Compare commits
222 Commits
v2.7.0-rc5
...
pull-ui-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e10c3ecfc | ||
|
|
93ca519ec4 | ||
|
|
99a9ef44dc | ||
|
|
bba4e1b591 | ||
|
|
7263da7804 | ||
|
|
d4c61988b8 | ||
|
|
90d6f60d07 | ||
|
|
d9269b274a | ||
|
|
a5d2f44d0d | ||
|
|
c569c537e5 | ||
|
|
a26f7f2cb8 | ||
|
|
fc0b9b0e1c | ||
|
|
947b205fdb | ||
|
|
71d19fc513 | ||
|
|
96a3d98d2c | ||
|
|
3eff376977 | ||
|
|
4a1e48beca | ||
|
|
297a75e6c5 | ||
|
|
104e70cae7 | ||
|
|
4b7f91ed02 | ||
|
|
d9997d89a4 | ||
|
|
14c985cffa | ||
|
|
a4d3c83476 | ||
|
|
e3aab6c7f3 | ||
|
|
a8bba0ada4 | ||
|
|
c2a57aae9a | ||
|
|
5f31bbf101 | ||
|
|
33e60e0198 | ||
|
|
e2dd21e510 | ||
|
|
5b1ded224f | ||
|
|
34e46f604d | ||
|
|
822e36ca35 | ||
|
|
f73480c36f | ||
|
|
e9529768d4 | ||
|
|
5ba344013c | ||
|
|
3e6c0c4c2c | ||
|
|
8197e24c38 | ||
|
|
ff1685a333 | ||
|
|
354fb471bd | ||
|
|
8ea753718b | ||
|
|
ac64c5fdf8 | ||
|
|
d80fe99de4 | ||
|
|
e305a16510 | ||
|
|
bd794065ff | ||
|
|
3972a4884d | ||
|
|
265804b5d7 | ||
|
|
d55f295b2b | ||
|
|
4ae3c0e27f | ||
|
|
d6f723b513 | ||
|
|
3e3e302ff3 | ||
|
|
2aa67a9196 | ||
|
|
5c7e3e9fb1 | ||
|
|
1e2713384c | ||
|
|
f8042deafa | ||
|
|
ae2f659ca5 | ||
|
|
00263139f8 | ||
|
|
a351b4b06e | ||
|
|
341edc0c47 | ||
|
|
b5dc88ce24 | ||
|
|
08f4e8d23d | ||
|
|
c977257045 | ||
|
|
9af4c174a3 | ||
|
|
59351d9b40 | ||
|
|
0813cbf913 | ||
|
|
d2ab58ffc9 | ||
|
|
29531542bc | ||
|
|
32f5f50dad | ||
|
|
a007b19b37 | ||
|
|
76a3d2f750 | ||
|
|
d0f6ced17f | ||
|
|
accc60c47c | ||
|
|
4f5d326046 | ||
|
|
ba4a8df83f | ||
|
|
dd2fa4f72d | ||
|
|
3654fa95bc | ||
|
|
ce9863b797 | ||
|
|
15848410af | ||
|
|
787bbe3711 | ||
|
|
4004c1dbca | ||
|
|
5644a17567 | ||
|
|
f7cc8466f1 | ||
|
|
377070595a | ||
|
|
217f6b8805 | ||
|
|
4110b586de | ||
|
|
b07c32dc4b | ||
|
|
5817355ed0 | ||
|
|
65f2475f1f | ||
|
|
5f2a625452 | ||
|
|
fbc3b39b39 | ||
|
|
c9f82d013b | ||
|
|
22b56ee568 | ||
|
|
3433b732a4 | ||
|
|
b00a3b3648 | ||
|
|
573708e329 | ||
|
|
72073dcce0 | ||
|
|
8c8966e218 | ||
|
|
57a2988b6f | ||
|
|
a13f0a9bc4 | ||
|
|
0f72b7c682 | ||
|
|
bd6fefe71c | ||
|
|
af6d376ea1 | ||
|
|
e41029b378 | ||
|
|
1b7d17cae4 | ||
|
|
ef24726e48 | ||
|
|
44f35bd1ac | ||
|
|
a93ecff935 | ||
|
|
f63fbc00d4 | ||
|
|
3014427af5 | ||
|
|
0304af897b | ||
|
|
8b25cdd371 | ||
|
|
4083de6b53 | ||
|
|
f96511215d | ||
|
|
db789c6cd3 | ||
|
|
323ad19bcc | ||
|
|
5f29cc8292 | ||
|
|
aeeb044c7b | ||
|
|
dc2ee038da | ||
|
|
082ce33005 | ||
|
|
b35344e4a0 | ||
|
|
e91d95b277 | ||
|
|
063cf14fe3 | ||
|
|
af2c66200e | ||
|
|
f2442ef93c | ||
|
|
c5b2b9ce12 | ||
|
|
eb640b13a3 | ||
|
|
706d64675a | ||
|
|
7804c353a9 | ||
|
|
1b1746a436 | ||
|
|
7faae0b36e | ||
|
|
c827c06a4d | ||
|
|
f460be435f | ||
|
|
e0fe723c24 | ||
|
|
c2da8a8b90 | ||
|
|
2926375cff | ||
|
|
f9ae6bcf1d | ||
|
|
f1a47d08ef | ||
|
|
4e82ef0502 | ||
|
|
137974cea3 | ||
|
|
b18b604334 | ||
|
|
0031e0d683 | ||
|
|
e09484efbc | ||
|
|
c85d21c73b | ||
|
|
07059effd1 | ||
|
|
34821036cd | ||
|
|
3b84c25cc7 | ||
|
|
392529cb77 | ||
|
|
a366930780 | ||
|
|
3fad3252a3 | ||
|
|
059be520d5 | ||
|
|
4dd4200ee7 | ||
|
|
1c07e01b61 | ||
|
|
026546e6c3 | ||
|
|
80560137cf | ||
|
|
7c72ac49ae | ||
|
|
0754f60429 | ||
|
|
ad5afd07b6 | ||
|
|
6c064de1e0 | ||
|
|
8b3d6cb1fa | ||
|
|
90229ebbad | ||
|
|
dced7eec3c | ||
|
|
7824174462 | ||
|
|
6efadc9050 | ||
|
|
41868f846d | ||
|
|
085c915019 | ||
|
|
30e7d092b2 | ||
|
|
1fd66154fd | ||
|
|
6546d0dba6 | ||
|
|
cdafe92961 | ||
|
|
cc728d1493 | ||
|
|
630eb0faf4 | ||
|
|
8eb1b9db55 | ||
|
|
a4d50b1d2a | ||
|
|
0a85241756 | ||
|
|
e7f98f2f92 | ||
|
|
c0088d79a7 | ||
|
|
1562047c89 | ||
|
|
1b7f01d966 | ||
|
|
0e438cdc93 | ||
|
|
8b2bd09338 | ||
|
|
980e66216f | ||
|
|
00198ecc77 | ||
|
|
e1b5c51f4c | ||
|
|
3b7b123659 | ||
|
|
13b9414b57 | ||
|
|
dc7a4a9ed1 | ||
|
|
81206a8987 | ||
|
|
3ea1a09111 | ||
|
|
35fadca80e | ||
|
|
655923df4b | ||
|
|
f2b95a1231 | ||
|
|
b2c622d365 | ||
|
|
a2c0ca6f55 | ||
|
|
fcccefc57f | ||
|
|
29a298af9d | ||
|
|
751e2f0698 | ||
|
|
fe5c1355e7 | ||
|
|
094138d09e | ||
|
|
cd7fca952c | ||
|
|
0524e93a3f | ||
|
|
b7e4fa2242 | ||
|
|
7b5dca3f02 | ||
|
|
75dfd402a7 | ||
|
|
2dfb4c033f | ||
|
|
07eec65272 | ||
|
|
cef34eebf3 | ||
|
|
1d13b167fd | ||
|
|
b6c1bae5df | ||
|
|
9ef6e505f0 | ||
|
|
67c75f3dff | ||
|
|
fc4b84b1c6 | ||
|
|
b60fae32ff | ||
|
|
dbdfea9226 | ||
|
|
882b3b9769 | ||
|
|
5759db1936 | ||
|
|
f2cab7f148 | ||
|
|
989fd865f5 | ||
|
|
0c2a16a4dc | ||
|
|
0d36d79192 | ||
|
|
61823988df | ||
|
|
e87d397e5e | ||
|
|
1dc33ed90b | ||
|
|
4ada797b05 |
@@ -212,7 +212,7 @@ hmp-commands-info.h: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
|
|||||||
qmp-commands-old.h: $(SRC_PATH)/qmp-commands.hx $(SRC_PATH)/scripts/hxtool
|
qmp-commands-old.h: $(SRC_PATH)/qmp-commands.hx $(SRC_PATH)/scripts/hxtool
|
||||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
|
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
|
||||||
|
|
||||||
clean:
|
clean: clean-target
|
||||||
rm -f *.a *~ $(PROGS)
|
rm -f *.a *~ $(PROGS)
|
||||||
rm -f $(shell find . -name '*.[od]')
|
rm -f $(shell find . -name '*.[od]')
|
||||||
rm -f hmp-commands.h qmp-commands-old.h gdbstub-xml.c
|
rm -f hmp-commands.h qmp-commands-old.h gdbstub-xml.c
|
||||||
|
|||||||
2
block.c
2
block.c
@@ -25,6 +25,7 @@
|
|||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "block/block_int.h"
|
#include "block/block_int.h"
|
||||||
#include "block/blockjob.h"
|
#include "block/blockjob.h"
|
||||||
|
#include "block/nbd.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "qapi/qmp/qerror.h"
|
#include "qapi/qmp/qerror.h"
|
||||||
@@ -2206,6 +2207,7 @@ static void bdrv_close(BlockDriverState *bs)
|
|||||||
void bdrv_close_all(void)
|
void bdrv_close_all(void)
|
||||||
{
|
{
|
||||||
block_job_cancel_sync_all();
|
block_job_cancel_sync_all();
|
||||||
|
nbd_export_close_all();
|
||||||
|
|
||||||
/* Drop references from requests still in flight, such as canceled block
|
/* Drop references from requests still in flight, such as canceled block
|
||||||
* jobs whose AIO context has not been polled yet */
|
* jobs whose AIO context has not been polled yet */
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ typedef struct BackupBlockJob {
|
|||||||
uint64_t sectors_read;
|
uint64_t sectors_read;
|
||||||
unsigned long *done_bitmap;
|
unsigned long *done_bitmap;
|
||||||
int64_t cluster_size;
|
int64_t cluster_size;
|
||||||
|
bool compress;
|
||||||
NotifierWithReturn before_write;
|
NotifierWithReturn before_write;
|
||||||
QLIST_HEAD(, CowRequest) inflight_reqs;
|
QLIST_HEAD(, CowRequest) inflight_reqs;
|
||||||
} BackupBlockJob;
|
} BackupBlockJob;
|
||||||
@@ -154,7 +155,8 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
|
|||||||
bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
|
bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
|
||||||
} else {
|
} else {
|
||||||
ret = blk_co_pwritev(job->target, start * job->cluster_size,
|
ret = blk_co_pwritev(job->target, start * job->cluster_size,
|
||||||
bounce_qiov.size, &bounce_qiov, 0);
|
bounce_qiov.size, &bounce_qiov,
|
||||||
|
job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
trace_backup_do_cow_write_fail(job, start, ret);
|
trace_backup_do_cow_write_fail(job, start, ret);
|
||||||
@@ -477,6 +479,7 @@ static void coroutine_fn backup_run(void *opaque)
|
|||||||
void backup_start(const char *job_id, BlockDriverState *bs,
|
void backup_start(const char *job_id, BlockDriverState *bs,
|
||||||
BlockDriverState *target, int64_t speed,
|
BlockDriverState *target, int64_t speed,
|
||||||
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
|
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
|
||||||
|
bool compress,
|
||||||
BlockdevOnError on_source_error,
|
BlockdevOnError on_source_error,
|
||||||
BlockdevOnError on_target_error,
|
BlockdevOnError on_target_error,
|
||||||
BlockCompletionFunc *cb, void *opaque,
|
BlockCompletionFunc *cb, void *opaque,
|
||||||
@@ -507,6 +510,12 @@ void backup_start(const char *job_id, BlockDriverState *bs,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (compress && target->drv->bdrv_co_pwritev_compressed == NULL) {
|
||||||
|
error_setg(errp, "Compression is not supported for this drive %s",
|
||||||
|
bdrv_get_device_name(target));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -555,6 +564,7 @@ void backup_start(const char *job_id, BlockDriverState *bs,
|
|||||||
job->sync_mode = sync_mode;
|
job->sync_mode = sync_mode;
|
||||||
job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ?
|
job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ?
|
||||||
sync_bitmap : NULL;
|
sync_bitmap : NULL;
|
||||||
|
job->compress = compress;
|
||||||
|
|
||||||
/* If there is no backing file on the target, we cannot rely on COW if our
|
/* If there is no backing file on the target, we cannot rely on COW if our
|
||||||
* backup cluster size is smaller than the target cluster size. Even for
|
* backup cluster size is smaller than the target cluster size. Even for
|
||||||
|
|||||||
@@ -409,6 +409,22 @@ bool bdrv_has_blk(BlockDriverState *bs)
|
|||||||
return bdrv_first_blk(bs) != NULL;
|
return bdrv_first_blk(bs) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true if @bs has only BlockBackends as parents.
|
||||||
|
*/
|
||||||
|
bool bdrv_is_root_node(BlockDriverState *bs)
|
||||||
|
{
|
||||||
|
BdrvChild *c;
|
||||||
|
|
||||||
|
QLIST_FOREACH(c, &bs->parents, next_parent) {
|
||||||
|
if (c->role != &child_root) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return @blk's DriveInfo if any, else null.
|
* Return @blk's DriveInfo if any, else null.
|
||||||
*/
|
*/
|
||||||
@@ -727,21 +743,6 @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int blk_check_request(BlockBackend *blk, int64_t sector_num,
|
|
||||||
int nb_sectors)
|
|
||||||
{
|
|
||||||
if (sector_num < 0 || sector_num > INT64_MAX / BDRV_SECTOR_SIZE) {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return blk_check_byte_request(blk, sector_num * BDRV_SECTOR_SIZE,
|
|
||||||
nb_sectors * BDRV_SECTOR_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
|
int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
|
||||||
unsigned int bytes, QEMUIOVector *qiov,
|
unsigned int bytes, QEMUIOVector *qiov,
|
||||||
BdrvRequestFlags flags)
|
BdrvRequestFlags flags)
|
||||||
@@ -1484,15 +1485,11 @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
|
|||||||
flags | BDRV_REQ_ZERO_WRITE);
|
flags | BDRV_REQ_ZERO_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int blk_write_compressed(BlockBackend *blk, int64_t sector_num,
|
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
|
||||||
const uint8_t *buf, int nb_sectors)
|
int count)
|
||||||
{
|
{
|
||||||
int ret = blk_check_request(blk, sector_num, nb_sectors);
|
return blk_prw(blk, offset, (void *) buf, count, blk_write_entry,
|
||||||
if (ret < 0) {
|
BDRV_REQ_WRITE_COMPRESSED);
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bdrv_write_compressed(blk_bs(blk), sector_num, buf, nb_sectors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int blk_truncate(BlockBackend *blk, int64_t offset)
|
int blk_truncate(BlockBackend *blk, int64_t offset)
|
||||||
|
|||||||
48
block/io.c
48
block/io.c
@@ -540,17 +540,6 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
|
|
||||||
int nb_sectors)
|
|
||||||
{
|
|
||||||
if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE,
|
|
||||||
nb_sectors * BDRV_SECTOR_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct RwCo {
|
typedef struct RwCo {
|
||||||
BdrvChild *child;
|
BdrvChild *child;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
@@ -897,6 +886,19 @@ emulate_flags:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int coroutine_fn
|
||||||
|
bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
|
||||||
|
uint64_t bytes, QEMUIOVector *qiov)
|
||||||
|
{
|
||||||
|
BlockDriver *drv = bs->drv;
|
||||||
|
|
||||||
|
if (!drv->bdrv_co_pwritev_compressed) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return drv->bdrv_co_pwritev_compressed(bs, offset, bytes, qiov);
|
||||||
|
}
|
||||||
|
|
||||||
static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs,
|
static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs,
|
||||||
int64_t offset, unsigned int bytes, QEMUIOVector *qiov)
|
int64_t offset, unsigned int bytes, QEMUIOVector *qiov)
|
||||||
{
|
{
|
||||||
@@ -1315,6 +1317,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
|
|||||||
} else if (flags & BDRV_REQ_ZERO_WRITE) {
|
} else if (flags & BDRV_REQ_ZERO_WRITE) {
|
||||||
bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
|
bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
|
||||||
ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
|
ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
|
||||||
|
} else if (flags & BDRV_REQ_WRITE_COMPRESSED) {
|
||||||
|
ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov);
|
||||||
} else if (bytes <= max_transfer) {
|
} else if (bytes <= max_transfer) {
|
||||||
bdrv_debug_event(bs, BLKDBG_PWRITEV);
|
bdrv_debug_event(bs, BLKDBG_PWRITEV);
|
||||||
ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, flags);
|
ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, flags);
|
||||||
@@ -1879,28 +1883,6 @@ int bdrv_is_allocated_above(BlockDriverState *top,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
|
||||||
const uint8_t *buf, int nb_sectors)
|
|
||||||
{
|
|
||||||
BlockDriver *drv = bs->drv;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!drv) {
|
|
||||||
return -ENOMEDIUM;
|
|
||||||
}
|
|
||||||
if (!drv->bdrv_write_compressed) {
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
ret = bdrv_check_request(bs, sector_num, nb_sectors);
|
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(QLIST_EMPTY(&bs->dirty_bitmaps));
|
|
||||||
|
|
||||||
return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct BdrvVmstateCo {
|
typedef struct BdrvVmstateCo {
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
QEMUIOVector *qiov;
|
QEMUIOVector *qiov;
|
||||||
|
|||||||
113
block/qcow.c
113
block/qcow.c
@@ -913,75 +913,32 @@ static int qcow_make_empty(BlockDriverState *bs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct QcowWriteCo {
|
|
||||||
BlockDriverState *bs;
|
|
||||||
int64_t sector_num;
|
|
||||||
const uint8_t *buf;
|
|
||||||
int nb_sectors;
|
|
||||||
int ret;
|
|
||||||
} QcowWriteCo;
|
|
||||||
|
|
||||||
static void qcow_write_co_entry(void *opaque)
|
|
||||||
{
|
|
||||||
QcowWriteCo *co = opaque;
|
|
||||||
QEMUIOVector qiov;
|
|
||||||
|
|
||||||
struct iovec iov = (struct iovec) {
|
|
||||||
.iov_base = (uint8_t*) co->buf,
|
|
||||||
.iov_len = co->nb_sectors * BDRV_SECTOR_SIZE,
|
|
||||||
};
|
|
||||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
|
||||||
|
|
||||||
co->ret = qcow_co_writev(co->bs, co->sector_num, co->nb_sectors, &qiov);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wrapper for non-coroutine contexts */
|
|
||||||
static int qcow_write(BlockDriverState *bs, int64_t sector_num,
|
|
||||||
const uint8_t *buf, int nb_sectors)
|
|
||||||
{
|
|
||||||
Coroutine *co;
|
|
||||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
|
||||||
QcowWriteCo data = {
|
|
||||||
.bs = bs,
|
|
||||||
.sector_num = sector_num,
|
|
||||||
.buf = buf,
|
|
||||||
.nb_sectors = nb_sectors,
|
|
||||||
.ret = -EINPROGRESS,
|
|
||||||
};
|
|
||||||
co = qemu_coroutine_create(qcow_write_co_entry, &data);
|
|
||||||
qemu_coroutine_enter(co);
|
|
||||||
while (data.ret == -EINPROGRESS) {
|
|
||||||
aio_poll(aio_context, true);
|
|
||||||
}
|
|
||||||
return data.ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: put compressed sectors first, then all the cluster aligned
|
/* XXX: put compressed sectors first, then all the cluster aligned
|
||||||
tables to avoid losing bytes in alignment */
|
tables to avoid losing bytes in alignment */
|
||||||
static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
static coroutine_fn int
|
||||||
const uint8_t *buf, int nb_sectors)
|
qcow_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
|
||||||
|
uint64_t bytes, QEMUIOVector *qiov)
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
|
QEMUIOVector hd_qiov;
|
||||||
|
struct iovec iov;
|
||||||
z_stream strm;
|
z_stream strm;
|
||||||
int ret, out_len;
|
int ret, out_len;
|
||||||
uint8_t *out_buf;
|
uint8_t *buf, *out_buf;
|
||||||
uint64_t cluster_offset;
|
uint64_t cluster_offset;
|
||||||
|
|
||||||
if (nb_sectors != s->cluster_sectors) {
|
buf = qemu_blockalign(bs, s->cluster_size);
|
||||||
ret = -EINVAL;
|
if (bytes != s->cluster_size) {
|
||||||
|
if (bytes > s->cluster_size ||
|
||||||
/* Zero-pad last write if image size is not cluster aligned */
|
offset + bytes != bs->total_sectors << BDRV_SECTOR_BITS)
|
||||||
if (sector_num + nb_sectors == bs->total_sectors &&
|
{
|
||||||
nb_sectors < s->cluster_sectors) {
|
qemu_vfree(buf);
|
||||||
uint8_t *pad_buf = qemu_blockalign(bs, s->cluster_size);
|
return -EINVAL;
|
||||||
memset(pad_buf, 0, s->cluster_size);
|
|
||||||
memcpy(pad_buf, buf, nb_sectors * BDRV_SECTOR_SIZE);
|
|
||||||
ret = qcow_write_compressed(bs, sector_num,
|
|
||||||
pad_buf, s->cluster_sectors);
|
|
||||||
qemu_vfree(pad_buf);
|
|
||||||
}
|
}
|
||||||
return ret;
|
/* Zero-pad last write if image size is not cluster aligned */
|
||||||
|
memset(buf + bytes, 0, s->cluster_size - bytes);
|
||||||
}
|
}
|
||||||
|
qemu_iovec_to_buf(qiov, 0, buf, qiov->size);
|
||||||
|
|
||||||
out_buf = g_malloc(s->cluster_size);
|
out_buf = g_malloc(s->cluster_size);
|
||||||
|
|
||||||
@@ -1012,27 +969,35 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
|||||||
|
|
||||||
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
|
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
|
||||||
/* could not compress: write normal cluster */
|
/* could not compress: write normal cluster */
|
||||||
ret = qcow_write(bs, sector_num, buf, s->cluster_sectors);
|
ret = qcow_co_writev(bs, offset >> BDRV_SECTOR_BITS,
|
||||||
if (ret < 0) {
|
bytes >> BDRV_SECTOR_BITS, qiov);
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
|
|
||||||
out_len, 0, 0);
|
|
||||||
if (cluster_offset == 0) {
|
|
||||||
ret = -EIO;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
cluster_offset &= s->cluster_offset_mask;
|
|
||||||
ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
goto success;
|
||||||
}
|
}
|
||||||
|
qemu_co_mutex_lock(&s->lock);
|
||||||
|
cluster_offset = get_cluster_offset(bs, offset, 2, out_len, 0, 0);
|
||||||
|
qemu_co_mutex_unlock(&s->lock);
|
||||||
|
if (cluster_offset == 0) {
|
||||||
|
ret = -EIO;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
cluster_offset &= s->cluster_offset_mask;
|
||||||
|
|
||||||
|
iov = (struct iovec) {
|
||||||
|
.iov_base = out_buf,
|
||||||
|
.iov_len = out_len,
|
||||||
|
};
|
||||||
|
qemu_iovec_init_external(&hd_qiov, &iov, 1);
|
||||||
|
ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
success:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
fail:
|
fail:
|
||||||
|
qemu_vfree(buf);
|
||||||
g_free(out_buf);
|
g_free(out_buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1085,7 +1050,7 @@ static BlockDriver bdrv_qcow = {
|
|||||||
|
|
||||||
.bdrv_set_key = qcow_set_key,
|
.bdrv_set_key = qcow_set_key,
|
||||||
.bdrv_make_empty = qcow_make_empty,
|
.bdrv_make_empty = qcow_make_empty,
|
||||||
.bdrv_write_compressed = qcow_write_compressed,
|
.bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed,
|
||||||
.bdrv_get_info = qcow_get_info,
|
.bdrv_get_info = qcow_get_info,
|
||||||
|
|
||||||
.create_opts = &qcow_create_opts,
|
.create_opts = &qcow_create_opts,
|
||||||
|
|||||||
132
block/qcow2.c
132
block/qcow2.c
@@ -2533,84 +2533,39 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct Qcow2WriteCo {
|
|
||||||
BlockDriverState *bs;
|
|
||||||
int64_t sector_num;
|
|
||||||
const uint8_t *buf;
|
|
||||||
int nb_sectors;
|
|
||||||
int ret;
|
|
||||||
} Qcow2WriteCo;
|
|
||||||
|
|
||||||
static void qcow2_write_co_entry(void *opaque)
|
|
||||||
{
|
|
||||||
Qcow2WriteCo *co = opaque;
|
|
||||||
QEMUIOVector qiov;
|
|
||||||
uint64_t offset = co->sector_num * BDRV_SECTOR_SIZE;
|
|
||||||
uint64_t bytes = co->nb_sectors * BDRV_SECTOR_SIZE;
|
|
||||||
|
|
||||||
struct iovec iov = (struct iovec) {
|
|
||||||
.iov_base = (uint8_t*) co->buf,
|
|
||||||
.iov_len = bytes,
|
|
||||||
};
|
|
||||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
|
||||||
|
|
||||||
co->ret = qcow2_co_pwritev(co->bs, offset, bytes, &qiov, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wrapper for non-coroutine contexts */
|
|
||||||
static int qcow2_write(BlockDriverState *bs, int64_t sector_num,
|
|
||||||
const uint8_t *buf, int nb_sectors)
|
|
||||||
{
|
|
||||||
Coroutine *co;
|
|
||||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
|
||||||
Qcow2WriteCo data = {
|
|
||||||
.bs = bs,
|
|
||||||
.sector_num = sector_num,
|
|
||||||
.buf = buf,
|
|
||||||
.nb_sectors = nb_sectors,
|
|
||||||
.ret = -EINPROGRESS,
|
|
||||||
};
|
|
||||||
co = qemu_coroutine_create(qcow2_write_co_entry, &data);
|
|
||||||
qemu_coroutine_enter(co);
|
|
||||||
while (data.ret == -EINPROGRESS) {
|
|
||||||
aio_poll(aio_context, true);
|
|
||||||
}
|
|
||||||
return data.ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: put compressed sectors first, then all the cluster aligned
|
/* XXX: put compressed sectors first, then all the cluster aligned
|
||||||
tables to avoid losing bytes in alignment */
|
tables to avoid losing bytes in alignment */
|
||||||
static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
static coroutine_fn int
|
||||||
const uint8_t *buf, int nb_sectors)
|
qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
|
||||||
|
uint64_t bytes, QEMUIOVector *qiov)
|
||||||
{
|
{
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
|
QEMUIOVector hd_qiov;
|
||||||
|
struct iovec iov;
|
||||||
z_stream strm;
|
z_stream strm;
|
||||||
int ret, out_len;
|
int ret, out_len;
|
||||||
uint8_t *out_buf;
|
uint8_t *buf, *out_buf;
|
||||||
uint64_t cluster_offset;
|
uint64_t cluster_offset;
|
||||||
|
|
||||||
if (nb_sectors == 0) {
|
if (bytes == 0) {
|
||||||
/* align end of file to a sector boundary to ease reading with
|
/* align end of file to a sector boundary to ease reading with
|
||||||
sector based I/Os */
|
sector based I/Os */
|
||||||
cluster_offset = bdrv_getlength(bs->file->bs);
|
cluster_offset = bdrv_getlength(bs->file->bs);
|
||||||
return bdrv_truncate(bs->file->bs, cluster_offset);
|
return bdrv_truncate(bs->file->bs, cluster_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nb_sectors != s->cluster_sectors) {
|
buf = qemu_blockalign(bs, s->cluster_size);
|
||||||
ret = -EINVAL;
|
if (bytes != s->cluster_size) {
|
||||||
|
if (bytes > s->cluster_size ||
|
||||||
/* Zero-pad last write if image size is not cluster aligned */
|
offset + bytes != bs->total_sectors << BDRV_SECTOR_BITS)
|
||||||
if (sector_num + nb_sectors == bs->total_sectors &&
|
{
|
||||||
nb_sectors < s->cluster_sectors) {
|
qemu_vfree(buf);
|
||||||
uint8_t *pad_buf = qemu_blockalign(bs, s->cluster_size);
|
return -EINVAL;
|
||||||
memset(pad_buf, 0, s->cluster_size);
|
|
||||||
memcpy(pad_buf, buf, nb_sectors * BDRV_SECTOR_SIZE);
|
|
||||||
ret = qcow2_write_compressed(bs, sector_num,
|
|
||||||
pad_buf, s->cluster_sectors);
|
|
||||||
qemu_vfree(pad_buf);
|
|
||||||
}
|
}
|
||||||
return ret;
|
/* Zero-pad last write if image size is not cluster aligned */
|
||||||
|
memset(buf + bytes, 0, s->cluster_size - bytes);
|
||||||
}
|
}
|
||||||
|
qemu_iovec_to_buf(qiov, 0, buf, bytes);
|
||||||
|
|
||||||
out_buf = g_malloc(s->cluster_size);
|
out_buf = g_malloc(s->cluster_size);
|
||||||
|
|
||||||
@@ -2641,33 +2596,44 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
|||||||
|
|
||||||
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
|
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
|
||||||
/* could not compress: write normal cluster */
|
/* could not compress: write normal cluster */
|
||||||
ret = qcow2_write(bs, sector_num, buf, s->cluster_sectors);
|
ret = qcow2_co_pwritev(bs, offset, bytes, qiov, 0);
|
||||||
if (ret < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cluster_offset = qcow2_alloc_compressed_cluster_offset(bs,
|
|
||||||
sector_num << 9, out_len);
|
|
||||||
if (!cluster_offset) {
|
|
||||||
ret = -EIO;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
cluster_offset &= s->cluster_offset_mask;
|
|
||||||
|
|
||||||
ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset, out_len);
|
|
||||||
if (ret < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
|
|
||||||
ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
goto success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qemu_co_mutex_lock(&s->lock);
|
||||||
|
cluster_offset =
|
||||||
|
qcow2_alloc_compressed_cluster_offset(bs, offset, out_len);
|
||||||
|
if (!cluster_offset) {
|
||||||
|
qemu_co_mutex_unlock(&s->lock);
|
||||||
|
ret = -EIO;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
cluster_offset &= s->cluster_offset_mask;
|
||||||
|
|
||||||
|
ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset, out_len);
|
||||||
|
qemu_co_mutex_unlock(&s->lock);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
iov = (struct iovec) {
|
||||||
|
.iov_base = out_buf,
|
||||||
|
.iov_len = out_len,
|
||||||
|
};
|
||||||
|
qemu_iovec_init_external(&hd_qiov, &iov, 1);
|
||||||
|
|
||||||
|
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
|
||||||
|
ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
success:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
fail:
|
fail:
|
||||||
|
qemu_vfree(buf);
|
||||||
g_free(out_buf);
|
g_free(out_buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -3412,7 +3378,7 @@ BlockDriver bdrv_qcow2 = {
|
|||||||
.bdrv_co_pwrite_zeroes = qcow2_co_pwrite_zeroes,
|
.bdrv_co_pwrite_zeroes = qcow2_co_pwrite_zeroes,
|
||||||
.bdrv_co_pdiscard = qcow2_co_pdiscard,
|
.bdrv_co_pdiscard = qcow2_co_pdiscard,
|
||||||
.bdrv_truncate = qcow2_truncate,
|
.bdrv_truncate = qcow2_truncate,
|
||||||
.bdrv_write_compressed = qcow2_write_compressed,
|
.bdrv_co_pwritev_compressed = qcow2_co_pwritev_compressed,
|
||||||
.bdrv_make_empty = qcow2_make_empty,
|
.bdrv_make_empty = qcow2_make_empty,
|
||||||
|
|
||||||
.bdrv_snapshot_create = qcow2_snapshot_create,
|
.bdrv_snapshot_create = qcow2_snapshot_create,
|
||||||
|
|||||||
55
block/vmdk.c
55
block/vmdk.c
@@ -1645,56 +1645,11 @@ vmdk_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct VmdkWriteCompressedCo {
|
static int coroutine_fn
|
||||||
BlockDriverState *bs;
|
vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
|
||||||
int64_t sector_num;
|
uint64_t bytes, QEMUIOVector *qiov)
|
||||||
const uint8_t *buf;
|
|
||||||
int nb_sectors;
|
|
||||||
int ret;
|
|
||||||
} VmdkWriteCompressedCo;
|
|
||||||
|
|
||||||
static void vmdk_co_write_compressed(void *opaque)
|
|
||||||
{
|
{
|
||||||
VmdkWriteCompressedCo *co = opaque;
|
return vmdk_co_pwritev(bs, offset, bytes, qiov, 0);
|
||||||
QEMUIOVector local_qiov;
|
|
||||||
uint64_t offset = co->sector_num * BDRV_SECTOR_SIZE;
|
|
||||||
uint64_t bytes = co->nb_sectors * BDRV_SECTOR_SIZE;
|
|
||||||
|
|
||||||
struct iovec iov = (struct iovec) {
|
|
||||||
.iov_base = (uint8_t*) co->buf,
|
|
||||||
.iov_len = bytes,
|
|
||||||
};
|
|
||||||
qemu_iovec_init_external(&local_qiov, &iov, 1);
|
|
||||||
|
|
||||||
co->ret = vmdk_pwritev(co->bs, offset, bytes, &local_qiov, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vmdk_write_compressed(BlockDriverState *bs,
|
|
||||||
int64_t sector_num,
|
|
||||||
const uint8_t *buf,
|
|
||||||
int nb_sectors)
|
|
||||||
{
|
|
||||||
BDRVVmdkState *s = bs->opaque;
|
|
||||||
|
|
||||||
if (s->num_extents == 1 && s->extents[0].compressed) {
|
|
||||||
Coroutine *co;
|
|
||||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
|
||||||
VmdkWriteCompressedCo data = {
|
|
||||||
.bs = bs,
|
|
||||||
.sector_num = sector_num,
|
|
||||||
.buf = buf,
|
|
||||||
.nb_sectors = nb_sectors,
|
|
||||||
.ret = -EINPROGRESS,
|
|
||||||
};
|
|
||||||
co = qemu_coroutine_create(vmdk_co_write_compressed, &data);
|
|
||||||
qemu_coroutine_enter(co);
|
|
||||||
while (data.ret == -EINPROGRESS) {
|
|
||||||
aio_poll(aio_context, true);
|
|
||||||
}
|
|
||||||
return data.ret;
|
|
||||||
} else {
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn vmdk_co_pwrite_zeroes(BlockDriverState *bs,
|
static int coroutine_fn vmdk_co_pwrite_zeroes(BlockDriverState *bs,
|
||||||
@@ -2393,7 +2348,7 @@ static BlockDriver bdrv_vmdk = {
|
|||||||
.bdrv_reopen_prepare = vmdk_reopen_prepare,
|
.bdrv_reopen_prepare = vmdk_reopen_prepare,
|
||||||
.bdrv_co_preadv = vmdk_co_preadv,
|
.bdrv_co_preadv = vmdk_co_preadv,
|
||||||
.bdrv_co_pwritev = vmdk_co_pwritev,
|
.bdrv_co_pwritev = vmdk_co_pwritev,
|
||||||
.bdrv_write_compressed = vmdk_write_compressed,
|
.bdrv_co_pwritev_compressed = vmdk_co_pwritev_compressed,
|
||||||
.bdrv_co_pwrite_zeroes = vmdk_co_pwrite_zeroes,
|
.bdrv_co_pwrite_zeroes = vmdk_co_pwrite_zeroes,
|
||||||
.bdrv_close = vmdk_close,
|
.bdrv_close = vmdk_close,
|
||||||
.bdrv_create = vmdk_create,
|
.bdrv_create = vmdk_create,
|
||||||
|
|||||||
@@ -145,7 +145,8 @@ void qmp_nbd_server_start(SocketAddress *addr,
|
|||||||
void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
|
void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockBackend *blk;
|
BlockDriverState *bs = NULL;
|
||||||
|
BlockBackend *on_eject_blk;
|
||||||
NBDExport *exp;
|
NBDExport *exp;
|
||||||
|
|
||||||
if (!nbd_server) {
|
if (!nbd_server) {
|
||||||
@@ -158,26 +159,22 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blk = blk_by_name(device);
|
on_eject_blk = blk_by_name(device);
|
||||||
if (!blk) {
|
|
||||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
bs = bdrv_lookup_bs(device, device, errp);
|
||||||
"Device '%s' not found", device);
|
if (!bs) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!blk_is_inserted(blk)) {
|
|
||||||
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_writable) {
|
if (!has_writable) {
|
||||||
writable = false;
|
writable = false;
|
||||||
}
|
}
|
||||||
if (blk_is_read_only(blk)) {
|
if (bdrv_is_read_only(bs)) {
|
||||||
writable = false;
|
writable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
exp = nbd_export_new(blk, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, NULL,
|
exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY,
|
||||||
errp);
|
NULL, false, on_eject_blk, errp);
|
||||||
if (!exp) {
|
if (!exp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
378
blockdev.c
378
blockdev.c
@@ -1174,6 +1174,28 @@ fail:
|
|||||||
return dinfo;
|
return dinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp)
|
||||||
|
{
|
||||||
|
BlockDriverState *bs;
|
||||||
|
|
||||||
|
bs = bdrv_lookup_bs(name, name, errp);
|
||||||
|
if (bs == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bdrv_is_root_node(bs)) {
|
||||||
|
error_setg(errp, "Need a root block node");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bdrv_is_inserted(bs)) {
|
||||||
|
error_setg(errp, "Device has no medium");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bs;
|
||||||
|
}
|
||||||
|
|
||||||
void hmp_commit(Monitor *mon, const QDict *qdict)
|
void hmp_commit(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
const char *device = qdict_get_str(qdict, "device");
|
const char *device = qdict_get_str(qdict, "device");
|
||||||
@@ -1284,21 +1306,17 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
|
|||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockBackend *blk;
|
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
QEMUSnapshotInfo sn;
|
QEMUSnapshotInfo sn;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
SnapshotInfo *info = NULL;
|
SnapshotInfo *info = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
blk = blk_by_name(device);
|
bs = qmp_get_root_bs(device, errp);
|
||||||
if (!blk) {
|
if (!bs) {
|
||||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
||||||
"Device '%s' not found", device);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context = blk_get_aio_context(blk);
|
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
if (!has_id) {
|
if (!has_id) {
|
||||||
@@ -1314,12 +1332,6 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
|
|||||||
goto out_aio_context;
|
goto out_aio_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!blk_is_available(blk)) {
|
|
||||||
error_setg(errp, "Device '%s' has no medium", device);
|
|
||||||
goto out_aio_context;
|
|
||||||
}
|
|
||||||
bs = blk_bs(blk);
|
|
||||||
|
|
||||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, errp)) {
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, errp)) {
|
||||||
goto out_aio_context;
|
goto out_aio_context;
|
||||||
}
|
}
|
||||||
@@ -1499,7 +1511,6 @@ static void internal_snapshot_prepare(BlkActionState *common,
|
|||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
const char *device;
|
const char *device;
|
||||||
const char *name;
|
const char *name;
|
||||||
BlockBackend *blk;
|
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
QEMUSnapshotInfo old_sn, *sn;
|
QEMUSnapshotInfo old_sn, *sn;
|
||||||
bool ret;
|
bool ret;
|
||||||
@@ -1522,23 +1533,15 @@ static void internal_snapshot_prepare(BlkActionState *common,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blk = blk_by_name(device);
|
bs = qmp_get_root_bs(device, errp);
|
||||||
if (!blk) {
|
if (!bs) {
|
||||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
||||||
"Device '%s' not found", device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AioContext is released in .clean() */
|
/* AioContext is released in .clean() */
|
||||||
state->aio_context = blk_get_aio_context(blk);
|
state->aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(state->aio_context);
|
aio_context_acquire(state->aio_context);
|
||||||
|
|
||||||
if (!blk_is_available(blk)) {
|
|
||||||
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bs = blk_bs(blk);
|
|
||||||
|
|
||||||
state->bs = bs;
|
state->bs = bs;
|
||||||
bdrv_drained_begin(bs);
|
bdrv_drained_begin(bs);
|
||||||
|
|
||||||
@@ -1838,56 +1841,31 @@ typedef struct DriveBackupState {
|
|||||||
BlockJob *job;
|
BlockJob *job;
|
||||||
} DriveBackupState;
|
} DriveBackupState;
|
||||||
|
|
||||||
static void do_drive_backup(const char *job_id, const char *device,
|
static void do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
|
||||||
const char *target, bool has_format,
|
Error **errp);
|
||||||
const char *format, enum MirrorSyncMode sync,
|
|
||||||
bool has_mode, enum NewImageMode mode,
|
|
||||||
bool has_speed, int64_t speed,
|
|
||||||
bool has_bitmap, const char *bitmap,
|
|
||||||
bool has_on_source_error,
|
|
||||||
BlockdevOnError on_source_error,
|
|
||||||
bool has_on_target_error,
|
|
||||||
BlockdevOnError on_target_error,
|
|
||||||
BlockJobTxn *txn, Error **errp);
|
|
||||||
|
|
||||||
static void drive_backup_prepare(BlkActionState *common, Error **errp)
|
static void drive_backup_prepare(BlkActionState *common, Error **errp)
|
||||||
{
|
{
|
||||||
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
|
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
|
||||||
BlockBackend *blk;
|
BlockDriverState *bs;
|
||||||
DriveBackup *backup;
|
DriveBackup *backup;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
|
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
|
||||||
backup = common->action->u.drive_backup.data;
|
backup = common->action->u.drive_backup.data;
|
||||||
|
|
||||||
blk = blk_by_name(backup->device);
|
bs = qmp_get_root_bs(backup->device, errp);
|
||||||
if (!blk) {
|
if (!bs) {
|
||||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
||||||
"Device '%s' not found", backup->device);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!blk_is_available(blk)) {
|
|
||||||
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, backup->device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AioContext is released in .clean() */
|
/* AioContext is released in .clean() */
|
||||||
state->aio_context = blk_get_aio_context(blk);
|
state->aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(state->aio_context);
|
aio_context_acquire(state->aio_context);
|
||||||
bdrv_drained_begin(blk_bs(blk));
|
bdrv_drained_begin(bs);
|
||||||
state->bs = blk_bs(blk);
|
state->bs = bs;
|
||||||
|
|
||||||
do_drive_backup(backup->has_job_id ? backup->job_id : NULL,
|
do_drive_backup(backup, common->block_job_txn, &local_err);
|
||||||
backup->device, backup->target,
|
|
||||||
backup->has_format, backup->format,
|
|
||||||
backup->sync,
|
|
||||||
backup->has_mode, backup->mode,
|
|
||||||
backup->has_speed, backup->speed,
|
|
||||||
backup->has_bitmap, backup->bitmap,
|
|
||||||
backup->has_on_source_error, backup->on_source_error,
|
|
||||||
backup->has_on_target_error, backup->on_target_error,
|
|
||||||
common->block_job_txn, &local_err);
|
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return;
|
return;
|
||||||
@@ -1924,34 +1902,21 @@ typedef struct BlockdevBackupState {
|
|||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
} BlockdevBackupState;
|
} BlockdevBackupState;
|
||||||
|
|
||||||
static void do_blockdev_backup(const char *job_id, const char *device,
|
static void do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn,
|
||||||
const char *target, enum MirrorSyncMode sync,
|
Error **errp);
|
||||||
bool has_speed, int64_t speed,
|
|
||||||
bool has_on_source_error,
|
|
||||||
BlockdevOnError on_source_error,
|
|
||||||
bool has_on_target_error,
|
|
||||||
BlockdevOnError on_target_error,
|
|
||||||
BlockJobTxn *txn, Error **errp);
|
|
||||||
|
|
||||||
static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
||||||
{
|
{
|
||||||
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
|
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
|
||||||
BlockdevBackup *backup;
|
BlockdevBackup *backup;
|
||||||
BlockBackend *blk;
|
BlockDriverState *bs, *target;
|
||||||
BlockDriverState *target;
|
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
|
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
|
||||||
backup = common->action->u.blockdev_backup.data;
|
backup = common->action->u.blockdev_backup.data;
|
||||||
|
|
||||||
blk = blk_by_name(backup->device);
|
bs = qmp_get_root_bs(backup->device, errp);
|
||||||
if (!blk) {
|
if (!bs) {
|
||||||
error_setg(errp, "Device '%s' not found", backup->device);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!blk_is_available(blk)) {
|
|
||||||
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, backup->device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1961,22 +1926,17 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* AioContext is released in .clean() */
|
/* AioContext is released in .clean() */
|
||||||
state->aio_context = blk_get_aio_context(blk);
|
state->aio_context = bdrv_get_aio_context(bs);
|
||||||
if (state->aio_context != bdrv_get_aio_context(target)) {
|
if (state->aio_context != bdrv_get_aio_context(target)) {
|
||||||
state->aio_context = NULL;
|
state->aio_context = NULL;
|
||||||
error_setg(errp, "Backup between two IO threads is not implemented");
|
error_setg(errp, "Backup between two IO threads is not implemented");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
aio_context_acquire(state->aio_context);
|
aio_context_acquire(state->aio_context);
|
||||||
state->bs = blk_bs(blk);
|
state->bs = bs;
|
||||||
bdrv_drained_begin(state->bs);
|
bdrv_drained_begin(state->bs);
|
||||||
|
|
||||||
do_blockdev_backup(backup->has_job_id ? backup->job_id : NULL,
|
do_blockdev_backup(backup, common->block_job_txn, &local_err);
|
||||||
backup->device, backup->target, backup->sync,
|
|
||||||
backup->has_speed, backup->speed,
|
|
||||||
backup->has_on_source_error, backup->on_source_error,
|
|
||||||
backup->has_on_target_error, backup->on_target_error,
|
|
||||||
common->block_job_txn, &local_err);
|
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return;
|
return;
|
||||||
@@ -2983,7 +2943,6 @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
|
|||||||
bool has_on_error, BlockdevOnError on_error,
|
bool has_on_error, BlockdevOnError on_error,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockBackend *blk;
|
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockDriverState *base_bs = NULL;
|
BlockDriverState *base_bs = NULL;
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
@@ -2994,22 +2953,14 @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
|
|||||||
on_error = BLOCKDEV_ON_ERROR_REPORT;
|
on_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
blk = blk_by_name(device);
|
bs = qmp_get_root_bs(device, errp);
|
||||||
if (!blk) {
|
if (!bs) {
|
||||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
||||||
"Device '%s' not found", device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
aio_context = blk_get_aio_context(blk);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
if (!blk_is_available(blk)) {
|
|
||||||
error_setg(errp, "Device '%s' has no medium", device);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
bs = blk_bs(blk);
|
|
||||||
|
|
||||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_STREAM, errp)) {
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_STREAM, errp)) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -3055,7 +3006,6 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
|
|||||||
bool has_speed, int64_t speed,
|
bool has_speed, int64_t speed,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockBackend *blk;
|
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockDriverState *base_bs, *top_bs;
|
BlockDriverState *base_bs, *top_bs;
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
@@ -3074,22 +3024,22 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
|
|||||||
* live commit feature versions; for this to work, we must make sure to
|
* live commit feature versions; for this to work, we must make sure to
|
||||||
* perform the device lookup before any generic errors that may occur in a
|
* perform the device lookup before any generic errors that may occur in a
|
||||||
* scenario in which all optional arguments are omitted. */
|
* scenario in which all optional arguments are omitted. */
|
||||||
blk = blk_by_name(device);
|
bs = qmp_get_root_bs(device, &local_err);
|
||||||
if (!blk) {
|
if (!bs) {
|
||||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
bs = bdrv_lookup_bs(device, device, NULL);
|
||||||
"Device '%s' not found", device);
|
if (!bs) {
|
||||||
|
error_free(local_err);
|
||||||
|
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
||||||
|
"Device '%s' not found", device);
|
||||||
|
} else {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
aio_context = blk_get_aio_context(blk);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
if (!blk_is_available(blk)) {
|
|
||||||
error_setg(errp, "Device '%s' has no medium", device);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
bs = blk_bs(blk);
|
|
||||||
|
|
||||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT_SOURCE, errp)) {
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT_SOURCE, errp)) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -3155,19 +3105,8 @@ out:
|
|||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_drive_backup(const char *job_id, const char *device,
|
static void do_drive_backup(DriveBackup *backup, BlockJobTxn *txn, Error **errp)
|
||||||
const char *target, bool has_format,
|
|
||||||
const char *format, enum MirrorSyncMode sync,
|
|
||||||
bool has_mode, enum NewImageMode mode,
|
|
||||||
bool has_speed, int64_t speed,
|
|
||||||
bool has_bitmap, const char *bitmap,
|
|
||||||
bool has_on_source_error,
|
|
||||||
BlockdevOnError on_source_error,
|
|
||||||
bool has_on_target_error,
|
|
||||||
BlockdevOnError on_target_error,
|
|
||||||
BlockJobTxn *txn, Error **errp)
|
|
||||||
{
|
{
|
||||||
BlockBackend *blk;
|
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockDriverState *target_bs;
|
BlockDriverState *target_bs;
|
||||||
BlockDriverState *source = NULL;
|
BlockDriverState *source = NULL;
|
||||||
@@ -3178,39 +3117,36 @@ static void do_drive_backup(const char *job_id, const char *device,
|
|||||||
int flags;
|
int flags;
|
||||||
int64_t size;
|
int64_t size;
|
||||||
|
|
||||||
if (!has_speed) {
|
if (!backup->has_speed) {
|
||||||
speed = 0;
|
backup->speed = 0;
|
||||||
}
|
}
|
||||||
if (!has_on_source_error) {
|
if (!backup->has_on_source_error) {
|
||||||
on_source_error = BLOCKDEV_ON_ERROR_REPORT;
|
backup->on_source_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||||
}
|
}
|
||||||
if (!has_on_target_error) {
|
if (!backup->has_on_target_error) {
|
||||||
on_target_error = BLOCKDEV_ON_ERROR_REPORT;
|
backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||||
}
|
}
|
||||||
if (!has_mode) {
|
if (!backup->has_mode) {
|
||||||
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
||||||
|
}
|
||||||
|
if (!backup->has_job_id) {
|
||||||
|
backup->job_id = NULL;
|
||||||
|
}
|
||||||
|
if (!backup->has_compress) {
|
||||||
|
backup->compress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
blk = blk_by_name(device);
|
bs = qmp_get_root_bs(backup->device, errp);
|
||||||
if (!blk) {
|
if (!bs) {
|
||||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
||||||
"Device '%s' not found", device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
aio_context = blk_get_aio_context(blk);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
/* Although backup_run has this check too, we need to use bs->drv below, so
|
if (!backup->has_format) {
|
||||||
* do an early check redundantly. */
|
backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ?
|
||||||
if (!blk_is_available(blk)) {
|
NULL : (char*) bs->drv->format_name;
|
||||||
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
bs = blk_bs(blk);
|
|
||||||
|
|
||||||
if (!has_format) {
|
|
||||||
format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Early check to avoid creating target */
|
/* Early check to avoid creating target */
|
||||||
@@ -3222,13 +3158,13 @@ static void do_drive_backup(const char *job_id, const char *device,
|
|||||||
|
|
||||||
/* See if we have a backing HD we can use to create our new image
|
/* See if we have a backing HD we can use to create our new image
|
||||||
* on top of. */
|
* on top of. */
|
||||||
if (sync == MIRROR_SYNC_MODE_TOP) {
|
if (backup->sync == MIRROR_SYNC_MODE_TOP) {
|
||||||
source = backing_bs(bs);
|
source = backing_bs(bs);
|
||||||
if (!source) {
|
if (!source) {
|
||||||
sync = MIRROR_SYNC_MODE_FULL;
|
backup->sync = MIRROR_SYNC_MODE_FULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sync == MIRROR_SYNC_MODE_NONE) {
|
if (backup->sync == MIRROR_SYNC_MODE_NONE) {
|
||||||
source = bs;
|
source = bs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3238,14 +3174,14 @@ static void do_drive_backup(const char *job_id, const char *device,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode != NEW_IMAGE_MODE_EXISTING) {
|
if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
|
||||||
assert(format);
|
assert(backup->format);
|
||||||
if (source) {
|
if (source) {
|
||||||
bdrv_img_create(target, format, source->filename,
|
bdrv_img_create(backup->target, backup->format, source->filename,
|
||||||
source->drv->format_name, NULL,
|
source->drv->format_name, NULL,
|
||||||
size, flags, &local_err, false);
|
size, flags, &local_err, false);
|
||||||
} else {
|
} else {
|
||||||
bdrv_img_create(target, format, NULL, NULL, NULL,
|
bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL,
|
||||||
size, flags, &local_err, false);
|
size, flags, &local_err, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3255,30 +3191,30 @@ static void do_drive_backup(const char *job_id, const char *device,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format) {
|
if (backup->format) {
|
||||||
options = qdict_new();
|
options = qdict_new();
|
||||||
qdict_put(options, "driver", qstring_from_str(format));
|
qdict_put(options, "driver", qstring_from_str(backup->format));
|
||||||
}
|
}
|
||||||
|
|
||||||
target_bs = bdrv_open(target, NULL, options, flags, errp);
|
target_bs = bdrv_open(backup->target, NULL, options, flags, errp);
|
||||||
if (!target_bs) {
|
if (!target_bs) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_set_aio_context(target_bs, aio_context);
|
bdrv_set_aio_context(target_bs, aio_context);
|
||||||
|
|
||||||
if (has_bitmap) {
|
if (backup->has_bitmap) {
|
||||||
bmap = bdrv_find_dirty_bitmap(bs, bitmap);
|
bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
|
||||||
if (!bmap) {
|
if (!bmap) {
|
||||||
error_setg(errp, "Bitmap '%s' could not be found", bitmap);
|
error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
|
||||||
bdrv_unref(target_bs);
|
bdrv_unref(target_bs);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
backup_start(job_id, bs, target_bs, speed, sync, bmap,
|
backup_start(backup->job_id, bs, target_bs, backup->speed, backup->sync,
|
||||||
on_source_error, on_target_error,
|
bmap, backup->compress, backup->on_source_error,
|
||||||
block_job_cb, bs, txn, &local_err);
|
backup->on_target_error, block_job_cb, bs, txn, &local_err);
|
||||||
bdrv_unref(target_bs);
|
bdrv_unref(target_bs);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
@@ -3289,24 +3225,9 @@ out:
|
|||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_drive_backup(bool has_job_id, const char *job_id,
|
void qmp_drive_backup(DriveBackup *arg, Error **errp)
|
||||||
const char *device, const char *target,
|
|
||||||
bool has_format, const char *format,
|
|
||||||
enum MirrorSyncMode sync,
|
|
||||||
bool has_mode, enum NewImageMode mode,
|
|
||||||
bool has_speed, int64_t speed,
|
|
||||||
bool has_bitmap, const char *bitmap,
|
|
||||||
bool has_on_source_error, BlockdevOnError on_source_error,
|
|
||||||
bool has_on_target_error, BlockdevOnError on_target_error,
|
|
||||||
Error **errp)
|
|
||||||
{
|
{
|
||||||
return do_drive_backup(has_job_id ? job_id : NULL, device, target,
|
return do_drive_backup(arg, NULL, errp);
|
||||||
has_format, format, sync,
|
|
||||||
has_mode, mode, has_speed, speed,
|
|
||||||
has_bitmap, bitmap,
|
|
||||||
has_on_source_error, on_source_error,
|
|
||||||
has_on_target_error, on_target_error,
|
|
||||||
NULL, errp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
|
BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
|
||||||
@@ -3314,47 +3235,38 @@ BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
|
|||||||
return bdrv_named_nodes_list(errp);
|
return bdrv_named_nodes_list(errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_blockdev_backup(const char *job_id, const char *device,
|
void do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn, Error **errp)
|
||||||
const char *target, enum MirrorSyncMode sync,
|
|
||||||
bool has_speed, int64_t speed,
|
|
||||||
bool has_on_source_error,
|
|
||||||
BlockdevOnError on_source_error,
|
|
||||||
bool has_on_target_error,
|
|
||||||
BlockdevOnError on_target_error,
|
|
||||||
BlockJobTxn *txn, Error **errp)
|
|
||||||
{
|
{
|
||||||
BlockBackend *blk;
|
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockDriverState *target_bs;
|
BlockDriverState *target_bs;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
|
|
||||||
if (!has_speed) {
|
if (!backup->has_speed) {
|
||||||
speed = 0;
|
backup->speed = 0;
|
||||||
}
|
}
|
||||||
if (!has_on_source_error) {
|
if (!backup->has_on_source_error) {
|
||||||
on_source_error = BLOCKDEV_ON_ERROR_REPORT;
|
backup->on_source_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||||
}
|
}
|
||||||
if (!has_on_target_error) {
|
if (!backup->has_on_target_error) {
|
||||||
on_target_error = BLOCKDEV_ON_ERROR_REPORT;
|
backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||||
|
}
|
||||||
|
if (!backup->has_job_id) {
|
||||||
|
backup->job_id = NULL;
|
||||||
|
}
|
||||||
|
if (!backup->has_compress) {
|
||||||
|
backup->compress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
blk = blk_by_name(device);
|
bs = qmp_get_root_bs(backup->device, errp);
|
||||||
if (!blk) {
|
if (!bs) {
|
||||||
error_setg(errp, "Device '%s' not found", device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
aio_context = blk_get_aio_context(blk);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
if (!blk_is_available(blk)) {
|
target_bs = bdrv_lookup_bs(backup->target, backup->target, errp);
|
||||||
error_setg(errp, "Device '%s' has no medium", device);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
bs = blk_bs(blk);
|
|
||||||
|
|
||||||
target_bs = bdrv_lookup_bs(target, target, errp);
|
|
||||||
if (!target_bs) {
|
if (!target_bs) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -3370,8 +3282,9 @@ void do_blockdev_backup(const char *job_id, const char *device,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
backup_start(job_id, bs, target_bs, speed, sync, NULL, on_source_error,
|
backup_start(backup->job_id, bs, target_bs, backup->speed, backup->sync,
|
||||||
on_target_error, block_job_cb, bs, txn, &local_err);
|
NULL, backup->compress, backup->on_source_error,
|
||||||
|
backup->on_target_error, block_job_cb, bs, txn, &local_err);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
}
|
}
|
||||||
@@ -3379,21 +3292,9 @@ out:
|
|||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_blockdev_backup(bool has_job_id, const char *job_id,
|
void qmp_blockdev_backup(BlockdevBackup *arg, Error **errp)
|
||||||
const char *device, const char *target,
|
|
||||||
enum MirrorSyncMode sync,
|
|
||||||
bool has_speed, int64_t speed,
|
|
||||||
bool has_on_source_error,
|
|
||||||
BlockdevOnError on_source_error,
|
|
||||||
bool has_on_target_error,
|
|
||||||
BlockdevOnError on_target_error,
|
|
||||||
Error **errp)
|
|
||||||
{
|
{
|
||||||
do_blockdev_backup(has_job_id ? job_id : NULL, device, target,
|
do_blockdev_backup(arg, NULL, errp);
|
||||||
sync, has_speed, speed,
|
|
||||||
has_on_source_error, on_source_error,
|
|
||||||
has_on_target_error, on_target_error,
|
|
||||||
NULL, errp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parameter check and block job starting for drive mirroring.
|
/* Parameter check and block job starting for drive mirroring.
|
||||||
@@ -3469,7 +3370,6 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
|
|||||||
void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockBackend *blk;
|
|
||||||
BlockDriverState *source, *target_bs;
|
BlockDriverState *source, *target_bs;
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
BlockMirrorBackingMode backing_mode;
|
BlockMirrorBackingMode backing_mode;
|
||||||
@@ -3479,21 +3379,14 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
|||||||
int64_t size;
|
int64_t size;
|
||||||
const char *format = arg->format;
|
const char *format = arg->format;
|
||||||
|
|
||||||
blk = blk_by_name(arg->device);
|
bs = qmp_get_root_bs(arg->device, errp);
|
||||||
if (!blk) {
|
if (!bs) {
|
||||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
||||||
"Device '%s' not found", arg->device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
aio_context = blk_get_aio_context(blk);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
if (!blk_is_available(blk)) {
|
|
||||||
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, arg->device);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
bs = blk_bs(blk);
|
|
||||||
if (!arg->has_mode) {
|
if (!arg->has_mode) {
|
||||||
arg->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
arg->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
||||||
}
|
}
|
||||||
@@ -3630,21 +3523,13 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
|||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockBackend *blk;
|
|
||||||
BlockDriverState *target_bs;
|
BlockDriverState *target_bs;
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
|
BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
blk = blk_by_name(device);
|
bs = qmp_get_root_bs(device, errp);
|
||||||
if (!blk) {
|
|
||||||
error_setg(errp, "Device '%s' not found", device);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bs = blk_bs(blk);
|
|
||||||
|
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
error_setg(errp, "Device '%s' has no media", device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3785,7 +3670,6 @@ void qmp_change_backing_file(const char *device,
|
|||||||
const char *backing_file,
|
const char *backing_file,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockBackend *blk;
|
|
||||||
BlockDriverState *bs = NULL;
|
BlockDriverState *bs = NULL;
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
BlockDriverState *image_bs = NULL;
|
BlockDriverState *image_bs = NULL;
|
||||||
@@ -3794,22 +3678,14 @@ void qmp_change_backing_file(const char *device,
|
|||||||
int open_flags;
|
int open_flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
blk = blk_by_name(device);
|
bs = qmp_get_root_bs(device, errp);
|
||||||
if (!blk) {
|
if (!bs) {
|
||||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
||||||
"Device '%s' not found", device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
aio_context = blk_get_aio_context(blk);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
if (!blk_is_available(blk)) {
|
|
||||||
error_setg(errp, "Device '%s' has no medium", device);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
bs = blk_bs(blk);
|
|
||||||
|
|
||||||
image_bs = bdrv_lookup_bs(NULL, image_node_name, &local_err);
|
image_bs = bdrv_lookup_bs(NULL, image_node_name, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
|
|||||||
@@ -132,6 +132,10 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
|||||||
|
|
||||||
if (job_id == NULL) {
|
if (job_id == NULL) {
|
||||||
job_id = bdrv_get_device_name(bs);
|
job_id = bdrv_get_device_name(bs);
|
||||||
|
if (!*job_id) {
|
||||||
|
error_setg(errp, "An explicit job ID is required for this node");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!id_wellformed(job_id)) {
|
if (!id_wellformed(job_id)) {
|
||||||
|
|||||||
29
configure
vendored
29
configure
vendored
@@ -229,6 +229,7 @@ xfs=""
|
|||||||
|
|
||||||
vhost_net="no"
|
vhost_net="no"
|
||||||
vhost_scsi="no"
|
vhost_scsi="no"
|
||||||
|
vhost_vsock="no"
|
||||||
kvm="no"
|
kvm="no"
|
||||||
rdma=""
|
rdma=""
|
||||||
gprof="no"
|
gprof="no"
|
||||||
@@ -674,6 +675,7 @@ Haiku)
|
|||||||
kvm="yes"
|
kvm="yes"
|
||||||
vhost_net="yes"
|
vhost_net="yes"
|
||||||
vhost_scsi="yes"
|
vhost_scsi="yes"
|
||||||
|
vhost_vsock="yes"
|
||||||
QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES"
|
QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -1017,6 +1019,10 @@ for opt do
|
|||||||
;;
|
;;
|
||||||
--enable-vhost-scsi) vhost_scsi="yes"
|
--enable-vhost-scsi) vhost_scsi="yes"
|
||||||
;;
|
;;
|
||||||
|
--disable-vhost-vsock) vhost_vsock="no"
|
||||||
|
;;
|
||||||
|
--enable-vhost-vsock) vhost_vsock="yes"
|
||||||
|
;;
|
||||||
--disable-opengl) opengl="no"
|
--disable-opengl) opengl="no"
|
||||||
;;
|
;;
|
||||||
--enable-opengl) opengl="yes"
|
--enable-opengl) opengl="yes"
|
||||||
@@ -4191,6 +4197,18 @@ if compile_prog "" "" ; then
|
|||||||
posix_madvise=yes
|
posix_madvise=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
##########################################
|
||||||
|
# check if we have posix_syslog
|
||||||
|
|
||||||
|
posix_syslog=no
|
||||||
|
cat > $TMPC << EOF
|
||||||
|
#include <syslog.h>
|
||||||
|
int main(void) { openlog("qemu", LOG_PID, LOG_DAEMON); syslog(LOG_INFO, "configure"); return 0; }
|
||||||
|
EOF
|
||||||
|
if compile_prog "" "" ; then
|
||||||
|
posix_syslog=yes
|
||||||
|
fi
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
# check if trace backend exists
|
# check if trace backend exists
|
||||||
|
|
||||||
@@ -4871,6 +4889,7 @@ echo "uuid support $uuid"
|
|||||||
echo "libcap-ng support $cap_ng"
|
echo "libcap-ng support $cap_ng"
|
||||||
echo "vhost-net support $vhost_net"
|
echo "vhost-net support $vhost_net"
|
||||||
echo "vhost-scsi support $vhost_scsi"
|
echo "vhost-scsi support $vhost_scsi"
|
||||||
|
echo "vhost-vsock support $vhost_vsock"
|
||||||
echo "Trace backends $trace_backends"
|
echo "Trace backends $trace_backends"
|
||||||
if have_backend "simple"; then
|
if have_backend "simple"; then
|
||||||
echo "Trace output file $trace_file-<pid>"
|
echo "Trace output file $trace_file-<pid>"
|
||||||
@@ -5252,6 +5271,9 @@ fi
|
|||||||
if test "$vhost_net" = "yes" ; then
|
if test "$vhost_net" = "yes" ; then
|
||||||
echo "CONFIG_VHOST_NET_USED=y" >> $config_host_mak
|
echo "CONFIG_VHOST_NET_USED=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
if test "$vhost_vsock" = "yes" ; then
|
||||||
|
echo "CONFIG_VHOST_VSOCK=y" >> $config_host_mak
|
||||||
|
fi
|
||||||
if test "$blobs" = "yes" ; then
|
if test "$blobs" = "yes" ; then
|
||||||
echo "INSTALL_BLOBS=yes" >> $config_host_mak
|
echo "INSTALL_BLOBS=yes" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
@@ -5468,6 +5490,13 @@ if have_backend "ftrace"; then
|
|||||||
feature_not_found "ftrace(trace backend)" "ftrace requires Linux"
|
feature_not_found "ftrace(trace backend)" "ftrace requires Linux"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
if have_backend "syslog"; then
|
||||||
|
if test "$posix_syslog" = "yes" ; then
|
||||||
|
echo "CONFIG_TRACE_SYSLOG=y" >> $config_host_mak
|
||||||
|
else
|
||||||
|
feature_not_found "syslog(trace backend)" "syslog not available"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
|
echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
|
||||||
|
|
||||||
if test "$rdma" = "yes" ; then
|
if test "$rdma" = "yes" ; then
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
|||||||
|
|
||||||
if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
|
if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
|
||||||
!qcrypto_block_drivers[options->format]) {
|
!qcrypto_block_drivers[options->format]) {
|
||||||
error_setg(errp, "Unsupported block driver %d", options->format);
|
error_setg(errp, "Unsupported block driver %s",
|
||||||
|
QCryptoBlockFormat_lookup[options->format]);
|
||||||
g_free(block);
|
g_free(block);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -88,7 +89,8 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
|
|||||||
|
|
||||||
if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
|
if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
|
||||||
!qcrypto_block_drivers[options->format]) {
|
!qcrypto_block_drivers[options->format]) {
|
||||||
error_setg(errp, "Unsupported block driver %d", options->format);
|
error_setg(errp, "Unsupported block driver %s",
|
||||||
|
QCryptoBlockFormat_lookup[options->format]);
|
||||||
g_free(block);
|
g_free(block);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -244,7 +244,8 @@ static int qcrypto_cipher_init_aes(QCryptoCipher *cipher,
|
|||||||
if (cipher->mode != QCRYPTO_CIPHER_MODE_CBC &&
|
if (cipher->mode != QCRYPTO_CIPHER_MODE_CBC &&
|
||||||
cipher->mode != QCRYPTO_CIPHER_MODE_ECB &&
|
cipher->mode != QCRYPTO_CIPHER_MODE_ECB &&
|
||||||
cipher->mode != QCRYPTO_CIPHER_MODE_XTS) {
|
cipher->mode != QCRYPTO_CIPHER_MODE_XTS) {
|
||||||
error_setg(errp, "Unsupported cipher mode %d", cipher->mode);
|
error_setg(errp, "Unsupported cipher mode %s",
|
||||||
|
QCryptoCipherMode_lookup[cipher->mode]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,7 +377,8 @@ static int qcrypto_cipher_init_des_rfb(QCryptoCipher *cipher,
|
|||||||
QCryptoCipherBuiltin *ctxt;
|
QCryptoCipherBuiltin *ctxt;
|
||||||
|
|
||||||
if (cipher->mode != QCRYPTO_CIPHER_MODE_ECB) {
|
if (cipher->mode != QCRYPTO_CIPHER_MODE_ECB) {
|
||||||
error_setg(errp, "Unsupported cipher mode %d", cipher->mode);
|
error_setg(errp, "Unsupported cipher mode %s",
|
||||||
|
QCryptoCipherMode_lookup[cipher->mode]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +444,8 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"Unsupported cipher algorithm %d", cipher->alg);
|
"Unsupported cipher algorithm %s",
|
||||||
|
QCryptoCipherAlgorithm_lookup[cipher->alg]);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,8 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
|||||||
gcrymode = GCRY_CIPHER_MODE_CBC;
|
gcrymode = GCRY_CIPHER_MODE_CBC;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error_setg(errp, "Unsupported cipher mode %d", mode);
|
error_setg(errp, "Unsupported cipher mode %s",
|
||||||
|
QCryptoCipherMode_lookup[mode]);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +121,8 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error_setg(errp, "Unsupported cipher algorithm %d", alg);
|
error_setg(errp, "Unsupported cipher algorithm %s",
|
||||||
|
QCryptoCipherAlgorithm_lookup[alg]);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,6 +194,12 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
|
if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
|
||||||
|
if (ctx->blocksize != XTS_BLOCK_SIZE) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Cipher block size %zu must equal XTS block size %d",
|
||||||
|
ctx->blocksize, XTS_BLOCK_SIZE);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
ctx->iv = g_new0(uint8_t, ctx->blocksize);
|
ctx->iv = g_new0(uint8_t, ctx->blocksize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -227,7 +227,8 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
|||||||
case QCRYPTO_CIPHER_MODE_XTS:
|
case QCRYPTO_CIPHER_MODE_XTS:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error_setg(errp, "Unsupported cipher mode %d", mode);
|
error_setg(errp, "Unsupported cipher mode %s",
|
||||||
|
QCryptoCipherMode_lookup[mode]);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,7 +358,15 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error_setg(errp, "Unsupported cipher algorithm %d", alg);
|
error_setg(errp, "Unsupported cipher algorithm %s",
|
||||||
|
QCryptoCipherAlgorithm_lookup[alg]);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == QCRYPTO_CIPHER_MODE_XTS &&
|
||||||
|
ctx->blocksize != XTS_BLOCK_SIZE) {
|
||||||
|
error_setg(errp, "Cipher block size %zu must equal XTS block size %d",
|
||||||
|
ctx->blocksize, XTS_BLOCK_SIZE);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,8 +431,8 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error_setg(errp, "Unsupported cipher algorithm %d",
|
error_setg(errp, "Unsupported cipher mode %s",
|
||||||
cipher->alg);
|
QCryptoCipherMode_lookup[cipher->mode]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -456,19 +465,14 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case QCRYPTO_CIPHER_MODE_XTS:
|
case QCRYPTO_CIPHER_MODE_XTS:
|
||||||
if (ctx->blocksize != XTS_BLOCK_SIZE) {
|
|
||||||
error_setg(errp, "Block size must be %d not %zu",
|
|
||||||
XTS_BLOCK_SIZE, ctx->blocksize);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
xts_decrypt(ctx->ctx, ctx->ctx_tweak,
|
xts_decrypt(ctx->ctx, ctx->ctx_tweak,
|
||||||
ctx->alg_encrypt_wrapper, ctx->alg_decrypt_wrapper,
|
ctx->alg_encrypt_wrapper, ctx->alg_decrypt_wrapper,
|
||||||
ctx->iv, len, out, in);
|
ctx->iv, len, out, in);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error_setg(errp, "Unsupported cipher algorithm %d",
|
error_setg(errp, "Unsupported cipher mode %s",
|
||||||
cipher->alg);
|
QCryptoCipherMode_lookup[cipher->mode]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -59,8 +59,7 @@
|
|||||||
|
|
||||||
#if (defined(CONFIG_GCRYPT) && \
|
#if (defined(CONFIG_GCRYPT) && \
|
||||||
(!defined(CONFIG_GNUTLS) || \
|
(!defined(CONFIG_GNUTLS) || \
|
||||||
!defined(GNUTLS_VERSION_NUMBER) || \
|
(LIBGNUTLS_VERSION_NUMBER < 0x020c00)) && \
|
||||||
(GNUTLS_VERSION_NUMBER < 0x020c00)) && \
|
|
||||||
(!defined(GCRYPT_VERSION_NUMBER) || \
|
(!defined(GCRYPT_VERSION_NUMBER) || \
|
||||||
(GCRYPT_VERSION_NUMBER < 0x010600)))
|
(GCRYPT_VERSION_NUMBER < 0x010600)))
|
||||||
#define QCRYPTO_INIT_GCRYPT_THREADS
|
#define QCRYPTO_INIT_GCRYPT_THREADS
|
||||||
|
|||||||
@@ -615,7 +615,7 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cert != NULL && key != NULL) {
|
if (cert != NULL && key != NULL) {
|
||||||
#if GNUTLS_VERSION_NUMBER >= 0x030111
|
#if LIBGNUTLS_VERSION_NUMBER >= 0x030111
|
||||||
char *password = NULL;
|
char *password = NULL;
|
||||||
if (creds->passwordid) {
|
if (creds->passwordid) {
|
||||||
password = qcrypto_secret_lookup_as_utf8(creds->passwordid,
|
password = qcrypto_secret_lookup_as_utf8(creds->passwordid,
|
||||||
@@ -630,7 +630,7 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
|
|||||||
password,
|
password,
|
||||||
0);
|
0);
|
||||||
g_free(password);
|
g_free(password);
|
||||||
#else /* GNUTLS_VERSION_NUMBER < 0x030111 */
|
#else /* LIBGNUTLS_VERSION_NUMBER < 0x030111 */
|
||||||
if (creds->passwordid) {
|
if (creds->passwordid) {
|
||||||
error_setg(errp, "PKCS8 decryption requires GNUTLS >= 3.1.11");
|
error_setg(errp, "PKCS8 decryption requires GNUTLS >= 3.1.11");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@@ -638,7 +638,7 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
|
|||||||
ret = gnutls_certificate_set_x509_key_file(creds->data,
|
ret = gnutls_certificate_set_x509_key_file(creds->data,
|
||||||
cert, key,
|
cert, key,
|
||||||
GNUTLS_X509_FMT_PEM);
|
GNUTLS_X509_FMT_PEM);
|
||||||
#endif /* GNUTLS_VERSION_NUMBER < 0x030111 */
|
#endif
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg(errp, "Cannot load certificate '%s' & key '%s': %s",
|
error_setg(errp, "Cannot load certificate '%s' & key '%s': %s",
|
||||||
cert, key, gnutls_strerror(ret));
|
cert, key, gnutls_strerror(ret));
|
||||||
|
|||||||
@@ -192,6 +192,18 @@ After running qemu by root user, you can get the trace:
|
|||||||
|
|
||||||
Restriction: "ftrace" backend is restricted to Linux only.
|
Restriction: "ftrace" backend is restricted to Linux only.
|
||||||
|
|
||||||
|
=== Syslog ===
|
||||||
|
|
||||||
|
The "syslog" backend sends trace events using the POSIX syslog API. The log
|
||||||
|
is opened specifying the LOG_DAEMON facility and LOG_PID option (so events
|
||||||
|
are tagged with the pid of the particular QEMU process that generated
|
||||||
|
them). All events are logged at LOG_INFO level.
|
||||||
|
|
||||||
|
NOTE: syslog may squash duplicate consecutive trace events and apply rate
|
||||||
|
limiting.
|
||||||
|
|
||||||
|
Restriction: "syslog" backend is restricted to POSIX compliant OS.
|
||||||
|
|
||||||
==== Monitor commands ====
|
==== Monitor commands ====
|
||||||
|
|
||||||
* trace-file on|off|flush|set <path>
|
* trace-file on|off|flush|set <path>
|
||||||
|
|||||||
7
exec.c
7
exec.c
@@ -598,11 +598,14 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool cpu_index_auto_assigned;
|
||||||
|
|
||||||
static int cpu_get_free_index(void)
|
static int cpu_get_free_index(void)
|
||||||
{
|
{
|
||||||
CPUState *some_cpu;
|
CPUState *some_cpu;
|
||||||
int cpu_index = 0;
|
int cpu_index = 0;
|
||||||
|
|
||||||
|
cpu_index_auto_assigned = true;
|
||||||
CPU_FOREACH(some_cpu) {
|
CPU_FOREACH(some_cpu) {
|
||||||
cpu_index++;
|
cpu_index++;
|
||||||
}
|
}
|
||||||
@@ -620,6 +623,8 @@ void cpu_exec_exit(CPUState *cpu)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(!(cpu_index_auto_assigned && cpu != QTAILQ_LAST(&cpus, CPUTailQ)));
|
||||||
|
|
||||||
QTAILQ_REMOVE(&cpus, cpu, node);
|
QTAILQ_REMOVE(&cpus, cpu, node);
|
||||||
cpu->node.tqe_prev = NULL;
|
cpu->node.tqe_prev = NULL;
|
||||||
cpu->cpu_index = UNASSIGNED_CPU_INDEX;
|
cpu->cpu_index = UNASSIGNED_CPU_INDEX;
|
||||||
@@ -663,6 +668,8 @@ void cpu_exec_init(CPUState *cpu, Error **errp)
|
|||||||
if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) {
|
if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) {
|
||||||
cpu->cpu_index = cpu_get_free_index();
|
cpu->cpu_index = cpu_get_free_index();
|
||||||
assert(cpu->cpu_index != UNASSIGNED_CPU_INDEX);
|
assert(cpu->cpu_index != UNASSIGNED_CPU_INDEX);
|
||||||
|
} else {
|
||||||
|
assert(!cpu_index_auto_assigned);
|
||||||
}
|
}
|
||||||
QTAILQ_INSERT_TAIL(&cpus, cpu, node);
|
QTAILQ_INSERT_TAIL(&cpus, cpu, node);
|
||||||
cpu_list_unlock();
|
cpu_list_unlock();
|
||||||
|
|||||||
@@ -1182,8 +1182,8 @@ ETEXI
|
|||||||
|
|
||||||
{
|
{
|
||||||
.name = "drive_backup",
|
.name = "drive_backup",
|
||||||
.args_type = "reuse:-n,full:-f,device:B,target:s,format:s?",
|
.args_type = "reuse:-n,full:-f,compress:-c,device:B,target:s,format:s?",
|
||||||
.params = "[-n] [-f] device target [format]",
|
.params = "[-n] [-f] [-c] device target [format]",
|
||||||
.help = "initiates a point-in-time\n\t\t\t"
|
.help = "initiates a point-in-time\n\t\t\t"
|
||||||
"copy for a device. The device's contents are\n\t\t\t"
|
"copy for a device. The device's contents are\n\t\t\t"
|
||||||
"copied to the new image file, excluding data that\n\t\t\t"
|
"copied to the new image file, excluding data that\n\t\t\t"
|
||||||
@@ -1191,7 +1191,9 @@ ETEXI
|
|||||||
"The -n flag requests QEMU to reuse the image found\n\t\t\t"
|
"The -n flag requests QEMU to reuse the image found\n\t\t\t"
|
||||||
"in new-image-file, instead of recreating it from scratch.\n\t\t\t"
|
"in new-image-file, instead of recreating it from scratch.\n\t\t\t"
|
||||||
"The -f flag requests QEMU to copy the whole disk,\n\t\t\t"
|
"The -f flag requests QEMU to copy the whole disk,\n\t\t\t"
|
||||||
"so that the result does not need a backing file.\n\t\t\t",
|
"so that the result does not need a backing file.\n\t\t\t"
|
||||||
|
"The -c flag requests QEMU to compress backup data\n\t\t\t"
|
||||||
|
"(if the target format supports it).\n\t\t\t",
|
||||||
.mhandler.cmd = hmp_drive_backup,
|
.mhandler.cmd = hmp_drive_backup,
|
||||||
},
|
},
|
||||||
STEXI
|
STEXI
|
||||||
|
|||||||
37
hmp.c
37
hmp.c
@@ -1109,8 +1109,19 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
|
|||||||
const char *format = qdict_get_try_str(qdict, "format");
|
const char *format = qdict_get_try_str(qdict, "format");
|
||||||
bool reuse = qdict_get_try_bool(qdict, "reuse", false);
|
bool reuse = qdict_get_try_bool(qdict, "reuse", false);
|
||||||
bool full = qdict_get_try_bool(qdict, "full", false);
|
bool full = qdict_get_try_bool(qdict, "full", false);
|
||||||
enum NewImageMode mode;
|
bool compress = qdict_get_try_bool(qdict, "compress", false);
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
DriveBackup backup = {
|
||||||
|
.device = (char *)device,
|
||||||
|
.target = (char *)filename,
|
||||||
|
.has_format = !!format,
|
||||||
|
.format = (char *)format,
|
||||||
|
.sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
|
||||||
|
.has_mode = true,
|
||||||
|
.mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
|
||||||
|
.has_compress = !!compress,
|
||||||
|
.compress = compress,
|
||||||
|
};
|
||||||
|
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
error_setg(&err, QERR_MISSING_PARAMETER, "target");
|
error_setg(&err, QERR_MISSING_PARAMETER, "target");
|
||||||
@@ -1118,16 +1129,7 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reuse) {
|
qmp_drive_backup(&backup, &err);
|
||||||
mode = NEW_IMAGE_MODE_EXISTING;
|
|
||||||
} else {
|
|
||||||
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
|
||||||
}
|
|
||||||
|
|
||||||
qmp_drive_backup(false, NULL, device, filename, !!format, format,
|
|
||||||
full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
|
|
||||||
true, mode, false, 0, false, NULL,
|
|
||||||
false, 0, false, 0, &err);
|
|
||||||
hmp_handle_error(mon, &err);
|
hmp_handle_error(mon, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1921,11 +1923,22 @@ void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
|
|||||||
void hmp_qemu_io(Monitor *mon, const QDict *qdict)
|
void hmp_qemu_io(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
|
BlockBackend *local_blk = NULL;
|
||||||
const char* device = qdict_get_str(qdict, "device");
|
const char* device = qdict_get_str(qdict, "device");
|
||||||
const char* command = qdict_get_str(qdict, "command");
|
const char* command = qdict_get_str(qdict, "command");
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
blk = blk_by_name(device);
|
blk = blk_by_name(device);
|
||||||
|
if (!blk) {
|
||||||
|
BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err);
|
||||||
|
if (bs) {
|
||||||
|
blk = local_blk = blk_new();
|
||||||
|
blk_insert_bs(blk, bs);
|
||||||
|
} else {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (blk) {
|
if (blk) {
|
||||||
AioContext *aio_context = blk_get_aio_context(blk);
|
AioContext *aio_context = blk_get_aio_context(blk);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
@@ -1938,6 +1951,8 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
|
|||||||
"Device '%s' not found", device);
|
"Device '%s' not found", device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
blk_unref(local_blk);
|
||||||
hmp_handle_error(mon, &err);
|
hmp_handle_error(mon, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#define AST2400_FMC_BASE 0X1E620000
|
#define AST2400_FMC_BASE 0X1E620000
|
||||||
#define AST2400_SPI_BASE 0X1E630000
|
#define AST2400_SPI_BASE 0X1E630000
|
||||||
#define AST2400_VIC_BASE 0x1E6C0000
|
#define AST2400_VIC_BASE 0x1E6C0000
|
||||||
|
#define AST2400_SDMC_BASE 0x1E6E0000
|
||||||
#define AST2400_SCU_BASE 0x1E6E2000
|
#define AST2400_SCU_BASE 0x1E6E2000
|
||||||
#define AST2400_TIMER_BASE 0x1E782000
|
#define AST2400_TIMER_BASE 0x1E782000
|
||||||
#define AST2400_I2C_BASE 0x1E78A000
|
#define AST2400_I2C_BASE 0x1E78A000
|
||||||
@@ -97,6 +98,12 @@ static void ast2400_init(Object *obj)
|
|||||||
object_initialize(&s->spi, sizeof(s->spi), "aspeed.smc.spi");
|
object_initialize(&s->spi, sizeof(s->spi), "aspeed.smc.spi");
|
||||||
object_property_add_child(obj, "spi", OBJECT(&s->spi), NULL);
|
object_property_add_child(obj, "spi", OBJECT(&s->spi), NULL);
|
||||||
qdev_set_parent_bus(DEVICE(&s->spi), sysbus_get_default());
|
qdev_set_parent_bus(DEVICE(&s->spi), sysbus_get_default());
|
||||||
|
|
||||||
|
object_initialize(&s->sdmc, sizeof(s->sdmc), TYPE_ASPEED_SDMC);
|
||||||
|
object_property_add_child(obj, "sdmc", OBJECT(&s->sdmc), NULL);
|
||||||
|
qdev_set_parent_bus(DEVICE(&s->sdmc), sysbus_get_default());
|
||||||
|
qdev_prop_set_uint32(DEVICE(&s->sdmc), "silicon-rev",
|
||||||
|
AST2400_A0_SILICON_REV);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ast2400_realize(DeviceState *dev, Error **errp)
|
static void ast2400_realize(DeviceState *dev, Error **errp)
|
||||||
@@ -183,6 +190,14 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
|
|||||||
}
|
}
|
||||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, AST2400_SPI_BASE);
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, AST2400_SPI_BASE);
|
||||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 1, AST2400_SPI_FLASH_BASE);
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 1, AST2400_SPI_FLASH_BASE);
|
||||||
|
|
||||||
|
/* SDMC - SDRAM Memory Controller */
|
||||||
|
object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err);
|
||||||
|
if (err) {
|
||||||
|
error_propagate(errp, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, AST2400_SDMC_BASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ast2400_class_init(ObjectClass *oc, void *data)
|
static void ast2400_class_init(ObjectClass *oc, void *data)
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
|
|||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
|
||||||
for (i = 0; i < smp_cpus; i++) {
|
for (i = 0; i < smp_cpus; i++) {
|
||||||
Aml *dev = aml_device("C%03x", i);
|
Aml *dev = aml_device("C%.03X", i);
|
||||||
aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
|
aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
|
||||||
aml_append(dev, aml_name_decl("_UID", aml_int(i)));
|
aml_append(dev, aml_name_decl("_UID", aml_int(i)));
|
||||||
aml_append(scope, dev);
|
aml_append(scope, dev);
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ typedef struct GUSState {
|
|||||||
int64_t last_ticks;
|
int64_t last_ticks;
|
||||||
qemu_irq pic;
|
qemu_irq pic;
|
||||||
IsaDma *isa_dma;
|
IsaDma *isa_dma;
|
||||||
|
PortioList portio_list1;
|
||||||
|
PortioList portio_list2;
|
||||||
} GUSState;
|
} GUSState;
|
||||||
|
|
||||||
static uint32_t gus_readb(void *opaque, uint32_t nport)
|
static uint32_t gus_readb(void *opaque, uint32_t nport)
|
||||||
@@ -265,9 +267,10 @@ static void gus_realizefn (DeviceState *dev, Error **errp)
|
|||||||
s->samples = AUD_get_buffer_size_out (s->voice) >> s->shift;
|
s->samples = AUD_get_buffer_size_out (s->voice) >> s->shift;
|
||||||
s->mixbuf = g_malloc0 (s->samples << s->shift);
|
s->mixbuf = g_malloc0 (s->samples << s->shift);
|
||||||
|
|
||||||
isa_register_portio_list (d, s->port, gus_portio_list1, s, "gus");
|
isa_register_portio_list(d, &s->portio_list1, s->port,
|
||||||
isa_register_portio_list (d, (s->port + 0x100) & 0xf00,
|
gus_portio_list1, s, "gus");
|
||||||
gus_portio_list2, s, "gus");
|
isa_register_portio_list(d, &s->portio_list2, (s->port + 0x100) & 0xf00,
|
||||||
|
gus_portio_list2, s, "gus");
|
||||||
|
|
||||||
s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->emu.gusdma);
|
s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->emu.gusdma);
|
||||||
k = ISADMA_GET_CLASS(s->isa_dma);
|
k = ISADMA_GET_CLASS(s->isa_dma);
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ typedef struct SB16State {
|
|||||||
/* mixer state */
|
/* mixer state */
|
||||||
int mixer_nreg;
|
int mixer_nreg;
|
||||||
uint8_t mixer_regs[256];
|
uint8_t mixer_regs[256];
|
||||||
|
PortioList portio_list;
|
||||||
} SB16State;
|
} SB16State;
|
||||||
|
|
||||||
static void SB_audio_callback (void *opaque, int free);
|
static void SB_audio_callback (void *opaque, int free);
|
||||||
@@ -1378,7 +1379,8 @@ static void sb16_realizefn (DeviceState *dev, Error **errp)
|
|||||||
dolog ("warning: Could not create auxiliary timer\n");
|
dolog ("warning: Could not create auxiliary timer\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
isa_register_portio_list (isadev, s->port, sb16_ioport_list, s, "sb16");
|
isa_register_portio_list(isadev, &s->portio_list, s->port,
|
||||||
|
sb16_ioport_list, s, "sb16");
|
||||||
|
|
||||||
s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma);
|
s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma);
|
||||||
k = ISADMA_GET_CLASS(s->isa_hdma);
|
k = ISADMA_GET_CLASS(s->isa_hdma);
|
||||||
|
|||||||
@@ -692,6 +692,7 @@ struct FDCtrl {
|
|||||||
/* Timers state */
|
/* Timers state */
|
||||||
uint8_t timer0;
|
uint8_t timer0;
|
||||||
uint8_t timer1;
|
uint8_t timer1;
|
||||||
|
PortioList portio_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
static FloppyDriveType get_fallback_drive_type(FDrive *drv)
|
static FloppyDriveType get_fallback_drive_type(FDrive *drv)
|
||||||
@@ -2495,7 +2496,8 @@ static void isabus_fdc_realize(DeviceState *dev, Error **errp)
|
|||||||
FDCtrl *fdctrl = &isa->state;
|
FDCtrl *fdctrl = &isa->state;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
isa_register_portio_list(isadev, isa->iobase, fdc_portio_list, fdctrl,
|
isa_register_portio_list(isadev, &fdctrl->portio_list,
|
||||||
|
isa->iobase, fdc_portio_list, fdctrl,
|
||||||
"fdc");
|
"fdc");
|
||||||
|
|
||||||
isa_init_irq(isadev, &fdctrl->irq, isa->irq);
|
isa_init_irq(isadev, &fdctrl->irq, isa->irq);
|
||||||
|
|||||||
@@ -1189,9 +1189,9 @@ static Property m25p80_properties[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const VMStateDescription vmstate_m25p80 = {
|
static const VMStateDescription vmstate_m25p80 = {
|
||||||
.name = "xilinx_spi",
|
.name = "m25p80",
|
||||||
.version_id = 3,
|
.version_id = 0,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 0,
|
||||||
.pre_save = m25p80_pre_save,
|
.pre_save = m25p80_pre_save,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8(state, Flash),
|
VMSTATE_UINT8(state, Flash),
|
||||||
@@ -1200,20 +1200,19 @@ static const VMStateDescription vmstate_m25p80 = {
|
|||||||
VMSTATE_UINT32(pos, Flash),
|
VMSTATE_UINT32(pos, Flash),
|
||||||
VMSTATE_UINT8(needed_bytes, Flash),
|
VMSTATE_UINT8(needed_bytes, Flash),
|
||||||
VMSTATE_UINT8(cmd_in_progress, Flash),
|
VMSTATE_UINT8(cmd_in_progress, Flash),
|
||||||
VMSTATE_UNUSED(4),
|
|
||||||
VMSTATE_UINT32(cur_addr, Flash),
|
VMSTATE_UINT32(cur_addr, Flash),
|
||||||
VMSTATE_BOOL(write_enable, Flash),
|
VMSTATE_BOOL(write_enable, Flash),
|
||||||
VMSTATE_BOOL_V(reset_enable, Flash, 2),
|
VMSTATE_BOOL(reset_enable, Flash),
|
||||||
VMSTATE_UINT8_V(ear, Flash, 2),
|
VMSTATE_UINT8(ear, Flash),
|
||||||
VMSTATE_BOOL_V(four_bytes_address_mode, Flash, 2),
|
VMSTATE_BOOL(four_bytes_address_mode, Flash),
|
||||||
VMSTATE_UINT32_V(nonvolatile_cfg, Flash, 2),
|
VMSTATE_UINT32(nonvolatile_cfg, Flash),
|
||||||
VMSTATE_UINT32_V(volatile_cfg, Flash, 2),
|
VMSTATE_UINT32(volatile_cfg, Flash),
|
||||||
VMSTATE_UINT32_V(enh_volatile_cfg, Flash, 2),
|
VMSTATE_UINT32(enh_volatile_cfg, Flash),
|
||||||
VMSTATE_BOOL_V(quad_enable, Flash, 3),
|
VMSTATE_BOOL(quad_enable, Flash),
|
||||||
VMSTATE_UINT8_V(spansion_cr1nv, Flash, 3),
|
VMSTATE_UINT8(spansion_cr1nv, Flash),
|
||||||
VMSTATE_UINT8_V(spansion_cr2nv, Flash, 3),
|
VMSTATE_UINT8(spansion_cr2nv, Flash),
|
||||||
VMSTATE_UINT8_V(spansion_cr3nv, Flash, 3),
|
VMSTATE_UINT8(spansion_cr3nv, Flash),
|
||||||
VMSTATE_UINT8_V(spansion_cr4nv, Flash, 3),
|
VMSTATE_UINT8(spansion_cr4nv, Flash),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -976,14 +976,16 @@ static int blk_connect(struct XenDevice *xendev)
|
|||||||
blkdev->feature_persistent = !!pers;
|
blkdev->feature_persistent = !!pers;
|
||||||
}
|
}
|
||||||
|
|
||||||
blkdev->protocol = BLKIF_PROTOCOL_NATIVE;
|
if (!blkdev->xendev.protocol) {
|
||||||
if (blkdev->xendev.protocol) {
|
blkdev->protocol = BLKIF_PROTOCOL_NATIVE;
|
||||||
if (strcmp(blkdev->xendev.protocol, XEN_IO_PROTO_ABI_X86_32) == 0) {
|
} else if (strcmp(blkdev->xendev.protocol, XEN_IO_PROTO_ABI_NATIVE) == 0) {
|
||||||
blkdev->protocol = BLKIF_PROTOCOL_X86_32;
|
blkdev->protocol = BLKIF_PROTOCOL_NATIVE;
|
||||||
}
|
} else if (strcmp(blkdev->xendev.protocol, XEN_IO_PROTO_ABI_X86_32) == 0) {
|
||||||
if (strcmp(blkdev->xendev.protocol, XEN_IO_PROTO_ABI_X86_64) == 0) {
|
blkdev->protocol = BLKIF_PROTOCOL_X86_32;
|
||||||
blkdev->protocol = BLKIF_PROTOCOL_X86_64;
|
} else if (strcmp(blkdev->xendev.protocol, XEN_IO_PROTO_ABI_X86_64) == 0) {
|
||||||
}
|
blkdev->protocol = BLKIF_PROTOCOL_X86_64;
|
||||||
|
} else {
|
||||||
|
blkdev->protocol = BLKIF_PROTOCOL_NATIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
blkdev->sring = xengnttab_map_grant_ref(blkdev->xendev.gnttabdev,
|
blkdev->sring = xengnttab_map_grant_ref(blkdev->xendev.gnttabdev,
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ typedef struct ParallelState {
|
|||||||
uint32_t last_read_offset; /* For debugging */
|
uint32_t last_read_offset; /* For debugging */
|
||||||
/* Memory-mapped interface */
|
/* Memory-mapped interface */
|
||||||
int it_shift;
|
int it_shift;
|
||||||
|
PortioList portio_list;
|
||||||
} ParallelState;
|
} ParallelState;
|
||||||
|
|
||||||
#define TYPE_ISA_PARALLEL "isa-parallel"
|
#define TYPE_ISA_PARALLEL "isa-parallel"
|
||||||
@@ -532,7 +533,7 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
|
|||||||
s->status = dummy;
|
s->status = dummy;
|
||||||
}
|
}
|
||||||
|
|
||||||
isa_register_portio_list(isadev, base,
|
isa_register_portio_list(isadev, &s->portio_list, base,
|
||||||
(s->hw_driver
|
(s->hw_driver
|
||||||
? &isa_parallel_portio_hw_list[0]
|
? &isa_parallel_portio_hw_list[0]
|
||||||
: &isa_parallel_portio_sw_list[0]),
|
: &isa_parallel_portio_sw_list[0]),
|
||||||
|
|||||||
@@ -78,8 +78,7 @@ static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
|
|||||||
{
|
{
|
||||||
const char *typename = object_get_typename(OBJECT(bus));
|
const char *typename = object_get_typename(OBJECT(bus));
|
||||||
BusClass *bc;
|
BusClass *bc;
|
||||||
char *buf;
|
int i, bus_id;
|
||||||
int i, len, bus_id;
|
|
||||||
|
|
||||||
bus->parent = parent;
|
bus->parent = parent;
|
||||||
|
|
||||||
@@ -88,23 +87,15 @@ static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
|
|||||||
} else if (bus->parent && bus->parent->id) {
|
} else if (bus->parent && bus->parent->id) {
|
||||||
/* parent device has id -> use it plus parent-bus-id for bus name */
|
/* parent device has id -> use it plus parent-bus-id for bus name */
|
||||||
bus_id = bus->parent->num_child_bus;
|
bus_id = bus->parent->num_child_bus;
|
||||||
|
bus->name = g_strdup_printf("%s.%d", bus->parent->id, bus_id);
|
||||||
len = strlen(bus->parent->id) + 16;
|
|
||||||
buf = g_malloc(len);
|
|
||||||
snprintf(buf, len, "%s.%d", bus->parent->id, bus_id);
|
|
||||||
bus->name = buf;
|
|
||||||
} else {
|
} else {
|
||||||
/* no id -> use lowercase bus type plus global bus-id for bus name */
|
/* no id -> use lowercase bus type plus global bus-id for bus name */
|
||||||
bc = BUS_GET_CLASS(bus);
|
bc = BUS_GET_CLASS(bus);
|
||||||
bus_id = bc->automatic_ids++;
|
bus_id = bc->automatic_ids++;
|
||||||
|
bus->name = g_strdup_printf("%s.%d", typename, bus_id);
|
||||||
len = strlen(typename) + 16;
|
for (i = 0; bus->name[i]; i++) {
|
||||||
buf = g_malloc(len);
|
bus->name[i] = qemu_tolower(bus->name[i]);
|
||||||
len = snprintf(buf, len, "%s.%d", typename, bus_id);
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
buf[i] = qemu_tolower(buf[i]);
|
|
||||||
}
|
}
|
||||||
bus->name = buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bus->parent) {
|
if (bus->parent) {
|
||||||
@@ -229,7 +220,7 @@ static void qbus_finalize(Object *obj)
|
|||||||
{
|
{
|
||||||
BusState *bus = BUS(obj);
|
BusState *bus = BUS(obj);
|
||||||
|
|
||||||
g_free((char *)bus->name);
|
g_free(bus->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo bus_info = {
|
static const TypeInfo bus_info = {
|
||||||
|
|||||||
@@ -561,6 +561,7 @@ static void machine_class_finalize(ObjectClass *klass, void *data)
|
|||||||
if (mc->compat_props) {
|
if (mc->compat_props) {
|
||||||
g_array_free(mc->compat_props, true);
|
g_array_free(mc->compat_props, true);
|
||||||
}
|
}
|
||||||
|
g_free(mc->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void machine_register_compat_props(MachineState *machine)
|
void machine_register_compat_props(MachineState *machine)
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ typedef struct ISAVGAState {
|
|||||||
ISADevice parent_obj;
|
ISADevice parent_obj;
|
||||||
|
|
||||||
struct VGACommonState state;
|
struct VGACommonState state;
|
||||||
|
PortioList portio_vga;
|
||||||
|
PortioList portio_vbe;
|
||||||
} ISAVGAState;
|
} ISAVGAState;
|
||||||
|
|
||||||
static void vga_isa_reset(DeviceState *dev)
|
static void vga_isa_reset(DeviceState *dev)
|
||||||
@@ -60,9 +62,11 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp)
|
|||||||
vga_common_init(s, OBJECT(dev), true);
|
vga_common_init(s, OBJECT(dev), true);
|
||||||
s->legacy_address_space = isa_address_space(isadev);
|
s->legacy_address_space = isa_address_space(isadev);
|
||||||
vga_io_memory = vga_init_io(s, OBJECT(dev), &vga_ports, &vbe_ports);
|
vga_io_memory = vga_init_io(s, OBJECT(dev), &vga_ports, &vbe_ports);
|
||||||
isa_register_portio_list(isadev, 0x3b0, vga_ports, s, "vga");
|
isa_register_portio_list(isadev, &d->portio_vga,
|
||||||
|
0x3b0, vga_ports, s, "vga");
|
||||||
if (vbe_ports) {
|
if (vbe_ports) {
|
||||||
isa_register_portio_list(isadev, 0x1ce, vbe_ports, s, "vbe");
|
isa_register_portio_list(isadev, &d->portio_vbe,
|
||||||
|
0x1ce, vbe_ports, s, "vbe");
|
||||||
}
|
}
|
||||||
memory_region_add_subregion_overlap(isa_address_space(isadev),
|
memory_region_add_subregion_overlap(isa_address_space(isadev),
|
||||||
0x000a0000,
|
0x000a0000,
|
||||||
|
|||||||
@@ -553,10 +553,12 @@ static void i8257_realize(DeviceState *dev, Error **errp)
|
|||||||
memory_region_add_subregion(isa_address_space_io(isa),
|
memory_region_add_subregion(isa_address_space_io(isa),
|
||||||
d->base, &d->channel_io);
|
d->base, &d->channel_io);
|
||||||
|
|
||||||
isa_register_portio_list(isa, d->page_base, page_portio_list, d,
|
isa_register_portio_list(isa, &d->portio_page,
|
||||||
|
d->page_base, page_portio_list, d,
|
||||||
"dma-page");
|
"dma-page");
|
||||||
if (d->pageh_base >= 0) {
|
if (d->pageh_base >= 0) {
|
||||||
isa_register_portio_list(isa, d->pageh_base, pageh_portio_list, d,
|
isa_register_portio_list(isa, &d->portio_pageh,
|
||||||
|
d->pageh_base, pageh_portio_list, d,
|
||||||
"dma-pageh");
|
"dma-pageh");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -789,7 +789,7 @@ static gint crs_range_compare(gconstpointer a, gconstpointer b)
|
|||||||
static void crs_replace_with_free_ranges(GPtrArray *ranges,
|
static void crs_replace_with_free_ranges(GPtrArray *ranges,
|
||||||
uint64_t start, uint64_t end)
|
uint64_t start, uint64_t end)
|
||||||
{
|
{
|
||||||
GPtrArray *free_ranges = g_ptr_array_new_with_free_func(crs_range_free);
|
GPtrArray *free_ranges = g_ptr_array_new();
|
||||||
uint64_t free_base = start;
|
uint64_t free_base = start;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -813,7 +813,7 @@ static void crs_replace_with_free_ranges(GPtrArray *ranges,
|
|||||||
g_ptr_array_add(ranges, g_ptr_array_index(free_ranges, i));
|
g_ptr_array_add(ranges, g_ptr_array_index(free_ranges, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
g_ptr_array_free(free_ranges, false);
|
g_ptr_array_free(free_ranges, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -530,9 +530,9 @@ static uint64_t port92_read(void *opaque, hwaddr addr,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void port92_init(ISADevice *dev, qemu_irq *a20_out)
|
static void port92_init(ISADevice *dev, qemu_irq a20_out)
|
||||||
{
|
{
|
||||||
qdev_connect_gpio_out_named(DEVICE(dev), PORT92_A20_LINE, 0, *a20_out);
|
qdev_connect_gpio_out_named(DEVICE(dev), PORT92_A20_LINE, 0, a20_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_port92_isa = {
|
static const VMStateDescription vmstate_port92_isa = {
|
||||||
@@ -1594,7 +1594,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
|
|||||||
|
|
||||||
a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
|
a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
|
||||||
i8042 = isa_create_simple(isa_bus, "i8042");
|
i8042 = isa_create_simple(isa_bus, "i8042");
|
||||||
i8042_setup_a20_line(i8042, &a20_line[0]);
|
i8042_setup_a20_line(i8042, a20_line[0]);
|
||||||
if (!no_vmport) {
|
if (!no_vmport) {
|
||||||
vmport_init(isa_bus);
|
vmport_init(isa_bus);
|
||||||
vmmouse = isa_try_create(isa_bus, "vmmouse");
|
vmmouse = isa_try_create(isa_bus, "vmmouse");
|
||||||
@@ -1607,7 +1607,8 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
|
|||||||
qdev_init_nofail(dev);
|
qdev_init_nofail(dev);
|
||||||
}
|
}
|
||||||
port92 = isa_create_simple(isa_bus, "port92");
|
port92 = isa_create_simple(isa_bus, "port92");
|
||||||
port92_init(port92, &a20_line[1]);
|
port92_init(port92, a20_line[1]);
|
||||||
|
g_free(a20_line);
|
||||||
|
|
||||||
DMA_init(isa_bus, 0);
|
DMA_init(isa_bus, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ static void pc_init1(MachineState *machine,
|
|||||||
ISABus *isa_bus;
|
ISABus *isa_bus;
|
||||||
PCII440FXState *i440fx_state;
|
PCII440FXState *i440fx_state;
|
||||||
int piix3_devfn = -1;
|
int piix3_devfn = -1;
|
||||||
qemu_irq *gsi;
|
|
||||||
qemu_irq *i8259;
|
qemu_irq *i8259;
|
||||||
qemu_irq smi_irq;
|
qemu_irq smi_irq;
|
||||||
GSIState *gsi_state;
|
GSIState *gsi_state;
|
||||||
@@ -185,16 +184,16 @@ static void pc_init1(MachineState *machine,
|
|||||||
gsi_state = g_malloc0(sizeof(*gsi_state));
|
gsi_state = g_malloc0(sizeof(*gsi_state));
|
||||||
if (kvm_ioapic_in_kernel()) {
|
if (kvm_ioapic_in_kernel()) {
|
||||||
kvm_pc_setup_irq_routing(pcmc->pci_enabled);
|
kvm_pc_setup_irq_routing(pcmc->pci_enabled);
|
||||||
gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
|
pcms->gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
|
||||||
GSI_NUM_PINS);
|
GSI_NUM_PINS);
|
||||||
} else {
|
} else {
|
||||||
gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
|
pcms->gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcmc->pci_enabled) {
|
if (pcmc->pci_enabled) {
|
||||||
pci_bus = i440fx_init(host_type,
|
pci_bus = i440fx_init(host_type,
|
||||||
pci_type,
|
pci_type,
|
||||||
&i440fx_state, &piix3_devfn, &isa_bus, gsi,
|
&i440fx_state, &piix3_devfn, &isa_bus, pcms->gsi,
|
||||||
system_memory, system_io, machine->ram_size,
|
system_memory, system_io, machine->ram_size,
|
||||||
pcms->below_4g_mem_size,
|
pcms->below_4g_mem_size,
|
||||||
pcms->above_4g_mem_size,
|
pcms->above_4g_mem_size,
|
||||||
@@ -207,7 +206,7 @@ static void pc_init1(MachineState *machine,
|
|||||||
&error_abort);
|
&error_abort);
|
||||||
no_hpet = 1;
|
no_hpet = 1;
|
||||||
}
|
}
|
||||||
isa_bus_irqs(isa_bus, gsi);
|
isa_bus_irqs(isa_bus, pcms->gsi);
|
||||||
|
|
||||||
if (kvm_pic_in_kernel()) {
|
if (kvm_pic_in_kernel()) {
|
||||||
i8259 = kvm_i8259_init(isa_bus);
|
i8259 = kvm_i8259_init(isa_bus);
|
||||||
@@ -225,7 +224,7 @@ static void pc_init1(MachineState *machine,
|
|||||||
ioapic_init_gsi(gsi_state, "i440fx");
|
ioapic_init_gsi(gsi_state, "i440fx");
|
||||||
}
|
}
|
||||||
|
|
||||||
pc_register_ferr_irq(gsi[13]);
|
pc_register_ferr_irq(pcms->gsi[13]);
|
||||||
|
|
||||||
pc_vga_init(isa_bus, pcmc->pci_enabled ? pci_bus : NULL);
|
pc_vga_init(isa_bus, pcmc->pci_enabled ? pci_bus : NULL);
|
||||||
|
|
||||||
@@ -235,7 +234,7 @@ static void pc_init1(MachineState *machine,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* init basic PC hardware */
|
/* init basic PC hardware */
|
||||||
pc_basic_device_init(isa_bus, gsi, &rtc_state, true,
|
pc_basic_device_init(isa_bus, pcms->gsi, &rtc_state, true,
|
||||||
(pcms->vmport != ON_OFF_AUTO_ON), 0x4);
|
(pcms->vmport != ON_OFF_AUTO_ON), 0x4);
|
||||||
|
|
||||||
pc_nic_init(isa_bus, pci_bus);
|
pc_nic_init(isa_bus, pci_bus);
|
||||||
@@ -279,7 +278,7 @@ static void pc_init1(MachineState *machine,
|
|||||||
smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0);
|
smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0);
|
||||||
/* TODO: Populate SPD eeprom data. */
|
/* TODO: Populate SPD eeprom data. */
|
||||||
smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
|
smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
|
||||||
gsi[9], smi_irq,
|
pcms->gsi[9], smi_irq,
|
||||||
pc_machine_is_smm_enabled(pcms),
|
pc_machine_is_smm_enabled(pcms),
|
||||||
&piix4_pm);
|
&piix4_pm);
|
||||||
smbus_eeprom_init(smbus, 8, NULL, 0);
|
smbus_eeprom_init(smbus, 8, NULL, 0);
|
||||||
@@ -438,13 +437,25 @@ static void pc_i440fx_machine_options(MachineClass *m)
|
|||||||
m->default_display = "std";
|
m->default_display = "std";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_i440fx_2_7_machine_options(MachineClass *m)
|
static void pc_i440fx_2_8_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_i440fx_machine_options(m);
|
pc_i440fx_machine_options(m);
|
||||||
m->alias = "pc";
|
m->alias = "pc";
|
||||||
m->is_default = 1;
|
m->is_default = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_I440FX_MACHINE(v2_8, "pc-i440fx-2.8", NULL,
|
||||||
|
pc_i440fx_2_8_machine_options);
|
||||||
|
|
||||||
|
|
||||||
|
static void pc_i440fx_2_7_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_i440fx_2_8_machine_options(m);
|
||||||
|
m->is_default = 0;
|
||||||
|
m->alias = NULL;
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_7);
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_I440FX_MACHINE(v2_7, "pc-i440fx-2.7", NULL,
|
DEFINE_I440FX_MACHINE(v2_7, "pc-i440fx-2.7", NULL,
|
||||||
pc_i440fx_2_7_machine_options);
|
pc_i440fx_2_7_machine_options);
|
||||||
|
|
||||||
@@ -453,8 +464,6 @@ static void pc_i440fx_2_6_machine_options(MachineClass *m)
|
|||||||
{
|
{
|
||||||
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||||
pc_i440fx_2_7_machine_options(m);
|
pc_i440fx_2_7_machine_options(m);
|
||||||
m->is_default = 0;
|
|
||||||
m->alias = NULL;
|
|
||||||
pcmc->legacy_cpu_hotplug = true;
|
pcmc->legacy_cpu_hotplug = true;
|
||||||
SET_MACHINE_COMPAT(m, PC_COMPAT_2_6);
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_6);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ static void pc_q35_init(MachineState *machine)
|
|||||||
MemoryRegion *ram_memory;
|
MemoryRegion *ram_memory;
|
||||||
GSIState *gsi_state;
|
GSIState *gsi_state;
|
||||||
ISABus *isa_bus;
|
ISABus *isa_bus;
|
||||||
qemu_irq *gsi;
|
|
||||||
qemu_irq *i8259;
|
qemu_irq *i8259;
|
||||||
int i;
|
int i;
|
||||||
ICH9LPCState *ich9_lpc;
|
ICH9LPCState *ich9_lpc;
|
||||||
@@ -153,10 +152,10 @@ static void pc_q35_init(MachineState *machine)
|
|||||||
gsi_state = g_malloc0(sizeof(*gsi_state));
|
gsi_state = g_malloc0(sizeof(*gsi_state));
|
||||||
if (kvm_ioapic_in_kernel()) {
|
if (kvm_ioapic_in_kernel()) {
|
||||||
kvm_pc_setup_irq_routing(pcmc->pci_enabled);
|
kvm_pc_setup_irq_routing(pcmc->pci_enabled);
|
||||||
gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
|
pcms->gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
|
||||||
GSI_NUM_PINS);
|
GSI_NUM_PINS);
|
||||||
} else {
|
} else {
|
||||||
gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
|
pcms->gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create pci host bus */
|
/* create pci host bus */
|
||||||
@@ -195,7 +194,7 @@ static void pc_q35_init(MachineState *machine)
|
|||||||
ich9_lpc = ICH9_LPC_DEVICE(lpc);
|
ich9_lpc = ICH9_LPC_DEVICE(lpc);
|
||||||
lpc_dev = DEVICE(lpc);
|
lpc_dev = DEVICE(lpc);
|
||||||
for (i = 0; i < GSI_NUM_PINS; i++) {
|
for (i = 0; i < GSI_NUM_PINS; i++) {
|
||||||
qdev_connect_gpio_out_named(lpc_dev, ICH9_GPIO_GSI, i, gsi[i]);
|
qdev_connect_gpio_out_named(lpc_dev, ICH9_GPIO_GSI, i, pcms->gsi[i]);
|
||||||
}
|
}
|
||||||
pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
|
pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
|
||||||
ICH9_LPC_NB_PIRQS);
|
ICH9_LPC_NB_PIRQS);
|
||||||
@@ -213,11 +212,13 @@ static void pc_q35_init(MachineState *machine)
|
|||||||
for (i = 0; i < ISA_NUM_IRQS; i++) {
|
for (i = 0; i < ISA_NUM_IRQS; i++) {
|
||||||
gsi_state->i8259_irq[i] = i8259[i];
|
gsi_state->i8259_irq[i] = i8259[i];
|
||||||
}
|
}
|
||||||
|
g_free(i8259);
|
||||||
|
|
||||||
if (pcmc->pci_enabled) {
|
if (pcmc->pci_enabled) {
|
||||||
ioapic_init_gsi(gsi_state, "q35");
|
ioapic_init_gsi(gsi_state, "q35");
|
||||||
}
|
}
|
||||||
|
|
||||||
pc_register_ferr_irq(gsi[13]);
|
pc_register_ferr_irq(pcms->gsi[13]);
|
||||||
|
|
||||||
assert(pcms->vmport != ON_OFF_AUTO__MAX);
|
assert(pcms->vmport != ON_OFF_AUTO__MAX);
|
||||||
if (pcms->vmport == ON_OFF_AUTO_AUTO) {
|
if (pcms->vmport == ON_OFF_AUTO_AUTO) {
|
||||||
@@ -225,7 +226,7 @@ static void pc_q35_init(MachineState *machine)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* init basic PC hardware */
|
/* init basic PC hardware */
|
||||||
pc_basic_device_init(isa_bus, gsi, &rtc_state, !mc->no_floppy,
|
pc_basic_device_init(isa_bus, pcms->gsi, &rtc_state, !mc->no_floppy,
|
||||||
(pcms->vmport != ON_OFF_AUTO_ON), 0xff0104);
|
(pcms->vmport != ON_OFF_AUTO_ON), 0xff0104);
|
||||||
|
|
||||||
/* connect pm stuff to lpc */
|
/* connect pm stuff to lpc */
|
||||||
@@ -292,12 +293,22 @@ static void pc_q35_machine_options(MachineClass *m)
|
|||||||
m->has_dynamic_sysbus = true;
|
m->has_dynamic_sysbus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_q35_2_7_machine_options(MachineClass *m)
|
static void pc_q35_2_8_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_q35_machine_options(m);
|
pc_q35_machine_options(m);
|
||||||
m->alias = "q35";
|
m->alias = "q35";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_Q35_MACHINE(v2_8, "pc-q35-2.8", NULL,
|
||||||
|
pc_q35_2_8_machine_options);
|
||||||
|
|
||||||
|
static void pc_q35_2_7_machine_options(MachineClass *m)
|
||||||
|
{
|
||||||
|
pc_q35_2_8_machine_options(m);
|
||||||
|
m->alias = NULL;
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_7);
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_Q35_MACHINE(v2_7, "pc-q35-2.7", NULL,
|
DEFINE_Q35_MACHINE(v2_7, "pc-q35-2.7", NULL,
|
||||||
pc_q35_2_7_machine_options);
|
pc_q35_2_7_machine_options);
|
||||||
|
|
||||||
@@ -305,7 +316,6 @@ static void pc_q35_2_6_machine_options(MachineClass *m)
|
|||||||
{
|
{
|
||||||
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||||
pc_q35_2_7_machine_options(m);
|
pc_q35_2_7_machine_options(m);
|
||||||
m->alias = NULL;
|
|
||||||
pcmc->legacy_cpu_hotplug = true;
|
pcmc->legacy_cpu_hotplug = true;
|
||||||
SET_MACHINE_COMPAT(m, PC_COMPAT_2_6);
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_6);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2619,10 +2619,12 @@ void ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2)
|
|||||||
{
|
{
|
||||||
/* ??? Assume only ISA and PCI configurations, and that the PCI-ISA
|
/* ??? Assume only ISA and PCI configurations, and that the PCI-ISA
|
||||||
bridge has been setup properly to always register with ISA. */
|
bridge has been setup properly to always register with ISA. */
|
||||||
isa_register_portio_list(dev, iobase, ide_portio_list, bus, "ide");
|
isa_register_portio_list(dev, &bus->portio_list,
|
||||||
|
iobase, ide_portio_list, bus, "ide");
|
||||||
|
|
||||||
if (iobase2) {
|
if (iobase2) {
|
||||||
isa_register_portio_list(dev, iobase2, ide_portio2_list, bus, "ide");
|
isa_register_portio_list(dev, &bus->portio2_list,
|
||||||
|
iobase2, ide_portio2_list, bus, "ide");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,10 +75,6 @@ static int ide_qdev_init(DeviceState *qdev)
|
|||||||
IDEDeviceClass *dc = IDE_DEVICE_GET_CLASS(dev);
|
IDEDeviceClass *dc = IDE_DEVICE_GET_CLASS(dev);
|
||||||
IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
|
IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
|
||||||
|
|
||||||
if (!dev->conf.blk) {
|
|
||||||
error_report("No drive specified");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (dev->unit == -1) {
|
if (dev->unit == -1) {
|
||||||
dev->unit = bus->master ? 1 : 0;
|
dev->unit = bus->master ? 1 : 0;
|
||||||
}
|
}
|
||||||
@@ -158,6 +154,16 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
|
|||||||
IDEState *s = bus->ifs + dev->unit;
|
IDEState *s = bus->ifs + dev->unit;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
|
if (!dev->conf.blk) {
|
||||||
|
if (kind != IDE_CD) {
|
||||||
|
error_report("No drive specified");
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
/* Anonymous BlockBackend for an empty drive */
|
||||||
|
dev->conf.blk = blk_new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (dev->conf.discard_granularity == -1) {
|
if (dev->conf.discard_granularity == -1) {
|
||||||
dev->conf.discard_granularity = 512;
|
dev->conf.discard_granularity = 512;
|
||||||
} else if (dev->conf.discard_granularity &&
|
} else if (dev->conf.discard_granularity &&
|
||||||
@@ -257,7 +263,11 @@ static int ide_cd_initfn(IDEDevice *dev)
|
|||||||
|
|
||||||
static int ide_drive_initfn(IDEDevice *dev)
|
static int ide_drive_initfn(IDEDevice *dev)
|
||||||
{
|
{
|
||||||
DriveInfo *dinfo = blk_legacy_dinfo(dev->conf.blk);
|
DriveInfo *dinfo = NULL;
|
||||||
|
|
||||||
|
if (dev->conf.blk) {
|
||||||
|
dinfo = blk_legacy_dinfo(dev->conf.blk);
|
||||||
|
}
|
||||||
|
|
||||||
return ide_dev_initfn(dev, dinfo && dinfo->media_cd ? IDE_CD : IDE_HD);
|
return ide_dev_initfn(dev, dinfo && dinfo->media_cd ? IDE_CD : IDE_HD);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -499,9 +499,9 @@ void i8042_isa_mouse_fake_event(void *opaque)
|
|||||||
ps2_mouse_fake_event(s->mouse);
|
ps2_mouse_fake_event(s->mouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out)
|
void i8042_setup_a20_line(ISADevice *dev, qemu_irq a20_out)
|
||||||
{
|
{
|
||||||
qdev_connect_gpio_out_named(DEVICE(dev), I8042_A20_LINE, 0, *a20_out);
|
qdev_connect_gpio_out_named(DEVICE(dev), I8042_A20_LINE, 0, a20_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_kbd_isa = {
|
static const VMStateDescription vmstate_kbd_isa = {
|
||||||
|
|||||||
@@ -280,12 +280,13 @@ static void kvm_s390_release_adapter_routes(S390FLICState *fs,
|
|||||||
* kvm_flic_save - Save pending floating interrupts
|
* kvm_flic_save - Save pending floating interrupts
|
||||||
* @f: QEMUFile containing migration state
|
* @f: QEMUFile containing migration state
|
||||||
* @opaque: pointer to flic device state
|
* @opaque: pointer to flic device state
|
||||||
|
* @size: ignored
|
||||||
*
|
*
|
||||||
* Note: Pass buf and len to kernel. Start with one page and
|
* Note: Pass buf and len to kernel. Start with one page and
|
||||||
* increase until buffer is sufficient or maxium size is
|
* increase until buffer is sufficient or maxium size is
|
||||||
* reached
|
* reached
|
||||||
*/
|
*/
|
||||||
static void kvm_flic_save(QEMUFile *f, void *opaque)
|
static void kvm_flic_save(QEMUFile *f, void *opaque, size_t size)
|
||||||
{
|
{
|
||||||
KVMS390FLICState *flic = opaque;
|
KVMS390FLICState *flic = opaque;
|
||||||
int len = FLIC_SAVE_INITIAL_SIZE;
|
int len = FLIC_SAVE_INITIAL_SIZE;
|
||||||
@@ -324,24 +325,19 @@ static void kvm_flic_save(QEMUFile *f, void *opaque)
|
|||||||
* kvm_flic_load - Load pending floating interrupts
|
* kvm_flic_load - Load pending floating interrupts
|
||||||
* @f: QEMUFile containing migration state
|
* @f: QEMUFile containing migration state
|
||||||
* @opaque: pointer to flic device state
|
* @opaque: pointer to flic device state
|
||||||
* @version_id: version id for migration
|
* @size: ignored
|
||||||
*
|
*
|
||||||
* Returns: value of flic_enqueue_irqs, -EINVAL on error
|
* Returns: value of flic_enqueue_irqs, -EINVAL on error
|
||||||
* Note: Do nothing when no interrupts where stored
|
* Note: Do nothing when no interrupts where stored
|
||||||
* in QEMUFile
|
* in QEMUFile
|
||||||
*/
|
*/
|
||||||
static int kvm_flic_load(QEMUFile *f, void *opaque, int version_id)
|
static int kvm_flic_load(QEMUFile *f, void *opaque, size_t size)
|
||||||
{
|
{
|
||||||
uint64_t len = 0;
|
uint64_t len = 0;
|
||||||
uint64_t count = 0;
|
uint64_t count = 0;
|
||||||
void *buf = NULL;
|
void *buf = NULL;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
if (version_id != FLIC_SAVEVM_VERSION) {
|
|
||||||
r = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
flic_enable_pfault((struct KVMS390FLICState *) opaque);
|
flic_enable_pfault((struct KVMS390FLICState *) opaque);
|
||||||
|
|
||||||
count = qemu_get_be64(f);
|
count = qemu_get_be64(f);
|
||||||
@@ -372,6 +368,24 @@ out:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const VMStateDescription kvm_s390_flic_vmstate = {
|
||||||
|
.name = "s390-flic",
|
||||||
|
.version_id = FLIC_SAVEVM_VERSION,
|
||||||
|
.minimum_version_id = FLIC_SAVEVM_VERSION,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
{
|
||||||
|
.name = "irqs",
|
||||||
|
.info = &(const VMStateInfo) {
|
||||||
|
.name = "irqs",
|
||||||
|
.get = kvm_flic_load,
|
||||||
|
.put = kvm_flic_save,
|
||||||
|
},
|
||||||
|
.flags = VMS_SINGLE,
|
||||||
|
},
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
|
static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
|
KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
|
||||||
@@ -398,16 +412,6 @@ static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
|
|||||||
flic_state->clear_io_supported = !ioctl(flic_state->fd,
|
flic_state->clear_io_supported = !ioctl(flic_state->fd,
|
||||||
KVM_HAS_DEVICE_ATTR, test_attr);
|
KVM_HAS_DEVICE_ATTR, test_attr);
|
||||||
|
|
||||||
/* Register savevm handler for floating interrupts */
|
|
||||||
register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save,
|
|
||||||
kvm_flic_load, (void *) flic_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void kvm_s390_flic_unrealize(DeviceState *dev, Error **errp)
|
|
||||||
{
|
|
||||||
KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
|
|
||||||
|
|
||||||
unregister_savevm(DEVICE(flic_state), "s390-flic", flic_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kvm_s390_flic_reset(DeviceState *dev)
|
static void kvm_s390_flic_reset(DeviceState *dev)
|
||||||
@@ -438,7 +442,7 @@ static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
|
|||||||
S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc);
|
S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc);
|
||||||
|
|
||||||
dc->realize = kvm_s390_flic_realize;
|
dc->realize = kvm_s390_flic_realize;
|
||||||
dc->unrealize = kvm_s390_flic_unrealize;
|
dc->vmsd = &kvm_s390_flic_vmstate;
|
||||||
dc->reset = kvm_s390_flic_reset;
|
dc->reset = kvm_s390_flic_reset;
|
||||||
fsc->register_io_adapter = kvm_s390_register_io_adapter;
|
fsc->register_io_adapter = kvm_s390_register_io_adapter;
|
||||||
fsc->io_adapter_map = kvm_s390_io_adapter_map;
|
fsc->io_adapter_map = kvm_s390_io_adapter_map;
|
||||||
|
|||||||
@@ -329,6 +329,7 @@ static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
|
|||||||
CPUState *cs;
|
CPUState *cs;
|
||||||
ICPState *ss;
|
ICPState *ss;
|
||||||
KVMXICSState *xicskvm = XICS_SPAPR_KVM(xics);
|
KVMXICSState *xicskvm = XICS_SPAPR_KVM(xics);
|
||||||
|
int ret;
|
||||||
|
|
||||||
cs = CPU(cpu);
|
cs = CPU(cpu);
|
||||||
ss = &xics->ss[cs->cpu_index];
|
ss = &xics->ss[cs->cpu_index];
|
||||||
@@ -347,19 +348,14 @@ static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xicskvm->kernel_xics_fd != -1) {
|
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_XICS, 0, xicskvm->kernel_xics_fd,
|
||||||
int ret;
|
kvm_arch_vcpu_id(cs));
|
||||||
|
if (ret < 0) {
|
||||||
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_XICS, 0,
|
error_report("Unable to connect CPU%ld to kernel XICS: %s",
|
||||||
xicskvm->kernel_xics_fd,
|
kvm_arch_vcpu_id(cs), strerror(errno));
|
||||||
kvm_arch_vcpu_id(cs));
|
exit(1);
|
||||||
if (ret < 0) {
|
|
||||||
error_report("Unable to connect CPU%ld to kernel XICS: %s",
|
|
||||||
kvm_arch_vcpu_id(cs), strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
ss->cap_irq_xics_enabled = true;
|
|
||||||
}
|
}
|
||||||
|
ss->cap_irq_xics_enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
|
static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
|
||||||
|
|||||||
@@ -487,6 +487,14 @@ static void ipmi_bmc_extern_init(Object *obj)
|
|||||||
vmstate_register(NULL, 0, &vmstate_ipmi_bmc_extern, ibe);
|
vmstate_register(NULL, 0, &vmstate_ipmi_bmc_extern, ibe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ipmi_bmc_extern_finalize(Object *obj)
|
||||||
|
{
|
||||||
|
IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(obj);
|
||||||
|
|
||||||
|
timer_del(ibe->extern_timer);
|
||||||
|
timer_free(ibe->extern_timer);
|
||||||
|
}
|
||||||
|
|
||||||
static Property ipmi_bmc_extern_properties[] = {
|
static Property ipmi_bmc_extern_properties[] = {
|
||||||
DEFINE_PROP_CHR("chardev", IPMIBmcExtern, chr),
|
DEFINE_PROP_CHR("chardev", IPMIBmcExtern, chr),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
@@ -508,6 +516,7 @@ static const TypeInfo ipmi_bmc_extern_type = {
|
|||||||
.parent = TYPE_IPMI_BMC,
|
.parent = TYPE_IPMI_BMC,
|
||||||
.instance_size = sizeof(IPMIBmcExtern),
|
.instance_size = sizeof(IPMIBmcExtern),
|
||||||
.instance_init = ipmi_bmc_extern_init,
|
.instance_init = ipmi_bmc_extern_init,
|
||||||
|
.instance_finalize = ipmi_bmc_extern_finalize,
|
||||||
.class_init = ipmi_bmc_extern_class_init,
|
.class_init = ipmi_bmc_extern_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -131,24 +131,20 @@ void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start)
|
|||||||
isa_init_ioport(dev, start);
|
isa_init_ioport(dev, start);
|
||||||
}
|
}
|
||||||
|
|
||||||
void isa_register_portio_list(ISADevice *dev, uint16_t start,
|
void isa_register_portio_list(ISADevice *dev,
|
||||||
|
PortioList *piolist, uint16_t start,
|
||||||
const MemoryRegionPortio *pio_start,
|
const MemoryRegionPortio *pio_start,
|
||||||
void *opaque, const char *name)
|
void *opaque, const char *name)
|
||||||
{
|
{
|
||||||
PortioList piolist;
|
assert(piolist && !piolist->owner);
|
||||||
|
|
||||||
/* START is how we should treat DEV, regardless of the actual
|
/* START is how we should treat DEV, regardless of the actual
|
||||||
contents of the portio array. This is how the old code
|
contents of the portio array. This is how the old code
|
||||||
actually handled e.g. the FDC device. */
|
actually handled e.g. the FDC device. */
|
||||||
isa_init_ioport(dev, start);
|
isa_init_ioport(dev, start);
|
||||||
|
|
||||||
/* FIXME: the device should store created PortioList in its state. Note
|
portio_list_init(piolist, OBJECT(dev), pio_start, opaque, name);
|
||||||
that DEV can be NULL here and that single device can register several
|
portio_list_add(piolist, isabus->address_space_io, start);
|
||||||
portio lists. Current implementation is leaking memory allocated
|
|
||||||
in portio_list_init. The leak is not critical because it happens only
|
|
||||||
at initialization time. */
|
|
||||||
portio_list_init(&piolist, OBJECT(dev), pio_start, opaque, name);
|
|
||||||
portio_list_add(&piolist, isabus->address_space_io, start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void isa_device_init(Object *obj)
|
static void isa_device_init(Object *obj)
|
||||||
|
|||||||
@@ -52,4 +52,4 @@ obj-$(CONFIG_PVPANIC) += pvpanic.o
|
|||||||
obj-$(CONFIG_EDU) += edu.o
|
obj-$(CONFIG_EDU) += edu.o
|
||||||
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
|
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
|
||||||
obj-$(CONFIG_AUX) += auxbus.o
|
obj-$(CONFIG_AUX) += auxbus.o
|
||||||
obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o
|
obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
|
||||||
|
|||||||
263
hw/misc/aspeed_sdmc.c
Normal file
263
hw/misc/aspeed_sdmc.c
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
/*
|
||||||
|
* ASPEED SDRAM Memory Controller
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 IBM Corp.
|
||||||
|
*
|
||||||
|
* This code is licensed under the GPL version 2 or later. See
|
||||||
|
* the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/log.h"
|
||||||
|
#include "hw/misc/aspeed_sdmc.h"
|
||||||
|
#include "hw/misc/aspeed_scu.h"
|
||||||
|
#include "hw/qdev-properties.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
/* Protection Key Register */
|
||||||
|
#define R_PROT (0x00 / 4)
|
||||||
|
#define PROT_KEY_UNLOCK 0xFC600309
|
||||||
|
|
||||||
|
/* Configuration Register */
|
||||||
|
#define R_CONF (0x04 / 4)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configuration register Ox4 (for Aspeed AST2400 SOC)
|
||||||
|
*
|
||||||
|
* These are for the record and future use. ASPEED_SDMC_DRAM_SIZE is
|
||||||
|
* what we care about right now as it is checked by U-Boot to
|
||||||
|
* determine the RAM size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ASPEED_SDMC_RESERVED 0xFFFFF800 /* 31:11 reserved */
|
||||||
|
#define ASPEED_SDMC_AST2300_COMPAT (1 << 10)
|
||||||
|
#define ASPEED_SDMC_SCRAMBLE_PATTERN (1 << 9)
|
||||||
|
#define ASPEED_SDMC_DATA_SCRAMBLE (1 << 8)
|
||||||
|
#define ASPEED_SDMC_ECC_ENABLE (1 << 7)
|
||||||
|
#define ASPEED_SDMC_VGA_COMPAT (1 << 6) /* readonly */
|
||||||
|
#define ASPEED_SDMC_DRAM_BANK (1 << 5)
|
||||||
|
#define ASPEED_SDMC_DRAM_BURST (1 << 4)
|
||||||
|
#define ASPEED_SDMC_VGA_APERTURE(x) ((x & 0x3) << 2) /* readonly */
|
||||||
|
#define ASPEED_SDMC_VGA_8MB 0x0
|
||||||
|
#define ASPEED_SDMC_VGA_16MB 0x1
|
||||||
|
#define ASPEED_SDMC_VGA_32MB 0x2
|
||||||
|
#define ASPEED_SDMC_VGA_64MB 0x3
|
||||||
|
#define ASPEED_SDMC_DRAM_SIZE(x) (x & 0x3)
|
||||||
|
#define ASPEED_SDMC_DRAM_64MB 0x0
|
||||||
|
#define ASPEED_SDMC_DRAM_128MB 0x1
|
||||||
|
#define ASPEED_SDMC_DRAM_256MB 0x2
|
||||||
|
#define ASPEED_SDMC_DRAM_512MB 0x3
|
||||||
|
|
||||||
|
#define ASPEED_SDMC_READONLY_MASK \
|
||||||
|
(ASPEED_SDMC_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
|
||||||
|
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
|
||||||
|
/*
|
||||||
|
* Configuration register Ox4 (for Aspeed AST2500 SOC and higher)
|
||||||
|
*
|
||||||
|
* Incompatibilities are annotated in the list. ASPEED_SDMC_HW_VERSION
|
||||||
|
* should be set to 1 for the AST2500 SOC.
|
||||||
|
*/
|
||||||
|
#define ASPEED_SDMC_HW_VERSION(x) ((x & 0xf) << 28) /* readonly */
|
||||||
|
#define ASPEED_SDMC_SW_VERSION ((x & 0xff) << 20)
|
||||||
|
#define ASPEED_SDMC_CACHE_INITIAL_DONE (1 << 19) /* readonly */
|
||||||
|
#define ASPEED_SDMC_AST2500_RESERVED 0x7C000 /* 18:14 reserved */
|
||||||
|
#define ASPEED_SDMC_CACHE_DDR4_CONF (1 << 13)
|
||||||
|
#define ASPEED_SDMC_CACHE_INITIAL (1 << 12)
|
||||||
|
#define ASPEED_SDMC_CACHE_RANGE_CTRL (1 << 11)
|
||||||
|
#define ASPEED_SDMC_CACHE_ENABLE (1 << 10) /* differs from AST2400 */
|
||||||
|
#define ASPEED_SDMC_DRAM_TYPE (1 << 4) /* differs from AST2400 */
|
||||||
|
|
||||||
|
/* DRAM size definitions differs */
|
||||||
|
#define ASPEED_SDMC_AST2500_128MB 0x0
|
||||||
|
#define ASPEED_SDMC_AST2500_256MB 0x1
|
||||||
|
#define ASPEED_SDMC_AST2500_512MB 0x2
|
||||||
|
#define ASPEED_SDMC_AST2500_1024MB 0x3
|
||||||
|
|
||||||
|
#define ASPEED_SDMC_AST2500_READONLY_MASK \
|
||||||
|
(ASPEED_SDMC_HW_VERSION(0xf) | ASPEED_SDMC_CACHE_INITIAL_DONE | \
|
||||||
|
ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
|
||||||
|
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
|
||||||
|
|
||||||
|
static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
|
||||||
|
{
|
||||||
|
AspeedSDMCState *s = ASPEED_SDMC(opaque);
|
||||||
|
|
||||||
|
addr >>= 2;
|
||||||
|
|
||||||
|
if (addr >= ARRAY_SIZE(s->regs)) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
|
||||||
|
__func__, addr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s->regs[addr];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
|
||||||
|
unsigned int size)
|
||||||
|
{
|
||||||
|
AspeedSDMCState *s = ASPEED_SDMC(opaque);
|
||||||
|
|
||||||
|
addr >>= 2;
|
||||||
|
|
||||||
|
if (addr >= ARRAY_SIZE(s->regs)) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
|
||||||
|
__func__, addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr != R_PROT && s->regs[R_PROT] != PROT_KEY_UNLOCK) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr == R_CONF) {
|
||||||
|
/* Make sure readonly bits are kept */
|
||||||
|
switch (s->silicon_rev) {
|
||||||
|
case AST2400_A0_SILICON_REV:
|
||||||
|
data &= ~ASPEED_SDMC_READONLY_MASK;
|
||||||
|
break;
|
||||||
|
case AST2500_A0_SILICON_REV:
|
||||||
|
data &= ~ASPEED_SDMC_AST2500_READONLY_MASK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s->regs[addr] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MemoryRegionOps aspeed_sdmc_ops = {
|
||||||
|
.read = aspeed_sdmc_read,
|
||||||
|
.write = aspeed_sdmc_write,
|
||||||
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
|
.valid.min_access_size = 4,
|
||||||
|
.valid.max_access_size = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ast2400_rambits(void)
|
||||||
|
{
|
||||||
|
switch (ram_size >> 20) {
|
||||||
|
case 64:
|
||||||
|
return ASPEED_SDMC_DRAM_64MB;
|
||||||
|
case 128:
|
||||||
|
return ASPEED_SDMC_DRAM_128MB;
|
||||||
|
case 256:
|
||||||
|
return ASPEED_SDMC_DRAM_256MB;
|
||||||
|
case 512:
|
||||||
|
return ASPEED_SDMC_DRAM_512MB;
|
||||||
|
default:
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid RAM size: 0x"
|
||||||
|
RAM_ADDR_FMT "\n", __func__, ram_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set a minimum default */
|
||||||
|
return ASPEED_SDMC_DRAM_64MB;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ast2500_rambits(void)
|
||||||
|
{
|
||||||
|
switch (ram_size >> 20) {
|
||||||
|
case 128:
|
||||||
|
return ASPEED_SDMC_AST2500_128MB;
|
||||||
|
case 256:
|
||||||
|
return ASPEED_SDMC_AST2500_256MB;
|
||||||
|
case 512:
|
||||||
|
return ASPEED_SDMC_AST2500_512MB;
|
||||||
|
case 1024:
|
||||||
|
return ASPEED_SDMC_AST2500_1024MB;
|
||||||
|
default:
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid RAM size: 0x"
|
||||||
|
RAM_ADDR_FMT "\n", __func__, ram_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set a minimum default */
|
||||||
|
return ASPEED_SDMC_AST2500_128MB;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aspeed_sdmc_reset(DeviceState *dev)
|
||||||
|
{
|
||||||
|
AspeedSDMCState *s = ASPEED_SDMC(dev);
|
||||||
|
|
||||||
|
memset(s->regs, 0, sizeof(s->regs));
|
||||||
|
|
||||||
|
/* Set ram size bit and defaults values */
|
||||||
|
switch (s->silicon_rev) {
|
||||||
|
case AST2400_A0_SILICON_REV:
|
||||||
|
s->regs[R_CONF] |=
|
||||||
|
ASPEED_SDMC_VGA_COMPAT |
|
||||||
|
ASPEED_SDMC_DRAM_SIZE(ast2400_rambits());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AST2500_A0_SILICON_REV:
|
||||||
|
s->regs[R_CONF] |=
|
||||||
|
ASPEED_SDMC_HW_VERSION(1) |
|
||||||
|
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
|
||||||
|
ASPEED_SDMC_DRAM_SIZE(ast2500_rambits());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
|
||||||
|
{
|
||||||
|
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||||
|
AspeedSDMCState *s = ASPEED_SDMC(dev);
|
||||||
|
|
||||||
|
if (!is_supported_silicon_rev(s->silicon_rev)) {
|
||||||
|
error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
|
||||||
|
s->silicon_rev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s,
|
||||||
|
TYPE_ASPEED_SDMC, 0x1000);
|
||||||
|
sysbus_init_mmio(sbd, &s->iomem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_aspeed_sdmc = {
|
||||||
|
.name = "aspeed.sdmc",
|
||||||
|
.version_id = 1,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_UINT32_ARRAY(regs, AspeedSDMCState, ASPEED_SDMC_NR_REGS),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static Property aspeed_sdmc_properties[] = {
|
||||||
|
DEFINE_PROP_UINT32("silicon-rev", AspeedSDMCState, silicon_rev, 0),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void aspeed_sdmc_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
dc->realize = aspeed_sdmc_realize;
|
||||||
|
dc->reset = aspeed_sdmc_reset;
|
||||||
|
dc->desc = "ASPEED SDRAM Memory Controller";
|
||||||
|
dc->vmsd = &vmstate_aspeed_sdmc;
|
||||||
|
dc->props = aspeed_sdmc_properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo aspeed_sdmc_info = {
|
||||||
|
.name = TYPE_ASPEED_SDMC,
|
||||||
|
.parent = TYPE_SYS_BUS_DEVICE,
|
||||||
|
.instance_size = sizeof(AspeedSDMCState),
|
||||||
|
.class_init = aspeed_sdmc_class_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void aspeed_sdmc_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&aspeed_sdmc_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(aspeed_sdmc_register_types);
|
||||||
@@ -89,22 +89,16 @@ static void macio_escc_legacy_setup(MacIOState *macio_state)
|
|||||||
MemoryRegion *bar = &macio_state->bar;
|
MemoryRegion *bar = &macio_state->bar;
|
||||||
int i;
|
int i;
|
||||||
static const int maps[] = {
|
static const int maps[] = {
|
||||||
0x00, 0x00,
|
0x00, 0x00, /* Command B */
|
||||||
0x02, 0x20,
|
0x02, 0x20, /* Command A */
|
||||||
0x04, 0x10,
|
0x04, 0x10, /* Data B */
|
||||||
0x06, 0x30,
|
0x06, 0x30, /* Data A */
|
||||||
0x08, 0x40,
|
0x08, 0x40, /* Enhancement B */
|
||||||
0x0A, 0x50,
|
0x0A, 0x50, /* Enhancement A */
|
||||||
0x60, 0x60,
|
0x80, 0x80, /* Recovery count */
|
||||||
0x70, 0x70,
|
0x90, 0x90, /* Start A */
|
||||||
0x80, 0x70,
|
0xa0, 0xa0, /* Start B */
|
||||||
0x90, 0x80,
|
0xb0, 0xb0, /* Detect AB */
|
||||||
0xA0, 0x90,
|
|
||||||
0xB0, 0xA0,
|
|
||||||
0xC0, 0xB0,
|
|
||||||
0xD0, 0xC0,
|
|
||||||
0xE0, 0xD0,
|
|
||||||
0xF0, 0xE0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256);
|
memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256);
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ typedef struct VIOsPAPRVLANDevice {
|
|||||||
VIOsPAPRDevice sdev;
|
VIOsPAPRDevice sdev;
|
||||||
NICConf nicconf;
|
NICConf nicconf;
|
||||||
NICState *nic;
|
NICState *nic;
|
||||||
|
MACAddr perm_mac;
|
||||||
bool isopen;
|
bool isopen;
|
||||||
hwaddr buf_list;
|
hwaddr buf_list;
|
||||||
uint32_t add_buf_ptr, use_buf_ptr, rx_bufs;
|
uint32_t add_buf_ptr, use_buf_ptr, rx_bufs;
|
||||||
@@ -316,6 +317,10 @@ static void spapr_vlan_reset(VIOsPAPRDevice *sdev)
|
|||||||
spapr_vlan_reset_rx_pool(dev->rx_pool[i]);
|
spapr_vlan_reset_rx_pool(dev->rx_pool[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(&dev->nicconf.macaddr.a, &dev->perm_mac.a,
|
||||||
|
sizeof(dev->nicconf.macaddr.a));
|
||||||
|
qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spapr_vlan_realize(VIOsPAPRDevice *sdev, Error **errp)
|
static void spapr_vlan_realize(VIOsPAPRDevice *sdev, Error **errp)
|
||||||
@@ -324,6 +329,8 @@ static void spapr_vlan_realize(VIOsPAPRDevice *sdev, Error **errp)
|
|||||||
|
|
||||||
qemu_macaddr_default_if_unset(&dev->nicconf.macaddr);
|
qemu_macaddr_default_if_unset(&dev->nicconf.macaddr);
|
||||||
|
|
||||||
|
memcpy(&dev->perm_mac.a, &dev->nicconf.macaddr.a, sizeof(dev->perm_mac.a));
|
||||||
|
|
||||||
dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf,
|
dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf,
|
||||||
object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
|
object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
|
||||||
qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
|
qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
|
||||||
@@ -756,6 +763,27 @@ static target_ulong h_multicast_ctrl(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
|||||||
return H_SUCCESS;
|
return H_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static target_ulong h_change_logical_lan_mac(PowerPCCPU *cpu,
|
||||||
|
sPAPRMachineState *spapr,
|
||||||
|
target_ulong opcode,
|
||||||
|
target_ulong *args)
|
||||||
|
{
|
||||||
|
target_ulong reg = args[0];
|
||||||
|
target_ulong macaddr = args[1];
|
||||||
|
VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
|
||||||
|
VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ETH_ALEN; i++) {
|
||||||
|
dev->nicconf.macaddr.a[ETH_ALEN - i - 1] = macaddr & 0xff;
|
||||||
|
macaddr >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
|
||||||
|
|
||||||
|
return H_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static Property spapr_vlan_properties[] = {
|
static Property spapr_vlan_properties[] = {
|
||||||
DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev),
|
DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev),
|
||||||
DEFINE_NIC_PROPERTIES(VIOsPAPRVLANDevice, nicconf),
|
DEFINE_NIC_PROPERTIES(VIOsPAPRVLANDevice, nicconf),
|
||||||
@@ -854,6 +882,8 @@ static void spapr_vlan_register_types(void)
|
|||||||
spapr_register_hypercall(H_ADD_LOGICAL_LAN_BUFFER,
|
spapr_register_hypercall(H_ADD_LOGICAL_LAN_BUFFER,
|
||||||
h_add_logical_lan_buffer);
|
h_add_logical_lan_buffer);
|
||||||
spapr_register_hypercall(H_MULTICAST_CTRL, h_multicast_ctrl);
|
spapr_register_hypercall(H_MULTICAST_CTRL, h_multicast_ctrl);
|
||||||
|
spapr_register_hypercall(H_CHANGE_LOGICAL_LAN_MAC,
|
||||||
|
h_change_logical_lan_mac);
|
||||||
type_register_static(&spapr_vlan_info);
|
type_register_static(&spapr_vlan_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# shared objects
|
# shared objects
|
||||||
obj-y += ppc.o ppc_booke.o
|
obj-y += ppc.o ppc_booke.o fdt.o
|
||||||
# IBM pSeries (sPAPR)
|
# IBM pSeries (sPAPR)
|
||||||
obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
|
obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
|
||||||
obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
|
obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
|
||||||
|
|||||||
49
hw/ppc/fdt.c
Normal file
49
hw/ppc/fdt.c
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* QEMU PowerPC helper routines for the device tree.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 IBM Corp.
|
||||||
|
*
|
||||||
|
* This code is licensed under the GPL version 2 or later. See the
|
||||||
|
* COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "target-ppc/cpu.h"
|
||||||
|
|
||||||
|
#include "hw/ppc/fdt.h"
|
||||||
|
|
||||||
|
#if defined(TARGET_PPC64)
|
||||||
|
size_t ppc_create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
|
||||||
|
size_t maxsize)
|
||||||
|
{
|
||||||
|
size_t maxcells = maxsize / sizeof(uint32_t);
|
||||||
|
int i, j, count;
|
||||||
|
uint32_t *p = prop;
|
||||||
|
|
||||||
|
for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
|
||||||
|
struct ppc_one_seg_page_size *sps = &env->sps.sps[i];
|
||||||
|
|
||||||
|
if (!sps->page_shift) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (count = 0; count < PPC_PAGE_SIZES_MAX_SZ; count++) {
|
||||||
|
if (sps->enc[count].page_shift == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((p - prop) >= (maxcells - 3 - count * 2)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*(p++) = cpu_to_be32(sps->page_shift);
|
||||||
|
*(p++) = cpu_to_be32(sps->slb_enc);
|
||||||
|
*(p++) = cpu_to_be32(count);
|
||||||
|
for (j = 0; j < count; j++) {
|
||||||
|
*(p++) = cpu_to_be32(sps->enc[j].page_shift);
|
||||||
|
*(p++) = cpu_to_be32(sps->enc[j].pte_enc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (p - prop) * sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -47,6 +47,7 @@
|
|||||||
#include "hw/ppc/ppc.h"
|
#include "hw/ppc/ppc.h"
|
||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
|
|
||||||
|
#include "hw/ppc/fdt.h"
|
||||||
#include "hw/ppc/spapr.h"
|
#include "hw/ppc/spapr.h"
|
||||||
#include "hw/ppc/spapr_vio.h"
|
#include "hw/ppc/spapr_vio.h"
|
||||||
#include "hw/pci-host/spapr.h"
|
#include "hw/pci-host/spapr.h"
|
||||||
@@ -249,40 +250,6 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
|
|
||||||
size_t maxsize)
|
|
||||||
{
|
|
||||||
size_t maxcells = maxsize / sizeof(uint32_t);
|
|
||||||
int i, j, count;
|
|
||||||
uint32_t *p = prop;
|
|
||||||
|
|
||||||
for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
|
|
||||||
struct ppc_one_seg_page_size *sps = &env->sps.sps[i];
|
|
||||||
|
|
||||||
if (!sps->page_shift) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (count = 0; count < PPC_PAGE_SIZES_MAX_SZ; count++) {
|
|
||||||
if (sps->enc[count].page_shift == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((p - prop) >= (maxcells - 3 - count * 2)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*(p++) = cpu_to_be32(sps->page_shift);
|
|
||||||
*(p++) = cpu_to_be32(sps->slb_enc);
|
|
||||||
*(p++) = cpu_to_be32(count);
|
|
||||||
for (j = 0; j < count; j++) {
|
|
||||||
*(p++) = cpu_to_be32(sps->enc[j].page_shift);
|
|
||||||
*(p++) = cpu_to_be32(sps->enc[j].pte_enc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (p - prop) * sizeof(uint32_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static hwaddr spapr_node0_size(void)
|
static hwaddr spapr_node0_size(void)
|
||||||
{
|
{
|
||||||
MachineState *machine = MACHINE(qdev_get_machine());
|
MachineState *machine = MACHINE(qdev_get_machine());
|
||||||
@@ -299,16 +266,6 @@ static hwaddr spapr_node0_size(void)
|
|||||||
return machine->ram_size;
|
return machine->ram_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _FDT(exp) \
|
|
||||||
do { \
|
|
||||||
int ret = (exp); \
|
|
||||||
if (ret < 0) { \
|
|
||||||
fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
|
|
||||||
#exp, fdt_strerror(ret)); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
static void add_str(GString *s, const gchar *s1)
|
static void add_str(GString *s, const gchar *s1)
|
||||||
{
|
{
|
||||||
g_string_append_len(s, s1, strlen(s1) + 1);
|
g_string_append_len(s, s1, strlen(s1) + 1);
|
||||||
@@ -656,13 +613,13 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
|
|||||||
_FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
|
_FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
|
||||||
pcc->l1_dcache_size)));
|
pcc->l1_dcache_size)));
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Warning: Unknown L1 dcache size for cpu\n");
|
error_report("Warning: Unknown L1 dcache size for cpu");
|
||||||
}
|
}
|
||||||
if (pcc->l1_icache_size) {
|
if (pcc->l1_icache_size) {
|
||||||
_FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
|
_FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
|
||||||
pcc->l1_icache_size)));
|
pcc->l1_icache_size)));
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Warning: Unknown L1 icache size for cpu\n");
|
error_report("Warning: Unknown L1 icache size for cpu");
|
||||||
}
|
}
|
||||||
|
|
||||||
_FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
|
_FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
|
||||||
@@ -698,7 +655,7 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
|
|||||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
|
_FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
page_sizes_prop_size = create_page_sizes_prop(env, page_sizes_prop,
|
page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop,
|
||||||
sizeof(page_sizes_prop));
|
sizeof(page_sizes_prop));
|
||||||
if (page_sizes_prop_size) {
|
if (page_sizes_prop_size) {
|
||||||
_FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
|
_FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
|
||||||
@@ -954,20 +911,20 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr,
|
|||||||
|
|
||||||
ret = spapr_populate_memory(spapr, fdt);
|
ret = spapr_populate_memory(spapr, fdt);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "couldn't setup memory nodes in fdt\n");
|
error_report("couldn't setup memory nodes in fdt");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
|
ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "couldn't setup vio devices in fdt\n");
|
error_report("couldn't setup vio devices in fdt");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) {
|
if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) {
|
||||||
ret = spapr_rng_populate_dt(fdt);
|
ret = spapr_rng_populate_dt(fdt);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "could not set up rng device in the fdt\n");
|
error_report("could not set up rng device in the fdt");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -983,7 +940,7 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr,
|
|||||||
/* RTAS */
|
/* RTAS */
|
||||||
ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size);
|
ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
|
error_report("Couldn't set up RTAS device tree properties");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cpus */
|
/* cpus */
|
||||||
|
|||||||
@@ -816,7 +816,7 @@ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
|
|||||||
drc_indexes->data,
|
drc_indexes->data,
|
||||||
drc_indexes->len * sizeof(uint32_t));
|
drc_indexes->len * sizeof(uint32_t));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "Couldn't create ibm,drc-indexes property\n");
|
error_report("Couldn't create ibm,drc-indexes property");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -824,21 +824,21 @@ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
|
|||||||
drc_power_domains->data,
|
drc_power_domains->data,
|
||||||
drc_power_domains->len * sizeof(uint32_t));
|
drc_power_domains->len * sizeof(uint32_t));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "Couldn't finalize ibm,drc-power-domains property\n");
|
error_report("Couldn't finalize ibm,drc-power-domains property");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-names",
|
ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-names",
|
||||||
drc_names->str, drc_names->len);
|
drc_names->str, drc_names->len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "Couldn't finalize ibm,drc-names property\n");
|
error_report("Couldn't finalize ibm,drc-names property");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-types",
|
ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-types",
|
||||||
drc_types->str, drc_types->len);
|
drc_types->str, drc_types->len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "Couldn't finalize ibm,drc-types property\n");
|
error_report("Couldn't finalize ibm,drc-types property");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "hw/qdev.h"
|
#include "hw/qdev.h"
|
||||||
#include "sysemu/device_tree.h"
|
#include "sysemu/device_tree.h"
|
||||||
|
|
||||||
|
#include "hw/ppc/fdt.h"
|
||||||
#include "hw/ppc/spapr.h"
|
#include "hw/ppc/spapr.h"
|
||||||
#include "hw/ppc/spapr_vio.h"
|
#include "hw/ppc/spapr_vio.h"
|
||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
@@ -210,16 +211,6 @@ struct hp_log_full {
|
|||||||
#define EVENT_MASK_HOTPLUG 0x10000000
|
#define EVENT_MASK_HOTPLUG 0x10000000
|
||||||
#define EVENT_MASK_IO 0x08000000
|
#define EVENT_MASK_IO 0x08000000
|
||||||
|
|
||||||
#define _FDT(exp) \
|
|
||||||
do { \
|
|
||||||
int ret = (exp); \
|
|
||||||
if (ret < 0) { \
|
|
||||||
fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
|
|
||||||
#exp, fdt_strerror(ret)); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
void spapr_events_fdt_skel(void *fdt, uint32_t check_exception_irq)
|
void spapr_events_fdt_skel(void *fdt, uint32_t check_exception_irq)
|
||||||
{
|
{
|
||||||
uint32_t irq_ranges[] = {cpu_to_be32(check_exception_irq), cpu_to_be32(1)};
|
uint32_t irq_ranges[] = {cpu_to_be32(check_exception_irq), cpu_to_be32(1)};
|
||||||
|
|||||||
@@ -310,8 +310,8 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn)
|
|||||||
char tmp[32];
|
char tmp[32];
|
||||||
|
|
||||||
if (spapr_tce_find_by_liobn(liobn)) {
|
if (spapr_tce_find_by_liobn(liobn)) {
|
||||||
fprintf(stderr, "Attempted to create TCE table with duplicate"
|
error_report("Attempted to create TCE table with duplicate"
|
||||||
" LIOBN 0x%x\n", liobn);
|
" LIOBN 0x%x", liobn);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "sysemu/char.h"
|
#include "sysemu/char.h"
|
||||||
#include "hw/qdev.h"
|
#include "hw/qdev.h"
|
||||||
@@ -716,7 +717,7 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
|
|||||||
|
|
||||||
ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size);
|
ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Couldn't add RTAS reserve entry: %s\n",
|
error_report("Couldn't add RTAS reserve entry: %s",
|
||||||
fdt_strerror(ret));
|
fdt_strerror(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -724,7 +725,7 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
|
|||||||
ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-base",
|
ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-base",
|
||||||
rtas_addr);
|
rtas_addr);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n",
|
error_report("Couldn't add linux,rtas-base property: %s",
|
||||||
fdt_strerror(ret));
|
fdt_strerror(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -732,7 +733,7 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
|
|||||||
ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-entry",
|
ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-entry",
|
||||||
rtas_addr);
|
rtas_addr);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n",
|
error_report("Couldn't add linux,rtas-entry property: %s",
|
||||||
fdt_strerror(ret));
|
fdt_strerror(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -740,7 +741,7 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
|
|||||||
ret = qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-size",
|
ret = qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-size",
|
||||||
rtas_size);
|
rtas_size);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Couldn't add rtas-size property: %s\n",
|
error_report("Couldn't add rtas-size property: %s",
|
||||||
fdt_strerror(ret));
|
fdt_strerror(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -755,7 +756,7 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
|
|||||||
ret = qemu_fdt_setprop_cell(fdt, "/rtas", call->name,
|
ret = qemu_fdt_setprop_cell(fdt, "/rtas", call->name,
|
||||||
i + RTAS_TOKEN_BASE);
|
i + RTAS_TOKEN_BASE);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Couldn't add rtas token for %s: %s\n",
|
error_report("Couldn't add rtas token for %s: %s",
|
||||||
call->name, fdt_strerror(ret));
|
call->name, fdt_strerror(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -770,7 +771,7 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
|
|||||||
ret = qemu_fdt_setprop(fdt, "/rtas", "ibm,lrdr-capacity", lrdr_capacity,
|
ret = qemu_fdt_setprop(fdt, "/rtas", "ibm,lrdr-capacity", lrdr_capacity,
|
||||||
sizeof(lrdr_capacity));
|
sizeof(lrdr_capacity));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Couldn't add ibm,lrdr-capacity rtas property\n");
|
error_report("Couldn't add ibm,lrdr-capacity rtas property");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
@@ -276,7 +277,7 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
|
|||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
|
|
||||||
if (!dev->crq.qsize) {
|
if (!dev->crq.qsize) {
|
||||||
fprintf(stderr, "spapr_vio_send_creq on uninitialized queue\n");
|
error_report("spapr_vio_send_creq on uninitialized queue");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,8 @@ out_err:
|
|||||||
int css_create_css_image(uint8_t cssid, bool default_image)
|
int css_create_css_image(uint8_t cssid, bool default_image)
|
||||||
{
|
{
|
||||||
trace_css_new_image(cssid, default_image ? "(default)" : "");
|
trace_css_new_image(cssid, default_image ? "(default)" : "");
|
||||||
if (cssid > MAX_CSSID) {
|
/* 255 is reserved */
|
||||||
|
if (cssid == 255) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (channel_subsys.css[cssid]) {
|
if (channel_subsys.css[cssid]) {
|
||||||
@@ -1267,7 +1268,7 @@ bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid)
|
|||||||
uint8_t real_cssid;
|
uint8_t real_cssid;
|
||||||
|
|
||||||
real_cssid = (!m && (cssid == 0)) ? channel_subsys.default_cssid : cssid;
|
real_cssid = (!m && (cssid == 0)) ? channel_subsys.default_cssid : cssid;
|
||||||
if (real_cssid > MAX_CSSID || ssid > MAX_SSID ||
|
if (ssid > MAX_SSID ||
|
||||||
!channel_subsys.css[real_cssid] ||
|
!channel_subsys.css[real_cssid] ||
|
||||||
!channel_subsys.css[real_cssid]->sch_set[ssid]) {
|
!channel_subsys.css[real_cssid]->sch_set[ssid]) {
|
||||||
return true;
|
return true;
|
||||||
@@ -1282,9 +1283,6 @@ static int css_add_virtual_chpid(uint8_t cssid, uint8_t chpid, uint8_t type)
|
|||||||
CssImage *css;
|
CssImage *css;
|
||||||
|
|
||||||
trace_css_chpid_add(cssid, chpid, type);
|
trace_css_chpid_add(cssid, chpid, type);
|
||||||
if (cssid > MAX_CSSID) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
css = channel_subsys.css[cssid];
|
css = channel_subsys.css[cssid];
|
||||||
if (!css) {
|
if (!css) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|||||||
@@ -649,6 +649,7 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
|
|||||||
pbdev = s390_pci_device_new(dev->id);
|
pbdev = s390_pci_device_new(dev->id);
|
||||||
if (!pbdev) {
|
if (!pbdev) {
|
||||||
error_setg(errp, "create zpci device failed");
|
error_setg(errp, "create zpci device failed");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -717,11 +718,7 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert(pbdev != NULL);
|
||||||
if (!pbdev) {
|
|
||||||
object_unparent(OBJECT(pci_dev));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) {
|
} else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) {
|
||||||
pbdev = S390_PCI_DEVICE(dev);
|
pbdev = S390_PCI_DEVICE(dev);
|
||||||
pci_dev = pbdev->pdev;
|
pci_dev = pbdev->pdev;
|
||||||
|
|||||||
@@ -249,6 +249,11 @@ bool ri_allowed(void)
|
|||||||
|
|
||||||
return s390mc->ri_allowed;
|
return s390mc->ri_allowed;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Make sure the "none" machine can have ri, otherwise it won't * be
|
||||||
|
* unlocked in KVM and therefore the host CPU model might be wrong.
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -316,7 +321,11 @@ static const TypeInfo ccw_machine_info = {
|
|||||||
} \
|
} \
|
||||||
type_init(ccw_machine_register_##suffix)
|
type_init(ccw_machine_register_##suffix)
|
||||||
|
|
||||||
|
#define CCW_COMPAT_2_7 \
|
||||||
|
HW_COMPAT_2_7
|
||||||
|
|
||||||
#define CCW_COMPAT_2_6 \
|
#define CCW_COMPAT_2_6 \
|
||||||
|
CCW_COMPAT_2_7 \
|
||||||
HW_COMPAT_2_6 \
|
HW_COMPAT_2_6 \
|
||||||
{\
|
{\
|
||||||
.driver = TYPE_S390_IPL,\
|
.driver = TYPE_S390_IPL,\
|
||||||
@@ -372,14 +381,26 @@ static const TypeInfo ccw_machine_info = {
|
|||||||
.value = "0",\
|
.value = "0",\
|
||||||
},
|
},
|
||||||
|
|
||||||
|
static void ccw_machine_2_8_instance_options(MachineState *machine)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccw_machine_2_8_class_options(MachineClass *mc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
DEFINE_CCW_MACHINE(2_8, "2.8", true);
|
||||||
|
|
||||||
static void ccw_machine_2_7_instance_options(MachineState *machine)
|
static void ccw_machine_2_7_instance_options(MachineState *machine)
|
||||||
{
|
{
|
||||||
|
ccw_machine_2_8_instance_options(machine);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ccw_machine_2_7_class_options(MachineClass *mc)
|
static void ccw_machine_2_7_class_options(MachineClass *mc)
|
||||||
{
|
{
|
||||||
|
ccw_machine_2_8_class_options(mc);
|
||||||
|
SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_7);
|
||||||
}
|
}
|
||||||
DEFINE_CCW_MACHINE(2_7, "2.7", true);
|
DEFINE_CCW_MACHINE(2_7, "2.7", false);
|
||||||
|
|
||||||
static void ccw_machine_2_6_instance_options(MachineState *machine)
|
static void ccw_machine_2_6_instance_options(MachineState *machine)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -101,7 +101,11 @@ void s390_init_cpus(MachineState *machine)
|
|||||||
gchar *name;
|
gchar *name;
|
||||||
|
|
||||||
if (machine->cpu_model == NULL) {
|
if (machine->cpu_model == NULL) {
|
||||||
machine->cpu_model = "host";
|
if (kvm_enabled()) {
|
||||||
|
machine->cpu_model = "host";
|
||||||
|
} else {
|
||||||
|
machine->cpu_model = "qemu";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_states = g_new0(S390CPU *, max_cpus);
|
cpu_states = g_new0(S390CPU *, max_cpus);
|
||||||
|
|||||||
@@ -26,7 +26,25 @@
|
|||||||
|
|
||||||
static inline SCLPDevice *get_sclp_device(void)
|
static inline SCLPDevice *get_sclp_device(void)
|
||||||
{
|
{
|
||||||
return SCLP(object_resolve_path_type("", TYPE_SCLP, NULL));
|
static SCLPDevice *sclp;
|
||||||
|
|
||||||
|
if (!sclp) {
|
||||||
|
sclp = SCLP(object_resolve_path_type("", TYPE_SCLP, NULL));
|
||||||
|
}
|
||||||
|
return sclp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int count)
|
||||||
|
{
|
||||||
|
uint8_t features[SCCB_CPU_FEATURE_LEN] = { 0 };
|
||||||
|
int i;
|
||||||
|
|
||||||
|
s390_get_feat_block(S390_FEAT_TYPE_SCLP_CPU, features);
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
entry[i].address = i;
|
||||||
|
entry[i].type = 0;
|
||||||
|
memcpy(entry[i].features, features, sizeof(entry[i].features));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Provide information about the configuration, CPUs and storage */
|
/* Provide information about the configuration, CPUs and storage */
|
||||||
@@ -37,7 +55,6 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
|
|||||||
sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev();
|
sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev();
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
int cpu_count = 0;
|
int cpu_count = 0;
|
||||||
int i = 0;
|
|
||||||
int rnsize, rnmax;
|
int rnsize, rnmax;
|
||||||
int slots = MIN(machine->ram_slots, s390_get_memslot_count(kvm_state));
|
int slots = MIN(machine->ram_slots, s390_get_memslot_count(kvm_state));
|
||||||
|
|
||||||
@@ -50,10 +67,15 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
|
|||||||
read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries));
|
read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries));
|
||||||
read_info->highest_cpu = cpu_to_be16(max_cpus);
|
read_info->highest_cpu = cpu_to_be16(max_cpus);
|
||||||
|
|
||||||
for (i = 0; i < cpu_count; i++) {
|
read_info->ibc_val = cpu_to_be32(s390_get_ibc_val());
|
||||||
read_info->entries[i].address = i;
|
|
||||||
read_info->entries[i].type = 0;
|
/* Configuration Characteristic (Extension) */
|
||||||
}
|
s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR,
|
||||||
|
read_info->conf_char);
|
||||||
|
s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT,
|
||||||
|
read_info->conf_char_ext);
|
||||||
|
|
||||||
|
prepare_cpu_entries(sclp, read_info->entries, cpu_count);
|
||||||
|
|
||||||
read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
|
read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
|
||||||
SCLP_HAS_PCI_RECONFIG);
|
SCLP_HAS_PCI_RECONFIG);
|
||||||
@@ -88,6 +110,8 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
|
|||||||
|
|
||||||
read_info->facilities |= cpu_to_be64(SCLP_FC_ASSIGN_ATTACH_READ_STOR);
|
read_info->facilities |= cpu_to_be64(SCLP_FC_ASSIGN_ATTACH_READ_STOR);
|
||||||
}
|
}
|
||||||
|
read_info->mha_pow = s390_get_mha_pow();
|
||||||
|
read_info->hmfai = cpu_to_be32(s390_get_hmfai());
|
||||||
|
|
||||||
rnsize = 1 << (sclp->increment_size - 20);
|
rnsize = 1 << (sclp->increment_size - 20);
|
||||||
if (rnsize <= 128) {
|
if (rnsize <= 128) {
|
||||||
@@ -304,7 +328,6 @@ static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
|
|||||||
ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
|
ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
int cpu_count = 0;
|
int cpu_count = 0;
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
CPU_FOREACH(cpu) {
|
CPU_FOREACH(cpu) {
|
||||||
cpu_count++;
|
cpu_count++;
|
||||||
@@ -318,10 +341,7 @@ static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
|
|||||||
cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured
|
cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured
|
||||||
+ cpu_info->nr_configured*sizeof(CPUEntry));
|
+ cpu_info->nr_configured*sizeof(CPUEntry));
|
||||||
|
|
||||||
for (i = 0; i < cpu_count; i++) {
|
prepare_cpu_entries(sclp, cpu_info->entries, cpu_count);
|
||||||
cpu_info->entries[i].address = i;
|
|
||||||
cpu_info->entries[i].type = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
|
sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1658,6 +1658,57 @@ static const TypeInfo virtio_ccw_9p_info = {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_VHOST_VSOCK
|
||||||
|
|
||||||
|
static Property vhost_vsock_ccw_properties[] = {
|
||||||
|
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
|
||||||
|
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
||||||
|
VIRTIO_CCW_MAX_REV),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void vhost_vsock_ccw_realize(VirtioCcwDevice *ccw_dev, Error **errp)
|
||||||
|
{
|
||||||
|
VHostVSockCCWState *dev = VHOST_VSOCK_CCW(ccw_dev);
|
||||||
|
DeviceState *vdev = DEVICE(&dev->vdev);
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
|
qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
|
||||||
|
object_property_set_bool(OBJECT(vdev), true, "realized", &err);
|
||||||
|
if (err) {
|
||||||
|
error_propagate(errp, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_ccw_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
|
k->realize = vhost_vsock_ccw_realize;
|
||||||
|
k->exit = virtio_ccw_exit;
|
||||||
|
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||||
|
dc->props = vhost_vsock_ccw_properties;
|
||||||
|
dc->reset = virtio_ccw_reset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_ccw_instance_init(Object *obj)
|
||||||
|
{
|
||||||
|
VHostVSockCCWState *dev = VHOST_VSOCK_CCW(obj);
|
||||||
|
|
||||||
|
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||||
|
TYPE_VHOST_VSOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo vhost_vsock_ccw_info = {
|
||||||
|
.name = TYPE_VHOST_VSOCK_CCW,
|
||||||
|
.parent = TYPE_VIRTIO_CCW_DEVICE,
|
||||||
|
.instance_size = sizeof(VHostVSockCCWState),
|
||||||
|
.instance_init = vhost_vsock_ccw_instance_init,
|
||||||
|
.class_init = vhost_vsock_ccw_class_init,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static void virtio_ccw_register(void)
|
static void virtio_ccw_register(void)
|
||||||
{
|
{
|
||||||
type_register_static(&virtio_ccw_bus_info);
|
type_register_static(&virtio_ccw_bus_info);
|
||||||
@@ -1674,6 +1725,9 @@ static void virtio_ccw_register(void)
|
|||||||
#ifdef CONFIG_VIRTFS
|
#ifdef CONFIG_VIRTFS
|
||||||
type_register_static(&virtio_ccw_9p_info);
|
type_register_static(&virtio_ccw_9p_info);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_VHOST_VSOCK
|
||||||
|
type_register_static(&vhost_vsock_ccw_info);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(virtio_ccw_register)
|
type_init(virtio_ccw_register)
|
||||||
|
|||||||
@@ -23,6 +23,9 @@
|
|||||||
#include "hw/virtio/virtio-balloon.h"
|
#include "hw/virtio/virtio-balloon.h"
|
||||||
#include "hw/virtio/virtio-rng.h"
|
#include "hw/virtio/virtio-rng.h"
|
||||||
#include "hw/virtio/virtio-bus.h"
|
#include "hw/virtio/virtio-bus.h"
|
||||||
|
#ifdef CONFIG_VHOST_VSOCK
|
||||||
|
#include "hw/virtio/vhost-vsock.h"
|
||||||
|
#endif /* CONFIG_VHOST_VSOCK */
|
||||||
|
|
||||||
#include "hw/s390x/s390_flic.h"
|
#include "hw/s390x/s390_flic.h"
|
||||||
#include "hw/s390x/css.h"
|
#include "hw/s390x/css.h"
|
||||||
@@ -197,4 +200,16 @@ typedef struct V9fsCCWState {
|
|||||||
|
|
||||||
#endif /* CONFIG_VIRTFS */
|
#endif /* CONFIG_VIRTFS */
|
||||||
|
|
||||||
|
#ifdef CONFIG_VHOST_VSOCK
|
||||||
|
#define TYPE_VHOST_VSOCK_CCW "vhost-vsock-ccw"
|
||||||
|
#define VHOST_VSOCK_CCW(obj) \
|
||||||
|
OBJECT_CHECK(VHostVSockCCWState, (obj), TYPE_VHOST_VSOCK_CCW)
|
||||||
|
|
||||||
|
typedef struct VHostVSockCCWState {
|
||||||
|
VirtioCcwDevice parent_obj;
|
||||||
|
VHostVSock vdev;
|
||||||
|
} VHostVSockCCWState;
|
||||||
|
|
||||||
|
#endif /* CONFIG_VHOST_VSOCK */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2359,6 +2359,11 @@ static void scsi_hd_realize(SCSIDevice *dev, Error **errp)
|
|||||||
static void scsi_cd_realize(SCSIDevice *dev, Error **errp)
|
static void scsi_cd_realize(SCSIDevice *dev, Error **errp)
|
||||||
{
|
{
|
||||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
|
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
|
||||||
|
|
||||||
|
if (!dev->conf.blk) {
|
||||||
|
dev->conf.blk = blk_new();
|
||||||
|
}
|
||||||
|
|
||||||
s->qdev.blocksize = 2048;
|
s->qdev.blocksize = 2048;
|
||||||
s->qdev.type = TYPE_ROM;
|
s->qdev.type = TYPE_ROM;
|
||||||
s->features |= 1 << SCSI_DISK_F_REMOVABLE;
|
s->features |= 1 << SCSI_DISK_F_REMOVABLE;
|
||||||
|
|||||||
@@ -1876,6 +1876,14 @@ static void sd_instance_init(Object *obj)
|
|||||||
sd->ocr_power_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sd_ocr_powerup, sd);
|
sd->ocr_power_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sd_ocr_powerup, sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sd_instance_finalize(Object *obj)
|
||||||
|
{
|
||||||
|
SDState *sd = SD_CARD(obj);
|
||||||
|
|
||||||
|
timer_del(sd->ocr_power_timer);
|
||||||
|
timer_free(sd->ocr_power_timer);
|
||||||
|
}
|
||||||
|
|
||||||
static void sd_realize(DeviceState *dev, Error **errp)
|
static void sd_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
SDState *sd = SD_CARD(dev);
|
SDState *sd = SD_CARD(dev);
|
||||||
@@ -1927,6 +1935,7 @@ static const TypeInfo sd_info = {
|
|||||||
.class_size = sizeof(SDCardClass),
|
.class_size = sizeof(SDCardClass),
|
||||||
.class_init = sd_class_init,
|
.class_init = sd_class_init,
|
||||||
.instance_init = sd_instance_init,
|
.instance_init = sd_instance_init,
|
||||||
|
.instance_finalize = sd_instance_finalize,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sd_register_types(void)
|
static void sd_register_types(void)
|
||||||
|
|||||||
@@ -5,3 +5,5 @@ common-obj-y += virtio-mmio.o
|
|||||||
|
|
||||||
obj-y += virtio.o virtio-balloon.o
|
obj-y += virtio.o virtio-balloon.o
|
||||||
obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o
|
obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock.o
|
||||||
|
|||||||
@@ -172,6 +172,19 @@ static int vhost_kernel_get_vq_index(struct vhost_dev *dev, int idx)
|
|||||||
return idx - dev->vq_index;
|
return idx - dev->vq_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VHOST_VSOCK
|
||||||
|
static int vhost_kernel_vsock_set_guest_cid(struct vhost_dev *dev,
|
||||||
|
uint64_t guest_cid)
|
||||||
|
{
|
||||||
|
return vhost_kernel_call(dev, VHOST_VSOCK_SET_GUEST_CID, &guest_cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vhost_kernel_vsock_set_running(struct vhost_dev *dev, int start)
|
||||||
|
{
|
||||||
|
return vhost_kernel_call(dev, VHOST_VSOCK_SET_RUNNING, &start);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_VHOST_VSOCK */
|
||||||
|
|
||||||
static const VhostOps kernel_ops = {
|
static const VhostOps kernel_ops = {
|
||||||
.backend_type = VHOST_BACKEND_TYPE_KERNEL,
|
.backend_type = VHOST_BACKEND_TYPE_KERNEL,
|
||||||
.vhost_backend_init = vhost_kernel_init,
|
.vhost_backend_init = vhost_kernel_init,
|
||||||
@@ -197,6 +210,10 @@ static const VhostOps kernel_ops = {
|
|||||||
.vhost_set_owner = vhost_kernel_set_owner,
|
.vhost_set_owner = vhost_kernel_set_owner,
|
||||||
.vhost_reset_device = vhost_kernel_reset_device,
|
.vhost_reset_device = vhost_kernel_reset_device,
|
||||||
.vhost_get_vq_index = vhost_kernel_get_vq_index,
|
.vhost_get_vq_index = vhost_kernel_get_vq_index,
|
||||||
|
#ifdef CONFIG_VHOST_VSOCK
|
||||||
|
.vhost_vsock_set_guest_cid = vhost_kernel_vsock_set_guest_cid,
|
||||||
|
.vhost_vsock_set_running = vhost_kernel_vsock_set_running,
|
||||||
|
#endif /* CONFIG_VHOST_VSOCK */
|
||||||
};
|
};
|
||||||
|
|
||||||
int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type)
|
int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type)
|
||||||
|
|||||||
417
hw/virtio/vhost-vsock.c
Normal file
417
hw/virtio/vhost-vsock.c
Normal file
@@ -0,0 +1,417 @@
|
|||||||
|
/*
|
||||||
|
* Virtio vsock device
|
||||||
|
*
|
||||||
|
* Copyright 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||||
|
* (at your option) any later version. See the COPYING file in the
|
||||||
|
* top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "standard-headers/linux/virtio_vsock.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "hw/virtio/virtio-bus.h"
|
||||||
|
#include "hw/virtio/virtio-access.h"
|
||||||
|
#include "migration/migration.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
#include "hw/virtio/vhost-vsock.h"
|
||||||
|
#include "qemu/iov.h"
|
||||||
|
#include "monitor/monitor.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VHOST_VSOCK_SAVEVM_VERSION = 0,
|
||||||
|
|
||||||
|
VHOST_VSOCK_QUEUE_SIZE = 128,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void vhost_vsock_get_config(VirtIODevice *vdev, uint8_t *config)
|
||||||
|
{
|
||||||
|
VHostVSock *vsock = VHOST_VSOCK(vdev);
|
||||||
|
struct virtio_vsock_config vsockcfg = {};
|
||||||
|
|
||||||
|
virtio_stq_p(vdev, &vsockcfg.guest_cid, vsock->conf.guest_cid);
|
||||||
|
memcpy(config, &vsockcfg, sizeof(vsockcfg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vhost_vsock_set_guest_cid(VHostVSock *vsock)
|
||||||
|
{
|
||||||
|
const VhostOps *vhost_ops = vsock->vhost_dev.vhost_ops;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!vhost_ops->vhost_vsock_set_guest_cid) {
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = vhost_ops->vhost_vsock_set_guest_cid(&vsock->vhost_dev,
|
||||||
|
vsock->conf.guest_cid);
|
||||||
|
if (ret < 0) {
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vhost_vsock_set_running(VHostVSock *vsock, int start)
|
||||||
|
{
|
||||||
|
const VhostOps *vhost_ops = vsock->vhost_dev.vhost_ops;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!vhost_ops->vhost_vsock_set_running) {
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = vhost_ops->vhost_vsock_set_running(&vsock->vhost_dev, start);
|
||||||
|
if (ret < 0) {
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_start(VirtIODevice *vdev)
|
||||||
|
{
|
||||||
|
VHostVSock *vsock = VHOST_VSOCK(vdev);
|
||||||
|
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
|
||||||
|
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!k->set_guest_notifiers) {
|
||||||
|
error_report("binding does not support guest notifiers");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = vhost_dev_enable_notifiers(&vsock->vhost_dev, vdev);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_report("Error enabling host notifiers: %d", -ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = k->set_guest_notifiers(qbus->parent, vsock->vhost_dev.nvqs, true);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_report("Error binding guest notifier: %d", -ret);
|
||||||
|
goto err_host_notifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
vsock->vhost_dev.acked_features = vdev->guest_features;
|
||||||
|
ret = vhost_dev_start(&vsock->vhost_dev, vdev);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_report("Error starting vhost: %d", -ret);
|
||||||
|
goto err_guest_notifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = vhost_vsock_set_running(vsock, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_report("Error starting vhost vsock: %d", -ret);
|
||||||
|
goto err_dev_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* guest_notifier_mask/pending not used yet, so just unmask
|
||||||
|
* everything here. virtio-pci will do the right thing by
|
||||||
|
* enabling/disabling irqfd.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < vsock->vhost_dev.nvqs; i++) {
|
||||||
|
vhost_virtqueue_mask(&vsock->vhost_dev, vdev, i, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
err_dev_start:
|
||||||
|
vhost_dev_stop(&vsock->vhost_dev, vdev);
|
||||||
|
err_guest_notifiers:
|
||||||
|
k->set_guest_notifiers(qbus->parent, vsock->vhost_dev.nvqs, false);
|
||||||
|
err_host_notifiers:
|
||||||
|
vhost_dev_disable_notifiers(&vsock->vhost_dev, vdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_stop(VirtIODevice *vdev)
|
||||||
|
{
|
||||||
|
VHostVSock *vsock = VHOST_VSOCK(vdev);
|
||||||
|
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
|
||||||
|
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!k->set_guest_notifiers) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = vhost_vsock_set_running(vsock, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_report("vhost vsock set running failed: %d", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vhost_dev_stop(&vsock->vhost_dev, vdev);
|
||||||
|
|
||||||
|
ret = k->set_guest_notifiers(qbus->parent, vsock->vhost_dev.nvqs, false);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_report("vhost guest notifier cleanup failed: %d", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vhost_dev_disable_notifiers(&vsock->vhost_dev, vdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_set_status(VirtIODevice *vdev, uint8_t status)
|
||||||
|
{
|
||||||
|
VHostVSock *vsock = VHOST_VSOCK(vdev);
|
||||||
|
bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK;
|
||||||
|
|
||||||
|
if (!vdev->vm_running) {
|
||||||
|
should_start = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vsock->vhost_dev.started == should_start) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_start) {
|
||||||
|
vhost_vsock_start(vdev);
|
||||||
|
} else {
|
||||||
|
vhost_vsock_stop(vdev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t vhost_vsock_get_features(VirtIODevice *vdev,
|
||||||
|
uint64_t requested_features,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
/* No feature bits used yet */
|
||||||
|
return requested_features;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||||
|
{
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_guest_notifier_mask(VirtIODevice *vdev, int idx,
|
||||||
|
bool mask)
|
||||||
|
{
|
||||||
|
VHostVSock *vsock = VHOST_VSOCK(vdev);
|
||||||
|
|
||||||
|
vhost_virtqueue_mask(&vsock->vhost_dev, vdev, idx, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool vhost_vsock_guest_notifier_pending(VirtIODevice *vdev, int idx)
|
||||||
|
{
|
||||||
|
VHostVSock *vsock = VHOST_VSOCK(vdev);
|
||||||
|
|
||||||
|
return vhost_virtqueue_pending(&vsock->vhost_dev, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_send_transport_reset(VHostVSock *vsock)
|
||||||
|
{
|
||||||
|
VirtQueueElement *elem;
|
||||||
|
VirtQueue *vq = vsock->event_vq;
|
||||||
|
struct virtio_vsock_event event = {
|
||||||
|
.id = cpu_to_le32(VIRTIO_VSOCK_EVENT_TRANSPORT_RESET),
|
||||||
|
};
|
||||||
|
|
||||||
|
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
||||||
|
if (!elem) {
|
||||||
|
error_report("vhost-vsock missed transport reset event");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem->out_num) {
|
||||||
|
error_report("invalid vhost-vsock event virtqueue element with "
|
||||||
|
"out buffers");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iov_from_buf(elem->in_sg, elem->in_num, 0,
|
||||||
|
&event, sizeof(event)) != sizeof(event)) {
|
||||||
|
error_report("vhost-vsock event virtqueue element is too short");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtqueue_push(vq, elem, sizeof(event));
|
||||||
|
virtio_notify(VIRTIO_DEVICE(vsock), vq);
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_free(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_save(QEMUFile *f, void *opaque, size_t size)
|
||||||
|
{
|
||||||
|
VHostVSock *vsock = opaque;
|
||||||
|
VirtIODevice *vdev = VIRTIO_DEVICE(vsock);
|
||||||
|
|
||||||
|
/* At this point, backend must be stopped, otherwise
|
||||||
|
* it might keep writing to memory. */
|
||||||
|
assert(!vsock->vhost_dev.started);
|
||||||
|
virtio_save(vdev, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_post_load_timer_cleanup(VHostVSock *vsock)
|
||||||
|
{
|
||||||
|
if (!vsock->post_load_timer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer_del(vsock->post_load_timer);
|
||||||
|
timer_free(vsock->post_load_timer);
|
||||||
|
vsock->post_load_timer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_post_load_timer_cb(void *opaque)
|
||||||
|
{
|
||||||
|
VHostVSock *vsock = opaque;
|
||||||
|
|
||||||
|
vhost_vsock_post_load_timer_cleanup(vsock);
|
||||||
|
vhost_vsock_send_transport_reset(vsock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vhost_vsock_load(QEMUFile *f, void *opaque, size_t size)
|
||||||
|
{
|
||||||
|
VHostVSock *vsock = opaque;
|
||||||
|
VirtIODevice *vdev = VIRTIO_DEVICE(vsock);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = virtio_load(vdev, f, VHOST_VSOCK_SAVEVM_VERSION);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virtio_queue_get_addr(vdev, 2)) {
|
||||||
|
/* Defer transport reset event to a vm clock timer so that virtqueue
|
||||||
|
* changes happen after migration has completed.
|
||||||
|
*/
|
||||||
|
assert(!vsock->post_load_timer);
|
||||||
|
vsock->post_load_timer =
|
||||||
|
timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||||
|
vhost_vsock_post_load_timer_cb,
|
||||||
|
vsock);
|
||||||
|
timer_mod(vsock->post_load_timer, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VMSTATE_VIRTIO_DEVICE(vhost_vsock, VHOST_VSOCK_SAVEVM_VERSION,
|
||||||
|
vhost_vsock_load, vhost_vsock_save);
|
||||||
|
|
||||||
|
static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
|
||||||
|
{
|
||||||
|
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||||
|
VHostVSock *vsock = VHOST_VSOCK(dev);
|
||||||
|
int vhostfd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Refuse to use reserved CID numbers */
|
||||||
|
if (vsock->conf.guest_cid <= 2) {
|
||||||
|
error_setg(errp, "guest-cid property must be greater than 2");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vsock->conf.guest_cid > UINT32_MAX) {
|
||||||
|
error_setg(errp, "guest-cid property must be a 32-bit number");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vsock->conf.vhostfd) {
|
||||||
|
vhostfd = monitor_fd_param(cur_mon, vsock->conf.vhostfd, errp);
|
||||||
|
if (vhostfd == -1) {
|
||||||
|
error_prepend(errp, "vhost-vsock: unable to parse vhostfd: ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vhostfd = open("/dev/vhost-vsock", O_RDWR);
|
||||||
|
if (vhostfd < 0) {
|
||||||
|
error_setg_errno(errp, -errno,
|
||||||
|
"vhost-vsock: failed to open vhost device");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtio_init(vdev, "vhost-vsock", VIRTIO_ID_VSOCK,
|
||||||
|
sizeof(struct virtio_vsock_config));
|
||||||
|
|
||||||
|
/* Receive and transmit queues belong to vhost */
|
||||||
|
virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, vhost_vsock_handle_output);
|
||||||
|
virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, vhost_vsock_handle_output);
|
||||||
|
|
||||||
|
/* The event queue belongs to QEMU */
|
||||||
|
vsock->event_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE,
|
||||||
|
vhost_vsock_handle_output);
|
||||||
|
|
||||||
|
vsock->vhost_dev.nvqs = ARRAY_SIZE(vsock->vhost_vqs);
|
||||||
|
vsock->vhost_dev.vqs = vsock->vhost_vqs;
|
||||||
|
ret = vhost_dev_init(&vsock->vhost_dev, (void *)(uintptr_t)vhostfd,
|
||||||
|
VHOST_BACKEND_TYPE_KERNEL, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "vhost-vsock: vhost_dev_init failed");
|
||||||
|
goto err_virtio;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = vhost_vsock_set_guest_cid(vsock);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "vhost-vsock: unable to set guest cid");
|
||||||
|
goto err_vhost_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
vsock->post_load_timer = NULL;
|
||||||
|
return;
|
||||||
|
|
||||||
|
err_vhost_dev:
|
||||||
|
vhost_dev_cleanup(&vsock->vhost_dev);
|
||||||
|
err_virtio:
|
||||||
|
virtio_cleanup(vdev);
|
||||||
|
close(vhostfd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_device_unrealize(DeviceState *dev, Error **errp)
|
||||||
|
{
|
||||||
|
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||||
|
VHostVSock *vsock = VHOST_VSOCK(dev);
|
||||||
|
|
||||||
|
vhost_vsock_post_load_timer_cleanup(vsock);
|
||||||
|
|
||||||
|
/* This will stop vhost backend if appropriate. */
|
||||||
|
vhost_vsock_set_status(vdev, 0);
|
||||||
|
|
||||||
|
vhost_dev_cleanup(&vsock->vhost_dev);
|
||||||
|
virtio_cleanup(vdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Property vhost_vsock_properties[] = {
|
||||||
|
DEFINE_PROP_UINT64("guest-cid", VHostVSock, conf.guest_cid, 0),
|
||||||
|
DEFINE_PROP_STRING("vhostfd", VHostVSock, conf.vhostfd),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void vhost_vsock_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
|
dc->props = vhost_vsock_properties;
|
||||||
|
dc->vmsd = &vmstate_virtio_vhost_vsock;
|
||||||
|
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||||
|
vdc->realize = vhost_vsock_device_realize;
|
||||||
|
vdc->unrealize = vhost_vsock_device_unrealize;
|
||||||
|
vdc->get_features = vhost_vsock_get_features;
|
||||||
|
vdc->get_config = vhost_vsock_get_config;
|
||||||
|
vdc->set_status = vhost_vsock_set_status;
|
||||||
|
vdc->guest_notifier_mask = vhost_vsock_guest_notifier_mask;
|
||||||
|
vdc->guest_notifier_pending = vhost_vsock_guest_notifier_pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo vhost_vsock_info = {
|
||||||
|
.name = TYPE_VHOST_VSOCK,
|
||||||
|
.parent = TYPE_VIRTIO_DEVICE,
|
||||||
|
.instance_size = sizeof(VHostVSock),
|
||||||
|
.class_init = vhost_vsock_class_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void vhost_vsock_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&vhost_vsock_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(vhost_vsock_register_types)
|
||||||
@@ -822,6 +822,9 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
|
|||||||
struct vhost_virtqueue *vq,
|
struct vhost_virtqueue *vq,
|
||||||
unsigned idx)
|
unsigned idx)
|
||||||
{
|
{
|
||||||
|
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
|
||||||
|
VirtioBusState *vbus = VIRTIO_BUS(qbus);
|
||||||
|
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
|
||||||
hwaddr s, l, a;
|
hwaddr s, l, a;
|
||||||
int r;
|
int r;
|
||||||
int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx);
|
int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx);
|
||||||
@@ -912,8 +915,19 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
|
|||||||
vhost_virtqueue_mask(dev, vdev, idx, false);
|
vhost_virtqueue_mask(dev, vdev, idx, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (k->query_guest_notifiers &&
|
||||||
|
k->query_guest_notifiers(qbus->parent) &&
|
||||||
|
virtio_queue_vector(vdev, idx) == VIRTIO_NO_VECTOR) {
|
||||||
|
file.fd = -1;
|
||||||
|
r = dev->vhost_ops->vhost_set_vring_call(dev, &file);
|
||||||
|
if (r) {
|
||||||
|
goto fail_vector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fail_vector:
|
||||||
fail_kick:
|
fail_kick:
|
||||||
fail_alloc:
|
fail_alloc:
|
||||||
cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
|
cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
|
||||||
|
|||||||
@@ -463,11 +463,24 @@ static void virtio_balloon_device_reset(VirtIODevice *vdev)
|
|||||||
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
|
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
|
||||||
|
|
||||||
if (s->stats_vq_elem != NULL) {
|
if (s->stats_vq_elem != NULL) {
|
||||||
|
virtqueue_discard(s->svq, s->stats_vq_elem, 0);
|
||||||
g_free(s->stats_vq_elem);
|
g_free(s->stats_vq_elem);
|
||||||
s->stats_vq_elem = NULL;
|
s->stats_vq_elem = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void virtio_balloon_set_status(VirtIODevice *vdev, uint8_t status)
|
||||||
|
{
|
||||||
|
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
|
||||||
|
|
||||||
|
if (!s->stats_vq_elem && vdev->vm_running &&
|
||||||
|
(status & VIRTIO_CONFIG_S_DRIVER_OK) && virtqueue_rewind(s->svq, 1)) {
|
||||||
|
/* poll stats queue for the element we have discarded when the VM
|
||||||
|
* was stopped */
|
||||||
|
virtio_balloon_receive_stats(vdev, s->svq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void virtio_balloon_instance_init(Object *obj)
|
static void virtio_balloon_instance_init(Object *obj)
|
||||||
{
|
{
|
||||||
VirtIOBalloon *s = VIRTIO_BALLOON(obj);
|
VirtIOBalloon *s = VIRTIO_BALLOON(obj);
|
||||||
@@ -505,6 +518,7 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
|
|||||||
vdc->get_features = virtio_balloon_get_features;
|
vdc->get_features = virtio_balloon_get_features;
|
||||||
vdc->save = virtio_balloon_save_device;
|
vdc->save = virtio_balloon_save_device;
|
||||||
vdc->load = virtio_balloon_load_device;
|
vdc->load = virtio_balloon_load_device;
|
||||||
|
vdc->set_status = virtio_balloon_set_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo virtio_balloon_info = {
|
static const TypeInfo virtio_balloon_info = {
|
||||||
|
|||||||
@@ -164,7 +164,8 @@ static int set_host_notifier_internal(DeviceState *proxy, VirtioBusState *bus,
|
|||||||
if (assign) {
|
if (assign) {
|
||||||
r = event_notifier_init(notifier, 1);
|
r = event_notifier_init(notifier, 1);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
error_report("%s: unable to init event notifier: %d", __func__, r);
|
error_report("%s: unable to init event notifier: %s (%d)",
|
||||||
|
__func__, strerror(-r), r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
|
virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
|
||||||
|
|||||||
@@ -294,6 +294,12 @@ static void virtio_pci_ioeventfd_set_disabled(DeviceState *d, bool disabled)
|
|||||||
|
|
||||||
#define QEMU_VIRTIO_PCI_QUEUE_MEM_MULT 0x1000
|
#define QEMU_VIRTIO_PCI_QUEUE_MEM_MULT 0x1000
|
||||||
|
|
||||||
|
static inline int virtio_pci_queue_mem_mult(struct VirtIOPCIProxy *proxy)
|
||||||
|
{
|
||||||
|
return (proxy->flags & VIRTIO_PCI_FLAG_PAGE_PER_VQ) ?
|
||||||
|
QEMU_VIRTIO_PCI_QUEUE_MEM_MULT : 4;
|
||||||
|
}
|
||||||
|
|
||||||
static int virtio_pci_ioeventfd_assign(DeviceState *d, EventNotifier *notifier,
|
static int virtio_pci_ioeventfd_assign(DeviceState *d, EventNotifier *notifier,
|
||||||
int n, bool assign)
|
int n, bool assign)
|
||||||
{
|
{
|
||||||
@@ -307,7 +313,7 @@ static int virtio_pci_ioeventfd_assign(DeviceState *d, EventNotifier *notifier,
|
|||||||
MemoryRegion *modern_mr = &proxy->notify.mr;
|
MemoryRegion *modern_mr = &proxy->notify.mr;
|
||||||
MemoryRegion *modern_notify_mr = &proxy->notify_pio.mr;
|
MemoryRegion *modern_notify_mr = &proxy->notify_pio.mr;
|
||||||
MemoryRegion *legacy_mr = &proxy->bar;
|
MemoryRegion *legacy_mr = &proxy->bar;
|
||||||
hwaddr modern_addr = QEMU_VIRTIO_PCI_QUEUE_MEM_MULT *
|
hwaddr modern_addr = virtio_pci_queue_mem_mult(proxy) *
|
||||||
virtio_get_queue_index(vq);
|
virtio_get_queue_index(vq);
|
||||||
hwaddr legacy_addr = VIRTIO_PCI_QUEUE_NOTIFY;
|
hwaddr legacy_addr = VIRTIO_PCI_QUEUE_NOTIFY;
|
||||||
|
|
||||||
@@ -1370,7 +1376,8 @@ static void virtio_pci_notify_write(void *opaque, hwaddr addr,
|
|||||||
uint64_t val, unsigned size)
|
uint64_t val, unsigned size)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = opaque;
|
VirtIODevice *vdev = opaque;
|
||||||
unsigned queue = addr / QEMU_VIRTIO_PCI_QUEUE_MEM_MULT;
|
VirtIOPCIProxy *proxy = VIRTIO_PCI(DEVICE(vdev)->parent_bus->parent);
|
||||||
|
unsigned queue = addr / virtio_pci_queue_mem_mult(proxy);
|
||||||
|
|
||||||
if (queue < VIRTIO_QUEUE_MAX) {
|
if (queue < VIRTIO_QUEUE_MAX) {
|
||||||
virtio_queue_notify(vdev, queue);
|
virtio_queue_notify(vdev, queue);
|
||||||
@@ -1520,7 +1527,7 @@ static void virtio_pci_modern_regions_init(VirtIOPCIProxy *proxy)
|
|||||||
¬ify_pio_ops,
|
¬ify_pio_ops,
|
||||||
virtio_bus_get_device(&proxy->bus),
|
virtio_bus_get_device(&proxy->bus),
|
||||||
"virtio-pci-notify-pio",
|
"virtio-pci-notify-pio",
|
||||||
proxy->notify.size);
|
proxy->notify_pio.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_pci_modern_region_map(VirtIOPCIProxy *proxy,
|
static void virtio_pci_modern_region_map(VirtIOPCIProxy *proxy,
|
||||||
@@ -1609,7 +1616,7 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
|
|||||||
struct virtio_pci_notify_cap notify = {
|
struct virtio_pci_notify_cap notify = {
|
||||||
.cap.cap_len = sizeof notify,
|
.cap.cap_len = sizeof notify,
|
||||||
.notify_off_multiplier =
|
.notify_off_multiplier =
|
||||||
cpu_to_le32(QEMU_VIRTIO_PCI_QUEUE_MEM_MULT),
|
cpu_to_le32(virtio_pci_queue_mem_mult(proxy)),
|
||||||
};
|
};
|
||||||
struct virtio_pci_cfg_cap cfg = {
|
struct virtio_pci_cfg_cap cfg = {
|
||||||
.cap.cap_len = sizeof cfg,
|
.cap.cap_len = sizeof cfg,
|
||||||
@@ -1744,8 +1751,7 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
|
|||||||
proxy->device.type = VIRTIO_PCI_CAP_DEVICE_CFG;
|
proxy->device.type = VIRTIO_PCI_CAP_DEVICE_CFG;
|
||||||
|
|
||||||
proxy->notify.offset = 0x3000;
|
proxy->notify.offset = 0x3000;
|
||||||
proxy->notify.size =
|
proxy->notify.size = virtio_pci_queue_mem_mult(proxy) * VIRTIO_QUEUE_MAX;
|
||||||
QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX;
|
|
||||||
proxy->notify.type = VIRTIO_PCI_CAP_NOTIFY_CFG;
|
proxy->notify.type = VIRTIO_PCI_CAP_NOTIFY_CFG;
|
||||||
|
|
||||||
proxy->notify_pio.offset = 0x0;
|
proxy->notify_pio.offset = 0x0;
|
||||||
@@ -1754,8 +1760,8 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
|
|||||||
|
|
||||||
/* subclasses can enforce modern, so do this unconditionally */
|
/* subclasses can enforce modern, so do this unconditionally */
|
||||||
memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci",
|
memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci",
|
||||||
2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT *
|
/* PCI BAR regions must be powers of 2 */
|
||||||
VIRTIO_QUEUE_MAX);
|
pow2ceil(proxy->notify.offset + proxy->notify.size));
|
||||||
|
|
||||||
memory_region_init_alias(&proxy->modern_cfg,
|
memory_region_init_alias(&proxy->modern_cfg,
|
||||||
OBJECT(proxy),
|
OBJECT(proxy),
|
||||||
@@ -1770,6 +1776,14 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
|
|||||||
proxy->disable_legacy = pcie_port ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
|
proxy->disable_legacy = pcie_port ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!virtio_pci_modern(proxy) && !virtio_pci_legacy(proxy)) {
|
||||||
|
error_setg(errp, "device cannot work as neither modern nor legacy mode"
|
||||||
|
" is enabled");
|
||||||
|
error_append_hint(errp, "Set either disable-modern or disable-legacy"
|
||||||
|
" to off\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (pcie_port && pci_is_express(pci_dev)) {
|
if (pcie_port && pci_is_express(pci_dev)) {
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
@@ -1833,6 +1847,8 @@ static Property virtio_pci_properties[] = {
|
|||||||
VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT, false),
|
VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT, false),
|
||||||
DEFINE_PROP_BIT("x-disable-pcie", VirtIOPCIProxy, flags,
|
DEFINE_PROP_BIT("x-disable-pcie", VirtIOPCIProxy, flags,
|
||||||
VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT, false),
|
VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT, false),
|
||||||
|
DEFINE_PROP_BIT("page-per-vq", VirtIOPCIProxy, flags,
|
||||||
|
VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT, false),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2055,6 +2071,54 @@ static const TypeInfo vhost_scsi_pci_info = {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* vhost-vsock-pci */
|
||||||
|
|
||||||
|
#ifdef CONFIG_VHOST_VSOCK
|
||||||
|
static Property vhost_vsock_pci_properties[] = {
|
||||||
|
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void vhost_vsock_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
|
||||||
|
{
|
||||||
|
VHostVSockPCI *dev = VHOST_VSOCK_PCI(vpci_dev);
|
||||||
|
DeviceState *vdev = DEVICE(&dev->vdev);
|
||||||
|
|
||||||
|
qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
|
||||||
|
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_pci_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
|
||||||
|
PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
|
||||||
|
k->realize = vhost_vsock_pci_realize;
|
||||||
|
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||||
|
dc->props = vhost_vsock_pci_properties;
|
||||||
|
pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
|
||||||
|
pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_VSOCK;
|
||||||
|
pcidev_k->revision = 0x00;
|
||||||
|
pcidev_k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_vsock_pci_instance_init(Object *obj)
|
||||||
|
{
|
||||||
|
VHostVSockPCI *dev = VHOST_VSOCK_PCI(obj);
|
||||||
|
|
||||||
|
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||||
|
TYPE_VHOST_VSOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo vhost_vsock_pci_info = {
|
||||||
|
.name = TYPE_VHOST_VSOCK_PCI,
|
||||||
|
.parent = TYPE_VIRTIO_PCI,
|
||||||
|
.instance_size = sizeof(VHostVSockPCI),
|
||||||
|
.instance_init = vhost_vsock_pci_instance_init,
|
||||||
|
.class_init = vhost_vsock_pci_class_init,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/* virtio-balloon-pci */
|
/* virtio-balloon-pci */
|
||||||
|
|
||||||
static Property virtio_balloon_pci_properties[] = {
|
static Property virtio_balloon_pci_properties[] = {
|
||||||
@@ -2485,6 +2549,9 @@ static void virtio_pci_register_types(void)
|
|||||||
#ifdef CONFIG_VHOST_SCSI
|
#ifdef CONFIG_VHOST_SCSI
|
||||||
type_register_static(&vhost_scsi_pci_info);
|
type_register_static(&vhost_scsi_pci_info);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_VHOST_VSOCK
|
||||||
|
type_register_static(&vhost_vsock_pci_info);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(virtio_pci_register_types)
|
type_init(virtio_pci_register_types)
|
||||||
|
|||||||
@@ -31,6 +31,9 @@
|
|||||||
#ifdef CONFIG_VHOST_SCSI
|
#ifdef CONFIG_VHOST_SCSI
|
||||||
#include "hw/virtio/vhost-scsi.h"
|
#include "hw/virtio/vhost-scsi.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_VHOST_VSOCK
|
||||||
|
#include "hw/virtio/vhost-vsock.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct VirtIOPCIProxy VirtIOPCIProxy;
|
typedef struct VirtIOPCIProxy VirtIOPCIProxy;
|
||||||
typedef struct VirtIOBlkPCI VirtIOBlkPCI;
|
typedef struct VirtIOBlkPCI VirtIOBlkPCI;
|
||||||
@@ -44,6 +47,7 @@ typedef struct VirtIOInputPCI VirtIOInputPCI;
|
|||||||
typedef struct VirtIOInputHIDPCI VirtIOInputHIDPCI;
|
typedef struct VirtIOInputHIDPCI VirtIOInputHIDPCI;
|
||||||
typedef struct VirtIOInputHostPCI VirtIOInputHostPCI;
|
typedef struct VirtIOInputHostPCI VirtIOInputHostPCI;
|
||||||
typedef struct VirtIOGPUPCI VirtIOGPUPCI;
|
typedef struct VirtIOGPUPCI VirtIOGPUPCI;
|
||||||
|
typedef struct VHostVSockPCI VHostVSockPCI;
|
||||||
|
|
||||||
/* virtio-pci-bus */
|
/* virtio-pci-bus */
|
||||||
|
|
||||||
@@ -64,6 +68,7 @@ enum {
|
|||||||
VIRTIO_PCI_FLAG_MIGRATE_EXTRA_BIT,
|
VIRTIO_PCI_FLAG_MIGRATE_EXTRA_BIT,
|
||||||
VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT,
|
VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT,
|
||||||
VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT,
|
VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT,
|
||||||
|
VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Need to activate work-arounds for buggy guests at vmstate load. */
|
/* Need to activate work-arounds for buggy guests at vmstate load. */
|
||||||
@@ -84,6 +89,10 @@ enum {
|
|||||||
#define VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY \
|
#define VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY \
|
||||||
(1 << VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT)
|
(1 << VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT)
|
||||||
|
|
||||||
|
/* page per vq flag to be used by split drivers within guests */
|
||||||
|
#define VIRTIO_PCI_FLAG_PAGE_PER_VQ \
|
||||||
|
(1 << VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MSIMessage msg;
|
MSIMessage msg;
|
||||||
int virq;
|
int virq;
|
||||||
@@ -324,6 +333,20 @@ struct VirtIOGPUPCI {
|
|||||||
VirtIOGPU vdev;
|
VirtIOGPU vdev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_VHOST_VSOCK
|
||||||
|
/*
|
||||||
|
* vhost-vsock-pci: This extends VirtioPCIProxy.
|
||||||
|
*/
|
||||||
|
#define TYPE_VHOST_VSOCK_PCI "vhost-vsock-pci"
|
||||||
|
#define VHOST_VSOCK_PCI(obj) \
|
||||||
|
OBJECT_CHECK(VHostVSockPCI, (obj), TYPE_VHOST_VSOCK_PCI)
|
||||||
|
|
||||||
|
struct VHostVSockPCI {
|
||||||
|
VirtIOPCIProxy parent_obj;
|
||||||
|
VHostVSock vdev;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Virtio ABI version, if we increment this, we break the guest driver. */
|
/* Virtio ABI version, if we increment this, we break the guest driver. */
|
||||||
#define VIRTIO_PCI_ABI_VERSION 0
|
#define VIRTIO_PCI_ABI_VERSION 0
|
||||||
|
|
||||||
|
|||||||
@@ -272,6 +272,28 @@ void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
|
|||||||
virtqueue_unmap_sg(vq, elem, len);
|
virtqueue_unmap_sg(vq, elem, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* virtqueue_rewind:
|
||||||
|
* @vq: The #VirtQueue
|
||||||
|
* @num: Number of elements to push back
|
||||||
|
*
|
||||||
|
* Pretend that elements weren't popped from the virtqueue. The next
|
||||||
|
* virtqueue_pop() will refetch the oldest element.
|
||||||
|
*
|
||||||
|
* Use virtqueue_discard() instead if you have a VirtQueueElement.
|
||||||
|
*
|
||||||
|
* Returns: true on success, false if @num is greater than the number of in use
|
||||||
|
* elements.
|
||||||
|
*/
|
||||||
|
bool virtqueue_rewind(VirtQueue *vq, unsigned int num)
|
||||||
|
{
|
||||||
|
if (num > vq->inuse) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
vq->last_avail_idx -= num;
|
||||||
|
vq->inuse -= num;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
||||||
unsigned int len, unsigned int idx)
|
unsigned int len, unsigned int idx)
|
||||||
{
|
{
|
||||||
@@ -822,6 +844,7 @@ void virtio_reset(void *opaque)
|
|||||||
vdev->vq[i].signalled_used_valid = false;
|
vdev->vq[i].signalled_used_valid = false;
|
||||||
vdev->vq[i].notification = true;
|
vdev->vq[i].notification = true;
|
||||||
vdev->vq[i].vring.num = vdev->vq[i].vring.num_default;
|
vdev->vq[i].vring.num = vdev->vq[i].vring.num_default;
|
||||||
|
vdev->vq[i].inuse = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,9 +65,10 @@ typedef enum {
|
|||||||
BDRV_REQ_MAY_UNMAP = 0x4,
|
BDRV_REQ_MAY_UNMAP = 0x4,
|
||||||
BDRV_REQ_NO_SERIALISING = 0x8,
|
BDRV_REQ_NO_SERIALISING = 0x8,
|
||||||
BDRV_REQ_FUA = 0x10,
|
BDRV_REQ_FUA = 0x10,
|
||||||
|
BDRV_REQ_WRITE_COMPRESSED = 0x20,
|
||||||
|
|
||||||
/* Mask of valid flags */
|
/* Mask of valid flags */
|
||||||
BDRV_REQ_MASK = 0x1f,
|
BDRV_REQ_MASK = 0x3f,
|
||||||
} BdrvRequestFlags;
|
} BdrvRequestFlags;
|
||||||
|
|
||||||
typedef struct BlockSizes {
|
typedef struct BlockSizes {
|
||||||
@@ -399,8 +400,6 @@ const char *bdrv_get_node_name(const BlockDriverState *bs);
|
|||||||
const char *bdrv_get_device_name(const BlockDriverState *bs);
|
const char *bdrv_get_device_name(const BlockDriverState *bs);
|
||||||
const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
|
const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
|
||||||
int bdrv_get_flags(BlockDriverState *bs);
|
int bdrv_get_flags(BlockDriverState *bs);
|
||||||
int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
|
||||||
const uint8_t *buf, int nb_sectors);
|
|
||||||
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
|
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
|
||||||
ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs);
|
ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs);
|
||||||
void bdrv_round_sectors_to_clusters(BlockDriverState *bs,
|
void bdrv_round_sectors_to_clusters(BlockDriverState *bs,
|
||||||
|
|||||||
@@ -204,8 +204,8 @@ struct BlockDriver {
|
|||||||
bool has_variable_length;
|
bool has_variable_length;
|
||||||
int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
|
int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
|
||||||
|
|
||||||
int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
|
int coroutine_fn (*bdrv_co_pwritev_compressed)(BlockDriverState *bs,
|
||||||
const uint8_t *buf, int nb_sectors);
|
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov);
|
||||||
|
|
||||||
int (*bdrv_snapshot_create)(BlockDriverState *bs,
|
int (*bdrv_snapshot_create)(BlockDriverState *bs,
|
||||||
QEMUSnapshotInfo *sn_info);
|
QEMUSnapshotInfo *sn_info);
|
||||||
@@ -765,6 +765,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
|||||||
void backup_start(const char *job_id, BlockDriverState *bs,
|
void backup_start(const char *job_id, BlockDriverState *bs,
|
||||||
BlockDriverState *target, int64_t speed,
|
BlockDriverState *target, int64_t speed,
|
||||||
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
|
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
|
||||||
|
bool compress,
|
||||||
BlockdevOnError on_source_error,
|
BlockdevOnError on_source_error,
|
||||||
BlockdevOnError on_target_error,
|
BlockdevOnError on_target_error,
|
||||||
BlockCompletionFunc *cb, void *opaque,
|
BlockCompletionFunc *cb, void *opaque,
|
||||||
|
|||||||
@@ -103,8 +103,9 @@ int nbd_disconnect(int fd);
|
|||||||
typedef struct NBDExport NBDExport;
|
typedef struct NBDExport NBDExport;
|
||||||
typedef struct NBDClient NBDClient;
|
typedef struct NBDClient NBDClient;
|
||||||
|
|
||||||
NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size,
|
NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
|
||||||
uint16_t nbdflags, void (*close)(NBDExport *),
|
uint16_t nbdflags, void (*close)(NBDExport *),
|
||||||
|
bool writethrough, BlockBackend *on_eject_blk,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
void nbd_export_close(NBDExport *exp);
|
void nbd_export_close(NBDExport *exp);
|
||||||
void nbd_export_get(NBDExport *exp);
|
void nbd_export_get(NBDExport *exp);
|
||||||
|
|||||||
@@ -280,4 +280,28 @@ static inline void g_hash_table_add(GHashTable *hash_table, gpointer key)
|
|||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !GLIB_CHECK_VERSION(2, 28, 0)
|
||||||
|
static inline void g_list_free_full(GList *list, GDestroyNotify free_func)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = list; l; l = l->next) {
|
||||||
|
free_func(l->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void g_slist_free_full(GSList *list, GDestroyNotify free_func)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
for (l = list; l; l = l->next) {
|
||||||
|
free_func(l->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_slist_free(list);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "hw/arm/arm.h"
|
#include "hw/arm/arm.h"
|
||||||
#include "hw/intc/aspeed_vic.h"
|
#include "hw/intc/aspeed_vic.h"
|
||||||
#include "hw/misc/aspeed_scu.h"
|
#include "hw/misc/aspeed_scu.h"
|
||||||
|
#include "hw/misc/aspeed_sdmc.h"
|
||||||
#include "hw/timer/aspeed_timer.h"
|
#include "hw/timer/aspeed_timer.h"
|
||||||
#include "hw/i2c/aspeed_i2c.h"
|
#include "hw/i2c/aspeed_i2c.h"
|
||||||
#include "hw/ssi/aspeed_smc.h"
|
#include "hw/ssi/aspeed_smc.h"
|
||||||
@@ -32,6 +33,7 @@ typedef struct AST2400State {
|
|||||||
AspeedSCUState scu;
|
AspeedSCUState scu;
|
||||||
AspeedSMCState smc;
|
AspeedSMCState smc;
|
||||||
AspeedSMCState spi;
|
AspeedSMCState spi;
|
||||||
|
AspeedSDMCState sdmc;
|
||||||
} AST2400State;
|
} AST2400State;
|
||||||
|
|
||||||
#define TYPE_AST2400 "ast2400"
|
#define TYPE_AST2400 "ast2400"
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ struct MachineClass {
|
|||||||
/*< public >*/
|
/*< public >*/
|
||||||
|
|
||||||
const char *family; /* NULL iff @name identifies a standalone machtype */
|
const char *family; /* NULL iff @name identifies a standalone machtype */
|
||||||
const char *name;
|
char *name;
|
||||||
const char *alias;
|
const char *alias;
|
||||||
const char *desc;
|
const char *desc;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
#ifndef HW_COMPAT_H
|
#ifndef HW_COMPAT_H
|
||||||
#define HW_COMPAT_H
|
#define HW_COMPAT_H
|
||||||
|
|
||||||
|
#define HW_COMPAT_2_7 \
|
||||||
|
{\
|
||||||
|
.driver = "virtio-pci",\
|
||||||
|
.property = "page-per-vq",\
|
||||||
|
.value = "on",\
|
||||||
|
},
|
||||||
|
|
||||||
#define HW_COMPAT_2_6 \
|
#define HW_COMPAT_2_6 \
|
||||||
{\
|
{\
|
||||||
.driver = "virtio-mmio",\
|
.driver = "virtio-mmio",\
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ struct PCMachineState {
|
|||||||
ISADevice *rtc;
|
ISADevice *rtc;
|
||||||
PCIBus *bus;
|
PCIBus *bus;
|
||||||
FWCfgState *fw_cfg;
|
FWCfgState *fw_cfg;
|
||||||
|
qemu_irq *gsi;
|
||||||
|
|
||||||
/* Configuration options: */
|
/* Configuration options: */
|
||||||
uint64_t max_ram_below_4g;
|
uint64_t max_ram_below_4g;
|
||||||
@@ -220,7 +221,7 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
|
|||||||
MemoryRegion *region, ram_addr_t size,
|
MemoryRegion *region, ram_addr_t size,
|
||||||
hwaddr mask);
|
hwaddr mask);
|
||||||
void i8042_isa_mouse_fake_event(void *opaque);
|
void i8042_isa_mouse_fake_event(void *opaque);
|
||||||
void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out);
|
void i8042_setup_a20_line(ISADevice *dev, qemu_irq a20_out);
|
||||||
|
|
||||||
/* pc.c */
|
/* pc.c */
|
||||||
extern int fd_bootchk;
|
extern int fd_bootchk;
|
||||||
@@ -367,6 +368,18 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
|
|||||||
int e820_get_num_entries(void);
|
int e820_get_num_entries(void);
|
||||||
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||||
|
|
||||||
|
#define PC_COMPAT_2_8 \
|
||||||
|
{\
|
||||||
|
.driver = TYPE_X86_CPU,\
|
||||||
|
.property = "l3-cache",\
|
||||||
|
.value = "off",\
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
#define PC_COMPAT_2_7 \
|
||||||
|
PC_COMPAT_2_8 \
|
||||||
|
HW_COMPAT_2_7
|
||||||
|
|
||||||
#define PC_COMPAT_2_6 \
|
#define PC_COMPAT_2_6 \
|
||||||
HW_COMPAT_2_6 \
|
HW_COMPAT_2_6 \
|
||||||
{\
|
{\
|
||||||
@@ -903,7 +916,6 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
|||||||
{ \
|
{ \
|
||||||
MachineClass *mc = MACHINE_CLASS(oc); \
|
MachineClass *mc = MACHINE_CLASS(oc); \
|
||||||
optsfn(mc); \
|
optsfn(mc); \
|
||||||
mc->name = namestr; \
|
|
||||||
mc->init = initfn; \
|
mc->init = initfn; \
|
||||||
} \
|
} \
|
||||||
static const TypeInfo pc_machine_type_##suffix = { \
|
static const TypeInfo pc_machine_type_##suffix = { \
|
||||||
|
|||||||
@@ -480,6 +480,8 @@ struct IDEBus {
|
|||||||
uint8_t retry_unit;
|
uint8_t retry_unit;
|
||||||
int64_t retry_sector_num;
|
int64_t retry_sector_num;
|
||||||
uint32_t retry_nsector;
|
uint32_t retry_nsector;
|
||||||
|
PortioList portio_list;
|
||||||
|
PortioList portio2_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TYPE_IDE_DEVICE "ide-device"
|
#define TYPE_IDE_DEVICE "ide-device"
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ typedef struct I8257State {
|
|||||||
QEMUBH *dma_bh;
|
QEMUBH *dma_bh;
|
||||||
bool dma_bh_scheduled;
|
bool dma_bh_scheduled;
|
||||||
int running;
|
int running;
|
||||||
|
PortioList portio_page;
|
||||||
|
PortioList portio_pageh;
|
||||||
} I8257State;
|
} I8257State;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -134,12 +134,15 @@ void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start);
|
|||||||
* device and use the legacy portio routines.
|
* device and use the legacy portio routines.
|
||||||
*
|
*
|
||||||
* @dev: the ISADevice against which these are registered; may be NULL.
|
* @dev: the ISADevice against which these are registered; may be NULL.
|
||||||
|
* @piolist: the PortioList associated with the io ports
|
||||||
* @start: the base I/O port against which the portio->offset is applied.
|
* @start: the base I/O port against which the portio->offset is applied.
|
||||||
* @portio: the ports, sorted by offset.
|
* @portio: the ports, sorted by offset.
|
||||||
* @opaque: passed into the portio callbacks.
|
* @opaque: passed into the portio callbacks.
|
||||||
* @name: passed into memory_region_init_io.
|
* @name: passed into memory_region_init_io.
|
||||||
*/
|
*/
|
||||||
void isa_register_portio_list(ISADevice *dev, uint16_t start,
|
void isa_register_portio_list(ISADevice *dev,
|
||||||
|
PortioList *piolist,
|
||||||
|
uint16_t start,
|
||||||
const MemoryRegionPortio *portio,
|
const MemoryRegionPortio *portio,
|
||||||
void *opaque, const char *name);
|
void *opaque, const char *name);
|
||||||
|
|
||||||
|
|||||||
31
include/hw/misc/aspeed_sdmc.h
Normal file
31
include/hw/misc/aspeed_sdmc.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* ASPEED SDRAM Memory Controller
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 IBM Corp.
|
||||||
|
*
|
||||||
|
* This code is licensed under the GPL version 2 or later. See the
|
||||||
|
* COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
#ifndef ASPEED_SDMC_H
|
||||||
|
#define ASPEED_SDMC_H
|
||||||
|
|
||||||
|
#include "hw/sysbus.h"
|
||||||
|
|
||||||
|
#define TYPE_ASPEED_SDMC "aspeed.sdmc"
|
||||||
|
#define ASPEED_SDMC(obj) OBJECT_CHECK(AspeedSDMCState, (obj), TYPE_ASPEED_SDMC)
|
||||||
|
|
||||||
|
#define ASPEED_SDMC_NR_REGS (0x8 >> 2)
|
||||||
|
|
||||||
|
typedef struct AspeedSDMCState {
|
||||||
|
/*< private >*/
|
||||||
|
SysBusDevice parent_obj;
|
||||||
|
|
||||||
|
/*< public >*/
|
||||||
|
MemoryRegion iomem;
|
||||||
|
|
||||||
|
uint32_t regs[ASPEED_SDMC_NR_REGS];
|
||||||
|
uint32_t silicon_rev;
|
||||||
|
|
||||||
|
} AspeedSDMCState;
|
||||||
|
|
||||||
|
#endif /* ASPEED_SDMC_H */
|
||||||
@@ -79,6 +79,7 @@
|
|||||||
#define PCI_DEVICE_ID_VIRTIO_SCSI 0x1004
|
#define PCI_DEVICE_ID_VIRTIO_SCSI 0x1004
|
||||||
#define PCI_DEVICE_ID_VIRTIO_RNG 0x1005
|
#define PCI_DEVICE_ID_VIRTIO_RNG 0x1005
|
||||||
#define PCI_DEVICE_ID_VIRTIO_9P 0x1009
|
#define PCI_DEVICE_ID_VIRTIO_9P 0x1009
|
||||||
|
#define PCI_DEVICE_ID_VIRTIO_VSOCK 0x1012
|
||||||
|
|
||||||
#define PCI_VENDOR_ID_REDHAT 0x1b36
|
#define PCI_VENDOR_ID_REDHAT 0x1b36
|
||||||
#define PCI_DEVICE_ID_REDHAT_BRIDGE 0x0001
|
#define PCI_DEVICE_ID_REDHAT_BRIDGE 0x0001
|
||||||
|
|||||||
30
include/hw/ppc/fdt.h
Normal file
30
include/hw/ppc/fdt.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* QEMU PowerPC helper routines for the device tree.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 IBM Corp.
|
||||||
|
*
|
||||||
|
* This code is licensed under the GPL version 2 or later. See the
|
||||||
|
* COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PPC_FDT_H
|
||||||
|
#define PPC_FDT_H
|
||||||
|
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
|
||||||
|
typedef struct CPUPPCState CPUPPCState;
|
||||||
|
|
||||||
|
#define _FDT(exp) \
|
||||||
|
do { \
|
||||||
|
int ret = (exp); \
|
||||||
|
if (ret < 0) { \
|
||||||
|
error_report("error creating device tree: %s: %s", \
|
||||||
|
#exp, fdt_strerror(ret)); \
|
||||||
|
exit(1); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
size_t ppc_create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
|
||||||
|
size_t maxsize);
|
||||||
|
|
||||||
|
#endif /* PPC_FDT_H */
|
||||||
@@ -224,7 +224,7 @@ typedef struct BusChild {
|
|||||||
struct BusState {
|
struct BusState {
|
||||||
Object obj;
|
Object obj;
|
||||||
DeviceState *parent;
|
DeviceState *parent;
|
||||||
const char *name;
|
char *name;
|
||||||
HotplugHandler *hotplug_handler;
|
HotplugHandler *hotplug_handler;
|
||||||
int max_index;
|
int max_index;
|
||||||
bool realized;
|
bool realized;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#define MAX_DEVNO 65535
|
#define MAX_DEVNO 65535
|
||||||
#define MAX_SCHID 65535
|
#define MAX_SCHID 65535
|
||||||
#define MAX_SSID 3
|
#define MAX_SSID 3
|
||||||
#define MAX_CSSID 254 /* 255 is reserved */
|
#define MAX_CSSID 255
|
||||||
#define MAX_CHPID 255
|
#define MAX_CHPID 255
|
||||||
|
|
||||||
#define MAX_CIWS 62
|
#define MAX_CIWS 62
|
||||||
|
|||||||
@@ -98,11 +98,14 @@ typedef struct SCCBHeader {
|
|||||||
} QEMU_PACKED SCCBHeader;
|
} QEMU_PACKED SCCBHeader;
|
||||||
|
|
||||||
#define SCCB_DATA_LEN (SCCB_SIZE - sizeof(SCCBHeader))
|
#define SCCB_DATA_LEN (SCCB_SIZE - sizeof(SCCBHeader))
|
||||||
|
#define SCCB_CPU_FEATURE_LEN 6
|
||||||
|
|
||||||
/* CPU information */
|
/* CPU information */
|
||||||
typedef struct CPUEntry {
|
typedef struct CPUEntry {
|
||||||
uint8_t address;
|
uint8_t address;
|
||||||
uint8_t reserved0[13];
|
uint8_t reserved0;
|
||||||
|
uint8_t features[SCCB_CPU_FEATURE_LEN];
|
||||||
|
uint8_t reserved2[6];
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t reserved1;
|
uint8_t reserved1;
|
||||||
} QEMU_PACKED CPUEntry;
|
} QEMU_PACKED CPUEntry;
|
||||||
@@ -118,12 +121,18 @@ typedef struct ReadInfo {
|
|||||||
uint8_t loadparm[8]; /* 24-31 */
|
uint8_t loadparm[8]; /* 24-31 */
|
||||||
uint8_t _reserved3[48 - 32]; /* 32-47 */
|
uint8_t _reserved3[48 - 32]; /* 32-47 */
|
||||||
uint64_t facilities; /* 48-55 */
|
uint64_t facilities; /* 48-55 */
|
||||||
uint8_t _reserved0[100 - 56];
|
uint8_t _reserved0[76 - 56]; /* 56-75 */
|
||||||
|
uint32_t ibc_val;
|
||||||
|
uint8_t conf_char[96 - 80]; /* 80-95 */
|
||||||
|
uint8_t _reserved4[99 - 96]; /* 96-98 */
|
||||||
|
uint8_t mha_pow;
|
||||||
uint32_t rnsize2;
|
uint32_t rnsize2;
|
||||||
uint64_t rnmax2;
|
uint64_t rnmax2;
|
||||||
uint8_t _reserved4[120-112]; /* 112-119 */
|
uint8_t _reserved6[116 - 112]; /* 112-115 */
|
||||||
|
uint8_t conf_char_ext[120 - 116]; /* 116-119 */
|
||||||
uint16_t highest_cpu;
|
uint16_t highest_cpu;
|
||||||
uint8_t _reserved5[128 - 122]; /* 122-127 */
|
uint8_t _reserved5[124 - 122]; /* 122-123 */
|
||||||
|
uint32_t hmfai;
|
||||||
struct CPUEntry entries[0];
|
struct CPUEntry entries[0];
|
||||||
} QEMU_PACKED ReadInfo;
|
} QEMU_PACKED ReadInfo;
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ typedef int (*vhost_migration_done_op)(struct vhost_dev *dev,
|
|||||||
typedef bool (*vhost_backend_can_merge_op)(struct vhost_dev *dev,
|
typedef bool (*vhost_backend_can_merge_op)(struct vhost_dev *dev,
|
||||||
uint64_t start1, uint64_t size1,
|
uint64_t start1, uint64_t size1,
|
||||||
uint64_t start2, uint64_t size2);
|
uint64_t start2, uint64_t size2);
|
||||||
|
typedef int (*vhost_vsock_set_guest_cid_op)(struct vhost_dev *dev,
|
||||||
|
uint64_t guest_cid);
|
||||||
|
typedef int (*vhost_vsock_set_running_op)(struct vhost_dev *dev, int start);
|
||||||
|
|
||||||
typedef struct VhostOps {
|
typedef struct VhostOps {
|
||||||
VhostBackendType backend_type;
|
VhostBackendType backend_type;
|
||||||
@@ -102,6 +105,8 @@ typedef struct VhostOps {
|
|||||||
vhost_requires_shm_log_op vhost_requires_shm_log;
|
vhost_requires_shm_log_op vhost_requires_shm_log;
|
||||||
vhost_migration_done_op vhost_migration_done;
|
vhost_migration_done_op vhost_migration_done;
|
||||||
vhost_backend_can_merge_op vhost_backend_can_merge;
|
vhost_backend_can_merge_op vhost_backend_can_merge;
|
||||||
|
vhost_vsock_set_guest_cid_op vhost_vsock_set_guest_cid;
|
||||||
|
vhost_vsock_set_running_op vhost_vsock_set_running;
|
||||||
} VhostOps;
|
} VhostOps;
|
||||||
|
|
||||||
extern const VhostOps user_ops;
|
extern const VhostOps user_ops;
|
||||||
|
|||||||
41
include/hw/virtio/vhost-vsock.h
Normal file
41
include/hw/virtio/vhost-vsock.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Vhost vsock virtio device
|
||||||
|
*
|
||||||
|
* Copyright 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||||
|
* (at your option) any later version. See the COPYING file in the
|
||||||
|
* top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _QEMU_VHOST_VSOCK_H
|
||||||
|
#define _QEMU_VHOST_VSOCK_H
|
||||||
|
|
||||||
|
#include "hw/virtio/virtio.h"
|
||||||
|
#include "hw/virtio/vhost.h"
|
||||||
|
|
||||||
|
#define TYPE_VHOST_VSOCK "vhost-vsock-device"
|
||||||
|
#define VHOST_VSOCK(obj) \
|
||||||
|
OBJECT_CHECK(VHostVSock, (obj), TYPE_VHOST_VSOCK)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t guest_cid;
|
||||||
|
char *vhostfd;
|
||||||
|
} VHostVSockConf;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/*< private >*/
|
||||||
|
VirtIODevice parent;
|
||||||
|
VHostVSockConf conf;
|
||||||
|
struct vhost_virtqueue vhost_vqs[2];
|
||||||
|
struct vhost_dev vhost_dev;
|
||||||
|
VirtQueue *event_vq;
|
||||||
|
QEMUTimer *post_load_timer;
|
||||||
|
|
||||||
|
/*< public >*/
|
||||||
|
} VHostVSock;
|
||||||
|
|
||||||
|
#endif /* _QEMU_VHOST_VSOCK_H */
|
||||||
@@ -154,6 +154,7 @@ void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
|
|||||||
void virtqueue_flush(VirtQueue *vq, unsigned int count);
|
void virtqueue_flush(VirtQueue *vq, unsigned int count);
|
||||||
void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
|
void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
|
||||||
unsigned int len);
|
unsigned int len);
|
||||||
|
bool virtqueue_rewind(VirtQueue *vq, unsigned int num);
|
||||||
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
||||||
unsigned int len, unsigned int idx);
|
unsigned int len, unsigned int idx);
|
||||||
|
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ bool qemu_co_queue_empty(CoQueue *queue);
|
|||||||
*/
|
*/
|
||||||
typedef struct CoMutex {
|
typedef struct CoMutex {
|
||||||
bool locked;
|
bool locked;
|
||||||
|
Coroutine *holder;
|
||||||
CoQueue queue;
|
CoQueue queue;
|
||||||
} CoMutex;
|
} CoMutex;
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ struct Coroutine {
|
|||||||
void *entry_arg;
|
void *entry_arg;
|
||||||
Coroutine *caller;
|
Coroutine *caller;
|
||||||
QSLIST_ENTRY(Coroutine) pool_next;
|
QSLIST_ENTRY(Coroutine) pool_next;
|
||||||
|
size_t locks_held;
|
||||||
|
|
||||||
/* Coroutines that should be woken up when we yield or terminate */
|
/* Coroutines that should be woken up when we yield or terminate */
|
||||||
QSIMPLEQ_HEAD(, Coroutine) co_queue_wakeup;
|
QSIMPLEQ_HEAD(, Coroutine) co_queue_wakeup;
|
||||||
|
|||||||
@@ -611,6 +611,37 @@
|
|||||||
#define KEY_KBDINPUTASSIST_ACCEPT 0x264
|
#define KEY_KBDINPUTASSIST_ACCEPT 0x264
|
||||||
#define KEY_KBDINPUTASSIST_CANCEL 0x265
|
#define KEY_KBDINPUTASSIST_CANCEL 0x265
|
||||||
|
|
||||||
|
/* Diagonal movement keys */
|
||||||
|
#define KEY_RIGHT_UP 0x266
|
||||||
|
#define KEY_RIGHT_DOWN 0x267
|
||||||
|
#define KEY_LEFT_UP 0x268
|
||||||
|
#define KEY_LEFT_DOWN 0x269
|
||||||
|
|
||||||
|
#define KEY_ROOT_MENU 0x26a /* Show Device's Root Menu */
|
||||||
|
/* Show Top Menu of the Media (e.g. DVD) */
|
||||||
|
#define KEY_MEDIA_TOP_MENU 0x26b
|
||||||
|
#define KEY_NUMERIC_11 0x26c
|
||||||
|
#define KEY_NUMERIC_12 0x26d
|
||||||
|
/*
|
||||||
|
* Toggle Audio Description: refers to an audio service that helps blind and
|
||||||
|
* visually impaired consumers understand the action in a program. Note: in
|
||||||
|
* some countries this is referred to as "Video Description".
|
||||||
|
*/
|
||||||
|
#define KEY_AUDIO_DESC 0x26e
|
||||||
|
#define KEY_3D_MODE 0x26f
|
||||||
|
#define KEY_NEXT_FAVORITE 0x270
|
||||||
|
#define KEY_STOP_RECORD 0x271
|
||||||
|
#define KEY_PAUSE_RECORD 0x272
|
||||||
|
#define KEY_VOD 0x273 /* Video on Demand */
|
||||||
|
#define KEY_UNMUTE 0x274
|
||||||
|
#define KEY_FASTREVERSE 0x275
|
||||||
|
#define KEY_SLOWREVERSE 0x276
|
||||||
|
/*
|
||||||
|
* Control a data application associated with the currently viewed channel,
|
||||||
|
* e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.)
|
||||||
|
*/
|
||||||
|
#define KEY_DATA 0x275
|
||||||
|
|
||||||
#define BTN_TRIGGER_HAPPY 0x2c0
|
#define BTN_TRIGGER_HAPPY 0x2c0
|
||||||
#define BTN_TRIGGER_HAPPY1 0x2c0
|
#define BTN_TRIGGER_HAPPY1 0x2c0
|
||||||
#define BTN_TRIGGER_HAPPY2 0x2c1
|
#define BTN_TRIGGER_HAPPY2 0x2c1
|
||||||
@@ -749,6 +780,7 @@
|
|||||||
#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */
|
#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */
|
||||||
#define SW_LINEIN_INSERT 0x0d /* set = inserted */
|
#define SW_LINEIN_INSERT 0x0d /* set = inserted */
|
||||||
#define SW_MUTE_DEVICE 0x0e /* set = device disabled */
|
#define SW_MUTE_DEVICE 0x0e /* set = device disabled */
|
||||||
|
#define SW_PEN_INSERTED 0x0f /* set = pen inserted */
|
||||||
#define SW_MAX_ 0x0f
|
#define SW_MAX_ 0x0f
|
||||||
#define SW_CNT (SW_MAX_+1)
|
#define SW_CNT (SW_MAX_+1)
|
||||||
|
|
||||||
|
|||||||
@@ -244,6 +244,7 @@ struct input_mask {
|
|||||||
#define BUS_ATARI 0x1B
|
#define BUS_ATARI 0x1B
|
||||||
#define BUS_SPI 0x1C
|
#define BUS_SPI 0x1C
|
||||||
#define BUS_RMI 0x1D
|
#define BUS_RMI 0x1D
|
||||||
|
#define BUS_CEC 0x1E
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MT_TOOL types
|
* MT_TOOL types
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user