Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1189be65 authored by Paul Mackerras's avatar Paul Mackerras
Browse files

[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: default avatarPaul Mackerras <paulus@samba.org>
parent 287e5d6f
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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 */
+7 −2
Original line number Diff line number Diff line
@@ -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;
	}
+65 −8
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@

/*
 * _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
 *		 pte_t *ptep, unsigned long trap, int local)
 *		 pte_t *ptep, unsigned long trap, int local, int ssize)
 *
 * Adds a 4K page to the hash table in a segment of 4K pages only
 */
@@ -66,6 +66,7 @@ _GLOBAL(__hash_page_4K)
	/* Save all params that we need after a function call */
	std	r6,STK_PARM(r6)(r1)
	std	r8,STK_PARM(r8)(r1)
	std	r9,STK_PARM(r9)(r1)
	
	/* Add _PAGE_PRESENT to access */
	ori	r4,r4,_PAGE_PRESENT
@@ -117,6 +118,10 @@ _GLOBAL(__hash_page_4K)
	 * r4 (access) is re-useable, we use it for the new HPTE flags
	 */

BEGIN_FTR_SECTION
	cmpdi	r9,0			/* check segment size */
	bne	3f
END_FTR_SECTION_IFSET(CPU_FTR_1T_SEGMENT)
	/* Calc va and put it in r29 */
	rldicr	r29,r5,28,63-28
	rldicl	r3,r3,0,36
@@ -126,9 +131,20 @@ _GLOBAL(__hash_page_4K)
	rldicl	r5,r5,0,25		/* vsid & 0x0000007fffffffff */
	rldicl	r0,r3,64-12,48		/* (ea >> 12) & 0xffff */
	xor	r28,r5,r0
	b	4f

3:	/* Calc VA and hash in r29 and r28 for 1T segment */
	sldi	r29,r5,40		/* vsid << 40 */
	clrldi	r3,r3,24		/* ea & 0xffffffffff */
	rldic	r28,r5,25,25		/* (vsid << 25) & 0x7fffffffff */
	clrldi	r5,r5,40		/* vsid & 0xffffff */
	rldicl	r0,r3,64-12,36		/* (ea >> 12) & 0xfffffff */
	xor	r28,r28,r5
	or	r29,r3,r29		/* VA */
	xor	r28,r28,r0		/* hash */

	/* Convert linux PTE bits into HW equivalents */
	andi.	r3,r30,0x1fe		/* Get basic set of flags */
4:	andi.	r3,r30,0x1fe		/* Get basic set of flags */
	xori	r3,r3,HPTE_R_N		/* _PAGE_EXEC -> NOEXEC */
	rlwinm	r0,r30,32-9+1,30,30	/* _PAGE_RW -> _PAGE_USER (r0) */
	rlwinm	r4,r30,32-7+1,30,30	/* _PAGE_DIRTY -> _PAGE_USER (r4) */
@@ -183,6 +199,7 @@ htab_insert_pte:
	mr	r4,r29			/* Retreive va */
	li	r7,0			/* !bolted, !secondary */
	li	r8,MMU_PAGE_4K		/* page size */
	ld	r9,STK_PARM(r9)(r1)	/* segment size */
_GLOBAL(htab_call_hpte_insert1)
	bl	.			/* Patched by htab_finish_init() */
	cmpdi	0,r3,0
@@ -205,6 +222,7 @@ _GLOBAL(htab_call_hpte_insert1)
	mr	r4,r29			/* Retreive va */
	li	r7,HPTE_V_SECONDARY	/* !bolted, secondary */
	li	r8,MMU_PAGE_4K		/* page size */
	ld	r9,STK_PARM(r9)(r1)	/* segment size */
_GLOBAL(htab_call_hpte_insert2)
	bl	.			/* Patched by htab_finish_init() */
	cmpdi	0,r3,0
@@ -273,7 +291,8 @@ htab_modify_pte:
	/* Call ppc_md.hpte_updatepp */
	mr	r5,r29			/* va */
	li	r6,MMU_PAGE_4K		/* page size */
	ld	r7,STK_PARM(r8)(r1)	/* get "local" param */
	ld	r7,STK_PARM(r9)(r1)	/* segment size */
	ld	r8,STK_PARM(r8)(r1)	/* get "local" param */
_GLOBAL(htab_call_hpte_updatepp)
	bl	.			/* Patched by htab_finish_init() */

