From owner-svn-src-stable-10@FreeBSD.ORG Tue Dec 30 22:22:52 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id EE769519; Tue, 30 Dec 2014 22:22:51 +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 D7256120C; Tue, 30 Dec 2014 22:22:51 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sBUMMpkm098803; Tue, 30 Dec 2014 22:22:51 GMT (envelope-from neel@FreeBSD.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sBUMMl35098781; Tue, 30 Dec 2014 22:22:47 GMT (envelope-from neel@FreeBSD.org) Message-Id: <201412302222.sBUMMl35098781@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: neel set sender to neel@FreeBSD.org using -f From: Neel Natu Date: Tue, 30 Dec 2014 22:22:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r276429 - in stable/10: sys/amd64/include sys/amd64/vmm sys/amd64/vmm/intel sys/amd64/vmm/io sys/modules/linux sys/modules/vmm usr.sbin/bhyve X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 30 Dec 2014 22:22:52 -0000 Author: neel Date: Tue Dec 30 22:22:46 2014 New Revision: 276429 URL: https://svnweb.freebsd.org/changeset/base/276429 Log: MFC r273683 Move the ACPI PM timer emulation into vmm.ko. MFC r273706 Change the type of the first argument to the I/O emulation handlers to 'struct vm *'. MFC r273710 Add a comment explaining the intent behind the I/O reservation [0x72-0x77]. MFC r273744 Add foo_genassym.c files to DPSRCS so dependencies for them are generated. This ensures these objects are rebuilt to generate an updated header of assembly constants if needed. MFC r274045 If the start bit, PxCMD.ST, is cleared and nothing is in-flight then PxCI, PxSACT, PxCMD.CCS and PxCMD.CR should be 0. MFC r274076 Improve the ability to cancel an in-flight request by using an interrupt, via SIGCONT, to force the read or write system call to return prematurely. MFC r274330 To allow a request to be submitted from within the callback routine of a completing one increase the total by 1 but don't advertise it. MFC r274931 Change the lower bound for guest vmspace allocation to 0 instead of using the VM_MIN_ADDRESS constant. MFC r275817 For level triggered interrupts clear the PIC IRR bit when the interrupt pin is deasserted. MFC r275850 Fix 8259 IRQ priority resolver. MFC r275952 Various 8259 device model improvements. MFC r275965 Emulate writes to the IA32_MISC_ENABLE MSR. Added: stable/10/sys/amd64/vmm/io/vpmtmr.c - copied, changed from r273683, head/sys/amd64/vmm/io/vpmtmr.c stable/10/sys/amd64/vmm/io/vpmtmr.h - copied, changed from r273683, head/sys/amd64/vmm/io/vpmtmr.h Deleted: stable/10/usr.sbin/bhyve/pmtmr.c Modified: stable/10/sys/amd64/include/vmm.h stable/10/sys/amd64/vmm/intel/vmx_msr.c stable/10/sys/amd64/vmm/io/vatpic.c stable/10/sys/amd64/vmm/io/vatpic.h stable/10/sys/amd64/vmm/io/vatpit.c stable/10/sys/amd64/vmm/io/vatpit.h stable/10/sys/amd64/vmm/vmm.c stable/10/sys/amd64/vmm/vmm_ioport.c stable/10/sys/amd64/vmm/vmm_ioport.h stable/10/sys/modules/linux/Makefile stable/10/sys/modules/vmm/Makefile stable/10/usr.sbin/bhyve/Makefile stable/10/usr.sbin/bhyve/block_if.c stable/10/usr.sbin/bhyve/pci_ahci.c stable/10/usr.sbin/bhyve/rtc.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/amd64/include/vmm.h ============================================================================== --- stable/10/sys/amd64/include/vmm.h Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/sys/amd64/include/vmm.h Tue Dec 30 22:22:46 2014 (r276429) @@ -285,6 +285,7 @@ int vm_assign_pptdev(struct vm *vm, int int vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func); struct vatpic *vm_atpic(struct vm *vm); struct vatpit *vm_atpit(struct vm *vm); +struct vpmtmr *vm_pmtmr(struct vm *vm); /* * Inject exception 'vme' into the guest vcpu. This function returns 0 on Modified: stable/10/sys/amd64/vmm/intel/vmx_msr.c ============================================================================== --- stable/10/sys/amd64/vmm/intel/vmx_msr.c Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/sys/amd64/vmm/intel/vmx_msr.c Tue Dec 30 22:22:46 2014 (r276429) @@ -376,9 +376,31 @@ vmx_rdmsr(struct vmx *vmx, int vcpuid, u int vmx_wrmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t val, bool *retu) { - int error = 0; - + uint64_t changed; + int error; + + error = 0; switch (num) { + case MSR_IA32_MISC_ENABLE: + changed = val ^ misc_enable; + /* + * If the host has disabled the NX feature then the guest + * also cannot use it. However, a Linux guest will try to + * enable the NX feature by writing to the MISC_ENABLE MSR. + * + * This can be safely ignored because the memory management + * code looks at CPUID.80000001H:EDX.NX to check if the + * functionality is actually enabled. + */ + changed &= ~(1UL << 34); + + /* + * Punt to userspace if any other bits are being modified. + */ + if (changed) + error = EINVAL; + + break; default: error = EINVAL; break; Modified: stable/10/sys/amd64/vmm/io/vatpic.c ============================================================================== --- stable/10/sys/amd64/vmm/io/vatpic.c Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/sys/amd64/vmm/io/vatpic.c Tue Dec 30 22:22:46 2014 (r276429) @@ -75,7 +75,7 @@ struct atpic { uint8_t mask; /* Interrupt Mask Register (IMR) */ int acnt[8]; /* sum of pin asserts and deasserts */ - int priority; /* current pin priority */ + int lowprio; /* lowest priority irq */ bool intr_raised; }; @@ -102,16 +102,33 @@ struct vatpic { #define VATPIC_CTR4(vatpic, fmt, a1, a2, a3, a4) \ VM_CTR4((vatpic)->vm, fmt, a1, a2, a3, a4) +/* + * Loop over all the pins in priority order from highest to lowest. + */ +#define ATPIC_PIN_FOREACH(pinvar, atpic, tmpvar) \ + for (tmpvar = 0, pinvar = (atpic->lowprio + 1) & 0x7; \ + tmpvar < 8; \ + tmpvar++, pinvar = (pinvar + 1) & 0x7) + static void vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate); +static __inline bool +master_atpic(struct vatpic *vatpic, struct atpic *atpic) +{ + + if (atpic == &vatpic->atpic[0]) + return (true); + else + return (false); +} + static __inline int vatpic_get_highest_isrpin(struct atpic *atpic) { int bit, pin; int i; - for (i = 0; i <= 7; i++) { - pin = ((i + 7 - atpic->priority) & 0x7); + ATPIC_PIN_FOREACH(pin, atpic, i) { bit = (1 << pin); if (atpic->service & bit) @@ -125,8 +142,7 @@ static __inline int vatpic_get_highest_irrpin(struct atpic *atpic) { int serviced; - int bit, pin; - int i, j; + int bit, pin, tmp; /* * In 'Special Fully-Nested Mode' when an interrupt request from @@ -137,17 +153,21 @@ vatpic_get_highest_irrpin(struct atpic * if (atpic->sfn) serviced &= ~(1 << 2); - for (i = 0; i <= 7; i++) { - pin = ((i + 7 - atpic->priority) & 0x7); - bit = (1 << pin); - if (serviced & bit) + ATPIC_PIN_FOREACH(pin, atpic, tmp) { + bit = 1 << pin; + + /* + * If there is already an interrupt in service at the same + * or higher priority then bail. + */ + if ((serviced & bit) != 0) break; - } - for (j = 0; j < i; j++) { - pin = ((j + 7 - atpic->priority) & 0x7); - bit = (1 << pin); - if (atpic->request & bit && (~atpic->mask & bit)) + /* + * If an interrupt is asserted and not masked then return + * the corresponding 'pin' to the caller. + */ + if ((atpic->request & bit) != 0 && (atpic->mask & bit) == 0) return (pin); } @@ -238,8 +258,9 @@ vatpic_icw1(struct vatpic *vatpic, struc atpic->icw_num = 1; atpic->mask = 0; - atpic->priority = 0; + atpic->lowprio = 7; atpic->rd_cmd_reg = 0; + atpic->poll = 0; if ((val & ICW1_SNGL) != 0) { VATPIC_CTR0(vatpic, "vatpic cascade mode required"); @@ -291,6 +312,15 @@ vatpic_icw4(struct vatpic *vatpic, struc if ((val & ICW4_AEOI) != 0) atpic->aeoi = true; + if ((val & ICW4_SFNM) != 0) { + if (master_atpic(vatpic, atpic)) { + atpic->sfn = true; + } else { + VATPIC_CTR1(vatpic, "Ignoring special fully nested " + "mode on slave atpic: %#x", val); + } + } + atpic->icw_num = 0; atpic->ready = true; @@ -329,11 +359,11 @@ vatpic_ocw2(struct vatpic *vatpic, struc atpic->service &= ~(1 << isr_bit); if (atpic->rotate) - atpic->priority = isr_bit; + atpic->lowprio = isr_bit; } } else if ((val & OCW2_SL) != 0 && atpic->rotate == true) { /* specific priority */ - atpic->priority = val & 0x7; + atpic->lowprio = val & 0x7; } return (0); @@ -344,11 +374,17 @@ vatpic_ocw3(struct vatpic *vatpic, struc { VATPIC_CTR1(vatpic, "atpic ocw3 0x%x", val); - atpic->poll = ((val & OCW3_P) != 0); + if (val & OCW3_ESMM) { + VATPIC_CTR0(vatpic, "atpic special mask mode not implemented"); + return (-1); + } if (val & OCW3_RR) { /* read register command */ atpic->rd_cmd_reg = val & OCW3_RIS; + + /* Polling mode */ + atpic->poll = ((val & OCW3_P) != 0); } return (0); @@ -388,6 +424,8 @@ vatpic_set_pinstate(struct vatpic *vatpi } else if (oldcnt == 1 && newcnt == 0) { /* falling edge */ VATPIC_CTR1(vatpic, "atpic pin%d: deasserted", pin); + if (level) + atpic->request &= ~(1 << (pin & 0x7)); } else { VATPIC_CTR3(vatpic, "atpic pin%d: %s, ignored, acnt %d", pin, newstate ? "asserted" : "deasserted", newcnt); @@ -528,7 +566,7 @@ vatpic_pin_accepted(struct atpic *atpic, if (atpic->aeoi == true) { if (atpic->rotate == true) - atpic->priority = pin; + atpic->lowprio = pin; } else { atpic->service |= (1 << pin); } @@ -566,12 +604,19 @@ static int vatpic_read(struct vatpic *vatpic, struct atpic *atpic, bool in, int port, int bytes, uint32_t *eax) { + int pin; + VATPIC_LOCK(vatpic); if (atpic->poll) { - VATPIC_CTR0(vatpic, "vatpic polled mode not supported"); - VATPIC_UNLOCK(vatpic); - return (-1); + atpic->poll = 0; + pin = vatpic_get_highest_irrpin(atpic); + if (pin >= 0) { + vatpic_pin_accepted(atpic, pin); + *eax = 0x80 | pin; + } else { + *eax = 0; + } } else { if (port & ICU_IMR_OFFSET) { /* read interrrupt mask register */ @@ -641,7 +686,7 @@ vatpic_write(struct vatpic *vatpic, stru } int -vatpic_master_handler(void *vm, int vcpuid, bool in, int port, int bytes, +vatpic_master_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, uint32_t *eax) { struct vatpic *vatpic; @@ -661,7 +706,7 @@ vatpic_master_handler(void *vm, int vcpu } int -vatpic_slave_handler(void *vm, int vcpuid, bool in, int port, int bytes, +vatpic_slave_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, uint32_t *eax) { struct vatpic *vatpic; @@ -681,7 +726,7 @@ vatpic_slave_handler(void *vm, int vcpui } int -vatpic_elc_handler(void *vm, int vcpuid, bool in, int port, int bytes, +vatpic_elc_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, uint32_t *eax) { struct vatpic *vatpic; Modified: stable/10/sys/amd64/vmm/io/vatpic.h ============================================================================== --- stable/10/sys/amd64/vmm/io/vatpic.h Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/sys/amd64/vmm/io/vatpic.h Tue Dec 30 22:22:46 2014 (r276429) @@ -39,11 +39,11 @@ struct vatpic *vatpic_init(struct vm *vm); void vatpic_cleanup(struct vatpic *vatpic); -int vatpic_master_handler(void *vm, int vcpuid, bool in, int port, int bytes, - uint32_t *eax); -int vatpic_slave_handler(void *vm, int vcpuid, bool in, int port, int bytes, - uint32_t *eax); -int vatpic_elc_handler(void *vm, int vcpuid, bool in, int port, int bytes, +int vatpic_master_handler(struct vm *vm, int vcpuid, bool in, int port, + int bytes, uint32_t *eax); +int vatpic_slave_handler(struct vm *vm, int vcpuid, bool in, int port, + int bytes, uint32_t *eax); +int vatpic_elc_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, uint32_t *eax); int vatpic_assert_irq(struct vm *vm, int irq); Modified: stable/10/sys/amd64/vmm/io/vatpit.c ============================================================================== --- stable/10/sys/amd64/vmm/io/vatpit.c Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/sys/amd64/vmm/io/vatpit.c Tue Dec 30 22:22:46 2014 (r276429) @@ -317,7 +317,7 @@ vatpit_update_mode(struct vatpit *vatpit } int -vatpit_handler(void *vm, int vcpuid, bool in, int port, int bytes, +vatpit_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, uint32_t *eax) { struct vatpit *vatpit; @@ -400,7 +400,7 @@ vatpit_handler(void *vm, int vcpuid, boo } int -vatpit_nmisc_handler(void *vm, int vcpuid, bool in, int port, int bytes, +vatpit_nmisc_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, uint32_t *eax) { struct vatpit *vatpit; Modified: stable/10/sys/amd64/vmm/io/vatpit.h ============================================================================== --- stable/10/sys/amd64/vmm/io/vatpit.h Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/sys/amd64/vmm/io/vatpit.h Tue Dec 30 22:22:46 2014 (r276429) @@ -37,9 +37,9 @@ struct vatpit *vatpit_init(struct vm *vm); void vatpit_cleanup(struct vatpit *vatpit); -int vatpit_handler(void *vm, int vcpuid, bool in, int port, int bytes, - uint32_t *eax); -int vatpit_nmisc_handler(void *vm, int vcpuid, bool in, int port, int bytes, +int vatpit_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, uint32_t *eax); +int vatpit_nmisc_handler(struct vm *vm, int vcpuid, bool in, int port, + int bytes, uint32_t *eax); #endif /* _VATPIT_H_ */ Copied and modified: stable/10/sys/amd64/vmm/io/vpmtmr.c (from r273683, head/sys/amd64/vmm/io/vpmtmr.c) ============================================================================== --- head/sys/amd64/vmm/io/vpmtmr.c Sun Oct 26 04:44:28 2014 (r273683, copy source) +++ stable/10/sys/amd64/vmm/io/vpmtmr.c Tue Dec 30 22:22:46 2014 (r276429) @@ -79,7 +79,7 @@ vpmtmr_cleanup(struct vpmtmr *vpmtmr) } int -vpmtmr_handler(void *vm, int vcpuid, bool in, int port, int bytes, +vpmtmr_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, uint32_t *val) { struct vpmtmr *vpmtmr; Copied and modified: stable/10/sys/amd64/vmm/io/vpmtmr.h (from r273683, head/sys/amd64/vmm/io/vpmtmr.h) ============================================================================== --- head/sys/amd64/vmm/io/vpmtmr.h Sun Oct 26 04:44:28 2014 (r273683, copy source) +++ stable/10/sys/amd64/vmm/io/vpmtmr.h Tue Dec 30 22:22:46 2014 (r276429) @@ -36,7 +36,7 @@ struct vpmtmr; struct vpmtmr *vpmtmr_init(struct vm *vm); void vpmtmr_cleanup(struct vpmtmr *pmtmr); -int vpmtmr_handler(void *vm, int vcpuid, bool in, int port, int bytes, +int vpmtmr_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, uint32_t *val); #endif Modified: stable/10/sys/amd64/vmm/vmm.c ============================================================================== --- stable/10/sys/amd64/vmm/vmm.c Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/sys/amd64/vmm/vmm.c Tue Dec 30 22:22:46 2014 (r276429) @@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$"); #include "vhpet.h" #include "vioapic.h" #include "vlapic.h" +#include "vpmtmr.h" #include "vmm_ipi.h" #include "vmm_stat.h" #include "vmm_lapic.h" @@ -134,6 +135,7 @@ struct vm { struct vioapic *vioapic; /* (i) virtual ioapic */ struct vatpic *vatpic; /* (i) virtual atpic */ struct vatpit *vatpit; /* (i) virtual atpit */ + struct vpmtmr *vpmtmr; /* (i) virtual ACPI PM timer */ volatile cpuset_t active_cpus; /* (i) active vcpus */ int suspend; /* (i) stop VM execution */ volatile cpuset_t suspended_cpus; /* (i) suspended vcpus */ @@ -373,6 +375,7 @@ vm_init(struct vm *vm, bool create) vm->vhpet = vhpet_init(vm); vm->vatpic = vatpic_init(vm); vm->vatpit = vatpit_init(vm); + vm->vpmtmr = vpmtmr_init(vm); CPU_ZERO(&vm->active_cpus); @@ -399,7 +402,7 @@ vm_create(const char *name, struct vm ** if (name == NULL || strlen(name) >= VM_MAX_NAMELEN) return (EINVAL); - vmspace = VMSPACE_ALLOC(VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); + vmspace = VMSPACE_ALLOC(0, VM_MAXUSER_ADDRESS); if (vmspace == NULL) return (ENOMEM); @@ -435,6 +438,7 @@ vm_cleanup(struct vm *vm, bool destroy) if (vm->iommu != NULL) iommu_destroy_domain(vm->iommu); + vpmtmr_cleanup(vm->vpmtmr); vatpit_cleanup(vm->vatpit); vhpet_cleanup(vm->vhpet); vatpic_cleanup(vm->vatpic); @@ -2212,6 +2216,13 @@ vm_atpit(struct vm *vm) return (vm->vatpit); } +struct vpmtmr * +vm_pmtmr(struct vm *vm) +{ + + return (vm->vpmtmr); +} + enum vm_reg_name vm_segment_name(int seg) { Modified: stable/10/sys/amd64/vmm/vmm_ioport.c ============================================================================== --- stable/10/sys/amd64/vmm/vmm_ioport.c Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/sys/amd64/vmm/vmm_ioport.c Tue Dec 30 22:22:46 2014 (r276429) @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include "vatpic.h" #include "vatpit.h" +#include "vpmtmr.h" #include "vmm_ioport.h" #include "vmm_ktr.h" @@ -58,6 +59,7 @@ ioport_handler_func_t ioport_handler[MAX [IO_ICU2 + ICU_IMR_OFFSET] = vatpic_slave_handler, [IO_ELCR1] = vatpic_elc_handler, [IO_ELCR2] = vatpic_elc_handler, + [IO_PMTMR] = vpmtmr_handler, }; #ifdef KTR Modified: stable/10/sys/amd64/vmm/vmm_ioport.h ============================================================================== --- stable/10/sys/amd64/vmm/vmm_ioport.h Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/sys/amd64/vmm/vmm_ioport.h Tue Dec 30 22:22:46 2014 (r276429) @@ -29,7 +29,7 @@ #ifndef _VMM_IOPORT_H_ #define _VMM_IOPORT_H_ -typedef int (*ioport_handler_func_t)(void *vm, int vcpuid, +typedef int (*ioport_handler_func_t)(struct vm *vm, int vcpuid, bool in, int port, int bytes, uint32_t *val); int vm_handle_inout(struct vm *vm, int vcpuid, struct vm_exit *vme, bool *retu); Modified: stable/10/sys/modules/linux/Makefile ============================================================================== --- stable/10/sys/modules/linux/Makefile Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/sys/modules/linux/Makefile Tue Dec 30 22:22:46 2014 (r276429) @@ -16,6 +16,7 @@ SRCS= linux_fork.c linux${SFX}_dummy.c l linux_timer.c \ opt_inet6.h opt_compat.h opt_kdtrace.h opt_posix.h opt_usb.h \ vnode_if.h device_if.h bus_if.h assym.s +DPSRCS= linux${SFX}_genassym.c # XXX: for assym.s SRCS+= opt_kstack_pages.h opt_nfs.h opt_compat.h opt_hwpmc_hooks.h Modified: stable/10/sys/modules/vmm/Makefile ============================================================================== --- stable/10/sys/modules/vmm/Makefile Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/sys/modules/vmm/Makefile Tue Dec 30 22:22:46 2014 (r276429) @@ -4,6 +4,7 @@ KMOD= vmm SRCS= opt_acpi.h opt_ddb.h device_if.h bus_if.h pci_if.h SRCS+= vmx_assym.h svm_assym.h +DPSRCS= vmx_genassym.c svm_genassym.c CFLAGS+= -DVMM_KEEP_STATS -DSMP CFLAGS+= -I${.CURDIR}/../../amd64/vmm @@ -33,7 +34,8 @@ SRCS+= iommu.c \ vatpit.c \ vhpet.c \ vioapic.c \ - vlapic.c + vlapic.c \ + vpmtmr.c # intel-specific files .PATH: ${.CURDIR}/../../amd64/vmm/intel @@ -52,7 +54,7 @@ SRCS+= vmcb.c \ npt.c \ amdv.c \ svm_msr.c - + CLEANFILES= vmx_assym.h vmx_genassym.o svm_assym.h svm_genassym.o vmx_assym.h: vmx_genassym.o Modified: stable/10/usr.sbin/bhyve/Makefile ============================================================================== --- stable/10/usr.sbin/bhyve/Makefile Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/usr.sbin/bhyve/Makefile Tue Dec 30 22:22:46 2014 (r276429) @@ -31,7 +31,6 @@ SRCS= \ pci_virtio_rnd.c \ pci_uart.c \ pm.c \ - pmtmr.c \ post.c \ rtc.c \ smbiostbl.c \ Modified: stable/10/usr.sbin/bhyve/block_if.c ============================================================================== --- stable/10/usr.sbin/bhyve/block_if.c Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/usr.sbin/bhyve/block_if.c Tue Dec 30 22:22:46 2014 (r276429) @@ -43,14 +43,18 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include + #include "bhyverun.h" +#include "mevent.h" #include "block_if.h" #define BLOCKIF_SIG 0xb109b109 -#define BLOCKIF_MAXREQ 32 +#define BLOCKIF_MAXREQ 33 enum blockop { BOP_READ, @@ -60,7 +64,9 @@ enum blockop { enum blockstat { BST_FREE, - BST_INUSE + BST_PEND, + BST_BUSY, + BST_DONE }; struct blockif_elem { @@ -68,6 +74,7 @@ struct blockif_elem { struct blockif_req *be_req; enum blockop be_op; enum blockstat be_status; + pthread_t be_tid; }; struct blockif_ctxt { @@ -81,13 +88,25 @@ struct blockif_ctxt { pthread_cond_t bc_cond; int bc_closing; - /* Request elements and free/inuse queues */ + /* Request elements and free/pending/busy queues */ TAILQ_HEAD(, blockif_elem) bc_freeq; - TAILQ_HEAD(, blockif_elem) bc_inuseq; + TAILQ_HEAD(, blockif_elem) bc_pendq; + TAILQ_HEAD(, blockif_elem) bc_busyq; u_int bc_req_count; struct blockif_elem bc_reqs[BLOCKIF_MAXREQ]; }; +static pthread_once_t blockif_once = PTHREAD_ONCE_INIT; + +struct blockif_sig_elem { + pthread_mutex_t bse_mtx; + pthread_cond_t bse_cond; + int bse_pending; + struct blockif_sig_elem *bse_next; +}; + +static struct blockif_sig_elem *blockif_bse_head; + static int blockif_enqueue(struct blockif_ctxt *bc, struct blockif_req *breq, enum blockop op) @@ -101,10 +120,10 @@ blockif_enqueue(struct blockif_ctxt *bc, assert(be->be_status == BST_FREE); TAILQ_REMOVE(&bc->bc_freeq, be, be_link); - be->be_status = BST_INUSE; + be->be_status = BST_PEND; be->be_req = breq; be->be_op = op; - TAILQ_INSERT_TAIL(&bc->bc_inuseq, be, be_link); + TAILQ_INSERT_TAIL(&bc->bc_pendq, be, be_link); bc->bc_req_count++; @@ -112,26 +131,38 @@ blockif_enqueue(struct blockif_ctxt *bc, } static int -blockif_dequeue(struct blockif_ctxt *bc, struct blockif_elem *el) +blockif_dequeue(struct blockif_ctxt *bc, struct blockif_elem **bep) { struct blockif_elem *be; if (bc->bc_req_count == 0) return (ENOENT); - be = TAILQ_FIRST(&bc->bc_inuseq); + be = TAILQ_FIRST(&bc->bc_pendq); assert(be != NULL); - assert(be->be_status == BST_INUSE); - *el = *be; + assert(be->be_status == BST_PEND); + TAILQ_REMOVE(&bc->bc_pendq, be, be_link); + be->be_status = BST_BUSY; + be->be_tid = bc->bc_btid; + TAILQ_INSERT_TAIL(&bc->bc_busyq, be, be_link); + + *bep = be; - TAILQ_REMOVE(&bc->bc_inuseq, be, be_link); + return (0); +} + +static void +blockif_complete(struct blockif_ctxt *bc, struct blockif_elem *be) +{ + assert(be->be_status == BST_DONE); + + TAILQ_REMOVE(&bc->bc_busyq, be, be_link); + be->be_tid = 0; be->be_status = BST_FREE; be->be_req = NULL; TAILQ_INSERT_TAIL(&bc->bc_freeq, be, be_link); - - bc->bc_req_count--; - return (0); + bc->bc_req_count--; } static void @@ -163,6 +194,8 @@ blockif_proc(struct blockif_ctxt *bc, st break; } + be->be_status = BST_DONE; + (*br->br_callback)(br, err); } @@ -170,16 +203,17 @@ static void * blockif_thr(void *arg) { struct blockif_ctxt *bc; - struct blockif_elem req; + struct blockif_elem *be; bc = arg; for (;;) { pthread_mutex_lock(&bc->bc_mtx); - while (!blockif_dequeue(bc, &req)) { + while (!blockif_dequeue(bc, &be)) { pthread_mutex_unlock(&bc->bc_mtx); - blockif_proc(bc, &req); + blockif_proc(bc, be); pthread_mutex_lock(&bc->bc_mtx); + blockif_complete(bc, be); } pthread_cond_wait(&bc->bc_cond, &bc->bc_mtx); pthread_mutex_unlock(&bc->bc_mtx); @@ -195,6 +229,38 @@ blockif_thr(void *arg) return (NULL); } +static void +blockif_sigcont_handler(int signal, enum ev_type type, void *arg) +{ + struct blockif_sig_elem *bse; + + for (;;) { + /* + * Process the entire list even if not intended for + * this thread. + */ + do { + bse = blockif_bse_head; + if (bse == NULL) + return; + } while (!atomic_cmpset_ptr((uintptr_t *)&blockif_bse_head, + (uintptr_t)bse, + (uintptr_t)bse->bse_next)); + + pthread_mutex_lock(&bse->bse_mtx); + bse->bse_pending = 0; + pthread_cond_signal(&bse->bse_cond); + pthread_mutex_unlock(&bse->bse_mtx); + } +} + +static void +blockif_init(void) +{ + mevent_add(SIGCONT, EVF_SIGNAL, blockif_sigcont_handler, NULL); + (void) signal(SIGCONT, SIG_IGN); +} + struct blockif_ctxt * blockif_open(const char *optstr, const char *ident) { @@ -206,6 +272,8 @@ blockif_open(const char *optstr, const c int extra, fd, i, sectsz; int nocache, sync, ro; + pthread_once(&blockif_once, blockif_init); + nocache = 0; sync = 0; ro = 0; @@ -280,7 +348,8 @@ blockif_open(const char *optstr, const c pthread_mutex_init(&bc->bc_mtx, NULL); pthread_cond_init(&bc->bc_cond, NULL); TAILQ_INIT(&bc->bc_freeq); - TAILQ_INIT(&bc->bc_inuseq); + TAILQ_INIT(&bc->bc_pendq); + TAILQ_INIT(&bc->bc_busyq); bc->bc_req_count = 0; for (i = 0; i < BLOCKIF_MAXREQ; i++) { bc->bc_reqs[i].be_status = BST_FREE; @@ -357,23 +426,76 @@ blockif_cancel(struct blockif_ctxt *bc, assert(bc->bc_magic == BLOCKIF_SIG); pthread_mutex_lock(&bc->bc_mtx); - TAILQ_FOREACH(be, &bc->bc_inuseq, be_link) { + /* + * Check pending requests. + */ + TAILQ_FOREACH(be, &bc->bc_pendq, be_link) { + if (be->be_req == breq) + break; + } + if (be != NULL) { + /* + * Found it. + */ + TAILQ_REMOVE(&bc->bc_pendq, be, be_link); + be->be_status = BST_FREE; + be->be_req = NULL; + TAILQ_INSERT_TAIL(&bc->bc_freeq, be, be_link); + bc->bc_req_count--; + pthread_mutex_unlock(&bc->bc_mtx); + + return (0); + } + + /* + * Check in-flight requests. + */ + TAILQ_FOREACH(be, &bc->bc_busyq, be_link) { if (be->be_req == breq) break; } if (be == NULL) { + /* + * Didn't find it. + */ pthread_mutex_unlock(&bc->bc_mtx); return (EINVAL); } - TAILQ_REMOVE(&bc->bc_inuseq, be, be_link); - be->be_status = BST_FREE; - be->be_req = NULL; - TAILQ_INSERT_TAIL(&bc->bc_freeq, be, be_link); - bc->bc_req_count--; + /* + * Interrupt the processing thread to force it return + * prematurely via it's normal callback path. + */ + while (be->be_status == BST_BUSY) { + struct blockif_sig_elem bse, *old_head; + + pthread_mutex_init(&bse.bse_mtx, NULL); + pthread_cond_init(&bse.bse_cond, NULL); + + bse.bse_pending = 1; + + do { + old_head = blockif_bse_head; + bse.bse_next = old_head; + } while (!atomic_cmpset_ptr((uintptr_t *)&blockif_bse_head, + (uintptr_t)old_head, + (uintptr_t)&bse)); + + pthread_kill(be->be_tid, SIGCONT); + + pthread_mutex_lock(&bse.bse_mtx); + while (bse.bse_pending) + pthread_cond_wait(&bse.bse_cond, &bse.bse_mtx); + pthread_mutex_unlock(&bse.bse_mtx); + } + pthread_mutex_unlock(&bc->bc_mtx); - return (0); + /* + * The processing thread has been interrupted. Since it's not + * clear if the callback has been invoked yet, return EBUSY. + */ + return (EBUSY); } int @@ -478,7 +600,7 @@ blockif_queuesz(struct blockif_ctxt *bc) { assert(bc->bc_magic == BLOCKIF_SIG); - return (BLOCKIF_MAXREQ); + return (BLOCKIF_MAXREQ - 1); } int Modified: stable/10/usr.sbin/bhyve/pci_ahci.c ============================================================================== --- stable/10/usr.sbin/bhyve/pci_ahci.c Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/usr.sbin/bhyve/pci_ahci.c Tue Dec 30 22:22:46 2014 (r276429) @@ -367,11 +367,15 @@ ahci_check_stopped(struct ahci_port *p) { /* * If we are no longer processing the command list and nothing - * is in-flight, clear the running bit. + * is in-flight, clear the running bit, the current command + * slot, the command issue and active bits. */ if (!(p->cmd & AHCI_P_CMD_ST)) { - if (p->pending == 0) + if (p->pending == 0) { p->cmd &= ~(AHCI_P_CMD_CR | AHCI_P_CMD_CCS_MASK); + p->ci = 0; + p->sact = 0; + } } } Modified: stable/10/usr.sbin/bhyve/rtc.c ============================================================================== --- stable/10/usr.sbin/bhyve/rtc.c Tue Dec 30 22:19:34 2014 (r276428) +++ stable/10/usr.sbin/bhyve/rtc.c Tue Dec 30 22:22:46 2014 (r276429) @@ -375,4 +375,8 @@ rtc_dsdt(void) } LPC_DSDT(rtc_dsdt); +/* + * Reserve the extended RTC I/O ports although they are not emulated at this + * time. + */ SYSRES_IO(0x72, 6);