10Sstevel@tonic-gate/* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*11172SHaik.Aftandilian@Sun.COM * Common Development and Distribution License (the "License"). 6*11172SHaik.Aftandilian@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate/* 22*11172SHaik.Aftandilian@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate#if defined(lint) 270Sstevel@tonic-gate#include <sys/types.h> 280Sstevel@tonic-gate#include <sys/cpuvar.h> 290Sstevel@tonic-gate#else /*lint */ 300Sstevel@tonic-gate#include "assym.h" 310Sstevel@tonic-gate#endif /* lint */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate#include <sys/asm_linkage.h> 340Sstevel@tonic-gate#include <sys/privregs.h> 350Sstevel@tonic-gate#include <sys/x_call.h> 360Sstevel@tonic-gate#include <sys/xc_impl.h> 370Sstevel@tonic-gate#include <sys/machthread.h> 380Sstevel@tonic-gate#include <sys/hypervisor_api.h> 390Sstevel@tonic-gate 400Sstevel@tonic-gate#ifdef TRAPTRACE 410Sstevel@tonic-gate#include <sys/traptrace.h> 420Sstevel@tonic-gate#endif /* TRAPTRACE */ 430Sstevel@tonic-gate 440Sstevel@tonic-gate 450Sstevel@tonic-gate#if defined(lint) 460Sstevel@tonic-gate 470Sstevel@tonic-gate/* ARGSUSED */ 480Sstevel@tonic-gatevoid 490Sstevel@tonic-gateself_xcall(struct cpu *cpu, uint64_t arg1, uint64_t arg2, xcfunc_t *func) 500Sstevel@tonic-gate{} 510Sstevel@tonic-gate 520Sstevel@tonic-gate#else 530Sstevel@tonic-gate 540Sstevel@tonic-gate/* 550Sstevel@tonic-gate * Entered by the software trap (TT=ST_SELFXCALL, TL>0) thru send_self_xcall(). 560Sstevel@tonic-gate * Emulate the mondo handler - vec_interrupt(). 570Sstevel@tonic-gate * 580Sstevel@tonic-gate * Global registers are the Alternate Globals. 590Sstevel@tonic-gate * Arguments: 600Sstevel@tonic-gate * %o0 - CPU 610Sstevel@tonic-gate * ILP32 kernel: 620Sstevel@tonic-gate * %o5 - function to call 630Sstevel@tonic-gate * %o1, %o2, %o3, %o4 - arguments 640Sstevel@tonic-gate * LP64 kernel: 650Sstevel@tonic-gate * %o3 - function to call 660Sstevel@tonic-gate * %o1, %o2 - arguments 670Sstevel@tonic-gate */ 680Sstevel@tonic-gate ENTRY_NP(self_xcall) 690Sstevel@tonic-gate ! 700Sstevel@tonic-gate ! TL>0 handlers are expected to do "retry" 710Sstevel@tonic-gate ! prepare their return PC and nPC now 720Sstevel@tonic-gate ! 730Sstevel@tonic-gate rdpr %tnpc, %g1 740Sstevel@tonic-gate wrpr %g1, %tpc ! PC <- TNPC[TL] 750Sstevel@tonic-gate add %g1, 4, %g1 760Sstevel@tonic-gate wrpr %g1, %tnpc ! nPC <- TNPC[TL] + 4 770Sstevel@tonic-gate 780Sstevel@tonic-gate#ifdef TRAPTRACE 790Sstevel@tonic-gate TRACE_PTR(%g4, %g6) 80*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g3) 810Sstevel@tonic-gate stxa %g6, [%g4 + TRAP_ENT_TICK]%asi 820Sstevel@tonic-gate rdpr %tl, %g6 830Sstevel@tonic-gate stha %g6, [%g4 + TRAP_ENT_TL]%asi 840Sstevel@tonic-gate rdpr %tt, %g6 850Sstevel@tonic-gate stha %g6, [%g4 + TRAP_ENT_TT]%asi 860Sstevel@tonic-gate stna %o3, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler 870Sstevel@tonic-gate rdpr %tpc, %g6 880Sstevel@tonic-gate stna %g6, [%g4 + TRAP_ENT_TPC]%asi 890Sstevel@tonic-gate rdpr %tstate, %g6 900Sstevel@tonic-gate stxa %g6, [%g4 + TRAP_ENT_TSTATE]%asi 910Sstevel@tonic-gate stna %sp, [%g4 + TRAP_ENT_SP]%asi 920Sstevel@tonic-gate stna %o1, [%g4 + TRAP_ENT_F1]%asi ! arg 1 930Sstevel@tonic-gate stna %o2, [%g4 + TRAP_ENT_F2]%asi ! arg 2 940Sstevel@tonic-gate stna %g0, [%g4 + TRAP_ENT_F3]%asi 950Sstevel@tonic-gate stna %g0, [%g4 + TRAP_ENT_F4]%asi 960Sstevel@tonic-gate TRACE_NEXT(%g4, %g6, %g3) 970Sstevel@tonic-gate#endif /* TRAPTRACE */ 980Sstevel@tonic-gate ! 990Sstevel@tonic-gate ! Load the arguments for the fast trap handler. 1000Sstevel@tonic-gate ! 1010Sstevel@tonic-gate mov %o1, %g1 1020Sstevel@tonic-gate jmp %o3 ! call the fast trap handler 1030Sstevel@tonic-gate mov %o2, %g2 1040Sstevel@tonic-gate /* Not Reached */ 1050Sstevel@tonic-gate SET_SIZE(self_xcall) 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate#endif /* lint */ 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate#ifdef TRAPTRACE 1100Sstevel@tonic-gate#if defined(lint) 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate/* ARGSUSED */ 1130Sstevel@tonic-gatevoid 1140Sstevel@tonic-gatexc_trace(u_int traptype, cpuset_t *cpu_set, xcfunc_t *func, 1150Sstevel@tonic-gate uint64_t arg1, uint64_t arg2) 1160Sstevel@tonic-gate{} 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate#else /* lint */ 1190Sstevel@tonic-gate ENTRY(xc_trace) 1200Sstevel@tonic-gate rdpr %pstate, %g1 1210Sstevel@tonic-gate andn %g1, PSTATE_IE | PSTATE_AM, %g2 1220Sstevel@tonic-gate wrpr %g0, %g2, %pstate /* disable interrupts */ 1230Sstevel@tonic-gate TRACE_PTR(%g3, %g4) 124*11172SHaik.Aftandilian@Sun.COM GET_TRACE_TICK(%g6, %g4) 1250Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TICK]%asi 1260Sstevel@tonic-gate stha %g0, [%g3 + TRAP_ENT_TL]%asi 1270Sstevel@tonic-gate set TT_XCALL, %g2 1280Sstevel@tonic-gate or %o0, %g2, %g4 1290Sstevel@tonic-gate stha %g4, [%g3 + TRAP_ENT_TT]%asi 1300Sstevel@tonic-gate stna %o7, [%g3 + TRAP_ENT_TPC]%asi 1310Sstevel@tonic-gate ldn [%o1], %g2 1320Sstevel@tonic-gate stna %g2, [%g3 + TRAP_ENT_SP]%asi /* sp = cpuset */ 1330Sstevel@tonic-gate stna %o2, [%g3 + TRAP_ENT_TR]%asi /* tr = func */ 1340Sstevel@tonic-gate stna %o3, [%g3 + TRAP_ENT_F1]%asi /* f1 = arg1 */ 1350Sstevel@tonic-gate stna %o4, [%g3 + TRAP_ENT_F2]%asi /* f2 = arg2 */ 1360Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_F3]%asi /* f3 = 0 */ 1370Sstevel@tonic-gate stna %i7, [%g3 + TRAP_ENT_F4]%asi /* f4 = xcall caller */ 1380Sstevel@tonic-gate stxa %g1, [%g3 + TRAP_ENT_TSTATE]%asi /* tstate = pstate */ 1390Sstevel@tonic-gate TRACE_NEXT(%g2, %g3, %g4) 1400Sstevel@tonic-gate/* 1410Sstevel@tonic-gate * In the case of a cpuset of greater size than a long we 1420Sstevel@tonic-gate * grab extra trace buffers just to store the cpuset. 1430Sstevel@tonic-gate * Seems like a waste but popular opinion opted for this 1440Sstevel@tonic-gate * rather than increase the size of the buffer. 1450Sstevel@tonic-gate */ 1460Sstevel@tonic-gate#if CPUSET_SIZE > CLONGSIZE 1470Sstevel@tonic-gate add %o1, CPUSET_SIZE, %g5 /* end of cpuset */ 1480Sstevel@tonic-gate clr %o2 1490Sstevel@tonic-gate1: 1500Sstevel@tonic-gate TRACE_PTR(%g3, %g4) 1510Sstevel@tonic-gate stha %g0, [%g3 + TRAP_ENT_TL]%asi 1520Sstevel@tonic-gate set TT_XCALL_CONT, %g2 1530Sstevel@tonic-gate or %g2, %o2, %g2 /* continuation # */ 1540Sstevel@tonic-gate stha %g2, [%g3 + TRAP_ENT_TT]%asi 1550Sstevel@tonic-gate stxa %g6, [%g3 + TRAP_ENT_TICK]%asi /* same tick */ 1560Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_TPC]%asi /* clr unused fields */ 1570Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_SP]%asi 1580Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_TR]%asi 1590Sstevel@tonic-gate stxa %g0, [%g3 + TRAP_ENT_TSTATE]%asi 1600Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_F2]%asi 1610Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_F3]%asi 1620Sstevel@tonic-gate stna %g0, [%g3 + TRAP_ENT_F4]%asi 1630Sstevel@tonic-gate ldn [%o1], %g2 1640Sstevel@tonic-gate stna %g2, [%g3 + TRAP_ENT_F1]%asi 1650Sstevel@tonic-gate add %o1, CLONGSIZE, %o1 1660Sstevel@tonic-gate cmp %o1, %g5 1670Sstevel@tonic-gate bge 2f 1680Sstevel@tonic-gate ldn [%o1], %g2 1690Sstevel@tonic-gate stna %g2, [%g3 + TRAP_ENT_F2]%asi 1700Sstevel@tonic-gate add %o1, CLONGSIZE, %o1 1710Sstevel@tonic-gate cmp %o1, %g5 1720Sstevel@tonic-gate bge 2f 1730Sstevel@tonic-gate ldn [%o1], %g2 1740Sstevel@tonic-gate stna %g2, [%g3 + TRAP_ENT_F3]%asi 1750Sstevel@tonic-gate add %o1, CLONGSIZE, %o1 1760Sstevel@tonic-gate cmp %o1, %g5 1770Sstevel@tonic-gate bge 2f 1780Sstevel@tonic-gate ldn [%o1], %g2 1790Sstevel@tonic-gate stna %g2, [%g3 + TRAP_ENT_F4]%asi 1800Sstevel@tonic-gate add %o1, CLONGSIZE, %o1 1810Sstevel@tonic-gate2: 1820Sstevel@tonic-gate TRACE_NEXT(%g2, %g3, %g4) 1830Sstevel@tonic-gate cmp %o1, %g5 1840Sstevel@tonic-gate bl 1b 1850Sstevel@tonic-gate inc %o2 1860Sstevel@tonic-gate#endif /* CPUSET_SIZE */ 1870Sstevel@tonic-gate retl 1880Sstevel@tonic-gate wrpr %g0, %g1, %pstate /* enable interrupts */ 1890Sstevel@tonic-gate SET_SIZE(xc_trace) 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate#endif /* lint */ 1920Sstevel@tonic-gate#endif /* TRAPTRACE */ 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate#if defined(lint) 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate/*ARGSUSED*/ 1970Sstevel@tonic-gatevoid 1980Sstevel@tonic-gateinit_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2) 1990Sstevel@tonic-gate{} 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate/*ARGSUSED*/ 2020Sstevel@tonic-gateint 2030Sstevel@tonic-gateshipit(int n, uint64_t cpuid) 2040Sstevel@tonic-gate{ return(0); } 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate#else /* lint */ 2070Sstevel@tonic-gate/* 2080Sstevel@tonic-gate * Setup interrupt dispatch data registers 2090Sstevel@tonic-gate * Entry: 2100Sstevel@tonic-gate * %o0 - function or inumber to call 2110Sstevel@tonic-gate * %o1, %o2 - arguments (2 uint64_t's) 2120Sstevel@tonic-gate */ 2130Sstevel@tonic-gate ENTRY(init_mondo) 2140Sstevel@tonic-gate ALTENTRY(init_mondo_nocheck) 2150Sstevel@tonic-gate CPU_ADDR(%g1, %g4) ! load CPU struct addr 2160Sstevel@tonic-gate add %g1, CPU_MCPU, %g1 2170Sstevel@tonic-gate ldx [%g1 + MCPU_MONDO_DATA], %g1 2180Sstevel@tonic-gate stx %o0, [%g1] 2190Sstevel@tonic-gate stx %o1, [%g1+8] 2200Sstevel@tonic-gate stx %o2, [%g1+0x10] 2210Sstevel@tonic-gate stx %g0, [%g1+0x18] 2220Sstevel@tonic-gate stx %g0, [%g1+0x20] 2230Sstevel@tonic-gate stx %g0, [%g1+0x28] 2240Sstevel@tonic-gate stx %g0, [%g1+0x30] 2250Sstevel@tonic-gate stx %g0, [%g1+0x38] 2260Sstevel@tonic-gate retl 2270Sstevel@tonic-gate membar #Sync ! allowed to be in the delay slot 2280Sstevel@tonic-gate SET_SIZE(init_mondo) 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate/* 2310Sstevel@tonic-gate * Ship mondo to cpuid 2320Sstevel@tonic-gate */ 2330Sstevel@tonic-gate ENTRY_NP(shipit) 2340Sstevel@tonic-gate /* For now use dummy interface: cpu# func arg1 arg2 */ 2350Sstevel@tonic-gate CPU_ADDR(%g1, %g4) 2360Sstevel@tonic-gate add %g1, CPU_MCPU, %g1 2370Sstevel@tonic-gate ldx [%g1 + MCPU_MONDO_DATA_RA], %o2 2380Sstevel@tonic-gate mov HV_INTR_SEND, %o5 2390Sstevel@tonic-gate ta FAST_TRAP 2400Sstevel@tonic-gate retl 2410Sstevel@tonic-gate membar #Sync 2420Sstevel@tonic-gate SET_SIZE(shipit) 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate#endif /* lint */ 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate#if defined(lint) 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate/*ARGSUSED*/ 2490Sstevel@tonic-gateuint64_t 2500Sstevel@tonic-gateget_cpuaddr(uint64_t reg, uint64_t scr) 2510Sstevel@tonic-gate{ return (0);} 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate#else /* lint */ 2540Sstevel@tonic-gate/* 2550Sstevel@tonic-gate * Get cpu structure 2560Sstevel@tonic-gate * Entry: 2570Sstevel@tonic-gate * %o0 - register for CPU_ADDR macro 2580Sstevel@tonic-gate * %o1 - scratch for CPU_ADDR macro 2590Sstevel@tonic-gate */ 2600Sstevel@tonic-gate ENTRY(get_cpuaddr) 2610Sstevel@tonic-gate CPU_ADDR(%o0, %o1) ! %o0 == CPU struct addr 2620Sstevel@tonic-gate retl 2630Sstevel@tonic-gate nop 2640Sstevel@tonic-gate SET_SIZE(get_cpuaddr) 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate#endif /* lint */ 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate#if defined(lint) 2690Sstevel@tonic-gate/* ARGSUSED */ 2700Sstevel@tonic-gatevoid 2710Sstevel@tonic-gatext_sync_tl1(uint64_t *cpu_sync_addr) 2720Sstevel@tonic-gate{} 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate#else /* lint */ 2750Sstevel@tonic-gate/* 2760Sstevel@tonic-gate * This is to ensure that previously called xtrap handlers have executed on 2770Sstevel@tonic-gate * sun4v. We zero out the byte corresponding to its cpuid in the 2780Sstevel@tonic-gate * array passed to us from xt_sync(), so the sender knows the previous 2790Sstevel@tonic-gate * mondo has been executed. 2800Sstevel@tonic-gate * Register: 2810Sstevel@tonic-gate * %g1 - Addr of the cpu_sync array. 2820Sstevel@tonic-gate */ 2830Sstevel@tonic-gate ENTRY_NP(xt_sync_tl1) 2840Sstevel@tonic-gate CPU_INDEX(%g3, %g4) /* %g3 = cpu id */ 2850Sstevel@tonic-gate stb %g0, [%g1 + %g3] 2860Sstevel@tonic-gate retry 2870Sstevel@tonic-gate SET_SIZE(xt_sync_tl1) 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate#endif /* lint */ 290