Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging

* more WHPX fixes and documentation
* hpet: fix bounds check for s->timer[]
* hpet: lower HPET_MAX_TIMERS to 24
* lsi53c895a: keep SCSIRequest alive during DMA
* lsi53c895a: keep device alive during SCRIPTS execution
* hw/acpi: fix save/restore for MIPS Malta machine

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCgAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmnKTQ0UHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroNDAQgAry87O2EtgZBK8084Rn41+8w7Hx4K
# HmKGGLRHunZgOPPbFtLFj8sjmZGqV6MuELf8zBIwheJiaWyp9SqPN2FtwldEwLsG
# C37MsUS02SbfPrJPuAMaDsfeFknHaV/pUWiZIYr5S5+dKckz8P9RUZghCVKBmwyL
# mapNE7/++A2HCX2FnABmAsMMo+kt425kCmkDFryJQ9R7j8vjYo2sHn+WpDRjOLYS
# 0K7a5HBCwE+TrdZC1Q3J17VMhX/sFL/Ms8ByIhwJa+WimZoF/roaDBiK/0iUfVlg
# 196U0rvejdymAMWqIU462fyHvVkeW50FCHjTccmqnrIbFEdL4CFZlnrNxQ==
# =JIqb
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon Mar 30 11:14:37 2026 BST
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# 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

* tag 'for-upstream' of https://gitlab.com/bonzini/qemu:
  hw/acpi: Do not save/load cpuhp state unconditionally
  lsi53c895a: keep SCSIRequest alive during DMA
  lsi53c895a: keep lsi_request alive as long as the SCSIRequest
  lsi53c895a: keep lsi_request and SCSIRequest in local variables
  lsi53c895a: do not do anything else if a reset is requested by writing ISTAT0
  lsi53c895a: keep a reference to the device while SCRIPTS execute
  hpet: lower HPET_MAX_TIMERS to 24
  hpet: fix bounds check for s->timer[]
  target/i386: emulate: remove redundant logging for unmapped MMIO access
  whpx: i386: trace unsupported MSR accesses
  docs: add WHPX section with initial info
  meson.build: remove i386-softmmu WHPX support

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2026-03-30 13:54:56 +01:00
14 changed files with 224 additions and 38 deletions

View File

