I've created an initial version of the patch which allows more flexible vcpu pinning configuration.
Current schema is: bhyve -p N pins vcpu i to hostcpu N + i. The propsed extension is: bhyve -p N:M .... -p 0:1 -p 3:5 which pins vcpu N to host pcpu M. Option needs to be specified individually for each vcpu. So it works like that for me: sudo /usr/sbin/bhyve -p 0:0 -p 1:3 -c 2 ... # sudo cpuset -g -t 100262 tid 100262 mask: 0 # sudo cpuset -g -t 100264 tid 100264 mask: 3 PS I used cpumat_t* array to store these values instead of int, because if the idea is OK, I'll extend it to support ranges like e.g. cpuset(1) supports, e.g.: "1:2-5". The questions are: - Is it OK to chance '-p' arg syntax or it's better to introduce a new one? - Is the syntax OK (currently: 'vcpu:pcpu', later 'vcpu:pcpuN-pcpuM,pcpuX")? Roman Bogorodskiy
Index: bhyverun.c
===================================================================
--- bhyverun.c (revision 264921)
+++ bhyverun.c (working copy)
@@ -83,7 +83,6 @@
int guest_ncpus;
-static int pincpu = -1;
static int guest_vmexit_on_hlt, guest_vmexit_on_pause, disable_x2apic;
static int virtio_msix = 1;
@@ -119,6 +118,8 @@
int mt_vcpu;
} mt_vmm_info[VM_MAXCPU];
+cpuset_t *vcpumap[VM_MAXCPU] = { NULL };
+
static void
usage(int code)
{
@@ -146,6 +147,56 @@
exit(code);
}
+static int
+pincpu_parse(const char *cpupin)
+{
+ char *token, *string;
+ size_t i = 0;
+ int vcpu = -1, pcpu = -1, ret = -1;
+ cpuset_t *mask;
+
+ if ((string = strdup(cpupin)) == NULL) {
+ fprintf(stderr, "strdup failed: %d\n", errno);
+ return -1;
+ }
+
+ while ((token = strsep(&string, ":")) != NULL) {
+ switch (i) {
+ case 0:
+ vcpu = atoi(token);
+ break;
+ case 1:
+ pcpu = atoi(token);
+ break;
+ default:
+ fprintf(stderr, "invalid format: %s\n", token);
+ goto cleanup;
+ }
+ i++;
+ }
+
+ if (vcpu == -1 || pcpu == -1) {
+ fprintf(stderr, "invalid format: %s\n", cpupin);
+ goto cleanup;
+ }
+
+ if ((mask = malloc(sizeof(cpuset_t))) == NULL) {
+ fprintf(stderr, "malloc failed: %d\n", errno);
+ goto cleanup;
+ }
+ CPU_ZERO(mask);
+ CPU_SET(pcpu, mask);
+
+ vcpumap[vcpu] = mask;
+
+ ret = 0;
+
+cleanup:
+ free(string);
+
+ return ret;
+}
+
void *
paddr_guest2host(struct vmctx *ctx, uintptr_t gaddr, size_t len)
{
@@ -479,15 +530,13 @@
static void
vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip)
{
- cpuset_t mask;
int error, rc, prevcpu;
enum vm_exitcode exitcode;
- if (pincpu >= 0) {
- CPU_ZERO(&mask);
- CPU_SET(pincpu + vcpu, &mask);
+ if (vcpumap[vcpu] != NULL) {
error = pthread_setaffinity_np(pthread_self(),
- sizeof(mask), &mask);
+ sizeof(cpuset_t),
+ vcpumap[vcpu]);
assert(error == 0);
}
@@ -622,7 +671,10 @@
bvmcons = 1;
break;
case 'p':
- pincpu = atoi(optarg);
+ if (pincpu_parse(optarg) < 0) {
+ errx(EX_USAGE, "invalid cpu pin "
+ "configuration '%s'", optarg);
+ }
break;
case 'c':
guest_ncpus = atoi(optarg);
pgpxeZu8t9Fjn.pgp
Description: PGP signature
