summaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/hppa/translate.c16
-rw-r--r--target/m68k/softfloat.c46
-rw-r--r--target/m68k/translate.c4
-rw-r--r--target/microblaze/mmu.c9
-rw-r--r--target/microblaze/translate.c6
-rw-r--r--target/ppc/cpu.h4
-rw-r--r--target/ppc/helper.h1
-rw-r--r--target/ppc/kvm.c46
-rw-r--r--target/ppc/kvm_ppc.h6
-rw-r--r--target/ppc/machine.c5
-rw-r--r--target/ppc/misc_helper.c12
-rw-r--r--target/ppc/mmu-book3s-v3.h6
-rw-r--r--target/ppc/mmu-hash64.c15
-rw-r--r--target/ppc/mmu-hash64.h6
-rw-r--r--target/ppc/mmu_helper.c29
-rw-r--r--target/ppc/translate.c3
-rw-r--r--target/ppc/translate_init.c80
17 files changed, 127 insertions, 167 deletions
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index c532889b1f..cdc397308b 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -151,13 +151,7 @@
#define tcg_gen_qemu_ld_reg tcg_gen_qemu_ld_i64
#define tcg_gen_qemu_st_reg tcg_gen_qemu_st_i64
#define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i64
-#if UINTPTR_MAX == UINT32_MAX
-# define tcg_gen_trunc_reg_ptr(p, r) \
- tcg_gen_trunc_i64_i32(TCGV_PTR_TO_NAT(p), r)
-#else
-# define tcg_gen_trunc_reg_ptr(p, r) \
- tcg_gen_mov_i64(TCGV_PTR_TO_NAT(p), r)
-#endif
+#define tcg_gen_trunc_reg_ptr tcg_gen_trunc_i64_ptr
#else
#define TCGv_reg TCGv_i32
#define tcg_temp_new tcg_temp_new_i32
@@ -251,13 +245,7 @@
#define tcg_gen_qemu_ld_reg tcg_gen_qemu_ld_i32
#define tcg_gen_qemu_st_reg tcg_gen_qemu_st_i32
#define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i32
-#if UINTPTR_MAX == UINT32_MAX
-# define tcg_gen_trunc_reg_ptr(p, r) \
- tcg_gen_mov_i32(TCGV_PTR_TO_NAT(p), r)
-#else
-# define tcg_gen_trunc_reg_ptr(p, r) \
- tcg_gen_extu_i32_i64(TCGV_PTR_TO_NAT(p), r)
-#endif
+#define tcg_gen_trunc_reg_ptr tcg_gen_ext_i32_ptr
#endif /* TARGET_REGISTER_BITS */
typedef struct DisasCond {
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index dffb371c71..e41b07d042 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -334,7 +334,8 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
if (aSign && aExp >= one_exp) {
if (aExp == one_exp && aSig == one_sig) {
float_raise(float_flag_divbyzero, status);
- packFloatx80(aSign, floatx80_infinity.high, floatx80_infinity.low);
+ return packFloatx80(aSign, floatx80_infinity.high,
+ floatx80_infinity.low);
}
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
@@ -1496,7 +1497,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
int32_t compact, l, n, j;
floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2;
float32 posneg1, twoto63;
- flag adjn, endflag;
+ flag endflag;
aSig = extractFloatx80Frac(a);
aExp = extractFloatx80Exp(a);
@@ -1514,8 +1515,6 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
return packFloatx80(aSign, 0, 0);
}
- adjn = 0;
-
user_rnd_mode = status->float_rounding_mode;
user_rnd_prec = status->floatx80_rounding_precision;
status->float_rounding_mode = float_round_nearest_even;
@@ -1590,14 +1589,8 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
status->float_rounding_mode = user_rnd_mode;
status->floatx80_rounding_precision = user_rnd_prec;
- if (adjn) {
- /* COSTINY */
- a = floatx80_sub(fp0, float32_to_floatx80(
- make_float32(0x00800000), status), status);
- } else {
- /* SINTINY */
- a = floatx80_move(a, status);
- }
+ /* SINTINY */
+ a = floatx80_move(a, status);
float_raise(float_flag_inexact, status);
return a;
@@ -1615,7 +1608,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
status); /* FP0 IS R = (X-Y1)-Y2 */
sincont:
- if ((n + adjn) & 1) {
+ if (n & 1) {
/* COSPOLY */
fp0 = floatx80_mul(fp0, fp0, status); /* FP0 IS S */
fp1 = floatx80_mul(fp0, fp0, status); /* FP1 IS T */
@@ -1628,7 +1621,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
xExp = extractFloatx80Exp(fp0);
xSig = extractFloatx80Frac(fp0);
- if (((n + adjn) >> 1) & 1) {
+ if ((n >> 1) & 1) {
xSign ^= 1;
posneg1 = make_float32(0xBF800000); /* -1 */
} else {
@@ -1680,7 +1673,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
xExp = extractFloatx80Exp(fp0);
xSig = extractFloatx80Frac(fp0);
- xSign ^= ((n + adjn) >> 1) & 1; /* X IS NOW R'= SGN*R */
+ xSign ^= (n >> 1) & 1; /* X IS NOW R'= SGN*R */
fp0 = floatx80_mul(fp0, fp0, status); /* FP0 IS S */
fp1 = floatx80_mul(fp0, fp0, status); /* FP1 IS T */
@@ -1743,7 +1736,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
int32_t compact, l, n, j;
floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2;
float32 posneg1, twoto63;
- flag adjn, endflag;
+ flag endflag;
aSig = extractFloatx80Frac(a);
aExp = extractFloatx80Exp(a);
@@ -1761,8 +1754,6 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
return packFloatx80(0, one_exp, one_sig);
}
- adjn = 1;
-
user_rnd_mode = status->float_rounding_mode;
user_rnd_prec = status->floatx80_rounding_precision;
status->float_rounding_mode = float_round_nearest_even;
@@ -1836,15 +1827,10 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
status->float_rounding_mode = user_rnd_mode;
status->floatx80_rounding_precision = user_rnd_prec;
- if (adjn) {
- /* COSTINY */
- a = floatx80_sub(fp0, float32_to_floatx80(
- make_float32(0x00800000), status),
- status);
- } else {
- /* SINTINY */
- a = floatx80_move(a, status);
- }
+ /* COSTINY */
+ a = floatx80_sub(fp0, float32_to_floatx80(
+ make_float32(0x00800000), status),
+ status);
float_raise(float_flag_inexact, status);
return a;
@@ -1862,7 +1848,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
status); /* FP0 IS R = (X-Y1)-Y2 */
sincont:
- if ((n + adjn) & 1) {
+ if ((n + 1) & 1) {
/* COSPOLY */
fp0 = floatx80_mul(fp0, fp0, status); /* FP0 IS S */
fp1 = floatx80_mul(fp0, fp0, status); /* FP1 IS T */
@@ -1875,7 +1861,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
xExp = extractFloatx80Exp(fp0);
xSig = extractFloatx80Frac(fp0);
- if (((n + adjn) >> 1) & 1) {
+ if (((n + 1) >> 1) & 1) {
xSign ^= 1;
posneg1 = make_float32(0xBF800000); /* -1 */
} else {
@@ -1926,7 +1912,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
xExp = extractFloatx80Exp(fp0);
xSig = extractFloatx80Frac(fp0);
- xSign ^= ((n + adjn) >> 1) & 1; /* X IS NOW R'= SGN*R */
+ xSign ^= ((n + 1) >> 1) & 1; /* X IS NOW R'= SGN*R */
fp0 = floatx80_mul(fp0, fp0, status); /* FP0 IS S */
fp1 = floatx80_mul(fp0, fp0, status); /* FP1 IS T */
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 6beaf9ed66..e407ba2db3 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -3166,11 +3166,11 @@ DISAS_INSN(subx_mem)
opsize = insn_opsize(insn);
addr_src = AREG(insn, 0);
- tcg_gen_subi_i32(addr_src, addr_src, opsize);
+ tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(opsize));
src = gen_load(s, opsize, addr_src, 1, IS_USER(s));
addr_dest = AREG(insn, 9);
- tcg_gen_subi_i32(addr_dest, addr_dest, opsize);
+ tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(opsize));
dest = gen_load(s, opsize, addr_dest, 1, IS_USER(s));
gen_subx(s, src, dest, opsize);
diff --git a/target/microblaze/mmu.c b/target/microblaze/mmu.c
index a0f06758f8..9d5e6aa8a5 100644
--- a/target/microblaze/mmu.c
+++ b/target/microblaze/mmu.c
@@ -182,7 +182,7 @@ done:
uint32_t mmu_read(CPUMBState *env, uint32_t rn)
{
unsigned int i;
- uint32_t r;
+ uint32_t r = 0;
if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) {
qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n");
@@ -211,6 +211,9 @@ uint32_t mmu_read(CPUMBState *env, uint32_t rn)
}
r = env->mmu.regs[rn];
break;
+ case MMU_R_TLBSX:
+ qemu_log_mask(LOG_GUEST_ERROR, "TLBSX is write-only.\n");
+ break;
default:
r = env->mmu.regs[rn];
break;
@@ -270,6 +273,10 @@ void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v)
env->mmu.regs[rn] = v;
}
break;
+ case MMU_R_TLBX:
+ /* Bit 31 is read-only. */
+ env->mmu.regs[rn] = deposit32(env->mmu.regs[rn], 0, 31, v);
+ break;
case MMU_R_TLBSX:
{
struct microblaze_mmu_lookup lu;
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index 7628b0e25b..100883e2cc 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -424,7 +424,7 @@ static inline void msr_write(DisasContext *dc, TCGv v)
/* PVR bit is not writable. */
tcg_gen_andi_tl(t, v, ~MSR_PVR);
tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], MSR_PVR);
- tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], v);
+ tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t);
tcg_temp_free(t);
}
@@ -952,7 +952,6 @@ static void dec_load(DisasContext *dc)
tcg_gen_sub_tl(low, tcg_const_tl(3), low);
tcg_gen_andi_tl(t, t, ~3);
tcg_gen_or_tl(t, t, low);
- tcg_gen_mov_tl(env_imm, t);
tcg_temp_free(low);
break;
}
@@ -1104,7 +1103,6 @@ static void dec_store(DisasContext *dc)
tcg_gen_sub_tl(low, tcg_const_tl(3), low);
tcg_gen_andi_tl(t, t, ~3);
tcg_gen_or_tl(t, t, low);
- tcg_gen_mov_tl(env_imm, t);
tcg_temp_free(low);
break;
}
@@ -1412,7 +1410,7 @@ static void dec_fpu(DisasContext *dc)
if ((dc->tb_flags & MSR_EE_FLAG)
&& (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
- && (dc->cpu->cfg.use_fpu != 1)) {
+ && !dc->cpu->cfg.use_fpu) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
return;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 8c9e03f54d..7ccd2f460e 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1295,6 +1295,7 @@ int ppc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
#if !defined(CONFIG_USER_ONLY)
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
+void ppc_store_ptcr(CPUPPCState *env, target_ulong value);
#endif /* !defined(CONFIG_USER_ONLY) */
void ppc_store_msr (CPUPPCState *env, target_ulong value);
@@ -1331,7 +1332,7 @@ void store_booke_tcr (CPUPPCState *env, target_ulong val);
void store_booke_tsr (CPUPPCState *env, target_ulong val);
void ppc_tlb_invalidate_all (CPUPPCState *env);
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
-void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp);
+void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp);
#endif
#endif
@@ -1585,6 +1586,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_BOOKE_GIVOR13 (0x1BC)
#define SPR_BOOKE_GIVOR14 (0x1BD)
#define SPR_TIR (0x1BE)
+#define SPR_PTCR (0x1D0)
#define SPR_BOOKE_SPEFSCR (0x200)
#define SPR_Exxx_BBEAR (0x201)
#define SPR_Exxx_BBTAR (0x202)
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 5b739179b8..19453c6813 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -709,6 +709,7 @@ DEF_HELPER_FLAGS_1(load_601_rtcu, TCG_CALL_NO_RWG, tl, env)
#if !defined(CONFIG_USER_ONLY)
#if defined(TARGET_PPC64)
DEF_HELPER_FLAGS_1(load_purr, TCG_CALL_NO_RWG, tl, env)
+DEF_HELPER_2(store_ptcr, void, env, tl)
#endif
DEF_HELPER_2(store_sdr1, void, env, tl)
DEF_HELPER_2(store_pidr, void, env, tl)
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 6de59c5b21..cbe13b18d1 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -72,7 +72,6 @@ static int cap_segstate;
static int cap_booke_sregs;
static int cap_ppc_smt;
static int cap_ppc_smt_possible;
-static int cap_ppc_rma;
static int cap_spapr_tce;
static int cap_spapr_tce_64;
static int cap_spapr_multitce;
@@ -133,7 +132,6 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE);
cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS);
cap_ppc_smt_possible = kvm_vm_check_extension(s, KVM_CAP_PPC_SMT_POSSIBLE);
- cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
cap_spapr_tce_64 = kvm_check_extension(s, KVM_CAP_SPAPR_TCE_64);
cap_spapr_multitce = kvm_check_extension(s, KVM_CAP_SPAPR_MULTITCE);
@@ -2090,6 +2088,10 @@ void kvmppc_set_papr(PowerPCCPU *cpu)
CPUState *cs = CPU(cpu);
int ret;
+ if (!kvm_enabled()) {
+ return;
+ }
+
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_PAPR, 0);
if (ret) {
error_report("This vCPU type or KVM version does not support PAPR");
@@ -2159,52 +2161,12 @@ void kvmppc_hint_smt_possible(Error **errp)
#ifdef TARGET_PPC64
-off_t kvmppc_alloc_rma(void **rma)
-{
- off_t size;
- int fd;
- struct kvm_allocate_rma ret;
-
- /* If cap_ppc_rma == 0, contiguous RMA allocation is not supported
- * if cap_ppc_rma == 1, contiguous RMA allocation is supported, but
- * not necessary on this hardware
- * if cap_ppc_rma == 2, contiguous RMA allocation is needed on this hardware
- *
- * FIXME: We should allow the user to force contiguous RMA
- * allocation in the cap_ppc_rma==1 case.
- */
- if (cap_ppc_rma < 2) {
- return 0;
- }
-
- fd = kvm_vm_ioctl(kvm_state, KVM_ALLOCATE_RMA, &ret);
- if (fd < 0) {
- fprintf(stderr, "KVM: Error on KVM_ALLOCATE_RMA: %s\n",
- strerror(errno));
- return -1;
- }
-
- size = MIN(ret.rma_size, 256ul << 20);
-
- *rma = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- if (*rma == MAP_FAILED) {
- fprintf(stderr, "KVM: Error mapping RMA: %s\n", strerror(errno));
- return -1;
- };
-
- return size;
-}
-
uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
{
struct kvm_ppc_smmu_info info;
long rampagesize, best_page_shift;
int i;
- if (cap_ppc_rma >= 2) {
- return current_size;
- }
-
/* Find the largest hardware supported page size that's less than
* or equal to the (logical) backing page size of guest RAM */
kvm_get_smmu_info(POWERPC_CPU(first_cpu), &info);
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index 4d2789eef6..e2840e1d33 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -37,7 +37,6 @@ target_ulong kvmppc_configure_v3_mmu(PowerPCCPU *cpu,
bool radix, bool gtse,
uint64_t proc_tbl);
#ifndef CONFIG_USER_ONLY
-off_t kvmppc_alloc_rma(void **rma);
bool kvmppc_spapr_use_multitce(void);
int kvmppc_spapr_enable_inkernel_multitce(void);
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift,
@@ -188,11 +187,6 @@ static inline target_ulong kvmppc_configure_v3_mmu(PowerPCCPU *cpu,
}
#ifndef CONFIG_USER_ONLY
-static inline off_t kvmppc_alloc_rma(void **rma)
-{
- return 0;
-}
-
static inline bool kvmppc_spapr_use_multitce(void)
{
return false;
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index 3d6434a006..ba1b9e531f 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -212,6 +212,11 @@ static int cpu_pre_save(void *opaque)
;
cpu->mig_msr_mask = env->msr_mask & ~metamask;
cpu->mig_insns_flags = env->insns_flags & insns_compat_mask;
+ /* CPU models supported by old machines all have PPC_MEM_TLBIE,
+ * so we set it unconditionally to allow backward migration from
+ * a POWER9 host to a POWER8 host.
+ */
+ cpu->mig_insns_flags |= PPC_MEM_TLBIE;
cpu->mig_insns_flags2 = env->insns_flags2 & insns_compat_mask2;
cpu->mig_nb_BATs = env->nb_BATs;
}
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index 0e4217821b..8c8cba5cc6 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -88,6 +88,18 @@ void helper_store_sdr1(CPUPPCState *env, target_ulong val)
}
}
+#if defined(TARGET_PPC64)
+void helper_store_ptcr(CPUPPCState *env, target_ulong val)
+{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+ if (env->spr[SPR_PTCR] != val) {
+ ppc_store_ptcr(env, val);
+ tlb_flush(CPU(cpu));
+ }
+}
+#endif /* defined(TARGET_PPC64) */
+
void helper_store_pidr(CPUPPCState *env, target_ulong val)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h
index 56095dab52..fdf80987d7 100644
--- a/target/ppc/mmu-book3s-v3.h
+++ b/target/ppc/mmu-book3s-v3.h
@@ -22,6 +22,12 @@
#ifndef CONFIG_USER_ONLY
+/*
+ * Partition table definitions
+ */
+#define PTCR_PATB 0x0FFFFFFFFFFFF000ULL /* Partition Table Base */
+#define PTCR_PATS 0x000000000000001FULL /* Partition Table Size */
+
/* Partition Table Entry Fields */
#define PATBE1_GR 0x8000000000000000
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index 7e0adecfd9..a1db20e3a8 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -942,7 +942,7 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong ptex,
cpu->env.tlb_need_flush = TLB_NEED_GLOBAL_FLUSH | TLB_NEED_LOCAL_FLUSH;
}
-void ppc_hash64_update_rmls(PowerPCCPU *cpu)
+static void ppc_hash64_update_rmls(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
uint64_t lpcr = env->spr[SPR_LPCR];
@@ -977,7 +977,7 @@ void ppc_hash64_update_rmls(PowerPCCPU *cpu)
}
}
-void ppc_hash64_update_vrma(PowerPCCPU *cpu)
+static void ppc_hash64_update_vrma(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
const PPCHash64SegmentPageSizes *sps = NULL;
@@ -1028,9 +1028,9 @@ void ppc_hash64_update_vrma(PowerPCCPU *cpu)
slb->sps = sps;
}
-void helper_store_lpcr(CPUPPCState *env, target_ulong val)
+void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
{
- PowerPCCPU *cpu = ppc_env_get_cpu(env);
+ CPUPPCState *env = &cpu->env;
uint64_t lpcr = 0;
/* Filter out bits */
@@ -1096,6 +1096,13 @@ void helper_store_lpcr(CPUPPCState *env, target_ulong val)
ppc_hash64_update_vrma(cpu);
}
+void helper_store_lpcr(CPUPPCState *env, target_ulong val)
+{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+ ppc_store_lpcr(cpu, val);
+}
+
void ppc_hash64_init(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h
index d5fc03441d..53dcec5b93 100644
--- a/target/ppc/mmu-hash64.h
+++ b/target/ppc/mmu-hash64.h
@@ -17,8 +17,7 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu,
target_ulong pte0, target_ulong pte1);
unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
uint64_t pte0, uint64_t pte1);
-void ppc_hash64_update_vrma(PowerPCCPU *cpu);
-void ppc_hash64_update_rmls(PowerPCCPU *cpu);
+void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val);
void ppc_hash64_init(PowerPCCPU *cpu);
void ppc_hash64_finalize(PowerPCCPU *cpu);
#endif
@@ -102,6 +101,9 @@ void ppc_hash64_finalize(PowerPCCPU *cpu);
static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
{
+ if (cpu->vhyp) {
+ return 0;
+ }
return cpu->env.spr[SPR_SDR1] & SDR_64_HTABORG;
}
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index 8075b7149a..98ce17985b 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -2028,6 +2028,35 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
env->spr[SPR_SDR1] = value;
}
+#if defined(TARGET_PPC64)
+void ppc_store_ptcr(CPUPPCState *env, target_ulong value)
+{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
+ target_ulong ptcr_mask = PTCR_PATB | PTCR_PATS;
+ target_ulong patbsize = value & PTCR_PATS;
+
+ qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
+
+ assert(!cpu->vhyp);
+ assert(env->mmu_model & POWERPC_MMU_3_00);
+
+ if (value & ~ptcr_mask) {
+ error_report("Invalid bits 0x"TARGET_FMT_lx" set in PTCR",
+ value & ~ptcr_mask);
+ value &= ptcr_mask;
+ }
+
+ if (patbsize > 24) {
+ error_report("Invalid Partition Table size 0x" TARGET_FMT_lx
+ " stored in PTCR", patbsize);
+ return;
+ }
+
+ env->spr[SPR_PTCR] = value;
+}
+
+#endif /* defined(TARGET_PPC64) */
+
/* Segment registers load and store */
target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
{
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 3beaa1e2f0..2a4140f420 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7136,6 +7136,9 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
if (env->spr_cb[SPR_SDR1].name) { /* SDR1 Exists */
cpu_fprintf(f, " SDR1 " TARGET_FMT_lx " ", env->spr[SPR_SDR1]);
}
+ if (env->spr_cb[SPR_PTCR].name) { /* PTCR Exists */
+ cpu_fprintf(f, " PTCR " TARGET_FMT_lx " ", env->spr[SPR_PTCR]);
+ }
cpu_fprintf(f, " DAR " TARGET_FMT_lx " DSISR " TARGET_FMT_lx "\n",
env->spr[SPR_DAR], env->spr[SPR_DSISR]);
break;
diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
index 808f6c1a08..118631efbe 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -420,6 +420,11 @@ static void spr_write_hior(DisasContext *ctx, int sprn, int gprn)
tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_prefix));
tcg_temp_free(t0);
}
+static void spr_write_ptcr(DisasContext *ctx, int sprn, int gprn)
+{
+ gen_helper_store_ptcr(cpu_env, cpu_gpr[gprn]);
+}
+
#endif
#endif
@@ -8167,6 +8172,18 @@ static void gen_spr_power8_rpr(CPUPPCState *env)
#endif
}
+static void gen_spr_power9_mmu(CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+ /* Partition Table Control */
+ spr_register_hv(env, SPR_PTCR, "PTCR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_ptcr,
+ 0x00000000);
+#endif
+}
+
static void init_proc_book3s_common(CPUPPCState *env)
{
gen_spr_ne_601(env);
@@ -8719,6 +8736,7 @@ static void init_proc_POWER9(CPUPPCState *env)
gen_spr_power8_ic(env);
gen_spr_power8_book4(env);
gen_spr_power8_rpr(env);
+ gen_spr_power9_mmu(env);
/* POWER9 Specific registers */
spr_register_kvm(env, SPR_TIDR, "TIDR", NULL, NULL,
@@ -8864,13 +8882,9 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
}
#if !defined(CONFIG_USER_ONLY)
-void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
+void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
{
- PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
CPUPPCState *env = &cpu->env;
- ppc_spr_t *lpcr = &env->spr_cb[SPR_LPCR];
- ppc_spr_t *amor = &env->spr_cb[SPR_AMOR];
- CPUState *cs = CPU(cpu);
cpu->vhyp = vhyp;
@@ -8879,62 +8893,6 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
* hypervisor mode itself
*/
env->msr_mask &= ~MSR_HVB;
-
- /* Set emulated LPCR to not send interrupts to hypervisor. Note that
- * under KVM, the actual HW LPCR will be set differently by KVM itself,
- * the settings below ensure proper operations with TCG in absence of
- * a real hypervisor.
- *
- * Clearing VPM0 will also cause us to use RMOR in mmu-hash64.c for
- * real mode accesses, which thankfully defaults to 0 and isn't
- * accessible in guest mode.
- */
- lpcr->default_value &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV);
- lpcr->default_value |= LPCR_LPES0 | LPCR_LPES1;
-
- /* Set RMLS to the max (ie, 16G) */
- lpcr->default_value &= ~LPCR_RMLS;
- lpcr->default_value |= 1ull << LPCR_RMLS_SHIFT;
-
- if (env->mmu_model == POWERPC_MMU_3_00) {
- /* By default we choose legacy mode and switch to new hash or radix
- * when a register process table hcall is made. So disable process
- * tables and guest translation shootdown by default
- *
- * Hot-plugged CPUs inherit from the guest radix setting under
- * KVM but not under TCG. Update the default LPCR to keep new
- * CPUs in sync when radix is enabled.
- */
- if (ppc64_radix_guest(cpu)) {
- lpcr->default_value |= LPCR_UPRT | LPCR_GTSE;
- } else {
- lpcr->default_value &= ~(LPCR_UPRT | LPCR_GTSE);
- }
- }
-
- /* Only enable Power-saving mode Exit Cause exceptions on the boot
- * CPU. The RTAS command start-cpu will enable them on secondaries.
- */
- if (cs == first_cpu) {
- lpcr->default_value |= pcc->lpcr_pm;
- }
-
- /* We should be followed by a CPU reset but update the active value
- * just in case...
- */
- env->spr[SPR_LPCR] = lpcr->default_value;
-
- /* Set a full AMOR so guest can use the AMR as it sees fit */
- env->spr[SPR_AMOR] = amor->default_value = 0xffffffffffffffffull;
-
- /* Update some env bits based on new LPCR value */
- ppc_hash64_update_rmls(cpu);
- ppc_hash64_update_vrma(cpu);
-
- /* Tell KVM that we're in PAPR mode */
- if (kvm_enabled()) {
- kvmppc_set_papr(cpu);
- }
}
#endif /* !defined(CONFIG_USER_ONLY) */