kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Avi Kivity <avi@redhat.com>
To: Christoffer Dall <c.dall@virtualopensystems.com>
Cc: android-virt@lists.cs.columbia.edu, kvm@vger.kernel.org
Subject: Re: [PATCH v8 10/15] ARM: KVM: Inject IRQs and FIQs from userspace
Date: Tue, 19 Jun 2012 11:49:29 +0300	[thread overview]
Message-ID: <4FE03D19.4050301@redhat.com> (raw)
In-Reply-To: <CANM98q+bHUfOznYyB4dkyVmORVxFdSVCs5zXkd0=7CrMZUtBPw@mail.gmail.com>

On 06/18/2012 11:56 PM, Christoffer Dall wrote:
> On Mon, Jun 18, 2012 at 9:32 AM, Avi Kivity <avi@redhat.com> wrote:
>> On 06/15/2012 10:08 PM, Christoffer Dall wrote:
>>> From: Christoffer Dall <cdall@cs.columbia.edu>
>>>
>>> Userspace can inject IRQs and FIQs through the KVM_IRQ_LINE VM ioctl.
>>> This ioctl is used since the sematics are in fact two lines that can be
>>> either raised or lowered on the VCPU - the IRQ and FIQ lines.
>>>
>>> KVM needs to know which VCPU it must operate on and whether the FIQ or
>>> IRQ line is raised/lowered. Hence both pieces of information is packed
>>> in the kvm_irq_level->irq field. The irq fild value will be:
>>>   IRQ: vcpu_index << 1
>>>   FIQ: (vcpu_index << 1) | 1
>>>
>>> This is documented in Documentation/kvm/api.txt.
>>>
>>> The effect of the ioctl is simply to simply raise/lower the
>>> corresponding irq_line field on the VCPU struct, which will cause the
>>> world-switch code to raise/lower virtual interrupts when running the
>>> guest on next switch. The wait_for_interrupt flag is also cleared for
>>> raised IRQs or FIQs causing an idle VCPU to become active again. CPUs
>>> in guest mode are kicked to make sure they refresh their interrupt status.
>>
>>>
>>> +static int kvm_arch_vm_ioctl_irq_line(struct kvm *kvm,
>>> +                                   struct kvm_irq_level *irq_level)
>>> +{
>>> +     int mask;
>>> +     unsigned int vcpu_idx;
>>> +     struct kvm_vcpu *vcpu;
>>> +     unsigned long old, new, *ptr;
>>> +
>>> +     vcpu_idx = irq_level->irq >> 1;
>>> +     if (vcpu_idx >= KVM_MAX_VCPUS)
>>> +             return -EINVAL;
>>> +
>>> +     vcpu = kvm_get_vcpu(kvm, vcpu_idx);
>>> +     if (!vcpu)
>>> +             return -EINVAL;
>>> +
>>> +     if ((irq_level->irq & 1) == KVM_ARM_IRQ_LINE)
>>> +             mask = HCR_VI;
>>> +     else /* KVM_ARM_FIQ_LINE */
>>> +             mask = HCR_VF;
>>> +
>>> +     trace_kvm_set_irq(irq_level->irq, irq_level->level, 0);
>>> +
>>> +     ptr = (unsigned long *)&vcpu->arch.irq_lines;
>>> +     do {
>>> +             old = ACCESS_ONCE(*ptr);
>>> +             if (irq_level->level)
>>> +                     new = old | mask;
>>> +             else
>>> +                     new = old & ~mask;
>>> +
>>> +             if (new == old)
>>> +                     return 0; /* no change */
>>> +     } while (cmpxchg(ptr, old, new) != old);
>>
>> Isn't this a complicated
>>
>>
>>   if (level)
>>       set_bit()
>>   else
>>       clear_bit()
>>
>> ?
>>
> 
> we need to atomically know if we changed either the FIQ/IRQ fields and
> atomically update without locking.

So use test_and_set_bit()/test_and_clear_bit().

> (I think you suggested this
> approach, in fact).

I think so too, but it only makes sense if you need to consider both
fields simultaneously (which you don't here).  For example, if IRQ was
asserted while FIQ was already raised, you don't need to kick.  But
that's not the case according to the below.

> 
>>> +
>>> +     /*
>>> +      * The vcpu irq_lines field was updated, wake up sleeping VCPUs and
>>> +      * trigger a world-switch round on the running physical CPU to set the
>>> +      * virtual IRQ/FIQ fields in the HCR appropriately.
>>> +      */
>>> +     kvm_vcpu_kick(vcpu);
>>
>> No need to wake when the line is asserted so you can make this
>> conditional on level.
>>
> 
> we need to trigger a world switch to update the virtualized register
> from the actual running physical CPU if we changed any of the IRQ/FIQ
> fields. We return in the loop above if we didn't change anything.

Okay.


> 
>>> +
>>> +     return 0;
>>> +}
>>> +
>>>  long kvm_arch_vcpu_ioctl(struct file *filp,
>>>                        unsigned int ioctl, unsigned long arg)
>>>  {
>>> @@ -298,7 +345,20 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
>>>  long kvm_arch_vm_ioctl(struct file *filp,
>>>                      unsigned int ioctl, unsigned long arg)
>>>  {
>>> -     return -EINVAL;
>>> +     struct kvm *kvm = filp->private_data;
>>> +     void __user *argp = (void __user *)arg;
>>> +
>>> +     switch (ioctl) {
>>> +     case KVM_IRQ_LINE: {
>>> +             struct kvm_irq_level irq_event;
>>> +
>>> +             if (copy_from_user(&irq_event, argp, sizeof irq_event))
>>> +                     return -EFAULT;
>>> +             return kvm_arch_vm_ioctl_irq_line(kvm, &irq_event);
>>> +     }
>>> +     default:
>>> +             return -EINVAL;
>>> +     }
>>>  }
>>
>> Should be in common code guarded by the define introduced previously.
>>
>>
> 
> you mean like this: ?
> 
> 
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index a9f209b..5bf2193 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -535,8 +535,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu,
> struct kvm_run *run)
>  	return ret;
>  }
> 
> -static int kvm_arch_vm_ioctl_irq_line(struct kvm *kvm,
> -				      struct kvm_irq_level *irq_level)
> +int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level)
>  {
>  	int mask;
>  	unsigned int vcpu_idx;
> @@ -596,20 +595,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
> struct kvm_dirty_log *log)
>  long kvm_arch_vm_ioctl(struct file *filp,
>  		       unsigned int ioctl, unsigned long arg)
>  {
> -	struct kvm *kvm = filp->private_data;
> -	void __user *argp = (void __user *)arg;
> -
> -	switch (ioctl) {
> -	case KVM_IRQ_LINE: {
> -		struct kvm_irq_level irq_event;
> -
> -		if (copy_from_user(&irq_event, argp, sizeof irq_event))
> -			return -EFAULT;
> -		return kvm_arch_vm_ioctl_irq_line(kvm, &irq_event);
> -	}
> -	default:
> -		return -EINVAL;
> -	}
> +	return -EINVAL;
>  }
> 
>  static void cpu_set_vector(void *vector)
> diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
> index bd77cb5..122a4b2 100644
> --- a/arch/ia64/kvm/kvm-ia64.c
> +++ b/arch/ia64/kvm/kvm-ia64.c
> @@ -924,6 +924,16 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu
> *vcpu, struct kvm_regs *regs)
>  	return 0;
>  }
> 
> +int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event)
> +{
> +	if (!irqchip_in_kernel(kvm))
> +		return -ENXIO;
> +
> +	irq_event->statusstatus = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
> +					      irq_event->irq, irq_event->level);
> +	return 0;
> +}
> +
>  long kvm_arch_vm_ioctl(struct file *filp,
>  		unsigned int ioctl, unsigned long arg)
>  {
> @@ -963,29 +973,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
>  			goto out;
>  		}
>  		break;
> -	case KVM_IRQ_LINE_STATUS:
> -	case KVM_IRQ_LINE: {
> -		struct kvm_irq_level irq_event;
> -
> -		r = -EFAULT;
> -		if (copy_from_user(&irq_event, argp, sizeof irq_event))
> -			goto out;
> -		r = -ENXIO;
> -		if (irqchip_in_kernel(kvm)) {
> -			__s32 status;
> -			status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
> -				    irq_event.irq, irq_event.level);
> -			if (ioctl == KVM_IRQ_LINE_STATUS) {
> -				r = -EFAULT;
> -				irq_event.status = status;
> -				if (copy_to_user(argp, &irq_event,
> -							sizeof irq_event))
> -					goto out;
> -			}
> -			r = 0;
> -		}
> -		break;
> -		}
>  	case KVM_GET_IRQCHIP: {
>  		/* 0: PIC master, 1: PIC slave, 2: IOAPIC */
>  		struct kvm_irqchip chip;
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index a01a424..c9c4186 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -3144,6 +3144,16 @@ out:
>  	return r;
>  }
> 
> +int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event)
> +{
> +	if (!irqchip_in_kernel(kvm))
> +		return -ENXIO;
> +
> +	irq_event->status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
> +					irq_event->irq, irq_event->level);
> +	return 0;
> +}
> +
>  long kvm_arch_vm_ioctl(struct file *filp,
>  		       unsigned int ioctl, unsigned long arg)
>  {
> @@ -3250,29 +3260,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
>  	create_pit_unlock:
>  		mutex_unlock(&kvm->slots_lock);
>  		break;
> -	case KVM_IRQ_LINE_STATUS:
> -	case KVM_IRQ_LINE: {
> -		struct kvm_irq_level irq_event;
> -
> -		r = -EFAULT;
> -		if (copy_from_user(&irq_event, argp, sizeof irq_event))
> -			goto out;
> -		r = -ENXIO;
> -		if (irqchip_in_kernel(kvm)) {
> -			__s32 status;
> -			status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
> -					irq_event.irq, irq_event.level);
> -			if (ioctl == KVM_IRQ_LINE_STATUS) {
> -				r = -EFAULT;
> -				irq_event.status = status;
> -				if (copy_to_user(argp, &irq_event,
> -							sizeof irq_event))
> -					goto out;
> -			}
> -			r = 0;
> -		}
> -		break;
> -	}
>  	case KVM_GET_IRQCHIP: {
>  		/* 0: PIC master, 1: PIC slave, 2: IOAPIC */
>  		struct kvm_irqchip *chip;
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index e3c86f8..96aa7fb 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -494,6 +494,7 @@ int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
>  				   struct
>  				   kvm_userspace_memory_region *mem,
>  				   int user_alloc);
> +int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level);
>  long kvm_arch_vm_ioctl(struct file *filp,
>  		       unsigned int ioctl, unsigned long arg);
> 
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 636bd08..1d33877 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2093,6 +2093,25 @@ static long kvm_vm_ioctl(struct file *filp,
>  		break;
>  	}
>  #endif
> +#ifdef __KVM_HAVE_IRQ_LINE
> +	case KVM_IRQ_LINE_STATUS:
> +	case KVM_IRQ_LINE: {
> +		struct kvm_irq_level irq_event;
> +
> +		r = -EFAULT;
> +		if (copy_from_user(&irq_event, argp, sizeof irq_event))
> +			goto out;
> +
> +		r = kvm_vm_ioctl_irq_line(kvm, &irq_event);
> +
> +		if (ioctl == KVM_IRQ_LINE_STATUS) {
> +			if (copy_to_user(argp, &irq_event, sizeof irq_event))
> +				r = -EFAULT;
> +		}
> +
> +		break;
> +	}
> +#endif
>  	default:
>  		r = kvm_arch_vm_ioctl(filp, ioctl, arg);
>  		if (r == -ENOTTY)

