ppc64 iSeries: Update create_pte_mapping to replace iSeries_bolt_kernel()
authorMichael Ellerman <michael@ellerman.id.au>
Fri, 23 Sep 2005 04:47:58 +0000 (14:47 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Fri, 23 Sep 2005 04:47:58 +0000 (14:47 +1000)
early_setup() calls htab_initialize() which is similar, but not identical
to iSeries_bolt_kernel().

On iSeries the Hypervisor has already inserted some ptes for us, and we
simply have to detect that and bolt them. iSeries_hpte_bolt_or_insert()
implements that logic.

For the case of a non-existing pte we just call iSeries_hpte_insert(). This
appears to work, although it's not entirely equivalent to the old code in
iSeries_make_pte() which panicked if we got a secondary slot. Not sure if
that's important.

Finally we call iSeries_hpte_bolt_or_insert() from create_pte_mapping(),
which is called from htab_initialize() for each lmb region.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
arch/ppc64/kernel/iSeries_htab.c
arch/ppc64/kernel/iSeries_setup.c
arch/ppc64/mm/hash_utils.c
include/asm-ppc64/mmu.h

index 2192055a90a07ba3f34f074e70cb75225d124fdb..9a2be3abf3494191853ab848fe70f6095e617338 100644 (file)
@@ -84,6 +84,25 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
        return (secondary << 3) | (slot & 7);
 }
 
+long iSeries_hpte_bolt_or_insert(unsigned long hpte_group,
+               unsigned long va, unsigned long prpn, unsigned long vflags,
+               unsigned long rflags)
+{
+       long slot;
+       hpte_t lhpte;
+
+       slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT);
+
+       if (lhpte.v & HPTE_V_VALID) {
+               /* Bolt the existing HPTE */
+               HvCallHpt_setSwBits(slot, 0x10, 0);
+               HvCallHpt_setPp(slot, PP_RWXX);
+               return 0;
+       }
+
+       return iSeries_hpte_insert(hpte_group, va, prpn, vflags, rflags);
+}
+
 static unsigned long iSeries_hpte_getword0(unsigned long slot)
 {
        hpte_t hpte;
index 75d8db4eaac6820fb31d3d83800cdd2ffaf76d79..49d0f99996828fbb766a24ce4a2e4a6ba3c24d7a 100644 (file)
@@ -75,7 +75,6 @@ extern void ppcdbg_initialize(void);
 
 static void build_iSeries_Memory_Map(void);
 static void setup_iSeries_cache_sizes(void);
-static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr);
 static int iseries_shared_idle(void);
 static int iseries_dedicated_idle(void);
 #ifdef CONFIG_PCI
@@ -383,9 +382,6 @@ static void __init iSeries_init_early(void)
                }
        }
 
-       /* Bolt kernel mappings for all of memory (or just a bit if we've got a limit) */
-       iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);
-
        lmb_init();
        lmb_add(0, systemcfg->physicalMemorySize);
        lmb_analyze();
@@ -636,62 +632,6 @@ static void __init setup_iSeries_cache_sizes(void)
                        (unsigned int)ppc64_caches.iline_size);
 }
 
