aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2016-01-15 16:12:09 +1100
committerDavid Gibson <david@gibson.dropbear.id.au>2016-01-30 23:49:27 +1100
commit61a36c9b5a12889994e6c45f4a175efcd63936db (patch)
treefd7f7c170caf817749400c3ba80bb68b7320941e /hw/ppc
parent4693364f31016cc08d79d1673c3f735a4f95fd89 (diff)
downloadqemu-61a36c9b5a12889994e6c45f4a175efcd63936db.zip
qemu-61a36c9b5a12889994e6c45f4a175efcd63936db.tar.gz
qemu-61a36c9b5a12889994e6c45f4a175efcd63936db.tar.bz2
target-ppc: Add new TLB invalidate by HPTE call for hash64 MMUs
When HPTEs are removed or modified by hypercalls on spapr, we need to invalidate the relevant pages in the qemu TLB. Currently we do that by doing some complicated calculations to work out the right encoding for the tlbie instruction, then passing that to ppc_tlb_invalidate_one()... which totally ignores the argument and flushes the whole tlb. Avoid that by adding a new flush-by-hpte helper in mmu-hash64.c. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Reviewed-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw/ppc')
-rw-r--r--hw/ppc/spapr_hcall.c46
1 files changed, 4 insertions, 42 deletions
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index a53bd2f..0a8378c 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -38,42 +38,6 @@ static void set_spr(CPUState *cs, int spr, target_ulong value,
run_on_cpu(cs, do_spr_sync, &s);
}
-static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
- target_ulong pte_index)
-{
- target_ulong rb, va_low;
-
- rb = (v & ~0x7fULL) << 16; /* AVA field */
- va_low = pte_index >> 3;
- if (v & HPTE64_V_SECONDARY) {
- va_low = ~va_low;
- }
- /* xor vsid from AVA */
- if (!(v & HPTE64_V_1TB_SEG)) {
- va_low ^= v >> 12;
- } else {
- va_low ^= v >> 24;
- }
- va_low &= 0x7ff;
- if (v & HPTE64_V_LARGE) {
- rb |= 1; /* L field */
-#if 0 /* Disable that P7 specific bit for now */
- if (r & 0xff000) {
- /* non-16MB large page, must be 64k */
- /* (masks depend on page size) */
- rb |= 0x1000; /* page encoding in LP field */
- rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
- rb |= (va_low & 0xfe); /* AVAL field */
- }
-#endif
- } else {
- /* 4kB page */
- rb |= (va_low & 0x7ff) << 12; /* remaining 11b of AVA */
- }
- rb |= (v >> 54) & 0x300; /* B field */
- return rb;
-}
-
static inline bool valid_pte_index(CPUPPCState *env, target_ulong pte_index)
{
/*
@@ -199,7 +163,7 @@ static RemoveResult remove_hpte(PowerPCCPU *cpu, target_ulong ptex,
{
CPUPPCState *env = &cpu->env;
uint64_t token;
- target_ulong v, r, rb;
+ target_ulong v, r;
if (!valid_pte_index(env, ptex)) {
return REMOVE_PARM;
@@ -218,8 +182,7 @@ static RemoveResult remove_hpte(PowerPCCPU *cpu, target_ulong ptex,
*vp = v;
*rp = r;
ppc_hash64_store_hpte(cpu, ptex, HPTE64_V_HPTE_DIRTY, 0);
- rb = compute_tlbie_rb(v, r, ptex);
- ppc_tlb_invalidate_one(env, rb);
+ ppc_hash64_tlb_flush_hpte(cpu, ptex, v, r);
return REMOVE_SUCCESS;
}
@@ -323,7 +286,7 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong pte_index = args[1];
target_ulong avpn = args[2];
uint64_t token;
- target_ulong v, r, rb;
+ target_ulong v, r;
if (!valid_pte_index(env, pte_index)) {
return H_PARAMETER;
@@ -344,10 +307,9 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPRMachineState *spapr,
r |= (flags << 55) & HPTE64_R_PP0;
r |= (flags << 48) & HPTE64_R_KEY_HI;
r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO);
- rb = compute_tlbie_rb(v, r, pte_index);
ppc_hash64_store_hpte(cpu, pte_index,
(v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY, 0);
- ppc_tlb_invalidate_one(env, rb);
+ ppc_hash64_tlb_flush_hpte(cpu, pte_index, v, r);
/* Don't need a memory barrier, due to qemu's global lock */
ppc_hash64_store_hpte(cpu, pte_index, v | HPTE64_V_HPTE_DIRTY, r);
return H_SUCCESS;