[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] VPIC (i8259) device model cleanups.
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |