Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Nov 2013 03:56:03 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r258494 - in head: lib/libvmmapi sys/amd64/include sys/amd64/vmm sys/amd64/vmm/io usr.sbin/bhyve
Message-ID:  <201311230356.rAN3u30w013275@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Sat Nov 23 03:56:03 2013
New Revision: 258494
URL: http://svnweb.freebsd.org/changeset/base/258494

Log:
  Add an ioctl to assert and deassert an ioapic pin atomically. This will be used
  to inject edge triggered legacy interrupts into the guest.
  
  Start using the new API in device models that use edge triggered interrupts:
  viz. the 8254 timer and the LPC/uart device emulation.
  
  Submitted by:	Tycho Nightingale (tycho.nightingale@pluribusnetworks.com)

Modified:
  head/lib/libvmmapi/vmmapi.c
  head/lib/libvmmapi/vmmapi.h
  head/sys/amd64/include/vmm_dev.h
  head/sys/amd64/vmm/io/vioapic.c
  head/sys/amd64/vmm/io/vioapic.h
  head/sys/amd64/vmm/vmm_dev.c
  head/usr.sbin/bhyve/pci_emul.c
  head/usr.sbin/bhyve/pci_emul.h
  head/usr.sbin/bhyve/pci_lpc.c
  head/usr.sbin/bhyve/pit_8254.c

Modified: head/lib/libvmmapi/vmmapi.c
==============================================================================
--- head/lib/libvmmapi/vmmapi.c	Sat Nov 23 01:20:17 2013	(r258493)
+++ head/lib/libvmmapi/vmmapi.c	Sat Nov 23 03:56:03 2013	(r258494)
@@ -419,6 +419,17 @@ vm_ioapic_deassert_irq(struct vmctx *ctx
 }
 
 int
