[PULL 01/37] bsd-user/mips*: Remove mips support

2022-01-07 Thread Warner Losh
FreeBSD is dropping support for mips starting with FreeBSD 14. mips
support has been removed from the bsd-user fork because updating it for
new signal requirements will take too much time. Remove it here since it
is a distraction.

Signed-off-by: Warner Losh 
Acked-by: Richard Henderson 
---
 bsd-user/mips/target_arch_sysarch.h   | 69 ---
 bsd-user/mips/target_syscall.h| 52 
 bsd-user/mips64/target_arch_sysarch.h | 69 ---
 bsd-user/mips64/target_syscall.h  | 53 
 4 files changed, 243 deletions(-)
 delete mode 100644 bsd-user/mips/target_arch_sysarch.h
 delete mode 100644 bsd-user/mips/target_syscall.h
 delete mode 100644 bsd-user/mips64/target_arch_sysarch.h
 delete mode 100644 bsd-user/mips64/target_syscall.h

diff --git a/bsd-user/mips/target_arch_sysarch.h 
b/bsd-user/mips/target_arch_sysarch.h
deleted file mode 100644
index 6da803a408e..000
--- a/bsd-user/mips/target_arch_sysarch.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  mips sysarch() system call emulation
- *
- *  Copyright (c) 2013 Stacey D. Son
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, see .
- */
-
-#ifndef BSD_USER_ARCH_SYSARCH_H_
-#define BSD_USER_ARCH_SYSARCH_H_
-
-#include "target_syscall.h"
-#include "target_arch.h"
-
-static inline abi_long do_freebsd_arch_sysarch(CPUMIPSState *env, int op,
-abi_ulong parms)
-{
-int ret = 0;
-
-switch (op) {
-case TARGET_MIPS_SET_TLS:
-target_cpu_set_tls(env, parms);
-break;
-
-case TARGET_MIPS_GET_TLS:
-if (put_user(target_cpu_get_tls(env), parms, abi_ulong)) {
-ret = -TARGET_EFAULT;
-}
-break;
-
-default:
-ret = -TARGET_EINVAL;
-break;
-}
-
-return ret;
-}
-
-static inline void do_freebsd_arch_print_sysarch(
-const struct syscallname *name, abi_long arg1, abi_long arg2,
-abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
-{
-
-switch (arg1) {
-case TARGET_MIPS_SET_TLS:
-gemu_log("%s(SET_TLS, 0x" TARGET_ABI_FMT_lx ")", name->name, arg2);
-break;
-
-case TARGET_MIPS_GET_TLS:
-gemu_log("%s(GET_TLS, 0x" TARGET_ABI_FMT_lx ")", name->name, arg2);
-break;
-
-default:
-gemu_log("UNKNOWN OP: %d, " TARGET_ABI_FMT_lx ")", (int)arg1, arg2);
-}
-}
-
-#endif /*!BSD_USER_ARCH_SYSARCH_H_ */
diff --git a/bsd-user/mips/target_syscall.h b/bsd-user/mips/target_syscall.h
deleted file mode 100644
index aacc6ddf9fc..000
--- a/bsd-user/mips/target_syscall.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *  mips system call definitions
- *
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, see .
- */
-#ifndef _MIPS_SYSCALL_H_
-#define _MIPS_SYSCALL_H_
-
-/*
- * struct target_pt_regs defines the way the registers are stored on the stack
- * during a system call.
- */
-
-struct target_pt_regs {
-/* Saved main processor registers. */
-abi_ulong regs[32];
-
-/* Saved special registers. */
-abi_ulong cp0_status;
-abi_ulong lo;
-abi_ulong hi;
-abi_ulong cp0_badvaddr;
-abi_ulong cp0_cause;
-abi_ulong cp0_epc;
-};
-
-#if defined(TARGET_WORDS_BIGENDIAN)
-#define UNAME_MACHINE "mips"
-#else
-#define UNAME_MACHINE "mipsel"
-#endif
-
-#define TARGET_HW_MACHINE   "mips"
-#define TARGET_HW_MACHINE_ARCH   UNAME_MACHINE
-
-/* sysarch() commands */
-#define TARGET_MIPS_SET_TLS 1
-#define TARGET_MIPS_GET_TLS 2
-
-#endif /* !_MIPS_SYSCALL_H_ */
diff --git a/bsd-user/mips64/target_arch_sysarch.h 
b/bsd-user/mips64/target_arch_sysarch.h
deleted file mode 100644
index e6f9c00d5f6..000
--- a/bsd-user/mips64/target_arch_sysarch.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  mips64 sysarch() system call 

[PATCH v4 04/12] tcg/mips: Move TCG_GUEST_BASE_REG to S7

2022-01-07 Thread Richard Henderson
No functional change; just moving the saved reserved regs to the end.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c.inc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 5702a6ad92..1bfe6aea0e 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -86,7 +86,7 @@ static const char * const 
tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 #define TCG_TMP3  TCG_REG_T7
 
 #ifndef CONFIG_SOFTMMU
-#define TCG_GUEST_BASE_REG TCG_REG_S1
+#define TCG_GUEST_BASE_REG TCG_REG_S7
 #endif
 
 /* check if we really need so many registers :P */
@@ -2555,7 +2555,7 @@ static const int tcg_target_callee_save_regs[] = {
 TCG_REG_S4,
 TCG_REG_S5,
 TCG_REG_S6,
-TCG_REG_S7,
+TCG_REG_S7,   /* used for guest_base */
 TCG_REG_S8,   /* used for the global env (TCG_AREG0) */
 TCG_REG_RA,   /* should be last for ABI compliance */
 };
-- 
2.25.1




[PULL 08/37] bsd-user/x86_64/target_arch_signal.h: Remove target_sigcontext

2022-01-07 Thread Warner Losh
In FreeBSD, sigcontext was retired in favor of ucontext/mcontext.
Remove vestigial target_sigcontext.

Signed-off-by: Warner Losh 
Reviewed-by: Richard Henderson 
---
 bsd-user/x86_64/target_arch_signal.h | 4 
 1 file changed, 4 deletions(-)

diff --git a/bsd-user/x86_64/target_arch_signal.h 
b/bsd-user/x86_64/target_arch_signal.h
index 4bb753b08bb..55f742b0a8c 100644
--- a/bsd-user/x86_64/target_arch_signal.h
+++ b/bsd-user/x86_64/target_arch_signal.h
@@ -27,10 +27,6 @@
 #define TARGET_MINSIGSTKSZ  (512 * 4)   /* min sig stack size */
 #define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768)   /* recommended size */
 
-struct target_sigcontext {
-/* to be added */
-};
-
 typedef struct target_mcontext {
 } target_mcontext_t;
 
-- 
2.33.1




[PULL 10/37] bsd-user/x86_64/target_arch_signal.h: Fill in mcontext_t

2022-01-07 Thread Warner Losh
Fill in target_mcontext match the FreeBSD mcontext_t structure. Also
define the size correctly.

Signed-off-by: Warner Losh 
Reviewed-by: Richard Henderson 
---
 bsd-user/x86_64/target_arch_signal.h | 54 
 1 file changed, 54 insertions(+)

diff --git a/bsd-user/x86_64/target_arch_signal.h 
b/bsd-user/x86_64/target_arch_signal.h
index e84aff948c5..720e3939c31 100644
--- a/bsd-user/x86_64/target_arch_signal.h
+++ b/bsd-user/x86_64/target_arch_signal.h
@@ -28,8 +28,62 @@
 #define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768)   /* recommended size */
 
 typedef struct target_mcontext {
+abi_ulong   mc_onstack; /* XXX - sigcontext compat. */
+abi_ulong   mc_rdi; /* machine state (struct trapframe) */
+abi_ulong   mc_rsi;
+abi_ulong   mc_rdx;
+abi_ulong   mc_rcx;
+abi_ulong   mc_r8;
+abi_ulong   mc_r9;
+abi_ulong   mc_rax;
+abi_ulong   mc_rbx;
+abi_ulong   mc_rbp;
+abi_ulong   mc_r10;
+abi_ulong   mc_r11;
+abi_ulong   mc_r12;
+abi_ulong   mc_r13;
+abi_ulong   mc_r14;
+abi_ulong   mc_r15;
+uint32_tmc_trapno;
+uint16_tmc_fs;
+uint16_tmc_gs;
+abi_ulong   mc_addr;
+uint32_tmc_flags;
+uint16_tmc_es;
+uint16_tmc_ds;
+abi_ulong   mc_err;
+abi_ulong   mc_rip;
+abi_ulong   mc_cs;
+abi_ulong   mc_rflags;
+abi_ulong   mc_rsp;
+abi_ulong   mc_ss;
+
+abi_longmc_len; /* sizeof(mcontext_t) */
+
+#define _MC_FPFMT_NODEV 0x1 /* device not present or configured */
+#define _MC_FPFMT_XMM   0x10002
+abi_longmc_fpformat;
+#define _MC_FPOWNED_NONE0x2 /* FP state not used */
+#define _MC_FPOWNED_FPU 0x20001 /* FP state came from FPU */
+#define _MC_FPOWNED_PCB 0x20002 /* FP state came from PCB */
+abi_longmc_ownedfp;
+/*
+ * See  for the internals of mc_fpstate[].
+ */
+abi_longmc_fpstate[64] __aligned(16);
+
+abi_ulong   mc_fsbase;
+abi_ulong   mc_gsbase;
+
+abi_ulong   mc_xfpustate;
+abi_ulong   mc_xfpustate_len;
+
+abi_longmc_spare[4];
 } target_mcontext_t;
 
+#define TARGET_MCONTEXT_SIZE 800
+#define TARGET_UCONTEXT_SIZE 880
+
 #include "target_os_ucontext.h"
 
 struct target_sigframe {
-- 
2.33.1




[PATCH v4 09/12] tcg/mips: Use the constant pool for 64-bit constants

2022-01-07 Thread Richard Henderson
During normal processing, the constant pool is accessible via
TCG_REG_TB.  During the prologue, it is accessible via TCG_REG_T9.

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.h |  1 +
 tcg/mips/tcg-target.c.inc | 65 +--
 2 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 28c42e23e1..839364b493 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -208,5 +208,6 @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, 
uintptr_t, uintptr_t)
 QEMU_ERROR("code path is reachable");
 
 #define TCG_TARGET_NEED_LDST_LABELS
+#define TCG_TARGET_NEED_POOL_LABELS
 
 #endif
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 142583b613..41cb155eb0 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -25,6 +25,7 @@
  */
 
 #include "../tcg-ldst.c.inc"
+#include "../tcg-pool.c.inc"
 
 #ifdef HOST_WORDS_BIGENDIAN
 # define MIPS_BE  1
@@ -166,9 +167,18 @@ static bool reloc_pc16(tcg_insn_unit *src_rw, const 
tcg_insn_unit *target)
 static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
 intptr_t value, intptr_t addend)
 {
-tcg_debug_assert(type == R_MIPS_PC16);
-tcg_debug_assert(addend == 0);
-return reloc_pc16(code_ptr, (const tcg_insn_unit *)value);
+value += addend;
+switch (type) {
+case R_MIPS_PC16:
+return reloc_pc16(code_ptr, (const tcg_insn_unit *)value);
+case R_MIPS_16:
+if (value != (int16_t)value) {
+return false;
+}
+*code_ptr = deposit32(*code_ptr, 0, 16, value);
+return true;
+}
+g_assert_not_reached();
 }
 
 #define TCG_CT_CONST_ZERO 0x100
@@ -500,6 +510,11 @@ static void tcg_out_nop(TCGContext *s)
 tcg_out32(s, 0);
 }
 
+static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
+{
+memset(p, 0, count * sizeof(tcg_insn_unit));
+}
+
 static void tcg_out_dsll(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
 {
 tcg_out_opc_sa64(s, OPC_DSLL, OPC_DSLL32, rd, rt, sa);
@@ -557,8 +572,15 @@ static bool tcg_out_movi_two(TCGContext *s, TCGReg ret, 
tcg_target_long arg)
 return false;
 }
 
-static void tcg_out_movi(TCGContext *s, TCGType type,
- TCGReg ret, tcg_target_long arg)
+static void tcg_out_movi_pool(TCGContext *s, TCGReg ret,
+  tcg_target_long arg, TCGReg tbreg)
+{
+new_pool_label(s, arg, R_MIPS_16, s->code_ptr, tcg_tbrel_diff(s, NULL));
+tcg_out_opc_imm(s, OPC_LD, ret, tbreg, 0);
+}
+
+static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret,
+ tcg_target_long arg, TCGReg tbreg)
 {
 if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
 arg = (int32_t)arg;
@@ -568,18 +590,17 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
 if (tcg_out_movi_two(s, ret, arg)) {
 return;
 }
+assert(TCG_TARGET_REG_BITS == 64);
 
-tcg_out_movi(s, TCG_TYPE_I32, ret, arg >> 31 >> 1);
-if (arg & 0xull) {
-tcg_out_dsll(s, ret, ret, 16);
-tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg >> 16);
-tcg_out_dsll(s, ret, ret, 16);
-} else {
-tcg_out_dsll(s, ret, ret, 32);
-}
-if (arg & 0x) {
-tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0x);
-}
+/* Otherwise, put 64-bit constants into the constant pool. */
+tcg_out_movi_pool(s, ret, arg, tbreg);
+}
+
+static void tcg_out_movi(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg)
+{
+TCGReg tbreg = TCG_TARGET_REG_BITS == 64 ? TCG_REG_TB : 0;
+tcg_out_movi_int(s, type, ret, arg, tbreg);
 }
 
 static void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg, int flags)
@@ -2748,10 +2769,20 @@ static void tcg_target_qemu_prologue(TCGContext *s)
 
 #ifndef CONFIG_SOFTMMU
 if (guest_base != (int16_t)guest_base) {
-tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
+/*
+ * The function call abi for n32 and n64 will have loaded $25 (t9)
+ * with the address of the prologue, so we can use that instead
+ * of TCG_REG_TB.
+ */
+#if TCG_TARGET_REG_BITS == 64 && !defined(__mips_abicalls)
+# error "Unknown mips abi"
+#endif
+tcg_out_movi_int(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base,
+ TCG_TARGET_REG_BITS == 64 ? TCG_REG_T9 : 0);
 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
 }
 #endif
+
 if (TCG_TARGET_REG_BITS == 64) {
 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, tcg_target_call_iarg_regs[1]);
 }
-- 
2.25.1




[PATCH v4 02/12] tcg/mips: Support unaligned access for softmmu

2022-01-07 Thread Richard Henderson
We can use the routines just added for user-only to emit
unaligned accesses in softmmu mode too.

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c.inc | 91 ++-
 1 file changed, 51 insertions(+), 40 deletions(-)

diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 5737d8a269..7682059d92 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -1134,8 +1134,10 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, 
TCGReg addrl,
  tcg_insn_unit *label_ptr[2], bool is_load)
 {
 MemOp opc = get_memop(oi);
-unsigned s_bits = opc & MO_SIZE;
 unsigned a_bits = get_alignment_bits(opc);
+unsigned s_bits = opc & MO_SIZE;
+unsigned a_mask = (1 << a_bits) - 1;
+unsigned s_mask = (1 << s_bits) - 1;
 int mem_index = get_mmuidx(oi);
 int fast_off = TLB_MASK_TABLE_OFS(mem_index);
 int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
@@ -1143,7 +1145,7 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, 
TCGReg addrl,
 int add_off = offsetof(CPUTLBEntry, addend);
 int cmp_off = (is_load ? offsetof(CPUTLBEntry, addr_read)
: offsetof(CPUTLBEntry, addr_write));
-target_ulong mask;
+target_ulong tlb_mask;
 
 /* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx].  */
 tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_AREG0, mask_off);
@@ -1157,27 +1159,13 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg 
base, TCGReg addrl,
 /* Add the tlb_table pointer, creating the CPUTLBEntry address in TMP3.  */
 tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP3, TCG_TMP3, TCG_TMP1);
 
-/* We don't currently support unaligned accesses.
-   We could do so with mips32r6.  */
-if (a_bits < s_bits) {
-a_bits = s_bits;
-}
-
-/* Mask the page bits, keeping the alignment bits to compare against.  */
-mask = (target_ulong)TARGET_PAGE_MASK | ((1 << a_bits) - 1);
-
 /* Load the (low-half) tlb comparator.  */
 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
-tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_TMP3, cmp_off + LO_OFF);
-tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1, mask);
+tcg_out_ldst(s, OPC_LW, TCG_TMP0, TCG_TMP3, cmp_off + LO_OFF);
 } else {
 tcg_out_ldst(s, (TARGET_LONG_BITS == 64 ? OPC_LD
  : TCG_TARGET_REG_BITS == 64 ? OPC_LWU : OPC_LW),
  TCG_TMP0, TCG_TMP3, cmp_off);
-tcg_out_movi(s, TCG_TYPE_TL, TCG_TMP1, mask);
-/* No second compare is required here;
-   load the tlb addend for the fast path.  */
-tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP2, TCG_TMP3, add_off);
 }
 
 /* Zero extend a 32-bit guest address for a 64-bit host. */
@@ -1185,7 +1173,25 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, 
TCGReg addrl,
 tcg_out_ext32u(s, base, addrl);
 addrl = base;
 }
-tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
+
+/*
+ * Mask the page bits, keeping the alignment bits to compare against.
+ * For unaligned accesses, compare against the end of the access to
+ * verify that it does not cross a page boundary.
+ */
+tlb_mask = (target_ulong)TARGET_PAGE_MASK | a_mask;
+tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1, tlb_mask);
+if (a_mask >= s_mask) {
+tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
+} else {
+tcg_out_opc_imm(s, ALIAS_PADDI, TCG_TMP2, addrl, s_mask - a_mask);
+tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, TCG_TMP2);
+}
+
+if (TCG_TARGET_REG_BITS >= TARGET_LONG_BITS) {
+/* Load the tlb addend for the fast path.  */
+tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP2, TCG_TMP3, add_off);
+}
 
 label_ptr[0] = s->code_ptr;
 tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
@@ -1193,7 +1199,7 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, 
TCGReg addrl,
 /* Load and test the high half tlb comparator.  */
 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
 /* delay slot */
-tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_TMP3, cmp_off + HI_OFF);
+tcg_out_ldst(s, OPC_LW, TCG_TMP0, TCG_TMP3, cmp_off + HI_OFF);
 
 /* Load the tlb addend for the fast path.  */
 tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP2, TCG_TMP3, add_off);
@@ -1515,8 +1521,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg 
lo, TCGReg hi,
 }
 }
 
-static void __attribute__((unused))
-tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
+static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
 TCGReg base, MemOp opc, bool is_64)
 {
 const MIPSInsn lw1 = MIPS_BE ? OPC_LWL : OPC_LWR;
@@ -1645,8 +1650,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg 
*args, bool is_64)
 #if defined(CONFIG_SOFTMMU)
 tcg_insn_unit *label_ptr[2];
 #else
-unsigned a_bits, s_bits;
 #endif
+

Re: [PATCH v3 2/2] hw/arm/virt: Support for virtio-mem-pci

2022-01-07 Thread Gavin Shan

Hi Peter,

On 1/8/22 12:40 AM, Peter Maydell wrote:

On Fri, 3 Dec 2021 at 23:34, Gavin Shan  wrote:


This supports virtio-mem-pci device on "virt" platform, by simply
following the implementation on x86.

* This implements the hotplug handlers to support virtio-mem-pci
  device hot-add, while the hot-remove isn't supported as we have
  on x86.

* The block size is 512MB on ARM64 instead of 128MB on x86.

* It has been passing the tests with various combinations like 64KB
  and 4KB page sizes on host and guest, different memory device
  backends like normal, transparent huge page and HugeTLB, plus
  migration.

Co-developed-by: David Hildenbrand 
Co-developed-by: Jonathan Cameron 
Signed-off-by: Gavin Shan 
Reviewed-by: Jonathan Cameron 
Reviewed-by: David Hildenbrand 




+static void virt_virtio_md_pci_pre_plug(HotplugHandler *hotplug_dev,
+DeviceState *dev, Error **errp)
+{
+HotplugHandler *hotplug_dev2 = qdev_get_bus_hotplug_handler(dev);
+Error *local_err = NULL;
+
+if (!hotplug_dev2 && dev->hotplugged) {
+/*
+ * Without a bus hotplug handler, we cannot control the plug/unplug
+ * order. We should never reach this point when hotplugging on x86,
+ * however, better add a safety net.
+ */


This comment looks like it was cut-n-pasted from x86 -- is whatever
it is that prevents us from reaching this point also true for arm ?
(What is the thing that prevents us reaching this point?)



Yeah, the comment was copied from x86. It's also true for ARM as a hotplug
controller on the parent bus is required for virtio-mem-pci device hot-add,
according to the following commit log.

commit a0a49813f7f2fc23bfe8a4fc6760e2a60c9a3e59
Author: David Hildenbrand 
Date:   Wed Jun 19 15:19:07 2019 +0530

pc: Support for virtio-pmem-pci

Override the device hotplug handler to properly handle the memory device

part via virtio-pmem-pci callbacks from the machine hotplug handler and
forward to the actual PCI bus hotplug handler.

As PCI hotplug has not been properly factored out into hotplug handlers,

most magic is performed in the (un)realize functions. Also some PCI host
buses don't have a PCI hotplug handler at all yet, just to be sure that
we alway have a hotplug handler on x86, add a simple error check.

Unlocking virtio-pmem will unlock virtio-pmem-pci.

Signed-off-by: David Hildenbrand 


However, I don't think the comment we have for ARM is precise enough because
it's irrelevant to x86. I will change it something like below in v4:

/*
 * Without a bus hotplug handler, we cannot control the plug/unplug
 * order. We should never reach this point when hotplugging on ARM.
 * However, it's nice to add a safety net, similar to what we have
 * on x86.
 */



+error_setg(errp, "hotplug of virtio based memory devices not supported"
+   " on this bus.");
+return;
+}
+/*
+ * First, see if we can plug this memory device at all. If that
+ * succeeds, branch of to the actual hotplug handler.
+ */
+memory_device_pre_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev), NULL,
+   _err);
+if (!local_err && hotplug_dev2) {
+hotplug_handler_pre_plug(hotplug_dev2, dev, _err);
+}
+error_propagate(errp, local_err);
+}





diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index b20595a496..21e4d572ab 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -125,7 +125,7 @@ static uint64_t virtio_mem_default_block_size(RAMBlock *rb)
   * The memory block size corresponds mostly to the section size.
   *
   * This allows e.g., to add 20MB with a section size of 128MB on x86_64, and
- * a section size of 1GB on arm64 (as long as the start address is properly
+ * a section size of 512MB on arm64 (as long as the start address is properly
   * aligned, similar to ordinary DIMMs).
   *
   * We can change this at any time and maybe even make it configurable if
@@ -134,6 +134,8 @@ static uint64_t virtio_mem_default_block_size(RAMBlock *rb)
   */
  #if defined(TARGET_X86_64) || defined(TARGET_I386)
  #define VIRTIO_MEM_USABLE_EXTENT (2 * (128 * MiB))
+#elif defined(TARGET_ARM)
+#define VIRTIO_MEM_USABLE_EXTENT (2 * (512 * MiB))
  #else
  #error VIRTIO_MEM_USABLE_EXTENT not defined
  #endif


Could this comment explain where the 128MB and 512MB come from
and why the value is different for different architectures ?



Yes, the comment already explained it by "section size", which is the
minimal hotpluggable unit. It's defined by the linux guest kernel as
below. On ARM64, we pick the larger section size without considering
the base page size. Besides, the virtio-mem is/will-be enabled on
x86_64 and ARM64 guest kernel only.

#define SECTION_SIZE_BITS  29  /* ARM:64KB base page size*/
#define 

[PATCH v4 7/7] tcg/arm: Support raising sigbus for user-only

2022-01-07 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/arm/tcg-target.h |  2 -
 tcg/arm/tcg-target.c.inc | 83 +++-
 2 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 1dd4cd5377..27c27a1f14 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -151,9 +151,7 @@ extern bool use_neon_instructions;
 /* not defined -- call should be eliminated at compile time */
 void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
 
-#ifdef CONFIG_SOFTMMU
 #define TCG_TARGET_NEED_LDST_LABELS
-#endif
 #define TCG_TARGET_NEED_POOL_LABELS
 
 #endif
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index 1c00311877..1e336a0eea 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -23,6 +23,7 @@
  */
 
 #include "elf.h"
+#include "../tcg-ldst.c.inc"
 #include "../tcg-pool.c.inc"
 
 int arm_arch = __ARM_ARCH;
@@ -1289,8 +1290,6 @@ static void tcg_out_vldst(TCGContext *s, ARMInsn insn,
 }
 
 #ifdef CONFIG_SOFTMMU
-#include "../tcg-ldst.c.inc"
-
 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
  * int mmu_idx, uintptr_t ra)
  */
@@ -1589,6 +1588,74 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *lb)
 tcg_out_goto(s, COND_AL, qemu_st_helpers[opc & MO_SIZE]);
 return true;
 }
+#else
+
+static void tcg_out_test_alignment(TCGContext *s, bool is_ld, TCGReg addrlo,
+   TCGReg addrhi, unsigned a_bits)
+{
+unsigned a_mask = (1 << a_bits) - 1;
+TCGLabelQemuLdst *label = new_ldst_label(s);
+
+label->is_ld = is_ld;
+label->addrlo_reg = addrlo;
+label->addrhi_reg = addrhi;
+
+/* We are expecting a_bits to max out at 7, and can easily support 8. */
+tcg_debug_assert(a_mask <= 0xff);
+/* tst addr, #mask */
+tcg_out_dat_imm(s, COND_AL, ARITH_TST, 0, addrlo, a_mask);
+
+/* blne slow_path */
+label->label_ptr[0] = s->code_ptr;
+tcg_out_bl_imm(s, COND_NE, 0);
+
+label->raddr = tcg_splitwx_to_rx(s->code_ptr);
+}
+
+static bool tcg_out_fail_alignment(TCGContext *s, TCGLabelQemuLdst *l)
+{
+if (!reloc_pc24(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
+return false;
+}
+
+if (TARGET_LONG_BITS == 64) {
+/* 64-bit target address is aligned into R2:R3. */
+if (l->addrhi_reg != TCG_REG_R2) {
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R2, l->addrlo_reg);
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R3, l->addrhi_reg);
+} else if (l->addrlo_reg != TCG_REG_R3) {
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R3, l->addrhi_reg);
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R2, l->addrlo_reg);
+} else {
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R1, TCG_REG_R2);
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R2, TCG_REG_R3);
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R3, TCG_REG_R1);
+}
+} else {
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R1, l->addrlo_reg);
+}
+tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_AREG0);
+
+/*
+ * Tail call to the helper, with the return address back inline,
+ * just for the clarity of the debugging traceback -- the helper
+ * cannot return.  We have used BLNE to arrive here, so LR is
+ * already set.
+ */
+tcg_out_goto(s, COND_AL, (const void *)
+ (l->is_ld ? helper_unaligned_ld : helper_unaligned_st));
+return true;
+}
+
+static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
+{
+return tcg_out_fail_alignment(s, l);
+}
+
+static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
+{
+return tcg_out_fail_alignment(s, l);
+}
 #endif /* SOFTMMU */
 
 static void tcg_out_qemu_ld_index(TCGContext *s, MemOp opc,
@@ -1686,6 +1753,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg 
*args, bool is64)
 int mem_index;
 TCGReg addend;
 tcg_insn_unit *label_ptr;
+#else
+unsigned a_bits;
 #endif
 
 datalo = *args++;
@@ -1709,6 +1778,10 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg 
*args, bool is64)
 add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi,
 s->code_ptr, label_ptr);
 #else /* !CONFIG_SOFTMMU */
+a_bits = get_alignment_bits(opc);
+if (a_bits) {
+tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits);
+}
 if (guest_base) {
 tcg_out_qemu_ld_index(s, opc, datalo, datahi,
   addrlo, TCG_REG_GUEST_BASE, false);
@@ -1798,6 +1871,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg 
*args, bool is64)
 int mem_index;
 TCGReg addend;
 tcg_insn_unit *label_ptr;
+#else
+unsigned a_bits;
 #endif
 
 datalo = *args++;
@@ -1821,6 +1896,10 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg 
*args, bool is64)
 add_qemu_ldst_label(s, false, 

[PULL 06/37] bsd-user/i386/target_arch_signal.h: Update mcontext_t to match FreeBSD

2022-01-07 Thread Warner Losh
Fill in target_mcontext_t to match the FreeBSD mcontex_t. Also tag the
current size of mcontext and ucontext to enable size checking for i386.

Signed-off-by: Warner Losh 
Reviewed-by: Richard Henderson 
---
 bsd-user/i386/target_arch_signal.h | 46 ++
 1 file changed, 46 insertions(+)

diff --git a/bsd-user/i386/target_arch_signal.h 
b/bsd-user/i386/target_arch_signal.h
index bf7263c4f8d..701c6f964f8 100644
--- a/bsd-user/i386/target_arch_signal.h
+++ b/bsd-user/i386/target_arch_signal.h
@@ -28,8 +28,54 @@
 #define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768)   /* recommended size */
 
 typedef struct target_mcontext {
+abi_ulong   mc_onstack; /* XXX - sigcontext compat. */
+abi_ulong   mc_gs;  /* machine state (struct trapframe) */
+abi_ulong   mc_fs;
+abi_ulong   mc_es;
+abi_ulong   mc_ds;
+abi_ulong   mc_edi;
+abi_ulong   mc_esi;
+abi_ulong   mc_ebp;
+abi_ulong   mc_isp;
+abi_ulong   mc_ebx;
+abi_ulong   mc_edx;
+abi_ulong   mc_ecx;
+abi_ulong   mc_eax;
+abi_ulong   mc_trapno;
+abi_ulong   mc_err;
+abi_ulong   mc_eip;
+abi_ulong   mc_cs;
+abi_ulong   mc_eflags;
+abi_ulong   mc_esp;
+abi_ulong   mc_ss;
+
+int32_t mc_len; /* sizeof(mcontext_t) */
+#define _MC_FPFMT_NODEV 0x1 /* device not present or configured */
+#define _MC_FPFMT_387   0x10001
+#define _MC_FPFMT_XMM   0x10002
+int32_t mc_fpformat;
+#define _MC_FPOWNED_NONE0x2 /* FP state not used */
+#define _MC_FPOWNED_FPU 0x20001 /* FP state came from FPU */
+#define _MC_FPOWNED_PCB 0x20002 /* FP state came from PCB */
+int32_t mc_ownedfp;
+abi_ulong mc_flags;
+/*
+ * See  for the internals of mc_fpstate[].
+ */
+int32_t mc_fpstate[128] __aligned(16);
+
+abi_ulong mc_fsbase;
+abi_ulong mc_gsbase;
+
+abi_ulong mc_xfpustate;
+abi_ulong mc_xfpustate_len;
+
+int32_t mc_spare2[4];
 } target_mcontext_t;
 
+#define TARGET_MCONTEXT_SIZE 640
+#define TARGET_UCONTEXT_SIZE 704
+
 #include "target_os_ucontext.h"
 
 struct target_sigframe {
-- 
2.33.1




[PATCH v4 07/12] tcg/mips: Split out tcg_out_movi_one

2022-01-07 Thread Richard Henderson
Emit all constants that can be loaded in exactly one insn.

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c.inc | 26 --
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 76fb1dada0..8741fdd49c 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -524,20 +524,34 @@ static bool tcg_out_mov(TCGContext *s, TCGType type, 
TCGReg ret, TCGReg arg)
 return true;
 }
 
+static bool tcg_out_movi_one(TCGContext *s, TCGReg ret, tcg_target_long arg)
+{
+if (arg == (int16_t)arg) {
+tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg);
+return true;
+}
+if (arg == (uint16_t)arg) {
+tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg);
+return true;
+}
+if (arg == (int32_t)arg && (arg & 0x) == 0) {
+tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
+return true;
+}
+return false;
+}
+
 static void tcg_out_movi(TCGContext *s, TCGType type,
  TCGReg ret, tcg_target_long arg)
 {
 if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
 arg = (int32_t)arg;
 }
-if (arg == (int16_t)arg) {
-tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg);
-return;
-}
-if (arg == (uint16_t)arg) {
-tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg);
+
+if (tcg_out_movi_one(s, ret, arg)) {
 return;
 }
+
 if (TCG_TARGET_REG_BITS == 32 || arg == (int32_t)arg) {
 tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
 } else {
-- 
2.25.1




[PATCH v4 6/7] tcg/arm: Reserve a register for guest_base

2022-01-07 Thread Richard Henderson
Reserve a register for the guest_base using aarch64 for reference.
By doing so, we do not have to recompute it for every memory load.

Signed-off-by: Richard Henderson 
---
 tcg/arm/tcg-target.c.inc | 39 ---
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index b6ef279cae..1c00311877 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -84,6 +84,9 @@ static const int tcg_target_call_oarg_regs[2] = {
 
 #define TCG_REG_TMP  TCG_REG_R12
 #define TCG_VEC_TMP  TCG_REG_Q15
+#ifndef CONFIG_SOFTMMU
+#define TCG_REG_GUEST_BASE  TCG_REG_R11
+#endif
 
 typedef enum {
 COND_EQ = 0x0,
@@ -1590,7 +1593,8 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *lb)
 
 static void tcg_out_qemu_ld_index(TCGContext *s, MemOp opc,
   TCGReg datalo, TCGReg datahi,
-  TCGReg addrlo, TCGReg addend)
+  TCGReg addrlo, TCGReg addend,
+  bool scratch_addend)
 {
 /* Byte swapping is left to middle-end expansion. */
 tcg_debug_assert((opc & MO_BSWAP) == 0);
@@ -1616,7 +1620,7 @@ static void tcg_out_qemu_ld_index(TCGContext *s, MemOp 
opc,
 if (get_alignment_bits(opc) >= MO_64
 && (datalo & 1) == 0 && datahi == datalo + 1) {
 tcg_out_ldrd_r(s, COND_AL, datalo, addrlo, addend);
-} else if (datalo != addend) {
+} else if (scratch_addend) {
 tcg_out_ld32_rwb(s, COND_AL, datalo, addend, addrlo);
 tcg_out_ld32_12(s, COND_AL, datahi, addend, 4);
 } else {
@@ -1700,14 +1704,14 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg 
*args, bool is64)
 label_ptr = s->code_ptr;
 tcg_out_bl_imm(s, COND_NE, 0);
 
-tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, addend);
+tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, addend, true);
 
 add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi,
 s->code_ptr, label_ptr);
 #else /* !CONFIG_SOFTMMU */
 if (guest_base) {
-tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, guest_base);
-tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, TCG_REG_TMP);
+tcg_out_qemu_ld_index(s, opc, datalo, datahi,
+  addrlo, TCG_REG_GUEST_BASE, false);
 } else {
 tcg_out_qemu_ld_direct(s, opc, datalo, datahi, addrlo);
 }
@@ -1716,7 +1720,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg 
*args, bool is64)
 
 static void tcg_out_qemu_st_index(TCGContext *s, ARMCond cond, MemOp opc,
   TCGReg datalo, TCGReg datahi,
-  TCGReg addrlo, TCGReg addend)
+  TCGReg addrlo, TCGReg addend,
+  bool scratch_addend)
 {
 /* Byte swapping is left to middle-end expansion. */
 tcg_debug_assert((opc & MO_BSWAP) == 0);
@@ -1736,9 +1741,14 @@ static void tcg_out_qemu_st_index(TCGContext *s, ARMCond 
cond, MemOp opc,
 if (get_alignment_bits(opc) >= MO_64
 && (datalo & 1) == 0 && datahi == datalo + 1) {
 tcg_out_strd_r(s, cond, datalo, addrlo, addend);
-} else {
+} else if (scratch_addend) {
 tcg_out_st32_rwb(s, cond, datalo, addend, addrlo);
 tcg_out_st32_12(s, cond, datahi, addend, 4);
+} else {
+tcg_out_dat_reg(s, cond, ARITH_ADD, TCG_REG_TMP,
+addend, addrlo, SHIFT_IMM_LSL(0));
+tcg_out_st32_12(s, cond, datalo, TCG_REG_TMP, 0);
+tcg_out_st32_12(s, cond, datahi, TCG_REG_TMP, 4);
 }
 break;
 default:
@@ -1801,7 +1811,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg 
*args, bool is64)
 mem_index = get_mmuidx(oi);
 addend = tcg_out_tlb_read(s, addrlo, addrhi, opc, mem_index, 0);
 
-tcg_out_qemu_st_index(s, COND_EQ, opc, datalo, datahi, addrlo, addend);
+tcg_out_qemu_st_index(s, COND_EQ, opc, datalo, datahi,
+  addrlo, addend, true);
 
 /* The conditional call must come last, as we're going to return here.  */
 label_ptr = s->code_ptr;
@@ -1811,9 +1822,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg 
*args, bool is64)
 s->code_ptr, label_ptr);
 #else /* !CONFIG_SOFTMMU */
 if (guest_base) {
-tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, guest_base);
-tcg_out_qemu_st_index(s, COND_AL, opc, datalo,
-  datahi, addrlo, TCG_REG_TMP);
+tcg_out_qemu_st_index(s, COND_AL, opc, datalo, datahi,
+  addrlo, TCG_REG_GUEST_BASE, false);
 } else {
 tcg_out_qemu_st_direct(s, opc, datalo, datahi, addrlo);
 }
