Commit 941711a3 authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Michael Ellerman

powerpc/mm/hash: Use context ids 1-4 for the kernel

Currently we use the top 4 context ids (0x7fffc-0x7ffff) for the kernel.
Kernel VSIDs are built using these top context values and effective the
segement ID. In subsequent patches we want to increase the max effective
address to 512TB. We will achieve that by increasing the effective
segment IDs there by increasing virtual address range.

We will be switching to a 68bit virtual address in the following patch.
But platforms like Power4 and Power5 only support a 65 bit virtual
address. We will handle that by limiting the context bits to 16 instead
of 19 on those platforms. That means the max context id will have a
different value on different platforms.

So that we don't have to deal with the kernel context ids changing
between different platforms, move the kernel context ids down to use
context ids 1-4.

We can't use segment 0 of context-id 0, because that maps to VSID 0,
which we want to keep as invalid, so we avoid context-id 0 entirely.
Similarly we can't use the last segment of the maximum context, so we
avoid it too.
Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
[mpe: Switch from 0-3 to 1-4 so VSID=0 remains invalid]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 760573c1
...@@ -491,13 +491,14 @@ extern void slb_set_size(u16 size); ...@@ -491,13 +491,14 @@ extern void slb_set_size(u16 size);
* We first generate a 37-bit "proto-VSID". Proto-VSIDs are generated * We first generate a 37-bit "proto-VSID". Proto-VSIDs are generated
* from mmu context id and effective segment id of the address. * from mmu context id and effective segment id of the address.
* *
* For user processes max context id is limited to ((1ul << 19) - 5) * For user processes max context id is limited to MAX_USER_CONTEXT.
* for kernel space, we use the top 4 context ids to map address as below
* For kernel space, we use context ids 1-5 to map address as below:
* NOTE: each context only support 64TB now. * NOTE: each context only support 64TB now.
* 0x7fffc - [ 0xc000000000000000 - 0xc0003fffffffffff ] * 0x00001 - [ 0xc000000000000000 - 0xc0003fffffffffff ]
* 0x7fffd - [ 0xd000000000000000 - 0xd0003fffffffffff ] * 0x00002 - [ 0xd000000000000000 - 0xd0003fffffffffff ]
* 0x7fffe - [ 0xe000000000000000 - 0xe0003fffffffffff ] * 0x00003 - [ 0xe000000000000000 - 0xe0003fffffffffff ]
* 0x7ffff - [ 0xf000000000000000 - 0xf0003fffffffffff ] * 0x00004 - [ 0xf000000000000000 - 0xf0003fffffffffff ]
* *
* The proto-VSIDs are then scrambled into real VSIDs with the * The proto-VSIDs are then scrambled into real VSIDs with the
* multiplicative hash: * multiplicative hash:
...@@ -511,15 +512,13 @@ extern void slb_set_size(u16 size); ...@@ -511,15 +512,13 @@ extern void slb_set_size(u16 size);
* robust scattering in the hash table (at least based on some initial * robust scattering in the hash table (at least based on some initial
* results). * results).
* *
* We also consider VSID 0 special. We use VSID 0 for slb entries mapping * We use VSID 0 to indicate an invalid VSID. The means we can't use context id
* bad address. This enables us to consolidate bad address handling in * 0, because a context id of 0 and an EA of 0 gives a proto-VSID of 0, which
* hash_page. * will produce a VSID of 0.
* *
* We also need to avoid the last segment of the last context, because that * We also need to avoid the last segment of the last context, because that
* would give a protovsid of 0x1fffffffff. That will result in a VSID 0 * would give a protovsid of 0x1fffffffff. That will result in a VSID 0
* because of the modulo operation in vsid scramble. But the vmemmap * because of the modulo operation in vsid scramble.
* (which is what uses region 0xf) will never be close to 64TB in size
* (it's 56 bytes per page of system memory).
*/ */
#define CONTEXT_BITS 19 #define CONTEXT_BITS 19
...@@ -532,12 +531,19 @@ extern void slb_set_size(u16 size); ...@@ -532,12 +531,19 @@ extern void slb_set_size(u16 size);
/* /*
* 256MB segment * 256MB segment
* The proto-VSID space has 2^(CONTEX_BITS + ESID_BITS) - 1 segments * The proto-VSID space has 2^(CONTEX_BITS + ESID_BITS) - 1 segments
* available for user + kernel mapping. The top 4 contexts are used for * available for user + kernel mapping. VSID 0 is reserved as invalid, contexts
* kernel mapping. Each segment contains 2^28 bytes. Each * 1-4 are used for kernel mapping. Each segment contains 2^28 bytes. Each
* context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts * context maps 2^46 bytes (64TB).
* (19 == 37 + 28 - 46). *
* We also need to avoid the last segment of the last context, because that
* would give a protovsid of 0x1fffffffff. That will result in a VSID 0
* because of the modulo operation in vsid scramble.
*/ */
#define MAX_USER_CONTEXT ((ASM_CONST(1) << CONTEXT_BITS) - 5) #define MAX_USER_CONTEXT ((ASM_CONST(1) << CONTEXT_BITS) - 2)
#define MIN_USER_CONTEXT (5)
/* Would be nice to use KERNEL_REGION_ID here */
#define KERNEL_REGION_CONTEXT_OFFSET (0xc - 1)
/* /*
* This should be computed such that protovosid * vsid_mulitplier * This should be computed such that protovosid * vsid_mulitplier
...@@ -671,21 +677,25 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea, ...@@ -671,21 +677,25 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
/* /*
* This is only valid for addresses >= PAGE_OFFSET * This is only valid for addresses >= PAGE_OFFSET
*
* For kernel space, we use the top 4 context ids to map address as below
* 0x7fffc - [ 0xc000000000000000 - 0xc0003fffffffffff ]
* 0x7fffd - [ 0xd000000000000000 - 0xd0003fffffffffff ]
* 0x7fffe - [ 0xe000000000000000 - 0xe0003fffffffffff ]
* 0x7ffff - [ 0xf000000000000000 - 0xf0003fffffffffff ]
*/ */
static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize) static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
{ {
unsigned long context; unsigned long context;
/* /*
* kernel take the top 4 context from the available range * For kernel space, we use context ids 1-4 to map the address space as
* below:
*
* 0x00001 - [ 0xc000000000000000 - 0xc0003fffffffffff ]
* 0x00002 - [ 0xd000000000000000 - 0xd0003fffffffffff ]
* 0x00003 - [ 0xe000000000000000 - 0xe0003fffffffffff ]
* 0x00004 - [ 0xf000000000000000 - 0xf0003fffffffffff ]
*
* So we can compute the context from the region (top nibble) by
* subtracting 11, or 0xc - 1.
*/ */
context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1; context = (ea >> 60) - KERNEL_REGION_CONTEXT_OFFSET;
return get_vsid(context, ea, ssize); return get_vsid(context, ea, ssize);
} }
......
...@@ -59,7 +59,7 @@ static int alloc_context_id(int min_id, int max_id) ...@@ -59,7 +59,7 @@ static int alloc_context_id(int min_id, int max_id)
int hash__alloc_context_id(void) int hash__alloc_context_id(void)
{ {
return alloc_context_id(1, MAX_USER_CONTEXT); return alloc_context_id(MIN_USER_CONTEXT, MAX_USER_CONTEXT);
} }
EXPORT_SYMBOL_GPL(hash__alloc_context_id); EXPORT_SYMBOL_GPL(hash__alloc_context_id);
......
...@@ -45,13 +45,6 @@ _GLOBAL(slb_allocate_realmode) ...@@ -45,13 +45,6 @@ _GLOBAL(slb_allocate_realmode)
/* r3 = address, r10 = esid, cr7 = <> PAGE_OFFSET */ /* r3 = address, r10 = esid, cr7 = <> PAGE_OFFSET */
blt cr7,0f /* user or kernel? */ blt cr7,0f /* user or kernel? */
/* kernel address: proto-VSID = ESID */
/* WARNING - MAGIC: we don't use the VSID 0xfffffffff, but
* this code will generate the protoVSID 0xfffffffff for the
* top segment. That's ok, the scramble below will translate
* it to VSID 0, which is reserved as a bad VSID - one which
* will never have any pages in it. */
/* Check if hitting the linear mapping or some other kernel space /* Check if hitting the linear mapping or some other kernel space
*/ */
bne cr7,1f bne cr7,1f
...@@ -63,12 +56,10 @@ _GLOBAL(slb_allocate_realmode) ...@@ -63,12 +56,10 @@ _GLOBAL(slb_allocate_realmode)
slb_miss_kernel_load_linear: slb_miss_kernel_load_linear:
li r11,0 li r11,0
/* /*
* context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1 * context = (ea >> 60) - (0xc - 1)
* r9 = region id. * r9 = region id.
*/ */
addis r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@ha subi r9,r9,KERNEL_REGION_CONTEXT_OFFSET
addi r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@l
BEGIN_FTR_SECTION BEGIN_FTR_SECTION
b .Lslb_finish_load b .Lslb_finish_load
...@@ -77,9 +68,9 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT) ...@@ -77,9 +68,9 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
1: 1:
#ifdef CONFIG_SPARSEMEM_VMEMMAP #ifdef CONFIG_SPARSEMEM_VMEMMAP
/* Check virtual memmap region. To be patches at kernel boot */
cmpldi cr0,r9,0xf cmpldi cr0,r9,0xf
bne 1f bne 1f
/* Check virtual memmap region. To be patched at kernel boot */
.globl slb_miss_kernel_load_vmemmap .globl slb_miss_kernel_load_vmemmap
slb_miss_kernel_load_vmemmap: slb_miss_kernel_load_vmemmap:
li r11,0 li r11,0
...@@ -102,11 +93,10 @@ slb_miss_kernel_load_io: ...@@ -102,11 +93,10 @@ slb_miss_kernel_load_io:
li r11,0 li r11,0
6: 6:
/* /*
* context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1 * context = (ea >> 60) - (0xc - 1)
* r9 = region id. * r9 = region id.
*/ */
addis r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@ha subi r9,r9,KERNEL_REGION_CONTEXT_OFFSET
addi r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@l
BEGIN_FTR_SECTION BEGIN_FTR_SECTION
b .Lslb_finish_load b .Lslb_finish_load
......
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