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

[Xen-changelog] [xen-unstable] [IA64] New SIOEmu interface: pass callback data in memory.



# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1206044949 21600
# Node ID e768be7bf56162347c1facf3b71e88d19f639599
# Parent  6bdb343977010df67469be15bb88dce7d93668bb
[IA64] New SIOEmu interface: pass callback data in memory.

This fixes lost data for callback while hypercall case.

Signed-off-by: Tristan Gingold <tgingold@xxxxxxx>
---
 xen/arch/ia64/asm-offsets.c           |    2 
 xen/arch/ia64/vmx/sioemu.c            |  206 +++++++++++++---------------------
 xen/arch/ia64/vmx/vmx_fault.c         |    4 
 xen/arch/ia64/vmx/vmx_init.c          |    4 
 xen/include/asm-ia64/sioemu.h         |    2 
 xen/include/asm-ia64/vmx_vpd.h        |    8 -
 xen/include/public/arch-ia64/sioemu.h |   31 +++--
 7 files changed, 114 insertions(+), 143 deletions(-)

diff -r 6bdb34397701 -r e768be7bf561 xen/arch/ia64/asm-offsets.c
--- a/xen/arch/ia64/asm-offsets.c       Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/arch/ia64/asm-offsets.c       Thu Mar 20 14:29:09 2008 -0600
@@ -150,6 +150,8 @@ void foo(void)
        DEFINE(IA64_VCPU_OPCODE_OFFSET, offsetof (struct vcpu, 
arch.arch_vmx.opcode));
        DEFINE(SWITCH_MPTA_OFFSET,offsetof(struct vcpu ,arch.arch_vmx.mpta));
        DEFINE(IA64_PT_REGS_R16_SLOT, (((offsetof(struct pt_regs, 
r16)-sizeof(struct pt_regs))>>3)&0x3f));
+       DEFINE(IA64_PT_REGS_R2_SLOT, (((offsetof(struct pt_regs, 
r16)-sizeof(struct pt_regs))>>3)&0x3f));
+       DEFINE(IA64_PT_REGS_R8_SLOT, (((offsetof(struct pt_regs, 
r16)-sizeof(struct pt_regs))>>3)&0x3f));
        DEFINE(IA64_VCPU_FLAGS_OFFSET,offsetof(struct vcpu 
,arch.arch_vmx.flags));
        DEFINE(IA64_VCPU_MMU_MODE_OFFSET,offsetof(struct vcpu, 
arch.arch_vmx.mmu_mode));
 
diff -r 6bdb34397701 -r e768be7bf561 xen/arch/ia64/vmx/sioemu.c
--- a/xen/arch/ia64/vmx/sioemu.c        Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/arch/ia64/vmx/sioemu.c        Thu Mar 20 14:29:09 2008 -0600
@@ -26,171 +26,137 @@
 #include <asm/sal.h>
 #include <asm/vlsapic.h>
 
