123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- ###############################################################################
- #
- # 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
|