@@ -325,6 +344,7 @@ _GLOBAL(__hash_page_4K)
	/* Save all params that we need after a function call */
	std	r6,STK_PARM(r6)(r1)
	std	r8,STK_PARM(r8)(r1)
	std	r9,STK_PARM(r9)(r1)

	/* Add _PAGE_PRESENT to access */
	ori	r4,r4,_PAGE_PRESENT
@@ -383,18 +403,33 @@ _GLOBAL(__hash_page_4K)
	/* Load the hidx index */
	rldicl	r25,r3,64-12,60

BEGIN_FTR_SECTION
	cmpdi	r9,0			/* check segment size */
	bne	3f
END_FTR_SECTION_IFSET(CPU_FTR_1T_SEGMENT)
	/* Calc va and put it in r29 */
	rldicr	r29,r5,28,63-28		/* r29 = (vsid << 28) */
	rldicl	r3,r3,0,36		/* r3 = (ea & 0x0fffffff) */
	or	r29,r3,r29		/* r29 = va
	or	r29,r3,r29		/* r29 = va */

	/* Calculate hash value for primary slot and store it in r28 */
	rldicl	r5,r5,0,25		/* vsid & 0x0000007fffffffff */
	rldicl	r0,r3,64-12,48		/* (ea >> 12) & 0xffff */
	xor	r28,r5,r0
	b	4f

3:	/* Calc VA and hash in r29 and r28 for 1T segment */
	sldi	r29,r5,40		/* vsid << 40 */
	clrldi	r3,r3,24		/* ea & 0xffffffffff */
	rldic	r28,r5,25,25		/* (vsid << 25) & 0x7fffffffff */
	clrldi	r5,r5,40		/* vsid & 0xffffff */
	rldicl	r0,r3,64-12,36		/* (ea >> 12) & 0xfffffff */
	xor	r28,r28,r5
	or	r29,r3,r29		/* VA */
	xor	r28,r28,r0		/* hash */

	/* Convert linux PTE bits into HW equivalents */
	andi.	r3,r30,0x1fe		/* Get basic set of flags */
4:	andi.	r3,r30,0x1fe		/* Get basic set of flags */
	xori	r3,r3,HPTE_R_N		/* _PAGE_EXEC -> NOEXEC */
	rlwinm	r0,r30,32-9+1,30,30	/* _PAGE_RW -> _PAGE_USER (r0) */
	rlwinm	r4,r30,32-7+1,30,30	/* _PAGE_DIRTY -> _PAGE_USER (r4) */
@@ -462,6 +497,7 @@ htab_special_pfn:
	mr	r4,r29			/* Retreive va */
	li	r7,0			/* !bolted, !secondary */
	li	r8,MMU_PAGE_4K		/* page size */
	ld	r9,STK_PARM(r9)(r1)	/* segment size */
_GLOBAL(htab_call_hpte_insert1)
	bl	.			/* patched by htab_finish_init() */
	cmpdi	0,r3,0
@@ -488,6 +524,7 @@ _GLOBAL(htab_call_hpte_insert1)
	mr	r4,r29			/* Retreive va */
	li	r7,HPTE_V_SECONDARY	/* !bolted, secondary */
	li	r8,MMU_PAGE_4K		/* page size */
	ld	r9,STK_PARM(r9)(r1)	/* segment size */
_GLOBAL(htab_call_hpte_insert2)
	bl	.			/* patched by htab_finish_init() */
	cmpdi	0,r3,0
@@ -586,7 +623,8 @@ htab_modify_pte:
	/* Call ppc_md.hpte_updatepp */
	mr	r5,r29			/* va */
	li	r6,MMU_PAGE_4K		/* page size */
	ld	r7,STK_PARM(r8)(r1)	/* get "local" param */
	ld	r7,STK_PARM(r9)(r1)	/* segment size */
	ld	r8,STK_PARM(r8)(r1)	/* get "local" param */
_GLOBAL(htab_call_hpte_updatepp)
	bl	.			/* patched by htab_finish_init() */

@@ -634,6 +672,7 @@ _GLOBAL(__hash_page_64K)
	/* Save all params that we need after a function call */
	std	r6,STK_PARM(r6)(r1)
	std	r8,STK_PARM(r8)(r1)
	std	r9,STK_PARM(r9)(r1)

	/* Add _PAGE_PRESENT to access */
	ori	r4,r4,_PAGE_PRESENT
