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

[Xen-changelog] This is a follow up of PIC device model by Xiaofeng and me to move to



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 2d5b92e7c79a714640397b6c7d797a56aa230f8b
# Parent  8eaaa622db81393ef0eae497090c34c04adf4212
This is a follow up of PIC device model by Xiaofeng and me to move to
hypervisor using virtual weired interrupt line.  With this patch the
performance of CPU2K improves 7%, kernel kuild improves 14% and
cyclesoak improves 12%. It is quite amazing!

Signed-off-by: Xiaofeng Ling <xiaofeng.ling@xxxxxxxxx>
Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx>

diff -r 8eaaa622db81 -r 2d5b92e7c79a tools/ioemu/hw/i8254.c
--- a/tools/ioemu/hw/i8254.c    Fri Oct 21 17:19:38 2005
+++ b/tools/ioemu/hw/i8254.c    Fri Oct 21 17:29:26 2005
@@ -222,9 +222,7 @@
     int irq, i;
     PITChannelState *s;
 
-    /* Assumes PIT is wired to IRQ0 and -1 is uninitialized irq base */
-    if ((irq = pic_irq2vec(0)) == -1)
-        return;
+    irq = 0;
 
     for(i = 0; i < 3; i++) {
         if (pit_state.channels[i].vmx_channel)
diff -r 8eaaa622db81 -r 2d5b92e7c79a tools/ioemu/target-i386-dm/Makefile
--- a/tools/ioemu/target-i386-dm/Makefile       Fri Oct 21 17:19:38 2005
+++ b/tools/ioemu/target-i386-dm/Makefile       Fri Oct 21 17:29:26 2005
@@ -271,7 +271,7 @@
 
 # Hardware support
 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o dma.o
-VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o port-e9.o
+VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259_stub.o i8254.o pc.o port-e9.o
 VL_OBJS+= cirrus_vga.o pcnet.o
 
 ifeq ($(TARGET_ARCH), ppc)
diff -r 8eaaa622db81 -r 2d5b92e7c79a tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c      Fri Oct 21 17:19:38 2005
+++ b/tools/ioemu/target-i386-dm/helper2.c      Fri Oct 21 17:29:26 2005
@@ -404,20 +404,6 @@
 }
 
 void
