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

[Xen-changelog] This patch provide local APIC support for vmx guest.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID cc23d4236b2054f9d0cea98cff2e2955d6b3bdd9
# Parent  f23b897930d15ec692060ff25c7acc1f44894d69
This patch provide local APIC support for vmx guest.

A configure option is also added to disable it, which is off by default.

Signed-off-by: Jiang Yunhong <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Li Xin <xin.b.li@xxxxxxxxx>
Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx>
Signed-off-by: Jun Nakajima <jun.nakajima@xxxxxxxxx>

diff -r f23b897930d1 -r cc23d4236b20 tools/libxc/xc_vmx_build.c
--- a/tools/libxc/xc_vmx_build.c        Thu Oct 27 17:22:45 2005
+++ b/tools/libxc/xc_vmx_build.c        Fri Oct 28 08:48:46 2005
@@ -279,6 +279,7 @@
                        vcpu_guest_context_t *ctxt,
                        unsigned long shared_info_frame,
                        unsigned int control_evtchn,
+                       unsigned int lapic,
                        unsigned int vcpus,
                        unsigned int store_evtchn,
                        unsigned long *store_mfn)
@@ -554,7 +555,7 @@
     ctxt->user_regs.eax = 0;
     ctxt->user_regs.esp = 0;
     ctxt->user_regs.ebx = 0; /* startup_32 expects this to be 0 to signal boot 
cpu */
-    ctxt->user_regs.ecx = 0;
+    ctxt->user_regs.ecx = lapic;
     ctxt->user_regs.esi = 0;
     ctxt->user_regs.edi = 0;
     ctxt->user_regs.ebp = 0;
@@ -597,6 +598,7 @@
                  int memsize,
                  const char *image_name,
                  unsigned int control_evtchn,
+                 unsigned int lapic,
                  unsigned int vcpus,
                  unsigned int store_evtchn,
                  unsigned long *store_mfn)
@@ -651,9 +653,9 @@
         goto error_out;
     }
 
-    if ( setup_guest(xc_handle, domid, memsize, image, image_size,
-                     nr_pages, ctxt, op.u.getdomaininfo.shared_info_frame,
-                     control_evtchn, vcpus, store_evtchn, store_mfn) < 0)
+    if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages,
+                     ctxt, op.u.getdomaininfo.shared_info_frame, 
control_evtchn,
+                     lapic, vcpus, store_evtchn, store_mfn) < 0)
     {
         ERROR("Error constructing guest OS");
         goto error_out;
diff -r f23b897930d1 -r cc23d4236b20 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h    Thu Oct 27 17:22:45 2005
+++ b/tools/libxc/xenguest.h    Fri Oct 28 08:48:46 2005
@@ -56,6 +56,7 @@
                  int memsize,
                  const char *image_name,
                  unsigned int control_evtchn,
+                 unsigned int lapic,
                  unsigned int vcpus,
                  unsigned int store_evtchn,
                  unsigned long *store_mfn);
diff -r f23b897930d1 -r cc23d4236b20 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu Oct 27 17:22:45 2005
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri Oct 28 08:48:46 2005
@@ -438,19 +438,20 @@
     char *image;
     int control_evtchn, store_evtchn;
     int vcpus = 1;
+    int lapic = 0;
     int memsize;
     unsigned long store_mfn = 0;
 
     static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
-                                "memsize", "image", "vcpus", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisi", kwd_list,
+                                "memsize", "image", "lapic", "vcpus", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisii", kwd_list,
                                       &dom, &control_evtchn, &store_evtchn,
-                                      &memsize, &image, &vcpus) )
+                                      &memsize, &image, &lapic, &vcpus) )
         return NULL;
 
     if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, control_evtchn,
-                      vcpus, store_evtchn, &store_mfn) != 0 )
+                      lapic, vcpus, store_evtchn, &store_mfn) != 0 )
         return PyErr_SetFromErrno(xc_error);
 
     return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
diff -r f23b897930d1 -r cc23d4236b20 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Thu Oct 27 17:22:45 2005
+++ b/tools/python/xen/xend/image.py    Fri Oct 28 08:48:46 2005
@@ -203,6 +203,10 @@
 
         self.dmargs += self.configVNC(imageConfig)
 
+        self.lapic = 0
+        lapic = sxp.child_value(imageConfig, 'lapic')
+        if not lapic is None:
+            self.lapic = int(lapic)
 
     def buildDomain(self):
         # Create an event channel
@@ -217,6 +221,7 @@
         log.debug("control_evtchn = %d", self.device_channel)
         log.debug("store_evtchn   = %d", store_evtchn)
         log.debug("memsize        = %d", self.vm.getMemoryTarget() / 1024)
+        log.debug("lapic          = %d", self.lapic)
         log.debug("vcpus          = %d", self.vm.getVCpuCount())
 
         return xc.vmx_build(dom            = self.vm.getDomid(),
@@ -224,6 +229,7 @@
                             control_evtchn = self.device_channel,
                             store_evtchn   = store_evtchn,
                             memsize        = self.vm.getMemoryTarget() / 1024,
+                            lapic          = self.lapic,
                             vcpus          = self.vm.getVCpuCount())
 
 
diff -r f23b897930d1 -r cc23d4236b20 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Thu Oct 27 17:22:45 2005
+++ b/tools/python/xen/xm/create.py     Fri Oct 28 08:48:46 2005
@@ -158,6 +158,10 @@
           fn=set_int, default=None,
           use="CPU to run the domain on.")
 
+gopts.var('lapic', val='LAPIC',
+          fn=set_int, default=0,
+          use="Disable or enable local APIC of VMX domain.")
+
 gopts.var('vcpus', val='VCPUS',
           fn=set_int, default=1,
           use="# of Virtual CPUS in domain.")
@@ -315,10 +319,6 @@
 gopts.var('nfs_root', val="PATH",
           fn=set_value, default=None,
           use="Set the path of the root NFS directory.")
-
-gopts.var('memmap', val='FILE',
-          fn=set_value, default='',
-          use="Path to memap SXP file.")
 
 gopts.var('device_model', val='FILE',
           fn=set_value, default='',
@@ -542,9 +542,9 @@
 def configure_vmx(opts, config_image, vals):
     """Create the config for VMX devices.
     """
-    args = [ 'memmap', 'device_model', 'vcpus', 'cdrom',
-             'boot', 'fda', 'fdb', 'localtime', 'serial', 'macaddr', 'stdvga', 
-             'isa', 'nographic', 'vnc', 'vncviewer', 'sdl', 'display', 
'ne2000']
+    args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
+             'localtime', 'serial', 'macaddr', 'stdvga', 'isa', 'nographic',
+             'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'lapic']
     for a in args:
         if (vals.__dict__[a]):
             config_image.append([a, vals.__dict__[a]])
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c       Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/apic.c       Fri Oct 28 08:48:46 2005
@@ -815,6 +815,10 @@
     return result;
 }
 
+unsigned int get_apic_bus_scale(void)
+{
+    return bus_scale;
+}
 
 static unsigned int calibration_result;
 
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/dm/i8259.c
--- a/xen/arch/x86/dm/i8259.c   Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/dm/i8259.c   Fri Oct 28 08:48:46 2005
@@ -32,8 +32,8 @@
 #include <public/io/ioreq.h>
 #include <asm/vmx.h>
 #include <public/io/vmx_vpic.h>
-#include <public/io/vmx_vlapic.h>
 #include <asm/current.h>
+#include <asm/vmx_vlapic.h>
 
 /* set irq level. If an edge is detected, then the IRR is set to 1 */
 static inline void pic_set_irq1(PicState *s, int irq, int level)
@@ -135,7 +135,6 @@
 {
     s->pics[1].irr |= (uint8_t)(irqs >> 8);
     s->pics[0].irr |= (uint8_t) irqs;
-    /* TODO for alt_irq_func */
     pic_update_irq(s);
 }
 
@@ -505,14 +504,22 @@
 {
     int intno;
     struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic;
-    
+    struct vmx_platform *plat = &v->domain->arch.vmx_platform;
+
+    if ( !vlapic_accept_pic_intr(v) )
+        return -1;
+
+    if ( !plat->interrupt_request )
+        return -1;
+
     /* read the irq from the PIC */
     intno = pic_read_irq(s);
     *type = VLAPIC_DELIV_MODE_EXT;
+    plat->interrupt_request = 0;
     return intno;
 }
 
