Compare commits
126
Commits
v1.2.0-rc0
...
v1.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8db972cfa4 | ||
|
|
3eea5498ca | ||
|
|
de188751da | ||
|
|
e7eee62a90 | ||
|
|
0232cd355d | ||
|
|
8bd6b06d7b | ||
|
|
23aec6005a | ||
|
|
cdedd9d867 | ||
|
|
347e40ffe6 | ||
|
|
adf478342b | ||
|
|
287fd3f1dd | ||
|
|
c7cdca3b85 | ||
|
|
574ef17191 | ||
|
|
53dd6f7032 | ||
|
|
a1c3e4b839 | ||
|
|
7ce86aa1aa | ||
|
|
e983395d30 | ||
|
|
0132b4b659 | ||
|
|
da9fbe76a0 | ||
|
|
b834b5081d | ||
|
|
c9a238e700 | ||
|
|
5bb0b62e75 | ||
|
|
3cac001e5a | ||
|
|
bc9a839d56 | ||
|
|
651682dcf5 | ||
|
|
ef8621b1a3 | ||
|
|
4d09d37c6a | ||
|
|
4bdb1a3059 | ||
|
|
7e2a62d82a | ||
|
|
7e7de876ae | ||
|
|
998a74bcda | ||
|
|
774a8850d7 | ||
|
|
571cd9dcc7 | ||
|
|
ef72f76e58 | ||
|
|
1e2778d59d | ||
|
|
7dd6f4b250 | ||
|
|
18fec301cd | ||
|
|
ce67604048 | ||
|
|
54cddd21b0 | ||
|
|
13ef70f64e | ||
|
|
135b908878 | ||
|
|
0f1da449ec | ||
|
|
9ea73f8b10 | ||
|
|
fb6541571e | ||
|
|
36c6711bbe | ||
|
|
2e15497c5b | ||
|
|
08406b035e | ||
|
|
9f227bc358 | ||
|
|
e4558dcae8 | ||
|
|
df8002103c | ||
|
|
4f213879f3 | ||
|
|
b316728836 | ||
|
|
0516867450 | ||
|
|
13d24f4972 | ||
|
|
d22d728987 | ||
|
|
097b8cb840 | ||
|
|
333858b77c | ||
|
|
42644cee08 | ||
|
|
d03c98d80f | ||
|
|
18d445b443 | ||
|
|
9716ef3b1b | ||
|
|
f278d4947f | ||
|
|
482f7bf86b | ||
|
|
39dda26062 | ||
|
|
7764ae9671 | ||
|
|
5c73b757e3 | ||
|
|
145c7c880f | ||
|
|
98609cd8fc | ||
|
|
da5a44e8b0 | ||
|
|
26efaca377 | ||
|
|
6fc97fafce | ||
|
|
94159135cb | ||
|
|
58617a795c | ||
|
|
b4a738bf93 | ||
|
|
af506c7036 | ||
|
|
86759aa89d | ||
|
|
b100fcfe49 | ||
|
|
a9b670b139 | ||
|
|
7b2f89c435 | ||
|
|
b6825cd79c | ||
|
|
99afc91d6c | ||
|
|
67c332fd12 | ||
|
|
8558d942b6 | ||
|
|
b44ff9d430 | ||
|
|
57fd7b7fce | ||
|
|
8c9f64df3d | ||
|
|
03a6b66770 | ||
|
|
9c1a61f0e5 | ||
|
|
42c281a283 | ||
|
|
8d43d7e591 | ||
|
|
0e655047c5 | ||
|
|
ab61536737 | ||
|
|
c5589ee974 | ||
|
|
94dd91d651 | ||
|
|
4240abff5a | ||
|
|
ea776abca6 | ||
|
|
15d9e3bc6a | ||
|
|
396bef4b38 | ||
|
|
a7e47d4bfc | ||
|
|
0d07fe47d4 | ||
|
|
4144f122b4 | ||
|
|
14d4018372 | ||
|
|
27b7652ef5 | ||
|
|
0ec64507a5 | ||
|
|
55ce75faf2 | ||
|
|
7aa939af39 | ||
|
|
b2dc64c391 | ||
|
|
e36c87667a | ||
|
|
07a5298c30 | ||
|
|
1bd075f29e | ||
|
|
cfb3f5064a | ||
|
|
27cbd828c6 | ||
|
|
b209091957 | ||
|
|
682527c004 | ||
|
|
e89001f72e | ||
|
|
ff96101552 | ||
|
|
d83c951cce | ||
|
|
5f893b4e9c | ||
|
|
eec7f96c2c | ||
|
|
48467328c6 | ||
|
|
65bd155c73 | ||
|
|
7a736bfa4e | ||
|
|
47d073cc3b | ||
|
|
6d3b6d3d2d | ||
|
|
0daf53047d | ||
|
|
c19537a114 |
No files matched your search
+11
@@ -44,6 +44,7 @@
|
||||
#include "exec-memory.h"
|
||||
#include "hw/pcspk.h"
|
||||
#include "qemu/page_cache.h"
|
||||
#include "qmp-commands.h"
|
||||
|
||||
#ifdef DEBUG_ARCH_INIT
|
||||
#define DPRINTF(fmt, ...) \
|
||||
@@ -1080,3 +1081,13 @@ int xen_available(void)
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
TargetInfo *qmp_query_target(Error **errp)
|
||||
{
|
||||
TargetInfo *info = g_malloc0(sizeof(*info));
|
||||
|
||||
info->arch = TARGET_TYPE;
|
||||
|
||||
return info;
|
||||
}
|
||||
@@ -349,21 +349,15 @@ static int winwave_ctl_out (HWVoiceOut *hw, int cmd, ...)
|
||||
else {
|
||||
hw->poll_mode = 0;
|
||||
}
|
||||
if (wave->paused) {
|
||||
mr = waveOutRestart (wave->hwo);
|
||||
if (mr != MMSYSERR_NOERROR) {
|
||||
winwave_logerr (mr, "waveOutRestart");
|
||||
}
|
||||
wave->paused = 0;
|
||||
}
|
||||
wave->paused = 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case VOICE_DISABLE:
|
||||
if (!wave->paused) {
|
||||
mr = waveOutPause (wave->hwo);
|
||||
mr = waveOutReset (wave->hwo);
|
||||
if (mr != MMSYSERR_NOERROR) {
|
||||
winwave_logerr (mr, "waveOutPause");
|
||||
winwave_logerr (mr, "waveOutReset");
|
||||
}
|
||||
else {
|
||||
wave->paused = 1;
|
||||
|
||||
+69
-60
@@ -72,14 +72,44 @@ struct IscsiTask {
|
||||
int complete;
|
||||
};
|
||||
|
||||
static void
|
||||
iscsi_bh_cb(void *p)
|
||||
{
|
||||
IscsiAIOCB *acb = p;
|
||||
|
||||
qemu_bh_delete(acb->bh);
|
||||
|
||||
if (acb->canceled == 0) {
|
||||
acb->common.cb(acb->common.opaque, acb->status);
|
||||
}
|
||||
|
||||
if (acb->task != NULL) {
|
||||
scsi_free_scsi_task(acb->task);
|
||||
acb->task = NULL;
|
||||
}
|
||||
|
||||
qemu_aio_release(acb);
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_schedule_bh(IscsiAIOCB *acb)
|
||||
{
|
||||
if (acb->bh) {
|
||||
return;
|
||||
}
|
||||
acb->bh = qemu_bh_new(iscsi_bh_cb, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
|
||||
void *private_data)
|
||||
{
|
||||
IscsiAIOCB *acb = (IscsiAIOCB *)private_data;
|
||||
IscsiAIOCB *acb = private_data;
|
||||
|
||||
scsi_free_scsi_task(acb->task);
|
||||
acb->task = NULL;
|
||||
acb->status = -ECANCELED;
|
||||
iscsi_schedule_bh(acb);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -88,15 +118,19 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
|
||||
IscsiLun *iscsilun = acb->iscsilun;
|
||||
|
||||
if (acb->status != -EINPROGRESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
acb->canceled = 1;
|
||||
|
||||
acb->common.cb(acb->common.opaque, -ECANCELED);
|
||||
|
||||
/* send a task mgmt call to the target to cancel the task on the target
|
||||
* this also cancels the task in libiscsi
|
||||
*/
|
||||
/* send a task mgmt call to the target to cancel the task on the target */
|
||||
iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task,
|
||||
iscsi_abort_task_cb, &acb);
|
||||
iscsi_abort_task_cb, acb);
|
||||
|
||||
while (acb->status == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
}
|
||||
}
|
||||
|
||||
static AIOPool iscsi_aio_pool = {
|
||||
@@ -163,41 +197,6 @@ iscsi_process_write(void *arg)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
iscsi_schedule_bh(QEMUBHFunc *cb, IscsiAIOCB *acb)
|
||||
{
|
||||
acb->bh = qemu_bh_new(cb, acb);
|
||||
if (!acb->bh) {
|
||||
error_report("oom: could not create iscsi bh");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
qemu_bh_schedule(acb->bh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_readv_writev_bh_cb(void *p)
|
||||
{
|
||||
IscsiAIOCB *acb = p;
|
||||
|
||||
qemu_bh_delete(acb->bh);
|
||||
|
||||
if (!acb->canceled) {
|
||||
acb->common.cb(acb->common.opaque, acb->status);
|
||||
}
|
||||
|
||||
qemu_aio_release(acb);
|
||||
|
||||
if (acb->canceled) {
|
||||
return;
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(acb->task);
|
||||
acb->task = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
|
||||
void *command_data, void *opaque)
|
||||
@@ -208,8 +207,7 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
|
||||
|
||||
g_free(acb->buf);
|
||||
|
||||
if (acb->canceled) {
|
||||
qemu_aio_release(acb);
|
||||
if (acb->canceled != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -220,7 +218,7 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
|
||||
acb->status = -EIO;
|
||||
}
|
||||
|
||||
iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
|
||||
iscsi_schedule_bh(acb);
|
||||
}
|
||||
|
||||
static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
|
||||
@@ -249,6 +247,8 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
acb->qiov = qiov;
|
||||
|
||||
acb->canceled = 0;
|
||||
acb->bh = NULL;
|
||||
acb->status = -EINPROGRESS;
|
||||
|
||||
/* XXX we should pass the iovec to write16 to avoid the extra copy */
|
||||
/* this will allow us to get rid of 'buf' completely */
|
||||
@@ -305,8 +305,7 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
|
||||
|
||||
trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
|
||||
|
||||
if (acb->canceled) {
|
||||
qemu_aio_release(acb);
|
||||
if (acb->canceled != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -317,7 +316,7 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
|
||||
acb->status = -EIO;
|
||||
}
|
||||
|
||||
iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
|
||||
iscsi_schedule_bh(acb);
|
||||
}
|
||||
|
||||
static BlockDriverAIOCB *
|
||||
@@ -343,6 +342,8 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
acb->qiov = qiov;
|
||||
|
||||
acb->canceled = 0;
|
||||
acb->bh = NULL;
|
||||
acb->status = -EINPROGRESS;
|
||||
acb->read_size = qemu_read_size;
|
||||
acb->buf = NULL;
|
||||
|
||||
@@ -417,8 +418,7 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
|
||||
{
|
||||
IscsiAIOCB *acb = opaque;
|
||||
|
||||
if (acb->canceled) {
|
||||
qemu_aio_release(acb);
|
||||
if (acb->canceled != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -429,7 +429,7 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
|
||||
acb->status = -EIO;
|
||||
}
|
||||
|
||||
iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
|
||||
iscsi_schedule_bh(acb);
|
||||
}
|
||||
|
||||
static BlockDriverAIOCB *
|
||||
@@ -444,6 +444,8 @@ iscsi_aio_flush(BlockDriverState *bs,
|
||||
|
||||
acb->iscsilun = iscsilun;
|
||||
acb->canceled = 0;
|
||||
acb->bh = NULL;
|
||||
acb->status = -EINPROGRESS;
|
||||
|
||||
acb->task = iscsi_synchronizecache10_task(iscsi, iscsilun->lun,
|
||||
0, 0, 0, 0,
|
||||
@@ -467,8 +469,7 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
|
||||
{
|
||||
IscsiAIOCB *acb = opaque;
|
||||
|
||||
if (acb->canceled) {
|
||||
qemu_aio_release(acb);
|
||||
if (acb->canceled != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -479,7 +480,7 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
|
||||
acb->status = -EIO;
|
||||
}
|
||||
|
||||
iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
|
||||
iscsi_schedule_bh(acb);
|
||||
}
|
||||
|
||||
static BlockDriverAIOCB *
|
||||
@@ -496,6 +497,8 @@ iscsi_aio_discard(BlockDriverState *bs,
|
||||
|
||||
acb->iscsilun = iscsilun;
|
||||
acb->canceled = 0;
|
||||
acb->bh = NULL;
|
||||
acb->status = -EINPROGRESS;
|
||||
|
||||
list[0].lba = sector_qemu2lun(sector_num, iscsilun);
|
||||
list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size;
|
||||
@@ -523,8 +526,7 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
|
||||
{
|
||||
IscsiAIOCB *acb = opaque;
|
||||
|
||||
if (acb->canceled) {
|
||||
qemu_aio_release(acb);
|
||||
if (acb->canceled != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -552,7 +554,7 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
|
||||
memcpy(acb->ioh->sbp, &acb->task->datain.data[2], ss);
|
||||
}
|
||||
|
||||
iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
|
||||
iscsi_schedule_bh(acb);
|
||||
}
|
||||
|
||||
static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
|
||||
@@ -570,6 +572,8 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
|
||||
|
||||
acb->iscsilun = iscsilun;
|
||||
acb->canceled = 0;
|
||||
acb->bh = NULL;
|
||||
acb->status = -EINPROGRESS;
|
||||
acb->buf = NULL;
|
||||
acb->ioh = buf;
|
||||
|
||||
@@ -717,7 +721,12 @@ iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
|
||||
}
|
||||
|
||||
itask->iscsilun->block_size = rc10->block_size;
|
||||
itask->iscsilun->num_blocks = rc10->lba + 1;
|
||||
if (rc10->lba == 0) {
|
||||
/* blank disk loaded */
|
||||
itask->iscsilun->num_blocks = 0;
|
||||
} else {
|
||||
itask->iscsilun->num_blocks = rc10->lba + 1;
|
||||
}
|
||||
itask->bs->total_sectors = itask->iscsilun->num_blocks *
|
||||
itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
|
||||
|
||||
|
||||
+11
@@ -1363,10 +1363,21 @@ static int coroutine_fn bdrv_qed_co_write_zeroes(BlockDriverState *bs,
|
||||
int nb_sectors)
|
||||
{
|
||||
BlockDriverAIOCB *blockacb;
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
QEDWriteZeroesCB cb = { .done = false };
|
||||
QEMUIOVector qiov;
|
||||
struct iovec iov;
|
||||
|
||||
/* Refuse if there are untouched backing file sectors */
|
||||
if (bs->backing_hd) {
|
||||
if (qed_offset_into_cluster(s, sector_num * BDRV_SECTOR_SIZE) != 0) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
if (qed_offset_into_cluster(s, nb_sectors * BDRV_SECTOR_SIZE) != 0) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
/* Zero writes start without an I/O buffer. If a buffer becomes necessary
|
||||
* then it will be allocated during request processing.
|
||||
*/
|
||||
|
||||
@@ -485,6 +485,7 @@ static int connect_to_sdog(const char *addr, const char *port)
|
||||
if (errno == EINTR) {
|
||||
goto reconnect;
|
||||
}
|
||||
close(fd);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +122,12 @@ wait:
|
||||
* known-unallocated area [sector_num, sector_num+n). */
|
||||
ret = bdrv_co_is_allocated_above(bs->backing_hd, base,
|
||||
sector_num, n, &n);
|
||||
|
||||
/* Finish early if end of backing file has been reached */
|
||||
if (ret == 0 && n == 0) {
|
||||
n = end - sector_num;
|
||||
}
|
||||
|
||||
copy = (ret == 1);
|
||||
}
|
||||
trace_stream_one_iteration(s, sector_num, n, ret);
|
||||
|
||||
+57
-1
@@ -35,6 +35,7 @@
|
||||
#define VMDK4_FLAG_RGD (1 << 1)
|
||||
#define VMDK4_FLAG_COMPRESS (1 << 16)
|
||||
#define VMDK4_FLAG_MARKER (1 << 17)
|
||||
#define VMDK4_GD_AT_END 0xffffffffffffffffULL
|
||||
|
||||
typedef struct {
|
||||
uint32_t version;
|
||||
@@ -57,8 +58,8 @@ typedef struct {
|
||||
int64_t desc_offset;
|
||||
int64_t desc_size;
|
||||
int32_t num_gtes_per_gte;
|
||||
int64_t gd_offset;
|
||||
int64_t rgd_offset;
|
||||
int64_t gd_offset;
|
||||
int64_t grain_offset;
|
||||
char filler[1];
|
||||
char check_bytes[4];
|
||||
@@ -115,6 +116,13 @@ typedef struct VmdkGrainMarker {
|
||||
uint8_t data[0];
|
||||
} VmdkGrainMarker;
|
||||
|
||||
enum {
|
||||
MARKER_END_OF_STREAM = 0,
|
||||
MARKER_GRAIN_TABLE = 1,
|
||||
MARKER_GRAIN_DIRECTORY = 2,
|
||||
MARKER_FOOTER = 3,
|
||||
};
|
||||
|
||||
static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||
{
|
||||
uint32_t magic;
|
||||
@@ -451,6 +459,54 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
||||
if (header.capacity == 0 && header.desc_offset) {
|
||||
return vmdk_open_desc_file(bs, flags, header.desc_offset << 9);
|
||||
}
|
||||
|
||||
if (le64_to_cpu(header.gd_offset) == VMDK4_GD_AT_END) {
|
||||
/*
|
||||
* The footer takes precedence over the header, so read it in. The
|
||||
* footer starts at offset -1024 from the end: One sector for the
|
||||
* footer, and another one for the end-of-stream marker.
|
||||
*/
|
||||
struct {
|
||||
struct {
|
||||
uint64_t val;
|
||||
uint32_t size;
|
||||
uint32_t type;
|
||||
uint8_t pad[512 - 16];
|
||||
} QEMU_PACKED footer_marker;
|
||||
|
||||
uint32_t magic;
|
||||
VMDK4Header header;
|
||||
uint8_t pad[512 - 4 - sizeof(VMDK4Header)];
|
||||
|
||||
struct {
|
||||
uint64_t val;
|
||||
uint32_t size;
|
||||
uint32_t type;
|
||||
uint8_t pad[512 - 16];
|
||||
} QEMU_PACKED eos_marker;
|
||||
} QEMU_PACKED footer;
|
||||
|
||||
ret = bdrv_pread(file,
|
||||
bs->file->total_sectors * 512 - 1536,
|
||||
&footer, sizeof(footer));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Some sanity checks for the footer */
|
||||
if (be32_to_cpu(footer.magic) != VMDK4_MAGIC ||
|
||||
le32_to_cpu(footer.footer_marker.size) != 0 ||
|
||||
le32_to_cpu(footer.footer_marker.type) != MARKER_FOOTER ||
|
||||
le64_to_cpu(footer.eos_marker.val) != 0 ||
|
||||
le32_to_cpu(footer.eos_marker.size) != 0 ||
|
||||
le32_to_cpu(footer.eos_marker.type) != MARKER_END_OF_STREAM)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
header = footer.header;
|
||||
}
|
||||
|
||||
l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
|
||||
* le64_to_cpu(header.granularity);
|
||||
if (l1_entry_sectors == 0) {
|
||||
|
||||
@@ -3834,14 +3834,19 @@ case "$target_arch2" in
|
||||
;;
|
||||
esac
|
||||
|
||||
upper() {
|
||||
echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]'
|
||||
}
|
||||
|
||||
echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak
|
||||
echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak
|
||||
echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak
|
||||
echo "TARGET_LLONG_ALIGNMENT=$target_llong_alignment" >> $config_target_mak
|
||||
echo "TARGET_ARCH=$TARGET_ARCH" >> $config_target_mak
|
||||
target_arch_name="`echo $TARGET_ARCH | LC_ALL=C tr '[a-z]' '[A-Z]'`"
|
||||
target_arch_name="`upper $TARGET_ARCH`"
|
||||
echo "TARGET_$target_arch_name=y" >> $config_target_mak
|
||||
echo "TARGET_ARCH2=$target_arch2" >> $config_target_mak
|
||||
echo "TARGET_TYPE=TARGET_TYPE_`upper $target_arch2`" >> $config_target_mak
|
||||
echo "TARGET_BASE_ARCH=$TARGET_BASE_ARCH" >> $config_target_mak
|
||||
if [ "$TARGET_ABI_DIR" = "" ]; then
|
||||
TARGET_ABI_DIR=$TARGET_ARCH
|
||||
|
||||
@@ -850,6 +850,26 @@ static void console_clear_xy(TextConsole *s, int x, int y)
|
||||
update_xy(s, x, y);
|
||||
}
|
||||
|
||||
/* set cursor, checking bounds */
|
||||
static void set_cursor(TextConsole *s, int x, int y)
|
||||
{
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
}
|
||||
if (y >= s->height) {
|
||||
y = s->height - 1;
|
||||
}
|
||||
if (x >= s->width) {
|
||||
x = s->width - 1;
|
||||
}
|
||||
|
||||
s->x = x;
|
||||
s->y = y;
|
||||
}
|
||||
|
||||
static void console_putchar(TextConsole *s, int ch)
|
||||
{
|
||||
TextCell *c;
|
||||
@@ -921,7 +941,8 @@ static void console_putchar(TextConsole *s, int ch)
|
||||
s->esc_params[s->nb_esc_params] * 10 + ch - '0';
|
||||
}
|
||||
} else {
|
||||
s->nb_esc_params++;
|
||||
if (s->nb_esc_params < MAX_ESC_PARAMS)
|
||||
s->nb_esc_params++;
|
||||
if (ch == ';')
|
||||
break;
|
||||
#ifdef DEBUG_CONSOLE
|
||||
@@ -935,59 +956,37 @@ static void console_putchar(TextConsole *s, int ch)
|
||||
if (s->esc_params[0] == 0) {
|
||||
s->esc_params[0] = 1;
|
||||
}
|
||||
s->y -= s->esc_params[0];
|
||||
if (s->y < 0) {
|
||||
s->y = 0;
|
||||
}
|
||||
set_cursor(s, s->x, s->y - s->esc_params[0]);
|
||||
break;
|
||||
case 'B':
|
||||
/* move cursor down */
|
||||
if (s->esc_params[0] == 0) {
|
||||
s->esc_params[0] = 1;
|
||||
}
|
||||
s->y += s->esc_params[0];
|
||||
if (s->y >= s->height) {
|
||||
s->y = s->height - 1;
|
||||
}
|
||||
set_cursor(s, s->x, s->y + s->esc_params[0]);
|
||||
break;
|
||||
case 'C':
|
||||
/* move cursor right */
|
||||
if (s->esc_params[0] == 0) {
|
||||
s->esc_params[0] = 1;
|
||||
}
|
||||
s->x += s->esc_params[0];
|
||||
if (s->x >= s->width) {
|
||||
s->x = s->width - 1;
|
||||
}
|
||||
set_cursor(s, s->x + s->esc_params[0], s->y);
|
||||
break;
|
||||
case 'D':
|
||||
/* move cursor left */
|
||||
if (s->esc_params[0] == 0) {
|
||||
s->esc_params[0] = 1;
|
||||
}
|
||||
s->x -= s->esc_params[0];
|
||||
if (s->x < 0) {
|
||||
s->x = 0;
|
||||
}
|
||||
set_cursor(s, s->x - s->esc_params[0], s->y);
|
||||
break;
|
||||
case 'G':
|
||||
/* move cursor to column */
|
||||
s->x = s->esc_params[0] - 1;
|
||||
if (s->x < 0) {
|
||||
s->x = 0;
|
||||
}
|
||||
set_cursor(s, s->esc_params[0] - 1, s->y);
|
||||
break;
|
||||
case 'f':
|
||||
case 'H':
|
||||
/* move cursor to row, column */
|
||||
s->x = s->esc_params[1] - 1;
|
||||
if (s->x < 0) {
|
||||
s->x = 0;
|
||||
}
|
||||
s->y = s->esc_params[0] - 1;
|
||||
if (s->y < 0) {
|
||||
s->y = 0;
|
||||
}
|
||||
set_cursor(s, s->esc_params[1] - 1, s->esc_params[0] - 1);
|
||||
break;
|
||||
case 'J':
|
||||
switch (s->esc_params[0]) {
|
||||
@@ -1087,7 +1086,7 @@ void console_select(unsigned int index)
|
||||
if (s) {
|
||||
DisplayState *ds = s->ds;
|
||||
|
||||
if (active_console->cursor_timer) {
|
||||
if (active_console && active_console->cursor_timer) {
|
||||
qemu_del_timer(active_console->cursor_timer);
|
||||
}
|
||||
active_console = s;
|
||||
|
||||
@@ -149,6 +149,8 @@ void hmp_info_migrate(Monitor *mon)
|
||||
|
||||
if (info->has_status) {
|
||||
monitor_printf(mon, "Migration status: %s\n", info->status);
|
||||
monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n",
|
||||
info->total_time);
|
||||
}
|
||||
|
||||
if (info->has_ram) {
|
||||
@@ -158,8 +160,6 @@ void hmp_info_migrate(Monitor *mon)
|
||||
info->ram->remaining >> 10);
|
||||
monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n",
|
||||
info->ram->total >> 10);
|
||||
monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n",
|
||||
info->ram->total_time);
|
||||
monitor_printf(mon, "duplicate: %" PRIu64 " pages\n",
|
||||
info->ram->duplicate);
|
||||
monitor_printf(mon, "normal: %" PRIu64 " pages\n",
|
||||
|
||||
@@ -134,6 +134,8 @@ hw-obj-$(CONFIG_DP8393X) += dp8393x.o
|
||||
hw-obj-$(CONFIG_DS1225Y) += ds1225y.o
|
||||
hw-obj-$(CONFIG_MIPSNET) += mipsnet.o
|
||||
|
||||
hw-obj-y += null-machine.o
|
||||
|
||||
# Sound
|
||||
sound-obj-y =
|
||||
sound-obj-$(CONFIG_SB16) += sb16.o
|
||||
|
||||
+3
-3
@@ -305,7 +305,6 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
|
||||
if (pc->no_hotplug) {
|
||||
slot_free = false;
|
||||
} else {
|
||||
object_unparent(OBJECT(dev));
|
||||
qdev_free(qdev);
|
||||
}
|
||||
}
|
||||
@@ -353,6 +352,9 @@ static void piix4_reset(void *opaque)
|
||||
pci_conf[0x5a] = 0;
|
||||
pci_conf[0x5b] = 0;
|
||||
|
||||
pci_conf[0x40] = 0x01; /* PM io base read only bit */
|
||||
pci_conf[0x80] = 0;
|
||||
|
||||
if (s->kvm_enabled) {
|
||||
/* Mark SMM as already inited (until KVM supports SMM). */
|
||||
pci_conf[0x5B] = 0x02;
|
||||
@@ -392,8 +394,6 @@ static int piix4_pm_initfn(PCIDevice *dev)
|
||||
pci_conf[0x09] = 0x00;
|
||||
pci_conf[0x3d] = 0x01; // interrupt pin 1
|
||||
|
||||
pci_conf[0x40] = 0x01; /* PM io base read only bit */
|
||||
|
||||
/* APM */
|
||||
apm_init(&s->apm, apm_ctrl_changed, s);
|
||||
|
||||
|
||||
+16
-10
@@ -15,6 +15,8 @@
|
||||
#include "exec-memory.h"
|
||||
|
||||
|
||||
#define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost"
|
||||
|
||||
typedef struct TyphoonCchip {
|
||||
MemoryRegion region;
|
||||
uint64_t misc;
|
||||
@@ -40,8 +42,12 @@ typedef struct TyphoonPchip {
|
||||
TyphoonWindow win[4];
|
||||
} TyphoonPchip;
|
||||
|
||||
#define TYPHOON_PCI_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(TyphoonState, (obj), TYPE_TYPHOON_PCI_HOST_BRIDGE)
|
||||
|
||||
typedef struct TyphoonState {
|
||||
PCIHostState host;
|
||||
PCIHostState parent_obj;
|
||||
|
||||
TyphoonCchip cchip;
|
||||
TyphoonPchip pchip;
|
||||
MemoryRegion dchip_region;
|
||||
@@ -700,16 +706,16 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
|
||||
MemoryRegion *addr_space = get_system_memory();
|
||||
MemoryRegion *addr_space_io = get_system_io();
|
||||
DeviceState *dev;
|
||||
PCIHostState *p;
|
||||
TyphoonState *s;
|
||||
PCIHostState *phb;
|
||||
PCIBus *b;
|
||||
int i;
|
||||
|
||||
dev = qdev_create(NULL, "typhoon-pcihost");
|
||||
dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE);
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
p = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
|
||||
s = container_of(p, TyphoonState, host);
|
||||
s = TYPHOON_PCI_HOST_BRIDGE(dev);
|
||||
phb = PCI_HOST_BRIDGE(dev);
|
||||
|
||||
/* Remember the CPUs so that we can deliver interrupts to them. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
@@ -763,10 +769,10 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
|
||||
memory_region_add_subregion(addr_space, 0x801fc000000ULL,
|
||||
&s->pchip.reg_io);
|
||||
|
||||
b = pci_register_bus(&s->host.busdev.qdev, "pci",
|
||||
b = pci_register_bus(dev, "pci",
|
||||
typhoon_set_irq, sys_map_irq, s,
|
||||
&s->pchip.reg_mem, addr_space_io, 0, 64);
|
||||
s->host.bus = b;
|
||||
phb->bus = b;
|
||||
|
||||
/* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB. */
|
||||
memory_region_init_io(&s->pchip.reg_iack, &alpha_pci_iack_ops, b,
|
||||
@@ -817,9 +823,9 @@ static void typhoon_pcihost_class_init(ObjectClass *klass, void *data)
|
||||
dc->no_user = 1;
|
||||
}
|
||||
|
||||
static TypeInfo typhoon_pcihost_info = {
|
||||
.name = "typhoon-pcihost",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo typhoon_pcihost_info = {
|
||||
.name = TYPE_TYPHOON_PCI_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(TyphoonState),
|
||||
.class_init = typhoon_pcihost_class_init,
|
||||
};
|
||||
|
||||
@@ -703,6 +703,7 @@ static TypeInfo arm_gic_info = {
|
||||
.parent = TYPE_ARM_GIC_COMMON,
|
||||
.instance_size = sizeof(gic_state),
|
||||
.class_init = arm_gic_class_init,
|
||||
.class_size = sizeof(ARMGICClass),
|
||||
};
|
||||
|
||||
static void arm_gic_register_types(void)
|
||||
|
||||
+93
-59
@@ -180,11 +180,14 @@
|
||||
#define PCI_ADDR(busno,devno,funno,regno) \
|
||||
((((busno)<<16)&0xff0000) + (((devno)<<11)&0xf800) + (((funno)<<8)&0x700) + (regno))
|
||||
|
||||
typedef PCIHostState BonitoState;
|
||||
#define TYPE_BONITO_PCI_HOST_BRIDGE "Bonito-pcihost"
|
||||
|
||||
typedef struct BonitoState BonitoState;
|
||||
|
||||
typedef struct PCIBonitoState
|
||||
{
|
||||
PCIDevice dev;
|
||||
|
||||
BonitoState *pcihost;
|
||||
uint32_t regs[BONITO_REGS];
|
||||
|
||||
@@ -218,7 +221,16 @@ typedef struct PCIBonitoState
|
||||
|
||||
} PCIBonitoState;
|
||||
|
||||
PCIBonitoState * bonito_state;
|
||||
#define BONITO_PCI_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(BonitoState, (obj), TYPE_BONITO_PCI_HOST_BRIDGE)
|
||||
|
||||
struct BonitoState {
|
||||
PCIHostState parent_obj;
|
||||
|
||||
qemu_irq *pic;
|
||||
|
||||
PCIBonitoState *pci_dev;
|
||||
};
|
||||
|
||||
static void bonito_writel(void *opaque, target_phys_addr_t addr,
|
||||
uint64_t val, unsigned size)
|
||||
@@ -314,9 +326,10 @@ static void bonito_pciconf_writel(void *opaque, target_phys_addr_t addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
PCIBonitoState *s = opaque;
|
||||
PCIDevice *d = PCI_DEVICE(s);
|
||||
|
||||
DPRINTF("bonito_pciconf_writel "TARGET_FMT_plx" val %x\n", addr, val);
|
||||
s->dev.config_write(&s->dev, addr, val, 4);
|
||||
d->config_write(d, addr, val, 4);
|
||||
}
|
||||
|
||||
static uint64_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr,
|
||||
@@ -324,9 +337,10 @@ static uint64_t bonito_pciconf_readl(void *opaque, target_phys_addr_t addr,
|
||||
{
|
||||
|
||||
PCIBonitoState *s = opaque;
|
||||
PCIDevice *d = PCI_DEVICE(s);
|
||||
|
||||
DPRINTF("bonito_pciconf_readl "TARGET_FMT_plx"\n", addr);
|
||||
return s->dev.config_read(&s->dev, addr, 4);
|
||||
return d->config_read(d, addr, 4);
|
||||
}
|
||||
|
||||
/* north bridge PCI configure space. 0x1fe0 0000 - 0x1fe0 00ff */
|
||||
@@ -402,6 +416,7 @@ static const MemoryRegionOps bonito_cop_ops = {
|
||||
static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
PCIBonitoState *s = opaque;
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
|
||||
uint32_t cfgaddr;
|
||||
uint32_t idsel;
|
||||
uint32_t devno;
|
||||
@@ -423,13 +438,13 @@ static uint32_t bonito_sbridge_pciaddr(void *opaque, target_phys_addr_t addr)
|
||||
regno = (cfgaddr & BONITO_PCICONF_REG_MASK) >> BONITO_PCICONF_REG_OFFSET;
|
||||
|
||||
if (idsel == 0) {
|
||||
fprintf(stderr, "error in bonito pci config address" TARGET_FMT_plx
|
||||
fprintf(stderr, "error in bonito pci config address " TARGET_FMT_plx
|
||||
",pcimap_cfg=%x\n", addr, s->regs[BONITO_PCIMAP_CFG]);
|
||||
exit(1);
|
||||
}
|
||||
pciaddr = PCI_ADDR(pci_bus_num(s->pcihost->bus), devno, funno, regno);
|
||||
pciaddr = PCI_ADDR(pci_bus_num(phb->bus), devno, funno, regno);
|
||||
DPRINTF("cfgaddr %x pciaddr %x busno %x devno %d funno %d regno %d\n",
|
||||
cfgaddr, pciaddr, pci_bus_num(s->pcihost->bus), devno, funno, regno);
|
||||
cfgaddr, pciaddr, pci_bus_num(phb->bus), devno, funno, regno);
|
||||
|
||||
return pciaddr;
|
||||
}
|
||||
@@ -438,6 +453,8 @@ static void bonito_spciconf_writeb(void *opaque, target_phys_addr_t addr,
|
||||
uint32_t val)
|
||||
{
|
||||
PCIBonitoState *s = opaque;
|
||||
PCIDevice *d = PCI_DEVICE(s);
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
|
||||
uint32_t pciaddr;
|
||||
uint16_t status;
|
||||
|
||||
@@ -449,24 +466,26 @@ static void bonito_spciconf_writeb(void *opaque, target_phys_addr_t addr,
|
||||
}
|
||||
|
||||
/* set the pci address in s->config_reg */
|
||||
s->pcihost->config_reg = (pciaddr) | (1u << 31);
|
||||
pci_data_write(s->pcihost->bus, s->pcihost->config_reg, val & 0xff, 1);
|
||||
phb->config_reg = (pciaddr) | (1u << 31);
|
||||
pci_data_write(phb->bus, phb->config_reg, val & 0xff, 1);
|
||||
|
||||
/* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
|
||||
status = pci_get_word(s->dev.config + PCI_STATUS);
|
||||
status = pci_get_word(d->config + PCI_STATUS);
|
||||
status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
|
||||
pci_set_word(s->dev.config + PCI_STATUS, status);
|
||||
pci_set_word(d->config + PCI_STATUS, status);
|
||||
}
|
||||
|
||||
static void bonito_spciconf_writew(void *opaque, target_phys_addr_t addr,
|
||||
uint32_t val)
|
||||
{
|
||||
PCIBonitoState *s = opaque;
|
||||
PCIDevice *d = PCI_DEVICE(s);
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
|
||||
uint32_t pciaddr;
|
||||
uint16_t status;
|
||||
|
||||
DPRINTF("bonito_spciconf_writew "TARGET_FMT_plx" val %x\n", addr, val);
|
||||
assert((addr&0x1)==0);
|
||||
assert((addr & 0x1) == 0);
|
||||
|
||||
pciaddr = bonito_sbridge_pciaddr(s, addr);
|
||||
|
||||
@@ -475,24 +494,26 @@ static void bonito_spciconf_writew(void *opaque, target_phys_addr_t addr,
|
||||
}
|
||||
|
||||
/* set the pci address in s->config_reg */
|
||||
s->pcihost->config_reg = (pciaddr) | (1u << 31);
|
||||
pci_data_write(s->pcihost->bus, s->pcihost->config_reg, val, 2);
|
||||
phb->config_reg = (pciaddr) | (1u << 31);
|
||||
pci_data_write(phb->bus, phb->config_reg, val, 2);
|
||||
|
||||
/* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
|
||||
status = pci_get_word(s->dev.config + PCI_STATUS);
|
||||
status = pci_get_word(d->config + PCI_STATUS);
|
||||
status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
|
||||
pci_set_word(s->dev.config + PCI_STATUS, status);
|
||||
pci_set_word(d->config + PCI_STATUS, status);
|
||||
}
|
||||
|
||||
static void bonito_spciconf_writel(void *opaque, target_phys_addr_t addr,
|
||||
uint32_t val)
|
||||
{
|
||||
PCIBonitoState *s = opaque;
|
||||
PCIDevice *d = PCI_DEVICE(s);
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
|
||||
uint32_t pciaddr;
|
||||
uint16_t status;
|
||||
|
||||
DPRINTF("bonito_spciconf_writel "TARGET_FMT_plx" val %x\n", addr, val);
|
||||
assert((addr&0x3)==0);
|
||||
assert((addr & 0x3) == 0);
|
||||
|
||||
pciaddr = bonito_sbridge_pciaddr(s, addr);
|
||||
|
||||
@@ -501,18 +522,20 @@ static void bonito_spciconf_writel(void *opaque, target_phys_addr_t addr,
|
||||
}
|
||||
|
||||
/* set the pci address in s->config_reg */
|
||||
s->pcihost->config_reg = (pciaddr) | (1u << 31);
|
||||
pci_data_write(s->pcihost->bus, s->pcihost->config_reg, val, 4);
|
||||
phb->config_reg = (pciaddr) | (1u << 31);
|
||||
pci_data_write(phb->bus, phb->config_reg, val, 4);
|
||||
|
||||
/* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
|
||||
status = pci_get_word(s->dev.config + PCI_STATUS);
|
||||
status = pci_get_word(d->config + PCI_STATUS);
|
||||
status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
|
||||
pci_set_word(s->dev.config + PCI_STATUS, status);
|
||||
pci_set_word(d->config + PCI_STATUS, status);
|
||||
}
|
||||
|
||||
static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
PCIBonitoState *s = opaque;
|
||||
PCIDevice *d = PCI_DEVICE(s);
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
|
||||
uint32_t pciaddr;
|
||||
uint16_t status;
|
||||
|
||||
@@ -524,24 +547,26 @@ static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr)
|
||||
}
|
||||
|
||||
/* set the pci address in s->config_reg */
|
||||
s->pcihost->config_reg = (pciaddr) | (1u << 31);
|
||||
phb->config_reg = (pciaddr) | (1u << 31);
|
||||
|
||||
/* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
|
||||
status = pci_get_word(s->dev.config + PCI_STATUS);
|
||||
status = pci_get_word(d->config + PCI_STATUS);
|
||||
status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
|
||||
pci_set_word(s->dev.config + PCI_STATUS, status);
|
||||
pci_set_word(d->config + PCI_STATUS, status);
|
||||
|
||||
return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 1);
|
||||
return pci_data_read(phb->bus, phb->config_reg, 1);
|
||||
}
|
||||
|
||||
static uint32_t bonito_spciconf_readw(void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
PCIBonitoState *s = opaque;
|
||||
PCIDevice *d = PCI_DEVICE(s);
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
|
||||
uint32_t pciaddr;
|
||||
uint16_t status;
|
||||
|
||||
DPRINTF("bonito_spciconf_readw "TARGET_FMT_plx"\n", addr);
|
||||
assert((addr&0x1)==0);
|
||||
assert((addr & 0x1) == 0);
|
||||
|
||||
pciaddr = bonito_sbridge_pciaddr(s, addr);
|
||||
|
||||
@@ -550,24 +575,26 @@ static uint32_t bonito_spciconf_readw(void *opaque, target_phys_addr_t addr)
|
||||
}
|
||||
|
||||
/* set the pci address in s->config_reg */
|
||||
s->pcihost->config_reg = (pciaddr) | (1u << 31);
|
||||
phb->config_reg = (pciaddr) | (1u << 31);
|
||||
|
||||
/* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
|
||||
status = pci_get_word(s->dev.config + PCI_STATUS);
|
||||
status = pci_get_word(d->config + PCI_STATUS);
|
||||
status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
|
||||
pci_set_word(s->dev.config + PCI_STATUS, status);
|
||||
pci_set_word(d->config + PCI_STATUS, status);
|
||||
|
||||
return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 2);
|
||||
return pci_data_read(phb->bus, phb->config_reg, 2);
|
||||
}
|
||||
|
||||
static uint32_t bonito_spciconf_readl(void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
PCIBonitoState *s = opaque;
|
||||
PCIDevice *d = PCI_DEVICE(s);
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
|
||||
uint32_t pciaddr;
|
||||
uint16_t status;
|
||||
|
||||
DPRINTF("bonito_spciconf_readl "TARGET_FMT_plx"\n", addr);
|
||||
assert((addr&0x3) == 0);
|
||||
assert((addr & 0x3) == 0);
|
||||
|
||||
pciaddr = bonito_sbridge_pciaddr(s, addr);
|
||||
|
||||
@@ -576,14 +603,14 @@ static uint32_t bonito_spciconf_readl(void *opaque, target_phys_addr_t addr)
|
||||
}
|
||||
|
||||
/* set the pci address in s->config_reg */
|
||||
s->pcihost->config_reg = (pciaddr) | (1u << 31);
|
||||
phb->config_reg = (pciaddr) | (1u << 31);
|
||||
|
||||
/* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
|
||||
status = pci_get_word(s->dev.config + PCI_STATUS);
|
||||
status = pci_get_word(d->config + PCI_STATUS);
|
||||
status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
|
||||
pci_set_word(s->dev.config + PCI_STATUS, status);
|
||||
pci_set_word(d->config + PCI_STATUS, status);
|
||||
|
||||
return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 4);
|
||||
return pci_data_read(phb->bus, phb->config_reg, 4);
|
||||
}
|
||||
|
||||
/* south bridge PCI configure space. 0x1fe8 0000 - 0x1fef ffff */
|
||||
@@ -607,13 +634,15 @@ static const MemoryRegionOps bonito_spciconf_ops = {
|
||||
|
||||
static void pci_bonito_set_irq(void *opaque, int irq_num, int level)
|
||||
{
|
||||
qemu_irq *pic = opaque;
|
||||
BonitoState *s = opaque;
|
||||
qemu_irq *pic = s->pic;
|
||||
PCIBonitoState *bonito_state = s->pci_dev;
|
||||
int internal_irq = irq_num - BONITO_IRQ_BASE;
|
||||
|
||||
if (bonito_state->regs[BONITO_INTEDGE] & (1<<internal_irq)) {
|
||||
if (bonito_state->regs[BONITO_INTEDGE] & (1 << internal_irq)) {
|
||||
qemu_irq_pulse(*pic);
|
||||
} else { /* level triggered */
|
||||
if (bonito_state->regs[BONITO_INTPOL] & (1<<internal_irq)) {
|
||||
if (bonito_state->regs[BONITO_INTPOL] & (1 << internal_irq)) {
|
||||
qemu_irq_raise(*pic);
|
||||
} else {
|
||||
qemu_irq_lower(*pic);
|
||||
@@ -673,13 +702,21 @@ static const VMStateDescription vmstate_bonito = {
|
||||
|
||||
static int bonito_pcihost_initfn(SysBusDevice *dev)
|
||||
{
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(dev);
|
||||
|
||||
phb->bus = pci_register_bus(DEVICE(dev), "pci",
|
||||
pci_bonito_set_irq, pci_bonito_map_irq, dev,
|
||||
get_system_memory(), get_system_io(),
|
||||
0x28, 32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bonito_initfn(PCIDevice *dev)
|
||||
{
|
||||
PCIBonitoState *s = DO_UPCAST(PCIBonitoState, dev, dev);
|
||||
SysBusDevice *sysbus = &s->pcihost->busdev;
|
||||
SysBusDevice *sysbus = SYS_BUS_DEVICE(s->pcihost);
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
|
||||
|
||||
/* Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */
|
||||
pci_config_set_prog_interface(dev->config, 0x00);
|
||||
@@ -691,15 +728,15 @@ static int bonito_initfn(PCIDevice *dev)
|
||||
sysbus_mmio_map(sysbus, 0, BONITO_INTERNAL_REG_BASE);
|
||||
|
||||
/* set the north bridge pci configure mapping */
|
||||
memory_region_init_io(&s->pcihost->conf_mem, &bonito_pciconf_ops, s,
|
||||
memory_region_init_io(&phb->conf_mem, &bonito_pciconf_ops, s,
|
||||
"north-bridge-pci-config", BONITO_PCICONFIG_SIZE);
|
||||
sysbus_init_mmio(sysbus, &s->pcihost->conf_mem);
|
||||
sysbus_init_mmio(sysbus, &phb->conf_mem);
|
||||
sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE);
|
||||
|
||||
/* set the south bridge pci configure mapping */
|
||||
memory_region_init_io(&s->pcihost->data_mem, &bonito_spciconf_ops, s,
|
||||
memory_region_init_io(&phb->data_mem, &bonito_spciconf_ops, s,
|
||||
"south-bridge-pci-config", BONITO_SPCICONFIG_SIZE);
|
||||
sysbus_init_mmio(sysbus, &s->pcihost->data_mem);
|
||||
sysbus_init_mmio(sysbus, &phb->data_mem);
|
||||
sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE);
|
||||
|
||||
memory_region_init_io(&s->iomem_ldma, &bonito_ldma_ops, s,
|
||||
@@ -742,28 +779,25 @@ static int bonito_initfn(PCIDevice *dev)
|
||||
PCIBus *bonito_init(qemu_irq *pic)
|
||||
{
|
||||
DeviceState *dev;
|
||||
PCIBus *b;
|
||||
BonitoState *pcihost;
|
||||
PCIHostState *phb;
|
||||
PCIBonitoState *s;
|
||||
PCIDevice *d;
|
||||
|
||||
dev = qdev_create(NULL, "Bonito-pcihost");
|
||||
pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev));
|
||||
b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq,
|
||||
pci_bonito_map_irq, pic, get_system_memory(),
|
||||
get_system_io(),
|
||||
0x28, 32);
|
||||
pcihost->bus = b;
|
||||
dev = qdev_create(NULL, TYPE_BONITO_PCI_HOST_BRIDGE);
|
||||
phb = PCI_HOST_BRIDGE(dev);
|
||||
pcihost = BONITO_PCI_HOST_BRIDGE(dev);
|
||||
pcihost->pic = pic;
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
/* set the pcihost pointer before bonito_initfn is called */
|
||||
d = pci_create(b, PCI_DEVFN(0, 0), "Bonito");
|
||||
d = pci_create(phb->bus, PCI_DEVFN(0, 0), "Bonito");
|
||||
s = DO_UPCAST(PCIBonitoState, dev, d);
|
||||
s->pcihost = pcihost;
|
||||
bonito_state = s;
|
||||
qdev_init_nofail(&d->qdev);
|
||||
pcihost->pci_dev = s;
|
||||
qdev_init_nofail(DEVICE(d));
|
||||
|
||||
return b;
|
||||
return phb->bus;
|
||||
}
|
||||
|
||||
static void bonito_class_init(ObjectClass *klass, void *data)
|
||||
@@ -781,7 +815,7 @@ static void bonito_class_init(ObjectClass *klass, void *data)
|
||||
dc->vmsd = &vmstate_bonito;
|
||||
}
|
||||
|
||||
static TypeInfo bonito_info = {
|
||||
static const TypeInfo bonito_info = {
|
||||
.name = "Bonito",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIBonitoState),
|
||||
@@ -797,9 +831,9 @@ static void bonito_pcihost_class_init(ObjectClass *klass, void *data)
|
||||
dc->no_user = 1;
|
||||
}
|
||||
|
||||
static TypeInfo bonito_pcihost_info = {
|
||||
.name = "Bonito-pcihost",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo bonito_pcihost_info = {
|
||||
.name = TYPE_BONITO_PCI_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(BonitoState),
|
||||
.class_init = bonito_pcihost_class_init,
|
||||
};
|
||||
|
||||
+16
-15
@@ -40,9 +40,10 @@
|
||||
#define DEC_DPRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
#define DEC_21154(obj) OBJECT_CHECK(DECState, (obj), TYPE_DEC_21154)
|
||||
|
||||
typedef struct DECState {
|
||||
SysBusDevice busdev;
|
||||
PCIHostState host_state;
|
||||
PCIHostState parent_obj;
|
||||
} DECState;
|
||||
|
||||
static int dec_map_irq(PCIDevice *pci_dev, int irq_num)
|
||||
@@ -66,7 +67,7 @@ static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data)
|
||||
dc->vmsd = &vmstate_pci_device;
|
||||
}
|
||||
|
||||
static TypeInfo dec_21154_pci_bridge_info = {
|
||||
static const TypeInfo dec_21154_pci_bridge_info = {
|
||||
.name = "dec-21154-p2p-bridge",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIBridge),
|
||||
@@ -88,16 +89,16 @@ PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn)
|
||||
|
||||
static int pci_dec_21154_device_init(SysBusDevice *dev)
|
||||
{
|
||||
DECState *s;
|
||||
PCIHostState *phb;
|
||||
|
||||
s = FROM_SYSBUS(DECState, dev);
|
||||
phb = PCI_HOST_BRIDGE(dev);
|
||||
|
||||
memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
|
||||
&s->host_state, "pci-conf-idx", 0x1000);
|
||||
memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
|
||||
&s->host_state, "pci-data-idx", 0x1000);
|
||||
sysbus_init_mmio(dev, &s->host_state.conf_mem);
|
||||
sysbus_init_mmio(dev, &s->host_state.data_mem);
|
||||
memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops,
|
||||
dev, "pci-conf-idx", 0x1000);
|
||||
memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops,
|
||||
dev, "pci-data-idx", 0x1000);
|
||||
sysbus_init_mmio(dev, &phb->conf_mem);
|
||||
sysbus_init_mmio(dev, &phb->data_mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -119,7 +120,7 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data)
|
||||
k->is_bridge = 1;
|
||||
}
|
||||
|
||||
static TypeInfo dec_21154_pci_host_info = {
|
||||
static const TypeInfo dec_21154_pci_host_info = {
|
||||
.name = "dec-21154",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIDevice),
|
||||
@@ -133,9 +134,9 @@ static void pci_dec_21154_device_class_init(ObjectClass *klass, void *data)
|
||||
sdc->init = pci_dec_21154_device_init;
|
||||
}
|
||||
|
||||
static TypeInfo pci_dec_21154_device_info = {
|
||||
.name = "dec-21154-sysbus",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo pci_dec_21154_device_info = {
|
||||
.name = TYPE_DEC_21154,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(DECState),
|
||||
.class_init = pci_dec_21154_device_class_init,
|
||||
};
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "qemu-common.h"
|
||||
|
||||
#define TYPE_DEC_21154 "dec-21154-sysbus"
|
||||
|
||||
PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn);
|
||||
|
||||
#endif
|
||||
@@ -87,7 +87,9 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
|
||||
|
||||
target = s->wregs[ESP_WBUSID] & BUSID_DID;
|
||||
if (s->dma) {
|
||||
dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
|
||||
dmalen = s->rregs[ESP_TCLO];
|
||||
dmalen |= s->rregs[ESP_TCMID] << 8;
|
||||
dmalen |= s->rregs[ESP_TCHI] << 16;
|
||||
s->dma_memory_read(s->dma_opaque, buf, dmalen);
|
||||
} else {
|
||||
dmalen = s->ti_size;
|
||||
@@ -226,6 +228,7 @@ static void esp_dma_done(ESPState *s)
|
||||
s->rregs[ESP_RFLAGS] = 0;
|
||||
s->rregs[ESP_TCLO] = 0;
|
||||
s->rregs[ESP_TCMID] = 0;
|
||||
s->rregs[ESP_TCHI] = 0;
|
||||
esp_raise_irq(s);
|
||||
}
|
||||
|
||||
@@ -328,7 +331,9 @@ static void handle_ti(ESPState *s)
|
||||
return;
|
||||
}
|
||||
|
||||
dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
|
||||
dmalen = s->rregs[ESP_TCLO];
|
||||
dmalen |= s->rregs[ESP_TCMID] << 8;
|
||||
dmalen |= s->rregs[ESP_TCHI] << 16;
|
||||
if (dmalen==0) {
|
||||
dmalen=0x10000;
|
||||
}
|
||||
@@ -429,6 +434,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
|
||||
switch (saddr) {
|
||||
case ESP_TCLO:
|
||||
case ESP_TCMID:
|
||||
case ESP_TCHI:
|
||||
s->rregs[ESP_RSTAT] &= ~STAT_TC;
|
||||
break;
|
||||
case ESP_FIFO:
|
||||
@@ -448,6 +454,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
|
||||
/* Reload DMA counter. */
|
||||
s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
|
||||
s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
|
||||
s->rregs[ESP_TCHI] = s->wregs[ESP_TCHI];
|
||||
} else {
|
||||
s->dma = 0;
|
||||
}
|
||||
@@ -530,13 +537,12 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
|
||||
case ESP_WBUSID ... ESP_WSYNO:
|
||||
break;
|
||||
case ESP_CFG1:
|
||||
case ESP_CFG2: case ESP_CFG3:
|
||||
case ESP_RES3: case ESP_RES4:
|
||||
s->rregs[saddr] = val;
|
||||
break;
|
||||
case ESP_WCCF ... ESP_WTEST:
|
||||
break;
|
||||
case ESP_CFG2 ... ESP_RES4:
|
||||
s->rregs[saddr] = val;
|
||||
break;
|
||||
default:
|
||||
trace_esp_error_invalid_write(val, saddr);
|
||||
return;
|
||||
|
||||
+32
-33
@@ -23,10 +23,9 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "sysbus.h"
|
||||
#include "pci_host.h"
|
||||
#include "ppc_mac.h"
|
||||
#include "pci.h"
|
||||
#include "pci_host.h"
|
||||
|
||||
/* debug Grackle */
|
||||
//#define DEBUG_GRACKLE
|
||||
@@ -38,9 +37,12 @@
|
||||
#define GRACKLE_DPRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
#define GRACKLE_PCI_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(GrackleState, (obj), TYPE_GRACKLE_PCI_HOST_BRIDGE)
|
||||
|
||||
typedef struct GrackleState {
|
||||
SysBusDevice busdev;
|
||||
PCIHostState host_state;
|
||||
PCIHostState parent_obj;
|
||||
|
||||
MemoryRegion pci_mmio;
|
||||
MemoryRegion pci_hole;
|
||||
} GrackleState;
|
||||
@@ -59,22 +61,20 @@ static void pci_grackle_set_irq(void *opaque, int irq_num, int level)
|
||||
qemu_set_irq(pic[irq_num + 0x15], level);
|
||||
}
|
||||
|
||||
static void pci_grackle_reset(void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
|
||||
MemoryRegion *address_space_mem,
|
||||
MemoryRegion *address_space_io)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
PCIHostState *phb;
|
||||
GrackleState *d;
|
||||
|
||||
dev = qdev_create(NULL, "grackle-pcihost");
|
||||
dev = qdev_create(NULL, TYPE_GRACKLE_PCI_HOST_BRIDGE);
|
||||
qdev_init_nofail(dev);
|
||||
s = sysbus_from_qdev(dev);
|
||||
d = FROM_SYSBUS(GrackleState, s);
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
phb = PCI_HOST_BRIDGE(dev);
|
||||
d = GRACKLE_PCI_HOST_BRIDGE(dev);
|
||||
|
||||
memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
|
||||
memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
|
||||
@@ -82,36 +82,35 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
|
||||
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
|
||||
&d->pci_hole);
|
||||
|
||||
d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
|
||||
pci_grackle_set_irq,
|
||||
pci_grackle_map_irq,
|
||||
pic,
|
||||
&d->pci_mmio,
|
||||
address_space_io,
|
||||
0, 4);
|
||||
phb->bus = pci_register_bus(dev, "pci",
|
||||
pci_grackle_set_irq,
|
||||
pci_grackle_map_irq,
|
||||
pic,
|
||||
&d->pci_mmio,
|
||||
address_space_io,
|
||||
0, 4);
|
||||
|
||||
pci_create_simple(d->host_state.bus, 0, "grackle");
|
||||
pci_create_simple(phb->bus, 0, "grackle");
|
||||
|
||||
sysbus_mmio_map(s, 0, base);
|
||||
sysbus_mmio_map(s, 1, base + 0x00200000);
|
||||
|
||||
return d->host_state.bus;
|
||||
return phb->bus;
|
||||
}
|
||||
|
||||
static int pci_grackle_init_device(SysBusDevice *dev)
|
||||
{
|
||||
GrackleState *s;
|
||||
PCIHostState *phb;
|
||||
|
||||
s = FROM_SYSBUS(GrackleState, dev);
|
||||
phb = PCI_HOST_BRIDGE(dev);
|
||||
|
||||
memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
|
||||
&s->host_state, "pci-conf-idx", 0x1000);
|
||||
memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
|
||||
&s->host_state, "pci-data-idx", 0x1000);
|
||||
sysbus_init_mmio(dev, &s->host_state.conf_mem);
|
||||
sysbus_init_mmio(dev, &s->host_state.data_mem);
|
||||
memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops,
|
||||
dev, "pci-conf-idx", 0x1000);
|
||||
memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops,
|
||||
dev, "pci-data-idx", 0x1000);
|
||||
sysbus_init_mmio(dev, &phb->conf_mem);
|
||||
sysbus_init_mmio(dev, &phb->data_mem);
|
||||
|
||||
qemu_register_reset(pci_grackle_reset, &s->host_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -134,7 +133,7 @@ static void grackle_pci_class_init(ObjectClass *klass, void *data)
|
||||
dc->no_user = 1;
|
||||
}
|
||||
|
||||
static TypeInfo grackle_pci_info = {
|
||||
static const TypeInfo grackle_pci_info = {
|
||||
.name = "grackle",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIDevice),
|
||||
@@ -150,9 +149,9 @@ static void pci_grackle_class_init(ObjectClass *klass, void *data)
|
||||
dc->no_user = 1;
|
||||
}
|
||||
|
||||
static TypeInfo grackle_pci_host_info = {
|
||||
.name = "grackle-pcihost",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo grackle_pci_host_info = {
|
||||
.name = TYPE_GRACKLE_PCI_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(GrackleState),
|
||||
.class_init = pci_grackle_class_init,
|
||||
};
|
||||
|
||||
+39
-28
@@ -229,9 +229,14 @@
|
||||
target_phys_addr_t regname ##_length; \
|
||||
MemoryRegion regname ##_mem
|
||||
|
||||
#define TYPE_GT64120_PCI_HOST_BRIDGE "gt64120"
|
||||
|
||||
#define GT64120_PCI_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(GT64120State, (obj), TYPE_GT64120_PCI_HOST_BRIDGE)
|
||||
|
||||
typedef struct GT64120State {
|
||||
SysBusDevice busdev;
|
||||
PCIHostState pci;
|
||||
PCIHostState parent_obj;
|
||||
|
||||
uint32_t regs[GT_REGS];
|
||||
PCI_MAPPING_ENTRY(PCI0IO);
|
||||
PCI_MAPPING_ENTRY(ISD);
|
||||
@@ -310,6 +315,7 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
GT64120State *s = opaque;
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||
uint32_t saddr;
|
||||
|
||||
if (!(s->regs[GT_CPU] & 0x00001000))
|
||||
@@ -530,13 +536,15 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr,
|
||||
/* not implemented */
|
||||
break;
|
||||
case GT_PCI0_CFGADDR:
|
||||
s->pci.config_reg = val & 0x80fffffc;
|
||||
phb->config_reg = val & 0x80fffffc;
|
||||
break;
|
||||
case GT_PCI0_CFGDATA:
|
||||
if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci.config_reg & 0x00fff800))
|
||||
if (!(s->regs[GT_PCI0_CMD] & 1) && (phb->config_reg & 0x00fff800)) {
|
||||
val = bswap32(val);
|
||||
if (s->pci.config_reg & (1u << 31))
|
||||
pci_data_write(s->pci.bus, s->pci.config_reg, val, 4);
|
||||
}
|
||||
if (phb->config_reg & (1u << 31)) {
|
||||
pci_data_write(phb->bus, phb->config_reg, val, 4);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Interrupts */
|
||||
@@ -589,6 +597,7 @@ static uint64_t gt64120_readl (void *opaque,
|
||||
target_phys_addr_t addr, unsigned size)
|
||||
{
|
||||
GT64120State *s = opaque;
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||
uint32_t val;
|
||||
uint32_t saddr;
|
||||
|
||||
@@ -770,15 +779,17 @@ static uint64_t gt64120_readl (void *opaque,
|
||||
|
||||
/* PCI Internal */
|
||||
case GT_PCI0_CFGADDR:
|
||||
val = s->pci.config_reg;
|
||||
val = phb->config_reg;
|
||||
break;
|
||||
case GT_PCI0_CFGDATA:
|
||||
if (!(s->pci.config_reg & (1 << 31)))
|
||||
if (!(phb->config_reg & (1 << 31))) {
|
||||
val = 0xffffffff;
|
||||
else
|
||||
val = pci_data_read(s->pci.bus, s->pci.config_reg, 4);
|
||||
if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci.config_reg & 0x00fff800))
|
||||
} else {
|
||||
val = pci_data_read(phb->bus, phb->config_reg, 4);
|
||||
}
|
||||
if (!(s->regs[GT_PCI0_CMD] & 1) && (phb->config_reg & 0x00fff800)) {
|
||||
val = bswap32(val);
|
||||
}
|
||||
break;
|
||||
|
||||
case GT_PCI0_CMD:
|
||||
@@ -1083,31 +1094,31 @@ static void gt64120_reset(void *opaque)
|
||||
|
||||
PCIBus *gt64120_register(qemu_irq *pic)
|
||||
{
|
||||
SysBusDevice *s;
|
||||
GT64120State *d;
|
||||
PCIHostState *phb;
|
||||
DeviceState *dev;
|
||||
|
||||
dev = qdev_create(NULL, "gt64120");
|
||||
dev = qdev_create(NULL, TYPE_GT64120_PCI_HOST_BRIDGE);
|
||||
qdev_init_nofail(dev);
|
||||
s = sysbus_from_qdev(dev);
|
||||
d = FROM_SYSBUS(GT64120State, s);
|
||||
d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci",
|
||||
gt64120_pci_set_irq, gt64120_pci_map_irq,
|
||||
pic,
|
||||
get_system_memory(),
|
||||
get_system_io(),
|
||||
PCI_DEVFN(18, 0), 4);
|
||||
d = GT64120_PCI_HOST_BRIDGE(dev);
|
||||
phb = PCI_HOST_BRIDGE(dev);
|
||||
phb->bus = pci_register_bus(dev, "pci",
|
||||
gt64120_pci_set_irq, gt64120_pci_map_irq,
|
||||
pic,
|
||||
get_system_memory(),
|
||||
get_system_io(),
|
||||
PCI_DEVFN(18, 0), 4);
|
||||
memory_region_init_io(&d->ISD_mem, &isd_mem_ops, d, "isd-mem", 0x1000);
|
||||
|
||||
pci_create_simple(d->pci.bus, PCI_DEVFN(0, 0), "gt64120_pci");
|
||||
return d->pci.bus;
|
||||
pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
|
||||
return phb->bus;
|
||||
}
|
||||
|
||||
static int gt64120_init(SysBusDevice *dev)
|
||||
{
|
||||
GT64120State *s;
|
||||
|
||||
s = FROM_SYSBUS(GT64120State, dev);
|
||||
s = GT64120_PCI_HOST_BRIDGE(dev);
|
||||
|
||||
/* FIXME: This value is computed from registers during reset, but some
|
||||
devices (e.g. VGA card) need to know it when they are registered.
|
||||
@@ -1147,7 +1158,7 @@ static void gt64120_pci_class_init(ObjectClass *klass, void *data)
|
||||
k->class_id = PCI_CLASS_BRIDGE_HOST;
|
||||
}
|
||||
|
||||
static TypeInfo gt64120_pci_info = {
|
||||
static const TypeInfo gt64120_pci_info = {
|
||||
.name = "gt64120_pci",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIDevice),
|
||||
@@ -1161,9 +1172,9 @@ static void gt64120_class_init(ObjectClass *klass, void *data)
|
||||
sdc->init = gt64120_init;
|
||||
}
|
||||
|
||||
static TypeInfo gt64120_info = {
|
||||
.name = "gt64120",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo gt64120_info = {
|
||||
.name = TYPE_GT64120_PCI_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(GT64120State),
|
||||
.class_init = gt64120_class_init,
|
||||
};
|
||||
|
||||
@@ -225,7 +225,6 @@ static int pci_i82378_init(PCIDevice *dev)
|
||||
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io);
|
||||
|
||||
memory_region_init_io(&s->mem, &i82378_mem_ops, s, "i82378-mem", 0x01000000);
|
||||
memory_region_set_coalescing(&s->mem);
|
||||
pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
|
||||
|
||||
/* Make I/O address read only */
|
||||
|
||||
+4
-15
@@ -366,6 +366,10 @@ static void close_guest_eventfds(IVShmemState *s, int posn)
|
||||
{
|
||||
int i, guest_curr_max;
|
||||
|
||||
if (!ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
|
||||
return;
|
||||
}
|
||||
|
||||
guest_curr_max = s->peers[posn].nb_eventfds;
|
||||
|
||||
memory_region_transaction_begin();
|
||||
@@ -381,17 +385,6 @@ static void close_guest_eventfds(IVShmemState *s, int posn)
|
||||
s->peers[posn].nb_eventfds = 0;
|
||||
}
|
||||
|
||||
static void setup_ioeventfds(IVShmemState *s) {
|
||||
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i <= s->max_peer; i++) {
|
||||
for (j = 0; j < s->peers[i].nb_eventfds; j++) {
|
||||
ivshmem_add_eventfd(s, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* this function increase the dynamic storage need to store data about other
|
||||
* guests */
|
||||
static void increase_dynamic_storage(IVShmemState *s, int new_min_size) {
|
||||
@@ -692,10 +685,6 @@ static int pci_ivshmem_init(PCIDevice *dev)
|
||||
memory_region_init_io(&s->ivshmem_mmio, &ivshmem_mmio_ops, s,
|
||||
"ivshmem-mmio", IVSHMEM_REG_BAR_SIZE);
|
||||
|
||||
if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
|
||||
setup_ioeventfds(s);
|
||||
}
|
||||
|
||||
/* region for registers*/
|
||||
pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
|
||||
&s->ivshmem_mmio);
|
||||
|
||||
+7
-2
@@ -38,6 +38,7 @@
|
||||
#define MEGASAS_MAX_SECTORS 0xFFFF /* No real limit */
|
||||
#define MEGASAS_MAX_ARRAYS 128
|
||||
|
||||
#define MEGASAS_HBA_SERIAL "QEMU123456"
|
||||
#define NAA_LOCALLY_ASSIGNED_ID 0x3ULL
|
||||
#define IEEE_COMPANY_LOCALLY_ASSIGNED 0x525400
|
||||
|
||||
@@ -93,6 +94,7 @@ typedef struct MegasasState {
|
||||
int boot_event;
|
||||
|
||||
uint64_t sas_addr;
|
||||
char *hba_serial;
|
||||
|
||||
uint64_t reply_queue_pa;
|
||||
void *reply_queue;
|
||||
@@ -698,8 +700,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
|
||||
}
|
||||
|
||||
memcpy(info.product_name, "MegaRAID SAS 8708EM2", 20);
|
||||
snprintf(info.serial_number, 32, "QEMU%08lx",
|
||||
(unsigned long)s & 0xFFFFFFFF);
|
||||
snprintf(info.serial_number, 32, "%s", s->hba_serial);
|
||||
snprintf(info.package_version, 0x60, "%s-QEMU", QEMU_VERSION);
|
||||
memcpy(info.image_component[0].name, "APP", 3);
|
||||
memcpy(info.image_component[0].version, MEGASAS_VERSION "-QEMU", 9);
|
||||
@@ -2132,6 +2133,9 @@ static int megasas_scsi_init(PCIDevice *dev)
|
||||
s->sas_addr |= (PCI_SLOT(dev->devfn) << 8);
|
||||
s->sas_addr |= PCI_FUNC(dev->devfn);
|
||||
}
|
||||
if (!s->hba_serial) {
|
||||
s->hba_serial = g_strdup(MEGASAS_HBA_SERIAL);
|
||||
}
|
||||
if (s->fw_sge >= MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE) {
|
||||
s->fw_sge = MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE;
|
||||
} else if (s->fw_sge >= 128 - MFI_PASS_FRAME_SIZE) {
|
||||
@@ -2166,6 +2170,7 @@ static Property megasas_properties[] = {
|
||||
MEGASAS_DEFAULT_SGE),
|
||||
DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds,
|
||||
MEGASAS_DEFAULT_FRAMES),
|
||||
DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial),
|
||||
DEFINE_PROP_HEX64("sas_address", MegasasState, sas_addr, 0),
|
||||
#ifdef USE_MSIX
|
||||
DEFINE_PROP_BIT("use_msix", MegasasState, flags,
|
||||
|
||||
@@ -307,13 +307,9 @@ int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (asprintf(&name, "%s-msix", dev->name) == -1) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
name = g_strdup_printf("%s-msix", dev->name);
|
||||
memory_region_init(&dev->msix_exclusive_bar, name, MSIX_EXCLUSIVE_BAR_SIZE);
|
||||
|
||||
free(name);
|
||||
g_free(name);
|
||||
|
||||
ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr,
|
||||
MSIX_EXCLUSIVE_BAR_TABLE_OFFSET, &dev->msix_exclusive_bar,
|
||||
@@ -340,6 +336,15 @@ static void msix_free_irq_entries(PCIDevice *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void msix_clear_all_vectors(PCIDevice *dev)
|
||||
{
|
||||
int vector;
|
||||
|
||||
for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
|
||||
msix_clr_pending(dev, vector);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up resources for the device. */
|
||||
void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar, MemoryRegion *pba_bar)
|
||||
{
|
||||
@@ -394,7 +399,7 @@ void msix_load(PCIDevice *dev, QEMUFile *f)
|
||||
return;
|
||||
}
|
||||
|
||||
msix_free_irq_entries(dev);
|
||||
msix_clear_all_vectors(dev);
|
||||
qemu_get_buffer(f, dev->msix_table, n * PCI_MSIX_ENTRY_SIZE);
|
||||
qemu_get_buffer(f, dev->msix_pba, (n + 7) / 8);
|
||||
msix_update_function_masked(dev);
|
||||
@@ -440,7 +445,7 @@ void msix_reset(PCIDevice *dev)
|
||||
if (!msix_present(dev)) {
|
||||
return;
|
||||
}
|
||||
msix_free_irq_entries(dev);
|
||||
msix_clear_all_vectors(dev);
|
||||
dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &=
|
||||
~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET];
|
||||
memset(dev->msix_table, 0, dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE);
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Empty machine
|
||||
*
|
||||
* Copyright IBM, Corp. 2012
|
||||
*
|
||||
* 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-common.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
static void machine_none_init(ram_addr_t ram_size,
|
||||
const char *boot_device,
|
||||
const char *kernel_filename,
|
||||
const char *kernel_cmdline,
|
||||
const char *initrd_filename,
|
||||
const char *cpu_model)
|
||||
{
|
||||
}
|
||||
|
||||
static QEMUMachine machine_none = {
|
||||
.name = "none",
|
||||
.desc = "empty machine",
|
||||
.init = machine_none_init,
|
||||
.max_cpus = 0,
|
||||
};
|
||||
|
||||
static void register_machines(void)
|
||||
{
|
||||
qemu_register_machine(&machine_none);
|
||||
}
|
||||
|
||||
machine_init(register_machines);
|
||||
|
||||
@@ -338,32 +338,37 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
|
||||
/* various important CMOS locations needed by PC/Bochs bios */
|
||||
|
||||
/* memory size */
|
||||
val = 640; /* base memory in K */
|
||||
/* base memory (first MiB) */
|
||||
val = MIN(ram_size / 1024, 640);
|
||||
rtc_set_memory(s, 0x15, val);
|
||||
rtc_set_memory(s, 0x16, val >> 8);
|
||||
|
||||
val = (ram_size / 1024) - 1024;
|
||||
/* extended memory (next 64MiB) */
|
||||
if (ram_size > 1024 * 1024) {
|
||||
val = (ram_size - 1024 * 1024) / 1024;
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
if (val > 65535)
|
||||
val = 65535;
|
||||
rtc_set_memory(s, 0x17, val);
|
||||
rtc_set_memory(s, 0x18, val >> 8);
|
||||
rtc_set_memory(s, 0x30, val);
|
||||
rtc_set_memory(s, 0x31, val >> 8);
|
||||
|
||||
if (above_4g_mem_size) {
|
||||
rtc_set_memory(s, 0x5b, (unsigned int)above_4g_mem_size >> 16);
|
||||
rtc_set_memory(s, 0x5c, (unsigned int)above_4g_mem_size >> 24);
|
||||
rtc_set_memory(s, 0x5d, (uint64_t)above_4g_mem_size >> 32);
|
||||
}
|
||||
|
||||
if (ram_size > (16 * 1024 * 1024))
|
||||
val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536);
|
||||
else
|
||||
/* memory between 16MiB and 4GiB */
|
||||
if (ram_size > 16 * 1024 * 1024) {
|
||||
val = (ram_size - 16 * 1024 * 1024) / 65536;
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
if (val > 65535)
|
||||
val = 65535;
|
||||
rtc_set_memory(s, 0x34, val);
|
||||
rtc_set_memory(s, 0x35, val >> 8);
|
||||
/* memory above 4GiB */
|
||||
val = above_4g_mem_size / 65536;
|
||||
rtc_set_memory(s, 0x5b, val);
|
||||
rtc_set_memory(s, 0x5c, val >> 8);
|
||||
rtc_set_memory(s, 0x5d, val >> 16);
|
||||
|
||||
/* set the number of CPU */
|
||||
rtc_set_memory(s, 0x5f, smp_cpus - 1);
|
||||
|
||||
@@ -360,6 +360,14 @@ static QEMUMachine pc_machine_v1_2 = {
|
||||
|
||||
#define PC_COMPAT_1_1 \
|
||||
{\
|
||||
.driver = "virtio-scsi-pci",\
|
||||
.property = "hotplug",\
|
||||
.value = "off",\
|
||||
},{\
|
||||
.driver = "virtio-scsi-pci",\
|
||||
.property = "param_change",\
|
||||
.value = "off",\
|
||||
},{\
|
||||
.driver = "VGA",\
|
||||
.property = "vgamem_mb",\
|
||||
.value = stringify(8),\
|
||||
@@ -375,6 +383,10 @@ static QEMUMachine pc_machine_v1_2 = {
|
||||
.driver = "qxl",\
|
||||
.property = "vgamem_mb",\
|
||||
.value = stringify(8),\
|
||||
},{\
|
||||
.driver = "virtio-blk-pci",\
|
||||
.property = "config-wce",\
|
||||
.value = "off",\
|
||||
}
|
||||
|
||||
static QEMUMachine pc_machine_v1_1 = {
|
||||
|
||||
@@ -165,4 +165,16 @@ const MemoryRegionOps pci_host_data_be_ops = {
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
};
|
||||
|
||||
static const TypeInfo pci_host_type_info = {
|
||||
.name = TYPE_PCI_HOST_BRIDGE,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.abstract = true,
|
||||
.instance_size = sizeof(PCIHostState),
|
||||
};
|
||||
|
||||
static void pci_host_register_types(void)
|
||||
{
|
||||
type_register_static(&pci_host_type_info);
|
||||
}
|
||||
|
||||
type_init(pci_host_register_types)
|
||||
@@ -30,8 +30,13 @@
|
||||
|
||||
#include "sysbus.h"
|
||||
|
||||
#define TYPE_PCI_HOST_BRIDGE "pci-host-bridge"
|
||||
#define PCI_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE)
|
||||
|
||||
struct PCIHostState {
|
||||
SysBusDevice busdev;
|
||||
|
||||
MemoryRegion conf_mem;
|
||||
MemoryRegion data_mem;
|
||||
MemoryRegion mmcfg;
|
||||
|
||||
+12
-10
@@ -36,7 +36,9 @@
|
||||
* http://download.intel.com/design/chipsets/datashts/29054901.pdf
|
||||
*/
|
||||
|
||||
typedef PCIHostState I440FXState;
|
||||
typedef struct I440FXState {
|
||||
PCIHostState parent_obj;
|
||||
} I440FXState;
|
||||
|
||||
#define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */
|
||||
#define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */
|
||||
@@ -225,7 +227,7 @@ static const VMStateDescription vmstate_i440fx = {
|
||||
|
||||
static int i440fx_pcihost_initfn(SysBusDevice *dev)
|
||||
{
|
||||
I440FXState *s = FROM_SYSBUS(I440FXState, dev);
|
||||
PCIHostState *s = PCI_HOST_BRIDGE(dev);
|
||||
|
||||
memory_region_init_io(&s->conf_mem, &pci_host_conf_le_ops, s,
|
||||
"pci-conf-idx", 4);
|
||||
@@ -267,14 +269,14 @@ static PCIBus *i440fx_common_init(const char *device_name,
|
||||
DeviceState *dev;
|
||||
PCIBus *b;
|
||||
PCIDevice *d;
|
||||
I440FXState *s;
|
||||
PCIHostState *s;
|
||||
PIIX3State *piix3;
|
||||
PCII440FXState *f;
|
||||
|
||||
dev = qdev_create(NULL, "i440FX-pcihost");
|
||||
s = FROM_SYSBUS(I440FXState, sysbus_from_qdev(dev));
|
||||
s = PCI_HOST_BRIDGE(dev);
|
||||
s->address_space = address_space_mem;
|
||||
b = pci_bus_new(&s->busdev.qdev, NULL, pci_address_space,
|
||||
b = pci_bus_new(dev, NULL, pci_address_space,
|
||||
address_space_io, 0);
|
||||
s->bus = b;
|
||||
object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
|
||||
@@ -537,7 +539,7 @@ static void piix3_class_init(ObjectClass *klass, void *data)
|
||||
k->class_id = PCI_CLASS_BRIDGE_ISA;
|
||||
}
|
||||
|
||||
static TypeInfo piix3_info = {
|
||||
static const TypeInfo piix3_info = {
|
||||
.name = "PIIX3",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PIIX3State),
|
||||
@@ -560,7 +562,7 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data)
|
||||
k->class_id = PCI_CLASS_BRIDGE_ISA;
|
||||
};
|
||||
|
||||
static TypeInfo piix3_xen_info = {
|
||||
static const TypeInfo piix3_xen_info = {
|
||||
.name = "PIIX3-xen",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PIIX3State),
|
||||
@@ -584,7 +586,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data)
|
||||
dc->vmsd = &vmstate_i440fx;
|
||||
}
|
||||
|
||||
static TypeInfo i440fx_info = {
|
||||
static const TypeInfo i440fx_info = {
|
||||
.name = "i440FX",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCII440FXState),
|
||||
@@ -601,9 +603,9 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
|
||||
dc->no_user = 1;
|
||||
}
|
||||
|
||||
static TypeInfo i440fx_pcihost_info = {
|
||||
static const TypeInfo i440fx_pcihost_info = {
|
||||
.name = "i440FX-pcihost",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(I440FXState),
|
||||
.class_init = i440fx_pcihost_class_init,
|
||||
};
|
||||
|
||||
+2
-1
@@ -216,7 +216,8 @@ static void bamboo_init(ram_addr_t ram_size,
|
||||
ram_bases, ram_sizes, 1);
|
||||
|
||||
/* PCI */
|
||||
dev = sysbus_create_varargs("ppc4xx-pcihost", PPC440EP_PCI_CONFIG,
|
||||
dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
|
||||
PPC440EP_PCI_CONFIG,
|
||||
pic[pci_irq_nrs[0]], pic[pci_irq_nrs[1]],
|
||||
pic[pci_irq_nrs[2]], pic[pci_irq_nrs[3]],
|
||||
NULL);
|
||||
|
||||
@@ -53,6 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
|
||||
target_phys_addr_t *ram_sizes,
|
||||
int do_init);
|
||||
|
||||
#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
|
||||
|
||||
PCIBus *ppc4xx_pci_init(CPUPPCState *env, qemu_irq pci_irqs[4],
|
||||
target_phys_addr_t config_space,
|
||||
target_phys_addr_t int_ack,
|
||||
|
||||
+16
-11
@@ -45,11 +45,14 @@ struct PCITargetMap {
|
||||
uint32_t la;
|
||||
};
|
||||
|
||||
#define PPC4xx_PCI_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(PPC4xxPCIState, (obj), TYPE_PPC4xx_PCI_HOST_BRIDGE)
|
||||
|
||||
#define PPC4xx_PCI_NR_PMMS 3
|
||||
#define PPC4xx_PCI_NR_PTMS 2
|
||||
|
||||
struct PPC4xxPCIState {
|
||||
PCIHostState pci_state;
|
||||
PCIHostState parent_obj;
|
||||
|
||||
struct PCIMasterMap pmm[PPC4xx_PCI_NR_PMMS];
|
||||
struct PCITargetMap ptm[PPC4xx_PCI_NR_PTMS];
|
||||
@@ -93,16 +96,18 @@ static uint64_t pci4xx_cfgaddr_read(void *opaque, target_phys_addr_t addr,
|
||||
unsigned size)
|
||||
{
|
||||
PPC4xxPCIState *ppc4xx_pci = opaque;
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(ppc4xx_pci);
|
||||
|
||||
return ppc4xx_pci->pci_state.config_reg;
|
||||
return phb->config_reg;
|
||||
}
|
||||
|
||||
static void pci4xx_cfgaddr_write(void *opaque, target_phys_addr_t addr,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
PPC4xxPCIState *ppc4xx_pci = opaque;
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(ppc4xx_pci);
|
||||
|
||||
ppc4xx_pci->pci_state.config_reg = value & ~0x3;
|
||||
phb->config_reg = value & ~0x3;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps pci4xx_cfgaddr_ops = {
|
||||
@@ -335,17 +340,17 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
|
||||
PCIBus *b;
|
||||
int i;
|
||||
|
||||
h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
|
||||
s = DO_UPCAST(PPC4xxPCIState, pci_state, h);
|
||||
h = PCI_HOST_BRIDGE(dev);
|
||||
s = PPC4xx_PCI_HOST_BRIDGE(dev);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
|
||||
sysbus_init_irq(dev, &s->irq[i]);
|
||||
}
|
||||
|
||||
b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, ppc4xx_pci_set_irq,
|
||||
b = pci_register_bus(DEVICE(dev), NULL, ppc4xx_pci_set_irq,
|
||||
ppc4xx_pci_map_irq, s->irq, get_system_memory(),
|
||||
get_system_io(), 0, 4);
|
||||
s->pci_state.bus = b;
|
||||
h->bus = b;
|
||||
|
||||
pci_create_simple(b, 0, "ppc4xx-host-bridge");
|
||||
|
||||
@@ -377,7 +382,7 @@ static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data)
|
||||
k->class_id = PCI_CLASS_BRIDGE_OTHER;
|
||||
}
|
||||
|
||||
static TypeInfo ppc4xx_host_bridge_info = {
|
||||
static const TypeInfo ppc4xx_host_bridge_info = {
|
||||
.name = "ppc4xx-host-bridge",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIDevice),
|
||||
@@ -393,9 +398,9 @@ static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data)
|
||||
dc->vmsd = &vmstate_ppc4xx_pci;
|
||||
}
|
||||
|
||||
static TypeInfo ppc4xx_pcihost_info = {
|
||||
.name = "ppc4xx-pcihost",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo ppc4xx_pcihost_info = {
|
||||
.name = TYPE_PPC4xx_PCI_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(PPC4xxPCIState),
|
||||
.class_init = ppc4xx_pcihost_class_init,
|
||||
};
|
||||
|
||||
@@ -55,6 +55,7 @@ qemu_irq *heathrow_pic_init(MemoryRegion **pmem,
|
||||
int nb_cpus, qemu_irq **irqs);
|
||||
|
||||
/* Grackle PCI */
|
||||
#define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost"
|
||||
PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
|
||||
MemoryRegion *address_space_mem,
|
||||
MemoryRegion *address_space_io);
|
||||
|
||||
+1
-3
@@ -471,7 +471,6 @@ static void ppc_prep_init (ram_addr_t ram_size,
|
||||
uint32_t kernel_base, initrd_base;
|
||||
long kernel_size, initrd_size;
|
||||
DeviceState *dev;
|
||||
SysBusDevice *sys;
|
||||
PCIHostState *pcihost;
|
||||
PCIBus *pci_bus;
|
||||
PCIDevice *pci;
|
||||
@@ -584,8 +583,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
|
||||
}
|
||||
|
||||
dev = qdev_create(NULL, "raven-pcihost");
|
||||
sys = sysbus_from_qdev(dev);
|
||||
pcihost = DO_UPCAST(PCIHostState, busdev, sys);
|
||||
pcihost = PCI_HOST_BRIDGE(dev);
|
||||
pcihost->address_space = get_system_memory();
|
||||
object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL);
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
+15
-9
@@ -72,8 +72,14 @@ struct pci_inbound {
|
||||
uint32_t piwar;
|
||||
};
|
||||
|
||||
#define TYPE_PPC_E500_PCI_HOST_BRIDGE "e500-pcihost"
|
||||
|
||||
#define PPC_E500_PCI_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(PPCE500PCIState, (obj), TYPE_PPC_E500_PCI_HOST_BRIDGE)
|
||||
|
||||
struct PPCE500PCIState {
|
||||
PCIHostState pci_state;
|
||||
PCIHostState parent_obj;
|
||||
|
||||
struct pci_outbound pob[PPCE500_PCI_NR_POBS];
|
||||
struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
|
||||
uint32_t gasket_time;
|
||||
@@ -310,17 +316,17 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *address_space_io = get_system_io();
|
||||
|
||||
h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
|
||||
s = DO_UPCAST(PPCE500PCIState, pci_state, h);
|
||||
h = PCI_HOST_BRIDGE(dev);
|
||||
s = PPC_E500_PCI_HOST_BRIDGE(dev);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
|
||||
sysbus_init_irq(dev, &s->irq[i]);
|
||||
}
|
||||
|
||||
b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq,
|
||||
b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
|
||||
mpc85xx_pci_map_irq, s->irq, address_space_mem,
|
||||
address_space_io, PCI_DEVFN(0x11, 0), 4);
|
||||
s->pci_state.bus = b;
|
||||
h->bus = b;
|
||||
|
||||
pci_create_simple(b, 0, "e500-host-bridge");
|
||||
|
||||
@@ -350,7 +356,7 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
|
||||
dc->desc = "Host bridge";
|
||||
}
|
||||
|
||||
static TypeInfo e500_host_bridge_info = {
|
||||
static const TypeInfo e500_host_bridge_info = {
|
||||
.name = "e500-host-bridge",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIDevice),
|
||||
@@ -366,9 +372,9 @@ static void e500_pcihost_class_init(ObjectClass *klass, void *data)
|
||||
dc->vmsd = &vmstate_ppce500_pci;
|
||||
}
|
||||
|
||||
static TypeInfo e500_pcihost_info = {
|
||||
.name = "e500-pcihost",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo e500_pcihost_info = {
|
||||
.name = TYPE_PPC_E500_PCI_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(PPCE500PCIState),
|
||||
.class_init = e500_pcihost_class_init,
|
||||
};
|
||||
|
||||
+21
-12
@@ -28,8 +28,14 @@
|
||||
#include "pc.h"
|
||||
#include "exec-memory.h"
|
||||
|
||||
#define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost"
|
||||
|
||||
#define RAVEN_PCI_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(PREPPCIState, (obj), TYPE_RAVEN_PCI_HOST_BRIDGE)
|
||||
|
||||
typedef struct PRePPCIState {
|
||||
PCIHostState host_state;
|
||||
PCIHostState parent_obj;
|
||||
|
||||
MemoryRegion intack;
|
||||
qemu_irq irq[4];
|
||||
} PREPPCIState;
|
||||
@@ -42,9 +48,10 @@ static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 11; i++) {
|
||||
if ((addr & (1 << (11 + i))) != 0)
|
||||
for (i = 0; i < 11; i++) {
|
||||
if ((addr & (1 << (11 + i))) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (addr & 0x7ff) | (i << 11);
|
||||
}
|
||||
@@ -53,14 +60,16 @@ static void ppc_pci_io_write(void *opaque, target_phys_addr_t addr,
|
||||
uint64_t val, unsigned int size)
|
||||
{
|
||||
PREPPCIState *s = opaque;
|
||||
pci_data_write(s->host_state.bus, PPC_PCIIO_config(addr), val, size);
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||
pci_data_write(phb->bus, PPC_PCIIO_config(addr), val, size);
|
||||
}
|
||||
|
||||
static uint64_t ppc_pci_io_read(void *opaque, target_phys_addr_t addr,
|
||||
unsigned int size)
|
||||
{
|
||||
PREPPCIState *s = opaque;
|
||||
return pci_data_read(s->host_state.bus, PPC_PCIIO_config(addr), size);
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||
return pci_data_read(phb->bus, PPC_PCIIO_config(addr), size);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps PPC_PCIIO_ops = {
|
||||
@@ -96,8 +105,8 @@ static void prep_set_irq(void *opaque, int irq_num, int level)
|
||||
|
||||
static int raven_pcihost_init(SysBusDevice *dev)
|
||||
{
|
||||
PCIHostState *h = FROM_SYSBUS(PCIHostState, dev);
|
||||
PREPPCIState *s = DO_UPCAST(PREPPCIState, host_state, h);
|
||||
PCIHostState *h = PCI_HOST_BRIDGE(dev);
|
||||
PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(dev);
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *address_space_io = get_system_io();
|
||||
PCIBus *bus;
|
||||
@@ -107,7 +116,7 @@ static int raven_pcihost_init(SysBusDevice *dev)
|
||||
sysbus_init_irq(dev, &s->irq[i]);
|
||||
}
|
||||
|
||||
bus = pci_register_bus(&h->busdev.qdev, NULL,
|
||||
bus = pci_register_bus(DEVICE(dev), NULL,
|
||||
prep_set_irq, prep_map_irq, s->irq,
|
||||
address_space_mem, address_space_io, 0, 4);
|
||||
h->bus = bus;
|
||||
@@ -166,7 +175,7 @@ static void raven_class_init(ObjectClass *klass, void *data)
|
||||
dc->no_user = 1;
|
||||
}
|
||||
|
||||
static TypeInfo raven_info = {
|
||||
static const TypeInfo raven_info = {
|
||||
.name = "raven",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(RavenPCIState),
|
||||
@@ -183,9 +192,9 @@ static void raven_pcihost_class_init(ObjectClass *klass, void *data)
|
||||
dc->no_user = 1;
|
||||
}
|
||||
|
||||
static TypeInfo raven_pcihost_info = {
|
||||
.name = "raven-pcihost",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo raven_pcihost_info = {
|
||||
.name = TYPE_RAVEN_PCI_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(PREPPCIState),
|
||||
.class_init = raven_pcihost_class_init,
|
||||
};
|
||||
|
||||
+1
-1
@@ -543,7 +543,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
|
||||
qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
|
||||
class = object_class_get_parent(class);
|
||||
} while (class != object_class_by_name(TYPE_DEVICE));
|
||||
bus_print_dev(dev->parent_bus, mon, dev, indent + 2);
|
||||
bus_print_dev(dev->parent_bus, mon, dev, indent);
|
||||
QLIST_FOREACH(child, &dev->child_bus, sibling) {
|
||||
qbus_print(mon, child, indent);
|
||||
}
|
||||
|
||||
@@ -159,7 +159,6 @@ int qdev_init(DeviceState *dev)
|
||||
|
||||
rc = dc->init(dev);
|
||||
if (rc < 0) {
|
||||
object_unparent(OBJECT(dev));
|
||||
qdev_free(dev);
|
||||
return rc;
|
||||
}
|
||||
@@ -243,7 +242,6 @@ void qbus_reset_all_fn(void *opaque)
|
||||
int qdev_simple_unplug_cb(DeviceState *dev)
|
||||
{
|
||||
/* just zap it */
|
||||
object_unparent(OBJECT(dev));
|
||||
qdev_free(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -761,6 +761,7 @@ static int ata_passthrough_12_xfer_size(SCSIDevice *dev, uint8_t *buf)
|
||||
switch (length) {
|
||||
case 0:
|
||||
case 3: /* USB-specific. */
|
||||
default:
|
||||
xfer = 0;
|
||||
break;
|
||||
case 1:
|
||||
@@ -784,6 +785,7 @@ static int ata_passthrough_16_xfer_size(SCSIDevice *dev, uint8_t *buf)
|
||||
switch (length) {
|
||||
case 0:
|
||||
case 3: /* USB-specific. */
|
||||
default:
|
||||
xfer = 0;
|
||||
break;
|
||||
case 1:
|
||||
|
||||
+2
-1
@@ -1461,7 +1461,7 @@ static void scsi_unmap_complete(void *opaque, int ret)
|
||||
SCSIDiskReq *r = data->r;
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
||||
uint64_t sector_num;
|
||||
uint32 nb_sectors;
|
||||
uint32_t nb_sectors;
|
||||
|
||||
r->req.aiocb = NULL;
|
||||
if (ret < 0) {
|
||||
@@ -2421,6 +2421,7 @@ static TypeInfo scsi_cd_info = {
|
||||
#ifdef __linux__
|
||||
static Property scsi_block_properties[] = {
|
||||
DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.bs),
|
||||
DEFINE_PROP_INT32("bootindex", SCSIDiskState, qdev.conf.bootindex, -1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
||||
+2
-1
@@ -479,7 +479,8 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
||||
}
|
||||
|
||||
static Property scsi_generic_properties[] = {
|
||||
DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
|
||||
DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs),
|
||||
DEFINE_PROP_INT32("bootindex", SCSIDevice, conf.bootindex, -1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
||||
@@ -253,7 +253,6 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
|
||||
++devfn) {
|
||||
PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
|
||||
if (affected_dev) {
|
||||
object_unparent(OBJECT(affected_dev));
|
||||
qdev_free(&affected_dev->qdev);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -612,6 +612,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
|
||||
{
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
PCIHostState *phb;
|
||||
int i;
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
@@ -742,6 +743,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
|
||||
SPAPR_PCI_MEM_WIN_SIZE,
|
||||
SPAPR_PCI_IO_WIN_ADDR,
|
||||
SPAPR_PCI_MSI_WIN_ADDR);
|
||||
phb = PCI_HOST_BRIDGE(QLIST_FIRST(&spapr->phbs));
|
||||
|
||||
for (i = 0; i < nb_nics; i++) {
|
||||
NICInfo *nd = &nd_table[i];
|
||||
@@ -762,13 +764,12 @@ static void ppc_spapr_init(ram_addr_t ram_size,
|
||||
}
|
||||
|
||||
/* Graphics */
|
||||
if (spapr_vga_init(QLIST_FIRST(&spapr->phbs)->host_state.bus)) {
|
||||
if (spapr_vga_init(phb->bus)) {
|
||||
spapr->has_graphics = true;
|
||||
}
|
||||
|
||||
if (usb_enabled) {
|
||||
pci_create_simple(QLIST_FIRST(&spapr->phbs)->host_state.bus,
|
||||
-1, "pci-ohci");
|
||||
pci_create_simple(phb->bus, -1, "pci-ohci");
|
||||
if (spapr->has_graphics) {
|
||||
usbdevice_create("keyboard");
|
||||
usbdevice_create("mouse");
|
||||
|
||||
+49
-45
@@ -48,13 +48,13 @@
|
||||
|
||||
static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid)
|
||||
{
|
||||
sPAPRPHBState *phb;
|
||||
sPAPRPHBState *sphb;
|
||||
|
||||
QLIST_FOREACH(phb, &spapr->phbs, list) {
|
||||
if (phb->buid != buid) {
|
||||
QLIST_FOREACH(sphb, &spapr->phbs, list) {
|
||||
if (sphb->buid != buid) {
|
||||
continue;
|
||||
}
|
||||
return phb;
|
||||
return sphb;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -63,7 +63,9 @@ static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid)
|
||||
static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid,
|
||||
uint32_t config_addr)
|
||||
{
|
||||
sPAPRPHBState *phb = find_phb(spapr, buid);
|
||||
sPAPRPHBState *sphb = find_phb(spapr, buid);
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(sphb);
|
||||
BusState *bus = BUS(phb->bus);
|
||||
BusChild *kid;
|
||||
int devfn = (config_addr >> 8) & 0xFF;
|
||||
|
||||
@@ -71,7 +73,7 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH(kid, &phb->host_state.bus->qbus.children, sibling) {
|
||||
QTAILQ_FOREACH(kid, &bus->children, sibling) {
|
||||
PCIDevice *dev = (PCIDevice *)kid->child;
|
||||
if (dev->devfn == devfn) {
|
||||
return dev;
|
||||
@@ -514,23 +516,24 @@ static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque,
|
||||
|
||||
static int spapr_phb_init(SysBusDevice *s)
|
||||
{
|
||||
sPAPRPHBState *phb = DO_UPCAST(sPAPRPHBState, host_state.busdev, s);
|
||||
sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||
char *namebuf;
|
||||
int i;
|
||||
PCIBus *bus;
|
||||
|
||||
phb->dtbusname = g_strdup_printf("pci@%" PRIx64, phb->buid);
|
||||
namebuf = alloca(strlen(phb->dtbusname) + 32);
|
||||
sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid);
|
||||
namebuf = alloca(strlen(sphb->dtbusname) + 32);
|
||||
|
||||
/* Initialize memory regions */
|
||||
sprintf(namebuf, "%s.mmio", phb->dtbusname);
|
||||
memory_region_init(&phb->memspace, namebuf, INT64_MAX);
|
||||
sprintf(namebuf, "%s.mmio", sphb->dtbusname);
|
||||
memory_region_init(&sphb->memspace, namebuf, INT64_MAX);
|
||||
|
||||
sprintf(namebuf, "%s.mmio-alias", phb->dtbusname);
|
||||
memory_region_init_alias(&phb->memwindow, namebuf, &phb->memspace,
|
||||
SPAPR_PCI_MEM_WIN_BUS_OFFSET, phb->mem_win_size);
|
||||
memory_region_add_subregion(get_system_memory(), phb->mem_win_addr,
|
||||
&phb->memwindow);
|
||||
sprintf(namebuf, "%s.mmio-alias", sphb->dtbusname);
|
||||
memory_region_init_alias(&sphb->memwindow, namebuf, &sphb->memspace,
|
||||
SPAPR_PCI_MEM_WIN_BUS_OFFSET, sphb->mem_win_size);
|
||||
memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr,
|
||||
&sphb->memwindow);
|
||||
|
||||
/* On ppc, we only have MMIO no specific IO space from the CPU
|
||||
* perspective. In theory we ought to be able to embed the PCI IO
|
||||
@@ -540,42 +543,42 @@ static int spapr_phb_init(SysBusDevice *s)
|
||||
* system io address space. This hack to bounce things via
|
||||
* system_io works around the problem until all the users of
|
||||
* old_portion are updated */
|
||||
sprintf(namebuf, "%s.io", phb->dtbusname);
|
||||
memory_region_init(&phb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
|
||||
sprintf(namebuf, "%s.io", sphb->dtbusname);
|
||||
memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
|
||||
/* FIXME: fix to support multiple PHBs */
|
||||
memory_region_add_subregion(get_system_io(), 0, &phb->iospace);
|
||||
memory_region_add_subregion(get_system_io(), 0, &sphb->iospace);
|
||||
|
||||
sprintf(namebuf, "%s.io-alias", phb->dtbusname);
|
||||
memory_region_init_io(&phb->iowindow, &spapr_io_ops, phb,
|
||||
sprintf(namebuf, "%s.io-alias", sphb->dtbusname);
|
||||
memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb,
|
||||
namebuf, SPAPR_PCI_IO_WIN_SIZE);
|
||||
memory_region_add_subregion(get_system_memory(), phb->io_win_addr,
|
||||
&phb->iowindow);
|
||||
memory_region_add_subregion(get_system_memory(), sphb->io_win_addr,
|
||||
&sphb->iowindow);
|
||||
|
||||
/* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors,
|
||||
* we need to allocate some memory to catch those writes coming
|
||||
* from msi_notify()/msix_notify() */
|
||||
if (msi_supported) {
|
||||
sprintf(namebuf, "%s.msi", phb->dtbusname);
|
||||
memory_region_init_io(&phb->msiwindow, &spapr_msi_ops, phb,
|
||||
sprintf(namebuf, "%s.msi", sphb->dtbusname);
|
||||
memory_region_init_io(&sphb->msiwindow, &spapr_msi_ops, sphb,
|
||||
namebuf, SPAPR_MSIX_MAX_DEVS * 0x10000);
|
||||
memory_region_add_subregion(get_system_memory(), phb->msi_win_addr,
|
||||
&phb->msiwindow);
|
||||
memory_region_add_subregion(get_system_memory(), sphb->msi_win_addr,
|
||||
&sphb->msiwindow);
|
||||
}
|
||||
|
||||
bus = pci_register_bus(&phb->host_state.busdev.qdev,
|
||||
phb->busname ? phb->busname : phb->dtbusname,
|
||||
pci_spapr_set_irq, pci_spapr_map_irq, phb,
|
||||
&phb->memspace, &phb->iospace,
|
||||
bus = pci_register_bus(DEVICE(s),
|
||||
sphb->busname ? sphb->busname : sphb->dtbusname,
|
||||
pci_spapr_set_irq, pci_spapr_map_irq, sphb,
|
||||
&sphb->memspace, &sphb->iospace,
|
||||
PCI_DEVFN(0, 0), PCI_NUM_PINS);
|
||||
phb->host_state.bus = bus;
|
||||
phb->bus = bus;
|
||||
|
||||
phb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16);
|
||||
phb->dma_window_start = 0;
|
||||
phb->dma_window_size = 0x40000000;
|
||||
phb->dma = spapr_tce_new_dma_context(phb->dma_liobn, phb->dma_window_size);
|
||||
pci_setup_iommu(bus, spapr_pci_dma_context_fn, phb);
|
||||
sphb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16);
|
||||
sphb->dma_window_start = 0;
|
||||
sphb->dma_window_size = 0x40000000;
|
||||
sphb->dma = spapr_tce_new_dma_context(sphb->dma_liobn, sphb->dma_window_size);
|
||||
pci_setup_iommu(bus, spapr_pci_dma_context_fn, sphb);
|
||||
|
||||
QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
|
||||
QLIST_INSERT_HEAD(&spapr->phbs, sphb, list);
|
||||
|
||||
/* Initialize the LSI table */
|
||||
for (i = 0; i < PCI_NUM_PINS; i++) {
|
||||
@@ -586,7 +589,7 @@ static int spapr_phb_init(SysBusDevice *s)
|
||||
return -1;
|
||||
}
|
||||
|
||||
phb->lsi_table[i].irq = irq;
|
||||
sphb->lsi_table[i].irq = irq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -612,9 +615,9 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
|
||||
dc->props = spapr_phb_properties;
|
||||
}
|
||||
|
||||
static TypeInfo spapr_phb_info = {
|
||||
.name = "spapr-pci-host-bridge",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo spapr_phb_info = {
|
||||
.name = TYPE_SPAPR_PCI_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(sPAPRPHBState),
|
||||
.class_init = spapr_phb_class_init,
|
||||
};
|
||||
@@ -626,7 +629,7 @@ void spapr_create_phb(sPAPREnvironment *spapr,
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
dev = qdev_create(NULL, spapr_phb_info.name);
|
||||
dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE);
|
||||
|
||||
if (busname) {
|
||||
qdev_prop_set_string(dev, "busname", g_strdup(busname));
|
||||
@@ -750,8 +753,9 @@ void spapr_pci_rtas_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void register_types(void)
|
||||
static void spapr_pci_register_types(void)
|
||||
{
|
||||
type_register_static(&spapr_phb_info);
|
||||
}
|
||||
type_init(register_types)
|
||||
|
||||
type_init(spapr_pci_register_types)
|
||||
+6
-1
@@ -29,8 +29,13 @@
|
||||
|
||||
#define SPAPR_MSIX_MAX_DEVS 32
|
||||
|
||||
#define TYPE_SPAPR_PCI_HOST_BRIDGE "spapr-pci-host-bridge"
|
||||
|
||||
#define SPAPR_PCI_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(sPAPRPHBState, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE)
|
||||
|
||||
typedef struct sPAPRPHBState {
|
||||
PCIHostState host_state;
|
||||
PCIHostState parent_obj;
|
||||
|
||||
uint64_t buid;
|
||||
char *busname;
|
||||
|
||||
+95
-86
@@ -38,8 +38,23 @@
|
||||
|
||||
static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e };
|
||||
|
||||
#define TYPE_UNI_NORTH_PCI_HOST_BRIDGE "uni-north-pci-pcihost"
|
||||
#define TYPE_UNI_NORTH_AGP_HOST_BRIDGE "uni-north-agp-pcihost"
|
||||
#define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost"
|
||||
#define TYPE_U3_AGP_HOST_BRIDGE "u3-agp-pcihost"
|
||||
|
||||
#define UNI_NORTH_PCI_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_PCI_HOST_BRIDGE)
|
||||
#define UNI_NORTH_AGP_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_AGP_HOST_BRIDGE)
|
||||
#define UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE)
|
||||
#define U3_AGP_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(UNINState, (obj), TYPE_U3_AGP_HOST_BRIDGE)
|
||||
|
||||
typedef struct UNINState {
|
||||
PCIHostState host_state;
|
||||
PCIHostState parent_obj;
|
||||
|
||||
MemoryRegion pci_mmio;
|
||||
MemoryRegion pci_hole;
|
||||
} UNINState;
|
||||
@@ -100,10 +115,11 @@ static void unin_data_write(void *opaque, target_phys_addr_t addr,
|
||||
uint64_t val, unsigned len)
|
||||
{
|
||||
UNINState *s = opaque;
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||
UNIN_DPRINTF("write addr %" TARGET_FMT_plx " len %d val %"PRIx64"\n",
|
||||
addr, len, val);
|
||||
pci_data_write(s->host_state.bus,
|
||||
unin_get_config_reg(s->host_state.config_reg, addr),
|
||||
pci_data_write(phb->bus,
|
||||
unin_get_config_reg(phb->config_reg, addr),
|
||||
val, len);
|
||||
}
|
||||
|
||||
@@ -111,10 +127,11 @@ static uint64_t unin_data_read(void *opaque, target_phys_addr_t addr,
|
||||
unsigned len)
|
||||
{
|
||||
UNINState *s = opaque;
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||
uint32_t val;
|
||||
|
||||
val = pci_data_read(s->host_state.bus,
|
||||
unin_get_config_reg(s->host_state.config_reg, addr),
|
||||
val = pci_data_read(phb->bus,
|
||||
unin_get_config_reg(phb->config_reg, addr),
|
||||
len);
|
||||
UNIN_DPRINTF("read addr %" TARGET_FMT_plx " len %d val %x\n",
|
||||
addr, len, val);
|
||||
@@ -130,19 +147,17 @@ static const MemoryRegionOps unin_data_ops = {
|
||||
static int pci_unin_main_init_device(SysBusDevice *dev)
|
||||
{
|
||||
PCIHostState *h;
|
||||
UNINState *s;
|
||||
|
||||
/* Use values found on a real PowerMac */
|
||||
/* Uninorth main bus */
|
||||
h = FROM_SYSBUS(PCIHostState, dev);
|
||||
s = DO_UPCAST(UNINState, host_state, h);
|
||||
h = PCI_HOST_BRIDGE(dev);
|
||||
|
||||
memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
|
||||
&s->host_state, "pci-conf-idx", 0x1000);
|
||||
memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s,
|
||||
memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
|
||||
dev, "pci-conf-idx", 0x1000);
|
||||
memory_region_init_io(&h->data_mem, &unin_data_ops, dev,
|
||||
"pci-conf-data", 0x1000);
|
||||
sysbus_init_mmio(dev, &s->host_state.conf_mem);
|
||||
sysbus_init_mmio(dev, &s->host_state.data_mem);
|
||||
sysbus_init_mmio(dev, &h->conf_mem);
|
||||
sysbus_init_mmio(dev, &h->data_mem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -151,18 +166,16 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
|
||||
static int pci_u3_agp_init_device(SysBusDevice *dev)
|
||||
{
|
||||
PCIHostState *h;
|
||||
UNINState *s;
|
||||
|
||||
/* Uninorth U3 AGP bus */
|
||||
h = FROM_SYSBUS(PCIHostState, dev);
|
||||
s = DO_UPCAST(UNINState, host_state, h);
|
||||
h = PCI_HOST_BRIDGE(dev);
|
||||
|
||||
memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
|
||||
&s->host_state, "pci-conf-idx", 0x1000);
|
||||
memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s,
|
||||
memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
|
||||
dev, "pci-conf-idx", 0x1000);
|
||||
memory_region_init_io(&h->data_mem, &unin_data_ops, dev,
|
||||
"pci-conf-data", 0x1000);
|
||||
sysbus_init_mmio(dev, &s->host_state.conf_mem);
|
||||
sysbus_init_mmio(dev, &s->host_state.data_mem);
|
||||
sysbus_init_mmio(dev, &h->conf_mem);
|
||||
sysbus_init_mmio(dev, &h->data_mem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -170,36 +183,32 @@ static int pci_u3_agp_init_device(SysBusDevice *dev)
|
||||
static int pci_unin_agp_init_device(SysBusDevice *dev)
|
||||
{
|
||||
PCIHostState *h;
|
||||
UNINState *s;
|
||||
|
||||
/* Uninorth AGP bus */
|
||||
h = FROM_SYSBUS(PCIHostState, dev);
|
||||
s = DO_UPCAST(UNINState, host_state, h);
|
||||
h = PCI_HOST_BRIDGE(dev);
|
||||
|
||||
memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
|
||||
&s->host_state, "pci-conf-idx", 0x1000);
|
||||
memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
|
||||
&s->host_state, "pci-conf-data", 0x1000);
|
||||
sysbus_init_mmio(dev, &s->host_state.conf_mem);
|
||||
sysbus_init_mmio(dev, &s->host_state.data_mem);
|
||||
memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
|
||||
dev, "pci-conf-idx", 0x1000);
|
||||
memory_region_init_io(&h->data_mem, &pci_host_data_le_ops,
|
||||
dev, "pci-conf-data", 0x1000);
|
||||
sysbus_init_mmio(dev, &h->conf_mem);
|
||||
sysbus_init_mmio(dev, &h->data_mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pci_unin_internal_init_device(SysBusDevice *dev)
|
||||
{
|
||||
PCIHostState *h;
|
||||
UNINState *s;
|
||||
|
||||
/* Uninorth internal bus */
|
||||
h = FROM_SYSBUS(PCIHostState, dev);
|
||||
s = DO_UPCAST(UNINState, host_state, h);
|
||||
h = PCI_HOST_BRIDGE(dev);
|
||||
|
||||
memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
|
||||
&s->host_state, "pci-conf-idx", 0x1000);
|
||||
memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops,
|
||||
&s->host_state, "pci-conf-data", 0x1000);
|
||||
sysbus_init_mmio(dev, &s->host_state.conf_mem);
|
||||
sysbus_init_mmio(dev, &s->host_state.data_mem);
|
||||
memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
|
||||
dev, "pci-conf-idx", 0x1000);
|
||||
memory_region_init_io(&h->data_mem, &pci_host_data_le_ops,
|
||||
dev, "pci-conf-data", 0x1000);
|
||||
sysbus_init_mmio(dev, &h->conf_mem);
|
||||
sysbus_init_mmio(dev, &h->data_mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -214,26 +223,26 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
|
||||
|
||||
/* Use values found on a real PowerMac */
|
||||
/* Uninorth main bus */
|
||||
dev = qdev_create(NULL, "uni-north-pci-pcihost");
|
||||
dev = qdev_create(NULL, TYPE_UNI_NORTH_PCI_HOST_BRIDGE);
|
||||
qdev_init_nofail(dev);
|
||||
s = sysbus_from_qdev(dev);
|
||||
h = FROM_SYSBUS(PCIHostState, s);
|
||||
d = DO_UPCAST(UNINState, host_state, h);
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
h = PCI_HOST_BRIDGE(s);
|
||||
d = UNI_NORTH_PCI_HOST_BRIDGE(dev);
|
||||
memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
|
||||
memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
|
||||
0x80000000ULL, 0x70000000ULL);
|
||||
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
|
||||
&d->pci_hole);
|
||||
|
||||
d->host_state.bus = pci_register_bus(dev, "pci",
|
||||
pci_unin_set_irq, pci_unin_map_irq,
|
||||
pic,
|
||||
&d->pci_mmio,
|
||||
address_space_io,
|
||||
PCI_DEVFN(11, 0), 4);
|
||||
h->bus = pci_register_bus(dev, "pci",
|
||||
pci_unin_set_irq, pci_unin_map_irq,
|
||||
pic,
|
||||
&d->pci_mmio,
|
||||
address_space_io,
|
||||
PCI_DEVFN(11, 0), 4);
|
||||
|
||||
#if 0
|
||||
pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north");
|
||||
pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north");
|
||||
#endif
|
||||
|
||||
sysbus_mmio_map(s, 0, 0xf2800000);
|
||||
@@ -242,30 +251,30 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
|
||||
/* DEC 21154 bridge */
|
||||
#if 0
|
||||
/* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
|
||||
pci_create_simple(d->host_state.bus, PCI_DEVFN(12, 0), "dec-21154");
|
||||
pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154");
|
||||
#endif
|
||||
|
||||
/* Uninorth AGP bus */
|
||||
pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north-agp");
|
||||
dev = qdev_create(NULL, "uni-north-agp-pcihost");
|
||||
pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp");
|
||||
dev = qdev_create(NULL, TYPE_UNI_NORTH_AGP_HOST_BRIDGE);
|
||||
qdev_init_nofail(dev);
|
||||
s = sysbus_from_qdev(dev);
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
sysbus_mmio_map(s, 0, 0xf0800000);
|
||||
sysbus_mmio_map(s, 1, 0xf0c00000);
|
||||
|
||||
/* Uninorth internal bus */
|
||||
#if 0
|
||||
/* XXX: not needed for now */
|
||||
pci_create_simple(d->host_state.bus, PCI_DEVFN(14, 0),
|
||||
pci_create_simple(h->bus, PCI_DEVFN(14, 0),
|
||||
"uni-north-internal-pci");
|
||||
dev = qdev_create(NULL, "uni-north-internal-pci-pcihost");
|
||||
dev = qdev_create(NULL, TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE);
|
||||
qdev_init_nofail(dev);
|
||||
s = sysbus_from_qdev(dev);
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
sysbus_mmio_map(s, 0, 0xf4800000);
|
||||
sysbus_mmio_map(s, 1, 0xf4c00000);
|
||||
#endif
|
||||
|
||||
return d->host_state.bus;
|
||||
return h->bus;
|
||||
}
|
||||
|
||||
PCIBus *pci_pmac_u3_init(qemu_irq *pic,
|
||||
@@ -279,11 +288,11 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
|
||||
|
||||
/* Uninorth AGP bus */
|
||||
|
||||
dev = qdev_create(NULL, "u3-agp-pcihost");
|
||||
dev = qdev_create(NULL, TYPE_U3_AGP_HOST_BRIDGE);
|
||||
qdev_init_nofail(dev);
|
||||
s = sysbus_from_qdev(dev);
|
||||
h = FROM_SYSBUS(PCIHostState, s);
|
||||
d = DO_UPCAST(UNINState, host_state, h);
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
h = PCI_HOST_BRIDGE(dev);
|
||||
d = U3_AGP_HOST_BRIDGE(dev);
|
||||
|
||||
memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
|
||||
memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
|
||||
@@ -291,19 +300,19 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
|
||||
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
|
||||
&d->pci_hole);
|
||||
|
||||
d->host_state.bus = pci_register_bus(dev, "pci",
|
||||
pci_unin_set_irq, pci_unin_map_irq,
|
||||
pic,
|
||||
&d->pci_mmio,
|
||||
address_space_io,
|
||||
PCI_DEVFN(11, 0), 4);
|
||||
h->bus = pci_register_bus(dev, "pci",
|
||||
pci_unin_set_irq, pci_unin_map_irq,
|
||||
pic,
|
||||
&d->pci_mmio,
|
||||
address_space_io,
|
||||
PCI_DEVFN(11, 0), 4);
|
||||
|
||||
sysbus_mmio_map(s, 0, 0xf0800000);
|
||||
sysbus_mmio_map(s, 1, 0xf0c00000);
|
||||
|
||||
pci_create_simple(d->host_state.bus, 11 << 3, "u3-agp");
|
||||
pci_create_simple(h->bus, 11 << 3, "u3-agp");
|
||||
|
||||
return d->host_state.bus;
|
||||
return h->bus;
|
||||
}
|
||||
|
||||
static int unin_main_pci_host_init(PCIDevice *d)
|
||||
@@ -350,7 +359,7 @@ static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
|
||||
k->class_id = PCI_CLASS_BRIDGE_HOST;
|
||||
}
|
||||
|
||||
static TypeInfo unin_main_pci_host_info = {
|
||||
static const TypeInfo unin_main_pci_host_info = {
|
||||
.name = "uni-north-pci",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIDevice),
|
||||
@@ -368,7 +377,7 @@ static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data)
|
||||
k->class_id = PCI_CLASS_BRIDGE_HOST;
|
||||
}
|
||||
|
||||
static TypeInfo u3_agp_pci_host_info = {
|
||||
static const TypeInfo u3_agp_pci_host_info = {
|
||||
.name = "u3-agp",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIDevice),
|
||||
@@ -386,7 +395,7 @@ static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data)
|
||||
k->class_id = PCI_CLASS_BRIDGE_HOST;
|
||||
}
|
||||
|
||||
static TypeInfo unin_agp_pci_host_info = {
|
||||
static const TypeInfo unin_agp_pci_host_info = {
|
||||
.name = "uni-north-agp",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIDevice),
|
||||
@@ -404,7 +413,7 @@ static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data)
|
||||
k->class_id = PCI_CLASS_BRIDGE_HOST;
|
||||
}
|
||||
|
||||
static TypeInfo unin_internal_pci_host_info = {
|
||||
static const TypeInfo unin_internal_pci_host_info = {
|
||||
.name = "uni-north-internal-pci",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIDevice),
|
||||
@@ -418,9 +427,9 @@ static void pci_unin_main_class_init(ObjectClass *klass, void *data)
|
||||
sbc->init = pci_unin_main_init_device;
|
||||
}
|
||||
|
||||
static TypeInfo pci_unin_main_info = {
|
||||
.name = "uni-north-pci-pcihost",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo pci_unin_main_info = {
|
||||
.name = TYPE_UNI_NORTH_PCI_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(UNINState),
|
||||
.class_init = pci_unin_main_class_init,
|
||||
};
|
||||
@@ -432,9 +441,9 @@ static void pci_u3_agp_class_init(ObjectClass *klass, void *data)
|
||||
sbc->init = pci_u3_agp_init_device;
|
||||
}
|
||||
|
||||
static TypeInfo pci_u3_agp_info = {
|
||||
.name = "u3-agp-pcihost",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo pci_u3_agp_info = {
|
||||
.name = TYPE_U3_AGP_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(UNINState),
|
||||
.class_init = pci_u3_agp_class_init,
|
||||
};
|
||||
@@ -446,9 +455,9 @@ static void pci_unin_agp_class_init(ObjectClass *klass, void *data)
|
||||
sbc->init = pci_unin_agp_init_device;
|
||||
}
|
||||
|
||||
static TypeInfo pci_unin_agp_info = {
|
||||
.name = "uni-north-agp-pcihost",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo pci_unin_agp_info = {
|
||||
.name = TYPE_UNI_NORTH_AGP_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(UNINState),
|
||||
.class_init = pci_unin_agp_class_init,
|
||||
};
|
||||
@@ -460,9 +469,9 @@ static void pci_unin_internal_class_init(ObjectClass *klass, void *data)
|
||||
sbc->init = pci_unin_internal_init_device;
|
||||
}
|
||||
|
||||
static TypeInfo pci_unin_internal_info = {
|
||||
.name = "uni-north-internal-pci-pcihost",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
static const TypeInfo pci_unin_internal_info = {
|
||||
.name = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(UNINState),
|
||||
.class_init = pci_unin_internal_class_init,
|
||||
};
|
||||
|
||||
@@ -179,6 +179,7 @@ struct USBEndpoint {
|
||||
uint8_t ifnum;
|
||||
int max_packet_size;
|
||||
bool pipeline;
|
||||
bool halted;
|
||||
USBDevice *dev;
|
||||
QTAILQ_HEAD(, USBPacket) queue;
|
||||
};
|
||||
@@ -331,6 +332,7 @@ typedef enum USBPacketState {
|
||||
struct USBPacket {
|
||||
/* Data fields for use by the driver. */
|
||||
int pid;
|
||||
uint64_t id;
|
||||
USBEndpoint *ep;
|
||||
QEMUIOVector iov;
|
||||
uint64_t parameter; /* control transfers */
|
||||
@@ -343,7 +345,7 @@ struct USBPacket {
|
||||
void usb_packet_init(USBPacket *p);
|
||||
void usb_packet_set_state(USBPacket *p, USBPacketState state);
|
||||
void usb_packet_check_state(USBPacket *p, USBPacketState expected);
|
||||
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep);
|
||||
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id);
|
||||
void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len);
|
||||
int usb_packet_map(USBPacket *p, QEMUSGList *sgl);
|
||||
void usb_packet_unmap(USBPacket *p, QEMUSGList *sgl);
|
||||
|
||||
+31
-8
@@ -107,6 +107,7 @@ static int do_token_setup(USBDevice *s, USBPacket *p)
|
||||
}
|
||||
|
||||
usb_packet_copy(p, s->setup_buf, p->iov.size);
|
||||
p->result = 0;
|
||||
s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
|
||||
s->setup_index = 0;
|
||||
|
||||
@@ -381,12 +382,23 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
|
||||
usb_packet_check_state(p, USB_PACKET_SETUP);
|
||||
assert(p->ep != NULL);
|
||||
|
||||
/* Submitting a new packet clears halt */
|
||||
if (p->ep->halted) {
|
||||
assert(QTAILQ_EMPTY(&p->ep->queue));
|
||||
p->ep->halted = false;
|
||||
}
|
||||
|
||||
if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
|
||||
ret = usb_process_one(p);
|
||||
if (ret == USB_RET_ASYNC) {
|
||||
usb_packet_set_state(p, USB_PACKET_ASYNC);
|
||||
QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
|
||||
} else {
|
||||
/*
|
||||
* When pipelining is enabled usb-devices must always return async,
|
||||
* otherwise packets can complete out of order!
|
||||
*/
|
||||
assert(!p->ep->pipeline);
|
||||
p->result = ret;
|
||||
usb_packet_set_state(p, USB_PACKET_COMPLETE);
|
||||
}
|
||||
@@ -398,6 +410,20 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __usb_packet_complete(USBDevice *dev, USBPacket *p)
|
||||
{
|
||||
USBEndpoint *ep = p->ep;
|
||||
|
||||
assert(p->result != USB_RET_ASYNC && p->result != USB_RET_NAK);
|
||||
|
||||
if (p->result < 0) {
|
||||
ep->halted = true;
|
||||
}
|
||||
usb_packet_set_state(p, USB_PACKET_COMPLETE);
|
||||
QTAILQ_REMOVE(&ep->queue, p, queue);
|
||||
dev->port->ops->complete(dev->port, p);
|
||||
}
|
||||
|
||||
/* Notify the controller that an async packet is complete. This should only
|
||||
be called for packets previously deferred by returning USB_RET_ASYNC from
|
||||
handle_packet. */
|
||||
@@ -408,11 +434,9 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
|
||||
|
||||
usb_packet_check_state(p, USB_PACKET_ASYNC);
|
||||
assert(QTAILQ_FIRST(&ep->queue) == p);
|
||||
usb_packet_set_state(p, USB_PACKET_COMPLETE);
|
||||
QTAILQ_REMOVE(&ep->queue, p, queue);
|
||||
dev->port->ops->complete(dev->port, p);
|
||||
__usb_packet_complete(dev, p);
|
||||
|
||||
while (!QTAILQ_EMPTY(&ep->queue)) {
|
||||
while (!ep->halted && !QTAILQ_EMPTY(&ep->queue)) {
|
||||
p = QTAILQ_FIRST(&ep->queue);
|
||||
if (p->state == USB_PACKET_ASYNC) {
|
||||
break;
|
||||
@@ -424,9 +448,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
|
||||
break;
|
||||
}
|
||||
p->result = ret;
|
||||
usb_packet_set_state(p, USB_PACKET_COMPLETE);
|
||||
QTAILQ_REMOVE(&ep->queue, p, queue);
|
||||
dev->port->ops->complete(dev->port, p);
|
||||
__usb_packet_complete(ep->dev, p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,10 +520,11 @@ void usb_packet_set_state(USBPacket *p, USBPacketState state)
|
||||
p->state = state;
|
||||
}
|
||||
|
||||
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep)
|
||||
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id)
|
||||
{
|
||||
assert(!usb_packet_is_inflight(p));
|
||||
assert(p->iov.iov != NULL);
|
||||
p->id = id;
|
||||
p->pid = pid;
|
||||
p->ep = ep;
|
||||
p->result = 0;
|
||||
|
||||
+2
-3
@@ -223,7 +223,7 @@ static const USBDescDevice desc_device_high = {
|
||||
static const USBDesc desc = {
|
||||
.id = {
|
||||
.idVendor = 0x46f4, /* CRC16() of "QEMU" */
|
||||
.idProduct = 0x0002,
|
||||
.idProduct = 0x0003,
|
||||
.bcdDevice = 0,
|
||||
.iManufacturer = STR_MANUFACTURER,
|
||||
.iProduct = STR_PRODUCT,
|
||||
@@ -424,6 +424,7 @@ static void usb_uas_scsi_free_request(SCSIBus *bus, void *priv)
|
||||
}
|
||||
QTAILQ_REMOVE(&uas->requests, req, next);
|
||||
g_free(req);
|
||||
usb_uas_start_next_transfer(uas);
|
||||
}
|
||||
|
||||
static UASRequest *usb_uas_find_request(UASDevice *uas, uint16_t tag)
|
||||
@@ -456,7 +457,6 @@ static void usb_uas_scsi_command_complete(SCSIRequest *r,
|
||||
uint32_t status, size_t resid)
|
||||
{
|
||||
UASRequest *req = r->hba_private;
|
||||
UASDevice *uas = req->uas;
|
||||
|
||||
trace_usb_uas_scsi_complete(req->uas->dev.addr, req->tag, status, resid);
|
||||
req->complete = true;
|
||||
@@ -465,7 +465,6 @@ static void usb_uas_scsi_command_complete(SCSIRequest *r,
|
||||
}
|
||||
usb_uas_queue_sense(req, status);
|
||||
scsi_req_unref(req->req);
|
||||
usb_uas_start_next_transfer(uas);
|
||||
}
|
||||
|
||||
static void usb_uas_scsi_request_cancelled(SCSIRequest *r)
|
||||
|
||||
+101
-54
@@ -575,7 +575,12 @@ static inline void ehci_update_irq(EHCIState *s)
|
||||
/* flag interrupt condition */
|
||||
static inline void ehci_raise_irq(EHCIState *s, int intr)
|
||||
{
|
||||
s->usbsts_pending |= intr;
|
||||
if (intr & (USBSTS_PCD | USBSTS_FLR | USBSTS_HSE)) {
|
||||
s->usbsts |= intr;
|
||||
ehci_update_irq(s);
|
||||
} else {
|
||||
s->usbsts_pending |= intr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -761,15 +766,27 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async)
|
||||
return q;
|
||||
}
|
||||
|
||||
static void ehci_cancel_queue(EHCIQueue *q)
|
||||
{
|
||||
EHCIPacket *p;
|
||||
|
||||
p = QTAILQ_FIRST(&q->packets);
|
||||
if (p == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
trace_usb_ehci_queue_action(q, "cancel");
|
||||
do {
|
||||
ehci_free_packet(p);
|
||||
} while ((p = QTAILQ_FIRST(&q->packets)) != NULL);
|
||||
}
|
||||
|
||||
static void ehci_free_queue(EHCIQueue *q)
|
||||
{
|
||||
EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues;
|
||||
EHCIPacket *p;
|
||||
|
||||
trace_usb_ehci_queue_action(q, "free");
|
||||
while ((p = QTAILQ_FIRST(&q->packets)) != NULL) {
|
||||
ehci_free_packet(p);
|
||||
}
|
||||
ehci_cancel_queue(q);
|
||||
QTAILQ_REMOVE(head, q, next);
|
||||
g_free(q);
|
||||
}
|
||||
@@ -1182,22 +1199,32 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) !=
|
||||
((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) {
|
||||
if (s->pstate == EST_INACTIVE) {
|
||||
SET_LAST_RUN_CLOCK(s);
|
||||
}
|
||||
ehci_update_halt(s);
|
||||
s->async_stepdown = 0;
|
||||
qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
|
||||
}
|
||||
|
||||
/* not supporting dynamic frame list size at the moment */
|
||||
if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) {
|
||||
fprintf(stderr, "attempt to set frame list size -- value %d\n",
|
||||
val & USBCMD_FLS);
|
||||
val &= ~USBCMD_FLS;
|
||||
}
|
||||
|
||||
if (val & USBCMD_IAAD) {
|
||||
/*
|
||||
* Process IAAD immediately, otherwise the Linux IAAD watchdog may
|
||||
* trigger and re-use a qh without us seeing the unlink.
|
||||
*/
|
||||
s->async_stepdown = 0;
|
||||
qemu_bh_schedule(s->async_bh);
|
||||
}
|
||||
|
||||
if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) !=
|
||||
((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) {
|
||||
if (s->pstate == EST_INACTIVE) {
|
||||
SET_LAST_RUN_CLOCK(s);
|
||||
}
|
||||
s->usbcmd = val; /* Set usbcmd for ehci_update_halt() */
|
||||
ehci_update_halt(s);
|
||||
s->async_stepdown = 0;
|
||||
qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
|
||||
}
|
||||
break;
|
||||
|
||||
case USBSTS:
|
||||
@@ -1524,7 +1551,7 @@ static int ehci_execute(EHCIPacket *p, const char *action)
|
||||
endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP);
|
||||
ep = usb_ep_get(p->queue->dev, p->pid, endp);
|
||||
|
||||
usb_packet_setup(&p->packet, p->pid, ep);
|
||||
usb_packet_setup(&p->packet, p->pid, ep, p->qtdaddr);
|
||||
usb_packet_map(&p->packet, &p->sgl);
|
||||
|
||||
trace_usb_ehci_packet_action(p->queue, p, action);
|
||||
@@ -1546,7 +1573,8 @@ static int ehci_execute(EHCIPacket *p, const char *action)
|
||||
*/
|
||||
|
||||
static int ehci_process_itd(EHCIState *ehci,
|
||||
EHCIitd *itd)
|
||||
EHCIitd *itd,
|
||||
uint32_t addr)
|
||||
{
|
||||
USBDevice *dev;
|
||||
USBEndpoint *ep;
|
||||
@@ -1591,8 +1619,8 @@ static int ehci_process_itd(EHCIState *ehci,
|
||||
|
||||
dev = ehci_find_device(ehci, devaddr);
|
||||
ep = usb_ep_get(dev, pid, endp);
|
||||
if (ep->type == USB_ENDPOINT_XFER_ISOC) {
|
||||
usb_packet_setup(&ehci->ipacket, pid, ep);
|
||||
if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) {
|
||||
usb_packet_setup(&ehci->ipacket, pid, ep, addr);
|
||||
usb_packet_map(&ehci->ipacket, &ehci->isgl);
|
||||
ret = usb_handle_packet(dev, &ehci->ipacket);
|
||||
assert(ret != USB_RET_ASYNC);
|
||||
@@ -1780,9 +1808,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
||||
if (q->dev != NULL && q->dev->addr != devaddr) {
|
||||
if (!QTAILQ_EMPTY(&q->packets)) {
|
||||
/* should not happen (guest bug) */
|
||||
while ((p = QTAILQ_FIRST(&q->packets)) != NULL) {
|
||||
ehci_free_packet(p);
|
||||
}
|
||||
ehci_cancel_queue(q);
|
||||
}
|
||||
q->dev = NULL;
|
||||
}
|
||||
@@ -1790,11 +1816,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
||||
q->dev = ehci_find_device(q->ehci, devaddr);
|
||||
}
|
||||
|
||||
if (p && p->async == EHCI_ASYNC_INFLIGHT) {
|
||||
/* I/O still in progress -- skip queue */
|
||||
ehci_set_state(ehci, async, EST_HORIZONTALQH);
|
||||
goto out;
|
||||
}
|
||||
if (p && p->async == EHCI_ASYNC_FINISHED) {
|
||||
/* I/O finished -- continue processing queue */
|
||||
trace_usb_ehci_packet_action(p->queue, p, "complete");
|
||||
@@ -1856,7 +1877,7 @@ static int ehci_state_fetchitd(EHCIState *ehci, int async)
|
||||
sizeof(EHCIitd) >> 2);
|
||||
ehci_trace_itd(ehci, entry, &itd);
|
||||
|
||||
if (ehci_process_itd(ehci, &itd) != 0) {
|
||||
if (ehci_process_itd(ehci, &itd, entry) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1943,29 +1964,50 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
|
||||
ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd);
|
||||
|
||||
p = QTAILQ_FIRST(&q->packets);
|
||||
while (p != NULL && p->qtdaddr != q->qtdaddr) {
|
||||
/* should not happen (guest bug) */
|
||||
ehci_free_packet(p);
|
||||
p = QTAILQ_FIRST(&q->packets);
|
||||
}
|
||||
if (p != NULL) {
|
||||
ehci_qh_do_overlay(q);
|
||||
ehci_flush_qh(q);
|
||||
if (p->async == EHCI_ASYNC_INFLIGHT) {
|
||||
ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
|
||||
if (p->qtdaddr != q->qtdaddr ||
|
||||
(!NLPTR_TBIT(p->qtd.next) && (p->qtd.next != qtd.next)) ||
|
||||
(!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd.altnext)) ||
|
||||
p->qtd.bufptr[0] != qtd.bufptr[0]) {
|
||||
/* guest bug: guest updated active QH or qTD underneath us */
|
||||
ehci_cancel_queue(q);
|
||||
p = NULL;
|
||||
} else {
|
||||
p->qtd = qtd;
|
||||
ehci_qh_do_overlay(q);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(qtd.token & QTD_TOKEN_ACTIVE)) {
|
||||
if (p != NULL) {
|
||||
/* transfer canceled by guest (clear active) */
|
||||
ehci_cancel_queue(q);
|
||||
p = NULL;
|
||||
}
|
||||
ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
|
||||
again = 1;
|
||||
} else if (p != NULL) {
|
||||
switch (p->async) {
|
||||
case EHCI_ASYNC_NONE:
|
||||
/* Previously nacked packet (likely interrupt ep) */
|
||||
ehci_set_state(q->ehci, q->async, EST_EXECUTE);
|
||||
break;
|
||||
case EHCI_ASYNC_INFLIGHT:
|
||||
/* Unfinyshed async handled packet, go horizontal */
|
||||
ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
|
||||
break;
|
||||
case EHCI_ASYNC_FINISHED:
|
||||
/* Should never happen, as this case is caught by fetchqh */
|
||||
ehci_set_state(q->ehci, q->async, EST_EXECUTING);
|
||||
break;
|
||||
}
|
||||
again = 1;
|
||||
} else if (qtd.token & QTD_TOKEN_ACTIVE) {
|
||||
} else {
|
||||
p = ehci_alloc_packet(q);
|
||||
p->qtdaddr = q->qtdaddr;
|
||||
p->qtd = qtd;
|
||||
ehci_set_state(q->ehci, q->async, EST_EXECUTE);
|
||||
again = 1;
|
||||
} else {
|
||||
ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
|
||||
again = 1;
|
||||
}
|
||||
|
||||
return again;
|
||||
@@ -2069,19 +2111,11 @@ out:
|
||||
static int ehci_state_executing(EHCIQueue *q)
|
||||
{
|
||||
EHCIPacket *p = QTAILQ_FIRST(&q->packets);
|
||||
int again = 0;
|
||||
|
||||
assert(p != NULL);
|
||||
assert(p->qtdaddr == q->qtdaddr);
|
||||
|
||||
ehci_execute_complete(q);
|
||||
if (p->usb_status == USB_RET_ASYNC) {
|
||||
goto out;
|
||||
}
|
||||
if (p->usb_status == USB_RET_PROCERR) {
|
||||
again = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// 4.10.3
|
||||
if (!q->async) {
|
||||
@@ -2099,11 +2133,8 @@ static int ehci_state_executing(EHCIQueue *q)
|
||||
ehci_set_state(q->ehci, q->async, EST_WRITEBACK);
|
||||
}
|
||||
|
||||
again = 1;
|
||||
|
||||
out:
|
||||
ehci_flush_qh(q);
|
||||
return again;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -2132,6 +2163,19 @@ static int ehci_state_writeback(EHCIQueue *q)
|
||||
* bit is clear.
|
||||
*/
|
||||
if (q->qh.token & QTD_TOKEN_HALT) {
|
||||
/*
|
||||
* We should not do any further processing on a halted queue!
|
||||
* This is esp. important for bulk endpoints with pipelining enabled
|
||||
* (redirection to a real USB device), where we must cancel all the
|
||||
* transfers after this one so that:
|
||||
* 1) If they've completed already, they are not processed further
|
||||
* causing more stalls, originating from the same failed transfer
|
||||
* 2) If still in flight, they are cancelled before the guest does
|
||||
* a clear stall, otherwise the guest and device can loose sync!
|
||||
*/
|
||||
while ((p = QTAILQ_FIRST(&q->packets)) != NULL) {
|
||||
ehci_free_packet(p);
|
||||
}
|
||||
ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
|
||||
again = 1;
|
||||
} else {
|
||||
@@ -2466,13 +2510,16 @@ static int usb_ehci_post_load(void *opaque, int version_id)
|
||||
|
||||
static const VMStateDescription vmstate_ehci = {
|
||||
.name = "ehci",
|
||||
.version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 1,
|
||||
.post_load = usb_ehci_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_PCI_DEVICE(dev, EHCIState),
|
||||
/* mmio registers */
|
||||
VMSTATE_UINT32(usbcmd, EHCIState),
|
||||
VMSTATE_UINT32(usbsts, EHCIState),
|
||||
VMSTATE_UINT32_V(usbsts_pending, EHCIState, 2),
|
||||
VMSTATE_UINT32_V(usbsts_frindex, EHCIState, 2),
|
||||
VMSTATE_UINT32(usbintr, EHCIState),
|
||||
VMSTATE_UINT32(frindex, EHCIState),
|
||||
VMSTATE_UINT32(ctrldssegment, EHCIState),
|
||||
|
||||
+2
-1
@@ -626,7 +626,8 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
|
||||
/* A wild guess on the FADDR semantics... */
|
||||
dev = usb_find_device(&s->port, ep->faddr[idx]);
|
||||
uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf);
|
||||
usb_packet_setup(&ep->packey[dir].p, pid, uep);
|
||||
usb_packet_setup(&ep->packey[dir].p, pid, uep,
|
||||
(dev->addr << 16) | (uep->nr << 8) | pid);
|
||||
usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len);
|
||||
ep->packey[dir].ep = ep;
|
||||
ep->packey[dir].dir = dir;
|
||||
|
||||
+2
-2
@@ -812,7 +812,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
|
||||
} else {
|
||||
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
|
||||
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
|
||||
usb_packet_setup(&ohci->usb_packet, pid, ep);
|
||||
usb_packet_setup(&ohci->usb_packet, pid, ep, addr);
|
||||
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
|
||||
ret = usb_handle_packet(dev, &ohci->usb_packet);
|
||||
if (ret == USB_RET_ASYNC) {
|
||||
@@ -1011,7 +1011,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
|
||||
}
|
||||
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
|
||||
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
|
||||
usb_packet_setup(&ohci->usb_packet, pid, ep);
|
||||
usb_packet_setup(&ohci->usb_packet, pid, ep, addr);
|
||||
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
|
||||
ret = usb_handle_packet(dev, &ohci->usb_packet);
|
||||
#ifdef DEBUG_PACKET
|
||||
|
||||
+18
-2
@@ -748,6 +748,22 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
|
||||
return TD_RESULT_COMPLETE;
|
||||
|
||||
out:
|
||||
/*
|
||||
* We should not do any further processing on a queue with errors!
|
||||
* This is esp. important for bulk endpoints with pipelining enabled
|
||||
* (redirection to a real USB device), where we must cancel all the
|
||||
* transfers after this one so that:
|
||||
* 1) If they've completed already, they are not processed further
|
||||
* causing more stalls, originating from the same failed transfer
|
||||
* 2) If still in flight, they are cancelled before the guest does
|
||||
* a clear stall, otherwise the guest and device can loose sync!
|
||||
*/
|
||||
while (!QTAILQ_EMPTY(&async->queue->asyncs)) {
|
||||
UHCIAsync *as = QTAILQ_FIRST(&async->queue->asyncs);
|
||||
uhci_async_unlink(as);
|
||||
uhci_async_cancel(as);
|
||||
}
|
||||
|
||||
switch(ret) {
|
||||
case USB_RET_STALL:
|
||||
td->ctrl |= TD_CTRL_STALL;
|
||||
@@ -843,14 +859,14 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td,
|
||||
* for initial isochronous requests
|
||||
*/
|
||||
async->queue->valid = 32;
|
||||
async->isoc = td->ctrl & TD_CTRL_IOS;
|
||||
async->isoc = td->ctrl & TD_CTRL_IOS;
|
||||
|
||||
max_len = ((td->token >> 21) + 1) & 0x7ff;
|
||||
pid = td->token & 0xff;
|
||||
|
||||
dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
|
||||
ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
|
||||
usb_packet_setup(&async->packet, pid, ep);
|
||||
usb_packet_setup(&async->packet, pid, ep, addr);
|
||||
qemu_sglist_add(&async->sgl, td->buffer, max_len);
|
||||
usb_packet_map(&async->packet, &async->sgl);
|
||||
|
||||
|
||||
+1
-1
@@ -1392,7 +1392,7 @@ static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
|
||||
|
||||
dir = xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT;
|
||||
ep = usb_ep_get(dev, dir, xfer->epid >> 1);
|
||||
usb_packet_setup(&xfer->packet, dir, ep);
|
||||
usb_packet_setup(&xfer->packet, dir, ep, xfer->trbs[0].addr);
|
||||
usb_packet_addbuf(&xfer->packet, xfer->data, xfer->data_length);
|
||||
DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n",
|
||||
xfer->packet.pid, dev->addr, ep->nr);
|
||||
|
||||
@@ -1045,6 +1045,7 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
|
||||
|
||||
/* Note request is (bRequestType << 8) | bRequest */
|
||||
trace_usb_host_req_control(s->bus_num, s->addr, p, request, value, index);
|
||||
assert(p->result == 0);
|
||||
|
||||
switch (request) {
|
||||
case DeviceOutRequest | USB_REQ_SET_ADDRESS:
|
||||
|
||||
@@ -533,7 +533,6 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
|
||||
features |= (1 << VIRTIO_BLK_F_BLK_SIZE);
|
||||
features |= (1 << VIRTIO_BLK_F_SCSI);
|
||||
|
||||
features |= (1 << VIRTIO_BLK_F_CONFIG_WCE);
|
||||
if (bdrv_enable_write_cache(s->bs))
|
||||
features |= (1 << VIRTIO_BLK_F_WCE);
|
||||
|
||||
|
||||
+3
-1
@@ -104,9 +104,11 @@ struct VirtIOBlkConf
|
||||
BlockConf conf;
|
||||
char *serial;
|
||||
uint32_t scsi;
|
||||
uint32_t config_wce;
|
||||
};
|
||||
|
||||
#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
|
||||
DEFINE_PROP_BIT("config-wce", _state, _field, VIRTIO_BLK_F_CONFIG_WCE, true)
|
||||
|
||||
#endif
|
||||
@@ -131,6 +131,7 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f)
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
msix_unuse_all_vectors(&proxy->pci_dev);
|
||||
msix_load(&proxy->pci_dev, f);
|
||||
if (msix_present(&proxy->pci_dev)) {
|
||||
qemu_get_be16s(f, &proxy->vdev->config_vector);
|
||||
@@ -246,6 +247,7 @@ void virtio_pci_reset(DeviceState *d)
|
||||
VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
|
||||
virtio_pci_stop_ioeventfd(proxy);
|
||||
virtio_reset(proxy->vdev);
|
||||
msix_unuse_all_vectors(&proxy->pci_dev);
|
||||
proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
|
||||
}
|
||||
|
||||
@@ -886,6 +888,7 @@ static Property virtio_blk_properties[] = {
|
||||
#ifdef __linux__
|
||||
DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
|
||||
#endif
|
||||
DEFINE_PROP_BIT("config-wce", VirtIOPCIProxy, blk.config_wce, 0, true),
|
||||
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
|
||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
|
||||
DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
|
||||
|
||||
@@ -24,11 +24,6 @@
|
||||
#define VIRTIO_SCSI_MAX_TARGET 255
|
||||
#define VIRTIO_SCSI_MAX_LUN 16383
|
||||
|
||||
/* Feature Bits */
|
||||
#define VIRTIO_SCSI_F_INOUT 0
|
||||
#define VIRTIO_SCSI_F_HOTPLUG 1
|
||||
#define VIRTIO_SCSI_F_CHANGE 2
|
||||
|
||||
/* Response codes */
|
||||
#define VIRTIO_SCSI_S_OK 0
|
||||
#define VIRTIO_SCSI_S_OVERRUN 1
|
||||
@@ -561,8 +556,6 @@ static void virtio_scsi_set_config(VirtIODevice *vdev,
|
||||
static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
|
||||
uint32_t requested_features)
|
||||
{
|
||||
requested_features |= (1UL << VIRTIO_SCSI_F_HOTPLUG);
|
||||
requested_features |= (1UL << VIRTIO_SCSI_F_CHANGE);
|
||||
return requested_features;
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -21,6 +21,11 @@
|
||||
/* The ID for virtio_scsi */
|
||||
#define VIRTIO_ID_SCSI 8
|
||||
|
||||
/* Feature Bits */
|
||||
#define VIRTIO_SCSI_F_INOUT 0
|
||||
#define VIRTIO_SCSI_F_HOTPLUG 1
|
||||
#define VIRTIO_SCSI_F_CHANGE 2
|
||||
|
||||
struct VirtIOSCSIConf {
|
||||
uint32_t num_queues;
|
||||
uint32_t max_sectors;
|
||||
@@ -31,6 +36,8 @@ struct VirtIOSCSIConf {
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(_state, _features_field), \
|
||||
DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \
|
||||
DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF), \
|
||||
DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128)
|
||||
DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128), \
|
||||
DEFINE_PROP_BIT("hotplug", _state, _features_field, VIRTIO_SCSI_F_HOTPLUG, true), \
|
||||
DEFINE_PROP_BIT("param_change", _state, _features_field, VIRTIO_SCSI_F_CHANGE, true)
|
||||
|
||||
#endif /* _QEMU_VIRTIO_SCSI_H */
|
||||
@@ -87,9 +87,6 @@ static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
|
||||
{
|
||||
if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
|
||||
PCI_CLASS_NETWORK_ETHERNET) {
|
||||
/* Until qdev_free includes a call to object_unparent, we call it here
|
||||
*/
|
||||
object_unparent(&d->qdev.parent_obj);
|
||||
qdev_free(&d->qdev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ int qemu_set_fd_handler2(int fd,
|
||||
ioh->fd_write = fd_write;
|
||||
ioh->opaque = opaque;
|
||||
ioh->deleted = 0;
|
||||
qemu_notify_event();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __LINUX_KVM_S390_H
|
||||
#define __LINUX_KVM_S390_H
|
||||
/*
|
||||
* asm-s390/kvm.h - KVM s390 specific structures and definitions
|
||||
* KVM s390 specific structures and definitions
|
||||
*
|
||||
* Copyright IBM Corp. 2008
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* asm-s390/kvm_para.h - definition for paravirtual devices on s390
|
||||
* definition for paravirtual devices on s390
|
||||
*
|
||||
* Copyright IBM Corp. 2008
|
||||
*
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
/* Select x86 specific features in <linux/kvm.h> */
|
||||
#define __KVM_HAVE_PIT
|
||||
#define __KVM_HAVE_IOAPIC
|
||||
#define __KVM_HAVE_IRQ_LINE
|
||||
#define __KVM_HAVE_DEVICE_ASSIGNMENT
|
||||
#define __KVM_HAVE_MSI
|
||||
#define __KVM_HAVE_USER_NMI
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define KVM_FEATURE_CLOCKSOURCE2 3
|
||||
#define KVM_FEATURE_ASYNC_PF 4
|
||||
#define KVM_FEATURE_STEAL_TIME 5
|
||||
#define KVM_FEATURE_PV_EOI 6
|
||||
|
||||
/* The last 8 bits are used to indicate how to interpret the flags field
|
||||
* in pvclock structure. If no bits are set, all flags are ignored.
|
||||
@@ -37,6 +38,7 @@
|
||||
#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
|
||||
#define MSR_KVM_ASYNC_PF_EN 0x4b564d02
|
||||
#define MSR_KVM_STEAL_TIME 0x4b564d03
|
||||
#define MSR_KVM_PV_EOI_EN 0x4b564d04
|
||||
|
||||
struct kvm_steal_time {
|
||||
__u64 steal;
|
||||
@@ -89,5 +91,10 @@ struct kvm_vcpu_pv_apf_data {
|
||||
__u32 enabled;
|
||||
};
|
||||
|
||||
#define KVM_PV_EOI_BIT 0
|
||||
#define KVM_PV_EOI_MASK (0x1 << KVM_PV_EOI_BIT)
|
||||
#define KVM_PV_EOI_ENABLED KVM_PV_EOI_MASK
|
||||
#define KVM_PV_EOI_DISABLED 0x0
|
||||
|
||||
|
||||
#endif /* _ASM_X86_KVM_PARA_H */
|
||||
@@ -617,6 +617,7 @@ struct kvm_ppc_smmu_info {
|
||||
#define KVM_CAP_SIGNAL_MSI 77
|
||||
#define KVM_CAP_PPC_GET_SMMU_INFO 78
|
||||
#define KVM_CAP_S390_COW 79
|
||||
#define KVM_CAP_PPC_ALLOC_HTAB 80
|
||||
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
|
||||
@@ -828,6 +829,8 @@ struct kvm_s390_ucas_mapping {
|
||||
#define KVM_SIGNAL_MSI _IOW(KVMIO, 0xa5, struct kvm_msi)
|
||||
/* Available with KVM_CAP_PPC_GET_SMMU_INFO */
|
||||
#define KVM_PPC_GET_SMMU_INFO _IOR(KVMIO, 0xa6, struct kvm_ppc_smmu_info)
|
||||
/* Available with KVM_CAP_PPC_ALLOC_HTAB */
|
||||
#define KVM_PPC_ALLOCATE_HTAB _IOWR(KVMIO, 0xa7, __u32)
|
||||
|
||||
/*
|
||||
* ioctls for vcpu fds
|
||||
|
||||
+7
-4
@@ -3222,7 +3222,7 @@ struct qemu_argument {
|
||||
const char *help;
|
||||
};
|
||||
|
||||
struct qemu_argument arg_table[] = {
|
||||
static const struct qemu_argument arg_table[] = {
|
||||
{"h", "", false, handle_arg_help,
|
||||
"", "print this help"},
|
||||
{"g", "QEMU_GDB", true, handle_arg_gdb,
|
||||
@@ -3264,7 +3264,7 @@ struct qemu_argument arg_table[] = {
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
struct qemu_argument *arginfo;
|
||||
const struct qemu_argument *arginfo;
|
||||
int maxarglen;
|
||||
int maxenvlen;
|
||||
|
||||
@@ -3330,7 +3330,7 @@ static int parse_args(int argc, char **argv)
|
||||
{
|
||||
const char *r;
|
||||
int optind;
|
||||
struct qemu_argument *arginfo;
|
||||
const struct qemu_argument *arginfo;
|
||||
|
||||
for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
|
||||
if (arginfo->env == NULL) {
|
||||
@@ -3519,7 +3519,10 @@ int main(int argc, char **argv, char **envp)
|
||||
guest_base = init_guest_space(guest_base, reserved_va, 0,
|
||||
have_guest_base);
|
||||
if (guest_base == (unsigned long)-1) {
|
||||
fprintf(stderr, "Unable to reserve guest address space\n");
|
||||
fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address "
|
||||
"space for use as guest address space (check your virtual "
|
||||
"memory ulimit setting or reserve less using -R option)\n",
|
||||
reserved_va);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -2848,7 +2848,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
|
||||
if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
|
||||
return -TARGET_EFAULT;
|
||||
|
||||
host_mb = malloc(msgsz+sizeof(long));
|
||||
host_mb = g_malloc(msgsz+sizeof(long));
|
||||
ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapal(msgtyp), msgflg));
|
||||
|
||||
if (ret > 0) {
|
||||
@@ -2863,11 +2863,11 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
|
||||
}
|
||||
|
||||
target_mb->mtype = tswapal(host_mb->mtype);
|
||||
free(host_mb);
|
||||
|
||||
end:
|
||||
if (target_mb)
|
||||
unlock_user_struct(target_mb, msgp, 1);
|
||||
g_free(host_mb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -7025,15 +7025,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
tde = target_dirp;
|
||||
while (len > 0) {
|
||||
reclen = de->d_reclen;
|
||||
treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
|
||||
tnamelen = reclen - offsetof(struct linux_dirent, d_name);
|
||||
assert(tnamelen >= 0);
|
||||
treclen = tnamelen + offsetof(struct target_dirent, d_name);
|
||||
assert(count1 + treclen <= count);
|
||||
tde->d_reclen = tswap16(treclen);
|
||||
tde->d_ino = tswapal(de->d_ino);
|
||||
tde->d_off = tswapal(de->d_off);
|
||||
tnamelen = treclen - (2 * sizeof(abi_long) + 2);
|
||||
if (tnamelen > 256)
|
||||
tnamelen = 256;
|
||||
/* XXX: may not be correct */
|
||||
pstrcpy(tde->d_name, tnamelen, de->d_name);
|
||||
memcpy(tde->d_name, de->d_name, tnamelen);
|
||||
de = (struct linux_dirent *)((char *)de + reclen);
|
||||
len -= reclen;
|
||||
tde = (struct target_dirent *)((char *)tde + treclen);
|
||||
|
||||
@@ -255,10 +255,10 @@ struct kernel_statfs {
|
||||
};
|
||||
|
||||
struct target_dirent {
|
||||
abi_long d_ino;
|
||||
abi_long d_off;
|
||||
unsigned short d_reclen;
|
||||
char d_name[256]; /* We must not include limits.h! */
|
||||
abi_long d_ino;
|
||||
abi_long d_off;
|
||||
unsigned short d_reclen;
|
||||
char d_name[];
|
||||
};
|
||||
|
||||
struct target_dirent64 {
|
||||
|
||||
@@ -426,7 +426,7 @@ static void memory_region_iorange_write(IORange *iorange,
|
||||
if (mrp) {
|
||||
mrp->write(mr->opaque, offset, data);
|
||||
} else if (width == 2) {
|
||||
mrp = find_portio(mr, offset - mrio->offset, 1, false);
|
||||
mrp = find_portio(mr, offset - mrio->offset, 1, true);
|
||||
assert(mrp);
|
||||
mrp->write(mr->opaque, offset, data & 0xff);
|
||||
mrp->write(mr->opaque, offset + 1, data >> 8);
|
||||
|
||||
+4
-3
@@ -166,14 +166,15 @@ MigrationInfo *qmp_query_migrate(Error **errp)
|
||||
case MIG_STATE_ACTIVE:
|
||||
info->has_status = true;
|
||||
info->status = g_strdup("active");
|
||||
info->has_total_time = true;
|
||||
info->total_time = qemu_get_clock_ms(rt_clock)
|
||||
- s->total_time;
|
||||
|
||||
info->has_ram = true;
|
||||
info->ram = g_malloc0(sizeof(*info->ram));
|
||||
info->ram->transferred = ram_bytes_transferred();
|
||||
info->ram->remaining = ram_bytes_remaining();
|
||||
info->ram->total = ram_bytes_total();
|
||||
info->ram->total_time = qemu_get_clock_ms(rt_clock)
|
||||
- s->total_time;
|
||||
info->ram->duplicate = dup_mig_pages_transferred();
|
||||
info->ram->normal = norm_mig_pages_transferred();
|
||||
info->ram->normal_bytes = norm_mig_bytes_transferred();
|
||||
@@ -193,13 +194,13 @@ MigrationInfo *qmp_query_migrate(Error **errp)
|
||||
|
||||
info->has_status = true;
|
||||
info->status = g_strdup("completed");
|
||||
info->total_time = s->total_time;
|
||||
|
||||
info->has_ram = true;
|
||||
info->ram = g_malloc0(sizeof(*info->ram));
|
||||
info->ram->transferred = ram_bytes_transferred();
|
||||
info->ram->remaining = 0;
|
||||
info->ram->total = ram_bytes_total();
|
||||
info->ram->total_time = s->total_time;
|
||||
info->ram->duplicate = dup_mig_pages_transferred();
|
||||
info->ram->normal = norm_mig_pages_transferred();
|
||||
info->ram->normal_bytes = norm_mig_bytes_transferred();
|
||||
|
||||
@@ -2570,11 +2570,11 @@ FdsetInfoList *qmp_query_fdsets(Error **errp)
|
||||
|
||||
int monitor_fdset_get_fd(int64_t fdset_id, int flags)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
MonFdset *mon_fdset;
|
||||
MonFdsetFd *mon_fdset_fd;
|
||||
int mon_fd_flags;
|
||||
|
||||
#ifndef _WIN32
|
||||
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
|
||||
if (mon_fdset->id != fdset_id) {
|
||||
continue;
|
||||
@@ -4832,7 +4832,6 @@ static void monitor_control_event(void *opaque, int event)
|
||||
switch (event) {
|
||||
case CHR_EVENT_OPENED:
|
||||
mon->mc->command_mode = 0;
|
||||
json_message_parser_init(&mon->mc->parser, handle_qmp_command);
|
||||
data = get_qmp_greeting();
|
||||
monitor_json_emitter(mon, data);
|
||||
qobject_decref(data);
|
||||
@@ -4840,6 +4839,7 @@ static void monitor_control_event(void *opaque, int event)
|
||||
break;
|
||||
case CHR_EVENT_CLOSED:
|
||||
json_message_parser_destroy(&mon->mc->parser);
|
||||
json_message_parser_init(&mon->mc->parser, handle_qmp_command);
|
||||
mon_refcount--;
|
||||
monitor_fdsets_cleanup();
|
||||
break;
|
||||
@@ -4946,6 +4946,8 @@ void monitor_init(CharDriverState *chr, int flags)
|
||||
qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
|
||||
monitor_control_event, mon);
|
||||
qemu_chr_fe_set_echo(chr, true);
|
||||
|
||||
json_message_parser_init(&mon->mc->parser, handle_qmp_command);
|
||||
} else {
|
||||
qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
|
||||
monitor_event, mon);
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
1275-1994 (referred to as Open Firmware) compliant firmware.
|
||||
The included images for PowerPC (for 32 and 64 bit PPC CPUs),
|
||||
Sparc32 and Sparc64 are built from OpenBIOS SVN revision
|
||||
1060.
|
||||
1063.
|
||||
|
||||
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
|
||||
implementation for certain IBM POWER hardware. The sources are at
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+46
-7
@@ -290,10 +290,6 @@
|
||||
#
|
||||
# @total: total amount of bytes involved in the migration process
|
||||
#
|
||||
# @total-time: total amount of ms since migration started. If
|
||||
# migration has ended, it returns the total migration
|
||||
# time. (since 1.2)
|
||||
#
|
||||
# @duplicate: number of duplicate pages (since 1.2)
|
||||
#
|
||||
# @normal : number of normal pages (since 1.2)
|
||||
@@ -304,8 +300,7 @@
|
||||
##
|
||||
{ 'type': 'MigrationStats',
|
||||
'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
|
||||
'total-time': 'int', 'duplicate': 'int', 'normal': 'int',
|
||||
'normal-bytes': 'int' } }
|
||||
'duplicate': 'int', 'normal': 'int', 'normal-bytes': 'int' } }
|
||||
|
||||
##
|
||||
# @XBZRLECacheStats
|
||||
@@ -350,12 +345,17 @@
|
||||
# migration statistics, only returned if XBZRLE feature is on and
|
||||
# status is 'active' or 'completed' (since 1.2)
|
||||
#
|
||||
# @total-time: #optional total amount of milliseconds since migration started.
|
||||
# If migration has ended, it returns the total migration
|
||||
# time. (since 1.2)
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
{ 'type': 'MigrationInfo',
|
||||
'data': {'*status': 'str', '*ram': 'MigrationStats',
|
||||
'*disk': 'MigrationStats',
|
||||
'*xbzrle-cache': 'XBZRLECacheStats'} }
|
||||
'*xbzrle-cache': 'XBZRLECacheStats',
|
||||
'*total-time': 'int'} }
|
||||
|
||||
##
|
||||
# @query-migrate
|
||||
@@ -2454,3 +2454,42 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-fdsets', 'returns': ['FdsetInfo'] }
|
||||
|
||||
##
|
||||
# @TargetType
|
||||
#
|
||||
# Target CPU emulation type
|
||||
#
|
||||
# These parameters correspond to the softmmu binary CPU name that is currently
|
||||
# running.
|
||||
#
|
||||
# Since: 1.2.0
|
||||
##
|
||||
{ 'enum': 'TargetType',
|
||||
'data': [ 'alpha', 'arm', 'cris', 'i386', 'lm32', 'm68k', 'microblazeel',
|
||||
'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'or32',
|
||||
'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4', 'sparc64',
|
||||
'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa' ] }
|
||||
|
||||
##
|
||||
# @TargetInfo:
|
||||
#
|
||||
# Information describing the QEMU target.
|
||||
#
|
||||
# @arch: the target architecture (eg "x86_64", "i386", etc)
|
||||
#
|
||||
# Since: 1.2.0
|
||||
##
|
||||
{ 'type': 'TargetInfo',
|
||||
'data': { 'arch': 'TargetType' } }
|
||||
|
||||
##
|
||||
# @query-target:
|
||||
#
|
||||
# Return information about the target for this QEMU
|
||||
#
|
||||
# Returns: TargetInfo
|
||||
#
|
||||
# Since: 1.2.0
|
||||
##
|
||||
{ 'command': 'query-target', 'returns': 'TargetInfo' }
|
||||
+1
-1
@@ -416,7 +416,7 @@ opts_visitor_cleanup(OptsVisitor *ov)
|
||||
g_hash_table_destroy(ov->unprocessed_opts);
|
||||
}
|
||||
g_free(ov->fake_id_opt);
|
||||
memset(ov, '\0', sizeof *ov);
|
||||
g_free(ov);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -247,6 +247,9 @@ static bool ga_open_pidfile(const char *pidfile)
|
||||
pidfd = open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
|
||||
if (pidfd == -1 || lockf(pidfd, F_TLOCK, 0)) {
|
||||
g_critical("Cannot lock pid file, %s", strerror(errno));
|
||||
if (pidfd != -1) {
|
||||
close(pidfd);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -435,7 +438,9 @@ static void become_daemon(const char *pidfile)
|
||||
return;
|
||||
|
||||
fail:
|
||||
unlink(pidfile);
|
||||
if (pidfile) {
|
||||
unlink(pidfile);
|
||||
}
|
||||
g_critical("failed to daemonize");
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
|
||||
@@ -4,6 +4,16 @@ usage: qemu-img command [command options]
|
||||
@c man end
|
||||
@end example
|
||||
|
||||
@c man begin DESCRIPTION
|
||||
qemu-img allows you to create, convert and modify images offline. It can handle
|
||||
all image formats supported by QEMU.
|
||||
|
||||
@b{Warning:} Never use qemu-img to modify images in use by a running virtual
|
||||
machine or any other process; this may destroy the image. Also, be aware that
|
||||
querying an image that is being modified by another process may encounter
|
||||
inconsistent state.
|
||||
@c man end
|
||||
|
||||
@c man begin OPTIONS
|
||||
|
||||
The following commands are supported:
|
||||
|
||||
@@ -759,11 +759,8 @@ int init_timer_alarm(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* first event is at time 0 */
|
||||
atexit(quit_timers);
|
||||
t->pending = true;
|
||||
alarm_timer = t;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
||||
+8
-3
@@ -2239,14 +2239,14 @@ The main json-object contains the following:
|
||||
|
||||
- "status": migration status (json-string)
|
||||
- Possible values: "active", "completed", "failed", "cancelled"
|
||||
- "total-time": total amount of ms since migration started. If
|
||||
migration has ended, it returns the total migration
|
||||
time (json-int)
|
||||
- "ram": only present if "status" is "active", it is a json-object with the
|
||||
following RAM information (in bytes):
|
||||
- "transferred": amount transferred (json-int)
|
||||
- "remaining": amount remaining (json-int)
|
||||
- "total": total (json-int)
|
||||
- "total-time": total amount of ms since migration started. If
|
||||
migration has ended, it returns the total migration time
|
||||
(json-int)
|
||||
- "duplicate": number of duplicated pages (json-int)
|
||||
- "normal" : number of normal pages transferred (json-int)
|
||||
- "normal-bytes" : number of normal bytes transferred (json-int)
|
||||
@@ -2509,3 +2509,8 @@ EQMP
|
||||
.mhandler.cmd_new = qmp_marshal_input_query_cpu_definitions,
|
||||
},
|
||||
|
||||
{
|
||||
.name = "query-target",
|
||||
.args_type = "",
|
||||
.mhandler.cmd_new = qmp_marshal_input_query_target,
|
||||
},
|
||||
+2
-3
@@ -373,8 +373,6 @@ static void object_deinit(Object *obj, TypeImpl *type)
|
||||
if (type_has_parent(type)) {
|
||||
object_deinit(obj, type_get_parent(type));
|
||||
}
|
||||
|
||||
object_unparent(obj);
|
||||
}
|
||||
|
||||
void object_finalize(void *data)
|
||||
@@ -411,8 +409,9 @@ Object *object_new(const char *typename)
|
||||
|
||||
void object_delete(Object *obj)
|
||||
{
|
||||
object_unparent(obj);
|
||||
g_assert(obj->ref == 1);
|
||||
object_unref(obj);
|
||||
g_assert(obj->ref == 0);
|
||||
g_free(obj);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
Submodule roms/openbios updated: d1d2787f87...f095c85813.
+4
-1
@@ -40,7 +40,7 @@ static void *softmmu_lock_user(CPUArchState *env, uint32_t addr, uint32_t len,
|
||||
uint8_t *p;
|
||||
/* TODO: Make this something that isn't fixed size. */
|
||||
p = malloc(len);
|
||||
if (copy)
|
||||
if (p && copy)
|
||||
cpu_memory_rw_debug(env, addr, p, len, 0);
|
||||
return p;
|
||||
}
|
||||
@@ -52,6 +52,9 @@ static char *softmmu_lock_user_string(CPUArchState *env, uint32_t addr)
|
||||
uint8_t c;
|
||||
/* TODO: Make this something that isn't fixed size. */
|
||||
s = p = malloc(1024);
|
||||
if (!s) {
|
||||
return NULL;
|
||||
}
|
||||
do {
|
||||
cpu_memory_rw_debug(env, addr, &c, 1, 0);
|
||||
addr++;
|
||||
|
||||
@@ -194,18 +194,19 @@ uint32_t do_arm_semihosting(CPUARMState *env)
|
||||
if (!(s = lock_user_string(ARG(0))))
|
||||
/* FIXME - should this error code be -TARGET_EFAULT ? */
|
||||
return (uint32_t)-1;
|
||||
if (ARG(1) >= 12)
|
||||
if (ARG(1) >= 12) {
|
||||
unlock_user(s, ARG(0), 0);
|
||||
return (uint32_t)-1;
|
||||
}
|
||||
if (strcmp(s, ":tt") == 0) {
|
||||
if (ARG(1) < 4)
|
||||
return STDIN_FILENO;
|
||||
else
|
||||
return STDOUT_FILENO;
|
||||
int result_fileno = ARG(1) < 4 ? STDIN_FILENO : STDOUT_FILENO;
|
||||
unlock_user(s, ARG(0), 0);
|
||||
return result_fileno;
|
||||
}
|
||||
if (use_gdb_syscalls()) {
|
||||
gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0),
|
||||
(int)ARG(2)+1, gdb_open_modeflags[ARG(1)]);
|
||||
return env->regs[0];
|
||||
ret = env->regs[0];
|
||||
} else {
|
||||
ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
|
||||
}
|
||||
|
||||
+14
-1
@@ -33,6 +33,9 @@
|
||||
#include "hyperv.h"
|
||||
|
||||
#include "hw/hw.h"
|
||||
#if defined(CONFIG_KVM)
|
||||
#include <linux/kvm_para.h>
|
||||
#endif
|
||||
|
||||
/* feature flags taken from "Intel Processor Identification and the CPUID
|
||||
* Instruction" and AMD's "CPUID Specification". In cases of disagreement
|
||||
@@ -887,7 +890,17 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
|
||||
memcpy(x86_cpu_def, def, sizeof(*def));
|
||||
}
|
||||
|
||||
plus_kvm_features = ~0; /* not supported bits will be filtered out later */
|
||||
#if defined(CONFIG_KVM)
|
||||
plus_kvm_features = (1 << KVM_FEATURE_CLOCKSOURCE) |
|
||||
(1 << KVM_FEATURE_NOP_IO_DELAY) |
|
||||
(1 << KVM_FEATURE_MMU_OP) |
|
||||
(1 << KVM_FEATURE_CLOCKSOURCE2) |
|
||||
(1 << KVM_FEATURE_ASYNC_PF) |
|
||||
(1 << KVM_FEATURE_STEAL_TIME) |
|
||||
(1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
|
||||
#else
|
||||
plus_kvm_features = 0;
|
||||
#endif
|
||||
|
||||
add_flagname_to_bitmaps("hypervisor", &plus_features,
|
||||
&plus_ext_features, &plus_ext2_features, &plus_ext3_features,
|
||||
|
||||
@@ -699,6 +699,7 @@ typedef struct CPUX86State {
|
||||
uint64_t system_time_msr;
|
||||
uint64_t wall_clock_msr;
|
||||
uint64_t async_pf_en_msr;
|
||||
uint64_t pv_eoi_en_msr;
|
||||
|
||||
uint64_t tsc;
|
||||
uint64_t tsc_deadline;
|
||||
|
||||
@@ -63,6 +63,7 @@ static bool has_msr_star;
|
||||
static bool has_msr_hsave_pa;
|
||||
static bool has_msr_tsc_deadline;
|
||||
static bool has_msr_async_pf_en;
|
||||
static bool has_msr_pv_eoi_en;
|
||||
static bool has_msr_misc_enable;
|
||||
static int lm_capable_kernel;
|
||||
|
||||
@@ -455,6 +456,8 @@ int kvm_arch_init_vcpu(CPUX86State *env)
|
||||
|
||||
has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);
|
||||
|
||||
has_msr_pv_eoi_en = c->eax & (1 << KVM_FEATURE_PV_EOI);
|
||||
|
||||
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
|
||||
|
||||
for (i = 0; i <= limit; i++) {
|
||||
@@ -1017,6 +1020,10 @@ static int kvm_put_msrs(CPUX86State *env, int level)
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN,
|
||||
env->async_pf_en_msr);
|
||||
}
|
||||
if (has_msr_pv_eoi_en) {
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_KVM_PV_EOI_EN,
|
||||
env->pv_eoi_en_msr);
|
||||
}
|
||||
if (hyperv_hypercall_available()) {
|
||||
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0);
|
||||
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0);
|
||||
@@ -1259,6 +1266,9 @@ static int kvm_get_msrs(CPUX86State *env)
|
||||
if (has_msr_async_pf_en) {
|
||||
msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
|
||||
}
|
||||
if (has_msr_pv_eoi_en) {
|
||||
msrs[n++].index = MSR_KVM_PV_EOI_EN;
|
||||
}
|
||||
|
||||
if (env->mcg_cap) {
|
||||
msrs[n++].index = MSR_MCG_STATUS;
|
||||
@@ -1338,6 +1348,9 @@ static int kvm_get_msrs(CPUX86State *env)
|
||||
case MSR_KVM_ASYNC_PF_EN:
|
||||
env->async_pf_en_msr = msrs[i].data;
|
||||
break;
|
||||
case MSR_KVM_PV_EOI_EN:
|
||||
env->pv_eoi_en_msr = msrs[i].data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -279,6 +279,13 @@ static bool async_pf_msr_needed(void *opaque)
|
||||
return cpu->async_pf_en_msr != 0;
|
||||
}
|
||||
|
||||
static bool pv_eoi_msr_needed(void *opaque)
|
||||
{
|
||||
CPUX86State *cpu = opaque;
|
||||
|
||||
return cpu->pv_eoi_en_msr != 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_async_pf_msr = {
|
||||
.name = "cpu/async_pf_msr",
|
||||
.version_id = 1,
|
||||
@@ -290,6 +297,17 @@ static const VMStateDescription vmstate_async_pf_msr = {
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_pv_eoi_msr = {
|
||||
.name = "cpu/async_pv_eoi_msr",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_UINT64(pv_eoi_en_msr, CPUX86State),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static bool fpop_ip_dp_needed(void *opaque)
|
||||
{
|
||||
CPUX86State *env = opaque;
|
||||
@@ -453,6 +471,9 @@ static const VMStateDescription vmstate_cpu = {
|
||||
{
|
||||
.vmsd = &vmstate_async_pf_msr,
|
||||
.needed = async_pf_msr_needed,
|
||||
} , {
|
||||
.vmsd = &vmstate_pv_eoi_msr,
|
||||
.needed = pv_eoi_msr_needed,
|
||||
} , {
|
||||
.vmsd = &vmstate_fpop_ip_dp,
|
||||
.needed = fpop_ip_dp_needed,
|
||||
|
||||
+10
-4
@@ -7551,8 +7551,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
|
||||
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
|
||||
} else {
|
||||
modrm = cpu_ldub_code(cpu_single_env, s->pc++);
|
||||
if ((modrm & 0xc0) != 0xc0)
|
||||
goto illegal_op;
|
||||
/* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
|
||||
* AMD documentation (24594.pdf) and testing of
|
||||
* intel 386 and 486 processors all show that the mod bits
|
||||
* are assumed to be 1's, regardless of actual values.
|
||||
*/
|
||||
rm = (modrm & 7) | REX_B(s);
|
||||
reg = ((modrm >> 3) & 7) | rex_r;
|
||||
if (CODE64(s))
|
||||
@@ -7594,8 +7597,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
|
||||
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
|
||||
} else {
|
||||
modrm = cpu_ldub_code(cpu_single_env, s->pc++);
|
||||
if ((modrm & 0xc0) != 0xc0)
|
||||
goto illegal_op;
|
||||
/* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
|
||||
* AMD documentation (24594.pdf) and testing of
|
||||
* intel 386 and 486 processors all show that the mod bits
|
||||
* are assumed to be 1's, regardless of actual values.
|
||||
*/
|
||||
rm = (modrm & 7) | REX_B(s);
|
||||
reg = ((modrm >> 3) & 7) | rex_r;
|
||||
if (CODE64(s))
|
||||
|
||||
+29
-46
@@ -192,115 +192,98 @@ static inline uint64_t get_HILO (void)
|
||||
return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0];
|
||||
}
|
||||
|
||||
static inline void set_HIT0_LO (target_ulong arg1, uint64_t HILO)
|
||||
static inline target_ulong set_HIT0_LO(uint64_t HILO)
|
||||
{
|
||||
target_ulong tmp;
|
||||
env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
|
||||
arg1 = env->active_tc.HI[0] = (int32_t)(HILO >> 32);
|
||||
tmp = env->active_tc.HI[0] = (int32_t)(HILO >> 32);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static inline void set_HI_LOT0 (target_ulong arg1, uint64_t HILO)
|
||||
static inline target_ulong set_HI_LOT0(uint64_t HILO)
|
||||
{
|
||||
arg1 = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
|
||||
target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
|
||||
env->active_tc.HI[0] = (int32_t)(HILO >> 32);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* Multiplication variants of the vr54xx. */
|
||||
target_ulong helper_muls (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HI_LOT0(arg1, 0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
|
||||
|
||||
return arg1;
|
||||
return set_HI_LOT0(0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
|
||||
}
|
||||
|
||||
target_ulong helper_mulsu (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HI_LOT0(arg1, 0 - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
|
||||
|
||||
return arg1;
|
||||
return set_HI_LOT0(0 - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
|
||||
}
|
||||
|
||||
target_ulong helper_macc (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HI_LOT0(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
|
||||
|
||||
return arg1;
|
||||
return set_HI_LOT0((int64_t)get_HILO() + (int64_t)(int32_t)arg1 *
|
||||
(int64_t)(int32_t)arg2);
|
||||
}
|
||||
|
||||
target_ulong helper_macchi (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HIT0_LO(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
|
||||
|
||||
return arg1;
|
||||
return set_HIT0_LO((int64_t)get_HILO() + (int64_t)(int32_t)arg1 *
|
||||
(int64_t)(int32_t)arg2);
|
||||
}
|
||||
|
||||
target_ulong helper_maccu (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HI_LOT0(arg1, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
|
||||
|
||||
return arg1;
|
||||
return set_HI_LOT0((uint64_t)get_HILO() + (uint64_t)(uint32_t)arg1 *
|
||||
(uint64_t)(uint32_t)arg2);
|
||||
}
|
||||
|
||||
target_ulong helper_macchiu (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HIT0_LO(arg1, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
|
||||
|
||||
return arg1;
|
||||
return set_HIT0_LO((uint64_t)get_HILO() + (uint64_t)(uint32_t)arg1 *
|
||||
(uint64_t)(uint32_t)arg2);
|
||||
}
|
||||
|
||||
target_ulong helper_msac (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HI_LOT0(arg1, ((int64_t)get_HILO()) - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
|
||||
|
||||
return arg1;
|
||||
return set_HI_LOT0((int64_t)get_HILO() - (int64_t)(int32_t)arg1 *
|
||||
(int64_t)(int32_t)arg2);
|
||||
}
|
||||
|
||||
target_ulong helper_msachi (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HIT0_LO(arg1, ((int64_t)get_HILO()) - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
|
||||
|
||||
return arg1;
|
||||
return set_HIT0_LO((int64_t)get_HILO() - (int64_t)(int32_t)arg1 *
|
||||
(int64_t)(int32_t)arg2);
|
||||
}
|
||||
|
||||
target_ulong helper_msacu (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HI_LOT0(arg1, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
|
||||
|
||||
return arg1;
|
||||
return set_HI_LOT0((uint64_t)get_HILO() - (uint64_t)(uint32_t)arg1 *
|
||||
(uint64_t)(uint32_t)arg2);
|
||||
}
|
||||
|
||||
target_ulong helper_msachiu (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HIT0_LO(arg1, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
|
||||
|
||||
return arg1;
|
||||
return set_HIT0_LO((uint64_t)get_HILO() - (uint64_t)(uint32_t)arg1 *
|
||||
(uint64_t)(uint32_t)arg2);
|
||||
}
|
||||
|
||||
target_ulong helper_mulhi (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HIT0_LO(arg1, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
|
||||
|
||||
return arg1;
|
||||
return set_HIT0_LO((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
|
||||
}
|
||||
|
||||
target_ulong helper_mulhiu (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HIT0_LO(arg1, (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
|
||||
|
||||
return arg1;
|
||||
return set_HIT0_LO((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
|
||||
}
|
||||
|
||||
target_ulong helper_mulshi (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HIT0_LO(arg1, 0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
|
||||
|
||||
return arg1;
|
||||
return set_HIT0_LO(0 - (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
|
||||
}
|
||||
|
||||
target_ulong helper_mulshiu (target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
set_HIT0_LO(arg1, 0 - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
|
||||
|
||||
return arg1;
|
||||
return set_HIT0_LO(0 - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
|
||||
}
|
||||
|
||||
#ifdef TARGET_MIPS64
|
||||
|
||||
+29
-8
@@ -5933,6 +5933,7 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
|
||||
{
|
||||
const char *opn = "ldst";
|
||||
|
||||
check_cp0_enabled(ctx);
|
||||
switch (opc) {
|
||||
case OPC_MFC0:
|
||||
if (rt == 0) {
|
||||
@@ -6805,7 +6806,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
TCGv_i32 fp1 = tcg_temp_new_i32();
|
||||
|
||||
gen_load_fpr32(fp0, fs);
|
||||
gen_load_fpr32(fp1, fd);
|
||||
gen_load_fpr32(fp1, ft);
|
||||
gen_helper_float_recip2_s(fp0, fp0, fp1);
|
||||
tcg_temp_free_i32(fp1);
|
||||
gen_store_fpr32(fp0, fd);
|
||||
@@ -6900,7 +6901,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
|
||||
gen_load_fpr32(fp32_0, fs);
|
||||
gen_load_fpr32(fp32_1, ft);
|
||||
tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
|
||||
tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
|
||||
tcg_temp_free_i32(fp32_1);
|
||||
tcg_temp_free_i32(fp32_0);
|
||||
gen_store_fpr64(ctx, fp64, fd);
|
||||
@@ -7543,7 +7544,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
TCGv_i64 fp1 = tcg_temp_new_i64();
|
||||
|
||||
gen_load_fpr64(ctx, fp0, fs);
|
||||
gen_load_fpr64(ctx, fp1, fd);
|
||||
gen_load_fpr64(ctx, fp1, ft);
|
||||
gen_helper_float_recip2_ps(fp0, fp0, fp1);
|
||||
tcg_temp_free_i64(fp1);
|
||||
gen_store_fpr64(ctx, fp0, fd);
|
||||
@@ -7742,8 +7743,7 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
|
||||
} else if (index == 0) {
|
||||
gen_load_gpr(t0, base);
|
||||
} else {
|
||||
gen_load_gpr(t0, index);
|
||||
gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
|
||||
gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
|
||||
}
|
||||
/* Don't do NOP if destination is zero: we must perform the actual
|
||||
memory access. */
|
||||
@@ -8112,7 +8112,11 @@ gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
|
||||
{
|
||||
TCGv t0;
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* The Linux kernel will emulate rdhwr if it's not supported natively.
|
||||
Therefore only check the ISA in system mode. */
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
#endif
|
||||
t0 = tcg_temp_new();
|
||||
|
||||
switch (rd) {
|
||||
@@ -10027,7 +10031,7 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
|
||||
const char *opn = "ldst_pair";
|
||||
TCGv t0, t1;
|
||||
|
||||
if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
|
||||
if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
return;
|
||||
}
|
||||
@@ -10039,6 +10043,10 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
|
||||
|
||||
switch (opc) {
|
||||
case LWP:
|
||||
if (rd == base) {
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
return;
|
||||
}
|
||||
save_cpu_state(ctx, 0);
|
||||
op_ld_lw(t1, t0, ctx);
|
||||
gen_store_gpr(t1, rd);
|
||||
@@ -10060,6 +10068,10 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
|
||||
break;
|
||||
#ifdef TARGET_MIPS64
|
||||
case LDP:
|
||||
if (rd == base) {
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
return;
|
||||
}
|
||||
save_cpu_state(ctx, 0);
|
||||
op_ld_ld(t1, t0, ctx);
|
||||
gen_store_gpr(t1, rd);
|
||||
@@ -10118,6 +10130,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
case MFC0:
|
||||
case MFC0 + 32:
|
||||
check_cp0_enabled(ctx);
|
||||
if (rt == 0) {
|
||||
/* Treat as NOP. */
|
||||
break;
|
||||
@@ -10126,6 +10139,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
|
||||
break;
|
||||
case MTC0:
|
||||
case MTC0 + 32:
|
||||
check_cp0_enabled(ctx);
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
|
||||
@@ -10222,10 +10236,12 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
|
||||
case 0x05:
|
||||
switch (minor) {
|
||||
case RDPGPR:
|
||||
check_cp0_enabled(ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_load_srsgpr(rt, rs);
|
||||
break;
|
||||
case WRPGPR:
|
||||
check_cp0_enabled(ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_store_srsgpr(rt, rs);
|
||||
break;
|
||||
@@ -10266,6 +10282,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
|
||||
case 0x1d:
|
||||
switch (minor) {
|
||||
case DI:
|
||||
check_cp0_enabled(ctx);
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
|
||||
@@ -10278,6 +10295,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
|
||||
}
|
||||
break;
|
||||
case EI:
|
||||
check_cp0_enabled(ctx);
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
|
||||
@@ -10758,6 +10776,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
|
||||
minor = (ctx->opcode >> 12) & 0xf;
|
||||
switch (minor) {
|
||||
case CACHE:
|
||||
check_cp0_enabled(ctx);
|
||||
/* Treat as no-op. */
|
||||
break;
|
||||
case LWC2:
|
||||
@@ -12208,6 +12227,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
|
||||
gen_st_cond(ctx, op, rt, rs, imm);
|
||||
break;
|
||||
case OPC_CACHE:
|
||||
check_cp0_enabled(ctx);
|
||||
check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
|
||||
/* Treat as NOP. */
|
||||
break;
|
||||
@@ -12768,8 +12788,9 @@ void cpu_state_reset(CPUMIPSState *env)
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
env->hflags = MIPS_HFLAG_UM;
|
||||
/* Enable access to the SYNCI_Step register. */
|
||||
env->CP0_HWREna |= (1 << 1);
|
||||
/* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
|
||||
hardware registers. */
|
||||
env->CP0_HWREna |= 0x0000000F;
|
||||
if (env->CP0_Config1 & (1 << CP0C1_FP)) {
|
||||
env->hflags |= MIPS_HFLAG_FPU;
|
||||
}
|
||||
|
||||
@@ -6530,7 +6530,7 @@ static void glue(gen_, name)(DisasContext *ctx) \
|
||||
ra = gen_avr_ptr(rA(ctx->opcode)); \
|
||||
rb = gen_avr_ptr(rB(ctx->opcode)); \
|
||||
rd = gen_avr_ptr(rD(ctx->opcode)); \
|
||||
gen_helper_##name(rd, cpu_env, ra, rb); \
|
||||
gen_helper_##name(cpu_env, rd, ra, rb); \
|
||||
tcg_temp_free_ptr(ra); \
|
||||
tcg_temp_free_ptr(rb); \
|
||||
tcg_temp_free_ptr(rd); \
|
||||
|
||||
@@ -218,6 +218,8 @@ void HELPER(simcall)(CPUXtensaState *env)
|
||||
|
||||
default:
|
||||
qemu_log("%s(%d): not implemented\n", __func__, regs[2]);
|
||||
regs[2] = -1;
|
||||
regs[3] = ENOSYS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
+153
-102
@@ -176,6 +176,13 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||
so don't use these. */
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
|
||||
#if defined(CONFIG_TCG_PASS_AREG0) && (TARGET_LONG_BITS == 64)
|
||||
/* If we're passing env to the helper as r0 and need a regpair
|
||||
* for the address then r2 will be overwritten as we're setting
|
||||
* up the args to the helper.
|
||||
*/
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
case 'L':
|
||||
@@ -197,6 +204,12 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||
use these. */
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
|
||||
#if defined(CONFIG_SOFTMMU) && \
|
||||
defined(CONFIG_TCG_PASS_AREG0) && (TARGET_LONG_BITS == 64)
|
||||
/* Avoid clashes with registers being used for helper args */
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
|
||||
#endif
|
||||
break;
|
||||
/* qemu_st64 data_reg2 */
|
||||
case 'S':
|
||||
@@ -210,6 +223,10 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
/* r2 is still needed to load data_reg, so don't use it. */
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
|
||||
#if defined(CONFIG_TCG_PASS_AREG0) && (TARGET_LONG_BITS == 64)
|
||||
/* Avoid clashes with registers being used for helper args */
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -388,6 +405,14 @@ static inline void tcg_out_dat_reg(TCGContext *s,
|
||||
(rn << 16) | (rd << 12) | shift | rm);
|
||||
}
|
||||
|
||||
static inline void tcg_out_mov_reg(TCGContext *s, int cond, int rd, int rm)
|
||||
{
|
||||
/* Simple reg-reg move, optimising out the 'do nothing' case */
|
||||
if (rd != rm) {
|
||||
tcg_out_dat_reg(s, cond, ARITH_MOV, rd, 0, rm, SHIFT_IMM_LSL(0));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void tcg_out_dat_reg2(TCGContext *s,
|
||||
int cond, int opc0, int opc1, int rd0, int rd1,
|
||||
int rn0, int rn1, int rm0, int rm1, int shift)
|
||||
@@ -966,6 +991,90 @@ static void *qemu_st_helpers[4] = {
|
||||
__stq_mmu,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Helper routines for marshalling helper function arguments into
|
||||
* the correct registers and stack.
|
||||
* argreg is where we want to put this argument, arg is the argument itself.
|
||||
* Return value is the updated argreg ready for the next call.
|
||||
* Note that argreg 0..3 is real registers, 4+ on stack.
|
||||
* When we reach the first stacked argument, we allocate space for it
|
||||
* and the following stacked arguments using "str r8, [sp, #-0x10]!".
|
||||
* Following arguments are filled in with "str r8, [sp, #0xNN]".
|
||||
* For more than 4 stacked arguments we'd need to know how much
|
||||
* space to allocate when we pushed the first stacked argument.
|
||||
* We don't need this, so don't implement it (and will assert if you try it.)
|
||||
*
|
||||
* We provide routines for arguments which are: immediate, 32 bit
|
||||
* value in register, 16 and 8 bit values in register (which must be zero
|
||||
* extended before use) and 64 bit value in a lo:hi register pair.
|
||||
*/
|
||||
#define DEFINE_TCG_OUT_ARG(NAME, ARGPARAM) \
|
||||
static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGPARAM) \
|
||||
{ \
|
||||
if (argreg < 4) { \
|
||||
TCG_OUT_ARG_GET_ARG(argreg); \
|
||||
} else if (argreg == 4) { \
|
||||
TCG_OUT_ARG_GET_ARG(TCG_REG_R8); \
|
||||
tcg_out32(s, (COND_AL << 28) | 0x052d8010); \
|
||||
} else { \
|
||||
assert(argreg < 8); \
|
||||
TCG_OUT_ARG_GET_ARG(TCG_REG_R8); \
|
||||
tcg_out32(s, (COND_AL << 28) | 0x058d8000 | (argreg - 4) * 4); \
|
||||
} \
|
||||
return argreg + 1; \
|
||||
}
|
||||
|
||||
#define TCG_OUT_ARG_GET_ARG(A) tcg_out_dat_imm(s, COND_AL, ARITH_MOV, A, 0, arg)
|
||||
DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t arg)
|
||||
#undef TCG_OUT_ARG_GET_ARG
|
||||
#define TCG_OUT_ARG_GET_ARG(A) tcg_out_ext8u(s, COND_AL, A, arg)
|
||||
DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg arg)
|
||||
#undef TCG_OUT_ARG_GET_ARG
|
||||
#define TCG_OUT_ARG_GET_ARG(A) tcg_out_ext16u(s, COND_AL, A, arg)
|
||||
DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg arg)
|
||||
#undef TCG_OUT_ARG_GET_ARG
|
||||
|
||||
/* We don't use the macro for this one to avoid an unnecessary reg-reg
|
||||
* move when storing to the stack.
|
||||
*/
|
||||
static TCGReg tcg_out_arg_reg32(TCGContext *s, TCGReg argreg, TCGReg arg)
|
||||
{
|
||||
if (argreg < 4) {
|
||||
tcg_out_mov_reg(s, COND_AL, argreg, arg);
|
||||
} else if (argreg == 4) {
|
||||
/* str arg, [sp, #-0x10]! */
|
||||
tcg_out32(s, (COND_AL << 28) | 0x052d0010 | (arg << 12));
|
||||
} else {
|
||||
assert(argreg < 8);
|
||||
/* str arg, [sp, #0xNN] */
|
||||
tcg_out32(s, (COND_AL << 28) | 0x058d0000 |
|
||||
(arg << 12) | (argreg - 4) * 4);
|
||||
}
|
||||
return argreg + 1;
|
||||
}
|
||||
|
||||
static inline TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
|
||||
TCGReg arglo, TCGReg arghi)
|
||||
{
|
||||
/* 64 bit arguments must go in even/odd register pairs
|
||||
* and in 8-aligned stack slots.
|
||||
*/
|
||||
if (argreg & 1) {
|
||||
argreg++;
|
||||
}
|
||||
argreg = tcg_out_arg_reg32(s, argreg, arglo);
|
||||
argreg = tcg_out_arg_reg32(s, argreg, arghi);
|
||||
return argreg;
|
||||
}
|
||||
|
||||
static inline void tcg_out_arg_stacktidy(TCGContext *s, TCGReg argreg)
|
||||
{
|
||||
/* Output any necessary post-call cleanup of the stack */
|
||||
if (argreg > 4) {
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
|
||||
@@ -975,6 +1084,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
|
||||
int addr_reg, data_reg, data_reg2, bswap;
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
int mem_index, s_bits;
|
||||
TCGReg argreg;
|
||||
# if TARGET_LONG_BITS == 64
|
||||
int addr_reg2;
|
||||
# endif
|
||||
@@ -1088,31 +1198,22 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
|
||||
tcg_out_b_noaddr(s, COND_EQ);
|
||||
|
||||
/* TODO: move this code to where the constants pool will be */
|
||||
if (addr_reg != TCG_REG_R0) {
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
|
||||
}
|
||||
# if TARGET_LONG_BITS == 32
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R1, 0, mem_index);
|
||||
# else
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
|
||||
# endif
|
||||
/* Note that this code relies on the constraints we set in arm_op_defs[]
|
||||
* to ensure that later arguments are not passed to us in registers we
|
||||
* trash by moving the earlier arguments into them.
|
||||
*/
|
||||
argreg = TCG_REG_R0;
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal and incorrect for 64 bit */
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[2], 0,
|
||||
tcg_target_call_iarg_regs[1], SHIFT_IMM_LSL(0));
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[1], 0,
|
||||
tcg_target_call_iarg_regs[0], SHIFT_IMM_LSL(0));
|
||||
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[0], 0, TCG_AREG0,
|
||||
SHIFT_IMM_LSL(0));
|
||||
argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
|
||||
#endif
|
||||
#if TARGET_LONG_BITS == 64
|
||||
argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2);
|
||||
#else
|
||||
argreg = tcg_out_arg_reg32(s, argreg, addr_reg);
|
||||
#endif
|
||||
argreg = tcg_out_arg_imm32(s, argreg, mem_index);
|
||||
tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]);
|
||||
tcg_out_arg_stacktidy(s, argreg);
|
||||
|
||||
switch (opc) {
|
||||
case 0 | 4:
|
||||
@@ -1211,6 +1312,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
|
||||
int addr_reg, data_reg, data_reg2, bswap;
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
int mem_index, s_bits;
|
||||
TCGReg argreg;
|
||||
# if TARGET_LONG_BITS == 64
|
||||
int addr_reg2;
|
||||
# endif
|
||||
@@ -1314,89 +1416,38 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
|
||||
tcg_out_b_noaddr(s, COND_EQ);
|
||||
|
||||
/* TODO: move this code to where the constants pool will be */
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
|
||||
# if TARGET_LONG_BITS == 32
|
||||
switch (opc) {
|
||||
case 0:
|
||||
tcg_out_ext8u(s, COND_AL, TCG_REG_R1, data_reg);
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
|
||||
break;
|
||||
case 1:
|
||||
tcg_out_ext16u(s, COND_AL, TCG_REG_R1, data_reg);
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
|
||||
break;
|
||||
case 2:
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
|
||||
break;
|
||||
case 3:
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index);
|
||||
tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
|
||||
if (data_reg != TCG_REG_R2) {
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
|
||||
}
|
||||
if (data_reg2 != TCG_REG_R3) {
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
# else
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
|
||||
switch (opc) {
|
||||
case 0:
|
||||
tcg_out_ext8u(s, COND_AL, TCG_REG_R2, data_reg);
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
|
||||
break;
|
||||
case 1:
|
||||
tcg_out_ext16u(s, COND_AL, TCG_REG_R2, data_reg);
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
|
||||
break;
|
||||
case 2:
|
||||
if (data_reg != TCG_REG_R2) {
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
|
||||
}
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
|
||||
break;
|
||||
case 3:
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index);
|
||||
tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
|
||||
if (data_reg != TCG_REG_R2) {
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
|
||||
}
|
||||
if (data_reg2 != TCG_REG_R3) {
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
# endif
|
||||
|
||||
/* Note that this code relies on the constraints we set in arm_op_defs[]
|
||||
* to ensure that later arguments are not passed to us in registers we
|
||||
* trash by moving the earlier arguments into them.
|
||||
*/
|
||||
argreg = TCG_REG_R0;
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal and incorrect for 64 bit */
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[3], 0,
|
||||
tcg_target_call_iarg_regs[2], SHIFT_IMM_LSL(0));
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[2], 0,
|
||||
tcg_target_call_iarg_regs[1], SHIFT_IMM_LSL(0));
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[1], 0,
|
||||
tcg_target_call_iarg_regs[0], SHIFT_IMM_LSL(0));
|
||||
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[0], 0, TCG_AREG0,
|
||||
SHIFT_IMM_LSL(0));
|
||||
argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
|
||||
#endif
|
||||
#if TARGET_LONG_BITS == 64
|
||||
argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2);
|
||||
#else
|
||||
argreg = tcg_out_arg_reg32(s, argreg, addr_reg);
|
||||
#endif
|
||||
|
||||
switch (opc) {
|
||||
case 0:
|
||||
argreg = tcg_out_arg_reg8(s, argreg, data_reg);
|
||||
break;
|
||||
case 1:
|
||||
argreg = tcg_out_arg_reg16(s, argreg, data_reg);
|
||||
break;
|
||||
case 2:
|
||||
argreg = tcg_out_arg_reg32(s, argreg, data_reg);
|
||||
break;
|
||||
case 3:
|
||||
argreg = tcg_out_arg_reg64(s, argreg, data_reg, data_reg2);
|
||||
break;
|
||||
}
|
||||
|
||||
argreg = tcg_out_arg_imm32(s, argreg, mem_index);
|
||||
tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]);
|
||||
if (opc == 3)
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
|
||||
tcg_out_arg_stacktidy(s, argreg);
|
||||
|
||||
reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
|
||||
#else /* !CONFIG_SOFTMMU */
|
||||
|
||||
+33
-25
@@ -107,7 +107,7 @@ enum {
|
||||
};
|
||||
|
||||
static const int tcg_target_reg_alloc_order[] = {
|
||||
TCG_REG_R34,
|
||||
TCG_REG_R33,
|
||||
TCG_REG_R35,
|
||||
TCG_REG_R36,
|
||||
TCG_REG_R37,
|
||||
@@ -1532,12 +1532,13 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
|
||||
}
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
tcg_out_bundle(s, mII,
|
||||
tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R58,
|
||||
mem_index, TCG_REG_R0),
|
||||
tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4,
|
||||
TCG_REG_R57, 0, TCG_REG_R56),
|
||||
tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4,
|
||||
TCG_REG_R56, 0, TCG_AREG0));
|
||||
#endif
|
||||
if (!bswap || s_bits == 0) {
|
||||
tcg_out_bundle(s, miB,
|
||||
@@ -1659,15 +1660,21 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
|
||||
tcg_target_call_iarg_regs[2]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
tcg_out_bundle(s, mII,
|
||||
tcg_opc_a5 (TCG_REG_P7, OPC_ADDL_A5, TCG_REG_R59,
|
||||
mem_index, TCG_REG_R0),
|
||||
tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4,
|
||||
TCG_REG_R58, 0, TCG_REG_R57),
|
||||
tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4,
|
||||
TCG_REG_R57, 0, TCG_REG_R56));
|
||||
tcg_out_bundle(s, miB,
|
||||
tcg_opc_m4 (TCG_REG_P6, opc_st_m4[opc],
|
||||
data_reg, TCG_REG_R3),
|
||||
tcg_opc_a4 (TCG_REG_P7, OPC_ADDS_A4,
|
||||
TCG_REG_R56, 0, TCG_AREG0),
|
||||
tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5,
|
||||
TCG_REG_B0, TCG_REG_B6));
|
||||
#else
|
||||
tcg_out_bundle(s, miB,
|
||||
tcg_opc_m4 (TCG_REG_P6, opc_st_m4[opc],
|
||||
data_reg, TCG_REG_R3),
|
||||
@@ -1675,6 +1682,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
|
||||
mem_index, TCG_REG_R0),
|
||||
tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5,
|
||||
TCG_REG_B0, TCG_REG_B6));
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* !CONFIG_SOFTMMU */
|
||||
@@ -2314,13 +2322,13 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
s->code_ptr += 16; /* skip GP */
|
||||
|
||||
/* prologue */
|
||||
tcg_out_bundle(s, mII,
|
||||
tcg_out_bundle(s, miI,
|
||||
tcg_opc_m34(TCG_REG_P0, OPC_ALLOC_M34,
|
||||
TCG_REG_R33, 32, 24, 0),
|
||||
TCG_REG_R34, 32, 24, 0),
|
||||
tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4,
|
||||
TCG_AREG0, 0, TCG_REG_R32),
|
||||
tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21,
|
||||
TCG_REG_B6, TCG_REG_R33, 0),
|
||||
tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22,
|
||||
TCG_REG_R32, TCG_REG_B0));
|
||||
TCG_REG_B6, TCG_REG_R33, 0));
|
||||
|
||||
/* ??? If GUEST_BASE < 0x200000, we could load the register via
|
||||
an ADDL in the M slot of the next bundle. */
|
||||
@@ -2334,10 +2342,10 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
}
|
||||
|
||||
tcg_out_bundle(s, miB,
|
||||
tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4,
|
||||
TCG_AREG0, 0, TCG_REG_R32),
|
||||
tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4,
|
||||
TCG_REG_R12, -frame_size, TCG_REG_R12),
|
||||
tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22,
|
||||
TCG_REG_R32, TCG_REG_B0),
|
||||
tcg_opc_b4 (TCG_REG_P0, OPC_BR_SPTK_MANY_B4, TCG_REG_B6));
|
||||
|
||||
/* epilogue */
|
||||
@@ -2351,7 +2359,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
tcg_out_bundle(s, miB,
|
||||
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
|
||||
tcg_opc_i26(TCG_REG_P0, OPC_MOV_I_I26,
|
||||
TCG_REG_PFS, TCG_REG_R33),
|
||||
TCG_REG_PFS, TCG_REG_R34),
|
||||
tcg_opc_b4 (TCG_REG_P0, OPC_BR_RET_SPTK_MANY_B4,
|
||||
TCG_REG_B0));
|
||||
}
|
||||
@@ -2403,7 +2411,7 @@ static void tcg_target_init(TCGContext *s)
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R12); /* stack pointer */
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* thread pointer */
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R32); /* return address */
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R33); /* PFS */
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R34); /* PFS */
|
||||
|
||||
/* The following 3 are not in use, are call-saved, but *not* saved
|
||||
by the prologue. Therefore we cannot use them without modifying
|
||||
|
||||
Loaded 100 of 106 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user