aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/Kconfig19
-rw-r--r--target/alpha/Kconfig2
-rw-r--r--target/arm/Kconfig6
-rw-r--r--target/arm/helper.c16
-rw-r--r--target/avr/Kconfig2
-rw-r--r--target/cris/Kconfig2
-rw-r--r--target/hppa/Kconfig2
-rw-r--r--target/i386/Kconfig5
-rw-r--r--target/i386/cpu.h2
-rw-r--r--target/i386/helper.h3
-rw-r--r--target/i386/svm.h3
-rw-r--r--target/i386/tcg/bpt_helper.c21
-rw-r--r--target/i386/tcg/sysemu/bpt_helper.c47
-rw-r--r--target/i386/tcg/sysemu/svm_helper.c24
-rw-r--r--target/i386/tcg/translate.c1
-rw-r--r--target/m68k/Kconfig2
-rw-r--r--target/microblaze/Kconfig2
-rw-r--r--target/mips/Kconfig6
-rw-r--r--target/nios2/Kconfig2
-rw-r--r--target/openrisc/Kconfig2
-rw-r--r--target/ppc/Kconfig5
-rw-r--r--target/ppc/arch_dump.c8
-rw-r--r--target/ppc/cpu-qom.h2
-rw-r--r--target/ppc/cpu.c2
-rw-r--r--target/ppc/cpu.h15
-rw-r--r--target/ppc/cpu_init.c64
-rw-r--r--target/ppc/excp_helper.c3
-rw-r--r--target/ppc/kvm.c12
-rw-r--r--target/ppc/kvm_ppc.h12
-rw-r--r--target/ppc/mmu-book3s-v3.c19
-rw-r--r--target/ppc/mmu-book3s-v3.h6
-rw-r--r--target/ppc/mmu-books.h30
-rw-r--r--target/ppc/mmu-hash32.c254
-rw-r--r--target/ppc/mmu-hash32.h8
-rw-r--r--target/ppc/mmu-hash64.c157
-rw-r--r--target/ppc/mmu-hash64.h6
-rw-r--r--target/ppc/mmu-radix64.c151
-rw-r--r--target/ppc/mmu-radix64.h6
-rw-r--r--target/ppc/mmu_helper.c215
-rw-r--r--target/ppc/translate.c5
-rw-r--r--target/riscv/Kconfig5
-rw-r--r--target/rx/Kconfig2
-rw-r--r--target/s390x/Kconfig2
-rw-r--r--target/s390x/translate.c6
-rw-r--r--target/sh4/Kconfig2
-rw-r--r--target/sparc/Kconfig5
-rw-r--r--target/tricore/Kconfig2
-rw-r--r--target/xtensa/Kconfig2
-rw-r--r--target/xtensa/xtensa-semi.c84
49 files changed, 618 insertions, 641 deletions
diff --git a/target/Kconfig b/target/Kconfig
new file mode 100644
index 0000000000..ae7f24fc66
--- /dev/null
+++ b/target/Kconfig
@@ -0,0 +1,19 @@
+source alpha/Kconfig
+source arm/Kconfig
+source avr/Kconfig
+source cris/Kconfig
+source hppa/Kconfig
+source i386/Kconfig
+source m68k/Kconfig
+source microblaze/Kconfig
+source mips/Kconfig
+source nios2/Kconfig
+source openrisc/Kconfig
+source ppc/Kconfig
+source riscv/Kconfig
+source rx/Kconfig
+source s390x/Kconfig
+source sh4/Kconfig
+source sparc/Kconfig
+source tricore/Kconfig
+source xtensa/Kconfig
diff --git a/target/alpha/Kconfig b/target/alpha/Kconfig
new file mode 100644
index 0000000000..267222c05b
--- /dev/null
+++ b/target/alpha/Kconfig
@@ -0,0 +1,2 @@
+config ALPHA
+ bool
diff --git a/target/arm/Kconfig b/target/arm/Kconfig
new file mode 100644
index 0000000000..3f3394a22b
--- /dev/null
+++ b/target/arm/Kconfig
@@ -0,0 +1,6 @@
+config ARM
+ bool
+
+config AARCH64
+ bool
+ select ARM
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a66c1f0b9e..910ace4274 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6326,11 +6326,21 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
.access = PL1_RW, .accessfn = access_tda,
.fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1),
.resetvalue = 0 },
- /* MDCCSR_EL0, aka DBGDSCRint. This is a read-only mirror of MDSCR_EL1.
+ /*
+ * MDCCSR_EL0[30:29] map to EDSCR[30:29]. Simply RAZ as the external
+ * Debug Communication Channel is not implemented.
+ */
+ { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 1, .opc2 = 0,
+ .access = PL0_R, .accessfn = access_tda,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ /*
+ * DBGDSCRint[15,12,5:2] map to MDSCR_EL1[15,12,5:2]. Map all bits as
+ * it is unlikely a guest will care.
* We don't implement the configurable EL0 access.
*/
- { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_BOTH,
- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
+ { .name = "DBGDSCRint", .state = ARM_CP_STATE_AA32,
+ .cp = 14, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
.type = ARM_CP_ALIAS,
.access = PL1_R, .accessfn = access_tda,
.fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), },
diff --git a/target/avr/Kconfig b/target/avr/Kconfig
new file mode 100644
index 0000000000..155592d353
--- /dev/null
+++ b/target/avr/Kconfig
@@ -0,0 +1,2 @@
+config AVR
+ bool
diff --git a/target/cris/Kconfig b/target/cris/Kconfig
new file mode 100644
index 0000000000..3fdc309fbb
--- /dev/null
+++ b/target/cris/Kconfig
@@ -0,0 +1,2 @@
+config CRIS
+ bool
diff --git a/target/hppa/Kconfig b/target/hppa/Kconfig
new file mode 100644
index 0000000000..395a35d799
--- /dev/null
+++ b/target/hppa/Kconfig
@@ -0,0 +1,2 @@
+config HPPA
+ bool
diff --git a/target/i386/Kconfig b/target/i386/Kconfig
new file mode 100644
index 0000000000..ce6968906e
--- /dev/null
+++ b/target/i386/Kconfig
@@ -0,0 +1,5 @@
+config I386
+ bool
+
+config X86_64
+ bool
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 0f7ddbfeae..8f3747dd28 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -268,6 +268,8 @@ typedef enum X86Seg {
#define DR7_TYPE_IO_RW 0x2
#define DR7_TYPE_DATA_RW 0x3
+#define DR_RESERVED_MASK 0xffffffff00000000ULL
+
#define PG_PRESENT_BIT 0
#define PG_RW_BIT 1
#define PG_USER_BIT 2
diff --git a/target/i386/helper.h b/target/i386/helper.h
index f3d8c3f949..574ff75615 100644
--- a/target/i386/helper.h
+++ b/target/i386/helper.h
@@ -46,9 +46,8 @@ DEF_HELPER_1(clts, void, env)
#ifndef CONFIG_USER_ONLY
DEF_HELPER_FLAGS_3(set_dr, TCG_CALL_NO_WG, void, env, int, tl)
-#endif /* !CONFIG_USER_ONLY */
-
DEF_HELPER_FLAGS_2(get_dr, TCG_CALL_NO_WG, tl, env, int)
+#endif /* !CONFIG_USER_ONLY */
DEF_HELPER_1(sysenter, void, env)
DEF_HELPER_2(sysexit, void, env, int)
diff --git a/target/i386/svm.h b/target/i386/svm.h
index 5098733053..adc058dc76 100644
--- a/target/i386/svm.h
+++ b/target/i386/svm.h
@@ -137,6 +137,9 @@
#define SVM_CR0_RESERVED_MASK 0xffffffff00000000U
+#define SVM_MSRPM_SIZE (1ULL << 13)
+#define SVM_IOPM_SIZE ((1ULL << 13) + 1)
+
struct QEMU_PACKED vmcb_control_area {
uint16_t intercept_cr_read;
uint16_t intercept_cr_write;
diff --git a/target/i386/tcg/bpt_helper.c b/target/i386/tcg/bpt_helper.c
index 83cd89581e..b6c1fff16e 100644
--- a/target/i386/tcg/bpt_helper.c
+++ b/target/i386/tcg/bpt_helper.c
@@ -37,24 +37,3 @@ void helper_rechecking_single_step(CPUX86State *env)
helper_single_step(env);
}
}
-
-target_ulong helper_get_dr(CPUX86State *env, int reg)
-{
- switch (reg) {
- case 0: case 1: case 2: case 3: case 6: case 7:
- return env->dr[reg];
- case 4:
- if (env->cr[4] & CR4_DE_MASK) {
- break;
- } else {
- return env->dr[6];
- }
- case 5:
- if (env->cr[4] & CR4_DE_MASK) {
- break;
- } else {
- return env->dr[7];
- }
- }
- raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
-}
diff --git a/target/i386/tcg/sysemu/bpt_helper.c b/target/i386/tcg/sysemu/bpt_helper.c
index f1fb479ad9..624f90b789 100644
--- a/target/i386/tcg/sysemu/bpt_helper.c
+++ b/target/i386/tcg/sysemu/bpt_helper.c
@@ -228,10 +228,30 @@ void breakpoint_handler(CPUState *cs)
}
}
+target_ulong helper_get_dr(CPUX86State *env, int reg)
+{
+ if (reg >= 4 && reg < 6) {
+ if (env->cr[4] & CR4_DE_MASK) {
+ raise_exception_ra(env, EXCP06_ILLOP, GETPC());
+ } else {
+ reg += 2;
+ }
+ }
+
+ return env->dr[reg];
+}
+
void helper_set_dr(CPUX86State *env, int reg, target_ulong t0)
{
- switch (reg) {
- case 0: case 1: case 2: case 3:
+ if (reg >= 4 && reg < 6) {
+ if (env->cr[4] & CR4_DE_MASK) {
+ raise_exception_ra(env, EXCP06_ILLOP, GETPC());
+ } else {
+ reg += 2;
+ }
+ }
+
+ if (reg < 4) {
if (hw_breakpoint_enabled(env->dr[7], reg)
&& hw_breakpoint_type(env->dr[7], reg) != DR7_TYPE_IO_RW) {
hw_breakpoint_remove(env, reg);
@@ -240,25 +260,16 @@ void helper_set_dr(CPUX86State *env, int reg, target_ulong t0)
} else {
env->dr[reg] = t0;
}
- return;
- case 4:
- if (env->cr[4] & CR4_DE_MASK) {
- break;
+ } else {
+ if (t0 & DR_RESERVED_MASK) {
+ raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
}
- /* fallthru */
- case 6:
- env->dr[6] = t0 | DR6_FIXED_1;
- return;
- case 5:
- if (env->cr[4] & CR4_DE_MASK) {
- break;
+ if (reg == 6) {
+ env->dr[6] = t0 | DR6_FIXED_1;
+ } else {
+ cpu_x86_update_dr7(env, t0);
}
- /* fallthru */
- case 7:
- cpu_x86_update_dr7(env, t0);
- return;
}
- raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
}
/* Check if Port I/O is trapped by a breakpoint. */
diff --git a/target/i386/tcg/sysemu/svm_helper.c b/target/i386/tcg/sysemu/svm_helper.c
index 1c2dbc1862..00618cff23 100644
--- a/target/i386/tcg/sysemu/svm_helper.c
+++ b/target/i386/tcg/sysemu/svm_helper.c
@@ -68,6 +68,7 @@ static inline void svm_load_seg_cache(CPUX86State *env, hwaddr addr,
void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
{
CPUState *cs = env_cpu(env);
+ X86CPU *cpu = env_archcpu(env);
target_ulong addr;
uint64_t nested_ctl;
uint32_t event_inj;
@@ -159,6 +160,20 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
asid = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
control.asid));
+ uint64_t msrpm_base_pa = x86_ldq_phys(cs, env->vm_vmcb +
+ offsetof(struct vmcb,
+ control.msrpm_base_pa));
+ uint64_t iopm_base_pa = x86_ldq_phys(cs, env->vm_vmcb +
+ offsetof(struct vmcb, control.iopm_base_pa));
+
+ if ((msrpm_base_pa & ~0xfff) >= (1ull << cpu->phys_bits) - SVM_MSRPM_SIZE) {
+ cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
+ }
+
+ if ((iopm_base_pa & ~0xfff) >= (1ull << cpu->phys_bits) - SVM_IOPM_SIZE) {
+ cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
+ }
+
env->nested_pg_mode = 0;
if (!cpu_svm_has_intercept(env, SVM_EXIT_VMRUN)) {
@@ -254,7 +269,14 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
env->dr[6] = x86_ldq_phys(cs,
env->vm_vmcb + offsetof(struct vmcb, save.dr6));
- /* FIXME: guest state consistency checks */
+#ifdef TARGET_X86_64
+ if (env->dr[6] & DR_RESERVED_MASK) {
+ cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
+ }
+ if (env->dr[7] & DR_RESERVED_MASK) {
+ cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
+ }
+#endif
switch (x86_ldub_phys(cs,
env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 37a66b4097..3814ce2a3e 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -205,6 +205,7 @@ STUB_HELPER(outw, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
STUB_HELPER(outl, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
STUB_HELPER(rdmsr, TCGv_env env)
STUB_HELPER(read_crN, TCGv ret, TCGv_env env, TCGv_i32 reg)
+STUB_HELPER(get_dr, TCGv ret, TCGv_env env, TCGv_i32 reg)
STUB_HELPER(set_dr, TCGv_env env, TCGv_i32 reg, TCGv val)
STUB_HELPER(stgi, TCGv_env env)
STUB_HELPER(svm_check_intercept, TCGv_env env, TCGv_i32 type)
diff --git a/target/m68k/Kconfig b/target/m68k/Kconfig
new file mode 100644
index 0000000000..23debad519
--- /dev/null
+++ b/target/m68k/Kconfig
@@ -0,0 +1,2 @@
+config M68K
+ bool
diff --git a/target/microblaze/Kconfig b/target/microblaze/Kconfig
new file mode 100644
index 0000000000..a5410d9218
--- /dev/null
+++ b/target/microblaze/Kconfig
@@ -0,0 +1,2 @@
+config MICROBLAZE
+ bool
diff --git a/target/mips/Kconfig b/target/mips/Kconfig
new file mode 100644
index 0000000000..6adf145354
--- /dev/null
+++ b/target/mips/Kconfig
@@ -0,0 +1,6 @@
+config MIPS
+ bool
+
+config MIPS64
+ bool
+ select MIPS
diff --git a/target/nios2/Kconfig b/target/nios2/Kconfig
new file mode 100644
index 0000000000..1529ab8950
--- /dev/null
+++ b/target/nios2/Kconfig
@@ -0,0 +1,2 @@
+config NIOS2
+ bool
diff --git a/target/openrisc/Kconfig b/target/openrisc/Kconfig
new file mode 100644
index 0000000000..e0da4ac1df
--- /dev/null
+++ b/target/openrisc/Kconfig
@@ -0,0 +1,2 @@
+config OPENRISC
+ bool
diff --git a/target/ppc/Kconfig b/target/ppc/Kconfig
new file mode 100644
index 0000000000..3ff152051a
--- /dev/null
+++ b/target/ppc/Kconfig
@@ -0,0 +1,5 @@
+config PPC
+ bool
+
+config PPC64
+ bool
diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c
index 9210e61ef4..bb392f6d88 100644
--- a/target/ppc/arch_dump.c
+++ b/target/ppc/arch_dump.c
@@ -227,22 +227,20 @@ int cpu_get_dump_info(ArchDumpInfo *info,
const struct GuestPhysBlockList *guest_phys_blocks)
{
PowerPCCPU *cpu;
- PowerPCCPUClass *pcc;
if (first_cpu == NULL) {
return -1;
}
cpu = POWERPC_CPU(first_cpu);
- pcc = POWERPC_CPU_GET_CLASS(cpu);
info->d_machine = PPC_ELF_MACHINE;
info->d_class = ELFCLASS;
- if ((*pcc->interrupts_big_endian)(cpu)) {
- info->d_endian = ELFDATA2MSB;
- } else {
+ if (ppc_interrupts_little_endian(cpu)) {
info->d_endian = ELFDATA2LSB;
+ } else {
+ info->d_endian = ELFDATA2MSB;
}
/* 64KB is the max page size for pseries kernel */
if (strncmp(object_get_typename(qdev_get_machine()),
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index 06b6571bc9..5800fa324e 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -198,8 +198,6 @@ struct PowerPCCPUClass {
int n_host_threads;
void (*init_proc)(CPUPPCState *env);
int (*check_pow)(CPUPPCState *env);
- int (*handle_mmu_fault)(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx);
- bool (*interrupts_big_endian)(PowerPCCPU *cpu);
};
#ifndef CONFIG_USER_ONLY
diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c
index 19d67b5b07..a29299882a 100644
--- a/target/ppc/cpu.c
+++ b/target/ppc/cpu.c
@@ -72,7 +72,7 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
{
PowerPCCPU *cpu = env_archcpu(env);
qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
- assert(!cpu->vhyp);
+ assert(!cpu->env.has_hv_mode || !cpu->vhyp);
#if defined(TARGET_PPC64)
if (mmu_is_64bit(env->mmu_model)) {
target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index b4de0db7ff..93d308ac8f 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -2643,6 +2643,21 @@ static inline bool ppc_has_spr(PowerPCCPU *cpu, int spr)
return cpu->env.spr_cb[spr].name != NULL;
}
+static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu)
+{
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+
+ /*
+ * Only models that have an LPCR and know about LPCR_ILE can do little
+ * endian.
+ */
+ if (pcc->lpcr_mask & LPCR_ILE) {
+ return !!(cpu->env.spr[SPR_LPCR] & LPCR_ILE);
+ }
+
+ return false;
+}
+
void dump_mmu(CPUPPCState *env);
void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len);
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index d0411e7302..505a0ed6ac 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -2666,18 +2666,6 @@ static int check_pow_hid0_74xx(CPUPPCState *env)
return 0;
}
-static bool ppc_cpu_interrupts_big_endian_always(PowerPCCPU *cpu)
-{
- return true;
-}
-
-#ifdef TARGET_PPC64
-static bool ppc_cpu_interrupts_big_endian_lpcr(PowerPCCPU *cpu)
-{
- return !(cpu->env.spr[SPR_LPCR] & LPCR_ILE);
-}
-#endif
-
/*****************************************************************************/
/* PowerPC implementations definitions */
@@ -4578,9 +4566,6 @@ POWERPC_FAMILY(601)(ObjectClass *oc, void *data)
(1ull << MSR_IR) |
(1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_601;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->excp_model = POWERPC_EXCP_601;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_601;
@@ -4623,9 +4608,6 @@ POWERPC_FAMILY(601v)(ObjectClass *oc, void *data)
(1ull << MSR_IR) |
(1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_601;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_601;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK | POWERPC_FLAG_HID0_LE;
@@ -4889,9 +4871,6 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->excp_model = POWERPC_EXCP_604;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_604;
@@ -4973,9 +4952,6 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->excp_model = POWERPC_EXCP_604;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_604;
@@ -5044,9 +5020,6 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->excp_model = POWERPC_EXCP_7x0;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
@@ -5124,9 +5097,6 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->excp_model = POWERPC_EXCP_7x0;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
@@ -5327,9 +5297,6 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->excp_model = POWERPC_EXCP_7x0;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
@@ -5410,9 +5377,6 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->excp_model = POWERPC_EXCP_7x0;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
@@ -5498,9 +5462,6 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->excp_model = POWERPC_EXCP_7x0;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
@@ -5586,9 +5547,6 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->excp_model = POWERPC_EXCP_7x0;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
@@ -5828,9 +5786,6 @@ POWERPC_FAMILY(7400)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->excp_model = POWERPC_EXCP_74xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_7400;
@@ -5914,9 +5869,6 @@ POWERPC_FAMILY(7410)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->excp_model = POWERPC_EXCP_74xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_7400;
@@ -6743,9 +6695,6 @@ POWERPC_FAMILY(e600)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
-#endif
pcc->excp_model = POWERPC_EXCP_74xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_7400;
@@ -7505,7 +7454,6 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
(1ull << MSR_RI);
pcc->mmu_model = POWERPC_MMU_64B;
#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
pcc->hash64_opts = &ppc_hash64_opts_basic;
#endif
pcc->excp_model = POWERPC_EXCP_970;
@@ -7583,7 +7531,6 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
LPCR_RMI | LPCR_HDICE;
pcc->mmu_model = POWERPC_MMU_2_03;
#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
pcc->hash64_opts = &ppc_hash64_opts_basic;
pcc->lrg_decr_bits = 32;
#endif
@@ -7727,7 +7674,6 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
pcc->lpcr_pm = LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2;
pcc->mmu_model = POWERPC_MMU_2_06;
#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
pcc->hash64_opts = &ppc_hash64_opts_POWER7;
pcc->lrg_decr_bits = 32;
#endif
@@ -7740,7 +7686,6 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
POWERPC_FLAG_VSX;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
- pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
}
static void init_proc_POWER8(CPUPPCState *env)
@@ -7904,7 +7849,6 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
LPCR_P8_PECE3 | LPCR_P8_PECE4;
pcc->mmu_model = POWERPC_MMU_2_07;
#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
pcc->hash64_opts = &ppc_hash64_opts_POWER7;
pcc->lrg_decr_bits = 32;
pcc->n_host_threads = 8;
@@ -7918,7 +7862,6 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
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;
}
#ifdef CONFIG_SOFTMMU
@@ -8120,7 +8063,6 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
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 = &POWER9_radix_page_info;
@@ -8136,7 +8078,6 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
POWERPC_FLAG_VSX | POWERPC_FLAG_TM | POWERPC_FLAG_SCV;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
- pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
}
#ifdef CONFIG_SOFTMMU
@@ -8332,7 +8273,6 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
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;
@@ -8347,7 +8287,6 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
POWERPC_FLAG_VSX | POWERPC_FLAG_TM | POWERPC_FLAG_SCV;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
- pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
}
#if !defined(CONFIG_USER_ONLY)
@@ -8908,9 +8847,11 @@ static void ppc_cpu_reset(DeviceState *dev)
#if !defined(CONFIG_USER_ONLY)
env->nip = env->hreset_vector | env->excp_prefix;
+#if defined(CONFIG_TCG)
if (env->mmu_model != POWERPC_MMU_REAL) {
ppc_tlb_invalidate_all(env);
}
+#endif /* CONFIG_TCG */
#endif
hreg_compute_hflags(env);
@@ -9094,7 +9035,6 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_parent_unrealize(dc, ppc_cpu_unrealize,
&pcc->parent_unrealize);
pcc->pvr_match = ppc_pvr_match_default;
- pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always;
device_class_set_props(dc, ppc_cpu_properties);
device_class_set_parent_reset(dc, ppc_cpu_reset, &pcc->parent_reset);
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index fd147e2a37..a79a0ed465 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1099,7 +1099,6 @@ void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
- PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
target_ulong msr = 0;
/*
@@ -1108,7 +1107,7 @@ void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
*/
msr = (1ULL << MSR_ME);
msr |= env->msr & (1ULL << MSR_SF);
- if (!(*pcc->interrupts_big_endian)(cpu)) {
+ if (ppc_interrupts_little_endian(cpu)) {
msr |= (1ULL << MSR_LE);
}
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 104a308abb..dc93b99189 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -89,6 +89,7 @@ static int cap_ppc_count_cache_flush_assist;
static int cap_ppc_nested_kvm_hv;
static int cap_large_decr;
static int cap_fwnmi;
+static int cap_rpt_invalidate;
static uint32_t debug_inst_opcode;
@@ -152,6 +153,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
exit(1);
}
+ cap_rpt_invalidate = kvm_vm_check_extension(s, KVM_CAP_PPC_RPT_INVALIDATE);
kvm_ppc_register_host_cpu_type();
return 0;
@@ -2040,6 +2042,11 @@ void kvmppc_enable_h_page_init(void)
kvmppc_enable_hcall(kvm_state, H_PAGE_INIT);
}
+void kvmppc_enable_h_rpt_invalidate(void)
+{
+ kvmppc_enable_hcall(kvm_state, H_RPT_INVALIDATE);
+}
+
void kvmppc_set_papr(PowerPCCPU *cpu)
{
CPUState *cs = CPU(cpu);
@@ -2551,6 +2558,11 @@ int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable)
return 0;
}
+int kvmppc_has_cap_rpt_invalidate(void)
+{
+ return cap_rpt_invalidate;
+}
+
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
{
uint32_t host_pvr = mfpvr();
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index 989f61ace0..ee9325bf9a 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -24,6 +24,7 @@ void kvmppc_enable_logical_ci_hcalls(void);
void kvmppc_enable_set_mode_hcall(void);
void kvmppc_enable_clear_ref_mod_hcalls(void);
void kvmppc_enable_h_page_init(void);
+void kvmppc_enable_h_rpt_invalidate(void);
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);
@@ -71,6 +72,7 @@ bool kvmppc_has_cap_nested_kvm_hv(void);
int kvmppc_set_cap_nested_kvm_hv(int enable);
int kvmppc_get_cap_large_decr(void);
int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable);
+int kvmppc_has_cap_rpt_invalidate(void);
int kvmppc_enable_hwrng(void);
int kvmppc_put_books_sregs(PowerPCCPU *cpu);
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
@@ -150,6 +152,11 @@ static inline void kvmppc_enable_h_page_init(void)
{
}
+static inline void kvmppc_enable_h_rpt_invalidate(void)
+{
+ g_assert_not_reached();
+}
+
static inline void kvmppc_set_papr(PowerPCCPU *cpu)
{
}
@@ -381,6 +388,11 @@ static inline int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable)
return -1;
}
+static inline int kvmppc_has_cap_rpt_invalidate(void)
+{
+ return false;
+}
+
static inline int kvmppc_enable_hwrng(void)
{
return -1;
diff --git a/target/ppc/mmu-book3s-v3.c b/target/ppc/mmu-book3s-v3.c
index c78fd8dc0e..f4985bae78 100644
--- a/target/ppc/mmu-book3s-v3.c
+++ b/target/ppc/mmu-book3s-v3.c
@@ -23,25 +23,6 @@
#include "mmu-book3s-v3.h"
#include "mmu-radix64.h"
-int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
- int mmu_idx)
-{
- if (ppc64_v3_radix(cpu)) { /* Guest uses radix */
- return ppc_radix64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx);
- } else { /* Guest uses hash */
- return ppc_hash64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx);
- }
-}
-
-hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr)
-{
- if (ppc64_v3_radix(cpu)) {
- return ppc_radix64_get_phys_page_debug(cpu, eaddr);
- } else {
- return ppc_hash64_get_phys_page_debug(cpu, eaddr);
- }
-}
-
bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, ppc_v3_pate_t *entry)
{
uint64_t patb = cpu->env.spr[SPR_PTCR] & PTCR_PATB;
diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h
index 7b89be54b8..d6d5ed8f8e 100644
--- a/target/ppc/mmu-book3s-v3.h
+++ b/target/ppc/mmu-book3s-v3.h
@@ -21,6 +21,7 @@
#define PPC_MMU_BOOK3S_V3_H
#include "mmu-hash64.h"
+#include "mmu-books.h"
#ifndef CONFIG_USER_ONLY
@@ -67,11 +68,6 @@ static inline bool ppc64_v3_radix(PowerPCCPU *cpu)
return !!(cpu->env.spr[SPR_LPCR] & LPCR_HR);
}
-hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr);
-
-int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
- int mmu_idx);
-
static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
{
uint64_t base;
diff --git a/target/ppc/mmu-books.h b/target/ppc/mmu-books.h
new file mode 100644
index 0000000000..0d12551867
--- /dev/null
+++ b/target/ppc/mmu-books.h
@@ -0,0 +1,30 @@
+/*
+ * PowerPC BookS emulation generic mmu definitions for qemu.
+ *
+ * Copyright (c) 2021 Instituto de Pesquisas Eldorado (eldorado.org.br)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PPC_MMU_BOOKS_H
+#define PPC_MMU_BOOKS_H
+
+/*
+ * These correspond to the mmu_idx values computed in
+ * hreg_compute_hflags_value. See the tables therein
+ */
+static inline bool mmuidx_pr(int idx) { return !(idx & 1); }
+static inline bool mmuidx_real(int idx) { return idx & 2; }
+static inline bool mmuidx_hv(int idx) { return idx & 4; }
+#endif /* PPC_MMU_BOOKS_H */
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 9f0a497657..3957aab2dc 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -25,9 +25,10 @@
#include "kvm_ppc.h"
#include "internal.h"
#include "mmu-hash32.h"
+#include "mmu-books.h"
#include "exec/log.h"
-/* #define DEBUG_BAT */
+/* #define DEBUG_BATS */
#ifdef DEBUG_BATS
# define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
@@ -86,25 +87,22 @@ static int ppc_hash32_pp_prot(int key, int pp, int nx)
return prot;
}
-static int ppc_hash32_pte_prot(PowerPCCPU *cpu,
+static int ppc_hash32_pte_prot(int mmu_idx,
target_ulong sr, ppc_hash_pte32_t pte)
{
- CPUPPCState *env = &cpu->env;
unsigned pp, key;
- key = !!(msr_pr ? (sr & SR32_KP) : (sr & SR32_KS));
+ key = !!(mmuidx_pr(mmu_idx) ? (sr & SR32_KP) : (sr & SR32_KS));
pp = pte.pte1 & HPTE32_R_PP;
return ppc_hash32_pp_prot(key, pp, !!(sr & SR32_NX));
}
-static target_ulong hash32_bat_size(PowerPCCPU *cpu,
+static target_ulong hash32_bat_size(int mmu_idx,
target_ulong batu, target_ulong batl)
{
- CPUPPCState *env = &cpu->env;
-
- if ((msr_pr && !(batu & BATU32_VP))
- || (!msr_pr && !(batu & BATU32_VS))) {
+ if ((mmuidx_pr(mmu_idx) && !(batu & BATU32_VP))
+ || (!mmuidx_pr(mmu_idx) && !(batu & BATU32_VS))) {
return 0;
}
@@ -137,14 +135,13 @@ static target_ulong hash32_bat_601_size(PowerPCCPU *cpu,
return BATU32_BEPI & ~((batl & BATL32_601_BL) << 17);
}
-static int hash32_bat_601_prot(PowerPCCPU *cpu,
+static int hash32_bat_601_prot(int mmu_idx,
target_ulong batu, target_ulong batl)
{
- CPUPPCState *env = &cpu->env;
int key, pp;
pp = batu & BATU32_601_PP;
- if (msr_pr == 0) {
+ if (mmuidx_pr(mmu_idx) == 0) {
key = !!(batu & BATU32_601_KS);
} else {
key = !!(batu & BATU32_601_KP);
@@ -153,7 +150,8 @@ static int hash32_bat_601_prot(PowerPCCPU *cpu,
}
static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
- MMUAccessType access_type, int *prot)
+ MMUAccessType access_type, int *prot,
+ int mmu_idx)
{
CPUPPCState *env = &cpu->env;
target_ulong *BATlt, *BATut;
@@ -177,7 +175,7 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
mask = hash32_bat_601_size(cpu, batu, batl);
} else {
- mask = hash32_bat_size(cpu, batu, batl);
+ mask = hash32_bat_size(mmu_idx, batu, batl);
}
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
" BATl " TARGET_FMT_lx "\n", __func__,
@@ -187,7 +185,7 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
hwaddr raddr = (batl & mask) | (ea & ~mask);
if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
- *prot = hash32_bat_601_prot(cpu, batu, batl);
+ *prot = hash32_bat_601_prot(mmu_idx, batu, batl);
} else {
*prot = hash32_bat_prot(cpu, batu, batl);
}
@@ -199,6 +197,9 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
/* No hit */
#if defined(DEBUG_BATS)
if (qemu_log_enabled()) {
+ target_ulong *BATu, *BATl;
+ target_ulong BEPIl, BEPIu, bl;
+
LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", ea);
for (i = 0; i < 4; i++) {
BATu = &BATut[i];
@@ -218,14 +219,15 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
return -1;
}
-static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
- target_ulong eaddr,
- MMUAccessType access_type,
- hwaddr *raddr, int *prot)
+static bool ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
+ target_ulong eaddr,
+ MMUAccessType access_type,
+ hwaddr *raddr, int *prot, int mmu_idx,
+ bool guest_visible)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
- int key = !!(msr_pr ? (sr & SR32_KP) : (sr & SR32_KS));
+ int key = !!(mmuidx_pr(mmu_idx) ? (sr & SR32_KP) : (sr & SR32_KS));
qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
@@ -238,17 +240,23 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
*/
*raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- return 0;
+ return true;
}
if (access_type == MMU_INST_FETCH) {
/* No code fetch is allowed in direct-store areas */
- cs->exception_index = POWERPC_EXCP_ISI;
- env->error_code = 0x10000000;
- return 1;
+ if (guest_visible) {
+ cs->exception_index = POWERPC_EXCP_ISI;
+ env->error_code = 0x10000000;
+ }
+ return false;
}
- switch (env->access_type) {
+ /*
+ * From ppc_cpu_get_phys_page_debug, env->access_type is not set.
+ * Assume ACCESS_INT for that case.
+ */
+ switch (guest_visible ? env->access_type : ACCESS_INT) {
case ACCESS_INT:
/* Integer load/store : only access allowed */
break;
@@ -257,7 +265,7 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
cs->exception_index = POWERPC_EXCP_ALIGN;
env->error_code = POWERPC_EXCP_ALIGN_FP;
env->spr[SPR_DAR] = eaddr;
- return 1;
+ return false;
case ACCESS_RES:
/* lwarx, ldarx or srwcx. */
env->error_code = 0;
@@ -267,7 +275,7 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
} else {
env->spr[SPR_DSISR] = 0x04000000;
}
- return 1;
+ return false;
case ACCESS_CACHE:
/*
* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
@@ -276,7 +284,7 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
* no-op, it's quite easy :-)
*/
*raddr = eaddr;
- return 0;
+ return true;
case ACCESS_EXT:
/* eciwx or ecowx */
cs->exception_index = POWERPC_EXCP_DSI;
@@ -287,16 +295,18 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
} else {
env->spr[SPR_DSISR] = 0x04100000;
}
- return 1;
+ return false;
default:
- cpu_abort(cs, "ERROR: instruction should not need "
- "address translation\n");
+ cpu_abort(cs, "ERROR: insn should not need address translation\n");
}
- if ((access_type == MMU_DATA_STORE || key != 1) &&
- (access_type == MMU_DATA_LOAD || key != 0)) {
+
+ *prot = key ? PAGE_READ | PAGE_WRITE : PAGE_READ;
+ if (*prot & prot_for_access_type(access_type)) {
*raddr = eaddr;
- return 0;
- } else {
+ return true;
+ }
+
+ if (guest_visible) {
cs->exception_index = POWERPC_EXCP_DSI;
env->error_code = 0;
env->spr[SPR_DAR] = eaddr;
@@ -305,8 +315,8 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
} else {
env->spr[SPR_DSISR] = 0x08000000;
}
- return 1;
}
+ return false;
}
hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash)
@@ -415,8 +425,9 @@ static hwaddr ppc_hash32_pte_raddr(target_ulong sr, ppc_hash_pte32_t pte,
return (rpn & ~mask) | (eaddr & mask);
}
-int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
- int mmu_idx)
+bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+ hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
+ bool guest_visible)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
@@ -425,48 +436,45 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
ppc_hash_pte32_t pte;
int prot;
int need_prot;
- MMUAccessType access_type;
hwaddr raddr;
- assert((rwx == 0) || (rwx == 1) || (rwx == 2));
- access_type = rwx;
- need_prot = prot_for_access_type(access_type);
+ /* There are no hash32 large pages. */
+ *psizep = TARGET_PAGE_BITS;
/* 1. Handle real mode accesses */
- if (access_type == MMU_INST_FETCH ? !msr_ir : !msr_dr) {
+ if (mmuidx_real(mmu_idx)) {
/* Translation is off */
- raddr = eaddr;
- tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
- PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx,
- TARGET_PAGE_SIZE);
- return 0;
+ *raddrp = eaddr;
+ *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ return true;
}
+ need_prot = prot_for_access_type(access_type);
+
/* 2. Check Block Address Translation entries (BATs) */
if (env->nb_BATs != 0) {
- raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, &prot);
+ raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, protp, mmu_idx);
if (raddr != -1) {
- if (need_prot & ~prot) {
- if (access_type == MMU_INST_FETCH) {
- cs->exception_index = POWERPC_EXCP_ISI;
- env->error_code = 0x08000000;
- } else {
- cs->exception_index = POWERPC_EXCP_DSI;
- env->error_code = 0;
- env->spr[SPR_DAR] = eaddr;
- if (access_type == MMU_DATA_STORE) {
- env->spr[SPR_DSISR] = 0x0a000000;
+ if (need_prot & ~*protp) {
+ if (guest_visible) {
+ if (access_type == MMU_INST_FETCH) {
+ cs->exception_index = POWERPC_EXCP_ISI;
+ env->error_code = 0x08000000;
} else {
- env->spr[SPR_DSISR] = 0x08000000;
+ cs->exception_index = POWERPC_EXCP_DSI;
+ env->error_code = 0;
+ env->spr[SPR_DAR] = eaddr;
+ if (access_type == MMU_DATA_STORE) {
+ env->spr[SPR_DSISR] = 0x0a000000;
+ } else {
+ env->spr[SPR_DSISR] = 0x08000000;
+ }
}
}
- return 1;
+ return false;
}
-
- tlb_set_page(cs, eaddr & TARGET_PAGE_MASK,
- raddr & TARGET_PAGE_MASK, prot, mmu_idx,
- TARGET_PAGE_SIZE);
- return 0;
+ *raddrp = raddr;
+ return true;
}
}
@@ -475,67 +483,65 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
/* 4. Handle direct store segments */
if (sr & SR32_T) {
- if (ppc_hash32_direct_store(cpu, sr, eaddr, access_type,
- &raddr, &prot) == 0) {
- tlb_set_page(cs, eaddr & TARGET_PAGE_MASK,
- raddr & TARGET_PAGE_MASK, prot, mmu_idx,
- TARGET_PAGE_SIZE);
- return 0;
- } else {
- return 1;
- }
+ return ppc_hash32_direct_store(cpu, sr, eaddr, access_type,
+ raddrp, protp, mmu_idx, guest_visible);
}
/* 5. Check for segment level no-execute violation */
if (access_type == MMU_INST_FETCH && (sr & SR32_NX)) {
- cs->exception_index = POWERPC_EXCP_ISI;
- env->error_code = 0x10000000;
- return 1;
+ if (guest_visible) {
+ cs->exception_index = POWERPC_EXCP_ISI;
+ env->error_code = 0x10000000;
+ }
+ return false;
}
/* 6. Locate the PTE in the hash table */
pte_offset = ppc_hash32_htab_lookup(cpu, sr, eaddr, &pte);
if (pte_offset == -1) {
- if (access_type == MMU_INST_FETCH) {
- cs->exception_index = POWERPC_EXCP_ISI;
- env->error_code = 0x40000000;
- } else {
- cs->exception_index = POWERPC_EXCP_DSI;
- env->error_code = 0;
- env->spr[SPR_DAR] = eaddr;
- if (access_type == MMU_DATA_STORE) {
- env->spr[SPR_DSISR] = 0x42000000;
+ if (guest_visible) {
+ if (access_type == MMU_INST_FETCH) {
+ cs->exception_index = POWERPC_EXCP_ISI;
+ env->error_code = 0x40000000;
} else {
- env->spr[SPR_DSISR] = 0x40000000;
+ cs->exception_index = POWERPC_EXCP_DSI;
+ env->error_code = 0;
+ env->spr[SPR_DAR] = eaddr;
+ if (access_type == MMU_DATA_STORE) {
+ env->spr[SPR_DSISR] = 0x42000000;
+ } else {
+ env->spr[SPR_DSISR] = 0x40000000;
+ }
}
}
-
- return 1;
+ return false;
}
qemu_log_mask(CPU_LOG_MMU,
"found PTE at offset %08" HWADDR_PRIx "\n", pte_offset);
/* 7. Check access permissions */
- prot = ppc_hash32_pte_prot(cpu, sr, pte);
+ prot = ppc_hash32_pte_prot(mmu_idx, sr, pte);
if (need_prot & ~prot) {
/* Access right violation */
qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
- if (access_type == MMU_INST_FETCH) {
- cs->exception_index = POWERPC_EXCP_ISI;
- env->error_code = 0x08000000;
- } else {
- cs->exception_index = POWERPC_EXCP_DSI;
- env->error_code = 0;
- env->spr[SPR_DAR] = eaddr;
- if (access_type == MMU_DATA_STORE) {
- env->spr[SPR_DSISR] = 0x0a000000;
+ if (guest_visible) {
+ if (access_type == MMU_INST_FETCH) {
+ cs->exception_index = POWERPC_EXCP_ISI;
+ env->error_code = 0x08000000;
} else {
- env->spr[SPR_DSISR] = 0x08000000;
+ cs->exception_index = POWERPC_EXCP_DSI;
+ env->error_code = 0;
+ env->spr[SPR_DAR] = eaddr;
+ if (access_type == MMU_DATA_STORE) {
+ env->spr[SPR_DSISR] = 0x0a000000;
+ } else {
+ env->spr[SPR_DSISR] = 0x08000000;
+ }
}
}
- return 1;
+ return false;
}
qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
@@ -559,45 +565,7 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
/* 9. Determine the real address from the PTE */
- raddr = ppc_hash32_pte_raddr(sr, pte, eaddr);
-
- tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
- prot, mmu_idx, TARGET_PAGE_SIZE);
-
- return 0;
-}
-
-hwaddr ppc_hash32_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr)
-{
- CPUPPCState *env = &cpu->env;
- target_ulong sr;
- hwaddr pte_offset;
- ppc_hash_pte32_t pte;
- int prot;
-
- if (msr_dr == 0) {
- /* Translation is off */
- return eaddr;
- }
-
- if (env->nb_BATs != 0) {
- hwaddr raddr = ppc_hash32_bat_lookup(cpu, eaddr, 0, &prot);
- if (raddr != -1) {
- return raddr;
- }
- }
-
- sr = env->sr[eaddr >> 28];
-
- if (sr & SR32_T) {
- /* FIXME: Add suitable debug support for Direct Store segments */
- return -1;
- }
-
- pte_offset = ppc_hash32_htab_lookup(cpu, sr, eaddr, &pte);
- if (pte_offset == -1) {
- return -1;
- }
-
- return ppc_hash32_pte_raddr(sr, pte, eaddr) & TARGET_PAGE_MASK;
+ *raddrp = ppc_hash32_pte_raddr(sr, pte, eaddr);
+ *protp = prot;
+ return true;
}
diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h
index 898021f0d8..3892b693d6 100644
--- a/target/ppc/mmu-hash32.h
+++ b/target/ppc/mmu-hash32.h
@@ -4,9 +4,9 @@
#ifndef CONFIG_USER_ONLY
hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash);
-hwaddr ppc_hash32_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr);
-int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, int rw,
- int mmu_idx);
+bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+ hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
+ bool guest_visible);
/*
* Segment register definitions
@@ -22,6 +22,8 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, int rw,
* Block Address Translation (BAT) definitions
*/
+#define BATU32_BEPIU 0xf0000000
+#define BATU32_BEPIL 0x0ffe0000
#define BATU32_BEPI 0xfffe0000
#define BATU32_BL 0x00001ffc
#define BATU32_VS 0x00000002
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index 708dffc31b..19832c4b46 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -366,10 +366,9 @@ static inline int ppc_hash64_pte_noexec_guard(PowerPCCPU *cpu,
}
/* Check Basic Storage Protection */
-static int ppc_hash64_pte_prot(PowerPCCPU *cpu,
+static int ppc_hash64_pte_prot(int mmu_idx,
ppc_slb_t *slb, ppc_hash_pte64_t pte)
{
- CPUPPCState *env = &cpu->env;
unsigned pp, key;
/*
* Some pp bit combinations have undefined behaviour, so default
@@ -377,7 +376,7 @@ static int ppc_hash64_pte_prot(PowerPCCPU *cpu,
*/
int prot = 0;
- key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP)
+ key = !!(mmuidx_pr(mmu_idx) ? (slb->vsid & SLB_VSID_KP)
: (slb->vsid & SLB_VSID_KS));
pp = (pte.pte1 & HPTE64_R_PP) | ((pte.pte1 & HPTE64_R_PP0) >> 61);
@@ -744,17 +743,17 @@ static bool ppc_hash64_use_vrma(CPUPPCState *env)
}
}
-static void ppc_hash64_set_isi(CPUState *cs, uint64_t error_code)
+static void ppc_hash64_set_isi(CPUState *cs, int mmu_idx, uint64_t error_code)
{
CPUPPCState *env = &POWERPC_CPU(cs)->env;
bool vpm;
- if (msr_ir) {
+ if (!mmuidx_real(mmu_idx)) {
vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM1);
} else {
vpm = ppc_hash64_use_vrma(env);
}
- if (vpm && !msr_hv) {
+ if (vpm && !mmuidx_hv(mmu_idx)) {
cs->exception_index = POWERPC_EXCP_HISI;
} else {
cs->exception_index = POWERPC_EXCP_ISI;
@@ -762,17 +761,17 @@ static void ppc_hash64_set_isi(CPUState *cs, uint64_t error_code)
env->error_code = error_code;
}
-static void ppc_hash64_set_dsi(CPUState *cs, uint64_t dar, uint64_t dsisr)
+static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, uint64_t dar, uint64_t dsisr)
{
CPUPPCState *env = &POWERPC_CPU(cs)->env;
bool vpm;
- if (msr_dr) {
+ if (!mmuidx_real(mmu_idx)) {
vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM1);
} else {
vpm = ppc_hash64_use_vrma(env);
}
- if (vpm && !msr_hv) {
+ if (vpm && !mmuidx_hv(mmu_idx)) {
cs->exception_index = POWERPC_EXCP_HDSI;
env->spr[SPR_HDAR] = dar;
env->spr[SPR_HDSISR] = dsisr;
@@ -873,8 +872,9 @@ static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb)
return -1;
}
-int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
- int rwx, int mmu_idx)
+bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+ hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
+ bool guest_visible)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
@@ -884,13 +884,9 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
hwaddr ptex;
ppc_hash_pte64_t pte;
int exec_prot, pp_prot, amr_prot, prot;
- MMUAccessType access_type;
int need_prot;
hwaddr raddr;
- assert((rwx == 0) || (rwx == 1) || (rwx == 2));
- access_type = rwx;
-
/*
* Note on LPCR usage: 970 uses HID4, but our special variant of
* store_spr copies relevant fields into env->spr[SPR_LPCR].
@@ -900,7 +896,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
*/
/* 1. Handle real mode accesses */
- if (access_type == MMU_INST_FETCH ? !msr_ir : !msr_dr) {
+ if (mmuidx_real(mmu_idx)) {
/*
* Translation is supposedly "off", but in real mode the top 4
* effective address bits are (mostly) ignored
@@ -912,7 +908,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
* In virtual hypervisor mode, there's nothing to do:
* EA == GPA == qemu guest address
*/
- } else if (msr_hv || !env->has_hv_mode) {
+ } else if (mmuidx_hv(mmu_idx) || !env->has_hv_mode) {
/* In HV mode, add HRMOR if top EA bit is clear */
if (!(eaddr >> 63)) {
raddr |= env->spr[SPR_HRMOR];
@@ -922,9 +918,11 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
slb = &vrma_slbe;
if (build_vrma_slbe(cpu, slb) != 0) {
/* Invalid VRMA setup, machine check */
- cs->exception_index = POWERPC_EXCP_MCHECK;
- env->error_code = 0;
- return 1;
+ if (guest_visible) {
+ cs->exception_index = POWERPC_EXCP_MCHECK;
+ env->error_code = 0;
+ }
+ return false;
}
goto skip_slb_search;
@@ -933,29 +931,33 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
/* Emulated old-style RMO mode, bounds check against RMLS */
if (raddr >= limit) {
+ if (!guest_visible) {
+ return false;
+ }
switch (access_type) {
case MMU_INST_FETCH:
- ppc_hash64_set_isi(cs, SRR1_PROTFAULT);
+ ppc_hash64_set_isi(cs, mmu_idx, SRR1_PROTFAULT);
break;
case MMU_DATA_LOAD:
- ppc_hash64_set_dsi(cs, eaddr, DSISR_PROTFAULT);
+ ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_PROTFAULT);
break;
case MMU_DATA_STORE:
- ppc_hash64_set_dsi(cs, eaddr,
+ ppc_hash64_set_dsi(cs, mmu_idx, eaddr,
DSISR_PROTFAULT | DSISR_ISSTORE);
break;
default:
g_assert_not_reached();
}
- return 1;
+ return false;
}
raddr |= env->spr[SPR_RMOR];
}
- tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
- PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx,
- TARGET_PAGE_SIZE);
- return 0;
+
+ *raddrp = raddr;
+ *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ *psizep = TARGET_PAGE_BITS;
+ return true;
}
/* 2. Translation is on, so look up the SLB */
@@ -968,6 +970,9 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
exit(1);
}
/* Segment still not found, generate the appropriate interrupt */
+ if (!guest_visible) {
+ return false;
+ }
switch (access_type) {
case MMU_INST_FETCH:
cs->exception_index = POWERPC_EXCP_ISEG;
@@ -982,34 +987,39 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
default:
g_assert_not_reached();
}
- return 1;
+ return false;
}
-skip_slb_search:
+ skip_slb_search:
/* 3. Check for segment level no-execute violation */
if (access_type == MMU_INST_FETCH && (slb->vsid & SLB_VSID_N)) {
- ppc_hash64_set_isi(cs, SRR1_NOEXEC_GUARD);
- return 1;
+ if (guest_visible) {
+ ppc_hash64_set_isi(cs, mmu_idx, SRR1_NOEXEC_GUARD);
+ }
+ return false;
}
/* 4. Locate the PTE in the hash table */
ptex = ppc_hash64_htab_lookup(cpu, slb, eaddr, &pte, &apshift);
if (ptex == -1) {
+ if (!guest_visible) {
+ return false;
+ }
switch (access_type) {
case MMU_INST_FETCH:
- ppc_hash64_set_isi(cs, SRR1_NOPTE);
+ ppc_hash64_set_isi(cs, mmu_idx, SRR1_NOPTE);
break;
case MMU_DATA_LOAD:
- ppc_hash64_set_dsi(cs, eaddr, DSISR_NOPTE);
+ ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_NOPTE);
break;
case MMU_DATA_STORE:
- ppc_hash64_set_dsi(cs, eaddr, DSISR_NOPTE | DSISR_ISSTORE);
+ ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_NOPTE | DSISR_ISSTORE);
break;
default:
g_assert_not_reached();
}
- return 1;
+ return false;
}
qemu_log_mask(CPU_LOG_MMU,
"found PTE at index %08" HWADDR_PRIx "\n", ptex);
@@ -1017,7 +1027,7 @@ skip_slb_search:
/* 5. Check access permissions */
exec_prot = ppc_hash64_pte_noexec_guard(cpu, pte);
- pp_prot = ppc_hash64_pte_prot(cpu, slb, pte);
+ pp_prot = ppc_hash64_pte_prot(mmu_idx, slb, pte);
amr_prot = ppc_hash64_amr_prot(cpu, pte);
prot = exec_prot & pp_prot & amr_prot;
@@ -1025,6 +1035,9 @@ skip_slb_search:
if (need_prot & ~prot) {
/* Access right violation */
qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
+ if (!guest_visible) {
+ return false;
+ }
if (access_type == MMU_INST_FETCH) {
int srr1 = 0;
if (PAGE_EXEC & ~exec_prot) {
@@ -1035,7 +1048,7 @@ skip_slb_search:
if (PAGE_EXEC & ~amr_prot) {
srr1 |= SRR1_IAMR; /* Access violates virt pg class key prot */
}
- ppc_hash64_set_isi(cs, srr1);
+ ppc_hash64_set_isi(cs, mmu_idx, srr1);
} else {
int dsisr = 0;
if (need_prot & ~pp_prot) {
@@ -1047,9 +1060,9 @@ skip_slb_search:
if (need_prot & ~amr_prot) {
dsisr |= DSISR_AMR;
}
- ppc_hash64_set_dsi(cs, eaddr, dsisr);
+ ppc_hash64_set_dsi(cs, mmu_idx, eaddr, dsisr);
}
- return 1;
+ return false;
}
qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
@@ -1073,66 +1086,10 @@ skip_slb_search:
/* 7. Determine the real address from the PTE */
- raddr = deposit64(pte.pte1 & HPTE64_R_RPN, 0, apshift, eaddr);
-
- tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
- prot, mmu_idx, 1ULL << apshift);
-
- return 0;
-}
-
-hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr)
-{
- CPUPPCState *env = &cpu->env;
- ppc_slb_t vrma_slbe;
- ppc_slb_t *slb;
- hwaddr ptex, raddr;
- ppc_hash_pte64_t pte;
- unsigned apshift;
-
- /* Handle real mode */
- if (msr_dr == 0) {
- /* In real mode the top 4 effective address bits are ignored */
- raddr = addr & 0x0FFFFFFFFFFFFFFFULL;
-
- if (cpu->vhyp) {
- /*
- * In virtual hypervisor mode, there's nothing to do:
- * EA == GPA == qemu guest address
- */
- return raddr;
- } else if ((msr_hv || !env->has_hv_mode) && !(addr >> 63)) {
- /* In HV mode, add HRMOR if top EA bit is clear */
- return raddr | env->spr[SPR_HRMOR];
- } else if (ppc_hash64_use_vrma(env)) {
- /* Emulated VRMA mode */
- slb = &vrma_slbe;
- if (build_vrma_slbe(cpu, slb) != 0) {
- return -1;
- }
- } else {
- target_ulong limit = rmls_limit(cpu);
-
- /* Emulated old-style RMO mode, bounds check against RMLS */
- if (raddr >= limit) {
- return -1;
- }
- return raddr | env->spr[SPR_RMOR];
- }
- } else {
- slb = slb_lookup(cpu, addr);
- if (!slb) {
- return -1;
- }
- }
-
- ptex = ppc_hash64_htab_lookup(cpu, slb, addr, &pte, &apshift);
- if (ptex == -1) {
- return -1;
- }
-
- return deposit64(pte.pte1 & HPTE64_R_RPN, 0, apshift, addr)
- & TARGET_PAGE_MASK;
+ *raddrp = deposit64(pte.pte1 & HPTE64_R_RPN, 0, apshift, eaddr);
+ *protp = prot;
+ *psizep = apshift;
+ return true;
}
void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong ptex,
diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h
index 4b8b8e7950..c5b2f97ff7 100644
--- a/target/ppc/mmu-hash64.h
+++ b/target/ppc/mmu-hash64.h
@@ -7,9 +7,9 @@
void dump_slb(PowerPCCPU *cpu);
int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot,
target_ulong esid, target_ulong vsid);
-hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr);
-int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, int rw,
- int mmu_idx);
+bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+ hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
+ bool guest_visible);
void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu,
target_ulong pte_index,
target_ulong pte0, target_ulong pte1);
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index b6d191c1d8..5b0e62e676 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -155,7 +155,7 @@ static void ppc_radix64_raise_hsi(PowerPCCPU *cpu, MMUAccessType access_type,
static bool ppc_radix64_check_prot(PowerPCCPU *cpu, MMUAccessType access_type,
uint64_t pte, int *fault_cause, int *prot,
- bool partition_scoped)
+ int mmu_idx, bool partition_scoped)
{
CPUPPCState *env = &cpu->env;
int need_prot;
@@ -173,7 +173,8 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, MMUAccessType access_type,
/* Determine permissions allowed by Encoded Access Authority */
if (!partition_scoped && (pte & R_PTE_EAA_PRIV) && msr_pr) {
*prot = 0;
- } else if (msr_pr || (pte & R_PTE_EAA_PRIV) || partition_scoped) {
+ } else if (mmuidx_pr(mmu_idx) || (pte & R_PTE_EAA_PRIV) ||
+ partition_scoped) {
*prot = ppc_radix64_get_prot_eaa(pte);
} else { /* !msr_pr && !(pte & R_PTE_EAA_PRIV) && !partition_scoped */
*prot = ppc_radix64_get_prot_eaa(pte);
@@ -299,7 +300,7 @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu,
ppc_v3_pate_t pate,
hwaddr *h_raddr, int *h_prot,
int *h_page_size, bool pde_addr,
- bool guest_visible)
+ int mmu_idx, bool guest_visible)
{
int fault_cause = 0;
hwaddr pte_addr;
@@ -310,7 +311,8 @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu,
if (ppc_radix64_walk_tree(CPU(cpu)->as, g_raddr, pate.dw0 & PRTBE_R_RPDB,
pate.dw0 & PRTBE_R_RPDS, h_raddr, h_page_size,
&pte, &fault_cause, &pte_addr) ||
- ppc_radix64_check_prot(cpu, access_type, pte, &fault_cause, h_prot, true)) {
+ ppc_radix64_check_prot(cpu, access_type, pte,
+ &fault_cause, h_prot, mmu_idx, true)) {
if (pde_addr) { /* address being translated was that of a guest pde */
fault_cause |= DSISR_PRTABLE_FAULT;
}
@@ -332,7 +334,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,
vaddr eaddr, uint64_t pid,
ppc_v3_pate_t pate, hwaddr *g_raddr,
int *g_prot, int *g_page_size,
- bool guest_visible)
+ int mmu_idx, bool guest_visible)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
@@ -367,7 +369,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,
ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, prtbe_addr,
pate, &h_raddr, &h_prot,
&h_page_size, true,
- guest_visible);
+ /* mmu_idx is 5 because we're translating from hypervisor scope */
+ 5, guest_visible);
if (ret) {
return ret;
}
@@ -407,7 +410,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,
ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, pte_addr,
pate, &h_raddr, &h_prot,
&h_page_size, true,
- guest_visible);
+ /* mmu_idx is 5 because we're translating from hypervisor scope */
+ 5, guest_visible);
if (ret) {
return ret;
}
@@ -431,7 +435,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,
*g_raddr = (rpn & ~mask) | (eaddr & mask);
}
- if (ppc_radix64_check_prot(cpu, access_type, pte, &fault_cause, g_prot, false)) {
+ if (ppc_radix64_check_prot(cpu, access_type, pte, &fault_cause,
+ g_prot, mmu_idx, false)) {
/* Access denied due to protection */
if (guest_visible) {
ppc_radix64_raise_si(cpu, access_type, eaddr, fault_cause);
@@ -463,24 +468,53 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,
* | = On | Process Scoped | Scoped |
* +-------------+----------------+---------------+
*/
-static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr,
- MMUAccessType access_type,
- bool relocation,
- hwaddr *raddr, int *psizep, int *protp,
- bool guest_visible)
+bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+ hwaddr *raddr, int *psizep, int *protp, int mmu_idx,
+ bool guest_visible)
{
CPUPPCState *env = &cpu->env;
uint64_t lpid, pid;
ppc_v3_pate_t pate;
int psize, prot;
hwaddr g_raddr;
+ bool relocation;
+
+ assert(!(mmuidx_hv(mmu_idx) && cpu->vhyp));
+
+ relocation = !mmuidx_real(mmu_idx);
+
+ /* HV or virtual hypervisor Real Mode Access */
+ if (!relocation && (mmuidx_hv(mmu_idx) || cpu->vhyp)) {
+ /* In real mode top 4 effective addr bits (mostly) ignored */
+ *raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
+
+ /* In HV mode, add HRMOR if top EA bit is clear */
+ if (mmuidx_hv(mmu_idx) || !env->has_hv_mode) {
+ if (!(eaddr >> 63)) {
+ *raddr |= env->spr[SPR_HRMOR];
+ }
+ }
+ *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ *psizep = TARGET_PAGE_BITS;
+ return true;
+ }
+
+ /*
+ * Check UPRT (we avoid the check in real mode to deal with
+ * transitional states during kexec.
+ */
+ if (guest_visible && !ppc64_use_proc_tbl(cpu)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "LPCR:UPRT not set in radix mode ! LPCR="
+ TARGET_FMT_lx "\n", env->spr[SPR_LPCR]);
+ }
/* Virtual Mode Access - get the fully qualified address */
if (!ppc_radix64_get_fully_qualified_addr(&cpu->env, eaddr, &lpid, &pid)) {
if (guest_visible) {
ppc_radix64_raise_segi(cpu, access_type, eaddr);
}
- return 1;
+ return false;
}
/* Get Process Table */
@@ -493,13 +527,13 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr,
if (guest_visible) {
ppc_radix64_raise_si(cpu, access_type, eaddr, DSISR_NOPTE);
}
- return 1;
+ return false;
}
if (!validate_pate(cpu, lpid, &pate)) {
if (guest_visible) {
ppc_radix64_raise_si(cpu, access_type, eaddr, DSISR_R_BADCONFIG);
}
- return 1;
+ return false;
}
}
@@ -517,9 +551,9 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr,
if (relocation) {
int ret = ppc_radix64_process_scoped_xlate(cpu, access_type, eaddr, pid,
pate, &g_raddr, &prot,
- &psize, guest_visible);
+ &psize, mmu_idx, guest_visible);
if (ret) {
- return ret;
+ return false;
}
*psizep = MIN(*psizep, psize);
*protp &= prot;
@@ -535,15 +569,15 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr,
* quadrants 1 or 2. Translates a guest real address to a host
* real address.
*/
- if (lpid || !msr_hv) {
+ if (lpid || !mmuidx_hv(mmu_idx)) {
int ret;
ret = ppc_radix64_partition_scoped_xlate(cpu, access_type, eaddr,
g_raddr, pate, raddr,
&prot, &psize, false,
- guest_visible);
+ mmu_idx, guest_visible);
if (ret) {
- return ret;
+ return false;
}
*psizep = MIN(*psizep, psize);
*protp &= prot;
@@ -552,78 +586,5 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr,
}
}
- return 0;
-}
-
-int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
- int mmu_idx)
-{
- CPUState *cs = CPU(cpu);
- CPUPPCState *env = &cpu->env;
- int page_size, prot;
- bool relocation;
- MMUAccessType access_type;
- hwaddr raddr;
-
- assert(!(msr_hv && cpu->vhyp));
- assert((rwx == 0) || (rwx == 1) || (rwx == 2));
- access_type = rwx;
-
- relocation = (access_type == MMU_INST_FETCH ? msr_ir : msr_dr);
- /* HV or virtual hypervisor Real Mode Access */
- if (!relocation && (msr_hv || cpu->vhyp)) {
- /* In real mode top 4 effective addr bits (mostly) ignored */
- raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
-
- /* In HV mode, add HRMOR if top EA bit is clear */
- if (msr_hv || !env->has_hv_mode) {
- if (!(eaddr >> 63)) {
- raddr |= env->spr[SPR_HRMOR];
- }
- }
- tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
- PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx,
- TARGET_PAGE_SIZE);
- return 0;
- }
-
- /*
- * Check UPRT (we avoid the check in real mode to deal with
- * transitional states during kexec.
- */
- if (!ppc64_use_proc_tbl(cpu)) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "LPCR:UPRT not set in radix mode ! LPCR="
- TARGET_FMT_lx "\n", env->spr[SPR_LPCR]);
- }
-
- /* Translate eaddr to raddr (where raddr is addr qemu needs for access) */
- if (ppc_radix64_xlate(cpu, eaddr, access_type, relocation, &raddr,
- &page_size, &prot, true)) {
- return 1;
- }
-
- tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
- prot, mmu_idx, 1UL << page_size);
- return 0;
-}
-
-hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr)
-{
- CPUPPCState *env = &cpu->env;
- int psize, prot;
- hwaddr raddr;
-
- /* Handle Real Mode */
- if ((msr_dr == 0) && (msr_hv || cpu->vhyp)) {
- /* In real mode top 4 effective addr bits (mostly) ignored */
- return eaddr & 0x0FFFFFFFFFFFFFFFULL;
- }
-
- if (ppc_radix64_xlate(cpu, eaddr, 0, msr_dr, &raddr, &psize,
- &prot, false)) {
- return -1;
- }
-
- return raddr & TARGET_PAGE_MASK;
+ return true;
}
diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h
index f28c5794d0..b70357cf34 100644
--- a/target/ppc/mmu-radix64.h
+++ b/target/ppc/mmu-radix64.h
@@ -44,9 +44,9 @@
#ifdef TARGET_PPC64
-int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
- int mmu_idx);
-hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr);
+bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+ hwaddr *raddr, int *psizep, int *protp, int mmu_idx,
+ bool guest_visible);
static inline int ppc_radix64_get_prot_eaa(uint64_t pte)
{
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index 1ecb36e85a..869d24d301 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -511,7 +511,7 @@ static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
"\n", ppc_hash32_hpt_base(cpu),
- ppc_hash32_hpt_mask(env) + 0x80);
+ ppc_hash32_hpt_mask(cpu) + 0x80);
for (curaddr = ppc_hash32_hpt_base(cpu);
curaddr < (ppc_hash32_hpt_base(cpu)
+ ppc_hash32_hpt_mask(cpu) + 0x80);
@@ -825,6 +825,7 @@ static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
return ret;
}
+#ifdef CONFIG_TCG
static void booke206_flush_tlb(CPUPPCState *env, int flags,
const int check_iprot)
{
@@ -846,6 +847,7 @@ static void booke206_flush_tlb(CPUPPCState *env, int flags,
tlb_flush(env_cpu(env));
}
+#endif
static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
ppcmas_tlb_t *tlb)
@@ -1435,48 +1437,6 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
}
#endif
-hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
-{
- PowerPCCPU *cpu = POWERPC_CPU(cs);
- CPUPPCState *env = &cpu->env;
- mmu_ctx_t ctx;
-
- switch (env->mmu_model) {
-#if defined(TARGET_PPC64)
- case POWERPC_MMU_64B:
- case POWERPC_MMU_2_03:
- case POWERPC_MMU_2_06:
- case POWERPC_MMU_2_07:
- return ppc_hash64_get_phys_page_debug(cpu, addr);
- case POWERPC_MMU_3_00:
- return ppc64_v3_get_phys_page_debug(cpu, addr);
-#endif
-
- case POWERPC_MMU_32B:
- case POWERPC_MMU_601:
- return ppc_hash32_get_phys_page_debug(cpu, addr);
-
- default:
- ;
- }
-
- if (unlikely(get_physical_address(env, &ctx, addr, MMU_DATA_LOAD,
- ACCESS_INT) != 0)) {
-
- /*
- * Some MMUs have separate TLBs for code and data. If we only
- * try an ACCESS_INT, we may not be able to read instructions
- * mapped by code TLBs, so we also try a ACCESS_CODE.
- */
- if (unlikely(get_physical_address(env, &ctx, addr, MMU_INST_FETCH,
- ACCESS_CODE) != 0)) {
- return -1;
- }
- }
-
- return ctx.raddr & TARGET_PAGE_MASK;
-}
-
static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
MMUAccessType access_type, int mmu_idx)
{
@@ -1532,30 +1492,38 @@ static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
}
/* Perform address translation */
-static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
- MMUAccessType access_type, int mmu_idx)
+/* TODO: Split this by mmu_model. */
+static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
+ MMUAccessType access_type,
+ hwaddr *raddrp, int *psizep, int *protp,
+ int mmu_idx, bool guest_visible)
{
- CPUState *cs = env_cpu(env);
- PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUState *cs = CPU(cpu);
+ CPUPPCState *env = &cpu->env;
mmu_ctx_t ctx;
int type;
- int ret = 0;
+ int ret;
if (access_type == MMU_INST_FETCH) {
/* code access */
type = ACCESS_CODE;
- } else {
+ } else if (guest_visible) {
/* data access */
type = env->access_type;
+ } else {
+ type = ACCESS_INT;
}
- ret = get_physical_address_wtlb(env, &ctx, address, access_type,
+
+ ret = get_physical_address_wtlb(env, &ctx, eaddr, access_type,
type, mmu_idx);
if (ret == 0) {
- tlb_set_page(cs, address & TARGET_PAGE_MASK,
- ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
- mmu_idx, TARGET_PAGE_SIZE);
- ret = 0;
- } else if (ret < 0) {
+ *raddrp = ctx.raddr;
+ *protp = ctx.prot;
+ *psizep = TARGET_PAGE_BITS;
+ return true;
+ }
+
+ if (guest_visible) {
LOG_MMU_STATE(cs);
if (type == ACCESS_CODE) {
switch (ret) {
@@ -1565,7 +1533,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
case POWERPC_MMU_SOFT_6xx:
cs->exception_index = POWERPC_EXCP_IFTLB;
env->error_code = 1 << 18;
- env->spr[SPR_IMISS] = address;
+ env->spr[SPR_IMISS] = eaddr;
env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
goto tlb_miss;
case POWERPC_MMU_SOFT_74xx:
@@ -1575,29 +1543,25 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
case POWERPC_MMU_SOFT_4xx_Z:
cs->exception_index = POWERPC_EXCP_ITLB;
env->error_code = 0;
- env->spr[SPR_40x_DEAR] = address;
+ env->spr[SPR_40x_DEAR] = eaddr;
env->spr[SPR_40x_ESR] = 0x00000000;
break;
case POWERPC_MMU_BOOKE206:
- booke206_update_mas_tlb_miss(env, address, 2, mmu_idx);
+ booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
/* fall through */
case POWERPC_MMU_BOOKE:
cs->exception_index = POWERPC_EXCP_ITLB;
env->error_code = 0;
- env->spr[SPR_BOOKE_DEAR] = address;
+ env->spr[SPR_BOOKE_DEAR] = eaddr;
env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, MMU_DATA_LOAD);
- return -1;
+ break;
case POWERPC_MMU_MPC8xx:
- /* XXX: TODO */
cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
- break;
case POWERPC_MMU_REAL:
cpu_abort(cs, "PowerPC in real mode should never raise "
"any MMU exceptions\n");
- return -1;
default:
cpu_abort(cs, "Unknown or invalid MMU model\n");
- return -1;
}
break;
case -2:
@@ -1634,7 +1598,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
cs->exception_index = POWERPC_EXCP_DLTLB;
env->error_code = 0;
}
- env->spr[SPR_DMISS] = address;
+ env->spr[SPR_DMISS] = eaddr;
env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
tlb_miss:
env->error_code |= ctx.key << 19;
@@ -1652,7 +1616,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
tlb_miss_74xx:
/* Implement LRU algorithm */
env->error_code = ctx.key << 19;
- env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
+ env->spr[SPR_TLBMISS] = (eaddr & ~((target_ulong)0x3)) |
((env->last_way + 1) & (env->nb_ways - 1));
env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
break;
@@ -1660,7 +1624,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
case POWERPC_MMU_SOFT_4xx_Z:
cs->exception_index = POWERPC_EXCP_DTLB;
env->error_code = 0;
- env->spr[SPR_40x_DEAR] = address;
+ env->spr[SPR_40x_DEAR] = eaddr;
if (access_type == MMU_DATA_STORE) {
env->spr[SPR_40x_ESR] = 0x00800000;
} else {
@@ -1670,23 +1634,20 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
case POWERPC_MMU_MPC8xx:
/* XXX: TODO */
cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
- break;
case POWERPC_MMU_BOOKE206:
- booke206_update_mas_tlb_miss(env, address, access_type, mmu_idx);
+ booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
/* fall through */
case POWERPC_MMU_BOOKE:
cs->exception_index = POWERPC_EXCP_DTLB;
env->error_code = 0;
- env->spr[SPR_BOOKE_DEAR] = address;
+ env->spr[SPR_BOOKE_DEAR] = eaddr;
env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
- return -1;
+ break;
case POWERPC_MMU_REAL:
cpu_abort(cs, "PowerPC in real mode should never raise "
"any MMU exceptions\n");
- return -1;
default:
cpu_abort(cs, "Unknown or invalid MMU model\n");
- return -1;
}
break;
case -2:
@@ -1695,16 +1656,16 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
env->error_code = 0;
if (env->mmu_model == POWERPC_MMU_SOFT_4xx
|| env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
- env->spr[SPR_40x_DEAR] = address;
+ env->spr[SPR_40x_DEAR] = eaddr;
if (access_type == MMU_DATA_STORE) {
env->spr[SPR_40x_ESR] |= 0x00800000;
}
} else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
(env->mmu_model == POWERPC_MMU_BOOKE206)) {
- env->spr[SPR_BOOKE_DEAR] = address;
+ env->spr[SPR_BOOKE_DEAR] = eaddr;
env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
} else {
- env->spr[SPR_DAR] = address;
+ env->spr[SPR_DAR] = eaddr;
if (access_type == MMU_DATA_STORE) {
env->spr[SPR_DSISR] = 0x0A000000;
} else {
@@ -1719,13 +1680,13 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
/* Floating point load/store */
cs->exception_index = POWERPC_EXCP_ALIGN;
env->error_code = POWERPC_EXCP_ALIGN_FP;
- env->spr[SPR_DAR] = address;
+ env->spr[SPR_DAR] = eaddr;
break;
case ACCESS_RES:
/* lwarx, ldarx or stwcx. */
cs->exception_index = POWERPC_EXCP_DSI;
env->error_code = 0;
- env->spr[SPR_DAR] = address;
+ env->spr[SPR_DAR] = eaddr;
if (access_type == MMU_DATA_STORE) {
env->spr[SPR_DSISR] = 0x06000000;
} else {
@@ -1736,7 +1697,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
/* eciwx or ecowx */
cs->exception_index = POWERPC_EXCP_DSI;
env->error_code = 0;
- env->spr[SPR_DAR] = address;
+ env->spr[SPR_DAR] = eaddr;
if (access_type == MMU_DATA_STORE) {
env->spr[SPR_DSISR] = 0x06100000;
} else {
@@ -1748,16 +1709,14 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
cs->exception_index = POWERPC_EXCP_PROGRAM;
env->error_code =
POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
- env->spr[SPR_DAR] = address;
+ env->spr[SPR_DAR] = eaddr;
break;
}
break;
}
}
- ret = 1;
}
-
- return ret;
+ return false;
}
#ifdef CONFIG_TCG
@@ -1798,9 +1757,6 @@ static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
{
target_ulong mask;
-#if defined(FLUSH_ALL_TLBS)
- PowerPCCPU *cpu = env_archcpu(env);
-#endif
dump_store_bat(env, 'I', 0, nr, value);
if (env->IBAT[0][nr] != value) {
@@ -1834,9 +1790,6 @@ void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value)
void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
{
target_ulong mask;
-#if defined(FLUSH_ALL_TLBS)
- PowerPCCPU *cpu = env_archcpu(env);
-#endif
dump_store_bat(env, 'D', 0, nr, value);
if (env->DBAT[0][nr] != value) {
@@ -1871,7 +1824,6 @@ void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
{
target_ulong mask;
#if defined(FLUSH_ALL_TLBS)
- PowerPCCPU *cpu = env_archcpu(env);
int do_inval;
#endif
@@ -1916,7 +1868,6 @@ void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
#if !defined(FLUSH_ALL_TLBS)
target_ulong mask;
#else
- PowerPCCPU *cpu = env_archcpu(env);
int do_inval;
#endif
@@ -1952,6 +1903,7 @@ void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
}
#endif
+#ifdef CONFIG_TCG
/*****************************************************************************/
/* TLB management */
void ppc_tlb_invalidate_all(CPUPPCState *env)
@@ -1995,6 +1947,7 @@ void ppc_tlb_invalidate_all(CPUPPCState *env)
break;
}
}
+#endif
#ifdef CONFIG_TCG
void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
@@ -2942,26 +2895,76 @@ void helper_check_tlb_flush_global(CPUPPCState *env)
/*****************************************************************************/
-bool ppc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
+static bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+ hwaddr *raddrp, int *psizep, int *protp,
+ int mmu_idx, bool guest_visible)
+{
+ switch (cpu->env.mmu_model) {
+#if defined(TARGET_PPC64)
+ case POWERPC_MMU_3_00:
+ if (ppc64_v3_radix(cpu)) {
+ return ppc_radix64_xlate(cpu, eaddr, access_type,
+ raddrp, psizep, protp, mmu_idx, guest_visible);
+ }
+ /* fall through */
+ case POWERPC_MMU_64B:
+ case POWERPC_MMU_2_03:
+ case POWERPC_MMU_2_06:
+ case POWERPC_MMU_2_07:
+ return ppc_hash64_xlate(cpu, eaddr, access_type,
+ raddrp, psizep, protp, mmu_idx, guest_visible);
+#endif
+
+ case POWERPC_MMU_32B:
+ case POWERPC_MMU_601:
+ return ppc_hash32_xlate(cpu, eaddr, access_type,
+ raddrp, psizep, protp, mmu_idx, guest_visible);
+
+ default:
+ return ppc_jumbo_xlate(cpu, eaddr, access_type, raddrp,
+ psizep, protp, mmu_idx, guest_visible);
+ }
+}
+
+hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ hwaddr raddr;
+ int s, p;
+
+ /*
+ * Some MMUs have separate TLBs for code and data. If we only
+ * try an MMU_DATA_LOAD, we may not be able to read instructions
+ * mapped by code TLBs, so we also try a MMU_INST_FETCH.
+ */
+ if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p,
+ cpu_mmu_index(&cpu->env, false), false) ||
+ ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p,
+ cpu_mmu_index(&cpu->env, true), false)) {
+ return raddr & TARGET_PAGE_MASK;
+ }
+ return -1;
+}
+
+#ifdef CONFIG_TCG
+bool ppc_cpu_tlb_fill(CPUState *cs, vaddr eaddr, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
- PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
- CPUPPCState *env = &cpu->env;
- int ret;
+ hwaddr raddr;
+ int page_size, prot;
- if (pcc->handle_mmu_fault) {
- ret = pcc->handle_mmu_fault(cpu, addr, access_type, mmu_idx);
- } else {
- ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx);
+ if (ppc_xlate(cpu, eaddr, access_type, &raddr,
+ &page_size, &prot, mmu_idx, !probe)) {
+ tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
+ prot, mmu_idx, 1UL << page_size);
+ return true;
}
- if (unlikely(ret != 0)) {
- if (probe) {
- return false;
- }
- raise_exception_err_ra(env, cs->exception_index, env->error_code,
- retaddr);
+ if (probe) {
+ return false;
}
- return true;
+ raise_exception_err_ra(&cpu->env, cs->exception_index,
+ cpu->env.error_code, retaddr);
}
+#endif
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 0ad601793c..0a55cb7181 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4931,6 +4931,11 @@ static void gen_mtcrf(DisasContext *ctx)
#if defined(TARGET_PPC64)
static void gen_mtmsrd(DisasContext *ctx)
{
+ if (unlikely(!is_book3s_arch2x(ctx))) {
+ gen_invalid(ctx);
+ return;
+ }
+
CHK_SV;
#if !defined(CONFIG_USER_ONLY)
diff --git a/target/riscv/Kconfig b/target/riscv/Kconfig
new file mode 100644
index 0000000000..b9e5932f13
--- /dev/null
+++ b/target/riscv/Kconfig
@@ -0,0 +1,5 @@
+config RISCV32
+ bool
+
+config RISCV64
+ bool
diff --git a/target/rx/Kconfig b/target/rx/Kconfig
new file mode 100644
index 0000000000..aceb5ed28f
--- /dev/null
+++ b/target/rx/Kconfig
@@ -0,0 +1,2 @@
+config RX
+ bool
diff --git a/target/s390x/Kconfig b/target/s390x/Kconfig
new file mode 100644
index 0000000000..72da48136c
--- /dev/null
+++ b/target/s390x/Kconfig
@@ -0,0 +1,2 @@
+config S390X
+ bool
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 0cfe29d227..c8d55d1f83 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -6257,8 +6257,10 @@ static void extract_field(DisasFields *o, const DisasField *f, uint64_t insn)
abort();
}
- /* Validate that the "compressed" encoding we selected above is valid.
- I.e. we havn't make two different original fields overlap. */
+ /*
+ * Validate that the "compressed" encoding we selected above is valid.
+ * I.e. we haven't made two different original fields overlap.
+ */
assert(((o->presentC >> f->indexC) & 1) == 0);
o->presentC |= 1 << f->indexC;
o->presentO |= 1 << f->indexO;
diff --git a/target/sh4/Kconfig b/target/sh4/Kconfig
new file mode 100644
index 0000000000..2397c86028
--- /dev/null
+++ b/target/sh4/Kconfig
@@ -0,0 +1,2 @@
+config SH4
+ bool
diff --git a/target/sparc/Kconfig b/target/sparc/Kconfig
new file mode 100644
index 0000000000..70cc0f3a21
--- /dev/null
+++ b/target/sparc/Kconfig
@@ -0,0 +1,5 @@
+config SPARC
+ bool
+
+config SPARC64
+ bool
diff --git a/target/tricore/Kconfig b/target/tricore/Kconfig
new file mode 100644
index 0000000000..9313409309
--- /dev/null
+++ b/target/tricore/Kconfig
@@ -0,0 +1,2 @@
+config TRICORE
+ bool
diff --git a/target/xtensa/Kconfig b/target/xtensa/Kconfig
new file mode 100644
index 0000000000..a3c8dc7f6d
--- /dev/null
+++ b/target/xtensa/Kconfig
@@ -0,0 +1,2 @@
+config XTENSA
+ bool
diff --git a/target/xtensa/xtensa-semi.c b/target/xtensa/xtensa-semi.c
index 79f2b043f2..fa21b7e11f 100644
--- a/target/xtensa/xtensa-semi.c
+++ b/target/xtensa/xtensa-semi.c
@@ -95,59 +95,53 @@ enum {
static uint32_t errno_h2g(int host_errno)
{
- static const uint32_t guest_errno[] = {
- [EPERM] = TARGET_EPERM,
- [ENOENT] = TARGET_ENOENT,
- [ESRCH] = TARGET_ESRCH,
- [EINTR] = TARGET_EINTR,
- [EIO] = TARGET_EIO,
- [ENXIO] = TARGET_ENXIO,
- [E2BIG] = TARGET_E2BIG,
- [ENOEXEC] = TARGET_ENOEXEC,
- [EBADF] = TARGET_EBADF,
- [ECHILD] = TARGET_ECHILD,
- [EAGAIN] = TARGET_EAGAIN,
- [ENOMEM] = TARGET_ENOMEM,
- [EACCES] = TARGET_EACCES,
- [EFAULT] = TARGET_EFAULT,
+ switch (host_errno) {
+ case 0: return 0;
+ case EPERM: return TARGET_EPERM;
+ case ENOENT: return TARGET_ENOENT;
+ case ESRCH: return TARGET_ESRCH;
+ case EINTR: return TARGET_EINTR;
+ case EIO: return TARGET_EIO;
+ case ENXIO: return TARGET_ENXIO;
+ case E2BIG: return TARGET_E2BIG;
+ case ENOEXEC: return TARGET_ENOEXEC;
+ case EBADF: return TARGET_EBADF;
+ case ECHILD: return TARGET_ECHILD;
+ case EAGAIN: return TARGET_EAGAIN;
+ case ENOMEM: return TARGET_ENOMEM;
+ case EACCES: return TARGET_EACCES;
+ case EFAULT: return TARGET_EFAULT;
#ifdef ENOTBLK
- [ENOTBLK] = TARGET_ENOTBLK,
+ case ENOTBLK: return TARGET_ENOTBLK;
#endif
- [EBUSY] = TARGET_EBUSY,
- [EEXIST] = TARGET_EEXIST,
- [EXDEV] = TARGET_EXDEV,
- [ENODEV] = TARGET_ENODEV,
- [ENOTDIR] = TARGET_ENOTDIR,
- [EISDIR] = TARGET_EISDIR,
- [EINVAL] = TARGET_EINVAL,
- [ENFILE] = TARGET_ENFILE,
- [EMFILE] = TARGET_EMFILE,
- [ENOTTY] = TARGET_ENOTTY,
+ case EBUSY: return TARGET_EBUSY;
+ case EEXIST: return TARGET_EEXIST;
+ case EXDEV: return TARGET_EXDEV;
+ case ENODEV: return TARGET_ENODEV;
+ case ENOTDIR: return TARGET_ENOTDIR;
+ case EISDIR: return TARGET_EISDIR;
+ case EINVAL: return TARGET_EINVAL;
+ case ENFILE: return TARGET_ENFILE;
+ case EMFILE: return TARGET_EMFILE;
+ case ENOTTY: return TARGET_ENOTTY;
#ifdef ETXTBSY
- [ETXTBSY] = TARGET_ETXTBSY,
+ case ETXTBSY: return TARGET_ETXTBSY;
#endif
- [EFBIG] = TARGET_EFBIG,
- [ENOSPC] = TARGET_ENOSPC,
- [ESPIPE] = TARGET_ESPIPE,
- [EROFS] = TARGET_EROFS,
- [EMLINK] = TARGET_EMLINK,
- [EPIPE] = TARGET_EPIPE,
- [EDOM] = TARGET_EDOM,
- [ERANGE] = TARGET_ERANGE,
- [ENOSYS] = TARGET_ENOSYS,
+ case EFBIG: return TARGET_EFBIG;
+ case ENOSPC: return TARGET_ENOSPC;
+ case ESPIPE: return TARGET_ESPIPE;
+ case EROFS: return TARGET_EROFS;
+ case EMLINK: return TARGET_EMLINK;
+ case EPIPE: return TARGET_EPIPE;
+ case EDOM: return TARGET_EDOM;
+ case ERANGE: return TARGET_ERANGE;
+ case ENOSYS: return TARGET_ENOSYS;
#ifdef ELOOP
- [ELOOP] = TARGET_ELOOP,
+ case ELOOP: return TARGET_ELOOP;
#endif
};
- if (host_errno == 0) {
- return 0;
- } else if (host_errno > 0 && host_errno < ARRAY_SIZE(guest_errno) &&
- guest_errno[host_errno]) {
- return guest_errno[host_errno];
- } else {
- return TARGET_EINVAL;
- }
+ return TARGET_EINVAL;
}
typedef struct XtensaSimConsole {