diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-08-23 19:03:53 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-08-23 19:03:54 +0100 |
commit | 3c825bb7c1b4289ef05f51b5b77ac0967b6a27fa (patch) | |
tree | 44c5189aacbe795b125bfb4b5144a37fe122d2e4 /hw | |
parent | 5ccac548faf041ff5229a8e8342e3be14a34c8af (diff) | |
parent | b2e78fac6f27c36938353e477354778896adc08f (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.c | 2 | ||||
-rw-r--r-- | hw/arm/pxa2xx.c | 2 | ||||
-rw-r--r-- | hw/audio/cs4231a.c | 1 | ||||
-rw-r--r-- | hw/audio/es1370.c | 235 | ||||
-rw-r--r-- | hw/audio/gusemu_hal.c | 1 | ||||
-rw-r--r-- | hw/audio/sb16.c | 11 | ||||
-rw-r--r-- | hw/display/cg3.c | 1 | ||||
-rw-r--r-- | hw/display/cirrus_vga.c | 3 | ||||
-rw-r--r-- | hw/i2c/pm_smbus.c | 254 | ||||
-rw-r--r-- | hw/i2c/smbus.c | 37 | ||||
-rw-r--r-- | hw/i2c/smbus_ich9.c | 26 | ||||
-rw-r--r-- | hw/i386/pc.c | 16 | ||||
-rw-r--r-- | hw/intc/apic.c | 42 | ||||
-rw-r--r-- | hw/ipmi/isa_ipmi_bt.c | 68 | ||||
-rw-r--r-- | hw/isa/vt82c686.c | 2 | ||||
-rw-r--r-- | hw/mem/pc-dimm.c | 61 | ||||
-rw-r--r-- | hw/misc/vmcoreinfo.c | 6 | ||||
-rw-r--r-- | hw/ppc/prep.c | 3 | ||||
-rw-r--r-- | hw/ppc/spapr.c | 30 | ||||
-rw-r--r-- | hw/scsi/lsi53c895a.c | 4 | ||||
-rw-r--r-- | hw/scsi/megasas.c | 2 | ||||
-rw-r--r-- | hw/scsi/mptsas.c | 1 | ||||
-rw-r--r-- | hw/scsi/vhost-scsi-common.c | 3 | ||||
-rw-r--r-- | hw/scsi/vhost-scsi.c | 3 | ||||
-rw-r--r-- | hw/scsi/vhost-user-scsi.c | 28 | ||||
-rw-r--r-- | hw/timer/mc146818rtc.c | 20 | ||||
-rw-r--r-- | hw/timer/sh_timer.c | 1 |
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; |