17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*8f230a59Sbs21162 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #ifndef _SYS_MACHTHREAD_H 287c478bd9Sstevel@tonic-gate #define _SYS_MACHTHREAD_H 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <sys/asi.h> 337c478bd9Sstevel@tonic-gate #include <sys/sun4asi.h> 347c478bd9Sstevel@tonic-gate #include <sys/machasi.h> 357c478bd9Sstevel@tonic-gate #include <sys/bitmap.h> 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #ifdef __cplusplus 387c478bd9Sstevel@tonic-gate extern "C" { 397c478bd9Sstevel@tonic-gate #endif 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #ifdef _ASM 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #define THREAD_REG %g7 /* pointer to current thread data */ 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate /* 467c478bd9Sstevel@tonic-gate * Get the processor implementation from the version register. 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate #define GET_CPU_IMPL(out) \ 497c478bd9Sstevel@tonic-gate rdpr %ver, out; \ 507c478bd9Sstevel@tonic-gate srlx out, 32, out; \ 517c478bd9Sstevel@tonic-gate sll out, 16, out; \ 527c478bd9Sstevel@tonic-gate srl out, 16, out; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #ifdef _STARFIRE 557c478bd9Sstevel@tonic-gate /* 567c478bd9Sstevel@tonic-gate * CPU_INDEX(r, scr) 577c478bd9Sstevel@tonic-gate * Returns cpu id in r. 587c478bd9Sstevel@tonic-gate * On Starfire, this is read from the Port Controller's Port ID 597c478bd9Sstevel@tonic-gate * register in local space. 607c478bd9Sstevel@tonic-gate * 617c478bd9Sstevel@tonic-gate * Need to load the 64 bit address of the PC's PortID reg 627c478bd9Sstevel@tonic-gate * using only one register. Kludge the 41 bits address constant to 637c478bd9Sstevel@tonic-gate * be 32bits by shifting it 12 bits to the right first. 647c478bd9Sstevel@tonic-gate */ 657c478bd9Sstevel@tonic-gate #define LOCAL_PC_PORTID_ADDR_SRL12 0x1FFF4000 667c478bd9Sstevel@tonic-gate #define PC_PORT_ID 0xD0 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate #define CPU_INDEX(r, scr) \ 697c478bd9Sstevel@tonic-gate rdpr %pstate, scr; \ 707c478bd9Sstevel@tonic-gate andn scr, PSTATE_IE | PSTATE_AM, r; \ 717c478bd9Sstevel@tonic-gate wrpr r, 0, %pstate; \ 727c478bd9Sstevel@tonic-gate set LOCAL_PC_PORTID_ADDR_SRL12, r; \ 737c478bd9Sstevel@tonic-gate sllx r, 12, r; \ 747c478bd9Sstevel@tonic-gate or r, PC_PORT_ID, r; \ 757c478bd9Sstevel@tonic-gate lduwa [r]ASI_IO, r; \ 767c478bd9Sstevel@tonic-gate wrpr scr, 0, %pstate 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate #else /* _STARFIRE */ 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* 817c478bd9Sstevel@tonic-gate * UPA supports up to 32 devices while Safari supports up to 827c478bd9Sstevel@tonic-gate * 1024 devices (utilizing the SSM protocol). Based upon the 837c478bd9Sstevel@tonic-gate * value of NCPU, a 5- or 10-bit mask will be needed for 847c478bd9Sstevel@tonic-gate * extracting the cpu id. 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate #if NCPU > 32 877c478bd9Sstevel@tonic-gate #define CPU_MASK 0x3ff 887c478bd9Sstevel@tonic-gate #else 897c478bd9Sstevel@tonic-gate #define CPU_MASK 0x1f 907c478bd9Sstevel@tonic-gate #endif /* NCPU > 32 */ 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * CPU_INDEX(r, scr) 947c478bd9Sstevel@tonic-gate * Returns cpu id in r. 957c478bd9Sstevel@tonic-gate * For UPA based systems, the cpu id corresponds to the mid field in 967c478bd9Sstevel@tonic-gate * the UPA config register. For Safari based machines, the cpu id 977c478bd9Sstevel@tonic-gate * corresponds to the aid field in the Safari config register. 987c478bd9Sstevel@tonic-gate * 997c478bd9Sstevel@tonic-gate * XXX - scr reg is not used here. 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate #define CPU_INDEX(r, scr) \ 1027c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_UPA_CONFIG, r; \ 1037c478bd9Sstevel@tonic-gate srlx r, 17, r; \ 1047c478bd9Sstevel@tonic-gate and r, CPU_MASK, r 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate #endif /* _STARFIRE */ 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate /* 1097c478bd9Sstevel@tonic-gate * Given a cpu id extract the appropriate word 1107c478bd9Sstevel@tonic-gate * in the cpuset mask for this cpu id. 1117c478bd9Sstevel@tonic-gate */ 1127c478bd9Sstevel@tonic-gate #if CPUSET_SIZE > CLONGSIZE 1137c478bd9Sstevel@tonic-gate #define CPU_INDEXTOSET(base, index, scr) \ 1147c478bd9Sstevel@tonic-gate srl index, BT_ULSHIFT, scr; \ 1157c478bd9Sstevel@tonic-gate and index, BT_ULMASK, index; \ 1167c478bd9Sstevel@tonic-gate sll scr, CLONGSHIFT, scr; \ 1177c478bd9Sstevel@tonic-gate add base, scr, base 1187c478bd9Sstevel@tonic-gate #else 1197c478bd9Sstevel@tonic-gate #define CPU_INDEXTOSET(base, index, scr) 1207c478bd9Sstevel@tonic-gate #endif /* CPUSET_SIZE */ 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * Assembly macro to find address of the current CPU. 1257c478bd9Sstevel@tonic-gate * Used when coming in from a user trap - cannot use THREAD_REG. 1267c478bd9Sstevel@tonic-gate * Args are destination register and one scratch register. 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate #define CPU_ADDR(reg, scr) \ 1297c478bd9Sstevel@tonic-gate .global cpu; \ 1307c478bd9Sstevel@tonic-gate CPU_INDEX(scr, reg); \ 1317c478bd9Sstevel@tonic-gate sll scr, CPTRSHIFT, scr; \ 1327c478bd9Sstevel@tonic-gate set cpu, reg; \ 1337c478bd9Sstevel@tonic-gate ldn [reg + scr], reg 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate #define CINT64SHIFT 3 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* 1387c478bd9Sstevel@tonic-gate * Assembly macro to find the physical address of the current CPU. 1397c478bd9Sstevel@tonic-gate * All memory references using VA must be limited to nucleus 1407c478bd9Sstevel@tonic-gate * memory to avoid any MMU side effect. 1417c478bd9Sstevel@tonic-gate */ 1427c478bd9Sstevel@tonic-gate #define CPU_PADDR(reg, scr) \ 1437c478bd9Sstevel@tonic-gate .global cpu_pa; \ 1447c478bd9Sstevel@tonic-gate CPU_INDEX(scr, reg); \ 1457c478bd9Sstevel@tonic-gate sll scr, CINT64SHIFT, scr; \ 1467c478bd9Sstevel@tonic-gate set cpu_pa, reg; \ 1477c478bd9Sstevel@tonic-gate ldx [reg + scr], reg 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate #endif /* _ASM */ 1507c478bd9Sstevel@tonic-gate 151*8f230a59Sbs21162 /* 152*8f230a59Sbs21162 * If a high level trap handler decides to call sys_trap() to execute some 153*8f230a59Sbs21162 * base level code, context and other registers must be set to proper 154*8f230a59Sbs21162 * values to run kernel. This is true for most part of the kernel, except 155*8f230a59Sbs21162 * for user_rtt, a substantial part of which is executed with registers 156*8f230a59Sbs21162 * ready to run user code. The following macro may be used to detect this 157*8f230a59Sbs21162 * condition and handle it. Please note that, in general, we can't restart 158*8f230a59Sbs21162 * arbitrary piece of code running at tl > 0; user_rtt is a special case 159*8f230a59Sbs21162 * that can be handled. 160*8f230a59Sbs21162 * 161*8f230a59Sbs21162 * Entry condition: 162*8f230a59Sbs21162 * 163*8f230a59Sbs21162 * %tl = 2 164*8f230a59Sbs21162 * pstate.ag = 1 165*8f230a59Sbs21162 * 166*8f230a59Sbs21162 * Register usage: 167*8f230a59Sbs21162 * 168*8f230a59Sbs21162 * scr1, scr2 - destroyed 169*8f230a59Sbs21162 * normal %g5 and %g6 - destroyed 170*8f230a59Sbs21162 * 171*8f230a59Sbs21162 */ 172*8f230a59Sbs21162 /* BEGIN CSTYLED */ 173*8f230a59Sbs21162 #define RESET_USER_RTT_REGS(scr1, scr2, label) \ 174*8f230a59Sbs21162 /* \ 175*8f230a59Sbs21162 * do nothing if %tl != 2. this an attempt to stop this \ 176*8f230a59Sbs21162 * piece of code from executing more than once before going \ 177*8f230a59Sbs21162 * back to TL=0. more specifically, the changes we are doing \ 178*8f230a59Sbs21162 * to %wstate, %canrestore and %otherwin can't be done more \ 179*8f230a59Sbs21162 * than once before going to TL=0. note that it is okay to \ 180*8f230a59Sbs21162 * execute this more than once if we restart at user_rtt and \ 181*8f230a59Sbs21162 * come back from there. \ 182*8f230a59Sbs21162 */ \ 183*8f230a59Sbs21162 rdpr %tl, scr1; \ 184*8f230a59Sbs21162 cmp scr1, 2; \ 185*8f230a59Sbs21162 bne,a,pn %xcc, label; \ 186*8f230a59Sbs21162 nop; \ 187*8f230a59Sbs21162 /* \ 188*8f230a59Sbs21162 * read tstate[2].%tpc. do nothing if it is not \ 189*8f230a59Sbs21162 * between rtt_ctx_start and rtt_ctx_end. \ 190*8f230a59Sbs21162 */ \ 191*8f230a59Sbs21162 rdpr %tpc, scr1; \ 192*8f230a59Sbs21162 set rtt_ctx_end, scr2; \ 193*8f230a59Sbs21162 cmp scr1, scr2; \ 194*8f230a59Sbs21162 bgu,a,pt %xcc, label; \ 195*8f230a59Sbs21162 nop; \ 196*8f230a59Sbs21162 set rtt_ctx_start, scr2; \ 197*8f230a59Sbs21162 cmp scr1, scr2; \ 198*8f230a59Sbs21162 blu,a,pt %xcc, label; \ 199*8f230a59Sbs21162 nop; \ 200*8f230a59Sbs21162 /* \ 201*8f230a59Sbs21162 * pickup tstate[2].cwp \ 202*8f230a59Sbs21162 */ \ 203*8f230a59Sbs21162 rdpr %tstate, scr1; \ 204*8f230a59Sbs21162 and scr1, TSTATE_CWP, scr1; \ 205*8f230a59Sbs21162 /* \ 206*8f230a59Sbs21162 * set tstate[1].cwp to tstate[2].cwp. fudge \ 207*8f230a59Sbs21162 * tstate[1].tpc and tstate[1].tnpc to restart \ 208*8f230a59Sbs21162 * user_rtt. \ 209*8f230a59Sbs21162 */ \ 210*8f230a59Sbs21162 wrpr %g0, 1, %tl; \ 211*8f230a59Sbs21162 set TSTATE_KERN | TSTATE_IE, scr2; \ 212*8f230a59Sbs21162 or scr1, scr2, scr2; \ 213*8f230a59Sbs21162 wrpr %g0, scr2, %tstate; \ 214*8f230a59Sbs21162 set user_rtt, scr1; \ 215*8f230a59Sbs21162 wrpr %g0, scr1, %tpc; \ 216*8f230a59Sbs21162 add scr1, 4, scr1; \ 217*8f230a59Sbs21162 wrpr %g0, scr1, %tnpc; \ 218*8f230a59Sbs21162 /* \ 219*8f230a59Sbs21162 * restore %tl \ 220*8f230a59Sbs21162 */ \ 221*8f230a59Sbs21162 wrpr %g0, 2, %tl; \ 222*8f230a59Sbs21162 /* \ 223*8f230a59Sbs21162 * set %wstate \ 224*8f230a59Sbs21162 */ \ 225*8f230a59Sbs21162 rdpr %wstate, scr1; \ 226*8f230a59Sbs21162 sllx scr1, WSTATE_SHIFT, scr1; \ 227*8f230a59Sbs21162 wrpr scr1, WSTATE_K64, %wstate; \ 228*8f230a59Sbs21162 /* \ 229*8f230a59Sbs21162 * setup window registers \ 230*8f230a59Sbs21162 * %cleanwin <-- nwin - 1 \ 231*8f230a59Sbs21162 * %otherwin <-- %canrestore \ 232*8f230a59Sbs21162 * %canrestore <-- 0 \ 233*8f230a59Sbs21162 */ \ 234*8f230a59Sbs21162 sethi %hi(nwin_minus_one), scr1; \ 235*8f230a59Sbs21162 ld [scr1 + %lo(nwin_minus_one)], scr1; \ 236*8f230a59Sbs21162 wrpr %g0, scr1, %cleanwin; \ 237*8f230a59Sbs21162 rdpr %canrestore, scr1; \ 238*8f230a59Sbs21162 wrpr %g0, scr1, %otherwin; \ 239*8f230a59Sbs21162 wrpr %g0, 0, %canrestore; \ 240*8f230a59Sbs21162 /* \ 241*8f230a59Sbs21162 * set THREAD_REG, as we have restored user \ 242*8f230a59Sbs21162 * registers in user_rtt. we trash %g5 and %g6 \ 243*8f230a59Sbs21162 * in the process. \ 244*8f230a59Sbs21162 */ \ 245*8f230a59Sbs21162 rdpr %pstate, scr1; \ 246*8f230a59Sbs21162 wrpr scr1, PSTATE_AG, %pstate; \ 247*8f230a59Sbs21162 /* \ 248*8f230a59Sbs21162 * using normal globals now \ 249*8f230a59Sbs21162 */ \ 250*8f230a59Sbs21162 CPU_ADDR(%g5, %g6); \ 251*8f230a59Sbs21162 ldn [%g5 + CPU_THREAD], %g6; \ 252*8f230a59Sbs21162 mov %g6, THREAD_REG; \ 253*8f230a59Sbs21162 rdpr %pstate, %g5; \ 254*8f230a59Sbs21162 wrpr %g5, PSTATE_AG, %pstate; \ 255*8f230a59Sbs21162 /* \ 256*8f230a59Sbs21162 * back to alternate globals. \ 257*8f230a59Sbs21162 * set PCONTEXT to run kernel. \ 258*8f230a59Sbs21162 * no need to demap I/DTLB as we \ 259*8f230a59Sbs21162 * never went back to user mode. \ 260*8f230a59Sbs21162 */ \ 261*8f230a59Sbs21162 mov MMU_PCONTEXT, scr1; \ 262*8f230a59Sbs21162 sethi %hi(kcontextreg), scr2; \ 263*8f230a59Sbs21162 ldx [scr2 + %lo(kcontextreg)], scr2; \ 264*8f230a59Sbs21162 stxa scr2, [scr1]ASI_MMU_CTX; \ 265*8f230a59Sbs21162 sethi %hi(FLUSH_ADDR), scr1; \ 266*8f230a59Sbs21162 flush scr1; 267*8f230a59Sbs21162 268*8f230a59Sbs21162 /* END CSTYLED */ 269*8f230a59Sbs21162 2707c478bd9Sstevel@tonic-gate #ifdef __cplusplus 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate #endif 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate #endif /* _SYS_MACHTHREAD_H */ 275