WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-ia64-devel

[Xen-ia64-devel] [patch 11/14] Kexec: Allow page fault handler to handle

To: xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-ia64-devel] [patch 11/14] Kexec: Allow page fault handler to handle EFI regions
From: Simon Horman <horms@xxxxxxxxxxxx>
Date: Wed, 12 Sep 2007 17:08:56 +0900
Delivery-date: Wed, 12 Sep 2007 01:43:52 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-ia64-devel-request@lists.xensource.com?subject=help>
List-id: Discussion of the ia64 port of Xen <xen-ia64-devel.lists.xensource.com>
List-post: <mailto:xen-ia64-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ia64-devel>, <mailto:xen-ia64-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ia64-devel>, <mailto:xen-ia64-devel-request@lists.xensource.com?subject=unsubscribe>
References: <20070912080845.674923870@xxxxxxxxxxxx>
Sender: xen-ia64-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: quilt/0.46-1
If the EFI region is mapped into a region within the address space usually
used by guests, then the page_fault handler needs to know about it. A
description of why this mapping is made is included in the patch that makes
the mapping.

The patch to actually make use of this code is separate.

This does not take into account other ways that relevant functions are
called.

In particular:
- vcpu_itc_d() and vcpu_itc_i() call translate_domain_pte()
- ia64_shadow_fault() and vcpu_tpa() call vcpu_translate()

This patch needs work, and I am positing it for discussion.

Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>

Index: xen-unstable.hg/xen/arch/ia64/xen/faults.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/faults.c     2007-08-16 
15:54:47.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/faults.c  2007-08-16 15:59:48.000000000 
+0900
@@ -166,6 +166,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};
@@ -184,17 +185,35 @@ void ia64_do_page_fault(unsigned long ad
        }
 
  again:
+       if (!guest_mode(regs)) {
+               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;
+               }
+       }
+
        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);
@@ -752,7 +771,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/arch/ia64/xen/vcpu.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/vcpu.c       2007-08-16 
15:54:47.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/vcpu.c    2007-08-16 15:59:57.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>
@@ -1675,13 +1676,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))) {
@@ -1808,7 +1826,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,13 +2333,25 @@ 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;
        unsigned long ps = (vcpu->domain == dom0) ? _itir.ps :
                                                    vcpu->arch.vhpt_pg_shift;
 
+       /* 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!
@@ -2348,12 +2378,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_one_rr(0x0, PSCB(vcpu, rrs[0]));
-       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)) {
@@ -2376,12 +2406,12 @@ IA64FAULT vcpu_itc_i(VCPU * vcpu, u64 pt
                             "smaller page size!\n");
       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_one_rr(0x0, PSCB(vcpu, rrs[0]));
-       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/arch/ia64/xen/mm.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/mm.c 2007-08-16 15:54:47.000000000 
+0900
+++ xen-unstable.hg/xen/arch/ia64/xen/mm.c      2007-08-16 15:54:53.000000000 
+0900
@@ -449,7 +449,7 @@ gmfn_to_mfn_foreign(struct domain *d, un
 // Xen PAGE_SIZE and return modified pte.  (NOTE: TLB insert should use
 // PAGE_SIZE!)
 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__};
@@ -458,6 +458,19 @@ 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) {
+               _itir.ps = IA64_GRANULE_SHIFT;
+               /* 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/include/asm-ia64/vcpu.h
===================================================================
--- xen-unstable.hg.orig/xen/include/asm-ia64/vcpu.h    2007-08-16 
15:54:47.000000000 +0900
+++ xen-unstable.hg/xen/include/asm-ia64/vcpu.h 2007-08-16 15:59:48.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);
 
Index: xen-unstable.hg/xen/include/asm-ia64/mm.h
===================================================================
--- xen-unstable.hg.orig/xen/include/asm-ia64/mm.h      2007-08-16 
15:54:47.000000000 +0900
+++ xen-unstable.hg/xen/include/asm-ia64/mm.h   2007-08-16 15:54:53.000000000 
+0900
@@ -448,7 +448,8 @@ extern unsigned long dom0vp_expose_p2m(s
 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)

-- 

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

<Prev in Thread] Current Thread [Next in Thread>