@@ -2955,6 +2965,13 @@ static void tcg_target_qemu_prologue(TCGContext 

[PATCH v4 2/7] tcg/arm: Remove use_armv5t_instructions

2022-01-07 Thread Richard Henderson
This is now always true, since we require armv6.

Signed-off-by: Richard Henderson 
---
 tcg/arm/tcg-target.h |  3 +--
 tcg/arm/tcg-target.c.inc | 35 ++-
 2 files changed, 7 insertions(+), 31 deletions(-)

diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index f41b809554..5c9ba5feea 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -28,7 +28,6 @@
 
 extern int arm_arch;
 
-#define use_armv5t_instructions (__ARM_ARCH >= 5 || arm_arch >= 5)
 #define use_armv6_instructions  (__ARM_ARCH >= 6 || arm_arch >= 6)
 #define use_armv7_instructions  (__ARM_ARCH >= 7 || arm_arch >= 7)
 
@@ -109,7 +108,7 @@ extern bool use_neon_instructions;
 #define TCG_TARGET_HAS_eqv_i32  0
 #define TCG_TARGET_HAS_nand_i32 0
 #define TCG_TARGET_HAS_nor_i32  0
-#define TCG_TARGET_HAS_clz_i32  use_armv5t_instructions
+#define TCG_TARGET_HAS_clz_i32  1
 #define TCG_TARGET_HAS_ctz_i32  use_armv7_instructions
 #define TCG_TARGET_HAS_ctpop_i320
 #define TCG_TARGET_HAS_deposit_i32  use_armv7_instructions
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index 72b384cc28..fd30e6e99e 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -596,11 +596,7 @@ static void tcg_out_b_reg(TCGContext *s, ARMCond cond, 
TCGReg rn)
  * Unless the C portion of QEMU is compiled as thumb, we don't need
  * true BX semantics; merely a branch to an address held in a register.
  */
-if (use_armv5t_instructions) {
-tcg_out_bx_reg(s, cond, rn);
-} else {
-tcg_out_mov_reg(s, cond, TCG_REG_PC, rn);
-}
+tcg_out_bx_reg(s, cond, rn);
 }
 
 static void tcg_out_dat_imm(TCGContext *s, ARMCond cond, ARMInsn opc,
@@ -1247,14 +1243,7 @@ static void tcg_out_goto(TCGContext *s, ARMCond cond, 
const tcg_insn_unit *addr)
 }
 
 /* LDR is interworking from v5t. */
-if (arm_mode || use_armv5t_instructions) {
-tcg_out_movi_pool(s, cond, TCG_REG_PC, addri);
-return;
-}
-
-/* else v4t */
-tcg_out_movi32(s, COND_AL, TCG_REG_TMP, addri);
-tcg_out_bx_reg(s, COND_AL, TCG_REG_TMP);
+tcg_out_movi_pool(s, cond, TCG_REG_PC, addri);
 }
 
 /*
@@ -1270,26 +1259,14 @@ static void tcg_out_call(TCGContext *s, const 
tcg_insn_unit *addr)
 if (disp - 8 < 0x0200 && disp - 8 >= -0x0200) {
 if (arm_mode) {
 tcg_out_bl_imm(s, COND_AL, disp);
-return;
-}
-if (use_armv5t_instructions) {
+} else {
 tcg_out_blx_imm(s, disp);
-return;
 }
+return;
 }
 
-if (use_armv5t_instructions) {
-tcg_out_movi32(s, COND_AL, TCG_REG_TMP, addri);
-tcg_out_blx_reg(s, COND_AL, TCG_REG_TMP);
-} else if (arm_mode) {
-/* ??? Know that movi_pool emits exactly 1 insn.  */
-tcg_out_mov_reg(s, COND_AL, TCG_REG_R14, TCG_REG_PC);
-tcg_out_movi_pool(s, COND_AL, TCG_REG_PC, addri);
-} else {
-tcg_out_movi32(s, COND_AL, TCG_REG_TMP, addri);
-tcg_out_mov_reg(s, COND_AL, TCG_REG_R14, TCG_REG_PC);
-tcg_out_bx_reg(s, COND_AL, TCG_REG_TMP);
-}
+tcg_out_movi32(s, COND_AL, TCG_REG_TMP, addri);
+tcg_out_blx_reg(s, COND_AL, TCG_REG_TMP);
 }
 
 static void tcg_out_goto_label(TCGContext *s, ARMCond cond, TCGLabel *l)
-- 
2.25.1




[PULL 03/37] bsd-user: create a per-arch signal.c file

2022-01-07 Thread Warner Losh
Create a place-holder signal.c file for each of the architectures that
are currently built. In the future, some code that's currently inlined
in target_arch_signal.h will live here.

Signed-off-by: Warner Losh 
Reviewed-by: Richard Henderson 
---
 bsd-user/i386/signal.c   | 1 +
 bsd-user/x86_64/signal.c | 1 +
 meson.build  | 2 +-
 3 files changed, 3 insertions(+), 1 deletion(-)
 create mode 100644 bsd-user/i386/signal.c
 create mode 100644 bsd-user/x86_64/signal.c

diff --git a/bsd-user/i386/signal.c b/bsd-user/i386/signal.c
new file mode 100644
index 000..ac903233653
--- /dev/null
+++ b/bsd-user/i386/signal.c
@@ -0,0 +1 @@
+/* Placeholder for signal.c */
diff --git a/bsd-user/x86_64/signal.c b/bsd-user/x86_64/signal.c
new file mode 100644
index 000..ac903233653
--- /dev/null
+++ b/bsd-user/x86_64/signal.c
@@ -0,0 +1 @@
+/* Placeholder for signal.c */
diff --git a/meson.build b/meson.build
index 53065e96ecf..c1b1db1e28c 100644
--- a/meson.build
+++ b/meson.build
@@ -2933,7 +2933,7 @@ foreach target : target_dirs
   base_dir = 'bsd-user'
   target_inc += include_directories('bsd-user/' / targetos)
   dir = base_dir / abi
-  arch_srcs += files(dir / 'target_arch_cpu.c')
+  arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
 endif
 target_inc += include_directories(
   base_dir,
-- 
2.33.1




[PATCH v4 4/7] tcg/arm: Check alignment for ldrd and strd

2022-01-07 Thread Richard Henderson
We will shortly allow the use of unaligned memory accesses,
and these require proper alignment.  Use get_alignment_bits
to verify and remove USING_SOFTMMU.

Signed-off-by: Richard Henderson 
---
 tcg/arm/tcg-target.c.inc | 22 --
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index ea8b90e6e2..8a20224dd1 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -35,12 +35,6 @@ bool use_neon_instructions;
 #endif
 
 /* ??? Ought to think about changing CONFIG_SOFTMMU to always defined.  */
-#ifdef CONFIG_SOFTMMU
-# define USING_SOFTMMU 1
-#else
-# define USING_SOFTMMU 0
-#endif
-
 #ifdef CONFIG_DEBUG_TCG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 "%r0",  "%r1",  "%r2",  "%r3",  "%r4",  "%r5",  "%r6",  "%r7",
@@ -1621,8 +1615,8 @@ static void tcg_out_qemu_ld_index(TCGContext *s, MemOp 
opc,
 tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend);
 break;
 case MO_Q:
-/* Avoid ldrd for user-only emulation, to handle unaligned.  */
-if (USING_SOFTMMU
+/* LDRD requires alignment; double-check that. */
+if (get_alignment_bits(opc) >= MO_64
 && (datalo & 1) == 0 && datahi == datalo + 1) {
 tcg_out_ldrd_r(s, COND_AL, datalo, addrlo, addend);
 } else if (datalo != addend) {
@@ -1664,8 +1658,8 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp 
opc, TCGReg datalo,
 tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0);
 break;
 case MO_Q:
-/* Avoid ldrd for user-only emulation, to handle unaligned.  */
-if (USING_SOFTMMU
+/* LDRD requires alignment; double-check that. */
+if (get_alignment_bits(opc) >= MO_64
 && (datalo & 1) == 0 && datahi == datalo + 1) {
 tcg_out_ldrd_8(s, COND_AL, datalo, addrlo, 0);
 } else if (datalo == addrlo) {
@@ -1741,8 +1735,8 @@ static void tcg_out_qemu_st_index(TCGContext *s, ARMCond 
cond, MemOp opc,
 tcg_out_st32_r(s, cond, datalo, addrlo, addend);
 break;
 case MO_64:
-/* Avoid strd for user-only emulation, to handle unaligned.  */
-if (USING_SOFTMMU
+/* STRD requires alignment; double-check that. */
+if (get_alignment_bits(opc) >= MO_64
 && (datalo & 1) == 0 && datahi == datalo + 1) {
 tcg_out_strd_r(s, cond, datalo, addrlo, addend);
 } else {
@@ -1773,8 +1767,8 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp 
opc, TCGReg datalo,
 tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
 break;
 case MO_64:
-/* Avoid strd for user-only emulation, to handle unaligned.  */
-if (USING_SOFTMMU
+/* STRD requires alignment; double-check that. */
+if (get_alignment_bits(opc) >= MO_64
 && (datalo & 1) == 0 && datahi == datalo + 1) {
 tcg_out_strd_8(s, COND_AL, datalo, addrlo, 0);
 } else {
-- 
2.25.1




[PULL 28/37] target/riscv: support for 128-bit shift instructions

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

Handling shifts for 32, 64 and 128 operation length for RV128, following the
general framework for handling various olens proposed by Richard.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-13-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  10 ++
 target/riscv/translate.c|  58 --
 target/riscv/insn_trans/trans_rvb.c.inc |  22 +--
 target/riscv/insn_trans/trans_rvi.c.inc | 224 ++--
 4 files changed, 270 insertions(+), 44 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index ddbf0da03c..a992c6d369 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -22,6 +22,7 @@
 %rs1   15:5
 %rd7:5
 %sh5   20:5
+%sh6   20:6
 
 %sh720:7
 %csr20:12
@@ -91,6 +92,9 @@
 # Formats 64:
 @sh5 ...  . .  ... . ...   shamt=%sh5  %rs1 
%rd
 
+# Formats 128:
+@sh6   .. .. . ... . ...  shamt=%sh6 %rs1 %rd
+
 # *** Privileged Instructions ***
 ecall    0 000 0 1110011
 ebreak  0001 0 000 0 1110011
@@ -166,6 +170,12 @@ sraw 010 .  . 101 . 0111011 @r
 ldu     . 111 . 011 @i
 lq      . 010 . 000 @i
 sq      . 100 . 0100011 @s
+sllid00 ..  . 001 . 1011011 @sh6
+srlid00 ..  . 101 . 1011011 @sh6
+sraid01 ..  . 101 . 1011011 @sh6
+slld 000 . .  001 . 011 @r
+srld 000 . .  101 . 011 @r
+srad 010 . .  101 . 011 @r
 
 # *** RV32M Standard Extension ***
 mul  001 .  . 000 . 0110011 @r
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index ba1ad1be5f..89220a5fae 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -635,7 +635,8 @@ static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, 
DisasExtend ext,
 }
 
 static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, target_long))
+ void (*func)(TCGv, TCGv, target_long),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
 {
 TCGv dest, src1;
 int max_len = get_olen(ctx);
@@ -647,26 +648,38 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
 dest = dest_gpr(ctx, a->rd);
 src1 = get_gpr(ctx, a->rs1, ext);
 
-func(dest, src1, a->shamt);
+if (max_len < 128) {
+func(dest, src1, a->shamt);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (f128 == NULL) {
+return false;
+}
+f128(dest, desth, src1, src1h, a->shamt);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a,
 DisasExtend ext,
 void (*f_tl)(TCGv, TCGv, target_long),
-void (*f_32)(TCGv, TCGv, target_long))
+void (*f_32)(TCGv, TCGv, target_long),
+void (*f_128)(TCGv, TCGv, TCGv, TCGv,
+  target_long))
 {
 int olen = get_olen(ctx);
 if (olen != TARGET_LONG_BITS) {
 if (olen == 32) {
 f_tl = f_32;
-} else {
+} else if (olen != 128) {
 g_assert_not_reached();
 }
 }
-return gen_shift_imm_fn(ctx, a, ext, f_tl);
+return gen_shift_imm_fn(ctx, a, ext, f_tl, f_128);
 }
 
 static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
@@ -690,34 +703,49 @@ static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift 
*a, DisasExtend ext,
 }
 
 static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext,
-  void (*func)(TCGv, TCGv, TCGv))
+  void (*func)(TCGv, TCGv, TCGv),
+  void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv))
 {
-TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 TCGv ext2 = tcg_temp_new();
+int max_len = get_olen(ctx);
 
-tcg_gen_andi_tl(ext2, src2, get_olen(ctx) - 1);
-func(dest, src1, ext2);
+tcg_gen_andi_tl(ext2, src2, max_len - 1);
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, ext);
+
+if (max_len < 128) {
+func(dest, src1, ext2);
+

[PATCH v4 0/7] tcg/arm: Unaligned access and other cleanup

2022-01-07 Thread Richard Henderson
Based-on: <20220104021543.396571-1-richard.hender...@linaro.org>
("[PATCH v4 0/7] Unaligned access for user only")

Changes from v3:
  * Rebase on master, which has some patches applied.
  * Drop support for armv4 and armv5.
  * Drop code to emit ldm/stm for aligned trapping insns.

Previously, I added quite a lot of code to support armv4, and
added more code to downgrade the detection of the host cpu,
but all that seems mostly pointless in retrospect.

The oldest reasonable system is probably the rpi, with armv6.
Stuff older than than probably doesn't have enough memory to
actually run qemu.  Armv6 is an interesting cutoff, because
that is the minimum that supports unaligned accesses in hw.


r~


Richard Henderson (7):
  tcg/arm: Drop support for armv4 and armv5 hosts
  tcg/arm: Remove use_armv5t_instructions
  tcg/arm: Remove use_armv6_instructions
  tcg/arm: Check alignment for ldrd and strd
  tcg/arm: Support unaligned access for softmmu
  tcg/arm: Reserve a register for guest_base
  tcg/arm: Support raising sigbus for user-only

 tcg/arm/tcg-target.h |   6 +-
 tcg/arm/tcg-target.c.inc | 407 ---
 2 files changed, 170 insertions(+), 243 deletions(-)

-- 
2.25.1




[PULL 26/37] target/riscv: support for 128-bit bitwise instructions

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

The 128-bit bitwise instructions do not need any function prototype change
as the functions can be applied independently on the lower and upper part of
the registers.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-11-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/translate.c | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index d4cf965c9e..b43efc9bc3 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -523,7 +523,15 @@ static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
 
 func(dest, src1, a->imm);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (get_xl(ctx) == MXL_RV128) {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+func(desth, src1h, -(a->imm < 0));
+gen_set_gpr128(ctx, a->rd, dest, desth);
+} else {
+gen_set_gpr(ctx, a->rd, dest);
+}
 
 return true;
 }
@@ -537,7 +545,16 @@ static bool gen_logic(DisasContext *ctx, arg_r *a,
 
 func(dest, src1, src2);
 
-gen_set_gpr(ctx, a->rd, dest);
+if (get_xl(ctx) == MXL_RV128) {
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = get_gprh(ctx, a->rs2);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+func(desth, src1h, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+} else {
+gen_set_gpr(ctx, a->rd, dest);
+}
 
 return true;
 }
-- 
2.31.1




[PATCH v4 12/12] tcg/mips: Try three insns with shift and add in tcg_out_movi

2022-01-07 Thread Richard Henderson
These sequences are inexpensive to test.  Maxing out at three insns
results in the same space as a load plus the constant pool entry.

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c.inc | 44 +++
 1 file changed, 44 insertions(+)

diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index a128c70154..185241da17 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -583,6 +583,7 @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, 
TCGReg ret,
  tcg_target_long arg, TCGReg tbreg)
 {
 tcg_target_long tmp;
+int sh, lo;
 
 if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
 arg = (int32_t)arg;
@@ -605,6 +606,49 @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, 
TCGReg ret,
 return;
 }
 
+/*
+ * Load bitmasks with a right-shift.  This is good for things
+ * like 0x0fff___fff0: ADDUI r,0xff00 + DSRL r,r,4.
+ * or similarly using LUI.  For this to work, bit 31 must be set.
+ */
+if (arg > 0 && (int32_t)arg < 0) {
+sh = clz64(arg);
+if (tcg_out_movi_one(s, ret, arg << sh)) {
+tcg_out_dsrl(s, ret, ret, sh);
+return;
+}
+}
+
+/*
+ * Load slightly larger constants using left-shift.
+ * Limit this sequence to 3 insns to avoid too much expansion.
+ */
+sh = ctz64(arg);
+if (sh && tcg_out_movi_two(s, ret, arg >> sh)) {
+tcg_out_dsll(s, ret, ret, sh);
+return;
+}
+
+/*
+ * Load slightly larger constants using left-shift and add/or.
+ * Prefer addi with a negative immediate when that would produce
+ * a larger shift.  For this to work, bits 15 and 16 must be set.
+ */
+lo = arg & 0x;
+if (lo) {
+if ((arg & 0x18000) == 0x18000) {
+lo = (int16_t)arg;
+}
+tmp = arg - lo;
+sh = ctz64(tmp);
+tmp >>= sh;
+if (tcg_out_movi_one(s, ret, tmp)) {
+tcg_out_dsll(s, ret, ret, sh);
+tcg_out_opc_imm(s, lo < 0 ? OPC_DADDIU : OPC_ORI, ret, ret, lo);
+return;
+}
+}
+
 /* Otherwise, put 64-bit constants into the constant pool. */
 tcg_out_movi_pool(s, ret, arg, tbreg);
 }
-- 
2.25.1




[PATCH v4 3/7] tcg/arm: Remove use_armv6_instructions

2022-01-07 Thread Richard Henderson
This is now always true, since we require armv6.

Signed-off-by: Richard Henderson 
---
 tcg/arm/tcg-target.h |   1 -
 tcg/arm/tcg-target.c.inc | 192 ++-
 2 files changed, 27 insertions(+), 166 deletions(-)

diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 5c9ba5feea..1dd4cd5377 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -28,7 +28,6 @@
 
 extern int arm_arch;
 
-#define use_armv6_instructions  (__ARM_ARCH >= 6 || arm_arch >= 6)
 #define use_armv7_instructions  (__ARM_ARCH >= 7 || arm_arch >= 7)
 
 #undef TCG_TARGET_STACK_GROWSUP
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index fd30e6e99e..ea8b90e6e2 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -923,17 +923,6 @@ static void tcg_out_dat_rIN(TCGContext *s, ARMCond cond, 
ARMInsn opc,
 static void tcg_out_mul32(TCGContext *s, ARMCond cond, TCGReg rd,
   TCGReg rn, TCGReg rm)
 {
-/* if ArchVersion() < 6 && d == n then UNPREDICTABLE;  */
-if (!use_armv6_instructions && rd == rn) {
-if (rd == rm) {
-/* rd == rn == rm; copy an input to tmp first.  */
-tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
-rm = rn = TCG_REG_TMP;
-} else {
-rn = rm;
-rm = rd;
-}
-}
 /* mul */
 tcg_out32(s, (cond << 28) | 0x90 | (rd << 16) | (rm << 8) | rn);
 }
@@ -941,17 +930,6 @@ static void tcg_out_mul32(TCGContext *s, ARMCond cond, 
TCGReg rd,
 static void tcg_out_umull32(TCGContext *s, ARMCond cond, TCGReg rd0,
 TCGReg rd1, TCGReg rn, TCGReg rm)
 {
-/* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE;  */
-if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) {
-if (rd0 == rm || rd1 == rm) {
-tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
-rn = TCG_REG_TMP;
-} else {
-TCGReg t = rn;
-rn = rm;
-rm = t;
-}
-}
 /* umull */
 tcg_out32(s, (cond << 28) | 0x00800090 |
   (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn);
@@ -960,17 +938,6 @@ static void tcg_out_umull32(TCGContext *s, ARMCond cond, 
TCGReg rd0,
 static void tcg_out_smull32(TCGContext *s, ARMCond cond, TCGReg rd0,
 TCGReg rd1, TCGReg rn, TCGReg rm)
 {
-/* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE;  */
-if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) {
-if (rd0 == rm || rd1 == rm) {
-tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
-rn = TCG_REG_TMP;
-} else {
-TCGReg t = rn;
-rn = rm;
-rm = t;
-}
-}
 /* smull */
 tcg_out32(s, (cond << 28) | 0x00c00090 |
   (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn);
@@ -990,15 +957,8 @@ static void tcg_out_udiv(TCGContext *s, ARMCond cond,
 
 static void tcg_out_ext8s(TCGContext *s, ARMCond cond, TCGReg rd, TCGReg rn)
 {
-if (use_armv6_instructions) {
-/* sxtb */
-tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
-} else {
-tcg_out_dat_reg(s, cond, ARITH_MOV,
-rd, 0, rn, SHIFT_IMM_LSL(24));
-tcg_out_dat_reg(s, cond, ARITH_MOV,
-rd, 0, rd, SHIFT_IMM_ASR(24));
-}
+/* sxtb */
+tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
 }
 
 static void __attribute__((unused))
@@ -1009,113 +969,37 @@ tcg_out_ext8u(TCGContext *s, ARMCond cond, TCGReg rd, 
TCGReg rn)
 
 static void tcg_out_ext16s(TCGContext *s, ARMCond cond, TCGReg rd, TCGReg rn)
 {
-if (use_armv6_instructions) {
-/* sxth */
-tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
-} else {
-tcg_out_dat_reg(s, cond, ARITH_MOV,
-rd, 0, rn, SHIFT_IMM_LSL(16));
-tcg_out_dat_reg(s, cond, ARITH_MOV,
-rd, 0, rd, SHIFT_IMM_ASR(16));
-}
+/* sxth */
+tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
 }
 
 static void tcg_out_ext16u(TCGContext *s, ARMCond cond, TCGReg rd, TCGReg rn)
 {
-if (use_armv6_instructions) {
-/* uxth */
-tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
-} else {
-tcg_out_dat_reg(s, cond, ARITH_MOV,
-rd, 0, rn, SHIFT_IMM_LSL(16));
-tcg_out_dat_reg(s, cond, ARITH_MOV,
-rd, 0, rd, SHIFT_IMM_LSR(16));
-}
+/* uxth */
+tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
 }
 
 static void tcg_out_bswap16(TCGContext *s, ARMCond cond,
 TCGReg rd, TCGReg rn, int flags)
 {
-if (use_armv6_instructions) {
-if (flags & TCG_BSWAP_OS) {
-/* revsh */
-tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
-return;
-}
-
-/* rev16 */
-

[PULL 25/37] target/riscv: accessors to registers upper part and 128-bit load/store

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

Get function to retrieve the 64 top bits of a register, stored in the gprh
field of the cpu state. Set function that writes the 128-bit value at once.
The access to the gprh field can not be protected at compile time to make
sure it is accessed only in the 128-bit version of the processor because we
have no way to indicate that the misa_mxl_max field is const.

The 128-bit ISA adds ldu, lq and sq. We provide support for these
instructions. Note that (a) we compute only 64-bit addresses to actually
access memory, cowardly utilizing the existing address translation mechanism
of QEMU, and (b) we assume for now little-endian memory accesses.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-10-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/insn16.decode  |  27 ++-
 target/riscv/insn32.decode  |   5 ++
 target/riscv/translate.c|  41 ++
 target/riscv/insn_trans/trans_rvi.c.inc | 100 ++--
 4 files changed, 163 insertions(+), 10 deletions(-)

diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index 2e9212663c..02c8f61b48 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -25,14 +25,17 @@
 # Immediates:
 %imm_ci12:s1 2:5
 %nzuimm_ciw7:4 11:2 5:1 6:1   !function=ex_shift_2
+%uimm_cl_q 10:1 5:2 11:2  !function=ex_shift_4
 %uimm_cl_d 5:2 10:3   !function=ex_shift_3
 %uimm_cl_w 5:1 10:3 6:1   !function=ex_shift_2
 %imm_cb12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
 %imm_cj12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
 
 %shimm_6bit   12:1 2:5   !function=ex_rvc_shifti
+%uimm_6bit_lq 2:4 12:1 6:1   !function=ex_shift_4
 %uimm_6bit_ld 2:3 12:1 5:2   !function=ex_shift_3
 %uimm_6bit_lw 2:2 12:1 4:3   !function=ex_shift_2
+%uimm_6bit_sq 7:4 11:2   !function=ex_shift_4
 %uimm_6bit_sd 7:3 10:3   !function=ex_shift_3
 %uimm_6bit_sw 7:2 9:4!function=ex_shift_2
 
@@ -54,16 +57,20 @@
 # Formats 16:
 @cr  . .  ..   rs2=%rs2_5   rs1=%rd %rd
 @ci... . . .  ..   imm=%imm_ci  rs1=%rd %rd
+@cl_q  ... . .  . ..   imm=%uimm_cl_q   rs1=%rs1_3  rd=%rs2_3
 @cl_d  ... ... ... .. ... ..   imm=%uimm_cl_d   rs1=%rs1_3  rd=%rs2_3
 @cl_w  ... ... ... .. ... ..   imm=%uimm_cl_w   rs1=%rs1_3  rd=%rs2_3
 @cs_2  ... ... ... .. ... ..   rs2=%rs2_3   rs1=%rs1_3  rd=%rs1_3
+@cs_q  ... ... ... .. ... ..   imm=%uimm_cl_q   rs1=%rs1_3  
rs2=%rs2_3
 @cs_d  ... ... ... .. ... ..   imm=%uimm_cl_d   rs1=%rs1_3  
rs2=%rs2_3
 @cs_w  ... ... ... .. ... ..   imm=%uimm_cl_w   rs1=%rs1_3  
rs2=%rs2_3
 @cj...... ..   imm=%imm_cj
 @cb_z  ... ... ... .. ... ..   imm=%imm_cb  rs1=%rs1_3  rs2=0
 
+@c_lqsp... . .  . ..   imm=%uimm_6bit_lq rs1=2 %rd
 @c_ldsp... . .  . ..   imm=%uimm_6bit_ld rs1=2 %rd
 @c_lwsp... . .  . ..   imm=%uimm_6bit_lw rs1=2 %rd
+@c_sqsp... . .  . ..   imm=%uimm_6bit_sq rs1=2 rs2=%rs2_5
 @c_sdsp... . .  . ..   imm=%uimm_6bit_sd rs1=2 rs2=%rs2_5
 @c_swsp... . .  . ..   imm=%uimm_6bit_sw rs1=2 rs2=%rs2_5
 @c_li  ... . .  . ..   imm=%imm_ci rs1=0 %rd
@@ -87,9 +94,15 @@
   illegal 000  000 000 00 --- 00
   addi000  ... ... .. ... 00 @c_addi4spn
 }
-fld   001  ... ... .. ... 00 @cl_d
+{
+  lq  001  ... ... .. ... 00 @cl_q
+  fld 001  ... ... .. ... 00 @cl_d
+}
 lw010  ... ... .. ... 00 @cl_w
-fsd   101  ... ... .. ... 00 @cs_d
+{
+  sq  101  ... ... .. ... 00 @cs_q
+  fsd 101  ... ... .. ... 00 @cs_d
+}
 sw110  ... ... .. ... 00 @cs_w
 
 # *** RV32C and RV64C specific Standard Extension (Quadrant 0) ***
@@ -132,7 +145,10 @@ addw  100 1 11 ... 01 ... 01 @cs_2
 
 # *** RV32/64C Standard Extension (Quadrant 2) ***
 slli  000 .  .  . 10 @c_shift2
-fld   001 .  .  . 10 @c_ldsp
+{
+  lq  001  ... ... .. ... 10 @c_lqsp
+  fld 001 .  .  . 10 @c_ldsp
+}
 {
   illegal 010 -  0  - 10 # c.lwsp, RES rd=0
   lw  010 .  .  . 10 @c_lwsp
@@ -147,7 +163,10 @@ fld   001 .  .  . 10 @c_ldsp
   jalr100 1  .  0 10 @c_jalr rd=1  # C.JALR
   add 100 1  .  . 10 @cr
 }
-fsd   101   ..  . 10 @c_sdsp
+{
+  sq  101  ... ... .. ... 10 @c_sqsp
+  fsd 101   ..  . 10 @c_sdsp
+}
 sw110 .  .  . 10 @c_swsp
 
 # *** RV32C and RV64C specific Standard 

[PATCH v4 06/12] tcg/mips: Create and use TCG_REG_TB

2022-01-07 Thread Richard Henderson
This vastly reduces the size of code generated for 64-bit addresses.
The code for exit_tb, for instance, where we load a (tagged) pointer
to the current TB, goes from

0x400aa9725c:  li   v0,64
0x400aa97260:  dsll v0,v0,0x10
0x400aa97264:  ori  v0,v0,0xaa9
0x400aa97268:  dsll v0,v0,0x10
0x400aa9726c:  j0x400aa9703c
0x400aa97270:  ori  v0,v0,0x7083

to

0x400aa97240:  j0x400aa97040
0x400aa97244:  daddiu   v0,s6,-189

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c.inc | 75 ---
 1 file changed, 62 insertions(+), 13 deletions(-)

diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 46616784f8..76fb1dada0 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -88,6 +88,11 @@ static const char * const 
tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 #ifndef CONFIG_SOFTMMU
 #define TCG_GUEST_BASE_REG TCG_REG_S7
 #endif
+#if TCG_TARGET_REG_BITS == 64
+#define TCG_REG_TB TCG_REG_S6
+#else
+#define TCG_REG_TB (qemu_build_not_reached(), TCG_REG_ZERO)
+#endif
 
 /* check if we really need so many registers :P */
 static const int tcg_target_reg_alloc_order[] = {
@@ -1971,34 +1976,72 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 switch (opc) {
 case INDEX_op_exit_tb:
 {
-TCGReg b0 = TCG_REG_ZERO;
+TCGReg base = TCG_REG_ZERO;
+int16_t lo = 0;
 
-a0 = (intptr_t)a0;
-if (a0 & ~0x) {
-tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0x);
-b0 = TCG_REG_V0;
+if (a0) {
+intptr_t ofs;
+if (TCG_TARGET_REG_BITS == 64) {
+ofs = tcg_tbrel_diff(s, (void *)a0);
+lo = ofs;
+if (ofs == lo) {
+base = TCG_REG_TB;
+} else {
+base = TCG_REG_V0;
+tcg_out_movi(s, TCG_TYPE_PTR, base, ofs - lo);
+tcg_out_opc_reg(s, ALIAS_PADD, base, base, TCG_REG_TB);
+}
+} else {
+ofs = a0;
+lo = ofs;
+base = TCG_REG_V0;
+tcg_out_movi(s, TCG_TYPE_PTR, base, ofs - lo);
+}
 }
 if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0,
  (uintptr_t)tb_ret_addr);
 tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
 }
-tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0x);
+tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_V0, base, lo);
 }
 break;
 case INDEX_op_goto_tb:
 /* indirect jump method */
 tcg_debug_assert(s->tb_jmp_insn_offset == 0);
-tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
-   (uintptr_t)(s->tb_jmp_target_addr + a0));
-tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
-tcg_out_nop(s);
-set_jmp_reset_offset(s, a0);
+{
+TCGReg base, dest;
+intptr_t ofs;
+
+if (TCG_TARGET_REG_BITS == 64) {
+dest = base = TCG_REG_TB;
+ofs = tcg_tbrel_diff(s, s->tb_jmp_target_addr + a0);
+} else {
+dest = TCG_TMP0;
+base = TCG_REG_ZERO;
+ofs = (intptr_t)(s->tb_jmp_target_addr + a0);
+}
+tcg_out_ld(s, TCG_TYPE_PTR, dest, base, ofs);
+tcg_out_opc_reg(s, OPC_JR, 0, dest, 0);
+/* delay slot */
+tcg_out_nop(s);
+
+set_jmp_reset_offset(s, args[0]);
+if (TCG_TARGET_REG_BITS == 64) {
+/* For the unlinked case, need to reset TCG_REG_TB. */
+tcg_out_ldst(s, ALIAS_PADDI, TCG_REG_TB, TCG_REG_TB,
+ -tcg_current_code_size(s));
+}
+}
 break;
 case INDEX_op_goto_ptr:
 /* jmp to the given host address (could be epilogue) */
 tcg_out_opc_reg(s, OPC_JR, 0, a0, 0);
-tcg_out_nop(s);
+if (TCG_TARGET_REG_BITS == 64) {
+tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, a0);
+} else {
+tcg_out_nop(s);
+}
 break;
 case INDEX_op_br:
 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO,
@@ -2554,7 +2597,7 @@ static const int tcg_target_callee_save_regs[] = {
 TCG_REG_S3,
 TCG_REG_S4,
 TCG_REG_S5,
-TCG_REG_S6,
+TCG_REG_S6,   /* used for the tb base (TCG_REG_TB) */
 TCG_REG_S7,   /* used for guest_base */
 TCG_REG_S8,   /* used for the global env (TCG_AREG0) */
 TCG_REG_RA,   /* should be last for ABI compliance */
@@ -2682,6 +2725,9 @@ static void tcg_target_qemu_prologue(TCGContext *s)
 tcg_regset_set_reg(s->reserved_regs, 

[PATCH v4 11/12] tcg/mips: Try tb-relative addresses in tcg_out_movi

2022-01-07 Thread Richard Henderson
These addresses are often loaded by the qemu_ld/st slow path,
for loading the retaddr value.

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c.inc | 13 +
 1 file changed, 13 insertions(+)

diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index e967f62869..a128c70154 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -582,6 +582,8 @@ static void tcg_out_movi_pool(TCGContext *s, TCGReg ret,
 static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret,
  tcg_target_long arg, TCGReg tbreg)
 {
+tcg_target_long tmp;
+
 if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
 arg = (int32_t)arg;
 }
@@ -592,6 +594,17 @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, 
TCGReg ret,
 }
 assert(TCG_TARGET_REG_BITS == 64);
 
+/* Load addresses within 2GB of TB with 1 or 3 insns. */
+tmp = tcg_tbrel_diff(s, (void *)arg);
+if (tmp == (int16_t)tmp) {
+tcg_out_opc_imm(s, OPC_DADDIU, ret, tbreg, tmp);
+return;
+}
+if (tcg_out_movi_two(s, ret, tmp)) {
+tcg_out_opc_reg(s, OPC_DADDU, ret, ret, tbreg);
+return;
+}
+
 /* Otherwise, put 64-bit constants into the constant pool. */
 tcg_out_movi_pool(s, ret, arg, tbreg);
 }
-- 
2.25.1




[PULL 37/37] target/riscv: Implement the stval/mtval illegal instruction

2022-01-07 Thread Alistair Francis
From: Alistair Francis 

The stval and mtval registers can optionally contain the faulting
instruction on an illegal instruction exception. This patch adds support
for setting the stval and mtval registers.

The RISC-V spec states that "The stval register can optionally also be
used to return the faulting instruction bits on an illegal instruction
exception...". In this case we are always writing the value on an
illegal instruction.

This doesn't match all CPUs (some CPUs won't write the data), but in
QEMU let's just populate the value on illegal instructions. This won't
break any guest software, but will provide more information to guests.

Signed-off-by: Alistair Francis 
Reviewed-by: Richard Henderson 
Reviewed-by: Bin Meng 
Message-id: 20211220064916.107241-4-alistair.fran...@opensource.wdc.com
---
 target/riscv/cpu.h| 2 ++
 target/riscv/cpu_helper.c | 3 +++
 target/riscv/translate.c  | 3 +++
 3 files changed, 8 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 9ee01f761f..4d63086765 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -132,6 +132,8 @@ struct CPURISCVState {
 target_ulong frm;
 
 target_ulong badaddr;
+uint32_t bins;
+
 target_ulong guest_phys_fault_addr;
 
 target_ulong priv_ver;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index ddacb8533a..434a83e66a 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1038,6 +1038,9 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 write_gva = true;
 tval = env->badaddr;
 break;
+case RISCV_EXCP_ILLEGAL_INST:
+tval = env->bins;
+break;
 default:
 break;
 }
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 9e4f9c3342..615048ec87 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -208,6 +208,9 @@ static void generate_exception_mtval(DisasContext *ctx, int 
excp)
 
 static void gen_exception_illegal(DisasContext *ctx)
 {
+tcg_gen_st_i32(tcg_constant_i32(ctx->opcode), cpu_env,
+   offsetof(CPURISCVState, bins));
+
 generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
 }
 
-- 
2.31.1




[PATCH v4 03/12] tcg/mips: Move TCG_AREG0 to S8

2022-01-07 Thread Richard Henderson
No functional change; just moving the saved reserved regs to the end.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.h | 2 +-
 tcg/mips/tcg-target.c.inc | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 7669213175..28c42e23e1 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -76,7 +76,7 @@ typedef enum {
 TCG_REG_RA,
 
 TCG_REG_CALL_STACK = TCG_REG_SP,
-TCG_AREG0 = TCG_REG_S0,
+TCG_AREG0 = TCG_REG_S8,
 } TCGReg;
 
 /* used for function call generation */
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 7682059d92..5702a6ad92 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -2548,7 +2548,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 }
 
 static const int tcg_target_callee_save_regs[] = {
-TCG_REG_S0,   /* used for the global env (TCG_AREG0) */
+TCG_REG_S0,
 TCG_REG_S1,
 TCG_REG_S2,
 TCG_REG_S3,
@@ -2556,7 +2556,7 @@ static const int tcg_target_callee_save_regs[] = {
 TCG_REG_S5,
 TCG_REG_S6,
 TCG_REG_S7,
-TCG_REG_S8,
+TCG_REG_S8,   /* used for the global env (TCG_AREG0) */
 TCG_REG_RA,   /* should be last for ABI compliance */
 };
 
-- 
2.25.1




[PULL 24/37] target/riscv: moving some insns close to similar insns

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

lwu and ld are functionally close to the other loads, but were after the
stores in the source file.
Similarly, xor was away from or and and by two arithmetic functions, while
the immediate versions were nicely put together.
This patch moves the aforementioned loads after lhu, and xor above or,
where they more logically belong.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-9-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvi.c.inc | 34 -
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 51607b3d40..710f5e6a85 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -176,6 +176,18 @@ static bool trans_lhu(DisasContext *ctx, arg_lhu *a)
 return gen_load(ctx, a, MO_TEUW);
 }
 
+static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
+{
+REQUIRE_64BIT(ctx);
+return gen_load(ctx, a, MO_TEUL);
+}
+
+static bool trans_ld(DisasContext *ctx, arg_ld *a)
+{
+REQUIRE_64BIT(ctx);
+return gen_load(ctx, a, MO_TEUQ);
+}
+
 static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
 {
 TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
@@ -207,18 +219,6 @@ static bool trans_sw(DisasContext *ctx, arg_sw *a)
 return gen_store(ctx, a, MO_TESL);
 }
 
-static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
-{
-REQUIRE_64BIT(ctx);
-return gen_load(ctx, a, MO_TEUL);
-}
-
-static bool trans_ld(DisasContext *ctx, arg_ld *a)
-{
-REQUIRE_64BIT(ctx);
-return gen_load(ctx, a, MO_TEUQ);
-}
-
 static bool trans_sd(DisasContext *ctx, arg_sd *a)
 {
 REQUIRE_64BIT(ctx);
@@ -317,11 +317,6 @@ static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
 return gen_arith(ctx, a, EXT_SIGN, gen_sltu);
 }
 
-static bool trans_xor(DisasContext *ctx, arg_xor *a)
-{
-return gen_logic(ctx, a, tcg_gen_xor_tl);
-}
-
 static bool trans_srl(DisasContext *ctx, arg_srl *a)
 {
 return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl);
@@ -332,6 +327,11 @@ static bool trans_sra(DisasContext *ctx, arg_sra *a)
 return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl);
 }
 
