File tree Expand file tree Collapse file tree 2 files changed +62
-9
lines changed Expand file tree Collapse file tree 2 files changed +62
-9
lines changed Original file line number Diff line number Diff line change @@ -10557,17 +10557,16 @@ output:
10557
10557
10558
10558
==== ARM multicore
10559
10559
10560
- TODO get working on QEMU, CPU 1 not waking up. gem5 works:
10561
-
10562
10560
....
10563
10561
./run --arch aarch64 --baremetal arch/aarch64/multicore --cpus 2
10562
+ ./run --arch aarch64 --baremetal arch/aarch64/multicore --cpus 2 --gem5
10564
10563
....
10565
10564
10566
10565
Source: link:baremetal/arch/aarch64/multicore.S[]
10567
10566
10568
10567
CPU 0 of this program enters a spinlock loop: it repeatedly checks if a given memory address is `1`.
10569
10568
10570
- So, we need CPU 1 to come to the rescue to that memory address be `1`, otherwise CPU 0 will be stuck there forever.
10569
+ So, we need CPU 1 to come to the rescue and set that memory address to `1`, otherwise CPU 0 will be stuck there forever!
10571
10570
10572
10571
Don't believe me? Then try:
10573
10572
@@ -10584,6 +10583,17 @@ Bibliography:
10584
10583
* https://stackoverflow.com/questions/20055754/arm-start-wakeup-bringup-the-other-cpu-cores-aps-and-pass-execution-start-addre
10585
10584
* https://stackoverflow.com/questions/980999/what-does-multicore-assembly-language-look-like/33651438#33651438
10586
10585
10586
+ ===== WFE and SEV
10587
+
10588
+ The `WFE` and `SEV` instructions are just hints: a compliant implementation can treat them as NOPs.
10589
+
10590
+ However, likely no implementation likely does (TODO confirm), since:
10591
+
10592
+ * `WFE` puts the core in a low power mode
10593
+ * `SEV` wakes up cores from a low power mode
10594
+
10595
+ and power consumption is key in ARM applications.
10596
+
10587
10597
=== How we got some baremetal stuff to work
10588
10598
10589
10599
It is nice when thing just work.
Original file line number Diff line number Diff line change 9
9
10
10
/ * Read cpu id into x1. * /
11
11
mrs x1 , mpidr_el1
12
- and x1 , x1 , # 3
13
- cbz x1 , 1f
12
+ and x1 , x1 , 3
13
+ cbz x1 , cpu0_only
14
+ cpu1_only:
14
15
/ * Only CPU 1 reaches this point and sets the spinlock. * /
15
- mov x0 , # 1
16
+ mov x0 , 1
16
17
ldr x1 , =spinlock
17
18
str x0 , [ x1 ]
18
- b .
19
- 1 :
19
+ / * Ensure th at CPU 0 sees the write right now.
20
+ * Optional , but could save some useless CPU 1 loops.
21
+ * /
22
+ dmb sy
23
+ / * Wake up CPU 0 if it is sleeping on wfe.
24
+ * Optional , but could save power on a real system.
25
+ * /
26
+ sev
27
+ cpu1_sleep_forever:
28
+ / * Hint CPU 1 to enter low power mode.
29
+ * Optional , but could save power on a real system.
30
+ * /
31
+ wfe
32
+ b cpu1_sleep_forever
33
+ cpu0_only:
20
34
/ * Only CPU 0 reaches this point. * /
35
+
36
+ #if !defined(GEM5)
37
+ / * Wake up CPU 1 from initial sleep!
38
+ * In gem5 , CPU 1 starts woken up from the start ,
39
+ * so this is not needed.
40
+ * /
41
+ / * Function identifier: PCSI CPU_ON. * /
42
+ ldr w0 , = 0xc4000003
43
+ / * Argument 1 : target_ cpu * /
44
+ mov x1 , 1
45
+ / * Argument 2 : entry_point_address * /
46
+ ldr x2 , =cpu1_only
47
+ / * Argument 3 : context_id * /
48
+ mov x3 , 0
49
+ / * Unused hvc args: the Linux kernel zeroes them ,
50
+ * but I don't think it is required.
51
+ * /
52
+ #if 0
53
+ mov x4 , 0
54
+ mov x5 , 0
55
+ mov x6 , 0
56
+ mov x7 , 0
57
+ #endif
58
+ hvc 0
59
+ #endif
60
+
61
+ spinlock_start:
21
62
ldr x0 , spinlock
22
- cbz x0 , 1b
63
+ / * Hint CPU 0 to enter low power mode. * /
64
+ wfe
65
+ cbz x0 , spinlock_start
23
66
24
67
ret
25
68
You can’t perform that action at this time.
0 commit comments