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

[Xen-changelog] This patch add virtual IOAPIC support for VMX guest.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 9bb7a75f120fcd7db6b9e9dd1bc3700701168ada
# Parent  781b6dd73e4c66ab0f05cd03a045b47e429510cc
This patch add virtual IOAPIC support for VMX guest.

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

diff -r 781b6dd73e4c -r 9bb7a75f120f xen/arch/x86/dm/i8259.c
--- a/xen/arch/x86/dm/i8259.c   Mon Nov  7 15:35:46 2005
+++ b/xen/arch/x86/dm/i8259.c   Mon Nov  7 15:36:27 2005
@@ -33,6 +33,7 @@
 #include <asm/vmx.h>
 #include <public/io/vmx_vpic.h>
 #include <asm/current.h>
+#include <asm/vmx_vioapic.h>
 #include <asm/vmx_vlapic.h>
 
 /* set irq level. If an edge is detected, then the IRR is set to 1 */
@@ -124,6 +125,7 @@
 {
     struct vmx_virpic *s = opaque;
 
+    vmx_vioapic_set_irq(current->domain, irq, level);
     pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
     /* used for IOAPIC irqs */
     if (s->alt_irq_func)
@@ -135,6 +137,7 @@
 {
     s->pics[1].irr |= (uint8_t)(irqs >> 8);
     s->pics[0].irr |= (uint8_t) irqs;
+    vmx_vioapic_do_irqs(current->domain, irqs);
     pic_update_irq(s);
 }
 
@@ -142,6 +145,7 @@
 {
     s->pics[1].irr &= ~(uint8_t)(irqs >> 8);
     s->pics[0].irr &= ~(uint8_t) irqs;
+    vmx_vioapic_do_irqs_clear(current->domain, irqs);
     pic_update_irq(s);
 }
 
@@ -521,7 +525,13 @@
 
 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;
+    int pit_vec;
+
+    if (type == VLAPIC_DELIV_MODE_EXT)
+        pit_vec = v->domain->arch.vmx_platform.vmx_pic.pics[0].irq_base;
+    else
+        pit_vec =
+          
v->domain->arch.vmx_platform.vmx_vioapic.redirtbl[0].RedirForm.vector;
 
     return (irq == pit_vec);
 }
diff -r 781b6dd73e4c -r 9bb7a75f120f xen/arch/x86/vmx_intercept.c
--- a/xen/arch/x86/vmx_intercept.c      Mon Nov  7 15:35:46 2005
+++ b/xen/arch/x86/vmx_intercept.c      Mon Nov  7 15:36:27 2005
@@ -34,12 +34,14 @@
 #ifdef CONFIG_VMX
 
 extern struct vmx_mmio_handler vlapic_mmio_handler;
-
-#define VMX_MMIO_HANDLER_NR 1
+extern struct vmx_mmio_handler vioapic_mmio_handler;
+
+#define VMX_MMIO_HANDLER_NR 2
 
 struct vmx_mmio_handler *vmx_mmio_handlers[VMX_MMIO_HANDLER_NR] =
 {
-    &vlapic_mmio_handler
+    &vlapic_mmio_handler,
+    &vioapic_mmio_handler
 };
 
 static inline void vmx_mmio_access(struct vcpu *v,
diff -r 781b6dd73e4c -r 9bb7a75f120f xen/arch/x86/vmx_vlapic.c
--- a/xen/arch/x86/vmx_vlapic.c Mon Nov  7 15:35:46 2005
+++ b/xen/arch/x86/vmx_vlapic.c Mon Nov  7 15:36:27 2005
@@ -307,6 +307,11 @@
 
     vlapic_clear_isr(vlapic, vector);
     vlapic_update_ppr(vlapic);
+
+    if (test_and_clear_bit(vector, &vlapic->tmr[0])) {
+        extern void ioapic_update_EOI(struct domain *d, int vector);
+        ioapic_update_EOI(vlapic->domain, vector);
+    }
 }
 
 int vlapic_check_vector(struct vlapic *vlapic,
@@ -969,6 +974,8 @@
 
     vlapic->spurious_vec = 0xff;
 
+    vmx_vioapic_add_lapic(vlapic, v);
+
     init_ac_timer(&vlapic->vlapic_timer,
                   vlapic_timer_fn, vlapic, v->processor);
 
diff -r 781b6dd73e4c -r 9bb7a75f120f xen/arch/x86/vmx_vmcs.c
--- a/xen/arch/x86/vmx_vmcs.c   Mon Nov  7 15:35:46 2005
+++ b/xen/arch/x86/vmx_vmcs.c   Mon Nov  7 15:36:27 2005
@@ -28,6 +28,7 @@
 #include <asm/processor.h>
 #include <asm/msr.h>
 #include <asm/vmx.h>
+#include <asm/vmx_vioapic.h>
 #include <asm/flushtlb.h>
 #include <xen/event.h>
 #include <xen/kernel.h>
@@ -255,6 +256,7 @@
 
     if ( vmx_apic_support(d) ) {
         spin_lock_init(&d->arch.vmx_platform.round_robin_lock);
+        vmx_vioapic_init(d);
     }
 }
 
