diff options
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | block.c | 5 | ||||
-rw-r--r-- | block/mirror.c | 4 | ||||
-rw-r--r-- | blockdev.c | 2 | ||||
-rw-r--r-- | hw/net/ne2000-isa.c | 1 | ||||
-rw-r--r-- | hw/net/ne2000.c | 10 | ||||
-rw-r--r-- | hw/net/ne2000.h | 1 | ||||
-rw-r--r-- | hw/net/rtl8139.c | 111 | ||||
-rw-r--r-- | hw/net/vmxnet3.c | 1 | ||||
-rw-r--r-- | include/block/block.h | 3 | ||||
-rw-r--r-- | target-alpha/helper.h | 1 | ||||
-rw-r--r-- | target-alpha/int_helper.c | 51 | ||||
-rw-r--r-- | target-alpha/translate.c | 7 | ||||
-rw-r--r-- | tcg/aarch64/tcg-target.c | 27 | ||||
-rw-r--r-- | tcg/i386/tcg-target.c | 15 |
15 files changed, 116 insertions, 124 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 5a4bac8895..688979bc10 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1308,6 +1308,7 @@ F: block/dmg.c parallels M: Stefan Hajnoczi <stefanha@redhat.com> +M: Denis V. Lunev <den@openvz.org> L: qemu-block@nongnu.org S: Supported F: block/parallels.c @@ -4077,7 +4077,8 @@ bool bdrv_is_first_non_filter(BlockDriverState *candidate) return false; } -BlockDriverState *check_to_replace_node(const char *node_name, Error **errp) +BlockDriverState *check_to_replace_node(BlockDriverState *parent_bs, + const char *node_name, Error **errp) { BlockDriverState *to_replace_bs = bdrv_find_node(node_name); AioContext *aio_context; @@ -4100,7 +4101,7 @@ BlockDriverState *check_to_replace_node(const char *node_name, Error **errp) * Another benefit is that this tests exclude backing files which are * blocked by the backing blockers. */ - if (!bdrv_is_first_non_filter(to_replace_bs)) { + if (!bdrv_recurse_is_first_non_filter(parent_bs, to_replace_bs)) { error_setg(errp, "Only top most non filter can be replaced"); to_replace_bs = NULL; goto out; diff --git a/block/mirror.c b/block/mirror.c index 94744432eb..a2589261f5 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -644,9 +644,9 @@ static void mirror_complete(BlockJob *job, Error **errp) if (s->replaces) { AioContext *replace_aio_context; - s->to_replace = check_to_replace_node(s->replaces, &local_err); + s->to_replace = bdrv_find_node(s->replaces); if (!s->to_replace) { - error_propagate(errp, local_err); + error_setg(errp, "Node name '%s' not found", s->replaces); return; } diff --git a/blockdev.c b/blockdev.c index 4125ff642a..6b48be60ba 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2760,7 +2760,7 @@ void qmp_drive_mirror(const char *device, const char *target, goto out; } - to_replace_bs = check_to_replace_node(replaces, &local_err); + to_replace_bs = check_to_replace_node(bs, replaces, &local_err); if (!to_replace_bs) { error_propagate(errp, local_err); diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c index 17e7199f70..18b064463a 100644 --- a/hw/net/ne2000-isa.c +++ b/hw/net/ne2000-isa.c @@ -44,7 +44,6 @@ typedef struct ISANE2000State { static NetClientInfo net_ne2000_isa_info = { .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), - .can_receive = ne2000_can_receive, .receive = ne2000_receive, }; diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c index 3492db3663..53c704ad41 100644 --- a/hw/net/ne2000.c +++ b/hw/net/ne2000.c @@ -165,15 +165,6 @@ static int ne2000_buffer_full(NE2000State *s) return 0; } -int ne2000_can_receive(NetClientState *nc) -{ - NE2000State *s = qemu_get_nic_opaque(nc); - - if (s->cmd & E8390_STOP) - return 1; - return !ne2000_buffer_full(s); -} - #define MIN_BUF_SIZE 60 ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_) @@ -705,7 +696,6 @@ void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size) static NetClientInfo net_ne2000_info = { .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), - .can_receive = ne2000_can_receive, .receive = ne2000_receive, }; diff --git a/hw/net/ne2000.h b/hw/net/ne2000.h index e500306aac..d022b28fc2 100644 --- a/hw/net/ne2000.h +++ b/hw/net/ne2000.h @@ -34,7 +34,6 @@ typedef struct NE2000State { void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size); extern const VMStateDescription vmstate_ne2000; void ne2000_reset(NE2000State *s); -int ne2000_can_receive(NetClientState *nc); ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_); #endif diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index edbb61ccf3..fb2c55ce0b 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -56,6 +56,7 @@ #include "sysemu/dma.h" #include "qemu/timer.h" #include "net/net.h" +#include "net/eth.h" #include "hw/loader.h" #include "sysemu/sysemu.h" #include "qemu/iov.h" @@ -72,11 +73,8 @@ #define MOD2(input, size) \ ( ( input ) & ( size - 1 ) ) -#define ETHER_ADDR_LEN 6 #define ETHER_TYPE_LEN 2 -#define ETH_HLEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) -#define ETH_P_IP 0x0800 /* Internet Protocol packet */ -#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ +#define ETH_HLEN (ETH_ALEN * 2 + ETHER_TYPE_LEN) #define ETH_MTU 1500 #define VLAN_TCI_LEN 2 @@ -1016,8 +1014,8 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t /* write VLAN info to descriptor variables. */ if (s->CpCmd & CPlusRxVLAN && be16_to_cpup((uint16_t *) - &buf[ETHER_ADDR_LEN * 2]) == ETH_P_8021Q) { - dot1q_buf = &buf[ETHER_ADDR_LEN * 2]; + &buf[ETH_ALEN * 2]) == ETH_P_VLAN) { + dot1q_buf = &buf[ETH_ALEN * 2]; size -= VLAN_HLEN; /* if too small buffer, use the tailroom added duing expansion */ if (size < MIN_BUF_SIZE) { @@ -1058,10 +1056,10 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t /* receive/copy to target memory */ if (dot1q_buf) { - pci_dma_write(d, rx_addr, buf, 2 * ETHER_ADDR_LEN); - pci_dma_write(d, rx_addr + 2 * ETHER_ADDR_LEN, - buf + 2 * ETHER_ADDR_LEN + VLAN_HLEN, - size - 2 * ETHER_ADDR_LEN); + pci_dma_write(d, rx_addr, buf, 2 * ETH_ALEN); + pci_dma_write(d, rx_addr + 2 * ETH_ALEN, + buf + 2 * ETH_ALEN + VLAN_HLEN, + size - 2 * ETH_ALEN); } else { pci_dma_write(d, rx_addr, buf, size); } @@ -1148,7 +1146,9 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t /* if receiver buffer is empty then avail == 0 */ - if (avail != 0 && size + 8 >= avail) +#define RX_ALIGN(x) (((x) + 3) & ~0x3) + + if (avail != 0 && RX_ALIGN(size + 8) >= avail) { DPRINTF("rx overflow: rx buffer length %d head 0x%04x " "read 0x%04x === available 0x%04x need 0x%04x\n", @@ -1157,7 +1157,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t s->IntrStatus |= RxOverflow; ++s->RxMissed; rtl8139_update_irq(s); - return size_; + return 0; } packet_header |= RxStatusOK; @@ -1176,7 +1176,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t rtl8139_write_buffer(s, (uint8_t *)&val, 4); /* correct buffer write pointer */ - s->RxBufAddr = MOD2((s->RxBufAddr + 3) & ~0x3, s->RxBufferSize); + s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize); /* now we can signal we have received something */ @@ -1783,12 +1783,12 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size, return; } - if (dot1q_buf && size >= ETHER_ADDR_LEN * 2) { + if (dot1q_buf && size >= ETH_ALEN * 2) { iov = (struct iovec[3]) { - { .iov_base = buf, .iov_len = ETHER_ADDR_LEN * 2 }, + { .iov_base = buf, .iov_len = ETH_ALEN * 2 }, { .iov_base = (void *) dot1q_buf, .iov_len = VLAN_HLEN }, - { .iov_base = buf + ETHER_ADDR_LEN * 2, - .iov_len = size - ETHER_ADDR_LEN * 2 }, + { .iov_base = buf + ETH_ALEN * 2, + .iov_len = size - ETH_ALEN * 2 }, }; memcpy(vlan_iov, iov, sizeof(vlan_iov)); @@ -1868,64 +1868,12 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor) } /* structures and macros for task offloading */ -typedef struct ip_header -{ - uint8_t ip_ver_len; /* version and header length */ - uint8_t ip_tos; /* type of service */ - uint16_t ip_len; /* total length */ - uint16_t ip_id; /* identification */ - uint16_t ip_off; /* fragment offset field */ - uint8_t ip_ttl; /* time to live */ - uint8_t ip_p; /* protocol */ - uint16_t ip_sum; /* checksum */ - uint32_t ip_src,ip_dst; /* source and dest address */ -} ip_header; - -#define IP_HEADER_VERSION_4 4 -#define IP_HEADER_VERSION(ip) ((ip->ip_ver_len >> 4)&0xf) -#define IP_HEADER_LENGTH(ip) (((ip->ip_ver_len)&0xf) << 2) - -typedef struct tcp_header -{ - uint16_t th_sport; /* source port */ - uint16_t th_dport; /* destination port */ - uint32_t th_seq; /* sequence number */ - uint32_t th_ack; /* acknowledgement number */ - uint16_t th_offset_flags; /* data offset, reserved 6 bits, TCP protocol flags */ - uint16_t th_win; /* window */ - uint16_t th_sum; /* checksum */ - uint16_t th_urp; /* urgent pointer */ -} tcp_header; - -typedef struct udp_header -{ - uint16_t uh_sport; /* source port */ - uint16_t uh_dport; /* destination port */ - uint16_t uh_ulen; /* udp length */ - uint16_t uh_sum; /* udp checksum */ -} udp_header; - -typedef struct ip_pseudo_header -{ - uint32_t ip_src; - uint32_t ip_dst; - uint8_t zeros; - uint8_t ip_proto; - uint16_t ip_payload; -} ip_pseudo_header; - -#define IP_PROTO_TCP 6 -#define IP_PROTO_UDP 17 - #define TCP_HEADER_DATA_OFFSET(tcp) (((be16_to_cpu(tcp->th_offset_flags) >> 12)&0xf) << 2) #define TCP_FLAGS_ONLY(flags) ((flags)&0x3f) #define TCP_HEADER_FLAGS(tcp) TCP_FLAGS_ONLY(be16_to_cpu(tcp->th_offset_flags)) #define TCP_HEADER_CLEAR_FLAGS(tcp, off) ((tcp)->th_offset_flags &= cpu_to_be16(~TCP_FLAGS_ONLY(off))) -#define TCP_FLAG_FIN 0x01 -#define TCP_FLAG_PUSH 0x08 - /* produces ones' complement sum of data */ static uint16_t ones_complement_sum(uint8_t *data, size_t len) { @@ -2134,7 +2082,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) bswap16(txdw1 & CP_TX_VLAN_TAG_MASK)); dot1q_buffer = (uint16_t *) dot1q_buffer_space; - dot1q_buffer[0] = cpu_to_be16(ETH_P_8021Q); + dot1q_buffer[0] = cpu_to_be16(ETH_P_VLAN); /* BE + le_to_cpu() + ~cpu_to_le()~ = BE */ dot1q_buffer[1] = cpu_to_le16(txdw1 & CP_TX_VLAN_TAG_MASK); } else { @@ -2151,12 +2099,12 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) DPRINTF("+++ C+ mode offloaded task checksum\n"); /* Large enough for Ethernet and IP headers? */ - if (saved_size < ETH_HLEN + sizeof(ip_header)) { + if (saved_size < ETH_HLEN + sizeof(struct ip_header)) { goto skip_offload; } /* ip packet header */ - ip_header *ip = NULL; + struct ip_header *ip = NULL; int hlen = 0; uint8_t ip_protocol = 0; uint16_t ip_data_len = 0; @@ -2172,11 +2120,15 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) DPRINTF("+++ C+ mode has IP packet\n"); - /* not aligned */ + /* Note on memory alignment: eth_payload_data is 16-bit aligned + * since saved_buffer is allocated with g_malloc() and ETH_HLEN is + * even. 32-bit accesses must use ldl/stl wrappers to avoid + * unaligned accesses. + */ eth_payload_data = saved_buffer + ETH_HLEN; eth_payload_len = saved_size - ETH_HLEN; - ip = (ip_header*)eth_payload_data; + ip = (struct ip_header*)eth_payload_data; if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { DPRINTF("+++ C+ mode packet has bad IP version %d " @@ -2185,8 +2137,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) goto skip_offload; } - hlen = IP_HEADER_LENGTH(ip); - if (hlen < sizeof(ip_header) || hlen > eth_payload_len) { + hlen = IP_HDR_GET_LEN(ip); + if (hlen < sizeof(struct ip_header) || hlen > eth_payload_len) { goto skip_offload; } @@ -2269,7 +2221,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) } DPRINTF("+++ C+ mode TSO TCP seqno %08x\n", - be32_to_cpu(p_tcp_hdr->th_seq)); + ldl_be_p(&p_tcp_hdr->th_seq)); /* add 4 TCP pseudoheader fields */ /* copy IP source and destination fields */ @@ -2287,7 +2239,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) /* keep PUSH and FIN flags only for the last frame */ if (!is_last_frame) { - TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN); + TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TH_PUSH | TH_FIN); } /* recalculate TCP checksum */ @@ -2325,7 +2277,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) 0, (uint8_t *) dot1q_buffer); /* add transferred count to TCP sequence number */ - p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq)); + stl_be_p(&p_tcp_hdr->th_seq, + chunk_size + ldl_be_p(&p_tcp_hdr->th_seq)); ++send_count; } diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 071feebf15..04159c8222 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -1988,7 +1988,6 @@ static void vmxnet3_set_link_status(NetClientState *nc) static NetClientInfo net_vmxnet3_info = { .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), - .can_receive = vmxnet3_can_receive, .receive = vmxnet3_receive, .link_status_changed = vmxnet3_set_link_status, }; diff --git a/include/block/block.h b/include/block/block.h index 37916f7208..608cd4e4fb 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -317,7 +317,8 @@ bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs, bool bdrv_is_first_non_filter(BlockDriverState *candidate); /* check if a named node can be replaced when doing drive-mirror */ -BlockDriverState *check_to_replace_node(const char *node_name, Error **errp); +BlockDriverState *check_to_replace_node(BlockDriverState *parent_bs, + const char *node_name, Error **errp); /* async block I/O */ typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector, diff --git a/target-alpha/helper.h b/target-alpha/helper.h index 42bb247e32..c3d8a3ee49 100644 --- a/target-alpha/helper.h +++ b/target-alpha/helper.h @@ -10,6 +10,7 @@ DEF_HELPER_FLAGS_1(cttz, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_2(zap, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(zapnot, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_1(cmpbe0, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_2(cmpbge, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(minub8, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-alpha/int_helper.c b/target-alpha/int_helper.c index 74f38cbe7b..d7f4774127 100644 --- a/target-alpha/int_helper.c +++ b/target-alpha/int_helper.c @@ -58,20 +58,47 @@ uint64_t helper_zap(uint64_t val, uint64_t mask) return helper_zapnot(val, ~mask); } -uint64_t helper_cmpbge(uint64_t op1, uint64_t op2) +uint64_t helper_cmpbe0(uint64_t a) { - uint8_t opa, opb, res; - int i; + uint64_t m = 0x7f7f7f7f7f7f7f7fULL; + uint64_t c = ~(((a & m) + m) | a | m); + /* a.......b.......c.......d.......e.......f.......g.......h....... */ + c |= c << 7; + /* ab......bc......cd......de......ef......fg......gh......h....... */ + c |= c << 14; + /* abcd....bcde....cdef....defg....efgh....fgh.....gh......h....... */ + c |= c << 28; + /* abcdefghbcdefgh.cdefgh..defgh...efgh....fgh.....gh......h....... */ + return c >> 56; +} - res = 0; - for (i = 0; i < 8; i++) { - opa = op1 >> (i * 8); - opb = op2 >> (i * 8); - if (opa >= opb) { - res |= 1 << i; - } - } - return res; +uint64_t helper_cmpbge(uint64_t a, uint64_t b) +{ + uint64_t mask = 0x00ff00ff00ff00ffULL; + uint64_t test = 0x0100010001000100ULL; + uint64_t al, ah, bl, bh, cl, ch; + + /* Separate the bytes to avoid false positives. */ + al = a & mask; + bl = b & mask; + ah = (a >> 8) & mask; + bh = (b >> 8) & mask; + + /* "Compare". If a byte in B is greater than a byte in A, + it will clear the test bit. */ + cl = ((al | test) - bl) & test; + ch = ((ah | test) - bh) & test; + + /* Fold all of the test bits into a contiguous set. */ + /* ch=.......a...............c...............e...............g........ */ + /* cl=.......b...............d...............f...............h........ */ + cl += ch << 1; + /* cl=......ab..............cd..............ef..............gh........ */ + cl |= cl << 14; + /* cl=......abcd............cdef............efgh............gh........ */ + cl |= cl << 28; + /* cl=......abcdefgh........cdefgh..........efgh............gh........ */ + return cl >> 50; } uint64_t helper_minub8(uint64_t op1, uint64_t op2) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 1fd9c3be96..206feb5746 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -1562,7 +1562,12 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) break; case 0x0F: /* CMPBGE */ - gen_helper_cmpbge(vc, va, vb); + if (ra == 31) { + /* Special case 0 >= X as X == 0. */ + gen_helper_cmpbe0(vc, vb); + } else { + gen_helper_cmpbge(vc, va, vb); + } break; case 0x12: /* S8ADDL */ diff --git a/tcg/aarch64/tcg-target.c b/tcg/aarch64/tcg-target.c index 01ae610cd7..0ed10a9741 100644 --- a/tcg/aarch64/tcg-target.c +++ b/tcg/aarch64/tcg-target.c @@ -56,6 +56,11 @@ static const int tcg_target_call_oarg_regs[1] = { #define TCG_REG_TMP TCG_REG_X30 #ifndef CONFIG_SOFTMMU +/* Note that XZR cannot be encoded in the address base register slot, + as that actaully encodes SP. So if we need to zero-extend the guest + address, via the address index register slot, we need to load even + a zero guest base into a register. */ +#define USE_GUEST_BASE (guest_base != 0 || TARGET_LONG_BITS == 32) #define TCG_REG_GUEST_BASE TCG_REG_X28 #endif @@ -1224,9 +1229,13 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, add_qemu_ldst_label(s, true, oi, ext, data_reg, addr_reg, s->code_ptr, label_ptr); #else /* !CONFIG_SOFTMMU */ - tcg_out_qemu_ld_direct(s, memop, ext, data_reg, - guest_base ? TCG_REG_GUEST_BASE : TCG_REG_XZR, - otype, addr_reg); + if (USE_GUEST_BASE) { + tcg_out_qemu_ld_direct(s, memop, ext, data_reg, + TCG_REG_GUEST_BASE, otype, addr_reg); + } else { + tcg_out_qemu_ld_direct(s, memop, ext, data_reg, + addr_reg, TCG_TYPE_I64, TCG_REG_XZR); + } #endif /* CONFIG_SOFTMMU */ } @@ -1245,9 +1254,13 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, add_qemu_ldst_label(s, false, oi, (memop & MO_SIZE)== MO_64, data_reg, addr_reg, s->code_ptr, label_ptr); #else /* !CONFIG_SOFTMMU */ - tcg_out_qemu_st_direct(s, memop, data_reg, - guest_base ? TCG_REG_GUEST_BASE : TCG_REG_XZR, - otype, addr_reg); + if (USE_GUEST_BASE) { + tcg_out_qemu_st_direct(s, memop, data_reg, + TCG_REG_GUEST_BASE, otype, addr_reg); + } else { + tcg_out_qemu_st_direct(s, memop, data_reg, + addr_reg, TCG_TYPE_I64, TCG_REG_XZR); + } #endif /* CONFIG_SOFTMMU */ } @@ -1806,7 +1819,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) CPU_TEMP_BUF_NLONGS * sizeof(long)); #if !defined(CONFIG_SOFTMMU) - if (guest_base) { + if (USE_GUEST_BASE) { tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, guest_base); tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE); } diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index d2adbc4d17..9187d34caf 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -1178,8 +1178,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, const TCGReg r0 = TCG_REG_L0; const TCGReg r1 = TCG_REG_L1; TCGType ttype = TCG_TYPE_I32; - TCGType htype = TCG_TYPE_I32; - int trexw = 0, hrexw = 0; + TCGType tlbtype = TCG_TYPE_I32; + int trexw = 0, hrexw = 0, tlbrexw = 0; int s_mask = (1 << (opc & MO_SIZE)) - 1; bool aligned = (opc & MO_AMASK) == MO_ALIGN || s_mask == 0; @@ -1189,12 +1189,15 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, trexw = P_REXW; } if (TCG_TYPE_PTR == TCG_TYPE_I64) { - htype = TCG_TYPE_I64; hrexw = P_REXW; + if (TARGET_PAGE_BITS + CPU_TLB_BITS > 32) { + tlbtype = TCG_TYPE_I64; + tlbrexw = P_REXW; + } } } - tcg_out_mov(s, htype, r0, addrlo); + tcg_out_mov(s, tlbtype, r0, addrlo); if (aligned) { tcg_out_mov(s, ttype, r1, addrlo); } else { @@ -1203,12 +1206,12 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, tcg_out_modrm_offset(s, OPC_LEA + trexw, r1, addrlo, s_mask); } - tcg_out_shifti(s, SHIFT_SHR + hrexw, r0, + tcg_out_shifti(s, SHIFT_SHR + tlbrexw, r0, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); tgen_arithi(s, ARITH_AND + trexw, r1, TARGET_PAGE_MASK | (aligned ? s_mask : 0), 0); - tgen_arithi(s, ARITH_AND + hrexw, r0, + tgen_arithi(s, ARITH_AND + tlbrexw, r0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0); tcg_out_modrm_sib_offset(s, OPC_LEA + hrexw, r0, TCG_AREG0, r0, 0, |