-do_interrupt(CPUState *env, int vector)
-{
-       unsigned long *intr;
-
-       // Send a message on the event channel. Add the vector to the shared mem
-       // page.
-       intr = (unsigned long *) &(shared_page->sp_global.pic_intr[0]);
-       atomic_set_bit(vector, intr);
-        if (loglevel & CPU_LOG_INT)
-                fprintf(logfile, "injecting vector: %x\n", vector);
-       env->send_event = 1;
-}
-
-void
 destroy_vmx_domain(void)
 {
     extern FILE* logfile;
@@ -429,7 +415,6 @@
 
 int main_loop(void)
 {
-       int vector;
        fd_set rfds;
        struct timeval tv;
        extern CPUState *global_env;
@@ -476,11 +461,6 @@
                ioapic_update_EOI();
 #endif
                cpu_timer_handler(env);
-               if (env->interrupt_request & CPU_INTERRUPT_HARD) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-                       vector = cpu_get_pic_interrupt(env); 
-                       do_interrupt(env, vector);
-               }
 #ifdef APIC_SUPPORT
                if (ioapic_has_intr())
                     do_ioapic();
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile     Fri Oct 21 17:19:38 2005
+++ b/xen/arch/x86/Makefile     Fri Oct 21 17:29:26 2005
@@ -4,6 +4,7 @@
 OBJS += $(patsubst %.S,%.o,$(wildcard $(TARGET_SUBARCH)/*.S))
 OBJS += $(patsubst %.c,%.o,$(wildcard $(TARGET_SUBARCH)/*.c))
 OBJS += $(patsubst %.c,%.o,$(wildcard acpi/*.c))
+OBJS += $(patsubst %.c,%.o,$(wildcard dm/*.c))
 OBJS += $(patsubst %.c,%.o,$(wildcard mtrr/*.c))
 OBJS += $(patsubst %.c,%.o,$(wildcard genapic/*.c))
 OBJS += $(patsubst %.c,%.o,$(wildcard cpu/*.c))
@@ -66,6 +67,7 @@
        rm -f x86_64/*.o x86_64/*~ x86_64/core
        rm -f mtrr/*.o mtrr/*~ mtrr/core
        rm -f acpi/*.o acpi/*~ acpi/core
+       rm -f dm/*.o dm/*~ dm/core
        rm -f genapic/*.o genapic/*~ genapic/core
        rm -f cpu/*.o cpu/*~ cpu/core
 
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Fri Oct 21 17:19:38 2005
+++ b/xen/arch/x86/domain.c     Fri Oct 21 17:29:26 2005
@@ -39,7 +39,6 @@
 #include <asm/msr.h>
 #include <asm/physdev.h>
 #include <xen/kernel.h>
-#include <public/io/ioreq.h>
 #include <xen/multicall.h>
 
 /* opt_noreboot: If true, machine will need manual reset on error. */
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/arch/x86/vmx.c
--- a/xen/arch/x86/vmx.c        Fri Oct 21 17:19:38 2005
+++ b/xen/arch/x86/vmx.c        Fri Oct 21 17:29:26 2005
@@ -647,8 +647,8 @@
         p->u.data = value;
 
     if (vmx_portio_intercept(p)) {
-        /* no blocking & no evtchn notification */
-        clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
+        p->state = STATE_IORESP_READY;
+        vmx_io_assist(v);
         return;
     }
 
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/arch/x86/vmx_intercept.c
--- a/xen/arch/x86/vmx_intercept.c      Fri Oct 21 17:19:38 2005
+++ b/xen/arch/x86/vmx_intercept.c      Fri Oct 21 17:29:26 2005
@@ -209,8 +209,7 @@
     missed_ticks = (NOW() - vpit->scheduled)/(s_time_t) vpit->period;
 
     /* Set the pending intr bit, and send evtchn notification to myself. */
-    if (test_and_set_bit(vpit->vector, vpit->intr_bitmap))
-        vpit->pending_intr_nr++; /* already set, then count the pending intr */
+    vpit->pending_intr_nr++; /* already set, then count the pending intr */
     evtchn_set_pending(vpit->v, iopacket_port(vpit->v->domain));
 
     /* pick up missed timer tick */
@@ -230,11 +229,8 @@
 {
     vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id);
     ioreq_t *p = &vio->vp_ioreq;
-    shared_iopage_t *sp = get_sp(v->domain);
-    u64 *intr = &(sp->sp_global.pic_intr[0]);
     struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
     int rw_mode, reinit = 0;
-    int oldvec = 0;
 
     /* load init count*/
     if (p->state == STATE_IORESP_HOOK) {
@@ -243,7 +239,7 @@
             VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT: guest reset PIT with channel 
%lx!\n", (unsigned long) ((p->u.data >> 24) & 0x3) );
             rem_ac_timer(&(vpit->pit_timer));
             reinit = 1;
-            oldvec = vpit->vector;
+ 
         }
         else
             init_ac_timer(&vpit->pit_timer, pit_timer_fn, vpit, v->processor);
@@ -257,12 +253,6 @@
             printk("VMX_PIT: guest programmed too small an init_val: %x\n",
                    vpit->init_val);
             vpit->period = 1000000;
-        }
-        vpit->vector = ((p->u.data >> 16) & 0xFF);
-
-        if( reinit && oldvec != vpit->vector){
-            clear_bit(oldvec, intr);
-            vpit->pending_intr_nr = 0;
         }
 
         vpit->channel = ((p->u.data >> 24) & 0x3);
@@ -287,7 +277,6 @@
             break;
         }
 
-        vpit->intr_bitmap = intr;
         vpit->v = v;
 
         vpit->scheduled = NOW() + vpit->period;
@@ -297,8 +286,9 @@
         p->state = STATE_IORESP_READY;
 
         /* register handler to intercept the PIT io when vm_exit */
-        if (!reinit)
+        if (!reinit) {
             register_portio_handler(0x40, 4, intercept_pit_io); 
+        }
     }
 }
 #endif /* CONFIG_VMX */
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/arch/x86/vmx_io.c
--- a/xen/arch/x86/vmx_io.c     Fri Oct 21 17:19:38 2005
+++ b/xen/arch/x86/vmx_io.c     Fri Oct 21 17:29:26 2005
@@ -37,6 +37,7 @@
 #include <asm/shadow.h>
 
 #include <public/io/ioreq.h>
+#include <public/io/vmx_vpic.h>
 #include <public/io/vmx_vlapic.h>
 
 #ifdef CONFIG_VMX
@@ -794,57 +795,6 @@
 }
 
 #define BSP_CPU(v)    (!(v->vcpu_id))
