aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/ppc/helper.h1
-rw-r--r--target/ppc/kvm.c59
-rw-r--r--target/ppc/misc_helper.c9
-rw-r--r--target/ppc/translate.c62
-rw-r--r--target/ppc/translate_init.inc.c11
5 files changed, 92 insertions, 50 deletions
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 19453c6813..d751f0e219 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -17,6 +17,7 @@ DEF_HELPER_2(pminsn, void, env, i32)
DEF_HELPER_1(rfid, void, env)
DEF_HELPER_1(hrfid, void, env)
DEF_HELPER_2(store_lpcr, void, env, tl)
+DEF_HELPER_2(store_pcr, void, env, tl)
#endif
DEF_HELPER_1(check_tlb_flush_local, void, env)
DEF_HELPER_1(check_tlb_flush_global, void, env)
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index cbe13b18d1..2c0c34e125 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2412,6 +2412,41 @@ bool kvmppc_has_cap_mmu_hash_v3(void)
return cap_mmu_hash_v3;
}
+static int parse_cap_ppc_safe_cache(struct kvm_ppc_cpu_char c)
+{
+ if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_L1D_FLUSH_PR) {
+ return 2;
+ } else if ((c.character & c.character_mask & H_CPU_CHAR_L1D_THREAD_PRIV) &&
+ (c.character & c.character_mask
+ & (H_CPU_CHAR_L1D_FLUSH_ORI30 | H_CPU_CHAR_L1D_FLUSH_TRIG2))) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int parse_cap_ppc_safe_bounds_check(struct kvm_ppc_cpu_char c)
+{
+ if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR) {
+ return 2;
+ } else if (c.character & c.character_mask & H_CPU_CHAR_SPEC_BAR_ORI31) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c)
+{
+ if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) {
+ return SPAPR_CAP_FIXED_CCD;
+ } else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) {
+ return SPAPR_CAP_FIXED_IBS;
+ }
+
+ return 0;
+}
+
static void kvmppc_get_cpu_characteristics(KVMState *s)
{
struct kvm_ppc_cpu_char c;
@@ -2430,26 +2465,10 @@ static void kvmppc_get_cpu_characteristics(KVMState *s)
if (ret < 0) {
return;
}
- /* Parse and set cap_ppc_safe_cache */
- if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_L1D_FLUSH_PR) {
- cap_ppc_safe_cache = 2;
- } else if ((c.character & c.character_mask & H_CPU_CHAR_L1D_THREAD_PRIV) &&
- (c.character & c.character_mask
- & (H_CPU_CHAR_L1D_FLUSH_ORI30 | H_CPU_CHAR_L1D_FLUSH_TRIG2))) {
- cap_ppc_safe_cache = 1;
- }
- /* Parse and set cap_ppc_safe_bounds_check */
- if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR) {
- cap_ppc_safe_bounds_check = 2;
- } else if (c.character & c.character_mask & H_CPU_CHAR_SPEC_BAR_ORI31) {
- cap_ppc_safe_bounds_check = 1;
- }
- /* Parse and set cap_ppc_safe_indirect_branch */
- if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) {
- cap_ppc_safe_indirect_branch = SPAPR_CAP_FIXED_CCD;
- } else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) {
- cap_ppc_safe_indirect_branch = SPAPR_CAP_FIXED_IBS;
- }
+
+ cap_ppc_safe_cache = parse_cap_ppc_safe_cache(c);
+ cap_ppc_safe_bounds_check = parse_cap_ppc_safe_bounds_check(c);
+ cap_ppc_safe_indirect_branch = parse_cap_ppc_safe_indirect_branch(c);
}
int kvmppc_get_cap_safe_cache(void)
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index 8c8cba5cc6..b884930096 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -20,6 +20,7 @@
#include "cpu.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
+#include "qemu/error-report.h"
#include "helper_regs.h"
@@ -98,6 +99,14 @@ void helper_store_ptcr(CPUPPCState *env, target_ulong val)
tlb_flush(CPU(cpu));
}
}
+
+void helper_store_pcr(CPUPPCState *env, target_ulong value)
+{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+
+ env->spr[SPR_PCR] = value & pcc->pcr_mask;
+}
#endif /* defined(TARGET_PPC64) */
void helper_store_pidr(CPUPPCState *env, target_ulong val)
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index b28e8b91d3..5fe1ba6555 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -2967,7 +2967,28 @@ static void gen_stswx(DisasContext *ctx)
/* eieio */
static void gen_eieio(DisasContext *ctx)
{
- tcg_gen_mb(TCG_MO_LD_ST | TCG_BAR_SC);
+ TCGBar bar = TCG_MO_LD_ST;
+
+ /*
+ * POWER9 has a eieio instruction variant using bit 6 as a hint to
+ * tell the CPU it is a store-forwarding barrier.
+ */
+ if (ctx->opcode & 0x2000000) {
+ /*
+ * ISA says that "Reserved fields in instructions are ignored
+ * by the processor". So ignore the bit 6 on non-POWER9 CPU but
+ * as this is not an instruction software should be using,
+ * complain to the user.
+ */
+ if (!(ctx->insns_flags2 & PPC2_ISA300)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "invalid eieio using bit 6 at @"
+ TARGET_FMT_lx "\n", ctx->base.pc_next - 4);
+ } else {
+ bar = TCG_MO_ST_LD;
+ }
+ }
+
+ tcg_gen_mb(bar | TCG_BAR_SC);
}
#if !defined(CONFIG_USER_ONLY)
@@ -3933,13 +3954,9 @@ static inline void gen_op_mfspr(DisasContext *ctx)
* allowing userland application to read the PVR
*/
if (sprn != SPR_PVR) {
- fprintf(stderr, "Trying to read privileged spr %d (0x%03x) at "
- TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
- if (qemu_log_separate()) {
- qemu_log("Trying to read privileged spr %d (0x%03x) at "
- TARGET_FMT_lx "\n", sprn, sprn,
- ctx->base.pc_next - 4);
- }
+ qemu_log_mask(LOG_GUEST_ERROR, "Trying to read privileged spr "
+ "%d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn,
+ ctx->base.pc_next - 4);
}
gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
}
@@ -3951,12 +3968,9 @@ static inline void gen_op_mfspr(DisasContext *ctx)
return;
}
/* Not defined */
- fprintf(stderr, "Trying to read invalid spr %d (0x%03x) at "
- TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
- if (qemu_log_separate()) {
- qemu_log("Trying to read invalid spr %d (0x%03x) at "
- TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
- }
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "Trying to read invalid spr %d (0x%03x) at "
+ TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
/* The behaviour depends on MSR:PR and SPR# bit 0x10,
* it can generate a priv, a hv emu or a no-op
@@ -4097,12 +4111,9 @@ static void gen_mtspr(DisasContext *ctx)
(*write_cb)(ctx, sprn, rS(ctx->opcode));
} else {
/* Privilege exception */
- fprintf(stderr, "Trying to write privileged spr %d (0x%03x) at "
- TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
- if (qemu_log_separate()) {
- qemu_log("Trying to write privileged spr %d (0x%03x) at "
- TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
- }
+ qemu_log_mask(LOG_GUEST_ERROR, "Trying to write privileged spr "
+ "%d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn,
+ ctx->base.pc_next - 4);
gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
}
} else {
@@ -4114,12 +4125,9 @@ static void gen_mtspr(DisasContext *ctx)
}
/* Not defined */
- if (qemu_log_separate()) {
- qemu_log("Trying to write invalid spr %d (0x%03x) at "
- TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
- }
- fprintf(stderr, "Trying to write invalid spr %d (0x%03x) at "
- TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "Trying to write invalid spr %d (0x%03x) at "
+ TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
/* The behaviour depends on MSR:PR and SPR# bit 0x10,
@@ -6496,7 +6504,7 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
-GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
+GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x01FFF801, PPC_MEM_EIEIO),
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index ab782cb32a..bb9296f5a3 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -424,6 +424,10 @@ static void spr_write_ptcr(DisasContext *ctx, int sprn, int gprn)
gen_helper_store_ptcr(cpu_env, cpu_gpr[gprn]);
}
+static void spr_write_pcr(DisasContext *ctx, int sprn, int gprn)
+{
+ gen_helper_store_pcr(cpu_env, cpu_gpr[gprn]);
+}
#endif
#endif
@@ -7815,7 +7819,7 @@ static void gen_spr_book3s_ids(CPUPPCState *env)
/* Processor identification */
spr_register_hv(env, SPR_PIR, "PIR",
SPR_NOACCESS, SPR_NOACCESS,
- SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, SPR_NOACCESS,
&spr_read_generic, NULL,
0x00000000);
spr_register_hv(env, SPR_HID0, "HID0",
@@ -7957,11 +7961,12 @@ static void gen_spr_power6_common(CPUPPCState *env)
#endif
/*
* Register PCR to report POWERPC_EXCP_PRIV_REG instead of
- * POWERPC_EXCP_INVAL_SPR.
+ * POWERPC_EXCP_INVAL_SPR in userspace. Permit hypervisor access.
*/
- spr_register(env, SPR_PCR, "PCR",
+ spr_register_hv(env, SPR_PCR, "PCR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_pcr,
0x00000000);
}