KVM: PPC: Book3s: PR: Add SPAPR H_BULK_REMOVE support
Subsystems (2)
PATCH 1/1 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 <[email protected]>
---
Alex, my "zomg, ls SIGILLs!" on IRC was due to a former broken version of
this patch skipping an invalidation or two... Works well now. ;)
arch/powerpc/kvm/book3s_pr_papr.c | 82 +++++++++++++++++++++++++++++++++++-- 1 files changed, 78 insertions(+), 4 deletions(-)
arch/powerpc/kvm/book3s_pr_papr.c +77 -4
@@ -98,6 +98,83 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)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) {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 :return kvmppc_h_pr_protect (vcpu);case H_BULK_REMOVE : -/* We just flush all PTEs, so user space can -handle the HPT modifications */ -kvmppc_mmu_pte_flush (vcpu,0 ,0 ); -break ; +return kvmppc_h_pr_bulk_remove (vcpu);case H_CEDE :kvm_vcpu_block (vcpu); vcpu->stat.halt_wakeup++;
Signature · 1 line
1.7.0.4