zulu_asm.s revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#if defined(lint)
#include <sys/types.h>
#include <sys/thread.h>
#else /* lint */
#include "assym.h"
#endif /* lint */
#include <sys/asi.h>
#include <sys/sun4asi.h>
#include <sys/machasi.h>
#include <sys/asm_linkage.h>
#include <sys/pte.h>
#include <sys/mmu.h>
#include <sys/intreg.h>
#include <sys/zulumod.h>
#include <vm/hat_sfmmu.h>
#include <sys/zulu_hat.h>
#include <zuluvm_offsets.h>
#ifdef lint
void
zuluvm_dmv_tlbmiss_tl1()
{}
#else /* lint */
DGDEF(zuluvm_base_pgsize)
.word 0
ENTRY_NP(zuluvm_dmv_tlbmiss_tl1)
! g1 - zuluvm_state_t pointer
! g2 - IRDR_0
mov UIII_IRDR_1, %g3
ldxa [%g3]ASI_INTR_RECEIVE, %g5
stx %g5, [%g1 + ZULUVM_ASM_TLB_ADDR]
mov UIII_IRDR_6, %g3
ldxa [%g3]ASI_INTR_RECEIVE, %g5
stx %g5, [%g1 + ZULUVM_ASM_TLB_TYPE]
stxa %g0, [%g0]ASI_INTR_RECEIVE_STATUS ! clear the BUSY bit
membar #Sync
mov %g1, %g7
! check the fast tlb miss flag
sethi %hi(zuluvm_fast_tlb), %g6
lduw [%g6 + %lo(zuluvm_fast_tlb)], %g6
brz,pn %g6, send_intr1
mov ZULUVM_TTE_DELAY, %g1
#if 1
add %g7, ZULUVM_STATE, %g4
mov ZULUVM_STATE_IDLE, %g1
mov ZULUVM_STATE_TLB_PENDING, %g6
casa [%g4]ASI_N, %g1, %g6
cmp %g6, %g1
be,pt %icc, 2f
nop
mov ZULUVM_STATE_CANCELED, %g1
cmp %g6, %g1
be,pt %icc, 1f
mov ZULUVM_STATE_STOPPED, %g1
retry
1:
st %g1, [%g4]
#ifdef ZULUVM_STATS
lduw [%g7 + ZULUVM_ST_TLBCANCEL], %g3
add %g3, 1, %g3
stuw %g3, [%g7 + ZULUVM_ST_TLBCANCEL]
#endif
retry
2:
ldx [%g7 + ZULUVM_ASM_TLB_TYPE], %g4
and %g4, ZULUVM_DMA_MASK, %g4
#ifdef ZULUVM_STATS
cmp %g4, ZULUVM_DMA2
be,a,pn %icc, 1f
add %g7, ZULUVM_ST_DTLB2MISS, %g1
cmp %g4, ZULUVM_ITLB1
be,a,pn %icc, 1f
add %g7, ZULUVM_ST_ITLB1MISS, %g1
cmp %g4, ZULUVM_ITLB2
be,a,pn %icc, 1f
add %g7, ZULUVM_ST_ITLB2MISS, %g1
add %g7, ZULUVM_ST_DTLB1MISS, %g1
1:
lduw [%g1], %g3
add %g3, 1, %g3
stuw %g3, [%g1]
#endif
/*
* lookup the tte in the tsb
* %g1 - vaddr[63:13], ctx[12:0]
* %g2 - our trap level
* %g3 - return address
* %g7 - zulu data pointer (needs to be preserved)
* return:
* %g1 - flags [63..58] and pfn [31..0]
* %g2 - status code if %g1 is null
* %g7 - zulu data pointer
*/
mov 1, %g2
set zulu_hat_tsb_lookup_tl1, %g3
jmpl %g3, %g3
ldx [%g7 + ZULUVM_ASM_TLB_ADDR], %g1 ! vaddr(tag)
/*
* did we find a tte ??
* If not, %g2 has the error code
*/
brgez,a,pt %g1, send_intr
mov %g2, %g1
set zulu_tsb_hit, %g6
ldx [%g6], %g3
add %g3, 1, %g3
stx %g3, [%g6]
/*
* get flags and pfn
*/
sllx %g1, 32, %g6
srlx %g6, 32, %g6 ! %g6 pfn
srlx %g1, 59, %g3
and %g3, 0x7, %g2 ! %g2 page size
srlx %g3, 3, %g4
and %g4, 1, %g4 ! %g4 write perm
mov %g6, %g1
/*
* check if this is a dtlb2 miss(no itlb, pgsz != 8k)
* and if the current dtlb2 pgsz != tte pgsz
*/
ldx [%g7 + ZULUVM_ASM_TLB_TYPE], %g3
and %g3, 0x1, %g3
brnz,pt %g3, 3f ! not 0 => itlb => handles
nop
! check page size, base page size is always handled by dtlb1, so we
! only need to check against dtlb2
sethi %hi(zuluvm_base_pgsize), %g3
lduw [%g3 + %lo(zuluvm_base_pgsize)], %g3
cmp %g2, %g3
be,pt %icc, 2f
cmp %g2, ZULU_TTE4M
be,pt %icc, 2f ! TTE4M => dtlb2 => ok!
nop
#ifdef ZULUVM_STATS
lduw [%g7 + ZULUVM_ST_PAGESIZE], %g3
add %g3, 1, %g3
stuw %g3, [%g7 + ZULUVM_ST_PAGESIZE]
add %g7, ZULUVM_ST_MISS, %g3
sll %g2, 2, %g5
add %g5, %g3, %g5
lduw [%g5], %g3
add %g3, 1, %g3
stuw %g3, [%g5]
#endif
! set tte size to ZULUVM_BASE_PGSZ
sethi %hi(zuluvm_base_pgsize), %g3
lduw [%g3 + %lo(zuluvm_base_pgsize)], %g3
ba,pt %icc, 3f
mov %g3, %g2
2:
#ifdef ZULUVM_STATS
add %g7, ZULUVM_ST_MISS, %g3
sll %g2, 2, %g5
add %g3, %g5, %g5
lduw [%g5], %g3
add %g3, 1, %g3
stuw %g3, [%g5]
#endif
! we maintain data on the last pfns for the last 12 pfns that we
! processed
3:
lduw [%g7 + ZULUVM_PFNCNT], %g5
add %g5, 4, %g3
cmp %g3, 48
be,a,pn %icc, 1f
mov %g0, %g3
1:
stuw %g3, [%g7 + ZULUVM_PFNCNT]
sllx %g5, 3, %g5
add %g7, ZULUVM_PFNBUF, %g3
add %g3, %g5, %g3
stx %g1, [%g3]
stx %g2, [%g3 + 8]
stx %g4, [%g3 + 16]
ldx [%g7 + ZULUVM_ASM_TLB_TYPE], %g5
stx %g5, [%g3 + 24]
ldx [%g7 + ZULUVM_ASM_TLB_TYPE], %g3
and %g3, 0x3, %g3 ! tlbtype
ldx [%g7 + ZULUVM_ARG], %g6
! write tte to zulu mmu
! %g1 pfn
! %g2 tte size
! %g3 tlbtype
! %g4 tte wrperm
! %g6 zulu device driver arg
! %g7 devtab pointer
sllx %g1, ZULUVM_ZFB_MMU_TLB_D_PA_SHIFT, %g1
mov 0x1, %g5
sllx %g5, 63, %g5 ! ZFB_MMU_TLB_D_V_MASK
or %g1, %g5, %g1
or %g1, ZULUVM_ZFB_MMU_TLB_D_C_MASK, %g1
sllx %g2, ZULUVM_ZFB_MMU_TLB_D_SZ_SHIFT, %g2
brz,pt %g4, 3f ! write perm ??
or %g2, %g1, %g1
or %g1, ZULUVM_ZFB_MMU_TLB_D_W_MASK, %g1
3:
! at this point %g1 is ready to be written to the corresponding
! data_in register, let's see which if it was itlb or dtlb...
and %g3, ZULUVM_ITLB_FLAG, %g3
! assumption is that data miss
brz,pt %g3, 4f ! is more likely than instr miss
ldx [%g7 + ZULUVM_PAMMU], %g2 ! physical addr of zulu mmu regs
! instruction miss
mov ZULUVM_ZFB_MMU_TLB_CR_IMISS_MASK, %g5
add %g2, ZULUVM_ITLB_DATA_IN, %g4
!stxa %g1, [%g4]ASI_IO
ba,pt %xcc, 5f
stxa %g1, [%g4]ASI_IO
!ldxa [%g4]ASI_IO, %g4
4:
! data miss
mov ZULUVM_ZFB_MMU_TLB_CR_DMISS_MASK, %g5
add %g2, ZULUVM_DTLB_DATA_IN, %g4
stxa %g1, [%g4]ASI_IO
!ldxa [%g4]ASI_IO, %g4
5:
add %g7, ZULUVM_STATE, %g4
mov ZULUVM_STATE_TLB_PENDING, %g6
mov ZULUVM_STATE_IDLE, %g1
casa [%g4]ASI_N, %g6, %g1
cmp %g6, %g1
bne,a,pn %icc, stopped
mov ZULUVM_STATE_STOPPED, %g3
ldx [%g7 + ZULUVM_PAMMU], %g2
add %g2, ZULUVM_TLB_CONTROL, %g2
stxa %g5, [%g2]ASI_IO
!ldxa [%g2]ASI_IO, %g3
retry
send_intr:
add %g7, ZULUVM_STATE, %g4
mov ZULUVM_STATE_INTR_QUEUED, %g5
mov ZULUVM_STATE_TLB_PENDING, %g3
casa [%g4]ASI_N, %g3, %g5
cmp %g3, %g5
be,pt %icc, deliver_intr
mov ZULUVM_STATE_STOPPED, %g3
ba,pt %icc, stopped
nop
#endif
send_intr1:
add %g7, ZULUVM_STATE, %g4
mov ZULUVM_STATE_IDLE, %g3
mov ZULUVM_STATE_INTR_QUEUED, %g5
casa [%g4]ASI_N, %g3, %g5
cmp %g3, %g5
be,pt %icc, deliver_intr
mov ZULUVM_STATE_STOPPED, %g3
stopped:
st %g3, [%g4]
#ifdef ZULUVM_STATS
lduw [%g7 + ZULUVM_ST_TLBCANCEL], %g3
add %g3, 1, %g3
stuw %g3, [%g7 + ZULUVM_ST_TLBCANCEL]
#endif
retry
deliver_intr:
stx %g1, [%g7 + ZULUVM_ASM_TLB_ERRCODE] ! set the error field
stx %g6, [%g7 + ZULUVM_ASM_TLB_TTE] ! deliver tte in data_0
! %g6 is invalid if error != SUCCESS
! setsoftint_tl1(uint64_t inum, uint64_t dummy)
set setsoftint_tl1, %g5
jmp %g5
lduh [%g7 + ZULUVM_INTRNUM], %g1
SET_SIZE(zuluvm_dmv_tlbmiss_tl1)
#endif /* lint */