diff options
author | Avi Kivity <avi@redhat.com> | 2009-09-09 12:08:52 +0300 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-09-09 12:08:52 +0300 |
commit | ea571d06d8e39187663f255d62b886bf01371667 (patch) | |
tree | 2662790614ecc0e6bdc9541aa2550388f9a7e34e | |
parent | Merge commit 'fd83e9b9dc7adac8244c613e0a51baa4610bb46d' into upstream-merge (diff) | |
parent | Support for multiple -monitor devices (diff) | |
download | qemu-kvm-ea571d06d8e39187663f255d62b886bf01371667.tar.gz qemu-kvm-ea571d06d8e39187663f255d62b886bf01371667.tar.bz2 qemu-kvm-ea571d06d8e39187663f255d62b886bf01371667.zip |
Merge commit 'ddd9bbd93bb2c12ade72dff1790d6d292aac073f' into upstream-merge
* commit 'ddd9bbd93bb2c12ade72dff1790d6d292aac073f':
Support for multiple -monitor devices
net: Fix send queue ordering
do not issue ioctl from within the io thread
Delay sighandler_setup()
Remove typedef for bool from eepro100.c
add documentation for multi-core features
piix3: use new vmstate infrastructure
i440fx: use new vmstate infrastructure
VMState: Fix sub-structs versioning
Update SaveVM versions
pci_irq_levels[] belong to PIIX3State
Save irq_state into PCII440FXState
Conflicts:
vl.c
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | hw/eepro100.c | 3 | ||||
-rw-r--r-- | hw/piix_pci.c | 81 | ||||
-rw-r--r-- | net.c | 29 | ||||
-rw-r--r-- | net.h | 5 | ||||
-rw-r--r-- | qemu-options.hx | 14 | ||||
-rw-r--r-- | savevm.c | 2 | ||||
-rw-r--r-- | vl.c | 92 |
7 files changed, 143 insertions, 83 deletions
diff --git a/hw/eepro100.c b/hw/eepro100.c index c374931dc..68fec9c99 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -38,6 +38,7 @@ #endif #include <stddef.h> /* offsetof */ +#include <stdbool.h> #include "hw.h" #include "pci.h" #include "net.h" @@ -109,8 +110,6 @@ #define INT_MASK 0x0100 #define DRVR_INT 0x0200 /* Driver generated interrupt. */ -typedef unsigned char bool; - /* Offsets to the various registers. All accesses need not be longword aligned. */ enum speedo_offsets { diff --git a/hw/piix_pci.c b/hw/piix_pci.c index a289a16bb..669a34fdc 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -37,6 +37,7 @@ typedef PCIHostState I440FXState; typedef struct PIIX3State { PCIDevice dev; + int pci_irq_levels[4]; } PIIX3State; typedef struct PIIX3IrqState { @@ -48,6 +49,7 @@ struct PCII440FXState { PCIDevice dev; target_phys_addr_t isa_page_descs[384 / 4]; uint8_t smm_enabled; + PIIX3IrqState *irq_state; }; static void i440fx_addr_writel(void* opaque, uint32_t addr, uint32_t val) @@ -74,8 +76,6 @@ static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) return (irq_num + slot_addend) & 3; } -static int pci_irq_levels[4]; - static void update_pam(PCII440FXState *d, uint32_t start, uint32_t end, int r) { uint32_t addr; @@ -160,38 +160,46 @@ static void i440fx_write_config(PCIDevice *dev, i440fx_update_memory_mappings(d); } -static void i440fx_save(QEMUFile* f, void *opaque) -{ - PCII440FXState *d = opaque; - int i; - - pci_device_save(&d->dev, f); - qemu_put_8s(f, &d->smm_enabled); - - for (i = 0; i < 4; i++) - qemu_put_be32(f, pci_irq_levels[i]); -} - -static int i440fx_load(QEMUFile* f, void *opaque, int version_id) +static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id) { PCII440FXState *d = opaque; int ret, i; - if (version_id > 2) - return -EINVAL; ret = pci_device_load(&d->dev, f); if (ret < 0) return ret; i440fx_update_memory_mappings(d); qemu_get_8s(f, &d->smm_enabled); - if (version_id >= 2) + if (version_id == 2) for (i = 0; i < 4; i++) - pci_irq_levels[i] = qemu_get_be32(f); + d->irq_state->piix3->pci_irq_levels[i] = qemu_get_be32(f); return 0; } +static int i440fx_after_load(void *opaque) +{ + PCII440FXState *d = opaque; + + i440fx_update_memory_mappings(d); + return 0; +} + +static const VMStateDescription vmstate_i440fx = { + .name = "I440FX", + .version_id = 3, + .minimum_version_id = 3, + .minimum_version_id_old = 1, + .load_state_old = i440fx_load_old, + .run_after_load = i440fx_after_load, + .fields = (VMStateField []) { + VMSTATE_PCI_DEVICE(dev, PCII440FXState), + VMSTATE_UINT8(smm_enabled, PCII440FXState), + VMSTATE_END_OF_LIST() + } +}; + static int i440fx_pcihost_initfn(SysBusDevice *dev) { I440FXState *s = FROM_SYSBUS(I440FXState, dev); @@ -220,7 +228,7 @@ static int i440fx_initfn(PCIDevice *dev) d->dev.config[0x72] = 0x02; /* SMRAM */ - register_savevm("I440FX", 0, 2, i440fx_save, i440fx_load, d); + vmstate_register(0, &vmstate_i440fx, d); return 0; } @@ -244,6 +252,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq * d = pci_create_simple(b, 0, "i440FX"); *pi440fx_state = DO_UPCAST(PCII440FXState, dev, d); + (*pi440fx_state)->irq_state = irq_state; irq_state->piix3 = DO_UPCAST(PIIX3State, dev, pci_create_simple(b, -1, "PIIX3")); @@ -261,7 +270,7 @@ static void piix3_set_irq(void *opaque, int irq_num, int level) int i, pic_irq, pic_level; PIIX3IrqState *irq_state = opaque; - pci_irq_levels[irq_num] = level; + irq_state->piix3->pci_irq_levels[irq_num] = level; /* now we change the pic irq level according to the piix irq mappings */ /* XXX: optimize */ @@ -272,7 +281,7 @@ static void piix3_set_irq(void *opaque, int irq_num, int level) pic_level = 0; for (i = 0; i < 4; i++) { if (pic_irq == irq_state->piix3->dev.config[0x60 + i]) - pic_level |= pci_irq_levels[i]; + pic_level |= irq_state->piix3->pci_irq_levels[i]; } qemu_set_irq(irq_state->pic[pic_irq], pic_level); } @@ -325,22 +334,20 @@ static void piix3_reset(void *opaque) pci_conf[0xac] = 0x00; pci_conf[0xae] = 0x00; - memset(pci_irq_levels, 0, sizeof(pci_irq_levels)); -} - -static void piix_save(QEMUFile* f, void *opaque) -{ - PCIDevice *d = opaque; - pci_device_save(d, f); + memset(d->pci_irq_levels, 0, sizeof(d->pci_irq_levels)); } -static int piix_load(QEMUFile* f, void *opaque, int version_id) -{ - PCIDevice *d = opaque; - if (version_id != 2) - return -EINVAL; - return pci_device_load(d, f); -} +static const VMStateDescription vmstate_piix3 = { + .name = "PIIX3", + .version_id = 3, + .minimum_version_id = 2, + .minimum_version_id_old = 2, + .fields = (VMStateField []) { + VMSTATE_PCI_DEVICE(dev, PIIX3State), + VMSTATE_INT32_ARRAY_V(pci_irq_levels, PIIX3State, 4, 3), + VMSTATE_END_OF_LIST() + } +}; static int piix3_initfn(PCIDevice *dev) { @@ -348,7 +355,7 @@ static int piix3_initfn(PCIDevice *dev) uint8_t *pci_conf; isa_bus_new(&d->dev.qdev); - register_savevm("PIIX3", 0, 2, piix_save, piix_load, d); + vmstate_register(0, &vmstate_piix3, d); pci_conf = d->dev.config; pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL); @@ -441,34 +441,29 @@ qemu_deliver_packet(VLANClientState *sender, const uint8_t *buf, int size, int r void qemu_purge_queued_packets(VLANClientState *vc) { - VLANPacket **pp = &vc->vlan->send_queue; - - while (*pp != NULL) { - VLANPacket *packet = *pp; + VLANPacket *packet, *next; + TAILQ_FOREACH_SAFE(packet, &vc->vlan->send_queue, entry, next) { if (packet->sender == vc) { - *pp = packet->next; + TAILQ_REMOVE(&vc->vlan->send_queue, packet, entry); qemu_free(packet); - } else { - pp = &packet->next; } } } void qemu_flush_queued_packets(VLANClientState *vc) { - VLANPacket *packet; - - while ((packet = vc->vlan->send_queue) != NULL) { + while (!TAILQ_EMPTY(&vc->vlan->send_queue)) { + VLANPacket *packet; int ret; - vc->vlan->send_queue = packet->next; + packet = TAILQ_FIRST(&vc->vlan->send_queue); + TAILQ_REMOVE(&vc->vlan->send_queue, packet, entry); ret = qemu_deliver_packet(packet->sender, packet->data, packet->size, packet->raw); if (ret == 0 && packet->sent_cb != NULL) { - packet->next = vc->vlan->send_queue; - vc->vlan->send_queue = packet; + TAILQ_INSERT_HEAD(&vc->vlan->send_queue, packet, entry); break; } @@ -486,13 +481,13 @@ static void qemu_enqueue_packet(VLANClientState *sender, VLANPacket *packet; packet = qemu_malloc(sizeof(VLANPacket) + size); - packet->next = sender->vlan->send_queue; packet->sender = sender; packet->size = size; packet->raw = raw; packet->sent_cb = sent_cb; memcpy(packet->data, buf, size); - sender->vlan->send_queue = packet; + + TAILQ_INSERT_TAIL(&sender->vlan->send_queue, packet, entry); } static ssize_t qemu_send_packet_async2(VLANClientState *sender, @@ -616,7 +611,6 @@ static ssize_t qemu_enqueue_packet_iov(VLANClientState *sender, max_len = calc_iov_length(iov, iovcnt); packet = qemu_malloc(sizeof(VLANPacket) + max_len); - packet->next = sender->vlan->send_queue; packet->sender = sender; packet->sent_cb = sent_cb; packet->size = 0; @@ -629,7 +623,7 @@ static ssize_t qemu_enqueue_packet_iov(VLANClientState *sender, packet->size += len; } - sender->vlan->send_queue = packet; + TAILQ_INSERT_TAIL(&sender->vlan->send_queue, packet, entry); return packet->size; } @@ -2501,6 +2495,7 @@ VLANState *qemu_find_vlan(int id, int allocate) } vlan = qemu_mallocz(sizeof(VLANState)); vlan->id = id; + TAILQ_INIT(&vlan->send_queue); vlan->next = NULL; pvlan = &first_vlan; while (*pvlan != NULL) @@ -1,6 +1,7 @@ #ifndef QEMU_NET_H #define QEMU_NET_H +#include "sys-queue.h" #include "qemu-common.h" /* VLANs support */ @@ -38,7 +39,7 @@ typedef struct VLANPacket VLANPacket; typedef void (NetPacketSent) (VLANClientState *, ssize_t); struct VLANPacket { - struct VLANPacket *next; + TAILQ_ENTRY(VLANPacket) entry; VLANClientState *sender; int size; int raw; @@ -51,7 +52,7 @@ struct VLANState { VLANClientState *first_client; struct VLANState *next; unsigned int nb_guest_devs, nb_host_devs; - VLANPacket *send_queue; + TAILQ_HEAD(send_queue, VLANPacket) send_queue; int delivering; }; diff --git a/qemu-options.hx b/qemu-options.hx index c1ec97681..f2e602ab4 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -39,15 +39,23 @@ Select CPU model (-cpu ? for list and additional feature selection) ETEXI DEF("smp", HAS_ARG, QEMU_OPTION_smp, - "-smp n[,maxcpus=cpus]\n" + "-smp n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets]\n" " set the number of CPUs to 'n' [default=1]\n" " maxcpus= maximum number of total cpus, including\n" - " offline CPUs for hotplug etc.\n") + " offline CPUs for hotplug etc.\n" + " cores= number of CPU cores on one socket\n" + " threads= number of threads on one CPU core\n" + " sockets= number of discrete sockets in the system\n") STEXI -@item -smp @var{n} +@item -smp @var{n}[,cores=@var{cores}][,threads=@var{threads}][,sockets=@var{sockets}][,maxcpus=@var{maxcpus}] Simulate an SMP system with @var{n} CPUs. On the PC target, up to 255 CPUs are supported. On Sparc32 target, Linux limits the number of usable CPUs to 4. +For the PC target, the number of @var{cores} per socket, the number +of @var{threads} per cores and the total number of @var{sockets} can be +specified. Missing values will be computed. If any on the three values is +given, the total number of CPUs @var{n} can be omitted. @var{maxcpus} +specifies the maximum number of hotpluggable CPUs. ETEXI DEF("numa", HAS_ARG, QEMU_OPTION_numa, @@ -1048,7 +1048,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, void *addr = base_addr + field->size * i; if (field->flags & VMS_STRUCT) { - ret = vmstate_load_state(f, field->vmsd, addr, version_id); + ret = vmstate_load_state(f, field->vmsd, addr, field->vmsd->version_id); } else { ret = field->info->get(f, addr, field->size); @@ -175,6 +175,9 @@ int main(int argc, char **argv) #define DEFAULT_RAM_SIZE 128 +/* Maximum number of monitor devices */ +#define MAX_MONITOR_DEVICES 10 + static const char *data_dir; const char *bios_name = NULL; /* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available @@ -3803,6 +3806,7 @@ static void *kvm_cpu_thread_fn(void *arg) block_io_signals(); qemu_thread_self(env->thread); + kvm_init_vcpu(env); /* signal CPU creation */ qemu_mutex_lock(&qemu_global_mutex); @@ -3998,7 +4002,6 @@ static void tcg_init_vcpu(void *_env) static void kvm_start_vcpu(CPUState *env) { - kvm_init_vcpu(env); env->thread = qemu_mallocz(sizeof(QemuThread)); env->halt_cond = qemu_mallocz(sizeof(QemuCond)); qemu_cond_init(env->halt_cond); @@ -4916,8 +4919,9 @@ int main(int argc, char **argv, char **envp) QemuOpts *hda_opts = NULL, *opts; int optind; const char *r, *optarg; - CharDriverState *monitor_hd = NULL; - const char *monitor_device; + CharDriverState *monitor_hds[MAX_MONITOR_DEVICES]; + const char *monitor_devices[MAX_MONITOR_DEVICES]; + int monitor_device_index; const char *serial_devices[MAX_SERIAL_PORTS]; int serial_device_index; const char *parallel_devices[MAX_PARALLEL_PORTS]; @@ -4986,7 +4990,6 @@ int main(int argc, char **argv, char **envp) kernel_cmdline = ""; cyls = heads = secs = 0; translation = BIOS_ATA_TRANSLATION_AUTO; - monitor_device = "vc:80Cx24C"; serial_devices[0] = "vc:80Cx24C"; for(i = 1; i < MAX_SERIAL_PORTS; i++) @@ -5002,6 +5005,12 @@ int main(int argc, char **argv, char **envp) virtio_consoles[i] = NULL; virtio_console_index = 0; + monitor_devices[0] = "vc:80Cx24C"; + for (i = 1; i < MAX_MONITOR_DEVICES; i++) { + monitor_devices[i] = NULL; + } + monitor_device_index = 0; + for (i = 0; i < MAX_NODES; i++) { node_mem[i] = 0; node_cpumask[i] = 0; @@ -5416,7 +5425,12 @@ int main(int argc, char **argv, char **envp) break; } case QEMU_OPTION_monitor: - monitor_device = optarg; + if (monitor_device_index >= MAX_MONITOR_DEVICES) { + fprintf(stderr, "qemu: too many monitor devices\n"); + exit(1); + } + monitor_devices[monitor_device_index] = optarg; + monitor_device_index++; break; case QEMU_OPTION_serial: if (serial_device_index >= MAX_SERIAL_PORTS) { @@ -5775,8 +5789,9 @@ int main(int argc, char **argv, char **envp) serial_devices[0] = "stdio"; if (parallel_device_index == 0) parallel_devices[0] = "null"; - if (strncmp(monitor_device, "vc", 2) == 0) - monitor_device = "stdio"; + if (strncmp(monitor_devices[0], "vc", 2) == 0) { + monitor_devices[0] = "stdio"; + } } #ifndef _WIN32 @@ -5935,20 +5950,15 @@ int main(int argc, char **argv, char **envp) register_savevm("timer", 0, 2, timer_save, timer_load, NULL); register_savevm_live("ram", 0, 3, ram_save_live, NULL, ram_load, NULL); -#ifndef _WIN32 - /* must be after terminal init, SDL library changes signal handlers */ - sighandler_setup(); -#endif - /* Maintain compatibility with multiple stdio monitors */ - if (!strcmp(monitor_device,"stdio")) { + if (!strcmp(monitor_devices[0],"stdio")) { for (i = 0; i < MAX_SERIAL_PORTS; i++) { const char *devname = serial_devices[i]; if (devname && !strcmp(devname,"mon:stdio")) { - monitor_device = NULL; + monitor_devices[0] = NULL; break; } else if (devname && !strcmp(devname,"stdio")) { - monitor_device = NULL; + monitor_devices[0] = NULL; serial_devices[i] = "mon:stdio"; break; } @@ -5997,14 +6007,44 @@ int main(int argc, char **argv, char **envp) } } - if (monitor_device) { - monitor_hd = qemu_chr_open("monitor", monitor_device, NULL); - if (!monitor_hd) { - fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device); + if (kvm_enabled()) { + int ret; + + ret = kvm_init(smp_cpus); + if (ret < 0) { + fprintf(stderr, "failed to initialize KVM\n"); + exit(1); + } + } + + if (kvm_enabled()) { + int ret; + + ret = kvm_init(smp_cpus); + if (ret < 0) { + fprintf(stderr, "failed to initialize KVM\n"); exit(1); } } + for (i = 0; i < MAX_MONITOR_DEVICES; i++) { + const char *devname = monitor_devices[i]; + if (devname && strcmp(devname, "none")) { + char label[32]; + if (i == 0) { + snprintf(label, sizeof(label), "monitor"); + } else { + snprintf(label, sizeof(label), "monitor%d", i); + } + monitor_hds[i] = qemu_chr_open(label, devname, NULL); + if (!monitor_hds[i]) { + fprintf(stderr, "qemu: could not open monitor device '%s'\n", + devname); + exit(1); + } + } + } + for(i = 0; i < MAX_SERIAL_PORTS; i++) { const char *devname = serial_devices[i]; if (devname && strcmp(devname, "none")) { @@ -6062,6 +6102,11 @@ int main(int argc, char **argv, char **envp) kernel_filename, kernel_cmdline, initrd_filename, cpu_model); +#ifndef _WIN32 + /* must be after terminal init, SDL library changes signal handlers */ + sighandler_setup(); +#endif + for (env = first_cpu; env != NULL; env = env->next_cpu) { for (i = 0; i < nb_numa_nodes; i++) { if (node_cpumask[i] & (1 << env->cpu_index)) { @@ -6145,8 +6190,13 @@ int main(int argc, char **argv, char **envp) text_consoles_set_display(display_state); qemu_chr_initial_reset(); - if (monitor_device && monitor_hd) - monitor_init(monitor_hd, MONITOR_USE_READLINE | MONITOR_IS_DEFAULT); + for (i = 0; i < MAX_MONITOR_DEVICES; i++) { + if (monitor_devices[i] && monitor_hds[i]) { + monitor_init(monitor_hds[i], + MONITOR_USE_READLINE | + ((i == 0) ? MONITOR_IS_DEFAULT : 0)); + } + } for(i = 0; i < MAX_SERIAL_PORTS; i++) { const char *devname = serial_devices[i]; |