aboutsummaryrefslogtreecommitdiff
path: root/arch/mn10300/mm/tlb-mn10300.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mn10300/mm/tlb-mn10300.S')
-rw-r--r--arch/mn10300/mm/tlb-mn10300.S207
1 files changed, 207 insertions, 0 deletions
diff --git a/arch/mn10300/mm/tlb-mn10300.S b/arch/mn10300/mm/tlb-mn10300.S
new file mode 100644
index 000000000000..789208094e98
--- /dev/null
+++ b/arch/mn10300/mm/tlb-mn10300.S
@@ -0,0 +1,207 @@
+###############################################################################
+#
+# 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)
+ and ~EPSW_NMID,epsw
+#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
+
+ 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)
+ bset _PAGE_ACCESSED,(0,a2)
+ and ~(xPTEL_UNUSED1|xPTEL_UNUSED2),d2
+itlb_miss_set:
+ mov d2,(IPTEL) # 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)
+ and ~EPSW_NMID,epsw
+#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
+
+ 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)
+ bset _PAGE_ACCESSED,(0,a2)
+ and ~(xPTEL_UNUSED1|xPTEL_UNUSED2),d2
+dtlb_miss_set:
+ mov d2,(DPTEL) # 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)
+ and ~EPSW_NMID,epsw
+ add -4,sp
+ SAVE_ALL
+ 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),a2
+ mov a2,d0
+ and PAGE_MASK,d0
+ mov d0,(12,sp)
+
+ clr d0
+ mov d0,(IPTEL)
+
+ and ~EPSW_NMID,epsw
+ 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)
+ and ~EPSW_NMID,epsw
+ add -4,sp
+ mov d1,(sp)
+
+ movhu (MMUFCR_DFC),d1 # is it the initial valid write
+ # to this page?
+ and MMUFCR_xFC_INITWR,d1
+ beq dtlb_pagefault # jump if not
+
+ mov (DPTEL),d1 # set the dirty bit
+ # (don't replace with BSET!)
+ or _PAGE_DIRTY,d1
+ mov d1,(DPTEL)
+ mov (sp),d1
+ add 4,sp
+ rti
+
+ ALIGN
+dtlb_pagefault:
+ mov (sp),d1
+ SAVE_ALL
+ add -4,sp # need to pass three params
+
+ # 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,(DPTEL)
+
+ and ~EPSW_NMID,epsw
+ 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