diff options
author | Michael Ellerman <michael@ellerman.id.au> | 2005-09-23 14:47:58 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2005-09-23 14:47:58 +1000 |
commit | 4c55130b2aa93370f1bf52d2304394e91cf8ee39 (patch) | |
tree | 522c7f510775f221c4e8046bc238a618db4768df /arch | |
parent | ba293fff085fde5b9f1b5a57c8abb1a8098d0c59 (diff) |
ppc64 iSeries: Update create_pte_mapping to replace iSeries_bolt_kernel()
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ppc64/kernel/iSeries_htab.c | 19 | ||||
-rw-r--r-- | arch/ppc64/kernel/iSeries_setup.c | 60 | ||||
-rw-r--r-- | arch/ppc64/mm/hash_utils.c | 15 |
3 files changed, 30 insertions, 64 deletions
diff --git a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c index 2192055a90a..9a2be3abf34 100644 --- a/arch/ppc64/kernel/iSeries_htab.c +++ b/arch/ppc64/kernel/iSeries_htab.c @@ -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; diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c index 75d8db4eaac..49d0f999968 100644 --- a/arch/ppc64/kernel/iSeries_setup.c +++ b/arch/ppc64/kernel/iSeries_setup.c @@ -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(); @@ -637,62 +633,6 @@ static void __init setup_iSeries_cache_sizes(void) } /* - * 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. */ static void __init iSeries_setup_arch(void) diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c index 36cf474b3d3..83507438d6a 100644 --- a/arch/ppc64/mm/hash_utils.c +++ b/arch/ppc64/mm/hash_utils.c @@ -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 |