+static bool trans_xor(DisasContext *ctx, arg_xor *a)
+{
+return gen_logic(ctx, a, tcg_gen_xor_tl);
+}
+
 static bool trans_or(DisasContext *ctx, arg_or *a)
 {
 return gen_logic(ctx, a, tcg_gen_or_tl);
-- 
2.31.1




[PATCH v4 10/12] tcg/mips: Aggressively use the constant pool for n64 calls

2022-01-07 Thread Richard Henderson
Repeated calls to a single helper are common -- especially
the ones for softmmu memory access.  Prefer the constant pool
to longer sequences to increase sharing.

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c.inc | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 41cb155eb0..e967f62869 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -1057,9 +1057,19 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, 
TCGReg ret,
 
 static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool 
tail)
 {
-/* Note that the ABI requires the called function's address to be
-   loaded into T9, even if a direct branch is in range.  */
-tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg);
+/*
+ * Note that __mips_abicalls requires the called function's address
+ * to be loaded into $25 (t9), even if a direct branch is in range.
+ *
+ * For n64, always drop the pointer into the constant pool.
+ * We can re-use helper addresses often and do not want any
+ * of the longer sequences tcg_out_movi may try.
+ */
+if (sizeof(uintptr_t) == 8) {
+tcg_out_movi_pool(s, TCG_REG_T9, (uintptr_t)arg, TCG_REG_TB);
+} else {
+tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg);
+}
 
 /* But do try a direct branch, allowing the cpu better insn prefetch.  */
 if (tail) {
-- 
2.25.1




[PULL 36/37] target/riscv: Fixup setting GVA

2022-01-07 Thread Alistair Francis
From: Alistair Francis 

In preparation for adding support for the illegal instruction address
let's fixup the Hypervisor extension setting GVA logic and improve the
variable names.

Signed-off-by: Alistair Francis 
Reviewed-by: Richard Henderson 
Reviewed-by: Bin Meng 
Message-id: 20211220064916.107241-3-alistair.fran...@opensource.wdc.com
---
 target/riscv/cpu_helper.c | 21 ++---
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 10f3baba53..ddacb8533a 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -998,6 +998,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
+bool write_gva = false;
 uint64_t s;
 
 /* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
@@ -1006,7 +1007,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG);
 target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
 target_ulong deleg = async ? env->mideleg : env->medeleg;
-bool write_tval = false;
 target_ulong tval = 0;
 target_ulong htval = 0;
 target_ulong mtval2 = 0;
@@ -1035,7 +1035,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 case RISCV_EXCP_INST_PAGE_FAULT:
 case RISCV_EXCP_LOAD_PAGE_FAULT:
 case RISCV_EXCP_STORE_PAGE_FAULT:
-write_tval  = true;
+write_gva = true;
 tval = env->badaddr;
 break;
 default:
@@ -1072,18 +1072,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 if (riscv_has_ext(env, RVH)) {
 target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
 
-if (env->two_stage_lookup && write_tval) {
-/*
- * If we are writing a guest virtual address to stval, set
- * this to 1. If we are trapping to VS we will set this to 0
- * later.
- */
-env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 1);
-} else {
-/* For other HS-mode traps, we set this to 0. */
-env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 0);
-}
-
 if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1)) {
 /* Trap to VS mode */
 /*
@@ -1094,7 +1082,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 cause == IRQ_VS_EXT) {
 cause = cause - 1;
 }
-env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 0);
+write_gva = false;
 } else if (riscv_cpu_virt_enabled(env)) {
 /* Trap into HS mode, from virt */
 riscv_cpu_swap_hypervisor_regs(env);
@@ -1103,6 +1091,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
  riscv_cpu_virt_enabled(env));
 
+
 htval = env->guest_phys_fault_addr;
 
 riscv_cpu_set_virt_enabled(env, 0);
@@ -1110,7 +1099,9 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 /* Trap into HS mode */
 env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false);
 htval = env->guest_phys_fault_addr;
+write_gva = false;
 }
+env->hstatus = set_field(env->hstatus, HSTATUS_GVA, write_gva);
 }
 
 s = env->mstatus;
-- 
2.31.1




[PULL 20/37] target/riscv: additional macros to check instruction support

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

Given that the 128-bit version of the riscv spec adds new instructions, and
that some instructions that were previously only available in 64-bit mode
are now available for both 64-bit and 128-bit, we added new macros to check
for the processor mode during translation.
Although RV128 is a superset of RV64, we keep for now the RV64 only tests
for extensions other than RVI and RVM.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-5-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/translate.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 5df6c0d800..502bf0d009 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -443,10 +443,22 @@ EX_SH(12)
 }  \
 } while (0)
 
-#define REQUIRE_64BIT(ctx) do {\
-if (get_xl(ctx) < MXL_RV64) {  \
-return false;  \
-}  \
+#define REQUIRE_64BIT(ctx) do { \
+if (get_xl(ctx) != MXL_RV64) {  \
+return false;   \
+}   \
+} while (0)
+
+#define REQUIRE_128BIT(ctx) do {\
+if (get_xl(ctx) != MXL_RV128) { \
+return false;   \
+}   \
+} while (0)
+
+#define REQUIRE_64_OR_128BIT(ctx) do { \
+if (get_xl(ctx) == MXL_RV32) { \
+return false;  \
+}  \
 } while (0)
 
 static int ex_rvc_register(DisasContext *ctx, int reg)
-- 
2.31.1




[PATCH v4 01/12] tcg/mips: Support unaligned access for user-only

2022-01-07 Thread Richard Henderson
This is kinda sorta the opposite of the other tcg hosts, where
we get (normal) alignment checks for free with host SIGBUS and
need to add code to support unaligned accesses.

Fortunately, the ISA contains pairs of instructions that are
used to implement unaligned memory accesses.  Use them.

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.h |   2 -
 tcg/mips/tcg-target.c.inc | 334 +-
 2 files changed, 328 insertions(+), 8 deletions(-)

diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index c366fdf74b..7669213175 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -207,8 +207,6 @@ extern bool use_mips32r2_instructions;
 void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t)
 QEMU_ERROR("code path is reachable");
 
-#ifdef CONFIG_SOFTMMU
 #define TCG_TARGET_NEED_LDST_LABELS
-#endif
 
 #endif
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index d8f6914f03..5737d8a269 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -24,6 +24,8 @@
  * THE SOFTWARE.
  */
 
+#include "../tcg-ldst.c.inc"
+
 #ifdef HOST_WORDS_BIGENDIAN
 # define MIPS_BE  1
 #else
@@ -230,16 +232,26 @@ typedef enum {
 OPC_ORI  = 015 << 26,
 OPC_XORI = 016 << 26,
 OPC_LUI  = 017 << 26,
+OPC_BNEL = 025 << 26,
+OPC_BNEZALC_R6 = 030 << 26,
 OPC_DADDIU   = 031 << 26,
+OPC_LDL  = 032 << 26,
+OPC_LDR  = 033 << 26,
 OPC_LB   = 040 << 26,
 OPC_LH   = 041 << 26,
+OPC_LWL  = 042 << 26,
 OPC_LW   = 043 << 26,
 OPC_LBU  = 044 << 26,
 OPC_LHU  = 045 << 26,
+OPC_LWR  = 046 << 26,
 OPC_LWU  = 047 << 26,
 OPC_SB   = 050 << 26,
 OPC_SH   = 051 << 26,
+OPC_SWL  = 052 << 26,
 OPC_SW   = 053 << 26,
+OPC_SDL  = 054 << 26,
+OPC_SDR  = 055 << 26,
+OPC_SWR  = 056 << 26,
 OPC_LD   = 067 << 26,
 OPC_SD   = 077 << 26,
 
@@ -1015,8 +1027,6 @@ static void tcg_out_call(TCGContext *s, const 
tcg_insn_unit *arg)
 }
 
 #if defined(CONFIG_SOFTMMU)
-#include "../tcg-ldst.c.inc"
-
 static void * const qemu_ld_helpers[(MO_SSIZE | MO_BSWAP) + 1] = {
 [MO_UB]   = helper_ret_ldub_mmu,
 [MO_SB]   = helper_ret_ldsb_mmu,
@@ -1324,7 +1334,82 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
 return true;
 }
-#endif
+
+#else
+
+static void tcg_out_test_alignment(TCGContext *s, bool is_ld, TCGReg addrlo,
+   TCGReg addrhi, unsigned a_bits)
+{
+unsigned a_mask = (1 << a_bits) - 1;
+TCGLabelQemuLdst *l = new_ldst_label(s);
+
+l->is_ld = is_ld;
+l->addrlo_reg = addrlo;
+l->addrhi_reg = addrhi;
+
+/* We are expecting a_bits to max out at 7, much lower than ANDI. */
+tcg_debug_assert(a_bits < 16);
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, addrlo, a_mask);
+
+l->label_ptr[0] = s->code_ptr;
+if (use_mips32r6_instructions) {
+tcg_out_opc_br(s, OPC_BNEZALC_R6, TCG_REG_ZERO, TCG_TMP0);
+} else {
+tcg_out_opc_br(s, OPC_BNEL, TCG_TMP0, TCG_REG_ZERO);
+tcg_out_nop(s);
+}
+
+l->raddr = tcg_splitwx_to_rx(s->code_ptr);
+}
+
+static bool tcg_out_fail_alignment(TCGContext *s, TCGLabelQemuLdst *l)
+{
+void *target;
+
+if (!reloc_pc16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
+return false;
+}
+
+if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
+/* A0 is env, A1 is skipped, A2:A3 is the uint64_t address. */
+TCGReg a2 = MIPS_BE ? l->addrhi_reg : l->addrlo_reg;
+TCGReg a3 = MIPS_BE ? l->addrlo_reg : l->addrhi_reg;
+
+if (a3 != TCG_REG_A2) {
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_A2, a2);
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_A3, a3);
+} else if (a2 != TCG_REG_A3) {
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_A3, a3);
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_A2, a2);
+} else {
+tcg_out_mov(s, TCG_TYPE_I32, TCG_TMP0, TCG_REG_A2);
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_A2, TCG_REG_A3);
+tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_A3, TCG_TMP0);
+}
+} else {
+tcg_out_mov(s, TCG_TYPE_TL, TCG_REG_A1, l->addrlo_reg);
+}
+tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0);
+
+/*
+ * Tail call to the helper, with the return address back inline.
+ * We have arrived here via BNEL, so $31 is already set.
+ */
+target = (l->is_ld ? helper_unaligned_ld : helper_unaligned_st);
+tcg_out_call_int(s, target, true);
+return true;
+}
+
+static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
+{
+return tcg_out_fail_alignment(s, l);
+}
+
+static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
+{
+return tcg_out_fail_alignment(s, l);
+}
+#endif /* 

[PULL 35/37] target/riscv: Set the opcode in DisasContext

2022-01-07 Thread Alistair Francis
From: Alistair Francis 

Signed-off-by: Alistair Francis 
Reviewed-by: Richard Henderson 
Reviewed-by: Bin Meng 
Message-id: 20211220064916.107241-2-alistair.fran...@opensource.wdc.com
---
 target/riscv/translate.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 4ae4345691..9e4f9c3342 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -846,6 +846,7 @@ static void decode_opc(CPURISCVState *env, DisasContext 
*ctx, uint16_t opcode)
 if (!has_ext(ctx, RVC)) {
 gen_exception_illegal(ctx);
 } else {
+ctx->opcode = opcode;
 ctx->pc_succ_insn = ctx->base.pc_next + 2;
 if (!decode_insn16(ctx, opcode)) {
 gen_exception_illegal(ctx);
@@ -856,6 +857,7 @@ static void decode_opc(CPURISCVState *env, DisasContext 
*ctx, uint16_t opcode)
 opcode32 = deposit32(opcode32, 16, 16,
  translator_lduw(env, >base,
  ctx->base.pc_next + 2));
+ctx->opcode = opcode32;
 ctx->pc_succ_insn = ctx->base.pc_next + 4;
 if (!decode_insn32(ctx, opcode32)) {
 gen_exception_illegal(ctx);
-- 
2.31.1




[PATCH v4 00/12] tcg/mips: Unaligned access and other cleanup

2022-01-07 Thread Richard Henderson
Based-on: <20220104021543.396571-1-richard.hender...@linaro.org>
("[PATCH v4 0/7] Unaligned access for user only")

Changes from v3:
  * Rebase on master, which has some patches applied.


r~


Richard Henderson (12):
  tcg/mips: Support unaligned access for user-only
  tcg/mips: Support unaligned access for softmmu
  tcg/mips: Move TCG_AREG0 to S8
  tcg/mips: Move TCG_GUEST_BASE_REG to S7
  tcg/mips: Unify TCG_GUEST_BASE_REG tests
  tcg/mips: Create and use TCG_REG_TB
  tcg/mips: Split out tcg_out_movi_one
  tcg/mips: Split out tcg_out_movi_two
  tcg/mips: Use the constant pool for 64-bit constants
  tcg/mips: Aggressively use the constant pool for n64 calls
  tcg/mips: Try tb-relative addresses in tcg_out_movi
  tcg/mips: Try three insns with shift and add in tcg_out_movi

 tcg/mips/tcg-target.h |   5 +-
 tcg/mips/tcg-target.c.inc | 647 +-
 2 files changed, 579 insertions(+), 73 deletions(-)

-- 
2.25.1




[PULL 16/37] target/riscv: Fix position of 'experimental' comment

2022-01-07 Thread Alistair Francis
From: Philipp Tomsich 

When commit 0643c12e4b dropped the 'x-' prefix for Zb[abcs] and set
them to be enabled by default, the comment about experimental
extensions was kept in place above them.  This moves it down a few
lines to only cover experimental extensions.

References: 0643c12e4b ("target/riscv: Enable bitmanip Zb[abcs] instructions")

Signed-off-by: Philipp Tomsich 
Reviewed-by: Bin Meng 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
Message-id: 20220106134020.1628889-1-philipp.toms...@vrull.eu
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 29749e834f..ce21c1b5b1 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -641,11 +641,12 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
 DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
 
-/* These are experimental so mark with 'x-' */
 DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
 DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
 DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
 DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true),
+
+/* These are experimental so mark with 'x-' */
 DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
 /* ePMP 0.9.3 */
 DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
-- 
2.31.1




[PATCH v4 5/7] tcg/arm: Support unaligned access for softmmu

2022-01-07 Thread Richard Henderson
>From armv6, the architecture supports unaligned accesses.
All we need to do is perform the correct alignment check
in tcg_out_tlb_read.

Signed-off-by: Richard Henderson 
---
 tcg/arm/tcg-target.c.inc | 39 ++-
 1 file changed, 18 insertions(+), 21 deletions(-)

diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index 8a20224dd1..b6ef279cae 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -34,7 +34,6 @@ bool use_idiv_instructions;
 bool use_neon_instructions;
 #endif
 
-/* ??? Ought to think about changing CONFIG_SOFTMMU to always defined.  */
 #ifdef CONFIG_DEBUG_TCG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 "%r0",  "%r1",  "%r2",  "%r3",  "%r4",  "%r5",  "%r6",  "%r7",
@@ -1397,16 +1396,9 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg 
addrlo, TCGReg addrhi,
 int cmp_off = (is_load ? offsetof(CPUTLBEntry, addr_read)
: offsetof(CPUTLBEntry, addr_write));
 int fast_off = TLB_MASK_TABLE_OFS(mem_index);
-unsigned s_bits = opc & MO_SIZE;
-unsigned a_bits = get_alignment_bits(opc);
-
-/*
- * We don't support inline unaligned acceses, but we can easily
- * support overalignment checks.
- */
-if (a_bits < s_bits) {
-a_bits = s_bits;
-}
+unsigned s_mask = (1 << (opc & MO_SIZE)) - 1;
+unsigned a_mask = (1 << get_alignment_bits(opc)) - 1;
+TCGReg t_addr;
 
 /* Load env_tlb(env)->f[mmu_idx].{mask,table} into {r0,r1}.  */
 tcg_out_ldrd_8(s, COND_AL, TCG_REG_R0, TCG_AREG0, fast_off);
@@ -1441,27 +1433,32 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg 
addrlo, TCGReg addrhi,
 
 /*
  * Check alignment, check comparators.
- * Do this in no more than 3 insns.  Use MOVW for v7, if possible,
+ * Do this in 2-4 insns.  Use MOVW for v7, if possible,
  * to reduce the number of sequential conditional instructions.
  * Almost all guests have at least 4k pages, which means that we need
  * to clear at least 9 bits even for an 8-byte memory, which means it
  * isn't worth checking for an immediate operand for BIC.
  */
+/* For unaligned accesses, test the page of the last byte. */
+t_addr = addrlo;
+if (a_mask < s_mask) {
+t_addr = TCG_REG_R0;
+tcg_out_dat_imm(s, COND_AL, ARITH_ADD, t_addr,
+addrlo, s_mask - a_mask);
+}
 if (use_armv7_instructions && TARGET_PAGE_BITS <= 16) {
-tcg_target_ulong mask = ~(TARGET_PAGE_MASK | ((1 << a_bits) - 1));
-
-tcg_out_movi32(s, COND_AL, TCG_REG_TMP, mask);
+tcg_out_movi32(s, COND_AL, TCG_REG_TMP, ~(TARGET_PAGE_MASK | a_mask));
 tcg_out_dat_reg(s, COND_AL, ARITH_BIC, TCG_REG_TMP,
-addrlo, TCG_REG_TMP, 0);
+t_addr, TCG_REG_TMP, 0);
 tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R2, TCG_REG_TMP, 0);
 } else {
-if (a_bits) {
-tcg_out_dat_imm(s, COND_AL, ARITH_TST, 0, addrlo,
-(1 << a_bits) - 1);
+if (a_mask) {
+tcg_debug_assert(a_mask <= 0xff);
+tcg_out_dat_imm(s, COND_AL, ARITH_TST, 0, addrlo, a_mask);
 }
-tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP, 0, addrlo,
+tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP, 0, t_addr,
 SHIFT_IMM_LSR(TARGET_PAGE_BITS));
-tcg_out_dat_reg(s, (a_bits ? COND_EQ : COND_AL), ARITH_CMP,
+tcg_out_dat_reg(s, (a_mask ? COND_EQ : COND_AL), ARITH_CMP,
 0, TCG_REG_R2, TCG_REG_TMP,
 SHIFT_IMM_LSL(TARGET_PAGE_BITS));
 }
-- 
2.25.1




Re: [PATCH v6 18/23] hw/intc: Add RISC-V AIA APLIC device emulation

2022-01-07 Thread Frank Chang
Anup Patel  於 2021年12月30日 週四 下午8:55寫道:

> From: Anup Patel 
>
> The RISC-V AIA (Advanced Interrupt Architecture) defines a new
> interrupt controller for wired interrupts called APLIC (Advanced
> Platform Level Interrupt Controller). The APLIC is capabable of
> forwarding wired interupts to RISC-V HARTs directly or as MSIs
> (Message Signaled Interupts).
>
> This patch adds device emulation for RISC-V AIA APLIC.
>
> Signed-off-by: Anup Patel 
> Signed-off-by: Anup Patel 
> ---
>  hw/intc/Kconfig   |   3 +
>  hw/intc/meson.build   |   1 +
>  hw/intc/riscv_aplic.c | 970 ++
>  include/hw/intc/riscv_aplic.h |  79 +++
>  4 files changed, 1053 insertions(+)
>  create mode 100644 hw/intc/riscv_aplic.c
>  create mode 100644 include/hw/intc/riscv_aplic.h
>
> diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
> index 010ded7eae..528e77b4a6 100644
> --- a/hw/intc/Kconfig
> +++ b/hw/intc/Kconfig
> @@ -70,6 +70,9 @@ config LOONGSON_LIOINTC
>  config RISCV_ACLINT
>  bool
>
> +config RISCV_APLIC
> +bool
> +
>  config SIFIVE_PLIC
>  bool
>
> diff --git a/hw/intc/meson.build b/hw/intc/meson.build
> index 70080bc161..7466024402 100644
> --- a/hw/intc/meson.build
> +++ b/hw/intc/meson.build
> @@ -50,6 +50,7 @@ specific_ss.add(when: 'CONFIG_S390_FLIC', if_true:
> files('s390_flic.c'))
>  specific_ss.add(when: 'CONFIG_S390_FLIC_KVM', if_true:
> files('s390_flic_kvm.c'))
>  specific_ss.add(when: 'CONFIG_SH_INTC', if_true: files('sh_intc.c'))
>  specific_ss.add(when: 'CONFIG_RISCV_ACLINT', if_true:
> files('riscv_aclint.c'))
> +specific_ss.add(when: 'CONFIG_RISCV_APLIC', if_true:
> files('riscv_aplic.c'))
>  specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true:
> files('sifive_plic.c'))
>  specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c'))
>  specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XICS'],
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> new file mode 100644
> index 00..f4b8828dac
> --- /dev/null
> +++ b/hw/intc/riscv_aplic.c
> @@ -0,0 +1,970 @@
> +/*
> + * RISC-V APLIC (Advanced Platform Level Interrupt Controller)
> + *
> + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2 or later, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> along with
> + * this program.  If not, see .
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu/log.h"
> +#include "qemu/module.h"
> +#include "qemu/error-report.h"
> +#include "qemu/bswap.h"
> +#include "exec/address-spaces.h"
> +#include "hw/sysbus.h"
> +#include "hw/pci/msi.h"
> +#include "hw/boards.h"
> +#include "hw/qdev-properties.h"
> +#include "hw/intc/riscv_aplic.h"
> +#include "hw/irq.h"
> +#include "target/riscv/cpu.h"
> +#include "sysemu/sysemu.h"
> +#include "migration/vmstate.h"
> +
> +#define APLIC_MAX_IDC  (1UL << 14)
> +#define APLIC_MAX_SOURCE   1024
> +#define APLIC_MIN_IPRIO_BITS   1
> +#define APLIC_MAX_IPRIO_BITS   8
> +#define APLIC_MAX_CHILDREN 1024
> +
> +#define APLIC_DOMAINCFG0x
> +#define APLIC_DOMAINCFG_IE (1 << 8)
> +#define APLIC_DOMAINCFG_DM (1 << 2)
> +#define APLIC_DOMAINCFG_BE (1 << 0)
> +
> +#define APLIC_SOURCECFG_BASE   0x0004
> +#define APLIC_SOURCECFG_D  (1 << 10)
> +#define APLIC_SOURCECFG_CHILDIDX_MASK  0x03ff
> +#define APLIC_SOURCECFG_SM_MASK0x0007
> +#define APLIC_SOURCECFG_SM_INACTIVE0x0
> +#define APLIC_SOURCECFG_SM_DETACH  0x1
> +#define APLIC_SOURCECFG_SM_EDGE_RISE   0x4
> +#define APLIC_SOURCECFG_SM_EDGE_FALL   0x5
> +#define APLIC_SOURCECFG_SM_LEVEL_HIGH  0x6
> +#define APLIC_SOURCECFG_SM_LEVEL_LOW   0x7
> +
> +#define APLIC_MMSICFGADDR  0x1bc0
> +#define APLIC_MMSICFGADDRH 0x1bc4
> +#define APLIC_SMSICFGADDR  0x1bc8
> +#define APLIC_SMSICFGADDRH 0x1bcc
> +
> +#define APLIC_xMSICFGADDRH_L   (1UL << 31)
> +#define APLIC_xMSICFGADDRH_HHXS_MASK   0x1f
> +#define APLIC_xMSICFGADDRH_HHXS_SHIFT  24
> +#define APLIC_xMSICFGADDRH_LHXS_MASK   0x7
> +#define APLIC_xMSICFGADDRH_LHXS_SHIFT  20
> +#define APLIC_xMSICFGADDRH_HHXW_MASK   0x7
> +#define APLIC_xMSICFGADDRH_HHXW_SHIFT  16
> +#define APLIC_xMSICFGADDRH_LHXW_MASK   0xf
> +#define APLIC_xMSICFGADDRH_LHXW_SHIFT  12
> +#define APLIC_xMSICFGADDRH_BAPPN_MASK  0xfff
> +
> +#define APLIC_xMSICFGADDR_PPN_SHIFT12
> 

[PULL 34/37] target/riscv: actual functions to realize crs 128-bit insns

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

The csrs are accessed through function pointers: we add 128-bit read
operations in the table for three csrs (writes fallback to the
64-bit version as the upper 64-bit information is handled elsewhere):
- misa, as mxl is needed for proper operation,
- mstatus and sstatus, to return sd
In addition, we also add read and write accesses to the machine and
supervisor scratch registers.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-19-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h  |   7 ++
 target/riscv/cpu_bits.h |   3 +
 target/riscv/csr.c  | 195 +---
 3 files changed, 175 insertions(+), 30 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 73d3d22f26..9ee01f761f 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -505,12 +505,19 @@ RISCVException riscv_csrrw_i128(CPURISCVState *env, int 
csrno,
 Int128 *ret_value,
 Int128 new_value, Int128 write_mask);
 
+typedef RISCVException (*riscv_csr_read128_fn)(CPURISCVState *env, int csrno,
+   Int128 *ret_value);
+typedef RISCVException (*riscv_csr_write128_fn)(CPURISCVState *env, int csrno,
+ Int128 new_value);
+
 typedef struct {
 const char *name;
 riscv_csr_predicate_fn predicate;
 riscv_csr_read_fn read;
 riscv_csr_write_fn write;
 riscv_csr_op_fn op;
+riscv_csr_read128_fn read128;
+riscv_csr_write128_fn write128;
 } riscv_csr_operations;
 
 /* CSR function table constants */
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 1e31f4d35f..5a6d49aa64 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -401,6 +401,7 @@
 
 #define MSTATUS32_SD0x8000
 #define MSTATUS64_SD0x8000ULL
+#define MSTATUSH128_SD  0x8000ULL
 
 #define MISA32_MXL  0xC000
 #define MISA64_MXL  0xC000ULL
@@ -423,6 +424,8 @@ typedef enum {
 #define SSTATUS_SUM 0x0004 /* since: priv-1.10 */
 #define SSTATUS_MXR 0x0008
 
+#define SSTATUS64_UXL   0x0003ULL
+
 #define SSTATUS32_SD0x8000
 #define SSTATUS64_SD0x8000ULL
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 4c6a44c0b8..adb3d4381d 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -481,7 +481,7 @@ static const target_ulong vs_delegable_excps = 
DELEGABLE_EXCPS &
   (1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT)));
 static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
 SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
-SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS;
+SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS | (target_ulong)SSTATUS64_UXL;
 static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
 static const target_ulong hip_writable_mask = MIP_VSSIP;
 static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
MIP_VSEIP;
@@ -527,6 +527,8 @@ static uint64_t add_status_sd(RISCVMXL xl, uint64_t status)
 return status | MSTATUS32_SD;
 case MXL_RV64:
 return status | MSTATUS64_SD;
+case MXL_RV128:
+return MSTATUSH128_SD;
 default:
 g_assert_not_reached();
 }
@@ -576,10 +578,11 @@ static RISCVException write_mstatus(CPURISCVState *env, 
int csrno,
 
 mstatus = (mstatus & ~mask) | (val & mask);
 
-if (riscv_cpu_mxl(env) == MXL_RV64) {
+RISCVMXL xl = riscv_cpu_mxl(env);
+if (xl > MXL_RV32) {
 /* SXL and UXL fields are for now read only */
-mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64);
-mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64);
+mstatus = set_field(mstatus, MSTATUS64_SXL, xl);
+mstatus = set_field(mstatus, MSTATUS64_UXL, xl);
 }
 env->mstatus = mstatus;
 
