Page MenuHomeFreeBSD

D9930.id26094.diff
No OneTemporary

D9930.id26094.diff

Index: lib/libvmmapi/vmmapi.h
===================================================================
--- lib/libvmmapi/vmmapi.h
+++ lib/libvmmapi/vmmapi.h
@@ -209,6 +209,9 @@
int vm_suspended_cpus(struct vmctx *ctx, cpuset_t *cpus);
int vm_activate_cpu(struct vmctx *ctx, int vcpu);
+/* Set cpu topology */
+int vm_set_topology(struct vmctx *ctx, uint64_t sockets, uint64_t cores, uint64_t threads, uint64_t maxcpus);
+
/*
* FreeBSD specific APIs
*/
Index: lib/libvmmapi/vmmapi.c
===================================================================
--- lib/libvmmapi/vmmapi.c
+++ lib/libvmmapi/vmmapi.c
@@ -1418,6 +1418,19 @@
}
int
+vm_set_topology(struct vmctx *ctx, uint64_t sockets, uint64_t cores, uint64_t threads, uint64_t maxcpus)
+{
+ struct vm_cpu_topology topology;
+
+ bzero(&topology, sizeof (struct vm_cpu_topology));
+ topology.sockets = sockets;
+ topology.cores = cores;
+ topology.threads = threads;
+ topology.maxcpus = maxcpus;
+ return (ioctl(ctx->fd, VM_SET_TOPOLOGY, &topology));
+}
+
+int
vm_get_device_fd(struct vmctx *ctx)
{
@@ -1444,7 +1457,7 @@
VM_GET_HPET_CAPABILITIES, VM_GET_GPA_PMAP, VM_GLA2GPA,
VM_ACTIVATE_CPU, VM_GET_CPUS, VM_SET_INTINFO, VM_GET_INTINFO,
VM_RTC_WRITE, VM_RTC_READ, VM_RTC_SETTIME, VM_RTC_GETTIME,
- VM_RESTART_INSTRUCTION };
+ VM_RESTART_INSTRUCTION, VM_SET_TOPOLOGY, VM_GET_TOPOLOGY };
if (len == NULL) {
cmds = malloc(sizeof(vm_ioctl_cmds));
Index: sys/amd64/include/vmm.h
===================================================================
--- sys/amd64/include/vmm.h
+++ sys/amd64/include/vmm.h
@@ -174,6 +174,10 @@
void vm_destroy(struct vm *vm);
int vm_reinit(struct vm *vm);
const char *vm_name(struct vm *vm);
+void vm_get_topology(struct vm *vm, uint64_t *sockets, uint64_t *cores,
+ uint64_t *threads, uint64_t *maxcpus);
+void vm_set_topology(struct vm *vm, uint64_t *sockets, uint64_t *cores,
+ uint64_t *threads, uint64_t *maxcpus);
/*
* APIs that modify the guest memory map require all vcpus to be frozen.
Index: sys/amd64/include/vmm_dev.h
===================================================================
--- sys/amd64/include/vmm_dev.h
+++ sys/amd64/include/vmm_dev.h
@@ -216,6 +216,13 @@
uint8_t value;
};
+struct vm_cpu_topology {
+ uint64_t sockets;
+ uint64_t cores;
+ uint64_t threads;
+ uint64_t maxcpus;
+};
+
enum {
/* general routines */
IOCNUM_ABIVERS = 0,
@@ -286,6 +293,10 @@
IOCNUM_RTC_WRITE = 101,
IOCNUM_RTC_SETTIME = 102,
IOCNUM_RTC_GETTIME = 103,
+
+ /* CPU Topology */
+ IOCNUM_SET_TOPOLOGY = 104,
+ IOCNUM_GET_TOPOLOGY = 105,
};
#define VM_RUN \
@@ -382,4 +393,8 @@
_IOR('v', IOCNUM_RTC_GETTIME, struct vm_rtc_time)
#define VM_RESTART_INSTRUCTION \
_IOW('v', IOCNUM_RESTART_INSTRUCTION, int)
+#define VM_SET_TOPOLOGY \
+ _IOW('v', IOCNUM_SET_TOPOLOGY, struct vm_cpu_topology)
+#define VM_GET_TOPOLOGY \
+ _IOR('v', IOCNUM_GET_TOPOLOGY, struct vm_cpu_topology)
#endif
Index: sys/amd64/vmm/vmm.c
===================================================================
--- sys/amd64/vmm/vmm.c
+++ sys/amd64/vmm/vmm.c
@@ -162,6 +162,11 @@
struct vmspace *vmspace; /* (o) guest's address space */
char name[VM_MAX_NAMELEN]; /* (o) virtual machine name */
struct vcpu vcpu[VM_MAXCPU]; /* (i) guest vcpus */
+ /* The following describe the vm cpu topology */
+ uint64_t sockets; /* (o) number of sockets */
+ uint64_t cores; /* (o) number of cores/socket */
+ uint64_t threads; /* (o) number of threads/core */
+ uint64_t maxcpus; /* (o) max pluggable cpus */
};
static int vmm_initialized;
@@ -419,6 +424,9 @@
vcpu_init(vm, i, create);
}
+extern u_int cores_per_package;
+extern u_int threads_per_core;
+
int
vm_create(const char *name, struct vm **retvm)
{
@@ -443,6 +451,10 @@
strcpy(vm->name, name);
vm->vmspace = vmspace;
mtx_init(&vm->rendezvous_mtx, "vm rendezvous lock", 0, MTX_DEF);
+ vm->sockets=1; /* XXX not implemented */
+ vm->cores=cores_per_package; /* XXX should come from userland */
+ vm->threads=threads_per_core; /* XXX should come from userland */
+ vm->maxcpus=0; /* XXX not implemented */
vm_init(vm, true);
@@ -450,6 +462,26 @@
return (0);
}
+void
+vm_get_topology(struct vm *vm, uint64_t *sockets, uint64_t *cores,
+ uint64_t *threads, uint64_t *maxcpus)
+{
+ *sockets=vm->sockets;
+ *cores=vm->cores;
+ *threads=vm->threads;
+ *maxcpus=vm->maxcpus;
+}
+
+void
+vm_set_topology(struct vm *vm, uint64_t *sockets, uint64_t *cores,
+ uint64_t *threads, uint64_t *maxcpus)
+{
+ vm->sockets=*sockets;
+ vm->cores=*cores;
+ vm->threads=*threads;
+ vm->maxcpus=*maxcpus;
+}
+
static void
vm_cleanup(struct vm *vm, bool destroy)
{
Index: sys/amd64/vmm/vmm_dev.c
===================================================================
--- sys/amd64/vmm/vmm_dev.c
+++ sys/amd64/vmm/vmm_dev.c
@@ -313,6 +313,7 @@
struct vm_rtc_time *rtctime;
struct vm_rtc_data *rtcdata;
struct vm_memmap *mm;
+ struct vm_cpu_topology *topology;
sc = vmmdev_lookup2(cdev);
if (sc == NULL)
@@ -640,6 +641,13 @@
case VM_RESTART_INSTRUCTION:
error = vm_restart_instruction(sc->vm, vcpu);
break;
+ case VM_SET_TOPOLOGY:
+ topology = (struct vm_cpu_topology *)data;
+ vm_set_topology(sc->vm, &topology->sockets, &topology->cores, &topology->threads, &topology->maxcpus);
+ break;
+ case VM_GET_TOPOLOGY:
+ break;
+
default:
error = ENOTTY;
break;
Index: sys/amd64/vmm/x86.c
===================================================================
--- sys/amd64/vmm/x86.c
+++ sys/amd64/vmm/x86.c
@@ -61,12 +61,12 @@
/*
* The default CPU topology is a single thread per package.
*/
-static u_int threads_per_core = 1;
-SYSCTL_UINT(_hw_vmm_topology, OID_AUTO, threads_per_core, CTLFLAG_RDTUN,
+u_int threads_per_core = 1;
+SYSCTL_UINT(_hw_vmm_topology, OID_AUTO, threads_per_core, CTLFLAG_RW,
&threads_per_core, 0, NULL);
-static u_int cores_per_package = 1;
-SYSCTL_UINT(_hw_vmm_topology, OID_AUTO, cores_per_package, CTLFLAG_RDTUN,
+u_int cores_per_package = 1;
+SYSCTL_UINT(_hw_vmm_topology, OID_AUTO, cores_per_package, CTLFLAG_RW,
&cores_per_package, 0, NULL);
static int cpuid_leaf_b = 1;
@@ -89,7 +89,7 @@
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
{
const struct xsave_limits *limits;
- uint64_t cr4;
+ uint64_t cores, cr4, maxcpus, sockets, threads;
int error, enable_invpcid, level, width, x2apic_id;
unsigned int func, regs[4], logical_cpus;
enum x2apic_state x2apic_state;
@@ -140,11 +140,12 @@
*
* However this matches the logical cpus as
* advertised by leaf 0x1 and will work even
- * if the 'threads_per_core' tunable is set
- * incorrectly on an AMD host.
+ * if threads is set incorrectly on an AMD host.
*/
- logical_cpus = threads_per_core *
- cores_per_package;
+ vm_get_topology(vm, &sockets, &cores, &threads,
+ &maxcpus);
+ logical_cpus = threads *
+ cores;
regs[2] = logical_cpus - 1;
}
break;
@@ -300,7 +301,9 @@
*/
regs[3] |= (CPUID_MCA | CPUID_MCE | CPUID_MTRR);
- logical_cpus = threads_per_core * cores_per_package;
+ vm_get_topology(vm, &sockets, &cores, &threads,
+ &maxcpus);
+ logical_cpus = threads * cores;
regs[1] &= ~CPUID_HTT_CORES;
regs[1] |= (logical_cpus & 0xff) << 16;
regs[3] |= CPUID_HTT;
@@ -310,8 +313,10 @@
cpuid_count(*eax, *ecx, regs);
if (regs[0] || regs[1] || regs[2] || regs[3]) {
+ vm_get_topology(vm, &sockets, &cores, &threads,
+ &maxcpus);
regs[0] &= 0x3ff;
- regs[0] |= (cores_per_package - 1) << 26;
+ regs[0] |= (cores - 1) << 26;
/*
* Cache topology:
* - L1 and L2 are shared only by the logical
@@ -319,10 +324,10 @@
* - L3 and above are shared by all logical
* processors in the package.
*/
- logical_cpus = threads_per_core;
+ logical_cpus = threads;
level = (regs[0] >> 5) & 0x7;
if (level >= 3)
- logical_cpus *= cores_per_package;
+ logical_cpus *= cores;
regs[0] |= (logical_cpus - 1) << 14;
}
break;
@@ -385,7 +390,9 @@
* Processor topology enumeration
*/
if (*ecx == 0) {
- logical_cpus = threads_per_core;
+ vm_get_topology(vm, &sockets, &cores, &threads,
+ &maxcpus);
+ logical_cpus = threads;
width = log2(logical_cpus);
level = CPUID_TYPE_SMT;
x2apic_id = vcpu_id;
@@ -392,8 +399,8 @@
}
if (*ecx == 1) {
- logical_cpus = threads_per_core *
- cores_per_package;
+ logical_cpus = threads *
+ cores;
width = log2(logical_cpus);
level = CPUID_TYPE_CORE;
x2apic_id = vcpu_id;
Index: usr.sbin/bhyve/bhyverun.c
===================================================================
--- usr.sbin/bhyve/bhyverun.c
+++ usr.sbin/bhyve/bhyverun.c
@@ -91,6 +91,11 @@
char *vmname;
int guest_ncpus;
+uint64_t sockets;
+uint64_t cores;
+uint64_t threads;
+uint64_t maxcpus;
+
char *guest_uuid_str;
static int guest_vmexit_on_hlt, guest_vmexit_on_pause;
@@ -163,6 +168,45 @@
}
static int
+topology_parse(const char *opt)
+{
+ char *cp, *str;
+ int i, tmp;
+
+ str = strdup(opt);
+ if ((cp = strchr(str, ',')) != NULL) {
+ for (i = 0; str; i++) {
+ if (sscanf(str, "cpus=%d", &tmp) == 1)
+ guest_ncpus = tmp;
+ else if (sscanf(str, "cores=%d", &tmp) == 1)
+ cores = tmp;
+ else if (sscanf(str, "threads=%d", &tmp) == 1)
+ threads = tmp;
+ else if (sscanf(str, "sockets=%d", &tmp) == 1)
+ sockets = tmp;
+ else if (sscanf(str, "maxcpus=%d", &tmp) == 1)
+ maxcpus = tmp;
+ else
+ return (-1);
+ if (cp == NULL)
+ str = NULL;
+ else {
+ str = ++cp;
+ cp = strchr(str, ',');
+ }
+ }
+ } else {
+ if (sscanf(str, "cpus=%d", &tmp) == 1)
+ guest_ncpus = tmp;
+ else if (sscanf(str, "%d", &tmp) == 1)
+ guest_ncpus = tmp;
+ else
+ return (-1);
+ }
+ return(0);
+}
+
+static int
pincpu_parse(const char *opt)
{
int vcpu, pcpu;
@@ -781,6 +825,7 @@
exit(1);
}
}
+ vm_set_topology(ctx, sockets, cores, threads, maxcpus);
return (ctx);
}
@@ -799,6 +844,8 @@
progname = basename(argv[0]);
gdb_port = 0;
guest_ncpus = 1;
+ sockets = cores = threads = 1;
+ maxcpus = 0;
memsize = 256 * MB;
mptgen = 1;
rtc_localtime = 1;
@@ -823,7 +870,10 @@
}
break;
case 'c':
- guest_ncpus = atoi(optarg);
+ if (topology_parse(optarg) !=0) {
+ errx(EX_USAGE, "invalid cpu topology "
+ "'%s'", optarg);
+ }
break;
case 'C':
memflags |= VM_MEM_F_INCORE;

File Metadata

Mime Type
text/plain
Expires
Wed, Jul 29, 8:56 AM (8 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35691581
Default Alt Text
D9930.id26094.diff (10 KB)

Event Timeline