mirror of
https://github.com/adulau/aha.git
synced 2025-01-01 13:46:24 +00:00
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>
This commit is contained in:
parent
ba293fff08
commit
4c55130b2a
4 changed files with 34 additions and 64 deletions
|
@ -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__ */
|
||||
|
|
Loading…
Reference in a new issue