Message ID | 1401344549.4116.8.camel@ale.ozlabs.ibm.com |
---|---|
State | New, archived |
Headers | show |
> Am 29.05.2014 um 08:22 schrieb Michael Neuling <mikey@neuling.org>: > > This adds support for the H_SET_MODE hcall. This hcall is a > multiplexer that has several functions, some of which are called > rarely, and some which are potentially called very frequently. > Here we add support for the functions that set the debug registers > CIABR (Completed Instruction Address Breakpoint Register) and > DAWR/DAWRX (Data Address Watchpoint Register and eXtension), > since they could be updated by the guest as often as every context > switch. > > This also adds a kvmppc_power8_compatible() function to test to see > if a guest is compatible with POWER8 or not. The CIABR and DAWR/X > only exist on POWER8. > > Signed-off-by: Michael Neuling <mikey@neuling.org> > Signed-off-by: Paul Mackerras <paulus@samba.org> > --- > v2: > add some #defines to make CIABR setting clearer. No functional change. > > diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h > index 5dbbb29..85bc8c0 100644 > --- a/arch/powerpc/include/asm/hvcall.h > +++ b/arch/powerpc/include/asm/hvcall.h > @@ -279,6 +279,12 @@ > #define H_GET_24X7_DATA 0xF07C > #define H_GET_PERF_COUNTER_INFO 0xF080 > > +/* Values for 2nd argument to H_SET_MODE */ > +#define H_SET_MODE_RESOURCE_SET_CIABR 1 > +#define H_SET_MODE_RESOURCE_SET_DAWR 2 > +#define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE 3 > +#define H_SET_MODE_RESOURCE_LE 4 Much better, but I think you want to make use of these in non-kvm code too, no? At least the LE one is definitely already implemented as call :) Alex > + > #ifndef __ASSEMBLY__ > > /** > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c > index e699047..e74dab2 100644 > --- a/arch/powerpc/kvm/book3s_hv.c > +++ b/arch/powerpc/kvm/book3s_hv.c > @@ -557,6 +557,48 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu, > vcpu->arch.dtl.dirty = true; > } > > +static bool kvmppc_power8_compatible(struct kvm_vcpu *vcpu) > +{ > + if (vcpu->arch.vcore->arch_compat >= PVR_ARCH_207) > + return true; > + if ((!vcpu->arch.vcore->arch_compat) && > + cpu_has_feature(CPU_FTR_ARCH_207S)) > + return true; > + return false; > +} > + > +static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags, > + unsigned long resource, unsigned long value1, > + unsigned long value2) > +{ > + switch (resource) { > + case H_SET_MODE_RESOURCE_SET_CIABR: > + if (!kvmppc_power8_compatible(vcpu)) > + return H_P2; > + if (value2) > + return H_P4; > + if (mflags) > + return H_UNSUPPORTED_FLAG_START; > + /* Guests can't breakpoint the hypervisor */ > + if ((value1 & CIABR_PRIV) == CIABR_PRIV_HYPER) > + return H_P3; > + vcpu->arch.ciabr = value1; > + return H_SUCCESS; > + case H_SET_MODE_RESOURCE_SET_DAWR: > + if (!kvmppc_power8_compatible(vcpu)) > + return H_P2; > + if (mflags) > + return H_UNSUPPORTED_FLAG_START; > + if (value2 & DABRX_HYP) > + return H_P4; > + vcpu->arch.dawr = value1; > + vcpu->arch.dawrx = value2; > + return H_SUCCESS; > + default: > + return H_TOO_HARD; > + } > +} > + > int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) > { > unsigned long req = kvmppc_get_gpr(vcpu, 3); > @@ -626,7 +668,14 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) > > /* Send the error out to userspace via KVM_RUN */ > return rc; > - > + case H_SET_MODE: > + ret = kvmppc_h_set_mode(vcpu, kvmppc_get_gpr(vcpu, 4), > + kvmppc_get_gpr(vcpu, 5), > + kvmppc_get_gpr(vcpu, 6), > + kvmppc_get_gpr(vcpu, 7)); > + if (ret == H_TOO_HARD) > + return RESUME_HOST; > + break; > case H_XIRR: > case H_CPPR: > case H_EOI: > @@ -652,6 +701,7 @@ static int kvmppc_hcall_impl_hv(struct kvm *kvm, unsigned long cmd) > case H_PROD: > case H_CONFER: > case H_REGISTER_VPA: > + case H_SET_MODE: > #ifdef CONFIG_KVM_XICS > case H_XIRR: > case H_CPPR: > > -- > To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index 5dbbb29..85bc8c0 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h @@ -279,6 +279,12 @@ #define H_GET_24X7_DATA 0xF07C #define H_GET_PERF_COUNTER_INFO 0xF080 +/* Values for 2nd argument to H_SET_MODE */ +#define H_SET_MODE_RESOURCE_SET_CIABR 1 +#define H_SET_MODE_RESOURCE_SET_DAWR 2 +#define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE 3 +#define H_SET_MODE_RESOURCE_LE 4 + #ifndef __ASSEMBLY__ /** diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index e699047..e74dab2 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -557,6 +557,48 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu, vcpu->arch.dtl.dirty = true; } +static bool kvmppc_power8_compatible(struct kvm_vcpu *vcpu) +{ + if (vcpu->arch.vcore->arch_compat >= PVR_ARCH_207) + return true; + if ((!vcpu->arch.vcore->arch_compat) && + cpu_has_feature(CPU_FTR_ARCH_207S)) + return true; + return false; +} + +static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags, + unsigned long resource, unsigned long value1, + unsigned long value2) +{ + switch (resource) { + case H_SET_MODE_RESOURCE_SET_CIABR: + if (!kvmppc_power8_compatible(vcpu)) + return H_P2; + if (value2) + return H_P4; + if (mflags) + return H_UNSUPPORTED_FLAG_START; + /* Guests can't breakpoint the hypervisor */ + if ((value1 & CIABR_PRIV) == CIABR_PRIV_HYPER) + return H_P3; + vcpu->arch.ciabr = value1; + return H_SUCCESS; + case H_SET_MODE_RESOURCE_SET_DAWR: + if (!kvmppc_power8_compatible(vcpu)) + return H_P2; + if (mflags) + return H_UNSUPPORTED_FLAG_START; + if (value2 & DABRX_HYP) + return H_P4; + vcpu->arch.dawr = value1; + vcpu->arch.dawrx = value2; + return H_SUCCESS; + default: + return H_TOO_HARD; + } +} + int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) { unsigned long req = kvmppc_get_gpr(vcpu, 3); @@ -626,7 +668,14 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) /* Send the error out to userspace via KVM_RUN */ return rc; - + case H_SET_MODE: + ret = kvmppc_h_set_mode(vcpu, kvmppc_get_gpr(vcpu, 4), + kvmppc_get_gpr(vcpu, 5), + kvmppc_get_gpr(vcpu, 6), + kvmppc_get_gpr(vcpu, 7)); + if (ret == H_TOO_HARD) + return RESUME_HOST; + break; case H_XIRR: case H_CPPR: case H_EOI: @@ -652,6 +701,7 @@ static int kvmppc_hcall_impl_hv(struct kvm *kvm, unsigned long cmd) case H_PROD: case H_CONFER: case H_REGISTER_VPA: + case H_SET_MODE: #ifdef CONFIG_KVM_XICS case H_XIRR: case H_CPPR: