ppc64 POWER3 segment table fix
PATCH 1/1 ppc64 POWER3 segment table fix
Hi,
The ppc64 fix last week (enforcing permissions on the kernel when accessing userspace pages) uncovered a bug on POWER3/RS64. We werent zeroing the segment table entry before overwriting it and it was possible for the ks bit to be set on a kernel segment.
The VSID mask was also changed to match reality (we only use 13 bits).
Anton
===== arch/ppc64/kernel/head.S 1.48 vs edited =====
arch/ppc64/kernel/head.S +11 -10
@@ -904,12 +904,13 @@ /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */ mfspr r21,DAR - rldicl r20,r21,36,32 /* Permits a full 32b of ESID */ - rldicr r20,r20,15,48 - rldicl r21,r21,4,60 - or r20,r20,r21 + rldicl r20,r21,36,51 + sldi r20,r20,15 + srdi r21,r21,60 + or r20,r20,r21 - li r21,9 /* VSID_RANDOMIZER */ + /* VSID_RANDOMIZER */ + li r21,9 sldi r21,r21,32 oris r21,r21,58231 ori r21,r21,39831
@@ -933,11 +934,11 @@ rldicl r23,r23,57,63 cmpwi r23,0 bne 2f - ld r23,8(r21) /* Get the current vsid part of the ste */ + li r23,0 rldimi r23,r20,12,0 /* Insert the new vsid value */ std r23,8(r21) /* Put new entry back into the stab */ eieio /* Order vsid update */ - ld r23,0(r21) /* Get the esid part of the ste */ + li r23,0 mfspr r20,DAR /* Get the new esid */ rldicl r20,r20,36,28 /* Permits a full 36b of ESID */ rldimi r23,r20,28,0 /* Insert the new esid value */
@@ -971,13 +972,13 @@ std r23,0(r21) sync - ld r23,8(r21) + li r23,0 rldimi r23,r20,12,0 std r23,8(r21) eieio - ld r23,0(r21) /* Get the esid part of the ste */ - mr r22,r23 + ld r22,0(r21) /* Get the esid part of the ste */ + li r23,0 mfspr r20,DAR /* Get the new esid */ rldicl r20,r20,36,28 /* Permits a full 32b of ESID */ rldimi r23,r20,28,0 /* Insert the new esid value */
===== include/asm-ppc64/mmu_context.h 1.13 vs edited =====
include/asm-ppc64/mmu_context.h +2 -2
@@ -186,7 +186,7 @@ {unsigned long ordinal, vsid; - ordinal = (((ea >>28 ) &0x1fffff ) *LAST_USER_CONTEXT ) | (ea >>60 ); + ordinal = (((ea >>28 ) &0x1fff ) *LAST_USER_CONTEXT ) | (ea >>60 ); vsid = (ordinal *VSID_RANDOMIZER ) &VSID_MASK ;ifppcdebug (PPCDBG_HTABSTRESS ) {
@@ -209,7 +209,7 @@ {unsigned long ordinal, vsid; - ordinal = (((ea >>28 ) &0x1fffff ) *LAST_USER_CONTEXT ) | context; + ordinal = (((ea >>28 ) &0x1fff ) *LAST_USER_CONTEXT ) | context; vsid = (ordinal *VSID_RANDOMIZER ) &VSID_MASK ;ifppcdebug (PPCDBG_HTABSTRESS ) {
arch/ppc64/kernel/stab.c renamed from dev/shm/linuxppc64-2.5/arch/ppc64/kernel/stab.c +5 -0
@@ -88,6 +88,8 @@ static int make_ste(unsigned long stab,for (group =0 ; group <2 ; group++) {for (entry =0 ; entry <8 ; entry++, ste++) {if (!(ste->dw0.dw0.v)) { + ste->dw0.dword0 =0 ; + ste->dw1.dword1 =0 ; ste->dw1.dw1.vsid = vsid; ste->dw0.dw0.esid = esid; ste->dw0.dw0.kp =1 ;
@@ -135,6 +137,9 @@ static int make_ste(unsigned long stab, castout_ste->dw0.dw0.v =0 ; asmvolatile ("sync" : : :"memory" );/* Order update */ + + castout_ste->dw0.dword0 =0 ; + castout_ste->dw1.dword1 =0 ; castout_ste->dw1.dw1.vsid = vsid; old_esid = castout_ste->dw0.dw0.esid; castout_ste->dw0.dw0.esid = esid;