Commit 4c55130b authored by Michael Ellerman's avatar Michael Ellerman Committed by Stephen Rothwell

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: default avatarMichael Ellerman <michael@ellerman.id.au>
Signed-off-by: default avatarStephen Rothwell <sfr@canb.auug.org.au>
parent ba293fff
...@@ -84,6 +84,25 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, ...@@ -84,6 +84,25 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
return (secondary << 3) | (slot & 7); 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) static unsigned long iSeries_hpte_getword0(unsigned long slot)
{ {
hpte_t hpte; hpte_t hpte;
......
...@@ -75,7 +75,6 @@ extern void ppcdbg_initialize(void); ...@@ -75,7 +75,6 @@ extern void ppcdbg_initialize(void);
static void build_iSeries_Memory_Map(void); static void build_iSeries_Memory_Map(void);
static void setup_iSeries_cache_sizes(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_shared_idle(void);
static int iseries_dedicated_idle(void); static int iseries_dedicated_idle(void);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
...@@ -383,9 +382,6 @@ static void __init iSeries_init_early(void) ...@@ -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_init();
lmb_add(0, systemcfg->physicalMemorySize); lmb_add(0, systemcfg->physicalMemorySize);
lmb_analyze(); lmb_analyze();
...@@ -636,62 +632,6 @@ static void __init setup_iSeries_cache_sizes(void) ...@@ -636,62 +632,6 @@ static void __init setup_iSeries_cache_sizes(void)
(unsigned int)ppc64_caches.iline_size); (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. * Document me.
*/ */
......
...@@ -90,7 +90,6 @@ static inline void loop_forever(void) ...@@ -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, static inline void create_pte_mapping(unsigned long start, unsigned long end,
unsigned long mode, int large) unsigned long mode, int large)
{ {
...@@ -111,7 +110,7 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end, ...@@ -111,7 +110,7 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
unsigned long vpn, hash, hpteg; unsigned long vpn, hash, hpteg;
unsigned long vsid = get_kernel_vsid(addr); unsigned long vsid = get_kernel_vsid(addr);
unsigned long va = (vsid << 28) | (addr & 0xfffffff); unsigned long va = (vsid << 28) | (addr & 0xfffffff);
int ret; int ret = -1;
if (large) if (large)
vpn = va >> HPAGE_SHIFT; vpn = va >> HPAGE_SHIFT;
...@@ -129,16 +128,25 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end, ...@@ -129,16 +128,25 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); 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 #ifdef CONFIG_PPC_PSERIES
if (systemcfg->platform & PLATFORM_LPAR) if (systemcfg->platform & PLATFORM_LPAR)
ret = pSeries_lpar_hpte_insert(hpteg, va, ret = pSeries_lpar_hpte_insert(hpteg, va,
virt_to_abs(addr) >> PAGE_SHIFT, virt_to_abs(addr) >> PAGE_SHIFT,
vflags, tmp_mode); vflags, tmp_mode);
else else
#endif /* CONFIG_PPC_PSERIES */ #endif
#ifdef CONFIG_PPC_MULTIPLATFORM
ret = native_hpte_insert(hpteg, va, ret = native_hpte_insert(hpteg, va,
virt_to_abs(addr) >> PAGE_SHIFT, virt_to_abs(addr) >> PAGE_SHIFT,
vflags, tmp_mode); vflags, tmp_mode);
#endif
if (ret == -1) { if (ret == -1) {
ppc64_terminate_msg(0x20, "create_pte_mapping"); ppc64_terminate_msg(0x20, "create_pte_mapping");
...@@ -261,7 +269,6 @@ void __init htab_initialize(void) ...@@ -261,7 +269,6 @@ void __init htab_initialize(void)
} }
#undef KB #undef KB
#undef MB #undef MB
#endif /* CONFIG_PPC_MULTIPLATFORM */
/* /*
* Called by asm hashtable.S for doing lazy icache flush * Called by asm hashtable.S for doing lazy icache flush
......
...@@ -206,6 +206,10 @@ extern long native_hpte_insert(unsigned long hpte_group, unsigned long va, ...@@ -206,6 +206,10 @@ extern long native_hpte_insert(unsigned long hpte_group, unsigned long va,
unsigned long prpn, unsigned long prpn,
unsigned long vflags, unsigned long rflags); 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); extern void stabs_alloc(void);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment