diff options
80 files changed, 4186 insertions, 2916 deletions
diff --git a/Makefile.objs b/Makefile.objs index 5ebbcfa171..309d066286 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -77,6 +77,7 @@ common-obj-y += qemu-char.o #aio.o common-obj-y += block-migration.o iohandler.o common-obj-y += pflib.o common-obj-y += bitmap.o bitops.o +common-obj-y += page_cache.o common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o common-obj-$(CONFIG_WIN32) += version.o @@ -211,6 +212,7 @@ common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y) # qapi qapi-obj-y = qapi/ +qapi-obj-y += qapi-types.o qapi-visit.o common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o common-obj-y += qmp.o hmp.o diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt index 9ba7079589..287805825f 100644 --- a/QMP/qmp-events.txt +++ b/QMP/qmp-events.txt @@ -1,6 +1,23 @@ QEMU Monitor Protocol Events ============================ +BALLOON_CHANGE +-------------- + +Emitted when the guest changes the actual BALLOON level. This +value is equivalent to the 'actual' field return by the +'query-balloon' command + +Data: + +- "actual": actual level of the guest memory balloon in bytes (json-number) + +Example: + +{ "event": "BALLOON_CHANGE", + "data": { "actual": 944766976 }, + "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } + BLOCK_IO_ERROR -------------- @@ -26,6 +43,57 @@ Example: Note: If action is "stop", a STOP event will eventually follow the BLOCK_IO_ERROR event. +BLOCK_JOB_CANCELLED +------------------- + +Emitted when a block job has been cancelled. + +Data: + +- "type": Job type ("stream" for image streaming, json-string) +- "device": Device name (json-string) +- "len": Maximum progress value (json-int) +- "offset": Current progress value (json-int) + On success this is equal to len. + On failure this is less than len. +- "speed": Rate limit, bytes per second (json-int) + +Example: + +{ "event": "BLOCK_JOB_CANCELLED", + "data": { "type": "stream", "device": "virtio-disk0", + "len": 10737418240, "offset": 134217728, + "speed": 0 }, + "timestamp": { "seconds": 1267061043, "microseconds": 959568 } } + +BLOCK_JOB_COMPLETED +------------------- + +Emitted when a block job has completed. + +Data: + +- "type": Job type ("stream" for image streaming, json-string) +- "device": Device name (json-string) +- "len": Maximum progress value (json-int) +- "offset": Current progress value (json-int) + On success this is equal to len. + On failure this is less than len. +- "speed": Rate limit, bytes per second (json-int) +- "error": Error message (json-string, optional) + Only present on failure. This field contains a human-readable + error message. There are no semantics other than that streaming + has failed and clients should not try to interpret the error + string. + +Example: + +{ "event": "BLOCK_JOB_COMPLETED", + "data": { "type": "stream", "device": "virtio-disk0", + "len": 10737418240, "offset": 10737418240, + "speed": 0 }, + "timestamp": { "seconds": 1267061043, "microseconds": 959568 } } + DEVICE_TRAY_MOVED ----------------- @@ -98,6 +166,68 @@ Example: Note: If the command-line option "-no-shutdown" has been specified, a STOP event will eventually follow the SHUTDOWN event. +SPICE_CONNECTED, SPICE_DISCONNECTED +----------------------------------- + +Emitted when a SPICE client connects or disconnects. + +Data: + +- "server": Server information (json-object) + - "host": IP address (json-string) + - "port": port number (json-string) + - "family": address family (json-string, "ipv4" or "ipv6") +- "client": Client information (json-object) + - "host": IP address (json-string) + - "port": port number (json-string) + - "family": address family (json-string, "ipv4" or "ipv6") + +Example: + +{ "timestamp": {"seconds": 1290688046, "microseconds": 388707}, + "event": "SPICE_CONNECTED", + "data": { + "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"}, + "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"} +}} + +SPICE_INITIALIZED +----------------- + +Emitted after initial handshake and authentication takes place (if any) +and the SPICE channel is up'n'running + +Data: + +- "server": Server information (json-object) + - "host": IP address (json-string) + - "port": port number (json-string) + - "family": address family (json-string, "ipv4" or "ipv6") + - "auth": authentication method (json-string, optional) +- "client": Client information (json-object) + - "host": IP address (json-string) + - "port": port number (json-string) + - "family": address family (json-string, "ipv4" or "ipv6") + - "connection-id": spice connection id. All channels with the same id + belong to the same spice session (json-int) + - "channel-type": channel type. "1" is the main control channel, filter for + this one if you want track spice sessions only (json-int) + - "channel-id": channel id. Usually "0", might be different needed when + multiple channels of the same type exist, such as multiple + display channels in a multihead setup (json-int) + - "tls": whevener the channel is encrypted (json-bool) + +Example: + +{ "timestamp": {"seconds": 1290688046, "microseconds": 417172}, + "event": "SPICE_INITIALIZED", + "data": {"server": {"auth": "spice", "port": "5921", + "family": "ipv4", "host": "127.0.0.1"}, + "client": {"port": "49004", "family": "ipv4", "channel-type": 3, + "connection-id": 1804289383, "host": "127.0.0.1", + "channel-id": 0, "tls": true} +}} + STOP ---- @@ -110,6 +240,32 @@ Example: { "event": "STOP", "timestamp": { "seconds": 1267041730, "microseconds": 281295 } } +SUSPEND +------- + +Emitted when guest enters S3 state. + +Data: None. + +Example: + +{ "event": "SUSPEND", + "timestamp": { "seconds": 1344456160, "microseconds": 309119 } } + +SUSPEND_DISK +------------ + +Emitted when the guest makes a request to enter S4 state. + +Data: None. + +Example: + +{ "event": "SUSPEND_DISK", + "timestamp": { "seconds": 1344456160, "microseconds": 309119 } } + +Note: QEMU shuts down when entering S4 state. + VNC_CONNECTED ------------- @@ -200,69 +356,17 @@ Example: "host": "127.0.0.1", "sasl_username": "luiz" } }, "timestamp": { "seconds": 1263475302, "microseconds": 150772 } } -SPICE_CONNECTED, SPICE_DISCONNECTED ------------------------------------ - -Emitted when a SPICE client connects or disconnects. - -Data: - -- "server": Server information (json-object) - - "host": IP address (json-string) - - "port": port number (json-string) - - "family": address family (json-string, "ipv4" or "ipv6") -- "client": Client information (json-object) - - "host": IP address (json-string) - - "port": port number (json-string) - - "family": address family (json-string, "ipv4" or "ipv6") - -Example: - -{ "timestamp": {"seconds": 1290688046, "microseconds": 388707}, - "event": "SPICE_CONNECTED", - "data": { - "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"}, - "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"} -}} - - -SPICE_INITIALIZED ------------------ - -Emitted after initial handshake and authentication takes place (if any) -and the SPICE channel is up'n'running +WAKEUP +------ -Data: +Emitted when the guest has woken up from S3 and is running. -- "server": Server information (json-object) - - "host": IP address (json-string) - - "port": port number (json-string) - - "family": address family (json-string, "ipv4" or "ipv6") - - "auth": authentication method (json-string, optional) -- "client": Client information (json-object) - - "host": IP address (json-string) - - "port": port number (json-string) - - "family": address family (json-string, "ipv4" or "ipv6") - - "connection-id": spice connection id. All channels with the same id - belong to the same spice session (json-int) - - "channel-type": channel type. "1" is the main control channel, filter for - this one if you want track spice sessions only (json-int) - - "channel-id": channel id. Usually "0", might be different needed when - multiple channels of the same type exist, such as multiple - display channels in a multihead setup (json-int) - - "tls": whevener the channel is encrypted (json-bool) +Data: None. Example: -{ "timestamp": {"seconds": 1290688046, "microseconds": 417172}, - "event": "SPICE_INITIALIZED", - "data": {"server": {"auth": "spice", "port": "5921", - "family": "ipv4", "host": "127.0.0.1"}, - "client": {"port": "49004", "family": "ipv4", "channel-type": 3, - "connection-id": 1804289383, "host": "127.0.0.1", - "channel-id": 0, "tls": true} -}} - +{ "event": "WATCHDOG", + "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } WATCHDOG -------- @@ -282,74 +386,3 @@ Example: Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is followed respectively by the RESET, SHUTDOWN, or STOP events. - - -BLOCK_JOB_COMPLETED -------------------- - -Emitted when a block job has completed. - -Data: - -- "type": Job type ("stream" for image streaming, json-string) -- "device": Device name (json-string) -- "len": Maximum progress value (json-int) -- "offset": Current progress value (json-int) - On success this is equal to len. - On failure this is less than len. -- "speed": Rate limit, bytes per second (json-int) -- "error": Error message (json-string, optional) - Only present on failure. This field contains a human-readable - error message. There are no semantics other than that streaming - has failed and clients should not try to interpret the error - string. - -Example: - -{ "event": "BLOCK_JOB_COMPLETED", - "data": { "type": "stream", "device": "virtio-disk0", - "len": 10737418240, "offset": 10737418240, - "speed": 0 }, - "timestamp": { "seconds": 1267061043, "microseconds": 959568 } } - - -BLOCK_JOB_CANCELLED -------------------- - -Emitted when a block job has been cancelled. - -Data: - -- "type": Job type ("stream" for image streaming, json-string) -- "device": Device name (json-string) -- "len": Maximum progress value (json-int) -- "offset": Current progress value (json-int) - On success this is equal to len. - On failure this is less than len. -- "speed": Rate limit, bytes per second (json-int) - -Example: - -{ "event": "BLOCK_JOB_CANCELLED", - "data": { "type": "stream", "device": "virtio-disk0", - "len": 10737418240, "offset": 134217728, - "speed": 0 }, - "timestamp": { "seconds": 1267061043, "microseconds": 959568 } } - - -BALLOON_CHANGE ----------- - -Emitted when the guest changes the actual BALLOON level. This -value is equivalent to the 'actual' field return by the -'query-balloon' command - -Data: - -- "actual": actual level of the guest memory balloon in bytes (json-number) - -Example: - -{ "event": "BALLOON_CHANGE", - "data": { "actual": 944766976 }, - "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } diff --git a/QMP/qmp-spec.txt b/QMP/qmp-spec.txt index 1ba916c9f2..a27789692b 100644 --- a/QMP/qmp-spec.txt +++ b/QMP/qmp-spec.txt @@ -106,14 +106,11 @@ completed because of an error condition. The format is: -{ "error": { "class": json-string, "data": json-object, "desc": json-string }, - "id": json-value } +{ "error": { "class": json-string, "desc": json-string }, "id": json-value } Where, -- The "class" member contains the error class name (eg. "ServiceUnavailable") -- The "data" member contains specific error data and is defined in a - per-command basis, it will be an empty json-object if the error has no data +- The "class" member contains the error class name (eg. "GenericError") - The "desc" member is a human-readable error message. Clients should not attempt to parse this message. - The "id" member contains the transaction identification associated with @@ -173,8 +170,7 @@ S: {"return": {"enabled": true, "present": true}, "id": "example"} ------------------ C: { "execute": } -S: {"error": {"class": "JSONParsing", "desc": "Invalid JSON syntax", "data": -{}}} +S: {"error": {"class": "GenericError", "desc": "Invalid JSON syntax" } } 3.5 Powerdown event ------------------- diff --git a/arch_init.c b/arch_init.c index 7b65c4888b..9b46bfcaa5 100644 --- a/arch_init.c +++ b/arch_init.c @@ -43,6 +43,7 @@ #include "hw/smbios.h" #include "exec-memory.h" #include "hw/pcspk.h" +#include "qemu/page_cache.h" #ifdef DEBUG_ARCH_INIT #define DPRINTF(fmt, ...) \ @@ -106,6 +107,7 @@ const uint32_t arch_type = QEMU_ARCH; #define RAM_SAVE_FLAG_PAGE 0x08 #define RAM_SAVE_FLAG_EOS 0x10 #define RAM_SAVE_FLAG_CONTINUE 0x20 +#define RAM_SAVE_FLAG_XBZRLE 0x40 #ifdef __ALTIVEC__ #include <altivec.h> @@ -173,6 +175,92 @@ static int is_dup_page(uint8_t *page) return 1; } +/* struct contains XBZRLE cache and a static page + used by the compression */ +static struct { + /* buffer used for XBZRLE encoding */ + uint8_t *encoded_buf; + /* buffer for storing page content */ + uint8_t *current_buf; + /* buffer used for XBZRLE decoding */ + uint8_t *decoded_buf; + /* Cache for XBZRLE */ + PageCache *cache; +} XBZRLE = { + .encoded_buf = NULL, + .current_buf = NULL, + .decoded_buf = NULL, + .cache = NULL, +}; + + +int64_t xbzrle_cache_resize(int64_t new_size) +{ + if (XBZRLE.cache != NULL) { + return cache_resize(XBZRLE.cache, new_size / TARGET_PAGE_SIZE) * + TARGET_PAGE_SIZE; + } + return pow2floor(new_size); +} + +/* accounting for migration statistics */ +typedef struct AccountingInfo { + uint64_t dup_pages; + uint64_t norm_pages; + uint64_t iterations; + uint64_t xbzrle_bytes; + uint64_t xbzrle_pages; + uint64_t xbzrle_cache_miss; + uint64_t xbzrle_overflows; +} AccountingInfo; + +static AccountingInfo acct_info; + +static void acct_clear(void) +{ + memset(&acct_info, 0, sizeof(acct_info)); +} + +uint64_t dup_mig_bytes_transferred(void) +{ + return acct_info.dup_pages * TARGET_PAGE_SIZE; +} + +uint64_t dup_mig_pages_transferred(void) +{ + return acct_info.dup_pages; +} + +uint64_t norm_mig_bytes_transferred(void) +{ + return acct_info.norm_pages * TARGET_PAGE_SIZE; +} + +uint64_t norm_mig_pages_transferred(void) +{ + return acct_info.norm_pages; +} + +uint64_t xbzrle_mig_bytes_transferred(void) +{ + return acct_info.xbzrle_bytes; +} + +uint64_t xbzrle_mig_pages_transferred(void) +{ + return acct_info.xbzrle_pages; +} + +uint64_t xbzrle_mig_pages_cache_miss(void) +{ + return acct_info.xbzrle_cache_miss; +} + +uint64_t xbzrle_mig_pages_overflow(void) +{ + return acct_info.xbzrle_overflows; +} + static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset, int cont, int flag) { @@ -185,6 +273,61 @@ static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset, } +#define ENCODING_FLAG_XBZRLE 0x1 + +static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, + ram_addr_t current_addr, RAMBlock *block, + ram_addr_t offset, int cont, bool last_stage) +{ + int encoded_len = 0, bytes_sent = -1; + uint8_t *prev_cached_page; + + if (!cache_is_cached(XBZRLE.cache, current_addr)) { + if (!last_stage) { + cache_insert(XBZRLE.cache, current_addr, + g_memdup(current_data, TARGET_PAGE_SIZE)); + } + acct_info.xbzrle_cache_miss++; + return -1; + } + + prev_cached_page = get_cached_data(XBZRLE.cache, current_addr); + + /* save current buffer into memory */ + memcpy(XBZRLE.current_buf, current_data, TARGET_PAGE_SIZE); + + /* XBZRLE encoding (if there is no overflow) */ + encoded_len = xbzrle_encode_buffer(prev_cached_page, XBZRLE.current_buf, + TARGET_PAGE_SIZE, XBZRLE.encoded_buf, + TARGET_PAGE_SIZE); + if (encoded_len == 0) { + DPRINTF("Skipping unmodified page\n"); + return 0; + } else if (encoded_len == -1) { + DPRINTF("Overflow\n"); + acct_info.xbzrle_overflows++; + /* update data in the cache */ + memcpy(prev_cached_page, current_data, TARGET_PAGE_SIZE); + return -1; + } + + /* we need to update the data in the cache, in order to get the same data */ + if (!last_stage) { + memcpy(prev_cached_page, XBZRLE.current_buf, TARGET_PAGE_SIZE); + } + + /* Send XBZRLE based compressed page */ + save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_XBZRLE); + qemu_put_byte(f, ENCODING_FLAG_XBZRLE); + qemu_put_be16(f, encoded_len); + qemu_put_buffer(f, XBZRLE.encoded_buf, encoded_len); + bytes_sent = encoded_len + 1 + 2; + acct_info.xbzrle_pages++; + acct_info.xbzrle_bytes += bytes_sent; + + return bytes_sent; +} + static RAMBlock *last_block; static ram_addr_t last_offset; @@ -196,12 +339,13 @@ static ram_addr_t last_offset; * n: the amount of bytes written in other case */ -static int ram_save_block(QEMUFile *f) +static int ram_save_block(QEMUFile *f, bool last_stage) { RAMBlock *block = last_block; ram_addr_t offset = last_offset; int bytes_sent = -1; MemoryRegion *mr; + ram_addr_t current_addr; if (!block) block = QLIST_FIRST(&ram_list.blocks); @@ -219,16 +363,31 @@ static int ram_save_block(QEMUFile *f) p = memory_region_get_ram_ptr(mr) + offset; if (is_dup_page(p)) { + acct_info.dup_pages++; save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_COMPRESS); qemu_put_byte(f, *p); bytes_sent = 1; - } else { + } else if (migrate_use_xbzrle()) { + current_addr = block->offset + offset; + bytes_sent = save_xbzrle_page(f, p, current_addr, block, + offset, cont, last_stage); + if (!last_stage) { + p = get_cached_data(XBZRLE.cache, current_addr); + } + } + + /* either we didn't send yet (we may have had XBZRLE overflow) */ + if (bytes_sent == -1) { save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE); qemu_put_buffer(f, p, TARGET_PAGE_SIZE); bytes_sent = TARGET_PAGE_SIZE; + acct_info.norm_pages++; } - break; + /* if page is unmodified, continue to the next */ + if (bytes_sent != 0) { + break; + } } offset += TARGET_PAGE_SIZE; @@ -306,6 +465,15 @@ static void sort_ram_list(void) static void migration_end(void) { memory_global_dirty_log_stop(); + + if (migrate_use_xbzrle()) { + cache_fini(XBZRLE.cache); + g_free(XBZRLE.cache); + g_free(XBZRLE.encoded_buf); + g_free(XBZRLE.current_buf); + g_free(XBZRLE.decoded_buf); + XBZRLE.cache = NULL; + } } static void ram_migration_cancel(void *opaque) @@ -325,6 +493,19 @@ static int ram_save_setup(QEMUFile *f, void *opaque) last_offset = 0; sort_ram_list(); + if (migrate_use_xbzrle()) { + XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() / + TARGET_PAGE_SIZE, + TARGET_PAGE_SIZE); + if (!XBZRLE.cache) { + DPRINTF("Error creating cache\n"); + return -1; + } + XBZRLE.encoded_buf = g_malloc0(TARGET_PAGE_SIZE); + XBZRLE.current_buf = g_malloc(TARGET_PAGE_SIZE); + acct_clear(); + } + /* Make sure all dirty bits are set */ QLIST_FOREACH(block, &ram_list.blocks, next) { for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) { @@ -365,12 +546,13 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) while ((ret = qemu_file_rate_limit(f)) == 0) { int bytes_sent; - bytes_sent = ram_save_block(f); + bytes_sent = ram_save_block(f, false); /* no more blocks to sent */ if (bytes_sent < 0) { break; } bytes_transferred += bytes_sent; + acct_info.iterations++; /* we want to check in the 1st loop, just in case it was the 1st time and we had to sync the dirty bitmap. qemu_get_clock_ns() is a bit expensive, so we only check each some @@ -426,7 +608,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque) while (true) { int bytes_sent; - bytes_sent = ram_save_block(f); + bytes_sent = ram_save_block(f, true); /* no more blocks to sent */ if (bytes_sent < 0) { break; @@ -440,6 +622,47 @@ static int ram_save_complete(QEMUFile *f, void *opaque) return 0; } +static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) +{ + int ret, rc = 0; + unsigned int xh_len; + int xh_flags; + + if (!XBZRLE.decoded_buf) { + XBZRLE.decoded_buf = g_malloc(TARGET_PAGE_SIZE); + } + + /* extract RLE header */ + xh_flags = qemu_get_byte(f); + xh_len = qemu_get_be16(f); + + if (xh_flags != ENCODING_FLAG_XBZRLE) { + fprintf(stderr, "Failed to load XBZRLE page - wrong compression!\n"); + return -1; + } + + if (xh_len > TARGET_PAGE_SIZE) { + fprintf(stderr, "Failed to load XBZRLE page - len overflow!\n"); + return -1; + } + /* load data and decode */ + qemu_get_buffer(f, XBZRLE.decoded_buf, xh_len); + + /* decode RLE */ + ret = xbzrle_decode_buffer(XBZRLE.decoded_buf, xh_len, host, + TARGET_PAGE_SIZE); + if (ret == -1) { + fprintf(stderr, "Failed to load XBZRLE page - decode error!\n"); + rc = -1; + } else if (ret > TARGET_PAGE_SIZE) { + fprintf(stderr, "Failed to load XBZRLE page - size %d exceeds %d!\n", + ret, TARGET_PAGE_SIZE); + abort(); + } + + return rc; +} + static inline void *host_from_stream_offset(QEMUFile *f, ram_addr_t offset, int flags) @@ -553,6 +776,19 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) } qemu_get_buffer(f, host, TARGET_PAGE_SIZE); + } else if (flags & RAM_SAVE_FLAG_XBZRLE) { + if (!migrate_use_xbzrle()) { + return -EINVAL; + } + void *host = host_from_stream_offset(f, addr, flags); + if (!host) { + return -EINVAL; + } + + if (load_xbzrle(f, addr, host) < 0) { + ret = -EINVAL; + goto done; + } } error = qemu_file_get_error(f); if (error) { diff --git a/block.c b/block.c index 24323c11d0..016858bf8c 100644 --- a/block.c +++ b/block.c @@ -2445,6 +2445,7 @@ BlockInfoList *qmp_query_block(Error **errp) info->value->inserted->ro = bs->read_only; info->value->inserted->drv = g_strdup(bs->drv->format_name); info->value->inserted->encrypted = bs->encrypted; + info->value->inserted->encryption_key_missing = bdrv_key_required(bs); if (bs->backing_file[0]) { info->value->inserted->has_backing_file = true; info->value->inserted->backing_file = g_strdup(bs->backing_file); diff --git a/block_int.h b/block_int.h index 6c1d9cafb1..4452f6f398 100644 --- a/block_int.h +++ b/block_int.h @@ -30,6 +30,7 @@ #include "qemu-coroutine.h" #include "qemu-timer.h" #include "qapi-types.h" +#include "qerror.h" #define BLOCK_FLAG_ENCRYPT 1 #define BLOCK_FLAG_COMPAT6 4 diff --git a/compiler.h b/compiler.h index 736e77075a..f76921e5b0 100644 --- a/compiler.h +++ b/compiler.h @@ -45,6 +45,7 @@ # define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2))) # define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m))) # endif +#define GCC_WEAK __attribute__((weak)) #else #define GCC_ATTR /**/ #define GCC_FMT_ATTR(n, m) diff --git a/configure b/configure index f0dbc03af2..edf9da44b5 100755 --- a/configure +++ b/configure @@ -171,7 +171,6 @@ vhost_net="no" kvm="no" gprof="no" debug_tcg="no" -debug_mon="no" debug="no" strip_opt="yes" tcg_interpreter="no" @@ -657,14 +656,9 @@ for opt do ;; --disable-debug-tcg) debug_tcg="no" ;; - --enable-debug-mon) debug_mon="yes" - ;; - --disable-debug-mon) debug_mon="no" - ;; --enable-debug) # Enable debugging options that aren't excessively noisy debug_tcg="yes" - debug_mon="yes" debug="yes" strip_opt="no" ;; @@ -3064,7 +3058,6 @@ echo "host CPU $cpu" echo "host big endian $bigendian" echo "target list $target_list" echo "tcg debug enabled $debug_tcg" -echo "Mon debug enabled $debug_mon" echo "gprof enabled $gprof" echo "sparse enabled $sparse" echo "strip binaries $strip_opt" @@ -3157,9 +3150,6 @@ echo "ARCH=$ARCH" >> $config_host_mak if test "$debug_tcg" = "yes" ; then echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak fi -if test "$debug_mon" = "yes" ; then - echo "CONFIG_DEBUG_MONITOR=y" >> $config_host_mak -fi if test "$debug" = "yes" ; then echo "CONFIG_DEBUG_EXEC=y" >> $config_host_mak fi @@ -3563,15 +3553,23 @@ if test "$linux" = "yes" ; then mkdir -p linux-headers case "$cpu" in i386|x86_64) - symlink "$source_path/linux-headers/asm-x86" linux-headers/asm + linux_arch=x86 ;; ppcemb|ppc|ppc64) - symlink "$source_path/linux-headers/asm-powerpc" linux-headers/asm + linux_arch=powerpc ;; s390x) - symlink "$source_path/linux-headers/asm-s390" linux-headers/asm + linux_arch=s390 + ;; + *) + # For most CPUs the kernel architecture name and QEMU CPU name match. + linux_arch="$cpu" ;; esac + # For non-KVM architectures we will not have asm headers + if [ -e "$source_path/linux-headers/asm-$linux_arch" ]; then + symlink "$source_path/linux-headers/asm-$linux_arch" linux-headers/asm + fi fi for target in $target_list; do @@ -3780,7 +3778,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile" case "$target_arch2" in - alpha | or32 | sparc* | xtensa* | ppc*) + alpha | i386 | or32 | sparc* | x86_64 | xtensa* | ppc*) echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak ;; esac diff --git a/cpu-all.h b/cpu-all.h index 82ba1d7cd5..5e07d28508 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -274,6 +274,28 @@ extern unsigned long reserved_va; #define cpu_ldsw_code(env1, p) ldsw_raw(p) #define cpu_ldl_code(env1, p) ldl_raw(p) #define cpu_ldq_code(env1, p) ldq_raw(p) + +#define cpu_ldub_data(env, addr) ldub_raw(addr) +#define cpu_lduw_data(env, addr) lduw_raw(addr) +#define cpu_ldsw_data(env, addr) ldsw_raw(addr) +#define cpu_ldl_data(env, addr) ldl_raw(addr) +#define cpu_ldq_data(env, addr) ldq_raw(addr) + +#define cpu_stb_data(env, addr, data) stb_raw(addr, data) +#define cpu_stw_data(env, addr, data) stw_raw(addr, data) +#define cpu_stl_data(env, addr, data) stl_raw(addr, data) +#define cpu_stq_data(env, addr, data) stq_raw(addr, data) + +#define cpu_ldub_kernel(env, addr) ldub_raw(addr) +#define cpu_lduw_kernel(env, addr) lduw_raw(addr) +#define cpu_ldsw_kernel(env, addr) ldsw_raw(addr) +#define cpu_ldl_kernel(env, addr) ldl_raw(addr) +#define cpu_ldq_kernel(env, addr) ldq_raw(addr) + +#define cpu_stb_kernel(env, addr, data) stb_raw(addr, data) +#define cpu_stw_kernel(env, addr, data) stw_raw(addr, data) +#define cpu_stl_kernel(env, addr, data) stl_raw(addr, data) +#define cpu_stq_kernel(env, addr, data) stq_raw(addr, data) #endif #define ldub_kernel(p) ldub_raw(p) diff --git a/cpus.c b/cpus.c index 3de2e27f41..e476a3cd5e 100644 --- a/cpus.c +++ b/cpus.c @@ -70,7 +70,8 @@ static bool cpu_thread_is_idle(CPUArchState *env) if (env->stopped || !runstate_is_running()) { return true; } - if (!env->halted || qemu_cpu_has_work(env) || kvm_irqchip_in_kernel()) { + if (!env->halted || qemu_cpu_has_work(env) || + kvm_async_interrupts_enabled()) { return false; } return true; diff --git a/cutils.c b/cutils.c index 9d4c570939..ee4614d378 100644 --- a/cutils.c +++ b/cutils.c @@ -382,3 +382,45 @@ int qemu_parse_fd(const char *param) } return fd; } + +/* round down to the nearest power of 2*/ +int64_t pow2floor(int64_t value) +{ + if (!is_power_of_2(value)) { + value = 0x8000000000000000ULL >> clz64(value); + } + return value; +} + +/* + * Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128) + * Input is limited to 14-bit numbers + */ +int uleb128_encode_small(uint8_t *out, uint32_t n) +{ + g_assert(n <= 0x3fff); + if (n < 0x80) { + *out++ = n; + return 1; + } else { + *out++ = (n & 0x7f) | 0x80; + *out++ = n >> 7; + return 2; + } +} + +int uleb128_decode_small(const uint8_t *in, uint32_t *n) +{ + if (!(*in & 0x80)) { + *n = *in++; + return 1; + } else { + *n = *in++ & 0x7f; + /* we exceed 14 bit number */ + if (*in & 0x80) { + return -1; + } + *n |= *in++ << 7; + return 2; + } +} diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index e542b4f8ee..f335a725f0 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -27,3 +27,21 @@ CONFIG_SMC91C111=y CONFIG_DS1338=y CONFIG_PFLASH_CFI01=y CONFIG_PFLASH_CFI02=y + +CONFIG_ARM_TIMER=y +CONFIG_PL011=y +CONFIG_PL022=y +CONFIG_PL031=y +CONFIG_PL041=y +CONFIG_PL050=y +CONFIG_PL061=y +CONFIG_PL080=y +CONFIG_PL110=y +CONFIG_PL181=y +CONFIG_PL190=y +CONFIG_PL310=y +CONFIG_CADENCE=y +CONFIG_XGMAC=y + +CONFIG_VERSATILE_PCI=y +CONFIG_VERSATILE_I2C=y diff --git a/docs/writing-qmp-commands.txt b/docs/writing-qmp-commands.txt index 0ad51aa22a..8349dec8af 100644 --- a/docs/writing-qmp-commands.txt +++ b/docs/writing-qmp-commands.txt @@ -210,19 +210,17 @@ if you don't see these strings, then something went wrong. === Errors === QMP commands should use the error interface exported by the error.h header -file. The basic function used to set an error is the error_set() one. +file. Basically, errors are set by calling the error_set() function. Let's say we don't accept the string "message" to contain the word "love". If -it does contain it, we want the "hello-world" command to the return the -InvalidParameter error. - -Only one change is required, and it's in the C implementation: +it does contain it, we want the "hello-world" command to return an error: void qmp_hello_world(bool has_message, const char *message, Error **errp) { if (has_message) { if (strstr(message, "love")) { - error_set(errp, QERR_INVALID_PARAMETER, "message"); + error_set(errp, ERROR_CLASS_GENERIC_ERROR, + "the word 'love' is not allowed"); return; } printf("%s\n", message); @@ -231,30 +229,40 @@ void qmp_hello_world(bool has_message, const char *message, Error **errp) } } -Let's test it. Build qemu, run it as defined in the "Testing" section, and -then issue the following command: +The first argument to the error_set() function is the Error pointer to pointer, +which is passed to all QMP functions. The second argument is a ErrorClass +value, which should be ERROR_CLASS_GENERIC_ERROR most of the time (more +details about error classes are given below). The third argument is a human +description of the error, this is a free-form printf-like string. + +Let's test the example above. Build qemu, run it as defined in the "Testing" +section, and then issue the following command: -{ "execute": "hello-world", "arguments": { "message": "we love qemu" } } +{ "execute": "hello-world", "arguments": { "message": "all you need is love" } } The QMP server's response should be: { "error": { - "class": "InvalidParameter", - "desc": "Invalid parameter 'message'", - "data": { - "name": "message" - } + "class": "GenericError", + "desc": "the word 'love' is not allowed" } } -Which is the InvalidParameter error. +As a general rule, all QMP errors should use ERROR_CLASS_GENERIC_ERROR. There +are two exceptions to this rule: + + 1. A non-generic ErrorClass value exists* for the failure you want to report + (eg. DeviceNotFound) + + 2. Management applications have to take special action on the failure you + want to report, hence you have to add a new ErrorClass value so that they + can check for it -When you have to return an error but you're unsure what error to return or -which arguments an error takes, you should look at the qerror.h file. Note -that you might be required to add new errors if needed. +If the failure you want to report doesn't fall in one of the two cases above, +just report ERROR_CLASS_GENERIC_ERROR. -FIXME: describe better the error API and how to add new errors. + * All existing ErrorClass values are defined in the qapi-schema.json file === Command Documentation === @@ -275,7 +283,6 @@ here goes "hello-world"'s new entry for the qapi-schema.json file: # @message: #optional string to be printed # # Returns: Nothing on success. -# If @message contains "love", InvalidParameter # # Notes: if @message is not provided, the "Hello, world" string will # be printed instead diff --git a/docs/xbzrle.txt b/docs/xbzrle.txt new file mode 100644 index 0000000000..cc3a26a91d --- /dev/null +++ b/docs/xbzrle.txt @@ -0,0 +1,128 @@ +XBZRLE (Xor Based Zero Run Length Encoding) +=========================================== + +Using XBZRLE (Xor Based Zero Run Length Encoding) allows for the reduction +of VM downtime and the total live-migration time of Virtual machines. +It is particularly useful for virtual machines running memory write intensive +workloads that are typical of large enterprise applications such as SAP ERP +Systems, and generally speaking for any application that uses a sparse memory +update pattern. + +Instead of sending the changed guest memory page this solution will send a +compressed version of the updates, thus reducing the amount of data sent during +live migration. +In order to be able to calculate the update, the previous memory pages need to +be stored on the source. Those pages are stored in a dedicated cache +(hash table) and are accessed by their address. +The larger the cache size the better the chances are that the page has already +been stored in the cache. +A small cache size will result in high cache miss rate. +Cache size can be changed before and during migration. + +Format +======= + +The compression format performs a XOR between the previous and current content +of the page, where zero represents an unchanged value. +The page data delta is represented by zero and non zero runs. +A zero run is represented by its length (in bytes). +A non zero run is represented by its length (in bytes) and the new data. +The run length is encoded using ULEB128 (http://en.wikipedia.org/wiki/LEB128) + +There can be more than one valid encoding, the sender may send a longer encoding +for the benefit of reducing computation cost. + +page = zrun nzrun + | zrun nzrun page + +zrun = length + +nzrun = length byte... + +length = uleb128 encoded integer + +On the sender side XBZRLE is used as a compact delta encoding of page updates, +retrieving the old page content from the cache (default size of 512 MB). The +receiving side uses the existing page's content and XBZRLE to decode the new +page's content. + +This work was originally based on research results published +VEE 2011: Evaluation of Delta Compression Techniques for Efficient Live +Migration of Large Virtual Machines by Benoit, Svard, Tordsson and Elmroth. +Additionally the delta encoder XBRLE was improved further using the XBZRLE +instead. + +XBZRLE has a sustained bandwidth of 2-2.5 GB/s for typical workloads making it +ideal for in-line, real-time encoding such as is needed for live-migration. + +Example +old buffer: +1001 zeros +05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 68 00 00 6b 00 6d +3074 zeros + +new buffer: +1001 zeros +01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 68 00 00 67 00 69 +3074 zeros + +encoded buffer: + +encoded length 24 +e9 07 0f 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 03 01 67 01 01 69 + +Usage +====================== +1. Verify the destination QEMU version is able to decode the new format. + {qemu} info migrate_capabilities + {qemu} xbzrle: off , ... + +2. Activate xbzrle on both source and destination: + {qemu} migrate_set_capability xbzrle on + +3. Set the XBZRLE cache size - the cache size is in MBytes and should be a +power of 2. The cache default value is 64MBytes. (on source only) + {qemu} migrate_set_cache_size 256m + +4. Start outgoing migration + {qemu} migrate -d tcp:destination.host:4444 + {qemu} info migrate + capabilities: xbzrle: on + Migration status: active + transferred ram: A kbytes + remaining ram: B kbytes + total ram: C kbytes + total time: D milliseconds + duplicate: E pages + normal: F pages + normal bytes: G kbytes + cache size: H bytes + xbzrle transferred: I kbytes + xbzrle pages: J pages + xbzrle cache miss: K + xbzrle overflow : L + +xbzrle cache-miss: the number of cache misses to date - high cache-miss rate +indicates that the cache size is set too low. +xbzrle overflow: the number of overflows in the decoding which where the delta +could not be compressed. This can happen if the changes in the pages are too +large or there are many short changes; for example, changing every second byte +(half a page). + +Testing: Testing indicated that live migration with XBZRLE was completed in 110 +seconds, whereas without it would not be able to complete. + +A simple synthetic memory r/w load generator: +.. include <stdlib.h> +.. include <stdio.h> +.. int main() +.. { +.. char *buf = (char *) calloc(4096, 4096); +.. while (1) { +.. int i; +.. for (i = 0; i < 4096 * 4; i++) { +.. buf[i * 4096 / 4]++; +.. } +.. printf("."); +.. } +.. } diff --git a/error.c b/error.c index 58f55a012e..1f05fc466e 100644 --- a/error.c +++ b/error.c @@ -14,17 +14,16 @@ #include "error.h" #include "qjson.h" #include "qdict.h" -#include "error_int.h" +#include "qapi-types.h" #include "qerror.h" struct Error { - QDict *obj; - const char *fmt; char *msg; + ErrorClass err_class; }; -void error_set(Error **errp, const char *fmt, ...) +void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...) { Error *err; va_list ap; @@ -37,9 +36,9 @@ void error_set(Error **errp, const char *fmt, ...) err = g_malloc0(sizeof(*err)); va_start(ap, fmt); - err->obj = qobject_to_qdict(qobject_from_jsonv(fmt, &ap)); + err->msg = g_strdup_vprintf(fmt, ap); va_end(ap); - err->fmt = fmt; + err->err_class = err_class; *errp = err; } @@ -50,9 +49,7 @@ Error *error_copy(const Error *err) err_new = g_malloc0(sizeof(*err)); err_new->msg = g_strdup(err->msg); - err_new->fmt = err->fmt; - err_new->obj = err->obj; - QINCREF(err_new->obj); + err_new->err_class = err->err_class; return err_new; } @@ -62,75 +59,24 @@ bool error_is_set(Error **errp) return (errp && *errp); } -const char *error_get_pretty(Error *err) -{ - if (err->msg == NULL) { - QString *str; - str = qerror_format(err->fmt, err->obj); - err->msg = g_strdup(qstring_get_str(str)); - QDECREF(str); - } - - return err->msg; -} - -const char *error_get_field(Error *err, const char *field) -{ - if (strcmp(field, "class") == 0) { - return qdict_get_str(err->obj, field); - } else { - QDict *dict = qdict_get_qdict(err->obj, "data"); - return qdict_get_str(dict, field); - } -} - -QDict *error_get_data(Error *err) +ErrorClass error_get_class(const Error *err) { - QDict *data = qdict_get_qdict(err->obj, "data"); - QINCREF(data); - return data; + return err->err_class; } -void error_set_field(Error *err, const char *field, const char *value) +const char *error_get_pretty(Error *err) { - QDict *dict = qdict_get_qdict(err->obj, "data"); - qdict_put(dict, field, qstring_from_str(value)); + return err->msg; } void error_free(Error *err) { if (err) { - QDECREF(err->obj); g_free(err->msg); g_free(err); } } -bool error_is_type(Error *err, const char *fmt) -{ - const char *error_class; - char *ptr; - char *end; - - if (!err) { - return false; - } - - ptr = strstr(fmt, "'class': '"); - assert(ptr != NULL); - ptr += strlen("'class': '"); - - end = strchr(ptr, '\''); - assert(end != NULL); - - error_class = error_get_field(err, "class"); - if (strlen(error_class) != end - ptr) { - return false; - } - - return strncmp(ptr, error_class, end - ptr) == 0; -} - void error_propagate(Error **dst_err, Error *local_err) { if (dst_err && !*dst_err) { @@ -139,22 +85,3 @@ void error_propagate(Error **dst_err, Error *local_err) error_free(local_err); } } - -QObject *error_get_qobject(Error *err) -{ - QINCREF(err->obj); - return QOBJECT(err->obj); -} - -void error_set_qobject(Error **errp, QObject *obj) -{ - Error *err; - if (errp == NULL) { - return; - } - err = g_malloc0(sizeof(*err)); - err->obj = qobject_to_qdict(obj); - qobject_incref(obj); - - *errp = err; -} diff --git a/error.h b/error.h index 3d9d96def0..96fc20328f 100644 --- a/error.h +++ b/error.h @@ -13,20 +13,21 @@ #define ERROR_H #include "compiler.h" +#include "qapi-types.h" #include <stdbool.h> /** - * A class representing internal errors within QEMU. An error has a string - * typename and optionally a set of named string parameters. + * A class representing internal errors within QEMU. An error has a ErrorClass + * code and a human message. */ typedef struct Error Error; /** - * Set an indirect pointer to an error given a printf-style format parameter. - * Currently, qerror.h defines these error formats. This function is not - * meant to be used outside of QEMU. + * Set an indirect pointer to an error given a ErrorClass value and a + * printf-style human message. This function is not meant to be used outside + * of QEMU. */ -void error_set(Error **err, const char *fmt, ...) GCC_FMT_ATTR(2, 3); +void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(3, 4); /** * Returns true if an indirect pointer to an error is pointing to a valid @@ -34,6 +35,11 @@ void error_set(Error **err, const char *fmt, ...) GCC_FMT_ATTR(2, 3); */ bool error_is_set(Error **err); +/* + * Get the error class of an error object. + */ +ErrorClass error_get_class(const Error *err); + /** * Returns an exact copy of the error passed as an argument. */ @@ -45,16 +51,6 @@ Error *error_copy(const Error *err); const char *error_get_pretty(Error *err); /** - * Get an individual named error field. - */ -const char *error_get_field(Error *err, const char *field); - -/** - * Get an individual named error field. - */ -void error_set_field(Error *err, const char *field, const char *value); - -/** * Propagate an error to an indirect pointer to an error. This function will * always transfer ownership of the error reference and handles the case where * dst_err is NULL correctly. Errors after the first are discarded. @@ -66,10 +62,4 @@ void error_propagate(Error **dst_err, Error *local_err); */ void error_free(Error *err); -/** - * Determine if an error is of a speific type (based on the qerror format). - * Non-QEMU users should get the `class' field to identify the error type. - */ -bool error_is_type(Error *err, const char *fmt); - #endif diff --git a/error_int.h b/error_int.h deleted file mode 100644 index 5e3942405a..0000000000 --- a/error_int.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * QEMU Error Objects - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.com> - * - * This work is licensed under the terms of the GNU LGPL, version 2. See - * the COPYING.LIB file in the top-level directory. - */ -#ifndef QEMU_ERROR_INT_H -#define QEMU_ERROR_INT_H - -#include "qemu-common.h" -#include "qobject.h" -#include "qdict.h" -#include "error.h" - -/** - * Internal QEMU functions for working with Error. - * - * These are used to convert QErrors to Errors - */ -QDict *error_get_data(Error *err); -QObject *error_get_qobject(Error *err); -void error_set_qobject(Error **errp, QObject *obj); - -#endif diff --git a/hmp-commands.hx b/hmp-commands.hx index 9bbc7f7555..f6104b099f 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -829,6 +829,26 @@ STEXI @item migrate_cancel @findex migrate_cancel Cancel the current VM migration. + +ETEXI + + { + .name = "migrate_set_cache_size", + .args_type = "value:o", + .params = "value", + .help = "set cache size (in bytes) for XBZRLE migrations," + "the cache size will be rounded down to the nearest " + "power of 2.\n" + "The cache size affects the number of cache misses." + "In case of a high cache miss ratio you need to increase" + " the cache size", + .mhandler.cmd = hmp_migrate_set_cache_size, + }, + +STEXI +@item migrate_set_cache_size @var{value} +@findex migrate_set_cache_size +Set cache size to @var{value} (in bytes) for xbzrle migrations. ETEXI { @@ -861,6 +881,20 @@ Set maximum tolerated downtime (in seconds) for migration. ETEXI { + .name = "migrate_set_capability", + .args_type = "capability:s,state:b", + .params = "capability state", + .help = "Enable/Disable the usage of a capability for migration", + .mhandler.cmd = hmp_migrate_set_capability, + }, + +STEXI +@item migrate_set_capability @var{capability} @var{state} +@findex migrate_set_capability +Enable/Disable the usage of a capability @var{capability} for migration. +ETEXI + + { .name = "client_migrate_info", .args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?", .params = "protocol hostname port tls-port cert-subject", @@ -1417,6 +1451,10 @@ show CPU statistics show user network stack connection states @item info migrate show migration status +@item info migrate_capabilities +show current migration capabilities +@item info migrate_cache_size +show current migration XBZRLE cache size @item info balloon show balloon information @item info qtree diff --git a/hmp.c b/hmp.c index 25688ab0e2..a9d5675fc8 100644 --- a/hmp.c +++ b/hmp.c @@ -131,8 +131,21 @@ void hmp_info_mice(Monitor *mon) void hmp_info_migrate(Monitor *mon) { MigrationInfo *info; + MigrationCapabilityStatusList *caps, *cap; info = qmp_query_migrate(NULL); + caps = qmp_query_migrate_capabilities(NULL); + + /* do not display parameters during setup */ + if (info->has_status && caps) { + monitor_printf(mon, "capabilities: "); + for (cap = caps; cap; cap = cap->next) { + monitor_printf(mon, "%s: %s ", + MigrationCapability_lookup[cap->value->capability], + cap->value->state ? "on" : "off"); + } + monitor_printf(mon, "\n"); + } if (info->has_status) { monitor_printf(mon, "Migration status: %s\n", info->status); @@ -147,6 +160,12 @@ void hmp_info_migrate(Monitor *mon) info->ram->total >> 10); monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n", info->ram->total_time); + monitor_printf(mon, "duplicate: %" PRIu64 " pages\n", + info->ram->duplicate); + monitor_printf(mon, "normal: %" PRIu64 " pages\n", + info->ram->normal); + monitor_printf(mon, "normal bytes: %" PRIu64 " kbytes\n", + info->ram->normal_bytes >> 10); } if (info->has_disk) { @@ -158,7 +177,46 @@ void hmp_info_migrate(Monitor *mon) info->disk->total >> 10); } + if (info->has_xbzrle_cache) { + monitor_printf(mon, "cache size: %" PRIu64 " bytes\n", + info->xbzrle_cache->cache_size); + monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n", + info->xbzrle_cache->bytes >> 10); + monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n", + info->xbzrle_cache->pages); + monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n", + info->xbzrle_cache->cache_miss); + monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n", + info->xbzrle_cache->overflow); + } + qapi_free_MigrationInfo(info); + qapi_free_MigrationCapabilityStatusList(caps); +} + +void hmp_info_migrate_capabilities(Monitor *mon) +{ + MigrationCapabilityStatusList *caps, *cap; + + caps = qmp_query_migrate_capabilities(NULL); + + if (caps) { + monitor_printf(mon, "capabilities: "); + for (cap = caps; cap; cap = cap->next) { + monitor_printf(mon, "%s: %s ", + MigrationCapability_lookup[cap->value->capability], + cap->value->state ? "on" : "off"); + } + monitor_printf(mon, "\n"); + } + + qapi_free_MigrationCapabilityStatusList(caps); +} + +void hmp_info_migrate_cache_size(Monitor *mon) +{ + monitor_printf(mon, "xbzrel cache size: %" PRId64 " kbytes\n", + qmp_query_migrate_cache_size(NULL) >> 10); } void hmp_info_cpus(Monitor *mon) @@ -612,34 +670,35 @@ void hmp_pmemsave(Monitor *mon, const QDict *qdict) static void hmp_cont_cb(void *opaque, int err) { - Monitor *mon = opaque; - if (!err) { - hmp_cont(mon, NULL); + qmp_cont(NULL); } } +static bool key_is_missing(const BlockInfo *bdev) +{ + return (bdev->inserted && bdev->inserted->encryption_key_missing); +} + void hmp_cont(Monitor *mon, const QDict *qdict) { + BlockInfoList *bdev_list, *bdev; Error *errp = NULL; - qmp_cont(&errp); - if (error_is_set(&errp)) { - if (error_is_type(errp, QERR_DEVICE_ENCRYPTED)) { - const char *device; - - /* The device is encrypted. Ask the user for the password - and retry */ - - device = error_get_field(errp, "device"); - assert(device != NULL); - - monitor_read_block_device_key(mon, device, hmp_cont_cb, mon); - error_free(errp); - return; + bdev_list = qmp_query_block(NULL); + for (bdev = bdev_list; bdev; bdev = bdev->next) { + if (key_is_missing(bdev->value)) { + monitor_read_block_device_key(mon, bdev->value->device, + hmp_cont_cb, NULL); + goto out; } - hmp_handle_error(mon, &errp); } + + qmp_cont(&errp); + hmp_handle_error(mon, &errp); + +out: + qapi_free_BlockInfoList(bdev_list); } void hmp_system_wakeup(Monitor *mon, const QDict *qdict) @@ -731,12 +790,57 @@ void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict) qmp_migrate_set_downtime(value, NULL); } +void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict) +{ + int64_t value = qdict_get_int(qdict, "value"); + Error *err = NULL; + + qmp_migrate_set_cache_size(value, &err); + if (err) { + monitor_printf(mon, "%s\n", error_get_pretty(err)); + error_free(err); + return; + } +} + void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict) { int64_t value = qdict_get_int(qdict, "value"); qmp_migrate_set_speed(value, NULL); } +void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict) +{ + const char *cap = qdict_get_str(qdict, "capability"); + bool state = qdict_get_bool(qdict, "state"); + Error *err = NULL; + MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps)); + int i; + + for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) { + if (strcmp(cap, MigrationCapability_lookup[i]) == 0) { + caps->value = g_malloc0(sizeof(*caps->value)); + caps->value->capability = i; + caps->value->state = state; + caps->next = NULL; + qmp_migrate_set_capabilities(caps, &err); + break; + } + } + + if (i == MIGRATION_CAPABILITY_MAX) { + error_set(&err, QERR_INVALID_PARAMETER, cap); + } + + qapi_free_MigrationCapabilityStatusList(caps); + + if (err) { + monitor_printf(mon, "migrate_set_parameter: %s\n", + error_get_pretty(err)); + error_free(err); + } +} + void hmp_set_password(Monitor *mon, const QDict *qdict) { const char *protocol = qdict_get_str(qdict, "protocol"); @@ -775,22 +879,6 @@ static void hmp_change_read_arg(Monitor *mon, const char *password, monitor_read_command(mon, 1); } -static void cb_hmp_change_bdrv_pwd(Monitor *mon, const char *password, - void *opaque) -{ - Error *encryption_err = opaque; - Error *err = NULL; - const char *device; - - device = error_get_field(encryption_err, "device"); - - qmp_block_passwd(device, password, &err); - hmp_handle_error(mon, &err); - error_free(encryption_err); - - monitor_read_command(mon, 1); -} - void hmp_change(Monitor *mon, const QDict *qdict) { const char *device = qdict_get_str(qdict, "device"); @@ -808,18 +896,10 @@ void hmp_change(Monitor *mon, const QDict *qdict) } qmp_change(device, target, !!arg, arg, &err); - if (error_is_type(err, QERR_DEVICE_ENCRYPTED)) { - monitor_printf(mon, "%s (%s) is encrypted.\n", - error_get_field(err, "device"), - error_get_field(err, "filename")); - if (!monitor_get_rs(mon)) { - monitor_printf(mon, - "terminal does not support password prompting\n"); - error_free(err); - return; - } - readline_start(monitor_get_rs(mon), "Password: ", 1, - cb_hmp_change_bdrv_pwd, err); + if (error_is_set(&err) && + error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) { + error_free(err); + monitor_read_block_device_key(mon, device, NULL, NULL); return; } hmp_handle_error(mon, &err); diff --git a/hmp.h b/hmp.h index 8d2b0d76da..7dd93bf0f4 100644 --- a/hmp.h +++ b/hmp.h @@ -16,6 +16,7 @@ #include "qemu-common.h" #include "qapi-types.h" +#include "qdict.h" void hmp_info_name(Monitor *mon); void hmp_info_version(Monitor *mon); @@ -25,6 +26,8 @@ void hmp_info_uuid(Monitor *mon); void hmp_info_chardev(Monitor *mon); void hmp_info_mice(Monitor *mon); void hmp_info_migrate(Monitor *mon); +void hmp_info_migrate_capabilities(Monitor *mon); +void hmp_info_migrate_cache_size(Monitor *mon); void hmp_info_cpus(Monitor *mon); void hmp_info_block(Monitor *mon); void hmp_info_blockstats(Monitor *mon); @@ -51,6 +54,8 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict); void hmp_migrate_cancel(Monitor *mon, const QDict *qdict); void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict); void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict); +void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict); +void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict); void hmp_set_password(Monitor *mon, const QDict *qdict); void hmp_expire_password(Monitor *mon, const QDict *qdict); void hmp_eject(Monitor *mon, const QDict *qdict); diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 6eee9a074c..7f57ed58e2 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -74,6 +74,26 @@ hw-obj-$(CONFIG_PUV3) += puv3_gpio.o hw-obj-$(CONFIG_PUV3) += puv3_pm.o hw-obj-$(CONFIG_PUV3) += puv3_dma.o +# ARM devices +hw-obj-$(CONFIG_ARM_TIMER) += arm_timer.o +hw-obj-$(CONFIG_PL011) += pl011.o +hw-obj-$(CONFIG_PL022) += pl022.o +hw-obj-$(CONFIG_PL031) += pl031.o +hw-obj-$(CONFIG_PL041) += pl041.o lm4549.o +hw-obj-$(CONFIG_PL050) += pl050.o +hw-obj-$(CONFIG_PL061) += pl061.o +hw-obj-$(CONFIG_PL080) += pl080.o +hw-obj-$(CONFIG_PL110) += pl110.o +hw-obj-$(CONFIG_PL181) += pl181.o +hw-obj-$(CONFIG_PL190) += pl190.o +hw-obj-$(CONFIG_PL310) += arm_l2x0.o +hw-obj-$(CONFIG_VERSATILE_PCI) += versatile_pci.o +hw-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o +hw-obj-$(CONFIG_CADENCE) += cadence_uart.o +hw-obj-$(CONFIG_CADENCE) += cadence_ttc.o +hw-obj-$(CONFIG_CADENCE) += cadence_gem.o +hw-obj-$(CONFIG_XGMAC) += xgmac.o + # PCI watchdog devices hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o diff --git a/hw/acpi.c b/hw/acpi.c index effc7ec23e..f7950be267 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -22,6 +22,7 @@ #include "hw.h" #include "pc.h" #include "acpi.h" +#include "monitor.h" struct acpi_table_header { uint16_t _length; /* our length, not actual part of the hdr */ @@ -386,6 +387,7 @@ void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4) break; default: if (sus_typ == s4) { /* S4 request */ + monitor_protocol_event(QEVENT_SUSPEND_DISK, NULL); qemu_system_shutdown_request(); } break; diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index c413780784..2b39fb3c85 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -1,10 +1,5 @@ -obj-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o -obj-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o -obj-y += versatile_pci.o -obj-y += versatile_i2c.o -obj-y += cadence_uart.o -obj-y += cadence_ttc.o -obj-y += cadence_gem.o +obj-y = integratorcp.o versatilepb.o arm_pic.o +obj-y += arm_boot.o obj-y += xilinx_zynq.o zynq_slcr.o obj-y += arm_gic.o arm_gic_common.o obj-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o @@ -12,12 +7,9 @@ obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o obj-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o obj-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o obj-y += exynos4210_rtc.o exynos4210_i2c.o -obj-y += arm_l2x0.o obj-y += arm_mptimer.o a15mpcore.o -obj-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o +obj-y += armv7m.o armv7m_nvic.o stellaris.o stellaris_enet.o obj-y += highbank.o -obj-y += pl061.o -obj-y += xgmac.o obj-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o obj-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o obj-y += gumstix.o @@ -37,7 +29,6 @@ obj-y += strongarm.o obj-y += collie.o obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o obj-y += kzm.o -obj-y += pl041.o lm4549.o obj-$(CONFIG_FDT) += ../device_tree.o obj-y := $(addprefix ../,$(obj-y)) diff --git a/hw/armv7m.c b/hw/armv7m.c index 8cec78db96..9f66667c6d 100644 --- a/hw/armv7m.c +++ b/hw/armv7m.c @@ -227,6 +227,11 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, big_endian = 0; #endif + if (!kernel_filename) { + fprintf(stderr, "Guest image must be specified (using -kernel)\n"); + exit(1); + } + image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr, NULL, big_endian, ELF_MACHINE, 1); if (image_size < 0) { diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c index 4867c1d5fa..6a0832eb3f 100644 --- a/hw/armv7m_nvic.c +++ b/hw/armv7m_nvic.c @@ -467,7 +467,7 @@ static int armv7m_nvic_init(SysBusDevice *dev) s->gic.num_cpu = 1; /* Tell the common code we're an NVIC */ s->gic.revision = 0xffffffff; - s->gic.num_irq = s->num_irq; + s->num_irq = s->gic.num_irq; nc->parent_init(dev); gic_init_irqs_and_distributor(&s->gic, s->num_irq); /* The NVIC and system controller register area looks like this: @@ -498,14 +498,21 @@ static int armv7m_nvic_init(SysBusDevice *dev) return 0; } -static Property armv7m_nvic_properties[] = { +static void armv7m_nvic_instance_init(Object *obj) +{ + /* We have a different default value for the num-irq property + * than our superclass. This function runs after qdev init + * has set the defaults from the Property array and before + * any user-specified property setting, so just modify the + * value in the gic_state struct. + */ + gic_state *s = ARM_GIC_COMMON(obj); /* The ARM v7m may have anything from 0 to 496 external interrupt * IRQ lines. We default to 64. Other boards may differ and should - * set this property appropriately. + * set the num-irq property appropriately. */ - DEFINE_PROP_UINT32("num-irq", nvic_state, num_irq, 64), - DEFINE_PROP_END_OF_LIST(), -}; + s->num_irq = 64; +} static void armv7m_nvic_class_init(ObjectClass *klass, void *data) { @@ -518,12 +525,12 @@ static void armv7m_nvic_class_init(ObjectClass *klass, void *data) sdc->init = armv7m_nvic_init; dc->vmsd = &vmstate_nvic; dc->reset = armv7m_nvic_reset; - dc->props = armv7m_nvic_properties; } static TypeInfo armv7m_nvic_info = { .name = TYPE_NVIC, .parent = TYPE_ARM_GIC_COMMON, + .instance_init = armv7m_nvic_instance_init, .instance_size = sizeof(nvic_state), .class_init = armv7m_nvic_class_init, .class_size = sizeof(NVICClass), diff --git a/hw/kvm/i8259.c b/hw/kvm/i8259.c index 94d1b9aa95..1e24cd4f36 100644 --- a/hw/kvm/i8259.c +++ b/hw/kvm/i8259.c @@ -94,7 +94,7 @@ static void kvm_pic_set_irq(void *opaque, int irq, int level) { int delivered; - delivered = kvm_irqchip_set_irq(kvm_state, irq, level); + delivered = kvm_set_irq(kvm_state, irq, level); apic_report_irq_delivered(delivered); } diff --git a/hw/kvm/ioapic.c b/hw/kvm/ioapic.c index 3ae3175403..6c3b8fe39a 100644 --- a/hw/kvm/ioapic.c +++ b/hw/kvm/ioapic.c @@ -82,7 +82,7 @@ static void kvm_ioapic_set_irq(void *opaque, int irq, int level) KVMIOAPICState *s = opaque; int delivered; - delivered = kvm_irqchip_set_irq(kvm_state, s->kvm_gsi_base + irq, level); + delivered = kvm_set_irq(kvm_state, s->kvm_gsi_base + irq, level); apic_report_irq_delivered(delivered); } diff --git a/hw/pc.c b/hw/pc.c index 81c391cd6a..e8bcfc0b4b 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -42,6 +42,7 @@ #include "sysbus.h" #include "sysemu.h" #include "kvm.h" +#include "kvm_i386.h" #include "xen.h" #include "blockdev.h" #include "hw/block-common.h" diff --git a/hw/sd.c b/hw/sd.c index 07eb263388..ec26407543 100644 --- a/hw/sd.c +++ b/hw/sd.c @@ -32,6 +32,7 @@ #include "hw.h" #include "block.h" #include "sd.h" +#include "bitmap.h" //#define DEBUG_SD 1 @@ -80,8 +81,8 @@ struct SDState { uint32_t card_status; uint8_t sd_status[64]; uint32_t vhs; - int wp_switch; - int *wp_groups; + bool wp_switch; + unsigned long *wp_groups; uint64_t size; int blk_len; uint32_t erase_start; @@ -90,12 +91,12 @@ struct SDState { int pwd_len; int function_group[6]; - int spi; + bool spi; int current_cmd; /* True if we will handle the next command as an ACMD. Note that this does * *not* track the APP_CMD status bit! */ - int expecting_acmd; + bool expecting_acmd; int blk_written; uint64_t data_start; uint32_t data_offset; @@ -105,7 +106,7 @@ struct SDState { BlockDriverState *bdrv; uint8_t *buf; - int enable; + bool enable; }; static void sd_set_mode(SDState *sd) @@ -387,6 +388,11 @@ static void sd_response_r7_make(SDState *sd, uint8_t *response) response[3] = (sd->vhs >> 0) & 0xff; } +static inline uint64_t sd_addr_to_wpnum(uint64_t addr) +{ + return addr >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT); +} + static void sd_reset(SDState *sd, BlockDriverState *bdrv) { uint64_t size; @@ -399,7 +405,7 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv) } size = sect << 9; - sect = (size >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) + 1; + sect = sd_addr_to_wpnum(size) + 1; sd->state = sd_idle_state; sd->rca = 0x0000; @@ -414,15 +420,15 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv) if (sd->wp_groups) g_free(sd->wp_groups); - sd->wp_switch = bdrv ? bdrv_is_read_only(bdrv) : 0; - sd->wp_groups = (int *) g_malloc0(sizeof(int) * sect); + sd->wp_switch = bdrv ? bdrv_is_read_only(bdrv) : false; + sd->wp_groups = bitmap_new(sect); memset(sd->function_group, 0, sizeof(int) * 6); sd->erase_start = 0; sd->erase_end = 0; sd->size = size; sd->blk_len = 0x200; sd->pwd_len = 0; - sd->expecting_acmd = 0; + sd->expecting_acmd = false; } static void sd_cardchange(void *opaque, bool load) @@ -444,14 +450,14 @@ static const BlockDevOps sd_block_ops = { whether card should be in SSI or MMC/SD mode. It is also up to the board to ensure that ssi transfers only occur when the chip select is asserted. */ -SDState *sd_init(BlockDriverState *bs, int is_spi) +SDState *sd_init(BlockDriverState *bs, bool is_spi) { SDState *sd; sd = (SDState *) g_malloc0(sizeof(SDState)); sd->buf = qemu_blockalign(bs, 512); sd->spi = is_spi; - sd->enable = 1; + sd->enable = true; sd_reset(sd, bs); if (sd->bdrv) { bdrv_attach_dev_nofail(sd->bdrv, sd); @@ -476,17 +482,17 @@ static void sd_erase(SDState *sd) return; } - start = sd->erase_start >> - (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT); - end = sd->erase_end >> - (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT); + start = sd_addr_to_wpnum(sd->erase_start); + end = sd_addr_to_wpnum(sd->erase_end); sd->erase_start = 0; sd->erase_end = 0; sd->csd[14] |= 0x40; - for (i = start; i <= end; i ++) - if (sd->wp_groups[i]) + for (i = start; i <= end; i++) { + if (test_bit(i, sd->wp_groups)) { sd->card_status |= WP_ERASE_SKIP; + } + } } static uint32_t sd_wpbits(SDState *sd, uint64_t addr) @@ -494,11 +500,13 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr) uint32_t i, wpnum; uint32_t ret = 0; - wpnum = addr >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT); + wpnum = sd_addr_to_wpnum(addr); - for (i = 0; i < 32; i ++, wpnum ++, addr += WPGROUP_SIZE) - if (addr < sd->size && sd->wp_groups[wpnum]) + for (i = 0; i < 32; i++, wpnum++, addr += WPGROUP_SIZE) { + if (addr < sd->size && test_bit(wpnum, sd->wp_groups)) { ret |= (1 << i); + } + } return ret; } @@ -534,10 +542,9 @@ static void sd_function_switch(SDState *sd, uint32_t arg) sd->data[66] = crc & 0xff; } -static inline int sd_wp_addr(SDState *sd, uint32_t addr) +static inline bool sd_wp_addr(SDState *sd, uint64_t addr) { - return sd->wp_groups[addr >> - (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)]; + return test_bit(sd_addr_to_wpnum(addr), sd->wp_groups); } static void sd_lock_command(SDState *sd) @@ -560,8 +567,7 @@ static void sd_lock_command(SDState *sd) sd->card_status |= LOCK_UNLOCK_FAILED; return; } - memset(sd->wp_groups, 0, sizeof(int) * (sd->size >> - (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT))); + bitmap_zero(sd->wp_groups, sd_addr_to_wpnum(sd->size) + 1); sd->csd[14] &= ~0x10; sd->card_status &= ~CARD_IS_LOCKED; sd->pwd_len = 0; @@ -1007,8 +1013,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, } sd->state = sd_programming_state; - sd->wp_groups[addr >> (HWBLOCK_SHIFT + - SECTOR_SHIFT + WPGROUP_SHIFT)] = 1; + set_bit(sd_addr_to_wpnum(addr), sd->wp_groups); /* Bzzzzzzztt .... Operation complete. */ sd->state = sd_transfer_state; return sd_r1b; @@ -1027,8 +1032,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, } sd->state = sd_programming_state; - sd->wp_groups[addr >> (HWBLOCK_SHIFT + - SECTOR_SHIFT + WPGROUP_SHIFT)] = 0; + clear_bit(sd_addr_to_wpnum(addr), sd->wp_groups); /* Bzzzzzzztt .... Operation complete. */ sd->state = sd_transfer_state; return sd_r1b; @@ -1125,7 +1129,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, if (sd->rca != rca) return sd_r0; - sd->expecting_acmd = 1; + sd->expecting_acmd = true; sd->card_status |= APP_CMD; return sd_r1; @@ -1307,7 +1311,7 @@ int sd_do_command(SDState *sd, SDRequest *req, if (sd->card_status & CARD_IS_LOCKED) { if (!cmd_valid_while_locked(sd, req)) { sd->card_status |= ILLEGAL_COMMAND; - sd->expecting_acmd = 0; + sd->expecting_acmd = false; fprintf(stderr, "SD: Card is locked\n"); rtype = sd_illegal; goto send_response; @@ -1318,7 +1322,7 @@ int sd_do_command(SDState *sd, SDRequest *req, sd_set_mode(sd); if (sd->expecting_acmd) { - sd->expecting_acmd = 0; + sd->expecting_acmd = false; rtype = sd_app_command(sd, *req); } else { rtype = sd_normal_command(sd, *req); @@ -1699,12 +1703,12 @@ uint8_t sd_read_data(SDState *sd) return ret; } -int sd_data_ready(SDState *sd) +bool sd_data_ready(SDState *sd) { return sd->state == sd_sendingdata_state; } -void sd_enable(SDState *sd, int enable) +void sd_enable(SDState *sd, bool enable) { sd->enable = enable; } diff --git a/hw/sd.h b/hw/sd.h index ac4b7c4dfa..4eb9679acd 100644 --- a/hw/sd.h +++ b/hw/sd.h @@ -67,13 +67,13 @@ typedef struct { typedef struct SDState SDState; -SDState *sd_init(BlockDriverState *bs, int is_spi); +SDState *sd_init(BlockDriverState *bs, bool is_spi); int sd_do_command(SDState *sd, SDRequest *req, uint8_t *response); void sd_write_data(SDState *sd, uint8_t value); uint8_t sd_read_data(SDState *sd); void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert); -int sd_data_ready(SDState *sd); -void sd_enable(SDState *sd, int enable); +bool sd_data_ready(SDState *sd); +void sd_enable(SDState *sd, bool enable); #endif /* __hw_sd_h */ diff --git a/hw/ssd0323.c b/hw/ssd0323.c index b0b2e94a81..b101c5112c 100644 --- a/hw/ssd0323.c +++ b/hw/ssd0323.c @@ -19,7 +19,9 @@ #define DPRINTF(fmt, ...) \ do { printf("ssd0323: " fmt , ## __VA_ARGS__); } while (0) #define BADF(fmt, ...) \ -do { fprintf(stderr, "ssd0323: error: " fmt , ## __VA_ARGS__); exit(1);} while (0) +do { \ + fprintf(stderr, "ssd0323: error: " fmt , ## __VA_ARGS__); abort(); \ +} while (0) #else #define DPRINTF(fmt, ...) do {} while(0) #define BADF(fmt, ...) \ diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 125eded9ca..5e6e09efb7 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -627,7 +627,7 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign) int r, n; /* Must unset vector notifier while guest notifier is still assigned */ - if (kvm_irqchip_in_kernel() && !assign) { + if (kvm_msi_via_irqfd_enabled() && !assign) { msix_unset_vector_notifiers(&proxy->pci_dev); g_free(proxy->vector_irqfd); proxy->vector_irqfd = NULL; @@ -645,7 +645,7 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign) } /* Must set vector notifier after guest notifier has been assigned */ - if (kvm_irqchip_in_kernel() && assign) { + if (kvm_msi_via_irqfd_enabled() && assign) { proxy->vector_irqfd = g_malloc0(sizeof(*proxy->vector_irqfd) * msix_nr_vectors_allocated(&proxy->pci_dev)); diff --git a/include/qemu/page_cache.h b/include/qemu/page_cache.h new file mode 100644 index 0000000000..3839ac7726 --- /dev/null +++ b/include/qemu/page_cache.h @@ -0,0 +1,79 @@ +/* + * Page cache for QEMU + * The cache is base on a hash of the page address + * + * Copyright 2012 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Orit Wasserman <owasserm@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. + * + */ + +#ifndef PAGE_CACHE_H +#define PAGE_CACHE_H + +/* Page cache for storing guest pages */ +typedef struct PageCache PageCache; + +/** + * cache_init: Initialize the page cache + * + * + * Returns new allocated cache or NULL on error + * + * @cache pointer to the PageCache struct + * @num_pages: cache maximal number of cached pages + * @page_size: cache page size + */ +PageCache *cache_init(int64_t num_pages, unsigned int page_size); + +/** + * cache_fini: free all cache resources + * @cache pointer to the PageCache struct + */ +void cache_fini(PageCache *cache); + +/** + * cache_is_cached: Checks to see if the page is cached + * + * Returns %true if page is cached + * + * @cache pointer to the PageCache struct + * @addr: page addr + */ +bool cache_is_cached(const PageCache *cache, uint64_t addr); + +/** + * get_cached_data: Get the data cached for an addr + * + * Returns pointer to the data cached or NULL if not cached + * + * @cache pointer to the PageCache struct + * @addr: page addr + */ +uint8_t *get_cached_data(const PageCache *cache, uint64_t addr); + +/** + * cache_insert: insert the page into the cache. the previous value will be overwritten + * + * @cache pointer to the PageCache struct + * @addr: page address + * @pdata: pointer to the page + */ +void cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata); + +/** + * cache_resize: resize the page cache. In case of size reduction the extra + * pages will be freed + * + * Returns -1 on error new cache size on success + * + * @cache pointer to the PageCache struct + * @num_pages: new page cache size (in pages) + */ +int64_t cache_resize(PageCache *cache, int64_t num_pages); + +#endif diff --git a/kvm-all.c b/kvm-all.c index 2148b20bdb..34b02c1fba 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -100,6 +100,10 @@ struct KVMState KVMState *kvm_state; bool kvm_kernel_irqchip; +bool kvm_async_interrupts_allowed; +bool kvm_irqfds_allowed; +bool kvm_msi_via_irqfd_allowed; +bool kvm_gsi_routing_allowed; static const KVMCapabilityInfo kvm_required_capabilites[] = { KVM_CAP_INFO(USER_MEMORY), @@ -852,18 +856,18 @@ static void kvm_handle_interrupt(CPUArchState *env, int mask) } } -int kvm_irqchip_set_irq(KVMState *s, int irq, int level) +int kvm_set_irq(KVMState *s, int irq, int level) { struct kvm_irq_level event; int ret; - assert(kvm_irqchip_in_kernel()); + assert(kvm_async_interrupts_enabled()); event.level = level; event.irq = irq; ret = kvm_vm_ioctl(s, s->irqchip_inject_ioctl, &event); if (ret < 0) { - perror("kvm_set_irqchip_line"); + perror("kvm_set_irq"); abort(); } @@ -1088,7 +1092,7 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg) assert(route->kroute.type == KVM_IRQ_ROUTING_MSI); - return kvm_irqchip_set_irq(s, route->kroute.gsi, 1); + return kvm_set_irq(s, route->kroute.gsi, 1); } int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) @@ -1096,7 +1100,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) struct kvm_irq_routing_entry kroute; int virq; - if (!kvm_irqchip_in_kernel()) { + if (!kvm_gsi_routing_enabled()) { return -ENOSYS; } @@ -1125,7 +1129,7 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign) .flags = assign ? 0 : KVM_IRQFD_FLAG_DEASSIGN, }; - if (!kvm_irqchip_in_kernel()) { + if (!kvm_irqfds_enabled()) { return -ENOSYS; } @@ -1201,12 +1205,36 @@ static int kvm_irqchip_create(KVMState *s) s->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS; } kvm_kernel_irqchip = true; + /* If we have an in-kernel IRQ chip then we must have asynchronous + * interrupt delivery (though the reverse is not necessarily true) + */ + kvm_async_interrupts_allowed = true; kvm_init_irq_routing(s); return 0; } +static int kvm_max_vcpus(KVMState *s) +{ + int ret; + + /* Find number of supported CPUs using the recommended + * procedure from the kernel API documentation to cope with + * older kernels that may be missing capabilities. + */ + ret = kvm_check_extension(s, KVM_CAP_MAX_VCPUS); + if (ret) { + return ret; + } + ret = kvm_check_extension(s, KVM_CAP_NR_VCPUS); + if (ret) { + return ret; + } + + return 4; +} + int kvm_init(void) { static const char upgrade_note[] = @@ -1216,6 +1244,7 @@ int kvm_init(void) const KVMCapabilityInfo *missing_cap; int ret; int i; + int max_vcpus; s = g_malloc0(sizeof(KVMState)); @@ -1256,6 +1285,14 @@ int kvm_init(void) goto err; } + max_vcpus = kvm_max_vcpus(s); + if (smp_cpus > max_vcpus) { + ret = -EINVAL; + fprintf(stderr, "Number of SMP cpus requested (%d) exceeds max cpus " + "supported by KVM (%d)\n", smp_cpus, max_vcpus); + goto err; + } + s->vmfd = kvm_ioctl(s, KVM_CREATE_VM, 0); if (s->vmfd < 0) { #ifdef TARGET_S390X @@ -1667,11 +1704,6 @@ int kvm_has_gsi_routing(void) #endif } -int kvm_allows_irq0_override(void) -{ - return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing(); -} - void *kvm_vmalloc(ram_addr_t size) { #ifdef TARGET_S390X diff --git a/kvm-stub.c b/kvm-stub.c index d23b11c020..94c9ea15b0 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -19,6 +19,10 @@ KVMState *kvm_state; bool kvm_kernel_irqchip; +bool kvm_async_interrupts_allowed; +bool kvm_irqfds_allowed; +bool kvm_msi_via_irqfd_allowed; +bool kvm_gsi_routing_allowed; int kvm_init_vcpu(CPUArchState *env) { @@ -71,11 +75,6 @@ int kvm_has_many_ioeventfds(void) return 0; } -int kvm_allows_irq0_override(void) -{ - return 1; -} - int kvm_has_pit_state2(void) { return 0; diff --git a/kvm.h b/kvm.h index 2617dd5acd..5b8f588813 100644 --- a/kvm.h +++ b/kvm.h @@ -24,13 +24,69 @@ extern int kvm_allowed; extern bool kvm_kernel_irqchip; +extern bool kvm_async_interrupts_allowed; +extern bool kvm_irqfds_allowed; +extern bool kvm_msi_via_irqfd_allowed; +extern bool kvm_gsi_routing_allowed; #if defined CONFIG_KVM || !defined NEED_CPU_H #define kvm_enabled() (kvm_allowed) +/** + * kvm_irqchip_in_kernel: + * + * Returns: true if the user asked us to create an in-kernel + * irqchip via the "kernel_irqchip=on" machine option. + * What this actually means is architecture and machine model + * specific: on PC, for instance, it means that the LAPIC, + * IOAPIC and PIT are all in kernel. This function should never + * be used from generic target-independent code: use one of the + * following functions or some other specific check instead. + */ #define kvm_irqchip_in_kernel() (kvm_kernel_irqchip) + +/** + * kvm_async_interrupts_enabled: + * + * Returns: true if we can deliver interrupts to KVM + * asynchronously (ie by ioctl from any thread at any time) + * rather than having to do interrupt delivery synchronously + * (where the vcpu must be stopped at a suitable point first). + */ +#define kvm_async_interrupts_enabled() (kvm_async_interrupts_allowed) + +/** + * kvm_irqfds_enabled: + * + * Returns: true if we can use irqfds to inject interrupts into + * a KVM CPU (ie the kernel supports irqfds and we are running + * with a configuration where it is meaningful to use them). + */ +#define kvm_irqfds_enabled() (kvm_irqfds_allowed) + +/** + * kvm_msi_via_irqfd_enabled: + * + * Returns: true if we can route a PCI MSI (Message Signaled Interrupt) + * to a KVM CPU via an irqfd. This requires that the kernel supports + * this and that we're running in a configuration that permits it. + */ +#define kvm_msi_via_irqfd_enabled() (kvm_msi_via_irqfd_allowed) + +/** + * kvm_gsi_routing_enabled: + * + * Returns: true if GSI routing is enabled (ie the kernel supports + * it and we're running in a configuration that permits it). + */ +#define kvm_gsi_routing_enabled() (kvm_gsi_routing_allowed) + #else #define kvm_enabled() (0) #define kvm_irqchip_in_kernel() (false) +#define kvm_async_interrupts_enabled() (false) +#define kvm_irqfds_enabled() (false) +#define kvm_msi_via_irqfd_enabled() (false) +#define kvm_gsi_routing_allowed() (false) #endif struct kvm_run; @@ -62,8 +118,6 @@ int kvm_has_pit_state2(void); int kvm_has_many_ioeventfds(void); int kvm_has_gsi_routing(void); -int kvm_allows_irq0_override(void); - #ifdef NEED_CPU_H int kvm_init_vcpu(CPUArchState *env); @@ -133,7 +187,7 @@ int kvm_arch_on_sigbus(int code, void *addr); void kvm_arch_init_irq_routing(KVMState *s); -int kvm_irqchip_set_irq(KVMState *s, int irq, int level); +int kvm_set_irq(KVMState *s, int irq, int level); int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg); void kvm_irqchip_add_irq_route(KVMState *s, int gsi, int irqchip, int pin); diff --git a/migration-tcp.c b/migration-tcp.c index 440804db75..ac891c38a3 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -82,27 +82,23 @@ static void tcp_wait_for_connect(void *opaque) int tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp) { + bool in_progress; + s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; - s->fd = inet_connect(host_port, false, errp); + s->fd = inet_connect(host_port, false, &in_progress, errp); + if (error_is_set(errp)) { + migrate_fd_error(s); + return -1; + } - if (!error_is_set(errp)) { - migrate_fd_connect(s); - } else if (error_is_type(*errp, QERR_SOCKET_CONNECT_IN_PROGRESS)) { + if (in_progress) { DPRINTF("connect in progress\n"); qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s); - } else if (error_is_type(*errp, QERR_SOCKET_CREATE_FAILED)) { - DPRINTF("connect failed\n"); - return -1; - } else if (error_is_type(*errp, QERR_SOCKET_CONNECT_FAILED)) { - DPRINTF("connect failed\n"); - migrate_fd_error(s); - return -1; } else { - DPRINTF("unknown error\n"); - return -1; + migrate_fd_connect(s); } return 0; diff --git a/migration.c b/migration.c index 8db1b433f0..653a3c1a88 100644 --- a/migration.c +++ b/migration.c @@ -43,6 +43,9 @@ enum { #define MAX_THROTTLE (32 << 20) /* Migration speed throttling */ +/* Migration XBZRLE default cache size */ +#define DEFAULT_MIGRATE_CACHE_SIZE (64 * 1024 * 1024) + static NotifierList migration_state_notifiers = NOTIFIER_LIST_INITIALIZER(migration_state_notifiers); @@ -55,6 +58,7 @@ static MigrationState *migrate_get_current(void) static MigrationState current_migration = { .state = MIG_STATE_SETUP, .bandwidth_limit = MAX_THROTTLE, + .xbzrle_cache_size = DEFAULT_MIGRATE_CACHE_SIZE, }; return ¤t_migration; @@ -113,6 +117,43 @@ uint64_t migrate_max_downtime(void) return max_downtime; } +MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp) +{ + MigrationCapabilityStatusList *head = NULL; + MigrationCapabilityStatusList *caps; + MigrationState *s = migrate_get_current(); + int i; + + for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) { + if (head == NULL) { + head = g_malloc0(sizeof(*caps)); + caps = head; + } else { + caps->next = g_malloc0(sizeof(*caps)); + caps = caps->next; + } + caps->value = + g_malloc(sizeof(*caps->value)); + caps->value->capability = i; + caps->value->state = s->enabled_capabilities[i]; + } + + return head; +} + +static void get_xbzrle_cache_stats(MigrationInfo *info) +{ + if (migrate_use_xbzrle()) { + info->has_xbzrle_cache = true; + info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache)); + info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size(); + info->xbzrle_cache->bytes = xbzrle_mig_bytes_transferred(); + info->xbzrle_cache->pages = xbzrle_mig_pages_transferred(); + info->xbzrle_cache->cache_miss = xbzrle_mig_pages_cache_miss(); + info->xbzrle_cache->overflow = xbzrle_mig_pages_overflow(); + } +} + MigrationInfo *qmp_query_migrate(Error **errp) { MigrationInfo *info = g_malloc0(sizeof(*info)); @@ -133,6 +174,9 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->ram->total = ram_bytes_total(); info->ram->total_time = qemu_get_clock_ms(rt_clock) - s->total_time; + info->ram->duplicate = dup_mig_pages_transferred(); + info->ram->normal = norm_mig_pages_transferred(); + info->ram->normal_bytes = norm_mig_bytes_transferred(); if (blk_mig_active()) { info->has_disk = true; @@ -141,8 +185,12 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->disk->remaining = blk_mig_bytes_remaining(); info->disk->total = blk_mig_bytes_total(); } + + get_xbzrle_cache_stats(info); break; case MIG_STATE_COMPLETED: + get_xbzrle_cache_stats(info); + info->has_status = true; info->status = g_strdup("completed"); @@ -152,6 +200,9 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->ram->remaining = 0; info->ram->total = ram_bytes_total(); info->ram->total_time = s->total_time; + info->ram->duplicate = dup_mig_pages_transferred(); + info->ram->normal = norm_mig_pages_transferred(); + info->ram->normal_bytes = norm_mig_bytes_transferred(); break; case MIG_STATE_ERROR: info->has_status = true; @@ -166,6 +217,22 @@ MigrationInfo *qmp_query_migrate(Error **errp) return info; } +void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, + Error **errp) +{ + MigrationState *s = migrate_get_current(); + MigrationCapabilityStatusList *cap; + + if (s->state == MIG_STATE_ACTIVE) { + error_set(errp, QERR_MIGRATION_ACTIVE); + return; + } + + for (cap = params; cap; cap = cap->next) { + s->enabled_capabilities[cap->value->capability] = cap->value->state; + } +} + /* shared migration helpers */ static int migrate_fd_cleanup(MigrationState *s) @@ -375,10 +442,18 @@ static MigrationState *migrate_init(const MigrationParams *params) { MigrationState *s = migrate_get_current(); int64_t bandwidth_limit = s->bandwidth_limit; + bool enabled_capabilities[MIGRATION_CAPABILITY_MAX]; + int64_t xbzrle_cache_size = s->xbzrle_cache_size; + + memcpy(enabled_capabilities, s->enabled_capabilities, + sizeof(enabled_capabilities)); memset(s, 0, sizeof(*s)); s->bandwidth_limit = bandwidth_limit; s->params = *params; + memcpy(s->enabled_capabilities, enabled_capabilities, + sizeof(enabled_capabilities)); + s->xbzrle_cache_size = xbzrle_cache_size; s->bandwidth_limit = bandwidth_limit; s->state = MIG_STATE_SETUP; @@ -459,6 +534,25 @@ void qmp_migrate_cancel(Error **errp) migrate_fd_cancel(migrate_get_current()); } +void qmp_migrate_set_cache_size(int64_t value, Error **errp) +{ + MigrationState *s = migrate_get_current(); + + /* Check for truncation */ + if (value != (size_t)value) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cache size", + "exceeding address space"); + return; + } + + s->xbzrle_cache_size = xbzrle_cache_resize(value); +} + +int64_t qmp_query_migrate_cache_size(Error **errp) +{ + return migrate_xbzrle_cache_size(); +} + void qmp_migrate_set_speed(int64_t value, Error **errp) { MigrationState *s; @@ -478,3 +572,21 @@ void qmp_migrate_set_downtime(double value, Error **errp) value = MAX(0, MIN(UINT64_MAX, value)); max_downtime = (uint64_t)value; } + +int migrate_use_xbzrle(void) +{ + MigrationState *s; + + s = migrate_get_current(); + + return s->enabled_capabilities[MIGRATION_CAPABILITY_XBZRLE]; +} + +int64_t migrate_xbzrle_cache_size(void) +{ + MigrationState *s; + + s = migrate_get_current(); + + return s->xbzrle_cache_size; +} diff --git a/migration.h b/migration.h index 57572a61e9..a9852fcae0 100644 --- a/migration.h +++ b/migration.h @@ -19,6 +19,7 @@ #include "notify.h" #include "error.h" #include "vmstate.h" +#include "qapi-types.h" struct MigrationParams { bool blk; @@ -39,6 +40,8 @@ struct MigrationState void *opaque; MigrationParams params; int64_t total_time; + bool enabled_capabilities[MIGRATION_CAPABILITY_MAX]; + int64_t xbzrle_cache_size; }; void process_incoming_migration(QEMUFile *f); @@ -84,6 +87,15 @@ uint64_t ram_bytes_total(void); extern SaveVMHandlers savevm_ram_handlers; +uint64_t dup_mig_bytes_transferred(void); +uint64_t dup_mig_pages_transferred(void); +uint64_t norm_mig_bytes_transferred(void); +uint64_t norm_mig_pages_transferred(void); +uint64_t xbzrle_mig_bytes_transferred(void); +uint64_t xbzrle_mig_pages_transferred(void); +uint64_t xbzrle_mig_pages_overflow(void); +uint64_t xbzrle_mig_pages_cache_miss(void); + /** * @migrate_add_blocker - prevent migration from proceeding * @@ -98,4 +110,13 @@ void migrate_add_blocker(Error *reason); */ void migrate_del_blocker(Error *reason); +int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen, + uint8_t *dst, int dlen); +int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen); + +int migrate_use_xbzrle(void); +int64_t migrate_xbzrle_cache_size(void); + +int64_t xbzrle_cache_resize(int64_t new_size); + #endif diff --git a/monitor.c b/monitor.c index 49dccfe854..dd63f1d640 100644 --- a/monitor.c +++ b/monitor.c @@ -172,41 +172,11 @@ struct Monitor { CPUArchState *mon_cpu; BlockDriverCompletionFunc *password_completion_cb; void *password_opaque; -#ifdef CONFIG_DEBUG_MONITOR - int print_calls_nr; -#endif QError *error; QLIST_HEAD(,mon_fd_t) fds; QLIST_ENTRY(Monitor) entry; }; -#ifdef CONFIG_DEBUG_MONITOR -#define MON_DEBUG(fmt, ...) do { \ - fprintf(stderr, "Monitor: "); \ - fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) - -static inline void mon_print_count_inc(Monitor *mon) -{ - mon->print_calls_nr++; -} - -static inline void mon_print_count_init(Monitor *mon) -{ - mon->print_calls_nr = 0; -} - -static inline int mon_print_count_get(const Monitor *mon) -{ - return mon->print_calls_nr; -} - -#else /* !CONFIG_DEBUG_MONITOR */ -#define MON_DEBUG(fmt, ...) do { } while (0) -static inline void mon_print_count_inc(Monitor *mon) { } -static inline void mon_print_count_init(Monitor *mon) { } -static inline int mon_print_count_get(const Monitor *mon) { return 0; } -#endif /* CONFIG_DEBUG_MONITOR */ - /* QMP checker flags */ #define QMP_ACCEPT_UNKNOWNS 1 @@ -299,8 +269,6 @@ void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) if (!mon) return; - mon_print_count_inc(mon); - if (monitor_ctrl_mode(mon)) { return; } @@ -385,16 +353,26 @@ static void monitor_json_emitter(Monitor *mon, const QObject *data) QDECREF(json); } +static QDict *build_qmp_error_dict(const QError *err) +{ + QObject *obj; + + obj = qobject_from_jsonf("{ 'error': { 'class': %s, 'desc': %p } }", + ErrorClass_lookup[err->err_class], + qerror_human(err)); + + return qobject_to_qdict(obj); +} + static void monitor_protocol_emitter(Monitor *mon, QObject *data) { QDict *qmp; trace_monitor_protocol_emitter(mon); - qmp = qdict_new(); - if (!monitor_has_error(mon)) { /* success response */ + qmp = qdict_new(); if (data) { qobject_incref(data); qdict_put_obj(qmp, "return", data); @@ -404,9 +382,7 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data) } } else { /* error response */ - qdict_put(mon->error->error, "desc", qerror_human(mon->error)); - qdict_put(qmp, "error", mon->error->error); - QINCREF(mon->error->error); + qmp = build_qmp_error_dict(mon->error); QDECREF(mon->error); mon->error = NULL; } @@ -456,6 +432,7 @@ static const char *monitor_event_names[] = { [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED", [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED", [QEVENT_SUSPEND] = "SUSPEND", + [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK", [QEVENT_WAKEUP] = "WAKEUP", [QEVENT_BALLOON_CHANGE] = "BALLOON_CHANGE", }; @@ -2655,6 +2632,20 @@ static mon_cmd_t info_cmds[] = { .mhandler.info = hmp_info_migrate, }, { + .name = "migrate_capabilities", + .args_type = "", + .params = "", + .help = "show current migration capabilities", + .mhandler.info = hmp_info_migrate_capabilities, + }, + { + .name = "migrate_cache_size", + .args_type = "", + .params = "", + .help = "show current migration xbzrle cache size", + .mhandler.info = hmp_info_migrate_cache_size, + }, + { .name = "balloon", .args_type = "", .params = "", @@ -3860,8 +3851,6 @@ void monitor_set_error(Monitor *mon, QError *qerror) if (!mon->error) { mon->error = qerror; } else { - MON_DEBUG("Additional error report at %s:%d\n", - qerror->file, qerror->linenr); QDECREF(qerror); } } @@ -3875,36 +3864,7 @@ static void handler_audit(Monitor *mon, const mon_cmd_t *cmd, int ret) * Action: Report an internal error to the client if in QMP. */ qerror_report(QERR_UNDEFINED_ERROR); - MON_DEBUG("command '%s' returned failure but did not pass an error\n", - cmd->name); } - -#ifdef CONFIG_DEBUG_MONITOR - if (!ret && monitor_has_error(mon)) { - /* - * If it returns success, it must not have passed an error. - * - * Action: Report the passed error to the client. - */ - MON_DEBUG("command '%s' returned success but passed an error\n", - cmd->name); - } - - if (mon_print_count_get(mon) > 0 && strcmp(cmd->name, "info") != 0) { - /* - * Handlers should not call Monitor print functions. - * - * Action: Ignore them in QMP. - * - * (XXX: we don't check any 'info' or 'query' command here - * because the user print function _is_ called by do_info(), hence - * we will trigger this check. This problem will go away when we - * make 'query' commands real and kill do_info()) - */ - MON_DEBUG("command '%s' called print functions %d time(s)\n", - cmd->name, mon_print_count_get(mon)); - } -#endif } static void handle_user_command(Monitor *mon, const char *cmdline) @@ -4433,8 +4393,6 @@ static void qmp_call_cmd(Monitor *mon, const mon_cmd_t *cmd, int ret; QObject *data = NULL; - mon_print_count_init(mon); - ret = cmd->mhandler.cmd_new(mon, params, &data); handler_audit(mon, cmd, ret); monitor_protocol_emitter(mon, data); diff --git a/monitor.h b/monitor.h index 5f4de1b3da..4ef9a046f8 100644 --- a/monitor.h +++ b/monitor.h @@ -40,6 +40,7 @@ typedef enum MonitorEvent { QEVENT_BLOCK_JOB_CANCELLED, QEVENT_DEVICE_TRAY_MOVED, QEVENT_SUSPEND, + QEVENT_SUSPEND_DISK, QEVENT_WAKEUP, QEVENT_BALLOON_CHANGE, diff --git a/nbd.c b/nbd.c index dc0adf90ed..0dd60c5f4c 100644 --- a/nbd.c +++ b/nbd.c @@ -162,7 +162,7 @@ int tcp_socket_outgoing(const char *address, uint16_t port) int tcp_socket_outgoing_spec(const char *address_and_port) { - return inet_connect(address_and_port, true, NULL); + return inet_connect(address_and_port, true, NULL, NULL); } int tcp_socket_incoming(const char *address, uint16_t port) diff --git a/page_cache.c b/page_cache.c new file mode 100644 index 0000000000..0294f7e9f6 --- /dev/null +++ b/page_cache.c @@ -0,0 +1,218 @@ +/* + * Page cache for QEMU + * The cache is base on a hash of the page address + * + * Copyright 2012 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Orit Wasserman <owasserm@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. + * + */ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <string.h> +#include <sys/time.h> +#include <sys/types.h> +#include <stdbool.h> +#include <glib.h> +#include <strings.h> + +#include "qemu-common.h" +#include "qemu/page_cache.h" + +#ifdef DEBUG_CACHE +#define DPRINTF(fmt, ...) \ + do { fprintf(stdout, "cache: " fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ + do { } while (0) +#endif + +typedef struct CacheItem CacheItem; + +struct CacheItem { + uint64_t it_addr; + uint64_t it_age; + uint8_t *it_data; +}; + +struct PageCache { + CacheItem *page_cache; + unsigned int page_size; + int64_t max_num_items; + uint64_t max_item_age; + int64_t num_items; +}; + +PageCache *cache_init(int64_t num_pages, unsigned int page_size) +{ + int64_t i; + + PageCache *cache; + + if (num_pages <= 0) { + DPRINTF("invalid number of pages\n"); + return NULL; + } + + cache = g_malloc(sizeof(*cache)); + + /* round down to the nearest power of 2 */ + if (!is_power_of_2(num_pages)) { + num_pages = pow2floor(num_pages); + DPRINTF("rounding down to %" PRId64 "\n", num_pages); + } + cache->page_size = page_size; + cache->num_items = 0; + cache->max_item_age = 0; + cache->max_num_items = num_pages; + + DPRINTF("Setting cache buckets to %" PRId64 "\n", cache->max_num_items); + + cache->page_cache = g_malloc((cache->max_num_items) * + sizeof(*cache->page_cache)); + + for (i = 0; i < cache->max_num_items; i++) { + cache->page_cache[i].it_data = NULL; + cache->page_cache[i].it_age = 0; + cache->page_cache[i].it_addr = -1; + } + + return cache; +} + +void cache_fini(PageCache *cache) +{ + int64_t i; + + g_assert(cache); + g_assert(cache->page_cache); + + for (i = 0; i < cache->max_num_items; i++) { + g_free(cache->page_cache[i].it_data); + } + + g_free(cache->page_cache); + cache->page_cache = NULL; +} + +static size_t cache_get_cache_pos(const PageCache *cache, + uint64_t address) +{ + size_t pos; + + g_assert(cache->max_num_items); + pos = (address / cache->page_size) & (cache->max_num_items - 1); + return pos; +} + +bool cache_is_cached(const PageCache *cache, uint64_t addr) +{ + size_t pos; + + g_assert(cache); + g_assert(cache->page_cache); + + pos = cache_get_cache_pos(cache, addr); + + return (cache->page_cache[pos].it_addr == addr); +} + +static CacheItem *cache_get_by_addr(const PageCache *cache, uint64_t addr) +{ + size_t pos; + + g_assert(cache); + g_assert(cache->page_cache); + + pos = cache_get_cache_pos(cache, addr); + + return &cache->page_cache[pos]; +} + +uint8_t *get_cached_data(const PageCache *cache, uint64_t addr) +{ + return cache_get_by_addr(cache, addr)->it_data; +} + +void cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata) +{ + + CacheItem *it = NULL; + + g_assert(cache); + g_assert(cache->page_cache); + + /* actual update of entry */ + it = cache_get_by_addr(cache, addr); + + if (!it->it_data) { + cache->num_items++; + } + + it->it_data = pdata; + it->it_age = ++cache->max_item_age; + it->it_addr = addr; +} + +int64_t cache_resize(PageCache *cache, int64_t new_num_pages) +{ + PageCache *new_cache; + int64_t i; + + CacheItem *old_it, *new_it; + + g_assert(cache); + + /* cache was not inited */ + if (cache->page_cache == NULL) { + return -1; + } + + /* same size */ + if (pow2floor(new_num_pages) == cache->max_num_items) { + return cache->max_num_items; + } + + new_cache = cache_init(new_num_pages, cache->page_size); + if (!(new_cache)) { + DPRINTF("Error creating new cache\n"); + return -1; + } + + /* move all data from old cache */ + for (i = 0; i < cache->max_num_items; i++) { + old_it = &cache->page_cache[i]; + if (old_it->it_addr != -1) { + /* check for collision, if there is, keep MRU page */ + new_it = cache_get_by_addr(new_cache, old_it->it_addr); + if (new_it->it_data) { + /* keep the MRU page */ + if (new_it->it_age >= old_it->it_age) { + g_free(old_it->it_data); + } else { + g_free(new_it->it_data); + new_it->it_data = old_it->it_data; + new_it->it_age = old_it->it_age; + new_it->it_addr = old_it->it_addr; + } + } else { + cache_insert(new_cache, old_it->it_addr, old_it->it_data); + } + } + } + + cache->page_cache = new_cache->page_cache; + cache->max_num_items = new_cache->max_num_items; + cache->num_items = new_cache->num_items; + + g_free(new_cache); + + return cache->max_num_items; +} diff --git a/qapi-schema.json b/qapi-schema.json index bd9c450029..53bbe46e4d 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -3,6 +3,36 @@ # QAPI Schema ## +# @ErrorClass +# +# QEMU error classes +# +# @GenericError: this is used for errors that don't require a specific error +# class. This should be the default case for most errors +# +# @CommandNotFound: the requested command has not been found +# +# @DeviceEncrypted: the requested operation can't be fulfilled because the +# selected device is encrypted +# +# @DeviceNotActive: a device has failed to be become active +# +# @DeviceNotFound: the requested device has not been found +# +# @KVMMissingCap: the requested operation can't be fulfilled because a +# required KVM capability is missing +# +# @MigrationExpected: the requested operation can't be fulfilled because a +# migration process is expected +# +# Since: 1.2 +## +{ 'enum': 'ErrorClass', + 'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted', + 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap', + 'MigrationExpected' ] } + +## # @NameInfo: # # Guest name information. @@ -260,15 +290,43 @@ # # @total: total amount of bytes involved in the migration process # -# @total_time: tota0l amount of ms since migration started. If +# @total-time: total amount of ms since migration started. If # migration has ended, it returns the total migration # time. (since 1.2) # -# Since: 0.14.0. +# @duplicate: number of duplicate pages (since 1.2) +# +# @normal : number of normal pages (since 1.2) +# +# @normal-bytes : number of normal bytes sent (since 1.2) +# +# Since: 0.14.0 ## { 'type': 'MigrationStats', 'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' , - 'total_time': 'int' } } + 'total-time': 'int', 'duplicate': 'int', 'normal': 'int', + 'normal-bytes': 'int' } } + +## +# @XBZRLECacheStats +# +# Detailed XBZRLE migration cache statistics +# +# @cache-size: XBZRLE cache size +# +# @bytes: amount of bytes already transferred to the target VM +# +# @pages: amount of pages transferred to the target VM +# +# @cache-miss: number of cache miss +# +# @overflow: number of overflows +# +# Since: 1.2 +## +{ 'type': 'XBZRLECacheStats', + 'data': {'cache-size': 'int', 'bytes': 'int', 'pages': 'int', + 'cache-miss': 'int', 'overflow': 'int' } } ## # @MigrationInfo @@ -288,11 +346,16 @@ # status, only returned if status is 'active' and it is a block # migration # +# @xbzrle-cache: #optional @XBZRLECacheStats containing detailed XBZRLE +# migration statistics, only returned if XBZRLE feature is on and +# status is 'active' or 'completed' (since 1.2) +# # Since: 0.14.0 ## { 'type': 'MigrationInfo', 'data': {'*status': 'str', '*ram': 'MigrationStats', - '*disk': 'MigrationStats'} } + '*disk': 'MigrationStats', + '*xbzrle-cache': 'XBZRLECacheStats'} } ## # @query-migrate @@ -306,6 +369,57 @@ { 'command': 'query-migrate', 'returns': 'MigrationInfo' } ## +# @MigrationCapability +# +# Migration capabilities enumeration +# +# @xbzrle: Migration supports xbzrle (Xor Based Zero Run Length Encoding). +# This feature allows us to minimize migration traffic for certain work +# loads, by sending compressed difference of the pages +# +# Since: 1.2 +## +{ 'enum': 'MigrationCapability', + 'data': ['xbzrle'] } + +## +# @MigrationCapabilityStatus +# +# Migration capability information +# +# @capability: capability enum +# +# @state: capability state bool +# +# Since: 1.2 +## +{ 'type': 'MigrationCapabilityStatus', + 'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } } + +## +# @migrate-set-capabilities +# +# Enable/Disable the following migration capabilities (like xbzrle) +# +# @capabilities: json array of capability modifications to make +# +# Since: 1.2 +## +{ 'command': 'migrate-set-capabilities', + 'data': { 'capabilities': ['MigrationCapabilityStatus'] } } + +## +# @query-migrate-capabilities +# +# Returns information about the current migration capabilities status +# +# Returns: @MigrationCapabilitiesStatus +# +# Since: 1.2 +## +{ 'command': 'query-migrate-capabilities', 'returns': ['MigrationCapabilityStatus']} + +## # @MouseInfo: # # Information about a mouse device. @@ -402,6 +516,9 @@ # # @encrypted: true if the backing device is encrypted # +# @encryption_key_missing: true if the backing device is encrypted but an +# valid encryption key is missing +# # @bps: total throughput limit in bytes per second is specified # # @bps_rd: read throughput limit in bytes per second is specified @@ -421,9 +538,9 @@ { 'type': 'BlockDeviceInfo', 'data': { 'file': 'str', 'ro': 'bool', 'drv': 'str', '*backing_file': 'str', 'backing_file_depth': 'int', - 'encrypted': 'bool', 'bps': 'int', 'bps_rd': 'int', - 'bps_wr': 'int', 'iops': 'int', 'iops_rd': 'int', - 'iops_wr': 'int'} } + 'encrypted': 'bool', 'encryption_key_missing': 'bool', + 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int', + 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int'} } ## # @BlockDeviceIoStatus: @@ -625,7 +742,6 @@ # Returns information about the current VNC server # # Returns: @VncInfo -# If VNC support is not compiled in, FeatureDisabled # # Since: 0.14.0 ## @@ -1009,9 +1125,6 @@ # virtual address (defaults to CPU 0) # # Returns: Nothing on success -# If @cpu is not a valid VCPU, InvalidParameterValue -# If @filename cannot be opened, OpenFileFailed -# If an I/O error occurs while writing the file, IOError # # Since: 0.14.0 # @@ -1032,8 +1145,6 @@ # @filename: the file to save the memory to as binary data # # Returns: Nothing on success -# If @filename cannot be opened, OpenFileFailed -# If an I/O error occurs while writing the file, IOError # # Since: 0.14.0 # @@ -1075,7 +1186,6 @@ # Injects an Non-Maskable Interrupt into all guest's VCPUs. # # Returns: If successful, nothing -# If the Virtual Machine doesn't support NMI injection, Unsupported # # Since: 0.14.0 # @@ -1126,7 +1236,6 @@ # Returns: nothing on success # If @device is not a valid block device, DeviceNotFound # If @device is not encrypted, DeviceNotEncrypted -# If @password is not valid for this device, InvalidPassword # # Notes: Not all block formats support encryption and some that do are not # able to validate that a password is correct. Disk corruption may @@ -1167,11 +1276,6 @@ # # Returns: nothing on success # If @device is not a valid block device, DeviceNotFound -# If @size is negative, InvalidParameterValue -# If the block device has no medium inserted, DeviceHasNoMedium -# If the block device does not support resize, Unsupported -# If the block device is read-only, DeviceIsReadOnly -# If a long-running operation is using the device, DeviceInUse # # Since: 0.14.0 ## @@ -1233,10 +1337,6 @@ # # Returns: nothing on success # If @device is not a valid block device, DeviceNotFound -# If @device is busy, DeviceInUse will be returned -# If @snapshot-file can't be created, OpenFileFailed -# If @snapshot-file can't be opened, OpenFileFailed -# If @format is invalid, InvalidBlockFormat # # Note: The transaction aborts on the first failure. Therefore, there will # be only one device or snapshot file returned in an error condition, and @@ -1265,8 +1365,6 @@ # # Returns: nothing on success # If @device is not a valid block device, DeviceNotFound -# If @snapshot-file can't be opened, OpenFileFailed -# If @format is invalid, InvalidBlockFormat # # Since 0.14.0 ## @@ -1344,6 +1442,33 @@ { 'command': 'migrate_set_speed', 'data': {'value': 'int'} } ## +# @migrate-set-cache-size +# +# Set XBZRLE cache size +# +# @value: cache size in bytes +# +# The size will be rounded down to the nearest power of 2. +# The cache size can be modified before and during ongoing migration +# +# Returns: nothing on success +# +# Since: 1.2 +## +{ 'command': 'migrate-set-cache-size', 'data': {'value': 'int'} } + +## +# @query-migrate-cache-size +# +# query XBZRLE cache size +# +# Returns: XBZRLE cache size in bytes +# +# Since: 1.2 +## +{ 'command': 'query-migrate-cache-size', 'returns': 'int' } + +## # @ObjectPropertyInfo: # # @name: the name of the property @@ -1363,9 +1488,7 @@ # 4) A link type in the form 'link<subtype>' where subtype is a qdev # device type name. Link properties form the device model graph. # -# Since: 1.1 -# -# Notes: This type is experimental. Its syntax may change in future releases. +# Since: 1.2 ## { 'type': 'ObjectPropertyInfo', 'data': { 'name': 'str', 'type': 'str' } } @@ -1382,10 +1505,7 @@ # Returns: a list of @ObjectPropertyInfo that describe the properties of the # object. # -# Since: 1.1 -# -# Notes: This command is experimental. It's syntax may change in future -# releases. +# Since: 1.2 ## { 'command': 'qom-list', 'data': { 'path': 'str' }, @@ -1421,9 +1541,7 @@ # returns as #str pathnames. All integer property types (u8, u16, etc) # are returned as #int. # -# Since: 1.1 -# -# Notes: This command is experimental and may change syntax in future releases. +# Since: 1.2 ## { 'command': 'qom-get', 'data': { 'path': 'str', 'property': 'str' }, @@ -1442,9 +1560,7 @@ # @value: a value who's type is appropriate for the property type. See @qom-get # for a description of type mapping. # -# Since: 1.1 -# -# Notes: This command is experimental and may change syntax in future releases. +# Since: 1.2 ## { 'command': 'qom-set', 'data': { 'path': 'str', 'property': 'str', 'value': 'visitor' }, @@ -1468,11 +1584,6 @@ # # Returns: Nothing on success # If Spice is not enabled, DeviceNotFound -# If @protocol does not support connected, InvalidParameter -# If @protocol is invalid, InvalidParameter -# If any other error occurs, SetPasswdFailed -# -# Notes: If VNC is not enabled, SetPasswdFailed is returned. # # Since: 0.14.0 ## @@ -1494,8 +1605,6 @@ # # Returns: Nothing on success # If @protocol is `spice' and Spice is not active, DeviceNotFound -# If an error occurs setting password expiration, SetPasswdFailed -# If @protocol is not `spice' or 'vnc', InvalidParameter # # Since: 0.14.0 # @@ -1518,8 +1627,6 @@ # # Returns: Nothing on success # If @device is not a valid block device, DeviceNotFound -# If @device is not removable and @force is false, DeviceNotRemovable -# If @force is false and @device is locked, DeviceLocked # # Notes: Ejecting a device will no media results in success # @@ -1562,7 +1669,6 @@ # # Returns: Nothing on success. # If @device is not a valid block device, DeviceNotFound -# If @format is not a valid block format, InvalidBlockFormat # If the new block device is encrypted, DeviceEncrypted. Note that # if this error is returned, the device has been opened successfully # and an additional call to @block_passwd is required to set the @@ -1598,7 +1704,6 @@ # # Returns: Nothing on success # If @device is not a valid block device, DeviceNotFound -# If the argument combination is invalid, InvalidParameterCombination # # Since: 1.1 ## @@ -1632,11 +1737,7 @@ # @speed: #optional the maximum speed, in bytes per second # # Returns: Nothing on success -# If streaming is already active on this device, DeviceInUse # If @device does not exist, DeviceNotFound -# If image streaming is not supported by this device, NotSupported -# If @base does not exist, BaseNotFound -# If @speed is invalid, InvalidParameter # # Since: 1.1 ## @@ -1658,8 +1759,6 @@ # Defaults to 0. # # Returns: Nothing on success -# If the job type does not support throttling, NotSupported -# If the speed value is invalid, InvalidParameter # If no background operation is active on this device, DeviceNotActive # # Since: 1.1 @@ -1689,7 +1788,6 @@ # # Returns: Nothing on success # If no background operation is active on this device, DeviceNotActive -# If cancellation already in progress, DeviceInUse # # Since: 1.1 ## @@ -1721,14 +1819,40 @@ # Returns: a list of @ObjectTypeInfo or an empty list if no results are found # # Since: 1.1 -# -# Notes: This command is experimental and may change syntax in future releases. ## { 'command': 'qom-list-types', 'data': { '*implements': 'str', '*abstract': 'bool' }, 'returns': [ 'ObjectTypeInfo' ] } ## +# @DevicePropertyInfo: +# +# Information about device properties. +# +# @name: the name of the property +# @type: the typename of the property +# +# Since: 1.2 +## +{ 'type': 'DevicePropertyInfo', + 'data': { 'name': 'str', 'type': 'str' } } + +## +# @device-list-properties: +# +# List properties associated with a device. +# +# @typename: the type name of a device +# +# Returns: a list of DevicePropertyInfo describing a devices properties +# +# Since: 1.2 +## +{ 'command': 'device-list-properties', + 'data': { 'typename': 'str'}, + 'returns': [ 'DevicePropertyInfo' ] } + +## # @migrate # # Migrates the current running guest to another Virtual Machine. @@ -1759,8 +1883,6 @@ # format. # # Returns: Nothing on success -# If @filename cannot be opened, OpenFileFailed -# If an I/O error occurs while writing the file, IOError # # Since: 1.1 ## @@ -1775,7 +1897,6 @@ # # Returns: Nothing on success # If @id is not a valid device, DeviceNotFound -# If the device does not support unplug, BusNoHotplug # # Notes: When this command completes, the device may not be removed from the # guest. Hot removal is an operation that requires guest cooperation. @@ -1816,14 +1937,6 @@ # want to dump all guest's memory, please specify the start @begin and @length # # Returns: nothing on success -# If @begin contains an invalid address, InvalidParameter -# If only one of @begin and @length is specified, MissingParameter -# If @protocol stats with "fd:", and the fd cannot be found, FdNotFound -# If @protocol starts with "file:", and the file cannot be -# opened, OpenFileFailed -# If @protocol does not start with "fd:" or "file:", InvalidParameter -# If an I/O error occurs while writing the file, IOError -# If the target does not support this command, Unsupported # # Since: 1.2 ## @@ -1850,10 +1963,6 @@ # # Returns: Nothing on success # If @type is not a valid network backend, DeviceNotFound -# If @id is not a valid identifier, InvalidParameterValue -# if @id already exists, DuplicateId -# If @props contains an invalid parameter for this backend, -# InvalidParameter ## { 'command': 'netdev_add', 'data': {'type': 'str', 'id': 'str', '*props': '**'}, @@ -2173,8 +2282,6 @@ # @fdname: file descriptor name # # Returns: Nothing on success -# If file descriptor was not received, FdNotSupplied -# If @fdname is not valid, InvalidParameterType # # Since: 0.14.0 # @@ -2194,8 +2301,58 @@ # @fdname: file descriptor name # # Returns: Nothing on success -# If @fdname is not found, FdNotFound # # Since: 0.14.0 ## { 'command': 'closefd', 'data': {'fdname': 'str'} } + +## +# @MachineInfo: +# +# Information describing a machine. +# +# @name: the name of the machine +# +# @alias: #optional an alias for the machine name +# +# @default: #optional whether the machine is default +# +# Since: 1.2.0 +## +{ 'type': 'MachineInfo', + 'data': { 'name': 'str', '*alias': 'str', + '*is-default': 'bool' } } + +## +# @query-machines: +# +# Return a list of supported machines +# +# Returns: a list of MachineInfo +# +# Since: 1.2.0 +## +{ 'command': 'query-machines', 'returns': ['MachineInfo'] } + +## +# @CpuDefinitionInfo: +# +# Virtual CPU definition. +# +# @name: the name of the CPU definition +# +# Since: 1.2.0 +## +{ 'type': 'CpuDefinitionInfo', + 'data': { 'name': 'str' } } + +## +# @query-cpu-definitions: +# +# Return a list of supported virtual CPU definitions +# +# Returns: a list of CpuDefInfo +# +# Since: 1.2.0 +## +{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] } diff --git a/qapi/qmp-core.h b/qapi/qmp-core.h index b0f64ba1ee..00446cff9b 100644 --- a/qapi/qmp-core.h +++ b/qapi/qmp-core.h @@ -49,6 +49,7 @@ void qmp_disable_command(const char *name); void qmp_enable_command(const char *name); bool qmp_command_is_enabled(const char *name); char **qmp_get_command_list(void); +QObject *qmp_build_error_object(Error *errp); #endif diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 122c1a29ba..4085994686 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -14,8 +14,8 @@ #include "qemu-objects.h" #include "qapi/qmp-core.h" #include "json-parser.h" +#include "qapi-types.h" #include "error.h" -#include "error_int.h" #include "qerror.h" static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) @@ -109,6 +109,13 @@ static QObject *do_qmp_dispatch(QObject *request, Error **errp) return ret; } +QObject *qmp_build_error_object(Error *errp) +{ + return qobject_from_jsonf("{ 'class': %s, 'desc': %s }", + ErrorClass_lookup[error_get_class(errp)], + error_get_pretty(errp)); +} + QObject *qmp_dispatch(QObject *request) { Error *err = NULL; @@ -119,7 +126,7 @@ QObject *qmp_dispatch(QObject *request) rsp = qdict_new(); if (err) { - qdict_put_obj(rsp, "error", error_get_qobject(err)); + qdict_put_obj(rsp, "error", qmp_build_error_object(err)); error_free(err); } else if (ret) { qdict_put_obj(rsp, "return", ret); diff --git a/qemu-char.c b/qemu-char.c index c2aaaeeb8f..382c71ebcd 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2446,7 +2446,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) if (is_listen) { fd = inet_listen_opts(opts, 0, NULL); } else { - fd = inet_connect_opts(opts, NULL); + fd = inet_connect_opts(opts, NULL, NULL); } } if (fd < 0) { diff --git a/qemu-common.h b/qemu-common.h index f9deca6f86..095e28d89a 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -1,3 +1,4 @@ + /* Common header file that is included by all of qemu. */ #ifndef QEMU_COMMON_H #define QEMU_COMMON_H @@ -429,6 +430,26 @@ static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) /* Round number up to multiple */ #define QEMU_ALIGN_UP(n, m) QEMU_ALIGN_DOWN((n) + (m) - 1, (m)) +static inline bool is_power_of_2(uint64_t value) +{ + if (!value) { + return 0; + } + + return !(value & (value - 1)); +} + +/* round down to the nearest power of 2*/ +int64_t pow2floor(int64_t value); + #include "module.h" +/* + * Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128) + * Input is limited to 14-bit numbers + */ + +int uleb128_encode_small(uint8_t *out, uint32_t n); +int uleb128_decode_small(const uint8_t *in, uint32_t *n); + #endif diff --git a/qemu-ga.c b/qemu-ga.c index f1a39ec3a6..8f87621ae4 100644 --- a/qemu-ga.c +++ b/qemu-ga.c @@ -28,7 +28,6 @@ #include "module.h" #include "signal.h" #include "qerror.h" -#include "error_int.h" #include "qapi/qmp-core.h" #include "qga/channel.h" #ifdef _WIN32 @@ -515,7 +514,7 @@ static void process_event(JSONMessageParser *parser, QList *tokens) } else { g_warning("failed to parse event: %s", error_get_pretty(err)); } - qdict_put_obj(qdict, "error", error_get_qobject(err)); + qdict_put_obj(qdict, "error", qmp_build_error_object(err)); error_free(err); } else { qdict = qobject_to_qdict(obj); @@ -532,7 +531,7 @@ static void process_event(JSONMessageParser *parser, QList *tokens) qdict = qdict_new(); g_warning("unrecognized payload format"); error_set(&err, QERR_UNSUPPORTED); - qdict_put_obj(qdict, "error", error_get_qobject(err)); + qdict_put_obj(qdict, "error", qmp_build_error_object(err)); error_free(err); } ret = send_response(s, QOBJECT(qdict)); diff --git a/qemu-sockets.c b/qemu-sockets.c index beb2bb6f4a..361d890da3 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -209,7 +209,7 @@ listen: return slisten; } -int inet_connect_opts(QemuOpts *opts, Error **errp) +int inet_connect_opts(QemuOpts *opts, bool *in_progress, Error **errp) { struct addrinfo ai,*res,*e; const char *addr; @@ -224,6 +224,10 @@ int inet_connect_opts(QemuOpts *opts, Error **errp) ai.ai_family = PF_UNSPEC; ai.ai_socktype = SOCK_STREAM; + if (in_progress) { + *in_progress = false; + } + addr = qemu_opt_get(opts, "host"); port = qemu_opt_get(opts, "port"); block = qemu_opt_get_bool(opts, "block", 0); @@ -277,7 +281,9 @@ int inet_connect_opts(QemuOpts *opts, Error **errp) #else if (!block && (rc == -EINPROGRESS)) { #endif - error_set(errp, QERR_SOCKET_CONNECT_IN_PROGRESS); + if (in_progress) { + *in_progress = true; + } } else if (rc < 0) { if (NULL == e->ai_next) fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, @@ -487,7 +493,7 @@ int inet_listen(const char *str, char *ostr, int olen, return sock; } -int inet_connect(const char *str, bool block, Error **errp) +int inet_connect(const char *str, bool block, bool *in_progress, Error **errp) { QemuOpts *opts; int sock = -1; @@ -497,7 +503,7 @@ int inet_connect(const char *str, bool block, Error **errp) if (block) { qemu_opt_set(opts, "block", "on"); } - sock = inet_connect_opts(opts, errp); + sock = inet_connect_opts(opts, in_progress, errp); } else { error_set(errp, QERR_SOCKET_CREATE_FAILED); } diff --git a/qemu_socket.h b/qemu_socket.h index 4689ff340d..30ae6af8b8 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -42,8 +42,8 @@ int send_all(int fd, const void *buf, int len1); int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp); int inet_listen(const char *str, char *ostr, int olen, int socktype, int port_offset, Error **errp); -int inet_connect_opts(QemuOpts *opts, Error **errp); -int inet_connect(const char *str, bool block, Error **errp); +int inet_connect_opts(QemuOpts *opts, bool *in_progress, Error **errp); +int inet_connect(const char *str, bool block, bool *in_progress, Error **errp); int inet_dgram_opts(QemuOpts *opts); const char *inet_strfamily(int family); diff --git a/qerror.c b/qerror.c index 92c4eff179..08185047b4 100644 --- a/qerror.c +++ b/qerror.c @@ -23,320 +23,11 @@ static const QType qerror_type = { }; /** - * The 'desc' parameter is a printf-like string, the format of the format - * string is: - * - * %(KEY) - * - * Where KEY is a QDict key, which has to be passed to qerror_from_info(). - * - * Example: - * - * "foo error on device: %(device) slot: %(slot_nr)" - * - * A single percent sign can be printed if followed by a second one, - * for example: - * - * "running out of foo: %(foo)%%" - * - * Please keep the entries in alphabetical order. - * Use scripts/check-qerror.sh to check. - */ -static const QErrorStringTable qerror_table[] = { - { - .error_fmt = QERR_ADD_CLIENT_FAILED, - .desc = "Could not add client", - }, - { - .error_fmt = QERR_AMBIGUOUS_PATH, - .desc = "Path '%(path)' does not uniquely identify a %(object)" - }, - { - .error_fmt = QERR_BAD_BUS_FOR_DEVICE, - .desc = "Device '%(device)' can't go on a %(bad_bus_type) bus", - }, - { - .error_fmt = QERR_BASE_NOT_FOUND, - .desc = "Base '%(base)' not found", - }, - { - .error_fmt = QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, - .desc = "Block format '%(format)' used by device '%(name)' does not support feature '%(feature)'", - }, - { - .error_fmt = QERR_BUS_NO_HOTPLUG, - .desc = "Bus '%(bus)' does not support hotplugging", - }, - { - .error_fmt = QERR_BUS_NOT_FOUND, - .desc = "Bus '%(bus)' not found", - }, - { - .error_fmt = QERR_COMMAND_DISABLED, - .desc = "The command %(name) has been disabled for this instance", - }, - { - .error_fmt = QERR_COMMAND_NOT_FOUND, - .desc = "The command %(name) has not been found", - }, - { - .error_fmt = QERR_DEVICE_ENCRYPTED, - .desc = "Device '%(device)' is encrypted", - }, - { - .error_fmt = QERR_DEVICE_FEATURE_BLOCKS_MIGRATION, - .desc = "Migration is disabled when using feature '%(feature)' in device '%(device)'", - }, - { - .error_fmt = QERR_DEVICE_HAS_NO_MEDIUM, - .desc = "Device '%(device)' has no medium", - }, - { - .error_fmt = QERR_DEVICE_INIT_FAILED, - .desc = "Device '%(device)' could not be initialized", - }, - { - .error_fmt = QERR_DEVICE_IN_USE, - .desc = "Device '%(device)' is in use", - }, - { - .error_fmt = QERR_DEVICE_IS_READ_ONLY, - .desc = "Device '%(device)' is read only", - }, - { - .error_fmt = QERR_DEVICE_LOCKED, - .desc = "Device '%(device)' is locked", - }, - { - .error_fmt = QERR_DEVICE_MULTIPLE_BUSSES, - .desc = "Device '%(device)' has multiple child busses", - }, - { - .error_fmt = QERR_DEVICE_NO_BUS, - .desc = "Device '%(device)' has no child bus", - }, - { - .error_fmt = QERR_DEVICE_NO_HOTPLUG, - .desc = "Device '%(device)' does not support hotplugging", - }, - { - .error_fmt = QERR_DEVICE_NOT_ACTIVE, - .desc = "Device '%(device)' has not been activated", - }, - { - .error_fmt = QERR_DEVICE_NOT_ENCRYPTED, - .desc = "Device '%(device)' is not encrypted", - }, - { - .error_fmt = QERR_DEVICE_NOT_FOUND, - .desc = "Device '%(device)' not found", - }, - { - .error_fmt = QERR_DEVICE_NOT_REMOVABLE, - .desc = "Device '%(device)' is not removable", - }, - { - .error_fmt = QERR_DUPLICATE_ID, - .desc = "Duplicate ID '%(id)' for %(object)", - }, - { - .error_fmt = QERR_FD_NOT_FOUND, - .desc = "File descriptor named '%(name)' not found", - }, - { - .error_fmt = QERR_FD_NOT_SUPPLIED, - .desc = "No file descriptor supplied via SCM_RIGHTS", - }, - { - .error_fmt = QERR_FEATURE_DISABLED, - .desc = "The feature '%(name)' is not enabled", - }, - { - .error_fmt = QERR_INVALID_BLOCK_FORMAT, - .desc = "Invalid block format '%(name)'", - }, - { - .error_fmt = QERR_INVALID_OPTION_GROUP, - .desc = "There is no option group '%(group)'", - }, - { - .error_fmt = QERR_INVALID_PARAMETER, - .desc = "Invalid parameter '%(name)'", - }, - { - .error_fmt = QERR_INVALID_PARAMETER_COMBINATION, - .desc = "Invalid parameter combination", - }, - { - .error_fmt = QERR_INVALID_PARAMETER_TYPE, - .desc = "Invalid parameter type for '%(name)', expected: %(expected)", - }, - { - .error_fmt = QERR_INVALID_PARAMETER_VALUE, - .desc = "Parameter '%(name)' expects %(expected)", - }, - { - .error_fmt = QERR_INVALID_PASSWORD, - .desc = "Password incorrect", - }, - { - .error_fmt = QERR_IO_ERROR, - .desc = "An IO error has occurred", - }, - { - .error_fmt = QERR_JSON_PARSE_ERROR, - .desc = "JSON parse error, %(message)", - - }, - { - .error_fmt = QERR_JSON_PARSING, - .desc = "Invalid JSON syntax", - }, - { - .error_fmt = QERR_KVM_MISSING_CAP, - .desc = "Using KVM without %(capability), %(feature) unavailable", - }, - { - .error_fmt = QERR_MIGRATION_ACTIVE, - .desc = "There's a migration process in progress", - }, - { - .error_fmt = QERR_MIGRATION_NOT_SUPPORTED, - .desc = "State blocked by non-migratable device '%(device)'", - }, - { - .error_fmt = QERR_MIGRATION_EXPECTED, - .desc = "An incoming migration is expected before this command can be executed", - }, - { - .error_fmt = QERR_MISSING_PARAMETER, - .desc = "Parameter '%(name)' is missing", - }, - { - .error_fmt = QERR_NO_BUS_FOR_DEVICE, - .desc = "No '%(bus)' bus found for device '%(device)'", - }, - { - .error_fmt = QERR_NOT_SUPPORTED, - .desc = "Not supported", - }, - { - .error_fmt = QERR_OPEN_FILE_FAILED, - .desc = "Could not open '%(filename)'", - }, - { - .error_fmt = QERR_PERMISSION_DENIED, - .desc = "Insufficient permission to perform this operation", - }, - { - .error_fmt = QERR_PROPERTY_NOT_FOUND, - .desc = "Property '%(device).%(property)' not found", - }, - { - .error_fmt = QERR_PROPERTY_VALUE_BAD, - .desc = "Property '%(device).%(property)' doesn't take value '%(value)'", - }, - { - .error_fmt = QERR_PROPERTY_VALUE_IN_USE, - .desc = "Property '%(device).%(property)' can't take value '%(value)', it's in use", - }, - { - .error_fmt = QERR_PROPERTY_VALUE_NOT_FOUND, - .desc = "Property '%(device).%(property)' can't find value '%(value)'", - }, - { - .error_fmt = QERR_PROPERTY_VALUE_NOT_POWER_OF_2, - .desc = "Property '%(device).%(property)' doesn't take " - "value '%(value)', it's not a power of 2", - }, - { - .error_fmt = QERR_PROPERTY_VALUE_OUT_OF_RANGE, - .desc = "Property '%(device).%(property)' doesn't take " - "value %(value) (minimum: %(min), maximum: %(max))", - }, - { - .error_fmt = QERR_QGA_COMMAND_FAILED, - .desc = "Guest agent command failed, error was '%(message)'", - }, - { - .error_fmt = QERR_QGA_LOGGING_FAILED, - .desc = "Guest agent failed to log non-optional log statement", - }, - { - .error_fmt = QERR_QMP_BAD_INPUT_OBJECT, - .desc = "Expected '%(expected)' in QMP input", - }, - { - .error_fmt = QERR_QMP_BAD_INPUT_OBJECT_MEMBER, - .desc = "QMP input object member '%(member)' expects '%(expected)'", - }, - { - .error_fmt = QERR_QMP_EXTRA_MEMBER, - .desc = "QMP input object member '%(member)' is unexpected", - }, - { - .error_fmt = QERR_RESET_REQUIRED, - .desc = "Resetting the Virtual Machine is required", - }, - { - .error_fmt = QERR_SET_PASSWD_FAILED, - .desc = "Could not set password", - }, - { - .error_fmt = QERR_TOO_MANY_FILES, - .desc = "Too many open files", - }, - { - .error_fmt = QERR_UNDEFINED_ERROR, - .desc = "An undefined error has occurred", - }, - { - .error_fmt = QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, - .desc = "'%(device)' uses a %(format) feature which is not " - "supported by this qemu version: %(feature)", - }, - { - .error_fmt = QERR_UNSUPPORTED, - .desc = "this feature or command is not currently supported", - }, - { - .error_fmt = QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION, - .desc = "Migration is disabled when VirtFS export path '%(path)' " - "is mounted in the guest using mount_tag '%(tag)'", - }, - { - .error_fmt = QERR_VNC_SERVER_FAILED, - .desc = "Could not start VNC server on %(target)", - }, - { - .error_fmt = QERR_SOCKET_CONNECT_IN_PROGRESS, - .desc = "Connection can not be completed immediately", - }, - { - .error_fmt = QERR_SOCKET_CONNECT_FAILED, - .desc = "Failed to connect to socket", - }, - { - .error_fmt = QERR_SOCKET_LISTEN_FAILED, - .desc = "Failed to set socket to listening mode", - }, - { - .error_fmt = QERR_SOCKET_BIND_FAILED, - .desc = "Failed to bind socket", - }, - { - .error_fmt = QERR_SOCKET_CREATE_FAILED, - .desc = "Failed to create socket", - }, - {} -}; - -/** * qerror_new(): Create a new QError * * Return strong reference. */ -QError *qerror_new(void) +static QError *qerror_new(void) { QError *qerr; @@ -346,200 +37,31 @@ QError *qerror_new(void) return qerr; } -static void GCC_FMT_ATTR(2, 3) qerror_abort(const QError *qerr, - const char *fmt, ...) -{ - va_list ap; - - fprintf(stderr, "qerror: bad call in function '%s':\n", qerr->func); - fprintf(stderr, "qerror: -> "); - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - fprintf(stderr, "\nqerror: call at %s:%d\n", qerr->file, qerr->linenr); - abort(); -} - -static void GCC_FMT_ATTR(2, 0) qerror_set_data(QError *qerr, - const char *fmt, va_list *va) -{ - QObject *obj; - - obj = qobject_from_jsonv(fmt, va); - if (!obj) { - qerror_abort(qerr, "invalid format '%s'", fmt); - } - if (qobject_type(obj) != QTYPE_QDICT) { - qerror_abort(qerr, "error format is not a QDict '%s'", fmt); - } - - qerr->error = qobject_to_qdict(obj); - - obj = qdict_get(qerr->error, "class"); - if (!obj) { - qerror_abort(qerr, "missing 'class' key in '%s'", fmt); - } - if (qobject_type(obj) != QTYPE_QSTRING) { - qerror_abort(qerr, "'class' key value should be a QString"); - } - - obj = qdict_get(qerr->error, "data"); - if (!obj) { - qerror_abort(qerr, "missing 'data' key in '%s'", fmt); - } - if (qobject_type(obj) != QTYPE_QDICT) { - qerror_abort(qerr, "'data' key value should be a QDICT"); - } -} - -static void qerror_set_desc(QError *qerr, const char *fmt) -{ - int i; - - // FIXME: inefficient loop - - for (i = 0; qerror_table[i].error_fmt; i++) { - if (strcmp(qerror_table[i].error_fmt, fmt) == 0) { - qerr->entry = &qerror_table[i]; - return; - } - } - - qerror_abort(qerr, "error format '%s' not found", fmt); -} - /** * qerror_from_info(): Create a new QError from error information * - * The information consists of: - * - * - file the file name of where the error occurred - * - linenr the line number of where the error occurred - * - func the function name of where the error occurred - * - fmt JSON printf-like dictionary, there must exist keys 'class' and - * 'data' - * - va va_list of all arguments specified by fmt - * * Return strong reference. */ -QError *qerror_from_info(const char *file, int linenr, const char *func, - const char *fmt, va_list *va) +static QError *qerror_from_info(ErrorClass err_class, const char *fmt, + va_list *va) { QError *qerr; qerr = qerror_new(); loc_save(&qerr->loc); - qerr->linenr = linenr; - qerr->file = file; - qerr->func = func; - - if (!fmt) { - qerror_abort(qerr, "QDict not specified"); - } - qerror_set_data(qerr, fmt, va); - qerror_set_desc(qerr, fmt); + qerr->err_msg = g_strdup_vprintf(fmt, *va); + qerr->err_class = err_class; return qerr; } -static void parse_error(const QErrorStringTable *entry, int c) -{ - fprintf(stderr, "expected '%c' in '%s'", c, entry->desc); - abort(); -} - -static const char *append_field(QDict *error, QString *outstr, - const QErrorStringTable *entry, - const char *start) -{ - QObject *obj; - QDict *qdict; - QString *key_qs; - const char *end, *key; - - if (*start != '%') - parse_error(entry, '%'); - start++; - if (*start != '(') - parse_error(entry, '('); - start++; - - end = strchr(start, ')'); - if (!end) - parse_error(entry, ')'); - - key_qs = qstring_from_substr(start, 0, end - start - 1); - key = qstring_get_str(key_qs); - - qdict = qobject_to_qdict(qdict_get(error, "data")); - obj = qdict_get(qdict, key); - if (!obj) { - abort(); - } - - switch (qobject_type(obj)) { - case QTYPE_QSTRING: - qstring_append(outstr, qdict_get_str(qdict, key)); - break; - case QTYPE_QINT: - qstring_append_int(outstr, qdict_get_int(qdict, key)); - break; - default: - abort(); - } - - QDECREF(key_qs); - return ++end; -} - -static QString *qerror_format_desc(QDict *error, - const QErrorStringTable *entry) -{ - QString *qstring; - const char *p; - - assert(entry != NULL); - - qstring = qstring_new(); - - for (p = entry->desc; *p != '\0';) { - if (*p != '%') { - qstring_append_chr(qstring, *p++); - } else if (*(p + 1) == '%') { - qstring_append_chr(qstring, '%'); - p += 2; - } else { - p = append_field(error, qstring, entry, p); - } - } - - return qstring; -} - -QString *qerror_format(const char *fmt, QDict *error) -{ - const QErrorStringTable *entry = NULL; - int i; - - for (i = 0; qerror_table[i].error_fmt; i++) { - if (strcmp(qerror_table[i].error_fmt, fmt) == 0) { - entry = &qerror_table[i]; - break; - } - } - - return qerror_format_desc(error, entry); -} - /** * qerror_human(): Format QError data into human-readable string. */ QString *qerror_human(const QError *qerror) { - return qerror_format_desc(qerror->error, qerror->entry); + return qstring_from_str(qerror->err_msg); } /** @@ -549,7 +71,7 @@ QString *qerror_human(const QError *qerror) * it uses error_report() for this, so that the output is routed to the right * place (ie. stderr or Monitor's device). */ -void qerror_print(QError *qerror) +static void qerror_print(QError *qerror) { QString *qstring = qerror_human(qerror); loc_push_restore(&qerror->loc); @@ -558,14 +80,13 @@ void qerror_print(QError *qerror) QDECREF(qstring); } -void qerror_report_internal(const char *file, int linenr, const char *func, - const char *fmt, ...) +void qerror_report(ErrorClass eclass, const char *fmt, ...) { va_list va; QError *qerror; va_start(va, fmt); - qerror = qerror_from_info(file, linenr, func, fmt, &va); + qerror = qerror_from_info(eclass, fmt, &va); va_end(va); if (monitor_cur_is_qmp()) { @@ -579,27 +100,18 @@ void qerror_report_internal(const char *file, int linenr, const char *func, /* Evil... */ struct Error { - QDict *obj; - const char *fmt; char *msg; + ErrorClass err_class; }; void qerror_report_err(Error *err) { QError *qerr; - int i; qerr = qerror_new(); loc_save(&qerr->loc); - QINCREF(err->obj); - qerr->error = err->obj; - - for (i = 0; qerror_table[i].error_fmt; i++) { - if (strcmp(qerror_table[i].error_fmt, err->fmt) == 0) { - qerr->entry = &qerror_table[i]; - break; - } - } + qerr->err_msg = g_strdup(err->msg); + qerr->err_class = err->err_class; if (monitor_cur_is_qmp()) { monitor_set_error(cur_mon, qerr); @@ -620,7 +132,7 @@ void assert_no_error(Error *err) /** * qobject_to_qerror(): Convert a QObject into a QError */ -QError *qobject_to_qerror(const QObject *obj) +static QError *qobject_to_qerror(const QObject *obj) { if (qobject_type(obj) != QTYPE_QERROR) { return NULL; @@ -639,6 +151,6 @@ static void qerror_destroy_obj(QObject *obj) assert(obj != NULL); qerr = qobject_to_qerror(obj); - QDECREF(qerr->error); + g_free(qerr->err_msg); g_free(qerr); } diff --git a/qerror.h b/qerror.h index b4c8758f40..d0a76a4f71 100644 --- a/qerror.h +++ b/qerror.h @@ -16,36 +16,20 @@ #include "qstring.h" #include "qemu-error.h" #include "error.h" +#include "qapi-types.h" #include <stdarg.h> -typedef struct QErrorStringTable { - const char *desc; - const char *error_fmt; -} QErrorStringTable; - typedef struct QError { QObject_HEAD; - QDict *error; Location loc; - int linenr; - const char *file; - const char *func; - const QErrorStringTable *entry; + char *err_msg; + ErrorClass err_class; } QError; -QError *qerror_new(void); -QError *qerror_from_info(const char *file, int linenr, const char *func, - const char *fmt, va_list *va) GCC_FMT_ATTR(4, 0); QString *qerror_human(const QError *qerror); -void qerror_print(QError *qerror); -void qerror_report_internal(const char *file, int linenr, const char *func, - const char *fmt, ...) GCC_FMT_ATTR(4, 5); +void qerror_report(ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(2, 3); void qerror_report_err(Error *err); void assert_no_error(Error *err); -QString *qerror_format(const char *fmt, QDict *error); -#define qerror_report(fmt, ...) \ - qerror_report_internal(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__) -QError *qobject_to_qerror(const QObject *obj); /* * QError class list @@ -53,217 +37,213 @@ QError *qobject_to_qerror(const QObject *obj); * Use scripts/check-qerror.sh to check. */ #define QERR_ADD_CLIENT_FAILED \ - "{ 'class': 'AddClientFailed', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Could not add client" #define QERR_AMBIGUOUS_PATH \ - "{ 'class': 'AmbiguousPath', 'data': { 'path': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Path '%s' does not uniquely identify an object" #define QERR_BAD_BUS_FOR_DEVICE \ - "{ 'class': 'BadBusForDevice', 'data': { 'device': %s, 'bad_bus_type': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Device '%s' can't go on a %s bus" #define QERR_BASE_NOT_FOUND \ - "{ 'class': 'BaseNotFound', 'data': { 'base': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Base '%s' not found" #define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \ - "{ 'class': 'BlockFormatFeatureNotSupported', 'data': { 'format': %s, 'name': %s, 'feature': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by device '%s' does not support feature '%s'" #define QERR_BUFFER_OVERRUN \ - "{ 'class': 'BufferOverrun', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "An internal buffer overran" #define QERR_BUS_NO_HOTPLUG \ - "{ 'class': 'BusNoHotplug', 'data': { 'bus': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Bus '%s' does not support hotplugging" #define QERR_BUS_NOT_FOUND \ - "{ 'class': 'BusNotFound', 'data': { 'bus': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Bus '%s' not found" #define QERR_COMMAND_DISABLED \ - "{ 'class': 'CommandDisabled', 'data': { 'name': %s } }" + ERROR_CLASS_GENERIC_ERROR, "The command %s has been disabled for this instance" #define QERR_COMMAND_NOT_FOUND \ - "{ 'class': 'CommandNotFound', 'data': { 'name': %s } }" + ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found" #define QERR_DEVICE_ENCRYPTED \ - "{ 'class': 'DeviceEncrypted', 'data': { 'device': %s, 'filename': %s } }" + ERROR_CLASS_DEVICE_ENCRYPTED, "'%s' (%s) is encrypted" #define QERR_DEVICE_FEATURE_BLOCKS_MIGRATION \ - "{ 'class': 'DeviceFeatureBlocksMigration', 'data': { 'device': %s, 'feature': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Migration is disabled when using feature '%s' in device '%s'" #define QERR_DEVICE_HAS_NO_MEDIUM \ - "{ 'class': 'DeviceHasNoMedium', 'data': { 'device': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Device '%s' has no medium" #define QERR_DEVICE_INIT_FAILED \ - "{ 'class': 'DeviceInitFailed', 'data': { 'device': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Device '%s' could not be initialized" #define QERR_DEVICE_IN_USE \ - "{ 'class': 'DeviceInUse', 'data': { 'device': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Device '%s' is in use" #define QERR_DEVICE_IS_READ_ONLY \ - "{ 'class': 'DeviceIsReadOnly', 'data': { 'device': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Device '%s' is read only" #define QERR_DEVICE_LOCKED \ - "{ 'class': 'DeviceLocked', 'data': { 'device': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Device '%s' is locked" #define QERR_DEVICE_MULTIPLE_BUSSES \ - "{ 'class': 'DeviceMultipleBusses', 'data': { 'device': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Device '%s' has multiple child busses" #define QERR_DEVICE_NO_BUS \ - "{ 'class': 'DeviceNoBus', 'data': { 'device': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Device '%s' has no child bus" #define QERR_DEVICE_NO_HOTPLUG \ - "{ 'class': 'DeviceNoHotplug', 'data': { 'device': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Device '%s' does not support hotplugging" #define QERR_DEVICE_NOT_ACTIVE \ - "{ 'class': 'DeviceNotActive', 'data': { 'device': %s } }" + ERROR_CLASS_DEVICE_NOT_ACTIVE, "Device '%s' has not been activated" #define QERR_DEVICE_NOT_ENCRYPTED \ - "{ 'class': 'DeviceNotEncrypted', 'data': { 'device': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Device '%s' is not encrypted" #define QERR_DEVICE_NOT_FOUND \ - "{ 'class': 'DeviceNotFound', 'data': { 'device': %s } }" + ERROR_CLASS_DEVICE_NOT_FOUND, "Device '%s' not found" #define QERR_DEVICE_NOT_REMOVABLE \ - "{ 'class': 'DeviceNotRemovable', 'data': { 'device': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Device '%s' is not removable" #define QERR_DUPLICATE_ID \ - "{ 'class': 'DuplicateId', 'data': { 'id': %s, 'object': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Duplicate ID '%s' for %s" #define QERR_FD_NOT_FOUND \ - "{ 'class': 'FdNotFound', 'data': { 'name': %s } }" + ERROR_CLASS_GENERIC_ERROR, "File descriptor named '%s' not found" #define QERR_FD_NOT_SUPPLIED \ - "{ 'class': 'FdNotSupplied', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "No file descriptor supplied via SCM_RIGHTS" #define QERR_FEATURE_DISABLED \ - "{ 'class': 'FeatureDisabled', 'data': { 'name': %s } }" + ERROR_CLASS_GENERIC_ERROR, "The feature '%s' is not enabled" #define QERR_INVALID_BLOCK_FORMAT \ - "{ 'class': 'InvalidBlockFormat', 'data': { 'name': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Invalid block format '%s'" #define QERR_INVALID_OPTION_GROUP \ - "{ 'class': 'InvalidOptionGroup', 'data': { 'group': %s } }" + ERROR_CLASS_GENERIC_ERROR, "There is no option group '%s'" #define QERR_INVALID_PARAMETER \ - "{ 'class': 'InvalidParameter', 'data': { 'name': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Invalid parameter '%s'" #define QERR_INVALID_PARAMETER_COMBINATION \ - "{ 'class': 'InvalidParameterCombination', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Invalid parameter combination" #define QERR_INVALID_PARAMETER_TYPE \ - "{ 'class': 'InvalidParameterType', 'data': { 'name': %s,'expected': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Invalid parameter type for '%s', expected: %s" #define QERR_INVALID_PARAMETER_VALUE \ - "{ 'class': 'InvalidParameterValue', 'data': { 'name': %s, 'expected': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Parameter '%s' expects %s" #define QERR_INVALID_PASSWORD \ - "{ 'class': 'InvalidPassword', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Password incorrect" #define QERR_IO_ERROR \ - "{ 'class': 'IOError', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "An IO error has occurred" #define QERR_JSON_PARSE_ERROR \ - "{ 'class': 'JSONParseError', 'data': { 'message': %s } }" + ERROR_CLASS_GENERIC_ERROR, "JSON parse error, %s" #define QERR_JSON_PARSING \ - "{ 'class': 'JSONParsing', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Invalid JSON syntax" #define QERR_KVM_MISSING_CAP \ - "{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }" + ERROR_CLASS_K_V_M_MISSING_CAP, "Using KVM without %s, %s unavailable" #define QERR_MIGRATION_ACTIVE \ - "{ 'class': 'MigrationActive', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "There's a migration process in progress" #define QERR_MIGRATION_NOT_SUPPORTED \ - "{ 'class': 'MigrationNotSupported', 'data': {'device': %s} }" + ERROR_CLASS_GENERIC_ERROR, "State blocked by non-migratable device '%s'" #define QERR_MIGRATION_EXPECTED \ - "{ 'class': 'MigrationExpected', 'data': {} }" + ERROR_CLASS_MIGRATION_EXPECTED, "An incoming migration is expected before this command can be executed" #define QERR_MISSING_PARAMETER \ - "{ 'class': 'MissingParameter', 'data': { 'name': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Parameter '%s' is missing" #define QERR_NO_BUS_FOR_DEVICE \ - "{ 'class': 'NoBusForDevice', 'data': { 'device': %s, 'bus': %s } }" + ERROR_CLASS_GENERIC_ERROR, "No '%s' bus found for device '%s'" #define QERR_NOT_SUPPORTED \ - "{ 'class': 'NotSupported', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Not supported" #define QERR_OPEN_FILE_FAILED \ - "{ 'class': 'OpenFileFailed', 'data': { 'filename': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Could not open '%s'" #define QERR_PERMISSION_DENIED \ - "{ 'class': 'PermissionDenied', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Insufficient permission to perform this operation" #define QERR_PROPERTY_NOT_FOUND \ - "{ 'class': 'PropertyNotFound', 'data': { 'device': %s, 'property': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' not found" #define QERR_PROPERTY_VALUE_BAD \ - "{ 'class': 'PropertyValueBad', 'data': { 'device': %s, 'property': %s, 'value': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' doesn't take value '%s'" #define QERR_PROPERTY_VALUE_IN_USE \ - "{ 'class': 'PropertyValueInUse', 'data': { 'device': %s, 'property': %s, 'value': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' can't take value '%s', it's in use" #define QERR_PROPERTY_VALUE_NOT_FOUND \ - "{ 'class': 'PropertyValueNotFound', 'data': { 'device': %s, 'property': %s, 'value': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' can't find value '%s'" #define QERR_PROPERTY_VALUE_NOT_POWER_OF_2 \ - "{ 'class': 'PropertyValueNotPowerOf2', 'data': { " \ - "'device': %s, 'property': %s, 'value': %"PRId64" } }" + ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2" #define QERR_PROPERTY_VALUE_OUT_OF_RANGE \ - "{ 'class': 'PropertyValueOutOfRange', 'data': { 'device': %s, 'property': %s, 'value': %"PRId64", 'min': %"PRId64", 'max': %"PRId64" } }" + ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value %" PRId64 " (minimum: %" PRId64 ", maximum: %" PRId64 ")" #define QERR_QGA_COMMAND_FAILED \ - "{ 'class': 'QgaCommandFailed', 'data': { 'message': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Guest agent command failed, error was '%s'" #define QERR_QGA_LOGGING_FAILED \ - "{ 'class': 'QgaLoggingFailed', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Guest agent failed to log non-optional log statement" #define QERR_QMP_BAD_INPUT_OBJECT \ - "{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Expected '%s' in QMP input" #define QERR_QMP_BAD_INPUT_OBJECT_MEMBER \ - "{ 'class': 'QMPBadInputObjectMember', 'data': { 'member': %s, 'expected': %s } }" + ERROR_CLASS_GENERIC_ERROR, "QMP input object member '%s' expects '%s'" #define QERR_QMP_EXTRA_MEMBER \ - "{ 'class': 'QMPExtraInputObjectMember', 'data': { 'member': %s } }" + ERROR_CLASS_GENERIC_ERROR, "QMP input object member '%s' is unexpected" #define QERR_RESET_REQUIRED \ - "{ 'class': 'ResetRequired', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Resetting the Virtual Machine is required" #define QERR_SET_PASSWD_FAILED \ - "{ 'class': 'SetPasswdFailed', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Could not set password" #define QERR_TOO_MANY_FILES \ - "{ 'class': 'TooManyFiles', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Too many open files" #define QERR_UNDEFINED_ERROR \ - "{ 'class': 'UndefinedError', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "An undefined error has occurred" #define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \ - "{ 'class': 'UnknownBlockFormatFeature', 'data': { 'device': %s, 'format': %s, 'feature': %s } }" + ERROR_CLASS_GENERIC_ERROR, "'%s' uses a %s feature which is not supported by this qemu version: %s" #define QERR_UNSUPPORTED \ - "{ 'class': 'Unsupported', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "this feature or command is not currently supported" #define QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION \ - "{ 'class': 'VirtFSFeatureBlocksMigration', 'data': { 'path': %s, 'tag': %s } }" + ERROR_CLASS_GENERIC_ERROR, "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'" #define QERR_VNC_SERVER_FAILED \ - "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }" - -#define QERR_SOCKET_CONNECT_IN_PROGRESS \ - "{ 'class': 'SockConnectInprogress', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Could not start VNC server on %s" #define QERR_SOCKET_CONNECT_FAILED \ - "{ 'class': 'SockConnectFailed', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Failed to connect to socket" #define QERR_SOCKET_LISTEN_FAILED \ - "{ 'class': 'SockListenFailed', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Failed to set socket to listening mode" #define QERR_SOCKET_BIND_FAILED \ - "{ 'class': 'SockBindFailed', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Failed to bind socket" #define QERR_SOCKET_CREATE_FAILED \ - "{ 'class': 'SockCreateFailed', 'data': {} }" + ERROR_CLASS_GENERIC_ERROR, "Failed to create socket" #endif /* QERROR_H */ diff --git a/qmp-commands.hx b/qmp-commands.hx index ac466382c0..527b9f7c24 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -435,8 +435,8 @@ Example: -> { "execute": "inject-nmi" } <- { "return": {} } -Note: inject-nmi is only supported for x86 guest currently, it will - returns "Unsupported" error for non-x86 guest. +Note: inject-nmi fails when the guest doesn't support injecting. + Currently, only x86 guests do. EQMP @@ -520,6 +520,50 @@ Example: <- { "return": {} } EQMP +{ + .name = "migrate-set-cache-size", + .args_type = "value:o", + .mhandler.cmd_new = qmp_marshal_input_migrate_set_cache_size, + }, + +SQMP +migrate-set-cache-size +--------------------- + +Set cache size to be used by XBZRLE migration, the cache size will be rounded +down to the nearest power of 2 + +Arguments: + +- "value": cache size in bytes (json-int) + +Example: + +-> { "execute": "migrate-set-cache-size", "arguments": { "value": 536870912 } } +<- { "return": {} } + +EQMP + { + .name = "query-migrate-cache-size", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_migrate_cache_size, + }, + +SQMP +query-migrate-cache-size +--------------------- + +Show cache size to be used by XBZRLE migration + +returns a json-object with the following information: +- "size" : json-int + +Example: + +-> { "execute": "query-migrate-cache-size" } +<- { "return": 67108864 } + +EQMP { .name = "migrate_set_speed", @@ -2078,12 +2122,24 @@ The main json-object contains the following: - "transferred": amount transferred (json-int) - "remaining": amount remaining (json-int) - "total": total (json-int) + - "total-time": total amount of ms since migration started. If + migration has ended, it returns the total migration time + (json-int) + - "duplicate": number of duplicated pages (json-int) + - "normal" : number of normal pages transferred (json-int) + - "normal-bytes" : number of normal bytes transferred (json-int) - "disk": only present if "status" is "active" and it is a block migration, it is a json-object with the following disk information (in bytes): - "transferred": amount transferred (json-int) - "remaining": amount remaining (json-int) - "total": total (json-int) - +- "xbzrle-cache": only present if XBZRLE is active. + It is a json-object with the following XBZRLE information: + - "cache-size": XBZRLE cache size + - "bytes": total XBZRLE bytes transferred + - "pages": number of XBZRLE compressed pages + - "cache-miss": number of cache misses + - "overflow": number of XBZRLE overflows Examples: 1. Before the first migration @@ -2094,7 +2150,19 @@ Examples: 2. Migration is done and has succeeded -> { "execute": "query-migrate" } -<- { "return": { "status": "completed" } } +<- { "return": { + "status": "completed", + "ram":{ + "transferred":123, + "remaining":123, + "total":246, + "total-time":12345, + "duplicate":123, + "normal":123, + "normal-bytes":123456 + } + } + } 3. Migration is done and has failed @@ -2110,7 +2178,11 @@ Examples: "ram":{ "transferred":123, "remaining":123, - "total":246 + "total":246, + "total-time":12345, + "duplicate":123, + "normal":123, + "normal-bytes":123456 } } } @@ -2124,7 +2196,11 @@ Examples: "ram":{ "total":1057024, "remaining":1053304, - "transferred":3720 + "transferred":3720, + "total-time":12345, + "duplicate":123, + "normal":123, + "normal-bytes":123456 }, "disk":{ "total":20971520, @@ -2134,6 +2210,32 @@ Examples: } } +6. Migration is being performed and XBZRLE is active: + +-> { "execute": "query-migrate" } +<- { + "return":{ + "status":"active", + "capabilities" : [ { "capability": "xbzrle", "state" : true } ], + "ram":{ + "total":1057024, + "remaining":1053304, + "transferred":3720, + "total-time":12345, + "duplicate":10, + "normal":3333, + "normal-bytes":3412992 + }, + "xbzrle-cache":{ + "cache-size":67108864, + "bytes":20971520, + "pages":2444343, + "cache-miss":2244, + "overflow":34434 + } + } + } + EQMP { @@ -2143,6 +2245,55 @@ EQMP }, SQMP +migrate-set-capabilities +------- + +Enable/Disable migration capabilities + +- "xbzrle": xbzrle support + +Arguments: + +Example: + +-> { "execute": "migrate-set-capabilities" , "arguments": + { "capabilities": [ { "capability": "xbzrle", "state": true } ] } } + +EQMP + + { + .name = "migrate-set-capabilities", + .args_type = "capabilities:O", + .params = "capability:s,state:b", + .mhandler.cmd_new = qmp_marshal_input_migrate_set_capabilities, + }, +SQMP +query-migrate-capabilities +------- + +Query current migration capabilities + +- "capabilities": migration capabilities state + - "xbzrle" : XBZRLE state (json-bool) + +Arguments: + +Example: + +-> { "execute": "query-migrate-capabilities" } +<- { "return": { + "capabilities" : [ { "capability" : "xbzrle", "state" : false } ] + } + } +EQMP + + { + .name = "query-migrate-capabilities", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_migrate_capabilities, + }, + +SQMP query-balloon ------------- @@ -2217,3 +2368,22 @@ EQMP .args_type = "implements:s?,abstract:b?", .mhandler.cmd_new = qmp_marshal_input_qom_list_types, }, + + { + .name = "device-list-properties", + .args_type = "typename:s", + .mhandler.cmd_new = qmp_marshal_input_device_list_properties, + }, + + { + .name = "query-machines", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_machines, + }, + + { + .name = "query-cpu-definitions", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_cpu_definitions, + }, + diff --git a/qmp.c b/qmp.c index fee9fb2a9d..6c1e4e8978 100644 --- a/qmp.c +++ b/qmp.c @@ -417,3 +417,59 @@ ObjectTypeInfoList *qmp_qom_list_types(bool has_implements, return ret; } + +DevicePropertyInfoList *qmp_device_list_properties(const char *typename, + Error **errp) +{ + ObjectClass *klass; + Property *prop; + DevicePropertyInfoList *prop_list = NULL; + + klass = object_class_by_name(typename); + if (klass == NULL) { + error_set(errp, QERR_DEVICE_NOT_FOUND, typename); + return NULL; + } + + klass = object_class_dynamic_cast(klass, TYPE_DEVICE); + if (klass == NULL) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, + "name", TYPE_DEVICE); + return NULL; + } + + do { + for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) { + DevicePropertyInfoList *entry; + DevicePropertyInfo *info; + + /* + * TODO Properties without a parser are just for dirty hacks. + * qdev_prop_ptr is the only such PropertyInfo. It's marked + * for removal. This conditional should be removed along with + * it. + */ + if (!prop->info->set) { + continue; /* no way to set it, don't show */ + } + + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(prop->name); + info->type = g_strdup(prop->info->legacy_name ?: prop->info->name); + + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + entry->next = prop_list; + prop_list = entry; + } + klass = object_class_get_parent(klass); + } while (klass != object_class_by_name(TYPE_DEVICE)); + + return prop_list; +} + +CpuDefinitionInfoList GCC_WEAK *qmp_query_cpu_definitions(Error **errp) +{ + error_set(errp, QERR_NOT_SUPPORTED); + return NULL; +} diff --git a/savevm.c b/savevm.c index 6e82b2d3e3..0ea10c9b66 100644 --- a/savevm.c +++ b/savevm.c @@ -2392,3 +2392,162 @@ void vmstate_register_ram_global(MemoryRegion *mr) { vmstate_register_ram(mr, NULL); } + +/* + page = zrun nzrun + | zrun nzrun page + + zrun = length + + nzrun = length byte... + + length = uleb128 encoded integer + */ +int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen, + uint8_t *dst, int dlen) +{ + uint32_t zrun_len = 0, nzrun_len = 0; + int d = 0, i = 0; + long res, xor; + uint8_t *nzrun_start = NULL; + + g_assert(!(((uintptr_t)old_buf | (uintptr_t)new_buf | slen) % + sizeof(long))); + + while (i < slen) { + /* overflow */ + if (d + 2 > dlen) { + return -1; + } + + /* not aligned to sizeof(long) */ + res = (slen - i) % sizeof(long); + while (res && old_buf[i] == new_buf[i]) { + zrun_len++; + i++; + res--; + } + + /* word at a time for speed */ + if (!res) { + while (i < slen && + (*(long *)(old_buf + i)) == (*(long *)(new_buf + i))) { + i += sizeof(long); + zrun_len += sizeof(long); + } + + /* go over the rest */ + while (i < slen && old_buf[i] == new_buf[i]) { + zrun_len++; + i++; + } + } + + /* buffer unchanged */ + if (zrun_len == slen) { + return 0; + } + + /* skip last zero run */ + if (i == slen) { + return d; + } + + d += uleb128_encode_small(dst + d, zrun_len); + + zrun_len = 0; + nzrun_start = new_buf + i; + + /* overflow */ + if (d + 2 > dlen) { + return -1; + } + /* not aligned to sizeof(long) */ + res = (slen - i) % sizeof(long); + while (res && old_buf[i] != new_buf[i]) { + i++; + nzrun_len++; + res--; + } + + /* word at a time for speed, use of 32-bit long okay */ + if (!res) { + /* truncation to 32-bit long okay */ + long mask = 0x0101010101010101ULL; + while (i < slen) { + xor = *(long *)(old_buf + i) ^ *(long *)(new_buf + i); + if ((xor - mask) & ~xor & (mask << 7)) { + /* found the end of an nzrun within the current long */ + while (old_buf[i] != new_buf[i]) { + nzrun_len++; + i++; + } + break; + } else { + i += sizeof(long); + nzrun_len += sizeof(long); + } + } + } + + d += uleb128_encode_small(dst + d, nzrun_len); + /* overflow */ + if (d + nzrun_len > dlen) { + return -1; + } + memcpy(dst + d, nzrun_start, nzrun_len); + d += nzrun_len; + nzrun_len = 0; + } + + return d; +} + +int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen) +{ + int i = 0, d = 0; + int ret; + uint32_t count = 0; + + while (i < slen) { + + /* zrun */ + if ((slen - i) < 2) { + return -1; + } + + ret = uleb128_decode_small(src + i, &count); + if (ret < 0 || (i && !count)) { + return -1; + } + i += ret; + d += count; + + /* overflow */ + if (d > dlen) { + return -1; + } + + /* nzrun */ + if ((slen - i) < 2) { + return -1; + } + + ret = uleb128_decode_small(src + i, &count); + if (ret < 0 || !count) { + return -1; + } + i += ret; + + /* overflow */ + if (d + count > dlen || i + count > slen) { + return -1; + } + + memcpy(dst + d, src + i, count); + d += count; + i += count; + } + + return d; +} diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 9eed40e18a..3c4678dbf1 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -342,6 +342,7 @@ def gen_command_decl_prologue(header, guard, prefix=""): #define %(guard)s #include "%(prefix)sqapi-types.h" +#include "qdict.h" #include "error.h" ''', diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 4a734f58d5..cf601ae2d2 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -70,7 +70,7 @@ const char *%(name)s_lookup[] = { ret += mcgen(''' "%(value)s", ''', - value=value.lower()) + value=value) ret += mcgen(''' NULL, @@ -79,6 +79,16 @@ const char *%(name)s_lookup[] = { ''') return ret +def generate_enum_name(name): + if name.isupper(): + return c_fun(name) + new_name = '' + for c in c_fun(name): + if c.isupper(): + new_name += '_' + new_name += c + return new_name.lstrip('_').upper() + def generate_enum(name, values): lookup_decl = mcgen(''' extern const char *%(name)s_lookup[]; @@ -100,7 +110,7 @@ typedef enum %(name)s %(abbrev)s_%(value)s = %(i)d, ''', abbrev=de_camel_case(name).upper(), - value=c_fun(value).upper(), + value=generate_enum_name(value), i=i) i += 1 @@ -253,7 +263,8 @@ fdecl.write(mcgen(''' #ifndef %(guard)s #define %(guard)s -#include "qapi/qapi-types-core.h" +#include "qemu-common.h" + ''', guard=guardname(h_file))) diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs index 683fd59af9..c1d4f059da 100644 --- a/target-i386/Makefile.objs +++ b/target-i386/Makefile.objs @@ -3,14 +3,6 @@ obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o obj-$(CONFIG_KVM) += kvm.o hyperv.o +obj-$(CONFIG_NO_KVM) += kvm-stub.o obj-$(CONFIG_LINUX_USER) += ioport-user.o obj-$(CONFIG_BSD_USER) += ioport-user.o - -$(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) -$(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) -$(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) -$(obj)/svm_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) -$(obj)/smm_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) -$(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) -$(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) -$(obj)/seg_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS) diff --git a/target-i386/cc_helper.c b/target-i386/cc_helper.c index ff654bc5ed..07892f9049 100644 --- a/target-i386/cc_helper.c +++ b/target-i386/cc_helper.c @@ -18,7 +18,6 @@ */ #include "cpu.h" -#include "dyngen-exec.h" #include "helper.h" const uint8_t parity_table[256] = { @@ -76,184 +75,177 @@ const uint8_t parity_table[256] = { #endif -static int compute_all_eflags(void) +static int compute_all_eflags(CPUX86State *env) { return CC_SRC; } -static int compute_c_eflags(void) +static int compute_c_eflags(CPUX86State *env) { return CC_SRC & CC_C; } -uint32_t helper_cc_compute_all(int op) +uint32_t helper_cc_compute_all(CPUX86State *env, int op) { switch (op) { default: /* should never happen */ return 0; case CC_OP_EFLAGS: - return compute_all_eflags(); + return compute_all_eflags(env); case CC_OP_MULB: - return compute_all_mulb(); + return compute_all_mulb(env); case CC_OP_MULW: - return compute_all_mulw(); + return compute_all_mulw(env); case CC_OP_MULL: - return compute_all_mull(); + return compute_all_mull(env); case CC_OP_ADDB: - return compute_all_addb(); + return compute_all_addb(env); case CC_OP_ADDW: - return compute_all_addw(); + return compute_all_addw(env); case CC_OP_ADDL: - return compute_all_addl(); + return compute_all_addl(env); case CC_OP_ADCB: - return compute_all_adcb(); + return compute_all_adcb(env); case CC_OP_ADCW: - return compute_all_adcw(); + return compute_all_adcw(env); case CC_OP_ADCL: - return compute_all_adcl(); + return compute_all_adcl(env); case CC_OP_SUBB: - return compute_all_subb(); + return compute_all_subb(env); case CC_OP_SUBW: - return compute_all_subw(); + return compute_all_subw(env); case CC_OP_SUBL: - return compute_all_subl(); + return compute_all_subl(env); case CC_OP_SBBB: - return compute_all_sbbb(); + return compute_all_sbbb(env); case CC_OP_SBBW: - return compute_all_sbbw(); + return compute_all_sbbw(env); case CC_OP_SBBL: - return compute_all_sbbl(); + return compute_all_sbbl(env); case CC_OP_LOGICB: - return compute_all_logicb(); + return compute_all_logicb(env); case CC_OP_LOGICW: - return compute_all_logicw(); + return compute_all_logicw(env); case CC_OP_LOGICL: - return compute_all_logicl(); + return compute_all_logicl(env); case CC_OP_INCB: - return compute_all_incb(); + return compute_all_incb(env); case CC_OP_INCW: - return compute_all_incw(); + return compute_all_incw(env); case CC_OP_INCL: - return compute_all_incl(); + return compute_all_incl(env); case CC_OP_DECB: - return compute_all_decb(); + return compute_all_decb(env); case CC_OP_DECW: - return compute_all_decw(); + return compute_all_decw(env); case CC_OP_DECL: - return compute_all_decl(); + return compute_all_decl(env); case CC_OP_SHLB: - return compute_all_shlb(); + return compute_all_shlb(env); case CC_OP_SHLW: - return compute_all_shlw(); + return compute_all_shlw(env); case CC_OP_SHLL: - return compute_all_shll(); + return compute_all_shll(env); case CC_OP_SARB: - return compute_all_sarb(); + return compute_all_sarb(env); case CC_OP_SARW: - return compute_all_sarw(); + return compute_all_sarw(env); case CC_OP_SARL: - return compute_all_sarl(); + return compute_all_sarl(env); #ifdef TARGET_X86_64 case CC_OP_MULQ: - return compute_all_mulq(); + return compute_all_mulq(env); case CC_OP_ADDQ: - return compute_all_addq(); + return compute_all_addq(env); case CC_OP_ADCQ: - return compute_all_adcq(); + return compute_all_adcq(env); case CC_OP_SUBQ: - return compute_all_subq(); + return compute_all_subq(env); case CC_OP_SBBQ: - return compute_all_sbbq(); + return compute_all_sbbq(env); case CC_OP_LOGICQ: - return compute_all_logicq(); + return compute_all_logicq(env); case CC_OP_INCQ: - return compute_all_incq(); + return compute_all_incq(env); case CC_OP_DECQ: - return compute_all_decq(); + return compute_all_decq(env); case CC_OP_SHLQ: - return compute_all_shlq(); + return compute_all_shlq(env); case CC_OP_SARQ: - return compute_all_sarq(); + return compute_all_sarq(env); #endif } } -uint32_t cpu_cc_compute_all(CPUX86State *env1, int op) +uint32_t cpu_cc_compute_all(CPUX86State *env, int op) { - CPUX86State *saved_env; - uint32_t ret; - - saved_env = env; - env = env1; - ret = helper_cc_compute_all(op); - env = saved_env; - return ret; + return helper_cc_compute_all(env, op); } -uint32_t helper_cc_compute_c(int op) +uint32_t helper_cc_compute_c(CPUX86State *env, int op) { switch (op) { default: /* should never happen */ return 0; case CC_OP_EFLAGS: - return compute_c_eflags(); + return compute_c_eflags(env); case CC_OP_MULB: - return compute_c_mull(); + return compute_c_mull(env); case CC_OP_MULW: - return compute_c_mull(); + return compute_c_mull(env); case CC_OP_MULL: - return compute_c_mull(); + return compute_c_mull(env); case CC_OP_ADDB: - return compute_c_addb(); + return compute_c_addb(env); case CC_OP_ADDW: - return compute_c_addw(); + return compute_c_addw(env); case CC_OP_ADDL: - return compute_c_addl(); + return compute_c_addl(env); case CC_OP_ADCB: - return compute_c_adcb(); + return compute_c_adcb(env); case CC_OP_ADCW: - return compute_c_adcw(); + return compute_c_adcw(env); case CC_OP_ADCL: - return compute_c_adcl(); + return compute_c_adcl(env); case CC_OP_SUBB: - return compute_c_subb(); + return compute_c_subb(env); case CC_OP_SUBW: - return compute_c_subw(); + return compute_c_subw(env); case CC_OP_SUBL: - return compute_c_subl(); + return compute_c_subl(env); case CC_OP_SBBB: - return compute_c_sbbb(); + return compute_c_sbbb(env); case CC_OP_SBBW: - return compute_c_sbbw(); + return compute_c_sbbw(env); case CC_OP_SBBL: - return compute_c_sbbl(); + return compute_c_sbbl(env); case CC_OP_LOGICB: return compute_c_logicb(); @@ -263,111 +255,112 @@ uint32_t helper_cc_compute_c(int op) return compute_c_logicl(); case CC_OP_INCB: - return compute_c_incl(); + return compute_c_incl(env); case CC_OP_INCW: - return compute_c_incl(); + return compute_c_incl(env); case CC_OP_INCL: - return compute_c_incl(); + return compute_c_incl(env); case CC_OP_DECB: - return compute_c_incl(); + return compute_c_incl(env); case CC_OP_DECW: - return compute_c_incl(); + return compute_c_incl(env); case CC_OP_DECL: - return compute_c_incl(); + return compute_c_incl(env); case CC_OP_SHLB: - return compute_c_shlb(); + return compute_c_shlb(env); case CC_OP_SHLW: - return compute_c_shlw(); + return compute_c_shlw(env); case CC_OP_SHLL: - return compute_c_shll(); + return compute_c_shll(env); case CC_OP_SARB: - return compute_c_sarl(); + return compute_c_sarl(env); case CC_OP_SARW: - return compute_c_sarl(); + return compute_c_sarl(env); case CC_OP_SARL: - return compute_c_sarl(); + return compute_c_sarl(env); #ifdef TARGET_X86_64 case CC_OP_MULQ: - return compute_c_mull(); + return compute_c_mull(env); case CC_OP_ADDQ: - return compute_c_addq(); + return compute_c_addq(env); case CC_OP_ADCQ: - return compute_c_adcq(); + return compute_c_adcq(env); case CC_OP_SUBQ: - return compute_c_subq(); + return compute_c_subq(env); case CC_OP_SBBQ: - return compute_c_sbbq(); + return compute_c_sbbq(env); case CC_OP_LOGICQ: return compute_c_logicq(); case CC_OP_INCQ: - return compute_c_incl(); + return compute_c_incl(env); case CC_OP_DECQ: - return compute_c_incl(); + return compute_c_incl(env); case CC_OP_SHLQ: - return compute_c_shlq(); + return compute_c_shlq(env); case CC_OP_SARQ: - return compute_c_sarl(); + return compute_c_sarl(env); #endif } } -void helper_write_eflags(target_ulong t0, uint32_t update_mask) +void helper_write_eflags(CPUX86State *env, target_ulong t0, + uint32_t update_mask) { cpu_load_eflags(env, t0, update_mask); } -target_ulong helper_read_eflags(void) +target_ulong helper_read_eflags(CPUX86State *env) { uint32_t eflags; - eflags = helper_cc_compute_all(CC_OP); + eflags = helper_cc_compute_all(env, CC_OP); eflags |= (DF & DF_MASK); eflags |= env->eflags & ~(VM_MASK | RF_MASK); return eflags; } -void helper_clts(void) +void helper_clts(CPUX86State *env) { env->cr[0] &= ~CR0_TS_MASK; env->hflags &= ~HF_TS_MASK; } -void helper_reset_rf(void) +void helper_reset_rf(CPUX86State *env) { env->eflags &= ~RF_MASK; } -void helper_cli(void) +void helper_cli(CPUX86State *env) { env->eflags &= ~IF_MASK; } -void helper_sti(void) +void helper_sti(CPUX86State *env) { env->eflags |= IF_MASK; } #if 0 /* vm86plus instructions */ -void helper_cli_vm(void) +void helper_cli_vm(CPUX86State *env) { env->eflags &= ~VIF_MASK; } -void helper_sti_vm(void) +void helper_sti_vm(CPUX86State *env) { env->eflags |= VIF_MASK; if (env->eflags & VIP_MASK) { @@ -376,12 +369,12 @@ void helper_sti_vm(void) } #endif -void helper_set_inhibit_irq(void) +void helper_set_inhibit_irq(CPUX86State *env) { env->hflags |= HF_INHIBIT_IRQ_MASK; } -void helper_reset_inhibit_irq(void) +void helper_reset_inhibit_irq(CPUX86State *env) { env->hflags &= ~HF_INHIBIT_IRQ_MASK; } diff --git a/target-i386/cc_helper_template.h b/target-i386/cc_helper_template.h index ff22830f6b..1f94e11dcf 100644 --- a/target-i386/cc_helper_template.h +++ b/target-i386/cc_helper_template.h @@ -42,7 +42,7 @@ /* dynamic flags computation */ -static int glue(compute_all_add, SUFFIX)(void) +static int glue(compute_all_add, SUFFIX)(CPUX86State *env) { int cf, pf, af, zf, sf, of; target_long src1, src2; @@ -58,7 +58,7 @@ static int glue(compute_all_add, SUFFIX)(void) return cf | pf | af | zf | sf | of; } -static int glue(compute_c_add, SUFFIX)(void) +static int glue(compute_c_add, SUFFIX)(CPUX86State *env) { int cf; target_long src1; @@ -68,7 +68,7 @@ static int glue(compute_c_add, SUFFIX)(void) return cf; } -static int glue(compute_all_adc, SUFFIX)(void) +static int glue(compute_all_adc, SUFFIX)(CPUX86State *env) { int cf, pf, af, zf, sf, of; target_long src1, src2; @@ -84,7 +84,7 @@ static int glue(compute_all_adc, SUFFIX)(void) return cf | pf | af | zf | sf | of; } -static int glue(compute_c_adc, SUFFIX)(void) +static int glue(compute_c_adc, SUFFIX)(CPUX86State *env) { int cf; target_long src1; @@ -94,7 +94,7 @@ static int glue(compute_c_adc, SUFFIX)(void) return cf; } -static int glue(compute_all_sub, SUFFIX)(void) +static int glue(compute_all_sub, SUFFIX)(CPUX86State *env) { int cf, pf, af, zf, sf, of; target_long src1, src2; @@ -110,7 +110,7 @@ static int glue(compute_all_sub, SUFFIX)(void) return cf | pf | af | zf | sf | of; } -static int glue(compute_c_sub, SUFFIX)(void) +static int glue(compute_c_sub, SUFFIX)(CPUX86State *env) { int cf; target_long src1, src2; @@ -121,7 +121,7 @@ static int glue(compute_c_sub, SUFFIX)(void) return cf; } -static int glue(compute_all_sbb, SUFFIX)(void) +static int glue(compute_all_sbb, SUFFIX)(CPUX86State *env) { int cf, pf, af, zf, sf, of; target_long src1, src2; @@ -137,7 +137,7 @@ static int glue(compute_all_sbb, SUFFIX)(void) return cf | pf | af | zf | sf | of; } -static int glue(compute_c_sbb, SUFFIX)(void) +static int glue(compute_c_sbb, SUFFIX)(CPUX86State *env) { int cf; target_long src1, src2; @@ -148,7 +148,7 @@ static int glue(compute_c_sbb, SUFFIX)(void) return cf; } -static int glue(compute_all_logic, SUFFIX)(void) +static int glue(compute_all_logic, SUFFIX)(CPUX86State *env) { int cf, pf, af, zf, sf, of; @@ -166,7 +166,7 @@ static int glue(compute_c_logic, SUFFIX)(void) return 0; } -static int glue(compute_all_inc, SUFFIX)(void) +static int glue(compute_all_inc, SUFFIX)(CPUX86State *env) { int cf, pf, af, zf, sf, of; target_long src1, src2; @@ -183,13 +183,13 @@ static int glue(compute_all_inc, SUFFIX)(void) } #if DATA_BITS == 32 -static int glue(compute_c_inc, SUFFIX)(void) +static int glue(compute_c_inc, SUFFIX)(CPUX86State *env) { return CC_SRC; } #endif -static int glue(compute_all_dec, SUFFIX)(void) +static int glue(compute_all_dec, SUFFIX)(CPUX86State *env) { int cf, pf, af, zf, sf, of; target_long src1, src2; @@ -205,7 +205,7 @@ static int glue(compute_all_dec, SUFFIX)(void) return cf | pf | af | zf | sf | of; } -static int glue(compute_all_shl, SUFFIX)(void) +static int glue(compute_all_shl, SUFFIX)(CPUX86State *env) { int cf, pf, af, zf, sf, of; @@ -219,19 +219,19 @@ static int glue(compute_all_shl, SUFFIX)(void) return cf | pf | af | zf | sf | of; } -static int glue(compute_c_shl, SUFFIX)(void) +static int glue(compute_c_shl, SUFFIX)(CPUX86State *env) { return (CC_SRC >> (DATA_BITS - 1)) & CC_C; } #if DATA_BITS == 32 -static int glue(compute_c_sar, SUFFIX)(void) +static int glue(compute_c_sar, SUFFIX)(CPUX86State *env) { return CC_SRC & 1; } #endif -static int glue(compute_all_sar, SUFFIX)(void) +static int glue(compute_all_sar, SUFFIX)(CPUX86State *env) { int cf, pf, af, zf, sf, of; @@ -246,7 +246,7 @@ static int glue(compute_all_sar, SUFFIX)(void) } #if DATA_BITS == 32 -static int glue(compute_c_mul, SUFFIX)(void) +static int glue(compute_c_mul, SUFFIX)(CPUX86State *env) { int cf; @@ -257,7 +257,7 @@ static int glue(compute_c_mul, SUFFIX)(void) /* NOTE: we compute the flags like the P4. On olders CPUs, only OF and CF are modified and it is slower to do that. */ -static int glue(compute_all_mul, SUFFIX)(void) +static int glue(compute_all_mul, SUFFIX)(CPUX86State *env) { int cf, pf, af, zf, sf, of; diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 880cfea3f8..6d5d0d6e10 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -28,6 +28,7 @@ #include "qemu-config.h" #include "qapi/qapi-visit-core.h" +#include "qmp-commands.h" #include "hyperv.h" @@ -1125,6 +1126,27 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg) } } +CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) +{ + CpuDefinitionInfoList *cpu_list = NULL; + x86_def_t *def; + + for (def = x86_defs; def; def = def->next) { + CpuDefinitionInfoList *entry; + CpuDefinitionInfo *info; + + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(def->name); + + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + entry->next = cpu_list; + cpu_list = entry; + } + + return cpu_list; +} + int cpu_x86_register(X86CPU *cpu, const char *cpu_model) { CPUX86State *env = &cpu->env; diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c index 6065c2e72d..dfc34a6253 100644 --- a/target-i386/fpu_helper.c +++ b/target-i386/fpu_helper.c @@ -19,7 +19,6 @@ #include <math.h> #include "cpu.h" -#include "dyngen-exec.h" #include "helper.h" #if !defined(CONFIG_USER_ONLY) @@ -58,39 +57,39 @@ #define floatx80_l2e make_floatx80(0x3fff, 0xb8aa3b295c17f0bcLL) #define floatx80_l2t make_floatx80(0x4000, 0xd49a784bcd1b8afeLL) -static inline void fpush(void) +static inline void fpush(CPUX86State *env) { env->fpstt = (env->fpstt - 1) & 7; env->fptags[env->fpstt] = 0; /* validate stack entry */ } -static inline void fpop(void) +static inline void fpop(CPUX86State *env) { env->fptags[env->fpstt] = 1; /* invalidate stack entry */ env->fpstt = (env->fpstt + 1) & 7; } -static inline floatx80 helper_fldt(target_ulong ptr) +static inline floatx80 helper_fldt(CPUX86State *env, target_ulong ptr) { CPU_LDoubleU temp; - temp.l.lower = ldq(ptr); - temp.l.upper = lduw(ptr + 8); + temp.l.lower = cpu_ldq_data(env, ptr); + temp.l.upper = cpu_lduw_data(env, ptr + 8); return temp.d; } -static inline void helper_fstt(floatx80 f, target_ulong ptr) +static inline void helper_fstt(CPUX86State *env, floatx80 f, target_ulong ptr) { CPU_LDoubleU temp; temp.d = f; - stq(ptr, temp.l.lower); - stw(ptr + 8, temp.l.upper); + cpu_stq_data(env, ptr, temp.l.lower); + cpu_stw_data(env, ptr + 8, temp.l.upper); } /* x87 FPU helpers */ -static inline double floatx80_to_double(floatx80 a) +static inline double floatx80_to_double(CPUX86State *env, floatx80 a) { union { float64 f64; @@ -101,7 +100,7 @@ static inline double floatx80_to_double(floatx80 a) return u.d; } -static inline floatx80 double_to_floatx80(double a) +static inline floatx80 double_to_floatx80(CPUX86State *env, double a) { union { float64 f64; @@ -112,7 +111,7 @@ static inline floatx80 double_to_floatx80(double a) return float64_to_floatx80(u.f64, &env->fp_status); } -static void fpu_set_exception(int mask) +static void fpu_set_exception(CPUX86State *env, int mask) { env->fpus |= mask; if (env->fpus & (~env->fpuc & FPUC_EM)) { @@ -120,15 +119,15 @@ static void fpu_set_exception(int mask) } } -static inline floatx80 helper_fdiv(floatx80 a, floatx80 b) +static inline floatx80 helper_fdiv(CPUX86State *env, floatx80 a, floatx80 b) { if (floatx80_is_zero(b)) { - fpu_set_exception(FPUS_ZE); + fpu_set_exception(env, FPUS_ZE); } return floatx80_div(a, b, &env->fp_status); } -static void fpu_raise_exception(void) +static void fpu_raise_exception(CPUX86State *env) { if (env->cr[0] & CR0_NE_MASK) { raise_exception(env, EXCP10_COPR); @@ -140,7 +139,7 @@ static void fpu_raise_exception(void) #endif } -void helper_flds_FT0(uint32_t val) +void helper_flds_FT0(CPUX86State *env, uint32_t val) { union { float32 f; @@ -151,7 +150,7 @@ void helper_flds_FT0(uint32_t val) FT0 = float32_to_floatx80(u.f, &env->fp_status); } -void helper_fldl_FT0(uint64_t val) +void helper_fldl_FT0(CPUX86State *env, uint64_t val) { union { float64 f; @@ -162,12 +161,12 @@ void helper_fldl_FT0(uint64_t val) FT0 = float64_to_floatx80(u.f, &env->fp_status); } -void helper_fildl_FT0(int32_t val) +void helper_fildl_FT0(CPUX86State *env, int32_t val) { FT0 = int32_to_floatx80(val, &env->fp_status); } -void helper_flds_ST0(uint32_t val) +void helper_flds_ST0(CPUX86State *env, uint32_t val) { int new_fpstt; union { @@ -182,7 +181,7 @@ void helper_flds_ST0(uint32_t val) env->fptags[new_fpstt] = 0; /* validate stack entry */ } -void helper_fldl_ST0(uint64_t val) +void helper_fldl_ST0(CPUX86State *env, uint64_t val) { int new_fpstt; union { @@ -197,7 +196,7 @@ void helper_fldl_ST0(uint64_t val) env->fptags[new_fpstt] = 0; /* validate stack entry */ } -void helper_fildl_ST0(int32_t val) +void helper_fildl_ST0(CPUX86State *env, int32_t val) { int new_fpstt; @@ -207,7 +206,7 @@ void helper_fildl_ST0(int32_t val) env->fptags[new_fpstt] = 0; /* validate stack entry */ } -void helper_fildll_ST0(int64_t val) +void helper_fildll_ST0(CPUX86State *env, int64_t val) { int new_fpstt; @@ -217,7 +216,7 @@ void helper_fildll_ST0(int64_t val) env->fptags[new_fpstt] = 0; /* validate stack entry */ } -uint32_t helper_fsts_ST0(void) +uint32_t helper_fsts_ST0(CPUX86State *env) { union { float32 f; @@ -228,7 +227,7 @@ uint32_t helper_fsts_ST0(void) return u.i; } -uint64_t helper_fstl_ST0(void) +uint64_t helper_fstl_ST0(CPUX86State *env) { union { float64 f; @@ -239,7 +238,7 @@ uint64_t helper_fstl_ST0(void) return u.i; } -int32_t helper_fist_ST0(void) +int32_t helper_fist_ST0(CPUX86State *env) { int32_t val; @@ -250,7 +249,7 @@ int32_t helper_fist_ST0(void) return val; } -int32_t helper_fistl_ST0(void) +int32_t helper_fistl_ST0(CPUX86State *env) { int32_t val; @@ -258,7 +257,7 @@ int32_t helper_fistl_ST0(void) return val; } -int64_t helper_fistll_ST0(void) +int64_t helper_fistll_ST0(CPUX86State *env) { int64_t val; @@ -266,7 +265,7 @@ int64_t helper_fistll_ST0(void) return val; } -int32_t helper_fistt_ST0(void) +int32_t helper_fistt_ST0(CPUX86State *env) { int32_t val; @@ -277,7 +276,7 @@ int32_t helper_fistt_ST0(void) return val; } -int32_t helper_fisttl_ST0(void) +int32_t helper_fisttl_ST0(CPUX86State *env) { int32_t val; @@ -285,7 +284,7 @@ int32_t helper_fisttl_ST0(void) return val; } -int64_t helper_fisttll_ST0(void) +int64_t helper_fisttll_ST0(CPUX86State *env) { int64_t val; @@ -293,38 +292,38 @@ int64_t helper_fisttll_ST0(void) return val; } -void helper_fldt_ST0(target_ulong ptr) +void helper_fldt_ST0(CPUX86State *env, target_ulong ptr) { int new_fpstt; new_fpstt = (env->fpstt - 1) & 7; - env->fpregs[new_fpstt].d = helper_fldt(ptr); + env->fpregs[new_fpstt].d = helper_fldt(env, ptr); env->fpstt = new_fpstt; env->fptags[new_fpstt] = 0; /* validate stack entry */ } -void helper_fstt_ST0(target_ulong ptr) +void helper_fstt_ST0(CPUX86State *env, target_ulong ptr) { - helper_fstt(ST0, ptr); + helper_fstt(env, ST0, ptr); } -void helper_fpush(void) +void helper_fpush(CPUX86State *env) { - fpush(); + fpush(env); } -void helper_fpop(void) +void helper_fpop(CPUX86State *env) { - fpop(); + fpop(env); } -void helper_fdecstp(void) +void helper_fdecstp(CPUX86State *env) { env->fpstt = (env->fpstt - 1) & 7; env->fpus &= ~0x4700; } -void helper_fincstp(void) +void helper_fincstp(CPUX86State *env) { env->fpstt = (env->fpstt + 1) & 7; env->fpus &= ~0x4700; @@ -332,32 +331,32 @@ void helper_fincstp(void) /* FPU move */ -void helper_ffree_STN(int st_index) +void helper_ffree_STN(CPUX86State *env, int st_index) { env->fptags[(env->fpstt + st_index) & 7] = 1; } -void helper_fmov_ST0_FT0(void) +void helper_fmov_ST0_FT0(CPUX86State *env) { ST0 = FT0; } -void helper_fmov_FT0_STN(int st_index) +void helper_fmov_FT0_STN(CPUX86State *env, int st_index) { FT0 = ST(st_index); } -void helper_fmov_ST0_STN(int st_index) +void helper_fmov_ST0_STN(CPUX86State *env, int st_index) { ST0 = ST(st_index); } -void helper_fmov_STN_ST0(int st_index) +void helper_fmov_STN_ST0(CPUX86State *env, int st_index) { ST(st_index) = ST0; } -void helper_fxchg_ST0_STN(int st_index) +void helper_fxchg_ST0_STN(CPUX86State *env, int st_index) { floatx80 tmp; @@ -370,7 +369,7 @@ void helper_fxchg_ST0_STN(int st_index) static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500}; -void helper_fcom_ST0_FT0(void) +void helper_fcom_ST0_FT0(CPUX86State *env) { int ret; @@ -378,7 +377,7 @@ void helper_fcom_ST0_FT0(void) env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1]; } -void helper_fucom_ST0_FT0(void) +void helper_fucom_ST0_FT0(CPUX86State *env) { int ret; @@ -388,158 +387,158 @@ void helper_fucom_ST0_FT0(void) static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C}; -void helper_fcomi_ST0_FT0(void) +void helper_fcomi_ST0_FT0(CPUX86State *env) { int eflags; int ret; ret = floatx80_compare(ST0, FT0, &env->fp_status); - eflags = helper_cc_compute_all(CC_OP); + eflags = cpu_cc_compute_all(env, CC_OP); eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; CC_SRC = eflags; } -void helper_fucomi_ST0_FT0(void) +void helper_fucomi_ST0_FT0(CPUX86State *env) { int eflags; int ret; ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status); - eflags = helper_cc_compute_all(CC_OP); + eflags = cpu_cc_compute_all(env, CC_OP); eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; CC_SRC = eflags; } -void helper_fadd_ST0_FT0(void) +void helper_fadd_ST0_FT0(CPUX86State *env) { ST0 = floatx80_add(ST0, FT0, &env->fp_status); } -void helper_fmul_ST0_FT0(void) +void helper_fmul_ST0_FT0(CPUX86State *env) { ST0 = floatx80_mul(ST0, FT0, &env->fp_status); } -void helper_fsub_ST0_FT0(void) +void helper_fsub_ST0_FT0(CPUX86State *env) { ST0 = floatx80_sub(ST0, FT0, &env->fp_status); } -void helper_fsubr_ST0_FT0(void) +void helper_fsubr_ST0_FT0(CPUX86State *env) { ST0 = floatx80_sub(FT0, ST0, &env->fp_status); } -void helper_fdiv_ST0_FT0(void) +void helper_fdiv_ST0_FT0(CPUX86State *env) { - ST0 = helper_fdiv(ST0, FT0); + ST0 = helper_fdiv(env, ST0, FT0); } -void helper_fdivr_ST0_FT0(void) +void helper_fdivr_ST0_FT0(CPUX86State *env) { - ST0 = helper_fdiv(FT0, ST0); + ST0 = helper_fdiv(env, FT0, ST0); } /* fp operations between STN and ST0 */ -void helper_fadd_STN_ST0(int st_index) +void helper_fadd_STN_ST0(CPUX86State *env, int st_index) { ST(st_index) = floatx80_add(ST(st_index), ST0, &env->fp_status); } -void helper_fmul_STN_ST0(int st_index) +void helper_fmul_STN_ST0(CPUX86State *env, int st_index) { ST(st_index) = floatx80_mul(ST(st_index), ST0, &env->fp_status); } -void helper_fsub_STN_ST0(int st_index) +void helper_fsub_STN_ST0(CPUX86State *env, int st_index) { ST(st_index) = floatx80_sub(ST(st_index), ST0, &env->fp_status); } -void helper_fsubr_STN_ST0(int st_index) +void helper_fsubr_STN_ST0(CPUX86State *env, int st_index) { ST(st_index) = floatx80_sub(ST0, ST(st_index), &env->fp_status); } -void helper_fdiv_STN_ST0(int st_index) +void helper_fdiv_STN_ST0(CPUX86State *env, int st_index) { floatx80 *p; p = &ST(st_index); - *p = helper_fdiv(*p, ST0); + *p = helper_fdiv(env, *p, ST0); } -void helper_fdivr_STN_ST0(int st_index) +void helper_fdivr_STN_ST0(CPUX86State *env, int st_index) { floatx80 *p; p = &ST(st_index); - *p = helper_fdiv(ST0, *p); + *p = helper_fdiv(env, ST0, *p); } /* misc FPU operations */ -void helper_fchs_ST0(void) +void helper_fchs_ST0(CPUX86State *env) { ST0 = floatx80_chs(ST0); } -void helper_fabs_ST0(void) +void helper_fabs_ST0(CPUX86State *env) { ST0 = floatx80_abs(ST0); } -void helper_fld1_ST0(void) +void helper_fld1_ST0(CPUX86State *env) { ST0 = floatx80_one; } -void helper_fldl2t_ST0(void) +void helper_fldl2t_ST0(CPUX86State *env) { ST0 = floatx80_l2t; } -void helper_fldl2e_ST0(void) +void helper_fldl2e_ST0(CPUX86State *env) { ST0 = floatx80_l2e; } -void helper_fldpi_ST0(void) +void helper_fldpi_ST0(CPUX86State *env) { ST0 = floatx80_pi; } -void helper_fldlg2_ST0(void) +void helper_fldlg2_ST0(CPUX86State *env) { ST0 = floatx80_lg2; } -void helper_fldln2_ST0(void) +void helper_fldln2_ST0(CPUX86State *env) { ST0 = floatx80_ln2; } -void helper_fldz_ST0(void) +void helper_fldz_ST0(CPUX86State *env) { ST0 = floatx80_zero; } -void helper_fldz_FT0(void) +void helper_fldz_FT0(CPUX86State *env) { FT0 = floatx80_zero; } -uint32_t helper_fnstsw(void) +uint32_t helper_fnstsw(CPUX86State *env) { return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; } -uint32_t helper_fnstcw(void) +uint32_t helper_fnstcw(CPUX86State *env) { return env->fpuc; } -static void update_fp_status(void) +static void update_fp_status(CPUX86State *env) { int rnd_type; @@ -575,25 +574,25 @@ static void update_fp_status(void) set_floatx80_rounding_precision(rnd_type, &env->fp_status); } -void helper_fldcw(uint32_t val) +void helper_fldcw(CPUX86State *env, uint32_t val) { env->fpuc = val; - update_fp_status(); + update_fp_status(env); } -void helper_fclex(void) +void helper_fclex(CPUX86State *env) { env->fpus &= 0x7f00; } -void helper_fwait(void) +void helper_fwait(CPUX86State *env) { if (env->fpus & FPUS_SE) { - fpu_raise_exception(); + fpu_raise_exception(env); } } -void helper_fninit(void) +void helper_fninit(CPUX86State *env) { env->fpus = 0; env->fpstt = 0; @@ -610,7 +609,7 @@ void helper_fninit(void) /* BCD ops */ -void helper_fbld_ST0(target_ulong ptr) +void helper_fbld_ST0(CPUX86State *env, target_ulong ptr) { floatx80 tmp; uint64_t val; @@ -619,18 +618,18 @@ void helper_fbld_ST0(target_ulong ptr) val = 0; for (i = 8; i >= 0; i--) { - v = ldub(ptr + i); + v = cpu_ldub_data(env, ptr + i); val = (val * 100) + ((v >> 4) * 10) + (v & 0xf); } tmp = int64_to_floatx80(val, &env->fp_status); - if (ldub(ptr + 9) & 0x80) { + if (cpu_ldub_data(env, ptr + 9) & 0x80) { floatx80_chs(tmp); } - fpush(); + fpush(env); ST0 = tmp; } -void helper_fbst_ST0(target_ulong ptr) +void helper_fbst_ST0(CPUX86State *env, target_ulong ptr) { int v; target_ulong mem_ref, mem_end; @@ -640,10 +639,10 @@ void helper_fbst_ST0(target_ulong ptr) mem_ref = ptr; mem_end = mem_ref + 9; if (val < 0) { - stb(mem_end, 0x80); + cpu_stb_data(env, mem_end, 0x80); val = -val; } else { - stb(mem_end, 0x00); + cpu_stb_data(env, mem_end, 0x00); } while (mem_ref < mem_end) { if (val == 0) { @@ -652,63 +651,63 @@ void helper_fbst_ST0(target_ulong ptr) v = val % 100; val = val / 100; v = ((v / 10) << 4) | (v % 10); - stb(mem_ref++, v); + cpu_stb_data(env, mem_ref++, v); } while (mem_ref < mem_end) { - stb(mem_ref++, 0); + cpu_stb_data(env, mem_ref++, 0); } } -void helper_f2xm1(void) +void helper_f2xm1(CPUX86State *env) { - double val = floatx80_to_double(ST0); + double val = floatx80_to_double(env, ST0); val = pow(2.0, val) - 1.0; - ST0 = double_to_floatx80(val); + ST0 = double_to_floatx80(env, val); } -void helper_fyl2x(void) +void helper_fyl2x(CPUX86State *env) { - double fptemp = floatx80_to_double(ST0); + double fptemp = floatx80_to_double(env, ST0); if (fptemp > 0.0) { fptemp = log(fptemp) / log(2.0); /* log2(ST) */ - fptemp *= floatx80_to_double(ST1); - ST1 = double_to_floatx80(fptemp); - fpop(); + fptemp *= floatx80_to_double(env, ST1); + ST1 = double_to_floatx80(env, fptemp); + fpop(env); } else { env->fpus &= ~0x4700; env->fpus |= 0x400; } } -void helper_fptan(void) +void helper_fptan(CPUX86State *env) { - double fptemp = floatx80_to_double(ST0); + double fptemp = floatx80_to_double(env, ST0); if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) { env->fpus |= 0x400; } else { fptemp = tan(fptemp); - ST0 = double_to_floatx80(fptemp); - fpush(); + ST0 = double_to_floatx80(env, fptemp); + fpush(env); ST0 = floatx80_one; env->fpus &= ~0x400; /* C2 <-- 0 */ /* the above code is for |arg| < 2**52 only */ } } -void helper_fpatan(void) +void helper_fpatan(CPUX86State *env) { double fptemp, fpsrcop; - fpsrcop = floatx80_to_double(ST1); - fptemp = floatx80_to_double(ST0); - ST1 = double_to_floatx80(atan2(fpsrcop, fptemp)); - fpop(); + fpsrcop = floatx80_to_double(env, ST1); + fptemp = floatx80_to_double(env, ST0); + ST1 = double_to_floatx80(env, atan2(fpsrcop, fptemp)); + fpop(env); } -void helper_fxtract(void) +void helper_fxtract(CPUX86State *env) { CPU_LDoubleU temp; @@ -718,7 +717,7 @@ void helper_fxtract(void) /* Easy way to generate -inf and raising division by 0 exception */ ST0 = floatx80_div(floatx80_chs(floatx80_one), floatx80_zero, &env->fp_status); - fpush(); + fpush(env); ST0 = temp.d; } else { int expdif; @@ -726,24 +725,24 @@ void helper_fxtract(void) expdif = EXPD(temp) - EXPBIAS; /* DP exponent bias */ ST0 = int32_to_floatx80(expdif, &env->fp_status); - fpush(); + fpush(env); BIASEXPONENT(temp); ST0 = temp.d; } } -void helper_fprem1(void) +void helper_fprem1(CPUX86State *env) { double st0, st1, dblq, fpsrcop, fptemp; CPU_LDoubleU fpsrcop1, fptemp1; int expdif; signed long long int q; - st0 = floatx80_to_double(ST0); - st1 = floatx80_to_double(ST1); + st0 = floatx80_to_double(env, ST0); + st1 = floatx80_to_double(env, ST1); if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) { - ST0 = double_to_floatx80(0.0 / 0.0); /* NaN */ + ST0 = double_to_floatx80(env, 0.0 / 0.0); /* NaN */ env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */ return; } @@ -788,21 +787,21 @@ void helper_fprem1(void) -(floor(fabs(fpsrcop))) : floor(fpsrcop); st0 -= (st1 * fpsrcop * fptemp); } - ST0 = double_to_floatx80(st0); + ST0 = double_to_floatx80(env, st0); } -void helper_fprem(void) +void helper_fprem(CPUX86State *env) { double st0, st1, dblq, fpsrcop, fptemp; CPU_LDoubleU fpsrcop1, fptemp1; int expdif; signed long long int q; - st0 = floatx80_to_double(ST0); - st1 = floatx80_to_double(ST1); + st0 = floatx80_to_double(env, ST0); + st1 = floatx80_to_double(env, ST1); if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) { - ST0 = double_to_floatx80(0.0 / 0.0); /* NaN */ + ST0 = double_to_floatx80(env, 0.0 / 0.0); /* NaN */ env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */ return; } @@ -849,25 +848,25 @@ void helper_fprem(void) -(floor(fabs(fpsrcop))) : floor(fpsrcop); st0 -= (st1 * fpsrcop * fptemp); } - ST0 = double_to_floatx80(st0); + ST0 = double_to_floatx80(env, st0); } -void helper_fyl2xp1(void) +void helper_fyl2xp1(CPUX86State *env) { - double fptemp = floatx80_to_double(ST0); + double fptemp = floatx80_to_double(env, ST0); if ((fptemp + 1.0) > 0.0) { fptemp = log(fptemp + 1.0) / log(2.0); /* log2(ST + 1.0) */ - fptemp *= floatx80_to_double(ST1); - ST1 = double_to_floatx80(fptemp); - fpop(); + fptemp *= floatx80_to_double(env, ST1); + ST1 = double_to_floatx80(env, fptemp); + fpop(env); } else { env->fpus &= ~0x4700; env->fpus |= 0x400; } } -void helper_fsqrt(void) +void helper_fsqrt(CPUX86State *env) { if (floatx80_is_neg(ST0)) { env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */ @@ -876,27 +875,27 @@ void helper_fsqrt(void) ST0 = floatx80_sqrt(ST0, &env->fp_status); } -void helper_fsincos(void) +void helper_fsincos(CPUX86State *env) { - double fptemp = floatx80_to_double(ST0); + double fptemp = floatx80_to_double(env, ST0); if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) { env->fpus |= 0x400; } else { - ST0 = double_to_floatx80(sin(fptemp)); - fpush(); - ST0 = double_to_floatx80(cos(fptemp)); + ST0 = double_to_floatx80(env, sin(fptemp)); + fpush(env); + ST0 = double_to_floatx80(env, cos(fptemp)); env->fpus &= ~0x400; /* C2 <-- 0 */ /* the above code is for |arg| < 2**63 only */ } } -void helper_frndint(void) +void helper_frndint(CPUX86State *env) { ST0 = floatx80_round_to_int(ST0, &env->fp_status); } -void helper_fscale(void) +void helper_fscale(CPUX86State *env) { if (floatx80_is_any_nan(ST1)) { ST0 = ST1; @@ -906,33 +905,33 @@ void helper_fscale(void) } } -void helper_fsin(void) +void helper_fsin(CPUX86State *env) { - double fptemp = floatx80_to_double(ST0); + double fptemp = floatx80_to_double(env, ST0); if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) { env->fpus |= 0x400; } else { - ST0 = double_to_floatx80(sin(fptemp)); + ST0 = double_to_floatx80(env, sin(fptemp)); env->fpus &= ~0x400; /* C2 <-- 0 */ /* the above code is for |arg| < 2**53 only */ } } -void helper_fcos(void) +void helper_fcos(CPUX86State *env) { - double fptemp = floatx80_to_double(ST0); + double fptemp = floatx80_to_double(env, ST0); if ((fptemp > MAXTAN) || (fptemp < -MAXTAN)) { env->fpus |= 0x400; } else { - ST0 = double_to_floatx80(cos(fptemp)); + ST0 = double_to_floatx80(env, cos(fptemp)); env->fpus &= ~0x400; /* C2 <-- 0 */ /* the above code is for |arg| < 2**63 only */ } } -void helper_fxam_ST0(void) +void helper_fxam_ST0(CPUX86State *env) { CPU_LDoubleU temp; int expdif; @@ -963,7 +962,7 @@ void helper_fxam_ST0(void) } } -void helper_fstenv(target_ulong ptr, int data32) +void helper_fstenv(CPUX86State *env, target_ulong ptr, int data32) { int fpus, fptag, exp, i; uint64_t mant; @@ -991,37 +990,37 @@ void helper_fstenv(target_ulong ptr, int data32) } if (data32) { /* 32 bit */ - stl(ptr, env->fpuc); - stl(ptr + 4, fpus); - stl(ptr + 8, fptag); - stl(ptr + 12, 0); /* fpip */ - stl(ptr + 16, 0); /* fpcs */ - stl(ptr + 20, 0); /* fpoo */ - stl(ptr + 24, 0); /* fpos */ + cpu_stl_data(env, ptr, env->fpuc); + cpu_stl_data(env, ptr + 4, fpus); + cpu_stl_data(env, ptr + 8, fptag); + cpu_stl_data(env, ptr + 12, 0); /* fpip */ + cpu_stl_data(env, ptr + 16, 0); /* fpcs */ + cpu_stl_data(env, ptr + 20, 0); /* fpoo */ + cpu_stl_data(env, ptr + 24, 0); /* fpos */ } else { /* 16 bit */ - stw(ptr, env->fpuc); - stw(ptr + 2, fpus); - stw(ptr + 4, fptag); - stw(ptr + 6, 0); - stw(ptr + 8, 0); - stw(ptr + 10, 0); - stw(ptr + 12, 0); + cpu_stw_data(env, ptr, env->fpuc); + cpu_stw_data(env, ptr + 2, fpus); + cpu_stw_data(env, ptr + 4, fptag); + cpu_stw_data(env, ptr + 6, 0); + cpu_stw_data(env, ptr + 8, 0); + cpu_stw_data(env, ptr + 10, 0); + cpu_stw_data(env, ptr + 12, 0); } } -void helper_fldenv(target_ulong ptr, int data32) +void helper_fldenv(CPUX86State *env, target_ulong ptr, int data32) { int i, fpus, fptag; if (data32) { - env->fpuc = lduw(ptr); - fpus = lduw(ptr + 4); - fptag = lduw(ptr + 8); + env->fpuc = cpu_lduw_data(env, ptr); + fpus = cpu_lduw_data(env, ptr + 4); + fptag = cpu_lduw_data(env, ptr + 8); } else { - env->fpuc = lduw(ptr); - fpus = lduw(ptr + 2); - fptag = lduw(ptr + 4); + env->fpuc = cpu_lduw_data(env, ptr); + fpus = cpu_lduw_data(env, ptr + 2); + fptag = cpu_lduw_data(env, ptr + 4); } env->fpstt = (fpus >> 11) & 7; env->fpus = fpus & ~0x3800; @@ -1031,17 +1030,17 @@ void helper_fldenv(target_ulong ptr, int data32) } } -void helper_fsave(target_ulong ptr, int data32) +void helper_fsave(CPUX86State *env, target_ulong ptr, int data32) { floatx80 tmp; int i; - helper_fstenv(ptr, data32); + helper_fstenv(env, ptr, data32); ptr += (14 << data32); for (i = 0; i < 8; i++) { tmp = ST(i); - helper_fstt(tmp, ptr); + helper_fstt(env, tmp, ptr); ptr += 10; } @@ -1059,48 +1058,34 @@ void helper_fsave(target_ulong ptr, int data32) env->fptags[7] = 1; } -void helper_frstor(target_ulong ptr, int data32) +void helper_frstor(CPUX86State *env, target_ulong ptr, int data32) { floatx80 tmp; int i; - helper_fldenv(ptr, data32); + helper_fldenv(env, ptr, data32); ptr += (14 << data32); for (i = 0; i < 8; i++) { - tmp = helper_fldt(ptr); + tmp = helper_fldt(env, ptr); ST(i) = tmp; ptr += 10; } } #if defined(CONFIG_USER_ONLY) -void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32) +void cpu_x86_fsave(CPUX86State *env, target_ulong ptr, int data32) { - CPUX86State *saved_env; - - saved_env = env; - env = s; - - helper_fsave(ptr, data32); - - env = saved_env; + helper_fsave(env, ptr, data32); } -void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32) +void cpu_x86_frstor(CPUX86State *env, target_ulong ptr, int data32) { - CPUX86State *saved_env; - - saved_env = env; - env = s; - - helper_frstor(ptr, data32); - - env = saved_env; + helper_frstor(env, ptr, data32); } #endif -void helper_fxsave(target_ulong ptr, int data64) +void helper_fxsave(CPUX86State *env, target_ulong ptr, int data64) { int fpus, fptag, i, nb_xmm_regs; floatx80 tmp; @@ -1116,33 +1101,33 @@ void helper_fxsave(target_ulong ptr, int data64) for (i = 0; i < 8; i++) { fptag |= (env->fptags[i] << i); } - stw(ptr, env->fpuc); - stw(ptr + 2, fpus); - stw(ptr + 4, fptag ^ 0xff); + cpu_stw_data(env, ptr, env->fpuc); + cpu_stw_data(env, ptr + 2, fpus); + cpu_stw_data(env, ptr + 4, fptag ^ 0xff); #ifdef TARGET_X86_64 if (data64) { - stq(ptr + 0x08, 0); /* rip */ - stq(ptr + 0x10, 0); /* rdp */ + cpu_stq_data(env, ptr + 0x08, 0); /* rip */ + cpu_stq_data(env, ptr + 0x10, 0); /* rdp */ } else #endif { - stl(ptr + 0x08, 0); /* eip */ - stl(ptr + 0x0c, 0); /* sel */ - stl(ptr + 0x10, 0); /* dp */ - stl(ptr + 0x14, 0); /* sel */ + cpu_stl_data(env, ptr + 0x08, 0); /* eip */ + cpu_stl_data(env, ptr + 0x0c, 0); /* sel */ + cpu_stl_data(env, ptr + 0x10, 0); /* dp */ + cpu_stl_data(env, ptr + 0x14, 0); /* sel */ } addr = ptr + 0x20; for (i = 0; i < 8; i++) { tmp = ST(i); - helper_fstt(tmp, addr); + helper_fstt(env, tmp, addr); addr += 16; } if (env->cr[4] & CR4_OSFXSR_MASK) { /* XXX: finish it */ - stl(ptr + 0x18, env->mxcsr); /* mxcsr */ - stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */ + cpu_stl_data(env, ptr + 0x18, env->mxcsr); /* mxcsr */ + cpu_stl_data(env, ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */ if (env->hflags & HF_CS64_MASK) { nb_xmm_regs = 16; } else { @@ -1154,15 +1139,15 @@ void helper_fxsave(target_ulong ptr, int data64) || (env->hflags & HF_CPL_MASK) || !(env->hflags & HF_LMA_MASK)) { for (i = 0; i < nb_xmm_regs; i++) { - stq(addr, env->xmm_regs[i].XMM_Q(0)); - stq(addr + 8, env->xmm_regs[i].XMM_Q(1)); + cpu_stq_data(env, addr, env->xmm_regs[i].XMM_Q(0)); + cpu_stq_data(env, addr + 8, env->xmm_regs[i].XMM_Q(1)); addr += 16; } } } } -void helper_fxrstor(target_ulong ptr, int data64) +void helper_fxrstor(CPUX86State *env, target_ulong ptr, int data64) { int i, fpus, fptag, nb_xmm_regs; floatx80 tmp; @@ -1173,9 +1158,9 @@ void helper_fxrstor(target_ulong ptr, int data64) raise_exception(env, EXCP0D_GPF); } - env->fpuc = lduw(ptr); - fpus = lduw(ptr + 2); - fptag = lduw(ptr + 4); + env->fpuc = cpu_lduw_data(env, ptr); + fpus = cpu_lduw_data(env, ptr + 2); + fptag = cpu_lduw_data(env, ptr + 4); env->fpstt = (fpus >> 11) & 7; env->fpus = fpus & ~0x3800; fptag ^= 0xff; @@ -1185,15 +1170,15 @@ void helper_fxrstor(target_ulong ptr, int data64) addr = ptr + 0x20; for (i = 0; i < 8; i++) { - tmp = helper_fldt(addr); + tmp = helper_fldt(env, addr); ST(i) = tmp; addr += 16; } if (env->cr[4] & CR4_OSFXSR_MASK) { /* XXX: finish it */ - env->mxcsr = ldl(ptr + 0x18); - /* ldl(ptr + 0x1c); */ + env->mxcsr = cpu_ldl_data(env, ptr + 0x18); + /* cpu_ldl_data(env, ptr + 0x1c); */ if (env->hflags & HF_CS64_MASK) { nb_xmm_regs = 16; } else { @@ -1205,8 +1190,8 @@ void helper_fxrstor(target_ulong ptr, int data64) || (env->hflags & HF_CPL_MASK) || !(env->hflags & HF_LMA_MASK)) { for (i = 0; i < nb_xmm_regs; i++) { - env->xmm_regs[i].XMM_Q(0) = ldq(addr); - env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8); + env->xmm_regs[i].XMM_Q(0) = cpu_ldq_data(env, addr); + env->xmm_regs[i].XMM_Q(1) = cpu_ldq_data(env, addr + 8); addr += 16; } } @@ -1242,7 +1227,7 @@ floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper) #define SSE_RC_CHOP 0x6000 #define SSE_FZ 0x8000 -static void update_sse_status(void) +static void update_sse_status(CPUX86State *env) { int rnd_type; @@ -1271,20 +1256,20 @@ static void update_sse_status(void) set_flush_to_zero((env->mxcsr & SSE_FZ) ? 1 : 0, &env->fp_status); } -void helper_ldmxcsr(uint32_t val) +void helper_ldmxcsr(CPUX86State *env, uint32_t val) { env->mxcsr = val; - update_sse_status(); + update_sse_status(env); } -void helper_enter_mmx(void) +void helper_enter_mmx(CPUX86State *env) { env->fpstt = 0; *(uint32_t *)(env->fptags) = 0; *(uint32_t *)(env->fptags + 4) = 0; } -void helper_emms(void) +void helper_emms(CPUX86State *env) { /* set to empty state */ *(uint32_t *)(env->fptags) = 0x01010101; @@ -1292,7 +1277,7 @@ void helper_emms(void) } /* XXX: suppress */ -void helper_movq(void *d, void *s) +void helper_movq(CPUX86State *env, void *d, void *s) { *(uint64_t *)d = *(uint64_t *)s; } diff --git a/target-i386/helper.h b/target-i386/helper.h index 99ca18396d..ab6af638e6 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -1,93 +1,93 @@ #include "def-helper.h" -DEF_HELPER_FLAGS_1(cc_compute_all, TCG_CALL_PURE, i32, int) -DEF_HELPER_FLAGS_1(cc_compute_c, TCG_CALL_PURE, i32, int) +DEF_HELPER_FLAGS_2(cc_compute_all, TCG_CALL_PURE, i32, env, int) +DEF_HELPER_FLAGS_2(cc_compute_c, TCG_CALL_PURE, i32, env, int) DEF_HELPER_0(lock, void) DEF_HELPER_0(unlock, void) -DEF_HELPER_2(write_eflags, void, tl, i32) -DEF_HELPER_0(read_eflags, tl) -DEF_HELPER_1(divb_AL, void, tl) -DEF_HELPER_1(idivb_AL, void, tl) -DEF_HELPER_1(divw_AX, void, tl) -DEF_HELPER_1(idivw_AX, void, tl) -DEF_HELPER_1(divl_EAX, void, tl) -DEF_HELPER_1(idivl_EAX, void, tl) +DEF_HELPER_3(write_eflags, void, env, tl, i32) +DEF_HELPER_1(read_eflags, tl, env) +DEF_HELPER_2(divb_AL, void, env, tl) +DEF_HELPER_2(idivb_AL, void, env, tl) +DEF_HELPER_2(divw_AX, void, env, tl) +DEF_HELPER_2(idivw_AX, void, env, tl) +DEF_HELPER_2(divl_EAX, void, env, tl) +DEF_HELPER_2(idivl_EAX, void, env, tl) #ifdef TARGET_X86_64 -DEF_HELPER_1(mulq_EAX_T0, void, tl) -DEF_HELPER_1(imulq_EAX_T0, void, tl) -DEF_HELPER_2(imulq_T0_T1, tl, tl, tl) -DEF_HELPER_1(divq_EAX, void, tl) -DEF_HELPER_1(idivq_EAX, void, tl) +DEF_HELPER_2(mulq_EAX_T0, void, env, tl) +DEF_HELPER_2(imulq_EAX_T0, void, env, tl) +DEF_HELPER_3(imulq_T0_T1, tl, env, tl, tl) +DEF_HELPER_2(divq_EAX, void, env, tl) +DEF_HELPER_2(idivq_EAX, void, env, tl) #endif -DEF_HELPER_1(aam, void, int) -DEF_HELPER_1(aad, void, int) -DEF_HELPER_0(aaa, void) -DEF_HELPER_0(aas, void) -DEF_HELPER_0(daa, void) -DEF_HELPER_0(das, void) +DEF_HELPER_2(aam, void, env, int) +DEF_HELPER_2(aad, void, env, int) +DEF_HELPER_1(aaa, void, env) +DEF_HELPER_1(aas, void, env) +DEF_HELPER_1(daa, void, env) +DEF_HELPER_1(das, void, env) -DEF_HELPER_1(lsl, tl, tl) -DEF_HELPER_1(lar, tl, tl) -DEF_HELPER_1(verr, void, tl) -DEF_HELPER_1(verw, void, tl) -DEF_HELPER_1(lldt, void, int) -DEF_HELPER_1(ltr, void, int) -DEF_HELPER_2(load_seg, void, int, int) -DEF_HELPER_3(ljmp_protected, void, int, tl, int) -DEF_HELPER_4(lcall_real, void, int, tl, int, int) -DEF_HELPER_4(lcall_protected, void, int, tl, int, int) -DEF_HELPER_1(iret_real, void, int) -DEF_HELPER_2(iret_protected, void, int, int) -DEF_HELPER_2(lret_protected, void, int, int) -DEF_HELPER_1(read_crN, tl, int) -DEF_HELPER_2(write_crN, void, int, tl) -DEF_HELPER_1(lmsw, void, tl) -DEF_HELPER_0(clts, void) -DEF_HELPER_2(movl_drN_T0, void, int, tl) -DEF_HELPER_1(invlpg, void, tl) +DEF_HELPER_2(lsl, tl, env, tl) +DEF_HELPER_2(lar, tl, env, tl) +DEF_HELPER_2(verr, void, env, tl) +DEF_HELPER_2(verw, void, env, tl) +DEF_HELPER_2(lldt, void, env, int) +DEF_HELPER_2(ltr, void, env, int) +DEF_HELPER_3(load_seg, void, env, int, int) +DEF_HELPER_4(ljmp_protected, void, env, int, tl, int) +DEF_HELPER_5(lcall_real, void, env, int, tl, int, int) +DEF_HELPER_5(lcall_protected, void, env, int, tl, int, int) +DEF_HELPER_2(iret_real, void, env, int) +DEF_HELPER_3(iret_protected, void, env, int, int) +DEF_HELPER_3(lret_protected, void, env, int, int) +DEF_HELPER_2(read_crN, tl, env, int) +DEF_HELPER_3(write_crN, void, env, int, tl) +DEF_HELPER_2(lmsw, void, env, tl) +DEF_HELPER_1(clts, void, env) +DEF_HELPER_3(movl_drN_T0, void, env, int, tl) +DEF_HELPER_2(invlpg, void, env, tl) -DEF_HELPER_3(enter_level, void, int, int, tl) +DEF_HELPER_4(enter_level, void, env, int, int, tl) #ifdef TARGET_X86_64 -DEF_HELPER_3(enter64_level, void, int, int, tl) +DEF_HELPER_4(enter64_level, void, env, int, int, tl) #endif -DEF_HELPER_0(sysenter, void) -DEF_HELPER_1(sysexit, void, int) +DEF_HELPER_1(sysenter, void, env) +DEF_HELPER_2(sysexit, void, env, int) #ifdef TARGET_X86_64 -DEF_HELPER_1(syscall, void, int) -DEF_HELPER_1(sysret, void, int) +DEF_HELPER_2(syscall, void, env, int) +DEF_HELPER_2(sysret, void, env, int) #endif -DEF_HELPER_1(hlt, void, int) -DEF_HELPER_1(monitor, void, tl) -DEF_HELPER_1(mwait, void, int) -DEF_HELPER_0(debug, void) -DEF_HELPER_0(reset_rf, void) +DEF_HELPER_2(hlt, void, env, int) +DEF_HELPER_2(monitor, void, env, tl) +DEF_HELPER_2(mwait, void, env, int) +DEF_HELPER_1(debug, void, env) +DEF_HELPER_1(reset_rf, void, env) DEF_HELPER_3(raise_interrupt, void, env, int, int) DEF_HELPER_2(raise_exception, void, env, int) -DEF_HELPER_0(cli, void) -DEF_HELPER_0(sti, void) -DEF_HELPER_0(set_inhibit_irq, void) -DEF_HELPER_0(reset_inhibit_irq, void) -DEF_HELPER_2(boundw, void, tl, int) -DEF_HELPER_2(boundl, void, tl, int) -DEF_HELPER_0(rsm, void) -DEF_HELPER_1(into, void, int) -DEF_HELPER_1(cmpxchg8b, void, tl) +DEF_HELPER_1(cli, void, env) +DEF_HELPER_1(sti, void, env) +DEF_HELPER_1(set_inhibit_irq, void, env) +DEF_HELPER_1(reset_inhibit_irq, void, env) +DEF_HELPER_3(boundw, void, env, tl, int) +DEF_HELPER_3(boundl, void, env, tl, int) +DEF_HELPER_1(rsm, void, env) +DEF_HELPER_2(into, void, env, int) +DEF_HELPER_2(cmpxchg8b, void, env, tl) #ifdef TARGET_X86_64 -DEF_HELPER_1(cmpxchg16b, void, tl) +DEF_HELPER_2(cmpxchg16b, void, env, tl) #endif -DEF_HELPER_0(single_step, void) -DEF_HELPER_0(cpuid, void) -DEF_HELPER_0(rdtsc, void) -DEF_HELPER_0(rdtscp, void) -DEF_HELPER_0(rdpmc, void) -DEF_HELPER_0(rdmsr, void) -DEF_HELPER_0(wrmsr, void) +DEF_HELPER_1(single_step, void, env) +DEF_HELPER_1(cpuid, void, env) +DEF_HELPER_1(rdtsc, void, env) +DEF_HELPER_1(rdtscp, void, env) +DEF_HELPER_1(rdpmc, void, env) +DEF_HELPER_1(rdmsr, void, env) +DEF_HELPER_1(wrmsr, void, env) -DEF_HELPER_1(check_iob, void, i32) -DEF_HELPER_1(check_iow, void, i32) -DEF_HELPER_1(check_iol, void, i32) +DEF_HELPER_2(check_iob, void, env, i32) +DEF_HELPER_2(check_iow, void, env, i32) +DEF_HELPER_2(check_iol, void, env, i32) DEF_HELPER_2(outb, void, i32, i32) DEF_HELPER_1(inb, tl, i32) DEF_HELPER_2(outw, void, i32, i32) @@ -95,127 +95,127 @@ DEF_HELPER_1(inw, tl, i32) DEF_HELPER_2(outl, void, i32, i32) DEF_HELPER_1(inl, tl, i32) -DEF_HELPER_2(svm_check_intercept_param, void, i32, i64) -DEF_HELPER_2(vmexit, void, i32, i64) -DEF_HELPER_3(svm_check_io, void, i32, i32, i32) -DEF_HELPER_2(vmrun, void, int, int) -DEF_HELPER_0(vmmcall, void) -DEF_HELPER_1(vmload, void, int) -DEF_HELPER_1(vmsave, void, int) -DEF_HELPER_0(stgi, void) -DEF_HELPER_0(clgi, void) -DEF_HELPER_0(skinit, void) -DEF_HELPER_1(invlpga, void, int) +DEF_HELPER_3(svm_check_intercept_param, void, env, i32, i64) +DEF_HELPER_3(vmexit, void, env, i32, i64) +DEF_HELPER_4(svm_check_io, void, env, i32, i32, i32) +DEF_HELPER_3(vmrun, void, env, int, int) +DEF_HELPER_1(vmmcall, void, env) +DEF_HELPER_2(vmload, void, env, int) +DEF_HELPER_2(vmsave, void, env, int) +DEF_HELPER_1(stgi, void, env) +DEF_HELPER_1(clgi, void, env) +DEF_HELPER_1(skinit, void, env) +DEF_HELPER_2(invlpga, void, env, int) /* x86 FPU */ -DEF_HELPER_1(flds_FT0, void, i32) -DEF_HELPER_1(fldl_FT0, void, i64) -DEF_HELPER_1(fildl_FT0, void, s32) -DEF_HELPER_1(flds_ST0, void, i32) -DEF_HELPER_1(fldl_ST0, void, i64) -DEF_HELPER_1(fildl_ST0, void, s32) -DEF_HELPER_1(fildll_ST0, void, s64) -DEF_HELPER_0(fsts_ST0, i32) -DEF_HELPER_0(fstl_ST0, i64) -DEF_HELPER_0(fist_ST0, s32) -DEF_HELPER_0(fistl_ST0, s32) -DEF_HELPER_0(fistll_ST0, s64) -DEF_HELPER_0(fistt_ST0, s32) -DEF_HELPER_0(fisttl_ST0, s32) -DEF_HELPER_0(fisttll_ST0, s64) -DEF_HELPER_1(fldt_ST0, void, tl) -DEF_HELPER_1(fstt_ST0, void, tl) -DEF_HELPER_0(fpush, void) -DEF_HELPER_0(fpop, void) -DEF_HELPER_0(fdecstp, void) -DEF_HELPER_0(fincstp, void) -DEF_HELPER_1(ffree_STN, void, int) -DEF_HELPER_0(fmov_ST0_FT0, void) -DEF_HELPER_1(fmov_FT0_STN, void, int) -DEF_HELPER_1(fmov_ST0_STN, void, int) -DEF_HELPER_1(fmov_STN_ST0, void, int) -DEF_HELPER_1(fxchg_ST0_STN, void, int) -DEF_HELPER_0(fcom_ST0_FT0, void) -DEF_HELPER_0(fucom_ST0_FT0, void) -DEF_HELPER_0(fcomi_ST0_FT0, void) -DEF_HELPER_0(fucomi_ST0_FT0, void) -DEF_HELPER_0(fadd_ST0_FT0, void) -DEF_HELPER_0(fmul_ST0_FT0, void) -DEF_HELPER_0(fsub_ST0_FT0, void) -DEF_HELPER_0(fsubr_ST0_FT0, void) -DEF_HELPER_0(fdiv_ST0_FT0, void) -DEF_HELPER_0(fdivr_ST0_FT0, void) -DEF_HELPER_1(fadd_STN_ST0, void, int) -DEF_HELPER_1(fmul_STN_ST0, void, int) -DEF_HELPER_1(fsub_STN_ST0, void, int) -DEF_HELPER_1(fsubr_STN_ST0, void, int) -DEF_HELPER_1(fdiv_STN_ST0, void, int) -DEF_HELPER_1(fdivr_STN_ST0, void, int) -DEF_HELPER_0(fchs_ST0, void) -DEF_HELPER_0(fabs_ST0, void) -DEF_HELPER_0(fxam_ST0, void) -DEF_HELPER_0(fld1_ST0, void) -DEF_HELPER_0(fldl2t_ST0, void) -DEF_HELPER_0(fldl2e_ST0, void) -DEF_HELPER_0(fldpi_ST0, void) -DEF_HELPER_0(fldlg2_ST0, void) -DEF_HELPER_0(fldln2_ST0, void) -DEF_HELPER_0(fldz_ST0, void) -DEF_HELPER_0(fldz_FT0, void) -DEF_HELPER_0(fnstsw, i32) -DEF_HELPER_0(fnstcw, i32) -DEF_HELPER_1(fldcw, void, i32) -DEF_HELPER_0(fclex, void) -DEF_HELPER_0(fwait, void) -DEF_HELPER_0(fninit, void) -DEF_HELPER_1(fbld_ST0, void, tl) -DEF_HELPER_1(fbst_ST0, void, tl) -DEF_HELPER_0(f2xm1, void) -DEF_HELPER_0(fyl2x, void) -DEF_HELPER_0(fptan, void) -DEF_HELPER_0(fpatan, void) -DEF_HELPER_0(fxtract, void) -DEF_HELPER_0(fprem1, void) -DEF_HELPER_0(fprem, void) -DEF_HELPER_0(fyl2xp1, void) -DEF_HELPER_0(fsqrt, void) -DEF_HELPER_0(fsincos, void) -DEF_HELPER_0(frndint, void) -DEF_HELPER_0(fscale, void) -DEF_HELPER_0(fsin, void) -DEF_HELPER_0(fcos, void) -DEF_HELPER_2(fstenv, void, tl, int) -DEF_HELPER_2(fldenv, void, tl, int) -DEF_HELPER_2(fsave, void, tl, int) -DEF_HELPER_2(frstor, void, tl, int) -DEF_HELPER_2(fxsave, void, tl, int) -DEF_HELPER_2(fxrstor, void, tl, int) +DEF_HELPER_2(flds_FT0, void, env, i32) +DEF_HELPER_2(fldl_FT0, void, env, i64) +DEF_HELPER_2(fildl_FT0, void, env, s32) +DEF_HELPER_2(flds_ST0, void, env, i32) +DEF_HELPER_2(fldl_ST0, void, env, i64) +DEF_HELPER_2(fildl_ST0, void, env, s32) +DEF_HELPER_2(fildll_ST0, void, env, s64) +DEF_HELPER_1(fsts_ST0, i32, env) +DEF_HELPER_1(fstl_ST0, i64, env) +DEF_HELPER_1(fist_ST0, s32, env) +DEF_HELPER_1(fistl_ST0, s32, env) +DEF_HELPER_1(fistll_ST0, s64, env) +DEF_HELPER_1(fistt_ST0, s32, env) +DEF_HELPER_1(fisttl_ST0, s32, env) +DEF_HELPER_1(fisttll_ST0, s64, env) +DEF_HELPER_2(fldt_ST0, void, env, tl) +DEF_HELPER_2(fstt_ST0, void, env, tl) +DEF_HELPER_1(fpush, void, env) +DEF_HELPER_1(fpop, void, env) +DEF_HELPER_1(fdecstp, void, env) +DEF_HELPER_1(fincstp, void, env) +DEF_HELPER_2(ffree_STN, void, env, int) +DEF_HELPER_1(fmov_ST0_FT0, void, env) +DEF_HELPER_2(fmov_FT0_STN, void, env, int) +DEF_HELPER_2(fmov_ST0_STN, void, env, int) +DEF_HELPER_2(fmov_STN_ST0, void, env, int) +DEF_HELPER_2(fxchg_ST0_STN, void, env, int) +DEF_HELPER_1(fcom_ST0_FT0, void, env) +DEF_HELPER_1(fucom_ST0_FT0, void, env) +DEF_HELPER_1(fcomi_ST0_FT0, void, env) +DEF_HELPER_1(fucomi_ST0_FT0, void, env) +DEF_HELPER_1(fadd_ST0_FT0, void, env) +DEF_HELPER_1(fmul_ST0_FT0, void, env) +DEF_HELPER_1(fsub_ST0_FT0, void, env) +DEF_HELPER_1(fsubr_ST0_FT0, void, env) +DEF_HELPER_1(fdiv_ST0_FT0, void, env) +DEF_HELPER_1(fdivr_ST0_FT0, void, env) +DEF_HELPER_2(fadd_STN_ST0, void, env, int) +DEF_HELPER_2(fmul_STN_ST0, void, env, int) +DEF_HELPER_2(fsub_STN_ST0, void, env, int) +DEF_HELPER_2(fsubr_STN_ST0, void, env, int) +DEF_HELPER_2(fdiv_STN_ST0, void, env, int) +DEF_HELPER_2(fdivr_STN_ST0, void, env, int) +DEF_HELPER_1(fchs_ST0, void, env) +DEF_HELPER_1(fabs_ST0, void, env) +DEF_HELPER_1(fxam_ST0, void, env) +DEF_HELPER_1(fld1_ST0, void, env) +DEF_HELPER_1(fldl2t_ST0, void, env) +DEF_HELPER_1(fldl2e_ST0, void, env) +DEF_HELPER_1(fldpi_ST0, void, env) +DEF_HELPER_1(fldlg2_ST0, void, env) +DEF_HELPER_1(fldln2_ST0, void, env) +DEF_HELPER_1(fldz_ST0, void, env) +DEF_HELPER_1(fldz_FT0, void, env) +DEF_HELPER_1(fnstsw, i32, env) +DEF_HELPER_1(fnstcw, i32, env) +DEF_HELPER_2(fldcw, void, env, i32) +DEF_HELPER_1(fclex, void, env) +DEF_HELPER_1(fwait, void, env) +DEF_HELPER_1(fninit, void, env) +DEF_HELPER_2(fbld_ST0, void, env, tl) +DEF_HELPER_2(fbst_ST0, void, env, tl) +DEF_HELPER_1(f2xm1, void, env) +DEF_HELPER_1(fyl2x, void, env) +DEF_HELPER_1(fptan, void, env) +DEF_HELPER_1(fpatan, void, env) +DEF_HELPER_1(fxtract, void, env) +DEF_HELPER_1(fprem1, void, env) +DEF_HELPER_1(fprem, void, env) +DEF_HELPER_1(fyl2xp1, void, env) +DEF_HELPER_1(fsqrt, void, env) +DEF_HELPER_1(fsincos, void, env) +DEF_HELPER_1(frndint, void, env) +DEF_HELPER_1(fscale, void, env) +DEF_HELPER_1(fsin, void, env) +DEF_HELPER_1(fcos, void, env) +DEF_HELPER_3(fstenv, void, env, tl, int) +DEF_HELPER_3(fldenv, void, env, tl, int) +DEF_HELPER_3(fsave, void, env, tl, int) +DEF_HELPER_3(frstor, void, env, tl, int) +DEF_HELPER_3(fxsave, void, env, tl, int) +DEF_HELPER_3(fxrstor, void, env, tl, int) DEF_HELPER_1(bsf, tl, tl) DEF_HELPER_1(bsr, tl, tl) DEF_HELPER_2(lzcnt, tl, tl, int) /* MMX/SSE */ -DEF_HELPER_1(ldmxcsr, void, i32) -DEF_HELPER_0(enter_mmx, void) -DEF_HELPER_0(emms, void) -DEF_HELPER_2(movq, void, ptr, ptr) +DEF_HELPER_2(ldmxcsr, void, env, i32) +DEF_HELPER_1(enter_mmx, void, env) +DEF_HELPER_1(emms, void, env) +DEF_HELPER_3(movq, void, env, ptr, ptr) #define SHIFT 0 #include "ops_sse_header.h" #define SHIFT 1 #include "ops_sse_header.h" -DEF_HELPER_2(rclb, tl, tl, tl) -DEF_HELPER_2(rclw, tl, tl, tl) -DEF_HELPER_2(rcll, tl, tl, tl) -DEF_HELPER_2(rcrb, tl, tl, tl) -DEF_HELPER_2(rcrw, tl, tl, tl) -DEF_HELPER_2(rcrl, tl, tl, tl) +DEF_HELPER_3(rclb, tl, env, tl, tl) +DEF_HELPER_3(rclw, tl, env, tl, tl) +DEF_HELPER_3(rcll, tl, env, tl, tl) +DEF_HELPER_3(rcrb, tl, env, tl, tl) +DEF_HELPER_3(rcrw, tl, env, tl, tl) +DEF_HELPER_3(rcrl, tl, env, tl, tl) #ifdef TARGET_X86_64 -DEF_HELPER_2(rclq, tl, tl, tl) -DEF_HELPER_2(rcrq, tl, tl, tl) +DEF_HELPER_3(rclq, tl, env, tl, tl) +DEF_HELPER_3(rcrq, tl, env, tl, tl) #endif #include "def-helper.h" diff --git a/target-i386/int_helper.c b/target-i386/int_helper.c index e1f66f5ad1..f39747e806 100644 --- a/target-i386/int_helper.c +++ b/target-i386/int_helper.c @@ -18,7 +18,6 @@ */ #include "cpu.h" -#include "dyngen-exec.h" #include "host-utils.h" #include "helper.h" @@ -42,7 +41,7 @@ static const uint8_t rclw_table[32] = { /* division, flags are undefined */ -void helper_divb_AL(target_ulong t0) +void helper_divb_AL(CPUX86State *env, target_ulong t0) { unsigned int num, den, q, r; @@ -60,7 +59,7 @@ void helper_divb_AL(target_ulong t0) EAX = (EAX & ~0xffff) | (r << 8) | q; } -void helper_idivb_AL(target_ulong t0) +void helper_idivb_AL(CPUX86State *env, target_ulong t0) { int num, den, q, r; @@ -78,7 +77,7 @@ void helper_idivb_AL(target_ulong t0) EAX = (EAX & ~0xffff) | (r << 8) | q; } -void helper_divw_AX(target_ulong t0) +void helper_divw_AX(CPUX86State *env, target_ulong t0) { unsigned int num, den, q, r; @@ -97,7 +96,7 @@ void helper_divw_AX(target_ulong t0) EDX = (EDX & ~0xffff) | r; } -void helper_idivw_AX(target_ulong t0) +void helper_idivw_AX(CPUX86State *env, target_ulong t0) { int num, den, q, r; @@ -116,7 +115,7 @@ void helper_idivw_AX(target_ulong t0) EDX = (EDX & ~0xffff) | r; } -void helper_divl_EAX(target_ulong t0) +void helper_divl_EAX(CPUX86State *env, target_ulong t0) { unsigned int den, r; uint64_t num, q; @@ -135,7 +134,7 @@ void helper_divl_EAX(target_ulong t0) EDX = (uint32_t)r; } -void helper_idivl_EAX(target_ulong t0) +void helper_idivl_EAX(CPUX86State *env, target_ulong t0) { int den, r; int64_t num, q; @@ -157,7 +156,7 @@ void helper_idivl_EAX(target_ulong t0) /* bcd */ /* XXX: exception */ -void helper_aam(int base) +void helper_aam(CPUX86State *env, int base) { int al, ah; @@ -168,7 +167,7 @@ void helper_aam(int base) CC_DST = al; } -void helper_aad(int base) +void helper_aad(CPUX86State *env, int base) { int al, ah; @@ -179,13 +178,13 @@ void helper_aad(int base) CC_DST = al; } -void helper_aaa(void) +void helper_aaa(CPUX86State *env) { int icarry; int al, ah, af; int eflags; - eflags = helper_cc_compute_all(CC_OP); + eflags = cpu_cc_compute_all(env, CC_OP); af = eflags & CC_A; al = EAX & 0xff; ah = (EAX >> 8) & 0xff; @@ -203,13 +202,13 @@ void helper_aaa(void) CC_SRC = eflags; } -void helper_aas(void) +void helper_aas(CPUX86State *env) { int icarry; int al, ah, af; int eflags; - eflags = helper_cc_compute_all(CC_OP); + eflags = cpu_cc_compute_all(env, CC_OP); af = eflags & CC_A; al = EAX & 0xff; ah = (EAX >> 8) & 0xff; @@ -227,12 +226,12 @@ void helper_aas(void) CC_SRC = eflags; } -void helper_daa(void) +void helper_daa(CPUX86State *env) { int old_al, al, af, cf; int eflags; - eflags = helper_cc_compute_all(CC_OP); + eflags = cpu_cc_compute_all(env, CC_OP); cf = eflags & CC_C; af = eflags & CC_A; old_al = al = EAX & 0xff; @@ -254,12 +253,12 @@ void helper_daa(void) CC_SRC = eflags; } -void helper_das(void) +void helper_das(CPUX86State *env) { int al, al1, af, cf; int eflags; - eflags = helper_cc_compute_all(CC_OP); + eflags = cpu_cc_compute_all(env, CC_OP); cf = eflags & CC_C; af = eflags & CC_A; al = EAX & 0xff; @@ -375,7 +374,7 @@ static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b) return 0; } -void helper_mulq_EAX_T0(target_ulong t0) +void helper_mulq_EAX_T0(CPUX86State *env, target_ulong t0) { uint64_t r0, r1; @@ -386,7 +385,7 @@ void helper_mulq_EAX_T0(target_ulong t0) CC_SRC = r1; } -void helper_imulq_EAX_T0(target_ulong t0) +void helper_imulq_EAX_T0(CPUX86State *env, target_ulong t0) { uint64_t r0, r1; @@ -397,7 +396,8 @@ void helper_imulq_EAX_T0(target_ulong t0) CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63)); } -target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1) +target_ulong helper_imulq_T0_T1(CPUX86State *env, target_ulong t0, + target_ulong t1) { uint64_t r0, r1; @@ -407,7 +407,7 @@ target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1) return r0; } -void helper_divq_EAX(target_ulong t0) +void helper_divq_EAX(CPUX86State *env, target_ulong t0) { uint64_t r0, r1; @@ -423,7 +423,7 @@ void helper_divq_EAX(target_ulong t0) EDX = r1; } -void helper_idivq_EAX(target_ulong t0) +void helper_idivq_EAX(CPUX86State *env, target_ulong t0) { uint64_t r0, r1; diff --git a/target-i386/kvm-stub.c b/target-i386/kvm-stub.c new file mode 100644 index 0000000000..11429c461e --- /dev/null +++ b/target-i386/kvm-stub.c @@ -0,0 +1,18 @@ +/* + * QEMU KVM x86 specific function stubs + * + * Copyright Linaro Limited 2012 + * + * Author: Peter Maydell <peter.maydell@linaro.org> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ +#include "qemu-common.h" +#include "kvm_i386.h" + +bool kvm_allows_irq0_override(void) +{ + return 1; +} diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 4cfb3faf01..696b14a04a 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -23,6 +23,7 @@ #include "qemu-common.h" #include "sysemu.h" #include "kvm.h" +#include "kvm_i386.h" #include "cpu.h" #include "gdbstub.h" #include "host-utils.h" @@ -65,6 +66,11 @@ static bool has_msr_async_pf_en; static bool has_msr_misc_enable; static int lm_capable_kernel; +bool kvm_allows_irq0_override(void) +{ + return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing(); +} + static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max) { struct kvm_cpuid2 *cpuid; @@ -2041,4 +2047,11 @@ void kvm_arch_init_irq_routing(KVMState *s) */ no_hpet = 1; } + /* We know at this point that we're using the in-kernel + * irqchip, so we can use irqfds, and on x86 we know + * we can use msi via irqfd and GSI routing. + */ + kvm_irqfds_allowed = true; + kvm_msi_via_irqfd_allowed = true; + kvm_gsi_routing_allowed = true; } diff --git a/target-i386/kvm_i386.h b/target-i386/kvm_i386.h new file mode 100644 index 0000000000..b82bbf401e --- /dev/null +++ b/target-i386/kvm_i386.h @@ -0,0 +1,16 @@ +/* + * QEMU KVM support -- x86 specific functions. + * + * Copyright (c) 2012 Linaro Limited + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QEMU_KVM_I386_H +#define QEMU_KVM_I386_H + +bool kvm_allows_irq0_override(void); + +#endif diff --git a/target-i386/mem_helper.c b/target-i386/mem_helper.c index 91353c0788..7f99c7cfe3 100644 --- a/target-i386/mem_helper.c +++ b/target-i386/mem_helper.c @@ -18,7 +18,6 @@ */ #include "cpu.h" -#include "dyngen-exec.h" #include "helper.h" #if !defined(CONFIG_USER_ONLY) @@ -39,19 +38,19 @@ void helper_unlock(void) spin_unlock(&global_cpu_lock); } -void helper_cmpxchg8b(target_ulong a0) +void helper_cmpxchg8b(CPUX86State *env, target_ulong a0) { uint64_t d; int eflags; - eflags = helper_cc_compute_all(CC_OP); - d = ldq(a0); + eflags = cpu_cc_compute_all(env, CC_OP); + d = cpu_ldq_data(env, a0); if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) { - stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX); + cpu_stq_data(env, a0, ((uint64_t)ECX << 32) | (uint32_t)EBX); eflags |= CC_Z; } else { /* always do the store */ - stq(a0, d); + cpu_stq_data(env, a0, d); EDX = (uint32_t)(d >> 32); EAX = (uint32_t)d; eflags &= ~CC_Z; @@ -60,7 +59,7 @@ void helper_cmpxchg8b(target_ulong a0) } #ifdef TARGET_X86_64 -void helper_cmpxchg16b(target_ulong a0) +void helper_cmpxchg16b(CPUX86State *env, target_ulong a0) { uint64_t d0, d1; int eflags; @@ -68,17 +67,17 @@ void helper_cmpxchg16b(target_ulong a0) if ((a0 & 0xf) != 0) { raise_exception(env, EXCP0D_GPF); } - eflags = helper_cc_compute_all(CC_OP); - d0 = ldq(a0); - d1 = ldq(a0 + 8); + eflags = cpu_cc_compute_all(env, CC_OP); + d0 = cpu_ldq_data(env, a0); + d1 = cpu_ldq_data(env, a0 + 8); if (d0 == EAX && d1 == EDX) { - stq(a0, EBX); - stq(a0 + 8, ECX); + cpu_stq_data(env, a0, EBX); + cpu_stq_data(env, a0 + 8, ECX); eflags |= CC_Z; } else { /* always do the store */ - stq(a0, d0); - stq(a0 + 8, d1); + cpu_stq_data(env, a0, d0); + cpu_stq_data(env, a0 + 8, d1); EDX = d1; EAX = d0; eflags &= ~CC_Z; @@ -87,24 +86,24 @@ void helper_cmpxchg16b(target_ulong a0) } #endif -void helper_boundw(target_ulong a0, int v) +void helper_boundw(CPUX86State *env, target_ulong a0, int v) { int low, high; - low = ldsw(a0); - high = ldsw(a0 + 2); + low = cpu_ldsw_data(env, a0); + high = cpu_ldsw_data(env, a0 + 2); v = (int16_t)v; if (v < low || v > high) { raise_exception(env, EXCP05_BOUND); } } -void helper_boundl(target_ulong a0, int v) +void helper_boundl(CPUX86State *env, target_ulong a0, int v) { int low, high; - low = ldl(a0); - high = ldl(a0 + 4); + low = cpu_ldl_data(env, a0); + high = cpu_ldl_data(env, a0 + 4); if (v < low || v > high) { raise_exception(env, EXCP05_BOUND); } @@ -133,15 +132,11 @@ void helper_boundl(target_ulong a0, int v) NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ /* XXX: fix it to restore all registers */ -void tlb_fill(CPUX86State *env1, target_ulong addr, int is_write, int mmu_idx, +void tlb_fill(CPUX86State *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { TranslationBlock *tb; int ret; - CPUX86State *saved_env; - - saved_env = env; - env = env1; ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx); if (ret) { @@ -156,6 +151,5 @@ void tlb_fill(CPUX86State *env1, target_ulong addr, int is_write, int mmu_idx, } raise_exception_err(env, env->exception_index, env->error_code); } - env = saved_env; } #endif diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c index ce675b7218..a02037963f 100644 --- a/target-i386/misc_helper.c +++ b/target-i386/misc_helper.c @@ -18,7 +18,6 @@ */ #include "cpu.h" -#include "dyngen-exec.h" #include "ioport.h" #include "helper.h" @@ -27,7 +26,7 @@ #endif /* !defined(CONFIG_USER_ONLY) */ /* check if Port I/O is allowed in TSS */ -static inline void check_io(int addr, int size) +static inline void check_io(CPUX86State *env, int addr, int size) { int io_offset, val, mask; @@ -37,13 +36,13 @@ static inline void check_io(int addr, int size) env->tr.limit < 103) { goto fail; } - io_offset = lduw_kernel(env->tr.base + 0x66); + io_offset = cpu_lduw_kernel(env, env->tr.base + 0x66); io_offset += (addr >> 3); /* Note: the check needs two bytes */ if ((io_offset + 1) > env->tr.limit) { goto fail; } - val = lduw_kernel(env->tr.base + io_offset); + val = cpu_lduw_kernel(env, env->tr.base + io_offset); val >>= (addr & 7); mask = (1 << size) - 1; /* all bits must be zero to allow the I/O */ @@ -53,19 +52,19 @@ static inline void check_io(int addr, int size) } } -void helper_check_iob(uint32_t t0) +void helper_check_iob(CPUX86State *env, uint32_t t0) { - check_io(t0, 1); + check_io(env, t0, 1); } -void helper_check_iow(uint32_t t0) +void helper_check_iow(CPUX86State *env, uint32_t t0) { - check_io(t0, 2); + check_io(env, t0, 2); } -void helper_check_iol(uint32_t t0) +void helper_check_iol(CPUX86State *env, uint32_t t0) { - check_io(t0, 4); + check_io(env, t0, 4); } void helper_outb(uint32_t port, uint32_t data) @@ -98,17 +97,17 @@ target_ulong helper_inl(uint32_t port) return cpu_inl(port); } -void helper_into(int next_eip_addend) +void helper_into(CPUX86State *env, int next_eip_addend) { int eflags; - eflags = helper_cc_compute_all(CC_OP); + eflags = cpu_cc_compute_all(env, CC_OP); if (eflags & CC_O) { raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend); } } -void helper_single_step(void) +void helper_single_step(CPUX86State *env) { #ifndef CONFIG_USER_ONLY check_hw_breakpoints(env, 1); @@ -117,7 +116,7 @@ void helper_single_step(void) raise_exception(env, EXCP01_DB); } -void helper_cpuid(void) +void helper_cpuid(CPUX86State *env) { uint32_t eax, ebx, ecx, edx; @@ -131,20 +130,20 @@ void helper_cpuid(void) } #if defined(CONFIG_USER_ONLY) -target_ulong helper_read_crN(int reg) +target_ulong helper_read_crN(CPUX86State *env, int reg) { return 0; } -void helper_write_crN(int reg, target_ulong t0) +void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) { } -void helper_movl_drN_T0(int reg, target_ulong t0) +void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0) { } #else -target_ulong helper_read_crN(int reg) +target_ulong helper_read_crN(CPUX86State *env, int reg) { target_ulong val; @@ -164,7 +163,7 @@ target_ulong helper_read_crN(int reg) return val; } -void helper_write_crN(int reg, target_ulong t0) +void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) { cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0); switch (reg) { @@ -189,7 +188,7 @@ void helper_write_crN(int reg, target_ulong t0) } } -void helper_movl_drN_T0(int reg, target_ulong t0) +void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0) { int i; @@ -211,21 +210,21 @@ void helper_movl_drN_T0(int reg, target_ulong t0) } #endif -void helper_lmsw(target_ulong t0) +void helper_lmsw(CPUX86State *env, target_ulong t0) { /* only 4 lower bits of CR0 are modified. PE cannot be set to zero if already set to one. */ t0 = (env->cr[0] & ~0xe) | (t0 & 0xf); - helper_write_crN(0, t0); + helper_write_crN(env, 0, t0); } -void helper_invlpg(target_ulong addr) +void helper_invlpg(CPUX86State *env, target_ulong addr) { cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0); tlb_flush_page(env, addr); } -void helper_rdtsc(void) +void helper_rdtsc(CPUX86State *env) { uint64_t val; @@ -239,13 +238,13 @@ void helper_rdtsc(void) EDX = (uint32_t)(val >> 32); } -void helper_rdtscp(void) +void helper_rdtscp(CPUX86State *env) { - helper_rdtsc(); + helper_rdtsc(env); ECX = (uint32_t)(env->tsc_aux); } -void helper_rdpmc(void) +void helper_rdpmc(CPUX86State *env) { if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { raise_exception(env, EXCP0D_GPF); @@ -258,15 +257,15 @@ void helper_rdpmc(void) } #if defined(CONFIG_USER_ONLY) -void helper_wrmsr(void) +void helper_wrmsr(CPUX86State *env) { } -void helper_rdmsr(void) +void helper_rdmsr(CPUX86State *env) { } #else -void helper_wrmsr(void) +void helper_wrmsr(CPUX86State *env) { uint64_t val; @@ -413,7 +412,7 @@ void helper_wrmsr(void) } } -void helper_rdmsr(void) +void helper_rdmsr(CPUX86State *env) { uint64_t val; @@ -554,7 +553,7 @@ void helper_rdmsr(void) } #endif -static void do_hlt(void) +static void do_hlt(CPUX86State *env) { env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */ env->halted = 1; @@ -562,15 +561,15 @@ static void do_hlt(void) cpu_loop_exit(env); } -void helper_hlt(int next_eip_addend) +void helper_hlt(CPUX86State *env, int next_eip_addend) { cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0); EIP += next_eip_addend; - do_hlt(); + do_hlt(env); } -void helper_monitor(target_ulong ptr) +void helper_monitor(CPUX86State *env, target_ulong ptr) { if ((uint32_t)ECX != 0) { raise_exception(env, EXCP0D_GPF); @@ -579,7 +578,7 @@ void helper_monitor(target_ulong ptr) cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0); } -void helper_mwait(int next_eip_addend) +void helper_mwait(CPUX86State *env, int next_eip_addend) { if ((uint32_t)ECX != 0) { raise_exception(env, EXCP0D_GPF); @@ -592,11 +591,11 @@ void helper_mwait(int next_eip_addend) /* more than one CPU: do not sleep because another CPU may wake this one */ } else { - do_hlt(); + do_hlt(env); } } -void helper_debug(void) +void helper_debug(CPUX86State *env) { env->exception_index = EXCP_DEBUG; cpu_loop_exit(env); diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h index d109512d5b..cad9d758de 100644 --- a/target-i386/ops_sse.h +++ b/target-i386/ops_sse.h @@ -35,7 +35,7 @@ #define SUFFIX _xmm #endif -void glue(helper_psrlw, SUFFIX)(Reg *d, Reg *s) +void glue(helper_psrlw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int shift; @@ -59,7 +59,7 @@ void glue(helper_psrlw, SUFFIX)(Reg *d, Reg *s) } } -void glue(helper_psraw, SUFFIX)(Reg *d, Reg *s) +void glue(helper_psraw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int shift; @@ -80,7 +80,7 @@ void glue(helper_psraw, SUFFIX)(Reg *d, Reg *s) #endif } -void glue(helper_psllw, SUFFIX)(Reg *d, Reg *s) +void glue(helper_psllw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int shift; @@ -104,7 +104,7 @@ void glue(helper_psllw, SUFFIX)(Reg *d, Reg *s) } } -void glue(helper_psrld, SUFFIX)(Reg *d, Reg *s) +void glue(helper_psrld, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int shift; @@ -124,7 +124,7 @@ void glue(helper_psrld, SUFFIX)(Reg *d, Reg *s) } } -void glue(helper_psrad, SUFFIX)(Reg *d, Reg *s) +void glue(helper_psrad, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int shift; @@ -141,7 +141,7 @@ void glue(helper_psrad, SUFFIX)(Reg *d, Reg *s) #endif } -void glue(helper_pslld, SUFFIX)(Reg *d, Reg *s) +void glue(helper_pslld, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int shift; @@ -161,7 +161,7 @@ void glue(helper_pslld, SUFFIX)(Reg *d, Reg *s) } } -void glue(helper_psrlq, SUFFIX)(Reg *d, Reg *s) +void glue(helper_psrlq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int shift; @@ -179,7 +179,7 @@ void glue(helper_psrlq, SUFFIX)(Reg *d, Reg *s) } } -void glue(helper_psllq, SUFFIX)(Reg *d, Reg *s) +void glue(helper_psllq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int shift; @@ -198,7 +198,7 @@ void glue(helper_psllq, SUFFIX)(Reg *d, Reg *s) } #if SHIFT == 1 -void glue(helper_psrldq, SUFFIX)(Reg *d, Reg *s) +void glue(helper_psrldq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int shift, i; @@ -214,7 +214,7 @@ void glue(helper_psrldq, SUFFIX)(Reg *d, Reg *s) } } -void glue(helper_pslldq, SUFFIX)(Reg *d, Reg *s) +void glue(helper_pslldq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int shift, i; @@ -232,7 +232,7 @@ void glue(helper_pslldq, SUFFIX)(Reg *d, Reg *s) #endif #define SSE_HELPER_B(name, F) \ - void glue(name, SUFFIX)(Reg *d, Reg *s) \ + void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ { \ d->B(0) = F(d->B(0), s->B(0)); \ d->B(1) = F(d->B(1), s->B(1)); \ @@ -255,7 +255,7 @@ void glue(helper_pslldq, SUFFIX)(Reg *d, Reg *s) } #define SSE_HELPER_W(name, F) \ - void glue(name, SUFFIX)(Reg *d, Reg *s) \ + void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ { \ d->W(0) = F(d->W(0), s->W(0)); \ d->W(1) = F(d->W(1), s->W(1)); \ @@ -270,7 +270,7 @@ void glue(helper_pslldq, SUFFIX)(Reg *d, Reg *s) } #define SSE_HELPER_L(name, F) \ - void glue(name, SUFFIX)(Reg *d, Reg *s) \ + void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ { \ d->L(0) = F(d->L(0), s->L(0)); \ d->L(1) = F(d->L(1), s->L(1)); \ @@ -281,7 +281,7 @@ void glue(helper_pslldq, SUFFIX)(Reg *d, Reg *s) } #define SSE_HELPER_Q(name, F) \ - void glue(name, SUFFIX)(Reg *d, Reg *s) \ + void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ { \ d->Q(0) = F(d->Q(0), s->Q(0)); \ XMM_ONLY( \ @@ -417,7 +417,7 @@ SSE_HELPER_W(helper_pmulhw, FMULHW) SSE_HELPER_B(helper_pavgb, FAVG) SSE_HELPER_W(helper_pavgw, FAVG) -void glue(helper_pmuludq, SUFFIX)(Reg *d, Reg *s) +void glue(helper_pmuludq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { d->Q(0) = (uint64_t)s->L(0) * (uint64_t)d->L(0); #if SHIFT == 1 @@ -425,7 +425,7 @@ void glue(helper_pmuludq, SUFFIX)(Reg *d, Reg *s) #endif } -void glue(helper_pmaddwd, SUFFIX)(Reg *d, Reg *s) +void glue(helper_pmaddwd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int i; @@ -445,7 +445,7 @@ static inline int abs1(int a) } } #endif -void glue(helper_psadbw, SUFFIX)(Reg *d, Reg *s) +void glue(helper_psadbw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { unsigned int val; @@ -473,13 +473,14 @@ void glue(helper_psadbw, SUFFIX)(Reg *d, Reg *s) #endif } -void glue(helper_maskmov, SUFFIX)(Reg *d, Reg *s, target_ulong a0) +void glue(helper_maskmov, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + target_ulong a0) { int i; for (i = 0; i < (8 << SHIFT); i++) { if (s->B(i) & 0x80) { - stb(a0 + i, d->B(i)); + cpu_stb_data(env, a0 + i, d->B(i)); } } } @@ -575,29 +576,29 @@ void glue(helper_pshufhw, SUFFIX)(Reg *d, Reg *s, int order) /* FPU ops */ /* XXX: not accurate */ -#define SSE_HELPER_S(name, F) \ - void helper_ ## name ## ps(Reg *d, Reg *s) \ - { \ - d->XMM_S(0) = F(32, d->XMM_S(0), s->XMM_S(0)); \ - d->XMM_S(1) = F(32, d->XMM_S(1), s->XMM_S(1)); \ - d->XMM_S(2) = F(32, d->XMM_S(2), s->XMM_S(2)); \ - d->XMM_S(3) = F(32, d->XMM_S(3), s->XMM_S(3)); \ - } \ - \ - void helper_ ## name ## ss(Reg *d, Reg *s) \ - { \ - d->XMM_S(0) = F(32, d->XMM_S(0), s->XMM_S(0)); \ - } \ - \ - void helper_ ## name ## pd(Reg *d, Reg *s) \ - { \ - d->XMM_D(0) = F(64, d->XMM_D(0), s->XMM_D(0)); \ - d->XMM_D(1) = F(64, d->XMM_D(1), s->XMM_D(1)); \ - } \ - \ - void helper_ ## name ## sd(Reg *d, Reg *s) \ - { \ - d->XMM_D(0) = F(64, d->XMM_D(0), s->XMM_D(0)); \ +#define SSE_HELPER_S(name, F) \ + void helper_ ## name ## ps(CPUX86State *env, Reg *d, Reg *s) \ + { \ + d->XMM_S(0) = F(32, d->XMM_S(0), s->XMM_S(0)); \ + d->XMM_S(1) = F(32, d->XMM_S(1), s->XMM_S(1)); \ + d->XMM_S(2) = F(32, d->XMM_S(2), s->XMM_S(2)); \ + d->XMM_S(3) = F(32, d->XMM_S(3), s->XMM_S(3)); \ + } \ + \ + void helper_ ## name ## ss(CPUX86State *env, Reg *d, Reg *s) \ + { \ + d->XMM_S(0) = F(32, d->XMM_S(0), s->XMM_S(0)); \ + } \ + \ + void helper_ ## name ## pd(CPUX86State *env, Reg *d, Reg *s) \ + { \ + d->XMM_D(0) = F(64, d->XMM_D(0), s->XMM_D(0)); \ + d->XMM_D(1) = F(64, d->XMM_D(1), s->XMM_D(1)); \ + } \ + \ + void helper_ ## name ## sd(CPUX86State *env, Reg *d, Reg *s) \ + { \ + d->XMM_D(0) = F(64, d->XMM_D(0), s->XMM_D(0)); \ } #define FPU_ADD(size, a, b) float ## size ## _add(a, b, &env->sse_status) @@ -625,7 +626,7 @@ SSE_HELPER_S(sqrt, FPU_SQRT) /* float to float conversions */ -void helper_cvtps2pd(Reg *d, Reg *s) +void helper_cvtps2pd(CPUX86State *env, Reg *d, Reg *s) { float32 s0, s1; @@ -635,25 +636,25 @@ void helper_cvtps2pd(Reg *d, Reg *s) d->XMM_D(1) = float32_to_float64(s1, &env->sse_status); } -void helper_cvtpd2ps(Reg *d, Reg *s) +void helper_cvtpd2ps(CPUX86State *env, Reg *d, Reg *s) { d->XMM_S(0) = float64_to_float32(s->XMM_D(0), &env->sse_status); d->XMM_S(1) = float64_to_float32(s->XMM_D(1), &env->sse_status); d->Q(1) = 0; } -void helper_cvtss2sd(Reg *d, Reg *s) +void helper_cvtss2sd(CPUX86State *env, Reg *d, Reg *s) { d->XMM_D(0) = float32_to_float64(s->XMM_S(0), &env->sse_status); } -void helper_cvtsd2ss(Reg *d, Reg *s) +void helper_cvtsd2ss(CPUX86State *env, Reg *d, Reg *s) { d->XMM_S(0) = float64_to_float32(s->XMM_D(0), &env->sse_status); } /* integer to float */ -void helper_cvtdq2ps(Reg *d, Reg *s) +void helper_cvtdq2ps(CPUX86State *env, Reg *d, Reg *s) { d->XMM_S(0) = int32_to_float32(s->XMM_L(0), &env->sse_status); d->XMM_S(1) = int32_to_float32(s->XMM_L(1), &env->sse_status); @@ -661,7 +662,7 @@ void helper_cvtdq2ps(Reg *d, Reg *s) d->XMM_S(3) = int32_to_float32(s->XMM_L(3), &env->sse_status); } -void helper_cvtdq2pd(Reg *d, Reg *s) +void helper_cvtdq2pd(CPUX86State *env, Reg *d, Reg *s) { int32_t l0, l1; @@ -671,42 +672,42 @@ void helper_cvtdq2pd(Reg *d, Reg *s) d->XMM_D(1) = int32_to_float64(l1, &env->sse_status); } -void helper_cvtpi2ps(XMMReg *d, MMXReg *s) +void helper_cvtpi2ps(CPUX86State *env, XMMReg *d, MMXReg *s) { d->XMM_S(0) = int32_to_float32(s->MMX_L(0), &env->sse_status); d->XMM_S(1) = int32_to_float32(s->MMX_L(1), &env->sse_status); } -void helper_cvtpi2pd(XMMReg *d, MMXReg *s) +void helper_cvtpi2pd(CPUX86State *env, XMMReg *d, MMXReg *s) { d->XMM_D(0) = int32_to_float64(s->MMX_L(0), &env->sse_status); d->XMM_D(1) = int32_to_float64(s->MMX_L(1), &env->sse_status); } -void helper_cvtsi2ss(XMMReg *d, uint32_t val) +void helper_cvtsi2ss(CPUX86State *env, XMMReg *d, uint32_t val) { d->XMM_S(0) = int32_to_float32(val, &env->sse_status); } -void helper_cvtsi2sd(XMMReg *d, uint32_t val) +void helper_cvtsi2sd(CPUX86State *env, XMMReg *d, uint32_t val) { d->XMM_D(0) = int32_to_float64(val, &env->sse_status); } #ifdef TARGET_X86_64 -void helper_cvtsq2ss(XMMReg *d, uint64_t val) +void helper_cvtsq2ss(CPUX86State *env, XMMReg *d, uint64_t val) { d->XMM_S(0) = int64_to_float32(val, &env->sse_status); } -void helper_cvtsq2sd(XMMReg *d, uint64_t val) +void helper_cvtsq2sd(CPUX86State *env, XMMReg *d, uint64_t val) { d->XMM_D(0) = int64_to_float64(val, &env->sse_status); } #endif /* float to integer */ -void helper_cvtps2dq(XMMReg *d, XMMReg *s) +void helper_cvtps2dq(CPUX86State *env, XMMReg *d, XMMReg *s) { d->XMM_L(0) = float32_to_int32(s->XMM_S(0), &env->sse_status); d->XMM_L(1) = float32_to_int32(s->XMM_S(1), &env->sse_status); @@ -714,49 +715,49 @@ void helper_cvtps2dq(XMMReg *d, XMMReg *s) d->XMM_L(3) = float32_to_int32(s->XMM_S(3), &env->sse_status); } -void helper_cvtpd2dq(XMMReg *d, XMMReg *s) +void helper_cvtpd2dq(CPUX86State *env, XMMReg *d, XMMReg *s) { d->XMM_L(0) = float64_to_int32(s->XMM_D(0), &env->sse_status); d->XMM_L(1) = float64_to_int32(s->XMM_D(1), &env->sse_status); d->XMM_Q(1) = 0; } -void helper_cvtps2pi(MMXReg *d, XMMReg *s) +void helper_cvtps2pi(CPUX86State *env, MMXReg *d, XMMReg *s) { d->MMX_L(0) = float32_to_int32(s->XMM_S(0), &env->sse_status); d->MMX_L(1) = float32_to_int32(s->XMM_S(1), &env->sse_status); } -void helper_cvtpd2pi(MMXReg *d, XMMReg *s) +void helper_cvtpd2pi(CPUX86State *env, MMXReg *d, XMMReg *s) { d->MMX_L(0) = float64_to_int32(s->XMM_D(0), &env->sse_status); d->MMX_L(1) = float64_to_int32(s->XMM_D(1), &env->sse_status); } -int32_t helper_cvtss2si(XMMReg *s) +int32_t helper_cvtss2si(CPUX86State *env, XMMReg *s) { return float32_to_int32(s->XMM_S(0), &env->sse_status); } -int32_t helper_cvtsd2si(XMMReg *s) +int32_t helper_cvtsd2si(CPUX86State *env, XMMReg *s) { return float64_to_int32(s->XMM_D(0), &env->sse_status); } #ifdef TARGET_X86_64 -int64_t helper_cvtss2sq(XMMReg *s) +int64_t helper_cvtss2sq(CPUX86State *env, XMMReg *s) { return float32_to_int64(s->XMM_S(0), &env->sse_status); } -int64_t helper_cvtsd2sq(XMMReg *s) +int64_t helper_cvtsd2sq(CPUX86State *env, XMMReg *s) { return float64_to_int64(s->XMM_D(0), &env->sse_status); } #endif /* float to integer truncated */ -void helper_cvttps2dq(XMMReg *d, XMMReg *s) +void helper_cvttps2dq(CPUX86State *env, XMMReg *d, XMMReg *s) { d->XMM_L(0) = float32_to_int32_round_to_zero(s->XMM_S(0), &env->sse_status); d->XMM_L(1) = float32_to_int32_round_to_zero(s->XMM_S(1), &env->sse_status); @@ -764,48 +765,48 @@ void helper_cvttps2dq(XMMReg *d, XMMReg *s) d->XMM_L(3) = float32_to_int32_round_to_zero(s->XMM_S(3), &env->sse_status); } -void helper_cvttpd2dq(XMMReg *d, XMMReg *s) +void helper_cvttpd2dq(CPUX86State *env, XMMReg *d, XMMReg *s) { d->XMM_L(0) = float64_to_int32_round_to_zero(s->XMM_D(0), &env->sse_status); d->XMM_L(1) = float64_to_int32_round_to_zero(s->XMM_D(1), &env->sse_status); d->XMM_Q(1) = 0; } -void helper_cvttps2pi(MMXReg *d, XMMReg *s) +void helper_cvttps2pi(CPUX86State *env, MMXReg *d, XMMReg *s) { d->MMX_L(0) = float32_to_int32_round_to_zero(s->XMM_S(0), &env->sse_status); d->MMX_L(1) = float32_to_int32_round_to_zero(s->XMM_S(1), &env->sse_status); } -void helper_cvttpd2pi(MMXReg *d, XMMReg *s) +void helper_cvttpd2pi(CPUX86State *env, MMXReg *d, XMMReg *s) { d->MMX_L(0) = float64_to_int32_round_to_zero(s->XMM_D(0), &env->sse_status); d->MMX_L(1) = float64_to_int32_round_to_zero(s->XMM_D(1), &env->sse_status); } -int32_t helper_cvttss2si(XMMReg *s) +int32_t helper_cvttss2si(CPUX86State *env, XMMReg *s) { return float32_to_int32_round_to_zero(s->XMM_S(0), &env->sse_status); } -int32_t helper_cvttsd2si(XMMReg *s) +int32_t helper_cvttsd2si(CPUX86State *env, XMMReg *s) { return float64_to_int32_round_to_zero(s->XMM_D(0), &env->sse_status); } #ifdef TARGET_X86_64 -int64_t helper_cvttss2sq(XMMReg *s) +int64_t helper_cvttss2sq(CPUX86State *env, XMMReg *s) { return float32_to_int64_round_to_zero(s->XMM_S(0), &env->sse_status); } -int64_t helper_cvttsd2sq(XMMReg *s) +int64_t helper_cvttsd2sq(CPUX86State *env, XMMReg *s) { return float64_to_int64_round_to_zero(s->XMM_D(0), &env->sse_status); } #endif -void helper_rsqrtps(XMMReg *d, XMMReg *s) +void helper_rsqrtps(CPUX86State *env, XMMReg *d, XMMReg *s) { d->XMM_S(0) = float32_div(float32_one, float32_sqrt(s->XMM_S(0), &env->sse_status), @@ -821,14 +822,14 @@ void helper_rsqrtps(XMMReg *d, XMMReg *s) &env->sse_status); } -void helper_rsqrtss(XMMReg *d, XMMReg *s) +void helper_rsqrtss(CPUX86State *env, XMMReg *d, XMMReg *s) { d->XMM_S(0) = float32_div(float32_one, float32_sqrt(s->XMM_S(0), &env->sse_status), &env->sse_status); } -void helper_rcpps(XMMReg *d, XMMReg *s) +void helper_rcpps(CPUX86State *env, XMMReg *d, XMMReg *s) { d->XMM_S(0) = float32_div(float32_one, s->XMM_S(0), &env->sse_status); d->XMM_S(1) = float32_div(float32_one, s->XMM_S(1), &env->sse_status); @@ -836,7 +837,7 @@ void helper_rcpps(XMMReg *d, XMMReg *s) d->XMM_S(3) = float32_div(float32_one, s->XMM_S(3), &env->sse_status); } -void helper_rcpss(XMMReg *d, XMMReg *s) +void helper_rcpss(CPUX86State *env, XMMReg *d, XMMReg *s) { d->XMM_S(0) = float32_div(float32_one, s->XMM_S(0), &env->sse_status); } @@ -853,12 +854,12 @@ static inline uint64_t helper_extrq(uint64_t src, int shift, int len) return (src >> shift) & mask; } -void helper_extrq_r(XMMReg *d, XMMReg *s) +void helper_extrq_r(CPUX86State *env, XMMReg *d, XMMReg *s) { d->XMM_Q(0) = helper_extrq(d->XMM_Q(0), s->XMM_B(1), s->XMM_B(0)); } -void helper_extrq_i(XMMReg *d, int index, int length) +void helper_extrq_i(CPUX86State *env, XMMReg *d, int index, int length) { d->XMM_Q(0) = helper_extrq(d->XMM_Q(0), index, length); } @@ -875,17 +876,17 @@ static inline uint64_t helper_insertq(uint64_t src, int shift, int len) return (src & ~(mask << shift)) | ((src & mask) << shift); } -void helper_insertq_r(XMMReg *d, XMMReg *s) +void helper_insertq_r(CPUX86State *env, XMMReg *d, XMMReg *s) { d->XMM_Q(0) = helper_insertq(s->XMM_Q(0), s->XMM_B(9), s->XMM_B(8)); } -void helper_insertq_i(XMMReg *d, int index, int length) +void helper_insertq_i(CPUX86State *env, XMMReg *d, int index, int length) { d->XMM_Q(0) = helper_insertq(d->XMM_Q(0), index, length); } -void helper_haddps(XMMReg *d, XMMReg *s) +void helper_haddps(CPUX86State *env, XMMReg *d, XMMReg *s) { XMMReg r; @@ -896,7 +897,7 @@ void helper_haddps(XMMReg *d, XMMReg *s) *d = r; } -void helper_haddpd(XMMReg *d, XMMReg *s) +void helper_haddpd(CPUX86State *env, XMMReg *d, XMMReg *s) { XMMReg r; @@ -905,7 +906,7 @@ void helper_haddpd(XMMReg *d, XMMReg *s) *d = r; } -void helper_hsubps(XMMReg *d, XMMReg *s) +void helper_hsubps(CPUX86State *env, XMMReg *d, XMMReg *s) { XMMReg r; @@ -916,7 +917,7 @@ void helper_hsubps(XMMReg *d, XMMReg *s) *d = r; } -void helper_hsubpd(XMMReg *d, XMMReg *s) +void helper_hsubpd(CPUX86State *env, XMMReg *d, XMMReg *s) { XMMReg r; @@ -925,7 +926,7 @@ void helper_hsubpd(XMMReg *d, XMMReg *s) *d = r; } -void helper_addsubps(XMMReg *d, XMMReg *s) +void helper_addsubps(CPUX86State *env, XMMReg *d, XMMReg *s) { d->XMM_S(0) = float32_sub(d->XMM_S(0), s->XMM_S(0), &env->sse_status); d->XMM_S(1) = float32_add(d->XMM_S(1), s->XMM_S(1), &env->sse_status); @@ -933,36 +934,36 @@ void helper_addsubps(XMMReg *d, XMMReg *s) d->XMM_S(3) = float32_add(d->XMM_S(3), s->XMM_S(3), &env->sse_status); } -void helper_addsubpd(XMMReg *d, XMMReg *s) +void helper_addsubpd(CPUX86State *env, XMMReg *d, XMMReg *s) { d->XMM_D(0) = float64_sub(d->XMM_D(0), s->XMM_D(0), &env->sse_status); d->XMM_D(1) = float64_add(d->XMM_D(1), s->XMM_D(1), &env->sse_status); } /* XXX: unordered */ -#define SSE_HELPER_CMP(name, F) \ - void helper_ ## name ## ps(Reg *d, Reg *s) \ - { \ - d->XMM_L(0) = F(32, d->XMM_S(0), s->XMM_S(0)); \ - d->XMM_L(1) = F(32, d->XMM_S(1), s->XMM_S(1)); \ - d->XMM_L(2) = F(32, d->XMM_S(2), s->XMM_S(2)); \ - d->XMM_L(3) = F(32, d->XMM_S(3), s->XMM_S(3)); \ - } \ - \ - void helper_ ## name ## ss(Reg *d, Reg *s) \ - { \ - d->XMM_L(0) = F(32, d->XMM_S(0), s->XMM_S(0)); \ - } \ - \ - void helper_ ## name ## pd(Reg *d, Reg *s) \ - { \ - d->XMM_Q(0) = F(64, d->XMM_D(0), s->XMM_D(0)); \ - d->XMM_Q(1) = F(64, d->XMM_D(1), s->XMM_D(1)); \ - } \ - \ - void helper_ ## name ## sd(Reg *d, Reg *s) \ - { \ - d->XMM_Q(0) = F(64, d->XMM_D(0), s->XMM_D(0)); \ +#define SSE_HELPER_CMP(name, F) \ + void helper_ ## name ## ps(CPUX86State *env, Reg *d, Reg *s) \ + { \ + d->XMM_L(0) = F(32, d->XMM_S(0), s->XMM_S(0)); \ + d->XMM_L(1) = F(32, d->XMM_S(1), s->XMM_S(1)); \ + d->XMM_L(2) = F(32, d->XMM_S(2), s->XMM_S(2)); \ + d->XMM_L(3) = F(32, d->XMM_S(3), s->XMM_S(3)); \ + } \ + \ + void helper_ ## name ## ss(CPUX86State *env, Reg *d, Reg *s) \ + { \ + d->XMM_L(0) = F(32, d->XMM_S(0), s->XMM_S(0)); \ + } \ + \ + void helper_ ## name ## pd(CPUX86State *env, Reg *d, Reg *s) \ + { \ + d->XMM_Q(0) = F(64, d->XMM_D(0), s->XMM_D(0)); \ + d->XMM_Q(1) = F(64, d->XMM_D(1), s->XMM_D(1)); \ + } \ + \ + void helper_ ## name ## sd(CPUX86State *env, Reg *d, Reg *s) \ + { \ + d->XMM_Q(0) = F(64, d->XMM_D(0), s->XMM_D(0)); \ } #define FPU_CMPEQ(size, a, b) \ @@ -993,7 +994,7 @@ SSE_HELPER_CMP(cmpord, FPU_CMPORD) static const int comis_eflags[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C}; -void helper_ucomiss(Reg *d, Reg *s) +void helper_ucomiss(CPUX86State *env, Reg *d, Reg *s) { int ret; float32 s0, s1; @@ -1004,7 +1005,7 @@ void helper_ucomiss(Reg *d, Reg *s) CC_SRC = comis_eflags[ret + 1]; } -void helper_comiss(Reg *d, Reg *s) +void helper_comiss(CPUX86State *env, Reg *d, Reg *s) { int ret; float32 s0, s1; @@ -1015,7 +1016,7 @@ void helper_comiss(Reg *d, Reg *s) CC_SRC = comis_eflags[ret + 1]; } -void helper_ucomisd(Reg *d, Reg *s) +void helper_ucomisd(CPUX86State *env, Reg *d, Reg *s) { int ret; float64 d0, d1; @@ -1026,7 +1027,7 @@ void helper_ucomisd(Reg *d, Reg *s) CC_SRC = comis_eflags[ret + 1]; } -void helper_comisd(Reg *d, Reg *s) +void helper_comisd(CPUX86State *env, Reg *d, Reg *s) { int ret; float64 d0, d1; @@ -1037,7 +1038,7 @@ void helper_comisd(Reg *d, Reg *s) CC_SRC = comis_eflags[ret + 1]; } -uint32_t helper_movmskps(Reg *s) +uint32_t helper_movmskps(CPUX86State *env, Reg *s) { int b0, b1, b2, b3; @@ -1048,7 +1049,7 @@ uint32_t helper_movmskps(Reg *s) return b0 | (b1 << 1) | (b2 << 2) | (b3 << 3); } -uint32_t helper_movmskpd(Reg *s) +uint32_t helper_movmskpd(CPUX86State *env, Reg *s) { int b0, b1; @@ -1059,7 +1060,7 @@ uint32_t helper_movmskpd(Reg *s) #endif -uint32_t glue(helper_pmovmskb, SUFFIX)(Reg *s) +uint32_t glue(helper_pmovmskb, SUFFIX)(CPUX86State *env, Reg *s) { uint32_t val; @@ -1085,7 +1086,7 @@ uint32_t glue(helper_pmovmskb, SUFFIX)(Reg *s) return val; } -void glue(helper_packsswb, SUFFIX)(Reg *d, Reg *s) +void glue(helper_packsswb, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { Reg r; @@ -1112,7 +1113,7 @@ void glue(helper_packsswb, SUFFIX)(Reg *d, Reg *s) *d = r; } -void glue(helper_packuswb, SUFFIX)(Reg *d, Reg *s) +void glue(helper_packuswb, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { Reg r; @@ -1139,7 +1140,7 @@ void glue(helper_packuswb, SUFFIX)(Reg *d, Reg *s) *d = r; } -void glue(helper_packssdw, SUFFIX)(Reg *d, Reg *s) +void glue(helper_packssdw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { Reg r; @@ -1160,7 +1161,8 @@ void glue(helper_packssdw, SUFFIX)(Reg *d, Reg *s) #define UNPCK_OP(base_name, base) \ \ - void glue(helper_punpck ## base_name ## bw, SUFFIX)(Reg *d, Reg *s) \ + void glue(helper_punpck ## base_name ## bw, SUFFIX)(CPUX86State *env,\ + Reg *d, Reg *s) \ { \ Reg r; \ \ @@ -1181,11 +1183,12 @@ void glue(helper_packssdw, SUFFIX)(Reg *d, Reg *s) r.B(13) = s->B((base << (SHIFT + 2)) + 6); \ r.B(14) = d->B((base << (SHIFT + 2)) + 7); \ r.B(15) = s->B((base << (SHIFT + 2)) + 7); \ - ) \ + ) \ *d = r; \ } \ \ - void glue(helper_punpck ## base_name ## wd, SUFFIX)(Reg *d, Reg *s) \ + void glue(helper_punpck ## base_name ## wd, SUFFIX)(CPUX86State *env,\ + Reg *d, Reg *s) \ { \ Reg r; \ \ @@ -1198,11 +1201,12 @@ void glue(helper_packssdw, SUFFIX)(Reg *d, Reg *s) r.W(5) = s->W((base << (SHIFT + 1)) + 2); \ r.W(6) = d->W((base << (SHIFT + 1)) + 3); \ r.W(7) = s->W((base << (SHIFT + 1)) + 3); \ - ) \ + ) \ *d = r; \ } \ \ - void glue(helper_punpck ## base_name ## dq, SUFFIX)(Reg *d, Reg *s) \ + void glue(helper_punpck ## base_name ## dq, SUFFIX)(CPUX86State *env,\ + Reg *d, Reg *s) \ { \ Reg r; \ \ @@ -1211,12 +1215,14 @@ void glue(helper_packssdw, SUFFIX)(Reg *d, Reg *s) XMM_ONLY( \ r.L(2) = d->L((base << SHIFT) + 1); \ r.L(3) = s->L((base << SHIFT) + 1); \ - ) \ + ) \ *d = r; \ } \ \ XMM_ONLY( \ - void glue(helper_punpck ## base_name ## qdq, SUFFIX)(Reg *d, \ + void glue(helper_punpck ## base_name ## qdq, SUFFIX)(CPUX86State \ + *env, \ + Reg *d, \ Reg *s) \ { \ Reg r; \ @@ -1232,25 +1238,25 @@ UNPCK_OP(h, 1) /* 3DNow! float ops */ #if SHIFT == 0 -void helper_pi2fd(MMXReg *d, MMXReg *s) +void helper_pi2fd(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_S(0) = int32_to_float32(s->MMX_L(0), &env->mmx_status); d->MMX_S(1) = int32_to_float32(s->MMX_L(1), &env->mmx_status); } -void helper_pi2fw(MMXReg *d, MMXReg *s) +void helper_pi2fw(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_S(0) = int32_to_float32((int16_t)s->MMX_W(0), &env->mmx_status); d->MMX_S(1) = int32_to_float32((int16_t)s->MMX_W(2), &env->mmx_status); } -void helper_pf2id(MMXReg *d, MMXReg *s) +void helper_pf2id(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_L(0) = float32_to_int32_round_to_zero(s->MMX_S(0), &env->mmx_status); d->MMX_L(1) = float32_to_int32_round_to_zero(s->MMX_S(1), &env->mmx_status); } -void helper_pf2iw(MMXReg *d, MMXReg *s) +void helper_pf2iw(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_L(0) = satsw(float32_to_int32_round_to_zero(s->MMX_S(0), &env->mmx_status)); @@ -1258,7 +1264,7 @@ void helper_pf2iw(MMXReg *d, MMXReg *s) &env->mmx_status)); } -void helper_pfacc(MMXReg *d, MMXReg *s) +void helper_pfacc(CPUX86State *env, MMXReg *d, MMXReg *s) { MMXReg r; @@ -1267,13 +1273,13 @@ void helper_pfacc(MMXReg *d, MMXReg *s) *d = r; } -void helper_pfadd(MMXReg *d, MMXReg *s) +void helper_pfadd(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_S(0) = float32_add(d->MMX_S(0), s->MMX_S(0), &env->mmx_status); d->MMX_S(1) = float32_add(d->MMX_S(1), s->MMX_S(1), &env->mmx_status); } -void helper_pfcmpeq(MMXReg *d, MMXReg *s) +void helper_pfcmpeq(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_L(0) = float32_eq_quiet(d->MMX_S(0), s->MMX_S(0), &env->mmx_status) ? -1 : 0; @@ -1281,7 +1287,7 @@ void helper_pfcmpeq(MMXReg *d, MMXReg *s) &env->mmx_status) ? -1 : 0; } -void helper_pfcmpge(MMXReg *d, MMXReg *s) +void helper_pfcmpge(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_L(0) = float32_le(s->MMX_S(0), d->MMX_S(0), &env->mmx_status) ? -1 : 0; @@ -1289,7 +1295,7 @@ void helper_pfcmpge(MMXReg *d, MMXReg *s) &env->mmx_status) ? -1 : 0; } -void helper_pfcmpgt(MMXReg *d, MMXReg *s) +void helper_pfcmpgt(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_L(0) = float32_lt(s->MMX_S(0), d->MMX_S(0), &env->mmx_status) ? -1 : 0; @@ -1297,7 +1303,7 @@ void helper_pfcmpgt(MMXReg *d, MMXReg *s) &env->mmx_status) ? -1 : 0; } -void helper_pfmax(MMXReg *d, MMXReg *s) +void helper_pfmax(CPUX86State *env, MMXReg *d, MMXReg *s) { if (float32_lt(d->MMX_S(0), s->MMX_S(0), &env->mmx_status)) { d->MMX_S(0) = s->MMX_S(0); @@ -1307,7 +1313,7 @@ void helper_pfmax(MMXReg *d, MMXReg *s) } } -void helper_pfmin(MMXReg *d, MMXReg *s) +void helper_pfmin(CPUX86State *env, MMXReg *d, MMXReg *s) { if (float32_lt(s->MMX_S(0), d->MMX_S(0), &env->mmx_status)) { d->MMX_S(0) = s->MMX_S(0); @@ -1317,13 +1323,13 @@ void helper_pfmin(MMXReg *d, MMXReg *s) } } -void helper_pfmul(MMXReg *d, MMXReg *s) +void helper_pfmul(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_S(0) = float32_mul(d->MMX_S(0), s->MMX_S(0), &env->mmx_status); d->MMX_S(1) = float32_mul(d->MMX_S(1), s->MMX_S(1), &env->mmx_status); } -void helper_pfnacc(MMXReg *d, MMXReg *s) +void helper_pfnacc(CPUX86State *env, MMXReg *d, MMXReg *s) { MMXReg r; @@ -1332,7 +1338,7 @@ void helper_pfnacc(MMXReg *d, MMXReg *s) *d = r; } -void helper_pfpnacc(MMXReg *d, MMXReg *s) +void helper_pfpnacc(CPUX86State *env, MMXReg *d, MMXReg *s) { MMXReg r; @@ -1341,13 +1347,13 @@ void helper_pfpnacc(MMXReg *d, MMXReg *s) *d = r; } -void helper_pfrcp(MMXReg *d, MMXReg *s) +void helper_pfrcp(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_S(0) = float32_div(float32_one, s->MMX_S(0), &env->mmx_status); d->MMX_S(1) = d->MMX_S(0); } -void helper_pfrsqrt(MMXReg *d, MMXReg *s) +void helper_pfrsqrt(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_L(1) = s->MMX_L(0) & 0x7fffffff; d->MMX_S(1) = float32_div(float32_one, @@ -1357,19 +1363,19 @@ void helper_pfrsqrt(MMXReg *d, MMXReg *s) d->MMX_L(0) = d->MMX_L(1); } -void helper_pfsub(MMXReg *d, MMXReg *s) +void helper_pfsub(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_S(0) = float32_sub(d->MMX_S(0), s->MMX_S(0), &env->mmx_status); d->MMX_S(1) = float32_sub(d->MMX_S(1), s->MMX_S(1), &env->mmx_status); } -void helper_pfsubr(MMXReg *d, MMXReg *s) +void helper_pfsubr(CPUX86State *env, MMXReg *d, MMXReg *s) { d->MMX_S(0) = float32_sub(s->MMX_S(0), d->MMX_S(0), &env->mmx_status); d->MMX_S(1) = float32_sub(s->MMX_S(1), d->MMX_S(1), &env->mmx_status); } -void helper_pswapd(MMXReg *d, MMXReg *s) +void helper_pswapd(CPUX86State *env, MMXReg *d, MMXReg *s) { MMXReg r; @@ -1380,7 +1386,7 @@ void helper_pswapd(MMXReg *d, MMXReg *s) #endif /* SSSE3 op helpers */ -void glue(helper_pshufb, SUFFIX)(Reg *d, Reg *s) +void glue(helper_pshufb, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int i; Reg r; @@ -1392,7 +1398,7 @@ void glue(helper_pshufb, SUFFIX)(Reg *d, Reg *s) *d = r; } -void glue(helper_phaddw, SUFFIX)(Reg *d, Reg *s) +void glue(helper_phaddw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { d->W(0) = (int16_t)d->W(0) + (int16_t)d->W(1); d->W(1) = (int16_t)d->W(2) + (int16_t)d->W(3); @@ -1404,7 +1410,7 @@ void glue(helper_phaddw, SUFFIX)(Reg *d, Reg *s) XMM_ONLY(d->W(7) = (int16_t)s->W(6) + (int16_t)s->W(7)); } -void glue(helper_phaddd, SUFFIX)(Reg *d, Reg *s) +void glue(helper_phaddd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { d->L(0) = (int32_t)d->L(0) + (int32_t)d->L(1); XMM_ONLY(d->L(1) = (int32_t)d->L(2) + (int32_t)d->L(3)); @@ -1412,7 +1418,7 @@ void glue(helper_phaddd, SUFFIX)(Reg *d, Reg *s) XMM_ONLY(d->L(3) = (int32_t)s->L(2) + (int32_t)s->L(3)); } -void glue(helper_phaddsw, SUFFIX)(Reg *d, Reg *s) +void glue(helper_phaddsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { d->W(0) = satsw((int16_t)d->W(0) + (int16_t)d->W(1)); d->W(1) = satsw((int16_t)d->W(2) + (int16_t)d->W(3)); @@ -1424,7 +1430,7 @@ void glue(helper_phaddsw, SUFFIX)(Reg *d, Reg *s) XMM_ONLY(d->W(7) = satsw((int16_t)s->W(6) + (int16_t)s->W(7))); } -void glue(helper_pmaddubsw, SUFFIX)(Reg *d, Reg *s) +void glue(helper_pmaddubsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { d->W(0) = satsw((int8_t)s->B(0) * (uint8_t)d->B(0) + (int8_t)s->B(1) * (uint8_t)d->B(1)); @@ -1446,7 +1452,7 @@ void glue(helper_pmaddubsw, SUFFIX)(Reg *d, Reg *s) #endif } -void glue(helper_phsubw, SUFFIX)(Reg *d, Reg *s) +void glue(helper_phsubw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { d->W(0) = (int16_t)d->W(0) - (int16_t)d->W(1); d->W(1) = (int16_t)d->W(2) - (int16_t)d->W(3); @@ -1458,7 +1464,7 @@ void glue(helper_phsubw, SUFFIX)(Reg *d, Reg *s) XMM_ONLY(d->W(7) = (int16_t)s->W(6) - (int16_t)s->W(7)); } -void glue(helper_phsubd, SUFFIX)(Reg *d, Reg *s) +void glue(helper_phsubd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { d->L(0) = (int32_t)d->L(0) - (int32_t)d->L(1); XMM_ONLY(d->L(1) = (int32_t)d->L(2) - (int32_t)d->L(3)); @@ -1466,7 +1472,7 @@ void glue(helper_phsubd, SUFFIX)(Reg *d, Reg *s) XMM_ONLY(d->L(3) = (int32_t)s->L(2) - (int32_t)s->L(3)); } -void glue(helper_phsubsw, SUFFIX)(Reg *d, Reg *s) +void glue(helper_phsubsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { d->W(0) = satsw((int16_t)d->W(0) - (int16_t)d->W(1)); d->W(1) = satsw((int16_t)d->W(2) - (int16_t)d->W(3)); @@ -1495,7 +1501,8 @@ SSE_HELPER_B(helper_psignb, FSIGNB) SSE_HELPER_W(helper_psignw, FSIGNW) SSE_HELPER_L(helper_psignd, FSIGNL) -void glue(helper_palignr, SUFFIX)(Reg *d, Reg *s, int32_t shift) +void glue(helper_palignr, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + int32_t shift) { Reg r; @@ -1529,7 +1536,7 @@ void glue(helper_palignr, SUFFIX)(Reg *d, Reg *s, int32_t shift) #if SHIFT == 1 #define SSE_HELPER_V(name, elem, num, F) \ - void glue(name, SUFFIX)(Reg *d, Reg *s) \ + void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ { \ d->elem(0) = F(d->elem(0), s->elem(0), XMM0.elem(0)); \ d->elem(1) = F(d->elem(1), s->elem(1), XMM0.elem(1)); \ @@ -1556,7 +1563,7 @@ void glue(helper_palignr, SUFFIX)(Reg *d, Reg *s, int32_t shift) } #define SSE_HELPER_I(name, elem, num, F) \ - void glue(name, SUFFIX)(Reg *d, Reg *s, uint32_t imm) \ + void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t imm) \ { \ d->elem(0) = F(d->elem(0), s->elem(0), ((imm >> 0) & 1)); \ d->elem(1) = F(d->elem(1), s->elem(1), ((imm >> 1) & 1)); \ @@ -1596,7 +1603,7 @@ SSE_HELPER_V(helper_pblendvb, B, 16, FBLENDVB) SSE_HELPER_V(helper_blendvps, L, 4, FBLENDVPS) SSE_HELPER_V(helper_blendvpd, Q, 2, FBLENDVPD) -void glue(helper_ptest, SUFFIX)(Reg *d, Reg *s) +void glue(helper_ptest, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { uint64_t zf = (s->Q(0) & d->Q(0)) | (s->Q(1) & d->Q(1)); uint64_t cf = (s->Q(0) & ~d->Q(0)) | (s->Q(1) & ~d->Q(1)); @@ -1605,7 +1612,7 @@ void glue(helper_ptest, SUFFIX)(Reg *d, Reg *s) } #define SSE_HELPER_F(name, elem, num, F) \ - void glue(name, SUFFIX)(Reg *d, Reg *s) \ + void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ { \ d->elem(0) = F(0); \ d->elem(1) = F(1); \ @@ -1634,7 +1641,7 @@ SSE_HELPER_F(helper_pmovzxwd, L, 4, s->W) SSE_HELPER_F(helper_pmovzxwq, Q, 2, s->W) SSE_HELPER_F(helper_pmovzxdq, Q, 2, s->L) -void glue(helper_pmuldq, SUFFIX)(Reg *d, Reg *s) +void glue(helper_pmuldq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { d->Q(0) = (int64_t)(int32_t) d->L(0) * (int32_t) s->L(0); d->Q(1) = (int64_t)(int32_t) d->L(2) * (int32_t) s->L(2); @@ -1643,7 +1650,7 @@ void glue(helper_pmuldq, SUFFIX)(Reg *d, Reg *s) #define FCMPEQQ(d, s) (d == s ? -1 : 0) SSE_HELPER_Q(helper_pcmpeqq, FCMPEQQ) -void glue(helper_packusdw, SUFFIX)(Reg *d, Reg *s) +void glue(helper_packusdw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { d->W(0) = satuw((int32_t) d->L(0)); d->W(1) = satuw((int32_t) d->L(1)); @@ -1671,7 +1678,7 @@ SSE_HELPER_L(helper_pmaxud, MAX) #define FMULLD(d, s) ((int32_t)d * (int32_t)s) SSE_HELPER_L(helper_pmulld, FMULLD) -void glue(helper_phminposuw, SUFFIX)(Reg *d, Reg *s) +void glue(helper_phminposuw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int idx = 0; @@ -1703,7 +1710,8 @@ void glue(helper_phminposuw, SUFFIX)(Reg *d, Reg *s) d->W(0) = s->W(idx); } -void glue(helper_roundps, SUFFIX)(Reg *d, Reg *s, uint32_t mode) +void glue(helper_roundps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + uint32_t mode) { signed char prev_rounding_mode; @@ -1740,7 +1748,8 @@ void glue(helper_roundps, SUFFIX)(Reg *d, Reg *s, uint32_t mode) env->sse_status.float_rounding_mode = prev_rounding_mode; } -void glue(helper_roundpd, SUFFIX)(Reg *d, Reg *s, uint32_t mode) +void glue(helper_roundpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + uint32_t mode) { signed char prev_rounding_mode; @@ -1775,7 +1784,8 @@ void glue(helper_roundpd, SUFFIX)(Reg *d, Reg *s, uint32_t mode) env->sse_status.float_rounding_mode = prev_rounding_mode; } -void glue(helper_roundss, SUFFIX)(Reg *d, Reg *s, uint32_t mode) +void glue(helper_roundss, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + uint32_t mode) { signed char prev_rounding_mode; @@ -1809,7 +1819,8 @@ void glue(helper_roundss, SUFFIX)(Reg *d, Reg *s, uint32_t mode) env->sse_status.float_rounding_mode = prev_rounding_mode; } -void glue(helper_roundsd, SUFFIX)(Reg *d, Reg *s, uint32_t mode) +void glue(helper_roundsd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + uint32_t mode) { signed char prev_rounding_mode; @@ -1848,7 +1859,7 @@ SSE_HELPER_I(helper_blendps, L, 4, FBLENDP) SSE_HELPER_I(helper_blendpd, Q, 2, FBLENDP) SSE_HELPER_I(helper_pblendw, W, 8, FBLENDP) -void glue(helper_dpps, SUFFIX)(Reg *d, Reg *s, uint32_t mask) +void glue(helper_dpps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mask) { float32 iresult = float32_zero; @@ -1882,7 +1893,7 @@ void glue(helper_dpps, SUFFIX)(Reg *d, Reg *s, uint32_t mask) d->XMM_S(3) = (mask & (1 << 3)) ? iresult : float32_zero; } -void glue(helper_dppd, SUFFIX)(Reg *d, Reg *s, uint32_t mask) +void glue(helper_dppd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mask) { float64 iresult = float64_zero; @@ -1902,7 +1913,8 @@ void glue(helper_dppd, SUFFIX)(Reg *d, Reg *s, uint32_t mask) d->XMM_D(1) = (mask & (1 << 1)) ? iresult : float64_zero; } -void glue(helper_mpsadbw, SUFFIX)(Reg *d, Reg *s, uint32_t offset) +void glue(helper_mpsadbw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + uint32_t offset) { int s0 = (offset & 3) << 2; int d0 = (offset & 4) << 0; @@ -1925,7 +1937,7 @@ void glue(helper_mpsadbw, SUFFIX)(Reg *d, Reg *s, uint32_t offset) #define FCMPGTQ(d, s) (d > s ? -1 : 0) SSE_HELPER_Q(helper_pcmpgtq, FCMPGTQ) -static inline int pcmp_elen(int reg, uint32_t ctrl) +static inline int pcmp_elen(CPUX86State *env, int reg, uint32_t ctrl) { int val; @@ -1980,7 +1992,7 @@ static inline int pcmp_val(Reg *r, uint8_t ctrl, int i) } } -static inline unsigned pcmpxstrx(Reg *d, Reg *s, +static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s, int8_t ctrl, int valids, int validd) { unsigned int res = 0; @@ -2080,11 +2092,12 @@ static inline int ffs1(unsigned int val) return ret; } -void glue(helper_pcmpestri, SUFFIX)(Reg *d, Reg *s, uint32_t ctrl) +void glue(helper_pcmpestri, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + uint32_t ctrl) { - unsigned int res = pcmpxstrx(d, s, ctrl, - pcmp_elen(R_EDX, ctrl), - pcmp_elen(R_EAX, ctrl)); + unsigned int res = pcmpxstrx(env, d, s, ctrl, + pcmp_elen(env, R_EDX, ctrl), + pcmp_elen(env, R_EAX, ctrl)); if (res) { env->regs[R_ECX] = ((ctrl & (1 << 6)) ? rffs1 : ffs1)(res) - 1; @@ -2093,12 +2106,13 @@ void glue(helper_pcmpestri, SUFFIX)(Reg *d, Reg *s, uint32_t ctrl) } } -void glue(helper_pcmpestrm, SUFFIX)(Reg *d, Reg *s, uint32_t ctrl) +void glue(helper_pcmpestrm, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + uint32_t ctrl) { int i; - unsigned int res = pcmpxstrx(d, s, ctrl, - pcmp_elen(R_EDX, ctrl), - pcmp_elen(R_EAX, ctrl)); + unsigned int res = pcmpxstrx(env, d, s, ctrl, + pcmp_elen(env, R_EDX, ctrl), + pcmp_elen(env, R_EAX, ctrl)); if ((ctrl >> 6) & 1) { if (ctrl & 1) { @@ -2116,9 +2130,10 @@ void glue(helper_pcmpestrm, SUFFIX)(Reg *d, Reg *s, uint32_t ctrl) } } -void glue(helper_pcmpistri, SUFFIX)(Reg *d, Reg *s, uint32_t ctrl) +void glue(helper_pcmpistri, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + uint32_t ctrl) { - unsigned int res = pcmpxstrx(d, s, ctrl, + unsigned int res = pcmpxstrx(env, d, s, ctrl, pcmp_ilen(s, ctrl), pcmp_ilen(d, ctrl)); @@ -2129,10 +2144,11 @@ void glue(helper_pcmpistri, SUFFIX)(Reg *d, Reg *s, uint32_t ctrl) } } -void glue(helper_pcmpistrm, SUFFIX)(Reg *d, Reg *s, uint32_t ctrl) +void glue(helper_pcmpistrm, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + uint32_t ctrl) { int i; - unsigned int res = pcmpxstrx(d, s, ctrl, + unsigned int res = pcmpxstrx(env, d, s, ctrl, pcmp_ilen(s, ctrl), pcmp_ilen(d, ctrl)); @@ -2168,7 +2184,7 @@ target_ulong helper_crc32(uint32_t crc1, target_ulong msg, uint32_t len) #define POPMASK(i) ((target_ulong) -1 / ((1LL << (1 << i)) + 1)) #define POPCOUNT(n, i) ((n & POPMASK(i)) + ((n >> (1 << i)) & POPMASK(i))) -target_ulong helper_popcnt(target_ulong n, uint32_t type) +target_ulong helper_popcnt(CPUX86State *env, target_ulong n, uint32_t type) { CC_SRC = n ? 0 : CC_Z; diff --git a/target-i386/ops_sse_header.h b/target-i386/ops_sse_header.h index 8d4b2b7006..401eac6f00 100644 --- a/target-i386/ops_sse_header.h +++ b/target-i386/ops_sse_header.h @@ -34,31 +34,31 @@ #define dh_is_signed_XMMReg dh_is_signed_ptr #define dh_is_signed_MMXReg dh_is_signed_ptr -DEF_HELPER_2(glue(psrlw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(psraw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(psllw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(psrld, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(psrad, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pslld, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(psrlq, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(psllq, SUFFIX), void, Reg, Reg) +DEF_HELPER_3(glue(psrlw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(psraw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(psllw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(psrld, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(psrad, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pslld, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(psrlq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(psllq, SUFFIX), void, env, Reg, Reg) #if SHIFT == 1 -DEF_HELPER_2(glue(psrldq, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pslldq, SUFFIX), void, Reg, Reg) +DEF_HELPER_3(glue(psrldq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pslldq, SUFFIX), void, env, Reg, Reg) #endif #define SSE_HELPER_B(name, F)\ - DEF_HELPER_2(glue(name, SUFFIX), void, Reg, Reg) + DEF_HELPER_3(glue(name, SUFFIX), void, env, Reg, Reg) #define SSE_HELPER_W(name, F)\ - DEF_HELPER_2(glue(name, SUFFIX), void, Reg, Reg) + DEF_HELPER_3(glue(name, SUFFIX), void, env, Reg, Reg) #define SSE_HELPER_L(name, F)\ - DEF_HELPER_2(glue(name, SUFFIX), void, Reg, Reg) + DEF_HELPER_3(glue(name, SUFFIX), void, env, Reg, Reg) #define SSE_HELPER_Q(name, F)\ - DEF_HELPER_2(glue(name, SUFFIX), void, Reg, Reg) + DEF_HELPER_3(glue(name, SUFFIX), void, env, Reg, Reg) SSE_HELPER_B(paddb, FADD) SSE_HELPER_W(paddw, FADD) @@ -109,11 +109,11 @@ SSE_HELPER_W(pmulhw, FMULHW) SSE_HELPER_B(pavgb, FAVG) SSE_HELPER_W(pavgw, FAVG) -DEF_HELPER_2(glue(pmuludq, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmaddwd, SUFFIX), void, Reg, Reg) +DEF_HELPER_3(glue(pmuludq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmaddwd, SUFFIX), void, env, Reg, Reg) -DEF_HELPER_2(glue(psadbw, SUFFIX), void, Reg, Reg) -DEF_HELPER_3(glue(maskmov, SUFFIX), void, Reg, Reg, tl) +DEF_HELPER_3(glue(psadbw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_4(glue(maskmov, SUFFIX), void, env, Reg, Reg, tl) DEF_HELPER_2(glue(movl_mm_T0, SUFFIX), void, Reg, i32) #ifdef TARGET_X86_64 DEF_HELPER_2(glue(movq_mm_T0, SUFFIX), void, Reg, i64) @@ -133,11 +133,11 @@ DEF_HELPER_3(glue(pshufhw, SUFFIX), void, Reg, Reg, int) /* FPU ops */ /* XXX: not accurate */ -#define SSE_HELPER_S(name, F)\ - DEF_HELPER_2(name ## ps , void, Reg, Reg) \ - DEF_HELPER_2(name ## ss , void, Reg, Reg) \ - DEF_HELPER_2(name ## pd , void, Reg, Reg) \ - DEF_HELPER_2(name ## sd , void, Reg, Reg) +#define SSE_HELPER_S(name, F) \ + DEF_HELPER_3(name ## ps, void, env, Reg, Reg) \ + DEF_HELPER_3(name ## ss, void, env, Reg, Reg) \ + DEF_HELPER_3(name ## pd, void, env, Reg, Reg) \ + DEF_HELPER_3(name ## sd, void, env, Reg, Reg) SSE_HELPER_S(add, FPU_ADD) SSE_HELPER_S(sub, FPU_SUB) @@ -148,64 +148,64 @@ SSE_HELPER_S(max, FPU_MAX) SSE_HELPER_S(sqrt, FPU_SQRT) -DEF_HELPER_2(cvtps2pd, void, Reg, Reg) -DEF_HELPER_2(cvtpd2ps, void, Reg, Reg) -DEF_HELPER_2(cvtss2sd, void, Reg, Reg) -DEF_HELPER_2(cvtsd2ss, void, Reg, Reg) -DEF_HELPER_2(cvtdq2ps, void, Reg, Reg) -DEF_HELPER_2(cvtdq2pd, void, Reg, Reg) -DEF_HELPER_2(cvtpi2ps, void, XMMReg, MMXReg) -DEF_HELPER_2(cvtpi2pd, void, XMMReg, MMXReg) -DEF_HELPER_2(cvtsi2ss, void, XMMReg, i32) -DEF_HELPER_2(cvtsi2sd, void, XMMReg, i32) +DEF_HELPER_3(cvtps2pd, void, env, Reg, Reg) +DEF_HELPER_3(cvtpd2ps, void, env, Reg, Reg) +DEF_HELPER_3(cvtss2sd, void, env, Reg, Reg) +DEF_HELPER_3(cvtsd2ss, void, env, Reg, Reg) +DEF_HELPER_3(cvtdq2ps, void, env, Reg, Reg) +DEF_HELPER_3(cvtdq2pd, void, env, Reg, Reg) +DEF_HELPER_3(cvtpi2ps, void, env, XMMReg, MMXReg) +DEF_HELPER_3(cvtpi2pd, void, env, XMMReg, MMXReg) +DEF_HELPER_3(cvtsi2ss, void, env, XMMReg, i32) +DEF_HELPER_3(cvtsi2sd, void, env, XMMReg, i32) #ifdef TARGET_X86_64 -DEF_HELPER_2(cvtsq2ss, void, XMMReg, i64) -DEF_HELPER_2(cvtsq2sd, void, XMMReg, i64) +DEF_HELPER_3(cvtsq2ss, void, env, XMMReg, i64) +DEF_HELPER_3(cvtsq2sd, void, env, XMMReg, i64) #endif -DEF_HELPER_2(cvtps2dq, void, XMMReg, XMMReg) -DEF_HELPER_2(cvtpd2dq, void, XMMReg, XMMReg) -DEF_HELPER_2(cvtps2pi, void, MMXReg, XMMReg) -DEF_HELPER_2(cvtpd2pi, void, MMXReg, XMMReg) -DEF_HELPER_1(cvtss2si, s32, XMMReg) -DEF_HELPER_1(cvtsd2si, s32, XMMReg) +DEF_HELPER_3(cvtps2dq, void, env, XMMReg, XMMReg) +DEF_HELPER_3(cvtpd2dq, void, env, XMMReg, XMMReg) +DEF_HELPER_3(cvtps2pi, void, env, MMXReg, XMMReg) +DEF_HELPER_3(cvtpd2pi, void, env, MMXReg, XMMReg) +DEF_HELPER_2(cvtss2si, s32, env, XMMReg) +DEF_HELPER_2(cvtsd2si, s32, env, XMMReg) #ifdef TARGET_X86_64 -DEF_HELPER_1(cvtss2sq, s64, XMMReg) -DEF_HELPER_1(cvtsd2sq, s64, XMMReg) +DEF_HELPER_2(cvtss2sq, s64, env, XMMReg) +DEF_HELPER_2(cvtsd2sq, s64, env, XMMReg) #endif -DEF_HELPER_2(cvttps2dq, void, XMMReg, XMMReg) -DEF_HELPER_2(cvttpd2dq, void, XMMReg, XMMReg) -DEF_HELPER_2(cvttps2pi, void, MMXReg, XMMReg) -DEF_HELPER_2(cvttpd2pi, void, MMXReg, XMMReg) -DEF_HELPER_1(cvttss2si, s32, XMMReg) -DEF_HELPER_1(cvttsd2si, s32, XMMReg) +DEF_HELPER_3(cvttps2dq, void, env, XMMReg, XMMReg) +DEF_HELPER_3(cvttpd2dq, void, env, XMMReg, XMMReg) +DEF_HELPER_3(cvttps2pi, void, env, MMXReg, XMMReg) +DEF_HELPER_3(cvttpd2pi, void, env, MMXReg, XMMReg) +DEF_HELPER_2(cvttss2si, s32, env, XMMReg) +DEF_HELPER_2(cvttsd2si, s32, env, XMMReg) #ifdef TARGET_X86_64 -DEF_HELPER_1(cvttss2sq, s64, XMMReg) -DEF_HELPER_1(cvttsd2sq, s64, XMMReg) +DEF_HELPER_2(cvttss2sq, s64, env, XMMReg) +DEF_HELPER_2(cvttsd2sq, s64, env, XMMReg) #endif -DEF_HELPER_2(rsqrtps, void, XMMReg, XMMReg) -DEF_HELPER_2(rsqrtss, void, XMMReg, XMMReg) -DEF_HELPER_2(rcpps, void, XMMReg, XMMReg) -DEF_HELPER_2(rcpss, void, XMMReg, XMMReg) -DEF_HELPER_2(extrq_r, void, XMMReg, XMMReg) -DEF_HELPER_3(extrq_i, void, XMMReg, int, int) -DEF_HELPER_2(insertq_r, void, XMMReg, XMMReg) -DEF_HELPER_3(insertq_i, void, XMMReg, int, int) -DEF_HELPER_2(haddps, void, XMMReg, XMMReg) -DEF_HELPER_2(haddpd, void, XMMReg, XMMReg) -DEF_HELPER_2(hsubps, void, XMMReg, XMMReg) -DEF_HELPER_2(hsubpd, void, XMMReg, XMMReg) -DEF_HELPER_2(addsubps, void, XMMReg, XMMReg) -DEF_HELPER_2(addsubpd, void, XMMReg, XMMReg) - -#define SSE_HELPER_CMP(name, F)\ - DEF_HELPER_2( name ## ps , void, Reg, Reg) \ - DEF_HELPER_2( name ## ss , void, Reg, Reg) \ - DEF_HELPER_2( name ## pd , void, Reg, Reg) \ - DEF_HELPER_2( name ## sd , void, Reg, Reg) +DEF_HELPER_3(rsqrtps, void, env, XMMReg, XMMReg) +DEF_HELPER_3(rsqrtss, void, env, XMMReg, XMMReg) +DEF_HELPER_3(rcpps, void, env, XMMReg, XMMReg) +DEF_HELPER_3(rcpss, void, env, XMMReg, XMMReg) +DEF_HELPER_3(extrq_r, void, env, XMMReg, XMMReg) +DEF_HELPER_4(extrq_i, void, env, XMMReg, int, int) +DEF_HELPER_3(insertq_r, void, env, XMMReg, XMMReg) +DEF_HELPER_4(insertq_i, void, env, XMMReg, int, int) +DEF_HELPER_3(haddps, void, env, XMMReg, XMMReg) +DEF_HELPER_3(haddpd, void, env, XMMReg, XMMReg) +DEF_HELPER_3(hsubps, void, env, XMMReg, XMMReg) +DEF_HELPER_3(hsubpd, void, env, XMMReg, XMMReg) +DEF_HELPER_3(addsubps, void, env, XMMReg, XMMReg) +DEF_HELPER_3(addsubpd, void, env, XMMReg, XMMReg) + +#define SSE_HELPER_CMP(name, F) \ + DEF_HELPER_3(name ## ps, void, env, Reg, Reg) \ + DEF_HELPER_3(name ## ss, void, env, Reg, Reg) \ + DEF_HELPER_3(name ## pd, void, env, Reg, Reg) \ + DEF_HELPER_3(name ## sd, void, env, Reg, Reg) SSE_HELPER_CMP(cmpeq, FPU_CMPEQ) SSE_HELPER_CMP(cmplt, FPU_CMPLT) @@ -216,124 +216,124 @@ SSE_HELPER_CMP(cmpnlt, FPU_CMPNLT) SSE_HELPER_CMP(cmpnle, FPU_CMPNLE) SSE_HELPER_CMP(cmpord, FPU_CMPORD) -DEF_HELPER_2(ucomiss, void, Reg, Reg) -DEF_HELPER_2(comiss, void, Reg, Reg) -DEF_HELPER_2(ucomisd, void, Reg, Reg) -DEF_HELPER_2(comisd, void, Reg, Reg) -DEF_HELPER_1(movmskps, i32, Reg) -DEF_HELPER_1(movmskpd, i32, Reg) +DEF_HELPER_3(ucomiss, void, env, Reg, Reg) +DEF_HELPER_3(comiss, void, env, Reg, Reg) +DEF_HELPER_3(ucomisd, void, env, Reg, Reg) +DEF_HELPER_3(comisd, void, env, Reg, Reg) +DEF_HELPER_2(movmskps, i32, env, Reg) +DEF_HELPER_2(movmskpd, i32, env, Reg) #endif -DEF_HELPER_1(glue(pmovmskb, SUFFIX), i32, Reg) -DEF_HELPER_2(glue(packsswb, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(packuswb, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(packssdw, SUFFIX), void, Reg, Reg) -#define UNPCK_OP(base_name, base) \ - DEF_HELPER_2(glue(punpck ## base_name ## bw, SUFFIX) , void, Reg, Reg) \ - DEF_HELPER_2(glue(punpck ## base_name ## wd, SUFFIX) , void, Reg, Reg) \ - DEF_HELPER_2(glue(punpck ## base_name ## dq, SUFFIX) , void, Reg, Reg) +DEF_HELPER_2(glue(pmovmskb, SUFFIX), i32, env, Reg) +DEF_HELPER_3(glue(packsswb, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(packuswb, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(packssdw, SUFFIX), void, env, Reg, Reg) +#define UNPCK_OP(base_name, base) \ + DEF_HELPER_3(glue(punpck ## base_name ## bw, SUFFIX), void, env, Reg, Reg) \ + DEF_HELPER_3(glue(punpck ## base_name ## wd, SUFFIX), void, env, Reg, Reg) \ + DEF_HELPER_3(glue(punpck ## base_name ## dq, SUFFIX), void, env, Reg, Reg) UNPCK_OP(l, 0) UNPCK_OP(h, 1) #if SHIFT == 1 -DEF_HELPER_2(glue(punpcklqdq, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(punpckhqdq, SUFFIX), void, Reg, Reg) +DEF_HELPER_3(glue(punpcklqdq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(punpckhqdq, SUFFIX), void, env, Reg, Reg) #endif /* 3DNow! float ops */ #if SHIFT == 0 -DEF_HELPER_2(pi2fd, void, MMXReg, MMXReg) -DEF_HELPER_2(pi2fw, void, MMXReg, MMXReg) -DEF_HELPER_2(pf2id, void, MMXReg, MMXReg) -DEF_HELPER_2(pf2iw, void, MMXReg, MMXReg) -DEF_HELPER_2(pfacc, void, MMXReg, MMXReg) -DEF_HELPER_2(pfadd, void, MMXReg, MMXReg) -DEF_HELPER_2(pfcmpeq, void, MMXReg, MMXReg) -DEF_HELPER_2(pfcmpge, void, MMXReg, MMXReg) -DEF_HELPER_2(pfcmpgt, void, MMXReg, MMXReg) -DEF_HELPER_2(pfmax, void, MMXReg, MMXReg) -DEF_HELPER_2(pfmin, void, MMXReg, MMXReg) -DEF_HELPER_2(pfmul, void, MMXReg, MMXReg) -DEF_HELPER_2(pfnacc, void, MMXReg, MMXReg) -DEF_HELPER_2(pfpnacc, void, MMXReg, MMXReg) -DEF_HELPER_2(pfrcp, void, MMXReg, MMXReg) -DEF_HELPER_2(pfrsqrt, void, MMXReg, MMXReg) -DEF_HELPER_2(pfsub, void, MMXReg, MMXReg) -DEF_HELPER_2(pfsubr, void, MMXReg, MMXReg) -DEF_HELPER_2(pswapd, void, MMXReg, MMXReg) +DEF_HELPER_3(pi2fd, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pi2fw, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pf2id, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pf2iw, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfacc, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfadd, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfcmpeq, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfcmpge, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfcmpgt, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfmax, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfmin, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfmul, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfnacc, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfpnacc, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfrcp, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfrsqrt, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfsub, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pfsubr, void, env, MMXReg, MMXReg) +DEF_HELPER_3(pswapd, void, env, MMXReg, MMXReg) #endif /* SSSE3 op helpers */ -DEF_HELPER_2(glue(phaddw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(phaddd, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(phaddsw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(phsubw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(phsubd, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(phsubsw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pabsb, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pabsw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pabsd, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmaddubsw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmulhrsw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pshufb, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(psignb, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(psignw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(psignd, SUFFIX), void, Reg, Reg) -DEF_HELPER_3(glue(palignr, SUFFIX), void, Reg, Reg, s32) +DEF_HELPER_3(glue(phaddw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(phaddd, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(phaddsw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(phsubw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(phsubd, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(phsubsw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pabsb, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pabsw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pabsd, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmaddubsw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmulhrsw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pshufb, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(psignb, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(psignw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(psignd, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_4(glue(palignr, SUFFIX), void, env, Reg, Reg, s32) /* SSE4.1 op helpers */ #if SHIFT == 1 -DEF_HELPER_2(glue(pblendvb, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(blendvps, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(blendvpd, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(ptest, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmovsxbw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmovsxbd, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmovsxbq, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmovsxwd, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmovsxwq, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmovsxdq, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmovzxbw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmovzxbd, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmovzxbq, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmovzxwd, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmovzxwq, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmovzxdq, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmuldq, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pcmpeqq, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(packusdw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pminsb, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pminsd, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pminuw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pminud, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmaxsb, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmaxsd, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmaxuw, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmaxud, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(pmulld, SUFFIX), void, Reg, Reg) -DEF_HELPER_2(glue(phminposuw, SUFFIX), void, Reg, Reg) -DEF_HELPER_3(glue(roundps, SUFFIX), void, Reg, Reg, i32) -DEF_HELPER_3(glue(roundpd, SUFFIX), void, Reg, Reg, i32) -DEF_HELPER_3(glue(roundss, SUFFIX), void, Reg, Reg, i32) -DEF_HELPER_3(glue(roundsd, SUFFIX), void, Reg, Reg, i32) -DEF_HELPER_3(glue(blendps, SUFFIX), void, Reg, Reg, i32) -DEF_HELPER_3(glue(blendpd, SUFFIX), void, Reg, Reg, i32) -DEF_HELPER_3(glue(pblendw, SUFFIX), void, Reg, Reg, i32) -DEF_HELPER_3(glue(dpps, SUFFIX), void, Reg, Reg, i32) -DEF_HELPER_3(glue(dppd, SUFFIX), void, Reg, Reg, i32) -DEF_HELPER_3(glue(mpsadbw, SUFFIX), void, Reg, Reg, i32) +DEF_HELPER_3(glue(pblendvb, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(blendvps, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(blendvpd, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(ptest, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmovsxbw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmovsxbd, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmovsxbq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmovsxwd, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmovsxwq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmovsxdq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmovzxbw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmovzxbd, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmovzxbq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmovzxwd, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmovzxwq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmovzxdq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmuldq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pcmpeqq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(packusdw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pminsb, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pminsd, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pminuw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pminud, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmaxsb, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmaxsd, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmaxuw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmaxud, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(pmulld, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(phminposuw, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_4(glue(roundps, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(roundpd, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(roundss, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(roundsd, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(blendps, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(blendpd, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(pblendw, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(dpps, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(dppd, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(mpsadbw, SUFFIX), void, env, Reg, Reg, i32) #endif /* SSE4.2 op helpers */ #if SHIFT == 1 -DEF_HELPER_2(glue(pcmpgtq, SUFFIX), void, Reg, Reg) -DEF_HELPER_3(glue(pcmpestri, SUFFIX), void, Reg, Reg, i32) -DEF_HELPER_3(glue(pcmpestrm, SUFFIX), void, Reg, Reg, i32) -DEF_HELPER_3(glue(pcmpistri, SUFFIX), void, Reg, Reg, i32) -DEF_HELPER_3(glue(pcmpistrm, SUFFIX), void, Reg, Reg, i32) +DEF_HELPER_3(glue(pcmpgtq, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_4(glue(pcmpestri, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(pcmpestrm, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(pcmpistri, SUFFIX), void, env, Reg, Reg, i32) +DEF_HELPER_4(glue(pcmpistrm, SUFFIX), void, env, Reg, Reg, i32) DEF_HELPER_3(crc32, tl, i32, tl, i32) -DEF_HELPER_2(popcnt, tl, tl, i32) +DEF_HELPER_3(popcnt, tl, env, tl, i32) #endif #undef SHIFT diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c index a4b8b640a0..5fff8d59c6 100644 --- a/target-i386/seg_helper.c +++ b/target-i386/seg_helper.c @@ -19,16 +19,15 @@ */ #include "cpu.h" -#include "dyngen-exec.h" #include "qemu-log.h" #include "helper.h" +//#define DEBUG_PCALL + #if !defined(CONFIG_USER_ONLY) #include "softmmu_exec.h" #endif /* !defined(CONFIG_USER_ONLY) */ -//#define DEBUG_PCALL - #ifdef DEBUG_PCALL # define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__) # define LOG_PCALL_STATE(env) \ @@ -39,8 +38,8 @@ #endif /* return non zero if error */ -static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr, - int selector) +static inline int load_segment(CPUX86State *env, uint32_t *e1_ptr, + uint32_t *e2_ptr, int selector) { SegmentCache *dt; int index; @@ -56,8 +55,8 @@ static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr, return -1; } ptr = dt->base + index; - *e1_ptr = ldl_kernel(ptr); - *e2_ptr = ldl_kernel(ptr + 4); + *e1_ptr = cpu_ldl_kernel(env, ptr); + *e2_ptr = cpu_ldl_kernel(env, ptr + 4); return 0; } @@ -86,14 +85,14 @@ static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, } /* init the segment cache in vm86 mode. */ -static inline void load_seg_vm(int seg, int selector) +static inline void load_seg_vm(CPUX86State *env, int seg, int selector) { selector &= 0xffff; cpu_x86_load_seg_cache(env, seg, selector, (selector << 4), 0xffff, 0); } -static inline void get_ss_esp_from_tss(uint32_t *ss_ptr, +static inline void get_ss_esp_from_tss(CPUX86State *env, uint32_t *ss_ptr, uint32_t *esp_ptr, int dpl) { int type, index, shift; @@ -125,22 +124,22 @@ static inline void get_ss_esp_from_tss(uint32_t *ss_ptr, raise_exception_err(env, EXCP0A_TSS, env->tr.selector & 0xfffc); } if (shift == 0) { - *esp_ptr = lduw_kernel(env->tr.base + index); - *ss_ptr = lduw_kernel(env->tr.base + index + 2); + *esp_ptr = cpu_lduw_kernel(env, env->tr.base + index); + *ss_ptr = cpu_lduw_kernel(env, env->tr.base + index + 2); } else { - *esp_ptr = ldl_kernel(env->tr.base + index); - *ss_ptr = lduw_kernel(env->tr.base + index + 4); + *esp_ptr = cpu_ldl_kernel(env, env->tr.base + index); + *ss_ptr = cpu_lduw_kernel(env, env->tr.base + index + 4); } } /* XXX: merge with load_seg() */ -static void tss_load_seg(int seg_reg, int selector) +static void tss_load_seg(CPUX86State *env, int seg_reg, int selector) { uint32_t e1, e2; int rpl, dpl, cpl; if ((selector & 0xfffc) != 0) { - if (load_segment(&e1, &e2, selector) != 0) { + if (load_segment(env, &e1, &e2, selector) != 0) { raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc); } if (!(e2 & DESC_S_MASK)) { @@ -199,7 +198,7 @@ static void tss_load_seg(int seg_reg, int selector) #define SWITCH_TSS_CALL 2 /* XXX: restore CPU state in registers (PowerPC case) */ -static void switch_tss(int tss_selector, +static void switch_tss(CPUX86State *env, int tss_selector, uint32_t e1, uint32_t e2, int source, uint32_t next_eip) { @@ -225,7 +224,7 @@ static void switch_tss(int tss_selector, if (tss_selector & 4) { raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc); } - if (load_segment(&e1, &e2, tss_selector) != 0) { + if (load_segment(env, &e1, &e2, tss_selector) != 0) { raise_exception_err(env, EXCP0D_GPF, tss_selector & 0xfffc); } if (e2 & DESC_S_MASK) { @@ -262,29 +261,30 @@ static void switch_tss(int tss_selector, /* read all the registers from the new TSS */ if (type & 8) { /* 32 bit */ - new_cr3 = ldl_kernel(tss_base + 0x1c); - new_eip = ldl_kernel(tss_base + 0x20); - new_eflags = ldl_kernel(tss_base + 0x24); + new_cr3 = cpu_ldl_kernel(env, tss_base + 0x1c); + new_eip = cpu_ldl_kernel(env, tss_base + 0x20); + new_eflags = cpu_ldl_kernel(env, tss_base + 0x24); for (i = 0; i < 8; i++) { - new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4)); + new_regs[i] = cpu_ldl_kernel(env, tss_base + (0x28 + i * 4)); } for (i = 0; i < 6; i++) { - new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4)); + new_segs[i] = cpu_lduw_kernel(env, tss_base + (0x48 + i * 4)); } - new_ldt = lduw_kernel(tss_base + 0x60); - new_trap = ldl_kernel(tss_base + 0x64); + new_ldt = cpu_lduw_kernel(env, tss_base + 0x60); + new_trap = cpu_ldl_kernel(env, tss_base + 0x64); } else { /* 16 bit */ new_cr3 = 0; - new_eip = lduw_kernel(tss_base + 0x0e); - new_eflags = lduw_kernel(tss_base + 0x10); + new_eip = cpu_lduw_kernel(env, tss_base + 0x0e); + new_eflags = cpu_lduw_kernel(env, tss_base + 0x10); for (i = 0; i < 8; i++) { - new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000; + new_regs[i] = cpu_lduw_kernel(env, tss_base + (0x12 + i * 2)) | + 0xffff0000; } for (i = 0; i < 4; i++) { - new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4)); + new_segs[i] = cpu_lduw_kernel(env, tss_base + (0x22 + i * 4)); } - new_ldt = lduw_kernel(tss_base + 0x2a); + new_ldt = cpu_lduw_kernel(env, tss_base + 0x2a); new_segs[R_FS] = 0; new_segs[R_GS] = 0; new_trap = 0; @@ -299,10 +299,10 @@ static void switch_tss(int tss_selector, /* XXX: it can still fail in some cases, so a bigger hack is necessary to valid the TLB after having done the accesses */ - v1 = ldub_kernel(env->tr.base); - v2 = ldub_kernel(env->tr.base + old_tss_limit_max); - stb_kernel(env->tr.base, v1); - stb_kernel(env->tr.base + old_tss_limit_max, v2); + v1 = cpu_ldub_kernel(env, env->tr.base); + v2 = cpu_ldub_kernel(env, env->tr.base + old_tss_limit_max); + cpu_stb_kernel(env, env->tr.base, v1); + cpu_stb_kernel(env, env->tr.base + old_tss_limit_max, v2); /* clear busy bit (it is restartable) */ if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) { @@ -310,9 +310,9 @@ static void switch_tss(int tss_selector, uint32_t e2; ptr = env->gdt.base + (env->tr.selector & ~7); - e2 = ldl_kernel(ptr + 4); + e2 = cpu_ldl_kernel(env, ptr + 4); e2 &= ~DESC_TSS_BUSY_MASK; - stl_kernel(ptr + 4, e2); + cpu_stl_kernel(env, ptr + 4, e2); } old_eflags = cpu_compute_eflags(env); if (source == SWITCH_TSS_IRET) { @@ -322,33 +322,35 @@ static void switch_tss(int tss_selector, /* save the current state in the old TSS */ if (type & 8) { /* 32 bit */ - stl_kernel(env->tr.base + 0x20, next_eip); - stl_kernel(env->tr.base + 0x24, old_eflags); - stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX); - stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX); - stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX); - stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX); - stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP); - stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP); - stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI); - stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI); + cpu_stl_kernel(env, env->tr.base + 0x20, next_eip); + cpu_stl_kernel(env, env->tr.base + 0x24, old_eflags); + cpu_stl_kernel(env, env->tr.base + (0x28 + 0 * 4), EAX); + cpu_stl_kernel(env, env->tr.base + (0x28 + 1 * 4), ECX); + cpu_stl_kernel(env, env->tr.base + (0x28 + 2 * 4), EDX); + cpu_stl_kernel(env, env->tr.base + (0x28 + 3 * 4), EBX); + cpu_stl_kernel(env, env->tr.base + (0x28 + 4 * 4), ESP); + cpu_stl_kernel(env, env->tr.base + (0x28 + 5 * 4), EBP); + cpu_stl_kernel(env, env->tr.base + (0x28 + 6 * 4), ESI); + cpu_stl_kernel(env, env->tr.base + (0x28 + 7 * 4), EDI); for (i = 0; i < 6; i++) { - stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector); + cpu_stw_kernel(env, env->tr.base + (0x48 + i * 4), + env->segs[i].selector); } } else { /* 16 bit */ - stw_kernel(env->tr.base + 0x0e, next_eip); - stw_kernel(env->tr.base + 0x10, old_eflags); - stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX); - stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX); - stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX); - stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX); - stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP); - stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP); - stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI); - stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI); + cpu_stw_kernel(env, env->tr.base + 0x0e, next_eip); + cpu_stw_kernel(env, env->tr.base + 0x10, old_eflags); + cpu_stw_kernel(env, env->tr.base + (0x12 + 0 * 2), EAX); + cpu_stw_kernel(env, env->tr.base + (0x12 + 1 * 2), ECX); + cpu_stw_kernel(env, env->tr.base + (0x12 + 2 * 2), EDX); + cpu_stw_kernel(env, env->tr.base + (0x12 + 3 * 2), EBX); + cpu_stw_kernel(env, env->tr.base + (0x12 + 4 * 2), ESP); + cpu_stw_kernel(env, env->tr.base + (0x12 + 5 * 2), EBP); + cpu_stw_kernel(env, env->tr.base + (0x12 + 6 * 2), ESI); + cpu_stw_kernel(env, env->tr.base + (0x12 + 7 * 2), EDI); for (i = 0; i < 4; i++) { - stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector); + cpu_stw_kernel(env, env->tr.base + (0x22 + i * 4), + env->segs[i].selector); } } @@ -356,7 +358,7 @@ static void switch_tss(int tss_selector, context */ if (source == SWITCH_TSS_CALL) { - stw_kernel(tss_base, env->tr.selector); + cpu_stw_kernel(env, tss_base, env->tr.selector); new_eflags |= NT_MASK; } @@ -366,9 +368,9 @@ static void switch_tss(int tss_selector, uint32_t e2; ptr = env->gdt.base + (tss_selector & ~7); - e2 = ldl_kernel(ptr + 4); + e2 = cpu_ldl_kernel(env, ptr + 4); e2 |= DESC_TSS_BUSY_MASK; - stl_kernel(ptr + 4, e2); + cpu_stl_kernel(env, ptr + 4, e2); } /* set the new CPU state */ @@ -404,7 +406,7 @@ static void switch_tss(int tss_selector, EDI = new_regs[7]; if (new_eflags & VM_MASK) { for (i = 0; i < 6; i++) { - load_seg_vm(i, new_segs[i]); + load_seg_vm(env, i, new_segs[i]); } /* in vm86, CPL is always 3 */ cpu_x86_set_cpl(env, 3); @@ -434,8 +436,8 @@ static void switch_tss(int tss_selector, raise_exception_err(env, EXCP0A_TSS, new_ldt & 0xfffc); } ptr = dt->base + index; - e1 = ldl_kernel(ptr); - e2 = ldl_kernel(ptr + 4); + e1 = cpu_ldl_kernel(env, ptr); + e2 = cpu_ldl_kernel(env, ptr + 4); if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) { raise_exception_err(env, EXCP0A_TSS, new_ldt & 0xfffc); } @@ -447,12 +449,12 @@ static void switch_tss(int tss_selector, /* load the segments */ if (!(new_eflags & VM_MASK)) { - tss_load_seg(R_CS, new_segs[R_CS]); - tss_load_seg(R_SS, new_segs[R_SS]); - tss_load_seg(R_ES, new_segs[R_ES]); - tss_load_seg(R_DS, new_segs[R_DS]); - tss_load_seg(R_FS, new_segs[R_FS]); - tss_load_seg(R_GS, new_segs[R_GS]); + tss_load_seg(env, R_CS, new_segs[R_CS]); + tss_load_seg(env, R_SS, new_segs[R_SS]); + tss_load_seg(env, R_ES, new_segs[R_ES]); + tss_load_seg(env, R_DS, new_segs[R_DS]); + tss_load_seg(env, R_FS, new_segs[R_FS]); + tss_load_seg(env, R_GS, new_segs[R_GS]); } /* check that EIP is in the CS segment limits */ @@ -521,33 +523,34 @@ static int exception_has_error_code(int intno) #define SEG_ADDL(ssp, sp, sp_mask) ((uint32_t)((ssp) + (sp & (sp_mask)))) /* XXX: add a is_user flag to have proper security support */ -#define PUSHW(ssp, sp, sp_mask, val) \ - { \ - sp -= 2; \ - stw_kernel((ssp) + (sp & (sp_mask)), (val)); \ +#define PUSHW(ssp, sp, sp_mask, val) \ + { \ + sp -= 2; \ + cpu_stw_kernel(env, (ssp) + (sp & (sp_mask)), (val)); \ } #define PUSHL(ssp, sp, sp_mask, val) \ { \ sp -= 4; \ - stl_kernel(SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val)); \ + cpu_stl_kernel(env, SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val)); \ } -#define POPW(ssp, sp, sp_mask, val) \ - { \ - val = lduw_kernel((ssp) + (sp & (sp_mask))); \ - sp += 2; \ +#define POPW(ssp, sp, sp_mask, val) \ + { \ + val = cpu_lduw_kernel(env, (ssp) + (sp & (sp_mask))); \ + sp += 2; \ } -#define POPL(ssp, sp, sp_mask, val) \ - { \ - val = (uint32_t)ldl_kernel(SEG_ADDL(ssp, sp, sp_mask)); \ - sp += 4; \ +#define POPL(ssp, sp, sp_mask, val) \ + { \ + val = (uint32_t)cpu_ldl_kernel(env, SEG_ADDL(ssp, sp, sp_mask)); \ + sp += 4; \ } /* protected mode interrupt */ -static void do_interrupt_protected(int intno, int is_int, int error_code, - unsigned int next_eip, int is_hw) +static void do_interrupt_protected(CPUX86State *env, int intno, int is_int, + int error_code, unsigned int next_eip, + int is_hw) { SegmentCache *dt; target_ulong ptr, ssp; @@ -571,8 +574,8 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2); } ptr = dt->base + intno * 8; - e1 = ldl_kernel(ptr); - e2 = ldl_kernel(ptr + 4); + e1 = cpu_ldl_kernel(env, ptr); + e2 = cpu_ldl_kernel(env, ptr + 4); /* check gate type */ type = (e2 >> DESC_TYPE_SHIFT) & 0x1f; switch (type) { @@ -581,7 +584,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, if (!(e2 & DESC_P_MASK)) { raise_exception_err(env, EXCP0B_NOSEG, intno * 8 + 2); } - switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip); + switch_tss(env, intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip); if (has_error_code) { int type; uint32_t mask; @@ -597,9 +600,9 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, esp = (ESP - (2 << shift)) & mask; ssp = env->segs[R_SS].base + esp; if (shift) { - stl_kernel(ssp, error_code); + cpu_stl_kernel(env, ssp, error_code); } else { - stw_kernel(ssp, error_code); + cpu_stw_kernel(env, ssp, error_code); } SET_ESP(esp, mask); } @@ -628,7 +631,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, if ((selector & 0xfffc) == 0) { raise_exception_err(env, EXCP0D_GPF, 0); } - if (load_segment(&e1, &e2, selector) != 0) { + if (load_segment(env, &e1, &e2, selector) != 0) { raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) { @@ -643,14 +646,14 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, } if (!(e2 & DESC_C_MASK) && dpl < cpl) { /* to inner privilege */ - get_ss_esp_from_tss(&ss, &esp, dpl); + get_ss_esp_from_tss(env, &ss, &esp, dpl); if ((ss & 0xfffc) == 0) { raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } if ((ss & 3) != dpl) { raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } - if (load_segment(&ss_e1, &ss_e2, ss) != 0) { + if (load_segment(env, &ss_e1, &ss_e2, ss) != 0) { raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3; @@ -765,16 +768,16 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, #define PUSHQ(sp, val) \ { \ sp -= 8; \ - stq_kernel(sp, (val)); \ + cpu_stq_kernel(env, sp, (val)); \ } #define POPQ(sp, val) \ { \ - val = ldq_kernel(sp); \ + val = cpu_ldq_kernel(env, sp); \ sp += 8; \ } -static inline target_ulong get_rsp_from_tss(int level) +static inline target_ulong get_rsp_from_tss(CPUX86State *env, int level) { int index; @@ -790,12 +793,12 @@ static inline target_ulong get_rsp_from_tss(int level) if ((index + 7) > env->tr.limit) { raise_exception_err(env, EXCP0A_TSS, env->tr.selector & 0xfffc); } - return ldq_kernel(env->tr.base + index); + return cpu_ldq_kernel(env, env->tr.base + index); } /* 64 bit interrupt */ -static void do_interrupt64(int intno, int is_int, int error_code, - target_ulong next_eip, int is_hw) +static void do_interrupt64(CPUX86State *env, int intno, int is_int, + int error_code, target_ulong next_eip, int is_hw) { SegmentCache *dt; target_ulong ptr; @@ -819,9 +822,9 @@ static void do_interrupt64(int intno, int is_int, int error_code, raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2); } ptr = dt->base + intno * 16; - e1 = ldl_kernel(ptr); - e2 = ldl_kernel(ptr + 4); - e3 = ldl_kernel(ptr + 8); + e1 = cpu_ldl_kernel(env, ptr); + e2 = cpu_ldl_kernel(env, ptr + 4); + e3 = cpu_ldl_kernel(env, ptr + 8); /* check gate type */ type = (e2 >> DESC_TYPE_SHIFT) & 0x1f; switch (type) { @@ -849,7 +852,7 @@ static void do_interrupt64(int intno, int is_int, int error_code, raise_exception_err(env, EXCP0D_GPF, 0); } - if (load_segment(&e1, &e2, selector) != 0) { + if (load_segment(env, &e1, &e2, selector) != 0) { raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) { @@ -868,9 +871,9 @@ static void do_interrupt64(int intno, int is_int, int error_code, if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) { /* to inner privilege */ if (ist != 0) { - esp = get_rsp_from_tss(ist + 3); + esp = get_rsp_from_tss(env, ist + 3); } else { - esp = get_rsp_from_tss(dpl); + esp = get_rsp_from_tss(env, dpl); } esp &= ~0xfLL; /* align stack */ ss = 0; @@ -882,7 +885,7 @@ static void do_interrupt64(int intno, int is_int, int error_code, } new_stack = 0; if (ist != 0) { - esp = get_rsp_from_tss(ist + 3); + esp = get_rsp_from_tss(env, ist + 3); } else { esp = ESP; } @@ -927,14 +930,14 @@ static void do_interrupt64(int intno, int is_int, int error_code, #ifdef TARGET_X86_64 #if defined(CONFIG_USER_ONLY) -void helper_syscall(int next_eip_addend) +void helper_syscall(CPUX86State *env, int next_eip_addend) { env->exception_index = EXCP_SYSCALL; env->exception_next_eip = env->eip + next_eip_addend; cpu_loop_exit(env); } #else -void helper_syscall(int next_eip_addend) +void helper_syscall(CPUX86State *env, int next_eip_addend) { int selector; @@ -991,7 +994,7 @@ void helper_syscall(int next_eip_addend) #endif #ifdef TARGET_X86_64 -void helper_sysret(int dflag) +void helper_sysret(CPUX86State *env, int dflag) { int cpl, selector; @@ -1048,8 +1051,8 @@ void helper_sysret(int dflag) #endif /* real mode interrupt */ -static void do_interrupt_real(int intno, int is_int, int error_code, - unsigned int next_eip) +static void do_interrupt_real(CPUX86State *env, int intno, int is_int, + int error_code, unsigned int next_eip) { SegmentCache *dt; target_ulong ptr, ssp; @@ -1063,8 +1066,8 @@ static void do_interrupt_real(int intno, int is_int, int error_code, raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2); } ptr = dt->base + intno * 4; - offset = lduw_kernel(ptr); - selector = lduw_kernel(ptr + 2); + offset = cpu_lduw_kernel(env, ptr); + selector = cpu_lduw_kernel(env, ptr + 2); esp = ESP; ssp = env->segs[R_SS].base; if (is_int) { @@ -1088,8 +1091,8 @@ static void do_interrupt_real(int intno, int is_int, int error_code, #if defined(CONFIG_USER_ONLY) /* fake user mode interrupt */ -static void do_interrupt_user(int intno, int is_int, int error_code, - target_ulong next_eip) +static void do_interrupt_user(CPUX86State *env, int intno, int is_int, + int error_code, target_ulong next_eip) { SegmentCache *dt; target_ulong ptr; @@ -1103,7 +1106,7 @@ static void do_interrupt_user(int intno, int is_int, int error_code, shift = 3; } ptr = dt->base + (intno << shift); - e2 = ldl_kernel(ptr + 4); + e2 = cpu_ldl_kernel(env, ptr + 4); dpl = (e2 >> DESC_DPL_SHIFT) & 3; cpl = env->hflags & HF_CPL_MASK; @@ -1122,8 +1125,8 @@ static void do_interrupt_user(int intno, int is_int, int error_code, #else -static void handle_even_inj(int intno, int is_int, int error_code, - int is_hw, int rm) +static void handle_even_inj(CPUX86State *env, int intno, int is_int, + int error_code, int is_hw, int rm) { uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)); @@ -1154,8 +1157,8 @@ static void handle_even_inj(int intno, int is_int, int error_code, * the int instruction. next_eip is the EIP value AFTER the interrupt * instruction. It is only relevant if is_int is TRUE. */ -static void do_interrupt_all(int intno, int is_int, int error_code, - target_ulong next_eip, int is_hw) +static void do_interrupt_all(CPUX86State *env, int intno, int is_int, + int error_code, target_ulong next_eip, int is_hw) { if (qemu_loglevel_mask(CPU_LOG_INT)) { if ((env->cr[0] & CR0_PE_MASK)) { @@ -1194,24 +1197,25 @@ static void do_interrupt_all(int intno, int is_int, int error_code, if (env->cr[0] & CR0_PE_MASK) { #if !defined(CONFIG_USER_ONLY) if (env->hflags & HF_SVMI_MASK) { - handle_even_inj(intno, is_int, error_code, is_hw, 0); + handle_even_inj(env, intno, is_int, error_code, is_hw, 0); } #endif #ifdef TARGET_X86_64 if (env->hflags & HF_LMA_MASK) { - do_interrupt64(intno, is_int, error_code, next_eip, is_hw); + do_interrupt64(env, intno, is_int, error_code, next_eip, is_hw); } else #endif { - do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); + do_interrupt_protected(env, intno, is_int, error_code, next_eip, + is_hw); } } else { #if !defined(CONFIG_USER_ONLY) if (env->hflags & HF_SVMI_MASK) { - handle_even_inj(intno, is_int, error_code, is_hw, 1); + handle_even_inj(env, intno, is_int, error_code, is_hw, 1); } #endif - do_interrupt_real(intno, is_int, error_code, next_eip); + do_interrupt_real(env, intno, is_int, error_code, next_eip); } #if !defined(CONFIG_USER_ONLY) @@ -1226,17 +1230,13 @@ static void do_interrupt_all(int intno, int is_int, int error_code, #endif } -void do_interrupt(CPUX86State *env1) +void do_interrupt(CPUX86State *env) { - CPUX86State *saved_env; - - saved_env = env; - env = env1; #if defined(CONFIG_USER_ONLY) /* if user mode only, we simulate a fake exception which will be handled outside the cpu execution loop */ - do_interrupt_user(env->exception_index, + do_interrupt_user(env, env->exception_index, env->exception_is_int, env->error_code, env->exception_next_eip); @@ -1246,27 +1246,22 @@ void do_interrupt(CPUX86State *env1) /* simulate a real cpu exception. On i386, it can trigger new exceptions, but we do not handle double or triple faults yet. */ - do_interrupt_all(env->exception_index, + do_interrupt_all(env, env->exception_index, env->exception_is_int, env->error_code, env->exception_next_eip, 0); /* successfully delivered */ env->old_exception = -1; #endif - env = saved_env; } -void do_interrupt_x86_hardirq(CPUX86State *env1, int intno, int is_hw) +void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw) { - CPUX86State *saved_env; - - saved_env = env; - env = env1; - do_interrupt_all(intno, 0, 0, 0, is_hw); - env = saved_env; + do_interrupt_all(env, intno, 0, 0, 0, is_hw); } -void helper_enter_level(int level, int data32, target_ulong t1) +void helper_enter_level(CPUX86State *env, int level, int data32, + target_ulong t1) { target_ulong ssp; uint32_t esp_mask, esp, ebp; @@ -1281,25 +1276,28 @@ void helper_enter_level(int level, int data32, target_ulong t1) while (--level) { esp -= 4; ebp -= 4; - stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask))); + cpu_stl_data(env, ssp + (esp & esp_mask), + cpu_ldl_data(env, ssp + (ebp & esp_mask))); } esp -= 4; - stl(ssp + (esp & esp_mask), t1); + cpu_stl_data(env, ssp + (esp & esp_mask), t1); } else { /* 16 bit */ esp -= 2; while (--level) { esp -= 2; ebp -= 2; - stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask))); + cpu_stw_data(env, ssp + (esp & esp_mask), + cpu_lduw_data(env, ssp + (ebp & esp_mask))); } esp -= 2; - stw(ssp + (esp & esp_mask), t1); + cpu_stw_data(env, ssp + (esp & esp_mask), t1); } } #ifdef TARGET_X86_64 -void helper_enter64_level(int level, int data64, target_ulong t1) +void helper_enter64_level(CPUX86State *env, int level, int data64, + target_ulong t1) { target_ulong esp, ebp; @@ -1312,25 +1310,25 @@ void helper_enter64_level(int level, int data64, target_ulong t1) while (--level) { esp -= 8; ebp -= 8; - stq(esp, ldq(ebp)); + cpu_stq_data(env, esp, cpu_ldq_data(env, ebp)); } esp -= 8; - stq(esp, t1); + cpu_stq_data(env, esp, t1); } else { /* 16 bit */ esp -= 2; while (--level) { esp -= 2; ebp -= 2; - stw(esp, lduw(ebp)); + cpu_stw_data(env, esp, cpu_lduw_data(env, ebp)); } esp -= 2; - stw(esp, t1); + cpu_stw_data(env, esp, t1); } } #endif -void helper_lldt(int selector) +void helper_lldt(CPUX86State *env, int selector) { SegmentCache *dt; uint32_t e1, e2; @@ -1360,8 +1358,8 @@ void helper_lldt(int selector) raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } ptr = dt->base + index; - e1 = ldl_kernel(ptr); - e2 = ldl_kernel(ptr + 4); + e1 = cpu_ldl_kernel(env, ptr); + e2 = cpu_ldl_kernel(env, ptr + 4); if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) { raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } @@ -1372,7 +1370,7 @@ void helper_lldt(int selector) if (env->hflags & HF_LMA_MASK) { uint32_t e3; - e3 = ldl_kernel(ptr + 8); + e3 = cpu_ldl_kernel(env, ptr + 8); load_seg_cache_raw_dt(&env->ldt, e1, e2); env->ldt.base |= (target_ulong)e3 << 32; } else @@ -1384,7 +1382,7 @@ void helper_lldt(int selector) env->ldt.selector = selector; } -void helper_ltr(int selector) +void helper_ltr(CPUX86State *env, int selector) { SegmentCache *dt; uint32_t e1, e2; @@ -1415,8 +1413,8 @@ void helper_ltr(int selector) raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } ptr = dt->base + index; - e1 = ldl_kernel(ptr); - e2 = ldl_kernel(ptr + 4); + e1 = cpu_ldl_kernel(env, ptr); + e2 = cpu_ldl_kernel(env, ptr + 4); type = (e2 >> DESC_TYPE_SHIFT) & 0xf; if ((e2 & DESC_S_MASK) || (type != 1 && type != 9)) { @@ -1429,8 +1427,8 @@ void helper_ltr(int selector) if (env->hflags & HF_LMA_MASK) { uint32_t e3, e4; - e3 = ldl_kernel(ptr + 8); - e4 = ldl_kernel(ptr + 12); + e3 = cpu_ldl_kernel(env, ptr + 8); + e4 = cpu_ldl_kernel(env, ptr + 12); if ((e4 >> DESC_TYPE_SHIFT) & 0xf) { raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } @@ -1442,13 +1440,13 @@ void helper_ltr(int selector) load_seg_cache_raw_dt(&env->tr, e1, e2); } e2 |= DESC_TSS_BUSY_MASK; - stl_kernel(ptr + 4, e2); + cpu_stl_kernel(env, ptr + 4, e2); } env->tr.selector = selector; } /* only works if protected mode and not VM86. seg_reg must be != R_CS */ -void helper_load_seg(int seg_reg, int selector) +void helper_load_seg(CPUX86State *env, int seg_reg, int selector) { uint32_t e1, e2; int cpl, dpl, rpl; @@ -1480,8 +1478,8 @@ void helper_load_seg(int seg_reg, int selector) raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } ptr = dt->base + index; - e1 = ldl_kernel(ptr); - e2 = ldl_kernel(ptr + 4); + e1 = cpu_ldl_kernel(env, ptr); + e2 = cpu_ldl_kernel(env, ptr + 4); if (!(e2 & DESC_S_MASK)) { raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); @@ -1521,7 +1519,7 @@ void helper_load_seg(int seg_reg, int selector) /* set the access bit if not already set */ if (!(e2 & DESC_A_MASK)) { e2 |= DESC_A_MASK; - stl_kernel(ptr + 4, e2); + cpu_stl_kernel(env, ptr + 4, e2); } cpu_x86_load_seg_cache(env, seg_reg, selector, @@ -1536,7 +1534,7 @@ void helper_load_seg(int seg_reg, int selector) } /* protected mode jump */ -void helper_ljmp_protected(int new_cs, target_ulong new_eip, +void helper_ljmp_protected(CPUX86State *env, int new_cs, target_ulong new_eip, int next_eip_addend) { int gate_cs, type; @@ -1546,7 +1544,7 @@ void helper_ljmp_protected(int new_cs, target_ulong new_eip, if ((new_cs & 0xfffc) == 0) { raise_exception_err(env, EXCP0D_GPF, 0); } - if (load_segment(&e1, &e2, new_cs) != 0) { + if (load_segment(env, &e1, &e2, new_cs) != 0) { raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } cpl = env->hflags & HF_CPL_MASK; @@ -1595,7 +1593,7 @@ void helper_ljmp_protected(int new_cs, target_ulong new_eip, raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } next_eip = env->eip + next_eip_addend; - switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip); + switch_tss(env, new_cs, e1, e2, SWITCH_TSS_JMP, next_eip); CC_OP = CC_OP_EFLAGS; break; case 4: /* 286 call gate */ @@ -1611,7 +1609,7 @@ void helper_ljmp_protected(int new_cs, target_ulong new_eip, if (type == 12) { new_eip |= (e2 & 0xffff0000); } - if (load_segment(&e1, &e2, gate_cs) != 0) { + if (load_segment(env, &e1, &e2, gate_cs) != 0) { raise_exception_err(env, EXCP0D_GPF, gate_cs & 0xfffc); } dpl = (e2 >> DESC_DPL_SHIFT) & 3; @@ -1643,7 +1641,7 @@ void helper_ljmp_protected(int new_cs, target_ulong new_eip, } /* real mode call */ -void helper_lcall_real(int new_cs, target_ulong new_eip1, +void helper_lcall_real(CPUX86State *env, int new_cs, target_ulong new_eip1, int shift, int next_eip) { int new_eip; @@ -1669,7 +1667,7 @@ void helper_lcall_real(int new_cs, target_ulong new_eip1, } /* protected mode call */ -void helper_lcall_protected(int new_cs, target_ulong new_eip, +void helper_lcall_protected(CPUX86State *env, int new_cs, target_ulong new_eip, int shift, int next_eip_addend) { int new_stack, i; @@ -1684,7 +1682,7 @@ void helper_lcall_protected(int new_cs, target_ulong new_eip, if ((new_cs & 0xfffc) == 0) { raise_exception_err(env, EXCP0D_GPF, 0); } - if (load_segment(&e1, &e2, new_cs) != 0) { + if (load_segment(env, &e1, &e2, new_cs) != 0) { raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } cpl = env->hflags & HF_CPL_MASK; @@ -1764,7 +1762,7 @@ void helper_lcall_protected(int new_cs, target_ulong new_eip, if (dpl < cpl || dpl < rpl) { raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } - switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip); + switch_tss(env, new_cs, e1, e2, SWITCH_TSS_CALL, next_eip); CC_OP = CC_OP_EFLAGS; return; case 4: /* 286 call gate */ @@ -1790,7 +1788,7 @@ void helper_lcall_protected(int new_cs, target_ulong new_eip, raise_exception_err(env, EXCP0D_GPF, 0); } - if (load_segment(&e1, &e2, selector) != 0) { + if (load_segment(env, &e1, &e2, selector) != 0) { raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) { @@ -1806,7 +1804,7 @@ void helper_lcall_protected(int new_cs, target_ulong new_eip, if (!(e2 & DESC_C_MASK) && dpl < cpl) { /* to inner privilege */ - get_ss_esp_from_tss(&ss, &sp, dpl); + get_ss_esp_from_tss(env, &ss, &sp, dpl); LOG_PCALL("new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n", ss, sp, param_count, ESP); @@ -1816,7 +1814,7 @@ void helper_lcall_protected(int new_cs, target_ulong new_eip, if ((ss & 3) != dpl) { raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } - if (load_segment(&ss_e1, &ss_e2, ss) != 0) { + if (load_segment(env, &ss_e1, &ss_e2, ss) != 0) { raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3; @@ -1843,14 +1841,16 @@ void helper_lcall_protected(int new_cs, target_ulong new_eip, PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector); PUSHL(ssp, sp, sp_mask, ESP); for (i = param_count - 1; i >= 0; i--) { - val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask)); + val = cpu_ldl_kernel(env, old_ssp + ((ESP + i * 4) & + old_sp_mask)); PUSHL(ssp, sp, sp_mask, val); } } else { PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector); PUSHW(ssp, sp, sp_mask, ESP); for (i = param_count - 1; i >= 0; i--) { - val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask)); + val = cpu_lduw_kernel(env, old_ssp + ((ESP + i * 2) & + old_sp_mask)); PUSHW(ssp, sp, sp_mask, val); } } @@ -1894,7 +1894,7 @@ void helper_lcall_protected(int new_cs, target_ulong new_eip, } /* real and vm86 mode iret */ -void helper_iret_real(int shift) +void helper_iret_real(CPUX86State *env, int shift) { uint32_t sp, new_cs, new_eip, new_eflags, sp_mask; target_ulong ssp; @@ -1933,7 +1933,7 @@ void helper_iret_real(int shift) env->hflags2 &= ~HF2_NMI_MASK; } -static inline void validate_seg(int seg_reg, int cpl) +static inline void validate_seg(CPUX86State *env, int seg_reg, int cpl) { int dpl; uint32_t e2; @@ -1957,7 +1957,8 @@ static inline void validate_seg(int seg_reg, int cpl) } /* protected mode iret */ -static inline void helper_ret_protected(int shift, int is_iret, int addend) +static inline void helper_ret_protected(CPUX86State *env, int shift, + int is_iret, int addend) { uint32_t new_cs, new_eflags, new_ss; uint32_t new_es, new_ds, new_fs, new_gs; @@ -2013,7 +2014,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) if ((new_cs & 0xfffc) == 0) { raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } - if (load_segment(&e1, &e2, new_cs) != 0) { + if (load_segment(env, &e1, &e2, new_cs) != 0) { raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } if (!(e2 & DESC_S_MASK) || @@ -2090,7 +2091,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) if ((new_ss & 3) != rpl) { raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc); } - if (load_segment(&ss_e1, &ss_e2, new_ss) != 0) { + if (load_segment(env, &ss_e1, &ss_e2, new_ss) != 0) { raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc); } if (!(ss_e2 & DESC_S_MASK) || @@ -2127,10 +2128,10 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) } /* validate data segments */ - validate_seg(R_ES, rpl); - validate_seg(R_DS, rpl); - validate_seg(R_FS, rpl); - validate_seg(R_GS, rpl); + validate_seg(env, R_ES, rpl); + validate_seg(env, R_DS, rpl); + validate_seg(env, R_FS, rpl); + validate_seg(env, R_GS, rpl); sp += addend; } @@ -2165,19 +2166,19 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) cpu_load_eflags(env, new_eflags, TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK); - load_seg_vm(R_CS, new_cs & 0xffff); + load_seg_vm(env, R_CS, new_cs & 0xffff); cpu_x86_set_cpl(env, 3); - load_seg_vm(R_SS, new_ss & 0xffff); - load_seg_vm(R_ES, new_es & 0xffff); - load_seg_vm(R_DS, new_ds & 0xffff); - load_seg_vm(R_FS, new_fs & 0xffff); - load_seg_vm(R_GS, new_gs & 0xffff); + load_seg_vm(env, R_SS, new_ss & 0xffff); + load_seg_vm(env, R_ES, new_es & 0xffff); + load_seg_vm(env, R_DS, new_ds & 0xffff); + load_seg_vm(env, R_FS, new_fs & 0xffff); + load_seg_vm(env, R_GS, new_gs & 0xffff); env->eip = new_eip & 0xffff; ESP = new_esp; } -void helper_iret_protected(int shift, int next_eip) +void helper_iret_protected(CPUX86State *env, int shift, int next_eip) { int tss_selector, type; uint32_t e1, e2; @@ -2189,11 +2190,11 @@ void helper_iret_protected(int shift, int next_eip) raise_exception_err(env, EXCP0D_GPF, 0); } #endif - tss_selector = lduw_kernel(env->tr.base + 0); + tss_selector = cpu_lduw_kernel(env, env->tr.base + 0); if (tss_selector & 4) { raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc); } - if (load_segment(&e1, &e2, tss_selector) != 0) { + if (load_segment(env, &e1, &e2, tss_selector) != 0) { raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc); } type = (e2 >> DESC_TYPE_SHIFT) & 0x17; @@ -2201,19 +2202,19 @@ void helper_iret_protected(int shift, int next_eip) if (type != 3) { raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc); } - switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip); + switch_tss(env, tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip); } else { - helper_ret_protected(shift, 1, 0); + helper_ret_protected(env, shift, 1, 0); } env->hflags2 &= ~HF2_NMI_MASK; } -void helper_lret_protected(int shift, int addend) +void helper_lret_protected(CPUX86State *env, int shift, int addend) { - helper_ret_protected(shift, 0, addend); + helper_ret_protected(env, shift, 0, addend); } -void helper_sysenter(void) +void helper_sysenter(CPUX86State *env) { if (env->sysenter_cs == 0) { raise_exception_err(env, EXCP0D_GPF, 0); @@ -2247,7 +2248,7 @@ void helper_sysenter(void) EIP = env->sysenter_eip; } -void helper_sysexit(int dflag) +void helper_sysexit(CPUX86State *env, int dflag) { int cpl; @@ -2287,18 +2288,18 @@ void helper_sysexit(int dflag) EIP = EDX; } -target_ulong helper_lsl(target_ulong selector1) +target_ulong helper_lsl(CPUX86State *env, target_ulong selector1) { unsigned int limit; uint32_t e1, e2, eflags, selector; int rpl, dpl, cpl, type; selector = selector1 & 0xffff; - eflags = helper_cc_compute_all(CC_OP); + eflags = cpu_cc_compute_all(env, CC_OP); if ((selector & 0xfffc) == 0) { goto fail; } - if (load_segment(&e1, &e2, selector) != 0) { + if (load_segment(env, &e1, &e2, selector) != 0) { goto fail; } rpl = selector & 3; @@ -2335,17 +2336,17 @@ target_ulong helper_lsl(target_ulong selector1) return limit; } -target_ulong helper_lar(target_ulong selector1) +target_ulong helper_lar(CPUX86State *env, target_ulong selector1) { uint32_t e1, e2, eflags, selector; int rpl, dpl, cpl, type; selector = selector1 & 0xffff; - eflags = helper_cc_compute_all(CC_OP); + eflags = cpu_cc_compute_all(env, CC_OP); if ((selector & 0xfffc) == 0) { goto fail; } - if (load_segment(&e1, &e2, selector) != 0) { + if (load_segment(env, &e1, &e2, selector) != 0) { goto fail; } rpl = selector & 3; @@ -2384,17 +2385,17 @@ target_ulong helper_lar(target_ulong selector1) return e2 & 0x00f0ff00; } -void helper_verr(target_ulong selector1) +void helper_verr(CPUX86State *env, target_ulong selector1) { uint32_t e1, e2, eflags, selector; int rpl, dpl, cpl; selector = selector1 & 0xffff; - eflags = helper_cc_compute_all(CC_OP); + eflags = cpu_cc_compute_all(env, CC_OP); if ((selector & 0xfffc) == 0) { goto fail; } - if (load_segment(&e1, &e2, selector) != 0) { + if (load_segment(env, &e1, &e2, selector) != 0) { goto fail; } if (!(e2 & DESC_S_MASK)) { @@ -2422,17 +2423,17 @@ void helper_verr(target_ulong selector1) CC_SRC = eflags | CC_Z; } -void helper_verw(target_ulong selector1) +void helper_verw(CPUX86State *env, target_ulong selector1) { uint32_t e1, e2, eflags, selector; int rpl, dpl, cpl; selector = selector1 & 0xffff; - eflags = helper_cc_compute_all(CC_OP); + eflags = cpu_cc_compute_all(env, CC_OP); if ((selector & 0xfffc) == 0) { goto fail; } - if (load_segment(&e1, &e2, selector) != 0) { + if (load_segment(env, &e1, &e2, selector) != 0) { goto fail; } if (!(e2 & DESC_S_MASK)) { @@ -2457,19 +2458,14 @@ void helper_verw(target_ulong selector1) } #if defined(CONFIG_USER_ONLY) -void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) +void cpu_x86_load_seg(CPUX86State *env, int seg_reg, int selector) { - CPUX86State *saved_env; - - saved_env = env; - env = s; if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) { selector &= 0xffff; cpu_x86_load_seg_cache(env, seg_reg, selector, (selector << 4), 0xffff, 0); } else { - helper_load_seg(seg_reg, selector); + helper_load_seg(env, seg_reg, selector); } - env = saved_env; } #endif diff --git a/target-i386/shift_helper_template.h b/target-i386/shift_helper_template.h index 239ee0973c..dda0da30cf 100644 --- a/target-i386/shift_helper_template.h +++ b/target-i386/shift_helper_template.h @@ -41,7 +41,8 @@ #error unhandled operand size #endif -target_ulong glue(helper_rcl, SUFFIX)(target_ulong t0, target_ulong t1) +target_ulong glue(helper_rcl, SUFFIX)(CPUX86State *env, target_ulong t0, + target_ulong t1) { int count, eflags; target_ulong src; @@ -54,7 +55,7 @@ target_ulong glue(helper_rcl, SUFFIX)(target_ulong t0, target_ulong t1) count = rclb_table[count]; #endif if (count) { - eflags = helper_cc_compute_all(CC_OP); + eflags = helper_cc_compute_all(env, CC_OP); t0 &= DATA_MASK; src = t0; res = (t0 << count) | ((target_ulong)(eflags & CC_C) << (count - 1)); @@ -71,7 +72,8 @@ target_ulong glue(helper_rcl, SUFFIX)(target_ulong t0, target_ulong t1) return t0; } -target_ulong glue(helper_rcr, SUFFIX)(target_ulong t0, target_ulong t1) +target_ulong glue(helper_rcr, SUFFIX)(CPUX86State *env, target_ulong t0, + target_ulong t1) { int count, eflags; target_ulong src; @@ -84,7 +86,7 @@ target_ulong glue(helper_rcr, SUFFIX)(target_ulong t0, target_ulong t1) count = rclb_table[count]; #endif if (count) { - eflags = helper_cc_compute_all(CC_OP); + eflags = helper_cc_compute_all(env, CC_OP); t0 &= DATA_MASK; src = t0; res = (t0 >> count) | diff --git a/target-i386/smm_helper.c b/target-i386/smm_helper.c index bc1bfa2a59..8b04eb2e00 100644 --- a/target-i386/smm_helper.c +++ b/target-i386/smm_helper.c @@ -18,18 +18,17 @@ */ #include "cpu.h" -#include "dyngen-exec.h" #include "helper.h" /* SMM support */ #if defined(CONFIG_USER_ONLY) -void do_smm_enter(CPUX86State *env1) +void do_smm_enter(CPUX86State *env) { } -void helper_rsm(void) +void helper_rsm(CPUX86State *env) { } @@ -41,15 +40,11 @@ void helper_rsm(void) #define SMM_REVISION_ID 0x00020000 #endif -void do_smm_enter(CPUX86State *env1) +void do_smm_enter(CPUX86State *env) { target_ulong sm_state; SegmentCache *dt; int i, offset; - CPUX86State *saved_env; - - saved_env = env; - env = env1; qemu_log_mask(CPU_LOG_INT, "SMM: enter\n"); log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP); @@ -180,10 +175,9 @@ void do_smm_enter(CPUX86State *env1) cpu_x86_update_cr4(env, 0); env->dr[7] = 0x00000400; CC_OP = CC_OP_EFLAGS; - env = saved_env; } -void helper_rsm(void) +void helper_rsm(CPUX86State *env) { target_ulong sm_state; int i, offset; diff --git a/target-i386/svm_helper.c b/target-i386/svm_helper.c index 64d842c82c..4943c37fee 100644 --- a/target-i386/svm_helper.c +++ b/target-i386/svm_helper.c @@ -18,46 +18,50 @@ */ #include "cpu.h" -#include "dyngen-exec.h" +#include "cpu-all.h" #include "helper.h" +#if !defined(CONFIG_USER_ONLY) +#include "softmmu_exec.h" +#endif /* !defined(CONFIG_USER_ONLY) */ + /* Secure Virtual Machine helpers */ #if defined(CONFIG_USER_ONLY) -void helper_vmrun(int aflag, int next_eip_addend) +void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) { } -void helper_vmmcall(void) +void helper_vmmcall(CPUX86State *env) { } -void helper_vmload(int aflag) +void helper_vmload(CPUX86State *env, int aflag) { } -void helper_vmsave(int aflag) +void helper_vmsave(CPUX86State *env, int aflag) { } -void helper_stgi(void) +void helper_stgi(CPUX86State *env) { } -void helper_clgi(void) +void helper_clgi(CPUX86State *env) { } -void helper_skinit(void) +void helper_skinit(CPUX86State *env) { } -void helper_invlpga(int aflag) +void helper_invlpga(CPUX86State *env, int aflag) { } -void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) +void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1) { } @@ -65,7 +69,8 @@ void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1) { } -void helper_svm_check_intercept_param(uint32_t type, uint64_t param) +void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type, + uint64_t param) { } @@ -74,13 +79,13 @@ void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type, { } -void helper_svm_check_io(uint32_t port, uint32_t param, +void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param, uint32_t next_eip_addend) { } #else -static inline void svm_save_seg(target_phys_addr_t addr, +static inline void svm_save_seg(CPUX86State *env, target_phys_addr_t addr, const SegmentCache *sc) { stw_phys(addr + offsetof(struct vmcb_seg, selector), @@ -93,7 +98,8 @@ static inline void svm_save_seg(target_phys_addr_t addr, ((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00)); } -static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc) +static inline void svm_load_seg(CPUX86State *env, target_phys_addr_t addr, + SegmentCache *sc) { unsigned int flags; @@ -104,23 +110,23 @@ static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc) sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12); } -static inline void svm_load_seg_cache(target_phys_addr_t addr, - CPUX86State *env, int seg_reg) +static inline void svm_load_seg_cache(CPUX86State *env, target_phys_addr_t addr, + int seg_reg) { SegmentCache sc1, *sc = &sc1; - svm_load_seg(addr, sc); + svm_load_seg(env, addr, sc); cpu_x86_load_seg_cache(env, seg_reg, sc->selector, sc->base, sc->limit, sc->flags); } -void helper_vmrun(int aflag, int next_eip_addend) +void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) { target_ulong addr; uint32_t event_inj; uint32_t int_ctl; - helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0); + cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0); if (aflag == 2) { addr = EAX; @@ -154,13 +160,13 @@ void helper_vmrun(int aflag, int next_eip_addend) stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), cpu_compute_eflags(env)); - svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), + svm_save_seg(env, env->vm_hsave + offsetof(struct vmcb, save.es), &env->segs[R_ES]); - svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), + svm_save_seg(env, env->vm_hsave + offsetof(struct vmcb, save.cs), &env->segs[R_CS]); - svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), + svm_save_seg(env, env->vm_hsave + offsetof(struct vmcb, save.ss), &env->segs[R_SS]); - svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), + svm_save_seg(env, env->vm_hsave + offsetof(struct vmcb, save.ds), &env->segs[R_DS]); stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), @@ -233,14 +239,14 @@ void helper_vmrun(int aflag, int next_eip_addend) ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); CC_OP = CC_OP_EFLAGS; - svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es), - env, R_ES); - svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs), - env, R_CS); - svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss), - env, R_SS); - svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds), - env, R_DS); + svm_load_seg_cache(env, env->vm_vmcb + offsetof(struct vmcb, save.es), + R_ES); + svm_load_seg_cache(env, env->vm_vmcb + offsetof(struct vmcb, save.cs), + R_CS); + svm_load_seg_cache(env, env->vm_vmcb + offsetof(struct vmcb, save.ss), + R_SS); + svm_load_seg_cache(env, env->vm_vmcb + offsetof(struct vmcb, save.ds), + R_DS); EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip)); env->eip = EIP; @@ -320,17 +326,17 @@ void helper_vmrun(int aflag, int next_eip_addend) } } -void helper_vmmcall(void) +void helper_vmmcall(CPUX86State *env) { - helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0); + cpu_svm_check_intercept_param(env, SVM_EXIT_VMMCALL, 0); raise_exception(env, EXCP06_ILLOP); } -void helper_vmload(int aflag) +void helper_vmload(CPUX86State *env, int aflag) { target_ulong addr; - helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0); + cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0); if (aflag == 2) { addr = EAX; @@ -340,17 +346,14 @@ void helper_vmload(int aflag) qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n", - addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)), + addr, ldq_phys(addr + offsetof(struct vmcb, + save.fs.base)), env->segs[R_FS].base); - svm_load_seg_cache(addr + offsetof(struct vmcb, save.fs), - env, R_FS); - svm_load_seg_cache(addr + offsetof(struct vmcb, save.gs), - env, R_GS); - svm_load_seg(addr + offsetof(struct vmcb, save.tr), - &env->tr); - svm_load_seg(addr + offsetof(struct vmcb, save.ldtr), - &env->ldt); + svm_load_seg_cache(env, addr + offsetof(struct vmcb, save.fs), R_FS); + svm_load_seg_cache(env, addr + offsetof(struct vmcb, save.gs), R_GS); + svm_load_seg(env, addr + offsetof(struct vmcb, save.tr), &env->tr); + svm_load_seg(env, addr + offsetof(struct vmcb, save.ldtr), &env->ldt); #ifdef TARGET_X86_64 env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, @@ -367,11 +370,11 @@ void helper_vmload(int aflag) save.sysenter_eip)); } -void helper_vmsave(int aflag) +void helper_vmsave(CPUX86State *env, int aflag) { target_ulong addr; - helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0); + cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0); if (aflag == 2) { addr = EAX; @@ -384,13 +387,13 @@ void helper_vmsave(int aflag) addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)), env->segs[R_FS].base); - svm_save_seg(addr + offsetof(struct vmcb, save.fs), + svm_save_seg(env, addr + offsetof(struct vmcb, save.fs), &env->segs[R_FS]); - svm_save_seg(addr + offsetof(struct vmcb, save.gs), + svm_save_seg(env, addr + offsetof(struct vmcb, save.gs), &env->segs[R_GS]); - svm_save_seg(addr + offsetof(struct vmcb, save.tr), + svm_save_seg(env, addr + offsetof(struct vmcb, save.tr), &env->tr); - svm_save_seg(addr + offsetof(struct vmcb, save.ldtr), + svm_save_seg(env, addr + offsetof(struct vmcb, save.ldtr), &env->ldt); #ifdef TARGET_X86_64 @@ -408,30 +411,30 @@ void helper_vmsave(int aflag) env->sysenter_eip); } -void helper_stgi(void) +void helper_stgi(CPUX86State *env) { - helper_svm_check_intercept_param(SVM_EXIT_STGI, 0); + cpu_svm_check_intercept_param(env, SVM_EXIT_STGI, 0); env->hflags2 |= HF2_GIF_MASK; } -void helper_clgi(void) +void helper_clgi(CPUX86State *env) { - helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0); + cpu_svm_check_intercept_param(env, SVM_EXIT_CLGI, 0); env->hflags2 &= ~HF2_GIF_MASK; } -void helper_skinit(void) +void helper_skinit(CPUX86State *env) { - helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0); + cpu_svm_check_intercept_param(env, SVM_EXIT_SKINIT, 0); /* XXX: not implemented */ raise_exception(env, EXCP06_ILLOP); } -void helper_invlpga(int aflag) +void helper_invlpga(CPUX86State *env, int aflag) { target_ulong addr; - helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0); + cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPGA, 0); if (aflag == 2) { addr = EAX; @@ -444,7 +447,8 @@ void helper_invlpga(int aflag) tlb_flush_page(env, addr); } -void helper_svm_check_intercept_param(uint32_t type, uint64_t param) +void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type, + uint64_t param) { if (likely(!(env->hflags & HF_SVMI_MASK))) { return; @@ -452,27 +456,27 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param) switch (type) { case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8: if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) { - helper_vmexit(type, param); + helper_vmexit(env, type, param); } break; case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8: if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) { - helper_vmexit(type, param); + helper_vmexit(env, type, param); } break; case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7: if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) { - helper_vmexit(type, param); + helper_vmexit(env, type, param); } break; case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7: if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) { - helper_vmexit(type, param); + helper_vmexit(env, type, param); } break; case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31: if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) { - helper_vmexit(type, param); + helper_vmexit(env, type, param); } break; case SVM_EXIT_MSR: @@ -499,36 +503,31 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param) t0 %= 8; break; default: - helper_vmexit(type, param); + helper_vmexit(env, type, param); t0 = 0; t1 = 0; break; } if (ldub_phys(addr + t1) & ((1 << param) << t0)) { - helper_vmexit(type, param); + helper_vmexit(env, type, param); } } break; default: if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) { - helper_vmexit(type, param); + helper_vmexit(env, type, param); } break; } } -void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type, +void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type, uint64_t param) { - CPUX86State *saved_env; - - saved_env = env; - env = env1; - helper_svm_check_intercept_param(type, param); - env = saved_env; + helper_svm_check_intercept_param(env, type, param); } -void helper_svm_check_io(uint32_t port, uint32_t param, +void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param, uint32_t next_eip_addend) { if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) { @@ -541,13 +540,13 @@ void helper_svm_check_io(uint32_t port, uint32_t param, /* next EIP */ stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), env->eip + next_eip_addend); - helper_vmexit(SVM_EXIT_IOIO, param | (port << 16)); + helper_vmexit(env, SVM_EXIT_IOIO, param | (port << 16)); } } } /* Note: currently only 32 bits of exit_code are used */ -void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) +void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1) { uint32_t int_ctl; @@ -567,13 +566,13 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) } /* Save the VM state in the vmcb */ - svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.es), + svm_save_seg(env, env->vm_vmcb + offsetof(struct vmcb, save.es), &env->segs[R_ES]); - svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.cs), + svm_save_seg(env, env->vm_vmcb + offsetof(struct vmcb, save.cs), &env->segs[R_CS]); - svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ss), + svm_save_seg(env, env->vm_vmcb + offsetof(struct vmcb, save.ss), &env->segs[R_SS]); - svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ds), + svm_save_seg(env, env->vm_vmcb + offsetof(struct vmcb, save.ds), &env->segs[R_DS]); stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), @@ -602,7 +601,8 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), cpu_compute_eflags(env)); - stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip); + stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), + env->eip); stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP); stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX); stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]); @@ -645,14 +645,14 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); CC_OP = CC_OP_EFLAGS; - svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.es), - env, R_ES); - svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.cs), - env, R_CS); - svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ss), - env, R_SS); - svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ds), - env, R_DS); + svm_load_seg_cache(env, env->vm_hsave + offsetof(struct vmcb, save.es), + R_ES); + svm_load_seg_cache(env, env->vm_hsave + offsetof(struct vmcb, save.cs), + R_CS); + svm_load_seg_cache(env, env->vm_hsave + offsetof(struct vmcb, save.ss), + R_SS); + svm_load_seg_cache(env, env->vm_hsave + offsetof(struct vmcb, save.ds), + R_DS); EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip)); ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp)); @@ -707,10 +707,9 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) cpu_loop_exit(env); } -void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1) +void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1) { - env = nenv; - helper_vmexit(exit_code, exit_info_1); + helper_vmexit(env, exit_code, exit_info_1); } #endif diff --git a/target-i386/translate.c b/target-i386/translate.c index 2b113333ac..7ab2ccb190 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -740,9 +740,15 @@ static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip, state_saved = 1; tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); switch (ot) { - case 0: gen_helper_check_iob(cpu_tmp2_i32); break; - case 1: gen_helper_check_iow(cpu_tmp2_i32); break; - case 2: gen_helper_check_iol(cpu_tmp2_i32); break; + case 0: + gen_helper_check_iob(cpu_env, cpu_tmp2_i32); + break; + case 1: + gen_helper_check_iow(cpu_env, cpu_tmp2_i32); + break; + case 2: + gen_helper_check_iol(cpu_env, cpu_tmp2_i32); + break; } } if(s->flags & HF_SVMI_MASK) { @@ -754,7 +760,8 @@ static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip, svm_flags |= (1 << (4 + ot)); next_eip = s->pc - s->cs_base; tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_svm_check_io(cpu_tmp2_i32, tcg_const_i32(svm_flags), + gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32, + tcg_const_i32(svm_flags), tcg_const_i32(next_eip - cur_eip)); } } @@ -811,14 +818,14 @@ static void gen_op_update_neg_cc(void) /* compute eflags.C to reg */ static void gen_compute_eflags_c(TCGv reg) { - gen_helper_cc_compute_c(cpu_tmp2_i32, cpu_cc_op); + gen_helper_cc_compute_c(cpu_tmp2_i32, cpu_env, cpu_cc_op); tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); } /* compute all eflags to cc_src */ static void gen_compute_eflags(TCGv reg) { - gen_helper_cc_compute_all(cpu_tmp2_i32, cpu_cc_op); + gen_helper_cc_compute_all(cpu_tmp2_i32, cpu_env, cpu_cc_op); tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); } @@ -1266,14 +1273,30 @@ GEN_REPZ2(cmps) static void gen_helper_fp_arith_ST0_FT0(int op) { switch (op) { - case 0: gen_helper_fadd_ST0_FT0(); break; - case 1: gen_helper_fmul_ST0_FT0(); break; - case 2: gen_helper_fcom_ST0_FT0(); break; - case 3: gen_helper_fcom_ST0_FT0(); break; - case 4: gen_helper_fsub_ST0_FT0(); break; - case 5: gen_helper_fsubr_ST0_FT0(); break; - case 6: gen_helper_fdiv_ST0_FT0(); break; - case 7: gen_helper_fdivr_ST0_FT0(); break; + case 0: + gen_helper_fadd_ST0_FT0(cpu_env); + break; + case 1: + gen_helper_fmul_ST0_FT0(cpu_env); + break; + case 2: + gen_helper_fcom_ST0_FT0(cpu_env); + break; + case 3: + gen_helper_fcom_ST0_FT0(cpu_env); + break; + case 4: + gen_helper_fsub_ST0_FT0(cpu_env); + break; + case 5: + gen_helper_fsubr_ST0_FT0(cpu_env); + break; + case 6: + gen_helper_fdiv_ST0_FT0(cpu_env); + break; + case 7: + gen_helper_fdivr_ST0_FT0(cpu_env); + break; } } @@ -1282,12 +1305,24 @@ static void gen_helper_fp_arith_STN_ST0(int op, int opreg) { TCGv_i32 tmp = tcg_const_i32(opreg); switch (op) { - case 0: gen_helper_fadd_STN_ST0(tmp); break; - case 1: gen_helper_fmul_STN_ST0(tmp); break; - case 4: gen_helper_fsubr_STN_ST0(tmp); break; - case 5: gen_helper_fsub_STN_ST0(tmp); break; - case 6: gen_helper_fdivr_STN_ST0(tmp); break; - case 7: gen_helper_fdiv_STN_ST0(tmp); break; + case 0: + gen_helper_fadd_STN_ST0(cpu_env, tmp); + break; + case 1: + gen_helper_fmul_STN_ST0(cpu_env, tmp); + break; + case 4: + gen_helper_fsubr_STN_ST0(cpu_env, tmp); + break; + case 5: + gen_helper_fsub_STN_ST0(cpu_env, tmp); + break; + case 6: + gen_helper_fdivr_STN_ST0(cpu_env, tmp); + break; + case 7: + gen_helper_fdiv_STN_ST0(cpu_env, tmp); + break; } } @@ -1745,20 +1780,36 @@ static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1, if (is_right) { switch (ot) { - case 0: gen_helper_rcrb(cpu_T[0], cpu_T[0], cpu_T[1]); break; - case 1: gen_helper_rcrw(cpu_T[0], cpu_T[0], cpu_T[1]); break; - case 2: gen_helper_rcrl(cpu_T[0], cpu_T[0], cpu_T[1]); break; + case 0: + gen_helper_rcrb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); + break; + case 1: + gen_helper_rcrw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); + break; + case 2: + gen_helper_rcrl(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); + break; #ifdef TARGET_X86_64 - case 3: gen_helper_rcrq(cpu_T[0], cpu_T[0], cpu_T[1]); break; + case 3: + gen_helper_rcrq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); + break; #endif } } else { switch (ot) { - case 0: gen_helper_rclb(cpu_T[0], cpu_T[0], cpu_T[1]); break; - case 1: gen_helper_rclw(cpu_T[0], cpu_T[0], cpu_T[1]); break; - case 2: gen_helper_rcll(cpu_T[0], cpu_T[0], cpu_T[1]); break; + case 0: + gen_helper_rclb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); + break; + case 1: + gen_helper_rclw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); + break; + case 2: + gen_helper_rcll(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); + break; #ifdef TARGET_X86_64 - case 3: gen_helper_rclq(cpu_T[0], cpu_T[0], cpu_T[1]); break; + case 3: + gen_helper_rclq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); + break; #endif } } @@ -1992,7 +2043,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ if (base == 4) { havesib = 1; - code = ldub_code(s->pc++); + code = cpu_ldub_code(cpu_single_env, s->pc++); scale = (code >> 6) & 3; index = ((code >> 3) & 7) | REX_X(s); base = (code & 7); @@ -2003,7 +2054,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ case 0: if ((base & 7) == 5) { base = -1; - disp = (int32_t)ldl_code(s->pc); + disp = (int32_t)cpu_ldl_code(cpu_single_env, s->pc); s->pc += 4; if (CODE64(s) && !havesib) { disp += s->pc + s->rip_offset; @@ -2013,11 +2064,11 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ } break; case 1: - disp = (int8_t)ldub_code(s->pc++); + disp = (int8_t)cpu_ldub_code(cpu_single_env, s->pc++); break; default: case 2: - disp = (int32_t)ldl_code(s->pc); + disp = (int32_t)cpu_ldl_code(cpu_single_env, s->pc); s->pc += 4; break; } @@ -2080,7 +2131,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ switch (mod) { case 0: if (rm == 6) { - disp = lduw_code(s->pc); + disp = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; gen_op_movl_A0_im(disp); rm = 0; /* avoid SS override */ @@ -2090,11 +2141,11 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ } break; case 1: - disp = (int8_t)ldub_code(s->pc++); + disp = (int8_t)cpu_ldub_code(cpu_single_env, s->pc++); break; default: case 2: - disp = lduw_code(s->pc); + disp = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; break; } @@ -2164,7 +2215,7 @@ static void gen_nop_modrm(DisasContext *s, int modrm) base = rm; if (base == 4) { - code = ldub_code(s->pc++); + code = cpu_ldub_code(cpu_single_env, s->pc++); base = (code & 7); } @@ -2260,16 +2311,16 @@ static inline uint32_t insn_get(DisasContext *s, int ot) switch(ot) { case OT_BYTE: - ret = ldub_code(s->pc); + ret = cpu_ldub_code(cpu_single_env, s->pc); s->pc++; break; case OT_WORD: - ret = lduw_code(s->pc); + ret = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; break; default: case OT_LONG: - ret = ldl_code(s->pc); + ret = cpu_ldl_code(cpu_single_env, s->pc); s->pc += 4; break; } @@ -2392,7 +2443,7 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip) gen_op_set_cc_op(s->cc_op); gen_jmp_im(cur_eip); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_load_seg(tcg_const_i32(seg_reg), cpu_tmp2_i32); + gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32); /* abort translation because the addseg value may change or because ss32 may change. For R_SS, translation must always stop as a special handling must be done to disable hardware @@ -2421,7 +2472,7 @@ gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_svm_check_intercept_param(tcg_const_i32(type), + gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type), tcg_const_i64(param)); } @@ -2629,7 +2680,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) gen_op_st_T0_A0(ot + s->mem_index); if (level) { /* XXX: must save state */ - gen_helper_enter64_level(tcg_const_i32(level), + gen_helper_enter64_level(cpu_env, tcg_const_i32(level), tcg_const_i32((ot == OT_QUAD)), cpu_T[1]); } @@ -2654,7 +2705,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) gen_op_st_T0_A0(ot + s->mem_index); if (level) { /* XXX: must save state */ - gen_helper_enter_level(tcg_const_i32(level), + gen_helper_enter_level(cpu_env, tcg_const_i32(level), tcg_const_i32(s->dflag), cpu_T[1]); } @@ -2691,7 +2742,7 @@ static void gen_debug(DisasContext *s, target_ulong cur_eip) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(cur_eip); - gen_helper_debug(); + gen_helper_debug(cpu_env); s->is_jmp = DISAS_TB_JUMP; } @@ -2702,15 +2753,15 @@ static void gen_eob(DisasContext *s) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); if (s->tb->flags & HF_INHIBIT_IRQ_MASK) { - gen_helper_reset_inhibit_irq(); + gen_helper_reset_inhibit_irq(cpu_env); } if (s->tb->flags & HF_RF_MASK) { - gen_helper_reset_rf(); + gen_helper_reset_rf(cpu_env); } if (s->singlestep_enabled) { - gen_helper_debug(); + gen_helper_debug(cpu_env); } else if (s->tf) { - gen_helper_single_step(); + gen_helper_single_step(cpu_env); } else { tcg_gen_exit_tb(0); } @@ -2796,13 +2847,16 @@ static inline void gen_op_movq_env_0(int d_offset) tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset); } -typedef void (*SSEFunc_i_p)(TCGv_i32 val, TCGv_ptr reg); -typedef void (*SSEFunc_l_p)(TCGv_i64 val, TCGv_ptr reg); -typedef void (*SSEFunc_0_pi)(TCGv_ptr reg, TCGv_i32 val); -typedef void (*SSEFunc_0_pl)(TCGv_ptr reg, TCGv_i64 val); -typedef void (*SSEFunc_0_pp)(TCGv_ptr reg_a, TCGv_ptr reg_b); +typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg); +typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg); +typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val); +typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val); +typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b); +typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, + TCGv_i32 val); typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val); -typedef void (*SSEFunc_0_ppt)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv val); +typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, + TCGv val); #define SSE_SPECIAL ((void *)1) #define SSE_DUMMY ((void *)2) @@ -2811,7 +2865,7 @@ typedef void (*SSEFunc_0_ppt)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv val); #define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \ gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, } -static const SSEFunc_0_pp sse_op_table1[256][4] = { +static const SSEFunc_0_epp sse_op_table1[256][4] = { /* 3DNow! extensions */ [0x0e] = { SSE_DUMMY }, /* femms */ [0x0f] = { SSE_DUMMY }, /* pf... */ @@ -2852,8 +2906,8 @@ static const SSEFunc_0_pp sse_op_table1[256][4] = { [0x5f] = SSE_FOP(max), [0xc2] = SSE_FOP(cmpeq), - [0xc6] = { (SSEFunc_0_pp)gen_helper_shufps, - (SSEFunc_0_pp)gen_helper_shufpd }, /* XXX: casts */ + [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps, + (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */ [0x38] = { SSE_SPECIAL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* SSSE3/SSE4 */ [0x3a] = { SSE_SPECIAL, SSE_SPECIAL }, /* SSSE3/SSE4 */ @@ -2875,10 +2929,10 @@ static const SSEFunc_0_pp sse_op_table1[256][4] = { [0x6d] = { NULL, gen_helper_punpckhqdq_xmm }, [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */ [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */ - [0x70] = { (SSEFunc_0_pp)gen_helper_pshufw_mmx, - (SSEFunc_0_pp)gen_helper_pshufd_xmm, - (SSEFunc_0_pp)gen_helper_pshufhw_xmm, - (SSEFunc_0_pp)gen_helper_pshuflw_xmm }, /* XXX: casts */ + [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx, + (SSEFunc_0_epp)gen_helper_pshufd_xmm, + (SSEFunc_0_epp)gen_helper_pshufhw_xmm, + (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */ [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */ [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */ [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */ @@ -2933,8 +2987,8 @@ static const SSEFunc_0_pp sse_op_table1[256][4] = { [0xf4] = MMX_OP2(pmuludq), [0xf5] = MMX_OP2(pmaddwd), [0xf6] = MMX_OP2(psadbw), - [0xf7] = { (SSEFunc_0_pp)gen_helper_maskmov_mmx, - (SSEFunc_0_pp)gen_helper_maskmov_xmm }, /* XXX: casts */ + [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx, + (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */ [0xf8] = MMX_OP2(psubb), [0xf9] = MMX_OP2(psubw), [0xfa] = MMX_OP2(psubl), @@ -2944,7 +2998,7 @@ static const SSEFunc_0_pp sse_op_table1[256][4] = { [0xfe] = MMX_OP2(paddl), }; -static const SSEFunc_0_pp sse_op_table2[3 * 8][2] = { +static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = { [0 + 2] = MMX_OP2(psrlw), [0 + 4] = MMX_OP2(psraw), [0 + 6] = MMX_OP2(psllw), @@ -2957,19 +3011,19 @@ static const SSEFunc_0_pp sse_op_table2[3 * 8][2] = { [16 + 7] = { NULL, gen_helper_pslldq_xmm }, }; -static const SSEFunc_0_pi sse_op_table3ai[] = { +static const SSEFunc_0_epi sse_op_table3ai[] = { gen_helper_cvtsi2ss, gen_helper_cvtsi2sd }; #ifdef TARGET_X86_64 -static const SSEFunc_0_pl sse_op_table3aq[] = { +static const SSEFunc_0_epl sse_op_table3aq[] = { gen_helper_cvtsq2ss, gen_helper_cvtsq2sd }; #endif -static const SSEFunc_i_p sse_op_table3bi[] = { +static const SSEFunc_i_ep sse_op_table3bi[] = { gen_helper_cvttss2si, gen_helper_cvtss2si, gen_helper_cvttsd2si, @@ -2977,7 +3031,7 @@ static const SSEFunc_i_p sse_op_table3bi[] = { }; #ifdef TARGET_X86_64 -static const SSEFunc_l_p sse_op_table3bq[] = { +static const SSEFunc_l_ep sse_op_table3bq[] = { gen_helper_cvttss2sq, gen_helper_cvtss2sq, gen_helper_cvttsd2sq, @@ -2985,7 +3039,7 @@ static const SSEFunc_l_p sse_op_table3bq[] = { }; #endif -static const SSEFunc_0_pp sse_op_table4[8][4] = { +static const SSEFunc_0_epp sse_op_table4[8][4] = { SSE_FOP(cmpeq), SSE_FOP(cmplt), SSE_FOP(cmple), @@ -2996,7 +3050,7 @@ static const SSEFunc_0_pp sse_op_table4[8][4] = { SSE_FOP(cmpord), }; -static const SSEFunc_0_pp sse_op_table5[256] = { +static const SSEFunc_0_epp sse_op_table5[256] = { [0x0c] = gen_helper_pi2fw, [0x0d] = gen_helper_pi2fd, [0x1c] = gen_helper_pf2iw, @@ -3023,13 +3077,13 @@ static const SSEFunc_0_pp sse_op_table5[256] = { [0xbf] = gen_helper_pavgb_mmx /* pavgusb */ }; -struct SSEOpHelper_pp { - SSEFunc_0_pp op[2]; +struct SSEOpHelper_epp { + SSEFunc_0_epp op[2]; uint32_t ext_mask; }; -struct SSEOpHelper_ppi { - SSEFunc_0_ppi op[2]; +struct SSEOpHelper_eppi { + SSEFunc_0_eppi op[2]; uint32_t ext_mask; }; @@ -3038,7 +3092,7 @@ struct SSEOpHelper_ppi { #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 } #define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 } -static const struct SSEOpHelper_pp sse_op_table6[256] = { +static const struct SSEOpHelper_epp sse_op_table6[256] = { [0x00] = SSSE3_OP(pshufb), [0x01] = SSSE3_OP(phaddw), [0x02] = SSSE3_OP(phaddd), @@ -3087,7 +3141,7 @@ static const struct SSEOpHelper_pp sse_op_table6[256] = { [0x41] = SSE41_OP(phminposuw), }; -static const struct SSEOpHelper_ppi sse_op_table7[256] = { +static const struct SSEOpHelper_eppi sse_op_table7[256] = { [0x08] = SSE41_OP(roundps), [0x09] = SSE41_OP(roundpd), [0x0a] = SSE41_OP(roundss), @@ -3116,9 +3170,10 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) { int b1, op1_offset, op2_offset, is_xmm, val, ot; int modrm, mod, rm, reg, reg_addr, offset_addr; - SSEFunc_0_pp sse_fn_pp; + SSEFunc_0_epp sse_fn_epp; + SSEFunc_0_eppi sse_fn_eppi; SSEFunc_0_ppi sse_fn_ppi; - SSEFunc_0_ppt sse_fn_ppt; + SSEFunc_0_eppt sse_fn_eppt; b &= 0xff; if (s->prefix & PREFIX_DATA) @@ -3129,8 +3184,8 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) b1 = 3; else b1 = 0; - sse_fn_pp = sse_op_table1[b][b1]; - if (!sse_fn_pp) { + sse_fn_epp = sse_op_table1[b][b1]; + if (!sse_fn_epp) { goto illegal_op; } if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) { @@ -3160,26 +3215,26 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) goto illegal_op; /* femms */ - gen_helper_emms(); + gen_helper_emms(cpu_env); return; } if (b == 0x77) { /* emms */ - gen_helper_emms(); + gen_helper_emms(cpu_env); return; } /* prepare MMX state (XXX: optimize by storing fptt and fptags in the static cpu state) */ if (!is_xmm) { - gen_helper_enter_mmx(); + gen_helper_enter_mmx(cpu_env); } - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7); if (is_xmm) reg |= rex_r; mod = (modrm >> 6) & 3; - if (sse_fn_pp == SSE_SPECIAL) { + if (sse_fn_epp == SSE_SPECIAL) { b |= (b1 << 8); switch(b) { case 0x0e7: /* movntq */ @@ -3378,16 +3433,18 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) if (b1 == 1 && reg != 0) goto illegal_op; - field_length = ldub_code(s->pc++) & 0x3F; - bit_index = ldub_code(s->pc++) & 0x3F; + field_length = cpu_ldub_code(cpu_single_env, s->pc++) & 0x3F; + bit_index = cpu_ldub_code(cpu_single_env, s->pc++) & 0x3F; tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[reg])); if (b1 == 1) - gen_helper_extrq_i(cpu_ptr0, tcg_const_i32(bit_index), - tcg_const_i32(field_length)); + gen_helper_extrq_i(cpu_env, cpu_ptr0, + tcg_const_i32(bit_index), + tcg_const_i32(field_length)); else - gen_helper_insertq_i(cpu_ptr0, tcg_const_i32(bit_index), - tcg_const_i32(field_length)); + gen_helper_insertq_i(cpu_env, cpu_ptr0, + tcg_const_i32(bit_index), + tcg_const_i32(field_length)); } break; case 0x7e: /* movd ea, mm */ @@ -3502,7 +3559,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) if (b1 >= 2) { goto illegal_op; } - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); if (is_xmm) { gen_op_movl_T0_im(val); tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0))); @@ -3516,8 +3573,9 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1))); op1_offset = offsetof(CPUX86State,mmx_t0); } - sse_fn_pp = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1]; - if (!sse_fn_pp) { + sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 + + (((modrm >> 3)) & 7)][b1]; + if (!sse_fn_epp) { goto illegal_op; } if (is_xmm) { @@ -3529,13 +3587,13 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) } tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset); tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset); - sse_fn_pp(cpu_ptr0, cpu_ptr1); + sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1); break; case 0x050: /* movmskps */ rm = (modrm & 7) | REX_B(s); tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm])); - gen_helper_movmskps(cpu_tmp2_i32, cpu_ptr0); + gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0); tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); gen_op_mov_reg_T0(OT_LONG, reg); break; @@ -3543,13 +3601,13 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) rm = (modrm & 7) | REX_B(s); tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm])); - gen_helper_movmskpd(cpu_tmp2_i32, cpu_ptr0); + gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0); tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); gen_op_mov_reg_T0(OT_LONG, reg); break; case 0x02a: /* cvtpi2ps */ case 0x12a: /* cvtpi2pd */ - gen_helper_enter_mmx(); + gen_helper_enter_mmx(cpu_env); if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); op2_offset = offsetof(CPUX86State,mmx_t0); @@ -3563,11 +3621,11 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); switch(b >> 8) { case 0x0: - gen_helper_cvtpi2ps(cpu_ptr0, cpu_ptr1); + gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1); break; default: case 0x1: - gen_helper_cvtpi2pd(cpu_ptr0, cpu_ptr1); + gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1); break; } break; @@ -3578,13 +3636,13 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) op1_offset = offsetof(CPUX86State,xmm_regs[reg]); tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); if (ot == OT_LONG) { - SSEFunc_0_pi sse_fn_pi = sse_op_table3ai[(b >> 8) & 1]; + SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1]; tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - sse_fn_pi(cpu_ptr0, cpu_tmp2_i32); + sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32); } else { #ifdef TARGET_X86_64 - SSEFunc_0_pl sse_fn_pl = sse_op_table3aq[(b >> 8) & 1]; - sse_fn_pl(cpu_ptr0, cpu_T[0]); + SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1]; + sse_fn_epl(cpu_env, cpu_ptr0, cpu_T[0]); #else goto illegal_op; #endif @@ -3594,7 +3652,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) case 0x12c: /* cvttpd2pi */ case 0x02d: /* cvtps2pi */ case 0x12d: /* cvtpd2pi */ - gen_helper_enter_mmx(); + gen_helper_enter_mmx(cpu_env); if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); op2_offset = offsetof(CPUX86State,xmm_t0); @@ -3608,16 +3666,16 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); switch(b) { case 0x02c: - gen_helper_cvttps2pi(cpu_ptr0, cpu_ptr1); + gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1); break; case 0x12c: - gen_helper_cvttpd2pi(cpu_ptr0, cpu_ptr1); + gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1); break; case 0x02d: - gen_helper_cvtps2pi(cpu_ptr0, cpu_ptr1); + gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1); break; case 0x12d: - gen_helper_cvtpd2pi(cpu_ptr0, cpu_ptr1); + gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1); break; } break; @@ -3641,15 +3699,15 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) } tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset); if (ot == OT_LONG) { - SSEFunc_i_p sse_fn_i_p = + SSEFunc_i_ep sse_fn_i_ep = sse_op_table3bi[((b >> 7) & 2) | (b & 1)]; - sse_fn_i_p(cpu_tmp2_i32, cpu_ptr0); + sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0); tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); } else { #ifdef TARGET_X86_64 - SSEFunc_l_p sse_fn_l_p = + SSEFunc_l_ep sse_fn_l_ep = sse_op_table3bq[((b >> 7) & 2) | (b & 1)]; - sse_fn_l_p(cpu_T[0], cpu_ptr0); + sse_fn_l_ep(cpu_T[0], cpu_env, cpu_ptr0); #else goto illegal_op; #endif @@ -3660,7 +3718,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) case 0x1c4: s->rip_offset = 1; gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); if (b1) { val &= 7; tcg_gen_st16_tl(cpu_T[0], cpu_env, @@ -3676,7 +3734,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) if (mod != 3) goto illegal_op; ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); if (b1) { val &= 7; rm = (modrm & 7) | REX_B(s); @@ -3703,14 +3761,14 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) } break; case 0x2d6: /* movq2dq */ - gen_helper_enter_mmx(); + gen_helper_enter_mmx(cpu_env); rm = (modrm & 7); gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)), offsetof(CPUX86State,fpregs[rm].mmx)); gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1))); break; case 0x3d6: /* movdq2q */ - gen_helper_enter_mmx(); + gen_helper_enter_mmx(cpu_env); rm = (modrm & 7) | REX_B(s); gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx), offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0))); @@ -3722,11 +3780,11 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) if (b1) { rm = (modrm & 7) | REX_B(s); tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm])); - gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_ptr0); + gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0); } else { rm = (modrm & 7); tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx)); - gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_ptr0); + gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0); } tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); reg = ((modrm >> 3) & 7) | rex_r; @@ -3737,7 +3795,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) goto crc32; case 0x038: b = modrm; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); rm = modrm & 7; reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; @@ -3745,8 +3803,8 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) goto illegal_op; } - sse_fn_pp = sse_op_table6[b].op[b1]; - if (!sse_fn_pp) { + sse_fn_epp = sse_op_table6[b].op[b1]; + if (!sse_fn_epp) { goto illegal_op; } if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask)) @@ -3797,13 +3855,13 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) gen_ldq_env_A0(s->mem_index, op2_offset); } } - if (sse_fn_pp == SSE_SPECIAL) { + if (sse_fn_epp == SSE_SPECIAL) { goto illegal_op; } tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); - sse_fn_pp(cpu_ptr0, cpu_ptr1); + sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1); if (b == 0x17) s->cc_op = CC_OP_EFLAGS; @@ -3811,7 +3869,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) case 0x338: /* crc32 */ crc32: b = modrm; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; if (b != 0xf0 && b != 0xf1) @@ -3841,7 +3899,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) case 0x03a: case 0x13a: b = modrm; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); rm = modrm & 7; reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; @@ -3849,20 +3907,20 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) goto illegal_op; } - sse_fn_ppi = sse_op_table7[b].op[b1]; - if (!sse_fn_ppi) { + sse_fn_eppi = sse_op_table7[b].op[b1]; + if (!sse_fn_eppi) { goto illegal_op; } if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask)) goto illegal_op; - if (sse_fn_ppi == SSE_SPECIAL) { + if (sse_fn_eppi == SSE_SPECIAL) { ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; rm = (modrm & 7) | REX_B(s); if (mod != 3) gen_lea_modrm(s, modrm, ®_addr, &offset_addr); reg = ((modrm >> 3) & 7) | rex_r; - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); switch (b) { case 0x14: /* pextrb */ tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, @@ -4005,7 +4063,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) gen_ldq_env_A0(s->mem_index, op2_offset); } } - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); if ((b & 0xfc) == 0x60) { /* pcmpXstrX */ s->cc_op = CC_OP_EFLAGS; @@ -4017,7 +4075,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); - sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val)); + sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val)); break; default: goto illegal_op; @@ -4071,34 +4129,34 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) case 0x0f: /* 3DNow! data insns */ if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) goto illegal_op; - val = ldub_code(s->pc++); - sse_fn_pp = sse_op_table5[val]; - if (!sse_fn_pp) { + val = cpu_ldub_code(cpu_single_env, s->pc++); + sse_fn_epp = sse_op_table5[val]; + if (!sse_fn_epp) { goto illegal_op; } tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); - sse_fn_pp(cpu_ptr0, cpu_ptr1); + sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1); break; case 0x70: /* pshufx insn */ case 0xc6: /* pshufx insn */ - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); /* XXX: introduce a new table? */ - sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_pp; + sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp; sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val)); break; case 0xc2: /* compare insns */ - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); if (val >= 8) goto illegal_op; - sse_fn_pp = sse_op_table4[val][b1]; + sse_fn_epp = sse_op_table4[val][b1]; tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); - sse_fn_pp(cpu_ptr0, cpu_ptr1); + sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1); break; case 0xf7: /* maskmov : we must prepare A0 */ @@ -4119,13 +4177,13 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); /* XXX: introduce a new table? */ - sse_fn_ppt = (SSEFunc_0_ppt)sse_fn_pp; - sse_fn_ppt(cpu_ptr0, cpu_ptr1, cpu_A0); + sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp; + sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0); break; default: tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); - sse_fn_pp(cpu_ptr0, cpu_ptr1); + sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1); break; } if (b == 0x2e || b == 0x2f) { @@ -4160,7 +4218,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) #endif s->rip_offset = 0; /* for relative ip address */ next_byte: - b = ldub_code(s->pc); + b = cpu_ldub_code(cpu_single_env, s->pc); s->pc++; /* check prefixes */ #ifdef TARGET_X86_64 @@ -4275,7 +4333,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x0f: /**************************/ /* extended op code */ - b = ldub_code(s->pc++) | 0x100; + b = cpu_ldub_code(cpu_single_env, s->pc++) | 0x100; goto reswitch; /**************************/ @@ -4300,7 +4358,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) switch(f) { case 0: /* OP Ev, Gv */ - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); @@ -4322,7 +4380,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op(s, op, ot, opreg); break; case 1: /* OP Gv, Ev */ - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; reg = ((modrm >> 3) & 7) | rex_r; rm = (modrm & 7) | REX_B(s); @@ -4359,7 +4417,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); op = (modrm >> 3) & 7; @@ -4408,7 +4466,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); op = (modrm >> 3) & 7; @@ -4506,7 +4564,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; #ifdef TARGET_X86_64 case OT_QUAD: - gen_helper_mulq_EAX_T0(cpu_T[0]); + gen_helper_mulq_EAX_T0(cpu_env, cpu_T[0]); s->cc_op = CC_OP_MULQ; break; #endif @@ -4576,7 +4634,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; #ifdef TARGET_X86_64 case OT_QUAD: - gen_helper_imulq_EAX_T0(cpu_T[0]); + gen_helper_imulq_EAX_T0(cpu_env, cpu_T[0]); s->cc_op = CC_OP_MULQ; break; #endif @@ -4586,21 +4644,21 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) switch(ot) { case OT_BYTE: gen_jmp_im(pc_start - s->cs_base); - gen_helper_divb_AL(cpu_T[0]); + gen_helper_divb_AL(cpu_env, cpu_T[0]); break; case OT_WORD: gen_jmp_im(pc_start - s->cs_base); - gen_helper_divw_AX(cpu_T[0]); + gen_helper_divw_AX(cpu_env, cpu_T[0]); break; default: case OT_LONG: gen_jmp_im(pc_start - s->cs_base); - gen_helper_divl_EAX(cpu_T[0]); + gen_helper_divl_EAX(cpu_env, cpu_T[0]); break; #ifdef TARGET_X86_64 case OT_QUAD: gen_jmp_im(pc_start - s->cs_base); - gen_helper_divq_EAX(cpu_T[0]); + gen_helper_divq_EAX(cpu_env, cpu_T[0]); break; #endif } @@ -4609,21 +4667,21 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) switch(ot) { case OT_BYTE: gen_jmp_im(pc_start - s->cs_base); - gen_helper_idivb_AL(cpu_T[0]); + gen_helper_idivb_AL(cpu_env, cpu_T[0]); break; case OT_WORD: gen_jmp_im(pc_start - s->cs_base); - gen_helper_idivw_AX(cpu_T[0]); + gen_helper_idivw_AX(cpu_env, cpu_T[0]); break; default: case OT_LONG: gen_jmp_im(pc_start - s->cs_base); - gen_helper_idivl_EAX(cpu_T[0]); + gen_helper_idivl_EAX(cpu_env, cpu_T[0]); break; #ifdef TARGET_X86_64 case OT_QUAD: gen_jmp_im(pc_start - s->cs_base); - gen_helper_idivq_EAX(cpu_T[0]); + gen_helper_idivq_EAX(cpu_env, cpu_T[0]); break; #endif } @@ -4640,7 +4698,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); op = (modrm >> 3) & 7; @@ -4701,13 +4759,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_lcall_protected(cpu_tmp2_i32, cpu_T[1], - tcg_const_i32(dflag), + gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1], + tcg_const_i32(dflag), tcg_const_i32(s->pc - pc_start)); } else { tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_lcall_real(cpu_tmp2_i32, cpu_T[1], - tcg_const_i32(dflag), + gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1], + tcg_const_i32(dflag), tcg_const_i32(s->pc - s->cs_base)); } gen_eob(s); @@ -4728,7 +4786,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_ljmp_protected(cpu_tmp2_i32, cpu_T[1], + gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1], tcg_const_i32(s->pc - pc_start)); } else { gen_op_movl_seg_T0_vm(R_CS); @@ -4752,7 +4810,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); @@ -4817,7 +4875,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x69: /* imul Gv, Ev, I */ case 0x6b: ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; if (b == 0x69) s->rip_offset = insn_const_size(ot); @@ -4836,7 +4894,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) #ifdef TARGET_X86_64 if (ot == OT_QUAD) { - gen_helper_imulq_T0_T1(cpu_T[0], cpu_T[0], cpu_T[1]); + gen_helper_imulq_T0_T1(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); } else #endif if (ot == OT_LONG) { @@ -4881,7 +4939,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = OT_BYTE; else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; if (mod == 3) { @@ -4912,7 +4970,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = OT_BYTE; else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; t0 = tcg_temp_local_new(); @@ -4960,7 +5018,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } break; case 0x1c7: /* cmpxchg8b */ - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; if ((mod == 3) || ((modrm & 0x38) != 0x8)) goto illegal_op; @@ -4972,7 +5030,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_helper_cmpxchg16b(cpu_A0); + gen_helper_cmpxchg16b(cpu_env, cpu_A0); } else #endif { @@ -4982,7 +5040,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_helper_cmpxchg8b(cpu_A0); + gen_helper_cmpxchg8b(cpu_env, cpu_A0); } s->cc_op = CC_OP_EFLAGS; break; @@ -5034,7 +5092,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } else { ot = dflag + OT_WORD; } - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; gen_pop_T0(s); if (mod == 3) { @@ -5053,9 +5111,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0xc8: /* enter */ { int level; - val = lduw_code(s->pc); + val = cpu_lduw_code(cpu_single_env, s->pc); s->pc += 2; - level = ldub_code(s->pc++); + level = cpu_ldub_code(cpu_single_env, s->pc++); gen_enter(s, val, level); } break; @@ -5108,7 +5166,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /* If several instructions disable interrupts, only the _first_ does it */ if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) - gen_helper_set_inhibit_irq(); + gen_helper_set_inhibit_irq(cpu_env); s->tf = 0; } if (s->is_jmp) { @@ -5135,7 +5193,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = OT_BYTE; else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; /* generate a generic store */ @@ -5147,7 +5205,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = OT_BYTE; else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; if (mod != 3) { s->rip_offset = insn_const_size(ot); @@ -5166,14 +5224,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = OT_BYTE; else ot = OT_WORD + dflag; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); gen_op_mov_reg_T0(ot, reg); break; case 0x8e: /* mov seg, Gv */ - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = (modrm >> 3) & 7; if (reg >= 6 || reg == R_CS) goto illegal_op; @@ -5184,7 +5242,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /* If several instructions disable interrupts, only the _first_ does it */ if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) - gen_helper_set_inhibit_irq(); + gen_helper_set_inhibit_irq(cpu_env); s->tf = 0; } if (s->is_jmp) { @@ -5193,7 +5251,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } break; case 0x8c: /* mov Gv, seg */ - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; if (reg >= 6) @@ -5216,7 +5274,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) d_ot = dflag + OT_WORD; /* ot is the size of source */ ot = (b & 1) + OT_BYTE; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); @@ -5253,7 +5311,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x8d: /* lea */ ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; if (mod == 3) goto illegal_op; @@ -5280,7 +5338,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = dflag + OT_WORD; #ifdef TARGET_X86_64 if (s->aflag == 2) { - offset_addr = ldq_code(s->pc); + offset_addr = cpu_ldq_code(cpu_single_env, s->pc); s->pc += 8; gen_op_movq_A0_im(offset_addr); } else @@ -5336,7 +5394,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (dflag == 2) { uint64_t tmp; /* 64 bit case */ - tmp = ldq_code(s->pc); + tmp = cpu_ldq_code(cpu_single_env, s->pc); s->pc += 8; reg = (b & 7) | REX_B(s); gen_movtl_T0_im(tmp); @@ -5364,7 +5422,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = OT_BYTE; else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; if (mod == 3) { @@ -5407,7 +5465,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) op = R_GS; do_lxx: ot = dflag ? OT_LONG : OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; if (mod == 3) @@ -5439,7 +5497,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) else ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; @@ -5458,7 +5516,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_shift(s, op, ot, opreg, OR_ECX); } else { if (shift == 2) { - shift = ldub_code(s->pc++); + shift = cpu_ldub_code(cpu_single_env, s->pc++); } gen_shifti(s, op, ot, opreg, shift); } @@ -5492,7 +5550,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) shift = 0; do_shiftd: ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); reg = ((modrm >> 3) & 7) | rex_r; @@ -5505,7 +5563,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_mov_TN_reg(ot, 1, reg); if (shift) { - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); tcg_gen_movi_tl(cpu_T3, val); } else { tcg_gen_mov_tl(cpu_T3, cpu_regs[R_ECX]); @@ -5522,7 +5580,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); break; } - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; rm = modrm & 7; op = ((b & 7) << 3) | ((modrm >> 3) & 7); @@ -5542,30 +5600,30 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0: gen_op_ld_T0_A0(OT_LONG + s->mem_index); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_flds_FT0(cpu_tmp2_i32); + gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32); break; case 1: gen_op_ld_T0_A0(OT_LONG + s->mem_index); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_fildl_FT0(cpu_tmp2_i32); + gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32); break; case 2: tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, (s->mem_index >> 2) - 1); - gen_helper_fldl_FT0(cpu_tmp1_i64); + gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64); break; case 3: default: gen_op_lds_T0_A0(OT_WORD + s->mem_index); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_fildl_FT0(cpu_tmp2_i32); + gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32); break; } gen_helper_fp_arith_ST0_FT0(op1); if (op1 == 3) { /* fcomp needs pop */ - gen_helper_fpop(); + gen_helper_fpop(cpu_env); } } break; @@ -5581,23 +5639,23 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0: gen_op_ld_T0_A0(OT_LONG + s->mem_index); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_flds_ST0(cpu_tmp2_i32); + gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32); break; case 1: gen_op_ld_T0_A0(OT_LONG + s->mem_index); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_fildl_ST0(cpu_tmp2_i32); + gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32); break; case 2: tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, (s->mem_index >> 2) - 1); - gen_helper_fldl_ST0(cpu_tmp1_i64); + gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64); break; case 3: default: gen_op_lds_T0_A0(OT_WORD + s->mem_index); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_fildl_ST0(cpu_tmp2_i32); + gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32); break; } break; @@ -5605,50 +5663,50 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /* XXX: the corresponding CPUID bit must be tested ! */ switch(op >> 4) { case 1: - gen_helper_fisttl_ST0(cpu_tmp2_i32); + gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env); tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); gen_op_st_T0_A0(OT_LONG + s->mem_index); break; case 2: - gen_helper_fisttll_ST0(cpu_tmp1_i64); + gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env); tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, (s->mem_index >> 2) - 1); break; case 3: default: - gen_helper_fistt_ST0(cpu_tmp2_i32); + gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env); tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); gen_op_st_T0_A0(OT_WORD + s->mem_index); break; } - gen_helper_fpop(); + gen_helper_fpop(cpu_env); break; default: switch(op >> 4) { case 0: - gen_helper_fsts_ST0(cpu_tmp2_i32); + gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env); tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); gen_op_st_T0_A0(OT_LONG + s->mem_index); break; case 1: - gen_helper_fistl_ST0(cpu_tmp2_i32); + gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env); tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); gen_op_st_T0_A0(OT_LONG + s->mem_index); break; case 2: - gen_helper_fstl_ST0(cpu_tmp1_i64); + gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env); tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, (s->mem_index >> 2) - 1); break; case 3: default: - gen_helper_fist_ST0(cpu_tmp2_i32); + gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env); tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); gen_op_st_T0_A0(OT_WORD + s->mem_index); break; } if ((op & 7) == 3) - gen_helper_fpop(); + gen_helper_fpop(cpu_env); break; } break; @@ -5656,22 +5714,21 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_fldenv( - cpu_A0, tcg_const_i32(s->dflag)); + gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag)); break; case 0x0d: /* fldcw mem */ gen_op_ld_T0_A0(OT_WORD + s->mem_index); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_fldcw(cpu_tmp2_i32); + gen_helper_fldcw(cpu_env, cpu_tmp2_i32); break; case 0x0e: /* fnstenv mem */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_fstenv(cpu_A0, tcg_const_i32(s->dflag)); + gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag)); break; case 0x0f: /* fnstcw mem */ - gen_helper_fnstcw(cpu_tmp2_i32); + gen_helper_fnstcw(cpu_tmp2_i32, cpu_env); tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); gen_op_st_T0_A0(OT_WORD + s->mem_index); break; @@ -5679,29 +5736,29 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_fldt_ST0(cpu_A0); + gen_helper_fldt_ST0(cpu_env, cpu_A0); break; case 0x1f: /* fstpt mem */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_fstt_ST0(cpu_A0); - gen_helper_fpop(); + gen_helper_fstt_ST0(cpu_env, cpu_A0); + gen_helper_fpop(cpu_env); break; case 0x2c: /* frstor mem */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_frstor(cpu_A0, tcg_const_i32(s->dflag)); + gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(s->dflag)); break; case 0x2e: /* fnsave mem */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_fsave(cpu_A0, tcg_const_i32(s->dflag)); + gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(s->dflag)); break; case 0x2f: /* fnstsw mem */ - gen_helper_fnstsw(cpu_tmp2_i32); + gen_helper_fnstsw(cpu_tmp2_i32, cpu_env); tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); gen_op_st_T0_A0(OT_WORD + s->mem_index); break; @@ -5709,25 +5766,25 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_fbld_ST0(cpu_A0); + gen_helper_fbld_ST0(cpu_env, cpu_A0); break; case 0x3e: /* fbstp */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_fbst_ST0(cpu_A0); - gen_helper_fpop(); + gen_helper_fbst_ST0(cpu_env, cpu_A0); + gen_helper_fpop(cpu_env); break; case 0x3d: /* fildll */ tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0, (s->mem_index >> 2) - 1); - gen_helper_fildll_ST0(cpu_tmp1_i64); + gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64); break; case 0x3f: /* fistpll */ - gen_helper_fistll_ST0(cpu_tmp1_i64); + gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env); tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0, (s->mem_index >> 2) - 1); - gen_helper_fpop(); + gen_helper_fpop(cpu_env); break; default: goto illegal_op; @@ -5738,13 +5795,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) switch(op) { case 0x08: /* fld sti */ - gen_helper_fpush(); - gen_helper_fmov_ST0_STN(tcg_const_i32((opreg + 1) & 7)); + gen_helper_fpush(cpu_env); + gen_helper_fmov_ST0_STN(cpu_env, + tcg_const_i32((opreg + 1) & 7)); break; case 0x09: /* fxchg sti */ case 0x29: /* fxchg4 sti, undocumented op */ case 0x39: /* fxchg7 sti, undocumented op */ - gen_helper_fxchg_ST0_STN(tcg_const_i32(opreg)); + gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg)); break; case 0x0a: /* grp d9/2 */ switch(rm) { @@ -5753,7 +5811,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_fwait(); + gen_helper_fwait(cpu_env); break; default: goto illegal_op; @@ -5762,17 +5820,17 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x0c: /* grp d9/4 */ switch(rm) { case 0: /* fchs */ - gen_helper_fchs_ST0(); + gen_helper_fchs_ST0(cpu_env); break; case 1: /* fabs */ - gen_helper_fabs_ST0(); + gen_helper_fabs_ST0(cpu_env); break; case 4: /* ftst */ - gen_helper_fldz_FT0(); - gen_helper_fcom_ST0_FT0(); + gen_helper_fldz_FT0(cpu_env); + gen_helper_fcom_ST0_FT0(cpu_env); break; case 5: /* fxam */ - gen_helper_fxam_ST0(); + gen_helper_fxam_ST0(cpu_env); break; default: goto illegal_op; @@ -5782,32 +5840,32 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) { switch(rm) { case 0: - gen_helper_fpush(); - gen_helper_fld1_ST0(); + gen_helper_fpush(cpu_env); + gen_helper_fld1_ST0(cpu_env); break; case 1: - gen_helper_fpush(); - gen_helper_fldl2t_ST0(); + gen_helper_fpush(cpu_env); + gen_helper_fldl2t_ST0(cpu_env); break; case 2: - gen_helper_fpush(); - gen_helper_fldl2e_ST0(); + gen_helper_fpush(cpu_env); + gen_helper_fldl2e_ST0(cpu_env); break; case 3: - gen_helper_fpush(); - gen_helper_fldpi_ST0(); + gen_helper_fpush(cpu_env); + gen_helper_fldpi_ST0(cpu_env); break; case 4: - gen_helper_fpush(); - gen_helper_fldlg2_ST0(); + gen_helper_fpush(cpu_env); + gen_helper_fldlg2_ST0(cpu_env); break; case 5: - gen_helper_fpush(); - gen_helper_fldln2_ST0(); + gen_helper_fpush(cpu_env); + gen_helper_fldln2_ST0(cpu_env); break; case 6: - gen_helper_fpush(); - gen_helper_fldz_ST0(); + gen_helper_fpush(cpu_env); + gen_helper_fldz_ST0(cpu_env); break; default: goto illegal_op; @@ -5817,58 +5875,58 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x0e: /* grp d9/6 */ switch(rm) { case 0: /* f2xm1 */ - gen_helper_f2xm1(); + gen_helper_f2xm1(cpu_env); break; case 1: /* fyl2x */ - gen_helper_fyl2x(); + gen_helper_fyl2x(cpu_env); break; case 2: /* fptan */ - gen_helper_fptan(); + gen_helper_fptan(cpu_env); break; case 3: /* fpatan */ - gen_helper_fpatan(); + gen_helper_fpatan(cpu_env); break; case 4: /* fxtract */ - gen_helper_fxtract(); + gen_helper_fxtract(cpu_env); break; case 5: /* fprem1 */ - gen_helper_fprem1(); + gen_helper_fprem1(cpu_env); break; case 6: /* fdecstp */ - gen_helper_fdecstp(); + gen_helper_fdecstp(cpu_env); break; default: case 7: /* fincstp */ - gen_helper_fincstp(); + gen_helper_fincstp(cpu_env); break; } break; case 0x0f: /* grp d9/7 */ switch(rm) { case 0: /* fprem */ - gen_helper_fprem(); + gen_helper_fprem(cpu_env); break; case 1: /* fyl2xp1 */ - gen_helper_fyl2xp1(); + gen_helper_fyl2xp1(cpu_env); break; case 2: /* fsqrt */ - gen_helper_fsqrt(); + gen_helper_fsqrt(cpu_env); break; case 3: /* fsincos */ - gen_helper_fsincos(); + gen_helper_fsincos(cpu_env); break; case 5: /* fscale */ - gen_helper_fscale(); + gen_helper_fscale(cpu_env); break; case 4: /* frndint */ - gen_helper_frndint(); + gen_helper_frndint(cpu_env); break; case 6: /* fsin */ - gen_helper_fsin(); + gen_helper_fsin(cpu_env); break; default: case 7: /* fcos */ - gen_helper_fcos(); + gen_helper_fcos(cpu_env); break; } break; @@ -5882,32 +5940,32 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (op >= 0x20) { gen_helper_fp_arith_STN_ST0(op1, opreg); if (op >= 0x30) - gen_helper_fpop(); + gen_helper_fpop(cpu_env); } else { - gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); gen_helper_fp_arith_ST0_FT0(op1); } } break; case 0x02: /* fcom */ case 0x22: /* fcom2, undocumented op */ - gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); - gen_helper_fcom_ST0_FT0(); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fcom_ST0_FT0(cpu_env); break; case 0x03: /* fcomp */ case 0x23: /* fcomp3, undocumented op */ case 0x32: /* fcomp5, undocumented op */ - gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); - gen_helper_fcom_ST0_FT0(); - gen_helper_fpop(); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fcom_ST0_FT0(cpu_env); + gen_helper_fpop(cpu_env); break; case 0x15: /* da/5 */ switch(rm) { case 1: /* fucompp */ - gen_helper_fmov_FT0_STN(tcg_const_i32(1)); - gen_helper_fucom_ST0_FT0(); - gen_helper_fpop(); - gen_helper_fpop(); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1)); + gen_helper_fucom_ST0_FT0(cpu_env); + gen_helper_fpop(cpu_env); + gen_helper_fpop(cpu_env); break; default: goto illegal_op; @@ -5920,10 +5978,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 1: /* fdisi (287 only, just do nop here) */ break; case 2: /* fclex */ - gen_helper_fclex(); + gen_helper_fclex(cpu_env); break; case 3: /* fninit */ - gen_helper_fninit(); + gen_helper_fninit(cpu_env); break; case 4: /* fsetpm (287 only, just do nop here) */ break; @@ -5934,59 +5992,59 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x1d: /* fucomi */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); - gen_helper_fucomi_ST0_FT0(); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fucomi_ST0_FT0(cpu_env); s->cc_op = CC_OP_EFLAGS; break; case 0x1e: /* fcomi */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); - gen_helper_fcomi_ST0_FT0(); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fcomi_ST0_FT0(cpu_env); s->cc_op = CC_OP_EFLAGS; break; case 0x28: /* ffree sti */ - gen_helper_ffree_STN(tcg_const_i32(opreg)); + gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg)); break; case 0x2a: /* fst sti */ - gen_helper_fmov_STN_ST0(tcg_const_i32(opreg)); + gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg)); break; case 0x2b: /* fstp sti */ case 0x0b: /* fstp1 sti, undocumented op */ case 0x3a: /* fstp8 sti, undocumented op */ case 0x3b: /* fstp9 sti, undocumented op */ - gen_helper_fmov_STN_ST0(tcg_const_i32(opreg)); - gen_helper_fpop(); + gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg)); + gen_helper_fpop(cpu_env); break; case 0x2c: /* fucom st(i) */ - gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); - gen_helper_fucom_ST0_FT0(); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fucom_ST0_FT0(cpu_env); break; case 0x2d: /* fucomp st(i) */ - gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); - gen_helper_fucom_ST0_FT0(); - gen_helper_fpop(); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fucom_ST0_FT0(cpu_env); + gen_helper_fpop(cpu_env); break; case 0x33: /* de/3 */ switch(rm) { case 1: /* fcompp */ - gen_helper_fmov_FT0_STN(tcg_const_i32(1)); - gen_helper_fcom_ST0_FT0(); - gen_helper_fpop(); - gen_helper_fpop(); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1)); + gen_helper_fcom_ST0_FT0(cpu_env); + gen_helper_fpop(cpu_env); + gen_helper_fpop(cpu_env); break; default: goto illegal_op; } break; case 0x38: /* ffreep sti, undocumented op */ - gen_helper_ffree_STN(tcg_const_i32(opreg)); - gen_helper_fpop(); + gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fpop(cpu_env); break; case 0x3c: /* df/4 */ switch(rm) { case 0: - gen_helper_fnstsw(cpu_tmp2_i32); + gen_helper_fnstsw(cpu_tmp2_i32, cpu_env); tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); gen_op_mov_reg_T0(OT_WORD, R_EAX); break; @@ -5997,17 +6055,17 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x3d: /* fucomip */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); - gen_helper_fucomi_ST0_FT0(); - gen_helper_fpop(); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fucomi_ST0_FT0(cpu_env); + gen_helper_fpop(cpu_env); s->cc_op = CC_OP_EFLAGS; break; case 0x3e: /* fcomip */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_helper_fmov_FT0_STN(tcg_const_i32(opreg)); - gen_helper_fcomi_ST0_FT0(); - gen_helper_fpop(); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fcomi_ST0_FT0(cpu_env); + gen_helper_fpop(cpu_env); s->cc_op = CC_OP_EFLAGS; break; case 0x10 ... 0x13: /* fcmovxx */ @@ -6023,7 +6081,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1); l1 = gen_new_label(); gen_jcc1(s, s->cc_op, op1, l1); - gen_helper_fmov_ST0_STN(tcg_const_i32(opreg)); + gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg)); gen_set_label(l1); } break; @@ -6153,7 +6211,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); gen_op_movl_T0_im(val); gen_check_io(s, ot, pc_start - s->cs_base, SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); @@ -6173,7 +6231,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); gen_op_movl_T0_im(val); gen_check_io(s, ot, pc_start - s->cs_base, svm_is_rep(prefixes)); @@ -6235,7 +6293,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /************************/ /* control */ case 0xc2: /* ret im */ - val = ldsw_code(s->pc); + val = cpu_ldsw_code(cpu_single_env, s->pc); s->pc += 2; gen_pop_T0(s); if (CODE64(s) && s->dflag) @@ -6255,14 +6313,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_eob(s); break; case 0xca: /* lret im */ - val = ldsw_code(s->pc); + val = cpu_ldsw_code(cpu_single_env, s->pc); s->pc += 2; do_lret: if (s->pe && !s->vm86) { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_lret_protected(tcg_const_i32(s->dflag), + gen_helper_lret_protected(cpu_env, tcg_const_i32(s->dflag), tcg_const_i32(val)); } else { gen_stack_A0(s); @@ -6289,20 +6347,20 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET); if (!s->pe) { /* real mode */ - gen_helper_iret_real(tcg_const_i32(s->dflag)); + gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag)); s->cc_op = CC_OP_EFLAGS; } else if (s->vm86) { if (s->iopl != 3) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - gen_helper_iret_real(tcg_const_i32(s->dflag)); + gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag)); s->cc_op = CC_OP_EFLAGS; } } else { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_iret_protected(tcg_const_i32(s->dflag), + gen_helper_iret_protected(cpu_env, tcg_const_i32(s->dflag), tcg_const_i32(s->pc - s->cs_base)); s->cc_op = CC_OP_EFLAGS; } @@ -6390,7 +6448,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; case 0x190 ... 0x19f: /* setcc Gv */ - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); gen_setcc(s, b); gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); break; @@ -6400,7 +6458,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) TCGv t0; ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; t0 = tcg_temp_local_new(); @@ -6440,7 +6498,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } else { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_helper_read_eflags(cpu_T[0]); + gen_helper_read_eflags(cpu_T[0], cpu_env); gen_push_T0(s); } break; @@ -6452,28 +6510,46 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_pop_T0(s); if (s->cpl == 0) { if (s->dflag) { - gen_helper_write_eflags(cpu_T[0], - tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK))); + gen_helper_write_eflags(cpu_env, cpu_T[0], + tcg_const_i32((TF_MASK | AC_MASK | + ID_MASK | NT_MASK | + IF_MASK | + IOPL_MASK))); } else { - gen_helper_write_eflags(cpu_T[0], - tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff)); + gen_helper_write_eflags(cpu_env, cpu_T[0], + tcg_const_i32((TF_MASK | AC_MASK | + ID_MASK | NT_MASK | + IF_MASK | IOPL_MASK) + & 0xffff)); } } else { if (s->cpl <= s->iopl) { if (s->dflag) { - gen_helper_write_eflags(cpu_T[0], - tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK))); + gen_helper_write_eflags(cpu_env, cpu_T[0], + tcg_const_i32((TF_MASK | + AC_MASK | + ID_MASK | + NT_MASK | + IF_MASK))); } else { - gen_helper_write_eflags(cpu_T[0], - tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff)); + gen_helper_write_eflags(cpu_env, cpu_T[0], + tcg_const_i32((TF_MASK | + AC_MASK | + ID_MASK | + NT_MASK | + IF_MASK) + & 0xffff)); } } else { if (s->dflag) { - gen_helper_write_eflags(cpu_T[0], - tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK))); + gen_helper_write_eflags(cpu_env, cpu_T[0], + tcg_const_i32((TF_MASK | AC_MASK | + ID_MASK | NT_MASK))); } else { - gen_helper_write_eflags(cpu_T[0], - tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff)); + gen_helper_write_eflags(cpu_env, cpu_T[0], + tcg_const_i32((TF_MASK | AC_MASK | + ID_MASK | NT_MASK) + & 0xffff)); } } } @@ -6540,7 +6616,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /* bit operations */ case 0x1ba: /* bt/bts/btr/btc Gv, im */ ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); op = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); @@ -6552,7 +6628,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_mov_TN_reg(ot, 0, rm); } /* load shift */ - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); gen_op_movl_T1_im(val); if (op < 4) goto illegal_op; @@ -6571,7 +6647,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) op = 3; do_btx: ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); @@ -6632,7 +6708,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) TCGv t0; ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(s,modrm, ot, OR_TMP0, 0); gen_extu(ot, cpu_T[0]); @@ -6674,7 +6750,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_helper_daa(); + gen_helper_daa(cpu_env); s->cc_op = CC_OP_EFLAGS; break; case 0x2f: /* das */ @@ -6682,7 +6758,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_helper_das(); + gen_helper_das(cpu_env); s->cc_op = CC_OP_EFLAGS; break; case 0x37: /* aaa */ @@ -6690,7 +6766,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_helper_aaa(); + gen_helper_aaa(cpu_env); s->cc_op = CC_OP_EFLAGS; break; case 0x3f: /* aas */ @@ -6698,25 +6774,25 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_helper_aas(); + gen_helper_aas(cpu_env); s->cc_op = CC_OP_EFLAGS; break; case 0xd4: /* aam */ if (CODE64(s)) goto illegal_op; - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); if (val == 0) { gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base); } else { - gen_helper_aam(tcg_const_i32(val)); + gen_helper_aam(cpu_env, tcg_const_i32(val)); s->cc_op = CC_OP_LOGICB; } break; case 0xd5: /* aad */ if (CODE64(s)) goto illegal_op; - val = ldub_code(s->pc++); - gen_helper_aad(tcg_const_i32(val)); + val = cpu_ldub_code(cpu_single_env, s->pc++); + gen_helper_aad(cpu_env, tcg_const_i32(val)); s->cc_op = CC_OP_LOGICB; break; /************************/ @@ -6742,14 +6818,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_fwait(); + gen_helper_fwait(cpu_env); } break; case 0xcc: /* int3 */ gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); break; case 0xcd: /* int N */ - val = ldub_code(s->pc++); + val = cpu_ldub_code(cpu_single_env, s->pc++); if (s->vm86 && s->iopl != 3) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { @@ -6762,7 +6838,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_into(tcg_const_i32(s->pc - pc_start)); + gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start)); break; #ifdef WANT_ICEBP case 0xf1: /* icebp (undocumented, exits to external debugger) */ @@ -6779,13 +6855,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0xfa: /* cli */ if (!s->vm86) { if (s->cpl <= s->iopl) { - gen_helper_cli(); + gen_helper_cli(cpu_env); } else { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } } else { if (s->iopl == 3) { - gen_helper_cli(); + gen_helper_cli(cpu_env); } else { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } @@ -6795,12 +6871,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (!s->vm86) { if (s->cpl <= s->iopl) { gen_sti: - gen_helper_sti(); + gen_helper_sti(cpu_env); /* interruptions are enabled only the first insn after sti */ /* If several instructions disable interrupts, only the _first_ does it */ if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) - gen_helper_set_inhibit_irq(); + gen_helper_set_inhibit_irq(cpu_env); /* give a chance to handle pending irqs */ gen_jmp_im(s->pc - s->cs_base); gen_eob(s); @@ -6819,7 +6895,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (CODE64(s)) goto illegal_op; ot = dflag ? OT_LONG : OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; if (mod == 3) @@ -6828,10 +6904,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_jmp_im(pc_start - s->cs_base); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - if (ot == OT_WORD) - gen_helper_boundw(cpu_A0, cpu_tmp2_i32); - else - gen_helper_boundl(cpu_A0, cpu_tmp2_i32); + if (ot == OT_WORD) { + gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32); + } else { + gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32); + } break; case 0x1c8 ... 0x1cf: /* bswap reg */ reg = (b & 7) | REX_B(s); @@ -6919,9 +6996,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); if (b & 2) { - gen_helper_rdmsr(); + gen_helper_rdmsr(cpu_env); } else { - gen_helper_wrmsr(); + gen_helper_wrmsr(cpu_env); } } break; @@ -6931,7 +7008,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_jmp_im(pc_start - s->cs_base); if (use_icount) gen_io_start(); - gen_helper_rdtsc(); + gen_helper_rdtsc(cpu_env); if (use_icount) { gen_io_end(); gen_jmp(s, s->pc - s->cs_base); @@ -6941,7 +7018,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_rdpmc(); + gen_helper_rdpmc(cpu_env); break; case 0x134: /* sysenter */ /* For Intel SYSENTER is valid on 64-bit */ @@ -6952,7 +7029,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } else { gen_update_cc_op(s); gen_jmp_im(pc_start - s->cs_base); - gen_helper_sysenter(); + gen_helper_sysenter(cpu_env); gen_eob(s); } break; @@ -6965,7 +7042,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } else { gen_update_cc_op(s); gen_jmp_im(pc_start - s->cs_base); - gen_helper_sysexit(tcg_const_i32(dflag)); + gen_helper_sysexit(cpu_env, tcg_const_i32(dflag)); gen_eob(s); } break; @@ -6974,7 +7051,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /* XXX: is it usable in real mode ? */ gen_update_cc_op(s); gen_jmp_im(pc_start - s->cs_base); - gen_helper_syscall(tcg_const_i32(s->pc - pc_start)); + gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start)); gen_eob(s); break; case 0x107: /* sysret */ @@ -6983,7 +7060,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } else { gen_update_cc_op(s); gen_jmp_im(pc_start - s->cs_base); - gen_helper_sysret(tcg_const_i32(s->dflag)); + gen_helper_sysret(cpu_env, tcg_const_i32(s->dflag)); /* condition codes are modified only in long mode */ if (s->lma) s->cc_op = CC_OP_EFLAGS; @@ -6995,7 +7072,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_cpuid(); + gen_helper_cpuid(cpu_env); break; case 0xf4: /* hlt */ if (s->cpl != 0) { @@ -7004,12 +7081,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_hlt(tcg_const_i32(s->pc - pc_start)); + gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start)); s->is_jmp = DISAS_TB_JUMP; } break; case 0x100: - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; switch(op) { @@ -7033,7 +7110,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); gen_jmp_im(pc_start - s->cs_base); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_lldt(cpu_tmp2_i32); + gen_helper_lldt(cpu_env, cpu_tmp2_i32); } break; case 1: /* str */ @@ -7056,7 +7133,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); gen_jmp_im(pc_start - s->cs_base); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_ltr(cpu_tmp2_i32); + gen_helper_ltr(cpu_env, cpu_tmp2_i32); } break; case 4: /* verr */ @@ -7066,10 +7143,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - if (op == 4) - gen_helper_verr(cpu_T[0]); - else - gen_helper_verw(cpu_T[0]); + if (op == 4) { + gen_helper_verr(cpu_env, cpu_T[0]); + } else { + gen_helper_verw(cpu_env, cpu_T[0]); + } s->cc_op = CC_OP_EFLAGS; break; default: @@ -7077,7 +7155,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } break; case 0x101: - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; rm = modrm & 7; @@ -7116,7 +7194,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_andl_A0_ffff(); } gen_add_A0_ds_seg(s); - gen_helper_monitor(cpu_A0); + gen_helper_monitor(cpu_env, cpu_A0); break; case 1: /* mwait */ if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || @@ -7124,7 +7202,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; gen_update_cc_op(s); gen_jmp_im(pc_start - s->cs_base); - gen_helper_mwait(tcg_const_i32(s->pc - pc_start)); + gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start)); gen_eob(s); break; default: @@ -7156,7 +7234,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); break; } else { - gen_helper_vmrun(tcg_const_i32(s->aflag), + gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag), tcg_const_i32(s->pc - pc_start)); tcg_gen_exit_tb(0); s->is_jmp = DISAS_TB_JUMP; @@ -7165,7 +7243,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 1: /* VMMCALL */ if (!(s->flags & HF_SVME_MASK)) goto illegal_op; - gen_helper_vmmcall(); + gen_helper_vmmcall(cpu_env); break; case 2: /* VMLOAD */ if (!(s->flags & HF_SVME_MASK) || !s->pe) @@ -7174,7 +7252,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); break; } else { - gen_helper_vmload(tcg_const_i32(s->aflag)); + gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag)); } break; case 3: /* VMSAVE */ @@ -7184,7 +7262,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); break; } else { - gen_helper_vmsave(tcg_const_i32(s->aflag)); + gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag)); } break; case 4: /* STGI */ @@ -7196,7 +7274,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); break; } else { - gen_helper_stgi(); + gen_helper_stgi(cpu_env); } break; case 5: /* CLGI */ @@ -7206,7 +7284,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); break; } else { - gen_helper_clgi(); + gen_helper_clgi(cpu_env); } break; case 6: /* SKINIT */ @@ -7214,7 +7292,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || !s->pe) goto illegal_op; - gen_helper_skinit(); + gen_helper_skinit(cpu_env); break; case 7: /* INVLPGA */ if (!(s->flags & HF_SVME_MASK) || !s->pe) @@ -7223,7 +7301,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); break; } else { - gen_helper_invlpga(tcg_const_i32(s->aflag)); + gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag)); } break; default: @@ -7264,7 +7342,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } else { gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0); gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); - gen_helper_lmsw(cpu_T[0]); + gen_helper_lmsw(cpu_env, cpu_T[0]); gen_jmp_im(s->pc - s->cs_base); gen_eob(s); } @@ -7278,7 +7356,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_helper_invlpg(cpu_A0); + gen_helper_invlpg(cpu_env, cpu_A0); gen_jmp_im(s->pc - s->cs_base); gen_eob(s); } @@ -7313,7 +7391,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_jmp_im(pc_start - s->cs_base); if (use_icount) gen_io_start(); - gen_helper_rdtscp(); + gen_helper_rdtscp(cpu_env); if (use_icount) { gen_io_end(); gen_jmp(s, s->pc - s->cs_base); @@ -7344,7 +7422,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /* d_ot is the size of destination */ d_ot = dflag + OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); @@ -7376,7 +7454,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) t1 = tcg_temp_local_new(); t2 = tcg_temp_local_new(); ot = OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; rm = modrm & 7; @@ -7424,16 +7502,17 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (!s->pe || s->vm86) goto illegal_op; ot = dflag ? OT_LONG : OT_WORD; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); t0 = tcg_temp_local_new(); if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - if (b == 0x102) - gen_helper_lar(t0, cpu_T[0]); - else - gen_helper_lsl(t0, cpu_T[0]); + if (b == 0x102) { + gen_helper_lar(t0, cpu_env, cpu_T[0]); + } else { + gen_helper_lsl(t0, cpu_env, cpu_T[0]); + } tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z); label1 = gen_new_label(); tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1); @@ -7444,7 +7523,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } break; case 0x118: - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; switch(op) { @@ -7463,7 +7542,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } break; case 0x119 ... 0x11f: /* nop (multi byte) */ - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); gen_nop_modrm(s, modrm); break; case 0x120: /* mov reg, crN */ @@ -7471,7 +7550,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); if ((modrm & 0xc0) != 0xc0) goto illegal_op; rm = (modrm & 7) | REX_B(s); @@ -7495,11 +7574,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_jmp_im(pc_start - s->cs_base); if (b & 2) { gen_op_mov_TN_reg(ot, 0, rm); - gen_helper_write_crN(tcg_const_i32(reg), cpu_T[0]); + gen_helper_write_crN(cpu_env, tcg_const_i32(reg), + cpu_T[0]); gen_jmp_im(s->pc - s->cs_base); gen_eob(s); } else { - gen_helper_read_crN(cpu_T[0], tcg_const_i32(reg)); + gen_helper_read_crN(cpu_T[0], cpu_env, tcg_const_i32(reg)); gen_op_mov_reg_T0(ot, rm); } break; @@ -7513,7 +7593,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); if ((modrm & 0xc0) != 0xc0) goto illegal_op; rm = (modrm & 7) | REX_B(s); @@ -7528,7 +7608,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (b & 2) { gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg); gen_op_mov_TN_reg(ot, 0, rm); - gen_helper_movl_drN_T0(tcg_const_i32(reg), cpu_T[0]); + gen_helper_movl_drN_T0(cpu_env, tcg_const_i32(reg), cpu_T[0]); gen_jmp_im(s->pc - s->cs_base); gen_eob(s); } else { @@ -7543,7 +7623,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0); - gen_helper_clts(); + gen_helper_clts(cpu_env); /* abort block because static cpu state changed */ gen_jmp_im(s->pc - s->cs_base); gen_eob(s); @@ -7554,7 +7634,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (!(s->cpuid_features & CPUID_SSE2)) goto illegal_op; ot = s->dflag == 2 ? OT_QUAD : OT_LONG; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; if (mod == 3) goto illegal_op; @@ -7563,7 +7643,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_ldst_modrm(s, modrm, ot, reg, 1); break; case 0x1ae: - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; switch(op) { @@ -7579,7 +7659,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_fxsave(cpu_A0, tcg_const_i32((s->dflag == 2))); + gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32((s->dflag == 2))); break; case 1: /* fxrstor */ if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || @@ -7593,7 +7673,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_helper_fxrstor(cpu_A0, tcg_const_i32((s->dflag == 2))); + gen_helper_fxrstor(cpu_env, cpu_A0, + tcg_const_i32((s->dflag == 2))); break; case 2: /* ldmxcsr */ case 3: /* stmxcsr */ @@ -7608,7 +7689,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (op == 2) { gen_op_ld_T0_A0(OT_LONG + s->mem_index); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - gen_helper_ldmxcsr(cpu_tmp2_i32); + gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32); } else { tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr)); gen_op_st_T0_A0(OT_LONG + s->mem_index); @@ -7637,7 +7718,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } break; case 0x10d: /* 3DNow! prefetch(w) */ - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); mod = (modrm >> 6) & 3; if (mod == 3) goto illegal_op; @@ -7650,7 +7731,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; gen_update_cc_op(s); gen_jmp_im(s->pc - s->cs_base); - gen_helper_rsm(); + gen_helper_rsm(cpu_env); gen_eob(s); break; case 0x1b8: /* SSE4.2 popcnt */ @@ -7660,7 +7741,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT)) goto illegal_op; - modrm = ldub_code(s->pc++); + modrm = cpu_ldub_code(cpu_single_env, s->pc++); reg = ((modrm >> 3) & 7); if (s->prefix & PREFIX_DATA) @@ -7671,7 +7752,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = OT_QUAD; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); - gen_helper_popcnt(cpu_T[0], cpu_T[0], tcg_const_i32(ot)); + gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot)); gen_op_mov_reg_T0(ot, reg); s->cc_op = CC_OP_EFLAGS; diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 5742229197..6fe4168dc0 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -27,6 +27,7 @@ #include "gdbstub.h" #include <kvm.h> #include "kvm_ppc.h" +#include "qmp-commands.h" //#define PPC_DUMP_CPU //#define PPC_DEBUG_SPR @@ -10345,6 +10346,31 @@ void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf) } } +CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) +{ + CpuDefinitionInfoList *cpu_list = NULL; + int i; + + for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) { + CpuDefinitionInfoList *entry; + CpuDefinitionInfo *info; + + if (!ppc_cpu_usable(&ppc_defs[i])) { + continue; + } + + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(ppc_defs[i].name); + + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + entry->next = cpu_list; + cpu_list = entry; + } + + return cpu_list; +} + /* CPUClass::reset() */ static void ppc_cpu_reset(CPUState *s) { diff --git a/ui/vnc.c b/ui/vnc.c index 312ad7fe36..385e345c31 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -3061,7 +3061,7 @@ int vnc_display_open(DisplayState *ds, const char *display) if (strncmp(display, "unix:", 5) == 0) vs->lsock = unix_connect(display+5); else - vs->lsock = inet_connect(display, true, NULL); + vs->lsock = inet_connect(display, true, NULL, NULL); if (-1 == vs->lsock) { g_free(vs->display); vs->display = NULL; diff --git a/vl.c b/vl.c index 91076f0e7c..d01256a6a3 100644 --- a/vl.c +++ b/vl.c @@ -1213,6 +1213,37 @@ QEMUMachine *find_default_machine(void) return NULL; } +MachineInfoList *qmp_query_machines(Error **errp) +{ + MachineInfoList *mach_list = NULL; + QEMUMachine *m; + + for (m = first_machine; m; m = m->next) { + MachineInfoList *entry; + MachineInfo *info; + + info = g_malloc0(sizeof(*info)); + if (m->is_default) { + info->has_is_default = true; + info->is_default = true; + } + + if (m->alias) { + info->has_alias = true; + info->alias = g_strdup(m->alias); + } + + info->name = g_strdup(m->name); + + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + entry->next = mach_list; + mach_list = entry; + } + + return mach_list; +} + /***********************************************************/ /* main execution loop */ @@ -1298,6 +1329,7 @@ static pid_t shutdown_pid; static int powerdown_requested; static int debug_requested; static int suspend_requested; +static int wakeup_requested; static NotifierList suspend_notifiers = NOTIFIER_LIST_INITIALIZER(suspend_notifiers); static NotifierList wakeup_notifiers = @@ -1352,6 +1384,13 @@ static int qemu_suspend_requested(void) return r; } +static int qemu_wakeup_requested(void) +{ + int r = wakeup_requested; + wakeup_requested = 0; + return r; +} + int qemu_powerdown_requested(void) { int r = powerdown_requested; @@ -1457,9 +1496,8 @@ void qemu_system_wakeup_request(WakeupReason reason) return; } runstate_set(RUN_STATE_RUNNING); - monitor_protocol_event(QEVENT_WAKEUP, NULL); notifier_list_notify(&wakeup_notifiers, &reason); - reset_requested = 1; + wakeup_requested = 1; qemu_notify_event(); } @@ -1539,6 +1577,13 @@ static bool main_loop_should_exit(void) runstate_set(RUN_STATE_PAUSED); } } + if (qemu_wakeup_requested()) { + pause_all_vcpus(); + cpu_synchronize_all_states(); + qemu_system_reset(VMRESET_SILENT); + resume_all_vcpus(); + monitor_protocol_event(QEVENT_WAKEUP, NULL); + } if (qemu_powerdown_requested()) { monitor_protocol_event(QEVENT_POWERDOWN, NULL); qemu_irq_raise(qemu_system_powerdown); |