# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 074b4b34e049269f25b3134bae8f6f1efd7b0cdb
# Parent cdd9e366aa59c07ae1dcdee7878f213a9a08339c
[HVM] VPIC (i8259) device model cleanups.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/hvm.c | 22 --
xen/arch/x86/hvm/i8259.c | 356 +++++++++++++++++++----------------------
xen/include/asm-x86/hvm/vpic.h | 5
xen/include/asm-x86/hvm/vpt.h | 29 ---
4 files changed, 186 insertions(+), 226 deletions(-)
diff -r cdd9e366aa59 -r 074b4b34e049 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Fri Nov 24 14:37:45 2006 +0000
+++ b/xen/arch/x86/hvm/hvm.c Fri Nov 24 15:42:14 2006 +0000
@@ -244,21 +244,13 @@ void hvm_vcpu_destroy(struct vcpu *v)
int cpu_get_interrupt(struct vcpu *v, int *type)
{
- int intno;
- struct vpic *vpic = domain_vpic(v->domain);
- unsigned long flags;
-
- if ( (intno = cpu_get_apic_interrupt(v, type)) != -1 ) {
- /* set irq request if a PIC irq is still pending */
- /* XXX: improve that */
- spin_lock_irqsave(vpic_lock(vpic), flags);
- pic_update_irq(vpic);
- spin_unlock_irqrestore(vpic_lock(vpic), flags);
- return intno;
- }
- /* read the irq from the PIC */
- if ( v->vcpu_id == 0 && (intno = cpu_get_pic_interrupt(v, type)) != -1 )
- return intno;
+ int irq;
+
+ if ( (irq = cpu_get_apic_interrupt(v, type)) != -1 )
+ return irq;
+
+ if ( (v->vcpu_id == 0) && ((irq = cpu_get_pic_interrupt(v, type)) != -1) )
+ return irq;
return -1;
}
diff -r cdd9e366aa59 -r 074b4b34e049 xen/arch/x86/hvm/i8259.c
--- a/xen/arch/x86/hvm/i8259.c Fri Nov 24 14:37:45 2006 +0000
+++ b/xen/arch/x86/hvm/i8259.c Fri Nov 24 15:42:14 2006 +0000
@@ -1,8 +1,9 @@
/*
- * QEMU 8259 interrupt controller emulation
+ * i8259 interrupt controller emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
* Copyright (c) 2005 Intel Corperation
+ * Copyright (c) 2006 Keir Fraser, XenSource Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -35,54 +36,60 @@
#include <asm/hvm/support.h>
#include <asm/current.h>
-#define hw_error(x) ((void)0)
-
-/* set irq level. If an edge is detected, then the IRR is set to 1 */
static inline void pic_set_irq1(PicState *s, int irq, int level)
{
- int mask;
-
- ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
-
- mask = 1 << irq;
- if (s->elcr & mask) {
- /* level triggered */
- if (level) {
+ int mask = 1 << irq;
+
+ ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
+
+ if ( s->elcr & mask )
+ {
+ /* Level triggered. */
+ if ( level )
+ {
s->irr |= mask;
s->last_irr |= mask;
- } else {
+ }
+ else
+ {
s->irr &= ~mask;
s->last_irr &= ~mask;
}
- } else {
- /* edge triggered */
- if (level) {
- if ((s->last_irr & mask) == 0)
+ }
+ else
+ {
+ /* Edge triggered. */
+ if ( level )
+ {
+ if ( (s->last_irr & mask) == 0 )
s->irr |= mask;
s->last_irr |= mask;
- } else {
+ }
+ else
+ {
s->last_irr &= ~mask;
}
}
}
-/* return the highest priority found in mask (highest = smallest
- number). Return 8 if no irq */
+/* Return the highest priority found in mask. Return 8 if no irq. */
static inline int get_priority(PicState *s, int mask)
{
int priority;
ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
- if (mask == 0)
+ if ( mask == 0 )
return 8;
+
priority = 0;
- while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
+ while ( (mask & (1 << ((priority + s->priority_add) & 7))) == 0 )
priority++;
+
return priority;
}
-/* return the pic wanted interrupt. return -1 if none */
+/* Return the PIC's highest priority pending interrupt. Return -1 if none. */
static int pic_get_irq(PicState *s)
{
int mask, cur_priority, priority;
@@ -91,42 +98,44 @@ static int pic_get_irq(PicState *s)
mask = s->irr & ~s->imr;
priority = get_priority(s, mask);
- if (priority == 8)
+ if ( priority == 8 )
return -1;
- /* compute current priority. If special fully nested mode on the
- master, the IRQ coming from the slave is not taken into account
- for the priority computation. */
+
+ /*
+ * Compute current priority. If special fully nested mode on the master,
+ * the IRQ coming from the slave is not taken into account for the
+ * priority computation.
+ */
mask = s->isr;
- if (s->special_fully_nested_mode && s == &s->pics_state->pics[0])
+ if ( s->special_fully_nested_mode && (s == &s->pics_state->pics[0]) )
mask &= ~(1 << 2);
cur_priority = get_priority(s, mask);
- if (priority < cur_priority) {
- /* higher priority found: an irq should be generated */
+ if ( priority < cur_priority )
+ /* Higher priority found: an irq should be generated. */
return (priority + s->priority_add) & 7;
- } else {
- return -1;
- }
-}
-
-/* raise irq to CPU if necessary. must be called every time the active
- irq may change */
-/* XXX: should not export it, but it is needed for an APIC kludge */
-void pic_update_irq(struct vpic *vpic)
+
+ return -1;
+}
+
+/* Raise irq to CPU if necessary. */
+static void pic_update_irq(struct vpic *vpic)
{
int irq2, irq;
ASSERT(spin_is_locked(vpic_lock(vpic)));
- /* first look at slave pic */
+ /* First look at slave PIC. */
irq2 = pic_get_irq(&vpic->pics[1]);
- if (irq2 >= 0) {
- /* if irq request by slave pic, signal master PIC */
+ if ( irq2 >= 0 )
+ {
+ /* If irq request by slave pic, signal master PIC. */
pic_set_irq1(&vpic->pics[0], 2, 1);
pic_set_irq1(&vpic->pics[0], 2, 0);
}
- /* look at requested irq */
+
+ /* Look at requested IRQ. */
irq = pic_get_irq(&vpic->pics[0]);
- if (irq >= 0)
+ if ( irq >= 0 )
vpic->irq_pending = 1;
}
@@ -137,53 +146,66 @@ void pic_set_irq(struct vpic *vpic, int
pic_update_irq(vpic);
}
-/* acknowledge interrupt 'irq' */
+/* Acknowledge interrupt @irq. */
static inline void pic_intack(PicState *s, int irq)
{
ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
- if (s->auto_eoi) {
- if (s->rotate_on_auto_eoi)
+ if ( s->auto_eoi )
+ {
+ if ( s->rotate_on_auto_eoi )
s->priority_add = (irq + 1) & 7;
- } else {
+ }
+ else
+ {
s->isr |= (1 << irq);
}
+
/* We don't clear a level sensitive interrupt here */
- if (!(s->elcr & (1 << irq)))
+ if ( !(s->elcr & (1 << irq)) )
s->irr &= ~(1 << irq);
}
static int pic_read_irq(struct vpic *vpic)
{
int irq, irq2, intno;
- unsigned long flags;
-
- spin_lock_irqsave(vpic_lock(vpic), flags);
+
+ spin_lock(vpic_lock(vpic));
+
irq = pic_get_irq(&vpic->pics[0]);
- if (irq >= 0) {
+ if ( irq >= 0 )
+ {
pic_intack(&vpic->pics[0], irq);
- if (irq == 2) {
+ if ( irq == 2 )
+ {
irq2 = pic_get_irq(&vpic->pics[1]);
- if (irq2 >= 0) {
+ if ( irq2 >= 0 )
+ {
pic_intack(&vpic->pics[1], irq2);
- } else {
- /* spurious IRQ on slave controller */
+ }
+ else
+ {
gdprintk(XENLOG_WARNING, "Spurious irq on slave i8259.\n");
irq2 = 7;
}
intno = vpic->pics[1].irq_base + irq2;
irq = irq2 + 8;
- } else {
+ }
+ else
+ {
intno = vpic->pics[0].irq_base + irq;
}
- } else {
- /* spurious IRQ on host controller */
+ }
+ else
+ {
irq = 7;
intno = vpic->pics[0].irq_base + irq;
gdprintk(XENLOG_WARNING, "Spurious irq on master i8259.\n");
}
+
pic_update_irq(vpic);
- spin_unlock_irqrestore(vpic_lock(vpic), flags);
+
+ spin_unlock(vpic_lock(vpic));
return intno;
}
@@ -191,8 +213,6 @@ static void pic_reset(void *opaque)
static void pic_reset(void *opaque)
{
PicState *s = opaque;
-
- ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
s->last_irr = 0;
s->irr = 0;
@@ -219,33 +239,34 @@ static void pic_ioport_write(void *opaqu
ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
addr &= 1;
- if (addr == 0) {
- if (val & 0x10) {
- /* init */
+ if ( addr == 0 )
+ {
+ if ( val & 0x10 )
+ {
pic_reset(s);
- /* deassert a pending interrupt */
s->pics_state->irq_pending = 0;
s->init_state = 1;
s->init4 = val & 1;
- if (val & 0x02)
- hw_error("single mode not supported");
- if (val & 0x08)
- hw_error("level sensitive irq not supported");
- } else if (val & 0x08) {
- if (val & 0x04)
+ }
+ else if ( val & 0x08 )
+ {
+ if ( val & 0x04 )
s->poll = 1;
- if (val & 0x02)
+ if ( val & 0x02 )
s->read_reg_select = val & 1;
- if (val & 0x40)
+ if ( val & 0x40 )
s->special_mask = (val >> 5) & 1;
- } else {
+ }
+ else
+ {
cmd = val >> 5;
- switch(cmd) {
+ switch ( cmd )
+ {
case 0:
case 4:
s->rotate_on_auto_eoi = cmd >> 2;
break;
- case 1: /* end of interrupt */
+ case 1:
case 5:
priority = get_priority(s, s->isr);
if (priority != 8) {
@@ -272,14 +293,15 @@ static void pic_ioport_write(void *opaqu
pic_update_irq(s->pics_state);
break;
default:
- /* no operation */
break;
}
}
- } else {
- switch(s->init_state) {
+ }
+ else
+ {
+ switch ( s->init_state )
+ {
case 0:
- /* normal mode */
s->imr = val;
pic_update_irq(s->pics_state);
break;
@@ -288,11 +310,7 @@ static void pic_ioport_write(void *opaqu
s->init_state = 2;
break;
case 2:
- if (s->init4) {
- s->init_state = 3;
- } else {
- s->init_state = 0;
- }
+ s->init_state = s->init4 ? 3 : 0;
break;
case 3:
s->special_fully_nested_mode = (val >> 4) & 1;
@@ -310,16 +328,20 @@ static uint32_t pic_poll_read (PicState
ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
ret = pic_get_irq(s);
- if (ret >= 0) {
- if (addr1 >> 7) {
+ if ( ret >= 0 )
+ {
+ if ( addr1 >> 7 )
+ {
s->pics_state->pics[0].isr &= ~(1 << 2);
s->pics_state->pics[0].irr &= ~(1 << 2);
}
s->irr &= ~(1 << ret);
s->isr &= ~(1 << ret);
- if (addr1 >> 7 || ret != 2)
+ if ( (addr1 >> 7) || (ret != 2) )
pic_update_irq(s->pics_state);
- } else {
+ }
+ else
+ {
ret = 0x07;
pic_update_irq(s->pics_state);
}
@@ -330,27 +352,19 @@ static uint32_t pic_ioport_read(void *op
static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
{
PicState *s = opaque;
- unsigned int addr;
- int ret;
-
- ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
-
- addr = addr1;
- addr &= 1;
- if (s->poll) {
- ret = pic_poll_read(s, addr1);
+
+ ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
+
+ if ( s->poll )
+ {
s->poll = 0;
- } else {
- if (addr == 0) {
- if (s->read_reg_select)
- ret = s->isr;
- else
- ret = s->irr;
- } else {
- ret = s->imr;
- }
- }
- return ret;
+ return pic_poll_read(s, addr1);
+ }
+
+ if ( (addr1 & 1) == 0 )
+ return (s->read_reg_select ? s->isr : s->irr);
+
+ return s->imr;
}
static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
@@ -368,92 +382,86 @@ static uint32_t elcr_ioport_read(void *o
return s->elcr;
}
-/* XXX: add generic master/slave system */
static void pic_init1(int io_addr, int elcr_addr, PicState *s)
{
- ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
-
pic_reset(s);
-
- /* XXX We set the ELCR to level triggered here, but that should
- really be done by the BIOS, and only for PCI IRQs. */
- s->elcr = 0xff & s->elcr_mask;
}
void pic_init(struct vpic *vpic)
{
- unsigned long flags;
-
memset(vpic, 0, sizeof(*vpic));
spin_lock_init(vpic_lock(vpic));
vpic->pics[0].pics_state = vpic;
vpic->pics[1].pics_state = vpic;
vpic->pics[0].elcr_mask = 0xf8;
vpic->pics[1].elcr_mask = 0xde;
- spin_lock_irqsave(vpic_lock(vpic), flags);
pic_init1(0x20, 0x4d0, &vpic->pics[0]);
pic_init1(0xa0, 0x4d1, &vpic->pics[1]);
- spin_unlock_irqrestore(vpic_lock(vpic), flags);
}
static int intercept_pic_io(ioreq_t *p)
{
- struct vpic *pic;
+ struct vpic *vpic = domain_vpic(current->domain);
uint32_t data;
- unsigned long flags;
-
- if ( p->size != 1 || p->count != 1 ) {
- printk("PIC_IO wrong access size %d!\n", (int)p->size);
+
+ if ( (p->size != 1) || (p->count != 1) )
+ {
+ gdprintk(XENLOG_WARNING,
+ "PIC_IO wrong access size %d!\n", (int)p->size);
return 1;
}
- pic = domain_vpic(current->domain);
- if ( p->dir == IOREQ_WRITE ) {
+ if ( p->dir == IOREQ_WRITE )
+ {
if ( p->data_is_ptr )
(void)hvm_copy_from_guest_phys(&data, p->data, p->size);
else
data = p->data;
- spin_lock_irqsave(vpic_lock(pic), flags);
- pic_ioport_write((void*)&pic->pics[p->addr>>7],
+ spin_lock(vpic_lock(vpic));
+ pic_ioport_write((void*)&vpic->pics[p->addr>>7],
(uint32_t) p->addr, (uint32_t) (data & 0xff));
- spin_unlock_irqrestore(vpic_lock(pic), flags);
- }
- else {
- spin_lock_irqsave(vpic_lock(pic), flags);
+ spin_unlock(vpic_lock(vpic));
+ }
+ else
+ {
+ spin_lock(vpic_lock(vpic));
data = pic_ioport_read(
- (void*)&pic->pics[p->addr>>7], (uint32_t) p->addr);
- spin_unlock_irqrestore(vpic_lock(pic), flags);
+ (void*)&vpic->pics[p->addr>>7], (uint32_t) p->addr);
+ spin_unlock(vpic_lock(vpic));
if ( p->data_is_ptr )
(void)hvm_copy_to_guest_phys(p->data, &data, p->size);
else
p->data = (u64)data;
}
+
return 1;
}
static int intercept_elcr_io(ioreq_t *p)
{
- struct vpic *vpic;
+ struct vpic *vpic = domain_vpic(current->domain);
uint32_t data;
- unsigned long flags;
-
- if ( p->size != 1 || p->count != 1 ) {
- printk("PIC_IO wrong access size %d!\n", (int)p->size);
+
+ if ( (p->size != 1) || (p->count != 1) )
+ {
+ gdprintk(XENLOG_WARNING,
+ "PIC_IO wrong access size %d!\n", (int)p->size);
return 1;
}
- vpic = domain_vpic(current->domain);
- if ( p->dir == IOREQ_WRITE ) {
+ if ( p->dir == IOREQ_WRITE )
+ {
if ( p->data_is_ptr )
(void)hvm_copy_from_guest_phys(&data, p->data, p->size);
else
data = p->data;
- spin_lock_irqsave(vpic_lock(vpic), flags);
+ spin_lock(vpic_lock(vpic));
elcr_ioport_write((void*)&vpic->pics[p->addr&1],
(uint32_t) p->addr, (uint32_t)( data & 0xff));
- spin_unlock_irqrestore(vpic_lock(vpic), flags);
- }
- else {
+ spin_unlock(vpic_lock(vpic));
+ }
+ else
+ {
data = (u64) elcr_ioport_read(
(void*)&vpic->pics[p->addr&1], (uint32_t) p->addr);
if ( p->data_is_ptr )
@@ -461,6 +469,7 @@ static int intercept_elcr_io(ioreq_t *p)
else
p->data = (u64)data;
}
+
return 1;
}
@@ -472,21 +481,18 @@ void register_pic_io_hook(struct domain
register_portio_handler(d, 0x4d1, 1, intercept_elcr_io);
}
-
-/* IRQ handling */
int cpu_get_pic_interrupt(struct vcpu *v, int *type)
{
int intno;
struct vpic *vpic = domain_vpic(v->domain);
- struct hvm_domain *plat = &v->domain->arch.hvm_domain;
if ( !vlapic_accept_pic_intr(v) )
return -1;
- if ( xchg(&plat->irq.vpic.irq_pending, 0) == 0 )
+ if ( xchg(&vpic->irq_pending, 0) == 0 )
return -1;
- /* read the irq from the PIC */
+ /* Read the irq from the PIC. */
intno = pic_read_irq(vpic);
*type = APIC_DM_EXTINT;
return intno;
@@ -495,35 +501,15 @@ int is_periodic_irq(struct vcpu *v, int
int is_periodic_irq(struct vcpu *v, int irq, int type)
{
int vec;
- struct periodic_time *pt =
- &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
-
- if (pt->irq == 0) { /* Is it pit irq? */
- if (type == APIC_DM_EXTINT)
- vec = domain_vpic(v->domain)->pics[0].irq_base;
- else
- vec = domain_vioapic(v->domain)->redirtbl[0].fields.vector;
-
- if (irq == vec)
- return 1;
- }
-
- return 0;
-}
-
-int is_irq_enabled(struct vcpu *v, int irq)
-{
- struct vioapic *vioapic = domain_vioapic(v->domain);
- struct vpic *vpic = domain_vpic(v->domain);
-
- if (vioapic->redirtbl[irq].fields.mask == 0)
- return 1;
-
- if ( irq & 8 ) {
- return !( (1 << (irq&7)) & vpic->pics[1].imr);
- }
- else {
- return !( (1 << irq) & vpic->pics[0].imr);
- }
-}
-
+ struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
+
+ if ( pt->irq != 0 )
+ return 0;
+
+ if ( type == APIC_DM_EXTINT )
+ vec = domain_vpic(v->domain)->pics[0].irq_base;
+ else
+ vec = domain_vioapic(v->domain)->redirtbl[0].fields.vector;
+
+ return (irq == vec);
+}
diff -r cdd9e366aa59 -r 074b4b34e049 xen/include/asm-x86/hvm/vpic.h
--- a/xen/include/asm-x86/hvm/vpic.h Fri Nov 24 14:37:45 2006 +0000
+++ b/xen/include/asm-x86/hvm/vpic.h Fri Nov 24 15:42:14 2006 +0000
@@ -1,8 +1,9 @@
/*
- * QEMU System Emulator header
+ * i8259 interrupt controller emulation
*
* Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2005 Intel Corp
+ * Copyright (c) 2006 Keir Fraser, XenSource Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -59,10 +60,8 @@ struct vpic {
void pic_set_irq(struct vpic *vpic, int irq, int level);
void pic_init(struct vpic *vpic);
-void pic_update_irq(struct vpic *vpic); /* Caller must hold vpic->lock */
void register_pic_io_hook(struct domain *d);
int cpu_get_pic_interrupt(struct vcpu *v, int *type);
int is_periodic_irq(struct vcpu *v, int irq, int type);
-int is_irq_enabled(struct vcpu *v, int irq);
#endif /* __ASM_X86_HVM_VPIC_H__ */
diff -r cdd9e366aa59 -r 074b4b34e049 xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h Fri Nov 24 14:37:45 2006 +0000
+++ b/xen/include/asm-x86/hvm/vpt.h Fri Nov 24 15:42:14 2006 +0000
@@ -111,36 +111,19 @@ struct pl_time { /* platform time */
struct PMTState vpmt;
};
-static __inline__ s_time_t get_scheduled(
- struct vcpu *v, int irq,
- struct periodic_time *pt)
+extern u64 hvm_get_guest_time(struct vcpu *v);
+static inline int64_t hvm_get_clock(struct vcpu *v)
{
- if ( is_irq_enabled(v, irq) ) {
- return pt->scheduled;
- }
- else
- return -1;
+ return hvm_get_guest_time(v);
}
-extern u64 hvm_get_guest_time(struct vcpu *v);
-/*
- * get processor time.
- * unit: TSC
- */
-static __inline__ int64_t hvm_get_clock(struct vcpu *v)
-{
- uint64_t gtsc;
-
- gtsc = hvm_get_guest_time(v);
- return gtsc;
-}
-
-#define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency)
+#define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency)
/* to hook the ioreq packet to get the PIT initialization info */
extern void hvm_hooks_assist(struct vcpu *v);
extern void pickup_deactive_ticks(struct periodic_time *vpit);
-extern struct periodic_time *create_periodic_time(u32 period, char irq, char
one_shot, time_cb *cb, void *data);
+extern struct periodic_time *create_periodic_time(
+ u32 period, char irq, char one_shot, time_cb *cb, void *data);
extern void destroy_periodic_time(struct periodic_time *pt);
void pit_init(struct vcpu *v, unsigned long cpu_khz);
void rtc_init(struct vcpu *v, int base, int irq);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|