Yup.  Note it brings in KVM_IRQ_LINE_STATUS for ARM.  I think it makes
sense if you have guests that do timekeeping by counting interrupts (as
opposed to reading a wall clock register).

-- 
error compiling committee.c: too many arguments to function



  reply	other threads:[~2012-06-19  8:49 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-15 19:06 [PATCH v8 00/15] KVM/ARM Implementation Christoffer Dall
2012-06-15 19:06 ` [PATCH v8 01/15] ARM: add mem_type prot_pte accessor Christoffer Dall
2012-06-15 19:07 ` [PATCH v8 02/15] KVM: use KVM_CAP_IRQ_ROUTING to protect the routing related code Christoffer Dall
2012-06-18 13:06   ` Avi Kivity
2012-06-15 19:07 ` [PATCH v8 03/15] KVM: Introduce __KVM_HAVE_IRQ_LINE Christoffer Dall
2012-06-18 13:07   ` Avi Kivity
2012-06-15 19:07 ` [PATCH v8 04/15] KVM: Guard mmu_notifier specific code with CONFIG_MMU_NOTIFIER Christoffer Dall
2012-06-18 13:08   ` Avi Kivity
2012-06-18 17:47     ` Christoffer Dall
2012-06-19  8:37       ` Avi Kivity
2012-06-28 21:28   ` Marcelo Tosatti
2012-06-15 19:07 ` [PATCH v8 05/15] ARM: KVM: Initial skeleton to compile KVM support Christoffer Dall
2012-06-15 19:07 ` [PATCH v8 06/15] ARM: KVM: Hypervisor identity mapping Christoffer Dall
2012-06-18 13:12   ` Avi Kivity
2012-06-18 17:55     ` Christoffer Dall
2012-06-19  8:38       ` Avi Kivity
2012-06-15 19:07 ` [PATCH v8 07/15] ARM: KVM: Hypervisor inititalization Christoffer Dall
2012-06-28 22:35   ` Marcelo Tosatti
2012-06-28 22:53     ` Christoffer Dall
2012-06-29  1:07       ` Marcelo Tosatti
2012-06-15 19:08 ` [PATCH v8 08/15] ARM: KVM: Module unloading support Christoffer Dall
2012-06-15 19:08 ` [PATCH v8 09/15] ARM: KVM: Memory virtualization setup Christoffer Dall
2012-06-21 12:29   ` Gleb Natapov
2012-06-21 19:48     ` Christoffer Dall
2012-06-28 22:34   ` Marcelo Tosatti
2012-06-28 22:51     ` Christoffer Dall
2012-06-15 19:08 ` [PATCH v8 10/15] ARM: KVM: Inject IRQs and FIQs from userspace Christoffer Dall
2012-06-18 13:32   ` Avi Kivity
2012-06-18 20:56     ` Christoffer Dall
2012-06-19  8:49       ` Avi Kivity [this message]
2012-06-20  3:17         ` Christoffer Dall
2012-06-15 19:08 ` [PATCH v8 11/15] ARM: KVM: World-switch implementation Christoffer Dall
2012-06-18 13:41   ` Avi Kivity
2012-06-18 22:05     ` Christoffer Dall
2012-06-19  9:16       ` Avi Kivity
2012-06-20  3:27         ` Christoffer Dall
2012-06-20  4:40           ` Christoffer Dall
2012-06-21  8:13             ` Avi Kivity
2012-06-21 17:54               ` Christoffer Dall
2012-07-02 13:07                 ` Avi Kivity
2012-06-15 19:08 ` [PATCH v8 12/15] ARM: KVM: Emulation framework and CP15 emulation Christoffer Dall
2012-06-15 19:09 ` [PATCH v8 13/15] ARM: KVM: Handle guest faults in KVM Christoffer Dall
2012-06-18 13:45   ` Avi Kivity
2012-06-18 22:20     ` Christoffer Dall
2012-06-19  9:32       ` Avi Kivity
2012-06-19 10:41         ` Andrea Arcangeli
2012-06-20 15:13           ` Christoffer Dall
2012-06-20 17:49             ` Andrea Arcangeli
2012-06-15 19:09 ` [PATCH v8 14/15] ARM: KVM: Handle I/O aborts Christoffer Dall
2012-06-18 13:48   ` Avi Kivity
2012-06-18 22:28     ` Christoffer Dall
2012-06-15 19:09 ` [PATCH v8 15/15] ARM: KVM: Guest wait-for-interrupts (WFI) support Christoffer Dall
2012-06-28 21:49 ` [PATCH v8 00/15] KVM/ARM Implementation Marcelo Tosatti
2012-06-28 22:44   ` Christoffer Dall

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=4FE03D19.4050301@redhat.com \
    --to=avi@redhat.com \
    --cc=android-virt@lists.cs.columbia.edu \
    --cc=c.dall@virtualopensystems.com \
    --cc=kvm@vger.kernel.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;
as well as URLs for NNTP newsgroup(s).