Skip to content

Commit

Permalink
drivers: plic: Refine interrupt targets from hartid to context
Browse files Browse the repository at this point in the history
The PLIC specification says the interrupt targets are usually hart
contexts, where a hart context is a given privilege mode on a given
hart. Therefore, PLIC driver should not only consider the HART ID, but
also current privilege mode. Refine it by introducing the function
called plic_get_context(), which translates the current HART ID into the
PLIC context ID. We assume that each hart has M-mode and S-mode,
therefore M-mode occupies even-numbered context ID, while S-mode
occupies odd-numbered context ID. The translation can be extended by
parsing device tree, submitted in future commits.

Signed-off-by: Alvin Chang <[email protected]>
  • Loading branch information
gagachang committed Aug 3, 2023
1 parent f03c3a3 commit f8a817d
Showing 1 changed file with 44 additions and 14 deletions.
58 changes: 44 additions & 14 deletions core/drivers/plic.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,39 @@
((base) + PLIC_PENDING_OFFSET + \
(4 * ((source) / 32)) \
)
#define PLIC_ENABLE(base, source, hart) \
#define PLIC_ENABLE(base, source, context) \
((base) + PLIC_ENABLE_OFFSET + \
SHIFT_U32(hart, PLIC_ENABLE_SHIFT_PER_TARGET) +\
SHIFT_U32(context, PLIC_ENABLE_SHIFT_PER_TARGET) +\
(4 * ((source) / 32)) \
)
#define PLIC_THRESHOLD(base, hart) \
#define PLIC_THRESHOLD(base, context) \
((base) + PLIC_THRESHOLD_OFFSET + \
SHIFT_U32(hart, PLIC_THRESHOLD_SHIFT_PER_TARGET) \
SHIFT_U32(context, PLIC_THRESHOLD_SHIFT_PER_TARGET) \
)
#define PLIC_COMPLETE(base, hart) \
#define PLIC_COMPLETE(base, context) \
((base) + PLIC_CLAIM_OFFSET + \
SHIFT_U32(hart, PLIC_CLAIM_SHIFT_PER_TARGET) \
SHIFT_U32(context, PLIC_CLAIM_SHIFT_PER_TARGET) \
)
#define PLIC_CLAIM(base, hart) PLIC_COMPLETE(base, hart)
#define PLIC_CLAIM(base, context) PLIC_COMPLETE(base, context)

register_phys_mem_pgdir(MEM_AREA_IO_SEC, PLIC_BASE, PLIC_REG_SIZE);

/*
* We assume that each hart has M-mode and S-mode, so the contexts look like:
* PLIC context 0 is hart 0 M-mode
* PLIC context 1 is hart 0 S-mode
* PLIC context 2 is hart 1 M-mode
* PLIC context 3 is hart 1 S-mode
* ...
*/
static uint32_t plic_get_context(void)
{
size_t hartid = get_core_pos();
bool smode = IS_ENABLED(CFG_RISCV_S_MODE) ? true : false;

return hartid * 2 + smode;
}

static bool __maybe_unused
plic_is_pending(struct plic_data *pd, uint32_t source)
{
Expand All @@ -66,31 +82,41 @@ static void plic_set_pending(struct plic_data *pd, uint32_t source)

static void plic_enable_interrupt(struct plic_data *pd, uint32_t source)
{
io_setbits32(PLIC_ENABLE(pd->plic_base, source, get_core_pos()),
uint32_t context = plic_get_context();

io_setbits32(PLIC_ENABLE(pd->plic_base, source, context),
BIT(source & 0x1f));
}

static uint32_t __maybe_unused
plic_get_interrupt_enable(struct plic_data *pd, uint32_t source)
{
return io_read32(PLIC_ENABLE(pd->plic_base, source, get_core_pos())) &
uint32_t context = plic_get_context();

return io_read32(PLIC_ENABLE(pd->plic_base, source, context)) &
BIT(source & 0x1f);
}

static void plic_disable_interrupt(struct plic_data *pd, uint32_t source)
{
io_clrbits32(PLIC_ENABLE(pd->plic_base, source, get_core_pos()),
uint32_t context = plic_get_context();

io_clrbits32(PLIC_ENABLE(pd->plic_base, source, context),
BIT(source & 0x1f));
}

static uint32_t __maybe_unused plic_get_threshold(struct plic_data *pd)
{
return io_read32(PLIC_THRESHOLD(pd->plic_base, get_core_pos()));
uint32_t context = plic_get_context();

return io_read32(PLIC_THRESHOLD(pd->plic_base, context));
}

static void plic_set_threshold(struct plic_data *pd, uint32_t threshold)
{
io_write32(PLIC_THRESHOLD(pd->plic_base, get_core_pos()), threshold);
uint32_t context = plic_get_context();

io_write32(PLIC_THRESHOLD(pd->plic_base, context), threshold);
}

static uint32_t __maybe_unused
Expand All @@ -107,12 +133,16 @@ static void plic_set_priority(struct plic_data *pd, uint32_t source,

static uint32_t plic_claim_interrupt(struct plic_data *pd)
{
return io_read32(PLIC_CLAIM(pd->plic_base, get_core_pos()));
uint32_t context = plic_get_context();

return io_read32(PLIC_CLAIM(pd->plic_base, context));
}

static void plic_complete_interrupt(struct plic_data *pd, uint32_t source)
{
io_write32(PLIC_CLAIM(pd->plic_base, get_core_pos()), source);
uint32_t context = plic_get_context();

io_write32(PLIC_CLAIM(pd->plic_base, context), source);
}

static void plic_op_add(struct itr_chip *chip, size_t it,
Expand Down

0 comments on commit f8a817d

Please sign in to comment.