summaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2013-01-15 13:31:42 -0800
committerAnas Nashif <anas.nashif@intel.com>2013-01-15 13:31:42 -0800
commit42bf3037d458a330856a0be584200c1e41c3f417 (patch)
tree25b9be1088727757e52271e25a446e8a852357df /target-ppc
parent060629c6ef0b7e5c267d84c91600113264d33120 (diff)
downloadqemu-42bf3037d458a330856a0be584200c1e41c3f417.tar.gz
qemu-42bf3037d458a330856a0be584200c1e41c3f417.tar.bz2
qemu-42bf3037d458a330856a0be584200c1e41c3f417.zip
Imported Upstream version 1.3.0upstream/1.3.0
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/cpu.h41
-rw-r--r--target-ppc/excp_helper.c40
-rw-r--r--target-ppc/helper.h38
-rw-r--r--target-ppc/int_helper.c127
-rw-r--r--target-ppc/kvm.c153
-rw-r--r--target-ppc/kvm_ppc.h19
-rw-r--r--target-ppc/machine.c12
-rw-r--r--target-ppc/mmu_helper.c65
-rw-r--r--target-ppc/translate.c48
-rw-r--r--target-ppc/translate_init.c11
10 files changed, 288 insertions, 266 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index ca2fc2198..5f1dc8b7d 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -355,7 +355,7 @@ struct ppc6xx_tlb_t {
typedef struct ppcemb_tlb_t ppcemb_tlb_t;
struct ppcemb_tlb_t {
- target_phys_addr_t RPN;
+ hwaddr RPN;
target_ulong EPN;
target_ulong PID;
target_ulong size;
@@ -963,7 +963,7 @@ struct CPUPPCState {
/* floating point registers */
float64 fpr[32];
/* floating point status and control register */
- uint32_t fpscr;
+ target_ulong fpscr;
/* Next instruction pointer */
target_ulong nip;
@@ -983,8 +983,8 @@ struct CPUPPCState {
int slb_nr;
#endif
/* segment registers */
- target_phys_addr_t htab_base;
- target_phys_addr_t htab_mask;
+ hwaddr htab_base;
+ hwaddr htab_mask;
target_ulong sr[32];
/* externally stored hash table */
uint8_t *external_htab;
@@ -1014,6 +1014,8 @@ struct CPUPPCState {
/* Altivec registers */
ppc_avr_t avr[32];
uint32_t vscr;
+ /* VSX registers */
+ uint64_t vsr[32];
/* SPE registers */
uint64_t spe_acc;
uint32_t spe_fscr;
@@ -1045,10 +1047,9 @@ struct CPUPPCState {
#endif
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
- target_phys_addr_t vpa;
- target_phys_addr_t slb_shadow;
- target_phys_addr_t dispatch_trace_log;
- uint32_t dtl_size;
+ uint64_t vpa_addr;
+ uint64_t slb_shadow_addr, slb_shadow_size;
+ uint64_t dtl_addr, dtl_size;
#endif /* TARGET_PPC64 */
int error_code;
@@ -1066,7 +1067,7 @@ struct CPUPPCState {
target_ulong ivor_mask;
target_ulong ivpr_mask;
target_ulong hreset_vector;
- target_phys_addr_t mpic_cpu_base;
+ hwaddr mpic_cpu_base;
#endif
/* Those resources are used only during code translation */
@@ -1079,7 +1080,6 @@ struct CPUPPCState {
int mmu_idx; /* precomputed MMU index to speed up mem accesses */
/* Power management */
- int power_mode;
int (*check_pow)(CPUPPCState *env);
#if !defined(CONFIG_USER_ONLY)
@@ -1118,10 +1118,10 @@ do { \
/* Context used internally during MMU translations */
typedef struct mmu_ctx_t mmu_ctx_t;
struct mmu_ctx_t {
- target_phys_addr_t raddr; /* Real address */
- target_phys_addr_t eaddr; /* Effective address */
+ hwaddr raddr; /* Real address */
+ hwaddr eaddr; /* Effective address */
int prot; /* Protection bits */
- target_phys_addr_t hash[2]; /* Pagetable hash values */
+ hwaddr hash[2]; /* Pagetable hash values */
target_ulong ptem; /* Virtual segment ID | API */
int key; /* Access key */
int nx; /* Non-execute area */
@@ -1142,10 +1142,6 @@ int cpu_ppc_signal_handler (int host_signum, void *pinfo,
int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
int mmu_idx);
#define cpu_handle_mmu_fault cpu_ppc_handle_mmu_fault
-#if !defined(CONFIG_USER_ONLY)
-int get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx, target_ulong vaddr,
- int rw, int access_type);
-#endif
void do_interrupt (CPUPPCState *env);
void ppc_hw_interrupt (CPUPPCState *env);
@@ -1179,7 +1175,6 @@ void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value);
uint32_t cpu_ppc_load_hdecr (CPUPPCState *env);
void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value);
uint64_t cpu_ppc_load_purr (CPUPPCState *env);
-void cpu_ppc_store_purr (CPUPPCState *env, uint64_t value);
uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env);
uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env);
#if !defined(CONFIG_USER_ONLY)
@@ -1191,10 +1186,8 @@ void store_40x_dbcr0 (CPUPPCState *env, uint32_t val);
void store_40x_sler (CPUPPCState *env, uint32_t val);
void store_booke_tcr (CPUPPCState *env, target_ulong val);
void store_booke_tsr (CPUPPCState *env, target_ulong val);
-void booke206_flush_tlb(CPUPPCState *env, int flags, const int check_iprot);
-target_phys_addr_t booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb);
int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
- target_phys_addr_t *raddrp, target_ulong address,
+ hwaddr *raddrp, target_ulong address,
uint32_t pid);
void ppc_tlb_invalidate_all (CPUPPCState *env);
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
@@ -2222,10 +2215,12 @@ static inline bool msr_is_64bit(CPUPPCState *env, target_ulong msr)
return msr & (1ULL << MSR_SF);
}
-extern void (*cpu_ppc_hypercall)(CPUPPCState *);
+extern void (*cpu_ppc_hypercall)(PowerPCCPU *);
-static inline bool cpu_has_work(CPUPPCState *env)
+static inline bool cpu_has_work(CPUState *cpu)
{
+ CPUPPCState *env = &POWERPC_CPU(cpu)->env;
+
return msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD);
}
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 1a593f6f3..5e34ad08a 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -33,7 +33,7 @@
/*****************************************************************************/
/* PowerPC Hypercall emulation */
-void (*cpu_ppc_hypercall)(CPUPPCState *);
+void (*cpu_ppc_hypercall)(PowerPCCPU *);
/*****************************************************************************/
/* Exception processing */
@@ -63,8 +63,9 @@ static inline void dump_syscall(CPUPPCState *env)
/* Note that this function should be greatly optimized
* when called with a constant excp, from ppc_hw_interrupt
*/
-static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp)
+static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
{
+ CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
int srr0, srr1, asrr0, asrr1;
int lpes0, lpes1, lev;
@@ -238,7 +239,7 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp)
dump_syscall(env);
lev = env->error_code;
if ((lev == 1) && cpu_ppc_hypercall) {
- cpu_ppc_hypercall(env);
+ cpu_ppc_hypercall(cpu);
return;
}
if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) {
@@ -643,11 +644,14 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp)
void do_interrupt(CPUPPCState *env)
{
- powerpc_excp(env, env->excp_model, env->exception_index);
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+ powerpc_excp(cpu, env->excp_model, env->exception_index);
}
void ppc_hw_interrupt(CPUPPCState *env)
{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
int hdice;
#if 0
@@ -658,20 +662,20 @@ void ppc_hw_interrupt(CPUPPCState *env)
/* External reset */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
return;
}
/* Machine check exception */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
return;
}
#if 0 /* TODO */
/* External debug exception */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
return;
}
#endif
@@ -685,7 +689,7 @@ void ppc_hw_interrupt(CPUPPCState *env)
/* Hypervisor decrementer exception */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
return;
}
}
@@ -698,7 +702,7 @@ void ppc_hw_interrupt(CPUPPCState *env)
#if 0
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
#endif
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
return;
}
}
@@ -706,30 +710,30 @@ void ppc_hw_interrupt(CPUPPCState *env)
/* Watchdog timer on embedded PowerPC */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
return;
}
if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
return;
}
/* Fixed interval timer on embedded PowerPC */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
return;
}
/* Programmable interval timer on embedded PowerPC */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
return;
}
/* Decrementer exception */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
return;
}
/* External interrupt */
@@ -740,23 +744,23 @@ void ppc_hw_interrupt(CPUPPCState *env)
#if 0
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
#endif
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
return;
}
if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
return;
}
if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
return;
}
/* Thermal interrupt */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
- powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
return;
}
}
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index fd04c063e..e588370e2 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -31,24 +31,24 @@ DEF_HELPER_2(icbi, void, env, tl)
DEF_HELPER_5(lscbx, tl, env, tl, i32, i32, i32)
#if defined(TARGET_PPC64)
-DEF_HELPER_FLAGS_2(mulhd, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(mulhdu, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(mulhd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(mulhdu, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_3(mulldo, i64, env, i64, i64)
#endif
-DEF_HELPER_FLAGS_1(cntlzw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
-DEF_HELPER_FLAGS_1(popcntb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
-DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(cntlzw, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_1(popcntb, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_3(sraw, tl, env, tl, tl)
#if defined(TARGET_PPC64)
-DEF_HELPER_FLAGS_1(cntlzd, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
-DEF_HELPER_FLAGS_1(popcntd, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(cntlzd, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_1(popcntd, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_3(srad, tl, env, tl, tl)
#endif
-DEF_HELPER_FLAGS_1(cntlsw32, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
-DEF_HELPER_FLAGS_1(cntlzw32, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
-DEF_HELPER_FLAGS_2(brinc, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_1(cntlsw32, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(cntlzw32, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_2(brinc, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_1(float_check_status, void, env)
DEF_HELPER_1(reset_fpstatus, void, env)
@@ -345,25 +345,25 @@ DEF_HELPER_2(6xx_tlbd, void, env, tl)
DEF_HELPER_2(6xx_tlbi, void, env, tl)
DEF_HELPER_2(74xx_tlbd, void, env, tl)
DEF_HELPER_2(74xx_tlbi, void, env, tl)
-DEF_HELPER_FLAGS_1(tlbia, TCG_CALL_CONST, void, env)
-DEF_HELPER_FLAGS_2(tlbie, TCG_CALL_CONST, void, env, tl)
+DEF_HELPER_FLAGS_1(tlbia, TCG_CALL_NO_RWG, void, env)
+DEF_HELPER_FLAGS_2(tlbie, TCG_CALL_NO_RWG, void, env, tl)
#if defined(TARGET_PPC64)
-DEF_HELPER_FLAGS_3(store_slb, TCG_CALL_CONST, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(store_slb, TCG_CALL_NO_RWG, void, env, tl, tl)
DEF_HELPER_2(load_slb_esid, tl, env, tl)
DEF_HELPER_2(load_slb_vsid, tl, env, tl)
-DEF_HELPER_FLAGS_1(slbia, TCG_CALL_CONST, void, env)
-DEF_HELPER_FLAGS_2(slbie, TCG_CALL_CONST, void, env, tl)
+DEF_HELPER_FLAGS_1(slbia, TCG_CALL_NO_RWG, void, env)
+DEF_HELPER_FLAGS_2(slbie, TCG_CALL_NO_RWG, void, env, tl)
#endif
-DEF_HELPER_FLAGS_2(load_sr, TCG_CALL_CONST, tl, env, tl);
-DEF_HELPER_FLAGS_3(store_sr, TCG_CALL_CONST, void, env, tl, tl)
+DEF_HELPER_FLAGS_2(load_sr, TCG_CALL_NO_RWG, tl, env, tl);
+DEF_HELPER_FLAGS_3(store_sr, TCG_CALL_NO_RWG, void, env, tl, tl)
-DEF_HELPER_FLAGS_1(602_mfrom, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(602_mfrom, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_1(msgsnd, void, tl)
DEF_HELPER_2(msgclr, void, env, tl)
#endif
DEF_HELPER_4(dlmzb, tl, env, tl, tl, i32)
-DEF_HELPER_FLAGS_2(clcs, TCG_CALL_CONST | TCG_CALL_PURE, tl, env, i32)
+DEF_HELPER_FLAGS_2(clcs, TCG_CALL_NO_RWG_SE, tl, env, i32)
#if !defined(CONFIG_USER_ONLY)
DEF_HELPER_2(rac, tl, env, tl)
#endif
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index f638b2a07..f39b4f682 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -287,23 +287,6 @@ target_ulong helper_602_mfrom(target_ulong arg)
for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
#endif
-/* If X is a NaN, store the corresponding QNaN into RESULT. Otherwise,
- * execute the following block. */
-#define DO_HANDLE_NAN(result, x) \
- if (float32_is_any_nan(x)) { \
- CPU_FloatU __f; \
- __f.f = x; \
- __f.l = __f.l | (1 << 22); /* Set QNaN bit. */ \
- result = __f.f; \
- } else
-
-#define HANDLE_NAN1(result, x) \
- DO_HANDLE_NAN(result, x)
-#define HANDLE_NAN2(result, x, y) \
- DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y)
-#define HANDLE_NAN3(result, x, y, z) \
- DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y) DO_HANDLE_NAN(result, z)
-
/* Saturating arithmetic helpers. */
#define SATCVT(from, to, from_type, to_type, min, max) \
static inline to_type cvt##from##to(from_type x, int *sat) \
@@ -409,15 +392,29 @@ VARITH(uwm, u32)
int i; \
\
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
- HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) { \
- r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \
- } \
+ r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \
} \
}
VARITHFP(addfp, float32_add)
VARITHFP(subfp, float32_sub)
+VARITHFP(minfp, float32_min)
+VARITHFP(maxfp, float32_max)
#undef VARITHFP
+#define VARITHFPFMA(suffix, type) \
+ void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
+ ppc_avr_t *b, ppc_avr_t *c) \
+ { \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
+ r->f[i] = float32_muladd(a->f[i], c->f[i], b->f[i], \
+ type, &env->vec_status); \
+ } \
+ }
+VARITHFPFMA(maddfp, 0);
+VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c);
+#undef VARITHFPFMA
+
#define VARITHSAT_CASE(type, op, cvt, element) \
{ \
type result = (type)a->element[i] op (type)b->element[i]; \
@@ -649,27 +646,6 @@ VCT(uxs, cvtsduw, u32)
VCT(sxs, cvtsdsw, s32)
#undef VCT
-void helper_vmaddfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
- ppc_avr_t *c)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(r->f); i++) {
- HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
- /* Need to do the computation in higher precision and round
- * once at the end. */
- float64 af, bf, cf, t;
-
- af = float32_to_float64(a->f[i], &env->vec_status);
- bf = float32_to_float64(b->f[i], &env->vec_status);
- cf = float32_to_float64(c->f[i], &env->vec_status);
- t = float64_mul(af, cf, &env->vec_status);
- t = float64_add(t, bf, &env->vec_status);
- r->f[i] = float64_to_float32(t, &env->vec_status);
- }
- }
-}
-
void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
ppc_avr_t *b, ppc_avr_t *c)
{
@@ -730,27 +706,6 @@ VMINMAX(uw, u32)
#undef VMINMAX_DO
#undef VMINMAX
-#define VMINMAXFP(suffix, rT, rF) \
- void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
- ppc_avr_t *b) \
- { \
- int i; \
- \
- for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
- HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) { \
- if (float32_lt_quiet(a->f[i], b->f[i], \
- &env->vec_status)) { \
- r->f[i] = rT->f[i]; \
- } else { \
- r->f[i] = rF->f[i]; \
- } \
- } \
- } \
- }
-VMINMAXFP(minfp, a, b)
-VMINMAXFP(maxfp, b, a)
-#undef VMINMAXFP
-
void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
int i;
@@ -930,28 +885,6 @@ VMUL(uh, u16, u32)
#undef VMUL_DO
#undef VMUL
-void helper_vnmsubfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
- ppc_avr_t *b, ppc_avr_t *c)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(r->f); i++) {
- HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
- /* Need to do the computation is higher precision and round
- * once at the end. */
- float64 af, bf, cf, t;
-
- af = float32_to_float64(a->f[i], &env->vec_status);
- bf = float32_to_float64(b->f[i], &env->vec_status);
- cf = float32_to_float64(c->f[i], &env->vec_status);
- t = float64_mul(af, cf, &env->vec_status);
- t = float64_sub(t, bf, &env->vec_status);
- t = float64_chs(t);
- r->f[i] = float64_to_float32(t, &env->vec_status);
- }
- }
-}
-
void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
ppc_avr_t *c)
{
@@ -1039,9 +972,7 @@ void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
int i;
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
- HANDLE_NAN1(r->f[i], b->f[i]) {
- r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
- }
+ r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
}
}
@@ -1054,9 +985,7 @@ void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
\
set_float_rounding_mode(rounding, &s); \
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
- HANDLE_NAN1(r->f[i], b->f[i]) { \
- r->f[i] = float32_round_to_int (b->f[i], &s); \
- } \
+ r->f[i] = float32_round_to_int (b->f[i], &s); \
} \
}
VRFI(n, float_round_nearest_even)
@@ -1089,11 +1018,9 @@ void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
int i;
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
- HANDLE_NAN1(r->f[i], b->f[i]) {
- float32 t = float32_sqrt(b->f[i], &env->vec_status);
+ float32 t = float32_sqrt(b->f[i], &env->vec_status);
- r->f[i] = float32_div(float32_one, t, &env->vec_status);
- }
+ r->f[i] = float32_div(float32_one, t, &env->vec_status);
}
}
@@ -1109,9 +1036,7 @@ void helper_vexptefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
int i;
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
- HANDLE_NAN1(r->f[i], b->f[i]) {
- r->f[i] = float32_exp2(b->f[i], &env->vec_status);
- }
+ r->f[i] = float32_exp2(b->f[i], &env->vec_status);
}
}
@@ -1120,9 +1045,7 @@ void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
int i;
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
- HANDLE_NAN1(r->f[i], b->f[i]) {
- r->f[i] = float32_log2(b->f[i], &env->vec_status);
- }
+ r->f[i] = float32_log2(b->f[i], &env->vec_status);
}
}
@@ -1473,10 +1396,6 @@ VUPK(lsh, s32, s16, UPKLO)
#undef UPKHI
#undef UPKLO
-#undef DO_HANDLE_NAN
-#undef HANDLE_NAN1
-#undef HANDLE_NAN2
-#undef HANDLE_NAN3
#undef VECTOR_FOR_INORDER_I
#undef HI_IDX
#undef LO_IDX
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index a31d278a5..3f5df5772 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -60,6 +60,7 @@ static int cap_booke_sregs;
static int cap_ppc_smt;
static int cap_ppc_rma;
static int cap_spapr_tce;
+static int cap_hior;
/* XXX We have a race condition where we actually have a level triggered
* interrupt, but the infrastructure can't expose that yet, so the guest
@@ -72,9 +73,11 @@ static int cap_spapr_tce;
*/
static QEMUTimer *idle_timer;
-static void kvm_kick_env(void *env)
+static void kvm_kick_cpu(void *opaque)
{
- qemu_cpu_kick(env);
+ PowerPCCPU *cpu = opaque;
+
+ qemu_cpu_kick(CPU(cpu));
}
int kvm_arch_init(KVMState *s)
@@ -86,6 +89,7 @@ int kvm_arch_init(KVMState *s)
cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT);
cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
+ cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
if (!cap_interrupt_level) {
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -373,6 +377,7 @@ static inline void kvm_fixup_page_sizes(CPUPPCState *env)
int kvm_arch_init_vcpu(CPUPPCState *cenv)
{
+ PowerPCCPU *cpu = ppc_env_get_cpu(cenv);
int ret;
/* Gather server mmu info from KVM and update the CPU state */
@@ -384,7 +389,7 @@ int kvm_arch_init_vcpu(CPUPPCState *cenv)
return ret;
}
- idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_env, cenv);
+ idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_cpu, cpu);
/* Some targets support access to KVM's guest TLB. */
switch (cenv->mmu_model) {
@@ -469,6 +474,54 @@ int kvm_arch_put_registers(CPUPPCState *env, int level)
env->tlb_dirty = false;
}
+ if (cap_segstate && (level >= KVM_PUT_RESET_STATE)) {
+ struct kvm_sregs sregs;
+
+ sregs.pvr = env->spr[SPR_PVR];
+
+ sregs.u.s.sdr1 = env->spr[SPR_SDR1];
+
+ /* Sync SLB */
+#ifdef TARGET_PPC64
+ for (i = 0; i < 64; i++) {
+ sregs.u.s.ppc64.slb[i].slbe = env->slb[i].esid;
+ sregs.u.s.ppc64.slb[i].slbv = env->slb[i].vsid;
+ }
+#endif
+
+ /* Sync SRs */
+ for (i = 0; i < 16; i++) {
+ sregs.u.s.ppc32.sr[i] = env->sr[i];
+ }
+
+ /* Sync BATs */
+ for (i = 0; i < 8; i++) {
+ /* Beware. We have to swap upper and lower bits here */
+ sregs.u.s.ppc32.dbat[i] = ((uint64_t)env->DBAT[0][i] << 32)
+ | env->DBAT[1][i];
+ sregs.u.s.ppc32.ibat[i] = ((uint64_t)env->IBAT[0][i] << 32)
+ | env->IBAT[1][i];
+ }
+
+ ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ if (cap_hior && (level >= KVM_PUT_RESET_STATE)) {
+ uint64_t hior = env->spr[SPR_HIOR];
+ struct kvm_one_reg reg = {
+ .id = KVM_REG_PPC_HIOR,
+ .addr = (uintptr_t) &hior,
+ };
+
+ ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, &reg);
+ if (ret) {
+ return ret;
+ }
+ }
+
return ret;
}
@@ -764,7 +817,8 @@ int kvm_arch_handle_exit(CPUPPCState *env, struct kvm_run *run)
#ifdef CONFIG_PSERIES
case KVM_EXIT_PAPR_HCALL:
dprintf("handle PAPR hypercall\n");
- run->papr_hcall.ret = spapr_hypercall(env, run->papr_hcall.nr,
+ run->papr_hcall.ret = spapr_hypercall(ppc_env_get_cpu(env),
+ run->papr_hcall.nr,
run->papr_hcall.args);
ret = 0;
break;
@@ -795,7 +849,7 @@ static int read_cpuinfo(const char *field, char *value, int len)
break;
}
if (!strncmp(line, field, field_len)) {
- strncpy(value, line, len);
+ pstrcpy(value, len, line);
ret = 0;
break;
}
@@ -946,52 +1000,14 @@ int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
void kvmppc_set_papr(CPUPPCState *env)
{
struct kvm_enable_cap cap = {};
- struct kvm_one_reg reg = {};
- struct kvm_sregs sregs = {};
int ret;
- uint64_t hior = env->spr[SPR_HIOR];
cap.cap = KVM_CAP_PPC_PAPR;
ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &cap);
if (ret) {
- goto fail;
+ cpu_abort(env, "This KVM version does not support PAPR\n");
}
-
- /*
- * XXX We set HIOR here. It really should be a qdev property of
- * the CPU node, but we don't have CPUs converted to qdev yet.
- *
- * Once we have qdev CPUs, move HIOR to a qdev property and
- * remove this chunk.
- */
- reg.id = KVM_REG_PPC_HIOR;
- reg.addr = (uintptr_t)&hior;
- ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, &reg);
- if (ret) {
- fprintf(stderr, "Couldn't set HIOR. Maybe you're running an old \n"
- "kernel with support for HV KVM but no PAPR PR \n"
- "KVM in which case things will work. If they don't \n"
- "please update your host kernel!\n");
- }
-
- /* Set SDR1 so kernel space finds the HTAB */
- ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
- if (ret) {
- goto fail;
- }
-
- sregs.u.s.sdr1 = env->spr[SPR_SDR1];
-
- ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
- if (ret) {
- goto fail;
- }
-
- return;
-
-fail:
- cpu_abort(env, "This KVM version does not support PAPR\n");
}
int kvmppc_smt_threads(void)
@@ -999,6 +1015,7 @@ int kvmppc_smt_threads(void)
return cap_ppc_smt ? cap_ppc_smt : 1;
}
+#ifdef TARGET_PPC64
off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
{
void *rma;
@@ -1042,6 +1059,16 @@ off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
return size;
}
+uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
+{
+ if (cap_ppc_rma >= 2) {
+ return current_size;
+ }
+ return MIN(current_size,
+ getrampagesize() << (hash_shift - 7));
+}
+#endif
+
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
{
struct kvm_create_spapr_tce args = {
@@ -1101,6 +1128,44 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
return 0;
}
+int kvmppc_reset_htab(int shift_hint)
+{
+ uint32_t shift = shift_hint;
+
+ if (!kvm_enabled()) {
+ /* Full emulation, tell caller to allocate htab itself */
+ return 0;
+ }
+ if (kvm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) {
+ int ret;
+ ret = kvm_vm_ioctl(kvm_state, KVM_PPC_ALLOCATE_HTAB, &shift);
+ if (ret == -ENOTTY) {
+ /* At least some versions of PR KVM advertise the
+ * capability, but don't implement the ioctl(). Oops.
+ * Return 0 so that we allocate the htab in qemu, as is
+ * correct for PR. */
+ return 0;
+ } else if (ret < 0) {
+ return ret;
+ }
+ return shift;
+ }
+
+ /* We have a kernel that predates the htab reset calls. For PR
+ * KVM, we need to allocate the htab ourselves, for an HV KVM of
+ * this era, it has allocated a 16MB fixed size hash table
+ * already. Kernels of this era have the GET_PVINFO capability
+ * only on PR, so we use this hack to determine the right
+ * answer */
+ if (kvm_check_extension(kvm_state, KVM_CAP_PPC_GET_PVINFO)) {
+ /* PR - tell caller to allocate htab */
+ return 0;
+ } else {
+ /* HV - assume 16MB kernel allocated htab */
+ return 24;
+ }
+}
+
static inline uint32_t mfpvr(void)
{
uint32_t pvr;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index e2f870385..baad6eb75 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -27,6 +27,8 @@ int kvmppc_smt_threads(void);
off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd);
int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
+int kvmppc_reset_htab(int shift_hint);
+uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift);
#endif /* !CONFIG_USER_ONLY */
const ppc_def_t *kvmppc_host_cpu_def(void);
int kvmppc_fixup_cpu(CPUPPCState *env);
@@ -94,6 +96,23 @@ static inline int kvmppc_remove_spapr_tce(void *table, int pfd,
{
return -1;
}
+
+static inline int kvmppc_reset_htab(int shift_hint)
+{
+ return -1;
+}
+
+static inline uint64_t kvmppc_rma_size(uint64_t current_size,
+ unsigned int hash_shift)
+{
+ return ram_size;
+}
+
+static inline int kvmppc_update_sdr1(CPUPPCState *env)
+{
+ return 0;
+}
+
#endif /* !CONFIG_USER_ONLY */
static inline const ppc_def_t *kvmppc_host_cpu_def(void)
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index d6c2ee41b..5e7bc00e2 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -6,6 +6,7 @@ void cpu_save(QEMUFile *f, void *opaque)
{
CPUPPCState *env = (CPUPPCState *)opaque;
unsigned int i, j;
+ uint32_t fpscr;
for (i = 0; i < 32; i++)
qemu_put_betls(f, &env->gpr[i]);
@@ -30,7 +31,8 @@ void cpu_save(QEMUFile *f, void *opaque)
u.d = env->fpr[i];
qemu_put_be64(f, u.l);
}
- qemu_put_be32s(f, &env->fpscr);
+ fpscr = env->fpscr;
+ qemu_put_be32s(f, &fpscr);
qemu_put_sbe32s(f, &env->access_type);
#if defined(TARGET_PPC64)
qemu_put_betls(f, &env->asr);
@@ -82,7 +84,7 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_betls(f, &env->hflags);
qemu_put_betls(f, &env->hflags_nmsr);
qemu_put_sbe32s(f, &env->mmu_idx);
- qemu_put_sbe32s(f, &env->power_mode);
+ qemu_put_sbe32(f, 0);
}
int cpu_load(QEMUFile *f, void *opaque, int version_id)
@@ -90,6 +92,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
CPUPPCState *env = (CPUPPCState *)opaque;
unsigned int i, j;
target_ulong sdr1;
+ uint32_t fpscr;
for (i = 0; i < 32; i++)
qemu_get_betls(f, &env->gpr[i]);
@@ -114,7 +117,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
u.l = qemu_get_be64(f);
env->fpr[i] = u.d;
}
- qemu_get_be32s(f, &env->fpscr);
+ qemu_get_be32s(f, &fpscr);
+ env->fpscr = fpscr;
qemu_get_sbe32s(f, &env->access_type);
#if defined(TARGET_PPC64)
qemu_get_betls(f, &env->asr);
@@ -167,7 +171,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_betls(f, &env->hflags);
qemu_get_betls(f, &env->hflags_nmsr);
qemu_get_sbe32s(f, &env->mmu_idx);
- qemu_get_sbe32s(f, &env->power_mode);
+ qemu_get_sbe32(f); /* Discard unused power_mode */
return 0;
}
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index d2664acef..318ce92ad 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -215,7 +215,7 @@ static inline int pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0,
pp = pte1 & 0x00000003;
}
if (ptem == ctx->ptem) {
- if (ctx->raddr != (target_phys_addr_t)-1ULL) {
+ if (ctx->raddr != (hwaddr)-1ULL) {
/* all matches should have equal RPN, WIMG & PP */
if ((ctx->raddr & mmask) != (pte1 & mmask)) {
qemu_log("Bad RPN/WIMG/PP\n");
@@ -556,8 +556,8 @@ static inline int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
return ret;
}
-static inline target_phys_addr_t get_pteg_offset(CPUPPCState *env,
- target_phys_addr_t hash,
+static inline hwaddr get_pteg_offset(CPUPPCState *env,
+ hwaddr hash,
int pte_size)
{
return (hash * pte_size * 8) & env->htab_mask;
@@ -567,7 +567,7 @@ static inline target_phys_addr_t get_pteg_offset(CPUPPCState *env,
static inline int find_pte2(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h,
int rw, int type, int target_page_bits)
{
- target_phys_addr_t pteg_off;
+ hwaddr pteg_off;
target_ulong pte0, pte1;
int i, good = -1;
int ret, r;
@@ -817,7 +817,7 @@ static int ppc_load_slb_vsid(CPUPPCState *env, target_ulong rb,
static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx,
target_ulong eaddr, int rw, int type)
{
- target_phys_addr_t hash;
+ hwaddr hash;
target_ulong vsid;
int ds, pr, target_page_bits;
int ret, ret2;
@@ -896,7 +896,7 @@ static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx,
ctx->hash[1] = ~hash;
/* Initialize real address with an invalid value */
- ctx->raddr = (target_phys_addr_t)-1ULL;
+ ctx->raddr = (hwaddr)-1ULL;
if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
/* Software TLB search */
@@ -926,7 +926,7 @@ static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx,
}
#if defined(DUMP_PAGE_TABLES)
if (qemu_log_enabled()) {
- target_phys_addr_t curaddr;
+ hwaddr curaddr;
uint32_t a0, a1, a2, a3;
qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
@@ -1009,7 +1009,7 @@ static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx,
/* Generic TLB check function for embedded PowerPC implementations */
static int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
- target_phys_addr_t *raddrp,
+ hwaddr *raddrp,
target_ulong address, uint32_t pid, int ext,
int i)
{
@@ -1032,12 +1032,10 @@ static int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
return -1;
}
*raddrp = (tlb->RPN & mask) | (address & ~mask);
-#if (TARGET_PHYS_ADDR_BITS >= 36)
if (ext) {
/* Extend the physical address to 36 bits */
- *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
+ *raddrp |= (uint64_t)(tlb->RPN & 0xF) << 32;
}
-#endif
return 0;
}
@@ -1047,7 +1045,7 @@ static int ppcemb_tlb_search(CPUPPCState *env, target_ulong address,
uint32_t pid)
{
ppcemb_tlb_t *tlb;
- target_phys_addr_t raddr;
+ hwaddr raddr;
int i, ret;
/* Default return value is no match */
@@ -1081,7 +1079,7 @@ static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState *env,
{
#if !defined(FLUSH_ALL_TLBS)
ppcemb_tlb_t *tlb;
- target_phys_addr_t raddr;
+ hwaddr raddr;
target_ulong page, end;
int i;
@@ -1106,11 +1104,11 @@ static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
int access_type)
{
ppcemb_tlb_t *tlb;
- target_phys_addr_t raddr;
+ hwaddr raddr;
int i, ret, zsel, zpr, pr;
ret = -1;
- raddr = (target_phys_addr_t)-1ULL;
+ raddr = (hwaddr)-1ULL;
pr = msr_pr;
for (i = 0; i < env->nb_tlb; i++) {
tlb = &env->tlb.tlbe[i];
@@ -1177,7 +1175,7 @@ void store_40x_sler(CPUPPCState *env, uint32_t val)
}
static inline int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb,
- target_phys_addr_t *raddr, int *prot,
+ hwaddr *raddr, int *prot,
target_ulong address, int rw,
int access_type, int i)
{
@@ -1251,11 +1249,11 @@ static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
int access_type)
{
ppcemb_tlb_t *tlb;
- target_phys_addr_t raddr;
+ hwaddr raddr;
int i, ret;
ret = -1;
- raddr = (target_phys_addr_t)-1ULL;
+ raddr = (hwaddr)-1ULL;
for (i = 0; i < env->nb_tlb; i++) {
tlb = &env->tlb.tlbe[i];
ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
@@ -1278,7 +1276,8 @@ static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
return ret;
}
-void booke206_flush_tlb(CPUPPCState *env, int flags, const int check_iprot)
+static void booke206_flush_tlb(CPUPPCState *env, int flags,
+ const int check_iprot)
{
int tlb_size;
int i, j;
@@ -1299,8 +1298,8 @@ void booke206_flush_tlb(CPUPPCState *env, int flags, const int check_iprot)
tlb_flush(env, 1);
}
-target_phys_addr_t booke206_tlb_to_page_size(CPUPPCState *env,
- ppcmas_tlb_t *tlb)
+static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
+ ppcmas_tlb_t *tlb)
{
int tlbm_size;
@@ -1311,7 +1310,7 @@ target_phys_addr_t booke206_tlb_to_page_size(CPUPPCState *env,
/* TLB check function for MAS based SoftTLBs */
int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
- target_phys_addr_t *raddrp,
+ hwaddr *raddrp,
target_ulong address, uint32_t pid)
{
target_ulong mask;
@@ -1347,7 +1346,7 @@ int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
}
static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
- target_phys_addr_t *raddr, int *prot,
+ hwaddr *raddr, int *prot,
target_ulong address, int rw,
int access_type)
{
@@ -1437,11 +1436,11 @@ static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
int access_type)
{
ppcmas_tlb_t *tlb;
- target_phys_addr_t raddr;
+ hwaddr raddr;
int i, j, ret;
ret = -1;
- raddr = (target_phys_addr_t)-1ULL;
+ raddr = (hwaddr)-1ULL;
for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
int ways = booke206_tlb_ways(env, i);
@@ -1498,7 +1497,7 @@ static void mmubooke_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
entry = &env->tlb.tlbe[0];
for (i = 0; i < env->nb_tlb; i++, entry++) {
- target_phys_addr_t ea, pa;
+ hwaddr ea, pa;
target_ulong mask;
uint64_t size = (uint64_t)entry->size;
char size_buf[20];
@@ -1511,10 +1510,8 @@ static void mmubooke_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
mask = ~(entry->size - 1);
ea = entry->EPN & mask;
pa = entry->RPN & mask;
-#if (TARGET_PHYS_ADDR_BITS >= 36)
/* Extend the physical address to 36 bits */
- pa |= (target_phys_addr_t)(entry->RPN & 0xF) << 32;
-#endif
+ pa |= (hwaddr)(entry->RPN & 0xF) << 32;
size /= 1024;
if (size >= 1024) {
snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / 1024);
@@ -1541,7 +1538,7 @@ static void mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf,
entry = &env->tlb.tlbm[offset];
for (i = 0; i < tlbsize; i++, entry++) {
- target_phys_addr_t ea, pa, size;
+ hwaddr ea, pa, size;
int tsize;
if (!(entry->mas1 & MAS1_VALID)) {
@@ -1710,8 +1707,8 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
return ret;
}
-int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
- int rw, int access_type)
+static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+ target_ulong eaddr, int rw, int access_type)
{
int ret;
@@ -1787,7 +1784,7 @@ int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
return ret;
}
-target_phys_addr_t cpu_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
+hwaddr cpu_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
{
mmu_ctx_t ctx;
@@ -3147,7 +3144,7 @@ void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address)
{
ppcmas_tlb_t *tlb = NULL;
int i, j;
- target_phys_addr_t raddr;
+ hwaddr raddr;
uint32_t spid, sas;
spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index ac915ccad..987b04eda 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -68,7 +68,7 @@ static TCGv cpu_cfar;
#endif
static TCGv cpu_xer;
static TCGv cpu_reserve;
-static TCGv_i32 cpu_fpscr;
+static TCGv cpu_fpscr;
static TCGv_i32 cpu_access_type;
#include "gen-icount.h"
@@ -163,8 +163,8 @@ void ppc_translate_init(void)
offsetof(CPUPPCState, reserve_addr),
"reserve_addr");
- cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
- offsetof(CPUPPCState, fpscr), "fpscr");
+ cpu_fpscr = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUPPCState, fpscr), "fpscr");
cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
offsetof(CPUPPCState, access_type), "access_type");
@@ -2302,6 +2302,7 @@ GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
/* mcrfs */
static void gen_mcrfs(DisasContext *ctx)
{
+ TCGv tmp = tcg_temp_new();
int bfa;
if (unlikely(!ctx->fpu_enabled)) {
@@ -2309,9 +2310,11 @@ static void gen_mcrfs(DisasContext *ctx)
return;
}
bfa = 4 * (7 - crfS(ctx->opcode));
- tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
+ tcg_gen_shri_tl(tmp, cpu_fpscr, bfa);
+ tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
+ tcg_temp_free(tmp);
tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
- tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
+ tcg_gen_andi_tl(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
}
/* mffs */
@@ -2322,7 +2325,7 @@ static void gen_mffs(DisasContext *ctx)
return;
}
gen_reset_fpstatus();
- tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
+ tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
}
@@ -2346,7 +2349,8 @@ static void gen_mtfsb0(DisasContext *ctx)
tcg_temp_free_i32(t0);
}
if (unlikely(Rc(ctx->opcode) != 0)) {
- tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
+ tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
+ tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
}
}
@@ -2371,7 +2375,8 @@ static void gen_mtfsb1(DisasContext *ctx)
tcg_temp_free_i32(t0);
}
if (unlikely(Rc(ctx->opcode) != 0)) {
- tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
+ tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
+ tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
}
/* We can raise a differed exception */
gen_helper_float_check_status(cpu_env);
@@ -2397,7 +2402,8 @@ static void gen_mtfsf(DisasContext *ctx)
gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
tcg_temp_free_i32(t0);
if (unlikely(Rc(ctx->opcode) != 0)) {
- tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
+ tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
+ tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
}
/* We can raise a differed exception */
gen_helper_float_check_status(cpu_env);
@@ -2425,7 +2431,8 @@ static void gen_mtfsfi(DisasContext *ctx)
tcg_temp_free_i64(t0);
tcg_temp_free_i32(t1);
if (unlikely(Rc(ctx->opcode) != 0)) {
- tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
+ tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
+ tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
}
/* We can raise a differed exception */
gen_helper_float_check_status(cpu_env);
@@ -3466,7 +3473,8 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
if (unlikely(ctx->singlestep_enabled)) {
if ((ctx->singlestep_enabled &
(CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
- ctx->exception == POWERPC_EXCP_BRANCH) {
+ (ctx->exception == POWERPC_EXCP_BRANCH ||
+ ctx->exception == POWERPC_EXCP_TRACE)) {
target_ulong tmp = ctx->nip;
ctx->nip = dest;
gen_exception(ctx, POWERPC_EXCP_TRACE);
@@ -9463,7 +9471,7 @@ void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf,
if ((i & (RFPL - 1)) == (RFPL - 1))
cpu_fprintf(f, "\n");
}
- cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
+ cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr);
#if !defined(CONFIG_USER_ONLY)
cpu_fprintf(f, " SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx
" PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n",
@@ -9617,7 +9625,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
int max_insns;
pc_start = tb->pc;
- gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+ gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
ctx.nip = pc_start;
ctx.tb = tb;
ctx.exception = POWERPC_EXCP_NONE;
@@ -9657,7 +9665,8 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
gen_icount_start();
/* Set env in case of segfault during code fetch */
- while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
+ while (ctx.exception == POWERPC_EXCP_NONE
+ && tcg_ctx.gen_opc_ptr < gen_opc_end) {
if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
if (bp->pc == ctx.nip) {
@@ -9667,7 +9676,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
}
}
if (unlikely(search_pc)) {
- j = gen_opc_ptr - gen_opc_buf;
+ j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
if (lj < j) {
lj++;
while (lj < j)
@@ -9690,8 +9699,9 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
opc3(ctx.opcode), little_endian ? "little" : "big");
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
tcg_gen_debug_insn_start(ctx.nip);
+ }
ctx.nip += 4;
table = env->opcodes;
num_insns++;
@@ -9766,9 +9776,9 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
tcg_gen_exit_tb(0);
}
gen_icount_end(tb, num_insns);
- *gen_opc_ptr = INDEX_op_end;
+ *tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (unlikely(search_pc)) {
- j = gen_opc_ptr - gen_opc_buf;
+ j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j)
gen_opc_instr_start[lj++] = 0;
@@ -9782,7 +9792,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
flags = env->bfd_mach;
flags |= ctx.le_mode << 16;
qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(pc_start, ctx.nip - pc_start, flags);
+ log_target_disas(env, pc_start, ctx.nip - pc_start, flags);
qemu_log("\n");
}
#endif
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index fba2b4242..e63627cac 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -1498,7 +1498,7 @@ static void gen_spr_BookE (CPUPPCState *env, uint64_t ivor_mask)
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_DBCR0, "DBCR0",
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_40x_dbcr0,
0x00000000);
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_DBCR1, "DBCR1",
@@ -10423,6 +10423,15 @@ static void ppc_cpu_reset(CPUState *s)
env->pending_interrupts = 0;
env->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
+
+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+ env->vpa_addr = 0;
+ env->slb_shadow_addr = 0;
+ env->slb_shadow_size = 0;
+ env->dtl_addr = 0;
+ env->dtl_size = 0;
+#endif /* TARGET_PPC64 */
+
/* Flush all TLBs */
tlb_flush(env, 1);
}