Commit 9efc74ff authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman
Browse files

powerpc/book3s/32: Use patch_site to patch hash functions



Use patch_sites and the new modify_instruction_site() function
instead of hardcoding hash functions patching.

Signed-off-by: default avatarChristophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 4a3a224c
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -92,6 +92,12 @@ typedef struct {
	unsigned long vdso_base;
} mm_context_t;

/* patch sites */
extern s32 patch__hash_page_A0, patch__hash_page_A1, patch__hash_page_A2;
extern s32 patch__hash_page_B, patch__hash_page_C;
extern s32 patch__flush_hash_A0, patch__flush_hash_A1, patch__flush_hash_A2;
extern s32 patch__flush_hash_B;

#endif /* !__ASSEMBLY__ */

/* We happily ignore the smaller BATs on 601, we don't actually use
+19 −14
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <asm/asm-offsets.h>
#include <asm/export.h>
#include <asm/feature-fixups.h>
#include <asm/code-patching-asm.h>

#ifdef CONFIG_SMP
	.section .bss
@@ -337,11 +338,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
	rlwimi	r5,r4,10,26,31		/* put in API (abbrev page index) */
	SET_V(r5)			/* set V (valid) bit */

	patch_site	0f, patch__hash_page_A0
	patch_site	1f, patch__hash_page_A1
	patch_site	2f, patch__hash_page_A2
	/* Get the address of the primary PTE group in the hash table (r3) */
_GLOBAL(hash_page_patch_A)
	addis	r0,r7,Hash_base@h	/* base address of hash table */
	rlwimi	r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT    /* VSID -> hash */
	rlwinm	r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
0:	addis	r0,r7,Hash_base@h	/* base address of hash table */
1:	rlwimi	r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT    /* VSID -> hash */
2:	rlwinm	r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
	xor	r3,r3,r0		/* make primary hash */
	li	r0,8			/* PTEs/group */

@@ -366,10 +369,10 @@ _GLOBAL(hash_page_patch_A)
	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
	beq+	found_slot

	patch_site	0f, patch__hash_page_B
	/* Search the secondary PTEG for a matching PTE */
	ori	r5,r5,PTE_H		/* set H (secondary hash) bit */
_GLOBAL(hash_page_patch_B)
	xoris	r4,r3,Hash_msk>>16	/* compute secondary hash */
0:	xoris	r4,r3,Hash_msk>>16	/* compute secondary hash */
	xori	r4,r4,(-PTEG_SIZE & 0xffff)
	addi	r4,r4,-HPTE_SIZE
	mtctr	r0
@@ -393,10 +396,10 @@ _GLOBAL(hash_page_patch_B)
	addi	r6,r6,1
	stw	r6,primary_pteg_full@l(r4)

	patch_site	0f, patch__hash_page_C
	/* Search the secondary PTEG for an empty slot */
	ori	r5,r5,PTE_H		/* set H (secondary hash) bit */
_GLOBAL(hash_page_patch_C)
	xoris	r4,r3,Hash_msk>>16	/* compute secondary hash */
0:	xoris	r4,r3,Hash_msk>>16	/* compute secondary hash */
	xori	r4,r4,(-PTEG_SIZE & 0xffff)
	addi	r4,r4,-HPTE_SIZE
	mtctr	r0
@@ -577,11 +580,13 @@ _GLOBAL(flush_hash_pages)
	stwcx.	r8,0,r5			/* update the pte */
	bne-	33b

	patch_site	0f, patch__flush_hash_A0
	patch_site	1f, patch__flush_hash_A1
	patch_site	2f, patch__flush_hash_A2
	/* Get the address of the primary PTE group in the hash table (r3) */
_GLOBAL(flush_hash_patch_A)
	addis	r8,r7,Hash_base@h	/* base address of hash table */
	rlwimi	r8,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT    /* VSID -> hash */
	rlwinm	r0,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
0:	addis	r8,r7,Hash_base@h	/* base address of hash table */
1:	rlwimi	r8,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT    /* VSID -> hash */
2:	rlwinm	r0,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
	xor	r8,r0,r8		/* make primary hash */

	/* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
@@ -593,11 +598,11 @@ _GLOBAL(flush_hash_patch_A)
	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
	beq+	3f

	patch_site	0f, patch__flush_hash_B
	/* Search the secondary PTEG for a matching PTE */
	ori	r11,r11,PTE_H		/* set H (secondary hash) bit */
	li	r0,8			/* PTEs/group */
_GLOBAL(flush_hash_patch_B)
	xoris	r12,r8,Hash_msk>>16	/* compute secondary hash */
0:	xoris	r12,r8,Hash_msk>>16	/* compute secondary hash */
	xori	r12,r12,(-PTEG_SIZE & 0xffff)
	addi	r12,r12,-HPTE_SIZE
	mtctr	r0
+10 −25
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <asm/prom.h>
#include <asm/mmu.h>
#include <asm/machdep.h>
#include <asm/code-patching.h>

#include "mmu_decl.h"

@@ -182,10 +183,6 @@ void __init MMU_init_hw(void)
	unsigned int hmask, mb, mb2;
	unsigned int n_hpteg, lg_n_hpteg;

	extern unsigned int hash_page_patch_A[];
	extern unsigned int hash_page_patch_B[], hash_page_patch_C[];
	extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[];

	if (!mmu_has_feature(MMU_FTR_HPTE_TABLE))
		return;

@@ -234,31 +231,19 @@ void __init MMU_init_hw(void)
	if (lg_n_hpteg > 16)
		mb2 = 16 - LG_HPTEG_SIZE;

	hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)
		| ((unsigned int)(Hash) >> 16);
	hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) | (mb << 6);
	hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) | (mb2 << 6);
	hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff) | hmask;
	hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) | hmask;

	/*
	 * Ensure that the locations we've patched have been written
	 * out from the data cache and invalidated in the instruction
	 * cache, on those machines with split caches.
	 */
	flush_icache_range((unsigned long) &hash_page_patch_A[0],
			   (unsigned long) &hash_page_patch_C[1]);
	modify_instruction_site(&patch__hash_page_A0, 0xffff, (unsigned int)Hash >> 16);
	modify_instruction_site(&patch__hash_page_A1, 0x7c0, mb << 6);
	modify_instruction_site(&patch__hash_page_A2, 0x7c0, mb2 << 6);
	modify_instruction_site(&patch__hash_page_B, 0xffff, hmask);
	modify_instruction_site(&patch__hash_page_C, 0xffff, hmask);

	/*
	 * Patch up the instructions in hashtable.S:flush_hash_page
	 */
	flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff)
		| ((unsigned int)(Hash) >> 16);
	flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0) | (mb << 6);
	flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0) | (mb2 << 6);
	flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff) | hmask;
	flush_icache_range((unsigned long) &flush_hash_patch_A[0],
			   (unsigned long) &flush_hash_patch_B[1]);
	modify_instruction_site(&patch__flush_hash_A0, 0xffff, (unsigned int)Hash >> 16);
	modify_instruction_site(&patch__flush_hash_A1, 0x7c0, mb << 6);
	modify_instruction_site(&patch__flush_hash_A2, 0x7c0, mb2 << 6);
	modify_instruction_site(&patch__flush_hash_B, 0xffff, hmask);

	if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
}