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

[Xen-changelog] Stack pal call emulation implemented. (by Tristan Gingold)



# HG changeset patch
# User djm@xxxxxxxxxxxxxxx
# Node ID eae5812f33f140ef14012776af502534b3655de3
# Parent  97de0e776d8b69d1c1e6db781eabacf03a5c504f
Stack pal call emulation implemented. (by Tristan Gingold)
PAL_HALT emulation added: stop machine if dom0, shutdown domain otherwise.

diff -r 97de0e776d8b -r eae5812f33f1 xen/arch/ia64/linux-xen/unaligned.c
--- a/xen/arch/ia64/linux-xen/unaligned.c       Fri Dec  2 16:27:22 2005
+++ b/xen/arch/ia64/linux-xen/unaligned.c       Fri Dec  2 18:12:11 2005
@@ -378,7 +378,7 @@
     if (ridx >= sof) {
         /* read of out-of-frame register returns an undefined value; 0 in our 
case.  */
         DPRINT("ignoring read from r%lu; only %lu registers are allocated!\n", 
r1, sof);
-        panic("wrong stack register number");
+        panic("wrong stack register number (iip=%p)\n", regs->cr_iip);
     }
 
     if (ridx < sor)
diff -r 97de0e776d8b -r eae5812f33f1 xen/arch/ia64/vmx/vmx_process.c
--- a/xen/arch/ia64/vmx/vmx_process.c   Fri Dec  2 16:27:22 2005
+++ b/xen/arch/ia64/vmx/vmx_process.c   Fri Dec  2 18:12:11 2005
@@ -53,8 +53,6 @@
 #define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034
 
 
-extern struct ia64_sal_retval pal_emulator_static(UINT64);
-extern struct ia64_sal_retval 
sal_emulator(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64);
 extern void rnat_consumption (VCPU *vcpu);
 #define DOMN_PAL_REQUEST    0x110000
 
