Index: xen-unstable.hg/xen/arch/ia64/xen/mm.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/mm.c	2008-01-21 11:46:50.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/mm.c	2008-01-21 11:47:01.000000000 +0900
@@ -502,7 +502,7 @@ gmfn_to_mfn_foreign(struct domain *d, un
 // Xen PAGE_SIZE and return modified pte.  (NOTE: TLB insert should use
 // current->arch.vhpt_pg_shift!)
 u64 translate_domain_pte(u64 pteval, u64 address, u64 itir__, u64* itir,
-                         struct p2m_entry* entry)
+                         struct p2m_entry* entry, unsigned long efi_attr)
 {
 	struct domain *d = current->domain;
 	ia64_itir_t _itir = {.itir = itir__};
@@ -511,6 +511,18 @@ u64 translate_domain_pte(u64 pteval, u64
 	u64 arflags2;
 	u64 maflags2;
 
+	/* EFI-Runtime areas are itendity mapped into the same location
+	 * that they are maped in Linux with GRANULE size pages.
+	 * If efi_attr is non-zero, then the address is EFI-Runtime memory.
+	 */
+	if (efi_attr) {
+		/* Copy the whole register. */
+		((ia64_itir_t*)itir)->itir = _itir.itir;
+		/* Overwrite ps part! */
+		((ia64_itir_t*)itir)->ps = IA64_GRANULE_SHIFT;
+		return pteval;
+	}
+
 	pteval &= ((1UL << 53) - 1);// ignore [63:53] bits
 
 	// FIXME address had better be pre-validated on insert
Index: xen-unstable.hg/xen/arch/ia64/xen/vcpu.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/vcpu.c	2008-01-21 11:46:50.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/vcpu.c	2008-01-21 11:47:01.000000000 +0900
@@ -7,6 +7,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/efi.h>
 #include <public/xen.h>
 #include <xen/mm.h>
 #include <asm/ia64_int.h>
@@ -1670,13 +1671,30 @@ vcpu_get_domain_bundle(VCPU * vcpu, REGS
 }
 
 IA64FAULT vcpu_translate(VCPU * vcpu, u64 address, BOOLEAN is_data,
-			 u64 * pteval, u64 * itir, u64 * iha)
+			 u64 * pteval, u64 * itir, u64 * iha,
+			 unsigned long efi_attr)
 {
 	unsigned long region = address >> 61;
 	unsigned long pta, rid, rr, key = 0;
 	union pte_flags pte;
 	TR_ENTRY *trp;
 
+	/* EFI-Runtime areas are identity mapped into
+	 * the same location that they are maped in Linux.
+	 * If efi_attr is non-zero then * (efi_attr & EFI_MEMORY_RUNTIME) is
+	 * true and that either (efi_attr & EFI_MEMORY_WB) is true or
+	 * (efi_attr & (EFI_MEMORY_UC|EFI_MEMORY_WC|EFI_MEMORY_WT)) is true.
+	 */
+	if (efi_attr) {
+		if (efi_attr & EFI_MEMORY_WB)
+			*pteval = (address & _PAGE_PPN_MASK) | __DIRTY_BITS |
+				_PAGE_AR_RWX;
+		else
+			*pteval = (address & _PAGE_PPN_MASK) | __DIRTY_BITS |
+				_PAGE_AR_RWX | _PAGE_PL_PRIV | _PAGE_MA_UC;
+		return IA64_NO_FAULT;
+	}
+
 	if (PSCB(vcpu, metaphysical_mode) && !(!is_data && region)) {
 		// dom0 may generate an uncacheable physical address (msb=1)
 		if (region && ((region != 4) || (vcpu->domain != dom0))) {
@@ -1806,7 +1824,7 @@ IA64FAULT vcpu_tpa(VCPU * vcpu, u64 vadr
 	u64 pteval, itir, mask, iha;
 	IA64FAULT fault;
 
-	fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
+	fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha, 0);
 	if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) {
 		mask = itir_mask(itir);
 		*padr = (pteval & _PAGE_PPN_MASK & mask) | (vadr & ~mask);
@@ -1820,7 +1838,7 @@ IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr
 	u64 pteval, itir, iha;
 	IA64FAULT fault;
 
-	fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
+	fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha, 0);
 	if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB)
 		*key = itir & IA64_ITIR_KEY_MASK;
 	else
@@ -2315,11 +2333,23 @@ vcpu_rebuild_vhpt(VCPU * vcpu, u64 ps)
 
 void
 vcpu_itc_no_srlz(VCPU * vcpu, u64 IorD, u64 vaddr, u64 pte,
-                 u64 mp_pte, u64 itir, struct p2m_entry *entry)
+		 u64 mp_pte, u64 itir, struct p2m_entry *entry,
+		 unsigned long efi_attr)
 {
 	ia64_itir_t _itir = {.itir = itir};
 	unsigned long psr;
 
+	/* EFI-Runtime areas are identity mapped into
+	 * the same location that they are maped in Linux.
+	 * If efi_attr is non-zero, then the address is EFI-Runtime memory
+	 */
+	if (efi_attr) {
+		unsigned long psr = ia64_clear_ic();
+		ia64_itc(IorD, vaddr, pte, _itir.itir);
+		ia64_set_psr(psr);
+		return;
+	}
+
 	check_xen_space_overlap("itc", vaddr, 1UL << _itir.ps);
 
 	// FIXME, must be inlined or potential for nested fault here!
@@ -2364,12 +2394,12 @@ IA64FAULT vcpu_itc_d(VCPU * vcpu, u64 pt
 
  again:
 	//itir = (itir & ~0xfc) | (vcpu->arch.vhpt_pg_shift<<2); // ign dom pgsz
-	pteval = translate_domain_pte(pte, ifa, itir, &(_itir.itir), &entry);
+	pteval = translate_domain_pte(pte, ifa, itir, &(_itir.itir), &entry, 0);
 	if (!pteval)
 		return IA64_ILLOP_FAULT;
 	if (swap_rr0)
 		set_virtual_rr0();
-	vcpu_itc_no_srlz(vcpu, 2, ifa, pteval, pte, _itir.itir, &entry);
+	vcpu_itc_no_srlz(vcpu, 2, ifa, pteval, pte, _itir.itir, &entry, 0);
 	if (swap_rr0)
 		set_metaphysical_rr0();
 	if (p2m_entry_retry(&entry)) {
@@ -2392,12 +2422,12 @@ IA64FAULT vcpu_itc_i(VCPU * vcpu, u64 pt
 
       again:
 	//itir = (itir & ~0xfc) | (vcpu->arch.vhpt_pg_shift<<2); // ign dom pgsz
-	pteval = translate_domain_pte(pte, ifa, itir, &(_itir.itir), &entry);
+	pteval = translate_domain_pte(pte, ifa, itir, &(_itir.itir), &entry, 0);
 	if (!pteval)
 		return IA64_ILLOP_FAULT;
 	if (swap_rr0)
 		set_virtual_rr0();
-	vcpu_itc_no_srlz(vcpu, 1, ifa, pteval, pte, _itir.itir, &entry);
+	vcpu_itc_no_srlz(vcpu, 1, ifa, pteval, pte, _itir.itir, &entry, 0);
 	if (swap_rr0)
 		set_metaphysical_rr0();
 	if (p2m_entry_retry(&entry)) {
Index: xen-unstable.hg/xen/include/asm-ia64/mm.h
===================================================================
--- xen-unstable.hg.orig/xen/include/asm-ia64/mm.h	2008-01-21 11:46:50.000000000 +0900
+++ xen-unstable.hg/xen/include/asm-ia64/mm.h	2008-01-21 11:47:01.000000000 +0900
@@ -459,7 +459,8 @@ extern unsigned long dom0vp_unexpose_for
 extern volatile unsigned long *mpt_table;
 extern unsigned long gmfn_to_mfn_foreign(struct domain *d, unsigned long gpfn);
 extern u64 translate_domain_pte(u64 pteval, u64 address, u64 itir__,
-				u64* itir, struct p2m_entry* entry);
+				u64* itir, struct p2m_entry* entry,
+				unsigned long efi_attr);
 #define machine_to_phys_mapping	mpt_table
 
 #define INVALID_M2P_ENTRY        (~0UL)
Index: xen-unstable.hg/xen/arch/ia64/xen/faults.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/faults.c	2008-01-21 11:46:50.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/faults.c	2008-01-21 11:47:15.000000000 +0900
@@ -164,6 +164,7 @@ void ia64_do_page_fault(unsigned long ad
 	// FIXME should validate address here
 	unsigned long pteval;
 	unsigned long is_data = !((isr >> IA64_ISR_X_BIT) & 1UL);
+	unsigned long attr = 0;
 	IA64FAULT fault;
 	int is_ptc_l_needed = 0;
 	ia64_itir_t _itir = {.itir = itir};
@@ -182,17 +183,41 @@ void ia64_do_page_fault(unsigned long ad
 	}
 
  again:
+	/* This is to handle page faults for EFI memory from guests
+	 * N.B: This is probably safe for dom0, but
+	 * completely unsafe for domU */
+	if (address >> 59 == __IA64_EFI_CACHED_OFFSET >> 59) {
+		attr = efi_mem_attributes(address &
+					  ~__IA64_EFI_CACHED_OFFSET);
+		if (! (attr & EFI_MEMORY_RUNTIME && attr & EFI_MEMORY_WB) )
+			attr = 0;
+	}
+	else if (address >> 59 == __IA64_EFI_UNCACHED_OFFSET >> 59) {
+		attr = efi_mem_attributes(address &
+					  ~__IA64_EFI_UNCACHED_OFFSET);
+		if (! (attr & EFI_MEMORY_RUNTIME &&
+		       attr & (EFI_MEMORY_UC|EFI_MEMORY_WC|EFI_MEMORY_WT)) )
+			attr = 0;
+	}
+	if (attr && guest_mode(regs)) {
+		/* Removing the following line caues
+		 * an unhandled page_fault in dom0 on my hardware,
+		 * similar to what Alex Williamson is seeing
+		 * without this patch. */
+		attr = 0;
+	}
+
 	fault = vcpu_translate(current, address, is_data, &pteval,
-	                       &itir, &iha);
+	                       &itir, &iha, attr);
 	if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) {
 		struct p2m_entry entry;
 		unsigned long m_pteval;
 		m_pteval = translate_domain_pte(pteval, address, itir,
-		                                &(_itir.itir), &entry);
+		                                &(_itir.itir), &entry, attr);
 		vcpu_itc_no_srlz(current, is_data ? 2 : 1, address,
-		                 m_pteval, pteval, _itir.itir, &entry);
+		                 m_pteval, pteval, _itir.itir, &entry, attr);
 		if ((fault == IA64_USE_TLB && !current->arch.dtlb.pte.p) ||
-		    p2m_entry_retry(&entry)) {
+		     (!attr && p2m_entry_retry(&entry))) {
 			/* dtlb has been purged in-between.  This dtlb was
 			   matching.  Undo the work.  */
 			vcpu_flush_tlb_vhpt_range(address, _itir.ps);
@@ -215,7 +240,9 @@ void ia64_do_page_fault(unsigned long ad
 			// indicate a bad xen pointer
 			printk("*** xen_handle_domain_access: exception table"
 			       " lookup failed, iip=0x%lx, addr=0x%lx, "
-			       "spinning...\n", iip, address);
+			       "rr[%d]=0x%lx kr2=0x%lx spinning...\n", iip,
+			       address, (address >> 62),
+			       ia64_get_rr(address >> 62), ia64_get_kr(2));
 			panic_domain(regs, "*** xen_handle_domain_access: "
 			             "exception table lookup failed, "
 			             "iip=0x%lx, addr=0x%lx, spinning...\n",
@@ -770,7 +797,7 @@ ia64_shadow_fault(unsigned long ifa, uns
 
 		/* FIXME: gives a chance to tpa, as the TC was valid.  */
 
-		fault = vcpu_translate(v, ifa, 1, &pte, &itir, &iha);
+		fault = vcpu_translate(v, ifa, 1, &pte, &itir, &iha, 0);
 
 		/* Try again!  */
 		if (fault != IA64_NO_FAULT) {
Index: xen-unstable.hg/xen/include/asm-ia64/vcpu.h
===================================================================
--- xen-unstable.hg.orig/xen/include/asm-ia64/vcpu.h	2008-01-21 11:46:50.000000000 +0900
+++ xen-unstable.hg/xen/include/asm-ia64/vcpu.h	2008-01-21 11:47:01.000000000 +0900
@@ -162,7 +162,8 @@ union U_IA64_BUNDLE;
 extern int vcpu_get_domain_bundle(VCPU * vcpu, REGS * regs, u64 gip,
                                   union U_IA64_BUNDLE *bundle);
 extern IA64FAULT vcpu_translate(VCPU * vcpu, u64 address, BOOLEAN is_data,
-                                u64 * pteval, u64 * itir, u64 * iha);
+				u64 * pteval, u64 * itir, u64 * iha,
+				unsigned long efi_attr);
 extern IA64FAULT vcpu_tpa(VCPU * vcpu, u64 vadr, u64 * padr);
 extern IA64FAULT vcpu_force_inst_miss(VCPU * vcpu, u64 ifa);
 extern IA64FAULT vcpu_force_data_miss(VCPU * vcpu, u64 ifa);
@@ -182,7 +183,7 @@ extern BOOLEAN vcpu_timer_expired(VCPU *
 extern u64 vcpu_deliverable_interrupts(VCPU * vcpu);
 struct p2m_entry;
 extern void vcpu_itc_no_srlz(VCPU * vcpu, u64, u64, u64, u64, u64,
-                             struct p2m_entry *);
+                             struct p2m_entry *, unsigned long efi_attr);
 extern u64 vcpu_get_tmp(VCPU *, u64);
 extern void vcpu_set_tmp(VCPU *, u64, u64);
 
