# 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
|