Compare commits
91 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
920019e0e0 | ||
|
9efdbc0224 | ||
|
28c1dde9aa | ||
|
ab630a065a | ||
|
71049d2a74 | ||
|
03d7712b4b | ||
|
4482258130 | ||
|
41dd30ff63 | ||
|
a1001760ab | ||
|
2a0e6f1369 | ||
|
017f271f7a | ||
|
5149630fed | ||
|
59a823017a | ||
|
3be7eb2f47 | ||
|
576964bf2a | ||
|
4c7f4c4bbb | ||
|
4e74e7a867 | ||
|
375667af78 | ||
|
bceff528ba | ||
|
1549e3a54a | ||
|
86d4f40141 | ||
|
37867211d9 | ||
|
43a3a1b694 | ||
|
ddacb784b3 | ||
|
03f130c682 | ||
|
10b1d6070a | ||
|
e634054c9d | ||
|
13cb31ce08 | ||
|
d0cb440280 | ||
|
21e5c69b85 | ||
|
e2ec206ea9 | ||
|
1f30e35861 | ||
|
19f55e7ab5 | ||
|
c6b77a64b4 | ||
|
0965d5583e | ||
|
14d9028a7d | ||
|
2aa5009412 | ||
|
46275f9091 | ||
|
b0d6feca99 | ||
|
07026c30c3 | ||
|
11dd808dc0 | ||
|
f8364784f0 | ||
|
38e8e9007d | ||
|
80c96a7b60 | ||
|
118112024d | ||
|
83cddbaadf | ||
|
89b0e359bc | ||
|
b260cdec21 | ||
|
7a31a0af31 | ||
|
f0a334345b | ||
|
fc6c2bce38 | ||
|
11665ca918 | ||
|
df42bc4897 | ||
|
c00635946f | ||
|
51ce84e119 | ||
|
0318166a9f | ||
|
261d7f653a | ||
|
044b0bcedf | ||
|
1742e3c74e | ||
|
f173a43a6d | ||
|
2157938f7b | ||
|
f56e70ee4f | ||
|
8a5aaad6c2 | ||
|
3c9e488dbe | ||
|
c627cc38be | ||
|
b443db97c1 | ||
|
6b29db871d | ||
|
6c77b5ab35 | ||
|
11cd30e71a | ||
|
4a25ba2e2b | ||
|
847fe10828 | ||
|
f3a70a4ae1 | ||
|
d7cae05bf5 | ||
|
d03c389511 | ||
|
02d735c274 | ||
|
821314aec3 | ||
|
7c693f0c3f | ||
|
83cd9ed3d7 | ||
|
c6f25642e0 | ||
|
27df37c1ea | ||
|
fe87edd5ed | ||
|
27b0c099fd | ||
|
00d0932e0b | ||
|
2e5502300e | ||
|
8ec7368c8f | ||
|
85bfce130a | ||
|
98cf1bb872 | ||
|
5363028d1f | ||
|
0d6b9ce17c | ||
|
def04278d1 | ||
|
08c410e390 |
19
block.c
19
block.c
@@ -3736,6 +3736,7 @@ static void bdrv_check_co_entry(void *opaque)
|
|||||||
{
|
{
|
||||||
CheckCo *cco = opaque;
|
CheckCo *cco = opaque;
|
||||||
cco->ret = bdrv_co_check(cco->bs, cco->res, cco->fix);
|
cco->ret = bdrv_co_check(cco->bs, cco->res, cco->fix);
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdrv_check(BlockDriverState *bs,
|
int bdrv_check(BlockDriverState *bs,
|
||||||
@@ -3754,7 +3755,7 @@ int bdrv_check(BlockDriverState *bs,
|
|||||||
bdrv_check_co_entry(&cco);
|
bdrv_check_co_entry(&cco);
|
||||||
} else {
|
} else {
|
||||||
co = qemu_coroutine_create(bdrv_check_co_entry, &cco);
|
co = qemu_coroutine_create(bdrv_check_co_entry, &cco);
|
||||||
qemu_coroutine_enter(co);
|
bdrv_coroutine_enter(bs, co);
|
||||||
BDRV_POLL_WHILE(bs, cco.ret == -EINPROGRESS);
|
BDRV_POLL_WHILE(bs, cco.ret == -EINPROGRESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4553,6 +4554,7 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
|
|||||||
if (parent->role->activate) {
|
if (parent->role->activate) {
|
||||||
parent->role->activate(parent, &local_err);
|
parent->role->activate(parent, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
|
bs->open_flags |= BDRV_O_INACTIVE;
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -4571,6 +4573,7 @@ static void coroutine_fn bdrv_invalidate_cache_co_entry(void *opaque)
|
|||||||
InvalidateCacheCo *ico = opaque;
|
InvalidateCacheCo *ico = opaque;
|
||||||
bdrv_co_invalidate_cache(ico->bs, ico->errp);
|
bdrv_co_invalidate_cache(ico->bs, ico->errp);
|
||||||
ico->done = true;
|
ico->done = true;
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
|
void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
|
||||||
@@ -4587,7 +4590,7 @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
|
|||||||
bdrv_invalidate_cache_co_entry(&ico);
|
bdrv_invalidate_cache_co_entry(&ico);
|
||||||
} else {
|
} else {
|
||||||
co = qemu_coroutine_create(bdrv_invalidate_cache_co_entry, &ico);
|
co = qemu_coroutine_create(bdrv_invalidate_cache_co_entry, &ico);
|
||||||
qemu_coroutine_enter(co);
|
bdrv_coroutine_enter(bs, co);
|
||||||
BDRV_POLL_WHILE(bs, !ico.done);
|
BDRV_POLL_WHILE(bs, !ico.done);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5055,10 +5058,6 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
|
|||||||
BdrvAioNotifier *baf, *baf_tmp;
|
BdrvAioNotifier *baf, *baf_tmp;
|
||||||
BdrvChild *child;
|
BdrvChild *child;
|
||||||
|
|
||||||
if (!bs->drv) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!bs->walking_aio_notifiers);
|
assert(!bs->walking_aio_notifiers);
|
||||||
bs->walking_aio_notifiers = true;
|
bs->walking_aio_notifiers = true;
|
||||||
QLIST_FOREACH_SAFE(baf, &bs->aio_notifiers, list, baf_tmp) {
|
QLIST_FOREACH_SAFE(baf, &bs->aio_notifiers, list, baf_tmp) {
|
||||||
@@ -5073,7 +5072,7 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
|
|||||||
*/
|
*/
|
||||||
bs->walking_aio_notifiers = false;
|
bs->walking_aio_notifiers = false;
|
||||||
|
|
||||||
if (bs->drv->bdrv_detach_aio_context) {
|
if (bs->drv && bs->drv->bdrv_detach_aio_context) {
|
||||||
bs->drv->bdrv_detach_aio_context(bs);
|
bs->drv->bdrv_detach_aio_context(bs);
|
||||||
}
|
}
|
||||||
QLIST_FOREACH(child, &bs->children, next) {
|
QLIST_FOREACH(child, &bs->children, next) {
|
||||||
@@ -5089,16 +5088,12 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
|
|||||||
BdrvAioNotifier *ban, *ban_tmp;
|
BdrvAioNotifier *ban, *ban_tmp;
|
||||||
BdrvChild *child;
|
BdrvChild *child;
|
||||||
|
|
||||||
if (!bs->drv) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bs->aio_context = new_context;
|
bs->aio_context = new_context;
|
||||||
|
|
||||||
QLIST_FOREACH(child, &bs->children, next) {
|
QLIST_FOREACH(child, &bs->children, next) {
|
||||||
bdrv_attach_aio_context(child->bs, new_context);
|
bdrv_attach_aio_context(child->bs, new_context);
|
||||||
}
|
}
|
||||||
if (bs->drv->bdrv_attach_aio_context) {
|
if (bs->drv && bs->drv->bdrv_attach_aio_context) {
|
||||||
bs->drv->bdrv_attach_aio_context(bs, new_context);
|
bs->drv->bdrv_attach_aio_context(bs, new_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1220,6 +1220,7 @@ static void blk_read_entry(void *opaque)
|
|||||||
|
|
||||||
rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, qiov->size,
|
rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, qiov->size,
|
||||||
qiov, rwco->flags);
|
qiov, rwco->flags);
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void blk_write_entry(void *opaque)
|
static void blk_write_entry(void *opaque)
|
||||||
@@ -1229,6 +1230,7 @@ static void blk_write_entry(void *opaque)
|
|||||||
|
|
||||||
rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, qiov->size,
|
rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, qiov->size,
|
||||||
qiov, rwco->flags);
|
qiov, rwco->flags);
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
|
static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
|
||||||
@@ -1540,6 +1542,7 @@ static void blk_ioctl_entry(void *opaque)
|
|||||||
|
|
||||||
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
|
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
|
||||||
qiov->iov[0].iov_base);
|
qiov->iov[0].iov_base);
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
|
int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
|
||||||
@@ -1586,6 +1589,7 @@ static void blk_flush_entry(void *opaque)
|
|||||||
{
|
{
|
||||||
BlkRwCo *rwco = opaque;
|
BlkRwCo *rwco = opaque;
|
||||||
rwco->ret = blk_co_flush(rwco->blk);
|
rwco->ret = blk_co_flush(rwco->blk);
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
int blk_flush(BlockBackend *blk)
|
int blk_flush(BlockBackend *blk)
|
||||||
@@ -2018,6 +2022,7 @@ static void blk_pdiscard_entry(void *opaque)
|
|||||||
QEMUIOVector *qiov = rwco->iobuf;
|
QEMUIOVector *qiov = rwco->iobuf;
|
||||||
|
|
||||||
rwco->ret = blk_co_pdiscard(rwco->blk, rwco->offset, qiov->size);
|
rwco->ret = blk_co_pdiscard(rwco->blk, rwco->offset, qiov->size);
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes)
|
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes)
|
||||||
|
@@ -2461,6 +2461,8 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
|
|||||||
off_t data = 0, hole = 0;
|
off_t data = 0, hole = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment));
|
||||||
|
|
||||||
ret = fd_open(bs);
|
ret = fd_open(bs);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
@@ -2486,6 +2488,20 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
|
|||||||
/* On a data extent, compute bytes to the end of the extent,
|
/* On a data extent, compute bytes to the end of the extent,
|
||||||
* possibly including a partial sector at EOF. */
|
* possibly including a partial sector at EOF. */
|
||||||
*pnum = MIN(bytes, hole - offset);
|
*pnum = MIN(bytes, hole - offset);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We are not allowed to return partial sectors, though, so
|
||||||
|
* round up if necessary.
|
||||||
|
*/
|
||||||
|
if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) {
|
||||||
|
int64_t file_length = raw_getlength(bs);
|
||||||
|
if (file_length > 0) {
|
||||||
|
/* Ignore errors, this is just a safeguard */
|
||||||
|
assert(hole == file_length);
|
||||||
|
}
|
||||||
|
*pnum = ROUND_UP(*pnum, bs->bl.request_alignment);
|
||||||
|
}
|
||||||
|
|
||||||
ret = BDRV_BLOCK_DATA;
|
ret = BDRV_BLOCK_DATA;
|
||||||
} else {
|
} else {
|
||||||
/* On a hole, compute bytes to the beginning of the next extent. */
|
/* On a hole, compute bytes to the beginning of the next extent. */
|
||||||
|
@@ -20,6 +20,10 @@
|
|||||||
#include "qemu/option.h"
|
#include "qemu/option.h"
|
||||||
#include "qemu/cutils.h"
|
#include "qemu/cutils.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT
|
||||||
|
# define glfs_ftruncate(fd, offset) glfs_ftruncate(fd, offset, NULL, NULL)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define GLUSTER_OPT_FILENAME "filename"
|
#define GLUSTER_OPT_FILENAME "filename"
|
||||||
#define GLUSTER_OPT_VOLUME "volume"
|
#define GLUSTER_OPT_VOLUME "volume"
|
||||||
#define GLUSTER_OPT_PATH "path"
|
#define GLUSTER_OPT_PATH "path"
|
||||||
@@ -725,7 +729,11 @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
|
|||||||
/*
|
/*
|
||||||
* AIO callback routine called from GlusterFS thread.
|
* AIO callback routine called from GlusterFS thread.
|
||||||
*/
|
*/
|
||||||
static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
|
static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret,
|
||||||
|
#ifdef CONFIG_GLUSTERFS_IOCB_HAS_STAT
|
||||||
|
struct glfs_stat *pre, struct glfs_stat *post,
|
||||||
|
#endif
|
||||||
|
void *arg)
|
||||||
{
|
{
|
||||||
GlusterAIOCB *acb = (GlusterAIOCB *)arg;
|
GlusterAIOCB *acb = (GlusterAIOCB *)arg;
|
||||||
|
|
||||||
|
@@ -806,6 +806,7 @@ static void coroutine_fn bdrv_rw_co_entry(void *opaque)
|
|||||||
rwco->qiov->size, rwco->qiov,
|
rwco->qiov->size, rwco->qiov,
|
||||||
rwco->flags);
|
rwco->flags);
|
||||||
}
|
}
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2279,6 +2280,7 @@ static void coroutine_fn bdrv_block_status_above_co_entry(void *opaque)
|
|||||||
data->offset, data->bytes,
|
data->offset, data->bytes,
|
||||||
data->pnum, data->map, data->file);
|
data->pnum, data->map, data->file);
|
||||||
data->done = true;
|
data->done = true;
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2438,6 +2440,7 @@ static void coroutine_fn bdrv_co_rw_vmstate_entry(void *opaque)
|
|||||||
{
|
{
|
||||||
BdrvVmstateCo *co = opaque;
|
BdrvVmstateCo *co = opaque;
|
||||||
co->ret = bdrv_co_rw_vmstate(co->bs, co->qiov, co->pos, co->is_read);
|
co->ret = bdrv_co_rw_vmstate(co->bs, co->qiov, co->pos, co->is_read);
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
@@ -2559,6 +2562,7 @@ static void coroutine_fn bdrv_flush_co_entry(void *opaque)
|
|||||||
FlushCo *rwco = opaque;
|
FlushCo *rwco = opaque;
|
||||||
|
|
||||||
rwco->ret = bdrv_co_flush(rwco->bs);
|
rwco->ret = bdrv_co_flush(rwco->bs);
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
|
int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
|
||||||
@@ -2704,6 +2708,7 @@ static void coroutine_fn bdrv_pdiscard_co_entry(void *opaque)
|
|||||||
DiscardCo *rwco = opaque;
|
DiscardCo *rwco = opaque;
|
||||||
|
|
||||||
rwco->ret = bdrv_co_pdiscard(rwco->child, rwco->offset, rwco->bytes);
|
rwco->ret = bdrv_co_pdiscard(rwco->child, rwco->offset, rwco->bytes);
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes)
|
int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes)
|
||||||
@@ -3217,6 +3222,7 @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
|
|||||||
TruncateCo *tco = opaque;
|
TruncateCo *tco = opaque;
|
||||||
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->prealloc,
|
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->prealloc,
|
||||||
tco->errp);
|
tco->errp);
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
|
int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
|
||||||
@@ -3236,7 +3242,7 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
|
|||||||
bdrv_truncate_co_entry(&tco);
|
bdrv_truncate_co_entry(&tco);
|
||||||
} else {
|
} else {
|
||||||
co = qemu_coroutine_create(bdrv_truncate_co_entry, &tco);
|
co = qemu_coroutine_create(bdrv_truncate_co_entry, &tco);
|
||||||
qemu_coroutine_enter(co);
|
bdrv_coroutine_enter(child->bs, co);
|
||||||
BDRV_POLL_WHILE(child->bs, tco.ret == NOT_DONE);
|
BDRV_POLL_WHILE(child->bs, tco.ret == NOT_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -116,6 +116,7 @@ static coroutine_fn void nbd_read_reply_entry(void *opaque)
|
|||||||
s->quit = true;
|
s->quit = true;
|
||||||
nbd_recv_coroutines_wake_all(s);
|
nbd_recv_coroutines_wake_all(s);
|
||||||
s->read_reply_co = NULL;
|
s->read_reply_co = NULL;
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nbd_co_send_request(BlockDriverState *bs,
|
static int nbd_co_send_request(BlockDriverState *bs,
|
||||||
|
@@ -390,6 +390,7 @@ static void nvme_cmd_sync_cb(void *opaque, int ret)
|
|||||||
{
|
{
|
||||||
int *pret = opaque;
|
int *pret = opaque;
|
||||||
*pret = ret;
|
*pret = ret;
|
||||||
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nvme_cmd_sync(BlockDriverState *bs, NVMeQueuePair *q,
|
static int nvme_cmd_sync(BlockDriverState *bs, NVMeQueuePair *q,
|
||||||
|
@@ -1665,6 +1665,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
/* From bdrv_co_create. */
|
/* From bdrv_co_create. */
|
||||||
qcow2_open_entry(&qoc);
|
qcow2_open_entry(&qoc);
|
||||||
} else {
|
} else {
|
||||||
|
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||||||
qemu_coroutine_enter(qemu_coroutine_create(qcow2_open_entry, &qoc));
|
qemu_coroutine_enter(qemu_coroutine_create(qcow2_open_entry, &qoc));
|
||||||
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
|
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
|
||||||
}
|
}
|
||||||
@@ -2590,6 +2591,7 @@ static int qcow2_set_up_encryption(BlockDriverState *bs,
|
|||||||
static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
|
static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
|
||||||
uint64_t new_length)
|
uint64_t new_length)
|
||||||
{
|
{
|
||||||
|
BDRVQcow2State *s = bs->opaque;
|
||||||
uint64_t bytes;
|
uint64_t bytes;
|
||||||
uint64_t host_offset = 0;
|
uint64_t host_offset = 0;
|
||||||
unsigned int cur_bytes;
|
unsigned int cur_bytes;
|
||||||
@@ -2600,7 +2602,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
|
|||||||
bytes = new_length - offset;
|
bytes = new_length - offset;
|
||||||
|
|
||||||
while (bytes) {
|
while (bytes) {
|
||||||
cur_bytes = MIN(bytes, INT_MAX);
|
cur_bytes = MIN(bytes, QEMU_ALIGN_DOWN(INT_MAX, s->cluster_size));
|
||||||
ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes,
|
ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes,
|
||||||
&host_offset, &meta);
|
&host_offset, &meta);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@@ -559,6 +559,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
if (qemu_in_coroutine()) {
|
if (qemu_in_coroutine()) {
|
||||||
bdrv_qed_open_entry(&qoc);
|
bdrv_qed_open_entry(&qoc);
|
||||||
} else {
|
} else {
|
||||||
|
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||||||
qemu_coroutine_enter(qemu_coroutine_create(bdrv_qed_open_entry, &qoc));
|
qemu_coroutine_enter(qemu_coroutine_create(bdrv_qed_open_entry, &qoc));
|
||||||
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
|
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
|
||||||
}
|
}
|
||||||
|
61
configure
vendored
61
configure
vendored
@@ -453,6 +453,8 @@ glusterfs_xlator_opt="no"
|
|||||||
glusterfs_discard="no"
|
glusterfs_discard="no"
|
||||||
glusterfs_fallocate="no"
|
glusterfs_fallocate="no"
|
||||||
glusterfs_zerofill="no"
|
glusterfs_zerofill="no"
|
||||||
|
glusterfs_ftruncate_has_stat="no"
|
||||||
|
glusterfs_iocb_has_stat="no"
|
||||||
gtk=""
|
gtk=""
|
||||||
gtk_gl="no"
|
gtk_gl="no"
|
||||||
tls_priority="NORMAL"
|
tls_priority="NORMAL"
|
||||||
@@ -3982,6 +3984,38 @@ if test "$glusterfs" != "no" ; then
|
|||||||
glusterfs_fallocate="yes"
|
glusterfs_fallocate="yes"
|
||||||
glusterfs_zerofill="yes"
|
glusterfs_zerofill="yes"
|
||||||
fi
|
fi
|
||||||
|
cat > $TMPC << EOF
|
||||||
|
#include <glusterfs/api/glfs.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
/* new glfs_ftruncate() passes two additional args */
|
||||||
|
return glfs_ftruncate(NULL, 0, NULL, NULL);
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then
|
||||||
|
glusterfs_ftruncate_has_stat="yes"
|
||||||
|
fi
|
||||||
|
cat > $TMPC << EOF
|
||||||
|
#include <glusterfs/api/glfs.h>
|
||||||
|
|
||||||
|
/* new glfs_io_cbk() passes two additional glfs_stat structs */
|
||||||
|
static void
|
||||||
|
glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
glfs_io_cbk iocb = &glusterfs_iocb;
|
||||||
|
iocb(NULL, 0 , NULL, NULL, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then
|
||||||
|
glusterfs_iocb_has_stat="yes"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
if test "$glusterfs" = "yes" ; then
|
if test "$glusterfs" = "yes" ; then
|
||||||
feature_not_found "GlusterFS backend support" \
|
feature_not_found "GlusterFS backend support" \
|
||||||
@@ -4203,10 +4237,25 @@ fi
|
|||||||
# check for usbfs
|
# check for usbfs
|
||||||
have_usbfs=no
|
have_usbfs=no
|
||||||
if test "$linux_user" = "yes"; then
|
if test "$linux_user" = "yes"; then
|
||||||
if check_include linux/usbdevice_fs.h; then
|
cat > $TMPC << EOF
|
||||||
|
#include <linux/usbdevice_fs.h>
|
||||||
|
|
||||||
|
#ifndef USBDEVFS_GET_CAPABILITIES
|
||||||
|
#error "USBDEVFS_GET_CAPABILITIES undefined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USBDEVFS_DISCONNECT_CLAIM
|
||||||
|
#error "USBDEVFS_DISCONNECT_CLAIM undefined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
if compile_prog "" ""; then
|
||||||
have_usbfs=yes
|
have_usbfs=yes
|
||||||
fi
|
fi
|
||||||
have_usbfs=yes
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# check for fallocate
|
# check for fallocate
|
||||||
@@ -6735,6 +6784,14 @@ if test "$glusterfs_zerofill" = "yes" ; then
|
|||||||
echo "CONFIG_GLUSTERFS_ZEROFILL=y" >> $config_host_mak
|
echo "CONFIG_GLUSTERFS_ZEROFILL=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$glusterfs_ftruncate_has_stat" = "yes" ; then
|
||||||
|
echo "CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT=y" >> $config_host_mak
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$glusterfs_iocb_has_stat" = "yes" ; then
|
||||||
|
echo "CONFIG_GLUSTERFS_IOCB_HAS_STAT=y" >> $config_host_mak
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$libssh2" = "yes" ; then
|
if test "$libssh2" = "yes" ; then
|
||||||
echo "CONFIG_LIBSSH2=m" >> $config_host_mak
|
echo "CONFIG_LIBSSH2=m" >> $config_host_mak
|
||||||
echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak
|
echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak
|
||||||
|
@@ -84,6 +84,10 @@ void *load_device_tree(const char *filename_path, int *sizep)
|
|||||||
filename_path);
|
filename_path);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (dt_size > INT_MAX / 2 - 10000) {
|
||||||
|
error_report("Device tree file '%s' is too large", filename_path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* Expand to 2x size to give enough room for manipulation. */
|
/* Expand to 2x size to give enough room for manipulation. */
|
||||||
dt_size += 10000;
|
dt_size += 10000;
|
||||||
@@ -91,7 +95,7 @@ void *load_device_tree(const char *filename_path, int *sizep)
|
|||||||
/* First allocate space in qemu for device tree */
|
/* First allocate space in qemu for device tree */
|
||||||
fdt = g_malloc0(dt_size);
|
fdt = g_malloc0(dt_size);
|
||||||
|
|
||||||
dt_file_load_size = load_image(filename_path, fdt);
|
dt_file_load_size = load_image_size(filename_path, fdt, dt_size);
|
||||||
if (dt_file_load_size < 0) {
|
if (dt_file_load_size < 0) {
|
||||||
error_report("Unable to open device tree file '%s'",
|
error_report("Unable to open device tree file '%s'",
|
||||||
filename_path);
|
filename_path);
|
||||||
|
10
exec.c
10
exec.c
@@ -664,7 +664,7 @@ static void tcg_register_iommu_notifier(CPUState *cpu,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
|
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
|
||||||
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
|
notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
|
||||||
if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) {
|
if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -672,7 +672,8 @@ static void tcg_register_iommu_notifier(CPUState *cpu,
|
|||||||
if (i == cpu->iommu_notifiers->len) {
|
if (i == cpu->iommu_notifiers->len) {
|
||||||
/* Not found, add a new entry at the end of the array */
|
/* Not found, add a new entry at the end of the array */
|
||||||
cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1);
|
cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1);
|
||||||
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
|
notifier = g_new0(TCGIOMMUNotifier, 1);
|
||||||
|
g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i) = notifier;
|
||||||
|
|
||||||
notifier->mr = mr;
|
notifier->mr = mr;
|
||||||
notifier->iommu_idx = iommu_idx;
|
notifier->iommu_idx = iommu_idx;
|
||||||
@@ -704,8 +705,9 @@ static void tcg_iommu_free_notifier_list(CPUState *cpu)
|
|||||||
TCGIOMMUNotifier *notifier;
|
TCGIOMMUNotifier *notifier;
|
||||||
|
|
||||||
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
|
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
|
||||||
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
|
notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
|
||||||
memory_region_unregister_iommu_notifier(notifier->mr, ¬ifier->n);
|
memory_region_unregister_iommu_notifier(notifier->mr, ¬ifier->n);
|
||||||
|
g_free(notifier);
|
||||||
}
|
}
|
||||||
g_array_free(cpu->iommu_notifiers, true);
|
g_array_free(cpu->iommu_notifiers, true);
|
||||||
}
|
}
|
||||||
@@ -975,7 +977,7 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
|
|||||||
vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu);
|
vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier));
|
cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier *));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -173,6 +173,7 @@ static int vmstate_acpi_post_load(void *opaque, int version_id)
|
|||||||
PIIX4PMState *s = opaque;
|
PIIX4PMState *s = opaque;
|
||||||
|
|
||||||
pm_io_space_update(s);
|
pm_io_space_update(s);
|
||||||
|
smbus_io_space_update(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -512,10 +512,10 @@ static void vexpress_modify_dtb(const struct arm_boot_info *info, void *fdt)
|
|||||||
/* Open code a private version of pflash registration since we
|
/* Open code a private version of pflash registration since we
|
||||||
* need to set non-default device width for VExpress platform.
|
* need to set non-default device width for VExpress platform.
|
||||||
*/
|
*/
|
||||||
static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
|
static PFlashCFI01 *ve_pflash_cfi01_register(hwaddr base, const char *name,
|
||||||
DriveInfo *di)
|
DriveInfo *di)
|
||||||
{
|
{
|
||||||
DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
|
DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01);
|
||||||
|
|
||||||
if (di) {
|
if (di) {
|
||||||
qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(di),
|
qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(di),
|
||||||
@@ -536,7 +536,7 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
|
|||||||
qdev_init_nofail(dev);
|
qdev_init_nofail(dev);
|
||||||
|
|
||||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
||||||
return OBJECT_CHECK(pflash_t, (dev), "cfi.pflash01");
|
return PFLASH_CFI01(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vexpress_common_init(MachineState *machine)
|
static void vexpress_common_init(MachineState *machine)
|
||||||
@@ -548,7 +548,7 @@ static void vexpress_common_init(MachineState *machine)
|
|||||||
qemu_irq pic[64];
|
qemu_irq pic[64];
|
||||||
uint32_t sys_id;
|
uint32_t sys_id;
|
||||||
DriveInfo *dinfo;
|
DriveInfo *dinfo;
|
||||||
pflash_t *pflash0;
|
PFlashCFI01 *pflash0;
|
||||||
I2CBus *i2c;
|
I2CBus *i2c;
|
||||||
ram_addr_t vram_size, sram_size;
|
ram_addr_t vram_size, sram_size;
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#include "hw/arm/arm.h"
|
#include "hw/arm/arm.h"
|
||||||
#include "hw/arm/primecell.h"
|
#include "hw/arm/primecell.h"
|
||||||
#include "hw/arm/virt.h"
|
#include "hw/arm/virt.h"
|
||||||
|
#include "hw/block/flash.h"
|
||||||
#include "hw/vfio/vfio-calxeda-xgmac.h"
|
#include "hw/vfio/vfio-calxeda-xgmac.h"
|
||||||
#include "hw/vfio/vfio-amd-xgbe.h"
|
#include "hw/vfio/vfio-amd-xgbe.h"
|
||||||
#include "hw/display/ramfb.h"
|
#include "hw/display/ramfb.h"
|
||||||
@@ -876,7 +877,7 @@ static void create_one_flash(const char *name, hwaddr flashbase,
|
|||||||
* parameters as the flash devices on the Versatile Express board.
|
* parameters as the flash devices on the Versatile Express board.
|
||||||
*/
|
*/
|
||||||
DriveInfo *dinfo = drive_get_next(IF_PFLASH);
|
DriveInfo *dinfo = drive_get_next(IF_PFLASH);
|
||||||
DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
|
DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01);
|
||||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||||
const uint64_t sectorlength = 256 * 1024;
|
const uint64_t sectorlength = 256 * 1024;
|
||||||
|
|
||||||
|
@@ -49,12 +49,6 @@
|
|||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
#define PFLASH_BUG(fmt, ...) \
|
|
||||||
do { \
|
|
||||||
fprintf(stderr, "PFLASH: Possible BUG - " fmt, ## __VA_ARGS__); \
|
|
||||||
exit(1); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
/* #define PFLASH_DEBUG */
|
/* #define PFLASH_DEBUG */
|
||||||
#ifdef PFLASH_DEBUG
|
#ifdef PFLASH_DEBUG
|
||||||
#define DPRINTF(fmt, ...) \
|
#define DPRINTF(fmt, ...) \
|
||||||
@@ -65,12 +59,10 @@ do { \
|
|||||||
#define DPRINTF(fmt, ...) do { } while (0)
|
#define DPRINTF(fmt, ...) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CFI_PFLASH01(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH01)
|
|
||||||
|
|
||||||
#define PFLASH_BE 0
|
#define PFLASH_BE 0
|
||||||
#define PFLASH_SECURE 1
|
#define PFLASH_SECURE 1
|
||||||
|
|
||||||
struct pflash_t {
|
struct PFlashCFI01 {
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
SysBusDevice parent_obj;
|
SysBusDevice parent_obj;
|
||||||
/*< public >*/
|
/*< public >*/
|
||||||
@@ -109,17 +101,17 @@ static const VMStateDescription vmstate_pflash = {
|
|||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.post_load = pflash_post_load,
|
.post_load = pflash_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8(wcycle, pflash_t),
|
VMSTATE_UINT8(wcycle, PFlashCFI01),
|
||||||
VMSTATE_UINT8(cmd, pflash_t),
|
VMSTATE_UINT8(cmd, PFlashCFI01),
|
||||||
VMSTATE_UINT8(status, pflash_t),
|
VMSTATE_UINT8(status, PFlashCFI01),
|
||||||
VMSTATE_UINT64(counter, pflash_t),
|
VMSTATE_UINT64(counter, PFlashCFI01),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void pflash_timer (void *opaque)
|
static void pflash_timer (void *opaque)
|
||||||
{
|
{
|
||||||
pflash_t *pfl = opaque;
|
PFlashCFI01 *pfl = opaque;
|
||||||
|
|
||||||
trace_pflash_timer_expired(pfl->cmd);
|
trace_pflash_timer_expired(pfl->cmd);
|
||||||
/* Reset flash */
|
/* Reset flash */
|
||||||
@@ -133,7 +125,7 @@ static void pflash_timer (void *opaque)
|
|||||||
* If this code is called we know we have a device_width set for
|
* If this code is called we know we have a device_width set for
|
||||||
* this flash.
|
* this flash.
|
||||||
*/
|
*/
|
||||||
static uint32_t pflash_cfi_query(pflash_t *pfl, hwaddr offset)
|
static uint32_t pflash_cfi_query(PFlashCFI01 *pfl, hwaddr offset)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint32_t resp = 0;
|
uint32_t resp = 0;
|
||||||
@@ -193,7 +185,7 @@ static uint32_t pflash_cfi_query(pflash_t *pfl, hwaddr offset)
|
|||||||
|
|
||||||
|
|
||||||
/* Perform a device id query based on the bank width of the flash. */
|
/* Perform a device id query based on the bank width of the flash. */
|
||||||
static uint32_t pflash_devid_query(pflash_t *pfl, hwaddr offset)
|
static uint32_t pflash_devid_query(PFlashCFI01 *pfl, hwaddr offset)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint32_t resp;
|
uint32_t resp;
|
||||||
@@ -241,7 +233,7 @@ static uint32_t pflash_devid_query(pflash_t *pfl, hwaddr offset)
|
|||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t pflash_data_read(pflash_t *pfl, hwaddr offset,
|
static uint32_t pflash_data_read(PFlashCFI01 *pfl, hwaddr offset,
|
||||||
int width, int be)
|
int width, int be)
|
||||||
{
|
{
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
@@ -284,8 +276,8 @@ static uint32_t pflash_data_read(pflash_t *pfl, hwaddr offset,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
|
static uint32_t pflash_read(PFlashCFI01 *pfl, hwaddr offset,
|
||||||
int width, int be)
|
int width, int be)
|
||||||
{
|
{
|
||||||
hwaddr boff;
|
hwaddr boff;
|
||||||
uint32_t ret;
|
uint32_t ret;
|
||||||
@@ -398,7 +390,7 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* update flash content on disk */
|
/* update flash content on disk */
|
||||||
static void pflash_update(pflash_t *pfl, int offset,
|
static void pflash_update(PFlashCFI01 *pfl, int offset,
|
||||||
int size)
|
int size)
|
||||||
{
|
{
|
||||||
int offset_end;
|
int offset_end;
|
||||||
@@ -412,7 +404,7 @@ static void pflash_update(pflash_t *pfl, int offset,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void pflash_data_write(pflash_t *pfl, hwaddr offset,
|
static inline void pflash_data_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||||
uint32_t value, int width, int be)
|
uint32_t value, int width, int be)
|
||||||
{
|
{
|
||||||
uint8_t *p = pfl->storage;
|
uint8_t *p = pfl->storage;
|
||||||
@@ -448,7 +440,7 @@ static inline void pflash_data_write(pflash_t *pfl, hwaddr offset,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pflash_write(pflash_t *pfl, hwaddr offset,
|
static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||||
uint32_t value, int width, int be)
|
uint32_t value, int width, int be)
|
||||||
{
|
{
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
@@ -507,6 +499,10 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
|
|||||||
break;
|
break;
|
||||||
case 0xe8: /* Write to buffer */
|
case 0xe8: /* Write to buffer */
|
||||||
DPRINTF("%s: Write to buffer\n", __func__);
|
DPRINTF("%s: Write to buffer\n", __func__);
|
||||||
|
/* FIXME should save @offset, @width for case 1+ */
|
||||||
|
qemu_log_mask(LOG_UNIMP,
|
||||||
|
"%s: Write to buffer emulation is flawed\n",
|
||||||
|
__func__);
|
||||||
pfl->status |= 0x80; /* Ready! */
|
pfl->status |= 0x80; /* Ready! */
|
||||||
break;
|
break;
|
||||||
case 0xf0: /* Probe for AMD flash */
|
case 0xf0: /* Probe for AMD flash */
|
||||||
@@ -550,6 +546,7 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
|
|||||||
/* Mask writeblock size based on device width, or bank width if
|
/* Mask writeblock size based on device width, or bank width if
|
||||||
* device width not specified.
|
* device width not specified.
|
||||||
*/
|
*/
|
||||||
|
/* FIXME check @offset, @width */
|
||||||
if (pfl->device_width) {
|
if (pfl->device_width) {
|
||||||
value = extract32(value, 0, pfl->device_width * 8);
|
value = extract32(value, 0, pfl->device_width * 8);
|
||||||
} else {
|
} else {
|
||||||
@@ -587,7 +584,13 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
|
|||||||
case 2:
|
case 2:
|
||||||
switch (pfl->cmd) {
|
switch (pfl->cmd) {
|
||||||
case 0xe8: /* Block write */
|
case 0xe8: /* Block write */
|
||||||
|
/* FIXME check @offset, @width */
|
||||||
if (!pfl->ro) {
|
if (!pfl->ro) {
|
||||||
|
/*
|
||||||
|
* FIXME writing straight to memory is *wrong*. We
|
||||||
|
* should write to a buffer, and flush it to memory
|
||||||
|
* only on confirm command (see below).
|
||||||
|
*/
|
||||||
pflash_data_write(pfl, offset, value, width, be);
|
pflash_data_write(pfl, offset, value, width, be);
|
||||||
} else {
|
} else {
|
||||||
pfl->status |= 0x10; /* Programming error */
|
pfl->status |= 0x10; /* Programming error */
|
||||||
@@ -603,6 +606,7 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
|
|||||||
pfl->wcycle++;
|
pfl->wcycle++;
|
||||||
if (!pfl->ro) {
|
if (!pfl->ro) {
|
||||||
/* Flush the entire write buffer onto backing storage. */
|
/* Flush the entire write buffer onto backing storage. */
|
||||||
|
/* FIXME premature! */
|
||||||
pflash_update(pfl, offset & mask, pfl->writeblock_size);
|
pflash_update(pfl, offset & mask, pfl->writeblock_size);
|
||||||
} else {
|
} else {
|
||||||
pfl->status |= 0x10; /* Programming error */
|
pfl->status |= 0x10; /* Programming error */
|
||||||
@@ -619,11 +623,15 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
|
|||||||
switch (pfl->cmd) {
|
switch (pfl->cmd) {
|
||||||
case 0xe8: /* Block write */
|
case 0xe8: /* Block write */
|
||||||
if (cmd == 0xd0) {
|
if (cmd == 0xd0) {
|
||||||
|
/* FIXME this is where we should write out the buffer */
|
||||||
pfl->wcycle = 0;
|
pfl->wcycle = 0;
|
||||||
pfl->status |= 0x80;
|
pfl->status |= 0x80;
|
||||||
} else {
|
} else {
|
||||||
DPRINTF("%s: unknown command for \"write block\"\n", __func__);
|
qemu_log_mask(LOG_UNIMP,
|
||||||
PFLASH_BUG("Write block confirm");
|
"%s: Aborting write to buffer not implemented,"
|
||||||
|
" the data is already written to storage!\n"
|
||||||
|
"Flash device reset into READ mode.\n",
|
||||||
|
__func__);
|
||||||
goto reset_flash;
|
goto reset_flash;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -654,7 +662,7 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
|
|||||||
static MemTxResult pflash_mem_read_with_attrs(void *opaque, hwaddr addr, uint64_t *value,
|
static MemTxResult pflash_mem_read_with_attrs(void *opaque, hwaddr addr, uint64_t *value,
|
||||||
unsigned len, MemTxAttrs attrs)
|
unsigned len, MemTxAttrs attrs)
|
||||||
{
|
{
|
||||||
pflash_t *pfl = opaque;
|
PFlashCFI01 *pfl = opaque;
|
||||||
bool be = !!(pfl->features & (1 << PFLASH_BE));
|
bool be = !!(pfl->features & (1 << PFLASH_BE));
|
||||||
|
|
||||||
if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
|
if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
|
||||||
@@ -668,7 +676,7 @@ static MemTxResult pflash_mem_read_with_attrs(void *opaque, hwaddr addr, uint64_
|
|||||||
static MemTxResult pflash_mem_write_with_attrs(void *opaque, hwaddr addr, uint64_t value,
|
static MemTxResult pflash_mem_write_with_attrs(void *opaque, hwaddr addr, uint64_t value,
|
||||||
unsigned len, MemTxAttrs attrs)
|
unsigned len, MemTxAttrs attrs)
|
||||||
{
|
{
|
||||||
pflash_t *pfl = opaque;
|
PFlashCFI01 *pfl = opaque;
|
||||||
bool be = !!(pfl->features & (1 << PFLASH_BE));
|
bool be = !!(pfl->features & (1 << PFLASH_BE));
|
||||||
|
|
||||||
if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
|
if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
|
||||||
@@ -687,7 +695,7 @@ static const MemoryRegionOps pflash_cfi01_ops = {
|
|||||||
|
|
||||||
static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
|
static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
pflash_t *pfl = CFI_PFLASH01(dev);
|
PFlashCFI01 *pfl = PFLASH_CFI01(dev);
|
||||||
uint64_t total_len;
|
uint64_t total_len;
|
||||||
int ret;
|
int ret;
|
||||||
uint64_t blocks_per_device, sector_len_per_device, device_len;
|
uint64_t blocks_per_device, sector_len_per_device, device_len;
|
||||||
@@ -863,15 +871,33 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
|
|||||||
pfl->cfi_table[0x3f] = 0x01; /* Number of protection fields */
|
pfl->cfi_table[0x3f] = 0x01; /* Number of protection fields */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pflash_cfi01_system_reset(DeviceState *dev)
|
||||||
|
{
|
||||||
|
PFlashCFI01 *pfl = PFLASH_CFI01(dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The command 0x00 is not assigned by the CFI open standard,
|
||||||
|
* but QEMU historically uses it for the READ_ARRAY command (0xff).
|
||||||
|
*/
|
||||||
|
pfl->cmd = 0x00;
|
||||||
|
pfl->wcycle = 0;
|
||||||
|
memory_region_rom_device_set_romd(&pfl->mem, true);
|
||||||
|
/*
|
||||||
|
* The WSM ready timer occurs at most 150ns after system reset.
|
||||||
|
* This model deliberately ignores this delay.
|
||||||
|
*/
|
||||||
|
pfl->status = 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
static Property pflash_cfi01_properties[] = {
|
static Property pflash_cfi01_properties[] = {
|
||||||
DEFINE_PROP_DRIVE("drive", struct pflash_t, blk),
|
DEFINE_PROP_DRIVE("drive", PFlashCFI01, blk),
|
||||||
/* num-blocks is the number of blocks actually visible to the guest,
|
/* num-blocks is the number of blocks actually visible to the guest,
|
||||||
* ie the total size of the device divided by the sector length.
|
* ie the total size of the device divided by the sector length.
|
||||||
* If we're emulating flash devices wired in parallel the actual
|
* If we're emulating flash devices wired in parallel the actual
|
||||||
* number of blocks per indvidual device will differ.
|
* number of blocks per indvidual device will differ.
|
||||||
*/
|
*/
|
||||||
DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
|
DEFINE_PROP_UINT32("num-blocks", PFlashCFI01, nb_blocs, 0),
|
||||||
DEFINE_PROP_UINT64("sector-length", struct pflash_t, sector_len, 0),
|
DEFINE_PROP_UINT64("sector-length", PFlashCFI01, sector_len, 0),
|
||||||
/* width here is the overall width of this QEMU device in bytes.
|
/* width here is the overall width of this QEMU device in bytes.
|
||||||
* The QEMU device may be emulating a number of flash devices
|
* The QEMU device may be emulating a number of flash devices
|
||||||
* wired up in parallel; the width of each individual flash
|
* wired up in parallel; the width of each individual flash
|
||||||
@@ -888,17 +914,17 @@ static Property pflash_cfi01_properties[] = {
|
|||||||
* 16 bit devices making up a 32 bit wide QEMU device. This
|
* 16 bit devices making up a 32 bit wide QEMU device. This
|
||||||
* is deprecated for new uses of this device.
|
* is deprecated for new uses of this device.
|
||||||
*/
|
*/
|
||||||
DEFINE_PROP_UINT8("width", struct pflash_t, bank_width, 0),
|
DEFINE_PROP_UINT8("width", PFlashCFI01, bank_width, 0),
|
||||||
DEFINE_PROP_UINT8("device-width", struct pflash_t, device_width, 0),
|
DEFINE_PROP_UINT8("device-width", PFlashCFI01, device_width, 0),
|
||||||
DEFINE_PROP_UINT8("max-device-width", struct pflash_t, max_device_width, 0),
|
DEFINE_PROP_UINT8("max-device-width", PFlashCFI01, max_device_width, 0),
|
||||||
DEFINE_PROP_BIT("big-endian", struct pflash_t, features, PFLASH_BE, 0),
|
DEFINE_PROP_BIT("big-endian", PFlashCFI01, features, PFLASH_BE, 0),
|
||||||
DEFINE_PROP_BIT("secure", struct pflash_t, features, PFLASH_SECURE, 0),
|
DEFINE_PROP_BIT("secure", PFlashCFI01, features, PFLASH_SECURE, 0),
|
||||||
DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
|
DEFINE_PROP_UINT16("id0", PFlashCFI01, ident0, 0),
|
||||||
DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
|
DEFINE_PROP_UINT16("id1", PFlashCFI01, ident1, 0),
|
||||||
DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
|
DEFINE_PROP_UINT16("id2", PFlashCFI01, ident2, 0),
|
||||||
DEFINE_PROP_UINT16("id3", struct pflash_t, ident3, 0),
|
DEFINE_PROP_UINT16("id3", PFlashCFI01, ident3, 0),
|
||||||
DEFINE_PROP_STRING("name", struct pflash_t, name),
|
DEFINE_PROP_STRING("name", PFlashCFI01, name),
|
||||||
DEFINE_PROP_BOOL("old-multiple-chip-handling", struct pflash_t,
|
DEFINE_PROP_BOOL("old-multiple-chip-handling", PFlashCFI01,
|
||||||
old_multiple_chip_handling, false),
|
old_multiple_chip_handling, false),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
@@ -907,6 +933,7 @@ static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
|
|||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
|
dc->reset = pflash_cfi01_system_reset;
|
||||||
dc->realize = pflash_cfi01_realize;
|
dc->realize = pflash_cfi01_realize;
|
||||||
dc->props = pflash_cfi01_properties;
|
dc->props = pflash_cfi01_properties;
|
||||||
dc->vmsd = &vmstate_pflash;
|
dc->vmsd = &vmstate_pflash;
|
||||||
@@ -915,9 +942,9 @@ static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
|
|||||||
|
|
||||||
|
|
||||||
static const TypeInfo pflash_cfi01_info = {
|
static const TypeInfo pflash_cfi01_info = {
|
||||||
.name = TYPE_CFI_PFLASH01,
|
.name = TYPE_PFLASH_CFI01,
|
||||||
.parent = TYPE_SYS_BUS_DEVICE,
|
.parent = TYPE_SYS_BUS_DEVICE,
|
||||||
.instance_size = sizeof(struct pflash_t),
|
.instance_size = sizeof(PFlashCFI01),
|
||||||
.class_init = pflash_cfi01_class_init,
|
.class_init = pflash_cfi01_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -928,15 +955,17 @@ static void pflash_cfi01_register_types(void)
|
|||||||
|
|
||||||
type_init(pflash_cfi01_register_types)
|
type_init(pflash_cfi01_register_types)
|
||||||
|
|
||||||
pflash_t *pflash_cfi01_register(hwaddr base,
|
PFlashCFI01 *pflash_cfi01_register(hwaddr base,
|
||||||
DeviceState *qdev, const char *name,
|
DeviceState *qdev, const char *name,
|
||||||
hwaddr size,
|
hwaddr size,
|
||||||
BlockBackend *blk,
|
BlockBackend *blk,
|
||||||
uint32_t sector_len, int nb_blocs,
|
uint32_t sector_len, int nb_blocs,
|
||||||
int bank_width, uint16_t id0, uint16_t id1,
|
int bank_width,
|
||||||
uint16_t id2, uint16_t id3, int be)
|
uint16_t id0, uint16_t id1,
|
||||||
|
uint16_t id2, uint16_t id3,
|
||||||
|
int be)
|
||||||
{
|
{
|
||||||
DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH01);
|
DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01);
|
||||||
|
|
||||||
if (blk) {
|
if (blk) {
|
||||||
qdev_prop_set_drive(dev, "drive", blk, &error_abort);
|
qdev_prop_set_drive(dev, "drive", blk, &error_abort);
|
||||||
@@ -953,17 +982,17 @@ pflash_t *pflash_cfi01_register(hwaddr base,
|
|||||||
qdev_init_nofail(dev);
|
qdev_init_nofail(dev);
|
||||||
|
|
||||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
||||||
return CFI_PFLASH01(dev);
|
return PFLASH_CFI01(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl)
|
MemoryRegion *pflash_cfi01_get_memory(PFlashCFI01 *fl)
|
||||||
{
|
{
|
||||||
return &fl->mem;
|
return &fl->mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void postload_update_cb(void *opaque, int running, RunState state)
|
static void postload_update_cb(void *opaque, int running, RunState state)
|
||||||
{
|
{
|
||||||
pflash_t *pfl = opaque;
|
PFlashCFI01 *pfl = opaque;
|
||||||
|
|
||||||
/* This is called after bdrv_invalidate_cache_all. */
|
/* This is called after bdrv_invalidate_cache_all. */
|
||||||
qemu_del_vm_change_state_handler(pfl->vmstate);
|
qemu_del_vm_change_state_handler(pfl->vmstate);
|
||||||
@@ -975,7 +1004,7 @@ static void postload_update_cb(void *opaque, int running, RunState state)
|
|||||||
|
|
||||||
static int pflash_post_load(void *opaque, int version_id)
|
static int pflash_post_load(void *opaque, int version_id)
|
||||||
{
|
{
|
||||||
pflash_t *pfl = opaque;
|
PFlashCFI01 *pfl = opaque;
|
||||||
|
|
||||||
if (!pfl->ro) {
|
if (!pfl->ro) {
|
||||||
pfl->vmstate = qemu_add_vm_change_state_handler(postload_update_cb,
|
pfl->vmstate = qemu_add_vm_change_state_handler(postload_update_cb,
|
||||||
|
@@ -57,9 +57,7 @@ do { \
|
|||||||
|
|
||||||
#define PFLASH_LAZY_ROMD_THRESHOLD 42
|
#define PFLASH_LAZY_ROMD_THRESHOLD 42
|
||||||
|
|
||||||
#define CFI_PFLASH02(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH02)
|
struct PFlashCFI02 {
|
||||||
|
|
||||||
struct pflash_t {
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
SysBusDevice parent_obj;
|
SysBusDevice parent_obj;
|
||||||
/*< public >*/
|
/*< public >*/
|
||||||
@@ -84,7 +82,7 @@ struct pflash_t {
|
|||||||
uint16_t unlock_addr0;
|
uint16_t unlock_addr0;
|
||||||
uint16_t unlock_addr1;
|
uint16_t unlock_addr1;
|
||||||
uint8_t cfi_table[0x52];
|
uint8_t cfi_table[0x52];
|
||||||
QEMUTimer *timer;
|
QEMUTimer timer;
|
||||||
/* The device replicates the flash memory across its memory space. Emulate
|
/* The device replicates the flash memory across its memory space. Emulate
|
||||||
* that by having a container (.mem) filled with an array of aliases
|
* that by having a container (.mem) filled with an array of aliases
|
||||||
* (.mem_mappings) pointing to the flash memory (.orig_mem).
|
* (.mem_mappings) pointing to the flash memory (.orig_mem).
|
||||||
@@ -101,7 +99,7 @@ struct pflash_t {
|
|||||||
/*
|
/*
|
||||||
* Set up replicated mappings of the same region.
|
* Set up replicated mappings of the same region.
|
||||||
*/
|
*/
|
||||||
static void pflash_setup_mappings(pflash_t *pfl)
|
static void pflash_setup_mappings(PFlashCFI02 *pfl)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
hwaddr size = memory_region_size(&pfl->orig_mem);
|
hwaddr size = memory_region_size(&pfl->orig_mem);
|
||||||
@@ -115,7 +113,7 @@ static void pflash_setup_mappings(pflash_t *pfl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pflash_register_memory(pflash_t *pfl, int rom_mode)
|
static void pflash_register_memory(PFlashCFI02 *pfl, int rom_mode)
|
||||||
{
|
{
|
||||||
memory_region_rom_device_set_romd(&pfl->orig_mem, rom_mode);
|
memory_region_rom_device_set_romd(&pfl->orig_mem, rom_mode);
|
||||||
pfl->rom_mode = rom_mode;
|
pfl->rom_mode = rom_mode;
|
||||||
@@ -123,7 +121,7 @@ static void pflash_register_memory(pflash_t *pfl, int rom_mode)
|
|||||||
|
|
||||||
static void pflash_timer (void *opaque)
|
static void pflash_timer (void *opaque)
|
||||||
{
|
{
|
||||||
pflash_t *pfl = opaque;
|
PFlashCFI02 *pfl = opaque;
|
||||||
|
|
||||||
trace_pflash_timer_expired(pfl->cmd);
|
trace_pflash_timer_expired(pfl->cmd);
|
||||||
/* Reset flash */
|
/* Reset flash */
|
||||||
@@ -137,8 +135,8 @@ static void pflash_timer (void *opaque)
|
|||||||
pfl->cmd = 0;
|
pfl->cmd = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
|
static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr offset,
|
||||||
int width, int be)
|
int width, int be)
|
||||||
{
|
{
|
||||||
hwaddr boff;
|
hwaddr boff;
|
||||||
uint32_t ret;
|
uint32_t ret;
|
||||||
@@ -246,7 +244,7 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* update flash content on disk */
|
/* update flash content on disk */
|
||||||
static void pflash_update(pflash_t *pfl, int offset,
|
static void pflash_update(PFlashCFI02 *pfl, int offset,
|
||||||
int size)
|
int size)
|
||||||
{
|
{
|
||||||
int offset_end;
|
int offset_end;
|
||||||
@@ -260,8 +258,8 @@ static void pflash_update(pflash_t *pfl, int offset,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pflash_write (pflash_t *pfl, hwaddr offset,
|
static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
|
||||||
uint32_t value, int width, int be)
|
uint32_t value, int width, int be)
|
||||||
{
|
{
|
||||||
hwaddr boff;
|
hwaddr boff;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
@@ -429,7 +427,7 @@ static void pflash_write (pflash_t *pfl, hwaddr offset,
|
|||||||
}
|
}
|
||||||
pfl->status = 0x00;
|
pfl->status = 0x00;
|
||||||
/* Let's wait 5 seconds before chip erase is done */
|
/* Let's wait 5 seconds before chip erase is done */
|
||||||
timer_mod(pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
||||||
(NANOSECONDS_PER_SECOND * 5));
|
(NANOSECONDS_PER_SECOND * 5));
|
||||||
break;
|
break;
|
||||||
case 0x30:
|
case 0x30:
|
||||||
@@ -444,7 +442,7 @@ static void pflash_write (pflash_t *pfl, hwaddr offset,
|
|||||||
}
|
}
|
||||||
pfl->status = 0x00;
|
pfl->status = 0x00;
|
||||||
/* Let's wait 1/2 second before sector erase is done */
|
/* Let's wait 1/2 second before sector erase is done */
|
||||||
timer_mod(pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
||||||
(NANOSECONDS_PER_SECOND / 2));
|
(NANOSECONDS_PER_SECOND / 2));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -533,7 +531,7 @@ static const MemoryRegionOps pflash_cfi02_ops_le = {
|
|||||||
|
|
||||||
static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
|
static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
pflash_t *pfl = CFI_PFLASH02(dev);
|
PFlashCFI02 *pfl = PFLASH_CFI02(dev);
|
||||||
uint32_t chip_len;
|
uint32_t chip_len;
|
||||||
int ret;
|
int ret;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
@@ -596,7 +594,7 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
|
|||||||
pfl->rom_mode = 1;
|
pfl->rom_mode = 1;
|
||||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
|
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
|
||||||
|
|
||||||
pfl->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pflash_timer, pfl);
|
timer_init_ns(&pfl->timer, QEMU_CLOCK_VIRTUAL, pflash_timer, pfl);
|
||||||
pfl->wcycle = 0;
|
pfl->wcycle = 0;
|
||||||
pfl->cmd = 0;
|
pfl->cmd = 0;
|
||||||
pfl->status = 0;
|
pfl->status = 0;
|
||||||
@@ -679,35 +677,42 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Property pflash_cfi02_properties[] = {
|
static Property pflash_cfi02_properties[] = {
|
||||||
DEFINE_PROP_DRIVE("drive", struct pflash_t, blk),
|
DEFINE_PROP_DRIVE("drive", PFlashCFI02, blk),
|
||||||
DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
|
DEFINE_PROP_UINT32("num-blocks", PFlashCFI02, nb_blocs, 0),
|
||||||
DEFINE_PROP_UINT32("sector-length", struct pflash_t, sector_len, 0),
|
DEFINE_PROP_UINT32("sector-length", PFlashCFI02, sector_len, 0),
|
||||||
DEFINE_PROP_UINT8("width", struct pflash_t, width, 0),
|
DEFINE_PROP_UINT8("width", PFlashCFI02, width, 0),
|
||||||
DEFINE_PROP_UINT8("mappings", struct pflash_t, mappings, 0),
|
DEFINE_PROP_UINT8("mappings", PFlashCFI02, mappings, 0),
|
||||||
DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0),
|
DEFINE_PROP_UINT8("big-endian", PFlashCFI02, be, 0),
|
||||||
DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
|
DEFINE_PROP_UINT16("id0", PFlashCFI02, ident0, 0),
|
||||||
DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
|
DEFINE_PROP_UINT16("id1", PFlashCFI02, ident1, 0),
|
||||||
DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
|
DEFINE_PROP_UINT16("id2", PFlashCFI02, ident2, 0),
|
||||||
DEFINE_PROP_UINT16("id3", struct pflash_t, ident3, 0),
|
DEFINE_PROP_UINT16("id3", PFlashCFI02, ident3, 0),
|
||||||
DEFINE_PROP_UINT16("unlock-addr0", struct pflash_t, unlock_addr0, 0),
|
DEFINE_PROP_UINT16("unlock-addr0", PFlashCFI02, unlock_addr0, 0),
|
||||||
DEFINE_PROP_UINT16("unlock-addr1", struct pflash_t, unlock_addr1, 0),
|
DEFINE_PROP_UINT16("unlock-addr1", PFlashCFI02, unlock_addr1, 0),
|
||||||
DEFINE_PROP_STRING("name", struct pflash_t, name),
|
DEFINE_PROP_STRING("name", PFlashCFI02, name),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void pflash_cfi02_unrealize(DeviceState *dev, Error **errp)
|
||||||
|
{
|
||||||
|
PFlashCFI02 *pfl = PFLASH_CFI02(dev);
|
||||||
|
timer_del(&pfl->timer);
|
||||||
|
}
|
||||||
|
|
||||||
static void pflash_cfi02_class_init(ObjectClass *klass, void *data)
|
static void pflash_cfi02_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
dc->realize = pflash_cfi02_realize;
|
dc->realize = pflash_cfi02_realize;
|
||||||
|
dc->unrealize = pflash_cfi02_unrealize;
|
||||||
dc->props = pflash_cfi02_properties;
|
dc->props = pflash_cfi02_properties;
|
||||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo pflash_cfi02_info = {
|
static const TypeInfo pflash_cfi02_info = {
|
||||||
.name = TYPE_CFI_PFLASH02,
|
.name = TYPE_PFLASH_CFI02,
|
||||||
.parent = TYPE_SYS_BUS_DEVICE,
|
.parent = TYPE_SYS_BUS_DEVICE,
|
||||||
.instance_size = sizeof(struct pflash_t),
|
.instance_size = sizeof(PFlashCFI02),
|
||||||
.class_init = pflash_cfi02_class_init,
|
.class_init = pflash_cfi02_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -718,17 +723,19 @@ static void pflash_cfi02_register_types(void)
|
|||||||
|
|
||||||
type_init(pflash_cfi02_register_types)
|
type_init(pflash_cfi02_register_types)
|
||||||
|
|
||||||
pflash_t *pflash_cfi02_register(hwaddr base,
|
PFlashCFI02 *pflash_cfi02_register(hwaddr base,
|
||||||
DeviceState *qdev, const char *name,
|
DeviceState *qdev, const char *name,
|
||||||
hwaddr size,
|
hwaddr size,
|
||||||
BlockBackend *blk, uint32_t sector_len,
|
BlockBackend *blk,
|
||||||
int nb_blocs, int nb_mappings, int width,
|
uint32_t sector_len, int nb_blocs,
|
||||||
uint16_t id0, uint16_t id1,
|
int nb_mappings, int width,
|
||||||
uint16_t id2, uint16_t id3,
|
uint16_t id0, uint16_t id1,
|
||||||
uint16_t unlock_addr0, uint16_t unlock_addr1,
|
uint16_t id2, uint16_t id3,
|
||||||
int be)
|
uint16_t unlock_addr0,
|
||||||
|
uint16_t unlock_addr1,
|
||||||
|
int be)
|
||||||
{
|
{
|
||||||
DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH02);
|
DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI02);
|
||||||
|
|
||||||
if (blk) {
|
if (blk) {
|
||||||
qdev_prop_set_drive(dev, "drive", blk, &error_abort);
|
qdev_prop_set_drive(dev, "drive", blk, &error_abort);
|
||||||
@@ -748,5 +755,5 @@ pflash_t *pflash_cfi02_register(hwaddr base,
|
|||||||
qdev_init_nofail(dev);
|
qdev_init_nofail(dev);
|
||||||
|
|
||||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
||||||
return CFI_PFLASH02(dev);
|
return PFLASH_CFI02(dev);
|
||||||
}
|
}
|
||||||
|
@@ -776,6 +776,9 @@ static void interface_release_resource(QXLInstance *sin,
|
|||||||
QXLReleaseRing *ring;
|
QXLReleaseRing *ring;
|
||||||
uint64_t *item, id;
|
uint64_t *item, id;
|
||||||
|
|
||||||
|
if (!ext.info) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (ext.group_id == MEMSLOT_GROUP_HOST) {
|
if (ext.group_id == MEMSLOT_GROUP_HOST) {
|
||||||
/* host group -> vga mode update request */
|
/* host group -> vga mode update request */
|
||||||
QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id);
|
QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id);
|
||||||
|
@@ -426,11 +426,18 @@ static uint8_t xlnx_dp_aux_pop_rx_fifo(XlnxDPState *s)
|
|||||||
uint8_t ret;
|
uint8_t ret;
|
||||||
|
|
||||||
if (fifo8_is_empty(&s->rx_fifo)) {
|
if (fifo8_is_empty(&s->rx_fifo)) {
|
||||||
DPRINTF("rx_fifo underflow..\n");
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
abort();
|
"%s: Reading empty RX_FIFO\n",
|
||||||
|
__func__);
|
||||||
|
/*
|
||||||
|
* The datasheet is not clear about the reset value, it seems
|
||||||
|
* to be unspecified. We choose to return '0'.
|
||||||
|
*/
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
ret = fifo8_pop(&s->rx_fifo);
|
||||||
|
DPRINTF("pop 0x%" PRIX8 " from rx_fifo.\n", ret);
|
||||||
}
|
}
|
||||||
ret = fifo8_pop(&s->rx_fifo);
|
|
||||||
DPRINTF("pop 0x%" PRIX8 " from rx_fifo.\n", ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
#include "hw/i2c/i2c.h"
|
#include "hw/i2c/i2c.h"
|
||||||
|
|
||||||
typedef struct bitbang_i2c_interface bitbang_i2c_interface;
|
|
||||||
|
|
||||||
#define BITBANG_I2C_SDA 0
|
#define BITBANG_I2C_SDA 0
|
||||||
#define BITBANG_I2C_SCL 1
|
#define BITBANG_I2C_SCL 1
|
||||||
|
|
||||||
|
@@ -56,7 +56,7 @@ static int i2c_ddc_rx(I2CSlave *i2c)
|
|||||||
I2CDDCState *s = I2CDDC(i2c);
|
I2CDDCState *s = I2CDDC(i2c);
|
||||||
|
|
||||||
int value;
|
int value;
|
||||||
value = s->edid_blob[s->reg];
|
value = s->edid_blob[s->reg % sizeof(s->edid_blob)];
|
||||||
s->reg++;
|
s->reg++;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@@ -737,10 +737,16 @@ static void crs_range_set_free(CrsRangeSet *range_set)
|
|||||||
|
|
||||||
static gint crs_range_compare(gconstpointer a, gconstpointer b)
|
static gint crs_range_compare(gconstpointer a, gconstpointer b)
|
||||||
{
|
{
|
||||||
CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
|
CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
|
||||||
CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
|
CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
|
||||||
|
|
||||||
return (int64_t)entry_a->base - (int64_t)entry_b->base;
|
if (entry_a->base < entry_b->base) {
|
||||||
|
return -1;
|
||||||
|
} else if (entry_a->base > entry_b->base) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1888,10 +1894,13 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
|||||||
scope = aml_scope("\\_SB");
|
scope = aml_scope("\\_SB");
|
||||||
dev = aml_device("PC%.02X", bus_num);
|
dev = aml_device("PC%.02X", bus_num);
|
||||||
aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
|
aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
|
||||||
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
|
|
||||||
aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
|
aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
|
||||||
if (pci_bus_is_express(bus)) {
|
if (pci_bus_is_express(bus)) {
|
||||||
|
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08")));
|
||||||
|
aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
|
||||||
aml_append(dev, build_q35_osc_method());
|
aml_append(dev, build_q35_osc_method());
|
||||||
|
} else {
|
||||||
|
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numa_node != NUMA_NODE_UNASSIGNED) {
|
if (numa_node != NUMA_NODE_UNASSIGNED) {
|
||||||
|
@@ -111,7 +111,7 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
|
|||||||
char *fatal_errmsg = NULL;
|
char *fatal_errmsg = NULL;
|
||||||
hwaddr phys_addr = 0x100000000ULL;
|
hwaddr phys_addr = 0x100000000ULL;
|
||||||
int sector_bits, sector_size;
|
int sector_bits, sector_size;
|
||||||
pflash_t *system_flash;
|
PFlashCFI01 *system_flash;
|
||||||
MemoryRegion *flash_mem;
|
MemoryRegion *flash_mem;
|
||||||
char name[64];
|
char name[64];
|
||||||
void *flash_ptr;
|
void *flash_ptr;
|
||||||
|
@@ -188,9 +188,11 @@ static void ioapic_update_kvm_routes(IOAPICCommonState *s)
|
|||||||
MSIMessage msg;
|
MSIMessage msg;
|
||||||
struct ioapic_entry_info info;
|
struct ioapic_entry_info info;
|
||||||
ioapic_entry_parse(s->ioredtbl[i], &info);
|
ioapic_entry_parse(s->ioredtbl[i], &info);
|
||||||
msg.address = info.addr;
|
if (!info.masked) {
|
||||||
msg.data = info.data;
|
msg.address = info.addr;
|
||||||
kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL);
|
msg.data = info.data;
|
||||||
|
kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
kvm_irqchip_commit_routes(kvm_state);
|
kvm_irqchip_commit_routes(kvm_state);
|
||||||
}
|
}
|
||||||
|
@@ -1188,7 +1188,7 @@ void mips_malta_init(MachineState *machine)
|
|||||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
const char *initrd_filename = machine->initrd_filename;
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
char *filename;
|
char *filename;
|
||||||
pflash_t *fl;
|
PFlashCFI01 *fl;
|
||||||
MemoryRegion *system_memory = get_system_memory();
|
MemoryRegion *system_memory = get_system_memory();
|
||||||
MemoryRegion *ram_high = g_new(MemoryRegion, 1);
|
MemoryRegion *ram_high = g_new(MemoryRegion, 1);
|
||||||
MemoryRegion *ram_low_preio = g_new(MemoryRegion, 1);
|
MemoryRegion *ram_low_preio = g_new(MemoryRegion, 1);
|
||||||
|
@@ -345,6 +345,10 @@ void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|||||||
if (!dev->hotplugged) {
|
if (!dev->hotplugged) {
|
||||||
pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
|
pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
|
||||||
PCI_EXP_SLTSTA_PDS);
|
PCI_EXP_SLTSTA_PDS);
|
||||||
|
if (pci_dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) {
|
||||||
|
pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA,
|
||||||
|
PCI_EXP_LNKSTA_DLLLA);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,6 +359,10 @@ void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|||||||
if (pci_get_function_0(pci_dev)) {
|
if (pci_get_function_0(pci_dev)) {
|
||||||
pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
|
pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
|
||||||
PCI_EXP_SLTSTA_PDS);
|
PCI_EXP_SLTSTA_PDS);
|
||||||
|
if (pci_dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) {
|
||||||
|
pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA,
|
||||||
|
PCI_EXP_LNKSTA_DLLLA);
|
||||||
|
}
|
||||||
pcie_cap_slot_event(PCI_DEVICE(hotplug_dev),
|
pcie_cap_slot_event(PCI_DEVICE(hotplug_dev),
|
||||||
PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP);
|
PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP);
|
||||||
}
|
}
|
||||||
@@ -531,6 +539,10 @@ void pcie_cap_slot_write_config(PCIDevice *dev,
|
|||||||
|
|
||||||
pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
|
pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
|
||||||
PCI_EXP_SLTSTA_PDS);
|
PCI_EXP_SLTSTA_PDS);
|
||||||
|
if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) {
|
||||||
|
pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA,
|
||||||
|
PCI_EXP_LNKSTA_DLLLA);
|
||||||
|
}
|
||||||
pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
|
pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
|
||||||
PCI_EXP_SLTSTA_PDC);
|
PCI_EXP_SLTSTA_PDC);
|
||||||
}
|
}
|
||||||
|
@@ -553,11 +553,11 @@ static char *core99_fw_dev_path(FWPathProvider *p, BusState *bus,
|
|||||||
return g_strdup("cdrom");
|
return g_strdup("cdrom");
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_strdup("hd");
|
return g_strdup("disk");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(object_get_typename(OBJECT(dev)), "ide-hd")) {
|
if (!strcmp(object_get_typename(OBJECT(dev)), "ide-hd")) {
|
||||||
return g_strdup("hd");
|
return g_strdup("disk");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(object_get_typename(OBJECT(dev)), "ide-cd")) {
|
if (!strcmp(object_get_typename(OBJECT(dev)), "ide-cd")) {
|
||||||
|
@@ -404,11 +404,11 @@ static char *heathrow_fw_dev_path(FWPathProvider *p, BusState *bus,
|
|||||||
return g_strdup("cdrom");
|
return g_strdup("cdrom");
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_strdup("hd");
|
return g_strdup("disk");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(object_get_typename(OBJECT(dev)), "ide-hd")) {
|
if (!strcmp(object_get_typename(OBJECT(dev)), "ide-hd")) {
|
||||||
return g_strdup("hd");
|
return g_strdup("disk");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(object_get_typename(OBJECT(dev)), "ide-cd")) {
|
if (!strcmp(object_get_typename(OBJECT(dev)), "ide-cd")) {
|
||||||
|
@@ -85,7 +85,7 @@ typedef struct RdmaRmPort {
|
|||||||
enum ibv_port_state state;
|
enum ibv_port_state state;
|
||||||
} RdmaRmPort;
|
} RdmaRmPort;
|
||||||
|
|
||||||
typedef struct RdmaDeviceResources {
|
struct RdmaDeviceResources {
|
||||||
RdmaRmPort ports[MAX_PORTS];
|
RdmaRmPort ports[MAX_PORTS];
|
||||||
RdmaRmResTbl pd_tbl;
|
RdmaRmResTbl pd_tbl;
|
||||||
RdmaRmResTbl mr_tbl;
|
RdmaRmResTbl mr_tbl;
|
||||||
@@ -94,6 +94,6 @@ typedef struct RdmaDeviceResources {
|
|||||||
RdmaRmResTbl cq_tbl;
|
RdmaRmResTbl cq_tbl;
|
||||||
RdmaRmResTbl cqe_ctx_tbl;
|
RdmaRmResTbl cqe_ctx_tbl;
|
||||||
GHashTable *qp_hash; /* Keeps mapping between real and emulated */
|
GHashTable *qp_hash; /* Keeps mapping between real and emulated */
|
||||||
} RdmaDeviceResources;
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -261,6 +261,11 @@ static int create_cq_ring(PCIDevice *pci_dev , PvrdmaRing **ring,
|
|||||||
int rc = -EINVAL;
|
int rc = -EINVAL;
|
||||||
char ring_name[MAX_RING_NAME_SZ];
|
char ring_name[MAX_RING_NAME_SZ];
|
||||||
|
|
||||||
|
if (!nchunks || nchunks > PVRDMA_MAX_FAST_REG_PAGES) {
|
||||||
|
pr_dbg("invalid nchunks: %d\n", nchunks);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
pr_dbg("pdir_dma=0x%llx\n", (long long unsigned int)pdir_dma);
|
pr_dbg("pdir_dma=0x%llx\n", (long long unsigned int)pdir_dma);
|
||||||
dir = rdma_pci_dma_map(pci_dev, pdir_dma, TARGET_PAGE_SIZE);
|
dir = rdma_pci_dma_map(pci_dev, pdir_dma, TARGET_PAGE_SIZE);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
@@ -310,6 +315,14 @@ out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void destroy_cq_ring(PvrdmaRing *ring)
|
||||||
|
{
|
||||||
|
pvrdma_ring_free(ring);
|
||||||
|
/* ring_state was in slot 1, not 0 so need to jump back */
|
||||||
|
rdma_pci_dma_unmap(ring->dev, --ring->ring_state, TARGET_PAGE_SIZE);
|
||||||
|
g_free(ring);
|
||||||
|
}
|
||||||
|
|
||||||
static int create_cq(PVRDMADev *dev, union pvrdma_cmd_req *req,
|
static int create_cq(PVRDMADev *dev, union pvrdma_cmd_req *req,
|
||||||
union pvrdma_cmd_resp *rsp)
|
union pvrdma_cmd_resp *rsp)
|
||||||
{
|
{
|
||||||
@@ -333,6 +346,10 @@ static int create_cq(PVRDMADev *dev, union pvrdma_cmd_req *req,
|
|||||||
|
|
||||||
resp->hdr.err = rdma_rm_alloc_cq(&dev->rdma_dev_res, &dev->backend_dev,
|
resp->hdr.err = rdma_rm_alloc_cq(&dev->rdma_dev_res, &dev->backend_dev,
|
||||||
cmd->cqe, &resp->cq_handle, ring);
|
cmd->cqe, &resp->cq_handle, ring);
|
||||||
|
if (resp->hdr.err) {
|
||||||
|
destroy_cq_ring(ring);
|
||||||
|
}
|
||||||
|
|
||||||
resp->cqe = cmd->cqe;
|
resp->cqe = cmd->cqe;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -356,10 +373,7 @@ static int destroy_cq(PVRDMADev *dev, union pvrdma_cmd_req *req,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ring = (PvrdmaRing *)cq->opaque;
|
ring = (PvrdmaRing *)cq->opaque;
|
||||||
pvrdma_ring_free(ring);
|
destroy_cq_ring(ring);
|
||||||
/* ring_state was in slot 1, not 0 so need to jump back */
|
|
||||||
rdma_pci_dma_unmap(PCI_DEVICE(dev), --ring->ring_state, TARGET_PAGE_SIZE);
|
|
||||||
g_free(ring);
|
|
||||||
|
|
||||||
rdma_rm_dealloc_cq(&dev->rdma_dev_res, cmd->cq_handle);
|
rdma_rm_dealloc_cq(&dev->rdma_dev_res, cmd->cq_handle);
|
||||||
|
|
||||||
@@ -377,6 +391,12 @@ static int create_qp_rings(PCIDevice *pci_dev, uint64_t pdir_dma,
|
|||||||
char ring_name[MAX_RING_NAME_SZ];
|
char ring_name[MAX_RING_NAME_SZ];
|
||||||
uint32_t wqe_sz;
|
uint32_t wqe_sz;
|
||||||
|
|
||||||
|
if (!spages || spages > PVRDMA_MAX_FAST_REG_PAGES
|
||||||
|
|| !rpages || rpages > PVRDMA_MAX_FAST_REG_PAGES) {
|
||||||
|
pr_dbg("invalid pages: %d, %d\n", spages, rpages);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
pr_dbg("pdir_dma=0x%llx\n", (long long unsigned int)pdir_dma);
|
pr_dbg("pdir_dma=0x%llx\n", (long long unsigned int)pdir_dma);
|
||||||
dir = rdma_pci_dma_map(pci_dev, pdir_dma, TARGET_PAGE_SIZE);
|
dir = rdma_pci_dma_map(pci_dev, pdir_dma, TARGET_PAGE_SIZE);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
@@ -451,6 +471,17 @@ out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void destroy_qp_rings(PvrdmaRing *ring)
|
||||||
|
{
|
||||||
|
pr_dbg("sring=%p\n", &ring[0]);
|
||||||
|
pvrdma_ring_free(&ring[0]);
|
||||||
|
pr_dbg("rring=%p\n", &ring[1]);
|
||||||
|
pvrdma_ring_free(&ring[1]);
|
||||||
|
|
||||||
|
rdma_pci_dma_unmap(ring->dev, ring->ring_state, TARGET_PAGE_SIZE);
|
||||||
|
g_free(ring);
|
||||||
|
}
|
||||||
|
|
||||||
static int create_qp(PVRDMADev *dev, union pvrdma_cmd_req *req,
|
static int create_qp(PVRDMADev *dev, union pvrdma_cmd_req *req,
|
||||||
union pvrdma_cmd_resp *rsp)
|
union pvrdma_cmd_resp *rsp)
|
||||||
{
|
{
|
||||||
@@ -481,6 +512,10 @@ static int create_qp(PVRDMADev *dev, union pvrdma_cmd_req *req,
|
|||||||
cmd->max_send_sge, cmd->send_cq_handle,
|
cmd->max_send_sge, cmd->send_cq_handle,
|
||||||
cmd->max_recv_wr, cmd->max_recv_sge,
|
cmd->max_recv_wr, cmd->max_recv_sge,
|
||||||
cmd->recv_cq_handle, rings, &resp->qpn);
|
cmd->recv_cq_handle, rings, &resp->qpn);
|
||||||
|
if (resp->hdr.err) {
|
||||||
|
destroy_qp_rings(rings);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
resp->max_send_wr = cmd->max_send_wr;
|
resp->max_send_wr = cmd->max_send_wr;
|
||||||
resp->max_recv_wr = cmd->max_recv_wr;
|
resp->max_recv_wr = cmd->max_recv_wr;
|
||||||
@@ -555,13 +590,7 @@ static int destroy_qp(PVRDMADev *dev, union pvrdma_cmd_req *req,
|
|||||||
rdma_rm_dealloc_qp(&dev->rdma_dev_res, cmd->qp_handle);
|
rdma_rm_dealloc_qp(&dev->rdma_dev_res, cmd->qp_handle);
|
||||||
|
|
||||||
ring = (PvrdmaRing *)qp->opaque;
|
ring = (PvrdmaRing *)qp->opaque;
|
||||||
pr_dbg("sring=%p\n", &ring[0]);
|
destroy_qp_rings(ring);
|
||||||
pvrdma_ring_free(&ring[0]);
|
|
||||||
pr_dbg("rring=%p\n", &ring[1]);
|
|
||||||
pvrdma_ring_free(&ring[1]);
|
|
||||||
|
|
||||||
rdma_pci_dma_unmap(PCI_DEVICE(dev), ring->ring_state, TARGET_PAGE_SIZE);
|
|
||||||
g_free(ring);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -73,23 +73,16 @@ out:
|
|||||||
|
|
||||||
void *pvrdma_ring_next_elem_read(PvrdmaRing *ring)
|
void *pvrdma_ring_next_elem_read(PvrdmaRing *ring)
|
||||||
{
|
{
|
||||||
|
int e;
|
||||||
unsigned int idx = 0, offset;
|
unsigned int idx = 0, offset;
|
||||||
|
|
||||||
/*
|
e = pvrdma_idx_ring_has_data(ring->ring_state, ring->max_elems, &idx);
|
||||||
pr_dbg("%s: t=%d, h=%d\n", ring->name, ring->ring_state->prod_tail,
|
if (e <= 0) {
|
||||||
ring->ring_state->cons_head);
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!pvrdma_idx_ring_has_data(ring->ring_state, ring->max_elems, &idx)) {
|
|
||||||
pr_dbg("No more data in ring\n");
|
pr_dbg("No more data in ring\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = idx * ring->elem_sz;
|
offset = idx * ring->elem_sz;
|
||||||
/*
|
|
||||||
pr_dbg("idx=%d\n", idx);
|
|
||||||
pr_dbg("offset=%d\n", offset);
|
|
||||||
*/
|
|
||||||
return ring->pages[offset / TARGET_PAGE_SIZE] + (offset % TARGET_PAGE_SIZE);
|
return ring->pages[offset / TARGET_PAGE_SIZE] + (offset % TARGET_PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,20 +98,20 @@ void pvrdma_ring_read_inc(PvrdmaRing *ring)
|
|||||||
|
|
||||||
void *pvrdma_ring_next_elem_write(PvrdmaRing *ring)
|
void *pvrdma_ring_next_elem_write(PvrdmaRing *ring)
|
||||||
{
|
{
|
||||||
unsigned int idx, offset, tail;
|
int idx;
|
||||||
|
unsigned int offset, tail;
|
||||||
|
|
||||||
/*
|
idx = pvrdma_idx_ring_has_space(ring->ring_state, ring->max_elems, &tail);
|
||||||
pr_dbg("%s: t=%d, h=%d\n", ring->name, ring->ring_state->prod_tail,
|
if (idx <= 0) {
|
||||||
ring->ring_state->cons_head);
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!pvrdma_idx_ring_has_space(ring->ring_state, ring->max_elems, &tail)) {
|
|
||||||
pr_dbg("CQ is full\n");
|
pr_dbg("CQ is full\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = pvrdma_idx(&ring->ring_state->prod_tail, ring->max_elems);
|
idx = pvrdma_idx(&ring->ring_state->prod_tail, ring->max_elems);
|
||||||
/* TODO: tail == idx */
|
if (idx < 0 || tail != idx) {
|
||||||
|
pr_dbg("invalid idx\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
offset = idx * ring->elem_sz;
|
offset = idx * ring->elem_sz;
|
||||||
return ring->pages[offset / TARGET_PAGE_SIZE] + (offset % TARGET_PAGE_SIZE);
|
return ring->pages[offset / TARGET_PAGE_SIZE] + (offset % TARGET_PAGE_SIZE);
|
||||||
|
@@ -455,6 +455,11 @@ static const MemoryRegionOps regs_ops = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static uint64_t uar_read(void *opaque, hwaddr addr, unsigned size)
|
||||||
|
{
|
||||||
|
return 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
static void uar_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
|
static void uar_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
|
||||||
{
|
{
|
||||||
PVRDMADev *dev = opaque;
|
PVRDMADev *dev = opaque;
|
||||||
@@ -496,6 +501,7 @@ static void uar_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const MemoryRegionOps uar_ops = {
|
static const MemoryRegionOps uar_ops = {
|
||||||
|
.read = uar_read,
|
||||||
.write = uar_write,
|
.write = uar_write,
|
||||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
.impl = {
|
.impl = {
|
||||||
@@ -572,7 +578,7 @@ static int pvrdma_check_ram_shared(Object *obj, void *opaque)
|
|||||||
|
|
||||||
static void pvrdma_realize(PCIDevice *pdev, Error **errp)
|
static void pvrdma_realize(PCIDevice *pdev, Error **errp)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc = 0;
|
||||||
PVRDMADev *dev = PVRDMA_DEV(pdev);
|
PVRDMADev *dev = PVRDMA_DEV(pdev);
|
||||||
Object *memdev_root;
|
Object *memdev_root;
|
||||||
bool ram_shared = false;
|
bool ram_shared = false;
|
||||||
@@ -632,6 +638,7 @@ static void pvrdma_realize(PCIDevice *pdev, Error **errp)
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
pvrdma_fini(pdev);
|
||||||
error_append_hint(errp, "Device fail to load\n");
|
error_append_hint(errp, "Device fail to load\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -477,7 +477,7 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s,
|
|||||||
{
|
{
|
||||||
PCIDevice *pcid = PCI_DEVICE(s);
|
PCIDevice *pcid = PCI_DEVICE(s);
|
||||||
MegasasCmd *cmd = NULL;
|
MegasasCmd *cmd = NULL;
|
||||||
int frame_size = MFI_FRAME_SIZE * 16;
|
int frame_size = MEGASAS_MAX_SGE * sizeof(union mfi_sgl);
|
||||||
hwaddr frame_size_p = frame_size;
|
hwaddr frame_size_p = frame_size;
|
||||||
unsigned long index;
|
unsigned long index;
|
||||||
|
|
||||||
|
@@ -182,7 +182,7 @@ static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
|
|||||||
/* Also take care of the opt xfer len. */
|
/* Also take care of the opt xfer len. */
|
||||||
stl_be_p(&r->buf[12],
|
stl_be_p(&r->buf[12],
|
||||||
MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12])));
|
MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12])));
|
||||||
} else if (s->needs_vpd_bl_emulation && page == 0x00) {
|
} else if (s->needs_vpd_bl_emulation && page == 0x00 && r->buflen >= 4) {
|
||||||
/*
|
/*
|
||||||
* Now we're capable of supplying the VPD Block Limits
|
* Now we're capable of supplying the VPD Block Limits
|
||||||
* response if the hardware can't. Add it in the INQUIRY
|
* response if the hardware can't. Add it in the INQUIRY
|
||||||
@@ -193,18 +193,20 @@ static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
|
|||||||
* and will use it to proper setup the SCSI device.
|
* and will use it to proper setup the SCSI device.
|
||||||
*
|
*
|
||||||
* VPD page numbers must be sorted, so insert 0xb0 at the
|
* VPD page numbers must be sorted, so insert 0xb0 at the
|
||||||
* right place with an in-place insert. After the initialization
|
* right place with an in-place insert. When the while loop
|
||||||
* part of the for loop is executed, the device response is
|
* begins the device response is at r[0] to r[page_idx - 1].
|
||||||
* at r[0] to r[page_idx - 1].
|
|
||||||
*/
|
*/
|
||||||
for (page_idx = lduw_be_p(r->buf + 2) + 4;
|
page_idx = lduw_be_p(r->buf + 2) + 4;
|
||||||
page_idx > 4 && r->buf[page_idx - 1] >= 0xb0;
|
page_idx = MIN(page_idx, r->buflen);
|
||||||
page_idx--) {
|
while (page_idx > 4 && r->buf[page_idx - 1] >= 0xb0) {
|
||||||
if (page_idx < r->buflen) {
|
if (page_idx < r->buflen) {
|
||||||
r->buf[page_idx] = r->buf[page_idx - 1];
|
r->buf[page_idx] = r->buf[page_idx - 1];
|
||||||
}
|
}
|
||||||
|
page_idx--;
|
||||||
|
}
|
||||||
|
if (page_idx < r->buflen) {
|
||||||
|
r->buf[page_idx] = 0xb0;
|
||||||
}
|
}
|
||||||
r->buf[page_idx] = 0xb0;
|
|
||||||
stw_be_p(r->buf + 2, lduw_be_p(r->buf + 2) + 1);
|
stw_be_p(r->buf + 2, lduw_be_p(r->buf + 2) + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -214,6 +214,11 @@ typedef struct PowerDevice {
|
|||||||
} PowerDevice;
|
} PowerDevice;
|
||||||
|
|
||||||
/* Power */
|
/* Power */
|
||||||
|
static uint64_t power_mem_read(void *opaque, hwaddr addr, unsigned size)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void power_mem_write(void *opaque, hwaddr addr,
|
static void power_mem_write(void *opaque, hwaddr addr,
|
||||||
uint64_t val, unsigned size)
|
uint64_t val, unsigned size)
|
||||||
{
|
{
|
||||||
@@ -224,6 +229,7 @@ static void power_mem_write(void *opaque, hwaddr addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const MemoryRegionOps power_mem_ops = {
|
static const MemoryRegionOps power_mem_ops = {
|
||||||
|
.read = power_mem_read,
|
||||||
.write = power_mem_write,
|
.write = power_mem_write,
|
||||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
.valid = {
|
.valid = {
|
||||||
|
@@ -164,7 +164,13 @@ spi_read(void *opaque, hwaddr addr, unsigned int size)
|
|||||||
case R_SPI_RX:
|
case R_SPI_RX:
|
||||||
s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;
|
s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;
|
||||||
s->regs[R_SPI_STATUS] &= ~S_RXCHOVRF;
|
s->regs[R_SPI_STATUS] &= ~S_RXCHOVRF;
|
||||||
ret = fifo32_pop(&s->rx_fifo);
|
if (fifo32_is_empty(&s->rx_fifo)) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"%s: Reading empty RX_FIFO\n",
|
||||||
|
__func__);
|
||||||
|
} else {
|
||||||
|
ret = fifo32_pop(&s->rx_fifo);
|
||||||
|
}
|
||||||
if (fifo32_is_empty(&s->rx_fifo)) {
|
if (fifo32_is_empty(&s->rx_fifo)) {
|
||||||
s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;
|
s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;
|
||||||
}
|
}
|
||||||
|
@@ -1221,6 +1221,10 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
|
|||||||
static const MemoryRegionOps lqspi_ops = {
|
static const MemoryRegionOps lqspi_ops = {
|
||||||
.read = lqspi_read,
|
.read = lqspi_read,
|
||||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
|
.impl = {
|
||||||
|
.min_access_size = 4,
|
||||||
|
.max_access_size = 4,
|
||||||
|
},
|
||||||
.valid = {
|
.valid = {
|
||||||
.min_access_size = 1,
|
.min_access_size = 1,
|
||||||
.max_access_size = 4
|
.max_access_size = 4
|
||||||
|
@@ -265,7 +265,9 @@ static void tpm_crb_reset(void *dev)
|
|||||||
s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
|
s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
|
||||||
CRB_CTRL_CMD_SIZE);
|
CRB_CTRL_CMD_SIZE);
|
||||||
|
|
||||||
tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size);
|
if (tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size) < 0) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tpm_crb_realize(DeviceState *dev, Error **errp)
|
static void tpm_crb_realize(DeviceState *dev, Error **errp)
|
||||||
|
@@ -81,6 +81,40 @@ typedef struct TPMEmulator {
|
|||||||
TPMBlobBuffers state_blobs;
|
TPMBlobBuffers state_blobs;
|
||||||
} TPMEmulator;
|
} TPMEmulator;
|
||||||
|
|
||||||
|
struct tpm_error {
|
||||||
|
uint32_t tpm_result;
|
||||||
|
const char *string;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct tpm_error tpm_errors[] = {
|
||||||
|
/* TPM 1.2 error codes */
|
||||||
|
{ TPM_BAD_PARAMETER , "a parameter is bad" },
|
||||||
|
{ TPM_FAIL , "operation failed" },
|
||||||
|
{ TPM_KEYNOTFOUND , "key could not be found" },
|
||||||
|
{ TPM_BAD_PARAM_SIZE , "bad parameter size"},
|
||||||
|
{ TPM_ENCRYPT_ERROR , "encryption error" },
|
||||||
|
{ TPM_DECRYPT_ERROR , "decryption error" },
|
||||||
|
{ TPM_BAD_KEY_PROPERTY, "bad key property" },
|
||||||
|
{ TPM_BAD_MODE , "bad (encryption) mode" },
|
||||||
|
{ TPM_BAD_VERSION , "bad version identifier" },
|
||||||
|
{ TPM_BAD_LOCALITY , "bad locality" },
|
||||||
|
/* TPM 2 error codes */
|
||||||
|
{ TPM_RC_FAILURE , "operation failed" },
|
||||||
|
{ TPM_RC_LOCALITY , "bad locality" },
|
||||||
|
{ TPM_RC_INSUFFICIENT, "insufficient amount of data" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *tpm_emulator_strerror(uint32_t tpm_result)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(tpm_errors); i++) {
|
||||||
|
if (tpm_errors[i].tpm_result == tpm_result) {
|
||||||
|
return tpm_errors[i].string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg,
|
static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg,
|
||||||
size_t msg_len_in, size_t msg_len_out)
|
size_t msg_len_in, size_t msg_len_out)
|
||||||
@@ -263,7 +297,8 @@ static int tpm_emulator_stop_tpm(TPMBackend *tb)
|
|||||||
|
|
||||||
res = be32_to_cpu(res);
|
res = be32_to_cpu(res);
|
||||||
if (res) {
|
if (res) {
|
||||||
error_report("tpm-emulator: TPM result for CMD_STOP: 0x%x", res);
|
error_report("tpm-emulator: TPM result for CMD_STOP: 0x%x %s", res,
|
||||||
|
tpm_emulator_strerror(res));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,8 +327,9 @@ static int tpm_emulator_set_buffer_size(TPMBackend *tb,
|
|||||||
|
|
||||||
psbs.u.resp.tpm_result = be32_to_cpu(psbs.u.resp.tpm_result);
|
psbs.u.resp.tpm_result = be32_to_cpu(psbs.u.resp.tpm_result);
|
||||||
if (psbs.u.resp.tpm_result != 0) {
|
if (psbs.u.resp.tpm_result != 0) {
|
||||||
error_report("tpm-emulator: TPM result for set buffer size : 0x%x",
|
error_report("tpm-emulator: TPM result for set buffer size : 0x%x %s",
|
||||||
psbs.u.resp.tpm_result);
|
psbs.u.resp.tpm_result,
|
||||||
|
tpm_emulator_strerror(psbs.u.resp.tpm_result));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +374,8 @@ static int tpm_emulator_startup_tpm_resume(TPMBackend *tb, size_t buffersize,
|
|||||||
|
|
||||||
res = be32_to_cpu(init.u.resp.tpm_result);
|
res = be32_to_cpu(init.u.resp.tpm_result);
|
||||||
if (res) {
|
if (res) {
|
||||||
error_report("tpm-emulator: TPM result for CMD_INIT: 0x%x", res);
|
error_report("tpm-emulator: TPM result for CMD_INIT: 0x%x %s", res,
|
||||||
|
tpm_emulator_strerror(res));
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -398,8 +435,9 @@ static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
|
|||||||
|
|
||||||
res = be32_to_cpu(reset_est.u.resp.tpm_result);
|
res = be32_to_cpu(reset_est.u.resp.tpm_result);
|
||||||
if (res) {
|
if (res) {
|
||||||
error_report("tpm-emulator: TPM result for rest establixhed flag: 0x%x",
|
error_report(
|
||||||
res);
|
"tpm-emulator: TPM result for rest established flag: 0x%x %s",
|
||||||
|
res, tpm_emulator_strerror(res));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,7 +675,8 @@ static int tpm_emulator_get_state_blob(TPMEmulator *tpm_emu,
|
|||||||
res = be32_to_cpu(pgs.u.resp.tpm_result);
|
res = be32_to_cpu(pgs.u.resp.tpm_result);
|
||||||
if (res != 0 && (res & 0x800) == 0) {
|
if (res != 0 && (res & 0x800) == 0) {
|
||||||
error_report("tpm-emulator: Getting the stateblob (type %d) failed "
|
error_report("tpm-emulator: Getting the stateblob (type %d) failed "
|
||||||
"with a TPM error 0x%x", type, res);
|
"with a TPM error 0x%x %s", type, res,
|
||||||
|
tpm_emulator_strerror(res));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -757,7 +796,8 @@ static int tpm_emulator_set_state_blob(TPMEmulator *tpm_emu,
|
|||||||
tpm_result = be32_to_cpu(pss.u.resp.tpm_result);
|
tpm_result = be32_to_cpu(pss.u.resp.tpm_result);
|
||||||
if (tpm_result != 0) {
|
if (tpm_result != 0) {
|
||||||
error_report("tpm-emulator: Setting the stateblob (type %d) failed "
|
error_report("tpm-emulator: Setting the stateblob (type %d) failed "
|
||||||
"with a TPM error 0x%x", type, tpm_result);
|
"with a TPM error 0x%x %s", type, tpm_result,
|
||||||
|
tpm_emulator_strerror(tpm_result));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -887,8 +927,8 @@ static void tpm_emulator_shutdown(TPMEmulator *tpm_emu)
|
|||||||
error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s",
|
error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
} else if (res != 0) {
|
} else if (res != 0) {
|
||||||
error_report("tpm-emulator: TPM result for sutdown: 0x%x",
|
error_report("tpm-emulator: TPM result for shutdown: 0x%x %s",
|
||||||
be32_to_cpu(res));
|
be32_to_cpu(res), tpm_emulator_strerror(be32_to_cpu(res)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -39,7 +39,16 @@ struct tpm_resp_hdr {
|
|||||||
#define TPM_TAG_RSP_AUTH1_COMMAND 0xc5
|
#define TPM_TAG_RSP_AUTH1_COMMAND 0xc5
|
||||||
#define TPM_TAG_RSP_AUTH2_COMMAND 0xc6
|
#define TPM_TAG_RSP_AUTH2_COMMAND 0xc6
|
||||||
|
|
||||||
|
#define TPM_BAD_PARAMETER 3
|
||||||
#define TPM_FAIL 9
|
#define TPM_FAIL 9
|
||||||
|
#define TPM_KEYNOTFOUND 13
|
||||||
|
#define TPM_BAD_PARAM_SIZE 25
|
||||||
|
#define TPM_ENCRYPT_ERROR 32
|
||||||
|
#define TPM_DECRYPT_ERROR 33
|
||||||
|
#define TPM_BAD_KEY_PROPERTY 40
|
||||||
|
#define TPM_BAD_MODE 44
|
||||||
|
#define TPM_BAD_VERSION 46
|
||||||
|
#define TPM_BAD_LOCALITY 61
|
||||||
|
|
||||||
#define TPM_ORD_ContinueSelfTest 0x53
|
#define TPM_ORD_ContinueSelfTest 0x53
|
||||||
#define TPM_ORD_GetTicks 0xf1
|
#define TPM_ORD_GetTicks 0xf1
|
||||||
@@ -59,4 +68,8 @@ struct tpm_resp_hdr {
|
|||||||
|
|
||||||
#define TPM2_PT_MAX_COMMAND_SIZE 0x11e
|
#define TPM2_PT_MAX_COMMAND_SIZE 0x11e
|
||||||
|
|
||||||
|
#define TPM_RC_INSUFFICIENT 0x9a
|
||||||
|
#define TPM_RC_FAILURE 0x101
|
||||||
|
#define TPM_RC_LOCALITY 0x907
|
||||||
|
|
||||||
#endif /* TPM_TPM_INT_H */
|
#endif /* TPM_TPM_INT_H */
|
||||||
|
@@ -263,7 +263,9 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
|
|||||||
{
|
{
|
||||||
uint8_t busy_locty;
|
uint8_t busy_locty;
|
||||||
|
|
||||||
s->aborting_locty = locty;
|
assert(TPM_TIS_IS_VALID_LOCTY(newlocty));
|
||||||
|
|
||||||
|
s->aborting_locty = locty; /* may also be TPM_TIS_NO_LOCALITY */
|
||||||
s->next_locty = newlocty; /* locality after successful abort */
|
s->next_locty = newlocty; /* locality after successful abort */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -293,6 +295,8 @@ static void tpm_tis_request_completed(TPMIf *ti, int ret)
|
|||||||
uint8_t locty = s->cmd.locty;
|
uint8_t locty = s->cmd.locty;
|
||||||
uint8_t l;
|
uint8_t l;
|
||||||
|
|
||||||
|
assert(TPM_TIS_IS_VALID_LOCTY(locty));
|
||||||
|
|
||||||
if (s->cmd.selftest_done) {
|
if (s->cmd.selftest_done) {
|
||||||
for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
|
for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
|
||||||
s->loc[l].sts |= TPM_TIS_STS_SELFTEST_DONE;
|
s->loc[l].sts |= TPM_TIS_STS_SELFTEST_DONE;
|
||||||
@@ -616,7 +620,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* cancel any seize by a lower locality */
|
/* cancel any seize by a lower locality */
|
||||||
for (l = 0; l < locty - 1; l++) {
|
for (l = 0; l < locty; l++) {
|
||||||
s->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE;
|
s->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -891,7 +895,9 @@ static void tpm_tis_reset(DeviceState *dev)
|
|||||||
s->rw_offset = 0;
|
s->rw_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tpm_backend_startup_tpm(s->be_driver, s->be_buffer_size);
|
if (tpm_backend_startup_tpm(s->be_driver, s->be_buffer_size) < 0) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* persistent state handling */
|
/* persistent state handling */
|
||||||
|
@@ -653,13 +653,18 @@ static void usb_mtp_object_readdir(MTPState *s, MTPObject *o)
|
|||||||
{
|
{
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
|
int fd;
|
||||||
|
|
||||||
if (o->have_children) {
|
if (o->have_children) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
o->have_children = true;
|
o->have_children = true;
|
||||||
|
|
||||||
dir = opendir(o->path);
|
fd = open(o->path, O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
|
||||||
|
if (fd < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dir = fdopendir(fd);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1007,7 +1012,7 @@ static MTPData *usb_mtp_get_object(MTPState *s, MTPControl *c,
|
|||||||
|
|
||||||
trace_usb_mtp_op_get_object(s->dev.addr, o->handle, o->path);
|
trace_usb_mtp_op_get_object(s->dev.addr, o->handle, o->path);
|
||||||
|
|
||||||
d->fd = open(o->path, O_RDONLY);
|
d->fd = open(o->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
|
||||||
if (d->fd == -1) {
|
if (d->fd == -1) {
|
||||||
usb_mtp_data_free(d);
|
usb_mtp_data_free(d);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1031,7 +1036,7 @@ static MTPData *usb_mtp_get_partial_object(MTPState *s, MTPControl *c,
|
|||||||
c->argv[1], c->argv[2]);
|
c->argv[1], c->argv[2]);
|
||||||
|
|
||||||
d = usb_mtp_data_alloc(c);
|
d = usb_mtp_data_alloc(c);
|
||||||
d->fd = open(o->path, O_RDONLY);
|
d->fd = open(o->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
|
||||||
if (d->fd == -1) {
|
if (d->fd == -1) {
|
||||||
usb_mtp_data_free(d);
|
usb_mtp_data_free(d);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1658,7 +1663,7 @@ static void usb_mtp_write_data(MTPState *s)
|
|||||||
0, 0, 0, 0);
|
0, 0, 0, 0);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
d->fd = open(path, O_CREAT | O_WRONLY, mask);
|
d->fd = open(path, O_CREAT | O_WRONLY | O_CLOEXEC | O_NOFOLLOW, mask);
|
||||||
if (d->fd == -1) {
|
if (d->fd == -1) {
|
||||||
usb_mtp_queue_result(s, RES_STORE_FULL, d->trans,
|
usb_mtp_queue_result(s, RES_STORE_FULL, d->trans,
|
||||||
0, 0, 0, 0);
|
0, 0, 0, 0);
|
||||||
|
@@ -104,6 +104,14 @@ static void vfio_ap_realize(DeviceState *dev, Error **errp)
|
|||||||
vapdev->vdev.name = g_strdup_printf("%s", mdevid);
|
vapdev->vdev.name = g_strdup_printf("%s", mdevid);
|
||||||
vapdev->vdev.dev = dev;
|
vapdev->vdev.dev = dev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vfio-ap devices operate in a way compatible with
|
||||||
|
* memory ballooning, as no pages are pinned in the host.
|
||||||
|
* This needs to be set before vfio_get_device() for vfio common to
|
||||||
|
* handle the balloon inhibitor.
|
||||||
|
*/
|
||||||
|
vapdev->vdev.balloon_allowed = true;
|
||||||
|
|
||||||
ret = vfio_get_device(vfio_group, mdevid, &vapdev->vdev, &local_err);
|
ret = vfio_get_device(vfio_group, mdevid, &vapdev->vdev, &local_err);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto out_get_dev_err;
|
goto out_get_dev_err;
|
||||||
|
@@ -131,6 +131,11 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
|
|||||||
}
|
}
|
||||||
for (i = 0; i < dev->nvqs; ++i) {
|
for (i = 0; i < dev->nvqs; ++i) {
|
||||||
struct vhost_virtqueue *vq = dev->vqs + i;
|
struct vhost_virtqueue *vq = dev->vqs + i;
|
||||||
|
|
||||||
|
if (!vq->used_phys && !vq->used_size) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys,
|
vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys,
|
||||||
range_get_last(vq->used_phys, vq->used_size));
|
range_get_last(vq->used_phys, vq->used_size));
|
||||||
}
|
}
|
||||||
@@ -168,6 +173,11 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev)
|
|||||||
}
|
}
|
||||||
for (i = 0; i < dev->nvqs; ++i) {
|
for (i = 0; i < dev->nvqs; ++i) {
|
||||||
struct vhost_virtqueue *vq = dev->vqs + i;
|
struct vhost_virtqueue *vq = dev->vqs + i;
|
||||||
|
|
||||||
|
if (!vq->used_phys && !vq->used_size) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t last = vq->used_phys + vq->used_size - 1;
|
uint64_t last = vq->used_phys + vq->used_size - 1;
|
||||||
log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
|
log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
|
||||||
}
|
}
|
||||||
|
@@ -33,11 +33,123 @@
|
|||||||
|
|
||||||
#define BALLOON_PAGE_SIZE (1 << VIRTIO_BALLOON_PFN_SHIFT)
|
#define BALLOON_PAGE_SIZE (1 << VIRTIO_BALLOON_PFN_SHIFT)
|
||||||
|
|
||||||
static void balloon_page(void *addr, int deflate)
|
typedef struct PartiallyBalloonedPage {
|
||||||
|
ram_addr_t base_gpa;
|
||||||
|
unsigned long *bitmap;
|
||||||
|
} PartiallyBalloonedPage;
|
||||||
|
|
||||||
|
static void virtio_balloon_pbp_free(PartiallyBalloonedPage *pbp)
|
||||||
{
|
{
|
||||||
if (!qemu_balloon_is_inhibited()) {
|
if (!pbp->bitmap) {
|
||||||
qemu_madvise(addr, BALLOON_PAGE_SIZE,
|
return;
|
||||||
deflate ? QEMU_MADV_WILLNEED : QEMU_MADV_DONTNEED);
|
}
|
||||||
|
g_free(pbp->bitmap);
|
||||||
|
pbp->bitmap = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_balloon_pbp_alloc(PartiallyBalloonedPage *pbp,
|
||||||
|
ram_addr_t base_gpa,
|
||||||
|
long subpages)
|
||||||
|
{
|
||||||
|
pbp->base_gpa = base_gpa;
|
||||||
|
pbp->bitmap = bitmap_new(subpages);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp,
|
||||||
|
ram_addr_t base_gpa)
|
||||||
|
{
|
||||||
|
return pbp->base_gpa == base_gpa;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||||
|
MemoryRegion *mr, hwaddr mr_offset,
|
||||||
|
PartiallyBalloonedPage *pbp)
|
||||||
|
{
|
||||||
|
void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
|
||||||
|
ram_addr_t rb_offset, rb_aligned_offset, base_gpa;
|
||||||
|
RAMBlock *rb;
|
||||||
|
size_t rb_page_size;
|
||||||
|
int subpages;
|
||||||
|
|
||||||
|
/* XXX is there a better way to get to the RAMBlock than via a
|
||||||
|
* host address? */
|
||||||
|
rb = qemu_ram_block_from_host(addr, false, &rb_offset);
|
||||||
|
rb_page_size = qemu_ram_pagesize(rb);
|
||||||
|
|
||||||
|
if (rb_page_size == BALLOON_PAGE_SIZE) {
|
||||||
|
/* Easy case */
|
||||||
|
|
||||||
|
ram_block_discard_range(rb, rb_offset, rb_page_size);
|
||||||
|
/* We ignore errors from ram_block_discard_range(), because it
|
||||||
|
* has already reported them, and failing to discard a balloon
|
||||||
|
* page is not fatal */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hard case
|
||||||
|
*
|
||||||
|
* We've put a piece of a larger host page into the balloon - we
|
||||||
|
* need to keep track until we have a whole host page to
|
||||||
|
* discard
|
||||||
|
*/
|
||||||
|
warn_report_once(
|
||||||
|
"Balloon used with backing page size > 4kiB, this may not be reliable");
|
||||||
|
|
||||||
|
rb_aligned_offset = QEMU_ALIGN_DOWN(rb_offset, rb_page_size);
|
||||||
|
subpages = rb_page_size / BALLOON_PAGE_SIZE;
|
||||||
|
base_gpa = memory_region_get_ram_addr(mr) + mr_offset -
|
||||||
|
(rb_offset - rb_aligned_offset);
|
||||||
|
|
||||||
|
if (pbp->bitmap && !virtio_balloon_pbp_matches(pbp, base_gpa)) {
|
||||||
|
/* We've partially ballooned part of a host page, but now
|
||||||
|
* we're trying to balloon part of a different one. Too hard,
|
||||||
|
* give up on the old partial page */
|
||||||
|
virtio_balloon_pbp_free(pbp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pbp->bitmap) {
|
||||||
|
virtio_balloon_pbp_alloc(pbp, base_gpa, subpages);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_bit((rb_offset - rb_aligned_offset) / BALLOON_PAGE_SIZE,
|
||||||
|
pbp->bitmap);
|
||||||
|
|
||||||
|
if (bitmap_full(pbp->bitmap, subpages)) {
|
||||||
|
/* We've accumulated a full host page, we can actually discard
|
||||||
|
* it now */
|
||||||
|
|
||||||
|
ram_block_discard_range(rb, rb_aligned_offset, rb_page_size);
|
||||||
|
/* We ignore errors from ram_block_discard_range(), because it
|
||||||
|
* has already reported them, and failing to discard a balloon
|
||||||
|
* page is not fatal */
|
||||||
|
virtio_balloon_pbp_free(pbp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void balloon_deflate_page(VirtIOBalloon *balloon,
|
||||||
|
MemoryRegion *mr, hwaddr mr_offset)
|
||||||
|
{
|
||||||
|
void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
|
||||||
|
ram_addr_t rb_offset;
|
||||||
|
RAMBlock *rb;
|
||||||
|
size_t rb_page_size;
|
||||||
|
void *host_addr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* XXX is there a better way to get to the RAMBlock than via a
|
||||||
|
* host address? */
|
||||||
|
rb = qemu_ram_block_from_host(addr, false, &rb_offset);
|
||||||
|
rb_page_size = qemu_ram_pagesize(rb);
|
||||||
|
|
||||||
|
host_addr = (void *)((uintptr_t)addr & ~(rb_page_size - 1));
|
||||||
|
|
||||||
|
/* When a page is deflated, we hint the whole host page it lives
|
||||||
|
* on, since we can't do anything smaller */
|
||||||
|
ret = qemu_madvise(host_addr, rb_page_size, QEMU_MADV_WILLNEED);
|
||||||
|
if (ret != 0) {
|
||||||
|
warn_report("Couldn't MADV_WILLNEED on balloon deflate: %s",
|
||||||
|
strerror(errno));
|
||||||
|
/* Otherwise ignore, failing to page hint shouldn't be fatal */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,25 +326,29 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
MemoryRegionSection section;
|
MemoryRegionSection section;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
PartiallyBalloonedPage pbp = {};
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
uint32_t pfn;
|
uint32_t pfn;
|
||||||
|
|
||||||
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
||||||
if (!elem) {
|
if (!elem) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (iov_to_buf(elem->out_sg, elem->out_num, offset, &pfn, 4) == 4) {
|
while (iov_to_buf(elem->out_sg, elem->out_num, offset, &pfn, 4) == 4) {
|
||||||
ram_addr_t pa;
|
unsigned int p = virtio_ldl_p(vdev, &pfn);
|
||||||
ram_addr_t addr;
|
hwaddr pa;
|
||||||
int p = virtio_ldl_p(vdev, &pfn);
|
|
||||||
|
|
||||||
pa = (ram_addr_t) p << VIRTIO_BALLOON_PFN_SHIFT;
|
pa = (hwaddr) p << VIRTIO_BALLOON_PFN_SHIFT;
|
||||||
offset += 4;
|
offset += 4;
|
||||||
|
|
||||||
/* FIXME: remove get_system_memory(), but how? */
|
section = memory_region_find(get_system_memory(), pa,
|
||||||
section = memory_region_find(get_system_memory(), pa, 1);
|
BALLOON_PAGE_SIZE);
|
||||||
if (!int128_nz(section.size) ||
|
if (!section.mr) {
|
||||||
!memory_region_is_ram(section.mr) ||
|
trace_virtio_balloon_bad_addr(pa);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!memory_region_is_ram(section.mr) ||
|
||||||
memory_region_is_rom(section.mr) ||
|
memory_region_is_rom(section.mr) ||
|
||||||
memory_region_is_romd(section.mr)) {
|
memory_region_is_romd(section.mr)) {
|
||||||
trace_virtio_balloon_bad_addr(pa);
|
trace_virtio_balloon_bad_addr(pa);
|
||||||
@@ -242,17 +358,23 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
|
|
||||||
trace_virtio_balloon_handle_output(memory_region_name(section.mr),
|
trace_virtio_balloon_handle_output(memory_region_name(section.mr),
|
||||||
pa);
|
pa);
|
||||||
/* Using memory_region_get_ram_ptr is bending the rules a bit, but
|
if (!qemu_balloon_is_inhibited()) {
|
||||||
should be OK because we only want a single page. */
|
if (vq == s->ivq) {
|
||||||
addr = section.offset_within_region;
|
balloon_inflate_page(s, section.mr,
|
||||||
balloon_page(memory_region_get_ram_ptr(section.mr) + addr,
|
section.offset_within_region, &pbp);
|
||||||
!!(vq == s->dvq));
|
} else if (vq == s->dvq) {
|
||||||
|
balloon_deflate_page(s, section.mr, section.offset_within_region);
|
||||||
|
} else {
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
memory_region_unref(section.mr);
|
memory_region_unref(section.mr);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtqueue_push(vq, elem, offset);
|
virtqueue_push(vq, elem, offset);
|
||||||
virtio_notify(vdev, vq);
|
virtio_notify(vdev, vq);
|
||||||
g_free(elem);
|
g_free(elem);
|
||||||
|
virtio_balloon_pbp_free(&pbp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +433,7 @@ out:
|
|||||||
static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
|
static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
|
||||||
{
|
{
|
||||||
VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
|
VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
|
||||||
struct virtio_balloon_config config;
|
struct virtio_balloon_config config = {};
|
||||||
|
|
||||||
config.num_pages = cpu_to_le32(dev->num_pages);
|
config.num_pages = cpu_to_le32(dev->num_pages);
|
||||||
config.actual = cpu_to_le32(dev->actual);
|
config.actual = cpu_to_le32(dev->actual);
|
||||||
|
@@ -159,12 +159,12 @@ static void xtfpga_net_init(MemoryRegion *address_space,
|
|||||||
memory_region_add_subregion(address_space, buffers, ram);
|
memory_region_add_subregion(address_space, buffers, ram);
|
||||||
}
|
}
|
||||||
|
|
||||||
static pflash_t *xtfpga_flash_init(MemoryRegion *address_space,
|
static PFlashCFI01 *xtfpga_flash_init(MemoryRegion *address_space,
|
||||||
const XtfpgaBoardDesc *board,
|
const XtfpgaBoardDesc *board,
|
||||||
DriveInfo *dinfo, int be)
|
DriveInfo *dinfo, int be)
|
||||||
{
|
{
|
||||||
SysBusDevice *s;
|
SysBusDevice *s;
|
||||||
DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
|
DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01);
|
||||||
|
|
||||||
qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
|
qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
|
||||||
&error_abort);
|
&error_abort);
|
||||||
@@ -178,7 +178,7 @@ static pflash_t *xtfpga_flash_init(MemoryRegion *address_space,
|
|||||||
s = SYS_BUS_DEVICE(dev);
|
s = SYS_BUS_DEVICE(dev);
|
||||||
memory_region_add_subregion(address_space, board->flash->base,
|
memory_region_add_subregion(address_space, board->flash->base,
|
||||||
sysbus_mmio_get_region(s, 0));
|
sysbus_mmio_get_region(s, 0));
|
||||||
return OBJECT_CHECK(pflash_t, (dev), "cfi.pflash01");
|
return PFLASH_CFI01(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t translate_phys_addr(void *opaque, uint64_t addr)
|
static uint64_t translate_phys_addr(void *opaque, uint64_t addr)
|
||||||
@@ -224,7 +224,7 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
|
|||||||
CPUXtensaState *env = NULL;
|
CPUXtensaState *env = NULL;
|
||||||
MemoryRegion *system_io;
|
MemoryRegion *system_io;
|
||||||
DriveInfo *dinfo;
|
DriveInfo *dinfo;
|
||||||
pflash_t *flash = NULL;
|
PFlashCFI01 *flash = NULL;
|
||||||
QemuOpts *machine_opts = qemu_get_machine_opts();
|
QemuOpts *machine_opts = qemu_get_machine_opts();
|
||||||
const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
|
const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
|
||||||
const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
|
const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
|
||||||
|
@@ -5,32 +5,45 @@
|
|||||||
|
|
||||||
#include "exec/memory.h"
|
#include "exec/memory.h"
|
||||||
|
|
||||||
#define TYPE_CFI_PFLASH01 "cfi.pflash01"
|
|
||||||
#define TYPE_CFI_PFLASH02 "cfi.pflash02"
|
|
||||||
|
|
||||||
typedef struct pflash_t pflash_t;
|
|
||||||
|
|
||||||
/* pflash_cfi01.c */
|
/* pflash_cfi01.c */
|
||||||
pflash_t *pflash_cfi01_register(hwaddr base,
|
|
||||||
DeviceState *qdev, const char *name,
|
#define TYPE_PFLASH_CFI01 "cfi.pflash01"
|
||||||
hwaddr size,
|
#define PFLASH_CFI01(obj) \
|
||||||
BlockBackend *blk,
|
OBJECT_CHECK(PFlashCFI01, (obj), TYPE_PFLASH_CFI01)
|
||||||
uint32_t sector_len, int nb_blocs, int width,
|
|
||||||
uint16_t id0, uint16_t id1,
|
typedef struct PFlashCFI01 PFlashCFI01;
|
||||||
uint16_t id2, uint16_t id3, int be);
|
|
||||||
|
PFlashCFI01 *pflash_cfi01_register(hwaddr base,
|
||||||
|
DeviceState *qdev, const char *name,
|
||||||
|
hwaddr size,
|
||||||
|
BlockBackend *blk,
|
||||||
|
uint32_t sector_len, int nb_blocs,
|
||||||
|
int width,
|
||||||
|
uint16_t id0, uint16_t id1,
|
||||||
|
uint16_t id2, uint16_t id3,
|
||||||
|
int be);
|
||||||
|
MemoryRegion *pflash_cfi01_get_memory(PFlashCFI01 *fl);
|
||||||
|
|
||||||
/* pflash_cfi02.c */
|
/* pflash_cfi02.c */
|
||||||
pflash_t *pflash_cfi02_register(hwaddr base,
|
|
||||||
DeviceState *qdev, const char *name,
|
|
||||||
hwaddr size,
|
|
||||||
BlockBackend *blk, uint32_t sector_len,
|
|
||||||
int nb_blocs, int nb_mappings, int width,
|
|
||||||
uint16_t id0, uint16_t id1,
|
|
||||||
uint16_t id2, uint16_t id3,
|
|
||||||
uint16_t unlock_addr0, uint16_t unlock_addr1,
|
|
||||||
int be);
|
|
||||||
|
|
||||||
MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl);
|
#define TYPE_PFLASH_CFI02 "cfi.pflash02"
|
||||||
|
#define PFLASH_CFI02(obj) \
|
||||||
|
OBJECT_CHECK(PFlashCFI02, (obj), TYPE_PFLASH_CFI02)
|
||||||
|
|
||||||
|
typedef struct PFlashCFI02 PFlashCFI02;
|
||||||
|
|
||||||
|
PFlashCFI02 *pflash_cfi02_register(hwaddr base,
|
||||||
|
DeviceState *qdev, const char *name,
|
||||||
|
hwaddr size,
|
||||||
|
BlockBackend *blk,
|
||||||
|
uint32_t sector_len, int nb_blocs,
|
||||||
|
int nb_mappings,
|
||||||
|
int width,
|
||||||
|
uint16_t id0, uint16_t id1,
|
||||||
|
uint16_t id2, uint16_t id3,
|
||||||
|
uint16_t unlock_addr0,
|
||||||
|
uint16_t unlock_addr1,
|
||||||
|
int be);
|
||||||
|
|
||||||
/* nand.c */
|
/* nand.c */
|
||||||
DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id);
|
DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id);
|
||||||
|
@@ -82,6 +82,8 @@ int i2c_recv(I2CBus *bus);
|
|||||||
|
|
||||||
DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr);
|
DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr);
|
||||||
|
|
||||||
|
typedef struct bitbang_i2c_interface bitbang_i2c_interface;
|
||||||
|
|
||||||
/* lm832x.c */
|
/* lm832x.c */
|
||||||
void lm832x_key_event(DeviceState *dev, int key, int state);
|
void lm832x_key_event(DeviceState *dev, int key, int state);
|
||||||
|
|
||||||
|
@@ -31,9 +31,6 @@
|
|||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
#include "hw/i2c/i2c.h"
|
#include "hw/i2c/i2c.h"
|
||||||
|
|
||||||
/* from hw/i2c/bitbang_i2c.h */
|
|
||||||
typedef struct bitbang_i2c_interface bitbang_i2c_interface;
|
|
||||||
|
|
||||||
#define TYPE_PPC4xx_I2C "ppc4xx-i2c"
|
#define TYPE_PPC4xx_I2C "ppc4xx-i2c"
|
||||||
#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
|
#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
|
||||||
|
|
||||||
|
@@ -50,7 +50,7 @@ typedef struct S390TODClass {
|
|||||||
/* Converts ns to s390's clock format */
|
/* Converts ns to s390's clock format */
|
||||||
static inline uint64_t time2tod(uint64_t ns)
|
static inline uint64_t time2tod(uint64_t ns)
|
||||||
{
|
{
|
||||||
return (ns << 9) / 125 + (((ns & 0xff10000000000000ull) / 125) << 9);
|
return (ns << 9) / 125 + (((ns & 0xff80000000000000ull) / 125) << 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Converts s390's clock format to ns */
|
/* Converts s390's clock format to ns */
|
||||||
|
@@ -30,6 +30,7 @@ typedef struct virtio_balloon_stat_modern {
|
|||||||
uint64_t val;
|
uint64_t val;
|
||||||
} VirtIOBalloonStatModern;
|
} VirtIOBalloonStatModern;
|
||||||
|
|
||||||
|
|
||||||
typedef struct VirtIOBalloon {
|
typedef struct VirtIOBalloon {
|
||||||
VirtIODevice parent_obj;
|
VirtIODevice parent_obj;
|
||||||
VirtQueue *ivq, *dvq, *svq;
|
VirtQueue *ivq, *dvq, *svq;
|
||||||
|
@@ -9677,8 +9677,15 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
|||||||
arg4 = arg5;
|
arg4 = arg5;
|
||||||
arg5 = arg6;
|
arg5 = arg6;
|
||||||
}
|
}
|
||||||
if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
|
if (arg2 == 0 && arg3 == 0) {
|
||||||
return -TARGET_EFAULT;
|
/* Special-case NULL buffer and zero length, which should succeed */
|
||||||
|
p = 0;
|
||||||
|
} else {
|
||||||
|
p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
|
||||||
|
if (!p) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
|
ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
|
||||||
unlock_user(p, arg2, ret);
|
unlock_user(p, arg2, ret);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -9687,8 +9694,15 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
|||||||
arg4 = arg5;
|
arg4 = arg5;
|
||||||
arg5 = arg6;
|
arg5 = arg6;
|
||||||
}
|
}
|
||||||
if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
|
if (arg2 == 0 && arg3 == 0) {
|
||||||
return -TARGET_EFAULT;
|
/* Special-case NULL buffer and zero length, which should succeed */
|
||||||
|
p = 0;
|
||||||
|
} else {
|
||||||
|
p = lock_user(VERIFY_READ, arg2, arg3, 1);
|
||||||
|
if (!p) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
|
ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
|
||||||
unlock_user(p, arg2, 0);
|
unlock_user(p, arg2, 0);
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -223,7 +223,6 @@ static void chr_closed_bh(void *opaque)
|
|||||||
s = DO_UPCAST(NetVhostUserState, nc, ncs[0]);
|
s = DO_UPCAST(NetVhostUserState, nc, ncs[0]);
|
||||||
|
|
||||||
qmp_set_link(name, false, &err);
|
qmp_set_link(name, false, &err);
|
||||||
vhost_user_stop(queues, ncs);
|
|
||||||
|
|
||||||
qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event,
|
qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event,
|
||||||
NULL, opaque, NULL, true);
|
NULL, opaque, NULL, true);
|
||||||
|
@@ -109,6 +109,13 @@ static int parse_acl_file(const char *filename, ACLList *acl_list)
|
|||||||
}
|
}
|
||||||
*argend = 0;
|
*argend = 0;
|
||||||
|
|
||||||
|
if (!g_str_equal(cmd, "include") && strlen(arg) >= IFNAMSIZ) {
|
||||||
|
fprintf(stderr, "name `%s' too long: %zu\n", arg, strlen(arg));
|
||||||
|
fclose(f);
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(cmd, "deny") == 0) {
|
if (strcmp(cmd, "deny") == 0) {
|
||||||
acl_rule = g_malloc(sizeof(*acl_rule));
|
acl_rule = g_malloc(sizeof(*acl_rule));
|
||||||
if (strcmp(arg, "all") == 0) {
|
if (strcmp(arg, "all") == 0) {
|
||||||
@@ -259,6 +266,10 @@ int main(int argc, char **argv)
|
|||||||
usage();
|
usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
if (strlen(bridge) >= IFNAMSIZ) {
|
||||||
|
fprintf(stderr, "name `%s' too long: %zu\n", bridge, strlen(bridge));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
/* parse default acl file */
|
/* parse default acl file */
|
||||||
QSIMPLEQ_INIT(&acl_list);
|
QSIMPLEQ_INIT(&acl_list);
|
||||||
|
26
qemu-img.c
26
qemu-img.c
@@ -503,7 +503,7 @@ static int img_create(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -753,7 +753,7 @@ static int img_check(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -966,7 +966,7 @@ static int img_commit(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1349,7 +1349,7 @@ static int img_compare(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
ret = 2;
|
ret = 2;
|
||||||
goto out4;
|
goto out4;
|
||||||
}
|
}
|
||||||
@@ -2159,7 +2159,7 @@ static int img_convert(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
goto fail_getopt;
|
goto fail_getopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2713,7 +2713,7 @@ static int img_info(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2932,7 +2932,7 @@ static int img_map(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3081,7 +3081,7 @@ static int img_snapshot(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3241,7 +3241,7 @@ static int img_rebase(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3621,7 +3621,7 @@ static int img_resize(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3865,7 +3865,7 @@ static int img_amend(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out_no_progress;
|
goto out_no_progress;
|
||||||
}
|
}
|
||||||
@@ -4509,7 +4509,7 @@ static int img_dd(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -4786,7 +4786,7 @@ static int img_measure(int argc, char **argv)
|
|||||||
|
|
||||||
if (qemu_opts_foreach(&qemu_object_opts,
|
if (qemu_opts_foreach(&qemu_object_opts,
|
||||||
user_creatable_add_opts_foreach,
|
user_creatable_add_opts_foreach,
|
||||||
NULL, NULL)) {
|
NULL, &error_fatal)) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -120,20 +120,37 @@ qemu_seccomp(unsigned int operation, unsigned int flags, void *args)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t qemu_seccomp_get_kill_action(void)
|
static uint32_t qemu_seccomp_get_action(int set)
|
||||||
{
|
{
|
||||||
|
switch (set) {
|
||||||
|
case QEMU_SECCOMP_SET_DEFAULT:
|
||||||
|
case QEMU_SECCOMP_SET_OBSOLETE:
|
||||||
|
case QEMU_SECCOMP_SET_PRIVILEGED:
|
||||||
|
case QEMU_SECCOMP_SET_SPAWN: {
|
||||||
#if defined(SECCOMP_GET_ACTION_AVAIL) && defined(SCMP_ACT_KILL_PROCESS) && \
|
#if defined(SECCOMP_GET_ACTION_AVAIL) && defined(SCMP_ACT_KILL_PROCESS) && \
|
||||||
defined(SECCOMP_RET_KILL_PROCESS)
|
defined(SECCOMP_RET_KILL_PROCESS)
|
||||||
{
|
static int kill_process = -1;
|
||||||
uint32_t action = SECCOMP_RET_KILL_PROCESS;
|
if (kill_process == -1) {
|
||||||
|
uint32_t action = SECCOMP_RET_KILL_PROCESS;
|
||||||
|
|
||||||
if (qemu_seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &action) == 0) {
|
if (qemu_seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &action) == 0) {
|
||||||
|
kill_process = 1;
|
||||||
|
}
|
||||||
|
kill_process = 0;
|
||||||
|
}
|
||||||
|
if (kill_process == 1) {
|
||||||
return SCMP_ACT_KILL_PROCESS;
|
return SCMP_ACT_KILL_PROCESS;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
return SCMP_ACT_TRAP;
|
||||||
|
}
|
||||||
|
|
||||||
return SCMP_ACT_TRAP;
|
case QEMU_SECCOMP_SET_RESOURCECTL:
|
||||||
|
return SCMP_ACT_ERRNO(EPERM);
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -142,7 +159,6 @@ static int seccomp_start(uint32_t seccomp_opts)
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
scmp_filter_ctx ctx;
|
scmp_filter_ctx ctx;
|
||||||
uint32_t action = qemu_seccomp_get_kill_action();
|
|
||||||
|
|
||||||
ctx = seccomp_init(SCMP_ACT_ALLOW);
|
ctx = seccomp_init(SCMP_ACT_ALLOW);
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
@@ -156,10 +172,12 @@ static int seccomp_start(uint32_t seccomp_opts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(blacklist); i++) {
|
for (i = 0; i < ARRAY_SIZE(blacklist); i++) {
|
||||||
|
uint32_t action;
|
||||||
if (!(seccomp_opts & blacklist[i].set)) {
|
if (!(seccomp_opts & blacklist[i].set)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action = qemu_seccomp_get_action(blacklist[i].set);
|
||||||
rc = seccomp_rule_add_array(ctx, action, blacklist[i].num,
|
rc = seccomp_rule_add_array(ctx, action, blacklist[i].num,
|
||||||
blacklist[i].narg, blacklist[i].arg_cmp);
|
blacklist[i].narg, blacklist[i].arg_cmp);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
@@ -532,12 +532,12 @@
|
|||||||
#
|
#
|
||||||
# Suspend guest to disk.
|
# Suspend guest to disk.
|
||||||
#
|
#
|
||||||
# This command tries to execute the scripts provided by the pm-utils package.
|
# This command attempts to suspend the guest using three strategies, in this
|
||||||
# If it's not available, the suspend operation will be performed by manually
|
# order:
|
||||||
# writing to a sysfs file.
|
|
||||||
#
|
#
|
||||||
# For the best results it's strongly recommended to have the pm-utils
|
# - systemd hibernate
|
||||||
# package installed in the guest.
|
# - pm-utils (via pm-hibernate)
|
||||||
|
# - manual write into sysfs
|
||||||
#
|
#
|
||||||
# This command does NOT return a response on success. There is a high chance
|
# This command does NOT return a response on success. There is a high chance
|
||||||
# the command succeeded if the VM exits with a zero exit status or, when
|
# the command succeeded if the VM exits with a zero exit status or, when
|
||||||
@@ -560,12 +560,12 @@
|
|||||||
#
|
#
|
||||||
# Suspend guest to ram.
|
# Suspend guest to ram.
|
||||||
#
|
#
|
||||||
# This command tries to execute the scripts provided by the pm-utils package.
|
# This command attempts to suspend the guest using three strategies, in this
|
||||||
# If it's not available, the suspend operation will be performed by manually
|
# order:
|
||||||
# writing to a sysfs file.
|
|
||||||
#
|
#
|
||||||
# For the best results it's strongly recommended to have the pm-utils
|
# - systemd suspend
|
||||||
# package installed in the guest.
|
# - pm-utils (via pm-suspend)
|
||||||
|
# - manual write into sysfs
|
||||||
#
|
#
|
||||||
# IMPORTANT: guest-suspend-ram requires QEMU to support the 'system_wakeup'
|
# IMPORTANT: guest-suspend-ram requires QEMU to support the 'system_wakeup'
|
||||||
# command. Thus, it's *required* to query QEMU for the presence of the
|
# command. Thus, it's *required* to query QEMU for the presence of the
|
||||||
@@ -592,7 +592,10 @@
|
|||||||
#
|
#
|
||||||
# Save guest state to disk and suspend to ram.
|
# Save guest state to disk and suspend to ram.
|
||||||
#
|
#
|
||||||
# This command requires the pm-utils package to be installed in the guest.
|
# This command attempts to suspend the guest by executing, in this order:
|
||||||
|
#
|
||||||
|
# - systemd hybrid-sleep
|
||||||
|
# - pm-utils (via pm-suspend-hybrid)
|
||||||
#
|
#
|
||||||
# IMPORTANT: guest-suspend-hybrid requires QEMU to support the 'system_wakeup'
|
# IMPORTANT: guest-suspend-hybrid requires QEMU to support the 'system_wakeup'
|
||||||
# command. Thus, it's *required* to query QEMU for the presence of the
|
# command. Thus, it's *required* to query QEMU for the presence of the
|
||||||
|
@@ -5,7 +5,7 @@ qga-vss-dll-obj-y += requester.o provider.o install.o
|
|||||||
obj-qga-vss-dll-obj-y = $(addprefix $(obj)/, $(qga-vss-dll-obj-y))
|
obj-qga-vss-dll-obj-y = $(addprefix $(obj)/, $(qga-vss-dll-obj-y))
|
||||||
$(obj-qga-vss-dll-obj-y): QEMU_CXXFLAGS = $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls -fstack-protector-all -fstack-protector-strong, $(QEMU_CFLAGS)) -Wno-unknown-pragmas -Wno-delete-non-virtual-dtor
|
$(obj-qga-vss-dll-obj-y): QEMU_CXXFLAGS = $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls -fstack-protector-all -fstack-protector-strong, $(QEMU_CFLAGS)) -Wno-unknown-pragmas -Wno-delete-non-virtual-dtor
|
||||||
|
|
||||||
$(obj)/qga-vss.dll: LDFLAGS = -shared -Wl,--add-stdcall-alias,--enable-stdcall-fixup -lole32 -loleaut32 -lshlwapi -luuid -static
|
$(obj)/qga-vss.dll: LDFLAGS = -shared -Wl,--add-stdcall-alias,--enable-stdcall-fixup -lglib-2.0 -lole32 -loleaut32 -lshlwapi -luuid -lintl -lws2_32 -static
|
||||||
$(obj)/qga-vss.dll: $(obj-qga-vss-dll-obj-y) $(SRC_PATH)/$(obj)/qga-vss.def
|
$(obj)/qga-vss.dll: $(obj-qga-vss-dll-obj-y) $(SRC_PATH)/$(obj)/qga-vss.def
|
||||||
$(call quiet-command,$(CXX) -o $@ $(qga-vss-dll-obj-y) $(SRC_PATH)/qga/vss-win32/qga-vss.def $(CXXFLAGS) $(LDFLAGS),"LINK","$(TARGET_DIR)$@")
|
$(call quiet-command,$(CXX) -o $@ $(qga-vss-dll-obj-y) $(SRC_PATH)/qga/vss-win32/qga-vss.def $(CXXFLAGS) $(LDFLAGS),"LINK","$(TARGET_DIR)$@")
|
||||||
|
|
||||||
|
@@ -208,11 +208,13 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
if (ctxt->ap && ptr[1] != '%') {
|
if (ctxt->ap) {
|
||||||
parse_error(ctxt, token, "can't interpolate into string");
|
if (ptr[1] != '%') {
|
||||||
goto out;
|
parse_error(ctxt, token, "can't interpolate into string");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
}
|
}
|
||||||
ptr++;
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
default:
|
default:
|
||||||
cp = mod_utf8_codepoint(ptr, 6, &end);
|
cp = mod_utf8_codepoint(ptr, 6, &end);
|
||||||
|
@@ -300,6 +300,7 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
|
|||||||
*/
|
*/
|
||||||
while (q != (struct ipasfrag*)&fp->frag_link &&
|
while (q != (struct ipasfrag*)&fp->frag_link &&
|
||||||
ip->ip_off + ip->ip_len > q->ipf_off) {
|
ip->ip_off + ip->ip_len > q->ipf_off) {
|
||||||
|
struct ipasfrag *prev;
|
||||||
i = (ip->ip_off + ip->ip_len) - q->ipf_off;
|
i = (ip->ip_off + ip->ip_len) - q->ipf_off;
|
||||||
if (i < q->ipf_len) {
|
if (i < q->ipf_len) {
|
||||||
q->ipf_len -= i;
|
q->ipf_len -= i;
|
||||||
@@ -307,9 +308,10 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
|
|||||||
m_adj(dtom(slirp, q), i);
|
m_adj(dtom(slirp, q), i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
prev = q;
|
||||||
q = q->ipf_next;
|
q = q->ipf_next;
|
||||||
m_free(dtom(slirp, q->ipf_prev));
|
ip_deq(prev);
|
||||||
ip_deq(q->ipf_prev);
|
m_free(dtom(slirp, prev));
|
||||||
}
|
}
|
||||||
|
|
||||||
insert:
|
insert:
|
||||||
@@ -334,6 +336,8 @@ insert:
|
|||||||
q = fp->frag_link.next;
|
q = fp->frag_link.next;
|
||||||
m = dtom(slirp, q);
|
m = dtom(slirp, q);
|
||||||
|
|
||||||
|
int was_ext = m->m_flags & M_EXT;
|
||||||
|
|
||||||
q = (struct ipasfrag *) q->ipf_next;
|
q = (struct ipasfrag *) q->ipf_next;
|
||||||
while (q != (struct ipasfrag*)&fp->frag_link) {
|
while (q != (struct ipasfrag*)&fp->frag_link) {
|
||||||
struct mbuf *t = dtom(slirp, q);
|
struct mbuf *t = dtom(slirp, q);
|
||||||
@@ -350,13 +354,12 @@ insert:
|
|||||||
q = fp->frag_link.next;
|
q = fp->frag_link.next;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the fragments concatenated to an mbuf that's
|
* If the fragments concatenated to an mbuf that's bigger than the total
|
||||||
* bigger than the total size of the fragment, then and
|
* size of the fragment and the mbuf was not already using an m_ext buffer,
|
||||||
* m_ext buffer was alloced. But fp->ipq_next points to
|
* then an m_ext buffer was alloced. But fp->ipq_next points to the old
|
||||||
* the old buffer (in the mbuf), so we must point ip
|
* buffer (in the mbuf), so we must point ip into the new buffer.
|
||||||
* into the new buffer.
|
|
||||||
*/
|
*/
|
||||||
if (m->m_flags & M_EXT) {
|
if (!was_ext && m->m_flags & M_EXT) {
|
||||||
int delta = (char *)q - m->m_dat;
|
int delta = (char *)q - m->m_dat;
|
||||||
q = (struct ipasfrag *)(m->m_ext + delta);
|
q = (struct ipasfrag *)(m->m_ext + delta);
|
||||||
}
|
}
|
||||||
|
@@ -635,6 +635,11 @@ tcp_emu(struct socket *so, struct mbuf *m)
|
|||||||
socklen_t addrlen = sizeof(struct sockaddr_in);
|
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||||
struct sbuf *so_rcv = &so->so_rcv;
|
struct sbuf *so_rcv = &so->so_rcv;
|
||||||
|
|
||||||
|
if (m->m_len > so_rcv->sb_datalen
|
||||||
|
- (so_rcv->sb_wptr - so_rcv->sb_data)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
|
memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
|
||||||
so_rcv->sb_wptr += m->m_len;
|
so_rcv->sb_wptr += m->m_len;
|
||||||
so_rcv->sb_rptr += m->m_len;
|
so_rcv->sb_rptr += m->m_len;
|
||||||
@@ -657,12 +662,12 @@ tcp_emu(struct socket *so, struct mbuf *m)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
so_rcv->sb_cc = snprintf(so_rcv->sb_data,
|
||||||
|
so_rcv->sb_datalen,
|
||||||
|
"%d,%d\r\n", n1, n2);
|
||||||
|
so_rcv->sb_rptr = so_rcv->sb_data;
|
||||||
|
so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
|
||||||
}
|
}
|
||||||
so_rcv->sb_cc = snprintf(so_rcv->sb_data,
|
|
||||||
so_rcv->sb_datalen,
|
|
||||||
"%d,%d\r\n", n1, n2);
|
|
||||||
so_rcv->sb_rptr = so_rcv->sb_data;
|
|
||||||
so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
|
|
||||||
}
|
}
|
||||||
m_free(m);
|
m_free(m);
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -2493,8 +2493,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
|||||||
CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB |
|
CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB |
|
||||||
CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ |
|
CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ |
|
||||||
CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD |
|
CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD |
|
||||||
CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT |
|
CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT,
|
||||||
CPUID_7_0_EBX_INTEL_PT,
|
|
||||||
.features[FEAT_7_0_ECX] =
|
.features[FEAT_7_0_ECX] =
|
||||||
CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE |
|
CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE |
|
||||||
CPUID_7_0_ECX_AVX512VNNI,
|
CPUID_7_0_ECX_AVX512VNNI,
|
||||||
@@ -2546,7 +2545,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
|||||||
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||||
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
|
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
|
||||||
CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
|
CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
|
||||||
CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_INTEL_PT,
|
CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX,
|
||||||
.features[FEAT_7_0_ECX] =
|
.features[FEAT_7_0_ECX] =
|
||||||
CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU |
|
CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU |
|
||||||
CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI |
|
CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI |
|
||||||
@@ -2604,8 +2603,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
|||||||
CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB |
|
CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB |
|
||||||
CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ |
|
CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ |
|
||||||
CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD |
|
CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD |
|
||||||
CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT |
|
CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT,
|
||||||
CPUID_7_0_EBX_INTEL_PT,
|
|
||||||
.features[FEAT_7_0_ECX] =
|
.features[FEAT_7_0_ECX] =
|
||||||
CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU |
|
CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU |
|
||||||
CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI |
|
CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI |
|
||||||
@@ -2613,8 +2611,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
|||||||
CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG |
|
CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG |
|
||||||
CPUID_7_0_ECX_AVX512_VPOPCNTDQ | CPUID_7_0_ECX_LA57,
|
CPUID_7_0_ECX_AVX512_VPOPCNTDQ | CPUID_7_0_ECX_LA57,
|
||||||
.features[FEAT_7_0_EDX] =
|
.features[FEAT_7_0_EDX] =
|
||||||
CPUID_7_0_EDX_PCONFIG | CPUID_7_0_EDX_SPEC_CTRL |
|
CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD,
|
||||||
CPUID_7_0_EDX_SPEC_CTRL_SSBD,
|
|
||||||
/* Missing: XSAVES (not supported by some Linux versions,
|
/* Missing: XSAVES (not supported by some Linux versions,
|
||||||
* including v4.1 to v4.12).
|
* including v4.1 to v4.12).
|
||||||
* KVM doesn't yet expose any XSAVES state save component,
|
* KVM doesn't yet expose any XSAVES state save component,
|
||||||
|
@@ -2226,6 +2226,7 @@ static TCGv gen_get_sr(DisasContext *s)
|
|||||||
sr = tcg_temp_new();
|
sr = tcg_temp_new();
|
||||||
tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
|
tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
|
||||||
tcg_gen_or_i32(sr, sr, ccr);
|
tcg_gen_or_i32(sr, sr, ccr);
|
||||||
|
tcg_temp_free(ccr);
|
||||||
return sr;
|
return sr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -143,7 +143,7 @@ GEN_VXFORM(vaddsws, 0, 14),
|
|||||||
GEN_VXFORM_DUAL(vsububs, bcdadd, 0, 24, PPC_ALTIVEC, PPC_NONE),
|
GEN_VXFORM_DUAL(vsububs, bcdadd, 0, 24, PPC_ALTIVEC, PPC_NONE),
|
||||||
GEN_VXFORM_DUAL(vsubuhs, bcdsub, 0, 25, PPC_ALTIVEC, PPC_NONE),
|
GEN_VXFORM_DUAL(vsubuhs, bcdsub, 0, 25, PPC_ALTIVEC, PPC_NONE),
|
||||||
GEN_VXFORM(vsubuws, 0, 26),
|
GEN_VXFORM(vsubuws, 0, 26),
|
||||||
GEN_VXFORM_DUAL(vsubsbs, bcdtrunc, 0, 28, PPC_NONE, PPC2_ISA300),
|
GEN_VXFORM_DUAL(vsubsbs, bcdtrunc, 0, 28, PPC_ALTIVEC, PPC2_ISA300),
|
||||||
GEN_VXFORM(vsubshs, 0, 29),
|
GEN_VXFORM(vsubshs, 0, 29),
|
||||||
GEN_VXFORM_DUAL(vsubsws, xpnd04_2, 0, 30, PPC_ALTIVEC, PPC_NONE),
|
GEN_VXFORM_DUAL(vsubsws, xpnd04_2, 0, 30, PPC_ALTIVEC, PPC_NONE),
|
||||||
GEN_VXFORM_207(vadduqm, 0, 4),
|
GEN_VXFORM_207(vadduqm, 0, 4),
|
||||||
|
@@ -1297,6 +1297,8 @@ static void init_ignored_base_feat(void)
|
|||||||
S390_FEAT_KM_TDEA_192,
|
S390_FEAT_KM_TDEA_192,
|
||||||
S390_FEAT_KIMD_SHA_1,
|
S390_FEAT_KIMD_SHA_1,
|
||||||
S390_FEAT_KLMD_SHA_1,
|
S390_FEAT_KLMD_SHA_1,
|
||||||
|
/* CSSKE is deprecated on newer generations */
|
||||||
|
S390_FEAT_CONDITIONAL_SSKE,
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@@ -130,7 +130,7 @@ out:
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
hw_error("Unhandled diag308 subcode %" PRIx64, subcode);
|
s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, ra);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -70,6 +70,7 @@ check-unit-y += tests/test-bdrv-drain$(EXESUF)
|
|||||||
check-unit-y += tests/test-blockjob$(EXESUF)
|
check-unit-y += tests/test-blockjob$(EXESUF)
|
||||||
check-unit-y += tests/test-blockjob-txn$(EXESUF)
|
check-unit-y += tests/test-blockjob-txn$(EXESUF)
|
||||||
check-unit-y += tests/test-block-backend$(EXESUF)
|
check-unit-y += tests/test-block-backend$(EXESUF)
|
||||||
|
check-unit-y += tests/test-block-iothread$(EXESUF)
|
||||||
check-unit-y += tests/test-image-locking$(EXESUF)
|
check-unit-y += tests/test-image-locking$(EXESUF)
|
||||||
check-unit-y += tests/test-x86-cpuid$(EXESUF)
|
check-unit-y += tests/test-x86-cpuid$(EXESUF)
|
||||||
# all code tested by test-x86-cpuid is inside topology.h
|
# all code tested by test-x86-cpuid is inside topology.h
|
||||||
@@ -538,6 +539,7 @@ tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(te
|
|||||||
tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
|
tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
|
||||||
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
|
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
|
||||||
tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y)
|
tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y)
|
||||||
|
tests/test-block-iothread$(EXESUF): tests/test-block-iothread.o $(test-block-obj-y) $(test-util-obj-y)
|
||||||
tests/test-image-locking$(EXESUF): tests/test-image-locking.o $(test-block-obj-y) $(test-util-obj-y)
|
tests/test-image-locking$(EXESUF): tests/test-image-locking.o $(test-block-obj-y) $(test-util-obj-y)
|
||||||
tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y)
|
tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y)
|
||||||
tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y)
|
tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y)
|
||||||
|
@@ -175,6 +175,11 @@ static void utf8_string(void)
|
|||||||
"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
|
"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
|
||||||
"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
|
"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
|
||||||
"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5",
|
"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5",
|
||||||
|
},
|
||||||
|
/* '%' character when not interpolating */
|
||||||
|
{
|
||||||
|
"100%",
|
||||||
|
"100%",
|
||||||
},
|
},
|
||||||
/* 2 Boundary condition test cases */
|
/* 2 Boundary condition test cases */
|
||||||
/* 2.1 First possible sequence of a certain length */
|
/* 2.1 First possible sequence of a certain length */
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# Test qemu-img vs. unaligned images
|
# Test qemu-img vs. unaligned images
|
||||||
|
# (See also 253, which is the O_DIRECT version)
|
||||||
#
|
#
|
||||||
# Copyright (C) 2018 Red Hat, Inc.
|
# Copyright (C) 2018 Red Hat, Inc.
|
||||||
#
|
#
|
||||||
@@ -37,6 +38,9 @@ _supported_fmt raw
|
|||||||
_supported_proto file
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
|
_default_cache_mode writeback
|
||||||
|
_supported_cache_modes writeback writethrough unsafe
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "=== Check mapping of unaligned raw image ==="
|
echo "=== Check mapping of unaligned raw image ==="
|
||||||
echo
|
echo
|
||||||
|
@@ -82,11 +82,15 @@ echo
|
|||||||
echo '=== Force cancel job paused in error state ==='
|
echo '=== Force cancel job paused in error state ==='
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
# Filter out BLOCK_JOB_ERROR events because they may or may not occur.
|
||||||
|
# Cancelling the job means resuming it for a bit before it is actually
|
||||||
|
# aborted, and in that time it may or may not re-encounter the error.
|
||||||
success_or_failure="y" _send_qemu_cmd $QEMU_HANDLE \
|
success_or_failure="y" _send_qemu_cmd $QEMU_HANDLE \
|
||||||
"{'execute': 'block-job-cancel',
|
"{'execute': 'block-job-cancel',
|
||||||
'arguments': { 'device': 'testdisk',
|
'arguments': { 'device': 'testdisk',
|
||||||
'force': true}}" \
|
'force': true}}" \
|
||||||
"BLOCK_JOB_CANCELLED" "Assertion"
|
"BLOCK_JOB_CANCELLED" "Assertion" \
|
||||||
|
| grep -v '"BLOCK_JOB_ERROR"'
|
||||||
|
|
||||||
# success, all done
|
# success, all done
|
||||||
echo "*** done"
|
echo "*** done"
|
||||||
|
@@ -17,7 +17,6 @@ wrote 2097152/2097152 bytes at offset 0
|
|||||||
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "testdisk", "operation": "write", "action": "stop"}}
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "testdisk"}}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "testdisk"}}
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "testdisk", "len": 2097152, "offset": 1048576, "speed": 0, "type": "mirror"}}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "testdisk", "len": 2097152, "offset": 1048576, "speed": 0, "type": "mirror"}}
|
||||||
*** done
|
*** done
|
||||||
|
@@ -49,7 +49,9 @@ qemu_img_create('-f', iotests.imgfmt, '-o', 'preallocation=metadata', disk,
|
|||||||
str(size))
|
str(size))
|
||||||
|
|
||||||
vm = QEMUMachine(iotests.qemu_prog)
|
vm = QEMUMachine(iotests.qemu_prog)
|
||||||
vm.add_args('-machine', 'pc,accel=kvm')
|
vm.add_args('-machine', 'accel=kvm')
|
||||||
|
if iotests.qemu_default_machine == 's390-ccw-virtio':
|
||||||
|
vm.add_args('-no-shutdown')
|
||||||
vm.add_args('-drive', 'id=src,file=' + disk)
|
vm.add_args('-drive', 'id=src,file=' + disk)
|
||||||
vm.launch()
|
vm.launch()
|
||||||
|
|
||||||
|
84
tests/qemu-iotests/253
Executable file
84
tests/qemu-iotests/253
Executable file
@@ -0,0 +1,84 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Test qemu-img vs. unaligned images; O_DIRECT version
|
||||||
|
# (Originates from 221)
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
seq="$(basename $0)"
|
||||||
|
echo "QA output created by $seq"
|
||||||
|
|
||||||
|
status=1 # failure is the default!
|
||||||
|
|
||||||
|
_cleanup()
|
||||||
|
{
|
||||||
|
_cleanup_test_img
|
||||||
|
}
|
||||||
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
|
# get standard environment, filters and checks
|
||||||
|
. ./common.rc
|
||||||
|
. ./common.filter
|
||||||
|
|
||||||
|
_supported_fmt raw
|
||||||
|
_supported_proto file
|
||||||
|
_supported_os Linux
|
||||||
|
|
||||||
|
_default_cache_mode none
|
||||||
|
_supported_cache_modes none directsync
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Check mapping of unaligned raw image ==="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# We do not know how large a physical sector is, but it is certainly
|
||||||
|
# going to be a factor of 1 MB
|
||||||
|
size=$((1 * 1024 * 1024 - 1))
|
||||||
|
|
||||||
|
# qemu-img create rounds size up to BDRV_SECTOR_SIZE
|
||||||
|
_make_test_img $size
|
||||||
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG,cache.direct=on" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
|
# so we resize it and check again
|
||||||
|
truncate --size=$size "$TEST_IMG"
|
||||||
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG,cache.direct=on" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
|
# qemu-io with O_DIRECT always writes whole physical sectors. Again,
|
||||||
|
# we do not know how large a physical sector is, so we just start
|
||||||
|
# writing from a 64 kB boundary, which should always be aligned.
|
||||||
|
offset=$((1 * 1024 * 1024 - 64 * 1024))
|
||||||
|
$QEMU_IO -c "w $offset $((size - offset))" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG,cache.direct=on" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
|
# Resize it and check again -- contrary to 221, we may not get partial
|
||||||
|
# sectors here, so there should be only two areas (one zero, one
|
||||||
|
# data).
|
||||||
|
truncate --size=$size "$TEST_IMG"
|
||||||
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG,cache.direct=on" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
|
# success, all done
|
||||||
|
echo '*** done'
|
||||||
|
rm -f $seq.full
|
||||||
|
status=0
|
14
tests/qemu-iotests/253.out
Normal file
14
tests/qemu-iotests/253.out
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
QA output created by 253
|
||||||
|
|
||||||
|
=== Check mapping of unaligned raw image ===
|
||||||
|
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048575
|
||||||
|
[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
|
||||||
|
[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
|
||||||
|
wrote 65535/65535 bytes at offset 983040
|
||||||
|
63.999 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
|
||||||
|
{ "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
|
||||||
|
[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
|
||||||
|
{ "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
|
||||||
|
*** done
|
@@ -233,3 +233,4 @@
|
|||||||
233 auto quick
|
233 auto quick
|
||||||
234 auto quick migration
|
234 auto quick migration
|
||||||
235 auto quick
|
235 auto quick
|
||||||
|
253 rw auto quick
|
||||||
|
372
tests/test-block-iothread.c
Normal file
372
tests/test-block-iothread.c
Normal file
@@ -0,0 +1,372 @@
|
|||||||
|
/*
|
||||||
|
* Block tests for iothreads
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Kevin Wolf <kwolf@redhat.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "block/block.h"
|
||||||
|
#include "block/blockjob_int.h"
|
||||||
|
#include "sysemu/block-backend.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "iothread.h"
|
||||||
|
|
||||||
|
static int coroutine_fn bdrv_test_co_prwv(BlockDriverState *bs,
|
||||||
|
uint64_t offset, uint64_t bytes,
|
||||||
|
QEMUIOVector *qiov, int flags)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
|
||||||
|
int64_t offset, int bytes)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int coroutine_fn
|
||||||
|
bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset,
|
||||||
|
PreallocMode prealloc, Error **errp)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int coroutine_fn bdrv_test_co_block_status(BlockDriverState *bs,
|
||||||
|
bool want_zero,
|
||||||
|
int64_t offset, int64_t count,
|
||||||
|
int64_t *pnum, int64_t *map,
|
||||||
|
BlockDriverState **file)
|
||||||
|
{
|
||||||
|
*pnum = count;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BlockDriver bdrv_test = {
|
||||||
|
.format_name = "test",
|
||||||
|
.instance_size = 1,
|
||||||
|
|
||||||
|
.bdrv_co_preadv = bdrv_test_co_prwv,
|
||||||
|
.bdrv_co_pwritev = bdrv_test_co_prwv,
|
||||||
|
.bdrv_co_pdiscard = bdrv_test_co_pdiscard,
|
||||||
|
.bdrv_co_truncate = bdrv_test_co_truncate,
|
||||||
|
.bdrv_co_block_status = bdrv_test_co_block_status,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void test_sync_op_pread(BdrvChild *c)
|
||||||
|
{
|
||||||
|
uint8_t buf[512];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
ret = bdrv_pread(c, 0, buf, sizeof(buf));
|
||||||
|
g_assert_cmpint(ret, ==, 512);
|
||||||
|
|
||||||
|
/* Early error: Negative offset */
|
||||||
|
ret = bdrv_pread(c, -2, buf, sizeof(buf));
|
||||||
|
g_assert_cmpint(ret, ==, -EIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_pwrite(BdrvChild *c)
|
||||||
|
{
|
||||||
|
uint8_t buf[512];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
ret = bdrv_pwrite(c, 0, buf, sizeof(buf));
|
||||||
|
g_assert_cmpint(ret, ==, 512);
|
||||||
|
|
||||||
|
/* Early error: Negative offset */
|
||||||
|
ret = bdrv_pwrite(c, -2, buf, sizeof(buf));
|
||||||
|
g_assert_cmpint(ret, ==, -EIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_blk_pread(BlockBackend *blk)
|
||||||
|
{
|
||||||
|
uint8_t buf[512];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
ret = blk_pread(blk, 0, buf, sizeof(buf));
|
||||||
|
g_assert_cmpint(ret, ==, 512);
|
||||||
|
|
||||||
|
/* Early error: Negative offset */
|
||||||
|
ret = blk_pread(blk, -2, buf, sizeof(buf));
|
||||||
|
g_assert_cmpint(ret, ==, -EIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_blk_pwrite(BlockBackend *blk)
|
||||||
|
{
|
||||||
|
uint8_t buf[512];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
ret = blk_pwrite(blk, 0, buf, sizeof(buf), 0);
|
||||||
|
g_assert_cmpint(ret, ==, 512);
|
||||||
|
|
||||||
|
/* Early error: Negative offset */
|
||||||
|
ret = blk_pwrite(blk, -2, buf, sizeof(buf), 0);
|
||||||
|
g_assert_cmpint(ret, ==, -EIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_load_vmstate(BdrvChild *c)
|
||||||
|
{
|
||||||
|
uint8_t buf[512];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Error: Driver does not support snapshots */
|
||||||
|
ret = bdrv_load_vmstate(c->bs, buf, 0, sizeof(buf));
|
||||||
|
g_assert_cmpint(ret, ==, -ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_save_vmstate(BdrvChild *c)
|
||||||
|
{
|
||||||
|
uint8_t buf[512];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Error: Driver does not support snapshots */
|
||||||
|
ret = bdrv_save_vmstate(c->bs, buf, 0, sizeof(buf));
|
||||||
|
g_assert_cmpint(ret, ==, -ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_pdiscard(BdrvChild *c)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Normal success path */
|
||||||
|
c->bs->open_flags |= BDRV_O_UNMAP;
|
||||||
|
ret = bdrv_pdiscard(c, 0, 512);
|
||||||
|
g_assert_cmpint(ret, ==, 0);
|
||||||
|
|
||||||
|
/* Early success: UNMAP not supported */
|
||||||
|
c->bs->open_flags &= ~BDRV_O_UNMAP;
|
||||||
|
ret = bdrv_pdiscard(c, 0, 512);
|
||||||
|
g_assert_cmpint(ret, ==, 0);
|
||||||
|
|
||||||
|
/* Early error: Negative offset */
|
||||||
|
ret = bdrv_pdiscard(c, -2, 512);
|
||||||
|
g_assert_cmpint(ret, ==, -EIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_blk_pdiscard(BlockBackend *blk)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Early success: UNMAP not supported */
|
||||||
|
ret = blk_pdiscard(blk, 0, 512);
|
||||||
|
g_assert_cmpint(ret, ==, 0);
|
||||||
|
|
||||||
|
/* Early error: Negative offset */
|
||||||
|
ret = blk_pdiscard(blk, -2, 512);
|
||||||
|
g_assert_cmpint(ret, ==, -EIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_truncate(BdrvChild *c)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Normal success path */
|
||||||
|
ret = bdrv_truncate(c, 65536, PREALLOC_MODE_OFF, NULL);
|
||||||
|
g_assert_cmpint(ret, ==, 0);
|
||||||
|
|
||||||
|
/* Early error: Negative offset */
|
||||||
|
ret = bdrv_truncate(c, -2, PREALLOC_MODE_OFF, NULL);
|
||||||
|
g_assert_cmpint(ret, ==, -EINVAL);
|
||||||
|
|
||||||
|
/* Error: Read-only image */
|
||||||
|
c->bs->read_only = true;
|
||||||
|
c->bs->open_flags &= ~BDRV_O_RDWR;
|
||||||
|
|
||||||
|
ret = bdrv_truncate(c, 65536, PREALLOC_MODE_OFF, NULL);
|
||||||
|
g_assert_cmpint(ret, ==, -EACCES);
|
||||||
|
|
||||||
|
c->bs->read_only = false;
|
||||||
|
c->bs->open_flags |= BDRV_O_RDWR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_block_status(BdrvChild *c)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int64_t n;
|
||||||
|
|
||||||
|
/* Normal success path */
|
||||||
|
ret = bdrv_is_allocated(c->bs, 0, 65536, &n);
|
||||||
|
g_assert_cmpint(ret, ==, 0);
|
||||||
|
|
||||||
|
/* Early success: No driver support */
|
||||||
|
bdrv_test.bdrv_co_block_status = NULL;
|
||||||
|
ret = bdrv_is_allocated(c->bs, 0, 65536, &n);
|
||||||
|
g_assert_cmpint(ret, ==, 1);
|
||||||
|
|
||||||
|
/* Early success: bytes = 0 */
|
||||||
|
ret = bdrv_is_allocated(c->bs, 0, 0, &n);
|
||||||
|
g_assert_cmpint(ret, ==, 0);
|
||||||
|
|
||||||
|
/* Early success: Offset > image size*/
|
||||||
|
ret = bdrv_is_allocated(c->bs, 0x1000000, 0x1000000, &n);
|
||||||
|
g_assert_cmpint(ret, ==, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_flush(BdrvChild *c)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Normal success path */
|
||||||
|
ret = bdrv_flush(c->bs);
|
||||||
|
g_assert_cmpint(ret, ==, 0);
|
||||||
|
|
||||||
|
/* Early success: Read-only image */
|
||||||
|
c->bs->read_only = true;
|
||||||
|
c->bs->open_flags &= ~BDRV_O_RDWR;
|
||||||
|
|
||||||
|
ret = bdrv_flush(c->bs);
|
||||||
|
g_assert_cmpint(ret, ==, 0);
|
||||||
|
|
||||||
|
c->bs->read_only = false;
|
||||||
|
c->bs->open_flags |= BDRV_O_RDWR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_blk_flush(BlockBackend *blk)
|
||||||
|
{
|
||||||
|
BlockDriverState *bs = blk_bs(blk);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Normal success path */
|
||||||
|
ret = blk_flush(blk);
|
||||||
|
g_assert_cmpint(ret, ==, 0);
|
||||||
|
|
||||||
|
/* Early success: Read-only image */
|
||||||
|
bs->read_only = true;
|
||||||
|
bs->open_flags &= ~BDRV_O_RDWR;
|
||||||
|
|
||||||
|
ret = blk_flush(blk);
|
||||||
|
g_assert_cmpint(ret, ==, 0);
|
||||||
|
|
||||||
|
bs->read_only = false;
|
||||||
|
bs->open_flags |= BDRV_O_RDWR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_check(BdrvChild *c)
|
||||||
|
{
|
||||||
|
BdrvCheckResult result;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Error: Driver does not implement check */
|
||||||
|
ret = bdrv_check(c->bs, &result, 0);
|
||||||
|
g_assert_cmpint(ret, ==, -ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sync_op_invalidate_cache(BdrvChild *c)
|
||||||
|
{
|
||||||
|
/* Early success: Image is not inactive */
|
||||||
|
bdrv_invalidate_cache(c->bs, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct SyncOpTest {
|
||||||
|
const char *name;
|
||||||
|
void (*fn)(BdrvChild *c);
|
||||||
|
void (*blkfn)(BlockBackend *blk);
|
||||||
|
} SyncOpTest;
|
||||||
|
|
||||||
|
const SyncOpTest sync_op_tests[] = {
|
||||||
|
{
|
||||||
|
.name = "/sync-op/pread",
|
||||||
|
.fn = test_sync_op_pread,
|
||||||
|
.blkfn = test_sync_op_blk_pread,
|
||||||
|
}, {
|
||||||
|
.name = "/sync-op/pwrite",
|
||||||
|
.fn = test_sync_op_pwrite,
|
||||||
|
.blkfn = test_sync_op_blk_pwrite,
|
||||||
|
}, {
|
||||||
|
.name = "/sync-op/load_vmstate",
|
||||||
|
.fn = test_sync_op_load_vmstate,
|
||||||
|
}, {
|
||||||
|
.name = "/sync-op/save_vmstate",
|
||||||
|
.fn = test_sync_op_save_vmstate,
|
||||||
|
}, {
|
||||||
|
.name = "/sync-op/pdiscard",
|
||||||
|
.fn = test_sync_op_pdiscard,
|
||||||
|
.blkfn = test_sync_op_blk_pdiscard,
|
||||||
|
}, {
|
||||||
|
.name = "/sync-op/truncate",
|
||||||
|
.fn = test_sync_op_truncate,
|
||||||
|
}, {
|
||||||
|
.name = "/sync-op/block_status",
|
||||||
|
.fn = test_sync_op_block_status,
|
||||||
|
}, {
|
||||||
|
.name = "/sync-op/flush",
|
||||||
|
.fn = test_sync_op_flush,
|
||||||
|
.blkfn = test_sync_op_blk_flush,
|
||||||
|
}, {
|
||||||
|
.name = "/sync-op/check",
|
||||||
|
.fn = test_sync_op_check,
|
||||||
|
}, {
|
||||||
|
.name = "/sync-op/invalidate_cache",
|
||||||
|
.fn = test_sync_op_invalidate_cache,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Test synchronous operations that run in a different iothread, so we have to
|
||||||
|
* poll for the coroutine there to return. */
|
||||||
|
static void test_sync_op(const void *opaque)
|
||||||
|
{
|
||||||
|
const SyncOpTest *t = opaque;
|
||||||
|
IOThread *iothread = iothread_new();
|
||||||
|
AioContext *ctx = iothread_get_aio_context(iothread);
|
||||||
|
BlockBackend *blk;
|
||||||
|
BlockDriverState *bs;
|
||||||
|
BdrvChild *c;
|
||||||
|
|
||||||
|
blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
|
||||||
|
bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
|
||||||
|
bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
|
||||||
|
blk_insert_bs(blk, bs, &error_abort);
|
||||||
|
c = QLIST_FIRST(&bs->parents);
|
||||||
|
|
||||||
|
blk_set_aio_context(blk, ctx);
|
||||||
|
aio_context_acquire(ctx);
|
||||||
|
t->fn(c);
|
||||||
|
if (t->blkfn) {
|
||||||
|
t->blkfn(blk);
|
||||||
|
}
|
||||||
|
aio_context_release(ctx);
|
||||||
|
blk_set_aio_context(blk, qemu_get_aio_context());
|
||||||
|
|
||||||
|
bdrv_unref(bs);
|
||||||
|
blk_unref(blk);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
bdrv_init();
|
||||||
|
qemu_init_main_loop(&error_abort);
|
||||||
|
|
||||||
|
g_test_init(&argc, &argv, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(sync_op_tests); i++) {
|
||||||
|
const SyncOpTest *t = &sync_op_tests[i];
|
||||||
|
g_test_add_data_func(t->name, t, test_sync_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_test_run();
|
||||||
|
}
|
@@ -754,7 +754,7 @@ const char *qemu_ether_ntoa(const MACAddr *mac)
|
|||||||
char *size_to_str(uint64_t val)
|
char *size_to_str(uint64_t val)
|
||||||
{
|
{
|
||||||
static const char *suffixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" };
|
static const char *suffixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" };
|
||||||
unsigned long div;
|
uint64_t div;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user