aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/cpu_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/ppc/cpu_init.c')
-rw-r--r--target/ppc/cpu_init.c235
1 files changed, 176 insertions, 59 deletions
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index c11a69fd90..01e358a4a5 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -246,7 +246,7 @@ static void register_amr_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_AMOR, "AMOR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_core_lpar_write_generic,
0);
#endif /* !CONFIG_USER_ONLY */
}
@@ -792,7 +792,7 @@ static void register_BookE_sprs(CPUPPCState *env, uint64_t ivor_mask)
0x00000000);
spr_register(env, SPR_BOOKE_DECAR, "DECAR",
SPR_NOACCESS, SPR_NOACCESS,
- SPR_NOACCESS, &spr_write_generic,
+ SPR_NOACCESS, &spr_write_generic32,
0x00000000);
/* SPRGs */
spr_register(env, SPR_USPRG0, "USPRG0",
@@ -2107,19 +2107,42 @@ static int check_pow_hid0_74xx(CPUPPCState *env)
return 0;
}
-static void init_proc_405(CPUPPCState *env)
+#if defined(TARGET_PPC64)
+static int check_attn_hid0(CPUPPCState *env)
{
- register_40x_sprs(env);
- register_405_sprs(env);
- register_usprgh_sprs(env);
+ if (env->spr[SPR_HID0] & HID0_ENABLE_ATTN) {
+ return 1;
+ }
- /* Memory management */
-#if !defined(CONFIG_USER_ONLY)
+ return 0;
+}
+
+static int check_attn_hid0_power9(CPUPPCState *env)
+{
+ if (env->spr[SPR_HID0] & HID0_POWER9_ENABLE_ATTN) {
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+static void init_tlbs_emb(CPUPPCState *env)
+{
+#ifndef CONFIG_USER_ONLY
env->nb_tlb = 64;
env->nb_ways = 1;
- env->id_tlbs = 0;
env->tlb_type = TLB_EMB;
#endif
+}
+
+static void init_proc_405(CPUPPCState *env)
+{
+ register_40x_sprs(env);
+ register_405_sprs(env);
+ register_usprgh_sprs(env);
+
+ init_tlbs_emb(env);
init_excp_4xx(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
@@ -2138,6 +2161,7 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 405";
pcc->init_proc = init_proc_405;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_DCR | PPC_WRTEE |
PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |
@@ -2186,13 +2210,8 @@ static void init_proc_440EP(CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
- /* Memory management */
-#if !defined(CONFIG_USER_ONLY)
- env->nb_tlb = 64;
- env->nb_ways = 1;
- env->id_tlbs = 0;
- env->tlb_type = TLB_EMB;
-#endif
+
+ init_tlbs_emb(env);
init_excp_BookE(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
@@ -2210,6 +2229,7 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 440 EP";
pcc->init_proc = init_proc_440EP;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -2248,6 +2268,7 @@ POWERPC_FAMILY(460EX)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 460 EX";
pcc->init_proc = init_proc_440EP;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -2284,13 +2305,7 @@ static void init_proc_440GP(CPUPPCState *env)
register_440_sprs(env);
register_usprgh_sprs(env);
- /* Memory management */
-#if !defined(CONFIG_USER_ONLY)
- env->nb_tlb = 64;
- env->nb_ways = 1;
- env->id_tlbs = 0;
- env->tlb_type = TLB_EMB;
-#endif
+ init_tlbs_emb(env);
init_excp_BookE(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
@@ -2308,6 +2323,7 @@ POWERPC_FAMILY(440GP)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 440 GP";
pcc->init_proc = init_proc_440GP;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_MFAPIDI |
PPC_CACHE | PPC_CACHE_ICBI |
@@ -2358,13 +2374,8 @@ static void init_proc_440x5(CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
- /* Memory management */
-#if !defined(CONFIG_USER_ONLY)
- env->nb_tlb = 64;
- env->nb_ways = 1;
- env->id_tlbs = 0;
- env->tlb_type = TLB_EMB;
-#endif
+
+ init_tlbs_emb(env);
init_excp_BookE(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
@@ -2382,6 +2393,7 @@ POWERPC_FAMILY(440x5)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 440x5";
pcc->init_proc = init_proc_440x5;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_DCR | PPC_WRTEE | PPC_RFMCI |
PPC_CACHE | PPC_CACHE_ICBI |
@@ -2417,6 +2429,7 @@ POWERPC_FAMILY(440x5wDFPU)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 440x5 with double precision FPU";
pcc->init_proc = init_proc_440x5;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_FLOAT | PPC_FLOAT_FSQRT |
PPC_FLOAT_STFIWX |
@@ -2465,6 +2478,7 @@ POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void *data)
dc->desc = "Freescale 5xx cores (aka RCPU)";
pcc->init_proc = init_proc_MPC5xx;
pcc->check_pow = check_pow_none;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_MEM_EIEIO | PPC_MEM_SYNC |
PPC_CACHE_ICBI | PPC_FLOAT | PPC_FLOAT_STFIWX |
@@ -2507,6 +2521,7 @@ POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void *data)
dc->desc = "Freescale 8xx cores (aka PowerQUICC)";
pcc->init_proc = init_proc_MPC8xx;
pcc->check_pow = check_pow_none;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_MEM_EIEIO | PPC_MEM_SYNC |
PPC_CACHE_ICBI | PPC_MFTB;
@@ -2557,6 +2572,7 @@ POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
dc->desc = "PowerPC G2";
pcc->init_proc = init_proc_G2;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_STFIWX |
@@ -2595,6 +2611,7 @@ POWERPC_FAMILY(G2LE)(ObjectClass *oc, void *data)
dc->desc = "PowerPC G2LE";
pcc->init_proc = init_proc_G2;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_STFIWX |
@@ -2721,12 +2738,8 @@ static void init_proc_e200(CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
-#if !defined(CONFIG_USER_ONLY)
- env->nb_tlb = 64;
- env->nb_ways = 1;
- env->id_tlbs = 0;
- env->tlb_type = TLB_EMB;
-#endif
+
+ init_tlbs_emb(env);
init_excp_e200(env, 0xFFFF0000UL);
env->dcache_line_size = 32;
env->icache_line_size = 32;
@@ -2741,6 +2754,7 @@ POWERPC_FAMILY(e200)(ObjectClass *oc, void *data)
dc->desc = "e200 core";
pcc->init_proc = init_proc_e200;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
/*
* XXX: unimplemented instructions:
* dcblc
@@ -2843,7 +2857,6 @@ static void init_proc_e500(CPUPPCState *env, int version)
/* Memory management */
env->nb_pids = 3;
env->nb_ways = 2;
- env->id_tlbs = 0;
switch (version) {
case fsl_e500v1:
tlbncfg[0] = register_tlbncfg(2, 1, 1, 0, 256);
@@ -3029,6 +3042,7 @@ POWERPC_FAMILY(e500v1)(ObjectClass *oc, void *data)
dc->desc = "e500v1 core";
pcc->init_proc = init_proc_e500v1;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
PPC_SPE | PPC_SPE_SINGLE |
PPC_WRTEE | PPC_RFDI |
@@ -3072,6 +3086,7 @@ POWERPC_FAMILY(e500v2)(ObjectClass *oc, void *data)
dc->desc = "e500v2 core";
pcc->init_proc = init_proc_e500v2;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE |
PPC_WRTEE | PPC_RFDI |
@@ -3115,6 +3130,7 @@ POWERPC_FAMILY(e500mc)(ObjectClass *oc, void *data)
dc->desc = "e500mc core";
pcc->init_proc = init_proc_e500mc;
pcc->check_pow = check_pow_none;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_MFTB |
PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
@@ -3161,6 +3177,7 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data)
dc->desc = "e5500 core";
pcc->init_proc = init_proc_e5500;
pcc->check_pow = check_pow_none;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_MFTB |
PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
@@ -3209,6 +3226,7 @@ POWERPC_FAMILY(e6500)(ObjectClass *oc, void *data)
dc->desc = "e6500 core";
pcc->init_proc = init_proc_e6500;
pcc->check_pow = check_pow_none;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_MFTB |
PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
@@ -3271,6 +3289,7 @@ POWERPC_FAMILY(603)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 603";
pcc->init_proc = init_proc_603;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3310,6 +3329,7 @@ POWERPC_FAMILY(603E)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 603e";
pcc->init_proc = init_proc_603;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3355,6 +3375,7 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
dc->desc = "e300 core";
pcc->init_proc = init_proc_e300;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_STFIWX |
@@ -3410,6 +3431,7 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 604";
pcc->init_proc = init_proc_604;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3455,6 +3477,7 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 604E";
pcc->init_proc = init_proc_604E;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3511,6 +3534,7 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 740";
pcc->init_proc = init_proc_740;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3576,6 +3600,7 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 750";
pcc->init_proc = init_proc_750;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3722,6 +3747,7 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 750 CL";
pcc->init_proc = init_proc_750cl;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
/*
* XXX: not implemented:
* cache lock instructions:
@@ -3829,6 +3855,7 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 750CX";
pcc->init_proc = init_proc_750cx;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3901,6 +3928,7 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 750FX";
pcc->init_proc = init_proc_750fx;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -3973,6 +4001,7 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 750GX";
pcc->init_proc = init_proc_750gx;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -4032,6 +4061,7 @@ POWERPC_FAMILY(745)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 745";
pcc->init_proc = init_proc_745;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -4077,6 +4107,7 @@ POWERPC_FAMILY(755)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 755";
pcc->init_proc = init_proc_755;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
@@ -4143,6 +4174,7 @@ POWERPC_FAMILY(7400)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7400 (aka G4)";
pcc->init_proc = init_proc_7400;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4222,6 +4254,7 @@ POWERPC_FAMILY(7410)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7410 (aka G4)";
pcc->init_proc = init_proc_7410;
pcc->check_pow = check_pow_hid0;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4322,6 +4355,7 @@ POWERPC_FAMILY(7440)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7440 (aka G4)";
pcc->init_proc = init_proc_7440;
pcc->check_pow = check_pow_hid0_74xx;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4444,6 +4478,7 @@ POWERPC_FAMILY(7450)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7450 (aka G4)";
pcc->init_proc = init_proc_7450;
pcc->check_pow = check_pow_hid0_74xx;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4573,6 +4608,7 @@ POWERPC_FAMILY(7445)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7445 (aka G4)";
pcc->init_proc = init_proc_7445;
pcc->check_pow = check_pow_hid0_74xx;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4704,6 +4740,7 @@ POWERPC_FAMILY(7455)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7455 (aka G4)";
pcc->init_proc = init_proc_7455;
pcc->check_pow = check_pow_hid0_74xx;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4855,6 +4892,7 @@ POWERPC_FAMILY(7457)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 7457 (aka G4)";
pcc->init_proc = init_proc_7457;
pcc->check_pow = check_pow_hid0_74xx;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -4989,6 +5027,7 @@ POWERPC_FAMILY(e600)(ObjectClass *oc, void *data)
dc->desc = "PowerPC e600";
pcc->init_proc = init_proc_e600;
pcc->check_pow = check_pow_hid0_74xx;
+ pcc->check_attn = check_attn_none;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -5152,7 +5191,7 @@ static void register_book3s_pmu_sup_sprs(CPUPPCState *env)
KVM_REG_PPC_MMCR1, 0x00000000);
spr_register_kvm(env, SPR_POWER_MMCRA, "MMCRA",
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_MMCRA,
KVM_REG_PPC_MMCRA, 0x00000000);
spr_register_kvm(env, SPR_POWER_PMC1, "PMC1",
SPR_NOACCESS, SPR_NOACCESS,
@@ -5415,7 +5454,7 @@ static void register_book3s_ids_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_MMCRC, "MMCRC",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic32,
+ &spr_read_generic, &spr_core_write_generic32,
0x00000000);
spr_register_hv(env, SPR_MMCRH, "MMCRH",
SPR_NOACCESS, SPR_NOACCESS,
@@ -5455,7 +5494,7 @@ static void register_book3s_ids_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_HRMOR, "HRMOR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_core_write_generic,
0x00000000);
}
@@ -5549,6 +5588,14 @@ static void register_HEIR64_spr(CPUPPCState *env)
0x00000000);
}
+static void register_power7_common_sprs(CPUPPCState *env)
+{
+ spr_register(env, SPR_PPR32, "PPR32",
+ &spr_read_ppr32, &spr_write_ppr32,
+ &spr_read_ppr32, &spr_write_ppr32,
+ 0x00000000);
+}
+
static void register_power8_tce_address_control_sprs(CPUPPCState *env)
{
spr_register_kvm(env, SPR_TAR, "TAR",
@@ -5675,7 +5722,7 @@ static void register_power_common_book4_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_TSCR, "TSCR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic32,
+ &spr_read_generic, &spr_core_write_generic32,
0x00000000);
spr_register_hv(env, SPR_HMER, "HMER",
SPR_NOACCESS, SPR_NOACCESS,
@@ -5685,7 +5732,7 @@ static void register_power_common_book4_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_HMEER, "HMEER",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_core_write_generic,
0x00000000);
spr_register_hv(env, SPR_TFMR, "TFMR",
SPR_NOACCESS, SPR_NOACCESS,
@@ -5702,6 +5749,26 @@ static void register_power_common_book4_sprs(CPUPPCState *env)
&spr_access_nop, &spr_write_generic,
&spr_access_nop, &spr_write_generic,
0x00000000);
+ spr_register_hv(env, SPR_LDBAR, "LDBAR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_core_lpar_write_generic,
+ 0x00000000);
+ spr_register_hv(env, SPR_POWER_TTR, "TTR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_core_write_generic,
+ 0x00000000);
+ spr_register_hv(env, SPR_POWER_SPRC, "SPRC",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_sprc,
+ 0x00000000);
+ spr_register_hv(env, SPR_POWER_SPRD, "SPRD",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_sprd, &spr_write_sprd,
+ 0x00000000);
#endif
}
@@ -5761,7 +5828,7 @@ static void register_power8_rpr_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_RPR, "RPR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_core_write_generic,
0x00000103070F1F3F);
#endif
}
@@ -5904,6 +5971,7 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 970";
pcc->init_proc = init_proc_970;
pcc->check_pow = check_pow_970;
+ pcc->check_attn = check_attn_hid0;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -5979,6 +6047,7 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
dc->desc = "POWER5+";
pcc->init_proc = init_proc_power5plus;
pcc->check_pow = check_pow_970;
+ pcc->check_attn = check_attn_hid0;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6042,6 +6111,7 @@ static void init_proc_POWER7(CPUPPCState *env)
register_power6_common_sprs(env);
register_HEIR32_spr(env);
register_power6_dbg_sprs(env);
+ register_power7_common_sprs(env);
register_power7_book4_sprs(env);
/* env variables */
@@ -6086,6 +6156,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
pcc->pcr_supported = PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
pcc->init_proc = init_proc_POWER7;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_hid0;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6142,6 +6213,28 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
pcc->l1_icache_size = 0x8000;
}
+static void bhrb_init_state(CPUPPCState *env, target_long num_entries_log2)
+{
+ if (env->flags & POWERPC_FLAG_BHRB) {
+ if (num_entries_log2 > BHRB_MAX_NUM_ENTRIES_LOG2) {
+ num_entries_log2 = BHRB_MAX_NUM_ENTRIES_LOG2;
+ }
+ env->bhrb_num_entries = 1 << num_entries_log2;
+ env->bhrb_base = (intptr_t)&env->bhrb[0];
+ env->bhrb_offset_mask = (env->bhrb_num_entries * sizeof(uint64_t)) - 1;
+ }
+}
+
+static void bhrb_reset_state(CPUPPCState *env)
+{
+ if (env->flags & POWERPC_FLAG_BHRB) {
+ env->bhrb_offset = 0;
+ env->bhrb_filter = 0;
+ memset(env->bhrb, 0, sizeof(env->bhrb));
+ }
+}
+
+#define POWER8_BHRB_ENTRIES_LOG2 5
static void init_proc_POWER8(CPUPPCState *env)
{
/* Common Registers */
@@ -6165,6 +6258,7 @@ static void init_proc_POWER8(CPUPPCState *env)
register_power6_common_sprs(env);
register_HEIR32_spr(env);
register_power6_dbg_sprs(env);
+ register_power7_common_sprs(env);
register_power8_tce_address_control_sprs(env);
register_power8_ids_sprs(env);
register_power8_ebb_sprs(env);
@@ -6183,6 +6277,8 @@ static void init_proc_POWER8(CPUPPCState *env)
env->dcache_line_size = 128;
env->icache_line_size = 128;
+ bhrb_init_state(env, POWER8_BHRB_ENTRIES_LOG2);
+
/* Allocate hardware IRQ controller */
init_excp_POWER8(env);
ppcPOWER7_irq_init(env_archcpu(env));
@@ -6223,6 +6319,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
pcc->pcr_supported = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
pcc->init_proc = init_proc_POWER8;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_hid0;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6307,6 +6404,7 @@ static struct ppc_radix_page_info POWER9_radix_page_info = {
};
#endif /* CONFIG_USER_ONLY */
+#define POWER9_BHRB_ENTRIES_LOG2 5
static void init_proc_POWER9(CPUPPCState *env)
{
/* Common Registers */
@@ -6328,6 +6426,7 @@ static void init_proc_POWER9(CPUPPCState *env)
register_power6_common_sprs(env);
register_HEIR32_spr(env);
register_power6_dbg_sprs(env);
+ register_power7_common_sprs(env);
register_power8_tce_address_control_sprs(env);
register_power8_ids_sprs(env);
register_power8_ebb_sprs(env);
@@ -6357,6 +6456,8 @@ static void init_proc_POWER9(CPUPPCState *env)
env->dcache_line_size = 128;
env->icache_line_size = 128;
+ bhrb_init_state(env, POWER9_BHRB_ENTRIES_LOG2);
+
/* Allocate hardware IRQ controller */
init_excp_POWER9(env);
ppcPOWER9_irq_init(env_archcpu(env));
@@ -6412,6 +6513,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
PCR_COMPAT_2_05;
pcc->init_proc = init_proc_POWER9;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_hid0_power9;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6497,6 +6599,7 @@ static struct ppc_radix_page_info POWER10_radix_page_info = {
};
#endif /* !CONFIG_USER_ONLY */
+#define POWER10_BHRB_ENTRIES_LOG2 5
static void init_proc_POWER10(CPUPPCState *env)
{
/* Common Registers */
@@ -6518,6 +6621,7 @@ static void init_proc_POWER10(CPUPPCState *env)
register_power6_common_sprs(env);
register_HEIR64_spr(env);
register_power6_dbg_sprs(env);
+ register_power7_common_sprs(env);
register_power8_tce_address_control_sprs(env);
register_power8_ids_sprs(env);
register_power8_ebb_sprs(env);
@@ -6546,6 +6650,8 @@ static void init_proc_POWER10(CPUPPCState *env)
env->dcache_line_size = 128;
env->icache_line_size = 128;
+ bhrb_init_state(env, POWER10_BHRB_ENTRIES_LOG2);
+
/* Allocate hardware IRQ controller */
init_excp_POWER10(env);
ppcPOWER9_irq_init(env_archcpu(env));
@@ -6588,6 +6694,7 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
pcc->init_proc = init_proc_POWER10;
pcc->check_pow = check_pow_nocheck;
+ pcc->check_attn = check_attn_hid0_power9;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6650,7 +6757,8 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR |
- POWERPC_FLAG_VSX | POWERPC_FLAG_SCV;
+ POWERPC_FLAG_VSX | POWERPC_FLAG_SCV |
+ POWERPC_FLAG_BHRB;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
}
@@ -6661,6 +6769,7 @@ void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
CPUPPCState *env = &cpu->env;
cpu->vhyp = vhyp;
+ cpu->vhyp_class = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(vhyp);
/*
* With a virtual hypervisor mode we never allow the CPU to go
@@ -6800,20 +6909,17 @@ static void init_ppc_proc(PowerPCCPU *cpu)
}
/* Allocate TLBs buffer when needed */
#if !defined(CONFIG_USER_ONLY)
- if (env->nb_tlb != 0) {
- int nb_tlb = env->nb_tlb;
- if (env->id_tlbs != 0) {
- nb_tlb *= 2;
- }
+ if (env->nb_tlb) {
switch (env->tlb_type) {
case TLB_6XX:
- env->tlb.tlb6 = g_new0(ppc6xx_tlb_t, nb_tlb);
+ /* 6xx has separate TLBs for instructions and data hence times 2 */
+ env->tlb.tlb6 = g_new0(ppc6xx_tlb_t, 2 * env->nb_tlb);
break;
case TLB_EMB:
- env->tlb.tlbe = g_new0(ppcemb_tlb_t, nb_tlb);
+ env->tlb.tlbe = g_new0(ppcemb_tlb_t, env->nb_tlb);
break;
case TLB_MAS:
- env->tlb.tlbm = g_new0(ppcmas_tlb_t, nb_tlb);
+ env->tlb.tlbm = g_new0(ppcmas_tlb_t, env->nb_tlb);
break;
}
/* Pre-compute some useful values */
@@ -6824,6 +6930,11 @@ static void init_ppc_proc(PowerPCCPU *cpu)
warn_report("no power management check handler registered."
" Attempt QEMU to crash very soon !");
}
+
+ if (env->check_attn == NULL) {
+ warn_report("no attn check handler registered."
+ " Attempt QEMU to crash very soon !");
+ }
}
@@ -7195,7 +7306,7 @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
if (env->mmu_model != POWERPC_MMU_REAL) {
ppc_tlb_invalidate_all(env);
}
- pmu_mmcr01_updated(env);
+ pmu_mmcr01a_updated(env);
}
/* clean any pending stop state */
@@ -7221,6 +7332,10 @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
}
env->spr[i] = spr->default_value;
}
+
+#if defined(TARGET_PPC64)
+ bhrb_reset_state(env);
+#endif
}
#ifndef CONFIG_USER_ONLY
@@ -7248,9 +7363,7 @@ static void ppc_cpu_exec_enter(CPUState *cs)
PowerPCCPU *cpu = POWERPC_CPU(cs);
if (cpu->vhyp) {
- PPCVirtualHypervisorClass *vhc =
- PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
- vhc->cpu_exec_enter(cpu->vhyp, cpu);
+ cpu->vhyp_class->cpu_exec_enter(cpu->vhyp, cpu);
}
}
@@ -7259,9 +7372,7 @@ static void ppc_cpu_exec_exit(CPUState *cs)
PowerPCCPU *cpu = POWERPC_CPU(cs);
if (cpu->vhyp) {
- PPCVirtualHypervisorClass *vhc =
- PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
- vhc->cpu_exec_exit(cpu->vhyp, cpu);
+ cpu->vhyp_class->cpu_exec_exit(cpu->vhyp, cpu);
}
}
#endif /* CONFIG_TCG */
@@ -7285,6 +7396,7 @@ static void ppc_cpu_instance_init(Object *obj)
env->flags = pcc->flags;
env->bfd_mach = pcc->bfd_mach;
env->check_pow = pcc->check_pow;
+ env->check_attn = pcc->check_attn;
/*
* Mark HV mode as supported if the CPU has an MSR_HV bit in the
@@ -7409,6 +7521,11 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
#ifndef CONFIG_USER_ONLY
cc->sysemu_ops = &ppc_sysemu_ops;
INTERRUPT_STATS_PROVIDER_CLASS(oc)->get_statistics = ppc_get_irq_stats;
+
+ /* check_prot_access_type relies on MMU access and PAGE bits relations */
+ qemu_build_assert(MMU_DATA_LOAD == 0 && MMU_DATA_STORE == 1 &&
+ MMU_INST_FETCH == 2 && PAGE_READ == 1 &&
+ PAGE_WRITE == 2 && PAGE_EXEC == 4);
#endif
cc->gdb_num_core_regs = 71;