summaryrefslogtreecommitdiffstats
path: root/hw/ppc/spapr_hcall.c
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2014-02-20 18:52:24 +0100
committerAlexander Graf <agraf@suse.de>2014-03-05 03:07:02 +0100
commit7c43bca004afdb2a86c20ab3131ec1eb7a78d80d (patch)
tree307e01bd324b38976bf99cca15ea574974293c59 /hw/ppc/spapr_hcall.c
parentf3c75d42adbba553eaf218a832d4fbea32c8f7b8 (diff)
downloadhqemu-7c43bca004afdb2a86c20ab3131ec1eb7a78d80d.zip
hqemu-7c43bca004afdb2a86c20ab3131ec1eb7a78d80d.tar.gz
target-ppc: Fix page table lookup with kvm enabled
With kvm enabled, we store the hash page table information in the hypervisor. Use ioctl to read the htab contents. Without this we get the below error when trying to read the guest address (gdb) x/10 do_fork 0xc000000000098660 <do_fork>: Cannot access memory at address 0xc000000000098660 (gdb) Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> [ fixes for 32 bit build (casts!), ldq_phys() API change, Greg Kurz <gkurz@linux.vnet.ibm.com ] Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw/ppc/spapr_hcall.c')
-rw-r--r--hw/ppc/spapr_hcall.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index d19e3fc..7493302 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -61,8 +61,9 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong ptel = args[3];
target_ulong page_shift = 12;
target_ulong raddr;
- target_ulong i;
+ target_ulong index;
hwaddr hpte;
+ uint64_t token;
/* only handle 4k and 16M pages for now */
if (pteh & HPTE64_V_LARGE) {
@@ -105,30 +106,37 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
if (!valid_pte_index(env, pte_index)) {
return H_PARAMETER;
}
+
+ index = 0;
+ hpte = pte_index * HASH_PTE_SIZE_64;
if (likely((flags & H_EXACT) == 0)) {
pte_index &= ~7ULL;
- hpte = pte_index * HASH_PTE_SIZE_64;
- for (i = 0; ; ++i) {
- if (i == 8) {
+ token = ppc_hash64_start_access(cpu, pte_index);
+ do {
+ if (index == 8) {
+ ppc_hash64_stop_access(token);
return H_PTEG_FULL;
}
- if ((ppc_hash64_load_hpte0(env, hpte) & HPTE64_V_VALID) == 0) {
+ if ((ppc_hash64_load_hpte0(env, token, index) & HPTE64_V_VALID) == 0) {
break;
}
- hpte += HASH_PTE_SIZE_64;
- }
+ } while (index++);
+ ppc_hash64_stop_access(token);
} else {
- i = 0;
- hpte = pte_index * HASH_PTE_SIZE_64;
- if (ppc_hash64_load_hpte0(env, hpte) & HPTE64_V_VALID) {
+ token = ppc_hash64_start_access(cpu, pte_index);
+ if (ppc_hash64_load_hpte0(env, token, 0) & HPTE64_V_VALID) {
+ ppc_hash64_stop_access(token);
return H_PTEG_FULL;
}
+ ppc_hash64_stop_access(token);
}
+ hpte += index * HASH_PTE_SIZE_64;
+
ppc_hash64_store_hpte1(env, hpte, ptel);
/* eieio(); FIXME: need some sort of barrier for smp? */
ppc_hash64_store_hpte0(env, hpte, pteh | HPTE64_V_HPTE_DIRTY);
- args[0] = pte_index + i;
+ args[0] = pte_index + index;
return H_SUCCESS;
}
@@ -145,16 +153,17 @@ static RemoveResult remove_hpte(CPUPPCState *env, target_ulong ptex,
target_ulong *vp, target_ulong *rp)
{
hwaddr hpte;
+ uint64_t token;
target_ulong v, r, rb;
if (!valid_pte_index(env, ptex)) {
return REMOVE_PARM;
}
- hpte = ptex * HASH_PTE_SIZE_64;
-
- v = ppc_hash64_load_hpte0(env, hpte);
- r = ppc_hash64_load_hpte1(env, hpte);
+ token = ppc_hash64_start_access(ppc_env_get_cpu(env), ptex);
+ v = ppc_hash64_load_hpte0(env, token, 0);
+ r = ppc_hash64_load_hpte1(env, token, 0);
+ ppc_hash64_stop_access(token);
if ((v & HPTE64_V_VALID) == 0 ||
((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
@@ -163,6 +172,7 @@ static RemoveResult remove_hpte(CPUPPCState *env, target_ulong ptex,
}
*vp = v;
*rp = r;
+ hpte = ptex * HASH_PTE_SIZE_64;
ppc_hash64_store_hpte0(env, hpte, HPTE64_V_HPTE_DIRTY);
rb = compute_tlbie_rb(v, r, ptex);
ppc_tlb_invalidate_one(env, rb);
@@ -271,16 +281,17 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong pte_index = args[1];
target_ulong avpn = args[2];
hwaddr hpte;
+ uint64_t token;
target_ulong v, r, rb;
if (!valid_pte_index(env, pte_index)) {
return H_PARAMETER;
}
- hpte = pte_index * HASH_PTE_SIZE_64;
-
- v = ppc_hash64_load_hpte0(env, hpte);
- r = ppc_hash64_load_hpte1(env, hpte);
+ token = ppc_hash64_start_access(cpu, pte_index);
+ v = ppc_hash64_load_hpte0(env, token, 0);
+ r = ppc_hash64_load_hpte1(env, token, 0);
+ ppc_hash64_stop_access(token);
if ((v & HPTE64_V_VALID) == 0 ||
((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
@@ -293,6 +304,7 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
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);
+ hpte = pte_index * HASH_PTE_SIZE_64;
ppc_hash64_store_hpte0(env, hpte, (v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY);
ppc_tlb_invalidate_one(env, rb);
ppc_hash64_store_hpte1(env, hpte, r);
OpenPOWER on IntegriCloud