200 lines
		
	
	
	
		
			4 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
		
		
			
		
	
	
			200 lines
		
	
	
	
		
			4 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
|   | /* | ||
|  |  * arch/score/mm/tlbex.S | ||
|  |  * | ||
|  |  * Score Processor version. | ||
|  |  * | ||
|  |  * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
|  |  *  Lennox Wu <lennox.wu@sunplusct.com>
 | ||
|  |  *  Chen Liqin <liqin.chen@sunplusct.com>
 | ||
|  |  * | ||
|  |  * This program is free software; you can redistribute it and/or modify
 | ||
|  |  * it under the terms of the GNU General Public License as published by | ||
|  |  * the Free Software Foundation; either version 2 of the License, or
 | ||
|  |  * (at your option) any later version. | ||
|  |  * | ||
|  |  * This program is distributed in the hope that it will be useful, | ||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||
|  |  * GNU General Public License for more details. | ||
|  |  * | ||
|  |  * You should have received a copy of the GNU General Public License | ||
|  |  * along with this program; if not, see the file COPYING, or write
 | ||
|  |  * to the Free Software Foundation, Inc., | ||
|  |  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | ||
|  |  */ | ||
|  | 
 | ||
|  | #include <asm/asmmacro.h> | ||
|  | #include <asm/pgtable-bits.h> | ||
|  | #include <asm/scoreregs.h> | ||
|  | 
 | ||
|  | /* | ||
|  | * After this macro runs, the pte faulted on is | ||
|  | * in register PTE, a ptr into the table in which | ||
|  | * the pte belongs is in PTR. | ||
|  | */ | ||
|  | 	.macro	load_pte, pte, ptr | ||
|  | 	la	\ptr, pgd_current | ||
|  | 	lw	\ptr, [\ptr, 0] | ||
|  | 	mfcr	\pte, cr6 | ||
|  | 	srli	\pte, \pte, 22 | ||
|  | 	slli	\pte, \pte, 2 | ||
|  | 	add	\ptr, \ptr, \pte | ||
|  | 	lw	\ptr, [\ptr, 0] | ||
|  | 	mfcr	\pte, cr6 | ||
|  | 	srli	\pte, \pte, 10 | ||
|  | 	andi	\pte, 0xffc | ||
|  | 	add	\ptr, \ptr, \pte | ||
|  | 	lw	\pte, [\ptr, 0] | ||
|  | 	.endm | ||
|  | 
 | ||
|  | 	.macro	pte_reload, ptr | ||
|  | 	lw	\ptr, [\ptr, 0] | ||
|  | 	mtcr	\ptr, cr12 | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	.endm | ||
|  | 
 | ||
|  | 	.macro do_fault, write | ||
|  | 	SAVE_ALL | ||
|  | 	mfcr	r6, cr6 | ||
|  | 	mv	r4, r0 | ||
|  | 	ldi	r5, \write | ||
|  | 	la	r8, do_page_fault | ||
|  | 	brl	r8 | ||
|  | 	j	ret_from_exception | ||
|  | 	.endm | ||
|  | 
 | ||
|  | 	.macro	pte_writable, pte, ptr, label | ||
|  | 	andi	\pte, 0x280 | ||
|  | 	cmpi.c	\pte, 0x280 | ||
|  | 	bne	\label | ||
|  | 	lw	\pte, [\ptr, 0]		/*reload PTE*/ | ||
|  | 	.endm | ||
|  | 
 | ||
|  | /* | ||
|  |  * Make PTE writable, update software status bits as well, | ||
|  |  * then store at PTR. | ||
|  |  */ | ||
|  | 	.macro	pte_makewrite, pte, ptr | ||
|  | 	ori	\pte, 0x426 | ||
|  | 	sw	\pte, [\ptr, 0] | ||
|  | 	.endm | ||
|  | 
 | ||