-static void
-sioemu_save_regs (VCPU *vcpu)
-{
-    REGS *regs = vcpu_regs(vcpu);
-
-    vcpu->arch.arch_vmx.stub_saved[0] = regs->r16;
-    vcpu->arch.arch_vmx.stub_saved[1] = regs->r17;
-    vcpu->arch.arch_vmx.stub_saved[2] = regs->r18;
-    vcpu->arch.arch_vmx.stub_saved[3] = regs->r19;
-    vcpu->arch.arch_vmx.stub_saved[4] = regs->r20;
-    vcpu->arch.arch_vmx.stub_saved[5] = regs->r21;
-    vcpu->arch.arch_vmx.stub_saved[6] = regs->r22;
-    vcpu->arch.arch_vmx.stub_saved[7] = regs->r23;
-    vcpu->arch.arch_vmx.stub_saved[8] = regs->r24;
-    vcpu->arch.arch_vmx.stub_saved[9] = regs->r25;
-    vcpu->arch.arch_vmx.stub_saved[10] = regs->r26;
-    vcpu->arch.arch_vmx.stub_saved[11] = regs->r27;
-    vcpu->arch.arch_vmx.stub_saved[12] = regs->r28;
-    vcpu->arch.arch_vmx.stub_saved[13] = regs->r29;
-    vcpu->arch.arch_vmx.stub_saved[14] = regs->r30;
-    vcpu->arch.arch_vmx.stub_saved[15] = regs->r31;
-    vcpu->arch.arch_vmx.stub_nats =
-        (regs->eml_unat >> IA64_PT_REGS_R16_SLOT) & 0xffff;
-}
-
-static void
-sioemu_restore_regs (VCPU *vcpu)
-{
-    REGS *regs = vcpu_regs(vcpu);
-
-    /* First restore registers.  */
-    regs->cr_iip = regs->r28;
-    regs->cr_ifs = regs->r30;
-    vmx_vcpu_set_psr (vcpu, regs->r29);
-
-    regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT);
-    regs->eml_unat |= vcpu->arch.arch_vmx.stub_nats << IA64_PT_REGS_R16_SLOT;
-
-    regs->r16 = vcpu->arch.arch_vmx.stub_saved[0];
-    regs->r17 = vcpu->arch.arch_vmx.stub_saved[1];
-    regs->r18 = vcpu->arch.arch_vmx.stub_saved[2];
-    regs->r19 = vcpu->arch.arch_vmx.stub_saved[3];
-    regs->r20 = vcpu->arch.arch_vmx.stub_saved[4];
-    regs->r21 = vcpu->arch.arch_vmx.stub_saved[5];
-    regs->r22 = vcpu->arch.arch_vmx.stub_saved[6];
-    regs->r23 = vcpu->arch.arch_vmx.stub_saved[7];
-    regs->r24 = vcpu->arch.arch_vmx.stub_saved[8];
-    regs->r25 = vcpu->arch.arch_vmx.stub_saved[9];
-    regs->r26 = vcpu->arch.arch_vmx.stub_saved[10];
-    regs->r27 = vcpu->arch.arch_vmx.stub_saved[11];
-    regs->r28 = vcpu->arch.arch_vmx.stub_saved[12];
-    regs->r29 = vcpu->arch.arch_vmx.stub_saved[13];
-    regs->r30 = vcpu->arch.arch_vmx.stub_saved[14];
-    regs->r31 = vcpu->arch.arch_vmx.stub_saved[15];
-
-}
-
-static REGS *
+struct sioemu_callback_info *
 sioemu_deliver (void)
 {
     VCPU *vcpu = current;
     REGS *regs = vcpu_regs(vcpu);
+    struct sioemu_callback_info *info = vcpu->arch.arch_vmx.sioemu_info_mva;
     unsigned long psr = vmx_vcpu_get_psr(vcpu);
 
     if (vcpu->vcpu_info->evtchn_upcall_mask)
         panic_domain (NULL, "sioemu_deliver: aleady in stub mode\n");
+    if (info == NULL)
+        panic_domain (NULL, "sioemu_deliver: set_callback not called\n");
 
     /* All cleared, but keep BN.  */
     vmx_vcpu_set_psr(vcpu, IA64_PSR_MC | (psr & IA64_PSR_BN));
 
-    /* Save registers. */
-    sioemu_save_regs (vcpu);
-
-    /* Context. */
-    regs->r28 = regs->cr_iip;
-    regs->r29 = psr;
-    regs->r30 = regs->cr_ifs;
+    /* Set info.  */
+    info->ip = regs->cr_iip;
+    info->psr = psr;
+    info->ifs = regs->cr_ifs;
+    info->nats = (((regs->eml_unat >> IA64_PT_REGS_R8_SLOT) & 0x0f) << 8)
+        | (((regs->eml_unat >> IA64_PT_REGS_R2_SLOT) & 1) << 2);
+    info->r8 = regs->r8;
+    info->r9 = regs->r9;
+    info->r10 = regs->r10;
+    info->r11 = regs->r11;
+    info->r2 = regs->r2;
 
     regs->cr_ifs = 0;  // pre-cover
-
     regs->cr_iip = vcpu->arch.event_callback_ip;
-    regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT);
-
-    /* Parameters.  */
-    regs->r16 = 0;
-    regs->r17 = vcpu->arch.arch_vmx.stub_buffer;
+    regs->eml_unat &= ~(1UL << IA64_PT_REGS_R8_SLOT);
+    regs->r8 = vcpu->arch.arch_vmx.sioemu_info_gpa;
 
     /* Mask events.  */
     vcpu->vcpu_info->evtchn_upcall_mask = 1;
 
     debugger_event(XEN_IA64_DEBUG_ON_EVENT);
 
