1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/barrier.h>
4 #include <arch/encoding.h>
5 #include <arch/smp/smp.h>
6 #include <arch/smp/atomic.h>
7 #include <console/console.h>
10 // made up value to sync hart state
11 #define HART_SLEEPING 0x1
12 #define HART_AWAKE 0x2
14 void smp_pause(int working_hartid
)
16 int hartid
= read_csr(mhartid
);
18 // pause all harts which are not the working hart
19 if (hartid
!= working_hartid
) {
20 clear_csr(mstatus
, MSTATUS_MIE
); // disable all interrupts
21 set_msip(hartid
, 0); // clear pending interrupts
22 write_csr(mie
, MIP_MSIP
); // enable only IPI (for smp_resume)
24 atomic_set(&HLS()->entry
.sync_a
, HART_SLEEPING
); // mark the hart as sleeping.
28 __asm__
volatile ("wfi"); // wait for interrupt
29 } while ((read_csr(mip
) & MIP_MSIP
) == 0);
31 atomic_set(&HLS()->entry
.sync_a
, HART_AWAKE
); // mark the hart as awake
32 HLS()->entry
.fn(HLS()->entry
.arg
);
36 // must only be called by the WORKING_HARTID
37 void smp_resume(void (*fn
)(void *), void *arg
)
40 printk(BIOS_ERR
, "must pass a non-null function pointer\n");
41 return; // we can still boot with one hart
44 int working_hartid
= read_csr(mhartid
);
46 int hart_count
= CONFIG_MAX_CPUS
;
47 if (CONFIG(RISCV_GET_HART_COUNT_AT_RUNTIME
))
48 hart_count
= smp_get_hart_count();
50 // check that all harts are present
52 u32 count_awake_harts
= 0;
53 for (int i
= 0; i
< hart_count
; i
++) {
54 // The working hart never sleeps. It is a hard working hart.
55 if (i
== working_hartid
)
58 if (atomic_read(&OTHER_HLS(i
)->entry
.sync_a
) != HART_SLEEPING
) {
60 * we assmue here that the time between smp_pause and smp_resume
61 * is enough for all harts to reach the smp_pause state.
62 * But for some reason that was not the case for this hart ...
64 printk(BIOS_ERR
, "hart %d did not enter smp_pause\n", i
);
65 OTHER_HLS(i
)->enabled
= 0; // disable hart
67 // hart is in wfi (wait for interrupt) state like it should be.
69 OTHER_HLS(i
)->entry
.fn
= fn
;
70 OTHER_HLS(i
)->entry
.arg
= arg
;
72 set_msip(i
, 1); // wake up hart
76 printk(BIOS_DEBUG
, "waiting for all harts to wake up...\n");
77 // confirm that all harts are wake
78 for (int i
= 0; i
< hart_count
; i
++) {
79 // The working hart never sleeps. It is a hard working hart.
80 if (i
== working_hartid
|| !OTHER_HLS(i
)->enabled
)
83 // wait for hart to publish its waking state
84 while (atomic_read(&OTHER_HLS(i
)->entry
.sync_a
) != HART_AWAKE
)
88 printk(BIOS_DEBUG
, "all harts up and running...\n");
90 if ((hart_count
- 1) != count_awake_harts
) { // exclude working hart
92 * Apparently one or more harts did not reach smp_pause before smp_resume has
93 * been called by the working hart. That should not happen and may indicate we
94 * need a timeout of sorts to make sure we get all harts resumed.
96 printk(BIOS_ERR
, "some harts were too slow and could not resume\n");
98 fn(arg
); // jump to fn with working hart