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] [xen-unstable] [IA64] Implement irq redirection of IOSAP

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [IA64] Implement irq redirection of IOSAPIC
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Sat, 09 Dec 2006 15:45:02 +0000
Delivery-date: Sat, 09 Dec 2006 07:47:41 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
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 awilliam@xxxxxxxxxxxx
# Node ID 3bd97b4fe77d2b751e2ef5beb4e0be4966e7dca3
# Parent  4f1a3ae07dbc11683f2f8064449c96aa590112b1
[IA64] Implement irq redirection of IOSAPIC

Signed-off-by: Anthony Xu <anthony.xu@xxxxxxxxx>
---
 xen/arch/ia64/vmx/mmio.c            |  299 ---------------------------------
 xen/arch/ia64/vmx/viosapic.c        |   20 +-
 xen/arch/ia64/vmx/vlsapic.c         |  323 +++++++++++++++++++++++++-----------
 xen/include/asm-ia64/viosapic.h     |    1 
 xen/include/asm-ia64/vlsapic.h      |   11 +
 xen/include/asm-ia64/vmx_platform.h |    1 
 xen/include/asm-ia64/vmx_vpd.h      |    2 
 7 files changed, 265 insertions(+), 392 deletions(-)

diff -r 4f1a3ae07dbc -r 3bd97b4fe77d xen/arch/ia64/vmx/mmio.c
--- a/xen/arch/ia64/vmx/mmio.c  Thu Dec 07 04:15:54 2006 -0700
+++ b/xen/arch/ia64/vmx/mmio.c  Thu Dec 07 05:34:07 2006 -0700
@@ -23,7 +23,6 @@
 
 #include <linux/sched.h>
 #include <xen/mm.h>
-#include <asm/tlb.h>
 #include <asm/vmx_mm_def.h>
 #include <asm/gcc_intrin.h>
 #include <linux/interrupt.h>
@@ -37,22 +36,7 @@
 #include <linux/event.h>
 #include <xen/domain.h>
 #include <asm/viosapic.h>
-
-/*
-struct mmio_list *lookup_mmio(u64 gpa, struct mmio_list *mio_base)
-{
-    int     i;
-    for (i=0; mio_base[i].iot != NOT_IO; i++ ) {
-        if ( gpa >= mio_base[i].start && gpa <= mio_base[i].end )
-            return &mio_base[i];
-    }
-    return NULL;
-}
-*/
-
-#define        PIB_LOW_HALF(ofst)      !(ofst&(1<<20))
-#define PIB_OFST_INTA           0x1E0000
-#define PIB_OFST_XTP            0x1E0008
+#include <asm/vlsapic.h>
 
 #define HVM_BUFFERED_IO_RANGE_NR 1
 
@@ -118,87 +102,6 @@ int hvm_buffered_io_intercept(ioreq_t *p
     return 1;
 }
 