@@ -110,14 +108,15 @@
        }
 #endif
        if (iim == d->arch.breakimm) {
-               struct ia64_sal_retval x;
+               struct ia64_pal_retval y;
+               struct sal_ret_values x;
                switch (regs->r2) {
                    case FW_HYPERCALL_PAL_CALL:
                        //printf("*** PAL hypercall: index=%d\n",regs->r28);
                        //FIXME: This should call a C routine
-                       x = pal_emulator_static(VCPU(v, vgr[12]));
-                       regs->r8 = x.status; regs->r9 = x.v0;
-                       regs->r10 = x.v1; regs->r11 = x.v2;
+                       y = pal_emulator_static(VCPU(v, vgr[12]));
+                       regs->r8 = y.status; regs->r9 = y.v0;
+                       regs->r10 = y.v1; regs->r11 = y.v2;
 #if 0
                        if (regs->r8)
                                printk("Failed vpal emulation, with 
index:0x%lx\n",
@@ -131,8 +130,8 @@
                                         sal_param[2], sal_param[3],
                                         sal_param[4], sal_param[5],
                                         sal_param[6], sal_param[7]);
-                       regs->r8 = x.status; regs->r9 = x.v0;
-                       regs->r10 = x.v1; regs->r11 = x.v2;
+                       regs->r8 = x.r8; regs->r9 = x.r9;
+                       regs->r10 = x.r10; regs->r11 = x.r11;
 #if 0
                        if (regs->r8)
                                printk("Failed vsal emulation, with 
index:0x%lx\n",
diff -r 97de0e776d8b -r eae5812f33f1 xen/arch/ia64/xen/dom_fw.c
--- a/xen/arch/ia64/xen/dom_fw.c        Fri Dec  2 16:27:22 2005
+++ b/xen/arch/ia64/xen/dom_fw.c        Fri Dec  2 18:12:11 2005
@@ -18,7 +18,7 @@
 
 #include <asm/dom_fw.h>
 
-struct ia64_boot_param *dom_fw_init(struct domain *, char *,int,char *,int);
+static struct ia64_boot_param *dom_fw_init(struct domain *, char *,int,char 
*,int);
 extern unsigned long domain_mpa_to_imva(struct domain *,unsigned long mpaddr);
 extern struct domain *dom0;
 extern unsigned long dom0_start;
@@ -56,13 +56,22 @@
 
 
 // builds a hypercall bundle at domain physical address
-void dom_fw_hypercall_patch(struct domain *d, unsigned long paddr, unsigned 
long hypercall,unsigned long ret)
+static void dom_fw_hypercall_patch(struct domain *d, unsigned long paddr, 
unsigned long hypercall,unsigned long ret)
 {
        unsigned long imva;
 
-       if (d == dom0) paddr += dom0_start;
        imva = domain_mpa_to_imva(d,paddr);
        build_hypercall_bundle(imva,d->arch.breakimm,hypercall,ret);
+}
+
+static void dom_fw_pal_hypercall_patch(struct domain *d, unsigned long paddr)
+{
+       unsigned long *imva;
+
+       imva = (unsigned long *)domain_mpa_to_imva(d,paddr);
+
+       build_pal_hypercall_bundles (imva, d->arch.breakimm,
+                                     FW_HYPERCALL_PAL_CALL);
 }
 
 
@@ -154,8 +163,6 @@
        tp->day = days + 1;
        return 1;
 }
-
-extern struct ia64_pal_retval pal_emulator_static (unsigned long);
 
 /* Macro to emulate SAL call using legacy IN and OUT calls to CF8, CFC etc.. */
 
@@ -293,11 +300,6 @@
        long status = -1;
 
        if (running_on_sim) return pal_emulator_static(index);
-       if (index >= PAL_COPY_PAL) {
-               // build_hypercall_bundle needs to be modified to generate
-               // a second bundle that conditionally does a br.ret
-               panic("xen_pal_emulator: stacked calls not supported!!\n");
-       }
        printk("xen_pal_emulator: index=%d\n",index);
        // pal code must be mapped by a TR when pal is called, however
        // calls are rare enough that we will map it lazily rather than
@@ -390,9 +392,26 @@
            case PAL_VM_TR_READ:        /* FIXME: vcpu_get_tr?? */
                printk("PAL_VM_TR_READ NOT IMPLEMENTED, IGNORED!\n");
                break;
-           case PAL_HALT_INFO:         /* inappropriate info for guest? */
-               printk("PAL_HALT_INFO NOT IMPLEMENTED, IGNORED!\n");
-               break;
+           case PAL_HALT_INFO:
+               {
+                   /* 1000 cycles to enter/leave low power state,
+                      consumes 10 mW, implemented and cache/TLB coherent.  */
+                   unsigned long res = 1000UL | (1000UL << 16) | (10UL << 32)
+                           | (1UL << 61) | (1UL << 60);
+                   if (copy_to_user ((void *)in1, &res, sizeof (res)))
+                           status = PAL_STATUS_EINVAL;    
+                   else
+                           status = PAL_STATUS_SUCCESS;
+               }
+               break;
+           case PAL_HALT:
+                   if (current->domain == dom0) {
+                           printf ("Domain0 halts the machine\n");
+                           (*efi.reset_system)(EFI_RESET_SHUTDOWN,0,0,NULL);
+                   }
+                   else
+                           domain_shutdown (current->domain, 0);
+                   break;
            default:
                printk("xen_pal_emulator: UNIMPLEMENTED PAL CALL %d!!!!\n",
                                index);
@@ -400,6 +419,7 @@
        }
        return ((struct ia64_pal_retval) {status, r9, r10, r11});
 }
+
 
 #define NFUNCPTRS 20
 
@@ -607,7 +627,7 @@
        return;
 }
 
