Compare commits
243 Commits
pull-seabi
...
pull-input
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e6a64cb8d | ||
|
|
2330e9e7cc | ||
|
|
d4df42c431 | ||
|
|
c80276b420 | ||
|
|
d7b7f526b1 | ||
|
|
96d7c0720e | ||
|
|
57a4e3b92b | ||
|
|
cde8dcbc92 | ||
|
|
f1ef557866 | ||
|
|
7de2cc8f78 | ||
|
|
a91a4e7d8c | ||
|
|
b3b22db69f | ||
|
|
f7d3f8c0c0 | ||
|
|
93d16d81c8 | ||
|
|
cdd85eb280 | ||
|
|
0a608a6e13 | ||
|
|
4e3bfc167d | ||
|
|
ab9746570a | ||
|
|
bd4976838d | ||
|
|
af9ed379fc | ||
|
|
bf328399da | ||
|
|
3e5cfba3ca | ||
|
|
67d5cd9722 | ||
|
|
90a0f9afec | ||
|
|
5d1abf2344 | ||
|
|
06a96dae11 | ||
|
|
c188e30315 | ||
|
|
67aad508de | ||
|
|
e7d336959b | ||
|
|
f7c40aa1e7 | ||
|
|
b804e8a62a | ||
|
|
dd70bd0d4c | ||
|
|
3f9e485964 | ||
|
|
cf2499350a | ||
|
|
bb0995468a | ||
|
|
e468b6730c | ||
|
|
07c6f329bd | ||
|
|
b39b7718dc | ||
|
|
cdbd727c20 | ||
|
|
7399a337e4 | ||
|
|
81daabaf7a | ||
|
|
a390284b80 | ||
|
|
7e9a7c50d9 | ||
|
|
4aa3f4dd5b | ||
|
|
40bfe48f1c | ||
|
|
217f1b4a72 | ||
|
|
87f8b62604 | ||
|
|
c35bd19a5c | ||
|
|
d6276d26bd | ||
|
|
6aff24c6a6 | ||
|
|
09f71b054a | ||
|
|
62a48a2a57 | ||
|
|
cf2887c973 | ||
|
|
7eb24386db | ||
|
|
fb02d56e96 | ||
|
|
adae837d40 | ||
|
|
39a3b377b8 | ||
|
|
77280adbdf | ||
|
|
8d76bfe8f8 | ||
|
|
823efc5d26 | ||
|
|
4f4a9ca4a4 | ||
|
|
66542f6399 | ||
|
|
eef9f19eea | ||
|
|
e0dadc1e9e | ||
|
|
5229f45bd9 | ||
|
|
bb14a1eda0 | ||
|
|
90e26f5aac | ||
|
|
5563168c53 | ||
|
|
69e87b3268 | ||
|
|
91d3550990 | ||
|
|
0c56c6ab68 | ||
|
|
975b1c3ac6 | ||
|
|
fc5d0a2b24 | ||
|
|
b6954712ab | ||
|
|
37f9e0a2b6 | ||
|
|
a15fcc3cf6 | ||
|
|
3b098d5697 | ||
|
|
23d1705f42 | ||
|
|
a8fff94d28 | ||
|
|
1830f22a67 | ||
|
|
e7ca565629 | ||
|
|
b70ce1018a | ||
|
|
7a0525c7be | ||
|
|
09204eac9b | ||
|
|
2c0ef9f411 | ||
|
|
1158bb2a05 | ||
|
|
911ee36d41 | ||
|
|
c7eb39cbd4 | ||
|
|
9d8256ebc0 | ||
|
|
c61d8126fc | ||
|
|
c540128f93 | ||
|
|
015e02f880 | ||
|
|
1331eab216 | ||
|
|
3cb5158f15 | ||
|
|
726bdf653a | ||
|
|
2f5ae772c6 | ||
|
|
de1b9b85ef | ||
|
|
ada03a0e84 | ||
|
|
1f00b27f17 | ||
|
|
59d7c14eef | ||
|
|
120c1084ed | ||
|
|
5f6f0e27fb | ||
|
|
07bee7f4f4 | ||
|
|
791b7d2340 | ||
|
|
b0aaca4d7f | ||
|
|
f1f7a1ddf3 | ||
|
|
a03ef88f77 | ||
|
|
e293b7a3df | ||
|
|
720ff280e7 | ||
|
|
d9ca2ea2e2 | ||
|
|
cf2ab8fc34 | ||
|
|
18d51c4bac | ||
|
|
fbcbbf4e80 | ||
|
|
f8e2bd538d | ||
|
|
83fd6dd3e7 | ||
|
|
adad6496c5 | ||
|
|
0d1049c7d1 | ||
|
|
ebb7af2173 | ||
|
|
25ec177d90 | ||
|
|
28b04a8f65 | ||
|
|
db1e80ee2e | ||
|
|
e858a9705c | ||
|
|
eecc77473b | ||
|
|
a9d52a7563 | ||
|
|
1c42f149dd | ||
|
|
5411541270 | ||
|
|
8cc9c6e92b | ||
|
|
a5b8dd2ce8 | ||
|
|
d9e0dfa246 | ||
|
|
ad82be2f4f | ||
|
|
b9f7855a50 | ||
|
|
29cc6a6834 | ||
|
|
5def6b80e1 | ||
|
|
79ba8c986a | ||
|
|
a65064816d | ||
|
|
2914a1de99 | ||
|
|
a84178ccff | ||
|
|
c8b3b998e2 | ||
|
|
835db3ee7b | ||
|
|
24ce9a2026 | ||
|
|
efaf4781a9 | ||
|
|
f9e95af0a6 | ||
|
|
202204717a | ||
|
|
476b923c32 | ||
|
|
82524274ea | ||
|
|
a604fa2ba5 | ||
|
|
cff86b38ac | ||
|
|
cfef6a45c7 | ||
|
|
60a0f1af07 | ||
|
|
269fe4c3ab | ||
|
|
66bf7d58d8 | ||
|
|
1070048eae | ||
|
|
2e2aa31674 | ||
|
|
afea4e1410 | ||
|
|
1108b2f8a9 | ||
|
|
69b205bb0b | ||
|
|
b4b4a57fa6 | ||
|
|
444dd1af1c | ||
|
|
c0f2abff73 | ||
|
|
290fd20db6 | ||
|
|
b2e1fffb5a | ||
|
|
8662d7db39 | ||
|
|
2c7ad80443 | ||
|
|
912acdf487 | ||
|
|
949868633f | ||
|
|
073de86aa9 | ||
|
|
651060aba7 | ||
|
|
1f0252e66e | ||
|
|
ae4de14cd3 | ||
|
|
2e4109de8e | ||
|
|
f4ec5e26ed | ||
|
|
318f67ce13 | ||
|
|
606b54986d | ||
|
|
c4e6c42353 | ||
|
|
7093645a84 | ||
|
|
158c87e5de | ||
|
|
600426f2df | ||
|
|
1165942311 | ||
|
|
0d7e96c9b5 | ||
|
|
3b1154fff1 | ||
|
|
a1c5e949dd | ||
|
|
13f12430d4 | ||
|
|
9164b89762 | ||
|
|
6b9c1dd2cd | ||
|
|
58eeb83cc7 | ||
|
|
6dd726a2bf | ||
|
|
a0efbf1660 | ||
|
|
58e19e6e79 | ||
|
|
5178ecd863 | ||
|
|
3173a1fd54 | ||
|
|
9b9611c85d | ||
|
|
e1ad9bc405 | ||
|
|
924ed16386 | ||
|
|
7c1c69bca4 | ||
|
|
73bce5187b | ||
|
|
b7f480c3f6 | ||
|
|
b68cb06093 | ||
|
|
cace7b801d | ||
|
|
7673bb4cd3 | ||
|
|
f4b99537f1 | ||
|
|
034c2e6902 | ||
|
|
a74229597e | ||
|
|
49e14ddbce | ||
|
|
684204593d | ||
|
|
0b73c9bb06 | ||
|
|
1599121b57 | ||
|
|
ae2923b5c2 | ||
|
|
5d636e21c4 | ||
|
|
a19861666b | ||
|
|
39e0b03dec | ||
|
|
a7aeb5f7b2 | ||
|
|
a1777f7f64 | ||
|
|
f5666418c4 | ||
|
|
d317091d5e | ||
|
|
6c6668232e | ||
|
|
62cee1a28a | ||
|
|
0830c96d70 | ||
|
|
01c9742d9d | ||
|
|
97a83ec3a9 | ||
|
|
10d01f73e3 | ||
|
|
621d983a1f | ||
|
|
bf8d492405 | ||
|
|
b86eacb804 | ||
|
|
1b04cc801a | ||
|
|
5ec7d09818 | ||
|
|
e2c8f9e44e | ||
|
|
0c16c056a4 | ||
|
|
8cbfc94269 | ||
|
|
8b7cdba386 | ||
|
|
7b143999f2 | ||
|
|
e5857062a6 | ||
|
|
f7725df387 | ||
|
|
ef763fa4bd | ||
|
|
1d17654e76 | ||
|
|
972487b878 | ||
|
|
8df42d855c | ||
|
|
45027808cd | ||
|
|
c52125ab92 | ||
|
|
43716de6b3 | ||
|
|
1676103dc2 | ||
|
|
4d9dc8b7a8 | ||
|
|
c9c3dc5f4b | ||
|
|
ffdc5a2bce |
6
Makefile
6
Makefile
@@ -30,7 +30,7 @@ CONFIG_ALL=y
|
||||
-include config-all-devices.mak
|
||||
-include config-all-disas.mak
|
||||
|
||||
config-host.mak: $(SRC_PATH)/configure
|
||||
config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios
|
||||
@echo $@ is out-of-date, running configure
|
||||
@# TODO: The next lines include code which supports a smooth
|
||||
@# transition from old configurations without config.status.
|
||||
@@ -408,8 +408,7 @@ common de-ch es fo fr-ca hu ja mk nl-be pt sl tr \
|
||||
bepo cz
|
||||
|
||||
ifdef INSTALL_BLOBS
|
||||
BLOBS=bios.bin bios-256k.bin bios-fast.bin \
|
||||
sgabios.bin vgabios.bin vgabios-cirrus.bin \
|
||||
BLOBS=bios.bin bios-256k.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
|
||||
vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin vgabios-virtio.bin \
|
||||
acpi-dsdt.aml \
|
||||
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin QEMU,cgthree.bin \
|
||||
@@ -417,6 +416,7 @@ pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
|
||||
pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
|
||||
efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \
|
||||
efi-pcnet.rom efi-rtl8139.rom efi-virtio.rom \
|
||||
efi-e1000e.rom efi-vmxnet3.rom \
|
||||
qemu-icon.bmp qemu_logo_no_text.svg \
|
||||
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
|
||||
multiboot.bin linuxboot.bin kvmvapic.bin \
|
||||
|
||||
@@ -25,16 +25,51 @@
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/char.h"
|
||||
#include "ui/console.h"
|
||||
#include "ui/input.h"
|
||||
|
||||
#define MSMOUSE_LO6(n) ((n) & 0x3f)
|
||||
#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
|
||||
|
||||
static void msmouse_event(void *opaque,
|
||||
int dx, int dy, int dz, int buttons_state)
|
||||
{
|
||||
CharDriverState *chr = (CharDriverState *)opaque;
|
||||
typedef struct {
|
||||
CharDriverState *chr;
|
||||
QemuInputHandlerState *hs;
|
||||
int axis[INPUT_AXIS__MAX];
|
||||
bool btns[INPUT_BUTTON__MAX];
|
||||
bool btnc[INPUT_BUTTON__MAX];
|
||||
uint8_t outbuf[32];
|
||||
int outlen;
|
||||
} MouseState;
|
||||
|
||||
static void msmouse_chr_accept_input(CharDriverState *chr)
|
||||
{
|
||||
MouseState *mouse = chr->opaque;
|
||||
int len;
|
||||
|
||||
len = qemu_chr_be_can_write(chr);
|
||||
if (len > mouse->outlen) {
|
||||
len = mouse->outlen;
|
||||
}
|
||||
if (!len) {
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_chr_be_write(chr, mouse->outbuf, len);
|
||||
mouse->outlen -= len;
|
||||
if (mouse->outlen) {
|
||||
memmove(mouse->outbuf, mouse->outbuf + len, mouse->outlen);
|
||||
}
|
||||
}
|
||||
|
||||
static void msmouse_queue_event(MouseState *mouse)
|
||||
{
|
||||
unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 };
|
||||
int dx, dy, count = 3;
|
||||
|
||||
dx = mouse->axis[INPUT_AXIS_X];
|
||||
mouse->axis[INPUT_AXIS_X] = 0;
|
||||
|
||||
dy = mouse->axis[INPUT_AXIS_Y];
|
||||
mouse->axis[INPUT_AXIS_Y] = 0;
|
||||
|
||||
/* Movement deltas */
|
||||
bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx);
|
||||
@@ -42,14 +77,54 @@ static void msmouse_event(void *opaque,
|
||||
bytes[2] |= MSMOUSE_LO6(dy);
|
||||
|
||||
/* Buttons */
|
||||
bytes[0] |= (buttons_state & 0x01 ? 0x20 : 0x00);
|
||||
bytes[0] |= (buttons_state & 0x02 ? 0x10 : 0x00);
|
||||
bytes[3] |= (buttons_state & 0x04 ? 0x20 : 0x00);
|
||||
bytes[0] |= (mouse->btns[INPUT_BUTTON_LEFT] ? 0x20 : 0x00);
|
||||
bytes[0] |= (mouse->btns[INPUT_BUTTON_RIGHT] ? 0x10 : 0x00);
|
||||
if (mouse->btns[INPUT_BUTTON_MIDDLE] ||
|
||||
mouse->btnc[INPUT_BUTTON_MIDDLE]) {
|
||||
bytes[3] |= (mouse->btns[INPUT_BUTTON_MIDDLE] ? 0x20 : 0x00);
|
||||
mouse->btnc[INPUT_BUTTON_MIDDLE] = false;
|
||||
count = 4;
|
||||
}
|
||||
|
||||
/* We always send the packet of, so that we do not have to keep track
|
||||
of previous state of the middle button. This can potentially confuse
|
||||
some very old drivers for two button mice though. */
|
||||
qemu_chr_be_write(chr, bytes, 4);
|
||||
if (mouse->outlen <= sizeof(mouse->outbuf) - count) {
|
||||
memcpy(mouse->outbuf + mouse->outlen, bytes, count);
|
||||
mouse->outlen += count;
|
||||
} else {
|
||||
/* queue full -> drop event */
|
||||
}
|
||||
}
|
||||
|
||||
static void msmouse_input_event(DeviceState *dev, QemuConsole *src,
|
||||
InputEvent *evt)
|
||||
{
|
||||
MouseState *mouse = (MouseState *)dev;
|
||||
InputMoveEvent *move;
|
||||
InputBtnEvent *btn;
|
||||
|
||||
switch (evt->type) {
|
||||
case INPUT_EVENT_KIND_REL:
|
||||
move = evt->u.rel.data;
|
||||
mouse->axis[move->axis] += move->value;
|
||||
break;
|
||||
|
||||
case INPUT_EVENT_KIND_BTN:
|
||||
btn = evt->u.btn.data;
|
||||
mouse->btns[btn->button] = btn->down;
|
||||
mouse->btnc[btn->button] = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* keep gcc happy */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void msmouse_input_sync(DeviceState *dev)
|
||||
{
|
||||
MouseState *mouse = (MouseState *)dev;
|
||||
|
||||
msmouse_queue_event(mouse);
|
||||
msmouse_chr_accept_input(mouse->chr);
|
||||
}
|
||||
|
||||
static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int len)
|
||||
@@ -60,26 +135,41 @@ static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int
|
||||
|
||||
static void msmouse_chr_close (struct CharDriverState *chr)
|
||||
{
|
||||
g_free (chr);
|
||||
MouseState *mouse = chr->opaque;
|
||||
|
||||
qemu_input_handler_unregister(mouse->hs);
|
||||
g_free(mouse);
|
||||
g_free(chr);
|
||||
}
|
||||
|
||||
static QemuInputHandler msmouse_handler = {
|
||||
.name = "QEMU Microsoft Mouse",
|
||||
.mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
|
||||
.event = msmouse_input_event,
|
||||
.sync = msmouse_input_sync,
|
||||
};
|
||||
|
||||
static CharDriverState *qemu_chr_open_msmouse(const char *id,
|
||||
ChardevBackend *backend,
|
||||
ChardevReturn *ret,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevCommon *common = backend->u.msmouse.data;
|
||||
MouseState *mouse;
|
||||
CharDriverState *chr;
|
||||
|
||||
chr = qemu_chr_alloc(common, errp);
|
||||
if (!chr) {
|
||||
return NULL;
|
||||
}
|
||||
chr->chr_write = msmouse_chr_write;
|
||||
chr->chr_close = msmouse_chr_close;
|
||||
chr->chr_accept_input = msmouse_chr_accept_input;
|
||||
chr->explicit_be_open = true;
|
||||
|
||||
qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
|
||||
mouse = g_new0(MouseState, 1);
|
||||
mouse->hs = qemu_input_handler_register((DeviceState *)mouse,
|
||||
&msmouse_handler);
|
||||
|
||||
mouse->chr = chr;
|
||||
chr->opaque = mouse;
|
||||
|
||||
return chr;
|
||||
}
|
||||
|
||||
142
block.c
142
block.c
@@ -536,9 +536,10 @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
|
||||
return drv;
|
||||
}
|
||||
|
||||
static int find_image_format(BlockDriverState *bs, const char *filename,
|
||||
static int find_image_format(BdrvChild *file, const char *filename,
|
||||
BlockDriver **pdrv, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs = file->bs;
|
||||
BlockDriver *drv;
|
||||
uint8_t buf[BLOCK_PROBE_BUF_SIZE];
|
||||
int ret = 0;
|
||||
@@ -549,7 +550,7 @@ static int find_image_format(BlockDriverState *bs, const char *filename,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs, 0, buf, sizeof(buf));
|
||||
ret = bdrv_pread(file, 0, buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not read image for determining its "
|
||||
"format");
|
||||
@@ -937,7 +938,6 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
|
||||
goto fail_opts;
|
||||
}
|
||||
|
||||
bs->request_alignment = drv->bdrv_co_preadv ? 1 : 512;
|
||||
bs->read_only = !(bs->open_flags & BDRV_O_RDWR);
|
||||
|
||||
if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) {
|
||||
@@ -1017,7 +1017,7 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
|
||||
|
||||
assert(bdrv_opt_mem_align(bs) != 0);
|
||||
assert(bdrv_min_mem_align(bs) != 0);
|
||||
assert(is_power_of_2(bs->request_alignment) || bdrv_is_sg(bs));
|
||||
assert(is_power_of_2(bs->bl.request_alignment));
|
||||
|
||||
qemu_opts_del(opts);
|
||||
return 0;
|
||||
@@ -1653,7 +1653,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||
/* Image format probing */
|
||||
bs->probed = !drv;
|
||||
if (!drv && file) {
|
||||
ret = find_image_format(file->bs, filename, &drv, &local_err);
|
||||
ret = find_image_format(file, filename, &drv, &local_err);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -2184,9 +2184,9 @@ static void bdrv_close(BlockDriverState *bs)
|
||||
bs->backing_file[0] = '\0';
|
||||
bs->backing_format[0] = '\0';
|
||||
bs->total_sectors = 0;
|
||||
bs->encrypted = 0;
|
||||
bs->valid_key = 0;
|
||||
bs->sg = 0;
|
||||
bs->encrypted = false;
|
||||
bs->valid_key = false;
|
||||
bs->sg = false;
|
||||
QDECREF(bs->options);
|
||||
QDECREF(bs->explicit_options);
|
||||
bs->options = NULL;
|
||||
@@ -2323,116 +2323,6 @@ int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix)
|
||||
return bs->drv->bdrv_check(bs, res, fix);
|
||||
}
|
||||
|
||||
#define COMMIT_BUF_SECTORS 2048
|
||||
|
||||
/* commit COW file into the raw image */
|
||||
int bdrv_commit(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
int64_t sector, total_sectors, length, backing_length;
|
||||
int n, ro, open_flags;
|
||||
int ret = 0;
|
||||
uint8_t *buf = NULL;
|
||||
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
|
||||
if (!bs->backing) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT_SOURCE, NULL) ||
|
||||
bdrv_op_is_blocked(bs->backing->bs, BLOCK_OP_TYPE_COMMIT_TARGET, NULL)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ro = bs->backing->bs->read_only;
|
||||
open_flags = bs->backing->bs->open_flags;
|
||||
|
||||
if (ro) {
|
||||
if (bdrv_reopen(bs->backing->bs, open_flags | BDRV_O_RDWR, NULL)) {
|
||||
return -EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
length = bdrv_getlength(bs);
|
||||
if (length < 0) {
|
||||
ret = length;
|
||||
goto ro_cleanup;
|
||||
}
|
||||
|
||||
backing_length = bdrv_getlength(bs->backing->bs);
|
||||
if (backing_length < 0) {
|
||||
ret = backing_length;
|
||||
goto ro_cleanup;
|
||||
}
|
||||
|
||||
/* If our top snapshot is larger than the backing file image,
|
||||
* grow the backing file image if possible. If not possible,
|
||||
* we must return an error */
|
||||
if (length > backing_length) {
|
||||
ret = bdrv_truncate(bs->backing->bs, length);
|
||||
if (ret < 0) {
|
||||
goto ro_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
total_sectors = length >> BDRV_SECTOR_BITS;
|
||||
|
||||
/* qemu_try_blockalign() for bs will choose an alignment that works for
|
||||
* bs->backing->bs as well, so no need to compare the alignment manually. */
|
||||
buf = qemu_try_blockalign(bs, COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
|
||||
if (buf == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto ro_cleanup;
|
||||
}
|
||||
|
||||
for (sector = 0; sector < total_sectors; sector += n) {
|
||||
ret = bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n);
|
||||
if (ret < 0) {
|
||||
goto ro_cleanup;
|
||||
}
|
||||
if (ret) {
|
||||
ret = bdrv_read(bs, sector, buf, n);
|
||||
if (ret < 0) {
|
||||
goto ro_cleanup;
|
||||
}
|
||||
|
||||
ret = bdrv_write(bs->backing->bs, sector, buf, n);
|
||||
if (ret < 0) {
|
||||
goto ro_cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (drv->bdrv_make_empty) {
|
||||
ret = drv->bdrv_make_empty(bs);
|
||||
if (ret < 0) {
|
||||
goto ro_cleanup;
|
||||
}
|
||||
bdrv_flush(bs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure all data we wrote to the backing device is actually
|
||||
* stable on disk.
|
||||
*/
|
||||
if (bs->backing) {
|
||||
bdrv_flush(bs->backing->bs);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
ro_cleanup:
|
||||
qemu_vfree(buf);
|
||||
|
||||
if (ro) {
|
||||
/* ignoring error return here */
|
||||
bdrv_reopen(bs->backing->bs, open_flags & ~BDRV_O_RDWR, NULL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return values:
|
||||
* 0 - success
|
||||
@@ -2644,30 +2534,30 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
|
||||
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
|
||||
}
|
||||
|
||||
int bdrv_is_read_only(BlockDriverState *bs)
|
||||
bool bdrv_is_read_only(BlockDriverState *bs)
|
||||
{
|
||||
return bs->read_only;
|
||||
}
|
||||
|
||||
int bdrv_is_sg(BlockDriverState *bs)
|
||||
bool bdrv_is_sg(BlockDriverState *bs)
|
||||
{
|
||||
return bs->sg;
|
||||
}
|
||||
|
||||
int bdrv_is_encrypted(BlockDriverState *bs)
|
||||
bool bdrv_is_encrypted(BlockDriverState *bs)
|
||||
{
|
||||
if (bs->backing && bs->backing->bs->encrypted) {
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
return bs->encrypted;
|
||||
}
|
||||
|
||||
int bdrv_key_required(BlockDriverState *bs)
|
||||
bool bdrv_key_required(BlockDriverState *bs)
|
||||
{
|
||||
BdrvChild *backing = bs->backing;
|
||||
|
||||
if (backing && backing->bs->encrypted && !backing->bs->valid_key) {
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
return (bs->encrypted && !bs->valid_key);
|
||||
}
|
||||
@@ -2689,10 +2579,10 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
|
||||
}
|
||||
ret = bs->drv->bdrv_set_key(bs, key);
|
||||
if (ret < 0) {
|
||||
bs->valid_key = 0;
|
||||
bs->valid_key = false;
|
||||
} else if (!bs->valid_key) {
|
||||
/* call the change callback now, we skipped it on open */
|
||||
bs->valid_key = 1;
|
||||
bs->valid_key = true;
|
||||
bdrv_parent_cb_change_media(bs, true);
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -9,7 +9,7 @@ block-obj-y += block-backend.o snapshot.o qapi.o
|
||||
block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
|
||||
block-obj-$(CONFIG_POSIX) += raw-posix.o
|
||||
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
|
||||
block-obj-y += null.o mirror.o io.o
|
||||
block-obj-y += null.o mirror.o commit.o io.o
|
||||
block-obj-y += throttle-groups.o
|
||||
|
||||
block-obj-y += nbd.o nbd-client.o sheepdog.o
|
||||
@@ -26,7 +26,6 @@ block-obj-y += write-threshold.o
|
||||
block-obj-y += crypto.o
|
||||
|
||||
common-obj-y += stream.o
|
||||
common-obj-y += commit.o
|
||||
common-obj-y += backup.o
|
||||
|
||||
iscsi.o-cflags := $(LIBISCSI_CFLAGS)
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
typedef struct BDRVBlkdebugState {
|
||||
int state;
|
||||
int new_state;
|
||||
int align;
|
||||
|
||||
QLIST_HEAD(, BlkdebugRule) rules[BLKDBG__MAX];
|
||||
QSIMPLEQ_HEAD(, BlkdebugRule) active_rules;
|
||||
@@ -382,10 +383,10 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
/* Set request alignment */
|
||||
align = qemu_opt_get_size(opts, "align", bs->request_alignment);
|
||||
if (align > 0 && align < INT_MAX && !(align & (align - 1))) {
|
||||
bs->request_alignment = align;
|
||||
} else {
|
||||
align = qemu_opt_get_size(opts, "align", 0);
|
||||
if (align < INT_MAX && is_power_of_2(align)) {
|
||||
s->align = align;
|
||||
} else if (align) {
|
||||
error_setg(errp, "Invalid alignment");
|
||||
ret = -EINVAL;
|
||||
goto fail_unref;
|
||||
@@ -456,7 +457,7 @@ static BlockAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
|
||||
return inject_error(bs, cb, opaque, rule);
|
||||
}
|
||||
|
||||
return bdrv_aio_readv(bs->file->bs, sector_num, qiov, nb_sectors,
|
||||
return bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors,
|
||||
cb, opaque);
|
||||
}
|
||||
|
||||
@@ -479,7 +480,7 @@ static BlockAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
|
||||
return inject_error(bs, cb, opaque, rule);
|
||||
}
|
||||
|
||||
return bdrv_aio_writev(bs->file->bs, sector_num, qiov, nb_sectors,
|
||||
return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors,
|
||||
cb, opaque);
|
||||
}
|
||||
|
||||
@@ -720,6 +721,15 @@ static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
|
||||
bs->full_open_options = opts;
|
||||
}
|
||||
|
||||
static void blkdebug_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
BDRVBlkdebugState *s = bs->opaque;
|
||||
|
||||
if (s->align) {
|
||||
bs->bl.request_alignment = s->align;
|
||||
}
|
||||
}
|
||||
|
||||
static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
|
||||
BlockReopenQueue *queue, Error **errp)
|
||||
{
|
||||
@@ -738,6 +748,7 @@ static BlockDriver bdrv_blkdebug = {
|
||||
.bdrv_getlength = blkdebug_getlength,
|
||||
.bdrv_truncate = blkdebug_truncate,
|
||||
.bdrv_refresh_filename = blkdebug_refresh_filename,
|
||||
.bdrv_refresh_limits = blkdebug_refresh_limits,
|
||||
|
||||
.bdrv_aio_readv = blkdebug_aio_readv,
|
||||
.bdrv_aio_writev = blkdebug_aio_writev,
|
||||
|
||||
@@ -81,22 +81,22 @@ static void block_request_create(uint64_t reqid, BlockDriverState *bs,
|
||||
replay_block_event(req->bh, reqid);
|
||||
}
|
||||
|
||||
static int coroutine_fn blkreplay_co_readv(BlockDriverState *bs,
|
||||
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
|
||||
static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
|
||||
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags)
|
||||
{
|
||||
uint64_t reqid = request_id++;
|
||||
int ret = bdrv_co_readv(bs->file->bs, sector_num, nb_sectors, qiov);
|
||||
int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
|
||||
block_request_create(reqid, bs, qemu_coroutine_self());
|
||||
qemu_coroutine_yield();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int coroutine_fn blkreplay_co_writev(BlockDriverState *bs,
|
||||
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
|
||||
static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
|
||||
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags)
|
||||
{
|
||||
uint64_t reqid = request_id++;
|
||||
int ret = bdrv_co_writev(bs->file->bs, sector_num, nb_sectors, qiov);
|
||||
int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
|
||||
block_request_create(reqid, bs, qemu_coroutine_self());
|
||||
qemu_coroutine_yield();
|
||||
|
||||
@@ -107,7 +107,7 @@ static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
|
||||
int64_t offset, int count, BdrvRequestFlags flags)
|
||||
{
|
||||
uint64_t reqid = request_id++;
|
||||
int ret = bdrv_co_pwrite_zeroes(bs->file->bs, offset, count, flags);
|
||||
int ret = bdrv_co_pwrite_zeroes(bs->file, offset, count, flags);
|
||||
block_request_create(reqid, bs, qemu_coroutine_self());
|
||||
qemu_coroutine_yield();
|
||||
|
||||
@@ -144,8 +144,8 @@ static BlockDriver bdrv_blkreplay = {
|
||||
.bdrv_close = blkreplay_close,
|
||||
.bdrv_getlength = blkreplay_getlength,
|
||||
|
||||
.bdrv_co_readv = blkreplay_co_readv,
|
||||
.bdrv_co_writev = blkreplay_co_writev,
|
||||
.bdrv_co_preadv = blkreplay_co_preadv,
|
||||
.bdrv_co_pwritev = blkreplay_co_pwritev,
|
||||
|
||||
.bdrv_co_pwrite_zeroes = blkreplay_co_pwrite_zeroes,
|
||||
.bdrv_co_discard = blkreplay_co_discard,
|
||||
|
||||
@@ -247,9 +247,9 @@ static BlockAIOCB *blkverify_aio_readv(BlockDriverState *bs,
|
||||
qemu_iovec_init(&acb->raw_qiov, acb->qiov->niov);
|
||||
qemu_iovec_clone(&acb->raw_qiov, qiov, acb->buf);
|
||||
|
||||
bdrv_aio_readv(s->test_file->bs, sector_num, qiov, nb_sectors,
|
||||
bdrv_aio_readv(s->test_file, sector_num, qiov, nb_sectors,
|
||||
blkverify_aio_cb, acb);
|
||||
bdrv_aio_readv(bs->file->bs, sector_num, &acb->raw_qiov, nb_sectors,
|
||||
bdrv_aio_readv(bs->file, sector_num, &acb->raw_qiov, nb_sectors,
|
||||
blkverify_aio_cb, acb);
|
||||
return &acb->common;
|
||||
}
|
||||
@@ -262,9 +262,9 @@ static BlockAIOCB *blkverify_aio_writev(BlockDriverState *bs,
|
||||
BlkverifyAIOCB *acb = blkverify_aio_get(bs, true, sector_num, qiov,
|
||||
nb_sectors, cb, opaque);
|
||||
|
||||
bdrv_aio_writev(s->test_file->bs, sector_num, qiov, nb_sectors,
|
||||
bdrv_aio_writev(s->test_file, sector_num, qiov, nb_sectors,
|
||||
blkverify_aio_cb, acb);
|
||||
bdrv_aio_writev(bs->file->bs, sector_num, qiov, nb_sectors,
|
||||
bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors,
|
||||
blkverify_aio_cb, acb);
|
||||
return &acb->common;
|
||||
}
|
||||
|
||||
@@ -760,7 +760,7 @@ int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
|
||||
throttle_group_co_io_limits_intercept(blk, bytes, false);
|
||||
}
|
||||
|
||||
return bdrv_co_preadv(blk_bs(blk), offset, bytes, qiov, flags);
|
||||
return bdrv_co_preadv(blk->root, offset, bytes, qiov, flags);
|
||||
}
|
||||
|
||||
int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
|
||||
@@ -785,7 +785,7 @@ int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
|
||||
flags |= BDRV_REQ_FUA;
|
||||
}
|
||||
|
||||
return bdrv_co_pwritev(blk_bs(blk), offset, bytes, qiov, flags);
|
||||
return bdrv_co_pwritev(blk->root, offset, bytes, qiov, flags);
|
||||
}
|
||||
|
||||
typedef struct BlkRwCo {
|
||||
@@ -870,6 +870,11 @@ int blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
|
||||
flags | BDRV_REQ_ZERO_WRITE);
|
||||
}
|
||||
|
||||
int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
|
||||
{
|
||||
return bdrv_make_zero(blk->root, flags);
|
||||
}
|
||||
|
||||
static void error_callback_bh(void *opaque)
|
||||
{
|
||||
struct BlockBackendAIOCB *acb = opaque;
|
||||
@@ -1303,15 +1308,16 @@ int blk_get_flags(BlockBackend *blk)
|
||||
}
|
||||
}
|
||||
|
||||
int blk_get_max_transfer_length(BlockBackend *blk)
|
||||
/* Returns the maximum transfer length, in bytes; guaranteed nonzero */
|
||||
uint32_t blk_get_max_transfer(BlockBackend *blk)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
uint32_t max = 0;
|
||||
|
||||
if (bs) {
|
||||
return bs->bl.max_transfer_length;
|
||||
} else {
|
||||
return 0;
|
||||
max = bs->bl.max_transfer;
|
||||
}
|
||||
return MIN_NON_ZERO(max, INT_MAX);
|
||||
}
|
||||
|
||||
int blk_get_max_iov(BlockBackend *blk)
|
||||
|
||||
@@ -104,10 +104,9 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
struct bochs_header bochs;
|
||||
int ret;
|
||||
|
||||
bs->read_only = 1; // no write support yet
|
||||
bs->request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O supported */
|
||||
bs->read_only = true; /* no write support yet */
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, 0, &bochs, sizeof(bochs));
|
||||
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -141,7 +140,7 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, le32_to_cpu(bochs.header), s->catalog_bitmap,
|
||||
ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
|
||||
s->catalog_size * 4);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -189,6 +188,11 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bochs_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
|
||||
}
|
||||
|
||||
static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
|
||||
{
|
||||
BDRVBochsState *s = bs->opaque;
|
||||
@@ -210,7 +214,7 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
|
||||
(s->extent_blocks + s->bitmap_blocks));
|
||||
|
||||
/* read in bitmap for current extent */
|
||||
ret = bdrv_pread(bs->file->bs, bitmap_offset + (extent_offset / 8),
|
||||
ret = bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
|
||||
&bitmap_entry, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -251,7 +255,7 @@ bochs_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
qemu_iovec_concat(&local_qiov, qiov, bytes_done, 512);
|
||||
|
||||
if (block_offset > 0) {
|
||||
ret = bdrv_co_preadv(bs->file->bs, block_offset, 512,
|
||||
ret = bdrv_co_preadv(bs->file, block_offset, 512,
|
||||
&local_qiov, 0);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -283,6 +287,7 @@ static BlockDriver bdrv_bochs = {
|
||||
.instance_size = sizeof(BDRVBochsState),
|
||||
.bdrv_probe = bochs_probe,
|
||||
.bdrv_open = bochs_open,
|
||||
.bdrv_refresh_limits = bochs_refresh_limits,
|
||||
.bdrv_co_preadv = bochs_co_preadv,
|
||||
.bdrv_close = bochs_close,
|
||||
};
|
||||
|
||||
@@ -66,11 +66,10 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
uint32_t offsets_size, max_compressed_block_size = 1, i;
|
||||
int ret;
|
||||
|
||||
bs->read_only = 1;
|
||||
bs->request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O supported */
|
||||
bs->read_only = true;
|
||||
|
||||
/* read header */
|
||||
ret = bdrv_pread(bs->file->bs, 128, &s->block_size, 4);
|
||||
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -96,7 +95,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, 128 + 4, &s->n_blocks, 4);
|
||||
ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -127,7 +126,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, 128 + 4 + 4, s->offsets, offsets_size);
|
||||
ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -199,6 +198,11 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cloop_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
|
||||
}
|
||||
|
||||
static inline int cloop_read_block(BlockDriverState *bs, int block_num)
|
||||
{
|
||||
BDRVCloopState *s = bs->opaque;
|
||||
@@ -207,7 +211,7 @@ static inline int cloop_read_block(BlockDriverState *bs, int block_num)
|
||||
int ret;
|
||||
uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, s->offsets[block_num],
|
||||
ret = bdrv_pread(bs->file, s->offsets[block_num],
|
||||
s->compressed_block, bytes);
|
||||
if (ret != bytes) {
|
||||
return -1;
|
||||
@@ -280,6 +284,7 @@ static BlockDriver bdrv_cloop = {
|
||||
.instance_size = sizeof(BDRVCloopState),
|
||||
.bdrv_probe = cloop_probe,
|
||||
.bdrv_open = cloop_open,
|
||||
.bdrv_refresh_limits = cloop_refresh_limits,
|
||||
.bdrv_co_preadv = cloop_co_preadv,
|
||||
.bdrv_close = cloop_close,
|
||||
};
|
||||
|
||||
121
block/commit.c
121
block/commit.c
@@ -282,3 +282,124 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
|
||||
trace_commit_start(bs, base, top, s, s->common.co, opaque);
|
||||
qemu_coroutine_enter(s->common.co, s);
|
||||
}
|
||||
|
||||
|
||||
#define COMMIT_BUF_SECTORS 2048
|
||||
|
||||
/* commit COW file into the raw image */
|
||||
int bdrv_commit(BlockDriverState *bs)
|
||||
{
|
||||
BlockBackend *src, *backing;
|
||||
BlockDriver *drv = bs->drv;
|
||||
int64_t sector, total_sectors, length, backing_length;
|
||||
int n, ro, open_flags;
|
||||
int ret = 0;
|
||||
uint8_t *buf = NULL;
|
||||
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
|
||||
if (!bs->backing) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT_SOURCE, NULL) ||
|
||||
bdrv_op_is_blocked(bs->backing->bs, BLOCK_OP_TYPE_COMMIT_TARGET, NULL)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ro = bs->backing->bs->read_only;
|
||||
open_flags = bs->backing->bs->open_flags;
|
||||
|
||||
if (ro) {
|
||||
if (bdrv_reopen(bs->backing->bs, open_flags | BDRV_O_RDWR, NULL)) {
|
||||
return -EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
src = blk_new();
|
||||
blk_insert_bs(src, bs);
|
||||
|
||||
backing = blk_new();
|
||||
blk_insert_bs(backing, bs->backing->bs);
|
||||
|
||||
length = blk_getlength(src);
|
||||
if (length < 0) {
|
||||
ret = length;
|
||||
goto ro_cleanup;
|
||||
}
|
||||
|
||||
backing_length = blk_getlength(backing);
|
||||
if (backing_length < 0) {
|
||||
ret = backing_length;
|
||||
goto ro_cleanup;
|
||||
}
|
||||
|
||||
/* If our top snapshot is larger than the backing file image,
|
||||
* grow the backing file image if possible. If not possible,
|
||||
* we must return an error */
|
||||
if (length > backing_length) {
|
||||
ret = blk_truncate(backing, length);
|
||||
if (ret < 0) {
|
||||
goto ro_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
total_sectors = length >> BDRV_SECTOR_BITS;
|
||||
|
||||
/* blk_try_blockalign() for src will choose an alignment that works for
|
||||
* backing as well, so no need to compare the alignment manually. */
|
||||
buf = blk_try_blockalign(src, COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
|
||||
if (buf == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto ro_cleanup;
|
||||
}
|
||||
|
||||
for (sector = 0; sector < total_sectors; sector += n) {
|
||||
ret = bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n);
|
||||
if (ret < 0) {
|
||||
goto ro_cleanup;
|
||||
}
|
||||
if (ret) {
|
||||
ret = blk_pread(src, sector * BDRV_SECTOR_SIZE, buf,
|
||||
n * BDRV_SECTOR_SIZE);
|
||||
if (ret < 0) {
|
||||
goto ro_cleanup;
|
||||
}
|
||||
|
||||
ret = blk_pwrite(backing, sector * BDRV_SECTOR_SIZE, buf,
|
||||
n * BDRV_SECTOR_SIZE, 0);
|
||||
if (ret < 0) {
|
||||
goto ro_cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (drv->bdrv_make_empty) {
|
||||
ret = drv->bdrv_make_empty(bs);
|
||||
if (ret < 0) {
|
||||
goto ro_cleanup;
|
||||
}
|
||||
blk_flush(src);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure all data we wrote to the backing device is actually
|
||||
* stable on disk.
|
||||
*/
|
||||
blk_flush(backing);
|
||||
|
||||
ret = 0;
|
||||
ro_cleanup:
|
||||
qemu_vfree(buf);
|
||||
|
||||
blk_unref(src);
|
||||
blk_unref(backing);
|
||||
|
||||
if (ro) {
|
||||
/* ignoring error return here */
|
||||
bdrv_reopen(bs->backing->bs, open_flags & ~BDRV_O_RDWR, NULL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ static ssize_t block_crypto_read_func(QCryptoBlock *block,
|
||||
BlockDriverState *bs = opaque;
|
||||
ssize_t ret;
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, offset, buf, buflen);
|
||||
ret = bdrv_pread(bs->file, offset, buf, buflen);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not read encryption header");
|
||||
return ret;
|
||||
@@ -193,17 +193,16 @@ block_crypto_open_opts_init(QCryptoBlockFormat format,
|
||||
QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
OptsVisitor *ov;
|
||||
Visitor *v;
|
||||
QCryptoBlockOpenOptions *ret = NULL;
|
||||
Error *local_err = NULL;
|
||||
|
||||
ret = g_new0(QCryptoBlockOpenOptions, 1);
|
||||
ret->format = format;
|
||||
|
||||
ov = opts_visitor_new(opts);
|
||||
v = opts_visitor_new(opts);
|
||||
|
||||
visit_start_struct(opts_get_visitor(ov),
|
||||
NULL, NULL, 0, &local_err);
|
||||
visit_start_struct(v, NULL, NULL, 0, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
@@ -211,7 +210,7 @@ block_crypto_open_opts_init(QCryptoBlockFormat format,
|
||||
switch (format) {
|
||||
case Q_CRYPTO_BLOCK_FORMAT_LUKS:
|
||||
visit_type_QCryptoBlockOptionsLUKS_members(
|
||||
opts_get_visitor(ov), &ret->u.luks, &local_err);
|
||||
v, &ret->u.luks, &local_err);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -219,10 +218,10 @@ block_crypto_open_opts_init(QCryptoBlockFormat format,
|
||||
break;
|
||||
}
|
||||
if (!local_err) {
|
||||
visit_check_struct(opts_get_visitor(ov), &local_err);
|
||||
visit_check_struct(v, &local_err);
|
||||
}
|
||||
|
||||
visit_end_struct(opts_get_visitor(ov));
|
||||
visit_end_struct(v, NULL);
|
||||
|
||||
out:
|
||||
if (local_err) {
|
||||
@@ -230,7 +229,7 @@ block_crypto_open_opts_init(QCryptoBlockFormat format,
|
||||
qapi_free_QCryptoBlockOpenOptions(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
opts_visitor_cleanup(ov);
|
||||
visit_free(v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -240,17 +239,16 @@ block_crypto_create_opts_init(QCryptoBlockFormat format,
|
||||
QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
OptsVisitor *ov;
|
||||
Visitor *v;
|
||||
QCryptoBlockCreateOptions *ret = NULL;
|
||||
Error *local_err = NULL;
|
||||
|
||||
ret = g_new0(QCryptoBlockCreateOptions, 1);
|
||||
ret->format = format;
|
||||
|
||||
ov = opts_visitor_new(opts);
|
||||
v = opts_visitor_new(opts);
|
||||
|
||||
visit_start_struct(opts_get_visitor(ov),
|
||||
NULL, NULL, 0, &local_err);
|
||||
visit_start_struct(v, NULL, NULL, 0, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
@@ -258,7 +256,7 @@ block_crypto_create_opts_init(QCryptoBlockFormat format,
|
||||
switch (format) {
|
||||
case Q_CRYPTO_BLOCK_FORMAT_LUKS:
|
||||
visit_type_QCryptoBlockCreateOptionsLUKS_members(
|
||||
opts_get_visitor(ov), &ret->u.luks, &local_err);
|
||||
v, &ret->u.luks, &local_err);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -266,10 +264,10 @@ block_crypto_create_opts_init(QCryptoBlockFormat format,
|
||||
break;
|
||||
}
|
||||
if (!local_err) {
|
||||
visit_check_struct(opts_get_visitor(ov), &local_err);
|
||||
visit_check_struct(v, &local_err);
|
||||
}
|
||||
|
||||
visit_end_struct(opts_get_visitor(ov));
|
||||
visit_end_struct(v, NULL);
|
||||
|
||||
out:
|
||||
if (local_err) {
|
||||
@@ -277,7 +275,7 @@ block_crypto_create_opts_init(QCryptoBlockFormat format,
|
||||
qapi_free_QCryptoBlockCreateOptions(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
opts_visitor_cleanup(ov);
|
||||
visit_free(v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -322,8 +320,8 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
bs->encrypted = 1;
|
||||
bs->valid_key = 1;
|
||||
bs->encrypted = true;
|
||||
bs->valid_key = true;
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
@@ -428,7 +426,7 @@ block_crypto_co_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
qemu_iovec_reset(&hd_qiov);
|
||||
qemu_iovec_add(&hd_qiov, cipher_data, cur_nr_sectors * 512);
|
||||
|
||||
ret = bdrv_co_readv(bs->file->bs,
|
||||
ret = bdrv_co_readv(bs->file,
|
||||
payload_offset + sector_num,
|
||||
cur_nr_sectors, &hd_qiov);
|
||||
if (ret < 0) {
|
||||
@@ -507,7 +505,7 @@ block_crypto_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
qemu_iovec_reset(&hd_qiov);
|
||||
qemu_iovec_add(&hd_qiov, cipher_data, cur_nr_sectors * 512);
|
||||
|
||||
ret = bdrv_co_writev(bs->file->bs,
|
||||
ret = bdrv_co_writev(bs->file,
|
||||
payload_offset + sector_num,
|
||||
cur_nr_sectors, &hd_qiov);
|
||||
if (ret < 0) {
|
||||
|
||||
30
block/dmg.c
30
block/dmg.c
@@ -86,7 +86,7 @@ static int read_uint64(BlockDriverState *bs, int64_t offset, uint64_t *result)
|
||||
uint64_t buffer;
|
||||
int ret;
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, offset, &buffer, 8);
|
||||
ret = bdrv_pread(bs->file, offset, &buffer, 8);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result)
|
||||
uint32_t buffer;
|
||||
int ret;
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, offset, &buffer, 4);
|
||||
ret = bdrv_pread(bs->file, offset, &buffer, 4);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -153,8 +153,9 @@ static void update_max_chunk_size(BDRVDMGState *s, uint32_t chunk,
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t dmg_find_koly_offset(BlockDriverState *file_bs, Error **errp)
|
||||
static int64_t dmg_find_koly_offset(BdrvChild *file, Error **errp)
|
||||
{
|
||||
BlockDriverState *file_bs = file->bs;
|
||||
int64_t length;
|
||||
int64_t offset = 0;
|
||||
uint8_t buffer[515];
|
||||
@@ -178,7 +179,7 @@ static int64_t dmg_find_koly_offset(BlockDriverState *file_bs, Error **errp)
|
||||
offset = length - 511 - 512;
|
||||
}
|
||||
length = length < 515 ? length : 515;
|
||||
ret = bdrv_pread(file_bs, offset, buffer, length);
|
||||
ret = bdrv_pread(file, offset, buffer, length);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed while reading UDIF trailer");
|
||||
return ret;
|
||||
@@ -355,7 +356,7 @@ static int dmg_read_resource_fork(BlockDriverState *bs, DmgHeaderState *ds,
|
||||
offset += 4;
|
||||
|
||||
buffer = g_realloc(buffer, count);
|
||||
ret = bdrv_pread(bs->file->bs, offset, buffer, count);
|
||||
ret = bdrv_pread(bs->file, offset, buffer, count);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -392,7 +393,7 @@ static int dmg_read_plist_xml(BlockDriverState *bs, DmgHeaderState *ds,
|
||||
|
||||
buffer = g_malloc(info_length + 1);
|
||||
buffer[info_length] = '\0';
|
||||
ret = bdrv_pread(bs->file->bs, info_begin, buffer, info_length);
|
||||
ret = bdrv_pread(bs->file, info_begin, buffer, info_length);
|
||||
if (ret != info_length) {
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
@@ -438,8 +439,7 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
int64_t offset;
|
||||
int ret;
|
||||
|
||||
bs->read_only = 1;
|
||||
bs->request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O supported */
|
||||
bs->read_only = true;
|
||||
|
||||
s->n_chunks = 0;
|
||||
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
|
||||
@@ -449,7 +449,7 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
ds.max_sectors_per_chunk = 1;
|
||||
|
||||
/* locate the UDIF trailer */
|
||||
offset = dmg_find_koly_offset(bs->file->bs, errp);
|
||||
offset = dmg_find_koly_offset(bs->file, errp);
|
||||
if (offset < 0) {
|
||||
ret = offset;
|
||||
goto fail;
|
||||
@@ -547,6 +547,11 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dmg_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
|
||||
}
|
||||
|
||||
static inline int is_sector_in_chunk(BDRVDMGState* s,
|
||||
uint32_t chunk_num, uint64_t sector_num)
|
||||
{
|
||||
@@ -595,7 +600,7 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
|
||||
case 0x80000005: { /* zlib compressed */
|
||||
/* we need to buffer, because only the chunk as whole can be
|
||||
* inflated. */
|
||||
ret = bdrv_pread(bs->file->bs, s->offsets[chunk],
|
||||
ret = bdrv_pread(bs->file, s->offsets[chunk],
|
||||
s->compressed_chunk, s->lengths[chunk]);
|
||||
if (ret != s->lengths[chunk]) {
|
||||
return -1;
|
||||
@@ -619,7 +624,7 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
|
||||
case 0x80000006: /* bzip2 compressed */
|
||||
/* we need to buffer, because only the chunk as whole can be
|
||||
* inflated. */
|
||||
ret = bdrv_pread(bs->file->bs, s->offsets[chunk],
|
||||
ret = bdrv_pread(bs->file, s->offsets[chunk],
|
||||
s->compressed_chunk, s->lengths[chunk]);
|
||||
if (ret != s->lengths[chunk]) {
|
||||
return -1;
|
||||
@@ -644,7 +649,7 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
|
||||
break;
|
||||
#endif /* CONFIG_BZIP2 */
|
||||
case 1: /* copy */
|
||||
ret = bdrv_pread(bs->file->bs, s->offsets[chunk],
|
||||
ret = bdrv_pread(bs->file, s->offsets[chunk],
|
||||
s->uncompressed_chunk, s->lengths[chunk]);
|
||||
if (ret != s->lengths[chunk]) {
|
||||
return -1;
|
||||
@@ -720,6 +725,7 @@ static BlockDriver bdrv_dmg = {
|
||||
.instance_size = sizeof(BDRVDMGState),
|
||||
.bdrv_probe = dmg_probe,
|
||||
.bdrv_open = dmg_open,
|
||||
.bdrv_refresh_limits = dmg_refresh_limits,
|
||||
.bdrv_co_preadv = dmg_co_preadv,
|
||||
.bdrv_close = dmg_close,
|
||||
};
|
||||
|
||||
238
block/io.c
238
block/io.c
@@ -33,7 +33,7 @@
|
||||
|
||||
#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
|
||||
|
||||
static BlockAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
|
||||
static BlockAIOCB *bdrv_co_aio_rw_vector(BdrvChild *child,
|
||||
int64_t sector_num,
|
||||
QEMUIOVector *qiov,
|
||||
int nb_sectors,
|
||||
@@ -67,6 +67,17 @@ static void bdrv_parent_drained_end(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
|
||||
static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src)
|
||||
{
|
||||
dst->opt_transfer = MAX(dst->opt_transfer, src->opt_transfer);
|
||||
dst->max_transfer = MIN_NON_ZERO(dst->max_transfer, src->max_transfer);
|
||||
dst->opt_mem_alignment = MAX(dst->opt_mem_alignment,
|
||||
src->opt_mem_alignment);
|
||||
dst->min_mem_alignment = MAX(dst->min_mem_alignment,
|
||||
src->min_mem_alignment);
|
||||
dst->max_iov = MIN_NON_ZERO(dst->max_iov, src->max_iov);
|
||||
}
|
||||
|
||||
void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
@@ -78,6 +89,9 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Default alignment based on whether driver has byte interface */
|
||||
bs->bl.request_alignment = drv->bdrv_co_preadv ? 1 : 512;
|
||||
|
||||
/* Take some limits from the children as a default */
|
||||
if (bs->file) {
|
||||
bdrv_refresh_limits(bs->file->bs, &local_err);
|
||||
@@ -85,11 +99,7 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
bs->bl.opt_transfer_length = bs->file->bs->bl.opt_transfer_length;
|
||||
bs->bl.max_transfer_length = bs->file->bs->bl.max_transfer_length;
|
||||
bs->bl.min_mem_alignment = bs->file->bs->bl.min_mem_alignment;
|
||||
bs->bl.opt_mem_alignment = bs->file->bs->bl.opt_mem_alignment;
|
||||
bs->bl.max_iov = bs->file->bs->bl.max_iov;
|
||||
bdrv_merge_limits(&bs->bl, &bs->file->bs->bl);
|
||||
} else {
|
||||
bs->bl.min_mem_alignment = 512;
|
||||
bs->bl.opt_mem_alignment = getpagesize();
|
||||
@@ -104,21 +114,7 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
bs->bl.opt_transfer_length =
|
||||
MAX(bs->bl.opt_transfer_length,
|
||||
bs->backing->bs->bl.opt_transfer_length);
|
||||
bs->bl.max_transfer_length =
|
||||
MIN_NON_ZERO(bs->bl.max_transfer_length,
|
||||
bs->backing->bs->bl.max_transfer_length);
|
||||
bs->bl.opt_mem_alignment =
|
||||
MAX(bs->bl.opt_mem_alignment,
|
||||
bs->backing->bs->bl.opt_mem_alignment);
|
||||
bs->bl.min_mem_alignment =
|
||||
MAX(bs->bl.min_mem_alignment,
|
||||
bs->backing->bs->bl.min_mem_alignment);
|
||||
bs->bl.max_iov =
|
||||
MIN(bs->bl.max_iov,
|
||||
bs->backing->bs->bl.max_iov);
|
||||
bdrv_merge_limits(&bs->bl, &bs->backing->bs->bl);
|
||||
}
|
||||
|
||||
/* Then let the driver override it */
|
||||
@@ -463,7 +459,7 @@ static int bdrv_get_cluster_size(BlockDriverState *bs)
|
||||
|
||||
ret = bdrv_get_info(bs, &bdi);
|
||||
if (ret < 0 || bdi.cluster_size == 0) {
|
||||
return bs->request_alignment;
|
||||
return bs->bl.request_alignment;
|
||||
} else {
|
||||
return bdi.cluster_size;
|
||||
}
|
||||
@@ -557,7 +553,7 @@ static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
|
||||
}
|
||||
|
||||
typedef struct RwCo {
|
||||
BlockDriverState *bs;
|
||||
BdrvChild *child;
|
||||
int64_t offset;
|
||||
QEMUIOVector *qiov;
|
||||
bool is_write;
|
||||
@@ -570,11 +566,11 @@ static void coroutine_fn bdrv_rw_co_entry(void *opaque)
|
||||
RwCo *rwco = opaque;
|
||||
|
||||
if (!rwco->is_write) {
|
||||
rwco->ret = bdrv_co_preadv(rwco->bs, rwco->offset,
|
||||
rwco->ret = bdrv_co_preadv(rwco->child, rwco->offset,
|
||||
rwco->qiov->size, rwco->qiov,
|
||||
rwco->flags);
|
||||
} else {
|
||||
rwco->ret = bdrv_co_pwritev(rwco->bs, rwco->offset,
|
||||
rwco->ret = bdrv_co_pwritev(rwco->child, rwco->offset,
|
||||
rwco->qiov->size, rwco->qiov,
|
||||
rwco->flags);
|
||||
}
|
||||
@@ -583,13 +579,13 @@ static void coroutine_fn bdrv_rw_co_entry(void *opaque)
|
||||
/*
|
||||
* Process a vectored synchronous request using coroutines
|
||||
*/
|
||||
static int bdrv_prwv_co(BlockDriverState *bs, int64_t offset,
|
||||
static int bdrv_prwv_co(BdrvChild *child, int64_t offset,
|
||||
QEMUIOVector *qiov, bool is_write,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
Coroutine *co;
|
||||
RwCo rwco = {
|
||||
.bs = bs,
|
||||
.child = child,
|
||||
.offset = offset,
|
||||
.qiov = qiov,
|
||||
.is_write = is_write,
|
||||
@@ -601,7 +597,7 @@ static int bdrv_prwv_co(BlockDriverState *bs, int64_t offset,
|
||||
/* Fast-path if already in coroutine context */
|
||||
bdrv_rw_co_entry(&rwco);
|
||||
} else {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
AioContext *aio_context = bdrv_get_aio_context(child->bs);
|
||||
|
||||
co = qemu_coroutine_create(bdrv_rw_co_entry);
|
||||
qemu_coroutine_enter(co, &rwco);
|
||||
@@ -615,7 +611,7 @@ static int bdrv_prwv_co(BlockDriverState *bs, int64_t offset,
|
||||
/*
|
||||
* Process a synchronous request using coroutines
|
||||
*/
|
||||
static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
|
||||
static int bdrv_rw_co(BdrvChild *child, int64_t sector_num, uint8_t *buf,
|
||||
int nb_sectors, bool is_write, BdrvRequestFlags flags)
|
||||
{
|
||||
QEMUIOVector qiov;
|
||||
@@ -629,15 +625,15 @@ static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
|
||||
}
|
||||
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
return bdrv_prwv_co(bs, sector_num << BDRV_SECTOR_BITS,
|
||||
return bdrv_prwv_co(child, sector_num << BDRV_SECTOR_BITS,
|
||||
&qiov, is_write, flags);
|
||||
}
|
||||
|
||||
/* return < 0 if error. See bdrv_write() for the return codes */
|
||||
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
|
||||
int bdrv_read(BdrvChild *child, int64_t sector_num,
|
||||
uint8_t *buf, int nb_sectors)
|
||||
{
|
||||
return bdrv_rw_co(bs, sector_num, buf, nb_sectors, false, 0);
|
||||
return bdrv_rw_co(child, sector_num, buf, nb_sectors, false, 0);
|
||||
}
|
||||
|
||||
/* Return < 0 if error. Important errors are:
|
||||
@@ -646,13 +642,13 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num,
|
||||
-EINVAL Invalid sector number or nb_sectors
|
||||
-EACCES Trying to write a read-only device
|
||||
*/
|
||||
int bdrv_write(BlockDriverState *bs, int64_t sector_num,
|
||||
int bdrv_write(BdrvChild *child, int64_t sector_num,
|
||||
const uint8_t *buf, int nb_sectors)
|
||||
{
|
||||
return bdrv_rw_co(bs, sector_num, (uint8_t *)buf, nb_sectors, true, 0);
|
||||
return bdrv_rw_co(child, sector_num, (uint8_t *)buf, nb_sectors, true, 0);
|
||||
}
|
||||
|
||||
int bdrv_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
|
||||
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
||||
int count, BdrvRequestFlags flags)
|
||||
{
|
||||
QEMUIOVector qiov;
|
||||
@@ -662,7 +658,7 @@ int bdrv_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
|
||||
};
|
||||
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
return bdrv_prwv_co(bs, offset, &qiov, true,
|
||||
return bdrv_prwv_co(child, offset, &qiov, true,
|
||||
BDRV_REQ_ZERO_WRITE | flags);
|
||||
}
|
||||
|
||||
@@ -675,9 +671,10 @@ int bdrv_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
|
||||
*
|
||||
* Returns < 0 on error, 0 on success. For error codes see bdrv_write().
|
||||
*/
|
||||
int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
|
||||
int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
|
||||
{
|
||||
int64_t target_sectors, ret, nb_sectors, sector_num = 0;
|
||||
BlockDriverState *bs = child->bs;
|
||||
BlockDriverState *file;
|
||||
int n;
|
||||
|
||||
@@ -701,7 +698,7 @@ int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
|
||||
sector_num += n;
|
||||
continue;
|
||||
}
|
||||
ret = bdrv_pwrite_zeroes(bs, sector_num << BDRV_SECTOR_BITS,
|
||||
ret = bdrv_pwrite_zeroes(child, sector_num << BDRV_SECTOR_BITS,
|
||||
n << BDRV_SECTOR_BITS, flags);
|
||||
if (ret < 0) {
|
||||
error_report("error writing zeroes at sector %" PRId64 ": %s",
|
||||
@@ -712,11 +709,11 @@ int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
|
||||
}
|
||||
}
|
||||
|
||||
int bdrv_preadv(BlockDriverState *bs, int64_t offset, QEMUIOVector *qiov)
|
||||
int bdrv_preadv(BdrvChild *child, int64_t offset, QEMUIOVector *qiov)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bdrv_prwv_co(bs, offset, qiov, false, 0);
|
||||
ret = bdrv_prwv_co(child, offset, qiov, false, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -724,7 +721,7 @@ int bdrv_preadv(BlockDriverState *bs, int64_t offset, QEMUIOVector *qiov)
|
||||
return qiov->size;
|
||||
}
|
||||
|
||||
int bdrv_pread(BlockDriverState *bs, int64_t offset, void *buf, int bytes)
|
||||
int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int bytes)
|
||||
{
|
||||
QEMUIOVector qiov;
|
||||
struct iovec iov = {
|
||||
@@ -737,14 +734,14 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset, void *buf, int bytes)
|
||||
}
|
||||
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
return bdrv_preadv(bs, offset, &qiov);
|
||||
return bdrv_preadv(child, offset, &qiov);
|
||||
}
|
||||
|
||||
int bdrv_pwritev(BlockDriverState *bs, int64_t offset, QEMUIOVector *qiov)
|
||||
int bdrv_pwritev(BdrvChild *child, int64_t offset, QEMUIOVector *qiov)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bdrv_prwv_co(bs, offset, qiov, true, 0);
|
||||
ret = bdrv_prwv_co(child, offset, qiov, true, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -752,8 +749,7 @@ int bdrv_pwritev(BlockDriverState *bs, int64_t offset, QEMUIOVector *qiov)
|
||||
return qiov->size;
|
||||
}
|
||||
|
||||
int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
|
||||
const void *buf, int bytes)
|
||||
int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf, int bytes)
|
||||
{
|
||||
QEMUIOVector qiov;
|
||||
struct iovec iov = {
|
||||
@@ -766,7 +762,7 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
|
||||
}
|
||||
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
return bdrv_pwritev(bs, offset, &qiov);
|
||||
return bdrv_pwritev(child, offset, &qiov);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -775,17 +771,17 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
|
||||
*
|
||||
* Returns 0 on success, -errno in error cases.
|
||||
*/
|
||||
int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset,
|
||||
const void *buf, int count)
|
||||
int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
|
||||
const void *buf, int count)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bdrv_pwrite(bs, offset, buf, count);
|
||||
ret = bdrv_pwrite(child, offset, buf, count);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = bdrv_flush(bs);
|
||||
ret = bdrv_flush(child->bs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -945,6 +941,9 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs,
|
||||
|
||||
if (drv->bdrv_co_pwrite_zeroes &&
|
||||
buffer_is_zero(bounce_buffer, iov.iov_len)) {
|
||||
/* FIXME: Should we (perhaps conditionally) be setting
|
||||
* BDRV_REQ_MAY_UNMAP, if it will allow for a sparser copy
|
||||
* that still correctly reads as zero? */
|
||||
ret = bdrv_co_do_pwrite_zeroes(bs, cluster_offset, cluster_bytes, 0);
|
||||
} else {
|
||||
/* This does not change the data on the disk, it is not necessary
|
||||
@@ -987,7 +986,12 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs,
|
||||
assert((bytes & (align - 1)) == 0);
|
||||
assert(!qiov || bytes == qiov->size);
|
||||
assert((bs->open_flags & BDRV_O_NO_IO) == 0);
|
||||
assert(!(flags & ~BDRV_REQ_MASK));
|
||||
|
||||
/* TODO: We would need a per-BDS .supported_read_flags and
|
||||
* potential fallback support, if we ever implement any read flags
|
||||
* to pass through to drivers. For now, there aren't any
|
||||
* passthrough flags. */
|
||||
assert(!(flags & ~(BDRV_REQ_NO_SERIALISING | BDRV_REQ_COPY_ON_READ)));
|
||||
|
||||
/* Handle Copy on Read and associated serialisation */
|
||||
if (flags & BDRV_REQ_COPY_ON_READ) {
|
||||
@@ -1028,7 +1032,7 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
max_bytes = ROUND_UP(MAX(0, total_bytes - offset), align);
|
||||
if (bytes < max_bytes) {
|
||||
if (bytes <= max_bytes) {
|
||||
ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0);
|
||||
} else if (max_bytes > 0) {
|
||||
QEMUIOVector local_qiov;
|
||||
@@ -1057,14 +1061,15 @@ out:
|
||||
/*
|
||||
* Handle a read request in coroutine context
|
||||
*/
|
||||
int coroutine_fn bdrv_co_preadv(BlockDriverState *bs,
|
||||
int coroutine_fn bdrv_co_preadv(BdrvChild *child,
|
||||
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
BlockDriverState *bs = child->bs;
|
||||
BlockDriver *drv = bs->drv;
|
||||
BdrvTrackedRequest req;
|
||||
|
||||
uint64_t align = bs->request_alignment;
|
||||
uint64_t align = bs->bl.request_alignment;
|
||||
uint8_t *head_buf = NULL;
|
||||
uint8_t *tail_buf = NULL;
|
||||
QEMUIOVector local_qiov;
|
||||
@@ -1125,7 +1130,7 @@ int coroutine_fn bdrv_co_preadv(BlockDriverState *bs,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs,
|
||||
static int coroutine_fn bdrv_co_do_readv(BdrvChild *child,
|
||||
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
@@ -1133,19 +1138,20 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return bdrv_co_preadv(bs, sector_num << BDRV_SECTOR_BITS,
|
||||
return bdrv_co_preadv(child, sector_num << BDRV_SECTOR_BITS,
|
||||
nb_sectors << BDRV_SECTOR_BITS, qiov, flags);
|
||||
}
|
||||
|
||||
int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
int nb_sectors, QEMUIOVector *qiov)
|
||||
int coroutine_fn bdrv_co_readv(BdrvChild *child, int64_t sector_num,
|
||||
int nb_sectors, QEMUIOVector *qiov)
|
||||
{
|
||||
trace_bdrv_co_readv(bs, sector_num, nb_sectors);
|
||||
trace_bdrv_co_readv(child->bs, sector_num, nb_sectors);
|
||||
|
||||
return bdrv_co_do_readv(bs, sector_num, nb_sectors, qiov, 0);
|
||||
return bdrv_co_do_readv(child, sector_num, nb_sectors, qiov, 0);
|
||||
}
|
||||
|
||||
#define MAX_WRITE_ZEROES_BOUNCE_BUFFER 32768
|
||||
/* Maximum buffer for write zeroes fallback, in bytes */
|
||||
#define MAX_WRITE_ZEROES_BOUNCE_BUFFER (32768 << BDRV_SECTOR_BITS)
|
||||
|
||||
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||
int64_t offset, int count, BdrvRequestFlags flags)
|
||||
@@ -1159,8 +1165,8 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||
int tail = 0;
|
||||
|
||||
int max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes, INT_MAX);
|
||||
int alignment = MAX(bs->bl.pwrite_zeroes_alignment ?: 1,
|
||||
bs->request_alignment);
|
||||
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
|
||||
bs->bl.request_alignment);
|
||||
|
||||
assert(is_power_of_2(alignment));
|
||||
head = offset & (alignment - 1);
|
||||
@@ -1203,7 +1209,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||
|
||||
if (ret == -ENOTSUP) {
|
||||
/* Fall back to bounce buffer if write zeroes is unsupported */
|
||||
int max_xfer_len = MIN_NON_ZERO(bs->bl.max_transfer_length,
|
||||
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
|
||||
MAX_WRITE_ZEROES_BOUNCE_BUFFER);
|
||||
BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE;
|
||||
|
||||
@@ -1214,7 +1220,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||
write_flags &= ~BDRV_REQ_FUA;
|
||||
need_flush = true;
|
||||
}
|
||||
num = MIN(num, max_xfer_len << BDRV_SECTOR_BITS);
|
||||
num = MIN(num, max_transfer);
|
||||
iov.iov_len = num;
|
||||
if (iov.iov_base == NULL) {
|
||||
iov.iov_base = qemu_try_blockalign(bs, num);
|
||||
@@ -1231,7 +1237,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||
/* Keep bounce buffer around if it is big enough for all
|
||||
* all future requests.
|
||||
*/
|
||||
if (num < max_xfer_len << BDRV_SECTOR_BITS) {
|
||||
if (num < max_transfer) {
|
||||
qemu_vfree(iov.iov_base);
|
||||
iov.iov_base = NULL;
|
||||
}
|
||||
@@ -1254,7 +1260,7 @@ fail:
|
||||
*/
|
||||
static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
|
||||
BdrvTrackedRequest *req, int64_t offset, unsigned int bytes,
|
||||
QEMUIOVector *qiov, int flags)
|
||||
int64_t align, QEMUIOVector *qiov, int flags)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
bool waited;
|
||||
@@ -1263,6 +1269,9 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
|
||||
int64_t start_sector = offset >> BDRV_SECTOR_BITS;
|
||||
int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
|
||||
|
||||
assert(is_power_of_2(align));
|
||||
assert((offset & (align - 1)) == 0);
|
||||
assert((bytes & (align - 1)) == 0);
|
||||
assert(!qiov || bytes == qiov->size);
|
||||
assert((bs->open_flags & BDRV_O_NO_IO) == 0);
|
||||
assert(!(flags & ~BDRV_REQ_MASK));
|
||||
@@ -1316,7 +1325,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BlockDriverState *bs,
|
||||
uint8_t *buf = NULL;
|
||||
QEMUIOVector local_qiov;
|
||||
struct iovec iov;
|
||||
uint64_t align = bs->request_alignment;
|
||||
uint64_t align = bs->bl.request_alignment;
|
||||
unsigned int head_padding_bytes, tail_padding_bytes;
|
||||
int ret = 0;
|
||||
|
||||
@@ -1349,7 +1358,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BlockDriverState *bs,
|
||||
|
||||
memset(buf + head_padding_bytes, 0, zero_bytes);
|
||||
ret = bdrv_aligned_pwritev(bs, req, offset & ~(align - 1), align,
|
||||
&local_qiov,
|
||||
align, &local_qiov,
|
||||
flags & ~BDRV_REQ_ZERO_WRITE);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -1362,7 +1371,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BlockDriverState *bs,
|
||||
if (bytes >= align) {
|
||||
/* Write the aligned part in the middle. */
|
||||
uint64_t aligned_bytes = bytes & ~(align - 1);
|
||||
ret = bdrv_aligned_pwritev(bs, req, offset, aligned_bytes,
|
||||
ret = bdrv_aligned_pwritev(bs, req, offset, aligned_bytes, align,
|
||||
NULL, flags);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -1386,7 +1395,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BlockDriverState *bs,
|
||||
bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
|
||||
|
||||
memset(buf, 0, bytes);
|
||||
ret = bdrv_aligned_pwritev(bs, req, offset, align,
|
||||
ret = bdrv_aligned_pwritev(bs, req, offset, align, align,
|
||||
&local_qiov, flags & ~BDRV_REQ_ZERO_WRITE);
|
||||
}
|
||||
fail:
|
||||
@@ -1398,12 +1407,13 @@ fail:
|
||||
/*
|
||||
* Handle a write request in coroutine context
|
||||
*/
|
||||
int coroutine_fn bdrv_co_pwritev(BlockDriverState *bs,
|
||||
int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
|
||||
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
BlockDriverState *bs = child->bs;
|
||||
BdrvTrackedRequest req;
|
||||
uint64_t align = bs->request_alignment;
|
||||
uint64_t align = bs->bl.request_alignment;
|
||||
uint8_t *head_buf = NULL;
|
||||
uint8_t *tail_buf = NULL;
|
||||
QEMUIOVector local_qiov;
|
||||
@@ -1511,7 +1521,7 @@ int coroutine_fn bdrv_co_pwritev(BlockDriverState *bs,
|
||||
bytes = ROUND_UP(bytes, align);
|
||||
}
|
||||
|
||||
ret = bdrv_aligned_pwritev(bs, &req, offset, bytes,
|
||||
ret = bdrv_aligned_pwritev(bs, &req, offset, bytes, align,
|
||||
use_local_qiov ? &local_qiov : qiov,
|
||||
flags);
|
||||
|
||||
@@ -1527,7 +1537,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
|
||||
static int coroutine_fn bdrv_co_do_writev(BdrvChild *child,
|
||||
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
@@ -1535,29 +1545,28 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return bdrv_co_pwritev(bs, sector_num << BDRV_SECTOR_BITS,
|
||||
return bdrv_co_pwritev(child, sector_num << BDRV_SECTOR_BITS,
|
||||
nb_sectors << BDRV_SECTOR_BITS, qiov, flags);
|
||||
}
|
||||
|
||||
int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
int coroutine_fn bdrv_co_writev(BdrvChild *child, int64_t sector_num,
|
||||
int nb_sectors, QEMUIOVector *qiov)
|
||||
{
|
||||
trace_bdrv_co_writev(bs, sector_num, nb_sectors);
|
||||
trace_bdrv_co_writev(child->bs, sector_num, nb_sectors);
|
||||
|
||||
return bdrv_co_do_writev(bs, sector_num, nb_sectors, qiov, 0);
|
||||
return bdrv_co_do_writev(child, sector_num, nb_sectors, qiov, 0);
|
||||
}
|
||||
|
||||
int coroutine_fn bdrv_co_pwrite_zeroes(BlockDriverState *bs,
|
||||
int64_t offset, int count,
|
||||
BdrvRequestFlags flags)
|
||||
int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
||||
int count, BdrvRequestFlags flags)
|
||||
{
|
||||
trace_bdrv_co_pwrite_zeroes(bs, offset, count, flags);
|
||||
trace_bdrv_co_pwrite_zeroes(child->bs, offset, count, flags);
|
||||
|
||||
if (!(bs->open_flags & BDRV_O_UNMAP)) {
|
||||
if (!(child->bs->open_flags & BDRV_O_UNMAP)) {
|
||||
flags &= ~BDRV_REQ_MAY_UNMAP;
|
||||
}
|
||||
|
||||
return bdrv_co_pwritev(bs, offset, count, NULL,
|
||||
return bdrv_co_pwritev(child, offset, count, NULL,
|
||||
BDRV_REQ_ZERO_WRITE | flags);
|
||||
}
|
||||
|
||||
@@ -1954,23 +1963,23 @@ int bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
|
||||
/**************************************************************/
|
||||
/* async I/Os */
|
||||
|
||||
BlockAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
BlockAIOCB *bdrv_aio_readv(BdrvChild *child, int64_t sector_num,
|
||||
QEMUIOVector *qiov, int nb_sectors,
|
||||
BlockCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
trace_bdrv_aio_readv(bs, sector_num, nb_sectors, opaque);
|
||||
trace_bdrv_aio_readv(child->bs, sector_num, nb_sectors, opaque);
|
||||
|
||||
return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, 0,
|
||||
return bdrv_co_aio_rw_vector(child, sector_num, qiov, nb_sectors, 0,
|
||||
cb, opaque, false);
|
||||
}
|
||||
|
||||
BlockAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
BlockAIOCB *bdrv_aio_writev(BdrvChild *child, int64_t sector_num,
|
||||
QEMUIOVector *qiov, int nb_sectors,
|
||||
BlockCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
trace_bdrv_aio_writev(bs, sector_num, nb_sectors, opaque);
|
||||
trace_bdrv_aio_writev(child->bs, sector_num, nb_sectors, opaque);
|
||||
|
||||
return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, 0,
|
||||
return bdrv_co_aio_rw_vector(child, sector_num, qiov, nb_sectors, 0,
|
||||
cb, opaque, true);
|
||||
}
|
||||
|
||||
@@ -2026,6 +2035,7 @@ typedef struct BlockRequest {
|
||||
|
||||
typedef struct BlockAIOCBCoroutine {
|
||||
BlockAIOCB common;
|
||||
BdrvChild *child;
|
||||
BlockRequest req;
|
||||
bool is_write;
|
||||
bool need_bh;
|
||||
@@ -2069,20 +2079,19 @@ static void bdrv_co_maybe_schedule_bh(BlockAIOCBCoroutine *acb)
|
||||
static void coroutine_fn bdrv_co_do_rw(void *opaque)
|
||||
{
|
||||
BlockAIOCBCoroutine *acb = opaque;
|
||||
BlockDriverState *bs = acb->common.bs;
|
||||
|
||||
if (!acb->is_write) {
|
||||
acb->req.error = bdrv_co_do_readv(bs, acb->req.sector,
|
||||
acb->req.error = bdrv_co_do_readv(acb->child, acb->req.sector,
|
||||
acb->req.nb_sectors, acb->req.qiov, acb->req.flags);
|
||||
} else {
|
||||
acb->req.error = bdrv_co_do_writev(bs, acb->req.sector,
|
||||
acb->req.error = bdrv_co_do_writev(acb->child, acb->req.sector,
|
||||
acb->req.nb_sectors, acb->req.qiov, acb->req.flags);
|
||||
}
|
||||
|
||||
bdrv_co_complete(acb);
|
||||
}
|
||||
|
||||
static BlockAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
|
||||
static BlockAIOCB *bdrv_co_aio_rw_vector(BdrvChild *child,
|
||||
int64_t sector_num,
|
||||
QEMUIOVector *qiov,
|
||||
int nb_sectors,
|
||||
@@ -2094,7 +2103,8 @@ static BlockAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
|
||||
Coroutine *co;
|
||||
BlockAIOCBCoroutine *acb;
|
||||
|
||||
acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
|
||||
acb = qemu_aio_get(&bdrv_em_co_aiocb_info, child->bs, cb, opaque);
|
||||
acb->child = child;
|
||||
acb->need_bh = true;
|
||||
acb->req.error = -EINPROGRESS;
|
||||
acb->req.sector = sector_num;
|
||||
@@ -2200,9 +2210,15 @@ void qemu_aio_unref(void *p)
|
||||
/**************************************************************/
|
||||
/* Coroutine block device emulation */
|
||||
|
||||
typedef struct FlushCo {
|
||||
BlockDriverState *bs;
|
||||
int ret;
|
||||
} FlushCo;
|
||||
|
||||
|
||||
static void coroutine_fn bdrv_flush_co_entry(void *opaque)
|
||||
{
|
||||
RwCo *rwco = opaque;
|
||||
FlushCo *rwco = opaque;
|
||||
|
||||
rwco->ret = bdrv_co_flush(rwco->bs);
|
||||
}
|
||||
@@ -2286,25 +2302,25 @@ out:
|
||||
int bdrv_flush(BlockDriverState *bs)
|
||||
{
|
||||
Coroutine *co;
|
||||
RwCo rwco = {
|
||||
FlushCo flush_co = {
|
||||
.bs = bs,
|
||||
.ret = NOT_DONE,
|
||||
};
|
||||
|
||||
if (qemu_in_coroutine()) {
|
||||
/* Fast-path if already in coroutine context */
|
||||
bdrv_flush_co_entry(&rwco);
|
||||
bdrv_flush_co_entry(&flush_co);
|
||||
} else {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
co = qemu_coroutine_create(bdrv_flush_co_entry);
|
||||
qemu_coroutine_enter(co, &rwco);
|
||||
while (rwco.ret == NOT_DONE) {
|
||||
qemu_coroutine_enter(co, &flush_co);
|
||||
while (flush_co.ret == NOT_DONE) {
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
return rwco.ret;
|
||||
return flush_co.ret;
|
||||
}
|
||||
|
||||
typedef struct DiscardCo {
|
||||
@@ -2355,19 +2371,21 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
|
||||
goto out;
|
||||
}
|
||||
|
||||
max_discard = MIN_NON_ZERO(bs->bl.max_discard, BDRV_REQUEST_MAX_SECTORS);
|
||||
max_discard = MIN_NON_ZERO(bs->bl.max_pdiscard >> BDRV_SECTOR_BITS,
|
||||
BDRV_REQUEST_MAX_SECTORS);
|
||||
while (nb_sectors > 0) {
|
||||
int ret;
|
||||
int num = nb_sectors;
|
||||
int discard_alignment = bs->bl.pdiscard_alignment >> BDRV_SECTOR_BITS;
|
||||
|
||||
/* align request */
|
||||
if (bs->bl.discard_alignment &&
|
||||
num >= bs->bl.discard_alignment &&
|
||||
sector_num % bs->bl.discard_alignment) {
|
||||
if (num > bs->bl.discard_alignment) {
|
||||
num = bs->bl.discard_alignment;
|
||||
if (discard_alignment &&
|
||||
num >= discard_alignment &&
|
||||
sector_num % discard_alignment) {
|
||||
if (num > discard_alignment) {
|
||||
num = discard_alignment;
|
||||
}
|
||||
num -= sector_num % bs->bl.discard_alignment;
|
||||
num -= sector_num % discard_alignment;
|
||||
}
|
||||
|
||||
/* limit request size */
|
||||
|
||||
@@ -473,9 +473,10 @@ iscsi_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bs->bl.max_transfer_length && nb_sectors > bs->bl.max_transfer_length) {
|
||||
if (bs->bl.max_transfer &&
|
||||
nb_sectors << BDRV_SECTOR_BITS > bs->bl.max_transfer) {
|
||||
error_report("iSCSI Error: Write of %d sectors exceeds max_xfer_len "
|
||||
"of %d sectors", nb_sectors, bs->bl.max_transfer_length);
|
||||
"of %" PRIu32 " bytes", nb_sectors, bs->bl.max_transfer);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -650,9 +651,10 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bs->bl.max_transfer_length && nb_sectors > bs->bl.max_transfer_length) {
|
||||
if (bs->bl.max_transfer &&
|
||||
nb_sectors << BDRV_SECTOR_BITS > bs->bl.max_transfer) {
|
||||
error_report("iSCSI Error: Read of %d sectors exceeds max_xfer_len "
|
||||
"of %d sectors", nb_sectors, bs->bl.max_transfer_length);
|
||||
"of %" PRIu32 " bytes", nb_sectors, bs->bl.max_transfer);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1589,14 +1591,13 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto out;
|
||||
}
|
||||
bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);
|
||||
bs->request_alignment = iscsilun->block_size;
|
||||
|
||||
/* We don't have any emulation for devices other than disks and CD-ROMs, so
|
||||
* this must be sg ioctl compatible. We force it to be sg, otherwise qemu
|
||||
* will try to read from the device to guess the image format.
|
||||
*/
|
||||
if (iscsilun->type != TYPE_DISK && iscsilun->type != TYPE_ROM) {
|
||||
bs->sg = 1;
|
||||
bs->sg = true;
|
||||
}
|
||||
|
||||
task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
|
||||
@@ -1696,34 +1697,33 @@ static void iscsi_close(BlockDriverState *bs)
|
||||
memset(iscsilun, 0, sizeof(IscsiLun));
|
||||
}
|
||||
|
||||
static int sector_limits_lun2qemu(int64_t sector, IscsiLun *iscsilun)
|
||||
{
|
||||
return MIN(sector_lun2qemu(sector, iscsilun), INT_MAX / 2 + 1);
|
||||
}
|
||||
|
||||
static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
/* We don't actually refresh here, but just return data queried in
|
||||
* iscsi_open(): iscsi targets don't change their limits. */
|
||||
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
uint32_t max_xfer_len = iscsilun->use_16_for_rw ? 0xffffffff : 0xffff;
|
||||
uint64_t max_xfer_len = iscsilun->use_16_for_rw ? 0xffffffff : 0xffff;
|
||||
|
||||
bs->bl.request_alignment = iscsilun->block_size;
|
||||
|
||||
if (iscsilun->bl.max_xfer_len) {
|
||||
max_xfer_len = MIN(max_xfer_len, iscsilun->bl.max_xfer_len);
|
||||
}
|
||||
|
||||
bs->bl.max_transfer_length = sector_limits_lun2qemu(max_xfer_len, iscsilun);
|
||||
if (max_xfer_len * iscsilun->block_size < INT_MAX) {
|
||||
bs->bl.max_transfer = max_xfer_len * iscsilun->block_size;
|
||||
}
|
||||
|
||||
if (iscsilun->lbp.lbpu) {
|
||||
if (iscsilun->bl.max_unmap < 0xffffffff) {
|
||||
bs->bl.max_discard =
|
||||
sector_limits_lun2qemu(iscsilun->bl.max_unmap, iscsilun);
|
||||
if (iscsilun->bl.max_unmap < 0xffffffff / iscsilun->block_size) {
|
||||
bs->bl.max_pdiscard =
|
||||
iscsilun->bl.max_unmap * iscsilun->block_size;
|
||||
}
|
||||
bs->bl.discard_alignment =
|
||||
sector_limits_lun2qemu(iscsilun->bl.opt_unmap_gran, iscsilun);
|
||||
bs->bl.pdiscard_alignment =
|
||||
iscsilun->bl.opt_unmap_gran * iscsilun->block_size;
|
||||
} else {
|
||||
bs->bl.discard_alignment = iscsilun->block_size >> BDRV_SECTOR_BITS;
|
||||
bs->bl.pdiscard_alignment = iscsilun->block_size;
|
||||
}
|
||||
|
||||
if (iscsilun->bl.max_ws_len < 0xffffffff / iscsilun->block_size) {
|
||||
@@ -1736,8 +1736,11 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
} else {
|
||||
bs->bl.pwrite_zeroes_alignment = iscsilun->block_size;
|
||||
}
|
||||
bs->bl.opt_transfer_length =
|
||||
sector_limits_lun2qemu(iscsilun->bl.opt_xfer_len, iscsilun);
|
||||
if (iscsilun->bl.opt_xfer_len &&
|
||||
iscsilun->bl.opt_xfer_len < INT_MAX / iscsilun->block_size) {
|
||||
bs->bl.opt_transfer = pow2floor(iscsilun->bl.opt_xfer_len *
|
||||
iscsilun->block_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that this will not re-establish a connection with an iSCSI target - it
|
||||
|
||||
@@ -87,7 +87,7 @@ static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
|
||||
qemu_iovec_memset(laiocb->qiov, ret, 0,
|
||||
laiocb->qiov->size - ret);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
ret = -ENOSPC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,10 +269,6 @@ static int nbd_co_writev_1(BlockDriverState *bs, int64_t sector_num,
|
||||
return -reply.error;
|
||||
}
|
||||
|
||||
/* qemu-nbd has a limit of slightly less than 1M per request. Try to
|
||||
* remain aligned to 4K. */
|
||||
#define NBD_MAX_SECTORS 2040
|
||||
|
||||
int nbd_client_co_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
int nb_sectors, QEMUIOVector *qiov)
|
||||
{
|
||||
|
||||
@@ -362,8 +362,8 @@ static int nbd_co_flush(BlockDriverState *bs)
|
||||
|
||||
static void nbd_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
bs->bl.max_discard = UINT32_MAX >> BDRV_SECTOR_BITS;
|
||||
bs->bl.max_transfer_length = UINT32_MAX >> BDRV_SECTOR_BITS;
|
||||
bs->bl.max_pdiscard = NBD_MAX_BUFFER_SIZE;
|
||||
bs->bl.max_transfer = NBD_MAX_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
static int nbd_co_discard(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
@@ -210,7 +210,7 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
|
||||
int ret;
|
||||
space += s->prealloc_size;
|
||||
if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
|
||||
ret = bdrv_pwrite_zeroes(bs->file->bs,
|
||||
ret = bdrv_pwrite_zeroes(bs->file,
|
||||
s->data_end << BDRV_SECTOR_BITS,
|
||||
space << BDRV_SECTOR_BITS, 0);
|
||||
} else {
|
||||
@@ -250,7 +250,7 @@ static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
|
||||
if (off + to_write > s->header_size) {
|
||||
to_write = s->header_size - off;
|
||||
}
|
||||
ret = bdrv_pwrite(bs->file->bs, off, (uint8_t *)s->header + off,
|
||||
ret = bdrv_pwrite(bs->file, off, (uint8_t *)s->header + off,
|
||||
to_write);
|
||||
if (ret < 0) {
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
@@ -311,7 +311,7 @@ static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
|
||||
qemu_iovec_reset(&hd_qiov);
|
||||
qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
|
||||
|
||||
ret = bdrv_co_writev(bs->file->bs, position, n, &hd_qiov);
|
||||
ret = bdrv_co_writev(bs->file, position, n, &hd_qiov);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
@@ -351,7 +351,7 @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
|
||||
qemu_iovec_reset(&hd_qiov);
|
||||
qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
|
||||
|
||||
ret = bdrv_co_readv(bs->file->bs, position, n, &hd_qiov);
|
||||
ret = bdrv_co_readv(bs->file, position, n, &hd_qiov);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
@@ -432,7 +432,7 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
}
|
||||
|
||||
if (flush_bat) {
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, 0, s->header, s->header_size);
|
||||
ret = bdrv_pwrite_sync(bs->file, 0, s->header, s->header_size);
|
||||
if (ret < 0) {
|
||||
res->check_errors++;
|
||||
return ret;
|
||||
@@ -563,7 +563,7 @@ static int parallels_update_header(BlockDriverState *bs)
|
||||
if (size > s->header_size) {
|
||||
size = s->header_size;
|
||||
}
|
||||
return bdrv_pwrite_sync(bs->file->bs, 0, s->header, size);
|
||||
return bdrv_pwrite_sync(bs->file, 0, s->header, size);
|
||||
}
|
||||
|
||||
static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
@@ -576,7 +576,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
Error *local_err = NULL;
|
||||
char *buf;
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, 0, &ph, sizeof(ph));
|
||||
ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -631,7 +631,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
s->header_size = size;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, 0, s->header, s->header_size);
|
||||
ret = bdrv_pread(bs->file, 0, s->header, s->header_size);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -690,16 +690,15 @@ static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
|
||||
void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
|
||||
ImageInfoSpecific *info_spec)
|
||||
{
|
||||
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
||||
QObject *obj, *data;
|
||||
Visitor *v = qmp_output_visitor_new(&obj);
|
||||
|
||||
visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), NULL, &info_spec,
|
||||
&error_abort);
|
||||
obj = qmp_output_get_qobject(ov);
|
||||
visit_type_ImageInfoSpecific(v, NULL, &info_spec, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
assert(qobject_type(obj) == QTYPE_QDICT);
|
||||
data = qdict_get(qobject_to_qdict(obj), "data");
|
||||
dump_qobject(func_fprintf, f, 1, data);
|
||||
qmp_output_visitor_cleanup(ov);
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
|
||||
|
||||
78
block/qcow.c
78
block/qcow.c
@@ -105,7 +105,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
int ret;
|
||||
QCowHeader header;
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, 0, &header, sizeof(header));
|
||||
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -174,7 +174,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bs->encrypted = 1;
|
||||
bs->encrypted = true;
|
||||
}
|
||||
s->cluster_bits = header.cluster_bits;
|
||||
s->cluster_size = 1 << s->cluster_bits;
|
||||
@@ -208,7 +208,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, s->l1_table_offset, s->l1_table,
|
||||
ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table,
|
||||
s->l1_size * sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -239,7 +239,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
ret = bdrv_pread(bs->file->bs, header.backing_file_offset,
|
||||
ret = bdrv_pread(bs->file, header.backing_file_offset,
|
||||
bs->backing_file, len);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -390,7 +390,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
|
||||
/* update the L1 entry */
|
||||
s->l1_table[l1_index] = l2_offset;
|
||||
tmp = cpu_to_be64(l2_offset);
|
||||
if (bdrv_pwrite_sync(bs->file->bs,
|
||||
if (bdrv_pwrite_sync(bs->file,
|
||||
s->l1_table_offset + l1_index * sizeof(tmp),
|
||||
&tmp, sizeof(tmp)) < 0)
|
||||
return 0;
|
||||
@@ -420,11 +420,11 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
|
||||
l2_table = s->l2_cache + (min_index << s->l2_bits);
|
||||
if (new_l2_table) {
|
||||
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
|
||||
if (bdrv_pwrite_sync(bs->file->bs, l2_offset, l2_table,
|
||||
if (bdrv_pwrite_sync(bs->file, l2_offset, l2_table,
|
||||
s->l2_size * sizeof(uint64_t)) < 0)
|
||||
return 0;
|
||||
} else {
|
||||
if (bdrv_pread(bs->file->bs, l2_offset, l2_table,
|
||||
if (bdrv_pread(bs->file, l2_offset, l2_table,
|
||||
s->l2_size * sizeof(uint64_t)) !=
|
||||
s->l2_size * sizeof(uint64_t))
|
||||
return 0;
|
||||
@@ -450,7 +450,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
|
||||
cluster_offset = (cluster_offset + s->cluster_size - 1) &
|
||||
~(s->cluster_size - 1);
|
||||
/* write the cluster content */
|
||||
if (bdrv_pwrite(bs->file->bs, cluster_offset, s->cluster_cache,
|
||||
if (bdrv_pwrite(bs->file, cluster_offset, s->cluster_cache,
|
||||
s->cluster_size) !=
|
||||
s->cluster_size)
|
||||
return -1;
|
||||
@@ -480,7 +480,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
if (bdrv_pwrite(bs->file->bs,
|
||||
if (bdrv_pwrite(bs->file,
|
||||
cluster_offset + i * 512,
|
||||
s->cluster_data, 512) != 512)
|
||||
return -1;
|
||||
@@ -495,7 +495,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
|
||||
/* update L2 table */
|
||||
tmp = cpu_to_be64(cluster_offset);
|
||||
l2_table[l2_index] = tmp;
|
||||
if (bdrv_pwrite_sync(bs->file->bs, l2_offset + l2_index * sizeof(tmp),
|
||||
if (bdrv_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
|
||||
&tmp, sizeof(tmp)) < 0)
|
||||
return 0;
|
||||
}
|
||||
@@ -565,7 +565,7 @@ static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
|
||||
if (s->cluster_cache_offset != coffset) {
|
||||
csize = cluster_offset >> (63 - s->cluster_bits);
|
||||
csize &= (s->cluster_size - 1);
|
||||
ret = bdrv_pread(bs->file->bs, coffset, s->cluster_data, csize);
|
||||
ret = bdrv_pread(bs->file, coffset, s->cluster_data, csize);
|
||||
if (ret != csize)
|
||||
return -1;
|
||||
if (decompress_buffer(s->cluster_cache, s->cluster_size,
|
||||
@@ -619,8 +619,7 @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
hd_iov.iov_len = n * 512;
|
||||
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
ret = bdrv_co_readv(bs->backing->bs, sector_num,
|
||||
n, &hd_qiov);
|
||||
ret = bdrv_co_readv(bs->backing, sector_num, n, &hd_qiov);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -644,7 +643,7 @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
hd_iov.iov_len = n * 512;
|
||||
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
ret = bdrv_co_readv(bs->file->bs,
|
||||
ret = bdrv_co_readv(bs->file,
|
||||
(cluster_offset >> 9) + index_in_cluster,
|
||||
n, &hd_qiov);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
@@ -746,7 +745,7 @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
hd_iov.iov_len = n * 512;
|
||||
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
ret = bdrv_co_writev(bs->file->bs,
|
||||
ret = bdrv_co_writev(bs->file,
|
||||
(cluster_offset >> 9) + index_in_cluster,
|
||||
n, &hd_qiov);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
@@ -900,7 +899,7 @@ static int qcow_make_empty(BlockDriverState *bs)
|
||||
int ret;
|
||||
|
||||
memset(s->l1_table, 0, l1_length);
|
||||
if (bdrv_pwrite_sync(bs->file->bs, s->l1_table_offset, s->l1_table,
|
||||
if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table,
|
||||
l1_length) < 0)
|
||||
return -1;
|
||||
ret = bdrv_truncate(bs->file->bs, s->l1_table_offset + l1_length);
|
||||
@@ -914,6 +913,49 @@ static int qcow_make_empty(BlockDriverState *bs)
|
||||
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);
|
||||
qemu_coroutine_enter(co, &data);
|
||||
while (data.ret == -EINPROGRESS) {
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
return data.ret;
|
||||
}
|
||||
|
||||
/* XXX: put compressed sectors first, then all the cluster aligned
|
||||
tables to avoid losing bytes in alignment */
|
||||
static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
@@ -970,7 +1012,7 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
|
||||
/* could not compress: write normal cluster */
|
||||
ret = bdrv_write(bs, sector_num, buf, s->cluster_sectors);
|
||||
ret = qcow_write(bs, sector_num, buf, s->cluster_sectors);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -983,7 +1025,7 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
}
|
||||
|
||||
cluster_offset &= s->cluster_offset_mask;
|
||||
ret = bdrv_pwrite(bs->file->bs, cluster_offset, out_buf, out_len);
|
||||
ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite(bs->file->bs, c->entries[i].offset,
|
||||
ret = bdrv_pwrite(bs->file, c->entries[i].offset,
|
||||
qcow2_cache_get_table_addr(bs, c, i), s->cluster_size);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -357,7 +357,7 @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, offset,
|
||||
ret = bdrv_pread(bs->file, offset,
|
||||
qcow2_cache_get_table_addr(bs, c, i),
|
||||
s->cluster_size);
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -108,7 +108,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE);
|
||||
for(i = 0; i < s->l1_size; i++)
|
||||
new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, new_l1_table_offset,
|
||||
ret = bdrv_pwrite_sync(bs->file, new_l1_table_offset,
|
||||
new_l1_table, new_l1_size2);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
@@ -117,9 +117,9 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
|
||||
/* set new table */
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ACTIVATE_TABLE);
|
||||
cpu_to_be32w((uint32_t*)data, new_l1_size);
|
||||
stl_be_p(data, new_l1_size);
|
||||
stq_be_p(data + 4, new_l1_table_offset);
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, offsetof(QCowHeader, l1_size),
|
||||
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_size),
|
||||
data, sizeof(data));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -185,7 +185,7 @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
|
||||
ret = bdrv_pwrite_sync(bs->file->bs,
|
||||
ret = bdrv_pwrite_sync(bs->file,
|
||||
s->l1_table_offset + 8 * l1_start_index,
|
||||
buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
@@ -446,7 +446,7 @@ static int coroutine_fn do_perform_cow(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE);
|
||||
ret = bdrv_co_pwritev(bs->file->bs, cluster_offset + offset_in_cluster,
|
||||
ret = bdrv_co_pwritev(bs->file, cluster_offset + offset_in_cluster,
|
||||
bytes, &qiov, 0);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
@@ -1408,7 +1408,7 @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
|
||||
sector_offset = coffset & 511;
|
||||
csize = nb_csectors * 512 - sector_offset;
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
|
||||
ret = bdrv_read(bs->file->bs, coffset >> 9, s->cluster_data,
|
||||
ret = bdrv_read(bs->file, coffset >> 9, s->cluster_data,
|
||||
nb_csectors);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -1677,7 +1677,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
(void **)&l2_table);
|
||||
} else {
|
||||
/* load inactive L2 tables from disk */
|
||||
ret = bdrv_read(bs->file->bs, l2_offset / BDRV_SECTOR_SIZE,
|
||||
ret = bdrv_read(bs->file, l2_offset / BDRV_SECTOR_SIZE,
|
||||
(void *)l2_table, s->cluster_sectors);
|
||||
}
|
||||
if (ret < 0) {
|
||||
@@ -1752,7 +1752,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite_zeroes(bs->file->bs, offset, s->cluster_size, 0);
|
||||
ret = bdrv_pwrite_zeroes(bs->file, offset, s->cluster_size, 0);
|
||||
if (ret < 0) {
|
||||
if (!preallocated) {
|
||||
qcow2_free_clusters(bs, offset, s->cluster_size,
|
||||
@@ -1784,7 +1784,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_write(bs->file->bs, l2_offset / BDRV_SECTOR_SIZE,
|
||||
ret = bdrv_write(bs->file, l2_offset / BDRV_SECTOR_SIZE,
|
||||
(void *)l2_table, s->cluster_sectors);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -1859,7 +1859,7 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
|
||||
|
||||
l1_table = g_realloc(l1_table, l1_sectors * BDRV_SECTOR_SIZE);
|
||||
|
||||
ret = bdrv_read(bs->file->bs,
|
||||
ret = bdrv_read(bs->file,
|
||||
s->snapshots[i].l1_table_offset / BDRV_SECTOR_SIZE,
|
||||
(void *)l1_table, l1_sectors);
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -104,7 +104,7 @@ int qcow2_refcount_init(BlockDriverState *bs)
|
||||
goto fail;
|
||||
}
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD);
|
||||
ret = bdrv_pread(bs->file->bs, s->refcount_table_offset,
|
||||
ret = bdrv_pread(bs->file, s->refcount_table_offset,
|
||||
s->refcount_table, refcount_table_size2);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -431,7 +431,7 @@ static int alloc_refcount_block(BlockDriverState *bs,
|
||||
if (refcount_table_index < s->refcount_table_size) {
|
||||
uint64_t data64 = cpu_to_be64(new_block);
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_HOOKUP);
|
||||
ret = bdrv_pwrite_sync(bs->file->bs,
|
||||
ret = bdrv_pwrite_sync(bs->file,
|
||||
s->refcount_table_offset + refcount_table_index * sizeof(uint64_t),
|
||||
&data64, sizeof(data64));
|
||||
if (ret < 0) {
|
||||
@@ -533,7 +533,7 @@ static int alloc_refcount_block(BlockDriverState *bs,
|
||||
|
||||
/* Write refcount blocks to disk */
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS);
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, meta_offset, new_blocks,
|
||||
ret = bdrv_pwrite_sync(bs->file, meta_offset, new_blocks,
|
||||
blocks_clusters * s->cluster_size);
|
||||
g_free(new_blocks);
|
||||
new_blocks = NULL;
|
||||
@@ -547,7 +547,7 @@ static int alloc_refcount_block(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE);
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, table_offset, new_table,
|
||||
ret = bdrv_pwrite_sync(bs->file, table_offset, new_table,
|
||||
table_size * sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
goto fail_table;
|
||||
@@ -562,10 +562,10 @@ static int alloc_refcount_block(BlockDriverState *bs,
|
||||
uint64_t d64;
|
||||
uint32_t d32;
|
||||
} data;
|
||||
cpu_to_be64w(&data.d64, table_offset);
|
||||
cpu_to_be32w(&data.d32, table_clusters);
|
||||
data.d64 = cpu_to_be64(table_offset);
|
||||
data.d32 = cpu_to_be32(table_clusters);
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE);
|
||||
ret = bdrv_pwrite_sync(bs->file->bs,
|
||||
ret = bdrv_pwrite_sync(bs->file,
|
||||
offsetof(QCowHeader, refcount_table_offset),
|
||||
&data, sizeof(data));
|
||||
if (ret < 0) {
|
||||
@@ -1070,7 +1070,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
}
|
||||
l1_allocated = true;
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, l1_table_offset, l1_table, l1_size2);
|
||||
ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size2);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -1223,7 +1223,7 @@ fail:
|
||||
cpu_to_be64s(&l1_table[i]);
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, l1_table_offset,
|
||||
ret = bdrv_pwrite_sync(bs->file, l1_table_offset,
|
||||
l1_table, l1_size2);
|
||||
|
||||
for (i = 0; i < l1_size; i++) {
|
||||
@@ -1382,7 +1382,7 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
l2_size = s->l2_size * sizeof(uint64_t);
|
||||
l2_table = g_malloc(l2_size);
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, l2_offset, l2_table, l2_size);
|
||||
ret = bdrv_pread(bs->file, l2_offset, l2_table, l2_size);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "ERROR: I/O error in check_refcounts_l2\n");
|
||||
res->check_errors++;
|
||||
@@ -1514,7 +1514,7 @@ static int check_refcounts_l1(BlockDriverState *bs,
|
||||
res->check_errors++;
|
||||
goto fail;
|
||||
}
|
||||
ret = bdrv_pread(bs->file->bs, l1_table_offset, l1_table, l1_size2);
|
||||
ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size2);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "ERROR: I/O error in check_refcounts_l1\n");
|
||||
res->check_errors++;
|
||||
@@ -1612,7 +1612,7 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
}
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, l2_offset, l2_table,
|
||||
ret = bdrv_pread(bs->file, l2_offset, l2_table,
|
||||
s->l2_size * sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "ERROR: Could not read L2 table: %s\n",
|
||||
@@ -1664,7 +1664,7 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite(bs->file->bs, l2_offset, l2_table,
|
||||
ret = bdrv_pwrite(bs->file, l2_offset, l2_table,
|
||||
s->cluster_size);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "ERROR: Could not write L2 table: %s\n",
|
||||
@@ -2098,7 +2098,7 @@ write_refblocks:
|
||||
on_disk_refblock = (void *)((char *) *refcount_table +
|
||||
refblock_index * s->cluster_size);
|
||||
|
||||
ret = bdrv_write(bs->file->bs, refblock_offset / BDRV_SECTOR_SIZE,
|
||||
ret = bdrv_write(bs->file, refblock_offset / BDRV_SECTOR_SIZE,
|
||||
on_disk_refblock, s->cluster_sectors);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "ERROR writing refblock: %s\n", strerror(-ret));
|
||||
@@ -2147,7 +2147,7 @@ write_refblocks:
|
||||
}
|
||||
|
||||
assert(reftable_size < INT_MAX / sizeof(uint64_t));
|
||||
ret = bdrv_pwrite(bs->file->bs, reftable_offset, on_disk_reftable,
|
||||
ret = bdrv_pwrite(bs->file, reftable_offset, on_disk_reftable,
|
||||
reftable_size * sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret));
|
||||
@@ -2155,12 +2155,11 @@ write_refblocks:
|
||||
}
|
||||
|
||||
/* Enter new reftable into the image header */
|
||||
cpu_to_be64w(&reftable_offset_and_clusters.reftable_offset,
|
||||
reftable_offset);
|
||||
cpu_to_be32w(&reftable_offset_and_clusters.reftable_clusters,
|
||||
size_to_clusters(s, reftable_size * sizeof(uint64_t)));
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, offsetof(QCowHeader,
|
||||
refcount_table_offset),
|
||||
reftable_offset_and_clusters.reftable_offset = cpu_to_be64(reftable_offset);
|
||||
reftable_offset_and_clusters.reftable_clusters =
|
||||
cpu_to_be32(size_to_clusters(s, reftable_size * sizeof(uint64_t)));
|
||||
ret = bdrv_pwrite_sync(bs->file,
|
||||
offsetof(QCowHeader, refcount_table_offset),
|
||||
&reftable_offset_and_clusters,
|
||||
sizeof(reftable_offset_and_clusters));
|
||||
if (ret < 0) {
|
||||
@@ -2407,7 +2406,7 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, l1_ofs, l1, l1_sz2);
|
||||
ret = bdrv_pread(bs->file, l1_ofs, l1, l1_sz2);
|
||||
if (ret < 0) {
|
||||
g_free(l1);
|
||||
return ret;
|
||||
@@ -2560,7 +2559,7 @@ static int flush_refblock(BlockDriverState *bs, uint64_t **reftable,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite(bs->file->bs, offset, refblock, s->cluster_size);
|
||||
ret = bdrv_pwrite(bs->file, offset, refblock, s->cluster_size);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to write refblock");
|
||||
return ret;
|
||||
@@ -2830,7 +2829,7 @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
|
||||
cpu_to_be64s(&new_reftable[i]);
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite(bs->file->bs, new_reftable_offset, new_reftable,
|
||||
ret = bdrv_pwrite(bs->file, new_reftable_offset, new_reftable,
|
||||
new_reftable_size * sizeof(uint64_t));
|
||||
|
||||
for (i = 0; i < new_reftable_size; i++) {
|
||||
|
||||
@@ -67,7 +67,7 @@ int qcow2_read_snapshots(BlockDriverState *bs)
|
||||
for(i = 0; i < s->nb_snapshots; i++) {
|
||||
/* Read statically sized part of the snapshot header */
|
||||
offset = align_offset(offset, 8);
|
||||
ret = bdrv_pread(bs->file->bs, offset, &h, sizeof(h));
|
||||
ret = bdrv_pread(bs->file, offset, &h, sizeof(h));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -86,7 +86,7 @@ int qcow2_read_snapshots(BlockDriverState *bs)
|
||||
name_size = be16_to_cpu(h.name_size);
|
||||
|
||||
/* Read extra data */
|
||||
ret = bdrv_pread(bs->file->bs, offset, &extra,
|
||||
ret = bdrv_pread(bs->file, offset, &extra,
|
||||
MIN(sizeof(extra), extra_data_size));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -105,7 +105,7 @@ int qcow2_read_snapshots(BlockDriverState *bs)
|
||||
|
||||
/* Read snapshot ID */
|
||||
sn->id_str = g_malloc(id_str_size + 1);
|
||||
ret = bdrv_pread(bs->file->bs, offset, sn->id_str, id_str_size);
|
||||
ret = bdrv_pread(bs->file, offset, sn->id_str, id_str_size);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -114,7 +114,7 @@ int qcow2_read_snapshots(BlockDriverState *bs)
|
||||
|
||||
/* Read snapshot name */
|
||||
sn->name = g_malloc(name_size + 1);
|
||||
ret = bdrv_pread(bs->file->bs, offset, sn->name, name_size);
|
||||
ret = bdrv_pread(bs->file, offset, sn->name, name_size);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -217,25 +217,25 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
|
||||
h.name_size = cpu_to_be16(name_size);
|
||||
offset = align_offset(offset, 8);
|
||||
|
||||
ret = bdrv_pwrite(bs->file->bs, offset, &h, sizeof(h));
|
||||
ret = bdrv_pwrite(bs->file, offset, &h, sizeof(h));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
offset += sizeof(h);
|
||||
|
||||
ret = bdrv_pwrite(bs->file->bs, offset, &extra, sizeof(extra));
|
||||
ret = bdrv_pwrite(bs->file, offset, &extra, sizeof(extra));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
offset += sizeof(extra);
|
||||
|
||||
ret = bdrv_pwrite(bs->file->bs, offset, sn->id_str, id_str_size);
|
||||
ret = bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
offset += id_str_size;
|
||||
|
||||
ret = bdrv_pwrite(bs->file->bs, offset, sn->name, name_size);
|
||||
ret = bdrv_pwrite(bs->file, offset, sn->name, name_size);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -257,7 +257,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
|
||||
header_data.nb_snapshots = cpu_to_be32(s->nb_snapshots);
|
||||
header_data.snapshots_offset = cpu_to_be64(snapshots_offset);
|
||||
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, offsetof(QCowHeader, nb_snapshots),
|
||||
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
|
||||
&header_data, sizeof(header_data));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -399,7 +399,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite(bs->file->bs, sn->l1_table_offset, l1_table,
|
||||
ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table,
|
||||
s->l1_size * sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -512,7 +512,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, sn->l1_table_offset,
|
||||
ret = bdrv_pread(bs->file, sn->l1_table_offset,
|
||||
sn_l1_table, sn_l1_bytes);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -530,7 +530,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, s->l1_table_offset, sn_l1_table,
|
||||
ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset, sn_l1_table,
|
||||
cur_l1_bytes);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -716,7 +716,7 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, sn->l1_table_offset,
|
||||
ret = bdrv_pread(bs->file, sn->l1_table_offset,
|
||||
new_l1_table, new_l1_bytes);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Failed to read l1 table for snapshot");
|
||||
|
||||
102
block/qcow2.c
102
block/qcow2.c
@@ -107,7 +107,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
||||
printf("attempting to read extended header in offset %lu\n", offset);
|
||||
#endif
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, offset, &ext, sizeof(ext));
|
||||
ret = bdrv_pread(bs->file, offset, &ext, sizeof(ext));
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "qcow2_read_extension: ERROR: "
|
||||
"pread fail from offset %" PRIu64, offset);
|
||||
@@ -135,7 +135,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
||||
sizeof(bs->backing_format));
|
||||
return 2;
|
||||
}
|
||||
ret = bdrv_pread(bs->file->bs, offset, bs->backing_format, ext.len);
|
||||
ret = bdrv_pread(bs->file, offset, bs->backing_format, ext.len);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "ERROR: ext_backing_format: "
|
||||
"Could not read format name");
|
||||
@@ -151,7 +151,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
||||
case QCOW2_EXT_MAGIC_FEATURE_TABLE:
|
||||
if (p_feature_table != NULL) {
|
||||
void* feature_table = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature));
|
||||
ret = bdrv_pread(bs->file->bs, offset , feature_table, ext.len);
|
||||
ret = bdrv_pread(bs->file, offset , feature_table, ext.len);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "ERROR: ext_feature_table: "
|
||||
"Could not read table");
|
||||
@@ -172,7 +172,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
||||
uext->len = ext.len;
|
||||
QLIST_INSERT_HEAD(&s->unknown_header_ext, uext, next);
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, offset , uext->data, uext->len);
|
||||
ret = bdrv_pread(bs->file, offset , uext->data, uext->len);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "ERROR: unknown extension: "
|
||||
"Could not read data");
|
||||
@@ -249,7 +249,7 @@ int qcow2_mark_dirty(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
val = cpu_to_be64(s->incompatible_features | QCOW2_INCOMPAT_DIRTY);
|
||||
ret = bdrv_pwrite(bs->file->bs, offsetof(QCowHeader, incompatible_features),
|
||||
ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, incompatible_features),
|
||||
&val, sizeof(val));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -817,7 +817,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
uint64_t ext_end;
|
||||
uint64_t l1_vm_state_index;
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, 0, &header, sizeof(header));
|
||||
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not read qcow2 header");
|
||||
goto fail;
|
||||
@@ -892,7 +892,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
if (header.header_length > sizeof(header)) {
|
||||
s->unknown_header_fields_size = header.header_length - sizeof(header);
|
||||
s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);
|
||||
ret = bdrv_pread(bs->file->bs, sizeof(header), s->unknown_header_fields,
|
||||
ret = bdrv_pread(bs->file, sizeof(header), s->unknown_header_fields,
|
||||
s->unknown_header_fields_size);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not read unknown qcow2 header "
|
||||
@@ -980,10 +980,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bs->encrypted = 1;
|
||||
|
||||
/* Encryption works on a sector granularity */
|
||||
bs->request_alignment = BDRV_SECTOR_SIZE;
|
||||
bs->encrypted = true;
|
||||
}
|
||||
|
||||
s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
|
||||
@@ -1069,7 +1066,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
ret = bdrv_pread(bs->file->bs, s->l1_table_offset, s->l1_table,
|
||||
ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table,
|
||||
s->l1_size * sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not read L1 table");
|
||||
@@ -1125,7 +1122,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
ret = bdrv_pread(bs->file->bs, header.backing_file_offset,
|
||||
ret = bdrv_pread(bs->file, header.backing_file_offset,
|
||||
bs->backing_file, len);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not read backing file name");
|
||||
@@ -1202,6 +1199,10 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
|
||||
if (bs->encrypted) {
|
||||
/* Encryption works on a sector granularity */
|
||||
bs->bl.request_alignment = BDRV_SECTOR_SIZE;
|
||||
}
|
||||
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
|
||||
}
|
||||
|
||||
@@ -1442,7 +1443,7 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
ret = bdrv_co_preadv(bs->backing->bs, offset, n1,
|
||||
ret = bdrv_co_preadv(bs->backing, offset, n1,
|
||||
&local_qiov, 0);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
|
||||
@@ -1505,7 +1506,7 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
ret = bdrv_co_preadv(bs->file->bs,
|
||||
ret = bdrv_co_preadv(bs->file,
|
||||
cluster_offset + offset_in_cluster,
|
||||
cur_bytes, &hd_qiov, 0);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
@@ -1636,7 +1637,7 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
|
||||
trace_qcow2_writev_data(qemu_coroutine_self(),
|
||||
cluster_offset + offset_in_cluster);
|
||||
ret = bdrv_co_pwritev(bs->file->bs,
|
||||
ret = bdrv_co_pwritev(bs->file,
|
||||
cluster_offset + offset_in_cluster,
|
||||
cur_bytes, &hd_qiov, 0);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
@@ -1975,7 +1976,7 @@ int qcow2_update_header(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
/* Write the new header */
|
||||
ret = bdrv_pwrite(bs->file->bs, 0, header, s->cluster_size);
|
||||
ret = bdrv_pwrite(bs->file, 0, header, s->cluster_size);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -2058,7 +2059,7 @@ static int preallocate(BlockDriverState *bs)
|
||||
*/
|
||||
if (host_offset != 0) {
|
||||
uint8_t data = 0;
|
||||
ret = bdrv_pwrite(bs->file->bs, (host_offset + cur_bytes) - 1,
|
||||
ret = bdrv_pwrite(bs->file, (host_offset + cur_bytes) - 1,
|
||||
&data, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -2522,7 +2523,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
|
||||
|
||||
/* write updated header.size */
|
||||
offset = cpu_to_be64(offset);
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, offsetof(QCowHeader, size),
|
||||
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
|
||||
&offset, sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -2532,6 +2533,51 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
|
||||
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);
|
||||
qemu_coroutine_enter(co, &data);
|
||||
while (data.ret == -EINPROGRESS) {
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
return data.ret;
|
||||
}
|
||||
|
||||
/* XXX: put compressed sectors first, then all the cluster aligned
|
||||
tables to avoid losing bytes in alignment */
|
||||
static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
@@ -2595,7 +2641,7 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
|
||||
/* could not compress: write normal cluster */
|
||||
ret = bdrv_write(bs, sector_num, buf, s->cluster_sectors);
|
||||
ret = qcow2_write(bs, sector_num, buf, s->cluster_sectors);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -2614,7 +2660,7 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
|
||||
ret = bdrv_pwrite(bs->file->bs, cluster_offset, out_buf, out_len);
|
||||
ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -2663,7 +2709,7 @@ static int make_completely_empty(BlockDriverState *bs)
|
||||
/* After this call, neither the in-memory nor the on-disk refcount
|
||||
* information accurately describe the actual references */
|
||||
|
||||
ret = bdrv_pwrite_zeroes(bs->file->bs, s->l1_table_offset,
|
||||
ret = bdrv_pwrite_zeroes(bs->file, s->l1_table_offset,
|
||||
l1_clusters * s->cluster_size, 0);
|
||||
if (ret < 0) {
|
||||
goto fail_broken_refcounts;
|
||||
@@ -2677,7 +2723,7 @@ static int make_completely_empty(BlockDriverState *bs)
|
||||
* overwrite parts of the existing refcount and L1 table, which is not
|
||||
* an issue because the dirty flag is set, complete data loss is in fact
|
||||
* desired and partial data loss is consequently fine as well */
|
||||
ret = bdrv_pwrite_zeroes(bs->file->bs, s->cluster_size,
|
||||
ret = bdrv_pwrite_zeroes(bs->file, s->cluster_size,
|
||||
(2 + l1_clusters) * s->cluster_size, 0);
|
||||
/* This call (even if it failed overall) may have overwritten on-disk
|
||||
* refcount structures; in that case, the in-memory refcount information
|
||||
@@ -2693,10 +2739,10 @@ static int make_completely_empty(BlockDriverState *bs)
|
||||
/* "Create" an empty reftable (one cluster) directly after the image
|
||||
* header and an empty L1 table three clusters after the image header;
|
||||
* the cluster between those two will be used as the first refblock */
|
||||
cpu_to_be64w(&l1_ofs_rt_ofs_cls.l1_offset, 3 * s->cluster_size);
|
||||
cpu_to_be64w(&l1_ofs_rt_ofs_cls.reftable_offset, s->cluster_size);
|
||||
cpu_to_be32w(&l1_ofs_rt_ofs_cls.reftable_clusters, 1);
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, offsetof(QCowHeader, l1_table_offset),
|
||||
l1_ofs_rt_ofs_cls.l1_offset = cpu_to_be64(3 * s->cluster_size);
|
||||
l1_ofs_rt_ofs_cls.reftable_offset = cpu_to_be64(s->cluster_size);
|
||||
l1_ofs_rt_ofs_cls.reftable_clusters = cpu_to_be32(1);
|
||||
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_table_offset),
|
||||
&l1_ofs_rt_ofs_cls, sizeof(l1_ofs_rt_ofs_cls));
|
||||
if (ret < 0) {
|
||||
goto fail_broken_refcounts;
|
||||
@@ -2727,7 +2773,7 @@ static int make_completely_empty(BlockDriverState *bs)
|
||||
|
||||
/* Enter the first refblock into the reftable */
|
||||
rt_entry = cpu_to_be64(2 * s->cluster_size);
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, s->cluster_size,
|
||||
ret = bdrv_pwrite_sync(bs->file, s->cluster_size,
|
||||
&rt_entry, sizeof(rt_entry));
|
||||
if (ret < 0) {
|
||||
goto fail_broken_refcounts;
|
||||
|
||||
@@ -65,7 +65,7 @@ static void qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
|
||||
read_table_cb->iov.iov_len = s->header.cluster_size * s->header.table_size,
|
||||
|
||||
qemu_iovec_init_external(qiov, &read_table_cb->iov, 1);
|
||||
bdrv_aio_readv(s->bs->file->bs, offset / BDRV_SECTOR_SIZE, qiov,
|
||||
bdrv_aio_readv(s->bs->file, offset / BDRV_SECTOR_SIZE, qiov,
|
||||
qiov->size / BDRV_SECTOR_SIZE,
|
||||
qed_read_table_cb, read_table_cb);
|
||||
}
|
||||
@@ -154,7 +154,7 @@ static void qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
|
||||
/* Adjust for offset into table */
|
||||
offset += start * sizeof(uint64_t);
|
||||
|
||||
bdrv_aio_writev(s->bs->file->bs, offset / BDRV_SECTOR_SIZE,
|
||||
bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
|
||||
&write_table_cb->qiov,
|
||||
write_table_cb->qiov.size / BDRV_SECTOR_SIZE,
|
||||
qed_write_table_cb, write_table_cb);
|
||||
|
||||
22
block/qed.c
22
block/qed.c
@@ -86,7 +86,7 @@ int qed_write_header_sync(BDRVQEDState *s)
|
||||
int ret;
|
||||
|
||||
qed_header_cpu_to_le(&s->header, &le);
|
||||
ret = bdrv_pwrite(s->bs->file->bs, 0, &le, sizeof(le));
|
||||
ret = bdrv_pwrite(s->bs->file, 0, &le, sizeof(le));
|
||||
if (ret != sizeof(le)) {
|
||||
return ret;
|
||||
}
|
||||
@@ -123,7 +123,7 @@ static void qed_write_header_read_cb(void *opaque, int ret)
|
||||
/* Update header */
|
||||
qed_header_cpu_to_le(&s->header, (QEDHeader *)write_header_cb->buf);
|
||||
|
||||
bdrv_aio_writev(s->bs->file->bs, 0, &write_header_cb->qiov,
|
||||
bdrv_aio_writev(s->bs->file, 0, &write_header_cb->qiov,
|
||||
write_header_cb->nsectors, qed_write_header_cb,
|
||||
write_header_cb);
|
||||
}
|
||||
@@ -155,7 +155,7 @@ static void qed_write_header(BDRVQEDState *s, BlockCompletionFunc cb,
|
||||
write_header_cb->iov.iov_len = len;
|
||||
qemu_iovec_init_external(&write_header_cb->qiov, &write_header_cb->iov, 1);
|
||||
|
||||
bdrv_aio_readv(s->bs->file->bs, 0, &write_header_cb->qiov, nsectors,
|
||||
bdrv_aio_readv(s->bs->file, 0, &write_header_cb->qiov, nsectors,
|
||||
qed_write_header_read_cb, write_header_cb);
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ static bool qed_is_image_size_valid(uint64_t image_size, uint32_t cluster_size,
|
||||
*
|
||||
* The string is NUL-terminated.
|
||||
*/
|
||||
static int qed_read_string(BlockDriverState *file, uint64_t offset, size_t n,
|
||||
static int qed_read_string(BdrvChild *file, uint64_t offset, size_t n,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
int ret;
|
||||
@@ -389,7 +389,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
s->bs = bs;
|
||||
QSIMPLEQ_INIT(&s->allocating_write_reqs);
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, 0, &le_header, sizeof(le_header));
|
||||
ret = bdrv_pread(bs->file, 0, &le_header, sizeof(le_header));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -446,7 +446,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = qed_read_string(bs->file->bs, s->header.backing_filename_offset,
|
||||
ret = qed_read_string(bs->file, s->header.backing_filename_offset,
|
||||
s->header.backing_filename_size, bs->backing_file,
|
||||
sizeof(bs->backing_file));
|
||||
if (ret < 0) {
|
||||
@@ -800,7 +800,7 @@ static void qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
|
||||
qemu_iovec_concat(*backing_qiov, qiov, 0, size);
|
||||
|
||||
BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO);
|
||||
bdrv_aio_readv(s->bs->backing->bs, pos / BDRV_SECTOR_SIZE,
|
||||
bdrv_aio_readv(s->bs->backing, pos / BDRV_SECTOR_SIZE,
|
||||
*backing_qiov, size / BDRV_SECTOR_SIZE, cb, opaque);
|
||||
}
|
||||
|
||||
@@ -837,7 +837,7 @@ static void qed_copy_from_backing_file_write(void *opaque, int ret)
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(s->bs->file, BLKDBG_COW_WRITE);
|
||||
bdrv_aio_writev(s->bs->file->bs, copy_cb->offset / BDRV_SECTOR_SIZE,
|
||||
bdrv_aio_writev(s->bs->file, copy_cb->offset / BDRV_SECTOR_SIZE,
|
||||
©_cb->qiov, copy_cb->qiov.size / BDRV_SECTOR_SIZE,
|
||||
qed_copy_from_backing_file_cb, copy_cb);
|
||||
}
|
||||
@@ -1087,7 +1087,7 @@ static void qed_aio_write_main(void *opaque, int ret)
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(s->bs->file, BLKDBG_WRITE_AIO);
|
||||
bdrv_aio_writev(s->bs->file->bs, offset / BDRV_SECTOR_SIZE,
|
||||
bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
|
||||
&acb->cur_qiov, acb->cur_qiov.size / BDRV_SECTOR_SIZE,
|
||||
next_fn, acb);
|
||||
}
|
||||
@@ -1319,7 +1319,7 @@ static void qed_aio_read_data(void *opaque, int ret,
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
|
||||
bdrv_aio_readv(bs->file->bs, offset / BDRV_SECTOR_SIZE,
|
||||
bdrv_aio_readv(bs->file, offset / BDRV_SECTOR_SIZE,
|
||||
&acb->cur_qiov, acb->cur_qiov.size / BDRV_SECTOR_SIZE,
|
||||
qed_aio_next_io, acb);
|
||||
return;
|
||||
@@ -1575,7 +1575,7 @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
/* Write new header */
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, 0, buffer, buffer_len);
|
||||
ret = bdrv_pwrite_sync(bs->file, 0, buffer, buffer_len);
|
||||
g_free(buffer);
|
||||
if (ret == 0) {
|
||||
memcpy(&s->header, &new_header, sizeof(new_header));
|
||||
|
||||
@@ -383,7 +383,7 @@ static bool quorum_rewrite_bad_versions(BDRVQuorumState *s, QuorumAIOCB *acb,
|
||||
continue;
|
||||
}
|
||||
QLIST_FOREACH(item, &version->items, next) {
|
||||
bdrv_aio_writev(s->children[item->index]->bs, acb->sector_num,
|
||||
bdrv_aio_writev(s->children[item->index], acb->sector_num,
|
||||
acb->qiov, acb->nb_sectors, quorum_rewrite_aio_cb,
|
||||
acb);
|
||||
}
|
||||
@@ -660,7 +660,7 @@ static BlockAIOCB *read_quorum_children(QuorumAIOCB *acb)
|
||||
}
|
||||
|
||||
for (i = 0; i < s->num_children; i++) {
|
||||
acb->qcrs[i].aiocb = bdrv_aio_readv(s->children[i]->bs, acb->sector_num,
|
||||
acb->qcrs[i].aiocb = bdrv_aio_readv(s->children[i], acb->sector_num,
|
||||
&acb->qcrs[i].qiov, acb->nb_sectors,
|
||||
quorum_aio_cb, &acb->qcrs[i]);
|
||||
}
|
||||
@@ -678,7 +678,7 @@ static BlockAIOCB *read_fifo_child(QuorumAIOCB *acb)
|
||||
qemu_iovec_clone(&acb->qcrs[acb->child_iter].qiov, acb->qiov,
|
||||
acb->qcrs[acb->child_iter].buf);
|
||||
acb->qcrs[acb->child_iter].aiocb =
|
||||
bdrv_aio_readv(s->children[acb->child_iter]->bs, acb->sector_num,
|
||||
bdrv_aio_readv(s->children[acb->child_iter], acb->sector_num,
|
||||
&acb->qcrs[acb->child_iter].qiov, acb->nb_sectors,
|
||||
quorum_aio_cb, &acb->qcrs[acb->child_iter]);
|
||||
|
||||
@@ -719,7 +719,7 @@ static BlockAIOCB *quorum_aio_writev(BlockDriverState *bs,
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->num_children; i++) {
|
||||
acb->qcrs[i].aiocb = bdrv_aio_writev(s->children[i]->bs, sector_num,
|
||||
acb->qcrs[i].aiocb = bdrv_aio_writev(s->children[i], sector_num,
|
||||
qiov, nb_sectors, &quorum_aio_cb,
|
||||
&acb->qcrs[i]);
|
||||
}
|
||||
|
||||
@@ -302,22 +302,22 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
|
||||
/* For SCSI generic devices the alignment is not really used.
|
||||
With buffered I/O, we don't have any restrictions. */
|
||||
if (bdrv_is_sg(bs) || !s->needs_alignment) {
|
||||
bs->request_alignment = 1;
|
||||
bs->bl.request_alignment = 1;
|
||||
s->buf_align = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
bs->request_alignment = 0;
|
||||
bs->bl.request_alignment = 0;
|
||||
s->buf_align = 0;
|
||||
/* Let's try to use the logical blocksize for the alignment. */
|
||||
if (probe_logical_blocksize(fd, &bs->request_alignment) < 0) {
|
||||
bs->request_alignment = 0;
|
||||
if (probe_logical_blocksize(fd, &bs->bl.request_alignment) < 0) {
|
||||
bs->bl.request_alignment = 0;
|
||||
}
|
||||
#ifdef CONFIG_XFS
|
||||
if (s->is_xfs) {
|
||||
struct dioattr da;
|
||||
if (xfsctl(NULL, fd, XFS_IOC_DIOINFO, &da) >= 0) {
|
||||
bs->request_alignment = da.d_miniosz;
|
||||
bs->bl.request_alignment = da.d_miniosz;
|
||||
/* The kernel returns wrong information for d_mem */
|
||||
/* s->buf_align = da.d_mem; */
|
||||
}
|
||||
@@ -337,21 +337,21 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
|
||||
qemu_vfree(buf);
|
||||
}
|
||||
|
||||
if (!bs->request_alignment) {
|
||||
if (!bs->bl.request_alignment) {
|
||||
size_t align;
|
||||
buf = qemu_memalign(s->buf_align, max_align);
|
||||
for (align = 512; align <= max_align; align <<= 1) {
|
||||
if (raw_is_io_aligned(fd, buf, align)) {
|
||||
bs->request_alignment = align;
|
||||
bs->bl.request_alignment = align;
|
||||
break;
|
||||
}
|
||||
}
|
||||
qemu_vfree(buf);
|
||||
}
|
||||
|
||||
if (!s->buf_align || !bs->request_alignment) {
|
||||
error_setg(errp, "Could not find working O_DIRECT alignment. "
|
||||
"Try cache.direct=off.");
|
||||
if (!s->buf_align || !bs->bl.request_alignment) {
|
||||
error_setg(errp, "Could not find working O_DIRECT alignment");
|
||||
error_append_hint(errp, "Try cache.direct=off\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -745,8 +745,8 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
if (!fstat(s->fd, &st)) {
|
||||
if (S_ISBLK(st.st_mode)) {
|
||||
int ret = hdev_get_max_transfer_length(s->fd);
|
||||
if (ret >= 0) {
|
||||
bs->bl.max_transfer_length = ret;
|
||||
if (ret > 0 && ret <= BDRV_REQUEST_MAX_SECTORS) {
|
||||
bs->bl.max_transfer = pow2floor(ret << BDRV_SECTOR_BITS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ static void raw_attach_aio_context(BlockDriverState *bs,
|
||||
}
|
||||
}
|
||||
|
||||
static void raw_probe_alignment(BlockDriverState *bs)
|
||||
static void raw_probe_alignment(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
DWORD sectorsPerCluster, freeClusters, totalClusters, count;
|
||||
@@ -230,14 +230,14 @@ static void raw_probe_alignment(BlockDriverState *bs)
|
||||
BOOL status;
|
||||
|
||||
if (s->type == FTYPE_CD) {
|
||||
bs->request_alignment = 2048;
|
||||
bs->bl.request_alignment = 2048;
|
||||
return;
|
||||
}
|
||||
if (s->type == FTYPE_HARDDISK) {
|
||||
status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
|
||||
NULL, 0, &dg, sizeof(dg), &count, NULL);
|
||||
if (status != 0) {
|
||||
bs->request_alignment = dg.Geometry.BytesPerSector;
|
||||
bs->bl.request_alignment = dg.Geometry.BytesPerSector;
|
||||
return;
|
||||
}
|
||||
/* try GetDiskFreeSpace too */
|
||||
@@ -247,7 +247,7 @@ static void raw_probe_alignment(BlockDriverState *bs)
|
||||
GetDiskFreeSpace(s->drive_path, §orsPerCluster,
|
||||
&dg.Geometry.BytesPerSector,
|
||||
&freeClusters, &totalClusters);
|
||||
bs->request_alignment = dg.Geometry.BytesPerSector;
|
||||
bs->bl.request_alignment = dg.Geometry.BytesPerSector;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,7 +365,6 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
win32_aio_attach_aio_context(s->aio, bdrv_get_aio_context(bs));
|
||||
}
|
||||
|
||||
raw_probe_alignment(bs);
|
||||
ret = 0;
|
||||
fail:
|
||||
qemu_opts_del(opts);
|
||||
@@ -550,6 +549,7 @@ BlockDriver bdrv_file = {
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_parse_filename = raw_parse_filename,
|
||||
.bdrv_file_open = raw_open,
|
||||
.bdrv_refresh_limits = raw_probe_alignment,
|
||||
.bdrv_close = raw_close,
|
||||
.bdrv_create = raw_create,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* BlockDriver implementation for "raw"
|
||||
*
|
||||
* Copyright (C) 2010, 2013, Red Hat, Inc.
|
||||
* Copyright (C) 2010-2016 Red Hat, Inc.
|
||||
* Copyright (C) 2010, Blue Swirl <blauwirbel@gmail.com>
|
||||
* Copyright (C) 2009, Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
@@ -54,7 +54,7 @@ static int coroutine_fn raw_co_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
int nb_sectors, QEMUIOVector *qiov)
|
||||
{
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
|
||||
return bdrv_co_readv(bs->file->bs, sector_num, nb_sectors, qiov);
|
||||
return bdrv_co_readv(bs->file, sector_num, nb_sectors, qiov);
|
||||
}
|
||||
|
||||
static int coroutine_fn
|
||||
@@ -105,7 +105,7 @@ raw_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
|
||||
ret = bdrv_co_pwritev(bs->file->bs, sector_num * BDRV_SECTOR_SIZE,
|
||||
ret = bdrv_co_pwritev(bs->file, sector_num * BDRV_SECTOR_SIZE,
|
||||
nb_sectors * BDRV_SECTOR_SIZE, qiov, flags);
|
||||
|
||||
fail:
|
||||
@@ -131,7 +131,7 @@ static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
|
||||
int64_t offset, int count,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
return bdrv_co_pwrite_zeroes(bs->file->bs, offset, count, flags);
|
||||
return bdrv_co_pwrite_zeroes(bs->file, offset, count, flags);
|
||||
}
|
||||
|
||||
static int coroutine_fn raw_co_discard(BlockDriverState *bs,
|
||||
@@ -150,11 +150,6 @@ static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
return bdrv_get_info(bs->file->bs, bdi);
|
||||
}
|
||||
|
||||
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
bs->bl = bs->file->bs->bl;
|
||||
}
|
||||
|
||||
static int raw_truncate(BlockDriverState *bs, int64_t offset)
|
||||
{
|
||||
return bdrv_truncate(bs->file->bs, offset);
|
||||
@@ -252,7 +247,6 @@ BlockDriver bdrv_raw = {
|
||||
.bdrv_getlength = &raw_getlength,
|
||||
.has_variable_length = true,
|
||||
.bdrv_get_info = &raw_get_info,
|
||||
.bdrv_refresh_limits = &raw_refresh_limits,
|
||||
.bdrv_probe_blocksizes = &raw_probe_blocksizes,
|
||||
.bdrv_probe_geometry = &raw_probe_geometry,
|
||||
.bdrv_media_changed = &raw_media_changed,
|
||||
|
||||
14
block/vdi.c
14
block/vdi.c
@@ -403,7 +403,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
logout("\n");
|
||||
|
||||
ret = bdrv_read(bs->file->bs, 0, (uint8_t *)&header, 1);
|
||||
ret = bdrv_read(bs->file, 0, (uint8_t *)&header, 1);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -500,7 +500,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_read(bs->file->bs, s->bmap_sector, (uint8_t *)s->bmap,
|
||||
ret = bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap,
|
||||
bmap_size);
|
||||
if (ret < 0) {
|
||||
goto fail_free_bmap;
|
||||
@@ -597,7 +597,7 @@ vdi_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
qemu_iovec_reset(&local_qiov);
|
||||
qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
|
||||
|
||||
ret = bdrv_co_preadv(bs->file->bs, data_offset, n_bytes,
|
||||
ret = bdrv_co_preadv(bs->file, data_offset, n_bytes,
|
||||
&local_qiov, 0);
|
||||
}
|
||||
logout("%u bytes read\n", n_bytes);
|
||||
@@ -670,7 +670,7 @@ vdi_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
* acquire the lock and thus the padded cluster is written before
|
||||
* the other coroutines can write to the affected area. */
|
||||
qemu_co_mutex_lock(&s->write_lock);
|
||||
ret = bdrv_pwrite(bs->file->bs, data_offset, block, s->block_size);
|
||||
ret = bdrv_pwrite(bs->file, data_offset, block, s->block_size);
|
||||
qemu_co_mutex_unlock(&s->write_lock);
|
||||
} else {
|
||||
uint64_t data_offset = s->header.offset_data +
|
||||
@@ -690,7 +690,7 @@ vdi_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
qemu_iovec_reset(&local_qiov);
|
||||
qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
|
||||
|
||||
ret = bdrv_co_pwritev(bs->file->bs, data_offset, n_bytes,
|
||||
ret = bdrv_co_pwritev(bs->file, data_offset, n_bytes,
|
||||
&local_qiov, 0);
|
||||
}
|
||||
|
||||
@@ -719,7 +719,7 @@ vdi_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
assert(VDI_IS_ALLOCATED(bmap_first));
|
||||
*header = s->header;
|
||||
vdi_header_to_le(header);
|
||||
ret = bdrv_write(bs->file->bs, 0, block, 1);
|
||||
ret = bdrv_write(bs->file, 0, block, 1);
|
||||
g_free(block);
|
||||
block = NULL;
|
||||
|
||||
@@ -737,7 +737,7 @@ vdi_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE;
|
||||
logout("will write %u block map sectors starting from entry %u\n",
|
||||
n_sectors, bmap_first);
|
||||
ret = bdrv_write(bs->file->bs, offset, base, n_sectors);
|
||||
ret = bdrv_write(bs->file, offset, base, n_sectors);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -84,7 +84,7 @@ static int vhdx_log_peek_hdr(BlockDriverState *bs, VHDXLogEntries *log,
|
||||
|
||||
offset = log->offset + read;
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, offset, hdr, sizeof(VHDXLogEntryHeader));
|
||||
ret = bdrv_pread(bs->file, offset, hdr, sizeof(VHDXLogEntryHeader));
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
@@ -144,7 +144,7 @@ static int vhdx_log_read_sectors(BlockDriverState *bs, VHDXLogEntries *log,
|
||||
}
|
||||
offset = log->offset + read;
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, offset, buffer, VHDX_LOG_SECTOR_SIZE);
|
||||
ret = bdrv_pread(bs->file, offset, buffer, VHDX_LOG_SECTOR_SIZE);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
@@ -194,7 +194,7 @@ static int vhdx_log_write_sectors(BlockDriverState *bs, VHDXLogEntries *log,
|
||||
/* full */
|
||||
break;
|
||||
}
|
||||
ret = bdrv_pwrite(bs->file->bs, offset, buffer_tmp,
|
||||
ret = bdrv_pwrite(bs->file, offset, buffer_tmp,
|
||||
VHDX_LOG_SECTOR_SIZE);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
@@ -466,7 +466,7 @@ static int vhdx_log_flush_desc(BlockDriverState *bs, VHDXLogDescriptor *desc,
|
||||
|
||||
/* count is only > 1 if we are writing zeroes */
|
||||
for (i = 0; i < count; i++) {
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, file_offset, buffer,
|
||||
ret = bdrv_pwrite_sync(bs->file, file_offset, buffer,
|
||||
VHDX_LOG_SECTOR_SIZE);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
@@ -945,7 +945,7 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
|
||||
if (i == 0 && leading_length) {
|
||||
/* partial sector at the front of the buffer */
|
||||
ret = bdrv_pread(bs->file->bs, file_offset, merged_sector,
|
||||
ret = bdrv_pread(bs->file, file_offset, merged_sector,
|
||||
VHDX_LOG_SECTOR_SIZE);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
@@ -955,7 +955,7 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
sector_write = merged_sector;
|
||||
} else if (i == sectors - 1 && trailing_length) {
|
||||
/* partial sector at the end of the buffer */
|
||||
ret = bdrv_pread(bs->file->bs,
|
||||
ret = bdrv_pread(bs->file,
|
||||
file_offset,
|
||||
merged_sector + trailing_length,
|
||||
VHDX_LOG_SECTOR_SIZE - trailing_length);
|
||||
|
||||
85
block/vhdx.c
85
block/vhdx.c
@@ -298,9 +298,10 @@ static int vhdx_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||
* and then update the header checksum. Header is converted to proper
|
||||
* endianness before being written to the specified file offset
|
||||
*/
|
||||
static int vhdx_write_header(BlockDriverState *bs_file, VHDXHeader *hdr,
|
||||
static int vhdx_write_header(BdrvChild *file, VHDXHeader *hdr,
|
||||
uint64_t offset, bool read)
|
||||
{
|
||||
BlockDriverState *bs_file = file->bs;
|
||||
uint8_t *buffer = NULL;
|
||||
int ret;
|
||||
VHDXHeader *header_le;
|
||||
@@ -315,7 +316,7 @@ static int vhdx_write_header(BlockDriverState *bs_file, VHDXHeader *hdr,
|
||||
buffer = qemu_blockalign(bs_file, VHDX_HEADER_SIZE);
|
||||
if (read) {
|
||||
/* if true, we can't assume the extra reserved bytes are 0 */
|
||||
ret = bdrv_pread(bs_file, offset, buffer, VHDX_HEADER_SIZE);
|
||||
ret = bdrv_pread(file, offset, buffer, VHDX_HEADER_SIZE);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
@@ -329,7 +330,7 @@ static int vhdx_write_header(BlockDriverState *bs_file, VHDXHeader *hdr,
|
||||
vhdx_header_le_export(hdr, header_le);
|
||||
vhdx_update_checksum(buffer, VHDX_HEADER_SIZE,
|
||||
offsetof(VHDXHeader, checksum));
|
||||
ret = bdrv_pwrite_sync(bs_file, offset, header_le, sizeof(VHDXHeader));
|
||||
ret = bdrv_pwrite_sync(file, offset, header_le, sizeof(VHDXHeader));
|
||||
|
||||
exit:
|
||||
qemu_vfree(buffer);
|
||||
@@ -378,7 +379,7 @@ static int vhdx_update_header(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
inactive_header->log_guid = *log_guid;
|
||||
}
|
||||
|
||||
ret = vhdx_write_header(bs->file->bs, inactive_header, header_offset, true);
|
||||
ret = vhdx_write_header(bs->file, inactive_header, header_offset, true);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
@@ -430,7 +431,7 @@ static void vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
/* We have to read the whole VHDX_HEADER_SIZE instead of
|
||||
* sizeof(VHDXHeader), because the checksum is over the whole
|
||||
* region */
|
||||
ret = bdrv_pread(bs->file->bs, VHDX_HEADER1_OFFSET, buffer,
|
||||
ret = bdrv_pread(bs->file, VHDX_HEADER1_OFFSET, buffer,
|
||||
VHDX_HEADER_SIZE);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -447,7 +448,7 @@ static void vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
}
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, VHDX_HEADER2_OFFSET, buffer,
|
||||
ret = bdrv_pread(bs->file, VHDX_HEADER2_OFFSET, buffer,
|
||||
VHDX_HEADER_SIZE);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -521,7 +522,7 @@ static int vhdx_open_region_tables(BlockDriverState *bs, BDRVVHDXState *s)
|
||||
* whole block */
|
||||
buffer = qemu_blockalign(bs, VHDX_HEADER_BLOCK_SIZE);
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, VHDX_REGION_TABLE_OFFSET, buffer,
|
||||
ret = bdrv_pread(bs->file, VHDX_REGION_TABLE_OFFSET, buffer,
|
||||
VHDX_HEADER_BLOCK_SIZE);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -634,7 +635,7 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
|
||||
|
||||
buffer = qemu_blockalign(bs, VHDX_METADATA_TABLE_MAX_SIZE);
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, s->metadata_rt.file_offset, buffer,
|
||||
ret = bdrv_pread(bs->file, s->metadata_rt.file_offset, buffer,
|
||||
VHDX_METADATA_TABLE_MAX_SIZE);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
@@ -737,7 +738,7 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs,
|
||||
ret = bdrv_pread(bs->file,
|
||||
s->metadata_entries.file_parameters_entry.offset
|
||||
+ s->metadata_rt.file_offset,
|
||||
&s->params,
|
||||
@@ -772,7 +773,7 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
|
||||
/* determine virtual disk size, logical sector size,
|
||||
* and phys sector size */
|
||||
|
||||
ret = bdrv_pread(bs->file->bs,
|
||||
ret = bdrv_pread(bs->file,
|
||||
s->metadata_entries.virtual_disk_size_entry.offset
|
||||
+ s->metadata_rt.file_offset,
|
||||
&s->virtual_disk_size,
|
||||
@@ -780,7 +781,7 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
ret = bdrv_pread(bs->file->bs,
|
||||
ret = bdrv_pread(bs->file,
|
||||
s->metadata_entries.logical_sector_size_entry.offset
|
||||
+ s->metadata_rt.file_offset,
|
||||
&s->logical_sector_size,
|
||||
@@ -788,7 +789,7 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
ret = bdrv_pread(bs->file->bs,
|
||||
ret = bdrv_pread(bs->file,
|
||||
s->metadata_entries.phys_sector_size_entry.offset
|
||||
+ s->metadata_rt.file_offset,
|
||||
&s->physical_sector_size,
|
||||
@@ -905,7 +906,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
QLIST_INIT(&s->regions);
|
||||
|
||||
/* validate the file signature */
|
||||
ret = bdrv_pread(bs->file->bs, 0, &signature, sizeof(uint64_t));
|
||||
ret = bdrv_pread(bs->file, 0, &signature, sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -964,7 +965,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, s->bat_offset, s->bat, s->bat_rt.length);
|
||||
ret = bdrv_pread(bs->file, s->bat_offset, s->bat, s->bat_rt.length);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -1117,7 +1118,7 @@ static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
break;
|
||||
case PAYLOAD_BLOCK_FULLY_PRESENT:
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
ret = bdrv_co_readv(bs->file->bs,
|
||||
ret = bdrv_co_readv(bs->file,
|
||||
sinfo.file_offset >> BDRV_SECTOR_BITS,
|
||||
sinfo.sectors_avail, &hd_qiov);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
@@ -1326,7 +1327,7 @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
}
|
||||
/* block exists, so we can just overwrite it */
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
ret = bdrv_co_writev(bs->file->bs,
|
||||
ret = bdrv_co_writev(bs->file,
|
||||
sinfo.file_offset >> BDRV_SECTOR_BITS,
|
||||
sectors_to_write, &hd_qiov);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
@@ -1387,9 +1388,11 @@ exit:
|
||||
* There are 2 headers, and the highest sequence number will represent
|
||||
* the active header
|
||||
*/
|
||||
static int vhdx_create_new_headers(BlockDriverState *bs, uint64_t image_size,
|
||||
static int vhdx_create_new_headers(BlockBackend *blk, uint64_t image_size,
|
||||
uint32_t log_size)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
BdrvChild *child;
|
||||
int ret = 0;
|
||||
VHDXHeader *hdr = NULL;
|
||||
|
||||
@@ -1404,12 +1407,18 @@ static int vhdx_create_new_headers(BlockDriverState *bs, uint64_t image_size,
|
||||
vhdx_guid_generate(&hdr->file_write_guid);
|
||||
vhdx_guid_generate(&hdr->data_write_guid);
|
||||
|
||||
ret = vhdx_write_header(bs, hdr, VHDX_HEADER1_OFFSET, false);
|
||||
/* XXX Ugly way to get blk->root, but that's a feature, not a bug. This
|
||||
* hack makes it obvious that vhdx_write_header() bypasses the BlockBackend
|
||||
* here, which it really shouldn't be doing. */
|
||||
child = QLIST_FIRST(&bs->parents);
|
||||
assert(!QLIST_NEXT(child, next_parent));
|
||||
|
||||
ret = vhdx_write_header(child, hdr, VHDX_HEADER1_OFFSET, false);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
hdr->sequence_number++;
|
||||
ret = vhdx_write_header(bs, hdr, VHDX_HEADER2_OFFSET, false);
|
||||
ret = vhdx_write_header(child, hdr, VHDX_HEADER2_OFFSET, false);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
@@ -1442,7 +1451,7 @@ exit:
|
||||
* The first 64KB of the Metadata section is reserved for the metadata
|
||||
* header and entries; beyond that, the metadata items themselves reside.
|
||||
*/
|
||||
static int vhdx_create_new_metadata(BlockDriverState *bs,
|
||||
static int vhdx_create_new_metadata(BlockBackend *blk,
|
||||
uint64_t image_size,
|
||||
uint32_t block_size,
|
||||
uint32_t sector_size,
|
||||
@@ -1538,13 +1547,13 @@ static int vhdx_create_new_metadata(BlockDriverState *bs,
|
||||
VHDX_META_FLAGS_IS_VIRTUAL_DISK;
|
||||
vhdx_metadata_entry_le_export(&md_table_entry[4]);
|
||||
|
||||
ret = bdrv_pwrite(bs, metadata_offset, buffer, VHDX_HEADER_BLOCK_SIZE);
|
||||
ret = blk_pwrite(blk, metadata_offset, buffer, VHDX_HEADER_BLOCK_SIZE, 0);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite(bs, metadata_offset + (64 * KiB), entry_buffer,
|
||||
VHDX_METADATA_ENTRY_BUFFER_SIZE);
|
||||
ret = blk_pwrite(blk, metadata_offset + (64 * KiB), entry_buffer,
|
||||
VHDX_METADATA_ENTRY_BUFFER_SIZE, 0);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
@@ -1564,7 +1573,7 @@ exit:
|
||||
* Fixed images: default state of the BAT is fully populated, with
|
||||
* file offsets and state PAYLOAD_BLOCK_FULLY_PRESENT.
|
||||
*/
|
||||
static int vhdx_create_bat(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
|
||||
uint64_t image_size, VHDXImageType type,
|
||||
bool use_zero_blocks, uint64_t file_offset,
|
||||
uint32_t length)
|
||||
@@ -1588,12 +1597,12 @@ static int vhdx_create_bat(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
if (type == VHDX_TYPE_DYNAMIC) {
|
||||
/* All zeroes, so we can just extend the file - the end of the BAT
|
||||
* is the furthest thing we have written yet */
|
||||
ret = bdrv_truncate(bs, data_file_offset);
|
||||
ret = blk_truncate(blk, data_file_offset);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
} else if (type == VHDX_TYPE_FIXED) {
|
||||
ret = bdrv_truncate(bs, data_file_offset + image_size);
|
||||
ret = blk_truncate(blk, data_file_offset + image_size);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
@@ -1604,7 +1613,7 @@ static int vhdx_create_bat(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
|
||||
if (type == VHDX_TYPE_FIXED ||
|
||||
use_zero_blocks ||
|
||||
bdrv_has_zero_init(bs) == 0) {
|
||||
bdrv_has_zero_init(blk_bs(blk)) == 0) {
|
||||
/* for a fixed file, the default BAT entry is not zero */
|
||||
s->bat = g_try_malloc0(length);
|
||||
if (length && s->bat == NULL) {
|
||||
@@ -1620,12 +1629,12 @@ static int vhdx_create_bat(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
sinfo.file_offset = data_file_offset +
|
||||
(sector_num << s->logical_sector_size_bits);
|
||||
sinfo.file_offset = ROUND_UP(sinfo.file_offset, MiB);
|
||||
vhdx_update_bat_table_entry(bs, s, &sinfo, &unused, &unused,
|
||||
vhdx_update_bat_table_entry(blk_bs(blk), s, &sinfo, &unused, &unused,
|
||||
block_state);
|
||||
cpu_to_le64s(&s->bat[sinfo.bat_idx]);
|
||||
sector_num += s->sectors_per_block;
|
||||
}
|
||||
ret = bdrv_pwrite(bs, file_offset, s->bat, length);
|
||||
ret = blk_pwrite(blk, file_offset, s->bat, length, 0);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
@@ -1645,7 +1654,7 @@ exit:
|
||||
* to create the BAT itself, we will also cause the BAT to be
|
||||
* created.
|
||||
*/
|
||||
static int vhdx_create_new_region_table(BlockDriverState *bs,
|
||||
static int vhdx_create_new_region_table(BlockBackend *blk,
|
||||
uint64_t image_size,
|
||||
uint32_t block_size,
|
||||
uint32_t sector_size,
|
||||
@@ -1720,21 +1729,21 @@ static int vhdx_create_new_region_table(BlockDriverState *bs,
|
||||
|
||||
/* The region table gives us the data we need to create the BAT,
|
||||
* so do that now */
|
||||
ret = vhdx_create_bat(bs, s, image_size, type, use_zero_blocks,
|
||||
ret = vhdx_create_bat(blk, s, image_size, type, use_zero_blocks,
|
||||
bat_file_offset, bat_length);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Now write out the region headers to disk */
|
||||
ret = bdrv_pwrite(bs, VHDX_REGION_TABLE_OFFSET, buffer,
|
||||
VHDX_HEADER_BLOCK_SIZE);
|
||||
ret = blk_pwrite(blk, VHDX_REGION_TABLE_OFFSET, buffer,
|
||||
VHDX_HEADER_BLOCK_SIZE, 0);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite(bs, VHDX_REGION_TABLE2_OFFSET, buffer,
|
||||
VHDX_HEADER_BLOCK_SIZE);
|
||||
ret = blk_pwrite(blk, VHDX_REGION_TABLE2_OFFSET, buffer,
|
||||
VHDX_HEADER_BLOCK_SIZE, 0);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
@@ -1871,13 +1880,13 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
|
||||
|
||||
/* Creates (B),(C) */
|
||||
ret = vhdx_create_new_headers(blk_bs(blk), image_size, log_size);
|
||||
ret = vhdx_create_new_headers(blk, image_size, log_size);
|
||||
if (ret < 0) {
|
||||
goto delete_and_exit;
|
||||
}
|
||||
|
||||
/* Creates (D),(E),(G) explicitly. (F) created as by-product */
|
||||
ret = vhdx_create_new_region_table(blk_bs(blk), image_size, block_size, 512,
|
||||
ret = vhdx_create_new_region_table(blk, image_size, block_size, 512,
|
||||
log_size, use_zero_blocks, image_type,
|
||||
&metadata_offset);
|
||||
if (ret < 0) {
|
||||
@@ -1885,7 +1894,7 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
}
|
||||
|
||||
/* Creates (H) */
|
||||
ret = vhdx_create_new_metadata(blk_bs(blk), image_size, block_size, 512,
|
||||
ret = vhdx_create_new_metadata(blk, image_size, block_size, 512,
|
||||
metadata_offset, image_type);
|
||||
if (ret < 0) {
|
||||
goto delete_and_exit;
|
||||
|
||||
54
block/vmdk.c
54
block/vmdk.c
@@ -252,7 +252,7 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
|
||||
int ret;
|
||||
|
||||
desc = g_malloc0(DESC_SIZE);
|
||||
ret = bdrv_pread(bs->file->bs, s->desc_offset, desc, DESC_SIZE);
|
||||
ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
|
||||
if (ret < 0) {
|
||||
g_free(desc);
|
||||
return 0;
|
||||
@@ -286,7 +286,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
|
||||
|
||||
desc = g_malloc0(DESC_SIZE);
|
||||
tmp_desc = g_malloc0(DESC_SIZE);
|
||||
ret = bdrv_pread(bs->file->bs, s->desc_offset, desc, DESC_SIZE);
|
||||
ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
@@ -306,7 +306,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
|
||||
pstrcat(desc, DESC_SIZE, tmp_desc);
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, s->desc_offset, desc, DESC_SIZE);
|
||||
ret = bdrv_pwrite_sync(bs->file, s->desc_offset, desc, DESC_SIZE);
|
||||
|
||||
out:
|
||||
g_free(desc);
|
||||
@@ -350,7 +350,7 @@ static int vmdk_parent_open(BlockDriverState *bs)
|
||||
int ret;
|
||||
|
||||
desc = g_malloc0(DESC_SIZE + 1);
|
||||
ret = bdrv_pread(bs->file->bs, s->desc_offset, desc, DESC_SIZE);
|
||||
ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
@@ -454,7 +454,7 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(extent->file->bs,
|
||||
ret = bdrv_pread(extent->file,
|
||||
extent->l1_table_offset,
|
||||
extent->l1_table,
|
||||
l1_size);
|
||||
@@ -474,7 +474,7 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
|
||||
ret = -ENOMEM;
|
||||
goto fail_l1;
|
||||
}
|
||||
ret = bdrv_pread(extent->file->bs,
|
||||
ret = bdrv_pread(extent->file,
|
||||
extent->l1_backup_table_offset,
|
||||
extent->l1_backup_table,
|
||||
l1_size);
|
||||
@@ -508,7 +508,7 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
|
||||
VMDK3Header header;
|
||||
VmdkExtent *extent;
|
||||
|
||||
ret = bdrv_pread(file->bs, sizeof(magic), &header, sizeof(header));
|
||||
ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret,
|
||||
"Could not read header from file '%s'",
|
||||
@@ -538,14 +538,13 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
|
||||
static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
|
||||
QDict *options, Error **errp);
|
||||
|
||||
static char *vmdk_read_desc(BlockDriverState *file, uint64_t desc_offset,
|
||||
Error **errp)
|
||||
static char *vmdk_read_desc(BdrvChild *file, uint64_t desc_offset, Error **errp)
|
||||
{
|
||||
int64_t size;
|
||||
char *buf;
|
||||
int ret;
|
||||
|
||||
size = bdrv_getlength(file);
|
||||
size = bdrv_getlength(file->bs);
|
||||
if (size < 0) {
|
||||
error_setg_errno(errp, -size, "Could not access file");
|
||||
return NULL;
|
||||
@@ -586,7 +585,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
||||
int64_t l1_backup_offset = 0;
|
||||
bool compressed;
|
||||
|
||||
ret = bdrv_pread(file->bs, sizeof(magic), &header, sizeof(header));
|
||||
ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret,
|
||||
"Could not read header from file '%s'",
|
||||
@@ -596,7 +595,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
||||
if (header.capacity == 0) {
|
||||
uint64_t desc_offset = le64_to_cpu(header.desc_offset);
|
||||
if (desc_offset) {
|
||||
char *buf = vmdk_read_desc(file->bs, desc_offset << 9, errp);
|
||||
char *buf = vmdk_read_desc(file, desc_offset << 9, errp);
|
||||
if (!buf) {
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -636,7 +635,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
||||
} QEMU_PACKED eos_marker;
|
||||
} QEMU_PACKED footer;
|
||||
|
||||
ret = bdrv_pread(file->bs,
|
||||
ret = bdrv_pread(file,
|
||||
bs->file->bs->total_sectors * 512 - 1536,
|
||||
&footer, sizeof(footer));
|
||||
if (ret < 0) {
|
||||
@@ -874,7 +873,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
||||
extent->flat_start_offset = flat_offset << 9;
|
||||
} else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) {
|
||||
/* SPARSE extent and VMFSSPARSE extent are both "COWD" sparse file*/
|
||||
char *buf = vmdk_read_desc(extent_file->bs, 0, errp);
|
||||
char *buf = vmdk_read_desc(extent_file, 0, errp);
|
||||
if (!buf) {
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
@@ -943,7 +942,7 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
uint32_t magic;
|
||||
|
||||
buf = vmdk_read_desc(bs->file->bs, 0, errp);
|
||||
buf = vmdk_read_desc(bs->file, 0, errp);
|
||||
if (!buf) {
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1046,14 +1045,14 @@ static int get_whole_cluster(BlockDriverState *bs,
|
||||
/* Read backing data before skip range */
|
||||
if (skip_start_bytes > 0) {
|
||||
if (bs->backing) {
|
||||
ret = bdrv_pread(bs->backing->bs, offset, whole_grain,
|
||||
ret = bdrv_pread(bs->backing, offset, whole_grain,
|
||||
skip_start_bytes);
|
||||
if (ret < 0) {
|
||||
ret = VMDK_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
ret = bdrv_pwrite(extent->file->bs, cluster_offset, whole_grain,
|
||||
ret = bdrv_pwrite(extent->file, cluster_offset, whole_grain,
|
||||
skip_start_bytes);
|
||||
if (ret < 0) {
|
||||
ret = VMDK_ERROR;
|
||||
@@ -1063,7 +1062,7 @@ static int get_whole_cluster(BlockDriverState *bs,
|
||||
/* Read backing data after skip range */
|
||||
if (skip_end_bytes < cluster_bytes) {
|
||||
if (bs->backing) {
|
||||
ret = bdrv_pread(bs->backing->bs, offset + skip_end_bytes,
|
||||
ret = bdrv_pread(bs->backing, offset + skip_end_bytes,
|
||||
whole_grain + skip_end_bytes,
|
||||
cluster_bytes - skip_end_bytes);
|
||||
if (ret < 0) {
|
||||
@@ -1071,7 +1070,7 @@ static int get_whole_cluster(BlockDriverState *bs,
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
ret = bdrv_pwrite(extent->file->bs, cluster_offset + skip_end_bytes,
|
||||
ret = bdrv_pwrite(extent->file, cluster_offset + skip_end_bytes,
|
||||
whole_grain + skip_end_bytes,
|
||||
cluster_bytes - skip_end_bytes);
|
||||
if (ret < 0) {
|
||||
@@ -1091,8 +1090,7 @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
|
||||
{
|
||||
offset = cpu_to_le32(offset);
|
||||
/* update L2 table */
|
||||
if (bdrv_pwrite_sync(
|
||||
extent->file->bs,
|
||||
if (bdrv_pwrite_sync(extent->file,
|
||||
((int64_t)m_data->l2_offset * 512)
|
||||
+ (m_data->l2_index * sizeof(offset)),
|
||||
&offset, sizeof(offset)) < 0) {
|
||||
@@ -1101,8 +1099,7 @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
|
||||
/* update backup L2 table */
|
||||
if (extent->l1_backup_table_offset != 0) {
|
||||
m_data->l2_offset = extent->l1_backup_table[m_data->l1_index];
|
||||
if (bdrv_pwrite_sync(
|
||||
extent->file->bs,
|
||||
if (bdrv_pwrite_sync(extent->file,
|
||||
((int64_t)m_data->l2_offset * 512)
|
||||
+ (m_data->l2_index * sizeof(offset)),
|
||||
&offset, sizeof(offset)) < 0) {
|
||||
@@ -1191,8 +1188,7 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||
}
|
||||
}
|
||||
l2_table = extent->l2_cache + (min_index * extent->l2_size);
|
||||
if (bdrv_pread(
|
||||
extent->file->bs,
|
||||
if (bdrv_pread(extent->file,
|
||||
(int64_t)l2_offset * 512,
|
||||
l2_table,
|
||||
extent->l2_size * sizeof(uint32_t)
|
||||
@@ -1373,7 +1369,7 @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
|
||||
}
|
||||
|
||||
write_offset = cluster_offset + offset_in_cluster,
|
||||
ret = bdrv_co_pwritev(extent->file->bs, write_offset, n_bytes,
|
||||
ret = bdrv_co_pwritev(extent->file, write_offset, n_bytes,
|
||||
&local_qiov, 0);
|
||||
|
||||
write_end_sector = DIV_ROUND_UP(write_offset + n_bytes, BDRV_SECTOR_SIZE);
|
||||
@@ -1411,7 +1407,7 @@ static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
|
||||
|
||||
|
||||
if (!extent->compressed) {
|
||||
ret = bdrv_co_preadv(extent->file->bs,
|
||||
ret = bdrv_co_preadv(extent->file,
|
||||
cluster_offset + offset_in_cluster, bytes,
|
||||
qiov, 0);
|
||||
if (ret < 0) {
|
||||
@@ -1424,7 +1420,7 @@ static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
|
||||
buf_bytes = cluster_bytes * 2;
|
||||
cluster_buf = g_malloc(buf_bytes);
|
||||
uncomp_buf = g_malloc(cluster_bytes);
|
||||
ret = bdrv_pread(extent->file->bs,
|
||||
ret = bdrv_pread(extent->file,
|
||||
cluster_offset,
|
||||
cluster_buf, buf_bytes);
|
||||
if (ret < 0) {
|
||||
@@ -1501,7 +1497,7 @@ vmdk_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
qemu_iovec_reset(&local_qiov);
|
||||
qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
|
||||
|
||||
ret = bdrv_co_preadv(bs->backing->bs, offset, n_bytes,
|
||||
ret = bdrv_co_preadv(bs->backing, offset, n_bytes,
|
||||
&local_qiov, 0);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
|
||||
24
block/vpc.c
24
block/vpc.c
@@ -237,7 +237,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, 0, s->footer_buf, HEADER_SIZE);
|
||||
ret = bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Unable to read VHD header");
|
||||
goto fail;
|
||||
@@ -257,7 +257,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
/* If a fixed disk, the footer is found only at the end of the file */
|
||||
ret = bdrv_pread(bs->file->bs, offset-HEADER_SIZE, s->footer_buf,
|
||||
ret = bdrv_pread(bs->file, offset-HEADER_SIZE, s->footer_buf,
|
||||
HEADER_SIZE);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -328,7 +328,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
if (disk_type == VHD_DYNAMIC) {
|
||||
ret = bdrv_pread(bs->file->bs, be64_to_cpu(footer->data_offset), buf,
|
||||
ret = bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf,
|
||||
HEADER_SIZE);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Error reading dynamic VHD header");
|
||||
@@ -385,7 +385,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
|
||||
|
||||
ret = bdrv_pread(bs->file->bs, s->bat_offset, s->pagetable,
|
||||
ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable,
|
||||
pagetable_size);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Error reading pagetable");
|
||||
@@ -481,7 +481,7 @@ static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset,
|
||||
|
||||
s->last_bitmap_offset = bitmap_offset;
|
||||
memset(bitmap, 0xff, s->bitmap_size);
|
||||
bdrv_pwrite_sync(bs->file->bs, bitmap_offset, bitmap, s->bitmap_size);
|
||||
bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size);
|
||||
}
|
||||
|
||||
return block_offset;
|
||||
@@ -505,7 +505,7 @@ static int rewrite_footer(BlockDriverState* bs)
|
||||
BDRVVPCState *s = bs->opaque;
|
||||
int64_t offset = s->free_data_block_offset;
|
||||
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, offset, s->footer_buf, HEADER_SIZE);
|
||||
ret = bdrv_pwrite_sync(bs->file, offset, s->footer_buf, HEADER_SIZE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -539,7 +539,7 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t offset)
|
||||
|
||||
/* Initialize the block's bitmap */
|
||||
memset(bitmap, 0xff, s->bitmap_size);
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, s->free_data_block_offset, bitmap,
|
||||
ret = bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap,
|
||||
s->bitmap_size);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -554,7 +554,7 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t offset)
|
||||
/* Write BAT entry to disk */
|
||||
bat_offset = s->bat_offset + (4 * index);
|
||||
bat_value = cpu_to_be32(s->pagetable[index]);
|
||||
ret = bdrv_pwrite_sync(bs->file->bs, bat_offset, &bat_value, 4);
|
||||
ret = bdrv_pwrite_sync(bs->file, bat_offset, &bat_value, 4);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
@@ -591,7 +591,7 @@ vpc_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
QEMUIOVector local_qiov;
|
||||
|
||||
if (be32_to_cpu(footer->type) == VHD_FIXED) {
|
||||
return bdrv_co_preadv(bs->file->bs, offset, bytes, qiov, 0);
|
||||
return bdrv_co_preadv(bs->file, offset, bytes, qiov, 0);
|
||||
}
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
@@ -607,7 +607,7 @@ vpc_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
qemu_iovec_reset(&local_qiov);
|
||||
qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
|
||||
|
||||
ret = bdrv_co_preadv(bs->file->bs, image_offset, n_bytes,
|
||||
ret = bdrv_co_preadv(bs->file, image_offset, n_bytes,
|
||||
&local_qiov, 0);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -640,7 +640,7 @@ vpc_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
QEMUIOVector local_qiov;
|
||||
|
||||
if (be32_to_cpu(footer->type) == VHD_FIXED) {
|
||||
return bdrv_co_pwritev(bs->file->bs, offset, bytes, qiov, 0);
|
||||
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, 0);
|
||||
}
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
@@ -661,7 +661,7 @@ vpc_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
qemu_iovec_reset(&local_qiov);
|
||||
qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
|
||||
|
||||
ret = bdrv_co_pwritev(bs->file->bs, image_offset, n_bytes,
|
||||
ret = bdrv_co_pwritev(bs->file, image_offset, n_bytes,
|
||||
&local_qiov, 0);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
|
||||
@@ -341,9 +341,8 @@ typedef struct BDRVVVFATState {
|
||||
unsigned int current_cluster;
|
||||
|
||||
/* write support */
|
||||
BlockDriverState* write_target;
|
||||
char* qcow_filename;
|
||||
BlockDriverState* qcow;
|
||||
BdrvChild* qcow;
|
||||
void* fat2;
|
||||
char* used_clusters;
|
||||
array_t commits;
|
||||
@@ -981,7 +980,7 @@ static int init_directories(BDRVVVFATState* s,
|
||||
static BDRVVVFATState *vvv = NULL;
|
||||
#endif
|
||||
|
||||
static int enable_write_target(BDRVVVFATState *s, Error **errp);
|
||||
static int enable_write_target(BlockDriverState *bs, Error **errp);
|
||||
static int is_consistent(BDRVVVFATState *s);
|
||||
|
||||
static QemuOptsList runtime_opts = {
|
||||
@@ -1158,8 +1157,8 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
s->current_cluster=0xffffffff;
|
||||
|
||||
/* read only is the default for safety */
|
||||
bs->read_only = 1;
|
||||
s->qcow = s->write_target = NULL;
|
||||
bs->read_only = true;
|
||||
s->qcow = NULL;
|
||||
s->qcow_filename = NULL;
|
||||
s->fat2 = NULL;
|
||||
s->downcase_short_names = 1;
|
||||
@@ -1170,14 +1169,13 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
|
||||
|
||||
if (qemu_opt_get_bool(opts, "rw", false)) {
|
||||
ret = enable_write_target(s, errp);
|
||||
ret = enable_write_target(bs, errp);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
bs->read_only = 0;
|
||||
bs->read_only = false;
|
||||
}
|
||||
|
||||
bs->request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O supported */
|
||||
bs->total_sectors = cyls * heads * secs;
|
||||
|
||||
if (init_directories(s, dirname, heads, secs, errp)) {
|
||||
@@ -1209,6 +1207,11 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void vvfat_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
|
||||
}
|
||||
|
||||
static inline void vvfat_close_current_file(BDRVVVFATState *s)
|
||||
{
|
||||
if(s->current_mapping) {
|
||||
@@ -1387,9 +1390,10 @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
|
||||
return -1;
|
||||
if (s->qcow) {
|
||||
int n;
|
||||
if (bdrv_is_allocated(s->qcow, sector_num, nb_sectors-i, &n)) {
|
||||
DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
|
||||
if (bdrv_read(s->qcow, sector_num, buf + i*0x200, n)) {
|
||||
if (bdrv_is_allocated(s->qcow->bs, sector_num, nb_sectors-i, &n)) {
|
||||
DLOG(fprintf(stderr, "sectors %d+%d allocated\n",
|
||||
(int)sector_num, n));
|
||||
if (bdrv_read(s->qcow, sector_num, buf + i * 0x200, n)) {
|
||||
return -1;
|
||||
}
|
||||
i += n - 1;
|
||||
@@ -1665,12 +1669,15 @@ static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
|
||||
int was_modified = 0;
|
||||
int i, dummy;
|
||||
|
||||
if (s->qcow == NULL)
|
||||
return 0;
|
||||
if (s->qcow == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
|
||||
was_modified = bdrv_is_allocated(s->qcow,
|
||||
cluster2sector(s, cluster_num) + i, 1, &dummy);
|
||||
for (i = 0; !was_modified && i < s->sectors_per_cluster; i++) {
|
||||
was_modified = bdrv_is_allocated(s->qcow->bs,
|
||||
cluster2sector(s, cluster_num) + i,
|
||||
1, &dummy);
|
||||
}
|
||||
|
||||
return was_modified;
|
||||
}
|
||||
@@ -1819,11 +1826,16 @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
|
||||
|
||||
vvfat_close_current_file(s);
|
||||
for (i = 0; i < s->sectors_per_cluster; i++) {
|
||||
if (!bdrv_is_allocated(s->qcow, offset + i, 1, &dummy)) {
|
||||
if (vvfat_read(s->bs, offset, s->cluster_buffer, 1)) {
|
||||
int res;
|
||||
|
||||
res = bdrv_is_allocated(s->qcow->bs, offset + i, 1, &dummy);
|
||||
if (!res) {
|
||||
res = vvfat_read(s->bs, offset, s->cluster_buffer, 1);
|
||||
if (res) {
|
||||
return -1;
|
||||
}
|
||||
if (bdrv_write(s->qcow, offset, s->cluster_buffer, 1)) {
|
||||
res = bdrv_write(s->qcow, offset, s->cluster_buffer, 1);
|
||||
if (res) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
@@ -2779,8 +2791,8 @@ static int do_commit(BDRVVVFATState* s)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (s->qcow->drv->bdrv_make_empty) {
|
||||
s->qcow->drv->bdrv_make_empty(s->qcow);
|
||||
if (s->qcow->bs->drv->bdrv_make_empty) {
|
||||
s->qcow->bs->drv->bdrv_make_empty(s->qcow->bs);
|
||||
}
|
||||
|
||||
memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
|
||||
@@ -2946,7 +2958,7 @@ write_target_commit(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
|
||||
static void write_target_close(BlockDriverState *bs) {
|
||||
BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
|
||||
bdrv_unref(s->qcow);
|
||||
bdrv_unref_child(s->bs, s->qcow);
|
||||
g_free(s->qcow_filename);
|
||||
}
|
||||
|
||||
@@ -2956,8 +2968,19 @@ static BlockDriver vvfat_write_target = {
|
||||
.bdrv_close = write_target_close,
|
||||
};
|
||||
|
||||
static int enable_write_target(BDRVVVFATState *s, Error **errp)
|
||||
static void vvfat_qcow_options(int *child_flags, QDict *child_options,
|
||||
int parent_flags, QDict *parent_options)
|
||||
{
|
||||
*child_flags = BDRV_O_RDWR | BDRV_O_NO_FLUSH;
|
||||
}
|
||||
|
||||
static const BdrvChildRole child_vvfat_qcow = {
|
||||
.inherit_options = vvfat_qcow_options,
|
||||
};
|
||||
|
||||
static int enable_write_target(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
BDRVVVFATState *s = bs->opaque;
|
||||
BlockDriver *bdrv_qcow = NULL;
|
||||
BlockDriverState *backing;
|
||||
QemuOpts *opts = NULL;
|
||||
@@ -2996,8 +3019,8 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
|
||||
|
||||
options = qdict_new();
|
||||
qdict_put(options, "driver", qstring_from_str("qcow"));
|
||||
s->qcow = bdrv_open(s->qcow_filename, NULL, options,
|
||||
BDRV_O_RDWR | BDRV_O_NO_FLUSH, errp);
|
||||
s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs,
|
||||
&child_vvfat_qcow, false, errp);
|
||||
if (!s->qcow) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
@@ -3046,6 +3069,7 @@ static BlockDriver bdrv_vvfat = {
|
||||
|
||||
.bdrv_parse_filename = vvfat_parse_filename,
|
||||
.bdrv_file_open = vvfat_open,
|
||||
.bdrv_refresh_limits = vvfat_refresh_limits,
|
||||
.bdrv_close = vvfat_close,
|
||||
|
||||
.bdrv_co_preadv = vvfat_co_preadv,
|
||||
|
||||
@@ -3950,10 +3950,10 @@ out:
|
||||
|
||||
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
||||
{
|
||||
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
||||
BlockDriverState *bs;
|
||||
BlockBackend *blk = NULL;
|
||||
QObject *obj;
|
||||
Visitor *v = qmp_output_visitor_new(&obj);
|
||||
QDict *qdict;
|
||||
Error *local_err = NULL;
|
||||
|
||||
@@ -3972,14 +3972,13 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
visit_type_BlockdevOptions(qmp_output_get_visitor(ov), NULL, &options,
|
||||
&local_err);
|
||||
visit_type_BlockdevOptions(v, NULL, &options, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
obj = qmp_output_get_qobject(ov);
|
||||
visit_complete(v, &obj);
|
||||
qdict = qobject_to_qdict(obj);
|
||||
|
||||
qdict_flatten(qdict);
|
||||
@@ -4020,7 +4019,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
||||
}
|
||||
|
||||
fail:
|
||||
qmp_output_visitor_cleanup(ov);
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
void qmp_x_blockdev_del(bool has_id, const char *id,
|
||||
|
||||
23
configure
vendored
23
configure
vendored
@@ -305,8 +305,8 @@ archipelago="no"
|
||||
gtk=""
|
||||
gtkabi=""
|
||||
gtk_gl="no"
|
||||
tls_priority="NORMAL"
|
||||
gnutls=""
|
||||
gnutls_hash=""
|
||||
gnutls_rnd=""
|
||||
nettle=""
|
||||
nettle_kdf="no"
|
||||
@@ -369,6 +369,7 @@ fi
|
||||
|
||||
ar="${AR-${cross_prefix}ar}"
|
||||
as="${AS-${cross_prefix}as}"
|
||||
ccas="${CCAS-$cc}"
|
||||
cpp="${CPP-$cc -E}"
|
||||
objcopy="${OBJCOPY-${cross_prefix}objcopy}"
|
||||
ld="${LD-${cross_prefix}ld}"
|
||||
@@ -1097,6 +1098,8 @@ for opt do
|
||||
;;
|
||||
--enable-gtk) gtk="yes"
|
||||
;;
|
||||
--tls-priority=*) tls_priority="$optarg"
|
||||
;;
|
||||
--disable-gnutls) gnutls="no"
|
||||
;;
|
||||
--enable-gnutls) gnutls="yes"
|
||||
@@ -1308,6 +1311,7 @@ Advanced options (experts only):
|
||||
--disable-blobs disable installing provided firmware blobs
|
||||
--with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent
|
||||
--with-win-sdk=SDK-path path to Windows Platform SDK (to build VSS .tlb)
|
||||
--tls-priority default TLS protocol/cipher priority string
|
||||
|
||||
Optional features, enabled with --enable-FEATURE and
|
||||
disabled with --disable-FEATURE, default is enabled if available:
|
||||
@@ -2218,13 +2222,6 @@ if test "$gnutls" != "no"; then
|
||||
QEMU_CFLAGS="$QEMU_CFLAGS $gnutls_cflags"
|
||||
gnutls="yes"
|
||||
|
||||
# gnutls_hash_init requires >= 2.9.10
|
||||
if $pkg_config --exists "gnutls >= 2.9.10"; then
|
||||
gnutls_hash="yes"
|
||||
else
|
||||
gnutls_hash="no"
|
||||
fi
|
||||
|
||||
# gnutls_rnd requires >= 2.11.0
|
||||
if $pkg_config --exists "gnutls >= 2.11.0"; then
|
||||
gnutls_rnd="yes"
|
||||
@@ -2258,11 +2255,9 @@ if test "$gnutls" != "no"; then
|
||||
feature_not_found "gnutls" "Install gnutls devel"
|
||||
else
|
||||
gnutls="no"
|
||||
gnutls_hash="no"
|
||||
gnutls_rnd="no"
|
||||
fi
|
||||
else
|
||||
gnutls_hash="no"
|
||||
gnutls_rnd="no"
|
||||
fi
|
||||
|
||||
@@ -4812,8 +4807,8 @@ echo "SDL support $sdl $(echo_version $sdl $sdlversion)"
|
||||
echo "GTK support $gtk $(echo_version $gtk $gtk_version)"
|
||||
echo "GTK GL support $gtk_gl"
|
||||
echo "VTE support $vte $(echo_version $vte $vteversion)"
|
||||
echo "TLS priority $tls_priority"
|
||||
echo "GNUTLS support $gnutls"
|
||||
echo "GNUTLS hash $gnutls_hash"
|
||||
echo "GNUTLS rnd $gnutls_rnd"
|
||||
echo "libgcrypt $gcrypt"
|
||||
echo "libgcrypt kdf $gcrypt_kdf"
|
||||
@@ -5176,12 +5171,10 @@ if test "$gtk" = "yes" ; then
|
||||
echo "CONFIG_GTK_GL=y" >> $config_host_mak
|
||||
fi
|
||||
fi
|
||||
echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak
|
||||
if test "$gnutls" = "yes" ; then
|
||||
echo "CONFIG_GNUTLS=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$gnutls_hash" = "yes" ; then
|
||||
echo "CONFIG_GNUTLS_HASH=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$gnutls_rnd" = "yes" ; then
|
||||
echo "CONFIG_GNUTLS_RND=y" >> $config_host_mak
|
||||
fi
|
||||
@@ -5517,6 +5510,7 @@ echo "OBJCC=$objcc" >> $config_host_mak
|
||||
echo "AR=$ar" >> $config_host_mak
|
||||
echo "ARFLAGS=$ARFLAGS" >> $config_host_mak
|
||||
echo "AS=$as" >> $config_host_mak
|
||||
echo "CCAS=$ccas" >> $config_host_mak
|
||||
echo "CPP=$cpp" >> $config_host_mak
|
||||
echo "OBJCOPY=$objcopy" >> $config_host_mak
|
||||
echo "LD=$ld" >> $config_host_mak
|
||||
@@ -5990,6 +5984,7 @@ for rom in seabios vgabios ; do
|
||||
echo "# Automatically generated by configure - do not modify" > $config_mak
|
||||
echo "SRC_PATH=$source_path/roms/$rom" >> $config_mak
|
||||
echo "AS=$as" >> $config_mak
|
||||
echo "CCAS=$ccas" >> $config_mak
|
||||
echo "CC=$cc" >> $config_mak
|
||||
echo "BCC=bcc" >> $config_mak
|
||||
echo "CPP=$cpp" >> $config_mak
|
||||
|
||||
29
cputlb.c
29
cputlb.c
@@ -498,6 +498,35 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
|
||||
return qemu_ram_addr_from_host_nofail(p);
|
||||
}
|
||||
|
||||
/* Return true if ADDR is present in the victim tlb, and has been copied
|
||||
back to the main tlb. */
|
||||
static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
|
||||
size_t elt_ofs, target_ulong page)
|
||||
{
|
||||
size_t vidx;
|
||||
for (vidx = 0; vidx < CPU_VTLB_SIZE; ++vidx) {
|
||||
CPUTLBEntry *vtlb = &env->tlb_v_table[mmu_idx][vidx];
|
||||
target_ulong cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs);
|
||||
|
||||
if (cmp == page) {
|
||||
/* Found entry in victim tlb, swap tlb and iotlb. */
|
||||
CPUTLBEntry tmptlb, *tlb = &env->tlb_table[mmu_idx][index];
|
||||
CPUIOTLBEntry tmpio, *io = &env->iotlb[mmu_idx][index];
|
||||
CPUIOTLBEntry *vio = &env->iotlb_v[mmu_idx][vidx];
|
||||
|
||||
tmptlb = *tlb; *tlb = *vtlb; *vtlb = tmptlb;
|
||||
tmpio = *io; *io = *vio; *vio = tmpio;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Macro to call the above, with local variables from the use context. */
|
||||
#define VICTIM_TLB_HIT(TY, ADDR) \
|
||||
victim_tlb_hit(env, mmu_idx, index, offsetof(CPUTLBEntry, TY), \
|
||||
(ADDR) & TARGET_PAGE_MASK)
|
||||
|
||||
#define MMUSUFFIX _mmu
|
||||
|
||||
#define SHIFT 0
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
crypto-obj-y = init.o
|
||||
crypto-obj-y += hash.o
|
||||
crypto-obj-$(CONFIG_NETTLE) += hash-nettle.o
|
||||
crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += hash-gcrypt.o
|
||||
crypto-obj-y += aes.o
|
||||
crypto-obj-y += desrfb.o
|
||||
crypto-obj-y += cipher.o
|
||||
@@ -28,3 +30,4 @@ crypto-aes-obj-y = aes.o
|
||||
|
||||
stub-obj-y += random-stub.o
|
||||
stub-obj-y += pbkdf-stub.o
|
||||
stub-obj-y += hash-stub.o
|
||||
|
||||
@@ -776,6 +776,11 @@ qcrypto_block_luks_open(QCryptoBlock *block,
|
||||
}
|
||||
|
||||
if (ivalg == QCRYPTO_IVGEN_ALG_ESSIV) {
|
||||
if (!ivhash_name) {
|
||||
ret = -EINVAL;
|
||||
error_setg(errp, "Missing IV generator hash specification");
|
||||
goto fail;
|
||||
}
|
||||
ivcipheralg = qcrypto_block_luks_essiv_cipher(cipheralg,
|
||||
ivhash,
|
||||
&local_err);
|
||||
@@ -785,6 +790,13 @@ qcrypto_block_luks_open(QCryptoBlock *block,
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
/* Note we parsed the ivhash_name earlier in the cipher_mode
|
||||
* spec string even with plain/plain64 ivgens, but we
|
||||
* will ignore it, since it is irrelevant for these ivgens.
|
||||
* This is for compat with dm-crypt which will silently
|
||||
* ignore hash names with these ivgens rather than report
|
||||
* an error about the invalid usage
|
||||
*/
|
||||
ivcipheralg = cipheralg;
|
||||
}
|
||||
|
||||
@@ -904,6 +916,15 @@ qcrypto_block_luks_create(QCryptoBlock *block,
|
||||
if (!luks_opts.has_hash_alg) {
|
||||
luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256;
|
||||
}
|
||||
if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
|
||||
if (!luks_opts.has_ivgen_hash_alg) {
|
||||
luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256;
|
||||
luks_opts.has_ivgen_hash_alg = true;
|
||||
}
|
||||
}
|
||||
/* Note we're allowing ivgen_hash_alg to be set even for
|
||||
* non-essiv iv generators that don't need a hash. It will
|
||||
* be silently ignored, for compatibility with dm-crypt */
|
||||
|
||||
if (!options->u.luks.key_secret) {
|
||||
error_setg(errp, "Parameter 'key-secret' is required for cipher");
|
||||
|
||||
110
crypto/hash-gcrypt.c
Normal file
110
crypto/hash-gcrypt.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* QEMU Crypto hash algorithms
|
||||
*
|
||||
* Copyright (c) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "gcrypt.h"
|
||||
|
||||
|
||||
static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
||||
[QCRYPTO_HASH_ALG_MD5] = GCRY_MD_MD5,
|
||||
[QCRYPTO_HASH_ALG_SHA1] = GCRY_MD_SHA1,
|
||||
[QCRYPTO_HASH_ALG_SHA224] = GCRY_MD_SHA224,
|
||||
[QCRYPTO_HASH_ALG_SHA256] = GCRY_MD_SHA256,
|
||||
[QCRYPTO_HASH_ALG_SHA384] = GCRY_MD_SHA384,
|
||||
[QCRYPTO_HASH_ALG_SHA512] = GCRY_MD_SHA512,
|
||||
[QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MD_RMD160,
|
||||
};
|
||||
|
||||
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
|
||||
{
|
||||
if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) &&
|
||||
qcrypto_hash_alg_map[alg] != GCRY_MD_NONE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||
const struct iovec *iov,
|
||||
size_t niov,
|
||||
uint8_t **result,
|
||||
size_t *resultlen,
|
||||
Error **errp)
|
||||
{
|
||||
int i, ret;
|
||||
gcry_md_hd_t md;
|
||||
unsigned char *digest;
|
||||
|
||||
if (alg >= G_N_ELEMENTS(qcrypto_hash_alg_map) ||
|
||||
qcrypto_hash_alg_map[alg] == GCRY_MD_NONE) {
|
||||
error_setg(errp,
|
||||
"Unknown hash algorithm %d",
|
||||
alg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = gcry_md_open(&md, qcrypto_hash_alg_map[alg], 0);
|
||||
|
||||
if (ret < 0) {
|
||||
error_setg(errp,
|
||||
"Unable to initialize hash algorithm: %s",
|
||||
gcry_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < niov; i++) {
|
||||
gcry_md_write(md, iov[i].iov_base, iov[i].iov_len);
|
||||
}
|
||||
|
||||
ret = gcry_md_get_algo_dlen(qcrypto_hash_alg_map[alg]);
|
||||
if (ret <= 0) {
|
||||
error_setg(errp,
|
||||
"Unable to get hash length: %s",
|
||||
gcry_strerror(ret));
|
||||
goto error;
|
||||
}
|
||||
if (*resultlen == 0) {
|
||||
*resultlen = ret;
|
||||
*result = g_new0(uint8_t, *resultlen);
|
||||
} else if (*resultlen != ret) {
|
||||
error_setg(errp,
|
||||
"Result buffer size %zu is smaller than hash %d",
|
||||
*resultlen, ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
digest = gcry_md_read(md, 0);
|
||||
if (!digest) {
|
||||
error_setg(errp,
|
||||
"No digest produced");
|
||||
goto error;
|
||||
}
|
||||
memcpy(*result, digest, *resultlen);
|
||||
|
||||
gcry_md_close(md);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
gcry_md_close(md);
|
||||
return -1;
|
||||
}
|
||||
155
crypto/hash-nettle.c
Normal file
155
crypto/hash-nettle.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* QEMU Crypto hash algorithms
|
||||
*
|
||||
* Copyright (c) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "crypto/hash.h"
|
||||
#include <nettle/md5.h>
|
||||
#include <nettle/sha.h>
|
||||
#include <nettle/ripemd160.h>
|
||||
|
||||
typedef void (*qcrypto_nettle_init)(void *ctx);
|
||||
typedef void (*qcrypto_nettle_write)(void *ctx,
|
||||
unsigned int len,
|
||||
const uint8_t *buf);
|
||||
typedef void (*qcrypto_nettle_result)(void *ctx,
|
||||
unsigned int len,
|
||||
uint8_t *buf);
|
||||
|
||||
union qcrypto_hash_ctx {
|
||||
struct md5_ctx md5;
|
||||
struct sha1_ctx sha1;
|
||||
struct sha224_ctx sha224;
|
||||
struct sha256_ctx sha256;
|
||||
struct sha384_ctx sha384;
|
||||
struct sha512_ctx sha512;
|
||||
struct ripemd160_ctx ripemd160;
|
||||
};
|
||||
|
||||
struct qcrypto_hash_alg {
|
||||
qcrypto_nettle_init init;
|
||||
qcrypto_nettle_write write;
|
||||
qcrypto_nettle_result result;
|
||||
size_t len;
|
||||
} qcrypto_hash_alg_map[] = {
|
||||
[QCRYPTO_HASH_ALG_MD5] = {
|
||||
.init = (qcrypto_nettle_init)md5_init,
|
||||
.write = (qcrypto_nettle_write)md5_update,
|
||||
.result = (qcrypto_nettle_result)md5_digest,
|
||||
.len = MD5_DIGEST_SIZE,
|
||||
},
|
||||
[QCRYPTO_HASH_ALG_SHA1] = {
|
||||
.init = (qcrypto_nettle_init)sha1_init,
|
||||
.write = (qcrypto_nettle_write)sha1_update,
|
||||
.result = (qcrypto_nettle_result)sha1_digest,
|
||||
.len = SHA1_DIGEST_SIZE,
|
||||
},
|
||||
[QCRYPTO_HASH_ALG_SHA224] = {
|
||||
.init = (qcrypto_nettle_init)sha224_init,
|
||||
.write = (qcrypto_nettle_write)sha224_update,
|
||||
.result = (qcrypto_nettle_result)sha224_digest,
|
||||
.len = SHA224_DIGEST_SIZE,
|
||||
},
|
||||
[QCRYPTO_HASH_ALG_SHA256] = {
|
||||
.init = (qcrypto_nettle_init)sha256_init,
|
||||
.write = (qcrypto_nettle_write)sha256_update,
|
||||
.result = (qcrypto_nettle_result)sha256_digest,
|
||||
.len = SHA256_DIGEST_SIZE,
|
||||
},
|
||||
[QCRYPTO_HASH_ALG_SHA384] = {
|
||||
.init = (qcrypto_nettle_init)sha384_init,
|
||||
.write = (qcrypto_nettle_write)sha384_update,
|
||||
.result = (qcrypto_nettle_result)sha384_digest,
|
||||
.len = SHA384_DIGEST_SIZE,
|
||||
},
|
||||
[QCRYPTO_HASH_ALG_SHA512] = {
|
||||
.init = (qcrypto_nettle_init)sha512_init,
|
||||
.write = (qcrypto_nettle_write)sha512_update,
|
||||
.result = (qcrypto_nettle_result)sha512_digest,
|
||||
.len = SHA512_DIGEST_SIZE,
|
||||
},
|
||||
[QCRYPTO_HASH_ALG_RIPEMD160] = {
|
||||
.init = (qcrypto_nettle_init)ripemd160_init,
|
||||
.write = (qcrypto_nettle_write)ripemd160_update,
|
||||
.result = (qcrypto_nettle_result)ripemd160_digest,
|
||||
.len = RIPEMD160_DIGEST_SIZE,
|
||||
},
|
||||
};
|
||||
|
||||
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
|
||||
{
|
||||
if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) &&
|
||||
qcrypto_hash_alg_map[alg].init != NULL) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||
const struct iovec *iov,
|
||||
size_t niov,
|
||||
uint8_t **result,
|
||||
size_t *resultlen,
|
||||
Error **errp)
|
||||
{
|
||||
int i;
|
||||
union qcrypto_hash_ctx ctx;
|
||||
|
||||
if (alg >= G_N_ELEMENTS(qcrypto_hash_alg_map) ||
|
||||
qcrypto_hash_alg_map[alg].init == NULL) {
|
||||
error_setg(errp,
|
||||
"Unknown hash algorithm %d",
|
||||
alg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
qcrypto_hash_alg_map[alg].init(&ctx);
|
||||
|
||||
for (i = 0; i < niov; i++) {
|
||||
/* Some versions of nettle have functions
|
||||
* declared with 'int' instead of 'size_t'
|
||||
* so to be safe avoid writing more than
|
||||
* UINT_MAX bytes at a time
|
||||
*/
|
||||
size_t len = iov[i].iov_len;
|
||||
uint8_t *base = iov[i].iov_base;
|
||||
while (len) {
|
||||
size_t shortlen = MIN(len, UINT_MAX);
|
||||
qcrypto_hash_alg_map[alg].write(&ctx, len, base);
|
||||
len -= shortlen;
|
||||
base += len;
|
||||
}
|
||||
}
|
||||
|
||||
if (*resultlen == 0) {
|
||||
*resultlen = qcrypto_hash_alg_map[alg].len;
|
||||
*result = g_new0(uint8_t, *resultlen);
|
||||
} else if (*resultlen != qcrypto_hash_alg_map[alg].len) {
|
||||
error_setg(errp,
|
||||
"Result buffer size %zu is smaller than hash %zu",
|
||||
*resultlen, qcrypto_hash_alg_map[alg].len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
qcrypto_hash_alg_map[alg].result(&ctx, *resultlen, *result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
41
crypto/hash-stub.c
Normal file
41
crypto/hash-stub.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* QEMU Crypto hash algorithms
|
||||
*
|
||||
* Copyright (c) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "crypto/hash.h"
|
||||
|
||||
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg G_GNUC_UNUSED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||
const struct iovec *iov G_GNUC_UNUSED,
|
||||
size_t niov G_GNUC_UNUSED,
|
||||
uint8_t **result G_GNUC_UNUSED,
|
||||
size_t *resultlen G_GNUC_UNUSED,
|
||||
Error **errp)
|
||||
{
|
||||
error_setg(errp,
|
||||
"Hash algorithm %d not supported without GNUTLS",
|
||||
alg);
|
||||
return -1;
|
||||
}
|
||||
109
crypto/hash.c
109
crypto/hash.c
@@ -22,16 +22,14 @@
|
||||
#include "qapi/error.h"
|
||||
#include "crypto/hash.h"
|
||||
|
||||
#ifdef CONFIG_GNUTLS_HASH
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#endif
|
||||
|
||||
|
||||
static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALG__MAX] = {
|
||||
[QCRYPTO_HASH_ALG_MD5] = 16,
|
||||
[QCRYPTO_HASH_ALG_SHA1] = 20,
|
||||
[QCRYPTO_HASH_ALG_SHA224] = 28,
|
||||
[QCRYPTO_HASH_ALG_SHA256] = 32,
|
||||
[QCRYPTO_HASH_ALG_SHA384] = 48,
|
||||
[QCRYPTO_HASH_ALG_SHA512] = 64,
|
||||
[QCRYPTO_HASH_ALG_RIPEMD160] = 20,
|
||||
};
|
||||
|
||||
size_t qcrypto_hash_digest_len(QCryptoHashAlgorithm alg)
|
||||
@@ -41,105 +39,6 @@ size_t qcrypto_hash_digest_len(QCryptoHashAlgorithm alg)
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_GNUTLS_HASH
|
||||
static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
||||
[QCRYPTO_HASH_ALG_MD5] = GNUTLS_DIG_MD5,
|
||||
[QCRYPTO_HASH_ALG_SHA1] = GNUTLS_DIG_SHA1,
|
||||
[QCRYPTO_HASH_ALG_SHA256] = GNUTLS_DIG_SHA256,
|
||||
};
|
||||
|
||||
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
|
||||
{
|
||||
if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||
const struct iovec *iov,
|
||||
size_t niov,
|
||||
uint8_t **result,
|
||||
size_t *resultlen,
|
||||
Error **errp)
|
||||
{
|
||||
int i, ret;
|
||||
gnutls_hash_hd_t dig;
|
||||
|
||||
if (alg >= G_N_ELEMENTS(qcrypto_hash_alg_map)) {
|
||||
error_setg(errp,
|
||||
"Unknown hash algorithm %d",
|
||||
alg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = gnutls_hash_init(&dig, qcrypto_hash_alg_map[alg]);
|
||||
|
||||
if (ret < 0) {
|
||||
error_setg(errp,
|
||||
"Unable to initialize hash algorithm: %s",
|
||||
gnutls_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < niov; i++) {
|
||||
ret = gnutls_hash(dig, iov[i].iov_base, iov[i].iov_len);
|
||||
if (ret < 0) {
|
||||
error_setg(errp,
|
||||
"Unable process hash data: %s",
|
||||
gnutls_strerror(ret));
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
ret = gnutls_hash_get_len(qcrypto_hash_alg_map[alg]);
|
||||
if (ret <= 0) {
|
||||
error_setg(errp,
|
||||
"Unable to get hash length: %s",
|
||||
gnutls_strerror(ret));
|
||||
goto error;
|
||||
}
|
||||
if (*resultlen == 0) {
|
||||
*resultlen = ret;
|
||||
*result = g_new0(uint8_t, *resultlen);
|
||||
} else if (*resultlen != ret) {
|
||||
error_setg(errp,
|
||||
"Result buffer size %zu is smaller than hash %d",
|
||||
*resultlen, ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
gnutls_hash_deinit(dig, *result);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
gnutls_hash_deinit(dig, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else /* ! CONFIG_GNUTLS_HASH */
|
||||
|
||||
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg G_GNUC_UNUSED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||
const struct iovec *iov G_GNUC_UNUSED,
|
||||
size_t niov G_GNUC_UNUSED,
|
||||
uint8_t **result G_GNUC_UNUSED,
|
||||
size_t *resultlen G_GNUC_UNUSED,
|
||||
Error **errp)
|
||||
{
|
||||
error_setg(errp,
|
||||
"Hash algorithm %d not supported without GNUTLS",
|
||||
alg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* ! CONFIG_GNUTLS_HASH */
|
||||
|
||||
int qcrypto_hash_bytes(QCryptoHashAlgorithm alg,
|
||||
const char *buf,
|
||||
size_t len,
|
||||
|
||||
@@ -178,6 +178,27 @@ qcrypto_tls_creds_prop_get_dir(Object *obj,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_prop_set_priority(Object *obj,
|
||||
const char *value,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
||||
|
||||
creds->priority = g_strdup(value);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
qcrypto_tls_creds_prop_get_priority(Object *obj,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
||||
|
||||
return g_strdup(creds->priority);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_prop_set_endpoint(Object *obj,
|
||||
int value,
|
||||
@@ -216,6 +237,10 @@ qcrypto_tls_creds_class_init(ObjectClass *oc, void *data)
|
||||
qcrypto_tls_creds_prop_get_endpoint,
|
||||
qcrypto_tls_creds_prop_set_endpoint,
|
||||
NULL);
|
||||
object_class_property_add_str(oc, "priority",
|
||||
qcrypto_tls_creds_prop_get_priority,
|
||||
qcrypto_tls_creds_prop_set_priority,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -234,6 +259,7 @@ qcrypto_tls_creds_finalize(Object *obj)
|
||||
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
||||
|
||||
g_free(creds->dir);
|
||||
g_free(creds->priority);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -132,14 +132,22 @@ qcrypto_tls_session_new(QCryptoTLSCreds *creds,
|
||||
if (object_dynamic_cast(OBJECT(creds),
|
||||
TYPE_QCRYPTO_TLS_CREDS_ANON)) {
|
||||
QCryptoTLSCredsAnon *acreds = QCRYPTO_TLS_CREDS_ANON(creds);
|
||||
char *prio;
|
||||
|
||||
ret = gnutls_priority_set_direct(session->handle,
|
||||
"NORMAL:+ANON-DH", NULL);
|
||||
if (creds->priority != NULL) {
|
||||
prio = g_strdup_printf("%s:+ANON-DH", creds->priority);
|
||||
} else {
|
||||
prio = g_strdup(CONFIG_TLS_PRIORITY ":+ANON-DH");
|
||||
}
|
||||
|
||||
ret = gnutls_priority_set_direct(session->handle, prio, NULL);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Unable to set TLS session priority: %s",
|
||||
gnutls_strerror(ret));
|
||||
error_setg(errp, "Unable to set TLS session priority %s: %s",
|
||||
prio, gnutls_strerror(ret));
|
||||
g_free(prio);
|
||||
goto error;
|
||||
}
|
||||
g_free(prio);
|
||||
if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
||||
ret = gnutls_credentials_set(session->handle,
|
||||
GNUTLS_CRD_ANON,
|
||||
@@ -157,11 +165,15 @@ qcrypto_tls_session_new(QCryptoTLSCreds *creds,
|
||||
} else if (object_dynamic_cast(OBJECT(creds),
|
||||
TYPE_QCRYPTO_TLS_CREDS_X509)) {
|
||||
QCryptoTLSCredsX509 *tcreds = QCRYPTO_TLS_CREDS_X509(creds);
|
||||
const char *prio = creds->priority;
|
||||
if (!prio) {
|
||||
prio = CONFIG_TLS_PRIORITY;
|
||||
}
|
||||
|
||||
ret = gnutls_set_default_priority(session->handle);
|
||||
ret = gnutls_priority_set_direct(session->handle, prio, NULL);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot set default TLS session priority: %s",
|
||||
gnutls_strerror(ret));
|
||||
error_setg(errp, "Cannot set default TLS session priority %s: %s",
|
||||
prio, gnutls_strerror(ret));
|
||||
goto error;
|
||||
}
|
||||
ret = gnutls_credentials_set(session->handle,
|
||||
|
||||
@@ -66,6 +66,7 @@ CONFIG_PXA2XX=y
|
||||
CONFIG_BITBANG_I2C=y
|
||||
CONFIG_FRAMEBUFFER=y
|
||||
CONFIG_XILINX_SPIPS=y
|
||||
CONFIG_ZYNQ_DEVCFG=y
|
||||
|
||||
CONFIG_ARM11SCU=y
|
||||
CONFIG_A9SCU=y
|
||||
|
||||
@@ -41,8 +41,13 @@ MemoryRegion):
|
||||
MemoryRegionOps structure describing the callbacks.
|
||||
|
||||
- ROM: a ROM memory region works like RAM for reads (directly accessing
|
||||
a region of host memory), but like MMIO for writes (invoking a callback).
|
||||
You initialize these with memory_region_init_rom_device().
|
||||
a region of host memory), and forbids writes. You initialize these with
|
||||
memory_region_init_rom().
|
||||
|
||||
- ROM device: a ROM device memory region works like RAM for reads
|
||||
(directly accessing a region of host memory), but like MMIO for
|
||||
writes (invoking a callback). You initialize these with
|
||||
memory_region_init_rom_device().
|
||||
|
||||
- IOMMU region: an IOMMU region translates addresses of accesses made to it
|
||||
and forwards them to some other target memory region. As the name suggests,
|
||||
|
||||
@@ -802,32 +802,28 @@ Example:
|
||||
|
||||
void qapi_free_UserDefOne(UserDefOne *obj)
|
||||
{
|
||||
QapiDeallocVisitor *qdv;
|
||||
Visitor *v;
|
||||
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
qdv = qapi_dealloc_visitor_new();
|
||||
v = qapi_dealloc_get_visitor(qdv);
|
||||
v = qapi_dealloc_visitor_new();
|
||||
visit_type_UserDefOne(v, NULL, &obj, NULL);
|
||||
qapi_dealloc_visitor_cleanup(qdv);
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
void qapi_free_UserDefOneList(UserDefOneList *obj)
|
||||
{
|
||||
QapiDeallocVisitor *qdv;
|
||||
Visitor *v;
|
||||
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
qdv = qapi_dealloc_visitor_new();
|
||||
v = qapi_dealloc_get_visitor(qdv);
|
||||
v = qapi_dealloc_visitor_new();
|
||||
visit_type_UserDefOneList(v, NULL, &obj, NULL);
|
||||
qapi_dealloc_visitor_cleanup(qdv);
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
=== scripts/qapi-visit.py ===
|
||||
@@ -904,7 +900,7 @@ Example:
|
||||
}
|
||||
visit_check_struct(v, &err);
|
||||
out_obj:
|
||||
visit_end_struct(v);
|
||||
visit_end_struct(v, (void **)obj);
|
||||
if (err && visit_is_input(v)) {
|
||||
qapi_free_UserDefOne(*obj);
|
||||
*obj = NULL;
|
||||
@@ -932,7 +928,7 @@ Example:
|
||||
}
|
||||
}
|
||||
|
||||
visit_end_list(v);
|
||||
visit_end_list(v, (void **)obj);
|
||||
if (err && visit_is_input(v)) {
|
||||
qapi_free_UserDefOneList(*obj);
|
||||
*obj = NULL;
|
||||
@@ -984,36 +980,28 @@ Example:
|
||||
static void qmp_marshal_output_UserDefOne(UserDefOne *ret_in, QObject **ret_out, Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
QmpOutputVisitor *qov = qmp_output_visitor_new();
|
||||
QapiDeallocVisitor *qdv;
|
||||
Visitor *v;
|
||||
|
||||
v = qmp_output_get_visitor(qov);
|
||||
v = qmp_output_visitor_new(ret_out);
|
||||
visit_type_UserDefOne(v, "unused", &ret_in, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
if (!err) {
|
||||
visit_complete(v, ret_out);
|
||||
}
|
||||
*ret_out = qmp_output_get_qobject(qov);
|
||||
|
||||
out:
|
||||
error_propagate(errp, err);
|
||||
qmp_output_visitor_cleanup(qov);
|
||||
qdv = qapi_dealloc_visitor_new();
|
||||
v = qapi_dealloc_get_visitor(qdv);
|
||||
visit_free(v);
|
||||
v = qapi_dealloc_visitor_new();
|
||||
visit_type_UserDefOne(v, "unused", &ret_in, NULL);
|
||||
qapi_dealloc_visitor_cleanup(qdv);
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
static void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
UserDefOne *retval;
|
||||
QmpInputVisitor *qiv = qmp_input_visitor_new(QOBJECT(args), true);
|
||||
QapiDeallocVisitor *qdv;
|
||||
Visitor *v;
|
||||
UserDefOneList *arg1 = NULL;
|
||||
|
||||
v = qmp_input_get_visitor(qiv);
|
||||
v = qmp_input_visitor_new(QOBJECT(args), true);
|
||||
visit_start_struct(v, NULL, NULL, 0, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
@@ -1022,7 +1010,7 @@ Example:
|
||||
if (!err) {
|
||||
visit_check_struct(v, &err);
|
||||
}
|
||||
visit_end_struct(v);
|
||||
visit_end_struct(v, NULL);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
@@ -1036,13 +1024,12 @@ Example:
|
||||
|
||||
out:
|
||||
error_propagate(errp, err);
|
||||
qmp_input_visitor_cleanup(qiv);
|
||||
qdv = qapi_dealloc_visitor_new();
|
||||
v = qapi_dealloc_get_visitor(qdv);
|
||||
visit_free(v);
|
||||
v = qapi_dealloc_visitor_new();
|
||||
visit_start_struct(v, NULL, NULL, 0, NULL);
|
||||
visit_type_UserDefOneList(v, "arg1", &arg1, NULL);
|
||||
visit_end_struct(v);
|
||||
qapi_dealloc_visitor_cleanup(qdv);
|
||||
visit_end_struct(v, NULL);
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
static void qmp_init_marshal(void)
|
||||
|
||||
19
hmp.c
19
hmp.c
@@ -1722,7 +1722,7 @@ void hmp_object_add(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
Error *err = NULL;
|
||||
QemuOpts *opts;
|
||||
OptsVisitor *ov;
|
||||
Visitor *v;
|
||||
Object *obj = NULL;
|
||||
|
||||
opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err);
|
||||
@@ -1731,9 +1731,9 @@ void hmp_object_add(Monitor *mon, const QDict *qdict)
|
||||
return;
|
||||
}
|
||||
|
||||
ov = opts_visitor_new(opts);
|
||||
obj = user_creatable_add(qdict, opts_get_visitor(ov), &err);
|
||||
opts_visitor_cleanup(ov);
|
||||
v = opts_visitor_new(opts);
|
||||
obj = user_creatable_add(qdict, v, &err);
|
||||
visit_free(v);
|
||||
qemu_opts_del(opts);
|
||||
|
||||
if (err) {
|
||||
@@ -1983,15 +1983,14 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict)
|
||||
Error *err = NULL;
|
||||
MemdevList *memdev_list = qmp_query_memdev(&err);
|
||||
MemdevList *m = memdev_list;
|
||||
StringOutputVisitor *ov;
|
||||
Visitor *v;
|
||||
char *str;
|
||||
int i = 0;
|
||||
|
||||
|
||||
while (m) {
|
||||
ov = string_output_visitor_new(false);
|
||||
visit_type_uint16List(string_output_get_visitor(ov), NULL,
|
||||
&m->value->host_nodes, NULL);
|
||||
v = string_output_visitor_new(false, &str);
|
||||
visit_type_uint16List(v, NULL, &m->value->host_nodes, NULL);
|
||||
monitor_printf(mon, "memory backend: %d\n", i);
|
||||
monitor_printf(mon, " size: %" PRId64 "\n", m->value->size);
|
||||
monitor_printf(mon, " merge: %s\n",
|
||||
@@ -2002,11 +2001,11 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict)
|
||||
m->value->prealloc ? "true" : "false");
|
||||
monitor_printf(mon, " policy: %s\n",
|
||||
HostMemPolicy_lookup[m->value->policy]);
|
||||
str = string_output_get_string(ov);
|
||||
visit_complete(v, &str);
|
||||
monitor_printf(mon, " host nodes: %s\n", str);
|
||||
|
||||
g_free(str);
|
||||
string_output_visitor_cleanup(ov);
|
||||
visit_free(v);
|
||||
m = m->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -239,11 +239,11 @@ void acpi_table_add(const QemuOpts *opts, Error **errp)
|
||||
char unsigned *blob = NULL;
|
||||
|
||||
{
|
||||
OptsVisitor *ov;
|
||||
Visitor *v;
|
||||
|
||||
ov = opts_visitor_new(opts);
|
||||
visit_type_AcpiTableOptions(opts_get_visitor(ov), NULL, &hdrs, &err);
|
||||
opts_visitor_cleanup(ov);
|
||||
v = opts_visitor_new(opts);
|
||||
visit_type_AcpiTableOptions(v, NULL, &hdrs, &err);
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
|
||||
@@ -23,11 +23,17 @@
|
||||
#define AST2400_UART_5_BASE 0x00184000
|
||||
#define AST2400_IOMEM_SIZE 0x00200000
|
||||
#define AST2400_IOMEM_BASE 0x1E600000
|
||||
#define AST2400_SMC_BASE AST2400_IOMEM_BASE /* Legacy SMC */
|
||||
#define AST2400_FMC_BASE 0X1E620000
|
||||
#define AST2400_SPI_BASE 0X1E630000
|
||||
#define AST2400_VIC_BASE 0x1E6C0000
|
||||
#define AST2400_SCU_BASE 0x1E6E2000
|
||||
#define AST2400_TIMER_BASE 0x1E782000
|
||||
#define AST2400_I2C_BASE 0x1E78A000
|
||||
|
||||
#define AST2400_FMC_FLASH_BASE 0x20000000
|
||||
#define AST2400_SPI_FLASH_BASE 0x30000000
|
||||
|
||||
#define AST2400_A0_SILICON_REV 0x02000303
|
||||
|
||||
static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
|
||||
@@ -85,13 +91,21 @@ static void ast2400_init(Object *obj)
|
||||
"hw-strap1", &error_abort);
|
||||
object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
|
||||
"hw-strap2", &error_abort);
|
||||
|
||||
object_initialize(&s->smc, sizeof(s->smc), "aspeed.smc.fmc");
|
||||
object_property_add_child(obj, "smc", OBJECT(&s->smc), NULL);
|
||||
qdev_set_parent_bus(DEVICE(&s->smc), sysbus_get_default());
|
||||
|
||||
object_initialize(&s->spi, sizeof(s->spi), "aspeed.smc.spi");
|
||||
object_property_add_child(obj, "spi", OBJECT(&s->spi), NULL);
|
||||
qdev_set_parent_bus(DEVICE(&s->spi), sysbus_get_default());
|
||||
}
|
||||
|
||||
static void ast2400_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
int i;
|
||||
AST2400State *s = AST2400(dev);
|
||||
Error *err = NULL;
|
||||
Error *err = NULL, *local_err = NULL;
|
||||
|
||||
/* IO space */
|
||||
memory_region_init_io(&s->iomem, NULL, &ast2400_io_ops, NULL,
|
||||
@@ -147,6 +161,30 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, AST2400_I2C_BASE);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
|
||||
qdev_get_gpio_in(DEVICE(&s->vic), 12));
|
||||
|
||||
/* SMC */
|
||||
object_property_set_int(OBJECT(&s->smc), 1, "num-cs", &err);
|
||||
object_property_set_bool(OBJECT(&s->smc), true, "realized", &local_err);
|
||||
error_propagate(&err, local_err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 0, AST2400_FMC_BASE);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 1, AST2400_FMC_FLASH_BASE);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->smc), 0,
|
||||
qdev_get_gpio_in(DEVICE(&s->vic), 19));
|
||||
|
||||
/* SPI */
|
||||
object_property_set_int(OBJECT(&s->spi), 1, "num-cs", &err);
|
||||
object_property_set_bool(OBJECT(&s->spi), true, "realized", &local_err);
|
||||
error_propagate(&err, local_err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
static void ast2400_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
@@ -51,7 +51,7 @@ static void fsl_imx25_init(Object *obj)
|
||||
}
|
||||
|
||||
for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
|
||||
object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX_GPT);
|
||||
object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX25_GPT);
|
||||
qdev_set_parent_bus(DEVICE(&s->gpt[i]), sysbus_get_default());
|
||||
}
|
||||
|
||||
@@ -249,16 +249,16 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
/* initialize 2 x 16 KB ROM */
|
||||
memory_region_init_rom_device(&s->rom[0], NULL, NULL, NULL,
|
||||
"imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
|
||||
memory_region_init_rom(&s->rom[0], NULL,
|
||||
"imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM0_ADDR,
|
||||
&s->rom[0]);
|
||||
memory_region_init_rom_device(&s->rom[1], NULL, NULL, NULL,
|
||||
"imx25.rom1", FSL_IMX25_ROM1_SIZE, &err);
|
||||
memory_region_init_rom(&s->rom[1], NULL,
|
||||
"imx25.rom1", FSL_IMX25_ROM1_SIZE, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
|
||||
@@ -47,7 +47,7 @@ static void fsl_imx31_init(Object *obj)
|
||||
qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus_get_default());
|
||||
}
|
||||
|
||||
object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX_GPT);
|
||||
object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX31_GPT);
|
||||
qdev_set_parent_bus(DEVICE(&s->gpt), sysbus_get_default());
|
||||
|
||||
for (i = 0; i < FSL_IMX31_NUM_EPITS; i++) {
|
||||
@@ -219,9 +219,8 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
/* On a real system, the first 16k is a `secure boot rom' */
|
||||
memory_region_init_rom_device(&s->secure_rom, NULL, NULL, NULL,
|
||||
"imx31.secure_rom",
|
||||
FSL_IMX31_SECURE_ROM_SIZE, &err);
|
||||
memory_region_init_rom(&s->secure_rom, NULL, "imx31.secure_rom",
|
||||
FSL_IMX31_SECURE_ROM_SIZE, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
@@ -230,8 +229,8 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
|
||||
&s->secure_rom);
|
||||
|
||||
/* There is also a 16k ROM */
|
||||
memory_region_init_rom_device(&s->rom, NULL, NULL, NULL, "imx31.rom",
|
||||
FSL_IMX31_ROM_SIZE, &err);
|
||||
memory_region_init_rom(&s->rom, NULL, "imx31.rom",
|
||||
FSL_IMX31_ROM_SIZE, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
|
||||
@@ -67,7 +67,7 @@ static void fsl_imx6_init(Object *obj)
|
||||
object_property_add_child(obj, name, OBJECT(&s->uart[i]), NULL);
|
||||
}
|
||||
|
||||
object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX_GPT);
|
||||
object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX6_GPT);
|
||||
qdev_set_parent_bus(DEVICE(&s->gpt), sysbus_get_default());
|
||||
object_property_add_child(obj, "gpt", OBJECT(&s->gpt), NULL);
|
||||
|
||||
@@ -399,8 +399,8 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
|
||||
FSL_IMX6_ENET_MAC_1588_IRQ));
|
||||
|
||||
/* ROM memory */
|
||||
memory_region_init_rom_device(&s->rom, NULL, NULL, NULL, "imx6.rom",
|
||||
FSL_IMX6_ROM_SIZE, &err);
|
||||
memory_region_init_rom(&s->rom, NULL, "imx6.rom",
|
||||
FSL_IMX6_ROM_SIZE, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
@@ -409,8 +409,8 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
|
||||
&s->rom);
|
||||
|
||||
/* CAAM memory */
|
||||
memory_region_init_rom_device(&s->caam, NULL, NULL, NULL, "imx6.caam",
|
||||
FSL_IMX6_CAAM_MEM_SIZE, &err);
|
||||
memory_region_init_rom(&s->caam, NULL, "imx6.caam",
|
||||
FSL_IMX6_CAAM_MEM_SIZE, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "hw/arm/ast2400.h"
|
||||
#include "hw/boards.h"
|
||||
#include "qemu/log.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
|
||||
static struct arm_boot_info palmetto_bmc_binfo = {
|
||||
.loader_start = AST2400_SDRAM_BASE,
|
||||
@@ -30,6 +32,32 @@ typedef struct PalmettoBMCState {
|
||||
MemoryRegion ram;
|
||||
} PalmettoBMCState;
|
||||
|
||||
static void palmetto_bmc_init_flashes(AspeedSMCState *s, const char *flashtype,
|
||||
Error **errp)
|
||||
{
|
||||
int i ;
|
||||
|
||||
for (i = 0; i < s->num_cs; ++i) {
|
||||
AspeedSMCFlash *fl = &s->flashes[i];
|
||||
DriveInfo *dinfo = drive_get_next(IF_MTD);
|
||||
qemu_irq cs_line;
|
||||
|
||||
/*
|
||||
* FIXME: check that we are not using a flash module exceeding
|
||||
* the controller segment size
|
||||
*/
|
||||
fl->flash = ssi_create_slave_no_init(s->spi, flashtype);
|
||||
if (dinfo) {
|
||||
qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo),
|
||||
errp);
|
||||
}
|
||||
qdev_init_nofail(fl->flash);
|
||||
|
||||
cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
|
||||
}
|
||||
}
|
||||
|
||||
static void palmetto_bmc_init(MachineState *machine)
|
||||
{
|
||||
PalmettoBMCState *bmc;
|
||||
@@ -49,6 +77,9 @@ static void palmetto_bmc_init(MachineState *machine)
|
||||
object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
|
||||
&error_abort);
|
||||
|
||||
palmetto_bmc_init_flashes(&bmc->soc.smc, "n25q256a", &error_abort);
|
||||
palmetto_bmc_init_flashes(&bmc->soc.spi, "mx25l25635e", &error_abort);
|
||||
|
||||
palmetto_bmc_binfo.kernel_filename = machine->kernel_filename;
|
||||
palmetto_bmc_binfo.initrd_filename = machine->initrd_filename;
|
||||
palmetto_bmc_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
|
||||
@@ -86,13 +86,19 @@ static void sabrelite_init(MachineState *machine)
|
||||
spi_bus = (SSIBus *)qdev_get_child_bus(DEVICE(spi_dev), "spi");
|
||||
if (spi_bus) {
|
||||
DeviceState *flash_dev;
|
||||
qemu_irq cs_line;
|
||||
DriveInfo *dinfo = drive_get_next(IF_MTD);
|
||||
|
||||
flash_dev = ssi_create_slave(spi_bus, "sst25vf016b");
|
||||
if (flash_dev) {
|
||||
qemu_irq cs_line = qdev_get_gpio_in_named(flash_dev,
|
||||
SSI_GPIO_CS, 0);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(spi_dev), 1, cs_line);
|
||||
flash_dev = ssi_create_slave_no_init(spi_bus, "sst25vf016b");
|
||||
if (dinfo) {
|
||||
qdev_prop_set_drive(flash_dev, "drive",
|
||||
blk_by_legacy_dinfo(dinfo),
|
||||
&error_fatal);
|
||||
}
|
||||
qdev_init_nofail(flash_dev);
|
||||
|
||||
cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(spi_dev), 1, cs_line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,15 +598,13 @@ static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spitz_lcdtg_init(SSISlave *dev)
|
||||
static void spitz_lcdtg_realize(SSISlave *dev, Error **errp)
|
||||
{
|
||||
SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
|
||||
|
||||
spitz_lcdtg = s;
|
||||
s->bl_power = 0;
|
||||
s->bl_intensity = 0x20;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SSP devices */
|
||||
@@ -666,7 +664,7 @@ static void spitz_adc_temp_on(void *opaque, int line, int level)
|
||||
max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
|
||||
}
|
||||
|
||||
static int corgi_ssp_init(SSISlave *d)
|
||||
static void corgi_ssp_realize(SSISlave *d, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(d);
|
||||
CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, d);
|
||||
@@ -675,8 +673,6 @@ static int corgi_ssp_init(SSISlave *d)
|
||||
s->bus[0] = ssi_create_bus(dev, "ssi0");
|
||||
s->bus[1] = ssi_create_bus(dev, "ssi1");
|
||||
s->bus[2] = ssi_create_bus(dev, "ssi2");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spitz_ssp_attach(PXA2xxState *cpu)
|
||||
@@ -1121,7 +1117,7 @@ static void corgi_ssp_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
||||
|
||||
k->init = corgi_ssp_init;
|
||||
k->realize = corgi_ssp_realize;
|
||||
k->transfer = corgi_ssp_transfer;
|
||||
dc->vmsd = &vmstate_corgi_ssp_regs;
|
||||
}
|
||||
@@ -1150,7 +1146,7 @@ static void spitz_lcdtg_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
||||
|
||||
k->init = spitz_lcdtg_init;
|
||||
k->realize = spitz_lcdtg_realize;
|
||||
k->transfer = spitz_lcdtg_transfer;
|
||||
dc->vmsd = &vmstate_spitz_lcdtg_regs;
|
||||
}
|
||||
|
||||
@@ -127,10 +127,9 @@ static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tosa_ssp_init(SSISlave *dev)
|
||||
static void tosa_ssp_realize(SSISlave *dev, Error **errp)
|
||||
{
|
||||
/* Nothing to do. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TYPE_TOSA_DAC "tosa_dac"
|
||||
@@ -283,7 +282,7 @@ static void tosa_ssp_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
||||
|
||||
k->init = tosa_ssp_init;
|
||||
k->realize = tosa_ssp_realize;
|
||||
k->transfer = tosa_ssp_tansfer;
|
||||
}
|
||||
|
||||
|
||||
@@ -1021,6 +1021,7 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic,
|
||||
qemu_fdt_setprop_cell(vbi->fdt, nodename, "#size-cells", 2);
|
||||
qemu_fdt_setprop_cells(vbi->fdt, nodename, "bus-range", 0,
|
||||
nr_pcie_buses - 1);
|
||||
qemu_fdt_setprop(vbi->fdt, nodename, "dma-coherent", NULL, 0);
|
||||
|
||||
if (vbi->v2m_phandle) {
|
||||
qemu_fdt_setprop_cells(vbi->fdt, nodename, "msi-parent",
|
||||
@@ -1175,6 +1176,10 @@ static void machvirt_init(MachineState *machine)
|
||||
VirtGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
|
||||
VirtGuestInfo *guest_info = &guest_info_state->info;
|
||||
char **cpustr;
|
||||
ObjectClass *oc;
|
||||
const char *typename;
|
||||
CPUClass *cc;
|
||||
Error *err = NULL;
|
||||
bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
|
||||
|
||||
if (!cpu_model) {
|
||||
@@ -1258,26 +1263,24 @@ static void machvirt_init(MachineState *machine)
|
||||
|
||||
create_fdt(vbi);
|
||||
|
||||
oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]);
|
||||
if (!oc) {
|
||||
error_report("Unable to find CPU definition");
|
||||
exit(1);
|
||||
}
|
||||
typename = object_class_get_name(oc);
|
||||
|
||||
/* convert -smp CPU options specified by the user into global props */
|
||||
cc = CPU_CLASS(oc);
|
||||
cc->parse_features(typename, cpustr[1], &err);
|
||||
g_strfreev(cpustr);
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (n = 0; n < smp_cpus; n++) {
|
||||
ObjectClass *oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]);
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
Object *cpuobj;
|
||||
Error *err = NULL;
|
||||
char *cpuopts = g_strdup(cpustr[1]);
|
||||
|
||||
if (!oc) {
|
||||
error_report("Unable to find CPU definition");
|
||||
exit(1);
|
||||
}
|
||||
cpuobj = object_new(object_class_get_name(oc));
|
||||
|
||||
/* Handle any CPU options specified by the user */
|
||||
cc->parse_features(CPU(cpuobj), cpuopts, &err);
|
||||
g_free(cpuopts);
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
exit(1);
|
||||
}
|
||||
Object *cpuobj = object_new(typename);
|
||||
|
||||
if (!vms->secure) {
|
||||
object_property_set_bool(cpuobj, false, "has_el3", NULL);
|
||||
@@ -1308,7 +1311,6 @@ static void machvirt_init(MachineState *machine)
|
||||
|
||||
object_property_set_bool(cpuobj, true, "realized", NULL);
|
||||
}
|
||||
g_strfreev(cpustr);
|
||||
fdt_add_timer_nodes(vbi, gic_version);
|
||||
fdt_add_cpu_nodes(vbi);
|
||||
fdt_add_psci_node(vbi);
|
||||
|
||||
@@ -138,7 +138,13 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
|
||||
spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
|
||||
|
||||
for (j = 0; j < num_ss; ++j) {
|
||||
flash_dev = ssi_create_slave(spi, "n25q128");
|
||||
DriveInfo *dinfo = drive_get_next(IF_MTD);
|
||||
flash_dev = ssi_create_slave_no_init(spi, "n25q128");
|
||||
if (dinfo) {
|
||||
qdev_prop_set_drive(flash_dev, "drive",
|
||||
blk_by_legacy_dinfo(dinfo), &error_fatal);
|
||||
}
|
||||
qdev_init_nofail(flash_dev);
|
||||
|
||||
cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
|
||||
sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line);
|
||||
@@ -294,6 +300,12 @@ static void zynq_init(MachineState *machine)
|
||||
sysbus_connect_irq(busdev, n + 1, pic[dma_irqs[n] - IRQ_OFFSET]);
|
||||
}
|
||||
|
||||
dev = qdev_create(NULL, "xlnx.ps7-dev-cfg");
|
||||
qdev_init_nofail(dev);
|
||||
busdev = SYS_BUS_DEVICE(dev);
|
||||
sysbus_connect_irq(busdev, 0, pic[40 - IRQ_OFFSET]);
|
||||
sysbus_mmio_map(busdev, 0, 0xF8007000);
|
||||
|
||||
zynq_binfo.ram_size = ram_size;
|
||||
zynq_binfo.kernel_filename = kernel_filename;
|
||||
zynq_binfo.kernel_cmdline = kernel_cmdline;
|
||||
|
||||
@@ -88,12 +88,19 @@ static void xlnx_ep108_init(MachineState *machine)
|
||||
SSIBus *spi_bus;
|
||||
DeviceState *flash_dev;
|
||||
qemu_irq cs_line;
|
||||
DriveInfo *dinfo = drive_get_next(IF_MTD);
|
||||
gchar *bus_name = g_strdup_printf("spi%d", i);
|
||||
|
||||
spi_bus = (SSIBus *)qdev_get_child_bus(DEVICE(&s->soc), bus_name);
|
||||
g_free(bus_name);
|
||||
|
||||
flash_dev = ssi_create_slave(spi_bus, "sst25wf080");
|
||||
flash_dev = ssi_create_slave_no_init(spi_bus, "sst25wf080");
|
||||
if (dinfo) {
|
||||
qdev_prop_set_drive(flash_dev, "drive", blk_by_legacy_dinfo(dinfo),
|
||||
&error_fatal);
|
||||
}
|
||||
qdev_init_nofail(flash_dev);
|
||||
|
||||
cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
|
||||
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.spi[i]), 1, cs_line);
|
||||
|
||||
@@ -151,14 +151,12 @@ static void z2_lcd_cs(void *opaque, int line, int level)
|
||||
z2_lcd->selected = !level;
|
||||
}
|
||||
|
||||
static int zipit_lcd_init(SSISlave *dev)
|
||||
static void zipit_lcd_realize(SSISlave *dev, Error **errp)
|
||||
{
|
||||
ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
|
||||
z->selected = 0;
|
||||
z->enabled = 0;
|
||||
z->pos = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static VMStateDescription vmstate_zipit_lcd_state = {
|
||||
@@ -181,7 +179,7 @@ static void zipit_lcd_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
||||
|
||||
k->init = zipit_lcd_init;
|
||||
k->realize = zipit_lcd_realize;
|
||||
k->transfer = zipit_lcd_transfer;
|
||||
dc->vmsd = &vmstate_zipit_lcd_state;
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ struct IntelHDAState {
|
||||
|
||||
/* properties */
|
||||
uint32_t debug;
|
||||
uint32_t msi;
|
||||
OnOffAuto msi;
|
||||
bool old_msi_addr;
|
||||
};
|
||||
|
||||
@@ -256,7 +256,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d)
|
||||
|
||||
static void intel_hda_update_irq(IntelHDAState *d)
|
||||
{
|
||||
int msi = d->msi && msi_enabled(&d->pci);
|
||||
bool msi = msi_enabled(&d->pci);
|
||||
int level;
|
||||
|
||||
intel_hda_update_int_sts(d);
|
||||
@@ -1132,6 +1132,8 @@ static void intel_hda_realize(PCIDevice *pci, Error **errp)
|
||||
{
|
||||
IntelHDAState *d = INTEL_HDA(pci);
|
||||
uint8_t *conf = d->pci.config;
|
||||
Error *err = NULL;
|
||||
int ret;
|
||||
|
||||
d->name = object_get_typename(OBJECT(d));
|
||||
|
||||
@@ -1140,12 +1142,27 @@ static void intel_hda_realize(PCIDevice *pci, Error **errp)
|
||||
/* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
|
||||
conf[0x40] = 0x01;
|
||||
|
||||
if (d->msi != ON_OFF_AUTO_OFF) {
|
||||
ret = msi_init(&d->pci, d->old_msi_addr ? 0x50 : 0x60,
|
||||
1, true, false, &err);
|
||||
/* Any error other than -ENOTSUP(board's MSI support is broken)
|
||||
* is a programming error */
|
||||
assert(!ret || ret == -ENOTSUP);
|
||||
if (ret && d->msi == ON_OFF_AUTO_ON) {
|
||||
/* Can't satisfy user's explicit msi=on request, fail */
|
||||
error_append_hint(&err, "You have to use msi=auto (default) or "
|
||||
"msi=off with this machine type.\n");
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
assert(!err || d->msi == ON_OFF_AUTO_AUTO);
|
||||
/* With msi=auto, we fall back to MSI off silently */
|
||||
error_free(err);
|
||||
}
|
||||
|
||||
memory_region_init_io(&d->mmio, OBJECT(d), &intel_hda_mmio_ops, d,
|
||||
"intel-hda", 0x4000);
|
||||
pci_register_bar(&d->pci, 0, 0, &d->mmio);
|
||||
if (d->msi) {
|
||||
msi_init(&d->pci, d->old_msi_addr ? 0x50 : 0x60, 1, true, false);
|
||||
}
|
||||
|
||||
hda_codec_bus_init(DEVICE(pci), &d->codecs, sizeof(d->codecs),
|
||||
intel_hda_response, intel_hda_xfer);
|
||||
@@ -1235,7 +1252,7 @@ static const VMStateDescription vmstate_intel_hda = {
|
||||
|
||||
static Property intel_hda_properties[] = {
|
||||
DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0),
|
||||
DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1),
|
||||
DEFINE_PROP_ON_OFF_AUTO("msi", IntelHDAState, msi, ON_OFF_AUTO_AUTO),
|
||||
DEFINE_PROP_BOOL("old_msi_addr", IntelHDAState, old_msi_addr, false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "hw/ssi/ssi.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#ifndef M25P80_ERR_DEBUG
|
||||
#define M25P80_ERR_DEBUG 0
|
||||
@@ -389,7 +390,7 @@ typedef struct Flash {
|
||||
uint32_t pos;
|
||||
uint8_t needed_bytes;
|
||||
uint8_t cmd_in_progress;
|
||||
uint64_t cur_addr;
|
||||
uint32_t cur_addr;
|
||||
uint32_t nonvolatile_cfg;
|
||||
/* Configuration register for Macronix */
|
||||
uint32_t volatile_cfg;
|
||||
@@ -446,6 +447,11 @@ static inline Manufacturer get_man(Flash *s)
|
||||
|
||||
static void blk_sync_complete(void *opaque, int ret)
|
||||
{
|
||||
QEMUIOVector *iov = opaque;
|
||||
|
||||
qemu_iovec_destroy(iov);
|
||||
g_free(iov);
|
||||
|
||||
/* do nothing. Masters do not directly interact with the backing store,
|
||||
* only the working copy so no mutexing required.
|
||||
*/
|
||||
@@ -453,31 +459,33 @@ static void blk_sync_complete(void *opaque, int ret)
|
||||
|
||||
static void flash_sync_page(Flash *s, int page)
|
||||
{
|
||||
QEMUIOVector iov;
|
||||
QEMUIOVector *iov;
|
||||
|
||||
if (!s->blk || blk_is_read_only(s->blk)) {
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_iovec_init(&iov, 1);
|
||||
qemu_iovec_add(&iov, s->storage + page * s->pi->page_size,
|
||||
iov = g_new(QEMUIOVector, 1);
|
||||
qemu_iovec_init(iov, 1);
|
||||
qemu_iovec_add(iov, s->storage + page * s->pi->page_size,
|
||||
s->pi->page_size);
|
||||
blk_aio_pwritev(s->blk, page * s->pi->page_size, &iov, 0,
|
||||
blk_sync_complete, NULL);
|
||||
blk_aio_pwritev(s->blk, page * s->pi->page_size, iov, 0,
|
||||
blk_sync_complete, iov);
|
||||
}
|
||||
|
||||
static inline void flash_sync_area(Flash *s, int64_t off, int64_t len)
|
||||
{
|
||||
QEMUIOVector iov;
|
||||
QEMUIOVector *iov;
|
||||
|
||||
if (!s->blk || blk_is_read_only(s->blk)) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(!(len % BDRV_SECTOR_SIZE));
|
||||
qemu_iovec_init(&iov, 1);
|
||||
qemu_iovec_add(&iov, s->storage + off, len);
|
||||
blk_aio_pwritev(s->blk, off, &iov, 0, blk_sync_complete, NULL);
|
||||
iov = g_new(QEMUIOVector, 1);
|
||||
qemu_iovec_init(iov, 1);
|
||||
qemu_iovec_add(iov, s->storage + off, len);
|
||||
blk_aio_pwritev(s->blk, off, iov, 0, blk_sync_complete, iov);
|
||||
}
|
||||
|
||||
static void flash_erase(Flash *s, int offset, FlashCMD cmd)
|
||||
@@ -530,9 +538,9 @@ static inline void flash_sync_dirty(Flash *s, int64_t newpage)
|
||||
}
|
||||
|
||||
static inline
|
||||
void flash_write8(Flash *s, uint64_t addr, uint8_t data)
|
||||
void flash_write8(Flash *s, uint32_t addr, uint8_t data)
|
||||
{
|
||||
int64_t page = addr / s->pi->page_size;
|
||||
uint32_t page = addr / s->pi->page_size;
|
||||
uint8_t prev = s->storage[s->cur_addr];
|
||||
|
||||
if (!s->write_enable) {
|
||||
@@ -540,7 +548,7 @@ void flash_write8(Flash *s, uint64_t addr, uint8_t data)
|
||||
}
|
||||
|
||||
if ((prev ^ data) & data) {
|
||||
DB_PRINT_L(1, "programming zero to one! addr=%" PRIx64 " %" PRIx8
|
||||
DB_PRINT_L(1, "programming zero to one! addr=%" PRIx32 " %" PRIx8
|
||||
" -> %" PRIx8 "\n", addr, prev, data);
|
||||
}
|
||||
|
||||
@@ -581,18 +589,16 @@ static inline int get_addr_length(Flash *s)
|
||||
|
||||
static void complete_collecting_data(Flash *s)
|
||||
{
|
||||
int i;
|
||||
int i, n;
|
||||
|
||||
s->cur_addr = 0;
|
||||
|
||||
for (i = 0; i < get_addr_length(s); ++i) {
|
||||
n = get_addr_length(s);
|
||||
s->cur_addr = (n == 3 ? s->ear : 0);
|
||||
for (i = 0; i < n; ++i) {
|
||||
s->cur_addr <<= 8;
|
||||
s->cur_addr |= s->data[i];
|
||||
}
|
||||
|
||||
if (get_addr_length(s) == 3) {
|
||||
s->cur_addr += s->ear * MAX_3BYTES_SIZE;
|
||||
}
|
||||
s->cur_addr &= s->size - 1;
|
||||
|
||||
s->state = STATE_IDLE;
|
||||
|
||||
@@ -1091,17 +1097,17 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
|
||||
switch (s->state) {
|
||||
|
||||
case STATE_PAGE_PROGRAM:
|
||||
DB_PRINT_L(1, "page program cur_addr=%#" PRIx64 " data=%" PRIx8 "\n",
|
||||
DB_PRINT_L(1, "page program cur_addr=%#" PRIx32 " data=%" PRIx8 "\n",
|
||||
s->cur_addr, (uint8_t)tx);
|
||||
flash_write8(s, s->cur_addr, (uint8_t)tx);
|
||||
s->cur_addr++;
|
||||
s->cur_addr = (s->cur_addr + 1) & (s->size - 1);
|
||||
break;
|
||||
|
||||
case STATE_READ:
|
||||
r = s->storage[s->cur_addr];
|
||||
DB_PRINT_L(1, "READ 0x%" PRIx64 "=%" PRIx8 "\n", s->cur_addr,
|
||||
DB_PRINT_L(1, "READ 0x%" PRIx32 "=%" PRIx8 "\n", s->cur_addr,
|
||||
(uint8_t)r);
|
||||
s->cur_addr = (s->cur_addr + 1) % s->size;
|
||||
s->cur_addr = (s->cur_addr + 1) & (s->size - 1);
|
||||
break;
|
||||
|
||||
case STATE_COLLECTING_DATA:
|
||||
@@ -1132,9 +1138,8 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int m25p80_init(SSISlave *ss)
|
||||
static void m25p80_realize(SSISlave *ss, Error **errp)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
Flash *s = M25P80(ss);
|
||||
M25P80Class *mc = M25P80_GET_CLASS(s);
|
||||
|
||||
@@ -1143,28 +1148,19 @@ static int m25p80_init(SSISlave *ss)
|
||||
s->size = s->pi->sector_size * s->pi->n_sectors;
|
||||
s->dirty_page = -1;
|
||||
|
||||
/* FIXME use a qdev drive property instead of drive_get_next() */
|
||||
dinfo = drive_get_next(IF_MTD);
|
||||
|
||||
if (dinfo) {
|
||||
if (s->blk) {
|
||||
DB_PRINT_L(0, "Binding to IF_MTD drive\n");
|
||||
s->blk = blk_by_legacy_dinfo(dinfo);
|
||||
blk_attach_dev_nofail(s->blk, s);
|
||||
|
||||
s->storage = blk_blockalign(s->blk, s->size);
|
||||
|
||||
/* FIXME: Move to late init */
|
||||
if (blk_pread(s->blk, 0, s->storage, s->size) != s->size) {
|
||||
fprintf(stderr, "Failed to initialize SPI flash!\n");
|
||||
return 1;
|
||||
error_setg(errp, "failed to read the initial flash content");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
DB_PRINT_L(0, "No BDRV - binding to RAM\n");
|
||||
s->storage = blk_blockalign(NULL, s->size);
|
||||
memset(s->storage, 0xFF, s->size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void m25p80_reset(DeviceState *d)
|
||||
@@ -1186,6 +1182,7 @@ static Property m25p80_properties[] = {
|
||||
DEFINE_PROP_UINT8("spansion-cr2nv", Flash, spansion_cr2nv, 0x8),
|
||||
DEFINE_PROP_UINT8("spansion-cr3nv", Flash, spansion_cr3nv, 0x2),
|
||||
DEFINE_PROP_UINT8("spansion-cr4nv", Flash, spansion_cr4nv, 0x10),
|
||||
DEFINE_PROP_DRIVE("drive", Flash, blk),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -1201,7 +1198,8 @@ static const VMStateDescription vmstate_m25p80 = {
|
||||
VMSTATE_UINT32(pos, Flash),
|
||||
VMSTATE_UINT8(needed_bytes, Flash),
|
||||
VMSTATE_UINT8(cmd_in_progress, Flash),
|
||||
VMSTATE_UINT64(cur_addr, Flash),
|
||||
VMSTATE_UNUSED(4),
|
||||
VMSTATE_UINT32(cur_addr, Flash),
|
||||
VMSTATE_BOOL(write_enable, Flash),
|
||||
VMSTATE_BOOL_V(reset_enable, Flash, 2),
|
||||
VMSTATE_UINT8_V(ear, Flash, 2),
|
||||
@@ -1224,7 +1222,7 @@ static void m25p80_class_init(ObjectClass *klass, void *data)
|
||||
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
||||
M25P80Class *mc = M25P80_CLASS(klass);
|
||||
|
||||
k->init = m25p80_init;
|
||||
k->realize = m25p80_realize;
|
||||
k->transfer = m25p80_transfer8;
|
||||
k->set_cs = m25p80_cs;
|
||||
k->cs_polarity = SSI_CS_LOW;
|
||||
|
||||
@@ -384,7 +384,7 @@ static int multireq_compare(const void *a, const void *b)
|
||||
void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
|
||||
{
|
||||
int i = 0, start = 0, num_reqs = 0, niov = 0, nb_sectors = 0;
|
||||
int max_xfer_len = 0;
|
||||
uint32_t max_transfer;
|
||||
int64_t sector_num = 0;
|
||||
|
||||
if (mrb->num_reqs == 1) {
|
||||
@@ -393,8 +393,7 @@ void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
|
||||
return;
|
||||
}
|
||||
|
||||
max_xfer_len = blk_get_max_transfer_length(mrb->reqs[0]->dev->blk);
|
||||
max_xfer_len = MIN_NON_ZERO(max_xfer_len, BDRV_REQUEST_MAX_SECTORS);
|
||||
max_transfer = blk_get_max_transfer(mrb->reqs[0]->dev->blk);
|
||||
|
||||
qsort(mrb->reqs, mrb->num_reqs, sizeof(*mrb->reqs),
|
||||
&multireq_compare);
|
||||
@@ -410,8 +409,9 @@ void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
|
||||
*/
|
||||
if (sector_num + nb_sectors != req->sector_num ||
|
||||
niov > blk_get_max_iov(blk) - req->qiov.niov ||
|
||||
req->qiov.size / BDRV_SECTOR_SIZE > max_xfer_len ||
|
||||
nb_sectors > max_xfer_len - req->qiov.size / BDRV_SECTOR_SIZE) {
|
||||
req->qiov.size > max_transfer ||
|
||||
nb_sectors > (max_transfer -
|
||||
req->qiov.size) / BDRV_SECTOR_SIZE) {
|
||||
submit_requests(blk, mrb, start, num_reqs, niov);
|
||||
num_reqs = 0;
|
||||
}
|
||||
|
||||
@@ -15,4 +15,5 @@ common-obj-$(CONFIG_SOFTMMU) += machine.o
|
||||
common-obj-$(CONFIG_SOFTMMU) += null-machine.o
|
||||
common-obj-$(CONFIG_SOFTMMU) += loader.o
|
||||
common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
|
||||
common-obj-$(CONFIG_SOFTMMU) += register.o
|
||||
common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
|
||||
|
||||
@@ -300,20 +300,6 @@ static void machine_set_firmware(Object *obj, const char *value, Error **errp)
|
||||
ms->firmware = g_strdup(value);
|
||||
}
|
||||
|
||||
static bool machine_get_iommu(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return ms->iommu;
|
||||
}
|
||||
|
||||
static void machine_set_iommu(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->iommu = value;
|
||||
}
|
||||
|
||||
static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
@@ -493,12 +479,6 @@ static void machine_initfn(Object *obj)
|
||||
object_property_set_description(obj, "firmware",
|
||||
"Firmware image",
|
||||
NULL);
|
||||
object_property_add_bool(obj, "iommu",
|
||||
machine_get_iommu,
|
||||
machine_set_iommu, NULL);
|
||||
object_property_set_description(obj, "iommu",
|
||||
"Set on/off to enable/disable Intel IOMMU (VT-d)",
|
||||
NULL);
|
||||
object_property_add_bool(obj, "suppress-vmdesc",
|
||||
machine_get_suppress_vmdesc,
|
||||
machine_set_suppress_vmdesc, NULL);
|
||||
@@ -580,6 +560,24 @@ static void machine_class_finalize(ObjectClass *klass, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
void machine_register_compat_props(MachineState *machine)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
int i;
|
||||
GlobalProperty *p;
|
||||
|
||||
if (!mc->compat_props) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < mc->compat_props->len; i++) {
|
||||
p = g_array_index(mc->compat_props, GlobalProperty *, i);
|
||||
/* Machine compat_props must never cause errors: */
|
||||
p->errp = &error_abort;
|
||||
qdev_prop_register_global(p);
|
||||
}
|
||||
}
|
||||
|
||||
static const TypeInfo machine_info = {
|
||||
.name = TYPE_MACHINE,
|
||||
.parent = TYPE_OBJECT,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* qdev property parsing and global properties
|
||||
* qdev property parsing
|
||||
* (parts specific for qemu-system-*)
|
||||
*
|
||||
* This file is based on code from hw/qdev-properties.c from
|
||||
@@ -82,7 +82,7 @@ static void parse_drive(DeviceState *dev, const char *str, void **ptr,
|
||||
if (blk_attach_dev(blk, dev) < 0) {
|
||||
DriveInfo *dinfo = blk_legacy_dinfo(blk);
|
||||
|
||||
if (dinfo->type != IF_NONE) {
|
||||
if (dinfo && dinfo->type != IF_NONE) {
|
||||
error_setg(errp, "Drive '%s' is already in use because "
|
||||
"it has been automatically connected to another "
|
||||
"device (did you need 'if=none' in the drive options?)",
|
||||
@@ -394,22 +394,3 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
|
||||
}
|
||||
nd->instantiated = 1;
|
||||
}
|
||||
|
||||
static int qdev_add_one_global(void *opaque, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
GlobalProperty *g;
|
||||
|
||||
g = g_malloc0(sizeof(*g));
|
||||
g->driver = qemu_opt_get(opts, "driver");
|
||||
g->property = qemu_opt_get(opts, "property");
|
||||
g->value = qemu_opt_get(opts, "value");
|
||||
g->user_provided = true;
|
||||
qdev_prop_register_global(g);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qemu_add_globals(void)
|
||||
{
|
||||
qemu_opts_foreach(qemu_find_opts("global"),
|
||||
qdev_add_one_global, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -1085,10 +1085,14 @@ static void qdev_prop_set_globals_for_type(DeviceState *dev,
|
||||
prop->used = true;
|
||||
object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
|
||||
if (err != NULL) {
|
||||
assert(prop->user_provided);
|
||||
error_reportf_err(err, "Warning: global %s.%s=%s ignored: ",
|
||||
prop->driver, prop->property, prop->value);
|
||||
return;
|
||||
error_prepend(&err, "can't apply global %s.%s=%s: ",
|
||||
prop->driver, prop->property, prop->value);
|
||||
if (prop->errp) {
|
||||
error_propagate(prop->errp, err);
|
||||
} else {
|
||||
assert(prop->user_provided);
|
||||
error_reportf_err(err, "Warning: ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
287
hw/core/register.c
Normal file
287
hw/core/register.c
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Register Definition API
|
||||
*
|
||||
* Copyright (c) 2016 Xilinx Inc.
|
||||
* Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/register.h"
|
||||
#include "hw/qdev.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
static inline void register_write_val(RegisterInfo *reg, uint64_t val)
|
||||
{
|
||||
g_assert(reg->data);
|
||||
|
||||
switch (reg->data_size) {
|
||||
case 1:
|
||||
*(uint8_t *)reg->data = val;
|
||||
break;
|
||||
case 2:
|
||||
*(uint16_t *)reg->data = val;
|
||||
break;
|
||||
case 4:
|
||||
*(uint32_t *)reg->data = val;
|
||||
break;
|
||||
case 8:
|
||||
*(uint64_t *)reg->data = val;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t register_read_val(RegisterInfo *reg)
|
||||
{
|
||||
switch (reg->data_size) {
|
||||
case 1:
|
||||
return *(uint8_t *)reg->data;
|
||||
case 2:
|
||||
return *(uint16_t *)reg->data;
|
||||
case 4:
|
||||
return *(uint32_t *)reg->data;
|
||||
case 8:
|
||||
return *(uint64_t *)reg->data;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return 0; /* unreachable */
|
||||
}
|
||||
|
||||
void register_write(RegisterInfo *reg, uint64_t val, uint64_t we,
|
||||
const char *prefix, bool debug)
|
||||
{
|
||||
uint64_t old_val, new_val, test, no_w_mask;
|
||||
const RegisterAccessInfo *ac;
|
||||
|
||||
assert(reg);
|
||||
|
||||
ac = reg->access;
|
||||
|
||||
if (!ac || !ac->name) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
|
||||
"(written value: %#" PRIx64 ")\n", prefix, val);
|
||||
return;
|
||||
}
|
||||
|
||||
old_val = reg->data ? register_read_val(reg) : ac->reset;
|
||||
|
||||
test = (old_val ^ val) & ac->rsvd;
|
||||
if (test) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: change of value in reserved bit"
|
||||
"fields: %#" PRIx64 ")\n", prefix, test);
|
||||
}
|
||||
|
||||
test = val & ac->unimp;
|
||||
if (test) {
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"%s:%s writing %#" PRIx64 " to unimplemented bits:" \
|
||||
" %#" PRIx64 "",
|
||||
prefix, reg->access->name, val, ac->unimp);
|
||||
}
|
||||
|
||||
/* Create the no write mask based on the read only, write to clear and
|
||||
* reserved bit masks.
|
||||
*/
|
||||
no_w_mask = ac->ro | ac->w1c | ac->rsvd | ~we;
|
||||
new_val = (val & ~no_w_mask) | (old_val & no_w_mask);
|
||||
new_val &= ~(val & ac->w1c);
|
||||
|
||||
if (ac->pre_write) {
|
||||
new_val = ac->pre_write(reg, new_val);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
qemu_log("%s:%s: write of value %#" PRIx64 "\n", prefix, ac->name,
|
||||
new_val);
|
||||
}
|
||||
|
||||
register_write_val(reg, new_val);
|
||||
|
||||
if (ac->post_write) {
|
||||
ac->post_write(reg, new_val);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t register_read(RegisterInfo *reg, uint64_t re, const char* prefix,
|
||||
bool debug)
|
||||
{
|
||||
uint64_t ret;
|
||||
const RegisterAccessInfo *ac;
|
||||
|
||||
assert(reg);
|
||||
|
||||
ac = reg->access;
|
||||
if (!ac || !ac->name) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: read from undefined device state\n",
|
||||
prefix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = reg->data ? register_read_val(reg) : ac->reset;
|
||||
|
||||
register_write_val(reg, ret & ~(ac->cor & re));
|
||||
|
||||
/* Mask based on the read enable size */
|
||||
ret &= re;
|
||||
|
||||
if (ac->post_read) {
|
||||
ret = ac->post_read(reg, ret);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
qemu_log("%s:%s: read of value %#" PRIx64 "\n", prefix,
|
||||
ac->name, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void register_reset(RegisterInfo *reg)
|
||||
{
|
||||
g_assert(reg);
|
||||
|
||||
if (!reg->data || !reg->access) {
|
||||
return;
|
||||
}
|
||||
|
||||
register_write_val(reg, reg->access->reset);
|
||||
}
|
||||
|
||||
void register_init(RegisterInfo *reg)
|
||||
{
|
||||
assert(reg);
|
||||
|
||||
if (!reg->data || !reg->access) {
|
||||
return;
|
||||
}
|
||||
|
||||
object_initialize((void *)reg, sizeof(*reg), TYPE_REGISTER);
|
||||
}
|
||||
|
||||
void register_write_memory(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
RegisterInfoArray *reg_array = opaque;
|
||||
RegisterInfo *reg = NULL;
|
||||
uint64_t we;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < reg_array->num_elements; i++) {
|
||||
if (reg_array->r[i]->access->addr == addr) {
|
||||
reg = reg_array->r[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!reg) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "Write to unimplemented register at " \
|
||||
"address: %#" PRIx64 "\n", addr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate appropriate write enable mask */
|
||||
if (reg->data_size < size) {
|
||||
we = MAKE_64BIT_MASK(0, reg->data_size * 8);
|
||||
} else {
|
||||
we = MAKE_64BIT_MASK(0, size * 8);
|
||||
}
|
||||
|
||||
register_write(reg, value, we, reg_array->prefix,
|
||||
reg_array->debug);
|
||||
}
|
||||
|
||||
uint64_t register_read_memory(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
RegisterInfoArray *reg_array = opaque;
|
||||
RegisterInfo *reg = NULL;
|
||||
uint64_t read_val;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < reg_array->num_elements; i++) {
|
||||
if (reg_array->r[i]->access->addr == addr) {
|
||||
reg = reg_array->r[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!reg) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "Read to unimplemented register at " \
|
||||
"address: %#" PRIx64 "\n", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read_val = register_read(reg, size * 8, reg_array->prefix,
|
||||
reg_array->debug);
|
||||
|
||||
return extract64(read_val, 0, size * 8);
|
||||
}
|
||||
|
||||
RegisterInfoArray *register_init_block32(DeviceState *owner,
|
||||
const RegisterAccessInfo *rae,
|
||||
int num, RegisterInfo *ri,
|
||||
uint32_t *data,
|
||||
const MemoryRegionOps *ops,
|
||||
bool debug_enabled,
|
||||
uint64_t memory_size)
|
||||
{
|
||||
const char *device_prefix = object_get_typename(OBJECT(owner));
|
||||
RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1);
|
||||
int i;
|
||||
|
||||
r_array->r = g_new0(RegisterInfo *, num);
|
||||
r_array->num_elements = num;
|
||||
r_array->debug = debug_enabled;
|
||||
r_array->prefix = device_prefix;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
int index = rae[i].addr / 4;
|
||||
RegisterInfo *r = &ri[index];
|
||||
|
||||
*r = (RegisterInfo) {
|
||||
.data = &data[index],
|
||||
.data_size = sizeof(uint32_t),
|
||||
.access = &rae[i],
|
||||
.opaque = owner,
|
||||
};
|
||||
register_init(r);
|
||||
|
||||
r_array->r[i] = r;
|
||||
}
|
||||
|
||||
memory_region_init_io(&r_array->mem, OBJECT(owner), ops, r_array,
|
||||
device_prefix, memory_size);
|
||||
|
||||
return r_array;
|
||||
}
|
||||
|
||||
void register_finalize_block(RegisterInfoArray *r_array)
|
||||
{
|
||||
object_unparent(OBJECT(&r_array->mem));
|
||||
g_free(r_array->r);
|
||||
g_free(r_array);
|
||||
}
|
||||
|
||||
static const TypeInfo register_info = {
|
||||
.name = TYPE_REGISTER,
|
||||
.parent = TYPE_DEVICE,
|
||||
};
|
||||
|
||||
static void register_register_types(void)
|
||||
{
|
||||
type_register_static(®ister_info);
|
||||
}
|
||||
|
||||
type_init(register_register_types)
|
||||
@@ -133,7 +133,7 @@ static const VMStateDescription vmstate_ads7846 = {
|
||||
}
|
||||
};
|
||||
|
||||
static int ads7846_init(SSISlave *d)
|
||||
static void ads7846_realize(SSISlave *d, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(d);
|
||||
ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, d);
|
||||
@@ -152,14 +152,13 @@ static int ads7846_init(SSISlave *d)
|
||||
ads7846_int_update(s);
|
||||
|
||||
vmstate_register(NULL, -1, &vmstate_ads7846, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ads7846_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
||||
|
||||
k->init = ads7846_init;
|
||||
k->realize = ads7846_realize;
|
||||
k->transfer = ads7846_transfer;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/misc/aux.h"
|
||||
#include "hw/misc/auxbus.h"
|
||||
#include "hw/display/dpcd.h"
|
||||
|
||||
#ifndef DEBUG_DPCD
|
||||
|
||||
126
hw/display/qxl.c
126
hw/display/qxl.c
@@ -504,6 +504,7 @@ static void interface_set_compression_level(QXLInstance *sin, int level)
|
||||
qxl_rom_set_dirty(qxl);
|
||||
}
|
||||
|
||||
#if SPICE_NEEDS_SET_MM_TIME
|
||||
static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
|
||||
{
|
||||
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
|
||||
@@ -517,6 +518,7 @@ static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
|
||||
qxl->rom->mm_clock = cpu_to_le32(mm_time);
|
||||
qxl_rom_set_dirty(qxl);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
|
||||
{
|
||||
@@ -893,7 +895,8 @@ static void interface_update_area_complete(QXLInstance *sin,
|
||||
int qxl_i;
|
||||
|
||||
qemu_mutex_lock(&qxl->ssd.lock);
|
||||
if (surface_id != 0 || !qxl->render_update_cookie_num) {
|
||||
if (surface_id != 0 || !num_updated_rects ||
|
||||
!qxl->render_update_cookie_num) {
|
||||
qemu_mutex_unlock(&qxl->ssd.lock);
|
||||
return;
|
||||
}
|
||||
@@ -1068,7 +1071,9 @@ static const QXLInterface qxl_interface = {
|
||||
|
||||
.attache_worker = interface_attach_worker,
|
||||
.set_compression_level = interface_set_compression_level,
|
||||
#if SPICE_NEEDS_SET_MM_TIME
|
||||
.set_mm_time = interface_set_mm_time,
|
||||
#endif
|
||||
.get_init_info = interface_get_init_info,
|
||||
|
||||
/* the callbacks below are called from spice server thread context */
|
||||
@@ -1243,6 +1248,7 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
|
||||
int pci_region;
|
||||
pcibus_t pci_start;
|
||||
pcibus_t pci_end;
|
||||
MemoryRegion *mr;
|
||||
intptr_t virt_start;
|
||||
QXLDevMemSlot memslot;
|
||||
int i;
|
||||
@@ -1289,11 +1295,11 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
|
||||
|
||||
switch (pci_region) {
|
||||
case QXL_RAM_RANGE_INDEX:
|
||||
virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vga.vram);
|
||||
mr = &d->vga.vram;
|
||||
break;
|
||||
case QXL_VRAM_RANGE_INDEX:
|
||||
case 4 /* vram 64bit */:
|
||||
virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vram_bar);
|
||||
mr = &d->vram_bar;
|
||||
break;
|
||||
default:
|
||||
/* should not happen */
|
||||
@@ -1301,6 +1307,7 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
|
||||
return 1;
|
||||
}
|
||||
|
||||
virt_start = (intptr_t)memory_region_get_ram_ptr(mr);
|
||||
memslot.slot_id = slot_id;
|
||||
memslot.slot_group_id = MEMSLOT_GROUP_GUEST; /* guest group */
|
||||
memslot.virt_start = virt_start + (guest_start - pci_start);
|
||||
@@ -1310,7 +1317,8 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
|
||||
qxl_rom_set_dirty(d);
|
||||
|
||||
qemu_spice_add_memslot(&d->ssd, &memslot, async);
|
||||
d->guest_slots[slot_id].ptr = (void*)memslot.virt_start;
|
||||
d->guest_slots[slot_id].mr = mr;
|
||||
d->guest_slots[slot_id].offset = memslot.virt_start - virt_start;
|
||||
d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start;
|
||||
d->guest_slots[slot_id].delta = delta;
|
||||
d->guest_slots[slot_id].active = 1;
|
||||
@@ -1337,39 +1345,60 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
|
||||
}
|
||||
|
||||
/* can be also called from spice server thread context */
|
||||
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
|
||||
static bool qxl_get_check_slot_offset(PCIQXLDevice *qxl, QXLPHYSICAL pqxl,
|
||||
uint32_t *s, uint64_t *o)
|
||||
{
|
||||
uint64_t phys = le64_to_cpu(pqxl);
|
||||
uint32_t slot = (phys >> (64 - 8)) & 0xff;
|
||||
uint64_t offset = phys & 0xffffffffffff;
|
||||
|
||||
switch (group_id) {
|
||||
case MEMSLOT_GROUP_HOST:
|
||||
return (void *)(intptr_t)offset;
|
||||
case MEMSLOT_GROUP_GUEST:
|
||||
if (slot >= NUM_MEMSLOTS) {
|
||||
qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot,
|
||||
NUM_MEMSLOTS);
|
||||
return NULL;
|
||||
}
|
||||
if (!qxl->guest_slots[slot].active) {
|
||||
qxl_set_guest_bug(qxl, "inactive slot %d\n", slot);
|
||||
return NULL;
|
||||
}
|
||||
if (offset < qxl->guest_slots[slot].delta) {
|
||||
qxl_set_guest_bug(qxl,
|
||||
if (slot >= NUM_MEMSLOTS) {
|
||||
qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot,
|
||||
NUM_MEMSLOTS);
|
||||
return false;
|
||||
}
|
||||
if (!qxl->guest_slots[slot].active) {
|
||||
qxl_set_guest_bug(qxl, "inactive slot %d\n", slot);
|
||||
return false;
|
||||
}
|
||||
if (offset < qxl->guest_slots[slot].delta) {
|
||||
qxl_set_guest_bug(qxl,
|
||||
"slot %d offset %"PRIu64" < delta %"PRIu64"\n",
|
||||
slot, offset, qxl->guest_slots[slot].delta);
|
||||
return NULL;
|
||||
}
|
||||
offset -= qxl->guest_slots[slot].delta;
|
||||
if (offset > qxl->guest_slots[slot].size) {
|
||||
qxl_set_guest_bug(qxl,
|
||||
return false;
|
||||
}
|
||||
offset -= qxl->guest_slots[slot].delta;
|
||||
if (offset > qxl->guest_slots[slot].size) {
|
||||
qxl_set_guest_bug(qxl,
|
||||
"slot %d offset %"PRIu64" > size %"PRIu64"\n",
|
||||
slot, offset, qxl->guest_slots[slot].size);
|
||||
return false;
|
||||
}
|
||||
|
||||
*s = slot;
|
||||
*o = offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* can be also called from spice server thread context */
|
||||
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
|
||||
{
|
||||
uint64_t offset;
|
||||
uint32_t slot;
|
||||
void *ptr;
|
||||
|
||||
switch (group_id) {
|
||||
case MEMSLOT_GROUP_HOST:
|
||||
offset = le64_to_cpu(pqxl) & 0xffffffffffff;
|
||||
return (void *)(intptr_t)offset;
|
||||
case MEMSLOT_GROUP_GUEST:
|
||||
if (!qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset)) {
|
||||
return NULL;
|
||||
}
|
||||
return qxl->guest_slots[slot].ptr + offset;
|
||||
ptr = memory_region_get_ram_ptr(qxl->guest_slots[slot].mr);
|
||||
ptr += qxl->guest_slots[slot].offset;
|
||||
ptr += offset;
|
||||
return ptr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1784,9 +1813,23 @@ static void qxl_hw_update(void *opaque)
|
||||
qxl_render_update(qxl);
|
||||
}
|
||||
|
||||
static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl,
|
||||
uint32_t height, int32_t stride)
|
||||
{
|
||||
uint64_t offset;
|
||||
uint32_t slot, size;
|
||||
bool rc;
|
||||
|
||||
rc = qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset);
|
||||
assert(rc == true);
|
||||
size = height * abs(stride);
|
||||
trace_qxl_surfaces_dirty(qxl->id, (int)offset, size);
|
||||
qxl_set_dirty(qxl->guest_slots[slot].mr,
|
||||
qxl->guest_slots[slot].offset + offset, size);
|
||||
}
|
||||
|
||||
static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
|
||||
{
|
||||
uintptr_t vram_start;
|
||||
int i;
|
||||
|
||||
if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) {
|
||||
@@ -1794,16 +1837,13 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
|
||||
}
|
||||
|
||||
/* dirty the primary surface */
|
||||
qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
|
||||
qxl->shadow_rom.surface0_area_size);
|
||||
|
||||
vram_start = (uintptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
|
||||
qxl_dirty_one_surface(qxl, qxl->guest_primary.surface.mem,
|
||||
qxl->guest_primary.surface.height,
|
||||
qxl->guest_primary.surface.stride);
|
||||
|
||||
/* dirty the off-screen surfaces */
|
||||
for (i = 0; i < qxl->ssd.num_surfaces; i++) {
|
||||
QXLSurfaceCmd *cmd;
|
||||
intptr_t surface_offset;
|
||||
int surface_size;
|
||||
|
||||
if (qxl->guest_surfaces.cmds[i] == 0) {
|
||||
continue;
|
||||
@@ -1813,15 +1853,9 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
|
||||
MEMSLOT_GROUP_GUEST);
|
||||
assert(cmd);
|
||||
assert(cmd->type == QXL_SURFACE_CMD_CREATE);
|
||||
surface_offset = (intptr_t)qxl_phys2virt(qxl,
|
||||
cmd->u.surface_create.data,
|
||||
MEMSLOT_GROUP_GUEST);
|
||||
assert(surface_offset);
|
||||
surface_offset -= vram_start;
|
||||
surface_size = cmd->u.surface_create.height *
|
||||
abs(cmd->u.surface_create.stride);
|
||||
trace_qxl_surfaces_dirty(qxl->id, i, (int)surface_offset, surface_size);
|
||||
qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
|
||||
qxl_dirty_one_surface(qxl, cmd->u.surface_create.data,
|
||||
cmd->u.surface_create.height,
|
||||
cmd->u.surface_create.stride);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1914,7 +1948,7 @@ static void qxl_init_ramsize(PCIQXLDevice *qxl)
|
||||
|
||||
/* vram (surfaces, 64bit, bar 4+5) */
|
||||
if (qxl->vram_size_mb != -1) {
|
||||
qxl->vram_size = qxl->vram_size_mb * 1024 * 1024;
|
||||
qxl->vram_size = (uint64_t)qxl->vram_size_mb * 1024 * 1024;
|
||||
}
|
||||
if (qxl->vram_size < qxl->vram32_size) {
|
||||
qxl->vram_size = qxl->vram32_size;
|
||||
@@ -2020,9 +2054,9 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp)
|
||||
dprint(qxl, 1, "ram/%s: %d MB [region 0]\n",
|
||||
qxl->id == 0 ? "pri" : "sec",
|
||||
qxl->vga.vram_size / (1024*1024));
|
||||
dprint(qxl, 1, "vram/32: %d MB [region 1]\n",
|
||||
dprint(qxl, 1, "vram/32: %" PRIx64 "d MB [region 1]\n",
|
||||
qxl->vram32_size / (1024*1024));
|
||||
dprint(qxl, 1, "vram/64: %d MB %s\n",
|
||||
dprint(qxl, 1, "vram/64: %" PRIx64 "d MB %s\n",
|
||||
qxl->vram_size / (1024*1024),
|
||||
qxl->vram32_size < qxl->vram_size ? "[region 4]" : "[unmapped]");
|
||||
|
||||
@@ -2276,7 +2310,7 @@ static VMStateDescription qxl_vmstate = {
|
||||
static Property qxl_properties[] = {
|
||||
DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
|
||||
64 * 1024 * 1024),
|
||||
DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram32_size,
|
||||
DEFINE_PROP_UINT64("vram_size", PCIQXLDevice, vram32_size,
|
||||
64 * 1024 * 1024),
|
||||
DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
|
||||
QXL_DEFAULT_REVISION),
|
||||
|
||||
@@ -53,7 +53,8 @@ typedef struct PCIQXLDevice {
|
||||
|
||||
struct guest_slots {
|
||||
QXLMemSlot slot;
|
||||
void *ptr;
|
||||
MemoryRegion *mr;
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
uint64_t delta;
|
||||
uint32_t active;
|
||||
@@ -104,9 +105,9 @@ typedef struct PCIQXLDevice {
|
||||
#endif
|
||||
|
||||
/* vram pci bar */
|
||||
uint32_t vram_size;
|
||||
uint64_t vram_size;
|
||||
MemoryRegion vram_bar;
|
||||
uint32_t vram32_size;
|
||||
uint64_t vram32_size;
|
||||
MemoryRegion vram32_bar;
|
||||
|
||||
/* io bar */
|
||||
|
||||
@@ -361,7 +361,7 @@ static const GraphicHwOps ssd0323_ops = {
|
||||
.gfx_update = ssd0323_update_display,
|
||||
};
|
||||
|
||||
static int ssd0323_init(SSISlave *d)
|
||||
static void ssd0323_realize(SSISlave *d, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(d);
|
||||
ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, d);
|
||||
@@ -375,14 +375,13 @@ static int ssd0323_init(SSISlave *d)
|
||||
|
||||
register_savevm(dev, "ssd0323_oled", -1, 1,
|
||||
ssd0323_save, ssd0323_load, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ssd0323_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
||||
|
||||
k->init = ssd0323_init;
|
||||
k->realize = ssd0323_realize;
|
||||
k->transfer = ssd0323_transfer;
|
||||
k->cs_polarity = SSI_CS_HIGH;
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ qxl_spice_reset_image_cache(int qid) "%d"
|
||||
qxl_spice_reset_memslots(int qid) "%d"
|
||||
qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "%d sid=%d [%d,%d,%d,%d]"
|
||||
qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d"
|
||||
qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d"
|
||||
qxl_surfaces_dirty(int qid, int offset, int size) "%d offset=%d size=%d"
|
||||
qxl_send_events(int qid, uint32_t events) "%d %d"
|
||||
qxl_send_events_vm_stopped(int qid, uint32_t events) "%d %d"
|
||||
qxl_set_guest_bug(int qid) "%d"
|
||||
|
||||
@@ -171,13 +171,14 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
|
||||
virgl_renderer_force_ctx_0();
|
||||
dpy_gl_scanout(g->scanout[ss.scanout_id].con, info.tex_id,
|
||||
info.flags & 1 /* FIXME: Y_0_TOP */,
|
||||
info.width, info.height,
|
||||
ss.r.x, ss.r.y, ss.r.width, ss.r.height);
|
||||
} else {
|
||||
if (ss.scanout_id != 0) {
|
||||
dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, NULL);
|
||||
}
|
||||
dpy_gl_scanout(g->scanout[ss.scanout_id].con, 0, false,
|
||||
0, 0, 0, 0);
|
||||
0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
g->scanout[ss.scanout_id].resource_id = ss.resource_id;
|
||||
}
|
||||
@@ -580,7 +581,7 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g)
|
||||
if (i != 0) {
|
||||
dpy_gfx_replace_surface(g->scanout[i].con, NULL);
|
||||
}
|
||||
dpy_gl_scanout(g->scanout[i].con, 0, false, 0, 0, 0, 0);
|
||||
dpy_gl_scanout(g->scanout[i].con, 0, false, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -934,8 +934,14 @@ static void virtio_gpu_gl_block(void *opaque, bool block)
|
||||
{
|
||||
VirtIOGPU *g = opaque;
|
||||
|
||||
g->renderer_blocked = block;
|
||||
if (!block) {
|
||||
if (block) {
|
||||
g->renderer_blocked++;
|
||||
} else {
|
||||
g->renderer_blocked--;
|
||||
}
|
||||
assert(g->renderer_blocked >= 0);
|
||||
|
||||
if (g->renderer_blocked == 0) {
|
||||
virtio_gpu_process_cmdq(g);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,10 +438,10 @@ static void xlnx_dp_aux_clear_tx_fifo(XlnxDPState *s)
|
||||
fifo8_reset(&s->tx_fifo);
|
||||
}
|
||||
|
||||
static void xlnx_dp_aux_push_tx_fifo(XlnxDPState *s, uint8_t val, size_t len)
|
||||
static void xlnx_dp_aux_push_tx_fifo(XlnxDPState *s, uint8_t *buf, size_t len)
|
||||
{
|
||||
DPRINTF("Push %u data in tx_fifo\n", (unsigned)len);
|
||||
fifo8_push_all(&s->tx_fifo, &val, len);
|
||||
fifo8_push_all(&s->tx_fifo, buf, len);
|
||||
}
|
||||
|
||||
static uint8_t xlnx_dp_aux_pop_tx_fifo(XlnxDPState *s)
|
||||
@@ -806,9 +806,11 @@ static void xlnx_dp_write(void *opaque, hwaddr offset, uint64_t value,
|
||||
* TODO: Power down things?
|
||||
*/
|
||||
break;
|
||||
case DP_AUX_WRITE_FIFO:
|
||||
xlnx_dp_aux_push_tx_fifo(s, value, 1);
|
||||
case DP_AUX_WRITE_FIFO: {
|
||||
uint8_t c = value;
|
||||
xlnx_dp_aux_push_tx_fifo(s, &c, 1);
|
||||
break;
|
||||
}
|
||||
case DP_AUX_CLOCK_DIVIDER:
|
||||
break;
|
||||
case DP_AUX_REPLY_COUNT:
|
||||
|
||||
@@ -5,6 +5,7 @@ common-obj-$(CONFIG_PL330) += pl330.o
|
||||
common-obj-$(CONFIG_I82374) += i82374.o
|
||||
common-obj-$(CONFIG_I8257) += i8257.o
|
||||
common-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o
|
||||
common-obj-$(CONFIG_ZYNQ_DEVCFG) += xlnx-zynq-devcfg.o
|
||||
common-obj-$(CONFIG_ETRAXFS) += etraxfs_dma.o
|
||||
common-obj-$(CONFIG_STP2000) += sparc32_dma.o
|
||||
common-obj-$(CONFIG_SUN4M) += sun4m_iommu.o
|
||||
|
||||
400
hw/dma/xlnx-zynq-devcfg.c
Normal file
400
hw/dma/xlnx-zynq-devcfg.c
Normal file
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* QEMU model of the Xilinx Zynq Devcfg Interface
|
||||
*
|
||||
* (C) 2011 PetaLogix Pty Ltd
|
||||
* (C) 2014 Xilinx Inc.
|
||||
* Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/dma/xlnx-zynq-devcfg.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/dma.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
#define FREQ_HZ 900000000
|
||||
|
||||
#define BTT_MAX 0x400
|
||||
|
||||
#ifndef XLNX_ZYNQ_DEVCFG_ERR_DEBUG
|
||||
#define XLNX_ZYNQ_DEVCFG_ERR_DEBUG 0
|
||||
#endif
|
||||
|
||||
#define DB_PRINT(fmt, args...) do { \
|
||||
if (XLNX_ZYNQ_DEVCFG_ERR_DEBUG) { \
|
||||
qemu_log("%s: " fmt, __func__, ## args); \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
REG32(CTRL, 0x00)
|
||||
FIELD(CTRL, FORCE_RST, 31, 1) /* Not supported, wr ignored */
|
||||
FIELD(CTRL, PCAP_PR, 27, 1) /* Forced to 0 on bad unlock */
|
||||
FIELD(CTRL, PCAP_MODE, 26, 1)
|
||||
FIELD(CTRL, MULTIBOOT_EN, 24, 1)
|
||||
FIELD(CTRL, USER_MODE, 15, 1)
|
||||
FIELD(CTRL, PCFG_AES_FUSE, 12, 1)
|
||||
FIELD(CTRL, PCFG_AES_EN, 9, 3)
|
||||
FIELD(CTRL, SEU_EN, 8, 1)
|
||||
FIELD(CTRL, SEC_EN, 7, 1)
|
||||
FIELD(CTRL, SPNIDEN, 6, 1)
|
||||
FIELD(CTRL, SPIDEN, 5, 1)
|
||||
FIELD(CTRL, NIDEN, 4, 1)
|
||||
FIELD(CTRL, DBGEN, 3, 1)
|
||||
FIELD(CTRL, DAP_EN, 0, 3)
|
||||
|
||||
REG32(LOCK, 0x04)
|
||||
#define AES_FUSE_LOCK 4
|
||||
#define AES_EN_LOCK 3
|
||||
#define SEU_LOCK 2
|
||||
#define SEC_LOCK 1
|
||||
#define DBG_LOCK 0
|
||||
|
||||
/* mapping bits in R_LOCK to what they lock in R_CTRL */
|
||||
static const uint32_t lock_ctrl_map[] = {
|
||||
[AES_FUSE_LOCK] = R_CTRL_PCFG_AES_FUSE_MASK,
|
||||
[AES_EN_LOCK] = R_CTRL_PCFG_AES_EN_MASK,
|
||||
[SEU_LOCK] = R_CTRL_SEU_EN_MASK,
|
||||
[SEC_LOCK] = R_CTRL_SEC_EN_MASK,
|
||||
[DBG_LOCK] = R_CTRL_SPNIDEN_MASK | R_CTRL_SPIDEN_MASK |
|
||||
R_CTRL_NIDEN_MASK | R_CTRL_DBGEN_MASK |
|
||||
R_CTRL_DAP_EN_MASK,
|
||||
};
|
||||
|
||||
REG32(CFG, 0x08)
|
||||
FIELD(CFG, RFIFO_TH, 10, 2)
|
||||
FIELD(CFG, WFIFO_TH, 8, 2)
|
||||
FIELD(CFG, RCLK_EDGE, 7, 1)
|
||||
FIELD(CFG, WCLK_EDGE, 6, 1)
|
||||
FIELD(CFG, DISABLE_SRC_INC, 5, 1)
|
||||
FIELD(CFG, DISABLE_DST_INC, 4, 1)
|
||||
#define R_CFG_RESET 0x50B
|
||||
|
||||
REG32(INT_STS, 0x0C)
|
||||
FIELD(INT_STS, PSS_GTS_USR_B, 31, 1)
|
||||
FIELD(INT_STS, PSS_FST_CFG_B, 30, 1)
|
||||
FIELD(INT_STS, PSS_CFG_RESET_B, 27, 1)
|
||||
FIELD(INT_STS, RX_FIFO_OV, 18, 1)
|
||||
FIELD(INT_STS, WR_FIFO_LVL, 17, 1)
|
||||
FIELD(INT_STS, RD_FIFO_LVL, 16, 1)
|
||||
FIELD(INT_STS, DMA_CMD_ERR, 15, 1)
|
||||
FIELD(INT_STS, DMA_Q_OV, 14, 1)
|
||||
FIELD(INT_STS, DMA_DONE, 13, 1)
|
||||
FIELD(INT_STS, DMA_P_DONE, 12, 1)
|
||||
FIELD(INT_STS, P2D_LEN_ERR, 11, 1)
|
||||
FIELD(INT_STS, PCFG_DONE, 2, 1)
|
||||
#define R_INT_STS_RSVD ((0x7 << 24) | (0x1 << 19) | (0xF < 7))
|
||||
|
||||
REG32(INT_MASK, 0x10)
|
||||
|
||||
REG32(STATUS, 0x14)
|
||||
FIELD(STATUS, DMA_CMD_Q_F, 31, 1)
|
||||
FIELD(STATUS, DMA_CMD_Q_E, 30, 1)
|
||||
FIELD(STATUS, DMA_DONE_CNT, 28, 2)
|
||||
FIELD(STATUS, RX_FIFO_LVL, 20, 5)
|
||||
FIELD(STATUS, TX_FIFO_LVL, 12, 7)
|
||||
FIELD(STATUS, PSS_GTS_USR_B, 11, 1)
|
||||
FIELD(STATUS, PSS_FST_CFG_B, 10, 1)
|
||||
FIELD(STATUS, PSS_CFG_RESET_B, 5, 1)
|
||||
|
||||
REG32(DMA_SRC_ADDR, 0x18)
|
||||
REG32(DMA_DST_ADDR, 0x1C)
|
||||
REG32(DMA_SRC_LEN, 0x20)
|
||||
REG32(DMA_DST_LEN, 0x24)
|
||||
REG32(ROM_SHADOW, 0x28)
|
||||
REG32(SW_ID, 0x30)
|
||||
REG32(UNLOCK, 0x34)
|
||||
|
||||
#define R_UNLOCK_MAGIC 0x757BDF0D
|
||||
|
||||
REG32(MCTRL, 0x80)
|
||||
FIELD(MCTRL, PS_VERSION, 28, 4)
|
||||
FIELD(MCTRL, PCFG_POR_B, 8, 1)
|
||||
FIELD(MCTRL, INT_PCAP_LPBK, 4, 1)
|
||||
FIELD(MCTRL, QEMU, 3, 1)
|
||||
|
||||
static void xlnx_zynq_devcfg_update_ixr(XlnxZynqDevcfg *s)
|
||||
{
|
||||
qemu_set_irq(s->irq, ~s->regs[R_INT_MASK] & s->regs[R_INT_STS]);
|
||||
}
|
||||
|
||||
static void xlnx_zynq_devcfg_reset(DeviceState *dev)
|
||||
{
|
||||
XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < XLNX_ZYNQ_DEVCFG_R_MAX; ++i) {
|
||||
register_reset(&s->regs_info[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void xlnx_zynq_devcfg_dma_go(XlnxZynqDevcfg *s)
|
||||
{
|
||||
do {
|
||||
uint8_t buf[BTT_MAX];
|
||||
XlnxZynqDevcfgDMACmd *dmah = s->dma_cmd_fifo;
|
||||
uint32_t btt = BTT_MAX;
|
||||
bool loopback = s->regs[R_MCTRL] & R_MCTRL_INT_PCAP_LPBK_MASK;
|
||||
|
||||
btt = MIN(btt, dmah->src_len);
|
||||
if (loopback) {
|
||||
btt = MIN(btt, dmah->dest_len);
|
||||
}
|
||||
DB_PRINT("reading %x bytes from %x\n", btt, dmah->src_addr);
|
||||
dma_memory_read(&address_space_memory, dmah->src_addr, buf, btt);
|
||||
dmah->src_len -= btt;
|
||||
dmah->src_addr += btt;
|
||||
if (loopback && (dmah->src_len || dmah->dest_len)) {
|
||||
DB_PRINT("writing %x bytes from %x\n", btt, dmah->dest_addr);
|
||||
dma_memory_write(&address_space_memory, dmah->dest_addr, buf, btt);
|
||||
dmah->dest_len -= btt;
|
||||
dmah->dest_addr += btt;
|
||||
}
|
||||
if (!dmah->src_len && !dmah->dest_len) {
|
||||
DB_PRINT("dma operation finished\n");
|
||||
s->regs[R_INT_STS] |= R_INT_STS_DMA_DONE_MASK |
|
||||
R_INT_STS_DMA_P_DONE_MASK;
|
||||
s->dma_cmd_fifo_num--;
|
||||
memmove(s->dma_cmd_fifo, &s->dma_cmd_fifo[1],
|
||||
sizeof(s->dma_cmd_fifo) - sizeof(s->dma_cmd_fifo[0]));
|
||||
}
|
||||
xlnx_zynq_devcfg_update_ixr(s);
|
||||
} while (s->dma_cmd_fifo_num);
|
||||
}
|
||||
|
||||
static void r_ixr_post_write(RegisterInfo *reg, uint64_t val)
|
||||
{
|
||||
XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque);
|
||||
|
||||
xlnx_zynq_devcfg_update_ixr(s);
|
||||
}
|
||||
|
||||
static uint64_t r_ctrl_pre_write(RegisterInfo *reg, uint64_t val)
|
||||
{
|
||||
XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lock_ctrl_map); ++i) {
|
||||
if (s->regs[R_LOCK] & 1 << i) {
|
||||
val &= ~lock_ctrl_map[i];
|
||||
val |= lock_ctrl_map[i] & s->regs[R_CTRL];
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void r_ctrl_post_write(RegisterInfo *reg, uint64_t val)
|
||||
{
|
||||
const char *device_prefix = object_get_typename(OBJECT(reg->opaque));
|
||||
uint32_t aes_en = FIELD_EX32(val, CTRL, PCFG_AES_EN);
|
||||
|
||||
if (aes_en != 0 && aes_en != 7) {
|
||||
qemu_log_mask(LOG_UNIMP, "%s: warning, aes-en bits inconsistent,"
|
||||
"unimplemented security reset should happen!\n",
|
||||
device_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
static void r_unlock_post_write(RegisterInfo *reg, uint64_t val)
|
||||
{
|
||||
XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque);
|
||||
const char *device_prefix = object_get_typename(OBJECT(s));
|
||||
|
||||
if (val == R_UNLOCK_MAGIC) {
|
||||
DB_PRINT("successful unlock\n");
|
||||
s->regs[R_CTRL] |= R_CTRL_PCAP_PR_MASK;
|
||||
s->regs[R_CTRL] |= R_CTRL_PCFG_AES_EN_MASK;
|
||||
memory_region_set_enabled(&s->iomem, true);
|
||||
} else { /* bad unlock attempt */
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: failed unlock\n", device_prefix);
|
||||
s->regs[R_CTRL] &= ~R_CTRL_PCAP_PR_MASK;
|
||||
s->regs[R_CTRL] &= ~R_CTRL_PCFG_AES_EN_MASK;
|
||||
/* core becomes inaccessible */
|
||||
memory_region_set_enabled(&s->iomem, false);
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t r_lock_pre_write(RegisterInfo *reg, uint64_t val)
|
||||
{
|
||||
XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque);
|
||||
|
||||
/* once bits are locked they stay locked */
|
||||
return s->regs[R_LOCK] | val;
|
||||
}
|
||||
|
||||
static void r_dma_dst_len_post_write(RegisterInfo *reg, uint64_t val)
|
||||
{
|
||||
XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque);
|
||||
|
||||
s->dma_cmd_fifo[s->dma_cmd_fifo_num] = (XlnxZynqDevcfgDMACmd) {
|
||||
.src_addr = s->regs[R_DMA_SRC_ADDR] & ~0x3UL,
|
||||
.dest_addr = s->regs[R_DMA_DST_ADDR] & ~0x3UL,
|
||||
.src_len = s->regs[R_DMA_SRC_LEN] << 2,
|
||||
.dest_len = s->regs[R_DMA_DST_LEN] << 2,
|
||||
};
|
||||
s->dma_cmd_fifo_num++;
|
||||
DB_PRINT("dma transfer started; %d total transfers pending\n",
|
||||
s->dma_cmd_fifo_num);
|
||||
xlnx_zynq_devcfg_dma_go(s);
|
||||
}
|
||||
|
||||
static const RegisterAccessInfo xlnx_zynq_devcfg_regs_info[] = {
|
||||
{ .name = "CTRL", .addr = A_CTRL,
|
||||
.reset = R_CTRL_PCAP_PR_MASK | R_CTRL_PCAP_MODE_MASK | 0x3 << 13,
|
||||
.rsvd = 0x1 << 28 | 0x3ff << 13 | 0x3 << 13,
|
||||
.pre_write = r_ctrl_pre_write,
|
||||
.post_write = r_ctrl_post_write,
|
||||
},
|
||||
{ .name = "LOCK", .addr = A_LOCK,
|
||||
.rsvd = MAKE_64BIT_MASK(5, 64 - 5),
|
||||
.pre_write = r_lock_pre_write,
|
||||
},
|
||||
{ .name = "CFG", .addr = A_CFG,
|
||||
.reset = R_CFG_RESET,
|
||||
.rsvd = 0xfffff00f,
|
||||
},
|
||||
{ .name = "INT_STS", .addr = A_INT_STS,
|
||||
.w1c = ~R_INT_STS_RSVD,
|
||||
.reset = R_INT_STS_PSS_GTS_USR_B_MASK |
|
||||
R_INT_STS_PSS_CFG_RESET_B_MASK |
|
||||
R_INT_STS_WR_FIFO_LVL_MASK,
|
||||
.rsvd = R_INT_STS_RSVD,
|
||||
.post_write = r_ixr_post_write,
|
||||
},
|
||||
{ .name = "INT_MASK", .addr = A_INT_MASK,
|
||||
.reset = ~0,
|
||||
.rsvd = R_INT_STS_RSVD,
|
||||
.post_write = r_ixr_post_write,
|
||||
},
|
||||
{ .name = "STATUS", .addr = A_STATUS,
|
||||
.reset = R_STATUS_DMA_CMD_Q_E_MASK |
|
||||
R_STATUS_PSS_GTS_USR_B_MASK |
|
||||
R_STATUS_PSS_CFG_RESET_B_MASK,
|
||||
.ro = ~0,
|
||||
},
|
||||
{ .name = "DMA_SRC_ADDR", .addr = A_DMA_SRC_ADDR, },
|
||||
{ .name = "DMA_DST_ADDR", .addr = A_DMA_DST_ADDR, },
|
||||
{ .name = "DMA_SRC_LEN", .addr = A_DMA_SRC_LEN,
|
||||
.ro = MAKE_64BIT_MASK(27, 64 - 27) },
|
||||
{ .name = "DMA_DST_LEN", .addr = A_DMA_DST_LEN,
|
||||
.ro = MAKE_64BIT_MASK(27, 64 - 27),
|
||||
.post_write = r_dma_dst_len_post_write,
|
||||
},
|
||||
{ .name = "ROM_SHADOW", .addr = A_ROM_SHADOW,
|
||||
.rsvd = ~0ull,
|
||||
},
|
||||
{ .name = "SW_ID", .addr = A_SW_ID, },
|
||||
{ .name = "UNLOCK", .addr = A_UNLOCK,
|
||||
.post_write = r_unlock_post_write,
|
||||
},
|
||||
{ .name = "MCTRL", .addr = R_MCTRL * 4,
|
||||
/* Silicon 3.0 for version field, the mysterious reserved bit 23
|
||||
* and QEMU platform identifier.
|
||||
*/
|
||||
.reset = 0x2 << R_MCTRL_PS_VERSION_SHIFT | 1 << 23 | R_MCTRL_QEMU_MASK,
|
||||
.ro = ~R_MCTRL_INT_PCAP_LPBK_MASK,
|
||||
.rsvd = 0x00f00303,
|
||||
},
|
||||
};
|
||||
|
||||
static const MemoryRegionOps xlnx_zynq_devcfg_reg_ops = {
|
||||
.read = register_read_memory,
|
||||
.write = register_write_memory,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_xlnx_zynq_devcfg_dma_cmd = {
|
||||
.name = "xlnx_zynq_devcfg_dma_cmd",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(src_addr, XlnxZynqDevcfgDMACmd),
|
||||
VMSTATE_UINT32(dest_addr, XlnxZynqDevcfgDMACmd),
|
||||
VMSTATE_UINT32(src_len, XlnxZynqDevcfgDMACmd),
|
||||
VMSTATE_UINT32(dest_len, XlnxZynqDevcfgDMACmd),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_xlnx_zynq_devcfg = {
|
||||
.name = "xlnx_zynq_devcfg",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_STRUCT_ARRAY(dma_cmd_fifo, XlnxZynqDevcfg,
|
||||
XLNX_ZYNQ_DEVCFG_DMA_CMD_FIFO_LEN, 0,
|
||||
vmstate_xlnx_zynq_devcfg_dma_cmd,
|
||||
XlnxZynqDevcfgDMACmd),
|
||||
VMSTATE_UINT8(dma_cmd_fifo_num, XlnxZynqDevcfg),
|
||||
VMSTATE_UINT32_ARRAY(regs, XlnxZynqDevcfg, XLNX_ZYNQ_DEVCFG_R_MAX),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void xlnx_zynq_devcfg_init(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(obj);
|
||||
RegisterInfoArray *reg_array;
|
||||
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
|
||||
memory_region_init(&s->iomem, obj, "devcfg", XLNX_ZYNQ_DEVCFG_R_MAX * 4);
|
||||
reg_array =
|
||||
register_init_block32(DEVICE(obj), xlnx_zynq_devcfg_regs_info,
|
||||
ARRAY_SIZE(xlnx_zynq_devcfg_regs_info),
|
||||
s->regs_info, s->regs,
|
||||
&xlnx_zynq_devcfg_reg_ops,
|
||||
XLNX_ZYNQ_DEVCFG_ERR_DEBUG,
|
||||
XLNX_ZYNQ_DEVCFG_R_MAX);
|
||||
memory_region_add_subregion(&s->iomem,
|
||||
A_CTRL,
|
||||
®_array->mem);
|
||||
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static void xlnx_zynq_devcfg_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->reset = xlnx_zynq_devcfg_reset;
|
||||
dc->vmsd = &vmstate_xlnx_zynq_devcfg;
|
||||
}
|
||||
|
||||
static const TypeInfo xlnx_zynq_devcfg_info = {
|
||||
.name = TYPE_XLNX_ZYNQ_DEVCFG,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(XlnxZynqDevcfg),
|
||||
.instance_init = xlnx_zynq_devcfg_init,
|
||||
.class_init = xlnx_zynq_devcfg_class_init,
|
||||
};
|
||||
|
||||
static void xlnx_zynq_devcfg_register_types(void)
|
||||
{
|
||||
type_register_static(&xlnx_zynq_devcfg_info);
|
||||
}
|
||||
|
||||
type_init(xlnx_zynq_devcfg_register_types)
|
||||
@@ -229,26 +229,27 @@ static Object *acpi_get_i386_pci_host(void)
|
||||
return OBJECT(host);
|
||||
}
|
||||
|
||||
static void acpi_get_pci_info(PcPciInfo *info)
|
||||
static void acpi_get_pci_holes(Range *hole, Range *hole64)
|
||||
{
|
||||
Object *pci_host;
|
||||
|
||||
|
||||
pci_host = acpi_get_i386_pci_host();
|
||||
g_assert(pci_host);
|
||||
|
||||
info->w32.begin = object_property_get_int(pci_host,
|
||||
range_set_bounds1(hole,
|
||||
object_property_get_int(pci_host,
|
||||
PCI_HOST_PROP_PCI_HOLE_START,
|
||||
NULL);
|
||||
info->w32.end = object_property_get_int(pci_host,
|
||||
PCI_HOST_PROP_PCI_HOLE_END,
|
||||
NULL);
|
||||
info->w64.begin = object_property_get_int(pci_host,
|
||||
NULL),
|
||||
object_property_get_int(pci_host,
|
||||
PCI_HOST_PROP_PCI_HOLE_END,
|
||||
NULL));
|
||||
range_set_bounds1(hole64,
|
||||
object_property_get_int(pci_host,
|
||||
PCI_HOST_PROP_PCI_HOLE64_START,
|
||||
NULL);
|
||||
info->w64.end = object_property_get_int(pci_host,
|
||||
PCI_HOST_PROP_PCI_HOLE64_END,
|
||||
NULL);
|
||||
NULL),
|
||||
object_property_get_int(pci_host,
|
||||
PCI_HOST_PROP_PCI_HOLE64_END,
|
||||
NULL));
|
||||
}
|
||||
|
||||
#define ACPI_PORT_SMI_CMD 0x00b2 /* TODO: this is APM_CNT_IOPORT */
|
||||
@@ -1890,7 +1891,7 @@ static Aml *build_q35_osc_method(void)
|
||||
static void
|
||||
build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
AcpiPmInfo *pm, AcpiMiscInfo *misc,
|
||||
PcPciInfo *pci, MachineState *machine)
|
||||
Range *pci_hole, Range *pci_hole64, MachineState *machine)
|
||||
{
|
||||
CrsRangeEntry *entry;
|
||||
Aml *dsdt, *sb_scope, *scope, *dev, *method, *field, *pkg, *crs;
|
||||
@@ -2047,7 +2048,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
AML_CACHEABLE, AML_READ_WRITE,
|
||||
0, 0x000A0000, 0x000BFFFF, 0, 0x00020000));
|
||||
|
||||
crs_replace_with_free_ranges(mem_ranges, pci->w32.begin, pci->w32.end - 1);
|
||||
crs_replace_with_free_ranges(mem_ranges,
|
||||
range_lob(pci_hole),
|
||||
range_upb(pci_hole));
|
||||
for (i = 0; i < mem_ranges->len; i++) {
|
||||
entry = g_ptr_array_index(mem_ranges, i);
|
||||
aml_append(crs,
|
||||
@@ -2057,12 +2060,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
0, entry->limit - entry->base + 1));
|
||||
}
|
||||
|
||||
if (pci->w64.begin) {
|
||||
if (!range_is_empty(pci_hole64)) {
|
||||
aml_append(crs,
|
||||
aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
|
||||
AML_CACHEABLE, AML_READ_WRITE,
|
||||
0, pci->w64.begin, pci->w64.end - 1, 0,
|
||||
pci->w64.end - pci->w64.begin));
|
||||
0, range_lob(pci_hole64), range_upb(pci_hole64), 0,
|
||||
range_upb(pci_hole64) + 1 - range_lob(pci_hole64)));
|
||||
}
|
||||
|
||||
if (misc->tpm_version != TPM_VERSION_UNSPEC) {
|
||||
@@ -2554,7 +2557,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
AcpiPmInfo pm;
|
||||
AcpiMiscInfo misc;
|
||||
AcpiMcfgInfo mcfg;
|
||||
PcPciInfo pci;
|
||||
Range pci_hole, pci_hole64;
|
||||
uint8_t *u;
|
||||
size_t aml_len = 0;
|
||||
GArray *tables_blob = tables->table_data;
|
||||
@@ -2562,7 +2565,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
|
||||
acpi_get_pm_info(&pm);
|
||||
acpi_get_misc_info(&misc);
|
||||
acpi_get_pci_info(&pci);
|
||||
acpi_get_pci_holes(&pci_hole, &pci_hole64);
|
||||
acpi_get_slic_oem(&slic_oem);
|
||||
|
||||
table_offsets = g_array_new(false, true /* clear */,
|
||||
@@ -2584,7 +2587,8 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
|
||||
/* DSDT is pointed to by FADT */
|
||||
dsdt = tables_blob->len;
|
||||
build_dsdt(tables_blob, tables->linker, &pm, &misc, &pci, machine);
|
||||
build_dsdt(tables_blob, tables->linker, &pm, &misc,
|
||||
&pci_hole, &pci_hole64, machine);
|
||||
|
||||
/* Count the size of the DSDT and SSDT, we will need it for legacy
|
||||
* sizing of ACPI tables.
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "intel_iommu_internal.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/pci_bus.h"
|
||||
#include "hw/i386/pc.h"
|
||||
|
||||
/*#define DEBUG_INTEL_IOMMU*/
|
||||
#ifdef DEBUG_INTEL_IOMMU
|
||||
@@ -2026,8 +2027,20 @@ static void vtd_reset(DeviceState *dev)
|
||||
vtd_init(s);
|
||||
}
|
||||
|
||||
static AddressSpace *vtd_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
|
||||
{
|
||||
IntelIOMMUState *s = opaque;
|
||||
VTDAddressSpace *vtd_as;
|
||||
|
||||
assert(0 <= devfn && devfn <= VTD_PCI_DEVFN_MAX);
|
||||
|
||||
vtd_as = vtd_find_add_as(s, bus, devfn);
|
||||
return &vtd_as->as;
|
||||
}
|
||||
|
||||
static void vtd_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PCIBus *bus = PC_MACHINE(qdev_get_machine())->bus;
|
||||
IntelIOMMUState *s = INTEL_IOMMU_DEVICE(dev);
|
||||
|
||||
VTD_DPRINTF(GENERAL, "");
|
||||
@@ -2041,6 +2054,8 @@ static void vtd_realize(DeviceState *dev, Error **errp)
|
||||
s->vtd_as_by_busptr = g_hash_table_new_full(vtd_uint64_hash, vtd_uint64_equal,
|
||||
g_free, g_free);
|
||||
vtd_init(s);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(s), 0, Q35_HOST_BRIDGE_IOMMU_ADDR);
|
||||
pci_setup_iommu(bus, vtd_host_dma_iommu, dev);
|
||||
}
|
||||
|
||||
static void vtd_class_init(ObjectClass *klass, void *data)
|
||||
@@ -2051,6 +2066,7 @@ static void vtd_class_init(ObjectClass *klass, void *data)
|
||||
dc->realize = vtd_realize;
|
||||
dc->vmsd = &vtd_vmstate;
|
||||
dc->props = vtd_properties;
|
||||
dc->hotpluggable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo vtd_info = {
|
||||
|
||||
68
hw/i386/pc.c
68
hw/i386/pc.c
@@ -1039,21 +1039,17 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
|
||||
}
|
||||
}
|
||||
|
||||
static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id,
|
||||
static X86CPU *pc_new_cpu(const char *typename, int64_t apic_id,
|
||||
Error **errp)
|
||||
{
|
||||
X86CPU *cpu = NULL;
|
||||
Error *local_err = NULL;
|
||||
|
||||
cpu = cpu_x86_create(cpu_model, &local_err);
|
||||
if (local_err != NULL) {
|
||||
goto out;
|
||||
}
|
||||
cpu = X86_CPU(object_new(typename));
|
||||
|
||||
object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err);
|
||||
object_property_set_bool(OBJECT(cpu), true, "realized", &local_err);
|
||||
|
||||
out:
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
object_unref(OBJECT(cpu));
|
||||
@@ -1065,7 +1061,8 @@ out:
|
||||
void pc_hot_add_cpu(const int64_t id, Error **errp)
|
||||
{
|
||||
X86CPU *cpu;
|
||||
MachineState *machine = MACHINE(qdev_get_machine());
|
||||
ObjectClass *oc;
|
||||
PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
|
||||
int64_t apic_id = x86_cpu_apic_id_from_index(id);
|
||||
Error *local_err = NULL;
|
||||
|
||||
@@ -1093,7 +1090,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
cpu = pc_new_cpu(machine->cpu_model, apic_id, &local_err);
|
||||
assert(pcms->possible_cpus->cpus[0].cpu); /* BSP is always present */
|
||||
oc = OBJECT_CLASS(CPU_GET_CLASS(pcms->possible_cpus->cpus[0].cpu));
|
||||
cpu = pc_new_cpu(object_class_get_name(oc), apic_id, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
@@ -1104,6 +1103,10 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
|
||||
void pc_cpus_init(PCMachineState *pcms)
|
||||
{
|
||||
int i;
|
||||
CPUClass *cc;
|
||||
ObjectClass *oc;
|
||||
const char *typename;
|
||||
gchar **model_pieces;
|
||||
X86CPU *cpu = NULL;
|
||||
MachineState *machine = MACHINE(pcms);
|
||||
|
||||
@@ -1116,6 +1119,22 @@ void pc_cpus_init(PCMachineState *pcms)
|
||||
#endif
|
||||
}
|
||||
|
||||
model_pieces = g_strsplit(machine->cpu_model, ",", 2);
|
||||
if (!model_pieces[0]) {
|
||||
error_report("Invalid/empty CPU model name");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
oc = cpu_class_by_name(TYPE_X86_CPU, model_pieces[0]);
|
||||
if (oc == NULL) {
|
||||
error_report("Unable to find CPU definition: %s", model_pieces[0]);
|
||||
exit(1);
|
||||
}
|
||||
typename = object_class_get_name(oc);
|
||||
cc = CPU_CLASS(oc);
|
||||
cc->parse_features(typename, model_pieces[1], &error_fatal);
|
||||
g_strfreev(model_pieces);
|
||||
|
||||
/* Calculates the limit to CPU APIC ID values
|
||||
*
|
||||
* Limit for the APIC ID value, so that all
|
||||
@@ -1136,7 +1155,7 @@ void pc_cpus_init(PCMachineState *pcms)
|
||||
pcms->possible_cpus->cpus[i].arch_id = x86_cpu_apic_id_from_index(i);
|
||||
pcms->possible_cpus->len++;
|
||||
if (i < smp_cpus) {
|
||||
cpu = pc_new_cpu(machine->cpu_model, x86_cpu_apic_id_from_index(i),
|
||||
cpu = pc_new_cpu(typename, x86_cpu_apic_id_from_index(i),
|
||||
&error_fatal);
|
||||
pcms->possible_cpus->cpus[i].cpu = CPU(cpu);
|
||||
object_unref(OBJECT(cpu));
|
||||
@@ -1147,6 +1166,34 @@ void pc_cpus_init(PCMachineState *pcms)
|
||||
smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]);
|
||||
}
|
||||
|
||||
static void pc_build_feature_control_file(PCMachineState *pcms)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(pcms->possible_cpus->cpus[0].cpu);
|
||||
CPUX86State *env = &cpu->env;
|
||||
uint32_t unused, ecx, edx;
|
||||
uint64_t feature_control_bits = 0;
|
||||
uint64_t *val;
|
||||
|
||||
cpu_x86_cpuid(env, 1, 0, &unused, &unused, &ecx, &edx);
|
||||
if (ecx & CPUID_EXT_VMX) {
|
||||
feature_control_bits |= FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
|
||||
}
|
||||
|
||||
if ((edx & (CPUID_EXT2_MCE | CPUID_EXT2_MCA)) ==
|
||||
(CPUID_EXT2_MCE | CPUID_EXT2_MCA) &&
|
||||
(env->mcg_cap & MCG_LMCE_P)) {
|
||||
feature_control_bits |= FEATURE_CONTROL_LMCE;
|
||||
}
|
||||
|
||||
if (!feature_control_bits) {
|
||||
return;
|
||||
}
|
||||
|
||||
val = g_malloc(sizeof(*val));
|
||||
*val = cpu_to_le64(feature_control_bits | FEATURE_CONTROL_LOCKED);
|
||||
fw_cfg_add_file(pcms->fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
|
||||
}
|
||||
|
||||
static
|
||||
void pc_machine_done(Notifier *notifier, void *data)
|
||||
{
|
||||
@@ -1174,6 +1221,7 @@ void pc_machine_done(Notifier *notifier, void *data)
|
||||
acpi_setup();
|
||||
if (pcms->fw_cfg) {
|
||||
pc_build_smbios(pcms->fw_cfg);
|
||||
pc_build_feature_control_file(pcms);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1919,7 +1967,7 @@ static void pc_machine_initfn(Object *obj)
|
||||
pc_machine_get_hotplug_memory_region_size,
|
||||
NULL, NULL, NULL, &error_abort);
|
||||
|
||||
pcms->max_ram_below_4g = 0xe0000000; /* 3.5G */
|
||||
pcms->max_ram_below_4g = 0; /* use default */
|
||||
object_property_add(obj, PC_MACHINE_MAX_RAM_BELOW_4G, "size",
|
||||
pc_machine_get_max_ram_below_4g,
|
||||
pc_machine_set_max_ram_below_4g,
|
||||
|
||||
@@ -108,37 +108,43 @@ static void pc_init1(MachineState *machine,
|
||||
* so legacy non-PAE guests can get as much memory as possible in
|
||||
* the 32bit address space below 4G.
|
||||
*
|
||||
* - Note that Xen has its own ram setp code in xen_ram_init(),
|
||||
* called via xen_hvm_init().
|
||||
*
|
||||
* Examples:
|
||||
* qemu -M pc-1.7 -m 4G (old default) -> 3584M low, 512M high
|
||||
* qemu -M pc -m 4G (new default) -> 3072M low, 1024M high
|
||||
* qemu -M pc,max-ram-below-4g=2G -m 4G -> 2048M low, 2048M high
|
||||
* qemu -M pc,max-ram-below-4g=4G -m 3968M -> 3968M low (=4G-128M)
|
||||
*/
|
||||
lowmem = pcms->max_ram_below_4g;
|
||||
if (machine->ram_size >= pcms->max_ram_below_4g) {
|
||||
if (pcmc->gigabyte_align) {
|
||||
if (lowmem > 0xc0000000) {
|
||||
lowmem = 0xc0000000;
|
||||
}
|
||||
if (lowmem & ((1ULL << 30) - 1)) {
|
||||
error_report("Warning: Large machine and max_ram_below_4g "
|
||||
"(%" PRIu64 ") not a multiple of 1G; "
|
||||
"possible bad performance.",
|
||||
pcms->max_ram_below_4g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (machine->ram_size >= lowmem) {
|
||||
pcms->above_4g_mem_size = machine->ram_size - lowmem;
|
||||
pcms->below_4g_mem_size = lowmem;
|
||||
} else {
|
||||
pcms->above_4g_mem_size = 0;
|
||||
pcms->below_4g_mem_size = machine->ram_size;
|
||||
}
|
||||
|
||||
if (xen_enabled()) {
|
||||
xen_hvm_init(pcms, &ram_memory);
|
||||
} else {
|
||||
if (!pcms->max_ram_below_4g) {
|
||||
pcms->max_ram_below_4g = 0xe0000000; /* default: 3.5G */
|
||||
}
|
||||
lowmem = pcms->max_ram_below_4g;
|
||||
if (machine->ram_size >= pcms->max_ram_below_4g) {
|
||||
if (pcmc->gigabyte_align) {
|
||||
if (lowmem > 0xc0000000) {
|
||||
lowmem = 0xc0000000;
|
||||
}
|
||||
if (lowmem & ((1ULL << 30) - 1)) {
|
||||
error_report("Warning: Large machine and max_ram_below_4g "
|
||||
"(%" PRIu64 ") not a multiple of 1G; "
|
||||
"possible bad performance.",
|
||||
pcms->max_ram_below_4g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (machine->ram_size >= lowmem) {
|
||||
pcms->above_4g_mem_size = machine->ram_size - lowmem;
|
||||
pcms->below_4g_mem_size = lowmem;
|
||||
} else {
|
||||
pcms->above_4g_mem_size = 0;
|
||||
pcms->below_4g_mem_size = machine->ram_size;
|
||||
}
|
||||
}
|
||||
|
||||
pc_cpus_init(pcms);
|
||||
|
||||
@@ -94,6 +94,9 @@ static void pc_q35_init(MachineState *machine)
|
||||
/* Handle the machine opt max-ram-below-4g. It is basically doing
|
||||
* min(qemu limit, user limit).
|
||||
*/
|
||||
if (!pcms->max_ram_below_4g) {
|
||||
pcms->max_ram_below_4g = 1ULL << 32; /* default: 4G */;
|
||||
}
|
||||
if (lowmem > pcms->max_ram_below_4g) {
|
||||
lowmem = pcms->max_ram_below_4g;
|
||||
if (machine->ram_size - lowmem > lowmem &&
|
||||
@@ -176,7 +179,6 @@ static void pc_q35_init(MachineState *machine)
|
||||
qdev_init_nofail(DEVICE(q35_host));
|
||||
phb = PCI_HOST_BRIDGE(q35_host);
|
||||
host_bus = phb->bus;
|
||||
pcms->bus = phb->bus;
|
||||
/* create ISA bus */
|
||||
lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
|
||||
ICH9_LPC_FUNC), true,
|
||||
@@ -287,6 +289,7 @@ static void pc_q35_machine_options(MachineClass *m)
|
||||
m->default_machine_opts = "firmware=bios-256k.bin";
|
||||
m->default_display = "std";
|
||||
m->no_floppy = 1;
|
||||
m->has_dynamic_sysbus = true;
|
||||
}
|
||||
|
||||
static void pc_q35_2_7_machine_options(MachineClass *m)
|
||||
|
||||
@@ -68,7 +68,6 @@
|
||||
#include <hw/isa/isa.h>
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/dma.h"
|
||||
|
||||
#include <hw/ide/pci.h>
|
||||
#include <hw/ide/ahci.h>
|
||||
|
||||
@@ -111,6 +110,7 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
|
||||
int sata_cap_offset;
|
||||
uint8_t *sata_cap;
|
||||
d = ICH_AHCI(dev);
|
||||
int ret;
|
||||
|
||||
ahci_realize(&d->ahci, DEVICE(dev), pci_get_address_space(dev), 6);
|
||||
|
||||
@@ -146,7 +146,10 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
|
||||
/* Although the AHCI 1.3 specification states that the first capability
|
||||
* should be PMCAP, the Intel ICH9 data sheet specifies that the ICH9
|
||||
* AHCI device puts the MSI capability first, pointing to 0x80. */
|
||||
msi_init(dev, ICH9_MSI_CAP_OFFSET, 1, true, false);
|
||||
ret = msi_init(dev, ICH9_MSI_CAP_OFFSET, 1, true, false, NULL);
|
||||
/* Any error other than -ENOTSUP(board's MSI support is broken)
|
||||
* is a programming error. Fall back to INTx silently on -ENOTSUP */
|
||||
assert(!ret || ret == -ENOTSUP);
|
||||
}
|
||||
|
||||
static void pci_ich9_uninit(PCIDevice *dev)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "ui/console.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/input/hid.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define HID_USAGE_ERROR_ROLLOVER 0x01
|
||||
#define HID_USAGE_POSTFAIL 0x02
|
||||
@@ -234,7 +235,7 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
|
||||
key->down,
|
||||
scancodes);
|
||||
if (hs->n + count > QUEUE_LENGTH) {
|
||||
fprintf(stderr, "usb-kbd: warning: key event queue full\n");
|
||||
trace_hid_kbd_queue_full();
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
|
||||
@@ -23,3 +23,9 @@ milkymist_softusb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %
|
||||
milkymist_softusb_mevt(uint8_t m) "m %d"
|
||||
milkymist_softusb_kevt(uint8_t m) "m %d"
|
||||
milkymist_softusb_pulse_irq(void) "Pulse IRQ"
|
||||
|
||||
# hw/input/hid.c
|
||||
hid_kbd_queue_full(void) "queue full"
|
||||
|
||||
# hw/input/virtio
|
||||
virtio_input_queue_full(void) "queue full"
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "hw/qdev.h"
|
||||
#include "hw/virtio/virtio.h"
|
||||
@@ -47,7 +48,7 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
|
||||
virtqueue_get_avail_bytes(vinput->evt, &have, NULL, need, 0);
|
||||
if (have < need) {
|
||||
vinput->qindex = 0;
|
||||
fprintf(stderr, "%s: ENOSPC in vq, dropping events\n", __func__);
|
||||
trace_virtio_input_queue_full();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -187,11 +187,11 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
|
||||
case 0x1c: /* SysTick Calibration Value. */
|
||||
return 10000;
|
||||
case 0xd00: /* CPUID Base. */
|
||||
cpu = ARM_CPU(current_cpu);
|
||||
cpu = ARM_CPU(qemu_get_cpu(0));
|
||||
return cpu->midr;
|
||||
case 0xd04: /* Interrupt Control State. */
|
||||
/* VECTACTIVE */
|
||||
cpu = ARM_CPU(current_cpu);
|
||||
cpu = ARM_CPU(qemu_get_cpu(0));
|
||||
val = cpu->env.v7m.exception;
|
||||
if (val == 1023) {
|
||||
val = 0;
|
||||
@@ -222,7 +222,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
|
||||
val |= (1 << 31);
|
||||
return val;
|
||||
case 0xd08: /* Vector Table Offset. */
|
||||
cpu = ARM_CPU(current_cpu);
|
||||
cpu = ARM_CPU(qemu_get_cpu(0));
|
||||
return cpu->env.v7m.vecbase;
|
||||
case 0xd0c: /* Application Interrupt/Reset Control. */
|
||||
return 0xfa050000;
|
||||
@@ -349,7 +349,7 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
|
||||
}
|
||||
break;
|
||||
case 0xd08: /* Vector Table Offset. */
|
||||
cpu = ARM_CPU(current_cpu);
|
||||
cpu = ARM_CPU(qemu_get_cpu(0));
|
||||
cpu->env.v7m.vecbase = value & 0xffffff80;
|
||||
break;
|
||||
case 0xd0c: /* Application Interrupt/Reset Control. */
|
||||
|
||||
@@ -191,9 +191,16 @@ petalogix_ml605_init(MachineState *machine)
|
||||
spi = (SSIBus *)qdev_get_child_bus(dev, "spi");
|
||||
|
||||
for (i = 0; i < NUM_SPI_FLASHES; i++) {
|
||||
DriveInfo *dinfo = drive_get_next(IF_MTD);
|
||||
qemu_irq cs_line;
|
||||
|
||||
dev = ssi_create_slave(spi, "n25q128");
|
||||
dev = ssi_create_slave_no_init(spi, "n25q128");
|
||||
if (dinfo) {
|
||||
qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
|
||||
&error_fatal);
|
||||
}
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
cs_line = qdev_get_gpio_in_named(dev, SSI_GPIO_CS, 0);
|
||||
sysbus_connect_irq(busdev, i+1, cs_line);
|
||||
}
|
||||
|
||||
@@ -51,5 +51,5 @@ obj-$(CONFIG_MIPS_ITU) += mips_itu.o
|
||||
obj-$(CONFIG_PVPANIC) += pvpanic.o
|
||||
obj-$(CONFIG_EDU) += edu.o
|
||||
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
|
||||
obj-$(CONFIG_AUX) += aux.o
|
||||
obj-$(CONFIG_AUX) += auxbus.o
|
||||
obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* aux.c
|
||||
* auxbus.c
|
||||
*
|
||||
* Copyright 2015 : GreenSocs Ltd
|
||||
* http://www.greensocs.com/ , email: info@greensocs.com
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/misc/aux.h"
|
||||
#include "hw/misc/auxbus.h"
|
||||
#include "hw/i2c/i2c.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
@@ -153,12 +153,12 @@ AUXReply aux_request(AUXBus *bus, AUXCommand cmd, uint32_t address,
|
||||
case WRITE_I2C_MOT:
|
||||
case READ_I2C_MOT:
|
||||
is_write = cmd == READ_I2C_MOT ? false : true;
|
||||
ret = AUX_I2C_NACK;
|
||||
if (!i2c_bus_busy(i2c_bus)) {
|
||||
/*
|
||||
* No transactions started..
|
||||
*/
|
||||
if (i2c_start_transfer(i2c_bus, address, is_write)) {
|
||||
ret = AUX_I2C_NACK;
|
||||
break;
|
||||
}
|
||||
} else if ((address != bus->last_i2c_address) ||
|
||||
@@ -168,22 +168,22 @@ AUXReply aux_request(AUXBus *bus, AUXCommand cmd, uint32_t address,
|
||||
*/
|
||||
i2c_end_transfer(i2c_bus);
|
||||
if (i2c_start_transfer(i2c_bus, address, is_write)) {
|
||||
ret = AUX_I2C_NACK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bus->last_transaction = cmd;
|
||||
bus->last_i2c_address = address;
|
||||
while (len > 0) {
|
||||
if (i2c_send_recv(i2c_bus, data++, is_write) < 0) {
|
||||
ret = AUX_I2C_NACK;
|
||||
i2c_end_transfer(i2c_bus);
|
||||
break;
|
||||
}
|
||||
len--;
|
||||
}
|
||||
bus->last_transaction = cmd;
|
||||
bus->last_i2c_address = address;
|
||||
ret = AUX_I2C_ACK;
|
||||
if (len == 0) {
|
||||
ret = AUX_I2C_ACK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DPRINTF("Not implemented!\n");
|
||||
@@ -371,6 +371,12 @@ static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
|
||||
case CLK_32k:
|
||||
freq = CKIL_FREQ;
|
||||
break;
|
||||
case CLK_HIGH:
|
||||
freq = 24000000;
|
||||
break;
|
||||
case CLK_HIGH_DIV:
|
||||
freq = 24000000 / 8;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
|
||||
TYPE_IMX6_CCM, __func__, clock);
|
||||
|
||||
@@ -147,14 +147,14 @@ static int max111x_init(SSISlave *d, int inputs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max1110_init(SSISlave *dev)
|
||||
static void max1110_realize(SSISlave *dev, Error **errp)
|
||||
{
|
||||
return max111x_init(dev, 8);
|
||||
max111x_init(dev, 8);
|
||||
}
|
||||
|
||||
static int max1111_init(SSISlave *dev)
|
||||
static void max1111_realize(SSISlave *dev, Error **errp)
|
||||
{
|
||||
return max111x_init(dev, 4);
|
||||
max111x_init(dev, 4);
|
||||
}
|
||||
|
||||
void max111x_set_input(DeviceState *dev, int line, uint8_t value)
|
||||
@@ -183,7 +183,7 @@ static void max1110_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
||||
|
||||
k->init = max1110_init;
|
||||
k->realize = max1110_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo max1110_info = {
|
||||
@@ -196,7 +196,7 @@ static void max1111_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
||||
|
||||
k->init = max1111_init;
|
||||
k->realize = max1111_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo max1111_info = {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user