-static inline void clear_extint(struct vcpu *v)
-{
-    global_iodata_t *spg;
-    int i;
-    spg = &get_sp(v->domain)->sp_global;
-
-    for(i = 0; i < INTR_LEN; i++)
-        spg->pic_intr[i] = 0;
-}
-
-static inline void clear_highest_bit(struct vcpu *v, int vector)
-{
-    global_iodata_t *spg;
-
-    spg = &get_sp(v->domain)->sp_global;
-
-    clear_bit(vector, &spg->pic_intr[0]);
-}
-
-static inline int find_highest_pic_irq(struct vcpu *v)
-{
-    u64 intr[INTR_LEN];
-    global_iodata_t *spg;
-    int i;
-
-    if(!BSP_CPU(v))
-        return -1;
-
-    spg = &get_sp(v->domain)->sp_global;
-
-    for(i = 0; i < INTR_LEN; i++){
-        intr[i] = spg->pic_intr[i] & ~spg->pic_mask[i];
-    }
-
-    return find_highest_irq((u32 *)&intr[0]);
-}
-
-/*
- * Return 0-255 for pending irq.
- *        -1 when no pending.
- */
-static inline int find_highest_pending_irq(struct vcpu *v, int *type)
-{
-    int result = -1;
-    if ((result = find_highest_pic_irq(v)) != -1){
-        *type = VLAPIC_DELIV_MODE_EXT;
-        return result;
-    }
-    return result;
-}
-
 static inline void
 interrupt_post_injection(struct vcpu * v, int vector, int type)
 {
@@ -853,17 +803,17 @@
     switch(type)
     {
     case VLAPIC_DELIV_MODE_EXT:
-        if (vpit->pending_intr_nr && vector == vpit->vector)
-            vpit->pending_intr_nr--;
-        else
-            clear_highest_bit(v, vector);
-
-        if (vector == vpit->vector && !vpit->first_injected){
-            vpit->first_injected = 1;
-            vpit->pending_intr_nr = 0;
-        }
-        if (vector == vpit->vector)
+        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();
+ 
+        }
         break;
 
     default:
@@ -893,6 +843,38 @@
 static inline int irq_masked(unsigned long eflags)
 {
     return ((eflags & X86_EFLAGS_IF) == 0);
+}
+
+void pic_irq_request(int *interrupt_request, int level)
+{
+    if (level)
+        *interrupt_request = 1;
+    else
+        *interrupt_request = 0;
+}
+
+void vmx_pic_assist(struct vcpu *v)
+{
+    global_iodata_t *spg;
+    u16   *virq_line, irqs;
+    struct vmx_virpic *pic = &v->domain->arch.vmx_platform.vmx_pic;
+    
+    spg = &get_sp(v->domain)->sp_global;
+    virq_line  = &spg->pic_clear_irr;
+    if ( *virq_line ) {
+        do {
+            irqs = *(volatile u16*)virq_line;
+        } while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
+        do_pic_irqs_clear(pic, irqs);
+    }
+    virq_line  = &spg->pic_irr;
+    if ( *virq_line ) {
+        do {
+            irqs = *(volatile u16*)virq_line;
+        } while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
+        do_pic_irqs(pic, irqs);
+    }
+
 }
 
 asmlinkage void vmx_intr_assist(void)
@@ -901,11 +883,18 @@
     int highest_vector;
     unsigned long intr_fields, eflags, interruptibility, cpu_exec_control;
     struct vcpu *v = current;
-
-    highest_vector = find_highest_pending_irq(v, &intr_type);
+    struct virtual_platform_def *plat=&v->domain->arch.vmx_platform;
+    struct vmx_virpit *vpit = &plat->vmx_pit;
+    struct vmx_virpic *pic= &plat->vmx_pic;
+
+    vmx_pic_assist(v);
     __vmread_vcpu(v, CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control);
-
-    if (highest_vector == -1) {
+    if ( vpit->pending_intr_nr ) {
+        pic_set_irq(pic, 0, 0);
+        pic_set_irq(pic, 0, 1);
+    }
+
+    if ( !plat->interrupt_request ) {
         disable_irq_window(cpu_exec_control);
         return;
     }
@@ -922,22 +911,20 @@
 
     if (interruptibility) {
         enable_irq_window(cpu_exec_control);
-        VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, interruptibility: %lx",
-                    highest_vector, interruptibility);
+        VMX_DBG_LOG(DBG_LEVEL_1, "interruptibility: %lx",interruptibility);
         return;
     }
 
     __vmread(GUEST_RFLAGS, &eflags);
+    if (irq_masked(eflags)) {
+        enable_irq_window(cpu_exec_control);
+        return;
+    }
+    plat->interrupt_request = 0;
+    highest_vector = cpu_get_pic_interrupt(v, &intr_type); 
 
     switch (intr_type) {
     case VLAPIC_DELIV_MODE_EXT:
-        if (irq_masked(eflags)) {
-            enable_irq_window(cpu_exec_control);
-            VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, eflags: %lx",
-                        highest_vector, eflags);
-            return;
-        }
-
         vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE);
         TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
         break;
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/arch/x86/vmx_vmcs.c
--- a/xen/arch/x86/vmx_vmcs.c   Fri Oct 21 17:19:38 2005
+++ b/xen/arch/x86/vmx_vmcs.c   Fri Oct 21 17:29:26 2005
@@ -210,8 +210,14 @@
 
 static void vmx_setup_platform(struct vcpu *v)
 {
-    if (v->vcpu_id == 0)
+    struct virtual_platform_def  *platform;
+    if (v->vcpu_id == 0) {
         get_io_shared_page(v);
+        platform = &v->domain->arch.vmx_platform;
+        pic_init(&platform->vmx_pic,  pic_irq_request, 
+                 &platform->interrupt_request);
+        register_pic_io_hook();
+    }
 }
 
 static void vmx_set_host_env(struct vcpu *v)
