Skip to content

Commit 7a91485

Browse files
committed
Preliminary allow PLIC to support 32 sources to 32 contexts
By changing `ie` from `uint32_t` to an array of `uint32_t`, this can simulate different interrupt enable registers for different contexts. For example, `ie[0]` simulates the interrupt enable register for the first context, which is at 0x002000 in the address map, and `ie[1]` simulates the second context with the address map at 0x002080.
1 parent 6525dc4 commit 7a91485

File tree

4 files changed

+23
-11
lines changed

4 files changed

+23
-11
lines changed

device.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ void ram_write(vm_t *core,
2525

2626
typedef struct {
2727
uint32_t masked;
28-
uint32_t ip;
29-
uint32_t ie;
28+
uint32_t ip; /* support 32 interrupt sources only */
29+
uint32_t ie[32]; /* support 32 sources to 32 contexts only */
3030
/* state of input interrupt lines (level-triggered), set by environment */
3131
uint32_t active;
3232
} plic_state_t;

main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ static int semu_start(int argc, char **argv)
410410
vm.s_mode = true;
411411
vm.x_regs[RV_R_A0] = 0; /* hart ID. i.e., cpuid */
412412
vm.x_regs[RV_R_A1] = dtb_addr;
413+
vm.mhartid = 0;
413414

414415
/* Set up peripherals */
415416
emu.uart.in_fd = 0, emu.uart.out_fd = 1;

plic.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ void plic_update_interrupts(vm_t *vm, plic_state_t *plic)
1010
plic->ip |= plic->active & ~plic->masked;
1111
plic->masked |= plic->active;
1212
/* Send interrupt to target */
13-
if (plic->ip & plic->ie)
13+
if (plic->ip & plic->ie[vm->mhartid])
1414
vm->sip |= RV_INT_SEI_BIT;
1515
else
1616
vm->sip &= ~RV_INT_SEI_BIT;
@@ -22,12 +22,17 @@ static bool plic_reg_read(plic_state_t *plic, uint32_t addr, uint32_t *value)
2222
if (1 <= addr && addr <= 31)
2323
return true;
2424

25-
switch (addr) {
26-
case 0x400:
25+
if (addr == 0x400) {
2726
*value = plic->ip;
2827
return true;
28+
}
29+
30+
int addr_mask = MASK(ilog2(addr)) ^ (1 & addr);
31+
int context = (addr_mask & addr);
32+
context >>= __builtin_ffs(context) - (__builtin_ffs(context) & 1);
33+
switch (addr & ~addr_mask) {
2934
case 0x800:
30-
*value = plic->ie;
35+
*value = plic->ie[context];
3136
return true;
3237
case 0x80000:
3338
*value = 0;
@@ -36,7 +41,7 @@ static bool plic_reg_read(plic_state_t *plic, uint32_t addr, uint32_t *value)
3641
case 0x80001:
3742
/* claim */
3843
*value = 0;
39-
uint32_t candidates = plic->ip & plic->ie;
44+
uint32_t candidates = plic->ip & plic->ie[context];
4045
if (candidates) {
4146
*value = ilog2(candidates);
4247
plic->ip &= ~(1 << (*value));
@@ -53,17 +58,20 @@ static bool plic_reg_write(plic_state_t *plic, uint32_t addr, uint32_t value)
5358
if (1 <= addr && addr <= 31)
5459
return true;
5560

56-
switch (addr) {
61+
int addr_mask = MASK(ilog2(addr)) ^ (1 & addr);
62+
int context = (addr_mask & addr);
63+
context >>= __builtin_ffs(context) - (__builtin_ffs(context) & 1);
64+
switch (addr & ~addr_mask) {
5765
case 0x800:
5866
value &= ~1;
59-
plic->ie = value;
67+
plic->ie[context] = value;
6068
return true;
6169
case 0x80000:
6270
/* no priority support: target priority threshold hardwired to 0 */
6371
return true;
6472
case 0x80001:
6573
/* completion */
66-
if (plic->ie & (1 << value))
74+
if (plic->ie[context] & (1 << value))
6775
plic->masked &= ~(1 << value);
6876
return true;
6977
default:
@@ -113,4 +121,4 @@ void plic_write(vm_t *vm,
113121
vm_set_exception(vm, RV_EXC_ILLEGAL_INSN, 0);
114122
return;
115123
}
116-
}
124+
}

riscv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ struct __vm_internal {
103103
uint32_t satp; /**< MMU */
104104
uint32_t *page_table;
105105

106+
/* Machine state */
107+
uint32_t mhartid;
108+
106109
void *priv; /**< environment supplied */
107110

108111
/* Memory access sets the vm->error to indicate failure. On successful

0 commit comments

Comments
 (0)