[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 3/9] RISC-V: Use atomic_cmpxchg to update PLIC bitmap
From: |
Alistair Francis |
Subject: |
[Qemu-devel] [PULL 3/9] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps |
Date: |
Tue, 4 Sep 2018 16:14:36 -0700 |
From: Michael Clark <address@hidden>
The PLIC previously used a mutex to protect against concurrent
access to the claimed and pending bitfields. Instead of using
a mutex, we update the bitfields using atomic_cmpxchg.
Rename sifive_plic_num_irqs_pending to sifive_plic_irqs_pending
and add an early out if any interrupts are pending as the
count of pending interrupts is not used.
Cc: Sagar Karandikar <address@hidden>
Cc: Bastian Koppelmann <address@hidden>
Cc: Palmer Dabbelt <address@hidden>
Cc: Alistair Francis <address@hidden>
Signed-off-by: Michael Clark <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
Signed-off-by: Alistair Francis <address@hidden>
---
hw/riscv/sifive_plic.c | 49 +++++++++++++++-------------------
include/hw/riscv/sifive_plic.h | 1 -
2 files changed, 22 insertions(+), 28 deletions(-)
diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
index a91aeb97ab..f635e6ff67 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/riscv/sifive_plic.c
@@ -81,36 +81,32 @@ static void sifive_plic_print_state(SiFivePLICState *plic)
}
}
-static
-void sifive_plic_set_pending(SiFivePLICState *plic, int irq, bool pending)
+static uint32_t atomic_set_masked(uint32_t *a, uint32_t mask, uint32_t value)
{
- qemu_mutex_lock(&plic->lock);
- uint32_t word = irq >> 5;
- if (pending) {
- plic->pending[word] |= (1 << (irq & 31));
- } else {
- plic->pending[word] &= ~(1 << (irq & 31));
- }
- qemu_mutex_unlock(&plic->lock);
+ uint32_t old, new, cmp = atomic_read(a);
+
+ do {
+ old = cmp;
+ new = (old & ~mask) | (value & mask);
+ cmp = atomic_cmpxchg(a, old, new);
+ } while (old != cmp);
+
+ return old;
}
-static
-void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool claimed)
+static void sifive_plic_set_pending(SiFivePLICState *plic, int irq, bool level)
{
- qemu_mutex_lock(&plic->lock);
- uint32_t word = irq >> 5;
- if (claimed) {
- plic->claimed[word] |= (1 << (irq & 31));
- } else {
- plic->claimed[word] &= ~(1 << (irq & 31));
- }
- qemu_mutex_unlock(&plic->lock);
+ atomic_set_masked(&plic->pending[irq >> 5], 1 << (irq & 31), -!!level);
}
-static
-int sifive_plic_num_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
+static void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool level)
{
- int i, j, count = 0;
+ atomic_set_masked(&plic->claimed[irq >> 5], 1 << (irq & 31), -!!level);
+}
+
+static int sifive_plic_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
+{
+ int i, j;
for (i = 0; i < plic->bitfield_words; i++) {
uint32_t pending_enabled_not_claimed =
(plic->pending[i] & ~plic->claimed[i]) &
@@ -123,11 +119,11 @@ int sifive_plic_num_irqs_pending(SiFivePLICState *plic,
uint32_t addrid)
uint32_t prio = plic->source_priority[irq];
int enabled = pending_enabled_not_claimed & (1 << j);
if (enabled && prio > plic->target_priority[addrid]) {
- count++;
+ return 1;
}
}
}
- return count;
+ return 0;
}
static void sifive_plic_update(SiFivePLICState *plic)
@@ -143,7 +139,7 @@ static void sifive_plic_update(SiFivePLICState *plic)
if (!env) {
continue;
}
- int level = sifive_plic_num_irqs_pending(plic, addrid) > 0;
+ int level = sifive_plic_irqs_pending(plic, addrid);
switch (mode) {
case PLICMode_M:
riscv_set_local_interrupt(RISCV_CPU(cpu), MIP_MEIP, level);
@@ -439,7 +435,6 @@ static void sifive_plic_realize(DeviceState *dev, Error
**errp)
memory_region_init_io(&plic->mmio, OBJECT(dev), &sifive_plic_ops, plic,
TYPE_SIFIVE_PLIC, plic->aperture_size);
parse_hart_config(plic);
- qemu_mutex_init(&plic->lock);
plic->bitfield_words = (plic->num_sources + 31) >> 5;
plic->source_priority = g_new0(uint32_t, plic->num_sources);
plic->target_priority = g_new(uint32_t, plic->num_addrs);
diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/riscv/sifive_plic.h
index 2f2af7e686..688cd97f82 100644
--- a/include/hw/riscv/sifive_plic.h
+++ b/include/hw/riscv/sifive_plic.h
@@ -55,7 +55,6 @@ typedef struct SiFivePLICState {
uint32_t *pending;
uint32_t *claimed;
uint32_t *enable;
- QemuMutex lock;
/* config */
char *hart_config;
--
2.17.1
- [Qemu-devel] [PULL 0/9] riscv-pullreq queue, Alistair Francis, 2018/09/04
- [Qemu-devel] [PULL 1/9] RISC-V: Update address bits to support sv39 and sv48, Alistair Francis, 2018/09/04
- [Qemu-devel] [PULL 2/9] RISC-V: Improve page table walker spec compliance, Alistair Francis, 2018/09/04
- [Qemu-devel] [PULL 3/9] RISC-V: Use atomic_cmpxchg to update PLIC bitmaps,
Alistair Francis <=
- [Qemu-devel] [PULL 4/9] RISC-V: Simplify riscv_cpu_local_irqs_pending, Alistair Francis, 2018/09/04
- [Qemu-devel] [PULL 5/9] target/riscv: optimize indirect branches, Alistair Francis, 2018/09/04
- [Qemu-devel] [PULL 7/9] hw/riscv/virtio: Set the soc device tree node as a simple-bus, Alistair Francis, 2018/09/04
- [Qemu-devel] [PULL 8/9] hw/riscv/spike: Set the soc device tree node as a simple-bus, Alistair Francis, 2018/09/04
- [Qemu-devel] [PULL 6/9] target/riscv: call gen_goto_tb on DISAS_TOO_MANY, Alistair Francis, 2018/09/04
- [Qemu-devel] [PULL 9/9] riscv: remove define cpu_init(), Alistair Francis, 2018/09/04
- Re: [Qemu-devel] [PULL 0/9] riscv-pullreq queue, Alistair Francis, 2018/09/05