|  | 	.text | ||
|  | ENTRY(score7_FTLB_refill_Handler) | ||
|  | 	la	r31, pgd_current	/* get pgd pointer */ | ||
|  | 	lw	r31, [r31, 0]		/* get the address of PGD */ | ||
|  | 	mfcr	r30, cr6 | ||
|  | 	srli	r30, r30, 22		/* PGDIR_SHIFT = 22*/ | ||
|  | 	slli	r30, r30, 2 | ||
|  | 	add	r31, r31, r30 | ||
|  | 	lw	r31, [r31, 0]		/* get the address of the start address of PTE table */ | ||
|  | 
 | ||
|  | 	mfcr	r30, cr9 | ||
|  | 	andi	r30, 0xfff 		/* equivalent to get PET index and right shift 2 bits */ | ||
|  | 	add	r31, r31, r30 | ||
|  | 	lw	r30, [r31, 0]		/* load pte entry */ | ||
|  | 	mtcr	r30, cr12 | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	mtrtlb | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	rte				/* 6 cycles to make sure tlb entry works */ | ||
|  | 
 | ||
|  | ENTRY(score7_KSEG_refill_Handler) | ||
|  | 	la	r31, pgd_current	/* get pgd pointer */ | ||
|  | 	lw	r31, [r31, 0]		/* get the address of PGD */ | ||
|  | 	mfcr	r30, cr6 | ||
|  | 	srli	r30, r30, 22		/* PGDIR_SHIFT = 22 */ | ||
|  | 	slli	r30, r30, 2 | ||
|  | 	add	r31, r31, r30 | ||
|  | 	lw	r31, [r31, 0]		/* get the address of the start address of PTE table */ | ||
|  | 
 | ||
|  | 	mfcr	r30, cr6		/* get Bad VPN */ | ||
|  | 	srli	r30, r30, 10 | ||
|  | 	andi	r30, 0xffc		/* PTE VPN mask (bit 11~2) */ | ||
|  | 
 | ||
|  | 	add	r31, r31, r30 | ||
|  | 	lw	r30, [r31, 0]		/* load pte entry */ | ||
|  | 	mtcr	r30, cr12 | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	mtrtlb | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	rte				/* 6 cycles to make sure tlb entry works */ | ||
|  | 
 | ||
|  | nopage_tlbl: | ||
|  | 	do_fault	0		/* Read */ | ||
|  | 
 | ||
|  | ENTRY(handle_tlb_refill) | ||
|  | 	load_pte	r30, r31 | ||
|  | 	pte_writable	r30, r31, handle_tlb_refill_nopage | ||
|  | 	pte_makewrite	r30, r31	/* Access|Modify|Dirty|Valid */ | ||
|  | 	pte_reload	r31 | ||
|  | 	mtrtlb | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	rte | ||
|  | handle_tlb_refill_nopage: | ||
|  | 	do_fault	0		/* Read */ | ||
|  | 
 | ||
|  | ENTRY(handle_tlb_invaild) | ||
|  | 	load_pte	r30, r31 | ||
|  | 	stlb				/* find faulting entry */ | ||
|  | 	pte_writable	r30, r31, handle_tlb_invaild_nopage | ||
|  | 	pte_makewrite	r30, r31	/* Access|Modify|Dirty|Valid */ | ||
|  | 	pte_reload	r31 | ||
|  | 	mtptlb | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	rte | ||
|  | handle_tlb_invaild_nopage: | ||
|  | 	do_fault	0		/* Read */ | ||
|  | 
 | ||
|  | ENTRY(handle_mod) | ||
|  | 	load_pte	r30, r31 | ||
|  | 	stlb				/* find faulting entry */ | ||
|  | 	andi	r30, _PAGE_WRITE	/* Writable? */ | ||
|  | 	cmpz.c	r30 | ||
|  | 	beq	nowrite_mod | ||
|  | 	lw	r30, [r31, 0]		/* reload into r30 */ | ||
|  | 
 | ||
|  | 	/* Present and writable bits set, set accessed and dirty bits. */ | ||
|  | 	pte_makewrite	r30, r31 | ||
|  | 
 | ||
|  | 	/* Now reload the entry into the tlb. */ | ||
|  | 	pte_reload	r31 | ||
|  | 	mtptlb | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	nop | ||
|  | 	rte | ||
|  | 
 | ||
|  | nowrite_mod: | ||
|  | 	do_fault	1	/* Write */ |