mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/dg-gitlab/tags/ppc-for-6.1-20210519' into staging
ppc patch queue 2021-05-19 Next set of ppc related patches for qemu-6.1. Highlights are: * Start of a significant softmmu cleanup from Richard Henderson * Further work towards allowing builds without CONFIG_TCG # gpg: Signature made Wed 19 May 2021 13:36:45 BST # 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/dg-gitlab/tags/ppc-for-6.1-20210519: (48 commits) target/ppc: Remove type argument for mmubooke206_get_physical_address target/ppc: Remove type argument from mmubooke206_check_tlb target/ppc: Remove type argument from mmubooke_get_physical_address target/ppc: Remove type argument from mmubooke_check_tlb target/ppc: Remove type argument from mmu40x_get_physical_address target/ppc: Remove type argument from get_bat_6xx_tlb target/ppc: Remove type argument from ppc6xx_tlb_check target/ppc: Remove type argument from ppc6xx_tlb_pte_check target/ppc: Remove type argument from check_prot target/ppc: Use MMUAccessType in mmu_helper.c target/ppc: Rename access_type to type in mmu_helper.c target/ppc: Use MMUAccessType in mmu-hash32.c target/ppc: Use MMUAccessType in mmu-hash64.c target/ppc: Use MMUAccessType in mmu-radix64.c target/ppc: Introduce prot_for_access_type target/ppc: Fix load endianness for lxvwsx/lxvdsx target/ppc: Use translator_loop_temp_check target/ppc: Mark helper_raise_exception* as noreturn target/ppc: Tidy exception vs exit_tb target/ppc: Move single-step check to ppc_tr_tb_stop ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -29,6 +29,9 @@ ppc_ss.add(when: 'CONFIG_PSERIES', if_true: files(
|
||||
'spapr_numa.c',
|
||||
'pef.c',
|
||||
))
|
||||
ppc_ss.add(when: ['CONFIG_PSERIES', 'CONFIG_TCG'], if_true: files(
|
||||
'spapr_softmmu.c',
|
||||
))
|
||||
ppc_ss.add(when: 'CONFIG_SPAPR_RNG', if_true: files('spapr_rng.c'))
|
||||
ppc_ss.add(when: ['CONFIG_PSERIES', 'CONFIG_LINUX'], if_true: files(
|
||||
'spapr_pci_vfio.c',
|
||||
|
||||
+1
-1
@@ -196,7 +196,7 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
|
||||
_FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
|
||||
_FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
|
||||
|
||||
if (env->spr_cb[SPR_PURR].oea_read) {
|
||||
if (ppc_has_spr(cpu, SPR_PURR)) {
|
||||
_FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
|
||||
}
|
||||
|
||||
|
||||
+19
-2
@@ -703,10 +703,10 @@ static void spapr_dt_cpu(CPUState *cs, void *fdt, int offset,
|
||||
_FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
|
||||
_FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
|
||||
|
||||
if (env->spr_cb[SPR_PURR].oea_read) {
|
||||
if (ppc_has_spr(cpu, SPR_PURR)) {
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,purr", 1)));
|
||||
}
|
||||
if (env->spr_cb[SPR_SPURR].oea_read) {
|
||||
if (ppc_has_spr(cpu, SPR_PURR)) {
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1)));
|
||||
}
|
||||
|
||||
@@ -979,6 +979,7 @@ static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
|
||||
*/
|
||||
val[1] = SPAPR_OV5_XIVE_LEGACY; /* XICS */
|
||||
val[3] = 0x00; /* Hash */
|
||||
spapr_check_mmu_mode(false);
|
||||
} else if (kvm_enabled()) {
|
||||
if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) {
|
||||
val[3] = 0x80; /* OV5_MMU_BOTH */
|
||||
@@ -1556,6 +1557,22 @@ void spapr_setup_hpt(SpaprMachineState *spapr)
|
||||
}
|
||||
}
|
||||
|
||||
void spapr_check_mmu_mode(bool guest_radix)
|
||||
{
|
||||
if (guest_radix) {
|
||||
if (kvm_enabled() && !kvmppc_has_cap_mmu_radix()) {
|
||||
error_report("Guest requested unavailable MMU mode (radix).");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
if (kvm_enabled() && kvmppc_has_cap_mmu_radix()
|
||||
&& !kvmppc_has_cap_mmu_hash_v3()) {
|
||||
error_report("Guest requested unavailable MMU mode (hash).");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void spapr_machine_reset(MachineState *machine)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(machine);
|
||||
|
||||
@@ -371,6 +371,65 @@ static bool spapr_pagesize_cb(void *opaque, uint32_t seg_pshift,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ppc_hash64_filter_pagesizes(PowerPCCPU *cpu,
|
||||
bool (*cb)(void *, uint32_t, uint32_t),
|
||||
void *opaque)
|
||||
{
|
||||
PPCHash64Options *opts = cpu->hash64_opts;
|
||||
int i;
|
||||
int n = 0;
|
||||
bool ci_largepage = false;
|
||||
|
||||
assert(opts);
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(opts->sps); i++) {
|
||||
PPCHash64SegmentPageSizes *sps = &opts->sps[i];
|
||||
int j;
|
||||
int m = 0;
|
||||
|
||||
assert(n <= i);
|
||||
|
||||
if (!sps->page_shift) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(sps->enc); j++) {
|
||||
PPCHash64PageSize *ps = &sps->enc[j];
|
||||
|
||||
assert(m <= j);
|
||||
if (!ps->page_shift) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (cb(opaque, sps->page_shift, ps->page_shift)) {
|
||||
if (ps->page_shift >= 16) {
|
||||
ci_largepage = true;
|
||||
}
|
||||
sps->enc[m++] = *ps;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear rest of the row */
|
||||
for (j = m; j < ARRAY_SIZE(sps->enc); j++) {
|
||||
memset(&sps->enc[j], 0, sizeof(sps->enc[j]));
|
||||
}
|
||||
|
||||
if (m) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the rest of the table */
|
||||
for (i = n; i < ARRAY_SIZE(opts->sps); i++) {
|
||||
memset(&opts->sps[i], 0, sizeof(opts->sps[i]));
|
||||
}
|
||||
|
||||
if (!ci_largepage) {
|
||||
opts->flags &= ~PPC_HASH64_CI_LARGEPAGE;
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_hpt_maxpagesize_cpu_apply(SpaprMachineState *spapr,
|
||||
PowerPCCPU *cpu,
|
||||
uint8_t val, Error **errp)
|
||||
|
||||
+38
-598
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -582,6 +582,12 @@ typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, SpaprMachineState *sm,
|
||||
void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
|
||||
target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
|
||||
target_ulong *args);
|
||||
target_ulong softmmu_resize_hpt_prepare(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
||||
target_ulong shift);
|
||||
target_ulong softmmu_resize_hpt_commit(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
||||
target_ulong flags, target_ulong shift);
|
||||
bool is_ram_address(SpaprMachineState *spapr, hwaddr addr);
|
||||
void push_sregs_to_kvm_pr(SpaprMachineState *spapr);
|
||||
|
||||
/* Virtual Processor Area structure constants */
|
||||
#define VPA_MIN_SIZE 640
|
||||
@@ -821,6 +827,7 @@ void spapr_dt_events(SpaprMachineState *sm, void *fdt);
|
||||
void close_htab_fd(SpaprMachineState *spapr);
|
||||
void spapr_setup_hpt(SpaprMachineState *spapr);
|
||||
void spapr_free_hpt(SpaprMachineState *spapr);
|
||||
void spapr_check_mmu_mode(bool guest_radix);
|
||||
SpaprTceTable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn);
|
||||
void spapr_tce_table_enable(SpaprTceTable *tcet,
|
||||
uint32_t page_shift, uint64_t bus_offset,
|
||||
|
||||
@@ -423,12 +423,6 @@ void cpu_loop(CPUPPCState *env)
|
||||
cpu_abort(cs, "Maintenance exception while in user mode. "
|
||||
"Aborting\n");
|
||||
break;
|
||||
case POWERPC_EXCP_STOP: /* stop translation */
|
||||
/* We did invalidate the instruction cache. Go on */
|
||||
break;
|
||||
case POWERPC_EXCP_BRANCH: /* branch instruction: */
|
||||
/* We just stopped because of a branch. Go on */
|
||||
break;
|
||||
case POWERPC_EXCP_SYSCALL_USER:
|
||||
/* system call in user-mode emulation */
|
||||
/* WARNING:
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "elf.h"
|
||||
#include "sysemu/dump.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
#ifdef TARGET_PPC64
|
||||
#define ELFCLASS ELFCLASS64
|
||||
@@ -176,7 +175,7 @@ static void ppc_write_elf_vmxregset(NoteFuncArg *arg, PowerPCCPU *cpu)
|
||||
vmxregset->avr[i].u64[1] = avr->u64[1];
|
||||
}
|
||||
}
|
||||
vmxregset->vscr.u32[3] = cpu_to_dump32(s, helper_mfvscr(&cpu->env));
|
||||
vmxregset->vscr.u32[3] = cpu_to_dump32(s, ppc_get_vscr(&cpu->env));
|
||||
}
|
||||
|
||||
static void ppc_write_elf_vsxregset(NoteFuncArg *arg, PowerPCCPU *cpu)
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "cpu-models.h"
|
||||
#include "cpu-qom.h"
|
||||
#include "exec/log.h"
|
||||
#include "fpu/softfloat-helpers.h"
|
||||
#include "mmu-hash64.h"
|
||||
|
||||
target_ulong cpu_read_xer(CPUPPCState *env)
|
||||
{
|
||||
@@ -45,3 +49,46 @@ void cpu_write_xer(CPUPPCState *env, target_ulong xer)
|
||||
(1ul << XER_OV) | (1ul << XER_CA) |
|
||||
(1ul << XER_OV32) | (1ul << XER_CA32));
|
||||
}
|
||||
|
||||
void ppc_store_vscr(CPUPPCState *env, uint32_t vscr)
|
||||
{
|
||||
env->vscr = vscr & ~(1u << VSCR_SAT);
|
||||
/* Which bit we set is completely arbitrary, but clear the rest. */
|
||||
env->vscr_sat.u64[0] = vscr & (1u << VSCR_SAT);
|
||||
env->vscr_sat.u64[1] = 0;
|
||||
set_flush_to_zero((vscr >> VSCR_NJ) & 1, &env->vec_status);
|
||||
}
|
||||
|
||||
uint32_t ppc_get_vscr(CPUPPCState *env)
|
||||
{
|
||||
uint32_t sat = (env->vscr_sat.u64[0] | env->vscr_sat.u64[1]) != 0;
|
||||
return env->vscr | (sat << VSCR_SAT);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
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);
|
||||
#if defined(TARGET_PPC64)
|
||||
if (mmu_is_64bit(env->mmu_model)) {
|
||||
target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
|
||||
target_ulong htabsize = value & SDR_64_HTABSIZE;
|
||||
|
||||
if (value & ~sdr_mask) {
|
||||
error_report("Invalid bits 0x"TARGET_FMT_lx" set in SDR1",
|
||||
value & ~sdr_mask);
|
||||
value &= sdr_mask;
|
||||
}
|
||||
if (htabsize > 28) {
|
||||
error_report("Invalid HTABSIZE 0x" TARGET_FMT_lx" stored in SDR1",
|
||||
htabsize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* defined(TARGET_PPC64) */
|
||||
/* FIXME: Should check for valid HTABMASK values in 32-bit case */
|
||||
env->spr[SPR_SDR1] = value;
|
||||
}
|
||||
#endif /* CONFIG_SOFTMMU */
|
||||
|
||||
+9
-4
@@ -131,11 +131,7 @@ enum {
|
||||
POWERPC_EXCP_SYSCALL_VECTORED = 102, /* scv exception */
|
||||
/* EOL */
|
||||
POWERPC_EXCP_NB = 103,
|
||||
/* QEMU exceptions: used internally during code translation */
|
||||
POWERPC_EXCP_STOP = 0x200, /* stop translation */
|
||||
POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */
|
||||
/* QEMU exceptions: special cases we want to stop translation */
|
||||
POWERPC_EXCP_SYNC = 0x202, /* context synchronizing instruction */
|
||||
POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only */
|
||||
};
|
||||
|
||||
@@ -1297,6 +1293,7 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value);
|
||||
void ppc_store_ptcr(CPUPPCState *env, target_ulong value);
|
||||
#endif /* !defined(CONFIG_USER_ONLY) */
|
||||
void ppc_store_msr(CPUPPCState *env, target_ulong value);
|
||||
void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val);
|
||||
|
||||
void ppc_cpu_list(void);
|
||||
|
||||
@@ -2641,7 +2638,15 @@ static inline ppc_avr_t *cpu_avr_ptr(CPUPPCState *env, int i)
|
||||
return (ppc_avr_t *)((uintptr_t)env + avr_full_offset(i));
|
||||
}
|
||||
|
||||
static inline bool ppc_has_spr(PowerPCCPU *cpu, int spr)
|
||||
{
|
||||
/* We can test whether the SPR is defined by checking for a valid name */
|
||||
return cpu->env.spr_cb[spr].name != NULL;
|
||||
}
|
||||
|
||||
void dump_mmu(CPUPPCState *env);
|
||||
|
||||
void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len);
|
||||
void ppc_store_vscr(CPUPPCState *env, uint32_t vscr);
|
||||
uint32_t ppc_get_vscr(CPUPPCState *env);
|
||||
#endif /* PPC_CPU_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -498,7 +498,7 @@ static int gdb_get_avr_reg(CPUPPCState *env, GByteArray *buf, int n)
|
||||
return 16;
|
||||
}
|
||||
if (n == 32) {
|
||||
gdb_get_reg32(buf, helper_mfvscr(env));
|
||||
gdb_get_reg32(buf, ppc_get_vscr(env));
|
||||
mem_buf = gdb_get_reg_ptr(buf, 4);
|
||||
ppc_maybe_bswap_register(env, mem_buf, 4);
|
||||
return 4;
|
||||
@@ -529,7 +529,7 @@ static int gdb_set_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
|
||||
}
|
||||
if (n == 32) {
|
||||
ppc_maybe_bswap_register(env, mem_buf, 4);
|
||||
helper_mtvscr(env, ldl_p(mem_buf));
|
||||
ppc_store_vscr(env, ldl_p(mem_buf));
|
||||
return 4;
|
||||
}
|
||||
if (n == 33) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
DEF_HELPER_FLAGS_3(raise_exception_err, TCG_CALL_NO_WG, void, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, void, env, i32)
|
||||
DEF_HELPER_FLAGS_3(raise_exception_err, TCG_CALL_NO_WG, noreturn, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, i32)
|
||||
DEF_HELPER_FLAGS_4(tw, TCG_CALL_NO_WG, void, env, tl, tl, i32)
|
||||
#if defined(TARGET_PPC64)
|
||||
DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32)
|
||||
|
||||
@@ -462,17 +462,12 @@ SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX)
|
||||
|
||||
void helper_mtvscr(CPUPPCState *env, uint32_t vscr)
|
||||
{
|
||||
env->vscr = vscr & ~(1u << VSCR_SAT);
|
||||
/* Which bit we set is completely arbitrary, but clear the rest. */
|
||||
env->vscr_sat.u64[0] = vscr & (1u << VSCR_SAT);
|
||||
env->vscr_sat.u64[1] = 0;
|
||||
set_flush_to_zero((vscr >> VSCR_NJ) & 1, &env->vec_status);
|
||||
ppc_store_vscr(env, vscr);
|
||||
}
|
||||
|
||||
uint32_t helper_mfvscr(CPUPPCState *env)
|
||||
{
|
||||
uint32_t sat = (env->vscr_sat.u64[0] | env->vscr_sat.u64[1]) != 0;
|
||||
return env->vscr | (sat << VSCR_SAT);
|
||||
return ppc_get_vscr(env);
|
||||
}
|
||||
|
||||
static inline void set_vscr_sat(CPUPPCState *env)
|
||||
|
||||
@@ -228,4 +228,23 @@ void destroy_ppc_opcodes(PowerPCCPU *cpu);
|
||||
void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *ppc);
|
||||
gchar *ppc_gdb_arch_name(CPUState *cs);
|
||||
|
||||
/**
|
||||
* prot_for_access_type:
|
||||
* @access_type: Access type
|
||||
*
|
||||
* Return the protection bit required for the given access type.
|
||||
*/
|
||||
static inline int prot_for_access_type(MMUAccessType access_type)
|
||||
{
|
||||
switch (access_type) {
|
||||
case MMU_INST_FETCH:
|
||||
return PAGE_EXEC;
|
||||
case MMU_DATA_LOAD:
|
||||
return PAGE_READ;
|
||||
case MMU_DATA_STORE:
|
||||
return PAGE_WRITE;
|
||||
}
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
#endif /* PPC_INTERNAL_H */
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
static void post_load_update_msr(CPUPPCState *env)
|
||||
{
|
||||
@@ -107,7 +106,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
|
||||
ppc_store_sdr1(env, sdr1);
|
||||
}
|
||||
qemu_get_be32s(f, &vscr);
|
||||
helper_mtvscr(env, vscr);
|
||||
ppc_store_vscr(env, vscr);
|
||||
qemu_get_be64s(f, &env->spe_acc);
|
||||
qemu_get_be32s(f, &env->spe_fscr);
|
||||
qemu_get_betls(f, &env->msr_mask);
|
||||
@@ -456,7 +455,7 @@ static int get_vscr(QEMUFile *f, void *opaque, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
PowerPCCPU *cpu = opaque;
|
||||
helper_mtvscr(&cpu->env, qemu_get_be32(f));
|
||||
ppc_store_vscr(&cpu->env, qemu_get_be32(f));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -464,7 +463,7 @@ static int put_vscr(QEMUFile *f, void *opaque, size_t size,
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
PowerPCCPU *cpu = opaque;
|
||||
qemu_put_be32(f, helper_mfvscr(&cpu->env));
|
||||
qemu_put_be32(f, ppc_get_vscr(&cpu->env));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ ppc_ss = ss.source_set()
|
||||
ppc_ss.add(files(
|
||||
'cpu-models.c',
|
||||
'cpu.c',
|
||||
'cpu_init.c',
|
||||
'dfp_helper.c',
|
||||
'excp_helper.c',
|
||||
'fpu_helper.c',
|
||||
|
||||
@@ -261,6 +261,16 @@ void ppc_store_msr(CPUPPCState *env, target_ulong value)
|
||||
hreg_store_msr(env, value, 0);
|
||||
}
|
||||
|
||||
void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
|
||||
{
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
env->spr[SPR_LPCR] = val & pcc->lpcr_mask;
|
||||
/* The gtse bit affects hflags */
|
||||
hreg_compute_hflags(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* This code is lifted from MacOnLinux. It is called whenever THRM1,2
|
||||
* or 3 is read an fixes up the values in such a way that will make
|
||||
|
||||
+33
-26
@@ -24,6 +24,7 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "internal.h"
|
||||
#include "mmu-hash32.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
@@ -152,16 +153,17 @@ static int hash32_bat_601_prot(PowerPCCPU *cpu,
|
||||
return ppc_hash32_pp_prot(key, pp, 0);
|
||||
}
|
||||
|
||||
static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea, int rwx,
|
||||
int *prot)
|
||||
static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
|
||||
MMUAccessType access_type, int *prot)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
target_ulong *BATlt, *BATut;
|
||||
bool ifetch = access_type == MMU_INST_FETCH;
|
||||
int i;
|
||||
|
||||
LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
|
||||
rwx == 2 ? 'I' : 'D', ea);
|
||||
if (rwx == 2) {
|
||||
ifetch ? 'I' : 'D', ea);
|
||||
if (ifetch) {
|
||||
BATlt = env->IBAT[1];
|
||||
BATut = env->IBAT[0];
|
||||
} else {
|
||||
@@ -180,7 +182,7 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea, int rwx,
|
||||
}
|
||||
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
|
||||
" BATl " TARGET_FMT_lx "\n", __func__,
|
||||
type == ACCESS_CODE ? 'I' : 'D', i, ea, batu, batl);
|
||||
ifetch ? 'I' : 'D', i, ea, batu, batl);
|
||||
|
||||
if (mask && ((ea & mask) == (batu & BATU32_BEPI))) {
|
||||
hwaddr raddr = (batl & mask) | (ea & ~mask);
|
||||
@@ -208,7 +210,7 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea, int rwx,
|
||||
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
|
||||
" BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
|
||||
TARGET_FMT_lx " " TARGET_FMT_lx "\n",
|
||||
__func__, type == ACCESS_CODE ? 'I' : 'D', i, ea,
|
||||
__func__, ifetch ? 'I' : 'D', i, ea,
|
||||
*BATu, *BATl, BEPIu, BEPIl, bl);
|
||||
}
|
||||
}
|
||||
@@ -218,7 +220,8 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea, int rwx,
|
||||
}
|
||||
|
||||
static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
|
||||
target_ulong eaddr, int rwx,
|
||||
target_ulong eaddr,
|
||||
MMUAccessType access_type,
|
||||
hwaddr *raddr, int *prot)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
@@ -239,7 +242,7 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rwx == 2) {
|
||||
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;
|
||||
@@ -260,7 +263,7 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
|
||||
/* lwarx, ldarx or srwcx. */
|
||||
env->error_code = 0;
|
||||
env->spr[SPR_DAR] = eaddr;
|
||||
if (rwx == 1) {
|
||||
if (access_type == MMU_DATA_STORE) {
|
||||
env->spr[SPR_DSISR] = 0x06000000;
|
||||
} else {
|
||||
env->spr[SPR_DSISR] = 0x04000000;
|
||||
@@ -280,7 +283,7 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
|
||||
cs->exception_index = POWERPC_EXCP_DSI;
|
||||
env->error_code = 0;
|
||||
env->spr[SPR_DAR] = eaddr;
|
||||
if (rwx == 1) {
|
||||
if (access_type == MMU_DATA_STORE) {
|
||||
env->spr[SPR_DSISR] = 0x06100000;
|
||||
} else {
|
||||
env->spr[SPR_DSISR] = 0x04100000;
|
||||
@@ -290,14 +293,15 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
|
||||
cpu_abort(cs, "ERROR: instruction should not need "
|
||||
"address translation\n");
|
||||
}
|
||||
if ((rwx == 1 || key != 1) && (rwx == 0 || key != 0)) {
|
||||
if ((access_type == MMU_DATA_STORE || key != 1) &&
|
||||
(access_type == MMU_DATA_LOAD || key != 0)) {
|
||||
*raddr = eaddr;
|
||||
return 0;
|
||||
} else {
|
||||
cs->exception_index = POWERPC_EXCP_DSI;
|
||||
env->error_code = 0;
|
||||
env->spr[SPR_DAR] = eaddr;
|
||||
if (rwx == 1) {
|
||||
if (access_type == MMU_DATA_STORE) {
|
||||
env->spr[SPR_DSISR] = 0x0a000000;
|
||||
} else {
|
||||
env->spr[SPR_DSISR] = 0x08000000;
|
||||
@@ -421,13 +425,16 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
|
||||
hwaddr pte_offset;
|
||||
ppc_hash_pte32_t pte;
|
||||
int prot;
|
||||
const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
|
||||
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);
|
||||
|
||||
/* 1. Handle real mode accesses */
|
||||
if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
|
||||
if (access_type == MMU_INST_FETCH ? !msr_ir : !msr_dr) {
|
||||
/* Translation is off */
|
||||
raddr = eaddr;
|
||||
tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
|
||||
@@ -438,17 +445,17 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
|
||||
|
||||
/* 2. Check Block Address Translation entries (BATs) */
|
||||
if (env->nb_BATs != 0) {
|
||||
raddr = ppc_hash32_bat_lookup(cpu, eaddr, rwx, &prot);
|
||||
raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, &prot);
|
||||
if (raddr != -1) {
|
||||
if (need_prot[rwx] & ~prot) {
|
||||
if (rwx == 2) {
|
||||
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 (rwx == 1) {
|
||||
if (access_type == MMU_DATA_STORE) {
|
||||
env->spr[SPR_DSISR] = 0x0a000000;
|
||||
} else {
|
||||
env->spr[SPR_DSISR] = 0x08000000;
|
||||
@@ -469,7 +476,7 @@ 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, rwx,
|
||||
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,
|
||||
@@ -481,7 +488,7 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
|
||||
}
|
||||
|
||||
/* 5. Check for segment level no-execute violation */
|
||||
if ((rwx == 2) && (sr & SR32_NX)) {
|
||||
if (access_type == MMU_INST_FETCH && (sr & SR32_NX)) {
|
||||
cs->exception_index = POWERPC_EXCP_ISI;
|
||||
env->error_code = 0x10000000;
|
||||
return 1;
|
||||
@@ -490,14 +497,14 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
|
||||
/* 6. Locate the PTE in the hash table */
|
||||
pte_offset = ppc_hash32_htab_lookup(cpu, sr, eaddr, &pte);
|
||||
if (pte_offset == -1) {
|
||||
if (rwx == 2) {
|
||||
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 (rwx == 1) {
|
||||
if (access_type == MMU_DATA_STORE) {
|
||||
env->spr[SPR_DSISR] = 0x42000000;
|
||||
} else {
|
||||
env->spr[SPR_DSISR] = 0x40000000;
|
||||
@@ -513,17 +520,17 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
|
||||
|
||||
prot = ppc_hash32_pte_prot(cpu, sr, pte);
|
||||
|
||||
if (need_prot[rwx] & ~prot) {
|
||||
if (need_prot & ~prot) {
|
||||
/* Access right violation */
|
||||
qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
|
||||
if (rwx == 2) {
|
||||
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 (rwx == 1) {
|
||||
if (access_type == MMU_DATA_STORE) {
|
||||
env->spr[SPR_DSISR] = 0x0a000000;
|
||||
} else {
|
||||
env->spr[SPR_DSISR] = 0x08000000;
|
||||
@@ -540,7 +547,7 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
|
||||
ppc_hash32_set_r(cpu, pte_offset, pte.pte1);
|
||||
}
|
||||
if (!(pte.pte1 & HPTE32_R_C)) {
|
||||
if (rwx == 1) {
|
||||
if (access_type == MMU_DATA_STORE) {
|
||||
ppc_hash32_set_c(cpu, pte_offset, pte.pte1);
|
||||
} else {
|
||||
/*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user