Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 25 Sep 2012 19:08:52 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r240922 - in projects/bhyve: lib/libvmmapi sys/amd64/include sys/amd64/vmm usr.sbin/vmmctl
Message-ID:  <201209251908.q8PJ8qhq080022@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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=<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)



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