From 2f160e0f9797c7522bfd0d09218d0c9340a5137c Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 10 Apr 2019 21:48:38 +0200 Subject: [PATCH 01/12] tci: Add implementation for INDEX_op_ld16u_i64 This fixes "make check-tcg" on a Debian x86_64 host. Signed-off-by: Stefan Weil Tested-by: Thomas Huth Message-Id: <20190410194838.10123-1-sw@weilnetz.de> Signed-off-by: Richard Henderson --- tcg/tci.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tcg/tci.c b/tcg/tci.c index 33edca1903..a6208653e8 100644 --- a/tcg/tci.c +++ b/tcg/tci.c @@ -127,6 +127,12 @@ static void tci_write_reg8(tcg_target_ulong *regs, TCGReg index, uint8_t value) tci_write_reg(regs, index, value); } +static void +tci_write_reg16(tcg_target_ulong *regs, TCGReg index, uint16_t value) +{ + tci_write_reg(regs, index, value); +} + static void tci_write_reg32(tcg_target_ulong *regs, TCGReg index, uint32_t value) { @@ -585,6 +591,8 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) tci_write_reg8(regs, t0, *(uint8_t *)(t1 + t2)); break; case INDEX_op_ld8s_i32: + TODO(); + break; case INDEX_op_ld16u_i32: TODO(); break; @@ -854,7 +862,14 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) tci_write_reg8(regs, t0, *(uint8_t *)(t1 + t2)); break; case INDEX_op_ld8s_i64: + TODO(); + break; case INDEX_op_ld16u_i64: + t0 = *tb_ptr++; + t1 = tci_read_r(regs, &tb_ptr); + t2 = tci_read_s32(&tb_ptr); + tci_write_reg16(regs, t0, *(uint16_t *)(t1 + t2)); + break; case INDEX_op_ld16s_i64: TODO(); break; From 4cef72d0425c34cca05f1df9796bd57a96318310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 21 Oct 2019 16:09:10 +0100 Subject: [PATCH 02/12] cputlb: ensure _cmmu helper functions follow the naming standard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We document this in docs/devel/load-stores.rst so lets follow it. The 32 bit and 64 bit access functions have historically not included the sign so we leave those as is. We also introduce some signed helpers which are used for loading immediate values in the translator. Fixes: 282dffc8 Reviewed-by: Richard Henderson Signed-off-by: Alex Bennée Message-Id: <20191021150910.23216-1-alex.bennee@linaro.org> Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 24 +++++++++++++++++++++--- include/exec/cpu_ldst_template.h | 4 ++-- target/cris/translate_v10.inc.c | 3 +-- tcg/tcg.h | 20 ++++++++++++++------ 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index defc8d5929..6f4194df96 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1862,12 +1862,18 @@ static uint64_t full_ldub_cmmu(CPUArchState *env, target_ulong addr, return load_helper(env, addr, oi, retaddr, MO_8, true, full_ldub_cmmu); } -uint8_t helper_ret_ldb_cmmu(CPUArchState *env, target_ulong addr, +uint8_t helper_ret_ldub_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t retaddr) { return full_ldub_cmmu(env, addr, oi, retaddr); } +int8_t helper_ret_ldsb_cmmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr) +{ + return (int8_t) full_ldub_cmmu(env, addr, oi, retaddr); +} + static uint64_t full_le_lduw_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t retaddr) { @@ -1875,12 +1881,18 @@ static uint64_t full_le_lduw_cmmu(CPUArchState *env, target_ulong addr, full_le_lduw_cmmu); } -uint16_t helper_le_ldw_cmmu(CPUArchState *env, target_ulong addr, +uint16_t helper_le_lduw_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t retaddr) { return full_le_lduw_cmmu(env, addr, oi, retaddr); } +int16_t helper_le_ldsw_cmmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr) +{ + return (int16_t) full_le_lduw_cmmu(env, addr, oi, retaddr); +} + static uint64_t full_be_lduw_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t retaddr) { @@ -1888,12 +1900,18 @@ static uint64_t full_be_lduw_cmmu(CPUArchState *env, target_ulong addr, full_be_lduw_cmmu); } -uint16_t helper_be_ldw_cmmu(CPUArchState *env, target_ulong addr, +uint16_t helper_be_lduw_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t retaddr) { return full_be_lduw_cmmu(env, addr, oi, retaddr); } +int16_t helper_be_ldsw_cmmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr) +{ + return (int16_t) full_be_lduw_cmmu(env, addr, oi, retaddr); +} + static uint64_t full_le_ldul_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t retaddr) { diff --git a/include/exec/cpu_ldst_template.h b/include/exec/cpu_ldst_template.h index af7e0b49f2..3d24ed9bd0 100644 --- a/include/exec/cpu_ldst_template.h +++ b/include/exec/cpu_ldst_template.h @@ -65,8 +65,8 @@ #ifdef SOFTMMU_CODE_ACCESS #define ADDR_READ addr_code #define MMUSUFFIX _cmmu -#define URETSUFFIX SUFFIX -#define SRETSUFFIX SUFFIX +#define URETSUFFIX USUFFIX +#define SRETSUFFIX glue(s, SUFFIX) #else #define ADDR_READ addr_read #define MMUSUFFIX _mmu diff --git a/target/cris/translate_v10.inc.c b/target/cris/translate_v10.inc.c index a87b8bb281..ae34a0d1a3 100644 --- a/target/cris/translate_v10.inc.c +++ b/target/cris/translate_v10.inc.c @@ -1202,8 +1202,7 @@ static unsigned int dec10_ind(CPUCRISState *env, DisasContext *dc) case CRISV10_IND_BCC_M: cris_cc_mask(dc, 0); - imm = cpu_ldsw_code(env, dc->pc + 2); - simm = (int16_t)imm; + simm = cpu_ldsw_code(env, dc->pc + 2); simm += 4; LOG_DIS("bcc_m: b%s %x\n", cc_name(dc->cond), dc->pc + simm); diff --git a/tcg/tcg.h b/tcg/tcg.h index a37181c899..2792f65d04 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -1269,16 +1269,22 @@ void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, TCGMemOpIdx oi, uintptr_t retaddr); -uint8_t helper_ret_ldb_cmmu(CPUArchState *env, target_ulong addr, +uint8_t helper_ret_ldub_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t retaddr); -uint16_t helper_le_ldw_cmmu(CPUArchState *env, target_ulong addr, +int8_t helper_ret_ldsb_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t retaddr); +uint16_t helper_le_lduw_cmmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +int16_t helper_le_ldsw_cmmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); uint32_t helper_le_ldl_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t retaddr); uint64_t helper_le_ldq_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t retaddr); -uint16_t helper_be_ldw_cmmu(CPUArchState *env, target_ulong addr, - TCGMemOpIdx oi, uintptr_t retaddr); +uint16_t helper_be_lduw_cmmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); +int16_t helper_be_ldsw_cmmu(CPUArchState *env, target_ulong addr, + TCGMemOpIdx oi, uintptr_t retaddr); uint32_t helper_be_ldl_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uintptr_t retaddr); uint64_t helper_be_ldq_cmmu(CPUArchState *env, target_ulong addr, @@ -1295,7 +1301,8 @@ uint64_t helper_be_ldq_cmmu(CPUArchState *env, target_ulong addr, # define helper_ret_stw_mmu helper_be_stw_mmu # define helper_ret_stl_mmu helper_be_stl_mmu # define helper_ret_stq_mmu helper_be_stq_mmu -# define helper_ret_ldw_cmmu helper_be_ldw_cmmu +# define helper_ret_lduw_cmmu helper_be_lduw_cmmu +# define helper_ret_ldsw_cmmu helper_be_ldsw_cmmu # define helper_ret_ldl_cmmu helper_be_ldl_cmmu # define helper_ret_ldq_cmmu helper_be_ldq_cmmu #else @@ -1308,7 +1315,8 @@ uint64_t helper_be_ldq_cmmu(CPUArchState *env, target_ulong addr, # define helper_ret_stw_mmu helper_le_stw_mmu # define helper_ret_stl_mmu helper_le_stl_mmu # define helper_ret_stq_mmu helper_le_stq_mmu -# define helper_ret_ldw_cmmu helper_le_ldw_cmmu +# define helper_ret_lduw_cmmu helper_le_lduw_cmmu +# define helper_ret_ldsw_cmmu helper_le_ldsw_cmmu # define helper_ret_ldl_cmmu helper_le_ldl_cmmu # define helper_ret_ldq_cmmu helper_le_ldq_cmmu #endif From 50276a79aa15713decfede5cab183fc371e3e57d Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Sun, 13 Oct 2019 10:11:44 +0800 Subject: [PATCH 03/12] cpu: use ROUND_UP() to define xxx_PAGE_ALIGN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use ROUND_UP() to define, which is a little bit easy to read. Reviewed-by: Alex Bennée Reviewed-by: Michael S. Tsirkin Reviewed-by: David Gibson Reviewed-by: Juan Quintela Signed-off-by: Wei Yang Message-Id: <20191013021145.16011-2-richardw.yang@linux.intel.com> Signed-off-by: Richard Henderson --- include/exec/cpu-all.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index ad9ab85eb3..255bb186ac 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -220,7 +220,7 @@ extern int target_page_bits; #define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS) #define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1) -#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK) +#define TARGET_PAGE_ALIGN(addr) ROUND_UP((addr), TARGET_PAGE_SIZE) /* Using intptr_t ensures that qemu_*_page_mask is sign-extended even * when intptr_t is 32-bit and we are aligning a long long. @@ -228,9 +228,8 @@ extern int target_page_bits; extern uintptr_t qemu_host_page_size; extern intptr_t qemu_host_page_mask; -#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask) -#define REAL_HOST_PAGE_ALIGN(addr) (((addr) + qemu_real_host_page_size - 1) & \ - qemu_real_host_page_mask) +#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size) +#define REAL_HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_real_host_page_size) /* same as PROT_xxx */ #define PAGE_READ 0x0001 From 7886cefe5ddd238c64d07eb037804f1aef24755c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 19 Sep 2019 13:30:29 -0700 Subject: [PATCH 04/12] exec: Split out variable page size support to exec-vary.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The next patch will play a trick with "const" that will confuse the compiler about the uses of target_page_bits within exec.c. Moving everything to a new file prevents this confusion. No functional change so far. Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Paolo Bonzini Signed-off-by: Richard Henderson --- Makefile.target | 2 +- exec-vary.c | 57 +++++++++++++++++++++++++++++++++++++++++++ exec.c | 34 -------------------------- include/qemu-common.h | 6 +++++ 4 files changed, 64 insertions(+), 35 deletions(-) create mode 100644 exec-vary.c diff --git a/Makefile.target b/Makefile.target index 5e916230c4..ca3d14efe1 100644 --- a/Makefile.target +++ b/Makefile.target @@ -107,7 +107,7 @@ obj-y += trace/ ######################################################### # cpu emulator library -obj-y += exec.o +obj-y += exec.o exec-vary.o obj-y += accel/ obj-$(CONFIG_TCG) += tcg/tcg.o tcg/tcg-op.o tcg/tcg-op-vec.o tcg/tcg-op-gvec.o obj-$(CONFIG_TCG) += tcg/tcg-common.o tcg/optimize.o diff --git a/exec-vary.c b/exec-vary.c new file mode 100644 index 0000000000..48c0ab306c --- /dev/null +++ b/exec-vary.c @@ -0,0 +1,57 @@ +/* + * Variable page size handling + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "exec/exec-all.h" + +#ifdef TARGET_PAGE_BITS_VARY +int target_page_bits; +bool target_page_bits_decided; +#endif + +bool set_preferred_target_page_bits(int bits) +{ + /* + * The target page size is the lowest common denominator for all + * the CPUs in the system, so we can only make it smaller, never + * larger. And we can't make it smaller once we've committed to + * a particular size. + */ +#ifdef TARGET_PAGE_BITS_VARY + assert(bits >= TARGET_PAGE_BITS_MIN); + if (target_page_bits == 0 || target_page_bits > bits) { + if (target_page_bits_decided) { + return false; + } + target_page_bits = bits; + } +#endif + return true; +} + +void finalize_target_page_bits(void) +{ +#ifdef TARGET_PAGE_BITS_VARY + if (target_page_bits == 0) { + target_page_bits = TARGET_PAGE_BITS_MIN; + } + target_page_bits_decided = true; +#endif +} diff --git a/exec.c b/exec.c index fb0943cfed..5bf181d23e 100644 --- a/exec.c +++ b/exec.c @@ -91,11 +91,6 @@ AddressSpace address_space_memory; static MemoryRegion io_mem_unassigned; #endif -#ifdef TARGET_PAGE_BITS_VARY -int target_page_bits; -bool target_page_bits_decided; -#endif - CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus); /* current CPU in the current thread. It is only valid inside @@ -109,37 +104,8 @@ int use_icount; uintptr_t qemu_host_page_size; intptr_t qemu_host_page_mask; -bool set_preferred_target_page_bits(int bits) -{ - /* The target page size is the lowest common denominator for all - * the CPUs in the system, so we can only make it smaller, never - * larger. And we can't make it smaller once we've committed to - * a particular size. - */ -#ifdef TARGET_PAGE_BITS_VARY - assert(bits >= TARGET_PAGE_BITS_MIN); - if (target_page_bits == 0 || target_page_bits > bits) { - if (target_page_bits_decided) { - return false; - } - target_page_bits = bits; - } -#endif - return true; -} - #if !defined(CONFIG_USER_ONLY) -static void finalize_target_page_bits(void) -{ -#ifdef TARGET_PAGE_BITS_VARY - if (target_page_bits == 0) { - target_page_bits = TARGET_PAGE_BITS_MIN; - } - target_page_bits_decided = true; -#endif -} - typedef struct PhysPageEntry PhysPageEntry; struct PhysPageEntry { diff --git a/include/qemu-common.h b/include/qemu-common.h index 8d84db90b0..082da59e85 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -74,6 +74,12 @@ void cpu_exec_step_atomic(CPUState *cpu); */ bool set_preferred_target_page_bits(int bits); +/** + * finalize_target_page_bits: + * Commit the final value set by set_preferred_target_page_bits. + */ +void finalize_target_page_bits(void); + /** * Sends a (part of) iovec down a socket, yielding when the socket is full, or * Receives data into a (part of) iovec from a socket, From db8aaae822dfdb18d993a686a146efcc63c216c0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 13 Oct 2019 16:12:19 -0700 Subject: [PATCH 05/12] configure: Detect compiler support for __attribute__((alias)) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Such support is present almost everywhere, except for Xcode 9. It is added in Xcode 10, but travis uses xcode9 by default, so we should support it for a while yet. Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson --- configure | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/configure b/configure index 145fcabbb3..3a9862fe5e 100755 --- a/configure +++ b/configure @@ -5518,6 +5518,21 @@ if compile_prog "" "" ; then vector16=yes fi +######################################## +# See if __attribute__((alias)) is supported. +# This false for Xcode 9, but has been remedied for Xcode 10. +# Unfortunately, travis uses Xcode 9 by default. + +attralias=no +cat > $TMPC << EOF +int x = 1; +extern const int y __attribute__((alias("x"))); +int main(void) { return 0; } +EOF +if compile_prog "" "" ; then + attralias=yes +fi + ######################################## # check if getauxval is available. @@ -7083,6 +7098,10 @@ if test "$vector16" = "yes" ; then echo "CONFIG_VECTOR16=y" >> $config_host_mak fi +if test "$attralias" = "yes" ; then + echo "CONFIG_ATTRIBUTE_ALIAS=y" >> $config_host_mak +fi + if test "$getauxval" = "yes" ; then echo "CONFIG_GETAUXVAL=y" >> $config_host_mak fi From bbc17caf81f94523e67c64a6e6cd8f869b7a1da5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 13 Sep 2019 11:21:53 -0400 Subject: [PATCH 06/12] exec: Use const alias for TARGET_PAGE_BITS_VARY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a variable that is declared "const" for this tells the compiler that it may read the value once and assume that it does not change across function calls. For target_page_size, this means we have only one assert per function, and one read of the variable. This reduces the size of qemu-system-aarch64 by 8k. Reviewed-by: Alex Bennée Reviewed-by: Paolo Bonzini Signed-off-by: Richard Henderson --- exec-vary.c | 66 +++++++++++++++++++++++++++++++++++++----- include/exec/cpu-all.h | 14 ++++++--- 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/exec-vary.c b/exec-vary.c index 48c0ab306c..8725fd0285 100644 --- a/exec-vary.c +++ b/exec-vary.c @@ -19,11 +19,55 @@ #include "qemu/osdep.h" #include "qemu-common.h" + +#define IN_EXEC_VARY 1 + #include "exec/exec-all.h" #ifdef TARGET_PAGE_BITS_VARY -int target_page_bits; -bool target_page_bits_decided; +# ifdef CONFIG_ATTRIBUTE_ALIAS +/* + * We want to declare the "target_page" variable as const, which tells + * the compiler that it can cache any value that it reads across calls. + * This avoids multiple assertions and multiple reads within any one user. + * + * This works because we finish initializing the data before we ever read + * from the "target_page" symbol. + * + * This also requires that we have a non-constant symbol by which we can + * perform the actual initialization, and which forces the data to be + * allocated within writable memory. Thus "init_target_page", and we use + * that symbol exclusively in the two functions that initialize this value. + * + * The "target_page" symbol is created as an alias of "init_target_page". + */ +static TargetPageBits init_target_page; + +/* + * Note that this is *not* a redundant decl, this is the definition of + * the "target_page" symbol. The syntax for this definition requires + * the use of the extern keyword. This seems to be a GCC bug in + * either the syntax for the alias attribute or in -Wredundant-decls. + * + * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91765 + */ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wredundant-decls" + +extern const TargetPageBits target_page + __attribute__((alias("init_target_page"))); + +# pragma GCC diagnostic pop +# else +/* + * When aliases are not supported then we force two different declarations, + * by way of suppressing the header declaration with IN_EXEC_VARY. + * We assume that on such an old compiler, LTO cannot be used, and so the + * compiler cannot not detect the mismatched declarations, and all is well. + */ +TargetPageBits target_page; +# define init_target_page target_page +# endif #endif bool set_preferred_target_page_bits(int bits) @@ -36,11 +80,11 @@ bool set_preferred_target_page_bits(int bits) */ #ifdef TARGET_PAGE_BITS_VARY assert(bits >= TARGET_PAGE_BITS_MIN); - if (target_page_bits == 0 || target_page_bits > bits) { - if (target_page_bits_decided) { + if (init_target_page.bits == 0 || init_target_page.bits > bits) { + if (init_target_page.decided) { return false; } - target_page_bits = bits; + init_target_page.bits = bits; } #endif return true; @@ -49,9 +93,15 @@ bool set_preferred_target_page_bits(int bits) void finalize_target_page_bits(void) { #ifdef TARGET_PAGE_BITS_VARY - if (target_page_bits == 0) { - target_page_bits = TARGET_PAGE_BITS_MIN; + if (init_target_page.bits == 0) { + init_target_page.bits = TARGET_PAGE_BITS_MIN; } - target_page_bits_decided = true; + init_target_page.decided = true; + + /* + * For the benefit of an -flto build, prevent the compiler from + * hoisting a read from target_page before we finish initializing. + */ + barrier(); #endif } diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 255bb186ac..0b449b98ba 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -210,10 +210,16 @@ static inline void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val /* page related stuff */ #ifdef TARGET_PAGE_BITS_VARY -extern bool target_page_bits_decided; -extern int target_page_bits; -#define TARGET_PAGE_BITS ({ assert(target_page_bits_decided); \ - target_page_bits; }) +typedef struct { + bool decided; + int bits; +} TargetPageBits; +#if defined(CONFIG_ATTRIBUTE_ALIAS) || !defined(IN_EXEC_VARY) +extern const TargetPageBits target_page; +#else +extern TargetPageBits target_page; +#endif +#define TARGET_PAGE_BITS ({ assert(target_page.decided); target_page.bits; }) #else #define TARGET_PAGE_BITS_MIN TARGET_PAGE_BITS #endif From 639044b5f121a44909eca929d7fd6d070024b9f9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 13 Sep 2019 11:41:51 -0400 Subject: [PATCH 07/12] exec: Restrict TARGET_PAGE_BITS_VARY assert to CONFIG_DEBUG_TCG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reduces the size of a release build by about 10k. Noticably, within the tlb miss helpers. Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Paolo Bonzini Signed-off-by: Richard Henderson --- include/exec/cpu-all.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 0b449b98ba..525059970c 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -219,8 +219,12 @@ extern const TargetPageBits target_page; #else extern TargetPageBits target_page; #endif +#ifdef CONFIG_DEBUG_TCG #define TARGET_PAGE_BITS ({ assert(target_page.decided); target_page.bits; }) #else +#define TARGET_PAGE_BITS target_page.bits +#endif +#else #define TARGET_PAGE_BITS_MIN TARGET_PAGE_BITS #endif From f048b8a7cefcabb0e55210a76775f9be57c4d3f4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 15 Oct 2019 11:10:27 -0700 Subject: [PATCH 08/12] exec: Promote TARGET_PAGE_MASK to target_long MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are some uint64_t uses that expect TARGET_PAGE_MASK to extend for a 32-bit, so this must continue to be a signed type. Define based on TARGET_PAGE_BITS not TARGET_PAGE_SIZE; this will make a following patch more clear. This should not have a functional effect so far. Reviewed-by: Alex Bennée Reviewed-by: Paolo Bonzini Signed-off-by: Richard Henderson --- include/exec/cpu-all.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 525059970c..0543359d0f 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -229,7 +229,7 @@ extern TargetPageBits target_page; #endif #define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS) -#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1) +#define TARGET_PAGE_MASK ((target_long)-1 << TARGET_PAGE_BITS) #define TARGET_PAGE_ALIGN(addr) ROUND_UP((addr), TARGET_PAGE_SIZE) /* Using intptr_t ensures that qemu_*_page_mask is sign-extended even From bb8e3ea6fa8f616678133c9e8c8c3bf232c179ec Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 13 Sep 2019 12:07:40 -0400 Subject: [PATCH 09/12] exec: Cache TARGET_PAGE_MASK for TARGET_PAGE_BITS_VARY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This eliminates a set of runtime shifts. It turns out that we require TARGET_PAGE_MASK more often than TARGET_PAGE_SIZE, so redefine TARGET_PAGE_SIZE based on TARGET_PAGE_MASK instead of the other way around. Reviewed-by: Alex Bennée Reviewed-by: David Hildenbrand Reviewed-by: Paolo Bonzini Signed-off-by: Richard Henderson --- exec-vary.c | 1 + include/exec/cpu-all.h | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/exec-vary.c b/exec-vary.c index 8725fd0285..ff905f2a8f 100644 --- a/exec-vary.c +++ b/exec-vary.c @@ -96,6 +96,7 @@ void finalize_target_page_bits(void) if (init_target_page.bits == 0) { init_target_page.bits = TARGET_PAGE_BITS_MIN; } + init_target_page.mask = (target_long)-1 << init_target_page.bits; init_target_page.decided = true; /* diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 0543359d0f..e96781a455 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -213,6 +213,7 @@ static inline void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val typedef struct { bool decided; int bits; + target_long mask; } TargetPageBits; #if defined(CONFIG_ATTRIBUTE_ALIAS) || !defined(IN_EXEC_VARY) extern const TargetPageBits target_page; @@ -221,15 +222,18 @@ extern TargetPageBits target_page; #endif #ifdef CONFIG_DEBUG_TCG #define TARGET_PAGE_BITS ({ assert(target_page.decided); target_page.bits; }) +#define TARGET_PAGE_MASK ({ assert(target_page.decided); target_page.mask; }) #else #define TARGET_PAGE_BITS target_page.bits +#define TARGET_PAGE_MASK target_page.mask #endif +#define TARGET_PAGE_SIZE (-(int)TARGET_PAGE_MASK) #else #define TARGET_PAGE_BITS_MIN TARGET_PAGE_BITS +#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS) +#define TARGET_PAGE_MASK ((target_long)-1 << TARGET_PAGE_BITS) #endif -#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS) -#define TARGET_PAGE_MASK ((target_long)-1 << TARGET_PAGE_BITS) #define TARGET_PAGE_ALIGN(addr) ROUND_UP((addr), TARGET_PAGE_SIZE) /* Using intptr_t ensures that qemu_*_page_mask is sign-extended even From 7f445c8c7aad0d8fca7d99a48cc8118dc82aa0f3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 3 Sep 2019 17:03:12 -0700 Subject: [PATCH 10/12] cputlb: Fix tlb_vaddr_to_host Using uintptr_t instead of target_ulong meant that, for 64-bit guest and 32-bit host, we truncated the guest address comparator and so may not hit the tlb when we should. Fixes: 4811e9095c0 Reviewed-by: David Hildenbrand Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 6f4194df96..5eebddcca8 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1189,7 +1189,7 @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, MMUAccessType access_type, int mmu_idx) { CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); - uintptr_t tlb_addr, page; + target_ulong tlb_addr, page; size_t elt_ofs; switch (access_type) { From 1b1940026c95b941d9cf75bd38b37fe3feaa78a7 Mon Sep 17 00:00:00 2001 From: Clement Deschamps Date: Tue, 22 Oct 2019 16:00:16 +0200 Subject: [PATCH 11/12] translate-all: fix uninitialized tb->orig_tb This fixes a segmentation fault in icount mode when executing from an IO region. TB is marked as CF_NOCACHE but tb->orig_tb is not initialized (equals previous value in code_gen_buffer). The issue happens in cpu_io_recompile() when it tries to invalidate orig_tb. Reviewed-by: Richard Henderson Signed-off-by: Clement Deschamps Message-Id: <20191022140016.918371-1-clement.deschamps@greensocs.com> Signed-off-by: Richard Henderson --- accel/tcg/translate-all.c | 1 + 1 file changed, 1 insertion(+) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 66d4bc4341..f9b7ba159d 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1722,6 +1722,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tb->cs_base = cs_base; tb->flags = flags; tb->cflags = cflags; + tb->orig_tb = NULL; tb->trace_vcpu_dstate = *cpu->trace_dstate; tcg_ctx->tb_cflags = cflags; tb_overflow: From fe9b676fb3160496b4b2bf0c57d33be724bf04c3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 23 Oct 2019 12:20:47 -0400 Subject: [PATCH 12/12] translate-all: Remove tb_alloc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since 2ac01d6dafab, this function does only two things: assert a lock is held, and call tcg_tb_alloc. It is used exactly once, and its user has already done the assert. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Clement Deschamps Signed-off-by: Richard Henderson --- accel/tcg/translate-all.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index f9b7ba159d..ae063b53f9 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1156,23 +1156,6 @@ void tcg_exec_init(unsigned long tb_size) #endif } -/* - * Allocate a new translation block. Flush the translation buffer if - * too many translation blocks or too much generated code. - */ -static TranslationBlock *tb_alloc(target_ulong pc) -{ - TranslationBlock *tb; - - assert_memory_lock(); - - tb = tcg_tb_alloc(tcg_ctx); - if (unlikely(tb == NULL)) { - return NULL; - } - return tb; -} - /* call with @p->lock held */ static inline void invalidate_page_bitmap(PageDesc *p) { @@ -1681,6 +1664,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, TCGProfile *prof = &tcg_ctx->prof; int64_t ti; #endif + assert_memory_lock(); phys_pc = get_page_addr_code(env, pc); @@ -1706,7 +1690,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, } buffer_overflow: - tb = tb_alloc(pc); + tb = tcg_tb_alloc(tcg_ctx); if (unlikely(!tb)) { /* flush must be done */ tb_flush(cpu);