From: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
To: Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
Subject: Re: [PATCH] Add irqdevice interface + userint implementation
Date: Sun, 08 Apr 2007 09:47:33 +0300 [thread overview]
Message-ID: <46189005.2090609@qumranet.com> (raw)
In-Reply-To: <4614FF5C.BA47.005A.0-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
Gregory Haskins wrote:
> Hi All,
> The following is another patch that I broke out of the in-kernel-apic patch that I sent earlier. This focuses purely on the irqdevice abstraction without introducing the concept of the in-kernel LAPIC. It also provides an implementation of a "userint" model, which should support a system with a QEMU based emulation of the (A)PIC (e.g. current behavior). I have cleaned up quite a few things based on all of your comments as well, so hopefully its a little more polished than last time.
>
> As far as testing, I have confirmed that I can boot a 64-bit linux guest with no discernable difference in behavior.
>
> Note that this patch applies after the in-kernel-mmio.patch that I sent earlier today which has not yet been accepted/commited. This patch should not depend on it. However, if you do have problems applying it let me know and I can generate another one that is not after in-kernel-mmio in the series.
>
A patchset is fine.
> --- a/drivers/kvm/Makefile
> +++ b/drivers/kvm/Makefile
> @@ -2,7 +2,7 @@
> # Makefile for Kernel-based Virtual Machine module
> #
>
> -kvm-objs := kvm_main.o mmu.o x86_emulate.o
> +kvm-objs := kvm_main.o mmu.o x86_emulate.o kvm_userint.o
>
kvm_ prefixes are not needed for drivers/kvm/. kvm_main is an
historical exception.
> obj-$(CONFIG_KVM) += kvm.o
> kvm-intel-objs = vmx.o
> obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
> diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
> index c1923df..6caf60b 100644
> --- a/drivers/kvm/kvm.h
> +++ b/drivers/kvm/kvm.h
> @@ -13,6 +13,7 @@
> #include <linux/mm.h>
>
> #include "vmx.h"
> +#include "kvm_irqdevice.h"
>
Ditto.
> +
> +#ifndef __KVM_IRQDEVICE_H
> +#define __KVM_IRQDEVICE_H
> +
> +#define KVM_IRQFLAGS_NMI (1 << 0)
> +#define KVM_IRQFLAGS_PEEK (1 << 1)
>
is PEEK still needed?
> +
> +struct kvm_irqdevice;
> +
> +struct kvm_irqsink {
> + void (*raise_intr)(struct kvm_irqsink *this,
> + struct kvm_irqdevice *dev);
> +
> + void *private;
> +};
> +
> +struct kvm_irqdevice {
> + int (*pending)(struct kvm_irqdevice *this, int flags);
> + int (*read_vector)(struct kvm_irqdevice *this, int flags);
>
I'm a bit confused here. The kvm_irqsink mechanism implies a push
mechanism. ->pending and ->read_vector imply a pull mechanism.
> +
> +/*
> + * kvm_irq_init()
> + *
> + * Description:
> + * Initialized the kvm_irqdevice for use. Should be called before calling
> + * any derived implementation init functions
> + *
> + * Parameters:
> + * struct kvm_irqdevice *dev: This device
> + *
> + * Returns: (void)
> + */
>
This is infinitely better than the usual kvm documentation, but it would
be better still to follow kerneldoc.
> +static inline void kvm_irq_init(struct kvm_irqdevice *dev)
> +{
> + memset(dev, 0, sizeof(*dev));
> +}
> +
> +/*
> + * kvm_irq_pending()
> + *
> + * Description:
> + * Efficiently determines if an interrupt is pending on an irqdevice
> + *
> + * Parameters:
> + * struct kvm_irqdevice *dev: The device
> + * int flags: Modifies the behavior as follows:
> + *
> + * KVM_IRQFLAGS_NMI: Mask everything but NMIs
> + *
> + * Returns: (int)
> + * -1 = failure
> + * 0 = no iterrupts pending (per "flags" criteria)
> + * >0 = one or more interrupts are pending
> + */
> +static inline int kvm_irq_pending(struct kvm_irqdevice *dev, int flags)
> +{
> + return dev->pending(dev, flags);
> +}
>
Usually -errno is returned for failure. Can this reasonably fail,
though? it would simplify upper layers if it couldn't.
> +
> +/*
> + * kvm_irq_set_pin()
> + *
> + * Description:
> + * Allows the caller to assert/deassert an IRQ input pin to the device
> + * according to device policy.
> + *
> + * Parameters:
> + * struct kvm_irqdevice *dev: The device
> + * int pin: The input pin to alter
> + * int level: The value to set (1 = assert, 0 = deassert)
> + * int flags: Reserved, must be 0
>
Just remove it for now. When we find a use for it, we can add it. It's
only userspace interfaces that are brittle.
> + /* walk the interrupt-bitmap and inject an IRQ for each bit found */
> + for (i = 0; i < NR_IRQ_WORDS; ++i) {
> + unsigned long word = sregs->interrupt_bitmap[i];
> + while(word) {
>
spaceafterwhile. Also, can just use a single loop with __test_bit(), as
we're not performance critical here.
> + int bit_index = __ffs(word);
> + int irq = i * BITS_PER_LONG + bit_index;
> +
> + kvm_irq_set_pin(&vcpu->irq_dev, irq, 1, 0);
> +
> + clear_bit(bit_index, &word);
> + }
> + }
>
> set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
> set_segment(vcpu, &sregs->ds, VCPU_SREG_DS);
> @@ -2318,6 +2317,33 @@ out1:
>
> diff --git a/drivers/kvm/kvm_userint.c b/drivers/kvm/kvm_userint.c
> new file mode 100644
> index 0000000..ded3098
> --- /dev/null
> +++ b/drivers/kvm/kvm_userint.c
> @@ -0,0 +1,201 @@
> +/*
> + * kvm_userint.c: User Interrupts IRQ device
> + *
> + * This acts as an extention of an interrupt controller that exists elsewhere
> + * (typically in userspace/QEMU). Because this PIC is a pseudo device that
> + * is downstream from a real emulated PIC, the "IRQ-to-vector" mapping has
> + * already occured. Therefore, this PIC has the following unusal properties:
> + *
> + * 1) It has 256 "pins" which are literal vectors (e.g.no translation)
> + * 2) It only supports "auto-EOI" behavior since it is expected that the
> + * upstream emulated PIC will handle the real EOIs (if applicable)
> + * 3) It only listens to "asserts" on the pins (deasserts are dropped)
> + * because its an auto-EOI device anyway.
>
Wierd, but well explained.
> +static inline int bitarray_findhighest(struct bitarray *this)
> +{
> + if (!this->summary)
> + return -1;
> + else {
> + int word_index = __ffs(this->summary);
> + int bit_index = __ffs(this->pending[word_index]);
> +
> + return word_index * BITS_PER_LONG + bit_index;
> + }
> +}
>
Um, this is the lowest?
> +
> +/*----------------------------------------------------------------------
> + * userint interface - provides the actual kvm_irqdevice implementation
> + *---------------------------------------------------------------------*/
> +
> +typedef struct {
> + spinlock_t lock;
> + struct bitarray irq_pending;
> + int nmi_pending;
> +}kvm_userint;
>
No typedefs in kernel code for ordinary structs.
> +
> +static int userint_pending(struct kvm_irqdevice *this, int flags)
> +{
> + kvm_userint *s = (kvm_userint*)this->private;
> + int ret;
> +
> + spin_lock_irq(&s->lock);
> +
> + if (flags & KVM_IRQFLAGS_NMI)
> + ret = s->nmi_pending;
> + else
> + ret = bitarray_pending(&s->irq_pending);
>
You probably want:
ret = s->nmi_pending;
if (!(flags & KVM_IRQFLAGS_NMI))
ret |= bitarray_pending(...);
To avoid calling this twice when interrupts are enabled.
> +static int userint_read_vector(struct kvm_irqdevice *this, int flags)
> +{
> + kvm_userint *s = (kvm_userint*)this->private;
> + int irq;
> +
> + spin_lock_irq(&s->lock);
> +
> + /* NMIs take priority, so if there is an NMI pending, or
> + * if we are filtering out NMIs, only consider them
> + */
> + if (s->nmi_pending || (flags & KVM_IRQFLAGS_NMI))
> + irq = s->nmi_pending ? 2 : -1;
> + else
> + irq = bitarray_findhighest(&s->irq_pending);
>
Same here. Actually the comment is correct (even though it does not
start with a /* on a line by itself).
In general, looks very good. The interface is a bit over-rich
(->pending, ->read_vector, and irq_sink) but that's not a showstopper.
--
Do not meddle in the internals of kernels, for they are subtle and quick to panic.
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
next prev parent reply other threads:[~2007-04-08 6:47 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-05 18:53 [PATCH] Add irqdevice interface + userint implementation Gregory Haskins
2007-04-05 21:38 ` Fwd: " Gregory Haskins
[not found] ` <4614FF5C.BA47.005A.0-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
2007-04-08 6:47 ` Avi Kivity [this message]
[not found] ` <46189005.2090609-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-04-09 18:36 ` Gregory Haskins
[not found] ` <461A415C.BA47.005A.0-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
2007-04-10 7:52 ` Avi Kivity
[not found] ` <461B4241.5030101-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-04-10 11:36 ` Gregory Haskins
[not found] ` <461B3E61.BA47.005A.0-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
2007-04-10 12:01 ` Avi Kivity
[not found] ` <461B7C81.7040102-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-04-10 14:20 ` Gregory Haskins
[not found] ` <461B64E4.BA47.005A.0-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
2007-04-10 14:46 ` Avi Kivity
[not found] ` <461BA363.5080308-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-04-10 15:39 ` Gregory Haskins
2007-04-10 15:53 ` Fwd: " Gregory Haskins
[not found] ` <461B7AC6.BA47.005A.0-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
2007-04-10 16:11 ` Avi Kivity
[not found] ` <461BB738.7040206-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-04-10 17:58 ` Gregory Haskins
[not found] ` <461B7755.BA47.005A.0-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
2007-04-10 16:08 ` Avi Kivity
2007-04-08 9:58 ` Christoph Hellwig
[not found] ` <20070408095853.GA31284-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>
2007-04-08 10:23 ` Avi Kivity
[not found] ` <4618C293.8030902-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-04-08 10:33 ` Christoph Hellwig
2007-04-09 14:53 ` Gregory Haskins
-- strict thread matches above, loose matches on Subject: below --
2007-04-09 20:27 Gregory Haskins
[not found] ` <461A5B6C.BA47.005A.0-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
2007-04-10 7:33 ` Avi Kivity
2007-04-10 8:23 ` Christoph Hellwig
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=46189005.2090609@qumranet.com \
--to=avi-atkuwr5tajbwk0htik3j/w@public.gmane.org \
--cc=ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org \
--cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.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