1/* $OpenBSD: locore.s,v 1.206 2024/10/21 07:21:18 jsg Exp $ */ 2/* $NetBSD: locore.s,v 1.145 1996/05/03 19:41:19 christos Exp $ */ 3 4/*- 5 * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved. 6 * Copyright (c) 1990 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * William Jolitz. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)locore.s 7.3 (Berkeley) 5/13/91 37 */ 38 39#include "npx.h" 40#include "assym.h" 41#include "lapic.h" 42 43#include <sys/errno.h> 44#include <sys/syscall.h> 45 46#include <machine/codepatch.h> 47#include <machine/param.h> 48#include <machine/pte.h> 49#include <machine/segments.h> 50#include <machine/specialreg.h> 51#include <machine/trap.h> 52 53#if NLAPIC > 0 54#include <machine/i82489reg.h> 55#endif 56 57/* 58 * As stac/clac SMAP instructions are 3 bytes, we want the fastest 59 * 3 byte nop sequence possible here. This will be replaced by 60 * stac/clac instructions if SMAP is detected after booting. 61 * 62 * Intel documents multi-byte NOP sequences as being available 63 * on all family 0x6 and 0xf processors (ie 686+) 64 * So use 3 of the single byte nops for compatibility 65 */ 66#define SMAP_NOP .byte 0x90, 0x90, 0x90 67#define SMAP_STAC CODEPATCH_START ;\ 68 SMAP_NOP ;\ 69 CODEPATCH_END(CPTAG_STAC) 70#define SMAP_CLAC CODEPATCH_START ;\ 71 SMAP_NOP ;\ 72 CODEPATCH_END(CPTAG_CLAC) 73 74/* 75 * override user-land alignment before including asm.h 76 */ 77 78#define ALIGN_DATA .align 4,0xcc 79#define ALIGN_TEXT .align 4,0x90 /* 4-byte boundaries, NOP-filled */ 80#define _ALIGN_TEXT ALIGN_TEXT 81#include <machine/asm.h> 82 83#define CPL lapic_tpr 84 85#define GET_CURPCB(reg) \ 86 movl CPUVAR(CURPCB), reg 87 88#define CHECK_ASTPENDING(treg) \ 89 movl CPUVAR(CURPROC),treg ; \ 90 cmpl $0, treg ; \ 91 je 1f ; \ 92 cmpl $0,P_MD_ASTPENDING(treg) ; \ 93 1: 94 95#define CLEAR_ASTPENDING(cpreg) \ 96 movl $0,P_MD_ASTPENDING(cpreg) 97 98/* 99 * These are used on interrupt or trap entry or exit. 100 */ 101#define INTR_COPY_FROM_TRAMP_STACK \ 102 movl TRF_SS(%ebp),%eax ; \ 103 movl %eax,IRF_SS(%esp) ; \ 104 movl TRF_ESP(%ebp),%eax ; \ 105 movl %eax,IRF_ESP(%esp) ; \ 106 movl TRF_EFLAGS(%ebp),%eax ; \ 107 movl %eax,IRF_EFLAGS(%esp) ; \ 108 movl TRF_CS(%ebp),%eax ; \ 109 movl %eax,IRF_CS(%esp) ; \ 110 movl TRF_EIP(%ebp),%eax ; \ 111 movl %eax,IRF_EIP(%esp) ; \ 112 movl TRF_ERR(%ebp),%eax ; \ 113 movl %eax,IRF_ERR(%esp) ; \ 114 movl TRF_TRAPNO(%ebp),%eax ; \ 115 movl %eax,IRF_TRAPNO(%esp) 116 117#define INTR_ENABLE_U_PLUS_K \ 118 movl $GSEL(GCPU_SEL, SEL_KPL),%eax ; \ 119 movw %ax,%fs ; \ 120 movl CPUVAR(KERN_CR3),%eax ; \ 121 testl %eax,%eax ; \ 122 jz 100f ; \ 123 movl %eax,%cr3 ; \ 124 100: 125 126#define INTRENTRY_LABEL(label) X##label##_untramp 127#define INTRENTRY(label) \ 128 /* we have an iretframe */ ; \ 129 testb $SEL_RPL,IRF_CS(%esp) ; \ 130 /* from kernel, stay on kernel stack, use iretframe */ ; \ 131 je INTRENTRY_LABEL(label) ; \ 132 /* entering from user space, map kernel */ ; \ 133 pushl %ebp ; \ 134 pushl %eax ; \ 135 pushl %fs ; \ 136 INTR_ENABLE_U_PLUS_K ; \ 137 jmp 99f ; \ 138 .text ; \ 139 .global INTRENTRY_LABEL(label) ; \ 140INTRENTRY_LABEL(label): /* from kernel */ ; \ 141 jmp 98f ; \ 142 /* from user space, build trampframe */ ; \ 14399: movl CPUVAR(KERN_ESP),%eax ; \ 144 pushl %eax ; \ 145 pushl $0xdeadbeef ; \ 146 movl %esp,%ebp ; \ 147 movl %eax,%esp ; \ 148 subl $SIZEOF_IRETFRAME,%esp ; \ 149 /* we have a trampframe, copy to iretframe on kernel stack */ ; \ 150 INTR_COPY_FROM_TRAMP_STACK ; \ 151 movl TRF_FS(%ebp),%eax ; \ 152 movw %ax,%fs ; \ 153 movl TRF_EAX(%ebp),%eax ; \ 154 movl TRF_EBP(%ebp),%ebp ; \ 15598: INTR_SAVE_ALL 156 157#define INTR_SAVE_ALL \ 158 cld ; \ 159 SMAP_CLAC ; \ 160 /* we have an iretframe, build trapframe */ ; \ 161 subl $44,%esp ; \ 162 movl %eax,TF_EAX(%esp) ; \ 163 /* the hardware puts err next to %eip, we move it elsewhere and */ ; \ 164 /* later put %ebp in this slot to make it look like a call frame */ ; \ 165 movl (TF_EIP - 4)(%esp),%eax ; \ 166 movl %eax,TF_ERR(%esp) ; \ 167 movl %ecx,TF_ECX(%esp) ; \ 168 movl %edx,TF_EDX(%esp) ; \ 169 movl %ebx,TF_EBX(%esp) ; \ 170 movl %ebp,TF_EBP(%esp) ; \ 171 leal TF_EBP(%esp),%ebp ; \ 172 movl %esi,TF_ESI(%esp) ; \ 173 movl %edi,TF_EDI(%esp) ; \ 174 movw %ds,TF_DS(%esp) ; \ 175 movw %es,TF_ES(%esp) ; \ 176 movw %gs,TF_GS(%esp) ; \ 177 movl $GSEL(GDATA_SEL, SEL_KPL),%eax ; \ 178 movw %ax,%ds ; \ 179 movw %ax,%es ; \ 180 xorl %eax,%eax ; /* $GSEL(GNULL_SEL, SEL_KPL) == 0 */ \ 181 movw %ax,%gs ; \ 182 movw %fs,TF_FS(%esp) ; \ 183 movl $GSEL(GCPU_SEL, SEL_KPL),%eax ; \ 184 movw %ax,%fs 185 186#define INTR_RESTORE_ALL \ 187 popl %fs ; \ 188 popl %gs ; \ 189 popl %es ; \ 190 popl %ds ; \ 191 popl %edi ; \ 192 popl %esi ; \ 193 addl $4,%esp /*err*/ ; \ 194 popl %ebx ; \ 195 popl %edx ; \ 196 popl %ecx ; \ 197 popl %eax ; \ 198 movl 4(%esp),%ebp 199 200#define INTRFASTEXIT \ 201 jmp intr_fast_exit 202 203#define INTR_FAKE_TRAP_PUSH_RPB 0xbadabada 204#define INTR_FAKE_TRAP_POP_RBP 0xbcbcbcbc 205 206/* 207 * PTmap is recursive pagemap at top of virtual address space. 208 * Within PTmap, the page directory can be found (third indirection). 209 */ 210 .globl PTmap, PTD 211 .set PTmap, (PDSLOT_PTE << PDSHIFT) 212 .set PTD, (PTmap + PDSLOT_PTE * NBPG) 213 214/* 215 * Initialization 216 */ 217 .data 218 219 .globl cpu_id, cpu_vendor 220 .globl cpu_brandstr 221 .globl cpuid_level 222 .globl cpu_miscinfo 223 .globl cpu_feature, cpu_ecxfeature 224 .globl ecpu_feature, ecpu_eaxfeature 225 .globl ecpu_ecxfeature 226 .globl cpu_cache_eax, cpu_cache_ebx 227 .globl cpu_cache_ecx, cpu_cache_edx 228 .globl cpu_perf_eax 229 .globl cpu_perf_ebx 230 .globl cpu_perf_edx 231 .globl cpu_apmi_edx 232 .globl cold, cnvmem, extmem 233 .globl cpu_pae 234 .globl esym 235 .globl ssym 236 .globl nkptp_max 237 .globl boothowto, bootdev, atdevbase 238 .globl proc0paddr, PTDpaddr, PTDsize 239 .globl gdt 240 .globl bootapiver, bootargc, bootargv 241 .globl lapic_tpr 242 .globl pg_g_kern 243 .globl cpu_meltdown 244 245#if NLAPIC > 0 246 .align NBPG 247 .globl local_apic, lapic_id 248local_apic: 249 .space LAPIC_ID 250lapic_id: 251 .long 0x00000000 252 .space LAPIC_TPRI-(LAPIC_ID+4) 253lapic_tpr: 254 .space LAPIC_PPRI-LAPIC_TPRI 255lapic_ppr: 256 .space LAPIC_ISR-LAPIC_PPRI 257lapic_isr: 258 .space NBPG-LAPIC_ISR 259#else 260lapic_tpr: 261 .long 0 262#endif 263 264cpu_id: .long 0 # saved from 'cpuid' instruction 265cpu_pae: .long 0 # are we using PAE paging mode? 266cpu_miscinfo: .long 0 # misc info (apic/brand id) from 'cpuid' 267cpu_feature: .long 0 # feature flags from 'cpuid' instruction 268ecpu_feature: .long 0 # extended feature flags from 'cpuid' 269cpu_ecxfeature: .long 0 # ecx feature flags from 'cpuid' 270ecpu_eaxfeature: .long 0 # extended eax feature flags 271ecpu_ecxfeature: .long 0 # extended ecx feature flags 272cpuid_level: .long -1 # max. lvl accepted by 'cpuid' insn 273cpu_cache_eax: .long 0 274cpu_cache_ebx: .long 0 275cpu_cache_ecx: .long 0 276cpu_cache_edx: .long 0 277cpu_perf_eax: .long 0 # arch. perf. mon. flags from 'cpuid' 278cpu_perf_ebx: .long 0 # arch. perf. mon. flags from 'cpuid' 279cpu_perf_edx: .long 0 # arch. perf. mon. flags from 'cpuid' 280cpu_apmi_edx: .long 0 # adv. power management info. 'cpuid' 281cpu_vendor: .space 16 # vendor string returned by 'cpuid' instruction 282cpu_brandstr: .space 48 # brand string returned by 'cpuid' 283cold: .long 1 # cold till we are not 284ssym: .long 0 # ptr to start of syms 285esym: .long 0 # ptr to end of syms 286cnvmem: .long 0 # conventional memory size 287extmem: .long 0 # extended memory size 288atdevbase: .long 0 # location of start of iomem in virtual 289bootapiver: .long 0 # /boot API version 290bootargc: .long 0 # /boot argc 291bootargv: .long 0 # /boot argv 292bootdev: .long 0 # device we booted from 293proc0paddr: .long 0 294PTDpaddr: .long 0 # paddr of PTD, for libkvm 295PTDsize: .long NBPG # size of PTD, for libkvm 296pg_g_kern: .long 0 # 0x100 if global pages should be used 297 # in kernel mappings, 0 otherwise (for 298 # insecure CPUs) 299cpu_meltdown: .long 0 # 1 if this CPU has Meltdown 300 301 .text 302 303NENTRY(proc_trampoline) 304 call proc_trampoline_mi 305 pushl %ebx 306 call *%esi 307 addl $4,%esp 308#ifdef DIAGNOSTIC 309 movl $0xfe,%esi 310#endif 311 jmp .Lsyscall_check_asts 312 313 /* This must come before any use of the CODEPATCH macros */ 314 .section .codepatch,"a" 315 .align 8 316 .globl codepatch_begin 317codepatch_begin: 318 .previous 319 320 .section .codepatchend,"a" 321 .globl codepatch_end 322codepatch_end: 323 .previous 324 325/*****************************************************************************/ 326 327/* 328 * Signal trampoline; copied to top of user stack. 329 */ 330 .section .rodata 331 .globl sigcode 332sigcode: 333 call *SIGF_HANDLER(%esp) 334 leal SIGF_SC(%esp),%eax # scp (the call may have clobbered the 335 # copy at SIGF_SCP(%esp)) 336 pushl %eax 337 pushl %eax # junk to fake return address 338 movl $SYS_sigreturn,%eax 339 .globl sigcodecall 340sigcodecall: 341 int $0x80 # enter kernel with args on stack 342 .globl sigcoderet 343sigcoderet: 344 .globl esigcode 345esigcode: 346 /* FALLTHROUGH */ 347 .globl sigfill 348sigfill: 349 int3 350esigfill: 351 352 .data 353 .globl sigfillsiz 354sigfillsiz: 355 .long esigfill - sigfill 356 357 .text 358 359/*****************************************************************************/ 360 361/* 362 * The following primitives are used to fill and copy regions of memory. 363 */ 364 365/* Frame pointer reserve on stack. */ 366#ifdef DDB 367#define FPADD 4 368#else 369#define FPADD 0 370#endif 371 372/* 373 * kcopy(caddr_t from, caddr_t to, size_t len); 374 * Copy len bytes, abort on fault. 375 */ 376ENTRY(kcopy) 377#ifdef DDB 378 pushl %ebp 379 movl %esp,%ebp 380#endif 381 pushl %esi 382 pushl %edi 383 GET_CURPCB(%eax) # load curpcb into eax and set on-fault 384 pushl PCB_ONFAULT(%eax) 385 movl $copy_fault, PCB_ONFAULT(%eax) 386 387 movl 16+FPADD(%esp),%esi 388 movl 20+FPADD(%esp),%edi 389 movl 24+FPADD(%esp),%ecx 390 movl %edi,%eax 391 subl %esi,%eax 392 cmpl %ecx,%eax # overlapping? 393 jb 1f 394 shrl $2,%ecx # nope, copy forward by 32-bit words 395 rep 396 movsl 397 movl 24+FPADD(%esp),%ecx 398 andl $3,%ecx # any bytes left? 399 rep 400 movsb 401 402 GET_CURPCB(%edx) # XXX save curpcb? 403 popl PCB_ONFAULT(%edx) 404 popl %edi 405 popl %esi 406 xorl %eax,%eax 407#ifdef DDB 408 leave 409#endif 410 ret 411 412 .align 4,0xcc 4131: addl %ecx,%edi # copy backward 414 addl %ecx,%esi 415 std 416 andl $3,%ecx # any fractional bytes? 417 decl %edi 418 decl %esi 419 rep 420 movsb 421 movl 24+FPADD(%esp),%ecx # copy remainder by 32-bit words 422 shrl $2,%ecx 423 subl $3,%esi 424 subl $3,%edi 425 rep 426 movsl 427 cld 428 429 GET_CURPCB(%edx) 430 popl PCB_ONFAULT(%edx) 431 popl %edi 432 popl %esi 433 xorl %eax,%eax 434#ifdef DDB 435 leave 436#endif 437 ret 438 439/*****************************************************************************/ 440 441/* 442 * The following primitives are used to copy data in and out of the user's 443 * address space. 444 */ 445 446/* 447 * copyout(caddr_t from, caddr_t to, size_t len); 448 * Copy len bytes into the user's address space. 449 */ 450ENTRY(copyout) 451#ifdef DDB 452 pushl %ebp 453 movl %esp,%ebp 454#endif 455 pushl %esi 456 pushl %edi 457 pushl $0 458 459 movl 16+FPADD(%esp),%esi 460 movl 20+FPADD(%esp),%edi 461 movl 24+FPADD(%esp),%eax 462 463 /* 464 * We check that the end of the destination buffer is not past the end 465 * of the user's address space. If it's not, then we only need to 466 * check that each page is writable. The 486 will do this for us; the 467 * 386 will not. (We assume that pages in user space that are not 468 * writable by the user are not writable by the kernel either.) 469 */ 470 movl %edi,%edx 471 addl %eax,%edx 472 jc copy_fault 473 cmpl $VM_MAXUSER_ADDRESS,%edx 474 ja copy_fault 475 476 GET_CURPCB(%edx) 477 movl $copy_fault,PCB_ONFAULT(%edx) 478 SMAP_STAC 479 480 /* bcopy(%esi, %edi, %eax); */ 481 movl %eax,%ecx 482 shrl $2,%ecx 483 rep 484 movsl 485 movl %eax,%ecx 486 andl $3,%ecx 487 rep 488 movsb 489 490 SMAP_CLAC 491 popl PCB_ONFAULT(%edx) 492 popl %edi 493 popl %esi 494 xorl %eax,%eax 495#ifdef DDB 496 leave 497#endif 498 ret 499 500/* 501 * _copyin(caddr_t from, caddr_t to, size_t len); 502 * Copy len bytes from the user's address space. 503 */ 504ENTRY(_copyin) 505#ifdef DDB 506 pushl %ebp 507 movl %esp,%ebp 508#endif 509 pushl %esi 510 pushl %edi 511 GET_CURPCB(%eax) 512 pushl $0 513 movl $copy_fault,PCB_ONFAULT(%eax) 514 SMAP_STAC 515 516 movl 16+FPADD(%esp),%esi 517 movl 20+FPADD(%esp),%edi 518 movl 24+FPADD(%esp),%eax 519 520 /* 521 * We check that the end of the destination buffer is not past the end 522 * of the user's address space. If it's not, then we only need to 523 * check that each page is readable, and the CPU will do that for us. 524 */ 525 movl %esi,%edx 526 addl %eax,%edx 527 jc copy_fault 528 cmpl $VM_MAXUSER_ADDRESS,%edx 529 ja copy_fault 530 531 /* bcopy(%esi, %edi, %eax); */ 532 movl %eax,%ecx 533 shrl $2,%ecx 534 rep 535 movsl 536 movb %al,%cl 537 andb $3,%cl 538 rep 539 movsb 540 541 SMAP_CLAC 542 GET_CURPCB(%edx) 543 popl PCB_ONFAULT(%edx) 544 popl %edi 545 popl %esi 546 xorl %eax,%eax 547#ifdef DDB 548 leave 549#endif 550 ret 551 552ENTRY(copy_fault) 553 cld 554 SMAP_CLAC 555 GET_CURPCB(%edx) 556 popl PCB_ONFAULT(%edx) 557 popl %edi 558 popl %esi 559 movl $EFAULT,%eax 560#ifdef DDB 561 leave 562#endif 563 ret 564 565/* 566 * copyoutstr(caddr_t from, caddr_t to, size_t maxlen, size_t *lencopied); 567 * Copy a NUL-terminated string, at most maxlen characters long, into the 568 * user's address space. Return the number of characters copied (including the 569 * NUL) in *lencopied. If the string is too long, return ENAMETOOLONG; else 570 * return 0 or EFAULT. 571 */ 572ENTRY(copyoutstr) 573#ifdef DDB 574 pushl %ebp 575 movl %esp,%ebp 576#endif 577 pushl %esi 578 pushl %edi 579 580 movl 12+FPADD(%esp),%esi # esi = from 581 movl 16+FPADD(%esp),%edi # edi = to 582 movl 20+FPADD(%esp),%edx # edx = maxlen 583 5845: GET_CURPCB(%eax) 585 movl $copystr_fault,PCB_ONFAULT(%eax) 586 SMAP_STAC 587 /* 588 * Get min(%edx, VM_MAXUSER_ADDRESS-%edi). 589 */ 590 movl $VM_MAXUSER_ADDRESS,%eax 591 subl %edi,%eax 592 jbe copystr_fault # die if CF == 1 || ZF == 1 593 # i.e. make sure that %edi 594 # is below VM_MAXUSER_ADDRESS 595 596 cmpl %edx,%eax 597 jae 1f 598 movl %eax,%edx 599 movl %eax,20+FPADD(%esp) 600 6011: incl %edx 602 6031: decl %edx 604 jz 2f 605 lodsb 606 stosb 607 testb %al,%al 608 jnz 1b 609 610 /* Success -- 0 byte reached. */ 611 decl %edx 612 xorl %eax,%eax 613 jmp copystr_return 614 6152: /* edx is zero -- return EFAULT or ENAMETOOLONG. */ 616 cmpl $VM_MAXUSER_ADDRESS,%edi 617 jae copystr_fault 618 movl $ENAMETOOLONG,%eax 619 jmp copystr_return 620 621/* 622 * _copyinstr(caddr_t from, caddr_t to, size_t maxlen, size_t *lencopied); 623 * Copy a NUL-terminated string, at most maxlen characters long, from the 624 * user's address space. Return the number of characters copied (including the 625 * NUL) in *lencopied. If the string is too long, return ENAMETOOLONG; else 626 * return 0 or EFAULT. 627 */ 628ENTRY(_copyinstr) 629#ifdef DDB 630 pushl %ebp 631 movl %esp,%ebp 632#endif 633 pushl %esi 634 pushl %edi 635 GET_CURPCB(%ecx) 636 movl $copystr_fault,PCB_ONFAULT(%ecx) 637 SMAP_STAC 638 639 movl 12+FPADD(%esp),%esi # %esi = from 640 movl 16+FPADD(%esp),%edi # %edi = to 641 movl 20+FPADD(%esp),%edx # %edx = maxlen 642 643 /* 644 * Get min(%edx, VM_MAXUSER_ADDRESS-%esi). 645 */ 646 movl $VM_MAXUSER_ADDRESS,%eax 647 subl %esi,%eax 648 jbe copystr_fault # Error if CF == 1 || ZF == 1 649 # i.e. make sure that %esi 650 # is below VM_MAXUSER_ADDRESS 651 cmpl %edx,%eax 652 jae 1f 653 movl %eax,%edx 654 movl %eax,20+FPADD(%esp) 655 6561: incl %edx 657 6581: decl %edx 659 jz 2f 660 lodsb 661 stosb 662 testb %al,%al 663 jnz 1b 664 665 /* Success -- 0 byte reached. */ 666 decl %edx 667 xorl %eax,%eax 668 jmp copystr_return 669 6702: /* edx is zero -- return EFAULT or ENAMETOOLONG. */ 671 cmpl $VM_MAXUSER_ADDRESS,%esi 672 jae copystr_fault 673 movl $ENAMETOOLONG,%eax 674 jmp copystr_return 675 676ENTRY(copystr_fault) 677 movl $EFAULT,%eax 678 679copystr_return: 680 SMAP_CLAC 681 /* Set *lencopied and return %eax. */ 682 GET_CURPCB(%ecx) 683 movl $0,PCB_ONFAULT(%ecx) 684 movl 20+FPADD(%esp),%ecx 685 subl %edx,%ecx 686 movl 24+FPADD(%esp),%edx 687 testl %edx,%edx 688 jz 8f 689 movl %ecx,(%edx) 690 6918: popl %edi 692 popl %esi 693#ifdef DDB 694 leave 695#endif 696 ret 697 698/*****************************************************************************/ 699 700/* 701 * The following is i386-specific nonsense. 702 */ 703 704/* 705 * void lgdt(struct region_descriptor *rdp); 706 * Change the global descriptor table. 707 */ 708NENTRY(lgdt) 709 /* Reload the descriptor table. */ 710 movl 4(%esp),%eax 711 lgdt (%eax) 712 /* Flush the prefetch q. */ 713 jmp 1f 714 nop 7151: /* Reload "stale" selectors. */ 716 movl $GSEL(GDATA_SEL, SEL_KPL),%eax 717 movw %ax,%ds 718 movw %ax,%es 719 movw %ax,%ss 720 movl $GSEL(GCPU_SEL, SEL_KPL),%eax 721 movw %ax,%fs 722 /* Reload code selector by doing intersegment return. */ 723 popl %eax 724 pushl $GSEL(GCODE_SEL, SEL_KPL) 725 pushl %eax 726 lret 727 728#ifdef DDB 729ENTRY(setjmp) 730 movl 4(%esp),%eax 731 movl %ebx,(%eax) # save ebx 732 movl %esp,4(%eax) # save esp 733 movl %ebp,8(%eax) # save ebp 734 movl %esi,12(%eax) # save esi 735 movl %edi,16(%eax) # save edi 736 movl (%esp),%edx # get rta 737 movl %edx,20(%eax) # save eip 738 xorl %eax,%eax # return (0); 739 ret 740 741ENTRY(longjmp) 742 movl 4(%esp),%eax 743 movl (%eax),%ebx # restore ebx 744 movl 4(%eax),%esp # restore esp 745 movl 8(%eax),%ebp # restore ebp 746 movl 12(%eax),%esi # restore esi 747 movl 16(%eax),%edi # restore edi 748 movl 20(%eax),%edx # get rta 749 movl %edx,(%esp) # put in return frame 750 xorl %eax,%eax # return (1); 751 incl %eax 752 ret 753#endif /* DDB */ 754 755/*****************************************************************************/ 756 757/* 758 * cpu_switchto(struct proc *old, struct proc *new) 759 * Switch from the "old" proc to the "new" proc. If "old" is NULL, we 760 * don't need to bother saving old context. 761 */ 762ENTRY(cpu_switchto) 763 pushl %ebx 764 pushl %esi 765 pushl %edi 766 767 movl 16(%esp), %esi 768 movl 20(%esp), %edi 769 770 /* If old process exited, don't bother. */ 771 testl %esi,%esi 772 jz switch_exited 773 774 /* Save old stack pointers. */ 775 movl P_ADDR(%esi),%ebx 776 movl %esp,PCB_ESP(%ebx) 777 movl %ebp,PCB_EBP(%ebx) 778 779switch_exited: 780 /* Restore saved context. */ 781 782 /* No interrupts while loading new state. */ 783 cli 784 785 /* Record new process. */ 786 movl %edi, CPUVAR(CURPROC) 787 movb $SONPROC, P_STAT(%edi) 788 789 /* Restore stack pointers. */ 790 movl P_ADDR(%edi),%ebx 791 movl PCB_ESP(%ebx),%esp 792 movl PCB_EBP(%ebx),%ebp 793 794 /* Record new pcb. */ 795 movl %ebx, CPUVAR(CURPCB) 796 797 /* record the bits needed for future U-->K transition */ 798 movl PCB_KSTACK(%ebx),%eax 799 subl $FRAMESIZE,%eax 800 movl %eax,CPUVAR(KERN_ESP) 801 802 /* 803 * Activate the address space. The pcb copy of %cr3 will 804 * be refreshed from the pmap, and because we're 805 * curproc they'll both be reloaded into the CPU. 806 */ 807 pushl %edi 808 pushl %esi 809 call pmap_switch 810 addl $8,%esp 811 812 /* Restore cr0 (including FPU state). */ 813 movl PCB_CR0(%ebx),%ecx 814#ifdef MULTIPROCESSOR 815 /* 816 * If our floating point registers are on a different CPU, 817 * clear CR0_TS so we'll trap rather than reuse bogus state. 818 */ 819 movl CPUVAR(SELF), %esi 820 cmpl PCB_FPCPU(%ebx), %esi 821 jz 1f 822 orl $CR0_TS,%ecx 8231: 824#endif 825 movl %ecx,%cr0 826 827 /* Interrupts are okay again. */ 828 sti 829 830 popl %edi 831 popl %esi 832 popl %ebx 833 ret 834 835ENTRY(cpu_idle_enter) 836 movl cpu_idle_enter_fcn,%eax 837 cmpl $0,%eax 838 je 1f 839 jmpl *%eax 8401: 841 ret 842 843ENTRY(cpu_idle_cycle) 844 movl cpu_idle_cycle_fcn,%eax 845 cmpl $0,%eax 846 je 1f 847 call *%eax 848 ret 8491: 850 sti 851 hlt 852 ret 853 854ENTRY(cpu_idle_leave) 855 movl cpu_idle_leave_fcn,%eax 856 cmpl $0,%eax 857 je 1f 858 jmpl *%eax 8591: 860 ret 861 862/* 863 * savectx(struct pcb *pcb); 864 * Update pcb, saving current processor state. 865 */ 866ENTRY(savectx) 867 movl 4(%esp),%edx # edx = p->p_addr 868 869 /* Save stack pointers. */ 870 movl %esp,PCB_ESP(%edx) 871 movl %ebp,PCB_EBP(%edx) 872 873 movl PCB_FLAGS(%edx),%ecx 874 orl $PCB_SAVECTX,%ecx 875 movl %ecx,PCB_FLAGS(%edx) 876 877 ret 878 879/*****************************************************************************/ 880 881/* 882 * Trap and fault vector routines 883 * 884 * On exit from the kernel to user mode, we always need to check for ASTs. In 885 * addition, we need to do this atomically; otherwise an interrupt may occur 886 * which causes an AST, but it won't get processed until the next kernel entry 887 * (possibly the next clock tick). Thus, we disable interrupt before checking, 888 * and only enable them again on the final `iret' or before calling the AST 889 * handler. 890 */ 891 892#define TRAP(a) pushl $(a) ; jmp alltraps 893#define ZTRAP(a) pushl $0 ; TRAP(a) 894 895IDTVEC(div) 896 ZTRAP(T_DIVIDE) 897IDTVEC(dbg) 898 subl $4,%esp 899 pushl %eax 900 movl %dr6,%eax 901 movl %eax,4(%esp) 902 andb $~0xf,%al 903 movl %eax,%dr6 904 popl %eax 905 TRAP(T_TRCTRAP) 906 907IDTVEC(nmi) 908 /* 909 * we came through a task gate; now U+K of the idle thread is 910 * enabled; NMIs are blocked until next iret; IRQs are disabled; 911 * all segment descriptors are useable 912 * 913 * first of all, switch back to the U+K we were actually running 914 * on before 915 */ 916 movl CPUVAR(CURPMAP),%eax 917 movl PM_PDIRPA(%eax),%eax 918 movl %eax,%cr3 919 920 /* 921 * when we came from within the kernel, iret will not 922 * switch back to the stack we came from but will keep 923 * running on the NMI stack. in that case we switch 924 * manually back to the stack we were running on and 925 * build the iretframe there. 926 */ 927 928 /* was there a ring transition? */ 929 movl CPUVAR(TSS),%eax 930 testb $SEL_RPL,TSS_CS(%eax) 931 jne 1f 932 933 /* 934 * no ring transition, switch back to original stack, build 935 * frame from state saved in TSS. 936 */ 937 movl TSS_ESP(%eax),%esp 938 subl $12,%esp 939 movl TSS_EFLAGS(%eax),%ebx 940 movl %ebx,8(%esp) 941 movl TSS_CS(%eax),%ebx 942 movl %ebx,4(%esp) 943 movl TSS_EIP(%eax),%ebx 944 movl %ebx,0(%esp) 945 pushl $0 946 pushl $T_NMI 947 jmp 2f 948 949 /* 950 * ring transition, stay on stack, build frame from state 951 * saved in TSS. 952 */ 9531: subl $20,%esp 954 pushl $0 955 pushl $T_NMI 956 movl TSS_SS(%eax),%ebx 957 movl %ebx,IRF_SS(%esp) 958 movl TSS_ESP(%eax),%ebx 959 movl %ebx,IRF_ESP(%esp) 960 movl TSS_EFLAGS(%eax),%ebx 961 movl %ebx,IRF_EFLAGS(%esp) 962 movl TSS_CS(%eax),%ebx 963 movl %ebx,IRF_CS(%esp) 964 movl TSS_EIP(%eax),%ebx 965 movl %ebx,IRF_EIP(%esp) 966 967 /* clear PSL_NT */ 9682: pushfl 969 popl %eax 970 andl $~PSL_NT,%eax 971 pushl %eax 972 popfl 973 974 /* clear CR0_TS XXX hshoexer: needed? */ 975 movl %cr0,%eax 976 andl $~CR0_TS,%eax 977 movl %eax,%cr0 978 979 /* unbusy descriptors and reload common TSS */ 980 movl CPUVAR(GDT),%eax 981 movl $GSEL(GNMITSS_SEL, SEL_KPL),%ebx 982 andl $~0x200,4-SEL_KPL(%eax,%ebx,1) 983 movl $GSEL(GTSS_SEL, SEL_KPL),%ebx 984 andl $~0x200,4-SEL_KPL(%eax,%ebx,1) 985 ltr %bx 986 987 /* load GPRs and segment registers with saved values from common TSS */ 988 movl CPUVAR(TSS),%eax 989 movl TSS_ECX(%eax),%ecx 990 movl TSS_EDX(%eax),%edx 991 movl TSS_ESI(%eax),%esi 992 movl TSS_EDI(%eax),%edi 993 movl TSS_EBP(%eax),%ebp 994 movw TSS_FS(%eax),%fs 995 movw TSS_GS(%eax),%gs 996 movw TSS_ES(%eax),%es 997 /* saved %ds might be invalid, thus push now and pop later */ 998 movl TSS_DS(%eax),%ebx 999 pushl %ebx 1000 movl TSS_EBX(%eax),%ebx 1001 movl TSS_EAX(%eax),%eax 1002 popl %ds 1003 1004 /* 1005 * we can now proceed and save everything on the stack as 1006 * if no task switch had happened. 1007 */ 1008 jmp alltraps 1009IDTVEC(bpt) 1010 ZTRAP(T_BPTFLT) 1011IDTVEC(ofl) 1012 ZTRAP(T_OFLOW) 1013IDTVEC(bnd) 1014 ZTRAP(T_BOUND) 1015IDTVEC(ill) 1016 ZTRAP(T_PRIVINFLT) 1017IDTVEC(dna) 1018#if NNPX > 0 1019 pushl $0 # dummy error code 1020 pushl $T_DNA 1021 INTRENTRY(dna) 1022 sti 1023 pushl CPUVAR(SELF) 1024 call *npxdna_func 1025 addl $4,%esp 1026 testl %eax,%eax 1027 jz calltrap 1028#ifdef DIAGNOSTIC 1029 movl $0xfd,%esi 1030#endif 1031 cli 1032 INTRFASTEXIT 1033#else 1034 ZTRAP(T_DNA) 1035#endif 1036IDTVEC(dble) 1037 TRAP(T_DOUBLEFLT) 1038IDTVEC(fpusegm) 1039 ZTRAP(T_FPOPFLT) 1040IDTVEC(tss) 1041 TRAP(T_TSSFLT) 1042IDTVEC(missing) 1043 TRAP(T_SEGNPFLT) 1044IDTVEC(stk) 1045 TRAP(T_STKFLT) 1046 1047IDTVEC(prot) 1048 pushl $T_PROTFLT 1049 /* If iret faults, we'll get a trap at doreti_iret+3 with CPL == 0. */ 1050 pushl %eax 1051 leal doreti_iret+3,%eax 1052 cmpl %eax,12(%esp) /* over %eax, trapno and err to %eip */ 1053 popl %eax 1054 jne 97f 1055 pushl %ebp 1056 pushl %eax 1057 pushl %fs 1058 INTR_ENABLE_U_PLUS_K 1059 /* 1060 * we have an iretframe on trampoline stack, above it the 1061 * remainder of the original iretframe iret faulted on. 1062 */ 1063 movl CPUVAR(KERN_ESP),%eax 1064 pushl %eax 1065 pushl $0xdeadbeef 1066 /* 1067 * now we have a trampframe on trampoline stack, above it the 1068 * remainder of the original iretframe iret faulted on. 1069 */ 1070 movl %esp,%ebp 1071 movl %eax,%esp 1072 subl $SIZEOF_IRETFRAME+(5*4),%esp 1073 /* copy to iretframe on kernel stack */ 1074 movl TRF_EFLAGS(%ebp),%eax 1075 movl %eax,IRF_EFLAGS(%esp) 1076 movl TRF_CS(%ebp),%eax 1077 movl %eax,IRF_CS(%esp) 1078 movl TRF_EIP(%ebp),%eax 1079 movl %eax,IRF_EIP(%esp) 1080 movl TRF_ERR(%ebp),%eax 1081 movl %eax,IRF_ERR(%esp) 1082 movl TRF_TRAPNO(%ebp),%eax 1083 movl %eax,IRF_TRAPNO(%esp) 1084 /* copy remainder of faulted iretframe */ 1085 movl 40(%ebp),%eax /* eip */ 1086 movl %eax,20(%esp) 1087 movl 44(%ebp),%eax /* cs */ 1088 movl %eax,24(%esp) 1089 movl 48(%ebp),%eax /* eflags */ 1090 movl %eax,28(%esp) 1091 movl 52(%ebp),%eax /* esp */ 1092 movl %eax,32(%esp) 1093 movl 56(%ebp),%eax /* ss */ 1094 movl %eax,36(%esp) 1095 movl TRF_FS(%ebp),%eax 1096 movw %ax,%fs 1097 movl TRF_EAX(%ebp),%eax 1098 movl TRF_EBP(%ebp),%ebp 1099 /* 1100 * we have an iretframe on kernel stack, above it the 1101 * remainder of the original iretframe iret faulted on. 1102 * for INTRENTRY(prot) it looks like the fault happened 1103 * on the kernel stack 1104 */ 110597: INTRENTRY(prot) 1106 sti 1107 jmp calltrap 1108IDTVEC(f00f_redirect) 1109 pushl $T_PAGEFLT 1110 INTRENTRY(f00f_redirect) 1111 sti 1112 testb $PGEX_U,TF_ERR(%esp) 1113 jnz calltrap 1114 movl %cr2,%eax 1115 subl idt,%eax 1116 cmpl $(6*8),%eax 1117 jne calltrap 1118 movb $T_PRIVINFLT,TF_TRAPNO(%esp) 1119 jmp calltrap 1120IDTVEC(page) 1121 TRAP(T_PAGEFLT) 1122IDTVEC(rsvd) 1123 ZTRAP(T_RESERVED) 1124IDTVEC(mchk) 1125 ZTRAP(T_MACHK) 1126IDTVEC(simd) 1127 ZTRAP(T_XFTRAP) 1128IDTVEC(intrspurious) 1129 /* 1130 * The Pentium Pro local APIC may erroneously call this vector for a 1131 * default IR7. Just ignore it. 1132 * 1133 * (The local APIC does this when CPL is raised while it's on the 1134 * way to delivering an interrupt.. presumably enough has been set 1135 * up that it's inconvenient to abort delivery completely..) 1136 */ 1137 iret 1138IDTVEC(fpu) 1139#if NNPX > 0 1140 /* 1141 * Handle like an interrupt so that we can call npxintr to clear the 1142 * error. It would be better to handle npx interrupts as traps but 1143 * this is difficult for nested interrupts. 1144 */ 1145 subl $8,%esp /* space for tf_{err,trapno} */ 1146 INTRENTRY(fpu) 1147 sti 1148 pushl CPL # if_ppl in intrframe 1149 pushl %esp # push address of intrframe 1150 incl uvmexp+V_TRAP 1151 call npxintr 1152 addl $8,%esp # pop address and if_ppl 1153#ifdef DIAGNOSTIC 1154 movl $0xfc,%esi 1155#endif 1156 cli 1157 INTRFASTEXIT 1158#else 1159 ZTRAP(T_ARITHTRAP) 1160#endif 1161IDTVEC(align) 1162 TRAP(T_ALIGNFLT) 1163 /* 18 - 31 reserved for future exp */ 1164 1165/* 1166 * If an error is detected during trap, syscall, or interrupt exit, trap() will 1167 * change %eip to point to one of these labels. We clean up the stack, if 1168 * necessary, and resume as if we were handling a general protection fault. 1169 * This will cause the process to get a SIGBUS. 1170 */ 1171KUENTRY(resume_iret) 1172 ZTRAP(T_PROTFLT) 1173NENTRY(resume_pop_ds) 1174 pushl %es 1175 movl $GSEL(GDATA_SEL, SEL_KPL),%eax 1176 movw %ax,%es 1177NENTRY(resume_pop_es) 1178 pushl %gs 1179 xorl %eax,%eax /* $GSEL(GNULL_SEL, SEL_KPL) == 0 */ 1180 movw %ax,%gs 1181NENTRY(resume_pop_gs) 1182 pushl %fs 1183 movl $GSEL(GCPU_SEL, SEL_KPL),%eax 1184 movw %ax,%fs 1185NENTRY(resume_pop_fs) 1186 movl $T_PROTFLT,TF_TRAPNO(%esp) 1187 sti 1188 jmp calltrap 1189 1190/* 1191 * All traps go through here. Call the generic trap handler, and 1192 * check for ASTs afterwards. 1193 */ 1194KUENTRY(alltraps) 1195 INTRENTRY(alltraps) 1196 sti 1197calltrap: 1198#ifdef DIAGNOSTIC 1199 movl CPL,%ebx 1200#endif /* DIAGNOSTIC */ 1201#if !defined(GPROF) && defined(DDBPROF) 1202 cmpl $T_BPTFLT,TF_TRAPNO(%esp) 1203 jne .Lreal_trap 1204 1205 pushl %esp 1206 subl $4, %esp 1207 pushl %eax 1208 leal dt_prov_kprobe, %eax 1209 movl %eax, 4(%esp) 1210 popl %eax 1211 call dt_prov_kprobe_hook 1212 addl $8, %esp 1213 cmpl $0, %eax 1214 je .Lreal_trap 1215 1216 /* 1217 * Abuse the error field to indicate that INTRFASTEXIT needs 1218 * to emulate the patched instruction. 1219 */ 1220 cmpl $1, %eax 1221 je .Lset_emulate_push_rbp 1222 1223 cmpl $2, %eax 1224 je .Lset_emulate_ret 1225 1226.Lset_emulate_push_rbp: 1227 movl $INTR_FAKE_TRAP_PUSH_RPB, TF_ERR(%esp) 1228 jmp .Lalltraps_check_asts 1229.Lset_emulate_ret: 1230 movl $INTR_FAKE_TRAP_POP_RBP, TF_ERR(%esp) 1231 jmp .Lalltraps_check_asts 1232.Lreal_trap: 1233#endif /* !defined(GPROF) && defined(DDBPROF) */ 1234 pushl %esp 1235 call trap 1236 addl $4,%esp 1237 1238.Lalltraps_check_asts: 1239 /* Check for ASTs on exit to user mode. */ 1240 cli 1241 CHECK_ASTPENDING(%ecx) 1242 je 1f 1243 testb $SEL_RPL,TF_CS(%esp) 1244 jz 1f 12455: CLEAR_ASTPENDING(%ecx) 1246 sti 1247 pushl %esp 1248 call ast 1249 addl $4,%esp 1250 jmp .Lalltraps_check_asts 12511: 1252#if !defined(GPROF) && defined(DDBPROF) 1253 /* 1254 * If we are returning from a probe trap we need to fix the 1255 * stack layout and emulate the patched instruction. 1256 * 1257 * The code below does that by trashing %eax, so it MUST be 1258 * restored afterward. 1259 */ 1260 cmpl $INTR_FAKE_TRAP_PUSH_RPB, TF_ERR(%esp) 1261 je .Lprobe_fixup_push_rbp 1262 cmpl $INTR_FAKE_TRAP_POP_RBP, TF_ERR(%esp) 1263 je .Lprobe_fixup_pop_rbp 1264#endif /* !defined(GPROF) && defined(DDBPROF) */ 1265#ifndef DIAGNOSTIC 1266 INTRFASTEXIT 1267#else 1268 cmpl CPL,%ebx 1269 jne 3f 1270#ifdef DIAGNOSTIC 1271 movl $0xfb,%esi 1272#endif 1273 INTRFASTEXIT 12743: sti 1275 pushl $spl_lowered 1276 call printf 1277 addl $4,%esp 1278#if defined(DDB) && 0 1279 int $3 1280#endif /* DDB */ 1281 movl %ebx,CPL 1282 jmp .Lalltraps_check_asts 1283 1284 .section .rodata 1285spl_lowered: 1286 .asciz "WARNING: SPL NOT LOWERED ON TRAP EXIT\n" 1287#endif /* DIAGNOSTIC */ 1288 1289 .text 1290#if !defined(GPROF) && defined(DDBPROF) 1291.Lprobe_fixup_push_rbp: 1292 /* Restore all register unwinding the stack. */ 1293 INTR_RESTORE_ALL 1294 1295 /* 1296 * Use the space left by ``err'' and ``trapno'' to emulate 1297 * "pushl %ebp". 1298 * 1299 * Temporarily save %eax. 1300 */ 1301 movl %eax,0(%esp) 1302 1303 /* Shift hardware-saved registers: eip, cs, eflags */ 1304 movl 8(%esp),%eax 1305 movl %eax,4(%esp) 1306 movl 12(%esp),%eax 1307 movl %eax,8(%esp) 1308 movl 16(%esp),%eax 1309 movl %eax,12(%esp) 1310 1311 /* Store %ebp in the expected location to finish the emulation. */ 1312 movl %ebp,16(%esp) 1313 1314 popl %eax 1315 iret 1316.Lprobe_fixup_pop_rbp: 1317 /* Restore all register unwinding the stack. */ 1318 INTR_RESTORE_ALL 1319 1320 movl %eax, 0(%esp) 1321 1322 /* pop %ebp */ 1323 movl 20(%esp), %ebp 1324 /* Shift hardware-saved registers: eflags, cs, eip */ 1325 movl 16(%esp), %eax 1326 movl %eax, 20(%esp) 1327 movl 12(%esp), %eax 1328 movl %eax, 16(%esp) 1329 movl 8(%esp), %eax 1330 movl %eax, 12(%esp) 1331 1332 /* Pop eax and restore the stack pointer */ 1333 popl %eax 1334 addl $8, %esp 1335 iret 1336#endif /* !defined(GPROF) && defined(DDBPROF) */ 1337 1338 .text 1339#ifdef DIAGNOSTIC 1340.Lintr_exit_not_blocked: 1341 movl warn_once,%eax 1342 testl %eax,%eax 1343 jnz 1f 1344 incl %eax 1345 movl %eax,warn_once 1346 pushl %esi /* marker indicating where we came from */ 1347 pushl %edx /* EFLAGS are in %edx */ 1348 pushl $.Lnot_blocked 1349 call printf 1350 addl $12,%esp 1351#ifdef DDB 1352 int $3 1353#endif /* DDB */ 13541: cli 1355 jmp intr_fast_exit 1356 1357 .data 1358 .global warn_once 1359warn_once: 1360 .long 0 1361 .section .rodata 1362.Lnot_blocked: 1363 .asciz "WARNING: INTERRUPTS NOT BLOCKED ON INTERRUPT RETURN 0x%x 0x%x\n" 1364 .text 1365#endif 1366 1367/* 1368 * Trap gate entry for syscall 1369 */ 1370IDTVEC(syscall) 1371 subl $8,%esp /* space for tf_{err,trapno} */ 1372 INTRENTRY(syscall) 1373 sti 1374 pushl %esp 1375 call syscall 1376 addl $4,%esp 1377 1378.Lsyscall_check_asts: 1379 /* Check for ASTs on exit to user mode. */ 1380 cli 1381 CHECK_ASTPENDING(%ecx) 1382 je 1f 1383 /* Always returning to user mode here. */ 1384 CLEAR_ASTPENDING(%ecx) 1385 sti 1386 pushl %esp 1387 call ast 1388 addl $4,%esp 1389 jmp .Lsyscall_check_asts 13901: 1391#ifdef DIAGNOSTIC 1392 movl $0xff,%esi 1393#endif 1394 jmp intr_fast_exit 1395 1396NENTRY(intr_fast_exit) 1397#ifdef DIAGNOSTIC 1398 pushfl 1399 popl %edx 1400 testl $PSL_I,%edx 1401 jnz .Lintr_exit_not_blocked 1402#endif 1403 /* we have a full trapframe */ 1404 INTR_RESTORE_ALL 1405 /* now we have an iretframe */ 1406 testb $SEL_RPL,IRF_CS(%esp) 1407 /* recursing into kernel: stay on kernel stack using iretframe */ 1408 je doreti_iret 1409 1410 /* leaving kernel: build trampframe on cpu stack */ 1411 pushl %ebp 1412 pushl %eax 1413 pushl %fs 1414 movl $GSEL(GCPU_SEL, SEL_KPL),%eax 1415 movw %ax,%fs 1416 movl CPUVAR(INTR_ESP),%eax 1417 pushl %eax 1418 pushl $0xcafecafe 1419 /* now we have an trampframe, copy frame to cpu stack */ 1420 movl %eax,%ebp 1421 movl TRF_EIP(%esp),%eax 1422 movl %eax,TRF_EIP(%ebp) 1423 movl TRF_CS(%esp),%eax 1424 movl %eax,TRF_CS(%ebp) 1425 movl TRF_EFLAGS(%esp),%eax 1426 movl %eax,TRF_EFLAGS(%ebp) 1427 movl TRF_ESP(%esp),%eax 1428 movl %eax,TRF_ESP(%ebp) 1429 movl TRF_SS(%esp),%eax 1430 movl %eax,TRF_SS(%ebp) 1431 movl TRF__DEADBEEF(%esp),%eax 1432 movl %eax,TRF__DEADBEEF(%ebp) 1433 movl TRF__KERN_ESP(%esp),%eax 1434 movl %eax,TRF__KERN_ESP(%ebp) 1435 movl TRF_FS(%esp),%eax 1436 movl %eax,TRF_FS(%ebp) 1437 movl TRF_EAX(%esp),%eax 1438 movl %eax,TRF_EAX(%ebp) 1439 movl TRF_EBP(%esp),%eax 1440 movl %eax,TRF_EBP(%ebp) 1441 /* switch to cpu stack, where we copied the trampframe */ 1442 movl %ebp,%esp 1443 movl CPUVAR(USER_CR3),%eax 1444 testl %eax,%eax 1445 jz 1f 1446 jmp iret_tramp 1447 1448KUENTRY(iret_tramp) 1449 movl %eax,%cr3 1450 /* we have a trampframe; restore registers and adjust to iretframe */ 14511: popl %eax 1452 popl %eax 1453 popl %fs 1454 popl %eax 1455 popl %ebp 1456 .globl doreti_iret 1457doreti_iret: 1458 /* we have an iretframe */ 1459 addl $IRF_EIP,%esp 1460 iret 1461 1462#include <i386/i386/vector.s> 1463#include <i386/isa/icu.s> 1464 1465#if !defined(SMALL_KERNEL) 1466ENTRY(sse2_pagezero) 1467 pushl %ebx 1468 movl 8(%esp),%ecx 1469 movl %ecx,%eax 1470 addl $4096,%eax 1471 xor %ebx,%ebx 14721: 1473 movnti %ebx,(%ecx) 1474 addl $4,%ecx 1475 cmpl %ecx,%eax 1476 jne 1b 1477 sfence 1478 popl %ebx 1479 ret 1480 1481ENTRY(i686_pagezero) 1482 pushl %edi 1483 pushl %ebx 1484 1485 movl 12(%esp), %edi 1486 movl $1024, %ecx 1487 1488 .align 4,0x90 14891: 1490 xorl %eax, %eax 1491 repe 1492 scasl 1493 jnz 2f 1494 1495 popl %ebx 1496 popl %edi 1497 ret 1498 1499 .align 4,0x90 15002: 1501 incl %ecx 1502 subl $4, %edi 1503 1504 movl %ecx, %edx 1505 cmpl $16, %ecx 1506 1507 jge 3f 1508 1509 movl %edi, %ebx 1510 andl $0x3f, %ebx 1511 shrl %ebx 1512 shrl %ebx 1513 movl $16, %ecx 1514 subl %ebx, %ecx 1515 15163: 1517 subl %ecx, %edx 1518 rep 1519 stosl 1520 1521 movl %edx, %ecx 1522 testl %edx, %edx 1523 jnz 1b 1524 1525 popl %ebx 1526 popl %edi 1527 ret 1528#endif 1529 1530/* 1531 * int cpu_paenable(void *); 1532 */ 1533ENTRY(cpu_paenable) 1534 movl $-1, %eax 1535 testl $CPUID_PAE, cpu_feature 1536 jz 1f 1537 1538 pushl %esi 1539 pushl %edi 1540 movl 12(%esp), %esi 1541 movl %cr3, %edi 1542 orl $0xfe0, %edi /* PDPT will be in the last four slots! */ 1543 movl %edi, %cr3 1544 addl $KERNBASE, %edi /* and make it back virtual again */ 1545 movl $8, %ecx 1546 rep 1547 movsl 1548 1549 movl $MSR_EFER, %ecx 1550 rdmsr 1551 orl $EFER_NXE, %eax 1552 wrmsr 1553 1554 movl %cr4, %eax 1555 orl $CR4_PAE, %eax 1556 movl %eax, %cr4 /* BANG!!! */ 1557 1558 movl 12(%esp), %eax 1559 subl $KERNBASE, %eax 1560 movl %eax, %cr3 /* reload real PDPT */ 1561 movl $4*NBPG, %eax 1562 movl %eax, PTDsize 1563 1564 xorl %eax, %eax 1565 popl %edi 1566 popl %esi 15671: 1568 ret 1569 1570#if NLAPIC > 0 1571#include <i386/i386/apicvec.s> 1572#endif 1573 1574 .section .rodata 1575 .globl _stac 1576_stac: 1577 stac 1578 1579 .globl _clac 1580_clac: 1581 clac 1582