[PATCH] smm: ignore bits 16,18-31 of SMM revision ID
by Paolo Bonzini
Bits 16-31 of the SMM revision ID are feature bits. We only need to
check that SMBASE relocation is supported, but do not care about other
features. In particular, this allows the SMM I/O instruction restart
feature to be present.
Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
---
src/fw/smm.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/fw/smm.c b/src/fw/smm.c
index dabc677..6cb484e 100644
--- a/src/fw/smm.c
+++ b/src/fw/smm.c
@@ -18,8 +18,14 @@
#include "util.h" // smm_setup
#include "x86.h" // wbinvd
-#define SMM_REV_I32 0x00020000
-#define SMM_REV_I64 0x00020064
+/*
+ * Check SMM state save area format (bits 0-15) and require support
+ * for SMBASE relocation.
+ */
+#define SMM_REV_MASK 0x0002ffff
+
+#define SMM_REV_I32 0x00020000
+#define SMM_REV_I64 0x00020064
struct smm_state {
union {
@@ -62,9 +68,10 @@ handle_smi(u16 cs)
if (smm == (void*)BUILD_SMM_INIT_ADDR) {
// relocate SMBASE to 0xa0000
- if (smm->cpu.i32.smm_rev == SMM_REV_I32) {
+ u32 rev = smm->cpu.i32.smm_rev & SMM_REV_MASK;
+ if (rev == SMM_REV_I32) {
smm->cpu.i32.smm_base = BUILD_SMM_ADDR;
- } else if (smm->cpu.i64.smm_rev == SMM_REV_I64) {
+ } else if (rev == SMM_REV_I64) {
smm->cpu.i64.smm_base = BUILD_SMM_ADDR;
} else {
warn_internalerror();
--
2.3.5
4 years, 4 months
[PATCH] ich9: initialise RCBA register through LPC interface
by Paulo Alcantara
This patch initialises root complex register block BAR in order to
support TCO watchdog emulation features on QEMU.
Signed-off-by: Paulo Alcantara <pcacjr(a)zytor.com>
---
src/fw/dev-q35.h | 3 +++
src/fw/pciinit.c | 4 ++++
2 files changed, 7 insertions(+)
diff --git a/src/fw/dev-q35.h b/src/fw/dev-q35.h
index c6f8bd9..201825d 100644
--- a/src/fw/dev-q35.h
+++ b/src/fw/dev-q35.h
@@ -27,6 +27,9 @@
#define ICH9_LPC_GEN_PMCON_1_SMI_LOCK (1 << 4)
#define ICH9_LPC_PORT_ELCR1 0x4d0
#define ICH9_LPC_PORT_ELCR2 0x4d1
+#define ICH9_LPC_RCBA 0xf0
+#define ICH9_LPC_RCBA_ADDR 0xfed1c000
+#define ICH9_LPC_RCBA_EN 0x1
#define PCI_DEVICE_ID_INTEL_ICH9_SMBUS 0x2930
#define ICH9_SMB_SMB_BASE 0x20
#define ICH9_SMB_HOSTC 0x40
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index ac39d23..defccf3 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -183,6 +183,10 @@ static void mch_isa_bridge_setup(struct pci_device *dev, void *arg)
/* acpi enable, SCI: IRQ9 000b = irq9*/
pci_config_writeb(bdf, ICH9_LPC_ACPI_CTRL, ICH9_LPC_ACPI_CTRL_ACPI_EN);
+ /* set root complex register block BAR */
+ pci_config_writel(bdf, ICH9_LPC_RCBA,
+ ICH9_LPC_RCBA_ADDR | ICH9_LPC_RCBA_EN);
+
acpi_pm1a_cnt = acpi_pm_base + 0x04;
pmtimer_setup(acpi_pm_base + 0x08);
}
--
2.1.0
4 years, 5 months
[PATCH] Make sure all code checks for malloc failures
by Kevin O'Connor
This is the result of an audit of callers of the malloc_XXX() and
memalign_XXX() calls. All callers need to check if these functions
return NULL.
Signed-off-by: Kevin O'Connor <kevin(a)koconnor.net>
---
src/cdrom.c | 1 -
src/hw/ahci.c | 8 ++++++++
src/hw/megasas.c | 6 +++++-
src/hw/ramdisk.c | 2 +-
src/hw/usb-xhci.c | 9 ++++++++-
src/hw/usb.c | 4 +++-
6 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/src/cdrom.c b/src/cdrom.c
index 7ee36d9..ba02340 100644
--- a/src/cdrom.c
+++ b/src/cdrom.c
@@ -123,7 +123,6 @@ cdrom_prepboot(void)
struct drive_s *drive = malloc_fseg(sizeof(*drive));
if (!drive) {
warn_noalloc();
- free(drive);
return;
}
cdemu_drive_gf = drive;
diff --git a/src/hw/ahci.c b/src/hw/ahci.c
index 3193d81..0d71cc4 100644
--- a/src/hw/ahci.c
+++ b/src/hw/ahci.c
@@ -405,6 +405,14 @@ static struct ahci_port_s* ahci_port_realloc(struct ahci_port_s *port)
port->list = memalign_high(1024, 1024);
port->fis = memalign_high(256, 256);
port->cmd = memalign_high(256, 256);
+ if (!port->list || !port->fis || !port->cmd) {
+ warn_noalloc();
+ free(port->list);
+ free(port->fis);
+ free(port->cmd);
+ free(port);
+ return NULL;
+ }
ahci_port_writel(port->ctrl, port->pnr, PORT_LST_ADDR, (u32)port->list);
ahci_port_writel(port->ctrl, port->pnr, PORT_FIS_ADDR, (u32)port->fis);
diff --git a/src/hw/megasas.c b/src/hw/megasas.c
index b2a65e4..6677977 100644
--- a/src/hw/megasas.c
+++ b/src/hw/megasas.c
@@ -241,7 +241,10 @@ static void megasas_scan_target(struct pci_device *pci, u32 iobase)
{
struct mfi_ld_list_s ld_list;
struct megasas_cmd_frame *frame = memalign_tmp(256, sizeof(*frame));
- int i;
+ if (!frame) {
+ warn_noalloc();
+ return;
+ }
memset(&ld_list, 0, sizeof(ld_list));
memset_fl(frame, 0, sizeof(*frame));
@@ -258,6 +261,7 @@ static void megasas_scan_target(struct pci_device *pci, u32 iobase)
if (megasas_fire_cmd(pci->device, iobase, frame) == 0) {
dprintf(2, "%d LD found\n", ld_list.count);
+ int i;
for (i = 0; i < ld_list.count; i++) {
dprintf(2, "LD %d:%d state 0x%x\n",
ld_list.lds[i].target, ld_list.lds[i].lun,
diff --git a/src/hw/ramdisk.c b/src/hw/ramdisk.c
index 1177bc0..6b44c83 100644
--- a/src/hw/ramdisk.c
+++ b/src/hw/ramdisk.c
@@ -7,7 +7,7 @@
#include "biosvar.h" // GET_GLOBALFLAT
#include "block.h" // struct drive_s
#include "bregs.h" // struct bregs
-#include "malloc.h" // malloc_fseg
+#include "malloc.h" // memalign_tmphigh
#include "memmap.h" // add_e820
#include "output.h" // dprintf
#include "romfile.h" // romfile_findprefix
diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c
index fd58334..41a6a3f 100644
--- a/src/hw/usb-xhci.c
+++ b/src/hw/usb-xhci.c
@@ -921,8 +921,14 @@ xhci_alloc_pipe(struct usbdevice_s *usbdev
usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
pipe->epid = epid;
pipe->reqs.cs = 1;
- if (eptype == USB_ENDPOINT_XFER_INT)
+ if (eptype == USB_ENDPOINT_XFER_INT) {
pipe->buf = malloc_high(pipe->pipe.maxpacket);
+ if (!pipe->buf) {
+ warn_noalloc();
+ free(pipe);
+ return NULL;
+ }
+ }
// Allocate input context and initialize endpoint info.
struct xhci_inctx *in = xhci_alloc_inctx(usbdev, epid);
@@ -988,6 +994,7 @@ xhci_alloc_pipe(struct usbdevice_s *usbdev
return &pipe->pipe;
fail:
+ free(pipe->buf);
free(pipe);
free(in);
return NULL;
diff --git a/src/hw/usb.c b/src/hw/usb.c
index 1b4ea8b..2d5c224 100644
--- a/src/hw/usb.c
+++ b/src/hw/usb.c
@@ -249,8 +249,10 @@ get_device_config(struct usb_pipe *pipe)
return NULL;
void *config = malloc_tmphigh(cfg.wTotalLength);
- if (!config)
+ if (!config) {
+ warn_noalloc();
return NULL;
+ }
req.wLength = cfg.wTotalLength;
ret = usb_send_default_control(pipe, &req, config);
if (ret) {
--
1.9.3
4 years, 5 months
[PATCH] bootorder: Update "extra pci root" buses bootorder format to match qemu
by Kevin O'Connor
The QEMU code will use the prefix "/pci@i0cf8,%x/" for devices on
extra pci root buses, so change the SeaBIOS code to match that.
Signed-off-by: Kevin O'Connor <kevin(a)koconnor.net>
---
src/boot.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/boot.c b/src/boot.c
index ec59c37..e0f73a3 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -112,9 +112,9 @@ build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci)
if (pci->parent) {
p = build_pci_path(p, max, "pci-bridge", pci->parent);
} else {
- if (pci->rootbus)
- p += snprintf(p, max, "/pci-root@%x", pci->rootbus);
p += snprintf(p, buf+max-p, "%s", FW_PCI_DOMAIN);
+ if (pci->rootbus)
+ p += snprintf(p, buf+max-p, ",%x", pci->rootbus);
}
int dev = pci_bdf_to_dev(pci->bdf), fn = pci_bdf_to_fn(pci->bdf);
--
1.9.3
4 years, 5 months
[PATCH 00/18] virtio: add version 1.0 support
by Gerd Hoffmann
Hi,
This patch series adds virtio 1.0 support to the virtio blk and scsi
drivers in seabios. With this series applied seabios happily boots
in virtio 1.0 mode from both transitional and modern devices.
Tested with Fedora 22 guest, booting from virtio-scsi cdrom (live iso),
virtio-scsi disk and virtio-blk disk.
The patches are also available in the git repository at:
git://git.kraxel.org/seabios virtio
please review,
Gerd
----------------------------------------------------------------
Gerd Hoffmann (18):
pci: allow to loop over capabilities
virtio: run drivers in 32bit mode
virtio: add struct vp_device
virtio: pass struct pci_device to vp_init_simple
virtio: add version 1.0 structs and #defines
virtio: find version 1.0 virtio capabilities
virtio: add version 1.0 read/write macros
virtio: make features 64bit, support version 1.0 features
virtio: add version 1.0 support to vp_{get,set}_status
virtio: add version 1.0 support to vp_get_isr
virtio: add version 1.0 support to vp_reset
virtio: add version 1.0 support to vp_notify
virtio: remove unused vp_del_vq
virtio: add version 1.0 support to vp_find_vq
virtio-scsi: fix initialization for version 1.0
virtio-blk: fix initialization for version 1.0
virtio: use version 1.0 if available (flip the big switch)
virtio: also probe version 1.0 pci ids
src/block.c | 8 +-
src/fw/pciinit.c | 4 +-
src/hw/pci.c | 11 ++-
src/hw/pci.h | 2 +-
src/hw/pci_ids.h | 8 +-
src/hw/virtio-blk.c | 104 +++++++++++++++------
src/hw/virtio-pci.c | 250 ++++++++++++++++++++++++++++++++++++++++++++++-----
src/hw/virtio-pci.h | 205 ++++++++++++++++++++++++++++++++----------
src/hw/virtio-ring.c | 4 +-
src/hw/virtio-ring.h | 9 +-
src/hw/virtio-scsi.c | 60 +++++++++----
11 files changed, 537 insertions(+), 128 deletions(-)
4 years, 5 months
[PATCH 1/3] ich9: add TCO interface emulation
by Paulo Alcantara
This interface provides some registers within a 32-byte range and can be
acessed through PCI-to-LPC bridge interface (PMBASE + 0x60).
It's commonly used as a watchdog timer to detect system lockups through
SMIs that are generated -- if TCO_EN bit is set -- on every timeout. If
NO_REBOOT bit is not set in GCS (General Control and Status register),
the system will be resetted upon second timeout if TCO_RLD register
wasn't previously written to prevent timeout.
This patch adds support to TCO watchdog logic and few other features
like mapping NMIs to SMIs (NMI2SMI_EN bit), system intruder detection,
etc. are not implemented yet.
Signed-off-by: Paulo Alcantara <pcacjr(a)zytor.com>
---
hw/acpi/Makefile.objs | 1 +
hw/acpi/ich9.c | 36 ++++++++++
hw/acpi/tco.c | 188 +++++++++++++++++++++++++++++++++++++++++++++++++
hw/isa/lpc_ich9.c | 10 +++
include/hw/acpi/ich9.h | 4 ++
include/hw/acpi/tco.h | 139 ++++++++++++++++++++++++++++++++++++
include/hw/i386/ich9.h | 8 +++
7 files changed, 386 insertions(+)
create mode 100644 hw/acpi/tco.c
create mode 100644 include/hw/acpi/tco.h
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index b9fefa7..a32b7f8 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -1,4 +1,5 @@
common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o pcihp.o cpu_hotplug.o
+common-obj-$(CONFIG_ACPI) += tco.o
common-obj-$(CONFIG_ACPI) += memory_hotplug.o
common-obj-$(CONFIG_ACPI) += acpi_interface.o
common-obj-$(CONFIG_ACPI) += bios-linker-loader.o
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 84e5bb8..8c4364b 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -30,6 +30,7 @@
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
#include "hw/acpi/acpi.h"
+#include "hw/acpi/tco.h"
#include "sysemu/kvm.h"
#include "exec/address-spaces.h"
@@ -92,8 +93,15 @@ static void ich9_smi_writel(void *opaque, hwaddr addr, uint64_t val,
unsigned width)
{
ICH9LPCPMRegs *pm = opaque;
+ TCOIORegs *tr = &pm->tco_regs;
+
switch (addr) {
case 0:
+ /* once TCO_LOCK bit is set, TCO_EN bit cannot be overwritten */
+ if (tr->tco.cnt1 & TCO_LOCK) {
+ val &= ~ICH9_PMIO_SMI_EN_TCO_EN;
+ val |= pm->smi_en & ICH9_PMIO_SMI_EN_TCO_EN;
+ }
pm->smi_en = val;
break;
}
@@ -107,6 +115,29 @@ static const MemoryRegionOps ich9_smi_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
+static uint64_t ich9_tco_readw(void *opaque, hwaddr addr, unsigned width)
+{
+ ICH9LPCPMRegs *pm = opaque;
+ return acpi_pm_tco_ioport_readw(&pm->tco_regs, addr);
+}
+
+static void ich9_tco_writew(void *opaque, hwaddr addr, uint64_t val,
+ unsigned width)
+{
+ ICH9LPCPMRegs *pm = opaque;
+ acpi_pm_tco_ioport_writew(&pm->tco_regs, addr, val);
+}
+
+static const MemoryRegionOps ich9_tco_ops = {
+ .read = ich9_tco_readw,
+ .write = ich9_tco_writew,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 2,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base)
{
ICH9_DEBUG("to 0x%x\n", pm_io_base);
@@ -230,6 +261,11 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
"acpi-smi", 8);
memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi);
+ acpi_pm_tco_init(&pm->tco_regs);
+ memory_region_init_io(&pm->io_tco, OBJECT(lpc_pci), &ich9_tco_ops, pm,
+ "sm-tco", ICH9_PMIO_TCO_LEN);
+ memory_region_add_subregion(&pm->io, ICH9_PMIO_TCO_RLD, &pm->io_tco);
+
pm->irq = sci_irq;
qemu_register_reset(pm_reset, pm);
pm->powerdown_notifier.notify = pm_powerdown_req;
diff --git a/hw/acpi/tco.c b/hw/acpi/tco.c
new file mode 100644
index 0000000..3a44a95
--- /dev/null
+++ b/hw/acpi/tco.c
@@ -0,0 +1,188 @@
+/*
+ * QEMU ICH9 TCO emulation
+ *
+ * Copyright (c) 2015 Paulo Alcantara <pcacjr(a)zytor.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu-common.h"
+#include "sysemu/watchdog.h"
+#include "hw/i386/ich9.h"
+
+#include "hw/acpi/tco.h"
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define TCO_DEBUG(fmt, ...) \
+ do { \
+ fprintf(stderr, "%s "fmt, __func__, ## __VA_ARGS__); \
+ } while (0)
+#else
+#define TCO_DEBUG(fmt, ...) do { } while (0)
+#endif
+
+static QEMUTimer *tco_timer;
+static unsigned int timeouts_no;
+
+static inline void tco_timer_reload(void)
+{
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+
+ timer_del(tco_timer);
+ timer_mod(tco_timer, now + tco_ticks_per_sec());
+}
+
+static inline void tco_timer_stop(void)
+{
+ timer_del(tco_timer);
+}
+
+static void tco_timer_expired(void *opaque)
+{
+ TCOIORegs *tr = opaque;
+ ICH9LPCPMRegs *pm = container_of(tr, ICH9LPCPMRegs, tco_regs);
+ ICH9LPCState *lpc = container_of(pm, ICH9LPCState, pm);
+ uint32_t gcs = pci_get_long(lpc->chip_config + ICH9_LPC_RCBA_GCS);
+
+ tr->tco.rld--;
+ if (tr->tco.rld & TCO_RLD_MASK) {
+ goto out;
+ }
+
+ tr->tco.sts1 |= TCO_TIMEOUT;
+ if (++timeouts_no == 2) {
+ tr->tco.sts1 |= TCO_SECOND_TO_STS;
+ tr->tco.sts1 |= TCO_BOOT_STS;
+ timeouts_no = 0;
+
+ if (!(gcs & ICH9_LPC_RCBA_GCS_NO_REBOOT)) {
+ watchdog_perform_action();
+ tco_timer_stop();
+ return;
+ }
+ }
+ tr->tco.rld = tr->tco.tmr;
+
+ if (pm->smi_en & ICH9_PMIO_SMI_EN_TCO_EN) {
+ ich9_generate_smi();
+ } else {
+ ich9_generate_nmi();
+ }
+
+out:
+ tco_timer_reload();
+}
+
+void acpi_pm_tco_init(TCOIORegs *tr)
+{
+ *tr = TCO_IO_REGS_DEFAULTS_INIT();
+ tco_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tco_timer_expired, tr);
+}
+
+uint32_t acpi_pm_tco_ioport_readw(TCOIORegs *tr, uint32_t addr)
+{
+ switch (addr) {
+ case TCO_RLD:
+ return tr->tco.rld;
+ case TCO_DAT_IN:
+ return tr->tco.din;
+ case TCO_DAT_OUT:
+ return tr->tco.dout;
+ case TCO1_STS:
+ return tr->tco.sts1;
+ case TCO2_STS:
+ return tr->tco.sts2;
+ case TCO1_CNT:
+ return tr->tco.cnt1;
+ case TCO2_CNT:
+ return tr->tco.cnt2;
+ case TCO_MESSAGE1:
+ return tr->tco.msg1;
+ case TCO_MESSAGE2:
+ return tr->tco.msg2;
+ case TCO_WDCNT:
+ return tr->tco.wdcnt;
+ case TCO_TMR:
+ return tr->tco.tmr;
+ case SW_IRQ_GEN:
+ return tr->sw_irq_gen;
+ }
+ return 0;
+}
+
+void acpi_pm_tco_ioport_writew(TCOIORegs *tr, uint32_t addr, uint32_t val)
+{
+ switch (addr) {
+ case TCO_RLD:
+ timeouts_no = 0;
+ if (can_start_tco_timer(tr)) {
+ tr->tco.rld = tr->tco.tmr;
+ tco_timer_reload();
+ } else {
+ tr->tco.rld = val;
+ }
+ break;
+ case TCO_DAT_IN:
+ tr->tco.din = val;
+ tr->tco.sts1 |= SW_TCO_SMI;
+ ich9_generate_smi();
+ break;
+ case TCO_DAT_OUT:
+ tr->tco.dout = val;
+ tr->tco.sts1 |= TCO_INT_STS;
+ /* TODO: cause an interrupt, as selected by the TCO_INT_SEL bits */
+ break;
+ case TCO1_STS:
+ tr->tco.sts1 = val & TCO1_STS_MASK;
+ break;
+ case TCO2_STS:
+ tr->tco.sts2 = val & TCO2_STS_MASK;
+ break;
+ case TCO1_CNT:
+ val &= TCO1_CNT_MASK;
+ /* TCO_LOCK bit cannot be changed once set */
+ tr->tco.cnt1 = (val & ~TCO_LOCK) | (tr->tco.cnt1 & TCO_LOCK);
+ if (can_start_tco_timer(tr)) {
+ tr->tco.rld = tr->tco.tmr;
+ tco_timer_reload();
+ } else {
+ tco_timer_stop();
+ }
+ break;
+ case TCO2_CNT:
+ tr->tco.cnt2 = val;
+ break;
+ case TCO_MESSAGE1:
+ tr->tco.msg1 = val;
+ break;
+ case TCO_MESSAGE2:
+ tr->tco.msg2 = val;
+ break;
+ case TCO_WDCNT:
+ tr->tco.wdcnt = val;
+ break;
+ case TCO_TMR:
+ tr->tco.tmr = val;
+ break;
+ case SW_IRQ_GEN:
+ tr->sw_irq_gen = val;
+ break;
+ }
+}
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index dba7585..7bfb683 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -313,6 +313,16 @@ PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin)
return route;
}
+void ich9_generate_smi(void)
+{
+ cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
+}
+
+void ich9_generate_nmi(void)
+{
+ cpu_interrupt(first_cpu, CPU_INTERRUPT_NMI);
+}
+
static int ich9_lpc_sci_irq(ICH9LPCState *lpc)
{
switch (lpc->d.config[ICH9_LPC_ACPI_CTRL] &
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index c2d3dba..31c74af 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -25,6 +25,7 @@
#include "hw/acpi/cpu_hotplug.h"
#include "hw/acpi/memory_hotplug.h"
#include "hw/acpi/acpi_dev_interface.h"
+#include "hw/acpi/tco.h"
typedef struct ICH9LPCPMRegs {
/*
@@ -37,6 +38,7 @@ typedef struct ICH9LPCPMRegs {
MemoryRegion io;
MemoryRegion io_gpe;
MemoryRegion io_smi;
+ MemoryRegion io_tco;
uint32_t smi_en;
uint32_t smi_sts;
@@ -53,6 +55,8 @@ typedef struct ICH9LPCPMRegs {
uint8_t disable_s3;
uint8_t disable_s4;
uint8_t s4_val;
+
+ TCOIORegs tco_regs;
} ICH9LPCPMRegs;
void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
diff --git a/include/hw/acpi/tco.h b/include/hw/acpi/tco.h
new file mode 100644
index 0000000..700532c
--- /dev/null
+++ b/include/hw/acpi/tco.h
@@ -0,0 +1,139 @@
+/*
+ * QEMU ICH9 TCO emulation
+ *
+ * Copyright (c) 2015 Paulo Alcantara <pcacjr(a)zytor.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef HW_ACPI_TCO_H
+#define HW_ACPI_TCO_H
+
+#include "qemu/typedefs.h"
+#include "qemu-common.h"
+
+/* TCO I/O register offsets */
+enum {
+ TCO_RLD = 0x00,
+ TCO_DAT_IN = 0x02,
+ TCO_DAT_OUT = 0x03,
+ TCO1_STS = 0x04,
+ TCO2_STS = 0x06,
+ TCO1_CNT = 0x08,
+ TCO2_CNT = 0x0a,
+ TCO_MESSAGE1 = 0x0c,
+ TCO_MESSAGE2 = 0x0d,
+ TCO_WDCNT = 0x0e,
+ SW_IRQ_GEN = 0x10,
+ TCO_TMR = 0x12,
+};
+
+/* TCO I/O register defaults */
+enum {
+ TCO_RLD_DEFAULT = 0x0000,
+ TCO_DAT_IN_DEFAULT = 0x00,
+ TCO_DAT_OUT_DEFAULT = 0x00,
+ TCO1_STS_DEFAULT = 0x0000,
+ TCO2_STS_DEFAULT = 0x0000,
+ TCO1_CNT_DEFAULT = 0x0000,
+ TCO2_CNT_DEFAULT = 0x0008,
+ TCO_MESSAGE1_DEFAULT = 0x00,
+ TCO_MESSAGE2_DEFAULT = 0x00,
+ TCO_WDCNT_DEFAULT = 0x00,
+ TCO_TMR_DEFAULT = 0x0004,
+ SW_IRQ_GEN_DEFAULT = 0x03,
+};
+
+/* TCO I/O register control/status bits */
+enum {
+ SW_TCO_SMI = (1 << 1),
+ TCO_INT_STS = (1 << 2),
+ TCO_LOCK = (1 << 12),
+ TCO_TMR_HLT = (1 << 11),
+ TCO_TIMEOUT = (1 << 3),
+ TCO_SECOND_TO_STS = (1 << 1),
+ TCO_BOOT_STS = (1 << 2),
+};
+
+/* TCO I/O registers mask bits */
+enum {
+ TCO_RLD_MASK = 0x3ff,
+ TCO1_STS_MASK = 0xe870,
+ TCO2_STS_MASK = 0xfff8,
+ TCO1_CNT_MASK = 0xfeff,
+ TCO_TMR_MASK = 0x3ff,
+};
+
+typedef struct TCOIORegs {
+ struct {
+ uint16_t rld;
+ uint8_t din;
+ uint8_t dout;
+ uint16_t sts1;
+ uint16_t sts2;
+ uint16_t cnt1;
+ uint16_t cnt2;
+ uint8_t msg1;
+ uint8_t msg2;
+ uint8_t wdcnt;
+ uint16_t tmr;
+ } tco;
+ uint8_t sw_irq_gen;
+} TCOIORegs;
+
+#define TCO_IO_REGS_DEFAULTS_INIT() \
+ (TCOIORegs) { \
+ .tco = { \
+ .rld = TCO_RLD_DEFAULT, \
+ .din = TCO_DAT_IN_DEFAULT, \
+ .dout = TCO_DAT_OUT_DEFAULT, \
+ .sts1 = TCO1_STS_DEFAULT, \
+ .sts2 = TCO2_STS_DEFAULT, \
+ .cnt1 = TCO1_CNT_DEFAULT, \
+ .cnt2 = TCO2_CNT_DEFAULT, \
+ .msg1 = TCO_MESSAGE1_DEFAULT, \
+ .msg2 = TCO_MESSAGE2_DEFAULT, \
+ .wdcnt = TCO_WDCNT_DEFAULT, \
+ .tmr = TCO_TMR_DEFAULT, \
+ }, \
+ .sw_irq_gen = SW_IRQ_GEN_DEFAULT \
+ }
+
+/* tco.c */
+void acpi_pm_tco_init(TCOIORegs *tr);
+uint32_t acpi_pm_tco_ioport_readw(TCOIORegs *tr, uint32_t addr);
+void acpi_pm_tco_ioport_writew(TCOIORegs *tr, uint32_t addr, uint32_t val);
+
+/* As per ICH9 spec, the internal timer has an error of ~0.6s on every tick */
+static inline int64_t tco_ticks_per_sec(void)
+{
+ return 600000000LL;
+}
+
+static inline int is_valid_tco_time(uint32_t val)
+{
+ /* values of 0 or 1 will be ignored by ICH */
+ return val > 1;
+}
+
+static inline int can_start_tco_timer(TCOIORegs *tr)
+{
+ return !(tr->tco.cnt1 & TCO_TMR_HLT) && is_valid_tco_time(tr->tco.tmr);
+}
+
+#endif /* HW_ACPI_TCO_H */
diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h
index f4e522c..f41cca6 100644
--- a/include/hw/i386/ich9.h
+++ b/include/hw/i386/ich9.h
@@ -20,6 +20,9 @@ PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin);
void ich9_lpc_pm_init(PCIDevice *pci_lpc);
I2CBus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
+void ich9_generate_smi(void);
+void ich9_generate_nmi(void);
+
#define ICH9_CC_SIZE (16 * 1024) /* 16KB */
#define TYPE_ICH9_LPC_DEVICE "ICH9-LPC"
@@ -156,6 +159,8 @@ Object *ich9_lpc_find(void);
#define ICH9_LPC_RCBA_BA_MASK Q35_MASK(32, 31, 14)
#define ICH9_LPC_RCBA_EN 0x1
#define ICH9_LPC_RCBA_DEFAULT 0x0
+#define ICH9_LPC_RCBA_GCS 0x3410
+#define ICH9_LPC_RCBA_GCS_NO_REBOOT (1 << 5)
#define ICH9_LPC_PIC_NUM_PINS 16
#define ICH9_LPC_IOAPIC_NUM_PINS 24
@@ -180,7 +185,10 @@ Object *ich9_lpc_find(void);
#define ICH9_PMIO_GPE0_LEN 16
#define ICH9_PMIO_SMI_EN 0x30
#define ICH9_PMIO_SMI_EN_APMC_EN (1 << 5)
+#define ICH9_PMIO_SMI_EN_TCO_EN (1 << 13)
#define ICH9_PMIO_SMI_STS 0x34
+#define ICH9_PMIO_TCO_RLD 0x60
+#define ICH9_PMIO_TCO_LEN 32
/* FADT ACPI_ENABLE/ACPI_DISABLE */
#define ICH9_APM_ACPI_ENABLE 0x2
--
2.1.0
4 years, 5 months
[PATCH v2 00/22] virtio: add version 1.0 support
by Gerd Hoffmann
Hi,
This patch series adds virtio 1.0 support to the virtio blk and scsi
drivers in seabios. With this series applied seabios happily boots
in virtio 1.0 mode from both transitional and modern devices.
Tested with Fedora 22 guest, booting from virtio-scsi cdrom (live iso),
virtio-scsi disk and virtio-blk disk.
The patches are also available in the git repository at:
git://git.kraxel.org/seabios virtio
v2 changes:
* rename vp_modern_{read_write} to vp_{read,write}
* switch legacy virtio code to vp_{read,write} too.
* make vp_read return the values.
Gerd Hoffmann (22):
pci: allow to loop over capabilities
virtio: run drivers in 32bit mode
virtio: add struct vp_device
virtio: pass struct pci_device to vp_init_simple
virtio: add version 1.0 structs and #defines
virtio: add version 0.9.5 struct
virtio: find version 1.0 virtio capabilities
virtio: create vp_cap struct for legacy bar
virtio: add version 0.9.5 struct [fixup]
virtio: add read/write functions and macros
virtio: make features 64bit, support version 1.0 features
virtio: add version 1.0 support to vp_{get,set}_status
virtio: add version 1.0 support to vp_get_isr
virtio: add version 1.0 support to vp_reset
virtio: add version 1.0 support to vp_notify
virtio: remove unused vp_del_vq
virtio: add version 1.0 support to vp_find_vq
virtio-scsi: fix initialization for version 1.0
virtio-blk: fix initialization for version 1.0
virtio: use version 1.0 if available (flip the big switch)
virtio: also probe version 1.0 pci ids
virtio: legacy cleanup
src/block.c | 8 +-
src/fw/pciinit.c | 4 +-
src/hw/pci.c | 11 ++-
src/hw/pci.h | 2 +-
src/hw/pci_ids.h | 8 +-
src/hw/virtio-blk.c | 104 +++++++++++++++------
src/hw/virtio-pci.c | 228 +++++++++++++++++++++++++++++++++++++++++-----
src/hw/virtio-pci.h | 252 ++++++++++++++++++++++++++++++++++++---------------
src/hw/virtio-ring.c | 4 +-
src/hw/virtio-ring.h | 9 +-
src/hw/virtio-scsi.c | 60 ++++++++----
11 files changed, 535 insertions(+), 155 deletions(-)
--
1.8.3.1
4 years, 5 months
[PATCH] virtio: add struct vp_device
by Gerd Hoffmann
For virtio 1.0 support we will need more state than just the (legacy
mode) ioaddr for each virtio-pci device. Prepare for that by adding
a new struct for it. For now it carries the ioaddr only.
Signed-off-by: Gerd Hoffmann <kraxel(a)redhat.com>
---
src/hw/virtio-blk.c | 20 ++++++++++----------
src/hw/virtio-pci.c | 15 +++++++++------
src/hw/virtio-pci.h | 46 +++++++++++++++++++++++++++-------------------
src/hw/virtio-ring.c | 4 ++--
src/hw/virtio-ring.h | 3 ++-
src/hw/virtio-scsi.c | 32 +++++++++++++++++---------------
6 files changed, 67 insertions(+), 53 deletions(-)
diff --git a/src/hw/virtio-blk.c b/src/hw/virtio-blk.c
index e2dbd3c..ef99d57 100644
--- a/src/hw/virtio-blk.c
+++ b/src/hw/virtio-blk.c
@@ -25,7 +25,7 @@
struct virtiodrive_s {
struct drive_s drive;
struct vring_virtqueue *vq;
- u16 ioaddr;
+ struct vp_device *vp;
};
static int
@@ -60,7 +60,7 @@ virtio_blk_op(struct disk_op_s *op, int write)
vring_add_buf(vq, sg, 2, 1, 0, 0);
else
vring_add_buf(vq, sg, 1, 2, 0, 0);
- vring_kick(GET_GLOBALFLAT(vdrive_gf->ioaddr), vq, 1);
+ vring_kick(GET_GLOBALFLAT(vdrive_gf->vp), vq, 1);
/* Wait for reply */
while (!vring_more_used(vq))
@@ -72,7 +72,7 @@ virtio_blk_op(struct disk_op_s *op, int write)
/* Clear interrupt status register. Avoid leaving interrupts stuck if
* VRING_AVAIL_F_NO_INTERRUPT was ignored and interrupts were raised.
*/
- vp_get_isr(GET_GLOBALFLAT(vdrive_gf->ioaddr));
+ vp_get_isr(GET_GLOBALFLAT(vdrive_gf->vp));
return status == VIRTIO_BLK_S_OK ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK;
}
@@ -113,18 +113,17 @@ init_virtio_blk(struct pci_device *pci)
vdrive->drive.type = DTYPE_VIRTIO_BLK;
vdrive->drive.cntl_id = bdf;
- u16 ioaddr = vp_init_simple(bdf);
- vdrive->ioaddr = ioaddr;
- if (vp_find_vq(ioaddr, 0, &vdrive->vq) < 0 ) {
+ vdrive->vp = vp_init_simple(bdf);
+ if (vp_find_vq(vdrive->vp, 0, &vdrive->vq) < 0 ) {
dprintf(1, "fail to find vq for virtio-blk %x:%x\n",
pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));
goto fail;
}
struct virtio_blk_config cfg;
- vp_get(ioaddr, 0, &cfg, sizeof(cfg));
+ vp_get(vdrive->vp, 0, &cfg, sizeof(cfg));
- u32 f = vp_get_features(ioaddr);
+ u32 f = vp_get_features(vdrive->vp);
vdrive->drive.blksize = (f & (1 << VIRTIO_BLK_F_BLK_SIZE)) ?
cfg.blk_size : DISK_SECTOR_SIZE;
@@ -148,12 +147,13 @@ init_virtio_blk(struct pci_device *pci)
boot_add_hd(&vdrive->drive, desc, bootprio_find_pci_device(pci));
- vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
+ vp_set_status(vdrive->vp, VIRTIO_CONFIG_S_ACKNOWLEDGE |
VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK);
return;
fail:
- vp_reset(ioaddr);
+ vp_reset(vdrive->vp);
+ free(vdrive->vp);
free(vdrive->vq);
free(vdrive);
}
diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c
index b9b3ab1..a1e9939 100644
--- a/src/hw/virtio-pci.c
+++ b/src/hw/virtio-pci.c
@@ -24,9 +24,10 @@
#include "virtio-pci.h"
#include "virtio-ring.h"
-int vp_find_vq(unsigned int ioaddr, int queue_index,
+int vp_find_vq(struct vp_device *vp, int queue_index,
struct vring_virtqueue **p_vq)
{
+ int ioaddr = GET_LOWFLAT(vp->ioaddr);
u16 num;
ASSERT32FLAT();
@@ -84,14 +85,16 @@ fail:
return -1;
}
-u16 vp_init_simple(u16 bdf)
+struct vp_device *vp_init_simple(u16 bdf)
{
- u16 ioaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) &
+ struct vp_device *vp = malloc_low(sizeof(*vp));
+
+ vp->ioaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) &
PCI_BASE_ADDRESS_IO_MASK;
- vp_reset(ioaddr);
+ vp_reset(vp);
pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
- vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
+ vp_set_status(vp, VIRTIO_CONFIG_S_ACKNOWLEDGE |
VIRTIO_CONFIG_S_DRIVER );
- return ioaddr;
+ return vp;
}
diff --git a/src/hw/virtio-pci.h b/src/hw/virtio-pci.h
index bc04b03..47bef3d 100644
--- a/src/hw/virtio-pci.h
+++ b/src/hw/virtio-pci.h
@@ -2,6 +2,7 @@
#define _VIRTIO_PCI_H
#include "x86.h" // inl
+#include "biosvar.h" // GET_LOWFLAT
/* A 32-bit r/o bitmask of the features supported by the host */
#define VIRTIO_PCI_HOST_FEATURES 0
@@ -39,19 +40,24 @@
/* Virtio ABI version, this must match exactly */
#define VIRTIO_PCI_ABI_VERSION 0
-static inline u32 vp_get_features(unsigned int ioaddr)
+struct vp_device {
+ unsigned int ioaddr;
+};
+
+static inline u32 vp_get_features(struct vp_device *vp)
{
- return inl(ioaddr + VIRTIO_PCI_HOST_FEATURES);
+ return inl(GET_LOWFLAT(vp->ioaddr) + VIRTIO_PCI_HOST_FEATURES);
}
-static inline void vp_set_features(unsigned int ioaddr, u32 features)
+static inline void vp_set_features(struct vp_device *vp, u32 features)
{
- outl(features, ioaddr + VIRTIO_PCI_GUEST_FEATURES);
+ outl(features, GET_LOWFLAT(vp->ioaddr) + VIRTIO_PCI_GUEST_FEATURES);
}
-static inline void vp_get(unsigned int ioaddr, unsigned offset,
+static inline void vp_get(struct vp_device *vp, unsigned offset,
void *buf, unsigned len)
{
+ int ioaddr = GET_LOWFLAT(vp->ioaddr);
u8 *ptr = buf;
unsigned i;
@@ -59,47 +65,49 @@ static inline void vp_get(unsigned int ioaddr, unsigned offset,
ptr[i] = inb(ioaddr + VIRTIO_PCI_CONFIG + offset + i);
}
-static inline u8 vp_get_status(unsigned int ioaddr)
+static inline u8 vp_get_status(struct vp_device *vp)
{
- return inb(ioaddr + VIRTIO_PCI_STATUS);
+ return inb(GET_LOWFLAT(vp->ioaddr) + VIRTIO_PCI_STATUS);
}
-static inline void vp_set_status(unsigned int ioaddr, u8 status)
+static inline void vp_set_status(struct vp_device *vp, u8 status)
{
if (status == 0) /* reset */
return;
- outb(status, ioaddr + VIRTIO_PCI_STATUS);
+ outb(status, GET_LOWFLAT(vp->ioaddr) + VIRTIO_PCI_STATUS);
}
-static inline u8 vp_get_isr(unsigned int ioaddr)
+static inline u8 vp_get_isr(struct vp_device *vp)
{
- return inb(ioaddr + VIRTIO_PCI_ISR);
+ return inb(GET_LOWFLAT(vp->ioaddr) + VIRTIO_PCI_ISR);
}
-static inline void vp_reset(unsigned int ioaddr)
+static inline void vp_reset(struct vp_device *vp)
{
+ int ioaddr = GET_LOWFLAT(vp->ioaddr);
+
outb(0, ioaddr + VIRTIO_PCI_STATUS);
(void)inb(ioaddr + VIRTIO_PCI_ISR);
}
-static inline void vp_notify(unsigned int ioaddr, int queue_index)
+static inline void vp_notify(struct vp_device *vp, int queue_index)
{
- outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
+ outw(queue_index, GET_LOWFLAT(vp->ioaddr) + VIRTIO_PCI_QUEUE_NOTIFY);
}
-static inline void vp_del_vq(unsigned int ioaddr, int queue_index)
+static inline void vp_del_vq(struct vp_device *vp, int queue_index)
{
+ int ioaddr = GET_LOWFLAT(vp->ioaddr);
+
/* select the queue */
-
outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
/* deactivate the queue */
-
outl(0, ioaddr + VIRTIO_PCI_QUEUE_PFN);
}
struct vring_virtqueue;
-u16 vp_init_simple(u16 bdf);
-int vp_find_vq(unsigned int ioaddr, int queue_index,
+struct vp_device *vp_init_simple(u16 bdf);
+int vp_find_vq(struct vp_device *vp, int queue_index,
struct vring_virtqueue **p_vq);
#endif /* _VIRTIO_PCI_H_ */
diff --git a/src/hw/virtio-ring.c b/src/hw/virtio-ring.c
index 97e0b34..5c6a32e 100644
--- a/src/hw/virtio-ring.c
+++ b/src/hw/virtio-ring.c
@@ -136,7 +136,7 @@ void vring_add_buf(struct vring_virtqueue *vq,
SET_LOWFLAT(avail->ring[av], head);
}
-void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
+void vring_kick(struct vp_device *vp, struct vring_virtqueue *vq, int num_added)
{
struct vring *vr = &vq->vring;
struct vring_avail *avail = GET_LOWFLAT(vr->avail);
@@ -145,5 +145,5 @@ void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
smp_wmb();
SET_LOWFLAT(avail->idx, GET_LOWFLAT(avail->idx) + num_added);
- vp_notify(ioaddr, GET_LOWFLAT(vq->queue_index));
+ vp_notify(vp, GET_LOWFLAT(vq->queue_index));
}
diff --git a/src/hw/virtio-ring.h b/src/hw/virtio-ring.h
index b7a7aaf..fe5133b 100644
--- a/src/hw/virtio-ring.h
+++ b/src/hw/virtio-ring.h
@@ -120,12 +120,13 @@ static inline void vring_init(struct vring *vr,
vr->desc[i].next = 0;
}
+struct vp_device;
int vring_more_used(struct vring_virtqueue *vq);
void vring_detach(struct vring_virtqueue *vq, unsigned int head);
int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len);
void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[],
unsigned int out, unsigned int in,
int index, int num_added);
-void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added);
+void vring_kick(struct vp_device *vp, struct vring_virtqueue *vq, int num_added);
#endif /* _VIRTIO_RING_H_ */
diff --git a/src/hw/virtio-scsi.c b/src/hw/virtio-scsi.c
index 8f96687..25d2db7 100644
--- a/src/hw/virtio-scsi.c
+++ b/src/hw/virtio-scsi.c
@@ -27,14 +27,15 @@ struct virtio_lun_s {
struct drive_s drive;
struct pci_device *pci;
struct vring_virtqueue *vq;
- u16 ioaddr;
+ struct vp_device *vp;
u16 target;
u16 lun;
};
static int
-virtio_scsi_cmd(u16 ioaddr, struct vring_virtqueue *vq, struct disk_op_s *op,
- void *cdbcmd, u16 target, u16 lun, u16 blocksize)
+virtio_scsi_cmd(struct vp_device *vp, struct vring_virtqueue *vq,
+ struct disk_op_s *op, void *cdbcmd, u16 target, u16 lun,
+ u16 blocksize)
{
struct virtio_scsi_req_cmd req;
struct virtio_scsi_resp_cmd resp;
@@ -66,7 +67,7 @@ virtio_scsi_cmd(u16 ioaddr, struct vring_virtqueue *vq, struct disk_op_s *op,
/* Add to virtqueue and kick host */
vring_add_buf(vq, sg, out_num, in_num, 0, 0);
- vring_kick(ioaddr, vq, 1);
+ vring_kick(vp, vq, 1);
/* Wait for reply */
while (!vring_more_used(vq))
@@ -78,7 +79,7 @@ virtio_scsi_cmd(u16 ioaddr, struct vring_virtqueue *vq, struct disk_op_s *op,
/* Clear interrupt status register. Avoid leaving interrupts stuck if
* VRING_AVAIL_F_NO_INTERRUPT was ignored and interrupts were raised.
*/
- vp_get_isr(ioaddr);
+ vp_get_isr(vp);
if (resp.response == VIRTIO_SCSI_S_OK && resp.status == 0) {
return DISK_RET_SUCCESS;
@@ -92,7 +93,7 @@ virtio_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
struct virtio_lun_s *vlun_gf =
container_of(op->drive_gf, struct virtio_lun_s, drive);
- return virtio_scsi_cmd(GET_GLOBALFLAT(vlun_gf->ioaddr),
+ return virtio_scsi_cmd(GET_GLOBALFLAT(vlun_gf->vp),
GET_GLOBALFLAT(vlun_gf->vq), op, cdbcmd,
GET_GLOBALFLAT(vlun_gf->target),
GET_GLOBALFLAT(vlun_gf->lun),
@@ -100,7 +101,7 @@ virtio_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
}
static int
-virtio_scsi_add_lun(struct pci_device *pci, u16 ioaddr,
+virtio_scsi_add_lun(struct pci_device *pci, struct vp_device *vp,
struct vring_virtqueue *vq, u16 target, u16 lun)
{
struct virtio_lun_s *vlun = malloc_fseg(sizeof(*vlun));
@@ -112,7 +113,7 @@ virtio_scsi_add_lun(struct pci_device *pci, u16 ioaddr,
vlun->drive.type = DTYPE_VIRTIO_SCSI;
vlun->drive.cntl_id = pci->bdf;
vlun->pci = pci;
- vlun->ioaddr = ioaddr;
+ vlun->vp = vp;
vlun->vq = vq;
vlun->target = target;
vlun->lun = lun;
@@ -129,11 +130,11 @@ fail:
}
static int
-virtio_scsi_scan_target(struct pci_device *pci, u16 ioaddr,
+virtio_scsi_scan_target(struct pci_device *pci, struct vp_device *vp,
struct vring_virtqueue *vq, u16 target)
{
/* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */
- int ret = virtio_scsi_add_lun(pci, ioaddr, vq, target, 0);
+ int ret = virtio_scsi_add_lun(pci, vp, vq, target, 0);
return ret < 0 ? 0 : 1;
}
@@ -144,19 +145,19 @@ init_virtio_scsi(struct pci_device *pci)
dprintf(1, "found virtio-scsi at %x:%x\n", pci_bdf_to_bus(bdf),
pci_bdf_to_dev(bdf));
struct vring_virtqueue *vq = NULL;
- u16 ioaddr = vp_init_simple(bdf);
- if (vp_find_vq(ioaddr, 2, &vq) < 0 ) {
+ struct vp_device *vp = vp_init_simple(bdf);
+ if (vp_find_vq(vp, 2, &vq) < 0 ) {
dprintf(1, "fail to find vq for virtio-scsi %x:%x\n",
pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));
goto fail;
}
- vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
+ vp_set_status(vp, VIRTIO_CONFIG_S_ACKNOWLEDGE |
VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK);
int i, tot;
for (tot = 0, i = 0; i < 256; i++)
- tot += virtio_scsi_scan_target(pci, ioaddr, vq, i);
+ tot += virtio_scsi_scan_target(pci, vp, vq, i);
if (!tot)
goto fail;
@@ -164,7 +165,8 @@ init_virtio_scsi(struct pci_device *pci)
return;
fail:
- vp_reset(ioaddr);
+ vp_reset(vp);
+ free(vp);
free(vq);
}
--
1.8.3.1
4 years, 5 months
Re: [SeaBIOS] [PATCH v7 10/10] hw/pci-bridge: format special OFW unit address for PXB host
by Kevin O'Connor
On Fri, Jun 19, 2015 at 04:40:17AM +0200, Laszlo Ersek wrote:
> We have agreed that OpenFirmware device paths in the "bootorder" fw_cfg
> file should follow the pattern
>
> /pci@i0cf8,%x/...
>
> for devices that live behind an extra root bus. The extra root bus in
> question is the %x'th among the extra root buses. (In other words, %x
> gives the position of the affected extra root bus relative to the other
> extra root buses, in bus_nr order.) %x starts at 1, and is formatted in
> hex.
>
> The portion of the unit address that comes before the comma is dynamically
> taken from the main host bridge, similarly to sysbus_get_fw_dev_path().
>
> Cc: Kevin O'Connor <kevin(a)koconnor.net>
> Cc: Michael S. Tsirkin <mst(a)redhat.com>
> Cc: Marcel Apfelbaum <marcel(a)redhat.com>
> Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
> ---
>
> Notes:
> v7:
> - implement the format that both Kevin and Michael agreed with. Example:
> /pci@i0cf8,1/pci-bridge@0/scsi@0/channel@0/disk@0,0
> - I updated the OVMF patchset accordingly, but I won't post it until
> this QEMU patch is applied
> - Someone please write the SeaBIOS patch
The associated SeaBIOS patch is below.
Does anyone have a qemu command line handy to test with the PXB bus?
-Kevin
--- a/src/boot.c
+++ b/src/boot.c
@@ -112,9 +112,9 @@ build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci)
if (pci->parent) {
p = build_pci_path(p, max, "pci-bridge", pci->parent);
} else {
- if (pci->rootbus)
- p += snprintf(p, max, "/pci-root@%x", pci->rootbus);
p += snprintf(p, buf+max-p, "%s", FW_PCI_DOMAIN);
+ if (pci->rootbus)
+ p += snprintf(p, buf+max-p, ",%x", pci->rootbus);
}
int dev = pci_bdf_to_dev(pci->bdf), fn = pci_bdf_to_fn(pci->bdf);
4 years, 5 months
Re: [SeaBIOS] [PATCH v4 1/3] ich9: add TCO interface emulation
by Paolo Bonzini
On 22/06/2015 10:43, Michael S. Tsirkin wrote:
> Given that support is known to be partial, would it make sense
> to keep it disabled by default for 2.4?
What is partial about it? In fact, considering that q35 behavior is
still experimental it makes no sense to even make it conditional. We
discussed this on IRC and I was hoping to hear you reply "sorry, I was
wrong". Instead, I get this.
Michael, I'm seriously getting annoyed by this behavior. Stop scaring
away contributors.
Paolo
> This way in 2.5 we won't need to add more flags to stay bug compatible.
4 years, 5 months