-struct ia64_boot_param *
+static struct ia64_boot_param *
 dom_fw_init (struct domain *d, char *args, int arglen, char *fw_mem, int 
fw_mem_size)
 {
        efi_system_table_t *efi_systab;
@@ -615,7 +635,6 @@
        efi_config_table_t *efi_tables;
        struct ia64_sal_systab *sal_systab;
        efi_memory_desc_t *efi_memmap, *md;
-       unsigned long *pal_desc, *sal_desc;
        struct ia64_sal_desc_entry_point *sal_ed;
        struct ia64_boot_param *bp;
        unsigned long *pfn;
@@ -623,7 +642,7 @@
        char *cp, *cmd_line, *fw_vendor;
        int i = 0;
        unsigned long maxmem = (d->max_pages - d->arch.sys_pgnr) * PAGE_SIZE;
-       unsigned long start_mpaddr = ((d==dom0)?dom0_start:0);
+       const unsigned long start_mpaddr = ((d==dom0)?dom0_start:0);
 
 #      define MAKE_MD(typ, attr, start, end, abs)      \       
        do {                                            \
@@ -646,13 +665,6 @@
 */
        memset(fw_mem, 0, fw_mem_size);
 
-#ifdef USE_PAL_EMULATOR
-       pal_desc = (unsigned long *) &pal_emulator_static;
-#else
-       pal_desc = (unsigned long *) &xen_pal_emulator;
-#endif
-       sal_desc = (unsigned long *) &sal_emulator;
-
        cp = fw_mem;
        efi_systab  = (void *) cp; cp += sizeof(*efi_systab);
        efi_runtime = (void *) cp; cp += sizeof(*efi_runtime);
@@ -695,7 +707,7 @@
 #define EFI_HYPERCALL_PATCH(tgt,call) do { \
     
dom_efi_hypercall_patch(d,FW_HYPERCALL_##call##_PADDR,FW_HYPERCALL_##call); \
     tgt = dom_pa(pfn); \
-    *pfn++ = FW_HYPERCALL_##call##_PADDR + ((d==dom0)?dom0_start:0); \
+    *pfn++ = FW_HYPERCALL_##call##_PADDR + start_mpaddr; \
     *pfn++ = 0; \
     } while (0)
 
@@ -783,12 +795,10 @@
 
        /* fill in an entry point: */
        sal_ed->type = SAL_DESC_ENTRY_POINT;
-#define FW_HYPERCALL_PATCH(tgt,call,ret) do { \
-    
dom_fw_hypercall_patch(d,FW_HYPERCALL_##call##_PADDR,FW_HYPERCALL_##call,ret); \
-    tgt = FW_HYPERCALL_##call##_PADDR + ((d==dom0)?dom0_start:0); \
-    } while (0)
-       FW_HYPERCALL_PATCH(sal_ed->pal_proc,PAL_CALL,0);
-       FW_HYPERCALL_PATCH(sal_ed->sal_proc,SAL_CALL,1);
+       sal_ed->pal_proc = FW_HYPERCALL_PAL_CALL_PADDR + start_mpaddr;
+       dom_fw_pal_hypercall_patch (d, sal_ed->pal_proc);
+       sal_ed->sal_proc = FW_HYPERCALL_SAL_CALL_PADDR + start_mpaddr;
+       dom_fw_hypercall_patch (d, sal_ed->sal_proc, FW_HYPERCALL_SAL_CALL, 1);
        sal_ed->gp = 0;  // will be ignored
 
        for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp)
diff -r 97de0e776d8b -r eae5812f33f1 xen/arch/ia64/xen/hypercall.c
--- a/xen/arch/ia64/xen/hypercall.c     Fri Dec  2 16:27:22 2005
+++ b/xen/arch/ia64/xen/hypercall.c     Fri Dec  2 18:12:11 2005
@@ -18,8 +18,6 @@
 #include <public/sched.h>
 
 extern unsigned long translate_domain_mpaddr(unsigned long);
-extern struct ia64_pal_retval xen_pal_emulator(UINT64,UINT64,UINT64,UINT64);
-extern struct ia64_sal_retval 
sal_emulator(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64);
 
 unsigned long idle_when_pending = 0;
 unsigned long pal_halt_light_count = 0;
@@ -28,8 +26,7 @@
 ia64_hypercall (struct pt_regs *regs)
 {
        struct vcpu *v = (struct domain *) current;
-       struct ia64_sal_retval x;
-       struct ia64_pal_retval y;
+       struct sal_ret_values x;
        unsigned long *tv, *tc;
        int pi;
 
@@ -62,25 +59,33 @@
                                pal_halt_light_count++;
                                do_sched_op(SCHEDOP_yield);
                        }
-                       //break;
+                       regs->r8 = 0;
+                       regs->r9 = 0;
+                       regs->r10 = 0;
+                       regs->r11 = 0;
                }
