Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/mmio/mmio_irq.c
- This file was added.
#include <sys/cdefs.h> | |||||
__FBSDID("$FreeBSD$"); | |||||
#include <sys/param.h> | |||||
#include <machine/vmm.h> | |||||
#include <assert.h> | |||||
#include <pthread.h> | |||||
#include <stdio.h> | |||||
#include <vmmapi.h> | |||||
#include "mmio_emul.h" | |||||
#include "mmio_irq.h" | |||||
#include "mmio_virtio.h" | |||||
/* IRQ count to disable IRQ */ | |||||
#define IRQ_DISABLED 0xff | |||||
static struct mmio_irq { | |||||
uint32_t use_count; /* number of binds */ | |||||
uint32_t active_count; /* number of asserts */ | |||||
uint32_t active; /* irq active */ | |||||
pthread_mutex_t lock; | |||||
} irqs[50]; | |||||
void | |||||
mmio_irq_reserve(int irq) | |||||
{ | |||||
assert(irq >= 0 && irq < nitems(irqs)); | |||||
assert(irqs[irq].active == 0 || irqs[irq].active == IRQ_DISABLED); | |||||
irqs[irq].active = IRQ_DISABLED; | |||||
} | |||||
void | |||||
mmio_irq_use(int irq) { | |||||
assert(irq >= 0 && irq < nitems(irqs)); | |||||
assert(irqs[irq].active != IRQ_DISABLED); | |||||
irqs[irq].active++; | |||||
} | |||||
void | |||||
mmio_irq_init(struct vmctx *ctx) | |||||
{ | |||||
int i; | |||||
for (i = 0; i < nitems(irqs); ++i) { | |||||
irqs[i].use_count = 0; | |||||
irqs[i].active_count = 0; | |||||
irqs[i].active = 0; | |||||
pthread_mutex_init(&irqs[i].lock, NULL); | |||||
} | |||||
} | |||||
void | |||||
mmio_irq_assert(struct mmio_devinst *di) | |||||
{ | |||||
struct mmio_irq *irq; | |||||
uint32_t irq_status; | |||||
assert(di->di_lintr.irq <= nitems(irqs)); | |||||
if (di->di_lintr.irq < 0) | |||||
return; | |||||
irq = &irqs[di->di_lintr.irq]; | |||||
pthread_mutex_lock(&irq->lock); | |||||
irq->active_count++; | |||||
pthread_mutex_lock(&di->di_lintr.lock); | |||||
irq_status = mmio_get_cfgreg32(di, VIRTIO_MMIO_INTERRUPT_STATUS); | |||||
irq_status |= VIRTIO_MMIO_INT_VRING; | |||||
mmio_set_cfgreg32(di, VIRTIO_MMIO_INTERRUPT_STATUS, irq_status); | |||||
if (irq->active_count == 1) | |||||
vm_assert_irq(di->pi_vmctx, di->di_lintr.irq); | |||||
pthread_mutex_unlock(&di->di_lintr.lock); | |||||
pthread_mutex_unlock(&irq->lock); | |||||
} | |||||
void | |||||
mmio_irq_deassert(struct mmio_devinst *di) | |||||
{ | |||||
struct mmio_irq *irq; | |||||
uint32_t irq_status; | |||||
assert(di->di_lintr.irq <= nitems(irqs)); | |||||
if (di->di_lintr.irq < 0) | |||||
return; | |||||
irq = &irqs[di->di_lintr.irq]; | |||||
pthread_mutex_lock(&irq->lock); | |||||
irq->active_count--; | |||||
pthread_mutex_lock(&di->di_lintr.lock); | |||||
irq_status = mmio_get_cfgreg32(di, VIRTIO_MMIO_INTERRUPT_STATUS); | |||||
irq_status &= ~VIRTIO_MMIO_INT_VRING; | |||||
mmio_set_cfgreg32(di, VIRTIO_MMIO_INTERRUPT_STATUS, irq_status); | |||||
#if 0 | |||||
/* MMIO devices do not require deassertions */ | |||||
if (irq->active_count == 0) | |||||
vm_deassert_irq(di->di_vmctx, di->di_lintr.irq); | |||||
#endif | |||||
pthread_mutex_unlock(&di->di_lintr.lock); | |||||
pthread_mutex_unlock(&irq->lock); | |||||
} |