+vm_ioapic_pulse_irq(struct vmctx *ctx, int irq)
+{
+	struct vm_ioapic_irq ioapic_irq;
+
+	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
+	ioapic_irq.irq = irq;
+
+	return (ioctl(ctx->fd, VM_IOAPIC_PULSE_IRQ, &ioapic_irq));
+}
+
+int
 vm_inject_nmi(struct vmctx *ctx, int vcpu)
 {
 	struct vm_nmi vmnmi;

Modified: head/lib/libvmmapi/vmmapi.h
==============================================================================
--- head/lib/libvmmapi/vmmapi.h	Sat Nov 23 01:20:17 2013	(r258493)
+++ head/lib/libvmmapi/vmmapi.h	Sat Nov 23 03:56:03 2013	(r258494)
@@ -69,6 +69,7 @@ int	vm_inject_event2(struct vmctx *ctx, 
 int	vm_lapic_irq(struct vmctx *ctx, int vcpu, int vector);
 int	vm_ioapic_assert_irq(struct vmctx *ctx, int irq);
 int	vm_ioapic_deassert_irq(struct vmctx *ctx, int irq);
+int	vm_ioapic_pulse_irq(struct vmctx *ctx, int irq);
 int	vm_inject_nmi(struct vmctx *ctx, int vcpu);
 int	vm_capability_name2type(const char *capname);
 const char *vm_capability_type2name(int type);

Modified: head/sys/amd64/include/vmm_dev.h
==============================================================================
--- head/sys/amd64/include/vmm_dev.h	Sat Nov 23 01:20:17 2013	(r258493)
+++ head/sys/amd64/include/vmm_dev.h	Sat Nov 23 03:56:03 2013	(r258494)
@@ -170,6 +170,7 @@ enum {
 	IOCNUM_INJECT_NMI = 32,
 	IOCNUM_IOAPIC_ASSERT_IRQ = 33,
 	IOCNUM_IOAPIC_DEASSERT_IRQ = 34,
+	IOCNUM_IOAPIC_PULSE_IRQ = 35,
 
 	/* PCI pass-thru */
 	IOCNUM_BIND_PPTDEV = 40,
@@ -209,6 +210,8 @@ enum {
 	_IOW('v', IOCNUM_IOAPIC_ASSERT_IRQ, struct vm_ioapic_irq)
 #define	VM_IOAPIC_DEASSERT_IRQ	\
 	_IOW('v', IOCNUM_IOAPIC_DEASSERT_IRQ, struct vm_ioapic_irq)
+#define	VM_IOAPIC_PULSE_IRQ	\
+	_IOW('v', IOCNUM_IOAPIC_PULSE_IRQ, struct vm_ioapic_irq)
 #define	VM_SET_CAPABILITY \
 	_IOW('v', IOCNUM_SET_CAPABILITY, struct vm_capability)
 #define	VM_GET_CAPABILITY \

Modified: head/sys/amd64/vmm/io/vioapic.c
==============================================================================
--- head/sys/amd64/vmm/io/vioapic.c	Sat Nov 23 01:20:17 2013	(r258493)
+++ head/sys/amd64/vmm/io/vioapic.c	Sat Nov 23 03:56:03 2013	(r258494)
@@ -160,8 +160,14 @@ vioapic_set_pinstate(struct vioapic *vio
 	}
 }
 
+enum irqstate {
+	IRQSTATE_ASSERT,
+	IRQSTATE_DEASSERT,
+	IRQSTATE_PULSE
+};
+
 static int
-vioapic_set_irqstate(struct vm *vm, int irq, bool state)
+vioapic_set_irqstate(struct vm *vm, int irq, enum irqstate irqstate)
 {
 	struct vioapic *vioapic;
 
@@ -171,7 +177,20 @@ vioapic_set_irqstate(struct vm *vm, int 
 	vioapic = vm_ioapic(vm);
 
 	VIOAPIC_LOCK(vioapic);
-	vioapic_set_pinstate(vioapic, irq, state);
+	switch (irqstate) {
+	case IRQSTATE_ASSERT:
+		vioapic_set_pinstate(vioapic, irq, true);
+		break;
+	case IRQSTATE_DEASSERT:
+		vioapic_set_pinstate(vioapic, irq, false);
+		break;
+	case IRQSTATE_PULSE:
+		vioapic_set_pinstate(vioapic, irq, true);
+		vioapic_set_pinstate(vioapic, irq, false);
+		break;
+	default:
+		panic("vioapic_set_irqstate: invalid irqstate %d", irqstate);
+	}
 	VIOAPIC_UNLOCK(vioapic);
 
 	return (0);
@@ -181,14 +200,21 @@ int
 vioapic_assert_irq(struct vm *vm, int irq)
 {
 
-	return (vioapic_set_irqstate(vm, irq, true));
+	return (vioapic_set_irqstate(vm, irq, IRQSTATE_ASSERT));
 }
 
 int
 vioapic_deassert_irq(struct vm *vm, int irq)
 {
 
-	return (vioapic_set_irqstate(vm, irq, false));
+	return (vioapic_set_irqstate(vm, irq, IRQSTATE_DEASSERT));
+}
+
+int
+vioapic_pulse_irq(struct vm *vm, int irq)
+{
+
+	return (vioapic_set_irqstate(vm, irq, IRQSTATE_PULSE));
 }
 
 static uint32_t

Modified: head/sys/amd64/vmm/io/vioapic.h
==============================================================================
--- head/sys/amd64/vmm/io/vioapic.h	Sat Nov 23 01:20:17 2013	(r258493)
+++ head/sys/amd64/vmm/io/vioapic.h	Sat Nov 23 03:56:03 2013	(r258494)
@@ -41,6 +41,7 @@ void	vioapic_cleanup(struct vioapic *vio
 
 int	vioapic_assert_irq(struct vm *vm, int irq);
 int	vioapic_deassert_irq(struct vm *vm, int irq);
+int	vioapic_pulse_irq(struct vm *vm, int irq);
 
 int	vioapic_mmio_write(void *vm, int vcpuid, uint64_t gpa,
 	    uint64_t wval, int size, void *arg);

Modified: head/sys/amd64/vmm/vmm_dev.c
==============================================================================
--- head/sys/amd64/vmm/vmm_dev.c	Sat Nov 23 01:20:17 2013	(r258493)
+++ head/sys/amd64/vmm/vmm_dev.c	Sat Nov 23 03:56:03 2013	(r258494)
@@ -303,6 +303,10 @@ vmmdev_ioctl(struct cdev *cdev, u_long c
 		ioapic_irq = (struct vm_ioapic_irq *)data;
 		error = vioapic_deassert_irq(sc->vm, ioapic_irq->irq);
 		break;
+	case VM_IOAPIC_PULSE_IRQ:
+		ioapic_irq = (struct vm_ioapic_irq *)data;
+		error = vioapic_pulse_irq(sc->vm, ioapic_irq->irq);
+		break;
 	case VM_MAP_MEMORY:
 		seg = (struct vm_memory_segment *)data;
 		error = vm_malloc(sc->vm, seg->gpa, seg->len);

Modified: head/usr.sbin/bhyve/pci_emul.c
==============================================================================
--- head/usr.sbin/bhyve/pci_emul.c	Sat Nov 23 01:20:17 2013	(r258493)
+++ head/usr.sbin/bhyve/pci_emul.c	Sat Nov 23 03:56:03 2013	(r258494)
@@ -1135,7 +1135,11 @@ pci_lintr_assert(struct pci_devinst *pi)
 {
 
 	assert(pi->pi_lintr_pin >= 0);
-	vm_ioapic_assert_irq(pi->pi_vmctx, pi->pi_lintr_pin);
+
+	if (pi->pi_lintr_state == 0) {
+		pi->pi_lintr_state = 1;
+		vm_ioapic_assert_irq(pi->pi_vmctx, pi->pi_lintr_pin);
+	}
 }
 
 void
@@ -1143,7 +1147,11 @@ pci_lintr_deassert(struct pci_devinst *p
 {
 
 	assert(pi->pi_lintr_pin >= 0);
-	vm_ioapic_deassert_irq(pi->pi_vmctx, pi->pi_lintr_pin);
+
+	if (pi->pi_lintr_state == 1) {
+		pi->pi_lintr_state = 0;
+		vm_ioapic_deassert_irq(pi->pi_vmctx, pi->pi_lintr_pin);
+	}
 }
 
 /*

Modified: head/usr.sbin/bhyve/pci_emul.h
==============================================================================
--- head/usr.sbin/bhyve/pci_emul.h	Sat Nov 23 01:20:17 2013	(r258493)
+++ head/usr.sbin/bhyve/pci_emul.h	Sat Nov 23 03:56:03 2013	(r258494)
@@ -104,6 +104,7 @@ struct pci_devinst {
 	struct vmctx *pi_vmctx;
 	uint8_t	  pi_bus, pi_slot, pi_func;
 	int8_t    pi_lintr_pin;
+	int8_t	  pi_lintr_state;
 	char	  pi_name[PI_NAMESZ];
 	int	  pi_bar_getsize;
 

Modified: head/usr.sbin/bhyve/pci_lpc.c
==============================================================================
--- head/usr.sbin/bhyve/pci_lpc.c	Sat Nov 23 01:20:17 2013	(r258493)
+++ head/usr.sbin/bhyve/pci_lpc.c	Sat Nov 23 03:56:03 2013	(r258494)
@@ -94,17 +94,16 @@ lpc_uart_intr_assert(void *arg)
 
 	assert(sc->irq >= 0);
 
-	vm_ioapic_assert_irq(lpc_bridge->pi_vmctx, sc->irq);
+	vm_ioapic_pulse_irq(lpc_bridge->pi_vmctx, sc->irq);
 }
 
 static void
 lpc_uart_intr_deassert(void *arg)
 {
-	struct lpc_uart_softc *sc = arg;
-
-	assert(sc->irq >= 0);
-
-	vm_ioapic_deassert_irq(lpc_bridge->pi_vmctx, sc->irq);
+	/* 
+	 * The COM devices on the LPC bus generate edge triggered interrupts,
+	 * so nothing more to do here.
+	 */
 }
 
 static int

Modified: head/usr.sbin/bhyve/pit_8254.c
==============================================================================
--- head/usr.sbin/bhyve/pit_8254.c	Sat Nov 23 01:20:17 2013	(r258493)
+++ head/usr.sbin/bhyve/pit_8254.c	Sat Nov 23 03:56:03 2013	(r258494)
@@ -105,8 +105,7 @@ pit_mevent_cb(int fd, enum ev_type type,
 
 	pit_mev_count++;
 
-	vm_ioapic_assert_irq(c->ctx, 2);
-	vm_ioapic_deassert_irq(c->ctx, 2);
+	vm_ioapic_pulse_irq(c->ctx, 2);
 
 	/*
 	 * Delete the timer for one-shots



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201311230356.rAN3u30w013275>