@@ -608,6 +611,20 @@ static RISCVException write_mstatush(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
+static RISCVException read_mstatus_i128(CPURISCVState *env, int csrno,
+Int128 *val)
+{
+*val = int128_make128(env->mstatus, add_status_sd(MXL_RV128, 
env->mstatus));
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_misa_i128(CPURISCVState *env, int csrno,
+ Int128 *val)
+{
+*val = int128_make128(env->misa_ext, (uint64_t)MXL_RV128 << 62);
+return RISCV_EXCP_NONE;
+}
+
 static RISCVException read_misa(CPURISCVState *env, int csrno,
 target_ulong *val)
 {
@@ -765,6 +782,21 @@ static RISCVException write_mcounteren(CPURISCVState *env, 
int csrno,
 }
 
 /* Machine Trap Handling */
+static 

[PULL 15/37] target/riscv: rvv-1.0: Call the correct RVF/RVD check function for narrowing fp/int type-convert insns

2022-01-07 Thread Alistair Francis
From: Frank Chang 

vfncvt.f.xu.w, vfncvt.f.x.w convert double-width integer to single-width
floating-point. Therefore, should use require_rvf() to check whether
RVF/RVD is enabled.

vfncvt.f.f.w, vfncvt.rod.f.f.w convert double-width floating-point to
single-width integer. Therefore, should use require_scale_rvf() to check
whether RVF/RVD is enabled.

Signed-off-by: Frank Chang 
Acked-by: Alistair Francis 
Message-Id: <20220105022247.21131-4-frank.ch...@sifive.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvv.c.inc | 32 ++---
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
b/target/riscv/insn_trans/trans_rvv.c.inc
index f1b44ccad2..6c285c958b 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -2719,17 +2719,29 @@ GEN_OPFXV_WIDEN_TRANS(vfwcvt_f_x_v)
 static bool opfv_narrow_check(DisasContext *s, arg_rmr *a)
 {
 return require_rvv(s) &&
-   require_rvf(s) &&
-   (s->sew != MO_64) &&
vext_check_isa_ill(s) &&
/* OPFV narrowing instructions ignore vs1 check */
vext_check_sd(s, a->rd, a->rs2, a->vm);
 }
 
-#define GEN_OPFV_NARROW_TRANS(NAME, HELPER, FRM)   \
+static bool opfxv_narrow_check(DisasContext *s, arg_rmr *a)
+{
+return opfv_narrow_check(s, a) &&
+   require_rvf(s) &&
+   (s->sew != MO_64);
+}
+
+static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
+{
+return opfv_narrow_check(s, a) &&
+   require_scale_rvf(s) &&
+   (s->sew != MO_8);
+}
+
+#define GEN_OPFV_NARROW_TRANS(NAME, CHECK, HELPER, FRM)\
 static bool trans_##NAME(DisasContext *s, arg_rmr *a)  \
 {  \
-if (opfv_narrow_check(s, a)) { \
+if (CHECK(s, a)) { \
 if (FRM != RISCV_FRM_DYN) {\
 gen_set_rm(s, RISCV_FRM_DYN);  \
 }  \
@@ -2756,11 +2768,15 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a)   
   \
 return false;  \
 }
 
-GEN_OPFV_NARROW_TRANS(vfncvt_f_xu_w, vfncvt_f_xu_w, RISCV_FRM_DYN)
-GEN_OPFV_NARROW_TRANS(vfncvt_f_x_w, vfncvt_f_x_w, RISCV_FRM_DYN)
-GEN_OPFV_NARROW_TRANS(vfncvt_f_f_w, vfncvt_f_f_w, RISCV_FRM_DYN)
+GEN_OPFV_NARROW_TRANS(vfncvt_f_xu_w, opfxv_narrow_check, vfncvt_f_xu_w,
+  RISCV_FRM_DYN)
+GEN_OPFV_NARROW_TRANS(vfncvt_f_x_w, opfxv_narrow_check, vfncvt_f_x_w,
+  RISCV_FRM_DYN)
+GEN_OPFV_NARROW_TRANS(vfncvt_f_f_w, opffv_narrow_check, vfncvt_f_f_w,
+  RISCV_FRM_DYN)
 /* Reuse the helper function from vfncvt.f.f.w */
-GEN_OPFV_NARROW_TRANS(vfncvt_rod_f_f_w, vfncvt_f_f_w, RISCV_FRM_ROD)
+GEN_OPFV_NARROW_TRANS(vfncvt_rod_f_f_w, opffv_narrow_check, vfncvt_f_f_w,
+  RISCV_FRM_ROD)
 
 static bool opxfv_narrow_check(DisasContext *s, arg_rmr *a)
 {
-- 
2.31.1




[PATCH v4 1/7] tcg/arm: Drop support for armv4 and armv5 hosts

2022-01-07 Thread Richard Henderson
Support for unaligned accesses is difficult for pre-v6 hosts.
While debian still builds for armv4, we cannot use a compile
time test, so test the architecture at runtime and error out.

Signed-off-by: Richard Henderson 
---
 tcg/arm/tcg-target.c.inc | 5 +
 1 file changed, 5 insertions(+)

diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index 9d322cdba6..72b384cc28 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -2474,6 +2474,11 @@ static void tcg_target_init(TCGContext *s)
 if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') {
 arm_arch = pl[1] - '0';
 }
+
+if (arm_arch < 6) {
+error_report("TCG: ARMv%d is unsupported; exiting", arm_arch);
+exit(EXIT_FAILURE);
+}
 }
 
 tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS;
-- 
2.25.1




[PULL 30/37] target/riscv: support for 128-bit M extension

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

Mult are generated inline (using a cool trick pointed out by Richard), but
for div and rem, given the complexity of the implementation of these
instructions, we call helpers to produce their behavior. From an
implementation standpoint, the helpers return the low part of the results,
while the high part is temporarily stored in a dedicated field of cpu_env
that is used to update the architectural register in the generation wrapper.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-15-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h  |   3 +
 target/riscv/helper.h   |   6 +
 target/riscv/insn32.decode  |   7 +
 target/riscv/m128_helper.c  | 109 ++
 target/riscv/insn_trans/trans_rvm.c.inc | 182 ++--
 target/riscv/meson.build|   1 +
 6 files changed, 295 insertions(+), 13 deletions(-)
 create mode 100644 target/riscv/m128_helper.c

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index fd583e0f41..b9dee7d147 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -143,6 +143,9 @@ struct CPURISCVState {
 uint32_t misa_ext;  /* current extensions */
 uint32_t misa_ext_mask; /* max ext for this cpu */
 
+/* 128-bit helpers upper part return value */
+target_ulong retxh;
+
 uint32_t features;
 
 #ifdef CONFIG_USER_ONLY
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index c15497e4a1..a8ee8a362a 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1101,3 +1101,9 @@ DEF_HELPER_5(vsext_vf2_d, void, ptr, ptr, ptr, env, i32)
 DEF_HELPER_5(vsext_vf4_w, void, ptr, ptr, ptr, env, i32)
 DEF_HELPER_5(vsext_vf4_d, void, ptr, ptr, ptr, env, i32)
 DEF_HELPER_5(vsext_vf8_d, void, ptr, ptr, ptr, env, i32)
+
+/* 128-bit integer multiplication and division */
+DEF_HELPER_5(divu_i128, tl, env, tl, tl, tl, tl)
+DEF_HELPER_5(divs_i128, tl, env, tl, tl, tl, tl)
+DEF_HELPER_5(remu_i128, tl, env, tl, tl, tl, tl)
+DEF_HELPER_5(rems_i128, tl, env, tl, tl, tl, tl)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 42366d20fb..5bbedc254c 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -197,6 +197,13 @@ divuw001 .  . 101 . 0111011 @r
 remw 001 .  . 110 . 0111011 @r
 remuw001 .  . 111 . 0111011 @r
 
+# *** RV128M Standard Extension (in addition to RV64M) ***
+muld 001 .  . 000 . 011 @r
+divd 001 .  . 100 . 011 @r
+divud001 .  . 101 . 011 @r
+remd 001 .  . 110 . 011 @r
+remud001 .  . 111 . 011 @r
+
 # *** RV32A Standard Extension ***
 lr_w   00010 . . 0 . 010 . 010 @atom_ld
 sc_w   00011 . . . . 010 . 010 @atom_st
diff --git a/target/riscv/m128_helper.c b/target/riscv/m128_helper.c
new file mode 100644
index 00..7bf115b85e
--- /dev/null
+++ b/target/riscv/m128_helper.c
@@ -0,0 +1,109 @@
+/*
+ * RISC-V Emulation Helpers for QEMU.
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "qemu/main-loop.h"
+#include "exec/exec-all.h"
+#include "exec/helper-proto.h"
+
+target_ulong HELPER(divu_i128)(CPURISCVState *env,
+   target_ulong ul, target_ulong uh,
+   target_ulong vl, target_ulong vh)
+{
+target_ulong ql, qh;
+Int128 q;
+
+if (vl == 0 && vh == 0) { /* Handle special behavior on div by zero */
+ql = ~0x0;
+qh = ~0x0;
+} else {
+q = int128_divu(int128_make128(ul, uh), int128_make128(vl, vh));
+ql = int128_getlo(q);
+qh = int128_gethi(q);
+}
+
+env->retxh = qh;
+return ql;
+}
+
+target_ulong HELPER(remu_i128)(CPURISCVState *env,
+   target_ulong ul, target_ulong uh,
+   target_ulong vl, target_ulong vh)
+{
+target_ulong rl, rh;
+Int128 r;
+
+if (vl == 0 && vh == 0) {
+rl = ul;
+rh = uh;
+} else {
+r = 

[PULL 14/37] target/riscv: rvv-1.0: Call the correct RVF/RVD check function for widening fp/int type-convert insns

2022-01-07 Thread Alistair Francis
From: Frank Chang 

vfwcvt.xu.f.v, vfwcvt.x.f.v, vfwcvt.rtz.xu.f.v and vfwcvt.rtz.x.f.v
convert single-width floating-point to double-width integer.
Therefore, should use require_rvf() to check whether RVF/RVD is enabled.

vfwcvt.f.xu.v, vfwcvt.f.x.v convert single-width integer to double-width
floating-point, and vfwcvt.f.f.v convert double-width floating-point to
single-width floating-point. Therefore, should use require_scale_rvf() to
check whether RVF/RVD is enabled.

Signed-off-by: Frank Chang 
Acked-by: Alistair Francis 
Message-Id: <20220105022247.21131-3-frank.ch...@sifive.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvv.c.inc | 34 ++---
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
b/target/riscv/insn_trans/trans_rvv.c.inc
index 8d92243f2b..f1b44ccad2 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -2613,16 +2613,27 @@ GEN_OPFV_CVT_TRANS(vfcvt_rtz_x_f_v, vfcvt_x_f_v, 
RISCV_FRM_RTZ)
 static bool opfv_widen_check(DisasContext *s, arg_rmr *a)
 {
 return require_rvv(s) &&
-   require_scale_rvf(s) &&
-   (s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_ds(s, a->rd, a->rs2, a->vm);
 }
 
-#define GEN_OPFV_WIDEN_TRANS(NAME, HELPER, FRM)\
+static bool opxfv_widen_check(DisasContext *s, arg_rmr *a)
+{
+return opfv_widen_check(s, a) &&
+   require_rvf(s);
+}
+
+static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
+{
+return opfv_widen_check(s, a) &&
+   require_scale_rvf(s) &&
+   (s->sew != MO_8);
+}
+
+#define GEN_OPFV_WIDEN_TRANS(NAME, CHECK, HELPER, FRM) \
 static bool trans_##NAME(DisasContext *s, arg_rmr *a)  \
 {  \
-if (opfv_widen_check(s, a)) {  \
+if (CHECK(s, a)) { \
 if (FRM != RISCV_FRM_DYN) {\
 gen_set_rm(s, RISCV_FRM_DYN);  \
 }  \
@@ -2649,12 +2660,17 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a)   
   \
 return false;  \
 }
 
-GEN_OPFV_WIDEN_TRANS(vfwcvt_xu_f_v, vfwcvt_xu_f_v, RISCV_FRM_DYN)
-GEN_OPFV_WIDEN_TRANS(vfwcvt_x_f_v, vfwcvt_x_f_v, RISCV_FRM_DYN)
-GEN_OPFV_WIDEN_TRANS(vfwcvt_f_f_v, vfwcvt_f_f_v, RISCV_FRM_DYN)
+GEN_OPFV_WIDEN_TRANS(vfwcvt_xu_f_v, opxfv_widen_check, vfwcvt_xu_f_v,
+ RISCV_FRM_DYN)
+GEN_OPFV_WIDEN_TRANS(vfwcvt_x_f_v, opxfv_widen_check, vfwcvt_x_f_v,
+ RISCV_FRM_DYN)
+GEN_OPFV_WIDEN_TRANS(vfwcvt_f_f_v, opffv_widen_check, vfwcvt_f_f_v,
+ RISCV_FRM_DYN)
 /* Reuse the helper functions from vfwcvt.xu.f.v and vfwcvt.x.f.v */
-GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_xu_f_v, vfwcvt_xu_f_v, RISCV_FRM_RTZ)
-GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_x_f_v, vfwcvt_x_f_v, RISCV_FRM_RTZ)
+GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_xu_f_v, opxfv_widen_check, vfwcvt_xu_f_v,
+ RISCV_FRM_RTZ)
+GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_x_f_v, opxfv_widen_check, vfwcvt_x_f_v,
+ RISCV_FRM_RTZ)
 
 static bool opfxv_widen_check(DisasContext *s, arg_rmr *a)
 {
-- 
2.31.1




[PULL 13/37] target/riscv: rvv-1.0: Call the correct RVF/RVD check function for widening fp insns

2022-01-07 Thread Alistair Francis
From: Frank Chang 

Vector widening floating-point instructions should use
require_scale_rvf() instead of require_rvf() to check whether RVF/RVD is
enabled.

Signed-off-by: Frank Chang 
Acked-by: Alistair Francis 
Message-Id: <20220105022247.21131-2-frank.ch...@sifive.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvv.c.inc | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
b/target/riscv/insn_trans/trans_rvv.c.inc
index 5e3f7fdb77..8d92243f2b 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -2254,7 +2254,8 @@ GEN_OPFVF_TRANS(vfrsub_vf,  opfvf_check)
 static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
 {
 return require_rvv(s) &&
-   require_rvf(s) &&
+   require_scale_rvf(s) &&
+   (s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
 }
@@ -2292,7 +2293,8 @@ GEN_OPFVV_WIDEN_TRANS(vfwsub_vv, opfvv_widen_check)
 static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
 {
 return require_rvv(s) &&
-   require_rvf(s) &&
+   require_scale_rvf(s) &&
+   (s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_ds(s, a->rd, a->rs2, a->vm);
 }
@@ -2321,7 +2323,8 @@ GEN_OPFVF_WIDEN_TRANS(vfwsub_vf)
 static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
 {
 return require_rvv(s) &&
-   require_rvf(s) &&
+   require_scale_rvf(s) &&
+   (s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm);
 }
@@ -2359,7 +2362,8 @@ GEN_OPFWV_WIDEN_TRANS(vfwsub_wv)
 static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
 {
 return require_rvv(s) &&
-   require_rvf(s) &&
+   require_scale_rvf(s) &&
+   (s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_dd(s, a->rd, a->rs2, a->vm);
 }
-- 
2.31.1




[PULL 22/37] target/riscv: array for the 64 upper bits of 128-bit registers

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

The upper 64-bit of the 128-bit registers have now a place inside
the cpu state structure, and are created as globals for future use.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-7-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h   |  2 ++
 target/riscv/cpu.c   |  9 +
 target/riscv/machine.c   | 20 
 target/riscv/translate.c |  5 -
 4 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index dc10f27093..fa5d238530 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -112,6 +112,7 @@ FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 1, 1)
 
 struct CPURISCVState {
 target_ulong gpr[32];
+target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
 uint64_t fpr[32]; /* assume both F and D extensions */
 
 /* vector coprocessor state. */
@@ -344,6 +345,7 @@ static inline bool riscv_feature(CPURISCVState *env, int 
feature)
 #include "cpu_user.h"
 
 extern const char * const riscv_int_regnames[];
+extern const char * const riscv_int_regnamesh[];
 extern const char * const riscv_fpr_regnames[];
 
 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ce21c1b5b1..1bd4a7c7aa 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -42,6 +42,15 @@ const char * const riscv_int_regnames[] = {
   "x28/t3",  "x29/t4", "x30/t5", "x31/t6"
 };
 
+const char * const riscv_int_regnamesh[] = {
+  "x0h/zeroh", "x1h/rah",  "x2h/sph",   "x3h/gph",   "x4h/tph",  "x5h/t0h",
+  "x6h/t1h",   "x7h/t2h",  "x8h/s0h",   "x9h/s1h",   "x10h/a0h", "x11h/a1h",
+  "x12h/a2h",  "x13h/a3h", "x14h/a4h",  "x15h/a5h",  "x16h/a6h", "x17h/a7h",
+  "x18h/s2h",  "x19h/s3h", "x20h/s4h",  "x21h/s5h",  "x22h/s6h", "x23h/s7h",
+  "x24h/s8h",  "x25h/s9h", "x26h/s10h", "x27h/s11h", "x28h/t3h", "x29h/t4h",
+  "x30h/t5h",  "x31h/t6h"
+};
+
 const char * const riscv_fpr_regnames[] = {
   "f0/ft0",   "f1/ft1",  "f2/ft2",   "f3/ft3",   "f4/ft4",  "f5/ft5",
   "f6/ft6",   "f7/ft7",  "f8/fs0",   "f9/fs1",   "f10/fa0", "f11/fa1",
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index ad8248ebfd..8af9caabf5 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -164,6 +164,25 @@ static const VMStateDescription vmstate_pointermasking = {
 }
 };
 
+static bool rv128_needed(void *opaque)
+{
+RISCVCPU *cpu = opaque;
+CPURISCVState *env = >env;
+
+return env->misa_mxl_max == MXL_RV128;
+}
+
+static const VMStateDescription vmstate_rv128 = {
+.name = "cpu/rv128",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = rv128_needed,
+.fields = (VMStateField[]) {
+VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32),
+VMSTATE_END_OF_LIST()
+}
+};
+
 const VMStateDescription vmstate_riscv_cpu = {
 .name = "cpu",
 .version_id = 3,
@@ -218,6 +237,7 @@ const VMStateDescription vmstate_riscv_cpu = {
 _hyper,
 _vector,
 _pointermasking,
+_rv128,
 NULL
 }
 };
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index c3b4950ad0..6c400e8452 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -33,7 +33,7 @@
 #include "internals.h"
 
 /* global register indices */
-static TCGv cpu_gpr[32], cpu_pc, cpu_vl, cpu_vstart;
+static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
 static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
 static TCGv load_res;
 static TCGv load_val;
@@ -858,10 +858,13 @@ void riscv_translate_init(void)
  * unless you specifically block reads/writes to reg 0.
  */
 cpu_gpr[0] = NULL;
+cpu_gprh[0] = NULL;
 
 for (i = 1; i < 32; i++) {
 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
 offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]);
+cpu_gprh[i] = tcg_global_mem_new(cpu_env,
+offsetof(CPURISCVState, gprh[i]), riscv_int_regnamesh[i]);
 }
 
 for (i = 0; i < 32; i++) {
-- 
2.31.1




[PULL 33/37] target/riscv: modification of the trans_csrxx for 128-bit support

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

As opposed to the gen_arith and gen_shift generation helpers, the csr insns
do not have a common prototype, so the choice to generate 32/64 or 128-bit
helper calls is done in the trans_csrxx functions.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-18-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvi.c.inc | 201 +++-
 1 file changed, 158 insertions(+), 43 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index ca354130ec..3a0ae28fef 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -881,20 +881,78 @@ static bool do_csrrw(DisasContext *ctx, int rd, int rc, 
TCGv src, TCGv mask)
 return do_csr_post(ctx);
 }
 
-static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a)
+static bool do_csrr_i128(DisasContext *ctx, int rd, int rc)
 {
-TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
+TCGv destl = dest_gpr(ctx, rd);
+TCGv desth = dest_gprh(ctx, rd);
+TCGv_i32 csr = tcg_constant_i32(rc);
 
-/*
- * If rd == 0, the insn shall not read the csr, nor cause any of the
- * side effects that might occur on a csr read.
- */
-if (a->rd == 0) {
-return do_csrw(ctx, a->csr, src);
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
 }
+gen_helper_csrr_i128(destl, cpu_env, csr);
+tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
+gen_set_gpr128(ctx, rd, destl, desth);
+return do_csr_post(ctx);
+}
+
+static bool do_csrw_i128(DisasContext *ctx, int rc, TCGv srcl, TCGv srch)
+{
+TCGv_i32 csr = tcg_constant_i32(rc);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_csrw_i128(cpu_env, csr, srcl, srch);
+return do_csr_post(ctx);
+}
 
-TCGv mask = tcg_constant_tl(-1);
-return do_csrrw(ctx, a->rd, a->csr, src, mask);
+static bool do_csrrw_i128(DisasContext *ctx, int rd, int rc,
+  TCGv srcl, TCGv srch, TCGv maskl, TCGv maskh)
+{
+TCGv destl = dest_gpr(ctx, rd);
+TCGv desth = dest_gprh(ctx, rd);
+TCGv_i32 csr = tcg_constant_i32(rc);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_csrrw_i128(destl, cpu_env, csr, srcl, srch, maskl, maskh);
+tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
+gen_set_gpr128(ctx, rd, destl, desth);
+return do_csr_post(ctx);
+}
+
+static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a)
+{
+if (get_xl(ctx) < MXL_RV128) {
+TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
+
+/*
+ * If rd == 0, the insn shall not read the csr, nor cause any of the
+ * side effects that might occur on a csr read.
+ */
+if (a->rd == 0) {
+return do_csrw(ctx, a->csr, src);
+}
+
+TCGv mask = tcg_constant_tl(-1);
+return do_csrrw(ctx, a->rd, a->csr, src, mask);
+} else {
+TCGv srcl = get_gpr(ctx, a->rs1, EXT_NONE);
+TCGv srch = get_gprh(ctx, a->rs1);
+
+/*
+ * If rd == 0, the insn shall not read the csr, nor cause any of the
+ * side effects that might occur on a csr read.
+ */
+if (a->rd == 0) {
+return do_csrw_i128(ctx, a->csr, srcl, srch);
+}
+
+TCGv mask = tcg_constant_tl(-1);
+return do_csrrw_i128(ctx, a->rd, a->csr, srcl, srch, mask, mask);
+}
 }
 
 static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
@@ -906,13 +964,24 @@ static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
  * a zero value, the instruction will still attempt to write the
  * unmodified value back to the csr and will cause side effects.
  */
-if (a->rs1 == 0) {
-return do_csrr(ctx, a->rd, a->csr);
-}
+if (get_xl(ctx) < MXL_RV128) {
+if (a->rs1 == 0) {
+return do_csrr(ctx, a->rd, a->csr);
+}
 
-TCGv ones = tcg_constant_tl(-1);
-TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
-return do_csrrw(ctx, a->rd, a->csr, ones, mask);
+TCGv ones = tcg_constant_tl(-1);
+TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
+return do_csrrw(ctx, a->rd, a->csr, ones, mask);
+} else {
+if (a->rs1 == 0) {
+return do_csrr_i128(ctx, a->rd, a->csr);
+}
+
+TCGv ones = tcg_constant_tl(-1);
+TCGv maskl = get_gpr(ctx, a->rs1, EXT_ZERO);
+TCGv maskh = get_gprh(ctx, a->rs1);
+return do_csrrw_i128(ctx, a->rd, a->csr, ones, ones, maskl, maskh);
+}
 }
 
 static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
@@ -924,28 +993,54 @@ static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
  * a zero value, the instruction will still attempt to write 

[PULL 08/37] target/riscv: Mark the Hypervisor extension as non experimental

2022-01-07 Thread Alistair Francis
From: Alistair Francis 

The Hypervisor spec is now frozen, so remove the experimental tag.

Signed-off-by: Alistair Francis 
Reviewed-by: Anup Patel 
Reviewed-by: Bin Meng 
Message-Id: <20220105213937.1113508-6-alistair.fran...@opensource.wdc.com>
---
 target/riscv/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 6ef3314bce..9ea67bedd3 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -627,6 +627,7 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true),
 DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
 DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false),
+DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, false),
 DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
 DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
 DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
@@ -645,7 +646,6 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
 DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
 DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true),
-DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false),
 DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
 /* ePMP 0.9.3 */
 DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
-- 
2.31.1




[PULL 31/37] target/riscv: adding high part of some csrs

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

Adding the high part of a very minimal set of csr.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-16-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h | 4 
 target/riscv/machine.c | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index b9dee7d147..e8c664a956 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -195,6 +195,10 @@ struct CPURISCVState {
 target_ulong hgatp;
 uint64_t htimedelta;
 
+/* Upper 64-bits of 128-bit CSRs */
+uint64_t mscratchh;
+uint64_t sscratchh;
+
 /* Virtual CSRs */
 /*
  * For RV32 this is 32-bit vsstatus and 32-bit vsstatush.
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 8af9caabf5..13b9ab375b 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -179,6 +179,8 @@ static const VMStateDescription vmstate_rv128 = {
 .needed = rv128_needed,
 .fields = (VMStateField[]) {
 VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32),
+VMSTATE_UINT64(env.mscratchh, RISCVCPU),
+VMSTATE_UINT64(env.sscratchh, RISCVCPU),
 VMSTATE_END_OF_LIST()
 }
 };
-- 
2.31.1




[PULL 18/37] exec/memop: Adding signed quad and octo defines

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

Adding defines to handle signed 64-bit and unsigned 128-bit quantities in
memory accesses.

Signed-off-by: Frédéric Pétrot 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-3-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 include/exec/memop.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/exec/memop.h b/include/exec/memop.h
index 72c2f0ff3d..2a885f3917 100644
--- a/include/exec/memop.h
+++ b/include/exec/memop.h
@@ -86,28 +86,35 @@ typedef enum MemOp {
 MO_UW= MO_16,
 MO_UL= MO_32,
 MO_UQ= MO_64,
+MO_UO= MO_128,
 MO_SB= MO_SIGN | MO_8,
 MO_SW= MO_SIGN | MO_16,
 MO_SL= MO_SIGN | MO_32,
+MO_SQ= MO_SIGN | MO_64,
+MO_SO= MO_SIGN | MO_128,
 
 MO_LEUW  = MO_LE | MO_UW,
 MO_LEUL  = MO_LE | MO_UL,
 MO_LEUQ  = MO_LE | MO_UQ,
 MO_LESW  = MO_LE | MO_SW,
 MO_LESL  = MO_LE | MO_SL,
+MO_LESQ  = MO_LE | MO_SQ,
 
 MO_BEUW  = MO_BE | MO_UW,
 MO_BEUL  = MO_BE | MO_UL,
 MO_BEUQ  = MO_BE | MO_UQ,
 MO_BESW  = MO_BE | MO_SW,
 MO_BESL  = MO_BE | MO_SL,
+MO_BESQ  = MO_BE | MO_SQ,
 
 #ifdef NEED_CPU_H
 MO_TEUW  = MO_TE | MO_UW,
 MO_TEUL  = MO_TE | MO_UL,
 MO_TEUQ  = MO_TE | MO_UQ,
+MO_TEUO  = MO_TE | MO_UO,
 MO_TESW  = MO_TE | MO_SW,
 MO_TESL  = MO_TE | MO_SL,
+MO_TESQ  = MO_TE | MO_SQ,
 #endif
 
 MO_SSIZE = MO_SIZE | MO_SIGN,
-- 
2.31.1




[PULL 32/37] target/riscv: helper functions to wrap calls to 128-bit csr insns

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

Given the side effects they have, the csr instructions are realized as
helpers. We extend this existing infrastructure for 128-bit sized csr.
We return 128-bit values using the same approach as for div/rem.
Theses helpers all call a unique function that is currently a fallback
on the 64-bit version.
The trans_csrxx functions supporting 128-bit are yet to be implemented.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-17-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h   |  5 +
 target/riscv/helper.h|  3 +++
 target/riscv/csr.c   | 17 
 target/riscv/op_helper.c | 44 
 4 files changed, 69 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index e8c664a956..73d3d22f26 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -25,6 +25,7 @@
 #include "exec/cpu-defs.h"
 #include "fpu/softfloat-types.h"
 #include "qom/object.h"
+#include "qemu/int128.h"
 #include "cpu_bits.h"
 
 #define TCG_GUEST_DEFAULT_MO 0
@@ -500,6 +501,10 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState 
*env, int csrno,
   target_ulong new_value,
   target_ulong write_mask);
 
+RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
+Int128 *ret_value,
+Int128 new_value, Int128 write_mask);
+
 typedef struct {
 const char *name;
 riscv_csr_predicate_fn predicate;
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index a8ee8a362a..6cf6d6ce98 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -96,6 +96,9 @@ DEF_HELPER_FLAGS_1(fclass_h, TCG_CALL_NO_RWG_SE, tl, i64)
 DEF_HELPER_2(csrr, tl, env, int)
 DEF_HELPER_3(csrw, void, env, int, tl)
 DEF_HELPER_4(csrrw, tl, env, int, tl, tl)
+DEF_HELPER_2(csrr_i128, tl, env, int)
+DEF_HELPER_4(csrw_i128, void, env, int, tl, tl)
+DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_2(sret, tl, env, tl)
 DEF_HELPER_2(mret, tl, env, tl)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 146447eac5..4c6a44c0b8 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1817,6 +1817,23 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
 return RISCV_EXCP_NONE;
 }
 
+RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
+   Int128 *ret_value,
+   Int128 new_value, Int128 write_mask)
+{
+/* fall back to 64-bit version for now */
+target_ulong ret_64;
+RISCVException ret = riscv_csrrw(env, csrno, _64,
+ int128_getlo(new_value),
+ int128_getlo(write_mask));
+
+if (ret_value) {
+*ret_value = int128_make64(ret_64);
+}
+
+return ret;
+}
+
 /*
  * Debugger support.  If not in user mode, set env->debugger before the
  * riscv_csrrw call and clear it after the call.
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 58d992e98a..6f040f2fb9 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -69,6 +69,50 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
 return val;
 }
 
+target_ulong helper_csrr_i128(CPURISCVState *env, int csr)
+{
+Int128 rv = int128_zero();
+RISCVException ret = riscv_csrrw_i128(env, csr, ,
+  int128_zero(),
+  int128_zero());
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+
+env->retxh = int128_gethi(rv);
+return int128_getlo(rv);
+}
+
+void helper_csrw_i128(CPURISCVState *env, int csr,
+  target_ulong srcl, target_ulong srch)
+{
+RISCVException ret = riscv_csrrw_i128(env, csr, NULL,
+  int128_make128(srcl, srch),
+  UINT128_MAX);
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+}
+
+target_ulong helper_csrrw_i128(CPURISCVState *env, int csr,
+   target_ulong srcl, target_ulong srch,
+   target_ulong maskl, target_ulong maskh)
+{
+Int128 rv = int128_zero();
+RISCVException ret = riscv_csrrw_i128(env, csr, ,
+  int128_make128(srcl, srch),
+  int128_make128(maskl, maskh));
+
+if (ret != RISCV_EXCP_NONE) {
+riscv_raise_exception(env, ret, GETPC());
+}
+
+env->retxh = int128_gethi(rv);
+return int128_getlo(rv);
+}
+
 #ifndef CONFIG_USER_ONLY
 
 target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
-- 
2.31.1




[PULL 29/37] target/riscv: support for 128-bit arithmetic instructions

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

Addition of 128-bit adds and subs in their various sizes,
"set if less than"s and branches.
Refactored the code to have a comparison function used for both stls and
branches.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-14-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  |   3 +
 target/riscv/translate.c|  63 --
 target/riscv/insn_trans/trans_rvb.c.inc |  20 +--
 target/riscv/insn_trans/trans_rvi.c.inc | 159 +---
 target/riscv/insn_trans/trans_rvm.c.inc |  26 ++--
 5 files changed, 222 insertions(+), 49 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index a992c6d369..42366d20fb 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -170,9 +170,12 @@ sraw 010 .  . 101 . 0111011 @r
 ldu     . 111 . 011 @i
 lq      . 010 . 000 @i
 sq      . 100 . 0100011 @s
+addid  .  000 . 1011011 @i
 sllid00 ..  . 001 . 1011011 @sh6
 srlid00 ..  . 101 . 1011011 @sh6
 sraid01 ..  . 101 . 1011011 @sh6
+addd 000 . .  000 . 011 @r
+subd 010 . .  000 . 011 @r
 slld 000 . .  001 . 011 @r
 srld 000 . .  101 . 011 @r
 srad 010 . .  101 . 011 @r
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 89220a5fae..4ae4345691 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -581,57 +581,96 @@ static bool gen_logic(DisasContext *ctx, arg_r *a,
 }
 
 static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, target_long))
+ void (*func)(TCGv, TCGv, target_long),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 
-func(dest, src1, a->imm);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, a->imm);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, a->imm);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext,
- void (*func)(TCGv, TCGv, TCGv))
+ void (*func)(TCGv, TCGv, TCGv),
+ void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = tcg_constant_tl(a->imm);
 
-func(dest, src1, src2);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, src2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = tcg_constant_tl(-(a->imm < 0));
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, src2, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext,
-  void (*func)(TCGv, TCGv, TCGv))
+  void (*func)(TCGv, TCGv, TCGv),
+  void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1 = get_gpr(ctx, a->rs1, ext);
 TCGv src2 = get_gpr(ctx, a->rs2, ext);
 
-func(dest, src1, src2);
+if (get_ol(ctx) < MXL_RV128) {
+func(dest, src1, src2);
+gen_set_gpr(ctx, a->rd, dest);
+} else {
+if (f128 == NULL) {
+return false;
+}
 
-gen_set_gpr(ctx, a->rd, dest);
+TCGv src1h = get_gprh(ctx, a->rs1);
+TCGv src2h = get_gprh(ctx, a->rs2);
+TCGv desth = dest_gprh(ctx, a->rd);
+
+f128(dest, desth, src1, src1h, src2, src2h);
+gen_set_gpr128(ctx, a->rd, dest, desth);
+}
 return true;
 }
 
 static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
  void (*f_tl)(TCGv, TCGv, TCGv),
- void (*f_32)(TCGv, TCGv, TCGv))
+ void (*f_32)(TCGv, TCGv, TCGv),
+ void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
 {
 int olen = get_olen(ctx);
 
 if (olen != TARGET_LONG_BITS) {
  

[PULL 06/37] hw/intc: sifive_plic: Cleanup the read function

2022-01-07 Thread Alistair Francis
From: Alistair Francis 

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-Id: <20220105213937.1113508-4-alistair.fran...@opensource.wdc.com>
---
 hw/intc/sifive_plic.c | 55 +--
 1 file changed, 11 insertions(+), 44 deletions(-)

diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
index 698492ce77..44d24b3c59 100644
--- a/hw/intc/sifive_plic.c
+++ b/hw/intc/sifive_plic.c
@@ -199,70 +199,37 @@ static uint64_t sifive_plic_read(void *opaque, hwaddr 
addr, unsigned size)
 {
 SiFivePLICState *plic = opaque;
 
-/* writes must be 4 byte words */
-if ((addr & 0x3) != 0) {
-goto err;
-}
-
-if (addr >= plic->priority_base && /* 4 bytes per source */
-addr < plic->priority_base + (plic->num_sources << 2))
-{
+if (addr_between(addr, plic->priority_base, plic->num_sources << 2)) {
 uint32_t irq = ((addr - plic->priority_base) >> 2) + 1;
-if (RISCV_DEBUG_PLIC) {
-qemu_log("plic: read priority: irq=%d priority=%d\n",
-irq, plic->source_priority[irq]);
-}
+
 return plic->source_priority[irq];
-} else if (addr >= plic->pending_base && /* 1 bit per source */
-   addr < plic->pending_base + (plic->num_sources >> 3))
-{
+} else if (addr_between(addr, plic->pending_base, plic->num_sources >> 3)) 
{
 uint32_t word = (addr - plic->pending_base) >> 2;
-if (RISCV_DEBUG_PLIC) {
-qemu_log("plic: read pending: word=%d value=%d\n",
-word, plic->pending[word]);
-}
+
 return plic->pending[word];
-} else if (addr >= plic->enable_base && /* 1 bit per source */
- addr < plic->enable_base + plic->num_addrs * plic->enable_stride)
-{
+} else if (addr_between(addr, plic->enable_base,
+plic->num_addrs * plic->enable_stride)) {
 uint32_t addrid = (addr - plic->enable_base) / plic->enable_stride;
 uint32_t wordid = (addr & (plic->enable_stride - 1)) >> 2;
+
 if (wordid < plic->bitfield_words) {
-if (RISCV_DEBUG_PLIC) {
-qemu_log("plic: read enable: hart%d-%c word=%d value=%x\n",
-plic->addr_config[addrid].hartid,
-mode_to_char(plic->addr_config[addrid].mode), wordid,
-plic->enable[addrid * plic->bitfield_words + wordid]);
-}
 return plic->enable[addrid * plic->bitfield_words + wordid];
 }
-} else if (addr >= plic->context_base && /* 1 bit per source */
- addr < plic->context_base + plic->num_addrs * 
plic->context_stride)
-{
+} else if (addr_between(addr, plic->context_base,
+plic->num_addrs * plic->context_stride)) {
 uint32_t addrid = (addr - plic->context_base) / plic->context_stride;
 uint32_t contextid = (addr & (plic->context_stride - 1));
+
 if (contextid == 0) {
-if (RISCV_DEBUG_PLIC) {
-qemu_log("plic: read priority: hart%d-%c priority=%x\n",
-plic->addr_config[addrid].hartid,
-mode_to_char(plic->addr_config[addrid].mode),
-plic->target_priority[addrid]);
-}
 return plic->target_priority[addrid];
 } else if (contextid == 4) {
 uint32_t value = sifive_plic_claim(plic, addrid);
-if (RISCV_DEBUG_PLIC) {
-qemu_log("plic: read claim: hart%d-%c irq=%x\n",
-plic->addr_config[addrid].hartid,
-mode_to_char(plic->addr_config[addrid].mode),
-value);
-}
+
 sifive_plic_update(plic);
 return value;
 }
 }
 
-err:
 qemu_log_mask(LOG_GUEST_ERROR,
   "%s: Invalid register read 0x%" HWADDR_PRIx "\n",
   __func__, addr);
-- 
2.31.1




[PULL 12/37] roms/opensbi: Upgrade from v0.9 to v1.0

2022-01-07 Thread Alistair Francis
From: Bin Meng 

Upgrade OpenSBI from v0.9 to v1.0 and the pre-built bios images.

The v1.0 release includes the following commits:

ec5274b platform: implement K210 system reset
5487cf0 include: sbi: Simplify HSM state define names
8df1f9a lib: sbi: Use SBI_HSM_STATE_xyz defines instead of SBI_STATE_xyz defines
7c867fd lib: sbi: Rename sbi_hsm_hart_started_mask() function
638c948 lib: sbi: Remove redundant sbi_hsm_hart_started() function
ca864a9 lib: sbi: Fix error codes returned by HSM start() and stop() functions
6290a22 include: sbi: Add HSM suspend related defines
4b05df6 lib: sbi: Add sbi_hart_reinit() function
807d71c include: sbi: Add hart_suspend() platform callback
7475689 lib: sbi: Implement SBI HSM suspend function
b9cf617 include: sbi: Upgrade SBI implementation version to v0.3
50d4fde lib: Remove redundant sbi_platform_ipi_clear() calls
ff5bd94 include: sbi: SBI function IDs for RFENCE extension
22d8ee9 firmware: Use lla to access all global symbols
0f20e8a firmware: Support position independent execution
ddad02d lib: sbi: illegal CSR 0x306 access in hpm_allowed()
bfc85c7 include: headers: Replace __ASSEMBLY__ with __ASSEMBLER__
9190ad1 lib/utils: Support the official clint DT bindings
ca3f358 lib/utils: Drop the 'compat' parameter of fdt_plic_fixup()
4edc822 lib/utils: Support fixing up the official DT bindings of PLIC
4ef2f5d firware: optimize the exception exit code
3d8a952 lib: fix csr detect support
e71a7c1 firmware: Remove redundant add instruction from trap restore path
d4a94ea include: types: Add __aligned(x) to define the minimum alignement
d0e406f include: sbi: Allow direct initialization via SPIN_LOCK_INIT()
4d8e2f1 lib: sbi: Replace test-and-set locks by ticket locks
70ffc3e lib: sbi: fix atomic_add_return
27a16b1 docs: fix link to OpenPiton documentation
b1df1ac lib: sbi: Domains can be registered only before finalizing domains
7495bce lib: sbi: Add sbi_domain_memregion_init() API
4dc0001 lib: sbi: Add sbi_domain_root_add_memregion() API
8b56980 lib: utils/sys: Add CLINT memregion in the root domain
fc37c97 lib: sbi: Make the root domain instance global variable
e7e4bcd lib: utils: Copy over restricted root domain memregions to FDT domains
f41196a lib: sbi: Make sbi_domain_memregion_initfw() a local function
c5d0645 lib: utils: Implement "64bit-mmio" property parsing
49e422c lib: utils: reset: Add T-HEAD sample platform reset driver
0d56293 lib: sbi: Fix sbi_domain_root_add_memregion() for merging memregions
bf3ef53 firmware: Enable FW_PIC by default
1db8436 platform: Remove platform/thead
6d1642f docs: generic: Add T-HEAD C9xx series processors
a3689db lib: sbi: Remove domains_root_regions() platform callback
068ca08 lib: sbi: Simplify console platform operations
559a8f1 lib: sbi: Simplify timer platform operations
dc39c7b lib: sbi: Simplify ipi platform operations
043d088 lib: sbi: Simplify system reset platform operations
a84a1dd lib: sbi: Simplify HSM platform operations
e9a27ab lib: sbi: Show devices provided by platform in boot prints
632e27b docs/platform: sifive_fu540: Update U-Boot defconfig name
117fb6d lib: utils/serial: Add support for Gaisler APBUART
552f53f docs: platform: Sort platform names
d4177e7 docs: platform: Describe sifive_fu540 as supported generic platform
26998f3 platform: Remove sifive/fu540 platform
f90c4c2 lib: sbi: Have spinlock checks return bool
e822b75 lib: utils/serial: Support Synopsys DesignWare APB UART
6139ab2 Makefile: unconditionally disable SSP
c9ef2bc lib: utils: Add strncpy macro to libfdt_env.h
ee7c2b2 lib: utils/fdt: Don't use sbi_string functions
fe92347 lib: utils/fdt: Replace strcmp with strncmp
b2dbbc0 lib: Check region base for merging in sbi_domain_root_add_memregion()
54d7def lib: utils: Try other FDT drivers when we see SBI_ENODEV
d9ba653 docs: debugging OpenSBI
66c4fca lib: utils: consider ':' in stdout-path
f30b189 lib: sbi_scratch: remove owner from sbi_scratch_alloc_offset
a03ea2e platform: andes/ae350: Cosmetic fixes in plicsw.c
b32fac4 docs/platform: andes-ae350: Fix missing spaces
de446cc platform: andes/ae350: Drop plicsw_get_pending()
434198e platform: andes/ae350: Drop plicsw_ipi_sync()
1da3d80 lib: sbi_scratch: zero out scratch memory on all harts
360ab88 lib: utils: missing initialization in thead_reset_init
79f9b42 lib: sbi: Fix GET_F64_REG inline assembly
eb90e0a lib: utils/libfdt: Upgrade to v1.6.1 release
cdcf907 lib: sign conflict in sbi_tlb_entry_process()
9901794 lib: sign conflict in wake_coldboot_harts()
11c345f lib: simplify sbi_fifo_inplace_update()
4519e29 lib: utils/timer: Add ACLINT MTIMER library
5a049fe lib: utils/ipi: Add ACLINT MSWI library
bd5d208 lib: utils: Add FDT parsing API common for both ACLINT and CLINT
56fc5f7 lib: utils/ipi: Add FDT based ACLINT MSWI IPI driver
03d6bb5 lib: utils/timer: Add FDT based ACLINT MTIMER driver
a731c7e platform: Replace CLINT library usage with ACLINT library
b7f2cd2 lib: utils: reset: unify naming of 'sifive_test' device
197e089 docs/platform: thead-c9xx: 

[PULL 03/37] hw/dma: sifive_pdma: permit 4/8-byte access size of PDMA registers

2022-01-07 Thread Alistair Francis
From: Jim Shu 

It's obvious that PDMA supports 64-bit access of 64-bit registers, and
in previous commit, we confirm that PDMA supports 32-bit access of
both 32/64-bit registers. Thus, we configure 32/64-bit memory access
of PDMA registers as valid in general.

Signed-off-by: Jim Shu 
Reviewed-by: Frank Chang 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
Message-id: 20220104063408.658169-3-jim@sifive.com
Signed-off-by: Alistair Francis 
---
 hw/dma/sifive_pdma.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
index f4df16449b..1dd88f3479 100644
--- a/hw/dma/sifive_pdma.c
+++ b/hw/dma/sifive_pdma.c
@@ -444,6 +444,10 @@ static const MemoryRegionOps sifive_pdma_ops = {
 .impl = {
 .min_access_size = 4,
 .max_access_size = 8,
+},
+.valid = {
+.min_access_size = 4,
+.max_access_size = 8,
 }
 };
 
-- 
2.31.1




[PULL 23/37] target/riscv: setup everything for rv64 to support rv128 execution

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

This patch adds the support of the '-cpu rv128' option to
qemu-system-riscv64 so that we can indicate that we want to run rv128
executables.
Still, there is no support for 128-bit insns at that stage so qemu fails
miserably (as expected) if launched with this option.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-8-frederic.pet...@univ-grenoble-alpes.fr
[ Changed by AF
 - Rename CPU to "x-rv128"
]
Signed-off-by: Alistair Francis 
---
 include/disas/dis-asm.h |  1 +
 target/riscv/cpu.h  |  1 +
 disas/riscv.c   |  5 +
 target/riscv/cpu.c  | 20 
 target/riscv/gdbstub.c  |  5 +
 5 files changed, 32 insertions(+)

diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 08e1beec85..102a1e7f50 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -459,6 +459,7 @@ int print_insn_nios2(bfd_vma, disassemble_info*);
 int print_insn_xtensa   (bfd_vma, disassemble_info*);
 int print_insn_riscv32  (bfd_vma, disassemble_info*);
 int print_insn_riscv64  (bfd_vma, disassemble_info*);
+int print_insn_riscv128 (bfd_vma, disassemble_info*);
 int print_insn_rx(bfd_vma, disassemble_info *);
 int print_insn_hexagon(bfd_vma, disassemble_info *);
 
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index fa5d238530..fd583e0f41 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -38,6 +38,7 @@
 #define TYPE_RISCV_CPU_ANY  RISCV_CPU_TYPE_NAME("any")
 #define TYPE_RISCV_CPU_BASE32   RISCV_CPU_TYPE_NAME("rv32")
 #define TYPE_RISCV_CPU_BASE64   RISCV_CPU_TYPE_NAME("rv64")
+#define TYPE_RISCV_CPU_BASE128  RISCV_CPU_TYPE_NAME("x-rv128")
 #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
 #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c")
 #define TYPE_RISCV_CPU_SIFIVE_E31   RISCV_CPU_TYPE_NAME("sifive-e31")
diff --git a/disas/riscv.c b/disas/riscv.c
index 793ad14c27..03c8dc9961 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -3090,3 +3090,8 @@ int print_insn_riscv64(bfd_vma memaddr, struct 
disassemble_info *info)
 {
 return print_insn_riscv(memaddr, info, rv64);
 }
+
+int print_insn_riscv128(bfd_vma memaddr, struct disassemble_info *info)
+{
+return print_insn_riscv(memaddr, info, rv128);
+}
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1bd4a7c7aa..9bc25d3055 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -178,6 +178,19 @@ static void rv64_sifive_e_cpu_init(Object *obj)
 set_priv_version(env, PRIV_VERSION_1_10_0);
 qdev_prop_set_bit(DEVICE(obj), "mmu", false);
 }
