summaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/efi.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/efi.c')
-rw-r--r--arch/ia64/kernel/efi.c51
1 files changed, 45 insertions, 6 deletions
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 32d83ae75..759db7f52 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -18,6 +18,7 @@
* Goutham Rao: <goutham.rao@intel.com>
* Skip non-WB memory and ignore empty memory ranges.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
@@ -216,12 +217,41 @@ efi_map_pal_code (void)
md->phys_addr);
continue;
}
- mask = ~((1 << _PAGE_SIZE_4M)-1); /* XXX should be dynamic? */
+ /*
+ * We must use the same page size as the one used
+ * for the kernel region when we map the PAL code.
+ * This way, we avoid overlapping TRs if code is
+ * executed nearby. The Alt I-TLB installs 256MB
+ * page sizes as defined for region 7.
+ *
+ * XXX Fixme: should be dynamic here (for page size)
+ */
+ mask = ~((1 << _PAGE_SIZE_256M)-1);
vaddr = PAGE_OFFSET + md->phys_addr;
- printk(__FUNCTION__": mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
- md->phys_addr, md->phys_addr + (md->num_pages << 12),
- vaddr & mask, (vaddr & mask) + 4*1024*1024);
+ /*
+ * We must check that the PAL mapping won't overlap
+ * with the kernel mapping on ITR1.
+ *
+ * PAL code is guaranteed to be aligned on a power of 2
+ * between 4k and 256KB.
+ * Also from the documentation, it seems like there is an
+ * implicit guarantee that you will need only ONE ITR to
+ * map it. This implies that the PAL code is always aligned
+ * on its size, i.e., the closest matching page size supported
+ * by the TLB. Therefore PAL code is guaranteed never to cross
+ * a 256MB unless it is bigger than 256MB (very unlikely!).
+ * So for now the following test is enough to determine whether
+ * or not we need a dedicated ITR for the PAL code.
+ */
+ if ((vaddr & mask) == (PAGE_OFFSET & mask)) {
+ printk(__FUNCTION__ " : no need to install ITR for PAL Code\n");
+ continue;
+ }
+
+ printk("CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
+ smp_processor_id(), md->phys_addr, md->phys_addr + (md->num_pages << 12),
+ vaddr & mask, (vaddr & mask) + 256*1024*1024);
/*
* Cannot write to CRx with PSR.ic=1
@@ -232,12 +262,11 @@ efi_map_pal_code (void)
* ITR0/DTR0: used for kernel code/data
* ITR1/DTR1: used by HP simulator
* ITR2/DTR2: map PAL code
- * ITR3/DTR3: used to map PAL calls buffer
*/
ia64_itr(0x1, 2, vaddr & mask,
pte_val(mk_pte_phys(md->phys_addr,
__pgprot(__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RX))),
- _PAGE_SIZE_4M);
+ _PAGE_SIZE_256M);
local_irq_restore(flags);
ia64_srlz_i ();
}
@@ -348,6 +377,16 @@ efi_init (void)
#endif
efi_map_pal_code();
+
+#ifndef CONFIG_IA64_SOFTSDV_HACKS
+ /*
+ * (Some) SoftSDVs seem to have a problem with this call.
+ * Since it's mostly a performance optimization, just don't do
+ * it for now... --davidm 99/12/6
+ */
+ efi_enter_virtual_mode();
+#endif
+
}
void