public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
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
>   

  reply	other threads:[~2014-05-28 13:27 UTC|newest]

Thread overview: 23+ 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 ` [PATCH 1/3] KVM: PPC: Book3S: Controls for in-kernel PAPR hypercall handling Paul Mackerras
2014-05-28 13:27   ` Alexander Graf [this message]
2014-05-29  5:27     ` Paul Mackerras
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-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-28 13:35   ` Alexander Graf
2014-05-29  5:47     ` Michael Neuling
2014-05-29  6:22       ` [PATCH v2 " Michael Neuling
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 21:27             ` Alexander Graf
2014-05-29 21:52               ` Benjamin Herrenschmidt
2014-05-30  7:44                 ` Alexander Graf
2014-05-30  8:56             ` Michael Ellerman
2014-05-30  9:10               ` Michael Neuling
2014-05-30  9:13                 ` Alexander Graf
2014-05-30  9:44                   ` Michael Neuling
2014-05-30  9:44                     ` Alexander Graf
  -- strict thread matches above, loose matches on Subject: below --
2014-05-31  7:21 [PATCH 0/3] New PAPR hypercall plus individual hypercall enables, v2 Paul Mackerras
2014-05-31  7:21 ` [PATCH 1/3] KVM: PPC: Book3S: Controls for in-kernel PAPR hypercall handling Paul Mackerras
2014-06-01  9:55   ` Alexander Graf

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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox