| Submitter | Glauber Costa |
|---|---|
| Date | Sept. 28, 2009, 9:15 p.m. |
| Message ID | <1254172517-28216-2-git-send-email-glommer@redhat.com> |
| Download | mbox | patch |
| Permalink | /patch/34395/ |
| State | Superseded |
| Headers | show |
Comments
On Mon, Sep 28, 2009 at 11:50:46PM +0200, Juan Quintela wrote: > Glauber Costa <glommer@redhat.com> wrote: > > This patch provides kvm with an in-kernel ioapic. We are currently not enabling it. > > The code is heavily based on what's in qemu-kvm.git. > > > > Signed-off-by: Glauber Costa <glommer@redhat.com> > > > base_address IOAPICState field missing. > > > +#if defined(KVM_CAP_IRQCHIP) && defined(TARGET_I386) > > +static void kvm_kernel_ioapic_load_from_user(IOAPICState *s) > > +{ > > + struct kvm_irqchip chip; > > + struct kvm_ioapic_state *kioapic; > > + int i; > > + > > if (!kvm_enabled() || !kvm_irqchip_in_kernel()) { > return; No need. if this function is ever called and this is not true, this is a bug. > > > + chip.chip_id = KVM_IRQCHIP_IOAPIC; > > + kioapic = &chip.chip.ioapic; > > + > > + kioapic->id = s->id; > > + kioapic->ioregsel = s->ioregsel; > > + kioapic->base_address = IOAPIC_DEFAULT_BASE_ADDRESS; > > + kioapic->irr = s->irr; > > + for (i = 0; i < IOAPIC_NUM_PINS; i++) { > > + kioapic->redirtbl[i].bits = s->ioredtbl[i]; > > + } > > + > > + kvm_set_irqchip(&chip); > > +} > > + > > +static void kvm_kernel_ioapic_save_to_user(IOAPICState *s) > > +{ > > + struct kvm_irqchip chip; > > + struct kvm_ioapic_state *kioapic; > > + int i; > > if (!kvm_enabled() || !kvm_irqchip_in_kernel()) { > return; ditto. > > > + chip.chip_id = KVM_IRQCHIP_IOAPIC; > > + kvm_get_irqchip(&chip); > > + kioapic = &chip.chip.ioapic; > > + > > + s->id = kioapic->id; > > + s->ioregsel = kioapic->ioregsel; > > + s->irr = kioapic->irr; > > + for (i = 0; i < IOAPIC_NUM_PINS; i++) { > > + s->ioredtbl[i] = kioapic->redirtbl[i].bits; > > + } > > +} > > +#endif > > + > > +static void ioapic_pre_save(const void *opaque) > > +{ > > +#if defined(KVM_CAP_IRQCHIP) && defined(TARGET_I386) > > + IOAPICState *s = (void *)opaque; > > + > > + if (kvm_enabled() && kvm_irqchip_in_kernel()) { > > Can we put this test inside the functions? Yes, I know that qemu-kvm > uses always this syntax, but it just makes the API simpler to use. I am not sure if we are aiming for a simpler api here. Those functions should never be called if we're not using in-kernel irqchip, and it is probably better to have callers to enforce it. > > > + kvm_kernel_ioapic_save_to_user(s); > > + } > > +#endif > > +} > > + > > +static int ioapic_pre_load(void *opaque) > > +{ > > + IOAPICState *s = opaque; > > + > > + /* in case we are doing version 1, we just set these to sane > > values */ > > You forgot to update vmstate_ioapic to version 2. ok. > > > + s->irr = 0; > > + return 0; > > +} > > + > > +static int ioapic_post_load(void *opaque) > > +{ > > +#if defined(KVM_CAP_IRQCHIP) && defined(TARGET_I386) > > + IOAPICState *s = opaque; > > + > > + if (kvm_enabled() && kvm_irqchip_in_kernel()) { > > + kvm_kernel_ioapic_load_from_user(s); > > + } > > +#endif > > + return 0; > > +} > > + > > + > > static const VMStateDescription vmstate_ioapic = { > > .name = "ioapic", > > .version_id = 1, > > @@ -201,7 +276,10 @@ static const VMStateDescription vmstate_ioapic = { > > VMSTATE_UINT8(ioregsel, IOAPICState), > > VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICState, IOAPIC_NUM_PINS), > > VMSTATE_END_OF_LIST() > > - } > > + }, > > + .pre_load = ioapic_pre_load, > > + .post_load = ioapic_post_load, > > + .pre_save = ioapic_pre_save, > > }; >
Patch
diff --git a/hw/ioapic.c b/hw/ioapic.c index b0ad78f..3af86f1 100644 --- a/hw/ioapic.c +++ b/hw/ioapic.c @@ -24,10 +24,12 @@ #include "pc.h" #include "qemu-timer.h" #include "host-utils.h" +#include "kvm.h" //#define DEBUG_IOAPIC #define IOAPIC_NUM_PINS 0x18 +#define IOAPIC_DEFAULT_BASE_ADDRESS 0xfec00000 #define IOAPIC_LVT_MASKED (1<<16) #define IOAPIC_TRIGGER_EDGE 0 @@ -191,6 +193,79 @@ static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va } } +#if defined(KVM_CAP_IRQCHIP) && defined(TARGET_I386) +static void kvm_kernel_ioapic_load_from_user(IOAPICState *s) +{ + struct kvm_irqchip chip; + struct kvm_ioapic_state *kioapic; + int i; + + chip.chip_id = KVM_IRQCHIP_IOAPIC; + kioapic = &chip.chip.ioapic; + + kioapic->id = s->id; + kioapic->ioregsel = s->ioregsel; + kioapic->base_address = IOAPIC_DEFAULT_BASE_ADDRESS; + kioapic->irr = s->irr; + for (i = 0; i < IOAPIC_NUM_PINS; i++) { + kioapic->redirtbl[i].bits = s->ioredtbl[i]; + } + + kvm_set_irqchip(&chip); +} + +static void kvm_kernel_ioapic_save_to_user(IOAPICState *s) +{ + struct kvm_irqchip chip; + struct kvm_ioapic_state *kioapic; + int i; + + chip.chip_id = KVM_IRQCHIP_IOAPIC; + kvm_get_irqchip(&chip); + kioapic = &chip.chip.ioapic; + + s->id = kioapic->id; + s->ioregsel = kioapic->ioregsel; + s->irr = kioapic->irr; + for (i = 0; i < IOAPIC_NUM_PINS; i++) { + s->ioredtbl[i] = kioapic->redirtbl[i].bits; + } +} +#endif + +static void ioapic_pre_save(const void *opaque) +{ +#if defined(KVM_CAP_IRQCHIP) && defined(TARGET_I386) + IOAPICState *s = (void *)opaque; + + if (kvm_enabled() && kvm_irqchip_in_kernel()) { + kvm_kernel_ioapic_save_to_user(s); + } +#endif +} + +static int ioapic_pre_load(void *opaque) +{ + IOAPICState *s = opaque; + + /* in case we are doing version 1, we just set these to sane values */ + s->irr = 0; + return 0; +} + +static int ioapic_post_load(void *opaque) +{ +#if defined(KVM_CAP_IRQCHIP) && defined(TARGET_I386) + IOAPICState *s = opaque; + + if (kvm_enabled() && kvm_irqchip_in_kernel()) { + kvm_kernel_ioapic_load_from_user(s); + } +#endif + return 0; +} + + static const VMStateDescription vmstate_ioapic = { .name = "ioapic", .version_id = 1, @@ -201,7 +276,10 @@ static const VMStateDescription vmstate_ioapic = { VMSTATE_UINT8(ioregsel, IOAPICState), VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICState, IOAPIC_NUM_PINS), VMSTATE_END_OF_LIST() - } + }, + .pre_load = ioapic_pre_load, + .post_load = ioapic_post_load, + .pre_save = ioapic_pre_save, }; static void ioapic_reset(void *opaque) @@ -212,6 +290,11 @@ static void ioapic_reset(void *opaque) memset(s, 0, sizeof(*s)); for(i = 0; i < IOAPIC_NUM_PINS; i++) s->ioredtbl[i] = 1 << 16; /* mask LVT */ +#ifdef KVM_CAP_IRQCHIP + if (kvm_enabled() && kvm_irqchip_in_kernel()) { + kvm_kernel_ioapic_load_from_user(s); + } +#endif } static CPUReadMemoryFunc * const ioapic_mem_read[3] = { diff --git a/kvm-all.c b/kvm-all.c index f8a05cc..ff439a5 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -411,6 +411,26 @@ int kvm_check_extension(KVMState *s, unsigned int extension) return ret; } +#ifdef KVM_CAP_IRQCHIP +int kvm_set_irqchip(struct kvm_irqchip *chip) +{ + if (!kvm_state->irqchip_in_kernel) { + return 0; + } + + return kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); +} + +int kvm_get_irqchip(struct kvm_irqchip *chip) +{ + if (!kvm_state->irqchip_in_kernel) { + return 0; + } + + return kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip); +} +#endif + int kvm_init(int smp_cpus) { static const char upgrade_note[] = diff --git a/kvm.h b/kvm.h index e7d5beb..8d4afa0 100644 --- a/kvm.h +++ b/kvm.h @@ -16,6 +16,7 @@ #include "config.h" #include "qemu-queue.h" +#include <linux/kvm.h> #ifdef CONFIG_KVM extern int kvm_allowed; @@ -63,6 +64,9 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap); int kvm_pit_in_kernel(void); int kvm_irqchip_in_kernel(void); +int kvm_set_irqchip(struct kvm_irqchip *chip); +int kvm_get_irqchip(struct kvm_irqchip *chip); + /* internal API */ struct KVMState;
This patch provides kvm with an in-kernel ioapic. We are currently not enabling it. The code is heavily based on what's in qemu-kvm.git. Signed-off-by: Glauber Costa <glommer@redhat.com> --- hw/ioapic.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- kvm-all.c | 20 ++++++++++++++ kvm.h | 4 +++ 3 files changed, 108 insertions(+), 1 deletions(-)