[POWERPC] Use 1TB segments
This makes the kernel use 1TB segments for all kernel mappings and for user addresses of 1TB and above, on machines which support them (currently POWER5+, POWER6 and PA6T). We detect that the machine supports 1TB segments by looking at the ibm,processor-segment-sizes property in the device tree. We don't currently use 1TB segments for user addresses < 1T, since that would effectively prevent 32-bit processes from using huge pages unless we also had a way to revert to using 256MB segments. That would be possible but would involve extra complications (such as keeping track of which segment size was used when HPTEs were inserted) and is not addressed here. Parts of this patch were originally written by Ben Herrenschmidt. Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
@@ -372,9 +372,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
||||
std r6,PACACURRENT(r13) /* Set new 'current' */
|
||||
|
||||
ld r8,KSP(r4) /* new stack pointer */
|
||||
BEGIN_FTR_SECTION
|
||||
b 2f
|
||||
END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
|
||||
BEGIN_FTR_SECTION
|
||||
clrrdi r6,r8,28 /* get its ESID */
|
||||
clrrdi r9,r1,28 /* get current sp ESID */
|
||||
END_FTR_SECTION_IFCLR(CPU_FTR_1T_SEGMENT)
|
||||
BEGIN_FTR_SECTION
|
||||
clrrdi r6,r8,40 /* get its 1T ESID */
|
||||
clrrdi r9,r1,40 /* get current sp 1T ESID */
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_1T_SEGMENT)
|
||||
clrldi. r0,r6,2 /* is new ESID c00000000? */
|
||||
cmpd cr1,r6,r9 /* or is new ESID the same as current ESID? */
|
||||
cror eq,4*cr1+eq,eq
|
||||
@@ -384,6 +392,11 @@ BEGIN_FTR_SECTION
|
||||
ld r7,KSP_VSID(r4) /* Get new stack's VSID */
|
||||
oris r0,r6,(SLB_ESID_V)@h
|
||||
ori r0,r0,(SLB_NUM_BOLTED-1)@l
|
||||
BEGIN_FTR_SECTION
|
||||
li r9,MMU_SEGSIZE_1T /* insert B field */
|
||||
oris r6,r6,(MMU_SEGSIZE_1T << SLBIE_SSIZE_SHIFT)@h
|
||||
rldimi r7,r9,SLB_VSID_SSIZE_SHIFT,0
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_1T_SEGMENT)
|
||||
|
||||
/* Update the last bolted SLB. No write barriers are needed
|
||||
* here, provided we only update the current CPU's SLB shadow
|
||||
@@ -401,7 +414,6 @@ BEGIN_FTR_SECTION
|
||||
isync
|
||||
|
||||
2:
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_SLB)
|
||||
clrrdi r7,r8,THREAD_SHIFT /* base of new stack */
|
||||
/* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE
|
||||
because we don't need to leave the 288-byte ABI gap at the
|
||||
|
@@ -935,7 +935,7 @@ _GLOBAL(do_stab_bolted)
|
||||
|
||||
/* Calculate VSID */
|
||||
/* This is a kernel address, so protovsid = ESID */
|
||||
ASM_VSID_SCRAMBLE(r11, r9)
|
||||
ASM_VSID_SCRAMBLE(r11, r9, 256M)
|
||||
rldic r9,r11,12,16 /* r9 = vsid << 12 */
|
||||
|
||||
/* Search the primary group for a free entry */
|
||||
|
@@ -564,10 +564,15 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
if (cpu_has_feature(CPU_FTR_SLB)) {
|
||||
unsigned long sp_vsid = get_kernel_vsid(sp);
|
||||
unsigned long sp_vsid;
|
||||
unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp;
|
||||
|
||||
sp_vsid <<= SLB_VSID_SHIFT;
|
||||
if (cpu_has_feature(CPU_FTR_1T_SEGMENT))
|
||||
sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_1T)
|
||||
<< SLB_VSID_SHIFT_1T;
|
||||
else
|
||||
sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_256M)
|
||||
<< SLB_VSID_SHIFT;
|
||||
sp_vsid |= SLB_VSID_KERNEL | llp;
|
||||
p->thread.ksp_vsid = sp_vsid;
|
||||
}
|
||||
|
Reference in New Issue
Block a user