aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2005-09-23 00:47:58 -0400
committerStephen Rothwell <sfr@canb.auug.org.au>2005-09-23 00:47:58 -0400
commit4c55130b2aa93370f1bf52d2304394e91cf8ee39 (patch)
tree522c7f510775f221c4e8046bc238a618db4768df /arch/ppc64/kernel
parentba293fff085fde5b9f1b5a57c8abb1a8098d0c59 (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/ppc64/kernel')
-rw-r--r--arch/ppc64/kernel/iSeries_htab.c19
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c60
2 files changed, 19 insertions, 60 deletions
diff --git a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c
index 2192055a90a0..9a2be3abf349 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,
84 return (secondary << 3) | (slot & 7); 84 return (secondary << 3) | (slot & 7);
85} 85}
86 86
87long iSeries_hpte_bolt_or_insert(unsigned long hpte_group,
88 unsigned long va, unsigned long prpn, unsigned long vflags,
89 unsigned long rflags)
90{
91 long slot;
92 hpte_t lhpte;
93
94 slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT);
95
96 if (lhpte.v & HPTE_V_VALID) {
97 /* Bolt the existing HPTE */
98 HvCallHpt_setSwBits(slot, 0x10, 0);
99 HvCallHpt_setPp(slot, PP_RWXX);
100 return 0;
101 }
102
103 return iSeries_hpte_insert(hpte_group, va, prpn, vflags, rflags);
104}
105
87static unsigned long iSeries_hpte_getword0(unsigned long slot) 106static unsigned long iSeries_hpte_getword0(unsigned long slot)
88{ 107{
89 hpte_t hpte; 108 hpte_t hpte;
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index 75d8db4eaac6..49d0f9999682 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -75,7 +75,6 @@ extern void ppcdbg_initialize(void);
75 75
76static void build_iSeries_Memory_Map(void); 76static void build_iSeries_Memory_Map(void);
77static void setup_iSeries_cache_sizes(void); 77static void setup_iSeries_cache_sizes(void);
78static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr);
79static int iseries_shared_idle(void); 78static int iseries_shared_idle(void);
80static int iseries_dedicated_idle(void); 79static int iseries_dedicated_idle(void);
81#ifdef CONFIG_PCI 80#ifdef CONFIG_PCI
@@ -383,9 +382,6 @@ static void __init iSeries_init_early(void)
383 } 382 }
384 } 383 }
385 384
386 /* Bolt kernel mappings for all of memory (or just a bit if we've got a limit) */
387 iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);
388
389 lmb_init(); 385 lmb_init();
390 lmb_add(0, systemcfg->physicalMemorySize); 386 lmb_add(0, systemcfg->physicalMemorySize);
391 lmb_analyze(); 387 lmb_analyze();
@@ -637,62 +633,6 @@ static void __init setup_iSeries_cache_sizes(void)
637} 633}
638 634
639/* 635/*
640 * Create a pte. Used during initialization only.
641 */
642static void iSeries_make_pte(unsigned long va, unsigned long pa,
643 int mode)
644{
645 hpte_t local_hpte, rhpte;
646 unsigned long hash, vpn;
647 long slot;
648
649 vpn = va >> PAGE_SHIFT;
650 hash = hpt_hash(vpn, 0);
651
652 local_hpte.r = pa | mode;
653 local_hpte.v = ((va >> 23) << HPTE_V_AVPN_SHIFT)
654 | HPTE_V_BOLTED | HPTE_V_VALID;
655
656 slot = HvCallHpt_findValid(&rhpte, vpn);
657 if (slot < 0) {
658 /* Must find space in primary group */
659 panic("hash_page: hpte already exists\n");
660 }
661 HvCallHpt_addValidate(slot, 0, &local_hpte);
662}
663
664/*
665 * Bolt the kernel addr space into the HPT
666 */
667static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
668{
669 unsigned long pa;
670 unsigned long mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
671 hpte_t hpte;
672
673 for (pa = saddr; pa < eaddr ;pa += PAGE_SIZE) {
674 unsigned long ea = (unsigned long)__va(pa);
675 unsigned long vsid = get_kernel_vsid(ea);
676 unsigned long va = (vsid << 28) | (pa & 0xfffffff);
677 unsigned long vpn = va >> PAGE_SHIFT;
678 unsigned long slot = HvCallHpt_findValid(&hpte, vpn);
679
680 /* Make non-kernel text non-executable */
681 if (!in_kernel_text(ea))
682 mode_rw |= HW_NO_EXEC;
683
684 if (hpte.v & HPTE_V_VALID) {
685 /* HPTE exists, so just bolt it */
686 HvCallHpt_setSwBits(slot, 0x10, 0);
687 /* And make sure the pp bits are correct */
688 HvCallHpt_setPp(slot, PP_RWXX);
689 } else
690 /* No HPTE exists, so create a new bolted one */
691 iSeries_make_pte(va, phys_to_abs(pa), mode_rw);
692 }
693}
694
695/*
696 * Document me. 636 * Document me.
697 */ 637 */
698static void __init iSeries_setup_arch(void) 638static void __init iSeries_setup_arch(void)