KVM: PPC: Book3s: PR: Add SPAPR H_BULK_REMOVE support
SPAPR support includes various in-kernel hypercalls, improving performance by cutting out the exit to userspace. H_BULK_REMOVE is implemented in this patch. Signed-off-by: Matt Evans <matt@ozlabs.org> Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
parent
03660ba270
commit
3aaefef200
@ -98,6 +98,83 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
|
|||||||
return EMULATE_DONE;
|
return EMULATE_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Request defs for kvmppc_h_pr_bulk_remove() */
|
||||||
|
#define H_BULK_REMOVE_TYPE 0xc000000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_REQUEST 0x4000000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_RESPONSE 0x8000000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_END 0xc000000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_CODE 0x3000000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_SUCCESS 0x0000000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_NOT_FOUND 0x1000000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_PARM 0x2000000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_HW 0x3000000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_RC 0x0c00000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_FLAGS 0x0300000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_ABSOLUTE 0x0000000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_ANDCOND 0x0100000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_AVPN 0x0200000000000000ULL
|
||||||
|
#define H_BULK_REMOVE_PTEX 0x00ffffffffffffffULL
|
||||||
|
#define H_BULK_REMOVE_MAX_BATCH 4
|
||||||
|
|
||||||
|
static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int paramnr = 4;
|
||||||
|
int ret = H_SUCCESS;
|
||||||
|
|
||||||
|
for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
|
||||||
|
unsigned long tsh = kvmppc_get_gpr(vcpu, paramnr+(2*i));
|
||||||
|
unsigned long tsl = kvmppc_get_gpr(vcpu, paramnr+(2*i)+1);
|
||||||
|
unsigned long pteg, rb, flags;
|
||||||
|
unsigned long pte[2];
|
||||||
|
unsigned long v = 0;
|
||||||
|
|
||||||
|
if ((tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) {
|
||||||
|
break; /* Exit success */
|
||||||
|
} else if ((tsh & H_BULK_REMOVE_TYPE) !=
|
||||||
|
H_BULK_REMOVE_REQUEST) {
|
||||||
|
ret = H_PARAMETER;
|
||||||
|
break; /* Exit fail */
|
||||||
|
}
|
||||||
|
|
||||||
|
tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS;
|
||||||
|
tsh |= H_BULK_REMOVE_RESPONSE;
|
||||||
|
|
||||||
|
if ((tsh & H_BULK_REMOVE_ANDCOND) &&
|
||||||
|
(tsh & H_BULK_REMOVE_AVPN)) {
|
||||||
|
tsh |= H_BULK_REMOVE_PARM;
|
||||||
|
kvmppc_set_gpr(vcpu, paramnr+(2*i), tsh);
|
||||||
|
ret = H_PARAMETER;
|
||||||
|
break; /* Exit fail */
|
||||||
|
}
|
||||||
|
|
||||||
|
pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX);
|
||||||
|
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
|
||||||
|
|
||||||
|
/* tsl = AVPN */
|
||||||
|
flags = (tsh & H_BULK_REMOVE_FLAGS) >> 26;
|
||||||
|
|
||||||
|
if ((pte[0] & HPTE_V_VALID) == 0 ||
|
||||||
|
((flags & H_AVPN) && (pte[0] & ~0x7fUL) != tsl) ||
|
||||||
|
((flags & H_ANDCOND) && (pte[0] & tsl) != 0)) {
|
||||||
|
tsh |= H_BULK_REMOVE_NOT_FOUND;
|
||||||
|
} else {
|
||||||
|
/* Splat the pteg in (userland) hpt */
|
||||||
|
copy_to_user((void __user *)pteg, &v, sizeof(v));
|
||||||
|
|
||||||
|
rb = compute_tlbie_rb(pte[0], pte[1],
|
||||||
|
tsh & H_BULK_REMOVE_PTEX);
|
||||||
|
vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
|
||||||
|
tsh |= H_BULK_REMOVE_SUCCESS;
|
||||||
|
tsh |= (pte[1] & (HPTE_R_C | HPTE_R_R)) << 43;
|
||||||
|
}
|
||||||
|
kvmppc_set_gpr(vcpu, paramnr+(2*i), tsh);
|
||||||
|
}
|
||||||
|
kvmppc_set_gpr(vcpu, 3, ret);
|
||||||
|
|
||||||
|
return EMULATE_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
|
static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
unsigned long flags = kvmppc_get_gpr(vcpu, 4);
|
unsigned long flags = kvmppc_get_gpr(vcpu, 4);
|
||||||
@ -144,10 +221,7 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
|
|||||||
case H_PROTECT:
|
case H_PROTECT:
|
||||||
return kvmppc_h_pr_protect(vcpu);
|
return kvmppc_h_pr_protect(vcpu);
|
||||||
case H_BULK_REMOVE:
|
case H_BULK_REMOVE:
|
||||||
/* We just flush all PTEs, so user space can
|
return kvmppc_h_pr_bulk_remove(vcpu);
|
||||||
handle the HPT modifications */
|
|
||||||
kvmppc_mmu_pte_flush(vcpu, 0, 0);
|
|
||||||
break;
|
|
||||||
case H_CEDE:
|
case H_CEDE:
|
||||||
kvm_vcpu_block(vcpu);
|
kvm_vcpu_block(vcpu);
|
||||||
vcpu->stat.halt_wakeup++;
|
vcpu->stat.halt_wakeup++;
|
||||||
|
Loading…
Reference in New Issue
Block a user