From owner-svn-src-all@FreeBSD.ORG Mon Apr 14 19:00:21 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id E4C3AC3E; Mon, 14 Apr 2014 19:00:21 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C58841C9C; Mon, 14 Apr 2014 19:00:21 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s3EJ0L5R084332; Mon, 14 Apr 2014 19:00:21 GMT (envelope-from tychon@svn.freebsd.org) Received: (from tychon@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s3EJ0LiR084329; Mon, 14 Apr 2014 19:00:21 GMT (envelope-from tychon@svn.freebsd.org) Message-Id: <201404141900.s3EJ0LiR084329@svn.freebsd.org> From: Tycho Nightingale Date: Mon, 14 Apr 2014 19:00:21 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r264468 - in head: lib/libvmmapi sys/amd64/vmm/io usr.sbin/bhyve X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 14 Apr 2014 19:00:22 -0000 Author: tychon Date: Mon Apr 14 19:00:20 2014 New Revision: 264468 URL: http://svnweb.freebsd.org/changeset/base/264468 Log: Add support for emulating the slave PIC. Reviewed by: grehan, jhb Approved by: grehan (co-mentor) Modified: head/lib/libvmmapi/vmmapi.h head/sys/amd64/vmm/io/vatpic.c head/usr.sbin/bhyve/pm.c Modified: head/lib/libvmmapi/vmmapi.h ============================================================================== --- head/lib/libvmmapi/vmmapi.h Mon Apr 14 18:38:14 2014 (r264467) +++ head/lib/libvmmapi/vmmapi.h Mon Apr 14 19:00:20 2014 (r264468) @@ -72,9 +72,9 @@ int vm_ioapic_assert_irq(struct vmctx *c int vm_ioapic_deassert_irq(struct vmctx *ctx, int irq); int vm_ioapic_pulse_irq(struct vmctx *ctx, int irq); int vm_ioapic_pincount(struct vmctx *ctx, int *pincount); +int vm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq); int vm_isa_deassert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq); int vm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq); -int vm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_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/vmm/io/vatpic.c ============================================================================== --- head/sys/amd64/vmm/io/vatpic.c Mon Apr 14 18:38:14 2014 (r264467) +++ head/sys/amd64/vmm/io/vatpic.c Mon Apr 14 19:00:20 2014 (r264468) @@ -67,6 +67,7 @@ struct atpic { bool aeoi; bool poll; bool rotate; + bool sfn; /* special fully-nested mode */ int irq_base; uint8_t request; /* Interrupt Request Register (IIR) */ @@ -75,6 +76,8 @@ struct atpic { int acnt[8]; /* sum of pin asserts and deasserts */ int priority; /* current pin priority */ + + bool intr_raised; }; struct vatpic { @@ -82,8 +85,6 @@ struct vatpic { struct mtx mtx; struct atpic atpic[2]; uint8_t elc[2]; - - bool intr_raised; }; #define VATPIC_CTR0(vatpic, fmt) \ @@ -101,6 +102,7 @@ struct vatpic { #define VATPIC_CTR4(vatpic, fmt, a1, a2, a3, a4) \ VM_CTR4((vatpic)->vm, fmt, a1, a2, a3, a4) +static void vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate); static __inline int vatpic_get_highest_isrpin(struct atpic *atpic) @@ -122,13 +124,23 @@ vatpic_get_highest_isrpin(struct atpic * static __inline int vatpic_get_highest_irrpin(struct atpic *atpic) { + int serviced; int bit, pin; int i, j; + /* + * In 'Special Fully-Nested Mode' when an interrupt request from + * a slave is in service, the slave is not locked out from the + * master's priority logic. + */ + serviced = atpic->service; + if (atpic->sfn) + serviced &= ~(1 << 2); + for (i = 0; i <= 7; i++) { pin = ((i + 7 - atpic->priority) & 0x7); bit = (1 << pin); - if (atpic->service & bit) + if (serviced & bit) break; } @@ -150,14 +162,35 @@ vatpic_notify_intr(struct vatpic *vatpic KASSERT(VATPIC_LOCKED(vatpic), ("vatpic_notify_intr not locked")); - if (vatpic->intr_raised == true) - return; + /* + * First check the slave. + */ + atpic = &vatpic->atpic[1]; + if (!atpic->intr_raised && + (pin = vatpic_get_highest_irrpin(atpic)) != -1) { + VATPIC_CTR4(vatpic, "atpic slave notify pin = %d " + "(imr 0x%x irr 0x%x isr 0x%x)", pin, + atpic->mask, atpic->request, atpic->service); - /* XXX master only */ - atpic = &vatpic->atpic[0]; + /* + * Cascade the request from the slave to the master. + */ + atpic->intr_raised = true; + vatpic_set_pinstate(vatpic, 2, true); + vatpic_set_pinstate(vatpic, 2, false); + } else { + VATPIC_CTR3(vatpic, "atpic slave no eligible interrupts " + "(imr 0x%x irr 0x%x isr 0x%x)", + atpic->mask, atpic->request, atpic->service); + } - if ((pin = vatpic_get_highest_irrpin(atpic)) != -1) { - VATPIC_CTR4(vatpic, "atpic notify pin = %d " + /* + * Then check the master. + */ + atpic = &vatpic->atpic[0]; + if (!atpic->intr_raised && + (pin = vatpic_get_highest_irrpin(atpic)) != -1) { + VATPIC_CTR4(vatpic, "atpic master notify pin = %d " "(imr 0x%x irr 0x%x isr 0x%x)", pin, atpic->mask, atpic->request, atpic->service); @@ -183,11 +216,11 @@ vatpic_notify_intr(struct vatpic *vatpic * programmed as ExtINT to indicate that the PIC is * the source of the interrupt. */ + atpic->intr_raised = true; lapic_set_local_intr(vatpic->vm, -1, APIC_LVT_LINT0); vioapic_pulse_irq(vatpic->vm, 0); - vatpic->intr_raised = true; } else { - VATPIC_CTR3(vatpic, "atpic no eligible interrupts " + VATPIC_CTR3(vatpic, "atpic master no eligible interrupts " "(imr 0x%x irr 0x%x isr 0x%x)", atpic->mask, atpic->request, atpic->service); } @@ -422,7 +455,6 @@ vatpic_pending_intr(struct vm *vm, int * vatpic = vm_atpic(vm); - /* XXX master only */ atpic = &vatpic->atpic[0]; VATPIC_LOCK(vatpic); @@ -430,37 +462,53 @@ vatpic_pending_intr(struct vm *vm, int * pin = vatpic_get_highest_irrpin(atpic); if (pin == -1) pin = 7; + if (pin == 2) { + atpic = &vatpic->atpic[1]; + pin = vatpic_get_highest_irrpin(atpic); + } *vecptr = atpic->irq_base + pin; VATPIC_UNLOCK(vatpic); } +static void +vatpic_pin_accepted(struct atpic *atpic, int pin) +{ + atpic->intr_raised = false; + + if (atpic->acnt[pin] == 0) + atpic->request &= ~(1 << pin); + + if (atpic->aeoi == true) { + if (atpic->rotate == true) + atpic->priority = pin; + } else { + atpic->service |= (1 << pin); + } +} + void vatpic_intr_accepted(struct vm *vm, int vector) { struct vatpic *vatpic; - struct atpic *atpic; int pin; vatpic = vm_atpic(vm); - /* XXX master only */ - atpic = &vatpic->atpic[0]; - VATPIC_LOCK(vatpic); - vatpic->intr_raised = false; pin = vector & 0x7; - if (atpic->acnt[pin] == 0) - atpic->request &= ~(1 << pin); - - if (atpic->aeoi == true) { - if (atpic->rotate == true) - atpic->priority = pin; + if ((vector & ~0x7) == vatpic->atpic[1].irq_base) { + vatpic_pin_accepted(&vatpic->atpic[1], pin); + /* + * If this vector originated from the slave, + * accept the cascaded interrupt too. + */ + vatpic_pin_accepted(&vatpic->atpic[0], 2); } else { - atpic->service |= (1 << pin); + vatpic_pin_accepted(&vatpic->atpic[0], pin); } vatpic_notify_intr(vatpic); @@ -468,47 +516,43 @@ vatpic_intr_accepted(struct vm *vm, int VATPIC_UNLOCK(vatpic); } -int -vatpic_master_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +static int +vatpic_read(struct vatpic *vatpic, struct atpic *atpic, struct vm_exit *vmexit) { - struct vatpic *vatpic; - struct atpic *atpic; - int error; - uint8_t val; - - error = 0; - vatpic = vm_atpic(vm); - atpic = &vatpic->atpic[0]; + VATPIC_LOCK(vatpic); - if (vmexit->u.inout.bytes != 1) + if (atpic->poll) { + VATPIC_CTR0(vatpic, "vatpic polled mode not supported"); + VATPIC_UNLOCK(vatpic); return (-1); - - if (vmexit->u.inout.in) { - VATPIC_LOCK(vatpic); - if (atpic->poll) { - VATPIC_CTR0(vatpic, "vatpic polled mode not " - "supported"); - VATPIC_UNLOCK(vatpic); - return (-1); + } else { + if (vmexit->u.inout.port & ICU_IMR_OFFSET) { + /* read interrrupt mask register */ + vmexit->u.inout.eax = atpic->mask; } else { - if (vmexit->u.inout.port & ICU_IMR_OFFSET) { - /* read interrrupt mask register */ - vmexit->u.inout.eax = atpic->mask; + if (atpic->rd_cmd_reg == OCW3_RIS) { + /* read interrupt service register */ + vmexit->u.inout.eax = atpic->service; } else { - if (atpic->rd_cmd_reg == OCW3_RIS) { - /* read interrupt service register */ - vmexit->u.inout.eax = atpic->service; - } else { - /* read interrupt request register */ - vmexit->u.inout.eax = atpic->request; - } + /* read interrupt request register */ + vmexit->u.inout.eax = atpic->request; } } - VATPIC_UNLOCK(vatpic); - - return (0); } + VATPIC_UNLOCK(vatpic); + + return (0); + +} + +static int +vatpic_write(struct vatpic *vatpic, struct atpic *atpic, + struct vm_exit *vmexit) +{ + int error; + uint8_t val; + val = vmexit->u.inout.eax; VATPIC_LOCK(vatpic); @@ -550,22 +594,41 @@ vatpic_master_handler(void *vm, int vcpu } int -vatpic_slave_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +vatpic_master_handler(void *vm, int vcpuid, struct vm_exit *vmexit) { + struct vatpic *vatpic; + struct atpic *atpic; + + vatpic = vm_atpic(vm); + atpic = &vatpic->atpic[0]; + if (vmexit->u.inout.bytes != 1) return (-1); if (vmexit->u.inout.in) { - if (vmexit->u.inout.port & ICU_IMR_OFFSET) { - /* all interrupts masked */ - vmexit->u.inout.eax = 0xff; - } else { - vmexit->u.inout.eax = 0x00; - } + return (vatpic_read(vatpic, atpic, vmexit)); } - /* Pretend all accesses to the slave 8259 are alright */ - return (0); + return (vatpic_write(vatpic, atpic, vmexit)); +} + +int +vatpic_slave_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +{ + struct vatpic *vatpic; + struct atpic *atpic; + + vatpic = vm_atpic(vm); + atpic = &vatpic->atpic[1]; + + if (vmexit->u.inout.bytes != 1) + return (-1); + + if (vmexit->u.inout.in) { + return (vatpic_read(vatpic, atpic, vmexit)); + } + + return (vatpic_write(vatpic, atpic, vmexit)); } int @@ -580,6 +643,8 @@ vatpic_elc_handler(void *vm, int vcpuid, if (vmexit->u.inout.bytes != 1) return (-1); + VATPIC_LOCK(vatpic); + if (vmexit->u.inout.in) { if (is_master) vmexit->u.inout.eax = vatpic->elc[0]; @@ -602,6 +667,8 @@ vatpic_elc_handler(void *vm, int vcpuid, vatpic->elc[1] = (vmexit->u.inout.eax & 0xde); } + VATPIC_UNLOCK(vatpic); + return (0); } Modified: head/usr.sbin/bhyve/pm.c ============================================================================== --- head/usr.sbin/bhyve/pm.c Mon Apr 14 18:38:14 2014 (r264467) +++ head/usr.sbin/bhyve/pm.c Mon Apr 14 19:00:20 2014 (r264468) @@ -83,7 +83,7 @@ sci_assert(struct vmctx *ctx) if (sci_active) return; - vm_ioapic_assert_irq(ctx, SCI_INT); + vm_isa_assert_irq(ctx, SCI_INT, SCI_INT); sci_active = 1; } @@ -93,7 +93,7 @@ sci_deassert(struct vmctx *ctx) if (!sci_active) return; - vm_ioapic_deassert_irq(ctx, SCI_INT); + vm_isa_deassert_irq(ctx, SCI_INT, SCI_INT); sci_active = 0; }