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*
|
||||
libuser
|
||||
/linux-headers/asm
|
||||
/qga/qapi-generated
|
||||
/qapi-generated
|
||||
/qapi-types.[ch]
|
||||
/qapi-visit.[ch]
|
||||
|
53
.travis.yml
53
.travis.yml
@@ -4,6 +4,12 @@ python:
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
- "irc.oftc.net#qemu"
|
||||
on_success: change
|
||||
on_failure: always
|
||||
env:
|
||||
global:
|
||||
- TEST_CMD="make check"
|
||||
@@ -14,23 +20,23 @@ env:
|
||||
- GUI_PKGS="libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev"
|
||||
- EXTRA_PKGS=""
|
||||
matrix:
|
||||
- TARGETS=alpha-softmmu,alpha-linux-user
|
||||
- TARGETS=arm-softmmu,arm-linux-user
|
||||
- TARGETS=aarch64-softmmu,aarch64-linux-user
|
||||
- TARGETS=cris-softmmu
|
||||
- TARGETS=i386-softmmu,x86_64-softmmu
|
||||
- TARGETS=lm32-softmmu
|
||||
- TARGETS=m68k-softmmu
|
||||
- TARGETS=microblaze-softmmu,microblazeel-softmmu
|
||||
- TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu
|
||||
- TARGETS=moxie-softmmu
|
||||
- TARGETS=or32-softmmu,
|
||||
- TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu
|
||||
- TARGETS=s390x-softmmu
|
||||
- TARGETS=sh4-softmmu,sh4eb-softmmu
|
||||
- TARGETS=sparc-softmmu,sparc64-softmmu
|
||||
- TARGETS=unicore32-softmmu
|
||||
- TARGETS=xtensa-softmmu,xtensaeb-softmmu
|
||||
- TARGETS=alpha-softmmu,alpha-linux-user
|
||||
- TARGETS=arm-softmmu,arm-linux-user
|
||||
- TARGETS=aarch64-softmmu,aarch64-linux-user
|
||||
- TARGETS=cris-softmmu
|
||||
- TARGETS=i386-softmmu,x86_64-softmmu
|
||||
- TARGETS=lm32-softmmu
|
||||
- TARGETS=m68k-softmmu
|
||||
- TARGETS=microblaze-softmmu,microblazeel-softmmu
|
||||
- TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu
|
||||
- TARGETS=moxie-softmmu
|
||||
- TARGETS=or32-softmmu,
|
||||
- TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu
|
||||
- TARGETS=s390x-softmmu
|
||||
- TARGETS=sh4-softmmu,sh4eb-softmmu
|
||||
- TARGETS=sparc-softmmu,sparc64-softmmu
|
||||
- TARGETS=unicore32-softmmu
|
||||
- TARGETS=xtensa-softmmu,xtensaeb-softmmu
|
||||
before_install:
|
||||
- git submodule update --init --recursive
|
||||
- sudo apt-get update -qq
|
||||
@@ -46,6 +52,10 @@ matrix:
|
||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
EXTRA_CONFIG="--enable-debug --enable-tcg-interpreter"
|
||||
compiler: gcc
|
||||
# All the extra -dev packages
|
||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
EXTRA_PKGS="libaio-dev libcap-ng-dev libattr1-dev libbrlapi-dev uuid-dev libusb-1.0.0-dev"
|
||||
compiler: gcc
|
||||
# Currently configure doesn't force --disable-pie
|
||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
EXTRA_CONFIG="--enable-gprof --enable-gcov --disable-pie"
|
||||
@@ -65,8 +75,7 @@ matrix:
|
||||
EXTRA_CONFIG="--enable-trace-backend=ftrace"
|
||||
TEST_CMD=""
|
||||
compiler: gcc
|
||||
# This disabled make check for the ftrace backend which needs more setting up
|
||||
# Currently broken on 12.04 due to mis-packaged liburcu and changed API, will be pulled.
|
||||
#- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
# EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
|
||||
# EXTRA_CONFIG="--enable-trace-backend=ust"
|
||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
|
||||
EXTRA_CONFIG="--enable-trace-backend=ust"
|
||||
compiler: gcc
|
||||
|
5
Makefile
5
Makefile
@@ -265,10 +265,7 @@ clean:
|
||||
# avoid old build problems by removing potentially incorrect old files
|
||||
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
|
||||
rm -f qemu-options.def
|
||||
find . -name '*.[oda]' -type f -exec rm -f {} +
|
||||
find . -name '*.l[oa]' -type f -exec rm -f {} +
|
||||
find . -name '*$(DSOSUF)' -type f -exec rm -f {} +
|
||||
find . -name '*.mo' -type f -exec rm -f {} +
|
||||
find . \( -name '*.l[oa]' -o -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f -exec rm {} +
|
||||
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
|
||||
rm -f fsdev/*.pod
|
||||
rm -rf .libs */.libs
|
||||
|
9
block.c
9
block.c
@@ -1388,12 +1388,19 @@ done:
|
||||
ret = -EINVAL;
|
||||
goto close_and_fail;
|
||||
}
|
||||
QDECREF(options);
|
||||
|
||||
if (!bdrv_key_required(bs)) {
|
||||
bdrv_dev_change_media_cb(bs, true);
|
||||
} else if (!runstate_check(RUN_STATE_PRELAUNCH)
|
||||
&& !runstate_check(RUN_STATE_INMIGRATE)
|
||||
&& !runstate_check(RUN_STATE_PAUSED)) { /* HACK */
|
||||
error_setg(errp,
|
||||
"Guest must be stopped for opening of encrypted image");
|
||||
ret = -EBUSY;
|
||||
goto close_and_fail;
|
||||
}
|
||||
|
||||
QDECREF(options);
|
||||
*pbs = bs;
|
||||
return 0;
|
||||
|
||||
|
@@ -43,6 +43,17 @@ static void nbd_recv_coroutines_enter_all(NbdClientSession *s)
|
||||
}
|
||||
}
|
||||
|
||||
static void nbd_teardown_connection(NbdClientSession *client)
|
||||
{
|
||||
/* finish any pending coroutines */
|
||||
shutdown(client->sock, 2);
|
||||
nbd_recv_coroutines_enter_all(client);
|
||||
|
||||
qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL);
|
||||
closesocket(client->sock);
|
||||
client->sock = -1;
|
||||
}
|
||||
|
||||
static void nbd_reply_ready(void *opaque)
|
||||
{
|
||||
NbdClientSession *s = opaque;
|
||||
@@ -78,7 +89,7 @@ static void nbd_reply_ready(void *opaque)
|
||||
}
|
||||
|
||||
fail:
|
||||
nbd_recv_coroutines_enter_all(s);
|
||||
nbd_teardown_connection(s);
|
||||
}
|
||||
|
||||
static void nbd_restart_write(void *opaque)
|
||||
@@ -324,7 +335,7 @@ int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num,
|
||||
|
||||
}
|
||||
|
||||
static void nbd_teardown_connection(NbdClientSession *client)
|
||||
void nbd_client_session_close(NbdClientSession *client)
|
||||
{
|
||||
struct nbd_request request = {
|
||||
.type = NBD_CMD_DISC,
|
||||
@@ -332,22 +343,14 @@ static void nbd_teardown_connection(NbdClientSession *client)
|
||||
.len = 0
|
||||
};
|
||||
|
||||
nbd_send_request(client->sock, &request);
|
||||
|
||||
/* finish any pending coroutines */
|
||||
shutdown(client->sock, 2);
|
||||
nbd_recv_coroutines_enter_all(client);
|
||||
|
||||
qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL);
|
||||
closesocket(client->sock);
|
||||
client->sock = -1;
|
||||
}
|
||||
|
||||
void nbd_client_session_close(NbdClientSession *client)
|
||||
{
|
||||
if (!client->bs) {
|
||||
return;
|
||||
}
|
||||
if (client->sock == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
nbd_send_request(client->sock, &request);
|
||||
|
||||
nbd_teardown_connection(client);
|
||||
client->bs = NULL;
|
||||
|
@@ -61,7 +61,7 @@
|
||||
/* These structures are ones that are defined in the VHDX specification
|
||||
* document */
|
||||
|
||||
#define VHDX_FILE_SIGNATURE 0x656C696678646876 /* "vhdxfile" in ASCII */
|
||||
#define VHDX_FILE_SIGNATURE 0x656C696678646876ULL /* "vhdxfile" in ASCII */
|
||||
typedef struct VHDXFileIdentifier {
|
||||
uint64_t signature; /* "vhdxfile" in ASCII */
|
||||
uint16_t creator[256]; /* optional; utf-16 string to identify
|
||||
@@ -238,7 +238,7 @@ typedef struct QEMU_PACKED VHDXLogDataSector {
|
||||
/* upper 44 bits are the file offset in 1MB units lower 3 bits are the state
|
||||
other bits are reserved */
|
||||
#define VHDX_BAT_STATE_BIT_MASK 0x07
|
||||
#define VHDX_BAT_FILE_OFF_MASK 0xFFFFFFFFFFF00000 /* upper 44 bits */
|
||||
#define VHDX_BAT_FILE_OFF_MASK 0xFFFFFFFFFFF00000ULL /* upper 44 bits */
|
||||
typedef uint64_t VHDXBatEntry;
|
||||
|
||||
/* ---- METADATA REGION STRUCTURES ---- */
|
||||
@@ -247,7 +247,7 @@ typedef uint64_t VHDXBatEntry;
|
||||
#define VHDX_METADATA_MAX_ENTRIES 2047 /* not including the header */
|
||||
#define VHDX_METADATA_TABLE_MAX_SIZE \
|
||||
(VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1))
|
||||
#define VHDX_METADATA_SIGNATURE 0x617461646174656D /* "metadata" in ASCII */
|
||||
#define VHDX_METADATA_SIGNATURE 0x617461646174656DULL /* "metadata" in ASCII */
|
||||
typedef struct QEMU_PACKED VHDXMetadataTableHeader {
|
||||
uint64_t signature; /* "metadata" in ASCII */
|
||||
uint16_t reserved;
|
||||
|
5
configure
vendored
5
configure
vendored
@@ -3822,6 +3822,11 @@ fi
|
||||
|
||||
int128=no
|
||||
cat > $TMPC << EOF
|
||||
#if defined(__clang_major__) && defined(__clang_minor__)
|
||||
# if ((__clang_major__ < 3) || (__clang_major__ == 3) && (__clang_minor__ < 2))
|
||||
# error __int128_t does not work in CLANG before 3.2
|
||||
# endif
|
||||
#endif
|
||||
__int128_t a;
|
||||
__uint128_t b;
|
||||
int main (void) {
|
||||
|
@@ -223,13 +223,13 @@ static void *cur_chip = NULL; /* current chip point */
|
||||
/* static OPLSAMPLE *bufL,*bufR; */
|
||||
static OPL_CH *S_CH;
|
||||
static OPL_CH *E_CH;
|
||||
OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
|
||||
static OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
|
||||
|
||||
static INT32 outd[1];
|
||||
static INT32 ams;
|
||||
static INT32 vib;
|
||||
INT32 *ams_table;
|
||||
INT32 *vib_table;
|
||||
static INT32 *ams_table;
|
||||
static INT32 *vib_table;
|
||||
static INT32 amsIncr;
|
||||
static INT32 vibIncr;
|
||||
static INT32 feedback2; /* connect for SLOT 2 */
|
||||
|
@@ -41,7 +41,6 @@ typedef struct SCLPConsoleLM {
|
||||
uint32_t write_errors; /* errors writing to char layer */
|
||||
uint32_t length; /* length of byte stream in buffer */
|
||||
uint8_t buf[SIZE_CONSOLE_BUFFER];
|
||||
qemu_irq irq_console_read;
|
||||
} SCLPConsoleLM;
|
||||
|
||||
/*
|
||||
@@ -68,13 +67,15 @@ static int chr_can_read(void *opaque)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void receive_from_chr_layer(SCLPConsoleLM *scon, const uint8_t *buf,
|
||||
int size)
|
||||
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
||||
{
|
||||
SCLPConsoleLM *scon = opaque;
|
||||
|
||||
assert(size == 1);
|
||||
|
||||
if (*buf == '\r' || *buf == '\n') {
|
||||
scon->event.event_pending = true;
|
||||
sclp_service_interrupt(0);
|
||||
return;
|
||||
}
|
||||
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 */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void trigger_console_data(void *opaque, int n, int level)
|
||||
{
|
||||
sclp_service_interrupt(0);
|
||||
}
|
||||
|
||||
/* functions for live migration */
|
||||
|
||||
static const VMStateDescription vmstate_sclplmconsole = {
|
||||
@@ -338,7 +320,6 @@ static int console_init(SCLPEvent *event)
|
||||
if (scon->chr) {
|
||||
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;
|
||||
}
|
||||
|
@@ -36,7 +36,6 @@ typedef struct SCLPConsole {
|
||||
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_sclp_rest; /* length of byte stream not read via SCLP */
|
||||
qemu_irq irq_read_vt220;
|
||||
} SCLPConsole;
|
||||
|
||||
/* character layer call-back functions */
|
||||
@@ -49,11 +48,12 @@ static int chr_can_read(void *opaque)
|
||||
return SIZE_BUFFER_VT220 - scon->iov_data_len;
|
||||
}
|
||||
|
||||
/* Receive n bytes from character layer, save in iov buffer,
|
||||
* and set event pending */
|
||||
static void receive_from_chr_layer(SCLPConsole *scon, const uint8_t *buf,
|
||||
int size)
|
||||
/* 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);
|
||||
/* read data must fit into current buffer */
|
||||
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_bs += size;
|
||||
scon->event.event_pending = true;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
sclp_service_interrupt(0);
|
||||
}
|
||||
|
||||
/* functions to be called by event facility */
|
||||
@@ -192,11 +181,6 @@ static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void trigger_ascii_console_data(void *opaque, int n, int level)
|
||||
{
|
||||
sclp_service_interrupt(0);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_sclpconsole = {
|
||||
.name = "sclpconsole",
|
||||
.version_id = 0,
|
||||
@@ -232,8 +216,6 @@ static int console_init(SCLPEvent *event)
|
||||
qemu_chr_add_handlers(scon->chr, chr_can_read,
|
||||
chr_read, NULL, scon);
|
||||
}
|
||||
scon->irq_read_vt220 = *qemu_allocate_irqs(trigger_ascii_console_data,
|
||||
NULL, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include "hw/loader.h"
|
||||
#include "trace.h"
|
||||
#include "ui/console.h"
|
||||
#include "ui/vnc.h"
|
||||
#include "hw/pci/pci.h"
|
||||
|
||||
#undef VERBOSE
|
||||
@@ -218,7 +219,7 @@ enum {
|
||||
|
||||
/* These values can probably be changed arbitrarily. */
|
||||
#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
|
||||
|
||||
#ifdef VERBOSE
|
||||
|
@@ -148,7 +148,7 @@ typedef void (*vgic_translate_fn)(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel);
|
||||
|
||||
/* synthetic translate function used for clear/set registers to completely
|
||||
* clear a setting using a clear-register before setting the remaing bits
|
||||
* clear a setting using a clear-register before setting the remaining bits
|
||||
* using a set-register */
|
||||
static void translate_clear(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel)
|
||||
|
@@ -195,8 +195,8 @@ static void process_tx_fcb(eTSEC *etsec)
|
||||
|
||||
/* if packet is IP4 and IP checksum is requested */
|
||||
if (flags & FCB_TX_IP && flags & FCB_TX_CIP) {
|
||||
/* do IP4 checksum (TODO This funtion does TCP/UDP checksum but not sure
|
||||
* if it also does IP4 checksum. */
|
||||
/* do IP4 checksum (TODO This function does TCP/UDP checksum
|
||||
* but not sure if it also does IP4 checksum.) */
|
||||
net_checksum_calculate(etsec->tx_buffer + 8,
|
||||
etsec->tx_buffer_len - 8);
|
||||
}
|
||||
@@ -592,7 +592,7 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
|
||||
|
||||
/* TODO: Broadcast and Multicast */
|
||||
|
||||
if (bd.flags | BD_INTERRUPT) {
|
||||
if (bd.flags & BD_INTERRUPT) {
|
||||
/* Set RXFx */
|
||||
etsec->regs[RSTAT].value |= 1 << (7 - ring_nbr);
|
||||
|
||||
@@ -601,7 +601,7 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
|
||||
}
|
||||
|
||||
} else {
|
||||
if (bd.flags | BD_INTERRUPT) {
|
||||
if (bd.flags & BD_INTERRUPT) {
|
||||
/* Set IEVENT */
|
||||
ievent_set(etsec, IEVENT_RXB);
|
||||
}
|
||||
|
@@ -80,7 +80,7 @@ static int s390_ipl_init(SysBusDevice *dev)
|
||||
|
||||
bios_size = load_elf(bios_filename, NULL, NULL, &ipl->start_addr, NULL,
|
||||
NULL, 1, ELF_MACHINE, 0);
|
||||
if (bios_size == -1) {
|
||||
if (bios_size < 0) {
|
||||
bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START,
|
||||
4096);
|
||||
ipl->start_addr = ZIPL_IMAGE_START;
|
||||
|
@@ -25,13 +25,13 @@ typedef struct ConfigMgtData {
|
||||
uint8_t event_qualifier;
|
||||
} 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
|
||||
|
||||
void raise_irq_cpu_hotplug(void)
|
||||
{
|
||||
qemu_irq_raise(irq_cpu_hotplug);
|
||||
qemu_irq_raise(*irq_cpu_hotplug);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
irq_cpu_hotplug = *qemu_allocate_irqs(trigger_signal, event, 1);
|
||||
irq_cpu_hotplug = qemu_allocate_irqs(trigger_signal, event, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -1905,6 +1905,26 @@ static const VMStateInfo vmstate_info_scsi_requests = {
|
||||
.put = put_scsi_requests,
|
||||
};
|
||||
|
||||
static bool scsi_sense_state_needed(void *opaque)
|
||||
{
|
||||
SCSIDevice *s = opaque;
|
||||
|
||||
return s->sense_len > SCSI_SENSE_BUF_SIZE_OLD;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_scsi_sense_state = {
|
||||
.name = "SCSIDevice/sense",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_UINT8_SUB_ARRAY(sense, SCSIDevice,
|
||||
SCSI_SENSE_BUF_SIZE_OLD,
|
||||
SCSI_SENSE_BUF_SIZE - SCSI_SENSE_BUF_SIZE_OLD),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_scsi_device = {
|
||||
.name = "SCSIDevice",
|
||||
.version_id = 1,
|
||||
@@ -1915,7 +1935,7 @@ const VMStateDescription vmstate_scsi_device = {
|
||||
VMSTATE_UINT8(unit_attention.asc, SCSIDevice),
|
||||
VMSTATE_UINT8(unit_attention.ascq, SCSIDevice),
|
||||
VMSTATE_BOOL(sense_is_ua, SCSIDevice),
|
||||
VMSTATE_UINT8_ARRAY(sense, SCSIDevice, SCSI_SENSE_BUF_SIZE),
|
||||
VMSTATE_UINT8_SUB_ARRAY(sense, SCSIDevice, 0, SCSI_SENSE_BUF_SIZE_OLD),
|
||||
VMSTATE_UINT32(sense_len, SCSIDevice),
|
||||
{
|
||||
.name = "requests",
|
||||
@@ -1927,6 +1947,14 @@ const VMStateDescription vmstate_scsi_device = {
|
||||
.offset = 0,
|
||||
},
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (VMStateSubsection []) {
|
||||
{
|
||||
.vmsd = &vmstate_scsi_sense_state,
|
||||
.needed = scsi_sense_state_needed,
|
||||
}, {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -195,9 +195,9 @@ static int vscsi_send_iu(VSCSIState *s, vscsi_req *req,
|
||||
req->crq.s.IU_data_ptr = req->iu.srp.rsp.tag; /* right byte order */
|
||||
|
||||
if (rc == 0) {
|
||||
req->crq.s.status = 0x99; /* Just needs to be non-zero */
|
||||
req->crq.s.status = VIOSRP_OK;
|
||||
} else {
|
||||
req->crq.s.status = 0x00;
|
||||
req->crq.s.status = VIOSRP_ADAPTER_FAIL;
|
||||
}
|
||||
|
||||
rc1 = spapr_vio_send_crq(&s->vdev, req->crq.raw);
|
||||
|
@@ -304,6 +304,8 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
|
||||
size_t resid)
|
||||
{
|
||||
VirtIOSCSIReq *req = r->hba_private;
|
||||
VirtIOSCSI *s = req->dev;
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
|
||||
uint32_t sense_len;
|
||||
|
||||
if (r->io_canceled) {
|
||||
@@ -317,7 +319,7 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
|
||||
} else {
|
||||
req->resp.cmd->resid = 0;
|
||||
sense_len = scsi_req_get_sense(r, req->resp.cmd->sense,
|
||||
VIRTIO_SCSI_SENSE_SIZE);
|
||||
vs->sense_size);
|
||||
req->resp.cmd->sense_len = tswap32(sense_len);
|
||||
}
|
||||
virtio_scsi_complete_req(req);
|
||||
|
@@ -106,9 +106,9 @@ static void grlib_gptimer_enable(GPTimer *timer)
|
||||
/* ptimer is triggered when the counter reach 0 but GPTimer is triggered at
|
||||
underflow. Set count + 1 to simulate the GPTimer behavior. */
|
||||
|
||||
trace_grlib_gptimer_enable(timer->id, timer->counter + 1);
|
||||
trace_grlib_gptimer_enable(timer->id, timer->counter);
|
||||
|
||||
ptimer_set_count(timer->ptimer, timer->counter + 1);
|
||||
ptimer_set_count(timer->ptimer, (uint64_t)timer->counter + 1);
|
||||
ptimer_run(timer->ptimer, 1);
|
||||
}
|
||||
|
||||
|
@@ -31,6 +31,7 @@ typedef struct SCSISense {
|
||||
uint8_t ascq;
|
||||
} SCSISense;
|
||||
|
||||
#define SCSI_SENSE_BUF_SIZE_OLD 96
|
||||
#define SCSI_SENSE_BUF_SIZE 252
|
||||
|
||||
struct SCSICommand {
|
||||
|
@@ -650,6 +650,9 @@ extern const VMStateInfo vmstate_info_bitmap;
|
||||
#define VMSTATE_UINT8_ARRAY(_f, _s, _n) \
|
||||
VMSTATE_UINT8_ARRAY_V(_f, _s, _n, 0)
|
||||
|
||||
#define VMSTATE_UINT8_SUB_ARRAY(_f, _s, _start, _num) \
|
||||
VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint8, uint8_t)
|
||||
|
||||
#define VMSTATE_UINT8_2DARRAY(_f, _s, _n1, _n2) \
|
||||
VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, 0)
|
||||
|
||||
|
@@ -345,6 +345,6 @@ int index_from_key(const char *key);
|
||||
|
||||
/* gtk.c */
|
||||
void early_gtk_display_init(void);
|
||||
void gtk_display_init(DisplayState *ds, bool full_screen);
|
||||
void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover);
|
||||
|
||||
#endif
|
||||
|
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,
|
||||
&size, &blocksize);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
goto out_socket;
|
||||
}
|
||||
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd < 0) {
|
||||
/* Linux-only, we can use %m in printf. */
|
||||
fprintf(stderr, "Failed to open %s: %m", device);
|
||||
goto out;
|
||||
goto out_socket;
|
||||
}
|
||||
|
||||
ret = nbd_init(fd, sock, nbdflags, size, blocksize);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
goto out_fd;
|
||||
}
|
||||
|
||||
/* update partition table */
|
||||
@@ -316,12 +316,16 @@ static void *nbd_client_thread(void *arg)
|
||||
|
||||
ret = nbd_client(fd);
|
||||
if (ret) {
|
||||
goto out;
|
||||
goto out_fd;
|
||||
}
|
||||
close(fd);
|
||||
kill(getpid(), SIGTERM);
|
||||
return (void *) EXIT_SUCCESS;
|
||||
|
||||
out_fd:
|
||||
close(fd);
|
||||
out_socket:
|
||||
closesocket(sock);
|
||||
out:
|
||||
kill(getpid(), SIGTERM);
|
||||
return (void *) EXIT_FAILURE;
|
||||
@@ -355,6 +359,11 @@ static void nbd_accept(void *opaque)
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
|
||||
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
|
||||
if (fd < 0) {
|
||||
perror("accept");
|
||||
return;
|
||||
}
|
||||
|
||||
if (state >= TERMINATE) {
|
||||
close(fd);
|
||||
return;
|
||||
|
@@ -810,6 +810,7 @@ ETEXI
|
||||
DEF("display", HAS_ARG, QEMU_OPTION_display,
|
||||
"-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
|
||||
" [,window_close=on|off]|curses|none|\n"
|
||||
" gtk[,grab_on_hover=on|off]|\n"
|
||||
" vnc=<display>[,<optargs>]\n"
|
||||
" select display type\n", QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
@@ -833,6 +834,10 @@ graphics card, but its output will not be displayed to the QEMU
|
||||
user. This option differs from the -nographic option in that it
|
||||
only affects what is done with video output; -nographic also changes
|
||||
the destination of the serial and parallel port data.
|
||||
@item gtk
|
||||
Display video output in a GTK window. This interface provides drop-down
|
||||
menus and other UI elements to configure and control the VM during
|
||||
runtime.
|
||||
@item vnc
|
||||
Start a VNC server on display <arg>
|
||||
@end table
|
||||
|
@@ -22,7 +22,9 @@ mech_list: digest-md5
|
||||
# Some older builds of MIT kerberos on Linux ignore this option &
|
||||
# instead need KRB5_KTNAME env var.
|
||||
# For modern Linux, and other OS, this should be sufficient
|
||||
keytab: /etc/qemu/krb5.tab
|
||||
#
|
||||
# There is no default value here, uncomment if you need this
|
||||
#keytab: /etc/qemu/krb5.tab
|
||||
|
||||
# If using digest-md5 for username/passwds, then this is the file
|
||||
# containing the passwds. Use 'saslpasswd2 -a qemu [username]'
|
||||
|
@@ -23,8 +23,8 @@ QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d
|
||||
QEMU_INCLUDES += -I$(<D) -I$(@D)
|
||||
|
||||
maybe-add = $(filter-out $1, $2) $1
|
||||
extract-libs = $(strip $(sort $(foreach o,$1,$($o-libs)) \
|
||||
$(foreach o,$(call expand-objs,$1),$($o-libs))))
|
||||
extract-libs = $(strip $(sort $(foreach o,$1,$($o-libs))) \
|
||||
$(foreach o,$(call expand-objs,$1),$($o-libs)))
|
||||
expand-objs = $(strip $(sort $(filter %.o,$1)) \
|
||||
$(foreach o,$(filter %.mo,$1),$($o-objs)) \
|
||||
$(filter-out %.o %.mo,$1))
|
||||
|
@@ -18,7 +18,7 @@ git clone "${src}" ${destination}
|
||||
pushd ${destination}
|
||||
git checkout "v${version}"
|
||||
git submodule update --init
|
||||
rm -rf .git roms/*/.git
|
||||
rm -rf .git roms/*/.git dtc/.git pixman/.git
|
||||
popd
|
||||
tar cfj ${destination}.tar.bz2 ${destination}
|
||||
rm -rf ${destination}
|
||||
|
@@ -20,6 +20,7 @@ stub-obj-y += mon-set-error.o
|
||||
stub-obj-y += pci-drive-hot-add.o
|
||||
stub-obj-y += qtest.o
|
||||
stub-obj-y += reset.o
|
||||
stub-obj-y += runstate-check.o
|
||||
stub-obj-y += set-fd-handler.o
|
||||
stub-obj-y += slirp.o
|
||||
stub-obj-y += sysbus.o
|
||||
|
6
stubs/runstate-check.c
Normal file
6
stubs/runstate-check.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
bool runstate_check(RunState state)
|
||||
{
|
||||
return state == RUN_STATE_PRELAUNCH;
|
||||
}
|
@@ -1927,6 +1927,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
|
||||
else {
|
||||
tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
|
||||
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1991,7 +1992,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
|
||||
} else {
|
||||
if (islit)
|
||||
tcg_gen_movi_i64(cpu_ir[rc], -lit);
|
||||
else
|
||||
else {
|
||||
tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
|
||||
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)
|
||||
{
|
||||
/* Perfomance monitor registers user accessibility is controlled
|
||||
/* Performance monitor registers user accessibility is controlled
|
||||
* by PMUSERENR.
|
||||
*/
|
||||
if (arm_current_pl(env) == 0 && !env->cp15.c9_pmuserenr) {
|
||||
|
@@ -2216,7 +2216,7 @@ static int bcd_cmp_mag(ppc_avr_t *a, ppc_avr_t *b)
|
||||
uint8_t dig_a = bcd_get_digit(a, i, &invalid);
|
||||
uint8_t dig_b = bcd_get_digit(b, i, &invalid);
|
||||
if (unlikely(invalid)) {
|
||||
return 0; /* doesnt matter */
|
||||
return 0; /* doesn't matter */
|
||||
} else if (dig_a > dig_b) {
|
||||
return 1;
|
||||
} else if (dig_a < dig_b) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -39,33 +39,33 @@ typedef enum {
|
||||
#define TCG_TARGET_CALL_STACK_OFFSET 0
|
||||
|
||||
/* optional instructions */
|
||||
#define TCG_TARGET_HAS_div_i32 0
|
||||
#define TCG_TARGET_HAS_rem_i32 0
|
||||
#define TCG_TARGET_HAS_div_i32 1
|
||||
#define TCG_TARGET_HAS_rem_i32 1
|
||||
#define TCG_TARGET_HAS_ext8s_i32 1
|
||||
#define TCG_TARGET_HAS_ext16s_i32 1
|
||||
#define TCG_TARGET_HAS_ext8u_i32 1
|
||||
#define TCG_TARGET_HAS_ext16u_i32 1
|
||||
#define TCG_TARGET_HAS_bswap16_i32 1
|
||||
#define TCG_TARGET_HAS_bswap32_i32 1
|
||||
#define TCG_TARGET_HAS_not_i32 0
|
||||
#define TCG_TARGET_HAS_neg_i32 0
|
||||
#define TCG_TARGET_HAS_not_i32 1
|
||||
#define TCG_TARGET_HAS_neg_i32 1
|
||||
#define TCG_TARGET_HAS_rot_i32 1
|
||||
#define TCG_TARGET_HAS_andc_i32 0
|
||||
#define TCG_TARGET_HAS_orc_i32 0
|
||||
#define TCG_TARGET_HAS_eqv_i32 0
|
||||
#define TCG_TARGET_HAS_andc_i32 1
|
||||
#define TCG_TARGET_HAS_orc_i32 1
|
||||
#define TCG_TARGET_HAS_eqv_i32 1
|
||||
#define TCG_TARGET_HAS_nand_i32 0
|
||||
#define TCG_TARGET_HAS_nor_i32 0
|
||||
#define TCG_TARGET_HAS_deposit_i32 0
|
||||
#define TCG_TARGET_HAS_movcond_i32 0
|
||||
#define TCG_TARGET_HAS_add2_i32 0
|
||||
#define TCG_TARGET_HAS_sub2_i32 0
|
||||
#define TCG_TARGET_HAS_deposit_i32 1
|
||||
#define TCG_TARGET_HAS_movcond_i32 1
|
||||
#define TCG_TARGET_HAS_add2_i32 1
|
||||
#define TCG_TARGET_HAS_sub2_i32 1
|
||||
#define TCG_TARGET_HAS_mulu2_i32 0
|
||||
#define TCG_TARGET_HAS_muls2_i32 0
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
|
||||
#define TCG_TARGET_HAS_div_i64 0
|
||||
#define TCG_TARGET_HAS_rem_i64 0
|
||||
#define TCG_TARGET_HAS_div_i64 1
|
||||
#define TCG_TARGET_HAS_rem_i64 1
|
||||
#define TCG_TARGET_HAS_ext8s_i64 1
|
||||
#define TCG_TARGET_HAS_ext16s_i64 1
|
||||
#define TCG_TARGET_HAS_ext32s_i64 1
|
||||
@@ -75,22 +75,22 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_bswap16_i64 1
|
||||
#define TCG_TARGET_HAS_bswap32_i64 1
|
||||
#define TCG_TARGET_HAS_bswap64_i64 1
|
||||
#define TCG_TARGET_HAS_not_i64 0
|
||||
#define TCG_TARGET_HAS_neg_i64 0
|
||||
#define TCG_TARGET_HAS_not_i64 1
|
||||
#define TCG_TARGET_HAS_neg_i64 1
|
||||
#define TCG_TARGET_HAS_rot_i64 1
|
||||
#define TCG_TARGET_HAS_andc_i64 0
|
||||
#define TCG_TARGET_HAS_orc_i64 0
|
||||
#define TCG_TARGET_HAS_eqv_i64 0
|
||||
#define TCG_TARGET_HAS_andc_i64 1
|
||||
#define TCG_TARGET_HAS_orc_i64 1
|
||||
#define TCG_TARGET_HAS_eqv_i64 1
|
||||
#define TCG_TARGET_HAS_nand_i64 0
|
||||
#define TCG_TARGET_HAS_nor_i64 0
|
||||
#define TCG_TARGET_HAS_deposit_i64 0
|
||||
#define TCG_TARGET_HAS_movcond_i64 0
|
||||
#define TCG_TARGET_HAS_add2_i64 0
|
||||
#define TCG_TARGET_HAS_sub2_i64 0
|
||||
#define TCG_TARGET_HAS_deposit_i64 1
|
||||
#define TCG_TARGET_HAS_movcond_i64 1
|
||||
#define TCG_TARGET_HAS_add2_i64 1
|
||||
#define TCG_TARGET_HAS_sub2_i64 1
|
||||
#define TCG_TARGET_HAS_mulu2_i64 0
|
||||
#define TCG_TARGET_HAS_muls2_i64 0
|
||||
#define TCG_TARGET_HAS_muluh_i64 0
|
||||
#define TCG_TARGET_HAS_mulsh_i64 0
|
||||
#define TCG_TARGET_HAS_muluh_i64 1
|
||||
#define TCG_TARGET_HAS_mulsh_i64 1
|
||||
|
||||
enum {
|
||||
TCG_AREG0 = TCG_REG_X19,
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
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_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);
|
||||
}
|
||||
}
|
||||
tcg_target_long hi, lo;
|
||||
|
||||
static inline void tcg_out_movi(TCGContext *s, TCGType type,
|
||||
TCGReg ret, tcg_target_long arg)
|
||||
{
|
||||
/* All 32-bit constants, as well as 64-bit constants with
|
||||
no high bits set go through movi_imm32. */
|
||||
/* A 13-bit constant sign-extended to 64-bits. */
|
||||
if (check_fit_tl(arg, 13)) {
|
||||
tcg_out_movi_imm13(s, ret, arg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* A 32-bit constant, or 32-bit zero-extended to 64-bits. */
|
||||
if (TCG_TARGET_REG_BITS == 32
|
||||
|| type == TCG_TYPE_I32
|
||||
|| (arg & ~(tcg_target_long)0xffffffff) == 0) {
|
||||
tcg_out_movi_imm32(s, ret, arg);
|
||||
} else if (check_fit_tl(arg, 13)) {
|
||||
/* A 13-bit constant sign-extended to 64-bits. */
|
||||
tcg_out_movi_imm13(s, ret, arg);
|
||||
} else if (check_fit_tl(arg, 32)) {
|
||||
/* A 32-bit constant sign-extended to 64-bits. */
|
||||
|| (arg & ~0xffffffffu) == 0) {
|
||||
tcg_out_sethi(s, ret, arg);
|
||||
if (arg & 0x3ff) {
|
||||
tcg_out_arithi(s, ret, ret, arg & 0x3ff, ARITH_OR);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* A 32-bit constant sign-extended to 64-bits. */
|
||||
if (check_fit_tl(arg, 32)) {
|
||||
tcg_out_sethi(s, ret, ~arg);
|
||||
tcg_out_arithi(s, ret, ret, (arg & 0x3ff) | -0x400, ARITH_XOR);
|
||||
} else {
|
||||
tcg_out_movi_imm32(s, ret, arg >> (TCG_TARGET_REG_BITS / 2));
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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_movi_imm32(s, TCG_REG_T2, arg);
|
||||
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));
|
||||
}
|
||||
|
||||
static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
|
||||
tcg_target_long arg)
|
||||
static inline void tcg_out_ld_ptr(TCGContext *s, TCGReg ret, uintptr_t arg)
|
||||
{
|
||||
TCGReg base = TCG_REG_G0;
|
||||
if (!check_fit_tl(arg, 10)) {
|
||||
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)
|
||||
@@ -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,
|
||||
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);
|
||||
}
|
||||
|
||||
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 */
|
||||
static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
{
|
||||
@@ -823,39 +925,22 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
}
|
||||
#endif
|
||||
|
||||
tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I1) |
|
||||
INSN_RS2(TCG_REG_G0));
|
||||
tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I1, 0, JMPL);
|
||||
/* delay slot */
|
||||
tcg_out_nop(s);
|
||||
|
||||
/* No epilogue required. We issue ret + restore directly in the TB. */
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
build_trampolines(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
#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.
|
||||
|
||||
Inputs:
|
||||
ADDRLO_IDX contains the index into ARGS of the low part of the
|
||||
address; the high part of the address is at ADDR_LOW_IDX+1.
|
||||
ADDRLO and ADDRHI contain the possible two parts of the address.
|
||||
|
||||
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
|
||||
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,
|
||||
int s_bits, const TCGArg *args, int which)
|
||||
static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
|
||||
int mem_index, TCGMemOp s_bits, int which)
|
||||
{
|
||||
const int addrlo = args[addrlo_idx];
|
||||
const int r0 = TCG_REG_O0;
|
||||
const int r1 = TCG_REG_O1;
|
||||
const int r2 = TCG_REG_O2;
|
||||
int addr = addrlo;
|
||||
const TCGReg r0 = TCG_REG_O0;
|
||||
const TCGReg r1 = TCG_REG_O1;
|
||||
const TCGReg r2 = TCG_REG_O2;
|
||||
TCGReg addr = addrlo;
|
||||
int tlb_ofs;
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
|
||||
/* Assemble the 64-bit address in R0. */
|
||||
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);
|
||||
addr = r0;
|
||||
}
|
||||
|
||||
/* Shift the page number down to tlb-entry. */
|
||||
tcg_out_arithi(s, r1, addrlo,
|
||||
TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, SHIFT_SRL);
|
||||
/* Shift the page number down. */
|
||||
tcg_out_arithi(s, r1, addrlo, TARGET_PAGE_BITS, SHIFT_SRL);
|
||||
|
||||
/* 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. */
|
||||
tcg_out_andi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
|
||||
/* Mask the tlb index. */
|
||||
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. */
|
||||
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. */
|
||||
tlb_ofs = offsetof(CPUArchState, tlb_table[mem_index][0]);
|
||||
if (!check_fit_tl(tlb_ofs + sizeof(CPUTLBEntry), 13)) {
|
||||
tcg_out_addi(s, r1, tlb_ofs);
|
||||
tlb_ofs = 0;
|
||||
tcg_out_addi(s, r1, tlb_ofs & ~0x3ff);
|
||||
tlb_ofs &= 0x3ff;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
||||
static const int qemu_ld_opc[8] = {
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
LDUB, LDUH, LDUW, LDX, LDSB, LDSH, LDSW, LDX
|
||||
#else
|
||||
LDUB, LDUH_LE, LDUW_LE, LDX_LE, LDSB, LDSH_LE, LDSW_LE, LDX_LE
|
||||
#endif
|
||||
static const int qemu_ld_opc[16] = {
|
||||
[MO_UB] = LDUB,
|
||||
[MO_SB] = LDSB,
|
||||
|
||||
[MO_BEUW] = LDUH,
|
||||
[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] = {
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
STB, STH, STW, STX
|
||||
#else
|
||||
STB, STH_LE, STW_LE, STX_LE
|
||||
#endif
|
||||
static const int qemu_st_opc[16] = {
|
||||
[MO_UB] = STB,
|
||||
|
||||
[MO_BEUW] = STH,
|
||||
[MO_BEUL] = STW,
|
||||
[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)
|
||||
int memi_idx, memi, s_bits, n;
|
||||
TCGReg addrz, param;
|
||||
uintptr_t func;
|
||||
int memi;
|
||||
uint32_t *label_ptr[2];
|
||||
#endif
|
||||
|
||||
datahi = datalo = args[0];
|
||||
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
|
||||
datahi = args[1];
|
||||
addrlo_idx = 2;
|
||||
}
|
||||
datalo = *args++;
|
||||
datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0);
|
||||
addrlo = *args++;
|
||||
addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
|
||||
memop = *args++;
|
||||
s_bits = memop & MO_SIZE;
|
||||
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
memi_idx = addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS);
|
||||
memi = args[memi_idx];
|
||||
s_bits = sizeop & 3;
|
||||
memi = *args++;
|
||||
addrz = tcg_out_tlb_load(s, addrlo, addrhi, memi, s_bits,
|
||||
offsetof(CPUTLBEntry, addr_read));
|
||||
|
||||
addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, s_bits, args,
|
||||
offsetof(CPUTLBEntry, addr_read));
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
|
||||
if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
|
||||
int reg64;
|
||||
|
||||
/* bne,pn %[xi]cc, label0 */
|
||||
label_ptr[0] = (uint32_t *)s->code_ptr;
|
||||
tcg_out_bpcc0(s, COND_NE, BPCC_PN
|
||||
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
|
||||
tcg_out_nop(s);
|
||||
|
||||
/* TLB Hit. */
|
||||
/* Load all 64-bits into an O/G register. */
|
||||
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. */
|
||||
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
|
||||
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
|
||||
/* 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. */
|
||||
@@ -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 -
|
||||
(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) {
|
||||
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
|
||||
args[addrlo_idx + 1]);
|
||||
tcg_out_mov(s, TCG_TYPE_REG, param++, addrhi);
|
||||
}
|
||||
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
|
||||
args[addrlo_idx]);
|
||||
tcg_out_mov(s, TCG_TYPE_REG, param++, addrlo);
|
||||
|
||||
/* qemu_ld_helper[s_bits](arg0, arg1) */
|
||||
tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits]
|
||||
- (tcg_target_ulong)s->code_ptr) >> 2)
|
||||
& 0x3fffffff));
|
||||
/* We use the helpers to extend SB and SW data, leaving the case
|
||||
of SL needing explicit extending below. */
|
||||
if ((memop & ~MO_BSWAP) == MO_SL) {
|
||||
func = qemu_ld_trampoline[memop & ~MO_SIGN];
|
||||
} else {
|
||||
func = qemu_ld_trampoline[memop];
|
||||
}
|
||||
assert(func != 0);
|
||||
tcg_out_calli(s, func);
|
||||
/* 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];
|
||||
/* datalo = sign_extend(arg0) */
|
||||
switch (sizeop) {
|
||||
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);
|
||||
switch (memop & ~MO_BSWAP) {
|
||||
case MO_SL:
|
||||
tcg_out_arithi(s, datalo, TCG_REG_O0, 0, SHIFT_SRA);
|
||||
break;
|
||||
case 1 | 4:
|
||||
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:
|
||||
case MO_Q:
|
||||
if (TCG_TARGET_REG_BITS == 32) {
|
||||
tcg_out_mov(s, TCG_TYPE_REG, datahi, n);
|
||||
tcg_out_mov(s, TCG_TYPE_REG, datalo, n + 1);
|
||||
tcg_out_mov(s, TCG_TYPE_REG, datahi, TCG_REG_O0);
|
||||
tcg_out_mov(s, TCG_TYPE_REG, datalo, TCG_REG_O1);
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
default:
|
||||
/* mov */
|
||||
tcg_out_mov(s, TCG_TYPE_REG, datalo, n);
|
||||
tcg_out_mov(s, TCG_TYPE_REG, datalo, TCG_REG_O0);
|
||||
break;
|
||||
}
|
||||
|
||||
*label_ptr[1] |= INSN_OFF19((unsigned long)s->code_ptr -
|
||||
(unsigned long)label_ptr[1]);
|
||||
#else
|
||||
addr_reg = args[addrlo_idx];
|
||||
if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
|
||||
tcg_out_arithi(s, TCG_REG_T1, addr_reg, 0, SHIFT_SRL);
|
||||
addr_reg = TCG_REG_T1;
|
||||
tcg_out_arithi(s, TCG_REG_T1, addrlo, 0, SHIFT_SRL);
|
||||
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);
|
||||
|
||||
tcg_out_ldst_rr(s, reg64, addr_reg,
|
||||
tcg_out_ldst_rr(s, reg64, addrlo,
|
||||
(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);
|
||||
if (reg64 != datalo) {
|
||||
tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64);
|
||||
}
|
||||
} 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),
|
||||
qemu_ld_opc[sizeop]);
|
||||
qemu_ld_opc[memop]);
|
||||
}
|
||||
#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)
|
||||
int memi_idx, memi, n, datafull;
|
||||
TCGReg addrz, datafull, param;
|
||||
uintptr_t func;
|
||||
int memi;
|
||||
uint32_t *label_ptr;
|
||||
#endif
|
||||
|
||||
datahi = datalo = args[0];
|
||||
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
|
||||
datahi = args[1];
|
||||
addrlo_idx = 2;
|
||||
}
|
||||
datalo = *args++;
|
||||
datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0);
|
||||
addrlo = *args++;
|
||||
addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
|
||||
memop = *args++;
|
||||
s_bits = memop & MO_SIZE;
|
||||
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
memi_idx = addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS);
|
||||
memi = args[memi_idx];
|
||||
|
||||
addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, sizeop, args,
|
||||
offsetof(CPUTLBEntry, addr_write));
|
||||
memi = *args++;
|
||||
addrz = tcg_out_tlb_load(s, addrlo, addrhi, memi, s_bits,
|
||||
offsetof(CPUTLBEntry, addr_write));
|
||||
|
||||
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. */
|
||||
tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL);
|
||||
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
|
||||
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
|
||||
/* 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. */
|
||||
|
||||
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) {
|
||||
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
|
||||
args[addrlo_idx + 1]);
|
||||
tcg_out_mov(s, TCG_TYPE_REG, param++, addrhi);
|
||||
}
|
||||
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
|
||||
args[addrlo_idx]);
|
||||
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
|
||||
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datahi);
|
||||
tcg_out_mov(s, TCG_TYPE_REG, param++, addrlo);
|
||||
if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
|
||||
tcg_out_mov(s, TCG_TYPE_REG, param++, 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) */
|
||||
tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[sizeop]
|
||||
- (tcg_target_ulong)s->code_ptr) >> 2)
|
||||
& 0x3fffffff));
|
||||
func = qemu_st_trampoline[memop];
|
||||
assert(func != 0);
|
||||
tcg_out_calli(s, func);
|
||||
/* 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 -
|
||||
(unsigned long)label_ptr);
|
||||
#else
|
||||
addr_reg = args[addrlo_idx];
|
||||
if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
|
||||
tcg_out_arithi(s, TCG_REG_T1, addr_reg, 0, SHIFT_SRL);
|
||||
addr_reg = TCG_REG_T1;
|
||||
tcg_out_arithi(s, TCG_REG_T1, addrlo, 0, SHIFT_SRL);
|
||||
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_O2, datahi, 32, SHIFT_SLLX);
|
||||
tcg_out_arith(s, TCG_REG_O2, TCG_REG_T1, TCG_REG_O2, ARITH_OR);
|
||||
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),
|
||||
qemu_st_opc[sizeop]);
|
||||
qemu_st_opc[memop]);
|
||||
#endif /* CONFIG_SOFTMMU */
|
||||
}
|
||||
|
||||
@@ -1161,8 +1252,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
|
||||
switch (opc) {
|
||||
case INDEX_op_exit_tb:
|
||||
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) |
|
||||
INSN_IMM13(8));
|
||||
tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, JMPL);
|
||||
tcg_out32(s, RESTORE | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_G0) |
|
||||
INSN_RS2(TCG_REG_G0));
|
||||
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)));
|
||||
} else {
|
||||
/* indirect jump method */
|
||||
tcg_out_ld_ptr(s, TCG_REG_T1,
|
||||
(tcg_target_long)(s->tb_next + args[0]));
|
||||
tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_T1) |
|
||||
INSN_RS2(TCG_REG_G0));
|
||||
tcg_out_ld_ptr(s, TCG_REG_T1, (uintptr_t)(s->tb_next + args[0]));
|
||||
tcg_out_arithi(s, TCG_REG_G0, TCG_REG_T1, 0, JMPL);
|
||||
}
|
||||
tcg_out_nop(s);
|
||||
s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
|
||||
break;
|
||||
case INDEX_op_call:
|
||||
if (const_args[0]) {
|
||||
tcg_out32(s, CALL | ((((tcg_target_ulong)args[0]
|
||||
- (tcg_target_ulong)s->code_ptr) >> 2)
|
||||
& 0x3fffffff));
|
||||
tcg_out_calli(s, args[0]);
|
||||
} else {
|
||||
tcg_out_ld_ptr(s, TCG_REG_T1,
|
||||
(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));
|
||||
tcg_out_arithi(s, TCG_REG_O7, args[0], 0, JMPL);
|
||||
}
|
||||
/* delay slot */
|
||||
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);
|
||||
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:
|
||||
tcg_out_brcond_i32(s, args[2], args[0], args[1], const_args[1],
|
||||
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]);
|
||||
break;
|
||||
|
||||
case INDEX_op_qemu_ld8u:
|
||||
case INDEX_op_qemu_ld_i32:
|
||||
tcg_out_qemu_ld(s, args, 0);
|
||||
break;
|
||||
case INDEX_op_qemu_ld8s:
|
||||
tcg_out_qemu_ld(s, args, 0 | 4);
|
||||
break;
|
||||
case INDEX_op_qemu_ld16u:
|
||||
case INDEX_op_qemu_ld_i64:
|
||||
tcg_out_qemu_ld(s, args, 1);
|
||||
break;
|
||||
case INDEX_op_qemu_ld16s:
|
||||
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:
|
||||
case INDEX_op_qemu_st_i32:
|
||||
tcg_out_qemu_st(s, args, 0);
|
||||
break;
|
||||
case INDEX_op_qemu_st16:
|
||||
case INDEX_op_qemu_st_i64:
|
||||
tcg_out_qemu_st(s, args, 1);
|
||||
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
|
||||
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:
|
||||
c = ARITH_UDIVX;
|
||||
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:
|
||||
if (const_args[1]) {
|
||||
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);
|
||||
}
|
||||
tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRA);
|
||||
break;
|
||||
case INDEX_op_ext32u_i64:
|
||||
if (const_args[1]) {
|
||||
tcg_out_movi_imm32(s, args[0], args[1]);
|
||||
} else {
|
||||
tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRL);
|
||||
}
|
||||
tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRL);
|
||||
break;
|
||||
|
||||
case INDEX_op_brcond_i64:
|
||||
@@ -1489,8 +1521,6 @@ static const TCGTargetOpDef sparc_op_defs[] = {
|
||||
{ INDEX_op_mul_i32, { "r", "rZ", "rJ" } },
|
||||
{ INDEX_op_div_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_and_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_div_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_and_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_not_i64, { "r", "rJ" } },
|
||||
|
||||
{ INDEX_op_ext32s_i64, { "r", "ri" } },
|
||||
{ INDEX_op_ext32u_i64, { "r", "ri" } },
|
||||
{ INDEX_op_ext32s_i64, { "r", "r" } },
|
||||
{ INDEX_op_ext32u_i64, { "r", "r" } },
|
||||
|
||||
{ INDEX_op_brcond_i64, { "rZ", "rJ" } },
|
||||
{ INDEX_op_setcond_i64, { "r", "rZ", "rJ" } },
|
||||
@@ -1562,43 +1590,20 @@ static const TCGTargetOpDef sparc_op_defs[] = {
|
||||
#endif
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
{ INDEX_op_qemu_ld8u, { "r", "L" } },
|
||||
{ INDEX_op_qemu_ld8s, { "r", "L" } },
|
||||
{ INDEX_op_qemu_ld16u, { "r", "L" } },
|
||||
{ INDEX_op_qemu_ld16s, { "r", "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" } },
|
||||
{ INDEX_op_qemu_ld_i32, { "r", "L" } },
|
||||
{ INDEX_op_qemu_ld_i64, { "r", "L" } },
|
||||
{ INDEX_op_qemu_st_i32, { "L", "L" } },
|
||||
{ INDEX_op_qemu_st_i64, { "L", "L" } },
|
||||
#elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
|
||||
{ INDEX_op_qemu_ld8u, { "r", "L" } },
|
||||
{ INDEX_op_qemu_ld8s, { "r", "L" } },
|
||||
{ INDEX_op_qemu_ld16u, { "r", "L" } },
|
||||
{ INDEX_op_qemu_ld16s, { "r", "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" } },
|
||||
{ INDEX_op_qemu_ld_i32, { "r", "L" } },
|
||||
{ INDEX_op_qemu_ld_i64, { "r", "r", "L" } },
|
||||
{ INDEX_op_qemu_st_i32, { "L", "L" } },
|
||||
{ INDEX_op_qemu_st_i64, { "L", "L", "L" } },
|
||||
#else
|
||||
{ INDEX_op_qemu_ld8u, { "r", "L", "L" } },
|
||||
{ INDEX_op_qemu_ld8s, { "r", "L", "L" } },
|
||||
{ INDEX_op_qemu_ld16u, { "r", "L", "L" } },
|
||||
{ INDEX_op_qemu_ld16s, { "r", "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" } },
|
||||
{ INDEX_op_qemu_ld_i32, { "r", "L", "L" } },
|
||||
{ INDEX_op_qemu_ld_i64, { "L", "L", "L", "L" } },
|
||||
{ INDEX_op_qemu_st_i32, { "L", "L", "L" } },
|
||||
{ INDEX_op_qemu_st_i64, { "L", "L", "L", "L" } },
|
||||
#endif
|
||||
|
||||
{ -1 },
|
||||
@@ -1679,7 +1684,7 @@ static DebugFrame debug_frame = {
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
the code_gen_buffer can't be larger than 2GB. */
|
||||
if (TCG_TARGET_REG_BITS == 64 && !check_fit_tl(disp, 30)) {
|
||||
tcg_abort();
|
||||
}
|
||||
assert(disp == (int32_t)disp);
|
||||
|
||||
*ptr = CALL | (disp & 0x3fffffff);
|
||||
*ptr = CALL | (uint32_t)disp >> 2;
|
||||
flush_icache_range(jmp_addr, jmp_addr + 4);
|
||||
}
|
||||
|
@@ -94,7 +94,7 @@ typedef enum {
|
||||
|
||||
/* optional instructions */
|
||||
#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_ext8s_i32 0
|
||||
#define TCG_TARGET_HAS_ext16s_i32 0
|
||||
@@ -120,7 +120,7 @@ typedef enum {
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
#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_ext8s_i64 0
|
||||
#define TCG_TARGET_HAS_ext16s_i64 0
|
||||
@@ -148,7 +148,7 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_mulsh_i64 0
|
||||
#endif
|
||||
|
||||
#define TCG_TARGET_HAS_new_ldst 0
|
||||
#define TCG_TARGET_HAS_new_ldst 1
|
||||
|
||||
#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
|
||||
|
||||
_make_test_img -o encryption=on $size
|
||||
run_qemu -S <<EOF
|
||||
{ "execute": "qmp_capabilities" }
|
||||
{ "execute": "blockdev-add",
|
||||
"arguments": {
|
||||
"options": {
|
||||
"driver": "$IMGFMT",
|
||||
"id": "disk",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_IMG"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{ "execute": "quit" }
|
||||
EOF
|
||||
|
||||
run_qemu <<EOF
|
||||
{ "execute": "qmp_capabilities" }
|
||||
{ "execute": "blockdev-add",
|
||||
|
@@ -28,7 +28,7 @@ QMP_VERSION
|
||||
=== Encrypted image ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
|
||||
Testing:
|
||||
Testing: -S
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "blockdev-add doesn't support encrypted devices"}}
|
||||
@@ -37,4 +37,13 @@ QMP_VERSION
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
|
||||
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "could not open disk image disk: Guest must be stopped for opening of encrypted image"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
|
||||
|
||||
*** done
|
||||
|
@@ -85,6 +85,7 @@
|
||||
079 rw auto
|
||||
081 rw auto
|
||||
082 rw auto quick
|
||||
085 rw auto quick
|
||||
083 rw auto
|
||||
085 rw auto
|
||||
086 rw auto quick
|
||||
087 rw auto quick
|
||||
087 rw auto
|
||||
|
264
tests/qemu-iotests/nbd-fault-injector.py
Executable file
264
tests/qemu-iotests/nbd-fault-injector.py
Executable file
@@ -0,0 +1,264 @@
|
||||
#!/usr/bin/env python
|
||||
# NBD server - fault injection utility
|
||||
#
|
||||
# Configuration file syntax:
|
||||
# [inject-error "disconnect-neg1"]
|
||||
# event=neg1
|
||||
# io=readwrite
|
||||
# when=before
|
||||
#
|
||||
# Note that Python's ConfigParser squashes together all sections with the same
|
||||
# name, so give each [inject-error] a unique name.
|
||||
#
|
||||
# inject-error options:
|
||||
# event - name of the trigger event
|
||||
# "neg1" - first part of negotiation struct
|
||||
# "export" - export struct
|
||||
# "neg2" - second part of negotiation struct
|
||||
# "request" - NBD request struct
|
||||
# "reply" - NBD reply struct
|
||||
# "data" - request/reply data
|
||||
# io - I/O direction that triggers this rule:
|
||||
# "read", "write", or "readwrite"
|
||||
# default: readwrite
|
||||
# when - after how many bytes to inject the fault
|
||||
# -1 - inject error after I/O
|
||||
# 0 - inject error before I/O
|
||||
# integer - inject error after integer bytes
|
||||
# "before" - alias for 0
|
||||
# "after" - alias for -1
|
||||
# default: before
|
||||
#
|
||||
# Currently the only error injection action is to terminate the server process.
|
||||
# This resets the TCP connection and thus forces the client to handle
|
||||
# unexpected connection termination.
|
||||
#
|
||||
# Other error injection actions could be added in the future.
|
||||
#
|
||||
# Copyright Red Hat, Inc. 2014
|
||||
#
|
||||
# Authors:
|
||||
# Stefan Hajnoczi <stefanha@redhat.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
# See the COPYING file in the top-level directory.
|
||||
|
||||
import sys
|
||||
import socket
|
||||
import struct
|
||||
import collections
|
||||
import ConfigParser
|
||||
|
||||
FAKE_DISK_SIZE = 8 * 1024 * 1024 * 1024 # 8 GB
|
||||
|
||||
# Protocol constants
|
||||
NBD_CMD_READ = 0
|
||||
NBD_CMD_WRITE = 1
|
||||
NBD_CMD_DISC = 2
|
||||
NBD_REQUEST_MAGIC = 0x25609513
|
||||
NBD_REPLY_MAGIC = 0x67446698
|
||||
NBD_PASSWD = 0x4e42444d41474943
|
||||
NBD_OPTS_MAGIC = 0x49484156454F5054
|
||||
NBD_CLIENT_MAGIC = 0x0000420281861253
|
||||
NBD_OPT_EXPORT_NAME = 1 << 0
|
||||
|
||||
# Protocol structs
|
||||
neg_classic_struct = struct.Struct('>QQQI124x')
|
||||
neg1_struct = struct.Struct('>QQH')
|
||||
export_tuple = collections.namedtuple('Export', 'reserved magic opt len')
|
||||
export_struct = struct.Struct('>IQII')
|
||||
neg2_struct = struct.Struct('>QH124x')
|
||||
request_tuple = collections.namedtuple('Request', 'magic type handle from_ len')
|
||||
request_struct = struct.Struct('>IIQQI')
|
||||
reply_struct = struct.Struct('>IIQ')
|
||||
|
||||
def err(msg):
|
||||
sys.stderr.write(msg + '\n')
|
||||
sys.exit(1)
|
||||
|
||||
def recvall(sock, bufsize):
|
||||
received = 0
|
||||
chunks = []
|
||||
while received < bufsize:
|
||||
chunk = sock.recv(bufsize - received)
|
||||
if len(chunk) == 0:
|
||||
raise Exception('unexpected disconnect')
|
||||
chunks.append(chunk)
|
||||
received += len(chunk)
|
||||
return ''.join(chunks)
|
||||
|
||||
class Rule(object):
|
||||
def __init__(self, name, event, io, when):
|
||||
self.name = name
|
||||
self.event = event
|
||||
self.io = io
|
||||
self.when = when
|
||||
|
||||
def match(self, event, io):
|
||||
if event != self.event:
|
||||
return False
|
||||
if io != self.io and self.io != 'readwrite':
|
||||
return False
|
||||
return True
|
||||
|
||||
class FaultInjectionSocket(object):
|
||||
def __init__(self, sock, rules):
|
||||
self.sock = sock
|
||||
self.rules = rules
|
||||
|
||||
def check(self, event, io, bufsize=None):
|
||||
for rule in self.rules:
|
||||
if rule.match(event, io):
|
||||
if rule.when == 0 or bufsize is None:
|
||||
print 'Closing connection on rule match %s' % rule.name
|
||||
sys.exit(0)
|
||||
if rule.when != -1:
|
||||
return rule.when
|
||||
return bufsize
|
||||
|
||||
def send(self, buf, event):
|
||||
bufsize = self.check(event, 'write', bufsize=len(buf))
|
||||
self.sock.sendall(buf[:bufsize])
|
||||
self.check(event, 'write')
|
||||
|
||||
def recv(self, bufsize, event):
|
||||
bufsize = self.check(event, 'read', bufsize=bufsize)
|
||||
data = recvall(self.sock, bufsize)
|
||||
self.check(event, 'read')
|
||||
return data
|
||||
|
||||
def close(self):
|
||||
self.sock.close()
|
||||
|
||||
def negotiate_classic(conn):
|
||||
buf = neg_classic_struct.pack(NBD_PASSWD, NBD_CLIENT_MAGIC,
|
||||
FAKE_DISK_SIZE, 0)
|
||||
conn.send(buf, event='neg-classic')
|
||||
|
||||
def negotiate_export(conn):
|
||||
# Send negotiation part 1
|
||||
buf = neg1_struct.pack(NBD_PASSWD, NBD_OPTS_MAGIC, 0)
|
||||
conn.send(buf, event='neg1')
|
||||
|
||||
# Receive export option
|
||||
buf = conn.recv(export_struct.size, event='export')
|
||||
export = export_tuple._make(export_struct.unpack(buf))
|
||||
assert export.magic == NBD_OPTS_MAGIC
|
||||
assert export.opt == NBD_OPT_EXPORT_NAME
|
||||
name = conn.recv(export.len, event='export-name')
|
||||
|
||||
# Send negotiation part 2
|
||||
buf = neg2_struct.pack(FAKE_DISK_SIZE, 0)
|
||||
conn.send(buf, event='neg2')
|
||||
|
||||
def negotiate(conn, use_export):
|
||||
'''Negotiate export with client'''
|
||||
if use_export:
|
||||
negotiate_export(conn)
|
||||
else:
|
||||
negotiate_classic(conn)
|
||||
|
||||
def read_request(conn):
|
||||
'''Parse NBD request from client'''
|
||||
buf = conn.recv(request_struct.size, event='request')
|
||||
req = request_tuple._make(request_struct.unpack(buf))
|
||||
assert req.magic == NBD_REQUEST_MAGIC
|
||||
return req
|
||||
|
||||
def write_reply(conn, error, handle):
|
||||
buf = reply_struct.pack(NBD_REPLY_MAGIC, error, handle)
|
||||
conn.send(buf, event='reply')
|
||||
|
||||
def handle_connection(conn, use_export):
|
||||
negotiate(conn, use_export)
|
||||
while True:
|
||||
req = read_request(conn)
|
||||
if req.type == NBD_CMD_READ:
|
||||
write_reply(conn, 0, req.handle)
|
||||
conn.send('\0' * req.len, event='data')
|
||||
elif req.type == NBD_CMD_WRITE:
|
||||
_ = conn.recv(req.len, event='data')
|
||||
write_reply(conn, 0, req.handle)
|
||||
elif req.type == NBD_CMD_DISC:
|
||||
break
|
||||
else:
|
||||
print 'unrecognized command type %#02x' % req.type
|
||||
break
|
||||
conn.close()
|
||||
|
||||
def run_server(sock, rules, use_export):
|
||||
while True:
|
||||
conn, _ = sock.accept()
|
||||
handle_connection(FaultInjectionSocket(conn, rules), use_export)
|
||||
|
||||
def parse_inject_error(name, options):
|
||||
if 'event' not in options:
|
||||
err('missing \"event\" option in %s' % name)
|
||||
event = options['event']
|
||||
if event not in ('neg-classic', 'neg1', 'export', 'neg2', 'request', 'reply', 'data'):
|
||||
err('invalid \"event\" option value \"%s\" in %s' % (event, name))
|
||||
io = options.get('io', 'readwrite')
|
||||
if io not in ('read', 'write', 'readwrite'):
|
||||
err('invalid \"io\" option value \"%s\" in %s' % (io, name))
|
||||
when = options.get('when', 'before')
|
||||
try:
|
||||
when = int(when)
|
||||
except ValueError:
|
||||
if when == 'before':
|
||||
when = 0
|
||||
elif when == 'after':
|
||||
when = -1
|
||||
else:
|
||||
err('invalid \"when\" option value \"%s\" in %s' % (when, name))
|
||||
return Rule(name, event, io, when)
|
||||
|
||||
def parse_config(config):
|
||||
rules = []
|
||||
for name in config.sections():
|
||||
if name.startswith('inject-error'):
|
||||
options = dict(config.items(name))
|
||||
rules.append(parse_inject_error(name, options))
|
||||
else:
|
||||
err('invalid config section name: %s' % name)
|
||||
return rules
|
||||
|
||||
def load_rules(filename):
|
||||
config = ConfigParser.RawConfigParser()
|
||||
with open(filename, 'rt') as f:
|
||||
config.readfp(f, filename)
|
||||
return parse_config(config)
|
||||
|
||||
def open_socket(path):
|
||||
'''Open a TCP or UNIX domain listen socket'''
|
||||
if ':' in path:
|
||||
host, port = path.split(':', 1)
|
||||
sock = socket.socket()
|
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
sock.bind((host, int(port)))
|
||||
else:
|
||||
sock = socket.socket(socket.AF_UNIX)
|
||||
sock.bind(path)
|
||||
sock.listen(0)
|
||||
print 'Listening on %s' % path
|
||||
return sock
|
||||
|
||||
def usage(args):
|
||||
sys.stderr.write('usage: %s [--classic-negotiation] <tcp-port>|<unix-path> <config-file>\n' % args[0])
|
||||
sys.stderr.write('Run an fault injector NBD server with rules defined in a config file.\n')
|
||||
sys.exit(1)
|
||||
|
||||
def main(args):
|
||||
if len(args) != 3 and len(args) != 4:
|
||||
usage(args)
|
||||
use_export = True
|
||||
if args[1] == '--classic-negotiation':
|
||||
use_export = False
|
||||
elif len(args) == 4:
|
||||
usage(args)
|
||||
sock = open_socket(args[1 if use_export else 2])
|
||||
rules = load_rules(args[2 if use_export else 3])
|
||||
run_server(sock, rules, use_export)
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
@@ -1,12 +1,15 @@
|
||||
/* Test path override code */
|
||||
#define _GNU_SOURCE
|
||||
#include "config-host.h"
|
||||
#include "iov.c"
|
||||
#include "cutils.c"
|
||||
#include "path.c"
|
||||
#include "trace.c"
|
||||
#include "util/cutils.c"
|
||||
#include "util/hexdump.c"
|
||||
#include "util/iov.c"
|
||||
#include "util/path.c"
|
||||
#include "util/qemu-timer-common.c"
|
||||
#include "trace/control.c"
|
||||
#include "../trace/generated-events.c"
|
||||
#ifdef CONFIG_TRACE_SIMPLE
|
||||
#include "../trace/simple.c"
|
||||
#include "trace/simple.c"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
15
ui/gtk.c
15
ui/gtk.c
@@ -340,13 +340,17 @@ static void gd_mouse_set(DisplayChangeListener *dcl,
|
||||
GdkDeviceManager *mgr;
|
||||
gint x_root, y_root;
|
||||
|
||||
if (qemu_input_is_absolute()) {
|
||||
return;
|
||||
}
|
||||
|
||||
dpy = gtk_widget_get_display(s->drawing_area);
|
||||
mgr = gdk_display_get_device_manager(dpy);
|
||||
gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area),
|
||||
x, y, &x_root, &y_root);
|
||||
gdk_device_warp(gdk_device_manager_get_client_pointer(mgr),
|
||||
gtk_widget_get_screen(s->drawing_area),
|
||||
x, y);
|
||||
x_root, y_root);
|
||||
}
|
||||
#else
|
||||
static void gd_mouse_set(DisplayChangeListener *dcl,
|
||||
@@ -355,6 +359,10 @@ static void gd_mouse_set(DisplayChangeListener *dcl,
|
||||
GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
|
||||
gint x_root, y_root;
|
||||
|
||||
if (qemu_input_is_absolute()) {
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area),
|
||||
x, y, &x_root, &y_root);
|
||||
gdk_display_warp_pointer(gtk_widget_get_display(s->drawing_area),
|
||||
@@ -1438,7 +1446,7 @@ static const DisplayChangeListenerOps dcl_ops = {
|
||||
.dpy_cursor_define = gd_cursor_define,
|
||||
};
|
||||
|
||||
void gtk_display_init(DisplayState *ds, bool full_screen)
|
||||
void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
|
||||
{
|
||||
GtkDisplayState *s = g_malloc0(sizeof(*s));
|
||||
char *filename;
|
||||
@@ -1517,6 +1525,9 @@ void gtk_display_init(DisplayState *ds, bool full_screen)
|
||||
if (full_screen) {
|
||||
gtk_menu_item_activate(GTK_MENU_ITEM(s->full_screen_item));
|
||||
}
|
||||
if (grab_on_hover) {
|
||||
gtk_menu_item_activate(GTK_MENU_ITEM(s->grab_on_hover_item));
|
||||
}
|
||||
|
||||
register_displaychangelistener(&s->dcl);
|
||||
|
||||
|
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;
|
||||
VncJob *job;
|
||||
int y;
|
||||
int height;
|
||||
int height, width;
|
||||
int n = 0;
|
||||
|
||||
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);
|
||||
|
||||
height = MIN(pixman_image_get_height(vd->server), vs->client_height);
|
||||
width = MIN(pixman_image_get_width(vd->server), vs->client_width);
|
||||
|
||||
y = 0;
|
||||
for (;;) {
|
||||
@@ -925,8 +926,11 @@ static int vnc_update_client(VncState *vs, int has_dirty, bool sync)
|
||||
VNC_DIRTY_BPL(vs), x);
|
||||
bitmap_clear(vs->dirty[y], x, x2 - x);
|
||||
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 - x) * VNC_DIRTY_PIXELS_PER_BIT, h);
|
||||
x2 = MIN(x2, width / VNC_DIRTY_PIXELS_PER_BIT);
|
||||
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);
|
||||
|
45
vl.c
45
vl.c
@@ -143,6 +143,9 @@ int vga_interface_type = VGA_NONE;
|
||||
static int full_screen = 0;
|
||||
static int no_frame = 0;
|
||||
int no_quit = 0;
|
||||
#ifdef CONFIG_GTK
|
||||
static bool grab_on_hover;
|
||||
#endif
|
||||
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
|
||||
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
|
||||
CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
|
||||
@@ -2276,6 +2279,25 @@ static DisplayType select_display(const char *p)
|
||||
} else if (strstart(p, "gtk", &opts)) {
|
||||
#ifdef CONFIG_GTK
|
||||
display = DT_GTK;
|
||||
while (*opts) {
|
||||
const char *nextopt;
|
||||
|
||||
if (strstart(opts, ",grab_on_hover=", &nextopt)) {
|
||||
opts = nextopt;
|
||||
if (strstart(opts, "on", &nextopt)) {
|
||||
grab_on_hover = true;
|
||||
} else if (strstart(opts, "off", &nextopt)) {
|
||||
grab_on_hover = false;
|
||||
} else {
|
||||
goto invalid_gtk_args;
|
||||
}
|
||||
} else {
|
||||
invalid_gtk_args:
|
||||
fprintf(stderr, "Invalid GTK option string: %s\n", p);
|
||||
exit(1);
|
||||
}
|
||||
opts = nextopt;
|
||||
}
|
||||
#else
|
||||
fprintf(stderr, "GTK support is disabled\n");
|
||||
exit(1);
|
||||
@@ -2651,15 +2673,20 @@ static MachineClass *machine_parse(const char *name)
|
||||
if (mc) {
|
||||
return mc;
|
||||
}
|
||||
printf("Supported machines are:\n");
|
||||
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);
|
||||
if (name && !is_help_option(name)) {
|
||||
error_report("Unsupported machine type");
|
||||
error_printf("Use -machine help to list supported machines!\n");
|
||||
} else {
|
||||
printf("Supported machines are:\n");
|
||||
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);
|
||||
@@ -4399,7 +4426,7 @@ int main(int argc, char **argv, char **envp)
|
||||
#endif
|
||||
#if defined(CONFIG_GTK)
|
||||
case DT_GTK:
|
||||
gtk_display_init(ds, full_screen);
|
||||
gtk_display_init(ds, full_screen, grab_on_hover);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
Reference in New Issue
Block a user