Message ID | 1362026742-27454-1-git-send-email-lig.fnst@cn.fujitsu.com |
---|---|
State | New |
Headers | show |
Hi, Anthony is it reasonable split? 在 2013-02-28四的 12:45 +0800,liguang写道: > 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 <lig.fnst@cn.fujitsu.com> > --- > 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);
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);
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 <lig.fnst@cn.fujitsu.com> --- 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