From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LCafG-0002wT-Rq for qemu-devel@nongnu.org; Tue, 16 Dec 2008 09:12:46 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LCafF-0002w3-VX for qemu-devel@nongnu.org; Tue, 16 Dec 2008 09:12:46 -0500 Received: from [199.232.76.173] (port=48180 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LCafF-0002vx-SB for qemu-devel@nongnu.org; Tue, 16 Dec 2008 09:12:45 -0500 Received: from outbound-dub.frontbridge.com ([213.199.154.16]:44941 helo=IE1EHSOBE004.bigfish.com) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_ARCFOUR_MD5:16) (Exim 4.60) (envelope-from ) id 1LCafF-0005Gu-B1 for qemu-devel@nongnu.org; Tue, 16 Dec 2008 09:12:45 -0500 Message-ID: <4947B784.8020300@amd.com> Date: Tue, 16 Dec 2008 15:13:24 +0100 From: Andre Przywara MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------020209060403070001020707" Subject: [Qemu-devel] [PATCH 1/8] v2: introduce -numa command line option Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Anthony Liguori Cc: qemu-devel@nongnu.org, Avi Kivity --------------020209060403070001020707 Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: 7bit Signed-off-by: Andre Przywara -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany Tel: +49 351 277-84917 ----to satisfy European Law for business letters: AMD Saxony Limited Liability Company & Co. KG, Wilschdorfer Landstr. 101, 01109 Dresden, Germany Register Court Dresden: HRA 4896, General Partner authorized to represent: AMD Saxony LLC (Wilmington, Delaware, US) General Manager of AMD Saxony LLC: Dr. Hans-R. Deppe, Thomas McCoy --------------020209060403070001020707 Content-Type: text/x-patch; name="qemunuma_v2_cmdline.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="qemunuma_v2_cmdline.patch" # HG changeset patch # User Andre Przywara # Date 1229425990 -3600 # Node ID 6690ab0a34fdedaebbfe1068dfe7351734e8a1d7 # Parent 4271a7547668e4b02cae88e66c936d9cacab624e add -numa command line option diff -r 4271a7547668 -r 6690ab0a34fd sysemu.h --- a/sysemu.h Tue Dec 16 12:02:50 2008 +0100 +++ b/sysemu.h Tue Dec 16 12:13:10 2008 +0100 @@ -92,6 +92,15 @@ extern int alt_grab; extern int alt_grab; extern int usb_enabled; extern int smp_cpus; + +#define MAX_NODES 64 +extern int numnumanodes; +extern uint64_t node_mem[MAX_NODES]; +extern uint64_t node_to_cpus[MAX_NODES]; + +int parse_numa_args(const char *opt, uint64_t *mems, + uint64_t *cpus, int maxentries, int expect_numnodes); + extern int cursor_hide; extern int graphic_rotate; extern int no_quit; diff -r 4271a7547668 -r 6690ab0a34fd vl.c --- a/vl.c Tue Dec 16 12:02:50 2008 +0100 +++ b/vl.c Tue Dec 16 12:13:10 2008 +0100 @@ -222,6 +222,9 @@ int win2k_install_hack = 0; #endif int usb_enabled = 0; int smp_cpus = 1; +int numnumanodes = 0; +uint64_t node_mem[MAX_NODES]; +uint64_t node_to_cpus[MAX_NODES]; const char *vnc_display; int acpi_enabled = 1; int fd_bootchk = 1; @@ -3968,6 +3971,10 @@ static void help(int exitcode) "-daemonize daemonize QEMU after initializing\n" #endif "-option-rom rom load a file, rom, into the option ROM space\n" + "-numa nrnodes[,mem:size1[;size2..]][,cpu:cpu1[;cpu2..]][,pin:node1[;node2]]\n" + " create a multi NUMA node guest and optionally pin it to\n" + " to the given host nodes. If mem and cpu are omitted,\n" + " resources are split equally\n" #ifdef TARGET_SPARC "-prom-env variable=value set OpenBIOS nvram variables\n" #endif @@ -4065,6 +4072,7 @@ enum { QEMU_OPTION_usb, QEMU_OPTION_usbdevice, QEMU_OPTION_smp, + QEMU_OPTION_numa, QEMU_OPTION_vnc, QEMU_OPTION_no_acpi, QEMU_OPTION_curses, @@ -4171,6 +4179,7 @@ static const QEMUOption qemu_options[] = { "win2k-hack", 0, QEMU_OPTION_win2k_hack }, { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice }, { "smp", HAS_ARG, QEMU_OPTION_smp }, + { "numa", HAS_ARG, QEMU_OPTION_numa}, { "vnc", HAS_ARG, QEMU_OPTION_vnc }, #ifdef CONFIG_CURSES { "curses", 0, QEMU_OPTION_curses }, @@ -4456,6 +4465,94 @@ static void termsig_setup(void) } #endif + +#define PARSE_FLAG_BITMASK 1 +#define PARSE_FLAG_SUFFIX 2 + +static int parse_to_array(const char *arg, uint64_t *array, + char delim, int maxentries, int flags) +{ + const char *s; + char *end; + int num = 0; + unsigned long long int val,endval; + + for (s = arg; s != NULL && *s != 0; s++) { + val = strtoull(s, &end, 10); + if (end == s && *s != '*') { + num++; continue; + } + if (num >= maxentries) break; + if (*end == delim && (flags & PARSE_FLAG_SUFFIX)) + val *= 1024 * 1024; + switch (*end) { + case 'g': + case 'G': + if (flags & PARSE_FLAG_SUFFIX) val *= 1024; + /* fall through */ + case 'm': + case 'M': + if (flags & PARSE_FLAG_SUFFIX) val *= 1024; + /* fall through */ + case 'k': + case 'K': + if (flags & PARSE_FLAG_SUFFIX) val *= 1024; + break; + case '*': + val = (unsigned long long int)-1; + break; + case '-': + if (!(flags & PARSE_FLAG_BITMASK)) break; + s = end + 1; + endval = strtoull(s, &end, 10); + val = (1 << (endval + 1)) - (1 << val); + break; + case 0: + if (flags & PARSE_FLAG_SUFFIX) val *= 1024 * 1024; + /* fall through */ + default: + if (flags & PARSE_FLAG_BITMASK) val = 1 << val; + break; + } + array[num++] = val; + if ((s = strchr(end, delim)) == NULL) break; + } + return num; +} + +int parse_numa_args(const char *opt, uint64_t *mems, + uint64_t *cpus, int maxentries, int expect_numnodes) +{ +const char *s; +char *arg, *val, *end, *token; +int num = 0; + + arg = strdup(opt); token = arg; + if (expect_numnodes) { + s = strsep(&token, ","); + if (s == NULL) { + free(arg); + return -1; + } + num = strtol(s, &end, 10); + if (s == end) { + free(arg); + return -1; + } + } + while ((s=strsep(&token, ","))!=NULL) { + if ((val = strchr(s, ':'))) { + *val++ = 0; + if (!strcmp(s, "mem") && mems != NULL) { + parse_to_array(val, mems, ';', maxentries, PARSE_FLAG_SUFFIX); + } else if (!strcmp(s, "cpu") && cpus != NULL) { + parse_to_array(val, cpus, ';', maxentries, PARSE_FLAG_BITMASK); + } + } + } + free(arg); + return num; +} int main(int argc, char **argv, char **envp) { @@ -4556,6 +4653,11 @@ int main(int argc, char **argv, char **e for(i = 1; i < MAX_PARALLEL_PORTS; i++) parallel_devices[i] = NULL; parallel_device_index = 0; + + for(i = 0; i < MAX_NODES; i++) { + node_to_cpus[i] = 0; + node_mem[i] = 0; + } usb_devices_index = 0; @@ -5011,6 +5113,20 @@ int main(int argc, char **argv, char **e exit(1); } break; + case QEMU_OPTION_numa: + if (numnumanodes > 0) + parse_numa_args(optarg, node_mem, + node_to_cpus, MAX_NODES, 0); + else + numnumanodes = parse_numa_args(optarg, + node_mem, node_to_cpus, MAX_NODES, 1); + numnumanodes = parse_numa_args(optarg, + node_mem, node_to_cpus, MAX_NODES, 1); + if (numnumanodes < 0) { + fprintf(stderr, "Invalid number of NUMA nodes\n"); + exit(1); + } + break; case QEMU_OPTION_vnc: vnc_display = optarg; break; @@ -5151,6 +5267,24 @@ int main(int argc, char **argv, char **e monitor_device = "stdio"; } + if (numnumanodes > 0) { + int i; + + if (numnumanodes > smp_cpus) + numnumanodes = smp_cpus; + + for (i = 0; i < numnumanodes; i++) if (node_mem[i] != 0) break; + if (i == numnumanodes) { + for (i = 0; i < numnumanodes; i++) + node_mem[i] = (ram_size / numnumanodes) & ~((1 << 20UL) - 1); + } + for (i = 0; i < numnumanodes; i++) if (node_to_cpus[i] != 0) break; + if (i == numnumanodes) { + for (i = 0; i < smp_cpus; i++) + node_to_cpus[i % numnumanodes] |= 1<