# HG changeset patch # User tristan.gingold@xxxxxxxx # Node ID 86a9e061530f0c2780a3e640e0b5fc7fefcb733d # Parent 0ee00faf332d4f9eb828ab1ca7b846787d77b2ca Stack pal call emulation implemented. PAL_HALT emulation added: stop machine if dom0, shutdown domain otherwise. diff -r 0ee00faf332d -r 86a9e061530f xen/arch/ia64/linux-xen/unaligned.c --- a/xen/arch/ia64/linux-xen/unaligned.c Wed Nov 23 21:23:28 2005 +++ b/xen/arch/ia64/linux-xen/unaligned.c Fri Nov 25 11:49:38 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 0ee00faf332d -r 86a9e061530f xen/arch/ia64/vmx/vmx_process.c --- a/xen/arch/ia64/vmx/vmx_process.c Wed Nov 23 21:23:28 2005 +++ b/xen/arch/ia64/vmx/vmx_process.c Fri Nov 25 11:49:38 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 0ee00faf332d -r 86a9e061530f xen/arch/ia64/xen/dom_fw.c --- a/xen/arch/ia64/xen/dom_fw.c Wed Nov 23 21:23:28 2005 +++ b/xen/arch/ia64/xen/dom_fw.c Fri Nov 25 11:49:38 2005 @@ -18,7 +18,7 @@ #include -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 0ee00faf332d -r 86a9e061530f xen/arch/ia64/xen/hypercall.c --- a/xen/arch/ia64/xen/hypercall.c Wed Nov 23 21:23:28 2005 +++ b/xen/arch/ia64/xen/hypercall.c Fri Nov 25 11:49:38 2005 @@ -18,8 +18,6 @@ #include 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 0ee00faf332d -r 86a9e061530f xen/arch/ia64/xen/privop.c --- a/xen/arch/ia64/xen/privop.c Wed Nov 23 21:23:28 2005 +++ b/xen/arch/ia64/xen/privop.c Fri Nov 25 11:49:38 2005 @@ -10,6 +10,7 @@ #include #include #include // Debug only +#include //#include 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 0ee00faf332d -r 86a9e061530f xen/arch/ia64/xen/process.c --- a/xen/arch/ia64/xen/process.c Wed Nov 23 21:23:28 2005 +++ b/xen/arch/ia64/xen/process.c Fri Nov 25 11:49:38 2005 @@ -33,8 +33,6 @@ #include 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 0ee00faf332d -r 86a9e061530f xen/arch/ia64/xen/xenasm.S --- a/xen/arch/ia64/xen/xenasm.S Wed Nov 23 21:23:28 2005 +++ b/xen/arch/ia64/xen/xenasm.S Fri Nov 25 11:49:38 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 0ee00faf332d -r 86a9e061530f xen/arch/ia64/xen/xenmisc.c --- a/xen/arch/ia64/xen/xenmisc.c Wed Nov 23 21:23:28 2005 +++ b/xen/arch/ia64/xen/xenmisc.c Fri Nov 25 11:49:38 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 0ee00faf332d -r 86a9e061530f xen/include/asm-ia64/dom_fw.h --- a/xen/include/asm-ia64/dom_fw.h Wed Nov 23 21:23:28 2005 +++ b/xen/include/asm-ia64/dom_fw.h Fri Nov 25 11:49:38 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 0ee00faf332d -r 86a9e061530f xen/include/asm-ia64/privop.h --- a/xen/include/asm-ia64/privop.h Wed Nov 23 21:23:28 2005 +++ b/xen/include/asm-ia64/privop.h Fri Nov 25 11:49:38 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