-               else if (regs->r28 >= PAL_COPY_PAL) {   /* FIXME */
-                       printf("stacked PAL hypercalls not supported\n");
-                       regs->r8 = -1;
-                       break;
+               else {
+                       struct ia64_pal_retval y;
+
+                       if (regs->r28 >= PAL_COPY_PAL)
+                               y = xen_pal_emulator
+                                       (regs->r28, vcpu_get_gr (v, 33),
+                                        vcpu_get_gr (v, 34),
+                                        vcpu_get_gr (v, 35));
+                       else
+                               y = xen_pal_emulator(regs->r28,regs->r29,
+                                                    regs->r30,regs->r31);
+                       regs->r8 = y.status; regs->r9 = y.v0;
+                       regs->r10 = y.v1; regs->r11 = y.v2;
                }
-               else y = xen_pal_emulator(regs->r28,regs->r29,
-                                               regs->r30,regs->r31);
-               regs->r8 = y.status; regs->r9 = y.v0;
-               regs->r10 = y.v1; regs->r11 = y.v2;
                break;
            case FW_HYPERCALL_SAL_CALL:
                x = sal_emulator(vcpu_get_gr(v,32),vcpu_get_gr(v,33),
                        vcpu_get_gr(v,34),vcpu_get_gr(v,35),
                        vcpu_get_gr(v,36),vcpu_get_gr(v,37),
                        vcpu_get_gr(v,38),vcpu_get_gr(v,39));
-               regs->r8 = x.status; regs->r9 = x.v0;
-               regs->r10 = x.v1; regs->r11 = x.v2;
+               regs->r8 = x.r8; regs->r9 = x.r9;
+               regs->r10 = x.r10; regs->r11 = x.r11;
                break;
            case FW_HYPERCALL_EFI_RESET_SYSTEM:
                printf("efi.reset_system called ");
diff -r 97de0e776d8b -r eae5812f33f1 xen/arch/ia64/xen/privop.c
--- a/xen/arch/ia64/xen/privop.c        Fri Dec  2 16:27:22 2005
+++ b/xen/arch/ia64/xen/privop.c        Fri Dec  2 18:12:11 2005
@@ -10,6 +10,7 @@
 #include <asm/vcpu.h>
 #include <asm/processor.h>
 #include <asm/delay.h> // Debug only
+#include <asm/dom_fw.h>
 //#include <debug.h>
 
 long priv_verbose=0;
@@ -53,6 +54,39 @@
        
        *imva++ = bundle.i64[0]; *imva = bundle.i64[1];
 }
+
+void build_pal_hypercall_bundles(UINT64 *imva, UINT64 brkimm, UINT64 hypnum)
+{
+       extern unsigned long pal_call_stub[];
+       IA64_BUNDLE bundle;
+       INST64_A5 slot_a5;
+       INST64_M37 slot_m37;
+
+       /* The source of the hypercall stub is the pal_call_stub function
+          defined in xenasm.S.  */
+
+       /* Copy the first bundle and patch the hypercall number.  */
+       bundle.i64[0] = pal_call_stub[0];
+       bundle.i64[1] = pal_call_stub[1];
+       slot_a5.inst = bundle.slot0;
+       slot_a5.imm7b = hypnum;
+       slot_a5.imm9d = hypnum >> 7;
+       slot_a5.imm5c = hypnum >> 16;
+       bundle.slot0 = slot_a5.inst;
+       imva[0] = bundle.i64[0];
+       imva[1] = bundle.i64[1];
+       
+       /* Copy the second bundle and patch the hypercall vector.  */
+       bundle.i64[0] = pal_call_stub[2];
+       bundle.i64[1] = pal_call_stub[3];
+       slot_m37.inst = bundle.slot0;
+       slot_m37.imm20a = brkimm;
+       slot_m37.i = brkimm >> 20;
+       bundle.slot0 = slot_m37.inst;
+       imva[2] = bundle.i64[0];
+       imva[3] = bundle.i64[1];
+}
+
 
 /**************************************************************************
 Privileged operation emulation routines
diff -r 97de0e776d8b -r eae5812f33f1 xen/arch/ia64/xen/process.c
--- a/xen/arch/ia64/xen/process.c       Fri Dec  2 16:27:22 2005
+++ b/xen/arch/ia64/xen/process.c       Fri Dec  2 18:12:11 2005
@@ -33,8 +33,6 @@
 #include <xen/multicall.h>
 
 extern unsigned long vcpu_get_itir_on_fault(struct vcpu *, UINT64);
-extern struct ia64_sal_retval pal_emulator_static(UINT64);
-extern struct ia64_sal_retval 
sal_emulator(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64);
 
 extern unsigned long dom0_start, dom0_size;
 
diff -r 97de0e776d8b -r eae5812f33f1 xen/arch/ia64/xen/xenasm.S
--- a/xen/arch/ia64/xen/xenasm.S        Fri Dec  2 16:27:22 2005
+++ b/xen/arch/ia64/xen/xenasm.S        Fri Dec  2 18:12:11 2005
@@ -516,3 +516,27 @@
        br.ret.sptk.few rp
        ;;
 END(vhpt_insert)
+
+//  These instructions are copied in the domains.
+//  This is the virtual PAL, which simply does an hypercall.
+//  The size is 2 bunldes (32 Bytes).  It handles both static and stacked
+//    convention.
+//  If you modify this code, you have to modify dom_fw.h (for the size) and
+//   dom_fw_pal_hypercall_patch.
+GLOBAL_ENTRY(pal_call_stub)
+       {
+        .mii
+       addl r2=0x1000,r0       //  Hypercall number (Value is patched).
+       mov r9=256
+       ;; 
+       cmp.gtu p7,p8=r9,r28            /* r32 <= 255? */
+       }
+       {
+        .mbb
+       break 0x1000    //  Hypercall vector (Value is patched).
+(p7)   br.cond.sptk.few rp
+(p8)   br.ret.sptk.few rp
+       }
+END(pal_call_stub)
+
+
diff -r 97de0e776d8b -r eae5812f33f1 xen/arch/ia64/xen/xenmisc.c
--- a/xen/arch/ia64/xen/xenmisc.c       Fri Dec  2 16:27:22 2005
+++ b/xen/arch/ia64/xen/xenmisc.c       Fri Dec  2 18:12:11 2005
@@ -141,10 +141,12 @@
     //memset(percpu_info, 0, sizeof(percpu_info));
 }
 
