powerpc/mm/hash64: Map all the kernel regions in the same 0xc range
This patch maps vmalloc, IO and vmemap regions in the 0xc address range instead of the current 0xd and 0xf range. This brings the mapping closer to radix translation mode. With hash 64K page size each of this region is 512TB whereas with 4K config we are limited by the max page table range of 64TB and hence there regions are of 16TB size. The kernel mapping is now: On 4K hash kernel_region_map_size = 16TB kernel vmalloc start = 0xc000100000000000 kernel IO start = 0xc000200000000000 kernel vmemmap start = 0xc000300000000000 64K hash, 64K radix and 4k radix: kernel_region_map_size = 512TB kernel vmalloc start = 0xc008000000000000 kernel IO start = 0xc00a000000000000 kernel vmemmap start = 0xc00c000000000000 Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:

committed by
Michael Ellerman

parent
a35a3c6f60
commit
0034d395f8
@@ -105,7 +105,7 @@ int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb)
|
||||
u64 vsid, vsidkey;
|
||||
int psize, ssize;
|
||||
|
||||
switch (REGION_ID(ea)) {
|
||||
switch (get_region_id(ea)) {
|
||||
case USER_REGION_ID:
|
||||
pr_devel("%s: 0x%llx -- USER_REGION_ID\n", __func__, ea);
|
||||
if (mm == NULL)
|
||||
@@ -117,10 +117,14 @@ int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb)
|
||||
break;
|
||||
case VMALLOC_REGION_ID:
|
||||
pr_devel("%s: 0x%llx -- VMALLOC_REGION_ID\n", __func__, ea);
|
||||
if (ea < VMALLOC_END)
|
||||
psize = mmu_vmalloc_psize;
|
||||
else
|
||||
psize = mmu_io_psize;
|
||||
psize = mmu_vmalloc_psize;
|
||||
ssize = mmu_kernel_ssize;
|
||||
vsid = get_kernel_vsid(ea, mmu_kernel_ssize);
|
||||
vsidkey = SLB_VSID_KERNEL;
|
||||
break;
|
||||
case IO_REGION_ID:
|
||||
pr_devel("%s: 0x%llx -- IO_REGION_ID\n", __func__, ea);
|
||||
psize = mmu_io_psize;
|
||||
ssize = mmu_kernel_ssize;
|
||||
vsid = get_kernel_vsid(ea, mmu_kernel_ssize);
|
||||
vsidkey = SLB_VSID_KERNEL;
|
||||
|
@@ -1009,12 +1009,11 @@ void __init hash__early_init_mmu(void)
|
||||
__pgd_val_bits = HASH_PGD_VAL_BITS;
|
||||
|
||||
__kernel_virt_start = H_KERN_VIRT_START;
|
||||
__kernel_virt_size = H_KERN_VIRT_SIZE;
|
||||
__vmalloc_start = H_VMALLOC_START;
|
||||
__vmalloc_end = H_VMALLOC_END;
|
||||
__kernel_io_start = H_KERN_IO_START;
|
||||
__kernel_io_end = H_KERN_IO_END;
|
||||
vmemmap = (struct page *)H_VMEMMAP_BASE;
|
||||
vmemmap = (struct page *)H_VMEMMAP_START;
|
||||
ioremap_bot = IOREMAP_BASE;
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
@@ -1241,7 +1240,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea,
|
||||
trace_hash_fault(ea, access, trap);
|
||||
|
||||
/* Get region & vsid */
|
||||
switch (REGION_ID(ea)) {
|
||||
switch (get_region_id(ea)) {
|
||||
case USER_REGION_ID:
|
||||
user_region = 1;
|
||||
if (! mm) {
|
||||
@@ -1255,10 +1254,13 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea,
|
||||
break;
|
||||
case VMALLOC_REGION_ID:
|
||||
vsid = get_kernel_vsid(ea, mmu_kernel_ssize);
|
||||
if (ea < VMALLOC_END)
|
||||
psize = mmu_vmalloc_psize;
|
||||
else
|
||||
psize = mmu_io_psize;
|
||||
psize = mmu_vmalloc_psize;
|
||||
ssize = mmu_kernel_ssize;
|
||||
break;
|
||||
|
||||
case IO_REGION_ID:
|
||||
vsid = get_kernel_vsid(ea, mmu_kernel_ssize);
|
||||
psize = mmu_io_psize;
|
||||
ssize = mmu_kernel_ssize;
|
||||
break;
|
||||
default:
|
||||
@@ -1424,7 +1426,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap,
|
||||
unsigned long flags = 0;
|
||||
struct mm_struct *mm = current->mm;
|
||||
|
||||
if (REGION_ID(ea) == VMALLOC_REGION_ID)
|
||||
if ((get_region_id(ea) == VMALLOC_REGION_ID) ||
|
||||
(get_region_id(ea) == IO_REGION_ID))
|
||||
mm = &init_mm;
|
||||
|
||||
if (dsisr & DSISR_NOHPTE)
|
||||
@@ -1440,8 +1443,9 @@ int __hash_page(unsigned long ea, unsigned long msr, unsigned long trap,
|
||||
unsigned long access = _PAGE_PRESENT | _PAGE_READ;
|
||||
unsigned long flags = 0;
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned int region_id = get_region_id(ea);
|
||||
|
||||
if (REGION_ID(ea) == VMALLOC_REGION_ID)
|
||||
if ((region_id == VMALLOC_REGION_ID) || (region_id == IO_REGION_ID))
|
||||
mm = &init_mm;
|
||||
|
||||
if (dsisr & DSISR_NOHPTE)
|
||||
@@ -1458,7 +1462,7 @@ int __hash_page(unsigned long ea, unsigned long msr, unsigned long trap,
|
||||
* 2) user space access kernel space.
|
||||
*/
|
||||
access |= _PAGE_PRIVILEGED;
|
||||
if ((msr & MSR_PR) || (REGION_ID(ea) == USER_REGION_ID))
|
||||
if ((msr & MSR_PR) || (region_id == USER_REGION_ID))
|
||||
access &= ~_PAGE_PRIVILEGED;
|
||||
|
||||
if (trap == 0x400)
|
||||
@@ -1502,7 +1506,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
|
||||
int rc, ssize, update_flags = 0;
|
||||
unsigned long access = _PAGE_PRESENT | _PAGE_READ | (is_exec ? _PAGE_EXEC : 0);
|
||||
|
||||
BUG_ON(REGION_ID(ea) != USER_REGION_ID);
|
||||
BUG_ON(get_region_id(ea) != USER_REGION_ID);
|
||||
|
||||
if (!should_hash_preload(mm, ea))
|
||||
return;
|
||||
|
@@ -136,6 +136,10 @@ static int __map_kernel_page(unsigned long ea, unsigned long pa,
|
||||
*/
|
||||
BUILD_BUG_ON(TASK_SIZE_USER64 > RADIX_PGTABLE_RANGE);
|
||||
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
BUILD_BUG_ON(RADIX_KERN_MAP_SIZE != (1UL << MAX_EA_BITS_PER_CONTEXT));
|
||||
#endif
|
||||
|
||||
if (unlikely(!slab_is_available()))
|
||||
return early_map_kernel_page(ea, pa, flags, map_page_size,
|
||||
nid, region_start, region_end);
|
||||
@@ -601,12 +605,11 @@ void __init radix__early_init_mmu(void)
|
||||
__pgd_val_bits = RADIX_PGD_VAL_BITS;
|
||||
|
||||
__kernel_virt_start = RADIX_KERN_VIRT_START;
|
||||
__kernel_virt_size = RADIX_KERN_VIRT_SIZE;
|
||||
__vmalloc_start = RADIX_VMALLOC_START;
|
||||
__vmalloc_end = RADIX_VMALLOC_END;
|
||||
__kernel_io_start = RADIX_KERN_IO_START;
|
||||
__kernel_io_end = RADIX_KERN_IO_END;
|
||||
vmemmap = (struct page *)RADIX_VMEMMAP_BASE;
|
||||
vmemmap = (struct page *)RADIX_VMEMMAP_START;
|
||||
ioremap_bot = IOREMAP_BASE;
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
@@ -90,8 +90,6 @@ unsigned long __pgd_val_bits;
|
||||
EXPORT_SYMBOL(__pgd_val_bits);
|
||||
unsigned long __kernel_virt_start;
|
||||
EXPORT_SYMBOL(__kernel_virt_start);
|
||||
unsigned long __kernel_virt_size;
|
||||
EXPORT_SYMBOL(__kernel_virt_size);
|
||||
unsigned long __vmalloc_start;
|
||||
EXPORT_SYMBOL(__vmalloc_start);
|
||||
unsigned long __vmalloc_end;
|
||||
|
@@ -500,7 +500,7 @@ static void populate_markers(void)
|
||||
address_markers[7].start_address = IOREMAP_BASE;
|
||||
address_markers[8].start_address = IOREMAP_END;
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
address_markers[9].start_address = H_VMEMMAP_BASE;
|
||||
address_markers[9].start_address = H_VMEMMAP_START;
|
||||
#else
|
||||
address_markers[9].start_address = VMEMMAP_BASE;
|
||||
#endif
|
||||
|
@@ -303,8 +303,9 @@ static void populate_markers(void)
|
||||
address_markers[i++].start_address = PHB_IO_END;
|
||||
address_markers[i++].start_address = IOREMAP_BASE;
|
||||
address_markers[i++].start_address = IOREMAP_END;
|
||||
/* What is the ifdef about? */
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
address_markers[i++].start_address = H_VMEMMAP_BASE;
|
||||
address_markers[i++].start_address = H_VMEMMAP_START;
|
||||
#else
|
||||
address_markers[i++].start_address = VMEMMAP_BASE;
|
||||
#endif
|
||||
|
@@ -694,7 +694,7 @@ static long slb_allocate_kernel(unsigned long ea, unsigned long id)
|
||||
if (id == KERNEL_REGION_ID) {
|
||||
|
||||
/* We only support upto MAX_PHYSMEM_BITS */
|
||||
if ((ea & ~REGION_MASK) > (1UL << MAX_PHYSMEM_BITS))
|
||||
if ((ea & EA_MASK) > (1UL << MAX_PHYSMEM_BITS))
|
||||
return -EFAULT;
|
||||
|
||||
flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_linear_psize].sllp;
|
||||
@@ -702,20 +702,25 @@ static long slb_allocate_kernel(unsigned long ea, unsigned long id)
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
} else if (id == VMEMMAP_REGION_ID) {
|
||||
|
||||
if ((ea & ~REGION_MASK) >= (1ULL << MAX_EA_BITS_PER_CONTEXT))
|
||||
if (ea >= H_VMEMMAP_END)
|
||||
return -EFAULT;
|
||||
|
||||
flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_vmemmap_psize].sllp;
|
||||
#endif
|
||||
} else if (id == VMALLOC_REGION_ID) {
|
||||
|
||||
if ((ea & ~REGION_MASK) >= (1ULL << MAX_EA_BITS_PER_CONTEXT))
|
||||
if (ea >= H_VMALLOC_END)
|
||||
return -EFAULT;
|
||||
|
||||
if (ea < H_VMALLOC_END)
|
||||
flags = local_paca->vmalloc_sllp;
|
||||
else
|
||||
flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_io_psize].sllp;
|
||||
flags = local_paca->vmalloc_sllp;
|
||||
|
||||
} else if (id == IO_REGION_ID) {
|
||||
|
||||
if (ea >= H_KERN_IO_END)
|
||||
return -EFAULT;
|
||||
|
||||
flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_io_psize].sllp;
|
||||
|
||||
} else {
|
||||
return -EFAULT;
|
||||
}
|
||||
@@ -725,6 +730,7 @@ static long slb_allocate_kernel(unsigned long ea, unsigned long id)
|
||||
ssize = MMU_SEGSIZE_256M;
|
||||
|
||||
context = get_kernel_context(ea);
|
||||
|
||||
return slb_insert_entry(ea, context, flags, ssize, true);
|
||||
}
|
||||
|
||||
@@ -761,7 +767,7 @@ static long slb_allocate_user(struct mm_struct *mm, unsigned long ea)
|
||||
|
||||
long do_slb_fault(struct pt_regs *regs, unsigned long ea)
|
||||
{
|
||||
unsigned long id = REGION_ID(ea);
|
||||
unsigned long id = get_region_id(ea);
|
||||
|
||||
/* IRQs are not reconciled here, so can't check irqs_disabled */
|
||||
VM_WARN_ON(mfmsr() & MSR_EE);
|
||||
|
Reference in New Issue
Block a user