aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-09-09 12:08:52 +0300
committerAvi Kivity <avi@redhat.com>2009-09-09 12:08:52 +0300
commitea571d06d8e39187663f255d62b886bf01371667 (patch)
tree2662790614ecc0e6bdc9541aa2550388f9a7e34e
parentMerge commit 'fd83e9b9dc7adac8244c613e0a51baa4610bb46d' into upstream-merge (diff)
parentSupport for multiple -monitor devices (diff)
downloadqemu-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.c3
-rw-r--r--hw/piix_pci.c81
-rw-r--r--net.c29
-rw-r--r--net.h5
-rw-r--r--qemu-options.hx14
-rw-r--r--savevm.c2
-rw-r--r--vl.c92
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);
diff --git a/net.c b/net.c
index e414b349c..4ccf1387e 100644
--- a/net.c
+++ b/net.c
@@ -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)
diff --git a/net.h b/net.h
index b172691be..57ab031bf 100644
--- a/net.h
+++ b/net.h
@@ -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,
diff --git a/savevm.c b/savevm.c
index dd176a5c3..22331ea86 100644
--- a/savevm.c
+++ b/savevm.c
@@ -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);
diff --git a/vl.c b/vl.c
index 3485ce63d..cb934206e 100644
--- a/vl.c
+++ b/vl.c
@@ -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];