#ifndef SIFIVE_SMP | |
#define SIFIVE_SMP | |
// The maximum number of HARTs this code supports | |
#ifndef MAX_HARTS | |
#define MAX_HARTS 32 | |
#endif | |
#define CLINT_END_HART_IPI CLINT_CTRL_ADDR + (MAX_HARTS*4) | |
// The hart that non-SMP tests should run on | |
#ifndef NONSMP_HART | |
#define NONSMP_HART 0 | |
#endif | |
/* If your test cannot handle multiple-threads, use this: | |
* smp_disable(reg1) | |
*/ | |
#define smp_disable(reg1, reg2) \ | |
csrr reg1, mhartid ;\ | |
li reg2, NONSMP_HART ;\ | |
beq reg1, reg2, hart0_entry ;\ | |
42: ;\ | |
wfi ;\ | |
j 42b ;\ | |
hart0_entry: | |
/* If your test needs to temporarily block multiple-threads, do this: | |
* smp_pause(reg1, reg2) | |
* ... single-threaded work ... | |
* smp_resume(reg1, reg2) | |
* ... multi-threaded work ... | |
*/ | |
#define smp_pause(reg1, reg2) \ | |
li reg2, 0x8 ;\ | |
csrw mie, reg2 ;\ | |
csrr reg2, mhartid ;\ | |
bnez reg2, 42f | |
#define smp_resume(reg1, reg2) \ | |
li reg1, CLINT_CTRL_ADDR ;\ | |
41: ;\ | |
li reg2, 1 ;\ | |
sw reg2, 0(reg1) ;\ | |
addi reg1, reg1, 4 ;\ | |
li reg2, CLINT_END_HART_IPI ;\ | |
blt reg1, reg2, 41b ;\ | |
42: ;\ | |
wfi ;\ | |
csrr reg2, mip ;\ | |
andi reg2, reg2, 0x8 ;\ | |
beqz reg2, 42b ;\ | |
li reg1, CLINT_CTRL_ADDR ;\ | |
csrr reg2, mhartid ;\ | |
slli reg2, reg2, 2 ;\ | |
add reg2, reg2, reg1 ;\ | |
sw zero, 0(reg2) ;\ | |
41: ;\ | |
lw reg2, 0(reg1) ;\ | |
bnez reg2, 41b ;\ | |
addi reg1, reg1, 4 ;\ | |
li reg2, CLINT_END_HART_IPI ;\ | |
blt reg1, reg2, 41b | |
#endif |