+
+static void rv128_base_cpu_init(Object *obj)
+{
+if (qemu_tcg_mttcg_enabled()) {
+/* Missing 128-bit aligned atomics */
+error_report("128-bit RISC-V currently does not work with Multi "
+ "Threaded TCG. Please use: -accel tcg,thread=single");
+exit(EXIT_FAILURE);
+}
+CPURISCVState *env = _CPU(obj)->env;
+/* We set this in the realise function */
+set_misa(env, MXL_RV128, 0);
+}
 #else
 static void rv32_base_cpu_init(Object *obj)
 {
@@ -402,6 +415,9 @@ static void riscv_cpu_disas_set_info(CPUState *s, 
disassemble_info *info)
 case MXL_RV64:
 info->print_insn = print_insn_riscv64;
 break;
+case MXL_RV128:
+info->print_insn = print_insn_riscv128;
+break;
 default:
 g_assert_not_reached();
 }
@@ -464,6 +480,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 #ifdef TARGET_RISCV64
 case MXL_RV64:
 break;
+case MXL_RV128:
+break;
 #endif
 case MXL_RV32:
 break;
@@ -673,6 +691,7 @@ static gchar *riscv_gdb_arch_name(CPUState *cs)
 case MXL_RV32:
 return g_strdup("riscv:rv32");
 case MXL_RV64:
+case MXL_RV128:
 return g_strdup("riscv:rv64");
 default:
 g_assert_not_reached();
@@ -827,6 +846,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51,   rv64_sifive_e_cpu_init),
 DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54,   rv64_sifive_u_cpu_init),
 DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C, rv64_sifive_u_cpu_init),
+DEFINE_CPU(TYPE_RISCV_CPU_BASE128,  rv128_base_cpu_init),
 #endif
 };
 
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 881ab33392..a5429b92d4 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -280,6 +280,11 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int 
base_reg)
 int bitsize = 16 << env->misa_mxl_max;
 int i;
 
+/* Until gdb knows about 128-bit registers */
+if (bitsize > 64) {
+bitsize = 64;
+}
+
 g_string_printf(s, "");
 g_string_append_printf(s, "");
 g_string_append_printf(s, "");
-- 
2.31.1




[PULL 27/37] target/riscv: support for 128-bit U-type instructions

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

Adding the 128-bit version of lui and auipc, and introducing to that end
a "set register with immediat" function to handle extension on 128 bits.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-12-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/translate.c| 21 +
 target/riscv/insn_trans/trans_rvi.c.inc |  8 
 2 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index b43efc9bc3..ba1ad1be5f 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -322,6 +322,27 @@ static void gen_set_gpr(DisasContext *ctx, int reg_num, 
TCGv t)
 }
 }
 
+static void gen_set_gpri(DisasContext *ctx, int reg_num, target_long imm)
+{
+if (reg_num != 0) {
+switch (get_ol(ctx)) {
+case MXL_RV32:
+tcg_gen_movi_tl(cpu_gpr[reg_num], (int32_t)imm);
+break;
+case MXL_RV64:
+case MXL_RV128:
+tcg_gen_movi_tl(cpu_gpr[reg_num], imm);
+break;
+default:
+g_assert_not_reached();
+}
+
+if (get_xl_max(ctx) == MXL_RV128) {
+tcg_gen_movi_tl(cpu_gprh[reg_num], -(imm < 0));
+}
+}
+}
+
 static void gen_set_gpr128(DisasContext *ctx, int reg_num, TCGv rl, TCGv rh)
 {
 assert(get_ol(ctx) == MXL_RV128);
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index e572976e88..6113acc669 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -26,14 +26,14 @@ static bool trans_illegal(DisasContext *ctx, arg_empty *a)
 
 static bool trans_c64_illegal(DisasContext *ctx, arg_empty *a)
 {
- REQUIRE_64BIT(ctx);
- return trans_illegal(ctx, a);
+REQUIRE_64_OR_128BIT(ctx);
+return trans_illegal(ctx, a);
 }
 
 static bool trans_lui(DisasContext *ctx, arg_lui *a)
 {
 if (a->rd != 0) {
-tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm);
+gen_set_gpri(ctx, a->rd, a->imm);
 }
 return true;
 }
@@ -41,7 +41,7 @@ static bool trans_lui(DisasContext *ctx, arg_lui *a)
 static bool trans_auipc(DisasContext *ctx, arg_auipc *a)
 {
 if (a->rd != 0) {
-tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm + ctx->base.pc_next);
+gen_set_gpri(ctx, a->rd, a->imm + ctx->base.pc_next);
 }
 return true;
 }
-- 
2.31.1




[PULL 11/37] hw/riscv: virt: Allow support for 32 cores

2022-01-07 Thread Alistair Francis
From: Alistair Francis 

Linux supports up to 32 cores for both 32-bit and 64-bit RISC-V, so
let's set that as the maximum for the virt board.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/435
Signed-off-by: Alistair Francis 
Reviewed-by: Anup Patel 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Bin Meng 
Message-Id: <20220105213937.1113508-9-alistair.fran...@opensource.wdc.com>
---
 include/hw/riscv/virt.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index b8ef99f348..6e9f61ccd9 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -24,7 +24,7 @@
 #include "hw/block/flash.h"
 #include "qom/object.h"
 
-#define VIRT_CPUS_MAX 8
+#define VIRT_CPUS_MAX 32
 #define VIRT_SOCKETS_MAX 8
 
 #define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
-- 
2.31.1




[PULL 21/37] target/riscv: separation of bitwise logic and arithmetic helpers

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

Introduction of a gen_logic function for bitwise logic to implement
instructions in which no propagation of information occurs between bits and
use of this function on the bitwise instructions.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-6-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 target/riscv/translate.c| 27 +
 target/riscv/insn_trans/trans_rvb.c.inc |  6 +++---
 target/riscv/insn_trans/trans_rvi.c.inc | 12 +--
 3 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 502bf0d009..c3b4950ad0 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -475,6 +475,33 @@ static int ex_rvc_shifti(DisasContext *ctx, int imm)
 /* Include the auto-generated decoder for 32 bit insn */
 #include "decode-insn32.c.inc"
 
+static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
+ void (*func)(TCGv, TCGv, target_long))
+{
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+
+func(dest, src1, a->imm);
+
+gen_set_gpr(ctx, a->rd, dest);
+
+return true;
+}
+
+static bool gen_logic(DisasContext *ctx, arg_r *a,
+  void (*func)(TCGv, TCGv, TCGv))
+{
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+
+func(dest, src1, src2);
+
+gen_set_gpr(ctx, a->rd, dest);
+
+return true;
+}
+
 static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
  void (*func)(TCGv, TCGv, target_long))
 {
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc 
b/target/riscv/insn_trans/trans_rvb.c.inc
index c8d31907c5..de2cd613b1 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -86,19 +86,19 @@ static bool trans_cpop(DisasContext *ctx, arg_cpop *a)
 static bool trans_andn(DisasContext *ctx, arg_andn *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_andc_tl);
+return gen_logic(ctx, a, tcg_gen_andc_tl);
 }
 
 static bool trans_orn(DisasContext *ctx, arg_orn *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_orc_tl);
+return gen_logic(ctx, a, tcg_gen_orc_tl);
 }
 
 static bool trans_xnor(DisasContext *ctx, arg_xnor *a)
 {
 REQUIRE_ZBB(ctx);
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_eqv_tl);
+return gen_logic(ctx, a, tcg_gen_eqv_tl);
 }
 
 static bool trans_min(DisasContext *ctx, arg_min *a)
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index 4a2aefe3a5..51607b3d40 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -252,17 +252,17 @@ static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a)
 
 static bool trans_xori(DisasContext *ctx, arg_xori *a)
 {
-return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_xori_tl);
+return gen_logic_imm_fn(ctx, a, tcg_gen_xori_tl);
 }
 
 static bool trans_ori(DisasContext *ctx, arg_ori *a)
 {
-return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_ori_tl);
+return gen_logic_imm_fn(ctx, a, tcg_gen_ori_tl);
 }
 
 static bool trans_andi(DisasContext *ctx, arg_andi *a)
 {
-return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_andi_tl);
+return gen_logic_imm_fn(ctx, a, tcg_gen_andi_tl);
 }
 
 static bool trans_slli(DisasContext *ctx, arg_slli *a)
@@ -319,7 +319,7 @@ static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
 
 static bool trans_xor(DisasContext *ctx, arg_xor *a)
 {
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_xor_tl);
+return gen_logic(ctx, a, tcg_gen_xor_tl);
 }
 
 static bool trans_srl(DisasContext *ctx, arg_srl *a)
@@ -334,12 +334,12 @@ static bool trans_sra(DisasContext *ctx, arg_sra *a)
 
 static bool trans_or(DisasContext *ctx, arg_or *a)
 {
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_or_tl);
+return gen_logic(ctx, a, tcg_gen_or_tl);
 }
 
 static bool trans_and(DisasContext *ctx, arg_and *a)
 {
-return gen_arith(ctx, a, EXT_NONE, tcg_gen_and_tl);
+return gen_logic(ctx, a, tcg_gen_and_tl);
 }
 
 static bool trans_addiw(DisasContext *ctx, arg_addiw *a)
-- 
2.31.1




[PULL 19/37] qemu/int128: addition of div/rem 128-bit operations

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

Addition of div and rem on 128-bit integers, using the 128/64->128 divu and
64x64->128 mulu in host-utils.
These operations will be used within div/rem helpers in the 128-bit riscv
target.

Signed-off-by: Frédéric Pétrot 
Co-authored-by: Fabien Portas 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-4-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 include/qemu/int128.h |  27 
 util/int128.c | 147 ++
 util/meson.build  |   1 +
 3 files changed, 175 insertions(+)
 create mode 100644 util/int128.c

diff --git a/include/qemu/int128.h b/include/qemu/int128.h
index b6d517aea4..2c4064256c 100644
--- a/include/qemu/int128.h
+++ b/include/qemu/int128.h
@@ -172,6 +172,26 @@ static inline Int128 bswap128(Int128 a)
 #endif
 }
 
+static inline Int128 int128_divu(Int128 a, Int128 b)
+{
+return (__uint128_t)a / (__uint128_t)b;
+}
+
+static inline Int128 int128_remu(Int128 a, Int128 b)
+{
+return (__uint128_t)a % (__uint128_t)b;
+}
+
+static inline Int128 int128_divs(Int128 a, Int128 b)
+{
+return a / b;
+}
+
+static inline Int128 int128_rems(Int128 a, Int128 b)
+{
+return a % b;
+}
+
 #else /* !CONFIG_INT128 */
 
 typedef struct Int128 Int128;
@@ -379,6 +399,11 @@ static inline Int128 bswap128(Int128 a)
 return int128_make128(bswap64(a.hi), bswap64(a.lo));
 }
 
+Int128 int128_divu(Int128, Int128);
+Int128 int128_remu(Int128, Int128);
+Int128 int128_divs(Int128, Int128);
+Int128 int128_rems(Int128, Int128);
+
 #endif /* CONFIG_INT128 */
 
 static inline void bswap128s(Int128 *s)
@@ -386,4 +411,6 @@ static inline void bswap128s(Int128 *s)
 *s = bswap128(*s);
 }
 
+#define UINT128_MAX int128_make128(~0LL, ~0LL)
+
 #endif /* INT128_H */
diff --git a/util/int128.c b/util/int128.c
new file mode 100644
index 00..ed8f25fef1
--- /dev/null
+++ b/util/int128.c
@@ -0,0 +1,147 @@
+/*
+ * 128-bit division and remainder for compilers not supporting __int128
+ *
+ * Copyright (c) 2021 Frédéric Pétrot 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/host-utils.h"
+#include "qemu/int128.h"
+
+#ifndef CONFIG_INT128
+
+/*
+ * Division and remainder algorithms for 128-bit due to Stefan Kanthak,
+ * https://skanthak.homepage.t-online.de/integer.html#udivmodti4
+ * Preconditions:
+ * - function should never be called with v equals to 0, it has to
+ *   be dealt with beforehand
+ * - quotien pointer must be valid
+ */
+static Int128 divrem128(Int128 u, Int128 v, Int128 *q)
+{
+Int128 qq;
+uint64_t hi, lo, tmp;
+int s = clz64(v.hi);
+
+if (s == 64) {
+/* we have uu÷0v => let's use divu128 */
+hi = u.hi;
+lo = u.lo;
+tmp = divu128(, , v.lo);
+*q = int128_make128(lo, hi);
+return int128_make128(tmp, 0);
+} else {
+hi = int128_gethi(int128_lshift(v, s));
+
+if (hi > u.hi) {
+lo = u.lo;
+tmp = u.hi;
+divu128(, , hi);
+lo = int128_gethi(int128_lshift(int128_make128(lo, 0), s));
+} else { /* prevent overflow */
+lo = u.lo;
+tmp = u.hi - hi;
+divu128(, , hi);
+lo = int128_gethi(int128_lshift(int128_make128(lo, 1), s));
+}
+
+qq = int128_make64(lo);
+
+tmp = lo * v.hi;
+mulu64(, , lo, v.lo);
+hi += tmp;
+
+if (hi < tmp /* quotient * divisor >= 2**128 > dividend */
+|| hi > u.hi /* quotient * divisor > dividend */
+|| (hi == u.hi && lo > u.lo)) {
+qq.lo -= 1;
+mulu64(, , qq.lo, v.lo);
+hi += qq.lo * v.hi;
+}
+
+*q = qq;
+u.hi -= hi + (u.lo < lo);
+u.lo -= lo;
+return u;
+}
+}
+
+Int128 int128_divu(Int128 a, Int128 b)
+{
+Int128 q;
+divrem128(a, b, );
+return 

[PULL 04/37] hw/intc: sifive_plic: Add a reset function

2022-01-07 Thread Alistair Francis
From: Alistair Francis 

Signed-off-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Bin Meng 
Message-Id: <20220105213937.1113508-2-alistair.fran...@opensource.wdc.com>
---
 hw/intc/sifive_plic.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
index 877e76877c..a9f7a1bfb0 100644
--- a/hw/intc/sifive_plic.c
+++ b/hw/intc/sifive_plic.c
@@ -355,6 +355,23 @@ static const MemoryRegionOps sifive_plic_ops = {
 }
 };
 
+static void sifive_plic_reset(DeviceState *dev)
+{
+SiFivePLICState *s = SIFIVE_PLIC(dev);
+int i;
+
+memset(s->source_priority, 0, sizeof(uint32_t) * s->num_sources);
+memset(s->target_priority, 0, sizeof(uint32_t) * s->num_addrs);
+memset(s->pending, 0, sizeof(uint32_t) * s->bitfield_words);
+memset(s->claimed, 0, sizeof(uint32_t) * s->bitfield_words);
+memset(s->enable, 0, sizeof(uint32_t) * s->num_enables);
+
+for (i = 0; i < s->num_harts; i++) {
+qemu_set_irq(s->m_external_irqs[i], 0);
+qemu_set_irq(s->s_external_irqs[i], 0);
+}
+}
+
 /*
  * parse PLIC hart/mode address offset config
  *
@@ -501,6 +518,7 @@ static void sifive_plic_class_init(ObjectClass *klass, void 
*data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 
+dc->reset = sifive_plic_reset;
 device_class_set_props(dc, sifive_plic_properties);
 dc->realize = sifive_plic_realize;
 dc->vmsd = _sifive_plic;
-- 
2.31.1




[PULL 09/37] target/riscv: Enable the Hypervisor extension by default

2022-01-07 Thread Alistair Francis
From: Alistair Francis 

Let's enable the Hypervisor extension by default. This doesn't affect
named CPUs (such as lowrisc-ibex or sifive-u54) but does enable the
Hypervisor extensions by default for the virt machine.

Signed-off-by: Alistair Francis 
Reviewed-by: Anup Patel 
Reviewed-by: Bin Meng 
Message-Id: <20220105213937.1113508-7-alistair.fran...@opensource.wdc.com>
---
 target/riscv/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 9ea67bedd3..29749e834f 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -627,7 +627,7 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true),
 DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
 DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false),
-DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, false),
+DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, true),
 DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
 DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
 DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
-- 
2.31.1




[PULL 17/37] exec/memop: Adding signedness to quad definitions

2022-01-07 Thread Alistair Francis
From: Frédéric Pétrot 

Renaming defines for quad in their various forms so that their signedness is
now explicit.
Done using git grep as suggested by Philippe, with a bit of hand edition to
keep assignments aligned.

Signed-off-by: Frédéric Pétrot 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Message-id: 20220106210108.138226-2-frederic.pet...@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis 
---
 include/exec/memop.h   |  8 +--
 include/tcg/tcg-op.h   |  4 +-
 target/arm/translate-a32.h |  4 +-
 accel/tcg/cputlb.c | 30 +--
 accel/tcg/user-exec.c  |  8 +--
 target/alpha/translate.c   | 32 ++--
 target/arm/helper-a64.c|  8 +--
 target/arm/translate-a64.c |  8 +--
 target/arm/translate-neon.c|  6 +--
 target/arm/translate-sve.c | 10 ++--
 target/arm/translate-vfp.c |  8 +--
 target/arm/translate.c |  2 +-
 target/cris/translate.c|  2 +-
 target/hppa/translate.c|  4 +-
 target/i386/tcg/mem_helper.c   |  2 +-
 target/i386/tcg/translate.c| 36 +++---
 target/m68k/op_helper.c|  2 +-
 target/mips/tcg/translate.c| 58 +++---
 target/mips/tcg/tx79_translate.c   |  8 +--
 target/ppc/translate.c | 32 ++--
 target/s390x/tcg/mem_helper.c  |  8 +--
 target/s390x/tcg/translate.c   |  8 +--
 target/sh4/translate.c | 12 ++---
 target/sparc/translate.c   | 36 +++---
 target/tricore/translate.c |  4 +-
 target/xtensa/translate.c  |  4 +-
 tcg/tcg.c  |  4 +-
 tcg/tci.c  | 16 +++---
 accel/tcg/ldst_common.c.inc|  8 +--
 target/mips/tcg/micromips_translate.c.inc  | 10 ++--
 target/ppc/translate/fixedpoint-impl.c.inc | 22 
 target/ppc/translate/fp-impl.c.inc |  4 +-
 target/ppc/translate/vsx-impl.c.inc| 42 
 target/riscv/insn_trans/trans_rva.c.inc| 22 
 target/riscv/insn_trans/trans_rvd.c.inc|  4 +-
 target/riscv/insn_trans/trans_rvh.c.inc|  4 +-
 target/riscv/insn_trans/trans_rvi.c.inc|  4 +-
 target/s390x/tcg/translate_vx.c.inc| 18 +++
 tcg/aarch64/tcg-target.c.inc   |  2 +-
 tcg/arm/tcg-target.c.inc   | 10 ++--
 tcg/i386/tcg-target.c.inc  | 12 ++---
 tcg/mips/tcg-target.c.inc  | 12 ++---
 tcg/ppc/tcg-target.c.inc   | 16 +++---
 tcg/riscv/tcg-target.c.inc |  6 +--
 tcg/s390x/tcg-target.c.inc | 18 +++
 tcg/sparc/tcg-target.c.inc | 16 +++---
 target/s390x/tcg/insn-data.def | 28 +--
 47 files changed, 311 insertions(+), 311 deletions(-)

diff --git a/include/exec/memop.h b/include/exec/memop.h
index 04264ffd6b..72c2f0ff3d 100644
--- a/include/exec/memop.h
+++ b/include/exec/memop.h
@@ -85,29 +85,29 @@ typedef enum MemOp {
 MO_UB= MO_8,
 MO_UW= MO_16,
 MO_UL= MO_32,
+MO_UQ= MO_64,
 MO_SB= MO_SIGN | MO_8,
 MO_SW= MO_SIGN | MO_16,
 MO_SL= MO_SIGN | MO_32,
-MO_Q = MO_64,
 
 MO_LEUW  = MO_LE | MO_UW,
 MO_LEUL  = MO_LE | MO_UL,
+MO_LEUQ  = MO_LE | MO_UQ,
 MO_LESW  = MO_LE | MO_SW,
 MO_LESL  = MO_LE | MO_SL,
-MO_LEQ   = MO_LE | MO_Q,
 
 MO_BEUW  = MO_BE | MO_UW,
 MO_BEUL  = MO_BE | MO_UL,
+MO_BEUQ  = MO_BE | MO_UQ,
 MO_BESW  = MO_BE | MO_SW,
 MO_BESL  = MO_BE | MO_SL,
-MO_BEQ   = MO_BE | MO_Q,
 
 #ifdef NEED_CPU_H
 MO_TEUW  = MO_TE | MO_UW,
 MO_TEUL  = MO_TE | MO_UL,
+MO_TEUQ  = MO_TE | MO_UQ,
 MO_TESW  = MO_TE | MO_SW,
 MO_TESL  = MO_TE | MO_SL,
-MO_TEQ   = MO_TE | MO_Q,
 #endif
 
 MO_SSIZE = MO_SIZE | MO_SIGN,
diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
index 0545a6224c..caa0a63612 100644
--- a/include/tcg/tcg-op.h
+++ b/include/tcg/tcg-op.h
@@ -894,7 +894,7 @@ static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, 
int mem_index)
 
 static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index)
 {
-tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEQ);
+tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEUQ);
 }
 
 static inline void tcg_gen_qemu_st8(TCGv arg, TCGv addr, int mem_index)
@@ -914,7 +914,7 @@ static inline void tcg_gen_qemu_st32(TCGv arg, TCGv addr, 
int mem_index)
 
 static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
 {
-tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEQ);
+tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEUQ);
 }
 
 void tcg_gen_atomic_cmpxchg_i32(TCGv_i32, 

[PULL 10/37] hw/riscv: Use error_fatal for SoC realisation

2022-01-07 Thread Alistair Francis
From: Alistair Francis 

When realising the SoC use error_fatal instead of error_abort as the
process can fail and report useful information to the user.

Currently a user can see this:

   $ ../qemu/bld/qemu-system-riscv64 -M sifive_u -S -monitor stdio -display 
none -drive if=pflash
QEMU 6.1.93 monitor - type 'help' for more information
(qemu) Unexpected error in sifive_u_otp_realize() at 
../hw/misc/sifive_u_otp.c:229:
qemu-system-riscv64: OTP drive size < 16K
Aborted (core dumped)

Which this patch addresses

Reported-by: Markus Armbruster 
Signed-off-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Markus Armbruster 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
Message-Id: <20220105213937.1113508-8-alistair.fran...@opensource.wdc.com>
---
 hw/riscv/microchip_pfsoc.c | 2 +-
 hw/riscv/opentitan.c   | 2 +-
 hw/riscv/sifive_e.c| 2 +-
 hw/riscv/sifive_u.c| 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index d1d065efbc..cafd1fc9ae 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -471,7 +471,7 @@ static void microchip_icicle_kit_machine_init(MachineState 
*machine)
 /* Initialize SoC */
 object_initialize_child(OBJECT(machine), "soc", >soc,
 TYPE_MICROCHIP_PFSOC);
-qdev_realize(DEVICE(>soc), NULL, _abort);
+qdev_realize(DEVICE(>soc), NULL, _fatal);
 
 /* Split RAM into low and high regions using aliases to machine->ram */
 mem_low_size = memmap[MICROCHIP_PFSOC_DRAM_LO].size;
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index c531450b9f..0856c347e8 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -80,7 +80,7 @@ static void opentitan_board_init(MachineState *machine)
 /* Initialize SoC */
 object_initialize_child(OBJECT(machine), "soc", >soc,
 TYPE_RISCV_IBEX_SOC);
-qdev_realize(DEVICE(>soc), NULL, _abort);
+qdev_realize(DEVICE(>soc), NULL, _fatal);
 
 memory_region_add_subregion(sys_mem,
 memmap[IBEX_DEV_RAM].base, machine->ram);
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 9b206407a6..dcb87b6cfd 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -88,7 +88,7 @@ static void sifive_e_machine_init(MachineState *machine)
 
 /* Initialize SoC */
 object_initialize_child(OBJECT(machine), "soc", >soc, TYPE_RISCV_E_SOC);
-qdev_realize(DEVICE(>soc), NULL, _abort);
+qdev_realize(DEVICE(>soc), NULL, _fatal);
 
 /* Data Tightly Integrated Memory */
 memory_region_add_subregion(sys_mem,
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index aa74e67889..7fbc7dea42 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -547,7 +547,7 @@ static void sifive_u_machine_init(MachineState *machine)
  _abort);
 object_property_set_str(OBJECT(>soc), "cpu-type", machine->cpu_type,
  _abort);
-qdev_realize(DEVICE(>soc), NULL, _abort);
+qdev_realize(DEVICE(>soc), NULL, _fatal);
 
 /* register RAM */
 memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_DRAM].base,
-- 
2.31.1




[PULL 01/37] target/riscv/pmp: fix no pmp illegal intrs

2022-01-07 Thread Alistair Francis
From: Nikita Shubin 

As per the privilege specification, any access from S/U mode should fail
if no pmp region is configured and pmp is present, othwerwise access
should succeed.

Fixes: d102f19a208 (target/riscv/pmp: Raise exception if no PMP entry is 
configured)
Signed-off-by: Nikita Shubin 
Reviewed-by: Alistair Francis 
Message-id: 20211214092659.15709-1-nikita.shu...@maquefel.me
Signed-off-by: Alistair Francis 
---
 target/riscv/op_helper.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index ee7c24efe7..58d992e98a 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -146,7 +146,8 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong 
cpu_pc_deb)
 uint64_t mstatus = env->mstatus;
 target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
 
