[#59873] cortex-a53-gicv3: Support multi-core configuration
diff --git a/platforms/cpus/cortex-a53-gicv3.repl b/platforms/cpus/cortex-a53-gicv3.repl
index c1b2e12..19a1d94 100644
--- a/platforms/cpus/cortex-a53-gicv3.repl
+++ b/platforms/cpus/cortex-a53-gicv3.repl
@@ -1,6 +1,7 @@
cpu: CPU.ARMv8A @ sysbus
cpuType: "cortex-a53"
genericInterruptController: gic
+ cpuId: 0
timer: Timers.ARM_GenericTimer @ cpu
frequency: 62500000
diff --git a/platforms/cpus/cortex-a53-gicv3_smp.repl b/platforms/cpus/cortex-a53-gicv3_smp.repl
new file mode 100644
index 0000000..321f160
--- /dev/null
+++ b/platforms/cpus/cortex-a53-gicv3_smp.repl
@@ -0,0 +1,57 @@
+using "./cortex-a53-gicv3.repl"
+
+cpu1: CPU.ARMv8A @ sysbus
+ cpuType: "cortex-a53"
+ genericInterruptController: gic
+ cpuId: 1
+ init:
+ IsHalted true
+
+cpu2: CPU.ARMv8A @ sysbus
+ cpuType: "cortex-a53"
+ genericInterruptController: gic
+ cpuId: 2
+ init:
+ IsHalted true
+
+cpu3: CPU.ARMv8A @ sysbus
+ cpuType: "cortex-a53"
+ genericInterruptController: gic
+ cpuId: 3
+ init:
+ IsHalted true
+
+timer1: Timers.ARM_GenericTimer @ cpu1
+ frequency: 62500000
+ EL3PhysicalTimerIRQ -> gic#1@29
+ EL1PhysicalTimerIRQ -> gic#1@30
+ EL1VirtualTimerIRQ -> gic#1@27
+ NonSecureEL2PhysicalTimerIRQ -> gic#1@26
+ NonSecureEL2VirtualTimerIRQ -> gic#1@28
+
+timer2: Timers.ARM_GenericTimer @ cpu2
+ frequency: 62500000
+ EL3PhysicalTimerIRQ -> gic#2@29
+ EL1PhysicalTimerIRQ -> gic#2@30
+ EL1VirtualTimerIRQ -> gic#2@27
+ NonSecureEL2PhysicalTimerIRQ -> gic#2@26
+ NonSecureEL2VirtualTimerIRQ -> gic#2@28
+
+timer3: Timers.ARM_GenericTimer @ cpu3
+ frequency: 62500000
+ EL3PhysicalTimerIRQ -> gic#3@29
+ EL1PhysicalTimerIRQ -> gic#3@30
+ EL1VirtualTimerIRQ -> gic#3@27
+ NonSecureEL2PhysicalTimerIRQ -> gic#3@26
+ NonSecureEL2VirtualTimerIRQ -> gic#3@28
+
+gic: @ {
+ sysbus new Bus.BusMultiRegistration { address: 0x8000000; size: 0x010000; region: "distributor" };
+ sysbus new IRQControllers.ArmGicRedistributorRegistration { attachedCPU: cpu; address: 0x80a0000 };
+ sysbus new IRQControllers.ArmGicRedistributorRegistration { attachedCPU: cpu1; address: 0x80c0000 };
+ sysbus new IRQControllers.ArmGicRedistributorRegistration { attachedCPU: cpu2; address: 0x80e0000 };
+ sysbus new IRQControllers.ArmGicRedistributorRegistration { attachedCPU: cpu3; address: 0x8100000 }
+ }
+ [4-7] -> cpu1@[0-3]
+ [8-11] -> cpu2@[0-3]
+ [12-15] -> cpu3@[0-3]
diff --git a/scripts/single-node/cortex-a53-linux.resc b/scripts/single-node/cortex-a53-linux.resc
index f4f12d8..201ce1a 100644
--- a/scripts/single-node/cortex-a53-linux.resc
+++ b/scripts/single-node/cortex-a53-linux.resc
@@ -1,16 +1,44 @@
:name: Cortex-A53
:description: This script runs Linux (with Coreboot and ATF) on a 64-bit ARM Cortex-A53.
-$bin?=@https://dl.antmicro.com/projects/renode/coreboot-linux-armv8a-gicv3.rom-s_67108864-2348c80d6b871b9ac1916dfe0fd590125559ef73
+$bin?=@https://dl.antmicro.com/projects/renode/coreboot-linux-armv8a-gicv3-multicore.rom-s_67108864-02cf8d5b31d105603e63306ac07517a48134bfed
$name?="ARM Cortex-A53"
using sysbus
mach create $name
-machine LoadPlatformDescription @platforms/cpus/cortex-a53-gicv3.repl
+machine LoadPlatformDescription @platforms/cpus/cortex-a53-gicv3_smp.repl
showAnalyzer uart0
+# Based on https://github.com/ARM-software/arm-trusted-firmware/blob/5436047a0e1f32543042d6de9f1f6a3edcd47591/plat/qemu/qemu/include/platform_def.h#L107C1-L115C35
+set py_virt_trusted_mailbox_hook
+"""
+from Antmicro.Renode.Peripherals.CPU import RegisterValue
+
+PLAT_VIRT_TRUSTED_MAILBOX_BASE = 0x0e000000
+PLAT_VIRT_HOLD_BASE = PLAT_VIRT_TRUSTED_MAILBOX_BASE + 0x8
+PLAT_VIRT_HOLD_ENTRY_SIZE = 0x8
+
+PLAT_VIRT_HOLD_STATE_WAIT = 0
+PLAT_VIRT_HOLD_STATE_GO = 1
+
+_cpus = filter(lambda cpu: str(type(cpu)) == "<type 'ARMv8A'>", emulationManager.Instance.CurrentEmulation.Machines[0].SystemBus.GetCPUs())
+cpus = {cpu.Id: cpu for cpu in _cpus}
+
+idx = (address - PLAT_VIRT_HOLD_BASE) // PLAT_VIRT_HOLD_ENTRY_SIZE
+
+secure_entrypoint = self.ReadQuadWord(PLAT_VIRT_TRUSTED_MAILBOX_BASE);
+
+if value == PLAT_VIRT_HOLD_STATE_GO:
+ cpus[idx].PC = RegisterValue.Create(secure_entrypoint, 64)
+ cpus[idx].IsHalted = False
+ cpu.InfoLog("CPU %d started at PC: 0x%x" % (idx, secure_entrypoint))
+elif value == PLAT_VIRT_HOLD_STATE_WAIT:
+ cpus[idx].IsHalted = True
+ cpu.InfoLog("CPU %d halted")
+"""
+
macro reset
"""
# Preconfigure UART to see Coreboot and ATF boot logs.
@@ -18,5 +46,16 @@
uart0 WriteDoubleWord 0x2c 0x40
sysbus LoadBinary $bin 0x0
+
+ sysbus LoadSymbolsFrom @https://dl.antmicro.com/projects/renode/coreboot-bootblock-armv8a-gicv3-multicore.elf-s_45992-e566f9ef7c7f1357a6a5f4e433b42eae686b2773
+ sysbus LoadSymbolsFrom @https://dl.antmicro.com/projects/renode/coreboot-romstage-armv8a-gicv3-multicore.elf-s_53824-78204652d3be096534a1e3036f308ff0c93f5423
+ sysbus LoadSymbolsFrom @https://dl.antmicro.com/projects/renode/coreboot-ramstage-armv8a-gicv3-multicore.elf-s_147352-4d8d77fcee90f90eceebef782140189b21169778
+ sysbus LoadSymbolsFrom @https://dl.antmicro.com/projects/renode/bl31-atf-armv8a-gicv3-multicore.elf-s_1259192-f31a6120e8881925b3290ddd7ac2bc008f56460a
+ sysbus LoadSymbolsFrom @https://dl.antmicro.com/projects/renode/vmlinux-armv8a-gicv3-multicore-s_14825032-9d3f0ca4dc4b246cc648bb45bb36d8c2317bc41b
+
+ sysbus AddWatchpointHook 0x0e000008 QuadWord Write $py_virt_trusted_mailbox_hook # CPU 0 Mailbox
+ sysbus AddWatchpointHook 0x0e000010 QuadWord Write $py_virt_trusted_mailbox_hook # CPU 1 Mailbox
+ sysbus AddWatchpointHook 0x0e000018 QuadWord Write $py_virt_trusted_mailbox_hook # CPU 2 Mailbox
+ sysbus AddWatchpointHook 0x0e000020 QuadWord Write $py_virt_trusted_mailbox_hook # CPU 3 Mailbox
"""
runMacro $reset
diff --git a/tests/platforms/ARMv8A-Linux.robot b/tests/platforms/ARMv8A-Linux.robot
index 645493e..d6a3e61 100644
--- a/tests/platforms/ARMv8A-Linux.robot
+++ b/tests/platforms/ARMv8A-Linux.robot
@@ -1,6 +1,7 @@
*** Variables ***
${UART} sysbus.uart0
${URI} @https://dl.antmicro.com/projects/renode
+${LINUX_PROMPT} \#${SPACE}
# DTBs are embedded in Coreboot+Linux ROMs. Built with Coreboot v4.20.1, ATF v2.9.0, Linux v6.3 and Buildroot 2023.08-rc1.
${COREBOOT_ARMv8A_ROM} ${URI}/coreboot-without-payload-armv8a.rom-s_16777216-b5c6df85cfb8d240d31fe3cd1d055a3106d2fadb
@@ -39,6 +40,17 @@
Create Terminal Tester ${UART} defaultPauseEmulation=true
Execute Command showAnalyzer ${UART}
+Create Multicore Machine
+ Execute Command include @scripts/single-node/cortex-a53-linux.resc
+ Create Terminal Tester ${UART}
+
+Boot Linux And Login
+ # Verify that SMP works
+ Wait For Line On Uart SMP: Total of 4 processors activated includeUnfinishedLine=true
+ Wait For Prompt On Uart buildroot login: timeout=50
+ Write Line To Uart root
+ Wait For Prompt On Uart ${LINUX_PROMPT}
+
Configure UART For Boot Logs
[Arguments] ${uart}
@@ -339,3 +351,12 @@
Wait For Services And Enter Shell with_network=True
Shell Should Handle Basic Commands
+
+Should Boot And Login
+ Create Multicore Machine
+
+ Boot Linux And Login
+
+ # Check if we see other CPUs
+ Write Line To Uart nproc
+ Wait For Line On Uart 4
\ No newline at end of file