From patchwork Thu Feb 28 04:45:42 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: liguang X-Patchwork-Id: 223775 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 284FE2C0085 for ; Thu, 28 Feb 2013 15:46:41 +1100 (EST) Received: from localhost ([::1]:39192 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UAvOB-0001Bn-3y for incoming@patchwork.ozlabs.org; Wed, 27 Feb 2013 23:46:39 -0500 Received: from eggs.gnu.org ([208.118.235.92]:35144) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UAvNl-00015w-IK for qemu-devel@nongnu.org; Wed, 27 Feb 2013 23:46:17 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UAvNi-0007uR-O8 for qemu-devel@nongnu.org; Wed, 27 Feb 2013 23:46:13 -0500 Received: from [222.73.24.84] (port=16850 helo=song.cn.fujitsu.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UAvNh-0007rM-8F for qemu-devel@nongnu.org; Wed, 27 Feb 2013 23:46:10 -0500 X-IronPort-AV: E=Sophos;i="4.84,753,1355068800"; d="scan'208";a="6784416" Received: from unknown (HELO tang.cn.fujitsu.com) ([10.167.250.3]) by song.cn.fujitsu.com with ESMTP; 28 Feb 2013 12:43:41 +0800 Received: from fnstmail02.fnst.cn.fujitsu.com (tang.cn.fujitsu.com [127.0.0.1]) by tang.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id r1S4k1nh016563; Thu, 28 Feb 2013 12:46:02 +0800 Received: from liguang.fnst.cn.fujitsu.com ([10.167.233.147]) by fnstmail02.fnst.cn.fujitsu.com (Lotus Domino Release 8.5.3) with ESMTP id 2013022812450932-480086 ; Thu, 28 Feb 2013 12:45:09 +0800 From: liguang To: aliguori@us.ibm.com, qemu-devel@nongnu.org Date: Thu, 28 Feb 2013 12:45:42 +0800 Message-Id: <1362026742-27454-1-git-send-email-lig.fnst@cn.fujitsu.com> X-Mailer: git-send-email 1.7.2.5 X-MIMETrack: Itemize by SMTP Server on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2013/02/28 12:45:09, Serialize by Router on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2013/02/28 12:45:09, Serialize complete at 2013/02/28 12:45:09 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 222.73.24.84 Cc: liguang Subject: [Qemu-devel] [PATCH][RFC] vl: move unrelated functions out of vl.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org now, lots of other functions which were not related with mainloop exist in vl.c, e.g. numa related functions (numa_add() ...) bt related functions (bt_parse() ...) usb related functions (usb_parse() ...) gui related functions (gui_update()) system power related functions (qemu_shutdown_requested() ...) ... they can all be moved out of vl.c by function, this patch is only a RFC patch, hope one can help to decide if I can continue to do clean up work. Signed-off-by: liguang --- Makefile.objs | 2 + bt-opts.c | 200 ++++++++++++++++++++++++++++ bt-opts.h | 13 ++ cpus.c | 2 +- hw/pc.c | 10 +- hw/spapr.c | 6 +- include/sysemu/sysemu.h | 1 - monitor.c | 4 +- numa-opts.c | 166 +++++++++++++++++++++++ numa-opts.h | 9 ++ vl.c | 339 +---------------------------------------------- 11 files changed, 406 insertions(+), 346 deletions(-) create mode 100644 bt-opts.c create mode 100644 bt-opts.h create mode 100644 numa-opts.c create mode 100644 numa-opts.h diff --git a/Makefile.objs b/Makefile.objs index a68cdac..4bfc559 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -73,6 +73,8 @@ common-obj-y += bt-host.o bt-vhci.o common-obj-y += dma-helpers.o common-obj-y += vl.o +common-obj-y += numa-opts.o +common-obj-y += bt-opts.o common-obj-$(CONFIG_SLIRP) += slirp/ diff --git a/bt-opts.c b/bt-opts.c new file mode 100644 index 0000000..d34ac62 --- /dev/null +++ b/bt-opts.c @@ -0,0 +1,200 @@ +#include "bt-opts.h" +#include "qemu-common.h" + + +static int nb_hcis; +static int cur_hci; +static struct HCIInfo *hci_table[MAX_NICS]; + +static struct bt_vlan_s { + struct bt_scatternet_s net; + int id; + struct bt_vlan_s *next; +} *first_bt_vlan; + +static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len) +{ +} + +static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr) +{ + return -ENOTSUP; +} + +/* find or alloc a new bluetooth "VLAN" */ +static struct HCIInfo null_hci = { + .cmd_send = null_hci_send, + .sco_send = null_hci_send, + .acl_send = null_hci_send, + .bdaddr_set = null_hci_addr_set, +}; + +struct HCIInfo *qemu_next_hci(void) +{ + if (cur_hci == nb_hcis) { + return &null_hci; + } + + return hci_table[cur_hci++]; +} + +struct HCIInfo *hci_init(const char *str) +{ + char *endp; + struct bt_scatternet_s *vlan = 0; + + if (!strcmp(str, "null")) { + /* null */ + return &null_hci; + } else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':')) { + /* host[:hciN] */ + return bt_host_hci(str[4] ? str + 5 : "hci0"); + } else if (!strncmp(str, "hci", 3)) { + /* hci[,vlan=n] */ + if (str[3]) { + if (!strncmp(str + 3, ",vlan=", 6)) { + vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0)); + if (*endp) { + vlan = 0; + } + } + } else { + vlan = qemu_find_bt_vlan(0); + } + if (vlan) { + return bt_new_hci(vlan); + } + } + + fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str); + + return 0; +} + +static int bt_hci_parse(const char *str) +{ + struct HCIInfo *hci; + bdaddr_t bdaddr; + + if (nb_hcis >= MAX_NICS) { + fprintf(stderr, "qemu: Too many bluetooth HCIs (max %i).\n", MAX_NICS); + return -1; + } + + hci = hci_init(str); + if (!hci) { + return -1; + } + bdaddr.b[0] = 0x52; + bdaddr.b[1] = 0x54; + bdaddr.b[2] = 0x00; + bdaddr.b[3] = 0x12; + bdaddr.b[4] = 0x34; + bdaddr.b[5] = 0x56 + nb_hcis; + hci->bdaddr_set(hci, bdaddr.b); + + hci_table[nb_hcis++] = hci; + + return 0; +} + +static void bt_vhci_add(int vlan_id) +{ + struct bt_scatternet_s *vlan = qemu_find_bt_vlan(vlan_id); + + if (!vlan->slave) { + fprintf(stderr, "qemu: warning: adding a VHCI to " + "an empty scatternet %i\n", vlan_id); + } + + bt_vhci_init(bt_new_hci(vlan)); +} + +static struct bt_device_s *bt_device_add(const char *opt) +{ + struct bt_scatternet_s *vlan; + int vlan_id = 0; + char *endp = strstr(opt, ",vlan="); + int len = (endp ? endp - opt : strlen(opt)) + 1; + char devname[10]; + + pstrcpy(devname, MIN(sizeof(devname), len), opt); + + if (endp) { + vlan_id = strtol(endp + 6, &endp, 0); + if (*endp) { + fprintf(stderr, "qemu: unrecognised bluetooth vlan Id\n"); + return 0; + } + } + + vlan = qemu_find_bt_vlan(vlan_id); + + if (!vlan->slave) { + fprintf(stderr, "qemu: warning: adding a slave device to " + "an empty scatternet %i\n", vlan_id); + } + if (!strcmp(devname, "keyboard")) { + return bt_keyboard_init(vlan); + } + fprintf(stderr, "qemu: unsupported bluetooth device `%s'\n", devname); + return 0; +} + +struct bt_scatternet_s *qemu_find_bt_vlan(int id) +{ + struct bt_vlan_s **pvlan, *vlan; + for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) { + if (vlan->id == id) { + return &vlan->net; + } + } + vlan = g_malloc0(sizeof(struct bt_vlan_s)); + vlan->id = id; + pvlan = &first_bt_vlan; + while (*pvlan != NULL) { + pvlan = &(*pvlan)->next; + } + *pvlan = vlan; + return &vlan->net; +} + +int bt_parse(const char *opt) +{ + const char *endp, *p; + int vlan; + + if (strstart(opt, "hci", &endp)) { + if (!*endp || *endp == ',') { + if (*endp) { + if (!strstart(endp, ",vlan=", 0)) { + opt = endp + 1; + } + } + return bt_hci_parse(opt); + } + } else if (strstart(opt, "vhci", &endp)) { + if (!*endp || *endp == ',') { + if (*endp) { + if (strstart(endp, ",vlan=", &p)) { + vlan = strtol(p, (char **) &endp, 0); + if (*endp) { + fprintf(stderr, "qemu: bad scatternet '%s'\n", p); + return 1; + } + } else { + fprintf(stderr, "qemu: bad parameter '%s'\n", endp + 1); + return 1; + } + } else { + vlan = 0; + } + bt_vhci_add(vlan); + return 0; + } + } else if (strstart(opt, "device:", &endp)) { + return !bt_device_add(endp); + } + fprintf(stderr, "qemu: bad bluetooth parameter '%s'\n", opt); + return 1; +} diff --git a/bt-opts.h b/bt-opts.h new file mode 100644 index 0000000..fcd80c1 --- /dev/null +++ b/bt-opts.h @@ -0,0 +1,13 @@ +#ifndef BT_OPTS_H +#define BT_OPTS_H + +#include "net/net.h" +#include "bt/bt.h" +#include "hw/bt.h" + +int bt_parse(const char *opt); +struct HCIInfo *hci_init(const char *str); +struct bt_scatternet_s *qemu_find_bt_vlan(int id); + + +#endif diff --git a/cpus.c b/cpus.c index c4b021d..9f05390 100644 --- a/cpus.c +++ b/cpus.c @@ -1167,7 +1167,7 @@ void set_numa_modes(void) for (env = first_cpu; env != NULL; env = env->next_cpu) { cpu = ENV_GET_CPU(env); - for (i = 0; i < nb_numa_nodes; i++) { + for (i = 0; i < get_nr_numa_nodes(); i++) { if (test_bit(cpu->cpu_index, node_cpumask[i])) { cpu->numa_node = i; } diff --git a/hw/pc.c b/hw/pc.c index 07caba7..6ea9452 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -606,23 +606,23 @@ static void *bochs_bios_init(void) * of nodes, one word for each VCPU->node and one word for each node to * hold the amount of memory. */ - numa_fw_cfg = g_new0(uint64_t, 1 + apic_id_limit + nb_numa_nodes); - numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes); + numa_fw_cfg = g_new0(uint64_t, 1 + apic_id_limit + get_nr_numa_nodes()); + numa_fw_cfg[0] = cpu_to_le64(get_nr_numa_nodes()); for (i = 0; i < max_cpus; i++) { unsigned int apic_id = x86_cpu_apic_id_from_index(i); assert(apic_id < apic_id_limit); - for (j = 0; j < nb_numa_nodes; j++) { + for (j = 0; j < get_nr_numa_nodes(); j++) { if (test_bit(i, node_cpumask[j])) { numa_fw_cfg[apic_id + 1] = cpu_to_le64(j); break; } } } - for (i = 0; i < nb_numa_nodes; i++) { + for (i = 0; i < get_nr_numa_nodes(); i++) { numa_fw_cfg[apic_id_limit + 1 + i] = cpu_to_le64(node_mem[i]); } fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg, - (1 + apic_id_limit + nb_numa_nodes) * + (1 + apic_id_limit + get_nr_numa_nodes()) * sizeof(*numa_fw_cfg)); return fw_cfg; diff --git a/hw/spapr.c b/hw/spapr.c index e88a27a..43777f8 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -162,7 +162,7 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr) return offset; } - if (nb_numa_nodes > 1) { + if (get_nr_numa_nodes() > 1) { ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity, sizeof(associativity)); if (ret < 0) { @@ -453,7 +453,7 @@ static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt) int i, off; /* memory node(s) */ - node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size; + node0_size = (get_nr_numa_nodes() > 1) ? node_mem[0] : ram_size; if (spapr->rma_size > node0_size) { spapr->rma_size = node0_size; } @@ -486,7 +486,7 @@ static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt) /* RAM: Node 1 and beyond */ mem_start = node0_size; - for (i = 1; i < nb_numa_nodes; i++) { + for (i = 1; i < get_nr_numa_nodes(); i++) { mem_reg_property[0] = cpu_to_be64(mem_start); mem_reg_property[1] = cpu_to_be64(node_mem[i]); associativity[3] = associativity[4] = cpu_to_be32(i); diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index b19ec95..1375f3b 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -128,7 +128,6 @@ extern QEMUClock *rtc_clock; #define MAX_NODES 64 #define MAX_CPUMASK_BITS 255 -extern int nb_numa_nodes; extern uint64_t node_mem[MAX_NODES]; extern unsigned long *node_cpumask[MAX_NODES]; diff --git a/monitor.c b/monitor.c index 32a6e74..1893766 100644 --- a/monitor.c +++ b/monitor.c @@ -1772,8 +1772,8 @@ static void do_info_numa(Monitor *mon, const QDict *qdict) CPUArchState *env; CPUState *cpu; - monitor_printf(mon, "%d nodes\n", nb_numa_nodes); - for (i = 0; i < nb_numa_nodes; i++) { + monitor_printf(mon, "%d nodes\n", get_nr_numa_nodes()); + for (i = 0; i < get_nr_numa_nodes(); i++) { monitor_printf(mon, "node %d cpus:", i); for (env = first_cpu; env != NULL; env = env->next_cpu) { cpu = ENV_GET_CPU(env); diff --git a/numa-opts.c b/numa-opts.c new file mode 100644 index 0000000..ae87c2d --- /dev/null +++ b/numa-opts.c @@ -0,0 +1,166 @@ +#include "numa-opts.h" +#include "sysemu/sysemu.h" +#include "qemu-common.h" +#include "qemu/bitmap.h" +#include "exec/cpu-common.h" + +extern ram_addr_t ram_size; + +static int nr_numa_nodes; +uint64_t node_mem[MAX_NODES]; +unsigned long *node_cpumask[MAX_NODES]; + +int get_nr_numa_nodes(void) +{ + return nr_numa_nodes; +} + +void set_nr_numa_nodes(int nr) +{ + nr_numa_nodes = nr; +} + +static void numa_node_parse_cpus(int nodenr, const char *cpus) +{ + char *endptr; + unsigned long long value, endvalue; + + /* Empty CPU range strings will be considered valid, they will simply + * not set any bit in the CPU bitmap. + */ + if (!*cpus) { + return; + } + + if (parse_uint(cpus, &value, &endptr, 10) < 0) { + goto error; + } + if (*endptr == '-') { + if (parse_uint_full(endptr + 1, &endvalue, 10) < 0) { + goto error; + } + } else if (*endptr == '\0') { + endvalue = value; + } else { + goto error; + } + + if (endvalue >= MAX_CPUMASK_BITS) { + endvalue = MAX_CPUMASK_BITS - 1; + fprintf(stderr, + "qemu: NUMA: A max of %d VCPUs are supported\n", + MAX_CPUMASK_BITS); + } + + if (endvalue < value) { + goto error; + } + + bitmap_set(node_cpumask[nodenr], value, endvalue-value+1); + return; + +error: + fprintf(stderr, "qemu: Invalid NUMA CPU range: %s\n", cpus); + exit(1); +} + + + +void numa_add(const char *optarg) +{ + char option[128]; + char *endptr; + unsigned long long nodenr; + + optarg = get_opt_name(option, 128, optarg, ','); + if (*optarg == ',') { + optarg++; + } + if (!strcmp(option, "node")) { + + if (nr_numa_nodes >= MAX_NODES) { + fprintf(stderr, "qemu: too many NUMA nodes\n"); + exit(1); + } + + if (get_param_value(option, 128, "nodeid", optarg) == 0) { + nodenr = nr_numa_nodes; + } else { + if (parse_uint_full(option, &nodenr, 10) < 0) { + fprintf(stderr, "qemu: Invalid NUMA nodeid: %s\n", option); + exit(1); + } + } + + if (nodenr >= MAX_NODES) { + fprintf(stderr, "qemu: invalid NUMA nodeid: %llu\n", nodenr); + exit(1); + } + + if (get_param_value(option, 128, "mem", optarg) == 0) { + node_mem[nodenr] = 0; + } else { + int64_t sval; + sval = strtosz(option, &endptr); + if (sval < 0 || *endptr) { + fprintf(stderr, "qemu: invalid numa mem size: %s\n", optarg); + exit(1); + } + node_mem[nodenr] = sval; + } + if (get_param_value(option, 128, "cpus", optarg) != 0) { + numa_node_parse_cpus(nodenr, option); + } + nr_numa_nodes++; + } else { + fprintf(stderr, "Invalid -numa option: %s\n", option); + exit(1); + } +} + +void numa_assignment(void) +{ + int i = 0; + + if (nr_numa_nodes > 0) { + if (nr_numa_nodes > MAX_NODES) { + nr_numa_nodes = MAX_NODES; + } + + /* If no memory size if given for any node, assume the default case + * and distribute the available memory equally across all nodes + */ + for (i = 0; i < nr_numa_nodes; i++) { + if (node_mem[i] != 0) { + break; + } + } + if (i == nr_numa_nodes) { + uint64_t usedmem = 0; + + /* On Linux, the each node's border has to be 8MB aligned, + * the final node gets the rest. + */ + for (i = 0; i < nr_numa_nodes - 1; i++) { + node_mem[i] = (ram_size / nr_numa_nodes) & ~((1 << 23UL) - 1); + usedmem += node_mem[i]; + } + node_mem[i] = ram_size - usedmem; + } + + for (i = 0; i < nr_numa_nodes; i++) { + if (!bitmap_empty(node_cpumask[i], MAX_CPUMASK_BITS)) { + break; + } + } + /* assigning the VCPUs round-robin is easier to implement, guest OSes + * must cope with this anyway, because there are BIOSes out there in + * real machines which also use this scheme. + */ + if (i == nr_numa_nodes) { + for (i = 0; i < max_cpus; i++) { + set_bit(i, node_cpumask[i % nr_numa_nodes]); + } + } + } +} diff --git a/numa-opts.h b/numa-opts.h new file mode 100644 index 0000000..9accea3 --- /dev/null +++ b/numa-opts.h @@ -0,0 +1,9 @@ +#ifndef NUMA_OPTS_H +#define NUMA_OPTS_H + +int get_nr_numa_nodes(void); +void set_nr_numa_nodes(int nr); +void numa_add(const char *optarg); +void numa_assignment(void); + +#endif diff --git a/vl.c b/vl.c index febd2ea..4e6606f 100644 --- a/vl.c +++ b/vl.c @@ -170,6 +170,9 @@ int main(int argc, char **argv) #include "ui/qemu-spice.h" #include "qapi/string-input-visitor.h" +#include "numa-opts.h" +#include "bt-opts.h" + //#define DEBUG_NET //#define DEBUG_SLIRP @@ -248,10 +251,6 @@ struct FWBootEntry { static QTAILQ_HEAD(, FWBootEntry) fw_boot_order = QTAILQ_HEAD_INITIALIZER(fw_boot_order); -int nb_numa_nodes; -uint64_t node_mem[MAX_NODES]; -unsigned long *node_cpumask[MAX_NODES]; - uint8_t qemu_uuid[16]; static QEMUBootSetHandler *boot_set_handler; @@ -769,197 +768,6 @@ static void configure_rtc(QemuOpts *opts) } } -/***********************************************************/ -/* Bluetooth support */ -static int nb_hcis; -static int cur_hci; -static struct HCIInfo *hci_table[MAX_NICS]; - -static struct bt_vlan_s { - struct bt_scatternet_s net; - int id; - struct bt_vlan_s *next; -} *first_bt_vlan; - -/* find or alloc a new bluetooth "VLAN" */ -static struct bt_scatternet_s *qemu_find_bt_vlan(int id) -{ - struct bt_vlan_s **pvlan, *vlan; - for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) { - if (vlan->id == id) - return &vlan->net; - } - vlan = g_malloc0(sizeof(struct bt_vlan_s)); - vlan->id = id; - pvlan = &first_bt_vlan; - while (*pvlan != NULL) - pvlan = &(*pvlan)->next; - *pvlan = vlan; - return &vlan->net; -} - -static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len) -{ -} - -static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr) -{ - return -ENOTSUP; -} - -static struct HCIInfo null_hci = { - .cmd_send = null_hci_send, - .sco_send = null_hci_send, - .acl_send = null_hci_send, - .bdaddr_set = null_hci_addr_set, -}; - -struct HCIInfo *qemu_next_hci(void) -{ - if (cur_hci == nb_hcis) - return &null_hci; - - return hci_table[cur_hci++]; -} - -static struct HCIInfo *hci_init(const char *str) -{ - char *endp; - struct bt_scatternet_s *vlan = 0; - - if (!strcmp(str, "null")) - /* null */ - return &null_hci; - else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':')) - /* host[:hciN] */ - return bt_host_hci(str[4] ? str + 5 : "hci0"); - else if (!strncmp(str, "hci", 3)) { - /* hci[,vlan=n] */ - if (str[3]) { - if (!strncmp(str + 3, ",vlan=", 6)) { - vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0)); - if (*endp) - vlan = 0; - } - } else - vlan = qemu_find_bt_vlan(0); - if (vlan) - return bt_new_hci(vlan); - } - - fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str); - - return 0; -} - -static int bt_hci_parse(const char *str) -{ - struct HCIInfo *hci; - bdaddr_t bdaddr; - - if (nb_hcis >= MAX_NICS) { - fprintf(stderr, "qemu: Too many bluetooth HCIs (max %i).\n", MAX_NICS); - return -1; - } - - hci = hci_init(str); - if (!hci) - return -1; - - bdaddr.b[0] = 0x52; - bdaddr.b[1] = 0x54; - bdaddr.b[2] = 0x00; - bdaddr.b[3] = 0x12; - bdaddr.b[4] = 0x34; - bdaddr.b[5] = 0x56 + nb_hcis; - hci->bdaddr_set(hci, bdaddr.b); - - hci_table[nb_hcis++] = hci; - - return 0; -} - -static void bt_vhci_add(int vlan_id) -{ - struct bt_scatternet_s *vlan = qemu_find_bt_vlan(vlan_id); - - if (!vlan->slave) - fprintf(stderr, "qemu: warning: adding a VHCI to " - "an empty scatternet %i\n", vlan_id); - - bt_vhci_init(bt_new_hci(vlan)); -} - -static struct bt_device_s *bt_device_add(const char *opt) -{ - struct bt_scatternet_s *vlan; - int vlan_id = 0; - char *endp = strstr(opt, ",vlan="); - int len = (endp ? endp - opt : strlen(opt)) + 1; - char devname[10]; - - pstrcpy(devname, MIN(sizeof(devname), len), opt); - - if (endp) { - vlan_id = strtol(endp + 6, &endp, 0); - if (*endp) { - fprintf(stderr, "qemu: unrecognised bluetooth vlan Id\n"); - return 0; - } - } - - vlan = qemu_find_bt_vlan(vlan_id); - - if (!vlan->slave) - fprintf(stderr, "qemu: warning: adding a slave device to " - "an empty scatternet %i\n", vlan_id); - - if (!strcmp(devname, "keyboard")) - return bt_keyboard_init(vlan); - - fprintf(stderr, "qemu: unsupported bluetooth device `%s'\n", devname); - return 0; -} - -static int bt_parse(const char *opt) -{ - const char *endp, *p; - int vlan; - - if (strstart(opt, "hci", &endp)) { - if (!*endp || *endp == ',') { - if (*endp) - if (!strstart(endp, ",vlan=", 0)) - opt = endp + 1; - - return bt_hci_parse(opt); - } - } else if (strstart(opt, "vhci", &endp)) { - if (!*endp || *endp == ',') { - if (*endp) { - if (strstart(endp, ",vlan=", &p)) { - vlan = strtol(p, (char **) &endp, 0); - if (*endp) { - fprintf(stderr, "qemu: bad scatternet '%s'\n", p); - return 1; - } - } else { - fprintf(stderr, "qemu: bad parameter '%s'\n", endp + 1); - return 1; - } - } else - vlan = 0; - - bt_vhci_add(vlan); - return 0; - } - } else if (strstart(opt, "device:", &endp)) - return !bt_device_add(endp); - - fprintf(stderr, "qemu: bad bluetooth parameter '%s'\n", opt); - return 1; -} - static int parse_sandbox(QemuOpts *opts, void *opaque) { /* FIXME: change this to true for 1.3 */ @@ -1244,102 +1052,6 @@ char *get_boot_devices_list(size_t *size) return list; } -static void numa_node_parse_cpus(int nodenr, const char *cpus) -{ - char *endptr; - unsigned long long value, endvalue; - - /* Empty CPU range strings will be considered valid, they will simply - * not set any bit in the CPU bitmap. - */ - if (!*cpus) { - return; - } - - if (parse_uint(cpus, &value, &endptr, 10) < 0) { - goto error; - } - if (*endptr == '-') { - if (parse_uint_full(endptr + 1, &endvalue, 10) < 0) { - goto error; - } - } else if (*endptr == '\0') { - endvalue = value; - } else { - goto error; - } - - if (endvalue >= MAX_CPUMASK_BITS) { - endvalue = MAX_CPUMASK_BITS - 1; - fprintf(stderr, - "qemu: NUMA: A max of %d VCPUs are supported\n", - MAX_CPUMASK_BITS); - } - - if (endvalue < value) { - goto error; - } - - bitmap_set(node_cpumask[nodenr], value, endvalue-value+1); - return; - -error: - fprintf(stderr, "qemu: Invalid NUMA CPU range: %s\n", cpus); - exit(1); -} - -static void numa_add(const char *optarg) -{ - char option[128]; - char *endptr; - unsigned long long nodenr; - - optarg = get_opt_name(option, 128, optarg, ','); - if (*optarg == ',') { - optarg++; - } - if (!strcmp(option, "node")) { - - if (nb_numa_nodes >= MAX_NODES) { - fprintf(stderr, "qemu: too many NUMA nodes\n"); - exit(1); - } - - if (get_param_value(option, 128, "nodeid", optarg) == 0) { - nodenr = nb_numa_nodes; - } else { - if (parse_uint_full(option, &nodenr, 10) < 0) { - fprintf(stderr, "qemu: Invalid NUMA nodeid: %s\n", option); - exit(1); - } - } - - if (nodenr >= MAX_NODES) { - fprintf(stderr, "qemu: invalid NUMA nodeid: %llu\n", nodenr); - exit(1); - } - - if (get_param_value(option, 128, "mem", optarg) == 0) { - node_mem[nodenr] = 0; - } else { - int64_t sval; - sval = strtosz(option, &endptr); - if (sval < 0 || *endptr) { - fprintf(stderr, "qemu: invalid numa mem size: %s\n", optarg); - exit(1); - } - node_mem[nodenr] = sval; - } - if (get_param_value(option, 128, "cpus", optarg) != 0) { - numa_node_parse_cpus(nodenr, option); - } - nb_numa_nodes++; - } else { - fprintf(stderr, "Invalid -numa option: %s\n", option); - exit(1); - } -} - static void smp_parse(const char *optarg) { int smp, sockets = 0, threads = 0, cores = 0; @@ -2892,7 +2604,7 @@ int main(int argc, char **argv, char **envp) node_cpumask[i] = bitmap_new(MAX_CPUMASK_BITS); } - nb_numa_nodes = 0; + set_nr_numa_nodes(0); nb_nics = 0; autostart= 1; @@ -4141,48 +3853,7 @@ int main(int argc, char **argv, char **envp) register_savevm_live(NULL, "ram", 0, 4, &savevm_ram_handlers, NULL); - if (nb_numa_nodes > 0) { - int i; - - if (nb_numa_nodes > MAX_NODES) { - nb_numa_nodes = MAX_NODES; - } - - /* If no memory size if given for any node, assume the default case - * and distribute the available memory equally across all nodes - */ - for (i = 0; i < nb_numa_nodes; i++) { - if (node_mem[i] != 0) - break; - } - if (i == nb_numa_nodes) { - uint64_t usedmem = 0; - - /* On Linux, the each node's border has to be 8MB aligned, - * the final node gets the rest. - */ - for (i = 0; i < nb_numa_nodes - 1; i++) { - node_mem[i] = (ram_size / nb_numa_nodes) & ~((1 << 23UL) - 1); - usedmem += node_mem[i]; - } - node_mem[i] = ram_size - usedmem; - } - - for (i = 0; i < nb_numa_nodes; i++) { - if (!bitmap_empty(node_cpumask[i], MAX_CPUMASK_BITS)) { - break; - } - } - /* assigning the VCPUs round-robin is easier to implement, guest OSes - * must cope with this anyway, because there are BIOSes out there in - * real machines which also use this scheme. - */ - if (i == nb_numa_nodes) { - for (i = 0; i < max_cpus; i++) { - set_bit(i, node_cpumask[i % nb_numa_nodes]); - } - } - } + numa_assignment(); if (qemu_opts_foreach(qemu_find_opts("mon"), mon_init_func, NULL, 1) != 0) { exit(1);