* ========== Copyright Header Begin ==========================================
* Hypervisor Software File: instr_emul.s
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* - Do no alter or remove copyright notices
* - Redistribution and use of this software in source and binary forms, with
* or without modification, are permitted provided that the following
* - Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of Sun Microsystems, Inc. or the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* You acknowledge that this software is not designed, licensed or
* intended for use in the design, construction, operation or maintenance of
* ========== Copyright Header End ============================================
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
#pragma ident "@(#)instr_emul.s 1.2 07/07/17 SMI"
* Niagara II unimplemented instruction emulation
#include <sys/asm_linkage.h>
#include <sparcv9/misc.h>
* Illegal access to non-cacheable page
* Emulate VIS LDBLOCKF instruction.
* %g2 VA from D-SFAR (sign-extended)
* Decode the instruction to determine whether it's a VIS block load
* Note: We know that we will never use these instructions in
* hyper-privileged mode so we could ignore that possibility and
* save a few instructions. Leave the test in for debug.
* Ascertain what the MMU is doing for instruction translation by
bz,pn %xcc, .dae_nc_page_tpc_ra
* Check if we are in nucleus ctx or not. If we
* are (ie, we took the trap the trap at TL == 0),
* we need to zero the primary ctx regs
* before using ASI_ITLB_PROBE.
STRAND_PUSH(%g4, %g6, %g7)
STRAND_PUSH(%g4, %g6, %g7)
* LSUCR.im == 1, virtual address translation is enabled
* %g1 contains VA of instruction, clear VA[12:0]
* VA[39:5] for ASI_ITLB_PROBE is VA[47:13]
ldxa [%g6]ASI_ITLB_PROBE, %g7
brlz,a,pt %g7, 2f ! valid PA ? (bit 63 == 1 ?)
! not a valid PA, look for RA->PA translation
ldxa [%g6]ASI_ITLB_PROBE, %g7
! if needed, restore MMU contexts
! valid PA ? (bit 63 is Valid bit)
brlz,a,pt %g7, .dae_nc_page_va
sllx %g7, 1, %g6 ! %g6 bit 62 after ITLB_PROBE,
* nope, retry the instruction and hope for better luck next time
* Note: We are introducing a possible infinite retry/trap loop
* here. This needs to be carefully considered.
* valid instruction address found with ASI_ITLB_PROBE
* better avoid multi-hits and parity errors
* %g7 Valid PA[39:13], (need to clear bit 63)
brlz,pn %g6, .dae_nc_page_dmmu_err ! %g6 bit 62 << 1
sllx %g6, 1, %g6 ! %g6 bit 61 after ITLB_PROBE,
brlz,pn %g6, .dae_nc_page_dmmu_err ! %g6 bit 61 << 1
and %g1, %g6, %g5 ! %g5 VA[12:0]
or %g7, %g5, %g7 ! %g7 PA of instruction
ba .dae_nc_page_decode_instr
ld [%g7], %g5 ! %g5 instruction
* %g1 contains RA of instruction
RA2PA_CONV(%g4, %g1, %g5, %g6) ! %g5 PA
ld [%g5], %g5 ! %g5 instruction
.dae_nc_page_decode_instr:
* %g2 VA from D-SFAR (sign-extended)
* %g5 instruction to decode
srlx %g5, LDBLOCKF_OP_SHIFT, %g7 ! op
bne,pn %xcc, .dae_nc_page_dmmu_err
set LDBLOCKF_OP3_MASK, %g7
srlx %g7, LDBLOCKF_OP3_SHIFT, %g7
cmp %g7, LDBLOCKF_OP3 ! block load
bne,pn %xcc, .dae_nc_page_dmmu_err
* Block load/store, check the ASI from the instruction if instr.i = 0,
* from TSTATE.ASI if instr.i = 1.
srlx %g5, LDBLOCKF_I_SHIFT, %g4
set LDBLOCKF_ASI_MASK, %g4
srlx %g4, LDBLOCKF_ASI_SHIFT, %g4 ! %g4 instr.imm_asi
srlx %g4, TSTATE_ASI_SHIFT, %g4
and %g4, TSTATE_ASI_MASK, %g4
* If the ASI is not for a block load/store, no emulation
* The following ASIs are for use with LDDFA and STDFA instructions
* as Block Load (LDBLOCKF) and Block Store (STBLOCKF) operations.
* The block load ASI is mapped as :-
* ASI_BLK_AIUP -> ASI_AIUP
* ASI_BLK_AIUS -> ASI_AIUS
* ASI_BLK_AIUP_LE -> ASI_AIUP_LE
* ASI_BLK_AIUS_LE -> ASI_AIUS_LE
* ASI_BLK_PL -> ASI_AIUP_LE
* ASI_BLK_SL -> ASI_AIUS_LE
* Note: Is there a possible TLB/TSB miss here which would cause
* a guest trap at TL > 1 but with a user VA ? We are entering
* dangerous territor here.
be,pn %xcc, .dae_nc_page_asi_ok
be,pn %xcc, .dae_nc_page_asi_ok
be,pn %xcc, .dae_nc_page_asi_ok
be,pn %xcc, .dae_nc_page_asi_ok
be,pn %xcc, .dae_nc_page_asi_ok
be,pn %xcc, .dae_nc_page_asi_ok
be,pn %xcc, .dae_nc_page_asi_ok
be,pn %xcc, .dae_nc_page_asi_ok
* Not a block load/store ASI, so treat this as any other
ba,a,pt %xcc, .dae_nc_page_dmmu_err
* Valid LDBLOCKF VIS instruction, emulate
* %g2 VA from D-SFAR (sign-extended)
* Get the target register, verify that it is a double-precision
* FP register aligned on an eight-double-precision register boundary.
set LDBLOCKF_RD_MASK, %g3
srlx %g3, LDBLOCKF_RD_SHIFT, %g3 ! %g3 target FP register
btst 1, %g3 ! if odd-numbered fp reg, it
bnz,a,pt %xcc, 0f ! it is for fp32 and up
add %g3, 31, %g3 ! only 5 bits available for
* illegal_inst trap has priority, no need to check for aligned fp reg
* save a couple of instructions here
bnz,pn %xcc, .dae_nc_page_dmmu_err
wr %g7, %asi ! set target ASI
* we know this was a valid FP block load operation,
* as the fp_disabled trap has priority, so FPRS.fef
* must have been set. Set it again now for the hypervisor
* without checking/storing FPRS, save a few instructions.
* The DAE_nc_page trap will have enabled PSTATE.PEF.
#define LD_FP_SIZE (SZ_INSTR * 9)
* get address of 'load table' below
ldda [%g2 + 40]%asi, %f10
ldda [%g2 + 48]%asi, %f12
ldda [%g2 + 56]%asi, %f14
ldda [%g2 + 16]%asi, %f20
ldda [%g2 + 24]%asi, %f22
ldda [%g2 + 32]%asi, %f24
ldda [%g2 + 40]%asi, %f26
ldda [%g2 + 48]%asi, %f28
ldda [%g2 + 56]%asi, %f30
ldda [%g2 + 16]%asi, %f36
ldda [%g2 + 24]%asi, %f38
ldda [%g2 + 32]%asi, %f40
ldda [%g2 + 40]%asi, %f42
ldda [%g2 + 48]%asi, %f44
ldda [%g2 + 56]%asi, %f46
ldda [%g2 + 16]%asi, %f52
ldda [%g2 + 24]%asi, %f54
ldda [%g2 + 32]%asi, %f56
ldda [%g2 + 40]%asi, %f58
ldda [%g2 + 48]%asi, %f60
ldda [%g2 + 56]%asi, %f62
* Jump into the load table, load the FP registers from the
* source address and return to TNPC.
* target register must be 8 double-aligned, (% 16 == 0)
* %g5 &.dae_nc_page_load_fp0
srlx %g3, 4, %g3 ! fpreg / 16
mulx %g3, LD_FP_SIZE, %g3
* Emulation not supported for this instruction, treat as
DMMU_ERR_RV(MMU_FT_NCATOMIC)