Compare commits
44 Commits
v2.0.0-rc0
...
pull-gtk-3
Author | SHA1 | Date | |
---|---|---|---|
|
2bda66028b | ||
|
298526fe92 | ||
|
881249c792 | ||
|
f4b11eee2f | ||
|
6fffa26244 | ||
|
e638308097 | ||
|
9c749e4dbe | ||
|
379e21c258 | ||
|
a00f66ab9b | ||
|
69df1c3c9d | ||
|
6d4adef48d | ||
|
3b163b0165 | ||
|
f214530f56 | ||
|
9d5614d582 | ||
|
39d16d29c8 | ||
|
cc13eead53 | ||
|
86c3b20a5f | ||
|
6d585ca559 | ||
|
dfb3804d47 | ||
|
4191d0eb41 | ||
|
03d51428e2 | ||
|
582ab779c5 | ||
|
8678b71ce6 | ||
|
1fcc9ddfb3 | ||
|
c6e929e784 | ||
|
b3c56df769 | ||
|
ed7a0aa8bc | ||
|
04ce397b33 | ||
|
14b155ddc4 | ||
|
e029f29385 | ||
|
90f1cd9138 | ||
|
7d11fc7c2b | ||
|
096c46c0ff | ||
|
df9351e372 | ||
|
50573c66eb | ||
|
46dea4160d | ||
|
dc668ded10 | ||
|
1e8ece0db3 | ||
|
4a41a2d68a | ||
|
62e466e845 | ||
|
c3adb58fe0 | ||
|
aa7a6a399f | ||
|
2e323f03bf | ||
|
22956a3755 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -21,6 +21,7 @@
|
||||
libdis*
|
||||
libuser
|
||||
/linux-headers/asm
|
||||
/qga/qapi-generated
|
||||
/qapi-generated
|
||||
/qapi-types.[ch]
|
||||
/qapi-visit.[ch]
|
||||
|
53
.travis.yml
53
.travis.yml
@@ -4,6 +4,12 @@ python:
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
- "irc.oftc.net#qemu"
|
||||
on_success: change
|
||||
on_failure: always
|
||||
env:
|
||||
global:
|
||||
- TEST_CMD="make check"
|
||||
@@ -14,23 +20,23 @@ env:
|
||||
- GUI_PKGS="libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev"
|
||||
- EXTRA_PKGS=""
|
||||
matrix:
|
||||
- TARGETS=alpha-softmmu,alpha-linux-user
|
||||
- TARGETS=arm-softmmu,arm-linux-user
|
||||
- TARGETS=aarch64-softmmu,aarch64-linux-user
|
||||
- TARGETS=cris-softmmu
|
||||
- TARGETS=i386-softmmu,x86_64-softmmu
|
||||
- TARGETS=lm32-softmmu
|
||||
- TARGETS=m68k-softmmu
|
||||
- TARGETS=microblaze-softmmu,microblazeel-softmmu
|
||||
- TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu
|
||||
- TARGETS=moxie-softmmu
|
||||
- TARGETS=or32-softmmu,
|
||||
- TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu
|
||||
- TARGETS=s390x-softmmu
|
||||
- TARGETS=sh4-softmmu,sh4eb-softmmu
|
||||
- TARGETS=sparc-softmmu,sparc64-softmmu
|
||||
- TARGETS=unicore32-softmmu
|
||||
- TARGETS=xtensa-softmmu,xtensaeb-softmmu
|
||||
- TARGETS=alpha-softmmu,alpha-linux-user
|
||||
- TARGETS=arm-softmmu,arm-linux-user
|
||||
- TARGETS=aarch64-softmmu,aarch64-linux-user
|
||||
- TARGETS=cris-softmmu
|
||||
- TARGETS=i386-softmmu,x86_64-softmmu
|
||||
- TARGETS=lm32-softmmu
|
||||
- TARGETS=m68k-softmmu
|
||||
- TARGETS=microblaze-softmmu,microblazeel-softmmu
|
||||
- TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu
|
||||
- TARGETS=moxie-softmmu
|
||||
- TARGETS=or32-softmmu,
|
||||
- TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu
|
||||
- TARGETS=s390x-softmmu
|
||||
- TARGETS=sh4-softmmu,sh4eb-softmmu
|
||||
- TARGETS=sparc-softmmu,sparc64-softmmu
|
||||
- TARGETS=unicore32-softmmu
|
||||
- TARGETS=xtensa-softmmu,xtensaeb-softmmu
|
||||
before_install:
|
||||
- git submodule update --init --recursive
|
||||
- sudo apt-get update -qq
|
||||
@@ -46,6 +52,10 @@ matrix:
|
||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
EXTRA_CONFIG="--enable-debug --enable-tcg-interpreter"
|
||||
compiler: gcc
|
||||
# All the extra -dev packages
|
||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
EXTRA_PKGS="libaio-dev libcap-ng-dev libattr1-dev libbrlapi-dev uuid-dev libusb-1.0.0-dev"
|
||||
compiler: gcc
|
||||
# Currently configure doesn't force --disable-pie
|
||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
EXTRA_CONFIG="--enable-gprof --enable-gcov --disable-pie"
|
||||
@@ -65,8 +75,7 @@ matrix:
|
||||
EXTRA_CONFIG="--enable-trace-backend=ftrace"
|
||||
TEST_CMD=""
|
||||
compiler: gcc
|
||||
# This disabled make check for the ftrace backend which needs more setting up
|
||||
# Currently broken on 12.04 due to mis-packaged liburcu and changed API, will be pulled.
|
||||
#- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
# EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
|
||||
# EXTRA_CONFIG="--enable-trace-backend=ust"
|
||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
|
||||
EXTRA_CONFIG="--enable-trace-backend=ust"
|
||||
compiler: gcc
|
||||
|
5
Makefile
5
Makefile
@@ -265,10 +265,7 @@ clean:
|
||||
# avoid old build problems by removing potentially incorrect old files
|
||||
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
|
||||
rm -f qemu-options.def
|
||||
find . -name '*.[oda]' -type f -exec rm -f {} +
|
||||
find . -name '*.l[oa]' -type f -exec rm -f {} +
|
||||
find . -name '*$(DSOSUF)' -type f -exec rm -f {} +
|
||||
find . -name '*.mo' -type f -exec rm -f {} +
|
||||
find . \( -name '*.l[oa]' -o -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f -exec rm {} +
|
||||
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
|
||||
rm -f fsdev/*.pod
|
||||
rm -rf .libs */.libs
|
||||
|
9
block.c
9
block.c
@@ -1388,12 +1388,19 @@ done:
|
||||
ret = -EINVAL;
|
||||
goto close_and_fail;
|
||||
}
|
||||
QDECREF(options);
|
||||
|
||||
if (!bdrv_key_required(bs)) {
|
||||
bdrv_dev_change_media_cb(bs, true);
|
||||
} else if (!runstate_check(RUN_STATE_PRELAUNCH)
|
||||
&& !runstate_check(RUN_STATE_INMIGRATE)
|
||||
&& !runstate_check(RUN_STATE_PAUSED)) { /* HACK */
|
||||
error_setg(errp,
|
||||
"Guest must be stopped for opening of encrypted image");
|
||||
ret = -EBUSY;
|
||||
goto close_and_fail;
|
||||
}
|
||||
|
||||
QDECREF(options);
|
||||
*pbs = bs;
|
||||
return 0;
|
||||
|
||||
|
@@ -43,6 +43,17 @@ static void nbd_recv_coroutines_enter_all(NbdClientSession *s)
|
||||
}
|
||||
}
|
||||
|
||||
static void nbd_teardown_connection(NbdClientSession *client)
|
||||
{
|
||||
/* finish any pending coroutines */
|
||||
shutdown(client->sock, 2);
|
||||
nbd_recv_coroutines_enter_all(client);
|
||||
|
||||
qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL);
|
||||
closesocket(client->sock);
|
||||
client->sock = -1;
|
||||
}
|
||||
|
||||
static void nbd_reply_ready(void *opaque)
|
||||
{
|
||||
NbdClientSession *s = opaque;
|
||||
@@ -78,7 +89,7 @@ static void nbd_reply_ready(void *opaque)
|
||||
}
|
||||
|
||||
fail:
|
||||
nbd_recv_coroutines_enter_all(s);
|
||||
nbd_teardown_connection(s);
|
||||
}
|
||||
|
||||
static void nbd_restart_write(void *opaque)
|
||||
@@ -324,7 +335,7 @@ int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num,
|
||||
|
||||
}
|
||||
|
||||
static void nbd_teardown_connection(NbdClientSession *client)
|
||||
void nbd_client_session_close(NbdClientSession *client)
|
||||
{
|
||||
struct nbd_request request = {
|
||||
.type = NBD_CMD_DISC,
|
||||
@@ -332,22 +343,14 @@ static void nbd_teardown_connection(NbdClientSession *client)
|
||||
.len = 0
|
||||
};
|
||||
|
||||
nbd_send_request(client->sock, &request);
|
||||
|
||||
/* finish any pending coroutines */
|
||||
shutdown(client->sock, 2);
|
||||
nbd_recv_coroutines_enter_all(client);
|
||||
|
||||
qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL);
|
||||
closesocket(client->sock);
|
||||
client->sock = -1;
|
||||
}
|
||||
|
||||
void nbd_client_session_close(NbdClientSession *client)
|
||||
{
|
||||
if (!client->bs) {
|
||||
return;
|
||||
}
|
||||
if (client->sock == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
nbd_send_request(client->sock, &request);
|
||||
|
||||
nbd_teardown_connection(client);
|
||||
client->bs = NULL;
|
||||
|
@@ -61,7 +61,7 @@
|
||||
/* These structures are ones that are defined in the VHDX specification
|
||||
* document */
|
||||
|
||||
#define VHDX_FILE_SIGNATURE 0x656C696678646876 /* "vhdxfile" in ASCII */
|
||||
#define VHDX_FILE_SIGNATURE 0x656C696678646876ULL /* "vhdxfile" in ASCII */
|
||||
typedef struct VHDXFileIdentifier {
|
||||
uint64_t signature; /* "vhdxfile" in ASCII */
|
||||
uint16_t creator[256]; /* optional; utf-16 string to identify
|
||||
@@ -238,7 +238,7 @@ typedef struct QEMU_PACKED VHDXLogDataSector {
|
||||
/* upper 44 bits are the file offset in 1MB units lower 3 bits are the state
|
||||
other bits are reserved */
|
||||
#define VHDX_BAT_STATE_BIT_MASK 0x07
|
||||
#define VHDX_BAT_FILE_OFF_MASK 0xFFFFFFFFFFF00000 /* upper 44 bits */
|
||||
#define VHDX_BAT_FILE_OFF_MASK 0xFFFFFFFFFFF00000ULL /* upper 44 bits */
|
||||
typedef uint64_t VHDXBatEntry;
|
||||
|
||||
/* ---- METADATA REGION STRUCTURES ---- */
|
||||
@@ -247,7 +247,7 @@ typedef uint64_t VHDXBatEntry;
|
||||
#define VHDX_METADATA_MAX_ENTRIES 2047 /* not including the header */
|
||||
#define VHDX_METADATA_TABLE_MAX_SIZE \
|
||||
(VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1))
|
||||
#define VHDX_METADATA_SIGNATURE 0x617461646174656D /* "metadata" in ASCII */
|
||||
#define VHDX_METADATA_SIGNATURE 0x617461646174656DULL /* "metadata" in ASCII */
|
||||
typedef struct QEMU_PACKED VHDXMetadataTableHeader {
|
||||
uint64_t signature; /* "metadata" in ASCII */
|
||||
uint16_t reserved;
|
||||
|
5
configure
vendored
5
configure
vendored
@@ -3822,6 +3822,11 @@ fi
|
||||
|
||||
int128=no
|
||||
cat > $TMPC << EOF
|
||||
#if defined(__clang_major__) && defined(__clang_minor__)
|
||||
# if ((__clang_major__ < 3) || (__clang_major__ == 3) && (__clang_minor__ < 2))
|
||||
# error __int128_t does not work in CLANG before 3.2
|
||||
# endif
|
||||
#endif
|
||||
__int128_t a;
|
||||
__uint128_t b;
|
||||
int main (void) {
|
||||
|
@@ -223,13 +223,13 @@ static void *cur_chip = NULL; /* current chip point */
|
||||
/* static OPLSAMPLE *bufL,*bufR; */
|
||||
static OPL_CH *S_CH;
|
||||
static OPL_CH *E_CH;
|
||||
OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
|
||||
static OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
|
||||
|
||||
static INT32 outd[1];
|
||||
static INT32 ams;
|
||||
static INT32 vib;
|
||||
INT32 *ams_table;
|
||||
INT32 *vib_table;
|
||||
static INT32 *ams_table;
|
||||
static INT32 *vib_table;
|
||||
static INT32 amsIncr;
|
||||
static INT32 vibIncr;
|
||||
static INT32 feedback2; /* connect for SLOT 2 */
|
||||
|
@@ -148,7 +148,7 @@ typedef void (*vgic_translate_fn)(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel);
|
||||
|
||||
/* synthetic translate function used for clear/set registers to completely
|
||||
* clear a setting using a clear-register before setting the remaing bits
|
||||
* clear a setting using a clear-register before setting the remaining bits
|
||||
* using a set-register */
|
||||
static void translate_clear(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel)
|
||||
|
@@ -195,8 +195,8 @@ static void process_tx_fcb(eTSEC *etsec)
|
||||
|
||||
/* if packet is IP4 and IP checksum is requested */
|
||||
if (flags & FCB_TX_IP && flags & FCB_TX_CIP) {
|
||||
/* do IP4 checksum (TODO This funtion does TCP/UDP checksum but not sure
|
||||
* if it also does IP4 checksum. */
|
||||
/* do IP4 checksum (TODO This function does TCP/UDP checksum
|
||||
* but not sure if it also does IP4 checksum.) */
|
||||
net_checksum_calculate(etsec->tx_buffer + 8,
|
||||
etsec->tx_buffer_len - 8);
|
||||
}
|
||||
@@ -592,7 +592,7 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
|
||||
|
||||
/* TODO: Broadcast and Multicast */
|
||||
|
||||
if (bd.flags | BD_INTERRUPT) {
|
||||
if (bd.flags & BD_INTERRUPT) {
|
||||
/* Set RXFx */
|
||||
etsec->regs[RSTAT].value |= 1 << (7 - ring_nbr);
|
||||
|
||||
@@ -601,7 +601,7 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
|
||||
}
|
||||
|
||||
} else {
|
||||
if (bd.flags | BD_INTERRUPT) {
|
||||
if (bd.flags & BD_INTERRUPT) {
|
||||
/* Set IEVENT */
|
||||
ievent_set(etsec, IEVENT_RXB);
|
||||
}
|
||||
|
@@ -1905,6 +1905,26 @@ static const VMStateInfo vmstate_info_scsi_requests = {
|
||||
.put = put_scsi_requests,
|
||||
};
|
||||
|
||||
static bool scsi_sense_state_needed(void *opaque)
|
||||
{
|
||||
SCSIDevice *s = opaque;
|
||||
|
||||
return s->sense_len > SCSI_SENSE_BUF_SIZE_OLD;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_scsi_sense_state = {
|
||||
.name = "SCSIDevice/sense",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_UINT8_SUB_ARRAY(sense, SCSIDevice,
|
||||
SCSI_SENSE_BUF_SIZE_OLD,
|
||||
SCSI_SENSE_BUF_SIZE - SCSI_SENSE_BUF_SIZE_OLD),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_scsi_device = {
|
||||
.name = "SCSIDevice",
|
||||
.version_id = 1,
|
||||
@@ -1915,7 +1935,7 @@ const VMStateDescription vmstate_scsi_device = {
|
||||
VMSTATE_UINT8(unit_attention.asc, SCSIDevice),
|
||||
VMSTATE_UINT8(unit_attention.ascq, SCSIDevice),
|
||||
VMSTATE_BOOL(sense_is_ua, SCSIDevice),
|
||||
VMSTATE_UINT8_ARRAY(sense, SCSIDevice, SCSI_SENSE_BUF_SIZE),
|
||||
VMSTATE_UINT8_SUB_ARRAY(sense, SCSIDevice, 0, SCSI_SENSE_BUF_SIZE_OLD),
|
||||
VMSTATE_UINT32(sense_len, SCSIDevice),
|
||||
{
|
||||
.name = "requests",
|
||||
@@ -1927,6 +1947,14 @@ const VMStateDescription vmstate_scsi_device = {
|
||||
.offset = 0,
|
||||
},
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (VMStateSubsection []) {
|
||||
{
|
||||
.vmsd = &vmstate_scsi_sense_state,
|
||||
.needed = scsi_sense_state_needed,
|
||||
}, {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -195,9 +195,9 @@ static int vscsi_send_iu(VSCSIState *s, vscsi_req *req,
|
||||
req->crq.s.IU_data_ptr = req->iu.srp.rsp.tag; /* right byte order */
|
||||
|
||||
if (rc == 0) {
|
||||
req->crq.s.status = 0x99; /* Just needs to be non-zero */
|
||||
req->crq.s.status = VIOSRP_OK;
|
||||
} else {
|
||||
req->crq.s.status = 0x00;
|
||||
req->crq.s.status = VIOSRP_ADAPTER_FAIL;
|
||||
}
|
||||
|
||||
rc1 = spapr_vio_send_crq(&s->vdev, req->crq.raw);
|
||||
|
@@ -304,6 +304,8 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
|
||||
size_t resid)
|
||||
{
|
||||
VirtIOSCSIReq *req = r->hba_private;
|
||||
VirtIOSCSI *s = req->dev;
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
|
||||
uint32_t sense_len;
|
||||
|
||||
if (r->io_canceled) {
|
||||
@@ -317,7 +319,7 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
|
||||
} else {
|
||||
req->resp.cmd->resid = 0;
|
||||
sense_len = scsi_req_get_sense(r, req->resp.cmd->sense,
|
||||
VIRTIO_SCSI_SENSE_SIZE);
|
||||
vs->sense_size);
|
||||
req->resp.cmd->sense_len = tswap32(sense_len);
|
||||
}
|
||||
virtio_scsi_complete_req(req);
|
||||
|
@@ -106,9 +106,9 @@ static void grlib_gptimer_enable(GPTimer *timer)
|
||||
/* ptimer is triggered when the counter reach 0 but GPTimer is triggered at
|
||||
underflow. Set count + 1 to simulate the GPTimer behavior. */
|
||||
|
||||
trace_grlib_gptimer_enable(timer->id, timer->counter + 1);
|
||||
trace_grlib_gptimer_enable(timer->id, timer->counter);
|
||||
|
||||
ptimer_set_count(timer->ptimer, timer->counter + 1);
|
||||
ptimer_set_count(timer->ptimer, (uint64_t)timer->counter + 1);
|
||||
ptimer_run(timer->ptimer, 1);
|
||||
}
|
||||
|
||||
|
@@ -31,6 +31,7 @@ typedef struct SCSISense {
|
||||
uint8_t ascq;
|
||||
} SCSISense;
|
||||
|
||||
#define SCSI_SENSE_BUF_SIZE_OLD 96
|
||||
#define SCSI_SENSE_BUF_SIZE 252
|
||||
|
||||
struct SCSICommand {
|
||||
|
@@ -650,6 +650,9 @@ extern const VMStateInfo vmstate_info_bitmap;
|
||||
#define VMSTATE_UINT8_ARRAY(_f, _s, _n) \
|
||||
VMSTATE_UINT8_ARRAY_V(_f, _s, _n, 0)
|
||||
|
||||
#define VMSTATE_UINT8_SUB_ARRAY(_f, _s, _start, _num) \
|
||||
VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint8, uint8_t)
|
||||
|
||||
#define VMSTATE_UINT8_2DARRAY(_f, _s, _n1, _n2) \
|
||||
VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, 0)
|
||||
|
||||
|
@@ -345,6 +345,6 @@ int index_from_key(const char *key);
|
||||
|
||||
/* gtk.c */
|
||||
void early_gtk_display_init(void);
|
||||
void gtk_display_init(DisplayState *ds, bool full_screen);
|
||||
void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover);
|
||||
|
||||
#endif
|
||||
|
@@ -810,6 +810,7 @@ ETEXI
|
||||
DEF("display", HAS_ARG, QEMU_OPTION_display,
|
||||
"-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
|
||||
" [,window_close=on|off]|curses|none|\n"
|
||||
" gtk[,grab_on_hover=on|off]|\n"
|
||||
" vnc=<display>[,<optargs>]\n"
|
||||
" select display type\n", QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
@@ -833,6 +834,10 @@ graphics card, but its output will not be displayed to the QEMU
|
||||
user. This option differs from the -nographic option in that it
|
||||
only affects what is done with video output; -nographic also changes
|
||||
the destination of the serial and parallel port data.
|
||||
@item gtk
|
||||
Display video output in a GTK window. This interface provides drop-down
|
||||
menus and other UI elements to configure and control the VM during
|
||||
runtime.
|
||||
@item vnc
|
||||
Start a VNC server on display <arg>
|
||||
@end table
|
||||
|
@@ -22,7 +22,9 @@ mech_list: digest-md5
|
||||
# Some older builds of MIT kerberos on Linux ignore this option &
|
||||
# instead need KRB5_KTNAME env var.
|
||||
# For modern Linux, and other OS, this should be sufficient
|
||||
keytab: /etc/qemu/krb5.tab
|
||||
#
|
||||
# There is no default value here, uncomment if you need this
|
||||
#keytab: /etc/qemu/krb5.tab
|
||||
|
||||
# If using digest-md5 for username/passwds, then this is the file
|
||||
# containing the passwds. Use 'saslpasswd2 -a qemu [username]'
|
||||
|
@@ -18,7 +18,7 @@ git clone "${src}" ${destination}
|
||||
pushd ${destination}
|
||||
git checkout "v${version}"
|
||||
git submodule update --init
|
||||
rm -rf .git roms/*/.git
|
||||
rm -rf .git roms/*/.git dtc/.git pixman/.git
|
||||
popd
|
||||
tar cfj ${destination}.tar.bz2 ${destination}
|
||||
rm -rf ${destination}
|
||||
|
@@ -20,6 +20,7 @@ stub-obj-y += mon-set-error.o
|
||||
stub-obj-y += pci-drive-hot-add.o
|
||||
stub-obj-y += qtest.o
|
||||
stub-obj-y += reset.o
|
||||
stub-obj-y += runstate-check.o
|
||||
stub-obj-y += set-fd-handler.o
|
||||
stub-obj-y += slirp.o
|
||||
stub-obj-y += sysbus.o
|
||||
|
6
stubs/runstate-check.c
Normal file
6
stubs/runstate-check.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
bool runstate_check(RunState state)
|
||||
{
|
||||
return state == RUN_STATE_PRELAUNCH;
|
||||
}
|
@@ -488,7 +488,7 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
|
||||
|
||||
static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
{
|
||||
/* Perfomance monitor registers user accessibility is controlled
|
||||
/* Performance monitor registers user accessibility is controlled
|
||||
* by PMUSERENR.
|
||||
*/
|
||||
if (arm_current_pl(env) == 0 && !env->cp15.c9_pmuserenr) {
|
||||
|
@@ -2216,7 +2216,7 @@ static int bcd_cmp_mag(ppc_avr_t *a, ppc_avr_t *b)
|
||||
uint8_t dig_a = bcd_get_digit(a, i, &invalid);
|
||||
uint8_t dig_b = bcd_get_digit(b, i, &invalid);
|
||||
if (unlikely(invalid)) {
|
||||
return 0; /* doesnt matter */
|
||||
return 0; /* doesn't matter */
|
||||
} else if (dig_a > dig_b) {
|
||||
return 1;
|
||||
} else if (dig_a < dig_b) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -39,33 +39,33 @@ typedef enum {
|
||||
#define TCG_TARGET_CALL_STACK_OFFSET 0
|
||||
|
||||
/* optional instructions */
|
||||
#define TCG_TARGET_HAS_div_i32 0
|
||||
#define TCG_TARGET_HAS_rem_i32 0
|
||||
#define TCG_TARGET_HAS_div_i32 1
|
||||
#define TCG_TARGET_HAS_rem_i32 1
|
||||
#define TCG_TARGET_HAS_ext8s_i32 1
|
||||
#define TCG_TARGET_HAS_ext16s_i32 1
|
||||
#define TCG_TARGET_HAS_ext8u_i32 1
|
||||
#define TCG_TARGET_HAS_ext16u_i32 1
|
||||
#define TCG_TARGET_HAS_bswap16_i32 1
|
||||
#define TCG_TARGET_HAS_bswap32_i32 1
|
||||
#define TCG_TARGET_HAS_not_i32 0
|
||||
#define TCG_TARGET_HAS_neg_i32 0
|
||||
#define TCG_TARGET_HAS_not_i32 1
|
||||
#define TCG_TARGET_HAS_neg_i32 1
|
||||
#define TCG_TARGET_HAS_rot_i32 1
|
||||
#define TCG_TARGET_HAS_andc_i32 0
|
||||
#define TCG_TARGET_HAS_orc_i32 0
|
||||
#define TCG_TARGET_HAS_eqv_i32 0
|
||||
#define TCG_TARGET_HAS_andc_i32 1
|
||||
#define TCG_TARGET_HAS_orc_i32 1
|
||||
#define TCG_TARGET_HAS_eqv_i32 1
|
||||
#define TCG_TARGET_HAS_nand_i32 0
|
||||
#define TCG_TARGET_HAS_nor_i32 0
|
||||
#define TCG_TARGET_HAS_deposit_i32 0
|
||||
#define TCG_TARGET_HAS_movcond_i32 0
|
||||
#define TCG_TARGET_HAS_add2_i32 0
|
||||
#define TCG_TARGET_HAS_sub2_i32 0
|
||||
#define TCG_TARGET_HAS_deposit_i32 1
|
||||
#define TCG_TARGET_HAS_movcond_i32 1
|
||||
#define TCG_TARGET_HAS_add2_i32 1
|
||||
#define TCG_TARGET_HAS_sub2_i32 1
|
||||
#define TCG_TARGET_HAS_mulu2_i32 0
|
||||
#define TCG_TARGET_HAS_muls2_i32 0
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
|
||||
#define TCG_TARGET_HAS_div_i64 0
|
||||
#define TCG_TARGET_HAS_rem_i64 0
|
||||
#define TCG_TARGET_HAS_div_i64 1
|
||||
#define TCG_TARGET_HAS_rem_i64 1
|
||||
#define TCG_TARGET_HAS_ext8s_i64 1
|
||||
#define TCG_TARGET_HAS_ext16s_i64 1
|
||||
#define TCG_TARGET_HAS_ext32s_i64 1
|
||||
@@ -75,22 +75,22 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_bswap16_i64 1
|
||||
#define TCG_TARGET_HAS_bswap32_i64 1
|
||||
#define TCG_TARGET_HAS_bswap64_i64 1
|
||||
#define TCG_TARGET_HAS_not_i64 0
|
||||
#define TCG_TARGET_HAS_neg_i64 0
|
||||
#define TCG_TARGET_HAS_not_i64 1
|
||||
#define TCG_TARGET_HAS_neg_i64 1
|
||||
#define TCG_TARGET_HAS_rot_i64 1
|
||||
#define TCG_TARGET_HAS_andc_i64 0
|
||||
#define TCG_TARGET_HAS_orc_i64 0
|
||||
#define TCG_TARGET_HAS_eqv_i64 0
|
||||
#define TCG_TARGET_HAS_andc_i64 1
|
||||
#define TCG_TARGET_HAS_orc_i64 1
|
||||
#define TCG_TARGET_HAS_eqv_i64 1
|
||||
#define TCG_TARGET_HAS_nand_i64 0
|
||||
#define TCG_TARGET_HAS_nor_i64 0
|
||||
#define TCG_TARGET_HAS_deposit_i64 0
|
||||
#define TCG_TARGET_HAS_movcond_i64 0
|
||||
#define TCG_TARGET_HAS_add2_i64 0
|
||||
#define TCG_TARGET_HAS_sub2_i64 0
|
||||
#define TCG_TARGET_HAS_deposit_i64 1
|
||||
#define TCG_TARGET_HAS_movcond_i64 1
|
||||
#define TCG_TARGET_HAS_add2_i64 1
|
||||
#define TCG_TARGET_HAS_sub2_i64 1
|
||||
#define TCG_TARGET_HAS_mulu2_i64 0
|
||||
#define TCG_TARGET_HAS_muls2_i64 0
|
||||
#define TCG_TARGET_HAS_muluh_i64 0
|
||||
#define TCG_TARGET_HAS_mulsh_i64 0
|
||||
#define TCG_TARGET_HAS_muluh_i64 1
|
||||
#define TCG_TARGET_HAS_mulsh_i64 1
|
||||
|
||||
enum {
|
||||
TCG_AREG0 = TCG_REG_X19,
|
||||
|
129
tests/qemu-iotests/083
Executable file
129
tests/qemu-iotests/083
Executable file
@@ -0,0 +1,129 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Test NBD client unexpected disconnect
|
||||
#
|
||||
# Copyright Red Hat, Inc. 2014
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# creator
|
||||
owner=stefanha@redhat.com
|
||||
|
||||
seq=`basename $0`
|
||||
echo "QA output created by $seq"
|
||||
|
||||
here=`pwd`
|
||||
tmp=/tmp/$$
|
||||
status=1 # failure is the default!
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt generic
|
||||
_supported_proto nbd
|
||||
_supported_os Linux
|
||||
|
||||
# Pick a TCP port based on our pid. This way multiple instances of this test
|
||||
# can run in parallel without conflicting.
|
||||
choose_tcp_port() {
|
||||
echo $((($$ % 31744) + 1024)) # 1024 <= port < 32768
|
||||
}
|
||||
|
||||
wait_for_tcp_port() {
|
||||
while ! (netstat --tcp --listening --numeric | \
|
||||
grep "$1.*0.0.0.0:\*.*LISTEN") 2>&1 >/dev/null; do
|
||||
sleep 0.1
|
||||
done
|
||||
}
|
||||
|
||||
filter_nbd() {
|
||||
# nbd.c error messages contain function names and line numbers that are prone
|
||||
# to change. Message ordering depends on timing between send and receive
|
||||
# callbacks sometimes, making them unreliable.
|
||||
#
|
||||
# Filter out the TCP port number since this changes between runs.
|
||||
sed -e 's#^nbd.c:.*##g' \
|
||||
-e 's#nbd:127.0.0.1:[^:]*:#nbd:127.0.0.1:PORT:#g'
|
||||
}
|
||||
|
||||
check_disconnect() {
|
||||
event=$1
|
||||
when=$2
|
||||
negotiation=$3
|
||||
echo "=== Check disconnect $when $event ==="
|
||||
echo
|
||||
|
||||
port=$(choose_tcp_port)
|
||||
|
||||
cat > "$TEST_DIR/nbd-fault-injector.conf" <<EOF
|
||||
[inject-error]
|
||||
event=$event
|
||||
when=$when
|
||||
EOF
|
||||
|
||||
if [ "$negotiation" = "--classic-negotiation" ]; then
|
||||
extra_args=--classic-negotiation
|
||||
nbd_url="nbd:127.0.0.1:$port"
|
||||
else
|
||||
nbd_url="nbd:127.0.0.1:$port:exportname=foo"
|
||||
fi
|
||||
|
||||
./nbd-fault-injector.py $extra_args "127.0.0.1:$port" "$TEST_DIR/nbd-fault-injector.conf" 2>&1 >/dev/null &
|
||||
wait_for_tcp_port "127.0.0.1:$port"
|
||||
$QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | filter_nbd
|
||||
|
||||
echo
|
||||
}
|
||||
|
||||
for event in neg1 "export" neg2 request reply data; do
|
||||
for when in before after; do
|
||||
check_disconnect "$event" "$when"
|
||||
done
|
||||
|
||||
# Also inject short replies from the NBD server
|
||||
case "$event" in
|
||||
neg1)
|
||||
for when in 8 16; do
|
||||
check_disconnect "$event" "$when"
|
||||
done
|
||||
;;
|
||||
"export")
|
||||
for when in 4 12 16; do
|
||||
check_disconnect "$event" "$when"
|
||||
done
|
||||
;;
|
||||
neg2)
|
||||
for when in 8 10; do
|
||||
check_disconnect "$event" "$when"
|
||||
done
|
||||
;;
|
||||
reply)
|
||||
for when in 4 8; do
|
||||
check_disconnect "$event" "$when"
|
||||
done
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Also check classic negotiation without export information
|
||||
for when in before 8 16 24 28 after; do
|
||||
check_disconnect "neg-classic" "$when" --classic-negotiation
|
||||
done
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
163
tests/qemu-iotests/083.out
Normal file
163
tests/qemu-iotests/083.out
Normal file
@@ -0,0 +1,163 @@
|
||||
QA output created by 083
|
||||
=== Check disconnect before neg1 ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect after neg1 ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 8 neg1 ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 16 neg1 ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect before export ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect after export ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 4 export ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 12 export ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 16 export ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect before neg2 ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect after neg2 ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 8 neg2 ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 10 neg2 ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect before request ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect after request ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect before reply ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect after reply ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 4 reply ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 8 reply ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect before data ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not read image for determining its format: Input/output error
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect after data ===
|
||||
|
||||
|
||||
read failed: Input/output error
|
||||
|
||||
=== Check disconnect before neg-classic ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 8 neg-classic ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 16 neg-classic ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 24 neg-classic ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect 28 neg-classic ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument
|
||||
no file open, try 'help open'
|
||||
|
||||
=== Check disconnect after neg-classic ===
|
||||
|
||||
|
||||
qemu-io: can't open device nbd:127.0.0.1:PORT: Could not read image for determining its format: Input/output error
|
||||
no file open, try 'help open'
|
||||
|
||||
*** done
|
@@ -99,6 +99,23 @@ echo === Encrypted image ===
|
||||
echo
|
||||
|
||||
_make_test_img -o encryption=on $size
|
||||
run_qemu -S <<EOF
|
||||
{ "execute": "qmp_capabilities" }
|
||||
{ "execute": "blockdev-add",
|
||||
"arguments": {
|
||||
"options": {
|
||||
"driver": "$IMGFMT",
|
||||
"id": "disk",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_IMG"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{ "execute": "quit" }
|
||||
EOF
|
||||
|
||||
run_qemu <<EOF
|
||||
{ "execute": "qmp_capabilities" }
|
||||
{ "execute": "blockdev-add",
|
||||
|
@@ -28,7 +28,7 @@ QMP_VERSION
|
||||
=== Encrypted image ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
|
||||
Testing:
|
||||
Testing: -S
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "blockdev-add doesn't support encrypted devices"}}
|
||||
@@ -37,4 +37,13 @@ QMP_VERSION
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
|
||||
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "could not open disk image disk: Guest must be stopped for opening of encrypted image"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
|
||||
|
||||
*** done
|
||||
|
@@ -85,6 +85,7 @@
|
||||
079 rw auto
|
||||
081 rw auto
|
||||
082 rw auto quick
|
||||
085 rw auto quick
|
||||
083 rw auto
|
||||
085 rw auto
|
||||
086 rw auto quick
|
||||
087 rw auto quick
|
||||
087 rw auto
|
||||
|
264
tests/qemu-iotests/nbd-fault-injector.py
Executable file
264
tests/qemu-iotests/nbd-fault-injector.py
Executable file
@@ -0,0 +1,264 @@
|
||||
#!/usr/bin/env python
|
||||
# NBD server - fault injection utility
|
||||
#
|
||||
# Configuration file syntax:
|
||||
# [inject-error "disconnect-neg1"]
|
||||
# event=neg1
|
||||
# io=readwrite
|
||||
# when=before
|
||||
#
|
||||
# Note that Python's ConfigParser squashes together all sections with the same
|
||||
# name, so give each [inject-error] a unique name.
|
||||
#
|
||||
# inject-error options:
|
||||
# event - name of the trigger event
|
||||
# "neg1" - first part of negotiation struct
|
||||
# "export" - export struct
|
||||
# "neg2" - second part of negotiation struct
|
||||
# "request" - NBD request struct
|
||||
# "reply" - NBD reply struct
|
||||
# "data" - request/reply data
|
||||
# io - I/O direction that triggers this rule:
|
||||
# "read", "write", or "readwrite"
|
||||
# default: readwrite
|
||||
# when - after how many bytes to inject the fault
|
||||
# -1 - inject error after I/O
|
||||
# 0 - inject error before I/O
|
||||
# integer - inject error after integer bytes
|
||||
# "before" - alias for 0
|
||||
# "after" - alias for -1
|
||||
# default: before
|
||||
#
|
||||
# Currently the only error injection action is to terminate the server process.
|
||||
# This resets the TCP connection and thus forces the client to handle
|
||||
# unexpected connection termination.
|
||||
#
|
||||
# Other error injection actions could be added in the future.
|
||||
#
|
||||
# Copyright Red Hat, Inc. 2014
|
||||
#
|
||||
# Authors:
|
||||
# Stefan Hajnoczi <stefanha@redhat.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
# See the COPYING file in the top-level directory.
|
||||
|
||||
import sys
|
||||
import socket
|
||||
import struct
|
||||
import collections
|
||||
import ConfigParser
|
||||
|
||||
FAKE_DISK_SIZE = 8 * 1024 * 1024 * 1024 # 8 GB
|
||||
|
||||
# Protocol constants
|
||||
NBD_CMD_READ = 0
|
||||
NBD_CMD_WRITE = 1
|
||||
NBD_CMD_DISC = 2
|
||||
NBD_REQUEST_MAGIC = 0x25609513
|
||||
NBD_REPLY_MAGIC = 0x67446698
|
||||
NBD_PASSWD = 0x4e42444d41474943
|
||||
NBD_OPTS_MAGIC = 0x49484156454F5054
|
||||
NBD_CLIENT_MAGIC = 0x0000420281861253
|
||||
NBD_OPT_EXPORT_NAME = 1 << 0
|
||||
|
||||
# Protocol structs
|
||||
neg_classic_struct = struct.Struct('>QQQI124x')
|
||||
neg1_struct = struct.Struct('>QQH')
|
||||
export_tuple = collections.namedtuple('Export', 'reserved magic opt len')
|
||||
export_struct = struct.Struct('>IQII')
|
||||
neg2_struct = struct.Struct('>QH124x')
|
||||
request_tuple = collections.namedtuple('Request', 'magic type handle from_ len')
|
||||
request_struct = struct.Struct('>IIQQI')
|
||||
reply_struct = struct.Struct('>IIQ')
|
||||
|
||||
def err(msg):
|
||||
sys.stderr.write(msg + '\n')
|
||||
sys.exit(1)
|
||||
|
||||
def recvall(sock, bufsize):
|
||||
received = 0
|
||||
chunks = []
|
||||
while received < bufsize:
|
||||
chunk = sock.recv(bufsize - received)
|
||||
if len(chunk) == 0:
|
||||
raise Exception('unexpected disconnect')
|
||||
chunks.append(chunk)
|
||||
received += len(chunk)
|
||||
return ''.join(chunks)
|
||||
|
||||
class Rule(object):
|
||||
def __init__(self, name, event, io, when):
|
||||
self.name = name
|
||||
self.event = event
|
||||
self.io = io
|
||||
self.when = when
|
||||
|
||||
def match(self, event, io):
|
||||
if event != self.event:
|
||||
return False
|
||||
if io != self.io and self.io != 'readwrite':
|
||||
return False
|
||||
return True
|
||||
|
||||
class FaultInjectionSocket(object):
|
||||
def __init__(self, sock, rules):
|
||||
self.sock = sock
|
||||
self.rules = rules
|
||||
|
||||
def check(self, event, io, bufsize=None):
|
||||
for rule in self.rules:
|
||||
if rule.match(event, io):
|
||||
if rule.when == 0 or bufsize is None:
|
||||
print 'Closing connection on rule match %s' % rule.name
|
||||
sys.exit(0)
|
||||
if rule.when != -1:
|
||||
return rule.when
|
||||
return bufsize
|
||||
|
||||
def send(self, buf, event):
|
||||
bufsize = self.check(event, 'write', bufsize=len(buf))
|
||||
self.sock.sendall(buf[:bufsize])
|
||||
self.check(event, 'write')
|
||||
|
||||
def recv(self, bufsize, event):
|
||||
bufsize = self.check(event, 'read', bufsize=bufsize)
|
||||
data = recvall(self.sock, bufsize)
|
||||
self.check(event, 'read')
|
||||
return data
|
||||
|
||||
def close(self):
|
||||
self.sock.close()
|
||||
|
||||
def negotiate_classic(conn):
|
||||
buf = neg_classic_struct.pack(NBD_PASSWD, NBD_CLIENT_MAGIC,
|
||||
FAKE_DISK_SIZE, 0)
|
||||
conn.send(buf, event='neg-classic')
|
||||
|
||||
def negotiate_export(conn):
|
||||
# Send negotiation part 1
|
||||
buf = neg1_struct.pack(NBD_PASSWD, NBD_OPTS_MAGIC, 0)
|
||||
conn.send(buf, event='neg1')
|
||||
|
||||
# Receive export option
|
||||
buf = conn.recv(export_struct.size, event='export')
|
||||
export = export_tuple._make(export_struct.unpack(buf))
|
||||
assert export.magic == NBD_OPTS_MAGIC
|
||||
assert export.opt == NBD_OPT_EXPORT_NAME
|
||||
name = conn.recv(export.len, event='export-name')
|
||||
|
||||
# Send negotiation part 2
|
||||
buf = neg2_struct.pack(FAKE_DISK_SIZE, 0)
|
||||
conn.send(buf, event='neg2')
|
||||
|
||||
def negotiate(conn, use_export):
|
||||
'''Negotiate export with client'''
|
||||
if use_export:
|
||||
negotiate_export(conn)
|
||||
else:
|
||||
negotiate_classic(conn)
|
||||
|
||||
def read_request(conn):
|
||||
'''Parse NBD request from client'''
|
||||
buf = conn.recv(request_struct.size, event='request')
|
||||
req = request_tuple._make(request_struct.unpack(buf))
|
||||
assert req.magic == NBD_REQUEST_MAGIC
|
||||
return req
|
||||
|
||||
def write_reply(conn, error, handle):
|
||||
buf = reply_struct.pack(NBD_REPLY_MAGIC, error, handle)
|
||||
conn.send(buf, event='reply')
|
||||
|
||||
def handle_connection(conn, use_export):
|
||||
negotiate(conn, use_export)
|
||||
while True:
|
||||
req = read_request(conn)
|
||||
if req.type == NBD_CMD_READ:
|
||||
write_reply(conn, 0, req.handle)
|
||||
conn.send('\0' * req.len, event='data')
|
||||
elif req.type == NBD_CMD_WRITE:
|
||||
_ = conn.recv(req.len, event='data')
|
||||
write_reply(conn, 0, req.handle)
|
||||
elif req.type == NBD_CMD_DISC:
|
||||
break
|
||||
else:
|
||||
print 'unrecognized command type %#02x' % req.type
|
||||
break
|
||||
conn.close()
|
||||
|
||||
def run_server(sock, rules, use_export):
|
||||
while True:
|
||||
conn, _ = sock.accept()
|
||||
handle_connection(FaultInjectionSocket(conn, rules), use_export)
|
||||
|
||||
def parse_inject_error(name, options):
|
||||
if 'event' not in options:
|
||||
err('missing \"event\" option in %s' % name)
|
||||
event = options['event']
|
||||
if event not in ('neg-classic', 'neg1', 'export', 'neg2', 'request', 'reply', 'data'):
|
||||
err('invalid \"event\" option value \"%s\" in %s' % (event, name))
|
||||
io = options.get('io', 'readwrite')
|
||||
if io not in ('read', 'write', 'readwrite'):
|
||||
err('invalid \"io\" option value \"%s\" in %s' % (io, name))
|
||||
when = options.get('when', 'before')
|
||||
try:
|
||||
when = int(when)
|
||||
except ValueError:
|
||||
if when == 'before':
|
||||
when = 0
|
||||
elif when == 'after':
|
||||
when = -1
|
||||
else:
|
||||
err('invalid \"when\" option value \"%s\" in %s' % (when, name))
|
||||
return Rule(name, event, io, when)
|
||||
|
||||
def parse_config(config):
|
||||
rules = []
|
||||
for name in config.sections():
|
||||
if name.startswith('inject-error'):
|
||||
options = dict(config.items(name))
|
||||
rules.append(parse_inject_error(name, options))
|
||||
else:
|
||||
err('invalid config section name: %s' % name)
|
||||
return rules
|
||||
|
||||
def load_rules(filename):
|
||||
config = ConfigParser.RawConfigParser()
|
||||
with open(filename, 'rt') as f:
|
||||
config.readfp(f, filename)
|
||||
return parse_config(config)
|
||||
|
||||
def open_socket(path):
|
||||
'''Open a TCP or UNIX domain listen socket'''
|
||||
if ':' in path:
|
||||
host, port = path.split(':', 1)
|
||||
sock = socket.socket()
|
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
sock.bind((host, int(port)))
|
||||
else:
|
||||
sock = socket.socket(socket.AF_UNIX)
|
||||
sock.bind(path)
|
||||
sock.listen(0)
|
||||
print 'Listening on %s' % path
|
||||
return sock
|
||||
|
||||
def usage(args):
|
||||
sys.stderr.write('usage: %s [--classic-negotiation] <tcp-port>|<unix-path> <config-file>\n' % args[0])
|
||||
sys.stderr.write('Run an fault injector NBD server with rules defined in a config file.\n')
|
||||
sys.exit(1)
|
||||
|
||||
def main(args):
|
||||
if len(args) != 3 and len(args) != 4:
|
||||
usage(args)
|
||||
use_export = True
|
||||
if args[1] == '--classic-negotiation':
|
||||
use_export = False
|
||||
elif len(args) == 4:
|
||||
usage(args)
|
||||
sock = open_socket(args[1 if use_export else 2])
|
||||
rules = load_rules(args[2 if use_export else 3])
|
||||
run_server(sock, rules, use_export)
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
@@ -1,12 +1,15 @@
|
||||
/* Test path override code */
|
||||
#define _GNU_SOURCE
|
||||
#include "config-host.h"
|
||||
#include "iov.c"
|
||||
#include "cutils.c"
|
||||
#include "path.c"
|
||||
#include "trace.c"
|
||||
#include "util/cutils.c"
|
||||
#include "util/hexdump.c"
|
||||
#include "util/iov.c"
|
||||
#include "util/path.c"
|
||||
#include "util/qemu-timer-common.c"
|
||||
#include "trace/control.c"
|
||||
#include "../trace/generated-events.c"
|
||||
#ifdef CONFIG_TRACE_SIMPLE
|
||||
#include "../trace/simple.c"
|
||||
#include "trace/simple.c"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
15
ui/gtk.c
15
ui/gtk.c
@@ -340,13 +340,17 @@ static void gd_mouse_set(DisplayChangeListener *dcl,
|
||||
GdkDeviceManager *mgr;
|
||||
gint x_root, y_root;
|
||||
|
||||
if (qemu_input_is_absolute()) {
|
||||
return;
|
||||
}
|
||||
|
||||
dpy = gtk_widget_get_display(s->drawing_area);
|
||||
mgr = gdk_display_get_device_manager(dpy);
|
||||
gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area),
|
||||
x, y, &x_root, &y_root);
|
||||
gdk_device_warp(gdk_device_manager_get_client_pointer(mgr),
|
||||
gtk_widget_get_screen(s->drawing_area),
|
||||
x, y);
|
||||
x_root, y_root);
|
||||
}
|
||||
#else
|
||||
static void gd_mouse_set(DisplayChangeListener *dcl,
|
||||
@@ -355,6 +359,10 @@ static void gd_mouse_set(DisplayChangeListener *dcl,
|
||||
GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
|
||||
gint x_root, y_root;
|
||||
|
||||
if (qemu_input_is_absolute()) {
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area),
|
||||
x, y, &x_root, &y_root);
|
||||
gdk_display_warp_pointer(gtk_widget_get_display(s->drawing_area),
|
||||
@@ -1438,7 +1446,7 @@ static const DisplayChangeListenerOps dcl_ops = {
|
||||
.dpy_cursor_define = gd_cursor_define,
|
||||
};
|
||||
|
||||
void gtk_display_init(DisplayState *ds, bool full_screen)
|
||||
void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
|
||||
{
|
||||
GtkDisplayState *s = g_malloc0(sizeof(*s));
|
||||
char *filename;
|
||||
@@ -1517,6 +1525,9 @@ void gtk_display_init(DisplayState *ds, bool full_screen)
|
||||
if (full_screen) {
|
||||
gtk_menu_item_activate(GTK_MENU_ITEM(s->full_screen_item));
|
||||
}
|
||||
if (grab_on_hover) {
|
||||
gtk_menu_item_activate(GTK_MENU_ITEM(s->grab_on_hover_item));
|
||||
}
|
||||
|
||||
register_displaychangelistener(&s->dcl);
|
||||
|
||||
|
24
vl.c
24
vl.c
@@ -143,6 +143,9 @@ int vga_interface_type = VGA_NONE;
|
||||
static int full_screen = 0;
|
||||
static int no_frame = 0;
|
||||
int no_quit = 0;
|
||||
#ifdef CONFIG_GTK
|
||||
static bool grab_on_hover;
|
||||
#endif
|
||||
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
|
||||
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
|
||||
CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
|
||||
@@ -2276,6 +2279,25 @@ static DisplayType select_display(const char *p)
|
||||
} else if (strstart(p, "gtk", &opts)) {
|
||||
#ifdef CONFIG_GTK
|
||||
display = DT_GTK;
|
||||
while (*opts) {
|
||||
const char *nextopt;
|
||||
|
||||
if (strstart(opts, ",grab_on_hover=", &nextopt)) {
|
||||
opts = nextopt;
|
||||
if (strstart(opts, "on", &nextopt)) {
|
||||
grab_on_hover = true;
|
||||
} else if (strstart(opts, "off", &nextopt)) {
|
||||
grab_on_hover = false;
|
||||
} else {
|
||||
goto invalid_gtk_args;
|
||||
}
|
||||
} else {
|
||||
invalid_gtk_args:
|
||||
fprintf(stderr, "Invalid GTK option string: %s\n", p);
|
||||
exit(1);
|
||||
}
|
||||
opts = nextopt;
|
||||
}
|
||||
#else
|
||||
fprintf(stderr, "GTK support is disabled\n");
|
||||
exit(1);
|
||||
@@ -4399,7 +4421,7 @@ int main(int argc, char **argv, char **envp)
|
||||
#endif
|
||||
#if defined(CONFIG_GTK)
|
||||
case DT_GTK:
|
||||
gtk_display_init(ds, full_screen);
|
||||
gtk_display_init(ds, full_screen, grab_on_hover);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
Reference in New Issue
Block a user