[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH][8/10] Infrastructure for interrupt handling.



Infrastructure for interrupt handling.

- support interruptibility
- handle interrupt window exiting control appropriately
- Add ioapic device models imported from Bochs under LGPL
- generalize the interrupt architecture to support both PIC/APIC

This patch is necessary to fix several bugs on 32 bit VMX and prepares the
ground for adding a local APIC device model in the hypervisor.

Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx>
Signed-off-by: Arun Sharma <arun.sharma@xxxxxxxxx>

diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/exec-all.h
--- a/tools/ioemu/exec-all.h    Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/exec-all.h    Thu Jun 30 05:24:52 2005
@@ -573,7 +573,7 @@
 }
 #endif
 
-//#define DEBUG_UNUSED_IOPORT
-//#define DEBUG_IOPORT
+#define DEBUG_UNUSED_IOPORT
+#define DEBUG_IOPORT
 #define TARGET_VMX
 
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/i8259.c
--- a/tools/ioemu/hw/i8259.c    Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/hw/i8259.c    Thu Jun 30 05:24:52 2005
@@ -22,12 +22,16 @@
  * THE SOFTWARE.
  */
 #include "vl.h"
+#include "xc.h"
+#include <io/ioreq.h>
 
 /* debug PIC */
 //#define DEBUG_PIC
 
 //#define DEBUG_IRQ_LATENCY
 #define DEBUG_IRQ_COUNT
+
+extern void pit_reset_vmx_vectors();
 
 typedef struct PicState {
     uint8_t last_irr; /* edge detection */
@@ -121,6 +125,26 @@
     }
 }
 
+/* pic[1] is connected to pin2 of pic[0] */
+#define CASCADE_IRQ 2
+
+static void shared_page_update()
+{
+    extern shared_iopage_t *shared_page;
+    uint8_t * pmask = (uint8_t *)&(shared_page->sp_global.pic_mask[0]);
+    int           index;
+
+    index = pics[0].irq_base/8;
+    pmask[index] = pics[0].imr;
+    index = pics[1].irq_base/8;
+
+    if ( pics[0].imr &  (1 << CASCADE_IRQ) ) {
+        pmask[index] = 0xff;
+    } else {
+        pmask[index] = pics[1].imr;
+    }
+}
+
 /* raise irq to CPU if necessary. must be called every time the active
    irq may change */
 static void pic_update_irq(void)
@@ -150,14 +174,18 @@
 #endif
         cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
     }
+    shared_page_update();
 }
 
 #ifdef DEBUG_IRQ_LATENCY
 int64_t irq_time[16];
 #endif
 
+extern void ioapic_legacy_irq(int irq, int level);
+
 void pic_set_irq(int irq, int level)
 {
+    ioapic_legacy_irq(irq, level);
 #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
     if (level != irq_level[irq]) {
 #if defined(DEBUG_PIC)
@@ -255,6 +283,7 @@
     tmp = s->elcr_mask;
     memset(s, 0, sizeof(PicState));
     s->elcr_mask = tmp;
+    shared_page_update();
 }
 
 static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c      Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/target-i386-dm/helper2.c      Thu Jun 30 05:24:52 2005
@@ -320,7 +320,7 @@
 
        // Send a message on the event channel. Add the vector to the shared mem
        // page.
-       intr = &(shared_page->vcpu_iodata[0].vp_intr[0]);
+       intr = &(shared_page->sp_global.pic_intr[0]);
        atomic_set_bit(vector, intr);
         if (loglevel & CPU_LOG_INT)
                 fprintf(logfile, "injecting vector: %x\n", vector);
@@ -345,11 +345,11 @@
        FD_ZERO(&rfds);
 
        while (1) {
-            if (vm_running) {
-                if (shutdown_requested) {
-                    break;
+                if (vm_running) {
+                    if (shutdown_requested) {
+                        break;
+                    }
                 }
-            }
 
                /* Wait up to one seconds. */
                tv.tv_sec = 0;
@@ -370,14 +370,19 @@
 #endif
 
                main_loop_wait(0);
-
+#ifdef APIC_SUPPORT
+               ioapic_update_EOI();
+#endif
                cpu_timer_handler(env);
                if (env->interrupt_request & CPU_INTERRUPT_HARD) {
                         env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                        vector = cpu_get_pic_interrupt(env); 
                        do_interrupt(env, vector);
                }
-
+#ifdef APIC_SUPPORT
+               if (ioapic_has_intr())
+                    do_ioapic();
+#endif
                if (env->send_event) {
                        int ret;
                        ret = xc_evtchn_send(xc_handle, ioreq_port);
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/include/asm-x86/vmx.h
--- a/xen/include/asm-x86/vmx.h Thu Jun 30 04:32:55 2005
+++ b/xen/include/asm-x86/vmx.h Thu Jun 30 05:24:52 2005
@@ -339,14 +339,19 @@
     return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
 }
 
+static inline shared_iopage_t *get_sp(struct domain *d)
+{
+    return (shared_iopage_t *) d->arch.vmx_platform.shared_page_va;
+}
+
 static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu)
 {
-    return &((shared_iopage_t *) 
d->arch.vmx_platform.shared_page_va)->vcpu_iodata[cpu];
+    return &get_sp(d)->vcpu_iodata[cpu];
 }
 
 static inline int iopacket_port(struct domain *d)
 {
-    return ((shared_iopage_t *) 
d->arch.vmx_platform.shared_page_va)->sp_global.eport;
+    return get_sp(d)->sp_global.eport;
 }
 
 #endif /* __ASM_X86_VMX_H__ */
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/arch/x86/vmx_vmcs.c
--- a/xen/arch/x86/vmx_vmcs.c   Thu Jun 30 04:32:55 2005
+++ b/xen/arch/x86/vmx_vmcs.c   Thu Jun 30 05:24:52 2005
@@ -153,6 +153,8 @@
     p = map_domain_page(mpfn);
     d->domain->arch.vmx_platform.shared_page_va = (unsigned long)p;
 
+   VMX_DBG_LOG(DBG_LEVEL_1, "eport: %x\n", iopacket_port(d->domain));
+
    clear_bit(iopacket_port(d->domain), 
              &d->domain->shared_info->evtchn_mask[0]);
 
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/include/asm-x86/vmx_virpit.h
--- a/xen/include/asm-x86/vmx_virpit.h  Thu Jun 30 04:32:55 2005
+++ b/xen/include/asm-x86/vmx_virpit.h  Thu Jun 30 05:24:52 2005
@@ -20,7 +20,7 @@
     int vector;                                /* the pit irq vector */
     unsigned int period;               /* the frequency. e.g. 10ms*/
     unsigned int channel;              /* the pit channel, counter 0~2 */
-    unsigned long *intr_bitmap;
+    u64  *intr_bitmap;
     unsigned int pending_intr_nr;      /* the couner for pending timer 
interrupts */
     unsigned long long inject_point;   /* the time inject virt intr */
     struct ac_timer pit_timer;         /* periodic timer for mode 2*/
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/target-i386-dm/Makefile
--- a/tools/ioemu/target-i386-dm/Makefile       Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/target-i386-dm/Makefile       Thu Jun 30 05:24:52 2005
@@ -188,7 +188,7 @@
 
 #########################################################
 
-DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE 
-DAPIC_SUPPORT
 LIBS+=-lm -L../../libxc -lxc
 ifndef CONFIG_USER_ONLY
 LIBS+=-lz
@@ -246,6 +246,7 @@
 # must use static linking to avoid leaving stuff in virtual address space
 VL_OBJS=vl.o exec.o monitor.o osdep.o block.o readline.o pci.o console.o 
 VL_OBJS+=block-cow.o block-qcow.o block-vmdk.o block-cloop.o aes.o
+VL_OBJS+=ioapic.o
 #VL_OBJS+= block-cloop.o
 
 SOUND_HW = sb16.o
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c       Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/hw/pc.c       Thu Jun 30 05:24:52 2005
@@ -543,6 +543,9 @@
             pci_ne2000_init(pci_bus, &nd_table[i]);
         }
         pci_piix3_ide_init(pci_bus, bs_table);
+#ifdef APIC_SUPPORT
+        IOAPICInit();
+#endif
     } else {
         nb_nics1 = nb_nics;
         if (nb_nics1 > NE2000_NB_MAX)
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/arch/x86/vmx_io.c
--- a/xen/arch/x86/vmx_io.c     Thu Jun 30 04:32:55 2005
+++ b/xen/arch/x86/vmx_io.c     Thu Jun 30 05:24:52 2005
@@ -22,6 +22,7 @@
 #include <xen/lib.h>
 #include <xen/errno.h>
 #include <xen/trace.h>
+#include <xen/event.h>
 
 #include <asm/current.h>
 #include <asm/cpufeature.h>
@@ -29,10 +30,12 @@
 #include <asm/msr.h>
 #include <asm/vmx.h>
 #include <asm/vmx_vmcs.h>
-#include <xen/event.h>
-#include <public/io/ioreq.h>
 #include <asm/vmx_platform.h>
 #include <asm/vmx_virpit.h>
+#include <asm/apic.h>
+
+#include <public/io/ioreq.h>
+#include <public/io/vmx_vlapic.h>
 
 #ifdef CONFIG_VMX
 #if defined (__i386__)
@@ -515,38 +518,100 @@
     return __fls(pintr[0]);
 }
 