@@ -275,7 +281,8 @@
     page = (struct pfn_info *) alloc_domheap_page(NULL);
     pfn = (unsigned long) (page - frame_table);
 
-    vmx_setup_platform(v);
+    if ( v == v->domain->vcpu[0] )
+        vmx_setup_platform(v);
 
     vmx_set_host_env(v);
 
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/include/asm-x86/vmx.h
--- a/xen/include/asm-x86/vmx.h Fri Oct 21 17:19:38 2005
+++ b/xen/include/asm-x86/vmx.h Fri Oct 21 17:29:26 2005
@@ -34,6 +34,7 @@
 extern void vmx_asm_do_resume(void);
 extern void vmx_asm_do_launch(void);
 extern void vmx_intr_assist(void);
+extern void pic_irq_request(int *interrupt_request, int level);
 
 extern void arch_vmx_do_launch(struct vcpu *);
 extern void arch_vmx_do_resume(struct vcpu *);
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/include/asm-x86/vmx_intercept.h
--- a/xen/include/asm-x86/vmx_intercept.h       Fri Oct 21 17:19:38 2005
+++ b/xen/include/asm-x86/vmx_intercept.h       Fri Oct 21 17:29:26 2005
@@ -8,7 +8,7 @@
 #include <xen/errno.h>
 #include <public/io/ioreq.h>
 
-#define MAX_IO_HANDLER              4
+#define MAX_IO_HANDLER              8
 
 #define VMX_PORTIO                  0
 #define VMX_MMIO                    1
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/include/asm-x86/vmx_platform.h
--- a/xen/include/asm-x86/vmx_platform.h        Fri Oct 21 17:19:38 2005
+++ b/xen/include/asm-x86/vmx_platform.h        Fri Oct 21 17:29:26 2005
@@ -24,6 +24,7 @@
 #include <asm/e820.h>
 #include <asm/vmx_virpit.h>
 #include <asm/vmx_intercept.h>
+#include <public/io/vmx_vpic.h>
 
 #define MAX_OPERAND_NUM 2
 
@@ -80,6 +81,8 @@
     unsigned long          shared_page_va;
     struct vmx_virpit      vmx_pit;
     struct vmx_io_handler  vmx_io_handler;
