/*
* 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 */