/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #if defined(lint) #include #include #else /* lint */ #include "assym.h" #endif /* lint */ #include #include #include #include #include #include #include #include #include #include #include #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 ldx [%g7 + ZULUVM_INTRNUM], %g1 SET_SIZE(zuluvm_dmv_tlbmiss_tl1) #endif /* lint */