-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1 iQEcBAABAgAGBQJWMmDMAAoJEJykq7OBq3PIHkIIAKyL9iY4EipKrtdMoWZu/Kfm I9g4NVVqPF4QmTfYpZVxWglvBy0g0+2p1h4DQ5KheUNr7DV2uchSSsN38MWnEgH/ XTRpY858jcWx4sSAvYpz+kUVRBEtJJL8a/1aTBvYRxcbNE1X1lm72m7mm4KXGGud PZ0fdj/UODHeoTOnMHddbs8Rs0kdHhlckl2Mfkz2dUgYAuZMK7xR7OIE7kOqWBcR p5/I1Jq3wgmp267ZPVNS17u8Cff2PIElv0Z3Ouubixhhf+k5kvLBtgTbTJ81h7/4 NfmIRwsmAPhtnDSDXqFJ8KgwUYpGYYtPrK8DIXIWYwPdSjkIIdl1gNtc2CGyV3w= =nA50 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging # gpg: Signature made Thu 29 Oct 2015 18:09:16 GMT using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" * remotes/stefanha/tags/block-pull-request: block: Consider all child nodes in bdrv_requests_pending() target-arm: xlnx-zynqmp: Add sdhci support. sdhci: Split sdhci.h for public and internal device usage sd.h: Move sd.h to include/hw/sd/ virtio: sync the dataplane vring state to the virtqueue before virtio_save gdb command: qemu handlers virtio-blk: switch off scsi-passthrough by default ppc/spapr: add 2.4 compat props s390x: include HW_COMPAT_* props qemu-gdb: add $qemu_coroutine_sp and $qemu_coroutine_pc qemu-gdb: extract parts of "qemu coroutine" implementation qemu-gdb: allow using glibc_pointer_guard() on core dumps Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3a958f559e
13
block/io.c
13
block/io.c
|
@ -216,6 +216,8 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs)
|
||||||
/* Check if any requests are in-flight (including throttled requests) */
|
/* Check if any requests are in-flight (including throttled requests) */
|
||||||
bool bdrv_requests_pending(BlockDriverState *bs)
|
bool bdrv_requests_pending(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
|
BdrvChild *child;
|
||||||
|
|
||||||
if (!QLIST_EMPTY(&bs->tracked_requests)) {
|
if (!QLIST_EMPTY(&bs->tracked_requests)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -225,12 +227,13 @@ bool bdrv_requests_pending(BlockDriverState *bs)
|
||||||
if (!qemu_co_queue_empty(&bs->throttled_reqs[1])) {
|
if (!qemu_co_queue_empty(&bs->throttled_reqs[1])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (bs->file && bdrv_requests_pending(bs->file->bs)) {
|
|
||||||
return true;
|
QLIST_FOREACH(child, &bs->children, next) {
|
||||||
}
|
if (bdrv_requests_pending(child->bs)) {
|
||||||
if (bs->backing && bdrv_requests_pending(bs->backing->bs)) {
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,14 @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
|
||||||
21, 22,
|
21, 22,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
|
||||||
|
0xFF160000, 0xFF170000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int sdhci_intr[XLNX_ZYNQMP_NUM_SDHCI] = {
|
||||||
|
48, 49,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct XlnxZynqMPGICRegion {
|
typedef struct XlnxZynqMPGICRegion {
|
||||||
int region_index;
|
int region_index;
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
|
@ -97,6 +105,13 @@ static void xlnx_zynqmp_init(Object *obj)
|
||||||
|
|
||||||
object_initialize(&s->sata, sizeof(s->sata), TYPE_SYSBUS_AHCI);
|
object_initialize(&s->sata, sizeof(s->sata), TYPE_SYSBUS_AHCI);
|
||||||
qdev_set_parent_bus(DEVICE(&s->sata), sysbus_get_default());
|
qdev_set_parent_bus(DEVICE(&s->sata), sysbus_get_default());
|
||||||
|
|
||||||
|
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
|
||||||
|
object_initialize(&s->sdhci[i], sizeof(s->sdhci[i]),
|
||||||
|
TYPE_SYSBUS_SDHCI);
|
||||||
|
qdev_set_parent_bus(DEVICE(&s->sdhci[i]),
|
||||||
|
sysbus_get_default());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
||||||
|
@ -258,6 +273,19 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
||||||
|
|
||||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sata), 0, SATA_ADDR);
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sata), 0, SATA_ADDR);
|
||||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0, gic_spi[SATA_INTR]);
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0, gic_spi[SATA_INTR]);
|
||||||
|
|
||||||
|
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
|
||||||
|
object_property_set_bool(OBJECT(&s->sdhci[i]), true,
|
||||||
|
"realized", &err);
|
||||||
|
if (err) {
|
||||||
|
error_propagate(errp, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci[i]), 0,
|
||||||
|
sdhci_addr[i]);
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci[i]), 0,
|
||||||
|
gic_spi[sdhci_intr[i]]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Property xlnx_zynqmp_props[] = {
|
static Property xlnx_zynqmp_props[] = {
|
||||||
|
|
|
@ -798,6 +798,11 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
|
||||||
static void virtio_blk_save(QEMUFile *f, void *opaque)
|
static void virtio_blk_save(QEMUFile *f, void *opaque)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
|
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
|
||||||
|
VirtIOBlock *s = VIRTIO_BLK(vdev);
|
||||||
|
|
||||||
|
if (s->dataplane) {
|
||||||
|
virtio_blk_data_plane_stop(s->dataplane);
|
||||||
|
}
|
||||||
|
|
||||||
virtio_save(vdev, f);
|
virtio_save(vdev, f);
|
||||||
}
|
}
|
||||||
|
@ -972,7 +977,7 @@ static Property virtio_blk_properties[] = {
|
||||||
DEFINE_PROP_STRING("serial", VirtIOBlock, conf.serial),
|
DEFINE_PROP_STRING("serial", VirtIOBlock, conf.serial),
|
||||||
DEFINE_PROP_BIT("config-wce", VirtIOBlock, conf.config_wce, 0, true),
|
DEFINE_PROP_BIT("config-wce", VirtIOBlock, conf.config_wce, 0, true),
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, true),
|
DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, false),
|
||||||
#endif
|
#endif
|
||||||
DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
|
DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
|
||||||
true),
|
true),
|
||||||
|
|
|
@ -2285,7 +2285,11 @@ static const TypeInfo spapr_machine_info = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SPAPR_COMPAT_2_4 \
|
||||||
|
HW_COMPAT_2_4
|
||||||
|
|
||||||
#define SPAPR_COMPAT_2_3 \
|
#define SPAPR_COMPAT_2_3 \
|
||||||
|
SPAPR_COMPAT_2_4 \
|
||||||
HW_COMPAT_2_3 \
|
HW_COMPAT_2_3 \
|
||||||
{\
|
{\
|
||||||
.driver = "spapr-pci-host-bridge",\
|
.driver = "spapr-pci-host-bridge",\
|
||||||
|
@ -2399,11 +2403,16 @@ static const TypeInfo spapr_machine_2_3_info = {
|
||||||
|
|
||||||
static void spapr_machine_2_4_class_init(ObjectClass *oc, void *data)
|
static void spapr_machine_2_4_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
|
static GlobalProperty compat_props[] = {
|
||||||
|
SPAPR_COMPAT_2_4
|
||||||
|
{ /* end of list */ }
|
||||||
|
};
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
|
|
||||||
mc->desc = "pSeries Logical Partition (PAPR compliant) v2.4";
|
mc->desc = "pSeries Logical Partition (PAPR compliant) v2.4";
|
||||||
mc->alias = "pseries";
|
mc->alias = "pseries";
|
||||||
mc->is_default = 0;
|
mc->is_default = 0;
|
||||||
|
mc->compat_props = compat_props;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo spapr_machine_2_4_info = {
|
static const TypeInfo spapr_machine_2_4_info = {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "s390-pci-bus.h"
|
#include "s390-pci-bus.h"
|
||||||
#include "hw/s390x/storage-keys.h"
|
#include "hw/s390x/storage-keys.h"
|
||||||
|
#include "hw/compat.h"
|
||||||
|
|
||||||
#define TYPE_S390_CCW_MACHINE "s390-ccw-machine"
|
#define TYPE_S390_CCW_MACHINE "s390-ccw-machine"
|
||||||
|
|
||||||
|
@ -236,6 +237,7 @@ static const TypeInfo ccw_machine_info = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CCW_COMPAT_2_4 \
|
#define CCW_COMPAT_2_4 \
|
||||||
|
HW_COMPAT_2_4 \
|
||||||
{\
|
{\
|
||||||
.driver = TYPE_S390_SKEYS,\
|
.driver = TYPE_S390_SKEYS,\
|
||||||
.property = "migration-enabled",\
|
.property = "migration-enabled",\
|
||||||
|
|
|
@ -653,6 +653,11 @@ static void virtio_scsi_reset(VirtIODevice *vdev)
|
||||||
static void virtio_scsi_save(QEMUFile *f, void *opaque)
|
static void virtio_scsi_save(QEMUFile *f, void *opaque)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
|
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
|
||||||
|
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
|
||||||
|
|
||||||
|
if (s->dataplane_started) {
|
||||||
|
virtio_scsi_dataplane_stop(s);
|
||||||
|
}
|
||||||
virtio_save(vdev, f);
|
virtio_save(vdev, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "sysemu/block-backend.h"
|
#include "sysemu/block-backend.h"
|
||||||
#include "sysemu/blockdev.h"
|
#include "sysemu/blockdev.h"
|
||||||
#include "hw/sd.h"
|
#include "hw/sd/sd.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ENABLE_CMD_TX = (1<<0),
|
ENABLE_CMD_TX = (1<<0),
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "hw/arm/omap.h"
|
#include "hw/arm/omap.h"
|
||||||
#include "hw/sd.h"
|
#include "hw/sd/sd.h"
|
||||||
|
|
||||||
struct omap_mmc_s {
|
struct omap_mmc_s {
|
||||||
qemu_irq irq;
|
qemu_irq irq;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "sysemu/block-backend.h"
|
#include "sysemu/block-backend.h"
|
||||||
#include "sysemu/blockdev.h"
|
#include "sysemu/blockdev.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
#include "hw/sd.h"
|
#include "hw/sd/sd.h"
|
||||||
|
|
||||||
//#define DEBUG_PL181 1
|
//#define DEBUG_PL181 1
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "hw/arm/pxa.h"
|
#include "hw/arm/pxa.h"
|
||||||
#include "hw/sd.h"
|
#include "hw/sd/sd.h"
|
||||||
#include "hw/qdev.h"
|
#include "hw/qdev.h"
|
||||||
|
|
||||||
struct PXA2xxMMCIState {
|
struct PXA2xxMMCIState {
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "sysemu/block-backend.h"
|
#include "sysemu/block-backend.h"
|
||||||
#include "hw/sd.h"
|
#include "hw/sd/sd.h"
|
||||||
#include "qemu/bitmap.h"
|
#include "qemu/bitmap.h"
|
||||||
|
|
||||||
//#define DEBUG_SD 1
|
//#define DEBUG_SD 1
|
||||||
|
|
|
@ -21,15 +21,10 @@
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
#ifndef SDHCI_INTERNAL_H
|
||||||
|
#define SDHCI_INTERNAL_H
|
||||||
|
|
||||||
#ifndef SDHCI_H
|
#include "hw/sd/sdhci.h"
|
||||||
#define SDHCI_H
|
|
||||||
|
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "hw/block/block.h"
|
|
||||||
#include "hw/pci/pci.h"
|
|
||||||
#include "hw/sysbus.h"
|
|
||||||
#include "hw/sd.h"
|
|
||||||
|
|
||||||
/* R/W SDMA System Address register 0x0 */
|
/* R/W SDMA System Address register 0x0 */
|
||||||
#define SDHC_SYSAD 0x00
|
#define SDHC_SYSAD 0x00
|
||||||
|
@ -232,66 +227,6 @@ enum {
|
||||||
sdhc_gap_write = 2 /* SDHC stopped at block gap during write operation */
|
sdhc_gap_write = 2 /* SDHC stopped at block gap during write operation */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SD/MMC host controller state */
|
|
||||||
typedef struct SDHCIState {
|
|
||||||
union {
|
|
||||||
PCIDevice pcidev;
|
|
||||||
SysBusDevice busdev;
|
|
||||||
};
|
|
||||||
SDState *card;
|
|
||||||
MemoryRegion iomem;
|
|
||||||
BlockConf conf;
|
|
||||||
|
|
||||||
QEMUTimer *insert_timer; /* timer for 'changing' sd card. */
|
|
||||||
QEMUTimer *transfer_timer;
|
|
||||||
qemu_irq eject_cb;
|
|
||||||
qemu_irq ro_cb;
|
|
||||||
qemu_irq irq;
|
|
||||||
|
|
||||||
uint32_t sdmasysad; /* SDMA System Address register */
|
|
||||||
uint16_t blksize; /* Host DMA Buff Boundary and Transfer BlkSize Reg */
|
|
||||||
uint16_t blkcnt; /* Blocks count for current transfer */
|
|
||||||
uint32_t argument; /* Command Argument Register */
|
|
||||||
uint16_t trnmod; /* Transfer Mode Setting Register */
|
|
||||||
uint16_t cmdreg; /* Command Register */
|
|
||||||
uint32_t rspreg[4]; /* Response Registers 0-3 */
|
|
||||||
uint32_t prnsts; /* Present State Register */
|
|
||||||
uint8_t hostctl; /* Host Control Register */
|
|
||||||
uint8_t pwrcon; /* Power control Register */
|
|
||||||
uint8_t blkgap; /* Block Gap Control Register */
|
|
||||||
uint8_t wakcon; /* WakeUp Control Register */
|
|
||||||
uint16_t clkcon; /* Clock control Register */
|
|
||||||
uint8_t timeoutcon; /* Timeout Control Register */
|
|
||||||
uint8_t admaerr; /* ADMA Error Status Register */
|
|
||||||
uint16_t norintsts; /* Normal Interrupt Status Register */
|
|
||||||
uint16_t errintsts; /* Error Interrupt Status Register */
|
|
||||||
uint16_t norintstsen; /* Normal Interrupt Status Enable Register */
|
|
||||||
uint16_t errintstsen; /* Error Interrupt Status Enable Register */
|
|
||||||
uint16_t norintsigen; /* Normal Interrupt Signal Enable Register */
|
|
||||||
uint16_t errintsigen; /* Error Interrupt Signal Enable Register */
|
|
||||||
uint16_t acmd12errsts; /* Auto CMD12 error status register */
|
|
||||||
uint64_t admasysaddr; /* ADMA System Address Register */
|
|
||||||
|
|
||||||
uint32_t capareg; /* Capabilities Register */
|
|
||||||
uint32_t maxcurr; /* Maximum Current Capabilities Register */
|
|
||||||
uint8_t *fifo_buffer; /* SD host i/o FIFO buffer */
|
|
||||||
uint32_t buf_maxsz;
|
|
||||||
uint16_t data_count; /* current element in FIFO buffer */
|
|
||||||
uint8_t stopped_state;/* Current SDHC state */
|
|
||||||
/* Buffer Data Port Register - virtual access point to R and W buffers */
|
|
||||||
/* Software Reset Register - always reads as 0 */
|
|
||||||
/* Force Event Auto CMD12 Error Interrupt Reg - write only */
|
|
||||||
/* Force Event Error Interrupt Register- write only */
|
|
||||||
/* RO Host Controller Version Register always reads as 0x2401 */
|
|
||||||
} SDHCIState;
|
|
||||||
|
|
||||||
extern const VMStateDescription sdhci_vmstate;
|
extern const VMStateDescription sdhci_vmstate;
|
||||||
|
|
||||||
#define TYPE_PCI_SDHCI "sdhci-pci"
|
#endif
|
||||||
#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI)
|
|
||||||
|
|
||||||
#define TYPE_SYSBUS_SDHCI "generic-sdhci"
|
|
||||||
#define SYSBUS_SDHCI(obj) \
|
|
||||||
OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI)
|
|
||||||
|
|
||||||
#endif /* SDHCI_H */
|
|
|
@ -29,8 +29,7 @@
|
||||||
#include "sysemu/dma.h"
|
#include "sysemu/dma.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "qemu/bitops.h"
|
#include "qemu/bitops.h"
|
||||||
|
#include "sdhci-internal.h"
|
||||||
#include "sdhci.h"
|
|
||||||
|
|
||||||
/* host controller debug messages */
|
/* host controller debug messages */
|
||||||
#ifndef SDHC_DEBUG
|
#ifndef SDHC_DEBUG
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "sysemu/block-backend.h"
|
#include "sysemu/block-backend.h"
|
||||||
#include "sysemu/blockdev.h"
|
#include "sysemu/blockdev.h"
|
||||||
#include "hw/ssi.h"
|
#include "hw/ssi.h"
|
||||||
#include "hw/sd.h"
|
#include "hw/sd/sd.h"
|
||||||
|
|
||||||
//#define DEBUG_SSI_SD 1
|
//#define DEBUG_SSI_SD 1
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "hw/char/cadence_uart.h"
|
#include "hw/char/cadence_uart.h"
|
||||||
#include "hw/ide/pci.h"
|
#include "hw/ide/pci.h"
|
||||||
#include "hw/ide/ahci.h"
|
#include "hw/ide/ahci.h"
|
||||||
|
#include "hw/sd/sdhci.h"
|
||||||
|
|
||||||
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
|
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
|
||||||
#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
|
#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
|
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
|
||||||
#define XLNX_ZYNQMP_NUM_GEMS 4
|
#define XLNX_ZYNQMP_NUM_GEMS 4
|
||||||
#define XLNX_ZYNQMP_NUM_UARTS 2
|
#define XLNX_ZYNQMP_NUM_UARTS 2
|
||||||
|
#define XLNX_ZYNQMP_NUM_SDHCI 2
|
||||||
|
|
||||||
#define XLNX_ZYNQMP_NUM_OCM_BANKS 4
|
#define XLNX_ZYNQMP_NUM_OCM_BANKS 4
|
||||||
#define XLNX_ZYNQMP_OCM_RAM_0_ADDRESS 0xFFFC0000
|
#define XLNX_ZYNQMP_OCM_RAM_0_ADDRESS 0xFFFC0000
|
||||||
|
@ -63,6 +65,7 @@ typedef struct XlnxZynqMPState {
|
||||||
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
|
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
|
||||||
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
|
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
|
||||||
SysbusAHCIState sata;
|
SysbusAHCIState sata;
|
||||||
|
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
|
||||||
|
|
||||||
char *boot_cpu;
|
char *boot_cpu;
|
||||||
ARMCPU *boot_cpu_ptr;
|
ARMCPU *boot_cpu_ptr;
|
||||||
|
|
|
@ -2,7 +2,11 @@
|
||||||
#define HW_COMPAT_H
|
#define HW_COMPAT_H
|
||||||
|
|
||||||
#define HW_COMPAT_2_4 \
|
#define HW_COMPAT_2_4 \
|
||||||
/* empty */
|
{\
|
||||||
|
.driver = "virtio-blk-device",\
|
||||||
|
.property = "scsi",\
|
||||||
|
.value = "true",\
|
||||||
|
},
|
||||||
|
|
||||||
#define HW_COMPAT_2_3 \
|
#define HW_COMPAT_2_3 \
|
||||||
{\
|
{\
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* SD Association Host Standard Specification v2.0 controller emulation
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
|
||||||
|
* Mitsyanko Igor <i.mitsyanko@samsung.com>
|
||||||
|
* Peter A.G. Crosthwaite <peter.crosthwaite@petalogix.com>
|
||||||
|
*
|
||||||
|
* Based on MMC controller for Samsung S5PC1xx-based board emulation
|
||||||
|
* by Alexey Merkulov and Vladimir Monakhov.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDHCI_H
|
||||||
|
#define SDHCI_H
|
||||||
|
|
||||||
|
#include "qemu-common.h"
|
||||||
|
#include "hw/block/block.h"
|
||||||
|
#include "hw/pci/pci.h"
|
||||||
|
#include "hw/sysbus.h"
|
||||||
|
#include "hw/sd/sd.h"
|
||||||
|
|
||||||
|
/* SD/MMC host controller state */
|
||||||
|
typedef struct SDHCIState {
|
||||||
|
union {
|
||||||
|
PCIDevice pcidev;
|
||||||
|
SysBusDevice busdev;
|
||||||
|
};
|
||||||
|
SDState *card;
|
||||||
|
MemoryRegion iomem;
|
||||||
|
BlockConf conf;
|
||||||
|
|
||||||
|
QEMUTimer *insert_timer; /* timer for 'changing' sd card. */
|
||||||
|
QEMUTimer *transfer_timer;
|
||||||
|
qemu_irq eject_cb;
|
||||||
|
qemu_irq ro_cb;
|
||||||
|
qemu_irq irq;
|
||||||
|
|
||||||
|
uint32_t sdmasysad; /* SDMA System Address register */
|
||||||
|
uint16_t blksize; /* Host DMA Buff Boundary and Transfer BlkSize Reg */
|
||||||
|
uint16_t blkcnt; /* Blocks count for current transfer */
|
||||||
|
uint32_t argument; /* Command Argument Register */
|
||||||
|
uint16_t trnmod; /* Transfer Mode Setting Register */
|
||||||
|
uint16_t cmdreg; /* Command Register */
|
||||||
|
uint32_t rspreg[4]; /* Response Registers 0-3 */
|
||||||
|
uint32_t prnsts; /* Present State Register */
|
||||||
|
uint8_t hostctl; /* Host Control Register */
|
||||||
|
uint8_t pwrcon; /* Power control Register */
|
||||||
|
uint8_t blkgap; /* Block Gap Control Register */
|
||||||
|
uint8_t wakcon; /* WakeUp Control Register */
|
||||||
|
uint16_t clkcon; /* Clock control Register */
|
||||||
|
uint8_t timeoutcon; /* Timeout Control Register */
|
||||||
|
uint8_t admaerr; /* ADMA Error Status Register */
|
||||||
|
uint16_t norintsts; /* Normal Interrupt Status Register */
|
||||||
|
uint16_t errintsts; /* Error Interrupt Status Register */
|
||||||
|
uint16_t norintstsen; /* Normal Interrupt Status Enable Register */
|
||||||
|
uint16_t errintstsen; /* Error Interrupt Status Enable Register */
|
||||||
|
uint16_t norintsigen; /* Normal Interrupt Signal Enable Register */
|
||||||
|
uint16_t errintsigen; /* Error Interrupt Signal Enable Register */
|
||||||
|
uint16_t acmd12errsts; /* Auto CMD12 error status register */
|
||||||
|
uint64_t admasysaddr; /* ADMA System Address Register */
|
||||||
|
|
||||||
|
uint32_t capareg; /* Capabilities Register */
|
||||||
|
uint32_t maxcurr; /* Maximum Current Capabilities Register */
|
||||||
|
uint8_t *fifo_buffer; /* SD host i/o FIFO buffer */
|
||||||
|
uint32_t buf_maxsz;
|
||||||
|
uint16_t data_count; /* current element in FIFO buffer */
|
||||||
|
uint8_t stopped_state;/* Current SDHC state */
|
||||||
|
/* Buffer Data Port Register - virtual access point to R and W buffers */
|
||||||
|
/* Software Reset Register - always reads as 0 */
|
||||||
|
/* Force Event Auto CMD12 Error Interrupt Reg - write only */
|
||||||
|
/* Force Event Error Interrupt Register- write only */
|
||||||
|
/* RO Host Controller Version Register always reads as 0x2401 */
|
||||||
|
} SDHCIState;
|
||||||
|
|
||||||
|
#define TYPE_PCI_SDHCI "sdhci-pci"
|
||||||
|
#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI)
|
||||||
|
|
||||||
|
#define TYPE_SYSBUS_SDHCI "generic-sdhci"
|
||||||
|
#define SYSBUS_SDHCI(obj) \
|
||||||
|
OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI)
|
||||||
|
|
||||||
|
#endif /* SDHCI_H */
|
|
@ -26,7 +26,7 @@ import os, sys
|
||||||
|
|
||||||
sys.path.append(os.path.dirname(__file__))
|
sys.path.append(os.path.dirname(__file__))
|
||||||
|
|
||||||
from qemugdb import mtree, coroutine
|
from qemugdb import aio, mtree, coroutine
|
||||||
|
|
||||||
class QemuCommand(gdb.Command):
|
class QemuCommand(gdb.Command):
|
||||||
'''Prefix for QEMU debug support commands'''
|
'''Prefix for QEMU debug support commands'''
|
||||||
|
@ -37,6 +37,10 @@ class QemuCommand(gdb.Command):
|
||||||
QemuCommand()
|
QemuCommand()
|
||||||
coroutine.CoroutineCommand()
|
coroutine.CoroutineCommand()
|
||||||
mtree.MtreeCommand()
|
mtree.MtreeCommand()
|
||||||
|
aio.HandlersCommand()
|
||||||
|
|
||||||
|
coroutine.CoroutineSPFunction()
|
||||||
|
coroutine.CoroutinePCFunction()
|
||||||
|
|
||||||
# Default to silently passing through SIGUSR1, because QEMU sends it
|
# Default to silently passing through SIGUSR1, because QEMU sends it
|
||||||
# to itself a lot.
|
# to itself a lot.
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
# GDB debugging support: aio/iohandler debug
|
||||||
|
#
|
||||||
|
# Copyright (c) 2015 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# Author: Dr. David Alan Gilbert <dgilbert@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.
|
||||||
|
#
|
||||||
|
|
||||||
|
import gdb
|
||||||
|
from qemugdb import coroutine
|
||||||
|
|
||||||
|
def isnull(ptr):
|
||||||
|
return ptr == gdb.Value(0).cast(ptr.type)
|
||||||
|
|
||||||
|
def dump_aiocontext(context, verbose):
|
||||||
|
'''Display a dump and backtrace for an aiocontext'''
|
||||||
|
cur = context['aio_handlers']['lh_first']
|
||||||
|
# Get pointers to functions we're going to process specially
|
||||||
|
sym_fd_coroutine_enter = gdb.parse_and_eval('fd_coroutine_enter')
|
||||||
|
|
||||||
|
while not isnull(cur):
|
||||||
|
entry = cur.dereference()
|
||||||
|
gdb.write('----\n%s\n' % entry)
|
||||||
|
if verbose and cur['io_read'] == sym_fd_coroutine_enter:
|
||||||
|
coptr = (cur['opaque'].cast(gdb.lookup_type('FDYieldUntilData').pointer()))['co']
|
||||||
|
coptr = coptr.cast(gdb.lookup_type('CoroutineUContext').pointer())
|
||||||
|
coroutine.bt_jmpbuf(coptr['env']['__jmpbuf'])
|
||||||
|
cur = cur['node']['le_next'];
|
||||||
|
|
||||||
|
gdb.write('----\n')
|
||||||
|
|
||||||
|
class HandlersCommand(gdb.Command):
|
||||||
|
'''Display aio handlers'''
|
||||||
|
def __init__(self):
|
||||||
|
gdb.Command.__init__(self, 'qemu handlers', gdb.COMMAND_DATA,
|
||||||
|
gdb.COMPLETE_NONE)
|
||||||
|
|
||||||
|
def invoke(self, arg, from_tty):
|
||||||
|
verbose = False
|
||||||
|
argv = gdb.string_to_argv(arg)
|
||||||
|
|
||||||
|
if len(argv) > 0 and argv[0] == '--verbose':
|
||||||
|
verbose = True
|
||||||
|
argv.pop(0)
|
||||||
|
|
||||||
|
if len(argv) > 1:
|
||||||
|
gdb.write('usage: qemu handlers [--verbose] [handler]\n')
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(argv) == 1:
|
||||||
|
handlers_name = argv[0]
|
||||||
|
else:
|
||||||
|
handlers_name = 'qemu_aio_context'
|
||||||
|
dump_aiocontext(gdb.parse_and_eval(handlers_name), verbose)
|
|
@ -15,8 +15,11 @@
|
||||||
|
|
||||||
import gdb
|
import gdb
|
||||||
|
|
||||||
|
VOID_PTR = gdb.lookup_type('void').pointer()
|
||||||
|
|
||||||
def get_fs_base():
|
def get_fs_base():
|
||||||
'''Fetch %fs base value using arch_prctl(ARCH_GET_FS)'''
|
'''Fetch %fs base value using arch_prctl(ARCH_GET_FS). This is
|
||||||
|
pthread_self().'''
|
||||||
# %rsp - 120 is scratch space according to the SystemV ABI
|
# %rsp - 120 is scratch space according to the SystemV ABI
|
||||||
old = gdb.parse_and_eval('*(uint64_t*)($rsp - 120)')
|
old = gdb.parse_and_eval('*(uint64_t*)($rsp - 120)')
|
||||||
gdb.execute('call arch_prctl(0x1003, $rsp - 120)', False, True)
|
gdb.execute('call arch_prctl(0x1003, $rsp - 120)', False, True)
|
||||||
|
@ -24,17 +27,29 @@ def get_fs_base():
|
||||||
gdb.execute('set *(uint64_t*)($rsp - 120) = %s' % old, False, True)
|
gdb.execute('set *(uint64_t*)($rsp - 120) = %s' % old, False, True)
|
||||||
return fs_base
|
return fs_base
|
||||||
|
|
||||||
|
def pthread_self():
|
||||||
|
'''Fetch pthread_self() from the glibc start_thread function.'''
|
||||||
|
f = gdb.newest_frame()
|
||||||
|
while f.name() != 'start_thread':
|
||||||
|
f = f.older()
|
||||||
|
if f is None:
|
||||||
|
return get_fs_base()
|
||||||
|
|
||||||
|
try:
|
||||||
|
return f.read_var("arg")
|
||||||
|
except ValueError:
|
||||||
|
return get_fs_base()
|
||||||
|
|
||||||
def get_glibc_pointer_guard():
|
def get_glibc_pointer_guard():
|
||||||
'''Fetch glibc pointer guard value'''
|
'''Fetch glibc pointer guard value'''
|
||||||
fs_base = get_fs_base()
|
fs_base = pthread_self()
|
||||||
return gdb.parse_and_eval('*(uint64_t*)((uint64_t)%s + 0x30)' % fs_base)
|
return gdb.parse_and_eval('*(uint64_t*)((uint64_t)%s + 0x30)' % fs_base)
|
||||||
|
|
||||||
def glibc_ptr_demangle(val, pointer_guard):
|
def glibc_ptr_demangle(val, pointer_guard):
|
||||||
'''Undo effect of glibc's PTR_MANGLE()'''
|
'''Undo effect of glibc's PTR_MANGLE()'''
|
||||||
return gdb.parse_and_eval('(((uint64_t)%s >> 0x11) | ((uint64_t)%s << (64 - 0x11))) ^ (uint64_t)%s' % (val, val, pointer_guard))
|
return gdb.parse_and_eval('(((uint64_t)%s >> 0x11) | ((uint64_t)%s << (64 - 0x11))) ^ (uint64_t)%s' % (val, val, pointer_guard))
|
||||||
|
|
||||||
def bt_jmpbuf(jmpbuf):
|
def get_jmpbuf_regs(jmpbuf):
|
||||||
'''Backtrace a jmpbuf'''
|
|
||||||
JB_RBX = 0
|
JB_RBX = 0
|
||||||
JB_RBP = 1
|
JB_RBP = 1
|
||||||
JB_R12 = 2
|
JB_R12 = 2
|
||||||
|
@ -44,35 +59,35 @@ def bt_jmpbuf(jmpbuf):
|
||||||
JB_RSP = 6
|
JB_RSP = 6
|
||||||
JB_PC = 7
|
JB_PC = 7
|
||||||
|
|
||||||
old_rbx = gdb.parse_and_eval('(uint64_t)$rbx')
|
|
||||||
old_rbp = gdb.parse_and_eval('(uint64_t)$rbp')
|
|
||||||
old_rsp = gdb.parse_and_eval('(uint64_t)$rsp')
|
|
||||||
old_r12 = gdb.parse_and_eval('(uint64_t)$r12')
|
|
||||||
old_r13 = gdb.parse_and_eval('(uint64_t)$r13')
|
|
||||||
old_r14 = gdb.parse_and_eval('(uint64_t)$r14')
|
|
||||||
old_r15 = gdb.parse_and_eval('(uint64_t)$r15')
|
|
||||||
old_rip = gdb.parse_and_eval('(uint64_t)$rip')
|
|
||||||
|
|
||||||
pointer_guard = get_glibc_pointer_guard()
|
pointer_guard = get_glibc_pointer_guard()
|
||||||
gdb.execute('set $rbx = %s' % jmpbuf[JB_RBX])
|
return {'rbx': jmpbuf[JB_RBX],
|
||||||
gdb.execute('set $rbp = %s' % glibc_ptr_demangle(jmpbuf[JB_RBP], pointer_guard))
|
'rbp': glibc_ptr_demangle(jmpbuf[JB_RBP], pointer_guard),
|
||||||
gdb.execute('set $rsp = %s' % glibc_ptr_demangle(jmpbuf[JB_RSP], pointer_guard))
|
'rsp': glibc_ptr_demangle(jmpbuf[JB_RSP], pointer_guard),
|
||||||
gdb.execute('set $r12 = %s' % jmpbuf[JB_R12])
|
'r12': jmpbuf[JB_R12],
|
||||||
gdb.execute('set $r13 = %s' % jmpbuf[JB_R13])
|
'r13': jmpbuf[JB_R13],
|
||||||
gdb.execute('set $r14 = %s' % jmpbuf[JB_R14])
|
'r14': jmpbuf[JB_R14],
|
||||||
gdb.execute('set $r15 = %s' % jmpbuf[JB_R15])
|
'r15': jmpbuf[JB_R15],
|
||||||
gdb.execute('set $rip = %s' % glibc_ptr_demangle(jmpbuf[JB_PC], pointer_guard))
|
'rip': glibc_ptr_demangle(jmpbuf[JB_PC], pointer_guard) }
|
||||||
|
|
||||||
|
def bt_jmpbuf(jmpbuf):
|
||||||
|
'''Backtrace a jmpbuf'''
|
||||||
|
regs = get_jmpbuf_regs(jmpbuf)
|
||||||
|
old = dict()
|
||||||
|
|
||||||
|
for i in regs:
|
||||||
|
old[i] = gdb.parse_and_eval('(uint64_t)$%s' % i)
|
||||||
|
|
||||||
|
for i in regs:
|
||||||
|
gdb.execute('set $%s = %s' % (i, regs[i]))
|
||||||
|
|
||||||
gdb.execute('bt')
|
gdb.execute('bt')
|
||||||
|
|
||||||
gdb.execute('set $rbx = %s' % old_rbx)
|
for i in regs:
|
||||||
gdb.execute('set $rbp = %s' % old_rbp)
|
gdb.execute('set $%s = %s' % (i, old[i]))
|
||||||
gdb.execute('set $rsp = %s' % old_rsp)
|
|
||||||
gdb.execute('set $r12 = %s' % old_r12)
|
def coroutine_to_jmpbuf(co):
|
||||||
gdb.execute('set $r13 = %s' % old_r13)
|
coroutine_pointer = co.cast(gdb.lookup_type('CoroutineUContext').pointer())
|
||||||
gdb.execute('set $r14 = %s' % old_r14)
|
return coroutine_pointer['env']['__jmpbuf']
|
||||||
gdb.execute('set $r15 = %s' % old_r15)
|
|
||||||
gdb.execute('set $rip = %s' % old_rip)
|
|
||||||
|
|
||||||
|
|
||||||
class CoroutineCommand(gdb.Command):
|
class CoroutineCommand(gdb.Command):
|
||||||
|
@ -87,5 +102,18 @@ class CoroutineCommand(gdb.Command):
|
||||||
gdb.write('usage: qemu coroutine <coroutine-pointer>\n')
|
gdb.write('usage: qemu coroutine <coroutine-pointer>\n')
|
||||||
return
|
return
|
||||||
|
|
||||||
coroutine_pointer = gdb.parse_and_eval(argv[0]).cast(gdb.lookup_type('CoroutineUContext').pointer())
|
bt_jmpbuf(coroutine_to_jmpbuf(gdb.parse_and_eval(argv[0])))
|
||||||
bt_jmpbuf(coroutine_pointer['env']['__jmpbuf'])
|
|
||||||
|
class CoroutineSPFunction(gdb.Function):
|
||||||
|
def __init__(self):
|
||||||
|
gdb.Function.__init__(self, 'qemu_coroutine_sp')
|
||||||
|
|
||||||
|
def invoke(self, addr):
|
||||||
|
return get_jmpbuf_regs(coroutine_to_jmpbuf(addr))['rsp'].cast(VOID_PTR)
|
||||||
|
|
||||||
|
class CoroutinePCFunction(gdb.Function):
|
||||||
|
def __init__(self):
|
||||||
|
gdb.Function.__init__(self, 'qemu_coroutine_pc')
|
||||||
|
|
||||||
|
def invoke(self, addr):
|
||||||
|
return get_jmpbuf_regs(coroutine_to_jmpbuf(addr))['rip'].cast(VOID_PTR)
|
||||||
|
|
Loading…
Reference in New Issue