This patch is a first cut at implementing Yamahata-san's idea of
assigning a special RID for use with EFI mappings. The basic
idea is to switch to this RID, which is in the range reserved
for the hypervisor, before making EFI, PAL or SAL calls. The page
fault handler where the identity mapping checks for this RID, if
present it does the identity mapping, else it just follows the normal
mapping rules. In this way, VMX domains should not be able to access
this memory, and they should be able to use the virtual addresses
that are used by EFI for their own purposes.
The patch does seem to work, in the sense that the EFI mappings work.
I have not stress tested it to see if domains can still do nefarious
things. I would appreciate a review of this.
Cc: Tristan Gingold <tgingold@xxxxxxx>
Cc: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
---
Tue, 23 Oct 2007 15:47:27 +0900
* Don't use #ifndef XEN to denote changes to SAL, PAL and EFI macros,
as this means that the macros have to be duplicated which leads to
a very bulky patch. Instead, define the new functionality as
XEN_EFI_RR_SAVE and XEN_EFI_RR_RESTORE (previously EFI_RR_SAV and
EFI_RR_RESTOR) and put these macros straight into the existing macros -
this should be obvious enough for future up-porters.
As suggested by Alex Williamson.
* Break header changes out into a separate patch
* Break macro definitions out into a separate patch and
put them in efi.h instead of pal.h. Documentation of how the
EFI RID is selected is included in this new patch.
* Use a uniform defineition of XEN_EFI_RID in assembly and C code
Index: xen-unstable.hg/xen/include/asm-ia64/linux/asm/sal.h
===================================================================
--- xen-unstable.hg.orig/xen/include/asm-ia64/linux/asm/sal.h 2007-10-23
16:20:06.000000000 +0900
+++ xen-unstable.hg/xen/include/asm-ia64/linux/asm/sal.h 2007-10-23
16:23:46.000000000 +0900
@@ -52,9 +52,12 @@ extern spinlock_t sal_lock;
# define SAL_CALL(result,args...) do { \
unsigned long __ia64_sc_flags; \
struct ia64_fpreg __ia64_sc_fr[6]; \
+ int rr6, rr7; \
ia64_save_scratch_fpregs(__ia64_sc_fr); \
spin_lock_irqsave(&sal_lock, __ia64_sc_flags); \
+ XEN_EFI_RR_SAVE(rr6, rr7); \
__SAL_CALL(result, args); \
+ XEN_EFI_RR_RESTORE(rr6, rr7); \
spin_unlock_irqrestore(&sal_lock, __ia64_sc_flags); \
ia64_load_scratch_fpregs(__ia64_sc_fr); \
} while (0)
@@ -62,18 +65,24 @@ extern spinlock_t sal_lock;
# define SAL_CALL_NOLOCK(result,args...) do { \
unsigned long __ia64_scn_flags; \
struct ia64_fpreg __ia64_scn_fr[6]; \
+ int rr6, rr7; \
ia64_save_scratch_fpregs(__ia64_scn_fr); \
local_irq_save(__ia64_scn_flags); \
+ XEN_EFI_RR_SAVE(rr6, rr7); \
__SAL_CALL(result, args); \
+ XEN_EFI_RR_RESTORE(rr6, rr7); \
local_irq_restore(__ia64_scn_flags); \
ia64_load_scratch_fpregs(__ia64_scn_fr); \
} while (0)
# define SAL_CALL_REENTRANT(result,args...) do { \
struct ia64_fpreg __ia64_scs_fr[6]; \
+ int rr6, rr7; \
ia64_save_scratch_fpregs(__ia64_scs_fr); \
preempt_disable(); \
+ XEN_EFI_RR_SAVE(rr6, rr7); \
__SAL_CALL(result, args); \
+ XEN_EFI_RR_RESTORE(rr6, rr7); \
preempt_enable(); \
ia64_load_scratch_fpregs(__ia64_scs_fr); \
} while (0)
Index: xen-unstable.hg/xen/arch/ia64/linux-xen/efi.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/linux-xen/efi.c 2007-10-23
16:21:48.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/linux-xen/efi.c 2007-10-23
16:23:46.000000000 +0900
@@ -58,6 +58,7 @@ static unsigned long mem_limit = ~0UL, m
#define efi_call_virt(f, args...) (*(f))(args)
+#ifndef XEN
#define STUB_GET_TIME(prefix, adjust_arg)
\
static efi_status_t
\
prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc)
\
@@ -71,6 +72,7 @@ prefix##_get_time (efi_time_t *tm, efi_t
ia64_save_scratch_fpregs(fr);
\
ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time),
adjust_arg(tm), atc); \
ia64_load_scratch_fpregs(fr);
\
+ ia64_set_rr(7, rr7);
\
return ret;
\
}
@@ -199,6 +201,179 @@ prefix##_reset_system (int reset_type, e
ia64_load_scratch_fpregs(fr);
\
}
+#else /* XEN */
+
+#define STUB_GET_TIME(prefix, adjust_arg)
\
+static efi_status_t
\
+prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc)
\
+{
\
+ struct ia64_fpreg fr[6];
\
+ unsigned long rr6, rr7;
\
+ efi_time_cap_t *atc = NULL;
\
+ efi_status_t ret;
\
+
\
+ if (tc)
\
+ atc = adjust_arg(tc);
\
+ ia64_save_scratch_fpregs(fr);
\
+ XEN_EFI_RR_SAVE(rr6, rr7);
\
+ ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time),
adjust_arg(tm), atc); \
+ XEN_EFI_RR_RESTORE(rr6, rr7);
\
+ ia64_load_scratch_fpregs(fr);
\
+ ia64_set_rr(7, rr7);
\
+ return ret;
\
+}
+
+#define STUB_SET_TIME(prefix, adjust_arg)
\
+static efi_status_t
\
+prefix##_set_time (efi_time_t *tm)
\
+{
\
+ struct ia64_fpreg fr[6];
\
+ unsigned long rr6, rr7;
\
+ efi_status_t ret;
\
+
\
+ ia64_save_scratch_fpregs(fr);
\
+ XEN_EFI_RR_SAVE(rr6, rr7);
\
+ ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time),
adjust_arg(tm)); \
+ XEN_EFI_RR_RESTORE(rr6, rr7);
\
+ ia64_load_scratch_fpregs(fr);
\
+ return ret;
\
+}
+
+#define STUB_GET_WAKEUP_TIME(prefix, adjust_arg)
\
+static efi_status_t
\
+prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t
*tm) \
+{
\
+ struct ia64_fpreg fr[6];
\
+ unsigned long rr6, rr7;
\
+ efi_status_t ret;
\
+
\
+ ia64_save_scratch_fpregs(fr);
\
+ XEN_EFI_RR_SAVE(rr6, rr7);
\
+ ret = efi_call_##prefix((efi_get_wakeup_time_t *)
__va(runtime->get_wakeup_time), \
+ adjust_arg(enabled), adjust_arg(pending),
adjust_arg(tm)); \
+ XEN_EFI_RR_RESTORE(rr6, rr7);
\
+ ia64_load_scratch_fpregs(fr);
\
+ return ret;
\
+}
+
+#define STUB_SET_WAKEUP_TIME(prefix, adjust_arg)
\
+static efi_status_t
\
+prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm)
\
+{
\
+ struct ia64_fpreg fr[6];
\
+ unsigned long rr6, rr7;
\
+ efi_time_t *atm = NULL;
\
+ efi_status_t ret;
\
+
\
+ if (tm)
\
+ atm = adjust_arg(tm);
\
+ ia64_save_scratch_fpregs(fr);
\
+ XEN_EFI_RR_SAVE(rr6, rr7);
\
+ ret = efi_call_##prefix((efi_set_wakeup_time_t *)
__va(runtime->set_wakeup_time), \
+ enabled, atm);
\
+ XEN_EFI_RR_RESTORE(rr6, rr7);
\
+ ia64_load_scratch_fpregs(fr);
\
+ return ret;
\
+}
+
+#define STUB_GET_VARIABLE(prefix, adjust_arg)
\
+static efi_status_t
\
+prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
\
+ unsigned long *data_size, void *data)
\
+{
\
+ struct ia64_fpreg fr[6];
\
+ unsigned long rr6, rr7;
\
+ u32 *aattr = NULL;
\
+ efi_status_t ret;
\
+
\
+ if (attr)
\
+ aattr = adjust_arg(attr);
\
+ ia64_save_scratch_fpregs(fr);
\
+ XEN_EFI_RR_SAVE(rr6, rr7);
\
+ ret = efi_call_##prefix((efi_get_variable_t *)
__va(runtime->get_variable), \
+ adjust_arg(name), adjust_arg(vendor), aattr,
\
+ adjust_arg(data_size), adjust_arg(data));
\
+ XEN_EFI_RR_RESTORE(rr6, rr7);
\
+ ia64_load_scratch_fpregs(fr);
\
+ return ret;
\
+}
+
+#define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg)
\
+static efi_status_t
\
+prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name,
efi_guid_t *vendor) \
+{
\
+ struct ia64_fpreg fr[6];
\
+ unsigned long rr6, rr7;
\
+ efi_status_t ret;
\
+
\
+ ia64_save_scratch_fpregs(fr);
\
+ XEN_EFI_RR_SAVE(rr6, rr7);
\
+ ret = efi_call_##prefix((efi_get_next_variable_t *)
__va(runtime->get_next_variable), \
+ adjust_arg(name_size), adjust_arg(name),
adjust_arg(vendor)); \
+ XEN_EFI_RR_RESTORE(rr6, rr7);
\
+ ia64_load_scratch_fpregs(fr);
\
+ return ret;
\
+}
+
+#define STUB_SET_VARIABLE(prefix, adjust_arg)
\
+static efi_status_t
\
+prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, unsigned long
attr, \
+ unsigned long data_size, void *data)
\
+{
\
+ struct ia64_fpreg fr[6];
\
+ unsigned long rr6, rr7;
\
+ efi_status_t ret;
\
+
\
+ ia64_save_scratch_fpregs(fr);
\
+ XEN_EFI_RR_SAVE(rr6, rr7);
\
+ ret = efi_call_##prefix((efi_set_variable_t *)
__va(runtime->set_variable), \
+ adjust_arg(name), adjust_arg(vendor), attr,
data_size, \
+ adjust_arg(data));
\
+ XEN_EFI_RR_RESTORE(rr6, rr7);
\
+ ia64_load_scratch_fpregs(fr);
\
+ return ret;
\
+}
+
+#define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg)
\
+static efi_status_t
\
+prefix##_get_next_high_mono_count (u32 *count)
\
+{
\
+ struct ia64_fpreg fr[6];
\
+ unsigned long rr6, rr7;
\
+ efi_status_t ret;
\
+
\
+ ia64_save_scratch_fpregs(fr);
\
+ XEN_EFI_RR_SAVE(rr6, rr7);
\
+ ret = efi_call_##prefix((efi_get_next_high_mono_count_t *)
\
+ __va(runtime->get_next_high_mono_count),
adjust_arg(count)); \
+ XEN_EFI_RR_RESTORE(rr6, rr7);
\
+ ia64_load_scratch_fpregs(fr);
\
+ return ret;
\
+}
+
+#define STUB_RESET_SYSTEM(prefix, adjust_arg)
\
+static void
\
+prefix##_reset_system (int reset_type, efi_status_t status,
\
+ unsigned long data_size, efi_char16_t *data)
\
+{
\
+ struct ia64_fpreg fr[6];
\
+ unsigned long rr6, rr7;
\
+ efi_char16_t *adata = NULL;
\
+
\
+ if (data)
\
+ adata = adjust_arg(data);
\
+
\
+ ia64_save_scratch_fpregs(fr);
\
+ XEN_EFI_RR_SAVE(rr6, rr7);
\
+ efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system),
\
+ reset_type, status, data_size, adata);
\
+ /* should not return, but just in case... */
\
+ XEN_EFI_RR_RESTORE(rr6, rr7);
\
+ ia64_load_scratch_fpregs(fr);
\
+}
+
+#endif /* XEN */
+
#define phys_ptr(arg) ((__typeof__(arg)) ia64_tpa(arg))
STUB_GET_TIME(phys, phys_ptr)
Index: xen-unstable.hg/xen/arch/ia64/xen/faults.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/faults.c 2007-10-23
16:21:24.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/faults.c 2007-10-23 16:34:54.000000000
+0900
@@ -188,7 +188,8 @@ void ia64_do_page_fault(unsigned long ad
attr = efi_mem_attributes(address &
~__IA64_EFI_CACHED_OFFSET);
if (! (attr & EFI_MEMORY_RUNTIME &&
- attr & EFI_MEMORY_WB) )
+ attr & EFI_MEMORY_WB &&
+ ia64_get_rr(7) == XEN_EFI_RID) )
attr = 0;
}
else if (address >> 59 == __IA64_EFI_UNCACHED_OFFSET >> 59) {
@@ -196,7 +197,8 @@ void ia64_do_page_fault(unsigned long ad
~__IA64_EFI_UNCACHED_OFFSET);
if (! ((attr & EFI_MEMORY_RUNTIME) &&
(attr & (EFI_MEMORY_UC|EFI_MEMORY_WC|
- EFI_MEMORY_WT))) )
+ EFI_MEMORY_WT)) &&
+ ia64_get_rr(6) == XEN_EFI_RID) )
attr = 0;
}
}
Index: xen-unstable.hg/xen/include/asm-ia64/linux-xen/asm/pal.h
===================================================================
--- xen-unstable.hg.orig/xen/include/asm-ia64/linux-xen/asm/pal.h
2007-10-23 16:20:06.000000000 +0900
+++ xen-unstable.hg/xen/include/asm-ia64/linux-xen/asm/pal.h 2007-10-23
16:23:46.000000000 +0900
@@ -80,6 +80,9 @@
#include <linux/types.h>
#include <asm/fpu.h>
+#ifdef XEN
+#include <linux/efi.h>
+#endif
/*
* Data types needed to pass information into PAL procedures and
@@ -772,36 +775,51 @@ extern void ia64_load_scratch_fpregs (st
#define PAL_CALL(iprv,a0,a1,a2,a3) do { \
struct ia64_fpreg fr[6]; \
+ unsigned long rr6, rr7; \
ia64_save_scratch_fpregs(fr); \
+ XEN_EFI_RR_SAVE(rr6, rr7); \
iprv = ia64_pal_call_static(a0, a1, a2, a3, 0); \
+ XEN_EFI_RR_RESTORE(rr6, rr7); \
ia64_load_scratch_fpregs(fr); \
} while (0)
#define PAL_CALL_IC_OFF(iprv,a0,a1,a2,a3) do { \
struct ia64_fpreg fr[6]; \
+ unsigned long rr6, rr7; \
ia64_save_scratch_fpregs(fr); \
+ XEN_EFI_RR_SAVE(rr6, rr7); \
iprv = ia64_pal_call_static(a0, a1, a2, a3, 1); \
+ XEN_EFI_RR_RESTORE(rr6, rr7); \
ia64_load_scratch_fpregs(fr); \
} while (0)
#define PAL_CALL_STK(iprv,a0,a1,a2,a3) do { \
struct ia64_fpreg fr[6]; \
+ unsigned long rr6, rr7; \
ia64_save_scratch_fpregs(fr); \
+ XEN_EFI_RR_SAVE(rr6, rr7); \
iprv = ia64_pal_call_stacked(a0, a1, a2, a3); \
+ XEN_EFI_RR_RESTORE(rr6, rr7); \
ia64_load_scratch_fpregs(fr); \
} while (0)
#define PAL_CALL_PHYS(iprv,a0,a1,a2,a3) do { \
struct ia64_fpreg fr[6]; \
+ unsigned long rr6, rr7; \
ia64_save_scratch_fpregs(fr); \
+ XEN_EFI_RR_SAVE(rr6, rr7); \
iprv = ia64_pal_call_phys_static(a0, a1, a2, a3); \
+ XEN_EFI_RR_RESTORE(rr6, rr7); \
ia64_load_scratch_fpregs(fr); \
} while (0)
#define PAL_CALL_PHYS_STK(iprv,a0,a1,a2,a3) do { \
struct ia64_fpreg fr[6]; \
+ unsigned long rr6, rr7; \
ia64_save_scratch_fpregs(fr); \
+ XEN_EFI_RR_SAVE(rr6, rr7); \
iprv = ia64_pal_call_phys_stacked(a0, a1, a2, a3); \
+ XEN_EFI_RR_RESTORE(rr6, rr7); \
ia64_load_scratch_fpregs(fr); \
} while (0)
Index: xen-unstable.hg/xen/arch/ia64/xen/ivt.S
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/ivt.S 2007-10-23
16:22:13.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/ivt.S 2007-10-23 16:30:19.000000000
+0900
@@ -57,6 +57,7 @@
#include <asm/thread_info.h>
#include <asm/unistd.h>
#include <xen/errno.h>
+#include <linux/efi.h>
#if 1
# define PSR_DEFAULT_BITS psr.ac
@@ -206,17 +207,31 @@ late_alt_dtlb_miss:
(p8) br.cond.sptk frametable_miss ;;
#endif
// If it is not a Xen address, handle it via page_fault.
+ // !( r22 == 0xf || (r22 == 0xc && rr[6] == XEN_EFI_RID) ||
+ // (r22 == 0xe && rr[7] == XEN_EFI_RID) ) )
extr.u r22=r16,59,5
;;
dep r20=0,r20,IA64_ITIR_KEY,IA64_ITIR_KEY_LEN // clear the key
- cmp.ne p8,p0=0x1e,r22 // 0xf...
- ;;
- cmp.ne.and p8,p0=0x18,r22 // 0xc...
- ;;
- cmp.ne.and p8,p0=0x1c,r22 // 0xe...
- ;;
-(p8) br.cond.sptk page_fault
+ cmp.eq p8,p0=0x1e,r22 // 0xf...
+ mov r23=6
+ mov r24=7
+ ;;
+ mov r23=rr[r23]
+ mov r24=rr[r24]
+(p8) br.cond.spnt no_slow_page_fault
+ ;;
+ mov r25=XEN_EFI_RID
+ cmp.eq p8,p0=0x18,r22 // 0xc...
+ cmp.eq p9,p0=0x1c,r22 // 0xe...
+ ;;
+ cmp.eq.and p8,p0=r25,r23 // rr[6] == XEN_EFI_RID
+ cmp.eq.and p9,p0=r25,r24 // rr[7] == XEN_EFI_RID
+ ;;
+(p8) br.cond.spnt no_slow_page_fault
+(p9) br.cond.spnt no_slow_page_fault
+ br.cond.sptk page_fault
;;
+no_slow_page_fault:
dep r21=-1,r21,IA64_PSR_ED_BIT,1
or r19=r19,r17 // insert PTE control bits into r19
mov cr.itir=r20 // set itir with cleared key
--
--
Horms
H: http://www.vergenet.net/~horms/
W: http://www.valinux.co.jp/en/
_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel
|