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,
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;
......
......@@ -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.
*/
......
......@@ -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
......
......@@ -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__ */
......
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