mmu-hash*: Add header file for definitions
Currently cpu.h contains a number of definitions relating to the 64-bit hash MMU. Some are used in the MMU emulation code, but some are only used in the spapr MMU management hcall implementations. This patch moves these definitions (except for a few that are needed more widely) into mmu-hash64.h header, shared between the MMU emulation code and the spapr hcall code. The MMU emulation code is also updated to actually use a number of those definitions in place of hard coded constants. Similarly, we add new analogous definitions to mmu-hash32.h and use those in place of many hard-coded constants in mmu-hash32.c Signed-off-by: David Gibson <david@gibson.dropbear.id.au> [agraf: fix 32-bit hosts] Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
5dc68eb0e4
commit
d5aea6f367
|
@ -3,39 +3,7 @@
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "helper_regs.h"
|
#include "helper_regs.h"
|
||||||
#include "hw/spapr.h"
|
#include "hw/spapr.h"
|
||||||
|
#include "mmu-hash64.h"
|
||||||
#define HPTES_PER_GROUP 8
|
|
||||||
|
|
||||||
#define HPTE_V_SSIZE_SHIFT 62
|
|
||||||
#define HPTE_V_AVPN_SHIFT 7
|
|
||||||
#define HPTE_V_AVPN 0x3fffffffffffff80ULL
|
|
||||||
#define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
|
|
||||||
#define HPTE_V_COMPARE(x, y) (!(((x) ^ (y)) & 0xffffffffffffff80UL))
|
|
||||||
#define HPTE_V_BOLTED 0x0000000000000010ULL
|
|
||||||
#define HPTE_V_LOCK 0x0000000000000008ULL
|
|
||||||
#define HPTE_V_LARGE 0x0000000000000004ULL
|
|
||||||
#define HPTE_V_SECONDARY 0x0000000000000002ULL
|
|
||||||
#define HPTE_V_VALID 0x0000000000000001ULL
|
|
||||||
|
|
||||||
#define HPTE_R_PP0 0x8000000000000000ULL
|
|
||||||
#define HPTE_R_TS 0x4000000000000000ULL
|
|
||||||
#define HPTE_R_KEY_HI 0x3000000000000000ULL
|
|
||||||
#define HPTE_R_RPN_SHIFT 12
|
|
||||||
#define HPTE_R_RPN 0x3ffffffffffff000ULL
|
|
||||||
#define HPTE_R_FLAGS 0x00000000000003ffULL
|
|
||||||
#define HPTE_R_PP 0x0000000000000003ULL
|
|
||||||
#define HPTE_R_N 0x0000000000000004ULL
|
|
||||||
#define HPTE_R_G 0x0000000000000008ULL
|
|
||||||
#define HPTE_R_M 0x0000000000000010ULL
|
|
||||||
#define HPTE_R_I 0x0000000000000020ULL
|
|
||||||
#define HPTE_R_W 0x0000000000000040ULL
|
|
||||||
#define HPTE_R_WIMG 0x0000000000000078ULL
|
|
||||||
#define HPTE_R_C 0x0000000000000080ULL
|
|
||||||
#define HPTE_R_R 0x0000000000000100ULL
|
|
||||||
#define HPTE_R_KEY_LO 0x0000000000000e00ULL
|
|
||||||
|
|
||||||
#define HPTE_V_1TB_SEG 0x4000000000000000ULL
|
|
||||||
#define HPTE_V_VRMA_MASK 0x4001ffffff000000ULL
|
|
||||||
|
|
||||||
static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
|
static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
|
||||||
target_ulong pte_index)
|
target_ulong pte_index)
|
||||||
|
@ -44,17 +12,17 @@ static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
|
||||||
|
|
||||||
rb = (v & ~0x7fULL) << 16; /* AVA field */
|
rb = (v & ~0x7fULL) << 16; /* AVA field */
|
||||||
va_low = pte_index >> 3;
|
va_low = pte_index >> 3;
|
||||||
if (v & HPTE_V_SECONDARY) {
|
if (v & HPTE64_V_SECONDARY) {
|
||||||
va_low = ~va_low;
|
va_low = ~va_low;
|
||||||
}
|
}
|
||||||
/* xor vsid from AVA */
|
/* xor vsid from AVA */
|
||||||
if (!(v & HPTE_V_1TB_SEG)) {
|
if (!(v & HPTE64_V_1TB_SEG)) {
|
||||||
va_low ^= v >> 12;
|
va_low ^= v >> 12;
|
||||||
} else {
|
} else {
|
||||||
va_low ^= v >> 24;
|
va_low ^= v >> 24;
|
||||||
}
|
}
|
||||||
va_low &= 0x7ff;
|
va_low &= 0x7ff;
|
||||||
if (v & HPTE_V_LARGE) {
|
if (v & HPTE64_V_LARGE) {
|
||||||
rb |= 1; /* L field */
|
rb |= 1; /* L field */
|
||||||
#if 0 /* Disable that P7 specific bit for now */
|
#if 0 /* Disable that P7 specific bit for now */
|
||||||
if (r & 0xff000) {
|
if (r & 0xff000) {
|
||||||
|
@ -87,7 +55,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||||
uint8_t *hpte;
|
uint8_t *hpte;
|
||||||
|
|
||||||
/* only handle 4k and 16M pages for now */
|
/* only handle 4k and 16M pages for now */
|
||||||
if (pteh & HPTE_V_LARGE) {
|
if (pteh & HPTE64_V_LARGE) {
|
||||||
#if 0 /* We don't support 64k pages yet */
|
#if 0 /* We don't support 64k pages yet */
|
||||||
if ((ptel & 0xf000) == 0x1000) {
|
if ((ptel & 0xf000) == 0x1000) {
|
||||||
/* 64k page */
|
/* 64k page */
|
||||||
|
@ -105,11 +73,11 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
raddr = (ptel & HPTE_R_RPN) & ~((1ULL << page_shift) - 1);
|
raddr = (ptel & HPTE64_R_RPN) & ~((1ULL << page_shift) - 1);
|
||||||
|
|
||||||
if (raddr < spapr->ram_limit) {
|
if (raddr < spapr->ram_limit) {
|
||||||
/* Regular RAM - should have WIMG=0010 */
|
/* Regular RAM - should have WIMG=0010 */
|
||||||
if ((ptel & HPTE_R_WIMG) != HPTE_R_M) {
|
if ((ptel & HPTE64_R_WIMG) != HPTE64_R_M) {
|
||||||
return H_PARAMETER;
|
return H_PARAMETER;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -117,7 +85,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||||
/* FIXME: What WIMG combinations could be sensible for IO?
|
/* FIXME: What WIMG combinations could be sensible for IO?
|
||||||
* For now we allow WIMG=010x, but are there others? */
|
* For now we allow WIMG=010x, but are there others? */
|
||||||
/* FIXME: Should we check against registered IO addresses? */
|
/* FIXME: Should we check against registered IO addresses? */
|
||||||
if ((ptel & (HPTE_R_W | HPTE_R_I | HPTE_R_M)) != HPTE_R_I) {
|
if ((ptel & (HPTE64_R_W | HPTE64_R_I | HPTE64_R_M)) != HPTE64_R_I) {
|
||||||
return H_PARAMETER;
|
return H_PARAMETER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +102,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||||
if (i == 8) {
|
if (i == 8) {
|
||||||
return H_PTEG_FULL;
|
return H_PTEG_FULL;
|
||||||
}
|
}
|
||||||
if ((ldq_p(hpte) & HPTE_V_VALID) == 0) {
|
if ((ldq_p(hpte) & HPTE64_V_VALID) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
hpte += HASH_PTE_SIZE_64;
|
hpte += HASH_PTE_SIZE_64;
|
||||||
|
@ -142,7 +110,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||||
} else {
|
} else {
|
||||||
i = 0;
|
i = 0;
|
||||||
hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
|
hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
|
||||||
if (ldq_p(hpte) & HPTE_V_VALID) {
|
if (ldq_p(hpte) & HPTE64_V_VALID) {
|
||||||
return H_PTEG_FULL;
|
return H_PTEG_FULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,7 +146,7 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
|
||||||
v = ldq_p(hpte);
|
v = ldq_p(hpte);
|
||||||
r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
|
r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
|
||||||
|
|
||||||
if ((v & HPTE_V_VALID) == 0 ||
|
if ((v & HPTE64_V_VALID) == 0 ||
|
||||||
((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
|
((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
|
||||||
((flags & H_ANDCOND) && (v & avpn) != 0)) {
|
((flags & H_ANDCOND) && (v & avpn) != 0)) {
|
||||||
return REMOVE_NOT_FOUND;
|
return REMOVE_NOT_FOUND;
|
||||||
|
@ -271,7 +239,7 @@ static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||||
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case REMOVE_SUCCESS:
|
case REMOVE_SUCCESS:
|
||||||
*tsh |= (r & (HPTE_R_C | HPTE_R_R)) << 43;
|
*tsh |= (r & (HPTE64_R_C | HPTE64_R_R)) << 43;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REMOVE_PARM:
|
case REMOVE_PARM:
|
||||||
|
@ -304,18 +272,18 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||||
v = ldq_p(hpte);
|
v = ldq_p(hpte);
|
||||||
r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
|
r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
|
||||||
|
|
||||||
if ((v & HPTE_V_VALID) == 0 ||
|
if ((v & HPTE64_V_VALID) == 0 ||
|
||||||
((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
|
((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
|
||||||
return H_NOT_FOUND;
|
return H_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
r &= ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N |
|
r &= ~(HPTE64_R_PP0 | HPTE64_R_PP | HPTE64_R_N |
|
||||||
HPTE_R_KEY_HI | HPTE_R_KEY_LO);
|
HPTE64_R_KEY_HI | HPTE64_R_KEY_LO);
|
||||||
r |= (flags << 55) & HPTE_R_PP0;
|
r |= (flags << 55) & HPTE64_R_PP0;
|
||||||
r |= (flags << 48) & HPTE_R_KEY_HI;
|
r |= (flags << 48) & HPTE64_R_KEY_HI;
|
||||||
r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
|
r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO);
|
||||||
rb = compute_tlbie_rb(v, r, pte_index);
|
rb = compute_tlbie_rb(v, r, pte_index);
|
||||||
stq_p(hpte, v & ~HPTE_V_VALID);
|
stq_p(hpte, v & ~HPTE64_V_VALID);
|
||||||
ppc_tlb_invalidate_one(env, rb);
|
ppc_tlb_invalidate_one(env, rb);
|
||||||
stq_p(hpte + (HASH_PTE_SIZE_64/2), r);
|
stq_p(hpte + (HASH_PTE_SIZE_64/2), r);
|
||||||
/* Don't need a memory barrier, due to qemu's global lock */
|
/* Don't need a memory barrier, due to qemu's global lock */
|
||||||
|
|
|
@ -394,36 +394,12 @@ union ppc_tlb_t {
|
||||||
#define SDR_64_HTABSIZE 0x000000000000001FULL
|
#define SDR_64_HTABSIZE 0x000000000000001FULL
|
||||||
#endif /* defined(TARGET_PPC64 */
|
#endif /* defined(TARGET_PPC64 */
|
||||||
|
|
||||||
#define HASH_PTE_SIZE_32 8
|
|
||||||
#define HASH_PTE_SIZE_64 16
|
|
||||||
|
|
||||||
typedef struct ppc_slb_t ppc_slb_t;
|
typedef struct ppc_slb_t ppc_slb_t;
|
||||||
struct ppc_slb_t {
|
struct ppc_slb_t {
|
||||||
uint64_t esid;
|
uint64_t esid;
|
||||||
uint64_t vsid;
|
uint64_t vsid;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Bits in the SLB ESID word */
|
|
||||||
#define SLB_ESID_ESID 0xFFFFFFFFF0000000ULL
|
|
||||||
#define SLB_ESID_V 0x0000000008000000ULL /* valid */
|
|
||||||
|
|
||||||
/* Bits in the SLB VSID word */
|
|
||||||
#define SLB_VSID_SHIFT 12
|
|
||||||
#define SLB_VSID_SHIFT_1T 24
|
|
||||||
#define SLB_VSID_SSIZE_SHIFT 62
|
|
||||||
#define SLB_VSID_B 0xc000000000000000ULL
|
|
||||||
#define SLB_VSID_B_256M 0x0000000000000000ULL
|
|
||||||
#define SLB_VSID_B_1T 0x4000000000000000ULL
|
|
||||||
#define SLB_VSID_VSID 0x3FFFFFFFFFFFF000ULL
|
|
||||||
#define SLB_VSID_PTEM (SLB_VSID_B | SLB_VSID_VSID)
|
|
||||||
#define SLB_VSID_KS 0x0000000000000800ULL
|
|
||||||
#define SLB_VSID_KP 0x0000000000000400ULL
|
|
||||||
#define SLB_VSID_N 0x0000000000000200ULL /* no-execute */
|
|
||||||
#define SLB_VSID_L 0x0000000000000100ULL
|
|
||||||
#define SLB_VSID_C 0x0000000000000080ULL /* class */
|
|
||||||
#define SLB_VSID_LP 0x0000000000000030ULL
|
|
||||||
#define SLB_VSID_ATTR 0x0000000000000FFFULL
|
|
||||||
|
|
||||||
#define SEGMENT_SHIFT_256M 28
|
#define SEGMENT_SHIFT_256M 28
|
||||||
#define SEGMENT_MASK_256M (~((1ULL << SEGMENT_SHIFT_256M) - 1))
|
#define SEGMENT_MASK_256M (~((1ULL << SEGMENT_SHIFT_256M) - 1))
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "sysemu/device_tree.h"
|
#include "sysemu/device_tree.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
#include "hw/spapr.h"
|
#include "hw/spapr.h"
|
||||||
|
#include "mmu-hash64.h"
|
||||||
|
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
#include "hw/spapr.h"
|
#include "hw/spapr.h"
|
||||||
|
|
|
@ -51,7 +51,6 @@ struct mmu_ctx_hash32 {
|
||||||
int nx; /* Non-execute area */
|
int nx; /* Non-execute area */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PTE_PTEM_MASK 0x7FFFFFBF
|
|
||||||
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
|
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
|
||||||
|
|
||||||
static int ppc_hash32_pp_check(int key, int pp, int nx)
|
static int ppc_hash32_pp_check(int key, int pp, int nx)
|
||||||
|
@ -127,13 +126,13 @@ static void hash32_bat_size_prot(CPUPPCState *env, target_ulong *blp,
|
||||||
target_ulong bl;
|
target_ulong bl;
|
||||||
int pp, valid, prot;
|
int pp, valid, prot;
|
||||||
|
|
||||||
bl = (*BATu & 0x00001FFC) << 15;
|
bl = (*BATu & BATU32_BL) << 15;
|
||||||
valid = 0;
|
valid = 0;
|
||||||
prot = 0;
|
prot = 0;
|
||||||
if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
|
if (((msr_pr == 0) && (*BATu & BATU32_VS)) ||
|
||||||
((msr_pr != 0) && (*BATu & 0x00000001))) {
|
((msr_pr != 0) && (*BATu & BATU32_VP))) {
|
||||||
valid = 1;
|
valid = 1;
|
||||||
pp = *BATl & 0x00000003;
|
pp = *BATl & BATL32_PP;
|
||||||
if (pp != 0) {
|
if (pp != 0) {
|
||||||
prot = PAGE_READ | PAGE_EXEC;
|
prot = PAGE_READ | PAGE_EXEC;
|
||||||
if (pp == 0x2) {
|
if (pp == 0x2) {
|
||||||
|
@ -153,17 +152,17 @@ static void hash32_bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
|
||||||
target_ulong bl;
|
target_ulong bl;
|
||||||
int key, pp, valid, prot;
|
int key, pp, valid, prot;
|
||||||
|
|
||||||
bl = (*BATl & 0x0000003F) << 17;
|
bl = (*BATl & BATL32_601_BL) << 17;
|
||||||
LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
|
LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
|
||||||
(uint8_t)(*BATl & 0x0000003F), bl, ~bl);
|
(uint8_t)(*BATl & BATL32_601_BL), bl, ~bl);
|
||||||
prot = 0;
|
prot = 0;
|
||||||
valid = (*BATl >> 6) & 1;
|
valid = !!(*BATl & BATL32_601_V);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
pp = *BATu & 0x00000003;
|
pp = *BATu & BATU32_601_PP;
|
||||||
if (msr_pr == 0) {
|
if (msr_pr == 0) {
|
||||||
key = (*BATu >> 3) & 1;
|
key = !!(*BATu & BATU32_601_KS);
|
||||||
} else {
|
} else {
|
||||||
key = (*BATu >> 2) & 1;
|
key = !!(*BATu & BATU32_601_KP);
|
||||||
}
|
}
|
||||||
prot = ppc_hash32_pp_check(key, pp, 0);
|
prot = ppc_hash32_pp_check(key, pp, 0);
|
||||||
}
|
}
|
||||||
|
@ -195,8 +194,8 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
|
||||||
for (i = 0; i < env->nb_BATs; i++) {
|
for (i = 0; i < env->nb_BATs; i++) {
|
||||||
BATu = &BATut[i];
|
BATu = &BATut[i];
|
||||||
BATl = &BATlt[i];
|
BATl = &BATlt[i];
|
||||||
BEPIu = *BATu & 0xF0000000;
|
BEPIu = *BATu & BATU32_BEPIU;
|
||||||
BEPIl = *BATu & 0x0FFE0000;
|
BEPIl = *BATu & BATU32_BEPIL;
|
||||||
if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
|
if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
|
||||||
hash32_bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
|
hash32_bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
|
||||||
} else {
|
} else {
|
||||||
|
@ -205,13 +204,13 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
|
||||||
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
|
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
|
||||||
" BATl " TARGET_FMT_lx "\n", __func__,
|
" BATl " TARGET_FMT_lx "\n", __func__,
|
||||||
type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
|
type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
|
||||||
if ((virtual & 0xF0000000) == BEPIu &&
|
if ((virtual & BATU32_BEPIU) == BEPIu &&
|
||||||
((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
|
((virtual & BATU32_BEPIL) & ~bl) == BEPIl) {
|
||||||
/* BAT matches */
|
/* BAT matches */
|
||||||
if (valid != 0) {
|
if (valid != 0) {
|
||||||
/* Get physical address */
|
/* Get physical address */
|
||||||
ctx->raddr = (*BATl & 0xF0000000) |
|
ctx->raddr = (*BATl & BATL32_BRPNU) |
|
||||||
((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
|
((virtual & BATU32_BEPIL & bl) | (*BATl & BATL32_BRPNL)) |
|
||||||
(virtual & 0x0001F000);
|
(virtual & 0x0001F000);
|
||||||
/* Compute access rights */
|
/* Compute access rights */
|
||||||
ctx->prot = prot;
|
ctx->prot = prot;
|
||||||
|
@ -232,8 +231,8 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
BATu = &BATut[i];
|
BATu = &BATut[i];
|
||||||
BATl = &BATlt[i];
|
BATl = &BATlt[i];
|
||||||
BEPIu = *BATu & 0xF0000000;
|
BEPIu = *BATu & BATU32_BEPIU;
|
||||||
BEPIl = *BATu & 0x0FFE0000;
|
BEPIl = *BATu & BATU32_BEPIL;
|
||||||
bl = (*BATu & 0x00001FFC) << 15;
|
bl = (*BATu & 0x00001FFC) << 15;
|
||||||
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
|
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
|
||||||
" BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
|
" BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
|
||||||
|
@ -248,28 +247,19 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline int pte_is_valid_hash32(target_ulong pte0)
|
|
||||||
{
|
|
||||||
return pte0 & 0x80000000 ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
|
static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
|
||||||
target_ulong pte1, int h, int rw, int type)
|
target_ulong pte1, int h, int rw, int type)
|
||||||
{
|
{
|
||||||
target_ulong ptem, mmask;
|
target_ulong mmask;
|
||||||
int access, ret, pteh, ptev, pp;
|
int access, ret, pp;
|
||||||
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
/* Check validity and table match */
|
/* Check validity and table match */
|
||||||
ptev = pte_is_valid_hash32(pte0);
|
if ((pte0 & HPTE32_V_VALID) && (h == !!(pte0 & HPTE32_V_SECONDARY))) {
|
||||||
pteh = (pte0 >> 6) & 1;
|
|
||||||
if (ptev && h == pteh) {
|
|
||||||
/* Check vsid & api */
|
/* Check vsid & api */
|
||||||
ptem = pte0 & PTE_PTEM_MASK;
|
|
||||||
mmask = PTE_CHECK_MASK;
|
mmask = PTE_CHECK_MASK;
|
||||||
pp = pte1 & 0x00000003;
|
pp = pte1 & HPTE32_R_PP;
|
||||||
if (ptem == ctx->ptem) {
|
if (HPTE32_V_COMPARE(pte0, ctx->ptem)) {
|
||||||
if (ctx->raddr != (hwaddr)-1ULL) {
|
if (ctx->raddr != (hwaddr)-1ULL) {
|
||||||
/* all matches should have equal RPN, WIMG & PP */
|
/* all matches should have equal RPN, WIMG & PP */
|
||||||
if ((ctx->raddr & mmask) != (pte1 & mmask)) {
|
if ((ctx->raddr & mmask) != (pte1 & mmask)) {
|
||||||
|
@ -302,15 +292,15 @@ static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong
|
||||||
int store = 0;
|
int store = 0;
|
||||||
|
|
||||||
/* Update page flags */
|
/* Update page flags */
|
||||||
if (!(*pte1p & 0x00000100)) {
|
if (!(*pte1p & HPTE32_R_R)) {
|
||||||
/* Update accessed flag */
|
/* Update accessed flag */
|
||||||
*pte1p |= 0x00000100;
|
*pte1p |= HPTE32_R_R;
|
||||||
store = 1;
|
store = 1;
|
||||||
}
|
}
|
||||||
if (!(*pte1p & 0x00000080)) {
|
if (!(*pte1p & HPTE32_R_C)) {
|
||||||
if (rw == 1 && ret == 0) {
|
if (rw == 1 && ret == 0) {
|
||||||
/* Update changed flag */
|
/* Update changed flag */
|
||||||
*pte1p |= 0x00000080;
|
*pte1p |= HPTE32_R_C;
|
||||||
store = 1;
|
store = 1;
|
||||||
} else {
|
} else {
|
||||||
/* Force page fault for first write access */
|
/* Force page fault for first write access */
|
||||||
|
@ -323,7 +313,7 @@ static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong
|
||||||
|
|
||||||
hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
|
hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
|
||||||
{
|
{
|
||||||
return (hash * HASH_PTE_SIZE_32 * 8) & env->htab_mask;
|
return (hash * HASH_PTEG_SIZE_32) & env->htab_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PTE table lookup */
|
/* PTE table lookup */
|
||||||
|
@ -337,7 +327,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h,
|
||||||
|
|
||||||
ret = -1; /* No entry found */
|
ret = -1; /* No entry found */
|
||||||
pteg_off = get_pteg_offset32(env, ctx->hash[h]);
|
pteg_off = get_pteg_offset32(env, ctx->hash[h]);
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < HPTES_PER_GROUP; i++) {
|
||||||
if (env->external_htab) {
|
if (env->external_htab) {
|
||||||
pte0 = ldl_p(env->external_htab + pteg_off + (i * 8));
|
pte0 = ldl_p(env->external_htab + pteg_off + (i * 8));
|
||||||
pte1 = ldl_p(env->external_htab + pteg_off + (i * 8) + 4);
|
pte1 = ldl_p(env->external_htab + pteg_off + (i * 8) + 4);
|
||||||
|
@ -413,11 +403,11 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
|
||||||
ctx->eaddr = eaddr;
|
ctx->eaddr = eaddr;
|
||||||
|
|
||||||
sr = env->sr[eaddr >> 28];
|
sr = env->sr[eaddr >> 28];
|
||||||
ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
|
ctx->key = (((sr & SR32_KP) && (pr != 0)) ||
|
||||||
((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
|
((sr & SR32_KS) && (pr == 0))) ? 1 : 0;
|
||||||
ds = sr & 0x80000000 ? 1 : 0;
|
ds = !!(sr & SR32_T);
|
||||||
ctx->nx = sr & 0x10000000 ? 1 : 0;
|
ctx->nx = !!(sr & SR32_NX);
|
||||||
vsid = sr & 0x00FFFFFF;
|
vsid = sr & SR32_VSID;
|
||||||
target_page_bits = TARGET_PAGE_BITS;
|
target_page_bits = TARGET_PAGE_BITS;
|
||||||
LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
|
LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
|
||||||
TARGET_FMT_lx " lr=" TARGET_FMT_lx
|
TARGET_FMT_lx " lr=" TARGET_FMT_lx
|
||||||
|
|
|
@ -8,6 +8,67 @@ hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr);
|
||||||
int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
|
int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
|
||||||
int mmu_idx);
|
int mmu_idx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Segment register definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SR32_T 0x80000000
|
||||||
|
#define SR32_KS 0x40000000
|
||||||
|
#define SR32_KP 0x20000000
|
||||||
|
#define SR32_NX 0x10000000
|
||||||
|
#define SR32_VSID 0x00ffffff
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
#define BATU32_VP 0x00000001
|
||||||
|
|
||||||
|
|
||||||
|
#define BATL32_BRPNU 0xf0000000
|
||||||
|
#define BATL32_BRPNL 0x0ffe0000
|
||||||
|
#define BATL32_BRPN 0xfffe0000
|
||||||
|
#define BATL32_WIMG 0x00000078
|
||||||
|
#define BATL32_PP 0x00000003
|
||||||
|
|
||||||
|
/* PowerPC 601 has slightly different BAT registers */
|
||||||
|
|
||||||
|
#define BATU32_601_KS 0x00000008
|
||||||
|
#define BATU32_601_KP 0x00000004
|
||||||
|
#define BATU32_601_PP 0x00000003
|
||||||
|
|
||||||
|
#define BATL32_601_V 0x00000040
|
||||||
|
#define BATL32_601_BL 0x0000003f
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hash page table definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HPTES_PER_GROUP 8
|
||||||
|
#define HASH_PTE_SIZE_32 8
|
||||||
|
#define HASH_PTEG_SIZE_32 (HASH_PTE_SIZE_32 * HPTES_PER_GROUP)
|
||||||
|
|
||||||
|
#define HPTE32_V_VALID 0x80000000
|
||||||
|
#define HPTE32_V_VSID 0x7fffff80
|
||||||
|
#define HPTE32_V_SECONDARY 0x00000040
|
||||||
|
#define HPTE32_V_API 0x0000003f
|
||||||
|
#define HPTE32_V_COMPARE(x, y) (!(((x) ^ (y)) & 0x7fffffbf))
|
||||||
|
|
||||||
|
#define HPTE32_R_RPN 0xfffff000
|
||||||
|
#define HPTE32_R_R 0x00000100
|
||||||
|
#define HPTE32_R_C 0x00000080
|
||||||
|
#define HPTE32_R_W 0x00000040
|
||||||
|
#define HPTE32_R_I 0x00000020
|
||||||
|
#define HPTE32_R_M 0x00000010
|
||||||
|
#define HPTE32_R_G 0x00000008
|
||||||
|
#define HPTE32_R_WIMG 0x00000078
|
||||||
|
#define HPTE32_R_PP 0x00000003
|
||||||
|
|
||||||
#endif /* CONFIG_USER_ONLY */
|
#endif /* CONFIG_USER_ONLY */
|
||||||
|
|
||||||
#endif /* __MMU_HASH32_H__ */
|
#endif /* __MMU_HASH32_H__ */
|
||||||
|
|
|
@ -233,7 +233,6 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb)
|
||||||
* 64-bit hash table MMU handling
|
* 64-bit hash table MMU handling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
|
|
||||||
#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
|
#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
|
||||||
|
|
||||||
static int ppc_hash64_pp_check(int key, int pp, int nx)
|
static int ppc_hash64_pp_check(int key, int pp, int nx)
|
||||||
|
@ -304,29 +303,21 @@ static int ppc_hash64_check_prot(int prot, int rw, int access_type)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int pte64_is_valid(target_ulong pte0)
|
|
||||||
{
|
|
||||||
return pte0 & 0x0000000000000001ULL ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
|
static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
|
||||||
target_ulong pte1, int h, int rw, int type)
|
target_ulong pte1, int h, int rw, int type)
|
||||||
{
|
{
|
||||||
target_ulong ptem, mmask;
|
target_ulong mmask;
|
||||||
int access, ret, pteh, ptev, pp;
|
int access, ret, pp;
|
||||||
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
/* Check validity and table match */
|
/* Check validity and table match */
|
||||||
ptev = pte64_is_valid(pte0);
|
if ((pte0 & HPTE64_V_VALID) && (h == !!(pte0 & HPTE64_V_SECONDARY))) {
|
||||||
pteh = (pte0 >> 1) & 1;
|
|
||||||
if (ptev && h == pteh) {
|
|
||||||
/* Check vsid & api */
|
/* Check vsid & api */
|
||||||
ptem = pte0 & PTE64_PTEM_MASK;
|
|
||||||
mmask = PTE64_CHECK_MASK;
|
mmask = PTE64_CHECK_MASK;
|
||||||
pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
|
pp = (pte1 & HPTE64_R_PP) | ((pte1 & HPTE64_R_PP0) >> 61);
|
||||||
ctx->nx = (pte1 >> 2) & 1; /* No execute bit */
|
/* No execute if either noexec or guarded bits set */
|
||||||
ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit */
|
ctx->nx = (pte1 & HPTE64_R_N) || (pte1 & HPTE64_R_G);
|
||||||
if (ptem == ctx->ptem) {
|
if (HPTE64_V_COMPARE(pte0, ctx->ptem)) {
|
||||||
if (ctx->raddr != (hwaddr)-1ULL) {
|
if (ctx->raddr != (hwaddr)-1ULL) {
|
||||||
/* all matches should have equal RPN, WIMG & PP */
|
/* all matches should have equal RPN, WIMG & PP */
|
||||||
if ((ctx->raddr & mmask) != (pte1 & mmask)) {
|
if ((ctx->raddr & mmask) != (pte1 & mmask)) {
|
||||||
|
@ -360,15 +351,15 @@ static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
|
||||||
int store = 0;
|
int store = 0;
|
||||||
|
|
||||||
/* Update page flags */
|
/* Update page flags */
|
||||||
if (!(*pte1p & 0x00000100)) {
|
if (!(*pte1p & HPTE64_R_R)) {
|
||||||
/* Update accessed flag */
|
/* Update accessed flag */
|
||||||
*pte1p |= 0x00000100;
|
*pte1p |= HPTE64_R_R;
|
||||||
store = 1;
|
store = 1;
|
||||||
}
|
}
|
||||||
if (!(*pte1p & 0x00000080)) {
|
if (!(*pte1p & HPTE64_R_C)) {
|
||||||
if (rw == 1 && ret == 0) {
|
if (rw == 1 && ret == 0) {
|
||||||
/* Update changed flag */
|
/* Update changed flag */
|
||||||
*pte1p |= 0x00000080;
|
*pte1p |= HPTE64_R_C;
|
||||||
store = 1;
|
store = 1;
|
||||||
} else {
|
} else {
|
||||||
/* Force page fault for first write access */
|
/* Force page fault for first write access */
|
||||||
|
@ -389,8 +380,8 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h,
|
||||||
int ret, r;
|
int ret, r;
|
||||||
|
|
||||||
ret = -1; /* No entry found */
|
ret = -1; /* No entry found */
|
||||||
pteg_off = (ctx->hash[h] * HASH_PTE_SIZE_64 * 8) & env->htab_mask;
|
pteg_off = (ctx->hash[h] * HASH_PTEG_SIZE_64) & env->htab_mask;
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < HPTES_PER_GROUP; i++) {
|
||||||
if (env->external_htab) {
|
if (env->external_htab) {
|
||||||
pte0 = ldq_p(env->external_htab + pteg_off + (i * 16));
|
pte0 = ldq_p(env->external_htab + pteg_off + (i * 16));
|
||||||
pte1 = ldq_p(env->external_htab + pteg_off + (i * 16) + 8);
|
pte1 = ldq_p(env->external_htab + pteg_off + (i * 16) + 8);
|
||||||
|
|
|
@ -11,6 +11,68 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
|
||||||
int mmu_idx);
|
int mmu_idx);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SLB definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Bits in the SLB ESID word */
|
||||||
|
#define SLB_ESID_ESID 0xFFFFFFFFF0000000ULL
|
||||||
|
#define SLB_ESID_V 0x0000000008000000ULL /* valid */
|
||||||
|
|
||||||
|
/* Bits in the SLB VSID word */
|
||||||
|
#define SLB_VSID_SHIFT 12
|
||||||
|
#define SLB_VSID_SHIFT_1T 24
|
||||||
|
#define SLB_VSID_SSIZE_SHIFT 62
|
||||||
|
#define SLB_VSID_B 0xc000000000000000ULL
|
||||||
|
#define SLB_VSID_B_256M 0x0000000000000000ULL
|
||||||
|
#define SLB_VSID_B_1T 0x4000000000000000ULL
|
||||||
|
#define SLB_VSID_VSID 0x3FFFFFFFFFFFF000ULL
|
||||||
|
#define SLB_VSID_PTEM (SLB_VSID_B | SLB_VSID_VSID)
|
||||||
|
#define SLB_VSID_KS 0x0000000000000800ULL
|
||||||
|
#define SLB_VSID_KP 0x0000000000000400ULL
|
||||||
|
#define SLB_VSID_N 0x0000000000000200ULL /* no-execute */
|
||||||
|
#define SLB_VSID_L 0x0000000000000100ULL
|
||||||
|
#define SLB_VSID_C 0x0000000000000080ULL /* class */
|
||||||
|
#define SLB_VSID_LP 0x0000000000000030ULL
|
||||||
|
#define SLB_VSID_ATTR 0x0000000000000FFFULL
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hash page table definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HPTES_PER_GROUP 8
|
||||||
|
#define HASH_PTE_SIZE_64 16
|
||||||
|
#define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP)
|
||||||
|
|
||||||
|
#define HPTE64_V_SSIZE_SHIFT 62
|
||||||
|
#define HPTE64_V_AVPN_SHIFT 7
|
||||||
|
#define HPTE64_V_AVPN 0x3fffffffffffff80ULL
|
||||||
|
#define HPTE64_V_AVPN_VAL(x) (((x) & HPTE64_V_AVPN) >> HPTE64_V_AVPN_SHIFT)
|
||||||
|
#define HPTE64_V_COMPARE(x, y) (!(((x) ^ (y)) & 0xffffffffffffff80ULL))
|
||||||
|
#define HPTE64_V_LARGE 0x0000000000000004ULL
|
||||||
|
#define HPTE64_V_SECONDARY 0x0000000000000002ULL
|
||||||
|
#define HPTE64_V_VALID 0x0000000000000001ULL
|
||||||
|
|
||||||
|
#define HPTE64_R_PP0 0x8000000000000000ULL
|
||||||
|
#define HPTE64_R_TS 0x4000000000000000ULL
|
||||||
|
#define HPTE64_R_KEY_HI 0x3000000000000000ULL
|
||||||
|
#define HPTE64_R_RPN_SHIFT 12
|
||||||
|
#define HPTE64_R_RPN 0x0ffffffffffff000ULL
|
||||||
|
#define HPTE64_R_FLAGS 0x00000000000003ffULL
|
||||||
|
#define HPTE64_R_PP 0x0000000000000003ULL
|
||||||
|
#define HPTE64_R_N 0x0000000000000004ULL
|
||||||
|
#define HPTE64_R_G 0x0000000000000008ULL
|
||||||
|
#define HPTE64_R_M 0x0000000000000010ULL
|
||||||
|
#define HPTE64_R_I 0x0000000000000020ULL
|
||||||
|
#define HPTE64_R_W 0x0000000000000040ULL
|
||||||
|
#define HPTE64_R_WIMG 0x0000000000000078ULL
|
||||||
|
#define HPTE64_R_C 0x0000000000000080ULL
|
||||||
|
#define HPTE64_R_R 0x0000000000000100ULL
|
||||||
|
#define HPTE64_R_KEY_LO 0x0000000000000e00ULL
|
||||||
|
|
||||||
|
#define HPTE64_V_1TB_SEG 0x4000000000000000ULL
|
||||||
|
#define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL
|
||||||
|
|
||||||
#endif /* CONFIG_USER_ONLY */
|
#endif /* CONFIG_USER_ONLY */
|
||||||
|
|
||||||
#endif /* !defined (__MMU_HASH64_H__) */
|
#endif /* !defined (__MMU_HASH64_H__) */
|
||||||
|
|
Loading…
Reference in a new issue