ia64/xen-unstable

changeset 7477:2d5b92e7c79a

This is a follow up of PIC device model by Xiaofeng and me to move to
hypervisor using virtual weired interrupt line. With this patch the
performance of CPU2K improves 7%, kernel kuild improves 14% and
cyclesoak improves 12%. It is quite amazing!

Signed-off-by: Xiaofeng Ling <xiaofeng.ling@intel.com>
Signed-off-by: Eddie Dong <eddie.dong@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Oct 21 18:29:26 2005 +0100 (2005-10-21)
parents 8eaaa622db81
children 17a9f111fa93
files tools/ioemu/hw/i8254.c tools/ioemu/hw/i8259_stub.c tools/ioemu/target-i386-dm/Makefile tools/ioemu/target-i386-dm/helper2.c xen/arch/x86/Makefile xen/arch/x86/dm/i8259.c xen/arch/x86/domain.c xen/arch/x86/vmx.c xen/arch/x86/vmx_intercept.c xen/arch/x86/vmx_io.c xen/arch/x86/vmx_vmcs.c xen/include/asm-x86/vmx.h xen/include/asm-x86/vmx_intercept.h xen/include/asm-x86/vmx_platform.h xen/include/asm-x86/vmx_virpit.h xen/include/public/io/ioreq.h xen/include/public/io/vmx_vpic.h
line diff
     1.1 --- a/tools/ioemu/hw/i8254.c	Fri Oct 21 18:19:38 2005 +0100
     1.2 +++ b/tools/ioemu/hw/i8254.c	Fri Oct 21 18:29:26 2005 +0100
     1.3 @@ -222,9 +222,7 @@ void pit_reset_vmx_vectors()
     1.4      int irq, i;
     1.5      PITChannelState *s;
     1.6  
     1.7 -    /* Assumes PIT is wired to IRQ0 and -1 is uninitialized irq base */
     1.8 -    if ((irq = pic_irq2vec(0)) == -1)
     1.9 -        return;
    1.10 +    irq = 0;
    1.11  
    1.12      for(i = 0; i < 3; i++) {
    1.13          if (pit_state.channels[i].vmx_channel)
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/ioemu/hw/i8259_stub.c	Fri Oct 21 18:29:26 2005 +0100
     2.3 @@ -0,0 +1,96 @@
     2.4 +/* Xen 8259 stub for interrupt controller emulation
     2.5 + * 
     2.6 + * Copyright (c) 2003-2004 Fabrice Bellard
     2.7 + * Copyright (c) 2005      Intel corperation
     2.8 + * 
     2.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    2.10 + * of this software and associated documentation files (the "Software"), to deal
    2.11 + * in the Software without restriction, including without limitation the rights
    2.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    2.13 + * copies of the Software, and to permit persons to whom the Software is
    2.14 + * furnished to do so, subject to the following conditions:
    2.15 + *
    2.16 + * The above copyright notice and this permission notice shall be included in
    2.17 + * all copies or substantial portions of the Software.
    2.18 + *
    2.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    2.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    2.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    2.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    2.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    2.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    2.25 + * THE SOFTWARE.
    2.26 + */
    2.27 +#include "xenctrl.h"
    2.28 +#include <xen/io/ioreq.h>
    2.29 +#include <stdio.h>
    2.30 +#include "cpu.h"
    2.31 +#include "cpu-all.h"
    2.32 +
    2.33 +static __inline__ void atomic_set_bit(long nr, volatile void *addr)
    2.34 +{
    2.35 +        __asm__ __volatile__(
    2.36 +                "lock ; bts %1,%0"
    2.37 +                :"=m" (*(volatile long *)addr)
    2.38 +                :"dIr" (nr));
    2.39 +}
    2.40 +static __inline__ void atomic_clear_bit(long nr, volatile void *addr)
    2.41 +{
    2.42 +        __asm__ __volatile__(
    2.43 +                "lock ; btr %1,%0"
    2.44 +                :"=m" (*(volatile long *)addr)
    2.45 +                :"dIr" (nr));
    2.46 +}
    2.47 +
    2.48 +#include <vl.h>
    2.49 +extern shared_iopage_t *shared_page;
    2.50 +extern CPUState *global_env;
    2.51 +void pic_set_irq(int irq, int level)
    2.52 +{
    2.53 +    global_iodata_t  *gio;
    2.54 +    int  mask;
    2.55 +
    2.56 +    gio = &shared_page->sp_global;
    2.57 +    mask = 1 << irq;
    2.58 +    if ( gio->pic_elcr & mask ) {
    2.59 +        /* level */
    2.60 +       if ( level ) {
    2.61 +           atomic_set_bit(irq, &gio->pic_irr);
    2.62 +           atomic_clear_bit(irq, &gio->pic_clear_irr);
    2.63 +           global_env->send_event = 1;
    2.64 +       }
    2.65 +       else {
    2.66 +           atomic_set_bit(irq, &gio->pic_clear_irr);
    2.67 +           atomic_clear_bit(irq, &gio->pic_irr);
    2.68 +           global_env->send_event = 1;
    2.69 +       }
    2.70 +    }
    2.71 +    else {
    2.72 +       /* edge */
    2.73 +       if ( level ) {
    2.74 +           if ( (mask & gio->pic_last_irr) == 0 ) { 
    2.75 +               atomic_set_bit(irq, &gio->pic_irr);
    2.76 +               atomic_set_bit(irq, &gio->pic_last_irr);
    2.77 +               global_env->send_event = 1;
    2.78 +           }
    2.79 +       }
    2.80 +       else {
    2.81 +           atomic_clear_bit(irq, &gio->pic_last_irr);
    2.82 +       }
    2.83 +    }
    2.84 +}
    2.85 +
    2.86 +void irq_info(void)
    2.87 +{
    2.88 +    term_printf("irq statistic code not compiled.\n");
    2.89 +}
    2.90 +
    2.91 +void pic_info(void)
    2.92 +{
    2.93 +    term_printf("pic_infoi code not compiled.\n");
    2.94 +}
    2.95 +
    2.96 +void pic_init(void)
    2.97 +{
    2.98 +}
    2.99 +
     3.1 --- a/tools/ioemu/target-i386-dm/Makefile	Fri Oct 21 18:19:38 2005 +0100
     3.2 +++ b/tools/ioemu/target-i386-dm/Makefile	Fri Oct 21 18:29:26 2005 +0100
     3.3 @@ -271,7 +271,7 @@ endif
     3.4  
     3.5  # Hardware support
     3.6  VL_OBJS+= ide.o ne2000.o pckbd.o vga.o dma.o
     3.7 -VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o port-e9.o
     3.8 +VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259_stub.o i8254.o pc.o port-e9.o
     3.9  VL_OBJS+= cirrus_vga.o pcnet.o
    3.10  
    3.11  ifeq ($(TARGET_ARCH), ppc)
     4.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Fri Oct 21 18:19:38 2005 +0100
     4.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Fri Oct 21 18:29:26 2005 +0100
     4.3 @@ -404,20 +404,6 @@ static __inline__ void atomic_set_bit(lo
     4.4  }
     4.5  
     4.6  void
     4.7 -do_interrupt(CPUState *env, int vector)
     4.8 -{
     4.9 -	unsigned long *intr;
    4.10 -
    4.11 -	// Send a message on the event channel. Add the vector to the shared mem
    4.12 -	// page.
    4.13 -	intr = (unsigned long *) &(shared_page->sp_global.pic_intr[0]);
    4.14 -	atomic_set_bit(vector, intr);
    4.15 -        if (loglevel & CPU_LOG_INT)
    4.16 -                fprintf(logfile, "injecting vector: %x\n", vector);
    4.17 -	env->send_event = 1;
    4.18 -}
    4.19 -
    4.20 -void
    4.21  destroy_vmx_domain(void)
    4.22  {
    4.23      extern FILE* logfile;
    4.24 @@ -429,7 +415,6 @@ destroy_vmx_domain(void)
    4.25  
    4.26  int main_loop(void)
    4.27  {
    4.28 -	int vector;
    4.29   	fd_set rfds;
    4.30  	struct timeval tv;
    4.31  	extern CPUState *global_env;
    4.32 @@ -476,11 +461,6 @@ int main_loop(void)
    4.33  		ioapic_update_EOI();
    4.34  #endif
    4.35  		cpu_timer_handler(env);
    4.36 -		if (env->interrupt_request & CPU_INTERRUPT_HARD) {
    4.37 -                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
    4.38 -			vector = cpu_get_pic_interrupt(env); 
    4.39 -			do_interrupt(env, vector);
    4.40 -		}
    4.41  #ifdef APIC_SUPPORT
    4.42  		if (ioapic_has_intr())
    4.43                      do_ioapic();
     5.1 --- a/xen/arch/x86/Makefile	Fri Oct 21 18:19:38 2005 +0100
     5.2 +++ b/xen/arch/x86/Makefile	Fri Oct 21 18:29:26 2005 +0100
     5.3 @@ -4,6 +4,7 @@ include $(BASEDIR)/Rules.mk
     5.4  OBJS += $(patsubst %.S,%.o,$(wildcard $(TARGET_SUBARCH)/*.S))
     5.5  OBJS += $(patsubst %.c,%.o,$(wildcard $(TARGET_SUBARCH)/*.c))
     5.6  OBJS += $(patsubst %.c,%.o,$(wildcard acpi/*.c))
     5.7 +OBJS += $(patsubst %.c,%.o,$(wildcard dm/*.c))
     5.8  OBJS += $(patsubst %.c,%.o,$(wildcard mtrr/*.c))
     5.9  OBJS += $(patsubst %.c,%.o,$(wildcard genapic/*.c))
    5.10  OBJS += $(patsubst %.c,%.o,$(wildcard cpu/*.c))
    5.11 @@ -66,6 +67,7 @@ clean:
    5.12  	rm -f x86_64/*.o x86_64/*~ x86_64/core
    5.13  	rm -f mtrr/*.o mtrr/*~ mtrr/core
    5.14  	rm -f acpi/*.o acpi/*~ acpi/core
    5.15 +	rm -f dm/*.o dm/*~ dm/core
    5.16  	rm -f genapic/*.o genapic/*~ genapic/core
    5.17  	rm -f cpu/*.o cpu/*~ cpu/core
    5.18  
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/arch/x86/dm/i8259.c	Fri Oct 21 18:29:26 2005 +0100
     6.3 @@ -0,0 +1,520 @@
     6.4 +/*
     6.5 + * QEMU 8259 interrupt controller emulation
     6.6 + * 
     6.7 + * Copyright (c) 2003-2004 Fabrice Bellard
     6.8 + * Copyright (c) 2005 Intel Corperation
     6.9 + * 
    6.10 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    6.11 + * of this software and associated documentation files (the "Software"), to deal
    6.12 + * in the Software without restriction, including without limitation the rights
    6.13 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    6.14 + * copies of the Software, and to permit persons to whom the Software is
    6.15 + * furnished to do so, subject to the following conditions:
    6.16 + *
    6.17 + * The above copyright notice and this permission notice shall be included in
    6.18 + * all copies or substantial portions of the Software.
    6.19 + *
    6.20 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    6.21 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    6.22 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    6.23 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    6.24 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    6.25 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    6.26 + * THE SOFTWARE.
    6.27 + */
    6.28 +#include <xen/config.h>
    6.29 +#include <xen/types.h>
    6.30 +#include <xen/mm.h>
    6.31 +#include <xen/xmalloc.h>
    6.32 +#include <xen/lib.h>
    6.33 +#include <xen/errno.h>
    6.34 +#include <xen/sched.h>
    6.35 +#include <public/io/ioreq.h>
    6.36 +#include <asm/vmx.h>
    6.37 +#include <public/io/vmx_vpic.h>
    6.38 +#include <public/io/vmx_vlapic.h>
    6.39 +#include <asm/current.h>
    6.40 +
    6.41 +/* set irq level. If an edge is detected, then the IRR is set to 1 */
    6.42 +static inline void pic_set_irq1(PicState *s, int irq, int level)
    6.43 +{
    6.44 +    int mask;
    6.45 +    mask = 1 << irq;
    6.46 +    if (s->elcr & mask) {
    6.47 +        /* level triggered */
    6.48 +        if (level) {
    6.49 +            s->irr |= mask;
    6.50 +            s->last_irr |= mask;
    6.51 +        } else {
    6.52 +            s->irr &= ~mask;
    6.53 +            s->last_irr &= ~mask;
    6.54 +        }
    6.55 +    } else {
    6.56 +        /* edge triggered */
    6.57 +        if (level) {
    6.58 +            if ((s->last_irr & mask) == 0) {
    6.59 +                s->irr |= mask;
    6.60 +	    }
    6.61 +            s->last_irr |= mask;
    6.62 +        } else {
    6.63 +            s->last_irr &= ~mask;
    6.64 +        }
    6.65 +    }
    6.66 +}
    6.67 +
    6.68 +/* return the highest priority found in mask (highest = smallest
    6.69 +   number). Return 8 if no irq */
    6.70 +static inline int get_priority(PicState *s, int mask)
    6.71 +{
    6.72 +    int priority;
    6.73 +    if (mask == 0)
    6.74 +        return 8;
    6.75 +    priority = 0;
    6.76 +    while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
    6.77 +        priority++;
    6.78 +    return priority;
    6.79 +}
    6.80 +
    6.81 +/* return the pic wanted interrupt. return -1 if none */
    6.82 +static int pic_get_irq(PicState *s)
    6.83 +{
    6.84 +    int mask, cur_priority, priority;
    6.85 +
    6.86 +    mask = s->irr & ~s->imr;
    6.87 +    priority = get_priority(s, mask);
    6.88 +    if (priority == 8)
    6.89 +        return -1;
    6.90 +    /* compute current priority. If special fully nested mode on the
    6.91 +       master, the IRQ coming from the slave is not taken into account
    6.92 +       for the priority computation. */
    6.93 +    mask = s->isr;
    6.94 +    if (s->special_fully_nested_mode && s == &s->pics_state->pics[0])
    6.95 +        mask &= ~(1 << 2);
    6.96 +    cur_priority = get_priority(s, mask);
    6.97 +    if (priority < cur_priority) {
    6.98 +        /* higher priority found: an irq should be generated */
    6.99 +        return (priority + s->priority_add) & 7;
   6.100 +    } else {
   6.101 +        return -1;
   6.102 +    }
   6.103 +}
   6.104 +
   6.105 +/* raise irq to CPU if necessary. must be called every time the active
   6.106 +   irq may change */
   6.107 +/* XXX: should not export it, but it is needed for an APIC kludge */
   6.108 +void pic_update_irq(struct vmx_virpic *s)
   6.109 +{
   6.110 +    int irq2, irq;
   6.111 +
   6.112 +    /* first look at slave pic */
   6.113 +    irq2 = pic_get_irq(&s->pics[1]);
   6.114 +    if (irq2 >= 0) {
   6.115 +        /* if irq request by slave pic, signal master PIC */
   6.116 +        pic_set_irq1(&s->pics[0], 2, 1);
   6.117 +        pic_set_irq1(&s->pics[0], 2, 0);
   6.118 +    }
   6.119 +    /* look at requested irq */
   6.120 +    irq = pic_get_irq(&s->pics[0]);
   6.121 +    if (irq >= 0) {
   6.122 +        s->irq_request(s->irq_request_opaque, 1);
   6.123 +    }
   6.124 +}
   6.125 +
   6.126 +void pic_set_irq_new(void *opaque, int irq, int level)
   6.127 +{
   6.128 +    struct vmx_virpic *s = opaque;
   6.129 +
   6.130 +    pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
   6.131 +    /* used for IOAPIC irqs */
   6.132 +    if (s->alt_irq_func)
   6.133 +        s->alt_irq_func(s->alt_irq_opaque, irq, level);
   6.134 +    pic_update_irq(s);
   6.135 +}
   6.136 +
   6.137 +void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs)
   6.138 +{
   6.139 +    s->pics[1].irr |= (uint8_t)(irqs >> 8);
   6.140 +    s->pics[0].irr |= (uint8_t) irqs;
   6.141 +    /* TODO for alt_irq_func */
   6.142 +    pic_update_irq(s);
   6.143 +}
   6.144 +
   6.145 +void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs)
   6.146 +{
   6.147 +    s->pics[1].irr &= ~(uint8_t)(irqs >> 8);
   6.148 +    s->pics[0].irr &= ~(uint8_t) irqs;
   6.149 +    pic_update_irq(s);
   6.150 +}
   6.151 +
   6.152 +/* obsolete function */
   6.153 +void pic_set_irq(struct vmx_virpic *isa_pic, int irq, int level)
   6.154 +{
   6.155 +    pic_set_irq_new(isa_pic, irq, level);
   6.156 +}
   6.157 +
   6.158 +/* acknowledge interrupt 'irq' */
   6.159 +static inline void pic_intack(PicState *s, int irq)
   6.160 +{
   6.161 +    if (s->auto_eoi) {
   6.162 +        if (s->rotate_on_auto_eoi)
   6.163 +            s->priority_add = (irq + 1) & 7;
   6.164 +    } else {
   6.165 +        s->isr |= (1 << irq);
   6.166 +    }
   6.167 +    /* We don't clear a level sensitive interrupt here */
   6.168 +    if (!(s->elcr & (1 << irq)))
   6.169 +        s->irr &= ~(1 << irq);
   6.170 +}
   6.171 +
   6.172 +int pic_read_irq(struct vmx_virpic *s)
   6.173 +{
   6.174 +    int irq, irq2, intno;
   6.175 +
   6.176 +    irq = pic_get_irq(&s->pics[0]);
   6.177 +    if (irq >= 0) {
   6.178 +        pic_intack(&s->pics[0], irq);
   6.179 +        if (irq == 2) {
   6.180 +            irq2 = pic_get_irq(&s->pics[1]);
   6.181 +            if (irq2 >= 0) {
   6.182 +                pic_intack(&s->pics[1], irq2);
   6.183 +            } else {
   6.184 +                /* spurious IRQ on slave controller */
   6.185 +                irq2 = 7;
   6.186 +            }
   6.187 +            intno = s->pics[1].irq_base + irq2;
   6.188 +            irq = irq2 + 8;
   6.189 +        } else {
   6.190 +            intno = s->pics[0].irq_base + irq;
   6.191 +        }
   6.192 +    } else {
   6.193 +        /* spurious IRQ on host controller */
   6.194 +        printk("spurious IRQ irq got=%d\n",irq);
   6.195 +        irq = 7;
   6.196 +        intno = s->pics[0].irq_base + irq;
   6.197 +    }
   6.198 +    pic_update_irq(s);
   6.199 +        
   6.200 +    return intno;
   6.201 +}
   6.202 +
   6.203 +static void update_shared_irr(struct vmx_virpic *s, PicState *c)
   6.204 +{
   6.205 +    uint8_t *pl, *pe;
   6.206 +
   6.207 +    get_sp(current->domain)->sp_global.pic_elcr = 
   6.208 +		s->pics[0].elcr | ((u16)s->pics[1].elcr << 8);
   6.209 +    pl =(uint8_t*)&get_sp(current->domain)->sp_global.pic_last_irr;
   6.210 +    pe =(uint8_t*)&get_sp(current->domain)->sp_global.pic_elcr;
   6.211 +    if ( c == &s->pics[0] ) {
   6.212 +         *pl = c->last_irr;
   6.213 +         *pe = c->elcr;
   6.214 +    }
   6.215 +    else {
   6.216 +         *(pl+1) = c->last_irr;
   6.217 +         *(pe+1) = c->elcr;
   6.218 +    }
   6.219 +}
   6.220 +
   6.221 +static void pic_reset(void *opaque)
   6.222 +{
   6.223 +    PicState *s = opaque;
   6.224 +
   6.225 +    s->last_irr = 0;
   6.226 +    s->irr = 0;
   6.227 +    s->imr = 0;
   6.228 +    s->isr = 0;
   6.229 +    s->priority_add = 0;
   6.230 +    s->irq_base = 0;
   6.231 +    s->read_reg_select = 0;
   6.232 +    s->poll = 0;
   6.233 +    s->special_mask = 0;
   6.234 +    s->init_state = 0;
   6.235 +    s->auto_eoi = 0;
   6.236 +    s->rotate_on_auto_eoi = 0;
   6.237 +    s->special_fully_nested_mode = 0;
   6.238 +    s->init4 = 0;
   6.239 +    s->elcr = 0;
   6.240 +}
   6.241 +
   6.242 +static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
   6.243 +{
   6.244 +    PicState *s = opaque;
   6.245 +    int priority, cmd, irq;
   6.246 +
   6.247 +    addr &= 1;
   6.248 +    if (addr == 0) {
   6.249 +        if (val & 0x10) {
   6.250 +            /* init */
   6.251 +            pic_reset(s);
   6.252 +            update_shared_irr(s->pics_state, s);
   6.253 +            /* deassert a pending interrupt */
   6.254 +            s->pics_state->irq_request(s->pics_state->irq_request_opaque, 0);
   6.255 +            s->init_state = 1;
   6.256 +            s->init4 = val & 1;
   6.257 +            if (val & 0x02)
   6.258 +                hw_error("single mode not supported");
   6.259 +            if (val & 0x08)
   6.260 +                hw_error("level sensitive irq not supported");
   6.261 +        } else if (val & 0x08) {
   6.262 +            if (val & 0x04)
   6.263 +                s->poll = 1;
   6.264 +            if (val & 0x02)
   6.265 +                s->read_reg_select = val & 1;
   6.266 +            if (val & 0x40)
   6.267 +                s->special_mask = (val >> 5) & 1;
   6.268 +        } else {
   6.269 +            cmd = val >> 5;
   6.270 +            switch(cmd) {
   6.271 +            case 0:
   6.272 +            case 4:
   6.273 +                s->rotate_on_auto_eoi = cmd >> 2;
   6.274 +                break;
   6.275 +            case 1: /* end of interrupt */
   6.276 +            case 5:
   6.277 +                priority = get_priority(s, s->isr);
   6.278 +                if (priority != 8) {
   6.279 +                    irq = (priority + s->priority_add) & 7;
   6.280 +                    s->isr &= ~(1 << irq);
   6.281 +                    if (cmd == 5)
   6.282 +                        s->priority_add = (irq + 1) & 7;
   6.283 +                    pic_update_irq(s->pics_state);
   6.284 +                }
   6.285 +                break;
   6.286 +            case 3:
   6.287 +                irq = val & 7;
   6.288 +                s->isr &= ~(1 << irq);
   6.289 +                pic_update_irq(s->pics_state);
   6.290 +                break;
   6.291 +            case 6:
   6.292 +                s->priority_add = (val + 1) & 7;
   6.293 +                pic_update_irq(s->pics_state);
   6.294 +                break;
   6.295 +            case 7:
   6.296 +                irq = val & 7;
   6.297 +                s->isr &= ~(1 << irq);
   6.298 +                s->priority_add = (irq + 1) & 7;
   6.299 +                pic_update_irq(s->pics_state);
   6.300 +                break;
   6.301 +            default:
   6.302 +                /* no operation */
   6.303 +                break;
   6.304 +            }
   6.305 +        }
   6.306 +    } else {
   6.307 +        switch(s->init_state) {
   6.308 +        case 0:
   6.309 +            /* normal mode */
   6.310 +            s->imr = val;
   6.311 +            pic_update_irq(s->pics_state);
   6.312 +            break;
   6.313 +        case 1:
   6.314 +            s->irq_base = val & 0xf8;
   6.315 +            s->init_state = 2;
   6.316 +            break;
   6.317 +        case 2:
   6.318 +            if (s->init4) {
   6.319 +                s->init_state = 3;
   6.320 +            } else {
   6.321 +                s->init_state = 0;
   6.322 +            }
   6.323 +            break;
   6.324 +        case 3:
   6.325 +            s->special_fully_nested_mode = (val >> 4) & 1;
   6.326 +            s->auto_eoi = (val >> 1) & 1;
   6.327 +            s->init_state = 0;
   6.328 +            break;
   6.329 +        }
   6.330 +    }
   6.331 +}
   6.332 +
   6.333 +static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
   6.334 +{
   6.335 +    int ret;
   6.336 +
   6.337 +    ret = pic_get_irq(s);
   6.338 +    if (ret >= 0) {
   6.339 +        if (addr1 >> 7) {
   6.340 +            s->pics_state->pics[0].isr &= ~(1 << 2);
   6.341 +            s->pics_state->pics[0].irr &= ~(1 << 2);
   6.342 +        }
   6.343 +        s->irr &= ~(1 << ret);
   6.344 +        s->isr &= ~(1 << ret);
   6.345 +        if (addr1 >> 7 || ret != 2)
   6.346 +            pic_update_irq(s->pics_state);
   6.347 +    } else {
   6.348 +        ret = 0x07;
   6.349 +        pic_update_irq(s->pics_state);
   6.350 +    }
   6.351 +
   6.352 +    return ret;
   6.353 +}
   6.354 +
   6.355 +static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
   6.356 +{
   6.357 +    PicState *s = opaque;
   6.358 +    unsigned int addr;
   6.359 +    int ret;
   6.360 +
   6.361 +    addr = addr1;
   6.362 +    addr &= 1;
   6.363 +    if (s->poll) {
   6.364 +        ret = pic_poll_read(s, addr1);
   6.365 +        s->poll = 0;
   6.366 +    } else {
   6.367 +        if (addr == 0) {
   6.368 +            if (s->read_reg_select)
   6.369 +                ret = s->isr;
   6.370 +            else
   6.371 +                ret = s->irr;
   6.372 +        } else {
   6.373 +            ret = s->imr;
   6.374 +        }
   6.375 +    }
   6.376 +    return ret;
   6.377 +}
   6.378 +
   6.379 +/* memory mapped interrupt status */
   6.380 +/* XXX: may be the same than pic_read_irq() */
   6.381 +uint32_t pic_intack_read(struct vmx_virpic *s)
   6.382 +{
   6.383 +    int ret;
   6.384 +
   6.385 +    ret = pic_poll_read(&s->pics[0], 0x00);
   6.386 +    if (ret == 2)
   6.387 +        ret = pic_poll_read(&s->pics[1], 0x80) + 8;
   6.388 +    /* Prepare for ISR read */
   6.389 +    s->pics[0].read_reg_select = 1;
   6.390 +    
   6.391 +    return ret;
   6.392 +}
   6.393 +
   6.394 +static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
   6.395 +{
   6.396 +    PicState *s = opaque;
   6.397 +    s->elcr = val & s->elcr_mask;
   6.398 +}
   6.399 +
   6.400 +static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1)
   6.401 +{
   6.402 +    PicState *s = opaque;
   6.403 +    return s->elcr;
   6.404 +}
   6.405 +
   6.406 +/* XXX: add generic master/slave system */
   6.407 +static void pic_init1(int io_addr, int elcr_addr, PicState *s)
   6.408 +{
   6.409 +    pic_reset(s);
   6.410 +}
   6.411 +
   6.412 +void pic_init(struct vmx_virpic *s, void (*irq_request)(), 
   6.413 +              void *irq_request_opaque)
   6.414 +{
   6.415 +    memset(s, 0, sizeof(*s));
   6.416 +    pic_init1(0x20, 0x4d0, &s->pics[0]);
   6.417 +    pic_init1(0xa0, 0x4d1, &s->pics[1]);
   6.418 +    s->pics[0].elcr_mask = 0xf8;
   6.419 +    s->pics[1].elcr_mask = 0xde;
   6.420 +    s->irq_request = irq_request;
   6.421 +    s->irq_request_opaque = irq_request_opaque;
   6.422 +    s->pics[0].pics_state = s;
   6.423 +    s->pics[1].pics_state = s;
   6.424 +    return; 
   6.425 +}
   6.426 +
   6.427 +void pic_set_alt_irq_func(struct vmx_virpic *s, void (*alt_irq_func)(),
   6.428 +                          void *alt_irq_opaque)
   6.429 +{
   6.430 +    s->alt_irq_func = alt_irq_func;
   6.431 +    s->alt_irq_opaque = alt_irq_opaque;
   6.432 +}
   6.433 +
   6.434 +static int intercept_pic_io(ioreq_t *p)
   6.435 +{
   6.436 +    struct vmx_virpic  *pic;
   6.437 +    struct vcpu *v = current;
   6.438 +    uint32_t data;
   6.439 +    
   6.440 +    if ( p->size != 1 || p->count != 1) {
   6.441 +        printk("PIC_IO wrong access size %d!\n", (int)p->size);
   6.442 +        return 1;
   6.443 +    }
   6.444 +    pic = &v->domain->arch.vmx_platform.vmx_pic;
   6.445 +    if ( p->dir == 0 ) {
   6.446 +        if(p->pdata_valid) 
   6.447 +            vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_IN);
   6.448 +        else
   6.449 +            data = p->u.data;
   6.450 +        pic_ioport_write((void*)&pic->pics[p->addr>>7],
   6.451 +                (uint32_t) p->addr, (uint32_t) (data & 0xff));
   6.452 +    }
   6.453 +    else {
   6.454 +        data = pic_ioport_read(
   6.455 +            (void*)&pic->pics[p->addr>>7], (uint32_t) p->addr);
   6.456 +        if(p->pdata_valid) 
   6.457 +            vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_OUT);
   6.458 +        else 
   6.459 +            p->u.data = (u64)data;
   6.460 +    }
   6.461 +    return 1;
   6.462 +}
   6.463 +
   6.464 +static int intercept_elcr_io(ioreq_t *p)
   6.465 +{
   6.466 +    struct vmx_virpic  *s;
   6.467 +    struct vcpu *v = current;
   6.468 +    uint32_t data;
   6.469 +    
   6.470 +    if ( p->size != 1 || p->count != 1 ) {
   6.471 +        printk("PIC_IO wrong access size %d!\n", (int)p->size);
   6.472 +        return 1;
   6.473 +    }
   6.474 +
   6.475 +    s = &v->domain->arch.vmx_platform.vmx_pic;
   6.476 +    if ( p->dir == 0 ) {
   6.477 +        if(p->pdata_valid) 
   6.478 +            vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_IN);
   6.479 +        else
   6.480 +            data = p->u.data;
   6.481 +        elcr_ioport_write((void*)&s->pics[p->addr&1],
   6.482 +                (uint32_t) p->addr, (uint32_t)( data & 0xff));
   6.483 +    	get_sp(current->domain)->sp_global.pic_elcr = 
   6.484 +            s->pics[0].elcr | ((u16)s->pics[1].elcr << 8);
   6.485 +    }
   6.486 +    else {
   6.487 +        data = (u64) elcr_ioport_read(
   6.488 +                (void*)&s->pics[p->addr&1], (uint32_t) p->addr);
   6.489 +        if(p->pdata_valid) 
   6.490 +            vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_OUT);
   6.491 +        else 
   6.492 +            p->u.data = (u64)data;
   6.493 +
   6.494 +    }
   6.495 +    return 1;
   6.496 +}
   6.497 +void register_pic_io_hook (void)
   6.498 +{
   6.499 +    register_portio_handler(0x20, 2, intercept_pic_io); 
   6.500 +    register_portio_handler(0x4d0, 1, intercept_elcr_io); 
   6.501 +    register_portio_handler(0xa0, 2, intercept_pic_io); 
   6.502 +    register_portio_handler(0x4d1, 1, intercept_elcr_io); 
   6.503 +}
   6.504 +
   6.505 +
   6.506 +/* IRQ handling */
   6.507 +int cpu_get_pic_interrupt(struct vcpu *v, int *type)
   6.508 +{
   6.509 +    int intno;
   6.510 +    struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic;
   6.511 +    
   6.512 +    /* read the irq from the PIC */
   6.513 +    intno = pic_read_irq(s);
   6.514 +    *type = VLAPIC_DELIV_MODE_EXT;
   6.515 +    return intno;
   6.516 +}
   6.517 +
   6.518 +int is_pit_irq(struct vcpu *v, int irq)
   6.519 +{
   6.520 +    int  pit_vec = v->domain->arch.vmx_platform.vmx_pic.pics[0].irq_base;
   6.521 +
   6.522 +    return (irq == pit_vec);
   6.523 +}
     7.1 --- a/xen/arch/x86/domain.c	Fri Oct 21 18:19:38 2005 +0100
     7.2 +++ b/xen/arch/x86/domain.c	Fri Oct 21 18:29:26 2005 +0100
     7.3 @@ -39,7 +39,6 @@
     7.4  #include <asm/msr.h>
     7.5  #include <asm/physdev.h>
     7.6  #include <xen/kernel.h>
     7.7 -#include <public/io/ioreq.h>
     7.8  #include <xen/multicall.h>
     7.9  
    7.10  /* opt_noreboot: If true, machine will need manual reset on error. */
     8.1 --- a/xen/arch/x86/vmx.c	Fri Oct 21 18:19:38 2005 +0100
     8.2 +++ b/xen/arch/x86/vmx.c	Fri Oct 21 18:29:26 2005 +0100
     8.3 @@ -647,8 +647,8 @@ void send_pio_req(struct cpu_user_regs *
     8.4          p->u.data = value;
     8.5  
     8.6      if (vmx_portio_intercept(p)) {
     8.7 -        /* no blocking & no evtchn notification */
     8.8 -        clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
     8.9 +        p->state = STATE_IORESP_READY;
    8.10 +        vmx_io_assist(v);
    8.11          return;
    8.12      }
    8.13  
     9.1 --- a/xen/arch/x86/vmx_intercept.c	Fri Oct 21 18:19:38 2005 +0100
     9.2 +++ b/xen/arch/x86/vmx_intercept.c	Fri Oct 21 18:29:26 2005 +0100
     9.3 @@ -209,8 +209,7 @@ static void pit_timer_fn(void *data)
     9.4      missed_ticks = (NOW() - vpit->scheduled)/(s_time_t) vpit->period;
     9.5  
     9.6      /* Set the pending intr bit, and send evtchn notification to myself. */
     9.7 -    if (test_and_set_bit(vpit->vector, vpit->intr_bitmap))
     9.8 -        vpit->pending_intr_nr++; /* already set, then count the pending intr */
     9.9 +    vpit->pending_intr_nr++; /* already set, then count the pending intr */
    9.10      evtchn_set_pending(vpit->v, iopacket_port(vpit->v->domain));
    9.11  
    9.12      /* pick up missed timer tick */
    9.13 @@ -230,11 +229,8 @@ void vmx_hooks_assist(struct vcpu *v)
    9.14  {
    9.15      vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id);
    9.16      ioreq_t *p = &vio->vp_ioreq;
    9.17 -    shared_iopage_t *sp = get_sp(v->domain);
    9.18 -    u64 *intr = &(sp->sp_global.pic_intr[0]);
    9.19      struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
    9.20      int rw_mode, reinit = 0;
    9.21 -    int oldvec = 0;
    9.22  
    9.23      /* load init count*/
    9.24      if (p->state == STATE_IORESP_HOOK) {
    9.25 @@ -243,7 +239,7 @@ void vmx_hooks_assist(struct vcpu *v)
    9.26              VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT: guest reset PIT with channel %lx!\n", (unsigned long) ((p->u.data >> 24) & 0x3) );
    9.27              rem_ac_timer(&(vpit->pit_timer));
    9.28              reinit = 1;
    9.29 -            oldvec = vpit->vector;
    9.30 + 
    9.31          }
    9.32          else
    9.33              init_ac_timer(&vpit->pit_timer, pit_timer_fn, vpit, v->processor);
    9.34 @@ -258,12 +254,6 @@ void vmx_hooks_assist(struct vcpu *v)
    9.35                     vpit->init_val);
    9.36              vpit->period = 1000000;
    9.37          }
    9.38 -        vpit->vector = ((p->u.data >> 16) & 0xFF);
    9.39 -
    9.40 -        if( reinit && oldvec != vpit->vector){
    9.41 -            clear_bit(oldvec, intr);
    9.42 -            vpit->pending_intr_nr = 0;
    9.43 -        }
    9.44  
    9.45          vpit->channel = ((p->u.data >> 24) & 0x3);
    9.46          vpit->first_injected = 0;
    9.47 @@ -287,7 +277,6 @@ void vmx_hooks_assist(struct vcpu *v)
    9.48              break;
    9.49          }
    9.50  
    9.51 -        vpit->intr_bitmap = intr;
    9.52          vpit->v = v;
    9.53  
    9.54          vpit->scheduled = NOW() + vpit->period;
    9.55 @@ -297,8 +286,9 @@ void vmx_hooks_assist(struct vcpu *v)
    9.56          p->state = STATE_IORESP_READY;
    9.57  
    9.58          /* register handler to intercept the PIT io when vm_exit */
    9.59 -        if (!reinit)
    9.60 +        if (!reinit) {
    9.61              register_portio_handler(0x40, 4, intercept_pit_io); 
    9.62 +        }
    9.63      }
    9.64  }
    9.65  #endif /* CONFIG_VMX */
    10.1 --- a/xen/arch/x86/vmx_io.c	Fri Oct 21 18:19:38 2005 +0100
    10.2 +++ b/xen/arch/x86/vmx_io.c	Fri Oct 21 18:29:26 2005 +0100
    10.3 @@ -37,6 +37,7 @@
    10.4  #include <asm/shadow.h>
    10.5  
    10.6  #include <public/io/ioreq.h>
    10.7 +#include <public/io/vmx_vpic.h>
    10.8  #include <public/io/vmx_vlapic.h>
    10.9  
   10.10  #ifdef CONFIG_VMX
   10.11 @@ -794,57 +795,6 @@ static __inline__ int find_highest_irq(u
   10.12  }
   10.13  
   10.14  #define BSP_CPU(v)    (!(v->vcpu_id))
   10.15 -static inline void clear_extint(struct vcpu *v)
   10.16 -{
   10.17 -    global_iodata_t *spg;
   10.18 -    int i;
   10.19 -    spg = &get_sp(v->domain)->sp_global;
   10.20 -
   10.21 -    for(i = 0; i < INTR_LEN; i++)
   10.22 -        spg->pic_intr[i] = 0;
   10.23 -}
   10.24 -
   10.25 -static inline void clear_highest_bit(struct vcpu *v, int vector)
   10.26 -{
   10.27 -    global_iodata_t *spg;
   10.28 -
   10.29 -    spg = &get_sp(v->domain)->sp_global;
   10.30 -
   10.31 -    clear_bit(vector, &spg->pic_intr[0]);
   10.32 -}
   10.33 -
   10.34 -static inline int find_highest_pic_irq(struct vcpu *v)
   10.35 -{
   10.36 -    u64 intr[INTR_LEN];
   10.37 -    global_iodata_t *spg;
   10.38 -    int i;
   10.39 -
   10.40 -    if(!BSP_CPU(v))
   10.41 -        return -1;
   10.42 -
   10.43 -    spg = &get_sp(v->domain)->sp_global;
   10.44 -
   10.45 -    for(i = 0; i < INTR_LEN; i++){
   10.46 -        intr[i] = spg->pic_intr[i] & ~spg->pic_mask[i];
   10.47 -    }
   10.48 -
   10.49 -    return find_highest_irq((u32 *)&intr[0]);
   10.50 -}
   10.51 -
   10.52 -/*
   10.53 - * Return 0-255 for pending irq.
   10.54 - *        -1 when no pending.
   10.55 - */
   10.56 -static inline int find_highest_pending_irq(struct vcpu *v, int *type)
   10.57 -{
   10.58 -    int result = -1;
   10.59 -    if ((result = find_highest_pic_irq(v)) != -1){
   10.60 -        *type = VLAPIC_DELIV_MODE_EXT;
   10.61 -        return result;
   10.62 -    }
   10.63 -    return result;
   10.64 -}
   10.65 -
   10.66  static inline void
   10.67  interrupt_post_injection(struct vcpu * v, int vector, int type)
   10.68  {
   10.69 @@ -853,17 +803,17 @@ interrupt_post_injection(struct vcpu * v
   10.70      switch(type)
   10.71      {
   10.72      case VLAPIC_DELIV_MODE_EXT:
   10.73 -        if (vpit->pending_intr_nr && vector == vpit->vector)
   10.74 -            vpit->pending_intr_nr--;
   10.75 -        else
   10.76 -            clear_highest_bit(v, vector);
   10.77 -
   10.78 -        if (vector == vpit->vector && !vpit->first_injected){
   10.79 -            vpit->first_injected = 1;
   10.80 -            vpit->pending_intr_nr = 0;
   10.81 +        if ( is_pit_irq(v, vector) ) {
   10.82 +            if ( !vpit->first_injected ) {
   10.83 +                vpit->first_injected = 1;
   10.84 +                vpit->pending_intr_nr = 0;
   10.85 +            }
   10.86 +            else {
   10.87 +                vpit->pending_intr_nr--;
   10.88 +            }
   10.89 +            vpit->inject_point = NOW();
   10.90 + 
   10.91          }
   10.92 -        if (vector == vpit->vector)
   10.93 -            vpit->inject_point = NOW();
   10.94          break;
   10.95  
   10.96      default:
   10.97 @@ -895,17 +845,56 @@ static inline int irq_masked(unsigned lo
   10.98      return ((eflags & X86_EFLAGS_IF) == 0);
   10.99  }
  10.100  
  10.101 +void pic_irq_request(int *interrupt_request, int level)
  10.102 +{
  10.103 +    if (level)
  10.104 +        *interrupt_request = 1;
  10.105 +    else
  10.106 +        *interrupt_request = 0;
  10.107 +}
  10.108 +
  10.109 +void vmx_pic_assist(struct vcpu *v)
  10.110 +{
  10.111 +    global_iodata_t *spg;
  10.112 +    u16   *virq_line, irqs;
  10.113 +    struct vmx_virpic *pic = &v->domain->arch.vmx_platform.vmx_pic;
  10.114 +    
  10.115 +    spg = &get_sp(v->domain)->sp_global;
  10.116 +    virq_line  = &spg->pic_clear_irr;
  10.117 +    if ( *virq_line ) {
  10.118 +        do {
  10.119 +            irqs = *(volatile u16*)virq_line;
  10.120 +        } while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
  10.121 +        do_pic_irqs_clear(pic, irqs);
  10.122 +    }
  10.123 +    virq_line  = &spg->pic_irr;
  10.124 +    if ( *virq_line ) {
  10.125 +        do {
  10.126 +            irqs = *(volatile u16*)virq_line;
  10.127 +        } while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
  10.128 +        do_pic_irqs(pic, irqs);
  10.129 +    }
  10.130 +
  10.131 +}
  10.132 +
  10.133  asmlinkage void vmx_intr_assist(void)
  10.134  {
  10.135      int intr_type = 0;
  10.136      int highest_vector;
  10.137      unsigned long intr_fields, eflags, interruptibility, cpu_exec_control;
  10.138      struct vcpu *v = current;
  10.139 +    struct virtual_platform_def *plat=&v->domain->arch.vmx_platform;
  10.140 +    struct vmx_virpit *vpit = &plat->vmx_pit;
  10.141 +    struct vmx_virpic *pic= &plat->vmx_pic;
  10.142  
  10.143 -    highest_vector = find_highest_pending_irq(v, &intr_type);
  10.144 +    vmx_pic_assist(v);
  10.145      __vmread_vcpu(v, CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control);
  10.146 +    if ( vpit->pending_intr_nr ) {
  10.147 +        pic_set_irq(pic, 0, 0);
  10.148 +        pic_set_irq(pic, 0, 1);
  10.149 +    }
  10.150  
  10.151 -    if (highest_vector == -1) {
  10.152 +    if ( !plat->interrupt_request ) {
  10.153          disable_irq_window(cpu_exec_control);
  10.154          return;
  10.155      }
  10.156 @@ -922,22 +911,20 @@ asmlinkage void vmx_intr_assist(void)
  10.157  
  10.158      if (interruptibility) {
  10.159          enable_irq_window(cpu_exec_control);
  10.160 -        VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, interruptibility: %lx",
  10.161 -                    highest_vector, interruptibility);
  10.162 +        VMX_DBG_LOG(DBG_LEVEL_1, "interruptibility: %lx",interruptibility);
  10.163          return;
  10.164      }
  10.165  
  10.166      __vmread(GUEST_RFLAGS, &eflags);
  10.167 +    if (irq_masked(eflags)) {
  10.168 +        enable_irq_window(cpu_exec_control);
  10.169 +        return;
  10.170 +    }
  10.171 +    plat->interrupt_request = 0;
  10.172 +    highest_vector = cpu_get_pic_interrupt(v, &intr_type); 
  10.173  
  10.174      switch (intr_type) {
  10.175      case VLAPIC_DELIV_MODE_EXT:
  10.176 -        if (irq_masked(eflags)) {
  10.177 -            enable_irq_window(cpu_exec_control);
  10.178 -            VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, eflags: %lx",
  10.179 -                        highest_vector, eflags);
  10.180 -            return;
  10.181 -        }
  10.182 -
  10.183          vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE);
  10.184          TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
  10.185          break;
    11.1 --- a/xen/arch/x86/vmx_vmcs.c	Fri Oct 21 18:19:38 2005 +0100
    11.2 +++ b/xen/arch/x86/vmx_vmcs.c	Fri Oct 21 18:29:26 2005 +0100
    11.3 @@ -210,8 +210,14 @@ static void get_io_shared_page(struct vc
    11.4  
    11.5  static void vmx_setup_platform(struct vcpu *v)
    11.6  {
    11.7 -    if (v->vcpu_id == 0)
    11.8 +    struct virtual_platform_def  *platform;
    11.9 +    if (v->vcpu_id == 0) {
   11.10          get_io_shared_page(v);
   11.11 +        platform = &v->domain->arch.vmx_platform;
   11.12 +        pic_init(&platform->vmx_pic,  pic_irq_request, 
   11.13 +                 &platform->interrupt_request);
   11.14 +        register_pic_io_hook();
   11.15 +    }
   11.16  }
   11.17  
   11.18  static void vmx_set_host_env(struct vcpu *v)
   11.19 @@ -275,7 +281,8 @@ static void vmx_do_launch(struct vcpu *v
   11.20      page = (struct pfn_info *) alloc_domheap_page(NULL);
   11.21      pfn = (unsigned long) (page - frame_table);
   11.22  
   11.23 -    vmx_setup_platform(v);
   11.24 +    if ( v == v->domain->vcpu[0] )
   11.25 +        vmx_setup_platform(v);
   11.26  
   11.27      vmx_set_host_env(v);
   11.28  
    12.1 --- a/xen/include/asm-x86/vmx.h	Fri Oct 21 18:19:38 2005 +0100
    12.2 +++ b/xen/include/asm-x86/vmx.h	Fri Oct 21 18:29:26 2005 +0100
    12.3 @@ -34,6 +34,7 @@ extern void vmx_asm_vmexit_handler(struc
    12.4  extern void vmx_asm_do_resume(void);
    12.5  extern void vmx_asm_do_launch(void);
    12.6  extern void vmx_intr_assist(void);
    12.7 +extern void pic_irq_request(int *interrupt_request, int level);
    12.8  
    12.9  extern void arch_vmx_do_launch(struct vcpu *);
   12.10  extern void arch_vmx_do_resume(struct vcpu *);
    13.1 --- a/xen/include/asm-x86/vmx_intercept.h	Fri Oct 21 18:19:38 2005 +0100
    13.2 +++ b/xen/include/asm-x86/vmx_intercept.h	Fri Oct 21 18:29:26 2005 +0100
    13.3 @@ -8,7 +8,7 @@
    13.4  #include <xen/errno.h>
    13.5  #include <public/io/ioreq.h>
    13.6  
    13.7 -#define MAX_IO_HANDLER              4
    13.8 +#define MAX_IO_HANDLER              8
    13.9  
   13.10  #define VMX_PORTIO                  0
   13.11  #define VMX_MMIO                    1
    14.1 --- a/xen/include/asm-x86/vmx_platform.h	Fri Oct 21 18:19:38 2005 +0100
    14.2 +++ b/xen/include/asm-x86/vmx_platform.h	Fri Oct 21 18:29:26 2005 +0100
    14.3 @@ -24,6 +24,7 @@
    14.4  #include <asm/e820.h>
    14.5  #include <asm/vmx_virpit.h>
    14.6  #include <asm/vmx_intercept.h>
    14.7 +#include <public/io/vmx_vpic.h>
    14.8  
    14.9  #define MAX_OPERAND_NUM 2
   14.10  
   14.11 @@ -80,6 +81,8 @@ struct virtual_platform_def {
   14.12      unsigned long          shared_page_va;
   14.13      struct vmx_virpit      vmx_pit;
   14.14      struct vmx_io_handler  vmx_io_handler;
   14.15 +    struct vmx_virpic      vmx_pic;
   14.16 +    int                    interrupt_request;
   14.17  };
   14.18  
   14.19  extern void handle_mmio(unsigned long, unsigned long);
    15.1 --- a/xen/include/asm-x86/vmx_virpit.h	Fri Oct 21 18:19:38 2005 +0100
    15.2 +++ b/xen/include/asm-x86/vmx_virpit.h	Fri Oct 21 18:29:26 2005 +0100
    15.3 @@ -18,13 +18,11 @@
    15.4  
    15.5  struct vmx_virpit {
    15.6      /* for simulation of counter 0 in mode 2*/
    15.7 -    int vector;    /* the pit irq vector */
    15.8 -    unsigned int period;  /* the frequency. e.g. 10ms*/
    15.9 +    u32 period;		/* pit frequency in ns */
   15.10      s_time_t scheduled;                 /* scheduled timer interrupt */
   15.11      unsigned int channel;  /* the pit channel, counter 0~2 */
   15.12 -    u64  *intr_bitmap;
   15.13      unsigned int pending_intr_nr; /* the couner for pending timer interrupts */
   15.14 -    unsigned long long inject_point; /* the time inject virt intr */
   15.15 +    u64 inject_point; /* the time inject virt intr */
   15.16      struct ac_timer pit_timer;  /* periodic timer for mode 2*/
   15.17      int first_injected;                 /* flag to prevent shadow window */
   15.18  
    16.1 --- a/xen/include/public/io/ioreq.h	Fri Oct 21 18:19:38 2005 +0100
    16.2 +++ b/xen/include/public/io/ioreq.h	Fri Oct 21 18:29:26 2005 +0100
    16.3 @@ -60,8 +60,10 @@ typedef struct {
    16.4  #define INTR_LEN        (MAX_VECTOR/(BITS_PER_BYTE * sizeof(uint64_t)))
    16.5  
    16.6  typedef struct {
    16.7 -    uint64_t pic_intr[INTR_LEN];
    16.8 -    uint64_t pic_mask[INTR_LEN];
    16.9 +    uint16_t  pic_elcr;
   16.10 +    uint16_t   pic_irr;
   16.11 +    uint16_t   pic_last_irr;
   16.12 +    uint16_t   pic_clear_irr;
   16.13      int      eport; /* Event channel port */
   16.14  } global_iodata_t;
   16.15  
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/xen/include/public/io/vmx_vpic.h	Fri Oct 21 18:29:26 2005 +0100
    17.3 @@ -0,0 +1,84 @@
    17.4 +/*
    17.5 + * QEMU System Emulator header
    17.6 + * 
    17.7 + * Copyright (c) 2003 Fabrice Bellard
    17.8 + * Copyright (c) 2005 Intel Corp
    17.9 + * 
   17.10 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   17.11 + * of this software and associated documentation files (the "Software"), to deal
   17.12 + * in the Software without restriction, including without limitation the rights
   17.13 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   17.14 + * copies of the Software, and to permit persons to whom the Software is
   17.15 + * furnished to do so, subject to the following conditions:
   17.16 + *
   17.17 + * The above copyright notice and this permission notice shall be included in
   17.18 + * all copies or substantial portions of the Software.
   17.19 + *
   17.20 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17.21 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   17.22 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   17.23 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   17.24 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   17.25 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   17.26 + * THE SOFTWARE.
   17.27 + */
   17.28 +
   17.29 +#ifndef _VMX_VPIC_H
   17.30 +#define _VMX_VPIC_H
   17.31 +
   17.32 +#define hw_error(x)  do {} while (0);
   17.33 +
   17.34 +
   17.35 +/* i8259.c */
   17.36 +typedef struct IOAPICState IOAPICState;
   17.37 +typedef struct PicState {
   17.38 +    uint8_t last_irr; /* edge detection */
   17.39 +    uint8_t irr; /* interrupt request register */
   17.40 +    uint8_t imr; /* interrupt mask register */
   17.41 +    uint8_t isr; /* interrupt service register */
   17.42 +    uint8_t priority_add; /* highest irq priority */
   17.43 +    uint8_t irq_base;
   17.44 +    uint8_t read_reg_select;
   17.45 +    uint8_t poll;
   17.46 +    uint8_t special_mask;
   17.47 +    uint8_t init_state;
   17.48 +    uint8_t auto_eoi;
   17.49 +    uint8_t rotate_on_auto_eoi;
   17.50 +    uint8_t special_fully_nested_mode;
   17.51 +    uint8_t init4; /* true if 4 byte init */
   17.52 +    uint8_t elcr; /* PIIX edge/trigger selection*/
   17.53 +    uint8_t elcr_mask;
   17.54 +    struct vmx_virpic *pics_state;
   17.55 +} PicState;
   17.56 +
   17.57 +struct vmx_virpic {
   17.58 +    /* 0 is master pic, 1 is slave pic */
   17.59 +    /* XXX: better separation between the two pics */
   17.60 +    PicState pics[2];
   17.61 +    void (*irq_request)(int *opaque, int level);
   17.62 +    void *irq_request_opaque;
   17.63 +    /* IOAPIC callback support */
   17.64 +    void (*alt_irq_func)(void *opaque, int irq_num, int level);
   17.65 +    void *alt_irq_opaque;
   17.66 +};
   17.67 +
   17.68 +
   17.69 +void pic_set_irq(struct vmx_virpic *s, int irq, int level);
   17.70 +void pic_set_irq_new(void *opaque, int irq, int level);
   17.71 +void pic_init(struct vmx_virpic *s, 
   17.72 +              void (*irq_request)(),
   17.73 +              void *irq_request_opaque);
   17.74 +void pic_set_alt_irq_func(struct vmx_virpic *s, 
   17.75 +                          void(*alt_irq_func)(),
   17.76 +                          void *alt_irq_opaque);
   17.77 +int pic_read_irq(struct vmx_virpic *s);
   17.78 +void pic_update_irq(struct vmx_virpic *s);
   17.79 +uint32_t pic_intack_read(struct vmx_virpic *s);
   17.80 +void register_pic_io_hook (void);
   17.81 +int cpu_get_pic_interrupt(struct vcpu *v, int *type);
   17.82 +int is_pit_irq(struct vcpu *v, int irq);
   17.83 +void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs);
   17.84 +void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs);
   17.85 +
   17.86 +/* APIC */
   17.87 +#endif  /* _VMX_VPIC_H */