aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-12-17 11:52:04 +0000
committerPeter Maydell <peter.maydell@linaro.org>2019-12-17 11:52:04 +0000
commit98ac38cd5ad5e9496277c943020bc4bf16adf10b (patch)
treecbcd38b8289c65f607064a17e4de4799497bf5a6 /target
parente98e5c35d8d9b83186f8d697afd68113abbac736 (diff)
parenta363e9ed8731f45674260932a340a0d81c4b0a6f (diff)
downloadqemu-98ac38cd5ad5e9496277c943020bc4bf16adf10b.zip
qemu-98ac38cd5ad5e9496277c943020bc4bf16adf10b.tar.gz
qemu-98ac38cd5ad5e9496277c943020bc4bf16adf10b.tar.bz2
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-5.0-20191217' into staging
ppc patch queue 2019-12-17 This is the first pull request for the qemu-5.0 branch. It has a lot of accumulated changes, including: * SLOF update to support boot using the IOMMU (will become necessary for secure guests) * Clean ups to pnv handling of chip models * A number of extensions to the powernv machine model * TCG extensions to allow powernv emulated systems to run KVM guests * Outline support for POWER10 chips in powernv * Cleanups to the ibm,client-architecture-support feature negotiation path * XIVE reworks to better handle the powernv machine * Improvements to not waste interrupt queues and other semi-scarce resources when using XIVE under KVM # gpg: Signature made Tue 17 Dec 2019 04:42:20 GMT # gpg: using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full] # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full] # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full] # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown] # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-5.0-20191217: (88 commits) pseries: Update SLOF firmware image ppc/pnv: Drop PnvChipClass::type ppc/pnv: Introduce PnvChipClass::xscom_pcba() method ppc/pnv: Drop pnv_chip_is_power9() and pnv_chip_is_power10() helpers ppc/pnv: Pass content of the "compatible" property to pnv_dt_xscom() ppc/pnv: Pass XSCOM base address and address size to pnv_dt_xscom() ppc/pnv: Introduce PnvChipClass::xscom_core_base() method ppc/pnv: Introduce PnvChipClass::intc_print_info() method ppc/pnv: Drop pnv_is_power9() and pnv_is_power10() helpers ppc/pnv: Introduce PnvMachineClass::dt_power_mgt() ppc/pnv: Introduce PnvMachineClass and PnvMachineClass::compat ppc/pnv: Drop PnvPsiClass::chip_type ppc/pnv: Introduce PnvPsiClass::compat ppc: Drop useless extern annotation for functions ppc/pnv: Fix OCC common area region mapping ppc/pnv: Introduce PBA registers ppc/pnv: Make PnvXScomInterface an incomplete type ppc/pnv: populate the DT with realized XSCOM devices ppc/pnv: Loop on the whole hierarchy to populate the DT with the XSCOM nodes target/ppc: Add SPR TBU40 ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/ppc/compat.c21
-rw-r--r--target/ppc/cpu-models.c3
-rw-r--r--target/ppc/cpu-models.h3
-rw-r--r--target/ppc/cpu.h14
-rw-r--r--target/ppc/helper.h4
-rw-r--r--target/ppc/helper_regs.h5
-rw-r--r--target/ppc/kvm.c6
-rw-r--r--target/ppc/kvm_ppc.h4
-rw-r--r--target/ppc/timebase_helper.c20
-rw-r--r--target/ppc/translate_init.inc.c283
10 files changed, 335 insertions, 28 deletions
diff --git a/target/ppc/compat.c b/target/ppc/compat.c
index 7de4bf3..f48df25 100644
--- a/target/ppc/compat.c
+++ b/target/ppc/compat.c
@@ -51,36 +51,38 @@ static const CompatInfo compat_table[] = {
{ /* POWER6, ISA2.05 */
.name = "power6",
.pvr = CPU_POWERPC_LOGICAL_2_05,
- .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 |
- PCR_COMPAT_2_05 | PCR_TM_DIS | PCR_VSX_DIS,
+ .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 |
+ PCR_COMPAT_2_06 | PCR_COMPAT_2_05 | PCR_TM_DIS | PCR_VSX_DIS,
.pcr_level = PCR_COMPAT_2_05,
.max_vthreads = 2,
},
{ /* POWER7, ISA2.06 */
.name = "power7",
.pvr = CPU_POWERPC_LOGICAL_2_06,
- .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS,
+ .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 |
+ PCR_COMPAT_2_06 | PCR_TM_DIS,
.pcr_level = PCR_COMPAT_2_06,
.max_vthreads = 4,
},
{
.name = "power7+",
.pvr = CPU_POWERPC_LOGICAL_2_06_PLUS,
- .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS,
+ .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 |
+ PCR_COMPAT_2_06 | PCR_TM_DIS,
.pcr_level = PCR_COMPAT_2_06,
.max_vthreads = 4,
},
{ /* POWER8, ISA2.07 */
.name = "power8",
.pvr = CPU_POWERPC_LOGICAL_2_07,
- .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07,
+ .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07,
.pcr_level = PCR_COMPAT_2_07,
.max_vthreads = 8,
},
{ /* POWER9, ISA3.00 */
.name = "power9",
.pvr = CPU_POWERPC_LOGICAL_3_00,
- .pcr = PCR_COMPAT_3_00,
+ .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00,
.pcr_level = PCR_COMPAT_3_00,
/*
* POWER9 hardware only supports 4 threads / core, but this
@@ -91,6 +93,13 @@ static const CompatInfo compat_table[] = {
*/
.max_vthreads = 8,
},
+ { /* POWER10, ISA3.10 */
+ .name = "power10",
+ .pvr = CPU_POWERPC_LOGICAL_3_10,
+ .pcr = PCR_COMPAT_3_10,
+ .pcr_level = PCR_COMPAT_3_10,
+ .max_vthreads = 8,
+ },
};
static const CompatInfo *compat_by_pvr(uint32_t pvr)
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index 086548e..4ad1686 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -774,6 +774,8 @@
"POWER9 v1.0")
POWERPC_DEF("power9_v2.0", CPU_POWERPC_POWER9_DD20, POWER9,
"POWER9 v2.0")
+ POWERPC_DEF("power10_v1.0", CPU_POWERPC_POWER10_DD1, POWER10,
+ "POWER10 v1.0")
#endif /* defined (TARGET_PPC64) */
/***************************************************************************/
@@ -950,6 +952,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
{ "power8", "power8_v2.0" },
{ "power8nvl", "power8nvl_v1.0" },
{ "power9", "power9_v2.0" },
+ { "power10", "power10_v1.0" },
#endif
/* Generic PowerPCs */
diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
index 4fdb730..ce750b2 100644
--- a/target/ppc/cpu-models.h
+++ b/target/ppc/cpu-models.h
@@ -373,6 +373,8 @@ enum {
CPU_POWERPC_POWER9_BASE = 0x004E0000,
CPU_POWERPC_POWER9_DD1 = 0x004E0100,
CPU_POWERPC_POWER9_DD20 = 0x004E1200,
+ CPU_POWERPC_POWER10_BASE = 0x00800000,
+ CPU_POWERPC_POWER10_DD1 = 0x00800100,
CPU_POWERPC_970_v22 = 0x00390202,
CPU_POWERPC_970FX_v10 = 0x00391100,
CPU_POWERPC_970FX_v20 = 0x003C0200,
@@ -409,6 +411,7 @@ enum {
CPU_POWERPC_LOGICAL_2_06_PLUS = 0x0F100003,
CPU_POWERPC_LOGICAL_2_07 = 0x0F000004,
CPU_POWERPC_LOGICAL_3_00 = 0x0F000005,
+ CPU_POWERPC_LOGICAL_3_10 = 0x0F000006,
};
/* System version register (used on MPC 8xxx) */
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index e3e8232..103bfe9 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1090,7 +1090,9 @@ struct CPUPPCState {
#if !defined(CONFIG_USER_ONLY)
/*
* This is the IRQ controller, which is implementation dependent
- * and only relevant when emulating a complete machine.
+ * and only relevant when emulating a complete machine. Note that
+ * this isn't used by recent Book3s compatible CPUs (POWER7 and
+ * newer).
*/
uint32_t irq_input_state;
void **irq_inputs;
@@ -1220,10 +1222,6 @@ PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr);
PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr);
PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc);
-struct PPCVirtualHypervisor {
- Object parent;
-};
-
struct PPCVirtualHypervisorClass {
InterfaceClass parent;
void (*hypercall)(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu);
@@ -1305,12 +1303,16 @@ uint64_t cpu_ppc_load_atbl(CPUPPCState *env);
uint32_t cpu_ppc_load_atbu(CPUPPCState *env);
void cpu_ppc_store_atbl(CPUPPCState *env, uint32_t value);
void cpu_ppc_store_atbu(CPUPPCState *env, uint32_t value);
+uint64_t cpu_ppc_load_vtb(CPUPPCState *env);
+void cpu_ppc_store_vtb(CPUPPCState *env, uint64_t value);
bool ppc_decr_clear_on_delivery(CPUPPCState *env);
target_ulong cpu_ppc_load_decr(CPUPPCState *env);
void cpu_ppc_store_decr(CPUPPCState *env, target_ulong value);
target_ulong cpu_ppc_load_hdecr(CPUPPCState *env);
void cpu_ppc_store_hdecr(CPUPPCState *env, target_ulong value);
+void cpu_ppc_store_tbu40(CPUPPCState *env, uint64_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)
@@ -1777,6 +1779,7 @@ typedef PowerPCCPU ArchCPU;
#define SPR_MPC_MD_DBRAM1 (0x32A)
#define SPR_RCPU_L2U_RA3 (0x32B)
#define SPR_TAR (0x32F)
+#define SPR_ASDR (0x330)
#define SPR_IC (0x350)
#define SPR_VTB (0x351)
#define SPR_MMCRC (0x353)
@@ -2366,6 +2369,7 @@ enum {
PCR_COMPAT_2_06 = PPC_BIT(61),
PCR_COMPAT_2_07 = PPC_BIT(60),
PCR_COMPAT_3_00 = PPC_BIT(59),
+ PCR_COMPAT_3_10 = PPC_BIT(58),
PCR_VEC_DIS = PPC_BIT(0), /* Vec. disable (bit NA since POWER8) */
PCR_VSX_DIS = PPC_BIT(1), /* VSX disable (bit NA since POWER8) */
PCR_TM_DIS = PPC_BIT(2), /* Trans. memory disable (POWER8) */
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index f843814..cd0dfe3 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -649,11 +649,13 @@ DEF_HELPER_FLAGS_1(load_tbl, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_1(load_tbu, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_1(load_atbl, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_1(load_atbu, TCG_CALL_NO_RWG, tl, env)
+DEF_HELPER_FLAGS_1(load_vtb, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_1(load_601_rtcl, TCG_CALL_NO_RWG, tl, env)
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_FLAGS_2(store_purr, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_2(store_ptcr, void, env, tl)
#endif
DEF_HELPER_2(store_sdr1, void, env, tl)
@@ -669,6 +671,8 @@ DEF_HELPER_FLAGS_1(load_decr, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_2(store_decr, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_1(load_hdecr, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_2(store_hdecr, TCG_CALL_NO_RWG, void, env, tl)
+DEF_HELPER_FLAGS_2(store_vtb, TCG_CALL_NO_RWG, void, env, tl)
+DEF_HELPER_FLAGS_2(store_tbu40, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_2(store_hid0_601, void, env, tl)
DEF_HELPER_3(store_403_pbr, void, env, i32, tl)
DEF_HELPER_FLAGS_1(load_40x_pit, TCG_CALL_NO_RWG, tl, env)
diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h
index 85dfe76..d78c2af 100644
--- a/target/ppc/helper_regs.h
+++ b/target/ppc/helper_regs.h
@@ -22,6 +22,7 @@
#include "qemu/main-loop.h"
#include "exec/exec-all.h"
+#include "sysemu/kvm.h"
/* Swap temporary saved registers with GPRs */
static inline void hreg_swap_gpr_tgpr(CPUPPCState *env)
@@ -102,6 +103,10 @@ static inline void hreg_compute_hflags(CPUPPCState *env)
static inline void cpu_interrupt_exittb(CPUState *cs)
{
+ if (!kvm_enabled()) {
+ return;
+ }
+
if (!qemu_mutex_iothread_locked()) {
qemu_mutex_lock_iothread();
cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index c77f984..7406d18 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2076,7 +2076,7 @@ int kvmppc_set_smt_threads(int smt)
return ret;
}
-void kvmppc_hint_smt_possible(Error **errp)
+void kvmppc_error_append_smt_possible_hint(Error **errp_in)
{
int i;
GString *g;
@@ -2091,10 +2091,10 @@ void kvmppc_hint_smt_possible(Error **errp)
}
}
s = g_string_free(g, false);
- error_append_hint(errp, "%s.\n", s);
+ error_append_hint(errp_in, "%s.\n", s);
g_free(s);
} else {
- error_append_hint(errp,
+ error_append_hint(errp_in,
"This KVM seems to be too old to support VSMT.\n");
}
}
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index 98bd7d5..47b08a4 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -28,7 +28,7 @@ void kvmppc_set_papr(PowerPCCPU *cpu);
int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr);
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
int kvmppc_smt_threads(void);
-void kvmppc_hint_smt_possible(Error **errp);
+void kvmppc_error_append_smt_possible_hint(Error **errp_in);
int kvmppc_set_smt_threads(int smt);
int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits);
int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits);
@@ -164,7 +164,7 @@ static inline int kvmppc_smt_threads(void)
return 1;
}
-static inline void kvmppc_hint_smt_possible(Error **errp)
+static inline void kvmppc_error_append_smt_possible_hint(Error **errp_in)
{
return;
}
diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c
index 73363e0..703bd9e 100644
--- a/target/ppc/timebase_helper.c
+++ b/target/ppc/timebase_helper.c
@@ -45,11 +45,21 @@ target_ulong helper_load_atbu(CPUPPCState *env)
return cpu_ppc_load_atbu(env);
}
+target_ulong helper_load_vtb(CPUPPCState *env)
+{
+ return cpu_ppc_load_vtb(env);
+}
+
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
target_ulong helper_load_purr(CPUPPCState *env)
{
return (target_ulong)cpu_ppc_load_purr(env);
}
+
+void helper_store_purr(CPUPPCState *env, target_ulong val)
+{
+ cpu_ppc_store_purr(env, val);
+}
#endif
target_ulong helper_load_601_rtcl(CPUPPCState *env)
@@ -113,6 +123,16 @@ void helper_store_hdecr(CPUPPCState *env, target_ulong val)
cpu_ppc_store_hdecr(env, val);
}
+void helper_store_vtb(CPUPPCState *env, target_ulong val)
+{
+ cpu_ppc_store_vtb(env, val);
+}
+
+void helper_store_tbu40(CPUPPCState *env, target_ulong val)
+{
+ cpu_ppc_store_tbu40(env, val);
+}
+
target_ulong helper_load_40x_pit(CPUPPCState *env)
{
return load_40x_pit(env);
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index ba726de..d33d65d 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -287,6 +287,11 @@ static void spr_read_purr(DisasContext *ctx, int gprn, int sprn)
gen_helper_load_purr(cpu_gpr[gprn], cpu_env);
}
+static void spr_write_purr(DisasContext *ctx, int sprn, int gprn)
+{
+ gen_helper_store_purr(cpu_env, cpu_gpr[gprn]);
+}
+
/* HDECR */
static void spr_read_hdecr(DisasContext *ctx, int gprn, int sprn)
{
@@ -312,6 +317,21 @@ static void spr_write_hdecr(DisasContext *ctx, int sprn, int gprn)
}
}
+static void spr_read_vtb(DisasContext *ctx, int gprn, int sprn)
+{
+ gen_helper_load_vtb(cpu_gpr[gprn], cpu_env);
+}
+
+static void spr_write_vtb(DisasContext *ctx, int sprn, int gprn)
+{
+ gen_helper_store_vtb(cpu_env, cpu_gpr[gprn]);
+}
+
+static void spr_write_tbu40(DisasContext *ctx, int sprn, int gprn)
+{
+ gen_helper_store_tbu40(cpu_env, cpu_gpr[gprn]);
+}
+
#endif
#endif
@@ -3354,6 +3374,11 @@ static void init_excp_POWER9(CPUPPCState *env)
#endif
}
+static void init_excp_POWER10(CPUPPCState *env)
+{
+ init_excp_POWER9(env);
+}
+
#endif
/*****************************************************************************/
@@ -7833,6 +7858,16 @@ static void gen_spr_power5p_ear(CPUPPCState *env)
0x00000000);
}
+static void gen_spr_power5p_tb(CPUPPCState *env)
+{
+ /* TBU40 (High 40 bits of the Timebase register */
+ spr_register_hv(env, SPR_TBU40, "TBU40",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, &spr_write_tbu40,
+ 0x00000000);
+}
+
#if !defined(CONFIG_USER_ONLY)
static void spr_write_hmer(DisasContext *ctx, int sprn, int gprn)
{
@@ -7998,14 +8033,16 @@ static void gen_spr_book3s_purr(CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
/* PURR & SPURR: Hack - treat these as aliases for the TB for now */
- spr_register_kvm(env, SPR_PURR, "PURR",
- &spr_read_purr, SPR_NOACCESS,
- &spr_read_purr, SPR_NOACCESS,
- KVM_REG_PPC_PURR, 0x00000000);
- spr_register_kvm(env, SPR_SPURR, "SPURR",
- &spr_read_purr, SPR_NOACCESS,
- &spr_read_purr, SPR_NOACCESS,
- KVM_REG_PPC_SPURR, 0x00000000);
+ spr_register_kvm_hv(env, SPR_PURR, "PURR",
+ &spr_read_purr, SPR_NOACCESS,
+ &spr_read_purr, SPR_NOACCESS,
+ &spr_read_purr, &spr_write_purr,
+ KVM_REG_PPC_PURR, 0x00000000);
+ spr_register_kvm_hv(env, SPR_SPURR, "SPURR",
+ &spr_read_purr, SPR_NOACCESS,
+ &spr_read_purr, SPR_NOACCESS,
+ &spr_read_purr, &spr_write_purr,
+ KVM_REG_PPC_SPURR, 0x00000000);
#endif
}
@@ -8169,10 +8206,11 @@ static void gen_spr_power8_ebb(CPUPPCState *env)
/* Virtual Time Base */
static void gen_spr_vtb(CPUPPCState *env)
{
- spr_register_kvm(env, SPR_VTB, "VTB",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_tbl, SPR_NOACCESS,
- KVM_REG_PPC_VTB, 0x00000000);
+ spr_register_kvm_hv(env, SPR_VTB, "VTB",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_vtb, SPR_NOACCESS,
+ &spr_read_vtb, &spr_write_vtb,
+ KVM_REG_PPC_VTB, 0x00000000);
}
static void gen_spr_power8_fscr(CPUPPCState *env)
@@ -8272,6 +8310,12 @@ static void gen_spr_power9_mmu(CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_ptcr,
KVM_REG_PPC_PTCR, 0x00000000);
+ /* Address Segment Descriptor Register */
+ spr_register_hv(env, SPR_ASDR, "ASDR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x0000000000000000);
#endif
}
@@ -8375,6 +8419,7 @@ static void init_proc_power5plus(CPUPPCState *env)
gen_spr_power5p_common(env);
gen_spr_power5p_lpar(env);
gen_spr_power5p_ear(env);
+ gen_spr_power5p_tb(env);
/* env variables */
env->dcache_line_size = 128;
@@ -8487,6 +8532,7 @@ static void init_proc_POWER7(CPUPPCState *env)
gen_spr_power5p_common(env);
gen_spr_power5p_lpar(env);
gen_spr_power5p_ear(env);
+ gen_spr_power5p_tb(env);
gen_spr_power6_common(env);
gen_spr_power6_dbg(env);
gen_spr_power7_book4(env);
@@ -8628,6 +8674,7 @@ static void init_proc_POWER8(CPUPPCState *env)
gen_spr_power5p_common(env);
gen_spr_power5p_lpar(env);
gen_spr_power5p_ear(env);
+ gen_spr_power5p_tb(env);
gen_spr_power6_common(env);
gen_spr_power6_dbg(env);
gen_spr_power8_tce_address_control(env);
@@ -8818,6 +8865,7 @@ static void init_proc_POWER9(CPUPPCState *env)
gen_spr_power5p_common(env);
gen_spr_power5p_lpar(env);
gen_spr_power5p_ear(env);
+ gen_spr_power5p_tb(env);
gen_spr_power6_common(env);
gen_spr_power6_dbg(env);
gen_spr_power8_tce_address_control(env);
@@ -8996,6 +9044,216 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
}
+#ifdef CONFIG_SOFTMMU
+/*
+ * Radix pg sizes and AP encodings for dt node ibm,processor-radix-AP-encodings
+ * Encoded as array of int_32s in the form:
+ * 0bxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
+ * x -> AP encoding
+ * y -> radix mode supported page size (encoded as a shift)
+ */
+static struct ppc_radix_page_info POWER10_radix_page_info = {
+ .count = 4,
+ .entries = {
+ 0x0000000c, /* 4K - enc: 0x0 */
+ 0xa0000010, /* 64K - enc: 0x5 */
+ 0x20000015, /* 2M - enc: 0x1 */
+ 0x4000001e /* 1G - enc: 0x2 */
+ }
+};
+#endif /* CONFIG_SOFTMMU */
+
+static void init_proc_POWER10(CPUPPCState *env)
+{
+ /* Common Registers */
+ init_proc_book3s_common(env);
+ gen_spr_book3s_207_dbg(env);
+
+ /* POWER8 Specific Registers */
+ gen_spr_book3s_ids(env);
+ gen_spr_amr(env);
+ gen_spr_iamr(env);
+ gen_spr_book3s_purr(env);
+ gen_spr_power5p_common(env);
+ gen_spr_power5p_lpar(env);
+ gen_spr_power5p_ear(env);
+ gen_spr_power6_common(env);
+ gen_spr_power6_dbg(env);
+ gen_spr_power8_tce_address_control(env);
+ gen_spr_power8_ids(env);
+ gen_spr_power8_ebb(env);
+ gen_spr_power8_fscr(env);
+ gen_spr_power8_pmu_sup(env);
+ gen_spr_power8_pmu_user(env);
+ gen_spr_power8_tm(env);
+ gen_spr_power8_pspb(env);
+ gen_spr_vtb(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,
+ spr_read_generic, spr_write_generic,
+ KVM_REG_PPC_TIDR, 0);
+
+ /* FIXME: Filter fields properly based on privilege level */
+ spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL,
+ spr_read_generic, spr_write_generic,
+ KVM_REG_PPC_PSSCR, 0);
+
+ /* env variables */
+ env->dcache_line_size = 128;
+ env->icache_line_size = 128;
+
+ /* Allocate hardware IRQ controller */
+ init_excp_POWER10(env);
+ ppcPOWER9_irq_init(env_archcpu(env));
+}
+
+static bool ppc_pvr_match_power10(PowerPCCPUClass *pcc, uint32_t pvr)
+{
+ if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER10_BASE) {
+ return true;
+ }
+ return false;
+}
+
+static bool cpu_has_work_POWER10(CPUState *cs)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+
+ if (cs->halted) {
+ uint64_t psscr = env->spr[SPR_PSSCR];
+
+ if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
+ return false;
+ }
+
+ /* If EC is clear, just return true on any pending interrupt */
+ if (!(psscr & PSSCR_EC)) {
+ return true;
+ }
+ /* External Exception */
+ if ((env->pending_interrupts & (1u << PPC_INTERRUPT_EXT)) &&
+ (env->spr[SPR_LPCR] & LPCR_EEE)) {
+ bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
+ if (heic == 0 || !msr_hv || msr_pr) {
+ return true;
+ }
+ }
+ /* Decrementer Exception */
+ if ((env->pending_interrupts & (1u << PPC_INTERRUPT_DECR)) &&
+ (env->spr[SPR_LPCR] & LPCR_DEE)) {
+ return true;
+ }
+ /* Machine Check or Hypervisor Maintenance Exception */
+ if ((env->pending_interrupts & (1u << PPC_INTERRUPT_MCK |
+ 1u << PPC_INTERRUPT_HMI)) && (env->spr[SPR_LPCR] & LPCR_OEE)) {
+ return true;
+ }
+ /* Privileged Doorbell Exception */
+ if ((env->pending_interrupts & (1u << PPC_INTERRUPT_DOORBELL)) &&
+ (env->spr[SPR_LPCR] & LPCR_PDEE)) {
+ return true;
+ }
+ /* Hypervisor Doorbell Exception */
+ if ((env->pending_interrupts & (1u << PPC_INTERRUPT_HDOORBELL)) &&
+ (env->spr[SPR_LPCR] & LPCR_HDEE)) {
+ return true;
+ }
+ /* Hypervisor virtualization exception */
+ if ((env->pending_interrupts & (1u << PPC_INTERRUPT_HVIRT)) &&
+ (env->spr[SPR_LPCR] & LPCR_HVEE)) {
+ return true;
+ }
+ if (env->pending_interrupts & (1u << PPC_INTERRUPT_RESET)) {
+ return true;
+ }
+ return false;
+ } else {
+ return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD);
+ }
+}
+
+POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+ CPUClass *cc = CPU_CLASS(oc);
+
+ dc->fw_name = "PowerPC,POWER10";
+ dc->desc = "POWER10";
+ dc->props = powerpc_servercpu_properties;
+ pcc->pvr_match = ppc_pvr_match_power10;
+ pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07 |
+ PCR_COMPAT_3_00;
+ pcc->pcr_supported = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 |
+ PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
+ pcc->init_proc = init_proc_POWER10;
+ pcc->check_pow = check_pow_nocheck;
+ cc->has_work = cpu_has_work_POWER10;
+ 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 |
+ PPC_FLOAT_FRSQRTES |
+ PPC_FLOAT_STFIWX |
+ PPC_FLOAT_EXT |
+ PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+ PPC_MEM_SYNC | PPC_MEM_EIEIO |
+ PPC_MEM_TLBSYNC |
+ PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC |
+ PPC_SEGMENT_64B | PPC_SLBI |
+ PPC_POPCNTB | PPC_POPCNTWD |
+ PPC_CILDST;
+ pcc->insns_flags2 = PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX |
+ PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 |
+ PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 |
+ PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
+ PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
+ PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
+ PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL;
+ pcc->msr_mask = (1ull << MSR_SF) |
+ (1ull << MSR_SHV) |
+ (1ull << MSR_TM) |
+ (1ull << MSR_VR) |
+ (1ull << MSR_VSX) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
+ pcc->mmu_model = POWERPC_MMU_3_00;
+#if defined(CONFIG_SOFTMMU)
+ pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault;
+ /* segment page size remain the same */
+ pcc->hash64_opts = &ppc_hash64_opts_POWER7;
+ pcc->radix_page_info = &POWER10_radix_page_info;
+ pcc->lrg_decr_bits = 56;
+#endif
+ pcc->excp_model = POWERPC_EXCP_POWER9;
+ pcc->bus_model = PPC_FLAGS_INPUT_POWER9;
+ pcc->bfd_mach = bfd_mach_ppc64;
+ 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_TM;
+ pcc->l1_dcache_size = 0x8000;
+ pcc->l1_icache_size = 0x8000;
+ pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
+ pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
+}
+
#if !defined(CONFIG_USER_ONLY)
void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
{
@@ -10461,6 +10719,7 @@ static void ppc_cpu_reset(CPUState *s)
env->pending_interrupts = 0;
s->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
+ ppc_irq_reset(cpu);
/* tininess for underflow is detected before rounding */
set_float_detect_tininess(float_tininess_before_rounding,