+    struct vmx_virpic      vmx_pic;
+    int                    interrupt_request;
 };
 
 extern void handle_mmio(unsigned long, unsigned long);
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/include/asm-x86/vmx_virpit.h
--- a/xen/include/asm-x86/vmx_virpit.h  Fri Oct 21 17:19:38 2005
+++ b/xen/include/asm-x86/vmx_virpit.h  Fri Oct 21 17:29:26 2005
@@ -18,13 +18,11 @@
 
 struct vmx_virpit {
     /* for simulation of counter 0 in mode 2*/
-    int vector;    /* the pit irq vector */
-    unsigned int period;  /* the frequency. e.g. 10ms*/
+    u32 period;                /* pit frequency in ns */
     s_time_t scheduled;                 /* scheduled timer interrupt */
     unsigned int channel;  /* the pit channel, counter 0~2 */
-    u64  *intr_bitmap;
     unsigned int pending_intr_nr; /* the couner for pending timer interrupts */
-    unsigned long long inject_point; /* the time inject virt intr */
+    u64 inject_point; /* the time inject virt intr */
     struct ac_timer pit_timer;  /* periodic timer for mode 2*/
     int first_injected;                 /* flag to prevent shadow window */
 
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/include/public/io/ioreq.h
--- a/xen/include/public/io/ioreq.h     Fri Oct 21 17:19:38 2005
+++ b/xen/include/public/io/ioreq.h     Fri Oct 21 17:29:26 2005
@@ -60,8 +60,10 @@
 #define INTR_LEN        (MAX_VECTOR/(BITS_PER_BYTE * sizeof(uint64_t)))
 
 typedef struct {
-    uint64_t pic_intr[INTR_LEN];
-    uint64_t pic_mask[INTR_LEN];
+    uint16_t  pic_elcr;
+    uint16_t   pic_irr;
+    uint16_t   pic_last_irr;
+    uint16_t   pic_clear_irr;
     int      eport; /* Event channel port */
 } global_iodata_t;
 
diff -r 8eaaa622db81 -r 2d5b92e7c79a tools/ioemu/hw/i8259_stub.c
--- /dev/null   Fri Oct 21 17:19:38 2005
+++ b/tools/ioemu/hw/i8259_stub.c       Fri Oct 21 17:29:26 2005
@@ -0,0 +1,96 @@
+/* Xen 8259 stub for interrupt controller emulation
+ * 
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2005      Intel corperation
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "xenctrl.h"
+#include <xen/io/ioreq.h>
+#include <stdio.h>
+#include "cpu.h"
+#include "cpu-all.h"
+
+static __inline__ void atomic_set_bit(long nr, volatile void *addr)
+{
+        __asm__ __volatile__(
+                "lock ; bts %1,%0"
+                :"=m" (*(volatile long *)addr)
+                :"dIr" (nr));
+}
+static __inline__ void atomic_clear_bit(long nr, volatile void *addr)
+{
+        __asm__ __volatile__(
+                "lock ; btr %1,%0"
+                :"=m" (*(volatile long *)addr)
+                :"dIr" (nr));
+}
+
+#include <vl.h>
+extern shared_iopage_t *shared_page;
+extern CPUState *global_env;
+void pic_set_irq(int irq, int level)
+{
+    global_iodata_t  *gio;
+    int  mask;
+
+    gio = &shared_page->sp_global;
+    mask = 1 << irq;
+    if ( gio->pic_elcr & mask ) {
+        /* level */
+       if ( level ) {
+           atomic_set_bit(irq, &gio->pic_irr);
+           atomic_clear_bit(irq, &gio->pic_clear_irr);
+           global_env->send_event = 1;
+       }
+       else {
+           atomic_set_bit(irq, &gio->pic_clear_irr);
+           atomic_clear_bit(irq, &gio->pic_irr);
+           global_env->send_event = 1;
+       }
+    }
+    else {
+       /* edge */
+       if ( level ) {
+           if ( (mask & gio->pic_last_irr) == 0 ) { 
+               atomic_set_bit(irq, &gio->pic_irr);
+               atomic_set_bit(irq, &gio->pic_last_irr);
+               global_env->send_event = 1;
+           }
+       }
+       else {
+           atomic_clear_bit(irq, &gio->pic_last_irr);
+       }
+    }
+}
+
+void irq_info(void)
+{
+    term_printf("irq statistic code not compiled.\n");
+}
+
+void pic_info(void)
+{
+    term_printf("pic_infoi code not compiled.\n");
+}
+
+void pic_init(void)
+{
+}
+
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/arch/x86/dm/i8259.c
--- /dev/null   Fri Oct 21 17:19:38 2005
+++ b/xen/arch/x86/dm/i8259.c   Fri Oct 21 17:29:26 2005
@@ -0,0 +1,520 @@
+/*
+ * QEMU 8259 interrupt controller emulation
+ * 
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2005 Intel Corperation
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#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 <public/io/vmx_vlapic.h>
+#include <asm/current.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)
+{
+    int mask;
+    mask = 1 << irq;
+    if (s->elcr & mask) {
+        /* level triggered */
+        if (level) {
+            s->irr |= mask;
+            s->last_irr |= mask;
+        } else {
+            s->irr &= ~mask;
+            s->last_irr &= ~mask;
+        }
+    } else {
+        /* edge triggered */
+        if (level) {
+            if ((s->last_irr & mask) == 0) {
+                s->irr |= mask;
+           }
+            s->last_irr |= mask;
+        } else {
+            s->last_irr &= ~mask;
+        }
+    }
+}
+
+/* return the highest priority found in mask (highest = smallest
+   number). Return 8 if no irq */
+static inline int get_priority(PicState *s, int mask)
+{
+    int priority;
+    if (mask == 0)
+        return 8;
+    priority = 0;
+    while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
+        priority++;
+    return priority;
+}
+
+/* return the pic wanted interrupt. return -1 if none */
+static int pic_get_irq(PicState *s)
+{
+    int mask, cur_priority, priority;
+
+    mask = s->irr & ~s->imr;
+    priority = get_priority(s, mask);
+    if (priority == 8)
+        return -1;
+    /* compute current priority. If special fully nested mode on the
+       master, the IRQ coming from the slave is not taken into account
+       for the priority computation. */
+    mask = s->isr;
+    if (s->special_fully_nested_mode && s == &s->pics_state->pics[0])
+        mask &= ~(1 << 2);
+    cur_priority = get_priority(s, mask);
+    if (priority < cur_priority) {
+        /* higher priority found: an irq should be generated */
+        return (priority + s->priority_add) & 7;
+    } else {
+        return -1;
+    }
+}
+
+/* raise irq to CPU if necessary. must be called every time the active
+   irq may change */
+/* XXX: should not export it, but it is needed for an APIC kludge */
+void pic_update_irq(struct vmx_virpic *s)
+{
+    int irq2, irq;
+
+    /* first look at slave pic */
+    irq2 = pic_get_irq(&s->pics[1]);
+    if (irq2 >= 0) {
+        /* if irq request by slave pic, signal master PIC */
+        pic_set_irq1(&s->pics[0], 2, 1);
+        pic_set_irq1(&s->pics[0], 2, 0);
+    }
+    /* look at requested irq */
+    irq = pic_get_irq(&s->pics[0]);
+    if (irq >= 0) {
+        s->irq_request(s->irq_request_opaque, 1);
+    }
+}
+
+void pic_set_irq_new(void *opaque, int irq, int level)
+{
+    struct vmx_virpic *s = opaque;
+
+    pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
+    /* used for IOAPIC irqs */
+    if (s->alt_irq_func)
+        s->alt_irq_func(s->alt_irq_opaque, irq, level);
+    pic_update_irq(s);
+}
+
+void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs)
+{
+    s->pics[1].irr |= (uint8_t)(irqs >> 8);
+    s->pics[0].irr |= (uint8_t) irqs;
+    /* TODO for alt_irq_func */
+    pic_update_irq(s);
+}
+
+void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs)
+{
+    s->pics[1].irr &= ~(uint8_t)(irqs >> 8);
+    s->pics[0].irr &= ~(uint8_t) irqs;
+    pic_update_irq(s);
+}
+
+/* obsolete function */
+void pic_set_irq(struct vmx_virpic *isa_pic, int irq, int level)
+{
+    pic_set_irq_new(isa_pic, irq, level);
+}
+
+/* acknowledge interrupt 'irq' */
+static inline void pic_intack(PicState *s, int irq)
+{
+    if (s->auto_eoi) {
+        if (s->rotate_on_auto_eoi)
+            s->priority_add = (irq + 1) & 7;
+    } else {
+        s->isr |= (1 << irq);
+    }
+    /* We don't clear a level sensitive interrupt here */
+    if (!(s->elcr & (1 << irq)))
+        s->irr &= ~(1 << irq);
+}
+
+int pic_read_irq(struct vmx_virpic *s)
+{
+    int irq, irq2, intno;
+
+    irq = pic_get_irq(&s->pics[0]);
+    if (irq >= 0) {
+        pic_intack(&s->pics[0], irq);
+        if (irq == 2) {
+            irq2 = pic_get_irq(&s->pics[1]);
+            if (irq2 >= 0) {
+                pic_intack(&s->pics[1], irq2);
+            } else {
+                /* spurious IRQ on slave controller */
+                irq2 = 7;
+            }
+            intno = s->pics[1].irq_base + irq2;
+            irq = irq2 + 8;
+        } else {
+            intno = s->pics[0].irq_base + irq;
+        }
+    } else {
+        /* spurious IRQ on host controller */
+        printk("spurious IRQ irq got=%d\n",irq);
+        irq = 7;
+        intno = s->pics[0].irq_base + irq;
+    }
+    pic_update_irq(s);
+        
+    return intno;
+}
+
+static void update_shared_irr(struct vmx_virpic *s, PicState *c)
+{
+    uint8_t *pl, *pe;
+
+    get_sp(current->domain)->sp_global.pic_elcr = 
+               s->pics[0].elcr | ((u16)s->pics[1].elcr << 8);
+    pl =(uint8_t*)&get_sp(current->domain)->sp_global.pic_last_irr;
+    pe =(uint8_t*)&get_sp(current->domain)->sp_global.pic_elcr;
+    if ( c == &s->pics[0] ) {
+         *pl = c->last_irr;
+         *pe = c->elcr;
+    }
+    else {
+         *(pl+1) = c->last_irr;
+         *(pe+1) = c->elcr;
+    }
+}
+
+static void pic_reset(void *opaque)
+{
+    PicState *s = opaque;
+
+    s->last_irr = 0;
+    s->irr = 0;
+    s->imr = 0;
+    s->isr = 0;
+    s->priority_add = 0;
+    s->irq_base = 0;
+    s->read_reg_select = 0;
+    s->poll = 0;
+    s->special_mask = 0;
+    s->init_state = 0;
+    s->auto_eoi = 0;
+    s->rotate_on_auto_eoi = 0;
+    s->special_fully_nested_mode = 0;
+    s->init4 = 0;
+    s->elcr = 0;
+}
+
+static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PicState *s = opaque;
+    int priority, cmd, irq;
+
+    addr &= 1;
+    if (addr == 0) {
+        if (val & 0x10) {
+            /* init */
+            pic_reset(s);
+            update_shared_irr(s->pics_state, s);
+            /* deassert a pending interrupt */
+            s->pics_state->irq_request(s->pics_state->irq_request_opaque, 0);
+            s->init_state = 1;
+            s->init4 = val & 1;
+            if (val & 0x02)
+                hw_error("single mode not supported");
+            if (val & 0x08)
+                hw_error("level sensitive irq not supported");
+        } else if (val & 0x08) {
+            if (val & 0x04)
+                s->poll = 1;
+            if (val & 0x02)
+                s->read_reg_select = val & 1;
+            if (val & 0x40)
+                s->special_mask = (val >> 5) & 1;
+        } else {
+            cmd = val >> 5;
+            switch(cmd) {
+            case 0:
+            case 4:
+                s->rotate_on_auto_eoi = cmd >> 2;
+                break;
+            case 1: /* end of interrupt */
+            case 5:
+                priority = get_priority(s, s->isr);
+                if (priority != 8) {
+                    irq = (priority + s->priority_add) & 7;
+                    s->isr &= ~(1 << irq);
+                    if (cmd == 5)
+                        s->priority_add = (irq + 1) & 7;
+                    pic_update_irq(s->pics_state);
+                }
+                break;
+            case 3:
+                irq = val & 7;
+                s->isr &= ~(1 << irq);
+                pic_update_irq(s->pics_state);
+                break;
+            case 6:
+                s->priority_add = (val + 1) & 7;
+                pic_update_irq(s->pics_state);
+                break;
+            case 7:
+                irq = val & 7;
+                s->isr &= ~(1 << irq);
+                s->priority_add = (irq + 1) & 7;
+                pic_update_irq(s->pics_state);
+                break;
+            default:
+                /* no operation */
+                break;
+            }
+        }
+    } else {
+        switch(s->init_state) {
+        case 0:
+            /* normal mode */
+            s->imr = val;
+            pic_update_irq(s->pics_state);
+            break;
+        case 1:
+            s->irq_base = val & 0xf8;
+            s->init_state = 2;
+            break;
+        case 2:
+            if (s->init4) {
+                s->init_state = 3;
+            } else {
+                s->init_state = 0;
+            }
+            break;
+        case 3:
+            s->special_fully_nested_mode = (val >> 4) & 1;
+            s->auto_eoi = (val >> 1) & 1;
+            s->init_state = 0;
+            break;
+        }
+    }
+}
+
+static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
+{
+    int ret;
+
+    ret = pic_get_irq(s);
+    if (ret >= 0) {
+        if (addr1 >> 7) {
+            s->pics_state->pics[0].isr &= ~(1 << 2);
+            s->pics_state->pics[0].irr &= ~(1 << 2);
+        }
+        s->irr &= ~(1 << ret);
+        s->isr &= ~(1 << ret);
+        if (addr1 >> 7 || ret != 2)
+            pic_update_irq(s->pics_state);
+    } else {
+        ret = 0x07;
+        pic_update_irq(s->pics_state);
+    }
+
+    return ret;
+}
+
+static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
+{
+    PicState *s = opaque;
+    unsigned int addr;
+    int ret;
+
+    addr = addr1;
+    addr &= 1;
+    if (s->poll) {
+        ret = pic_poll_read(s, addr1);
+        s->poll = 0;
+    } else {
+        if (addr == 0) {
+            if (s->read_reg_select)
+                ret = s->isr;
+            else
+                ret = s->irr;
+        } else {
+            ret = s->imr;
+        }
+    }
+    return ret;
+}
+
+/* memory mapped interrupt status */
+/* XXX: may be the same than pic_read_irq() */
+uint32_t pic_intack_read(struct vmx_virpic *s)
+{
+    int ret;
+
+    ret = pic_poll_read(&s->pics[0], 0x00);
+    if (ret == 2)
+        ret = pic_poll_read(&s->pics[1], 0x80) + 8;
+    /* Prepare for ISR read */
+    s->pics[0].read_reg_select = 1;
+    
+    return ret;
+}
+
+static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PicState *s = opaque;
+    s->elcr = val & s->elcr_mask;
+}
+
+static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1)
+{
+    PicState *s = opaque;
+    return s->elcr;
+}
+
+/* XXX: add generic master/slave system */
+static void pic_init1(int io_addr, int elcr_addr, PicState *s)
+{
+    pic_reset(s);
+}
+
+void pic_init(struct vmx_virpic *s, void (*irq_request)(), 
+              void *irq_request_opaque)
+{
+    memset(s, 0, sizeof(*s));
+    pic_init1(0x20, 0x4d0, &s->pics[0]);
+    pic_init1(0xa0, 0x4d1, &s->pics[1]);
+    s->pics[0].elcr_mask = 0xf8;
+    s->pics[1].elcr_mask = 0xde;
+    s->irq_request = irq_request;
+    s->irq_request_opaque = irq_request_opaque;
+    s->pics[0].pics_state = s;
+    s->pics[1].pics_state = s;
+    return; 
+}
+
+void pic_set_alt_irq_func(struct vmx_virpic *s, void (*alt_irq_func)(),
+                          void *alt_irq_opaque)
+{
+    s->alt_irq_func = alt_irq_func;
+    s->alt_irq_opaque = alt_irq_opaque;
+}
+
+static int intercept_pic_io(ioreq_t *p)
+{
+    struct vmx_virpic  *pic;
+    struct vcpu *v = current;
+    uint32_t data;
+    
+    if ( p->size != 1 || p->count != 1) {
+        printk("PIC_IO wrong access size %d!\n", (int)p->size);
+        return 1;
+    }
+    pic = &v->domain->arch.vmx_platform.vmx_pic;
+    if ( p->dir == 0 ) {
+        if(p->pdata_valid) 
+            vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_IN);
+        else
+            data = p->u.data;
+        pic_ioport_write((void*)&pic->pics[p->addr>>7],
+                (uint32_t) p->addr, (uint32_t) (data & 0xff));
+    }
+    else {
+        data = pic_ioport_read(
+            (void*)&pic->pics[p->addr>>7], (uint32_t) p->addr);
+        if(p->pdata_valid) 
+            vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_OUT);
+        else 
+            p->u.data = (u64)data;
+    }
+    return 1;
+}
+
+static int intercept_elcr_io(ioreq_t *p)
+{
+    struct vmx_virpic  *s;
+    struct vcpu *v = current;
+    uint32_t data;
+    
+    if ( p->size != 1 || p->count != 1 ) {
+        printk("PIC_IO wrong access size %d!\n", (int)p->size);
+        return 1;
+    }
+
+    s = &v->domain->arch.vmx_platform.vmx_pic;
+    if ( p->dir == 0 ) {
+        if(p->pdata_valid) 
+            vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_IN);
+        else
+            data = p->u.data;
+        elcr_ioport_write((void*)&s->pics[p->addr&1],
+                (uint32_t) p->addr, (uint32_t)( data & 0xff));
+       get_sp(current->domain)->sp_global.pic_elcr = 
+            s->pics[0].elcr | ((u16)s->pics[1].elcr << 8);
+    }
+    else {
+        data = (u64) elcr_ioport_read(
+                (void*)&s->pics[p->addr&1], (uint32_t) p->addr);
+        if(p->pdata_valid) 
+            vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_OUT);
+        else 
+            p->u.data = (u64)data;
+
+    }
+    return 1;
+}
+void register_pic_io_hook (void)
+{
+    register_portio_handler(0x20, 2, intercept_pic_io); 
+    register_portio_handler(0x4d0, 1, intercept_elcr_io); 
+    register_portio_handler(0xa0, 2, intercept_pic_io); 
+    register_portio_handler(0x4d1, 1, intercept_elcr_io); 
+}
+
+
+/* IRQ handling */
+int cpu_get_pic_interrupt(struct vcpu *v, int *type)
+{
+    int intno;
+    struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic;
+    
+    /* read the irq from the PIC */
+    intno = pic_read_irq(s);
+    *type = VLAPIC_DELIV_MODE_EXT;
+    return intno;
+}
+
+int is_pit_irq(struct vcpu *v, int irq)
+{
+    int  pit_vec = v->domain->arch.vmx_platform.vmx_pic.pics[0].irq_base;
+
+    return (irq == pit_vec);
+}
diff -r 8eaaa622db81 -r 2d5b92e7c79a xen/include/public/io/vmx_vpic.h
--- /dev/null   Fri Oct 21 17:19:38 2005
+++ b/xen/include/public/io/vmx_vpic.h  Fri Oct 21 17:29:26 2005
@@ -0,0 +1,84 @@
+/*
+ * QEMU System Emulator header
+ * 
+ * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2005 Intel Corp
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef _VMX_VPIC_H
+#define _VMX_VPIC_H
+
+#define hw_error(x)  do {} while (0);
+
+
+/* i8259.c */
+typedef struct IOAPICState IOAPICState;
+typedef struct PicState {
+    uint8_t last_irr; /* edge detection */
+    uint8_t irr; /* interrupt request register */
+    uint8_t imr; /* interrupt mask register */
+    uint8_t isr; /* interrupt service register */
+    uint8_t priority_add; /* highest irq priority */
+    uint8_t irq_base;
+    uint8_t read_reg_select;
+    uint8_t poll;
+    uint8_t special_mask;
+    uint8_t init_state;
+    uint8_t auto_eoi;
+    uint8_t rotate_on_auto_eoi;
+    uint8_t special_fully_nested_mode;
+    uint8_t init4; /* true if 4 byte init */
+    uint8_t elcr; /* PIIX edge/trigger selection*/
+    uint8_t elcr_mask;
+    struct vmx_virpic *pics_state;
+} PicState;
+
+struct vmx_virpic {
+    /* 0 is master pic, 1 is slave pic */
+    /* XXX: better separation between the two pics */
+    PicState pics[2];
+    void (*irq_request)(int *opaque, int level);
+    void *irq_request_opaque;
+    /* IOAPIC callback support */
+    void (*alt_irq_func)(void *opaque, int irq_num, int level);
+    void *alt_irq_opaque;
+};
+
+
+void pic_set_irq(struct vmx_virpic *s, int irq, int level);
+void pic_set_irq_new(void *opaque, int irq, int level);
+void pic_init(struct vmx_virpic *s, 
+              void (*irq_request)(),
+              void *irq_request_opaque);
+void pic_set_alt_irq_func(struct vmx_virpic *s, 
+                          void(*alt_irq_func)(),
+                          void *alt_irq_opaque);
+int pic_read_irq(struct vmx_virpic *s);
+void pic_update_irq(struct vmx_virpic *s);
+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);
+void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs);
+void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs);
+
+/* APIC */
+#endif  /* _VMX_VPIC_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®.