|  | ############################################################################### | 
|  | # | 
|  | # TLB loading functions | 
|  | # | 
|  | # Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd. | 
|  | # Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 
|  | # Modified by David Howells (dhowells@redhat.com) | 
|  | # | 
|  | # This program is free software; you can redistribute it and/or | 
|  | # modify it under the terms of the GNU General Public Licence | 
|  | # as published by the Free Software Foundation; either version | 
|  | # 2 of the Licence, or (at your option) any later version. | 
|  | # | 
|  | ############################################################################### | 
|  | #include <linux/sys.h> | 
|  | #include <linux/linkage.h> | 
|  | #include <asm/smp.h> | 
|  | #include <asm/intctl-regs.h> | 
|  | #include <asm/frame.inc> | 
|  | #include <asm/page.h> | 
|  | #include <asm/pgtable.h> | 
|  |  | 
|  | ############################################################################### | 
|  | # | 
|  | # Instruction TLB Miss handler entry point | 
|  | # | 
|  | ############################################################################### | 
|  | .type	itlb_miss,@function | 
|  | ENTRY(itlb_miss) | 
|  | #ifdef CONFIG_GDBSTUB | 
|  | movm	[d2,d3,a2],(sp) | 
|  | #else | 
|  | or	EPSW_nAR,epsw		# switch D0-D3 & A0-A3 to the alternate | 
|  | # register bank | 
|  | nop | 
|  | nop | 
|  | nop | 
|  | #endif | 
|  |  | 
|  | #if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR) | 
|  | mov	(MMUCTR),d2 | 
|  | mov	d2,(MMUCTR) | 
|  | #endif | 
|  |  | 
|  | and	~EPSW_NMID,epsw | 
|  | mov	(IPTEU),d3 | 
|  | mov	(PTBR),a2 | 
|  | mov	d3,d2 | 
|  | and	0xffc00000,d2 | 
|  | lsr	20,d2 | 
|  | mov	(a2,d2),a2		# PTD *ptd = PGD[addr 31..22] | 
|  | btst	_PAGE_VALID,a2 | 
|  | beq	itlb_miss_fault		# jump if doesn't point anywhere | 
|  |  | 
|  | and	~(PAGE_SIZE-1),a2 | 
|  | mov	d3,d2 | 
|  | and	0x003ff000,d2 | 
|  | lsr	10,d2 | 
|  | add	d2,a2 | 
|  | mov	(a2),d2			# get pte from PTD[addr 21..12] | 
|  | btst	_PAGE_VALID,d2 | 
|  | beq	itlb_miss_fault		# jump if doesn't point to a page | 
|  | # (might be a swap id) | 
|  | #if	((_PAGE_ACCESSED & 0xffffff00) == 0) | 
|  | bset	_PAGE_ACCESSED,(0,a2) | 
|  | #elif	((_PAGE_ACCESSED & 0xffff00ff) == 0) | 
|  | bset	+(_PAGE_ACCESSED >> 8),(1,a2) | 
|  | #else | 
|  | #error	"_PAGE_ACCESSED value is out of range" | 
|  | #endif | 
|  | and	~xPTEL2_UNUSED1,d2 | 
|  | itlb_miss_set: | 
|  | mov	d2,(IPTEL2)		# change the TLB | 
|  | #ifdef CONFIG_GDBSTUB | 
|  | movm	(sp),[d2,d3,a2] | 
|  | #endif | 
|  | rti | 
|  |  | 
|  | itlb_miss_fault: | 
|  | mov	_PAGE_VALID,d2		# force address error handler to be | 
|  | # invoked | 
|  | bra	itlb_miss_set | 
|  |  | 
|  | .size	itlb_miss, . - itlb_miss | 
|  |  | 
|  | ############################################################################### | 
|  | # | 
|  | # Data TLB Miss handler entry point | 
|  | # | 
|  | ############################################################################### | 
|  | .type	dtlb_miss,@function | 
|  | ENTRY(dtlb_miss) | 
|  | #ifdef CONFIG_GDBSTUB | 
|  | movm	[d2,d3,a2],(sp) | 
|  | #else | 
|  | or	EPSW_nAR,epsw		# switch D0-D3 & A0-A3 to the alternate | 
|  | # register bank | 
|  | nop | 
|  | nop | 
|  | nop | 
|  | #endif | 
|  |  | 
|  | #if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR) | 
|  | mov	(MMUCTR),d2 | 
|  | mov	d2,(MMUCTR) | 
|  | #endif | 
|  |  | 
|  | and	~EPSW_NMID,epsw | 
|  | mov	(DPTEU),d3 | 
|  | mov	(PTBR),a2 | 
|  | mov	d3,d2 | 
|  | and	0xffc00000,d2 | 
|  | lsr	20,d2 | 
|  | mov	(a2,d2),a2		# PTD *ptd = PGD[addr 31..22] | 
|  | btst	_PAGE_VALID,a2 | 
|  | beq	dtlb_miss_fault		# jump if doesn't point anywhere | 
|  |  | 
|  | and	~(PAGE_SIZE-1),a2 | 
|  | mov	d3,d2 | 
|  | and	0x003ff000,d2 | 
|  | lsr	10,d2 | 
|  | add	d2,a2 | 
|  | mov	(a2),d2			# get pte from PTD[addr 21..12] | 
|  | btst	_PAGE_VALID,d2 | 
|  | beq	dtlb_miss_fault		# jump if doesn't point to a page | 
|  | # (might be a swap id) | 
|  | #if	((_PAGE_ACCESSED & 0xffffff00) == 0) | 
|  | bset	_PAGE_ACCESSED,(0,a2) | 
|  | #elif	((_PAGE_ACCESSED & 0xffff00ff) == 0) | 
|  | bset	+(_PAGE_ACCESSED >> 8),(1,a2) | 
|  | #else | 
|  | #error	"_PAGE_ACCESSED value is out of range" | 
|  | #endif | 
|  | and	~xPTEL2_UNUSED1,d2 | 
|  | dtlb_miss_set: | 
|  | mov	d2,(DPTEL2)		# change the TLB | 
|  | #ifdef CONFIG_GDBSTUB | 
|  | movm	(sp),[d2,d3,a2] | 
|  | #endif | 
|  | rti | 
|  |  | 
|  | dtlb_miss_fault: | 
|  | mov	_PAGE_VALID,d2		# force address error handler to be | 
|  | # invoked | 
|  | bra	dtlb_miss_set | 
|  | .size	dtlb_miss, . - dtlb_miss | 
|  |  | 
|  | ############################################################################### | 
|  | # | 
|  | # Instruction TLB Address Error handler entry point | 
|  | # | 
|  | ############################################################################### | 
|  | .type	itlb_aerror,@function | 
|  | ENTRY(itlb_aerror) | 
|  | add	-4,sp | 
|  | SAVE_ALL | 
|  |  | 
|  | #if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR) | 
|  | mov	(MMUCTR),d1 | 
|  | mov	d1,(MMUCTR) | 
|  | #endif | 
|  |  | 
|  | and	~EPSW_NMID,epsw | 
|  | add	-4,sp				# need to pass three params | 
|  |  | 
|  | # calculate the fault code | 
|  | movhu	(MMUFCR_IFC),d1 | 
|  | or	0x00010000,d1			# it's an instruction fetch | 
|  |  | 
|  | # determine the page address | 
|  | mov	(IPTEU),d0 | 
|  | and	PAGE_MASK,d0 | 
|  | mov	d0,(12,sp) | 
|  |  | 
|  | clr	d0 | 
|  | mov	d0,(IPTEL2) | 
|  |  | 
|  | or	EPSW_IE,epsw | 
|  | mov	fp,d0 | 
|  | call	do_page_fault[],0		# do_page_fault(regs,code,addr | 
|  |  | 
|  | jmp	ret_from_exception | 
|  | .size	itlb_aerror, . - itlb_aerror | 
|  |  | 
|  | ############################################################################### | 
|  | # | 
|  | # Data TLB Address Error handler entry point | 
|  | # | 
|  | ############################################################################### | 
|  | .type	dtlb_aerror,@function | 
|  | ENTRY(dtlb_aerror) | 
|  | add	-4,sp | 
|  | SAVE_ALL | 
|  |  | 
|  | #if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR) | 
|  | mov	(MMUCTR),d1 | 
|  | mov	d1,(MMUCTR) | 
|  | #endif | 
|  |  | 
|  | add	-4,sp				# need to pass three params | 
|  | and	~EPSW_NMID,epsw | 
|  |  | 
|  | # calculate the fault code | 
|  | movhu	(MMUFCR_DFC),d1 | 
|  |  | 
|  | # determine the page address | 
|  | mov	(DPTEU),a2 | 
|  | mov	a2,d0 | 
|  | and	PAGE_MASK,d0 | 
|  | mov	d0,(12,sp) | 
|  |  | 
|  | clr	d0 | 
|  | mov	d0,(DPTEL2) | 
|  |  | 
|  | or	EPSW_IE,epsw | 
|  | mov	fp,d0 | 
|  | call	do_page_fault[],0		# do_page_fault(regs,code,addr | 
|  |  | 
|  | jmp	ret_from_exception | 
|  | .size	dtlb_aerror, . - dtlb_aerror |