diff options
author | neel <neel@FreeBSD.org> | 2012-09-25 19:08:51 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2012-09-25 19:08:51 +0000 |
commit | ebdd69568d7fa97153aa47a86afe367476a0a1de (patch) | |
tree | b73faadf3ccee979f76090f7f988fe5e700627d7 | |
parent | c34be7b811ad199e64f66db339e7f64c773ca0a7 (diff) | |
download | FreeBSD-src-ebdd69568d7fa97153aa47a86afe367476a0a1de.zip FreeBSD-src-ebdd69568d7fa97153aa47a86afe367476a0a1de.tar.gz |
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.
-rw-r--r-- | lib/libvmmapi/vmmapi.c | 29 | ||||
-rw-r--r-- | lib/libvmmapi/vmmapi.h | 4 | ||||
-rw-r--r-- | sys/amd64/include/vmm.h | 11 | ||||
-rw-r--r-- | sys/amd64/include/vmm_dev.h | 11 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm.c | 27 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_dev.c | 12 | ||||
-rw-r--r-- | usr.sbin/vmmctl/vmmctl.c | 20 |
7 files changed, 114 insertions, 0 deletions
diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c index d7e6143..78ed368 100644 --- a/lib/libvmmapi/vmmapi.c +++ b/lib/libvmmapi/vmmapi.c @@ -537,6 +537,35 @@ vm_get_stat_desc(struct vmctx *ctx, int index) 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 diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h index 516bbc3..b918409 100644 --- a/lib/libvmmapi/vmmapi.h +++ b/lib/libvmmapi/vmmapi.h @@ -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 vcpu, struct timeval *ret_tv, 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); diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index e841963..0b3a29c 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -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, int cpu); 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. diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h index d1a50d6..fc64fd8 100644 --- a/sys/amd64/include/vmm_dev.h +++ b/sys/amd64/include/vmm_dev.h @@ -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 diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index d896f6d..29dbe67 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -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_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 * @@ -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); +} diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c index 116b5f1..686ddec 100644 --- a/sys/amd64/vmm/vmm_dev.c +++ b/sys/amd64/vmm/vmm_dev.c @@ -163,6 +163,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, 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 cmd, caddr_t data, int fflag, 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 cmd, caddr_t data, int fflag, 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; diff --git a/usr.sbin/vmmctl/vmmctl.c b/usr.sbin/vmmctl/vmmctl.c index c0e0402..b205c7b 100644 --- a/usr.sbin/vmmctl/vmmctl.c +++ b/usr.sbin/vmmctl/vmmctl.c @@ -185,6 +185,8 @@ usage(void) " [--get-vmcs-interruptibility]\n" " [--set-pinning=<host_cpuid>]\n" " [--get-pinning]\n" + " [--set-x2apic-state=<state>]\n" + " [--get-x2apic-state]\n" " [--set-lowmem=<memory below 4GB in units of MB>]\n" " [--get-lowmem]\n" " [--set-highmem=<memory above 4GB in units of MB>]\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) |