-if (!pmp_get_num_rules(env) && (prev_priv != PRV_M)) {
+if (riscv_feature(env, RISCV_FEATURE_PMP) &&
+!pmp_get_num_rules(env) && (prev_priv != PRV_M)) {
 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
 }
 
-- 
2.31.1




[PULL 05/37] hw/intc: sifive_plic: Cleanup the write function

2022-01-07 Thread Alistair Francis
From: Alistair Francis 

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-Id: <20220105213937.1113508-3-alistair.fran...@opensource.wdc.com>
---
 hw/intc/sifive_plic.c | 76 +++
 1 file changed, 27 insertions(+), 49 deletions(-)

diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
index a9f7a1bfb0..698492ce77 100644
--- a/hw/intc/sifive_plic.c
+++ b/hw/intc/sifive_plic.c
@@ -33,6 +33,11 @@
 
 #define RISCV_DEBUG_PLIC 0
 
+static bool addr_between(uint32_t addr, uint32_t base, uint32_t num)
+{
+return addr >= base && addr - base < num;
+}
+
 static PLICMode char_to_mode(char c)
 {
 switch (c) {
@@ -269,80 +274,53 @@ static void sifive_plic_write(void *opaque, hwaddr addr, 
uint64_t value,
 {
 SiFivePLICState *plic = opaque;
 
-/* writes must be 4 byte words */
-if ((addr & 0x3) != 0) {
-goto err;
-}
-
-if (addr >= plic->priority_base && /* 4 bytes per source */
-addr < plic->priority_base + (plic->num_sources << 2))
-{
+if (addr_between(addr, plic->priority_base, plic->num_sources << 2)) {
 uint32_t irq = ((addr - plic->priority_base) >> 2) + 1;
+
 plic->source_priority[irq] = value & 7;
-if (RISCV_DEBUG_PLIC) {
-qemu_log("plic: write priority: irq=%d priority=%d\n",
-irq, plic->source_priority[irq]);
-}
 sifive_plic_update(plic);
-return;
-} else if (addr >= plic->pending_base && /* 1 bit per source */
-   addr < plic->pending_base + (plic->num_sources >> 3))
-{
+} else if (addr_between(addr, plic->pending_base,
+plic->num_sources >> 3)) {
 qemu_log_mask(LOG_GUEST_ERROR,
   "%s: invalid pending write: 0x%" HWADDR_PRIx "",
   __func__, addr);
-return;
-} else if (addr >= plic->enable_base && /* 1 bit per source */
-addr < plic->enable_base + plic->num_addrs * plic->enable_stride)
-{
+} else if (addr_between(addr, plic->enable_base,
+plic->num_addrs * plic->enable_stride)) {
 uint32_t addrid = (addr - plic->enable_base) / plic->enable_stride;
 uint32_t wordid = (addr & (plic->enable_stride - 1)) >> 2;
+
 if (wordid < plic->bitfield_words) {
 plic->enable[addrid * plic->bitfield_words + wordid] = value;
-if (RISCV_DEBUG_PLIC) {
-qemu_log("plic: write enable: hart%d-%c word=%d value=%x\n",
-plic->addr_config[addrid].hartid,
-mode_to_char(plic->addr_config[addrid].mode), wordid,
-plic->enable[addrid * plic->bitfield_words + wordid]);
-}
-return;
+} else {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Invalid enable write 0x%" HWADDR_PRIx "\n",
+  __func__, addr);
 }
-} else if (addr >= plic->context_base && /* 4 bytes per reg */
-addr < plic->context_base + plic->num_addrs * plic->context_stride)
-{
+} else if (addr_between(addr, plic->context_base,
+plic->num_addrs * plic->context_stride)) {
 uint32_t addrid = (addr - plic->context_base) / plic->context_stride;
 uint32_t contextid = (addr & (plic->context_stride - 1));
+
 if (contextid == 0) {
-if (RISCV_DEBUG_PLIC) {
-qemu_log("plic: write priority: hart%d-%c priority=%x\n",
-plic->addr_config[addrid].hartid,
-mode_to_char(plic->addr_config[addrid].mode),
-plic->target_priority[addrid]);
-}
 if (value <= plic->num_priorities) {
 plic->target_priority[addrid] = value;
 sifive_plic_update(plic);
 }
-return;
 } else if (contextid == 4) {
-if (RISCV_DEBUG_PLIC) {
-qemu_log("plic: write claim: hart%d-%c irq=%x\n",
-plic->addr_config[addrid].hartid,
-mode_to_char(plic->addr_config[addrid].mode),
-(uint32_t)value);
-}
 if (value < plic->num_sources) {
 sifive_plic_set_claimed(plic, value, false);
 sifive_plic_update(plic);
 }
-return;
+} else {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Invalid context write 0x%" HWADDR_PRIx "\n",
+  __func__, addr);
 }
+} else {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Invalid register write 0x%" HWADDR_PRIx "\n",
+  __func__, addr);
 }
-
-err:
-qemu_log_mask(LOG_GUEST_ERROR,
-  "%s: Invalid register write 0x%" HWADDR_PRIx "\n",
-  __func__, addr);
 }
 
 static const MemoryRegionOps sifive_plic_ops = {
-- 

[PULL 02/37] hw/dma: sifive_pdma: support high 32-bit access of 64-bit register

2022-01-07 Thread Alistair Francis
From: Jim Shu 

Real PDMA supports high 32-bit read/write memory access of 64-bit
register.

The following result is PDMA tested in U-Boot on Unmatched board:

1. Real PDMA allows high 32-bit read/write to 64-bit register.
=> mw.l 0x300 0x0  <= Disclaim channel 0
=> mw.l 0x300 0x1  <= Claim channel 0
=> mw.l 0x310 0x8000   <= Write low 32-bit NextDest 
(NextDest = 0x28000)
=> mw.l 0x314 0x2  <= Write high 32-bit NextDest
=> md.l 0x310 1<= Dump low 32-bit NextDest
0310: 8000
=> md.l 0x314 1<= Dump high 32-bit NextDest
0314: 0002
=> mw.l 0x318 0x80001000   <= Write low 32-bit NextSrc (NextSrc 
= 0x280001000)
=> mw.l 0x31c 0x2  <= Write high 32-bit NextSrc
=> md.l 0x318 1<= Dump low 32-bit NextSrc
0310: 80001000
=> md.l 0x31c 1<= Dump high 32-bit NextSrc
0314: 0002

2. PDMA transfer from 0x280001000 to 0x28000 is OK.
=> mw.q 0x308 0x4  <= NextBytes = 4
=> mw.l 0x304 0x2200   <= wsize = rsize = 2 (2^2 = 4 bytes)
=> mw.l 0x28000 0x87654321 <= Fill test data to dst
=> mw.l 0x280001000 0x12345678 <= Fill test data to src
=> md.l 0x28000 1; md.l 0x280001000 1  <= Dump src/dst memory contents
28000: 87654321  !Ce.
280001000: 12345678  xV4.
=> md.l 0x300 8<= Dump PDMA status
0300: 0001 2200 0004 ..."
0310: 8000 0002 80001000 0002
=> mw.l 0x300 0x3  <= Set channel 0 run and claim bits
=> md.l 0x300 8<= Dump PDMA status
0300: 4001 2200 0004 ...@..."
0310: 8000 0002 80001000 0002
=> md.l 0x28000 1; md.l 0x280001000 1  <= Dump src/dst memory contents
28000: 12345678   xV4.
280001000: 12345678   xV4.

Signed-off-by: Jim Shu 
Reviewed-by: Frank Chang 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
Message-id: 20220104063408.658169-2-jim@sifive.com
Signed-off-by: Alistair Francis 
---
 hw/dma/sifive_pdma.c | 177 +--
 1 file changed, 155 insertions(+), 22 deletions(-)

diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
index 85fe34f5f3..f4df16449b 100644
--- a/hw/dma/sifive_pdma.c
+++ b/hw/dma/sifive_pdma.c
@@ -177,18 +177,44 @@ static inline void sifive_pdma_update_irq(SiFivePDMAState 
*s, int ch)
 s->chan[ch].state = DMA_CHAN_STATE_IDLE;
 }
 
-static uint64_t sifive_pdma_read(void *opaque, hwaddr offset, unsigned size)
+static uint64_t sifive_pdma_readq(SiFivePDMAState *s, int ch, hwaddr offset)
 {
-SiFivePDMAState *s = opaque;
-int ch = SIFIVE_PDMA_CHAN_NO(offset);
 uint64_t val = 0;
 
-if (ch >= SIFIVE_PDMA_CHANS) {
-qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
-  __func__, ch);
-return 0;
+offset &= 0xfff;
+switch (offset) {
+case DMA_NEXT_BYTES:
+val = s->chan[ch].next_bytes;
+break;
+case DMA_NEXT_DST:
+val = s->chan[ch].next_dst;
+break;
+case DMA_NEXT_SRC:
+val = s->chan[ch].next_src;
+break;
+case DMA_EXEC_BYTES:
+val = s->chan[ch].exec_bytes;
+break;
+case DMA_EXEC_DST:
+val = s->chan[ch].exec_dst;
+break;
+case DMA_EXEC_SRC:
+val = s->chan[ch].exec_src;
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Unexpected 64-bit access to 0x%" HWADDR_PRIX "\n",
+  __func__, offset);
+break;
 }
 
+return val;
+}
+
+static uint32_t sifive_pdma_readl(SiFivePDMAState *s, int ch, hwaddr offset)
+{
+uint32_t val = 0;
+
 offset &= 0xfff;
 switch (offset) {
 case DMA_CONTROL:
@@ -198,28 +224,47 @@ static uint64_t sifive_pdma_read(void *opaque, hwaddr 
offset, unsigned size)
 val = s->chan[ch].next_config;
 break;
 case DMA_NEXT_BYTES:
-val = s->chan[ch].next_bytes;
+val = extract64(s->chan[ch].next_bytes, 0, 32);
+break;
+case DMA_NEXT_BYTES + 4:
+val = extract64(s->chan[ch].next_bytes, 32, 32);
 break;
 case DMA_NEXT_DST:
-val = s->chan[ch].next_dst;
+val = extract64(s->chan[ch].next_dst, 0, 32);
+break;
+case DMA_NEXT_DST + 4:
+val = extract64(s->chan[ch].next_dst, 32, 32);
 break;
 case DMA_NEXT_SRC:
-val = s->chan[ch].next_src;
+val = extract64(s->chan[ch].next_src, 0, 32);
+break;
+case DMA_NEXT_SRC + 4:
+val = 

[PULL 00/37] riscv-to-apply queue

2022-01-07 Thread Alistair Francis
From: Alistair Francis 

The following changes since commit d70075373af51b6aa1d637962c962120e201fc98:

  Merge tag 'for_upstream' of git://git.kernel.org/pub/scm/virt/kvm/mst/qemu 
into staging (2022-01-07 17:24:24 -0800)

are available in the Git repository at:

  g...@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20220108

for you to fetch changes up to 48eaeb56debf91817dea00a2cd9c1f6c986eb531:

  target/riscv: Implement the stval/mtval illegal instruction (2022-01-08 
15:46:10 +1000)


Second RISC-V PR for QEMU 7.0

 - Fix illegal instruction when PMP is disabled
 - SiFive PDMA 64-bit support
 - SiFive PLIC cleanups
 - Mark Hypervisor extension as non experimental
 - Enable Hypervisor extension by default
 - Support 32 cores on the virt machine
 - Corrections for the Vector extension
 - Experimental support for 128-bit CPUs
 - stval and mtval support for illegal instructions


Alistair Francis (11):
  hw/intc: sifive_plic: Add a reset function
  hw/intc: sifive_plic: Cleanup the write function
  hw/intc: sifive_plic: Cleanup the read function
  hw/intc: sifive_plic: Cleanup remaining functions
  target/riscv: Mark the Hypervisor extension as non experimental
  target/riscv: Enable the Hypervisor extension by default
  hw/riscv: Use error_fatal for SoC realisation
  hw/riscv: virt: Allow support for 32 cores
  target/riscv: Set the opcode in DisasContext
  target/riscv: Fixup setting GVA
  target/riscv: Implement the stval/mtval illegal instruction

Bin Meng (1):
  roms/opensbi: Upgrade from v0.9 to v1.0

Frank Chang (3):
  target/riscv: rvv-1.0: Call the correct RVF/RVD check function for 
widening fp insns
  target/riscv: rvv-1.0: Call the correct RVF/RVD check function for 
widening fp/int type-convert insns
  target/riscv: rvv-1.0: Call the correct RVF/RVD check function for 
narrowing fp/int type-convert insns

Frédéric Pétrot (18):
  exec/memop: Adding signedness to quad definitions
  exec/memop: Adding signed quad and octo defines
  qemu/int128: addition of div/rem 128-bit operations
  target/riscv: additional macros to check instruction support
  target/riscv: separation of bitwise logic and arithmetic helpers
  target/riscv: array for the 64 upper bits of 128-bit registers
  target/riscv: setup everything for rv64 to support rv128 execution
  target/riscv: moving some insns close to similar insns
  target/riscv: accessors to registers upper part and 128-bit load/store
  target/riscv: support for 128-bit bitwise instructions
  target/riscv: support for 128-bit U-type instructions
  target/riscv: support for 128-bit shift instructions
  target/riscv: support for 128-bit arithmetic instructions
  target/riscv: support for 128-bit M extension
  target/riscv: adding high part of some csrs
  target/riscv: helper functions to wrap calls to 128-bit csr insns
  target/riscv: modification of the trans_csrxx for 128-bit support
  target/riscv: actual functions to realize crs 128-bit insns

Jim Shu (2):
  hw/dma: sifive_pdma: support high 32-bit access of 64-bit register
  hw/dma: sifive_pdma: permit 4/8-byte access size of PDMA registers

Nikita Shubin (1):
  target/riscv/pmp: fix no pmp illegal intrs

Philipp Tomsich (1):
  target/riscv: Fix position of 'experimental' comment

 include/disas/dis-asm.h|   1 +
 include/exec/memop.h   |  15 +-
 include/hw/riscv/virt.h|   2 +-
 include/qemu/int128.h  |  27 +
 include/tcg/tcg-op.h   |   4 +-
 target/arm/translate-a32.h |   4 +-
 target/riscv/cpu.h |  24 +
 target/riscv/cpu_bits.h|   3 +
 target/riscv/helper.h  |   9 +
 target/riscv/insn16.decode |  27 +-
 target/riscv/insn32.decode |  25 +
 accel/tcg/cputlb.c |  30 +-
 accel/tcg/user-exec.c  |   8 +-
 disas/riscv.c  |   5 +
 hw/dma/sifive_pdma.c   | 181 ++-
 hw/intc/sifive_plic.c  | 254 +++--
 hw/riscv/microchip_pfsoc.c |   2 +-
 hw/riscv/opentitan.c   |   2 +-
 hw/riscv/sifive_e.c|   2 +-
 hw/riscv/sifive_u.c|   2 +-
 target/alpha/translate.c   |  32 +-
 target/arm/helper-a64.c|   8 +-
 target/arm/translate-a64.c |   8 +-
 target/arm/translate-neon.c|   6 +-
 target/arm/translate-sve.c |  10 +-
 target/arm/translate-vfp.c   

[PULL 07/37] hw/intc: sifive_plic: Cleanup remaining functions

2022-01-07 Thread Alistair Francis
From: Alistair Francis 

We can remove the original sifive_plic_irqs_pending() function and
instead just use the sifive_plic_claim() function (renamed to
sifive_plic_claimed()) to determine if any interrupts are pending.

This requires move the side effects outside of sifive_plic_claimed(),
but as they are only invoked once that isn't a problem.

We have also removed all of the old #ifdef debugging logs, so let's
cleanup the last remaining debug function while we are here.

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-Id: <20220105213937.1113508-5-alistair.fran...@opensource.wdc.com>
---
 hw/intc/sifive_plic.c | 109 +-
 1 file changed, 22 insertions(+), 87 deletions(-)

diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
index 44d24b3c59..746c0f0343 100644
--- a/hw/intc/sifive_plic.c
+++ b/hw/intc/sifive_plic.c
@@ -31,8 +31,6 @@
 #include "migration/vmstate.h"
 #include "hw/irq.h"
 
-#define RISCV_DEBUG_PLIC 0
-
 static bool addr_between(uint32_t addr, uint32_t base, uint32_t num)
 {
 return addr >= base && addr - base < num;
@@ -51,47 +49,6 @@ static PLICMode char_to_mode(char c)
 }
 }
 
-static char mode_to_char(PLICMode m)
-{
-switch (m) {
-case PLICMode_U: return 'U';
-case PLICMode_S: return 'S';
-case PLICMode_H: return 'H';
-case PLICMode_M: return 'M';
-default: return '?';
-}
-}
-
-static void sifive_plic_print_state(SiFivePLICState *plic)
-{
-int i;
-int addrid;
-
-/* pending */
-qemu_log("pending   : ");
-for (i = plic->bitfield_words - 1; i >= 0; i--) {
-qemu_log("%08x", plic->pending[i]);
-}
-qemu_log("\n");
-
-/* pending */
-qemu_log("claimed   : ");
-for (i = plic->bitfield_words - 1; i >= 0; i--) {
-qemu_log("%08x", plic->claimed[i]);
-}
-qemu_log("\n");
-
-for (addrid = 0; addrid < plic->num_addrs; addrid++) {
-qemu_log("hart%d-%c enable: ",
-plic->addr_config[addrid].hartid,
-mode_to_char(plic->addr_config[addrid].mode));
-for (i = plic->bitfield_words - 1; i >= 0; i--) {
-qemu_log("%08x", plic->enable[addrid * plic->bitfield_words + i]);
-}
-qemu_log("\n");
-}
-}
-
 static uint32_t atomic_set_masked(uint32_t *a, uint32_t mask, uint32_t value)
 {
 uint32_t old, new, cmp = qatomic_read(a);
@@ -115,26 +72,34 @@ static void sifive_plic_set_claimed(SiFivePLICState *plic, 
int irq, bool level)
 atomic_set_masked(>claimed[irq >> 5], 1 << (irq & 31), -!!level);
 }
 
-static int sifive_plic_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
+static uint32_t sifive_plic_claimed(SiFivePLICState *plic, uint32_t addrid)
 {
+uint32_t max_irq = 0;
+uint32_t max_prio = plic->target_priority[addrid];
 int i, j;
+
 for (i = 0; i < plic->bitfield_words; i++) {
 uint32_t pending_enabled_not_claimed =
-(plic->pending[i] & ~plic->claimed[i]) &
-plic->enable[addrid * plic->bitfield_words + i];
+(plic->pending[i] & ~plic->claimed[i]) &
+plic->enable[addrid * plic->bitfield_words + i];
+
 if (!pending_enabled_not_claimed) {
 continue;
 }
+
 for (j = 0; j < 32; j++) {
 int irq = (i << 5) + j;
 uint32_t prio = plic->source_priority[irq];
 int enabled = pending_enabled_not_claimed & (1 << j);
-if (enabled && prio > plic->target_priority[addrid]) {
-return 1;
+
+if (enabled && prio > max_prio) {
+max_irq = irq;
+max_prio = prio;
 }
 }
 }
-return 0;
+
+return max_irq;
 }
 
 static void sifive_plic_update(SiFivePLICState *plic)
@@ -145,7 +110,7 @@ static void sifive_plic_update(SiFivePLICState *plic)
 for (addrid = 0; addrid < plic->num_addrs; addrid++) {
 uint32_t hartid = plic->addr_config[addrid].hartid;
 PLICMode mode = plic->addr_config[addrid].mode;
-int level = sifive_plic_irqs_pending(plic, addrid);
+bool level = !!sifive_plic_claimed(plic, addrid);
 
 switch (mode) {
 case PLICMode_M:
@@ -158,41 +123,6 @@ static void sifive_plic_update(SiFivePLICState *plic)
 break;
 }
 }
-
-if (RISCV_DEBUG_PLIC) {
-sifive_plic_print_state(plic);
-}
-}
-
-static uint32_t sifive_plic_claim(SiFivePLICState *plic, uint32_t addrid)
-{
-int i, j;
-uint32_t max_irq = 0;
-uint32_t max_prio = plic->target_priority[addrid];
-
-for (i = 0; i < plic->bitfield_words; i++) {
-uint32_t pending_enabled_not_claimed =
-(plic->pending[i] & ~plic->claimed[i]) &
-plic->enable[addrid * plic->bitfield_words + i];
-if (!pending_enabled_not_claimed) {
-continue;
-}
-for (j = 0; j < 32; j++) {
-int irq = (i << 5) + j;
-uint32_t 

Re: [PULL v3 00/55] virtio,pci,pc: features,fixes,cleanups

2022-01-07 Thread Richard Henderson

On 1/7/22 5:03 PM, Michael S. Tsirkin wrote:

Changes from v2:
- fix fallout from attempts to fix up virtio mem prealloc patches

Changes from v1:
- mingw build fixes
- added TPM patches which got acks meanwhile

Big changes that were tagged originally but did not make the cut:
- SRIOV/nvme (not sure they are my tree material anyway)
- ACPI ERST (some coding style violations)



The following changes since commit 7d4ae4d4978079d564d3b6354c90a949130409fe:

   Merge tag 'pull-request-2022-01-05' of https://gitlab.com/thuth/qemu into 
staging (2022-01-05 08:47:18 -0800)

are available in the Git repository at:

   git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream

for you to fetch changes up to ca745d2277496464b54fd832c15c45d0227325bb:

   tests: acpi: Add updated TPM related tables (2022-01-07 19:30:13 -0500)


virtio,pci,pc: features,fixes,cleanups

New virtio mem options.
A vhost-user cleanup.
Control over smbios entry point type.
Config interrupt support for vdpa.
Fixes, cleanups all over the place.

Signed-off-by: Michael S. Tsirkin 


Andy Pei (1):
   hw/vhost-user-blk: turn on VIRTIO_BLK_F_SIZE_MAX feature for virtio blk 
device

Ani Sinha (2):
   MAINTAINERS: Add a separate entry for acpi/VIOT tables
   acpihp: simplify acpi_pcihp_disable_root_bus

Cindy Lu (10):
   virtio: introduce macro IRTIO_CONFIG_IRQ_IDX
   virtio-pci: decouple notifier from interrupt process
   virtio-pci: decouple the single vector from the interrupt process
   vhost: introduce new VhostOps vhost_set_config_call
   vhost-vdpa: add support for config interrupt
   virtio: add support for configure interrupt
   vhost: add support for configure interrupt
   virtio-net: add support for configure interrupt
   virtio-mmio: add support for configure interrupt
   virtio-pci: add support for configure interrupt

Daniil Tatianin (3):
   hw/scsi/vhost-scsi: don't leak vqs on error
   hw/scsi/vhost-scsi: don't double close vhostfd on error
   virtio/vhost-vsock: don't double close vhostfd, remove redundant cleanup

David Hildenbrand (12):
   virtio-mem: Don't skip alignment checks when warning about block size
   util/oslib-posix: Let touch_all_pages() return an error
   util/oslib-posix: Support MADV_POPULATE_WRITE for os_mem_prealloc()
   util/oslib-posix: Introduce and use MemsetContext for touch_all_pages()
   util/oslib-posix: Don't create too many threads with small memory or 
little pages
   util/oslib-posix: Avoid creating a single thread with MADV_POPULATE_WRITE
   util/oslib-posix: Support concurrent os_mem_prealloc() invocation
   util/oslib-posix: Forward SIGBUS to MCE handler under Linux
   virtio-mem: Support "prealloc=on" option
   linux-headers: sync VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE
   virtio-mem: Support VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE
   virtio-mem: Set "unplugged-inaccessible=auto" for the 7.0 machine on x86

Eduardo Habkost (3):
   smbios: Rename SMBIOS_ENTRY_POINT_* enums
   hw/smbios: Use qapi for SmbiosEntryPointType
   hw/i386: expose a "smbios-entry-point-type" PC machine property

Frederic Barrat (2):
   pci: Export the pci_intx() function
   pcie_aer: Don't trigger a LSI if none are defined

Igor Mammedov (4):
   acpi: fix QEMU crash when started with SLIC table
   tests: acpi: whitelist expected blobs before changing them
   tests: acpi: add SLIC table test
   tests: acpi: SLIC: update expected blobs

Jason Wang (1):
   intel-iommu: correctly check passthrough during translation

Laurent Vivier (1):
   trace-events,pci: unify trace events format

Michael S. Tsirkin (1):
   acpi: validate hotplug selector on access

Roman Kagan (9):
   vhost-user-blk: reconnect on any error during realize
   chardev/char-socket: tcp_chr_recv: don't clobber errno
   chardev/char-socket: tcp_chr_sync_read: don't clobber errno
   vhost-backend: avoid overflow on memslots_limit
   vhost-backend: stick to -errno error return convention
   vhost-vdpa: stick to -errno error return convention
   vhost-user: stick to -errno error return convention
   vhost: stick to -errno error return convention
   vhost-user-blk: propagate error return from generic vhost

Stefan Berger (3):
   tests: acpi: prepare for updated TPM related tables
   acpi: tpm: Add missing device identification objects
   tests: acpi: Add updated TPM related tables

Stefan Hajnoczi (1):
   virtio: signal after wrapping packed used_idx

Thomas Huth (2):
   hw/i386/pc: Add missing property descriptions
   docs: reSTify virtio-balloon-stats documentation and move to docs/interop

  qapi/machine.json  |  12 +
  hw/virtio/virtio-pci.h |   4 +-
  

[PATCH] hw/sensor: Add SB-TSI Temperature Sensor Interface

2022-01-07 Thread Patrick Venture
From: Hao Wu 

SB Temperature Sensor Interface (SB-TSI) is an SMBus compatible
interface that reports AMD SoC's Ttcl (normalized temperature),
and resembles a typical 8-pin remote temperature sensor's I2C interface
to BMC.

This patch implements a basic AMD SB-TSI sensor that is
compatible with the open-source data sheet from AMD and Linux
kernel driver.

Reference:
Linux kernel driver:
https://lkml.org/lkml/2020/12/11/968
Register Map:
https://developer.amd.com/wp-content/resources/56255_3_03.PDF
(Chapter 6)

Signed-off-by: Hao Wu 
Reviewed-by: Doug Evans 
---
 hw/sensor/Kconfig|   4 +
 hw/sensor/meson.build|   1 +
 hw/sensor/tmp_sbtsi.c| 393 +++
 hw/sensor/trace-events   |   5 +
 hw/sensor/trace.h|   1 +
 meson.build  |   1 +
 tests/qtest/meson.build  |   1 +
 tests/qtest/tmp_sbtsi-test.c | 180 
 8 files changed, 586 insertions(+)
 create mode 100644 hw/sensor/tmp_sbtsi.c
 create mode 100644 hw/sensor/trace-events
 create mode 100644 hw/sensor/trace.h
 create mode 100644 tests/qtest/tmp_sbtsi-test.c

diff --git a/hw/sensor/Kconfig b/hw/sensor/Kconfig
index 9c8a049b06..27f6f79c84 100644
--- a/hw/sensor/Kconfig
+++ b/hw/sensor/Kconfig
@@ -21,3 +21,7 @@ config ADM1272
 config MAX34451
 bool
 depends on I2C
+
+config AMDSBTSI
+bool
+depends on I2C
diff --git a/hw/sensor/meson.build b/hw/sensor/meson.build
index 059c4ca935..f7b0e645eb 100644
--- a/hw/sensor/meson.build
+++ b/hw/sensor/meson.build
@@ -4,3 +4,4 @@ softmmu_ss.add(when: 'CONFIG_DPS310', if_true: 
files('dps310.c'))
 softmmu_ss.add(when: 'CONFIG_EMC141X', if_true: files('emc141x.c'))
 softmmu_ss.add(when: 'CONFIG_ADM1272', if_true: files('adm1272.c'))
 softmmu_ss.add(when: 'CONFIG_MAX34451', if_true: files('max34451.c'))
+softmmu_ss.add(when: 'CONFIG_AMDSBTSI', if_true: files('tmp_sbtsi.c'))
diff --git a/hw/sensor/tmp_sbtsi.c b/hw/sensor/tmp_sbtsi.c
new file mode 100644
index 00..b68c7ebf61
--- /dev/null
+++ b/hw/sensor/tmp_sbtsi.c
@@ -0,0 +1,393 @@
+/*
+ * AMD SBI Temperature Sensor Interface (SB-TSI)
+ *
+ * Copyright 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/i2c/smbus_slave.h"
+#include "hw/irq.h"
+#include "migration/vmstate.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "trace.h"
+
+#define TYPE_SBTSI "sbtsi"
+#define SBTSI(obj) OBJECT_CHECK(SBTSIState, (obj), TYPE_SBTSI)
+
+/**
+ * SBTSIState:
+ * temperatures are in units of 0.125 degrees
+ * @temperature: Temperature
+ * @limit_low: Lowest temperature
+ * @limit_high: Highest temperature
+ * @status: The status register
+ * @config: The config register
+ * @alert_config: The config for alarm_l output.
+ * @addr: The address to read/write for the next cmd.
+ * @alarm: The alarm_l output pin (GPIO)
+ */
+typedef struct SBTSIState {
+SMBusDevice parent;
+
+uint32_t temperature;
+uint32_t limit_low;
+uint32_t limit_high;
+uint8_t status;
+uint8_t config;
+uint8_t alert_config;
+uint8_t addr;
+qemu_irq alarm;
+} SBTSIState;
+
+/*
+ * SB-TSI registers only support SMBus byte data access. "_INT" registers are
+ * the integer part of a temperature value or limit, and "_DEC" registers are
+ * corresponding decimal parts.
+ */
+#define SBTSI_REG_TEMP_INT  0x01 /* RO */
+#define SBTSI_REG_STATUS0x02 /* RO */
+#define SBTSI_REG_CONFIG0x03 /* RO */
+#define SBTSI_REG_TEMP_HIGH_INT 0x07 /* RW */
+#define SBTSI_REG_TEMP_LOW_INT  0x08 /* RW */
+#define SBTSI_REG_CONFIG_WR 0x09 /* RW */
+#define SBTSI_REG_TEMP_DEC  0x10 /* RO */
+#define SBTSI_REG_TEMP_HIGH_DEC 0x13 /* RW */
+#define SBTSI_REG_TEMP_LOW_DEC  0x14 /* RW */
+#define SBTSI_REG_ALERT_CONFIG  0xBF /* RW */
+#define SBTSI_REG_MAN   0xFE /* RO */
+#define SBTSI_REG_REV   0xFF /* RO */
+
+#define SBTSI_STATUS_HIGH_ALERT BIT(4)
+#define SBTSI_STATUS_LOW_ALERT  BIT(3)
+#define SBTSI_CONFIG_ALERT_MASK BIT(7)
+#define SBTSI_ALARM_EN  BIT(0)
+
+#define SBTSI_LIMIT_LOW_DEFAULT (0)
+#define SBTSI_LIMIT_HIGH_DEFAULT (560)
+#define SBTSI_MAN_DEFAULT (0)
+#define SBTSI_REV_DEFAULT (4)
+#define SBTSI_ALARM_L "alarm_l"
+
+/* The temperature we stored are in units of 0.125 degrees. */
+#define SBTSI_TEMP_UNIT_IN_MILLIDEGREE 125
+
+/*
+ * The integer part and decimal of the temperature both 8 bits.
+ * Only the top 3 bits of the decimal parts are used.

Re: [PATCH v3 4/6] target/riscv: add support for zdinx

2022-01-07 Thread Weiwei Li

在 2022/1/8 上午4:54, Richard Henderson 写道:

On 1/7/22 3:27 AM, Weiwei Li wrote:

+#define REQUIRE_EVEN(ctx, reg) do { \
+    if (ctx->ext_zdinx && (get_xl(ctx) == MXL_RV32) && \
+    (reg & 0x1)) { \
+    return false; \
+    } \
+} while (0)


Parenthesis around reg.


+    REQUIRE_EVEN(ctx, a->rd);
+    REQUIRE_EVEN(ctx, a->rs1);
+    REQUIRE_EVEN(ctx, a->rs2);
+    REQUIRE_EVEN(ctx, a->rs3);


I think these could all be combined:

    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3);

Yeah, That's true. I'll update this.


etc.

Otherwise,
Reviewed-by: Richard Henderson 


r~





[PULL v3 55/55] tests: acpi: Add updated TPM related tables

2022-01-07 Thread Michael S. Tsirkin
From: Stefan Berger 

The updated TPM related tables have the following additions:

   Device (TPM)
   {
   Name (_HID, "MSFT0101" /* TPM 2.0 Security Device */)  // _HID: Hardware 
ID
+  Name (_STR, "TPM 2.0 Device")  // _STR: Description String
+  Name (_UID, One)  // _UID: Unique ID
   Name (_STA, 0x0F)  // _STA: Status
   Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings

Cc: Michael S. Tsirkin 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Signed-off-by: Stefan Berger 
Acked-by: Ani Sinha 
Message-id: 20211223022310.575496-4-stef...@linux.ibm.com
Message-Id: <20220104175806.872996-4-stef...@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 tests/qtest/bios-tables-test-allowed-diff.h |   2 --
 tests/data/acpi/q35/DSDT.tis.tpm12  | Bin 8894 -> 8900 bytes
 tests/data/acpi/q35/DSDT.tis.tpm2   | Bin 8894 -> 8921 bytes
 3 files changed, 2 deletions(-)

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index 5d80e408d4..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,3 +1 @@
 /* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/q35/DSDT.tis.tpm12",
-"tests/data/acpi/q35/DSDT.tis.tpm2",
diff --git a/tests/data/acpi/q35/DSDT.tis.tpm12 
b/tests/data/acpi/q35/DSDT.tis.tpm12
index 
0ebdf6fbd77967f1ab5d5337b7b1fed314cfaca8..fb9dd1f0599afd6b555ea570ecd00a3bb227aa84
 100644
GIT binary patch
delta 50
zcmdnzdc>8>CDH@7HQF#!OXcoHoD

delta 46
zcmccVy3du%CD

[PULL v3 54/55] acpi: tpm: Add missing device identification objects

2022-01-07 Thread Michael S. Tsirkin
From: Stefan Berger 

Add missing TPM device identification objects _STR and _UID. They will
appear as files 'description' and 'uid' under Linux sysfs.

Following inspection of sysfs entries for hardware TPMs we chose
uid '1'.

Cc: Shannon Zhao 
Cc: Michael S. Tsirkin 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/708
Signed-off-by: Stefan Berger 
Reviewed-by: Ani Sinha 
Reviewed-by: Shannon Zhao 
Message-id: 20211223022310.575496-3-stef...@linux.ibm.com
Message-Id: <20220104175806.872996-3-stef...@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
Reviewed-by: Igor Mammedov 
---
 hw/arm/virt-acpi-build.c | 1 +
 hw/i386/acpi-build.c | 7 +++
 2 files changed, 8 insertions(+)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index d0f4867fdf..f2514ce77c 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -229,6 +229,7 @@ static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState 
*vms)
 
 Aml *dev = aml_device("TPM0");
 aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
+aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
 aml_append(dev, aml_name_decl("_UID", aml_int(0)));
 
 Aml *crs = aml_resource_template();
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 0234fe7588..ce823e8fcb 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1812,11 +1812,15 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 dev = aml_device("TPM");
 aml_append(dev, aml_name_decl("_HID",
   aml_string("MSFT0101")));
+aml_append(dev,
+   aml_name_decl("_STR",
+ aml_string("TPM 2.0 Device")));
 } else {
 dev = aml_device("ISA.TPM");
 aml_append(dev, aml_name_decl("_HID",
   aml_eisaid("PNP0C31")));
 }
+aml_append(dev, aml_name_decl("_UID", aml_int(1)));
 
 aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
 crs = aml_resource_template();
@@ -1844,12 +1848,15 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 if (TPM_IS_CRB(tpm)) {
 dev = aml_device("TPM");
 aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
+aml_append(dev, aml_name_decl("_STR",
+  aml_string("TPM 2.0 Device")));
 crs = aml_resource_template();
 aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
 aml_append(dev, aml_name_decl("_CRS", crs));
 
 aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
+aml_append(dev, aml_name_decl("_UID", aml_int(1)));
 
 tpm_build_ppi_acpi(tpm, dev);
 
-- 
MST




[PULL v3 49/55] docs: reSTify virtio-balloon-stats documentation and move to docs/interop

2022-01-07 Thread Michael S. Tsirkin
From: Thomas Huth 

The virtio-balloon-stats documentation might be useful for people that
are implementing software that talks to QEMU via QMP, so this should
reside in the docs/interop/ directory. While we're at it, also convert
the file to restructured text and mention it in the MAINTAINERS file.

Signed-off-by: Thomas Huth 
Message-Id: <20220105115245.420945-1-th...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 MAINTAINERS   |  1 +
 docs/interop/index.rst|  1 +
 .../virtio-balloon-stats.rst} | 58 ++-
 3 files changed, 32 insertions(+), 28 deletions(-)
 rename docs/{virtio-balloon-stats.txt => interop/virtio-balloon-stats.rst} 
(66%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 6aa0335560..c98a61caee 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1932,6 +1932,7 @@ virtio-balloon
 M: Michael S. Tsirkin 
 M: David Hildenbrand 
 S: Maintained
+F: docs/interop/virtio-balloon-stats.rst
 F: hw/virtio/virtio-balloon*.c
 F: include/hw/virtio/virtio-balloon.h
 F: softmmu/balloon.c
diff --git a/docs/interop/index.rst b/docs/interop/index.rst
index c59bac9834..b7632acb7b 100644
--- a/docs/interop/index.rst
+++ b/docs/interop/index.rst
@@ -22,3 +22,4 @@ are useful for making QEMU interoperate with other software.
vhost-user
vhost-user-gpu
vhost-vdpa
+   virtio-balloon-stats
diff --git a/docs/virtio-balloon-stats.txt 
b/docs/interop/virtio-balloon-stats.rst
similarity index 66%
rename from docs/virtio-balloon-stats.txt
rename to docs/interop/virtio-balloon-stats.rst
index 1732cc8c8a..b9a6a6edb2 100644
--- a/docs/virtio-balloon-stats.txt
+++ b/docs/interop/virtio-balloon-stats.rst
@@ -1,4 +1,4 @@
-virtio balloon memory statistics
+Virtio balloon memory statistics
 
 
 The virtio balloon driver supports guest memory statistics reporting. These
@@ -9,10 +9,12 @@ Before querying the available stats, clients first have to 
enable polling.
 This is done by writing a time interval value (in seconds) to the
 guest-stats-polling-interval property. This value can be:
 
-  > 0  enables polling in the specified interval. If polling is already
+  > 0
+   enables polling in the specified interval. If polling is already
enabled, the polling time interval is changed to the new value
 
-  0disables polling. Previous polled statistics are still valid and
+  0
+   disables polling. Previous polled statistics are still valid and
can be queried.
 
 Once polling is enabled, the virtio-balloon device in QEMU will start
@@ -22,7 +24,7 @@ interval.
 To retrieve those stats, clients have to query the guest-stats property,
 which will return a dictionary containing:
 
-  o A key named 'stats', containing all available stats. If the guest
+  * A key named 'stats', containing all available stats. If the guest
 doesn't support a particular stat, or if it couldn't be retrieved,
 its value will be -1. Currently, the following stats are supported:
 
@@ -37,7 +39,7 @@ which will return a dictionary containing:
   - stat-htlb-pgalloc
   - stat-htlb-pgfail
 
-  o A key named last-update, which contains the last stats update
+  * A key named last-update, which contains the last stats update
 timestamp in seconds. Since this timestamp is generated by the host,
 a buggy guest can't influence its value. The value is 0 if the guest
 has not updated the stats (yet).
@@ -61,32 +63,32 @@ It's also important to note the following:
respond to the request the timer will never be re-armed, which has
the same effect as disabling polling
 
-Here are a few examples. QEMU is started with '-device virtio-balloon',
-which generates '/machine/peripheral-anon/device[1]' as the QOM path for
+Here are a few examples. QEMU is started with ``-device virtio-balloon``,
+which generates ``/machine/peripheral-anon/device[1]`` as the QOM path for
 the balloon device.
 
-Enable polling with 2 seconds interval:
+Enable polling with 2 seconds interval::
 
-{ "execute": "qom-set",
- "arguments": { "path": "/machine/peripheral-anon/device[1]",
-"property": "guest-stats-polling-interval", "value": 2 
} }
+  { "execute": "qom-set",
+   "arguments": { "path": "/machine/peripheral-anon/device[1]",
+   "property": "guest-stats-polling-interval", "value": 2 } }
 
-{ "return": {} }
+  { "return": {} }
 
-Change polling to 10 seconds:
+Change polling to 10 seconds::
 
-{ "execute": "qom-set",
- "arguments": { "path": "/machine/peripheral-anon/device[1]",
-"property": "guest-stats-polling-interval", "value": 
10 } }
+  { "execute": "qom-set",
+   "arguments": { "path": "/machine/peripheral-anon/device[1]",
+   "property": "guest-stats-polling-interval", "value": 10 } }
 
-{ "return": {} }
+  { "return": {} }
 
-Get stats:
+Get stats::
 
-{ 

[PULL v3 51/55] hw/scsi/vhost-scsi: don't double close vhostfd on error

2022-01-07 Thread Michael S. Tsirkin
From: Daniil Tatianin 

vhost_dev_init calls vhost_dev_cleanup on error, which closes vhostfd,
don't double close it.

Signed-off-by: Daniil Tatianin 
Message-Id: <20211129132358.1110372-2-d-tatia...@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 hw/scsi/vhost-scsi.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index efb3e14d9e..778f43e4c1 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -222,6 +222,11 @@ static void vhost_scsi_realize(DeviceState *dev, Error 
**errp)
 ret = vhost_dev_init(>dev, (void *)(uintptr_t)vhostfd,
  VHOST_BACKEND_TYPE_KERNEL, 0, errp);
 if (ret < 0) {
+/*
+ * vhost_dev_init calls vhost_dev_cleanup on error, which closes
+ * vhostfd, don't double close it.
+ */
+vhostfd = -1;
 goto free_vqs;
 }
 
@@ -242,7 +247,9 @@ static void vhost_scsi_realize(DeviceState *dev, Error 
**errp)
 error_free(vsc->migration_blocker);
 virtio_scsi_common_unrealize(dev);
  close_fd:
-close(vhostfd);
+if (vhostfd >= 0) {
+close(vhostfd);
+}
 return;
 }
 
-- 
MST




[PULL v3 43/55] acpi: fix QEMU crash when started with SLIC table

2022-01-07 Thread Michael S. Tsirkin
From: Igor Mammedov 

if QEMU is started with used provided SLIC table blob,

  -acpitable sig=SLIC,oem_id='CRASH 
',oem_table_id="ME",oem_rev=2210,asl_compiler_id="",asl_compiler_rev=,data=/dev/null
it will assert with:

  hw/acpi/aml-build.c:61:build_append_padded_str: assertion failed: (len <= 
maxlen)

and following backtrace:

  ...
  build_append_padded_str (array=0x56afe320, str=0x56afdb2e "CRASH ME", 
maxlen=0x6, pad=0x20) at hw/acpi/aml-build.c:61
  acpi_table_begin (desc=0x7fffd1b0, array=0x56afe320) at 
hw/acpi/aml-build.c:1727
  build_fadt (tbl=0x56afe320, linker=0x57ca3830, f=0x7fffd318, 
oem_id=0x56afdb2e "CRASH ME", oem_table_id=0x56afdb34 "ME") at 
hw/acpi/aml-build.c:2064
  ...

which happens due to acpi_table_begin() expecting NULL terminated
oem_id and oem_table_id strings, which is normally the case, but
in case of user provided SLIC table, oem_id points to table's blob
directly and as result oem_id became longer than expected.

Fix issue by handling oem_id consistently and make acpi_get_slic_oem()
return NULL terminated strings.

PS:
After [1] refactoring, oem_id semantics became inconsistent, where
NULL terminated string was coming from machine and old way pointer
into byte array coming from -acpitable option. That used to work
since build_header() wasn't expecting NULL terminated string and
blindly copied the 1st 6 bytes only.

However commit [2] broke that by replacing build_header() with
acpi_table_begin(), which was expecting NULL terminated string
and was checking oem_id size.

1) 602b45820 ("acpi: Permit OEM ID and OEM table ID fields to be changed")
2)
Fixes: 4b56e1e4eb08 ("acpi: build_fadt: use acpi_table_begin()/acpi_table_end() 
instead of build_header()")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/786
Signed-off-by: Igor Mammedov 
Message-Id: <20211227193120.1084176-2-imamm...@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Denis Lisov 
Tested-by: Alexander Tsoy 
Cc: qemu-sta...@nongnu.org
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 hw/acpi/core.c   | 4 ++--
 hw/i386/acpi-build.c | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 1e004d0078..3e811bf03c 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -345,8 +345,8 @@ int acpi_get_slic_oem(AcpiSlicOem *oem)
 struct acpi_table_header *hdr = (void *)(u - sizeof(hdr->_length));
 
 if (memcmp(hdr->sig, "SLIC", 4) == 0) {
-oem->id = hdr->oem_id;
-oem->table_id = hdr->oem_table_id;
+oem->id = g_strndup(hdr->oem_id, 6);
+oem->table_id = g_strndup(hdr->oem_table_id, 8);
 return 0;
 }
 }
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 8383b83ee3..0234fe7588 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2723,6 +2723,8 @@ void acpi_build(AcpiBuildTables *tables, MachineState 
*machine)
 
 /* Cleanup memory that's no longer used. */
 g_array_free(table_offsets, true);
