208 lines
4.7 KiB
ArmAsm
208 lines
4.7 KiB
ArmAsm
![]() |
###############################################################################
|
||
|
#
|
||
|
# 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
|