-    return regs;
-}
-
-void
+    return info;
+}
+
+static void
 sioemu_callback_return (void)
 {
     VCPU *vcpu = current;
     REGS *regs = vcpu_regs(vcpu);
-    u64 cmd = regs->r16;
-    u64 arg1 = regs->r19;
-    u64 arg2 = regs->r20;
-    u64 arg3 = regs->r21;
-
-    if ((cmd & ~0x1UL) != 0)
+    struct sioemu_callback_info *info = vcpu->arch.arch_vmx.sioemu_info_mva;
+
+    if (info == NULL)
+        panic_domain (NULL, "sioemu_deliver: set_callback not called\n");
+    if ((info->cause & ~0x1UL) != 0)
         panic_domain (NULL, "sioemu_callback_return: bad operation (%lx)\n",
-                      cmd);
+                      info->cause);
 
     /* First restore registers.  */
-    regs->cr_iip = regs->r28;
-    regs->cr_ifs = regs->r30;
-    vmx_vcpu_set_psr (vcpu, regs->r29);
-
-    sioemu_restore_regs (vcpu);
+    regs->cr_iip = info->ip;
+    regs->cr_ifs = info->ifs;
+    vmx_vcpu_set_psr (vcpu, info->psr);
+    regs->r8 = info->r8;
+    regs->r9 = info->r9;
+    regs->r10 = info->r10;
+    regs->r11 = info->r11;
+    regs->r2 = info->r2;
+    regs->eml_unat &= ~((0x0fUL << IA64_PT_REGS_R8_SLOT)
+                        | (1UL << IA64_PT_REGS_R2_SLOT));
+    regs->eml_unat |= (((info->nats >> 8) & 0x0f) << IA64_PT_REGS_R8_SLOT)
+        | (((info->nats >> 2) & 1) << IA64_PT_REGS_R2_SLOT);
 
     /* Unmask events.  */
     vcpu->vcpu_info->evtchn_upcall_mask = 0;
 
     /* Then apply commands.  */
-    if (cmd & 1) {
-        emulate_io_update (vcpu, arg1, arg2, arg3);
+    if (info->cause & 1) {
+        emulate_io_update (vcpu, info->arg0, info->arg1, info->arg2);
     }
 }
 
 void
 sioemu_deliver_event (void)
 {
-    REGS *regs;
-
-    regs = sioemu_deliver ();
-    regs->r16 = SIOEMU_CB_EVENT;
+    struct sioemu_callback_info *info;
+
+    info = sioemu_deliver ();
+    info->cause = SIOEMU_CB_EVENT;
 }
 
 void
 sioemu_io_emulate (unsigned long padr, unsigned long data,
                   unsigned long data1, unsigned long word)
 {
-    REGS *regs;
-
-    regs = sioemu_deliver ();
-    regs->r16 = SIOEMU_CB_IO_EMULATE;
-    regs->r19 = padr;
-    regs->r20 = data;
-    regs->r21 = data1;
-    regs->r22 = word;
-}
-
-void
-sioemu_wakeup_vcpu (int vcpu_id)
-{
-    REGS *regs;
-
-    regs = sioemu_deliver();
-    regs->r16 = SIOEMU_CB_WAKEUP_VCPU;
-    regs->r19 = vcpu_id;
+    struct sioemu_callback_info *info;
+
+    info = sioemu_deliver ();
+    info->cause = SIOEMU_CB_IO_EMULATE;
+    info->arg0 = padr;
+    info->arg1 = data;
+    info->arg2 = data1;
+    info->arg3 = word;
 }
 
 void
 sioemu_sal_assist (struct vcpu *v)
 {
-    REGS *regs;
-
-    regs = sioemu_deliver();
-    regs->r16 = SIOEMU_CB_SAL_ASSIST;
+    struct sioemu_callback_info *info;
+
+    info = sioemu_deliver ();
+    info->cause = SIOEMU_CB_SAL_ASSIST;
+}
+
+static int
+sioemu_set_callback (struct vcpu *v, unsigned long cb_ip, unsigned long paddr)
+{
+    struct page_info *page;
+    unsigned long mfn;
+    pte_t pte;
+
+    v->arch.event_callback_ip = cb_ip;
+    if ((paddr & 0xfff) || v->arch.arch_vmx.sioemu_info_mva)
+        return -EINVAL;
+    pte = *lookup_noalloc_domain_pte(v->domain, paddr);
+    if (!pte_present(pte) || !pte_mem(pte))
+        return -EINVAL;
+    mfn = (pte_val(pte) & _PFN_MASK) >> PAGE_SHIFT;
+    ASSERT(mfn_valid(mfn));
+
+    page = mfn_to_page(mfn);
+    if (get_page(page, v->domain) == 0)
+        return -EINVAL;
+    v->arch.arch_vmx.sioemu_info_gpa = paddr;
+    v->arch.arch_vmx.sioemu_info_mva = mfn_to_virt(mfn);
+    return 0;
 }
 
 static int
