1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26#pragma ident "%Z%%M% %I% %E% SMI" 27 28#include <sys/asm_linkage.h> 29#include <sys/asm_misc.h> 30#include <sys/regset.h> 31#include <sys/panic.h> 32#include <sys/ontrap.h> 33#include <sys/privregs.h> 34#include <sys/segments.h> 35 36#if defined(__lint) 37#include <sys/types.h> 38#include <sys/systm.h> 39#include <sys/thread.h> 40#include <sys/archsystm.h> 41#include <sys/byteorder.h> 42#include <sys/dtrace.h> 43#include <sys/x86_archext.h> 44#else /* __lint */ 45#include "assym.h" 46#endif /* __lint */ 47 48#if !defined(__lint) 49 DGDEF3(gdt0, MMU_STD_PAGESIZE, MMU_STD_PAGESIZE) 50 .zero MMU_STD_PAGESIZE 51#endif /* __lint */ 52 53#if defined(__lint) 54 55/*ARGSUSED*/ 56void rd_idtr(desctbr_t *idtr) 57{} 58 59/*ARGSUSED*/ 60void wr_idtr(desctbr_t *idtr) 61{} 62 63#else /* __lint */ 64 65#if defined(__amd64) 66 67 ENTRY_NP(rd_idtr) 68 sidt (%rdi) 69 ret 70 SET_SIZE(rd_idtr) 71 72 ENTRY_NP(wr_idtr) 73 lidt (%rdi) 74 ret 75 SET_SIZE(wr_idtr) 76 77#elif defined(__i386) 78 79 ENTRY_NP(rd_idtr) 80 pushl %ebp 81 movl %esp, %ebp 82 movl 8(%ebp), %edx 83 sidt (%edx) 84 leave 85 ret 86 SET_SIZE(rd_idtr) 87 88 ENTRY_NP(wr_idtr) 89 pushl %ebp 90 movl %esp, %ebp 91 movl 8(%ebp), %edx 92 lidt (%edx) 93 leave 94 ret 95 SET_SIZE(wr_idtr) 96 97#endif /* __i386 */ 98#endif /* __lint */ 99 100#if defined(__lint) 101 102/*ARGSUSED*/ 103void rd_gdtr(desctbr_t *gdtr) 104{} 105 106/*ARGSUSED*/ 107void wr_gdtr(desctbr_t *gdtr) 108{} 109 110#else /* __lint */ 111 112#if defined(__amd64) 113 114 ENTRY_NP(rd_gdtr) 115 sgdt (%rdi) 116 ret 117 SET_SIZE(rd_gdtr) 118 119 ENTRY_NP(wr_gdtr) 120 lgdt (%rdi) 121 jmp 1f 122 nop 1231: 124 movl $KDS_SEL, %eax 125 movw %ax, %ss 126 /* 127 * zero %ds and %es - they're ignored anyway 128 */ 129 xorl %eax, %eax 130 movw %ax, %ds 131 movw %ax, %es 132 /* 133 * set %fs and %gs (probably to zero also) 134 */ 135 movl $KFS_SEL, %eax 136 movw %ax, %fs 137 movl $KGS_SEL, %eax 138 movw %ax, %gs 139 popq %rax 140 pushq $KCS_SEL 141 pushq %rax 142 lretq 143 SET_SIZE(wr_gdtr) 144 145#elif defined(__i386) 146 147 ENTRY_NP(rd_gdtr) 148 pushl %ebp 149 movl %esp, %ebp 150 movl 8(%ebp), %edx 151 sgdt (%edx) 152 leave 153 ret 154 SET_SIZE(rd_gdtr) 155 156 ENTRY_NP(wr_gdtr) 157 pushl %ebp 158 movl %esp, %ebp 159 movl 8(%ebp), %edx 160 lgdt (%edx) 161 nop 162 ljmp $KCS_SEL, $.next 163.next: 164 movl $KDS_SEL, %eax 165 movw %ax, %ds 166 movw %ax, %es 167 movw %ax, %ss 168 movl $KFS_SEL, %eax 169 movw %ax, %fs 170 movl $KGS_SEL, %eax 171 movw %ax, %gs 172 leave 173 ret 174 SET_SIZE(wr_gdtr) 175 176#endif /* __i386 */ 177#endif /* __lint */ 178 179#if defined(__lint) 180 181/*ARGSUSED*/ 182void wr_ldtr(selector_t ldtsel) 183{} 184 185selector_t rd_ldtr(void) 186{ return (0); } 187 188#if defined(__amd64) 189void clr_ldt_sregs(void) 190{} 191#endif 192 193#else /* __lint */ 194 195#if defined(__amd64) 196 197 ENTRY_NP(wr_ldtr) 198 movq %rdi, %rax 199 lldt %ax 200 ret 201 SET_SIZE(wr_ldtr) 202 203 ENTRY_NP(rd_ldtr) 204 xorl %eax, %eax 205 sldt %ax 206 ret 207 SET_SIZE(rd_ldtr) 208 209 /* 210 * Make sure any stale ldt selectors are cleared by loading 211 * KDS_SEL (kernel %ds gdt selector). This is necessary 212 * since the kernel does not use %es, %fs and %ds. %cs and 213 * %ss are necessary and setup by the kernel along with %gs 214 * to point to current cpu struct. If we take a kmdb breakpoint 215 * in the kernel and resume with a stale ldt selector kmdb 216 * would #gp fault if it points to a ldt in the context of 217 * another process. 218 * 219 * WARNING: Nocona and AMD have different behaviour about storing 220 * the null selector into %fs and %gs while in long mode. On AMD 221 * chips fsbase and gsbase is not cleared. But on nocona storing 222 * null selector into %fs or %gs has the side effect of clearing 223 * fsbase or gsbase. For that reason we use KDS_SEL which has 224 * consistent behavoir between AMD and Nocona. 225 */ 226 ENTRY_NP(clr_ldt_sregs) 227 228 /* 229 * Save GSBASE before resetting %gs to KDS_SEL 230 * then restore GSBASE. 231 */ 232 cli 233 movq %rbx, %rdi 234 movw $KDS_SEL, %bx 235 movl $MSR_AMD_GSBASE, %ecx 236 rdmsr 237 movw %bx, %gs 238 wrmsr 239 sti 240 movw %bx, %ds 241 movw %bx, %es 242 movw %bx, %fs 243 movq %rdi, %rbx 244 ret 245 SET_SIZE(clr_ldt_sregs) 246 247#elif defined(__i386) 248 249 ENTRY_NP(wr_ldtr) 250 movw 4(%esp), %ax 251 lldt %ax 252 ret 253 SET_SIZE(wr_ldtr) 254 255 ENTRY_NP(rd_ldtr) 256 xorl %eax, %eax 257 sldt %ax 258 ret 259 SET_SIZE(rd_ldtr) 260 261#endif /* __i386 */ 262#endif /* __lint */ 263 264#if defined(__lint) 265 266/*ARGSUSED*/ 267void wr_tsr(selector_t tsssel) 268{} 269 270#else /* __lint */ 271 272#if defined(__amd64) 273 274 ENTRY_NP(wr_tsr) 275 movq %rdi, %rax 276 ltr %ax 277 ret 278 SET_SIZE(wr_tsr) 279 280#elif defined(__i386) 281 282 ENTRY_NP(wr_tsr) 283 movw 4(%esp), %ax 284 ltr %ax 285 ret 286 SET_SIZE(wr_tsr) 287 288#endif /* __i386 */ 289#endif /* __lint */ 290