+g_free(slic_oem.id);
+g_free(slic_oem.table_id);
 }
 
 static void acpi_ram_update(MemoryRegion *mr, GArray *data)
-- 
MST




[PULL v3 48/55] hw/i386/pc: Add missing property descriptions

2022-01-07 Thread Michael S. Tsirkin
From: Thomas Huth 

When running "qemu-system-x86_64 -M pc,help" I noticed that some
properties were still missing their description. Add them now so
that users get at least a slightly better idea what they are all
about.

Signed-off-by: Thomas Huth 
Message-Id: <20211206134255.94784-1-th...@redhat.com>
Reviewed-by: Igor Mammedov 
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 hw/i386/pc.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 718ab81ba8..c8696ac01e 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1759,15 +1759,23 @@ static void pc_machine_class_init(ObjectClass *oc, void 
*data)
 
 object_class_property_add_bool(oc, PC_MACHINE_SMBUS,
 pc_machine_get_smbus, pc_machine_set_smbus);
+object_class_property_set_description(oc, PC_MACHINE_SMBUS,
+"Enable/disable system management bus");
 
 object_class_property_add_bool(oc, PC_MACHINE_SATA,
 pc_machine_get_sata, pc_machine_set_sata);
+object_class_property_set_description(oc, PC_MACHINE_SATA,
+"Enable/disable Serial ATA bus");
 
 object_class_property_add_bool(oc, PC_MACHINE_PIT,
 pc_machine_get_pit, pc_machine_set_pit);
+object_class_property_set_description(oc, PC_MACHINE_PIT,
+"Enable/disable Intel 8254 programmable interval timer emulation");
 
 object_class_property_add_bool(oc, "hpet",
 pc_machine_get_hpet, pc_machine_set_hpet);
