aboutsummaryrefslogtreecommitdiff
path: root/hw/spapr_hcall.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/spapr_hcall.c')
-rw-r--r--hw/spapr_hcall.c119
1 files changed, 44 insertions, 75 deletions
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index a5990a9..63cadb8 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -1,6 +1,5 @@
#include "sysemu.h"
#include "cpu.h"
-#include "dyngen-exec.h"
#include "qemu-char.h"
#include "sysemu.h"
#include "qemu-char.h"
@@ -40,22 +39,6 @@
#define HPTE_V_1TB_SEG 0x4000000000000000ULL
#define HPTE_V_VRMA_MASK 0x4001ffffff000000ULL
-#define HPTE_V_HVLOCK 0x40ULL
-
-static inline int lock_hpte(void *hpte, target_ulong bits)
-{
- uint64_t pteh;
-
- pteh = ldq_p(hpte);
-
- /* We're protected by qemu's global lock here */
- if (pteh & bits) {
- return 0;
- }
- stq_p(hpte, pteh | HPTE_V_HVLOCK);
- return 1;
-}
-
static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
target_ulong pte_index)
{
@@ -92,9 +75,10 @@ static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
return rb;
}
-static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
+ CPUPPCState *env = &cpu->env;
target_ulong flags = args[0];
target_ulong pte_index = args[1];
target_ulong pteh = args[2];
@@ -152,8 +136,7 @@ static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr,
if (i == 8) {
return H_PTEG_FULL;
}
- if (((ldq_p(hpte) & HPTE_V_VALID) == 0) &&
- lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID)) {
+ if ((ldq_p(hpte) & HPTE_V_VALID) == 0) {
break;
}
hpte += HASH_PTE_SIZE_64;
@@ -161,7 +144,7 @@ static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr,
} else {
i = 0;
hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
- if (!lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID)) {
+ if (ldq_p(hpte) & HPTE_V_VALID) {
return H_PTEG_FULL;
}
}
@@ -169,7 +152,6 @@ static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr,
/* eieio(); FIXME: need some sort of barrier for smp? */
stq_p(hpte, pteh);
- assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
args[0] = pte_index + i;
return H_SUCCESS;
}
@@ -194,11 +176,6 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
}
hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64);
- while (!lock_hpte(hpte, HPTE_V_HVLOCK)) {
- /* We have no real concurrency in qemu soft-emulation, so we
- * will never actually have a contested lock */
- assert(0);
- }
v = ldq_p(hpte);
r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
@@ -206,22 +183,20 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
if ((v & HPTE_V_VALID) == 0 ||
((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
((flags & H_ANDCOND) && (v & avpn) != 0)) {
- stq_p(hpte, v & ~HPTE_V_HVLOCK);
- assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
return REMOVE_NOT_FOUND;
}
- *vp = v & ~HPTE_V_HVLOCK;
+ *vp = v;
*rp = r;
stq_p(hpte, 0);
rb = compute_tlbie_rb(v, r, ptex);
ppc_tlb_invalidate_one(env, rb);
- assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
return REMOVE_SUCCESS;
}
-static target_ulong h_remove(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
+ CPUPPCState *env = &cpu->env;
target_ulong flags = args[0];
target_ulong pte_index = args[1];
target_ulong avpn = args[2];
@@ -265,9 +240,10 @@ static target_ulong h_remove(CPUPPCState *env, sPAPREnvironment *spapr,
#define H_BULK_REMOVE_MAX_BATCH 4
-static target_ulong h_bulk_remove(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
+ CPUPPCState *env = &cpu->env;
int i;
for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
@@ -311,9 +287,10 @@ static target_ulong h_bulk_remove(CPUPPCState *env, sPAPREnvironment *spapr,
return H_SUCCESS;
}
-static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
+ CPUPPCState *env = &cpu->env;
target_ulong flags = args[0];
target_ulong pte_index = args[1];
target_ulong avpn = args[2];
@@ -325,19 +302,12 @@ static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr,
}
hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
- while (!lock_hpte(hpte, HPTE_V_HVLOCK)) {
- /* We have no real concurrency in qemu soft-emulation, so we
- * will never actually have a contested lock */
- assert(0);
- }
v = ldq_p(hpte);
r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
if ((v & HPTE_V_VALID) == 0 ||
((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
- stq_p(hpte, v & ~HPTE_V_HVLOCK);
- assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
return H_NOT_FOUND;
}
@@ -351,12 +321,11 @@ static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr,
ppc_tlb_invalidate_one(env, rb);
stq_p(hpte + (HASH_PTE_SIZE_64/2), r);
/* Don't need a memory barrier, due to qemu's global lock */
- stq_p(hpte, v & ~HPTE_V_HVLOCK);
- assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
+ stq_p(hpte, v);
return H_SUCCESS;
}
-static target_ulong h_set_dabr(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
/* FIXME: actually implement this */
@@ -401,26 +370,26 @@ static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa)
return H_PARAMETER;
}
- env->vpa = vpa;
+ env->vpa_addr = vpa;
- tmp = ldub_phys(env->vpa + VPA_SHARED_PROC_OFFSET);
+ tmp = ldub_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET);
tmp |= VPA_SHARED_PROC_VAL;
- stb_phys(env->vpa + VPA_SHARED_PROC_OFFSET, tmp);
+ stb_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET, tmp);
return H_SUCCESS;
}
static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa)
{
- if (env->slb_shadow) {
+ if (env->slb_shadow_addr) {
return H_RESOURCE;
}
- if (env->dispatch_trace_log) {
+ if (env->dtl_addr) {
return H_RESOURCE;
}
- env->vpa = 0;
+ env->vpa_addr = 0;
return H_SUCCESS;
}
@@ -442,18 +411,20 @@ static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr)
return H_PARAMETER;
}
- if (!env->vpa) {
+ if (!env->vpa_addr) {
return H_RESOURCE;
}
- env->slb_shadow = addr;
+ env->slb_shadow_addr = addr;
+ env->slb_shadow_size = size;
return H_SUCCESS;
}
static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr)
{
- env->slb_shadow = 0;
+ env->slb_shadow_addr = 0;
+ env->slb_shadow_size = 0;
return H_SUCCESS;
}
@@ -472,11 +443,11 @@ static target_ulong register_dtl(CPUPPCState *env, target_ulong addr)
return H_PARAMETER;
}
- if (!env->vpa) {
+ if (!env->vpa_addr) {
return H_RESOURCE;
}
- env->dispatch_trace_log = addr;
+ env->dtl_addr = addr;
env->dtl_size = size;
return H_SUCCESS;
@@ -484,13 +455,13 @@ static target_ulong register_dtl(CPUPPCState *env, target_ulong addr)
static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr)
{
- env->dispatch_trace_log = 0;
+ env->dtl_addr = 0;
env->dtl_size = 0;
return H_SUCCESS;
}
-static target_ulong h_register_vpa(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong flags = args[0];
@@ -538,18 +509,22 @@ static target_ulong h_register_vpa(CPUPPCState *env, sPAPREnvironment *spapr,
return ret;
}
-static target_ulong h_cede(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
+ CPUPPCState *env = &cpu->env;
+
env->msr |= (1ULL << MSR_EE);
hreg_compute_hflags(env);
- if (!cpu_has_work(env)) {
+ if (!cpu_has_work(CPU(cpu))) {
env->halted = 1;
+ env->exception_index = EXCP_HLT;
+ env->exit_request = 1;
}
return H_SUCCESS;
}
-static target_ulong h_rtas(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong rtas_r3 = args[0];
@@ -561,7 +536,7 @@ static target_ulong h_rtas(CPUPPCState *env, sPAPREnvironment *spapr,
nret, rtas_r3 + 12 + 4*nargs);
}
-static target_ulong h_logical_load(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong size = args[0];
@@ -584,7 +559,7 @@ static target_ulong h_logical_load(CPUPPCState *env, sPAPREnvironment *spapr,
return H_PARAMETER;
}
-static target_ulong h_logical_store(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong size = args[0];
@@ -608,7 +583,7 @@ static target_ulong h_logical_store(CPUPPCState *env, sPAPREnvironment *spapr,
return H_PARAMETER;
}
-static target_ulong h_logical_memop(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong dst = args[0]; /* Destination address */
@@ -675,14 +650,14 @@ static target_ulong h_logical_memop(CPUPPCState *env, sPAPREnvironment *spapr,
return H_SUCCESS;
}
-static target_ulong h_logical_icbi(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_logical_icbi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
/* Nothing to do on emulation, KVM will trap this in the kernel */
return H_SUCCESS;
}
-static target_ulong h_logical_dcbf(CPUPPCState *env, sPAPREnvironment *spapr,
+static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
/* Nothing to do on emulation, KVM will trap this in the kernel */
@@ -703,35 +678,29 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
} else {
assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX));
-
slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
}
- assert(!(*slot) || (fn == *slot));
+ assert(!(*slot));
*slot = fn;
}
-target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
+target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
target_ulong *args)
{
- if (msr_pr) {
- hcall_dprintf("Hypercall made with MSR[PR]=1\n");
- return H_PRIVILEGE;
- }
-
if ((opcode <= MAX_HCALL_OPCODE)
&& ((opcode & 0x3) == 0)) {
spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
if (fn) {
- return fn(env, spapr, opcode, args);
+ return fn(cpu, spapr, opcode, args);
}
} else if ((opcode >= KVMPPC_HCALL_BASE) &&
(opcode <= KVMPPC_HCALL_MAX)) {
spapr_hcall_fn fn = kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
if (fn) {
- return fn(env, spapr, opcode, args);
+ return fn(cpu, spapr, opcode, args);
}
}