Signed-off-by: Benyu Xu <benyux...@intel.com> --- vl.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+)
diff --git a/vl.c b/vl.c index 36ff3f4..8c5dd25 100644 --- a/vl.c +++ b/vl.c @@ -167,6 +167,7 @@ int smp_cpus = 1; int max_cpus = 1; int smp_cores = 1; int smp_threads = 1; +int pcpu_id_array[131072 + 2] = {0}; /* 131072 = 1024 * 128 */ int acpi_enabled = 1; int no_hpet = 0; int fd_bootchk = 1; @@ -1270,6 +1271,106 @@ static void smp_parse(QemuOpts *opts) } } +static void vcpupin_parse(const char *pcpu_id_list, const int smp_cpus_num) +{ + long pcpu_id; + int pcpu_num = 0; + bool pin_auto = false; + bool id_is_range = false; + long id_range_left; + long id_range_right; + int host_cpu_num; + const char *tmp_id_list = pcpu_id_list; + int ret = 0; + + if (!pcpu_id_list) { + return; + } + + if (strcmp(pcpu_id_list, "auto") == 0) { + pin_auto = true; + } + + host_cpu_num = get_pcpu_num(pin_auto, pcpu_id_array); + if (host_cpu_num <= 0) { + error_report("cannot determine host cpu number"); + exit(1); + } + + if (smp_cpus_num > host_cpu_num) { + error_report("host can serve only %d cpus, less than smp_cpus_num %d", + host_cpu_num, smp_cpus_num); + exit(1); + } + + if (pin_auto == true) { + return; + } + + if (isdigit(tmp_id_list[0]) == 0) { + error_report("invalid pcpu id list %s", pcpu_id_list); + error_report("pcpu id list should be \"auto\" or begin by digit"); + exit(1); + } + + while (tmp_id_list[0] != '\0') { + if (isdigit(tmp_id_list[0]) == 0 && tmp_id_list[0] != ',' && + tmp_id_list[0] != '-') { + error_report("invalid pcpu id list %s", pcpu_id_list); + error_report("pcpu id list only accept digit or ',' or '-'"); + exit(1); + } + tmp_id_list++; + } + tmp_id_list = pcpu_id_list; + + while (tmp_id_list) { + ret = qemu_strtol(tmp_id_list, &tmp_id_list, 10, &pcpu_id); + if (ret == ERANGE || pcpu_id < 0 || pcpu_id >= host_cpu_num) { + error_report("pcpu id %ld is out of range", pcpu_id); + exit(1); + } + + if (id_is_range == true) { + id_range_right = pcpu_id; + if (id_range_right <= id_range_left) { + error_report("invalid pcpu id list [%ld-%ld]", + id_range_left, id_range_right); + exit(1); + } + for (; id_range_left <= id_range_right; id_range_left++) { + pcpu_id_array[0] = pcpu_num; + pcpu_id_array[pcpu_num] = id_range_left; + pcpu_num++; + } + pcpu_num--; + } else { + pcpu_num++; + pcpu_id_array[0] = pcpu_num; + pcpu_id_array[pcpu_num] = pcpu_id; + } + + if (tmp_id_list[0] == '\0') { + break; + } else if (tmp_id_list[0] == '-') { + id_is_range = true; + id_range_left = pcpu_id; + } else { + id_is_range = false; + } + tmp_id_list++; + + if (tmp_id_list[0] == '\0') { + error_report("invalid pcpu id list %s", pcpu_id_list); + error_report("pcpu id list should be end by digit"); + exit(1); + } else if (isdigit(tmp_id_list[0]) == 0) { + error_report("invalid pcpu id list %s", pcpu_id_list); + exit(1); + } + } +} + static void realtime_init(void) { if (enable_mlock) { @@ -3024,6 +3125,9 @@ int main(int argc, char **argv, char **envp) Error *main_loop_err = NULL; Error *err = NULL; bool list_data_dirs = false; + + const char *pcpu_id_list = NULL; + typedef struct BlockdevOptions_queue { BlockdevOptions *bdo; Location loc; @@ -3810,6 +3914,9 @@ int main(int argc, char **argv, char **envp) exit(1); } break; + case QEMU_OPTION_vcpupin: + pcpu_id_list = optarg; + break; case QEMU_OPTION_vnc: vnc_parse(optarg, &error_fatal); break; @@ -4222,6 +4329,8 @@ int main(int argc, char **argv, char **envp) smp_parse(qemu_opts_find(qemu_find_opts("smp-opts"), NULL)); + vcpupin_parse(pcpu_id_list, smp_cpus); + machine_class->max_cpus = machine_class->max_cpus ?: 1; /* Default to UP */ if (max_cpus > machine_class->max_cpus) { error_report("Number of SMP CPUs requested (%d) exceeds max CPUs " @@ -4621,6 +4730,12 @@ int main(int argc, char **argv, char **envp) machine_run_board_init(current_machine); + pin_all_vcpus(smp_cpus, pcpu_id_array, &err); + if (err) { + error_report_err(err); + exit(1); + } + realtime_init(); soundhw_init(); -- 1.8.3.1