+#define BSP_CPU(d)    (!(d->vcpu_id))
+static inline void clear_extint(struct vcpu *v)
+{
+    global_iodata_t *spg;
+    int i;
+    spg = &get_sp(v->domain)->sp_global;
+
+    for(i = 0; i < INTR_LEN; i++)
+        spg->pic_intr[i] = 0;
+}
+
+static inline void clear_highest_bit(struct vcpu *v, int vector)
+{
+    global_iodata_t *spg;
+
+    spg = &get_sp(v->domain)->sp_global;
+
+    clear_bit(vector, &spg->pic_intr[0]);
+}
+
+static inline int find_highest_pic_irq(struct vcpu *v)
+{
+    u64 intr[INTR_LEN];
+    global_iodata_t *spg;
+    int i;
+
+    if(!BSP_CPU(v))
+        return -1;
+
+    spg = &get_sp(v->domain)->sp_global;
+
+    for(i = 0; i < INTR_LEN; i++){
+        intr[i] = spg->pic_intr[i] & ~spg->pic_mask[i];
+    }
+
+    return find_highest_irq((u32 *)&intr[0]);
+}
+
 /*
  * Return 0-255 for pending irq.
  *        -1 when no pending.
  */
-static inline int find_highest_pending_irq(struct vcpu *d)
-{
-    vcpu_iodata_t *vio;
-
-    vio = get_vio(d->domain, d->vcpu_id);
-
-    if (vio == 0) {
-        VMX_DBG_LOG(DBG_LEVEL_1, 
-                    "bad shared page: %lx", (unsigned long) vio);
-        domain_crash_synchronous();
-    }
-        
-    return find_highest_irq((unsigned int *)&vio->vp_intr[0]);
-}
-
-static inline void clear_highest_bit(struct vcpu *d, int vector)
-{
-    vcpu_iodata_t *vio;
-
-    vio = get_vio(d->domain, d->vcpu_id);
-
-    if (vio == 0) {
-        VMX_DBG_LOG(DBG_LEVEL_1, 
-                    "bad shared page: %lx", (unsigned long) vio);
-        domain_crash_synchronous();
-    }
-        
-    clear_bit(vector, &vio->vp_intr[0]);
+static inline int find_highest_pending_irq(struct vcpu *v, int *type)
+{
+    int result = -1;
+    if ((result = find_highest_pic_irq(v)) != -1){
+        *type = VLAPIC_DELIV_MODE_EXT;
+        return result;
+    }
+    return result;
+}
+
+static inline void
+interrupt_post_injection(struct vcpu * v, int vector, int type)
+{
+    struct vmx_virpit_t *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
+    switch(type)
+    {
+        case VLAPIC_DELIV_MODE_EXT:
+            if (vpit->pending_intr_nr && vector == vpit->vector)
+                vpit->pending_intr_nr--;
+            else
+                clear_highest_bit(v, vector);
+
+            if (vector == vpit->vector && !vpit->first_injected){
+                vpit->first_injected = 1;
+                vpit->pending_intr_nr = 0;
+            }
+            if (vector == vpit->vector)
+                vpit->inject_point = NOW();
+            break;
+
+        default:
+            printk("Not support interrupt type\n");
+            break;
+    }
+}
+
+static inline void
+enable_irq_window(unsigned long cpu_exec_control)
+{
+    if (!(cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING)) {
+        cpu_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
+        __vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control);
+    }
+}
+
+static inline void
+disable_irq_window(unsigned long cpu_exec_control)
+{
+    if ( cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING ) {
+        cpu_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
+        __vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control);
+    }
 }
 
 static inline int irq_masked(unsigned long eflags)
