mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-20 20:53:46 +00:00
softirq:spinlock: correct vioapic/vpic lock usage
Now, we are trying to move softirq from vcpu thread context to real softirq context (it was not real softirq context even it has softirq name), we need to make sure all the spinlock could be access from softirq handler to use spinlock_irqsave_obtain and spinlock_irqrestore_release. Tracked-On: #3387 Signed-off-by: Yin Fengwei <fengwei.yin@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
parent
87558b6f98
commit
cb9866bc6c
@ -175,11 +175,12 @@ vioapic_set_irqline_nolock(const struct acrn_vm *vm, uint32_t irqline, uint32_t
|
||||
void
|
||||
vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t irqline, uint32_t operation)
|
||||
{
|
||||
uint64_t rflags;
|
||||
struct acrn_vioapic *vioapic = vm_ioapic(vm);
|
||||
if (vioapic->ready) {
|
||||
spinlock_obtain(&(vioapic->mtx));
|
||||
spinlock_irqsave_obtain(&(vioapic->mtx), &rflags);
|
||||
vioapic_set_irqline_nolock(vm, irqline, operation);
|
||||
spinlock_release(&(vioapic->mtx));
|
||||
spinlock_irqrestore_release(&(vioapic->mtx), rflags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,8 +246,9 @@ static inline bool vioapic_need_intr(const struct acrn_vioapic *vioapic, uint16_
|
||||
}
|
||||
|
||||
/*
|
||||
* Due to the race between vcpus, ensure to do spinlock_obtain(&(vioapic->mtx))
|
||||
* & spinlock_release(&(vioapic->mtx)) by caller.
|
||||
* Due to the race between vcpus and vioapic->mtx could be accessed from softirq, ensure to do
|
||||
* spinlock_irqsave_obtain(&(vioapic->mtx), &rflags) & spinlock_irqrestore_release(&(vioapic->mtx), rflags)
|
||||
* by caller.
|
||||
*/
|
||||
static void vioapic_indirect_write(struct acrn_vioapic *vioapic, uint32_t addr, uint32_t data)
|
||||
{
|
||||
@ -354,10 +356,11 @@ vioapic_mmio_rw(struct acrn_vioapic *vioapic, uint64_t gpa,
|
||||
uint32_t *data, bool do_read)
|
||||
{
|
||||
uint32_t offset;
|
||||
uint64_t rflags;
|
||||
|
||||
offset = (uint32_t)(gpa - VIOAPIC_BASE);
|
||||
|
||||
spinlock_obtain(&(vioapic->mtx));
|
||||
spinlock_irqsave_obtain(&(vioapic->mtx), &rflags);
|
||||
|
||||
/* The IOAPIC specification allows 32-bit wide accesses to the
|
||||
* IOAPIC_REGSEL (offset 0) and IOAPIC_WINDOW (offset 16) registers.
|
||||
@ -386,7 +389,7 @@ vioapic_mmio_rw(struct acrn_vioapic *vioapic, uint64_t gpa,
|
||||
break;
|
||||
}
|
||||
|
||||
spinlock_release(&(vioapic->mtx));
|
||||
spinlock_irqrestore_release(&(vioapic->mtx), rflags);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -399,6 +402,7 @@ vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector)
|
||||
struct acrn_vioapic *vioapic;
|
||||
uint32_t pin, pincount = vioapic_pincount(vm);
|
||||
union ioapic_rte rte;
|
||||
uint64_t rflags;
|
||||
|
||||
if ((vector < VECTOR_DYNAMIC_START) || (vector > NR_MAX_VECTOR)) {
|
||||
pr_err("vioapic_process_eoi: invalid vector %u", vector);
|
||||
@ -422,7 +426,7 @@ vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector)
|
||||
* XXX keep track of the pins associated with this vector instead
|
||||
* of iterating on every single pin each time.
|
||||
*/
|
||||
spinlock_obtain(&(vioapic->mtx));
|
||||
spinlock_irqsave_obtain(&(vioapic->mtx), &rflags);
|
||||
for (pin = 0U; pin < pincount; pin++) {
|
||||
rte = vioapic->rtbl[pin];
|
||||
if ((rte.bits.vector != vector) ||
|
||||
@ -437,7 +441,7 @@ vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector)
|
||||
vioapic_generate_intr(vioapic, pin);
|
||||
}
|
||||
}
|
||||
spinlock_release(&(vioapic->mtx));
|
||||
spinlock_irqrestore_release(&(vioapic->mtx), rflags);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <vm.h>
|
||||
#include <irq.h>
|
||||
#include <assign.h>
|
||||
#include <spinlock.h>
|
||||
#include <logmsg.h>
|
||||
|
||||
#define ACRN_DBG_PIC 6U
|
||||
@ -464,13 +465,14 @@ void vpic_set_irqline(struct acrn_vpic *vpic, uint32_t irqline, uint32_t operati
|
||||
{
|
||||
struct i8259_reg_state *i8259;
|
||||
uint32_t pin;
|
||||
uint64_t rflags;
|
||||
|
||||
if (irqline < NR_VPIC_PINS_TOTAL) {
|
||||
i8259 = &vpic->i8259[irqline >> 3U];
|
||||
pin = irqline;
|
||||
|
||||
if (i8259->ready) {
|
||||
spinlock_obtain(&(vpic->lock));
|
||||
spinlock_irqsave_obtain(&(vpic->lock), &rflags);
|
||||
switch (operation) {
|
||||
case GSI_SET_HIGH:
|
||||
vpic_set_pinstate(vpic, pin, 1U);
|
||||
@ -493,7 +495,7 @@ void vpic_set_irqline(struct acrn_vpic *vpic, uint32_t irqline, uint32_t operati
|
||||
break;
|
||||
}
|
||||
vpic_notify_intr(vpic);
|
||||
spinlock_release(&(vpic->lock));
|
||||
spinlock_irqrestore_release(&(vpic->lock), rflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,8 +37,8 @@
|
||||
#include <logmsg.h>
|
||||
|
||||
#define vuart_lock_init(vu) spinlock_init(&((vu)->lock))
|
||||
#define vuart_lock(vu) spinlock_obtain(&((vu)->lock))
|
||||
#define vuart_unlock(vu) spinlock_release(&((vu)->lock))
|
||||
#define vuart_lock(vu, flags) spinlock_irqsave_obtain(&((vu)->lock), &(flags))
|
||||
#define vuart_unlock(vu, flags) spinlock_irqrestore_release(&((vu)->lock), (flags))
|
||||
|
||||
static inline void fifo_reset(struct vuart_fifo *fifo)
|
||||
{
|
||||
@ -78,18 +78,21 @@ static inline uint32_t fifo_numchars(const struct vuart_fifo *fifo)
|
||||
|
||||
void vuart_putchar(struct acrn_vuart *vu, char ch)
|
||||
{
|
||||
vuart_lock(vu);
|
||||
uint64_t rflags;
|
||||
|
||||
vuart_lock(vu, rflags);
|
||||
fifo_putchar(&vu->rxfifo, ch);
|
||||
vuart_unlock(vu);
|
||||
vuart_unlock(vu, rflags);
|
||||
}
|
||||
|
||||
char vuart_getchar(struct acrn_vuart *vu)
|
||||
{
|
||||
uint64_t rflags;
|
||||
char c;
|
||||
|
||||
vuart_lock(vu);
|
||||
vuart_lock(vu, rflags);
|
||||
c = fifo_getchar(&vu->txfifo);
|
||||
vuart_unlock(vu);
|
||||
vuart_unlock(vu, rflags);
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -177,12 +180,14 @@ void vuart_toggle_intr(const struct acrn_vuart *vu)
|
||||
|
||||
static void send_to_target(struct acrn_vuart *vu, uint8_t value_u8)
|
||||
{
|
||||
vuart_lock(vu);
|
||||
uint64_t rflags;
|
||||
|
||||
vuart_lock(vu, rflags);
|
||||
if (vu->active) {
|
||||
fifo_putchar(&vu->rxfifo, (char)value_u8);
|
||||
vuart_toggle_intr(vu);
|
||||
}
|
||||
vuart_unlock(vu);
|
||||
vuart_unlock(vu, rflags);
|
||||
}
|
||||
|
||||
static uint8_t get_modem_status(uint8_t mcr)
|
||||
@ -249,8 +254,9 @@ static uint8_t update_modem_status(uint8_t new_msr, uint8_t old_msr)
|
||||
static void write_reg(struct acrn_vuart *vu, uint16_t reg, uint8_t value_u8)
|
||||
{
|
||||
uint8_t msr;
|
||||
uint64_t rflags;
|
||||
|
||||
vuart_lock(vu);
|
||||
vuart_lock(vu, rflags);
|
||||
/*
|
||||
* Take care of the special case DLAB accesses first
|
||||
*/
|
||||
@ -330,7 +336,7 @@ static void write_reg(struct acrn_vuart *vu, uint16_t reg, uint8_t value_u8)
|
||||
}
|
||||
}
|
||||
vuart_toggle_intr(vu);
|
||||
vuart_unlock(vu);
|
||||
vuart_unlock(vu, rflags);
|
||||
}
|
||||
|
||||
static bool vuart_write(struct acrn_vm *vm, uint16_t offset_arg,
|
||||
@ -340,6 +346,7 @@ static bool vuart_write(struct acrn_vm *vm, uint16_t offset_arg,
|
||||
struct acrn_vuart *vu = find_vuart_by_port(vm, offset);
|
||||
uint8_t value_u8 = (uint8_t)value;
|
||||
struct acrn_vuart *target_vu = NULL;
|
||||
uint64_t rflags;
|
||||
|
||||
if (vu != NULL) {
|
||||
offset -= vu->port_base;
|
||||
@ -348,10 +355,10 @@ static bool vuart_write(struct acrn_vm *vm, uint16_t offset_arg,
|
||||
if (((vu->mcr & MCR_LOOPBACK) == 0U) &&
|
||||
(offset == UART16550_THR) && (target_vu != NULL)) {
|
||||
send_to_target(target_vu, value_u8);
|
||||
vuart_lock(vu);
|
||||
vuart_lock(vu, rflags);
|
||||
vu->thre_int_pending = true;
|
||||
vuart_toggle_intr(vu);
|
||||
vuart_unlock(vu);
|
||||
vuart_unlock(vu, rflags);
|
||||
} else {
|
||||
write_reg(vu, offset, value_u8);
|
||||
}
|
||||
@ -366,10 +373,11 @@ static bool vuart_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t offs
|
||||
uint8_t iir, reg, intr_reason;
|
||||
struct acrn_vuart *vu = find_vuart_by_port(vm, offset);
|
||||
struct pio_request *pio_req = &vcpu->req.reqs.pio;
|
||||
uint64_t rflags;
|
||||
|
||||
if (vu != NULL) {
|
||||
offset -= vu->port_base;
|
||||
vuart_lock(vu);
|
||||
vuart_lock(vu, rflags);
|
||||
/*
|
||||
* Take care of the special case DLAB accesses first
|
||||
*/
|
||||
@ -438,7 +446,7 @@ static bool vuart_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t offs
|
||||
}
|
||||
vuart_toggle_intr(vu);
|
||||
pio_req->value = (uint32_t)reg;
|
||||
vuart_unlock(vu);
|
||||
vuart_unlock(vu, rflags);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user