From owner-svn-src-projects@FreeBSD.ORG Mon Sep 24 19:32:25 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 63A48106564A; Mon, 24 Sep 2012 19:32:25 +0000 (UTC) (envelope-from neel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 444898FC18; Mon, 24 Sep 2012 19:32:25 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8OJWPHP082840; Mon, 24 Sep 2012 19:32:25 GMT (envelope-from neel@svn.freebsd.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8OJWPUE082835; Mon, 24 Sep 2012 19:32:25 GMT (envelope-from neel@svn.freebsd.org) Message-Id: <201209241932.q8OJWPUE082835@svn.freebsd.org> From: Neel Natu Date: Mon, 24 Sep 2012 19:32:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240894 - in projects/bhyve/sys/amd64: include vmm vmm/amd vmm/intel X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 24 Sep 2012 19:32:25 -0000 Author: neel Date: Mon Sep 24 19:32:24 2012 New Revision: 240894 URL: http://svn.freebsd.org/changeset/base/240894 Log: Stash the 'vm_exit' information in each 'struct vcpu'. There is no functional change at this time but this paves the way for vm exit handler functions to easily modify the exit reason going forward. Modified: projects/bhyve/sys/amd64/include/vmm.h projects/bhyve/sys/amd64/vmm/amd/amdv.c projects/bhyve/sys/amd64/vmm/intel/vmx.c projects/bhyve/sys/amd64/vmm/vmm.c Modified: projects/bhyve/sys/amd64/include/vmm.h ============================================================================== --- projects/bhyve/sys/amd64/include/vmm.h Mon Sep 24 17:34:30 2012 (r240893) +++ projects/bhyve/sys/amd64/include/vmm.h Mon Sep 24 19:32:24 2012 (r240894) @@ -43,8 +43,7 @@ struct vlapic; typedef int (*vmm_init_func_t)(void); typedef int (*vmm_cleanup_func_t)(void); typedef void * (*vmi_init_func_t)(struct vm *vm); /* instance specific apis */ -typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip, - struct vm_exit *vmexit); +typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip); typedef void (*vmi_cleanup_func_t)(void *vmi); typedef int (*vmi_mmap_func_t)(void *vmi, vm_paddr_t gpa, vm_paddr_t hpa, size_t length, vm_memattr_t attr, @@ -112,6 +111,7 @@ int vm_get_capability(struct vm *vm, int int vm_set_capability(struct vm *vm, int vcpu, int type, int val); void vm_activate_cpu(struct vm *vm, int vcpu); cpuset_t vm_active_cpus(struct vm *vm); +struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid); /* * Return 1 if device indicated by bus/slot/func is supposed to be a Modified: projects/bhyve/sys/amd64/vmm/amd/amdv.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/amd/amdv.c Mon Sep 24 17:34:30 2012 (r240893) +++ projects/bhyve/sys/amd64/vmm/amd/amdv.c Mon Sep 24 19:32:24 2012 (r240894) @@ -62,7 +62,7 @@ amdv_vminit(struct vm *vm) } static int -amdv_vmrun(void *arg, int vcpu, register_t rip, struct vm_exit *vmexit) +amdv_vmrun(void *arg, int vcpu, register_t rip) { printf("amdv_vmrun: not implemented\n"); Modified: projects/bhyve/sys/amd64/vmm/intel/vmx.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/intel/vmx.c Mon Sep 24 17:34:30 2012 (r240893) +++ projects/bhyve/sys/amd64/vmm/intel/vmx.c Mon Sep 24 19:32:24 2012 (r240894) @@ -1272,19 +1272,22 @@ vmx_exit_process(struct vmx *vmx, int vc } static int -vmx_run(void *arg, int vcpu, register_t rip, struct vm_exit *vmexit) +vmx_run(void *arg, int vcpu, register_t rip) { int error, vie, rc, handled, astpending; uint32_t exit_reason; struct vmx *vmx; struct vmxctx *vmxctx; struct vmcs *vmcs; + struct vm_exit *vmexit; vmx = arg; vmcs = &vmx->vmcs[vcpu]; vmxctx = &vmx->ctx[vcpu]; vmxctx->launched = 0; + vmexit = vm_exitinfo(vmx->vm, vcpu); + /* * XXX Can we avoid doing this every time we do a vm run? */ Modified: projects/bhyve/sys/amd64/vmm/vmm.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm.c Mon Sep 24 17:34:30 2012 (r240893) +++ projects/bhyve/sys/amd64/vmm/vmm.c Mon Sep 24 19:32:24 2012 (r240894) @@ -72,6 +72,7 @@ struct vcpu { int vcpuid; struct savefpu *guestfpu; /* guest fpu state */ void *stats; + struct vm_exit exitinfo; }; #define VCPU_F_PINNED 0x0001 #define VCPU_F_RUNNING 0x0002 @@ -110,8 +111,8 @@ static struct vmm_ops *ops; #define VMM_CLEANUP() (ops != NULL ? (*ops->cleanup)() : 0) #define VMINIT(vm) (ops != NULL ? (*ops->vminit)(vm): NULL) -#define VMRUN(vmi, vcpu, rip, vmexit) \ - (ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip, vmexit) : ENXIO) +#define VMRUN(vmi, vcpu, rip) \ + (ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip) : ENXIO) #define VMCLEANUP(vmi) (ops != NULL ? (*ops->vmcleanup)(vmi) : NULL) #define VMMMAP(vmi, gpa, hpa, len, attr, prot, spm) \ (ops != NULL ? (*ops->vmmmap)(vmi, gpa, hpa, len, attr, prot, spm) : ENXIO) @@ -164,6 +165,19 @@ vcpu_init(struct vm *vm, uint32_t vcpu_i vcpu->stats = vmm_stat_alloc(); } +struct vm_exit * +vm_exitinfo(struct vm *vm, int cpuid) +{ + struct vcpu *vcpu; + + if (cpuid < 0 || cpuid >= VM_MAXCPU) + panic("vm_exitinfo: invalid cpuid %d", cpuid); + + vcpu = &vm->vcpu[cpuid]; + + return (&vcpu->exitinfo); +} + static int vmm_init(void) { @@ -545,12 +559,15 @@ vm_run(struct vm *vm, struct vm_run *vmr restore_guest_msrs(vm, vcpuid); restore_guest_fpustate(vcpu); - error = VMRUN(vm->cookie, vcpuid, vmrun->rip, &vmrun->vm_exit); + error = VMRUN(vm->cookie, vcpuid, vmrun->rip); save_guest_fpustate(vcpu); restore_host_msrs(vm, vcpuid); vmm_stat_incr(vm, vcpuid, VCPU_TOTAL_RUNTIME, rdtsc() - tscval); + /* copy the exit information */ + bcopy(&vcpu->exitinfo, &vmrun->vm_exit, sizeof(struct vm_exit)); + critical_exit(); return (error); From owner-svn-src-projects@FreeBSD.ORG Tue Sep 25 02:33:26 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 2CD6D106564A; Tue, 25 Sep 2012 02:33:26 +0000 (UTC) (envelope-from neel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 15A088FC14; Tue, 25 Sep 2012 02:33:26 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8P2XQeK044600; Tue, 25 Sep 2012 02:33:26 GMT (envelope-from neel@svn.freebsd.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8P2XP5a044589; Tue, 25 Sep 2012 02:33:25 GMT (envelope-from neel@svn.freebsd.org) Message-Id: <201209250233.q8P2XP5a044589@svn.freebsd.org> From: Neel Natu Date: Tue, 25 Sep 2012 02:33:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240912 - in projects/bhyve: sys/amd64/include sys/amd64/vmm/intel sys/amd64/vmm/io usr.sbin/bhyve X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Sep 2012 02:33:26 -0000 Author: neel Date: Tue Sep 25 02:33:25 2012 New Revision: 240912 URL: http://svn.freebsd.org/changeset/base/240912 Log: Add an explicit exit code 'SPINUP_AP' to tell the controlling process that an AP needs to be activated by spinning up an execution context for it. The local apic emulation is now completely done in the hypervisor and it will detect writes to the ICR_LO register that try to bring up the AP. In response to such writes it will return to userspace with an exit code of SPINUP_AP. Reviewed by: grehan Added: projects/bhyve/usr.sbin/bhyve/spinup_ap.c (contents, props changed) projects/bhyve/usr.sbin/bhyve/spinup_ap.h (contents, props changed) Modified: projects/bhyve/sys/amd64/include/vmm.h projects/bhyve/sys/amd64/vmm/intel/vmx.c projects/bhyve/sys/amd64/vmm/io/vlapic.c projects/bhyve/usr.sbin/bhyve/Makefile projects/bhyve/usr.sbin/bhyve/fbsdrun.c projects/bhyve/usr.sbin/bhyve/xmsr.c Modified: projects/bhyve/sys/amd64/include/vmm.h ============================================================================== --- projects/bhyve/sys/amd64/include/vmm.h Tue Sep 25 01:33:23 2012 (r240911) +++ projects/bhyve/sys/amd64/include/vmm.h Tue Sep 25 02:33:25 2012 (r240912) @@ -228,6 +228,7 @@ enum vm_exitcode { VM_EXITCODE_MTRAP, VM_EXITCODE_PAUSE, VM_EXITCODE_PAGING, + VM_EXITCODE_SPINUP_AP, VM_EXITCODE_MAX }; @@ -260,6 +261,10 @@ struct vm_exit { uint32_t code; /* ecx value */ uint64_t wval; } msr; + struct { + int vcpu; + uint64_t rip; + } spinup_ap; } u; }; Modified: projects/bhyve/sys/amd64/vmm/intel/vmx.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/intel/vmx.c Tue Sep 25 01:33:23 2012 (r240911) +++ projects/bhyve/sys/amd64/vmm/intel/vmx.c Tue Sep 25 02:33:25 2012 (r240912) @@ -1253,6 +1253,14 @@ vmx_exit_process(struct vmx *vmx, int vc vm_exit_update_rip(vmexit); vmexit->rip += vmexit->inst_length; vmexit->inst_length = 0; + + /* + * Special case for spinning up an AP - exit to userspace to + * give the controlling process a chance to intercept and + * spin up a thread for the AP. + */ + if (vmexit->exitcode == VM_EXITCODE_SPINUP_AP) + handled = 0; } else { if (vmexit->exitcode == VM_EXITCODE_BOGUS) { /* Modified: projects/bhyve/sys/amd64/vmm/io/vlapic.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/io/vlapic.c Tue Sep 25 01:33:23 2012 (r240911) +++ projects/bhyve/sys/amd64/vmm/io/vlapic.c Tue Sep 25 02:33:25 2012 (r240912) @@ -89,6 +89,12 @@ static MALLOC_DEFINE(M_VLAPIC, "vlapic", #define x2apic(vlapic) ((vlapic)->msr_apicbase & APICBASE_X2APIC) +enum boot_state { + BS_INIT, + BS_SIPI, + BS_RUNNING +}; + struct vlapic { struct vm *vm; int vcpuid; @@ -112,6 +118,7 @@ struct vlapic { int isrvec_stk_top; uint64_t msr_apicbase; + enum boot_state boot_state; }; static void @@ -168,6 +175,11 @@ vlapic_op_reset(void* dev) memset(lapic, 0, sizeof(*lapic)); lapic->apr = vlapic->vcpuid; vlapic_init_ipi(vlapic); + + if (vlapic->vcpuid == 0) + vlapic->boot_state = BS_RUNNING; /* BSP */ + else + vlapic->boot_state = BS_INIT; /* AP */ return 0; @@ -418,6 +430,8 @@ lapic_process_icr(struct vlapic *vlapic, int i; cpuset_t dmask; uint32_t dest, vec, mode; + struct vlapic *vlapic2; + struct vm_exit *vmexit; dest = icrval >> 32; vec = icrval & APIC_VECTOR_MASK; @@ -452,11 +466,46 @@ lapic_process_icr(struct vlapic *vlapic, return (0); /* handled completely in the kernel */ } - /* - * XXX this assumes that the startup IPI always succeeds - */ - if (mode == APIC_DELMODE_STARTUP) - vm_activate_cpu(vlapic->vm, dest); + if (mode == APIC_DELMODE_INIT) { + if ((icrval & APIC_LEVEL_MASK) == APIC_LEVEL_DEASSERT) + return (0); + + if (vlapic->vcpuid == 0 && dest != 0 && dest < VM_MAXCPU) { + vlapic2 = vm_lapic(vlapic->vm, dest); + + /* move from INIT to waiting-for-SIPI state */ + if (vlapic2->boot_state == BS_INIT) { + vlapic2->boot_state = BS_SIPI; + } + + return (0); + } + } + + if (mode == APIC_DELMODE_STARTUP) { + if (vlapic->vcpuid == 0 && dest != 0 && dest < VM_MAXCPU) { + vlapic2 = vm_lapic(vlapic->vm, dest); + + /* + * Ignore SIPIs in any state other than wait-for-SIPI + */ + if (vlapic2->boot_state != BS_SIPI) + return (0); + + vmexit = vm_exitinfo(vlapic->vm, vlapic->vcpuid); + vmexit->exitcode = VM_EXITCODE_SPINUP_AP; + vmexit->u.spinup_ap.vcpu = dest; + vmexit->u.spinup_ap.rip = vec << PAGE_SHIFT; + + /* + * XXX this assumes that the startup IPI always succeeds + */ + vlapic2->boot_state = BS_RUNNING; + vm_activate_cpu(vlapic2->vm, dest); + + return (0); + } + } /* * This will cause a return to userland. Modified: projects/bhyve/usr.sbin/bhyve/Makefile ============================================================================== --- projects/bhyve/usr.sbin/bhyve/Makefile Tue Sep 25 01:33:23 2012 (r240911) +++ projects/bhyve/usr.sbin/bhyve/Makefile Tue Sep 25 02:33:25 2012 (r240912) @@ -8,6 +8,7 @@ SRCS= atpic.c consport.c dbgport.c elcr. SRCS+= instruction_emul.c ioapic.c mevent.c SRCS+= pci_emul.c pci_hostbridge.c pci_passthru.c pci_virtio_block.c SRCS+= pci_virtio_net.c pci_uart.c pit_8254.c post.c rtc.c uart.c xmsr.c +SRCS+= spinup_ap.c NO_MAN= Modified: projects/bhyve/usr.sbin/bhyve/fbsdrun.c ============================================================================== --- projects/bhyve/usr.sbin/bhyve/fbsdrun.c Tue Sep 25 01:33:23 2012 (r240911) +++ projects/bhyve/usr.sbin/bhyve/fbsdrun.c Tue Sep 25 02:33:25 2012 (r240912) @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include "xmsr.h" #include "instruction_emul.h" #include "ioapic.h" +#include "spinup_ap.h" #define DEFAULT_GUEST_HZ 100 #define DEFAULT_GUEST_TSLICE 200 @@ -346,6 +347,23 @@ vmexit_wrmsr(struct vmctx *ctx, struct v } static int +vmexit_spinup_ap(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu) +{ + int newcpu; + int retval = VMEXIT_CONTINUE; + + newcpu = spinup_ap(ctx, *pvcpu, + vme->u.spinup_ap.vcpu, vme->u.spinup_ap.rip); + + if (guest_vcpu_mux && *pvcpu != newcpu) { + retval = VMEXIT_SWITCH; + *pvcpu = newcpu; + } + + return (retval); +} + +static int vmexit_vmx(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) { @@ -471,7 +489,8 @@ static vmexit_handler_t handler[VM_EXITC [VM_EXITCODE_RDMSR] = vmexit_rdmsr, [VM_EXITCODE_WRMSR] = vmexit_wrmsr, [VM_EXITCODE_MTRAP] = vmexit_mtrap, - [VM_EXITCODE_PAGING] = vmexit_paging + [VM_EXITCODE_PAGING] = vmexit_paging, + [VM_EXITCODE_SPINUP_AP] = vmexit_spinup_ap, }; static void Added: projects/bhyve/usr.sbin/bhyve/spinup_ap.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/bhyve/usr.sbin/bhyve/spinup_ap.c Tue Sep 25 02:33:25 2012 (r240912) @@ -0,0 +1,180 @@ +/*- + * Copyright (c) 2012 NetApp, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include + +#include +#include +#include + +#include "fbsdrun.h" +#include "spinup_ap.h" + +/* + * Trampoline for hypervisor direct 64-bit jump. + * + * 0 - signature for guest->host verification + * 8 - kernel virtual address of trampoline + * 16 - instruction virtual address + * 24 - stack pointer virtual address + * 32 - CR3, physical address of kernel page table + * 40 - 24-byte area for null/code/data GDT entries + */ +#define MP_V64T_SIG 0xcafebabecafebabeULL +struct mp_v64tramp { + uint64_t mt_sig; + uint64_t mt_virt; + uint64_t mt_eip; + uint64_t mt_rsp; + uint64_t mt_cr3; + uint64_t mt_gdtr[3]; +}; + +static void +spinup_ap_realmode(struct vmctx *ctx, int newcpu, uint64_t *rip) +{ + int vector, error; + uint16_t cs; + uint64_t desc_base; + uint32_t desc_limit, desc_access; + + vector = *rip >> PAGE_SHIFT; + *rip = 0; + + /* + * Update the %cs and %rip of the guest so that it starts + * executing real mode code at at 'vector << 12'. + */ + error = vm_set_register(ctx, newcpu, VM_REG_GUEST_RIP, *rip); + assert(error == 0); + + error = vm_get_desc(ctx, newcpu, VM_REG_GUEST_CS, &desc_base, + &desc_limit, &desc_access); + assert(error == 0); + + desc_base = vector << PAGE_SHIFT; + error = vm_set_desc(ctx, newcpu, VM_REG_GUEST_CS, + desc_base, desc_limit, desc_access); + assert(error == 0); + + cs = (vector << PAGE_SHIFT) >> 4; + error = vm_set_register(ctx, newcpu, VM_REG_GUEST_CS, cs); + assert(error == 0); +} + +static void +spinup_ap_direct64(struct vmctx *ctx, int newcpu, uint64_t *rip) +{ + struct mp_v64tramp *mvt; + char *errstr; + int error; + uint64_t gdtbase; + + mvt = paddr_guest2host(*rip); + + assert(mvt->mt_sig == MP_V64T_SIG); + + /* + * Set up the 3-entry GDT using memory supplied in the + * guest's trampoline structure. + */ + vm_setup_freebsd_gdt(mvt->mt_gdtr); + +#define CHECK_ERROR(msg) \ + if (error != 0) { \ + errstr = msg; \ + goto err_exit; \ + } + + /* entry point */ + *rip = mvt->mt_eip; + + /* Get the guest virtual address of the GDT */ + gdtbase = mvt->mt_virt + __offsetof(struct mp_v64tramp, mt_gdtr); + + error = vm_setup_freebsd_registers(ctx, newcpu, mvt->mt_eip, + mvt->mt_cr3, gdtbase, mvt->mt_rsp); + CHECK_ERROR("vm_setup_freebsd_registers"); + + return; +err_exit: + printf("spinup_ap_direct64: machine state error: %s", errstr); + exit(1); +} + +int +spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip) +{ + int error; + + assert(newcpu != 0); + assert(newcpu < guest_ncpus); + + error = vcpu_reset(ctx, newcpu); + assert(error == 0); + + /* Set up capabilities */ + if (fbsdrun_vmexit_on_hlt()) { + error = vm_set_capability(ctx, newcpu, VM_CAP_HALT_EXIT, 1); + assert(error == 0); + } + + if (fbsdrun_vmexit_on_pause()) { + error = vm_set_capability(ctx, newcpu, VM_CAP_PAUSE_EXIT, 1); + assert(error == 0); + } + + /* + * There are 2 startup modes possible here: + * - if the CPU supports 'unrestricted guest' mode, the spinup can + * set up the processor state in power-on 16-bit mode, with the CS:IP + * init'd to the specified low-mem 4K page. + * - if the guest has requested a 64-bit trampoline in the low-mem 4K + * page by placing in the specified signature, set up the register + * state using register state in the signature. Note that this + * requires accessing guest physical memory to read the signature + * while 'unrestricted mode' does not. + */ + error = vm_set_capability(ctx, newcpu, VM_CAP_UNRESTRICTED_GUEST, 1); + if (error) { + spinup_ap_direct64(ctx, newcpu, &rip); + } else { + spinup_ap_realmode(ctx, newcpu, &rip); + } + + fbsdrun_addcpu(ctx, newcpu, rip); + + return (newcpu); +} Added: projects/bhyve/usr.sbin/bhyve/spinup_ap.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/bhyve/usr.sbin/bhyve/spinup_ap.h Tue Sep 25 02:33:25 2012 (r240912) @@ -0,0 +1,34 @@ +/*- + * Copyright (c) 2012 NetApp, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SPINUP_AP_H_ +#define _SPINUP_AP_H_ + +int spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip); + +#endif Modified: projects/bhyve/usr.sbin/bhyve/xmsr.c ============================================================================== --- projects/bhyve/usr.sbin/bhyve/xmsr.c Tue Sep 25 01:33:23 2012 (r240911) +++ projects/bhyve/usr.sbin/bhyve/xmsr.c Tue Sep 25 02:33:25 2012 (r240912) @@ -29,233 +29,20 @@ #include __FBSDID("$FreeBSD$"); -#include -#include +#include -#include -#include -#include #include #include -#include "fbsdrun.h" -#include "xmsr.h" - -/* - * Trampoline for hypervisor direct 64-bit jump. - * - * 0 - signature for guest->host verification - * 8 - kernel virtual address of trampoline - * 16 - instruction virtual address - * 24 - stack pointer virtual address - * 32 - CR3, physical address of kernel page table - * 40 - 24-byte area for null/code/data GDT entries - */ -#define MP_V64T_SIG 0xcafebabecafebabeULL -struct mp_v64tramp { - uint64_t mt_sig; - uint64_t mt_virt; - uint64_t mt_eip; - uint64_t mt_rsp; - uint64_t mt_cr3; - uint64_t mt_gdtr[3]; -}; - -/* - * CPU 0 is considered to be the BSP and is set to the RUNNING state. - * All other CPUs are set up in the INIT state. - */ -#define BSP 0 -enum cpu_bstate { - CPU_S_INIT, - CPU_S_SIPI, - CPU_S_RUNNING -} static cpu_b[VM_MAXCPU] = { [BSP] = CPU_S_RUNNING }; +#include +#include -static void spinup_ap(struct vmctx *, int, int, uint64_t *); -static void spinup_ap_direct64(struct vmctx *, int, uintptr_t, uint64_t *); +#include "xmsr.h" int emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val) { - int dest; - int mode; - int thiscpu; - int vec; - int error, retval; - uint64_t rip; - - retval = vcpu; - thiscpu = 1 << vcpu; - - /* - * The only MSR value handled is the x2apic CR register - */ - if (code != 0x830) { - printf("Unknown WRMSR code %x, val %lx, cpu %d\n", - code, val, vcpu); - exit(1); - } - - /* - * The value written to the MSR will generate an IPI to - * a set of CPUs. If this is a SIPI, create the initial - * state for the CPU and switch to it. Otherwise, inject - * an interrupt for the destination CPU(s), and request - * a switch to the next available one by returning -1 - */ - dest = val >> 32; - vec = val & APIC_VECTOR_MASK; - mode = val & APIC_DELMODE_MASK; - - switch (mode) { - case APIC_DELMODE_INIT: - /* - * Ignore legacy de-assert INITs in x2apic mode - */ - if ((val & APIC_LEVEL_MASK) == APIC_LEVEL_DEASSERT) { - break; - } - - assert(dest != 0); - assert(dest < guest_ncpus); - assert(cpu_b[dest] == CPU_S_INIT); - - /* - * Move CPU to wait-for-SIPI state - */ - error = vcpu_reset(ctx, dest); - assert(error == 0); - - cpu_b[dest] = CPU_S_SIPI; - break; - - case APIC_DELMODE_STARTUP: - assert(dest != 0); - assert(dest < guest_ncpus); - /* - * Ignore SIPIs in any state other than wait-for-SIPI - */ - if (cpu_b[dest] != CPU_S_SIPI) { - break; - } - - /* - * Bring up the AP and signal the main loop that it is - * available and to switch to it. - */ - spinup_ap(ctx, dest, vec, &rip); - cpu_b[dest] = CPU_S_RUNNING; - fbsdrun_addcpu(ctx, dest, rip); - retval = dest; - break; - - default: - printf("APIC delivery mode %lx not supported!\n", - val & APIC_DELMODE_MASK); - exit(1); - } - return (retval); -} - -/* - * There are 2 startup modes possible here: - * - if the CPU supports 'unrestricted guest' mode, the spinup can - * set up the processor state in power-on 16-bit mode, with the CS:IP - * init'd to the specified low-mem 4K page. - * - if the guest has requested a 64-bit trampoline in the low-mem 4K - * page by placing in the specified signature, set up the register - * state using register state in the signature. Note that this - * requires accessing guest physical memory to read the signature - * while 'unrestricted mode' does not. - */ -static void -spinup_ap(struct vmctx *ctx, int newcpu, int vector, uint64_t *rip) -{ - int error; - uint16_t cs; - uint64_t desc_base; - uint32_t desc_limit, desc_access; - - if (fbsdrun_vmexit_on_hlt()) { - error = vm_set_capability(ctx, newcpu, VM_CAP_HALT_EXIT, 1); - assert(error == 0); - } - - if (fbsdrun_vmexit_on_pause()) { - error = vm_set_capability(ctx, newcpu, VM_CAP_PAUSE_EXIT, 1); - assert(error == 0); - } - - error = vm_set_capability(ctx, newcpu, VM_CAP_UNRESTRICTED_GUEST, 1); - if (error) { - /* - * If the guest does not support real-mode execution then - * we will bring up the AP directly in 64-bit mode. - */ - spinup_ap_direct64(ctx, newcpu, vector << PAGE_SHIFT, rip); - } else { - /* - * Update the %cs and %rip of the guest so that it starts - * executing real mode code at at 'vector << 12'. - */ - *rip = 0; - error = vm_set_register(ctx, newcpu, VM_REG_GUEST_RIP, *rip); - assert(error == 0); - - error = vm_get_desc(ctx, newcpu, VM_REG_GUEST_CS, &desc_base, - &desc_limit, &desc_access); - assert(error == 0); - - desc_base = vector << PAGE_SHIFT; - error = vm_set_desc(ctx, newcpu, VM_REG_GUEST_CS, - desc_base, desc_limit, desc_access); - assert(error == 0); - - cs = (vector << PAGE_SHIFT) >> 4; - error = vm_set_register(ctx, newcpu, VM_REG_GUEST_CS, cs); - assert(error == 0); - } -} - -static void -spinup_ap_direct64(struct vmctx *ctx, int newcpu, uintptr_t gaddr, - uint64_t *rip) -{ - struct mp_v64tramp *mvt; - char *errstr; - int error; - uint64_t gdtbase; - - mvt = paddr_guest2host(gaddr); - - assert(mvt->mt_sig == MP_V64T_SIG); - - /* - * Set up the 3-entry GDT using memory supplied in the - * guest's trampoline structure. - */ - vm_setup_freebsd_gdt(mvt->mt_gdtr); - -#define CHECK_ERROR(msg) \ - if (error != 0) { \ - errstr = msg; \ - goto err_exit; \ - } - - /* entry point */ - *rip = mvt->mt_eip; - - /* Get the guest virtual address of the GDT */ - gdtbase = mvt->mt_virt + __offsetof(struct mp_v64tramp, mt_gdtr); - - error = vm_setup_freebsd_registers(ctx, newcpu, mvt->mt_eip, - mvt->mt_cr3, gdtbase, mvt->mt_rsp); - CHECK_ERROR("vm_setup_freebsd_registers"); - - return; -err_exit: - printf("spinup_ap_direct64: machine state error: %s", errstr); + printf("Unknown WRMSR code %x, val %lx, cpu %d\n", code, val, vcpu); exit(1); } From owner-svn-src-projects@FreeBSD.ORG Tue Sep 25 19:08:52 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C25AE106566C; Tue, 25 Sep 2012 19:08:52 +0000 (UTC) (envelope-from neel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id ABAB58FC0C; Tue, 25 Sep 2012 19:08:52 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8PJ8qeq080030; Tue, 25 Sep 2012 19:08:52 GMT (envelope-from neel@svn.freebsd.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8PJ8qhq080022; Tue, 25 Sep 2012 19:08:52 GMT (envelope-from neel@svn.freebsd.org) Message-Id: <201209251908.q8PJ8qhq080022@svn.freebsd.org> From: Neel Natu Date: Tue, 25 Sep 2012 19:08:52 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240922 - in projects/bhyve: lib/libvmmapi sys/amd64/include sys/amd64/vmm usr.sbin/vmmctl X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Sep 2012 19:08:53 -0000 Author: neel Date: Tue Sep 25 19:08:51 2012 New Revision: 240922 URL: http://svn.freebsd.org/changeset/base/240922 Log: Add ioctls to control the X2APIC capability exposed by the virtual machine to the guest. At the moment this simply sets the state in the 'vcpu' instance but there is no code that acts upon these settings. Modified: projects/bhyve/lib/libvmmapi/vmmapi.c projects/bhyve/lib/libvmmapi/vmmapi.h projects/bhyve/sys/amd64/include/vmm.h projects/bhyve/sys/amd64/include/vmm_dev.h projects/bhyve/sys/amd64/vmm/vmm.c projects/bhyve/sys/amd64/vmm/vmm_dev.c projects/bhyve/usr.sbin/vmmctl/vmmctl.c Modified: projects/bhyve/lib/libvmmapi/vmmapi.c ============================================================================== --- projects/bhyve/lib/libvmmapi/vmmapi.c Tue Sep 25 14:55:46 2012 (r240921) +++ projects/bhyve/lib/libvmmapi/vmmapi.c Tue Sep 25 19:08:51 2012 (r240922) @@ -537,6 +537,35 @@ vm_get_stat_desc(struct vmctx *ctx, int return (NULL); } +int +vm_get_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state *state) +{ + int error; + struct vm_x2apic x2apic; + + bzero(&x2apic, sizeof(x2apic)); + x2apic.cpuid = vcpu; + + error = ioctl(ctx->fd, VM_GET_X2APIC_STATE, &x2apic); + *state = x2apic.state; + return (error); +} + +int +vm_set_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state state) +{ + int error; + struct vm_x2apic x2apic; + + bzero(&x2apic, sizeof(x2apic)); + x2apic.cpuid = vcpu; + x2apic.state = state; + + error = ioctl(ctx->fd, VM_SET_X2APIC_STATE, &x2apic); + + return (error); +} + /* * From Intel Vol 3a: * Table 9-1. IA-32 Processor States Following Power-up, Reset or INIT Modified: projects/bhyve/lib/libvmmapi/vmmapi.h ============================================================================== --- projects/bhyve/lib/libvmmapi/vmmapi.h Tue Sep 25 14:55:46 2012 (r240921) +++ projects/bhyve/lib/libvmmapi/vmmapi.h Tue Sep 25 19:08:51 2012 (r240922) @@ -30,6 +30,7 @@ #define _VMMAPI_H_ struct vmctx; +enum x2apic_state; int vm_create(const char *name); struct vmctx *vm_open(const char *name); @@ -90,6 +91,9 @@ uint64_t *vm_get_stats(struct vmctx *ctx int *ret_entries); const char *vm_get_stat_desc(struct vmctx *ctx, int index); +int vm_get_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state *s); +int vm_set_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state s); + /* Reset vcpu register state */ int vcpu_reset(struct vmctx *ctx, int vcpu); Modified: projects/bhyve/sys/amd64/include/vmm.h ============================================================================== --- projects/bhyve/sys/amd64/include/vmm.h Tue Sep 25 14:55:46 2012 (r240921) +++ projects/bhyve/sys/amd64/include/vmm.h Tue Sep 25 19:08:51 2012 (r240922) @@ -40,6 +40,8 @@ struct vm_exit; struct vm_run; struct vlapic; +enum x2apic_state; + typedef int (*vmm_init_func_t)(void); typedef int (*vmm_cleanup_func_t)(void); typedef void * (*vmi_init_func_t)(struct vm *vm); /* instance specific apis */ @@ -109,6 +111,8 @@ uint64_t *vm_guest_msrs(struct vm *vm, i struct vlapic *vm_lapic(struct vm *vm, int cpu); int vm_get_capability(struct vm *vm, int vcpu, int type, int *val); int vm_set_capability(struct vm *vm, int vcpu, int type, int val); +int vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state); +int vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state); void vm_activate_cpu(struct vm *vm, int vcpu); cpuset_t vm_active_cpus(struct vm *vm); struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid); @@ -205,6 +209,13 @@ enum vm_cap_type { VM_CAP_MAX }; +enum x2apic_state { + X2APIC_ENABLED, + X2APIC_AVAILABLE, + X2APIC_DISABLED, + X2APIC_STATE_LAST +}; + /* * The 'access' field has the format specified in Table 21-2 of the Intel * Architecture Manual vol 3b. Modified: projects/bhyve/sys/amd64/include/vmm_dev.h ============================================================================== --- projects/bhyve/sys/amd64/include/vmm_dev.h Tue Sep 25 14:55:46 2012 (r240921) +++ projects/bhyve/sys/amd64/include/vmm_dev.h Tue Sep 25 19:08:51 2012 (r240922) @@ -136,6 +136,11 @@ struct vm_stat_desc { char desc[128]; /* out */ }; +struct vm_x2apic { + int cpuid; + enum x2apic_state state; +}; + enum { IOCNUM_RUN, IOCNUM_SET_PINNING, @@ -158,6 +163,8 @@ enum { IOCNUM_INJECT_NMI, IOCNUM_VM_STATS, IOCNUM_VM_STAT_DESC, + IOCNUM_SET_X2APIC_STATE, + IOCNUM_GET_X2APIC_STATE, }; #define VM_RUN \ @@ -202,4 +209,8 @@ enum { _IOWR('v', IOCNUM_VM_STATS, struct vm_stats) #define VM_STAT_DESC \ _IOWR('v', IOCNUM_VM_STAT_DESC, struct vm_stat_desc) +#define VM_SET_X2APIC_STATE \ + _IOW('v', IOCNUM_SET_X2APIC_STATE, struct vm_x2apic) +#define VM_GET_X2APIC_STATE \ + _IOWR('v', IOCNUM_GET_X2APIC_STATE, struct vm_x2apic) #endif Modified: projects/bhyve/sys/amd64/vmm/vmm.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm.c Tue Sep 25 14:55:46 2012 (r240921) +++ projects/bhyve/sys/amd64/vmm/vmm.c Tue Sep 25 19:08:51 2012 (r240922) @@ -73,6 +73,7 @@ struct vcpu { struct savefpu *guestfpu; /* guest fpu state */ void *stats; struct vm_exit exitinfo; + enum x2apic_state x2apic_state; }; #define VCPU_F_PINNED 0x0001 #define VCPU_F_RUNNING 0x0002 @@ -163,6 +164,7 @@ vcpu_init(struct vm *vm, uint32_t vcpu_i vcpu->guestfpu = fpu_save_area_alloc(); fpu_save_area_reset(vcpu->guestfpu); vcpu->stats = vmm_stat_alloc(); + vcpu->x2apic_state = X2APIC_ENABLED; } struct vm_exit * @@ -745,3 +747,28 @@ vcpu_stats(struct vm *vm, int vcpuid) return (vm->vcpu[vcpuid].stats); } + +int +vm_get_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state *state) +{ + if (vcpuid < 0 || vcpuid >= VM_MAXCPU) + return (EINVAL); + + *state = vm->vcpu[vcpuid].x2apic_state; + + return (0); +} + +int +vm_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state state) +{ + if (vcpuid < 0 || vcpuid >= VM_MAXCPU) + return (EINVAL); + + if (state < 0 || state >= X2APIC_STATE_LAST) + return (EINVAL); + + vm->vcpu[vcpuid].x2apic_state = state; + + return (0); +} Modified: projects/bhyve/sys/amd64/vmm/vmm_dev.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm_dev.c Tue Sep 25 14:55:46 2012 (r240921) +++ projects/bhyve/sys/amd64/vmm/vmm_dev.c Tue Sep 25 19:08:51 2012 (r240922) @@ -163,6 +163,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long c struct vm_nmi *vmnmi; struct vm_stats *vmstats; struct vm_stat_desc *statdesc; + struct vm_x2apic *x2apic; mtx_lock(&vmmdev_mtx); sc = vmmdev_lookup2(cdev); @@ -185,6 +186,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long c case VM_GET_CAPABILITY: case VM_SET_CAPABILITY: case VM_PPTDEV_MSI: + case VM_SET_X2APIC_STATE: /* * XXX fragile, handle with care * Assumes that the first field of the ioctl data is the vcpu. @@ -335,6 +337,16 @@ vmmdev_ioctl(struct cdev *cdev, u_long c vmcap->captype, vmcap->capval); break; + case VM_SET_X2APIC_STATE: + x2apic = (struct vm_x2apic *)data; + error = vm_set_x2apic_state(sc->vm, + x2apic->cpuid, x2apic->state); + break; + case VM_GET_X2APIC_STATE: + x2apic = (struct vm_x2apic *)data; + error = vm_get_x2apic_state(sc->vm, + x2apic->cpuid, &x2apic->state); + break; default: error = ENOTTY; break; Modified: projects/bhyve/usr.sbin/vmmctl/vmmctl.c ============================================================================== --- projects/bhyve/usr.sbin/vmmctl/vmmctl.c Tue Sep 25 14:55:46 2012 (r240921) +++ projects/bhyve/usr.sbin/vmmctl/vmmctl.c Tue Sep 25 19:08:51 2012 (r240922) @@ -185,6 +185,8 @@ usage(void) " [--get-vmcs-interruptibility]\n" " [--set-pinning=]\n" " [--get-pinning]\n" + " [--set-x2apic-state=]\n" + " [--get-x2apic-state]\n" " [--set-lowmem=]\n" " [--get-lowmem]\n" " [--set-highmem=]\n" @@ -217,6 +219,8 @@ static int set_desc_ldtr, get_desc_ldtr; static int set_cs, set_ds, set_es, set_fs, set_gs, set_ss, set_tr, set_ldtr; static int get_cs, get_ds, get_es, get_fs, get_gs, get_ss, get_tr, get_ldtr; static int set_pinning, get_pinning, pincpu; +static int set_x2apic_state, get_x2apic_state; +enum x2apic_state x2apic_state; static int run; /* @@ -371,6 +375,7 @@ enum { SET_TR, SET_LDTR, SET_PINNING, + SET_X2APIC_STATE, SET_VMCS_EXCEPTION_BITMAP, SET_VMCS_ENTRY_INTERRUPTION_INFO, SET_CAP, @@ -419,6 +424,7 @@ main(int argc, char *argv[]) { "set-tr", REQ_ARG, 0, SET_TR }, { "set-ldtr", REQ_ARG, 0, SET_LDTR }, { "set-pinning",REQ_ARG, 0, SET_PINNING }, + { "set-x2apic-state",REQ_ARG, 0, SET_X2APIC_STATE }, { "set-vmcs-exception-bitmap", REQ_ARG, 0, SET_VMCS_EXCEPTION_BITMAP }, { "set-vmcs-entry-interruption-info", @@ -547,6 +553,7 @@ main(int argc, char *argv[]) { "get-vmcs-interruptibility", NO_ARG, &get_vmcs_interruptibility, 1 }, { "get-pinning",NO_ARG, &get_pinning, 1 }, + { "get-x2apic-state",NO_ARG, &get_x2apic_state, 1 }, { "get-all", NO_ARG, &get_all, 1 }, { "run", NO_ARG, &run, 1 }, { "create", NO_ARG, &create, 1 }, @@ -656,6 +663,10 @@ main(int argc, char *argv[]) pincpu = strtol(optarg, NULL, 0); set_pinning = 1; break; + case SET_X2APIC_STATE: + x2apic_state = strtol(optarg, NULL, 0); + set_x2apic_state = 1; + break; case SET_VMCS_EXCEPTION_BITMAP: exception_bitmap = strtoul(optarg, NULL, 0); set_exception_bitmap = 1; @@ -804,6 +815,9 @@ main(int argc, char *argv[]) if (!error && set_pinning) error = vm_set_pinning(ctx, vcpu, pincpu); + if (!error && set_x2apic_state) + error = vm_set_x2apic_state(ctx, vcpu, x2apic_state); + if (!error && set_exception_bitmap) { error = vm_set_vmcs_field(ctx, vcpu, VMCS_EXCEPTION_BITMAP, exception_bitmap); @@ -1129,6 +1143,12 @@ main(int argc, char *argv[]) } } + if (!error && (get_x2apic_state || get_all)) { + error = vm_get_x2apic_state(ctx, vcpu, &x2apic_state); + if (error == 0) + printf("x2apic_state[%d]\t%d\n", vcpu, x2apic_state); + } + if (!error && (get_pinbased_ctls || get_all)) { error = vm_get_vmcs_field(ctx, vcpu, VMCS_PIN_BASED_CTLS, &ctl); if (error == 0) From owner-svn-src-projects@FreeBSD.ORG Tue Sep 25 20:27:43 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id CA52C106566B; Tue, 25 Sep 2012 20:27:42 +0000 (UTC) (envelope-from brooks@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B3BC58FC15; Tue, 25 Sep 2012 20:27:42 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8PKRggA090272; Tue, 25 Sep 2012 20:27:42 GMT (envelope-from brooks@svn.freebsd.org) Received: (from brooks@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8PKRgmM090268; Tue, 25 Sep 2012 20:27:42 GMT (envelope-from brooks@svn.freebsd.org) Message-Id: <201209252027.q8PKRgmM090268@svn.freebsd.org> From: Brooks Davis Date: Tue, 25 Sep 2012 20:27:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240925 - projects/mtree/contrib/install X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Sep 2012 20:27:43 -0000 Author: brooks Date: Tue Sep 25 20:27:42 2012 New Revision: 240925 URL: http://svn.freebsd.org/changeset/base/240925 Log: Virgin import of NetBSD's install(1). Added: projects/mtree/contrib/install/ projects/mtree/contrib/install/Makefile projects/mtree/contrib/install/install.1 projects/mtree/contrib/install/pathnames.h projects/mtree/contrib/install/xinstall.c Added: projects/mtree/contrib/install/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/mtree/contrib/install/Makefile Tue Sep 25 20:27:42 2012 (r240925) @@ -0,0 +1,23 @@ +# $NetBSD: Makefile,v 1.22 2011/08/17 14:00:30 christos Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +.include + +PROG= xinstall +SRCS= xinstall.c getid.c +MAN= install.1 + +.PATH: ${NETBSDSRCDIR}/usr.sbin/mtree +CPPFLAGS+= -I${NETBSDSRCDIR}/usr.sbin/mtree + +.if (${HOSTPROG:U} == "") +DPADD+= ${LIBUTIL} +LDADD+= -lutil +.endif + +COPTS.xinstall.c += -Wno-format-nonliteral + + +PROGNAME=install + +.include Added: projects/mtree/contrib/install/install.1 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/mtree/contrib/install/install.1 Tue Sep 25 20:27:42 2012 (r240925) @@ -0,0 +1,338 @@ +.\" $NetBSD: install.1,v 1.47 2012/04/08 22:00:40 wiz Exp $ +.\" +.\" Copyright (c) 1987, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)install.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd May 1, 2009 +.Dt INSTALL 1 +.Os +.Sh NAME +.Nm install +.Nd install binaries +.Sh SYNOPSIS +.Nm +.Op Fl bcprsU +.Op Fl a Ar command +.Op Fl B Ar suffix +.Op Fl D Ar destdir +.Op Fl f Ar flags +.Op Fl g Ar group +.Op Fl h Ar hash +.Op Fl l Ar linkflags +.Op Fl M Ar metalog +.Op Fl m Ar mode +.Op Fl N Ar dbdir +.Op Fl o Ar owner +.Op Fl S Ar stripflag +.Op Fl T Ar tags +.Ar file1 file2 +.Nm +.Op Fl bcprsU +.Op Fl a Ar command +.Op Fl B Ar suffix +.Op Fl D Ar destdir +.Op Fl f Ar flags +.Op Fl g Ar group +.Op Fl h Ar hash +.Op Fl l Ar linkflags +.Op Fl M Ar metalog +.Op Fl m Ar mode +.Op Fl N Ar dbdir +.Op Fl o Ar owner +.Op Fl S Ar stripflag +.Op Fl T Ar tags +.Ar file1 ...\& +.Ar fileN directory +.Nm +.Fl d +.Op Fl pU +.Op Fl a Ar command +.Op Fl D Ar destdir +.Op Fl g Ar group +.Op Fl M Ar metalog +.Op Fl m Ar mode +.Op Fl N Ar dbdir +.Op Fl o Ar owner +.Op Fl T Ar tags +.Ar directory ...\& +.Sh DESCRIPTION +The file(s) are copied +(or linked if the +.Fl l +option is specified) to the target file or directory. +If the destination is a directory, then the +.Ar file +is copied into +.Ar directory +with its original filename. +If the target file already exists, it is +either renamed to +.Ar file.old +if the +.Fl b +option is given +or overwritten +if permissions allow; an alternate backup suffix may be specified via the +.Fl B +option's argument. +.Pp +.Bl -tag -width XsXXstripflagsXX +.It Fl a Ar command +Run +.Ar command +on the target after installation and stripping +.Pq Fl s , +but before +ownership, permissions or timestamps are set and before renaming +.Pq Fl r +occurs. +.Ar command +is invoked via the +.Xr sh 1 +shell, allowing a single +.Fl a +argument be to specified to +.Nm +which the shell can then tokenize. +.It Fl B Ar suffix +Use +.Ar suffix +as the backup suffix if +.Fl b +is given. +If +.Ar suffix +contains a '%' sign, a numbered backup will be performed, and the +%-pattern will be expanded using +.Xr sprintf 3 , +given an integer counter as the backup number. +The counter used starts from 0, and the first available name resulting +from the expansion is used. +.It Fl b +Backup any existing files before overwriting them by renaming +them to +.Ar file.old . See +.Fl B +for specifying a different backup suffix. +.It Fl c +Copy the file. +This is the default behavior; the flag is maintained for backwards +compatibility only. +.It Fl D Ar destdir +Specify the +.Ev DESTDIR +(top of the file hierarchy) that the items are installed in to. +If +.Fl M Ar metalog +is in use, a leading string of +.Dq Ar destdir +will be removed from the file names logged to the +.Ar metalog . +This option does not affect where the actual files are installed. +.It Fl d +Create directories. +Missing parent directories are created as required. +.It Fl f Ar flags +Specify the target's file flags. +(See +.Xr chflags 1 +for a list of possible flags and their meanings.) +.It Fl g Ar group +Specify a group. +.It Fl h Ar hash +When copying, calculate the digest of the files with +.Ar hash +to store in the +.Fl M Ar metalog . +Supported digests: +.Bl -tag -width rmd160 -offset indent +.It Sy none +No hash. +This is the default. +.It Sy md5 +The MD5 cryptographic message digest. +.It Sy rmd160 +The RMD-160 cryptographic message digest. +.It Sy sha1 +The SHA-1 cryptographic message digest. +.It Sy sha256 +The 256-bits +.Tn SHA-2 +cryptographic message digest of the file. +.It Sy sha384 +The 384-bits +.Tn SHA-2 +cryptographic message digest of the file. +.It Sy sha512 +The 512-bits +.Tn SHA-2 +cryptographic message digest of the file. +.El +.It Fl l Ar linkflags +Instead of copying the file make a link to the source. +The type of the link is determined by the +.Ar linkflags +argument. +Valid +.Ar linkflags +are: +.Ar a +(absolute), +.Ar r +(relative), +.Ar h +(hard), +.Ar s +(symbolic), +.Ar m +(mixed). +Absolute and relative have effect only for symbolic links. +Mixed links +are hard links for files on the same filesystem, symbolic otherwise. +.It Fl M Ar metalog +Write the metadata associated with each item installed to +.Ar metalog +in an +.Xr mtree 8 +.Dq full path +specification line. +The metadata includes: the file name and file type, and depending upon +other options, the owner, group, file flags, modification time, and tags. +.It Fl m Ar mode +Specify an alternative mode. +The default mode is set to rwxr-xr-x (0755). +The specified mode may be either an octal or symbolic value; see +.Xr chmod 1 +for a description of possible mode values. +.It Fl N Ar dbdir +Use the user database text file +.Pa master.passwd +and group database text file +.Pa group +from +.Ar dbdir , +rather than using the results from the system's +.Xr getpwnam 3 +and +.Xr getgrnam 3 +(and related) library calls. +.It Fl o Ar owner +Specify an owner. +.It Fl p +Preserve the source files access and modification times. +.It Fl r +Install to a temporary file and then rename the file to its final destination +name. +This can be used for precious files, to avoid truncation of the original +when error conditions (filesystem full etc.) occur. +.It Fl S Ar stripflags +.Nm +passes +.Ar stripflags +as option arguments to +.Xr strip 1 . +When +.Fl S +is used, +.Xr strip 1 +is invoked via the +.Xr sh 1 +shell, allowing a single +.Fl S +argument be to specified to +.Nm +which the shell can then tokenize. +Normally, +.Nm +invokes +.Xr strip 1 +directly. +This flag implies +.Fl s . +.It Fl s +.Nm +exec's the command +.Xr strip 1 +to strip binaries so that install can be portable over a large +number of systems and binary types. +If the environment variable +.Ev STRIP +is set, it is used as the +.Xr strip 1 +program. +.It Fl T Ar tags +Specify the +.Xr mtree 8 +tags to write out for the file when using +.Fl M Ar metalog . +.It Fl U +Indicate that install is running unprivileged, and that it should not +try to change the owner, the group, or the file flags of the destination. +The information that would have been updated can be stored in a log +file with +.Fl M Ar metalog . +.El +.Pp +By default, +.Nm +preserves all file flags, with the exception of the ``nodump'' flag. +.Pp +The +.Nm +utility attempts to prevent copying a file onto itself. +.Pp +Installing +.Pa /dev/null +creates an empty file. +.Sh ENVIRONMENT +.Bl -tag -width Fl +.It Ev STRIP +The program used to strip installed binaries when the +.Fl s +option is used. +If unspecified, +.Pa /usr/bin/strip +is used. +.El +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr chflags 1 , +.Xr chgrp 1 , +.Xr chmod 1 , +.Xr cp 1 , +.Xr mv 1 , +.Xr strip 1 , +.Xr chown 8 , +.Xr mtree 8 +.Sh HISTORY +The +.Nm +utility appeared in +.Bx 4.2 . Added: projects/mtree/contrib/install/pathnames.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/mtree/contrib/install/pathnames.h Tue Sep 25 20:27:42 2012 (r240925) @@ -0,0 +1,36 @@ +/* $NetBSD: pathnames.h,v 1.6 2003/08/07 11:17:50 agc Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#ifndef _PATH_STRIP +#define _PATH_STRIP "/usr/bin/strip" +#endif Added: projects/mtree/contrib/install/xinstall.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/mtree/contrib/install/xinstall.c Tue Sep 25 20:27:42 2012 (r240925) @@ -0,0 +1,1273 @@ +/* $NetBSD: xinstall.c,v 1.115 2011/09/06 18:50:32 joerg Exp $ */ + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#else +#define HAVE_FUTIMES 1 +#define HAVE_STRUCT_STAT_ST_FLAGS 1 +#endif + +#include +#if defined(__COPYRIGHT) && !defined(lint) +__COPYRIGHT("@(#) Copyright (c) 1987, 1993\ + The Regents of the University of California. All rights reserved."); +#endif /* not lint */ + +#if defined(__RCSID) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)xinstall.c 8.1 (Berkeley) 7/21/93"; +#else +__RCSID("$NetBSD: xinstall.c,v 1.115 2011/09/06 18:50:32 joerg Exp $"); +#endif +#endif /* not lint */ + +#define __MKTEMP_OK__ /* All uses of mktemp have been checked */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "pathnames.h" +#include "mtree.h" + +#define STRIP_ARGS_MAX 32 +#define BACKUP_SUFFIX ".old" + +static int dobackup, dodir, dostrip, dolink, dopreserve, dorename, dounpriv; +static int haveopt_f, haveopt_g, haveopt_m, haveopt_o; +static int numberedbackup; +static int mode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; +static char pathbuf[MAXPATHLEN]; +static uid_t uid = -1; +static gid_t gid = -1; +static char *group, *owner, *fflags, *tags; +static FILE *metafp; +static char *metafile; +static u_long fileflags; +static char *stripArgs; +static char *afterinstallcmd; +static const char *suffix = BACKUP_SUFFIX; +static char *destdir; + +enum { + DIGEST_NONE = 0, + DIGEST_MD5, + DIGEST_RMD160, + DIGEST_SHA1, + DIGEST_SHA256, + DIGEST_SHA384, + DIGEST_SHA512, +} digesttype = DIGEST_NONE; + +static char *digest; + +#define LN_ABSOLUTE 0x01 +#define LN_RELATIVE 0x02 +#define LN_HARD 0x04 +#define LN_SYMBOLIC 0x08 +#define LN_MIXED 0x10 + +#define DIRECTORY 0x01 /* Tell install it's a directory. */ +#define SETFLAGS 0x02 /* Tell install to set flags. */ +#define HASUID 0x04 /* Tell install the uid was given */ +#define HASGID 0x08 /* Tell install the gid was given */ + +static void afterinstall(const char *, const char *, int); +static void backup(const char *); +static char *copy(int, char *, int, char *, off_t); +static int do_link(char *, char *); +static void do_symlink(char *, char *); +static void install(char *, char *, u_int); +static void install_dir(char *, u_int); +static void makelink(char *, char *); +static void metadata_log(const char *, const char *, struct timeval *, + const char *, const char *, off_t); +static int parseid(char *, id_t *); +static void strip(char *); +__dead static void usage(void); +static char *xbasename(char *); +static char *xdirname(char *); + +int +main(int argc, char *argv[]) +{ + struct stat from_sb, to_sb; + void *set; + u_int iflags; + int ch, no_target; + char *p, *to_name; + + setprogname(argv[0]); + + iflags = 0; + while ((ch = getopt(argc, argv, "a:cbB:dD:f:g:h:l:m:M:N:o:prsS:T:U")) + != -1) + switch((char)ch) { + case 'a': + afterinstallcmd = strdup(optarg); + if (afterinstallcmd == NULL) + errx(1, "%s", strerror(ENOMEM)); + break; + case 'B': + suffix = optarg; + numberedbackup = 0; + { + /* Check if given suffix really generates + different suffixes - catch e.g. ".%" */ + char suffix_expanded0[FILENAME_MAX], + suffix_expanded1[FILENAME_MAX]; + (void)snprintf(suffix_expanded0, FILENAME_MAX, + suffix, 0); + (void)snprintf(suffix_expanded1, FILENAME_MAX, + suffix, 1); + if (strcmp(suffix_expanded0, suffix_expanded1) + != 0) + numberedbackup = 1; + } + /* fall through; -B implies -b */ + /*FALLTHROUGH*/ + case 'b': + dobackup = 1; + break; + case 'c': + /* ignored; was "docopy" which is now the default. */ + break; + case 'd': + dodir = 1; + break; + case 'D': + destdir = optarg; + break; +#if ! HAVE_NBTOOL_CONFIG_H + case 'f': + haveopt_f = 1; + fflags = optarg; + break; +#endif + case 'g': + haveopt_g = 1; + group = optarg; + break; + case 'h': + digest = optarg; + break; + case 'l': + for (p = optarg; *p; p++) + switch (*p) { + case 's': + dolink &= ~(LN_HARD|LN_MIXED); + dolink |= LN_SYMBOLIC; + break; + case 'h': + dolink &= ~(LN_SYMBOLIC|LN_MIXED); + dolink |= LN_HARD; + break; + case 'm': + dolink &= ~(LN_SYMBOLIC|LN_HARD); + dolink |= LN_MIXED; + break; + case 'a': + dolink &= ~LN_RELATIVE; + dolink |= LN_ABSOLUTE; + break; + case 'r': + dolink &= ~LN_ABSOLUTE; + dolink |= LN_RELATIVE; + break; + default: + errx(1, "%c: invalid link type", *p); + /* NOTREACHED */ + } + break; + case 'm': + haveopt_m = 1; + if (!(set = setmode(optarg))) + err(1, "Cannot set file mode `%s'", optarg); + mode = getmode(set, 0); + free(set); + break; + case 'M': + metafile = optarg; + break; + case 'N': + if (! setup_getid(optarg)) + errx(1, + "Unable to use user and group databases in `%s'", + optarg); + break; + case 'o': + haveopt_o = 1; + owner = optarg; + break; + case 'p': + dopreserve = 1; + break; + case 'r': + dorename = 1; + break; + case 'S': + stripArgs = strdup(optarg); + if (stripArgs == NULL) + errx(1, "%s", strerror(ENOMEM)); + /* fall through; -S implies -s */ + /*FALLTHROUGH*/ + case 's': + dostrip = 1; + break; + case 'T': + tags = optarg; + break; + case 'U': + dounpriv = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + /* strip and link options make no sense when creating directories */ + if ((dostrip || dolink) && dodir) + usage(); + + /* strip and flags make no sense with links */ + if ((dostrip || fflags) && dolink) + usage(); + + /* must have at least two arguments, except when creating directories */ + if (argc < 2 && !dodir) + usage(); + + if (digest) { + if (0) { + } else if (strcmp(digest, "none") == 0) { + digesttype = DIGEST_NONE; + } else if (strcmp(digest, "md5") == 0) { + digesttype = DIGEST_MD5; + } else if (strcmp(digest, "rmd160") == 0) { + digesttype = DIGEST_RMD160; + } else if (strcmp(digest, "sha1") == 0) { + digesttype = DIGEST_SHA1; + } else if (strcmp(digest, "sha256") == 0) { + digesttype = DIGEST_SHA256; + } else if (strcmp(digest, "sha384") == 0) { + digesttype = DIGEST_SHA384; + } else if (strcmp(digest, "sha512") == 0) { + digesttype = DIGEST_SHA512; + } else { + warnx("unknown digest `%s'", digest); + usage(); + } + } + + /* get group and owner id's */ + if (group && !dounpriv) { + if (gid_from_group(group, &gid) == -1) { + id_t id; + if (!parseid(group, &id)) + errx(1, "unknown group %s", group); + gid = id; + } + iflags |= HASGID; + } + if (owner && !dounpriv) { + if (uid_from_user(owner, &uid) == -1) { + id_t id; + if (!parseid(owner, &id)) + errx(1, "unknown user %s", owner); + uid = id; + } + iflags |= HASUID; + } + +#if ! HAVE_NBTOOL_CONFIG_H + if (fflags && !dounpriv) { + if (string_to_flags(&fflags, &fileflags, NULL)) + errx(1, "%s: invalid flag", fflags); + /* restore fflags since string_to_flags() changed it */ + fflags = flags_to_string(fileflags, "-"); + iflags |= SETFLAGS; + } +#endif + + if (metafile) { + if ((metafp = fopen(metafile, "a")) == NULL) + warn("open %s", metafile); + } else + digesttype = DIGEST_NONE; + + if (dodir) { + for (; *argv != NULL; ++argv) + install_dir(*argv, iflags); + exit (0); + } + + no_target = stat(to_name = argv[argc - 1], &to_sb); + if (!no_target && S_ISDIR(to_sb.st_mode)) { + for (; *argv != to_name; ++argv) + install(*argv, to_name, iflags | DIRECTORY); + exit(0); + } + + /* can't do file1 file2 directory/file */ + if (argc != 2) { + errx(EXIT_FAILURE, "the last argument (%s) " + "must name an existing directory", argv[argc - 1]); + /* NOTREACHED */ + } + + if (!no_target) { + /* makelink() handles checks for links */ + if (!dolink) { + if (stat(*argv, &from_sb)) + err(1, "%s: stat", *argv); + if (!S_ISREG(to_sb.st_mode)) + errx(1, "%s: not a regular file", to_name); + if (to_sb.st_dev == from_sb.st_dev && + to_sb.st_ino == from_sb.st_ino) + errx(1, "%s and %s are the same file", *argv, + to_name); + } + /* + * Unlink now... avoid ETXTBSY errors later. Try and turn + * off the append/immutable bits -- if we fail, go ahead, + * it might work. + */ +#if ! HAVE_NBTOOL_CONFIG_H +#define NOCHANGEBITS (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND) + if (to_sb.st_flags & NOCHANGEBITS) + (void)chflags(to_name, + to_sb.st_flags & ~(NOCHANGEBITS)); +#endif + if (dobackup) + backup(to_name); + else if (!dorename) + (void)unlink(to_name); + } + install(*argv, to_name, iflags); + exit(0); +} + +/* + * parseid -- + * parse uid or gid from arg into id, returning non-zero if successful + */ +static int +parseid(char *name, id_t *id) +{ + char *ep; + + errno = 0; + *id = (id_t)strtoul(name, &ep, 10); + if (errno || *ep != '\0') + return (0); + return (1); +} + +/* + * do_link -- + * make a hard link, obeying dorename if set + * return -1 on failure + */ +static int +do_link(char *from_name, char *to_name) +{ + char tmpl[MAXPATHLEN]; + int ret; + + if (dorename) { + (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name); + /* This usage is safe. */ + if (mktemp(tmpl) == NULL) + err(1, "%s: mktemp", tmpl); + ret = link(from_name, tmpl); + if (ret == 0) { + ret = rename(tmpl, to_name); + /* If rename has posix semantics, then the temporary + * file may still exist when from_name and to_name point + * to the same file, so unlink it unconditionally. + */ + (void)unlink(tmpl); + } + return (ret); + } else + return (link(from_name, to_name)); +} + +/* + * do_symlink -- + * make a symbolic link, obeying dorename if set + * exit on failure + */ +static void +do_symlink(char *from_name, char *to_name) +{ + char tmpl[MAXPATHLEN]; + + if (dorename) { + (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name); + /* This usage is safe. */ + if (mktemp(tmpl) == NULL) + err(1, "%s: mktemp", tmpl); + + if (symlink(from_name, tmpl) == -1) + err(1, "symlink %s -> %s", from_name, tmpl); + if (rename(tmpl, to_name) == -1) { + /* remove temporary link before exiting */ + (void)unlink(tmpl); + err(1, "%s: rename", to_name); + } + } else { + if (symlink(from_name, to_name) == -1) + err(1, "symlink %s -> %s", from_name, to_name); + } +} + +/* + * makelink -- + * make a link from source to destination + */ +static void +makelink(char *from_name, char *to_name) +{ + char src[MAXPATHLEN], dst[MAXPATHLEN], lnk[MAXPATHLEN]; + struct stat to_sb; + + /* Try hard links first */ + if (dolink & (LN_HARD|LN_MIXED)) { + if (do_link(from_name, to_name) == -1) { + if ((dolink & LN_HARD) || errno != EXDEV) + err(1, "link %s -> %s", from_name, to_name); + } else { + if (stat(to_name, &to_sb)) + err(1, "%s: stat", to_name); + if (S_ISREG(to_sb.st_mode)) { + /* XXX: hard links to anything + * other than plain files are not + * metalogged + */ + int omode; + char *oowner, *ogroup, *offlags; + char *dres; + + /* XXX: use underlying perms, + * unless overridden on command line. + */ + omode = mode; + if (!haveopt_m) + mode = (to_sb.st_mode & 0777); + oowner = owner; + if (!haveopt_o) + owner = NULL; + ogroup = group; + if (!haveopt_g) + group = NULL; + offlags = fflags; + if (!haveopt_f) + fflags = NULL; + switch (digesttype) { + case DIGEST_MD5: + dres = MD5File(from_name, NULL); + break; + case DIGEST_RMD160: + dres = RMD160File(from_name, NULL); + break; + case DIGEST_SHA1: + dres = SHA1File(from_name, NULL); + break; + case DIGEST_SHA256: + dres = SHA256_File(from_name, NULL); + break; + case DIGEST_SHA384: + dres = SHA384_File(from_name, NULL); + break; + case DIGEST_SHA512: + dres = SHA512_File(from_name, NULL); + break; + default: + dres = NULL; + } + metadata_log(to_name, "file", NULL, NULL, + dres, to_sb.st_size); + free(dres); + mode = omode; + owner = oowner; + group = ogroup; + fflags = offlags; + } + return; + } + } + + /* Symbolic links */ + if (dolink & LN_ABSOLUTE) { + /* Convert source path to absolute */ + if (realpath(from_name, src) == NULL) + err(1, "%s: realpath", from_name); + do_symlink(src, to_name); + /* XXX: src may point outside of destdir */ + metadata_log(to_name, "link", NULL, src, NULL, 0); + return; + } + + if (dolink & LN_RELATIVE) { + char *cp, *d, *s; + + /* Resolve pathnames */ + if (realpath(from_name, src) == NULL) + err(1, "%s: realpath", from_name); + + /* + * The last component of to_name may be a symlink, + * so use realpath to resolve only the directory. + */ + cp = xdirname(to_name); + if (realpath(cp, dst) == NULL) + err(1, "%s: realpath", cp); + /* .. and add the last component */ + if (strcmp(dst, "/") != 0) { + if (strlcat(dst, "/", sizeof(dst)) > sizeof(dst)) + errx(1, "resolved pathname too long"); + } + cp = xbasename(to_name); + if (strlcat(dst, cp, sizeof(dst)) > sizeof(dst)) + errx(1, "resolved pathname too long"); + + /* trim common path components */ + for (s = src, d = dst; *s == *d; s++, d++) + continue; + while (*s != '/') + s--, d--; *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From owner-svn-src-projects@FreeBSD.ORG Tue Sep 25 21:25:48 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1DC22106566C; Tue, 25 Sep 2012 21:25:48 +0000 (UTC) (envelope-from brooks@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 0A2078FC12; Tue, 25 Sep 2012 21:25:48 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8PLPlZH098200; Tue, 25 Sep 2012 21:25:47 GMT (envelope-from brooks@svn.freebsd.org) Received: (from brooks@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8PLPl0j098197; Tue, 25 Sep 2012 21:25:47 GMT (envelope-from brooks@svn.freebsd.org) Message-Id: <201209252125.q8PLPl0j098197@svn.freebsd.org> From: Brooks Davis Date: Tue, 25 Sep 2012 21:25:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240933 - projects/mtree/usr.sbin/nmtree X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Sep 2012 21:25:48 -0000 Author: brooks Date: Tue Sep 25 21:25:47 2012 New Revision: 240933 URL: http://svn.freebsd.org/changeset/base/240933 Log: Shim more function names for install's benefit. Modified: projects/mtree/usr.sbin/nmtree/rmd160.h projects/mtree/usr.sbin/nmtree/sha1.h Modified: projects/mtree/usr.sbin/nmtree/rmd160.h ============================================================================== --- projects/mtree/usr.sbin/nmtree/rmd160.h Tue Sep 25 21:19:17 2012 (r240932) +++ projects/mtree/usr.sbin/nmtree/rmd160.h Tue Sep 25 21:25:47 2012 (r240933) @@ -2,4 +2,8 @@ #include +#define RMD160_CTX RIPEMD160_CTX +#define RMD160End RIPEMD160_End #define RMD160File RIPEMD160_File +#define RMD160Init RIPEMD160_Init +#define RMD160Update RIPEMD160_Update Modified: projects/mtree/usr.sbin/nmtree/sha1.h ============================================================================== --- projects/mtree/usr.sbin/nmtree/sha1.h Tue Sep 25 21:19:17 2012 (r240932) +++ projects/mtree/usr.sbin/nmtree/sha1.h Tue Sep 25 21:25:47 2012 (r240933) @@ -1,4 +1,8 @@ /* $FreeBSD$ */ #include + +#define SHA1End SHA1_End #define SHA1File SHA1_File +#define SHA1Init SHA1_Init +#define SHA1Update SHA1_Update From owner-svn-src-projects@FreeBSD.ORG Tue Sep 25 21:26:45 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 83FB2106564A; Tue, 25 Sep 2012 21:26:45 +0000 (UTC) (envelope-from brooks@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6FC8A8FC08; Tue, 25 Sep 2012 21:26:45 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8PLQjC4098372; Tue, 25 Sep 2012 21:26:45 GMT (envelope-from brooks@svn.freebsd.org) Received: (from brooks@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8PLQj9R098370; Tue, 25 Sep 2012 21:26:45 GMT (envelope-from brooks@svn.freebsd.org) Message-Id: <201209252126.q8PLQj9R098370@svn.freebsd.org> From: Brooks Davis Date: Tue, 25 Sep 2012 21:26:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240934 - projects/mtree/contrib/mtree X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Sep 2012 21:26:45 -0000 Author: brooks Date: Tue Sep 25 21:26:44 2012 New Revision: 240934 URL: http://svn.freebsd.org/changeset/base/240934 Log: Initialize the name variable to work around older gcc's weak uninitialized variable checking. Modified: projects/mtree/contrib/mtree/create.c Modified: projects/mtree/contrib/mtree/create.c ============================================================================== --- projects/mtree/contrib/mtree/create.c Tue Sep 25 21:25:47 2012 (r240933) +++ projects/mtree/contrib/mtree/create.c Tue Sep 25 21:26:44 2012 (r240934) @@ -167,7 +167,7 @@ statf(int indent, FTSENT *p) { u_int32_t len, val; int fd, offset; - const char *name; + const char *name = NULL; #if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2) char *digestbuf; #endif @@ -314,7 +314,7 @@ statd(FTS *t, FTSENT *parent, uid_t *pui uid_t suid; mode_t smode; u_long sflags = 0; - const char *name; + const char *name = NULL; gid_t savegid; uid_t saveuid; mode_t savemode; From owner-svn-src-projects@FreeBSD.ORG Tue Sep 25 21:27:37 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C8557106566B; Tue, 25 Sep 2012 21:27:37 +0000 (UTC) (envelope-from brooks@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id AA0958FC08; Tue, 25 Sep 2012 21:27:37 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8PLRb14098514; Tue, 25 Sep 2012 21:27:37 GMT (envelope-from brooks@svn.freebsd.org) Received: (from brooks@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8PLRbYR098512; Tue, 25 Sep 2012 21:27:37 GMT (envelope-from brooks@svn.freebsd.org) Message-Id: <201209252127.q8PLRbYR098512@svn.freebsd.org> From: Brooks Davis Date: Tue, 25 Sep 2012 21:27:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240935 - projects/mtree/contrib/install X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Sep 2012 21:27:38 -0000 Author: brooks Date: Tue Sep 25 21:27:37 2012 New Revision: 240935 URL: http://svn.freebsd.org/changeset/base/240935 Log: s/__dead/__dead2/ Add a NO_SHA384 option. Modified: projects/mtree/contrib/install/xinstall.c Modified: projects/mtree/contrib/install/xinstall.c ============================================================================== --- projects/mtree/contrib/install/xinstall.c Tue Sep 25 21:26:44 2012 (r240934) +++ projects/mtree/contrib/install/xinstall.c Tue Sep 25 21:27:37 2012 (r240935) @@ -105,7 +105,9 @@ enum { DIGEST_RMD160, DIGEST_SHA1, DIGEST_SHA256, +#ifndef NO_SHA384 DIGEST_SHA384, +#endif DIGEST_SHA512, } digesttype = DIGEST_NONE; @@ -134,7 +136,7 @@ static void metadata_log(const char *, c const char *, const char *, off_t); static int parseid(char *, id_t *); static void strip(char *); -__dead static void usage(void); +__dead2 static void usage(void); static char *xbasename(char *); static char *xdirname(char *); @@ -301,8 +303,10 @@ main(int argc, char *argv[]) digesttype = DIGEST_SHA1; } else if (strcmp(digest, "sha256") == 0) { digesttype = DIGEST_SHA256; +#ifndef NO_SHA384 } else if (strcmp(digest, "sha384") == 0) { digesttype = DIGEST_SHA384; +#endif } else if (strcmp(digest, "sha512") == 0) { digesttype = DIGEST_SHA512; } else { @@ -529,9 +533,11 @@ makelink(char *from_name, char *to_name) case DIGEST_SHA256: dres = SHA256_File(from_name, NULL); break; +#ifndef NO_SHA384 case DIGEST_SHA384: dres = SHA384_File(from_name, NULL); break; +#endif case DIGEST_SHA512: dres = SHA512_File(from_name, NULL); break; @@ -819,7 +825,9 @@ copy(int from_fd, char *from_name, int t RMD160_CTX ctxRMD160; SHA1_CTX ctxSHA1; SHA256_CTX ctxSHA256; +#ifndef NO_SHA384 SHA384_CTX ctxSHA384; +#endif SHA512_CTX ctxSHA512; switch (digesttype) { @@ -835,9 +843,11 @@ copy(int from_fd, char *from_name, int t case DIGEST_SHA256: SHA256_Init(&ctxSHA256); break; +#ifndef NO_SHA384 case DIGEST_SHA384: SHA384_Init(&ctxSHA384); break; +#endif case DIGEST_SHA512: SHA512_Init(&ctxSHA512); break; @@ -890,9 +900,11 @@ copy(int from_fd, char *from_name, int t case DIGEST_SHA256: SHA256_Update(&ctxSHA256, p, size); break; +#ifndef NO_SHA384 case DIGEST_SHA384: SHA384_Update(&ctxSHA384, p, size); break; +#endif case DIGEST_SHA512: SHA512_Update(&ctxSHA512, p, size); break; @@ -923,9 +935,11 @@ copy(int from_fd, char *from_name, int t case DIGEST_SHA256: SHA256_Update(&ctxSHA256, buf, nr); break; +#ifndef NO_SHA384 case DIGEST_SHA384: SHA384_Update(&ctxSHA384, buf, nr); break; +#endif case DIGEST_SHA512: SHA512_Update(&ctxSHA512, buf, nr); break; @@ -949,8 +963,10 @@ copy(int from_fd, char *from_name, int t return SHA1End(&ctxSHA1, NULL); case DIGEST_SHA256: return SHA256_End(&ctxSHA256, NULL); +#ifndef NO_SHA384 case DIGEST_SHA384: return SHA384_End(&ctxSHA384, NULL); +#endif case DIGEST_SHA512: return SHA512_End(&ctxSHA512, NULL); default: From owner-svn-src-projects@FreeBSD.ORG Tue Sep 25 21:33:38 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EFB0C106566B; Tue, 25 Sep 2012 21:33:37 +0000 (UTC) (envelope-from brooks@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 657038FC1E; Tue, 25 Sep 2012 21:33:37 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8PLXbCs099318; Tue, 25 Sep 2012 21:33:37 GMT (envelope-from brooks@svn.freebsd.org) Received: (from brooks@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8PLXbY8099315; Tue, 25 Sep 2012 21:33:37 GMT (envelope-from brooks@svn.freebsd.org) Message-Id: <201209252133.q8PLXbY8099315@svn.freebsd.org> From: Brooks Davis Date: Tue, 25 Sep 2012 21:33:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240937 - in projects/mtree/usr.bin: . install X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Sep 2012 21:33:38 -0000 Author: brooks Date: Tue Sep 25 21:33:36 2012 New Revision: 240937 URL: http://svn.freebsd.org/changeset/base/240937 Log: Hook NetBSD's install up to the build. For now it is installed as ninstall and without a manpage. Added: projects/mtree/usr.bin/install/ projects/mtree/usr.bin/install/Makefile Modified: projects/mtree/usr.bin/Makefile Modified: projects/mtree/usr.bin/Makefile ============================================================================== --- projects/mtree/usr.bin/Makefile Tue Sep 25 21:31:17 2012 (r240936) +++ projects/mtree/usr.bin/Makefile Tue Sep 25 21:33:36 2012 (r240937) @@ -64,6 +64,7 @@ SUBDIR= alias \ hexdump \ ${_iconv} \ id \ + install \ ipcrm \ ipcs \ join \ Added: projects/mtree/usr.bin/install/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/mtree/usr.bin/install/Makefile Tue Sep 25 21:33:36 2012 (r240937) @@ -0,0 +1,17 @@ +# $FreeBSD$ + +.include + +PROG= ninstall +SRCS= xinstall.c getid.c util.c +MAN= + +.PATH: ${.CURDIR}/../../contrib/install +.PATH: ${.CURDIR}/../../contrib/mtree +.PATH: ${.CURDIR}/../../usr.sbin/nmtree +CFLAGS+= -I${.CURDIR}/../../contrib/mtree \ + -I${.CURDIR}/../../usr.sbin/nmtree \ + -DNO_SHA384 +LDADD+= -lmd + +.include From owner-svn-src-projects@FreeBSD.ORG Tue Sep 25 22:31:35 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id E150C106566C; Tue, 25 Sep 2012 22:31:35 +0000 (UTC) (envelope-from neel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id CBAA38FC08; Tue, 25 Sep 2012 22:31:35 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8PMVZTn006919; Tue, 25 Sep 2012 22:31:35 GMT (envelope-from neel@svn.freebsd.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8PMVZwX006907; Tue, 25 Sep 2012 22:31:35 GMT (envelope-from neel@svn.freebsd.org) Message-Id: <201209252231.q8PMVZwX006907@svn.freebsd.org> From: Neel Natu Date: Tue, 25 Sep 2012 22:31:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240941 - in projects/bhyve/sys: amd64/vmm amd64/vmm/intel amd64/vmm/io modules/vmm X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Sep 2012 22:31:36 -0000 Author: neel Date: Tue Sep 25 22:31:35 2012 New Revision: 240941 URL: http://svn.freebsd.org/changeset/base/240941 Log: Add support for trapping MMIO writes to local apic registers and emulating them. The default behavior is still to present the local apic to the guest in the x2apic mode. Added: projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c (contents, props changed) projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.h (contents, props changed) Modified: projects/bhyve/sys/amd64/vmm/intel/vmcs.h projects/bhyve/sys/amd64/vmm/intel/vmx.c projects/bhyve/sys/amd64/vmm/io/vlapic.c projects/bhyve/sys/amd64/vmm/vmm.c projects/bhyve/sys/amd64/vmm/vmm_lapic.c projects/bhyve/sys/amd64/vmm/vmm_lapic.h projects/bhyve/sys/amd64/vmm/x86.c projects/bhyve/sys/amd64/vmm/x86.h projects/bhyve/sys/modules/vmm/Makefile Modified: projects/bhyve/sys/amd64/vmm/intel/vmcs.h ============================================================================== --- projects/bhyve/sys/amd64/vmm/intel/vmcs.h Tue Sep 25 22:15:59 2012 (r240940) +++ projects/bhyve/sys/amd64/vmm/intel/vmcs.h Tue Sep 25 22:31:35 2012 (r240941) @@ -66,6 +66,7 @@ uint64_t vmcs_read(uint32_t encoding); #define vmcs_exit_reason() (vmcs_read(VMCS_EXIT_REASON) & 0xffff) #define vmcs_exit_qualification() vmcs_read(VMCS_EXIT_QUALIFICATION) #define vmcs_guest_cr3() vmcs_read(VMCS_GUEST_CR3) +#define vmcs_gpa() vmcs_read(VMCS_GUEST_PHYSICAL_ADDRESS) #endif /* _KERNEL */ @@ -324,4 +325,13 @@ uint64_t vmcs_read(uint32_t encoding); */ #define EXIT_QUAL_NMI_WHILE_STI_BLOCKING 3 +/* + * Exit qualification for EPT violation + */ +#define EPT_VIOLATION_DATA_READ (1UL << 0) +#define EPT_VIOLATION_DATA_WRITE (1UL << 1) +#define EPT_VIOLATION_INST_FETCH (1UL << 2) +#define EPT_VIOLATION_GLA_VALID (1UL << 7) +#define EPT_VIOLATION_XLAT_VALID (1UL << 8) + #endif Modified: projects/bhyve/sys/amd64/vmm/intel/vmx.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/intel/vmx.c Tue Sep 25 22:15:59 2012 (r240940) +++ projects/bhyve/sys/amd64/vmm/intel/vmx.c Tue Sep 25 22:31:35 2012 (r240941) @@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include "vmm_lapic.h" #include "vmm_msr.h" @@ -60,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include "vmx.h" #include "x86.h" #include "vmx_controls.h" +#include "vmm_instruction_emul.h" #define CR4_VMXE (1UL << 13) @@ -771,21 +774,17 @@ vmx_vminit(struct vm *vm) } static int -vmx_handle_cpuid(int vcpu, struct vmxctx *vmxctx) +vmx_handle_cpuid(struct vm *vm, int vcpu, struct vmxctx *vmxctx) { int handled, func; func = vmxctx->guest_rax; - handled = x86_emulate_cpuid((uint32_t*)(&vmxctx->guest_rax), - (uint32_t*)(&vmxctx->guest_rbx), (uint32_t*)(&vmxctx->guest_rcx), - (uint32_t*)(&vmxctx->guest_rdx), vcpu); -#if 0 - printf("%s: func %x rax %lx rbx %lx rcx %lx rdx %lx handled %d\n", - __func__, func, vmxctx->guest_rax, vmxctx->guest_rbx, - vmxctx->guest_rcx, vmxctx->guest_rdx, handled); -#endif - + handled = x86_emulate_cpuid(vm, vcpu, + (uint32_t*)(&vmxctx->guest_rax), + (uint32_t*)(&vmxctx->guest_rbx), + (uint32_t*)(&vmxctx->guest_rcx), + (uint32_t*)(&vmxctx->guest_rdx)); return (handled); } @@ -1146,13 +1145,54 @@ vmx_emulate_cr_access(struct vmx *vmx, i } static int +vmx_lapic_fault(struct vm *vm, int cpu, + uint64_t gpa, uint64_t rip, uint64_t cr3, uint64_t ept_qual) +{ + int read, write, handled; + + /* + * For this to be a legitimate access to the local apic: + * - the GPA in the local apic page + * - the GPA must be aligned on a 16 byte boundary + */ + if (gpa < DEFAULT_APIC_BASE || gpa >= DEFAULT_APIC_BASE + PAGE_SIZE) + return (UNHANDLED); + + if ((gpa & 0xF) != 0) + return (UNHANDLED); + + /* EPT violation on an instruction fetch doesn't make sense here */ + if (ept_qual & EPT_VIOLATION_INST_FETCH) + return (UNHANDLED); + + /* EPT violation must be a read fault or a write fault but not both */ + read = ept_qual & EPT_VIOLATION_DATA_READ ? 1 : 0; + write = ept_qual & EPT_VIOLATION_DATA_WRITE ? 1 : 0; + if ((read ^ write) == 0) + return (UNHANDLED); + + /* + * The EPT violation must have been caused by accessing a guest-physical + * address that is a translation of a guest-linear address. + */ + if ((ept_qual & EPT_VIOLATION_GLA_VALID) == 0 || + (ept_qual & EPT_VIOLATION_XLAT_VALID) == 0) { + return (UNHANDLED); + } + + handled = lapic_mmio(vm, cpu, gpa - DEFAULT_APIC_BASE, read, rip, cr3); + + return (handled); +} + +static int vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) { int handled; struct vmcs *vmcs; struct vmxctx *vmxctx; uint32_t eax, ecx, edx; - uint64_t qual; + uint64_t qual, gpa, cr3; handled = 0; vmcs = &vmx->vmcs[vcpu]; @@ -1229,11 +1269,17 @@ vmx_exit_process(struct vmx *vmx, int vc vmexit->u.inout.eax = (uint32_t)(vmxctx->guest_rax); break; case EXIT_REASON_CPUID: - handled = vmx_handle_cpuid(vcpu, vmxctx); + handled = vmx_handle_cpuid(vmx->vm, vcpu, vmxctx); break; case EXIT_REASON_EPT_FAULT: - vmexit->exitcode = VM_EXITCODE_PAGING; - vmexit->u.paging.cr3 = vmcs_guest_cr3(); + gpa = vmcs_gpa(); + cr3 = vmcs_guest_cr3(); + handled = vmx_lapic_fault(vmx->vm, vcpu, + gpa, vmexit->rip, cr3, qual); + if (!handled) { + vmexit->exitcode = VM_EXITCODE_PAGING; + vmexit->u.paging.cr3 = cr3; + } break; default: break; Modified: projects/bhyve/sys/amd64/vmm/io/vlapic.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/io/vlapic.c Tue Sep 25 22:15:59 2012 (r240940) +++ projects/bhyve/sys/amd64/vmm/io/vlapic.c Tue Sep 25 22:31:35 2012 (r240941) @@ -87,7 +87,7 @@ static MALLOC_DEFINE(M_VLAPIC, "vlapic", #define VLAPIC_VERSION (16) #define VLAPIC_MAXLVT_ENTRIES (5) -#define x2apic(vlapic) ((vlapic)->msr_apicbase & APICBASE_X2APIC) +#define x2apic(vlapic) (((vlapic)->msr_apicbase & APICBASE_X2APIC) ? 1 : 0) enum boot_state { BS_INIT, @@ -433,7 +433,10 @@ lapic_process_icr(struct vlapic *vlapic, struct vlapic *vlapic2; struct vm_exit *vmexit; - dest = icrval >> 32; + if (x2apic(vlapic)) + dest = icrval >> 32; + else + dest = icrval >> (32 + 24); vec = icrval & APIC_VECTOR_MASK; mode = icrval & APIC_DELMODE_MASK; @@ -703,8 +706,18 @@ vlapic_op_mem_write(void* dev, uint64_t lapic->svr = data; break; case APIC_OFFSET_ICR_LOW: + if (!x2apic(vlapic)) { + data &= 0xffffffff; + data |= (uint64_t)lapic->icr_hi << 32; + } retval = lapic_process_icr(vlapic, data); break; + case APIC_OFFSET_ICR_HI: + if (!x2apic(vlapic)) { + retval = 0; + lapic->icr_hi = data; + } + break; case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT: reg = vlapic_get_lvt(vlapic, offset); if (!(lapic->svr & APIC_SVR_ENABLE)) { @@ -810,19 +823,26 @@ static struct io_region vlapic_mmio[VM_M struct vlapic * vlapic_init(struct vm *vm, int vcpuid) { + int err; + enum x2apic_state state; struct vlapic *vlapic; + err = vm_get_x2apic_state(vm, vcpuid, &state); + if (err) + panic("vlapic_set_apicbase: err %d fetching x2apic state", err); + vlapic = malloc(sizeof(struct vlapic), M_VLAPIC, M_WAITOK | M_ZERO); vlapic->vm = vm; vlapic->vcpuid = vcpuid; - vlapic->msr_apicbase = DEFAULT_APIC_BASE | - APICBASE_ENABLED | - APICBASE_X2APIC; + vlapic->msr_apicbase = DEFAULT_APIC_BASE | APICBASE_ENABLED; if (vcpuid == 0) vlapic->msr_apicbase |= APICBASE_BSP; + if (state == X2APIC_ENABLED) + vlapic->msr_apicbase |= APICBASE_X2APIC; + vlapic->ops = &vlapic_dev_ops; vlapic->mmio = vlapic_mmio + vcpuid; @@ -856,6 +876,15 @@ vlapic_get_apicbase(struct vlapic *vlapi void vlapic_set_apicbase(struct vlapic *vlapic, uint64_t val) { + int err; + enum x2apic_state state; + + err = vm_get_x2apic_state(vlapic->vm, vlapic->vcpuid, &state); + if (err) + panic("vlapic_set_apicbase: err %d fetching x2apic state", err); + + if (state == X2APIC_DISABLED) + val &= ~APICBASE_X2APIC; vlapic->msr_apicbase = val; } Modified: projects/bhyve/sys/amd64/vmm/vmm.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm.c Tue Sep 25 22:15:59 2012 (r240940) +++ projects/bhyve/sys/amd64/vmm/vmm.c Tue Sep 25 22:31:35 2012 (r240941) @@ -160,11 +160,11 @@ vcpu_init(struct vm *vm, uint32_t vcpu_i vcpu->hostcpu = -1; vcpu->vcpuid = vcpu_id; + vcpu->x2apic_state = X2APIC_ENABLED; vcpu->vlapic = vlapic_init(vm, vcpu_id); vcpu->guestfpu = fpu_save_area_alloc(); fpu_save_area_reset(vcpu->guestfpu); vcpu->stats = vmm_stat_alloc(); - vcpu->x2apic_state = X2APIC_ENABLED; } struct vm_exit * Added: projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c Tue Sep 25 22:31:35 2012 (r240941) @@ -0,0 +1,385 @@ +/*- + * Copyright (c) 2012 Sandvine, Inc. + * Copyright (c) 2012 NetApp, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "vmm_instruction_emul.h" + +#define GB (1024 * 1024 * 1024) + +static enum vm_reg_name gpr_map[16] = { + VM_REG_GUEST_RAX, + VM_REG_GUEST_RCX, + VM_REG_GUEST_RDX, + VM_REG_GUEST_RBX, + VM_REG_GUEST_RSP, + VM_REG_GUEST_RBP, + VM_REG_GUEST_RSI, + VM_REG_GUEST_RDI, + VM_REG_GUEST_R8, + VM_REG_GUEST_R9, + VM_REG_GUEST_R10, + VM_REG_GUEST_R11, + VM_REG_GUEST_R12, + VM_REG_GUEST_R13, + VM_REG_GUEST_R14, + VM_REG_GUEST_R15 +}; + +static void +vie_init(struct vie *vie) +{ + + bzero(vie, sizeof(struct vie)); + + vie->op_size = VIE_OP_SIZE_32BIT; + + vie->base_register = VM_REG_LAST; + vie->index_register = VM_REG_LAST; + vie->operand_register = VM_REG_LAST; +} + +static int +gla2gpa(struct vm *vm, uint64_t gla, uint64_t ptpphys, + uint64_t *gpa, uint64_t *gpaend) +{ + vm_paddr_t hpa; + int nlevels, ptpshift, ptpindex; + uint64_t *ptpbase, pte, pgsize; + + /* + * XXX assumes 64-bit guest with 4 page walk levels + */ + nlevels = 4; + while (--nlevels >= 0) { + /* Zero out the lower 12 bits and the upper 12 bits */ + ptpphys >>= 12; ptpphys <<= 24; ptpphys >>= 12; + + hpa = vm_gpa2hpa(vm, ptpphys, PAGE_SIZE); + if (hpa == -1) + goto error; + + ptpbase = (uint64_t *)PHYS_TO_DMAP(hpa); + + ptpshift = PAGE_SHIFT + nlevels * 9; + ptpindex = (gla >> ptpshift) & 0x1FF; + pgsize = 1UL << ptpshift; + + pte = ptpbase[ptpindex]; + + if ((pte & PG_V) == 0) + goto error; + + if (pte & PG_PS) { + if (pgsize > 1 * GB) + goto error; + else + break; + } + + ptpphys = pte; + } + + /* Zero out the lower 'ptpshift' bits and the upper 12 bits */ + pte >>= ptpshift; pte <<= (ptpshift + 12); pte >>= 12; + *gpa = pte | (gla & (pgsize - 1)); + *gpaend = pte + pgsize; + return (0); + +error: + return (-1); +} + +void +vmm_fetch_instruction(struct vm *vm, uint64_t rip, uint64_t cr3, + struct vie *vie) +{ + int n, err; + uint64_t hpa, gpa, gpaend; + + /* + * XXX cache previously fetched instructions using 'rip' as the tag + */ + + vie_init(vie); + + /* + * Copy up to 15 bytes of the instruction stream into 'vie' + */ + while (vie->num_valid < VIE_INST_SIZE) { + err = gla2gpa(vm, rip, cr3, &gpa, &gpaend); + if (err) + break; + + n = min(VIE_INST_SIZE - vie->num_valid, gpaend - gpa); + + hpa = vm_gpa2hpa(vm, gpa, n); + if (hpa == -1) + break; + + bcopy((void *)PHYS_TO_DMAP(hpa), &vie->inst[vie->num_valid], n); + + rip += n; + vie->num_valid += n; + } +} + +static int +vie_peek(struct vie *vie, uint8_t *x) +{ + if (vie->num_processed < vie->num_valid) { + *x = vie->inst[vie->num_processed]; + return (0); + } else + return (-1); +} + +static void +vie_advance(struct vie *vie) +{ + if (vie->num_processed >= vie->num_valid) + panic("vie_advance: %d/%d", vie->num_processed, vie->num_valid); + + vie->num_processed++; +} + +static int +decode_rex(struct vie *vie) +{ + uint8_t x; + + if (vie_peek(vie, &x)) + return (-1); + + if (x >= 0x40 && x <= 0x4F) { + vie->rex_w = x & 0x8 ? 1 : 0; + vie->rex_r = x & 0x4 ? 1 : 0; + vie->rex_x = x & 0x2 ? 1 : 0; + vie->rex_b = x & 0x1 ? 1 : 0; + + vie_advance(vie); + } + + return (0); +} + +static int +decode_opcode(struct vie *vie) +{ + uint8_t x; + + static const uint8_t flags[256] = { + [0x89] = VIE_F_HAS_MODRM | VIE_F_FROM_REG | VIE_F_TO_RM, + [0x8B] = VIE_F_HAS_MODRM | VIE_F_FROM_RM | VIE_F_TO_REG, + [0xC7] = VIE_F_HAS_MODRM | VIE_F_FROM_IMM | VIE_F_TO_RM, + }; + + if (vie_peek(vie, &x)) + return (-1); + + vie->opcode_byte = x; + vie->opcode_flags = flags[x]; + + vie_advance(vie); + + if (vie->opcode_flags == 0) + return (-1); + else + return (0); +} + +/* + * XXX assuming 32-bit or 64-bit guest + */ +static int +decode_modrm(struct vie *vie) +{ + uint8_t x; + + if ((vie->opcode_flags & VIE_F_HAS_MODRM) == 0) + return (0); + + if (vie_peek(vie, &x)) + return (-1); + + vie->mod = (x >> 6) & 0x3; + vie->rm = (x >> 0) & 0x7; + vie->reg = (x >> 3) & 0x7; + + if ((vie->mod == VIE_MOD_INDIRECT && vie->rm == VIE_RM_DISP32) || + (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB)) { + /* + * Table 2-5: Special Cases of REX Encodings + * + * mod=0, r/m=5 is used in the compatibility mode to + * indicate a disp32 without a base register. + * + * mod!=3, r/m=4 is used in the compatibility mode to + * indicate that the SIB byte is present. + * + * The 'b' bit in the REX prefix is don't care in + * this case. + */ + } else { + vie->rm |= (vie->rex_b << 3); + } + + vie->reg |= (vie->rex_r << 3); + + /* SIB addressing not supported yet */ + if (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB) + return (-1); + + vie->base_register = gpr_map[vie->rm]; + + if (vie->opcode_flags & (VIE_F_FROM_REG | VIE_F_TO_REG)) + vie->operand_register = gpr_map[vie->reg]; + + switch (vie->mod) { + case VIE_MOD_INDIRECT_DISP8: + vie->disp_bytes = 1; + break; + case VIE_MOD_INDIRECT_DISP32: + vie->disp_bytes = 4; + break; + case VIE_MOD_INDIRECT: + if (vie->rm == VIE_RM_DISP32) { + vie->disp_bytes = 4; + vie->base_register = VM_REG_LAST; /* no base */ + } + break; + } + + /* calculate the operand size */ + if (vie->rex_w) + vie->op_size = VIE_OP_SIZE_64BIT; + + if (vie->opcode_flags & VIE_F_FROM_IMM) + vie->imm_bytes = 4; + + vie_advance(vie); + + return (0); +} + +static int +decode_displacement(struct vie *vie) +{ + int n, i; + uint8_t x; + + union { + char buf[4]; + int8_t signed8; + int32_t signed32; + } u; + + if ((n = vie->disp_bytes) == 0) + return (0); + + if (n != 1 && n != 4) + panic("decode_displacement: invalid disp_bytes %d", n); + + for (i = 0; i < n; i++) { + if (vie_peek(vie, &x)) + return (-1); + + u.buf[i] = x; + vie_advance(vie); + } + + if (n == 1) + vie->displacement = u.signed8; /* sign-extended */ + else + vie->displacement = u.signed32; /* sign-extended */ + + return (0); +} + +static int +decode_immediate(struct vie *vie) +{ + int i, n; + uint8_t x; + union { + char buf[4]; + int32_t signed32; + } u; + + if ((n = vie->imm_bytes) == 0) + return (0); + + if (n != 4) + panic("decode_immediate: invalid imm_bytes %d", n); + + for (i = 0; i < n; i++) { + if (vie_peek(vie, &x)) + return (-1); + + u.buf[i] = x; + vie_advance(vie); + } + + vie->immediate = u.signed32; /* sign-extended */ + + return (0); +} + +int +vmm_decode_instruction(struct vie *vie) +{ + if (decode_rex(vie)) + return (-1); + + if (decode_opcode(vie)) + return (-1); + + if (decode_modrm(vie)) + return (-1); + + if (decode_displacement(vie)) + return (-1); + + if (decode_immediate(vie)) + return (-1); + + return (0); +} Added: projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.h Tue Sep 25 22:31:35 2012 (r240941) @@ -0,0 +1,91 @@ +/*- + * Copyright (c) 2012 NetApp, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _VMM_INSTRUCTION_EMUL_H_ +#define _VMM_INSTRUCTION_EMUL_H_ + +enum vie_op_size { + VIE_OP_SIZE_32BIT, /* default */ + VIE_OP_SIZE_64BIT, + VIE_OP_SIZE_8BIT +}; + +#define VIE_INST_SIZE 15 +struct vie { + uint8_t inst[VIE_INST_SIZE]; + + uint8_t rex_w:1, + rex_r:1, + rex_x:1, + rex_b:1; + + uint8_t mod:2, + reg:4, + rm:4; + + + uint8_t opcode_byte; + uint16_t opcode_flags; + uint8_t disp_bytes; + uint8_t imm_bytes; + + int num_valid; + int num_processed; + + enum vm_reg_name base_register; + enum vm_reg_name index_register; + enum vm_reg_name operand_register; + + int op_size; + int64_t displacement; + int64_t immediate; +}; + +#define VIE_F_HAS_MODRM (1 << 0) +#define VIE_F_FROM_RM (1 << 1) +#define VIE_F_FROM_REG (1 << 2) +#define VIE_F_TO_RM (1 << 3) +#define VIE_F_TO_REG (1 << 4) +#define VIE_F_FROM_IMM (1 << 5) + +#define VIE_MOD_INDIRECT 0 +#define VIE_MOD_INDIRECT_DISP8 1 +#define VIE_MOD_INDIRECT_DISP32 2 +#define VIE_MOD_DIRECT 3 + +#define VIE_RM_SIB 4 +#define VIE_RM_DISP32 5 + +struct vm; + +void vmm_fetch_instruction(struct vm *vm, uint64_t rip, uint64_t cr3, + struct vie *vie); + +int vmm_decode_instruction(struct vie *vie); + +#endif Modified: projects/bhyve/sys/amd64/vmm/vmm_lapic.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm_lapic.c Tue Sep 25 22:15:59 2012 (r240940) +++ projects/bhyve/sys/amd64/vmm/vmm_lapic.c Tue Sep 25 22:31:35 2012 (r240941) @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include "vmm_ipi.h" #include "vmm_lapic.h" #include "vlapic.h" +#include "vmm_instruction_emul.h" static int lapic_write(struct vlapic *vlapic, u_int offset, uint64_t val) @@ -174,3 +175,73 @@ lapic_wrmsr(struct vm *vm, int cpu, u_in return (handled); } + +int +lapic_mmio(struct vm *vm, int cpu, u_int offset, int read, + uint64_t rip, uint64_t cr3) +{ + int handled, error; + uint64_t val; + struct vie vie; + struct vlapic *vlapic; + + const int UNHANDLED = 0; + + vlapic = vm_lapic(vm, cpu); + + vmm_fetch_instruction(vm, rip, cr3, &vie); + + if (vmm_decode_instruction(&vie) != 0) + return (UNHANDLED); + + /* Only 32-bit accesses to local apic */ + if (vie.op_size != VIE_OP_SIZE_32BIT) + return (UNHANDLED); + + /* + * XXX + * The operand register in which we store the result of the + * read must be a GPR that we can modify even if the vcpu + * is "running". All the GPRs qualify except for %rsp. + * + * This is a limitation of the vm_set_register() API + * and can be fixed if necessary. + */ + if (vie.operand_register == VM_REG_GUEST_RSP) + return (UNHANDLED); + + if (read) { + if ((vie.opcode_flags & VIE_F_TO_REG) == 0) + return (UNHANDLED); + + if (vie.operand_register >= VM_REG_LAST) + return (UNHANDLED); + + handled = lapic_read(vlapic, offset, &val); + if (handled) { + error = vm_set_register(vm, cpu, vie.operand_register, + val); + if (error) + panic("lapic_mmio: error %d setting gpr %d", + error, vie.operand_register); + } + } else { + if ((vie.opcode_flags & VIE_F_FROM_REG) && + (vie.operand_register < VM_REG_LAST)) { + error = vm_get_register(vm, cpu, vie.operand_register, + &val); + if (error) { + panic("lapic_mmio: error %d getting gpr %d", + error, vie.operand_register); + } + } else if (vie.opcode_flags & VIE_F_FROM_IMM) { + val = vie.immediate; + } else { + return (UNHANDLED); + } + + handled = lapic_write(vlapic, offset, val); + } + + return (handled); +} Modified: projects/bhyve/sys/amd64/vmm/vmm_lapic.h ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm_lapic.h Tue Sep 25 22:15:59 2012 (r240940) +++ projects/bhyve/sys/amd64/vmm/vmm_lapic.h Tue Sep 25 22:31:35 2012 (r240941) @@ -35,6 +35,9 @@ boolean_t lapic_msr(u_int num); int lapic_rdmsr(struct vm *vm, int cpu, u_int msr, uint64_t *rval); int lapic_wrmsr(struct vm *vm, int cpu, u_int msr, uint64_t wval); +int lapic_mmio(struct vm *vm, int cpu, u_int offset, int read, + uint64_t rip, uint64_t cr3); + void lapic_timer_tick(struct vm *vm, int cpu); /* Modified: projects/bhyve/sys/amd64/vmm/x86.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/x86.c Tue Sep 25 22:15:59 2012 (r240940) +++ projects/bhyve/sys/amd64/vmm/x86.c Tue Sep 25 22:31:35 2012 (r240941) @@ -29,13 +29,17 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include +#include #include #include #include +#include + #include "x86.h" #define CPUID_VM_HIGH 0x40000000 @@ -43,10 +47,12 @@ __FBSDID("$FreeBSD$"); static const char bhyve_id[12] = "BHyVE BHyVE "; int -x86_emulate_cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx, - uint32_t vcpu_id) +x86_emulate_cpuid(struct vm *vm, int vcpu_id, + uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { + int error; unsigned int func, regs[4]; + enum x2apic_state x2apic_state; func = *eax; @@ -91,6 +97,12 @@ x86_emulate_cpuid(uint32_t *eax, uint32_ case CPUID_0000_0001: do_cpuid(1, regs); + error = vm_get_x2apic_state(vm, vcpu_id, &x2apic_state); + if (error) { + panic("x86_emulate_cpuid: error %d " + "fetching x2apic state", error); + } + /* * Override the APIC ID only in ebx */ @@ -102,7 +114,11 @@ x86_emulate_cpuid(uint32_t *eax, uint32_ * Advertise x2APIC capability and Hypervisor guest. */ regs[2] &= ~(CPUID2_VMX | CPUID2_EST | CPUID2_TM2); - regs[2] |= CPUID2_X2APIC | CPUID2_HV; + + regs[2] |= CPUID2_HV; + + if (x2apic_state != X2APIC_DISABLED) + regs[2] |= CPUID2_X2APIC; /* * Hide xsave/osxsave/avx until the FPU save/restore Modified: projects/bhyve/sys/amd64/vmm/x86.h ============================================================================== --- projects/bhyve/sys/amd64/vmm/x86.h Tue Sep 25 22:15:59 2012 (r240940) +++ projects/bhyve/sys/amd64/vmm/x86.h Tue Sep 25 22:31:35 2012 (r240941) @@ -57,7 +57,7 @@ */ #define CPUID_0000_0001_FEAT0_VMX (1<<5) -int x86_emulate_cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, - uint32_t *edx, uint32_t vcpu_id); +int x86_emulate_cpuid(struct vm *vm, int vcpu_id, uint32_t *eax, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx); #endif Modified: projects/bhyve/sys/modules/vmm/Makefile ============================================================================== --- projects/bhyve/sys/modules/vmm/Makefile Tue Sep 25 22:15:59 2012 (r240940) +++ projects/bhyve/sys/modules/vmm/Makefile Tue Sep 25 22:31:35 2012 (r240941) @@ -13,6 +13,7 @@ CFLAGS+= -I${.CURDIR}/../../amd64/vmm/in .PATH: ${.CURDIR}/../../amd64/vmm SRCS+= vmm.c \ vmm_dev.c \ + vmm_instruction_emul.c \ vmm_ipi.c \ vmm_lapic.c \ vmm_mem.c \ From owner-svn-src-projects@FreeBSD.ORG Wed Sep 26 00:06:18 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 494BA1065676; Wed, 26 Sep 2012 00:06:18 +0000 (UTC) (envelope-from neel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 341D58FC14; Wed, 26 Sep 2012 00:06:18 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8Q06I1K018388; Wed, 26 Sep 2012 00:06:18 GMT (envelope-from neel@svn.freebsd.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8Q06HVn018380; Wed, 26 Sep 2012 00:06:17 GMT (envelope-from neel@svn.freebsd.org) Message-Id: <201209260006.q8Q06HVn018380@svn.freebsd.org> From: Neel Natu Date: Wed, 26 Sep 2012 00:06:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240943 - in projects/bhyve: sys/amd64/vmm sys/amd64/vmm/io usr.sbin/bhyve X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 26 Sep 2012 00:06:18 -0000 Author: neel Date: Wed Sep 26 00:06:17 2012 New Revision: 240943 URL: http://svn.freebsd.org/changeset/base/240943 Log: Add an option "-a" to present the local apic in the XAPIC mode instead of the default X2APIC mode to the guest. Modified: projects/bhyve/sys/amd64/vmm/io/vlapic.c projects/bhyve/sys/amd64/vmm/io/vlapic.h projects/bhyve/sys/amd64/vmm/vmm.c projects/bhyve/usr.sbin/bhyve/fbsdrun.c projects/bhyve/usr.sbin/bhyve/fbsdrun.h projects/bhyve/usr.sbin/bhyve/spinup_ap.c Modified: projects/bhyve/sys/amd64/vmm/io/vlapic.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/io/vlapic.c Tue Sep 25 23:41:45 2012 (r240942) +++ projects/bhyve/sys/amd64/vmm/io/vlapic.c Wed Sep 26 00:06:17 2012 (r240943) @@ -823,14 +823,8 @@ static struct io_region vlapic_mmio[VM_M struct vlapic * vlapic_init(struct vm *vm, int vcpuid) { - int err; - enum x2apic_state state; struct vlapic *vlapic; - err = vm_get_x2apic_state(vm, vcpuid, &state); - if (err) - panic("vlapic_set_apicbase: err %d fetching x2apic state", err); - vlapic = malloc(sizeof(struct vlapic), M_VLAPIC, M_WAITOK | M_ZERO); vlapic->vm = vm; vlapic->vcpuid = vcpuid; @@ -840,9 +834,6 @@ vlapic_init(struct vm *vm, int vcpuid) if (vcpuid == 0) vlapic->msr_apicbase |= APICBASE_BSP; - if (state == X2APIC_ENABLED) - vlapic->msr_apicbase |= APICBASE_X2APIC; - vlapic->ops = &vlapic_dev_ops; vlapic->mmio = vlapic_mmio + vcpuid; @@ -888,3 +879,16 @@ vlapic_set_apicbase(struct vlapic *vlapi vlapic->msr_apicbase = val; } + +void +vlapic_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state state) +{ + struct vlapic *vlapic; + + vlapic = vm_lapic(vm, vcpuid); + + if (state == X2APIC_ENABLED) + vlapic->msr_apicbase |= APICBASE_X2APIC; + else + vlapic->msr_apicbase &= ~APICBASE_X2APIC; +} Modified: projects/bhyve/sys/amd64/vmm/io/vlapic.h ============================================================================== --- projects/bhyve/sys/amd64/vmm/io/vlapic.h Tue Sep 25 23:41:45 2012 (r240942) +++ projects/bhyve/sys/amd64/vmm/io/vlapic.h Wed Sep 26 00:06:17 2012 (r240943) @@ -88,6 +88,8 @@ struct vm; */ #define ISRVEC_STK_SIZE (16 + 1) +enum x2apic_state; + struct vlapic *vlapic_init(struct vm *vm, int vcpuid); void vlapic_cleanup(struct vlapic *vlapic); @@ -104,5 +106,6 @@ void vlapic_timer_tick(struct vlapic *vl uint64_t vlapic_get_apicbase(struct vlapic *vlapic); void vlapic_set_apicbase(struct vlapic *vlapic, uint64_t val); +void vlapic_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state s); #endif /* _VLAPIC_H_ */ Modified: projects/bhyve/sys/amd64/vmm/vmm.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm.c Tue Sep 25 23:41:45 2012 (r240942) +++ projects/bhyve/sys/amd64/vmm/vmm.c Wed Sep 26 00:06:17 2012 (r240943) @@ -160,8 +160,8 @@ vcpu_init(struct vm *vm, uint32_t vcpu_i vcpu->hostcpu = -1; vcpu->vcpuid = vcpu_id; - vcpu->x2apic_state = X2APIC_ENABLED; vcpu->vlapic = vlapic_init(vm, vcpu_id); + vm_set_x2apic_state(vm, vcpu_id, X2APIC_ENABLED); vcpu->guestfpu = fpu_save_area_alloc(); fpu_save_area_reset(vcpu->guestfpu); vcpu->stats = vmm_stat_alloc(); @@ -770,5 +770,7 @@ vm_set_x2apic_state(struct vm *vm, int v vm->vcpu[vcpuid].x2apic_state = state; + vlapic_set_x2apic_state(vm, vcpuid, state); + return (0); } Modified: projects/bhyve/usr.sbin/bhyve/fbsdrun.c ============================================================================== --- projects/bhyve/usr.sbin/bhyve/fbsdrun.c Tue Sep 25 23:41:45 2012 (r240942) +++ projects/bhyve/usr.sbin/bhyve/fbsdrun.c Wed Sep 26 00:06:17 2012 (r240943) @@ -84,7 +84,7 @@ int guest_ncpus; static int pincpu = -1; static int guest_vcpu_mux; -static int guest_vmexit_on_hlt, guest_vmexit_on_pause; +static int guest_vmexit_on_hlt, guest_vmexit_on_pause, disable_x2apic; static int foundcpus; @@ -128,8 +128,9 @@ usage(int code) { fprintf(stderr, - "Usage: %s [-ehBHIP][-g ][-z ][-s ]" + "Usage: %s [-aehBHIP][-g ][-z ][-s ]" "[-S ][-p pincpu][-n ][-m lowmem][-M highmem] \n" + " -a: local apic is in XAPIC mode (default is X2APIC)\n" " -g: gdb port (default is %d and 0 means don't open)\n" " -c: # cpus (default 1)\n" " -p: pin vcpu 'n' to host cpu 'pincpu + n'\n" @@ -174,6 +175,13 @@ fbsdrun_add_oemtbl(void *tbl, int tblsz) } int +fbsdrun_disable_x2apic(void) +{ + + return (disable_x2apic); +} + +int fbsdrun_vmexit_on_pause(void) { @@ -553,8 +561,11 @@ main(int argc, char *argv[]) guest_ncpus = 1; ioapic = 0; - while ((c = getopt(argc, argv, "ehBHIPxp:g:c:z:s:S:n:m:M:")) != -1) { + while ((c = getopt(argc, argv, "aehBHIPxp:g:c:z:s:S:n:m:M:")) != -1) { switch (c) { + case 'a': + disable_x2apic = 1; + break; case 'B': inject_bkpt = 1; break; @@ -656,6 +667,16 @@ main(int argc, char *argv[]) handler[VM_EXITCODE_PAUSE] = vmexit_pause; } + if (fbsdrun_disable_x2apic()) + err = vm_set_x2apic_state(ctx, BSP, X2APIC_DISABLED); + else + err = vm_set_x2apic_state(ctx, BSP, X2APIC_ENABLED); + + if (err) { + printf("Unable to set x2apic state (%d)\n", err); + exit(1); + } + if (lomem_sz != 0) { lomem_addr = vm_map_memory(ctx, 0, lomem_sz); if (lomem_addr == (char *) MAP_FAILED) { Modified: projects/bhyve/usr.sbin/bhyve/fbsdrun.h ============================================================================== --- projects/bhyve/usr.sbin/bhyve/fbsdrun.h Tue Sep 25 23:41:45 2012 (r240942) +++ projects/bhyve/usr.sbin/bhyve/fbsdrun.h Wed Sep 26 00:06:17 2012 (r240943) @@ -50,4 +50,5 @@ void fbsdrun_add_oemtbl(void *tbl, int t int fbsdrun_muxed(void); int fbsdrun_vmexit_on_hlt(void); int fbsdrun_vmexit_on_pause(void); +int fbsdrun_disable_x2apic(void); #endif Modified: projects/bhyve/usr.sbin/bhyve/spinup_ap.c ============================================================================== --- projects/bhyve/usr.sbin/bhyve/spinup_ap.c Tue Sep 25 23:41:45 2012 (r240942) +++ projects/bhyve/usr.sbin/bhyve/spinup_ap.c Wed Sep 26 00:06:17 2012 (r240943) @@ -156,6 +156,12 @@ spinup_ap(struct vmctx *ctx, int vcpu, i assert(error == 0); } + if (fbsdrun_disable_x2apic()) + error = vm_set_x2apic_state(ctx, newcpu, X2APIC_DISABLED); + else + error = vm_set_x2apic_state(ctx, newcpu, X2APIC_ENABLED); + assert(error == 0); + /* * There are 2 startup modes possible here: * - if the CPU supports 'unrestricted guest' mode, the spinup can From owner-svn-src-projects@FreeBSD.ORG Thu Sep 27 00:27:59 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2BD6A106566C; Thu, 27 Sep 2012 00:27:59 +0000 (UTC) (envelope-from neel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 175AB8FC0A; Thu, 27 Sep 2012 00:27:59 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8R0RwvR019631; Thu, 27 Sep 2012 00:27:58 GMT (envelope-from neel@svn.freebsd.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8R0RwpD019625; Thu, 27 Sep 2012 00:27:58 GMT (envelope-from neel@svn.freebsd.org) Message-Id: <201209270027.q8R0RwpD019625@svn.freebsd.org> From: Neel Natu Date: Thu, 27 Sep 2012 00:27:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240978 - in projects/bhyve/sys/amd64/vmm: . intel X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 Sep 2012 00:27:59 -0000 Author: neel Date: Thu Sep 27 00:27:58 2012 New Revision: 240978 URL: http://svn.freebsd.org/changeset/base/240978 Log: Intel VT-x provides the length of the instruction at the time of the nested page table fault. Use this when fetching the instruction bytes from the guest memory. Also modify the lapic_mmio() API so that a decoded instruction is fed into it instead of having it fetch the instruction bytes from the guest. This is useful for hardware assists like SVM that provide the faulting instruction as part of the vmexit. Modified: projects/bhyve/sys/amd64/vmm/intel/vmx.c projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.h projects/bhyve/sys/amd64/vmm/vmm_lapic.c projects/bhyve/sys/amd64/vmm/vmm_lapic.h Modified: projects/bhyve/sys/amd64/vmm/intel/vmx.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/intel/vmx.c Wed Sep 26 23:07:00 2012 (r240977) +++ projects/bhyve/sys/amd64/vmm/intel/vmx.c Thu Sep 27 00:27:58 2012 (r240978) @@ -1146,9 +1146,11 @@ vmx_emulate_cr_access(struct vmx *vmx, i static int vmx_lapic_fault(struct vm *vm, int cpu, - uint64_t gpa, uint64_t rip, uint64_t cr3, uint64_t ept_qual) + uint64_t gpa, uint64_t rip, int inst_length, + uint64_t cr3, uint64_t ept_qual) { int read, write, handled; + struct vie vie; /* * For this to be a legitimate access to the local apic: @@ -1180,7 +1182,14 @@ vmx_lapic_fault(struct vm *vm, int cpu, return (UNHANDLED); } - handled = lapic_mmio(vm, cpu, gpa - DEFAULT_APIC_BASE, read, rip, cr3); + /* Fetch, decode and emulate the faulting instruction */ + if (vmm_fetch_instruction(vm, rip, inst_length, cr3, &vie) != 0) + return (UNHANDLED); + + if (vmm_decode_instruction(&vie) != 0) + return (UNHANDLED); + + handled = lapic_mmio(vm, cpu, gpa - DEFAULT_APIC_BASE, read, &vie); return (handled); } @@ -1275,7 +1284,8 @@ vmx_exit_process(struct vmx *vmx, int vc gpa = vmcs_gpa(); cr3 = vmcs_guest_cr3(); handled = vmx_lapic_fault(vmx->vm, vcpu, - gpa, vmexit->rip, cr3, qual); + gpa, vmexit->rip, vmexit->inst_length, + cr3, qual); if (!handled) { vmexit->exitcode = VM_EXITCODE_PAGING; vmexit->u.paging.cr3 = cr3; Modified: projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c Wed Sep 26 23:07:00 2012 (r240977) +++ projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c Thu Sep 27 00:27:58 2012 (r240978) @@ -128,9 +128,9 @@ error: return (-1); } -void -vmm_fetch_instruction(struct vm *vm, uint64_t rip, uint64_t cr3, - struct vie *vie) +int +vmm_fetch_instruction(struct vm *vm, uint64_t rip, int inst_length, + uint64_t cr3, struct vie *vie) { int n, err; uint64_t hpa, gpa, gpaend; @@ -139,17 +139,18 @@ vmm_fetch_instruction(struct vm *vm, uin * XXX cache previously fetched instructions using 'rip' as the tag */ + if (inst_length > VIE_INST_SIZE) + panic("vmm_fetch_instruction: invalid length %d", inst_length); + vie_init(vie); - /* - * Copy up to 15 bytes of the instruction stream into 'vie' - */ - while (vie->num_valid < VIE_INST_SIZE) { + /* Copy the instruction into 'vie' */ + while (vie->num_valid < inst_length) { err = gla2gpa(vm, rip, cr3, &gpa, &gpaend); if (err) break; - n = min(VIE_INST_SIZE - vie->num_valid, gpaend - gpa); + n = min(inst_length - vie->num_valid, gpaend - gpa); hpa = vm_gpa2hpa(vm, gpa, n); if (hpa == -1) @@ -160,6 +161,11 @@ vmm_fetch_instruction(struct vm *vm, uin rip += n; vie->num_valid += n; } + + if (vie->num_valid == inst_length) + return (0); + else + return (-1); } static int Modified: projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.h ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.h Wed Sep 26 23:07:00 2012 (r240977) +++ projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.h Thu Sep 27 00:27:58 2012 (r240978) @@ -83,8 +83,8 @@ struct vie { struct vm; -void vmm_fetch_instruction(struct vm *vm, uint64_t rip, uint64_t cr3, - struct vie *vie); +int vmm_fetch_instruction(struct vm *vm, uint64_t rip, int inst_length, + uint64_t cr3, struct vie *vie); int vmm_decode_instruction(struct vie *vie); Modified: projects/bhyve/sys/amd64/vmm/vmm_lapic.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm_lapic.c Wed Sep 26 23:07:00 2012 (r240977) +++ projects/bhyve/sys/amd64/vmm/vmm_lapic.c Thu Sep 27 00:27:58 2012 (r240978) @@ -177,25 +177,18 @@ lapic_wrmsr(struct vm *vm, int cpu, u_in } int -lapic_mmio(struct vm *vm, int cpu, u_int offset, int read, - uint64_t rip, uint64_t cr3) +lapic_mmio(struct vm *vm, int cpu, u_int offset, int read, struct vie *vie) { int handled, error; uint64_t val; - struct vie vie; struct vlapic *vlapic; const int UNHANDLED = 0; vlapic = vm_lapic(vm, cpu); - vmm_fetch_instruction(vm, rip, cr3, &vie); - - if (vmm_decode_instruction(&vie) != 0) - return (UNHANDLED); - /* Only 32-bit accesses to local apic */ - if (vie.op_size != VIE_OP_SIZE_32BIT) + if (vie->op_size != VIE_OP_SIZE_32BIT) return (UNHANDLED); /* @@ -207,35 +200,35 @@ lapic_mmio(struct vm *vm, int cpu, u_int * This is a limitation of the vm_set_register() API * and can be fixed if necessary. */ - if (vie.operand_register == VM_REG_GUEST_RSP) + if (vie->operand_register == VM_REG_GUEST_RSP) return (UNHANDLED); if (read) { - if ((vie.opcode_flags & VIE_F_TO_REG) == 0) + if ((vie->opcode_flags & VIE_F_TO_REG) == 0) return (UNHANDLED); - if (vie.operand_register >= VM_REG_LAST) + if (vie->operand_register >= VM_REG_LAST) return (UNHANDLED); handled = lapic_read(vlapic, offset, &val); if (handled) { - error = vm_set_register(vm, cpu, vie.operand_register, + error = vm_set_register(vm, cpu, vie->operand_register, val); if (error) panic("lapic_mmio: error %d setting gpr %d", - error, vie.operand_register); + error, vie->operand_register); } } else { - if ((vie.opcode_flags & VIE_F_FROM_REG) && - (vie.operand_register < VM_REG_LAST)) { - error = vm_get_register(vm, cpu, vie.operand_register, + if ((vie->opcode_flags & VIE_F_FROM_REG) && + (vie->operand_register < VM_REG_LAST)) { + error = vm_get_register(vm, cpu, vie->operand_register, &val); if (error) { panic("lapic_mmio: error %d getting gpr %d", - error, vie.operand_register); + error, vie->operand_register); } - } else if (vie.opcode_flags & VIE_F_FROM_IMM) { - val = vie.immediate; + } else if (vie->opcode_flags & VIE_F_FROM_IMM) { + val = vie->immediate; } else { return (UNHANDLED); } Modified: projects/bhyve/sys/amd64/vmm/vmm_lapic.h ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm_lapic.h Wed Sep 26 23:07:00 2012 (r240977) +++ projects/bhyve/sys/amd64/vmm/vmm_lapic.h Thu Sep 27 00:27:58 2012 (r240978) @@ -30,13 +30,13 @@ #define _VMM_LAPIC_H_ struct vm; +struct vie; boolean_t lapic_msr(u_int num); int lapic_rdmsr(struct vm *vm, int cpu, u_int msr, uint64_t *rval); int lapic_wrmsr(struct vm *vm, int cpu, u_int msr, uint64_t wval); -int lapic_mmio(struct vm *vm, int cpu, u_int offset, int read, - uint64_t rip, uint64_t cr3); +int lapic_mmio(struct vm *vm, int cpu, u_int offset, int rd, struct vie *); void lapic_timer_tick(struct vm *vm, int cpu); From owner-svn-src-projects@FreeBSD.ORG Thu Sep 27 14:29:19 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8000C106564A; Thu, 27 Sep 2012 14:29:19 +0000 (UTC) (envelope-from brooks@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6AEDC8FC0C; Thu, 27 Sep 2012 14:29:19 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8RETJPp034752; Thu, 27 Sep 2012 14:29:19 GMT (envelope-from brooks@svn.freebsd.org) Received: (from brooks@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8RETJWH034751; Thu, 27 Sep 2012 14:29:19 GMT (envelope-from brooks@svn.freebsd.org) Message-Id: <201209271429.q8RETJWH034751@svn.freebsd.org> From: Brooks Davis Date: Thu, 27 Sep 2012 14:29:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240996 - projects/mtree/usr.sbin/nmtree/sys X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 Sep 2012 14:29:19 -0000 Author: brooks Date: Thu Sep 27 14:29:18 2012 New Revision: 240996 URL: http://svn.freebsd.org/changeset/base/240996 Log: Implement a wrapper around sys/cdefs.h to define NetBSD's __dead. This reduces the number of patches required to mtree's source. Added: projects/mtree/usr.sbin/nmtree/sys/ projects/mtree/usr.sbin/nmtree/sys/cdefs.h Added: projects/mtree/usr.sbin/nmtree/sys/cdefs.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/mtree/usr.sbin/nmtree/sys/cdefs.h Thu Sep 27 14:29:18 2012 (r240996) @@ -0,0 +1,9 @@ +/* $FreeBSD$ */ + +#include_next + +#ifdef __dead2 +#define __dead __dead2 +#else +#define __dead +#endif From owner-svn-src-projects@FreeBSD.ORG Thu Sep 27 18:52:15 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B3FCD106568F; Thu, 27 Sep 2012 18:52:15 +0000 (UTC) (envelope-from brooks@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 9F84B8FC18; Thu, 27 Sep 2012 18:52:15 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8RIqFpK076453; Thu, 27 Sep 2012 18:52:15 GMT (envelope-from brooks@svn.freebsd.org) Received: (from brooks@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8RIqFpw076450; Thu, 27 Sep 2012 18:52:15 GMT (envelope-from brooks@svn.freebsd.org) Message-Id: <201209271852.q8RIqFpw076450@svn.freebsd.org> From: Brooks Davis Date: Thu, 27 Sep 2012 18:52:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r241005 - projects/mtree/contrib/mtree X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 Sep 2012 18:52:15 -0000 Author: brooks Date: Thu Sep 27 18:52:15 2012 New Revision: 241005 URL: http://svn.freebsd.org/changeset/base/241005 Log: Revert s/__dead/__dead2/ in r240706. I'm now using a sys/cdefs.h wrapper instead. Modified: projects/mtree/contrib/mtree/extern.h projects/mtree/contrib/mtree/mtree.c Modified: projects/mtree/contrib/mtree/extern.h ============================================================================== --- projects/mtree/contrib/mtree/extern.h Thu Sep 27 18:52:04 2012 (r241004) +++ projects/mtree/contrib/mtree/extern.h Thu Sep 27 18:52:15 2012 (r241005) @@ -60,7 +60,7 @@ void cwalk(void); void dump_nodes(const char *, NODE *, int); void init_excludes(void); int matchtags(NODE *); -__dead2 __printflike(1,2) void mtree_err(const char *, ...); +__dead __printflike(1,2) void mtree_err(const char *, ...); const char *nodetype(u_int); u_int parsekey(const char *, int *); void parsetags(slist_t *, char *); Modified: projects/mtree/contrib/mtree/mtree.c ============================================================================== --- projects/mtree/contrib/mtree/mtree.c Thu Sep 27 18:52:04 2012 (r241004) +++ projects/mtree/contrib/mtree/mtree.c Thu Sep 27 18:52:15 2012 (r241005) @@ -63,7 +63,7 @@ int cflag, Cflag, dflag, Dflag, eflag, i nflag, qflag, rflag, sflag, tflag, uflag, Uflag; char fullpath[MAXPATHLEN]; -__dead2 static void usage(void); +__dead static void usage(void); int main(int argc, char **argv) From owner-svn-src-projects@FreeBSD.ORG Sat Sep 29 01:15:46 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 3EDE9106566B; Sat, 29 Sep 2012 01:15:46 +0000 (UTC) (envelope-from neel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 291998FC0A; Sat, 29 Sep 2012 01:15:46 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8T1Fk3l037692; Sat, 29 Sep 2012 01:15:46 GMT (envelope-from neel@svn.freebsd.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8T1Fjv3037688; Sat, 29 Sep 2012 01:15:45 GMT (envelope-from neel@svn.freebsd.org) Message-Id: <201209290115.q8T1Fjv3037688@svn.freebsd.org> From: Neel Natu Date: Sat, 29 Sep 2012 01:15:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r241041 - in projects/bhyve/sys/amd64: include vmm X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 29 Sep 2012 01:15:46 -0000 Author: neel Date: Sat Sep 29 01:15:45 2012 New Revision: 241041 URL: http://svn.freebsd.org/changeset/base/241041 Log: Get rid of assumptions in the hypervisor that the host physical memory associated with guest physical memory is contiguous. In this case vm_malloc() was using vm_gpa2hpa() to indirectly infer whether or not the address range had already been allocated. Replace this instead with an explicit API 'vm_gpa_available()' that returns TRUE if a page is available for allocation in guest physical address space. Modified: projects/bhyve/sys/amd64/include/vmm.h projects/bhyve/sys/amd64/vmm/vmm.c projects/bhyve/sys/amd64/vmm/vmm_dev.c Modified: projects/bhyve/sys/amd64/include/vmm.h ============================================================================== --- projects/bhyve/sys/amd64/include/vmm.h Fri Sep 28 22:26:44 2012 (r241040) +++ projects/bhyve/sys/amd64/include/vmm.h Sat Sep 29 01:15:45 2012 (r241041) @@ -89,7 +89,7 @@ extern struct vmm_ops vmm_ops_amd; struct vm *vm_create(const char *name); void vm_destroy(struct vm *vm); const char *vm_name(struct vm *vm); -int vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t *ret_hpa); +int vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len); int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len); vm_paddr_t vm_gpa2hpa(struct vm *vm, vm_paddr_t gpa, size_t size); Modified: projects/bhyve/sys/amd64/vmm/vmm.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm.c Fri Sep 28 22:26:44 2012 (r241040) +++ projects/bhyve/sys/amd64/vmm/vmm.c Sat Sep 29 01:15:45 2012 (r241041) @@ -315,20 +315,63 @@ vm_unmap_mmio(struct vm *vm, vm_paddr_t VM_PROT_NONE, spok)); } +/* + * Returns TRUE if 'gpa' is available for allocation and FALSE otherwise + */ +static boolean_t +vm_gpa_available(struct vm *vm, vm_paddr_t gpa) +{ + int i; + vm_paddr_t gpabase, gpalimit; + + if (gpa & PAGE_MASK) + panic("vm_gpa_available: gpa (0x%016lx) not page aligned", gpa); + + for (i = 0; i < vm->num_mem_segs; i++) { + gpabase = vm->mem_segs[i].gpa; + gpalimit = gpabase + vm->mem_segs[i].len; + if (gpa >= gpabase && gpa < gpalimit) + return (FALSE); + } + + return (TRUE); +} + int -vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t *ret_hpa) +vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len) { - int error; - vm_paddr_t hpa; + int error, available, allocated; + vm_paddr_t g, hpa; const boolean_t spok = TRUE; /* superpage mappings are ok */ + + if ((gpa & PAGE_MASK) || (len & PAGE_MASK) || len == 0) + return (EINVAL); + available = allocated = 0; + g = gpa; + while (g < gpa + len) { + if (vm_gpa_available(vm, g)) + available++; + else + allocated++; + + g += PAGE_SIZE; + } + /* - * find the hpa if already it was already vm_malloc'd. + * If there are some allocated and some available pages in the address + * range then it is an error. */ - hpa = vm_gpa2hpa(vm, gpa, len); - if (hpa != ((vm_paddr_t)-1)) - goto out; + if (allocated && available) + return (EINVAL); + + /* + * If the entire address range being requested has already been + * allocated then there isn't anything more to do. + */ + if (allocated && available == 0) + return (0); if (vm->num_mem_segs >= VM_MAX_MEMORY_SEGMENTS) return (E2BIG); @@ -350,8 +393,7 @@ vm_malloc(struct vm *vm, vm_paddr_t gpa, vm->mem_segs[vm->num_mem_segs].hpa = hpa; vm->mem_segs[vm->num_mem_segs].len = len; vm->num_mem_segs++; -out: - *ret_hpa = hpa; + return (0); } Modified: projects/bhyve/sys/amd64/vmm/vmm_dev.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm_dev.c Fri Sep 28 22:26:44 2012 (r241040) +++ projects/bhyve/sys/amd64/vmm/vmm_dev.c Sat Sep 29 01:15:45 2012 (r241041) @@ -295,7 +295,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long c break; case VM_MAP_MEMORY: seg = (struct vm_memory_segment *)data; - error = vm_malloc(sc->vm, seg->gpa, seg->len, &seg->hpa); + error = vm_malloc(sc->vm, seg->gpa, seg->len); break; case VM_GET_MEMORY_SEG: seg = (struct vm_memory_segment *)data;