@@ -554,50 +619,68 @@
     return ((eflags & X86_EFLAGS_IF) == 0);
 }
 
-void vmx_intr_assist(struct vcpu *d) 
-{
-    int highest_vector = find_highest_pending_irq(d);
-    unsigned long intr_fields, eflags;
-    struct vmx_virpit_t *vpit = &(d->domain->arch.vmx_platform.vmx_pit);
-
-    if (highest_vector == -1)
+void vmx_intr_assist(struct vcpu *v) 
+{
+    int intr_type;
+    int highest_vector = find_highest_pending_irq(v, &intr_type);
+    unsigned long intr_fields, eflags, interruptibility, cpu_exec_control;
+
+    __vmread(CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control);
+
+    if (highest_vector == -1) {
+        disable_irq_window(cpu_exec_control);
         return;
-
-    __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
-    if (intr_fields & INTR_INFO_VALID_MASK) {
-        VMX_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx",
-                    intr_fields);
-        return;
-    }
-
-    __vmread(GUEST_RFLAGS, &eflags);
-    if (irq_masked(eflags)) {
-        VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, eflags: %lx",
-                    highest_vector, eflags);
-        return;
-    }
-        
-    if (vpit->pending_intr_nr && highest_vector == vpit->vector)
-        vpit->pending_intr_nr--;
-    else
-        clear_highest_bit(d, highest_vector); 
-
-    /* close the window between guest PIT initialization and sti */
-    if (highest_vector == vpit->vector && !vpit->first_injected){
-        vpit->first_injected = 1;
-        vpit->pending_intr_nr = 0;
-    }
-
-    intr_fields = (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR | highest_vector);
-    __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
-
-    __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
-
-    TRACE_3D(TRC_VMX_INT, d->domain->domain_id, highest_vector, 0);
-    if (highest_vector == vpit->vector)
-        vpit->inject_point = NOW();
-
-    return;
+    }
+
+     __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
+
+     if (intr_fields & INTR_INFO_VALID_MASK) {
+         VMX_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx",
+           intr_fields);
+         return;
+     }
+
+     __vmread(GUEST_INTERRUPTIBILITY_INFO, &interruptibility);
+
+     if (interruptibility) {
+         enable_irq_window(cpu_exec_control);
+         VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, interruptibility: 
%lx",
+                     highest_vector, interruptibility);
+         return;
+     }
+
+     __vmread(GUEST_RFLAGS, &eflags);
+
+     switch (intr_type) {
+         case VLAPIC_DELIV_MODE_EXT:
+             if (irq_masked(eflags)) {
+                 enable_irq_window(cpu_exec_control);
+                 VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, eflags: %lx",
+                             highest_vector, eflags);
+                 return;
+             }
+
+             intr_fields = (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR 
+                            | highest_vector);
+             __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
+             __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
+
+             TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
+             break;
+         case VLAPIC_DELIV_MODE_FIXED:
+         case VLAPIC_DELIV_MODE_LPRI:
+         case VLAPIC_DELIV_MODE_SMI:
+         case VLAPIC_DELIV_MODE_NMI:
+         case VLAPIC_DELIV_MODE_INIT:
+         case VLAPIC_DELIV_MODE_STARTUP:
+         default:
+             printk("Unsupported interrupt type\n");
+             BUG();
+             break;
+     }
+
+     interrupt_post_injection(v, highest_vector, intr_type);
+     return;
 }
 
 void vmx_do_resume(struct vcpu *d) 
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/arch/x86/vmx_intercept.c
--- a/xen/arch/x86/vmx_intercept.c      Thu Jun 30 04:32:55 2005
+++ b/xen/arch/x86/vmx_intercept.c      Thu Jun 30 05:24:52 2005
@@ -213,7 +213,8 @@
 {
     vcpu_iodata_t * vio = get_vio(d->domain, d->vcpu_id);
     ioreq_t *p = &vio->vp_ioreq;
-    unsigned long *intr = &(vio->vp_intr[0]);
+    shared_iopage_t *sp = get_sp(d->domain);
+    u64 *intr = &(sp->sp_global.pic_intr[0]);
     struct vmx_virpit_t *vpit = &(d->domain->arch.vmx_platform.vmx_pit);
     int rw_mode;
 
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/pci.c
--- a/tools/ioemu/hw/pci.c      Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/hw/pci.c      Thu Jun 30 05:24:52 2005
@@ -53,6 +53,7 @@
 static int pci_irq_index;
 static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS];
 static PCIBus *first_bus;
+extern FILE *logfile;
 
 static PCIBus *pci_register_bus(void)
 {
@@ -569,13 +570,26 @@
     pci_conf[0xae] = 0x00;
 }
 
+#define PIIX_CONFIG_XBCS 0x4f
+void piix3_write_config(PCIDevice *d,
+  uint32_t address, uint32_t val, int len)
+{
+    if ((PIIX3State *)d != piix3_state){
+        fprintf(logfile, "piix3_write_config: error PCIDevice\n");
+        return;
+    }
+
+    pci_default_write_config(d, address, val, len);
+}
+
+
 void piix3_init(PCIBus *bus)
 {
     PIIX3State *d;
     uint8_t *pci_conf;
 
     d = (PIIX3State *)pci_register_device(bus, "PIIX3", sizeof(PIIX3State),
-                                          -1, NULL, NULL);
+                                          -1, NULL, piix3_write_config);
     register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d);
 
     piix3_state = d;
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/include/public/io/ioreq.h
--- a/xen/include/public/io/ioreq.h     Thu Jun 30 04:32:55 2005
+++ b/xen/include/public/io/ioreq.h     Thu Jun 30 05:24:52 2005
@@ -49,14 +49,11 @@
 
 #define MAX_VECTOR    256
 #define BITS_PER_BYTE   8