-static void write_ipi (VCPU *vcpu, uint64_t addr, uint64_t value);
-
-static void pib_write(VCPU *vcpu, void *src, uint64_t pib_off, size_t s, int 
ma)
-{
-    switch (pib_off) {
-    case PIB_OFST_INTA:
-        panic_domain(NULL,"Undefined write on PIB INTA\n");
-        break;
-    case PIB_OFST_XTP:
-        if ( s == 1 && ma == 4 /* UC */) {
-            vmx_vcpu_get_plat(vcpu)->xtp = *(uint8_t *)src;
-        }
-        else {
-            panic_domain(NULL,"Undefined write on PIB XTP\n");
-        }
-        break;
-    default:
-        if ( PIB_LOW_HALF(pib_off) ) {   // lower half
-            if ( s != 8 || ma != 0x4 /* UC */ ) {
-                panic_domain
-                 (NULL,"Undefined IPI-LHF write with s %ld, ma %d!\n", s, ma);
-            }
-            else {
-                write_ipi(vcpu, pib_off, *(uint64_t *)src);
-                // TODO for SM-VP
-            }
-        }
-        else {      // upper half
-            printk("IPI-UHF write %lx\n",pib_off);
-            panic_domain(NULL,"Not support yet for SM-VP\n");
-        }
-        break;
-    }
-}
-
-static void pib_read(VCPU *vcpu, uint64_t pib_off, void *dest, size_t s, int 
ma)
-{
-    switch (pib_off) {
-    case PIB_OFST_INTA:
-        // todo --- emit on processor system bus.
-        if ( s == 1 && ma == 4) { // 1 byte load
-            // TODO: INTA read from IOSAPIC
-        }
-        else {
-            panic_domain(NULL,"Undefined read on PIB INTA\n");
-        }
-        break;
-    case PIB_OFST_XTP:
-        if ( s == 1 && ma == 4) {
-            *((uint8_t*)dest) = vmx_vcpu_get_plat(vcpu)->xtp;
-        }
-        else {
-            panic_domain(NULL,"Undefined read on PIB XTP\n");
-        }
-        break;
-    default:
-        if ( PIB_LOW_HALF(pib_off) ) {   // lower half
-            if ( s != 8 || ma != 4 ) {
-                panic_domain(NULL,"Undefined IPI-LHF read!\n");
-            }
-            else {
-#ifdef  IPI_DEBUG
-                printk("IPI-LHF read %lx\n",pib_off);
-#endif
-                *(uint64_t *)dest = 0;  // TODO for SM-VP
-            }
-        }
-        else {      // upper half
-            if ( s != 1 || ma != 4 ) {
-                panic_domain(NULL,"Undefined PIB-UHF read!\n");
-            }
-            else {
-#ifdef  IPI_DEBUG
-                printk("IPI-UHF read %lx\n",pib_off);
-#endif
-                *(uint8_t *)dest = 0;   // TODO for SM-VP
-            }
-        }
-        break;
-    }
-}
 
 static void low_mmio_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir)
 {
@@ -283,11 +186,14 @@ static void mmio_access(VCPU *vcpu, u64 
 
     perfc_incra(vmx_mmio_access, iot >> 56);
     switch (iot) {
-    case GPFN_PIB:
-        if(!dir)
-            pib_write(vcpu, dest, src_pa - v_plat->pib_base, s, ma);
+    case GPFN_PIB:       
+        if (ma != 4)
+            panic_domain(NULL, "Access PIB not with UC attribute\n");
+
+        if (!dir)
+            vlsapic_write(vcpu, src_pa, s, *dest);
         else
-            pib_read(vcpu, src_pa - v_plat->pib_base, dest, s, ma);
+            *dest = vlsapic_read(vcpu, src_pa, s);
         break;
     case GPFN_GFW:
         break;
@@ -310,195 +216,6 @@ static void mmio_access(VCPU *vcpu, u64 
     }
     return;
 }
-
-/*
- * Read or write data in guest virtual address mode.
- */
-/*
-void
-memwrite_v(VCPU *vcpu, thash_data_t *vtlb, u64 *src, u64 *dest, size_t s)
-{
-    uint64_t pa;
-
-    if (!vtlb->nomap)
-        panic("Normal memory write shouldn't go to this point!");
-    pa = PPN_2_PA(vtlb->ppn);
-    pa += POFFSET((u64)dest, vtlb->ps);
-    mmio_write (vcpu, src, pa, s, vtlb->ma);
-}
-
-
-void
-memwrite_p(VCPU *vcpu, u64 *src, u64 *dest, size_t s)
-{
-    uint64_t pa = (uint64_t)dest;
-    int    ma;
-
-    if ( pa & (1UL <<63) ) {
-        // UC
-        ma = 4;
-        pa <<=1;
-        pa >>=1;
-    }
-    else {
-        // WBL
-        ma = 0;     // using WB for WBL
-    }
-    mmio_write (vcpu, src, pa, s, ma);
-}
-
-void
-memread_v(VCPU *vcpu, thash_data_t *vtlb, u64 *src, u64 *dest, size_t s)
-{
-    uint64_t pa;
-
-    if (!vtlb->nomap)
-        panic_domain(NULL,"Normal memory write shouldn't go to this point!");
-    pa = PPN_2_PA(vtlb->ppn);
-    pa += POFFSET((u64)src, vtlb->ps);
-
-    mmio_read(vcpu, pa, dest, s, vtlb->ma);
-}
-
-void
-memread_p(VCPU *vcpu, u64 *src, u64 *dest, size_t s)
-{
-    uint64_t pa = (uint64_t)src;
-    int    ma;
-
-    if ( pa & (1UL <<63) ) {
-        // UC
-        ma = 4;
-        pa <<=1;
-        pa >>=1;
-    }
-    else {
-        // WBL
-        ma = 0;     // using WB for WBL
-    }
-    mmio_read(vcpu, pa, dest, s, ma);
-}
-*/
-
-/*
- * To inject INIT to guest, we must set the PAL_INIT entry 
- * and set psr to switch to physical mode
- */
-#define PAL_INIT_ENTRY 0x80000000ffffffa0
-#define PSR_SET_BITS (IA64_PSR_DT | IA64_PSR_IT | IA64_PSR_RT |        \
-                      IA64_PSR_IC | IA64_PSR_RI)
-
-static void vmx_inject_guest_pal_init(VCPU *vcpu)
-{
-    REGS *regs = vcpu_regs(vcpu);
-    uint64_t psr = vmx_vcpu_get_psr(vcpu);
-
-    regs->cr_iip = PAL_INIT_ENTRY;
-
-    psr = psr & (~PSR_SET_BITS);
-    vmx_vcpu_set_psr(vcpu,psr);
-}
-
-/*
- * Deliver IPI message. (Only U-VP is supported now)
- *  offset: address offset to IPI space.
- *  value:  deliver value.
- */
-static void deliver_ipi (VCPU *vcpu, uint64_t dm, uint64_t vector)
-{
-#ifdef  IPI_DEBUG
-  printk ("deliver_ipi %lx %lx\n",dm,vector);
-#endif
-    switch ( dm ) {
-    case 0:     // INT
-        vmx_vcpu_pend_interrupt (vcpu, vector);
-        break;
-    case 2:     // PMI
-        // TODO -- inject guest PMI
-        panic_domain (NULL, "Inject guest PMI!\n");
-        break;
-    case 4:     // NMI
-        vmx_vcpu_pend_interrupt (vcpu, 2);
-        break;
-    case 5:     // INIT
-        vmx_inject_guest_pal_init(vcpu);
-        break;
-    case 7:     // ExtINT
-        vmx_vcpu_pend_interrupt (vcpu, 0);
-        break;
-    case 1:
-    case 3:
-    case 6:
-    default:
-        panic_domain (NULL, "Deliver reserved IPI!\n");
-        break;
-    }
-}
-
-/*
- * TODO: Use hash table for the lookup.
- */
-static inline VCPU *lid_2_vcpu (struct domain *d, u64 id, u64 eid)
-{
-    int   i;
-    VCPU  *vcpu;
-    LID   lid;
-    for (i=0; i<MAX_VIRT_CPUS; i++) {
-        vcpu = d->vcpu[i];
-        if (!vcpu)
-            continue;
-        lid.val = VCPU_LID(vcpu);
-        if ( lid.id == id && lid.eid == eid )
-            return vcpu;
-    }
-    return NULL;
-}
-
-/*
- * execute write IPI op.
- */
-static void write_ipi (VCPU *vcpu, uint64_t addr, uint64_t value)
-{
-    VCPU   *targ;
-    struct domain *d=vcpu->domain; 
-    targ = lid_2_vcpu(vcpu->domain, 
-           ((ipi_a_t)addr).id, ((ipi_a_t)addr).eid);
-    if ( targ == NULL ) panic_domain (NULL,"Unknown IPI cpu\n");
-
-    if (!test_bit(_VCPUF_initialised, &targ->vcpu_flags)) {
-        struct pt_regs *targ_regs = vcpu_regs (targ);
-        struct vcpu_guest_context c;
-
-        memset (&c, 0, sizeof (c));
-
-        if (arch_set_info_guest (targ, &c) != 0) {
-            printk ("arch_boot_vcpu: failure\n");
-            return;
-        }
-        /* First or next rendez-vous: set registers.  */
-        vcpu_init_regs (targ);
-        targ_regs->cr_iip = d->arch.sal_data->boot_rdv_ip;
-        targ_regs->r1 = d->arch.sal_data->boot_rdv_r1;
-
-        if (test_and_clear_bit(_VCPUF_down,&targ->vcpu_flags)) {
-            vcpu_wake(targ);
-            printk ("arch_boot_vcpu: vcpu %d awaken %016lx!\n",
-                    targ->vcpu_id, targ_regs->cr_iip);
-        }
-        else
-            printk ("arch_boot_vcpu: huu, already awaken!");
-    }
-    else {
-        int running = test_bit(_VCPUF_running,&targ->vcpu_flags);
-        deliver_ipi (targ, ((ipi_d_t)value).dm, 
-                    ((ipi_d_t)value).vector);
-        vcpu_unblock(targ);
-        if (running)
-            smp_send_event_check_cpu(targ->processor);
-    }
-    return;
-}
-
 
 /*
    dir 1: read 0:write
diff -r 4f1a3ae07dbc -r 3bd97b4fe77d xen/arch/ia64/vmx/viosapic.c
--- a/xen/arch/ia64/vmx/viosapic.c      Thu Dec 07 04:15:54 2006 -0700
+++ b/xen/arch/ia64/vmx/viosapic.c      Thu Dec 07 05:34:07 2006 -0700
@@ -31,7 +31,6 @@
 #include <xen/xmalloc.h>
 #include <xen/lib.h>
 #include <xen/errno.h>
-#include <xen/sched.h>
 #include <public/hvm/ioreq.h>
 #include <asm/vlsapic.h>
 #include <asm/viosapic.h>
@@ -47,11 +46,18 @@ static void viosapic_deliver(struct vios
 
     switch ( delivery_mode )
     {
-    // don't support interrupt direct currently
     case SAPIC_FIXED:
+    {
+        v = vlsapic_lid_to_vcpu(viosapic_domain(viosapic), dest);
+        vlsapic_set_irq(v, vector);
+        vcpu_kick(v);
+        break;
+    }
     case SAPIC_LOWEST_PRIORITY:
     {
         v = vlsapic_lid_to_vcpu(viosapic_domain(viosapic), dest);
+        if (viosapic->lowest_vcpu)
+            v = viosapic->lowest_vcpu;
         vlsapic_set_irq(v, vector);
         vcpu_kick(v);
         break;
@@ -72,10 +78,10 @@ static int iosapic_get_highest_irq(struc
 {
     uint64_t irqs = viosapic->irr & ~viosapic->isr ;
    
-    if (irqs >> 32)
-        return (fls(irqs >> 32) - 1 + 32);
-    else
-        return fls(irqs) - 1;
+    if (irqs)
+        return ia64_fls(irqs);
+
+    return -1;
 }
 
 
@@ -327,5 +333,7 @@ void viosapic_init(struct domain *d)
 
     viosapic_reset(viosapic);
 
+    viosapic->lowest_vcpu = NULL;
+    
     viosapic->base_address = VIOSAPIC_DEFAULT_BASE_ADDRESS;
 }
diff -r 4f1a3ae07dbc -r 3bd97b4fe77d xen/arch/ia64/vmx/vlsapic.c
--- a/xen/arch/ia64/vmx/vlsapic.c       Thu Dec 07 04:15:54 2006 -0700
+++ b/xen/arch/ia64/vmx/vlsapic.c       Thu Dec 07 05:34:07 2006 -0700
@@ -25,10 +25,8 @@
 #include <asm/ia64_int.h>
 #include <asm/vcpu.h>
 #include <asm/regionreg.h>
-#include <asm/tlb.h>
 #include <asm/processor.h>
 #include <asm/delay.h>
-#include <asm/vmx_vcpu.h>
 #include <asm/vmx_vcpu.h>
 #include <asm/regs.h>
 #include <asm/gcc_intrin.h>
@@ -39,7 +37,15 @@
 #include <asm/kregs.h>
 #include <asm/vmx_platform.h>
 #include <asm/viosapic.h>
+#include <asm/vlsapic.h>
 #include <asm/linux/jiffies.h>
+#include <xen/domain.h>
+
+#ifdef IPI_DEBUG
+#define IPI_DPRINTK(x...) printk(x)
+#else
+#define IPI_DPRINTK(x...)
+#endif
 
 //u64  fire_itc;
 //u64  fire_itc2;
@@ -116,16 +122,13 @@ static int vmx_vcpu_unpend_interrupt(VCP
  */
 static uint64_t now_itc(vtime_t *vtm)
 {
-        uint64_t guest_itc=vtm->vtm_offset+ia64_get_itc();
-        
-        if ( vtm->vtm_local_drift ) {
-//          guest_itc -= vtm->vtm_local_drift;
-        }       
-        if (guest_itc >= vtm->last_itc)
-            return guest_itc;
-        else
-            /* guest ITC backwarded due after LP switch */
-            return vtm->last_itc;
+    uint64_t guest_itc = vtm->vtm_offset + ia64_get_itc();
+
+    if (guest_itc >= vtm->last_itc)
+        return guest_itc;
+    else
+        /* guest ITC went backward due to LP switch */
+        return vtm->last_itc;
 }
 
 /*
@@ -175,7 +178,7 @@ void vtm_init(VCPU *vcpu)
 {
     vtime_t     *vtm;
     uint64_t    itc_freq;
-    
+
     vtm = &VMX(vcpu, vtm);
 
     itc_freq = local_cpu_data->itc_freq;
@@ -261,76 +264,6 @@ void vtm_set_itv(VCPU *vcpu, uint64_t va
         vtm->pending = 0;
     }
 }
-
-
-/*
- * Update interrupt or hook the vtm timer for fire
- * At this point vtm_timer should be removed if itv is masked.
- */
-/* Interrupt must be disabled at this point */
-/*
-void vtm_interruption_update(VCPU *vcpu, vtime_t* vtm)
-{
-    uint64_t    cur_itc,vitm,vitv;
-    uint64_t    expires;
-    long        diff_now, diff_last;
-    uint64_t    spsr;
-    
-    vitv = VCPU(vcpu, itv);
-    if ( ITV_IRQ_MASK(vitv) ) {
-        return;
-    }
-    
-    vitm =VCPU(vcpu, itm);
-    local_irq_save(spsr);
-    cur_itc =now_itc(vtm);
-    diff_last = vtm->last_itc - vitm;
-    diff_now = cur_itc - vitm;
-
-    if ( diff_last >= 0 ) {
-        // interrupt already fired.
-        stop_timer(&vtm->vtm_timer);
-    }
-    else if ( diff_now >= 0 ) {
-        // ITV is fired.
-        vmx_vcpu_pend_interrupt(vcpu, vitv&0xff);
-    }
-*/
-    /* Both last_itc & cur_itc < itm, wait for fire condition */
-/*    else {
-        expires = NOW() + cycle_to_ns(0-diff_now) + TIMER_SLOP;
-        set_timer(&vtm->vtm_timer, expires);
-    }
-    local_irq_restore(spsr);
-}
- */
-
-/*
- * Action for vtm when the domain is scheduled out.
- * Remove the timer for vtm.
- */
-/*
-void vtm_domain_out(VCPU *vcpu)
-{
-    if(!is_idle_domain(vcpu->domain))
-       stop_timer(&vcpu->arch.arch_vmx.vtm.vtm_timer);
-}
- */
-/*
- * Action for vtm when the domain is scheduled in.
- * Fire vtm IRQ or add the timer for vtm.
- */
-/*
-void vtm_domain_in(VCPU *vcpu)
-{
-    vtime_t     *vtm;
-
-    if(!is_idle_domain(vcpu->domain)) {
-       vtm=&(vcpu->arch.arch_vmx.vtm);
-       vtm_interruption_update(vcpu, vtm);
-    }
-}
- */
 
 
 void vlsapic_reset(VCPU *vcpu)
@@ -350,6 +283,7 @@ void vlsapic_reset(VCPU *vcpu)
     VCPU(vcpu, lrr0) = 0x10000;   // default reset value?
     VCPU(vcpu, lrr1) = 0x10000;   // default reset value?
     update_vhpi(vcpu, NULL_VECTOR);
+    VLSAPIC_XTP(vcpu) = 0x80;   // disabled
     for ( i=0; i<4; i++) {
         VLSAPIC_INSVC(vcpu,i) = 0;
     }
@@ -367,7 +301,7 @@ static __inline__ int highest_bits(uint6
 {
     uint64_t  bits, bitnum;
     int i;
-    
+
     /* loop for all 256 bits */
     for ( i=3; i >= 0 ; i -- ) {
         bits = dat[i];
@@ -411,12 +345,6 @@ static int is_higher_class(int pending, 
 {
     return ( (pending >> 4) > mic );
 }
-#if 0
-static int is_invalid_irq(int vec)
-{
-    return (vec == 1 || ((vec <= 14 && vec >= 3)));
-}
-#endif //shadow it due to no use currently
 
 #define   IRQ_NO_MASKED         0
 #define   IRQ_MASKED_BY_VTPR    1
@@ -427,7 +355,7 @@ _xirq_masked(VCPU *vcpu, int h_pending, 
 _xirq_masked(VCPU *vcpu, int h_pending, int h_inservice)
 {
     tpr_t    vtpr;
-    
+
     vtpr.val = VCPU(vcpu, tpr);
 
     if ( h_inservice == NMI_VECTOR ) {
@@ -467,7 +395,7 @@ static int irq_masked(VCPU *vcpu, int h_
 static int irq_masked(VCPU *vcpu, int h_pending, int h_inservice)
 {
     int mask;
-    
+
     mask = _xirq_masked(vcpu, h_pending, h_inservice);
     return mask;
 }
@@ -655,4 +583,213 @@ struct vcpu * vlsapic_lid_to_vcpu(struct
             return v;
     }
     return NULL;
-}                                     
+}
+
+
+/*
+ * To inject INIT to guest, we must set the PAL_INIT entry 
+ * and set psr to switch to physical mode
+ */
+#define PAL_INIT_ENTRY 0x80000000ffffffa0
+#define PSR_SET_BITS (IA64_PSR_DT | IA64_PSR_IT | IA64_PSR_RT | \
+                      IA64_PSR_IC | IA64_PSR_RI)
+
+static void vmx_inject_guest_pal_init(VCPU *vcpu)
+{
+    REGS *regs = vcpu_regs(vcpu);
+    uint64_t psr = vmx_vcpu_get_psr(vcpu);
+
+    regs->cr_iip = PAL_INIT_ENTRY;
+
+    psr = psr & ~PSR_SET_BITS;
+    vmx_vcpu_set_psr(vcpu, psr);
+}
+
+
+/*
+ * Deliver IPI message. (Only U-VP is supported now)
+ *  offset: address offset to IPI space.
+ *  value:  deliver value.
+ */
+static void vlsapic_deliver_ipi(VCPU *vcpu, uint64_t dm, uint64_t vector)
+{
+    IPI_DPRINTK("deliver_ipi %lx %lx\n", dm, vector);
+
+    switch (dm) {
+    case SAPIC_FIXED:     // INT
+        vmx_vcpu_pend_interrupt(vcpu, vector);
+        break;
+    case SAPIC_PMI:
+        // TODO -- inject guest PMI
+        panic_domain(NULL, "Inject guest PMI!\n");
+        break;
+    case SAPIC_NMI:
+        vmx_vcpu_pend_interrupt(vcpu, 2);
+        break;
+    case SAPIC_INIT:
+        vmx_inject_guest_pal_init(vcpu);
+        break;
+    case SAPIC_EXTINT:     // ExtINT
+        vmx_vcpu_pend_interrupt(vcpu, 0);
+        break;
+    default:
+        panic_domain(NULL, "Deliver reserved IPI!\n");
+        break;
+    }
+}
+
+/*
+ * TODO: Use hash table for the lookup.
+ */
+static inline VCPU *lid_to_vcpu(struct domain *d, uint8_t id, uint8_t eid)
+{
+    VCPU  *v;
+    LID   lid; 
+
+    for_each_vcpu(d, v) {
+        lid.val = VCPU_LID(v);
+        if (lid.id == id && lid.eid == eid)
+            return v;
+    }
+    return NULL;
+}
+
+
+/*
+ * execute write IPI op.
+ */
+static void vlsapic_write_ipi(VCPU *vcpu, uint64_t addr, uint64_t value)
+{
+    VCPU   *targ;
+    struct domain *d = vcpu->domain; 
+
+    targ = lid_to_vcpu(vcpu->domain, ((ipi_a_t)addr).id, ((ipi_a_t)addr).eid);
+    if (targ == NULL)
+        panic_domain(NULL, "Unknown IPI cpu\n");
+
+    if (!test_bit(_VCPUF_initialised, &targ->vcpu_flags)) {
+        struct pt_regs *targ_regs = vcpu_regs(targ);
+        struct vcpu_guest_context c;
+
+        memset (&c, 0, sizeof(c));
+
+        if (arch_set_info_guest(targ, &c) != 0) {
+            printk("arch_boot_vcpu: failure\n");
+            return;
+        }
+        /* First or next rendez-vous: set registers. */
+        vcpu_init_regs(targ);
+        targ_regs->cr_iip = d->arch.sal_data->boot_rdv_ip;
+        targ_regs->r1 = d->arch.sal_data->boot_rdv_r1;
+
+        if (test_and_clear_bit(_VCPUF_down,&targ->vcpu_flags)) {
+            vcpu_wake(targ);
+            printk("arch_boot_vcpu: vcpu %d awaken %016lx!\n",
+                   targ->vcpu_id, targ_regs->cr_iip);
+        } else {
+            printk("arch_boot_vcpu: huh, already awake!");
+        }
+    } else {
+        int running = test_bit(_VCPUF_running, &targ->vcpu_flags);
+        vlsapic_deliver_ipi(targ, ((ipi_d_t)value).dm, 
+                            ((ipi_d_t)value).vector);
+        vcpu_unblock(targ);
+        if (running)
+            smp_send_event_check_cpu(targ->processor);
+    }
+    return;
+}
+
+
+unsigned long vlsapic_read(struct vcpu *v,
+                           unsigned long addr,
+                           unsigned long length)
+{
+    uint64_t result = 0;
+
+    addr &= (PIB_SIZE - 1);
+
+    switch (addr) {
+    case PIB_OFST_INTA:
+        if (length == 1) // 1 byte load
+            ; // There is no i8259, there is no INTA access
+        else
+            panic_domain(NULL,"Undefined read on PIB INTA\n");
+
+        break;
+    case PIB_OFST_XTP:
+        if (length == 1) {
+            result = VLSAPIC_XTP(v);
+            // printk("read xtp %lx\n", result);
+        } else {
+            panic_domain(NULL, "Undefined read on PIB XTP\n");
+        }
+        break;
+    default:
+        if (PIB_LOW_HALF(addr)) {  // lower half
+            if (length != 8 )
+                panic_domain(NULL, "Undefined IPI-LHF read!\n");
+            else
+                IPI_DPRINTK("IPI-LHF read %lx\n", pib_off);
+        } else {  // upper half
+            IPI_DPRINTK("IPI-UHF read %lx\n", addr);
+        }
+        break;
+    }
+    return result;
+}
+
+static void vlsapic_write_xtp(struct vcpu *v, uint8_t val)
+{
+    struct viosapic * viosapic;
+    struct vcpu *lvcpu, *vcpu;
+    viosapic = vcpu_viosapic(v); 
+    lvcpu = viosapic->lowest_vcpu;
+    VLSAPIC_XTP(v) = val;
+    
+    for_each_vcpu(v->domain, vcpu) {
+        if (VLSAPIC_XTP(lvcpu) > VLSAPIC_XTP(vcpu))
+            lvcpu = vcpu;
+    }
+        
+    if (VLSAPIC_XTP(lvcpu) & 0x80)  // Disabled
+        lvcpu = NULL;
+
+    viosapic->lowest_vcpu = lvcpu;
+}
+
+void vlsapic_write(struct vcpu *v,
+                      unsigned long addr,
+                      unsigned long length,
+                      unsigned long val)
+{
+    addr &= (PIB_SIZE - 1);
+
+    switch (addr) {
+    case PIB_OFST_INTA:
+        panic_domain(NULL, "Undefined write on PIB INTA\n");
+        break;
+    case PIB_OFST_XTP:
+        if (length == 1) {
+            // printk("write xtp %lx\n", val);
+            vlsapic_write_xtp(v, val);
+        } else {
+            panic_domain(NULL, "Undefined write on PIB XTP\n");
+        }
+        break;
+    default:
+        if (PIB_LOW_HALF(addr)) {   // lower half
+            if (length != 8)
+                panic_domain(NULL, "Undefined IPI-LHF write with size %ld!\n",
+                             length);
+            else
+                vlsapic_write_ipi(v, addr, val);
+        }
+        else {   // upper half
+            // printk("IPI-UHF write %lx\n",addr);
+            panic_domain(NULL, "No support for SM-VP yet\n");
+        }
+        break;
+    }
+}
+
diff -r 4f1a3ae07dbc -r 3bd97b4fe77d xen/include/asm-ia64/viosapic.h
--- a/xen/include/asm-ia64/viosapic.h   Thu Dec 07 04:15:54 2006 -0700
+++ b/xen/include/asm-ia64/viosapic.h   Thu Dec 07 05:34:07 2006 -0700
@@ -78,6 +78,7 @@ struct viosapic {
     uint64_t isr;     /* This is used for level trigger */
     uint32_t ioregsel;
     spinlock_t lock;
+    struct vcpu * lowest_vcpu;
     uint64_t base_address;
     union viosapic_rte redirtbl[VIOSAPIC_NUM_PINS];
 };
diff -r 4f1a3ae07dbc -r 3bd97b4fe77d xen/include/asm-ia64/vlsapic.h
--- a/xen/include/asm-ia64/vlsapic.h    Thu Dec 07 04:15:54 2006 -0700
+++ b/xen/include/asm-ia64/vlsapic.h    Thu Dec 07 05:34:07 2006 -0700
@@ -50,10 +50,19 @@
 #define SAPIC_LEVEL            1
 
 /*
+ * LSAPIC OFFSET
+ */
+#define PIB_LOW_HALF(ofst)     !(ofst & (1 << 20))
+#define PIB_OFST_INTA          0x1E0000
+#define PIB_OFST_XTP           0x1E0008
+
+/*
  *Mask bit
  */
 #define SAPIC_MASK_SHIFT       16
 #define SAPIC_MASK             (1 << SAPIC_MASK_SHIFT)
+
+#define VLSAPIC_XTP(_v)        VMX(_v, xtp)
 
 extern void vtm_init(struct vcpu *vcpu);
 extern void vtm_set_itc(struct  vcpu *vcpu, uint64_t new_itc);
@@ -63,5 +72,7 @@ extern void vhpi_detection(struct vcpu *
 extern void vhpi_detection(struct vcpu *vcpu);
 extern int vmx_vcpu_pend_interrupt(VCPU * vcpu, uint8_t vector);
 extern struct vcpu * vlsapic_lid_to_vcpu(struct domain *d, uint16_t dest);
+extern uint64_t vlsapic_read(struct vcpu *v, uint64_t addr, uint64_t s);
+extern void vlsapic_write(struct vcpu *v, uint64_t addr, uint64_t s, uint64_t 
val);
 #define vlsapic_set_irq vmx_vcpu_pend_interrupt
 #endif
diff -r 4f1a3ae07dbc -r 3bd97b4fe77d xen/include/asm-ia64/vmx_platform.h
--- a/xen/include/asm-ia64/vmx_platform.h       Thu Dec 07 04:15:54 2006 -0700
+++ b/xen/include/asm-ia64/vmx_platform.h       Thu Dec 07 05:34:07 2006 -0700
@@ -28,7 +28,6 @@ typedef struct virtual_platform_def {
     spinlock_t             buffered_io_lock;
     unsigned long       shared_page_va;
     unsigned long       pib_base;
-    unsigned char       xtp;
     unsigned long       params[HVM_NR_PARAMS];
     struct mmio_list    *mmio;
     /* One IOSAPIC now... */
diff -r 4f1a3ae07dbc -r 3bd97b4fe77d xen/include/asm-ia64/vmx_vpd.h
--- a/xen/include/asm-ia64/vmx_vpd.h    Thu Dec 07 04:15:54 2006 -0700
+++ b/xen/include/asm-ia64/vmx_vpd.h    Thu Dec 07 05:34:07 2006 -0700
@@ -96,9 +96,9 @@ struct arch_vmx_struct {
 //    unsigned long   rfi_iip;
 //    unsigned long   rfi_ipsr;
 //    unsigned long   rfi_ifs;
-//     unsigned long   in_service[4];  // vLsapic inservice IRQ bits
     unsigned long   flags;
     unsigned long   xen_port;
+    unsigned char   xtp;
 #ifdef VTI_DEBUG
     unsigned long  ivt_current;
     struct ivt_debug ivt_debug[IVT_DEBUG_MAX];

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [IA64] Implement irq redirection of IOSAPIC, Xen patchbot-unstable <=