aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-08-23 19:03:53 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-08-23 19:03:54 +0100
commit3c825bb7c1b4289ef05f51b5b77ac0967b6a27fa (patch)
tree44c5189aacbe795b125bfb4b5144a37fe122d2e4 /hw
parent5ccac548faf041ff5229a8e8342e3be14a34c8af (diff)
parentb2e78fac6f27c36938353e477354778896adc08f (diff)
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* x86 TCG fixes for 64-bit call gates (Andrew) * qumu-guest-agent freeze-hook tweak (Christian) * pm_smbus improvements (Corey) * Move validation to pre_plug for pc-dimm (David) * Fix memory leaks (Eduardo, Marc-André) * synchronization profiler (Emilio) * Convert the CPU list to RCU (Emilio) * LSI support for PPR Extended Message (George) * vhost-scsi support for protection information (Greg) * Mark mptsas as a storage device in the help (Guenter) * checkpatch tweak cherry-picked from Linux (me) * Typos, cleanups and dead-code removal (Julia, Marc-André) * qemu-pr-helper support for old libmultipath (Murilo) * Annotate fallthroughs (me) * MemoryRegionOps cleanup (me, Peter) * Make s390 qtests independent from libqos, which doesn't actually support it (me) * Make cpu_get_ticks independent from BQL (me) * Introspection fixes (Thomas) * Support QEMU_MODULE_DIR environment variable (ryang) # gpg: Signature made Thu 23 Aug 2018 17:46:30 BST # gpg: using RSA key BFFBD25F78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: (69 commits) KVM: cleanup unnecessary #ifdef KVM_CAP_... target/i386: update MPX flags when CPL changes i2c: pm_smbus: Add the ability to force block transfer enable i2c: pm_smbus: Don't delay host status register busy bit when interrupts are enabled i2c: pm_smbus: Add interrupt handling i2c: pm_smbus: Add block transfer capability i2c: pm_smbus: Make the I2C block read command read-only i2c: pm_smbus: Fix the semantics of block I2C transfers i2c: pm_smbus: Clean up some style issues pc-dimm: assign and verify the "addr" property during pre_plug pc: drop memory region alignment check for 0 util/oslib-win32: indicate alignment for qemu_anon_ram_alloc() pc-dimm: assign and verify the "slot" property during pre_plug ipmi: Use proper struct reference for BT vmstate vhost-scsi: expose 't10_pi' property for VIRTIO_SCSI_F_T10_PI vhost-scsi: unify vhost-scsi get_features implementations vhost-user-scsi: move host_features into VHostSCSICommon cpus: allow cpu_get_ticks out of BQL cpus: protect TimerState writes with a spinlock seqlock: add QemuLockable support ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/piix4.c2
-rw-r--r--hw/arm/pxa2xx.c2
-rw-r--r--hw/audio/cs4231a.c1
-rw-r--r--hw/audio/es1370.c235
-rw-r--r--hw/audio/gusemu_hal.c1
-rw-r--r--hw/audio/sb16.c11
-rw-r--r--hw/display/cg3.c1
-rw-r--r--hw/display/cirrus_vga.c3
-rw-r--r--hw/i2c/pm_smbus.c254
-rw-r--r--hw/i2c/smbus.c37
-rw-r--r--hw/i2c/smbus_ich9.c26
-rw-r--r--hw/i386/pc.c16
-rw-r--r--hw/intc/apic.c42
-rw-r--r--hw/ipmi/isa_ipmi_bt.c68
-rw-r--r--hw/isa/vt82c686.c2
-rw-r--r--hw/mem/pc-dimm.c61
-rw-r--r--hw/misc/vmcoreinfo.c6
-rw-r--r--hw/ppc/prep.c3
-rw-r--r--hw/ppc/spapr.c30
-rw-r--r--hw/scsi/lsi53c895a.c4
-rw-r--r--hw/scsi/megasas.c2
-rw-r--r--hw/scsi/mptsas.c1
-rw-r--r--hw/scsi/vhost-scsi-common.c3
-rw-r--r--hw/scsi/vhost-scsi.c3
-rw-r--r--hw/scsi/vhost-user-scsi.c28
-rw-r--r--hw/timer/mc146818rtc.c20
-rw-r--r--hw/timer/sh_timer.c1
27 files changed, 474 insertions, 389 deletions
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 6404af5f33..e330f24c71 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -512,7 +512,7 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp)
pci_conf[0x90] = s->smb_io_base | 1;
pci_conf[0x91] = s->smb_io_base >> 8;
pci_conf[0xd2] = 0x09;
- pm_smbus_init(DEVICE(dev), &s->smb);
+ pm_smbus_init(DEVICE(dev), &s->smb, true);
memory_region_set_enabled(&s->smb.io, pci_conf[0xd2] & 1);
memory_region_add_subregion(pci_address_space_io(dev),
s->smb_io_base, &s->smb.io);
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index b67b0cefb6..f598a1c053 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -409,7 +409,7 @@ static uint64_t pxa2xx_mm_read(void *opaque, hwaddr addr,
case MDCNFG ... SA1110:
if ((addr & 3) == 0)
return s->mm_regs[addr >> 2];
-
+ /* fall through */
default:
printf("%s: Bad register " REG_FMT "\n", __func__, addr);
break;
diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c
index aaebec1839..9089dcb47e 100644
--- a/hw/audio/cs4231a.c
+++ b/hw/audio/cs4231a.c
@@ -305,6 +305,7 @@ static void cs_reset_voices (CSState *s, uint32_t val)
case 6:
as.endianness = 1;
+ /* fall through */
case 2:
as.fmt = AUD_FMT_S16;
s->shift = as.nchannels;
diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c
index 59cf252754..dd75c9e8f5 100644
--- a/hw/audio/es1370.c
+++ b/hw/audio/es1370.c
@@ -474,82 +474,7 @@ static inline uint32_t es1370_fixup (ES1370State *s, uint32_t addr)
return addr;
}
-static void es1370_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
- ES1370State *s = opaque;
- uint32_t shift, mask;
-
- addr = es1370_fixup (s, addr);
-
- switch (addr) {
- case ES1370_REG_CONTROL:
- case ES1370_REG_CONTROL + 1:
- case ES1370_REG_CONTROL + 2:
- case ES1370_REG_CONTROL + 3:
- shift = (addr - ES1370_REG_CONTROL) << 3;
- mask = 0xff << shift;
- val = (s->ctl & ~mask) | ((val & 0xff) << shift);
- es1370_update_voices (s, val, s->sctl);
- print_ctl (val);
- break;
- case ES1370_REG_MEMPAGE:
- s->mempage = val;
- break;
- case ES1370_REG_SERIAL_CONTROL:
- case ES1370_REG_SERIAL_CONTROL + 1:
- case ES1370_REG_SERIAL_CONTROL + 2:
- case ES1370_REG_SERIAL_CONTROL + 3:
- shift = (addr - ES1370_REG_SERIAL_CONTROL) << 3;
- mask = 0xff << shift;
- val = (s->sctl & ~mask) | ((val & 0xff) << shift);
- es1370_maybe_lower_irq (s, val);
- es1370_update_voices (s, s->ctl, val);
- print_sctl (val);
- break;
- default:
- lwarn ("writeb %#x <- %#x\n", addr, val);
- break;
- }
-}
-
-static void es1370_writew(void *opaque, uint32_t addr, uint32_t val)
-{
- ES1370State *s = opaque;
- addr = es1370_fixup (s, addr);
- uint32_t shift, mask;
- struct chan *d = &s->chan[0];
-
- switch (addr) {
- case ES1370_REG_CODEC:
- dolog ("ignored codec write address %#x, data %#x\n",
- (val >> 8) & 0xff, val & 0xff);
- s->codec = val;
- break;
-
- case ES1370_REG_CONTROL:
- case ES1370_REG_CONTROL + 2:
- shift = (addr != ES1370_REG_CONTROL) << 4;
- mask = 0xffff << shift;
- val = (s->ctl & ~mask) | ((val & 0xffff) << shift);
- es1370_update_voices (s, val, s->sctl);
- print_ctl (val);
- break;
-
- case ES1370_REG_ADC_SCOUNT:
- d++;
- case ES1370_REG_DAC2_SCOUNT:
- d++;
- case ES1370_REG_DAC1_SCOUNT:
- d->scount = (d->scount & ~0xffff) | (val & 0xffff);
- break;
-
- default:
- lwarn ("writew %#x <- %#x\n", addr, val);
- break;
- }
-}
-
-static void es1370_writel(void *opaque, uint32_t addr, uint32_t val)
+static void es1370_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
{
ES1370State *s = opaque;
struct chan *d = &s->chan[0];
@@ -572,21 +497,19 @@ static void es1370_writel(void *opaque, uint32_t addr, uint32_t val)
print_sctl (val);
break;
- case ES1370_REG_ADC_SCOUNT:
- d++;
- case ES1370_REG_DAC2_SCOUNT:
- d++;
case ES1370_REG_DAC1_SCOUNT:
+ case ES1370_REG_DAC2_SCOUNT:
+ case ES1370_REG_ADC_SCOUNT:
+ d += (addr - ES1370_REG_DAC1_SCOUNT) >> 2;
d->scount = (val & 0xffff) | (d->scount & ~0xffff);
ldebug ("chan %td CURR_SAMP_CT %d, SAMP_CT %d\n",
d - &s->chan[0], val >> 16, (val & 0xffff));
break;
- case ES1370_REG_ADC_FRAMEADR:
- d++;
- case ES1370_REG_DAC2_FRAMEADR:
- d++;
case ES1370_REG_DAC1_FRAMEADR:
+ case ES1370_REG_DAC2_FRAMEADR:
+ case ES1370_REG_ADC_FRAMEADR:
+ d += (addr - ES1370_REG_DAC1_FRAMEADR) >> 3;
d->frame_addr = val;
ldebug ("chan %td frame address %#x\n", d - &s->chan[0], val);
break;
@@ -598,11 +521,10 @@ static void es1370_writel(void *opaque, uint32_t addr, uint32_t val)
lwarn ("writing to phantom frame address %#x\n", val);
break;
- case ES1370_REG_ADC_FRAMECNT:
- d++;
- case ES1370_REG_DAC2_FRAMECNT:
- d++;
case ES1370_REG_DAC1_FRAMECNT:
+ case ES1370_REG_DAC2_FRAMECNT:
+ case ES1370_REG_ADC_FRAMECNT:
+ d += (addr - ES1370_REG_DAC1_FRAMECNT) >> 3;
d->frame_cnt = val;
d->leftover = 0;
ldebug ("chan %td frame count %d, buffer size %d\n",
@@ -615,84 +537,7 @@ static void es1370_writel(void *opaque, uint32_t addr, uint32_t val)
}
}
-static uint32_t es1370_readb(void *opaque, uint32_t addr)
-{
- ES1370State *s = opaque;
- uint32_t val;
-
- addr = es1370_fixup (s, addr);
-
- switch (addr) {
- case 0x1b: /* Legacy */
- lwarn ("Attempt to read from legacy register\n");
- val = 5;
- break;
- case ES1370_REG_MEMPAGE:
- val = s->mempage;
- break;
- case ES1370_REG_CONTROL + 0:
- case ES1370_REG_CONTROL + 1:
- case ES1370_REG_CONTROL + 2:
- case ES1370_REG_CONTROL + 3:
- val = s->ctl >> ((addr - ES1370_REG_CONTROL) << 3);
- break;
- case ES1370_REG_STATUS + 0:
- case ES1370_REG_STATUS + 1:
- case ES1370_REG_STATUS + 2:
- case ES1370_REG_STATUS + 3:
- val = s->status >> ((addr - ES1370_REG_STATUS) << 3);
- break;
- default:
- val = ~0;
- lwarn ("readb %#x -> %#x\n", addr, val);
- break;
- }
- return val;
-}
-
-static uint32_t es1370_readw(void *opaque, uint32_t addr)
-{
- ES1370State *s = opaque;
- struct chan *d = &s->chan[0];
- uint32_t val;
-
- addr = es1370_fixup (s, addr);
-
- switch (addr) {
- case ES1370_REG_ADC_SCOUNT + 2:
- d++;
- case ES1370_REG_DAC2_SCOUNT + 2:
- d++;
- case ES1370_REG_DAC1_SCOUNT + 2:
- val = d->scount >> 16;
- break;
-
- case ES1370_REG_ADC_FRAMECNT:
- d++;
- case ES1370_REG_DAC2_FRAMECNT:
- d++;
- case ES1370_REG_DAC1_FRAMECNT:
- val = d->frame_cnt & 0xffff;
- break;
-
- case ES1370_REG_ADC_FRAMECNT + 2:
- d++;
- case ES1370_REG_DAC2_FRAMECNT + 2:
- d++;
- case ES1370_REG_DAC1_FRAMECNT + 2:
- val = d->frame_cnt >> 16;
- break;
-
- default:
- val = ~0;
- lwarn ("readw %#x -> %#x\n", addr, val);
- break;
- }
-
- return val;
-}
-
-static uint32_t es1370_readl(void *opaque, uint32_t addr)
+static uint64_t es1370_read(void *opaque, hwaddr addr, unsigned size)
{
ES1370State *s = opaque;
uint32_t val;
@@ -717,11 +562,10 @@ static uint32_t es1370_readl(void *opaque, uint32_t addr)
val = s->sctl;
break;
- case ES1370_REG_ADC_SCOUNT:
- d++;
- case ES1370_REG_DAC2_SCOUNT:
- d++;
case ES1370_REG_DAC1_SCOUNT:
+ case ES1370_REG_DAC2_SCOUNT:
+ case ES1370_REG_ADC_SCOUNT:
+ d += (addr - ES1370_REG_DAC1_SCOUNT) >> 2;
val = d->scount;
#ifdef DEBUG_ES1370
{
@@ -735,11 +579,10 @@ static uint32_t es1370_readl(void *opaque, uint32_t addr)
#endif
break;
- case ES1370_REG_ADC_FRAMECNT:
- d++;
- case ES1370_REG_DAC2_FRAMECNT:
- d++;
case ES1370_REG_DAC1_FRAMECNT:
+ case ES1370_REG_DAC2_FRAMECNT:
+ case ES1370_REG_ADC_FRAMECNT:
+ d += (addr - ES1370_REG_DAC1_FRAMECNT) >> 3;
val = d->frame_cnt;
#ifdef DEBUG_ES1370
{
@@ -753,11 +596,10 @@ static uint32_t es1370_readl(void *opaque, uint32_t addr)
#endif
break;
- case ES1370_REG_ADC_FRAMEADR:
- d++;
- case ES1370_REG_DAC2_FRAMEADR:
- d++;
case ES1370_REG_DAC1_FRAMEADR:
+ case ES1370_REG_DAC2_FRAMEADR:
+ case ES1370_REG_ADC_FRAMEADR:
+ d += (addr - ES1370_REG_DAC1_FRAMEADR) >> 3;
val = d->frame_addr;
break;
@@ -908,44 +750,17 @@ static void es1370_adc_callback (void *opaque, int avail)
es1370_run_channel (s, ADC_CHANNEL, avail);
}
-static uint64_t es1370_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- switch (size) {
- case 1:
- return es1370_readb(opaque, addr);
- case 2:
- return es1370_readw(opaque, addr);
- case 4:
- return es1370_readl(opaque, addr);
- default:
- return -1;
- }
-}
-
-static void es1370_write(void *opaque, hwaddr addr, uint64_t val,
- unsigned size)
-{
- switch (size) {
- case 1:
- es1370_writeb(opaque, addr, val);
- break;
- case 2:
- es1370_writew(opaque, addr, val);
- break;
- case 4:
- es1370_writel(opaque, addr, val);
- break;
- }
-}
-
static const MemoryRegionOps es1370_io_ops = {
.read = es1370_read,
.write = es1370_write,
- .impl = {
+ .valid = {
.min_access_size = 1,
.max_access_size = 4,
},
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
.endianness = DEVICE_LITTLE_ENDIAN,
};
diff --git a/hw/audio/gusemu_hal.c b/hw/audio/gusemu_hal.c
index 1150fc4426..ae40ca341c 100644
--- a/hw/audio/gusemu_hal.c
+++ b/hw/audio/gusemu_hal.c
@@ -261,6 +261,7 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
GUSregb(IRQStatReg2x6) = 0x10;
GUS_irqrequest(state, state->gusirq, 1);
}
+ /* fall through */
case 0x20D: /* SB2xCd no IRQ */
GUSregb(SB2xCd) = (uint8_t) data;
break;
diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c
index 5a4d32364e..c5b9bf79e8 100644
--- a/hw/audio/sb16.c
+++ b/hw/audio/sb16.c
@@ -741,10 +741,15 @@ static void complete (SB16State *s)
ldebug ("set time const %d\n", s->time_const);
break;
- case 0x42: /* FT2 sets output freq with this, go figure */
- qemu_log_mask(LOG_UNIMP, "cmd 0x42 might not do what it think it"
- " should\n");
case 0x41:
+ case 0x42:
+ /*
+ * 0x41 is documented as setting the output sample rate,
+ * and 0x42 the input sample rate, but in fact SB16 hardware
+ * seems to have only a single sample rate under the hood,
+ * and FT2 sets output freq with this (go figure). Compare:
+ * http://homepages.cae.wisc.edu/~brodskye/sb16doc/sb16doc.html#SamplingRate
+ */
s->freq = dsp_get_hilo (s);
ldebug ("set freq %d\n", s->freq);
break;
diff --git a/hw/display/cg3.c b/hw/display/cg3.c
index 6fff4852c5..1c199ab369 100644
--- a/hw/display/cg3.c
+++ b/hw/display/cg3.c
@@ -232,6 +232,7 @@ static void cg3_reg_write(void *opaque, hwaddr addr, uint64_t val,
s->b[s->dac_index] = regval;
/* Index autoincrement */
s->dac_index = (s->dac_index + 1) & 0xff;
+ /* fall through */
default:
s->dac_state = 0;
break;
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 7583b18c29..04c87c8e8d 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -1426,7 +1426,8 @@ static void cirrus_vga_write_sr(CirrusVGAState * s, uint32_t val)
s->vga.hw_cursor_y = (val << 3) | (s->vga.sr_index >> 5);
break;
case 0x07: // Extended Sequencer Mode
- cirrus_update_memory_access(s);
+ cirrus_update_memory_access(s);
+ /* fall through */
case 0x08: // EEPROM Control
case 0x09: // Scratch Register 0
case 0x0a: // Scratch Register 1
diff --git a/hw/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c
index 0d26e0f6b5..685a2378ed 100644
--- a/hw/i2c/pm_smbus.c
+++ b/hw/i2c/pm_smbus.c
@@ -22,8 +22,6 @@
#include "hw/i2c/pm_smbus.h"
#include "hw/i2c/smbus.h"
-/* no save/load? */
-
#define SMBHSTSTS 0x00
#define SMBHSTCNT 0x02
#define SMBHSTCMD 0x03
@@ -31,20 +29,40 @@
#define SMBHSTDAT0 0x05
#define SMBHSTDAT1 0x06
#define SMBBLKDAT 0x07
+#define SMBAUXCTL 0x0d
-#define STS_HOST_BUSY (1)
-#define STS_INTR (1<<1)
-#define STS_DEV_ERR (1<<2)
-#define STS_BUS_ERR (1<<3)
-#define STS_FAILED (1<<4)
-#define STS_SMBALERT (1<<5)
-#define STS_INUSE_STS (1<<6)
-#define STS_BYTE_DONE (1<<7)
+#define STS_HOST_BUSY (1 << 0)
+#define STS_INTR (1 << 1)
+#define STS_DEV_ERR (1 << 2)
+#define STS_BUS_ERR (1 << 3)
+#define STS_FAILED (1 << 4)
+#define STS_SMBALERT (1 << 5)
+#define STS_INUSE_STS (1 << 6)
+#define STS_BYTE_DONE (1 << 7)
/* Signs of successfully transaction end :
* ByteDoneStatus = 1 (STS_BYTE_DONE) and INTR = 1 (STS_INTR )
*/
-//#define DEBUG
+#define CTL_INTREN (1 << 0)
+#define CTL_KILL (1 << 1)
+#define CTL_LAST_BYTE (1 << 5)
+#define CTL_START (1 << 6)
+#define CTL_PEC_EN (1 << 7)
+#define CTL_RETURN_MASK 0x1f
+
+#define PROT_QUICK 0
+#define PROT_BYTE 1
+#define PROT_BYTE_DATA 2
+#define PROT_WORD_DATA 3
+#define PROT_PROC_CALL 4
+#define PROT_BLOCK_DATA 5
+#define PROT_I2C_BLOCK_READ 6
+
+#define AUX_PEC (1 << 0)
+#define AUX_BLK (1 << 1)
+#define AUX_MASK 0x3
+
+/*#define DEBUG*/
#ifdef DEBUG
# define SMBUS_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
@@ -62,19 +80,17 @@ static void smb_transaction(PMSMBus *s)
I2CBus *bus = s->smbus;
int ret;
- assert(s->smb_stat & STS_HOST_BUSY);
- s->smb_stat &= ~STS_HOST_BUSY;
-
SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
/* Transaction isn't exec if STS_DEV_ERR bit set */
if ((s->smb_stat & STS_DEV_ERR) != 0) {
goto error;
}
+
switch(prot) {
- case 0x0:
+ case PROT_QUICK:
ret = smbus_quick_command(bus, addr, read);
goto done;
- case 0x1:
+ case PROT_BYTE:
if (read) {
ret = smbus_receive_byte(bus, addr);
goto data8;
@@ -82,7 +98,7 @@ static void smb_transaction(PMSMBus *s)
ret = smbus_send_byte(bus, addr, cmd);
goto done;
}
- case 0x2:
+ case PROT_BYTE_DATA:
if (read) {
ret = smbus_read_byte(bus, addr, cmd);
goto data8;
@@ -91,22 +107,73 @@ static void smb_transaction(PMSMBus *s)
goto done;
}
break;
- case 0x3:
+ case PROT_WORD_DATA:
if (read) {
ret = smbus_read_word(bus, addr, cmd);
goto data16;
} else {
- ret = smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
+ ret = smbus_write_word(bus, addr, cmd,
+ (s->smb_data1 << 8) | s->smb_data0);
goto done;
}
break;
- case 0x5:
+ case PROT_I2C_BLOCK_READ:
if (read) {
- ret = smbus_read_block(bus, addr, cmd, s->smb_data);
+ int xfersize = s->smb_data0;
+ if (xfersize > sizeof(s->smb_data)) {
+ xfersize = sizeof(s->smb_data);
+ }
+ ret = smbus_read_block(bus, addr, s->smb_data1, s->smb_data,
+ xfersize, false, true);
goto data8;
} else {
- ret = smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
- goto done;
+ /* The manual says the behavior is undefined, just set DEV_ERR. */
+ goto error;
+ }
+ break;
+ case PROT_BLOCK_DATA:
+ if (read) {
+ ret = smbus_read_block(bus, addr, cmd, s->smb_data,
+ sizeof(s->smb_data), !s->i2c_enable,
+ !s->i2c_enable);
+ if (ret < 0) {
+ goto error;
+ }
+ s->smb_index = 0;
+ s->op_done = false;
+ if (s->smb_auxctl & AUX_BLK) {
+ s->smb_stat |= STS_INTR;
+ } else {
+ s->smb_blkdata = s->smb_data[0];
+ s->smb_stat |= STS_HOST_BUSY | STS_BYTE_DONE;
+ }
+ s->smb_data0 = ret;
+ goto out;
+ } else {
+ if (s->smb_auxctl & AUX_BLK) {
+ if (s->smb_index != s->smb_data0) {
+ s->smb_index = 0;
+ goto error;
+ }
+ /* Data is already all written to the queue, just do
+ the operation. */
+ s->smb_index = 0;
+ ret = smbus_write_block(bus, addr, cmd, s->smb_data,
+ s->smb_data0, !s->i2c_enable);
+ if (ret < 0) {
+ goto error;
+ }
+ s->op_done = true;
+ s->smb_stat |= STS_INTR;
+ s->smb_stat &= ~STS_HOST_BUSY;
+ } else {
+ s->op_done = false;
+ s->smb_stat |= STS_HOST_BUSY | STS_BYTE_DONE;
+ s->smb_data[0] = s->smb_blkdata;
+ s->smb_index = 0;
+ ret = 0;
+ }
+ goto out;
}
break;
default:
@@ -128,20 +195,35 @@ done:
if (ret < 0) {
goto error;
}
- s->smb_stat |= STS_BYTE_DONE | STS_INTR;
+ s->smb_stat |= STS_INTR;
+out:
return;
error:
s->smb_stat |= STS_DEV_ERR;
return;
-
}
static void smb_transaction_start(PMSMBus *s)
{
- /* Do not execute immediately the command ; it will be
- * executed when guest will read SMB_STAT register */
- s->smb_stat |= STS_HOST_BUSY;
+ if (s->smb_ctl & CTL_INTREN) {
+ smb_transaction(s);
+ } else {
+ /* Do not execute immediately the command; it will be
+ * executed when guest will read SMB_STAT register. This
+ * is to work around a bug in AMIBIOS (that is working
+ * around another bug in some specific hardware) where
+ * it waits for STS_HOST_BUSY to be set before waiting
+ * checking for status. If STS_HOST_BUSY doesn't get
+ * set, it gets stuck. */
+ s->smb_stat |= STS_HOST_BUSY;
+ }
+}
+
+static bool
+smb_irq_value(PMSMBus *s)
+{
+ return ((s->smb_stat & ~STS_HOST_BUSY) != 0) && (s->smb_ctl & CTL_INTREN);
}
static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
@@ -153,13 +235,61 @@ static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
" val=0x%02" PRIx64 "\n", addr, val);
switch(addr) {
case SMBHSTSTS:
- s->smb_stat = (~(val & 0xff)) & s->smb_stat;
- s->smb_index = 0;
+ s->smb_stat &= ~(val & ~STS_HOST_BUSY);
+ if (!s->op_done && !(s->smb_auxctl & AUX_BLK)) {
+ uint8_t read = s->smb_addr & 0x01;
+
+ s->smb_index++;
+ if (!read && s->smb_index == s->smb_data0) {
+ uint8_t prot = (s->smb_ctl >> 2) & 0x07;
+ uint8_t cmd = s->smb_cmd;
+ uint8_t addr = s->smb_addr >> 1;
+ int ret;
+
+ if (prot == PROT_I2C_BLOCK_READ) {
+ s->smb_stat |= STS_DEV_ERR;
+ goto out;
+ }
+
+ ret = smbus_write_block(s->smbus, addr, cmd, s->smb_data,
+ s->smb_data0, !s->i2c_enable);
+ if (ret < 0) {
+ s->smb_stat |= STS_DEV_ERR;
+ goto out;
+ }
+ s->op_done = true;
+ s->smb_stat |= STS_INTR;
+ s->smb_stat &= ~STS_HOST_BUSY;
+ } else if (!read) {
+ s->smb_data[s->smb_index] = s->smb_blkdata;
+ s->smb_stat |= STS_BYTE_DONE;
+ } else if (s->smb_ctl & CTL_LAST_BYTE) {
+ s->op_done = true;
+ s->smb_blkdata = s->smb_data[s->smb_index];
+ s->smb_index = 0;
+ s->smb_stat |= STS_INTR;
+ s->smb_stat &= ~STS_HOST_BUSY;
+ } else {
+ s->smb_blkdata = s->smb_data[s->smb_index];
+ s->smb_stat |= STS_BYTE_DONE;
+ }
+ }
break;
case SMBHSTCNT:
- s->smb_ctl = val;
- if (val & 0x40)
+ s->smb_ctl = val & ~CTL_START; /* CTL_START always reads 0 */
+ if (val & CTL_START) {
+ if (!s->op_done) {
+ s->smb_index = 0;
+ s->op_done = true;
+ }
smb_transaction_start(s);
+ }
+ if (s->smb_ctl & CTL_KILL) {
+ s->op_done = true;
+ s->smb_index = 0;
+ s->smb_stat |= STS_FAILED;
+ s->smb_stat &= ~STS_HOST_BUSY;
+ }
break;
case SMBHSTCMD:
s->smb_cmd = val;
@@ -174,13 +304,26 @@ static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
s->smb_data1 = val;
break;
case SMBBLKDAT:
- s->smb_data[s->smb_index++] = val;
- if (s->smb_index > 31)
+ if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) {
s->smb_index = 0;
+ }
+ if (s->smb_auxctl & AUX_BLK) {
+ s->smb_data[s->smb_index++] = val;
+ } else {
+ s->smb_blkdata = val;
+ }
+ break;
+ case SMBAUXCTL:
+ s->smb_auxctl = val & AUX_MASK;
break;
default:
break;
}
+
+ out:
+ if (s->set_irq) {
+ s->set_irq(s, smb_irq_value(s));
+ }
}
static uint64_t smb_ioport_readb(void *opaque, hwaddr addr, unsigned width)
@@ -193,12 +336,12 @@ static uint64_t smb_ioport_readb(void *opaque, hwaddr addr, unsigned width)
val = s->smb_stat;
if (s->smb_stat & STS_HOST_BUSY) {
/* execute command now */
+ s->smb_stat &= ~STS_HOST_BUSY;
smb_transaction(s);
}
break;
case SMBHSTCNT:
- s->smb_index = 0;
- val = s->smb_ctl & 0x1f;
+ val = s->smb_ctl & CTL_RETURN_MASK;
break;
case SMBHSTCMD:
val = s->smb_cmd;
@@ -213,18 +356,44 @@ static uint64_t smb_ioport_readb(void *opaque, hwaddr addr, unsigned width)
val = s->smb_data1;
break;
case SMBBLKDAT:
- val = s->smb_data[s->smb_index++];
- if (s->smb_index > 31)
+ if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) {
s->smb_index = 0;
+ }
+ if (s->smb_auxctl & AUX_BLK) {
+ val = s->smb_data[s->smb_index++];
+ if (!s->op_done && s->smb_index == s->smb_data0) {
+ s->op_done = true;
+ s->smb_index = 0;
+ s->smb_stat &= ~STS_HOST_BUSY;
+ }
+ } else {
+ val = s->smb_blkdata;
+ }
+ break;
+ case SMBAUXCTL:
+ val = s->smb_auxctl;
break;
default:
val = 0;
break;
}
- SMBUS_DPRINTF("SMB readb port=0x%04" HWADDR_PRIx " val=0x%02x\n", addr, val);
+ SMBUS_DPRINTF("SMB readb port=0x%04" HWADDR_PRIx " val=0x%02x\n",
+ addr, val);
+
+ if (s->set_irq) {
+ s->set_irq(s, smb_irq_value(s));
+ }
+
return val;
}
+static void pm_smbus_reset(PMSMBus *s)
+{
+ s->op_done = true;
+ s->smb_index = 0;
+ s->smb_stat = 0;
+}
+
static const MemoryRegionOps pm_smbus_ops = {
.read = smb_ioport_readb,
.write = smb_ioport_writeb,
@@ -233,9 +402,14 @@ static const MemoryRegionOps pm_smbus_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-void pm_smbus_init(DeviceState *parent, PMSMBus *smb)
+void pm_smbus_init(DeviceState *parent, PMSMBus *smb, bool force_aux_blk)
{
+ smb->op_done = true;
+ smb->reset = pm_smbus_reset;
smb->smbus = i2c_init_bus(parent, "i2c");
+ if (force_aux_blk) {
+ smb->smb_auxctl |= AUX_BLK;
+ }
memory_region_init_io(&smb->io, OBJECT(parent), &pm_smbus_ops, smb,
"pm-smbus", 64);
}
diff --git a/hw/i2c/smbus.c b/hw/i2c/smbus.c
index 587ce1ab7f..6ff77c582f 100644
--- a/hw/i2c/smbus.c
+++ b/hw/i2c/smbus.c
@@ -293,33 +293,42 @@ int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data)
return 0;
}
-int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data)
+int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
+ int len, bool recv_len, bool send_cmd)
{
- int len;
+ int rlen;
int i;
- if (i2c_start_transfer(bus, addr, 0)) {
- return -1;
+ if (send_cmd) {
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
+ i2c_send(bus, command);
}
- i2c_send(bus, command);
if (i2c_start_transfer(bus, addr, 1)) {
- i2c_end_transfer(bus);
+ if (send_cmd) {
+ i2c_end_transfer(bus);
+ }
return -1;
}
- len = i2c_recv(bus);
- if (len > 32) {
- len = 0;
+ if (recv_len) {
+ rlen = i2c_recv(bus);
+ } else {
+ rlen = len;
}
- for (i = 0; i < len; i++) {
+ if (rlen > len) {
+ rlen = 0;
+ }
+ for (i = 0; i < rlen; i++) {
data[i] = i2c_recv(bus);
}
i2c_nack(bus);
i2c_end_transfer(bus);
- return len;
+ return rlen;
}
int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
- int len)
+ int len, bool send_len)
{
int i;
@@ -330,7 +339,9 @@ int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
return -1;
}
i2c_send(bus, command);
- i2c_send(bus, len);
+ if (send_len) {
+ i2c_send(bus, len);
+ }
for (i = 0; i < len; i++) {
i2c_send(bus, data[i]);
}
diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c
index 007cb6701d..2a8b49e02f 100644
--- a/hw/i2c/smbus_ich9.c
+++ b/hw/i2c/smbus_ich9.c
@@ -40,6 +40,8 @@
typedef struct ICH9SMBState {
PCIDevice dev;
+ bool irq_enabled;
+
PMSMBus smb;
} ICH9SMBState;
@@ -61,12 +63,16 @@ static void ich9_smbus_write_config(PCIDevice *d, uint32_t address,
pci_default_write_config(d, address, val, len);
if (range_covers_byte(address, len, ICH9_SMB_HOSTC)) {
uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
- if ((hostc & ICH9_SMB_HOSTC_HST_EN) &&
- !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
+ if (hostc & ICH9_SMB_HOSTC_HST_EN) {
memory_region_set_enabled(&s->smb.io, true);
} else {
memory_region_set_enabled(&s->smb.io, false);
}
+ s->smb.i2c_enable = (hostc & ICH9_SMB_HOSTC_I2C_EN) != 0;
+ if (hostc & ICH9_SMB_HOSTC_SSRESET) {
+ s->smb.reset(&s->smb);
+ s->dev.config[ICH9_SMB_HOSTC] &= ~ICH9_SMB_HOSTC_SSRESET;
+ }
}
}
@@ -80,7 +86,7 @@ static void ich9_smbus_realize(PCIDevice *d, Error **errp)
pci_set_byte(d->config + ICH9_SMB_HOSTC, 0);
/* TODO bar0, bar1: 64bit BAR support*/
- pm_smbus_init(&d->qdev, &s->smb);
+ pm_smbus_init(&d->qdev, &s->smb, false);
pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO,
&s->smb.io);
}
@@ -105,11 +111,25 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data)
dc->user_creatable = false;
}
+static void ich9_smb_set_irq(PMSMBus *pmsmb, bool enabled)
+{
+ ICH9SMBState *s = pmsmb->opaque;
+
+ if (enabled == s->irq_enabled) {
+ return;
+ }
+
+ s->irq_enabled = enabled;
+ pci_set_irq(&s->dev, enabled);
+}
+
I2CBus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base)
{
PCIDevice *d =
pci_create_simple_multifunction(bus, devfn, true, TYPE_ICH9_SMB_DEVICE);
ICH9SMBState *s = ICH9_SMB_DEVICE(d);
+ s->smb.set_irq = ich9_smb_set_irq;
+ s->smb.opaque = s;
return s->smb.smbus;
}
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 83a444472b..03148450c8 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1679,7 +1679,9 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
const PCMachineState *pcms = PC_MACHINE(hotplug_dev);
+ const PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
+ const uint64_t legacy_align = TARGET_PAGE_SIZE;
/*
* When -no-acpi is used with Q35 machine type, no ACPI is built,
@@ -1696,6 +1698,9 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
error_setg(errp, "nvdimm is not enabled: missing 'nvdimm' in '-M'");
return;
}
+
+ pc_dimm_pre_plug(dev, MACHINE(hotplug_dev),
+ pcmc->enforce_aligned_dimm ? NULL : &legacy_align, errp);
}
static void pc_memory_plug(HotplugHandler *hotplug_dev,
@@ -1704,18 +1709,9 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev,
HotplugHandlerClass *hhc;
Error *local_err = NULL;
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
- PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
- PCDIMMDevice *dimm = PC_DIMM(dev);
- PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
- MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort);
- uint64_t align = TARGET_PAGE_SIZE;
bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
- if (memory_region_get_alignment(mr) && pcmc->enforce_aligned_dimm) {
- align = memory_region_get_alignment(mr);
- }
-
- pc_dimm_plug(dev, MACHINE(pcms), align, &local_err);
+ pc_dimm_plug(dev, MACHINE(pcms), &local_err);
if (local_err) {
goto out;
}
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index 6fda52b86c..97ffdd820f 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -650,31 +650,17 @@ static void apic_timer(void *opaque)
apic_timer_update(s, s->next_time);
}
-static uint32_t apic_mem_readb(void *opaque, hwaddr addr)
-{
- return 0;
-}
-
-static uint32_t apic_mem_readw(void *opaque, hwaddr addr)
-{
- return 0;
-}
-
-static void apic_mem_writeb(void *opaque, hwaddr addr, uint32_t val)
-{
-}
-
-static void apic_mem_writew(void *opaque, hwaddr addr, uint32_t val)
-{
-}
-
-static uint32_t apic_mem_readl(void *opaque, hwaddr addr)
+static uint64_t apic_mem_read(void *opaque, hwaddr addr, unsigned size)
{
DeviceState *dev;
APICCommonState *s;
uint32_t val;
int index;
+ if (size < 4) {
+ return 0;
+ }
+
dev = cpu_get_current_apic();
if (!dev) {
return 0;
@@ -765,11 +751,17 @@ static void apic_send_msi(MSIMessage *msi)
apic_deliver_irq(dest, dest_mode, delivery, vector, trigger_mode);
}
-static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val)
+static void apic_mem_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
{
DeviceState *dev;
APICCommonState *s;
int index = (addr >> 4) & 0xff;
+
+ if (size < 4) {
+ return;
+ }
+
if (addr > 0xfff || !index) {
/* MSI and MMIO APIC are at the same memory location,
* but actually not on the global bus: MSI is on PCI bus
@@ -880,10 +872,12 @@ static void apic_post_load(APICCommonState *s)
}
static const MemoryRegionOps apic_io_ops = {
- .old_mmio = {
- .read = { apic_mem_readb, apic_mem_readw, apic_mem_readl, },
- .write = { apic_mem_writeb, apic_mem_writew, apic_mem_writel, },
- },
+ .read = apic_mem_read,
+ .write = apic_mem_write,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 4,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
.endianness = DEVICE_NATIVE_ENDIAN,
};
diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c
index e946030e84..8bbb1fa785 100644
--- a/hw/ipmi/isa_ipmi_bt.c
+++ b/hw/ipmi/isa_ipmi_bt.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
+#include "qemu/log.h"
#include "qapi/error.h"
#include "hw/hw.h"
#include "hw/ipmi/ipmi.h"
@@ -450,22 +451,63 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp)
isa_register_ioport(isadev, &iib->bt.io, iib->bt.io_base);
}
-static const VMStateDescription vmstate_ISAIPMIBTDevice = {
- .name = TYPE_IPMI_INTERFACE,
+static int ipmi_bt_vmstate_post_load(void *opaque, int version)
+{
+ IPMIBT *ib = opaque;
+
+ /* Make sure all the values are sane. */
+ if (ib->outpos >= MAX_IPMI_MSG_SIZE || ib->outlen >= MAX_IPMI_MSG_SIZE ||
+ ib->outpos >= ib->outlen) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "ipmi:bt: vmstate transfer received bad out values: %d %d\n",
+ ib->outpos, ib->outlen);
+ ib->outpos = 0;
+ ib->outlen = 0;
+ }
+
+ if (ib->inlen >= MAX_IPMI_MSG_SIZE) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "ipmi:bt: vmstate transfer received bad in value: %d\n",
+ ib->inlen);
+ ib->inlen = 0;
+ }
+
+ return 0;
+}
+
+const VMStateDescription vmstate_IPMIBT = {
+ .name = TYPE_IPMI_INTERFACE_PREFIX "bt",
.version_id = 1,
.minimum_version_id = 1,
+ .post_load = ipmi_bt_vmstate_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_BOOL(obf_irq_set, IPMIBT),
+ VMSTATE_BOOL(atn_irq_set, IPMIBT),
+ VMSTATE_BOOL(irqs_enabled, IPMIBT),
+ VMSTATE_UINT32(outpos, IPMIBT),
+ VMSTATE_UINT32(outlen, IPMIBT),
+ VMSTATE_UINT8_ARRAY(outmsg, IPMIBT, MAX_IPMI_MSG_SIZE),
+ VMSTATE_UINT32(inlen, IPMIBT),
+ VMSTATE_UINT8_ARRAY(inmsg, IPMIBT, MAX_IPMI_MSG_SIZE),
+ VMSTATE_UINT8(control_reg, IPMIBT),
+ VMSTATE_UINT8(mask_reg, IPMIBT),
+ VMSTATE_UINT8(waiting_rsp, IPMIBT),
+ VMSTATE_UINT8(waiting_seq, IPMIBT),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_ISAIPMIBTDevice = {
+ .name = TYPE_IPMI_INTERFACE_PREFIX "isa-bt",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ /*
+ * Version 1 had messed up the array transfer, it's not even usable
+ * because it used VMSTATE_VBUFFER_UINT32, but it did not transfer
+ * the buffer length, so random things would happen.
+ */
.fields = (VMStateField[]) {
- VMSTATE_BOOL(bt.obf_irq_set, ISAIPMIBTDevice),
- VMSTATE_BOOL(bt.atn_irq_set, ISAIPMIBTDevice),
- VMSTATE_BOOL(bt.use_irq, ISAIPMIBTDevice),
- VMSTATE_BOOL(bt.irqs_enabled, ISAIPMIBTDevice),
- VMSTATE_UINT32(bt.outpos, ISAIPMIBTDevice),
- VMSTATE_VBUFFER_UINT32(bt.outmsg, ISAIPMIBTDevice, 1, NULL, bt.outlen),
- VMSTATE_VBUFFER_UINT32(bt.inmsg, ISAIPMIBTDevice, 1, NULL, bt.inlen),
- VMSTATE_UINT8(bt.control_reg, ISAIPMIBTDevice),
- VMSTATE_UINT8(bt.mask_reg, ISAIPMIBTDevice),
- VMSTATE_UINT8(bt.waiting_rsp, ISAIPMIBTDevice),
- VMSTATE_UINT8(bt.waiting_seq, ISAIPMIBTDevice),
+ VMSTATE_STRUCT(bt, ISAIPMIBTDevice, 1, vmstate_IPMIBT, IPMIBT),
VMSTATE_END_OF_LIST()
}
};
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index cff1946232..7302f6d74b 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -370,7 +370,7 @@ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp)
pci_conf[0x90] = s->smb_io_base | 1;
pci_conf[0x91] = s->smb_io_base >> 8;
pci_conf[0xd2] = 0x90;
- pm_smbus_init(&s->dev.qdev, &s->smb);
+ pm_smbus_init(&s->dev.qdev, &s->smb, false);
memory_region_add_subregion(get_system_io(), s->smb_io_base, &s->smb.io);
apm_init(dev, &s->apm, NULL, s);
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 65843bc52a..fb6bcaedc4 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -29,57 +29,60 @@
static int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
-void pc_dimm_plug(DeviceState *dev, MachineState *machine, uint64_t align,
- Error **errp)
+void pc_dimm_pre_plug(DeviceState *dev, MachineState *machine,
+ const uint64_t *legacy_align, Error **errp)
{
- int slot;
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
- MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm,
- &error_abort);
- MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort);
Error *local_err = NULL;
- uint64_t addr;
+ MemoryRegion *mr;
+ uint64_t addr, align;
+ int slot;
- addr = object_property_get_uint(OBJECT(dimm),
- PC_DIMM_ADDR_PROP, &local_err);
+ slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
+ &error_abort);
+ slot = pc_dimm_get_free_slot(slot == PC_DIMM_UNASSIGNED_SLOT ? NULL : &slot,
+ machine->ram_slots, &local_err);
if (local_err) {
goto out;
}
+ object_property_set_int(OBJECT(dev), slot, PC_DIMM_SLOT_PROP, &error_abort);
+ trace_mhp_pc_dimm_assigned_slot(slot);
- addr = memory_device_get_free_addr(machine, !addr ? NULL : &addr, align,
- memory_region_size(mr), &local_err);
+ mr = ddc->get_memory_region(dimm, &local_err);
if (local_err) {
goto out;
}
- object_property_set_uint(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err);
+ align = legacy_align ? *legacy_align : memory_region_get_alignment(mr);
+ addr = object_property_get_uint(OBJECT(dev), PC_DIMM_ADDR_PROP,
+ &error_abort);
+ addr = memory_device_get_free_addr(machine, !addr ? NULL : &addr, align,
+ memory_region_size(mr), &local_err);
if (local_err) {
goto out;
}
trace_mhp_pc_dimm_assigned_address(addr);
+ object_property_set_uint(OBJECT(dev), addr, PC_DIMM_ADDR_PROP,
+ &error_abort);
+out:
+ error_propagate(errp, local_err);
+}
- slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, &local_err);
- if (local_err) {
- goto out;
- }
+void pc_dimm_plug(DeviceState *dev, MachineState *machine, Error **errp)
+{
+ PCDIMMDevice *dimm = PC_DIMM(dev);
+ PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
+ MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm,
+ &error_abort);
+ MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort);
+ uint64_t addr;
- slot = pc_dimm_get_free_slot(slot == PC_DIMM_UNASSIGNED_SLOT ? NULL : &slot,
- machine->ram_slots, &local_err);
- if (local_err) {
- goto out;
- }
- object_property_set_int(OBJECT(dev), slot, PC_DIMM_SLOT_PROP, &local_err);
- if (local_err) {
- goto out;
- }
- trace_mhp_pc_dimm_assigned_slot(slot);
+ addr = object_property_get_uint(OBJECT(dev), PC_DIMM_ADDR_PROP,
+ &error_abort);
memory_device_plug_region(machine, mr, addr);
vmstate_register_ram(vmstate_mr, dev);
-
-out:
- error_propagate(errp, local_err);
}
void pc_dimm_unplug(DeviceState *dev, MachineState *machine)
diff --git a/hw/misc/vmcoreinfo.c b/hw/misc/vmcoreinfo.c
index a2805527cb..304c6287c7 100644
--- a/hw/misc/vmcoreinfo.c
+++ b/hw/misc/vmcoreinfo.c
@@ -19,7 +19,7 @@ static void fw_cfg_vmci_write(void *dev, off_t offset, size_t len)
VMCoreInfoState *s = VMCOREINFO(dev);
s->has_vmcoreinfo = offset == 0 && len == sizeof(s->vmcoreinfo)
- && s->vmcoreinfo.guest_format != VMCOREINFO_FORMAT_NONE;
+ && s->vmcoreinfo.guest_format != FW_CFG_VMCOREINFO_FORMAT_NONE;
}
static void vmcoreinfo_reset(void *dev)
@@ -28,7 +28,7 @@ static void vmcoreinfo_reset(void *dev)
s->has_vmcoreinfo = false;
memset(&s->vmcoreinfo, 0, sizeof(s->vmcoreinfo));
- s->vmcoreinfo.host_format = cpu_to_le16(VMCOREINFO_FORMAT_ELF);
+ s->vmcoreinfo.host_format = cpu_to_le16(FW_CFG_VMCOREINFO_FORMAT_ELF);
}
static void vmcoreinfo_realize(DeviceState *dev, Error **errp)
@@ -53,7 +53,7 @@ static void vmcoreinfo_realize(DeviceState *dev, Error **errp)
return;
}
- fw_cfg_add_file_callback(fw_cfg, "etc/vmcoreinfo",
+ fw_cfg_add_file_callback(fw_cfg, FW_CFG_VMCOREINFO_FILENAME,
NULL, fw_cfg_vmci_write, s,
&s->vmcoreinfo, sizeof(s->vmcoreinfo), false);
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 47146ba12a..162b27a3b8 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -608,6 +608,9 @@ static int prep_set_cmos_checksum(DeviceState *dev, void *opaque)
rtc_set_memory(rtc, 0x3e, checksum & 0xff);
rtc_set_memory(rtc, 0x2f, checksum >> 8);
rtc_set_memory(rtc, 0x3f, checksum >> 8);
+
+ object_property_add_alias(qdev_get_machine(), "rtc-time", OBJECT(rtc),
+ "date", NULL);
}
return 0;
}
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index ddd4478a34..4edb6c7d16 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -562,9 +562,12 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr)
{
+ CPUState **rev;
CPUState *cs;
+ int n_cpus;
int cpus_offset;
char *nodename;
+ int i;
cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
_FDT(cpus_offset);
@@ -575,8 +578,19 @@ static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr)
* We walk the CPUs in reverse order to ensure that CPU DT nodes
* created by fdt_add_subnode() end up in the right order in FDT
* for the guest kernel the enumerate the CPUs correctly.
+ *
+ * The CPU list cannot be traversed in reverse order, so we need
+ * to do extra work.
*/
- CPU_FOREACH_REVERSE(cs) {
+ n_cpus = 0;
+ rev = NULL;
+ CPU_FOREACH(cs) {
+ rev = g_renew(CPUState *, rev, n_cpus + 1);
+ rev[n_cpus++] = cs;
+ }
+
+ for (i = n_cpus - 1; i >= 0; i--) {
+ CPUState *cs = rev[i];
PowerPCCPU *cpu = POWERPC_CPU(cs);
int index = spapr_get_vcpu_id(cpu);
DeviceClass *dc = DEVICE_GET_CLASS(cs);
@@ -3113,13 +3127,12 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort);
- uint64_t align, size, addr;
+ uint64_t size, addr;
uint32_t node;
- align = memory_region_get_alignment(mr);
size = memory_region_size(mr);
- pc_dimm_plug(dev, MACHINE(ms), align, &local_err);
+ pc_dimm_plug(dev, MACHINE(ms), &local_err);
if (local_err) {
goto out;
}
@@ -3154,6 +3167,7 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
+ Error *local_err = NULL;
MemoryRegion *mr;
uint64_t size;
Object *memdev;
@@ -3179,7 +3193,13 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP,
&error_abort);
pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev));
- spapr_check_pagesize(spapr, pagesize, errp);
+ spapr_check_pagesize(spapr, pagesize, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ pc_dimm_pre_plug(dev, MACHINE(hotplug_dev), NULL, errp);
}
struct sPAPRDIMMState {
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index 160657f4b9..955ba94800 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -959,6 +959,10 @@ static void lsi_do_msgout(LSIState *s)
DPRINTF("WDTR (ignored)\n");
lsi_skip_msgbytes(s, 1);
break;
+ case 4:
+ DPRINTF("PPR (ignored)\n");
+ lsi_skip_msgbytes(s, 5);
+ break;
default:
goto bad;
}
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index ba1afa3c1e..a56317e026 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -464,6 +464,7 @@ static void megasas_unmap_frame(MegasasState *s, MegasasCmd *cmd)
cmd->frame = NULL;
cmd->pa = 0;
cmd->pa_size = 0;
+ qemu_sglist_destroy(&cmd->qsg);
clear_bit(cmd->index, s->frame_map);
}
@@ -580,7 +581,6 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context)
static void megasas_complete_command(MegasasCmd *cmd)
{
- qemu_sglist_destroy(&cmd->qsg);
cmd->iov_size = 0;
cmd->iov_offset = 0;
diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
index 4176e871e1..929404fb48 100644
--- a/hw/scsi/mptsas.c
+++ b/hw/scsi/mptsas.c
@@ -1431,6 +1431,7 @@ static void mptsas1068_class_init(ObjectClass *oc, void *data)
dc->reset = mptsas_reset;
dc->vmsd = &vmstate_mptsas;
dc->desc = "LSI SAS 1068";
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo mptsas_info = {
diff --git a/hw/scsi/vhost-scsi-common.c b/hw/scsi/vhost-scsi-common.c
index e2a5828af1..b7fbab65dd 100644
--- a/hw/scsi/vhost-scsi-common.c
+++ b/hw/scsi/vhost-scsi-common.c
@@ -96,6 +96,9 @@ uint64_t vhost_scsi_common_get_features(VirtIODevice *vdev, uint64_t features,
{
VHostSCSICommon *vsc = VHOST_SCSI_COMMON(vdev);
+ /* Turn on predefined features supported by this device */
+ features |= vsc->host_features;
+
return vhost_get_features(&vsc->dev, vsc->feature_bits, features);
}
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 9c1bea8ff3..becf550085 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -238,6 +238,9 @@ static Property vhost_scsi_properties[] = {
DEFINE_PROP_UINT32("max_sectors", VirtIOSCSICommon, conf.max_sectors,
0xFFFF),
DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSICommon, conf.cmd_per_lun, 128),
+ DEFINE_PROP_BIT64("t10_pi", VHostSCSICommon, host_features,
+ VIRTIO_SCSI_F_T10_PI,
+ false),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c
index 9355cfdf07..2e1ba4a87b 100644
--- a/hw/scsi/vhost-user-scsi.c
+++ b/hw/scsi/vhost-user-scsi.c
@@ -137,17 +137,6 @@ static void vhost_user_scsi_unrealize(DeviceState *dev, Error **errp)
}
}
-static uint64_t vhost_user_scsi_get_features(VirtIODevice *vdev,
- uint64_t features, Error **errp)
-{
- VHostUserSCSI *s = VHOST_USER_SCSI(vdev);
-
- /* Turn on predefined features supported by this device */
- features |= s->host_features;
-
- return vhost_scsi_common_get_features(vdev, features, errp);
-}
-
static Property vhost_user_scsi_properties[] = {
DEFINE_PROP_CHR("chardev", VirtIOSCSICommon, conf.chardev),
DEFINE_PROP_UINT32("boot_tpgt", VirtIOSCSICommon, conf.boot_tpgt, 0),
@@ -157,12 +146,15 @@ static Property vhost_user_scsi_properties[] = {
DEFINE_PROP_UINT32("max_sectors", VirtIOSCSICommon, conf.max_sectors,
0xFFFF),
DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSICommon, conf.cmd_per_lun, 128),
- DEFINE_PROP_BIT64("hotplug", VHostUserSCSI, host_features,
- VIRTIO_SCSI_F_HOTPLUG,
- true),
- DEFINE_PROP_BIT64("param_change", VHostUserSCSI, host_features,
- VIRTIO_SCSI_F_CHANGE,
- true),
+ DEFINE_PROP_BIT64("hotplug", VHostSCSICommon, host_features,
+ VIRTIO_SCSI_F_HOTPLUG,
+ true),
+ DEFINE_PROP_BIT64("param_change", VHostSCSICommon, host_features,
+ VIRTIO_SCSI_F_CHANGE,
+ true),
+ DEFINE_PROP_BIT64("t10_pi", VHostSCSICommon, host_features,
+ VIRTIO_SCSI_F_T10_PI,
+ false),
DEFINE_PROP_END_OF_LIST(),
};
@@ -187,7 +179,7 @@ static void vhost_user_scsi_class_init(ObjectClass *klass, void *data)
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->realize = vhost_user_scsi_realize;
vdc->unrealize = vhost_user_scsi_unrealize;
- vdc->get_features = vhost_user_scsi_get_features;
+ vdc->get_features = vhost_scsi_common_get_features;
vdc->set_config = vhost_scsi_common_set_config;
vdc->set_status = vhost_user_scsi_set_status;
fwc->get_dev_path = vhost_scsi_common_get_fw_dev_path;
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 6f1f723b1f..a504f0308d 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -120,7 +120,7 @@ static void rtc_coalesced_timer_update(RTCState *s)
timer_del(s->coalesced_timer);
} else {
/* divide each RTC interval to 2 - 8 smaller intervals */
- int c = MIN(s->irq_coalesced, 7) + 1;
+ int c = MIN(s->irq_coalesced, 7) + 1;
int64_t next_clock = qemu_clock_get_ns(rtc_clock) +
periodic_clock_to_ns(s->period / c);
timer_mod(s->coalesced_timer, next_clock);
@@ -485,7 +485,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
s->cmos_data[s->cmos_index] = data;
check_update_timer(s);
break;
- case RTC_IBM_PS2_CENTURY_BYTE:
+ case RTC_IBM_PS2_CENTURY_BYTE:
s->cmos_index = RTC_CENTURY;
/* fall through */
case RTC_CENTURY:
@@ -713,7 +713,7 @@ static uint64_t cmos_ioport_read(void *opaque, hwaddr addr,
return 0xff;
} else {
switch(s->cmos_index) {
- case RTC_IBM_PS2_CENTURY_BYTE:
+ case RTC_IBM_PS2_CENTURY_BYTE:
s->cmos_index = RTC_CENTURY;
/* fall through */
case RTC_CENTURY:
@@ -915,7 +915,7 @@ static void rtc_reset(void *opaque)
if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
s->irq_coalesced = 0;
- s->irq_reinject_on_ack_count = 0;
+ s->irq_reinject_on_ack_count = 0;
}
}
@@ -995,9 +995,6 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
object_property_add_tm(OBJECT(s), "date", rtc_get_date, NULL);
- object_property_add_alias(qdev_get_machine(), "rtc-time",
- OBJECT(s), "date", NULL);
-
qdev_init_gpio_out(dev, &s->irq, 1);
}
@@ -1019,6 +1016,9 @@ ISADevice *mc146818_rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
}
QLIST_INSERT_HEAD(&rtc_devices, s, link);
+ object_property_add_alias(qdev_get_machine(), "rtc-time", OBJECT(s),
+ "date", NULL);
+
return isadev;
}
@@ -1052,17 +1052,11 @@ static void rtc_class_initfn(ObjectClass *klass, void *data)
dc->user_creatable = false;
}
-static void rtc_finalize(Object *obj)
-{
- object_property_del(qdev_get_machine(), "rtc", NULL);
-}
-
static const TypeInfo mc146818rtc_info = {
.name = TYPE_MC146818_RTC,
.parent = TYPE_ISA_DEVICE,
.instance_size = sizeof(RTCState),
.class_init = rtc_class_initfn,
- .instance_finalize = rtc_finalize,
};
static void mc146818rtc_register_types(void)
diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c
index 5f8736cf10..91b18ba312 100644
--- a/hw/timer/sh_timer.c
+++ b/hw/timer/sh_timer.c
@@ -74,6 +74,7 @@ static uint32_t sh_timer_read(void *opaque, hwaddr offset)
case OFFSET_TCPR:
if (s->feat & TIMER_FEAT_CAPT)
return s->tcpr;
+ /* fall through */
default:
hw_error("sh_timer_read: Bad offset %x\n", (int)offset);
return 0;