+object_class_property_set_description(oc, "hpet",
+"Enable/disable high precision event timer emulation");
 
 object_class_property_add_bool(oc, "default-bus-bypass-iommu",
 pc_machine_get_default_bus_bypass_iommu,
-- 
MST




[PULL v3 39/55] linux-headers: sync VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE

2022-01-07 Thread Michael S. Tsirkin
From: David Hildenbrand 

Let's synchronize the new feature flag, available in Linux since
v5.16-rc1.

Reviewed-by: Michal Privoznik 
Signed-off-by: David Hildenbrand 
Message-Id: <20211217134039.29670-2-da...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 include/standard-headers/linux/virtio_mem.h | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/include/standard-headers/linux/virtio_mem.h 
b/include/standard-headers/linux/virtio_mem.h
index 05e5ade75d..18c74c527c 100644
--- a/include/standard-headers/linux/virtio_mem.h
+++ b/include/standard-headers/linux/virtio_mem.h
@@ -68,9 +68,10 @@
  * explicitly triggered (VIRTIO_MEM_REQ_UNPLUG).
  *
  * There are no guarantees what will happen if unplugged memory is
- * read/written. Such memory should, in general, not be touched. E.g.,
- * even writing might succeed, but the values will simply be discarded at
- * random points in time.
+ * read/written. In general, unplugged memory should not be touched, because
+ * the resulting action is undefined. There is one exception: without
+ * VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, unplugged memory inside the usable
+ * region can be read, to simplify creation of memory dumps.
  *
  * It can happen that the device cannot process a request, because it is
  * busy. The device driver has to retry later.
@@ -87,6 +88,8 @@
 
 /* node_id is an ACPI PXM and is valid */
 #define VIRTIO_MEM_F_ACPI_PXM  0
+/* unplugged memory must not be accessed */
+#define VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE1
 
 
 /* --- virtio-mem: guest -> host requests --- */
-- 
MST




Re: [PATCH v3 2/6] target/riscv: hardwire mstatus.FS to zero when enable zfinx

2022-01-07 Thread Weiwei Li



在 2022/1/8 上午4:48, Richard Henderson 写道:

On 1/7/22 3:27 AM, Weiwei Li wrote:

@@ -342,6 +342,11 @@ static void mark_fs_dirty(DisasContext *ctx)
  {
  TCGv tmp;
  +    /* hardwire mstatus.FS to zero when enable zfinx */
+    if (ctx->ext_zfinx) {
+    return;
+    }
+
  if (ctx->mstatus_fs != MSTATUS_FS) {


This should also test RVF.

Finally, there needs to be a change to write_misa -- MSTATUS_FS needs 
to be cleared when RVF is disabled.




OK. I'll update this.

r~





[PULL v3 53/55] tests: acpi: prepare for updated TPM related tables

2022-01-07 Thread Michael S. Tsirkin
From: Stefan Berger 

Replace existing TPM related tables, that are about to change, with
empty files.

Cc: Michael S. Tsirkin 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Signed-off-by: Stefan Berger 
Acked-by: Ani Sinha 
Message-id: 20211223022310.575496-2-stef...@linux.ibm.com
Message-Id: <20220104175806.872996-2-stef...@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
Acked-by: Igor Mammedov 
---
 tests/qtest/bios-tables-test-allowed-diff.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..5d80e408d4 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,3 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/q35/DSDT.tis.tpm12",
+"tests/data/acpi/q35/DSDT.tis.tpm2",
-- 
MST




[PULL v3 31/55] util/oslib-posix: Introduce and use MemsetContext for touch_all_pages()

2022-01-07 Thread Michael S. Tsirkin
From: David Hildenbrand 

Let's minimize the number of global variables to prepare for
os_mem_prealloc() getting called concurrently and make the code a bit
easier to read.

The only consumer that really needs a global variable is the sigbus
handler, which will require protection via a mutex in the future either way
as we cannot concurrently mess with the SIGBUS handler.

Reviewed-by: Daniel P. Berrangé 
Reviewed-by: Michal Privoznik 
Signed-off-by: David Hildenbrand 
Message-Id: <20211217134611.31172-4-da...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 util/oslib-posix.c | 73 +-
 1 file changed, 47 insertions(+), 26 deletions(-)

diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index cb89e07770..cf2ead54ad 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -73,21 +73,30 @@
 
 #define MAX_MEM_PREALLOC_THREAD_COUNT 16
 
+struct MemsetThread;
+
+typedef struct MemsetContext {
+bool all_threads_created;
+bool any_thread_failed;
+struct MemsetThread *threads;
+int num_threads;
+} MemsetContext;
+
 struct MemsetThread {
 char *addr;
 size_t numpages;
 size_t hpagesize;
 QemuThread pgthread;
 sigjmp_buf env;
+MemsetContext *context;
 };
 typedef struct MemsetThread MemsetThread;
 
-static MemsetThread *memset_thread;
-static int memset_num_threads;
+/* used by sigbus_handler() */
+static MemsetContext *sigbus_memset_context;
 
 static QemuMutex page_mutex;
 static QemuCond page_cond;
-static bool threads_created_flag;
 
 int qemu_get_thread_id(void)
 {
@@ -438,10 +447,13 @@ const char *qemu_get_exec_dir(void)
 static void sigbus_handler(int signal)
 {
 int i;
-if (memset_thread) {
-for (i = 0; i < memset_num_threads; i++) {
-if (qemu_thread_is_self(_thread[i].pgthread)) {
-siglongjmp(memset_thread[i].env, 1);
+
+if (sigbus_memset_context) {
+for (i = 0; i < sigbus_memset_context->num_threads; i++) {
+MemsetThread *thread = _memset_context->threads[i];
+
+if (qemu_thread_is_self(>pgthread)) {
+siglongjmp(thread->env, 1);
 }
 }
 }
@@ -459,7 +471,7 @@ static void *do_touch_pages(void *arg)
  * clearing until all threads have been created.
  */
 qemu_mutex_lock(_mutex);
-while(!threads_created_flag){
+while (!memset_args->context->all_threads_created) {
 qemu_cond_wait(_cond, _mutex);
 }
 qemu_mutex_unlock(_mutex);
@@ -502,7 +514,7 @@ static void *do_madv_populate_write_pages(void *arg)
 
 /* See do_touch_pages(). */
 qemu_mutex_lock(_mutex);
-while (!threads_created_flag) {
+while (!memset_args->context->all_threads_created) {
 qemu_cond_wait(_cond, _mutex);
 }
 qemu_mutex_unlock(_mutex);
@@ -529,6 +541,9 @@ static int touch_all_pages(char *area, size_t hpagesize, 
size_t numpages,
int smp_cpus, bool use_madv_populate_write)
 {
 static gsize initialized = 0;
+MemsetContext context = {
+.num_threads = get_memset_num_threads(smp_cpus),
+};
 size_t numpages_per_thread, leftover;
 void *(*touch_fn)(void *);
 int ret = 0, i = 0;
@@ -546,35 +561,41 @@ static int touch_all_pages(char *area, size_t hpagesize, 
size_t numpages,
 touch_fn = do_touch_pages;
 }
 
-threads_created_flag = false;
-memset_num_threads = get_memset_num_threads(smp_cpus);
-memset_thread = g_new0(MemsetThread, memset_num_threads);
-numpages_per_thread = numpages / memset_num_threads;
-leftover = numpages % memset_num_threads;
-for (i = 0; i < memset_num_threads; i++) {
-memset_thread[i].addr = addr;
-memset_thread[i].numpages = numpages_per_thread + (i < leftover);
-memset_thread[i].hpagesize = hpagesize;
-qemu_thread_create(_thread[i].pgthread, "touch_pages",
-   touch_fn, _thread[i],
+context.threads = g_new0(MemsetThread, context.num_threads);
+numpages_per_thread = numpages / context.num_threads;
+leftover = numpages % context.num_threads;
+for (i = 0; i < context.num_threads; i++) {
+context.threads[i].addr = addr;
+context.threads[i].numpages = numpages_per_thread + (i < leftover);
+context.threads[i].hpagesize = hpagesize;
+context.threads[i].context = 
+qemu_thread_create([i].pgthread, "touch_pages",
+   touch_fn, [i],
QEMU_THREAD_JOINABLE);
-addr += memset_thread[i].numpages * hpagesize;
+addr += context.threads[i].numpages * hpagesize;
+}
+
+if (!use_madv_populate_write) {
+sigbus_memset_context = 
 }
 
 qemu_mutex_lock(_mutex);
-threads_created_flag = true;
+context.all_threads_created = true;
 qemu_cond_broadcast(_cond);
 qemu_mutex_unlock(_mutex);
 
-for (i = 0; i < memset_num_threads; i++) {
-int 

[PULL v3 38/55] MAINTAINERS: Add a separate entry for acpi/VIOT tables

2022-01-07 Thread Michael S. Tsirkin
From: Ani Sinha 

All work related to VIOT tables are being done by Jean. Adding him as the
maintainer for acpi VIOT table code in qemu.

Signed-off-by: Ani Sinha 
Message-Id: <20211213045924.344214-1-...@anisinha.ca>
Acked-by: Jean-Philippe Brucker 
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index f871d759fd..6aa0335560 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1777,6 +1777,13 @@ F: docs/specs/acpi_mem_hotplug.rst
 F: docs/specs/acpi_pci_hotplug.rst
 F: docs/specs/acpi_hw_reduced_hotplug.rst
 
+ACPI/VIOT
+M: Jean-Philippe Brucker 
+R: Ani Sinha 
+S: Supported
+F: hw/acpi/viot.c
+F: hw/acpi/viot.h
+
 ACPI/HEST/GHES
 R: Dongjiu Geng 
 L: qemu-...@nongnu.org
-- 
MST




[PULL v3 50/55] hw/scsi/vhost-scsi: don't leak vqs on error

2022-01-07 Thread Michael S. Tsirkin
From: Daniil Tatianin 

vhost_dev_init calls vhost_dev_cleanup in case of an error during
initialization, which zeroes out the entire vsc->dev as well as the
vsc->dev.vqs pointer. This prevents us from properly freeing it in free_vqs.
Keep a local copy of the pointer so we can free it later.

Signed-off-by: Daniil Tatianin 
Message-Id: <20211129132358.1110372-1-d-tatia...@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 hw/scsi/vhost-scsi.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 039caf2614..efb3e14d9e 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -170,6 +170,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error 
**errp)
 Error *err = NULL;
 int vhostfd = -1;
 int ret;
+struct vhost_virtqueue *vqs = NULL;
 
 if (!vs->conf.wwpn) {
 error_setg(errp, "vhost-scsi: missing wwpn");
@@ -213,7 +214,8 @@ static void vhost_scsi_realize(DeviceState *dev, Error 
**errp)
 }
 
 vsc->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
-vsc->dev.vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs);
+vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs);
+vsc->dev.vqs = vqs;
 vsc->dev.vq_index = 0;
 vsc->dev.backend_features = 0;
 
@@ -232,7 +234,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error 
**errp)
 return;
 
  free_vqs:
-g_free(vsc->dev.vqs);
+g_free(vqs);
 if (!vsc->migratable) {
 migrate_del_blocker(vsc->migration_blocker);
 }
-- 
MST




[PULL v3 52/55] virtio/vhost-vsock: don't double close vhostfd, remove redundant cleanup

2022-01-07 Thread Michael S. Tsirkin
From: Daniil Tatianin 

In case of an error during initialization in vhost_dev_init, vhostfd is
closed in vhost_dev_cleanup. Remove close from err_virtio as it's both
redundant and causes a double close on vhostfd.

Signed-off-by: Daniil Tatianin 
Message-Id: <20211129125204.1108088-1-d-tatia...@yandex-team.ru>
Reviewed-by: Stefano Garzarella 
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 hw/virtio/vhost-vsock.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c
index 478c0c9a87..433d42d897 100644
--- a/hw/virtio/vhost-vsock.c
+++ b/hw/virtio/vhost-vsock.c
@@ -171,6 +171,10 @@ static void vhost_vsock_device_realize(DeviceState *dev, 
Error **errp)
 ret = vhost_dev_init(>vhost_dev, (void *)(uintptr_t)vhostfd,
  VHOST_BACKEND_TYPE_KERNEL, 0, errp);
 if (ret < 0) {
+/*
+ * vhostfd is closed by vhost_dev_cleanup, which is called
+ * by vhost_dev_init on initialization error.
+ */
 goto err_virtio;
 }
 
@@ -183,15 +187,10 @@ static void vhost_vsock_device_realize(DeviceState *dev, 
Error **errp)
 return;
 
 err_vhost_dev:
-vhost_dev_cleanup(>vhost_dev);
 /* vhost_dev_cleanup() closes the vhostfd passed to vhost_dev_init() */
-vhostfd = -1;
+vhost_dev_cleanup(>vhost_dev);
 err_virtio:
 vhost_vsock_common_unrealize(vdev);
-if (vhostfd >= 0) {
-close(vhostfd);
-}
-return;
 }
 
 static void vhost_vsock_device_unrealize(DeviceState *dev)
-- 
MST




[PULL v3 37/55] virtio: signal after wrapping packed used_idx

2022-01-07 Thread Michael S. Tsirkin
From: Stefan Hajnoczi 

Packed Virtqueues wrap used_idx instead of letting it run freely like
Split Virtqueues do. If the used ring wraps more than once there is no
way to compare vq->signalled_used and vq->used_idx in
virtio_packed_should_notify() since they are modulo vq->vring.num.

This causes the device to stop sending used buffer notifications when
when virtio_packed_should_notify() is called less than once each time
around the used ring.

It is possible to trigger this with virtio-blk's dataplane
notify_guest_bh() irq coalescing optimization. The call to
virtio_notify_irqfd() (and virtio_packed_should_notify()) is deferred to
a BH. If the guest driver is polling it can complete and submit more
requests before the BH executes, causing the used ring to wrap more than
once. The result is that the virtio-blk device ceases to raise
interrupts and I/O hangs.

Cc: Tiwei Bie 
Cc: Jason Wang 
Cc: Michael S. Tsirkin 
Signed-off-by: Stefan Hajnoczi 
Message-Id: <20211130134510.267382-1-stefa...@redhat.com>
Fixes: 86044b24e865fb9596ed77a4d0f3af8b90a088a1 ("virtio: basic packed 
virtqueue support")
Acked-by: Jason Wang 
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 hw/virtio/virtio.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 36edb1dad5..971e59a663 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -885,6 +885,7 @@ static void virtqueue_packed_flush(VirtQueue *vq, unsigned 
int count)
 if (vq->used_idx >= vq->vring.num) {
 vq->used_idx -= vq->vring.num;
 vq->used_wrap_counter ^= 1;
+vq->signalled_used_valid = false;
 }
 }
 
-- 
MST




[PULL v3 47/55] acpihp: simplify acpi_pcihp_disable_root_bus

2022-01-07 Thread Michael S. Tsirkin
From: Ani Sinha 

Get rid of the static variable that keeps track of whether hotplug has been
disabled on the root pci bus. Simply use qbus_is_hotpluggable() api to
perform the same check. This eliminates additional if conditional and
simplifies the function.

Signed-off-by: Ani Sinha 
Message-Id: <1640764674-7784-1-git-send-email-...@anirban.org>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 hw/acpi/pcihp.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index a5e182dd3a..6befd23e16 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -128,20 +128,15 @@ static void acpi_set_pci_info(void)
 
 static void acpi_pcihp_disable_root_bus(void)
 {
-static bool root_hp_disabled;
 Object *host = acpi_get_i386_pci_host();
 PCIBus *bus;
 
-if (root_hp_disabled) {
-return;
-}
-
 bus = PCI_HOST_BRIDGE(host)->bus;
-if (bus) {
+if (bus && qbus_is_hotpluggable(BUS(bus))) {
 /* setting the hotplug handler to NULL makes the bus non-hotpluggable 
*/
 qbus_set_hotplug_handler(BUS(bus), NULL);
 }
-root_hp_disabled = true;
+
 return;
 }
 
-- 
MST




[PULL v3 32/55] util/oslib-posix: Don't create too many threads with small memory or little pages

2022-01-07 Thread Michael S. Tsirkin
From: David Hildenbrand 

Let's limit the number of threads to something sane, especially that
- We don't have more threads than the number of pages we have
- We don't have threads that initialize small (< 64 MiB) memory

Reviewed-by: Pankaj Gupta 
Reviewed-by: Dr. David Alan Gilbert 
Reviewed-by: Daniel P. Berrangé 
Reviewed-by: Michal Privoznik 
Signed-off-by: David Hildenbrand 
Message-Id: <20211217134611.31172-5-da...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 util/oslib-posix.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index cf2ead54ad..67c08a425e 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -40,6 +40,7 @@
 #include 
 #include "qemu/cutils.h"
 #include "qemu/compiler.h"
+#include "qemu/units.h"
 
 #ifdef CONFIG_LINUX
 #include 
@@ -525,7 +526,8 @@ static void *do_madv_populate_write_pages(void *arg)
 return (void *)(uintptr_t)ret;
 }
 
-static inline int get_memset_num_threads(int smp_cpus)
+static inline int get_memset_num_threads(size_t hpagesize, size_t numpages,
+ int smp_cpus)
 {
 long host_procs = sysconf(_SC_NPROCESSORS_ONLN);
 int ret = 1;
@@ -533,6 +535,12 @@ static inline int get_memset_num_threads(int smp_cpus)
 if (host_procs > 0) {
 ret = MIN(MIN(host_procs, MAX_MEM_PREALLOC_THREAD_COUNT), smp_cpus);
 }
+
+/* Especially with gigantic pages, don't create more threads than pages. */
+ret = MIN(ret, numpages);
+/* Don't start threads to prealloc comparatively little memory. */
+ret = MIN(ret, MAX(1, hpagesize * numpages / (64 * MiB)));
+
 /* In case sysconf() fails, we fall back to single threaded */
 return ret;
 }
@@ -542,7 +550,7 @@ static int touch_all_pages(char *area, size_t hpagesize, 
size_t numpages,
 {
 static gsize initialized = 0;
 MemsetContext context = {
-.num_threads = get_memset_num_threads(smp_cpus),
+.num_threads = get_memset_num_threads(hpagesize, numpages, smp_cpus),
 };
 size_t numpages_per_thread, leftover;
 void *(*touch_fn)(void *);
-- 
MST




[PULL v3 46/55] tests: acpi: SLIC: update expected blobs

2022-01-07 Thread Michael S. Tsirkin
From: Igor Mammedov 

Signed-off-by: Igor Mammedov 
Message-Id: <20211227193120.1084176-5-imamm...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 tests/qtest/bios-tables-test-allowed-diff.h |   2 --
 tests/data/acpi/q35/FACP.slic   | Bin 244 -> 244 bytes
 tests/data/acpi/q35/SLIC.slic   | Bin 0 -> 36 bytes
 3 files changed, 2 deletions(-)

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index 49dbf8fa3e..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,3 +1 @@
 /* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/q35/FACP.slic",
-"tests/data/acpi/q35/SLIC.slic",
diff --git a/tests/data/acpi/q35/FACP.slic b/tests/data/acpi/q35/FACP.slic
index 
f6a864cc863c7763f6c09d3814ad184a658fa0a0..891fd4b784b7b6b3ea303976db7ecd5b669bc84b
 100644
GIT binary patch
delta 28
jcmeyu_=Qo#+fKvygL;W3Y#Uud9N>M3Dyoc<=}c

delta 28
jcmeyu_=Qo#+fK^G+v!XOCb7r-%UOi6RdGgN+Fa

diff --git a/tests/data/acpi/q35/SLIC.slic b/tests/data/acpi/q35/SLIC.slic
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fd26592e2480c5d02a018e0d855a04106661a7b5
 100644
GIT binary patch
literal 36
mcmWIc@pM*UU|?YMbPjS1_E7M31#*C(gN1>iFg3Rn#0CI%)&>Cp

literal 0
HcmV?d1

-- 
MST




[PULL v3 29/55] util/oslib-posix: Let touch_all_pages() return an error

2022-01-07 Thread Michael S. Tsirkin
From: David Hildenbrand 

Let's prepare touch_all_pages() for returning differing errors. Return
an error from the thread and report the last processed error.

Translate SIGBUS to -EFAULT, as a SIGBUS can mean all different kind of
things (memory error, read error, out of memory). When allocating memory
fails via the current SIGBUS-based mechanism, we'll get:
os_mem_prealloc: preallocating memory failed: Bad address

Reviewed-by: Daniel P. Berrangé 
Reviewed-by: Michal Privoznik 
Signed-off-by: David Hildenbrand 
Message-Id: <20211217134611.31172-2-da...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 util/oslib-posix.c | 28 
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index e8bdb02e1d..b146beef78 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -84,7 +84,6 @@ typedef struct MemsetThread MemsetThread;
 
 static MemsetThread *memset_thread;
 static int memset_num_threads;
-static bool memset_thread_failed;
 
 static QemuMutex page_mutex;
 static QemuCond page_cond;
@@ -452,6 +451,7 @@ static void *do_touch_pages(void *arg)
 {
 MemsetThread *memset_args = (MemsetThread *)arg;
 sigset_t set, oldset;
+int ret = 0;
 
 /*
  * On Linux, the page faults from the loop below can cause mmap_sem
@@ -470,7 +470,7 @@ static void *do_touch_pages(void *arg)
 pthread_sigmask(SIG_UNBLOCK, , );
 
 if (sigsetjmp(memset_args->env, 1)) {
-memset_thread_failed = true;
+ret = -EFAULT;
 } else {
 char *addr = memset_args->addr;
 size_t numpages = memset_args->numpages;
@@ -494,7 +494,7 @@ static void *do_touch_pages(void *arg)
 }
 }
 pthread_sigmask(SIG_SETMASK, , NULL);
-return NULL;
+return (void *)(uintptr_t)ret;
 }
 
 static inline int get_memset_num_threads(int smp_cpus)
@@ -509,13 +509,13 @@ static inline int get_memset_num_threads(int smp_cpus)
 return ret;
 }
 
-static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages,
-int smp_cpus)
+static int touch_all_pages(char *area, size_t hpagesize, size_t numpages,
+   int smp_cpus)
 {
 static gsize initialized = 0;
 size_t numpages_per_thread, leftover;
+int ret = 0, i = 0;
 char *addr = area;
-int i = 0;
 
 if (g_once_init_enter()) {
 qemu_mutex_init(_mutex);
@@ -523,7 +523,6 @@ static bool touch_all_pages(char *area, size_t hpagesize, 
size_t numpages,
 g_once_init_leave(, 1);
 }
 
-memset_thread_failed = false;
 threads_created_flag = false;
 memset_num_threads = get_memset_num_threads(smp_cpus);
 memset_thread = g_new0(MemsetThread, memset_num_threads);
@@ -545,12 +544,16 @@ static bool touch_all_pages(char *area, size_t hpagesize, 
size_t numpages,
 qemu_mutex_unlock(_mutex);
 
 for (i = 0; i < memset_num_threads; i++) {
-qemu_thread_join(_thread[i].pgthread);
+int tmp = (uintptr_t)qemu_thread_join(_thread[i].pgthread);
+
+if (tmp) {
+ret = tmp;
+}
 }
 g_free(memset_thread);
 memset_thread = NULL;
 
-return memset_thread_failed;
+return ret;
 }
 
 void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus,
@@ -573,9 +576,10 @@ void os_mem_prealloc(int fd, char *area, size_t memory, 
int smp_cpus,
 }
 
 /* touch pages simultaneously */
-if (touch_all_pages(area, hpagesize, numpages, smp_cpus)) {
-error_setg(errp, "os_mem_prealloc: Insufficient free host memory "
-"pages available to allocate guest RAM");
+ret = touch_all_pages(area, hpagesize, numpages, smp_cpus);
+if (ret) {
+error_setg_errno(errp, -ret,
+ "os_mem_prealloc: preallocating memory failed");
 }
 
 ret = sigaction(SIGBUS, , NULL);
-- 
MST




[PULL v3 42/55] intel-iommu: correctly check passthrough during translation

2022-01-07 Thread Michael S. Tsirkin
From: Jason Wang 

When scalable mode is enabled, the passthrough more is not determined
by the context entry but PASID entry, so switch to use the logic of
vtd_dev_pt_enabled() to determine the passthrough mode in
vtd_do_iommu_translate().

Signed-off-by: Jason Wang 
Message-Id: <20220105041945.13459-2-jasow...@redhat.com>
Reviewed-by: Peter Xu 
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 hw/i386/intel_iommu.c | 38 +++---
 1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 5b865ac08c..4c6c016388 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -1516,11 +1516,29 @@ static int vtd_sync_shadow_page_table(VTDAddressSpace 
*vtd_as)
  * 1st-level translation or 2nd-level translation, it depends
  * on PGTT setting.
  */
-static bool vtd_dev_pt_enabled(VTDAddressSpace *as)
+static bool vtd_dev_pt_enabled(IntelIOMMUState *s, VTDContextEntry *ce)
+{
+VTDPASIDEntry pe;
+int ret;
+
+if (s->root_scalable) {
+ret = vtd_ce_get_rid2pasid_entry(s, ce, );
+if (ret) {
+error_report_once("%s: vtd_ce_get_rid2pasid_entry error: %"PRId32,
+  __func__, ret);
+return false;
+}
+return (VTD_PE_GET_TYPE() == VTD_SM_PASID_ENTRY_PT);
+}
+
+return (vtd_ce_get_type(ce) == VTD_CONTEXT_TT_PASS_THROUGH);
+
+}
+
+static bool vtd_as_pt_enabled(VTDAddressSpace *as)
 {
 IntelIOMMUState *s;
 VTDContextEntry ce;
-VTDPASIDEntry pe;
 int ret;
 
 assert(as);
@@ -1538,17 +1556,7 @@ static bool vtd_dev_pt_enabled(VTDAddressSpace *as)
 return false;
 }
 
-if (s->root_scalable) {
-ret = vtd_ce_get_rid2pasid_entry(s, , );
-if (ret) {
-error_report_once("%s: vtd_ce_get_rid2pasid_entry error: %"PRId32,
-  __func__, ret);
-return false;
-}
-return (VTD_PE_GET_TYPE() == VTD_SM_PASID_ENTRY_PT);
-}
-
-return (vtd_ce_get_type() == VTD_CONTEXT_TT_PASS_THROUGH);
+return vtd_dev_pt_enabled(s, );
 }
 
 /* Return whether the device is using IOMMU translation. */
@@ -1560,7 +1568,7 @@ static bool vtd_switch_address_space(VTDAddressSpace *as)
 
 assert(as);
 
-use_iommu = as->iommu_state->dmar_enabled && !vtd_dev_pt_enabled(as);
+use_iommu = as->iommu_state->dmar_enabled && !vtd_as_pt_enabled(as);
 
 trace_vtd_switch_address_space(pci_bus_num(as->bus),
VTD_PCI_SLOT(as->devfn),
@@ -1753,7 +1761,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace 
*vtd_as, PCIBus *bus,
  * We don't need to translate for pass-through context entries.
  * Also, let's ignore IOTLB caching as well for PT devices.
  */
-if (vtd_ce_get_type() == VTD_CONTEXT_TT_PASS_THROUGH) {
+if (vtd_dev_pt_enabled(s, )) {
 entry->iova = addr & VTD_PAGE_MASK_4K;
 entry->translated_addr = entry->iova;
 entry->addr_mask = ~VTD_PAGE_MASK_4K;
-- 
MST




[PULL v3 45/55] tests: acpi: add SLIC table test

2022-01-07 Thread Michael S. Tsirkin
From: Igor Mammedov 

When user uses '-acpitable' to add SLIC table, some ACPI
tables (FADT) will change its 'Oem ID'/'Oem Table ID' fields to
match that of SLIC. Test makes sure thati QEMU handles
those fields correctly when SLIC table is added with
'-acpitable' option.

Signed-off-by: Igor Mammedov 
Message-Id: <20211227193120.1084176-4-imamm...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 tests/qtest/bios-tables-test.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 9a468e29eb..e6b72d9026 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1502,6 +1502,20 @@ static void test_acpi_virt_viot(void)
 free_test_data();
 }
 
+static void test_acpi_q35_slic(void)
+{
+test_data data = {
+.machine = MACHINE_Q35,
+.variant = ".slic",
+};
+
+test_acpi_one("-acpitable sig=SLIC,oem_id='CRASH ',oem_table_id='ME',"
+  "oem_rev=2210,asl_compiler_id='qemu',"
+  "asl_compiler_rev=,data=/dev/null",
+  );
+free_test_data();
+}
+
 static void test_oem_fields(test_data *data)
 {
 int i;
@@ -1677,6 +1691,7 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/kvm/dmar", test_acpi_q35_kvm_dmar);
 }
 qtest_add_func("acpi/q35/viot", test_acpi_q35_viot);
+qtest_add_func("acpi/q35/slic", test_acpi_q35_slic);
 } else if (strcmp(arch, "aarch64") == 0) {
 if (has_tcg) {
 qtest_add_func("acpi/virt", test_acpi_virt_tcg);
-- 
MST




[PULL v3 30/55] util/oslib-posix: Support MADV_POPULATE_WRITE for os_mem_prealloc()

2022-01-07 Thread Michael S. Tsirkin
From: David Hildenbrand 

Let's sense support and use it for preallocation. MADV_POPULATE_WRITE
does not require a SIGBUS handler, doesn't actually touch page content,
and avoids context switches; it is, therefore, faster and easier to handle
than our current approach.

While MADV_POPULATE_WRITE is, in general, faster than manual
prefaulting, and especially faster with 4k pages, there is still value in
prefaulting using multiple threads to speed up preallocation.

More details on MADV_POPULATE_WRITE can be found in the Linux commits
4ca9b3859dac ("mm/madvise: introduce MADV_POPULATE_(READ|WRITE) to prefault
page tables") and eb2faa513c24 ("mm/madvise: report SIGBUS as -EFAULT for
MADV_POPULATE_(READ|WRITE)"), and in the man page proposal [1].

This resolves the TODO in do_touch_pages().

In the future, we might want to look into using fallocate(), eventually
combined with MADV_POPULATE_READ, when dealing with shared file/fd
mappings and not caring about memory bindings.

[1] https://lkml.kernel.org/r/20210816081922.5155-1-da...@redhat.com

Reviewed-by: Pankaj Gupta 
Reviewed-by: Daniel P. Berrangé 
Reviewed-by: Michal Privoznik 
Signed-off-by: David Hildenbrand 
Message-Id: <20211217134611.31172-3-da...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 include/qemu/osdep.h |  7 
 util/oslib-posix.c   | 81 +---
 2 files changed, 68 insertions(+), 20 deletions(-)

diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 60718fc342..d1660d67fa 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -471,6 +471,11 @@ static inline void qemu_cleanup_generic_vfree(void *p)
 #else
 #define QEMU_MADV_REMOVE QEMU_MADV_DONTNEED
 #endif
+#ifdef MADV_POPULATE_WRITE
+#define QEMU_MADV_POPULATE_WRITE MADV_POPULATE_WRITE
+#else
+#define QEMU_MADV_POPULATE_WRITE QEMU_MADV_INVALID
+#endif
 
 #elif defined(CONFIG_POSIX_MADVISE)
 
@@ -484,6 +489,7 @@ static inline void qemu_cleanup_generic_vfree(void *p)
 #define QEMU_MADV_HUGEPAGE  QEMU_MADV_INVALID
 #define QEMU_MADV_NOHUGEPAGE  QEMU_MADV_INVALID
 #define QEMU_MADV_REMOVE QEMU_MADV_DONTNEED
+#define QEMU_MADV_POPULATE_WRITE QEMU_MADV_INVALID
 
 #else /* no-op */
 
@@ -497,6 +503,7 @@ static inline void qemu_cleanup_generic_vfree(void *p)
 #define QEMU_MADV_HUGEPAGE  QEMU_MADV_INVALID
 #define QEMU_MADV_NOHUGEPAGE  QEMU_MADV_INVALID
 #define QEMU_MADV_REMOVE QEMU_MADV_INVALID
+#define QEMU_MADV_POPULATE_WRITE QEMU_MADV_INVALID
 
 #endif
 
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index b146beef78..cb89e07770 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -484,10 +484,6 @@ static void *do_touch_pages(void *arg)
  *
  * 'volatile' to stop compiler optimizing this away
  * to a no-op
- *
- * TODO: get a better solution from kernel so we
- * don't need to write at all so we don't cause
- * wear on the storage backing the region...
  */
 *(volatile char *)addr = *addr;
 addr += hpagesize;
@@ -497,6 +493,26 @@ static void *do_touch_pages(void *arg)
 return (void *)(uintptr_t)ret;
 }
 
+static void *do_madv_populate_write_pages(void *arg)
+{
+MemsetThread *memset_args = (MemsetThread *)arg;
+const size_t size = memset_args->numpages * memset_args->hpagesize;
+char * const addr = memset_args->addr;
+int ret = 0;
+
+/* See do_touch_pages(). */
+qemu_mutex_lock(_mutex);
+while (!threads_created_flag) {
+qemu_cond_wait(_cond, _mutex);
+}
+qemu_mutex_unlock(_mutex);
+
+if (size && qemu_madvise(addr, size, QEMU_MADV_POPULATE_WRITE)) {
+ret = -errno;
+}
+return (void *)(uintptr_t)ret;
+}
+
 static inline int get_memset_num_threads(int smp_cpus)
 {
 long host_procs = sysconf(_SC_NPROCESSORS_ONLN);
@@ -510,10 +526,11 @@ static inline int get_memset_num_threads(int smp_cpus)
 }
 
 static int touch_all_pages(char *area, size_t hpagesize, size_t numpages,
-   int smp_cpus)
+   int smp_cpus, bool use_madv_populate_write)
 {
 static gsize initialized = 0;
 size_t numpages_per_thread, leftover;
+void *(*touch_fn)(void *);
 int ret = 0, i = 0;
 char *addr = area;
 
@@ -523,6 +540,12 @@ static int touch_all_pages(char *area, size_t hpagesize, 
size_t numpages,
 g_once_init_leave(, 1);
 }
 
+if (use_madv_populate_write) {
+touch_fn = do_madv_populate_write_pages;
+} else {
+touch_fn = do_touch_pages;
+}
+
 threads_created_flag = false;
 memset_num_threads = get_memset_num_threads(smp_cpus);
 memset_thread = g_new0(MemsetThread, memset_num_threads);
@@ -533,7 +556,7 @@ static int touch_all_pages(char *area, size_t hpagesize, 
size_t numpages,
 memset_thread[i].numpages = numpages_per_thread + (i < leftover);
 memset_thread[i].hpagesize = hpagesize;
 

[PULL v3 28/55] hw/vhost-user-blk: turn on VIRTIO_BLK_F_SIZE_MAX feature for virtio blk device

2022-01-07 Thread Michael S. Tsirkin
From: Andy Pei 

Turn on pre-defined feature VIRTIO_BLK_F_SIZE_MAX for virtio blk device to
avoid guest DMA request sizes which are too large for hardware spec.

Signed-off-by: Andy Pei 
Message-Id: <1641202092-149677-1-git-send-email-andy@intel.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
Acked-by: Raphael Norwitz 
---
 hw/block/vhost-user-blk.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index ab11ce8252..1a42ae9187 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -252,6 +252,7 @@ static uint64_t vhost_user_blk_get_features(VirtIODevice 
*vdev,
 VHostUserBlk *s = VHOST_USER_BLK(vdev);
 
 /* Turn on pre-defined features */
+virtio_add_feature(, VIRTIO_BLK_F_SIZE_MAX);
 virtio_add_feature(, VIRTIO_BLK_F_SEG_MAX);
 virtio_add_feature(, VIRTIO_BLK_F_GEOMETRY);
 virtio_add_feature(, VIRTIO_BLK_F_TOPOLOGY);
-- 
MST




[PULL v3 40/55] virtio-mem: Support VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE

2022-01-07 Thread Michael S. Tsirkin
From: David Hildenbrand 

With VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, we signal the VM that reading
unplugged memory is not supported. We have to fail feature negotiation
in case the guest does not support VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE.

First, VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE is required to properly handle
memory backends (or architectures) without support for the shared zeropage
in the hypervisor cleanly. Without the shared zeropage, even reading an
unpopulated virtual memory location can populate real memory and
consequently consume memory in the hypervisor. We have a guaranteed shared
zeropage only on MAP_PRIVATE anonymous memory.

Second, we want VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE to be the default
long-term as even populating the shared zeropage can be problematic: for
example, without THP support (possible) or without support for the shared
huge zeropage with THP (unlikely), the PTE page tables to hold the shared
zeropage entries can consume quite some memory that cannot be reclaimed
easily.

Third, there are other optimizations+features (e.g., protection of
unplugged memory, reducing the total memory slot size and bitmap sizes)
that will require VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE.

We really only support x86 targets with virtio-mem for now (and
Linux similarly only support x86), but that might change soon, so prepare
for different targets already.

Add a new "unplugged-inaccessible" tristate property for x86 targets:
- "off" will keep VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE unset and legacy
  guests working.
- "on" will set VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE and stop legacy guests
  from using the device.
- "auto" selects the default based on support for the shared zeropage.

Warn in case the property is set to "off" and we don't have support for the
shared zeropage.

For existing compat machines, the property will default to "off", to
not change the behavior but eventually warn about a problematic setup.
Short-term, we'll set the property default to "auto" for new QEMU machines.
Mid-term, we'll set the property default to "on" for new QEMU machines.
Long-term, we'll deprecate the parameter and disallow legacy
guests completely.

The property has to match on the migration source and destination. "auto"
will result in the same VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE setting as long
as the qemu command line (esp. memdev) match -- so "auto" is good enough
for migration purposes and the parameter doesn't have to be migrated
explicitly.

Reviewed-by: Michal Privoznik 
Signed-off-by: David Hildenbrand 
Message-Id: <20211217134039.29670-3-da...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 include/hw/virtio/virtio-mem.h |  8 +
 hw/virtio/virtio-mem.c | 63 ++
 2 files changed, 71 insertions(+)

diff --git a/include/hw/virtio/virtio-mem.h b/include/hw/virtio/virtio-mem.h
index 0ac7bcb3b6..7745cfc1a3 100644
--- a/include/hw/virtio/virtio-mem.h
+++ b/include/hw/virtio/virtio-mem.h
@@ -30,6 +30,7 @@ OBJECT_DECLARE_TYPE(VirtIOMEM, VirtIOMEMClass,
 #define VIRTIO_MEM_REQUESTED_SIZE_PROP "requested-size"
 #define VIRTIO_MEM_BLOCK_SIZE_PROP "block-size"
 #define VIRTIO_MEM_ADDR_PROP "memaddr"
+#define VIRTIO_MEM_UNPLUGGED_INACCESSIBLE_PROP "unplugged-inaccessible"
 #define VIRTIO_MEM_PREALLOC_PROP "prealloc"
 
 struct VirtIOMEM {
@@ -63,6 +64,13 @@ struct VirtIOMEM {
 /* block size and alignment */
 uint64_t block_size;
 
+/*
+ * Whether we indicate VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE to the guest.
+ * For !x86 targets this will always be "on" and consequently indicate
+ * VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE.
+ */
+OnOffAuto unplugged_inaccessible;
+
 /* whether to prealloc memory when plugging new blocks */
 bool prealloc;
 
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index ab975ff566..fb6687d4c7 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -32,6 +32,14 @@
 #include CONFIG_DEVICES
 #include "trace.h"
 
+/*
+ * We only had legacy x86 guests that did not support
+ * VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE. Other targets don't have legacy guests.
+ */
+#if defined(TARGET_X86_64) || defined(TARGET_I386)
+#define VIRTIO_MEM_HAS_LEGACY_GUESTS
+#endif
+
 /*
  * Let's not allow blocks smaller than 1 MiB, for example, to keep the tracking
  * bitmap small.
@@ -110,6 +118,19 @@ static uint64_t virtio_mem_default_block_size(RAMBlock *rb)
 return MAX(page_size, VIRTIO_MEM_MIN_BLOCK_SIZE);
 }
 
+#if defined(VIRTIO_MEM_HAS_LEGACY_GUESTS)
+static bool virtio_mem_has_shared_zeropage(RAMBlock *rb)
+{
+/*
+ * We only have a guaranteed shared zeropage on ordinary MAP_PRIVATE
+ * anonymous RAM. In any other case, reading unplugged *can* populate a
+ * fresh page, consuming actual memory.
+ */
+return !qemu_ram_is_shared(rb) && rb->fd < 0 &&
+   qemu_ram_pagesize(rb) == qemu_real_host_page_size;
+}
+#endif /* VIRTIO_MEM_HAS_LEGACY_GUESTS 

[PULL v3 27/55] hw/i386: expose a "smbios-entry-point-type" PC machine property

2022-01-07 Thread Michael S. Tsirkin
From: Eduardo Habkost 

The i440fx and Q35 machine types are both hardcoded to use the
legacy SMBIOS 2.1 (32-bit) entry point. This is a sensible
conservative choice because SeaBIOS only supports SMBIOS 2.1

EDK2, however, can also support SMBIOS 3.0 (64-bit) entry points,
and QEMU already uses this on the ARM virt machine type.

This adds a property to allow the choice of SMBIOS entry point
versions For example to opt in to 64-bit SMBIOS entry point:

   $QEMU -machine q35,smbios-entry-point-type=64

Based on a patch submitted by Daniel Berrangé.

Signed-off-by: Daniel P. Berrangé 
Signed-off-by: Eduardo Habkost 
Message-Id: <20211026151100.1691925-4-ehabk...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
Reviewed-by: Philippe Mathieu-Daudé 
---
 include/hw/i386/pc.h |  4 
 hw/i386/pc.c | 26 ++
 hw/i386/pc_piix.c|  2 +-
 hw/i386/pc_q35.c |  2 +-
 4 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index b38947c224..9c9f4ac748 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -13,6 +13,7 @@
 #include "hw/hotplug.h"
 #include "qom/object.h"
 #include "hw/i386/sgx-epc.h"
+#include "hw/firmware/smbios.h"
 
 #define HPET_INTCAP "hpet-intcap"
 
@@ -40,6 +41,7 @@ typedef struct PCMachineState {
 /* Configuration options: */
 uint64_t max_ram_below_4g;
 OnOffAuto vmport;
+SmbiosEntryPointType smbios_entry_point_type;
 
 bool acpi_build_enabled;
 bool smbus_enabled;
@@ -63,6 +65,8 @@ typedef struct PCMachineState {
 #define PC_MACHINE_SATA "sata"
 #define PC_MACHINE_PIT  "pit"
 #define PC_MACHINE_MAX_FW_SIZE  "max-fw-size"
+#define PC_MACHINE_SMBIOS_EP"smbios-entry-point-type"
+
 /**
  * PCMachineClass:
  *
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index fccde2ef39..959efa5b3f 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -77,6 +77,7 @@
 #include "hw/mem/nvdimm.h"
 #include "qapi/error.h"
 #include "qapi/qapi-visit-common.h"
+#include "qapi/qapi-visit-machine.h"
 #include "qapi/visitor.h"
 #include "hw/core/cpu.h"
 #include "hw/usb.h"
@@ -1524,6 +1525,23 @@ static void 
pc_machine_set_default_bus_bypass_iommu(Object *obj, bool value,
 pcms->default_bus_bypass_iommu = value;
 }
 
+static void pc_machine_get_smbios_ep(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+SmbiosEntryPointType smbios_entry_point_type = 
pcms->smbios_entry_point_type;
+
+visit_type_SmbiosEntryPointType(v, name, _entry_point_type, errp);
+}
+
+static void pc_machine_set_smbios_ep(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+PCMachineState *pcms = PC_MACHINE(obj);
+
+visit_type_SmbiosEntryPointType(v, name, >smbios_entry_point_type, 
errp);
+}
+
 static void pc_machine_get_max_ram_below_4g(Object *obj, Visitor *v,
 const char *name, void *opaque,
 Error **errp)
@@ -1614,6 +1632,8 @@ static void pc_machine_initfn(Object *obj)
 pcms->vmport = ON_OFF_AUTO_OFF;
 #endif /* CONFIG_VMPORT */
 pcms->max_ram_below_4g = 0; /* use default */
+pcms->smbios_entry_point_type = SMBIOS_ENTRY_POINT_TYPE_32;
+
 /* acpi build is enabled by default if machine supports it */
 pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build;
 pcms->smbus_enabled = true;
@@ -1756,6 +1776,12 @@ static void pc_machine_class_init(ObjectClass *oc, void 
*data)
 NULL, NULL);
 object_class_property_set_description(oc, PC_MACHINE_MAX_FW_SIZE,
 "Maximum combined firmware size");
+
+object_class_property_add(oc, PC_MACHINE_SMBIOS_EP, "str",
+pc_machine_get_smbios_ep, pc_machine_set_smbios_ep,
+NULL, NULL);
+object_class_property_set_description(oc, PC_MACHINE_SMBIOS_EP,
+"SMBIOS Entry Point type [32, 64]");
 }
 
 static const TypeInfo pc_machine_info = {
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 25f918b609..7c7790a5ce 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -177,7 +177,7 @@ static void pc_init1(MachineState *machine,
 smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
 mc->name, pcmc->smbios_legacy_mode,
 pcmc->smbios_uuid_encoded,
-SMBIOS_ENTRY_POINT_TYPE_32);
+pcms->smbios_entry_point_type);
 }
 
 /* allocate ram and load rom/bios */
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 1103fbcd90..1780f79bc1 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -200,7 +200,7 @@ static void pc_q35_init(MachineState *machine)
 smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
 mc->name, 

[PULL v3 44/55] tests: acpi: whitelist expected blobs before changing them

2022-01-07 Thread Michael S. Tsirkin
From: Igor Mammedov 

Signed-off-by: Igor Mammedov 
Message-Id: <20211227193120.1084176-3-imamm...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 tests/qtest/bios-tables-test-allowed-diff.h |   2 ++
 tests/data/acpi/q35/FACP.slic   | Bin 0 -> 244 bytes
 tests/data/acpi/q35/SLIC.slic   |   0
 3 files changed, 2 insertions(+)
 create mode 100644 tests/data/acpi/q35/FACP.slic
 create mode 100644 tests/data/acpi/q35/SLIC.slic

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..49dbf8fa3e 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,3 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/q35/FACP.slic",
+"tests/data/acpi/q35/SLIC.slic",
diff --git a/tests/data/acpi/q35/FACP.slic b/tests/data/acpi/q35/FACP.slic
new file mode 100644
index 
..f6a864cc863c7763f6c09d3814ad184a658fa0a0
GIT binary patch
literal 244
zcmZ>BbPo8!z`($~)5+i2BUr(N+hD|^Y6El!tgNU*~X%LSC
z$X0-fGcm9T0LA|E|L2FOWMD7?GM2V5Ffej3F#P0!h{7ddihwku0+2v57svwxMxcSn
X_QAxFX+{NzJ3wNL4G8yu_%Hwf>-7!+

literal 0
HcmV?d1

diff --git a/tests/data/acpi/q35/SLIC.slic b/tests/data/acpi/q35/SLIC.slic
new file mode 100644
index 00..e69de29bb2
-- 
MST




[PULL v3 26/55] hw/smbios: Use qapi for SmbiosEntryPointType

2022-01-07 Thread Michael S. Tsirkin
From: Eduardo Habkost 

This prepares for exposing the SMBIOS entry point type as a
machine property on x86.

Based on a patch from Daniel P. Berrangé.

Signed-off-by: Daniel P. Berrangé 
Signed-off-by: Eduardo Habkost 
Message-Id: <20211026151100.1691925-3-ehabk...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
Reviewed-by: Philippe Mathieu-Daudé 
Acked-by: Markus Armbruster 
---
 qapi/machine.json| 12 
 include/hw/firmware/smbios.h | 10 ++
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/qapi/machine.json b/qapi/machine.json
index 372535b348..b6a37e17c4 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -1568,3 +1568,15 @@
 { 'command': 'x-query-usb',
   'returns': 'HumanReadableText',
   'features': [ 'unstable' ] }
+
+##
+# @SmbiosEntryPointType:
+#
+# @32: SMBIOS version 2.1 (32-bit) Entry Point
+#
+# @64: SMBIOS version 3.0 (64-bit) Entry Point
+#
+# Since: 7.0
+##
+{ 'enum': 'SmbiosEntryPointType',
+  'data': [ '32', '64' ] }
diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
index d916baed6a..4b7ad77a44 100644
--- a/include/hw/firmware/smbios.h
+++ b/include/hw/firmware/smbios.h
@@ -1,6 +1,8 @@
 #ifndef QEMU_SMBIOS_H
 #define QEMU_SMBIOS_H
 
+#include "qapi/qapi-types-machine.h"
+
 /*
  * SMBIOS Support
  *
@@ -23,14 +25,6 @@ struct smbios_phys_mem_area {
 uint64_t length;
 };
 
-/*
- * SMBIOS spec defined tables
- */
-typedef enum SmbiosEntryPointType {
-SMBIOS_ENTRY_POINT_TYPE_32,
-SMBIOS_ENTRY_POINT_TYPE_64,
-} SmbiosEntryPointType;
-
 /* SMBIOS Entry Point
  * There are two types of entry points defined in the SMBIOS specification
  * (see below). BIOS must place the entry point(s) at a 16-byte-aligned
-- 
MST




[PULL v3 25/55] smbios: Rename SMBIOS_ENTRY_POINT_* enums

2022-01-07 Thread Michael S. Tsirkin
From: Eduardo Habkost 

Rename the enums to match the naming style used by QAPI, and to
use "32" and "64" instead of "20" and "31".  This will allow us
to more easily move the enum to the QAPI schema later.

About the naming choice: "SMBIOS 2.1 entry point"/"SMBIOS 3.0
entry point" and "32-bit entry point"/"64-bit entry point" are
synonymous in the SMBIOS specification.  However, the phrases
"32-bit entry point" and "64-bit entry point" are used more often.

The new names also avoid confusion between the entry point format
and the actual SMBIOS version reported in the entry point
structure.  For example: currently the 32-bit entry point
actually report SMBIOS 2.8 support, not 2.1.

Based on portions of a patch submitted by Daniel P. Berrangé.

Signed-off-by: Eduardo Habkost 
Message-Id: <20211026151100.1691925-2-ehabk...@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 include/hw/firmware/smbios.h | 4 ++--
 hw/arm/virt.c| 2 +-
 hw/i386/pc_piix.c| 2 +-
 hw/i386/pc_q35.c | 2 +-
 hw/smbios/smbios.c   | 8 
 5 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
index 5a0dd0c8cf..d916baed6a 100644
--- a/include/hw/firmware/smbios.h
+++ b/include/hw/firmware/smbios.h
@@ -27,8 +27,8 @@ struct smbios_phys_mem_area {
  * SMBIOS spec defined tables
  */
 typedef enum SmbiosEntryPointType {
-SMBIOS_ENTRY_POINT_21,
-SMBIOS_ENTRY_POINT_30,
+SMBIOS_ENTRY_POINT_TYPE_32,
+SMBIOS_ENTRY_POINT_TYPE_64,
 } SmbiosEntryPointType;
 
 /* SMBIOS Entry Point
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 4593fea1ce..b45b52c90e 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1589,7 +1589,7 @@ static void virt_build_smbios(VirtMachineState *vms)
 
 smbios_set_defaults("QEMU", product,
 vmc->smbios_old_sys_ver ? "1.0" : mc->name, false,
-true, SMBIOS_ENTRY_POINT_30);
+true, SMBIOS_ENTRY_POINT_TYPE_64);
 
 smbios_get_tables(MACHINE(vms), NULL, 0,
   _tables, _tables_len,
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 1999190276..25f918b609 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -177,7 +177,7 @@ static void pc_init1(MachineState *machine,
 smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
 mc->name, pcmc->smbios_legacy_mode,
 pcmc->smbios_uuid_encoded,
-SMBIOS_ENTRY_POINT_21);
+SMBIOS_ENTRY_POINT_TYPE_32);
 }
 
 /* allocate ram and load rom/bios */
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 2e981f436c..1103fbcd90 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -200,7 +200,7 @@ static void pc_q35_init(MachineState *machine)
 smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
 mc->name, pcmc->smbios_legacy_mode,
 pcmc->smbios_uuid_encoded,
-SMBIOS_ENTRY_POINT_21);
+SMBIOS_ENTRY_POINT_TYPE_32);
 }
 
 /* allocate ram and load rom/bios */
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 7397e56737..6013df1698 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -62,7 +62,7 @@ uint8_t *smbios_tables;
 size_t smbios_tables_len;
 unsigned smbios_table_max;
 unsigned smbios_table_cnt;
-static SmbiosEntryPointType smbios_ep_type = SMBIOS_ENTRY_POINT_21;
+static SmbiosEntryPointType smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_32;
 
 static SmbiosEntryPoint ep;
 
@@ -432,7 +432,7 @@ static void smbios_validate_table(MachineState *ms)
 exit(1);
 }
 
-if (smbios_ep_type == SMBIOS_ENTRY_POINT_21 &&
+if (smbios_ep_type == SMBIOS_ENTRY_POINT_TYPE_32 &&
 smbios_tables_len > SMBIOS_21_MAX_TABLES_LEN) {
 error_report("SMBIOS 2.1 table length %zu exceeds %d",
  smbios_tables_len, SMBIOS_21_MAX_TABLES_LEN);
@@ -927,7 +927,7 @@ void smbios_set_defaults(const char *manufacturer, const 
char *product,
 static void smbios_entry_point_setup(void)
 {
 switch (smbios_ep_type) {
-case SMBIOS_ENTRY_POINT_21:
+case SMBIOS_ENTRY_POINT_TYPE_32:
 memcpy(ep.ep21.anchor_string, "_SM_", 4);
 memcpy(ep.ep21.intermediate_anchor_string, "_DMI_", 5);
 ep.ep21.length = sizeof(struct smbios_21_entry_point);
@@ -950,7 +950,7 @@ static void smbios_entry_point_setup(void)
 ep.ep21.structure_table_address = cpu_to_le32(0);
 
 break;
-case SMBIOS_ENTRY_POINT_30:
+case SMBIOS_ENTRY_POINT_TYPE_64:
 memcpy(ep.ep30.anchor_string, "_SM3_", 5);
 ep.ep30.length = sizeof(struct smbios_30_entry_point);
 ep.ep30.entry_point_revision = 1;
-- 
MST




[PULL v3 35/55] util/oslib-posix: Forward SIGBUS to MCE handler under Linux

2022-01-07 Thread Michael S. Tsirkin
From: David Hildenbrand 

Temporarily modifying the SIGBUS handler is really nasty, as we might be
unlucky and receive an MCE SIGBUS while having our handler registered.
Unfortunately, there is no way around messing with SIGBUS when
MADV_POPULATE_WRITE is not applicable or not around.

Let's forward SIGBUS that don't belong to us to the already registered
handler and document the situation.

Reviewed-by: Daniel P. Berrangé 
Reviewed-by: Michal Privoznik 
Signed-off-by: David Hildenbrand 
Message-Id: <20211217134611.31172-8-da...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 softmmu/cpus.c |  4 
 util/oslib-posix.c | 37 ++---
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/softmmu/cpus.c b/softmmu/cpus.c
index 071085f840..23bca46b07 100644
--- a/softmmu/cpus.c
+++ b/softmmu/cpus.c
@@ -352,6 +352,10 @@ static void qemu_init_sigbus(void)
 {
 struct sigaction action;
 
+/*
+ * ALERT: when modifying this, take care that SIGBUS forwarding in
+ * os_mem_prealloc() will continue working as expected.
+ */
 memset(, 0, sizeof(action));
 action.sa_flags = SA_SIGINFO;
 action.sa_sigaction = sigbus_handler;
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 9829149e4b..9efdc74bba 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -35,6 +35,7 @@
 #include "sysemu/sysemu.h"
 #include "trace.h"
 #include "qapi/error.h"
+#include "qemu/error-report.h"
 #include "qemu/sockets.h"
 #include "qemu/thread.h"
 #include 
@@ -95,6 +96,7 @@ typedef struct MemsetThread MemsetThread;
 
 /* used by sigbus_handler() */
 static MemsetContext *sigbus_memset_context;
+struct sigaction sigbus_oldact;
 static QemuMutex sigbus_mutex;
 
 static QemuMutex page_mutex;
@@ -446,7 +448,11 @@ const char *qemu_get_exec_dir(void)
 return exec_dir;
 }
 
+#ifdef CONFIG_LINUX
+static void sigbus_handler(int signal, siginfo_t *siginfo, void *ctx)
+#else /* CONFIG_LINUX */
 static void sigbus_handler(int signal)
+#endif /* CONFIG_LINUX */
 {
 int i;
 
@@ -459,6 +465,26 @@ static void sigbus_handler(int signal)
 }
 }
 }
+
+#ifdef CONFIG_LINUX
+/*
+ * We assume that the MCE SIGBUS handler could have been registered. We
+ * should never receive BUS_MCEERR_AO on any of our threads, but only on
+ * the main thread registered for PR_MCE_KILL_EARLY. Further, we should not
+ * receive BUS_MCEERR_AR triggered by action of other threads on one of
+ * our threads. So, no need to check for unrelated SIGBUS when seeing one
+ * for our threads.
+ *
+ * We will forward to the MCE handler, which will either handle the SIGBUS
+ * or reinstall the default SIGBUS handler and reraise the SIGBUS. The
+ * default SIGBUS handler will crash the process, so we don't care.
+ */
+if (sigbus_oldact.sa_flags & SA_SIGINFO) {
+sigbus_oldact.sa_sigaction(signal, siginfo, ctx);
+return;
+}
+#endif /* CONFIG_LINUX */
+warn_report("os_mem_prealloc: unrelated SIGBUS detected and ignored");
 }
 
 static void *do_touch_pages(void *arg)
@@ -628,10 +654,10 @@ void os_mem_prealloc(int fd, char *area, size_t memory, 
int smp_cpus,
 {
 static gsize initialized;
 int ret;
-struct sigaction act, oldact;
 size_t hpagesize = qemu_fd_getpagesize(fd);
 size_t numpages = DIV_ROUND_UP(memory, hpagesize);
 bool use_madv_populate_write;
+struct sigaction act;
 
 /*
  * Sense on every invocation, as MADV_POPULATE_WRITE cannot be used for
@@ -647,10 +673,15 @@ void os_mem_prealloc(int fd, char *area, size_t memory, 
int smp_cpus,
 
 qemu_mutex_lock(_mutex);
 memset(, 0, sizeof(act));
+#ifdef CONFIG_LINUX
+act.sa_sigaction = _handler;
+act.sa_flags = SA_SIGINFO;
+#else /* CONFIG_LINUX */
 act.sa_handler = _handler;
 act.sa_flags = 0;
+#endif /* CONFIG_LINUX */
 
-ret = sigaction(SIGBUS, , );
+ret = sigaction(SIGBUS, , _oldact);
 if (ret) {
 error_setg_errno(errp, errno,
 "os_mem_prealloc: failed to install signal handler");
@@ -667,7 +698,7 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int 
smp_cpus,
 }
 
 if (!use_madv_populate_write) {
-ret = sigaction(SIGBUS, , NULL);
+ret = sigaction(SIGBUS, _oldact, NULL);
 if (ret) {
 /* Terminate QEMU since it can't recover from error */
 perror("os_mem_prealloc: failed to reinstall signal handler");
-- 
MST




[PULL v3 41/55] virtio-mem: Set "unplugged-inaccessible=auto" for the 7.0 machine on x86

2022-01-07 Thread Michael S. Tsirkin
From: David Hildenbrand 

Set the new default to "auto", keeping it set to "off" for compat
machines. This property is only available for x86 targets.

Reviewed-by: Michal Privoznik 
Reviewed-by: Pankaj Gupta 
Signed-off-by: David Hildenbrand 
Message-Id: <20211217134039.29670-4-da...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 hw/i386/pc.c   | 4 +++-
 hw/virtio/virtio-mem.c | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 959efa5b3f..718ab81ba8 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -95,7 +95,9 @@
 #include "trace.h"
 #include CONFIG_DEVICES
 
-GlobalProperty pc_compat_6_2[] = {};
+GlobalProperty pc_compat_6_2[] = {
+{ "virtio-mem", "unplugged-inaccessible", "off" },
+};
 const size_t pc_compat_6_2_len = G_N_ELEMENTS(pc_compat_6_2);
 
 GlobalProperty pc_compat_6_1[] = {
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index fb6687d4c7..04c223b0c9 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -1201,7 +1201,7 @@ static Property virtio_mem_properties[] = {
  TYPE_MEMORY_BACKEND, HostMemoryBackend *),
 #if defined(VIRTIO_MEM_HAS_LEGACY_GUESTS)
 DEFINE_PROP_ON_OFF_AUTO(VIRTIO_MEM_UNPLUGGED_INACCESSIBLE_PROP, VirtIOMEM,
-unplugged_inaccessible, ON_OFF_AUTO_OFF),
+unplugged_inaccessible, ON_OFF_AUTO_AUTO),
 #endif
 DEFINE_PROP_END_OF_LIST(),
 };
-- 
MST




[PULL v3 24/55] pcie_aer: Don't trigger a LSI if none are defined

2022-01-07 Thread Michael S. Tsirkin
From: Frederic Barrat 

Skip triggering an LSI when the AER root error status is updated if no
LSI is defined for the device. We can have a root bridge with no LSI,
MSI and MSI-X defined, for example on POWER systems.

Signed-off-by: Frederic Barrat 
Message-Id: <2026170133.724751-4-fbar...@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
Reviewed-by: Cédric Le Goater 
---
 hw/pci/pcie_aer.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
index 27f9cc56af..e1a8a88c8c 100644
--- a/hw/pci/pcie_aer.c
+++ b/hw/pci/pcie_aer.c
@@ -774,7 +774,9 @@ void pcie_aer_root_write_config(PCIDevice *dev,
 uint32_t root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
 /* 6.2.4.1.2 Interrupt Generation */
 if (!msix_enabled(dev) && !msi_enabled(dev)) {
-pci_set_irq(dev, !!(root_cmd & enabled_cmd));
+if (pci_intx(dev) != -1) {
+pci_set_irq(dev, !!(root_cmd & enabled_cmd));
+}
 return;
 }
 
-- 
MST




[PULL v3 33/55] util/oslib-posix: Avoid creating a single thread with MADV_POPULATE_WRITE

2022-01-07 Thread Michael S. Tsirkin
From: David Hildenbrand 

Let's simplify the case when we only want a single thread and don't have
to mess with signal handlers.

Reviewed-by: Pankaj Gupta 
Reviewed-by: Daniel P. Berrangé 
Reviewed-by: Michal Privoznik 
Signed-off-by: David Hildenbrand 
Message-Id: <20211217134611.31172-6-da...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 util/oslib-posix.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 67c08a425e..efa4f96d56 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -564,6 +564,14 @@ static int touch_all_pages(char *area, size_t hpagesize, 
size_t numpages,
 }
 
 if (use_madv_populate_write) {
+/* Avoid creating a single thread for MADV_POPULATE_WRITE */
+if (context.num_threads == 1) {
+if (qemu_madvise(area, hpagesize * numpages,
+ QEMU_MADV_POPULATE_WRITE)) {
+return -errno;
+}
+return 0;
+}
 touch_fn = do_madv_populate_write_pages;
 } else {
 touch_fn = do_touch_pages;
-- 
MST




[PULL v3 23/55] pci: Export the pci_intx() function

2022-01-07 Thread Michael S. Tsirkin
From: Frederic Barrat 

Move the pci_intx() definition to the PCI header file, so that it can
be called from other PCI files. It is used by the next patch.

Signed-off-by: Frederic Barrat 
Message-Id: <2026170133.724751-3-fbar...@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
Reviewed-by: Cédric Le Goater 
---
 include/hw/pci/pci.h | 5 +
 hw/pci/pci.c | 5 -
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 5b36334a28..483d5c7c72 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -735,6 +735,11 @@ void lsi53c8xx_handle_legacy_cmdline(DeviceState *lsi_dev);
 qemu_irq pci_allocate_irq(PCIDevice *pci_dev);
 void pci_set_irq(PCIDevice *pci_dev, int level);
 
+static inline int pci_intx(PCIDevice *pci_dev)
+{
+return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;
+}
+
 static inline void pci_irq_assert(PCIDevice *pci_dev)
 {
 pci_set_irq(pci_dev, 1);
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 322ba450e7..5d30f9ca60 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1497,11 +1497,6 @@ static void pci_irq_handler(void *opaque, int irq_num, 
int level)
 pci_change_irq_level(pci_dev, irq_num, change);
 }
 
-static inline int pci_intx(PCIDevice *pci_dev)
-{
-return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;
-}
-
 qemu_irq pci_allocate_irq(PCIDevice *pci_dev)
 {
 int intx = pci_intx(pci_dev);
-- 
MST




[PULL v3 36/55] virtio-mem: Support "prealloc=on" option

2022-01-07 Thread Michael S. Tsirkin
From: David Hildenbrand 

For scarce memory resources, such as hugetlb, we want to be able to
prealloc such memory resources in order to not crash later on access. On
simple user errors we could otherwise easily run out of memory resources
an crash the VM -- pretty much undesired.

For ordinary memory devices, such as DIMMs, we preallocate memory via the
memory backend for such use cases; however, with virtio-mem we're dealing
with sparse memory backends; preallocating the whole memory backend
destroys the whole purpose of virtio-mem.

Instead, we want to preallocate memory when actually exposing memory to the
VM dynamically, and fail plugging memory gracefully + warn the user in case
preallocation fails.

A common use case for hugetlb will be using "reserve=off,prealloc=off" for
the memory backend and "prealloc=on" for the virtio-mem device. This
way, no huge pages will be reserved for the process, but we can recover
if there are no actual huge pages when plugging memory. Libvirt is
already prepared for this.

Note that preallocation cannot protect from the OOM killer -- which
holds true for any kind of preallocation in QEMU. It's primarily useful
only for scarce memory resources such as hugetlb, or shared file-backed
memory. It's of little use for ordinary anonymous memory that can be
swapped, KSM merged, ... but we won't forbid it.

Reviewed-by: Michal Privoznik 
Signed-off-by: David Hildenbrand 
Message-Id: <20211217134611.31172-9-da...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 include/hw/virtio/virtio-mem.h |  4 
 hw/virtio/virtio-mem.c | 39 ++
 2 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/include/hw/virtio/virtio-mem.h b/include/hw/virtio/virtio-mem.h
index a5dd6a493b..0ac7bcb3b6 100644
--- a/include/hw/virtio/virtio-mem.h
+++ b/include/hw/virtio/virtio-mem.h
@@ -30,6 +30,7 @@ OBJECT_DECLARE_TYPE(VirtIOMEM, VirtIOMEMClass,
 #define VIRTIO_MEM_REQUESTED_SIZE_PROP "requested-size"
 #define VIRTIO_MEM_BLOCK_SIZE_PROP "block-size"
 #define VIRTIO_MEM_ADDR_PROP "memaddr"
+#define VIRTIO_MEM_PREALLOC_PROP "prealloc"
 
 struct VirtIOMEM {
 VirtIODevice parent_obj;
@@ -62,6 +63,9 @@ struct VirtIOMEM {
 /* block size and alignment */
 uint64_t block_size;
 
+/* whether to prealloc memory when plugging new blocks */
+bool prealloc;
+
 /* notifiers to notify when "size" changes */
 NotifierList size_change_notifiers;
 
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index 341c3fa2c1..ab975ff566 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -429,10 +429,40 @@ static int virtio_mem_set_block_state(VirtIOMEM *vmem, 
uint64_t start_gpa,
 return -EBUSY;
 }
 virtio_mem_notify_unplug(vmem, offset, size);
-} else if (virtio_mem_notify_plug(vmem, offset, size)) {
-/* Could be a mapping attempt resulted in memory getting populated. */
-ram_block_discard_range(vmem->memdev->mr.ram_block, offset, size);
-return -EBUSY;
+} else {
+int ret = 0;
+
+if (vmem->prealloc) {
+void *area = memory_region_get_ram_ptr(>memdev->mr) + offset;
+int fd = memory_region_get_fd(>memdev->mr);
+Error *local_err = NULL;
+
+os_mem_prealloc(fd, area, size, 1, _err);
+if (local_err) {
+static bool warned;
+
+/*
+ * Warn only once, we don't want to fill the log with these
+ * warnings.
+ */
+if (!warned) {
+warn_report_err(local_err);
+warned = true;
+} else {
+error_free(local_err);
+}
+ret = -EBUSY;
+}
+}
+if (!ret) {
+ret = virtio_mem_notify_plug(vmem, offset, size);
+}
+
+if (ret) {
+/* Could be preallocation or a notifier populated memory. */
+ram_block_discard_range(vmem->memdev->mr.ram_block, offset, size);
+return -EBUSY;
+}
 }
 virtio_mem_set_bitmap(vmem, start_gpa, size, plug);
 return 0;
@@ -1108,6 +1138,7 @@ static void virtio_mem_instance_init(Object *obj)
 static Property virtio_mem_properties[] = {
 DEFINE_PROP_UINT64(VIRTIO_MEM_ADDR_PROP, VirtIOMEM, addr, 0),
 DEFINE_PROP_UINT32(VIRTIO_MEM_NODE_PROP, VirtIOMEM, node, 0),
+DEFINE_PROP_BOOL(VIRTIO_MEM_PREALLOC_PROP, VirtIOMEM, prealloc, false),
 DEFINE_PROP_LINK(VIRTIO_MEM_MEMDEV_PROP, VirtIOMEM, memdev,
  TYPE_MEMORY_BACKEND, HostMemoryBackend *),
 DEFINE_PROP_END_OF_LIST(),
-- 
MST




  1   2   3   4   5   >