From: Alexander Graf <agraf@suse.de>
To: Paul Mackerras <paulus@samba.org>
Cc: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org
Subject: Re: [PATCH 1/3] KVM: PPC: Book3S: Controls for in-kernel PAPR hypercall handling
Date: Wed, 28 May 2014 13:27:32 +0000 [thread overview]
Message-ID: <5385E444.2080509@suse.de> (raw)
In-Reply-To: <1401106626-13130-2-git-send-email-paulus@samba.org>
On 26.05.14 14:17, Paul Mackerras wrote:
> This provides a way for userspace controls which PAPR hcalls get
> handled in the kernel. Each hcall can be individually enabled or
> disabled for in-kernel handling, except for H_RTAS. The exception
> for H_RTAS is because userspace can already control whether
> individual RTAS functions are handled in-kernel or not via the
> KVM_PPC_RTAS_DEFINE_TOKEN ioctl, and because the numeric value for
> H_RTAS is out of the normal sequence of hcall numbers.
>
> Hcalls are enabled or disabled using the KVM_ENABLE_CAP ioctl for
> the KVM_CAP_PPC_ENABLE_HCALL capability. The args field of the
> struct kvm_enable_cap specifies the hcall number in args[0] and
> the enable/disable flag in args[1]; 0 means disable in-kernel
> handling (so that the hcall will always cause an exit to userspace)
> and 1 means enable.
>
> Enabling or disabling in-kernel handling of an hcall is effective
> across the whole VM, even though the KVM_ENABLE_CAP ioctl is
> applied to a vcpu.
>
> When a VM is created, an initial set of hcalls are enabled for
> in-kernel handling. The set that is enabled is the set that have
> an in-kernel implementation at this point. Any new hcall
> implementations from this point onwards should not be added to the
> default set.
>
> No distinction is made between real-mode and virtual-mode hcall
> implementations; the one setting controls them both.
>
> Signed-off-by: Paul Mackerras <paulus@samba.org>
> ---
> Documentation/virtual/kvm/api.txt | 17 +++++++++++
> arch/powerpc/include/asm/kvm_book3s.h | 1 +
> arch/powerpc/include/asm/kvm_host.h | 2 ++
> arch/powerpc/kernel/asm-offsets.c | 1 +
> arch/powerpc/kvm/book3s_hv.c | 51 +++++++++++++++++++++++++++++++++
> arch/powerpc/kvm/book3s_hv_rmhandlers.S | 11 +++++++
> arch/powerpc/kvm/book3s_pr.c | 5 ++++
> arch/powerpc/kvm/book3s_pr_papr.c | 37 ++++++++++++++++++++++++
> arch/powerpc/kvm/powerpc.c | 19 ++++++++++++
> include/uapi/linux/kvm.h | 1 +
> 10 files changed, 145 insertions(+)
>
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index 6b0225d..dfd6e0c 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -2983,3 +2983,20 @@ Parameters: args[0] is the XICS device fd
> args[1] is the XICS CPU number (server ID) for this vcpu
>
> This capability connects the vcpu to an in-kernel XICS device.
> +
> +6.8 KVM_CAP_PPC_ENABLE_HCALL
> +
> +Architectures: ppc
> +Parameters: args[0] is the PAPR hcall number
> + args[1] is 0 to disable, 1 to enable in-kernel handling
> +
> +This capability controls whether individual PAPR hypercalls (hcalls)
> +get handled by the kernel or not. Enabling or disabling in-kernel
> +handling of an hcall is effective across the VM. On creation, an
Hrm. Could we move the CAP to vm level then?
> +initial set of hcalls are enabled for in-kernel handling, which
> +consists of those hcalls for which in-kernel handlers were implemented
> +before this capability was implemented. If disabled, the kernel will
> +not to attempt to handle the hcall, but will always exit to userspace
> +to handle it. Note that it may not make sense to enable some and
> +disable others of a group of related hcalls, but KVM will not prevent
> +userspace from doing that.
> diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
> index f52f656..772044b 100644
> --- a/arch/powerpc/include/asm/kvm_book3s.h
> +++ b/arch/powerpc/include/asm/kvm_book3s.h
> @@ -189,6 +189,7 @@ extern void kvmppc_hv_entry_trampoline(void);
> extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
> extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
> extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
> +extern void kvmppc_pr_init_default_hcalls(struct kvm *kvm);
> extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
> struct kvm_vcpu *vcpu);
> extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
> diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> index bb66d8b..2889587 100644
> --- a/arch/powerpc/include/asm/kvm_host.h
> +++ b/arch/powerpc/include/asm/kvm_host.h
> @@ -34,6 +34,7 @@
> #include <asm/processor.h>
> #include <asm/page.h>
> #include <asm/cacheflush.h>
> +#include <asm/hvcall.h>
>
> #define KVM_MAX_VCPUS NR_CPUS
> #define KVM_MAX_VCORES NR_CPUS
> @@ -263,6 +264,7 @@ struct kvm_arch {
> #ifdef CONFIG_PPC_BOOK3S_64
> struct list_head spapr_tce_tables;
> struct list_head rtas_tokens;
> + DECLARE_BITMAP(enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
> #endif
> #ifdef CONFIG_KVM_MPIC
> struct openpic *mpic;
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index 93e1465..c427b51 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -492,6 +492,7 @@ int main(void)
> DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1));
> DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock));
> DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits));
> + DEFINE(KVM_ENABLED_HCALLS, offsetof(struct kvm, arch.enabled_hcalls));
> DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr));
> DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor));
> DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v));
> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> index aba05bb..84e695d 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -67,6 +67,8 @@
> /* Used as a "null" value for timebase values */
> #define TB_NIL (~(u64)0)
>
> +static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
> +
> static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
> static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
>
> @@ -562,6 +564,10 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
> struct kvm_vcpu *tvcpu;
> int idx, rc;
>
> + if (req <= MAX_HCALL_OPCODE &&
> + !test_bit(req/4, vcpu->kvm->arch.enabled_hcalls))
> + return RESUME_HOST;
> +
> switch (req) {
> case H_ENTER:
> idx = srcu_read_lock(&vcpu->kvm->srcu);
> @@ -2275,6 +2281,10 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
> */
> cpumask_setall(&kvm->arch.need_tlb_flush);
>
> + /* Start out with the default set of hcalls enabled */
> + memcpy(kvm->arch.enabled_hcalls, default_enabled_hcalls,
> + sizeof(kvm->arch.enabled_hcalls));
> +
> kvm->arch.rma = NULL;
>
> kvm->arch.host_sdr1 = mfspr(SPRN_SDR1);
> @@ -2413,6 +2423,45 @@ static long kvm_arch_vm_ioctl_hv(struct file *filp,
> return r;
> }
>
> +/*
> + * List of hcall numbers to enable by default.
> + * For compatibility with old userspace, we enable by default
> + * all hcalls that were implemented before the hcall-enabling
> + * facility was added. Note this list should not include H_RTAS.
> + */
> +static unsigned int default_hcall_list[] = {
> + H_REMOVE,
> + H_ENTER,
> + H_READ,
> + H_PROTECT,
> + H_BULK_REMOVE,
> + H_GET_TCE,
> + H_PUT_TCE,
> + H_SET_DABR,
> + H_SET_XDABR,
> + H_CEDE,
> + H_PROD,
> + H_CONFER,
> + H_REGISTER_VPA,
> +#ifdef CONFIG_KVM_XICS
> + H_EOI,
> + H_CPPR,
> + H_IPI,
> + H_IPOLL,
> + H_XIRR,
> + H_XIRR_X,
> +#endif
> + 0
> +};
> +
> +static void init_default_hcalls(void)
> +{
> + int i;
> +
> + for (i = 0; default_hcall_list[i]; ++i)
BUG_ON(default_hcall_list[i] > MAX_HCALL_OPCODE);
Alex
> + __set_bit(default_hcall_list[i] / 4, default_enabled_hcalls);
> +}
> +
> static struct kvmppc_ops kvm_ops_hv = {
> .get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv,
> .set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv,
> @@ -2460,6 +2509,8 @@ static int kvmppc_book3s_init_hv(void)
> kvm_ops_hv.owner = THIS_MODULE;
> kvmppc_hv_ops = &kvm_ops_hv;
>
> + init_default_hcalls();
> +
> r = kvmppc_mmu_hv_init();
> return r;
> }
> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> index 220aefb..c26b0e2 100644
> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> @@ -1795,6 +1795,17 @@ hcall_try_real_mode:
> clrrdi r3,r3,2
> cmpldi r3,hcall_real_table_end - hcall_real_table
> bge guest_exit_cont
> + /* See if this hcall is enabled for in-kernel handling */
> + ld r4, VCPU_KVM(r9)
> + srdi r0, r3, 8 /* r0 = (r3 / 4) >> 6 */
> + sldi r0, r0, 3 /* index into kvm->arch.enabled_hcalls[] */
> + add r4, r4, r0
> + ld r0, KVM_ENABLED_HCALLS(r4)
> + rlwinm r4, r3, 32-2, 0x3f /* r4 = (r3 / 4) & 0x3f */
> + srd r0, r0, r4
> + andi. r0, r0, 1
> + beq guest_exit_cont
> + /* Get pointer to handler, if any, and call it */
> LOAD_REG_ADDR(r4, hcall_real_table)
> lwax r3,r3,r4
> cmpwi r3,0
> diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
> index 23367a7..59dc94e 100644
> --- a/arch/powerpc/kvm/book3s_pr.c
> +++ b/arch/powerpc/kvm/book3s_pr.c
> @@ -1568,6 +1568,11 @@ static int kvmppc_core_init_vm_pr(struct kvm *kvm)
> {
> mutex_init(&kvm->arch.hpt_mutex);
>
> +#ifdef CONFIG_PPC_BOOK3S_64
> + /* Start out with the default set of hcalls enabled */
> + kvmppc_pr_init_default_hcalls(kvm);
> +#endif
> +
> if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
> spin_lock(&kvm_global_user_count_lock);
> if (++kvm_global_user_count = 1)
> diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c
> index 52a63bf..c5afde2 100644
> --- a/arch/powerpc/kvm/book3s_pr_papr.c
> +++ b/arch/powerpc/kvm/book3s_pr_papr.c
> @@ -266,6 +266,10 @@ static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
>
> int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
> {
> + if (cmd <= MAX_HCALL_OPCODE &&
> + !test_bit(cmd/4, vcpu->kvm->arch.enabled_hcalls))
> + return EMULATE_FAIL;
> +
> switch (cmd) {
> case H_ENTER:
> return kvmppc_h_pr_enter(vcpu);
> @@ -303,3 +307,36 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
>
> return EMULATE_FAIL;
> }
> +
> +
> +/*
> + * List of hcall numbers to enable by default.
> + * For compatibility with old userspace, we enable by default
> + * all hcalls that were implemented before the hcall-enabling
> + * facility was added. Note this list should not include H_RTAS.
> + */
> +static unsigned int default_hcall_list[] = {
> + H_ENTER,
> + H_REMOVE,
> + H_PROTECT,
> + H_BULK_REMOVE,
> + H_PUT_TCE,
> + H_CEDE,
> +#ifdef CONFIG_KVM_XICS
> + H_XIRR,
> + H_CPPR,
> + H_EOI,
> + H_IPI,
> + H_IPOLL,
> + H_XIRR_X,
> +#endif
> + 0
> +};
> +
> +void kvmppc_pr_init_default_hcalls(struct kvm *kvm)
> +{
> + int i;
> +
> + for (i = 0; default_hcall_list[i]; ++i)
> + __set_bit(default_hcall_list[i] / 4, kvm->arch.enabled_hcalls);
> +}
> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> index 154f352..5690c74 100644
> --- a/arch/powerpc/kvm/powerpc.c
> +++ b/arch/powerpc/kvm/powerpc.c
> @@ -416,6 +416,7 @@ int kvm_dev_ioctl_check_extension(long ext)
> case KVM_CAP_SPAPR_TCE:
> case KVM_CAP_PPC_ALLOC_HTAB:
> case KVM_CAP_PPC_RTAS:
> + case KVM_CAP_PPC_ENABLE_HCALL:
> #ifdef CONFIG_KVM_XICS
> case KVM_CAP_IRQ_XICS:
> #endif
> @@ -964,6 +965,24 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
> break;
> }
> #endif /* CONFIG_KVM_XICS */
> +#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
> + case KVM_CAP_PPC_ENABLE_HCALL: {
> + unsigned long hcall = cap->args[0];
> +
> + r = -EINVAL;
> + if (!vcpu->arch.papr_enabled)
> + break;
> + if (hcall > MAX_HCALL_OPCODE || (hcall & 3) ||
> + cap->args[1] > 1)
> + break;
> + if (cap->args[1])
> + set_bit(hcall / 4, vcpu->kvm->arch.enabled_hcalls);
> + else
> + clear_bit(hcall / 4, vcpu->kvm->arch.enabled_hcalls);
> + r = 0;
> + break;
> + }
> +#endif
> default:
> r = -EINVAL;
> break;
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 836e15b..79e4532 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -746,6 +746,7 @@ struct kvm_ppc_smmu_info {
> #define KVM_CAP_S390_IRQCHIP 99
> #define KVM_CAP_IOEVENTFD_NO_LENGTH 100
> #define KVM_CAP_VM_ATTRIBUTES 101
> +#define KVM_CAP_PPC_ENABLE_HCALL 102
>
> #ifdef KVM_CAP_IRQ_ROUTING
>
WARNING: multiple messages have this Message-ID (diff)
From: Alexander Graf <agraf@suse.de>
To: Paul Mackerras <paulus@samba.org>
Cc: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org
Subject: Re: [PATCH 1/3] KVM: PPC: Book3S: Controls for in-kernel PAPR hypercall handling
Date: Wed, 28 May 2014 15:27:32 +0200 [thread overview]
Message-ID: <5385E444.2080509@suse.de> (raw)
In-Reply-To: <1401106626-13130-2-git-send-email-paulus@samba.org>
On 26.05.14 14:17, Paul Mackerras wrote:
> This provides a way for userspace controls which PAPR hcalls get
> handled in the kernel. Each hcall can be individually enabled or
> disabled for in-kernel handling, except for H_RTAS. The exception
> for H_RTAS is because userspace can already control whether
> individual RTAS functions are handled in-kernel or not via the
> KVM_PPC_RTAS_DEFINE_TOKEN ioctl, and because the numeric value for
> H_RTAS is out of the normal sequence of hcall numbers.
>
> Hcalls are enabled or disabled using the KVM_ENABLE_CAP ioctl for
> the KVM_CAP_PPC_ENABLE_HCALL capability. The args field of the
> struct kvm_enable_cap specifies the hcall number in args[0] and
> the enable/disable flag in args[1]; 0 means disable in-kernel
> handling (so that the hcall will always cause an exit to userspace)
> and 1 means enable.
>
> Enabling or disabling in-kernel handling of an hcall is effective
> across the whole VM, even though the KVM_ENABLE_CAP ioctl is
> applied to a vcpu.
>
> When a VM is created, an initial set of hcalls are enabled for
> in-kernel handling. The set that is enabled is the set that have
> an in-kernel implementation at this point. Any new hcall
> implementations from this point onwards should not be added to the
> default set.
>
> No distinction is made between real-mode and virtual-mode hcall
> implementations; the one setting controls them both.
>
> Signed-off-by: Paul Mackerras <paulus@samba.org>
> ---
> Documentation/virtual/kvm/api.txt | 17 +++++++++++
> arch/powerpc/include/asm/kvm_book3s.h | 1 +
> arch/powerpc/include/asm/kvm_host.h | 2 ++
> arch/powerpc/kernel/asm-offsets.c | 1 +
> arch/powerpc/kvm/book3s_hv.c | 51 +++++++++++++++++++++++++++++++++
> arch/powerpc/kvm/book3s_hv_rmhandlers.S | 11 +++++++
> arch/powerpc/kvm/book3s_pr.c | 5 ++++
> arch/powerpc/kvm/book3s_pr_papr.c | 37 ++++++++++++++++++++++++
> arch/powerpc/kvm/powerpc.c | 19 ++++++++++++
> include/uapi/linux/kvm.h | 1 +
> 10 files changed, 145 insertions(+)
>
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index 6b0225d..dfd6e0c 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -2983,3 +2983,20 @@ Parameters: args[0] is the XICS device fd
> args[1] is the XICS CPU number (server ID) for this vcpu
>
> This capability connects the vcpu to an in-kernel XICS device.
> +
> +6.8 KVM_CAP_PPC_ENABLE_HCALL
> +
> +Architectures: ppc
> +Parameters: args[0] is the PAPR hcall number
> + args[1] is 0 to disable, 1 to enable in-kernel handling
> +
> +This capability controls whether individual PAPR hypercalls (hcalls)
> +get handled by the kernel or not. Enabling or disabling in-kernel
> +handling of an hcall is effective across the VM. On creation, an
Hrm. Could we move the CAP to vm level then?
> +initial set of hcalls are enabled for in-kernel handling, which
> +consists of those hcalls for which in-kernel handlers were implemented
> +before this capability was implemented. If disabled, the kernel will
> +not to attempt to handle the hcall, but will always exit to userspace
> +to handle it. Note that it may not make sense to enable some and
> +disable others of a group of related hcalls, but KVM will not prevent
> +userspace from doing that.
> diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
> index f52f656..772044b 100644
> --- a/arch/powerpc/include/asm/kvm_book3s.h
> +++ b/arch/powerpc/include/asm/kvm_book3s.h
> @@ -189,6 +189,7 @@ extern void kvmppc_hv_entry_trampoline(void);
> extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
> extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
> extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
> +extern void kvmppc_pr_init_default_hcalls(struct kvm *kvm);
> extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
> struct kvm_vcpu *vcpu);
> extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
> diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> index bb66d8b..2889587 100644
> --- a/arch/powerpc/include/asm/kvm_host.h
> +++ b/arch/powerpc/include/asm/kvm_host.h
> @@ -34,6 +34,7 @@
> #include <asm/processor.h>
> #include <asm/page.h>
> #include <asm/cacheflush.h>
> +#include <asm/hvcall.h>
>
> #define KVM_MAX_VCPUS NR_CPUS
> #define KVM_MAX_VCORES NR_CPUS
> @@ -263,6 +264,7 @@ struct kvm_arch {
> #ifdef CONFIG_PPC_BOOK3S_64
> struct list_head spapr_tce_tables;
> struct list_head rtas_tokens;
> + DECLARE_BITMAP(enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
> #endif
> #ifdef CONFIG_KVM_MPIC
> struct openpic *mpic;
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index 93e1465..c427b51 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -492,6 +492,7 @@ int main(void)
> DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1));
> DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock));
> DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits));
> + DEFINE(KVM_ENABLED_HCALLS, offsetof(struct kvm, arch.enabled_hcalls));
> DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr));
> DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor));
> DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v));
> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> index aba05bb..84e695d 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -67,6 +67,8 @@
> /* Used as a "null" value for timebase values */
> #define TB_NIL (~(u64)0)
>
> +static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
> +
> static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
> static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
>
> @@ -562,6 +564,10 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
> struct kvm_vcpu *tvcpu;
> int idx, rc;
>
> + if (req <= MAX_HCALL_OPCODE &&
> + !test_bit(req/4, vcpu->kvm->arch.enabled_hcalls))
> + return RESUME_HOST;
> +
> switch (req) {
> case H_ENTER:
> idx = srcu_read_lock(&vcpu->kvm->srcu);
> @@ -2275,6 +2281,10 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
> */
> cpumask_setall(&kvm->arch.need_tlb_flush);
>
> + /* Start out with the default set of hcalls enabled */
> + memcpy(kvm->arch.enabled_hcalls, default_enabled_hcalls,
> + sizeof(kvm->arch.enabled_hcalls));
> +
> kvm->arch.rma = NULL;
>
> kvm->arch.host_sdr1 = mfspr(SPRN_SDR1);
> @@ -2413,6 +2423,45 @@ static long kvm_arch_vm_ioctl_hv(struct file *filp,
> return r;
> }
>
> +/*
> + * List of hcall numbers to enable by default.
> + * For compatibility with old userspace, we enable by default
> + * all hcalls that were implemented before the hcall-enabling
> + * facility was added. Note this list should not include H_RTAS.
> + */
> +static unsigned int default_hcall_list[] = {
> + H_REMOVE,
> + H_ENTER,
> + H_READ,
> + H_PROTECT,
> + H_BULK_REMOVE,
> + H_GET_TCE,
> + H_PUT_TCE,
> + H_SET_DABR,
> + H_SET_XDABR,
> + H_CEDE,
> + H_PROD,
> + H_CONFER,
> + H_REGISTER_VPA,
> +#ifdef CONFIG_KVM_XICS
> + H_EOI,
> + H_CPPR,
> + H_IPI,
> + H_IPOLL,
> + H_XIRR,
> + H_XIRR_X,
> +#endif
> + 0
> +};
> +
> +static void init_default_hcalls(void)
> +{
> + int i;
> +
> + for (i = 0; default_hcall_list[i]; ++i)
BUG_ON(default_hcall_list[i] > MAX_HCALL_OPCODE);
Alex
> + __set_bit(default_hcall_list[i] / 4, default_enabled_hcalls);
> +}
> +
> static struct kvmppc_ops kvm_ops_hv = {
> .get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv,
> .set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv,
> @@ -2460,6 +2509,8 @@ static int kvmppc_book3s_init_hv(void)
> kvm_ops_hv.owner = THIS_MODULE;
> kvmppc_hv_ops = &kvm_ops_hv;
>
> + init_default_hcalls();
> +
> r = kvmppc_mmu_hv_init();
> return r;
> }
> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> index 220aefb..c26b0e2 100644
> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> @@ -1795,6 +1795,17 @@ hcall_try_real_mode:
> clrrdi r3,r3,2
> cmpldi r3,hcall_real_table_end - hcall_real_table
> bge guest_exit_cont
> + /* See if this hcall is enabled for in-kernel handling */
> + ld r4, VCPU_KVM(r9)
> + srdi r0, r3, 8 /* r0 = (r3 / 4) >> 6 */
> + sldi r0, r0, 3 /* index into kvm->arch.enabled_hcalls[] */
> + add r4, r4, r0
> + ld r0, KVM_ENABLED_HCALLS(r4)
> + rlwinm r4, r3, 32-2, 0x3f /* r4 = (r3 / 4) & 0x3f */
> + srd r0, r0, r4
> + andi. r0, r0, 1
> + beq guest_exit_cont
> + /* Get pointer to handler, if any, and call it */
> LOAD_REG_ADDR(r4, hcall_real_table)
> lwax r3,r3,r4
> cmpwi r3,0
> diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
> index 23367a7..59dc94e 100644
> --- a/arch/powerpc/kvm/book3s_pr.c
> +++ b/arch/powerpc/kvm/book3s_pr.c
> @@ -1568,6 +1568,11 @@ static int kvmppc_core_init_vm_pr(struct kvm *kvm)
> {
> mutex_init(&kvm->arch.hpt_mutex);
>
> +#ifdef CONFIG_PPC_BOOK3S_64
> + /* Start out with the default set of hcalls enabled */
> + kvmppc_pr_init_default_hcalls(kvm);
> +#endif
> +
> if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
> spin_lock(&kvm_global_user_count_lock);
> if (++kvm_global_user_count == 1)
> diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c
> index 52a63bf..c5afde2 100644
> --- a/arch/powerpc/kvm/book3s_pr_papr.c
> +++ b/arch/powerpc/kvm/book3s_pr_papr.c
> @@ -266,6 +266,10 @@ static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
>
> int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
> {
> + if (cmd <= MAX_HCALL_OPCODE &&
> + !test_bit(cmd/4, vcpu->kvm->arch.enabled_hcalls))
> + return EMULATE_FAIL;
> +
> switch (cmd) {
> case H_ENTER:
> return kvmppc_h_pr_enter(vcpu);
> @@ -303,3 +307,36 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
>
> return EMULATE_FAIL;
> }
> +
> +
> +/*
> + * List of hcall numbers to enable by default.
> + * For compatibility with old userspace, we enable by default
> + * all hcalls that were implemented before the hcall-enabling
> + * facility was added. Note this list should not include H_RTAS.
> + */
> +static unsigned int default_hcall_list[] = {
> + H_ENTER,
> + H_REMOVE,
> + H_PROTECT,
> + H_BULK_REMOVE,
> + H_PUT_TCE,
> + H_CEDE,
> +#ifdef CONFIG_KVM_XICS
> + H_XIRR,
> + H_CPPR,
> + H_EOI,
> + H_IPI,
> + H_IPOLL,
> + H_XIRR_X,
> +#endif
> + 0
> +};
> +
> +void kvmppc_pr_init_default_hcalls(struct kvm *kvm)
> +{
> + int i;
> +
> + for (i = 0; default_hcall_list[i]; ++i)
> + __set_bit(default_hcall_list[i] / 4, kvm->arch.enabled_hcalls);
> +}
> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> index 154f352..5690c74 100644
> --- a/arch/powerpc/kvm/powerpc.c
> +++ b/arch/powerpc/kvm/powerpc.c
> @@ -416,6 +416,7 @@ int kvm_dev_ioctl_check_extension(long ext)
> case KVM_CAP_SPAPR_TCE:
> case KVM_CAP_PPC_ALLOC_HTAB:
> case KVM_CAP_PPC_RTAS:
> + case KVM_CAP_PPC_ENABLE_HCALL:
> #ifdef CONFIG_KVM_XICS
> case KVM_CAP_IRQ_XICS:
> #endif
> @@ -964,6 +965,24 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
> break;
> }
> #endif /* CONFIG_KVM_XICS */
> +#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
> + case KVM_CAP_PPC_ENABLE_HCALL: {
> + unsigned long hcall = cap->args[0];
> +
> + r = -EINVAL;
> + if (!vcpu->arch.papr_enabled)
> + break;
> + if (hcall > MAX_HCALL_OPCODE || (hcall & 3) ||
> + cap->args[1] > 1)
> + break;
> + if (cap->args[1])
> + set_bit(hcall / 4, vcpu->kvm->arch.enabled_hcalls);
> + else
> + clear_bit(hcall / 4, vcpu->kvm->arch.enabled_hcalls);
> + r = 0;
> + break;
> + }
> +#endif
> default:
> r = -EINVAL;
> break;
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 836e15b..79e4532 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -746,6 +746,7 @@ struct kvm_ppc_smmu_info {
> #define KVM_CAP_S390_IRQCHIP 99
> #define KVM_CAP_IOEVENTFD_NO_LENGTH 100
> #define KVM_CAP_VM_ATTRIBUTES 101
> +#define KVM_CAP_PPC_ENABLE_HCALL 102
>
> #ifdef KVM_CAP_IRQ_ROUTING
>
next prev parent reply other threads:[~2014-05-28 13:27 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-26 12:17 [PATCH 0/3] New PAPR hypercall plus individual hypercall enables Paul Mackerras
2014-05-26 12:17 ` Paul Mackerras
2014-05-26 12:17 ` [PATCH 1/3] KVM: PPC: Book3S: Controls for in-kernel PAPR hypercall handling Paul Mackerras
2014-05-26 12:17 ` Paul Mackerras
2014-05-28 13:27 ` Alexander Graf [this message]
2014-05-28 13:27 ` Alexander Graf
2014-05-29 5:27 ` Paul Mackerras
2014-05-29 5:27 ` Paul Mackerras
2014-05-29 6:35 ` Alexander Graf
2014-05-29 6:35 ` Alexander Graf
2014-05-26 12:17 ` [PATCH 2/3] KVM: PPC: Book3S: Allow only implemented hcalls to be enabled or disabled Paul Mackerras
2014-05-26 12:17 ` Paul Mackerras
2014-05-28 13:30 ` Alexander Graf
2014-05-28 13:30 ` Alexander Graf
2014-05-26 12:17 ` [PATCH 3/3] KVM: PPC: Book3S HV: Add H_SET_MODE hcall handling Paul Mackerras
2014-05-26 12:17 ` Paul Mackerras
2014-05-28 13:35 ` Alexander Graf
2014-05-28 13:35 ` Alexander Graf
2014-05-29 5:47 ` Michael Neuling
2014-05-29 5:47 ` Michael Neuling
2014-05-29 6:22 ` [PATCH v2 " Michael Neuling
2014-05-29 6:22 ` Michael Neuling
2014-05-29 7:18 ` Alexander Graf
2014-05-29 7:18 ` Alexander Graf
2014-05-29 7:45 ` powerpc/pseries: Use new defines when calling h_set_mode Michael Neuling
2014-05-29 7:45 ` Michael Neuling
2014-05-29 7:45 ` Michael Neuling
2014-05-29 21:27 ` Alexander Graf
2014-05-29 21:27 ` Alexander Graf
2014-05-29 21:27 ` Alexander Graf
2014-05-29 21:52 ` Benjamin Herrenschmidt
2014-05-29 21:52 ` Benjamin Herrenschmidt
2014-05-29 21:52 ` Benjamin Herrenschmidt
2014-05-30 7:44 ` Alexander Graf
2014-05-30 7:44 ` Alexander Graf
2014-05-30 7:44 ` Alexander Graf
2014-05-30 8:56 ` Michael Ellerman
2014-05-30 8:56 ` Michael Ellerman
2014-05-30 8:56 ` Michael Ellerman
2014-05-30 9:10 ` Michael Neuling
2014-05-30 9:10 ` Michael Neuling
2014-05-30 9:10 ` Michael Neuling
2014-05-30 9:13 ` Alexander Graf
2014-05-30 9:13 ` Alexander Graf
2014-05-30 9:13 ` Alexander Graf
2014-05-30 9:44 ` Michael Neuling
2014-05-30 9:44 ` Michael Neuling
2014-05-30 9:44 ` Alexander Graf
2014-05-30 9:44 ` Alexander Graf
2014-05-30 9:44 ` Alexander Graf
2014-05-31 7:21 ` [PATCH 0/3] New PAPR hypercall plus individual hypercall enables, v2 Paul Mackerras
2014-05-31 7:21 ` Paul Mackerras
2014-05-31 7:21 ` [PATCH 1/3] KVM: PPC: Book3S: Controls for in-kernel PAPR hypercall handling Paul Mackerras
2014-05-31 7:21 ` Paul Mackerras
2014-06-01 9:55 ` Alexander Graf
2014-06-01 9:55 ` Alexander Graf
2014-05-31 7:21 ` [PATCH 2/3] KVM: PPC: Book3S: Allow only implemented hcalls to be enabled or disabled Paul Mackerras
2014-05-31 7:21 ` Paul Mackerras
2014-05-31 7:21 ` [PATCH 3/3] KVM: PPC: Book3S HV: Add H_SET_MODE hcall handling Paul Mackerras
2014-05-31 7:21 ` Paul Mackerras
2014-06-01 10:01 ` [PATCH 0/3] New PAPR hypercall plus individual hypercall enables, v2 Alexander Graf
2014-06-01 10:01 ` Alexander Graf
2014-06-02 1:02 ` [PATCH 0/3] New PAPR hypercall plus individual hypercall enables, v3 Paul Mackerras
2014-06-02 1:02 ` Paul Mackerras
2014-06-02 1:02 ` [PATCH 1/3] KVM: PPC: Book3S: Controls for in-kernel sPAPR hypercall handling Paul Mackerras
2014-06-02 1:02 ` Paul Mackerras
2014-06-02 1:03 ` [PATCH 2/3] KVM: PPC: Book3S: Allow only implemented hcalls to be enabled or disabled Paul Mackerras
2014-06-02 1:03 ` Paul Mackerras
2014-06-02 1:03 ` [PATCH 3/3] KVM: PPC: Book3S HV: Add H_SET_MODE hcall handling Paul Mackerras
2014-06-02 1:03 ` Paul Mackerras
2014-06-25 21:46 ` [PATCH 0/3] New PAPR hypercall plus individual hypercall enables, v3 Alexander Graf
2014-06-25 21:46 ` Alexander Graf
2014-06-25 23:08 ` Paul Mackerras
2014-06-25 23:08 ` Paul Mackerras
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5385E444.2080509@suse.de \
--to=agraf@suse.de \
--cc=kvm-ppc@vger.kernel.org \
--cc=kvm@vger.kernel.org \
--cc=paulus@samba.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.