ia64/xen-unstable

changeset 12571:d37b210bb8a7

[HVM] Update VPIC device model for new interrupt delivery code.
Move BSP VLAPIC initialisation to hvmloader.
Remove callback_irq update hack from Linux unmodified drivers.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@localhost.localdomain
date Sun Nov 26 13:37:27 2006 +0000 (2006-11-26)
parents 074b4b34e049
children e4bb22422b50
files tools/firmware/hvmloader/apic_regs.h tools/firmware/hvmloader/hvmloader.c tools/firmware/hvmloader/util.c tools/firmware/hvmloader/util.h unmodified_drivers/linux-2.6/platform-pci/evtchn.c xen/arch/x86/hvm/Makefile xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/i8259.c xen/arch/x86/hvm/irq.c xen/arch/x86/hvm/svm/intr.c xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vmx/io.c xen/arch/x86/hvm/vpic.c xen/include/asm-x86/hvm/irq.h xen/include/asm-x86/hvm/vlapic.h xen/include/asm-x86/hvm/vpic.h
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/firmware/hvmloader/apic_regs.h	Sun Nov 26 13:37:27 2006 +0000
     1.3 @@ -0,0 +1,108 @@
     1.4 +#ifndef __ASM_APICDEF_H
     1.5 +#define __ASM_APICDEF_H
     1.6 +
     1.7 +#define APIC_DEFAULT_PHYS_BASE 0xfee00000
     1.8 + 
     1.9 +#define APIC_ID       0x20
    1.10 +#define     APIC_ID_MASK             (0xFFu<<24)
    1.11 +#define     GET_APIC_ID(x)           (((x)>>24)&0xFFu)
    1.12 +#define     SET_APIC_ID(x)           (((x)<<24))
    1.13 +#define APIC_LVR      0x30
    1.14 +#define     APIC_LVR_MASK            0xFF00FF
    1.15 +#define     GET_APIC_VERSION(x)      ((x)&0xFF)
    1.16 +#define     GET_APIC_MAXLVT(x)       (((x)>>16)&0xFF)
    1.17 +#define     APIC_INTEGRATED(x)       ((x)&0xF0)
    1.18 +#define     APIC_XAPIC(x)            ((x) >= 0x14)
    1.19 +#define APIC_TASKPRI  0x80
    1.20 +#define     APIC_TPRI_MASK           0xFF
    1.21 +#define APIC_ARBPRI   0x90
    1.22 +#define     APIC_ARBPRI_MASK         0xFF
    1.23 +#define APIC_PROCPRI  0xA0
    1.24 +#define APIC_EOI      0xB0
    1.25 +#define     APIC_EIO_ACK             0x0
    1.26 +#define APIC_RRR      0xC0
    1.27 +#define APIC_LDR      0xD0
    1.28 +#define     APIC_LDR_MASK            (0xFF<<24)
    1.29 +#define     GET_APIC_LOGICAL_ID(x)   (((x)>>24)&0xFF)
    1.30 +#define     SET_APIC_LOGICAL_ID(x)   (((x)<<24))
    1.31 +#define     APIC_ALL_CPUS            0xFF
    1.32 +#define APIC_DFR      0xE0
    1.33 +#define     APIC_DFR_CLUSTER         0x0FFFFFFFul
    1.34 +#define     APIC_DFR_FLAT            0xFFFFFFFFul
    1.35 +#define APIC_SPIV     0xF0
    1.36 +#define     APIC_SPIV_FOCUS_DISABLED (1<<9)
    1.37 +#define     APIC_SPIV_APIC_ENABLED   (1<<8)
    1.38 +#define APIC_ISR      0x100
    1.39 +#define APIC_TMR      0x180
    1.40 +#define     APIC_IRR                 0x200
    1.41 +#define     APIC_ESR                 0x280
    1.42 +#define     APIC_ESR_SEND_CS         0x00001
    1.43 +#define     APIC_ESR_RECV_CS         0x00002
    1.44 +#define     APIC_ESR_SEND_ACC        0x00004
    1.45 +#define     APIC_ESR_RECV_ACC        0x00008
    1.46 +#define     APIC_ESR_SENDILL         0x00020
    1.47 +#define     APIC_ESR_RECVILL         0x00040
    1.48 +#define     APIC_ESR_ILLREGA         0x00080
    1.49 +#define APIC_ICR      0x300
    1.50 +#define     APIC_DEST_SELF           0x40000
    1.51 +#define     APIC_DEST_ALLINC         0x80000
    1.52 +#define     APIC_DEST_ALLBUT         0xC0000
    1.53 +#define     APIC_ICR_RR_MASK         0x30000
    1.54 +#define     APIC_ICR_RR_INVALID      0x00000
    1.55 +#define     APIC_ICR_RR_INPROG       0x10000
    1.56 +#define     APIC_ICR_RR_VALID        0x20000
    1.57 +#define     APIC_INT_LEVELTRIG       0x08000
    1.58 +#define     APIC_INT_ASSERT          0x04000
    1.59 +#define     APIC_ICR_BUSY            0x01000
    1.60 +#define     APIC_DEST_LOGICAL        0x00800
    1.61 +#define     APIC_DEST_PHYSICAL       0x00000
    1.62 +#define     APIC_DM_FIXED            0x00000
    1.63 +#define     APIC_DM_LOWEST           0x00100
    1.64 +#define     APIC_DM_SMI              0x00200
    1.65 +#define     APIC_DM_REMRD            0x00300
    1.66 +#define     APIC_DM_NMI              0x00400
    1.67 +#define     APIC_DM_INIT             0x00500
    1.68 +#define     APIC_DM_STARTUP          0x00600
    1.69 +#define     APIC_DM_EXTINT           0x00700
    1.70 +#define     APIC_VECTOR_MASK         0x000FF
    1.71 +#define APIC_ICR2     0x310
    1.72 +#define     GET_APIC_DEST_FIELD(x)   (((x)>>24)&0xFF)
    1.73 +#define     SET_APIC_DEST_FIELD(x)   ((x)<<24)
    1.74 +#define APIC_LVTT     0x320
    1.75 +#define APIC_LVTTHMR  0x330
    1.76 +#define APIC_LVTPC    0x340
    1.77 +#define APIC_LVT0     0x350
    1.78 +#define     APIC_LVT_TIMER_BASE_MASK (0x3<<18)
    1.79 +#define     GET_APIC_TIMER_BASE(x)   (((x)>>18)&0x3)
    1.80 +#define     SET_APIC_TIMER_BASE(x)   (((x)<<18))
    1.81 +#define     APIC_TIMER_BASE_CLKIN    0x0
    1.82 +#define     APIC_TIMER_BASE_TMBASE   0x1
    1.83 +#define     APIC_TIMER_BASE_DIV      0x2
    1.84 +#define     APIC_LVT_TIMER_PERIODIC  (1<<17)
    1.85 +#define     APIC_LVT_MASKED          (1<<16)
    1.86 +#define     APIC_LVT_LEVEL_TRIGGER   (1<<15)
    1.87 +#define     APIC_LVT_REMOTE_IRR      (1<<14)
    1.88 +#define     APIC_INPUT_POLARITY      (1<<13)
    1.89 +#define     APIC_SEND_PENDING        (1<<12)
    1.90 +#define     APIC_MODE_MASK           0x700
    1.91 +#define     GET_APIC_DELIVERY_MODE(x) (((x)>>8)&0x7)
    1.92 +#define     SET_APIC_DELIVERY_MODE(x,y) (((x)&~0x700)|((y)<<8))
    1.93 +#define         APIC_MODE_FIXED          0x0
    1.94 +#define         APIC_MODE_NMI            0x4
    1.95 +#define         APIC_MODE_EXTINT         0x7
    1.96 +#define APIC_LVT1     0x360
    1.97 +#define APIC_LVTERR   0x370
    1.98 +#define APIC_TMICT    0x380
    1.99 +#define APIC_TMCCT    0x390
   1.100 +#define APIC_TDCR     0x3E0
   1.101 +#define     APIC_TDR_DIV_TMBASE      (1<<2)
   1.102 +#define     APIC_TDR_DIV_1           0xB
   1.103 +#define     APIC_TDR_DIV_2           0x0
   1.104 +#define     APIC_TDR_DIV_4           0x1
   1.105 +#define     APIC_TDR_DIV_8           0x2
   1.106 +#define     APIC_TDR_DIV_16          0x3
   1.107 +#define     APIC_TDR_DIV_32          0x8
   1.108 +#define     APIC_TDR_DIV_64          0x9
   1.109 +#define     APIC_TDR_DIV_128         0xA
   1.110 +
   1.111 +#endif
     2.1 --- a/tools/firmware/hvmloader/hvmloader.c	Fri Nov 24 15:42:14 2006 +0000
     2.2 +++ b/tools/firmware/hvmloader/hvmloader.c	Sun Nov 26 13:37:27 2006 +0000
     2.3 @@ -26,6 +26,7 @@
     2.4  #include "acpi_utils.h"
     2.5  #include "smbios.h"
     2.6  #include "config.h"
     2.7 +#include "apic_regs.h"
     2.8  #include "pci_regs.h"
     2.9  #include <xen/version.h>
    2.10  #include <xen/hvm/params.h>
    2.11 @@ -154,16 +155,13 @@ init_hypercalls(void)
    2.12  
    2.13  static void apic_setup(void)
    2.14  {
    2.15 -    volatile uint32_t *ioregsel;
    2.16 -    volatile uint32_t *iowin;
    2.17 +    /* Set the IOAPIC ID to tha static value used in the MP/ACPI tables. */
    2.18 +    ioapic_write(0x00, IOAPIC_ID);
    2.19  
    2.20 -    /* IOAPIC memory-mapped access window registers. */
    2.21 -    ioregsel = (volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00);
    2.22 -    iowin    = (volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10);
    2.23 -
    2.24 -    /* Set the IOAPIC ID to tha static value used in the MP/ACPI tables. */
    2.25 -    *ioregsel = 0;
    2.26 -    *iowin    = IOAPIC_ID;
    2.27 +    /* Set up Virtual Wire mode. */
    2.28 +    lapic_write(APIC_SPIV, APIC_SPIV_APIC_ENABLED | 0xFF);
    2.29 +    lapic_write(APIC_LVT0, APIC_MODE_EXTINT << 8);
    2.30 +    lapic_write(APIC_LVT1, APIC_MODE_NMI    << 8);
    2.31  }
    2.32  
    2.33  static void pci_setup(void)
     3.1 --- a/tools/firmware/hvmloader/util.c	Fri Nov 24 15:42:14 2006 +0000
     3.2 +++ b/tools/firmware/hvmloader/util.c	Sun Nov 26 13:37:27 2006 +0000
     3.3 @@ -309,22 +309,24 @@ uint64_t e820_malloc(uint64_t size, uint
     3.4  
     3.5  uint32_t ioapic_read(uint32_t reg)
     3.6  {
     3.7 -    uint32_t *ioregsel = (uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00);
     3.8 -    uint32_t *iowin    = (uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10);
     3.9 -
    3.10 -    *ioregsel = reg;
    3.11 -    mb();
    3.12 -    return *iowin;
    3.13 +    *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00) = reg;
    3.14 +    return *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10);
    3.15  }
    3.16  
    3.17  void ioapic_write(uint32_t reg, uint32_t val)
    3.18  {
    3.19 -    uint32_t *ioregsel = (uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00);
    3.20 -    uint32_t *iowin    = (uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10);
    3.21 +    *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00) = reg;
    3.22 +    *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10) = val;
    3.23 +}
    3.24  
    3.25 -    *ioregsel = reg;
    3.26 -    wmb();
    3.27 -    *iowin = val;
    3.28 +uint32_t lapic_read(uint32_t reg)
    3.29 +{
    3.30 +    return *(volatile uint32_t *)(LAPIC_BASE_ADDRESS + reg);
    3.31 +}
    3.32 +
    3.33 +void lapic_write(uint32_t reg, uint32_t val)
    3.34 +{
    3.35 +    *(volatile uint32_t *)(LAPIC_BASE_ADDRESS + reg) = val;
    3.36  }
    3.37  
    3.38  #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
     4.1 --- a/tools/firmware/hvmloader/util.h	Fri Nov 24 15:42:14 2006 +0000
     4.2 +++ b/tools/firmware/hvmloader/util.h	Sun Nov 26 13:37:27 2006 +0000
     4.3 @@ -20,6 +20,12 @@ uint8_t  inb(uint16_t addr);
     4.4  uint16_t inw(uint16_t addr);
     4.5  uint32_t inl(uint16_t addr);
     4.6  
     4.7 +/* APIC access */
     4.8 +uint32_t ioapic_read(uint32_t reg);
     4.9 +void ioapic_write(uint32_t reg, uint32_t val);
    4.10 +uint32_t lapic_read(uint32_t reg);
    4.11 +void lapic_write(uint32_t reg, uint32_t val);
    4.12 +
    4.13  /* PCI access */
    4.14  uint32_t pci_read(uint32_t devfn, uint32_t reg, uint32_t len);
    4.15  #define pci_readb(devfn, reg) ((uint8_t) pci_read(devfn, reg, 1))
     5.1 --- a/unmodified_drivers/linux-2.6/platform-pci/evtchn.c	Fri Nov 24 15:42:14 2006 +0000
     5.2 +++ b/unmodified_drivers/linux-2.6/platform-pci/evtchn.c	Sun Nov 26 13:37:27 2006 +0000
     5.3 @@ -132,7 +132,7 @@ EXPORT_SYMBOL(notify_remote_via_irq);
     5.4  
     5.5  irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     5.6  {
     5.7 -	unsigned int l1i, l2i, port;
     5.8 +	unsigned int l1i, port;
     5.9  	int cpu = smp_processor_id();
    5.10  	irqreturn_t(*handler) (int, void *, struct pt_regs *);
    5.11  	shared_info_t *s = shared_info_area;
    5.12 @@ -140,44 +140,28 @@ irqreturn_t evtchn_interrupt(int irq, vo
    5.13  	unsigned long l1, l2;
    5.14  
    5.15  	v->evtchn_upcall_pending = 0;
    5.16 -	/* NB. No need for a barrier here -- XCHG is a barrier
    5.17 -	 * on x86. */
    5.18 +	/* NB. No need for a barrier here -- XCHG is a barrier on x86. */
    5.19  	l1 = xchg(&v->evtchn_pending_sel, 0);
    5.20 -	while (l1 != 0)
    5.21 -	{
    5.22 +	while (l1 != 0) {
    5.23  		l1i = __ffs(l1);
    5.24  		l1 &= ~(1 << l1i);
    5.25 -
    5.26 -		l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i];
    5.27 -		while (l2 != 0)
    5.28 -		{
    5.29 -			l2i = __ffs(l2);
    5.30 -
    5.31 -			port = (l1i * BITS_PER_LONG) + l2i;
    5.32 +		while ((l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i])) {
    5.33 +			port = (l1i * BITS_PER_LONG) + __ffs(l2);
    5.34  			synch_clear_bit(port, &s->evtchn_pending[0]);
    5.35  			if ((handler = evtchns[port].handler) != NULL)
    5.36 -			{
    5.37  				handler(port, evtchns[port].dev_id,
    5.38  					regs);
    5.39 -			}
    5.40  			else
    5.41 -			{
    5.42 -				printk(KERN_WARNING "unexpected event channel upcall on port %d!\n", port);
    5.43 -			}
    5.44 -			l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i];
    5.45 +				printk(KERN_WARNING "unexpected event channel "
    5.46 +				       "upcall on port %d!\n", port);
    5.47  		}
    5.48  	}
    5.49  
    5.50 -	/* Make sure the hypervisor has a chance to notice that the
    5.51 -	   upcall_pending condition has been cleared, so that we don't
    5.52 -	   try and reinject the interrupt again. */
    5.53 -        (void)HYPERVISOR_xen_version(0, NULL);
    5.54 -
    5.55  	return IRQ_HANDLED;
    5.56  }
    5.57  
    5.58  void force_evtchn_callback(void)
    5.59  {
    5.60 -        (void)HYPERVISOR_xen_version(0, NULL);
    5.61 +	(void)HYPERVISOR_xen_version(0, NULL);
    5.62  }
    5.63  EXPORT_SYMBOL(force_evtchn_callback);
     6.1 --- a/xen/arch/x86/hvm/Makefile	Fri Nov 24 15:42:14 2006 +0000
     6.2 +++ b/xen/arch/x86/hvm/Makefile	Sun Nov 26 13:37:27 2006 +0000
     6.3 @@ -3,7 +3,6 @@ subdir-y += vmx
     6.4  
     6.5  obj-y += hvm.o
     6.6  obj-y += i8254.o
     6.7 -obj-y += i8259.o
     6.8  obj-y += instrlen.o
     6.9  obj-y += intercept.o
    6.10  obj-y += io.o
    6.11 @@ -13,3 +12,4 @@ obj-y += pmtimer.o
    6.12  obj-y += rtc.o
    6.13  obj-y += vioapic.o
    6.14  obj-y += vlapic.o
    6.15 +obj-y += vpic.o
     7.1 --- a/xen/arch/x86/hvm/hvm.c	Fri Nov 24 15:42:14 2006 +0000
     7.2 +++ b/xen/arch/x86/hvm/hvm.c	Sun Nov 26 13:37:27 2006 +0000
     7.3 @@ -168,14 +168,13 @@ int hvm_domain_initialise(struct domain 
     7.4  
     7.5      spin_lock_init(&d->arch.hvm_domain.pbuf_lock);
     7.6      spin_lock_init(&d->arch.hvm_domain.buffered_io_lock);
     7.7 +    spin_lock_init(&d->arch.hvm_domain.irq.lock);
     7.8  
     7.9      rc = shadow_enable(d, SHM2_refcounts|SHM2_translate|SHM2_external);
    7.10      if ( rc != 0 )
    7.11          return rc;
    7.12  
    7.13 -    pic_init(domain_vpic(d));
    7.14 -    register_pic_io_hook(d);
    7.15 -
    7.16 +    vpic_init(d);
    7.17      vioapic_init(d);
    7.18  
    7.19      return 0;
    7.20 @@ -244,13 +243,14 @@ void hvm_vcpu_destroy(struct vcpu *v)
    7.21  
    7.22  int cpu_get_interrupt(struct vcpu *v, int *type)
    7.23  {
    7.24 -    int irq;
    7.25 +    int vector;
    7.26  
    7.27 -    if ( (irq = cpu_get_apic_interrupt(v, type)) != -1 )
    7.28 -        return irq;
    7.29 +    if ( (vector = cpu_get_apic_interrupt(v, type)) != -1 )
    7.30 +        return vector;
    7.31  
    7.32 -    if ( (v->vcpu_id == 0) && ((irq = cpu_get_pic_interrupt(v, type)) != -1) )
    7.33 -        return irq;
    7.34 +    if ( (v->vcpu_id == 0) &&
    7.35 +         ((vector = cpu_get_pic_interrupt(v, type)) != -1) )
    7.36 +        return vector;
    7.37  
    7.38      return -1;
    7.39  }
     8.1 --- a/xen/arch/x86/hvm/i8259.c	Fri Nov 24 15:42:14 2006 +0000
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,515 +0,0 @@
     8.4 -/*
     8.5 - * i8259 interrupt controller emulation
     8.6 - * 
     8.7 - * Copyright (c) 2003-2004 Fabrice Bellard
     8.8 - * Copyright (c) 2005 Intel Corperation
     8.9 - * Copyright (c) 2006 Keir Fraser, XenSource Inc.
    8.10 - * 
    8.11 - * Permission is hereby granted, free of charge, to any person obtaining a copy
    8.12 - * of this software and associated documentation files (the "Software"), to
    8.13 - * deal in the Software without restriction, including without limitation the
    8.14 - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    8.15 - * sell copies of the Software, and to permit persons to whom the Software is
    8.16 - * furnished to do so, subject to the following conditions:
    8.17 - *
    8.18 - * The above copyright notice and this permission notice shall be included in
    8.19 - * all copies or substantial portions of the Software.
    8.20 - *
    8.21 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    8.22 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    8.23 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    8.24 - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    8.25 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    8.26 - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    8.27 - * IN THE SOFTWARE.
    8.28 - */
    8.29 -
    8.30 -#include <xen/config.h>
    8.31 -#include <xen/types.h>
    8.32 -#include <xen/mm.h>
    8.33 -#include <xen/xmalloc.h>
    8.34 -#include <xen/lib.h>
    8.35 -#include <xen/errno.h>
    8.36 -#include <xen/sched.h>
    8.37 -#include <asm/hvm/hvm.h>
    8.38 -#include <asm/hvm/io.h>
    8.39 -#include <asm/hvm/support.h>
    8.40 -#include <asm/current.h>
    8.41 -
    8.42 -static inline void pic_set_irq1(PicState *s, int irq, int level)
    8.43 -{
    8.44 -    int mask = 1 << irq;
    8.45 -
    8.46 -    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
    8.47 -
    8.48 -    if ( s->elcr & mask )
    8.49 -    {
    8.50 -        /* Level triggered. */
    8.51 -        if ( level )
    8.52 -        {
    8.53 -            s->irr |= mask;
    8.54 -            s->last_irr |= mask;
    8.55 -        }
    8.56 -        else
    8.57 -        {
    8.58 -            s->irr &= ~mask;
    8.59 -            s->last_irr &= ~mask;
    8.60 -        }
    8.61 -    }
    8.62 -    else
    8.63 -    {
    8.64 -        /* Edge triggered. */
    8.65 -        if ( level )
    8.66 -        {
    8.67 -            if ( (s->last_irr & mask) == 0 )
    8.68 -                s->irr |= mask;
    8.69 -            s->last_irr |= mask;
    8.70 -        }
    8.71 -        else
    8.72 -        {
    8.73 -            s->last_irr &= ~mask;
    8.74 -        }
    8.75 -    }
    8.76 -}
    8.77 -
    8.78 -/* Return the highest priority found in mask. Return 8 if no irq. */
    8.79 -static inline int get_priority(PicState *s, int mask)
    8.80 -{
    8.81 -    int priority;
    8.82 -
    8.83 -    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
    8.84 -
    8.85 -    if ( mask == 0 )
    8.86 -        return 8;
    8.87 -
    8.88 -    priority = 0;
    8.89 -    while ( (mask & (1 << ((priority + s->priority_add) & 7))) == 0 )
    8.90 -        priority++;
    8.91 -
    8.92 -    return priority;
    8.93 -}
    8.94 -
    8.95 -/* Return the PIC's highest priority pending interrupt. Return -1 if none. */
    8.96 -static int pic_get_irq(PicState *s)
    8.97 -{
    8.98 -    int mask, cur_priority, priority;
    8.99 -
   8.100 -    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
   8.101 -
   8.102 -    mask = s->irr & ~s->imr;
   8.103 -    priority = get_priority(s, mask);
   8.104 -    if ( priority == 8 )
   8.105 -        return -1;
   8.106 -
   8.107 -    /*
   8.108 -     * Compute current priority. If special fully nested mode on the master,
   8.109 -     * the IRQ coming from the slave is not taken into account for the
   8.110 -     * priority computation.
   8.111 -     */
   8.112 -    mask = s->isr;
   8.113 -    if ( s->special_fully_nested_mode && (s == &s->pics_state->pics[0]) )
   8.114 -        mask &= ~(1 << 2);
   8.115 -    cur_priority = get_priority(s, mask);
   8.116 -    if ( priority < cur_priority )
   8.117 -        /* Higher priority found: an irq should be generated. */
   8.118 -        return (priority + s->priority_add) & 7;
   8.119 -
   8.120 -    return -1;
   8.121 -}
   8.122 -
   8.123 -/* Raise irq to CPU if necessary. */
   8.124 -static void pic_update_irq(struct vpic *vpic)
   8.125 -{
   8.126 -    int irq2, irq;
   8.127 -
   8.128 -    ASSERT(spin_is_locked(vpic_lock(vpic)));
   8.129 -
   8.130 -    /* First look at slave PIC. */
   8.131 -    irq2 = pic_get_irq(&vpic->pics[1]);
   8.132 -    if ( irq2 >= 0 )
   8.133 -    {
   8.134 -        /* If irq request by slave pic, signal master PIC. */
   8.135 -        pic_set_irq1(&vpic->pics[0], 2, 1);
   8.136 -        pic_set_irq1(&vpic->pics[0], 2, 0);
   8.137 -    }
   8.138 -
   8.139 -    /* Look at requested IRQ. */
   8.140 -    irq = pic_get_irq(&vpic->pics[0]);
   8.141 -    if ( irq >= 0 )
   8.142 -        vpic->irq_pending = 1;
   8.143 -}
   8.144 -
   8.145 -void pic_set_irq(struct vpic *vpic, int irq, int level)
   8.146 -{
   8.147 -    ASSERT(spin_is_locked(vpic_lock(vpic)));
   8.148 -    pic_set_irq1(&vpic->pics[irq >> 3], irq & 7, level);
   8.149 -    pic_update_irq(vpic);
   8.150 -}
   8.151 -
   8.152 -/* Acknowledge interrupt @irq. */
   8.153 -static inline void pic_intack(PicState *s, int irq)
   8.154 -{
   8.155 -    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
   8.156 -
   8.157 -    if ( s->auto_eoi )
   8.158 -    {
   8.159 -        if ( s->rotate_on_auto_eoi )
   8.160 -            s->priority_add = (irq + 1) & 7;
   8.161 -    }
   8.162 -    else
   8.163 -    {
   8.164 -        s->isr |= (1 << irq);
   8.165 -    }
   8.166 -
   8.167 -    /* We don't clear a level sensitive interrupt here */
   8.168 -    if ( !(s->elcr & (1 << irq)) )
   8.169 -        s->irr &= ~(1 << irq);
   8.170 -}
   8.171 -
   8.172 -static int pic_read_irq(struct vpic *vpic)
   8.173 -{
   8.174 -    int irq, irq2, intno;
   8.175 -
   8.176 -    spin_lock(vpic_lock(vpic));
   8.177 -
   8.178 -    irq = pic_get_irq(&vpic->pics[0]);
   8.179 -    if ( irq >= 0 )
   8.180 -    {
   8.181 -        pic_intack(&vpic->pics[0], irq);
   8.182 -        if ( irq == 2 )
   8.183 -        {
   8.184 -            irq2 = pic_get_irq(&vpic->pics[1]);
   8.185 -            if ( irq2 >= 0 )
   8.186 -            {
   8.187 -                pic_intack(&vpic->pics[1], irq2);
   8.188 -            }
   8.189 -            else
   8.190 -            {
   8.191 -		gdprintk(XENLOG_WARNING, "Spurious irq on slave i8259.\n");
   8.192 -                irq2 = 7;
   8.193 -            }
   8.194 -            intno = vpic->pics[1].irq_base + irq2;
   8.195 -            irq = irq2 + 8;
   8.196 -        }
   8.197 -        else
   8.198 -        {
   8.199 -            intno = vpic->pics[0].irq_base + irq;
   8.200 -        }
   8.201 -    }
   8.202 -    else
   8.203 -    {
   8.204 -        irq = 7;
   8.205 -        intno = vpic->pics[0].irq_base + irq;
   8.206 -	gdprintk(XENLOG_WARNING, "Spurious irq on master i8259.\n");
   8.207 -    }
   8.208 -
   8.209 -    pic_update_irq(vpic);
   8.210 -
   8.211 -    spin_unlock(vpic_lock(vpic));
   8.212 -
   8.213 -    return intno;
   8.214 -}
   8.215 -
   8.216 -static void pic_reset(void *opaque)
   8.217 -{
   8.218 -    PicState *s = opaque;
   8.219 -
   8.220 -    s->last_irr = 0;
   8.221 -    s->irr = 0;
   8.222 -    s->imr = 0;
   8.223 -    s->isr = 0;
   8.224 -    s->priority_add = 0;
   8.225 -    s->irq_base = 0;
   8.226 -    s->read_reg_select = 0;
   8.227 -    s->poll = 0;
   8.228 -    s->special_mask = 0;
   8.229 -    s->init_state = 0;
   8.230 -    s->auto_eoi = 0;
   8.231 -    s->rotate_on_auto_eoi = 0;
   8.232 -    s->special_fully_nested_mode = 0;
   8.233 -    s->init4 = 0;
   8.234 -    /* Note: ELCR is not reset */
   8.235 -}
   8.236 -
   8.237 -static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
   8.238 -{
   8.239 -    PicState *s = opaque;
   8.240 -    int priority, cmd, irq;
   8.241 -
   8.242 -    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
   8.243 -
   8.244 -    addr &= 1;
   8.245 -    if ( addr == 0 )
   8.246 -    {
   8.247 -        if ( val & 0x10 )
   8.248 -        {
   8.249 -            pic_reset(s);
   8.250 -            s->pics_state->irq_pending = 0;
   8.251 -            s->init_state = 1;
   8.252 -            s->init4 = val & 1;
   8.253 -        }
   8.254 -        else if ( val & 0x08 )
   8.255 -        {
   8.256 -            if ( val & 0x04 )
   8.257 -                s->poll = 1;
   8.258 -            if ( val & 0x02 )
   8.259 -                s->read_reg_select = val & 1;
   8.260 -            if ( val & 0x40 )
   8.261 -                s->special_mask = (val >> 5) & 1;
   8.262 -        }
   8.263 -        else
   8.264 -        {
   8.265 -            cmd = val >> 5;
   8.266 -            switch ( cmd )
   8.267 -            {
   8.268 -            case 0:
   8.269 -            case 4:
   8.270 -                s->rotate_on_auto_eoi = cmd >> 2;
   8.271 -                break;
   8.272 -            case 1:
   8.273 -            case 5:
   8.274 -                priority = get_priority(s, s->isr);
   8.275 -                if (priority != 8) {
   8.276 -                    irq = (priority + s->priority_add) & 7;
   8.277 -                    s->isr &= ~(1 << irq);
   8.278 -                    if (cmd == 5)
   8.279 -                        s->priority_add = (irq + 1) & 7;
   8.280 -                    pic_update_irq(s->pics_state);
   8.281 -                }
   8.282 -                break;
   8.283 -            case 3:
   8.284 -                irq = val & 7;
   8.285 -                s->isr &= ~(1 << irq);
   8.286 -                pic_update_irq(s->pics_state);
   8.287 -                break;
   8.288 -            case 6:
   8.289 -                s->priority_add = (val + 1) & 7;
   8.290 -                pic_update_irq(s->pics_state);
   8.291 -                break;
   8.292 -            case 7:
   8.293 -                irq = val & 7;
   8.294 -                s->isr &= ~(1 << irq);
   8.295 -                s->priority_add = (irq + 1) & 7;
   8.296 -                pic_update_irq(s->pics_state);
   8.297 -                break;
   8.298 -            default:
   8.299 -                break;
   8.300 -            }
   8.301 -        }
   8.302 -    }
   8.303 -    else
   8.304 -    {
   8.305 -        switch ( s->init_state )
   8.306 -        {
   8.307 -        case 0:
   8.308 -            s->imr = val;
   8.309 -            pic_update_irq(s->pics_state);
   8.310 -            break;
   8.311 -        case 1:
   8.312 -            s->irq_base = val & 0xf8;
   8.313 -            s->init_state = 2;
   8.314 -            break;
   8.315 -        case 2:
   8.316 -            s->init_state = s->init4 ? 3 : 0;
   8.317 -            break;
   8.318 -        case 3:
   8.319 -            s->special_fully_nested_mode = (val >> 4) & 1;
   8.320 -            s->auto_eoi = (val >> 1) & 1;
   8.321 -            s->init_state = 0;
   8.322 -            break;
   8.323 -        }
   8.324 -    }
   8.325 -}
   8.326 -
   8.327 -static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
   8.328 -{
   8.329 -    int ret;
   8.330 -
   8.331 -    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
   8.332 -
   8.333 -    ret = pic_get_irq(s);
   8.334 -    if ( ret >= 0 )
   8.335 -    {
   8.336 -        if ( addr1 >> 7 )
   8.337 -        {
   8.338 -            s->pics_state->pics[0].isr &= ~(1 << 2);
   8.339 -            s->pics_state->pics[0].irr &= ~(1 << 2);
   8.340 -        }
   8.341 -        s->irr &= ~(1 << ret);
   8.342 -        s->isr &= ~(1 << ret);
   8.343 -        if ( (addr1 >> 7) || (ret != 2) )
   8.344 -            pic_update_irq(s->pics_state);
   8.345 -    }
   8.346 -    else
   8.347 -    {
   8.348 -        ret = 0x07;
   8.349 -        pic_update_irq(s->pics_state);
   8.350 -    }
   8.351 -
   8.352 -    return ret;
   8.353 -}
   8.354 -
   8.355 -static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
   8.356 -{
   8.357 -    PicState *s = opaque;
   8.358 -
   8.359 -    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
   8.360 -
   8.361 -    if ( s->poll )
   8.362 -    {
   8.363 -        s->poll = 0;
   8.364 -        return pic_poll_read(s, addr1);
   8.365 -    }
   8.366 -
   8.367 -    if ( (addr1 & 1) == 0 )
   8.368 -        return (s->read_reg_select ? s->isr : s->irr);
   8.369 -
   8.370 -    return s->imr;
   8.371 -}
   8.372 -
   8.373 -static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
   8.374 -{
   8.375 -    PicState *s = opaque;
   8.376 -
   8.377 -    ASSERT(spin_is_locked(vpic_lock(s->pics_state)));
   8.378 -
   8.379 -    s->elcr = val & s->elcr_mask;
   8.380 -}
   8.381 -
   8.382 -static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1)
   8.383 -{
   8.384 -    PicState *s = opaque;
   8.385 -    return s->elcr;
   8.386 -}
   8.387 -
   8.388 -static void pic_init1(int io_addr, int elcr_addr, PicState *s)
   8.389 -{
   8.390 -    pic_reset(s);
   8.391 -}
   8.392 -
   8.393 -void pic_init(struct vpic *vpic)
   8.394 -{
   8.395 -    memset(vpic, 0, sizeof(*vpic));
   8.396 -    spin_lock_init(vpic_lock(vpic));
   8.397 -    vpic->pics[0].pics_state = vpic;
   8.398 -    vpic->pics[1].pics_state = vpic;
   8.399 -    vpic->pics[0].elcr_mask = 0xf8;
   8.400 -    vpic->pics[1].elcr_mask = 0xde;
   8.401 -    pic_init1(0x20, 0x4d0, &vpic->pics[0]);
   8.402 -    pic_init1(0xa0, 0x4d1, &vpic->pics[1]);
   8.403 -}
   8.404 -
   8.405 -static int intercept_pic_io(ioreq_t *p)
   8.406 -{
   8.407 -    struct vpic *vpic = domain_vpic(current->domain);
   8.408 -    uint32_t data;
   8.409 -
   8.410 -    if ( (p->size != 1) || (p->count != 1) )
   8.411 -    {
   8.412 -        gdprintk(XENLOG_WARNING,
   8.413 -                 "PIC_IO wrong access size %d!\n", (int)p->size);
   8.414 -        return 1;
   8.415 -    }
   8.416 -
   8.417 -    if ( p->dir == IOREQ_WRITE )
   8.418 -    {
   8.419 -        if ( p->data_is_ptr )
   8.420 -            (void)hvm_copy_from_guest_phys(&data, p->data, p->size);
   8.421 -        else
   8.422 -            data = p->data;
   8.423 -        spin_lock(vpic_lock(vpic));
   8.424 -        pic_ioport_write((void*)&vpic->pics[p->addr>>7],
   8.425 -                (uint32_t) p->addr, (uint32_t) (data & 0xff));
   8.426 -        spin_unlock(vpic_lock(vpic));
   8.427 -    }
   8.428 -    else
   8.429 -    {
   8.430 -        spin_lock(vpic_lock(vpic));
   8.431 -        data = pic_ioport_read(
   8.432 -            (void*)&vpic->pics[p->addr>>7], (uint32_t) p->addr);
   8.433 -        spin_unlock(vpic_lock(vpic));
   8.434 -        if ( p->data_is_ptr )
   8.435 -            (void)hvm_copy_to_guest_phys(p->data, &data, p->size);
   8.436 -        else
   8.437 -            p->data = (u64)data;
   8.438 -    }
   8.439 -
   8.440 -    return 1;
   8.441 -}
   8.442 -
   8.443 -static int intercept_elcr_io(ioreq_t *p)
   8.444 -{
   8.445 -    struct vpic *vpic = domain_vpic(current->domain);
   8.446 -    uint32_t data;
   8.447 -
   8.448 -    if ( (p->size != 1) || (p->count != 1) )
   8.449 -    {
   8.450 -        gdprintk(XENLOG_WARNING,
   8.451 -                 "PIC_IO wrong access size %d!\n", (int)p->size);
   8.452 -        return 1;
   8.453 -    }
   8.454 -
   8.455 -    if ( p->dir == IOREQ_WRITE )
   8.456 -    {
   8.457 -        if ( p->data_is_ptr )
   8.458 -            (void)hvm_copy_from_guest_phys(&data, p->data, p->size);
   8.459 -        else
   8.460 -            data = p->data;
   8.461 -        spin_lock(vpic_lock(vpic));
   8.462 -        elcr_ioport_write((void*)&vpic->pics[p->addr&1],
   8.463 -                (uint32_t) p->addr, (uint32_t)( data & 0xff));
   8.464 -        spin_unlock(vpic_lock(vpic));
   8.465 -    }
   8.466 -    else
   8.467 -    {
   8.468 -        data = (u64) elcr_ioport_read(
   8.469 -                (void*)&vpic->pics[p->addr&1], (uint32_t) p->addr);
   8.470 -        if ( p->data_is_ptr )
   8.471 -            (void)hvm_copy_to_guest_phys(p->data, &data, p->size);
   8.472 -        else
   8.473 -            p->data = (u64)data;
   8.474 -    }
   8.475 -
   8.476 -    return 1;
   8.477 -}
   8.478 -
   8.479 -void register_pic_io_hook(struct domain *d)
   8.480 -{
   8.481 -    register_portio_handler(d, 0x20, 2, intercept_pic_io);
   8.482 -    register_portio_handler(d, 0x4d0, 1, intercept_elcr_io);
   8.483 -    register_portio_handler(d, 0xa0, 2, intercept_pic_io);
   8.484 -    register_portio_handler(d, 0x4d1, 1, intercept_elcr_io);
   8.485 -}
   8.486 -
   8.487 -int cpu_get_pic_interrupt(struct vcpu *v, int *type)
   8.488 -{
   8.489 -    int intno;
   8.490 -    struct vpic *vpic = domain_vpic(v->domain);
   8.491 -
   8.492 -    if ( !vlapic_accept_pic_intr(v) )
   8.493 -        return -1;
   8.494 -
   8.495 -    if ( xchg(&vpic->irq_pending, 0) == 0 )
   8.496 -        return -1;
   8.497 -
   8.498 -    /* Read the irq from the PIC. */
   8.499 -    intno = pic_read_irq(vpic);
   8.500 -    *type = APIC_DM_EXTINT;
   8.501 -    return intno;
   8.502 -}
   8.503 -
   8.504 -int is_periodic_irq(struct vcpu *v, int irq, int type)
   8.505 -{
   8.506 -    int vec;
   8.507 -    struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
   8.508 -
   8.509 -    if ( pt->irq != 0 )
   8.510 -        return 0;
   8.511 -
   8.512 -    if ( type == APIC_DM_EXTINT )
   8.513 -        vec = domain_vpic(v->domain)->pics[0].irq_base;
   8.514 -    else
   8.515 -        vec = domain_vioapic(v->domain)->redirtbl[0].fields.vector;
   8.516 -
   8.517 -    return (irq == vec);
   8.518 -}
     9.1 --- a/xen/arch/x86/hvm/irq.c	Fri Nov 24 15:42:14 2006 +0000
     9.2 +++ b/xen/arch/x86/hvm/irq.c	Sun Nov 26 13:37:27 2006 +0000
     9.3 @@ -48,7 +48,7 @@ void hvm_pci_intx_assert(
     9.4           (hvm_irq->gsi_assert_count[isa_irq]++ == 0) )
     9.5      {
     9.6          vioapic_irq_positive_edge(d, isa_irq);
     9.7 -        pic_set_irq(&hvm_irq->vpic, isa_irq, 1);
     9.8 +        vpic_irq_positive_edge(d, isa_irq);
     9.9      }
    9.10  
    9.11   out:
    9.12 @@ -75,7 +75,7 @@ void hvm_pci_intx_deassert(
    9.13      isa_irq = hvm_irq->pci_link_route[link];
    9.14      if ( (--hvm_irq->pci_link_assert_count[link] == 0) && isa_irq &&
    9.15           (--hvm_irq->gsi_assert_count[isa_irq] == 0) )
    9.16 -        pic_set_irq(&hvm_irq->vpic, isa_irq, 0);
    9.17 +        vpic_irq_negative_edge(d, isa_irq);
    9.18  
    9.19   out:
    9.20      spin_unlock(&hvm_irq->lock);
    9.21 @@ -94,7 +94,7 @@ void hvm_isa_irq_assert(
    9.22           (hvm_irq->gsi_assert_count[isa_irq]++ == 0) )
    9.23      {
    9.24          vioapic_irq_positive_edge(d, isa_irq);
    9.25 -        pic_set_irq(&hvm_irq->vpic, isa_irq, 1);
    9.26 +        vpic_irq_positive_edge(d, isa_irq);
    9.27      }
    9.28  
    9.29      spin_unlock(&hvm_irq->lock);
    9.30 @@ -111,7 +111,7 @@ void hvm_isa_irq_deassert(
    9.31  
    9.32      if ( __test_and_clear_bit(isa_irq, &hvm_irq->isa_irq) &&
    9.33           (--hvm_irq->gsi_assert_count[isa_irq] == 0) )
    9.34 -        pic_set_irq(&hvm_irq->vpic, isa_irq, 0);
    9.35 +        vpic_irq_negative_edge(d, isa_irq);
    9.36  
    9.37      spin_unlock(&hvm_irq->lock);
    9.38  }
    9.39 @@ -140,7 +140,7 @@ void hvm_set_callback_irq_level(void)
    9.40          {
    9.41              vioapic_irq_positive_edge(d, gsi);
    9.42              if ( gsi <= 15 )
    9.43 -                pic_set_irq(&hvm_irq->vpic, gsi, 1);
    9.44 +                vpic_irq_positive_edge(d, gsi);
    9.45          }
    9.46      }
    9.47      else
    9.48 @@ -149,7 +149,7 @@ void hvm_set_callback_irq_level(void)
    9.49               (--hvm_irq->gsi_assert_count[gsi] == 0) )
    9.50          {
    9.51              if ( gsi <= 15 )
    9.52 -                pic_set_irq(&hvm_irq->vpic, gsi, 0);
    9.53 +                vpic_irq_negative_edge(d, gsi);
    9.54          }
    9.55      }
    9.56  
    9.57 @@ -175,12 +175,12 @@ void hvm_set_pci_link_route(struct domai
    9.58          goto out;
    9.59  
    9.60      if ( old_isa_irq && (--hvm_irq->gsi_assert_count[old_isa_irq] == 0) )
    9.61 -        pic_set_irq(&hvm_irq->vpic, isa_irq, 0);
    9.62 +        vpic_irq_negative_edge(d, isa_irq);
    9.63  
    9.64      if ( isa_irq && (hvm_irq->gsi_assert_count[isa_irq]++ == 0) )
    9.65      {
    9.66          vioapic_irq_positive_edge(d, isa_irq);
    9.67 -        pic_set_irq(&hvm_irq->vpic, isa_irq, 1);
    9.68 +        vpic_irq_positive_edge(d, isa_irq);
    9.69      }
    9.70  
    9.71   out:
    9.72 @@ -210,13 +210,13 @@ void hvm_set_callback_gsi(struct domain 
    9.73  
    9.74      if ( old_gsi && (--hvm_irq->gsi_assert_count[old_gsi] == 0) )
    9.75          if ( old_gsi <= 15 )
    9.76 -            pic_set_irq(&hvm_irq->vpic, old_gsi, 0);
    9.77 +            vpic_irq_negative_edge(d, old_gsi);
    9.78  
    9.79      if ( gsi && (hvm_irq->gsi_assert_count[gsi]++ == 0) )
    9.80      {
    9.81          vioapic_irq_positive_edge(d, gsi);
    9.82          if ( gsi <= 15 )
    9.83 -            pic_set_irq(&hvm_irq->vpic, gsi, 1);
    9.84 +            vpic_irq_positive_edge(d, gsi);
    9.85      }
    9.86  
    9.87   out:
    10.1 --- a/xen/arch/x86/hvm/svm/intr.c	Fri Nov 24 15:42:14 2006 +0000
    10.2 +++ b/xen/arch/x86/hvm/svm/intr.c	Sun Nov 26 13:37:27 2006 +0000
    10.3 @@ -128,32 +128,33 @@ asmlinkage void svm_intr_assist(void)
    10.4      }
    10.5  
    10.6      /* have we got an interrupt to inject? */
    10.7 -    if ( intr_vector >= 0 )
    10.8 +    if ( intr_vector < 0 )
    10.9 +        return;
   10.10 +
   10.11 +    switch ( intr_type )
   10.12      {
   10.13 -        switch ( intr_type )
   10.14 -        {
   10.15 -        case APIC_DM_EXTINT:
   10.16 -        case APIC_DM_FIXED:
   10.17 -        case APIC_DM_LOWEST:
   10.18 -            /* Re-injecting a PIT interruptt? */
   10.19 -            if ( re_injecting && pt->enabled && 
   10.20 -                 is_periodic_irq(v, intr_vector, intr_type) )
   10.21 -                ++pt->pending_intr_nr;
   10.22 -            /* let's inject this interrupt */
   10.23 -            TRACE_3D(TRC_VMX_INTR, v->domain->domain_id, intr_vector, 0);
   10.24 -            svm_inject_extint(v, intr_vector);
   10.25 -            break;
   10.26 -        case APIC_DM_SMI:
   10.27 -        case APIC_DM_NMI:
   10.28 -        case APIC_DM_INIT:
   10.29 -        case APIC_DM_STARTUP:
   10.30 -        default:
   10.31 -            printk("Unsupported interrupt type: %d\n", intr_type);
   10.32 -            BUG();
   10.33 -            break;
   10.34 -        }
   10.35 -        hvm_interrupt_post(v, intr_vector, intr_type);
   10.36 +    case APIC_DM_EXTINT:
   10.37 +    case APIC_DM_FIXED:
   10.38 +    case APIC_DM_LOWEST:
   10.39 +        /* Re-injecting a PIT interruptt? */
   10.40 +        if ( re_injecting && pt->enabled && 
   10.41 +             is_periodic_irq(v, intr_vector, intr_type) )
   10.42 +            ++pt->pending_intr_nr;
   10.43 +        /* let's inject this interrupt */
   10.44 +        TRACE_3D(TRC_VMX_INTR, v->domain->domain_id, intr_vector, 0);
   10.45 +        svm_inject_extint(v, intr_vector);
   10.46 +        break;
   10.47 +    case APIC_DM_SMI:
   10.48 +    case APIC_DM_NMI:
   10.49 +    case APIC_DM_INIT:
   10.50 +    case APIC_DM_STARTUP:
   10.51 +    default:
   10.52 +        printk("Unsupported interrupt type: %d\n", intr_type);
   10.53 +        BUG();
   10.54 +        break;
   10.55      }
   10.56 +
   10.57 +    hvm_interrupt_post(v, intr_vector, intr_type);
   10.58  }
   10.59  
   10.60  /*
    11.1 --- a/xen/arch/x86/hvm/vlapic.c	Fri Nov 24 15:42:14 2006 +0000
    11.2 +++ b/xen/arch/x86/hvm/vlapic.c	Sun Nov 26 13:37:27 2006 +0000
    11.3 @@ -2,6 +2,7 @@
    11.4   * vlapic.c: virtualize LAPIC for HVM vcpus.
    11.5   *
    11.6   * Copyright (c) 2004, Intel Corporation.
    11.7 + * Copyright (c) 2006 Keir Fraser, XenSource Inc.
    11.8   *
    11.9   * This program is free software; you can redistribute it and/or modify it
   11.10   * under the terms and conditions of the GNU General Public License,
   11.11 @@ -38,9 +39,6 @@
   11.12  #define VLAPIC_VERSION                  0x00050014
   11.13  #define VLAPIC_LVT_NUM                  6
   11.14  
   11.15 -/* XXX remove this definition after GFW enabled */
   11.16 -#define VLAPIC_NO_BIOS
   11.17 -
   11.18  extern u32 get_apic_bus_cycle(void);
   11.19  
   11.20  #define APIC_BUS_CYCLE_NS (((s_time_t)get_apic_bus_cycle()) / 1000)
   11.21 @@ -147,7 +145,6 @@ int vlapic_find_highest_irr(struct vlapi
   11.22      return result;
   11.23  }
   11.24  
   11.25 -
   11.26  int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig)
   11.27  {
   11.28      int ret;
   11.29 @@ -860,7 +857,7 @@ int cpu_has_pending_irq(struct vcpu *v)
   11.30      if ( !vlapic_accept_pic_intr(v) )
   11.31          return 0;
   11.32  
   11.33 -    return plat->irq.vpic.irq_pending;
   11.34 +    return plat->irq.vpic[0].int_output;
   11.35  }
   11.36  
   11.37  void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode)
   11.38 @@ -960,15 +957,6 @@ int vlapic_init(struct vcpu *v)
   11.39      init_timer(&vlapic->vlapic_timer,
   11.40                    vlapic_timer_fn, vlapic, v->processor);
   11.41  
   11.42 -#ifdef VLAPIC_NO_BIOS
   11.43 -    /* According to mp specification, BIOS will enable LVT0/1. */
   11.44 -    if ( v->vcpu_id == 0 )
   11.45 -    {
   11.46 -        vlapic_set_reg(vlapic, APIC_LVT0, APIC_MODE_EXTINT << 8);
   11.47 -        vlapic_set_reg(vlapic, APIC_LVT1, APIC_MODE_NMI << 8);
   11.48 -    }
   11.49 -#endif
   11.50 -
   11.51      return 0;
   11.52  }
   11.53  
    12.1 --- a/xen/arch/x86/hvm/vmx/io.c	Fri Nov 24 15:42:14 2006 +0000
    12.2 +++ b/xen/arch/x86/hvm/vmx/io.c	Sun Nov 26 13:37:27 2006 +0000
    12.3 @@ -115,7 +115,8 @@ asmlinkage void vmx_intr_assist(void)
    12.4  
    12.5      has_ext_irq = cpu_has_pending_irq(v);
    12.6  
    12.7 -    if (unlikely(v->arch.hvm_vmx.vector_injected)) {
    12.8 +    if ( unlikely(v->arch.hvm_vmx.vector_injected) )
    12.9 +    {
   12.10          v->arch.hvm_vmx.vector_injected=0;
   12.11          if (unlikely(has_ext_irq)) enable_irq_window(v);
   12.12          return;
   12.13 @@ -123,7 +124,8 @@ asmlinkage void vmx_intr_assist(void)
   12.14  
   12.15      /* This could be moved earlier in the VMX resume sequence. */
   12.16      idtv_info_field = __vmread(IDT_VECTORING_INFO_FIELD);
   12.17 -    if (unlikely(idtv_info_field & INTR_INFO_VALID_MASK)) {
   12.18 +    if ( unlikely(idtv_info_field & INTR_INFO_VALID_MASK) )
   12.19 +    {
   12.20          __vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
   12.21  
   12.22          /*
   12.23 @@ -145,9 +147,11 @@ asmlinkage void vmx_intr_assist(void)
   12.24          return;
   12.25      }
   12.26  
   12.27 -    if (likely(!has_ext_irq)) return;
   12.28 +    if ( likely(!has_ext_irq) )
   12.29 +        return;
   12.30  
   12.31 -    if (unlikely(is_interruptibility_state())) {    
   12.32 +    if ( unlikely(is_interruptibility_state()) )
   12.33 +    {
   12.34          /* pre-cleared for emulated instruction */
   12.35          enable_irq_window(v);
   12.36          HVM_DBG_LOG(DBG_LEVEL_1, "interruptibility");
   12.37 @@ -155,13 +159,18 @@ asmlinkage void vmx_intr_assist(void)
   12.38      }
   12.39  
   12.40      eflags = __vmread(GUEST_RFLAGS);
   12.41 -    if (irq_masked(eflags)) {
   12.42 +    if ( irq_masked(eflags) )
   12.43 +    {
   12.44          enable_irq_window(v);
   12.45          return;
   12.46      }
   12.47  
   12.48      highest_vector = cpu_get_interrupt(v, &intr_type);
   12.49 -    switch (intr_type) {
   12.50 +    if ( highest_vector < 0 )
   12.51 +        return;
   12.52 +
   12.53 +    switch ( intr_type )
   12.54 +    {
   12.55      case APIC_DM_EXTINT:
   12.56      case APIC_DM_FIXED:
   12.57      case APIC_DM_LOWEST:
   12.58 @@ -180,7 +189,6 @@ asmlinkage void vmx_intr_assist(void)
   12.59      }
   12.60      
   12.61      hvm_interrupt_post(v, highest_vector, intr_type);
   12.62 -    return;
   12.63  }
   12.64  
   12.65  /*
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/xen/arch/x86/hvm/vpic.c	Sun Nov 26 13:37:27 2006 +0000
    13.3 @@ -0,0 +1,463 @@
    13.4 +/*
    13.5 + * i8259 interrupt controller emulation
    13.6 + * 
    13.7 + * Copyright (c) 2003-2004 Fabrice Bellard
    13.8 + * Copyright (c) 2005 Intel Corperation
    13.9 + * Copyright (c) 2006 Keir Fraser, XenSource Inc.
   13.10 + * 
   13.11 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   13.12 + * of this software and associated documentation files (the "Software"), to
   13.13 + * deal in the Software without restriction, including without limitation the
   13.14 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   13.15 + * sell copies of the Software, and to permit persons to whom the Software is
   13.16 + * furnished to do so, subject to the following conditions:
   13.17 + *
   13.18 + * The above copyright notice and this permission notice shall be included in
   13.19 + * all copies or substantial portions of the Software.
   13.20 + *
   13.21 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   13.22 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   13.23 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   13.24 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   13.25 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   13.26 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   13.27 + * IN THE SOFTWARE.
   13.28 + */
   13.29 +
   13.30 +#include <xen/config.h>
   13.31 +#include <xen/types.h>
   13.32 +#include <xen/event.h>
   13.33 +#include <xen/lib.h>
   13.34 +#include <xen/errno.h>
   13.35 +#include <xen/sched.h>
   13.36 +#include <asm/hvm/hvm.h>
   13.37 +#include <asm/hvm/io.h>
   13.38 +#include <asm/hvm/support.h>
   13.39 +
   13.40 +#define vpic_domain(v) (container_of((v), struct domain, \
   13.41 +                        arch.hvm_domain.irq.vpic[!vpic->is_master]))
   13.42 +#define __vpic_lock(v) &container_of((v), struct hvm_irq, \
   13.43 +                                     vpic[!(v)->is_master])->lock
   13.44 +#define vpic_lock(v)   spin_lock(__vpic_lock(v))
   13.45 +#define vpic_unlock(v) spin_unlock(__vpic_lock(v))
   13.46 +#define vpic_is_locked(v) spin_is_locked(__vpic_lock(v))
   13.47 +#define vpic_elcr_mask(v) (vpic->is_master ? (uint8_t)0xd8 : (uint8_t)0xfe);
   13.48 +
   13.49 +/* Return the highest priority found in mask. Return 8 if none. */
   13.50 +#define VPIC_PRIO_NONE 8
   13.51 +static int vpic_get_priority(struct vpic *vpic, uint8_t mask)
   13.52 +{
   13.53 +    int prio;
   13.54 +
   13.55 +    ASSERT(vpic_is_locked(vpic));
   13.56 +
   13.57 +    if ( mask == 0 )
   13.58 +        return VPIC_PRIO_NONE;
   13.59 +
   13.60 +    /* prio = ffs(mask ROL vpic->priority_add); */
   13.61 +    asm ( "rol %%cl,%b1 ; bsf %1,%0"
   13.62 +          : "=r" (prio) : "r" ((uint32_t)mask), "c" (vpic->priority_add) );
   13.63 +    return prio;
   13.64 +}
   13.65 +
   13.66 +/* Return the PIC's highest priority pending interrupt. Return -1 if none. */
   13.67 +static int vpic_get_highest_priority_irq(struct vpic *vpic)
   13.68 +{
   13.69 +    int cur_priority, priority, irq;
   13.70 +    uint8_t mask;
   13.71 +
   13.72 +    ASSERT(vpic_is_locked(vpic));
   13.73 +
   13.74 +    mask = vpic->irr & ~vpic->imr;
   13.75 +    priority = vpic_get_priority(vpic, mask);
   13.76 +    if ( priority == VPIC_PRIO_NONE )
   13.77 +        return -1;
   13.78 +
   13.79 +    irq = (priority + vpic->priority_add) & 7;
   13.80 +
   13.81 +    /*
   13.82 +     * Compute current priority. If special fully nested mode on the master,
   13.83 +     * the IRQ coming from the slave is not taken into account for the
   13.84 +     * priority computation. In special mask mode, masked interrupts do not
   13.85 +     * block lower-priority interrupts even if their IS bit is set.
   13.86 +     */
   13.87 +    mask = vpic->isr;
   13.88 +    if ( vpic->special_fully_nested_mode && vpic->is_master && (irq == 2) )
   13.89 +        mask &= ~(1 << 2);
   13.90 +    if ( vpic->special_mask_mode )
   13.91 +        mask &= ~vpic->imr;
   13.92 +    cur_priority = vpic_get_priority(vpic, mask);
   13.93 +
   13.94 +    /* If a higher priority is found then an irq should be generated. */
   13.95 +    return (priority < cur_priority) ? irq : -1;
   13.96 +}
   13.97 +
   13.98 +static void vpic_update_int_output(struct vpic *vpic)
   13.99 +{
  13.100 +    int irq;
  13.101 +
  13.102 +    ASSERT(vpic_is_locked(vpic));
  13.103 +
  13.104 +    irq = vpic_get_highest_priority_irq(vpic);
  13.105 +    if ( vpic->int_output == (irq >= 0) )
  13.106 +        return;
  13.107 +
  13.108 +    /* INT line transition L->H or H->L. */
  13.109 +    vpic->int_output = !vpic->int_output;
  13.110 +
  13.111 +    if ( vpic->int_output )
  13.112 +    {
  13.113 +        if ( vpic->is_master )
  13.114 +        {
  13.115 +            /* Master INT line is connected to VCPU0's VLAPIC LVT0. */
  13.116 +            struct vcpu *v = vpic_domain(vpic)->vcpu[0];
  13.117 +            if ( (v != NULL) && vlapic_accept_pic_intr(v) )
  13.118 +                vcpu_kick(v);
  13.119 +        }
  13.120 +        else
  13.121 +        {
  13.122 +            /* Assert slave line in master PIC. */
  13.123 +            (--vpic)->irr |= 1 << 2;
  13.124 +            vpic_update_int_output(vpic);
  13.125 +        }
  13.126 +    }
  13.127 +    else if ( !vpic->is_master )
  13.128 +    {
  13.129 +        /* Clear slave line in master PIC. */
  13.130 +        (--vpic)->irr &= ~(1 << 2);
  13.131 +        vpic_update_int_output(vpic);
  13.132 +    }
  13.133 +}
  13.134 +
  13.135 +static void __vpic_intack(struct vpic *vpic, int irq)
  13.136 +{
  13.137 +    uint8_t mask = 1 << irq;
  13.138 +
  13.139 +    ASSERT(vpic_is_locked(vpic));
  13.140 +
  13.141 +    /* Edge-triggered: clear the IRR (forget the edge). */
  13.142 +    if ( !(vpic->elcr & mask) )
  13.143 +        vpic->irr &= ~mask;
  13.144 +
  13.145 +    if ( !vpic->auto_eoi )
  13.146 +        vpic->isr |= mask;
  13.147 +    else if ( vpic->rotate_on_auto_eoi )
  13.148 +        vpic->priority_add = (irq + 1) & 7;
  13.149 +
  13.150 +    vpic_update_int_output(vpic);
  13.151 +}
  13.152 +
  13.153 +static int vpic_intack(struct vpic *vpic)
  13.154 +{
  13.155 +    int irq = -1;
  13.156 +
  13.157 +    vpic_lock(vpic);
  13.158 +
  13.159 +    if ( !vpic->int_output )
  13.160 +        goto out;
  13.161 +
  13.162 +    irq = vpic_get_highest_priority_irq(vpic);
  13.163 +    BUG_ON(irq < 0);
  13.164 +    __vpic_intack(vpic, irq);
  13.165 +
  13.166 +    if ( (irq == 2) && vpic->is_master )
  13.167 +    {
  13.168 +        vpic++; /* Slave PIC */
  13.169 +        irq = vpic_get_highest_priority_irq(vpic);
  13.170 +        BUG_ON(irq < 0);
  13.171 +        __vpic_intack(vpic, irq);
  13.172 +        irq += 8;
  13.173 +    }
  13.174 +
  13.175 + out:
  13.176 +    vpic_unlock(vpic);
  13.177 +    return irq;
  13.178 +}
  13.179 +
  13.180 +static void vpic_ioport_write(struct vpic *vpic, uint32_t addr, uint32_t val)
  13.181 +{
  13.182 +    int priority, cmd, irq;
  13.183 +    uint8_t mask;
  13.184 +
  13.185 +    vpic_lock(vpic);
  13.186 +
  13.187 +    addr &= 1;
  13.188 +    if ( addr == 0 )
  13.189 +    {
  13.190 +        if ( val & 0x10 )
  13.191 +        {
  13.192 +            /* ICW1 */
  13.193 +            /* Clear edge-sensing logic. */
  13.194 +            vpic->irr &= vpic->elcr;
  13.195 +
  13.196 +            /* No interrupts masked or in service. */
  13.197 +            vpic->imr = vpic->isr = 0;
  13.198 +
  13.199 +            /* IR7 is lowest priority. */
  13.200 +            vpic->priority_add = 0;
  13.201 +            vpic->rotate_on_auto_eoi = 0;
  13.202 +
  13.203 +            vpic->special_mask_mode = 0;
  13.204 +            vpic->readsel_isr = 0;
  13.205 +            vpic->poll = 0;
  13.206 +
  13.207 +            if ( !(val & 1) )
  13.208 +            {
  13.209 +                /* NO ICW4: ICW4 features are cleared. */
  13.210 +                vpic->auto_eoi = 0;
  13.211 +                vpic->special_fully_nested_mode = 0;
  13.212 +            }
  13.213 +
  13.214 +            vpic->init_state = ((val & 3) << 2) | 1;
  13.215 +        }
  13.216 +        else if ( val & 0x08 )
  13.217 +        {
  13.218 +            /* OCW3 */
  13.219 +            if ( val & 0x04 )
  13.220 +                vpic->poll = 1;
  13.221 +            if ( val & 0x02 )
  13.222 +                vpic->readsel_isr = val & 1;
  13.223 +            if ( val & 0x40 )
  13.224 +                vpic->special_mask_mode = (val >> 5) & 1;
  13.225 +        }
  13.226 +        else
  13.227 +        {
  13.228 +            /* OCW2 */
  13.229 +            cmd = val >> 5;
  13.230 +            switch ( cmd )
  13.231 +            {
  13.232 +            case 0: /* Rotate in AEOI Mode (Clear) */
  13.233 +            case 4: /* Rotate in AEOI Mode (Set)   */
  13.234 +                vpic->rotate_on_auto_eoi = cmd >> 2;
  13.235 +                break;
  13.236 +            case 1: /* Non-Specific EOI            */
  13.237 +            case 5: /* Non-Specific EOI & Rotate   */
  13.238 +                mask = vpic->isr;
  13.239 +                if ( vpic->special_mask_mode )
  13.240 +                    mask &= ~vpic->imr; /* SMM: ignore masked IRs. */
  13.241 +                priority = vpic_get_priority(vpic, mask);
  13.242 +                if ( priority == VPIC_PRIO_NONE )
  13.243 +                    break;
  13.244 +                irq = (priority + vpic->priority_add) & 7;
  13.245 +                vpic->isr &= ~(1 << irq);
  13.246 +                if ( cmd == 5 )
  13.247 +                    vpic->priority_add = (irq + 1) & 7;
  13.248 +                break;
  13.249 +            case 3: /* Specific EOI                */
  13.250 +            case 7: /* Specific EOI & Rotate       */
  13.251 +                irq = val & 7;
  13.252 +                vpic->isr &= ~(1 << irq);
  13.253 +                if ( cmd == 7 )
  13.254 +                    vpic->priority_add = (irq + 1) & 7;
  13.255 +                break;
  13.256 +            case 6: /* Set Priority                */
  13.257 +                vpic->priority_add = (val + 1) & 7;
  13.258 +                break;
  13.259 +            }
  13.260 +        }
  13.261 +    }
  13.262 +    else
  13.263 +    {
  13.264 +        switch ( vpic->init_state & 3 )
  13.265 +        {
  13.266 +        case 0:
  13.267 +            /* OCW1 */
  13.268 +            vpic->imr = val;
  13.269 +            break;
  13.270 +        case 1:
  13.271 +            /* ICW2 */
  13.272 +            vpic->irq_base = val & 0xf8;
  13.273 +            vpic->init_state++;
  13.274 +            if ( !(vpic->init_state & 8) )
  13.275 +                break; /* CASCADE mode: wait for write to ICW3. */
  13.276 +            /* SNGL mode: fall through (no ICW3). */
  13.277 +        case 2:
  13.278 +            /* ICW3 */
  13.279 +            vpic->init_state++;
  13.280 +            if ( !(vpic->init_state & 4) )
  13.281 +                vpic->init_state = 0; /* No ICW4: init done */
  13.282 +            break;
  13.283 +        case 3:
  13.284 +            /* ICW4 */
  13.285 +            vpic->special_fully_nested_mode = (val >> 4) & 1;
  13.286 +            vpic->auto_eoi = (val >> 1) & 1;
  13.287 +            vpic->init_state = 0;
  13.288 +            break;
  13.289 +        }
  13.290 +    }
  13.291 +
  13.292 +    vpic_update_int_output(vpic);
  13.293 +
  13.294 +    vpic_unlock(vpic);
  13.295 +}
  13.296 +
  13.297 +static uint32_t vpic_ioport_read(struct vpic *vpic, uint32_t addr)
  13.298 +{
  13.299 +    if ( vpic->poll )
  13.300 +    {
  13.301 +        vpic->poll = 0;
  13.302 +        return vpic_intack(vpic);
  13.303 +    }
  13.304 +
  13.305 +    if ( (addr & 1) == 0 )
  13.306 +        return (vpic->readsel_isr ? vpic->isr : vpic->irr);
  13.307 +
  13.308 +    return vpic->imr;
  13.309 +}
  13.310 +
  13.311 +static int vpic_intercept_pic_io(ioreq_t *p)
  13.312 +{
  13.313 +    struct vpic *vpic;
  13.314 +    uint32_t data;
  13.315 +
  13.316 +    if ( (p->size != 1) || (p->count != 1) )
  13.317 +    {
  13.318 +        gdprintk(XENLOG_WARNING, "PIC_IO bad access size %d\n", (int)p->size);
  13.319 +        return 1;
  13.320 +    }
  13.321 +
  13.322 +    vpic = &current->domain->arch.hvm_domain.irq.vpic[p->addr >> 7];
  13.323 +
  13.324 +    if ( p->dir == IOREQ_WRITE )
  13.325 +    {
  13.326 +        if ( p->data_is_ptr )
  13.327 +            (void)hvm_copy_from_guest_phys(&data, p->data, p->size);
  13.328 +        else
  13.329 +            data = p->data;
  13.330 +        vpic_ioport_write(vpic, (uint32_t)p->addr, (uint8_t)data);
  13.331 +    }
  13.332 +    else
  13.333 +    {
  13.334 +        data = vpic_ioport_read(vpic, (uint32_t)p->addr);
  13.335 +        if ( p->data_is_ptr )
  13.336 +            (void)hvm_copy_to_guest_phys(p->data, &data, p->size);
  13.337 +        else
  13.338 +            p->data = (u64)data;
  13.339 +    }
  13.340 +
  13.341 +    return 1;
  13.342 +}
  13.343 +
  13.344 +static int vpic_intercept_elcr_io(ioreq_t *p)
  13.345 +{
  13.346 +    struct vpic *vpic;
  13.347 +    uint32_t data;
  13.348 +
  13.349 +    if ( (p->size != 1) || (p->count != 1) )
  13.350 +    {
  13.351 +        gdprintk(XENLOG_WARNING, "PIC_IO bad access size %d\n", (int)p->size);
  13.352 +        return 1;
  13.353 +    }
  13.354 +
  13.355 +    vpic = &current->domain->arch.hvm_domain.irq.vpic[p->addr & 1];
  13.356 +
  13.357 +    if ( p->dir == IOREQ_WRITE )
  13.358 +    {
  13.359 +        if ( p->data_is_ptr )
  13.360 +            (void)hvm_copy_from_guest_phys(&data, p->data, p->size);
  13.361 +        else
  13.362 +            data = p->data;
  13.363 +
  13.364 +        /* Some IRs are always edge trig. Slave IR is always level trig. */
  13.365 +        data &= vpic_elcr_mask(vpic);
  13.366 +        if ( vpic->is_master )
  13.367 +            data |= 1 << 2;
  13.368 +        vpic->elcr = data;
  13.369 +    }
  13.370 +    else
  13.371 +    {
  13.372 +        /* Reader should not see hardcoded level-triggered slave IR. */
  13.373 +        data = vpic->elcr & vpic_elcr_mask(vpic);
  13.374 +
  13.375 +        if ( p->data_is_ptr )
  13.376 +            (void)hvm_copy_to_guest_phys(p->data, &data, p->size);
  13.377 +        else
  13.378 +            p->data = data;
  13.379 +    }
  13.380 +
  13.381 +    return 1;
  13.382 +}
  13.383 +
  13.384 +void vpic_init(struct domain *d)
  13.385 +{
  13.386 +    struct vpic *vpic;
  13.387 +
  13.388 +    /* Master PIC. */
  13.389 +    vpic = &d->arch.hvm_domain.irq.vpic[0];
  13.390 +    memset(vpic, 0, sizeof(*vpic));
  13.391 +    vpic->is_master = 1;
  13.392 +    vpic->elcr      = 1 << 2;
  13.393 +    register_portio_handler(d, 0x20, 2, vpic_intercept_pic_io);
  13.394 +    register_portio_handler(d, 0x4d0, 1, vpic_intercept_elcr_io);
  13.395 +
  13.396 +    /* Slave PIC. */
  13.397 +    vpic++;
  13.398 +    memset(vpic, 0, sizeof(*vpic));
  13.399 +    register_portio_handler(d, 0xa0, 2, vpic_intercept_pic_io);
  13.400 +    register_portio_handler(d, 0x4d1, 1, vpic_intercept_elcr_io);
  13.401 +}
  13.402 +
  13.403 +void vpic_irq_positive_edge(struct domain *d, int irq)
  13.404 +{
  13.405 +    struct vpic *vpic = &d->arch.hvm_domain.irq.vpic[irq >> 3];
  13.406 +    uint8_t mask = 1 << (irq & 7);
  13.407 +
  13.408 +    ASSERT(irq <= 15);
  13.409 +    ASSERT(vpic_is_locked(vpic));
  13.410 +
  13.411 +    if ( irq == 2 )
  13.412 +        return;
  13.413 +
  13.414 +    vpic->irr |= mask;
  13.415 +    if ( !(vpic->imr & mask) )
  13.416 +        vpic_update_int_output(vpic);
  13.417 +}
  13.418 +
  13.419 +void vpic_irq_negative_edge(struct domain *d, int irq)
  13.420 +{
  13.421 +    struct vpic *vpic = &d->arch.hvm_domain.irq.vpic[irq >> 3];
  13.422 +    uint8_t mask = 1 << (irq & 7);
  13.423 +
  13.424 +    ASSERT(irq <= 15);
  13.425 +    ASSERT(vpic_is_locked(vpic));
  13.426 +
  13.427 +    if ( irq == 2 )
  13.428 +        return;
  13.429 +
  13.430 +    vpic->irr &= ~mask;
  13.431 +    if ( !(vpic->imr & mask) )
  13.432 +        vpic_update_int_output(vpic);
  13.433 +}
  13.434 +
  13.435 +int cpu_get_pic_interrupt(struct vcpu *v, int *type)
  13.436 +{
  13.437 +    int irq, vector;
  13.438 +    struct vpic *vpic = &v->domain->arch.hvm_domain.irq.vpic[0];
  13.439 +
  13.440 +    if ( !vlapic_accept_pic_intr(v) || !vpic->int_output )
  13.441 +        return -1;
  13.442 +
  13.443 +    irq = vpic_intack(vpic);
  13.444 +    if ( irq == -1 )
  13.445 +        return -1;
  13.446 +
  13.447 +    vector = vpic[irq >> 3].irq_base + (irq & 7);
  13.448 +    *type = APIC_DM_EXTINT;
  13.449 +    return vector;
  13.450 +}
  13.451 +
  13.452 +int is_periodic_irq(struct vcpu *v, int irq, int type)
  13.453 +{
  13.454 +    int vec;
  13.455 +    struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
  13.456 +
  13.457 +    if ( pt->irq != 0 )
  13.458 +        return 0;
  13.459 +
  13.460 +    if ( type == APIC_DM_EXTINT )
  13.461 +        vec = v->domain->arch.hvm_domain.irq.vpic[0].irq_base;
  13.462 +    else
  13.463 +        vec = domain_vioapic(v->domain)->redirtbl[0].fields.vector;
  13.464 +
  13.465 +    return (irq == vec);
  13.466 +}
    14.1 --- a/xen/include/asm-x86/hvm/irq.h	Fri Nov 24 15:42:14 2006 +0000
    14.2 +++ b/xen/include/asm-x86/hvm/irq.h	Sun Nov 26 13:37:27 2006 +0000
    14.3 @@ -75,7 +75,7 @@ struct hvm_irq {
    14.4       *  8-15: Slave  8259 PIC, IO-APIC pins 8-15
    14.5       *  16+ : IO-APIC pins 16+
    14.6       */
    14.7 -    struct vpic    vpic;
    14.8 +    struct vpic    vpic[2]; /* 0=master; 1=slave */
    14.9      struct vioapic vioapic;
   14.10  
   14.11      /* Last VCPU that was delivered a LowestPrio interrupt. */
    15.1 --- a/xen/include/asm-x86/hvm/vlapic.h	Fri Nov 24 15:42:14 2006 +0000
    15.2 +++ b/xen/include/asm-x86/hvm/vlapic.h	Sun Nov 26 13:37:27 2006 +0000
    15.3 @@ -2,6 +2,7 @@
    15.4   * hvm_vlapic.h: virtualize LAPIC definitions.
    15.5   *
    15.6   * Copyright (c) 2004, Intel Corporation.
    15.7 + * Copyright (c) 2006 Keir Fraser, XenSource Inc.
    15.8   *
    15.9   * This program is free software; you can redistribute it and/or modify it
   15.10   * under the terms and conditions of the GNU General Public License,
    16.1 --- a/xen/include/asm-x86/hvm/vpic.h	Fri Nov 24 15:42:14 2006 +0000
    16.2 +++ b/xen/include/asm-x86/hvm/vpic.h	Sun Nov 26 13:37:27 2006 +0000
    16.3 @@ -27,40 +27,55 @@
    16.4  #ifndef __ASM_X86_HVM_VPIC_H__
    16.5  #define __ASM_X86_HVM_VPIC_H__
    16.6  
    16.7 -#define domain_vpic(d) (&(d)->arch.hvm_domain.irq.vpic)
    16.8 -#define vpic_domain(v) (container_of((v), struct domain, \
    16.9 -                                     arch.hvm_domain.irq.vpic))
   16.10 -#define vpic_lock(v)   (&container_of((v), struct hvm_irq, vpic)->lock)
   16.11 +struct vpic {
   16.12 +    /* IR line bitmasks. */
   16.13 +    uint8_t irr, imr, isr;
   16.14  
   16.15 -typedef struct PicState {
   16.16 -    uint8_t last_irr; /* edge detection */
   16.17 -    uint8_t irr; /* interrupt request register */
   16.18 -    uint8_t imr; /* interrupt mask register */
   16.19 -    uint8_t isr; /* interrupt service register */
   16.20 -    uint8_t priority_add; /* highest irq priority */
   16.21 +    /* Line IRx maps to IRQ irq_base+x */
   16.22      uint8_t irq_base;
   16.23 -    uint8_t read_reg_select;
   16.24 -    uint8_t poll;
   16.25 -    uint8_t special_mask;
   16.26 -    uint8_t init_state;
   16.27 -    uint8_t auto_eoi;
   16.28 -    uint8_t rotate_on_auto_eoi;
   16.29 -    uint8_t special_fully_nested_mode;
   16.30 -    uint8_t init4; /* true if 4 byte init */
   16.31 -    uint8_t elcr; /* PIIX edge/trigger selection*/
   16.32 -    uint8_t elcr_mask;
   16.33 -    struct vpic *pics_state;
   16.34 -} PicState;
   16.35  
   16.36 -struct vpic {
   16.37 -    /* 0 is master pic, 1 is slave pic */
   16.38 -    PicState pics[2];
   16.39 -    int irq_pending;
   16.40 +    /*
   16.41 +     * Where are we in ICW2-4 initialisation (0 means no init in progress)?
   16.42 +     * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1).
   16.43 +     * Bit 2: ICW1.IC4  (1 == ICW4 included in init sequence)
   16.44 +     * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence)
   16.45 +     */
   16.46 +    uint8_t init_state:4;
   16.47 +
   16.48 +    /* IR line with highest priority. */
   16.49 +    uint8_t priority_add:4;
   16.50 +
   16.51 +    /* Reads from A=0 obtain ISR or IRR? */
   16.52 +    uint8_t readsel_isr:1;
   16.53 +
   16.54 +    /* Reads perform a polling read? */
   16.55 +    uint8_t poll:1;
   16.56 +
   16.57 +    /* Automatically clear IRQs from the ISR during INTA? */
   16.58 +    uint8_t auto_eoi:1;
   16.59 +
   16.60 +    /* Automatically rotate IRQ priorities during AEOI? */
   16.61 +    uint8_t rotate_on_auto_eoi:1;
   16.62 +
   16.63 +    /* Exclude slave inputs when considering in-service IRQs? */
   16.64 +    uint8_t special_fully_nested_mode:1;
   16.65 +
   16.66 +    /* Special mask mode excludes masked IRs from AEOI and priority checks. */
   16.67 +    uint8_t special_mask_mode:1;
   16.68 +
   16.69 +    /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */
   16.70 +    uint8_t is_master:1;
   16.71 +
   16.72 +    /* Edge/trigger selection. */
   16.73 +    uint8_t elcr;
   16.74 +
   16.75 +    /* Virtual INT output. */
   16.76 +    uint8_t int_output;
   16.77  };
   16.78  
   16.79 -void pic_set_irq(struct vpic *vpic, int irq, int level);
   16.80 -void pic_init(struct vpic *vpic);
   16.81 -void register_pic_io_hook(struct domain *d);
   16.82 +void vpic_irq_positive_edge(struct domain *d, int irq);
   16.83 +void vpic_irq_negative_edge(struct domain *d, int irq);
   16.84 +void vpic_init(struct domain *d);
   16.85  int cpu_get_pic_interrupt(struct vcpu *v, int *type);
   16.86  int is_periodic_irq(struct vcpu *v, int irq, int type);
   16.87