-/*
- * Create a pte. Used during initialization only.
- */
-static void iSeries_make_pte(unsigned long va, unsigned long pa,
-                            int mode)
-{
-       hpte_t local_hpte, rhpte;
-       unsigned long hash, vpn;
-       long slot;
-
-       vpn = va >> PAGE_SHIFT;
-       hash = hpt_hash(vpn, 0);
-
-       local_hpte.r = pa | mode;
-       local_hpte.v = ((va >> 23) << HPTE_V_AVPN_SHIFT)
-               | HPTE_V_BOLTED | HPTE_V_VALID;
-
-       slot = HvCallHpt_findValid(&rhpte, vpn);
-       if (slot < 0) {
-               /* Must find space in primary group */
-               panic("hash_page: hpte already exists\n");
-       }
-       HvCallHpt_addValidate(slot, 0, &local_hpte);
-}
-
-/*
- * Bolt the kernel addr space into the HPT
- */
-static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
-{
-       unsigned long pa;
-       unsigned long mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
-       hpte_t hpte;
-
-       for (pa = saddr; pa < eaddr ;pa += PAGE_SIZE) {
-               unsigned long ea = (unsigned long)__va(pa);
-               unsigned long vsid = get_kernel_vsid(ea);
-               unsigned long va = (vsid << 28) | (pa & 0xfffffff);
-               unsigned long vpn = va >> PAGE_SHIFT;
-               unsigned long slot = HvCallHpt_findValid(&hpte, vpn);
-
-               /* Make non-kernel text non-executable */
-               if (!in_kernel_text(ea))
-                       mode_rw |= HW_NO_EXEC;
-
-               if (hpte.v & HPTE_V_VALID) {
-                       /* HPTE exists, so just bolt it */
-                       HvCallHpt_setSwBits(slot, 0x10, 0);
-                       /* And make sure the pp bits are correct */
-                       HvCallHpt_setPp(slot, PP_RWXX);
-               } else
-                       /* No HPTE exists, so create a new bolted one */
-                       iSeries_make_pte(va, phys_to_abs(pa), mode_rw);
-       }
-}
-
 /*
  * Document me.
  */
index 36cf474b3d365f4dba63c93834683ba17f5e5c2a..83507438d6a0aa6a178d45c5e1a1e3881cc36442 100644 (file)
@@ -90,7 +90,6 @@ static inline void loop_forever(void)
                ;
 }
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
 static inline void create_pte_mapping(unsigned long start, unsigned long end,
                                      unsigned long mode, int large)
 {
@@ -111,7 +110,7 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
                unsigned long vpn, hash, hpteg;
                unsigned long vsid = get_kernel_vsid(addr);
                unsigned long va = (vsid << 28) | (addr & 0xfffffff);
-               int ret;
+               int ret = -1;
 
                if (large)
                        vpn = va >> HPAGE_SHIFT;
@@ -129,16 +128,25 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
 
                hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
+#ifdef CONFIG_PPC_ISERIES
+               if (systemcfg->platform & PLATFORM_ISERIES_LPAR)
+                       ret = iSeries_hpte_bolt_or_insert(hpteg, va,
+                               virt_to_abs(addr) >> PAGE_SHIFT,
+                               vflags, tmp_mode);
+               else
+#endif
 #ifdef CONFIG_PPC_PSERIES
                if (systemcfg->platform & PLATFORM_LPAR)
                        ret = pSeries_lpar_hpte_insert(hpteg, va,
                                virt_to_abs(addr) >> PAGE_SHIFT,
                                vflags, tmp_mode);
                else
-#endif /* CONFIG_PPC_PSERIES */
+#endif
+#ifdef CONFIG_PPC_MULTIPLATFORM
                        ret = native_hpte_insert(hpteg, va,
                                virt_to_abs(addr) >> PAGE_SHIFT,
                                vflags, tmp_mode);
+#endif
 
                if (ret == -1) {
                        ppc64_terminate_msg(0x20, "create_pte_mapping");
@@ -261,7 +269,6 @@ void __init htab_initialize(void)
 }
 #undef KB
 #undef MB
-#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 /*
  * Called by asm hashtable.S for doing lazy icache flush
index d2b0b796d35e14376488a0ca4fc3bea51484ee2e..e0505acb77d9971dff1dc19ee3f364d09f193ec2 100644 (file)
@@ -206,6 +206,10 @@ extern long native_hpte_insert(unsigned long hpte_group, unsigned long va,
                               unsigned long prpn,
                               unsigned long vflags, unsigned long rflags);
 
+extern long iSeries_hpte_bolt_or_insert(unsigned long hpte_group,
+               unsigned long va, unsigned long prpn,
+               unsigned long vflags, unsigned long rflags);
+
 extern void stabs_alloc(void);
 
 #endif /* __ASSEMBLY__ */