-int is_pit_irq(struct vcpu *v, int irq)
+int is_pit_irq(struct vcpu *v, int irq, int type)
 {
     int  pit_vec = v->domain->arch.vmx_platform.vmx_pic.pics[0].irq_base;
 
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/vmx.c
--- a/xen/arch/x86/vmx.c        Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/vmx.c        Fri Oct 28 08:48:46 2005
@@ -65,6 +65,11 @@
 
     if ( v == v->domain->vcpu[0] )
     {
+        v->domain->arch.vmx_platform.lapic_enable =
+            v->arch.guest_context.user_regs.ecx;
+        v->arch.guest_context.user_regs.ecx = 0;
+        VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "lapic enable is %d.\n",
+                    v->domain->arch.vmx_platform.lapic_enable);
         /*
          * Required to do this once per domain
          * XXX todo: add a seperate function to do these.
@@ -96,6 +101,10 @@
     destroy_vmcs(&v->arch.arch_vmx);
     free_monitor_pagetable(v);
     rem_ac_timer(&v->domain->arch.vmx_platform.vmx_pit.pit_timer);
+    if ( vmx_apic_support(v->domain) ) {
+        rem_ac_timer( &(VLAPIC(v)->vlapic_timer) );
+        xfree( VLAPIC(v) );
+    }
 }
 
 #ifdef __x86_64__
@@ -442,7 +451,9 @@
 
     /* Use 1:1 page table to identify MMIO address space */
     if ( mmio_space(gpa) ){
-        if (gpa >= 0xFEE00000) { /* workaround for local APIC */
+        struct vcpu *v = current;
+        /* No support for APIC */
+        if (!vmx_apic_support(v->domain) && gpa >= 0xFEC00000) { 
             u32 inst_len;
             __vmread(VM_EXIT_INSTRUCTION_LEN, &(inst_len));
             __update_guest_eip(inst_len);
@@ -487,6 +498,7 @@
 {
     unsigned int eax, ebx, ecx, edx;
     unsigned long eip;
+    struct vcpu *v = current;
 
     __vmread(GUEST_RIP, &eip);
 
@@ -500,6 +512,9 @@
     cpuid(input, &eax, &ebx, &ecx, &edx);
 
     if (input == 1) {
+        if ( vmx_apic_support(v->domain) &&
+                !vlapic_global_enabled((VLAPIC(v))) )
+            clear_bit(X86_FEATURE_APIC, &edx);
 #ifdef __i386__
         clear_bit(X86_FEATURE_PSE, &edx);
         clear_bit(X86_FEATURE_PAE, &edx);
@@ -1441,6 +1456,7 @@
 static inline void vmx_do_msr_read(struct cpu_user_regs *regs)
 {
     u64 msr_content = 0;
+    struct vcpu *v = current;
 
     VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read: ecx=%lx, eax=%lx, edx=%lx",
                 (unsigned long)regs->ecx, (unsigned long)regs->eax,
@@ -1455,6 +1471,9 @@
     case MSR_IA32_SYSENTER_EIP:
         __vmread(GUEST_SYSENTER_EIP, &msr_content);
         break;
+    case MSR_IA32_APICBASE:
+        msr_content = VLAPIC(v) ? VLAPIC(v)->apic_base_msr : 0;
+        break;
     default:
         if(long_mode_do_msr_read(regs))
             return;
@@ -1474,6 +1493,7 @@
 static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
 {
     u64 msr_content;
+    struct vcpu *v = current;
 
     VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_write: ecx=%lx, eax=%lx, edx=%lx",
                 (unsigned long)regs->ecx, (unsigned long)regs->eax,
@@ -1490,6 +1510,9 @@
         break;
     case MSR_IA32_SYSENTER_EIP:
         __vmwrite(GUEST_SYSENTER_EIP, msr_content);
+        break;
+    case MSR_IA32_APICBASE:
+        vlapic_msr_set(VLAPIC(v), msr_content);
         break;
     default:
         long_mode_do_msr_write(regs);
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/vmx_intercept.c
--- a/xen/arch/x86/vmx_intercept.c      Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/vmx_intercept.c      Fri Oct 28 08:48:46 2005
@@ -23,6 +23,7 @@
 #include <asm/vmx_platform.h>
 #include <asm/vmx_virpit.h>
 #include <asm/vmx_intercept.h>
+#include <asm/vmx_vlapic.h>
 #include <public/io/ioreq.h>
 #include <xen/lib.h>
 #include <xen/sched.h>
@@ -31,6 +32,123 @@
 #include <xen/event.h>
 
 #ifdef CONFIG_VMX
+
+struct vmx_mmio_handler vmx_mmio_handers[VMX_MMIO_HANDLER_NR] =
+{
+    {
+        .check_handler = vlapic_range,
+        .read_handler  = vlapic_read,
+        .write_handler = vlapic_write
+    }
+};
+
+static inline void vmx_mmio_access(struct vcpu *v,
+                                   ioreq_t *p,
+                                   vmx_mmio_read_t read_handler,
+                                   vmx_mmio_write_t write_handler)
+{
+    ioreq_t *req;
+    vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id);
+    unsigned int tmp1, tmp2;
+    unsigned long data;
+
+    if (vio == NULL) {
+        printk("vlapic_access: bad shared page\n");
+        domain_crash_synchronous();
+    }
+
+    req = &vio->vp_ioreq;
+
+    switch (req->type) {
+    case IOREQ_TYPE_COPY:
+    {
+        int sign = (req->df) ? -1 : 1, i;
+
+        if (!req->pdata_valid) {
+            if (req->dir == IOREQ_READ){
+                req->u.data = read_handler(v, req->addr, req->size);
+            } else {                 /* req->dir != IOREQ_READ */
+                write_handler(v, req->addr, req->size, req->u.data);
+            }
+        } else {                     /* !req->pdata_valid */
+            if (req->dir == IOREQ_READ) {
+                for (i = 0; i < req->count; i++) {
+                    data = read_handler(v,
+                      req->addr + (sign * i * req->size),
+                      req->size);
+                    vmx_copy(&data,
+                      (unsigned long)p->u.pdata + (sign * i * req->size),
+                      p->size,
+                      VMX_COPY_OUT);
+                }
+            } else {                  /* !req->dir == IOREQ_READ */
+                for (i = 0; i < req->count; i++) {
+                    vmx_copy(&data,
+                      (unsigned long)p->u.pdata + (sign * i * req->size),
+                      p->size,
+                      VMX_COPY_IN);
+                    write_handler(v,
+                      req->addr + (sign * i * req->size),
+                      req->size, data);
+                }
+            }
+        }
+        break;
+    }
+
+    case IOREQ_TYPE_AND:
+        tmp1 = read_handler(v, req->addr, req->size);
+        if (req->dir == IOREQ_WRITE) {
+            tmp2 = tmp1 & (unsigned long) req->u.data;
+            write_handler(v, req->addr, req->size, tmp2);
+        }
+        req->u.data = tmp1;
+        break;
+
+    case IOREQ_TYPE_OR:
+        tmp1 = read_handler(v, req->addr, req->size);
+        if (req->dir == IOREQ_WRITE) {
+            tmp2 = tmp1 | (unsigned long) req->u.data;
+            write_handler(v, req->addr, req->size, tmp2);
+        }
+        req->u.data = tmp1;
+        break;
+
+    case IOREQ_TYPE_XOR:
+        tmp1 = read_handler(v, req->addr, req->size);
+        if (req->dir == IOREQ_WRITE) {
+            tmp2 = tmp1 ^ (unsigned long) req->u.data;
+            write_handler(v, req->addr, req->size, tmp2);
+        }
+        req->u.data = tmp1;
+        break;
+
+    default:
+        printk("error ioreq type for local APIC %x\n", req->type);
+        domain_crash_synchronous();
+        break;
+    }
+}
+
+int vmx_mmio_intercept(ioreq_t *p)
+{
+    struct vcpu *v = current;
+    int i;
+    struct vmx_mmio_handler *handler = vmx_mmio_handers;
+
+    /* XXX currently only APIC use intercept */
+    if ( !vmx_apic_support(v->domain) )
+        return 0;
+
+    for ( i = 0; i < VMX_MMIO_HANDLER_NR; i++ ) {
+        if ( handler[i].check_handler(v, p->addr) ) {
+            vmx_mmio_access(v, p,
+              handler[i].read_handler, handler[i].write_handler);
+            return 1;
+        }
+    }
+    return 0;
+}
 
 /*
  * Check if the request is handled inside xen
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/vmx_io.c
--- a/xen/arch/x86/vmx_io.c     Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/vmx_io.c     Fri Oct 28 08:48:46 2005
@@ -36,9 +36,9 @@
 #include <asm/apic.h>
 #include <asm/shadow.h>
 
+#include <asm/vmx_vlapic.h>
 #include <public/io/ioreq.h>
 #include <public/io/vmx_vpic.h>
-#include <public/io/vmx_vlapic.h>
 
 #ifdef CONFIG_VMX
 #if defined (__i386__)
@@ -732,48 +732,6 @@
     } while(1);
 }
 
-#if defined(__i386__) || defined(__x86_64__)
-static inline int __fls(u32 word)
-{
-    int bit;
-
-    __asm__("bsrl %1,%0"
-            :"=r" (bit)
-            :"rm" (word));
-    return word ? bit : -1;
-}
-#else
-#define __fls(x)  generic_fls(x)
-static __inline__ int generic_fls(u32 x)
-{
-    int r = 31;
-
-    if (!x)
-        return -1;
-    if (!(x & 0xffff0000u)) {
-        x <<= 16;
-        r -= 16;
-    }
-    if (!(x & 0xff000000u)) {
-        x <<= 8;
-        r -= 8;
-    }
-    if (!(x & 0xf0000000u)) {
-        x <<= 4;
-        r -= 4;
-    }
-    if (!(x & 0xc0000000u)) {
-        x <<= 2;
-        r -= 2;
-    }
-    if (!(x & 0x80000000u)) {
-        x <<= 1;
-        r -= 1;
-    }
-    return r;
-}
-#endif
-
 /* Simple minded Local APIC priority implementation. Fix later */
 static __inline__ int find_highest_irq(u32 *pintr)
 {
@@ -801,31 +759,31 @@
     struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
     u64    drift;
 
+    if ( is_pit_irq(v, vector, type) ) {
+        if ( !vpit->first_injected ) {
+            vpit->first_injected = 1;
+            vpit->pending_intr_nr = 0;
+        } else {
+            vpit->pending_intr_nr--;
+        }
+        vpit->inject_point = NOW();
+        drift = vpit->period_cycles * vpit->pending_intr_nr;
+        drift = v->arch.arch_vmx.tsc_offset - drift;
+        __vmwrite(TSC_OFFSET, drift);
+
+#if defined (__i386__)
+        __vmwrite(TSC_OFFSET_HIGH, (drift >> 32));
+#endif
+
+    }
+
     switch(type)
     {
     case VLAPIC_DELIV_MODE_EXT:
-        if ( is_pit_irq(v, vector) ) {
-            if ( !vpit->first_injected ) {
-                vpit->first_injected = 1;
-                vpit->pending_intr_nr = 0;
-            }
-            else {
-                vpit->pending_intr_nr--;
-            }
-            vpit->inject_point = NOW();
-            drift = vpit->period_cycles * vpit->pending_intr_nr;
-            drift = v->arch.arch_vmx.tsc_offset - drift;
-            __vmwrite(TSC_OFFSET, drift);
-
-#if defined (__i386__)
-            __vmwrite(TSC_OFFSET_HIGH, (drift >> 32));
-#endif
- 
-        }
         break;
 
     default:
-        printk("Not support interrupt type\n");
+        vlapic_post_injection(v, vector, type);
         break;
     }
 }
@@ -885,6 +843,24 @@
 
 }
 
+int cpu_get_interrupt(struct vcpu *v, int *type)
+{
+    int intno;
+    struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic;
+
+    if ( (intno = cpu_get_apic_interrupt(v, type)) != -1 ) {
+        /* set irq request if a PIC irq is still pending */
+        /* XXX: improve that */
+        pic_update_irq(s);
+        return intno;
+    }
+    /* read the irq from the PIC */
+    if ( (intno = cpu_get_pic_interrupt(v, type)) != -1 )
+        return intno;
+
+    return -1;
+}
+
 asmlinkage void vmx_intr_assist(void)
 {
     int intr_type = 0;
@@ -902,11 +878,6 @@
         pic_set_irq(pic, 0, 1);
     }
 
-    if ( !plat->interrupt_request ) {
-        disable_irq_window(cpu_exec_control);
-        return;
-    }
-
     __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
 
     if (intr_fields & INTR_INFO_VALID_MASK) {
@@ -928,16 +899,21 @@
         enable_irq_window(cpu_exec_control);
         return;
     }
-    plat->interrupt_request = 0;
-    highest_vector = cpu_get_pic_interrupt(v, &intr_type); 
+
+    highest_vector = cpu_get_interrupt(v, &intr_type); 
+
+    if (highest_vector == -1) {
+        disable_irq_window(cpu_exec_control);
+        return;
+    }
 
     switch (intr_type) {
     case VLAPIC_DELIV_MODE_EXT:
+    case VLAPIC_DELIV_MODE_FIXED:
+    case VLAPIC_DELIV_MODE_LPRI:
         vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE);
         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:
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/vmx_vmcs.c
--- a/xen/arch/x86/vmx_vmcs.c   Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/vmx_vmcs.c   Fri Oct 28 08:48:46 2005
@@ -252,6 +252,10 @@
     pic_init(&platform->vmx_pic,  pic_irq_request, 
              &platform->interrupt_request);
     register_pic_io_hook();
+
+    if ( vmx_apic_support(d) ) {
+        spin_lock_init(&d->arch.vmx_platform.round_robin_lock);
+    }
 }
 
 static void vmx_set_host_env(struct vcpu *v)
@@ -312,6 +316,9 @@
     error |= __vmwrite(CR4_READ_SHADOW, cr4);
 
     vmx_stts();
+
+    if(vmx_apic_support(v->domain))
+        vlapic_init(v);
 
     vmx_set_host_env(v);
 
diff -r f23b897930d1 -r cc23d4236b20 xen/include/asm-x86/vmx_intercept.h
--- a/xen/include/asm-x86/vmx_intercept.h       Thu Oct 27 17:22:45 2005
+++ b/xen/include/asm-x86/vmx_intercept.h       Fri Oct 28 08:48:46 2005
@@ -14,6 +14,16 @@
 #define VMX_MMIO                    1
 
 typedef int (*intercept_action_t)(ioreq_t *);
+typedef unsigned long (*vmx_mmio_read_t)(struct vcpu *v,
+                                         unsigned long addr,
+                                         unsigned long length);
+
+typedef unsigned long (*vmx_mmio_write_t)(struct vcpu *v,
+                                         unsigned long addr,
+                                         unsigned long length,
+                                         unsigned long val);
+
+typedef int (*vmx_mmio_check_t)(struct vcpu *v, unsigned long addr);
 
 struct io_handler {
     int                 type;
@@ -27,6 +37,16 @@
     struct  io_handler hdl_list[MAX_IO_HANDLER];
 };
 
+struct vmx_mmio_handler {
+    vmx_mmio_check_t check_handler;
+    vmx_mmio_read_t read_handler;
+    vmx_mmio_write_t write_handler;
+};
+
+#define VMX_MMIO_HANDLER_NR 1
+
+extern struct vmx_mmio_handler vmx_mmio_handers[VMX_MMIO_HANDLER_NR];
+
 /* global io interception point in HV */
 extern int vmx_io_intercept(ioreq_t *p, int type);
 extern int register_io_handler(unsigned long addr, unsigned long size,
@@ -37,10 +57,7 @@
     return vmx_io_intercept(p, VMX_PORTIO);
 }
 
-static inline int vmx_mmio_intercept(ioreq_t *p)
-{
-    return vmx_io_intercept(p, VMX_MMIO);
-}
+int vmx_mmio_intercept(ioreq_t *p);
 
 static inline int register_portio_handler(unsigned long addr,
                                           unsigned long size,
@@ -49,11 +66,4 @@
     return register_io_handler(addr, size, action, VMX_PORTIO);
 }
 
-static inline int register_mmio_handler(unsigned long addr,
-                                        unsigned long size,
-                                        intercept_action_t action)
-{
-    return register_io_handler(addr, size, action, VMX_MMIO);
-}
-
 #endif /* _VMX_INTERCEPT_H */
diff -r f23b897930d1 -r cc23d4236b20 xen/include/asm-x86/vmx_platform.h
--- a/xen/include/asm-x86/vmx_platform.h        Thu Oct 27 17:22:45 2005
+++ b/xen/include/asm-x86/vmx_platform.h        Fri Oct 28 08:48:46 2005
@@ -80,10 +80,13 @@
 struct vmx_platform {
     unsigned long          shared_page_va;
     unsigned int           nr_vcpu;
+    unsigned int           lapic_enable;
 
     struct vmx_virpit      vmx_pit;
     struct vmx_io_handler  vmx_io_handler;
     struct vmx_virpic      vmx_pic;
+    unsigned char          round_info[256];
+    spinlock_t             round_robin_lock;
     int                    interrupt_request;
 };
 
diff -r f23b897930d1 -r cc23d4236b20 xen/include/asm-x86/vmx_vmcs.h
--- a/xen/include/asm-x86/vmx_vmcs.h    Thu Oct 27 17:22:45 2005
+++ b/xen/include/asm-x86/vmx_vmcs.h    Fri Oct 28 08:48:46 2005
@@ -22,6 +22,7 @@
 #include <asm/config.h>
 #include <asm/vmx_cpu.h>
 #include <asm/vmx_platform.h>
+#include <asm/vmx_vlapic.h>
 #include <public/vmx_assist.h>
 
 extern int start_vmx(void);
@@ -96,6 +97,7 @@
     struct msr_state        msr_content;
     struct mmio_op          mmio_op;  /* MMIO */
     void                    *io_bitmap_a, *io_bitmap_b;
+    struct vlapic           *vlapic;
     u64                     tsc_offset;
 };
 
@@ -272,18 +274,21 @@
 
 #define VMX_DEBUG 1
 #if VMX_DEBUG
-#define DBG_LEVEL_0     (1 << 0)
-#define DBG_LEVEL_1     (1 << 1)
-#define DBG_LEVEL_2     (1 << 2)
-#define DBG_LEVEL_3     (1 << 3)
-#define DBG_LEVEL_IO    (1 << 4)
-#define DBG_LEVEL_VMMU  (1 << 5)
+#define DBG_LEVEL_0                 (1 << 0)
+#define DBG_LEVEL_1                 (1 << 1)
+#define DBG_LEVEL_2                 (1 << 2)
+#define DBG_LEVEL_3                 (1 << 3)
+#define DBG_LEVEL_IO                (1 << 4)
+#define DBG_LEVEL_VMMU              (1 << 5)
+#define DBG_LEVEL_VLAPIC            (1 << 6)
+#define DBG_LEVEL_VLAPIC_TIMER      (1 << 7)
+#define DBG_LEVEL_VLAPIC_INTERRUPT  (1 << 7)
 
 extern unsigned int opt_vmx_debug_level;
 #define VMX_DBG_LOG(level, _f, _a...)           \
     if ((level) & opt_vmx_debug_level)          \
         printk("[VMX:%d.%d] " _f "\n",          \
-                current->domain->domain_id, current->vcpu_id, ## _a)
+               current->domain->domain_id, current->vcpu_id, ## _a)
 #else
 #define VMX_DBG_LOG(level, _f, _a...)
 #endif
diff -r f23b897930d1 -r cc23d4236b20 xen/include/public/io/ioreq.h
--- a/xen/include/public/io/ioreq.h     Thu Oct 27 17:22:45 2005
+++ b/xen/include/public/io/ioreq.h     Fri Oct 28 08:48:46 2005
@@ -29,11 +29,11 @@
 #define STATE_IORESP_READY      3
 #define STATE_IORESP_HOOK       4
 
-#define IOREQ_TYPE_PIO  0 /* pio */
-#define IOREQ_TYPE_COPY  1 /* mmio ops */
-#define IOREQ_TYPE_AND  2
-#define IOREQ_TYPE_OR  3
-#define IOREQ_TYPE_XOR  4
+#define IOREQ_TYPE_PIO          0 /* pio */
+#define IOREQ_TYPE_COPY         1 /* mmio ops */
+#define IOREQ_TYPE_AND          2
+#define IOREQ_TYPE_OR           3
+#define IOREQ_TYPE_XOR          4
 
 /*
  * VMExit dispatcher should cooperate with instruction decoder to
@@ -55,9 +55,10 @@
     uint8_t type;    /* I/O type                     */
 } ioreq_t;
 
-#define MAX_VECTOR    256
+#define MAX_VECTOR      256
 #define BITS_PER_BYTE   8
 #define INTR_LEN        (MAX_VECTOR/(BITS_PER_BYTE * sizeof(uint64_t)))
+#define INTR_LEN_32     (MAX_VECTOR/(BITS_PER_BYTE * sizeof(uint32_t)))
 
 typedef struct {
     uint16_t  pic_elcr;
diff -r f23b897930d1 -r cc23d4236b20 xen/include/public/io/vmx_vpic.h
--- a/xen/include/public/io/vmx_vpic.h  Thu Oct 27 17:22:45 2005
+++ b/xen/include/public/io/vmx_vpic.h  Fri Oct 28 08:48:46 2005
@@ -76,7 +76,7 @@
 uint32_t pic_intack_read(struct vmx_virpic *s);
 void register_pic_io_hook (void);
 int cpu_get_pic_interrupt(struct vcpu *v, int *type);
-int is_pit_irq(struct vcpu *v, int irq);
+int is_pit_irq(struct vcpu *v, int irq, int type);
 void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs);
 void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs);
 
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/vmx_vlapic.c
--- /dev/null   Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/vmx_vlapic.c Fri Oct 28 08:48:46 2005
@@ -0,0 +1,997 @@
+/*
+ * vmx_vlapic.c: virtualize LAPIC for VMX vcpus.
+ * Copyright (c) 2004, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/mm.h>
+#include <xen/xmalloc.h>
+#include <asm/shadow.h>
+#include <asm/page.h>
+#include <xen/event.h>
+#include <xen/trace.h>
+#include <asm/vmx.h>
+#include <asm/vmx_platform.h>
+#include <asm/vmx_vlapic.h>
+
+#include <xen/lib.h>
+#include <xen/sched.h>
+#include <asm/current.h>
+#include <public/io/ioreq.h>
+
+#ifdef CONFIG_VMX
+
+/* XXX remove this definition after GFW enabled */
+#define VLAPIC_NO_BIOS
+
+extern unsigned int get_apic_bus_scale(void);
+
+static unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] =
+{
+    0x310ff, 0x117ff, 0x117ff, 0x1f7ff, 0x1f7ff, 0x117ff
+};
+
+int vlapic_find_highest_irr(struct vlapic *vlapic)
+{
+    int result;
+
+    result = find_highest_bit((uint32_t *)&vlapic->irr[0], INTR_LEN_32);
+
+    if (result != -1 && result < 16) {
+        printk("VLAPIC: irr on reserved bits %d\n ", result);
+        domain_crash_synchronous();
+    }
+
+    return result;
+}
+
+inline int vmx_apic_support(struct domain *d)
+{
+    return d->arch.vmx_platform.lapic_enable;
+}
+
+int vlapic_find_highest_isr(struct vlapic *vlapic)
+{
+    int result;
+
+    result = find_highest_bit((uint32_t *)&vlapic->isr[0], INTR_LEN_32);
+
+    if (result != -1 && result < 16) {
+        int i = 0;
+        printk("VLAPIC: isr on reserved bits %d, isr is\n ", result);
+        for (i = 0; i < INTR_LEN_32; i += 2)
+            printk("%d: 0x%08x%08x\n", i, vlapic->isr[i], vlapic->isr[i+1]);
+        return -1;
+    }
+
+    return result;
+}
+
+uint32_t vlapic_update_ppr(struct vlapic *vlapic)
+{
+    uint32_t tpr, isrv, ppr;
+    int isr;
+
+    tpr = (vlapic->task_priority >> 4) & 0xf;      /* we want 7:4 */
+
+    isr = vlapic_find_highest_isr(vlapic);
+    if (isr != -1)
+        isrv = (isr >> 4) & 0xf;   /* ditto */
+    else
+        isrv = 0;
+
+    if (tpr >= isrv)
+        ppr = vlapic->task_priority & 0xff;
+    else
+        ppr = isrv << 4;  /* low 4 bits of PPR have to be cleared */
+
+    vlapic->processor_priority = ppr;
+
+    VMX_DBG_LOG(DBG_LEVEL_VLAPIC_INTERRUPT,
+                "vlapic_update_ppr: vlapic %p ppr %x isr %x isrv %x",
+                vlapic, ppr, isr, isrv);
+
+    return ppr;
+}
+
+/* This only for fixed delivery mode */
+int vlapic_match_dest(struct vlapic *target, struct vlapic *source,
+                      int short_hand, int dest, int dest_mode,
+                      int delivery_mode)
+{
+    int result = 0;
+
+    VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest: "
+                "target %p source %p dest %x dest_mode %x short_hand %x "
+                "delivery_mode %x",
+                target, source, dest, dest_mode, short_hand, delivery_mode);
+
+    switch (short_hand) {
+    case VLAPIC_NO_SHORTHAND:
+        if (!dest_mode) {   /* Physical */
+            result = (target->id == dest);
+        } else {            /* Logical */
+            if (((target->dest_format >> 28) & 0xf) == 0xf) {   /* Flat mode */
+                result = (target->logical_dest >> 24) & dest;
+            } else {
+                if ((delivery_mode == VLAPIC_DELIV_MODE_LPRI) &&
+                   (dest == 0xff)) {
+                    /* What shall we do now? */
+                    printk("Broadcast IPI with lowest priority "
+                           "delivery mode\n");
+                    domain_crash_synchronous();
+                }
+                result = (target->logical_dest == (dest & 0xf)) ?
+                  ((target->logical_dest >> 4) & (dest >> 4)) : 0;
+            }
+        }
+        break;
+
+    case VLAPIC_SHORTHAND_SELF:
+        if (target == source)
+            result = 1;
+        break;
+
+    case VLAPIC_SHORTHAND_INCLUDE_SELF:
+        result = 1;
+        break;
+
+    case VLAPIC_SHORTHAND_EXCLUDE_SELF:
+        if (target != source)
+            result = 1;
+        break;
+
+    default:
+        break;
+    }
+
+    return result;
+}
+
+/*
+ * Add a pending IRQ into lapic.
+ * Return 1 if successfully added and 0 if discarded.
+ */
+int vlapic_accept_irq(struct vlapic *vlapic, int delivery_mode,
+                      int vector, int level, int trig_mode)
+{
+    int        result = 1;
+
+    switch (delivery_mode) {
+    case VLAPIC_DELIV_MODE_FIXED:
+    case VLAPIC_DELIV_MODE_LPRI:
+        /* FIXME add logic for vcpu on reset */
+        if (!vlapic->vcpu || !vlapic_enabled(vlapic))
+            return 0;
+
+        if (test_and_set_bit(vector, &vlapic->irr[0])) {
+            printk("<vlapic_accept_irq>"
+                    "level trig mode repeatedly for vector %d\n", vector);
+            result = 0;
+        } else {
+            if (level) {
+                printk("<vlapic_accept_irq> level trig mode for vector %d\n", 
vector);
+                set_bit(vector, &vlapic->tmr[0]);
+            }
+        }
+        evtchn_set_pending(vlapic->vcpu, iopacket_port(vlapic->domain));
+        break;
+
+    case VLAPIC_DELIV_MODE_RESERVED:
+        printk("Ignore deliver mode 3 in vlapic_accept_irq\n");
+        break;
+
+    case VLAPIC_DELIV_MODE_SMI:
+    case VLAPIC_DELIV_MODE_NMI:
+        /* Fixme */
+        printk("TODO: for guest SMI/NMI\n");
+        break;
+
+    case VLAPIC_DELIV_MODE_INIT:
+        if (!level && trig_mode == 1) {        //Deassert
+            printk("This vmx_vlapic is for P4, no work for De-assert init\n");
+        } else {
+            /* FIXME How to check the situation after vcpu reset? */
+            vlapic->init_sipi_sipi_state = 
VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI;
+            if (vlapic->vcpu) {
+                vcpu_pause(vlapic->vcpu);
+            }
+        }
+        break;
+
+    case VLAPIC_DELIV_MODE_STARTUP:
+        if (vlapic->init_sipi_sipi_state != 
VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI)
+            break;
+        vlapic->init_sipi_sipi_state = VLAPIC_INIT_SIPI_SIPI_STATE_NORM;
+        if (!vlapic->vcpu) {
+            /* XXX Call vmx_bringup_ap here */
+             result = 0;
+        }else{
+            //vmx_vcpu_reset(vlapic->vcpu);
+        }
+        break;
+
+    default:
+        printk("TODO: not support interrup type %x\n", delivery_mode);
+        domain_crash_synchronous();
+        break;
+    }
+
+    return result;
+}
+/*
+    This function is used by both ioapic and local APIC
+    The bitmap is for vcpu_id
+ */
+struct vlapic* apic_round_robin(struct domain *d,
+                                uint8_t dest_mode,
+                                uint8_t vector,
+                                uint32_t bitmap)
+{
+    int next, old;
+    struct vlapic* target = NULL;
+
+    if (dest_mode == 0) { //Physical mode
+        printk("<apic_round_robin> lowest priority for physical mode\n");
+        return NULL;
+    }
+
+    if (!bitmap) {
+        printk("<apic_round_robin> no bit on bitmap\n");
+        return NULL;
+    }
+
+    spin_lock(&d->arch.vmx_platform.round_robin_lock);
+
+    old = next = d->arch.vmx_platform.round_info[vector];
+
+    next++;
+    if (next == MAX_VIRT_CPUS || !d->vcpu[next])
+        next = 0;
+
+    do {
+        /* the vcpu array is arranged according to vcpu_id */
+        if (test_bit(next, &bitmap)) {
+            target = d->vcpu[next]->arch.arch_vmx.vlapic;
+            if (!vlapic_enabled(target)) {
+                printk("warning: targe round robin local apic disabled\n");
+                /* XXX should we domain crash?? Or should we return NULL */
+            }
+            break;
+        }
+
+        next ++;
+        if (next == MAX_VIRT_CPUS || !d->vcpu[next])
+            next = 0;
+    }while(next != old);
+
+    d->arch.vmx_platform.round_info[vector] = next;
+    spin_unlock(&d->arch.vmx_platform.round_robin_lock);
+    return target;
+}
+
+void
+vlapic_EOI_set(struct vlapic *vlapic)
+{
+    int vector = vlapic_find_highest_isr(vlapic);
+
+    /* Not every write EOI will has correpsoning ISR,
+       one example is when Kernel check timer on setup_IO_APIC */
+    if (vector == -1) {
+        return ;
+    }
+
+    vlapic_clear_isr(vlapic, vector);
+    vlapic_update_ppr(vlapic);
+}
+
+int vlapic_check_vector(struct vlapic *vlapic,
+                        unsigned char dm, int vector)
+{
+    if ((dm == VLAPIC_DELIV_MODE_FIXED) && (vector < 16)) {
+        vlapic->err_status |= 0x40;
+        vlapic_accept_irq(vlapic, VLAPIC_DELIV_MODE_FIXED,
+          vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), 0, 0);
+        printk("<vlapic_check_vector>: check fail\n");
+        return 0;
+    }
+    return 1;
+}
+
+
+void vlapic_ipi(struct vlapic *vlapic)
+{
+    unsigned int dest = (vlapic->icr_high >> 24) & 0xff;
+    unsigned int short_hand = (vlapic->icr_low >> 18) & 3;
+    unsigned int trig_mode = (vlapic->icr_low >> 15) & 1;
+    unsigned int level = (vlapic->icr_low >> 14) & 1;
+    unsigned int dest_mode = (vlapic->icr_low >> 11) & 1;
+    unsigned int delivery_mode = (vlapic->icr_low >> 8) & 7;
+    unsigned int vector = (vlapic->icr_low & 0xff);
+
+    struct vlapic *target;
+    struct vcpu *v = NULL;
+    int result = 0;
+    uint32_t lpr_map;
+
+    VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_ipi: "
+                "icr_high %x icr_low %x "
+                "short_hand %x dest %x trig_mode %x level %x "
+                "dest_mode %x delivery_mode %x vector %x",
+                vlapic->icr_high, vlapic->icr_low,
+                short_hand, dest, trig_mode, level, dest_mode,
+                delivery_mode, vector);
+
+    for_each_vcpu ( vlapic->domain, v ) {
+        target = VLAPIC(v);
+        if (vlapic_match_dest(target, vlapic, short_hand,
+                              dest, dest_mode, delivery_mode)) {
+            if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) {
+                set_bit(v->vcpu_id, &lpr_map);
+            }else
+                result = vlapic_accept_irq(target, delivery_mode,
+                  vector, level, trig_mode);
+        }
+    }
+
+    if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) {
+        extern struct vlapic*
+          apic_round_robin(struct domain *d,
+            uint8_t dest_mode, uint8_t vector, uint32_t bitmap);
+
+        v = vlapic->vcpu;
+        target = apic_round_robin(v->domain, dest_mode, vector, lpr_map);
+
+        if (target)
+            vlapic_accept_irq(target, delivery_mode,
+              vector, level, trig_mode);
+    }
+}
+
+void vlapic_begin_timer(struct vlapic *vlapic)
+{
+    s_time_t cur = NOW(), offset;
+
+    offset = vlapic->timer_current *
+      (262144 / get_apic_bus_scale()) * vlapic->timer_divide_counter;
+    vlapic->vlapic_timer.expires = cur + offset;
+
+    set_ac_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires );
+
+    VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_begin_timer: "
+                "bus_scale %x now %08x%08x expire %08x%08x "
+                "offset %08x%08x current %x",
+                get_apic_bus_scale(), (uint32_t)(cur >> 32), (uint32_t)cur,
+                (uint32_t)(vlapic->vlapic_timer.expires >> 32),
+                (uint32_t) vlapic->vlapic_timer.expires,
+                (uint32_t)(offset >> 32), (uint32_t)offset,
+                vlapic->timer_current);
+}
+
+void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
+                         unsigned int len, unsigned int *result)
+{
+    if (len != 4) {
+        VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+                    "local apic read with len=%d (should be 4)", len);
+    }
+
+    *result = 0;
+
+    switch (offset) {
+    case APIC_ID:
+        *result = (vlapic->id) << 24;
+        break;
+
+    case APIC_LVR:
+        *result = vlapic->version;
+        break;
+
+    case APIC_TASKPRI:
+        *result = vlapic->task_priority;
+        break;
+
+    case APIC_ARBPRI:
+        printk("Access local APIC ARBPRI register which is for P6\n");
+        break;
+
+    case APIC_PROCPRI:
+        *result = vlapic->processor_priority;
+        break;
+
+    case APIC_EOI:      /* EOI is write only */
+        break;
+
+    case APIC_LDR:
+        *result = vlapic->logical_dest;
+        break;
+
+    case APIC_DFR:
+        *result = vlapic->dest_format;
+        break;
+
+    case APIC_SPIV:
+        *result = vlapic->spurious_vec;
+        break;
+
+    case APIC_ISR:
+    case 0x110:
+    case 0x120:
+    case 0x130:
+    case 0x140:
+    case 0x150:
+    case 0x160:
+    case 0x170:
+        *result = vlapic->isr[(offset - APIC_ISR) >> 4];
+        break;
+
+    case APIC_TMR:
+    case 0x190:
+    case 0x1a0:
+    case 0x1b0:
+    case 0x1c0:
+    case 0x1d0:
+    case 0x1e0:
+    case 0x1f0:
+        *result = vlapic->tmr[(offset - APIC_TMR) >> 4];
+        break;
+
+    case APIC_IRR:
+    case 0x210:
+    case 0x220:
+    case 0x230:
+    case 0x240:
+    case 0x250:
+    case 0x260:
+    case 0x270:
+        *result = vlapic->irr[(offset - APIC_IRR) >> 4];
+        break;
+
+    case APIC_ESR:
+        if (vlapic->err_write_count)
+            *result = vlapic->err_status;
+        break;
+
+    case APIC_ICR:
+        *result = vlapic->icr_low;
+        break;
+
+    case APIC_ICR2:
+        *result = vlapic->icr_high;
+        break;
+
+    case APIC_LVTT:     /* LVT Timer Reg */
+    case APIC_LVTTHMR:     /* LVT Thermal Monitor */
+    case APIC_LVTPC:     /* LVT Performance Counter */
+    case APIC_LVT0:     /* LVT LINT0 Reg */
+    case APIC_LVT1:     /* LVT Lint1 Reg */
+    case APIC_LVTERR:     /* LVT Error Reg */
+        *result = vlapic->lvt[(offset - APIC_LVTT) >> 4];
+        break;
+
+    case APIC_TMICT:
+        *result = vlapic->timer_initial;
+        break;
+
+    case APIC_TMCCT:         //Timer CCR
+        {
+            uint32_t counter;
+            s_time_t passed, cur = NOW();
+
+            if (cur <= vlapic->timer_current_update) {
+                passed = ~0x0LL - vlapic->timer_current_update + cur;
+                VMX_DBG_LOG(DBG_LEVEL_VLAPIC,"time elapsed");
+            }else
+                passed = cur - vlapic->timer_current_update;
+
+            counter = (passed * get_apic_bus_scale()) / (262144* 
vlapic->timer_divide_counter);
+            if (vlapic->timer_current > counter)
+                *result = vlapic->timer_current - counter;
+            else {
+                if (!vlapic_lvt_timer_period(vlapic))
+                    *result = 0;
+                //FIXME should we add interrupt here?
+                else
+                    //*result = counter % vlapic->timer_initial;
+                    *result = vlapic->timer_initial - (counter - 
vlapic->timer_current);
+            }
+            vlapic->timer_current = *result;
+            vlapic->timer_current_update = NOW();
+
+            VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+                        "initial %x timer current %x "
+                        "update %08x%08x cur %08x%08x offset %d",
+                        vlapic->timer_initial, vlapic->timer_current,
+                        (uint32_t)(vlapic->timer_current_update >> 32),
+                        (uint32_t)vlapic->timer_current_update ,
+                        (uint32_t)(cur >> 32), (uint32_t)cur, counter);
+        }
+        break;
+
+    case APIC_TDCR:
+        *result = vlapic->timer_divconf;
+        break;
+
+    default:
+        printk("Read local APIC address %x not implemented\n",offset);
+        *result = 0;
+        break;
+    }
+}
+
+unsigned long vlapic_read(struct vcpu *v, unsigned long address,
+            unsigned long len)
+{
+    unsigned int alignment;
+    unsigned int tmp;
+    unsigned long result;
+    struct vlapic *vlapic = VLAPIC(v);
+    unsigned int offset = address - vlapic->base_address;
+
+    if ( len != 4) {
+        /* some bugs on kernel cause read this with byte*/
+        printk("Local APIC read with len = %lx, should be 4 instead\n", len);
+    }
+
+    alignment = offset & 0x3;
+
+    vlapic_read_aligned(vlapic, offset & ~0x3, 4, &tmp);
+    switch (len) {
+    case 1:
+        result = *((unsigned char *)&tmp + alignment);
+        break;
+
+    case 2:
+        result = *(unsigned short *)((unsigned char *)&tmp + alignment);
+        break;
+
+    case 4:
+        result = *(unsigned int *)((unsigned char *)&tmp + alignment);
+        break;
+
+    default:
+        printk("Local APIC read with len = %lx, should be 4 instead\n", len);
+        domain_crash_synchronous();
+        break;
+    }
+
+    VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+                "vlapic_read offset %x with length %lx and the result is %lx",
+                offset, len, result);
+    return result;
+}
+
+unsigned long vlapic_write(struct vcpu *v, unsigned long address,
+                  unsigned long len, unsigned long val)
+{
+    struct vlapic *vlapic = VLAPIC(v);
+    unsigned int offset = address - vlapic->base_address;
+
+    if (offset != 0xb0)
+        VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+          "vlapic_write offset %x with length %lx source %lx",
+          offset, len, val);
+
+    /*
+     * According to IA 32 Manual, all resgiters should be accessed with
+     * 32 bits alignment.
+     */
+    if (len != 4) {
+        unsigned int tmp;
+        unsigned char alignment;
+
+        /* Some kernel do will access with byte/word alignment*/
+        printk("Notice: Local APIC write with len = %lx\n",len);
+        alignment = offset & 0x3;
+        tmp = vlapic_read(v, offset & (~0x3), 4);
+        switch (len) {
+        case 1:
+            /* XXX the saddr is a tmp variable from caller, so should be ok
+               But we should still change the following ref to val to 
+               local variable later */
+            val  = (tmp & ~(0xff << alignment)) |
+                        ((val & 0xff) << alignment);
+            break;
+
+        case 2:
+            if (alignment != 0x0 && alignment != 0x2) {
+                printk("alignment error for vlapic with len == 2\n");
+                    domain_crash_synchronous();
+            }
+
+            val = (tmp & ~(0xffff << alignment)) |
+                        ((val & 0xffff)  << alignment);
+            break;
+
+        case 3:
+            /* will it happen? */
+            printk("vlapic_write with len = 3 !!!\n");
+            domain_crash_synchronous();
+            break;
+
+        default:
+            printk("Local APIC write with len = %lx, should be 4 instead\n", 
len);
+            domain_crash_synchronous();
+            break;
+        }
+    }
+
+    offset &= 0xff0;
+
+    switch (offset) {
+    case APIC_ID:   /* Local APIC ID */
+        vlapic->id = ((val) >> 24) & VAPIC_ID_MASK;
+        break;
+
+    case APIC_TASKPRI:
+        vlapic->task_priority = val & 0xff;
+        vlapic_update_ppr(vlapic);
+        break;
+
+    case APIC_EOI:
+        vlapic_EOI_set(vlapic);
+        break;
+
+    case APIC_LDR:
+        vlapic->logical_dest = val & VAPIC_LDR_MASK;
+        break;
+
+    case APIC_DFR:
+        vlapic->dest_format = val ;
+        break;
+
+    case APIC_SPIV:
+        vlapic->spurious_vec = val & 0x1ff;
+        if (!(vlapic->spurious_vec & 0x100)) {
+            int i = 0;
+            for (i=0; i < VLAPIC_LVT_NUM; i++) 
+                vlapic->lvt[i] |= 0x10000;
+            vlapic->status |= VLAPIC_SOFTWARE_DISABLE_MASK;
+        }
+        else
+            vlapic->status &= ~VLAPIC_SOFTWARE_DISABLE_MASK;
+        break;
+
+    case APIC_ESR:
+        vlapic->err_write_count = !vlapic->err_write_count;
+        if (!vlapic->err_write_count)
+            vlapic->err_status = 0;
+        break;
+
+    case APIC_ICR:
+        /* No delay here, so we always clear the pending bit*/
+        vlapic->icr_low = val & ~(1 << 12);
+        vlapic_ipi(vlapic);
+        break;
+
+    case APIC_ICR2:
+        vlapic->icr_high = val & 0xff000000;
+        break;
+
+    case APIC_LVTT: // LVT Timer Reg
+    case APIC_LVTTHMR: // LVT Thermal Monitor
+    case APIC_LVTPC: // LVT Performance Counter
+    case APIC_LVT0: // LVT LINT0 Reg
+    case APIC_LVT1: // LVT Lint1 Reg
+    case APIC_LVTERR: // LVT Error Reg
+        {
+            int vt = (offset - APIC_LVTT) >> 4;
+
+            vlapic->lvt[vt] = val & vlapic_lvt_mask[vt];
+            if (vlapic->status & VLAPIC_SOFTWARE_DISABLE_MASK)
+                vlapic->lvt[vt] |= VLAPIC_LVT_BIT_MASK;
+
+            /* On hardware, when write vector less than 0x20 will error */
+            vlapic_check_vector(vlapic, vlapic_lvt_dm(vlapic->lvt[vt]),
+              vlapic_lvt_vector(vlapic, vt));
+
+            if (!vlapic->vcpu_id && (offset == APIC_LVT0)) {
+                if ((vlapic->lvt[VLAPIC_LVT_LINT0] & VLAPIC_LVT_BIT_DELIMOD)
+                            == 0x700) {
+                    if (!(vlapic->lvt[VLAPIC_LVT_LINT0] & 
VLAPIC_LVT_BIT_MASK)) {
+                        set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+                    }else
+                        clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+                }
+                else
+                    clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+            }
+
+        }
+        break;
+
+    case APIC_TMICT:
+        if (vlapic_timer_active(vlapic))
+            rem_ac_timer(&(vlapic->vlapic_timer));
+
+        vlapic->timer_initial = val;
+        vlapic->timer_current = val;
+        vlapic->timer_current_update = NOW();
+
+        VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+          "timer_init %x timer_current %x timer_current_update %08x%08x",
+          vlapic->timer_initial, vlapic->timer_current, 
(uint32_t)(vlapic->timer_current_update>>32), 
(uint32_t)vlapic->timer_current_update);
+        vlapic_begin_timer(vlapic);
+        break;
+
+    case APIC_TDCR:
+        {
+            //FIXME clean this code
+            unsigned char tmp1,tmp2;
+            tmp1 = (val & 0xf);
+            tmp2 = ((tmp1 & 0x3 )|((tmp1 & 0x8) >>1)) + 1;
+            vlapic->timer_divide_counter = 0x1<<tmp2;
+
+            VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+                        "timer divider is 0x%x",
+                        vlapic->timer_divide_counter);
+        }
+        break;
+
+    default:
+        printk("Local APIC Write to read-only register\n");
+        break;
+    }
+    return 1;
+}
+
+int vlapic_range(struct vcpu *v, unsigned long addr)
+{
+    struct vlapic *vlapic = VLAPIC(v);
+
+    if (vlapic_global_enabled(vlapic) &&
+        (addr >= vlapic->base_address) &&
+        (addr <= (vlapic->base_address + VLOCAL_APIC_MEM_LENGTH)))
+        return 1;
+
+    return 0;
+}
+
+void vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
+{
+    /* When apic disabled */
+    if (!vlapic)
+        return;
+
+    if (vlapic->vcpu_id)
+        value &= ~MSR_IA32_APICBASE_BSP;
+
+    vlapic->apic_base_msr = value;
+    vlapic->base_address = vlapic_get_base_address(vlapic);
+
+    if (!(value & 0x800))
+        set_bit(_VLAPIC_GLOB_DISABLE, &vlapic->status );
+
+    VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+                "apic base msr = 0x%08x%08x,\nbase address = 0x%lx",
+                (uint32_t)(vlapic->apic_base_msr >> 32),
+                (uint32_t)vlapic->apic_base_msr,
+                vlapic->base_address);
+}
+
+static inline int vlapic_get_init_id(struct vcpu *v)
+{
+    return v->vcpu_id;
+}
+
+void vlapic_timer_fn(void *data)
+{
+    struct vlapic *vlapic;
+
+    vlapic = data;
+    if (!vlapic_enabled(vlapic)) return;
+
+    vlapic->timer_current_update = NOW();
+
+    if (vlapic_lvt_timer_enabled(vlapic)) {
+        if (!vlapic_irr_status(vlapic,
+              vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER))) {
+            test_and_set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER),
+              &vlapic->irr[0]);
+        }
+        else
+            vlapic->intr_pending_count[vlapic_lvt_vector(vlapic, 
VLAPIC_LVT_TIMER)]++;
+    }
+
+    vlapic->timer_current_update = NOW();
+    if (vlapic_lvt_timer_period(vlapic)) {
+        s_time_t offset;
+
+        vlapic->timer_current = vlapic->timer_initial;
+        offset = vlapic->timer_current * (262144/get_apic_bus_scale()) * 
vlapic->timer_divide_counter;
+        vlapic->vlapic_timer.expires = NOW() + offset;
+        set_ac_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires);
+    }else {
+        vlapic->timer_current = 0;
+    }
+
+    VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+      "vlapic_timer_fn: now: %08x%08x expire %08x%08x init %x current %x",
+      (uint32_t)(NOW() >> 32),(uint32_t)NOW(),
+      (uint32_t)(vlapic->vlapic_timer.expires >> 32),
+      (uint32_t)vlapic->vlapic_timer.expires,
+      vlapic->timer_initial,vlapic->timer_current);
+}
+
+#if 0
+static int
+vlapic_check_direct_intr(struct vcpu *v, int * mode)
+{
+    struct vlapic *vlapic = VLAPIC(v);
+    int type;
+
+    type = __fls(vlapic->direct_intr.deliver_mode);
+    if (type == -1)
+        return -1;
+
+    *mode = type;
+    return 0;
+}
+#endif
+
+int
+vlapic_accept_pic_intr(struct vcpu *v)
+{
+    struct vlapic *vlapic = VLAPIC(v);
+
+    return vlapic ? test_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status) : 1;
+}
+
+int cpu_get_apic_interrupt(struct vcpu* v, int *mode)
+{
+    struct vlapic *vlapic = VLAPIC(v);
+
+    if (vlapic && vlapic_enabled(vlapic)) {
+        int highest_irr = vlapic_find_highest_irr(vlapic);
+
+        if (highest_irr != -1 && highest_irr >= vlapic->processor_priority) {
+            if (highest_irr < 0x10) {
+                vlapic->err_status |= 0x20;
+                /* XXX What will happen if this vector illegal stil */
+                VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+                  "vmx_intr_assist: illegal vector number %x err_status %x",
+                  highest_irr,  vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR));
+
+                set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), 
&vlapic->irr[0]);
+                highest_irr = vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR);
+            }
+
+            *mode = VLAPIC_DELIV_MODE_FIXED;
+            return highest_irr;
+        }
+    }
+    return -1;
+}
+
+void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode) {
+    struct vlapic  *vlapic = VLAPIC(v);
+
+    if (!vlapic)
+        return;
+
+    switch (deliver_mode) {
+    case VLAPIC_DELIV_MODE_FIXED:
+    case VLAPIC_DELIV_MODE_LPRI:
+        vlapic_set_isr(vlapic, vector);
+        vlapic_clear_irr(vlapic, vector);
+        vlapic_update_ppr(vlapic);
+
+        if (vector == vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER)) {
+            vlapic->intr_pending_count[vector]--;
+            if (vlapic->intr_pending_count[vector] > 0)
+                test_and_set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER),
+                  &vlapic->irr[0]);
+        }
+
+        break;
+        /*XXX deal with these later */
+
+    case VLAPIC_DELIV_MODE_RESERVED:
+        printk("Ignore deliver mode 3 in vlapic_post_injection\n");
+        break;
+
+    case VLAPIC_DELIV_MODE_SMI:
+    case VLAPIC_DELIV_MODE_NMI:
+    case VLAPIC_DELIV_MODE_INIT:
+    case VLAPIC_DELIV_MODE_STARTUP:
+        vlapic->direct_intr.deliver_mode &= ~(1 << deliver_mode);
+        break;
+
+    default:
+        printk("<vlapic_post_injection> error deliver mode\n");
+        break;
+    }
+}
+
+static int vlapic_reset(struct vlapic *vlapic)
+{
+    struct vcpu *v = vlapic->vcpu;
+    int apic_id = v->vcpu_id, i;
+
+    if (!v || !vlapic)
+        return 0;
+
+    memset(vlapic, 0,sizeof(struct vlapic));
+
+    v->arch.arch_vmx.vlapic = vlapic;
+
+    vlapic->domain = v->domain;
+
+    vlapic->id = apic_id;
+
+    vlapic->version = VLAPIC_VERSION;
+
+    vlapic->apic_base_msr = VLAPIC_BASE_MSR_INIT_VALUE;
+
+    if (apic_id == 0)
+        vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP;
+    vlapic->base_address = vlapic_get_base_address(vlapic);
+
+    for (i = 0; i < VLAPIC_LVT_NUM; i++)
+        vlapic->lvt[i] = VLAPIC_LVT_BIT_MASK;
+
+    vlapic->dest_format = 0xffffffffU;
+
+    vlapic->spurious_vec = 0xff;
+
+
+    init_ac_timer(&vlapic->vlapic_timer,
+      vlapic_timer_fn, vlapic, v->processor);
+
+#ifdef VLAPIC_NO_BIOS
+    /*
+     * XXX According to mp sepcific, BIOS will enable LVT0/1,
+     * remove it after BIOS enabled
+     */
+    if (!v->vcpu_id) {
+        vlapic->lvt[VLAPIC_LVT_LINT0] = 0x700;
+        vlapic->lvt[VLAPIC_LVT_LINT1] = 0x500;
+        set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+    }
+#endif
+
+    VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_reset: "
+      "vcpu=%p id=%d vlapic_apic_base_msr=%08x%08x "
+      "vlapic_base_address=%0lx",
+      v, vlapic->id, (uint32_t)(vlapic->apic_base_msr >> 32),
+      (uint32_t)vlapic->apic_base_msr, vlapic->base_address);
+
+    return 1;
+}
+
+int vlapic_init(struct vcpu *v)
+{
+    struct vlapic *vlapic = NULL;
+
+    VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_init %d", v->vcpu_id);
+
+    vlapic = xmalloc_bytes(sizeof(struct vlapic));
+
+    if (!vlapic) {
+        printk("malloc vlapic error for vcpu %x\n", v->vcpu_id);
+        return -ENOMEM;
+    }
+
+    vlapic->vcpu = v;
+
+    vlapic_reset(vlapic);
+
+    return 0;
+}
+
+#endif  /* CONFIG_VMX */
diff -r f23b897930d1 -r cc23d4236b20 xen/include/asm-x86/vmx_vlapic.h
--- /dev/null   Thu Oct 27 17:22:45 2005
+++ b/xen/include/asm-x86/vmx_vlapic.h  Fri Oct 28 08:48:46 2005
@@ -0,0 +1,245 @@
+/*
+ * vmx_vlapic.h: virtualize LAPIC definitions.
+ * Copyright (c) 2004, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#ifndef VMX_VLAPIC_H
+#define VMX_VLAPIC_H
+
+#include <asm/msr.h>
+#include <public/io/ioreq.h>
+
+#if defined(__i386__) || defined(__x86_64__)
+static inline int __fls(uint32_t word)
+{
+    int bit;
+
+    __asm__("bsrl %1,%0"
+      :"=r" (bit)
+      :"rm" (word));
+    return word ? bit : -1;
+}
+#else
+#define __fls(x)    generic_fls(x)
+static __inline__ int generic_fls(uint32_t x)
+{
+    int r = 31;
+
+    if (!x)
+        return -1;
+    if (!(x & 0xffff0000u)) {
+        x <<= 16;
+        r -= 16;
+    }
+    if (!(x & 0xff000000u)) {
+        x <<= 8;
+        r -= 8;
+    }
+    if (!(x & 0xf0000000u)) {
+        x <<= 4;
+        r -= 4;
+    }
+    if (!(x & 0xc0000000u)) {
+        x <<= 2;
+        r -= 2;
+    }
+    if (!(x & 0x80000000u)) {
+        x <<= 1;
+        r -= 1;
+    }
+    return r;
+}
+#endif
+
+static __inline__ int find_highest_bit(uint32_t *data, int length)
+{
+    while(length && !data[--length]);
+    return __fls(data[length]) +  32 * length;
+}
+
+#define VLAPIC(v)                       (v->arch.arch_vmx.vlapic)
+
+#define VAPIC_ID_MASK                   0xff
+#define VAPIC_LDR_MASK                  (VAPIC_ID_MASK << 24)
+#define VLAPIC_VERSION                  0x00050014
+
+#define VLAPIC_BASE_MSR_MASK            0x00000000fffff900ULL
+#define VLAPIC_BASE_MSR_INIT_BASE_ADDR  0xfee00000U
+#define VLAPIC_BASE_MSR_BASE_ADDR_MASK  0xfffff000U
+#define VLAPIC_BASE_MSR_INIT_VALUE      (VLAPIC_BASE_MSR_INIT_BASE_ADDR | \
+                                         MSR_IA32_APICBASE_ENABLE)
+#define VLOCAL_APIC_MEM_LENGTH          (1 << 12)
+
+#define VLAPIC_LVT_TIMER                0
+#define VLAPIC_LVT_THERMAL              1
+#define VLAPIC_LVT_PERFORM              2
+#define VLAPIC_LVT_LINT0                3
+#define VLAPIC_LVT_LINT1                4
+#define VLAPIC_LVT_ERROR                5
+#define VLAPIC_LVT_NUM                  6
+
+#define VLAPIC_LVT_BIT_MASK             (1 << 16)
+#define VLAPIC_LVT_BIT_VECTOR           0xff
+#define VLAPIC_LVT_BIT_DELIMOD          (0x7 << 8)
+#define VLAPIC_LVT_BIT_DELISTATUS       (1 << 12)
+#define VLAPIC_LVT_BIT_POLARITY         (1 << 13)
+#define VLAPIC_LVT_BIT_IRR              (1 << 14)
+#define VLAPIC_LVT_BIT_TRIG             (1 << 15)
+#define VLAPIC_LVT_TIMERMODE            (1 << 17)
+
+#define VLAPIC_DELIV_MODE_FIXED          0x0
+#define VLAPIC_DELIV_MODE_LPRI           0x1
+#define VLAPIC_DELIV_MODE_SMI            0x2
+#define VLAPIC_DELIV_MODE_RESERVED       0x3
+#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_NO_SHORTHAND             0x0
+#define VLAPIC_SHORTHAND_SELF           0x1
+#define VLAPIC_SHORTHAND_INCLUDE_SELF   0x2
+#define VLAPIC_SHORTHAND_EXCLUDE_SELF   0x3
+
+#define vlapic_lvt_timer_enabled(vlapic)    \
+  (!(vlapic->lvt[VLAPIC_LVT_TIMER] & VLAPIC_LVT_BIT_MASK))
+
+#define vlapic_lvt_vector(vlapic, type)   \
+  (vlapic->lvt[type] & VLAPIC_LVT_BIT_VECTOR)
+
+#define vlapic_lvt_dm(value)        ((value >> 8) && 7)
+#define vlapic_lvt_timer_period(vlapic) \
+  (vlapic->lvt[VLAPIC_LVT_TIMER] & VLAPIC_LVT_TIMERMODE)
+
+#define vlapic_isr_status(vlapic,vector)    \
+  test_bit(vector, &vlapic->isr[0])
+
+#define vlapic_irr_status(vlapic,vector)    \
+  test_bit(vector, &vlapic->irr[0])
+
+#define vlapic_set_isr(vlapic,vector) \
+  test_and_set_bit(vector, &vlapic->isr[0])
+
+#define vlapic_set_irr(vlapic,vector)      \
+  test_and_set_bit(vector, &vlapic->irr[0])
+
+#define vlapic_clear_irr(vlapic,vector)      \
+  clear_bit(vector, &vlapic->irr[0])
+#define vlapic_clear_isr(vlapic,vector)     \
+  clear_bit(vector, &vlapic->isr[0])
+
+#define vlapic_enabled(vlapic)               \
+  (!(vlapic->status &                           \
+     (VLAPIC_GLOB_DISABLE_MASK | VLAPIC_SOFTWARE_DISABLE_MASK)))
+
+#define vlapic_global_enabled(vlapic)               \
+  !(test_bit(_VLAPIC_GLOB_DISABLE, &(vlapic)->status))
+
+typedef struct direct_intr_info {
+    int deliver_mode;
+    int source[6];
+} direct_intr_info_t;
+
+#define VLAPIC_INIT_SIPI_SIPI_STATE_NORM          0
+#define VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI     1
+
+struct vlapic
+{
+    //FIXME check what would be 64 bit on EM64T
+    uint32_t           version;
+#define _VLAPIC_GLOB_DISABLE            0x0
+#define VLAPIC_GLOB_DISABLE_MASK        0x1
+#define VLAPIC_SOFTWARE_DISABLE_MASK    0x2
+#define _VLAPIC_BSP_ACCEPT_PIC          0x3
+    uint32_t           status;
+    uint32_t           id;
+    uint32_t           vcpu_id;
+    unsigned long      base_address;
+    uint32_t           isr[8];
+    uint32_t           irr[INTR_LEN_32];
+    uint32_t           tmr[INTR_LEN_32];
+    uint32_t           task_priority;
+    uint32_t           processor_priority;
+    uint32_t           logical_dest;
+    uint32_t           dest_format;
+    uint32_t           spurious_vec;
+    uint32_t           lvt[6];
+    uint32_t           timer_initial;
+    uint32_t           timer_current;
+    uint32_t           timer_divconf;
+    uint32_t           timer_divide_counter;
+    struct ac_timer    vlapic_timer;
+    int                intr_pending_count[MAX_VECTOR];
+    s_time_t           timer_current_update;
+    uint32_t           icr_high;
+    uint32_t           icr_low;
+    direct_intr_info_t direct_intr;
+    uint32_t           err_status;
+    unsigned long      init_ticks;
+    uint32_t           err_write_count;
+    uint64_t           apic_base_msr;
+    uint32_t           init_sipi_sipi_state;
+    struct vcpu        *vcpu;
+    struct domain      *domain;
+};
+
+static inline int  vlapic_timer_active(struct vlapic *vlapic)
+{
+    return  active_ac_timer(&(vlapic->vlapic_timer));
+}
+
+int vlapic_find_highest_irr(struct vlapic *vlapic);
+
+int vlapic_find_highest_isr(struct vlapic *vlapic);
+
+static uint32_t inline vlapic_get_base_address(struct vlapic *vlapic)
+{
+    return (vlapic->apic_base_msr & VLAPIC_BASE_MSR_BASE_ADDR_MASK);
+}
+
+void vlapic_post_injection(struct vcpu* v, int vector, int deliver_mode);
+
+int cpu_get_apic_interrupt(struct vcpu* v, int *mode);
+
+extern uint32_t vlapic_update_ppr(struct vlapic *vlapic);
+
+int vlapic_update(struct vcpu *v);
+
+extern int vlapic_init(struct vcpu *vc);
+
+extern void vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
+
+int vlapic_range(struct vcpu *v, unsigned long addr);
+
+unsigned long vlapic_write(struct vcpu *v, unsigned long address,
+                           unsigned long len, unsigned long val);
+
+unsigned long vlapic_read(struct vcpu *v, unsigned long address,
+                          unsigned long len);
+
+int vlapic_accept_pic_intr(struct vcpu *v);
+
+struct vlapic* apic_round_robin(struct domain *d,
+                                uint8_t dest_mode,
+                                uint8_t vector,
+                                uint32_t bitmap);
+
+int vmx_apic_support(struct domain *d);
+
+#endif /* VMX_VLAPIC_H */

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


 


Rackspace

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