-#define INTR_LEN        (MAX_VECTOR/(BITS_PER_BYTE * sizeof(unsigned long)))
+#define INTR_LEN        (MAX_VECTOR/(BITS_PER_BYTE * sizeof(u64)))
 
-/* We only track the master PIC state here */
 typedef struct {
-    uint16_t irr; /* interrupt request register */
-    uint16_t imr; /* interrupt mask register */
-    uint16_t isr; /* interrupt service register */
-
+    u64   pic_intr[INTR_LEN];
+    u64   pic_mask[INTR_LEN];
     int     eport; /* Event channel port */
 } global_iodata_t;
 
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/ioapic.c
--- /dev/null   Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/hw/ioapic.c   Thu Jun 30 05:24:52 2005
@@ -0,0 +1,704 @@
+/////////////////////////////////////////////////////////////////////////
+//
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+
+#include "vl.h"
+#include "ioapic.h"
+
+#ifdef __OS
+#undef __OS
+#endif
+#ifdef __i386__
+#define __OS   "l"
+#else
+#define __OS "q"
+#endif
+#define ADDR (*(volatile long *) addr)
+
+#ifdef IOAPIC_DEBUG
+#define IOAPIC_LOG(a...) fprintf(logfile, ##a)
+#else
+#define IOAPIC_LOG(a...)
+#endif
+
+static IOAPICState *ioapic;
+
+#define IOAPIC_ERR(a...) fprintf(logfile, ##a)
+static __inline__ int test_and_set_bit(long nr, volatile void * addr)
+{
+       long oldbit;
+
+       __asm__ __volatile__( 
+               "bts"__OS" %2,%1\n\tsbb"__OS" %0,%0"
+               :"=r" (oldbit),"=m" (ADDR)
+               :"Ir" (nr) : "memory");
+       return oldbit;
+}
+
+static __inline__ int test_and_clear_bit(long nr, volatile void * addr)
+{
+       long oldbit;
+
+       __asm__ __volatile__( LOCK_PREFIX
+               "btr"__OS" %2,%1\n\tsbb"__OS" %0,%0"
+               :"=r" (oldbit),"=m" (ADDR)
+               :"dIr" (nr) : "memory");
+       return oldbit;
+}
+
+static __inline__ void clear_bit(long nr, volatile void * addr)
+{
+       __asm__ __volatile__( 
+               "btr"__OS" %1,%0"
+               :"=m" (ADDR)
+               :"Ir" (nr));
+}
+
+static inline
+void get_shareinfo_apic_msg(vlapic_info *share_info){
+    while(test_and_set_bit(VL_STATE_MSG_LOCK, &share_info->vl_state)){};
+}
+
+static inline
+void put_shareinfo_apic_msg(vlapic_info *share_info){
+    clear_bit(VL_STATE_MSG_LOCK, &share_info->vl_state);
+}
+static inline
+void get_shareinfo_eoi(vlapic_info *share_info){
+    while(test_and_set_bit(VL_STATE_EOI_LOCK, &share_info->vl_state)){};
+}
+
+static inline
+void put_shareinfo_eoi(vlapic_info *share_info){
+    clear_bit(VL_STATE_EOI_LOCK, &share_info->vl_state);
+}
+
+
+static inline
+void get_shareinfo_ext(vlapic_info *share_info){
+    while(test_and_set_bit(VL_STATE_EXT_LOCK, &share_info->vl_state));
+}
+
+static inline
+void put_shareinfo_ext(vlapic_info *share_info){
+    clear_bit(VL_STATE_EXT_LOCK, &share_info->vl_state);
+}
+
+
+static __inline__ int test_bit(int nr, uint32_t value){
+    return value & (1 << nr);
+}
+
+static void ioapic_enable(IOAPICState *s, uint8_t enable)
+{
+    if (!enable ^ IOAPICEnabled(s)) return;
+    if(enable)
+        s->flags |= IOAPIC_ENABLE_FLAG;
+    else
+        s->flags &= ~IOAPIC_ENABLE_FLAG;
+}
+
+#ifdef IOAPIC_DEBUG
+static void
+ioapic_dump_redir(IOAPICState *s, uint8_t entry)
+{
+    if (!s)
+        return;
+
+    RedirStatus redir = s->redirtbl[entry];
+
+    fprintf(logfile, "entry %x: "
+      "vector %x deliver_mod %x destmode %x delivestatus %x "
+      "polarity %x remote_irr %x trigmod %x mask %x dest_id %x\n",
+      entry,
+      redir.RedirForm.vector, redir.RedirForm.deliver_mode,
+      redir.RedirForm.destmode, redir.RedirForm.delivestatus,
+      redir.RedirForm.polarity, redir.RedirForm.remoteirr,
+      redir.RedirForm.trigmod, redir.RedirForm.mask,
+      redir.RedirForm.dest_id);
+}
+
+static void
+ioapic_dump_shareinfo(IOAPICState *s , int number)
+{
+    if (!s || !s->lapic_info[number])
+        return;
+    vlapic_info *m = s->lapic_info[number];
+    IOAPIC_LOG("lapic_info %x : "
+      "vl_lapic_id %x vl_logical_dest %x vl_dest_format %x vl_arb_id %x\n",
+      number, m->vl_lapic_id, m->vl_logical_dest, m->vl_dest_format, 
m->vl_arb_id );
+}
+#endif
+
+static void
+ioapic_save(QEMUFile* f,void* opaque)
+{
+    IOAPIC_ERR("no implementation for ioapic_save\n");
+}
+
+static
+int ioapic_load(QEMUFile* f,void* opaque,int version_id)
+{
+    IOAPIC_ERR("no implementation for ioapic_load\n");
+    return 0;
+}
+
+uint32_t
+ioapic_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+    IOAPIC_ERR("ioapic_mem_readb\n");
+    return 0;
+}
+
+uint32_t
+ioapic_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+    IOAPIC_ERR("ioapic_mem_readw\n");
+    return 0;
+}
+
+static
+void ioapic_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    IOAPIC_ERR("ioapic_mem_writeb\n");
+}
+
+static
+void ioapic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    IOAPIC_ERR("ioapic_mem_writew\n");
+}
+
+static
+uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+    unsigned short ioregsel;
+    IOAPICState *s = opaque;
+    uint32_t    result = 0;
+    uint32_t    redir_index = 0;
+    uint64_t    redir_content = 0;
+
+    IOAPIC_LOG("apic_mem_readl addr %x\n", addr);
+    if (!s){
+        IOAPIC_ERR("null pointer for apic_mem_readl\n");
+        return result;
+    }
+
+    addr &= 0xff;
+    if(addr == 0x00){
+        result = s->ioregsel;
+        return result;
+    }else if (addr != 0x10){
+        IOAPIC_ERR("apic_mem_readl address error\n");
+        return result;
+    }
+
+    ioregsel = s->ioregsel;
+
+    switch (ioregsel){
+        case IOAPIC_REG_APIC_ID:
+            result = ((s->id & 0xf) << 24);
+            break;
+        case IOAPIC_REG_VERSION:
+            result = ((((IOAPIC_NUM_PINS-1) & 0xff) << 16)  
+                     | (IOAPIC_VERSION_ID & 0x0f));
+            break;
+        case IOAPIC_REG_ARB_ID:
+            //FIXME
+            result = ((s->id & 0xf) << 24);
+            break;
+        default:
+            redir_index = (ioregsel - 0x10) >> 1;
+            if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS){
+               redir_content = s->redirtbl[redir_index].value;
+               result = (ioregsel & 0x1)?
+                        (redir_content >> 32) & 0xffffffff :
+                        redir_content & 0xffffffff;
+            }else{
+                IOAPIC_ERR(
+                  "upic_mem_readl:undefined ioregsel %x\n",
+                  ioregsel);
+            }
+    }
+    return result;
+}
+
+static
+void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    IOAPICState *s = opaque;
+    uint32_t redir_index = 0;
+    uint64_t redir_content;
+
+    IOAPIC_LOG("apic_mem_writel addr %x val %x\n", addr, val);
+
+    if (!s){
+        IOAPIC_ERR("apic_mem_writel: null opaque\n");
+        return;
+    }
+
+    addr &= 0xff;
+    if (addr == 0x00){
+        s->ioregsel = val;
+        return;
+    }else if (addr != 0x10){
+        IOAPIC_ERR("apic_mem_writel: unsupported address\n");
+    }
+
+    switch (s->ioregsel){
+        case IOAPIC_REG_APIC_ID:
+            s->id = (val >> 24) & 0xf;
+            break;
+        case IOAPIC_REG_VERSION:
+            IOAPIC_ERR("apic_mem_writel: version register read only\n");
+            break;
+        case IOAPIC_REG_ARB_ID:
+            s->arb_id = val;
+            break;
+        default:
+            redir_index = (s->ioregsel - 0x10) >> 1;
+//            IOAPIC_LOG("apic_mem_write: change redir :index %x before %lx, 
val %x\n", redir_index, s->redirtbl[redir_index].value, val);
+            if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS){
+                redir_content = s->redirtbl[redir_index].value;
+                if (s->ioregsel & 0x1)
+                   redir_content = (((uint64_t)val & 0xffffffff) << 32) | 
(redir_content & 0xffffffff);
+                else
+                    redir_content = ((redir_content >> 32) << 32) | (val & 
0xffffffff);
+                s->redirtbl[redir_index].value = redir_content;
+            }else {
+                IOAPIC_ERR("apic_mem_writel: error register\n");
+            }
+            //IOAPIC_LOG("after value is %lx\n",  
s->redirtbl[redir_index].value);
+    }
+}
+
+static CPUReadMemoryFunc *ioapic_mem_read[3] = {
+    ioapic_mem_readb,
+    ioapic_mem_readw,
+    ioapic_mem_readl,
+};
+
+static CPUWriteMemoryFunc *ioapic_mem_write[3] = {
+    ioapic_mem_writeb,
+    ioapic_mem_writew,
+    ioapic_mem_writel,
+};
+
+void
+IOAPICReset(IOAPICState *s)
+{
+    int i;
+    if (!s)
+        return ;
+
+    memset(s, 0, sizeof(IOAPICState));
+
+    for (i = 0; i < IOAPIC_NUM_PINS; i++)
+        s->redirtbl[i].RedirForm.mask = 0x1;
+//    IOAPIC_LOG("after Reset %lx\n",  s->redirtbl[0].value);
+}
+
+void
+ioapic_update_config(IOAPICState *s, unsigned long address, uint8_t enable)
+{
+    int ioapic_mem;
+    if (!s)
+       return;
+
+    ioapic_enable(s, enable);
+
+    if (address != s->base_address){
+        ioapic_mem = cpu_register_io_memory(0, ioapic_mem_read, 
ioapic_mem_write, s);
+        cpu_register_physical_memory(address, IOAPIC_MEM_LENGTH, ioapic_mem);
+        s->base_address = ioapic_mem;
+    }
+}
+
+#define direct_intr(mode)   \
+  (mode == VLAPIC_DELIV_MODE_SMI || \
+   mode == VLAPIC_DELIV_MODE_NMI || \
+   mode == VLAPIC_DELIV_MODE_INIT ||\
+   mode == VLAPIC_DELIV_MODE_STARTUP)
+
+int
+ioapic_inj_irq(IOAPICState *s, uint8_t dest, uint8_t vector, uint8_t 
trig_mode, uint8_t delivery_mode)
+{
+    int msg_count;
+    if (!s || !s->lapic_info[dest]){
+        IOAPIC_ERR("ioapic_inj_irq NULL parameter\n");
+        return 0;
+    }
+    IOAPIC_LOG("ioapic_inj_irq %d , trig %d delive mode %d\n",
+      vector, trig_mode, delivery_mode);
+    switch(delivery_mode){
+        case VLAPIC_DELIV_MODE_FIXED:
+        case VLAPIC_DELIV_MODE_LPRI:
+            get_shareinfo_apic_msg(s->lapic_info[dest]);
+            msg_count = s->lapic_info[dest]->apic_msg_count;
+            s->lapic_info[dest]->vl_apic_msg[msg_count].deliv_mode = 
delivery_mode;
+            s->lapic_info[dest]->vl_apic_msg[msg_count].level = trig_mode;
+            s->lapic_info[dest]->vl_apic_msg[msg_count].vector = vector;
+            s->lapic_info[dest]->vl_apic_msg[msg_count].vector = vector;
+            s->lapic_info[dest]->apic_msg_count ++;
+            put_shareinfo_apic_msg(s->lapic_info[dest]);
+            break;
+        case VLAPIC_DELIV_MODE_EXT:
+/*            get_shareinfo_ext(s->lapic_info[dest]);
+            test_and_set_bit(vector, &s->lapic_info[dest]->vl_ext_intr[0]);
+            put_shareinfo_ext(s->lapic_info[dest]);*/
+            IOAPIC_ERR("<ioapic_inj_irq> Ext interrupt\n");
+            return 0;
+        default:
+            IOAPIC_ERR("<ioapic_inj_irq> error delivery mode\n");
+            break;
+    }
+    return 1;
+}
+
+int
+ioapic_match_logical_addr(IOAPICState *s, int number, uint8_t address)
+{
+    if(!s || !s->lapic_info[number]){
+        IOAPIC_ERR("ioapic_match_logical_addr NULL parameter: "
+          "number: %i s %p address %x\n",
+          number, s, address);
+        return 0;
+    }
+    IOAPIC_LOG("ioapic_match_logical_addr number %i address %x\n",
+      number, address);
+
+    if (((s->lapic_info[number]->vl_dest_format >> 28 ) & 0xf) != 0xf) {
+        IOAPIC_ERR("ioapic_match_logical_addr: cluster model not implemented 
still%x"
+          ,s->lapic_info[number]->vl_dest_format);
+#ifdef IOAPIC_DEBUG
+        ioapic_dump_shareinfo(s, number);
+#endif
+        return 0;
+    }
+    return ((address & ((s->lapic_info[number]->vl_logical_dest >> 24) & 
0xff)) != 0);
+}
+
+int
+ioapic_get_apr_lowpri(IOAPICState *s, int number)
+{
+    if(!s || !s->lapic_info[number]){
+        IOAPIC_ERR("ioapic_get_apr_lowpri NULL parameter\n");
+        return 0;
+    }
+    return s->lapic_info[number]->vl_arb_id;
+}
+
+uint32_t
+ioapic_get_delivery_bitmask(IOAPICState *s,
+uint8_t dest, uint8_t dest_mode, uint8_t vector, uint8_t delivery_mode)
+{
+    uint32_t mask = 0;
+    int low_priority = 256, selected = -1, i;
+    fprintf(logfile, "<ioapic_get_delivery_bitmask>: dest %d dest_mode %d"
+      "vector %d del_mode %d, lapic_count %d\n",
+      dest, dest_mode, vector, delivery_mode, s->lapic_count);
+    if (!s) return mask;
+    if (dest_mode == 0) { //Physical mode
+        if ((dest < s->lapic_count) && s->lapic_info[dest])
+            mask = 1 << dest;
+    }
+    else {
+        /* logical destination. call match_logical_addr for each APIC. */
+        if (dest == 0) return 0;
+        for (i=0; i< s->lapic_count; i++) {
+            //FIXME focus one, since no such issue on IPF, shoudl we add it?
+            if ( s->lapic_info[i] && ioapic_match_logical_addr(s, i, dest)){
+                if (delivery_mode != APIC_DM_LOWPRI)
+                    mask |= (1<<i);
+                else {
+                    if (low_priority > ioapic_get_apr_lowpri(s, i)){
+                        low_priority = ioapic_get_apr_lowpri(s, i);
+                        selected = i;
+                    }
+                    fprintf(logfile, "%d low_priority %d apr %d select %d\n",
+                      i, low_priority, ioapic_get_apr_lowpri(s, i), selected);
+                }
+            }
+        }
+        if (delivery_mode == APIC_DM_LOWPRI && (selected != -1)) 
+            mask |= (1<< selected);
+    }
+  return mask;
+}
+
+void
+ioapic_deliver(IOAPICState *s, int irqno){
+    uint8_t dest = s->redirtbl[irqno].RedirForm.dest_id;
+    uint8_t dest_mode = s->redirtbl[irqno].RedirForm.destmode;
+    uint8_t delivery_mode = s->redirtbl[irqno].RedirForm.deliver_mode;
+    uint8_t vector = s->redirtbl[irqno].RedirForm.vector;
+    uint8_t trig_mode = s->redirtbl[irqno].RedirForm.trigmod;
+    uint8_t bit;
+    uint32_t deliver_bitmask; 
+
+    IOAPIC_LOG("IOAPIC deliver: "
+      "dest %x dest_mode %x delivery_mode %x vector %x trig_mode %x\n",
+      dest, dest_mode, delivery_mode, vector, trig_mode);
+
+    deliver_bitmask =
+      ioapic_get_delivery_bitmask(s, dest, dest_mode, vector, delivery_mode);
+
+      IOAPIC_LOG("ioapic_get_delivery_bitmask return %x\n", deliver_bitmask);
+    if (!deliver_bitmask){
+        IOAPIC_ERR("Ioapic deliver, no target on destination\n");
+        return ;
+    }
+
+    switch (delivery_mode){
+        case VLAPIC_DELIV_MODE_FIXED:
+        case VLAPIC_DELIV_MODE_LPRI:
+        case VLAPIC_DELIV_MODE_EXT:
+            break;
+        case VLAPIC_DELIV_MODE_SMI:
+        case VLAPIC_DELIV_MODE_NMI:
+        case VLAPIC_DELIV_MODE_INIT:
+        case VLAPIC_DELIV_MODE_STARTUP:
+        default:
+            IOAPIC_ERR("Not support delivey mode %d\n", delivery_mode);
+            return ;
+    }
+
+    for (bit = 0; bit < s->lapic_count; bit++){
+        if (deliver_bitmask & (1 << bit)){
+            if (s->lapic_info[bit]){
+                ioapic_inj_irq(s, bit, vector, trig_mode, delivery_mode);
+            }
+        }
+    }
+}
+
+static inline int __fls(u32 word)
+{
+    int bit;
+    __asm__("bsrl %1,%0"
+      :"=r" (bit)
+      :"rm" (word));
+    return word ? bit : -1;
+}
+
+#if 0
+static __inline__ int find_highest_bit(unsigned long *data, int length){
+    while(length && !data[--length]);
+    return __fls(data[length]) +  32 * length;
+}
+#endif
+int
+ioapic_get_highest_irq(IOAPICState *s){
+    uint32_t irqs;
+    if (!s)
+        return -1;
+    irqs = s->irr & ~s->isr;
+    return __fls(irqs);
+}
+
+
+void
+service_ioapic(IOAPICState *s){
+    int irqno;
+
+    while((irqno = ioapic_get_highest_irq(s)) != -1){
+        IOAPIC_LOG("service_ioapic: highest irqno %x\n", irqno);
+
+        if (!s->redirtbl[irqno].RedirForm.mask)
+            ioapic_deliver(s, irqno);
+
+        if (s->redirtbl[irqno].RedirForm.trigmod == IOAPIC_LEVEL_TRIGGER){
+            s->isr |= (1 << irqno);
+        }
+ //       clear_bit(irqno, &s->irr);
+        s->irr &= ~(1 << irqno);
+    }
+}
+
+void
+ioapic_update_irq(IOAPICState *s)
+{
+    s->INTR = 1;
+}
+
+void
+ioapic_set_irq(IOAPICState *s, int irq, int level)
+{
+    IOAPIC_LOG("ioapic_set_irq %x %x\n", irq, level);
+
+    /* Timer interrupt implemented on HV side */
+    if(irq == 0x0) return;
+    if (!s){
+        fprintf(logfile, "ioapic_set_irq null parameter\n");
+        return;
+    }
+    if (!IOAPICEnabled(s) || s->redirtbl[irq].RedirForm.mask)
+        return;
+#ifdef IOAPIC_DEBUG
+    ioapic_dump_redir(s, irq);
+#endif
+    if (irq >= 0 && irq < IOAPIC_NUM_PINS){
+        uint32_t bit = 1 << irq;
+        if (s->redirtbl[irq].RedirForm.trigmod == IOAPIC_LEVEL_TRIGGER){
+            if(level)
+                s->irr |= bit;
+            else
+                s->irr &= ~bit;
+        }else{
+            if(level)
+                /* XXX No irr clear for edge interrupt */
+                s->irr |= bit;
+        }
+    }
+
+    ioapic_update_irq(s);
+}
+
+void
+ioapic_legacy_irq(int irq, int level)
+{
+    ioapic_set_irq(ioapic, irq, level);
+}
+
+static inline int find_highest_bit(u32 *data, int length){
+        while(length && !data[--length]);
+            return __fls(data[length]) +  32 * length;
+}
+
+int
+get_redir_num(IOAPICState *s, int vector){
+    int i = 0;
+    if(!s){
+        IOAPIC_ERR("Null parameter for get_redir_num\n");
+        return -1;
+    }
+    for(; i < IOAPIC_NUM_PINS-1; i++){
+        if (s->redirtbl[i].RedirForm.vector == vector)
+            return i;
+    }
+    return -1;
+}
+
+void
+ioapic_update_EOI()
+{
+    int i = 0;
+    uint32_t isr_info ;
+    uint32_t vector;
+    IOAPICState *s = ioapic;
+
+    isr_info = s->isr;
+
+    for (i = 0; i < s->lapic_count; i++){
+        if (!s->lapic_info[i] ||
+          !test_bit(VL_STATE_EOI, s->lapic_info[i]->vl_state))
+            continue;
+        get_shareinfo_eoi(s->lapic_info[i]);
+        while((vector = find_highest_bit((unsigned int 
*)&s->lapic_info[i]->vl_eoi[0],VLAPIC_INT_COUNT_32)) != -1){
+            int redir_num;
+            if ((redir_num = get_redir_num(s, vector)) == -1){
+                IOAPIC_ERR("Can't find redir item for %d EOI \n", vector);
+                continue;
+            }
+            if (!test_and_clear_bit(redir_num, &s->isr)){
+                IOAPIC_ERR("redir %d not set for %d  EOI\n", redir_num, 
vector);
+                continue;
+            }
+            clear_bit(vector, &s->lapic_info[i]->vl_eoi[0]); 
+        }
+        clear_bit(VL_STATE_EOI, &s->lapic_info[i]->vl_state);
+        put_shareinfo_eoi(s->lapic_info[i]);
+    }
+}
+
+
+void
+ioapic_init_apic_info(IOAPICState *s)
+{
+#ifdef IOAPIC_DEBUG
+    fprintf(logfile, "ioapic_init_apic_info\n");
+    if (!s)
+        return;
+#endif
+
+#if 0
+    if (!vio || !(vio->vl_number)){
+        fprintf(logfile, "null vio or o vl number\n");
+        return;
+    }
+
+    for (i = 0; i < MAX_LAPIC_NUM; i++) s->lapic_info[i] = NULL;
+
+    s->lapic_count = vio->vl_number;
+    for (i = 0; i < vio->vl_number; i++)
+        s->lapic_info[i] = vio->vl_info + i;
+#endif
+
+}
+
+void
+ioapic_intack(IOAPICState *s)
+{
+#ifdef IOAPIC_DEBUG
+    if (!s){
+        fprintf(logfile, "ioapic_intack null parameter\n");
+        return;
+    }
+#endif
+    if (!s) s->INTR = 0;
+}
+
+int
+ioapic_has_intr()
+{
+    return ioapic->INTR;
+}
+
+void
+do_ioapic()
+{
+    service_ioapic(ioapic);
+    ioapic_intack(ioapic);
+}
+
+IOAPICState *
+IOAPICInit( )
+{
+    IOAPICState *s;
+
+    s = qemu_mallocz(sizeof(IOAPICState));
+    if (!s){
+        fprintf(logfile, "IOAPICInit: malloc failed\n");
+        return NULL;
+    }
+
+    IOAPICReset(s);
+    ioapic_init_apic_info(s);
+    register_savevm("ioapic", 0, 1, ioapic_save, ioapic_load, s);
+    /* Remove after GFW ready */
+    ioapic_update_config(s, 0xfec00000, 1);
+
+    ioapic = s;
+    return s;
+}
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/ioapic.h
--- /dev/null   Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/hw/ioapic.h   Thu Jun 30 05:24:52 2005
@@ -0,0 +1,128 @@
+/////////////////////////////////////////////////////////////////////////
+//
+//  Copyright (C) 2001  MandrakeSoft S.A.
+//
+//    MandrakeSoft S.A.
+//    43, rue d'Aboukir
+//    75002 Paris - France
+//    http://www.linux-mandrake.com/
+//    http://www.mandrakesoft.com/
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+
+#ifndef __IOAPIC_H
+#define __IOAPIC_H
+
+#include "xc.h"
+#include <io/ioreq.h>
+#include <io/vmx_vlapic.h>
+
+#define IOAPIC_NUM_PINS 24
+#define IOAPIC_VERSION_ID 0x11
+#define IOAPIC_LEVEL_TRIGGER 1
+#define APIC_DM_FIXED  0
+#define APIC_DM_LOWPRI 1
+
+
+
+#ifdef CONFIG_SMP
+#define LOCK_PREFIX "lock ; "
+#else
+#define LOCK_PREFIX ""
+#endif
+
+#ifdef __I386__
+#define __OS "q" 
+#define __OP "r" 
+#else
+#define __OS "l"  /* Operation Suffix */
+#define __OP "e"  /* Operand Prefix */
+#endif
+
+#define ADDR (*(volatile long *) addr)
+#if 0
+#endif
+extern void *shared_page;
+extern FILE *logfile;
+#ifdef __BIGENDIAN__
+typedef union RedirStatus
+{
+    uint64_t value;
+    struct {
+        uint8_t dest_id;
+        uint8_t reserved[4];
+        uint8_t reserve:7;
+        uint8_t mask:1;         /* interrupt mask*/
+        uint8_t trigmod:1;
+        uint8_t remoteirr:1;
+        uint8_t polarity:1;
+        uint8_t delivestatus:1;
+        uint8_t destmode:1;
+        uint8_t deliver_mode:3;
+        uint8_t vector;
+    }RedirForm;
+}RedirStatus;
+#else
+typedef union RedirStatus
+{
+    uint64_t value;
+    struct {
+        uint8_t vector;
+        uint8_t deliver_mode:3;
+        uint8_t destmode:1;
+        uint8_t delivestatus:1;
+        uint8_t polarity:1;
+        uint8_t remoteirr:1;
+        uint8_t trigmod:1;
+        uint8_t mask:1;         /* interrupt mask*/
+        uint8_t reserve:7;
+        uint8_t reserved[4];
+        uint8_t dest_id;
+    }RedirForm;
+}RedirStatus;
+#endif
+/*
+ * IOAPICState stands for a instance of a IOAPIC
+ */
+
+/* FIXME tmp before working with Local APIC */
+#define IOAPIC_MEM_LENGTH 0x100
+#define IOAPIC_ENABLE_MASK 0x0
+#define IOAPIC_ENABLE_FLAG (1 << IOAPIC_ENABLE_MASK)
+#define MAX_LAPIC_NUM 32
+
+struct IOAPICState{
+    uint32_t INTR;
+    uint32_t id;
+    uint32_t arb_id;
+    uint32_t  flags;
+    unsigned long base_address;
+    uint32_t irr;
+    uint32_t isr;           /* This is used for level trigger */
+    uint8_t  vector_irr[256];
+    RedirStatus redirtbl[IOAPIC_NUM_PINS];
+    uint32_t ioregsel;
+    uint32_t lapic_count;
+    vlapic_info *lapic_info[MAX_LAPIC_NUM];
+};
+#define IOAPIC_REG_APIC_ID 0x0
+#define IOAPIC_REG_VERSION 0x1
+#define IOAPIC_REG_ARB_ID  0x2
+#define IOAPICEnabled(s) (s->flags & IOAPIC_ENABLE_FLAG)
+
+typedef struct IOAPICState IOAPICState;
+
+#endif
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/include/public/io/vmx_vlapic.h
--- /dev/null   Thu Jun 30 04:32:55 2005
+++ b/xen/include/public/io/vmx_vlapic.h        Thu Jun 30 05:24:52 2005
@@ -0,0 +1,57 @@
+#ifndef _VMX_VLAPIC_H
+#define _VMX_VLAPIC_H
+
+/*
+   We extended one bit for PIC type
+ */
+#define VLAPIC_DELIV_MODE_FIXED          0x0
+#define VLAPIC_DELIV_MODE_LPRI           0x1
+#define VLAPIC_DELIV_MODE_SMI            0x2
+#define VLAPIC_DELIV_MODE_NMI            0x4
+#define VLAPIC_DELIV_MODE_INIT           0x5
+#define VLAPIC_DELIV_MODE_STARTUP        0x6
+#define VLAPIC_DELIV_MODE_EXT            0x7
+#define VLAPIC_DELIV_MODE_MASK            0x8
+
+#define VLAPIC_MSG_LEVEL                4
+
+#define INTR_EXT   0
+#define INTR_APIC   1
+#define INTR_LAPIC  2
+
+#define VL_STATE_EOI    1
+#define VL_STATE_EXT_LOCK   2
+#define VL_STATE_MSG_LOCK   3
+#define VL_STATE_EOI_LOCK   3
+
+#define VLOCAL_APIC_MAX_INTS             256
+#define VLAPIC_INT_COUNT                (VLOCAL_APIC_MAX_INTS/(BITS_PER_BYTE * 
sizeof(u64)))
+#define VLAPIC_INT_COUNT_32             (VLOCAL_APIC_MAX_INTS/(BITS_PER_BYTE * 
sizeof(u32)))
+
+struct vapic_bus_message{
+   u8   deliv_mode:4;   /* deliver mode, including fixed, LPRI, etc */
+   u8   level:1;        /* level or edge */
+   u8   trig_mod:1;    /* assert or disassert */
+   u8   reserved:2;
+   u8   vector;
+};
+
+typedef struct {
+    /* interrupt for PIC and ext type IOAPIC interrupt */
+    u64   vl_ext_intr[VLAPIC_INT_COUNT];
+    u64   vl_ext_intr_mask[VLAPIC_INT_COUNT];
+    u64   vl_apic_intr[VLAPIC_INT_COUNT];
+    u64   vl_apic_tmr[VLAPIC_INT_COUNT];
+    u64   vl_eoi[VLAPIC_INT_COUNT];
+    u32   vl_lapic_id;
+    u32   direct_intr;
+    u32   vl_apr;
+    u32   vl_logical_dest;
+    u32   vl_dest_format;
+    u32   vl_arb_id;
+    u32   vl_state;
+    u32   apic_msg_count;
+    struct vapic_bus_message  vl_apic_msg[24];
+} vlapic_info;
+
+#endif /* _VMX_VLAPIC_H_ */

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.