diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/hppa/translate.c | 16 | ||||
-rw-r--r-- | target/m68k/softfloat.c | 46 | ||||
-rw-r--r-- | target/m68k/translate.c | 4 | ||||
-rw-r--r-- | target/microblaze/mmu.c | 9 | ||||
-rw-r--r-- | target/microblaze/translate.c | 6 | ||||
-rw-r--r-- | target/ppc/cpu.h | 4 | ||||
-rw-r--r-- | target/ppc/helper.h | 1 | ||||
-rw-r--r-- | target/ppc/kvm.c | 46 | ||||
-rw-r--r-- | target/ppc/kvm_ppc.h | 6 | ||||
-rw-r--r-- | target/ppc/machine.c | 5 | ||||
-rw-r--r-- | target/ppc/misc_helper.c | 12 | ||||
-rw-r--r-- | target/ppc/mmu-book3s-v3.h | 6 | ||||
-rw-r--r-- | target/ppc/mmu-hash64.c | 15 | ||||
-rw-r--r-- | target/ppc/mmu-hash64.h | 6 | ||||
-rw-r--r-- | target/ppc/mmu_helper.c | 29 | ||||
-rw-r--r-- | target/ppc/translate.c | 3 | ||||
-rw-r--r-- | target/ppc/translate_init.c | 80 |
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) */ |