@@ -690,6 +729,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE)
	 * r4 (access) is re-useable, we use it for the new HPTE flags
	 */

BEGIN_FTR_SECTION
	cmpdi	r9,0			/* check segment size */
	bne	3f
END_FTR_SECTION_IFSET(CPU_FTR_1T_SEGMENT)
	/* Calc va and put it in r29 */
	rldicr	r29,r5,28,63-28
	rldicl	r3,r3,0,36
@@ -699,9 +742,20 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE)
	rldicl	r5,r5,0,25		/* vsid & 0x0000007fffffffff */
	rldicl	r0,r3,64-16,52		/* (ea >> 16) & 0xfff */
	xor	r28,r5,r0
	b	4f

3:	/* Calc VA and hash in r29 and r28 for 1T segment */
	sldi	r29,r5,40		/* vsid << 40 */
	clrldi	r3,r3,24		/* ea & 0xffffffffff */
	rldic	r28,r5,25,25		/* (vsid << 25) & 0x7fffffffff */
	clrldi	r5,r5,40		/* vsid & 0xffffff */
	rldicl	r0,r3,64-16,40		/* (ea >> 16) & 0xffffff */
	xor	r28,r28,r5
	or	r29,r3,r29		/* VA */
	xor	r28,r28,r0		/* hash */

	/* Convert linux PTE bits into HW equivalents */
	andi.	r3,r30,0x1fe		/* Get basic set of flags */
4:	andi.	r3,r30,0x1fe		/* Get basic set of flags */
	xori	r3,r3,HPTE_R_N		/* _PAGE_EXEC -> NOEXEC */
	rlwinm	r0,r30,32-9+1,30,30	/* _PAGE_RW -> _PAGE_USER (r0) */
	rlwinm	r4,r30,32-7+1,30,30	/* _PAGE_DIRTY -> _PAGE_USER (r4) */
@@ -756,6 +810,7 @@ ht64_insert_pte:
	mr	r4,r29			/* Retreive va */
	li	r7,0			/* !bolted, !secondary */
	li	r8,MMU_PAGE_64K
	ld	r9,STK_PARM(r9)(r1)	/* segment size */
_GLOBAL(ht64_call_hpte_insert1)
	bl	.			/* patched by htab_finish_init() */
	cmpdi	0,r3,0
@@ -778,6 +833,7 @@ _GLOBAL(ht64_call_hpte_insert1)
	mr	r4,r29			/* Retreive va */
	li	r7,HPTE_V_SECONDARY	/* !bolted, secondary */
	li	r8,MMU_PAGE_64K
	ld	r9,STK_PARM(r9)(r1)	/* segment size */
_GLOBAL(ht64_call_hpte_insert2)
	bl	.			/* patched by htab_finish_init() */
	cmpdi	0,r3,0
@@ -846,7 +902,8 @@ ht64_modify_pte:
	/* Call ppc_md.hpte_updatepp */
	mr	r5,r29			/* va */
	li	r6,MMU_PAGE_64K
	ld	r7,STK_PARM(r8)(r1)	/* get "local" param */
	ld	r7,STK_PARM(r9)(r1)	/* segment size */
	ld	r8,STK_PARM(r8)(r1)	/* get "local" param */
_GLOBAL(ht64_call_hpte_updatepp)
	bl	.			/* patched by htab_finish_init() */

+46 −46
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@

static DEFINE_SPINLOCK(native_tlbie_lock);

static inline void __tlbie(unsigned long va, unsigned int psize)
static inline void __tlbie(unsigned long va, int psize, int ssize)
{
	unsigned int penc;

@@ -48,18 +48,20 @@ static inline void __tlbie(unsigned long va, unsigned int psize)
	switch (psize) {
	case MMU_PAGE_4K:
		va &= ~0xffful;
		va |= ssize << 8;
		asm volatile("tlbie %0,0" : : "r" (va) : "memory");
		break;
	default:
		penc = mmu_psize_defs[psize].penc;
		va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
		va |= penc << 12;
		va |= ssize << 8;
		asm volatile("tlbie %0,1" : : "r" (va) : "memory");
		break;
	}
}

static inline void __tlbiel(unsigned long va, unsigned int psize)
static inline void __tlbiel(unsigned long va, int psize, int ssize)
{
	unsigned int penc;

@@ -69,6 +71,7 @@ static inline void __tlbiel(unsigned long va, unsigned int psize)
	switch (psize) {
	case MMU_PAGE_4K:
		va &= ~0xffful;
		va |= ssize << 8;
		asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)"
			     : : "r"(va) : "memory");
		break;
