Compare commits
68 Commits
v2.0.0-rc0
...
pull-vnc-2
Author | SHA1 | Date | |
---|---|---|---|
|
2f487a3d40 | ||
|
315b593441 | ||
|
cdf0592cb8 | ||
|
4f3ed190a6 | ||
|
b074e62205 | ||
|
7b53f2940e | ||
|
0a1bec8a4e | ||
|
cab0a7ea00 | ||
|
7ea5d7256d | ||
|
a8b12c108c | ||
|
eef0d9e740 | ||
|
a9c7d27bd1 | ||
|
1d0a60681a | ||
|
5f9eb02555 | ||
|
c8fc56cedd | ||
|
aad2f06a7f | ||
|
d801a8f2ce | ||
|
e7bc9004e7 | ||
|
87f6396293 | ||
|
2bda66028b | ||
|
298526fe92 | ||
|
881249c792 | ||
|
087edb503a | ||
|
025172d56e | ||
|
83d1c8ae88 | ||
|
0c544d73bb | ||
|
6295b98d7b | ||
|
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*
|
libdis*
|
||||||
libuser
|
libuser
|
||||||
/linux-headers/asm
|
/linux-headers/asm
|
||||||
|
/qga/qapi-generated
|
||||||
/qapi-generated
|
/qapi-generated
|
||||||
/qapi-types.[ch]
|
/qapi-types.[ch]
|
||||||
/qapi-visit.[ch]
|
/qapi-visit.[ch]
|
||||||
|
53
.travis.yml
53
.travis.yml
@@ -4,6 +4,12 @@ python:
|
|||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
- clang
|
- clang
|
||||||
|
notifications:
|
||||||
|
irc:
|
||||||
|
channels:
|
||||||
|
- "irc.oftc.net#qemu"
|
||||||
|
on_success: change
|
||||||
|
on_failure: always
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- TEST_CMD="make check"
|
- 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"
|
- GUI_PKGS="libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev"
|
||||||
- EXTRA_PKGS=""
|
- EXTRA_PKGS=""
|
||||||
matrix:
|
matrix:
|
||||||
- TARGETS=alpha-softmmu,alpha-linux-user
|
- TARGETS=alpha-softmmu,alpha-linux-user
|
||||||
- TARGETS=arm-softmmu,arm-linux-user
|
- TARGETS=arm-softmmu,arm-linux-user
|
||||||
- TARGETS=aarch64-softmmu,aarch64-linux-user
|
- TARGETS=aarch64-softmmu,aarch64-linux-user
|
||||||
- TARGETS=cris-softmmu
|
- TARGETS=cris-softmmu
|
||||||
- TARGETS=i386-softmmu,x86_64-softmmu
|
- TARGETS=i386-softmmu,x86_64-softmmu
|
||||||
- TARGETS=lm32-softmmu
|
- TARGETS=lm32-softmmu
|
||||||
- TARGETS=m68k-softmmu
|
- TARGETS=m68k-softmmu
|
||||||
- TARGETS=microblaze-softmmu,microblazeel-softmmu
|
- TARGETS=microblaze-softmmu,microblazeel-softmmu
|
||||||
- TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu
|
- TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu
|
||||||
- TARGETS=moxie-softmmu
|
- TARGETS=moxie-softmmu
|
||||||
- TARGETS=or32-softmmu,
|
- TARGETS=or32-softmmu,
|
||||||
- TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu
|
- TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu
|
||||||
- TARGETS=s390x-softmmu
|
- TARGETS=s390x-softmmu
|
||||||
- TARGETS=sh4-softmmu,sh4eb-softmmu
|
- TARGETS=sh4-softmmu,sh4eb-softmmu
|
||||||
- TARGETS=sparc-softmmu,sparc64-softmmu
|
- TARGETS=sparc-softmmu,sparc64-softmmu
|
||||||
- TARGETS=unicore32-softmmu
|
- TARGETS=unicore32-softmmu
|
||||||
- TARGETS=xtensa-softmmu,xtensaeb-softmmu
|
- TARGETS=xtensa-softmmu,xtensaeb-softmmu
|
||||||
before_install:
|
before_install:
|
||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
@@ -46,6 +52,10 @@ matrix:
|
|||||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||||
EXTRA_CONFIG="--enable-debug --enable-tcg-interpreter"
|
EXTRA_CONFIG="--enable-debug --enable-tcg-interpreter"
|
||||||
compiler: gcc
|
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
|
# Currently configure doesn't force --disable-pie
|
||||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||||
EXTRA_CONFIG="--enable-gprof --enable-gcov --disable-pie"
|
EXTRA_CONFIG="--enable-gprof --enable-gcov --disable-pie"
|
||||||
@@ -65,8 +75,7 @@ matrix:
|
|||||||
EXTRA_CONFIG="--enable-trace-backend=ftrace"
|
EXTRA_CONFIG="--enable-trace-backend=ftrace"
|
||||||
TEST_CMD=""
|
TEST_CMD=""
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
# This disabled make check for the ftrace backend which needs more setting up
|
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||||
# Currently broken on 12.04 due to mis-packaged liburcu and changed API, will be pulled.
|
EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
|
||||||
#- env: TARGETS=i386-softmmu,x86_64-softmmu
|
EXTRA_CONFIG="--enable-trace-backend=ust"
|
||||||
# EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
|
compiler: gcc
|
||||||
# EXTRA_CONFIG="--enable-trace-backend=ust"
|
|
||||||
|
5
Makefile
5
Makefile
@@ -265,10 +265,7 @@ clean:
|
|||||||
# avoid old build problems by removing potentially incorrect old files
|
# 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 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
|
rm -f qemu-options.def
|
||||||
find . -name '*.[oda]' -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 {} +
|
||||||
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 {} +
|
|
||||||
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
|
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
|
||||||
rm -f fsdev/*.pod
|
rm -f fsdev/*.pod
|
||||||
rm -rf .libs */.libs
|
rm -rf .libs */.libs
|
||||||
|
9
block.c
9
block.c
@@ -1388,12 +1388,19 @@ done:
|
|||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto close_and_fail;
|
goto close_and_fail;
|
||||||
}
|
}
|
||||||
QDECREF(options);
|
|
||||||
|
|
||||||
if (!bdrv_key_required(bs)) {
|
if (!bdrv_key_required(bs)) {
|
||||||
bdrv_dev_change_media_cb(bs, true);
|
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;
|
*pbs = bs;
|
||||||
return 0;
|
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)
|
static void nbd_reply_ready(void *opaque)
|
||||||
{
|
{
|
||||||
NbdClientSession *s = opaque;
|
NbdClientSession *s = opaque;
|
||||||
@@ -78,7 +89,7 @@ static void nbd_reply_ready(void *opaque)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
nbd_recv_coroutines_enter_all(s);
|
nbd_teardown_connection(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nbd_restart_write(void *opaque)
|
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 = {
|
struct nbd_request request = {
|
||||||
.type = NBD_CMD_DISC,
|
.type = NBD_CMD_DISC,
|
||||||
@@ -332,22 +343,14 @@ static void nbd_teardown_connection(NbdClientSession *client)
|
|||||||
.len = 0
|
.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) {
|
if (!client->bs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (client->sock == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbd_send_request(client->sock, &request);
|
||||||
|
|
||||||
nbd_teardown_connection(client);
|
nbd_teardown_connection(client);
|
||||||
client->bs = NULL;
|
client->bs = NULL;
|
||||||
|
@@ -61,7 +61,7 @@
|
|||||||
/* These structures are ones that are defined in the VHDX specification
|
/* These structures are ones that are defined in the VHDX specification
|
||||||
* document */
|
* document */
|
||||||
|
|
||||||
#define VHDX_FILE_SIGNATURE 0x656C696678646876 /* "vhdxfile" in ASCII */
|
#define VHDX_FILE_SIGNATURE 0x656C696678646876ULL /* "vhdxfile" in ASCII */
|
||||||
typedef struct VHDXFileIdentifier {
|
typedef struct VHDXFileIdentifier {
|
||||||
uint64_t signature; /* "vhdxfile" in ASCII */
|
uint64_t signature; /* "vhdxfile" in ASCII */
|
||||||
uint16_t creator[256]; /* optional; utf-16 string to identify
|
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
|
/* upper 44 bits are the file offset in 1MB units lower 3 bits are the state
|
||||||
other bits are reserved */
|
other bits are reserved */
|
||||||
#define VHDX_BAT_STATE_BIT_MASK 0x07
|
#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;
|
typedef uint64_t VHDXBatEntry;
|
||||||
|
|
||||||
/* ---- METADATA REGION STRUCTURES ---- */
|
/* ---- METADATA REGION STRUCTURES ---- */
|
||||||
@@ -247,7 +247,7 @@ typedef uint64_t VHDXBatEntry;
|
|||||||
#define VHDX_METADATA_MAX_ENTRIES 2047 /* not including the header */
|
#define VHDX_METADATA_MAX_ENTRIES 2047 /* not including the header */
|
||||||
#define VHDX_METADATA_TABLE_MAX_SIZE \
|
#define VHDX_METADATA_TABLE_MAX_SIZE \
|
||||||
(VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1))
|
(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 {
|
typedef struct QEMU_PACKED VHDXMetadataTableHeader {
|
||||||
uint64_t signature; /* "metadata" in ASCII */
|
uint64_t signature; /* "metadata" in ASCII */
|
||||||
uint16_t reserved;
|
uint16_t reserved;
|
||||||
|
5
configure
vendored
5
configure
vendored
@@ -3822,6 +3822,11 @@ fi
|
|||||||
|
|
||||||
int128=no
|
int128=no
|
||||||
cat > $TMPC << EOF
|
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;
|
__int128_t a;
|
||||||
__uint128_t b;
|
__uint128_t b;
|
||||||
int main (void) {
|
int main (void) {
|
||||||
|
@@ -223,13 +223,13 @@ static void *cur_chip = NULL; /* current chip point */
|
|||||||
/* static OPLSAMPLE *bufL,*bufR; */
|
/* static OPLSAMPLE *bufL,*bufR; */
|
||||||
static OPL_CH *S_CH;
|
static OPL_CH *S_CH;
|
||||||
static OPL_CH *E_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 outd[1];
|
||||||
static INT32 ams;
|
static INT32 ams;
|
||||||
static INT32 vib;
|
static INT32 vib;
|
||||||
INT32 *ams_table;
|
static INT32 *ams_table;
|
||||||
INT32 *vib_table;
|
static INT32 *vib_table;
|
||||||
static INT32 amsIncr;
|
static INT32 amsIncr;
|
||||||
static INT32 vibIncr;
|
static INT32 vibIncr;
|
||||||
static INT32 feedback2; /* connect for SLOT 2 */
|
static INT32 feedback2; /* connect for SLOT 2 */
|
||||||
|
@@ -41,7 +41,6 @@ typedef struct SCLPConsoleLM {
|
|||||||
uint32_t write_errors; /* errors writing to char layer */
|
uint32_t write_errors; /* errors writing to char layer */
|
||||||
uint32_t length; /* length of byte stream in buffer */
|
uint32_t length; /* length of byte stream in buffer */
|
||||||
uint8_t buf[SIZE_CONSOLE_BUFFER];
|
uint8_t buf[SIZE_CONSOLE_BUFFER];
|
||||||
qemu_irq irq_console_read;
|
|
||||||
} SCLPConsoleLM;
|
} SCLPConsoleLM;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -68,13 +67,15 @@ static int chr_can_read(void *opaque)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void receive_from_chr_layer(SCLPConsoleLM *scon, const uint8_t *buf,
|
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
||||||
int size)
|
|
||||||
{
|
{
|
||||||
|
SCLPConsoleLM *scon = opaque;
|
||||||
|
|
||||||
assert(size == 1);
|
assert(size == 1);
|
||||||
|
|
||||||
if (*buf == '\r' || *buf == '\n') {
|
if (*buf == '\r' || *buf == '\n') {
|
||||||
scon->event.event_pending = true;
|
scon->event.event_pending = true;
|
||||||
|
sclp_service_interrupt(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scon->buf[scon->length] = *buf;
|
scon->buf[scon->length] = *buf;
|
||||||
@@ -84,20 +85,6 @@ static void receive_from_chr_layer(SCLPConsoleLM *scon, const uint8_t *buf,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Send data from a char device over to the guest
|
|
||||||
*/
|
|
||||||
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
|
||||||
{
|
|
||||||
SCLPConsoleLM *scon = opaque;
|
|
||||||
|
|
||||||
receive_from_chr_layer(scon, buf, size);
|
|
||||||
if (scon->event.event_pending) {
|
|
||||||
/* trigger SCLP read operation */
|
|
||||||
qemu_irq_raise(scon->irq_console_read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* functions to be called by event facility */
|
/* functions to be called by event facility */
|
||||||
|
|
||||||
static bool can_handle_event(uint8_t type)
|
static bool can_handle_event(uint8_t type)
|
||||||
@@ -298,11 +285,6 @@ static int write_event_data(SCLPEvent *event, EventBufferHeader *ebh)
|
|||||||
return SCLP_RC_NORMAL_COMPLETION;
|
return SCLP_RC_NORMAL_COMPLETION;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trigger_console_data(void *opaque, int n, int level)
|
|
||||||
{
|
|
||||||
sclp_service_interrupt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* functions for live migration */
|
/* functions for live migration */
|
||||||
|
|
||||||
static const VMStateDescription vmstate_sclplmconsole = {
|
static const VMStateDescription vmstate_sclplmconsole = {
|
||||||
@@ -338,7 +320,6 @@ static int console_init(SCLPEvent *event)
|
|||||||
if (scon->chr) {
|
if (scon->chr) {
|
||||||
qemu_chr_add_handlers(scon->chr, chr_can_read, chr_read, NULL, scon);
|
qemu_chr_add_handlers(scon->chr, chr_can_read, chr_read, NULL, scon);
|
||||||
}
|
}
|
||||||
scon->irq_console_read = *qemu_allocate_irqs(trigger_console_data, NULL, 1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -36,7 +36,6 @@ typedef struct SCLPConsole {
|
|||||||
uint32_t iov_bs; /* offset in buf for char layer read operation */
|
uint32_t iov_bs; /* offset in buf for char layer read operation */
|
||||||
uint32_t iov_data_len; /* length of byte stream in buffer */
|
uint32_t iov_data_len; /* length of byte stream in buffer */
|
||||||
uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */
|
uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */
|
||||||
qemu_irq irq_read_vt220;
|
|
||||||
} SCLPConsole;
|
} SCLPConsole;
|
||||||
|
|
||||||
/* character layer call-back functions */
|
/* character layer call-back functions */
|
||||||
@@ -49,11 +48,12 @@ static int chr_can_read(void *opaque)
|
|||||||
return SIZE_BUFFER_VT220 - scon->iov_data_len;
|
return SIZE_BUFFER_VT220 - scon->iov_data_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive n bytes from character layer, save in iov buffer,
|
/* Send data from a char device over to the guest */
|
||||||
* and set event pending */
|
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
||||||
static void receive_from_chr_layer(SCLPConsole *scon, const uint8_t *buf,
|
|
||||||
int size)
|
|
||||||
{
|
{
|
||||||
|
SCLPConsole *scon = opaque;
|
||||||
|
|
||||||
|
assert(scon);
|
||||||
/* read data must fit into current buffer */
|
/* read data must fit into current buffer */
|
||||||
assert(size <= SIZE_BUFFER_VT220 - scon->iov_data_len);
|
assert(size <= SIZE_BUFFER_VT220 - scon->iov_data_len);
|
||||||
|
|
||||||
@@ -63,18 +63,7 @@ static void receive_from_chr_layer(SCLPConsole *scon, const uint8_t *buf,
|
|||||||
scon->iov_sclp_rest += size;
|
scon->iov_sclp_rest += size;
|
||||||
scon->iov_bs += size;
|
scon->iov_bs += size;
|
||||||
scon->event.event_pending = true;
|
scon->event.event_pending = true;
|
||||||
}
|
sclp_service_interrupt(0);
|
||||||
|
|
||||||
/* Send data from a char device over to the guest */
|
|
||||||
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
|
||||||
{
|
|
||||||
SCLPConsole *scon = opaque;
|
|
||||||
|
|
||||||
assert(scon);
|
|
||||||
|
|
||||||
receive_from_chr_layer(scon, buf, size);
|
|
||||||
/* trigger SCLP read operation */
|
|
||||||
qemu_irq_raise(scon->irq_read_vt220);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* functions to be called by event facility */
|
/* functions to be called by event facility */
|
||||||
@@ -192,11 +181,6 @@ static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trigger_ascii_console_data(void *opaque, int n, int level)
|
|
||||||
{
|
|
||||||
sclp_service_interrupt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const VMStateDescription vmstate_sclpconsole = {
|
static const VMStateDescription vmstate_sclpconsole = {
|
||||||
.name = "sclpconsole",
|
.name = "sclpconsole",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
@@ -232,8 +216,6 @@ static int console_init(SCLPEvent *event)
|
|||||||
qemu_chr_add_handlers(scon->chr, chr_can_read,
|
qemu_chr_add_handlers(scon->chr, chr_can_read,
|
||||||
chr_read, NULL, scon);
|
chr_read, NULL, scon);
|
||||||
}
|
}
|
||||||
scon->irq_read_vt220 = *qemu_allocate_irqs(trigger_ascii_console_data,
|
|
||||||
NULL, 1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "ui/console.h"
|
#include "ui/console.h"
|
||||||
|
#include "ui/vnc.h"
|
||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
|
|
||||||
#undef VERBOSE
|
#undef VERBOSE
|
||||||
@@ -218,7 +219,7 @@ enum {
|
|||||||
|
|
||||||
/* These values can probably be changed arbitrarily. */
|
/* These values can probably be changed arbitrarily. */
|
||||||
#define SVGA_SCRATCH_SIZE 0x8000
|
#define SVGA_SCRATCH_SIZE 0x8000
|
||||||
#define SVGA_MAX_WIDTH 2360
|
#define SVGA_MAX_WIDTH ROUND_UP(2360, VNC_DIRTY_PIXELS_PER_BIT)
|
||||||
#define SVGA_MAX_HEIGHT 1770
|
#define SVGA_MAX_HEIGHT 1770
|
||||||
|
|
||||||
#ifdef VERBOSE
|
#ifdef VERBOSE
|
||||||
|
@@ -148,7 +148,7 @@ typedef void (*vgic_translate_fn)(GICState *s, int irq, int cpu,
|
|||||||
uint32_t *field, bool to_kernel);
|
uint32_t *field, bool to_kernel);
|
||||||
|
|
||||||
/* synthetic translate function used for clear/set registers to completely
|
/* 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 */
|
* using a set-register */
|
||||||
static void translate_clear(GICState *s, int irq, int cpu,
|
static void translate_clear(GICState *s, int irq, int cpu,
|
||||||
uint32_t *field, bool to_kernel)
|
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 packet is IP4 and IP checksum is requested */
|
||||||
if (flags & FCB_TX_IP && flags & FCB_TX_CIP) {
|
if (flags & FCB_TX_IP && flags & FCB_TX_CIP) {
|
||||||
/* do IP4 checksum (TODO This funtion does TCP/UDP checksum but not sure
|
/* do IP4 checksum (TODO This function does TCP/UDP checksum
|
||||||
* if it also does IP4 checksum. */
|
* but not sure if it also does IP4 checksum.) */
|
||||||
net_checksum_calculate(etsec->tx_buffer + 8,
|
net_checksum_calculate(etsec->tx_buffer + 8,
|
||||||
etsec->tx_buffer_len - 8);
|
etsec->tx_buffer_len - 8);
|
||||||
}
|
}
|
||||||
@@ -592,7 +592,7 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
|
|||||||
|
|
||||||
/* TODO: Broadcast and Multicast */
|
/* TODO: Broadcast and Multicast */
|
||||||
|
|
||||||
if (bd.flags | BD_INTERRUPT) {
|
if (bd.flags & BD_INTERRUPT) {
|
||||||
/* Set RXFx */
|
/* Set RXFx */
|
||||||
etsec->regs[RSTAT].value |= 1 << (7 - ring_nbr);
|
etsec->regs[RSTAT].value |= 1 << (7 - ring_nbr);
|
||||||
|
|
||||||
@@ -601,7 +601,7 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (bd.flags | BD_INTERRUPT) {
|
if (bd.flags & BD_INTERRUPT) {
|
||||||
/* Set IEVENT */
|
/* Set IEVENT */
|
||||||
ievent_set(etsec, IEVENT_RXB);
|
ievent_set(etsec, IEVENT_RXB);
|
||||||
}
|
}
|
||||||
|
@@ -80,7 +80,7 @@ static int s390_ipl_init(SysBusDevice *dev)
|
|||||||
|
|
||||||
bios_size = load_elf(bios_filename, NULL, NULL, &ipl->start_addr, NULL,
|
bios_size = load_elf(bios_filename, NULL, NULL, &ipl->start_addr, NULL,
|
||||||
NULL, 1, ELF_MACHINE, 0);
|
NULL, 1, ELF_MACHINE, 0);
|
||||||
if (bios_size == -1) {
|
if (bios_size < 0) {
|
||||||
bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START,
|
bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START,
|
||||||
4096);
|
4096);
|
||||||
ipl->start_addr = ZIPL_IMAGE_START;
|
ipl->start_addr = ZIPL_IMAGE_START;
|
||||||
|
@@ -25,13 +25,13 @@ typedef struct ConfigMgtData {
|
|||||||
uint8_t event_qualifier;
|
uint8_t event_qualifier;
|
||||||
} QEMU_PACKED ConfigMgtData;
|
} QEMU_PACKED ConfigMgtData;
|
||||||
|
|
||||||
static qemu_irq irq_cpu_hotplug; /* Only used in this file */
|
static qemu_irq *irq_cpu_hotplug; /* Only used in this file */
|
||||||
|
|
||||||
#define EVENT_QUAL_CPU_CHANGE 1
|
#define EVENT_QUAL_CPU_CHANGE 1
|
||||||
|
|
||||||
void raise_irq_cpu_hotplug(void)
|
void raise_irq_cpu_hotplug(void)
|
||||||
{
|
{
|
||||||
qemu_irq_raise(irq_cpu_hotplug);
|
qemu_irq_raise(*irq_cpu_hotplug);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int send_mask(void)
|
static unsigned int send_mask(void)
|
||||||
@@ -81,7 +81,7 @@ static void trigger_signal(void *opaque, int n, int level)
|
|||||||
|
|
||||||
static int irq_cpu_hotplug_init(SCLPEvent *event)
|
static int irq_cpu_hotplug_init(SCLPEvent *event)
|
||||||
{
|
{
|
||||||
irq_cpu_hotplug = *qemu_allocate_irqs(trigger_signal, event, 1);
|
irq_cpu_hotplug = qemu_allocate_irqs(trigger_signal, event, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1905,6 +1905,26 @@ static const VMStateInfo vmstate_info_scsi_requests = {
|
|||||||
.put = put_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 = {
|
const VMStateDescription vmstate_scsi_device = {
|
||||||
.name = "SCSIDevice",
|
.name = "SCSIDevice",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
@@ -1915,7 +1935,7 @@ const VMStateDescription vmstate_scsi_device = {
|
|||||||
VMSTATE_UINT8(unit_attention.asc, SCSIDevice),
|
VMSTATE_UINT8(unit_attention.asc, SCSIDevice),
|
||||||
VMSTATE_UINT8(unit_attention.ascq, SCSIDevice),
|
VMSTATE_UINT8(unit_attention.ascq, SCSIDevice),
|
||||||
VMSTATE_BOOL(sense_is_ua, 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),
|
VMSTATE_UINT32(sense_len, SCSIDevice),
|
||||||
{
|
{
|
||||||
.name = "requests",
|
.name = "requests",
|
||||||
@@ -1927,6 +1947,14 @@ const VMStateDescription vmstate_scsi_device = {
|
|||||||
.offset = 0,
|
.offset = 0,
|
||||||
},
|
},
|
||||||
VMSTATE_END_OF_LIST()
|
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 */
|
req->crq.s.IU_data_ptr = req->iu.srp.rsp.tag; /* right byte order */
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
req->crq.s.status = 0x99; /* Just needs to be non-zero */
|
req->crq.s.status = VIOSRP_OK;
|
||||||
} else {
|
} else {
|
||||||
req->crq.s.status = 0x00;
|
req->crq.s.status = VIOSRP_ADAPTER_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc1 = spapr_vio_send_crq(&s->vdev, req->crq.raw);
|
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)
|
size_t resid)
|
||||||
{
|
{
|
||||||
VirtIOSCSIReq *req = r->hba_private;
|
VirtIOSCSIReq *req = r->hba_private;
|
||||||
|
VirtIOSCSI *s = req->dev;
|
||||||
|
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
|
||||||
uint32_t sense_len;
|
uint32_t sense_len;
|
||||||
|
|
||||||
if (r->io_canceled) {
|
if (r->io_canceled) {
|
||||||
@@ -317,7 +319,7 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
|
|||||||
} else {
|
} else {
|
||||||
req->resp.cmd->resid = 0;
|
req->resp.cmd->resid = 0;
|
||||||
sense_len = scsi_req_get_sense(r, req->resp.cmd->sense,
|
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);
|
req->resp.cmd->sense_len = tswap32(sense_len);
|
||||||
}
|
}
|
||||||
virtio_scsi_complete_req(req);
|
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
|
/* ptimer is triggered when the counter reach 0 but GPTimer is triggered at
|
||||||
underflow. Set count + 1 to simulate the GPTimer behavior. */
|
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);
|
ptimer_run(timer->ptimer, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -31,6 +31,7 @@ typedef struct SCSISense {
|
|||||||
uint8_t ascq;
|
uint8_t ascq;
|
||||||
} SCSISense;
|
} SCSISense;
|
||||||
|
|
||||||
|
#define SCSI_SENSE_BUF_SIZE_OLD 96
|
||||||
#define SCSI_SENSE_BUF_SIZE 252
|
#define SCSI_SENSE_BUF_SIZE 252
|
||||||
|
|
||||||
struct SCSICommand {
|
struct SCSICommand {
|
||||||
|
@@ -650,6 +650,9 @@ extern const VMStateInfo vmstate_info_bitmap;
|
|||||||
#define VMSTATE_UINT8_ARRAY(_f, _s, _n) \
|
#define VMSTATE_UINT8_ARRAY(_f, _s, _n) \
|
||||||
VMSTATE_UINT8_ARRAY_V(_f, _s, _n, 0)
|
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) \
|
#define VMSTATE_UINT8_2DARRAY(_f, _s, _n1, _n2) \
|
||||||
VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, 0)
|
VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, 0)
|
||||||
|
|
||||||
|
@@ -345,6 +345,6 @@ int index_from_key(const char *key);
|
|||||||
|
|
||||||
/* gtk.c */
|
/* gtk.c */
|
||||||
void early_gtk_display_init(void);
|
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
|
#endif
|
||||||
|
17
qemu-nbd.c
17
qemu-nbd.c
@@ -288,19 +288,19 @@ static void *nbd_client_thread(void *arg)
|
|||||||
ret = nbd_receive_negotiate(sock, NULL, &nbdflags,
|
ret = nbd_receive_negotiate(sock, NULL, &nbdflags,
|
||||||
&size, &blocksize);
|
&size, &blocksize);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open(device, O_RDWR);
|
fd = open(device, O_RDWR);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
/* Linux-only, we can use %m in printf. */
|
/* Linux-only, we can use %m in printf. */
|
||||||
fprintf(stderr, "Failed to open %s: %m", device);
|
fprintf(stderr, "Failed to open %s: %m", device);
|
||||||
goto out;
|
goto out_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nbd_init(fd, sock, nbdflags, size, blocksize);
|
ret = nbd_init(fd, sock, nbdflags, size, blocksize);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update partition table */
|
/* update partition table */
|
||||||
@@ -316,12 +316,16 @@ static void *nbd_client_thread(void *arg)
|
|||||||
|
|
||||||
ret = nbd_client(fd);
|
ret = nbd_client(fd);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto out;
|
goto out_fd;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
kill(getpid(), SIGTERM);
|
kill(getpid(), SIGTERM);
|
||||||
return (void *) EXIT_SUCCESS;
|
return (void *) EXIT_SUCCESS;
|
||||||
|
|
||||||
|
out_fd:
|
||||||
|
close(fd);
|
||||||
|
out_socket:
|
||||||
|
closesocket(sock);
|
||||||
out:
|
out:
|
||||||
kill(getpid(), SIGTERM);
|
kill(getpid(), SIGTERM);
|
||||||
return (void *) EXIT_FAILURE;
|
return (void *) EXIT_FAILURE;
|
||||||
@@ -355,6 +359,11 @@ static void nbd_accept(void *opaque)
|
|||||||
socklen_t addr_len = sizeof(addr);
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
|
||||||
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
|
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror("accept");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (state >= TERMINATE) {
|
if (state >= TERMINATE) {
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
|
@@ -810,6 +810,7 @@ ETEXI
|
|||||||
DEF("display", HAS_ARG, QEMU_OPTION_display,
|
DEF("display", HAS_ARG, QEMU_OPTION_display,
|
||||||
"-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
|
"-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
|
||||||
" [,window_close=on|off]|curses|none|\n"
|
" [,window_close=on|off]|curses|none|\n"
|
||||||
|
" gtk[,grab_on_hover=on|off]|\n"
|
||||||
" vnc=<display>[,<optargs>]\n"
|
" vnc=<display>[,<optargs>]\n"
|
||||||
" select display type\n", QEMU_ARCH_ALL)
|
" select display type\n", QEMU_ARCH_ALL)
|
||||||
STEXI
|
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
|
user. This option differs from the -nographic option in that it
|
||||||
only affects what is done with video output; -nographic also changes
|
only affects what is done with video output; -nographic also changes
|
||||||
the destination of the serial and parallel port data.
|
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
|
@item vnc
|
||||||
Start a VNC server on display <arg>
|
Start a VNC server on display <arg>
|
||||||
@end table
|
@end table
|
||||||
|
@@ -22,7 +22,9 @@ mech_list: digest-md5
|
|||||||
# Some older builds of MIT kerberos on Linux ignore this option &
|
# Some older builds of MIT kerberos on Linux ignore this option &
|
||||||
# instead need KRB5_KTNAME env var.
|
# instead need KRB5_KTNAME env var.
|
||||||
# For modern Linux, and other OS, this should be sufficient
|
# 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
|
# If using digest-md5 for username/passwds, then this is the file
|
||||||
# containing the passwds. Use 'saslpasswd2 -a qemu [username]'
|
# containing the passwds. Use 'saslpasswd2 -a qemu [username]'
|
||||||
|
@@ -23,8 +23,8 @@ QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d
|
|||||||
QEMU_INCLUDES += -I$(<D) -I$(@D)
|
QEMU_INCLUDES += -I$(<D) -I$(@D)
|
||||||
|
|
||||||
maybe-add = $(filter-out $1, $2) $1
|
maybe-add = $(filter-out $1, $2) $1
|
||||||
extract-libs = $(strip $(sort $(foreach o,$1,$($o-libs)) \
|
extract-libs = $(strip $(sort $(foreach o,$1,$($o-libs))) \
|
||||||
$(foreach o,$(call expand-objs,$1),$($o-libs))))
|
$(foreach o,$(call expand-objs,$1),$($o-libs)))
|
||||||
expand-objs = $(strip $(sort $(filter %.o,$1)) \
|
expand-objs = $(strip $(sort $(filter %.o,$1)) \
|
||||||
$(foreach o,$(filter %.mo,$1),$($o-objs)) \
|
$(foreach o,$(filter %.mo,$1),$($o-objs)) \
|
||||||
$(filter-out %.o %.mo,$1))
|
$(filter-out %.o %.mo,$1))
|
||||||
|
@@ -18,7 +18,7 @@ git clone "${src}" ${destination}
|
|||||||
pushd ${destination}
|
pushd ${destination}
|
||||||
git checkout "v${version}"
|
git checkout "v${version}"
|
||||||
git submodule update --init
|
git submodule update --init
|
||||||
rm -rf .git roms/*/.git
|
rm -rf .git roms/*/.git dtc/.git pixman/.git
|
||||||
popd
|
popd
|
||||||
tar cfj ${destination}.tar.bz2 ${destination}
|
tar cfj ${destination}.tar.bz2 ${destination}
|
||||||
rm -rf ${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 += pci-drive-hot-add.o
|
||||||
stub-obj-y += qtest.o
|
stub-obj-y += qtest.o
|
||||||
stub-obj-y += reset.o
|
stub-obj-y += reset.o
|
||||||
|
stub-obj-y += runstate-check.o
|
||||||
stub-obj-y += set-fd-handler.o
|
stub-obj-y += set-fd-handler.o
|
||||||
stub-obj-y += slirp.o
|
stub-obj-y += slirp.o
|
||||||
stub-obj-y += sysbus.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;
|
||||||
|
}
|
@@ -1927,6 +1927,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
|
|||||||
else {
|
else {
|
||||||
tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
|
tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
|
||||||
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
|
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1991,7 +1992,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
|
|||||||
} else {
|
} else {
|
||||||
if (islit)
|
if (islit)
|
||||||
tcg_gen_movi_i64(cpu_ir[rc], -lit);
|
tcg_gen_movi_i64(cpu_ir[rc], -lit);
|
||||||
else
|
else {
|
||||||
tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
|
tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
|
||||||
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
|
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
|
||||||
}
|
}
|
||||||
|
@@ -488,7 +488,7 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
|
|||||||
|
|
||||||
static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri)
|
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.
|
* by PMUSERENR.
|
||||||
*/
|
*/
|
||||||
if (arm_current_pl(env) == 0 && !env->cp15.c9_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_a = bcd_get_digit(a, i, &invalid);
|
||||||
uint8_t dig_b = bcd_get_digit(b, i, &invalid);
|
uint8_t dig_b = bcd_get_digit(b, i, &invalid);
|
||||||
if (unlikely(invalid)) {
|
if (unlikely(invalid)) {
|
||||||
return 0; /* doesnt matter */
|
return 0; /* doesn't matter */
|
||||||
} else if (dig_a > dig_b) {
|
} else if (dig_a > dig_b) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (dig_a < dig_b) {
|
} 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
|
#define TCG_TARGET_CALL_STACK_OFFSET 0
|
||||||
|
|
||||||
/* optional instructions */
|
/* optional instructions */
|
||||||
#define TCG_TARGET_HAS_div_i32 0
|
#define TCG_TARGET_HAS_div_i32 1
|
||||||
#define TCG_TARGET_HAS_rem_i32 0
|
#define TCG_TARGET_HAS_rem_i32 1
|
||||||
#define TCG_TARGET_HAS_ext8s_i32 1
|
#define TCG_TARGET_HAS_ext8s_i32 1
|
||||||
#define TCG_TARGET_HAS_ext16s_i32 1
|
#define TCG_TARGET_HAS_ext16s_i32 1
|
||||||
#define TCG_TARGET_HAS_ext8u_i32 1
|
#define TCG_TARGET_HAS_ext8u_i32 1
|
||||||
#define TCG_TARGET_HAS_ext16u_i32 1
|
#define TCG_TARGET_HAS_ext16u_i32 1
|
||||||
#define TCG_TARGET_HAS_bswap16_i32 1
|
#define TCG_TARGET_HAS_bswap16_i32 1
|
||||||
#define TCG_TARGET_HAS_bswap32_i32 1
|
#define TCG_TARGET_HAS_bswap32_i32 1
|
||||||
#define TCG_TARGET_HAS_not_i32 0
|
#define TCG_TARGET_HAS_not_i32 1
|
||||||
#define TCG_TARGET_HAS_neg_i32 0
|
#define TCG_TARGET_HAS_neg_i32 1
|
||||||
#define TCG_TARGET_HAS_rot_i32 1
|
#define TCG_TARGET_HAS_rot_i32 1
|
||||||
#define TCG_TARGET_HAS_andc_i32 0
|
#define TCG_TARGET_HAS_andc_i32 1
|
||||||
#define TCG_TARGET_HAS_orc_i32 0
|
#define TCG_TARGET_HAS_orc_i32 1
|
||||||
#define TCG_TARGET_HAS_eqv_i32 0
|
#define TCG_TARGET_HAS_eqv_i32 1
|
||||||
#define TCG_TARGET_HAS_nand_i32 0
|
#define TCG_TARGET_HAS_nand_i32 0
|
||||||
#define TCG_TARGET_HAS_nor_i32 0
|
#define TCG_TARGET_HAS_nor_i32 0
|
||||||
#define TCG_TARGET_HAS_deposit_i32 0
|
#define TCG_TARGET_HAS_deposit_i32 1
|
||||||
#define TCG_TARGET_HAS_movcond_i32 0
|
#define TCG_TARGET_HAS_movcond_i32 1
|
||||||
#define TCG_TARGET_HAS_add2_i32 0
|
#define TCG_TARGET_HAS_add2_i32 1
|
||||||
#define TCG_TARGET_HAS_sub2_i32 0
|
#define TCG_TARGET_HAS_sub2_i32 1
|
||||||
#define TCG_TARGET_HAS_mulu2_i32 0
|
#define TCG_TARGET_HAS_mulu2_i32 0
|
||||||
#define TCG_TARGET_HAS_muls2_i32 0
|
#define TCG_TARGET_HAS_muls2_i32 0
|
||||||
#define TCG_TARGET_HAS_muluh_i32 0
|
#define TCG_TARGET_HAS_muluh_i32 0
|
||||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||||
|
|
||||||
#define TCG_TARGET_HAS_div_i64 0
|
#define TCG_TARGET_HAS_div_i64 1
|
||||||
#define TCG_TARGET_HAS_rem_i64 0
|
#define TCG_TARGET_HAS_rem_i64 1
|
||||||
#define TCG_TARGET_HAS_ext8s_i64 1
|
#define TCG_TARGET_HAS_ext8s_i64 1
|
||||||
#define TCG_TARGET_HAS_ext16s_i64 1
|
#define TCG_TARGET_HAS_ext16s_i64 1
|
||||||
#define TCG_TARGET_HAS_ext32s_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_bswap16_i64 1
|
||||||
#define TCG_TARGET_HAS_bswap32_i64 1
|
#define TCG_TARGET_HAS_bswap32_i64 1
|
||||||
#define TCG_TARGET_HAS_bswap64_i64 1
|
#define TCG_TARGET_HAS_bswap64_i64 1
|
||||||
#define TCG_TARGET_HAS_not_i64 0
|
#define TCG_TARGET_HAS_not_i64 1
|
||||||
#define TCG_TARGET_HAS_neg_i64 0
|
#define TCG_TARGET_HAS_neg_i64 1
|
||||||
#define TCG_TARGET_HAS_rot_i64 1
|
#define TCG_TARGET_HAS_rot_i64 1
|
||||||
#define TCG_TARGET_HAS_andc_i64 0
|
#define TCG_TARGET_HAS_andc_i64 1
|
||||||
#define TCG_TARGET_HAS_orc_i64 0
|
#define TCG_TARGET_HAS_orc_i64 1
|
||||||
#define TCG_TARGET_HAS_eqv_i64 0
|
#define TCG_TARGET_HAS_eqv_i64 1
|
||||||
#define TCG_TARGET_HAS_nand_i64 0
|
#define TCG_TARGET_HAS_nand_i64 0
|
||||||
#define TCG_TARGET_HAS_nor_i64 0
|
#define TCG_TARGET_HAS_nor_i64 0
|
||||||
#define TCG_TARGET_HAS_deposit_i64 0
|
#define TCG_TARGET_HAS_deposit_i64 1
|
||||||
#define TCG_TARGET_HAS_movcond_i64 0
|
#define TCG_TARGET_HAS_movcond_i64 1
|
||||||
#define TCG_TARGET_HAS_add2_i64 0
|
#define TCG_TARGET_HAS_add2_i64 1
|
||||||
#define TCG_TARGET_HAS_sub2_i64 0
|
#define TCG_TARGET_HAS_sub2_i64 1
|
||||||
#define TCG_TARGET_HAS_mulu2_i64 0
|
#define TCG_TARGET_HAS_mulu2_i64 0
|
||||||
#define TCG_TARGET_HAS_muls2_i64 0
|
#define TCG_TARGET_HAS_muls2_i64 0
|
||||||
#define TCG_TARGET_HAS_muluh_i64 0
|
#define TCG_TARGET_HAS_muluh_i64 1
|
||||||
#define TCG_TARGET_HAS_mulsh_i64 0
|
#define TCG_TARGET_HAS_mulsh_i64 1
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TCG_AREG0 = TCG_REG_X19,
|
TCG_AREG0 = TCG_REG_X19,
|
||||||
|
@@ -384,37 +384,47 @@ static inline void tcg_out_movi_imm13(TCGContext *s, int ret, uint32_t arg)
|
|||||||
tcg_out_arithi(s, ret, TCG_REG_G0, arg, ARITH_OR);
|
tcg_out_arithi(s, ret, TCG_REG_G0, arg, ARITH_OR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_movi_imm32(TCGContext *s, int ret, uint32_t arg)
|
static void tcg_out_movi(TCGContext *s, TCGType type,
|
||||||
|
TCGReg ret, tcg_target_long arg)
|
||||||
{
|
{
|
||||||
if (check_fit_tl(arg, 13))
|
tcg_target_long hi, lo;
|
||||||
tcg_out_movi_imm13(s, ret, arg);
|
|
||||||
else {
|
|
||||||
tcg_out_sethi(s, ret, arg);
|
|
||||||
if (arg & 0x3ff)
|
|
||||||
tcg_out_arithi(s, ret, ret, arg & 0x3ff, ARITH_OR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void tcg_out_movi(TCGContext *s, TCGType type,
|
/* A 13-bit constant sign-extended to 64-bits. */
|
||||||
TCGReg ret, tcg_target_long arg)
|
if (check_fit_tl(arg, 13)) {
|
||||||
{
|
tcg_out_movi_imm13(s, ret, arg);
|
||||||
/* All 32-bit constants, as well as 64-bit constants with
|
return;
|
||||||
no high bits set go through movi_imm32. */
|
}
|
||||||
|
|
||||||
|
/* A 32-bit constant, or 32-bit zero-extended to 64-bits. */
|
||||||
if (TCG_TARGET_REG_BITS == 32
|
if (TCG_TARGET_REG_BITS == 32
|
||||||
|| type == TCG_TYPE_I32
|
|| type == TCG_TYPE_I32
|
||||||
|| (arg & ~(tcg_target_long)0xffffffff) == 0) {
|
|| (arg & ~0xffffffffu) == 0) {
|
||||||
tcg_out_movi_imm32(s, ret, arg);
|
tcg_out_sethi(s, ret, arg);
|
||||||
} else if (check_fit_tl(arg, 13)) {
|
if (arg & 0x3ff) {
|
||||||
/* A 13-bit constant sign-extended to 64-bits. */
|
tcg_out_arithi(s, ret, ret, arg & 0x3ff, ARITH_OR);
|
||||||
tcg_out_movi_imm13(s, ret, arg);
|
}
|
||||||
} else if (check_fit_tl(arg, 32)) {
|
return;
|
||||||
/* A 32-bit constant sign-extended to 64-bits. */
|
}
|
||||||
|
|
||||||
|
/* A 32-bit constant sign-extended to 64-bits. */
|
||||||
|
if (check_fit_tl(arg, 32)) {
|
||||||
tcg_out_sethi(s, ret, ~arg);
|
tcg_out_sethi(s, ret, ~arg);
|
||||||
tcg_out_arithi(s, ret, ret, (arg & 0x3ff) | -0x400, ARITH_XOR);
|
tcg_out_arithi(s, ret, ret, (arg & 0x3ff) | -0x400, ARITH_XOR);
|
||||||
} else {
|
return;
|
||||||
tcg_out_movi_imm32(s, ret, arg >> (TCG_TARGET_REG_BITS / 2));
|
}
|
||||||
|
|
||||||
|
/* A 64-bit constant decomposed into 2 32-bit pieces. */
|
||||||
|
lo = (int32_t)arg;
|
||||||
|
if (check_fit_tl(lo, 13)) {
|
||||||
|
hi = (arg - lo) >> 31 >> 1;
|
||||||
|
tcg_out_movi(s, TCG_TYPE_I32, ret, hi);
|
||||||
|
tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX);
|
||||||
|
tcg_out_arithi(s, ret, ret, lo, ARITH_ADD);
|
||||||
|
} else {
|
||||||
|
hi = arg >> 31 >> 1;
|
||||||
|
tcg_out_movi(s, TCG_TYPE_I32, ret, hi);
|
||||||
|
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T2, lo);
|
||||||
tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX);
|
tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX);
|
||||||
tcg_out_movi_imm32(s, TCG_REG_T2, arg);
|
|
||||||
tcg_out_arith(s, ret, ret, TCG_REG_T2, ARITH_OR);
|
tcg_out_arith(s, ret, ret, TCG_REG_T2, ARITH_OR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -449,13 +459,14 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
|
|||||||
tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX));
|
tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
|
static inline void tcg_out_ld_ptr(TCGContext *s, TCGReg ret, uintptr_t arg)
|
||||||
tcg_target_long arg)
|
|
||||||
{
|
{
|
||||||
|
TCGReg base = TCG_REG_G0;
|
||||||
if (!check_fit_tl(arg, 10)) {
|
if (!check_fit_tl(arg, 10)) {
|
||||||
tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ff);
|
tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ff);
|
||||||
|
base = ret;
|
||||||
}
|
}
|
||||||
tcg_out_ld(s, TCG_TYPE_PTR, ret, ret, arg & 0x3ff);
|
tcg_out_ld(s, TCG_TYPE_PTR, ret, base, arg & 0x3ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_sety(TCGContext *s, int rs)
|
static inline void tcg_out_sety(TCGContext *s, int rs)
|
||||||
@@ -480,19 +491,6 @@ static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_andi(TCGContext *s, int rd, int rs,
|
|
||||||
tcg_target_long val)
|
|
||||||
{
|
|
||||||
if (val != 0) {
|
|
||||||
if (check_fit_tl(val, 13))
|
|
||||||
tcg_out_arithi(s, rd, rs, val, ARITH_AND);
|
|
||||||
else {
|
|
||||||
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T1, val);
|
|
||||||
tcg_out_arith(s, rd, rs, TCG_REG_T1, ARITH_AND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tcg_out_div32(TCGContext *s, int rd, int rs1,
|
static void tcg_out_div32(TCGContext *s, int rd, int rs1,
|
||||||
int val2, int val2const, int uns)
|
int val2, int val2const, int uns)
|
||||||
{
|
{
|
||||||
@@ -796,6 +794,110 @@ static void tcg_out_addsub2(TCGContext *s, TCGArg rl, TCGArg rh,
|
|||||||
tcg_out_mov(s, TCG_TYPE_I32, rl, tmp);
|
tcg_out_mov(s, TCG_TYPE_I32, rl, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void tcg_out_calli(TCGContext *s, uintptr_t dest)
|
||||||
|
{
|
||||||
|
intptr_t disp = dest - (uintptr_t)s->code_ptr;
|
||||||
|
|
||||||
|
if (disp == (int32_t)disp) {
|
||||||
|
tcg_out32(s, CALL | (uint32_t)disp >> 2);
|
||||||
|
} else {
|
||||||
|
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, dest & ~0xfff);
|
||||||
|
tcg_out_arithi(s, TCG_REG_O7, TCG_REG_T1, dest & 0xfff, JMPL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SOFTMMU
|
||||||
|
static uintptr_t qemu_ld_trampoline[16];
|
||||||
|
static uintptr_t qemu_st_trampoline[16];
|
||||||
|
|
||||||
|
static void build_trampolines(TCGContext *s)
|
||||||
|
{
|
||||||
|
static uintptr_t const qemu_ld_helpers[16] = {
|
||||||
|
[MO_UB] = (uintptr_t)helper_ret_ldub_mmu,
|
||||||
|
[MO_SB] = (uintptr_t)helper_ret_ldsb_mmu,
|
||||||
|
[MO_LEUW] = (uintptr_t)helper_le_lduw_mmu,
|
||||||
|
[MO_LESW] = (uintptr_t)helper_le_ldsw_mmu,
|
||||||
|
[MO_LEUL] = (uintptr_t)helper_le_ldul_mmu,
|
||||||
|
[MO_LEQ] = (uintptr_t)helper_le_ldq_mmu,
|
||||||
|
[MO_BEUW] = (uintptr_t)helper_be_lduw_mmu,
|
||||||
|
[MO_BESW] = (uintptr_t)helper_be_ldsw_mmu,
|
||||||
|
[MO_BEUL] = (uintptr_t)helper_be_ldul_mmu,
|
||||||
|
[MO_BEQ] = (uintptr_t)helper_be_ldq_mmu,
|
||||||
|
};
|
||||||
|
static uintptr_t const qemu_st_helpers[16] = {
|
||||||
|
[MO_UB] = (uintptr_t)helper_ret_stb_mmu,
|
||||||
|
[MO_LEUW] = (uintptr_t)helper_le_stw_mmu,
|
||||||
|
[MO_LEUL] = (uintptr_t)helper_le_stl_mmu,
|
||||||
|
[MO_LEQ] = (uintptr_t)helper_le_stq_mmu,
|
||||||
|
[MO_BEUW] = (uintptr_t)helper_be_stw_mmu,
|
||||||
|
[MO_BEUL] = (uintptr_t)helper_be_stl_mmu,
|
||||||
|
[MO_BEQ] = (uintptr_t)helper_be_stq_mmu,
|
||||||
|
};
|
||||||
|
|
||||||
|
int i;
|
||||||
|
TCGReg ra;
|
||||||
|
uintptr_t tramp;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; ++i) {
|
||||||
|
if (qemu_ld_helpers[i] == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* May as well align the trampoline. */
|
||||||
|
tramp = (uintptr_t)s->code_ptr;
|
||||||
|
while (tramp & 15) {
|
||||||
|
tcg_out_nop(s);
|
||||||
|
tramp += 4;
|
||||||
|
}
|
||||||
|
qemu_ld_trampoline[i] = tramp;
|
||||||
|
|
||||||
|
/* Find the retaddr argument register. */
|
||||||
|
ra = TCG_REG_O3 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS);
|
||||||
|
|
||||||
|
/* Set the retaddr operand. */
|
||||||
|
tcg_out_mov(s, TCG_TYPE_PTR, ra, TCG_REG_O7);
|
||||||
|
/* Set the env operand. */
|
||||||
|
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O0, TCG_AREG0);
|
||||||
|
/* Tail call. */
|
||||||
|
tcg_out_calli(s, qemu_ld_helpers[i]);
|
||||||
|
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O7, ra);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 16; ++i) {
|
||||||
|
if (qemu_st_helpers[i] == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* May as well align the trampoline. */
|
||||||
|
tramp = (uintptr_t)s->code_ptr;
|
||||||
|
while (tramp & 15) {
|
||||||
|
tcg_out_nop(s);
|
||||||
|
tramp += 4;
|
||||||
|
}
|
||||||
|
qemu_st_trampoline[i] = tramp;
|
||||||
|
|
||||||
|
/* Find the retaddr argument. For 32-bit, this may be past the
|
||||||
|
last argument register, and need passing on the stack. */
|
||||||
|
ra = (TCG_REG_O4
|
||||||
|
+ (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)
|
||||||
|
+ (TCG_TARGET_REG_BITS == 32 && (i & MO_SIZE) == MO_64));
|
||||||
|
|
||||||
|
/* Set the retaddr operand. */
|
||||||
|
if (ra >= TCG_REG_O6) {
|
||||||
|
tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_O7, TCG_REG_CALL_STACK,
|
||||||
|
TCG_TARGET_CALL_STACK_OFFSET);
|
||||||
|
ra = TCG_REG_G1;
|
||||||
|
}
|
||||||
|
tcg_out_mov(s, TCG_TYPE_PTR, ra, TCG_REG_O7);
|
||||||
|
/* Set the env operand. */
|
||||||
|
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O0, TCG_AREG0);
|
||||||
|
/* Tail call. */
|
||||||
|
tcg_out_calli(s, qemu_st_helpers[i]);
|
||||||
|
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O7, ra);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Generate global QEMU prologue and epilogue code */
|
/* Generate global QEMU prologue and epilogue code */
|
||||||
static void tcg_target_qemu_prologue(TCGContext *s)
|
static void tcg_target_qemu_prologue(TCGContext *s)
|
||||||
{
|
{
|
||||||
@@ -823,39 +925,22 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I1) |
|
tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I1, 0, JMPL);
|
||||||
INSN_RS2(TCG_REG_G0));
|
|
||||||
/* delay slot */
|
/* delay slot */
|
||||||
tcg_out_nop(s);
|
tcg_out_nop(s);
|
||||||
|
|
||||||
/* No epilogue required. We issue ret + restore directly in the TB. */
|
/* No epilogue required. We issue ret + restore directly in the TB. */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SOFTMMU
|
||||||
|
build_trampolines(s);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_SOFTMMU)
|
#if defined(CONFIG_SOFTMMU)
|
||||||
|
|
||||||
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
|
||||||
int mmu_idx) */
|
|
||||||
static const void * const qemu_ld_helpers[4] = {
|
|
||||||
helper_ldb_mmu,
|
|
||||||
helper_ldw_mmu,
|
|
||||||
helper_ldl_mmu,
|
|
||||||
helper_ldq_mmu,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
|
|
||||||
uintxx_t val, int mmu_idx) */
|
|
||||||
static const void * const qemu_st_helpers[4] = {
|
|
||||||
helper_stb_mmu,
|
|
||||||
helper_stw_mmu,
|
|
||||||
helper_stl_mmu,
|
|
||||||
helper_stq_mmu,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Perform the TLB load and compare.
|
/* Perform the TLB load and compare.
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
ADDRLO_IDX contains the index into ARGS of the low part of the
|
ADDRLO and ADDRHI contain the possible two parts of the address.
|
||||||
address; the high part of the address is at ADDR_LOW_IDX+1.
|
|
||||||
|
|
||||||
MEM_INDEX and S_BITS are the memory context and log2 size of the load.
|
MEM_INDEX and S_BITS are the memory context and log2 size of the load.
|
||||||
|
|
||||||
@@ -865,32 +950,38 @@ static const void * const qemu_st_helpers[4] = {
|
|||||||
The result of the TLB comparison is in %[ix]cc. The sanitized address
|
The result of the TLB comparison is in %[ix]cc. The sanitized address
|
||||||
is in the returned register, maybe %o0. The TLB addend is in %o1. */
|
is in the returned register, maybe %o0. The TLB addend is in %o1. */
|
||||||
|
|
||||||
static int tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index,
|
static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
|
||||||
int s_bits, const TCGArg *args, int which)
|
int mem_index, TCGMemOp s_bits, int which)
|
||||||
{
|
{
|
||||||
const int addrlo = args[addrlo_idx];
|
const TCGReg r0 = TCG_REG_O0;
|
||||||
const int r0 = TCG_REG_O0;
|
const TCGReg r1 = TCG_REG_O1;
|
||||||
const int r1 = TCG_REG_O1;
|
const TCGReg r2 = TCG_REG_O2;
|
||||||
const int r2 = TCG_REG_O2;
|
TCGReg addr = addrlo;
|
||||||
int addr = addrlo;
|
|
||||||
int tlb_ofs;
|
int tlb_ofs;
|
||||||
|
|
||||||
if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
|
if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
|
||||||
/* Assemble the 64-bit address in R0. */
|
/* Assemble the 64-bit address in R0. */
|
||||||
tcg_out_arithi(s, r0, addrlo, 0, SHIFT_SRL);
|
tcg_out_arithi(s, r0, addrlo, 0, SHIFT_SRL);
|
||||||
tcg_out_arithi(s, r1, args[addrlo_idx + 1], 32, SHIFT_SLLX);
|
tcg_out_arithi(s, r1, addrhi, 32, SHIFT_SLLX);
|
||||||
tcg_out_arith(s, r0, r0, r1, ARITH_OR);
|
tcg_out_arith(s, r0, r0, r1, ARITH_OR);
|
||||||
|
addr = r0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shift the page number down to tlb-entry. */
|
/* Shift the page number down. */
|
||||||
tcg_out_arithi(s, r1, addrlo,
|
tcg_out_arithi(s, r1, addrlo, TARGET_PAGE_BITS, SHIFT_SRL);
|
||||||
TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, SHIFT_SRL);
|
|
||||||
|
|
||||||
/* Mask out the page offset, except for the required alignment. */
|
/* Mask out the page offset, except for the required alignment. */
|
||||||
tcg_out_andi(s, r0, addr, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
|
tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_T1,
|
||||||
|
TARGET_PAGE_MASK | ((1 << s_bits) - 1));
|
||||||
|
|
||||||
/* Compute tlb index, modulo tlb size. */
|
/* Mask the tlb index. */
|
||||||
tcg_out_andi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
|
tcg_out_arithi(s, r1, r1, CPU_TLB_SIZE - 1, ARITH_AND);
|
||||||
|
|
||||||
|
/* Mask page, part 2. */
|
||||||
|
tcg_out_arith(s, r0, addr, TCG_REG_T1, ARITH_AND);
|
||||||
|
|
||||||
|
/* Shift the tlb index into place. */
|
||||||
|
tcg_out_arithi(s, r1, r1, CPU_TLB_ENTRY_BITS, SHIFT_SLL);
|
||||||
|
|
||||||
/* Relative to the current ENV. */
|
/* Relative to the current ENV. */
|
||||||
tcg_out_arith(s, r1, TCG_AREG0, r1, ARITH_ADD);
|
tcg_out_arith(s, r1, TCG_AREG0, r1, ARITH_ADD);
|
||||||
@@ -898,8 +989,8 @@ static int tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index,
|
|||||||
/* Find a base address that can load both tlb comparator and addend. */
|
/* Find a base address that can load both tlb comparator and addend. */
|
||||||
tlb_ofs = offsetof(CPUArchState, tlb_table[mem_index][0]);
|
tlb_ofs = offsetof(CPUArchState, tlb_table[mem_index][0]);
|
||||||
if (!check_fit_tl(tlb_ofs + sizeof(CPUTLBEntry), 13)) {
|
if (!check_fit_tl(tlb_ofs + sizeof(CPUTLBEntry), 13)) {
|
||||||
tcg_out_addi(s, r1, tlb_ofs);
|
tcg_out_addi(s, r1, tlb_ofs & ~0x3ff);
|
||||||
tlb_ofs = 0;
|
tlb_ofs &= 0x3ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load the tlb comparator and the addend. */
|
/* Load the tlb comparator and the addend. */
|
||||||
@@ -918,56 +1009,71 @@ static int tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_SOFTMMU */
|
#endif /* CONFIG_SOFTMMU */
|
||||||
|
|
||||||
static const int qemu_ld_opc[8] = {
|
static const int qemu_ld_opc[16] = {
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
[MO_UB] = LDUB,
|
||||||
LDUB, LDUH, LDUW, LDX, LDSB, LDSH, LDSW, LDX
|
[MO_SB] = LDSB,
|
||||||
#else
|
|
||||||
LDUB, LDUH_LE, LDUW_LE, LDX_LE, LDSB, LDSH_LE, LDSW_LE, LDX_LE
|
[MO_BEUW] = LDUH,
|
||||||
#endif
|
[MO_BESW] = LDSH,
|
||||||
|
[MO_BEUL] = LDUW,
|
||||||
|
[MO_BESL] = LDSW,
|
||||||
|
[MO_BEQ] = LDX,
|
||||||
|
|
||||||
|
[MO_LEUW] = LDUH_LE,
|
||||||
|
[MO_LESW] = LDSH_LE,
|
||||||
|
[MO_LEUL] = LDUW_LE,
|
||||||
|
[MO_LESL] = LDSW_LE,
|
||||||
|
[MO_LEQ] = LDX_LE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int qemu_st_opc[4] = {
|
static const int qemu_st_opc[16] = {
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
[MO_UB] = STB,
|
||||||
STB, STH, STW, STX
|
|
||||||
#else
|
[MO_BEUW] = STH,
|
||||||
STB, STH_LE, STW_LE, STX_LE
|
[MO_BEUL] = STW,
|
||||||
#endif
|
[MO_BEQ] = STX,
|
||||||
|
|
||||||
|
[MO_LEUW] = STH_LE,
|
||||||
|
[MO_LEUL] = STW_LE,
|
||||||
|
[MO_LEQ] = STX_LE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
|
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
|
||||||
{
|
{
|
||||||
int addrlo_idx = 1, datalo, datahi, addr_reg;
|
TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
|
||||||
|
TCGMemOp memop, s_bits;
|
||||||
#if defined(CONFIG_SOFTMMU)
|
#if defined(CONFIG_SOFTMMU)
|
||||||
int memi_idx, memi, s_bits, n;
|
TCGReg addrz, param;
|
||||||
|
uintptr_t func;
|
||||||
|
int memi;
|
||||||
uint32_t *label_ptr[2];
|
uint32_t *label_ptr[2];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
datahi = datalo = args[0];
|
datalo = *args++;
|
||||||
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
|
datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0);
|
||||||
datahi = args[1];
|
addrlo = *args++;
|
||||||
addrlo_idx = 2;
|
addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
|
||||||
}
|
memop = *args++;
|
||||||
|
s_bits = memop & MO_SIZE;
|
||||||
|
|
||||||
#if defined(CONFIG_SOFTMMU)
|
#if defined(CONFIG_SOFTMMU)
|
||||||
memi_idx = addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS);
|
memi = *args++;
|
||||||
memi = args[memi_idx];
|
addrz = tcg_out_tlb_load(s, addrlo, addrhi, memi, s_bits,
|
||||||
s_bits = sizeop & 3;
|
offsetof(CPUTLBEntry, addr_read));
|
||||||
|
|
||||||
addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, s_bits, args,
|
if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
|
||||||
offsetof(CPUTLBEntry, addr_read));
|
|
||||||
|
|
||||||
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
|
|
||||||
int reg64;
|
int reg64;
|
||||||
|
|
||||||
/* bne,pn %[xi]cc, label0 */
|
/* bne,pn %[xi]cc, label0 */
|
||||||
label_ptr[0] = (uint32_t *)s->code_ptr;
|
label_ptr[0] = (uint32_t *)s->code_ptr;
|
||||||
tcg_out_bpcc0(s, COND_NE, BPCC_PN
|
tcg_out_bpcc0(s, COND_NE, BPCC_PN
|
||||||
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
|
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
|
||||||
|
tcg_out_nop(s);
|
||||||
|
|
||||||
/* TLB Hit. */
|
/* TLB Hit. */
|
||||||
/* Load all 64-bits into an O/G register. */
|
/* Load all 64-bits into an O/G register. */
|
||||||
reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
|
reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
|
||||||
tcg_out_ldst_rr(s, reg64, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]);
|
tcg_out_ldst_rr(s, reg64, addrz, TCG_REG_O1, qemu_ld_opc[memop]);
|
||||||
|
|
||||||
/* Move the two 32-bit pieces into the destination registers. */
|
/* Move the two 32-bit pieces into the destination registers. */
|
||||||
tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
|
tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
|
||||||
@@ -989,7 +1095,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
|
|||||||
tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
|
tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
|
||||||
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
|
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
|
||||||
/* delay slot */
|
/* delay slot */
|
||||||
tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]);
|
tcg_out_ldst_rr(s, datalo, addrz, TCG_REG_O1, qemu_ld_opc[memop]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TLB Miss. */
|
/* TLB Miss. */
|
||||||
@@ -998,103 +1104,93 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
|
|||||||
*label_ptr[0] |= INSN_OFF19((unsigned long)s->code_ptr -
|
*label_ptr[0] |= INSN_OFF19((unsigned long)s->code_ptr -
|
||||||
(unsigned long)label_ptr[0]);
|
(unsigned long)label_ptr[0]);
|
||||||
}
|
}
|
||||||
n = 0;
|
|
||||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[n++], TCG_AREG0);
|
param = TCG_REG_O1;
|
||||||
if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
|
if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
|
tcg_out_mov(s, TCG_TYPE_REG, param++, addrhi);
|
||||||
args[addrlo_idx + 1]);
|
|
||||||
}
|
}
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
|
tcg_out_mov(s, TCG_TYPE_REG, param++, addrlo);
|
||||||
args[addrlo_idx]);
|
|
||||||
|
|
||||||
/* qemu_ld_helper[s_bits](arg0, arg1) */
|
/* We use the helpers to extend SB and SW data, leaving the case
|
||||||
tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits]
|
of SL needing explicit extending below. */
|
||||||
- (tcg_target_ulong)s->code_ptr) >> 2)
|
if ((memop & ~MO_BSWAP) == MO_SL) {
|
||||||
& 0x3fffffff));
|
func = qemu_ld_trampoline[memop & ~MO_SIGN];
|
||||||
|
} else {
|
||||||
|
func = qemu_ld_trampoline[memop];
|
||||||
|
}
|
||||||
|
assert(func != 0);
|
||||||
|
tcg_out_calli(s, func);
|
||||||
/* delay slot */
|
/* delay slot */
|
||||||
tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[n], memi);
|
tcg_out_movi(s, TCG_TYPE_I32, param, memi);
|
||||||
|
|
||||||
n = tcg_target_call_oarg_regs[0];
|
switch (memop & ~MO_BSWAP) {
|
||||||
/* datalo = sign_extend(arg0) */
|
case MO_SL:
|
||||||
switch (sizeop) {
|
tcg_out_arithi(s, datalo, TCG_REG_O0, 0, SHIFT_SRA);
|
||||||
case 0 | 4:
|
|
||||||
/* Recall that SRA sign extends from bit 31 through bit 63. */
|
|
||||||
tcg_out_arithi(s, datalo, n, 24, SHIFT_SLL);
|
|
||||||
tcg_out_arithi(s, datalo, datalo, 24, SHIFT_SRA);
|
|
||||||
break;
|
break;
|
||||||
case 1 | 4:
|
case MO_Q:
|
||||||
tcg_out_arithi(s, datalo, n, 16, SHIFT_SLL);
|
|
||||||
tcg_out_arithi(s, datalo, datalo, 16, SHIFT_SRA);
|
|
||||||
break;
|
|
||||||
case 2 | 4:
|
|
||||||
tcg_out_arithi(s, datalo, n, 0, SHIFT_SRA);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if (TCG_TARGET_REG_BITS == 32) {
|
if (TCG_TARGET_REG_BITS == 32) {
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, datahi, n);
|
tcg_out_mov(s, TCG_TYPE_REG, datahi, TCG_REG_O0);
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, datalo, n + 1);
|
tcg_out_mov(s, TCG_TYPE_REG, datalo, TCG_REG_O1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* FALLTHRU */
|
/* FALLTHRU */
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
default:
|
default:
|
||||||
/* mov */
|
/* mov */
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, datalo, n);
|
tcg_out_mov(s, TCG_TYPE_REG, datalo, TCG_REG_O0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*label_ptr[1] |= INSN_OFF19((unsigned long)s->code_ptr -
|
*label_ptr[1] |= INSN_OFF19((unsigned long)s->code_ptr -
|
||||||
(unsigned long)label_ptr[1]);
|
(unsigned long)label_ptr[1]);
|
||||||
#else
|
#else
|
||||||
addr_reg = args[addrlo_idx];
|
|
||||||
if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
|
if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
|
||||||
tcg_out_arithi(s, TCG_REG_T1, addr_reg, 0, SHIFT_SRL);
|
tcg_out_arithi(s, TCG_REG_T1, addrlo, 0, SHIFT_SRL);
|
||||||
addr_reg = TCG_REG_T1;
|
addrlo = TCG_REG_T1;
|
||||||
}
|
}
|
||||||
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
|
if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
|
||||||
int reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
|
int reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
|
||||||
|
|
||||||
tcg_out_ldst_rr(s, reg64, addr_reg,
|
tcg_out_ldst_rr(s, reg64, addrlo,
|
||||||
(GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
|
(GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
|
||||||
qemu_ld_opc[sizeop]);
|
qemu_ld_opc[memop]);
|
||||||
|
|
||||||
tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
|
tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
|
||||||
if (reg64 != datalo) {
|
if (reg64 != datalo) {
|
||||||
tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64);
|
tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tcg_out_ldst_rr(s, datalo, addr_reg,
|
tcg_out_ldst_rr(s, datalo, addrlo,
|
||||||
(GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
|
(GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
|
||||||
qemu_ld_opc[sizeop]);
|
qemu_ld_opc[memop]);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SOFTMMU */
|
#endif /* CONFIG_SOFTMMU */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop)
|
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
|
||||||
{
|
{
|
||||||
int addrlo_idx = 1, datalo, datahi, addr_reg;
|
TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
|
||||||
|
TCGMemOp memop, s_bits;
|
||||||
#if defined(CONFIG_SOFTMMU)
|
#if defined(CONFIG_SOFTMMU)
|
||||||
int memi_idx, memi, n, datafull;
|
TCGReg addrz, datafull, param;
|
||||||
|
uintptr_t func;
|
||||||
|
int memi;
|
||||||
uint32_t *label_ptr;
|
uint32_t *label_ptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
datahi = datalo = args[0];
|
datalo = *args++;
|
||||||
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
|
datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0);
|
||||||
datahi = args[1];
|
addrlo = *args++;
|
||||||
addrlo_idx = 2;
|
addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
|
||||||
}
|
memop = *args++;
|
||||||
|
s_bits = memop & MO_SIZE;
|
||||||
|
|
||||||
#if defined(CONFIG_SOFTMMU)
|
#if defined(CONFIG_SOFTMMU)
|
||||||
memi_idx = addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS);
|
memi = *args++;
|
||||||
memi = args[memi_idx];
|
addrz = tcg_out_tlb_load(s, addrlo, addrhi, memi, s_bits,
|
||||||
|
offsetof(CPUTLBEntry, addr_write));
|
||||||
addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, sizeop, args,
|
|
||||||
offsetof(CPUTLBEntry, addr_write));
|
|
||||||
|
|
||||||
datafull = datalo;
|
datafull = datalo;
|
||||||
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
|
if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
|
||||||
/* Reconstruct the full 64-bit value. */
|
/* Reconstruct the full 64-bit value. */
|
||||||
tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL);
|
tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL);
|
||||||
tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
|
tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
|
||||||
@@ -1109,47 +1205,42 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop)
|
|||||||
tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
|
tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
|
||||||
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
|
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
|
||||||
/* delay slot */
|
/* delay slot */
|
||||||
tcg_out_ldst_rr(s, datafull, addr_reg, TCG_REG_O1, qemu_st_opc[sizeop]);
|
tcg_out_ldst_rr(s, datafull, addrz, TCG_REG_O1, qemu_st_opc[memop]);
|
||||||
|
|
||||||
/* TLB Miss. */
|
/* TLB Miss. */
|
||||||
|
|
||||||
n = 0;
|
param = TCG_REG_O1;
|
||||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[n++], TCG_AREG0);
|
|
||||||
if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
|
if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
|
tcg_out_mov(s, TCG_TYPE_REG, param++, addrhi);
|
||||||
args[addrlo_idx + 1]);
|
|
||||||
}
|
}
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
|
tcg_out_mov(s, TCG_TYPE_REG, param++, addrlo);
|
||||||
args[addrlo_idx]);
|
if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
|
||||||
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
|
tcg_out_mov(s, TCG_TYPE_REG, param++, datahi);
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datahi);
|
|
||||||
}
|
}
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datalo);
|
tcg_out_mov(s, TCG_TYPE_REG, param++, datalo);
|
||||||
|
|
||||||
/* qemu_st_helper[s_bits](arg0, arg1, arg2) */
|
func = qemu_st_trampoline[memop];
|
||||||
tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[sizeop]
|
assert(func != 0);
|
||||||
- (tcg_target_ulong)s->code_ptr) >> 2)
|
tcg_out_calli(s, func);
|
||||||
& 0x3fffffff));
|
|
||||||
/* delay slot */
|
/* delay slot */
|
||||||
tcg_out_movi(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n], memi);
|
tcg_out_movi(s, TCG_TYPE_REG, param, memi);
|
||||||
|
|
||||||
*label_ptr |= INSN_OFF19((unsigned long)s->code_ptr -
|
*label_ptr |= INSN_OFF19((unsigned long)s->code_ptr -
|
||||||
(unsigned long)label_ptr);
|
(unsigned long)label_ptr);
|
||||||
#else
|
#else
|
||||||
addr_reg = args[addrlo_idx];
|
|
||||||
if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
|
if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
|
||||||
tcg_out_arithi(s, TCG_REG_T1, addr_reg, 0, SHIFT_SRL);
|
tcg_out_arithi(s, TCG_REG_T1, addrlo, 0, SHIFT_SRL);
|
||||||
addr_reg = TCG_REG_T1;
|
addrlo = TCG_REG_T1;
|
||||||
}
|
}
|
||||||
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
|
if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
|
||||||
tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL);
|
tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL);
|
||||||
tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
|
tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
|
||||||
tcg_out_arith(s, TCG_REG_O2, TCG_REG_T1, TCG_REG_O2, ARITH_OR);
|
tcg_out_arith(s, TCG_REG_O2, TCG_REG_T1, TCG_REG_O2, ARITH_OR);
|
||||||
datalo = TCG_REG_O2;
|
datalo = TCG_REG_O2;
|
||||||
}
|
}
|
||||||
tcg_out_ldst_rr(s, datalo, addr_reg,
|
tcg_out_ldst_rr(s, datalo, addrlo,
|
||||||
(GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
|
(GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
|
||||||
qemu_st_opc[sizeop]);
|
qemu_st_opc[memop]);
|
||||||
#endif /* CONFIG_SOFTMMU */
|
#endif /* CONFIG_SOFTMMU */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1161,8 +1252,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
|
|||||||
switch (opc) {
|
switch (opc) {
|
||||||
case INDEX_op_exit_tb:
|
case INDEX_op_exit_tb:
|
||||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, args[0]);
|
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, args[0]);
|
||||||
tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I7) |
|
tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, JMPL);
|
||||||
INSN_IMM13(8));
|
|
||||||
tcg_out32(s, RESTORE | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_G0) |
|
tcg_out32(s, RESTORE | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_G0) |
|
||||||
INSN_RS2(TCG_REG_G0));
|
INSN_RS2(TCG_REG_G0));
|
||||||
break;
|
break;
|
||||||
@@ -1175,24 +1265,17 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
|
|||||||
tcg_out32(s, CALL | (old_insn & ~INSN_OP(-1)));
|
tcg_out32(s, CALL | (old_insn & ~INSN_OP(-1)));
|
||||||
} else {
|
} else {
|
||||||
/* indirect jump method */
|
/* indirect jump method */
|
||||||
tcg_out_ld_ptr(s, TCG_REG_T1,
|
tcg_out_ld_ptr(s, TCG_REG_T1, (uintptr_t)(s->tb_next + args[0]));
|
||||||
(tcg_target_long)(s->tb_next + args[0]));
|
tcg_out_arithi(s, TCG_REG_G0, TCG_REG_T1, 0, JMPL);
|
||||||
tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_T1) |
|
|
||||||
INSN_RS2(TCG_REG_G0));
|
|
||||||
}
|
}
|
||||||
tcg_out_nop(s);
|
tcg_out_nop(s);
|
||||||
s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
|
s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
|
||||||
break;
|
break;
|
||||||
case INDEX_op_call:
|
case INDEX_op_call:
|
||||||
if (const_args[0]) {
|
if (const_args[0]) {
|
||||||
tcg_out32(s, CALL | ((((tcg_target_ulong)args[0]
|
tcg_out_calli(s, args[0]);
|
||||||
- (tcg_target_ulong)s->code_ptr) >> 2)
|
|
||||||
& 0x3fffffff));
|
|
||||||
} else {
|
} else {
|
||||||
tcg_out_ld_ptr(s, TCG_REG_T1,
|
tcg_out_arithi(s, TCG_REG_O7, args[0], 0, JMPL);
|
||||||
(tcg_target_long)(s->tb_next + args[0]));
|
|
||||||
tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_T1) |
|
|
||||||
INSN_RS2(TCG_REG_G0));
|
|
||||||
}
|
}
|
||||||
/* delay slot */
|
/* delay slot */
|
||||||
tcg_out_nop(s);
|
tcg_out_nop(s);
|
||||||
@@ -1294,15 +1377,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
|
|||||||
tcg_out_div32(s, args[0], args[1], args[2], const_args[2], 1);
|
tcg_out_div32(s, args[0], args[1], args[2], const_args[2], 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_rem_i32:
|
|
||||||
case INDEX_op_remu_i32:
|
|
||||||
tcg_out_div32(s, TCG_REG_T1, args[1], args[2], const_args[2],
|
|
||||||
opc == INDEX_op_remu_i32);
|
|
||||||
tcg_out_arithc(s, TCG_REG_T1, TCG_REG_T1, args[2], const_args[2],
|
|
||||||
ARITH_UMUL);
|
|
||||||
tcg_out_arith(s, args[0], args[1], TCG_REG_T1, ARITH_SUB);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_brcond_i32:
|
case INDEX_op_brcond_i32:
|
||||||
tcg_out_brcond_i32(s, args[2], args[0], args[1], const_args[1],
|
tcg_out_brcond_i32(s, args[2], args[0], args[1], const_args[1],
|
||||||
args[3]);
|
args[3]);
|
||||||
@@ -1345,44 +1419,18 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
|
|||||||
tcg_out_rdy(s, args[1]);
|
tcg_out_rdy(s, args[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_qemu_ld8u:
|
case INDEX_op_qemu_ld_i32:
|
||||||
tcg_out_qemu_ld(s, args, 0);
|
tcg_out_qemu_ld(s, args, 0);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_qemu_ld8s:
|
case INDEX_op_qemu_ld_i64:
|
||||||
tcg_out_qemu_ld(s, args, 0 | 4);
|
|
||||||
break;
|
|
||||||
case INDEX_op_qemu_ld16u:
|
|
||||||
tcg_out_qemu_ld(s, args, 1);
|
tcg_out_qemu_ld(s, args, 1);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_qemu_ld16s:
|
case INDEX_op_qemu_st_i32:
|
||||||
tcg_out_qemu_ld(s, args, 1 | 4);
|
|
||||||
break;
|
|
||||||
case INDEX_op_qemu_ld32:
|
|
||||||
#if TCG_TARGET_REG_BITS == 64
|
|
||||||
case INDEX_op_qemu_ld32u:
|
|
||||||
#endif
|
|
||||||
tcg_out_qemu_ld(s, args, 2);
|
|
||||||
break;
|
|
||||||
#if TCG_TARGET_REG_BITS == 64
|
|
||||||
case INDEX_op_qemu_ld32s:
|
|
||||||
tcg_out_qemu_ld(s, args, 2 | 4);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case INDEX_op_qemu_ld64:
|
|
||||||
tcg_out_qemu_ld(s, args, 3);
|
|
||||||
break;
|
|
||||||
case INDEX_op_qemu_st8:
|
|
||||||
tcg_out_qemu_st(s, args, 0);
|
tcg_out_qemu_st(s, args, 0);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_qemu_st16:
|
case INDEX_op_qemu_st_i64:
|
||||||
tcg_out_qemu_st(s, args, 1);
|
tcg_out_qemu_st(s, args, 1);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_qemu_st32:
|
|
||||||
tcg_out_qemu_st(s, args, 2);
|
|
||||||
break;
|
|
||||||
case INDEX_op_qemu_st64:
|
|
||||||
tcg_out_qemu_st(s, args, 3);
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if TCG_TARGET_REG_BITS == 64
|
#if TCG_TARGET_REG_BITS == 64
|
||||||
case INDEX_op_movi_i64:
|
case INDEX_op_movi_i64:
|
||||||
@@ -1418,27 +1466,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
|
|||||||
case INDEX_op_divu_i64:
|
case INDEX_op_divu_i64:
|
||||||
c = ARITH_UDIVX;
|
c = ARITH_UDIVX;
|
||||||
goto gen_arith;
|
goto gen_arith;
|
||||||
case INDEX_op_rem_i64:
|
|
||||||
case INDEX_op_remu_i64:
|
|
||||||
tcg_out_arithc(s, TCG_REG_T1, args[1], args[2], const_args[2],
|
|
||||||
opc == INDEX_op_rem_i64 ? ARITH_SDIVX : ARITH_UDIVX);
|
|
||||||
tcg_out_arithc(s, TCG_REG_T1, TCG_REG_T1, args[2], const_args[2],
|
|
||||||
ARITH_MULX);
|
|
||||||
tcg_out_arith(s, args[0], args[1], TCG_REG_T1, ARITH_SUB);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext32s_i64:
|
case INDEX_op_ext32s_i64:
|
||||||
if (const_args[1]) {
|
tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRA);
|
||||||
tcg_out_movi(s, TCG_TYPE_I64, args[0], (int32_t)args[1]);
|
|
||||||
} else {
|
|
||||||
tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRA);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case INDEX_op_ext32u_i64:
|
case INDEX_op_ext32u_i64:
|
||||||
if (const_args[1]) {
|
tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRL);
|
||||||
tcg_out_movi_imm32(s, args[0], args[1]);
|
|
||||||
} else {
|
|
||||||
tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRL);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_brcond_i64:
|
case INDEX_op_brcond_i64:
|
||||||
@@ -1489,8 +1521,6 @@ static const TCGTargetOpDef sparc_op_defs[] = {
|
|||||||
{ INDEX_op_mul_i32, { "r", "rZ", "rJ" } },
|
{ INDEX_op_mul_i32, { "r", "rZ", "rJ" } },
|
||||||
{ INDEX_op_div_i32, { "r", "rZ", "rJ" } },
|
{ INDEX_op_div_i32, { "r", "rZ", "rJ" } },
|
||||||
{ INDEX_op_divu_i32, { "r", "rZ", "rJ" } },
|
{ INDEX_op_divu_i32, { "r", "rZ", "rJ" } },
|
||||||
{ INDEX_op_rem_i32, { "r", "rZ", "rJ" } },
|
|
||||||
{ INDEX_op_remu_i32, { "r", "rZ", "rJ" } },
|
|
||||||
{ INDEX_op_sub_i32, { "r", "rZ", "rJ" } },
|
{ INDEX_op_sub_i32, { "r", "rZ", "rJ" } },
|
||||||
{ INDEX_op_and_i32, { "r", "rZ", "rJ" } },
|
{ INDEX_op_and_i32, { "r", "rZ", "rJ" } },
|
||||||
{ INDEX_op_andc_i32, { "r", "rZ", "rJ" } },
|
{ INDEX_op_andc_i32, { "r", "rZ", "rJ" } },
|
||||||
@@ -1537,8 +1567,6 @@ static const TCGTargetOpDef sparc_op_defs[] = {
|
|||||||
{ INDEX_op_mul_i64, { "r", "rZ", "rJ" } },
|
{ INDEX_op_mul_i64, { "r", "rZ", "rJ" } },
|
||||||
{ INDEX_op_div_i64, { "r", "rZ", "rJ" } },
|
{ INDEX_op_div_i64, { "r", "rZ", "rJ" } },
|
||||||
{ INDEX_op_divu_i64, { "r", "rZ", "rJ" } },
|
{ INDEX_op_divu_i64, { "r", "rZ", "rJ" } },
|
||||||
{ INDEX_op_rem_i64, { "r", "rZ", "rJ" } },
|
|
||||||
{ INDEX_op_remu_i64, { "r", "rZ", "rJ" } },
|
|
||||||
{ INDEX_op_sub_i64, { "r", "rZ", "rJ" } },
|
{ INDEX_op_sub_i64, { "r", "rZ", "rJ" } },
|
||||||
{ INDEX_op_and_i64, { "r", "rZ", "rJ" } },
|
{ INDEX_op_and_i64, { "r", "rZ", "rJ" } },
|
||||||
{ INDEX_op_andc_i64, { "r", "rZ", "rJ" } },
|
{ INDEX_op_andc_i64, { "r", "rZ", "rJ" } },
|
||||||
@@ -1553,8 +1581,8 @@ static const TCGTargetOpDef sparc_op_defs[] = {
|
|||||||
{ INDEX_op_neg_i64, { "r", "rJ" } },
|
{ INDEX_op_neg_i64, { "r", "rJ" } },
|
||||||
{ INDEX_op_not_i64, { "r", "rJ" } },
|
{ INDEX_op_not_i64, { "r", "rJ" } },
|
||||||
|
|
||||||
{ INDEX_op_ext32s_i64, { "r", "ri" } },
|
{ INDEX_op_ext32s_i64, { "r", "r" } },
|
||||||
{ INDEX_op_ext32u_i64, { "r", "ri" } },
|
{ INDEX_op_ext32u_i64, { "r", "r" } },
|
||||||
|
|
||||||
{ INDEX_op_brcond_i64, { "rZ", "rJ" } },
|
{ INDEX_op_brcond_i64, { "rZ", "rJ" } },
|
||||||
{ INDEX_op_setcond_i64, { "r", "rZ", "rJ" } },
|
{ INDEX_op_setcond_i64, { "r", "rZ", "rJ" } },
|
||||||
@@ -1562,43 +1590,20 @@ static const TCGTargetOpDef sparc_op_defs[] = {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TCG_TARGET_REG_BITS == 64
|
#if TCG_TARGET_REG_BITS == 64
|
||||||
{ INDEX_op_qemu_ld8u, { "r", "L" } },
|
{ INDEX_op_qemu_ld_i32, { "r", "L" } },
|
||||||
{ INDEX_op_qemu_ld8s, { "r", "L" } },
|
{ INDEX_op_qemu_ld_i64, { "r", "L" } },
|
||||||
{ INDEX_op_qemu_ld16u, { "r", "L" } },
|
{ INDEX_op_qemu_st_i32, { "L", "L" } },
|
||||||
{ INDEX_op_qemu_ld16s, { "r", "L" } },
|
{ INDEX_op_qemu_st_i64, { "L", "L" } },
|
||||||
{ INDEX_op_qemu_ld32, { "r", "L" } },
|
|
||||||
{ INDEX_op_qemu_ld32u, { "r", "L" } },
|
|
||||||
{ INDEX_op_qemu_ld32s, { "r", "L" } },
|
|
||||||
{ INDEX_op_qemu_ld64, { "r", "L" } },
|
|
||||||
|
|
||||||
{ INDEX_op_qemu_st8, { "L", "L" } },
|
|
||||||
{ INDEX_op_qemu_st16, { "L", "L" } },
|
|
||||||
{ INDEX_op_qemu_st32, { "L", "L" } },
|
|
||||||
{ INDEX_op_qemu_st64, { "L", "L" } },
|
|
||||||
#elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
|
#elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
|
||||||
{ INDEX_op_qemu_ld8u, { "r", "L" } },
|
{ INDEX_op_qemu_ld_i32, { "r", "L" } },
|
||||||
{ INDEX_op_qemu_ld8s, { "r", "L" } },
|
{ INDEX_op_qemu_ld_i64, { "r", "r", "L" } },
|
||||||
{ INDEX_op_qemu_ld16u, { "r", "L" } },
|
{ INDEX_op_qemu_st_i32, { "L", "L" } },
|
||||||
{ INDEX_op_qemu_ld16s, { "r", "L" } },
|
{ INDEX_op_qemu_st_i64, { "L", "L", "L" } },
|
||||||
{ INDEX_op_qemu_ld32, { "r", "L" } },
|
|
||||||
{ INDEX_op_qemu_ld64, { "r", "r", "L" } },
|
|
||||||
|
|
||||||
{ INDEX_op_qemu_st8, { "L", "L" } },
|
|
||||||
{ INDEX_op_qemu_st16, { "L", "L" } },
|
|
||||||
{ INDEX_op_qemu_st32, { "L", "L" } },
|
|
||||||
{ INDEX_op_qemu_st64, { "L", "L", "L" } },
|
|
||||||
#else
|
#else
|
||||||
{ INDEX_op_qemu_ld8u, { "r", "L", "L" } },
|
{ INDEX_op_qemu_ld_i32, { "r", "L", "L" } },
|
||||||
{ INDEX_op_qemu_ld8s, { "r", "L", "L" } },
|
{ INDEX_op_qemu_ld_i64, { "L", "L", "L", "L" } },
|
||||||
{ INDEX_op_qemu_ld16u, { "r", "L", "L" } },
|
{ INDEX_op_qemu_st_i32, { "L", "L", "L" } },
|
||||||
{ INDEX_op_qemu_ld16s, { "r", "L", "L" } },
|
{ INDEX_op_qemu_st_i64, { "L", "L", "L", "L" } },
|
||||||
{ INDEX_op_qemu_ld32, { "r", "L", "L" } },
|
|
||||||
{ INDEX_op_qemu_ld64, { "L", "L", "L", "L" } },
|
|
||||||
|
|
||||||
{ INDEX_op_qemu_st8, { "L", "L", "L" } },
|
|
||||||
{ INDEX_op_qemu_st16, { "L", "L", "L" } },
|
|
||||||
{ INDEX_op_qemu_st32, { "L", "L", "L" } },
|
|
||||||
{ INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{ -1 },
|
{ -1 },
|
||||||
@@ -1679,7 +1684,7 @@ static DebugFrame debug_frame = {
|
|||||||
|
|
||||||
void tcg_register_jit(void *buf, size_t buf_size)
|
void tcg_register_jit(void *buf, size_t buf_size)
|
||||||
{
|
{
|
||||||
debug_frame.fde.func_start = (tcg_target_long) buf;
|
debug_frame.fde.func_start = (uintptr_t)buf;
|
||||||
debug_frame.fde.func_len = buf_size;
|
debug_frame.fde.func_len = buf_size;
|
||||||
|
|
||||||
tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
|
tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
|
||||||
@@ -1688,14 +1693,12 @@ void tcg_register_jit(void *buf, size_t buf_size)
|
|||||||
void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
|
void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
|
||||||
{
|
{
|
||||||
uint32_t *ptr = (uint32_t *)jmp_addr;
|
uint32_t *ptr = (uint32_t *)jmp_addr;
|
||||||
tcg_target_long disp = (tcg_target_long)(addr - jmp_addr) >> 2;
|
uintptr_t disp = addr - jmp_addr;
|
||||||
|
|
||||||
/* We can reach the entire address space for 32-bit. For 64-bit
|
/* We can reach the entire address space for 32-bit. For 64-bit
|
||||||
the code_gen_buffer can't be larger than 2GB. */
|
the code_gen_buffer can't be larger than 2GB. */
|
||||||
if (TCG_TARGET_REG_BITS == 64 && !check_fit_tl(disp, 30)) {
|
assert(disp == (int32_t)disp);
|
||||||
tcg_abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
*ptr = CALL | (disp & 0x3fffffff);
|
*ptr = CALL | (uint32_t)disp >> 2;
|
||||||
flush_icache_range(jmp_addr, jmp_addr + 4);
|
flush_icache_range(jmp_addr, jmp_addr + 4);
|
||||||
}
|
}
|
||||||
|
@@ -94,7 +94,7 @@ typedef enum {
|
|||||||
|
|
||||||
/* optional instructions */
|
/* optional instructions */
|
||||||
#define TCG_TARGET_HAS_div_i32 1
|
#define TCG_TARGET_HAS_div_i32 1
|
||||||
#define TCG_TARGET_HAS_rem_i32 1
|
#define TCG_TARGET_HAS_rem_i32 0
|
||||||
#define TCG_TARGET_HAS_rot_i32 0
|
#define TCG_TARGET_HAS_rot_i32 0
|
||||||
#define TCG_TARGET_HAS_ext8s_i32 0
|
#define TCG_TARGET_HAS_ext8s_i32 0
|
||||||
#define TCG_TARGET_HAS_ext16s_i32 0
|
#define TCG_TARGET_HAS_ext16s_i32 0
|
||||||
@@ -120,7 +120,7 @@ typedef enum {
|
|||||||
|
|
||||||
#if TCG_TARGET_REG_BITS == 64
|
#if TCG_TARGET_REG_BITS == 64
|
||||||
#define TCG_TARGET_HAS_div_i64 1
|
#define TCG_TARGET_HAS_div_i64 1
|
||||||
#define TCG_TARGET_HAS_rem_i64 1
|
#define TCG_TARGET_HAS_rem_i64 0
|
||||||
#define TCG_TARGET_HAS_rot_i64 0
|
#define TCG_TARGET_HAS_rot_i64 0
|
||||||
#define TCG_TARGET_HAS_ext8s_i64 0
|
#define TCG_TARGET_HAS_ext8s_i64 0
|
||||||
#define TCG_TARGET_HAS_ext16s_i64 0
|
#define TCG_TARGET_HAS_ext16s_i64 0
|
||||||
@@ -148,7 +148,7 @@ typedef enum {
|
|||||||
#define TCG_TARGET_HAS_mulsh_i64 0
|
#define TCG_TARGET_HAS_mulsh_i64 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TCG_TARGET_HAS_new_ldst 0
|
#define TCG_TARGET_HAS_new_ldst 1
|
||||||
|
|
||||||
#define TCG_AREG0 TCG_REG_I0
|
#define TCG_AREG0 TCG_REG_I0
|
||||||
|
|
||||||
|
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
|
echo
|
||||||
|
|
||||||
_make_test_img -o encryption=on $size
|
_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
|
run_qemu <<EOF
|
||||||
{ "execute": "qmp_capabilities" }
|
{ "execute": "qmp_capabilities" }
|
||||||
{ "execute": "blockdev-add",
|
{ "execute": "blockdev-add",
|
||||||
|
@@ -28,7 +28,7 @@ QMP_VERSION
|
|||||||
=== Encrypted image ===
|
=== Encrypted image ===
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
|
||||||
Testing:
|
Testing: -S
|
||||||
QMP_VERSION
|
QMP_VERSION
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{"error": {"class": "GenericError", "desc": "blockdev-add doesn't support encrypted devices"}}
|
{"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": "ide1-cd0", "tray-open": true}}
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "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
|
*** done
|
||||||
|
@@ -85,6 +85,7 @@
|
|||||||
079 rw auto
|
079 rw auto
|
||||||
081 rw auto
|
081 rw auto
|
||||||
082 rw auto quick
|
082 rw auto quick
|
||||||
085 rw auto quick
|
083 rw auto
|
||||||
|
085 rw auto
|
||||||
086 rw auto quick
|
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 */
|
/* Test path override code */
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include "config-host.h"
|
#include "config-host.h"
|
||||||
#include "iov.c"
|
#include "util/cutils.c"
|
||||||
#include "cutils.c"
|
#include "util/hexdump.c"
|
||||||
#include "path.c"
|
#include "util/iov.c"
|
||||||
#include "trace.c"
|
#include "util/path.c"
|
||||||
|
#include "util/qemu-timer-common.c"
|
||||||
|
#include "trace/control.c"
|
||||||
|
#include "../trace/generated-events.c"
|
||||||
#ifdef CONFIG_TRACE_SIMPLE
|
#ifdef CONFIG_TRACE_SIMPLE
|
||||||
#include "../trace/simple.c"
|
#include "trace/simple.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
15
ui/gtk.c
15
ui/gtk.c
@@ -340,13 +340,17 @@ static void gd_mouse_set(DisplayChangeListener *dcl,
|
|||||||
GdkDeviceManager *mgr;
|
GdkDeviceManager *mgr;
|
||||||
gint x_root, y_root;
|
gint x_root, y_root;
|
||||||
|
|
||||||
|
if (qemu_input_is_absolute()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dpy = gtk_widget_get_display(s->drawing_area);
|
dpy = gtk_widget_get_display(s->drawing_area);
|
||||||
mgr = gdk_display_get_device_manager(dpy);
|
mgr = gdk_display_get_device_manager(dpy);
|
||||||
gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area),
|
gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area),
|
||||||
x, y, &x_root, &y_root);
|
x, y, &x_root, &y_root);
|
||||||
gdk_device_warp(gdk_device_manager_get_client_pointer(mgr),
|
gdk_device_warp(gdk_device_manager_get_client_pointer(mgr),
|
||||||
gtk_widget_get_screen(s->drawing_area),
|
gtk_widget_get_screen(s->drawing_area),
|
||||||
x, y);
|
x_root, y_root);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void gd_mouse_set(DisplayChangeListener *dcl,
|
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);
|
GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
|
||||||
gint x_root, y_root;
|
gint x_root, y_root;
|
||||||
|
|
||||||
|
if (qemu_input_is_absolute()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area),
|
gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area),
|
||||||
x, y, &x_root, &y_root);
|
x, y, &x_root, &y_root);
|
||||||
gdk_display_warp_pointer(gtk_widget_get_display(s->drawing_area),
|
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,
|
.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));
|
GtkDisplayState *s = g_malloc0(sizeof(*s));
|
||||||
char *filename;
|
char *filename;
|
||||||
@@ -1517,6 +1525,9 @@ void gtk_display_init(DisplayState *ds, bool full_screen)
|
|||||||
if (full_screen) {
|
if (full_screen) {
|
||||||
gtk_menu_item_activate(GTK_MENU_ITEM(s->full_screen_item));
|
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);
|
register_displaychangelistener(&s->dcl);
|
||||||
|
|
||||||
|
10
ui/vnc.c
10
ui/vnc.c
@@ -888,7 +888,7 @@ static int vnc_update_client(VncState *vs, int has_dirty, bool sync)
|
|||||||
VncDisplay *vd = vs->vd;
|
VncDisplay *vd = vs->vd;
|
||||||
VncJob *job;
|
VncJob *job;
|
||||||
int y;
|
int y;
|
||||||
int height;
|
int height, width;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
if (vs->output.offset && !vs->audio_cap && !vs->force_update)
|
if (vs->output.offset && !vs->audio_cap && !vs->force_update)
|
||||||
@@ -907,6 +907,7 @@ static int vnc_update_client(VncState *vs, int has_dirty, bool sync)
|
|||||||
job = vnc_job_new(vs);
|
job = vnc_job_new(vs);
|
||||||
|
|
||||||
height = MIN(pixman_image_get_height(vd->server), vs->client_height);
|
height = MIN(pixman_image_get_height(vd->server), vs->client_height);
|
||||||
|
width = MIN(pixman_image_get_width(vd->server), vs->client_width);
|
||||||
|
|
||||||
y = 0;
|
y = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -925,8 +926,11 @@ static int vnc_update_client(VncState *vs, int has_dirty, bool sync)
|
|||||||
VNC_DIRTY_BPL(vs), x);
|
VNC_DIRTY_BPL(vs), x);
|
||||||
bitmap_clear(vs->dirty[y], x, x2 - x);
|
bitmap_clear(vs->dirty[y], x, x2 - x);
|
||||||
h = find_and_clear_dirty_height(vs, y, x, x2, height);
|
h = find_and_clear_dirty_height(vs, y, x, x2, height);
|
||||||
n += vnc_job_add_rect(job, x * VNC_DIRTY_PIXELS_PER_BIT, y,
|
x2 = MIN(x2, width / VNC_DIRTY_PIXELS_PER_BIT);
|
||||||
(x2 - x) * VNC_DIRTY_PIXELS_PER_BIT, h);
|
if (x2 > x) {
|
||||||
|
n += vnc_job_add_rect(job, x * VNC_DIRTY_PIXELS_PER_BIT, y,
|
||||||
|
(x2 - x) * VNC_DIRTY_PIXELS_PER_BIT, h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vnc_job_push(job);
|
vnc_job_push(job);
|
||||||
|
45
vl.c
45
vl.c
@@ -143,6 +143,9 @@ int vga_interface_type = VGA_NONE;
|
|||||||
static int full_screen = 0;
|
static int full_screen = 0;
|
||||||
static int no_frame = 0;
|
static int no_frame = 0;
|
||||||
int no_quit = 0;
|
int no_quit = 0;
|
||||||
|
#ifdef CONFIG_GTK
|
||||||
|
static bool grab_on_hover;
|
||||||
|
#endif
|
||||||
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
|
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
|
||||||
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
|
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
|
||||||
CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
|
CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
|
||||||
@@ -2276,6 +2279,25 @@ static DisplayType select_display(const char *p)
|
|||||||
} else if (strstart(p, "gtk", &opts)) {
|
} else if (strstart(p, "gtk", &opts)) {
|
||||||
#ifdef CONFIG_GTK
|
#ifdef CONFIG_GTK
|
||||||
display = DT_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
|
#else
|
||||||
fprintf(stderr, "GTK support is disabled\n");
|
fprintf(stderr, "GTK support is disabled\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -2651,15 +2673,20 @@ static MachineClass *machine_parse(const char *name)
|
|||||||
if (mc) {
|
if (mc) {
|
||||||
return mc;
|
return mc;
|
||||||
}
|
}
|
||||||
printf("Supported machines are:\n");
|
if (name && !is_help_option(name)) {
|
||||||
for (el = machines; el; el = el->next) {
|
error_report("Unsupported machine type");
|
||||||
MachineClass *mc = el->data;
|
error_printf("Use -machine help to list supported machines!\n");
|
||||||
QEMUMachine *m = mc->qemu_machine;
|
} else {
|
||||||
if (m->alias) {
|
printf("Supported machines are:\n");
|
||||||
printf("%-20s %s (alias of %s)\n", m->alias, m->desc, m->name);
|
for (el = machines; el; el = el->next) {
|
||||||
|
MachineClass *mc = el->data;
|
||||||
|
QEMUMachine *m = mc->qemu_machine;
|
||||||
|
if (m->alias) {
|
||||||
|
printf("%-20s %s (alias of %s)\n", m->alias, m->desc, m->name);
|
||||||
|
}
|
||||||
|
printf("%-20s %s%s\n", m->name, m->desc,
|
||||||
|
m->is_default ? " (default)" : "");
|
||||||
}
|
}
|
||||||
printf("%-20s %s%s\n", m->name, m->desc,
|
|
||||||
m->is_default ? " (default)" : "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_slist_free(machines);
|
g_slist_free(machines);
|
||||||
@@ -4399,7 +4426,7 @@ int main(int argc, char **argv, char **envp)
|
|||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_GTK)
|
#if defined(CONFIG_GTK)
|
||||||
case DT_GTK:
|
case DT_GTK:
|
||||||
gtk_display_init(ds, full_screen);
|
gtk_display_init(ds, full_screen, grab_on_hover);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
Reference in New Issue
Block a user