@@ -234,8 +200,7 @@ sioemu_hypercall (struct pt_regs *regs)
     switch (regs->r2 & FW_HYPERCALL_NUM_MASK_LOW)
     {
     case SIOEMU_HYPERCALL_SET_CALLBACK:
-        current->arch.event_callback_ip = regs->r8;
-        current->arch.arch_vmx.stub_buffer = regs->r9;
+        regs->r8 = sioemu_set_callback(current, regs->r8, regs->r9);
         break;
     case SIOEMU_HYPERCALL_START_FW:
         regs->cr_iip = regs->r8;
@@ -254,12 +219,6 @@ sioemu_hypercall (struct pt_regs *regs)
         regs->r9 = now;
         break;
     }
-    case SIOEMU_HYPERCALL_GET_REGS:
-        sioemu_restore_regs(current);
-        break;
-    case SIOEMU_HYPERCALL_SET_REGS:
-        sioemu_save_regs(current);
-        break;
     case SIOEMU_HYPERCALL_FLUSH_CACHE:
         regs->r8 = ia64_sal_cache_flush(regs->r8);
         break;
@@ -271,7 +230,6 @@ sioemu_hypercall (struct pt_regs *regs)
                                        regs->r8, regs->r9, regs->r10);
         break;
     case SIOEMU_HYPERCALL_CALLBACK_RETURN:
-        regs->r2 = regs->r27;
         sioemu_callback_return ();
         vcpu_decrement_iip(current);
         break;
diff -r 6bdb34397701 -r e768be7bf561 xen/arch/ia64/vmx/vmx_fault.c
--- a/xen/arch/ia64/vmx/vmx_fault.c     Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/arch/ia64/vmx/vmx_fault.c     Thu Mar 20 14:29:09 2008 -0600
@@ -215,10 +215,6 @@ vmx_ia64_handle_break (unsigned long ifa
                 vcpu_increment_iip(v);
             }
             return IA64_NO_FAULT;
-        } else if (d->arch.is_sioemu
-                   && iim == SIOEMU_HYPERPRIVOP_CALLBACK_RETURN) {
-            sioemu_callback_return ();
-            return IA64_NO_FAULT;
         }
     }
     vmx_reflect_interruption(ifa, isr, iim, 11, regs);
diff -r 6bdb34397701 -r e768be7bf561 xen/arch/ia64/vmx/vmx_init.c
--- a/xen/arch/ia64/vmx/vmx_init.c      Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/arch/ia64/vmx/vmx_init.c      Thu Mar 20 14:29:09 2008 -0600
@@ -540,6 +540,10 @@ vmx_relinquish_vcpu_resources(struct vcp
 
        kill_timer(&vtm->vtm_timer);
 
+       if (v->arch.arch_vmx.sioemu_info_mva)
+               put_page(virt_to_page((unsigned long)
+                                     v->arch.arch_vmx.sioemu_info_mva));
+
        free_domain_tlb(v);
        free_vpd(v);
 }
