summaryrefslogtreecommitdiffstats
path: root/qemu/tests/libqos
diff options
context:
space:
mode:
authorRajithaY <rajithax.yerrumsetty@intel.com>2017-04-25 03:31:15 -0700
committerRajitha Yerrumchetty <rajithax.yerrumsetty@intel.com>2017-05-22 06:48:08 +0000
commitbb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch)
treeca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/tests/libqos
parenta14b48d18a9ed03ec191cf16b162206998a895ce (diff)
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to kvmfornfv repo and make use of the updated latest qemu for the execution of all testcase Change-Id: I1280af507a857675c7f81d30c95255635667bdd7 Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/tests/libqos')
-rw-r--r--qemu/tests/libqos/ahci.c1124
-rw-r--r--qemu/tests/libqos/ahci.h627
-rw-r--r--qemu/tests/libqos/fw_cfg.c108
-rw-r--r--qemu/tests/libqos/fw_cfg.h41
-rw-r--r--qemu/tests/libqos/i2c-imx.c208
-rw-r--r--qemu/tests/libqos/i2c-omap.c172
-rw-r--r--qemu/tests/libqos/i2c.c23
-rw-r--r--qemu/tests/libqos/i2c.h32
-rw-r--r--qemu/tests/libqos/libqos-pc.c30
-rw-r--r--qemu/tests/libqos/libqos-pc.h10
-rw-r--r--qemu/tests/libqos/libqos.c254
-rw-r--r--qemu/tests/libqos/libqos.h40
-rw-r--r--qemu/tests/libqos/malloc-generic.c40
-rw-r--r--qemu/tests/libqos/malloc-generic.h21
-rw-r--r--qemu/tests/libqos/malloc-pc.c52
-rw-r--r--qemu/tests/libqos/malloc-pc.h22
-rw-r--r--qemu/tests/libqos/malloc.c377
-rw-r--r--qemu/tests/libqos/malloc.h40
-rw-r--r--qemu/tests/libqos/pci-pc.c303
-rw-r--r--qemu/tests/libqos/pci-pc.h21
-rw-r--r--qemu/tests/libqos/pci.c267
-rw-r--r--qemu/tests/libqos/pci.h92
-rw-r--r--qemu/tests/libqos/usb.c70
-rw-r--r--qemu/tests/libqos/usb.h17
-rw-r--r--qemu/tests/libqos/virtio-mmio.c198
-rw-r--r--qemu/tests/libqos/virtio-mmio.h46
-rw-r--r--qemu/tests/libqos/virtio-pci.c353
-rw-r--r--qemu/tests/libqos/virtio-pci.h61
-rw-r--r--qemu/tests/libqos/virtio.c282
-rw-r--r--qemu/tests/libqos/virtio.h193
30 files changed, 0 insertions, 5124 deletions
diff --git a/qemu/tests/libqos/ahci.c b/qemu/tests/libqos/ahci.c
deleted file mode 100644
index ac6c155c8..000000000
--- a/qemu/tests/libqos/ahci.c
+++ /dev/null
@@ -1,1124 +0,0 @@
-/*
- * libqos AHCI functions
- *
- * Copyright (c) 2014 John Snow <jsnow@redhat.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/osdep.h"
-#include <glib.h>
-
-#include "libqtest.h"
-#include "libqos/ahci.h"
-#include "libqos/pci-pc.h"
-
-#include "qemu-common.h"
-#include "qemu/host-utils.h"
-
-#include "hw/pci/pci_ids.h"
-#include "hw/pci/pci_regs.h"
-
-typedef struct AHCICommandProp {
- uint8_t cmd; /* Command Code */
- bool data; /* Data transfer command? */
- bool pio;
- bool dma;
- bool lba28;
- bool lba48;
- bool read;
- bool write;
- bool atapi;
- bool ncq;
- uint64_t size; /* Static transfer size, for commands like IDENTIFY. */
- uint32_t interrupts; /* Expected interrupts for this command. */
-} AHCICommandProp;
-
-AHCICommandProp ahci_command_properties[] = {
- { .cmd = CMD_READ_PIO, .data = true, .pio = true,
- .lba28 = true, .read = true },
- { .cmd = CMD_WRITE_PIO, .data = true, .pio = true,
- .lba28 = true, .write = true },
- { .cmd = CMD_READ_PIO_EXT, .data = true, .pio = true,
- .lba48 = true, .read = true },
- { .cmd = CMD_WRITE_PIO_EXT, .data = true, .pio = true,
- .lba48 = true, .write = true },
- { .cmd = CMD_READ_DMA, .data = true, .dma = true,
- .lba28 = true, .read = true },
- { .cmd = CMD_WRITE_DMA, .data = true, .dma = true,
- .lba28 = true, .write = true },
- { .cmd = CMD_READ_DMA_EXT, .data = true, .dma = true,
- .lba48 = true, .read = true },
- { .cmd = CMD_WRITE_DMA_EXT, .data = true, .dma = true,
- .lba48 = true, .write = true },
- { .cmd = CMD_IDENTIFY, .data = true, .pio = true,
- .size = 512, .read = true },
- { .cmd = READ_FPDMA_QUEUED, .data = true, .dma = true,
- .lba48 = true, .read = true, .ncq = true },
- { .cmd = WRITE_FPDMA_QUEUED, .data = true, .dma = true,
- .lba48 = true, .write = true, .ncq = true },
- { .cmd = CMD_READ_MAX, .lba28 = true },
- { .cmd = CMD_READ_MAX_EXT, .lba48 = true },
- { .cmd = CMD_FLUSH_CACHE, .data = false },
- { .cmd = CMD_PACKET, .data = true, .size = 16,
- .atapi = true, .pio = true },
- { .cmd = CMD_PACKET_ID, .data = true, .pio = true,
- .size = 512, .read = true }
-};
-
-struct AHCICommand {
- /* Test Management Data */
- uint8_t name;
- uint8_t port;
- uint8_t slot;
- uint32_t interrupts;
- uint64_t xbytes;
- uint32_t prd_size;
- uint64_t buffer;
- AHCICommandProp *props;
- /* Data to be transferred to the guest */
- AHCICommandHeader header;
- RegH2DFIS fis;
- unsigned char *atapi_cmd;
-};
-
-/**
- * Allocate space in the guest using information in the AHCIQState object.
- */
-uint64_t ahci_alloc(AHCIQState *ahci, size_t bytes)
-{
- g_assert(ahci);
- g_assert(ahci->parent);
- return qmalloc(ahci->parent, bytes);
-}
-
-void ahci_free(AHCIQState *ahci, uint64_t addr)
-{
- g_assert(ahci);
- g_assert(ahci->parent);
- qfree(ahci->parent, addr);
-}
-
-bool is_atapi(AHCIQState *ahci, uint8_t port)
-{
- return ahci_px_rreg(ahci, port, AHCI_PX_SIG) == AHCI_SIGNATURE_CDROM;
-}
-
-/**
- * Locate, verify, and return a handle to the AHCI device.
- */
-QPCIDevice *get_ahci_device(uint32_t *fingerprint)
-{
- QPCIDevice *ahci;
- uint32_t ahci_fingerprint;
- QPCIBus *pcibus;
-
- pcibus = qpci_init_pc();
-
- /* Find the AHCI PCI device and verify it's the right one. */
- ahci = qpci_device_find(pcibus, QPCI_DEVFN(0x1F, 0x02));
- g_assert(ahci != NULL);
-
- ahci_fingerprint = qpci_config_readl(ahci, PCI_VENDOR_ID);
-
- switch (ahci_fingerprint) {
- case AHCI_INTEL_ICH9:
- break;
- default:
- /* Unknown device. */
- g_assert_not_reached();
- }
-
- if (fingerprint) {
- *fingerprint = ahci_fingerprint;
- }
- return ahci;
-}
-
-void free_ahci_device(QPCIDevice *dev)
-{
- QPCIBus *pcibus = dev ? dev->bus : NULL;
-
- /* libqos doesn't have a function for this, so free it manually */
- g_free(dev);
- qpci_free_pc(pcibus);
-}
-
-/* Free all memory in-use by the AHCI device. */
-void ahci_clean_mem(AHCIQState *ahci)
-{
- uint8_t port, slot;
-
- for (port = 0; port < 32; ++port) {
- if (ahci->port[port].fb) {
- ahci_free(ahci, ahci->port[port].fb);
- ahci->port[port].fb = 0;
- }
- if (ahci->port[port].clb) {
- for (slot = 0; slot < 32; slot++) {
- ahci_destroy_command(ahci, port, slot);
- }
- ahci_free(ahci, ahci->port[port].clb);
- ahci->port[port].clb = 0;
- }
- }
-}
-
-/*** Logical Device Initialization ***/
-
-/**
- * Start the PCI device and sanity-check default operation.
- */
-void ahci_pci_enable(AHCIQState *ahci)
-{
- uint8_t reg;
-
- start_ahci_device(ahci);
-
- switch (ahci->fingerprint) {
- case AHCI_INTEL_ICH9:
- /* ICH9 has a register at PCI 0x92 that
- * acts as a master port enabler mask. */
- reg = qpci_config_readb(ahci->dev, 0x92);
- reg |= 0x3F;
- qpci_config_writeb(ahci->dev, 0x92, reg);
- /* 0...0111111b -- bit significant, ports 0-5 enabled. */
- ASSERT_BIT_SET(qpci_config_readb(ahci->dev, 0x92), 0x3F);
- break;
- }
-
-}
-
-/**
- * Map BAR5/ABAR, and engage the PCI device.
- */
-void start_ahci_device(AHCIQState *ahci)
-{
- /* Map AHCI's ABAR (BAR5) */
- ahci->hba_base = qpci_iomap(ahci->dev, 5, &ahci->barsize);
- g_assert(ahci->hba_base);
-
- /* turns on pci.cmd.iose, pci.cmd.mse and pci.cmd.bme */
- qpci_device_enable(ahci->dev);
-}
-
-/**
- * Test and initialize the AHCI's HBA memory areas.
- * Initialize and start any ports with devices attached.
- * Bring the HBA into the idle state.
- */
-void ahci_hba_enable(AHCIQState *ahci)
-{
- /* Bits of interest in this section:
- * GHC.AE Global Host Control / AHCI Enable
- * PxCMD.ST Port Command: Start
- * PxCMD.SUD "Spin Up Device"
- * PxCMD.POD "Power On Device"
- * PxCMD.FRE "FIS Receive Enable"
- * PxCMD.FR "FIS Receive Running"
- * PxCMD.CR "Command List Running"
- */
- uint32_t reg, ports_impl;
- uint16_t i;
- uint8_t num_cmd_slots;
-
- g_assert(ahci != NULL);
-
- /* Set GHC.AE to 1 */
- ahci_set(ahci, AHCI_GHC, AHCI_GHC_AE);
- reg = ahci_rreg(ahci, AHCI_GHC);
- ASSERT_BIT_SET(reg, AHCI_GHC_AE);
-
- /* Cache CAP and CAP2. */
- ahci->cap = ahci_rreg(ahci, AHCI_CAP);
- ahci->cap2 = ahci_rreg(ahci, AHCI_CAP2);
-
- /* Read CAP.NCS, how many command slots do we have? */
- num_cmd_slots = ((ahci->cap & AHCI_CAP_NCS) >> ctzl(AHCI_CAP_NCS)) + 1;
- g_test_message("Number of Command Slots: %u", num_cmd_slots);
-
- /* Determine which ports are implemented. */
- ports_impl = ahci_rreg(ahci, AHCI_PI);
-
- for (i = 0; ports_impl; ports_impl >>= 1, ++i) {
- if (!(ports_impl & 0x01)) {
- continue;
- }
-
- g_test_message("Initializing port %u", i);
-
- reg = ahci_px_rreg(ahci, i, AHCI_PX_CMD);
- if (BITCLR(reg, AHCI_PX_CMD_ST | AHCI_PX_CMD_CR |
- AHCI_PX_CMD_FRE | AHCI_PX_CMD_FR)) {
- g_test_message("port is idle");
- } else {
- g_test_message("port needs to be idled");
- ahci_px_clr(ahci, i, AHCI_PX_CMD,
- (AHCI_PX_CMD_ST | AHCI_PX_CMD_FRE));
- /* The port has 500ms to disengage. */
- usleep(500000);
- reg = ahci_px_rreg(ahci, i, AHCI_PX_CMD);
- ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_CR);
- ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_FR);
- g_test_message("port is now idle");
- /* The spec does allow for possibly needing a PORT RESET
- * or HBA reset if we fail to idle the port. */
- }
-
- /* Allocate Memory for the Command List Buffer & FIS Buffer */
- /* PxCLB space ... 0x20 per command, as in 4.2.2 p 36 */
- ahci->port[i].clb = ahci_alloc(ahci, num_cmd_slots * 0x20);
- qmemset(ahci->port[i].clb, 0x00, num_cmd_slots * 0x20);
- g_test_message("CLB: 0x%08" PRIx64, ahci->port[i].clb);
- ahci_px_wreg(ahci, i, AHCI_PX_CLB, ahci->port[i].clb);
- g_assert_cmphex(ahci->port[i].clb, ==,
- ahci_px_rreg(ahci, i, AHCI_PX_CLB));
-
- /* PxFB space ... 0x100, as in 4.2.1 p 35 */
- ahci->port[i].fb = ahci_alloc(ahci, 0x100);
- qmemset(ahci->port[i].fb, 0x00, 0x100);
- g_test_message("FB: 0x%08" PRIx64, ahci->port[i].fb);
- ahci_px_wreg(ahci, i, AHCI_PX_FB, ahci->port[i].fb);
- g_assert_cmphex(ahci->port[i].fb, ==,
- ahci_px_rreg(ahci, i, AHCI_PX_FB));
-
- /* Clear PxSERR, PxIS, then IS.IPS[x] by writing '1's. */
- ahci_px_wreg(ahci, i, AHCI_PX_SERR, 0xFFFFFFFF);
- ahci_px_wreg(ahci, i, AHCI_PX_IS, 0xFFFFFFFF);
- ahci_wreg(ahci, AHCI_IS, (1 << i));
-
- /* Verify Interrupts Cleared */
- reg = ahci_px_rreg(ahci, i, AHCI_PX_SERR);
- g_assert_cmphex(reg, ==, 0);
-
- reg = ahci_px_rreg(ahci, i, AHCI_PX_IS);
- g_assert_cmphex(reg, ==, 0);
-
- reg = ahci_rreg(ahci, AHCI_IS);
- ASSERT_BIT_CLEAR(reg, (1 << i));
-
- /* Enable All Interrupts: */
- ahci_px_wreg(ahci, i, AHCI_PX_IE, 0xFFFFFFFF);
- reg = ahci_px_rreg(ahci, i, AHCI_PX_IE);
- g_assert_cmphex(reg, ==, ~((uint32_t)AHCI_PX_IE_RESERVED));
-
- /* Enable the FIS Receive Engine. */
- ahci_px_set(ahci, i, AHCI_PX_CMD, AHCI_PX_CMD_FRE);
- reg = ahci_px_rreg(ahci, i, AHCI_PX_CMD);
- ASSERT_BIT_SET(reg, AHCI_PX_CMD_FR);
-
- /* AHCI 1.3 spec: if !STS.BSY, !STS.DRQ and PxSSTS.DET indicates
- * physical presence, a device is present and may be started. However,
- * PxSERR.DIAG.X /may/ need to be cleared a priori. */
- reg = ahci_px_rreg(ahci, i, AHCI_PX_SERR);
- if (BITSET(reg, AHCI_PX_SERR_DIAG_X)) {
- ahci_px_set(ahci, i, AHCI_PX_SERR, AHCI_PX_SERR_DIAG_X);
- }
-
- reg = ahci_px_rreg(ahci, i, AHCI_PX_TFD);
- if (BITCLR(reg, AHCI_PX_TFD_STS_BSY | AHCI_PX_TFD_STS_DRQ)) {
- reg = ahci_px_rreg(ahci, i, AHCI_PX_SSTS);
- if ((reg & AHCI_PX_SSTS_DET) == SSTS_DET_ESTABLISHED) {
- /* Device Found: set PxCMD.ST := 1 */
- ahci_px_set(ahci, i, AHCI_PX_CMD, AHCI_PX_CMD_ST);
- ASSERT_BIT_SET(ahci_px_rreg(ahci, i, AHCI_PX_CMD),
- AHCI_PX_CMD_CR);
- g_test_message("Started Device %u", i);
- } else if ((reg & AHCI_PX_SSTS_DET)) {
- /* Device present, but in some unknown state. */
- g_assert_not_reached();
- }
- }
- }
-
- /* Enable GHC.IE */
- ahci_set(ahci, AHCI_GHC, AHCI_GHC_IE);
- reg = ahci_rreg(ahci, AHCI_GHC);
- ASSERT_BIT_SET(reg, AHCI_GHC_IE);
-
- /* TODO: The device should now be idling and waiting for commands.
- * In the future, a small test-case to inspect the Register D2H FIS
- * and clear the initial interrupts might be good. */
-}
-
-/**
- * Pick the first implemented and running port
- */
-unsigned ahci_port_select(AHCIQState *ahci)
-{
- uint32_t ports, reg;
- unsigned i;
-
- ports = ahci_rreg(ahci, AHCI_PI);
- for (i = 0; i < 32; ports >>= 1, ++i) {
- if (ports == 0) {
- i = 32;
- }
-
- if (!(ports & 0x01)) {
- continue;
- }
-
- reg = ahci_px_rreg(ahci, i, AHCI_PX_CMD);
- if (BITSET(reg, AHCI_PX_CMD_ST)) {
- break;
- }
- }
- g_assert(i < 32);
- return i;
-}
-
-/**
- * Clear a port's interrupts and status information prior to a test.
- */
-void ahci_port_clear(AHCIQState *ahci, uint8_t port)
-{
- uint32_t reg;
-
- /* Clear out this port's interrupts (ignore the init register d2h fis) */
- reg = ahci_px_rreg(ahci, port, AHCI_PX_IS);
- ahci_px_wreg(ahci, port, AHCI_PX_IS, reg);
- g_assert_cmphex(ahci_px_rreg(ahci, port, AHCI_PX_IS), ==, 0);
-
- /* Wipe the FIS-Receive Buffer */
- qmemset(ahci->port[port].fb, 0x00, 0x100);
-}
-
-/**
- * Check a port for errors.
- */
-void ahci_port_check_error(AHCIQState *ahci, uint8_t port)
-{
- uint32_t reg;
-
- /* The upper 9 bits of the IS register all indicate errors. */
- reg = ahci_px_rreg(ahci, port, AHCI_PX_IS);
- reg >>= 23;
- g_assert_cmphex(reg, ==, 0);
-
- /* The Sata Error Register should be empty. */
- reg = ahci_px_rreg(ahci, port, AHCI_PX_SERR);
- g_assert_cmphex(reg, ==, 0);
-
- /* The TFD also has two error sections. */
- reg = ahci_px_rreg(ahci, port, AHCI_PX_TFD);
- ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_STS_ERR);
- ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_ERR);
-}
-
-void ahci_port_check_interrupts(AHCIQState *ahci, uint8_t port,
- uint32_t intr_mask)
-{
- uint32_t reg;
-
- /* Check for expected interrupts */
- reg = ahci_px_rreg(ahci, port, AHCI_PX_IS);
- ASSERT_BIT_SET(reg, intr_mask);
-
- /* Clear expected interrupts and assert all interrupts now cleared. */
- ahci_px_wreg(ahci, port, AHCI_PX_IS, intr_mask);
- g_assert_cmphex(ahci_px_rreg(ahci, port, AHCI_PX_IS), ==, 0);
-}
-
-void ahci_port_check_nonbusy(AHCIQState *ahci, uint8_t port, uint8_t slot)
-{
- uint32_t reg;
-
- /* Assert that the command slot is no longer busy (NCQ) */
- reg = ahci_px_rreg(ahci, port, AHCI_PX_SACT);
- ASSERT_BIT_CLEAR(reg, (1 << slot));
-
- /* Non-NCQ */
- reg = ahci_px_rreg(ahci, port, AHCI_PX_CI);
- ASSERT_BIT_CLEAR(reg, (1 << slot));
-
- /* And assert that we are generally not busy. */
- reg = ahci_px_rreg(ahci, port, AHCI_PX_TFD);
- ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_STS_BSY);
- ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_STS_DRQ);
-}
-
-void ahci_port_check_d2h_sanity(AHCIQState *ahci, uint8_t port, uint8_t slot)
-{
- RegD2HFIS *d2h = g_malloc0(0x20);
- uint32_t reg;
-
- memread(ahci->port[port].fb + 0x40, d2h, 0x20);
- g_assert_cmphex(d2h->fis_type, ==, 0x34);
-
- reg = ahci_px_rreg(ahci, port, AHCI_PX_TFD);
- g_assert_cmphex((reg & AHCI_PX_TFD_ERR) >> 8, ==, d2h->error);
- g_assert_cmphex((reg & AHCI_PX_TFD_STS), ==, d2h->status);
-
- g_free(d2h);
-}
-
-void ahci_port_check_pio_sanity(AHCIQState *ahci, uint8_t port,
- uint8_t slot, size_t buffsize)
-{
- PIOSetupFIS *pio = g_malloc0(0x20);
-
- /* We cannot check the Status or E_Status registers, because
- * the status may have again changed between the PIO Setup FIS
- * and the conclusion of the command with the D2H Register FIS. */
- memread(ahci->port[port].fb + 0x20, pio, 0x20);
- g_assert_cmphex(pio->fis_type, ==, 0x5f);
-
- /* BUG: PIO Setup FIS as utilized by QEMU tries to fit the entire
- * transfer size in a uint16_t field. The maximum transfer size can
- * eclipse this; the field is meant to convey the size of data per
- * each Data FIS, not the entire operation as a whole. For now,
- * we will sanity check the broken case where applicable. */
- if (buffsize <= UINT16_MAX) {
- g_assert_cmphex(le16_to_cpu(pio->tx_count), ==, buffsize);
- }
-
- g_free(pio);
-}
-
-void ahci_port_check_cmd_sanity(AHCIQState *ahci, AHCICommand *cmd)
-{
- AHCICommandHeader cmdh;
-
- ahci_get_command_header(ahci, cmd->port, cmd->slot, &cmdh);
- /* Physical Region Descriptor Byte Count is not required to work for NCQ. */
- if (!cmd->props->ncq) {
- g_assert_cmphex(cmd->xbytes, ==, cmdh.prdbc);
- }
-}
-
-/* Get the command in #slot of port #port. */
-void ahci_get_command_header(AHCIQState *ahci, uint8_t port,
- uint8_t slot, AHCICommandHeader *cmd)
-{
- uint64_t ba = ahci->port[port].clb;
- ba += slot * sizeof(AHCICommandHeader);
- memread(ba, cmd, sizeof(AHCICommandHeader));
-
- cmd->flags = le16_to_cpu(cmd->flags);
- cmd->prdtl = le16_to_cpu(cmd->prdtl);
- cmd->prdbc = le32_to_cpu(cmd->prdbc);
- cmd->ctba = le64_to_cpu(cmd->ctba);
-}
-
-/* Set the command in #slot of port #port. */
-void ahci_set_command_header(AHCIQState *ahci, uint8_t port,
- uint8_t slot, AHCICommandHeader *cmd)
-{
- AHCICommandHeader tmp = { .flags = 0 };
- uint64_t ba = ahci->port[port].clb;
- ba += slot * sizeof(AHCICommandHeader);
-
- tmp.flags = cpu_to_le16(cmd->flags);
- tmp.prdtl = cpu_to_le16(cmd->prdtl);
- tmp.prdbc = cpu_to_le32(cmd->prdbc);
- tmp.ctba = cpu_to_le64(cmd->ctba);
-
- memwrite(ba, &tmp, sizeof(AHCICommandHeader));
-}
-
-void ahci_destroy_command(AHCIQState *ahci, uint8_t port, uint8_t slot)
-{
- AHCICommandHeader cmd;
-
- /* Obtain the Nth Command Header */
- ahci_get_command_header(ahci, port, slot, &cmd);
- if (cmd.ctba == 0) {
- /* No address in it, so just return -- it's empty. */
- goto tidy;
- }
-
- /* Free the Table */
- ahci_free(ahci, cmd.ctba);
-
- tidy:
- /* NULL the header. */
- memset(&cmd, 0x00, sizeof(cmd));
- ahci_set_command_header(ahci, port, slot, &cmd);
- ahci->port[port].ctba[slot] = 0;
- ahci->port[port].prdtl[slot] = 0;
-}
-
-void ahci_write_fis(AHCIQState *ahci, AHCICommand *cmd)
-{
- RegH2DFIS tmp = cmd->fis;
- uint64_t addr = cmd->header.ctba;
-
- /* NCQ commands use exclusively 8 bit fields and needs no adjustment.
- * Only the count field needs to be adjusted for non-NCQ commands.
- * The auxiliary FIS fields are defined per-command and are not currently
- * implemented in libqos/ahci.o, but may or may not need to be flipped. */
- if (!cmd->props->ncq) {
- tmp.count = cpu_to_le16(tmp.count);
- }
-
- memwrite(addr, &tmp, sizeof(tmp));
-}
-
-unsigned ahci_pick_cmd(AHCIQState *ahci, uint8_t port)
-{
- unsigned i;
- unsigned j;
- uint32_t reg;
-
- reg = ahci_px_rreg(ahci, port, AHCI_PX_CI);
-
- /* Pick the least recently used command slot that's available */
- for (i = 0; i < 32; ++i) {
- j = ((ahci->port[port].next + i) % 32);
- if (reg & (1 << j)) {
- continue;
- }
- ahci_destroy_command(ahci, port, j);
- ahci->port[port].next = (j + 1) % 32;
- return j;
- }
-
- g_test_message("All command slots were busy.");
- g_assert_not_reached();
-}
-
-inline unsigned size_to_prdtl(unsigned bytes, unsigned bytes_per_prd)
-{
- /* Each PRD can describe up to 4MiB */
- g_assert_cmphex(bytes_per_prd, <=, 4096 * 1024);
- g_assert_cmphex(bytes_per_prd & 0x01, ==, 0x00);
- return (bytes + bytes_per_prd - 1) / bytes_per_prd;
-}
-
-const AHCIOpts default_opts = { .size = 0 };
-
-/**
- * ahci_exec: execute a given command on a specific
- * AHCI port.
- *
- * @ahci: The device to send the command to
- * @port: The port number of the SATA device we wish
- * to have execute this command
- * @op: The S/ATA command to execute, or if opts.atapi
- * is true, the SCSI command code.
- * @opts: Optional arguments to modify execution behavior.
- */
-void ahci_exec(AHCIQState *ahci, uint8_t port,
- uint8_t op, const AHCIOpts *opts_in)
-{
- AHCICommand *cmd;
- int rc;
- AHCIOpts *opts;
-
- opts = g_memdup((opts_in == NULL ? &default_opts : opts_in),
- sizeof(AHCIOpts));
-
- /* No guest buffer provided, create one. */
- if (opts->size && !opts->buffer) {
- opts->buffer = ahci_alloc(ahci, opts->size);
- g_assert(opts->buffer);
- qmemset(opts->buffer, 0x00, opts->size);
- }
-
- /* Command creation */
- if (opts->atapi) {
- cmd = ahci_atapi_command_create(op);
- if (opts->atapi_dma) {
- ahci_command_enable_atapi_dma(cmd);
- }
- } else {
- cmd = ahci_command_create(op);
- }
- ahci_command_adjust(cmd, opts->lba, opts->buffer,
- opts->size, opts->prd_size);
-
- if (opts->pre_cb) {
- rc = opts->pre_cb(ahci, cmd, opts);
- g_assert_cmpint(rc, ==, 0);
- }
-
- /* Write command to memory and issue it */
- ahci_command_commit(ahci, cmd, port);
- ahci_command_issue_async(ahci, cmd);
- if (opts->error) {
- qmp_eventwait("STOP");
- }
- if (opts->mid_cb) {
- rc = opts->mid_cb(ahci, cmd, opts);
- g_assert_cmpint(rc, ==, 0);
- }
- if (opts->error) {
- qmp_async("{'execute':'cont' }");
- qmp_eventwait("RESUME");
- }
-
- /* Wait for command to complete and verify sanity */
- ahci_command_wait(ahci, cmd);
- ahci_command_verify(ahci, cmd);
- if (opts->post_cb) {
- rc = opts->post_cb(ahci, cmd, opts);
- g_assert_cmpint(rc, ==, 0);
- }
- ahci_command_free(cmd);
- if (opts->buffer != opts_in->buffer) {
- ahci_free(ahci, opts->buffer);
- }
- g_free(opts);
-}
-
-/* Issue a command, expecting it to fail and STOP the VM */
-AHCICommand *ahci_guest_io_halt(AHCIQState *ahci, uint8_t port,
- uint8_t ide_cmd, uint64_t buffer,
- size_t bufsize, uint64_t sector)
-{
- AHCICommand *cmd;
-
- cmd = ahci_command_create(ide_cmd);
- ahci_command_adjust(cmd, sector, buffer, bufsize, 0);
- ahci_command_commit(ahci, cmd, port);
- ahci_command_issue_async(ahci, cmd);
- qmp_eventwait("STOP");
-
- return cmd;
-}
-
-/* Resume a previously failed command and verify/finalize */
-void ahci_guest_io_resume(AHCIQState *ahci, AHCICommand *cmd)
-{
- /* Complete the command */
- qmp_async("{'execute':'cont' }");
- qmp_eventwait("RESUME");
- ahci_command_wait(ahci, cmd);
- ahci_command_verify(ahci, cmd);
- ahci_command_free(cmd);
-}
-
-/* Given a guest buffer address, perform an IO operation */
-void ahci_guest_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd,
- uint64_t buffer, size_t bufsize, uint64_t sector)
-{
- AHCICommand *cmd;
- cmd = ahci_command_create(ide_cmd);
- ahci_command_set_buffer(cmd, buffer);
- ahci_command_set_size(cmd, bufsize);
- if (sector) {
- ahci_command_set_offset(cmd, sector);
- }
- ahci_command_commit(ahci, cmd, port);
- ahci_command_issue(ahci, cmd);
- ahci_command_verify(ahci, cmd);
- ahci_command_free(cmd);
-}
-
-static AHCICommandProp *ahci_command_find(uint8_t command_name)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ahci_command_properties); i++) {
- if (ahci_command_properties[i].cmd == command_name) {
- return &ahci_command_properties[i];
- }
- }
-
- return NULL;
-}
-
-/* Given a HOST buffer, create a buffer address and perform an IO operation. */
-void ahci_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd,
- void *buffer, size_t bufsize, uint64_t sector)
-{
- uint64_t ptr;
- AHCICommandProp *props;
-
- props = ahci_command_find(ide_cmd);
- g_assert(props);
- ptr = ahci_alloc(ahci, bufsize);
- g_assert(!bufsize || ptr);
- qmemset(ptr, 0x00, bufsize);
-
- if (bufsize && props->write) {
- bufwrite(ptr, buffer, bufsize);
- }
-
- ahci_guest_io(ahci, port, ide_cmd, ptr, bufsize, sector);
-
- if (bufsize && props->read) {
- bufread(ptr, buffer, bufsize);
- }
-
- ahci_free(ahci, ptr);
-}
-
-/**
- * Initializes a basic command header in memory.
- * We assume that this is for an ATA command using RegH2DFIS.
- */
-static void command_header_init(AHCICommand *cmd)
-{
- AHCICommandHeader *hdr = &cmd->header;
- AHCICommandProp *props = cmd->props;
-
- hdr->flags = 5; /* RegH2DFIS is 5 DW long. Must be < 32 */
- hdr->flags |= CMDH_CLR_BSY; /* Clear the BSY bit when done */
- if (props->write) {
- hdr->flags |= CMDH_WRITE;
- }
- if (props->atapi) {
- hdr->flags |= CMDH_ATAPI;
- }
- /* Other flags: PREFETCH, RESET, and BIST */
- hdr->prdtl = size_to_prdtl(cmd->xbytes, cmd->prd_size);
- hdr->prdbc = 0;
- hdr->ctba = 0;
-}
-
-static void command_table_init(AHCICommand *cmd)
-{
- RegH2DFIS *fis = &(cmd->fis);
- uint16_t sect_count = (cmd->xbytes / AHCI_SECTOR_SIZE);
-
- fis->fis_type = REG_H2D_FIS;
- fis->flags = REG_H2D_FIS_CMD; /* "Command" bit */
- fis->command = cmd->name;
-
- if (cmd->props->ncq) {
- NCQFIS *ncqfis = (NCQFIS *)fis;
- /* NCQ is weird and re-uses FIS frames for unrelated data.
- * See SATA 3.2, 13.6.4.1 READ FPDMA QUEUED for an example. */
- ncqfis->sector_low = sect_count & 0xFF;
- ncqfis->sector_hi = (sect_count >> 8) & 0xFF;
- ncqfis->device = NCQ_DEVICE_MAGIC;
- /* Force Unit Access is bit 7 in the device register */
- ncqfis->tag = 0; /* bits 3-7 are the NCQ tag */
- ncqfis->prio = 0; /* bits 6,7 are a prio tag */
- /* RARC bit is bit 0 of TAG field */
- } else {
- fis->feature_low = 0x00;
- fis->feature_high = 0x00;
- if (cmd->props->lba28 || cmd->props->lba48) {
- fis->device = ATA_DEVICE_LBA;
- }
- fis->count = (cmd->xbytes / AHCI_SECTOR_SIZE);
- }
- fis->icc = 0x00;
- fis->control = 0x00;
- memset(fis->aux, 0x00, ARRAY_SIZE(fis->aux));
-}
-
-void ahci_command_enable_atapi_dma(AHCICommand *cmd)
-{
- RegH2DFIS *fis = &(cmd->fis);
- g_assert(cmd->props->atapi);
- fis->feature_low |= 0x01;
- cmd->interrupts &= ~AHCI_PX_IS_PSS;
- cmd->props->dma = true;
- cmd->props->pio = false;
- /* BUG: We expect the DMA Setup interrupt for DMA commands */
- /* cmd->interrupts |= AHCI_PX_IS_DSS; */
-}
-
-AHCICommand *ahci_command_create(uint8_t command_name)
-{
- AHCICommandProp *props = ahci_command_find(command_name);
- AHCICommand *cmd;
-
- g_assert(props);
- cmd = g_malloc0(sizeof(AHCICommand));
- g_assert(!(props->dma && props->pio));
- g_assert(!(props->lba28 && props->lba48));
- g_assert(!(props->read && props->write));
- g_assert(!props->size || props->data);
- g_assert(!props->ncq || props->lba48);
-
- /* Defaults and book-keeping */
- cmd->props = g_memdup(props, sizeof(AHCICommandProp));
- cmd->name = command_name;
- cmd->xbytes = props->size;
- cmd->prd_size = 4096;
- cmd->buffer = 0xabad1dea;
-
- if (!cmd->props->ncq) {
- cmd->interrupts = AHCI_PX_IS_DHRS;
- }
- /* BUG: We expect the DPS interrupt for data commands */
- /* cmd->interrupts |= props->data ? AHCI_PX_IS_DPS : 0; */
- /* BUG: We expect the DMA Setup interrupt for DMA commands */
- /* cmd->interrupts |= props->dma ? AHCI_PX_IS_DSS : 0; */
- cmd->interrupts |= props->pio ? AHCI_PX_IS_PSS : 0;
- cmd->interrupts |= props->ncq ? AHCI_PX_IS_SDBS : 0;
-
- command_header_init(cmd);
- command_table_init(cmd);
-
- return cmd;
-}
-
-AHCICommand *ahci_atapi_command_create(uint8_t scsi_cmd)
-{
- AHCICommand *cmd = ahci_command_create(CMD_PACKET);
- cmd->atapi_cmd = g_malloc0(16);
- cmd->atapi_cmd[0] = scsi_cmd;
- /* ATAPI needs a PIO transfer chunk size set inside of the LBA registers.
- * The block/sector size is a natural default. */
- cmd->fis.lba_lo[1] = ATAPI_SECTOR_SIZE >> 8 & 0xFF;
- cmd->fis.lba_lo[2] = ATAPI_SECTOR_SIZE & 0xFF;
-
- return cmd;
-}
-
-void ahci_command_free(AHCICommand *cmd)
-{
- g_free(cmd->atapi_cmd);
- g_free(cmd->props);
- g_free(cmd);
-}
-
-void ahci_command_set_flags(AHCICommand *cmd, uint16_t cmdh_flags)
-{
- cmd->header.flags |= cmdh_flags;
-}
-
-void ahci_command_clr_flags(AHCICommand *cmd, uint16_t cmdh_flags)
-{
- cmd->header.flags &= ~cmdh_flags;
-}
-
-static void ahci_atapi_command_set_offset(AHCICommand *cmd, uint64_t lba)
-{
- unsigned char *cbd = cmd->atapi_cmd;
- g_assert(cbd);
-
- switch (cbd[0]) {
- case CMD_ATAPI_READ_10:
- g_assert_cmpuint(lba, <=, UINT32_MAX);
- stl_be_p(&cbd[2], lba);
- break;
- default:
- /* SCSI doesn't have uniform packet formats,
- * so you have to add support for it manually. Sorry! */
- g_assert_not_reached();
- }
-}
-
-void ahci_command_set_offset(AHCICommand *cmd, uint64_t lba_sect)
-{
- RegH2DFIS *fis = &(cmd->fis);
-
- if (cmd->props->atapi) {
- ahci_atapi_command_set_offset(cmd, lba_sect);
- return;
- } else if (!cmd->props->data && !lba_sect) {
- /* Not meaningful, ignore. */
- return;
- } else if (cmd->props->lba28) {
- g_assert_cmphex(lba_sect, <=, 0xFFFFFFF);
- } else if (cmd->props->lba48 || cmd->props->ncq) {
- g_assert_cmphex(lba_sect, <=, 0xFFFFFFFFFFFF);
- } else {
- /* Can't set offset if we don't know the format. */
- g_assert_not_reached();
- }
-
- /* LBA28 uses the low nibble of the device/control register for LBA24:27 */
- fis->lba_lo[0] = (lba_sect & 0xFF);
- fis->lba_lo[1] = (lba_sect >> 8) & 0xFF;
- fis->lba_lo[2] = (lba_sect >> 16) & 0xFF;
- if (cmd->props->lba28) {
- fis->device = (fis->device & 0xF0) | ((lba_sect >> 24) & 0x0F);
- }
- fis->lba_hi[0] = (lba_sect >> 24) & 0xFF;
- fis->lba_hi[1] = (lba_sect >> 32) & 0xFF;
- fis->lba_hi[2] = (lba_sect >> 40) & 0xFF;
-}
-
-void ahci_command_set_buffer(AHCICommand *cmd, uint64_t buffer)
-{
- cmd->buffer = buffer;
-}
-
-static void ahci_atapi_set_size(AHCICommand *cmd, uint64_t xbytes)
-{
- unsigned char *cbd = cmd->atapi_cmd;
- uint64_t nsectors = xbytes / 2048;
- g_assert(cbd);
-
- switch (cbd[0]) {
- case CMD_ATAPI_READ_10:
- g_assert_cmpuint(nsectors, <=, UINT16_MAX);
- stw_be_p(&cbd[7], nsectors);
- break;
- default:
- /* SCSI doesn't have uniform packet formats,
- * so you have to add support for it manually. Sorry! */
- g_assert_not_reached();
- }
-}
-
-void ahci_command_set_sizes(AHCICommand *cmd, uint64_t xbytes,
- unsigned prd_size)
-{
- uint16_t sect_count;
-
- /* Each PRD can describe up to 4MiB, and must not be odd. */
- g_assert_cmphex(prd_size, <=, 4096 * 1024);
- g_assert_cmphex(prd_size & 0x01, ==, 0x00);
- if (prd_size) {
- cmd->prd_size = prd_size;
- }
- cmd->xbytes = xbytes;
- sect_count = (cmd->xbytes / AHCI_SECTOR_SIZE);
-
- if (cmd->props->ncq) {
- NCQFIS *nfis = (NCQFIS *)&(cmd->fis);
- nfis->sector_low = sect_count & 0xFF;
- nfis->sector_hi = (sect_count >> 8) & 0xFF;
- } else if (cmd->props->atapi) {
- ahci_atapi_set_size(cmd, xbytes);
- } else {
- cmd->fis.count = sect_count;
- }
- cmd->header.prdtl = size_to_prdtl(cmd->xbytes, cmd->prd_size);
-}
-
-void ahci_command_set_size(AHCICommand *cmd, uint64_t xbytes)
-{
- ahci_command_set_sizes(cmd, xbytes, cmd->prd_size);
-}
-
-void ahci_command_set_prd_size(AHCICommand *cmd, unsigned prd_size)
-{
- ahci_command_set_sizes(cmd, cmd->xbytes, prd_size);
-}
-
-void ahci_command_adjust(AHCICommand *cmd, uint64_t offset, uint64_t buffer,
- uint64_t xbytes, unsigned prd_size)
-{
- ahci_command_set_sizes(cmd, xbytes, prd_size);
- ahci_command_set_buffer(cmd, buffer);
- ahci_command_set_offset(cmd, offset);
-}
-
-void ahci_command_commit(AHCIQState *ahci, AHCICommand *cmd, uint8_t port)
-{
- uint16_t i, prdtl;
- uint64_t table_size, table_ptr, remaining;
- PRD prd;
-
- /* This command is now tied to this port/command slot */
- cmd->port = port;
- cmd->slot = ahci_pick_cmd(ahci, port);
-
- if (cmd->props->ncq) {
- NCQFIS *nfis = (NCQFIS *)&cmd->fis;
- nfis->tag = (cmd->slot << 3) & 0xFC;
- }
-
- /* Create a buffer for the command table */
- prdtl = size_to_prdtl(cmd->xbytes, cmd->prd_size);
- table_size = CMD_TBL_SIZ(prdtl);
- table_ptr = ahci_alloc(ahci, table_size);
- g_assert(table_ptr);
- /* AHCI 1.3: Must be aligned to 0x80 */
- g_assert((table_ptr & 0x7F) == 0x00);
- cmd->header.ctba = table_ptr;
-
- /* Commit the command header (part of the Command List Buffer) */
- ahci_set_command_header(ahci, port, cmd->slot, &(cmd->header));
- /* Now, write the command table (FIS, ACMD, and PRDT) -- FIS first, */
- ahci_write_fis(ahci, cmd);
- /* Then ATAPI CMD, if needed */
- if (cmd->props->atapi) {
- memwrite(table_ptr + 0x40, cmd->atapi_cmd, 16);
- }
-
- /* Construct and write the PRDs to the command table */
- g_assert_cmphex(prdtl, ==, cmd->header.prdtl);
- remaining = cmd->xbytes;
- for (i = 0; i < prdtl; ++i) {
- prd.dba = cpu_to_le64(cmd->buffer + (cmd->prd_size * i));
- prd.res = 0;
- if (remaining > cmd->prd_size) {
- /* Note that byte count is 0-based. */
- prd.dbc = cpu_to_le32(cmd->prd_size - 1);
- remaining -= cmd->prd_size;
- } else {
- /* Again, dbc is 0-based. */
- prd.dbc = cpu_to_le32(remaining - 1);
- remaining = 0;
- }
- prd.dbc |= cpu_to_le32(0x80000000); /* Request DPS Interrupt */
-
- /* Commit the PRD entry to the Command Table */
- memwrite(table_ptr + 0x80 + (i * sizeof(PRD)),
- &prd, sizeof(PRD));
- }
-
- /* Bookmark the PRDTL and CTBA values */
- ahci->port[port].ctba[cmd->slot] = table_ptr;
- ahci->port[port].prdtl[cmd->slot] = prdtl;
-}
-
-void ahci_command_issue_async(AHCIQState *ahci, AHCICommand *cmd)
-{
- if (cmd->props->ncq) {
- ahci_px_wreg(ahci, cmd->port, AHCI_PX_SACT, (1 << cmd->slot));
- }
-
- ahci_px_wreg(ahci, cmd->port, AHCI_PX_CI, (1 << cmd->slot));
-}
-
-void ahci_command_wait(AHCIQState *ahci, AHCICommand *cmd)
-{
- /* We can't rely on STS_BSY until the command has started processing.
- * Therefore, we also use the Command Issue bit as indication of
- * a command in-flight. */
-
-#define RSET(REG, MASK) (BITSET(ahci_px_rreg(ahci, cmd->port, (REG)), (MASK)))
-
- while (RSET(AHCI_PX_TFD, AHCI_PX_TFD_STS_BSY) ||
- RSET(AHCI_PX_CI, 1 << cmd->slot) ||
- (cmd->props->ncq && RSET(AHCI_PX_SACT, 1 << cmd->slot))) {
- usleep(50);
- }
-
-}
-
-void ahci_command_issue(AHCIQState *ahci, AHCICommand *cmd)
-{
- ahci_command_issue_async(ahci, cmd);
- ahci_command_wait(ahci, cmd);
-}
-
-void ahci_command_verify(AHCIQState *ahci, AHCICommand *cmd)
-{
- uint8_t slot = cmd->slot;
- uint8_t port = cmd->port;
-
- ahci_port_check_error(ahci, port);
- ahci_port_check_interrupts(ahci, port, cmd->interrupts);
- ahci_port_check_nonbusy(ahci, port, slot);
- ahci_port_check_cmd_sanity(ahci, cmd);
- if (cmd->interrupts & AHCI_PX_IS_DHRS) {
- ahci_port_check_d2h_sanity(ahci, port, slot);
- }
- if (cmd->props->pio) {
- ahci_port_check_pio_sanity(ahci, port, slot, cmd->xbytes);
- }
-}
-
-uint8_t ahci_command_slot(AHCICommand *cmd)
-{
- return cmd->slot;
-}
diff --git a/qemu/tests/libqos/ahci.h b/qemu/tests/libqos/ahci.h
deleted file mode 100644
index 71dd7a6e5..000000000
--- a/qemu/tests/libqos/ahci.h
+++ /dev/null
@@ -1,627 +0,0 @@
-#ifndef __libqos_ahci_h
-#define __libqos_ahci_h
-
-/*
- * AHCI qtest library functions and definitions
- *
- * Copyright (c) 2014 John Snow <jsnow@redhat.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 "libqos/libqos.h"
-#include "libqos/pci.h"
-#include "libqos/malloc-pc.h"
-
-/*** Supplementary PCI Config Space IDs & Masks ***/
-#define PCI_DEVICE_ID_INTEL_Q35_AHCI (0x2922)
-#define PCI_MSI_FLAGS_RESERVED (0xFF00)
-#define PCI_PM_CTRL_RESERVED (0xFC)
-#define PCI_BCC(REG32) ((REG32) >> 24)
-#define PCI_PI(REG32) (((REG32) >> 8) & 0xFF)
-#define PCI_SCC(REG32) (((REG32) >> 16) & 0xFF)
-
-/*** Recognized AHCI Device Types ***/
-#define AHCI_INTEL_ICH9 (PCI_DEVICE_ID_INTEL_Q35_AHCI << 16 | \
- PCI_VENDOR_ID_INTEL)
-
-/*** AHCI/HBA Register Offsets and Bitmasks ***/
-#define AHCI_CAP (0)
-#define AHCI_CAP_NP (0x1F)
-#define AHCI_CAP_SXS (0x20)
-#define AHCI_CAP_EMS (0x40)
-#define AHCI_CAP_CCCS (0x80)
-#define AHCI_CAP_NCS (0x1F00)
-#define AHCI_CAP_PSC (0x2000)
-#define AHCI_CAP_SSC (0x4000)
-#define AHCI_CAP_PMD (0x8000)
-#define AHCI_CAP_FBSS (0x10000)
-#define AHCI_CAP_SPM (0x20000)
-#define AHCI_CAP_SAM (0x40000)
-#define AHCI_CAP_RESERVED (0x80000)
-#define AHCI_CAP_ISS (0xF00000)
-#define AHCI_CAP_SCLO (0x1000000)
-#define AHCI_CAP_SAL (0x2000000)
-#define AHCI_CAP_SALP (0x4000000)
-#define AHCI_CAP_SSS (0x8000000)
-#define AHCI_CAP_SMPS (0x10000000)
-#define AHCI_CAP_SSNTF (0x20000000)
-#define AHCI_CAP_SNCQ (0x40000000)
-#define AHCI_CAP_S64A (0x80000000)
-
-#define AHCI_GHC (1)
-#define AHCI_GHC_HR (0x01)
-#define AHCI_GHC_IE (0x02)
-#define AHCI_GHC_MRSM (0x04)
-#define AHCI_GHC_RESERVED (0x7FFFFFF8)
-#define AHCI_GHC_AE (0x80000000)
-
-#define AHCI_IS (2)
-#define AHCI_PI (3)
-#define AHCI_VS (4)
-
-#define AHCI_CCCCTL (5)
-#define AHCI_CCCCTL_EN (0x01)
-#define AHCI_CCCCTL_RESERVED (0x06)
-#define AHCI_CCCCTL_CC (0xFF00)
-#define AHCI_CCCCTL_TV (0xFFFF0000)
-
-#define AHCI_CCCPORTS (6)
-#define AHCI_EMLOC (7)
-
-#define AHCI_EMCTL (8)
-#define AHCI_EMCTL_STSMR (0x01)
-#define AHCI_EMCTL_CTLTM (0x100)
-#define AHCI_EMCTL_CTLRST (0x200)
-#define AHCI_EMCTL_RESERVED (0xF0F0FCFE)
-
-#define AHCI_CAP2 (9)
-#define AHCI_CAP2_BOH (0x01)
-#define AHCI_CAP2_NVMP (0x02)
-#define AHCI_CAP2_APST (0x04)
-#define AHCI_CAP2_RESERVED (0xFFFFFFF8)
-
-#define AHCI_BOHC (10)
-#define AHCI_RESERVED (11)
-#define AHCI_NVMHCI (24)
-#define AHCI_VENDOR (40)
-#define AHCI_PORTS (64)
-
-/*** Port Memory Offsets & Bitmasks ***/
-#define AHCI_PX_CLB (0)
-#define AHCI_PX_CLB_RESERVED (0x1FF)
-
-#define AHCI_PX_CLBU (1)
-
-#define AHCI_PX_FB (2)
-#define AHCI_PX_FB_RESERVED (0xFF)
-
-#define AHCI_PX_FBU (3)
-
-#define AHCI_PX_IS (4)
-#define AHCI_PX_IS_DHRS (0x1)
-#define AHCI_PX_IS_PSS (0x2)
-#define AHCI_PX_IS_DSS (0x4)
-#define AHCI_PX_IS_SDBS (0x8)
-#define AHCI_PX_IS_UFS (0x10)
-#define AHCI_PX_IS_DPS (0x20)
-#define AHCI_PX_IS_PCS (0x40)
-#define AHCI_PX_IS_DMPS (0x80)
-#define AHCI_PX_IS_RESERVED (0x23FFF00)
-#define AHCI_PX_IS_PRCS (0x400000)
-#define AHCI_PX_IS_IPMS (0x800000)
-#define AHCI_PX_IS_OFS (0x1000000)
-#define AHCI_PX_IS_INFS (0x4000000)
-#define AHCI_PX_IS_IFS (0x8000000)
-#define AHCI_PX_IS_HBDS (0x10000000)
-#define AHCI_PX_IS_HBFS (0x20000000)
-#define AHCI_PX_IS_TFES (0x40000000)
-#define AHCI_PX_IS_CPDS (0x80000000)
-
-#define AHCI_PX_IE (5)
-#define AHCI_PX_IE_DHRE (0x1)
-#define AHCI_PX_IE_PSE (0x2)
-#define AHCI_PX_IE_DSE (0x4)
-#define AHCI_PX_IE_SDBE (0x8)
-#define AHCI_PX_IE_UFE (0x10)
-#define AHCI_PX_IE_DPE (0x20)
-#define AHCI_PX_IE_PCE (0x40)
-#define AHCI_PX_IE_DMPE (0x80)
-#define AHCI_PX_IE_RESERVED (0x23FFF00)
-#define AHCI_PX_IE_PRCE (0x400000)
-#define AHCI_PX_IE_IPME (0x800000)
-#define AHCI_PX_IE_OFE (0x1000000)
-#define AHCI_PX_IE_INFE (0x4000000)
-#define AHCI_PX_IE_IFE (0x8000000)
-#define AHCI_PX_IE_HBDE (0x10000000)
-#define AHCI_PX_IE_HBFE (0x20000000)
-#define AHCI_PX_IE_TFEE (0x40000000)
-#define AHCI_PX_IE_CPDE (0x80000000)
-
-#define AHCI_PX_CMD (6)
-#define AHCI_PX_CMD_ST (0x1)
-#define AHCI_PX_CMD_SUD (0x2)
-#define AHCI_PX_CMD_POD (0x4)
-#define AHCI_PX_CMD_CLO (0x8)
-#define AHCI_PX_CMD_FRE (0x10)
-#define AHCI_PX_CMD_RESERVED (0xE0)
-#define AHCI_PX_CMD_CCS (0x1F00)
-#define AHCI_PX_CMD_MPSS (0x2000)
-#define AHCI_PX_CMD_FR (0x4000)
-#define AHCI_PX_CMD_CR (0x8000)
-#define AHCI_PX_CMD_CPS (0x10000)
-#define AHCI_PX_CMD_PMA (0x20000)
-#define AHCI_PX_CMD_HPCP (0x40000)
-#define AHCI_PX_CMD_MPSP (0x80000)
-#define AHCI_PX_CMD_CPD (0x100000)
-#define AHCI_PX_CMD_ESP (0x200000)
-#define AHCI_PX_CMD_FBSCP (0x400000)
-#define AHCI_PX_CMD_APSTE (0x800000)
-#define AHCI_PX_CMD_ATAPI (0x1000000)
-#define AHCI_PX_CMD_DLAE (0x2000000)
-#define AHCI_PX_CMD_ALPE (0x4000000)
-#define AHCI_PX_CMD_ASP (0x8000000)
-#define AHCI_PX_CMD_ICC (0xF0000000)
-
-#define AHCI_PX_RES1 (7)
-
-#define AHCI_PX_TFD (8)
-#define AHCI_PX_TFD_STS (0xFF)
-#define AHCI_PX_TFD_STS_ERR (0x01)
-#define AHCI_PX_TFD_STS_CS1 (0x06)
-#define AHCI_PX_TFD_STS_DRQ (0x08)
-#define AHCI_PX_TFD_STS_CS2 (0x70)
-#define AHCI_PX_TFD_STS_BSY (0x80)
-#define AHCI_PX_TFD_ERR (0xFF00)
-#define AHCI_PX_TFD_RESERVED (0xFFFF0000)
-
-#define AHCI_PX_SIG (9)
-#define AHCI_PX_SIG_SECTOR_COUNT (0xFF)
-#define AHCI_PX_SIG_LBA_LOW (0xFF00)
-#define AHCI_PX_SIG_LBA_MID (0xFF0000)
-#define AHCI_PX_SIG_LBA_HIGH (0xFF000000)
-
-#define AHCI_PX_SSTS (10)
-#define AHCI_PX_SSTS_DET (0x0F)
-#define AHCI_PX_SSTS_SPD (0xF0)
-#define AHCI_PX_SSTS_IPM (0xF00)
-#define AHCI_PX_SSTS_RESERVED (0xFFFFF000)
-#define SSTS_DET_NO_DEVICE (0x00)
-#define SSTS_DET_PRESENT (0x01)
-#define SSTS_DET_ESTABLISHED (0x03)
-#define SSTS_DET_OFFLINE (0x04)
-
-#define AHCI_PX_SCTL (11)
-
-#define AHCI_PX_SERR (12)
-#define AHCI_PX_SERR_ERR (0xFFFF)
-#define AHCI_PX_SERR_DIAG (0xFFFF0000)
-#define AHCI_PX_SERR_DIAG_X (0x04000000)
-
-#define AHCI_PX_SACT (13)
-#define AHCI_PX_CI (14)
-#define AHCI_PX_SNTF (15)
-
-#define AHCI_PX_FBS (16)
-#define AHCI_PX_FBS_EN (0x1)
-#define AHCI_PX_FBS_DEC (0x2)
-#define AHCI_PX_FBS_SDE (0x4)
-#define AHCI_PX_FBS_DEV (0xF00)
-#define AHCI_PX_FBS_ADO (0xF000)
-#define AHCI_PX_FBS_DWE (0xF0000)
-#define AHCI_PX_FBS_RESERVED (0xFFF000F8)
-
-#define AHCI_PX_RES2 (17)
-#define AHCI_PX_VS (28)
-
-#define HBA_DATA_REGION_SIZE (256)
-#define HBA_PORT_DATA_SIZE (128)
-#define HBA_PORT_NUM_REG (HBA_PORT_DATA_SIZE/4)
-
-#define AHCI_VERSION_0_95 (0x00000905)
-#define AHCI_VERSION_1_0 (0x00010000)
-#define AHCI_VERSION_1_1 (0x00010100)
-#define AHCI_VERSION_1_2 (0x00010200)
-#define AHCI_VERSION_1_3 (0x00010300)
-
-#define AHCI_SECTOR_SIZE (512)
-#define ATAPI_SECTOR_SIZE (2048)
-
-#define AHCI_SIGNATURE_CDROM (0xeb140101)
-#define AHCI_SIGNATURE_DISK (0x00000101)
-
-/* FIS types */
-enum {
- REG_H2D_FIS = 0x27,
- REG_D2H_FIS = 0x34,
- DMA_ACTIVATE_FIS = 0x39,
- DMA_SETUP_FIS = 0x41,
- DATA_FIS = 0x46,
- BIST_ACTIVATE_FIS = 0x58,
- PIO_SETUP_FIS = 0x5F,
- SDB_FIS = 0xA1
-};
-
-/* FIS flags */
-#define REG_H2D_FIS_CMD 0x80
-
-/* ATA Commands */
-enum {
- /* DMA */
- CMD_READ_DMA = 0xC8,
- CMD_READ_DMA_EXT = 0x25,
- CMD_WRITE_DMA = 0xCA,
- CMD_WRITE_DMA_EXT = 0x35,
- /* PIO */
- CMD_READ_PIO = 0x20,
- CMD_READ_PIO_EXT = 0x24,
- CMD_WRITE_PIO = 0x30,
- CMD_WRITE_PIO_EXT = 0x34,
- /* Misc */
- CMD_READ_MAX = 0xF8,
- CMD_READ_MAX_EXT = 0x27,
- CMD_FLUSH_CACHE = 0xE7,
- CMD_IDENTIFY = 0xEC,
- CMD_PACKET = 0xA0,
- CMD_PACKET_ID = 0xA1,
- /* NCQ */
- READ_FPDMA_QUEUED = 0x60,
- WRITE_FPDMA_QUEUED = 0x61,
-};
-
-/* ATAPI Commands */
-enum {
- CMD_ATAPI_READ_10 = 0x28,
-};
-
-/* AHCI Command Header Flags & Masks*/
-#define CMDH_CFL (0x1F)
-#define CMDH_ATAPI (0x20)
-#define CMDH_WRITE (0x40)
-#define CMDH_PREFETCH (0x80)
-#define CMDH_RESET (0x100)
-#define CMDH_BIST (0x200)
-#define CMDH_CLR_BSY (0x400)
-#define CMDH_RES (0x800)
-#define CMDH_PMP (0xF000)
-
-/* ATA device register masks */
-#define ATA_DEVICE_MAGIC 0xA0 /* used in ata1-3 */
-#define ATA_DEVICE_LBA 0x40
-#define NCQ_DEVICE_MAGIC 0x40 /* for ncq device registers */
-#define ATA_DEVICE_DRIVE 0x10
-#define ATA_DEVICE_HEAD 0x0F
-
-/*** Structures ***/
-
-typedef struct AHCIPortQState {
- uint64_t fb;
- uint64_t clb;
- uint64_t ctba[32];
- uint16_t prdtl[32];
- uint8_t next; /** Next Command Slot to Use **/
-} AHCIPortQState;
-
-typedef struct AHCIQState {
- QOSState *parent;
- QPCIDevice *dev;
- void *hba_base;
- uint64_t barsize;
- uint32_t fingerprint;
- uint32_t cap;
- uint32_t cap2;
- AHCIPortQState port[32];
-} AHCIQState;
-
-/**
- * Generic FIS structure.
- */
-typedef struct FIS {
- uint8_t fis_type;
- uint8_t flags;
- char data[0];
-} __attribute__((__packed__)) FIS;
-
-/**
- * Register device-to-host FIS structure.
- */
-typedef struct RegD2HFIS {
- /* DW0 */
- uint8_t fis_type;
- uint8_t flags;
- uint8_t status;
- uint8_t error;
- /* DW1 */
- uint8_t lba_lo[3];
- uint8_t device;
- /* DW2 */
- uint8_t lba_hi[3];
- uint8_t res0;
- /* DW3 */
- uint16_t count;
- uint16_t res1;
- /* DW4 */
- uint32_t res2;
-} __attribute__((__packed__)) RegD2HFIS;
-
-/**
- * Register device-to-host FIS structure;
- * PIO Setup variety.
- */
-typedef struct PIOSetupFIS {
- /* DW0 */
- uint8_t fis_type;
- uint8_t flags;
- uint8_t status;
- uint8_t error;
- /* DW1 */
- uint8_t lba_lo[3];
- uint8_t device;
- /* DW2 */
- uint8_t lba_hi[3];
- uint8_t res0;
- /* DW3 */
- uint16_t count;
- uint8_t res1;
- uint8_t e_status;
- /* DW4 */
- uint16_t tx_count;
- uint16_t res2;
-} __attribute__((__packed__)) PIOSetupFIS;
-
-/**
- * Register host-to-device FIS structure.
- */
-typedef struct RegH2DFIS {
- /* DW0 */
- uint8_t fis_type;
- uint8_t flags;
- uint8_t command;
- uint8_t feature_low;
- /* DW1 */
- uint8_t lba_lo[3];
- uint8_t device;
- /* DW2 */
- uint8_t lba_hi[3];
- uint8_t feature_high;
- /* DW3 */
- uint16_t count;
- uint8_t icc;
- uint8_t control;
- /* DW4 */
- uint8_t aux[4];
-} __attribute__((__packed__)) RegH2DFIS;
-
-/**
- * Register host-to-device FIS structure, for NCQ commands.
- * Actually just a RegH2DFIS, but with fields repurposed.
- * Repurposed fields are annotated below.
- */
-typedef struct NCQFIS {
- /* DW0 */
- uint8_t fis_type;
- uint8_t flags;
- uint8_t command;
- uint8_t sector_low; /* H2D: Feature 7:0 */
- /* DW1 */
- uint8_t lba_lo[3];
- uint8_t device;
- /* DW2 */
- uint8_t lba_hi[3];
- uint8_t sector_hi; /* H2D: Feature 15:8 */
- /* DW3 */
- uint8_t tag; /* H2D: Count 0:7 */
- uint8_t prio; /* H2D: Count 15:8 */
- uint8_t icc;
- uint8_t control;
- /* DW4 */
- uint8_t aux[4];
-} __attribute__((__packed__)) NCQFIS;
-
-/**
- * Command List entry structure.
- * The command list contains between 1-32 of these structures.
- */
-typedef struct AHCICommandHeader {
- uint16_t flags; /* Cmd-Fis-Len, PMP#, and flags. */
- uint16_t prdtl; /* Phys Region Desc. Table Length */
- uint32_t prdbc; /* Phys Region Desc. Byte Count */
- uint64_t ctba; /* Command Table Descriptor Base Address */
- uint32_t res[4];
-} __attribute__((__packed__)) AHCICommandHeader;
-
-/**
- * Physical Region Descriptor; pointed to by the Command List Header,
- * struct ahci_command.
- */
-typedef struct PRD {
- uint64_t dba; /* Data Base Address */
- uint32_t res; /* Reserved */
- uint32_t dbc; /* Data Byte Count (0-indexed) & Interrupt Flag (bit 2^31) */
-} __attribute__((__packed__)) PRD;
-
-/* Opaque, defined within ahci.c */
-typedef struct AHCICommand AHCICommand;
-
-/* Options to ahci_exec */
-typedef struct AHCIOpts {
- size_t size;
- unsigned prd_size;
- uint64_t lba;
- uint64_t buffer;
- bool atapi;
- bool atapi_dma;
- bool error;
- int (*pre_cb)(AHCIQState*, AHCICommand*, const struct AHCIOpts *);
- int (*mid_cb)(AHCIQState*, AHCICommand*, const struct AHCIOpts *);
- int (*post_cb)(AHCIQState*, AHCICommand*, const struct AHCIOpts *);
- void *opaque;
-} AHCIOpts;
-
-/*** Macro Utilities ***/
-#define BITANY(data, mask) (((data) & (mask)) != 0)
-#define BITSET(data, mask) (((data) & (mask)) == (mask))
-#define BITCLR(data, mask) (((data) & (mask)) == 0)
-#define ASSERT_BIT_SET(data, mask) g_assert_cmphex((data) & (mask), ==, (mask))
-#define ASSERT_BIT_CLEAR(data, mask) g_assert_cmphex((data) & (mask), ==, 0)
-
-/* For calculating how big the PRD table needs to be: */
-#define CMD_TBL_SIZ(n) ((0x80 + ((n) * sizeof(PRD)) + 0x7F) & ~0x7F)
-
-/* Helpers for reading/writing AHCI HBA register values */
-
-static inline uint32_t ahci_mread(AHCIQState *ahci, size_t offset)
-{
- return qpci_io_readl(ahci->dev, ahci->hba_base + offset);
-}
-
-static inline void ahci_mwrite(AHCIQState *ahci, size_t offset, uint32_t value)
-{
- qpci_io_writel(ahci->dev, ahci->hba_base + offset, value);
-}
-
-static inline uint32_t ahci_rreg(AHCIQState *ahci, uint32_t reg_num)
-{
- return ahci_mread(ahci, 4 * reg_num);
-}
-
-static inline void ahci_wreg(AHCIQState *ahci, uint32_t reg_num, uint32_t value)
-{
- ahci_mwrite(ahci, 4 * reg_num, value);
-}
-
-static inline void ahci_set(AHCIQState *ahci, uint32_t reg_num, uint32_t mask)
-{
- ahci_wreg(ahci, reg_num, ahci_rreg(ahci, reg_num) | mask);
-}
-
-static inline void ahci_clr(AHCIQState *ahci, uint32_t reg_num, uint32_t mask)
-{
- ahci_wreg(ahci, reg_num, ahci_rreg(ahci, reg_num) & ~mask);
-}
-
-static inline size_t ahci_px_offset(uint8_t port, uint32_t reg_num)
-{
- return AHCI_PORTS + (HBA_PORT_NUM_REG * port) + reg_num;
-}
-
-static inline uint32_t ahci_px_rreg(AHCIQState *ahci, uint8_t port,
- uint32_t reg_num)
-{
- return ahci_rreg(ahci, ahci_px_offset(port, reg_num));
-}
-
-static inline void ahci_px_wreg(AHCIQState *ahci, uint8_t port,
- uint32_t reg_num, uint32_t value)
-{
- ahci_wreg(ahci, ahci_px_offset(port, reg_num), value);
-}
-
-static inline void ahci_px_set(AHCIQState *ahci, uint8_t port,
- uint32_t reg_num, uint32_t mask)
-{
- ahci_px_wreg(ahci, port, reg_num,
- ahci_px_rreg(ahci, port, reg_num) | mask);
-}
-
-static inline void ahci_px_clr(AHCIQState *ahci, uint8_t port,
- uint32_t reg_num, uint32_t mask)
-{
- ahci_px_wreg(ahci, port, reg_num,
- ahci_px_rreg(ahci, port, reg_num) & ~mask);
-}
-
-/*** Prototypes ***/
-uint64_t ahci_alloc(AHCIQState *ahci, size_t bytes);
-void ahci_free(AHCIQState *ahci, uint64_t addr);
-void ahci_clean_mem(AHCIQState *ahci);
-
-/* Device management */
-QPCIDevice *get_ahci_device(uint32_t *fingerprint);
-void free_ahci_device(QPCIDevice *dev);
-void ahci_pci_enable(AHCIQState *ahci);
-void start_ahci_device(AHCIQState *ahci);
-void ahci_hba_enable(AHCIQState *ahci);
-
-/* Port Management */
-unsigned ahci_port_select(AHCIQState *ahci);
-void ahci_port_clear(AHCIQState *ahci, uint8_t port);
-
-/* Command header / table management */
-unsigned ahci_pick_cmd(AHCIQState *ahci, uint8_t port);
-void ahci_get_command_header(AHCIQState *ahci, uint8_t port,
- uint8_t slot, AHCICommandHeader *cmd);
-void ahci_set_command_header(AHCIQState *ahci, uint8_t port,
- uint8_t slot, AHCICommandHeader *cmd);
-void ahci_destroy_command(AHCIQState *ahci, uint8_t port, uint8_t slot);
-
-/* AHCI sanity check routines */
-void ahci_port_check_error(AHCIQState *ahci, uint8_t port);
-void ahci_port_check_interrupts(AHCIQState *ahci, uint8_t port,
- uint32_t intr_mask);
-void ahci_port_check_nonbusy(AHCIQState *ahci, uint8_t port, uint8_t slot);
-void ahci_port_check_d2h_sanity(AHCIQState *ahci, uint8_t port, uint8_t slot);
-void ahci_port_check_pio_sanity(AHCIQState *ahci, uint8_t port,
- uint8_t slot, size_t buffsize);
-void ahci_port_check_cmd_sanity(AHCIQState *ahci, AHCICommand *cmd);
-
-/* Misc */
-bool is_atapi(AHCIQState *ahci, uint8_t port);
-unsigned size_to_prdtl(unsigned bytes, unsigned bytes_per_prd);
-
-/* Command: Macro level execution */
-void ahci_guest_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd,
- uint64_t gbuffer, size_t size, uint64_t sector);
-AHCICommand *ahci_guest_io_halt(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd,
- uint64_t gbuffer, size_t size, uint64_t sector);
-void ahci_guest_io_resume(AHCIQState *ahci, AHCICommand *cmd);
-void ahci_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd,
- void *buffer, size_t bufsize, uint64_t sector);
-void ahci_exec(AHCIQState *ahci, uint8_t port,
- uint8_t op, const AHCIOpts *opts);
-
-/* Command: Fine-grained lifecycle */
-AHCICommand *ahci_command_create(uint8_t command_name);
-AHCICommand *ahci_atapi_command_create(uint8_t scsi_cmd);
-void ahci_command_commit(AHCIQState *ahci, AHCICommand *cmd, uint8_t port);
-void ahci_command_issue(AHCIQState *ahci, AHCICommand *cmd);
-void ahci_command_issue_async(AHCIQState *ahci, AHCICommand *cmd);
-void ahci_command_wait(AHCIQState *ahci, AHCICommand *cmd);
-void ahci_command_verify(AHCIQState *ahci, AHCICommand *cmd);
-void ahci_command_free(AHCICommand *cmd);
-
-/* Command: adjustments */
-void ahci_command_set_flags(AHCICommand *cmd, uint16_t cmdh_flags);
-void ahci_command_clr_flags(AHCICommand *cmd, uint16_t cmdh_flags);
-void ahci_command_set_offset(AHCICommand *cmd, uint64_t lba_sect);
-void ahci_command_set_buffer(AHCICommand *cmd, uint64_t buffer);
-void ahci_command_set_size(AHCICommand *cmd, uint64_t xbytes);
-void ahci_command_set_prd_size(AHCICommand *cmd, unsigned prd_size);
-void ahci_command_set_sizes(AHCICommand *cmd, uint64_t xbytes,
- unsigned prd_size);
-void ahci_command_set_acmd(AHCICommand *cmd, void *acmd);
-void ahci_command_enable_atapi_dma(AHCICommand *cmd);
-void ahci_command_adjust(AHCICommand *cmd, uint64_t lba_sect, uint64_t gbuffer,
- uint64_t xbytes, unsigned prd_size);
-
-/* Command: Misc */
-uint8_t ahci_command_slot(AHCICommand *cmd);
-void ahci_write_fis(AHCIQState *ahci, AHCICommand *cmd);
-
-#endif
diff --git a/qemu/tests/libqos/fw_cfg.c b/qemu/tests/libqos/fw_cfg.c
deleted file mode 100644
index 76894d575..000000000
--- a/qemu/tests/libqos/fw_cfg.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * libqos fw_cfg support
- *
- * Copyright IBM, Corp. 2012-2013
- * Copyright (C) 2013 Red Hat Inc.
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- * Markus Armbruster <armbru@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include <glib.h>
-#include "libqos/fw_cfg.h"
-#include "libqtest.h"
-#include "qemu/bswap.h"
-
-void qfw_cfg_select(QFWCFG *fw_cfg, uint16_t key)
-{
- fw_cfg->select(fw_cfg, key);
-}
-
-void qfw_cfg_read_data(QFWCFG *fw_cfg, void *data, size_t len)
-{
- fw_cfg->read(fw_cfg, data, len);
-}
-
-void qfw_cfg_get(QFWCFG *fw_cfg, uint16_t key, void *data, size_t len)
-{
- qfw_cfg_select(fw_cfg, key);
- qfw_cfg_read_data(fw_cfg, data, len);
-}
-
-uint16_t qfw_cfg_get_u16(QFWCFG *fw_cfg, uint16_t key)
-{
- uint16_t value;
- qfw_cfg_get(fw_cfg, key, &value, sizeof(value));
- return le16_to_cpu(value);
-}
-
-uint32_t qfw_cfg_get_u32(QFWCFG *fw_cfg, uint16_t key)
-{
- uint32_t value;
- qfw_cfg_get(fw_cfg, key, &value, sizeof(value));
- return le32_to_cpu(value);
-}
-
-uint64_t qfw_cfg_get_u64(QFWCFG *fw_cfg, uint16_t key)
-{
- uint64_t value;
- qfw_cfg_get(fw_cfg, key, &value, sizeof(value));
- return le64_to_cpu(value);
-}
-
-static void mm_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key)
-{
- writew(fw_cfg->base, key);
-}
-
-static void mm_fw_cfg_read(QFWCFG *fw_cfg, void *data, size_t len)
-{
- uint8_t *ptr = data;
- int i;
-
- for (i = 0; i < len; i++) {
- ptr[i] = readb(fw_cfg->base + 2);
- }
-}
-
-QFWCFG *mm_fw_cfg_init(uint64_t base)
-{
- QFWCFG *fw_cfg = g_malloc0(sizeof(*fw_cfg));
-
- fw_cfg->base = base;
- fw_cfg->select = mm_fw_cfg_select;
- fw_cfg->read = mm_fw_cfg_read;
-
- return fw_cfg;
-}
-
-static void io_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key)
-{
- outw(fw_cfg->base, key);
-}
-
-static void io_fw_cfg_read(QFWCFG *fw_cfg, void *data, size_t len)
-{
- uint8_t *ptr = data;
- int i;
-
- for (i = 0; i < len; i++) {
- ptr[i] = inb(fw_cfg->base + 1);
- }
-}
-
-QFWCFG *io_fw_cfg_init(uint16_t base)
-{
- QFWCFG *fw_cfg = g_malloc0(sizeof(*fw_cfg));
-
- fw_cfg->base = base;
- fw_cfg->select = io_fw_cfg_select;
- fw_cfg->read = io_fw_cfg_read;
-
- return fw_cfg;
-}
diff --git a/qemu/tests/libqos/fw_cfg.h b/qemu/tests/libqos/fw_cfg.h
deleted file mode 100644
index e8371b231..000000000
--- a/qemu/tests/libqos/fw_cfg.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * libqos fw_cfg support
- *
- * Copyright IBM, Corp. 2012-2013
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef LIBQOS_FW_CFG_H
-#define LIBQOS_FW_CFG_H
-
-
-typedef struct QFWCFG QFWCFG;
-
-struct QFWCFG
-{
- uint64_t base;
- void (*select)(QFWCFG *fw_cfg, uint16_t key);
- void (*read)(QFWCFG *fw_cfg, void *data, size_t len);
-};
-
-void qfw_cfg_select(QFWCFG *fw_cfg, uint16_t key);
-void qfw_cfg_read_data(QFWCFG *fw_cfg, void *data, size_t len);
-void qfw_cfg_get(QFWCFG *fw_cfg, uint16_t key, void *data, size_t len);
-uint16_t qfw_cfg_get_u16(QFWCFG *fw_cfg, uint16_t key);
-uint32_t qfw_cfg_get_u32(QFWCFG *fw_cfg, uint16_t key);
-uint64_t qfw_cfg_get_u64(QFWCFG *fw_cfg, uint16_t key);
-
-QFWCFG *mm_fw_cfg_init(uint64_t base);
-QFWCFG *io_fw_cfg_init(uint16_t base);
-
-static inline QFWCFG *pc_fw_cfg_init(void)
-{
- return io_fw_cfg_init(0x510);
-}
-
-#endif
diff --git a/qemu/tests/libqos/i2c-imx.c b/qemu/tests/libqos/i2c-imx.c
deleted file mode 100644
index 51c3468f9..000000000
--- a/qemu/tests/libqos/i2c-imx.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * QTest i.MX I2C driver
- *
- * Copyright (c) 2013 Jean-Christophe Dubois
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "libqos/i2c.h"
-
-#include <glib.h>
-
-#include "libqtest.h"
-
-#include "hw/i2c/imx_i2c.h"
-
-enum IMXI2CDirection {
- IMX_I2C_READ,
- IMX_I2C_WRITE,
-};
-
-typedef struct IMXI2C {
- I2CAdapter parent;
-
- uint64_t addr;
-} IMXI2C;
-
-
-static void imx_i2c_set_slave_addr(IMXI2C *s, uint8_t addr,
- enum IMXI2CDirection direction)
-{
- writeb(s->addr + I2DR_ADDR, (addr << 1) |
- (direction == IMX_I2C_READ ? 1 : 0));
-}
-
-static void imx_i2c_send(I2CAdapter *i2c, uint8_t addr,
- const uint8_t *buf, uint16_t len)
-{
- IMXI2C *s = (IMXI2C *)i2c;
- uint8_t data;
- uint8_t status;
- uint16_t size = 0;
-
- if (!len) {
- return;
- }
-
- /* set the bus for write */
- data = I2CR_IEN |
- I2CR_IIEN |
- I2CR_MSTA |
- I2CR_MTX |
- I2CR_TXAK;
-
- writeb(s->addr + I2CR_ADDR, data);
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IBB) != 0);
-
- /* set the slave address */
- imx_i2c_set_slave_addr(s, addr, IMX_I2C_WRITE);
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IIF) != 0);
- g_assert((status & I2SR_RXAK) == 0);
-
- /* ack the interrupt */
- writeb(s->addr + I2SR_ADDR, 0);
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IIF) == 0);
-
- while (size < len) {
- /* check we are still busy */
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IBB) != 0);
-
- /* write the data */
- writeb(s->addr + I2DR_ADDR, buf[size]);
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IIF) != 0);
- g_assert((status & I2SR_RXAK) == 0);
-
- /* ack the interrupt */
- writeb(s->addr + I2SR_ADDR, 0);
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IIF) == 0);
-
- size++;
- }
-
- /* release the bus */
- data &= ~(I2CR_MSTA | I2CR_MTX);
- writeb(s->addr + I2CR_ADDR, data);
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IBB) == 0);
-}
-
-static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr,
- uint8_t *buf, uint16_t len)
-{
- IMXI2C *s = (IMXI2C *)i2c;
- uint8_t data;
- uint8_t status;
- uint16_t size = 0;
-
- if (!len) {
- return;
- }
-
- /* set the bus for write */
- data = I2CR_IEN |
- I2CR_IIEN |
- I2CR_MSTA |
- I2CR_MTX |
- I2CR_TXAK;
-
- writeb(s->addr + I2CR_ADDR, data);
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IBB) != 0);
-
- /* set the slave address */
- imx_i2c_set_slave_addr(s, addr, IMX_I2C_READ);
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IIF) != 0);
- g_assert((status & I2SR_RXAK) == 0);
-
- /* ack the interrupt */
- writeb(s->addr + I2SR_ADDR, 0);
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IIF) == 0);
-
- /* set the bus for read */
- data &= ~I2CR_MTX;
- /* if only one byte don't ack */
- if (len != 1) {
- data &= ~I2CR_TXAK;
- }
- writeb(s->addr + I2CR_ADDR, data);
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IBB) != 0);
-
- /* dummy read */
- readb(s->addr + I2DR_ADDR);
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IIF) != 0);
-
- /* ack the interrupt */
- writeb(s->addr + I2SR_ADDR, 0);
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IIF) == 0);
-
- while (size < len) {
- /* check we are still busy */
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IBB) != 0);
-
- if (size == (len - 1)) {
- /* stop the read transaction */
- data &= ~(I2CR_MSTA | I2CR_MTX);
- } else {
- /* ack the data read */
- data |= I2CR_TXAK;
- }
- writeb(s->addr + I2CR_ADDR, data);
-
- /* read the data */
- buf[size] = readb(s->addr + I2DR_ADDR);
-
- if (size != (len - 1)) {
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IIF) != 0);
-
- /* ack the interrupt */
- writeb(s->addr + I2SR_ADDR, 0);
- }
-
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IIF) == 0);
-
- size++;
- }
-
- status = readb(s->addr + I2SR_ADDR);
- g_assert((status & I2SR_IBB) == 0);
-}
-
-I2CAdapter *imx_i2c_create(uint64_t addr)
-{
- IMXI2C *s = g_malloc0(sizeof(*s));
- I2CAdapter *i2c = (I2CAdapter *)s;
-
- s->addr = addr;
-
- i2c->send = imx_i2c_send;
- i2c->recv = imx_i2c_recv;
-
- return i2c;
-}
diff --git a/qemu/tests/libqos/i2c-omap.c b/qemu/tests/libqos/i2c-omap.c
deleted file mode 100644
index 2028f2f14..000000000
--- a/qemu/tests/libqos/i2c-omap.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * QTest I2C driver
- *
- * Copyright (c) 2012 Andreas Färber
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-#include "qemu/osdep.h"
-#include "libqos/i2c.h"
-
-#include <glib.h>
-
-#include "qemu/bswap.h"
-#include "libqtest.h"
-
-enum OMAPI2CRegisters {
- OMAP_I2C_REV = 0x00,
- OMAP_I2C_STAT = 0x08,
- OMAP_I2C_CNT = 0x18,
- OMAP_I2C_DATA = 0x1c,
- OMAP_I2C_CON = 0x24,
- OMAP_I2C_SA = 0x2c,
-};
-
-enum OMAPI2CSTATBits {
- OMAP_I2C_STAT_NACK = 1 << 1,
- OMAP_I2C_STAT_ARDY = 1 << 2,
- OMAP_I2C_STAT_RRDY = 1 << 3,
- OMAP_I2C_STAT_XRDY = 1 << 4,
- OMAP_I2C_STAT_ROVR = 1 << 11,
- OMAP_I2C_STAT_SBD = 1 << 15,
-};
-
-enum OMAPI2CCONBits {
- OMAP_I2C_CON_STT = 1 << 0,
- OMAP_I2C_CON_STP = 1 << 1,
- OMAP_I2C_CON_TRX = 1 << 9,
- OMAP_I2C_CON_MST = 1 << 10,
- OMAP_I2C_CON_BE = 1 << 14,
- OMAP_I2C_CON_I2C_EN = 1 << 15,
-};
-
-typedef struct OMAPI2C {
- I2CAdapter parent;
-
- uint64_t addr;
-} OMAPI2C;
-
-
-static void omap_i2c_set_slave_addr(OMAPI2C *s, uint8_t addr)
-{
- uint16_t data = addr;
-
- writew(s->addr + OMAP_I2C_SA, data);
- data = readw(s->addr + OMAP_I2C_SA);
- g_assert_cmphex(data, ==, addr);
-}
-
-static void omap_i2c_send(I2CAdapter *i2c, uint8_t addr,
- const uint8_t *buf, uint16_t len)
-{
- OMAPI2C *s = (OMAPI2C *)i2c;
- uint16_t data;
-
- omap_i2c_set_slave_addr(s, addr);
-
- data = len;
- writew(s->addr + OMAP_I2C_CNT, data);
-
- data = OMAP_I2C_CON_I2C_EN |
- OMAP_I2C_CON_TRX |
- OMAP_I2C_CON_MST |
- OMAP_I2C_CON_STT |
- OMAP_I2C_CON_STP;
- writew(s->addr + OMAP_I2C_CON, data);
- data = readw(s->addr + OMAP_I2C_CON);
- g_assert((data & OMAP_I2C_CON_STP) != 0);
-
- data = readw(s->addr + OMAP_I2C_STAT);
- g_assert((data & OMAP_I2C_STAT_NACK) == 0);
-
- while (len > 1) {
- data = readw(s->addr + OMAP_I2C_STAT);
- g_assert((data & OMAP_I2C_STAT_XRDY) != 0);
-
- data = buf[0] | ((uint16_t)buf[1] << 8);
- writew(s->addr + OMAP_I2C_DATA, data);
- buf = (uint8_t *)buf + 2;
- len -= 2;
- }
- if (len == 1) {
- data = readw(s->addr + OMAP_I2C_STAT);
- g_assert((data & OMAP_I2C_STAT_XRDY) != 0);
-
- data = buf[0];
- writew(s->addr + OMAP_I2C_DATA, data);
- }
-
- data = readw(s->addr + OMAP_I2C_CON);
- g_assert((data & OMAP_I2C_CON_STP) == 0);
-}
-
-static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr,
- uint8_t *buf, uint16_t len)
-{
- OMAPI2C *s = (OMAPI2C *)i2c;
- uint16_t data, stat;
-
- omap_i2c_set_slave_addr(s, addr);
-
- data = len;
- writew(s->addr + OMAP_I2C_CNT, data);
-
- data = OMAP_I2C_CON_I2C_EN |
- OMAP_I2C_CON_MST |
- OMAP_I2C_CON_STT |
- OMAP_I2C_CON_STP;
- writew(s->addr + OMAP_I2C_CON, data);
- data = readw(s->addr + OMAP_I2C_CON);
- g_assert((data & OMAP_I2C_CON_STP) == 0);
-
- data = readw(s->addr + OMAP_I2C_STAT);
- g_assert((data & OMAP_I2C_STAT_NACK) == 0);
-
- data = readw(s->addr + OMAP_I2C_CNT);
- g_assert_cmpuint(data, ==, len);
-
- while (len > 0) {
- data = readw(s->addr + OMAP_I2C_STAT);
- g_assert((data & OMAP_I2C_STAT_RRDY) != 0);
- g_assert((data & OMAP_I2C_STAT_ROVR) == 0);
-
- data = readw(s->addr + OMAP_I2C_DATA);
-
- stat = readw(s->addr + OMAP_I2C_STAT);
-
- if (unlikely(len == 1)) {
- g_assert((stat & OMAP_I2C_STAT_SBD) != 0);
-
- buf[0] = data & 0xff;
- buf++;
- len--;
- } else {
- buf[0] = data & 0xff;
- buf[1] = data >> 8;
- buf += 2;
- len -= 2;
- }
- }
-
- data = readw(s->addr + OMAP_I2C_CON);
- g_assert((data & OMAP_I2C_CON_STP) == 0);
-}
-
-I2CAdapter *omap_i2c_create(uint64_t addr)
-{
- OMAPI2C *s = g_malloc0(sizeof(*s));
- I2CAdapter *i2c = (I2CAdapter *)s;
- uint16_t data;
-
- s->addr = addr;
-
- i2c->send = omap_i2c_send;
- i2c->recv = omap_i2c_recv;
-
- /* verify the mmio address by looking for a known signature */
- data = readw(addr + OMAP_I2C_REV);
- g_assert_cmphex(data, ==, 0x34);
-
- return i2c;
-}
diff --git a/qemu/tests/libqos/i2c.c b/qemu/tests/libqos/i2c.c
deleted file mode 100644
index 23bc2a3eb..000000000
--- a/qemu/tests/libqos/i2c.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * QTest I2C driver
- *
- * Copyright (c) 2012 Andreas Färber
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-#include "qemu/osdep.h"
-#include "libqos/i2c.h"
-#include "libqtest.h"
-
-void i2c_send(I2CAdapter *i2c, uint8_t addr,
- const uint8_t *buf, uint16_t len)
-{
- i2c->send(i2c, addr, buf, len);
-}
-
-void i2c_recv(I2CAdapter *i2c, uint8_t addr,
- uint8_t *buf, uint16_t len)
-{
- i2c->recv(i2c, addr, buf, len);
-}
diff --git a/qemu/tests/libqos/i2c.h b/qemu/tests/libqos/i2c.h
deleted file mode 100644
index 6e648f922..000000000
--- a/qemu/tests/libqos/i2c.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * I2C libqos
- *
- * Copyright (c) 2012 Andreas Färber
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-#ifndef LIBQOS_I2C_H
-#define LIBQOS_I2C_H
-
-
-typedef struct I2CAdapter I2CAdapter;
-struct I2CAdapter {
- void (*send)(I2CAdapter *adapter, uint8_t addr,
- const uint8_t *buf, uint16_t len);
- void (*recv)(I2CAdapter *adapter, uint8_t addr,
- uint8_t *buf, uint16_t len);
-};
-
-void i2c_send(I2CAdapter *i2c, uint8_t addr,
- const uint8_t *buf, uint16_t len);
-void i2c_recv(I2CAdapter *i2c, uint8_t addr,
- uint8_t *buf, uint16_t len);
-
-/* libi2c-omap.c */
-I2CAdapter *omap_i2c_create(uint64_t addr);
-
-/* libi2c-imx.c */
-I2CAdapter *imx_i2c_create(uint64_t addr);
-
-#endif
diff --git a/qemu/tests/libqos/libqos-pc.c b/qemu/tests/libqos/libqos-pc.c
deleted file mode 100644
index 72b5e3ba0..000000000
--- a/qemu/tests/libqos/libqos-pc.c
+++ /dev/null
@@ -1,30 +0,0 @@
-#include "qemu/osdep.h"
-#include "libqos/libqos-pc.h"
-#include "libqos/malloc-pc.h"
-
-static QOSOps qos_ops = {
- .init_allocator = pc_alloc_init_flags,
- .uninit_allocator = pc_alloc_uninit
-};
-
-QOSState *qtest_pc_vboot(const char *cmdline_fmt, va_list ap)
-{
- return qtest_vboot(&qos_ops, cmdline_fmt, ap);
-}
-
-QOSState *qtest_pc_boot(const char *cmdline_fmt, ...)
-{
- QOSState *qs;
- va_list ap;
-
- va_start(ap, cmdline_fmt);
- qs = qtest_vboot(&qos_ops, cmdline_fmt, ap);
- va_end(ap);
-
- return qs;
-}
-
-void qtest_pc_shutdown(QOSState *qs)
-{
- return qtest_shutdown(qs);
-}
diff --git a/qemu/tests/libqos/libqos-pc.h b/qemu/tests/libqos/libqos-pc.h
deleted file mode 100644
index b1820c573..000000000
--- a/qemu/tests/libqos/libqos-pc.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __libqos_pc_h
-#define __libqos_pc_h
-
-#include "libqos/libqos.h"
-
-QOSState *qtest_pc_vboot(const char *cmdline_fmt, va_list ap);
-QOSState *qtest_pc_boot(const char *cmdline_fmt, ...);
-void qtest_pc_shutdown(QOSState *qs);
-
-#endif
diff --git a/qemu/tests/libqos/libqos.c b/qemu/tests/libqos/libqos.c
deleted file mode 100644
index 79b0b29b4..000000000
--- a/qemu/tests/libqos/libqos.c
+++ /dev/null
@@ -1,254 +0,0 @@
-#include "qemu/osdep.h"
-#include <glib.h>
-#include <sys/wait.h>
-
-#include "libqtest.h"
-#include "libqos/libqos.h"
-#include "libqos/pci.h"
-
-/*** Test Setup & Teardown ***/
-
-/**
- * Launch QEMU with the given command line,
- * and then set up interrupts and our guest malloc interface.
- */
-QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap)
-{
- char *cmdline;
-
- struct QOSState *qs = g_malloc(sizeof(QOSState));
-
- cmdline = g_strdup_vprintf(cmdline_fmt, ap);
- qs->qts = qtest_start(cmdline);
- qs->ops = ops;
- qtest_irq_intercept_in(global_qtest, "ioapic");
- if (ops && ops->init_allocator) {
- qs->alloc = ops->init_allocator(ALLOC_NO_FLAGS);
- }
-
- g_free(cmdline);
- return qs;
-}
-
-/**
- * Launch QEMU with the given command line,
- * and then set up interrupts and our guest malloc interface.
- */
-QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...)
-{
- QOSState *qs;
- va_list ap;
-
- va_start(ap, cmdline_fmt);
- qs = qtest_vboot(ops, cmdline_fmt, ap);
- va_end(ap);
-
- return qs;
-}
-
-/**
- * Tear down the QEMU instance.
- */
-void qtest_shutdown(QOSState *qs)
-{
- if (qs->alloc && qs->ops && qs->ops->uninit_allocator) {
- qs->ops->uninit_allocator(qs->alloc);
- qs->alloc = NULL;
- }
- qtest_quit(qs->qts);
- g_free(qs);
-}
-
-void set_context(QOSState *s)
-{
- global_qtest = s->qts;
-}
-
-static QDict *qmp_execute(const char *command)
-{
- char *fmt;
- QDict *rsp;
-
- fmt = g_strdup_printf("{ 'execute': '%s' }", command);
- rsp = qmp(fmt);
- g_free(fmt);
-
- return rsp;
-}
-
-void migrate(QOSState *from, QOSState *to, const char *uri)
-{
- const char *st;
- char *s;
- QDict *rsp, *sub;
- bool running;
-
- set_context(from);
-
- /* Is the machine currently running? */
- rsp = qmp_execute("query-status");
- g_assert(qdict_haskey(rsp, "return"));
- sub = qdict_get_qdict(rsp, "return");
- g_assert(qdict_haskey(sub, "running"));
- running = qdict_get_bool(sub, "running");
- QDECREF(rsp);
-
- /* Issue the migrate command. */
- s = g_strdup_printf("{ 'execute': 'migrate',"
- "'arguments': { 'uri': '%s' } }",
- uri);
- rsp = qmp(s);
- g_free(s);
- g_assert(qdict_haskey(rsp, "return"));
- QDECREF(rsp);
-
- /* Wait for STOP event, but only if we were running: */
- if (running) {
- qmp_eventwait("STOP");
- }
-
- /* If we were running, we can wait for an event. */
- if (running) {
- migrate_allocator(from->alloc, to->alloc);
- set_context(to);
- qmp_eventwait("RESUME");
- return;
- }
-
- /* Otherwise, we need to wait: poll until migration is completed. */
- while (1) {
- rsp = qmp_execute("query-migrate");
- g_assert(qdict_haskey(rsp, "return"));
- sub = qdict_get_qdict(rsp, "return");
- g_assert(qdict_haskey(sub, "status"));
- st = qdict_get_str(sub, "status");
-
- /* "setup", "active", "completed", "failed", "cancelled" */
- if (strcmp(st, "completed") == 0) {
- QDECREF(rsp);
- break;
- }
-
- if ((strcmp(st, "setup") == 0) || (strcmp(st, "active") == 0)) {
- QDECREF(rsp);
- g_usleep(5000);
- continue;
- }
-
- fprintf(stderr, "Migration did not complete, status: %s\n", st);
- g_assert_not_reached();
- }
-
- migrate_allocator(from->alloc, to->alloc);
- set_context(to);
-}
-
-bool have_qemu_img(void)
-{
- char *rpath;
- const char *path = getenv("QTEST_QEMU_IMG");
- if (!path) {
- return false;
- }
-
- rpath = realpath(path, NULL);
- if (!rpath) {
- return false;
- } else {
- free(rpath);
- return true;
- }
-}
-
-void mkimg(const char *file, const char *fmt, unsigned size_mb)
-{
- gchar *cli;
- bool ret;
- int rc;
- GError *err = NULL;
- char *qemu_img_path;
- gchar *out, *out2;
- char *qemu_img_abs_path;
-
- qemu_img_path = getenv("QTEST_QEMU_IMG");
- g_assert(qemu_img_path);
- qemu_img_abs_path = realpath(qemu_img_path, NULL);
- g_assert(qemu_img_abs_path);
-
- cli = g_strdup_printf("%s create -f %s %s %uM", qemu_img_abs_path,
- fmt, file, size_mb);
- ret = g_spawn_command_line_sync(cli, &out, &out2, &rc, &err);
- if (err) {
- fprintf(stderr, "%s\n", err->message);
- g_error_free(err);
- }
- g_assert(ret && !err);
-
- /* In glib 2.34, we have g_spawn_check_exit_status. in 2.12, we don't.
- * glib 2.43.91 implementation assumes that any non-zero is an error for
- * windows, but uses extra precautions for Linux. However,
- * 0 is only possible if the program exited normally, so that should be
- * sufficient for our purposes on all platforms, here. */
- if (rc) {
- fprintf(stderr, "qemu-img returned status code %d\n", rc);
- }
- g_assert(!rc);
-
- g_free(out);
- g_free(out2);
- g_free(cli);
- free(qemu_img_abs_path);
-}
-
-void mkqcow2(const char *file, unsigned size_mb)
-{
- return mkimg(file, "qcow2", size_mb);
-}
-
-void prepare_blkdebug_script(const char *debug_fn, const char *event)
-{
- FILE *debug_file = fopen(debug_fn, "w");
- int ret;
-
- fprintf(debug_file, "[inject-error]\n");
- fprintf(debug_file, "event = \"%s\"\n", event);
- fprintf(debug_file, "errno = \"5\"\n");
- fprintf(debug_file, "state = \"1\"\n");
- fprintf(debug_file, "immediately = \"off\"\n");
- fprintf(debug_file, "once = \"on\"\n");
-
- fprintf(debug_file, "[set-state]\n");
- fprintf(debug_file, "event = \"%s\"\n", event);
- fprintf(debug_file, "new_state = \"2\"\n");
- fflush(debug_file);
- g_assert(!ferror(debug_file));
-
- ret = fclose(debug_file);
- g_assert(ret == 0);
-}
-
-void generate_pattern(void *buffer, size_t len, size_t cycle_len)
-{
- int i, j;
- unsigned char *tx = (unsigned char *)buffer;
- unsigned char p;
- size_t *sx;
-
- /* Write an indicative pattern that varies and is unique per-cycle */
- p = rand() % 256;
- for (i = 0; i < len; i++) {
- tx[i] = p++ % 256;
- if (i % cycle_len == 0) {
- p = rand() % 256;
- }
- }
-
- /* force uniqueness by writing an id per-cycle */
- for (i = 0; i < len / cycle_len; i++) {
- j = i * cycle_len;
- if (j + sizeof(*sx) <= len) {
- sx = (size_t *)&tx[j];
- *sx = i;
- }
- }
-}
diff --git a/qemu/tests/libqos/libqos.h b/qemu/tests/libqos/libqos.h
deleted file mode 100644
index ca14d2e9f..000000000
--- a/qemu/tests/libqos/libqos.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef __libqos_h
-#define __libqos_h
-
-#include "libqtest.h"
-#include "libqos/pci.h"
-#include "libqos/malloc-pc.h"
-
-typedef struct QOSOps {
- QGuestAllocator *(*init_allocator)(QAllocOpts);
- void (*uninit_allocator)(QGuestAllocator *);
-} QOSOps;
-
-typedef struct QOSState {
- QTestState *qts;
- QGuestAllocator *alloc;
- QOSOps *ops;
-} QOSState;
-
-QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap);
-QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...);
-void qtest_shutdown(QOSState *qs);
-bool have_qemu_img(void);
-void mkimg(const char *file, const char *fmt, unsigned size_mb);
-void mkqcow2(const char *file, unsigned size_mb);
-void set_context(QOSState *s);
-void migrate(QOSState *from, QOSState *to, const char *uri);
-void prepare_blkdebug_script(const char *debug_fn, const char *event);
-void generate_pattern(void *buffer, size_t len, size_t cycle_len);
-
-static inline uint64_t qmalloc(QOSState *q, size_t bytes)
-{
- return guest_alloc(q->alloc, bytes);
-}
-
-static inline void qfree(QOSState *q, uint64_t addr)
-{
- guest_free(q->alloc, addr);
-}
-
-#endif
diff --git a/qemu/tests/libqos/malloc-generic.c b/qemu/tests/libqos/malloc-generic.c
deleted file mode 100644
index 6000df2b8..000000000
--- a/qemu/tests/libqos/malloc-generic.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Basic libqos generic malloc support
- *
- * Copyright (c) 2014 Marc Marí
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include <glib.h>
-#include "libqos/malloc-generic.h"
-#include "libqos/malloc.h"
-
-/*
- * Mostly for valgrind happiness, but it does offer
- * a chokepoint for debugging guest memory leaks, too.
- */
-void generic_alloc_uninit(QGuestAllocator *allocator)
-{
- alloc_uninit(allocator);
-}
-
-QGuestAllocator *generic_alloc_init_flags(uint64_t base_addr, uint64_t size,
- uint32_t page_size, QAllocOpts flags)
-{
- QGuestAllocator *s;
- uint64_t start = base_addr + (1 << 20); /* Start at 1MB */
-
- s = alloc_init_flags(flags, start, start + size);
- alloc_set_page_size(s, page_size);
-
- return s;
-}
-
-inline QGuestAllocator *generic_alloc_init(uint64_t base_addr, uint64_t size,
- uint32_t page_size)
-{
- return generic_alloc_init_flags(base_addr, size, page_size, ALLOC_NO_FLAGS);
-}
diff --git a/qemu/tests/libqos/malloc-generic.h b/qemu/tests/libqos/malloc-generic.h
deleted file mode 100644
index 90104ecec..000000000
--- a/qemu/tests/libqos/malloc-generic.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Basic libqos generic malloc support
- *
- * Copyright (c) 2014 Marc Marí
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef LIBQOS_MALLOC_GENERIC_H
-#define LIBQOS_MALLOC_GENERIC_H
-
-#include "libqos/malloc.h"
-
-QGuestAllocator *generic_alloc_init(uint64_t base_addr, uint64_t size,
- uint32_t page_size);
-QGuestAllocator *generic_alloc_init_flags(uint64_t base_addr, uint64_t size,
- uint32_t page_size, QAllocOpts flags);
-void generic_alloc_uninit(QGuestAllocator *allocator);
-
-#endif
diff --git a/qemu/tests/libqos/malloc-pc.c b/qemu/tests/libqos/malloc-pc.c
deleted file mode 100644
index eee706bd6..000000000
--- a/qemu/tests/libqos/malloc-pc.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * libqos malloc support for PC
- *
- * Copyright IBM, Corp. 2012-2013
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "libqos/malloc-pc.h"
-#include "libqos/fw_cfg.h"
-
-#include "hw/nvram/fw_cfg_keys.h"
-
-#include "qemu-common.h"
-#include <glib.h>
-
-#define PAGE_SIZE (4096)
-
-/*
- * Mostly for valgrind happiness, but it does offer
- * a chokepoint for debugging guest memory leaks, too.
- */
-void pc_alloc_uninit(QGuestAllocator *allocator)
-{
- alloc_uninit(allocator);
-}
-
-QGuestAllocator *pc_alloc_init_flags(QAllocOpts flags)
-{
- QGuestAllocator *s;
- uint64_t ram_size;
- QFWCFG *fw_cfg = pc_fw_cfg_init();
-
- ram_size = qfw_cfg_get_u64(fw_cfg, FW_CFG_RAM_SIZE);
- s = alloc_init_flags(flags, 1 << 20, MIN(ram_size, 0xE0000000));
- alloc_set_page_size(s, PAGE_SIZE);
-
- /* clean-up */
- g_free(fw_cfg);
-
- return s;
-}
-
-inline QGuestAllocator *pc_alloc_init(void)
-{
- return pc_alloc_init_flags(ALLOC_NO_FLAGS);
-}
diff --git a/qemu/tests/libqos/malloc-pc.h b/qemu/tests/libqos/malloc-pc.h
deleted file mode 100644
index 86ab9f042..000000000
--- a/qemu/tests/libqos/malloc-pc.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * libqos malloc support for PC
- *
- * Copyright IBM, Corp. 2012-2013
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef LIBQOS_MALLOC_PC_H
-#define LIBQOS_MALLOC_PC_H
-
-#include "libqos/malloc.h"
-
-QGuestAllocator *pc_alloc_init(void);
-QGuestAllocator *pc_alloc_init_flags(QAllocOpts flags);
-void pc_alloc_uninit(QGuestAllocator *allocator);
-
-#endif
diff --git a/qemu/tests/libqos/malloc.c b/qemu/tests/libqos/malloc.c
deleted file mode 100644
index c0df52f33..000000000
--- a/qemu/tests/libqos/malloc.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * libqos malloc support
- *
- * Copyright (c) 2014
- *
- * Author:
- * John Snow <jsnow@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "libqos/malloc.h"
-#include "qemu-common.h"
-#include <glib.h>
-
-typedef QTAILQ_HEAD(MemList, MemBlock) MemList;
-
-typedef struct MemBlock {
- QTAILQ_ENTRY(MemBlock) MLIST_ENTNAME;
- uint64_t size;
- uint64_t addr;
-} MemBlock;
-
-struct QGuestAllocator {
- QAllocOpts opts;
- uint64_t start;
- uint64_t end;
- uint32_t page_size;
-
- MemList *used;
- MemList *free;
-};
-
-#define DEFAULT_PAGE_SIZE 4096
-
-static void mlist_delete(MemList *list, MemBlock *node)
-{
- g_assert(list && node);
- QTAILQ_REMOVE(list, node, MLIST_ENTNAME);
- g_free(node);
-}
-
-static MemBlock *mlist_find_key(MemList *head, uint64_t addr)
-{
- MemBlock *node;
- QTAILQ_FOREACH(node, head, MLIST_ENTNAME) {
- if (node->addr == addr) {
- return node;
- }
- }
- return NULL;
-}
-
-static MemBlock *mlist_find_space(MemList *head, uint64_t size)
-{
- MemBlock *node;
-
- QTAILQ_FOREACH(node, head, MLIST_ENTNAME) {
- if (node->size >= size) {
- return node;
- }
- }
- return NULL;
-}
-
-static MemBlock *mlist_sort_insert(MemList *head, MemBlock *insr)
-{
- MemBlock *node;
- g_assert(head && insr);
-
- QTAILQ_FOREACH(node, head, MLIST_ENTNAME) {
- if (insr->addr < node->addr) {
- QTAILQ_INSERT_BEFORE(node, insr, MLIST_ENTNAME);
- return insr;
- }
- }
-
- QTAILQ_INSERT_TAIL(head, insr, MLIST_ENTNAME);
- return insr;
-}
-
-static inline uint64_t mlist_boundary(MemBlock *node)
-{
- return node->size + node->addr;
-}
-
-static MemBlock *mlist_join(MemList *head, MemBlock *left, MemBlock *right)
-{
- g_assert(head && left && right);
-
- left->size += right->size;
- mlist_delete(head, right);
- return left;
-}
-
-static void mlist_coalesce(MemList *head, MemBlock *node)
-{
- g_assert(node);
- MemBlock *left;
- MemBlock *right;
- char merge;
-
- do {
- merge = 0;
- left = QTAILQ_PREV(node, MemList, MLIST_ENTNAME);
- right = QTAILQ_NEXT(node, MLIST_ENTNAME);
-
- /* clowns to the left of me */
- if (left && mlist_boundary(left) == node->addr) {
- node = mlist_join(head, left, node);
- merge = 1;
- }
-
- /* jokers to the right */
- if (right && mlist_boundary(node) == right->addr) {
- node = mlist_join(head, node, right);
- merge = 1;
- }
-
- } while (merge);
-}
-
-static MemBlock *mlist_new(uint64_t addr, uint64_t size)
-{
- MemBlock *block;
-
- if (!size) {
- return NULL;
- }
- block = g_malloc0(sizeof(MemBlock));
-
- block->addr = addr;
- block->size = size;
-
- return block;
-}
-
-static uint64_t mlist_fulfill(QGuestAllocator *s, MemBlock *freenode,
- uint64_t size)
-{
- uint64_t addr;
- MemBlock *usednode;
-
- g_assert(freenode);
- g_assert_cmpint(freenode->size, >=, size);
-
- addr = freenode->addr;
- if (freenode->size == size) {
- /* re-use this freenode as our used node */
- QTAILQ_REMOVE(s->free, freenode, MLIST_ENTNAME);
- usednode = freenode;
- } else {
- /* adjust the free node and create a new used node */
- freenode->addr += size;
- freenode->size -= size;
- usednode = mlist_new(addr, size);
- }
-
- mlist_sort_insert(s->used, usednode);
- return addr;
-}
-
-/* To assert the correctness of the list.
- * Used only if ALLOC_PARANOID is set. */
-static void mlist_check(QGuestAllocator *s)
-{
- MemBlock *node;
- uint64_t addr = s->start > 0 ? s->start - 1 : 0;
- uint64_t next = s->start;
-
- QTAILQ_FOREACH(node, s->free, MLIST_ENTNAME) {
- g_assert_cmpint(node->addr, >, addr);
- g_assert_cmpint(node->addr, >=, next);
- addr = node->addr;
- next = node->addr + node->size;
- }
-
- addr = s->start > 0 ? s->start - 1 : 0;
- next = s->start;
- QTAILQ_FOREACH(node, s->used, MLIST_ENTNAME) {
- g_assert_cmpint(node->addr, >, addr);
- g_assert_cmpint(node->addr, >=, next);
- addr = node->addr;
- next = node->addr + node->size;
- }
-}
-
-static uint64_t mlist_alloc(QGuestAllocator *s, uint64_t size)
-{
- MemBlock *node;
-
- node = mlist_find_space(s->free, size);
- if (!node) {
- fprintf(stderr, "Out of guest memory.\n");
- g_assert_not_reached();
- }
- return mlist_fulfill(s, node, size);
-}
-
-static void mlist_free(QGuestAllocator *s, uint64_t addr)
-{
- MemBlock *node;
-
- if (addr == 0) {
- return;
- }
-
- node = mlist_find_key(s->used, addr);
- if (!node) {
- fprintf(stderr, "Error: no record found for an allocation at "
- "0x%016" PRIx64 ".\n",
- addr);
- g_assert_not_reached();
- }
-
- /* Rip it out of the used list and re-insert back into the free list. */
- QTAILQ_REMOVE(s->used, node, MLIST_ENTNAME);
- mlist_sort_insert(s->free, node);
- mlist_coalesce(s->free, node);
-}
-
-/*
- * Mostly for valgrind happiness, but it does offer
- * a chokepoint for debugging guest memory leaks, too.
- */
-void alloc_uninit(QGuestAllocator *allocator)
-{
- MemBlock *node;
- MemBlock *tmp;
- QAllocOpts mask;
-
- /* Check for guest leaks, and destroy the list. */
- QTAILQ_FOREACH_SAFE(node, allocator->used, MLIST_ENTNAME, tmp) {
- if (allocator->opts & (ALLOC_LEAK_WARN | ALLOC_LEAK_ASSERT)) {
- fprintf(stderr, "guest malloc leak @ 0x%016" PRIx64 "; "
- "size 0x%016" PRIx64 ".\n",
- node->addr, node->size);
- }
- if (allocator->opts & (ALLOC_LEAK_ASSERT)) {
- g_assert_not_reached();
- }
- g_free(node);
- }
-
- /* If we have previously asserted that there are no leaks, then there
- * should be only one node here with a specific address and size. */
- mask = ALLOC_LEAK_ASSERT | ALLOC_PARANOID;
- QTAILQ_FOREACH_SAFE(node, allocator->free, MLIST_ENTNAME, tmp) {
- if ((allocator->opts & mask) == mask) {
- if ((node->addr != allocator->start) ||
- (node->size != allocator->end - allocator->start)) {
- fprintf(stderr, "Free list is corrupted.\n");
- g_assert_not_reached();
- }
- }
-
- g_free(node);
- }
-
- g_free(allocator->used);
- g_free(allocator->free);
- g_free(allocator);
-}
-
-uint64_t guest_alloc(QGuestAllocator *allocator, size_t size)
-{
- uint64_t rsize = size;
- uint64_t naddr;
-
- if (!size) {
- return 0;
- }
-
- rsize += (allocator->page_size - 1);
- rsize &= -allocator->page_size;
- g_assert_cmpint((allocator->start + rsize), <=, allocator->end);
- g_assert_cmpint(rsize, >=, size);
-
- naddr = mlist_alloc(allocator, rsize);
- if (allocator->opts & ALLOC_PARANOID) {
- mlist_check(allocator);
- }
-
- return naddr;
-}
-
-void guest_free(QGuestAllocator *allocator, uint64_t addr)
-{
- if (!addr) {
- return;
- }
- mlist_free(allocator, addr);
- if (allocator->opts & ALLOC_PARANOID) {
- mlist_check(allocator);
- }
-}
-
-QGuestAllocator *alloc_init(uint64_t start, uint64_t end)
-{
- QGuestAllocator *s = g_malloc0(sizeof(*s));
- MemBlock *node;
-
- s->start = start;
- s->end = end;
-
- s->used = g_malloc(sizeof(MemList));
- s->free = g_malloc(sizeof(MemList));
- QTAILQ_INIT(s->used);
- QTAILQ_INIT(s->free);
-
- node = mlist_new(s->start, s->end - s->start);
- QTAILQ_INSERT_HEAD(s->free, node, MLIST_ENTNAME);
-
- s->page_size = DEFAULT_PAGE_SIZE;
-
- return s;
-}
-
-QGuestAllocator *alloc_init_flags(QAllocOpts opts,
- uint64_t start, uint64_t end)
-{
- QGuestAllocator *s = alloc_init(start, end);
- s->opts = opts;
- return s;
-}
-
-void alloc_set_page_size(QGuestAllocator *allocator, size_t page_size)
-{
- /* Can't alter the page_size for an allocator in-use */
- g_assert(QTAILQ_EMPTY(allocator->used));
-
- g_assert(is_power_of_2(page_size));
- allocator->page_size = page_size;
-}
-
-void alloc_set_flags(QGuestAllocator *allocator, QAllocOpts opts)
-{
- allocator->opts |= opts;
-}
-
-void migrate_allocator(QGuestAllocator *src,
- QGuestAllocator *dst)
-{
- MemBlock *node, *tmp;
- MemList *tmpused, *tmpfree;
-
- /* The general memory layout should be equivalent,
- * though opts can differ. */
- g_assert_cmphex(src->start, ==, dst->start);
- g_assert_cmphex(src->end, ==, dst->end);
-
- /* Destroy (silently, regardless of options) the dest-list: */
- QTAILQ_FOREACH_SAFE(node, dst->used, MLIST_ENTNAME, tmp) {
- g_free(node);
- }
- QTAILQ_FOREACH_SAFE(node, dst->free, MLIST_ENTNAME, tmp) {
- g_free(node);
- }
-
- tmpused = dst->used;
- tmpfree = dst->free;
-
- /* Inherit the lists of the source allocator: */
- dst->used = src->used;
- dst->free = src->free;
-
- /* Source is now re-initialized, the source memory is 'invalid' now: */
- src->used = tmpused;
- src->free = tmpfree;
- QTAILQ_INIT(src->used);
- QTAILQ_INIT(src->free);
- node = mlist_new(src->start, src->end - src->start);
- QTAILQ_INSERT_HEAD(src->free, node, MLIST_ENTNAME);
- return;
-}
diff --git a/qemu/tests/libqos/malloc.h b/qemu/tests/libqos/malloc.h
deleted file mode 100644
index ae9dac8f6..000000000
--- a/qemu/tests/libqos/malloc.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * libqos malloc support
- *
- * Copyright IBM, Corp. 2012-2013
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef LIBQOS_MALLOC_H
-#define LIBQOS_MALLOC_H
-
-#include "qemu/queue.h"
-
-typedef enum {
- ALLOC_NO_FLAGS = 0x00,
- ALLOC_LEAK_WARN = 0x01,
- ALLOC_LEAK_ASSERT = 0x02,
- ALLOC_PARANOID = 0x04
-} QAllocOpts;
-
-typedef struct QGuestAllocator QGuestAllocator;
-
-void alloc_uninit(QGuestAllocator *allocator);
-
-/* Always returns page aligned values */
-uint64_t guest_alloc(QGuestAllocator *allocator, size_t size);
-void guest_free(QGuestAllocator *allocator, uint64_t addr);
-void migrate_allocator(QGuestAllocator *src, QGuestAllocator *dst);
-
-QGuestAllocator *alloc_init(uint64_t start, uint64_t end);
-QGuestAllocator *alloc_init_flags(QAllocOpts flags,
- uint64_t start, uint64_t end);
-void alloc_set_page_size(QGuestAllocator *allocator, size_t page_size);
-void alloc_set_flags(QGuestAllocator *allocator, QAllocOpts opts);
-
-#endif
diff --git a/qemu/tests/libqos/pci-pc.c b/qemu/tests/libqos/pci-pc.c
deleted file mode 100644
index 77f15e5a0..000000000
--- a/qemu/tests/libqos/pci-pc.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * libqos PCI bindings for PC
- *
- * Copyright IBM, Corp. 2012-2013
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "libqtest.h"
-#include "libqos/pci-pc.h"
-
-#include "hw/pci/pci_regs.h"
-
-#include "qemu-common.h"
-#include "qemu/host-utils.h"
-
-#include <glib.h>
-
-#define ACPI_PCIHP_ADDR 0xae00
-#define PCI_EJ_BASE 0x0008
-
-typedef struct QPCIBusPC
-{
- QPCIBus bus;
-
- uint32_t pci_hole_start;
- uint32_t pci_hole_size;
- uint32_t pci_hole_alloc;
-
- uint16_t pci_iohole_start;
- uint16_t pci_iohole_size;
- uint16_t pci_iohole_alloc;
-} QPCIBusPC;
-
-static uint8_t qpci_pc_io_readb(QPCIBus *bus, void *addr)
-{
- uintptr_t port = (uintptr_t)addr;
- uint8_t value;
-
- if (port < 0x10000) {
- value = inb(port);
- } else {
- value = readb(port);
- }
-
- return value;
-}
-
-static uint16_t qpci_pc_io_readw(QPCIBus *bus, void *addr)
-{
- uintptr_t port = (uintptr_t)addr;
- uint16_t value;
-
- if (port < 0x10000) {
- value = inw(port);
- } else {
- value = readw(port);
- }
-
- return value;
-}
-
-static uint32_t qpci_pc_io_readl(QPCIBus *bus, void *addr)
-{
- uintptr_t port = (uintptr_t)addr;
- uint32_t value;
-
- if (port < 0x10000) {
- value = inl(port);
- } else {
- value = readl(port);
- }
-
- return value;
-}
-
-static void qpci_pc_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
-{
- uintptr_t port = (uintptr_t)addr;
-
- if (port < 0x10000) {
- outb(port, value);
- } else {
- writeb(port, value);
- }
-}
-
-static void qpci_pc_io_writew(QPCIBus *bus, void *addr, uint16_t value)
-{
- uintptr_t port = (uintptr_t)addr;
-
- if (port < 0x10000) {
- outw(port, value);
- } else {
- writew(port, value);
- }
-}
-
-static void qpci_pc_io_writel(QPCIBus *bus, void *addr, uint32_t value)
-{
- uintptr_t port = (uintptr_t)addr;
-
- if (port < 0x10000) {
- outl(port, value);
- } else {
- writel(port, value);
- }
-}
-
-static uint8_t qpci_pc_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
-{
- outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
- return inb(0xcfc);
-}
-
-static uint16_t qpci_pc_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
-{
- outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
- return inw(0xcfc);
-}
-
-static uint32_t qpci_pc_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
-{
- outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
- return inl(0xcfc);
-}
-
-static void qpci_pc_config_writeb(QPCIBus *bus, int devfn, uint8_t offset, uint8_t value)
-{
- outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
- outb(0xcfc, value);
-}
-
-static void qpci_pc_config_writew(QPCIBus *bus, int devfn, uint8_t offset, uint16_t value)
-{
- outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
- outw(0xcfc, value);
-}
-
-static void qpci_pc_config_writel(QPCIBus *bus, int devfn, uint8_t offset, uint32_t value)
-{
- outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
- outl(0xcfc, value);
-}
-
-static void *qpci_pc_iomap(QPCIBus *bus, QPCIDevice *dev, int barno, uint64_t *sizeptr)
-{
- QPCIBusPC *s = container_of(bus, QPCIBusPC, bus);
- static const int bar_reg_map[] = {
- PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
- PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
- };
- int bar_reg;
- uint32_t addr;
- uint64_t size;
- uint32_t io_type;
-
- g_assert(barno >= 0 && barno <= 5);
- bar_reg = bar_reg_map[barno];
-
- qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
- addr = qpci_config_readl(dev, bar_reg);
-
- io_type = addr & PCI_BASE_ADDRESS_SPACE;
- if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
- addr &= PCI_BASE_ADDRESS_IO_MASK;
- } else {
- addr &= PCI_BASE_ADDRESS_MEM_MASK;
- }
-
- size = (1ULL << ctzl(addr));
- if (size == 0) {
- return NULL;
- }
- if (sizeptr) {
- *sizeptr = size;
- }
-
- if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
- uint16_t loc;
-
- g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
- <= s->pci_iohole_size);
- s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
- loc = s->pci_iohole_start + s->pci_iohole_alloc;
- s->pci_iohole_alloc += size;
-
- qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
-
- return (void *)(intptr_t)loc;
- } else {
- uint64_t loc;
-
- g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
- <= s->pci_hole_size);
- s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
- loc = s->pci_hole_start + s->pci_hole_alloc;
- s->pci_hole_alloc += size;
-
- qpci_config_writel(dev, bar_reg, loc);
-
- return (void *)(intptr_t)loc;
- }
-}
-
-static void qpci_pc_iounmap(QPCIBus *bus, void *data)
-{
- /* FIXME */
-}
-
-QPCIBus *qpci_init_pc(void)
-{
- QPCIBusPC *ret;
-
- ret = g_malloc(sizeof(*ret));
-
- ret->bus.io_readb = qpci_pc_io_readb;
- ret->bus.io_readw = qpci_pc_io_readw;
- ret->bus.io_readl = qpci_pc_io_readl;
-
- ret->bus.io_writeb = qpci_pc_io_writeb;
- ret->bus.io_writew = qpci_pc_io_writew;
- ret->bus.io_writel = qpci_pc_io_writel;
-
- ret->bus.config_readb = qpci_pc_config_readb;
- ret->bus.config_readw = qpci_pc_config_readw;
- ret->bus.config_readl = qpci_pc_config_readl;
-
- ret->bus.config_writeb = qpci_pc_config_writeb;
- ret->bus.config_writew = qpci_pc_config_writew;
- ret->bus.config_writel = qpci_pc_config_writel;
-
- ret->bus.iomap = qpci_pc_iomap;
- ret->bus.iounmap = qpci_pc_iounmap;
-
- ret->pci_hole_start = 0xE0000000;
- ret->pci_hole_size = 0x20000000;
- ret->pci_hole_alloc = 0;
-
- ret->pci_iohole_start = 0xc000;
- ret->pci_iohole_size = 0x4000;
- ret->pci_iohole_alloc = 0;
-
- return &ret->bus;
-}
-
-void qpci_free_pc(QPCIBus *bus)
-{
- QPCIBusPC *s = container_of(bus, QPCIBusPC, bus);
-
- g_free(s);
-}
-
-void qpci_plug_device_test(const char *driver, const char *id,
- uint8_t slot, const char *opts)
-{
- QDict *response;
- char *cmd;
-
- cmd = g_strdup_printf("{'execute': 'device_add',"
- " 'arguments': {"
- " 'driver': '%s',"
- " 'addr': '%d',"
- " %s%s"
- " 'id': '%s'"
- "}}", driver, slot,
- opts ? opts : "", opts ? "," : "",
- id);
- response = qmp(cmd);
- g_free(cmd);
- g_assert(response);
- g_assert(!qdict_haskey(response, "error"));
- QDECREF(response);
-}
-
-void qpci_unplug_acpi_device_test(const char *id, uint8_t slot)
-{
- QDict *response;
- char *cmd;
-
- cmd = g_strdup_printf("{'execute': 'device_del',"
- " 'arguments': {"
- " 'id': '%s'"
- "}}", id);
- response = qmp(cmd);
- g_free(cmd);
- g_assert(response);
- g_assert(!qdict_haskey(response, "error"));
- QDECREF(response);
-
- outb(ACPI_PCIHP_ADDR + PCI_EJ_BASE, 1 << slot);
-
- response = qmp("");
- g_assert(response);
- g_assert(qdict_haskey(response, "event"));
- g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED"));
- QDECREF(response);
-}
diff --git a/qemu/tests/libqos/pci-pc.h b/qemu/tests/libqos/pci-pc.h
deleted file mode 100644
index 26211790c..000000000
--- a/qemu/tests/libqos/pci-pc.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * libqos PCI bindings for PC
- *
- * Copyright IBM, Corp. 2012-2013
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef LIBQOS_PCI_PC_H
-#define LIBQOS_PCI_PC_H
-
-#include "libqos/pci.h"
-
-QPCIBus *qpci_init_pc(void);
-void qpci_free_pc(QPCIBus *bus);
-
-#endif
diff --git a/qemu/tests/libqos/pci.c b/qemu/tests/libqos/pci.c
deleted file mode 100644
index 0e104e14e..000000000
--- a/qemu/tests/libqos/pci.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * libqos PCI bindings
- *
- * Copyright IBM, Corp. 2012-2013
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "libqos/pci.h"
-
-#include "hw/pci/pci_regs.h"
-#include <glib.h>
-
-void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
- void (*func)(QPCIDevice *dev, int devfn, void *data),
- void *data)
-{
- int slot;
-
- for (slot = 0; slot < 32; slot++) {
- int fn;
-
- for (fn = 0; fn < 8; fn++) {
- QPCIDevice *dev;
-
- dev = qpci_device_find(bus, QPCI_DEVFN(slot, fn));
- if (!dev) {
- continue;
- }
-
- if (vendor_id != -1 &&
- qpci_config_readw(dev, PCI_VENDOR_ID) != vendor_id) {
- g_free(dev);
- continue;
- }
-
- if (device_id != -1 &&
- qpci_config_readw(dev, PCI_DEVICE_ID) != device_id) {
- g_free(dev);
- continue;
- }
-
- func(dev, QPCI_DEVFN(slot, fn), data);
- }
- }
-}
-
-QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn)
-{
- QPCIDevice *dev;
-
- dev = g_malloc0(sizeof(*dev));
- dev->bus = bus;
- dev->devfn = devfn;
-
- if (qpci_config_readw(dev, PCI_VENDOR_ID) == 0xFFFF) {
- g_free(dev);
- return NULL;
- }
-
- return dev;
-}
-
-void qpci_device_enable(QPCIDevice *dev)
-{
- uint16_t cmd;
-
- /* FIXME -- does this need to be a bus callout? */
- cmd = qpci_config_readw(dev, PCI_COMMAND);
- cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
- qpci_config_writew(dev, PCI_COMMAND, cmd);
-
- /* Verify the bits are now set. */
- cmd = qpci_config_readw(dev, PCI_COMMAND);
- g_assert_cmphex(cmd & PCI_COMMAND_IO, ==, PCI_COMMAND_IO);
- g_assert_cmphex(cmd & PCI_COMMAND_MEMORY, ==, PCI_COMMAND_MEMORY);
- g_assert_cmphex(cmd & PCI_COMMAND_MASTER, ==, PCI_COMMAND_MASTER);
-}
-
-uint8_t qpci_find_capability(QPCIDevice *dev, uint8_t id)
-{
- uint8_t cap;
- uint8_t addr = qpci_config_readb(dev, PCI_CAPABILITY_LIST);
-
- do {
- cap = qpci_config_readb(dev, addr);
- if (cap != id) {
- addr = qpci_config_readb(dev, addr + PCI_CAP_LIST_NEXT);
- }
- } while (cap != id && addr != 0);
-
- return addr;
-}
-
-void qpci_msix_enable(QPCIDevice *dev)
-{
- uint8_t addr;
- uint16_t val;
- uint32_t table;
- uint8_t bir_table;
- uint8_t bir_pba;
- void *offset;
-
- addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX);
- g_assert_cmphex(addr, !=, 0);
-
- val = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
- qpci_config_writew(dev, addr + PCI_MSIX_FLAGS, val | PCI_MSIX_FLAGS_ENABLE);
-
- table = qpci_config_readl(dev, addr + PCI_MSIX_TABLE);
- bir_table = table & PCI_MSIX_FLAGS_BIRMASK;
- offset = qpci_iomap(dev, bir_table, NULL);
- dev->msix_table = offset + (table & ~PCI_MSIX_FLAGS_BIRMASK);
-
- table = qpci_config_readl(dev, addr + PCI_MSIX_PBA);
- bir_pba = table & PCI_MSIX_FLAGS_BIRMASK;
- if (bir_pba != bir_table) {
- offset = qpci_iomap(dev, bir_pba, NULL);
- }
- dev->msix_pba = offset + (table & ~PCI_MSIX_FLAGS_BIRMASK);
-
- g_assert(dev->msix_table != NULL);
- g_assert(dev->msix_pba != NULL);
- dev->msix_enabled = true;
-}
-
-void qpci_msix_disable(QPCIDevice *dev)
-{
- uint8_t addr;
- uint16_t val;
-
- g_assert(dev->msix_enabled);
- addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX);
- g_assert_cmphex(addr, !=, 0);
- val = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
- qpci_config_writew(dev, addr + PCI_MSIX_FLAGS,
- val & ~PCI_MSIX_FLAGS_ENABLE);
-
- qpci_iounmap(dev, dev->msix_table);
- qpci_iounmap(dev, dev->msix_pba);
- dev->msix_enabled = 0;
- dev->msix_table = NULL;
- dev->msix_pba = NULL;
-}
-
-bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry)
-{
- uint32_t pba_entry;
- uint8_t bit_n = entry % 32;
- void *addr = dev->msix_pba + (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4;
-
- g_assert(dev->msix_enabled);
- pba_entry = qpci_io_readl(dev, addr);
- qpci_io_writel(dev, addr, pba_entry & ~(1 << bit_n));
- return (pba_entry & (1 << bit_n)) != 0;
-}
-
-bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
-{
- uint8_t addr;
- uint16_t val;
- void *vector_addr = dev->msix_table + (entry * PCI_MSIX_ENTRY_SIZE);
-
- g_assert(dev->msix_enabled);
- addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX);
- g_assert_cmphex(addr, !=, 0);
- val = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
-
- if (val & PCI_MSIX_FLAGS_MASKALL) {
- return true;
- } else {
- return (qpci_io_readl(dev, vector_addr + PCI_MSIX_ENTRY_VECTOR_CTRL)
- & PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0;
- }
-}
-
-uint16_t qpci_msix_table_size(QPCIDevice *dev)
-{
- uint8_t addr;
- uint16_t control;
-
- addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX);
- g_assert_cmphex(addr, !=, 0);
-
- control = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
- return (control & PCI_MSIX_FLAGS_QSIZE) + 1;
-}
-
-uint8_t qpci_config_readb(QPCIDevice *dev, uint8_t offset)
-{
- return dev->bus->config_readb(dev->bus, dev->devfn, offset);
-}
-
-uint16_t qpci_config_readw(QPCIDevice *dev, uint8_t offset)
-{
- return dev->bus->config_readw(dev->bus, dev->devfn, offset);
-}
-
-uint32_t qpci_config_readl(QPCIDevice *dev, uint8_t offset)
-{
- return dev->bus->config_readl(dev->bus, dev->devfn, offset);
-}
-
-
-void qpci_config_writeb(QPCIDevice *dev, uint8_t offset, uint8_t value)
-{
- dev->bus->config_writeb(dev->bus, dev->devfn, offset, value);
-}
-
-void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value)
-{
- dev->bus->config_writew(dev->bus, dev->devfn, offset, value);
-}
-
-void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
-{
- dev->bus->config_writel(dev->bus, dev->devfn, offset, value);
-}
-
-
-uint8_t qpci_io_readb(QPCIDevice *dev, void *data)
-{
- return dev->bus->io_readb(dev->bus, data);
-}
-
-uint16_t qpci_io_readw(QPCIDevice *dev, void *data)
-{
- return dev->bus->io_readw(dev->bus, data);
-}
-
-uint32_t qpci_io_readl(QPCIDevice *dev, void *data)
-{
- return dev->bus->io_readl(dev->bus, data);
-}
-
-
-void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value)
-{
- dev->bus->io_writeb(dev->bus, data, value);
-}
-
-void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value)
-{
- dev->bus->io_writew(dev->bus, data, value);
-}
-
-void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
-{
- dev->bus->io_writel(dev->bus, data, value);
-}
-
-void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
-{
- return dev->bus->iomap(dev->bus, dev, barno, sizeptr);
-}
-
-void qpci_iounmap(QPCIDevice *dev, void *data)
-{
- dev->bus->iounmap(dev->bus, data);
-}
-
-
diff --git a/qemu/tests/libqos/pci.h b/qemu/tests/libqos/pci.h
deleted file mode 100644
index c06add8db..000000000
--- a/qemu/tests/libqos/pci.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * libqos PCI bindings
- *
- * Copyright IBM, Corp. 2012-2013
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef LIBQOS_PCI_H
-#define LIBQOS_PCI_H
-
-#include "libqtest.h"
-
-#define QPCI_DEVFN(dev, fn) (((dev) << 3) | (fn))
-
-typedef struct QPCIDevice QPCIDevice;
-typedef struct QPCIBus QPCIBus;
-
-struct QPCIBus
-{
- uint8_t (*io_readb)(QPCIBus *bus, void *addr);
- uint16_t (*io_readw)(QPCIBus *bus, void *addr);
- uint32_t (*io_readl)(QPCIBus *bus, void *addr);
-
- void (*io_writeb)(QPCIBus *bus, void *addr, uint8_t value);
- void (*io_writew)(QPCIBus *bus, void *addr, uint16_t value);
- void (*io_writel)(QPCIBus *bus, void *addr, uint32_t value);
-
- uint8_t (*config_readb)(QPCIBus *bus, int devfn, uint8_t offset);
- uint16_t (*config_readw)(QPCIBus *bus, int devfn, uint8_t offset);
- uint32_t (*config_readl)(QPCIBus *bus, int devfn, uint8_t offset);
-
- void (*config_writeb)(QPCIBus *bus, int devfn,
- uint8_t offset, uint8_t value);
- void (*config_writew)(QPCIBus *bus, int devfn,
- uint8_t offset, uint16_t value);
- void (*config_writel)(QPCIBus *bus, int devfn,
- uint8_t offset, uint32_t value);
-
- void *(*iomap)(QPCIBus *bus, QPCIDevice *dev, int barno, uint64_t *sizeptr);
- void (*iounmap)(QPCIBus *bus, void *data);
-};
-
-struct QPCIDevice
-{
- QPCIBus *bus;
- int devfn;
- bool msix_enabled;
- void *msix_table;
- void *msix_pba;
-};
-
-void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
- void (*func)(QPCIDevice *dev, int devfn, void *data),
- void *data);
-QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn);
-
-void qpci_device_enable(QPCIDevice *dev);
-uint8_t qpci_find_capability(QPCIDevice *dev, uint8_t id);
-void qpci_msix_enable(QPCIDevice *dev);
-void qpci_msix_disable(QPCIDevice *dev);
-bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry);
-bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry);
-uint16_t qpci_msix_table_size(QPCIDevice *dev);
-
-uint8_t qpci_config_readb(QPCIDevice *dev, uint8_t offset);
-uint16_t qpci_config_readw(QPCIDevice *dev, uint8_t offset);
-uint32_t qpci_config_readl(QPCIDevice *dev, uint8_t offset);
-
-void qpci_config_writeb(QPCIDevice *dev, uint8_t offset, uint8_t value);
-void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value);
-void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value);
-
-uint8_t qpci_io_readb(QPCIDevice *dev, void *data);
-uint16_t qpci_io_readw(QPCIDevice *dev, void *data);
-uint32_t qpci_io_readl(QPCIDevice *dev, void *data);
-
-void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value);
-void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value);
-void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value);
-
-void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr);
-void qpci_iounmap(QPCIDevice *dev, void *data);
-
-void qpci_plug_device_test(const char *driver, const char *id,
- uint8_t slot, const char *opts);
-void qpci_unplug_acpi_device_test(const char *id, uint8_t slot);
-#endif
diff --git a/qemu/tests/libqos/usb.c b/qemu/tests/libqos/usb.c
deleted file mode 100644
index 87efb9078..000000000
--- a/qemu/tests/libqos/usb.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * common code shared by usb tests
- *
- * Copyright (c) 2014 Red Hat, Inc
- *
- * Authors:
- * Gerd Hoffmann <kraxel@redhat.com>
- * John Snow <jsnow@redhat.com>
- * Igor Mammedov <imammedo@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-#include "qemu/osdep.h"
-#include <glib.h>
-#include "libqtest.h"
-#include "hw/usb/uhci-regs.h"
-#include "libqos/usb.h"
-
-void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc, uint32_t devfn, int bar)
-{
- hc->dev = qpci_device_find(pcibus, devfn);
- g_assert(hc->dev != NULL);
- qpci_device_enable(hc->dev);
- hc->base = qpci_iomap(hc->dev, bar, NULL);
- g_assert(hc->base != NULL);
-}
-
-void uhci_port_test(struct qhc *hc, int port, uint16_t expect)
-{
- void *addr = hc->base + 0x10 + 2 * port;
- uint16_t value = qpci_io_readw(hc->dev, addr);
- uint16_t mask = ~(UHCI_PORT_WRITE_CLEAR | UHCI_PORT_RSVD1);
-
- g_assert((value & mask) == (expect & mask));
-}
-
-void usb_test_hotplug(const char *hcd_id, const int port,
- void (*port_check)(void))
-{
- QDict *response;
- char *cmd;
-
- cmd = g_strdup_printf("{'execute': 'device_add',"
- " 'arguments': {"
- " 'driver': 'usb-tablet',"
- " 'port': '%d',"
- " 'bus': '%s.0',"
- " 'id': 'usbdev%d'"
- "}}", port, hcd_id, port);
- response = qmp(cmd);
- g_free(cmd);
- g_assert(response);
- g_assert(!qdict_haskey(response, "error"));
- QDECREF(response);
-
- if (port_check) {
- port_check();
- }
-
- cmd = g_strdup_printf("{'execute': 'device_del',"
- " 'arguments': {"
- " 'id': 'usbdev%d'"
- "}}", port);
- response = qmp(cmd);
- g_free(cmd);
- g_assert(response);
- g_assert(qdict_haskey(response, "event"));
- g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED"));
-}
diff --git a/qemu/tests/libqos/usb.h b/qemu/tests/libqos/usb.h
deleted file mode 100644
index 8fe56872b..000000000
--- a/qemu/tests/libqos/usb.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef LIBQOS_USB_H
-#define LIBQOS_USB_H
-
-#include "libqos/pci-pc.h"
-
-struct qhc {
- QPCIDevice *dev;
- void *base;
-};
-
-void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc,
- uint32_t devfn, int bar);
-void uhci_port_test(struct qhc *hc, int port, uint16_t expect);
-
-void usb_test_hotplug(const char *bus_name, const int port,
- void (*port_check)(void));
-#endif
diff --git a/qemu/tests/libqos/virtio-mmio.c b/qemu/tests/libqos/virtio-mmio.c
deleted file mode 100644
index a4382f366..000000000
--- a/qemu/tests/libqos/virtio-mmio.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * libqos virtio MMIO driver
- *
- * Copyright (c) 2014 Marc Marí
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include <glib.h>
-#include "libqtest.h"
-#include "libqos/virtio.h"
-#include "libqos/virtio-mmio.h"
-#include "libqos/malloc.h"
-#include "libqos/malloc-generic.h"
-
-static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t addr)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- return readb(dev->addr + addr);
-}
-
-static uint16_t qvirtio_mmio_config_readw(QVirtioDevice *d, uint64_t addr)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- return readw(dev->addr + addr);
-}
-
-static uint32_t qvirtio_mmio_config_readl(QVirtioDevice *d, uint64_t addr)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- return readl(dev->addr + addr);
-}
-
-static uint64_t qvirtio_mmio_config_readq(QVirtioDevice *d, uint64_t addr)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- return readq(dev->addr + addr);
-}
-
-static uint32_t qvirtio_mmio_get_features(QVirtioDevice *d)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- writel(dev->addr + QVIRTIO_MMIO_HOST_FEATURES_SEL, 0);
- return readl(dev->addr + QVIRTIO_MMIO_HOST_FEATURES);
-}
-
-static void qvirtio_mmio_set_features(QVirtioDevice *d, uint32_t features)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- dev->features = features;
- writel(dev->addr + QVIRTIO_MMIO_GUEST_FEATURES_SEL, 0);
- writel(dev->addr + QVIRTIO_MMIO_GUEST_FEATURES, features);
-}
-
-static uint32_t qvirtio_mmio_get_guest_features(QVirtioDevice *d)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- return dev->features;
-}
-
-static uint8_t qvirtio_mmio_get_status(QVirtioDevice *d)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- return (uint8_t)readl(dev->addr + QVIRTIO_MMIO_DEVICE_STATUS);
-}
-
-static void qvirtio_mmio_set_status(QVirtioDevice *d, uint8_t status)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- writel(dev->addr + QVIRTIO_MMIO_DEVICE_STATUS, (uint32_t)status);
-}
-
-static bool qvirtio_mmio_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- uint32_t isr;
-
- isr = readl(dev->addr + QVIRTIO_MMIO_INTERRUPT_STATUS) & 1;
- if (isr != 0) {
- writel(dev->addr + QVIRTIO_MMIO_INTERRUPT_ACK, 1);
- return true;
- }
-
- return false;
-}
-
-static bool qvirtio_mmio_get_config_isr_status(QVirtioDevice *d)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- uint32_t isr;
-
- isr = readl(dev->addr + QVIRTIO_MMIO_INTERRUPT_STATUS) & 2;
- if (isr != 0) {
- writel(dev->addr + QVIRTIO_MMIO_INTERRUPT_ACK, 2);
- return true;
- }
-
- return false;
-}
-
-static void qvirtio_mmio_queue_select(QVirtioDevice *d, uint16_t index)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- writel(dev->addr + QVIRTIO_MMIO_QUEUE_SEL, (uint32_t)index);
-
- g_assert_cmphex(readl(dev->addr + QVIRTIO_MMIO_QUEUE_PFN), ==, 0);
-}
-
-static uint16_t qvirtio_mmio_get_queue_size(QVirtioDevice *d)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- return (uint16_t)readl(dev->addr + QVIRTIO_MMIO_QUEUE_NUM_MAX);
-}
-
-static void qvirtio_mmio_set_queue_address(QVirtioDevice *d, uint32_t pfn)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- writel(dev->addr + QVIRTIO_MMIO_QUEUE_PFN, pfn);
-}
-
-static QVirtQueue *qvirtio_mmio_virtqueue_setup(QVirtioDevice *d,
- QGuestAllocator *alloc, uint16_t index)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- QVirtQueue *vq;
- uint64_t addr;
-
- vq = g_malloc0(sizeof(*vq));
- qvirtio_mmio_queue_select(d, index);
- writel(dev->addr + QVIRTIO_MMIO_QUEUE_ALIGN, dev->page_size);
-
- vq->index = index;
- vq->size = qvirtio_mmio_get_queue_size(d);
- vq->free_head = 0;
- vq->num_free = vq->size;
- vq->align = dev->page_size;
- vq->indirect = (dev->features & QVIRTIO_F_RING_INDIRECT_DESC) != 0;
- vq->event = (dev->features & QVIRTIO_F_RING_EVENT_IDX) != 0;
-
- writel(dev->addr + QVIRTIO_MMIO_QUEUE_NUM, vq->size);
-
- /* Check different than 0 */
- g_assert_cmpint(vq->size, !=, 0);
-
- /* Check power of 2 */
- g_assert_cmpint(vq->size & (vq->size - 1), ==, 0);
-
- addr = guest_alloc(alloc, qvring_size(vq->size, dev->page_size));
- qvring_init(alloc, vq, addr);
- qvirtio_mmio_set_queue_address(d, vq->desc / dev->page_size);
-
- return vq;
-}
-
-static void qvirtio_mmio_virtqueue_kick(QVirtioDevice *d, QVirtQueue *vq)
-{
- QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
- writel(dev->addr + QVIRTIO_MMIO_QUEUE_NOTIFY, vq->index);
-}
-
-const QVirtioBus qvirtio_mmio = {
- .config_readb = qvirtio_mmio_config_readb,
- .config_readw = qvirtio_mmio_config_readw,
- .config_readl = qvirtio_mmio_config_readl,
- .config_readq = qvirtio_mmio_config_readq,
- .get_features = qvirtio_mmio_get_features,
- .set_features = qvirtio_mmio_set_features,
- .get_guest_features = qvirtio_mmio_get_guest_features,
- .get_status = qvirtio_mmio_get_status,
- .set_status = qvirtio_mmio_set_status,
- .get_queue_isr_status = qvirtio_mmio_get_queue_isr_status,
- .get_config_isr_status = qvirtio_mmio_get_config_isr_status,
- .queue_select = qvirtio_mmio_queue_select,
- .get_queue_size = qvirtio_mmio_get_queue_size,
- .set_queue_address = qvirtio_mmio_set_queue_address,
- .virtqueue_setup = qvirtio_mmio_virtqueue_setup,
- .virtqueue_kick = qvirtio_mmio_virtqueue_kick,
-};
-
-QVirtioMMIODevice *qvirtio_mmio_init_device(uint64_t addr, uint32_t page_size)
-{
- QVirtioMMIODevice *dev;
- uint32_t magic;
- dev = g_malloc0(sizeof(*dev));
-
- magic = readl(addr + QVIRTIO_MMIO_MAGIC_VALUE);
- g_assert(magic == ('v' | 'i' << 8 | 'r' << 16 | 't' << 24));
-
- dev->addr = addr;
- dev->page_size = page_size;
- dev->vdev.device_type = readl(addr + QVIRTIO_MMIO_DEVICE_ID);
-
- writel(addr + QVIRTIO_MMIO_GUEST_PAGE_SIZE, page_size);
-
- return dev;
-}
diff --git a/qemu/tests/libqos/virtio-mmio.h b/qemu/tests/libqos/virtio-mmio.h
deleted file mode 100644
index e3e52b9ce..000000000
--- a/qemu/tests/libqos/virtio-mmio.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * libqos virtio MMIO definitions
- *
- * Copyright (c) 2014 Marc Marí
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef LIBQOS_VIRTIO_MMIO_H
-#define LIBQOS_VIRTIO_MMIO_H
-
-#include "libqos/virtio.h"
-
-#define QVIRTIO_MMIO_MAGIC_VALUE 0x000
-#define QVIRTIO_MMIO_VERSION 0x004
-#define QVIRTIO_MMIO_DEVICE_ID 0x008
-#define QVIRTIO_MMIO_VENDOR_ID 0x00C
-#define QVIRTIO_MMIO_HOST_FEATURES 0x010
-#define QVIRTIO_MMIO_HOST_FEATURES_SEL 0x014
-#define QVIRTIO_MMIO_GUEST_FEATURES 0x020
-#define QVIRTIO_MMIO_GUEST_FEATURES_SEL 0x024
-#define QVIRTIO_MMIO_GUEST_PAGE_SIZE 0x028
-#define QVIRTIO_MMIO_QUEUE_SEL 0x030
-#define QVIRTIO_MMIO_QUEUE_NUM_MAX 0x034
-#define QVIRTIO_MMIO_QUEUE_NUM 0x038
-#define QVIRTIO_MMIO_QUEUE_ALIGN 0x03C
-#define QVIRTIO_MMIO_QUEUE_PFN 0x040
-#define QVIRTIO_MMIO_QUEUE_NOTIFY 0x050
-#define QVIRTIO_MMIO_INTERRUPT_STATUS 0x060
-#define QVIRTIO_MMIO_INTERRUPT_ACK 0x064
-#define QVIRTIO_MMIO_DEVICE_STATUS 0x070
-#define QVIRTIO_MMIO_DEVICE_SPECIFIC 0x100
-
-typedef struct QVirtioMMIODevice {
- QVirtioDevice vdev;
- uint64_t addr;
- uint32_t page_size;
- uint32_t features; /* As it cannot be read later, save it */
-} QVirtioMMIODevice;
-
-extern const QVirtioBus qvirtio_mmio;
-
-QVirtioMMIODevice *qvirtio_mmio_init_device(uint64_t addr, uint32_t page_size);
-
-#endif
diff --git a/qemu/tests/libqos/virtio-pci.c b/qemu/tests/libqos/virtio-pci.c
deleted file mode 100644
index fde2ff0bc..000000000
--- a/qemu/tests/libqos/virtio-pci.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * libqos virtio PCI driver
- *
- * Copyright (c) 2014 Marc Marí
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include <glib.h>
-#include "libqtest.h"
-#include "libqos/virtio.h"
-#include "libqos/virtio-pci.h"
-#include "libqos/pci.h"
-#include "libqos/pci-pc.h"
-#include "libqos/malloc.h"
-#include "libqos/malloc-pc.h"
-
-#include "hw/pci/pci_regs.h"
-
-typedef struct QVirtioPCIForeachData {
- void (*func)(QVirtioDevice *d, void *data);
- uint16_t device_type;
- void *user_data;
-} QVirtioPCIForeachData;
-
-static QVirtioPCIDevice *qpcidevice_to_qvirtiodevice(QPCIDevice *pdev)
-{
- QVirtioPCIDevice *vpcidev;
- vpcidev = g_malloc0(sizeof(*vpcidev));
-
- if (pdev) {
- vpcidev->pdev = pdev;
- vpcidev->vdev.device_type =
- qpci_config_readw(vpcidev->pdev, PCI_SUBSYSTEM_ID);
- }
-
- vpcidev->config_msix_entry = -1;
-
- return vpcidev;
-}
-
-static void qvirtio_pci_foreach_callback(
- QPCIDevice *dev, int devfn, void *data)
-{
- QVirtioPCIForeachData *d = data;
- QVirtioPCIDevice *vpcidev = qpcidevice_to_qvirtiodevice(dev);
-
- if (vpcidev->vdev.device_type == d->device_type) {
- d->func(&vpcidev->vdev, d->user_data);
- } else {
- g_free(vpcidev);
- }
-}
-
-static void qvirtio_pci_assign_device(QVirtioDevice *d, void *data)
-{
- QVirtioPCIDevice **vpcidev = data;
- *vpcidev = (QVirtioPCIDevice *)d;
-}
-
-static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t addr)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- return qpci_io_readb(dev->pdev, (void *)(uintptr_t)addr);
-}
-
-static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t addr)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- return qpci_io_readw(dev->pdev, (void *)(uintptr_t)addr);
-}
-
-static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t addr)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- return qpci_io_readl(dev->pdev, (void *)(uintptr_t)addr);
-}
-
-static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t addr)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- int i;
- uint64_t u64 = 0;
-
- if (qtest_big_endian()) {
- for (i = 0; i < 8; ++i) {
- u64 |= (uint64_t)qpci_io_readb(dev->pdev,
- (void *)(uintptr_t)addr + i) << (7 - i) * 8;
- }
- } else {
- for (i = 0; i < 8; ++i) {
- u64 |= (uint64_t)qpci_io_readb(dev->pdev,
- (void *)(uintptr_t)addr + i) << i * 8;
- }
- }
-
- return u64;
-}
-
-static uint32_t qvirtio_pci_get_features(QVirtioDevice *d)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- return qpci_io_readl(dev->pdev, dev->addr + QVIRTIO_PCI_DEVICE_FEATURES);
-}
-
-static void qvirtio_pci_set_features(QVirtioDevice *d, uint32_t features)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- qpci_io_writel(dev->pdev, dev->addr + QVIRTIO_PCI_GUEST_FEATURES, features);
-}
-
-static uint32_t qvirtio_pci_get_guest_features(QVirtioDevice *d)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- return qpci_io_readl(dev->pdev, dev->addr + QVIRTIO_PCI_GUEST_FEATURES);
-}
-
-static uint8_t qvirtio_pci_get_status(QVirtioDevice *d)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_PCI_DEVICE_STATUS);
-}
-
-static void qvirtio_pci_set_status(QVirtioDevice *d, uint8_t status)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- qpci_io_writeb(dev->pdev, dev->addr + QVIRTIO_PCI_DEVICE_STATUS, status);
-}
-
-static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- QVirtQueuePCI *vqpci = (QVirtQueuePCI *)vq;
- uint32_t data;
-
- if (dev->pdev->msix_enabled) {
- g_assert_cmpint(vqpci->msix_entry, !=, -1);
- if (qpci_msix_masked(dev->pdev, vqpci->msix_entry)) {
- /* No ISR checking should be done if masked, but read anyway */
- return qpci_msix_pending(dev->pdev, vqpci->msix_entry);
- } else {
- data = readl(vqpci->msix_addr);
- if (data == vqpci->msix_data) {
- writel(vqpci->msix_addr, 0);
- return true;
- } else {
- return false;
- }
- }
- } else {
- return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_PCI_ISR_STATUS) & 1;
- }
-}
-
-static bool qvirtio_pci_get_config_isr_status(QVirtioDevice *d)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- uint32_t data;
-
- if (dev->pdev->msix_enabled) {
- g_assert_cmpint(dev->config_msix_entry, !=, -1);
- if (qpci_msix_masked(dev->pdev, dev->config_msix_entry)) {
- /* No ISR checking should be done if masked, but read anyway */
- return qpci_msix_pending(dev->pdev, dev->config_msix_entry);
- } else {
- data = readl(dev->config_msix_addr);
- if (data == dev->config_msix_data) {
- writel(dev->config_msix_addr, 0);
- return true;
- } else {
- return false;
- }
- }
- } else {
- return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_PCI_ISR_STATUS) & 2;
- }
-}
-
-static void qvirtio_pci_queue_select(QVirtioDevice *d, uint16_t index)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- qpci_io_writeb(dev->pdev, dev->addr + QVIRTIO_PCI_QUEUE_SELECT, index);
-}
-
-static uint16_t qvirtio_pci_get_queue_size(QVirtioDevice *d)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- return qpci_io_readw(dev->pdev, dev->addr + QVIRTIO_PCI_QUEUE_SIZE);
-}
-
-static void qvirtio_pci_set_queue_address(QVirtioDevice *d, uint32_t pfn)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- qpci_io_writel(dev->pdev, dev->addr + QVIRTIO_PCI_QUEUE_ADDRESS, pfn);
-}
-
-static QVirtQueue *qvirtio_pci_virtqueue_setup(QVirtioDevice *d,
- QGuestAllocator *alloc, uint16_t index)
-{
- uint32_t feat;
- uint64_t addr;
- QVirtQueuePCI *vqpci;
-
- vqpci = g_malloc0(sizeof(*vqpci));
- feat = qvirtio_pci_get_guest_features(d);
-
- qvirtio_pci_queue_select(d, index);
- vqpci->vq.index = index;
- vqpci->vq.size = qvirtio_pci_get_queue_size(d);
- vqpci->vq.free_head = 0;
- vqpci->vq.num_free = vqpci->vq.size;
- vqpci->vq.align = QVIRTIO_PCI_ALIGN;
- vqpci->vq.indirect = (feat & QVIRTIO_F_RING_INDIRECT_DESC) != 0;
- vqpci->vq.event = (feat & QVIRTIO_F_RING_EVENT_IDX) != 0;
-
- vqpci->msix_entry = -1;
- vqpci->msix_addr = 0;
- vqpci->msix_data = 0x12345678;
-
- /* Check different than 0 */
- g_assert_cmpint(vqpci->vq.size, !=, 0);
-
- /* Check power of 2 */
- g_assert_cmpint(vqpci->vq.size & (vqpci->vq.size - 1), ==, 0);
-
- addr = guest_alloc(alloc, qvring_size(vqpci->vq.size, QVIRTIO_PCI_ALIGN));
- qvring_init(alloc, &vqpci->vq, addr);
- qvirtio_pci_set_queue_address(d, vqpci->vq.desc / QVIRTIO_PCI_ALIGN);
-
- return &vqpci->vq;
-}
-
-static void qvirtio_pci_virtqueue_kick(QVirtioDevice *d, QVirtQueue *vq)
-{
- QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- qpci_io_writew(dev->pdev, dev->addr + QVIRTIO_PCI_QUEUE_NOTIFY, vq->index);
-}
-
-const QVirtioBus qvirtio_pci = {
- .config_readb = qvirtio_pci_config_readb,
- .config_readw = qvirtio_pci_config_readw,
- .config_readl = qvirtio_pci_config_readl,
- .config_readq = qvirtio_pci_config_readq,
- .get_features = qvirtio_pci_get_features,
- .set_features = qvirtio_pci_set_features,
- .get_guest_features = qvirtio_pci_get_guest_features,
- .get_status = qvirtio_pci_get_status,
- .set_status = qvirtio_pci_set_status,
- .get_queue_isr_status = qvirtio_pci_get_queue_isr_status,
- .get_config_isr_status = qvirtio_pci_get_config_isr_status,
- .queue_select = qvirtio_pci_queue_select,
- .get_queue_size = qvirtio_pci_get_queue_size,
- .set_queue_address = qvirtio_pci_set_queue_address,
- .virtqueue_setup = qvirtio_pci_virtqueue_setup,
- .virtqueue_kick = qvirtio_pci_virtqueue_kick,
-};
-
-void qvirtio_pci_foreach(QPCIBus *bus, uint16_t device_type,
- void (*func)(QVirtioDevice *d, void *data), void *data)
-{
- QVirtioPCIForeachData d = { .func = func,
- .device_type = device_type,
- .user_data = data };
-
- qpci_device_foreach(bus, QVIRTIO_VENDOR_ID, -1,
- qvirtio_pci_foreach_callback, &d);
-}
-
-QVirtioPCIDevice *qvirtio_pci_device_find(QPCIBus *bus, uint16_t device_type)
-{
- QVirtioPCIDevice *dev = NULL;
- qvirtio_pci_foreach(bus, device_type, qvirtio_pci_assign_device, &dev);
-
- return dev;
-}
-
-void qvirtio_pci_device_enable(QVirtioPCIDevice *d)
-{
- qpci_device_enable(d->pdev);
- d->addr = qpci_iomap(d->pdev, 0, NULL);
- g_assert(d->addr != NULL);
-}
-
-void qvirtio_pci_device_disable(QVirtioPCIDevice *d)
-{
- qpci_iounmap(d->pdev, d->addr);
- d->addr = NULL;
-}
-
-void qvirtqueue_pci_msix_setup(QVirtioPCIDevice *d, QVirtQueuePCI *vqpci,
- QGuestAllocator *alloc, uint16_t entry)
-{
- uint16_t vector;
- uint32_t control;
- void *addr;
-
- g_assert(d->pdev->msix_enabled);
- addr = d->pdev->msix_table + (entry * 16);
-
- g_assert_cmpint(entry, >=, 0);
- g_assert_cmpint(entry, <, qpci_msix_table_size(d->pdev));
- vqpci->msix_entry = entry;
-
- vqpci->msix_addr = guest_alloc(alloc, 4);
- qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_LOWER_ADDR,
- vqpci->msix_addr & ~0UL);
- qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_UPPER_ADDR,
- (vqpci->msix_addr >> 32) & ~0UL);
- qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_DATA, vqpci->msix_data);
-
- control = qpci_io_readl(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
- qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL,
- control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
-
- qvirtio_pci_queue_select(&d->vdev, vqpci->vq.index);
- qpci_io_writew(d->pdev, d->addr + QVIRTIO_PCI_MSIX_QUEUE_VECTOR, entry);
- vector = qpci_io_readw(d->pdev, d->addr + QVIRTIO_PCI_MSIX_QUEUE_VECTOR);
- g_assert_cmphex(vector, !=, QVIRTIO_MSI_NO_VECTOR);
-}
-
-void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d,
- QGuestAllocator *alloc, uint16_t entry)
-{
- uint16_t vector;
- uint32_t control;
- void *addr;
-
- g_assert(d->pdev->msix_enabled);
- addr = d->pdev->msix_table + (entry * 16);
-
- g_assert_cmpint(entry, >=, 0);
- g_assert_cmpint(entry, <, qpci_msix_table_size(d->pdev));
- d->config_msix_entry = entry;
-
- d->config_msix_data = 0x12345678;
- d->config_msix_addr = guest_alloc(alloc, 4);
-
- qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_LOWER_ADDR,
- d->config_msix_addr & ~0UL);
- qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_UPPER_ADDR,
- (d->config_msix_addr >> 32) & ~0UL);
- qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_DATA, d->config_msix_data);
-
- control = qpci_io_readl(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
- qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL,
- control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
-
- qpci_io_writew(d->pdev, d->addr + QVIRTIO_PCI_MSIX_CONF_VECTOR, entry);
- vector = qpci_io_readw(d->pdev, d->addr + QVIRTIO_PCI_MSIX_CONF_VECTOR);
- g_assert_cmphex(vector, !=, QVIRTIO_MSI_NO_VECTOR);
-}
diff --git a/qemu/tests/libqos/virtio-pci.h b/qemu/tests/libqos/virtio-pci.h
deleted file mode 100644
index 8f0e52ad4..000000000
--- a/qemu/tests/libqos/virtio-pci.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * libqos virtio PCI definitions
- *
- * Copyright (c) 2014 Marc Marí
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef LIBQOS_VIRTIO_PCI_H
-#define LIBQOS_VIRTIO_PCI_H
-
-#include "libqos/virtio.h"
-#include "libqos/pci.h"
-
-#define QVIRTIO_PCI_DEVICE_FEATURES 0x00
-#define QVIRTIO_PCI_GUEST_FEATURES 0x04
-#define QVIRTIO_PCI_QUEUE_ADDRESS 0x08
-#define QVIRTIO_PCI_QUEUE_SIZE 0x0C
-#define QVIRTIO_PCI_QUEUE_SELECT 0x0E
-#define QVIRTIO_PCI_QUEUE_NOTIFY 0x10
-#define QVIRTIO_PCI_DEVICE_STATUS 0x12
-#define QVIRTIO_PCI_ISR_STATUS 0x13
-#define QVIRTIO_PCI_MSIX_CONF_VECTOR 0x14
-#define QVIRTIO_PCI_MSIX_QUEUE_VECTOR 0x16
-#define QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX 0x18
-#define QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX 0x14
-
-#define QVIRTIO_PCI_ALIGN 4096
-
-#define QVIRTIO_MSI_NO_VECTOR 0xFFFF
-
-typedef struct QVirtioPCIDevice {
- QVirtioDevice vdev;
- QPCIDevice *pdev;
- void *addr;
- uint16_t config_msix_entry;
- uint64_t config_msix_addr;
- uint32_t config_msix_data;
-} QVirtioPCIDevice;
-
-typedef struct QVirtQueuePCI {
- QVirtQueue vq;
- uint16_t msix_entry;
- uint64_t msix_addr;
- uint32_t msix_data;
-} QVirtQueuePCI;
-
-extern const QVirtioBus qvirtio_pci;
-
-void qvirtio_pci_foreach(QPCIBus *bus, uint16_t device_type,
- void (*func)(QVirtioDevice *d, void *data), void *data);
-QVirtioPCIDevice *qvirtio_pci_device_find(QPCIBus *bus, uint16_t device_type);
-void qvirtio_pci_device_enable(QVirtioPCIDevice *d);
-void qvirtio_pci_device_disable(QVirtioPCIDevice *d);
-
-void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d,
- QGuestAllocator *alloc, uint16_t entry);
-void qvirtqueue_pci_msix_setup(QVirtioPCIDevice *d, QVirtQueuePCI *vqpci,
- QGuestAllocator *alloc, uint16_t entry);
-#endif
diff --git a/qemu/tests/libqos/virtio.c b/qemu/tests/libqos/virtio.c
deleted file mode 100644
index 613decea5..000000000
--- a/qemu/tests/libqos/virtio.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * libqos virtio driver
- *
- * Copyright (c) 2014 Marc Marí
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include <glib.h>
-#include "libqtest.h"
-#include "libqos/virtio.h"
-
-uint8_t qvirtio_config_readb(const QVirtioBus *bus, QVirtioDevice *d,
- uint64_t addr)
-{
- return bus->config_readb(d, addr);
-}
-
-uint16_t qvirtio_config_readw(const QVirtioBus *bus, QVirtioDevice *d,
- uint64_t addr)
-{
- return bus->config_readw(d, addr);
-}
-
-uint32_t qvirtio_config_readl(const QVirtioBus *bus, QVirtioDevice *d,
- uint64_t addr)
-{
- return bus->config_readl(d, addr);
-}
-
-uint64_t qvirtio_config_readq(const QVirtioBus *bus, QVirtioDevice *d,
- uint64_t addr)
-{
- return bus->config_readq(d, addr);
-}
-
-uint32_t qvirtio_get_features(const QVirtioBus *bus, QVirtioDevice *d)
-{
- return bus->get_features(d);
-}
-
-void qvirtio_set_features(const QVirtioBus *bus, QVirtioDevice *d,
- uint32_t features)
-{
- bus->set_features(d, features);
-}
-
-QVirtQueue *qvirtqueue_setup(const QVirtioBus *bus, QVirtioDevice *d,
- QGuestAllocator *alloc, uint16_t index)
-{
- return bus->virtqueue_setup(d, alloc, index);
-}
-
-void qvirtio_reset(const QVirtioBus *bus, QVirtioDevice *d)
-{
- bus->set_status(d, QVIRTIO_RESET);
- g_assert_cmphex(bus->get_status(d), ==, QVIRTIO_RESET);
-}
-
-void qvirtio_set_acknowledge(const QVirtioBus *bus, QVirtioDevice *d)
-{
- bus->set_status(d, bus->get_status(d) | QVIRTIO_ACKNOWLEDGE);
- g_assert_cmphex(bus->get_status(d), ==, QVIRTIO_ACKNOWLEDGE);
-}
-
-void qvirtio_set_driver(const QVirtioBus *bus, QVirtioDevice *d)
-{
- bus->set_status(d, bus->get_status(d) | QVIRTIO_DRIVER);
- g_assert_cmphex(bus->get_status(d), ==,
- QVIRTIO_DRIVER | QVIRTIO_ACKNOWLEDGE);
-}
-
-void qvirtio_set_driver_ok(const QVirtioBus *bus, QVirtioDevice *d)
-{
- bus->set_status(d, bus->get_status(d) | QVIRTIO_DRIVER_OK);
- g_assert_cmphex(bus->get_status(d), ==,
- QVIRTIO_DRIVER_OK | QVIRTIO_DRIVER | QVIRTIO_ACKNOWLEDGE);
-}
-
-void qvirtio_wait_queue_isr(const QVirtioBus *bus, QVirtioDevice *d,
- QVirtQueue *vq, gint64 timeout_us)
-{
- gint64 start_time = g_get_monotonic_time();
-
- for (;;) {
- clock_step(100);
- if (bus->get_queue_isr_status(d, vq)) {
- return;
- }
- g_assert(g_get_monotonic_time() - start_time <= timeout_us);
- }
-}
-
-/* Wait for the status byte at given guest memory address to be set
- *
- * The virtqueue interrupt must not be raised, making this useful for testing
- * event_index functionality.
- */
-uint8_t qvirtio_wait_status_byte_no_isr(const QVirtioBus *bus,
- QVirtioDevice *d,
- QVirtQueue *vq,
- uint64_t addr,
- gint64 timeout_us)
-{
- gint64 start_time = g_get_monotonic_time();
- uint8_t val;
-
- while ((val = readb(addr)) == 0xff) {
- clock_step(100);
- g_assert(!bus->get_queue_isr_status(d, vq));
- g_assert(g_get_monotonic_time() - start_time <= timeout_us);
- }
- return val;
-}
-
-void qvirtio_wait_config_isr(const QVirtioBus *bus, QVirtioDevice *d,
- gint64 timeout_us)
-{
- gint64 start_time = g_get_monotonic_time();
-
- for (;;) {
- clock_step(100);
- if (bus->get_config_isr_status(d)) {
- return;
- }
- g_assert(g_get_monotonic_time() - start_time <= timeout_us);
- }
-}
-
-void qvring_init(const QGuestAllocator *alloc, QVirtQueue *vq, uint64_t addr)
-{
- int i;
-
- vq->desc = addr;
- vq->avail = vq->desc + vq->size*sizeof(QVRingDesc);
- vq->used = (uint64_t)((vq->avail + sizeof(uint16_t) * (3 + vq->size)
- + vq->align - 1) & ~(vq->align - 1));
-
- for (i = 0; i < vq->size - 1; i++) {
- /* vq->desc[i].addr */
- writew(vq->desc + (16 * i), 0);
- /* vq->desc[i].next */
- writew(vq->desc + (16 * i) + 14, i + 1);
- }
-
- /* vq->avail->flags */
- writew(vq->avail, 0);
- /* vq->avail->idx */
- writew(vq->avail + 2, 0);
- /* vq->avail->used_event */
- writew(vq->avail + 4 + (2 * vq->size), 0);
-
- /* vq->used->flags */
- writew(vq->used, 0);
- /* vq->used->avail_event */
- writew(vq->used+2+(sizeof(struct QVRingUsedElem)*vq->size), 0);
-}
-
-QVRingIndirectDesc *qvring_indirect_desc_setup(QVirtioDevice *d,
- QGuestAllocator *alloc, uint16_t elem)
-{
- int i;
- QVRingIndirectDesc *indirect = g_malloc(sizeof(*indirect));
-
- indirect->index = 0;
- indirect->elem = elem;
- indirect->desc = guest_alloc(alloc, sizeof(QVRingDesc)*elem);
-
- for (i = 0; i < elem - 1; ++i) {
- /* indirect->desc[i].addr */
- writeq(indirect->desc + (16 * i), 0);
- /* indirect->desc[i].flags */
- writew(indirect->desc + (16 * i) + 12, QVRING_DESC_F_NEXT);
- /* indirect->desc[i].next */
- writew(indirect->desc + (16 * i) + 14, i + 1);
- }
-
- return indirect;
-}
-
-void qvring_indirect_desc_add(QVRingIndirectDesc *indirect, uint64_t data,
- uint32_t len, bool write)
-{
- uint16_t flags;
-
- g_assert_cmpint(indirect->index, <, indirect->elem);
-
- flags = readw(indirect->desc + (16 * indirect->index) + 12);
-
- if (write) {
- flags |= QVRING_DESC_F_WRITE;
- }
-
- /* indirect->desc[indirect->index].addr */
- writeq(indirect->desc + (16 * indirect->index), data);
- /* indirect->desc[indirect->index].len */
- writel(indirect->desc + (16 * indirect->index) + 8, len);
- /* indirect->desc[indirect->index].flags */
- writew(indirect->desc + (16 * indirect->index) + 12, flags);
-
- indirect->index++;
-}
-
-uint32_t qvirtqueue_add(QVirtQueue *vq, uint64_t data, uint32_t len, bool write,
- bool next)
-{
- uint16_t flags = 0;
- vq->num_free--;
-
- if (write) {
- flags |= QVRING_DESC_F_WRITE;
- }
-
- if (next) {
- flags |= QVRING_DESC_F_NEXT;
- }
-
- /* vq->desc[vq->free_head].addr */
- writeq(vq->desc + (16 * vq->free_head), data);
- /* vq->desc[vq->free_head].len */
- writel(vq->desc + (16 * vq->free_head) + 8, len);
- /* vq->desc[vq->free_head].flags */
- writew(vq->desc + (16 * vq->free_head) + 12, flags);
-
- return vq->free_head++; /* Return and increase, in this order */
-}
-
-uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect)
-{
- g_assert(vq->indirect);
- g_assert_cmpint(vq->size, >=, indirect->elem);
- g_assert_cmpint(indirect->index, ==, indirect->elem);
-
- vq->num_free--;
-
- /* vq->desc[vq->free_head].addr */
- writeq(vq->desc + (16 * vq->free_head), indirect->desc);
- /* vq->desc[vq->free_head].len */
- writel(vq->desc + (16 * vq->free_head) + 8,
- sizeof(QVRingDesc) * indirect->elem);
- /* vq->desc[vq->free_head].flags */
- writew(vq->desc + (16 * vq->free_head) + 12, QVRING_DESC_F_INDIRECT);
-
- return vq->free_head++; /* Return and increase, in this order */
-}
-
-void qvirtqueue_kick(const QVirtioBus *bus, QVirtioDevice *d, QVirtQueue *vq,
- uint32_t free_head)
-{
- /* vq->avail->idx */
- uint16_t idx = readl(vq->avail + 2);
- /* vq->used->flags */
- uint16_t flags;
- /* vq->used->avail_event */
- uint16_t avail_event;
-
- /* vq->avail->ring[idx % vq->size] */
- writel(vq->avail + 4 + (2 * (idx % vq->size)), free_head);
- /* vq->avail->idx */
- writel(vq->avail + 2, idx + 1);
-
- /* Must read after idx is updated */
- flags = readw(vq->avail);
- avail_event = readw(vq->used + 4 +
- (sizeof(struct QVRingUsedElem) * vq->size));
-
- /* < 1 because we add elements to avail queue one by one */
- if ((flags & QVRING_USED_F_NO_NOTIFY) == 0 &&
- (!vq->event || (uint16_t)(idx-avail_event) < 1)) {
- bus->virtqueue_kick(d, vq);
- }
-}
-
-void qvirtqueue_set_used_event(QVirtQueue *vq, uint16_t idx)
-{
- g_assert(vq->event);
-
- /* vq->avail->used_event */
- writew(vq->avail + 4 + (2 * vq->size), idx);
-}
diff --git a/qemu/tests/libqos/virtio.h b/qemu/tests/libqos/virtio.h
deleted file mode 100644
index 01012787b..000000000
--- a/qemu/tests/libqos/virtio.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * libqos virtio definitions
- *
- * Copyright (c) 2014 Marc Marí
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef LIBQOS_VIRTIO_H
-#define LIBQOS_VIRTIO_H
-
-#include "libqos/malloc.h"
-
-#define QVIRTIO_VENDOR_ID 0x1AF4
-
-#define QVIRTIO_RESET 0x0
-#define QVIRTIO_ACKNOWLEDGE 0x1
-#define QVIRTIO_DRIVER 0x2
-#define QVIRTIO_DRIVER_OK 0x4
-
-#define QVIRTIO_NET_DEVICE_ID 0x1
-#define QVIRTIO_BLK_DEVICE_ID 0x2
-#define QVIRTIO_CONSOLE_DEVICE_ID 0x3
-#define QVIRTIO_RNG_DEVICE_ID 0x4
-#define QVIRTIO_BALLOON_DEVICE_ID 0x5
-#define QVIRTIO_RPMSG_DEVICE_ID 0x7
-#define QVIRTIO_SCSI_DEVICE_ID 0x8
-#define QVIRTIO_9P_DEVICE_ID 0x9
-
-#define QVIRTIO_F_NOTIFY_ON_EMPTY 0x01000000
-#define QVIRTIO_F_ANY_LAYOUT 0x08000000
-#define QVIRTIO_F_RING_INDIRECT_DESC 0x10000000
-#define QVIRTIO_F_RING_EVENT_IDX 0x20000000
-#define QVIRTIO_F_BAD_FEATURE 0x40000000
-
-#define QVRING_DESC_F_NEXT 0x1
-#define QVRING_DESC_F_WRITE 0x2
-#define QVRING_DESC_F_INDIRECT 0x4
-
-#define QVIRTIO_F_NOTIFY_ON_EMPTY 0x01000000
-#define QVIRTIO_F_ANY_LAYOUT 0x08000000
-#define QVIRTIO_F_RING_INDIRECT_DESC 0x10000000
-#define QVIRTIO_F_RING_EVENT_IDX 0x20000000
-#define QVIRTIO_F_BAD_FEATURE 0x40000000
-
-#define QVRING_AVAIL_F_NO_INTERRUPT 1
-
-#define QVRING_USED_F_NO_NOTIFY 1
-
-typedef struct QVirtioDevice {
- /* Device type */
- uint16_t device_type;
-} QVirtioDevice;
-
-typedef struct QVRingDesc {
- uint64_t addr;
- uint32_t len;
- uint16_t flags;
- uint16_t next;
-} QVRingDesc;
-
-typedef struct QVRingAvail {
- uint16_t flags;
- uint16_t idx;
- uint16_t ring[0]; /* This is an array of uint16_t */
- uint16_t used_event;
-} QVRingAvail;
-
-typedef struct QVRingUsedElem {
- uint32_t id;
- uint32_t len;
-} QVRingUsedElem;
-
-typedef struct QVRingUsed {
- uint16_t flags;
- uint16_t idx;
- QVRingUsedElem ring[0]; /* This is an array of QVRingUsedElem structs */
- uint16_t avail_event;
-} QVRingUsed;
-
-typedef struct QVirtQueue {
- uint64_t desc; /* This points to an array of QVRingDesc */
- uint64_t avail; /* This points to a QVRingAvail */
- uint64_t used; /* This points to a QVRingDesc */
- uint16_t index;
- uint32_t size;
- uint32_t free_head;
- uint32_t num_free;
- uint32_t align;
- bool indirect;
- bool event;
-} QVirtQueue;
-
-typedef struct QVRingIndirectDesc {
- uint64_t desc; /* This points to an array fo QVRingDesc */
- uint16_t index;
- uint16_t elem;
-} QVRingIndirectDesc;
-
-typedef struct QVirtioBus {
- uint8_t (*config_readb)(QVirtioDevice *d, uint64_t addr);
- uint16_t (*config_readw)(QVirtioDevice *d, uint64_t addr);
- uint32_t (*config_readl)(QVirtioDevice *d, uint64_t addr);
- uint64_t (*config_readq)(QVirtioDevice *d, uint64_t addr);
-
- /* Get features of the device */
- uint32_t (*get_features)(QVirtioDevice *d);
-
- /* Set features of the device */
- void (*set_features)(QVirtioDevice *d, uint32_t features);
-
- /* Get features of the guest */
- uint32_t (*get_guest_features)(QVirtioDevice *d);
-
- /* Get status of the device */
- uint8_t (*get_status)(QVirtioDevice *d);
-
- /* Set status of the device */
- void (*set_status)(QVirtioDevice *d, uint8_t status);
-
- /* Get the queue ISR status of the device */
- bool (*get_queue_isr_status)(QVirtioDevice *d, QVirtQueue *vq);
-
- /* Get the configuration ISR status of the device */
- bool (*get_config_isr_status)(QVirtioDevice *d);
-
- /* Select a queue to work on */
- void (*queue_select)(QVirtioDevice *d, uint16_t index);
-
- /* Get the size of the selected queue */
- uint16_t (*get_queue_size)(QVirtioDevice *d);
-
- /* Set the address of the selected queue */
- void (*set_queue_address)(QVirtioDevice *d, uint32_t pfn);
-
- /* Setup the virtqueue specified by index */
- QVirtQueue *(*virtqueue_setup)(QVirtioDevice *d, QGuestAllocator *alloc,
- uint16_t index);
-
- /* Notify changes in virtqueue */
- void (*virtqueue_kick)(QVirtioDevice *d, QVirtQueue *vq);
-} QVirtioBus;
-
-static inline uint32_t qvring_size(uint32_t num, uint32_t align)
-{
- return ((sizeof(struct QVRingDesc) * num + sizeof(uint16_t) * (3 + num)
- + align - 1) & ~(align - 1))
- + sizeof(uint16_t) * 3 + sizeof(struct QVRingUsedElem) * num;
-}
-
-uint8_t qvirtio_config_readb(const QVirtioBus *bus, QVirtioDevice *d,
- uint64_t addr);
-uint16_t qvirtio_config_readw(const QVirtioBus *bus, QVirtioDevice *d,
- uint64_t addr);
-uint32_t qvirtio_config_readl(const QVirtioBus *bus, QVirtioDevice *d,
- uint64_t addr);
-uint64_t qvirtio_config_readq(const QVirtioBus *bus, QVirtioDevice *d,
- uint64_t addr);
-uint32_t qvirtio_get_features(const QVirtioBus *bus, QVirtioDevice *d);
-void qvirtio_set_features(const QVirtioBus *bus, QVirtioDevice *d,
- uint32_t features);
-
-void qvirtio_reset(const QVirtioBus *bus, QVirtioDevice *d);
-void qvirtio_set_acknowledge(const QVirtioBus *bus, QVirtioDevice *d);
-void qvirtio_set_driver(const QVirtioBus *bus, QVirtioDevice *d);
-void qvirtio_set_driver_ok(const QVirtioBus *bus, QVirtioDevice *d);
-
-void qvirtio_wait_queue_isr(const QVirtioBus *bus, QVirtioDevice *d,
- QVirtQueue *vq, gint64 timeout_us);
-uint8_t qvirtio_wait_status_byte_no_isr(const QVirtioBus *bus,
- QVirtioDevice *d,
- QVirtQueue *vq,
- uint64_t addr,
- gint64 timeout_us);
-void qvirtio_wait_config_isr(const QVirtioBus *bus, QVirtioDevice *d,
- gint64 timeout_us);
-QVirtQueue *qvirtqueue_setup(const QVirtioBus *bus, QVirtioDevice *d,
- QGuestAllocator *alloc, uint16_t index);
-
-void qvring_init(const QGuestAllocator *alloc, QVirtQueue *vq, uint64_t addr);
-QVRingIndirectDesc *qvring_indirect_desc_setup(QVirtioDevice *d,
- QGuestAllocator *alloc, uint16_t elem);
-void qvring_indirect_desc_add(QVRingIndirectDesc *indirect, uint64_t data,
- uint32_t len, bool write);
-uint32_t qvirtqueue_add(QVirtQueue *vq, uint64_t data, uint32_t len, bool write,
- bool next);
-uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect);
-void qvirtqueue_kick(const QVirtioBus *bus, QVirtioDevice *d, QVirtQueue *vq,
- uint32_t free_head);
-
-void qvirtqueue_set_used_event(QVirtQueue *vq, uint16_t idx);
-#endif