前言
這個標題可能有點繞口,但主要的動作就是,我們先關閉一顆 cpu,之後我們去 trace smp 相關的程式
之後針對 smp 的啟動程序去執行特定的位址,達到該 cpu 啟動後,會自動執行 baremetal application 的成果
實驗步驟
首先,我們先分析一下我們 dump 出來的運作流程
我們將 message 塞入 platsmp.c
1 | [ 0.126278] rockchip_smp_prepare_cpus: disable core1 |
rockchip_smp_prepare_cpus()
: 這一部份是將 cpu disable,會執行pmu_set_power_domain(cpu, false)
將除了 0 以外的 core 關閉1
2
3-> pmu_set_power_domain(1, false);
-> pmu_set_power_domain(2, false);
-> pmu_set_power_domain(3, false);pmu_set_power_domain(int cpu , int on)
: 這部份是將 power domain 關閉或是開啟1
2
3
4
5
6
7
8-> disable cpu N:
-> assert reset control register (cpu3: set CRU_SOFTRST0_CON bit 3 to 1)
-> set PMU_PWRDN_CON bit 1 2 3 to 1, 1 is off (0x0 -> 0x2 -> 0x6 -> 0xe)
-> free reset control register address
-> enable cpu N:
-> set PMU_PWRDN_CON bit 1 2 3 to 0, 0 is on (0xe -> 0xc -> 0x8 -> 0x0)
-> disassert reset control register (cpu3: set CRU_SOFTRST0_CON bit 3 to 0)
-> free reset control register addressrockchip_boot_secondary()
: enable cpu N 並且將 boot entry 設定到指定位址1
2
3-> pmu_set_power_domain(N, true);
-> sram_base + 8 = pc
-> sram_base + 4 = DEADBEAF
1 | static int rockchip_boot_secondary(unsigned int cpu, struct task_struct *idle) |
修改 baremetal code
然後我們修改一下 code
修改位址與 makefile
首先,我們使用的是 Firefly-RK3288 ,提供了 2G DDR 的空間,也就是 0x00000000 - 0x80000000
為了防止 kernel remap 我們無法預知的位址,因此我們在 uboot 中加入了 mem=960m
表示我們只提供 960M 的 memory 空間給 kernel 使用
也就是 0x00000000 - 0x3c0000000
使 kernel 可能會用到的位址
因此我們也將 entry point 修改成 0x40000000 避免 kernel 使用,但是我們還是可以透過 devmem 來寫入
備註:1
2
3以上是在 firefly RK3288 的公版上進行設置的,之後 HW 所提供的 DDR size 可能只有 1G
也就是從到 0x40000000 而已,如果使用以上設定會造成資料無法存取的狀況,因此之後要運行 application 的話
應該是要將存取位址設置成 0x3c000000
loadmetal 加入 RK3288 支援
沒有改什麼大部分的內容,但因為要使用 hardfloat compiler 才可以在 rootfs 使用,因此我們就照此辦理
1 | source /usr/local/weintek-i686/environment-setup-armv7ahf-vfp-neon-weintek-linux-gnueabi |
這樣就可以 build 出可使用的 loadmetal binary
若要使用,請將 #define LOAD_RK3288
打開
Source code of loadmetal
1 |
|
問題:open(“/dev/mem”) 會失敗: permission denied
原因是因為 CONFIG_STRICT_DEVMEM
被開啟,結果 user space 就只能access reserver memory 和kernel 使用的 system Ram 兩種
所以透過 menu -> Kernel Hacking
把 config 關閉後就可以了
這邊忘記針對 GPIO8 clock 進行設定,設定如下:
1 | void bootmain(void) |
補充:透過 uboot boot command maxcpus=3
進行測試
我們修改 include/config_distro_bootcmd.h
1 | diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h |
之後進系統先查看 cpu 狀態1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17cat /proc/cpuinfo
....省略
processor : 2
model name : ARMv7 Processor rev 1 (v7l)
BogoMIPS : 12.09
Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc0d
CPU revision : 1
Hardware : Rockchip (Device Tree)
Revision : 0000
Serial : 0000000000000000
可以看到 kernel 只啟動到 cpu 2
之後執行 loadmetal
+ insmod