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 2007 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#include <sys/trap.h> 36 37#if defined(__lint) 38#include <sys/types.h> 39#include <sys/systm.h> 40#include <sys/thread.h> 41#include <sys/archsystm.h> 42#include <sys/byteorder.h> 43#include <sys/dtrace.h> 44#include <sys/x86_archext.h> 45#else /* __lint */ 46#include "assym.h" 47#endif /* __lint */ 48 49#if defined(__lint) 50 51/*ARGSUSED*/ 52void 53rd_idtr(desctbr_t *idtr) 54{} 55 56/*ARGSUSED*/ 57void 58wr_idtr(desctbr_t *idtr) 59{} 60 61#else /* __lint */ 62 63#if defined(__amd64) 64 65 ENTRY_NP(rd_idtr) 66 sidt (%rdi) 67 ret 68 SET_SIZE(rd_idtr) 69 70 ENTRY_NP(wr_idtr) 71 lidt (%rdi) 72 ret 73 SET_SIZE(wr_idtr) 74 75#elif defined(__i386) 76 77 ENTRY_NP(rd_idtr) 78 pushl %ebp 79 movl %esp, %ebp 80 movl 8(%ebp), %edx 81 sidt (%edx) 82 leave 83 ret 84 SET_SIZE(rd_idtr) 85 86 ENTRY_NP(wr_idtr) 87 pushl %ebp 88 movl %esp, %ebp 89 movl 8(%ebp), %edx 90 lidt (%edx) 91 leave 92 ret 93 SET_SIZE(wr_idtr) 94 95#endif /* __i386 */ 96#endif /* __lint */ 97 98#if defined(__lint) 99 100/*ARGSUSED*/ 101void 102rd_gdtr(desctbr_t *gdtr) 103{} 104 105/*ARGSUSED*/ 106void 107wr_gdtr(desctbr_t *gdtr) 108{} 109 110#else /* __lint */ 111 112#if defined(__amd64) 113 114 ENTRY_NP(rd_gdtr) 115 pushq %rbp 116 movq %rsp, %rbp 117 sgdt (%rdi) 118 leave 119 ret 120 SET_SIZE(rd_gdtr) 121 122 ENTRY_NP(wr_gdtr) 123 pushq %rbp 124 movq %rsp, %rbp 125 lgdt (%rdi) 126 jmp 1f 127 nop 1281: 129 leave 130 ret 131 SET_SIZE(wr_gdtr) 132 133#elif defined(__i386) 134 135 ENTRY_NP(rd_gdtr) 136 pushl %ebp 137 movl %esp, %ebp 138 movl 8(%ebp), %edx 139 sgdt (%edx) 140 leave 141 ret 142 SET_SIZE(rd_gdtr) 143 144 ENTRY_NP(wr_gdtr) 145 pushl %ebp 146 movl %esp, %ebp 147 movl 8(%ebp), %edx 148 lgdt (%edx) 149 jmp 1f 150 nop 1511: 152 leave 153 ret 154 SET_SIZE(wr_gdtr) 155 156#endif /* __i386 */ 157#endif /* __lint */ 158 159#if defined(__amd64) 160#if defined(__lint) 161 162/*ARGSUSED*/ 163void 164load_segment_registers(selector_t cs, selector_t fs, selector_t gs, 165 selector_t ss) 166{} 167 168#else /* __lint */ 169 170 /* 171 * loads zero selector for ds and es. 172 */ 173 ENTRY_NP(load_segment_registers) 174 pushq %rbp 175 movq %rsp, %rbp 176 pushq %rdi 177 pushq $.newcs 178 lretq 179.newcs: 180 /* 181 * zero %ds and %es - they're ignored anyway 182 */ 183 xorl %eax, %eax 184 movw %ax, %ds 185 movw %ax, %es 186 movl %esi, %eax 187 movw %ax, %fs 188 movl %edx, %eax 189 movw %ax, %gs 190 movl %ecx, %eax 191 movw %ax, %ss 192 leave 193 ret 194 SET_SIZE(load_segment_registers) 195 196#endif /* __lint */ 197#elif defined(__i386) 198 199#if defined(__lint) 200 201/*ARGSUSED*/ 202void 203load_segment_registers( 204 selector_t cs, selector_t ds, selector_t es, 205 selector_t fs, selector_t gs, selector_t ss) 206{} 207 208#else /* __lint */ 209 210 ENTRY_NP(load_segment_registers) 211 pushl %ebp 212 movl %esp, %ebp 213 214 pushl 0x8(%ebp) 215 pushl $.newcs 216 lret 217.newcs: 218 movw 0xc(%ebp), %ax 219 movw %ax, %ds 220 movw 0x10(%ebp), %ax 221 movw %ax, %es 222 movw 0x14(%ebp), %ax 223 movw %ax, %fs 224 movw 0x18(%ebp), %ax 225 movw %ax, %gs 226 movw 0x1c(%ebp), %ax 227 movw %ax, %ss 228 leave 229 ret 230 SET_SIZE(load_segment_registers) 231 232#endif /* __lint */ 233#endif /* __i386 */ 234 235#if defined(__lint) 236 237/*ARGSUSED*/ 238void 239wr_ldtr(selector_t ldtsel) 240{} 241 242selector_t 243rd_ldtr(void) 244{ return (0); } 245 246#if defined(__amd64) 247void 248clr_ldt_sregs(void) 249{} 250#endif 251 252#else /* __lint */ 253 254#if defined(__amd64) 255 256 ENTRY_NP(wr_ldtr) 257 movq %rdi, %rax 258 lldt %ax 259 ret 260 SET_SIZE(wr_ldtr) 261 262 ENTRY_NP(rd_ldtr) 263 xorl %eax, %eax 264 sldt %ax 265 ret 266 SET_SIZE(rd_ldtr) 267 268 /* 269 * Make sure any stale ldt selectors are cleared by loading 270 * KDS_SEL (kernel %ds gdt selector). This is necessary 271 * since the kernel does not use %es, %fs and %ds. %cs and 272 * %ss are necessary and setup by the kernel along with %gs 273 * to point to current cpu struct. If we take a kmdb breakpoint 274 * in the kernel and resume with a stale ldt selector kmdb 275 * would #gp fault if it points to a ldt in the context of 276 * another process. 277 * 278 * WARNING: Nocona and AMD have different behaviour about storing 279 * the null selector into %fs and %gs while in long mode. On AMD 280 * chips fsbase and gsbase is not cleared. But on nocona storing 281 * null selector into %fs or %gs has the side effect of clearing 282 * fsbase or gsbase. For that reason we use KDS_SEL which has 283 * consistent behavoir between AMD and Nocona. 284 */ 285 ENTRY_NP(clr_ldt_sregs) 286 287 /* 288 * Save GSBASE before resetting %gs to KDS_SEL 289 * then restore GSBASE. 290 */ 291 cli 292 movq %rbx, %rdi 293 movw $KDS_SEL, %bx 294 movl $MSR_AMD_GSBASE, %ecx 295 rdmsr 296 movw %bx, %gs 297 wrmsr 298 sti 299 movw %bx, %ds 300 movw %bx, %es 301 movw %bx, %fs 302 movq %rdi, %rbx 303 ret 304 SET_SIZE(clr_ldt_sregs) 305 306#elif defined(__i386) 307 308 ENTRY_NP(wr_ldtr) 309 movw 4(%esp), %ax 310 lldt %ax 311 ret 312 SET_SIZE(wr_ldtr) 313 314 ENTRY_NP(rd_ldtr) 315 xorl %eax, %eax 316 sldt %ax 317 ret 318 SET_SIZE(rd_ldtr) 319 320#endif /* __i386 */ 321#endif /* __lint */ 322 323#if defined(__lint) 324 325/*ARGSUSED*/ 326void 327wr_tsr(selector_t tsssel) 328{} 329 330#else /* __lint */ 331 332#if defined(__amd64) 333 334 ENTRY_NP(wr_tsr) 335 movq %rdi, %rax 336 ltr %ax 337 ret 338 SET_SIZE(wr_tsr) 339 340#elif defined(__i386) 341 342 ENTRY_NP(wr_tsr) 343 movw 4(%esp), %ax 344 ltr %ax 345 ret 346 SET_SIZE(wr_tsr) 347 348#endif /* __i386 */ 349#endif /* __lint */ 350