mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
arm64 secondary CPU entry point
This commit is contained in:
90
README.adoc
90
README.adoc
@@ -2063,8 +2063,6 @@ As a result, we are unable to break on early symbols such as:
|
|||||||
|
|
||||||
<<gem5-execall-trace-format>>>> however does show the right symbols however! This could be because <<vmlinux-vs-bzimage-vs-zimage-vs-image,gem5 uses vmlinux to boot>>, which QEMU uses the compressed version, and as mentioned on the Stack Overflow answer, the entry point is actually a tiny decompresser routine.
|
<<gem5-execall-trace-format>>>> however does show the right symbols however! This could be because <<vmlinux-vs-bzimage-vs-zimage-vs-image,gem5 uses vmlinux to boot>>, which QEMU uses the compressed version, and as mentioned on the Stack Overflow answer, the entry point is actually a tiny decompresser routine.
|
||||||
|
|
||||||
In gem5 aarch64 Linux v4.18, experimentally the entry point of secondary CPUs seems to be `secondary_holding_pen` as shown at https://gist.github.com/cirosantilli2/34a7bc450fcb6c1c1a910369be1fdd90
|
|
||||||
|
|
||||||
I also tried to hack `run-gdb` with:
|
I also tried to hack `run-gdb` with:
|
||||||
|
|
||||||
....
|
....
|
||||||
@@ -2091,6 +2089,75 @@ config KERNEL_UNCOMPRESSED
|
|||||||
depends on HAVE_KERNEL_UNCOMPRESSED
|
depends on HAVE_KERNEL_UNCOMPRESSED
|
||||||
....
|
....
|
||||||
|
|
||||||
|
===== arm64 secondary CPU entry point
|
||||||
|
|
||||||
|
In gem5 aarch64 Linux v4.18, experimentally the entry point of secondary CPUs seems to be `secondary_holding_pen` as shown at https://gist.github.com/cirosantilli2/34a7bc450fcb6c1c1a910369be1fdd90
|
||||||
|
|
||||||
|
What happens is that:
|
||||||
|
|
||||||
|
* the bootloader goes in in WFE
|
||||||
|
* the kernel writes the entry point to the secondary CPU (the address of `secondary_holding_pen`) with CPU0 at the address given to the kernel in the `cpu-release-addr` of the DTB
|
||||||
|
* the kernel wakes up the bootloader with a SEV, and the bootloader boots to the address the kernel told it
|
||||||
|
|
||||||
|
The CPU0 action happens at: https://github.com/cirosantilli/linux/blob/v5.7/arch/arm64/kernel/smp_spin_table.c[]:
|
||||||
|
|
||||||
|
Here's the code that writes the address and does SEV:
|
||||||
|
|
||||||
|
....
|
||||||
|
static int smp_spin_table_cpu_prepare(unsigned int cpu)
|
||||||
|
{
|
||||||
|
__le64 __iomem *release_addr;
|
||||||
|
|
||||||
|
if (!cpu_release_addr[cpu])
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The cpu-release-addr may or may not be inside the linear mapping.
|
||||||
|
* As ioremap_cache will either give us a new mapping or reuse the
|
||||||
|
* existing linear mapping, we can use it to cover both cases. In
|
||||||
|
* either case the memory will be MT_NORMAL.
|
||||||
|
*/
|
||||||
|
release_addr = ioremap_cache(cpu_release_addr[cpu],
|
||||||
|
sizeof(*release_addr));
|
||||||
|
if (!release_addr)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We write the release address as LE regardless of the native
|
||||||
|
* endianess of the kernel. Therefore, any boot-loaders that
|
||||||
|
* read this address need to convert this address to the
|
||||||
|
* boot-loader's endianess before jumping. This is mandated by
|
||||||
|
* the boot protocol.
|
||||||
|
*/
|
||||||
|
writeq_relaxed(__pa_symbol(secondary_holding_pen), release_addr);
|
||||||
|
__flush_dcache_area((__force void *)release_addr,
|
||||||
|
sizeof(*release_addr));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send an event to wake up the secondary CPU.
|
||||||
|
*/
|
||||||
|
sev();
|
||||||
|
....
|
||||||
|
|
||||||
|
and here's the code that reads the value from the DTB:
|
||||||
|
|
||||||
|
....
|
||||||
|
static int smp_spin_table_cpu_init(unsigned int cpu)
|
||||||
|
{
|
||||||
|
struct device_node *dn;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dn = of_get_cpu_node(cpu, NULL);
|
||||||
|
if (!dn)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the address from which the CPU is polling.
|
||||||
|
*/
|
||||||
|
ret = of_property_read_u64(dn, "cpu-release-addr",
|
||||||
|
&cpu_release_addr[cpu]);
|
||||||
|
....
|
||||||
|
|
||||||
==== Linux kernel arch-agnostic entry point
|
==== Linux kernel arch-agnostic entry point
|
||||||
|
|
||||||
`start_kernel` is the first C function to be executed basically: https://stackoverflow.com/questions/18266063/does-kernel-have-main-function/33422401#33422401
|
`start_kernel` is the first C function to be executed basically: https://stackoverflow.com/questions/18266063/does-kernel-have-main-function/33422401#33422401
|
||||||
@@ -5578,7 +5645,7 @@ To use just your own exact `.config` instead of our defaults ones, use:
|
|||||||
./build-linux --custom-config-file data/myconfig
|
./build-linux --custom-config-file data/myconfig
|
||||||
....
|
....
|
||||||
|
|
||||||
There is also a shortcut `--custom-config-file` to use the <<gem5-arm-linux-kernel-patches>>.
|
There is also a shortcut `--custom-config-file-gem5` to use the <<gem5-arm-linux-kernel-patches>>.
|
||||||
|
|
||||||
The following options can all be used together, sorted by decreasing config setting power precedence:
|
The following options can all be used together, sorted by decreasing config setting power precedence:
|
||||||
|
|
||||||
@@ -26586,6 +26653,17 @@ Same but hacking `BR2_LINUX_KERNEL_LATEST_VERSION=y` and `BR2_PACKAGE_HOST_LINUX
|
|||||||
|
|
||||||
Same but with: <<gem5-arm-linux-kernel-patches>> at v4.15: 73s, kernel size: 132M.
|
Same but with: <<gem5-arm-linux-kernel-patches>> at v4.15: 73s, kernel size: 132M.
|
||||||
|
|
||||||
|
On Ubuntu 20.04, LKMC d3f8d3e99f2e554aae6c3b325b350bcf7f3f087f (Linux kernel 5.4.3), gem5 6bc2111c9674d0c8db22f6a6adcc00e49625aabd (sept 2020):
|
||||||
|
|
||||||
|
....
|
||||||
|
./run --arch aarch64 --emulator gem5 --quit-after-boot
|
||||||
|
....
|
||||||
|
|
||||||
|
took 193s. With some minimal newer kernel boot patches:
|
||||||
|
|
||||||
|
* kernel v5.7: 238s
|
||||||
|
* kernel v5.8: 239s
|
||||||
|
|
||||||
On Ubuntu 20.04 gem5 3ca404da175a66e0b958165ad75eb5f54cb5e772 this took 22 minutes 53 seconds:
|
On Ubuntu 20.04 gem5 3ca404da175a66e0b958165ad75eb5f54cb5e772 this took 22 minutes 53 seconds:
|
||||||
|
|
||||||
....
|
....
|
||||||
@@ -27323,6 +27401,12 @@ gem5:
|
|||||||
** https://stackoverflow.com/questions/47997565/gem5-system-requirements-for-decent-performance/48941793#48941793
|
** https://stackoverflow.com/questions/47997565/gem5-system-requirements-for-decent-performance/48941793#48941793
|
||||||
** https://github.com/gem5/gem5/issues/25
|
** https://github.com/gem5/gem5/issues/25
|
||||||
|
|
||||||
|
== FreeBSD
|
||||||
|
|
||||||
|
Prebuilt on Ubuntu 20.04 worked: https://stackoverflow.com/questions/49656395/how-to-boot-freebsd-image-under-qemu/64027161#64027161[]
|
||||||
|
|
||||||
|
TODO minimal build + boot on QEMU example anywhere???
|
||||||
|
|
||||||
== RTOS
|
== RTOS
|
||||||
|
|
||||||
=== Zephyr
|
=== Zephyr
|
||||||
|
|||||||
Reference in New Issue
Block a user