diff -r 781b6dd73e4c -r 9bb7a75f120f xen/include/asm-x86/vmx_platform.h
--- a/xen/include/asm-x86/vmx_platform.h        Mon Nov  7 15:35:46 2005
+++ b/xen/include/asm-x86/vmx_platform.h        Mon Nov  7 15:36:27 2005
@@ -24,6 +24,7 @@
 #include <asm/e820.h>
 #include <asm/vmx_virpit.h>
 #include <asm/vmx_intercept.h>
+#include <asm/vmx_vioapic.h>
 #include <public/io/vmx_vpic.h>
 
 #define MAX_OPERAND_NUM 2
@@ -85,6 +86,7 @@
     struct vmx_virpit      vmx_pit;
     struct vmx_io_handler  vmx_io_handler;
     struct vmx_virpic      vmx_pic;
+    struct vmx_vioapic      vmx_vioapic;
     unsigned char          round_info[256];
     spinlock_t             round_robin_lock;
     int                    interrupt_request;
diff -r 781b6dd73e4c -r 9bb7a75f120f xen/include/asm-x86/vmx_vmcs.h
--- a/xen/include/asm-x86/vmx_vmcs.h    Mon Nov  7 15:35:46 2005
+++ b/xen/include/asm-x86/vmx_vmcs.h    Mon Nov  7 15:36:27 2005
@@ -284,7 +284,8 @@
 #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)
+#define DBG_LEVEL_VLAPIC_INTERRUPT  (1 << 8)
+#define DBG_LEVEL_IOAPIC            (1 << 9)
 
 extern unsigned int opt_vmx_debug_level;
 #define VMX_DBG_LOG(level, _f, _a...)           \