@@ -76,6 +79,7 @@ static inline void __tlbiel(unsigned long va, unsigned int psize)
		penc = mmu_psize_defs[psize].penc;
		va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
		va |= penc << 12;
		va |= ssize << 8;
		asm volatile(".long 0x7c000224 | (%0 << 11) | (1 << 21)"
			     : : "r"(va) : "memory");
		break;
@@ -83,7 +87,7 @@ static inline void __tlbiel(unsigned long va, unsigned int psize)

}

static inline void tlbie(unsigned long va, int psize, int local)
static inline void tlbie(unsigned long va, int psize, int ssize, int local)
{
	unsigned int use_local = local && cpu_has_feature(CPU_FTR_TLBIEL);
	int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
@@ -94,10 +98,10 @@ static inline void tlbie(unsigned long va, int psize, int local)
		spin_lock(&native_tlbie_lock);
	asm volatile("ptesync": : :"memory");
	if (use_local) {
		__tlbiel(va, psize);
		__tlbiel(va, psize, ssize);
		asm volatile("ptesync": : :"memory");
	} else {
		__tlbie(va, psize);
		__tlbie(va, psize, ssize);
		asm volatile("eieio; tlbsync; ptesync": : :"memory");
	}
	if (lock_tlbie && !use_local)
@@ -126,7 +130,7 @@ static inline void native_unlock_hpte(struct hash_pte *hptep)

static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
			unsigned long pa, unsigned long rflags,
			unsigned long vflags, int psize)
			unsigned long vflags, int psize, int ssize)
{
	struct hash_pte *hptep = htab_address + hpte_group;
	unsigned long hpte_v, hpte_r;
@@ -153,7 +157,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
	if (i == HPTES_PER_GROUP)
		return -1;

	hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID;
	hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
	hpte_r = hpte_encode_r(pa, psize) | rflags;

	if (!(vflags & HPTE_V_BOLTED)) {
@@ -215,13 +219,14 @@ static long native_hpte_remove(unsigned long hpte_group)
}

static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
				 unsigned long va, int psize, int local)
				 unsigned long va, int psize, int ssize,
				 int local)
{
	struct hash_pte *hptep = htab_address + slot;
	unsigned long hpte_v, want_v;
	int ret = 0;

	want_v = hpte_encode_v(va, psize);
	want_v = hpte_encode_v(va, psize, ssize);

	DBG_LOW("    update(va=%016lx, avpnv=%016lx, hash=%016lx, newpp=%x)",
		va, want_v & HPTE_V_AVPN, slot, newpp);
@@ -243,40 +248,33 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
	native_unlock_hpte(hptep);

	/* Ensure it is out of the tlb too. */
	tlbie(va, psize, local);
	tlbie(va, psize, ssize, local);

	return ret;
}

static long native_hpte_find(unsigned long va, int psize)
static long native_hpte_find(unsigned long va, int psize, int ssize)
{
	struct hash_pte *hptep;
	unsigned long hash;
	unsigned long i, j;
	unsigned long i;
	long slot;
	unsigned long want_v, hpte_v;

	hash = hpt_hash(va, mmu_psize_defs[psize].shift);
	want_v = hpte_encode_v(va, psize);
	hash = hpt_hash(va, mmu_psize_defs[psize].shift, ssize);
	want_v = hpte_encode_v(va, psize, ssize);

	for (j = 0; j < 2; j++) {
	/* Bolted mappings are only ever in the primary group */
	slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
	for (i = 0; i < HPTES_PER_GROUP; i++) {
		hptep = htab_address + slot;
		hpte_v = hptep->v;

			if (HPTE_V_COMPARE(hpte_v, want_v)
			    && (hpte_v & HPTE_V_VALID)
			    && ( !!(hpte_v & HPTE_V_SECONDARY) == j)) {
		if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID))
			/* HPTE matches */
				if (j)
					slot = -slot;
			return slot;
			}
		++slot;
	}
		hash = ~hash;
	}

	return -1;
}
@@ -289,16 +287,16 @@ static long native_hpte_find(unsigned long va, int psize)
 * No need to lock here because we should be the only user.
 */
