Skip to contentSkip to conversation

ppc64 POWER3 segment table fix

PATCH New Anton Blanchard 1 participant 1 message Mar 10, 2004

lore
Share & tools
lore
#0 lore raw

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
diff -p -purNX /suse/olh/kernel/kernel_exclude.txt /dev/shm/linuxppc64-2.5/arch/ppc64/kernel/stab.c linuxppc64-2.5/arch/ppc64/kernel/stab.c
@@ -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;
 	asm volatile("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;