aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/alpha/translate.c173
-rw-r--r--target/arm/helper-a64.c61
-rw-r--r--target/arm/m_helper.c6
-rw-r--r--target/hexagon/cpu.h9
-rw-r--r--target/i386/cpu.c16
-rw-r--r--target/i386/kvm/kvm.c3
-rw-r--r--target/i386/kvm/meson.build8
-rw-r--r--target/i386/kvm/sev-stub.c22
-rw-r--r--target/i386/meson.build4
-rw-r--r--target/i386/monitor.c124
-rw-r--r--target/i386/sev-stub.c88
-rw-r--r--target/i386/sev-sysemu-stub.c70
-rw-r--r--target/i386/sev.c201
-rw-r--r--target/i386/sev.h (renamed from target/i386/sev_i386.h)35
-rw-r--r--target/i386/tcg/mem_helper.c2
-rw-r--r--target/m68k/op_helper.c1
-rw-r--r--target/mips/tcg/msa_helper.c389
-rw-r--r--target/ppc/mem_helper.c1
-rw-r--r--target/ppc/translate.c12
-rw-r--r--target/s390x/tcg/mem_helper.c13
-rw-r--r--target/sparc/ldst_helper.c14
21 files changed, 496 insertions, 756 deletions
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index b034206688..0eee3a1bcc 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -267,51 +267,51 @@ static inline DisasJumpType gen_invalid(DisasContext *ctx)
return gen_excp(ctx, EXCP_OPCDEC, 0);
}
-static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
+static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr)
{
TCGv_i32 tmp32 = tcg_temp_new_i32();
- tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
- gen_helper_memory_to_f(t0, tmp32);
+ tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
+ gen_helper_memory_to_f(dest, tmp32);
tcg_temp_free_i32(tmp32);
}
-static inline void gen_qemu_ldg(TCGv t0, TCGv t1, int flags)
+static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr)
{
TCGv tmp = tcg_temp_new();
- tcg_gen_qemu_ld_i64(tmp, t1, flags, MO_LEQ);
- gen_helper_memory_to_g(t0, tmp);
+ tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEQ);
+ gen_helper_memory_to_g(dest, tmp);
tcg_temp_free(tmp);
}
-static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
+static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr)
{
TCGv_i32 tmp32 = tcg_temp_new_i32();
- tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
- gen_helper_memory_to_s(t0, tmp32);
+ tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
+ gen_helper_memory_to_s(dest, tmp32);
tcg_temp_free_i32(tmp32);
}
-static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
+static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr)
{
- tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LESL);
- tcg_gen_mov_i64(cpu_lock_addr, t1);
- tcg_gen_mov_i64(cpu_lock_value, t0);
+ tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEQ);
}
-static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
+static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
+ void (*func)(DisasContext *, TCGv, TCGv))
{
- tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LEQ);
- tcg_gen_mov_i64(cpu_lock_addr, t1);
- tcg_gen_mov_i64(cpu_lock_value, t0);
+ /* Loads to $f31 are prefetches, which we can treat as nops. */
+ if (likely(ra != 31)) {
+ TCGv addr = tcg_temp_new();
+ tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
+ func(ctx, cpu_fir[ra], addr);
+ tcg_temp_free(addr);
+ }
}
-static inline void gen_load_mem(DisasContext *ctx,
- void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1,
- int flags),
- int ra, int rb, int32_t disp16, bool fp,
- bool clear)
+static void gen_load_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
+ MemOp op, bool clear, bool locked)
{
- TCGv tmp, addr, va;
+ TCGv addr, dest;
/* LDQ_U with ra $31 is UNOP. Other various loads are forms of
prefetches, which we can treat as nops. No worries about
@@ -320,72 +320,75 @@ static inline void gen_load_mem(DisasContext *ctx,
return;
}
- tmp = tcg_temp_new();
- addr = load_gpr(ctx, rb);
-
- if (disp16) {
- tcg_gen_addi_i64(tmp, addr, disp16);
- addr = tmp;
- }
+ addr = tcg_temp_new();
+ tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
if (clear) {
- tcg_gen_andi_i64(tmp, addr, ~0x7);
- addr = tmp;
+ tcg_gen_andi_i64(addr, addr, ~0x7);
}
- va = (fp ? cpu_fir[ra] : ctx->ir[ra]);
- tcg_gen_qemu_load(va, addr, ctx->mem_idx);
+ dest = ctx->ir[ra];
+ tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, op);
- tcg_temp_free(tmp);
+ if (locked) {
+ tcg_gen_mov_i64(cpu_lock_addr, addr);
+ tcg_gen_mov_i64(cpu_lock_value, dest);
+ }
+ tcg_temp_free(addr);
}
-static inline void gen_qemu_stf(TCGv t0, TCGv t1, int flags)
+static void gen_stf(DisasContext *ctx, TCGv src, TCGv addr)
{
TCGv_i32 tmp32 = tcg_temp_new_i32();
- gen_helper_f_to_memory(tmp32, t0);
- tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
+ gen_helper_f_to_memory(tmp32, addr);
+ tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
tcg_temp_free_i32(tmp32);
}
-static inline void gen_qemu_stg(TCGv t0, TCGv t1, int flags)
+static void gen_stg(DisasContext *ctx, TCGv src, TCGv addr)
{
TCGv tmp = tcg_temp_new();
- gen_helper_g_to_memory(tmp, t0);
- tcg_gen_qemu_st_i64(tmp, t1, flags, MO_LEQ);
+ gen_helper_g_to_memory(tmp, src);
+ tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEQ);
tcg_temp_free(tmp);
}
-static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
+static void gen_sts(DisasContext *ctx, TCGv src, TCGv addr)
{
TCGv_i32 tmp32 = tcg_temp_new_i32();
- gen_helper_s_to_memory(tmp32, t0);
- tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
+ gen_helper_s_to_memory(tmp32, src);
+ tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
tcg_temp_free_i32(tmp32);
}
-static inline void gen_store_mem(DisasContext *ctx,
- void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
- int flags),
- int ra, int rb, int32_t disp16, bool fp,
- bool clear)
+static void gen_stt(DisasContext *ctx, TCGv src, TCGv addr)
{
- TCGv tmp, addr, va;
+ tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEQ);
+}
- tmp = tcg_temp_new();
- addr = load_gpr(ctx, rb);
+static void gen_store_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
+ void (*func)(DisasContext *, TCGv, TCGv))
+{
+ TCGv addr = tcg_temp_new();
+ tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
+ func(ctx, load_fpr(ctx, ra), addr);
+ tcg_temp_free(addr);
+}
- if (disp16) {
- tcg_gen_addi_i64(tmp, addr, disp16);
- addr = tmp;
- }
+static void gen_store_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
+ MemOp op, bool clear)
+{
+ TCGv addr, src;
+
+ addr = tcg_temp_new();
+ tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
if (clear) {
- tcg_gen_andi_i64(tmp, addr, ~0x7);
- addr = tmp;
+ tcg_gen_andi_i64(addr, addr, ~0x7);
}
- va = (fp ? load_fpr(ctx, ra) : load_gpr(ctx, ra));
- tcg_gen_qemu_store(va, addr, ctx->mem_idx);
+ src = load_gpr(ctx, ra);
+ tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, op);
- tcg_temp_free(tmp);
+ tcg_temp_free(addr);
}
static DisasJumpType gen_store_conditional(DisasContext *ctx, int ra, int rb,
@@ -1480,30 +1483,30 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
case 0x0A:
/* LDBU */
REQUIRE_AMASK(BWX);
- gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
+ gen_load_int(ctx, ra, rb, disp16, MO_UB, 0, 0);
break;
case 0x0B:
/* LDQ_U */
- gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
+ gen_load_int(ctx, ra, rb, disp16, MO_LEQ, 1, 0);
break;
case 0x0C:
/* LDWU */
REQUIRE_AMASK(BWX);
- gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
+ gen_load_int(ctx, ra, rb, disp16, MO_LEUW, 0, 0);
break;
case 0x0D:
/* STW */
REQUIRE_AMASK(BWX);
- gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
+ gen_store_int(ctx, ra, rb, disp16, MO_LEUW, 0);
break;
case 0x0E:
/* STB */
REQUIRE_AMASK(BWX);
- gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
+ gen_store_int(ctx, ra, rb, disp16, MO_UB, 0);
break;
case 0x0F:
/* STQ_U */
- gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
+ gen_store_int(ctx, ra, rb, disp16, MO_LEQ, 1);
break;
case 0x10:
@@ -2458,11 +2461,15 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x2:
/* Longword physical access with lock (hw_ldl_l/p) */
- gen_qemu_ldl_l(va, addr, MMU_PHYS_IDX);
+ tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL);
+ tcg_gen_mov_i64(cpu_lock_addr, addr);
+ tcg_gen_mov_i64(cpu_lock_value, va);
break;
case 0x3:
/* Quadword physical access with lock (hw_ldq_l/p) */
- gen_qemu_ldq_l(va, addr, MMU_PHYS_IDX);
+ tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEQ);
+ tcg_gen_mov_i64(cpu_lock_addr, addr);
+ tcg_gen_mov_i64(cpu_lock_value, va);
break;
case 0x4:
/* Longword virtual PTE fetch (hw_ldl/v) */
@@ -2776,66 +2783,66 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
case 0x20:
/* LDF */
REQUIRE_FEN;
- gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
+ gen_load_fp(ctx, ra, rb, disp16, gen_ldf);
break;
case 0x21:
/* LDG */
REQUIRE_FEN;
- gen_load_mem(ctx, &gen_qemu_ldg, ra, rb, disp16, 1, 0);
+ gen_load_fp(ctx, ra, rb, disp16, gen_ldg);
break;
case 0x22:
/* LDS */
REQUIRE_FEN;
- gen_load_mem(ctx, &gen_qemu_lds, ra, rb, disp16, 1, 0);
+ gen_load_fp(ctx, ra, rb, disp16, gen_lds);
break;
case 0x23:
/* LDT */
REQUIRE_FEN;
- gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 1, 0);
+ gen_load_fp(ctx, ra, rb, disp16, gen_ldt);
break;
case 0x24:
/* STF */
REQUIRE_FEN;
- gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0);
+ gen_store_fp(ctx, ra, rb, disp16, gen_stf);
break;
case 0x25:
/* STG */
REQUIRE_FEN;
- gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0);
+ gen_store_fp(ctx, ra, rb, disp16, gen_stg);
break;
case 0x26:
/* STS */
REQUIRE_FEN;
- gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0);
+ gen_store_fp(ctx, ra, rb, disp16, gen_sts);
break;
case 0x27:
/* STT */
REQUIRE_FEN;
- gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0);
+ gen_store_fp(ctx, ra, rb, disp16, gen_stt);
break;
case 0x28:
/* LDL */
- gen_load_mem(ctx, &tcg_gen_qemu_ld32s, ra, rb, disp16, 0, 0);
+ gen_load_int(ctx, ra, rb, disp16, MO_LESL, 0, 0);
break;
case 0x29:
/* LDQ */
- gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 0);
+ gen_load_int(ctx, ra, rb, disp16, MO_LEQ, 0, 0);
break;
case 0x2A:
/* LDL_L */
- gen_load_mem(ctx, &gen_qemu_ldl_l, ra, rb, disp16, 0, 0);
+ gen_load_int(ctx, ra, rb, disp16, MO_LESL, 0, 1);
break;
case 0x2B:
/* LDQ_L */
- gen_load_mem(ctx, &gen_qemu_ldq_l, ra, rb, disp16, 0, 0);
+ gen_load_int(ctx, ra, rb, disp16, MO_LEQ, 0, 1);
break;
case 0x2C:
/* STL */
- gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0);
+ gen_store_int(ctx, ra, rb, disp16, MO_LEUL, 0);
break;
case 0x2D:
/* STQ */
- gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0);
+ gen_store_int(ctx, ra, rb, disp16, MO_LEQ, 0);
break;
case 0x2E:
/* STL_C */
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index c5af779006..5ae2ecb0f3 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -32,7 +32,6 @@
#include "exec/cpu_ldst.h"
#include "qemu/int128.h"
#include "qemu/atomic128.h"
-#include "tcg/tcg.h"
#include "fpu/softfloat.h"
#include <zlib.h> /* For crc32 */
@@ -513,37 +512,19 @@ uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr,
uintptr_t ra = GETPC();
uint64_t o0, o1;
bool success;
-
-#ifdef CONFIG_USER_ONLY
- /* ??? Enforce alignment. */
- uint64_t *haddr = g2h(env_cpu(env), addr);
-
- set_helper_retaddr(ra);
- o0 = ldq_le_p(haddr + 0);
- o1 = ldq_le_p(haddr + 1);
- oldv = int128_make128(o0, o1);
-
- success = int128_eq(oldv, cmpv);
- if (success) {
- stq_le_p(haddr + 0, int128_getlo(newv));
- stq_le_p(haddr + 1, int128_gethi(newv));
- }
- clear_helper_retaddr();
-#else
int mem_idx = cpu_mmu_index(env, false);
MemOpIdx oi0 = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
MemOpIdx oi1 = make_memop_idx(MO_LEQ, mem_idx);
- o0 = helper_le_ldq_mmu(env, addr + 0, oi0, ra);
- o1 = helper_le_ldq_mmu(env, addr + 8, oi1, ra);
+ o0 = cpu_ldq_le_mmu(env, addr + 0, oi0, ra);
+ o1 = cpu_ldq_le_mmu(env, addr + 8, oi1, ra);
oldv = int128_make128(o0, o1);
success = int128_eq(oldv, cmpv);
if (success) {
- helper_le_stq_mmu(env, addr + 0, int128_getlo(newv), oi1, ra);
- helper_le_stq_mmu(env, addr + 8, int128_gethi(newv), oi1, ra);
+ cpu_stq_le_mmu(env, addr + 0, int128_getlo(newv), oi1, ra);
+ cpu_stq_le_mmu(env, addr + 8, int128_gethi(newv), oi1, ra);
}
-#endif
return !success;
}
@@ -560,7 +541,7 @@ uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState *env, uint64_t addr,
assert(HAVE_CMPXCHG128);
mem_idx = cpu_mmu_index(env, false);
- oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
+ oi = make_memop_idx(MO_LE | MO_128 | MO_ALIGN, mem_idx);
cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
newv = int128_make128(new_lo, new_hi);
@@ -583,37 +564,19 @@ uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr,
uintptr_t ra = GETPC();
uint64_t o0, o1;
bool success;
-
-#ifdef CONFIG_USER_ONLY
- /* ??? Enforce alignment. */
- uint64_t *haddr = g2h(env_cpu(env), addr);
-
- set_helper_retaddr(ra);
- o1 = ldq_be_p(haddr + 0);
- o0 = ldq_be_p(haddr + 1);
- oldv = int128_make128(o0, o1);
-
- success = int128_eq(oldv, cmpv);
- if (success) {
- stq_be_p(haddr + 0, int128_gethi(newv));
- stq_be_p(haddr + 1, int128_getlo(newv));
- }
- clear_helper_retaddr();
-#else
int mem_idx = cpu_mmu_index(env, false);
MemOpIdx oi0 = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
MemOpIdx oi1 = make_memop_idx(MO_BEQ, mem_idx);
- o1 = helper_be_ldq_mmu(env, addr + 0, oi0, ra);
- o0 = helper_be_ldq_mmu(env, addr + 8, oi1, ra);
+ o1 = cpu_ldq_be_mmu(env, addr + 0, oi0, ra);
+ o0 = cpu_ldq_be_mmu(env, addr + 8, oi1, ra);
oldv = int128_make128(o0, o1);
success = int128_eq(oldv, cmpv);
if (success) {
- helper_be_stq_mmu(env, addr + 0, int128_gethi(newv), oi1, ra);
- helper_be_stq_mmu(env, addr + 8, int128_getlo(newv), oi1, ra);
+ cpu_stq_be_mmu(env, addr + 0, int128_gethi(newv), oi1, ra);
+ cpu_stq_be_mmu(env, addr + 8, int128_getlo(newv), oi1, ra);
}
-#endif
return !success;
}
@@ -630,7 +593,7 @@ uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr,
assert(HAVE_CMPXCHG128);
mem_idx = cpu_mmu_index(env, false);
- oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
+ oi = make_memop_idx(MO_BE | MO_128 | MO_ALIGN, mem_idx);
/*
* High and low need to be switched here because this is not actually a
@@ -656,7 +619,7 @@ void HELPER(casp_le_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
assert(HAVE_CMPXCHG128);
mem_idx = cpu_mmu_index(env, false);
- oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
+ oi = make_memop_idx(MO_LE | MO_128 | MO_ALIGN, mem_idx);
cmpv = int128_make128(env->xregs[rs], env->xregs[rs + 1]);
newv = int128_make128(new_lo, new_hi);
@@ -677,7 +640,7 @@ void HELPER(casp_be_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
assert(HAVE_CMPXCHG128);
mem_idx = cpu_mmu_index(env, false);
- oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
+ oi = make_memop_idx(MO_LE | MO_128 | MO_ALIGN, mem_idx);
cmpv = int128_make128(env->xregs[rs + 1], env->xregs[rs]);
newv = int128_make128(new_lo, new_hi);
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
index 62aa12c9d8..2c9922dc29 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/m_helper.c
@@ -1947,9 +1947,9 @@ static bool do_v7m_function_return(ARMCPU *cpu)
* do them as secure, so work out what MMU index that is.
*/
mmu_idx = arm_v7m_mmu_idx_for_secstate(env, true);
- oi = make_memop_idx(MO_LE, arm_to_core_mmu_idx(mmu_idx));
- newpc = helper_le_ldul_mmu(env, frameptr, oi, 0);
- newpsr = helper_le_ldul_mmu(env, frameptr + 4, oi, 0);
+ oi = make_memop_idx(MO_LEUL, arm_to_core_mmu_idx(mmu_idx));
+ newpc = cpu_ldl_le_mmu(env, frameptr, oi, 0);
+ newpsr = cpu_ldl_le_mmu(env, frameptr + 4, oi, 0);
/* Consistency checks on new IPSR */
newpsr_exc = newpsr & XPSR_EXCP;
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index f7d043865b..f90c187888 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -141,6 +141,15 @@ static inline void cpu_get_tb_cpu_state(CPUHexagonState *env, target_ulong *pc,
#endif
}
+static inline int cpu_mmu_index(CPUHexagonState *env, bool ifetch)
+{
+#ifdef CONFIG_USER_ONLY
+ return MMU_USER_IDX;
+#else
+#error System mode not supported on Hexagon yet
+#endif
+}
+
typedef struct CPUHexagonState CPUArchState;
typedef HexagonCPU ArchCPU;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index a7b1b6aa93..fc3ed80ef1 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -26,7 +26,8 @@
#include "sysemu/reset.h"
#include "sysemu/hvf.h"
#include "kvm/kvm_i386.h"
-#include "sev_i386.h"
+#include "sev.h"
+#include "qapi/error.h"
#include "qapi/qapi-visit-machine.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qapi-commands-machine-target.h"
@@ -5763,12 +5764,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*edx = 0;
break;
case 0x8000001F:
- *eax = sev_enabled() ? 0x2 : 0;
- *eax |= sev_es_enabled() ? 0x8 : 0;
- *ebx = sev_get_cbit_position();
- *ebx |= sev_get_reduced_phys_bits() << 6;
- *ecx = 0;
- *edx = 0;
+ *eax = *ebx = *ecx = *edx = 0;
+ if (sev_enabled()) {
+ *eax = 0x2;
+ *eax |= sev_es_enabled() ? 0x8 : 0;
+ *ebx = sev_get_cbit_position();
+ *ebx |= sev_get_reduced_phys_bits() << 6;
+ }
break;
default:
/* reserved values: zero */
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index f25837f63f..0eb7a0340c 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -28,7 +28,7 @@
#include "sysemu/kvm_int.h"
#include "sysemu/runstate.h"
#include "kvm_i386.h"
-#include "sev_i386.h"
+#include "sev.h"
#include "hyperv.h"
#include "hyperv-proto.h"
@@ -44,7 +44,6 @@
#include "hw/i386/intel_iommu.h"
#include "hw/i386/x86-iommu.h"
#include "hw/i386/e820_memory_layout.h"
-#include "sysemu/sev.h"
#include "hw/pci/pci.h"
#include "hw/pci/msi.h"
diff --git a/target/i386/kvm/meson.build b/target/i386/kvm/meson.build
index 0a533411ca..736df8b72e 100644
--- a/target/i386/kvm/meson.build
+++ b/target/i386/kvm/meson.build
@@ -1,8 +1,14 @@
i386_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
-i386_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files(
+i386_softmmu_kvm_ss = ss.source_set()
+
+i386_softmmu_kvm_ss.add(files(
'kvm.c',
'kvm-cpu.c',
))
+i386_softmmu_kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c'))
+
i386_softmmu_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
+
+i386_softmmu_ss.add_all(when: 'CONFIG_KVM', if_true: i386_softmmu_kvm_ss)
diff --git a/target/i386/kvm/sev-stub.c b/target/i386/kvm/sev-stub.c
new file mode 100644
index 0000000000..6080c007a2
--- /dev/null
+++ b/target/i386/kvm/sev-stub.c
@@ -0,0 +1,22 @@
+/*
+ * QEMU SEV stub
+ *
+ * Copyright Advanced Micro Devices 2018
+ *
+ * Authors:
+ * Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "sev.h"
+
+int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
+{
+ /* If we get here, cgs must be some non-SEV thing */
+ return 0;
+}
diff --git a/target/i386/meson.build b/target/i386/meson.build
index dac19ec00d..ae38dc9563 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -6,7 +6,7 @@ i386_ss.add(files(
'xsave_helper.c',
'cpu-dump.c',
))
-i386_ss.add(when: 'CONFIG_SEV', if_true: files('host-cpu.c', 'sev.c'), if_false: files('sev-stub.c'))
+i386_ss.add(when: 'CONFIG_SEV', if_true: files('host-cpu.c'))
# x86 cpu type
i386_ss.add(when: 'CONFIG_KVM', if_true: files('host-cpu.c'))
@@ -20,6 +20,8 @@ i386_softmmu_ss.add(files(
'monitor.c',
'cpu-sysemu.c',
))
+i386_softmmu_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'), if_false: files('sev-sysemu-stub.c'))
+
i386_user_ss = ss.source_set()
subdir('kvm')
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 196c1c9e77..8166e17693 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -28,14 +28,12 @@
#include "monitor/hmp-target.h"
#include "monitor/hmp.h"
#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qerror.h"
#include "sysemu/kvm.h"
-#include "sysemu/sev.h"
#include "qapi/error.h"
-#include "sev_i386.h"
#include "qapi/qapi-commands-misc-target.h"
#include "qapi/qapi-commands-misc.h"
#include "hw/i386/pc.h"
-#include "hw/i386/sgx.h"
/* Perform linear address sign extension */
static hwaddr addr_canonical(CPUArchState *env, hwaddr addr)
@@ -675,123 +673,3 @@ void hmp_info_io_apic(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "This command is obsolete and will be "
"removed soon. Please use 'info pic' instead.\n");
}
-
-SevInfo *qmp_query_sev(Error **errp)
-{
- SevInfo *info;
-
- info = sev_get_info();
- if (!info) {
- error_setg(errp, "SEV feature is not available");
- return NULL;
- }
-
- return info;
-}
-
-void hmp_info_sev(Monitor *mon, const QDict *qdict)
-{
- SevInfo *info = sev_get_info();
-
- if (info && info->enabled) {
- monitor_printf(mon, "handle: %d\n", info->handle);
- monitor_printf(mon, "state: %s\n", SevState_str(info->state));
- monitor_printf(mon, "build: %d\n", info->build_id);
- monitor_printf(mon, "api version: %d.%d\n",
- info->api_major, info->api_minor);
- monitor_printf(mon, "debug: %s\n",
- info->policy & SEV_POLICY_NODBG ? "off" : "on");
- monitor_printf(mon, "key-sharing: %s\n",
- info->policy & SEV_POLICY_NOKS ? "off" : "on");
- } else {
- monitor_printf(mon, "SEV is not enabled\n");
- }
-
- qapi_free_SevInfo(info);
-}
-
-SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp)
-{
- char *data;
- SevLaunchMeasureInfo *info;
-
- data = sev_get_launch_measurement();
- if (!data) {
- error_setg(errp, "Measurement is not available");
- return NULL;
- }
-
- info = g_malloc0(sizeof(*info));
- info->data = data;
-
- return info;
-}
-
-SevCapability *qmp_query_sev_capabilities(Error **errp)
-{
- return sev_get_capabilities(errp);
-}
-
-#define SEV_SECRET_GUID "4c2eb361-7d9b-4cc3-8081-127c90d3d294"
-struct sev_secret_area {
- uint32_t base;
- uint32_t size;
-};
-
-void qmp_sev_inject_launch_secret(const char *packet_hdr,
- const char *secret,
- bool has_gpa, uint64_t gpa,
- Error **errp)
-{
- if (!has_gpa) {
- uint8_t *data;
- struct sev_secret_area *area;
-
- if (!pc_system_ovmf_table_find(SEV_SECRET_GUID, &data, NULL)) {
- error_setg(errp, "SEV: no secret area found in OVMF,"
- " gpa must be specified.");
- return;
- }
- area = (struct sev_secret_area *)data;
- gpa = area->base;
- }
-
- sev_inject_launch_secret(packet_hdr, secret, gpa, errp);
-}
-
-SevAttestationReport *
-qmp_query_sev_attestation_report(const char *mnonce, Error **errp)
-{
- return sev_get_attestation_report(mnonce, errp);
-}
-
-SGXInfo *qmp_query_sgx(Error **errp)
-{
- return sgx_get_info(errp);
-}
-
-void hmp_info_sgx(Monitor *mon, const QDict *qdict)
-{
- Error *err = NULL;
- g_autoptr(SGXInfo) info = qmp_query_sgx(&err);
-
- if (err) {
- error_report_err(err);
- return;
- }
- monitor_printf(mon, "SGX support: %s\n",
- info->sgx ? "enabled" : "disabled");
- monitor_printf(mon, "SGX1 support: %s\n",
- info->sgx1 ? "enabled" : "disabled");
- monitor_printf(mon, "SGX2 support: %s\n",
- info->sgx2 ? "enabled" : "disabled");
- monitor_printf(mon, "FLC support: %s\n",
- info->flc ? "enabled" : "disabled");
- monitor_printf(mon, "size: %" PRIu64 "\n",
- info->section_size);
-}
-
-SGXInfo *qmp_query_sgx_capabilities(Error **errp)
-{
- return sgx_get_capabilities(errp);
-}
diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c
deleted file mode 100644
index d8e6583171..0000000000
--- a/target/i386/sev-stub.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * QEMU SEV stub
- *
- * Copyright Advanced Micro Devices 2018
- *
- * Authors:
- * Brijesh Singh <brijesh.singh@amd.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "sev_i386.h"
-
-SevInfo *sev_get_info(void)
-{
- return NULL;
-}
-
-bool sev_enabled(void)
-{
- return false;
-}
-
-uint64_t sev_get_me_mask(void)
-{
- return ~0;
-}
-
-uint32_t sev_get_cbit_position(void)
-{
- return 0;
-}
-
-uint32_t sev_get_reduced_phys_bits(void)
-{
- return 0;
-}
-
-char *sev_get_launch_measurement(void)
-{
- return NULL;
-}
-
-SevCapability *sev_get_capabilities(Error **errp)
-{
- error_setg(errp, "SEV is not available in this QEMU");
- return NULL;
-}
-
-int sev_inject_launch_secret(const char *hdr, const char *secret,
- uint64_t gpa, Error **errp)
-{
- return 1;
-}
-
-int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
-{
- return 0;
-}
-
-bool sev_es_enabled(void)
-{
- return false;
-}
-
-void sev_es_set_reset_vector(CPUState *cpu)
-{
-}
-
-int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size)
-{
- abort();
-}
-
-SevAttestationReport *
-sev_get_attestation_report(const char *mnonce, Error **errp)
-{
- error_setg(errp, "SEV is not available in this QEMU");
- return NULL;
-}
-
-bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
-{
- g_assert_not_reached();
-}
diff --git a/target/i386/sev-sysemu-stub.c b/target/i386/sev-sysemu-stub.c
new file mode 100644
index 0000000000..7a29295d1e
--- /dev/null
+++ b/target/i386/sev-sysemu-stub.c
@@ -0,0 +1,70 @@
+/*
+ * QEMU SEV system stub
+ *
+ * Copyright Advanced Micro Devices 2018
+ *
+ * Authors:
+ * Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "monitor/monitor.h"
+#include "monitor/hmp-target.h"
+#include "qapi/qapi-commands-misc-target.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi/error.h"
+#include "sev.h"
+
+SevInfo *qmp_query_sev(Error **errp)
+{
+ error_setg(errp, "SEV is not available in this QEMU");
+ return NULL;
+}
+
+SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp)
+{
+ error_setg(errp, "SEV is not available in this QEMU");
+ return NULL;
+}
+
+SevCapability *qmp_query_sev_capabilities(Error **errp)
+{
+ error_setg(errp, "SEV is not available in this QEMU");
+ return NULL;
+}
+
+void qmp_sev_inject_launch_secret(const char *packet_header, const char *secret,
+ bool has_gpa, uint64_t gpa, Error **errp)
+{
+ error_setg(errp, "SEV is not available in this QEMU");
+}
+
+int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
+{
+ g_assert_not_reached();
+}
+
+void sev_es_set_reset_vector(CPUState *cpu)
+{
+}
+
+int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size)
+{
+ g_assert_not_reached();
+}
+
+SevAttestationReport *qmp_query_sev_attestation_report(const char *mnonce,
+ Error **errp)
+{
+ error_setg(errp, "SEV is not available in this QEMU");
+ return NULL;
+}
+
+void hmp_info_sev(Monitor *mon, const QDict *qdict)
+{
+ monitor_printf(mon, "SEV is not available in this QEMU\n");
+}
diff --git a/target/i386/sev.c b/target/i386/sev.c
index bcd9260fa4..eede07f11d 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -25,13 +25,16 @@
#include "qemu/uuid.h"
#include "crypto/hash.h"
#include "sysemu/kvm.h"
-#include "sev_i386.h"
+#include "sev.h"
#include "sysemu/sysemu.h"
#include "sysemu/runstate.h"
#include "trace.h"
#include "migration/blocker.h"
#include "qom/object.h"
#include "monitor/monitor.h"
+#include "monitor/hmp-target.h"
+#include "qapi/qapi-commands-misc-target.h"
+#include "qapi/qmp/qerror.h"
#include "exec/confidential-guest-support.h"
#include "hw/i386/pc.h"
@@ -65,7 +68,6 @@ struct SevGuestState {
uint8_t api_major;
uint8_t api_minor;
uint8_t build_id;
- uint64_t me_mask;
int sev_fd;
SevState state;
gchar *measurement;
@@ -389,12 +391,6 @@ sev_es_enabled(void)
return sev_enabled() && (sev_guest->policy & SEV_POLICY_ES);
}
-uint64_t
-sev_get_me_mask(void)
-{
- return sev_guest ? sev_guest->me_mask : ~0;
-}
-
uint32_t
sev_get_cbit_position(void)
{
@@ -407,8 +403,7 @@ sev_get_reduced_phys_bits(void)
return sev_guest ? sev_guest->reduced_phys_bits : 0;
}
-SevInfo *
-sev_get_info(void)
+static SevInfo *sev_get_info(void)
{
SevInfo *info;
@@ -427,6 +422,40 @@ sev_get_info(void)
return info;
}
+SevInfo *qmp_query_sev(Error **errp)
+{
+ SevInfo *info;
+
+ info = sev_get_info();
+ if (!info) {
+ error_setg(errp, "SEV feature is not available");
+ return NULL;
+ }
+
+ return info;
+}
+
+void hmp_info_sev(Monitor *mon, const QDict *qdict)
+{
+ SevInfo *info = sev_get_info();
+
+ if (info && info->enabled) {
+ monitor_printf(mon, "handle: %d\n", info->handle);
+ monitor_printf(mon, "state: %s\n", SevState_str(info->state));
+ monitor_printf(mon, "build: %d\n", info->build_id);
+ monitor_printf(mon, "api version: %d.%d\n",
+ info->api_major, info->api_minor);
+ monitor_printf(mon, "debug: %s\n",
+ info->policy & SEV_POLICY_NODBG ? "off" : "on");
+ monitor_printf(mon, "key-sharing: %s\n",
+ info->policy & SEV_POLICY_NOKS ? "off" : "on");
+ } else {
+ monitor_printf(mon, "SEV is not enabled\n");
+ }
+
+ qapi_free_SevInfo(info);
+}
+
static int
sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
size_t *cert_chain_len, Error **errp)
@@ -440,7 +469,8 @@ sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
if (r < 0) {
if (err != SEV_RET_INVALID_LEN) {
- error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
+ error_setg(errp, "SEV: Failed to export PDH cert"
+ " ret=%d fw_err=%d (%s)",
r, err, fw_error_to_str(err));
return 1;
}
@@ -453,7 +483,7 @@ sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
if (r < 0) {
- error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
+ error_setg(errp, "SEV: Failed to export PDH cert ret=%d fw_err=%d (%s)",
r, err, fw_error_to_str(err));
goto e_free;
}
@@ -470,8 +500,7 @@ e_free:
return 1;
}
-SevCapability *
-sev_get_capabilities(Error **errp)
+static SevCapability *sev_get_capabilities(Error **errp)
{
SevCapability *cap = NULL;
guchar *pdh_data = NULL;
@@ -491,7 +520,7 @@ sev_get_capabilities(Error **errp)
fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
if (fd < 0) {
- error_setg_errno(errp, errno, "Failed to open %s",
+ error_setg_errno(errp, errno, "SEV: Failed to open %s",
DEFAULT_SEV_DEVICE);
return NULL;
}
@@ -521,14 +550,19 @@ out:
return cap;
}
-SevAttestationReport *
-sev_get_attestation_report(const char *mnonce, Error **errp)
+SevCapability *qmp_query_sev_capabilities(Error **errp)
+{
+ return sev_get_capabilities(errp);
+}
+
+static SevAttestationReport *sev_get_attestation_report(const char *mnonce,
+ Error **errp)
{
struct kvm_sev_attestation_report input = {};
SevAttestationReport *report = NULL;
SevGuestState *sev = sev_guest;
- guchar *data;
- guchar *buf;
+ g_autofree guchar *data = NULL;
+ g_autofree guchar *buf = NULL;
gsize len;
int err = 0, ret;
@@ -548,7 +582,6 @@ sev_get_attestation_report(const char *mnonce, Error **errp)
if (len != sizeof(input.mnonce)) {
error_setg(errp, "SEV: mnonce must be %zu bytes (got %" G_GSIZE_FORMAT ")",
sizeof(input.mnonce), len);
- g_free(buf);
return NULL;
}
@@ -557,9 +590,9 @@ sev_get_attestation_report(const char *mnonce, Error **errp)
&input, &err);
if (ret < 0) {
if (err != SEV_RET_INVALID_LEN) {
- error_setg(errp, "failed to query the attestation report length "
- "ret=%d fw_err=%d (%s)", ret, err, fw_error_to_str(err));
- g_free(buf);
+ error_setg(errp, "SEV: Failed to query the attestation report"
+ " length ret=%d fw_err=%d (%s)",
+ ret, err, fw_error_to_str(err));
return NULL;
}
}
@@ -572,9 +605,9 @@ sev_get_attestation_report(const char *mnonce, Error **errp)
ret = sev_ioctl(sev->sev_fd, KVM_SEV_GET_ATTESTATION_REPORT,
&input, &err);
if (ret) {
- error_setg_errno(errp, errno, "Failed to get attestation report"
+ error_setg_errno(errp, errno, "SEV: Failed to get attestation report"
" ret=%d fw_err=%d (%s)", ret, err, fw_error_to_str(err));
- goto e_free_data;
+ return NULL;
}
report = g_new0(SevAttestationReport, 1);
@@ -582,12 +615,15 @@ sev_get_attestation_report(const char *mnonce, Error **errp)
trace_kvm_sev_attestation_report(mnonce, report->data);
-e_free_data:
- g_free(data);
- g_free(buf);
return report;
}
+SevAttestationReport *qmp_query_sev_attestation_report(const char *mnonce,
+ Error **errp)
+{
+ return sev_get_attestation_report(mnonce, errp);
+}
+
static int
sev_read_file_base64(const char *filename, guchar **data, gsize *len)
{
@@ -596,7 +632,7 @@ sev_read_file_base64(const char *filename, guchar **data, gsize *len)
GError *error = NULL;
if (!g_file_get_contents(filename, &base64, &sz, &error)) {
- error_report("failed to read '%s' (%s)", filename, error->message);
+ error_report("SEV: Failed to read '%s' (%s)", filename, error->message);
g_error_free(error);
return -1;
}
@@ -611,31 +647,29 @@ sev_launch_start(SevGuestState *sev)
gsize sz;
int ret = 1;
int fw_error, rc;
- struct kvm_sev_launch_start *start;
+ struct kvm_sev_launch_start start = {
+ .handle = sev->handle, .policy = sev->policy
+ };
guchar *session = NULL, *dh_cert = NULL;
- start = g_new0(struct kvm_sev_launch_start, 1);
-
- start->handle = sev->handle;
- start->policy = sev->policy;
if (sev->session_file) {
if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
goto out;
}
- start->session_uaddr = (unsigned long)session;
- start->session_len = sz;
+ start.session_uaddr = (unsigned long)session;
+ start.session_len = sz;
}
if (sev->dh_cert_file) {
if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
goto out;
}
- start->dh_uaddr = (unsigned long)dh_cert;
- start->dh_len = sz;
+ start.dh_uaddr = (unsigned long)dh_cert;
+ start.dh_len = sz;
}
- trace_kvm_sev_launch_start(start->policy, session, dh_cert);
- rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
+ trace_kvm_sev_launch_start(start.policy, session, dh_cert);
+ rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, &start, &fw_error);
if (rc < 0) {
error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
__func__, ret, fw_error, fw_error_to_str(fw_error));
@@ -643,11 +677,10 @@ sev_launch_start(SevGuestState *sev)
}
sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
- sev->handle = start->handle;
+ sev->handle = start.handle;
ret = 0;
out:
- g_free(start);
g_free(session);
g_free(dh_cert);
return ret;
@@ -695,8 +728,8 @@ sev_launch_get_measure(Notifier *notifier, void *unused)
{
SevGuestState *sev = sev_guest;
int ret, error;
- guchar *data;
- struct kvm_sev_launch_measure *measurement;
+ g_autofree guchar *data = NULL;
+ struct kvm_sev_launch_measure measurement = {};
if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
return;
@@ -710,43 +743,35 @@ sev_launch_get_measure(Notifier *notifier, void *unused)
}
}
- measurement = g_new0(struct kvm_sev_launch_measure, 1);
-
/* query the measurement blob length */
ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
- measurement, &error);
- if (!measurement->len) {
+ &measurement, &error);
+ if (!measurement.len) {
error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
__func__, ret, error, fw_error_to_str(errno));
- goto free_measurement;
+ return;
}
- data = g_new0(guchar, measurement->len);
- measurement->uaddr = (unsigned long)data;
+ data = g_new0(guchar, measurement.len);
+ measurement.uaddr = (unsigned long)data;
/* get the measurement blob */
ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
- measurement, &error);
+ &measurement, &error);
if (ret) {
error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
__func__, ret, error, fw_error_to_str(errno));
- goto free_data;
+ return;
}
sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
/* encode the measurement value and emit the event */
- sev->measurement = g_base64_encode(data, measurement->len);
+ sev->measurement = g_base64_encode(data, measurement.len);
trace_kvm_sev_launch_measurement(sev->measurement);
-
-free_data:
- g_free(data);
-free_measurement:
- g_free(measurement);
}
-char *
-sev_get_launch_measurement(void)
+static char *sev_get_launch_measurement(void)
{
if (sev_guest &&
sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
@@ -756,6 +781,23 @@ sev_get_launch_measurement(void)
return NULL;
}
+SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp)
+{
+ char *data;
+ SevLaunchMeasureInfo *info;
+
+ data = sev_get_launch_measurement();
+ if (!data) {
+ error_setg(errp, "SEV launch measurement is not available");
+ return NULL;
+ }
+
+ info = g_malloc0(sizeof(*info));
+ info->data = data;
+
+ return info;
+}
+
static Notifier sev_machine_done_notify = {
.notify = sev_launch_get_measure,
};
@@ -831,8 +873,6 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
goto err;
}
- sev->me_mask = ~(1UL << sev->cbitpos);
-
devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
sev->sev_fd = open(devname, O_RDWR);
if (sev->sev_fd < 0) {
@@ -911,7 +951,7 @@ sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
if (sev_check_state(sev_guest, SEV_STATE_LAUNCH_UPDATE)) {
int ret = sev_launch_update_data(sev_guest, ptr, len);
if (ret < 0) {
- error_setg(errp, "failed to encrypt pflash rom");
+ error_setg(errp, "SEV: Failed to encrypt pflash rom");
return ret;
}
}
@@ -930,7 +970,7 @@ int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
MemoryRegion *mr = NULL;
if (!sev_guest) {
- error_setg(errp, "SEV: SEV not enabled.");
+ error_setg(errp, "SEV not enabled for guest");
return 1;
}
@@ -982,6 +1022,37 @@ int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
return 0;
}
+#define SEV_SECRET_GUID "4c2eb361-7d9b-4cc3-8081-127c90d3d294"
+struct sev_secret_area {
+ uint32_t base;
+ uint32_t size;
+};
+
+void qmp_sev_inject_launch_secret(const char *packet_hdr,
+ const char *secret,
+ bool has_gpa, uint64_t gpa,
+ Error **errp)
+{
+ if (!sev_enabled()) {
+ error_setg(errp, "SEV not enabled for guest");
+ return;
+ }
+ if (!has_gpa) {
+ uint8_t *data;
+ struct sev_secret_area *area;
+
+ if (!pc_system_ovmf_table_find(SEV_SECRET_GUID, &data, NULL)) {
+ error_setg(errp, "SEV: no secret area found in OVMF,"
+ " gpa must be specified.");
+ return;
+ }
+ area = (struct sev_secret_area *)data;
+ gpa = area->base;
+ }
+
+ sev_inject_launch_secret(packet_hdr, secret, gpa, errp);
+}
+
static int
sev_es_parse_reset_block(SevInfoBlock *info, uint32_t *addr)
{
diff --git a/target/i386/sev_i386.h b/target/i386/sev.h
index 2afe108069..83e82aa42c 100644
--- a/target/i386/sev_i386.h
+++ b/target/i386/sev.h
@@ -14,12 +14,11 @@
#ifndef QEMU_SEV_I386_H
#define QEMU_SEV_I386_H
-#include "qom/object.h"
-#include "qapi/error.h"
-#include "sysemu/kvm.h"
-#include "sysemu/sev.h"
-#include "qemu/error-report.h"
-#include "qapi/qapi-types-misc-target.h"
+#ifndef CONFIG_USER_ONLY
+#include CONFIG_DEVICES /* CONFIG_SEV */
+#endif
+
+#include "exec/confidential-guest-support.h"
#define SEV_POLICY_NODBG 0x1
#define SEV_POLICY_NOKS 0x2
@@ -39,15 +38,25 @@ typedef struct SevKernelLoaderContext {
size_t cmdline_size;
} SevKernelLoaderContext;
-extern bool sev_es_enabled(void);
-extern uint64_t sev_get_me_mask(void);
-extern SevInfo *sev_get_info(void);
+#ifdef CONFIG_SEV
+bool sev_enabled(void);
+bool sev_es_enabled(void);
+#else
+#define sev_enabled() 0
+#define sev_es_enabled() 0
+#endif
+
extern uint32_t sev_get_cbit_position(void);
extern uint32_t sev_get_reduced_phys_bits(void);
-extern char *sev_get_launch_measurement(void);
-extern SevCapability *sev_get_capabilities(Error **errp);
-extern SevAttestationReport *
-sev_get_attestation_report(const char *mnonce, Error **errp);
extern bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp);
+int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp);
+int sev_inject_launch_secret(const char *hdr, const char *secret,
+ uint64_t gpa, Error **errp);
+
+int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size);
+void sev_es_set_reset_vector(CPUState *cpu);
+
+int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
+
#endif
diff --git a/target/i386/tcg/mem_helper.c b/target/i386/tcg/mem_helper.c
index 0fd696f9c1..a207e624cb 100644
--- a/target/i386/tcg/mem_helper.c
+++ b/target/i386/tcg/mem_helper.c
@@ -136,7 +136,7 @@ void helper_cmpxchg16b(CPUX86State *env, target_ulong a0)
Int128 newv = int128_make128(env->regs[R_EBX], env->regs[R_ECX]);
int mem_idx = cpu_mmu_index(env, false);
- MemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
+ MemOpIdx oi = make_memop_idx(MO_TE | MO_128 | MO_ALIGN, mem_idx);
Int128 oldv = cpu_atomic_cmpxchgo_le_mmu(env, a0, cmpv, newv, oi, ra);
if (int128_eq(oldv, cmpv)) {
diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index c1bf73b6f9..cfbc987ba6 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -22,7 +22,6 @@
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
#include "semihosting/semihost.h"
-#include "tcg/tcg.h"
#if !defined(CONFIG_USER_ONLY)
diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c
index 167d9a591c..e40c1b7057 100644
--- a/target/mips/tcg/msa_helper.c
+++ b/target/mips/tcg/msa_helper.c
@@ -8218,178 +8218,86 @@ void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
#define MEMOP_IDX(DF)
#endif
+#ifdef TARGET_WORDS_BIGENDIAN
+static inline uint64_t bswap16x4(uint64_t x)
+{
+ uint64_t m = 0x00ff00ff00ff00ffull;
+ return ((x & m) << 8) | ((x >> 8) & m);
+}
+
+static inline uint64_t bswap32x2(uint64_t x)
+{
+ return ror64(bswap64(x), 32);
+}
+#endif
+
void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- MEMOP_IDX(DF_BYTE)
-#if !defined(CONFIG_USER_ONLY)
-#if !defined(HOST_WORDS_BIGENDIAN)
- pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
- pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
- pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
- pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
- pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
- pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
- pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
- pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
- pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
- pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
- pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
- pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
- pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
- pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
- pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
- pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
-#else
- pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
- pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
- pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
- pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
- pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
- pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
- pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
- pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
- pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
- pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
- pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
- pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
- pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
- pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
- pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
- pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
-#endif
-#else
-#if !defined(HOST_WORDS_BIGENDIAN)
- pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
- pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
- pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
- pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
- pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
- pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
- pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
- pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
- pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
- pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
- pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
- pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
- pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
- pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
- pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
- pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
-#else
- pwd->b[0] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
- pwd->b[1] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
- pwd->b[2] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
- pwd->b[3] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
- pwd->b[4] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
- pwd->b[5] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
- pwd->b[6] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
- pwd->b[7] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
- pwd->b[8] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
- pwd->b[9] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
- pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
- pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
- pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
- pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
- pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
- pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
-#endif
-#endif
+ uintptr_t ra = GETPC();
+ uint64_t d0, d1;
+
+ /* Load 8 bytes at a time. Vector element ordering makes this LE. */
+ d0 = cpu_ldq_le_data_ra(env, addr + 0, ra);
+ d1 = cpu_ldq_le_data_ra(env, addr + 8, ra);
+ pwd->d[0] = d0;
+ pwd->d[1] = d1;
}
void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- MEMOP_IDX(DF_HALF)
-#if !defined(CONFIG_USER_ONLY)
-#if !defined(HOST_WORDS_BIGENDIAN)
- pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
- pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
- pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
- pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
- pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
- pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
- pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
- pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
-#else
- pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
- pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
- pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
- pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
- pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
- pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
- pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
- pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
-#endif
-#else
-#if !defined(HOST_WORDS_BIGENDIAN)
- pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF));
- pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF));
- pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF));
- pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF));
- pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF));
- pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF));
- pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF));
- pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF));
-#else
- pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF));
- pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF));
- pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF));
- pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF));
- pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF));
- pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF));
- pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF));
- pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF));
-#endif
+ uintptr_t ra = GETPC();
+ uint64_t d0, d1;
+
+ /*
+ * Load 8 bytes at a time. Use little-endian load, then for
+ * big-endian target, we must then swap the four halfwords.
+ */
+ d0 = cpu_ldq_le_data_ra(env, addr + 0, ra);
+ d1 = cpu_ldq_le_data_ra(env, addr + 8, ra);
+#ifdef TARGET_WORDS_BIGENDIAN
+ d0 = bswap16x4(d0);
+ d1 = bswap16x4(d1);
#endif
+ pwd->d[0] = d0;
+ pwd->d[1] = d1;
}
void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- MEMOP_IDX(DF_WORD)
-#if !defined(CONFIG_USER_ONLY)
-#if !defined(HOST_WORDS_BIGENDIAN)
- pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
- pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
- pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
- pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
-#else
- pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
- pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
- pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
- pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
-#endif
-#else
-#if !defined(HOST_WORDS_BIGENDIAN)
- pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD));
- pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD));
- pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD));
- pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD));
-#else
- pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD));
- pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD));
- pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD));
- pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD));
-#endif
+ uintptr_t ra = GETPC();
+ uint64_t d0, d1;
+
+ /*
+ * Load 8 bytes at a time. Use little-endian load, then for
+ * big-endian target, we must then bswap the two words.
+ */
+ d0 = cpu_ldq_le_data_ra(env, addr + 0, ra);
+ d1 = cpu_ldq_le_data_ra(env, addr + 8, ra);
+#ifdef TARGET_WORDS_BIGENDIAN
+ d0 = bswap32x2(d0);
+ d1 = bswap32x2(d1);
#endif
+ pwd->d[0] = d0;
+ pwd->d[1] = d1;
}
void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd,
target_ulong addr)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- MEMOP_IDX(DF_DOUBLE)
-#if !defined(CONFIG_USER_ONLY)
- pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC());
- pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC());
-#else
- pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE));
- pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE));
-#endif
+ uintptr_t ra = GETPC();
+ uint64_t d0, d1;
+
+ d0 = cpu_ldq_data_ra(env, addr + 0, ra);
+ d1 = cpu_ldq_data_ra(env, addr + 8, ra);
+ pwd->d[0] = d0;
+ pwd->d[1] = d1;
}
#define MSA_PAGESPAN(x) \
@@ -8415,82 +8323,13 @@ void helper_msa_st_b(CPUMIPSState *env, uint32_t wd,
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
int mmu_idx = cpu_mmu_index(env, false);
+ uintptr_t ra = GETPC();
- MEMOP_IDX(DF_BYTE)
- ensure_writable_pages(env, addr, mmu_idx, GETPC());
-#if !defined(CONFIG_USER_ONLY)
-#if !defined(HOST_WORDS_BIGENDIAN)
- helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[0], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[1], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[2], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[3], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[4], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[5], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[6], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[7], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[8], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[9], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC());
-#else
- helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[0], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[1], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[2], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[3], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[4], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[5], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[6], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[7], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[14], oi, GETPC());
- helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[15], oi, GETPC());
-#endif
-#else
-#if !defined(HOST_WORDS_BIGENDIAN)
- cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[0]);
- cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[1]);
- cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[2]);
- cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[3]);
- cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[4]);
- cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[5]);
- cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[6]);
- cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[7]);
- cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[8]);
- cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[9]);
- cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]);
- cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]);
- cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]);
- cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]);
- cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]);
- cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]);
-#else
- cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[0]);
- cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[1]);
- cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[2]);
- cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[3]);
- cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[4]);
- cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[5]);
- cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[6]);
- cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[7]);
- cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]);
- cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]);
- cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]);
- cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]);
- cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]);
- cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]);
- cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[14]);
- cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[15]);
-#endif
-#endif
+ ensure_writable_pages(env, addr, mmu_idx, ra);
+
+ /* Store 8 bytes at a time. Vector element ordering makes this LE. */
+ cpu_stq_le_data_ra(env, addr + 0, pwd->d[0], ra);
+ cpu_stq_le_data_ra(env, addr + 0, pwd->d[1], ra);
}
void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
@@ -8498,50 +8337,20 @@ void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
int mmu_idx = cpu_mmu_index(env, false);
+ uintptr_t ra = GETPC();
+ uint64_t d0, d1;
- MEMOP_IDX(DF_HALF)
- ensure_writable_pages(env, addr, mmu_idx, GETPC());
-#if !defined(CONFIG_USER_ONLY)
-#if !defined(HOST_WORDS_BIGENDIAN)
- helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC());
-#else
- helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC());
- helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC());
-#endif
-#else
-#if !defined(HOST_WORDS_BIGENDIAN)
- cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]);
- cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]);
- cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]);
- cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]);
- cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]);
- cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]);
- cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]);
- cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]);
-#else
- cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]);
- cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]);
- cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]);
- cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]);
- cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]);
- cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]);
- cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]);
- cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]);
-#endif
+ ensure_writable_pages(env, addr, mmu_idx, ra);
+
+ /* Store 8 bytes at a time. See helper_msa_ld_h. */
+ d0 = pwd->d[0];
+ d1 = pwd->d[1];
+#ifdef TARGET_WORDS_BIGENDIAN
+ d0 = bswap16x4(d0);
+ d1 = bswap16x4(d1);
#endif
+ cpu_stq_le_data_ra(env, addr + 0, d0, ra);
+ cpu_stq_le_data_ra(env, addr + 8, d1, ra);
}
void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
@@ -8549,34 +8358,20 @@ void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
int mmu_idx = cpu_mmu_index(env, false);
+ uintptr_t ra = GETPC();
+ uint64_t d0, d1;
- MEMOP_IDX(DF_WORD)
- ensure_writable_pages(env, addr, mmu_idx, GETPC());
-#if !defined(CONFIG_USER_ONLY)
-#if !defined(HOST_WORDS_BIGENDIAN)
- helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[0], oi, GETPC());
- helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[1], oi, GETPC());
- helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[2], oi, GETPC());
- helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[3], oi, GETPC());
-#else
- helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[0], oi, GETPC());
- helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[1], oi, GETPC());
- helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[2], oi, GETPC());
- helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[3], oi, GETPC());
-#endif
-#else
-#if !defined(HOST_WORDS_BIGENDIAN)
- cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[0]);
- cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[1]);
- cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[2]);
- cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[3]);
-#else
- cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[0]);
- cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[1]);
- cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[2]);
- cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[3]);
-#endif
+ ensure_writable_pages(env, addr, mmu_idx, ra);
+
+ /* Store 8 bytes at a time. See helper_msa_ld_w. */
+ d0 = pwd->d[0];
+ d1 = pwd->d[1];
+#ifdef TARGET_WORDS_BIGENDIAN
+ d0 = bswap32x2(d0);
+ d1 = bswap32x2(d1);
#endif
+ cpu_stq_le_data_ra(env, addr + 0, d0, ra);
+ cpu_stq_le_data_ra(env, addr + 8, d1, ra);
}
void helper_msa_st_d(CPUMIPSState *env, uint32_t wd,
@@ -8584,14 +8379,10 @@ void helper_msa_st_d(CPUMIPSState *env, uint32_t wd,
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
int mmu_idx = cpu_mmu_index(env, false);
+ uintptr_t ra = GETPC();
- MEMOP_IDX(DF_DOUBLE)
ensure_writable_pages(env, addr, mmu_idx, GETPC());
-#if !defined(CONFIG_USER_ONLY)
- helper_ret_stq_mmu(env, addr + (0 << DF_DOUBLE), pwd->d[0], oi, GETPC());
- helper_ret_stq_mmu(env, addr + (1 << DF_DOUBLE), pwd->d[1], oi, GETPC());
-#else
- cpu_stq_data(env, addr + (0 << DF_DOUBLE), pwd->d[0]);
- cpu_stq_data(env, addr + (1 << DF_DOUBLE), pwd->d[1]);
-#endif
+
+ cpu_stq_data_ra(env, addr + 0, pwd->d[0], ra);
+ cpu_stq_data_ra(env, addr + 8, pwd->d[1], ra);
}
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c
index e2282baa8d..39945d9ea5 100644
--- a/target/ppc/mem_helper.c
+++ b/target/ppc/mem_helper.c
@@ -25,7 +25,6 @@
#include "exec/helper-proto.h"
#include "helper_regs.h"
#include "exec/cpu_ldst.h"
-#include "tcg/tcg.h"
#include "internal.h"
#include "qemu/atomic128.h"
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index b985e9e55b..9ca78ee156 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3462,10 +3462,12 @@ static void gen_std(DisasContext *ctx)
if (HAVE_ATOMIC128) {
TCGv_i32 oi = tcg_temp_new_i32();
if (ctx->le_mode) {
- tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_LE | MO_128,
+ ctx->mem_idx));
gen_helper_stq_le_parallel(cpu_env, EA, lo, hi, oi);
} else {
- tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_BE | MO_128,
+ ctx->mem_idx));
gen_helper_stq_be_parallel(cpu_env, EA, lo, hi, oi);
}
tcg_temp_free_i32(oi);
@@ -4067,11 +4069,11 @@ static void gen_lqarx(DisasContext *ctx)
if (HAVE_ATOMIC128) {
TCGv_i32 oi = tcg_temp_new_i32();
if (ctx->le_mode) {
- tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ | MO_ALIGN_16,
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_LE | MO_128 | MO_ALIGN,
ctx->mem_idx));
gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
} else {
- tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ | MO_ALIGN_16,
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_BE | MO_128 | MO_ALIGN,
ctx->mem_idx));
gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
}
@@ -4122,7 +4124,7 @@ static void gen_stqcx_(DisasContext *ctx)
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
if (HAVE_CMPXCHG128) {
- TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_Q) | MO_ALIGN_16);
+ TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_128) | MO_ALIGN);
if (ctx->le_mode) {
gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env,
EA, lo, hi, oi);
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
index 75f6735545..17e3f83641 100644
--- a/target/s390x/tcg/mem_helper.c
+++ b/target/s390x/tcg/mem_helper.c
@@ -27,7 +27,6 @@
#include "exec/cpu_ldst.h"
#include "qemu/int128.h"
#include "qemu/atomic128.h"
-#include "tcg/tcg.h"
#include "trace.h"
#if !defined(CONFIG_USER_ONLY)
@@ -250,13 +249,13 @@ static void do_access_memset(CPUS390XState *env, vaddr vaddr, char *haddr,
* page. This is especially relevant to speed up TLB_NOTDIRTY.
*/
g_assert(size > 0);
- helper_ret_stb_mmu(env, vaddr, byte, oi, ra);
+ cpu_stb_mmu(env, vaddr, byte, oi, ra);
haddr = tlb_vaddr_to_host(env, vaddr, MMU_DATA_STORE, mmu_idx);
if (likely(haddr)) {
memset(haddr + 1, byte, size - 1);
} else {
for (i = 1; i < size; i++) {
- helper_ret_stb_mmu(env, vaddr + i, byte, oi, ra);
+ cpu_stb_mmu(env, vaddr + i, byte, oi, ra);
}
}
}
@@ -292,7 +291,7 @@ static uint8_t do_access_get_byte(CPUS390XState *env, vaddr vaddr, char **haddr,
* Do a single access and test if we can then get access to the
* page. This is especially relevant to speed up TLB_NOTDIRTY.
*/
- byte = helper_ret_ldub_mmu(env, vaddr + offset, oi, ra);
+ byte = cpu_ldb_mmu(env, vaddr + offset, oi, ra);
*haddr = tlb_vaddr_to_host(env, vaddr, MMU_DATA_LOAD, mmu_idx);
return byte;
#endif
@@ -326,7 +325,7 @@ static void do_access_set_byte(CPUS390XState *env, vaddr vaddr, char **haddr,
* Do a single access and test if we can then get access to the
* page. This is especially relevant to speed up TLB_NOTDIRTY.
*/
- helper_ret_stb_mmu(env, vaddr + offset, byte, oi, ra);
+ cpu_stb_mmu(env, vaddr + offset, byte, oi, ra);
*haddr = tlb_vaddr_to_host(env, vaddr, MMU_DATA_STORE, mmu_idx);
#endif
}
@@ -1811,7 +1810,7 @@ void HELPER(cdsg_parallel)(CPUS390XState *env, uint64_t addr,
assert(HAVE_CMPXCHG128);
mem_idx = cpu_mmu_index(env, false);
- oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
+ oi = make_memop_idx(MO_TE | MO_128 | MO_ALIGN, mem_idx);
oldv = cpu_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
fail = !int128_eq(oldv, cmpv);
@@ -1940,7 +1939,7 @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
cpu_stq_data_ra(env, a1 + 0, int128_gethi(nv), ra);
cpu_stq_data_ra(env, a1 + 8, int128_getlo(nv), ra);
} else if (HAVE_CMPXCHG128) {
- MemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
+ MemOpIdx oi = make_memop_idx(MO_TE | MO_128 | MO_ALIGN, mem_idx);
ov = cpu_atomic_cmpxchgo_be_mmu(env, a1, cv, nv, oi, ra);
cc = !int128_eq(ov, cv);
} else {
diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c
index abe2889d27..bbf3601cb1 100644
--- a/target/sparc/ldst_helper.c
+++ b/target/sparc/ldst_helper.c
@@ -1333,27 +1333,27 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
oi = make_memop_idx(memop, idx);
switch (size) {
case 1:
- ret = helper_ret_ldub_mmu(env, addr, oi, GETPC());
+ ret = cpu_ldb_mmu(env, addr, oi, GETPC());
break;
case 2:
if (asi & 8) {
- ret = helper_le_lduw_mmu(env, addr, oi, GETPC());
+ ret = cpu_ldw_le_mmu(env, addr, oi, GETPC());
} else {
- ret = helper_be_lduw_mmu(env, addr, oi, GETPC());
+ ret = cpu_ldw_be_mmu(env, addr, oi, GETPC());
}
break;
case 4:
if (asi & 8) {
- ret = helper_le_ldul_mmu(env, addr, oi, GETPC());
+ ret = cpu_ldl_le_mmu(env, addr, oi, GETPC());
} else {
- ret = helper_be_ldul_mmu(env, addr, oi, GETPC());
+ ret = cpu_ldl_be_mmu(env, addr, oi, GETPC());
}
break;
case 8:
if (asi & 8) {
- ret = helper_le_ldq_mmu(env, addr, oi, GETPC());
+ ret = cpu_ldq_le_mmu(env, addr, oi, GETPC());
} else {
- ret = helper_be_ldq_mmu(env, addr, oi, GETPC());
+ ret = cpu_ldq_be_mmu(env, addr, oi, GETPC());
}
break;
default: