hw/intc: sifive_plic: Cleanup the write function

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Message-Id: <20220105213937.1113508-3-alistair.francis@opensource.wdc.com>
This commit is contained in:
Alistair Francis 2022-01-06 07:39:31 +10:00
parent 83b92b8efc
commit fb926d57cc

View file

@ -33,6 +33,11 @@
#define RISCV_DEBUG_PLIC 0 #define RISCV_DEBUG_PLIC 0
static bool addr_between(uint32_t addr, uint32_t base, uint32_t num)
{
return addr >= base && addr - base < num;
}
static PLICMode char_to_mode(char c) static PLICMode char_to_mode(char c)
{ {
switch (c) { switch (c) {
@ -269,81 +274,54 @@ static void sifive_plic_write(void *opaque, hwaddr addr, uint64_t value,
{ {
SiFivePLICState *plic = opaque; SiFivePLICState *plic = opaque;
/* writes must be 4 byte words */ if (addr_between(addr, plic->priority_base, plic->num_sources << 2)) {
if ((addr & 0x3) != 0) {
goto err;
}
if (addr >= plic->priority_base && /* 4 bytes per source */
addr < plic->priority_base + (plic->num_sources << 2))
{
uint32_t irq = ((addr - plic->priority_base) >> 2) + 1; uint32_t irq = ((addr - plic->priority_base) >> 2) + 1;
plic->source_priority[irq] = value & 7; plic->source_priority[irq] = value & 7;
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: write priority: irq=%d priority=%d\n",
irq, plic->source_priority[irq]);
}
sifive_plic_update(plic); sifive_plic_update(plic);
return; } else if (addr_between(addr, plic->pending_base,
} else if (addr >= plic->pending_base && /* 1 bit per source */ plic->num_sources >> 3)) {
addr < plic->pending_base + (plic->num_sources >> 3))
{
qemu_log_mask(LOG_GUEST_ERROR, qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid pending write: 0x%" HWADDR_PRIx "", "%s: invalid pending write: 0x%" HWADDR_PRIx "",
__func__, addr); __func__, addr);
return; } else if (addr_between(addr, plic->enable_base,
} else if (addr >= plic->enable_base && /* 1 bit per source */ plic->num_addrs * plic->enable_stride)) {
addr < plic->enable_base + plic->num_addrs * plic->enable_stride)
{
uint32_t addrid = (addr - plic->enable_base) / plic->enable_stride; uint32_t addrid = (addr - plic->enable_base) / plic->enable_stride;
uint32_t wordid = (addr & (plic->enable_stride - 1)) >> 2; uint32_t wordid = (addr & (plic->enable_stride - 1)) >> 2;
if (wordid < plic->bitfield_words) { if (wordid < plic->bitfield_words) {
plic->enable[addrid * plic->bitfield_words + wordid] = value; plic->enable[addrid * plic->bitfield_words + wordid] = value;
if (RISCV_DEBUG_PLIC) { } else {
qemu_log("plic: write enable: hart%d-%c word=%d value=%x\n", qemu_log_mask(LOG_GUEST_ERROR,
plic->addr_config[addrid].hartid, "%s: Invalid enable write 0x%" HWADDR_PRIx "\n",
mode_to_char(plic->addr_config[addrid].mode), wordid, __func__, addr);
plic->enable[addrid * plic->bitfield_words + wordid]);
} }
return; } else if (addr_between(addr, plic->context_base,
} plic->num_addrs * plic->context_stride)) {
} else if (addr >= plic->context_base && /* 4 bytes per reg */
addr < plic->context_base + plic->num_addrs * plic->context_stride)
{
uint32_t addrid = (addr - plic->context_base) / plic->context_stride; uint32_t addrid = (addr - plic->context_base) / plic->context_stride;
uint32_t contextid = (addr & (plic->context_stride - 1)); uint32_t contextid = (addr & (plic->context_stride - 1));
if (contextid == 0) { if (contextid == 0) {
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: write priority: hart%d-%c priority=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode),
plic->target_priority[addrid]);
}
if (value <= plic->num_priorities) { if (value <= plic->num_priorities) {
plic->target_priority[addrid] = value; plic->target_priority[addrid] = value;
sifive_plic_update(plic); sifive_plic_update(plic);
} }
return;
} else if (contextid == 4) { } else if (contextid == 4) {
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: write claim: hart%d-%c irq=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode),
(uint32_t)value);
}
if (value < plic->num_sources) { if (value < plic->num_sources) {
sifive_plic_set_claimed(plic, value, false); sifive_plic_set_claimed(plic, value, false);
sifive_plic_update(plic); sifive_plic_update(plic);
} }
return; } else {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid context write 0x%" HWADDR_PRIx "\n",
__func__, addr);
} }
} } else {
err:
qemu_log_mask(LOG_GUEST_ERROR, qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid register write 0x%" HWADDR_PRIx "\n", "%s: Invalid register write 0x%" HWADDR_PRIx "\n",
__func__, addr); __func__, addr);
} }
}
static const MemoryRegionOps sifive_plic_ops = { static const MemoryRegionOps sifive_plic_ops = {
.read = sifive_plic_read, .read = sifive_plic_read,