static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
				       int psize)
				       int psize, int ssize)
{
	unsigned long vsid, va;
	long slot;
	struct hash_pte *hptep;

	vsid = get_kernel_vsid(ea);
	va = (vsid << 28) | (ea & 0x0fffffff);
	vsid = get_kernel_vsid(ea, ssize);
	va = hpt_va(ea, vsid, ssize);

	slot = native_hpte_find(va, psize);
	slot = native_hpte_find(va, psize, ssize);
	if (slot == -1)
		panic("could not find page to bolt\n");
	hptep = htab_address + slot;
@@ -308,11 +306,11 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
		(newpp & (HPTE_R_PP | HPTE_R_N));

	/* Ensure it is out of the tlb too. */
	tlbie(va, psize, 0);
	tlbie(va, psize, ssize, 0);
}

static void native_hpte_invalidate(unsigned long slot, unsigned long va,
				   int psize, int local)
				   int psize, int ssize, int local)
{
	struct hash_pte *hptep = htab_address + slot;
	unsigned long hpte_v;
@@ -323,7 +321,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,

	DBG_LOW("    invalidate(va=%016lx, hash: %x)\n", va, slot);

	want_v = hpte_encode_v(va, psize);
	want_v = hpte_encode_v(va, psize, ssize);
	native_lock_hpte(hptep);
	hpte_v = hptep->v;

@@ -335,7 +333,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
		hptep->v = 0;

	/* Invalidate the TLB */
	tlbie(va, psize, local);
	tlbie(va, psize, ssize, local);

	local_irq_restore(flags);
}
@@ -345,7 +343,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
#define LP_MASK(i)	((0xFF >> (i)) << LP_SHIFT)

static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
			int *psize, unsigned long *va)
			int *psize, int *ssize, unsigned long *va)
{
	unsigned long hpte_r = hpte->r;
	unsigned long hpte_v = hpte->v;
@@ -401,6 +399,7 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,

	*va = avpn;
	*psize = size;
	*ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
}

/*
@@ -417,7 +416,7 @@ static void native_hpte_clear(void)
	struct hash_pte *hptep = htab_address;
	unsigned long hpte_v, va;
	unsigned long pteg_count;
	int psize;
	int psize, ssize;

	pteg_count = htab_hash_mask + 1;

@@ -443,9 +442,9 @@ static void native_hpte_clear(void)
		 * already hold the native_tlbie_lock.
		 */
		if (hpte_v & HPTE_V_VALID) {
			hpte_decode(hptep, slot, &psize, &va);
			hpte_decode(hptep, slot, &psize, &ssize, &va);
			hptep->v = 0;
			__tlbie(va, psize);
			__tlbie(va, psize, ssize);
		}
	}

@@ -468,6 +467,7 @@ static void native_flush_hash_range(unsigned long number, int local)
	real_pte_t pte;
	struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
	unsigned long psize = batch->psize;
	int ssize = batch->ssize;
	int i;

	local_irq_save(flags);
@@ -477,14 +477,14 @@ static void native_flush_hash_range(unsigned long number, int local)
		pte = batch->pte[i];

		pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
			hash = hpt_hash(va, shift);
			hash = hpt_hash(va, shift, ssize);
			hidx = __rpte_to_hidx(pte, index);
			if (hidx & _PTEIDX_SECONDARY)
				hash = ~hash;
			slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
			slot += hidx & _PTEIDX_GROUP_IX;
			hptep = htab_address + slot;
			want_v = hpte_encode_v(va, psize);
			want_v = hpte_encode_v(va, psize, ssize);
			native_lock_hpte(hptep);
			hpte_v = hptep->v;
			if (!HPTE_V_COMPARE(hpte_v, want_v) ||
@@ -504,7 +504,7 @@ static void native_flush_hash_range(unsigned long number, int local)

			pte_iterate_hashed_subpages(pte, psize, va, index,
						    shift) {
				__tlbiel(va, psize);
				__tlbiel(va, psize, ssize);
			} pte_iterate_hashed_end();
		}
		asm volatile("ptesync":::"memory");
@@ -521,7 +521,7 @@ static void native_flush_hash_range(unsigned long number, int local)

			pte_iterate_hashed_subpages(pte, psize, va, index,
						    shift) {
				__tlbie(va, psize);
				__tlbie(va, psize, ssize);
			} pte_iterate_hashed_end();
		}
		asm volatile("eieio; tlbsync; ptesync":::"memory");
Loading