@@ -184,10 +184,18 @@ static const VMStateDescription vmstate_tco_io_state = {
}
};
static bool cpuhp_needed(void *opaque)
{
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
return mc->has_hotpluggable_cpus;
}
static const VMStateDescription vmstate_cpuhp_state = {
.name = "ich9_pm/cpuhp",
.version_id = 1,
.minimum_version_id = 1,
.needed = cpuhp_needed,
.fields = (const VMStateField[]) {
VMSTATE_CPU_HOTPLUG(cpuhp_state, ICH9LPCPMRegs),
VMSTATE_END_OF_LIST()

View File

@@ -195,10 +195,18 @@ static const VMStateDescription vmstate_memhp_state = {
}
};
static bool cpuhp_needed(void *opaque)
{
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
return mc->has_hotpluggable_cpus;
}
static const VMStateDescription vmstate_cpuhp_state = {
.name = "piix4_pm/cpuhp",
.version_id = 1,
.minimum_version_id = 1,
.needed = cpuhp_needed,
.fields = (const VMStateField[]) {
VMSTATE_CPU_HOTPLUG(cpuhp_state, PIIX4PMState),
VMSTATE_END_OF_LIST()

View File

@@ -197,6 +197,7 @@ typedef struct lsi_request {
uint8_t *dma_buf;
uint32_t pending;
int out;
bool orphan;
QTAILQ_ENTRY(lsi_request) next;
} lsi_request;
@@ -626,6 +627,8 @@ static void lsi_do_dma(LSIState *s, int out)
uint32_t count;
dma_addr_t addr;
SCSIDevice *dev;
SCSIRequest *req;
lsi_request *p;
if (!s->current || !s->current->dma_len) {
/* Wait until data is available. */
@@ -633,12 +636,14 @@ static void lsi_do_dma(LSIState *s, int out)
return;
}
dev = s->current->req->dev;
p = s->current;
req = scsi_req_ref(s->current->req);
dev = req->dev;
assert(dev);
count = s->dbc;
if (count > s->current->dma_len)
count = s->current->dma_len;
if (count > p->dma_len)
count = p->dma_len;
addr = s->dnad;
/* both 40 and Table Indirect 64-bit DMAs store upper bits in dnad64 */
@@ -653,21 +658,27 @@ static void lsi_do_dma(LSIState *s, int out)
s->csbc += count;
s->dnad += count;
s->dbc -= count;
if (s->current->dma_buf == NULL) {
s->current->dma_buf = scsi_req_get_buf(s->current->req);
if (p->dma_buf == NULL) {
p->dma_buf = scsi_req_get_buf(req);
}
/* ??? Set SFBR to first data byte. */
if (out) {
lsi_mem_read(s, addr, s->current->dma_buf, count);
lsi_mem_read(s, addr, p->dma_buf, count);
} else {
lsi_mem_write(s, addr, s->current->dma_buf, count);
lsi_mem_write(s, addr, p->dma_buf, count);
}
s->current->dma_len -= count;
if (s->current->dma_len == 0) {
s->current->dma_buf = NULL;
scsi_req_continue(s->current->req);
if (p->orphan) {
scsi_req_unref(req);
return;
}
scsi_req_unref(req);
p->dma_len -= count;
if (p->dma_len == 0) {
p->dma_buf = NULL;
scsi_req_continue(req);
} else {
s->current->dma_buf += count;
p->dma_buf += count;
lsi_resume_script(s);
}
}
@@ -743,14 +754,20 @@ static lsi_request *lsi_find_by_tag(LSIState *s, uint32_t tag)
return NULL;
}
static void lsi_request_free(LSIState *s, lsi_request *p)
static void lsi_request_orphan(LSIState *s, lsi_request *p)
{
p->orphan = true;
if (p == s->current) {
s->current = NULL;
} else {
QTAILQ_REMOVE(&s->queue, p, next);
}
g_free(p);
scsi_req_unref(p->req);
}
static void lsi_free_request(SCSIBus *bus, void *priv)
{
g_free(priv);
}
static void lsi_request_cancelled(SCSIRequest *req)
@@ -758,9 +775,7 @@ static void lsi_request_cancelled(SCSIRequest *req)
LSIState *s = LSI53C895A(req->bus->qbus.parent);
lsi_request *p = req->hba_private;
req->hba_private = NULL;
lsi_request_free(s, p);
scsi_req_unref(req);
lsi_request_orphan(s, p);
}
/* Record that data is available for a queued command. Returns zero if
@@ -812,9 +827,7 @@ static void lsi_command_complete(SCSIRequest *req, size_t resid)
}
if (req->hba_private == s->current) {
req->hba_private = NULL;
lsi_request_free(s, s->current);
scsi_req_unref(req);
lsi_request_orphan(s, s->current);
}
if (!stop) {
lsi_resume_script(s);
@@ -825,10 +838,11 @@ static void lsi_command_complete(SCSIRequest *req, size_t resid)
static void lsi_transfer_data(SCSIRequest *req, uint32_t len)
{
LSIState *s = LSI53C895A(req->bus->qbus.parent);
lsi_request *p = req->hba_private;
int out;
assert(req->hba_private);
if (s->waiting == LSI_WAIT_RESELECT || req->hba_private != s->current ||
assert(!p->orphan);
if (s->waiting == LSI_WAIT_RESELECT || p != s->current ||
(lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON))) {
if (lsi_queue_req(s, req, len)) {
return;
@@ -1163,6 +1177,7 @@ static void lsi_execute_script(LSIState *s)
s->waiting = LSI_NOWAIT;
}
object_ref(s);
reentrancy_level++;
s->istat1 |= LSI_ISTAT1_SRUN;
@@ -1182,6 +1197,7 @@ again:
s->waiting = LSI_WAIT_SCRIPTS;
lsi_scripts_timer_start(s);
reentrancy_level--;
object_unref(s);
return;
}
insn = read_dword(s, s->dsp);
@@ -1630,6 +1646,7 @@ again:
trace_lsi_execute_script_stop();
reentrancy_level--;
object_unref(s);
}
static uint8_t lsi_reg_readb(LSIState *s, int offset)
@@ -1946,6 +1963,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
CASE_SET_REG32(dsa, 0x10)
case 0x14: /* ISTAT0 */
s->istat0 = (s->istat0 & 0x0f) | (val & 0xf0);
if (val & LSI_ISTAT0_SRST) {
device_cold_reset(DEVICE(s));
return;
}
if (val & LSI_ISTAT0_ABRT) {
lsi_script_dma_interrupt(s, LSI_DSTAT_ABRT);
}
@@ -1959,9 +1980,6 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
s->dsp = s->dnad;
lsi_execute_script(s);
}
if (val & LSI_ISTAT0_SRST) {
device_cold_reset(DEVICE(s));
}
break;
case 0x16: /* MBOX0 */
s->mbox0 = val;
@@ -2316,7 +2334,8 @@ static const struct SCSIBusInfo lsi_scsi_info = {
.transfer_data = lsi_transfer_data,
.complete = lsi_command_complete,
.cancel = lsi_request_cancelled
.cancel = lsi_request_cancelled,
.free_request = lsi_free_request,
};
static void scripts_timer_cb(void *opaque)

View File

@@ -464,13 +464,14 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
}
} else {
uint8_t timer_id = (addr - 0x100) / 0x20;
HPETTimer *timer = &s->timer[timer_id];
HPETTimer *timer;
if (timer_id > s->num_timers) {
if (timer_id >= s->num_timers) {
trace_hpet_timer_id_out_of_range(timer_id);
return 0;
}
timer = &s->timer[timer_id];
switch (addr & 0x1f) {
case HPET_TN_CFG: // including interrupt capabilities
return timer->config >> shift;
@@ -564,13 +565,15 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
}
} else {
uint8_t timer_id = (addr - 0x100) / 0x20;
HPETTimer *timer = &s->timer[timer_id];
HPETTimer *timer;
trace_hpet_ram_write_timer_id(timer_id);
if (timer_id > s->num_timers) {
if (timer_id >= s->num_timers) {
trace_hpet_timer_id_out_of_range(timer_id);
return;
}
timer = &s->timer[timer_id];
switch (addr & 0x18) {
case HPET_TN_CFG:
trace_hpet_ram_write_tn_cfg(addr & 4);