diff -r 6bdb34397701 -r e768be7bf561 xen/include/asm-ia64/sioemu.h
--- a/xen/include/asm-ia64/sioemu.h     Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/include/asm-ia64/sioemu.h     Thu Mar 20 14:29:09 2008 -0600
@@ -23,9 +23,7 @@
 #define __ASM_SIOEMU_H_
 extern void sioemu_hypercall (struct pt_regs *regs);
 extern void sioemu_deliver_event (void);
-extern void sioemu_callback_return (void);
 extern void sioemu_io_emulate (unsigned long padr, unsigned long data,
                               unsigned long data1, unsigned long word);
-extern void sioemu_wakeup_vcpu (int vcpu_id);
 extern void sioemu_sal_assist (struct vcpu *v);
 #endif /* __ASM_SIOEMU_H_ */
diff -r 6bdb34397701 -r e768be7bf561 xen/include/asm-ia64/vmx_vpd.h
--- a/xen/include/asm-ia64/vmx_vpd.h    Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/include/asm-ia64/vmx_vpd.h    Thu Mar 20 14:29:09 2008 -0600
@@ -40,6 +40,8 @@
 #include <public/xen.h>
 #include <xen/spinlock.h>
 
+struct sioemu_callback_info;
+
 #define VPD_SHIFT      16
 #define VPD_SIZE       (1 << VPD_SHIFT)
 
@@ -74,9 +76,9 @@ struct arch_vmx_struct {
     unsigned long  ivt_current;
     struct ivt_debug ivt_debug[IVT_DEBUG_MAX];
 #endif
-    unsigned long stub_saved[16];
-    unsigned long stub_buffer;
-    unsigned int  stub_nats;
+    /* sioemu info buffer.  */
+    unsigned long sioemu_info_gpa;
+    struct sioemu_callback_info *sioemu_info_mva;
 };
 
 #define VMX_DOMAIN(v)   v->arch.arch_vmx.flags
diff -r 6bdb34397701 -r e768be7bf561 xen/include/public/arch-ia64/sioemu.h
--- a/xen/include/public/arch-ia64/sioemu.h     Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/include/public/arch-ia64/sioemu.h     Thu Mar 20 14:29:09 2008 -0600
@@ -38,10 +38,6 @@
 /* Get wallclock time.  */
 #define SIOEMU_HYPERCALL_GET_TIME 0x04
 
-/* Get/Set shadow registers.  */
-#define SIOEMU_HYPERCALL_GET_REGS 0x05
-#define SIOEMU_HYPERCALL_SET_REGS 0x06
-
 /* Flush cache.  */
 #define SIOEMU_HYPERCALL_FLUSH_CACHE 0x07
 
@@ -68,11 +64,26 @@
 /* A SAL hypercall is executed.  */
 #define SIOEMU_CB_SAL_ASSIST  0x03
 
+#ifndef __ASSEMBLY__
+struct sioemu_callback_info {
+    /* Saved registers.  */
+    unsigned long ip;
+    unsigned long psr;
+    unsigned long ifs;
+    unsigned long nats;
+    unsigned long r8;
+    unsigned long r9;
+    unsigned long r10;
+    unsigned long r11;
 
-/* SIOEMU firmware mode hypercalls.  */
-
-/* Return from callback.  r16=0.
-   Unmask vcpu events.  */
-#define SIOEMU_HYPERPRIVOP_CALLBACK_RETURN 0x01
-
+    /* Callback parameters.  */
+    unsigned long cause;
+    unsigned long arg0;
+    unsigned long arg1;
+    unsigned long arg2;
+    unsigned long arg3;
+    unsigned long _pad2[2];
+    unsigned long r2;
+};
+#endif /* __ASSEMBLY__ */
 #endif /* __XEN_PUBLIC_IA64_SIOEMU_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®.