diff options
author | Avi Kivity <avi@redhat.com> | 2009-08-29 10:36:54 +0300 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-08-29 10:36:54 +0300 |
commit | 1a20533f56f5e2c0e2f4507205bf4acb0f669a43 (patch) | |
tree | 7799aa18f7dba660def0cd5c29869816a99f2ea6 | |
parent | Merge commit 'b31a0277558db5eeb71164ad511467cf5125b853' into upstream-merge (diff) | |
parent | Add isa_reserve_irq(). (diff) | |
download | qemu-kvm-1a20533f56f5e2c0e2f4507205bf4acb0f669a43.tar.gz qemu-kvm-1a20533f56f5e2c0e2f4507205bf4acb0f669a43.tar.bz2 qemu-kvm-1a20533f56f5e2c0e2f4507205bf4acb0f669a43.zip |
Merge commit '3a38d437ca60ce19ee92dbabbe6e672e9ba3c529' into upstream-merge
* commit '3a38d437ca60ce19ee92dbabbe6e672e9ba3c529':
Add isa_reserve_irq().
isa bus irq changes and fixes.
hw/eepro100.c: Use extended TBD only where applicable
pci-hotplug: initialize dinfo to NULL in pci_device_hot_add
block/vdi.c: Fix several bugs
introduce kvm64 CPU
allow overriding of CPUID level on command line
set CPUID bits to present cores and threads topology
push CPUID level to 4 to allow Intel multicore decoding
extend -smp parsing to include cores= and threads= options
add file descriptor migration
Add sparse to new feature convention
Conflicts:
hw/pc.c
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | Makefile.target | 4 | ||||
-rw-r--r-- | block/vdi.c | 13 | ||||
-rwxr-xr-x | configure | 19 | ||||
-rw-r--r-- | cpu-defs.h | 2 | ||||
-rw-r--r-- | hw/cs4231a.c | 12 | ||||
-rw-r--r-- | hw/eepro100.c | 6 | ||||
-rw-r--r-- | hw/fdc.c | 47 | ||||
-rw-r--r-- | hw/fdc.h | 9 | ||||
-rw-r--r-- | hw/hw.h | 1 | ||||
-rw-r--r-- | hw/ide.c | 7 | ||||
-rw-r--r-- | hw/isa-bus.c | 91 | ||||
-rw-r--r-- | hw/isa.h | 5 | ||||
-rw-r--r-- | hw/mips_jazz.c | 2 | ||||
-rw-r--r-- | hw/mips_malta.c | 2 | ||||
-rw-r--r-- | hw/pc.c | 34 | ||||
-rw-r--r-- | hw/pci-hotplug.c | 2 | ||||
-rw-r--r-- | hw/ppc_prep.c | 2 | ||||
-rw-r--r-- | hw/sb16.c | 25 | ||||
-rw-r--r-- | hw/sun4u.c | 2 | ||||
-rw-r--r-- | migration-fd.c | 137 | ||||
-rw-r--r-- | migration.c | 4 | ||||
-rw-r--r-- | migration.h | 7 | ||||
-rw-r--r-- | savevm.c | 28 | ||||
-rw-r--r-- | target-i386/helper.c | 97 | ||||
-rw-r--r-- | vl.c | 66 |
26 files changed, 516 insertions, 110 deletions
@@ -110,7 +110,7 @@ obj-y += qdev.o qdev-properties.o ssi.o obj-$(CONFIG_BRLAPI) += baum.o obj-$(CONFIG_WIN32) += tap-win32.o -obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o +obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS) diff --git a/Makefile.target b/Makefile.target index 0c20ca2d9..80932eb8f 100644 --- a/Makefile.target +++ b/Makefile.target @@ -303,7 +303,7 @@ obj-arm-y += arm-semi.o obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o obj-arm-y += pflash_cfi01.o gumstix.o -obj-arm-y += zaurus.o ide.o serial.o spitz.o tosa.o tc6393xb.o +obj-arm-y += zaurus.o ide.o isa-bus.o serial.o spitz.o tosa.o tc6393xb.o obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o obj-arm-y += omap2.o omap_dss.o soc_dma.o obj-arm-y += omap_sx1.o palm.o tsc210x.o @@ -317,7 +317,7 @@ obj-arm-y += syborg_virtio.o obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o serial.o -obj-sh4-y += ide.o +obj-sh4-y += ide.o isa-bus.o obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o obj-m68k-y += m68k-semi.o dummy_m68k.o diff --git a/block/vdi.c b/block/vdi.c index 4ca8dcb7d..c9c8890f5 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -437,9 +437,9 @@ static int vdi_open(BlockDriverState *bs, const char *filename, int flags) s->header = header; bmap_size = header.blocks_in_image * sizeof(uint32_t); - s->bmap = qemu_malloc(bmap_size); - if (bdrv_read(s->hd, s->bmap_sector, - (uint8_t *)s->bmap, bmap_size / SECTOR_SIZE) < 0) { + bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE; + s->bmap = qemu_malloc(bmap_size * SECTOR_SIZE); + if (bdrv_read(s->hd, s->bmap_sector, (uint8_t *)s->bmap, bmap_size) < 0) { goto fail_free_bmap; } @@ -817,7 +817,9 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options) #endif #if defined(CONFIG_VDI_STATIC_IMAGE) } else if (!strcmp(options->name, BLOCK_OPT_STATIC)) { - image_type = VDI_TYPE_STATIC; + if (options->value.n) { + image_type = VDI_TYPE_STATIC; + } #endif } options++; @@ -845,6 +847,9 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options) header.disk_size = bytes; header.block_size = block_size; header.blocks_in_image = blocks; + if (image_type == VDI_TYPE_STATIC) { + header.blocks_allocated = blocks; + } uuid_generate(header.uuid_image); uuid_generate(header.uuid_last_snap); /* There is no need to set header.uuid_link or header.uuid_parent here. */ @@ -196,6 +196,7 @@ fdt="" kvm="" nptl="" sdl="" +sparse="no" vde="" vnc_tls="" vnc_sasl="" @@ -204,7 +205,6 @@ xen="" gprof="no" debug_tcg="no" debug="no" -sparse="no" strip_opt="yes" bigendian="no" mingw32="no" @@ -719,10 +719,6 @@ echo "NOTE: The object files are built at the place where configure is launched" exit 1 fi -if test ! -x "$(which cgcc 2>/dev/null)"; then - sparse="no" -fi - # # Solaris specific configure tool chain decisions # @@ -1000,6 +996,19 @@ EOF fi ########################################## +# Sparse probe +if test "$sparse" != "no" ; then + if test -x "$(which cgcc 2>/dev/null)"; then + sparse=yes + else + if test "$sparse" = "yes" ; then + feature_not_found "sparse" + fi + sparse=no + fi +fi + +########################################## # SDL probe sdl_too_old=no diff --git a/cpu-defs.h b/cpu-defs.h index 1cd9a1504..a7d6d94e4 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -194,6 +194,8 @@ struct KVMCPUState { int cpu_index; /* CPU index (informative) */ \ uint32_t host_tid; /* host thread ID */ \ int numa_node; /* NUMA node this cpu is belonging to */ \ + int nr_cores; /* number of cores within this CPU package */ \ + int nr_threads;/* number of threads within this CPU */ \ int running; /* Nonzero if cpu is currently running(usermode). */ \ int thread_id; \ /* user data */ \ diff --git a/hw/cs4231a.c b/hw/cs4231a.c index 5516867ab..d482e04ac 100644 --- a/hw/cs4231a.c +++ b/hw/cs4231a.c @@ -60,10 +60,9 @@ static struct { typedef struct CSState { QEMUSoundCard card; - qemu_irq *pic; + qemu_irq pic; uint32_t regs[CS_REGS]; uint8_t dregs[CS_DREGS]; - int irq; int dma; int port; int shift; @@ -483,7 +482,7 @@ IO_WRITE_PROTO (cs_write) case Alternate_Feature_Status: if ((s->dregs[iaddr] & PI) && !(val & PI)) { /* XXX: TI CI */ - qemu_irq_lower (s->pic[s->irq]); + qemu_irq_lower (s->pic); s->regs[Status] &= ~INT; } s->dregs[iaddr] = val; @@ -503,7 +502,7 @@ IO_WRITE_PROTO (cs_write) case Status: if (s->regs[Status] & INT) { - qemu_irq_lower (s->pic[s->irq]); + qemu_irq_lower (s->pic); } s->regs[Status] &= ~INT; s->dregs[Alternate_Feature_Status] &= ~(PI | CI | TI); @@ -588,7 +587,7 @@ static int cs_dma_read (void *opaque, int nchan, int dma_pos, int dma_len) s->regs[Status] |= INT; s->dregs[Alternate_Feature_Status] |= PI; s->transferred = 0; - qemu_irq_raise (s->pic[s->irq]); + qemu_irq_raise (s->pic); } else { s->transferred += written; @@ -643,8 +642,7 @@ int cs4231a_init (qemu_irq *pic) s = qemu_mallocz (sizeof (*s)); - s->pic = pic; - s->irq = conf.irq; + s->pic = isa_reserve_irq(conf.irq); s->dma = conf.dma; s->port = conf.port; diff --git a/hw/eepro100.c b/hw/eepro100.c index 8988b3f94..199026443 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -715,8 +715,8 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) } else { /* Flexible mode. */ uint8_t tbd_count = 0; - if (!(s->configuration[6] & BIT(4))) { - /* Extended TCB. */ + if ((s->device >= i82558B) && !(s->configuration[6] & BIT(4))) { + /* Extended Flexible TCB. */ assert(tcb_bytes == 0); for (; tbd_count < 2; tbd_count++) { uint32_t tx_buffer_address = ldl_phys(tbd_address); @@ -724,7 +724,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) uint16_t tx_buffer_el = lduw_phys(tbd_address + 6); tbd_address += 8; logout - ("TBD (extended mode): buffer address 0x%08x, size 0x%04x\n", + ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n", tx_buffer_address, tx_buffer_size); cpu_physical_memory_read(tx_buffer_address, &buf[size], tx_buffer_size); @@ -1871,33 +1871,42 @@ static void fdctrl_connect_drives(fdctrl_t *fdctrl, BlockDriverState **fds) } } -fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped, - target_phys_addr_t io_base, - BlockDriverState **fds) +fdctrl_t *fdctrl_init_isa(int isairq, int dma_chann, + uint32_t io_base, + BlockDriverState **fds) { fdctrl_t *fdctrl; + ISADevice *dev; - if (mem_mapped) { - DeviceState *dev; - fdctrl_sysbus_t *sys; + dev = isa_create_simple("isa-fdc", io_base, 0); + fdctrl = &(DO_UPCAST(fdctrl_isabus_t, busdev, dev)->state); + isa_connect_irq(dev, 0, isairq); - dev = qdev_create(NULL, "sysbus-fdc"); - qdev_init(dev); - sys = DO_UPCAST(fdctrl_sysbus_t, busdev.qdev, dev); - fdctrl = &sys->state; - sysbus_connect_irq(&sys->busdev, 0, irq); - sysbus_mmio_map(&sys->busdev, 0, io_base); - } else { - ISADevice *dev; + fdctrl->dma_chann = dma_chann; + DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl); - dev = isa_create_simple("isa-fdc", io_base, 0); - fdctrl = &(DO_UPCAST(fdctrl_isabus_t, busdev, dev)->state); - isa_connect_irq(dev, 0, irq); - } + fdctrl_connect_drives(fdctrl, fds); + + return fdctrl; +} + +fdctrl_t *fdctrl_init_sysbus(qemu_irq irq, int dma_chann, + target_phys_addr_t mmio_base, + BlockDriverState **fds) +{ + fdctrl_t *fdctrl; + DeviceState *dev; + fdctrl_sysbus_t *sys; + + dev = qdev_create(NULL, "sysbus-fdc"); + qdev_init(dev); + sys = DO_UPCAST(fdctrl_sysbus_t, busdev.qdev, dev); + fdctrl = &sys->state; + sysbus_connect_irq(&sys->busdev, 0, irq); + sysbus_mmio_map(&sys->busdev, 0, mmio_base); fdctrl->dma_chann = dma_chann; DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl); - fdctrl_connect_drives(fdctrl, fds); return fdctrl; @@ -3,9 +3,12 @@ typedef struct fdctrl_t fdctrl_t; -fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped, - target_phys_addr_t io_base, - BlockDriverState **fds); +fdctrl_t *fdctrl_init_isa(int isairq, int dma_chann, + uint32_t io_base, + BlockDriverState **fds); +fdctrl_t *fdctrl_init_sysbus(qemu_irq irq, int dma_chann, + target_phys_addr_t mmio_base, + BlockDriverState **fds); fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base, BlockDriverState **fds, qemu_irq *fdc_tc); int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num); @@ -49,6 +49,7 @@ QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, QEMUFileRateLimit *rate_limit, QEMUFileSetRateLimit *set_rate_limit); QEMUFile *qemu_fopen(const char *filename, const char *mode); +QEMUFile *qemu_fdopen(int fd, const char *mode); QEMUFile *qemu_fopen_socket(int fd); QEMUFile *qemu_popen(FILE *popen_file, const char *mode); QEMUFile *qemu_popen_cmd(const char *command, const char *mode); @@ -3610,8 +3610,8 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn, pci_register_bar((PCIDevice *)d, 4, 0x10, PCI_ADDRESS_SPACE_IO, bmdma_map); - ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]); - ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]); + ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], isa_reserve_irq(14)); + ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], isa_reserve_irq(15)); ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6); ide_init_ioport(&d->ide_if[2], 0x170, 0x376); @@ -3650,6 +3650,9 @@ void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn, pci_register_bar((PCIDevice *)d, 4, 0x10, PCI_ADDRESS_SPACE_IO, bmdma_map); + /* + * These should call isa_reserve_irq() instead when MIPS supports it + */ ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]); ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]); ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6); diff --git a/hw/isa-bus.c b/hw/isa-bus.c index 315efbbec..9561c3112 100644 --- a/hw/isa-bus.c +++ b/hw/isa-bus.c @@ -18,17 +18,24 @@ */ #include "hw.h" #include "sysemu.h" +#include "monitor.h" +#include "sysbus.h" #include "isa.h" struct ISABus { BusState qbus; + qemu_irq *irqs; + uint32_t assigned; }; static ISABus *isabus; +static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent); + static struct BusInfo isa_bus_info = { - .name = "ISA", - .size = sizeof(ISABus), - .props = (Property[]) { + .name = "ISA", + .size = sizeof(ISABus), + .print_dev = isabus_dev_print, + .props = (Property[]) { DEFINE_PROP_HEX32("iobase", ISADevice, iobase[0], -1), DEFINE_PROP_HEX32("iobase2", ISADevice, iobase[1], -1), DEFINE_PROP_END_OF_LIST(), @@ -41,16 +48,53 @@ ISABus *isa_bus_new(DeviceState *dev) fprintf(stderr, "Can't create a second ISA bus\n"); return NULL; } + if (NULL == dev) { + dev = qdev_create(NULL, "isabus-bridge"); + qdev_init(dev); + } isabus = FROM_QBUS(ISABus, qbus_create(&isa_bus_info, dev, NULL)); return isabus; } -void isa_connect_irq(ISADevice *dev, int n, qemu_irq irq) +void isa_bus_irqs(qemu_irq *irqs) +{ + isabus->irqs = irqs; +} + +void isa_connect_irq(ISADevice *dev, int devnr, int isairq) { - assert(n >= 0 && n < dev->nirqs); - if (dev->irqs[n]) - *dev->irqs[n] = irq; + assert(devnr >= 0 && devnr < dev->nirqs); + if (isabus->assigned & (1 << isairq)) { + fprintf(stderr, "isa irq %d already assigned\n", isairq); + exit(1); + } + if (dev->irqs[devnr]) { + isabus->assigned |= (1 << isairq); + dev->isairq[devnr] = isairq; + *dev->irqs[devnr] = isabus->irqs[isairq]; + } +} + +/* + * isa_reserve_irq() reserves the ISA irq and returns the corresponding + * qemu_irq entry for the i8259. + * + * This function is only for special cases such as the 'ferr', and + * temporary use for normal devices until they are converted to qdev. + */ +qemu_irq isa_reserve_irq(int isairq) +{ + if (isairq < 0 || isairq > 15) { + fprintf(stderr, "isa irq %d invalid\n", isairq); + exit(1); + } + if (isabus->assigned & (1 << isairq)) { + fprintf(stderr, "isa irq %d already assigned\n", isairq); + exit(1); + } + isabus->assigned |= (1 << isairq); + return isabus->irqs[isairq]; } void isa_init_irq(ISADevice *dev, qemu_irq *p) @@ -65,6 +109,8 @@ static void isa_qdev_init(DeviceState *qdev, DeviceInfo *base) ISADevice *dev = DO_UPCAST(ISADevice, qdev, qdev); ISADeviceInfo *info = DO_UPCAST(ISADeviceInfo, qdev, base); + dev->isairq[0] = -1; + dev->isairq[1] = -1; info->init(dev); } @@ -91,3 +137,34 @@ ISADevice *isa_create_simple(const char *name, uint32_t iobase, uint32_t iobase2 qdev_init(dev); return isa; } + +static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent) +{ + ISADevice *d = DO_UPCAST(ISADevice, qdev, dev); + + if (d->isairq[1] != -1) { + monitor_printf(mon, "%*sisa irqs %d,%d\n", indent, "", + d->isairq[0], d->isairq[1]); + } else if (d->isairq[0] != -1) { + monitor_printf(mon, "%*sisa irq %d\n", indent, "", + d->isairq[0]); + } +} + +static void isabus_bridge_init(SysBusDevice *dev) +{ + /* nothing */ +} + +static SysBusDeviceInfo isabus_bridge_info = { + .init = isabus_bridge_init, + .qdev.name = "isabus-bridge", + .qdev.size = sizeof(SysBusDevice), +}; + +static void isabus_register_devices(void) +{ + sysbus_register_withprop(&isabus_bridge_info); +} + +device_init(isabus_register_devices) @@ -13,6 +13,7 @@ typedef struct ISADeviceInfo ISADeviceInfo; struct ISADevice { DeviceState qdev; uint32_t iobase[2]; + uint32_t isairq[2]; qemu_irq *irqs[2]; int nirqs; }; @@ -24,7 +25,9 @@ struct ISADeviceInfo { }; ISABus *isa_bus_new(DeviceState *dev); -void isa_connect_irq(ISADevice *dev, int n, qemu_irq irq); +void isa_bus_irqs(qemu_irq *irqs); +void isa_connect_irq(ISADevice *dev, int devirq, int isairq); +qemu_irq isa_reserve_irq(int isairq); void isa_init_irq(ISADevice *dev, qemu_irq *p); void isa_qdev_register(ISADeviceInfo *info); ISADevice *isa_create_simple(const char *name, uint32_t iobase, uint32_t iobase2); diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index 9740d728c..1cbd947fe 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -238,7 +238,7 @@ void mips_jazz_init (ram_addr_t ram_size, DriveInfo *dinfo = drive_get(IF_FLOPPY, 0, n); fds[n] = dinfo ? dinfo->bdrv : NULL; } - fdctrl_init(rc4030[1], 0, 1, 0x80003000, fds); + fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds); /* Real time clock */ rtc_init(0x70, i8259[8], 1980); diff --git a/hw/mips_malta.c b/hw/mips_malta.c index d8fa26437..6d4145035 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -929,7 +929,7 @@ void mips_malta_init (ram_addr_t ram_size, dinfo = drive_get(IF_FLOPPY, 0, i); fd[i] = dinfo ? dinfo->bdrv : NULL; } - floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd); + floppy_controller = fdctrl_init_isa(6, 2, 0x3f0, fd); /* Sound card */ #ifdef HAS_AUDIO @@ -1047,13 +1047,14 @@ static void audio_init (PCIBus *pci_bus, qemu_irq *pic) } #endif -static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic) +static void pc_init_ne2k_isa(NICInfo *nd) { static int nb_ne2k = 0; if (nb_ne2k == NE2000_NB_MAX) return; - isa_ne2000_init(ne2000_io[nb_ne2k], pic[ne2000_irq[nb_ne2k]], nd); + isa_ne2000_init(ne2000_io[nb_ne2k], + isa_reserve_irq(ne2000_irq[nb_ne2k]), nd); nb_ne2k++; } @@ -1294,14 +1295,17 @@ static void pc_init1(ram_addr_t ram_size, isa_irq_state->i8259 = i8259; isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24); } - ferr_irq = isa_irq[13]; if (pci_enabled) { pci_bus = i440fx_init(&i440fx_state, isa_irq); piix3_devfn = piix3_init(pci_bus, -1); } else { pci_bus = NULL; + isa_bus_new(NULL); } + isa_bus_irqs(isa_irq); + + ferr_irq = isa_reserve_irq(13); /* init basic PC hardware */ register_ioport_write(0x80, 1, 1, ioport80_write, NULL); @@ -1327,7 +1331,7 @@ static void pc_init1(ram_addr_t ram_size, } } - rtc_state = rtc_init(0x70, isa_irq[8], 2000); + rtc_state = rtc_init(0x70, isa_reserve_irq(8), 2000); qemu_register_boot_set(pc_boot_set, rtc_state); @@ -1339,10 +1343,10 @@ static void pc_init1(ram_addr_t ram_size, } #ifdef USE_KVM_PIT if (kvm_enabled() && qemu_kvm_pit_in_kernel()) - pit = kvm_pit_init(0x40, isa_irq[0]); + pit = kvm_pit_init(0x40, isa_reserve_irq(0)); else #endif - pit = pit_init(0x40, isa_irq[0]); + pit = pit_init(0x40, isa_reserve_irq(0)); pcspk_init(pit); if (!no_hpet) { hpet_init(isa_irq); @@ -1350,14 +1354,14 @@ static void pc_init1(ram_addr_t ram_size, for(i = 0; i < MAX_SERIAL_PORTS; i++) { if (serial_hds[i]) { - serial_init(serial_io[i], isa_irq[serial_irq[i]], 115200, + serial_init(serial_io[i], isa_reserve_irq(serial_irq[i]), 115200, serial_hds[i]); } } for(i = 0; i < MAX_PARALLEL_PORTS; i++) { if (parallel_hds[i]) { - parallel_init(parallel_io[i], isa_irq[parallel_irq[i]], + parallel_init(parallel_io[i], isa_reserve_irq(parallel_irq[i]), parallel_hds[i]); } } @@ -1368,7 +1372,7 @@ static void pc_init1(ram_addr_t ram_size, NICInfo *nd = &nd_table[i]; if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0)) - pc_init_ne2k_isa(nd, isa_irq); + pc_init_ne2k_isa(nd); else pci_nic_init(nd, "e1000", NULL); } @@ -1389,14 +1393,15 @@ static void pc_init1(ram_addr_t ram_size, pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, isa_irq); } else { for(i = 0; i < MAX_IDE_BUS; i++) { - isa_ide_init(ide_iobase[i], ide_iobase2[i], isa_irq[ide_irq[i]], + isa_ide_init(ide_iobase[i], ide_iobase2[i], + isa_reserve_irq(ide_irq[i]), hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); } } isa_dev = isa_create_simple("i8042", 0x60, 0x64); - isa_connect_irq(isa_dev, 0, isa_irq[1]); - isa_connect_irq(isa_dev, 1, isa_irq[12]); + isa_connect_irq(isa_dev, 0, 1); + isa_connect_irq(isa_dev, 1, 12); DMA_init(0); #ifdef HAS_AUDIO audio_init(pci_enabled ? pci_bus : NULL, isa_irq); @@ -1406,7 +1411,7 @@ static void pc_init1(ram_addr_t ram_size, dinfo = drive_get(IF_FLOPPY, 0, i); fd[i] = dinfo ? dinfo->bdrv : NULL; } - floppy_controller = fdctrl_init(isa_irq[6], 2, 0, 0x3f0, fd); + floppy_controller = fdctrl_init_isa(6, 2, 0x3f0, fd); cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd); @@ -1419,7 +1424,8 @@ static void pc_init1(ram_addr_t ram_size, i2c_bus *smbus; /* TODO: Populate SPD eeprom data. */ - smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, isa_irq[9]); + smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, + isa_reserve_irq(9)); for (i = 0; i < 8; i++) { DeviceState *eeprom; eeprom = qdev_create((BusState *)smbus, "smbus-eeprom"); diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index 69ee92a13..206239109 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -100,7 +100,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, const char *opts) { PCIDevice *dev; - DriveInfo *dinfo; + DriveInfo *dinfo = NULL; int type = -1; char buf[128]; diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 223ca6193..7665cb7dd 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -719,7 +719,7 @@ static void ppc_prep_init (ram_addr_t ram_size, dinfo = drive_get(IF_FLOPPY, 0, i); fd[i] = dinfo ? dinfo->bdrv : NULL; } - fdctrl_init(i8259[6], 2, 0, 0x3f0, fd); + fdctrl_init_isa(6, 2, 0x3f0, fd); /* Register speaker port */ register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL); @@ -56,7 +56,7 @@ static struct { typedef struct SB16State { QEMUSoundCard card; - qemu_irq *pic; + qemu_irq pic; int irq; int dma; int hdma; @@ -190,7 +190,7 @@ static void aux_timer (void *opaque) { SB16State *s = opaque; s->can_write = 1; - qemu_irq_raise (s->pic[s->irq]); + qemu_irq_raise (s->pic); } #define DMA8_AUTO 1 @@ -598,7 +598,7 @@ static void command (SB16State *s, uint8_t cmd) case 0xf3: dsp_out_data (s, 0xaa); s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2; - qemu_irq_raise (s->pic[s->irq]); + qemu_irq_raise (s->pic); break; case 0xf9: @@ -766,7 +766,7 @@ static void complete (SB16State *s) bytes = samples << s->fmt_stereo << (s->fmt_bits == 16); ticks = (bytes * ticks_per_sec) / freq; if (ticks < ticks_per_sec / 1024) { - qemu_irq_raise (s->pic[s->irq]); + qemu_irq_raise (s->pic); } else { if (s->aux_ts) { @@ -858,10 +858,10 @@ static void legacy_reset (SB16State *s) static void reset (SB16State *s) { - qemu_irq_lower (s->pic[s->irq]); + qemu_irq_lower (s->pic); if (s->dma_auto) { - qemu_irq_raise (s->pic[s->irq]); - qemu_irq_lower (s->pic[s->irq]); + qemu_irq_raise (s->pic); + qemu_irq_lower (s->pic); } s->mixer_regs[0x82] = 0; @@ -897,7 +897,7 @@ static IO_WRITE_PROTO (dsp_write) if (s->v2x6 == 1) { if (0 && s->highspeed) { s->highspeed = 0; - qemu_irq_lower (s->pic[s->irq]); + qemu_irq_lower (s->pic); control (s, 0); } else { @@ -1008,7 +1008,7 @@ static IO_READ_PROTO (dsp_read) if (s->mixer_regs[0x82] & 1) { ack = 1; s->mixer_regs[0x82] &= 1; - qemu_irq_lower (s->pic[s->irq]); + qemu_irq_lower (s->pic); } break; @@ -1017,7 +1017,7 @@ static IO_READ_PROTO (dsp_read) if (s->mixer_regs[0x82] & 2) { ack = 1; s->mixer_regs[0x82] &= 2; - qemu_irq_lower (s->pic[s->irq]); + qemu_irq_lower (s->pic); } break; @@ -1231,7 +1231,7 @@ static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len) if (s->left_till_irq <= 0) { s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1; - qemu_irq_raise (s->pic[s->irq]); + qemu_irq_raise (s->pic); if (0 == s->dma_auto) { control (s, 0); speaker (s, 0); @@ -1408,8 +1408,7 @@ int SB16_init (qemu_irq *pic) s = qemu_mallocz (sizeof (*s)); s->cmd = -1; - s->pic = pic; - s->irq = conf.irq; + s->pic = isa_reserve_irq(conf.irq); s->dma = conf.dma; s->hdma = conf.hdma; s->port = conf.port; diff --git a/hw/sun4u.c b/hw/sun4u.c index bc832557d..09027e2f9 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -618,7 +618,7 @@ static void sun4uv_init(ram_addr_t RAM_size, dinfo = drive_get(IF_FLOPPY, 0, i); fd[i] = dinfo ? dinfo->bdrv : NULL; } - floppy_controller = fdctrl_init(NULL/*6*/, 2, 0, 0x3f0, fd); + floppy_controller = fdctrl_init_isa(6, 2, 0x3f0, fd); nvram = m48t59_init(NULL/*8*/, 0, 0x0074, NVRAM_SIZE, 59); initrd_size = 0; diff --git a/migration-fd.c b/migration-fd.c new file mode 100644 index 000000000..15b44158f --- /dev/null +++ b/migration-fd.c @@ -0,0 +1,137 @@ +/* + * QEMU live migration via generic fd + * + * Copyright Red Hat, Inc. 2009 + * + * Authors: + * Chris Lalancette <clalance@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include "qemu-common.h" +#include "qemu_socket.h" +#include "migration.h" +#include "monitor.h" +#include "qemu-char.h" +#include "sysemu.h" +#include "buffered_file.h" +#include "block.h" +#include "qemu_socket.h" + +//#define DEBUG_MIGRATION_FD + +#ifdef DEBUG_MIGRATION_FD +#define dprintf(fmt, ...) \ + do { printf("migration-fd: " fmt, ## __VA_ARGS__); } while (0) +#else +#define dprintf(fmt, ...) \ + do { } while (0) +#endif + +static int fd_errno(FdMigrationState *s) +{ + return errno; +} + +static int fd_write(FdMigrationState *s, const void * buf, size_t size) +{ + return write(s->fd, buf, size); +} + +static int fd_close(FdMigrationState *s) +{ + dprintf("fd_close\n"); + if (s->fd != -1) { + close(s->fd); + s->fd = -1; + } + return 0; +} + +MigrationState *fd_start_outgoing_migration(Monitor *mon, + const char *fdname, + int64_t bandwidth_limit, + int detach) +{ + FdMigrationState *s; + + s = qemu_mallocz(sizeof(*s)); + + s->fd = monitor_get_fd(mon, fdname); + if (s->fd == -1) { + dprintf("fd_migration: invalid file descriptor identifier\n"); + goto err_after_alloc; + } + + if (fcntl(s->fd, F_SETFL, O_NONBLOCK) == -1) { + dprintf("Unable to set nonblocking mode on file descriptor\n"); + goto err_after_open; + } + + s->get_error = fd_errno; + s->write = fd_write; + s->close = fd_close; + s->mig_state.cancel = migrate_fd_cancel; + s->mig_state.get_status = migrate_fd_get_status; + s->mig_state.release = migrate_fd_release; + + s->state = MIG_STATE_ACTIVE; + s->mon_resume = NULL; + s->bandwidth_limit = bandwidth_limit; + + if (!detach) + migrate_fd_monitor_suspend(s); + + migrate_fd_connect(s); + return &s->mig_state; + +err_after_open: + close(s->fd); +err_after_alloc: + qemu_free(s); + return NULL; +} + +static void fd_accept_incoming_migration(void *opaque) +{ + QEMUFile *f = opaque; + int ret; + + ret = qemu_loadvm_state(f); + if (ret < 0) { + fprintf(stderr, "load of migration failed\n"); + goto err; + } + qemu_announce_self(); + dprintf("successfully loaded vm state\n"); + /* we've successfully migrated, close the fd */ + qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL); + if (autostart) + vm_start(); + +err: + qemu_fclose(f); +} + +int fd_start_incoming_migration(const char *infd) +{ + int fd; + QEMUFile *f; + + dprintf("Attempting to start an incoming migration via fd\n"); + + fd = strtol(infd, NULL, 0); + f = qemu_fdopen(fd, "rb"); + if(f == NULL) { + dprintf("Unable to apply qemu wrapper to file descriptor\n"); + return -errno; + } + + qemu_set_fd_handler2(fd, NULL, fd_accept_incoming_migration, NULL, + (void *)(unsigned long)f); + + return 0; +} diff --git a/migration.c b/migration.c index 34e2bc14c..c18d59584 100644 --- a/migration.c +++ b/migration.c @@ -45,6 +45,8 @@ void qemu_start_incoming_migration(const char *uri) exec_start_incoming_migration(p); else if (strstart(uri, "unix:", &p)) unix_start_incoming_migration(p); + else if (strstart(uri, "fd:", &p)) + fd_start_incoming_migration(p); #endif else fprintf(stderr, "unknown migration protocol: %s\n", uri); @@ -62,6 +64,8 @@ void do_migrate(Monitor *mon, int detach, const char *uri) s = exec_start_outgoing_migration(p, max_throttle, detach); else if (strstart(uri, "unix:", &p)) s = unix_start_outgoing_migration(p, max_throttle, detach); + else if (strstart(uri, "fd:", &p)) + s = fd_start_outgoing_migration(mon, p, max_throttle, detach); #endif else monitor_printf(mon, "unknown migration protocol: %s\n", uri); diff --git a/migration.h b/migration.h index 0ed1fcb51..96dad38eb 100644 --- a/migration.h +++ b/migration.h @@ -79,6 +79,13 @@ MigrationState *unix_start_outgoing_migration(const char *path, int64_t bandwidth_limit, int detach); +int fd_start_incoming_migration(const char *path); + +MigrationState *fd_start_outgoing_migration(Monitor *mon, + const char *fdname, + int64_t bandwidth_limit, + int detach); + void migrate_fd_monitor_suspend(FdMigrationState *s); void migrate_fd_error(FdMigrationState *s); @@ -285,6 +285,34 @@ int qemu_stdio_fd(QEMUFile *f) return fd; } +QEMUFile *qemu_fdopen(int fd, const char *mode) +{ + QEMUFileStdio *s; + + if (mode == NULL || + (mode[0] != 'r' && mode[0] != 'w') || + mode[1] != 'b' || mode[2] != 0) { + fprintf(stderr, "qemu_fdopen: Argument validity check failed\n"); + return NULL; + } + + s = qemu_mallocz(sizeof(QEMUFileStdio)); + s->stdio_file = fdopen(fd, mode); + if (!s->stdio_file) + goto fail; + + if(mode[0] == 'r') { + s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_fclose, NULL, NULL); + } else { + s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_fclose, NULL, NULL); + } + return s->file; + +fail: + qemu_free(s); + return NULL; +} + QEMUFile *qemu_fopen_socket(int fd) { QEMUFileSocket *s = qemu_mallocz(sizeof(QEMUFileSocket)); diff --git a/target-i386/helper.c b/target-i386/helper.c index 81feef7a6..4a16887c1 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -121,7 +121,7 @@ static x86_def_t x86_defs[] = { #ifdef TARGET_X86_64 { .name = "qemu64", - .level = 2, + .level = 4, .vendor1 = CPUID_VENDOR_AMD_1, .vendor2 = CPUID_VENDOR_AMD_2, .vendor3 = CPUID_VENDOR_AMD_3, @@ -189,10 +189,36 @@ static x86_def_t x86_defs[] = { .xlevel = 0x80000008, .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz", }, + { + .name = "kvm64", + .level = 5, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 15, + .model = 6, + .stepping = 1, + /* Missing: CPUID_VME, CPUID_HT */ + .features = PPRO_FEATURES | + CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | + CPUID_PSE36, + /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */ + .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16, + /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */ + .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC, + CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A, + CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH, + CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */ + .ext3_features = 0, + .xlevel = 0x80000008, + .model_id = "Common KVM processor" + }, #endif { .name = "qemu32", - .level = 2, + .level = 4, .family = 6, .model = 3, .stepping = 3, @@ -351,7 +377,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) char *featurestr, *name = strtok(s, ","); uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0; uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0; - int family = -1, model = -1, stepping = -1; + uint32_t numvalue; def = NULL; for (i = 0; i < ARRAY_SIZE(x86_defs); i++) { @@ -383,28 +409,47 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) *val = 0; val++; if (!strcmp(featurestr, "family")) { char *err; - family = strtol(val, &err, 10); - if (!*val || *err || family < 0) { + numvalue = strtoul(val, &err, 0); + if (!*val || *err) { fprintf(stderr, "bad numerical value %s\n", val); goto error; } - x86_cpu_def->family = family; + x86_cpu_def->family = numvalue; } else if (!strcmp(featurestr, "model")) { char *err; - model = strtol(val, &err, 10); - if (!*val || *err || model < 0 || model > 0xff) { + numvalue = strtoul(val, &err, 0); + if (!*val || *err || numvalue > 0xff) { fprintf(stderr, "bad numerical value %s\n", val); goto error; } - x86_cpu_def->model = model; + x86_cpu_def->model = numvalue; } else if (!strcmp(featurestr, "stepping")) { char *err; - stepping = strtol(val, &err, 10); - if (!*val || *err || stepping < 0 || stepping > 0xf) { + numvalue = strtoul(val, &err, 0); + if (!*val || *err || numvalue > 0xf) { fprintf(stderr, "bad numerical value %s\n", val); goto error; } - x86_cpu_def->stepping = stepping; + x86_cpu_def->stepping = numvalue ; + } else if (!strcmp(featurestr, "level")) { + char *err; + numvalue = strtoul(val, &err, 0); + if (!*val || *err) { + fprintf(stderr, "bad numerical value %s\n", val); + goto error; + } + x86_cpu_def->level = numvalue; + } else if (!strcmp(featurestr, "xlevel")) { + char *err; + numvalue = strtoul(val, &err, 0); + if (!*val || *err) { + fprintf(stderr, "bad numerical value %s\n", val); + goto error; + } + if (numvalue < 0x80000000) { + numvalue += 0x80000000; + } + x86_cpu_def->xlevel = numvalue; } else if (!strcmp(featurestr, "vendor")) { if (strlen(val) != 12) { fprintf(stderr, "vendor string must be 12 chars long\n"); @@ -1634,6 +1679,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */ *ecx = env->cpuid_ext_features; *edx = env->cpuid_features; + if (env->nr_cores * env->nr_threads > 1) { + *ebx |= (env->nr_cores * env->nr_threads) << 16; + *edx |= 1 << 28; /* HTT bit */ + } break; case 2: /* cache info: needed for Pentium Pro compatibility */ @@ -1644,21 +1693,29 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 4: /* cache info: needed for Core compatibility */ + if (env->nr_cores > 1) { + *eax = (env->nr_cores - 1) << 26; + } else { + *eax = 0; + } switch (count) { case 0: /* L1 dcache info */ - *eax = 0x0000121; + *eax |= 0x0000121; *ebx = 0x1c0003f; *ecx = 0x000003f; *edx = 0x0000001; break; case 1: /* L1 icache info */ - *eax = 0x0000122; + *eax |= 0x0000122; *ebx = 0x1c0003f; *ecx = 0x000003f; *edx = 0x0000001; break; case 2: /* L2 cache info */ - *eax = 0x0000143; + *eax |= 0x0000143; + if (env->nr_threads > 1) { + *eax |= (env->nr_threads - 1) << 14; + } *ebx = 0x3c0003f; *ecx = 0x0000fff; *edx = 0x0000001; @@ -1711,6 +1768,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ecx = env->cpuid_ext3_features; *edx = env->cpuid_ext2_features; + if (env->nr_cores * env->nr_threads > 1 && + env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && + env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && + env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) { + *ecx |= 1 << 1; /* CmpLegacy bit */ + } + if (kvm_enabled()) { uint32_t h_eax, h_edx; @@ -1778,6 +1842,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ebx = 0; *ecx = 0; *edx = 0; + if (env->nr_cores * env->nr_threads > 1) { + *ecx |= (env->nr_cores * env->nr_threads) - 1; + } break; case 0x8000000A: *eax = 0x00000001; /* SVM Revision */ @@ -222,6 +222,8 @@ const char *assigned_devices[MAX_DEV_ASSIGN_CMDLINE]; int assigned_devices_index; int smp_cpus = 1; int max_cpus = 0; +int smp_cores = 1; +int smp_threads = 1; const char *vnc_display; int acpi_enabled = 1; #ifdef TARGET_I386 @@ -2380,6 +2382,56 @@ static void numa_add(const char *optarg) return; } +static void smp_parse(const char *optarg) +{ + int smp, sockets = 0, threads = 0, cores = 0; + char *endptr; + char option[128]; + + smp = strtoul(optarg, &endptr, 10); + if (endptr != optarg) { + if (*endptr == ',') { + endptr++; + } + } + if (get_param_value(option, 128, "sockets", endptr) != 0) + sockets = strtoull(option, NULL, 10); + if (get_param_value(option, 128, "cores", endptr) != 0) + cores = strtoull(option, NULL, 10); + if (get_param_value(option, 128, "threads", endptr) != 0) + threads = strtoull(option, NULL, 10); + if (get_param_value(option, 128, "maxcpus", endptr) != 0) + max_cpus = strtoull(option, NULL, 10); + + /* compute missing values, prefer sockets over cores over threads */ + if (smp == 0 || sockets == 0) { + sockets = sockets > 0 ? sockets : 1; + cores = cores > 0 ? cores : 1; + threads = threads > 0 ? threads : 1; + if (smp == 0) { + smp = cores * threads * sockets; + } else { + sockets = smp / (cores * threads); + } + } else { + if (cores == 0) { + threads = threads > 0 ? threads : 1; + cores = smp / (sockets * threads); + } else { + if (sockets == 0) { + sockets = smp / (cores * threads); + } else { + threads = smp / (cores * sockets); + } + } + } + smp_cpus = smp; + smp_cores = cores > 0 ? cores : 1; + smp_threads = threads > 0 ? threads : 1; + if (max_cpus == 0) + max_cpus = smp_cpus; +} + /***********************************************************/ /* USB devices */ @@ -3613,6 +3665,8 @@ void qemu_init_vcpu(void *_env) if (kvm_enabled()) kvm_init_vcpu(env); + env->nr_cores = smp_cores; + env->nr_threads = smp_threads; return; } @@ -3942,6 +3996,8 @@ void qemu_init_vcpu(void *_env) kvm_start_vcpu(env); else tcg_init_vcpu(env); + env->nr_cores = smp_cores; + env->nr_threads = smp_threads; } void qemu_notify_event(void) @@ -5470,18 +5526,11 @@ int main(int argc, char **argv, char **envp) } break; case QEMU_OPTION_smp: - { - char *p; - char option[128]; - smp_cpus = strtol(optarg, &p, 10); + smp_parse(optarg); if (smp_cpus < 1) { fprintf(stderr, "Invalid number of CPUs\n"); exit(1); } - if (*p++ != ',') - break; - if (get_param_value(option, 128, "maxcpus", p)) - max_cpus = strtol(option, NULL, 0); if (max_cpus < smp_cpus) { fprintf(stderr, "maxcpus must be equal to or greater than " "smp\n"); @@ -5492,7 +5541,6 @@ int main(int argc, char **argv, char **envp) exit(1); } break; - } case QEMU_OPTION_vnc: display_type = DT_VNC; vnc_display = optarg; |