diff -r 781b6dd73e4c -r 9bb7a75f120f xen/arch/x86/dm/vmx_vioapic.c
--- /dev/null   Mon Nov  7 15:35:46 2005
+++ b/xen/arch/x86/dm/vmx_vioapic.c     Mon Nov  7 15:36:27 2005
@@ -0,0 +1,608 @@
+/*
+*  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
+*/
+
+/*
+*  Yunhong Jiang <yunhong.jiang@xxxxxxxxx>
+*  Ported to xen by using virtual IRQ line.
+*/
+
+#include <asm/vmx_vioapic.h>
+#include <asm/vmx_platform.h>
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/mm.h>
+#include <xen/xmalloc.h>
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/sched.h>
+#include <public/io/ioreq.h>
+#include <asm/vmx.h>
+#include <public/io/vmx_vpic.h>
+#include <asm/current.h>
+
+static void ioapic_enable(vmx_vioapic_t *s, uint8_t enable)
+{
+    if (enable)
+        s->flags |= IOAPIC_ENABLE_FLAG;
+    else
+        s->flags &= ~IOAPIC_ENABLE_FLAG;
+}
+
+static void ioapic_dump_redir(vmx_vioapic_t *s, uint8_t entry)
+{
+    ASSERT(s);
+
+    RedirStatus redir = s->redirtbl[entry];
+
+    VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_dump_redir "
+      "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);
+}
+
+#ifdef VMX_DOMAIN_SAVE_RESTORE
+void ioapic_save(QEMUFile* f, void* opaque)
+{
+    printk("no implementation for ioapic_save\n");
+}
+
+int ioapic_load(QEMUFile* f, void* opaque, int version_id)
+{
+    printk("no implementation for ioapic_load\n");
+    return 0;
+}
+#endif
+
+static unsigned long vmx_vioapic_read_indirect(struct vmx_vioapic *s,
+                                              unsigned long addr,
+                                              unsigned long length)
+{
+    unsigned long result = 0;
+
+    ASSERT(s);
+
+    switch (s->ioregsel) {
+    case IOAPIC_REG_VERSION:
+        result = ((((IOAPIC_NUM_PINS-1) & 0xff) << 16)
+                  | (IOAPIC_VERSION_ID & 0x0f));
+        break;
+
+#ifndef __ia64__
+    case IOAPIC_REG_APIC_ID:
+        result = ((s->id & 0xf) << 24);
+        break;
+
+    case IOAPIC_REG_ARB_ID:
+        /* XXX how arb_id used on p4? */
+        result = ((s->id & 0xf) << 24);
+        break;
+#endif
+
+    default:
+        {
+            uint32_t redir_index = 0;
+            uint64_t redir_content = 0;
+
+            redir_index = (s->ioregsel - 0x10) >> 1;
+
+            if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS) {
+                redir_content = s->redirtbl[redir_index].value;
+
+                result = (s->ioregsel & 0x1)?
+                           (redir_content >> 32) & 0xffffffff :
+                           redir_content & 0xffffffff;
+            } else {
+                printk("upic_mem_readl:undefined ioregsel %x\n",
+                        s->ioregsel);
+                domain_crash_synchronous();
+            }
+            break;
+        }
+    } /* switch */
+
+    return result;
+}
+
+static unsigned long vmx_vioapic_read(struct vcpu *v,
+                                     unsigned long addr,
+                                     unsigned long length)
+{
+    struct vmx_vioapic *s = &(v->domain->arch.vmx_platform.vmx_vioapic);
+    uint32_t    result = 0;
+
+    VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "vmx_vioapic_read addr %lx\n", addr);
+
+    ASSERT(s);
+
+    addr &= 0xff;
+
+    switch (addr) {
+    case IOAPIC_REG_SELECT:
+        result = s->ioregsel;
+        break;
+
+    case IOAPIC_REG_WINDOW:
+        result = vmx_vioapic_read_indirect(s, addr, length);
+        break;
+
+    default:
+          break;
+    }
+
+    return result;
+}
+
+static void vmx_vioapic_write_indirect(struct vmx_vioapic *s,
+                                      unsigned long addr,
+                                      unsigned long length,
+                                      unsigned long val)
+{
+    switch (s->ioregsel) {
+    case IOAPIC_REG_VERSION:
+        printk("vmx_vioapic_write_indirect: version register read only\n");
+        break;
+
+#ifndef __ia64__
+    case IOAPIC_REG_APIC_ID:
+        s->id = (val >> 24) & 0xf;
+        break;
+
+    case IOAPIC_REG_ARB_ID:
+        s->arb_id = val;
+        break;
+#endif
+
+    default:
+        {
+            uint32_t redir_index = 0;
+
+            VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "vmx_vioapic_write_indirect "
+              "change redir index %x val %lx\n",
+              redir_index, val);
+
+            redir_index = (s->ioregsel - 0x10) >> 1;
+
+            if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS) {
+                uint64_t redir_content;
+
+                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  {
+                printk("vmx_vioapic_write_indirect "
+                  "error register %x\n", s->ioregsel);
+            }
+            break;
+        }
+    } /* switch */
+}
+
+static void vmx_vioapic_write(struct vcpu *v,
+                             unsigned long addr,
+                             unsigned long length,
+                             unsigned long val)
+{
+    vmx_vioapic_t *s = &(v->domain->arch.vmx_platform.vmx_vioapic);
+
+    ASSERT(s);
+
+    addr &= 0xff;
+
+    switch (addr) {
+    case IOAPIC_REG_SELECT:
+        s->ioregsel = val;
+        break;
+
+    case IOAPIC_REG_WINDOW:
+        vmx_vioapic_write_indirect(s, addr, length, val);
+        break;
+
+#ifdef __ia64__
+    case IOAPIC_REG_EOI:
+        ioapic_update_EOI(v->domain, val);
+        break;
+#endif
+
+    default:
+        break;
+    }
+}
+
+static int vmx_vioapic_range(struct vcpu *v, unsigned long addr)
+{
+    vmx_vioapic_t *s = &(v->domain->arch.vmx_platform.vmx_vioapic);
+
+    if ((s->flags & IOAPIC_ENABLE_FLAG) &&
+        (addr >= s->base_address &&
+        (addr <= s->base_address + IOAPIC_MEM_LENGTH)))
+        return 1;
+    else
+        return 0;
+}
+
+struct vmx_mmio_handler vioapic_mmio_handler = {
+    .check_handler = vmx_vioapic_range,
+    .read_handler = vmx_vioapic_read,
+    .write_handler = vmx_vioapic_write
+};
+
+static void vmx_vioapic_reset(vmx_vioapic_t *s)
+{
+    int i;
+
+    memset(s, 0, sizeof(vmx_vioapic_t));
+
+    for (i = 0; i < IOAPIC_NUM_PINS; i++)
+        s->redirtbl[i].RedirForm.mask = 0x1;
+}
+
+static void ioapic_update_config(vmx_vioapic_t *s,
+                                 unsigned long address,
+                                 uint8_t enable)
+{
+    ASSERT(s);
+
+    ioapic_enable(s, enable);
+
+    if (address != s->base_address)
+        s->base_address = address;
+}
+
+static int ioapic_inj_irq(vmx_vioapic_t *s,
+                          struct vlapic * target,
+                          uint8_t vector,
+                          uint8_t trig_mode,
+                          uint8_t delivery_mode)
+{
+    int result = 0;
+
+    ASSERT(s && target);
+
+    VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_inj_irq "
+      "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:
+        if (test_and_set_bit(vector, &target->irr[0]) && trig_mode == 1) {
+            /* the level interrupt should not happen before it is cleard */
+            printk("<ioapic_inj_irq> level interrupt happen before cleard\n");
+        }
+        if (trig_mode)
+            test_and_set_bit(vector, &target->tmr[0]);
+        result = 1;
+        break;
+    default:
+        printk("<ioapic_inj_irq> error delivery mode %d\n",
+                delivery_mode);
+        break;
+   }
+
+   return result;
+}
+
+#ifndef __ia64__
+static int ioapic_match_logical_addr(vmx_vioapic_t *s, int number, uint8_t 
dest)
+{
+    int result = 0;
+
+    ASSERT(s && s->lapic_info[number]);
+
+    VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_match_logical_addr "
+      "number %i dest %x\n",
+      number, dest);
+
+    switch (((s->lapic_info[number]->dest_format >> 28) & 0xf)) {
+    case 0xf:
+        result =
+          (dest & ((s->lapic_info[number]->logical_dest >> 24) & 0xff)) != 0;
+        break;
+    case 0x0:
+        /* Should we support flat cluster mode ?*/
+        if ( ((s->lapic_info[number]->logical_dest >> 28)
+               == ((dest >> 0x4) & 0xf)) &&
+             (((s->lapic_info[number]->logical_dest >> 24) & 0xf)
+               & (dest  & 0xf)) )
+            result = 1;
+        break;
+    default:
+        printk("error DFR value for %x local apic\n", number);
+        break;
+    }
+
+    return result;
+}
+#else
+extern int ioapic_match_logical_addr(vmx_vioapic_t *s, int number, uint8_t 
dest);
+#endif
+
+static uint32_t ioapic_get_delivery_bitmask(vmx_vioapic_t *s,
+                                            uint16_t dest,
+                                            uint8_t dest_mode,
+                                            uint8_t vector,
+                                            uint8_t delivery_mode)
+{
+    uint32_t mask = 0;
+    int i;
+
+    VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "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);
+
+    ASSERT(s);
+
+    if (dest_mode == 0) { /* Physical mode */
+        for (i = 0; i < s->lapic_count; i++) {
+            if (s->lapic_info[i]->id == dest) {
+                mask = 1 << i;
+                break;
+            }
+        }
+    } else {
+        /* logical destination. call match_logical_addr for each APIC. */
+        if (dest != 0) {
+            for (i=0; i< s->lapic_count; i++) {
+                if ( s->lapic_info[i] &&
+                     ioapic_match_logical_addr(s, i, dest) ) {
+                    mask |= (1<<i);
+                }
+            }
+        }
+    }
+
+    VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask "
+      "mask %x\n", mask);
+
+    return mask;
+}
+
+static void ioapic_deliver(vmx_vioapic_t *s, int irqno)
+{
+    uint16_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;
+    uint32_t deliver_bitmask;
+
+    VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "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);
+
+    if (!deliver_bitmask) {
+        VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver "
+          "no target on destination\n");
+
+        return;
+    }
+
+    switch (delivery_mode) {
+    case VLAPIC_DELIV_MODE_LPRI:
+    {
+        struct vlapic* target;
+
+        target = apic_round_robin(
+                s->domain, dest_mode, vector, deliver_bitmask);
+        ioapic_inj_irq(s, target, vector, trig_mode, delivery_mode);
+        break;
+    }
+
+    case VLAPIC_DELIV_MODE_FIXED:
+    case VLAPIC_DELIV_MODE_EXT:
+    {
+        uint8_t bit;
+        for (bit = 0; bit < s->lapic_count; bit++) {
+            if (deliver_bitmask & (1 << bit)) {
+                if (s->lapic_info[bit]) {
+                    ioapic_inj_irq(s, s->lapic_info[bit],
+                                vector, trig_mode, delivery_mode);
+                }
+            }
+        }
+        break;
+    }
+
+    case VLAPIC_DELIV_MODE_SMI:
+    case VLAPIC_DELIV_MODE_NMI:
+    case VLAPIC_DELIV_MODE_INIT:
+    case VLAPIC_DELIV_MODE_STARTUP:
+    default:
+        printk("Not support delivey mode %d\n", delivery_mode);
+        break;
+    }
+}
+
+static int ioapic_get_highest_irq(vmx_vioapic_t *s)
+{
+    uint32_t irqs;
+
+    ASSERT(s);
+
+    irqs = s->irr & ~s->isr;
+    return __fls(irqs);
+}
+
+
+static void service_ioapic(vmx_vioapic_t *s)
+{
+    int irqno;
+
+    while ((irqno = ioapic_get_highest_irq(s)) != -1) {
+
+        VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "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);
+        }
+
+        s->irr &= ~(1 << irqno);
+    }
+}
+
+void vmx_vioapic_do_irqs(struct domain *d, uint16_t irqs)
+{
+    vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic);
+
+    if (!vmx_apic_support(d))
+        return;
+
+    s->irr |= irqs;
+    service_ioapic(s);
+}
+
+void vmx_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs)
+{
+    vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic);
+
+    if (!vmx_apic_support(d))
+        return;
+
+    s->irr &= ~irqs;
+    service_ioapic(s);
+}
+
+void vmx_vioapic_set_irq(struct domain *d, int irq, int level)
+{
+    vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic);
+
+    if (!vmx_apic_support(d))
+        return ;
+
+    VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_set_irq "
+      "irq %x level %x\n", irq, level);
+
+    if (irq < 0 || irq >= IOAPIC_NUM_PINS) {
+        printk("ioapic_set_irq irq %x is illegal\n", irq);
+        domain_crash_synchronous();
+    }
+
+    if (!IOAPICEnabled(s) || s->redirtbl[irq].RedirForm.mask)
+        return;
+
+    ioapic_dump_redir(s, irq);
+
+    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;
+        }
+    }
+
+    service_ioapic(s);
+}
+
+/* XXX If level interrupt, use vector->irq table for performance */
+static int get_redir_num(vmx_vioapic_t *s, int vector)
+{
+    int i = 0;
+
+    ASSERT(s);
+
+    for(i = 0; i < IOAPIC_NUM_PINS - 1; i++) {
+        if (s->redirtbl[i].RedirForm.vector == vector)
+            return i;
+    }
+
+    return -1;
+}
+
+void ioapic_update_EOI(struct domain *d, int vector)
+{
+    vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic);
+    int redir_num;
+
+    if ((redir_num = get_redir_num(s, vector)) == -1) {
+        printk("Can't find redir item for %d EOI \n", vector);
+        return;
+    }
+
+    if (!test_and_clear_bit(redir_num, &s->isr)) {
+        printk("redir %d not set for %d  EOI\n", redir_num, vector);
+        return;
+    }
+}
+
+int vmx_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v)
+{
+    vmx_vioapic_t *s = &(v->domain->arch.vmx_platform.vmx_vioapic);
+
+    if (v->vcpu_id != s->lapic_count) {
+        printk("vmx_vioapic_add_lapic "
+           "cpu_id not match vcpu_id %x lapic_count %x\n",
+           v->vcpu_id, s->lapic_count);
+        domain_crash_synchronous();
+    }
+
+    s->lapic_info[s->lapic_count ++] = vlapic;
+
+    return s->lapic_count;
+}
+
+vmx_vioapic_t * vmx_vioapic_init(struct domain *d)
+{
+    int i = 0;
+    vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic);
+
+    VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "vmx_vioapic_init\n");
+
+    vmx_vioapic_reset(s);
+
+    s->domain = d;
+
+    for (i = 0; i < MAX_LAPIC_NUM; i++)
+        s->lapic_info[i] = NULL;
+
+    /* Remove after GFW ready */
+    ioapic_update_config(s, IOAPIC_DEFAULT_BASE_ADDRESS, 1);
+
+    return s;
+}
diff -r 781b6dd73e4c -r 9bb7a75f120f xen/include/asm-x86/vmx_vioapic.h
--- /dev/null   Mon Nov  7 15:35:46 2005
+++ b/xen/include/asm-x86/vmx_vioapic.h Mon Nov  7 15:36:27 2005
@@ -0,0 +1,136 @@
+/*
+ *
+ *  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 <xen/config.h>
+#include <xen/types.h>
+#include <xen/smp.h>
+
+#ifndef __ia64__
+#define IOAPIC_VERSION_ID 0x11
+#else
+#define IOAPIC_VERSION_ID 0x21
+#endif
+
+#define IOAPIC_NUM_PINS 24
+#define MAX_LAPIC_NUM   32
+
+#define IOAPIC_LEVEL_TRIGGER 1
+
+#define IOAPIC_DEFAULT_BASE_ADDRESS  0xfec00000
+#define IOAPIC_MEM_LENGTH            0x100
+
+#define IOAPIC_ENABLE_MASK  0x0
+#define IOAPIC_ENABLE_FLAG  (1 << IOAPIC_ENABLE_MASK)
+#define IOAPICEnabled(s)    (s->flags & IOAPIC_ENABLE_FLAG)
+
+#define IOAPIC_REG_SELECT  0x0
+#define IOAPIC_REG_WINDOW  0x10
+
+#ifdef __ia64__
+#define IOAPIC_REG_ASSERTION    0x20
+#define IOAPIC_REG_EOI          0x40
+#endif
+
+#ifndef __ia64__
+#define IOAPIC_REG_APIC_ID 0x0
+#define IOAPIC_REG_ARB_ID  0x2
+#endif
+
+#define IOAPIC_REG_VERSION 0x1
+
+#ifdef __ia64__
+typedef union RedirStatus
+{
+    uint64_t value;
+    struct {
+        uint16_t dest_id;
+        uint8_t reserved[3];
+        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
+
+#define IOAPIC_MEM_LENGTH    0x100
+#define IOAPIC_ENABLE_MASK   0x0
+#define IOAPIC_ENABLE_FLAG   (1 << IOAPIC_ENABLE_MASK)
+#define MAX_LAPIC_NUM        32
+
+typedef struct vmx_vioapic {
+    uint32_t ioregsel;
+    uint32_t irr;
+    uint32_t isr;           /* This is used for level trigger */
+    uint32_t flags;
+    uint32_t lapic_count;
+    uint32_t id;
+    uint32_t arb_id;
+    unsigned long base_address;
+    RedirStatus redirtbl[IOAPIC_NUM_PINS];
+    struct vlapic *lapic_info[MAX_LAPIC_NUM];
+    struct domain *domain;
+} vmx_vioapic_t;
+
+vmx_vioapic_t *vmx_vioapic_init(struct domain *d);
+
+void vmx_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs);
+void vmx_vioapic_do_irqs(struct domain *d, uint16_t irqs);
+void vmx_vioapic_set_irq(struct domain *d, int irq, int level);
+
+int vmx_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v);
+
+#ifdef VMX_DOMAIN_SAVE_RESTORE
+void ioapic_save(QEMUFile* f, void* opaque);
+int ioapic_load(QEMUFile* f, void* opaque, int version_id);
+#endif
+
+#endif

_______________________________________________
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®.