+#if 0
 void free_page_type(struct pfn_info *page, unsigned int type)
 {
        dummy();
 }
+#endif
 
 ///////////////////////////////
 //// misc memory stuff
diff -r 97de0e776d8b -r eae5812f33f1 xen/include/asm-ia64/dom_fw.h
--- a/xen/include/asm-ia64/dom_fw.h     Fri Dec  2 16:27:22 2005
+++ b/xen/include/asm-ia64/dom_fw.h     Fri Dec  2 18:12:11 2005
@@ -35,6 +35,7 @@
  * rp=b0 indicates the return point.
  *
  * A single hypercall is used for all PAL calls.
+ * The hypercall stub is pal_call_stub (xenasm.S).  Its size is 2 bundles.
  */
 
 #define FW_HYPERCALL_PAL_CALL_INDEX    0x80UL
@@ -53,7 +54,7 @@
  * A single hypercall is used for all SAL calls.
  */
 
-#define FW_HYPERCALL_SAL_CALL_INDEX    0x81UL
+#define FW_HYPERCALL_SAL_CALL_INDEX    0x82UL
 #define FW_HYPERCALL_SAL_CALL_PADDR    
FW_HYPERCALL_PADDR(FW_HYPERCALL_SAL_CALL_INDEX)
 #define FW_HYPERCALL_SAL_CALL          0x1001UL
 
@@ -117,3 +118,12 @@
 #define FW_HYPERCALL_EFI_SET_VARIABLE_PADDR            
FW_HYPERCALL_PADDR(FW_HYPERCALL_EFI_SET_VARIABLE_INDEX)
 #define FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT_PADDR        
FW_HYPERCALL_PADDR(FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT_INDEX)
 #define FW_HYPERCALL_EFI_RESET_SYSTEM_PADDR            
FW_HYPERCALL_PADDR(FW_HYPERCALL_EFI_RESET_SYSTEM_INDEX)
+
+extern struct ia64_pal_retval xen_pal_emulator(UINT64,UINT64,UINT64,UINT64);
+extern struct sal_ret_values sal_emulator (long index, unsigned long in1, 
unsigned long in2, unsigned long in3, unsigned long in4, unsigned long in5, 
unsigned long in6, unsigned long in7);
+extern struct ia64_pal_retval pal_emulator_static (unsigned long);
+
+extern void build_pal_hypercall_bundles(unsigned long *imva, unsigned long 
brkimm, unsigned long hypnum);
+extern void build_hypercall_bundle(UINT64 *imva, UINT64 brkimm, UINT64 hypnum, 
UINT64 ret);
+
+
diff -r 97de0e776d8b -r eae5812f33f1 xen/include/asm-ia64/privop.h
--- a/xen/include/asm-ia64/privop.h     Fri Dec  2 16:27:22 2005
+++ b/xen/include/asm-ia64/privop.h     Fri Dec  2 18:12:11 2005
@@ -99,6 +99,11 @@
     IA64_INST inst;
     struct { unsigned long qp:6, r1:7, :14, x6:6, x3:3, :1, major:4; }; 
 } INST64_M36;
+
+typedef union U_INST64_M37 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, imm20a:20,:1, x4:4,x2:2,x3:3, i:1, major:4; };
+} INST64_M37;
 
 typedef union U_INST64_M41 {
     IA64_INST inst;
@@ -190,6 +195,7 @@
     INST64_M33 M33;    // mov from cr
     INST64_M35 M35;    // mov to psr
     INST64_M36 M36;    // mov from psr
+    INST64_M37 M37;    // break.m
     INST64_M41 M41;    // translation cache insert
     INST64_M42 M42;    // mov to indirect reg/translation reg insert
     INST64_M43 M43;    // mov from indirect reg

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