aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS3
-rw-r--r--Makefile9
-rw-r--r--block/iscsi.c2
-rw-r--r--exec.c1
-rw-r--r--hw/arm/vexpress.c6
-rw-r--r--hw/arm/virt.c6
-rw-r--r--hw/block/pflash_cfi01.c4
-rw-r--r--hw/block/pflash_cfi02.c4
-rw-r--r--hw/core/qdev-properties-system.c22
-rw-r--r--hw/i386/pc.c35
-rw-r--r--hw/ppc/ppc.c161
-rw-r--r--hw/ppc/ppc405_boards.c2
-rw-r--r--hw/ppc/prep.c163
-rw-r--r--hw/scsi/esp-pci.c28
-rw-r--r--hw/scsi/lsi53c895a.c13
-rw-r--r--hw/scsi/megasas.c12
-rw-r--r--hw/scsi/scsi-bus.c6
-rw-r--r--hw/sparc/sun4m.c10
-rw-r--r--hw/sparc64/sun4u.c20
-rw-r--r--hw/timer/m48t59.c359
-rw-r--r--hw/usb/dev-storage.c7
-rw-r--r--include/hw/i386/topology.h (renamed from target-i386/topology.h)6
-rw-r--r--include/hw/qdev-properties.h4
-rw-r--r--include/hw/timer/m48t59.h61
-rw-r--r--include/ui/console.h1
-rw-r--r--pc-bios/openbios-ppcbin746588 -> 746588 bytes
-rw-r--r--pc-bios/openbios-sparc32bin381512 -> 381512 bytes
-rw-r--r--pc-bios/openbios-sparc64bin1616768 -> 1616768 bytes
-rw-r--r--qemu-doc.texi7
-rw-r--r--qmp.c1
m---------roms/openbios0
-rwxr-xr-xscripts/kvm/kvm_stat5
-rw-r--r--scripts/kvm/kvm_stat.texi55
-rw-r--r--target-i386/cpu-qom.h1
-rw-r--r--target-i386/cpu.c122
-rw-r--r--target-i386/cpu.h2
-rw-r--r--target-i386/kvm.c2
-rw-r--r--target-i386/seg_helper.c4
-rw-r--r--tests/Makefile2
-rw-r--r--tests/test-x86-cpuid.c2
-rw-r--r--ui/vnc-ws.c3
-rw-r--r--ui/vnc.c22
-rw-r--r--util/qemu-thread-posix.c6
-rw-r--r--util/rcu.c33
-rw-r--r--vl.c7
45 files changed, 711 insertions, 508 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 08443c20e4..e857cf8bf3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -159,6 +159,7 @@ F: hw/sh4/
SPARC
M: Blue Swirl <blauwirbel@gmail.com>
+M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
S: Maintained
F: target-sparc/
F: hw/sparc/
@@ -518,11 +519,13 @@ SPARC Machines
--------------
Sun4m
M: Blue Swirl <blauwirbel@gmail.com>
+M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
S: Maintained
F: hw/sparc/sun4m.c
Sun4u
M: Blue Swirl <blauwirbel@gmail.com>
+M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
S: Maintained
F: hw/sparc64/sun4u.c
diff --git a/Makefile b/Makefile
index d92d4cd573..884b59dc06 100644
--- a/Makefile
+++ b/Makefile
@@ -84,6 +84,9 @@ HELPERS-$(CONFIG_LINUX) = qemu-bridge-helper$(EXESUF)
ifdef BUILD_DOCS
DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 qmp-commands.txt
+ifdef CONFIG_LINUX
+DOCS+=kvm_stat.1
+endif
ifdef CONFIG_VIRTFS
DOCS+=fsdev/virtfs-proxy-helper.1
endif
@@ -490,6 +493,12 @@ qemu-nbd.8: qemu-nbd.texi
$(POD2MAN) --section=8 --center=" " --release=" " qemu-nbd.pod > $@, \
" GEN $@")
+kvm_stat.1: scripts/kvm/kvm_stat.texi
+ $(call quiet-command, \
+ perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< kvm_stat.pod && \
+ $(POD2MAN) --section=1 --center=" " --release=" " kvm_stat.pod > $@, \
+ " GEN $@")
+
dvi: qemu-doc.dvi qemu-tech.dvi
html: qemu-doc.html qemu-tech.html
info: qemu-doc.info qemu-tech.info
diff --git a/block/iscsi.c b/block/iscsi.c
index 1fa855acdd..3e34b1f3a2 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1326,7 +1326,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
goto out;
}
- if (iscsi_url->user != NULL) {
+ if (iscsi_url->user[0] != '\0') {
ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
iscsi_url->passwd);
if (ret != 0) {
diff --git a/exec.c b/exec.c
index b44a33c9ac..60b9752b0b 100644
--- a/exec.c
+++ b/exec.c
@@ -548,6 +548,7 @@ void cpu_exec_init(CPUArchState *env)
#ifndef CONFIG_USER_ONLY
cpu->as = &address_space_memory;
cpu->thread_id = qemu_get_thread_id();
+ cpu_reload_memory_map(cpu);
#endif
QTAILQ_INSERT_TAIL(&cpus, cpu, node);
#if defined(CONFIG_USER_ONLY)
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 5933454cfd..8496c1622a 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -515,9 +515,9 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
{
DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
- if (di && qdev_prop_set_drive(dev, "drive",
- blk_by_legacy_dinfo(di))) {
- abort();
+ if (di) {
+ qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(di),
+ &error_abort);
}
qdev_prop_set_uint32(dev, "num-blocks",
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 69f51ac0da..93b7605722 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -522,9 +522,9 @@ static void create_one_flash(const char *name, hwaddr flashbase,
DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
const uint64_t sectorlength = 256 * 1024;
- if (dinfo && qdev_prop_set_drive(dev, "drive",
- blk_by_legacy_dinfo(dinfo))) {
- abort();
+ if (dinfo) {
+ qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
+ &error_abort);
}
qdev_prop_set_uint32(dev, "num-blocks", flashsize / sectorlength);
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 89d380e59d..d282695086 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -969,8 +969,8 @@ pflash_t *pflash_cfi01_register(hwaddr base,
{
DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH01);
- if (blk && qdev_prop_set_drive(dev, "drive", blk)) {
- abort();
+ if (blk) {
+ qdev_prop_set_drive(dev, "drive", blk, &error_abort);
}
qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
qdev_prop_set_uint64(dev, "sector-length", sector_len);
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index 389b4aa1f4..074a005f69 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -773,8 +773,8 @@ pflash_t *pflash_cfi02_register(hwaddr base,
{
DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH02);
- if (blk && qdev_prop_set_drive(dev, "drive", blk)) {
- abort();
+ if (blk) {
+ qdev_prop_set_drive(dev, "drive", blk, &error_abort);
}
qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
qdev_prop_set_uint32(dev, "sector-length", sector_len);
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index a2e44bd4e8..c413226a97 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -341,27 +341,25 @@ PropertyInfo qdev_prop_vlan = {
.set = set_vlan,
};
-int qdev_prop_set_drive(DeviceState *dev, const char *name,
- BlockBackend *value)
+void qdev_prop_set_drive(DeviceState *dev, const char *name,
+ BlockBackend *value, Error **errp)
{
- Error *err = NULL;
- object_property_set_str(OBJECT(dev),
- value ? blk_name(value) : "", name, &err);
- if (err) {
- qerror_report_err(err);
- error_free(err);
- return -1;
- }
- return 0;
+ object_property_set_str(OBJECT(dev), value ? blk_name(value) : "",
+ name, errp);
}
void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name,
BlockBackend *value)
{
- if (qdev_prop_set_drive(dev, name, value) < 0) {
+ Error *err = NULL;
+
+ qdev_prop_set_drive(dev, name, value, &err);
+ if (err) {
+ error_report_err(err);
exit(1);
}
}
+
void qdev_prop_set_chr(DeviceState *dev, const char *name,
CharDriverState *value)
{
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 79eaad5fec..b5b2aadb52 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -25,6 +25,8 @@
#include "hw/i386/pc.h"
#include "hw/char/serial.h"
#include "hw/i386/apic.h"
+#include "hw/i386/topology.h"
+#include "sysemu/cpus.h"
#include "hw/block/fdc.h"
#include "hw/ide.h"
#include "hw/pci/pci.h"
@@ -629,6 +631,39 @@ bool e820_get_entry(int idx, uint32_t type, uint64_t *address, uint64_t *length)
return false;
}
+/* Enables contiguous-apic-ID mode, for compatibility */
+static bool compat_apic_id_mode;
+
+void enable_compat_apic_id_mode(void)
+{
+ compat_apic_id_mode = true;
+}
+
+/* Calculates initial APIC ID for a specific CPU index
+ *
+ * Currently we need to be able to calculate the APIC ID from the CPU index
+ * alone (without requiring a CPU object), as the QEMU<->Seabios interfaces have
+ * no concept of "CPU index", and the NUMA tables on fw_cfg need the APIC ID of
+ * all CPUs up to max_cpus.
+ */
+static uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index)
+{
+ uint32_t correct_id;
+ static bool warned;
+
+ correct_id = x86_apicid_from_cpu_idx(smp_cores, smp_threads, cpu_index);
+ if (compat_apic_id_mode) {
+ if (cpu_index != correct_id && !warned) {
+ error_report("APIC IDs set in compatibility mode, "
+ "CPU topology won't match the configuration");
+ warned = true;
+ }
+ return cpu_index;
+ } else {
+ return correct_id;
+ }
+}
+
/* Calculates the limit to CPU APIC ID values
*
* This function returns the limit for the APIC ID value, so that all
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index 5ce565d5ec..99db56c8d0 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -1318,167 +1318,6 @@ void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
}
}
-/*****************************************************************************/
-/* NVRAM helpers */
-static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
-{
- return (*nvram->read_fn)(nvram->opaque, addr);
-}
-
-static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
-{
- (*nvram->write_fn)(nvram->opaque, addr, val);
-}
-
-static void NVRAM_set_byte(nvram_t *nvram, uint32_t addr, uint8_t value)
-{
- nvram_write(nvram, addr, value);
-}
-
-static uint8_t NVRAM_get_byte(nvram_t *nvram, uint32_t addr)
-{
- return nvram_read(nvram, addr);
-}
-
-static void NVRAM_set_word(nvram_t *nvram, uint32_t addr, uint16_t value)
-{
- nvram_write(nvram, addr, value >> 8);
- nvram_write(nvram, addr + 1, value & 0xFF);
-}
-
-static uint16_t NVRAM_get_word(nvram_t *nvram, uint32_t addr)
-{
- uint16_t tmp;
-
- tmp = nvram_read(nvram, addr) << 8;
- tmp |= nvram_read(nvram, addr + 1);
-
- return tmp;
-}
-
-static void NVRAM_set_lword(nvram_t *nvram, uint32_t addr, uint32_t value)
-{
- nvram_write(nvram, addr, value >> 24);
- nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
- nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
- nvram_write(nvram, addr + 3, value & 0xFF);
-}
-
-uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
-{
- uint32_t tmp;
-
- tmp = nvram_read(nvram, addr) << 24;
- tmp |= nvram_read(nvram, addr + 1) << 16;
- tmp |= nvram_read(nvram, addr + 2) << 8;
- tmp |= nvram_read(nvram, addr + 3);
-
- return tmp;
-}
-
-static void NVRAM_set_string(nvram_t *nvram, uint32_t addr, const char *str,
- uint32_t max)
-{
- int i;
-
- for (i = 0; i < max && str[i] != '\0'; i++) {
- nvram_write(nvram, addr + i, str[i]);
- }
- nvram_write(nvram, addr + i, str[i]);
- nvram_write(nvram, addr + max - 1, '\0');
-}
-
-int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
-{
- int i;
-
- memset(dst, 0, max);
- for (i = 0; i < max; i++) {
- dst[i] = NVRAM_get_byte(nvram, addr + i);
- if (dst[i] == '\0')
- break;
- }
-
- return i;
-}
-
-static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
-{
- uint16_t tmp;
- uint16_t pd, pd1, pd2;
-
- tmp = prev >> 8;
- pd = prev ^ value;
- pd1 = pd & 0x000F;
- pd2 = ((pd >> 4) & 0x000F) ^ pd1;
- tmp ^= (pd1 << 3) | (pd1 << 8);
- tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
-
- return tmp;
-}
-
-static uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
-{
- uint32_t i;
- uint16_t crc = 0xFFFF;
- int odd;
-
- odd = count & 1;
- count &= ~1;
- for (i = 0; i != count; i++) {
- crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
- }
- if (odd) {
- crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
- }
-
- return crc;
-}
-
-#define CMDLINE_ADDR 0x017ff000
-
-int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
- const char *arch,
- uint32_t RAM_size, int boot_device,
- uint32_t kernel_image, uint32_t kernel_size,
- const char *cmdline,
- uint32_t initrd_image, uint32_t initrd_size,
- uint32_t NVRAM_image,
- int width, int height, int depth)
-{
- uint16_t crc;
-
- /* Set parameters for Open Hack'Ware BIOS */
- NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
- NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */
- NVRAM_set_word(nvram, 0x14, NVRAM_size);
- NVRAM_set_string(nvram, 0x20, arch, 16);
- NVRAM_set_lword(nvram, 0x30, RAM_size);
- NVRAM_set_byte(nvram, 0x34, boot_device);
- NVRAM_set_lword(nvram, 0x38, kernel_image);
- NVRAM_set_lword(nvram, 0x3C, kernel_size);
- if (cmdline) {
- /* XXX: put the cmdline in NVRAM too ? */
- pstrcpy_targphys("cmdline", CMDLINE_ADDR, RAM_size - CMDLINE_ADDR, cmdline);
- NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR);
- NVRAM_set_lword(nvram, 0x44, strlen(cmdline));
- } else {
- NVRAM_set_lword(nvram, 0x40, 0);
- NVRAM_set_lword(nvram, 0x44, 0);
- }
- NVRAM_set_lword(nvram, 0x48, initrd_image);
- NVRAM_set_lword(nvram, 0x4C, initrd_size);
- NVRAM_set_lword(nvram, 0x50, NVRAM_image);
-
- NVRAM_set_word(nvram, 0x54, width);
- NVRAM_set_word(nvram, 0x56, height);
- NVRAM_set_word(nvram, 0x58, depth);
- crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
- NVRAM_set_word(nvram, 0xFC, crc);
-
- return 0;
-}
-
/* CPU device-tree ID helpers */
int ppc_get_vcpu_dt_id(PowerPCCPU *cpu)
{
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 1dcea7730e..ec6c4cbaf1 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -283,7 +283,7 @@ static void ref405ep_init(MachineState *machine)
#ifdef DEBUG_BOARD_INIT
printf("%s: register NVRAM\n", __func__);
#endif
- m48t59_init(NULL, 0xF0000000, 0, 8192, 8);
+ m48t59_init(NULL, 0xF0000000, 0, 8192, 1968, 8);
/* Load kernel */
linux_boot = (kernel_filename != NULL);
if (linux_boot) {
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 15df7f3dae..7f52662d76 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -181,7 +181,7 @@ static const MemoryRegionOps PPC_XCSR_ops = {
/* Fake super-io ports for PREP platform (Intel 82378ZB) */
typedef struct sysctrl_t {
qemu_irq reset_irq;
- M48t59State *nvram;
+ Nvram *nvram;
uint8_t state;
uint8_t syscontrol;
int contiguous_map;
@@ -235,13 +235,17 @@ static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
break;
case 0x0810:
/* Password protect 1 register */
- if (sysctrl->nvram != NULL)
- m48t59_toggle_lock(sysctrl->nvram, 1);
+ if (sysctrl->nvram != NULL) {
+ NvramClass *k = NVRAM_GET_CLASS(sysctrl->nvram);
+ (k->toggle_lock)(sysctrl->nvram, 1);
+ }
break;
case 0x0812:
/* Password protect 2 register */
- if (sysctrl->nvram != NULL)
- m48t59_toggle_lock(sysctrl->nvram, 2);
+ if (sysctrl->nvram != NULL) {
+ NvramClass *k = NVRAM_GET_CLASS(sysctrl->nvram);
+ (k->toggle_lock)(sysctrl->nvram, 2);
+ }
break;
case 0x0814:
/* L2 invalidate register */
@@ -360,6 +364,144 @@ static const MemoryRegionPortio prep_portio_list[] = {
static PortioList prep_port_list;
+/*****************************************************************************/
+/* NVRAM helpers */
+static inline uint32_t nvram_read(Nvram *nvram, uint32_t addr)
+{
+ NvramClass *k = NVRAM_GET_CLASS(sysctrl->nvram);
+ return (k->read)(nvram, addr);
+}
+
+static inline void nvram_write(Nvram *nvram, uint32_t addr, uint32_t val)
+{
+ NvramClass *k = NVRAM_GET_CLASS(sysctrl->nvram);
+ (k->write)(nvram, addr, val);
+}
+
+static void NVRAM_set_byte(Nvram *nvram, uint32_t addr, uint8_t value)
+{
+ nvram_write(nvram, addr, value);
+}
+
+static uint8_t NVRAM_get_byte(Nvram *nvram, uint32_t addr)
+{
+ return nvram_read(nvram, addr);
+}
+
+static void NVRAM_set_word(Nvram *nvram, uint32_t addr, uint16_t value)
+{
+ nvram_write(nvram, addr, value >> 8);
+ nvram_write(nvram, addr + 1, value & 0xFF);
+}
+
+static uint16_t NVRAM_get_word(Nvram *nvram, uint32_t addr)
+{
+ uint16_t tmp;
+
+ tmp = nvram_read(nvram, addr) << 8;
+ tmp |= nvram_read(nvram, addr + 1);
+
+ return tmp;
+}
+
+static void NVRAM_set_lword(Nvram *nvram, uint32_t addr, uint32_t value)
+{
+ nvram_write(nvram, addr, value >> 24);
+ nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
+ nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
+ nvram_write(nvram, addr + 3, value & 0xFF);
+}
+
+static void NVRAM_set_string(Nvram *nvram, uint32_t addr, const char *str,
+ uint32_t max)
+{
+ int i;
+
+ for (i = 0; i < max && str[i] != '\0'; i++) {
+ nvram_write(nvram, addr + i, str[i]);
+ }
+ nvram_write(nvram, addr + i, str[i]);
+ nvram_write(nvram, addr + max - 1, '\0');
+}
+
+static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
+{
+ uint16_t tmp;
+ uint16_t pd, pd1, pd2;
+
+ tmp = prev >> 8;
+ pd = prev ^ value;
+ pd1 = pd & 0x000F;
+ pd2 = ((pd >> 4) & 0x000F) ^ pd1;
+ tmp ^= (pd1 << 3) | (pd1 << 8);
+ tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
+
+ return tmp;
+}
+
+static uint16_t NVRAM_compute_crc (Nvram *nvram, uint32_t start, uint32_t count)
+{
+ uint32_t i;
+ uint16_t crc = 0xFFFF;
+ int odd;
+
+ odd = count & 1;
+ count &= ~1;
+ for (i = 0; i != count; i++) {
+ crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
+ }
+ if (odd) {
+ crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
+ }
+
+ return crc;
+}
+
+#define CMDLINE_ADDR 0x017ff000
+
+static int PPC_NVRAM_set_params (Nvram *nvram, uint16_t NVRAM_size,
+ const char *arch,
+ uint32_t RAM_size, int boot_device,
+ uint32_t kernel_image, uint32_t kernel_size,
+ const char *cmdline,
+ uint32_t initrd_image, uint32_t initrd_size,
+ uint32_t NVRAM_image,
+ int width, int height, int depth)
+{
+ uint16_t crc;
+
+ /* Set parameters for Open Hack'Ware BIOS */
+ NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
+ NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */
+ NVRAM_set_word(nvram, 0x14, NVRAM_size);
+ NVRAM_set_string(nvram, 0x20, arch, 16);
+ NVRAM_set_lword(nvram, 0x30, RAM_size);
+ NVRAM_set_byte(nvram, 0x34, boot_device);
+ NVRAM_set_lword(nvram, 0x38, kernel_image);
+ NVRAM_set_lword(nvram, 0x3C, kernel_size);
+ if (cmdline) {
+ /* XXX: put the cmdline in NVRAM too ? */
+ pstrcpy_targphys("cmdline", CMDLINE_ADDR, RAM_size - CMDLINE_ADDR,
+ cmdline);
+ NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR);
+ NVRAM_set_lword(nvram, 0x44, strlen(cmdline));
+ } else {
+ NVRAM_set_lword(nvram, 0x40, 0);
+ NVRAM_set_lword(nvram, 0x44, 0);
+ }
+ NVRAM_set_lword(nvram, 0x48, initrd_image);
+ NVRAM_set_lword(nvram, 0x4C, initrd_size);
+ NVRAM_set_lword(nvram, 0x50, NVRAM_image);
+
+ NVRAM_set_word(nvram, 0x54, width);
+ NVRAM_set_word(nvram, 0x56, height);
+ NVRAM_set_word(nvram, 0x58, depth);
+ crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
+ NVRAM_set_word(nvram, 0xFC, crc);
+
+ return 0;
+}
+
/* PowerPC PREP hardware initialisation */
static void ppc_prep_init(MachineState *machine)
{
@@ -372,8 +514,7 @@ static void ppc_prep_init(MachineState *machine)
MemoryRegion *sysmem = get_system_memory();
PowerPCCPU *cpu = NULL;
CPUPPCState *env = NULL;
- nvram_t nvram;
- M48t59State *m48t59;
+ Nvram *m48t59;
#if 0
MemoryRegion *xcsr = g_new(MemoryRegion, 1);
#endif
@@ -543,16 +684,14 @@ static void ppc_prep_init(MachineState *machine)
pci_create_simple(pci_bus, -1, "pci-ohci");
}
- m48t59 = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59);
+ m48t59 = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 2000, 59);
if (m48t59 == NULL)
return;
sysctrl->nvram = m48t59;
/* Initialise NVRAM */
- nvram.opaque = m48t59;
- nvram.read_fn = &m48t59_read;
- nvram.write_fn = &m48t59_write;
- PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "PREP", ram_size, ppc_boot_device,
+ PPC_NVRAM_set_params(m48t59, NVRAM_SIZE, "PREP", ram_size,
+ ppc_boot_device,
kernel_base, kernel_size,
kernel_cmdline,
initrd_base, initrd_size,
diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
index 00b7297354..8d2242d0a4 100644
--- a/hw/scsi/esp-pci.c
+++ b/hw/scsi/esp-pci.c
@@ -342,13 +342,12 @@ static const struct SCSIBusInfo esp_pci_scsi_info = {
.cancel = esp_request_cancelled,
};
-static int esp_pci_scsi_init(PCIDevice *dev)
+static void esp_pci_scsi_realize(PCIDevice *dev, Error **errp)
{
PCIESPState *pci = PCI_ESP(dev);
DeviceState *d = DEVICE(dev);
ESPState *s = &pci->esp;
uint8_t *pci_conf;
- Error *err = NULL;
pci_conf = dev->config;
@@ -367,13 +366,8 @@ static int esp_pci_scsi_init(PCIDevice *dev)
scsi_bus_new(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info, NULL);
if (!d->hotplugged) {
- scsi_bus_legacy_handle_cmdline(&s->bus, &err);
- if (err != NULL) {
- error_free(err);
- return -1;
- }
+ scsi_bus_legacy_handle_cmdline(&s->bus, errp);
}
- return 0;
}
static void esp_pci_scsi_uninit(PCIDevice *d)
@@ -388,7 +382,7 @@ static void esp_pci_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->init = esp_pci_scsi_init;
+ k->realize = esp_pci_scsi_realize;
k->exit = esp_pci_scsi_uninit;
k->vendor_id = PCI_VENDOR_ID_AMD;
k->device_id = PCI_DEVICE_ID_AMD_SCSI;
@@ -466,17 +460,19 @@ static void dc390_write_config(PCIDevice *dev,
}
}
-static int dc390_scsi_init(PCIDevice *dev)
+static void dc390_scsi_realize(PCIDevice *dev, Error **errp)
{
DC390State *pci = DC390(dev);
+ Error *err = NULL;
uint8_t *contents;
uint16_t chksum = 0;
- int i, ret;
+ int i;
/* init base class */
- ret = esp_pci_scsi_init(dev);
- if (ret < 0) {
- return ret;
+ esp_pci_scsi_realize(dev, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
}
/* EEPROM */
@@ -503,8 +499,6 @@ static int dc390_scsi_init(PCIDevice *dev)
chksum = 0x1234 - chksum;
contents[EE_CHKSUM1] = chksum & 0xff;
contents[EE_CHKSUM2] = chksum >> 8;
-
- return 0;
}
static void dc390_class_init(ObjectClass *klass, void *data)
@@ -512,7 +506,7 @@ static void dc390_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->init = dc390_scsi_init;
+ k->realize = dc390_scsi_realize;
k->config_read = dc390_read_config;
k->config_write = dc390_write_config;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index db7d4b8c9c..c5b0cc5caf 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -19,7 +19,6 @@
#include "hw/pci/pci.h"
#include "hw/scsi/scsi.h"
#include "sysemu/dma.h"
-#include "qemu/error-report.h"
//#define DEBUG_LSI
//#define DEBUG_LSI_REG
@@ -2089,12 +2088,11 @@ static const struct SCSIBusInfo lsi_scsi_info = {
.cancel = lsi_request_cancelled
};
-static int lsi_scsi_init(PCIDevice *dev)
+static void lsi_scsi_realize(PCIDevice *dev, Error **errp)
{
LSIState *s = LSI53C895A(dev);
DeviceState *d = DEVICE(dev);
uint8_t *pci_conf;
- Error *err = NULL;
pci_conf = dev->config;
@@ -2117,13 +2115,8 @@ static int lsi_scsi_init(PCIDevice *dev)
scsi_bus_new(&s->bus, sizeof(s->bus), d, &lsi_scsi_info, NULL);
if (!d->hotplugged) {
- scsi_bus_legacy_handle_cmdline(&s->bus, &err);
- if (err != NULL) {
- error_free(err);
- return -1;
- }
+ scsi_bus_legacy_handle_cmdline(&s->bus, errp);
}
- return 0;
}
static void lsi_class_init(ObjectClass *klass, void *data)
@@ -2131,7 +2124,7 @@ static void lsi_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->init = lsi_scsi_init;
+ k->realize = lsi_scsi_realize;
k->vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
k->device_id = PCI_DEVICE_ID_LSI_53C895A;
k->class_id = PCI_CLASS_STORAGE_SCSI;
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 4852237a79..bf83b65383 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -2320,14 +2320,13 @@ static const struct SCSIBusInfo megasas_scsi_info = {
.cancel = megasas_command_cancel,
};
-static int megasas_scsi_init(PCIDevice *dev)
+static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
{
DeviceState *d = DEVICE(dev);
MegasasState *s = MEGASAS(dev);
MegasasBaseClass *b = MEGASAS_DEVICE_GET_CLASS(s);
uint8_t *pci_conf;
int i, bar_type;
- Error *err = NULL;
pci_conf = dev->config;
@@ -2407,13 +2406,8 @@ static int megasas_scsi_init(PCIDevice *dev)
scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
&megasas_scsi_info, NULL);
if (!d->hotplugged) {
- scsi_bus_legacy_handle_cmdline(&s->bus, &err);
- if (err != NULL) {
- error_free(err);
- return -1;
- }
+ scsi_bus_legacy_handle_cmdline(&s->bus, errp);
}
- return 0;
}
static void
@@ -2507,7 +2501,7 @@ static void megasas_class_init(ObjectClass *oc, void *data)
MegasasBaseClass *e = MEGASAS_DEVICE_CLASS(oc);
const MegasasInfo *info = data;
- pc->init = megasas_scsi_init;
+ pc->realize = megasas_scsi_realize;
pc->exit = megasas_scsi_uninit;
pc->vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
pc->device_id = info->device_id;
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index dca9576828..bd2c0e4caa 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -242,8 +242,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
if (serial && object_property_find(OBJECT(dev), "serial", NULL)) {
qdev_prop_set_string(dev, "serial", serial);
}
- if (qdev_prop_set_drive(dev, "drive", blk) < 0) {
- error_setg(errp, "Setting drive property failed");
+ qdev_prop_set_drive(dev, "drive", blk, &err);
+ if (err) {
+ error_propagate(errp, err);
object_unparent(OBJECT(dev));
return NULL;
}
@@ -273,7 +274,6 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp)
scsi_bus_legacy_add_drive(bus, blk_by_legacy_dinfo(dinfo),
unit, false, -1, NULL, &err);
if (err != NULL) {
- error_report("%s", error_get_pretty(err));
error_propagate(errp, err);
break;
}
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 09afccf860..b879aa91eb 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -127,7 +127,7 @@ static void fw_cfg_boot_set(void *opaque, const char *boot_device,
fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
}
-static void nvram_init(M48t59State *nvram, uint8_t *macaddr,
+static void nvram_init(Nvram *nvram, uint8_t *macaddr,
const char *cmdline, const char *boot_devices,
ram_addr_t RAM_size, uint32_t kernel_size,
int width, int height, int depth,
@@ -137,6 +137,7 @@ static void nvram_init(M48t59State *nvram, uint8_t *macaddr,
uint32_t start, end;
uint8_t image[0x1ff0];
struct OpenBIOS_nvpart_v1 *part_header;
+ NvramClass *k = NVRAM_GET_CLASS(nvram);
memset(image, '\0', sizeof(image));
@@ -170,8 +171,9 @@ static void nvram_init(M48t59State *nvram, uint8_t *macaddr,
Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr,
nvram_machine_id);
- for (i = 0; i < sizeof(image); i++)
- m48t59_write(nvram, i, image[i]);
+ for (i = 0; i < sizeof(image); i++) {
+ (k->write)(nvram, i, image[i]);
+ }
}
static DeviceState *slavio_intctl;
@@ -1012,7 +1014,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
- nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 8);
+ nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 1968, 8);
slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus);
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index b310588ff7..f027caf909 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -130,7 +130,7 @@ static void fw_cfg_boot_set(void *opaque, const char *boot_device,
fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
}
-static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
+static int sun4u_NVRAM_set_params(Nvram *nvram, uint16_t NVRAM_size,
const char *arch, ram_addr_t RAM_size,
const char *boot_devices,
uint32_t kernel_image, uint32_t kernel_size,
@@ -144,6 +144,7 @@ static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
uint32_t start, end;
uint8_t image[0x1ff0];
struct OpenBIOS_nvpart_v1 *part_header;
+ NvramClass *k = NVRAM_GET_CLASS(nvram);
memset(image, '\0', sizeof(image));
@@ -176,8 +177,9 @@ static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr, 0x80);
- for (i = 0; i < sizeof(image); i++)
- m48t59_write(nvram, i, image[i]);
+ for (i = 0; i < sizeof(image); i++) {
+ (k->write)(nvram, i, image[i]);
+ }
return 0;
}
@@ -610,7 +612,7 @@ pci_ebus_init1(PCIDevice *pci_dev)
0, 0x1000000);
pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);
memory_region_init_alias(&s->bar1, OBJECT(s), "bar1", get_system_io(),
- 0, 0x1000);
+ 0, 0x4000);
pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->bar1);
return 0;
}
@@ -818,11 +820,12 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
const struct hwdef *hwdef)
{
SPARCCPU *cpu;
- M48t59State *nvram;
+ Nvram *nvram;
unsigned int i;
uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
PCIBus *pci_bus, *pci_bus2, *pci_bus3;
ISABus *isa_bus;
+ SysBusDevice *s;
qemu_irq *ivec_irqs, *pbm_irqs;
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
DriveInfo *fd[MAX_FD];
@@ -866,8 +869,13 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
fd[i] = drive_get(IF_FLOPPY, 0, i);
}
fdctrl_init_isa(isa_bus, fd);
- nvram = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59);
+ /* Map NVRAM into I/O (ebus) space */
+ nvram = m48t59_init(NULL, 0, 0, NVRAM_SIZE, 1968, 59);
+ s = SYS_BUS_DEVICE(nvram);
+ memory_region_add_subregion(get_system_io(), 0x2000,
+ sysbus_mmio_get_region(s, 0));
+
initrd_size = 0;
initrd_addr = 0;
kernel_size = sun4u_load_kernel(machine->kernel_filename,
diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
index 31509d5c28..8ab683ddac 100644
--- a/hw/timer/m48t59.c
+++ b/hw/timer/m48t59.c
@@ -2,6 +2,7 @@
* QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
*
* Copyright (c) 2003-2005, 2007 Jocelyn Mayer
+ * Copyright (c) 2013 Hervé Poussineau
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -37,12 +38,35 @@
#define NVRAM_PRINTF(fmt, ...) do { } while (0)
#endif
+#define TYPE_M48TXX_SYS_BUS "sysbus-m48txx"
+#define M48TXX_SYS_BUS_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(M48txxSysBusDeviceClass, (obj), TYPE_M48TXX_SYS_BUS)
+#define M48TXX_SYS_BUS_CLASS(klass) \
+ OBJECT_CLASS_CHECK(M48txxSysBusDeviceClass, (klass), TYPE_M48TXX_SYS_BUS)
+#define M48TXX_SYS_BUS(obj) \
+ OBJECT_CHECK(M48txxSysBusState, (obj), TYPE_M48TXX_SYS_BUS)
+
+#define TYPE_M48TXX_ISA "isa-m48txx"
+#define M48TXX_ISA_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(M48txxISADeviceClass, (obj), TYPE_M48TXX_ISA)
+#define M48TXX_ISA_CLASS(klass) \
+ OBJECT_CLASS_CHECK(M48txxISADeviceClass, (klass), TYPE_M48TXX_ISA)
+#define M48TXX_ISA(obj) \
+ OBJECT_CHECK(M48txxISAState, (obj), TYPE_M48TXX_ISA)
+
/*
* The M48T02, M48T08 and M48T59 chips are very similar. The newer '59 has
* alarm and a watchdog timer and related control registers. In the
* PPC platform there is also a nvram lock function.
*/
+typedef struct M48txxInfo {
+ const char *isa_name;
+ const char *sysbus_name;
+ uint32_t model; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */
+ uint32_t size;
+} M48txxInfo;
+
/*
* Chipset docs:
* http://www.st.com/stonline/products/literature/ds/2410/m48t02.pdf
@@ -50,12 +74,12 @@
* http://www.st.com/stonline/products/literature/od/7001/m48t59y.pdf
*/
-struct M48t59State {
+typedef struct M48t59State {
/* Hardware parameters */
qemu_irq IRQ;
MemoryRegion iomem;
- uint32_t io_base;
uint32_t size;
+ int32_t base_year;
/* RTC management */
time_t time_offset;
time_t stop_time;
@@ -70,28 +94,51 @@ struct M48t59State {
/* NVRAM storage */
uint16_t addr;
uint8_t lock;
-};
-
-#define TYPE_ISA_M48T59 "m48t59_isa"
-#define ISA_M48T59(obj) \
- OBJECT_CHECK(M48t59ISAState, (obj), TYPE_ISA_M48T59)
+} M48t59State;
-typedef struct M48t59ISAState {
+typedef struct M48txxISAState {
ISADevice parent_obj;
-
M48t59State state;
+ uint32_t io_base;
MemoryRegion io;
-} M48t59ISAState;
+} M48txxISAState;
-#define SYSBUS_M48T59(obj) \
- OBJECT_CHECK(M48t59SysBusState, (obj), TYPE_SYSBUS_M48T59)
+typedef struct M48txxISADeviceClass {
+ ISADeviceClass parent_class;
+ M48txxInfo info;
+} M48txxISADeviceClass;
-typedef struct M48t59SysBusState {
+typedef struct M48txxSysBusState {
SysBusDevice parent_obj;
-
M48t59State state;
MemoryRegion io;
-} M48t59SysBusState;
+} M48txxSysBusState;
+
+typedef struct M48txxSysBusDeviceClass {
+ SysBusDeviceClass parent_class;
+ M48txxInfo info;
+} M48txxSysBusDeviceClass;
+
+static M48txxInfo m48txx_info[] = {
+ {
+ .sysbus_name = "sysbus-m48t02",
+ .model = 2,
+ .size = 0x800,
+ },{
+ .sysbus_name = "sysbus-m48t08",
+ .model = 8,
+ .size = 0x2000,
+ },{
+ .sysbus_name = "sysbus-m48t59",
+ .model = 59,
+ .size = 0x2000,
+ },{
+ .isa_name = "isa-m48t59",
+ .model = 59,
+ .size = 0x2000,
+ }
+};
+
/* Fake timer functions */
@@ -198,9 +245,8 @@ static void set_up_watchdog(M48t59State *NVRAM, uint8_t value)
}
/* Direct access to NVRAM */
-void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
+static void m48t59_write(M48t59State *NVRAM, uint32_t addr, uint32_t val)
{
- M48t59State *NVRAM = opaque;
struct tm tm;
int tmp;
@@ -346,11 +392,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
tmp = from_bcd(val);
if (tmp >= 0 && tmp <= 99) {
get_time(NVRAM, &tm);
- if (NVRAM->model == 8) {
- tm.tm_year = from_bcd(val) + 68; // Base year is 1968
- } else {
- tm.tm_year = from_bcd(val);
- }
+ tm.tm_year = from_bcd(val) + NVRAM->base_year - 1900;
set_time(NVRAM, &tm);
}
break;
@@ -368,9 +410,8 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
}
}
-uint32_t m48t59_read (void *opaque, uint32_t addr)
+static uint32_t m48t59_read(M48t59State *NVRAM, uint32_t addr)
{
- M48t59State *NVRAM = opaque;
struct tm tm;
uint32_t retval = 0xFF;
@@ -453,11 +494,7 @@ uint32_t m48t59_read (void *opaque, uint32_t addr)
case 0x07FF:
/* year */
get_time(NVRAM, &tm);
- if (NVRAM->model == 8) {
- retval = to_bcd(tm.tm_year - 68); // Base year is 1968
- } else {
- retval = to_bcd(tm.tm_year);
- }
+ retval = to_bcd((tm.tm_year + 1900 - NVRAM->base_year) % 100);
break;
default:
/* Check lock registers state */
@@ -477,10 +514,8 @@ uint32_t m48t59_read (void *opaque, uint32_t addr)
return retval;
}
-void m48t59_toggle_lock (void *opaque, int lock)
+static void m48t59_toggle_lock(M48t59State *NVRAM, int lock)
{
- M48t59State *NVRAM = opaque;
-
NVRAM->lock ^= 1 << lock;
}
@@ -616,7 +651,7 @@ static void m48t59_reset_common(M48t59State *NVRAM)
static void m48t59_reset_isa(DeviceState *d)
{
- M48t59ISAState *isa = ISA_M48T59(d);
+ M48txxISAState *isa = M48TXX_ISA(d);
M48t59State *NVRAM = &isa->state;
m48t59_reset_common(NVRAM);
@@ -624,7 +659,7 @@ static void m48t59_reset_isa(DeviceState *d)
static void m48t59_reset_sysbus(DeviceState *d)
{
- M48t59SysBusState *sys = SYSBUS_M48T59(d);
+ M48txxSysBusState *sys = M48TXX_SYS_BUS(d);
M48t59State *NVRAM = &sys->state;
m48t59_reset_common(NVRAM);
@@ -641,58 +676,63 @@ static const MemoryRegionOps m48t59_io_ops = {
};
/* Initialisation routine */
-M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
- uint32_t io_base, uint16_t size, int model)
+Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
+ uint32_t io_base, uint16_t size, int base_year,
+ int model)
{
DeviceState *dev;
SysBusDevice *s;
- M48t59SysBusState *d;
- M48t59State *state;
-
- dev = qdev_create(NULL, TYPE_SYSBUS_M48T59);
- qdev_prop_set_uint32(dev, "model", model);
- qdev_prop_set_uint32(dev, "size", size);
- qdev_prop_set_uint32(dev, "io_base", io_base);
- qdev_init_nofail(dev);
- s = SYS_BUS_DEVICE(dev);
- d = SYSBUS_M48T59(dev);
- state = &d->state;
- sysbus_connect_irq(s, 0, IRQ);
- memory_region_init_io(&d->io, OBJECT(d), &m48t59_io_ops, state,
- "m48t59", 4);
- if (io_base != 0) {
- memory_region_add_subregion(get_system_io(), io_base, &d->io);
- }
- if (mem_base != 0) {
- sysbus_mmio_map(s, 0, mem_base);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
+ if (!m48txx_info[i].sysbus_name ||
+ m48txx_info[i].size != size ||
+ m48txx_info[i].model != model) {
+ continue;
+ }
+
+ dev = qdev_create(NULL, m48txx_info[i].sysbus_name);
+ qdev_prop_set_int32(dev, "base-year", base_year);
+ qdev_init_nofail(dev);
+ s = SYS_BUS_DEVICE(dev);
+ sysbus_connect_irq(s, 0, IRQ);
+ if (io_base != 0) {
+ memory_region_add_subregion(get_system_io(), io_base,
+ sysbus_mmio_get_region(s, 1));
+ }
+ if (mem_base != 0) {
+ sysbus_mmio_map(s, 0, mem_base);
+ }
+
+ return NVRAM(s);
}
- return state;
+ assert(false);
+ return NULL;
}
-M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
- int model)
+Nvram *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
+ int base_year, int model)
{
- M48t59ISAState *d;
- ISADevice *isadev;
DeviceState *dev;
- M48t59State *s;
-
- isadev = isa_create(bus, TYPE_ISA_M48T59);
- dev = DEVICE(isadev);
- qdev_prop_set_uint32(dev, "model", model);
- qdev_prop_set_uint32(dev, "size", size);
- qdev_prop_set_uint32(dev, "io_base", io_base);
- qdev_init_nofail(dev);
- d = ISA_M48T59(isadev);
- s = &d->state;
-
- memory_region_init_io(&d->io, OBJECT(d), &m48t59_io_ops, s, "m48t59", 4);
- if (io_base != 0) {
- isa_register_ioport(isadev, &d->io, io_base);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
+ if (!m48txx_info[i].isa_name ||
+ m48txx_info[i].size != size ||
+ m48txx_info[i].model != model) {
+ continue;
+ }
+
+ dev = DEVICE(isa_create(bus, m48txx_info[i].isa_name));
+ qdev_prop_set_uint32(dev, "iobase", io_base);
+ qdev_prop_set_int32(dev, "base-year", base_year);
+ qdev_init_nofail(dev);
+ return NVRAM(dev);
}
- return s;
+ assert(false);
+ return NULL;
}
static void m48t59_realize_common(M48t59State *s, Error **errp)
@@ -709,25 +749,38 @@ static void m48t59_realize_common(M48t59State *s, Error **errp)
static void m48t59_isa_realize(DeviceState *dev, Error **errp)
{
+ M48txxISADeviceClass *u = M48TXX_ISA_GET_CLASS(dev);
ISADevice *isadev = ISA_DEVICE(dev);
- M48t59ISAState *d = ISA_M48T59(dev);
+ M48txxISAState *d = M48TXX_ISA(dev);
M48t59State *s = &d->state;
+ s->model = u->info.model;
+ s->size = u->info.size;
isa_init_irq(isadev, &s->IRQ, 8);
m48t59_realize_common(s, errp);
+ memory_region_init_io(&d->io, OBJECT(dev), &m48t59_io_ops, s, "m48t59", 4);
+ if (d->io_base != 0) {
+ isa_register_ioport(isadev, &d->io, d->io_base);
+ }
}
static int m48t59_init1(SysBusDevice *dev)
{
- M48t59SysBusState *d = SYSBUS_M48T59(dev);
+ M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_GET_CLASS(dev);
+ M48txxSysBusState *d = M48TXX_SYS_BUS(dev);
+ Object *o = OBJECT(dev);
M48t59State *s = &d->state;
Error *err = NULL;
+ s->model = u->info.model;
+ s->size = u->info.size;
sysbus_init_irq(dev, &s->IRQ);
- memory_region_init_io(&s->iomem, OBJECT(d), &nvram_ops, s,
- "m48t59.nvram", s->size);
+ memory_region_init_io(&s->iomem, o, &nvram_ops, s, "m48t59.nvram",
+ s->size);
+ memory_region_init_io(&d->io, o, &m48t59_io_ops, s, "m48t59", 4);
sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(dev, &d->io);
m48t59_realize_common(s, &err);
if (err != NULL) {
error_free(err);
@@ -737,59 +790,157 @@ static int m48t59_init1(SysBusDevice *dev)
return 0;
}
+static uint32_t m48txx_isa_read(Nvram *obj, uint32_t addr)
+{
+ M48txxISAState *d = M48TXX_ISA(obj);
+ return m48t59_read(&d->state, addr);
+}
+
+static void m48txx_isa_write(Nvram *obj, uint32_t addr, uint32_t val)
+{
+ M48txxISAState *d = M48TXX_ISA(obj);
+ m48t59_write(&d->state, addr, val);
+}
+
+static void m48txx_isa_toggle_lock(Nvram *obj, int lock)
+{
+ M48txxISAState *d = M48TXX_ISA(obj);
+ m48t59_toggle_lock(&d->state, lock);
+}
+
static Property m48t59_isa_properties[] = {
- DEFINE_PROP_UINT32("size", M48t59ISAState, state.size, -1),
- DEFINE_PROP_UINT32("model", M48t59ISAState, state.model, -1),
- DEFINE_PROP_UINT32("io_base", M48t59ISAState, state.io_base, 0),
+ DEFINE_PROP_INT32("base-year", M48txxISAState, state.base_year, 0),
+ DEFINE_PROP_UINT32("iobase", M48txxISAState, io_base, 0x74),
DEFINE_PROP_END_OF_LIST(),
};
-static void m48t59_isa_class_init(ObjectClass *klass, void *data)
+static void m48txx_isa_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ NvramClass *nc = NVRAM_CLASS(klass);
dc->realize = m48t59_isa_realize;
dc->reset = m48t59_reset_isa;
dc->props = m48t59_isa_properties;
- /* Reason: needs to be wired up by m48t59_init_isa() */
- dc->cannot_instantiate_with_device_add_yet = true;
+ nc->read = m48txx_isa_read;
+ nc->write = m48txx_isa_write;
+ nc->toggle_lock = m48txx_isa_toggle_lock;
}
-static const TypeInfo m48t59_isa_info = {
- .name = TYPE_ISA_M48T59,
- .parent = TYPE_ISA_DEVICE,
- .instance_size = sizeof(M48t59ISAState),
- .class_init = m48t59_isa_class_init,
-};
+static void m48txx_isa_concrete_class_init(ObjectClass *klass, void *data)
+{
+ M48txxISADeviceClass *u = M48TXX_ISA_CLASS(klass);
+ M48txxInfo *info = data;
+
+ u->info = *info;
+}
+
+static uint32_t m48txx_sysbus_read(Nvram *obj, uint32_t addr)
+{
+ M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
+ return m48t59_read(&d->state, addr);
+}
+
+static void m48txx_sysbus_write(Nvram *obj, uint32_t addr, uint32_t val)
+{
+ M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
+ m48t59_write(&d->state, addr, val);
+}
+
+static void m48txx_sysbus_toggle_lock(Nvram *obj, int lock)
+{
+ M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
+ m48t59_toggle_lock(&d->state, lock);
+}
-static Property m48t59_properties[] = {
- DEFINE_PROP_UINT32("size", M48t59SysBusState, state.size, -1),
- DEFINE_PROP_UINT32("model", M48t59SysBusState, state.model, -1),
- DEFINE_PROP_UINT32("io_base", M48t59SysBusState, state.io_base, 0),
+static Property m48t59_sysbus_properties[] = {
+ DEFINE_PROP_INT32("base-year", M48txxSysBusState, state.base_year, 0),
DEFINE_PROP_END_OF_LIST(),
};
-static void m48t59_class_init(ObjectClass *klass, void *data)
+static void m48txx_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ NvramClass *nc = NVRAM_CLASS(klass);
k->init = m48t59_init1;
dc->reset = m48t59_reset_sysbus;
- dc->props = m48t59_properties;
+ dc->props = m48t59_sysbus_properties;
+ nc->read = m48txx_sysbus_read;
+ nc->write = m48txx_sysbus_write;
+ nc->toggle_lock = m48txx_sysbus_toggle_lock;
+}
+
+static void m48txx_sysbus_concrete_class_init(ObjectClass *klass, void *data)
+{
+ M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_CLASS(klass);
+ M48txxInfo *info = data;
+
+ u->info = *info;
}
-static const TypeInfo m48t59_info = {
- .name = TYPE_SYSBUS_M48T59,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(M48t59SysBusState),
- .class_init = m48t59_class_init,
+static const TypeInfo nvram_info = {
+ .name = TYPE_NVRAM,
+ .parent = TYPE_INTERFACE,
+ .class_size = sizeof(NvramClass),
+};
+
+static const TypeInfo m48txx_sysbus_type_info = {
+ .name = TYPE_M48TXX_SYS_BUS,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(M48txxSysBusState),
+ .abstract = true,
+ .class_init = m48txx_sysbus_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_NVRAM },
+ { }
+ }
+};
+
+static const TypeInfo m48txx_isa_type_info = {
+ .name = TYPE_M48TXX_ISA,
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(M48txxISAState),
+ .abstract = true,
+ .class_init = m48txx_isa_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_NVRAM },
+ { }
+ }
};
static void m48t59_register_types(void)
{
- type_register_static(&m48t59_info);
- type_register_static(&m48t59_isa_info);
+ TypeInfo sysbus_type_info = {
+ .parent = TYPE_M48TXX_SYS_BUS,
+ .class_size = sizeof(M48txxSysBusDeviceClass),
+ .class_init = m48txx_sysbus_concrete_class_init,
+ };
+ TypeInfo isa_type_info = {
+ .parent = TYPE_M48TXX_ISA,
+ .class_size = sizeof(M48txxISADeviceClass),
+ .class_init = m48txx_isa_concrete_class_init,
+ };
+ int i;
+
+ type_register_static(&nvram_info);
+ type_register_static(&m48txx_sysbus_type_info);
+ type_register_static(&m48txx_isa_type_info);
+
+ for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
+ if (m48txx_info[i].sysbus_name) {
+ sysbus_type_info.name = m48txx_info[i].sysbus_name;
+ sysbus_type_info.class_data = &m48txx_info[i];
+ type_register(&sysbus_type_info);
+ }
+
+ if (m48txx_info[i].isa_name) {
+ isa_type_info.name = m48txx_info[i].isa_name;
+ isa_type_info.class_data = &m48txx_info[i];
+ type_register(&isa_type_info);
+ }
+ }
}
type_init(m48t59_register_types)
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 8edc314fab..dacefd71a5 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -664,6 +664,7 @@ static void usb_msd_realize_bot(USBDevice *dev, Error **errp)
static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
{
static int nr=0;
+ Error *err = NULL;
char id[8];
QemuOpts *opts;
DriveInfo *dinfo;
@@ -707,8 +708,10 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
/* create guest device */
dev = usb_create(bus, "usb-storage");
- if (qdev_prop_set_drive(&dev->qdev, "drive",
- blk_by_legacy_dinfo(dinfo)) < 0) {
+ qdev_prop_set_drive(&dev->qdev, "drive", blk_by_legacy_dinfo(dinfo),
+ &err);
+ if (err) {
+ error_report_err(err);
object_unparent(OBJECT(dev));
return NULL;
}
diff --git a/target-i386/topology.h b/include/hw/i386/topology.h
index 07a6c5fb55..9c6f3a937a 100644
--- a/target-i386/topology.h
+++ b/include/hw/i386/topology.h
@@ -21,8 +21,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#ifndef TARGET_I386_TOPOLOGY_H
-#define TARGET_I386_TOPOLOGY_H
+#ifndef HW_I386_TOPOLOGY_H
+#define HW_I386_TOPOLOGY_H
/* This file implements the APIC-ID-based CPU topology enumeration logic,
* documented at the following document:
@@ -131,4 +131,4 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores,
return apicid_from_topo_ids(nr_cores, nr_threads, pkg_id, core_id, smt_id);
}
-#endif /* TARGET_I386_TOPOLOGY_H */
+#endif /* HW_I386_TOPOLOGY_H */
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 0772a567c0..d67dad5f77 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -168,8 +168,8 @@ void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value);
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value);
-int qdev_prop_set_drive(DeviceState *dev, const char *name,
- BlockBackend *value) QEMU_WARN_UNUSED_RESULT;
+void qdev_prop_set_drive(DeviceState *dev, const char *name,
+ BlockBackend *value, Error **errp);
void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name,
BlockBackend *value);
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
diff --git a/include/hw/timer/m48t59.h b/include/hw/timer/m48t59.h
index 8217522291..3367923639 100644
--- a/include/hw/timer/m48t59.h
+++ b/include/hw/timer/m48t59.h
@@ -1,37 +1,34 @@
#ifndef NVRAM_H
#define NVRAM_H
-/* NVRAM helpers */
-typedef uint32_t (*nvram_read_t)(void *private, uint32_t addr);
-typedef void (*nvram_write_t)(void *private, uint32_t addr, uint32_t val);
-typedef struct nvram_t {
- void *opaque;
- nvram_read_t read_fn;
- nvram_write_t write_fn;
-} nvram_t;
-
-uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr);
-int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max);
-
-int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
- const char *arch,
- uint32_t RAM_size, int boot_device,
- uint32_t kernel_image, uint32_t kernel_size,
- const char *cmdline,
- uint32_t initrd_image, uint32_t initrd_size,
- uint32_t NVRAM_image,
- int width, int height, int depth);
-
-#define TYPE_SYSBUS_M48T59 "m48t59"
-
-typedef struct M48t59State M48t59State;
-
-void m48t59_write (void *private, uint32_t addr, uint32_t val);
-uint32_t m48t59_read (void *private, uint32_t addr);
-void m48t59_toggle_lock (void *private, int lock);
-M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
- int type);
-M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
- uint32_t io_base, uint16_t size, int type);
+#include "qemu-common.h"
+#include "qom/object.h"
+
+#define TYPE_NVRAM "nvram"
+
+#define NVRAM_CLASS(klass) \
+ OBJECT_CLASS_CHECK(NvramClass, (klass), TYPE_NVRAM)
+#define NVRAM_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(NvramClass, (obj), TYPE_NVRAM)
+#define NVRAM(obj) \
+ INTERFACE_CHECK(Nvram, (obj), TYPE_NVRAM)
+
+typedef struct Nvram {
+ Object parent;
+} Nvram;
+
+typedef struct NvramClass {
+ InterfaceClass parent;
+
+ uint32_t (*read)(Nvram *obj, uint32_t addr);
+ void (*write)(Nvram *obj, uint32_t addr, uint32_t val);
+ void (*toggle_lock)(Nvram *obj, int lock);
+} NvramClass;
+
+Nvram *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
+ int base_year, int type);
+Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
+ uint32_t io_base, uint16_t size, int base_year,
+ int type);
#endif /* !NVRAM_H */
diff --git a/include/ui/console.h b/include/ui/console.h
index 6e5a867fec..2f5b9f0634 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -332,7 +332,6 @@ void vnc_display_init(const char *id);
void vnc_display_open(const char *id, Error **errp);
void vnc_display_add_client(const char *id, int csock, bool skipauth);
char *vnc_display_local_addr(const char *id);
-void vnc_auto_assign_id(QemuOptsList *olist, QemuOpts *opts);
#ifdef CONFIG_VNC
int vnc_display_password(const char *id, const char *password);
int vnc_display_pw_expire(const char *id, time_t expires);
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index 994052f14d..91e4193c2d 100644
--- a/pc-bios/openbios-ppc
+++ b/pc-bios/openbios-ppc
Binary files differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index 6d5a381a7f..d693865c32 100644
--- a/pc-bios/openbios-sparc32
+++ b/pc-bios/openbios-sparc32
Binary files differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index 61bd46bf44..e5d9e5a7b1 100644
--- a/pc-bios/openbios-sparc64
+++ b/pc-bios/openbios-sparc64
Binary files differ
diff --git a/qemu-doc.texi b/qemu-doc.texi
index aabe8df2f3..f5b0dc4588 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -2052,7 +2052,7 @@ firmware implementation. The goal is to implement a 100% IEEE
A sample Linux 2.6 series kernel and ram disk image are available on
the QEMU web site. There are still issues with NetBSD and OpenBSD, but
-some kernel versions work. Please note that currently older Solaris kernels
+most kernel versions work. Please note that currently older Solaris kernels
don't work probably due to interface issues between OpenBIOS and
Solaris.
@@ -2091,8 +2091,9 @@ Set the emulated machine type. Default is SS-5.
Use the executable @file{qemu-system-sparc64} to simulate a Sun4u
(UltraSPARC PC-like machine), Sun4v (T1 PC-like machine), or generic
-Niagara (T1) machine. The emulator is not usable for anything yet, but
-it can launch some kernels.
+Niagara (T1) machine. The Sun4u emulator is mostly complete, being
+able to run Linux, NetBSD and OpenBSD in headless (-nographic) mode. The
+Sun4v and Niagara emulators are still a work in progress.
QEMU emulates the following peripherals:
diff --git a/qmp.c b/qmp.c
index d701cff5ac..c479e7751c 100644
--- a/qmp.c
+++ b/qmp.c
@@ -391,7 +391,6 @@ static void qmp_change_vnc_listen(const char *target, Error **errp)
return;
}
- vnc_auto_assign_id(olist, opts);
vnc_display_open("default", errp);
}
diff --git a/roms/openbios b/roms/openbios
-Subproject 038aa78d3c331731733378a73e778ee620a5b9d
+Subproject b8dea39718916f4d7d391cd1664314d52a45b87
diff --git a/scripts/kvm/kvm_stat b/scripts/kvm/kvm_stat
index c65cabda5a..7e5d25612b 100755
--- a/scripts/kvm/kvm_stat
+++ b/scripts/kvm/kvm_stat
@@ -519,7 +519,10 @@ def tui(screen, stats):
def refresh(sleeptime):
screen.erase()
screen.addstr(0, 0, 'kvm statistics')
- row = 2
+ screen.addstr(2, 1, 'Event')
+ screen.addstr(2, 1 + label_width + number_width - len('Total'), 'Total')
+ screen.addstr(2, 1 + label_width + number_width + 8 - len('Current'), 'Current')
+ row = 3
s = stats.get()
def sortkey(x):
if s[x][1]:
diff --git a/scripts/kvm/kvm_stat.texi b/scripts/kvm/kvm_stat.texi
new file mode 100644
index 0000000000..6ce00d80e7
--- /dev/null
+++ b/scripts/kvm/kvm_stat.texi
@@ -0,0 +1,55 @@
+@example
+@c man begin SYNOPSIS
+usage: kvm_stat [OPTION]...
+@c man end
+@end example
+
+@c man begin DESCRIPTION
+
+kvm_stat prints counts of KVM kernel module trace events. These events signify
+state transitions such as guest mode entry and exit.
+
+This tool is useful for observing guest behavior from the host perspective.
+Often conclusions about performance or buggy behavior can be drawn from the
+output.
+
+The set of KVM kernel module trace events may be specific to the kernel version
+or architecture. It is best to check the KVM kernel module source code for the
+meaning of events.
+
+Note that trace events are counted globally across all running guests.
+
+@c man end
+
+@c man begin OPTIONS
+@table @option
+@item -1, --once, --batch
+ run in batch mode for one second
+@item -l, --log
+ run in logging mode (like vmstat)
+@item -t, --tracepoints
+ retrieve statistics from tracepoints
+@item -d, --debugfs
+ retrieve statistics from debugfs
+@item -f, --fields=@var{fields}
+ fields to display (regex)
+@item -h, --help
+ show help message
+@end table
+
+@c man end
+
+@ignore
+
+@setfilename kvm_stat
+@settitle Report KVM kernel module event counters.
+
+@c man begin AUTHOR
+Stefan Hajnoczi <stefanha@redhat.com>
+@c man end
+
+@c man begin SEEALSO
+perf(1), trace-cmd(1)
+@c man end
+
+@end ignore
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index b557b619cf..31a0c1e776 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -93,6 +93,7 @@ typedef struct X86CPU {
bool expose_kvm;
bool migratable;
bool host_features;
+ int64_t apic_id;
/* if true the CPUID code directly forward host cache leaves to the guest */
bool cache_info_passthrough;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 97777fb57a..ed7e5d5de3 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -25,7 +25,6 @@
#include "sysemu/kvm.h"
#include "sysemu/cpus.h"
#include "kvm_i386.h"
-#include "topology.h"
#include "qemu/option.h"
#include "qemu/config-file.h"
@@ -1690,7 +1689,7 @@ static void x86_cpuid_get_apic_id(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
- int64_t value = cpu->env.cpuid_apic_id;
+ int64_t value = cpu->apic_id;
visit_type_int(v, &value, name, errp);
}
@@ -1723,11 +1722,11 @@ static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque,
return;
}
- if ((value != cpu->env.cpuid_apic_id) && cpu_exists(value)) {
+ if ((value != cpu->apic_id) && cpu_exists(value)) {
error_setg(errp, "CPU with APIC ID %" PRIi64 " exists", value);
return;
}
- cpu->env.cpuid_apic_id = value;
+ cpu->apic_id = value;
}
/* Generic getter for "feature-words" and "filtered-features" properties */
@@ -1911,34 +1910,19 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
}
}
-/* generate a composite string into buf of all cpuid names in featureset
- * selected by fbits. indicate truncation at bufsize in the event of overflow.
- * if flags, suppress names undefined in featureset.
+/* Print all cpuid feature names in featureset
*/
-static void listflags(char *buf, int bufsize, uint32_t fbits,
- const char **featureset, uint32_t flags)
-{
- const char **p = &featureset[31];
- char *q, *b, bit;
- int nc;
-
- b = 4 <= bufsize ? buf + (bufsize -= 3) - 1 : NULL;
- *buf = '\0';
- for (q = buf, bit = 31; fbits && bufsize; --p, fbits &= ~(1 << bit), --bit)
- if (fbits & 1 << bit && (*p || !flags)) {
- if (*p)
- nc = snprintf(q, bufsize, "%s%s", q == buf ? "" : " ", *p);
- else
- nc = snprintf(q, bufsize, "%s[%d]", q == buf ? "" : " ", bit);
- if (bufsize <= nc) {
- if (b) {
- memcpy(b, "...", sizeof("..."));
- }
- return;
- }
- q += nc;
- bufsize -= nc;
+static void listflags(FILE *f, fprintf_function print, const char **featureset)
+{
+ int bit;
+ bool first = true;
+
+ for (bit = 0; bit < 32; bit++) {
+ if (featureset[bit]) {
+ print(f, "%s%s", first ? "" : " ", featureset[bit]);
+ first = false;
}
+ }
}
/* generate CPU information. */
@@ -1963,8 +1947,9 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf)
for (i = 0; i < ARRAY_SIZE(feature_word_info); i++) {
FeatureWordInfo *fw = &feature_word_info[i];
- listflags(buf, sizeof(buf), (uint32_t)~0, fw->feat_names, 1);
- (*cpu_fprintf)(f, " %s\n", buf);
+ (*cpu_fprintf)(f, " ");
+ listflags(f, cpu_fprintf, fw->feat_names);
+ (*cpu_fprintf)(f, "\n");
}
}
@@ -2227,14 +2212,6 @@ void x86_cpudef_setup(void)
}
}
-static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
- uint32_t *ecx, uint32_t *edx)
-{
- *ebx = env->cpuid_vendor1;
- *edx = env->cpuid_vendor2;
- *ecx = env->cpuid_vendor3;
-}
-
void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
@@ -2268,11 +2245,14 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
switch(index) {
case 0:
*eax = env->cpuid_level;
- get_cpuid_vendor(env, ebx, ecx, edx);
+ *ebx = env->cpuid_vendor1;
+ *edx = env->cpuid_vendor2;
+ *ecx = env->cpuid_vendor3;
break;
case 1:
*eax = env->cpuid_version;
- *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
+ *ebx = (cpu->apic_id << 24) |
+ 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
*ecx = env->features[FEAT_1_ECX];
*edx = env->features[FEAT_1_EDX];
if (cs->nr_cores * cs->nr_threads > 1) {
@@ -2461,11 +2441,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
* So dont set it here for Intel to make Linux guests happy.
*/
if (cs->nr_cores * cs->nr_threads > 1) {
- uint32_t tebx, tecx, tedx;
- get_cpuid_vendor(env, &tebx, &tecx, &tedx);
- if (tebx != CPUID_VENDOR_INTEL_1 ||
- tedx != CPUID_VENDOR_INTEL_2 ||
- tecx != CPUID_VENDOR_INTEL_3) {
+ if (env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 ||
+ env->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 ||
+ env->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) {
*ecx |= 1 << 1; /* CmpLegacy bit */
}
}
@@ -2721,7 +2699,6 @@ static void mce_init(X86CPU *cpu)
#ifndef CONFIG_USER_ONLY
static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
{
- CPUX86State *env = &cpu->env;
DeviceState *dev = DEVICE(cpu);
APICCommonState *apic;
const char *apic_type = "apic";
@@ -2740,7 +2717,7 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
object_property_add_child(OBJECT(cpu), "apic",
OBJECT(cpu->apic_state), NULL);
- qdev_prop_set_uint8(cpu->apic_state, "id", env->cpuid_apic_id);
+ qdev_prop_set_uint8(cpu->apic_state, "id", cpu->apic_id);
/* TODO: convert to link<> */
apic = APIC_COMMON(cpu->apic_state);
apic->cpu = cpu;
@@ -2776,6 +2753,11 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
Error *local_err = NULL;
static bool ht_warned;
+ if (cpu->apic_id < 0) {
+ error_setg(errp, "apic-id property was not initialized properly");
+ return;
+ }
+
if (env->features[FEAT_7_0_EBX] && env->cpuid_level < 7) {
env->cpuid_level = 7;
}
@@ -2840,39 +2822,6 @@ out:
}
}
-/* Enables contiguous-apic-ID mode, for compatibility */
-static bool compat_apic_id_mode;
-
-void enable_compat_apic_id_mode(void)
-{
- compat_apic_id_mode = true;
-}
-
-/* Calculates initial APIC ID for a specific CPU index
- *
- * Currently we need to be able to calculate the APIC ID from the CPU index
- * alone (without requiring a CPU object), as the QEMU<->Seabios interfaces have
- * no concept of "CPU index", and the NUMA tables on fw_cfg need the APIC ID of
- * all CPUs up to max_cpus.
- */
-uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index)
-{
- uint32_t correct_id;
- static bool warned;
-
- correct_id = x86_apicid_from_cpu_idx(smp_cores, smp_threads, cpu_index);
- if (compat_apic_id_mode) {
- if (cpu_index != correct_id && !warned) {
- error_report("APIC IDs set in compatibility mode, "
- "CPU topology won't match the configuration");
- warned = true;
- }
- return cpu_index;
- } else {
- return correct_id;
- }
-}
-
static void x86_cpu_initfn(Object *obj)
{
CPUState *cs = CPU(obj);
@@ -2919,7 +2868,11 @@ static void x86_cpu_initfn(Object *obj)
NULL, NULL, (void *)cpu->filtered_features, NULL);
cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY;
- env->cpuid_apic_id = x86_cpu_apic_id_from_index(cs->cpu_index);
+
+#ifndef CONFIG_USER_ONLY
+ /* Any code creating new X86CPU objects have to set apic-id explicitly */
+ cpu->apic_id = -1;
+#endif
x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort);
@@ -2933,9 +2886,8 @@ static void x86_cpu_initfn(Object *obj)
static int64_t x86_cpu_get_arch_id(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- return env->cpuid_apic_id;
+ return cpu->apic_id;
}
static bool x86_cpu_get_paging_enabled(const CPUState *cs)
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 425580372e..e4c27b1fa8 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -944,7 +944,6 @@ typedef struct CPUX86State {
uint32_t cpuid_version;
FeatureWordArray features;
uint32_t cpuid_model[12];
- uint32_t cpuid_apic_id;
/* MTRRs */
uint64_t mtrr_fixed[11];
@@ -1322,7 +1321,6 @@ void x86_cpu_compat_kvm_no_autodisable(FeatureWord w, uint32_t features);
/* Return name of 32-bit register, from a R_* constant */
const char *get_register_name_32(unsigned int reg);
-uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index);
void enable_compat_apic_id_mode(void);
#define APIC_DEFAULT_ADDRESS 0xfee00000
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 40d6a14c85..27fe2be653 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -430,7 +430,7 @@ static void cpu_update_state(void *opaque, int running, RunState state)
unsigned long kvm_arch_vcpu_id(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
- return cpu->env.cpuid_apic_id;
+ return cpu->apic_id;
}
#ifndef KVM_CPUID_SIGNATURE_NEXT
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index fa374d0c0b..2bc757af31 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -1043,7 +1043,7 @@ void helper_sysret(CPUX86State *env, int dflag)
DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
env->eip = (uint32_t)env->regs[R_ECX];
}
- cpu_x86_load_seg_cache(env, R_SS, selector + 8,
+ cpu_x86_load_seg_cache(env, R_SS, (selector + 8) | 3,
0, 0xffffffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
@@ -1056,7 +1056,7 @@ void helper_sysret(CPUX86State *env, int dflag)
DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
env->eip = (uint32_t)env->regs[R_ECX];
- cpu_x86_load_seg_cache(env, R_SS, selector + 8,
+ cpu_x86_load_seg_cache(env, R_SS, (selector + 8) | 3,
0, 0xffffffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
diff --git a/tests/Makefile b/tests/Makefile
index fed8096e94..588f43888c 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -241,8 +241,6 @@ $(test-obj-y): QEMU_INCLUDES += -Itests
QEMU_CFLAGS += -I$(SRC_PATH)/tests
qom-core-obj = qom/object.o qom/qom-qobject.o qom/container.o
-tests/test-x86-cpuid.o: QEMU_INCLUDES += -I$(SRC_PATH)/target-i386
-
tests/check-qint$(EXESUF): tests/check-qint.o libqemuutil.a
tests/check-qstring$(EXESUF): tests/check-qstring.o libqemuutil.a
tests/check-qdict$(EXESUF): tests/check-qdict.o libqemuutil.a
diff --git a/tests/test-x86-cpuid.c b/tests/test-x86-cpuid.c
index 8d9f96a113..6cd20d4a23 100644
--- a/tests/test-x86-cpuid.c
+++ b/tests/test-x86-cpuid.c
@@ -24,7 +24,7 @@
#include <glib.h>
-#include "topology.h"
+#include "hw/i386/topology.h"
static void test_topo_bits(void)
{
diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
index e304bafeb0..d75950d7b1 100644
--- a/ui/vnc-ws.c
+++ b/ui/vnc-ws.c
@@ -207,8 +207,7 @@ static void vncws_send_handshake_response(VncState *vs, const char* key)
}
response = g_strdup_printf(WS_HANDSHAKE, accept);
- vnc_write(vs, response, strlen(response));
- vnc_flush(vs);
+ vnc_client_write_buf(vs, (const uint8_t *)response, strlen(response));
g_free(accept);
g_free(response);
diff --git a/ui/vnc.c b/ui/vnc.c
index 10a272450b..ff0b5bda9b 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3687,12 +3687,7 @@ void vnc_display_add_client(const char *id, int csock, bool skipauth)
vnc_connect(vs, csock, skipauth, false);
}
-QemuOpts *vnc_parse_func(const char *str)
-{
- return qemu_opts_parse(qemu_find_opts("vnc"), str, 1);
-}
-
-void vnc_auto_assign_id(QemuOptsList *olist, QemuOpts *opts)
+static void vnc_auto_assign_id(QemuOptsList *olist, QemuOpts *opts)
{
int i = 2;
char *id;
@@ -3705,18 +3700,25 @@ void vnc_auto_assign_id(QemuOptsList *olist, QemuOpts *opts)
qemu_opts_set_id(opts, id);
}
-int vnc_init_func(QemuOpts *opts, void *opaque)
+QemuOpts *vnc_parse_func(const char *str)
{
- Error *local_err = NULL;
QemuOptsList *olist = qemu_find_opts("vnc");
- char *id = (char *)qemu_opts_id(opts);
+ QemuOpts *opts = qemu_opts_parse(olist, str, 1);
+ const char *id = qemu_opts_id(opts);
if (!id) {
/* auto-assign id if not present */
vnc_auto_assign_id(olist, opts);
- id = (char *)qemu_opts_id(opts);
}
+ return opts;
+}
+
+int vnc_init_func(QemuOpts *opts, void *opaque)
+{
+ Error *local_err = NULL;
+ char *id = (char *)qemu_opts_id(opts);
+ assert(id);
vnc_display_init(id);
vnc_display_open(id, &local_err);
if (local_err != NULL) {
diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
index 50a29d8f7a..ba67cec62b 100644
--- a/util/qemu-thread-posix.c
+++ b/util/qemu-thread-posix.c
@@ -51,12 +51,8 @@ static void error_exit(int err, const char *msg)
void qemu_mutex_init(QemuMutex *mutex)
{
int err;
- pthread_mutexattr_t mutexattr;
- pthread_mutexattr_init(&mutexattr);
- pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
- err = pthread_mutex_init(&mutex->lock, &mutexattr);
- pthread_mutexattr_destroy(&mutexattr);
+ err = pthread_mutex_init(&mutex->lock, NULL);
if (err)
error_exit(err, __func__);
}
diff --git a/util/rcu.c b/util/rcu.c
index bd73b8eb47..27802a4bed 100644
--- a/util/rcu.c
+++ b/util/rcu.c
@@ -283,7 +283,7 @@ void rcu_unregister_thread(void)
qemu_mutex_unlock(&rcu_gp_lock);
}
-static void __attribute__((__constructor__)) rcu_init(void)
+static void rcu_init_complete(void)
{
QemuThread thread;
@@ -291,8 +291,39 @@ static void __attribute__((__constructor__)) rcu_init(void)
qemu_event_init(&rcu_gp_event, true);
qemu_event_init(&rcu_call_ready_event, false);
+
+ /* The caller is assumed to have iothread lock, so the call_rcu thread
+ * must have been quiescent even after forking, just recreate it.
+ */
qemu_thread_create(&thread, "call_rcu", call_rcu_thread,
NULL, QEMU_THREAD_DETACHED);
rcu_register_thread();
}
+
+#ifdef CONFIG_POSIX
+static void rcu_init_lock(void)
+{
+ qemu_mutex_lock(&rcu_gp_lock);
+}
+
+static void rcu_init_unlock(void)
+{
+ qemu_mutex_unlock(&rcu_gp_lock);
+}
+
+static void rcu_init_child(void)
+{
+ qemu_mutex_unlock(&rcu_gp_lock);
+ memset(&registry, 0, sizeof(registry));
+ rcu_init_complete();
+}
+#endif
+
+static void __attribute__((__constructor__)) rcu_init(void)
+{
+#ifdef CONFIG_POSIX
+ pthread_atfork(rcu_init_lock, rcu_init_unlock, rcu_init_child);
+#endif
+ rcu_init_complete();
+}
diff --git a/vl.c b/vl.c
index b47e223a49..eba5d4c99b 100644
--- a/vl.c
+++ b/vl.c
@@ -2001,7 +2001,6 @@ static DisplayType select_display(const char *p)
} else if (strstart(p, "vnc", &opts)) {
#ifdef CONFIG_VNC
if (*opts == '=') {
- display_remote++;
if (vnc_parse_func(opts+1) == NULL) {
exit(1);
}
@@ -3477,7 +3476,6 @@ int main(int argc, char **argv, char **envp)
break;
case QEMU_OPTION_vnc:
#ifdef CONFIG_VNC
- display_remote++;
if (vnc_parse_func(optarg) == NULL) {
exit(1);
}
@@ -3970,6 +3968,11 @@ int main(int argc, char **argv, char **envp)
}
}
+#if defined(CONFIG_VNC)
+ if (!QTAILQ_EMPTY(&(qemu_find_opts("vnc")->head))) {
+ display_remote++;
+ }
+#endif
if (display_type == DT_DEFAULT && !display_remote) {
#if defined(CONFIG_GTK)
display_type = DT_GTK;