WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] This patch add virtual IOAPIC support for VMX guest.
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 07 Nov 2005 19:54:07 +0000
Delivery-date: Mon, 07 Nov 2005 19:54:50 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] This patch add virtual IOAPIC support for VMX guest., Xen patchbot -unstable <=