From 71bdc27a0f9a8664015353129f8c7bdc4a163de8 Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Tue, 21 Jan 2020 14:53:21 -0800 Subject: [PATCH] acrn-dm: implement cpu_affinity command line argument User has a chance to specify VCPU affinity through acrn-dm command line argument. Examples of the command line: 3 PCPUs: 1/2/3 --cpu_affinity 1-3 5 PCPUs: 2/3/6/7/8 --cpu_affinity 2,3,6-8 8 PCPUs: 2/3/6/7/9/10/11/12 --cpu_affinity 2,3,6-7,9,10-12 The specified pCPUs must be included in the guest VM's statically defined vm_config[].cpu_affinity_bitmap. Tracked-On: #4616 Signed-off-by: Zide Chen --- devicemodel/core/main.c | 7 ++++ devicemodel/core/vmmapi.c | 79 ++++++++++++++++++++++++++++++++++++ devicemodel/include/vmmapi.h | 1 + 3 files changed, 87 insertions(+) diff --git a/devicemodel/core/main.c b/devicemodel/core/main.c index dc9fb4359..481f0e0a5 100644 --- a/devicemodel/core/main.c +++ b/devicemodel/core/main.c @@ -164,6 +164,7 @@ usage(int code) #endif " --vsbl: vsbl file path\n" " --ovmf: ovmf file path\n" + " --pcpu_list: list of pCPUs assigned to this VM\n" " --part_info: guest partition info file path\n" " --enable_trusty: enable trusty for guest\n" " --debugexit: enable debug exit function\n" @@ -718,6 +719,7 @@ sig_handler_term(int signo) enum { CMD_OPT_VSBL = 1000, CMD_OPT_OVMF, + CMD_OPT_PCPU_LIST, CMD_OPT_PART_INFO, CMD_OPT_TRUSTY_ENABLE, CMD_OPT_VIRTIO_POLL_ENABLE, @@ -757,6 +759,7 @@ static struct option long_options[] = { #endif {"vsbl", required_argument, 0, CMD_OPT_VSBL}, {"ovmf", required_argument, 0, CMD_OPT_OVMF}, + {"pcpu_list", required_argument, 0, CMD_OPT_PCPU_LIST}, {"part_info", required_argument, 0, CMD_OPT_PART_INFO}, {"enable_trusty", no_argument, 0, CMD_OPT_TRUSTY_ENABLE}, @@ -874,6 +877,10 @@ main(int argc, char *argv[]) errx(EX_USAGE, "invalid ovmf param %s", optarg); skip_pci_mem64bar_workaround = true; break; + case CMD_OPT_PCPU_LIST: + if (acrn_parse_pcpu_list(optarg) != 0) + errx(EX_USAGE, "invalid pcpu param %s", optarg); + break; case CMD_OPT_PART_INFO: if (acrn_parse_guest_part_info(optarg) != 0) { errx(EX_USAGE, diff --git a/devicemodel/core/vmmapi.c b/devicemodel/core/vmmapi.c index 0db51ab3c..fcb68fa33 100644 --- a/devicemodel/core/vmmapi.c +++ b/devicemodel/core/vmmapi.c @@ -85,6 +85,82 @@ check_api(int fd) } static int devfd = -1; +static uint64_t cpu_affinity_bitmap = 0UL; + +static void add_one_pcpu(int pcpu_id) +{ + if (cpu_affinity_bitmap & (1UL << pcpu_id)) { + pr_err("%s: pcpu_id %d has been allocated to this VM.\n", __func__, pcpu_id); + return; + } + + cpu_affinity_bitmap |= (1UL << pcpu_id); +} + +/* + * example options: + * --pcpu_list 1,2,3 + * --pcpu_list 1-3 + * --pcpu_list 1,3,4-6 + * --pcpu_list 1,3,4-6,9 + */ +int acrn_parse_pcpu_list(char *opt) +{ + char *str, *cp; + int pcpu_id; + int pcpu_start, pcpu_end; + + cp = strdup(opt); + if (!cp) { + pr_err("%s: strdup returns NULL\n", __func__); + return -1; + } + + while (cp) { + str = strpbrk(cp, ",-"); + + /* no more entries delimited by ',' or '-' */ + if (!str) { + if (!dm_strtoi(cp, NULL, 10, &pcpu_id)) { + add_one_pcpu(pcpu_id); + break; + } + } + + if (*str == ',') { + /* after this, 'cp' points to the character after ',' */ + str = strsep(&cp, ","); + + /* parse the entry before ',' */ + if (dm_strtoi(str, NULL, 10, &pcpu_id)) { + return -1; + } + add_one_pcpu(pcpu_id); + } + + if (*str == '-') { + str = strsep(&cp, "-"); + + /* parse the entry before and after '-' respectively */ + if (dm_strtoi(str, NULL, 10, &pcpu_start) || dm_strtoi(cp, NULL, 10, &pcpu_end)) { + return -1; + } + + if (pcpu_end <= pcpu_start) { + return -1; + } + + for (; pcpu_start <= pcpu_end; pcpu_start++) { + add_one_pcpu(pcpu_start); + } + + /* skip the ',' after pcpu_end */ + str = strsep(&cp, ","); + } + } + + return 0; +} struct vmctx * vm_create(const char *name, uint64_t req_buf, int *vcpu_num) @@ -150,6 +226,9 @@ vm_create(const char *name, uint64_t req_buf, int *vcpu_num) create_vm.vm_flag &= (~GUEST_FLAG_IO_COMPLETION_POLLING); } + /* command line arguments specified CPU affinity could overwrite HV's static configuration */ + create_vm.cpu_affinity = cpu_affinity_bitmap; + if (is_rtvm) { create_vm.vm_flag |= GUEST_FLAG_RT; create_vm.vm_flag |= GUEST_FLAG_IO_COMPLETION_POLLING; diff --git a/devicemodel/include/vmmapi.h b/devicemodel/include/vmmapi.h index a09e037f1..e291baf24 100644 --- a/devicemodel/include/vmmapi.h +++ b/devicemodel/include/vmmapi.h @@ -134,6 +134,7 @@ int vm_set_ptdev_intx_info(struct vmctx *ctx, uint16_t virt_bdf, int vm_reset_ptdev_intx_info(struct vmctx *ctx, uint16_t virt_bdf, uint16_t phys_bdf, int virt_pin, bool pic_pin); +int acrn_parse_pcpu_list(char *arg); int vm_create_vcpu(struct vmctx *ctx, uint16_t vcpu_id); int vm_set_vcpu_regs(struct vmctx *ctx, struct acrn_set_vcpu_regs *cpu_regs);