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/* 23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25/* 26 * Copyright 2011 Joyent, Inc. All rights reserved. 27 * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. 28 */ 29 30/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ 31/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ 32/* All Rights Reserved */ 33 34/* Copyright (c) 1987, 1988 Microsoft Corporation */ 35/* All Rights Reserved */ 36 37 38#include <sys/asm_linkage.h> 39#include <sys/asm_misc.h> 40#include <sys/regset.h> 41#include <sys/privregs.h> 42#include <sys/psw.h> 43#include <sys/reboot.h> 44#include <sys/x86_archext.h> 45#include <sys/machparam.h> 46 47#if defined(__lint) 48 49#include <sys/types.h> 50#include <sys/thread.h> 51#include <sys/systm.h> 52#include <sys/lgrp.h> 53#include <sys/regset.h> 54#include <sys/link.h> 55#include <sys/bootconf.h> 56#include <sys/bootsvcs.h> 57 58#else /* __lint */ 59 60#include <sys/segments.h> 61#include <sys/pcb.h> 62#include <sys/trap.h> 63#include <sys/ftrace.h> 64#include <sys/traptrace.h> 65#include <sys/clock.h> 66#include <sys/cmn_err.h> 67#include <sys/pit.h> 68#include <sys/panic.h> 69 70#if defined(__xpv) 71#include <sys/hypervisor.h> 72#endif 73 74#include "assym.h" 75 76/* 77 * Our assumptions: 78 * - We are running in protected-paged mode. 79 * - Interrupts are disabled. 80 * - The GDT and IDT are the callers; we need our copies. 81 * - The kernel's text, initialized data and bss are mapped. 82 * 83 * Our actions: 84 * - Save arguments 85 * - Initialize our stack pointer to the thread 0 stack (t0stack) 86 * and leave room for a phony "struct regs". 87 * - Our GDT and IDT need to get munged. 88 * - Since we are using the boot's GDT descriptors, we need 89 * to copy them into our GDT before we switch to ours. 90 * - We start using our GDT by loading correct values in the 91 * selector registers (cs=KCS_SEL, ds=es=ss=KDS_SEL, fs=KFS_SEL, 92 * gs=KGS_SEL). 93 * - The default LDT entry for syscall is set. 94 * - We load the default LDT into the hardware LDT register. 95 * - We load the default TSS into the hardware task register. 96 * - Check for cpu type, i.e. 486 vs. P5 vs. P6 etc. 97 * - mlsetup(%esp) gets called. 98 * - We change our appearance to look like the real thread 0. 99 * (NOTE: making ourselves to be a real thread may be a noop) 100 * - main() gets called. (NOTE: main() never returns). 101 * 102 * NOW, the real code! 103 */ 104 /* 105 * The very first thing in the kernel's text segment must be a jump 106 * to the os/fakebop.c startup code. 107 */ 108 .text 109 jmp _start 110 111 /* 112 * Globals: 113 */ 114 .globl _locore_start 115 .globl mlsetup 116 .globl main 117 .globl panic 118 .globl t0stack 119 .globl t0 120 .globl sysp 121 .globl edata 122 123 /* 124 * call back into boot - sysp (bootsvcs.h) and bootops (bootconf.h) 125 */ 126 .globl bootops 127 .globl bootopsp 128 129 /* 130 * NOTE: t0stack should be the first thing in the data section so that 131 * if it ever overflows, it will fault on the last kernel text page. 132 */ 133 .data 134 .comm t0stack, DEFAULTSTKSZ, 32 135 .comm t0, 4094, 32 136 137#endif /* __lint */ 138 139 140#if defined(__amd64) 141 142#if defined(__lint) 143 144/* ARGSUSED */ 145void 146_locore_start(struct boot_syscalls *sysp, ulong_t rsi, struct bootops *bop) 147{} 148 149#else /* __lint */ 150 151 /* 152 * kobj_init() vectors us back to here with (note) a slightly different 153 * set of arguments than _start is given (see lint prototypes above). 154 * 155 * XXX Make this less vile, please. 156 */ 157 ENTRY_NP(_locore_start) 158 159 /* 160 * %rdi = boot services (should die someday) 161 * %rdx = bootops 162 * end 163 */ 164 165 leaq edata(%rip), %rbp /* reference edata for ksyms */ 166 movq $0, (%rbp) /* limit stack back trace */ 167 168 /* 169 * Initialize our stack pointer to the thread 0 stack (t0stack) 170 * and leave room for a "struct regs" for lwp0. Note that the 171 * stack doesn't actually align to a 16-byte boundary until just 172 * before we call mlsetup because we want to use %rsp to point at 173 * our regs structure. 174 */ 175 leaq t0stack(%rip), %rsp 176 addq $_CONST(DEFAULTSTKSZ - REGSIZE), %rsp 177#if (REGSIZE & 15) == 0 178 subq $8, %rsp 179#endif 180 /* 181 * Save call back for special x86 boot services vector 182 */ 183 movq %rdi, sysp(%rip) 184 185 movq %rdx, bootops(%rip) /* save bootops */ 186 movq $bootops, bootopsp(%rip) 187 188 /* 189 * Save arguments and flags, if only for debugging .. 190 */ 191 movq %rdi, REGOFF_RDI(%rsp) 192 movq %rsi, REGOFF_RSI(%rsp) 193 movq %rdx, REGOFF_RDX(%rsp) 194 movq %rcx, REGOFF_RCX(%rsp) 195 movq %r8, REGOFF_R8(%rsp) 196 movq %r9, REGOFF_R9(%rsp) 197 pushf 198 popq %r11 199 movq %r11, REGOFF_RFL(%rsp) 200 201#if !defined(__xpv) 202 /* 203 * Enable write protect and alignment check faults. 204 */ 205 movq %cr0, %rax 206 orq $_CONST(CR0_WP|CR0_AM), %rax 207 andq $_BITNOT(CR0_WT|CR0_CE), %rax 208 movq %rax, %cr0 209#endif /* __xpv */ 210 211 /* 212 * (We just assert this works by virtue of being here) 213 */ 214 btsl $X86FSET_CPUID, x86_featureset(%rip) 215 216 /* 217 * mlsetup() gets called with a struct regs as argument, while 218 * main takes no args and should never return. 219 */ 220 xorl %ebp, %ebp 221 movq %rsp, %rdi 222 pushq %rbp 223 /* (stack pointer now aligned on 16-byte boundary right here) */ 224 movq %rsp, %rbp 225 call mlsetup 226 call main 227 /* NOTREACHED */ 228 leaq __return_from_main(%rip), %rdi 229 xorl %eax, %eax 230 call panic 231 SET_SIZE(_locore_start) 232 233#endif /* __amd64 */ 234#endif /* __lint */ 235 236#if !defined(__lint) 237 238__return_from_main: 239 .string "main() returned" 240__unsupported_cpu: 241 .string "486 style cpu detected - no longer supported!" 242 243#endif /* !__lint */ 244 245#if !defined(__amd64) 246 247#if defined(__lint) 248 249/* ARGSUSED */ 250void 251_locore_start(struct boot_syscalls *sysp, struct bootops *bop) 252{} 253 254#else /* __lint */ 255 256 /* 257 * kobj_init() vectors us back to here with (note) a slightly different 258 * set of arguments than _start is given (see lint prototypes above). 259 * 260 * XXX Make this less vile, please. 261 */ 262 ENTRY_NP(_locore_start) 263 264 /* 265 * %ecx = boot services (should die someday) 266 * %ebx = bootops 267 */ 268 mov $edata, %ebp / edata needs to be defined for ksyms 269 movl $0, (%ebp) / limit stack back trace 270 271 /* 272 * Initialize our stack pointer to the thread 0 stack (t0stack) 273 * and leave room for a phony "struct regs". 274 */ 275 movl $t0stack + DEFAULTSTKSZ - REGSIZE, %esp 276 277 /* 278 * Save call back for special x86 boot services vector 279 */ 280 mov %ecx, sysp / save call back for boot services 281 282 mov %ebx, bootops / save bootops 283 movl $bootops, bootopsp 284 285 286 /* 287 * Save all registers and flags 288 */ 289 pushal 290 pushfl 291 292#if !defined(__xpv) 293 /* 294 * Override bios settings and enable write protect and 295 * alignment check faults. 296 */ 297 movl %cr0, %eax 298 299 /* 300 * enable WP for detecting faults, and enable alignment checking. 301 */ 302 orl $_CONST(CR0_WP|CR0_AM), %eax 303 andl $_BITNOT(CR0_WT|CR0_CE), %eax 304 movl %eax, %cr0 / set the cr0 register correctly and 305 / override the BIOS setup 306 307 /* 308 * If bit 21 of eflags can be flipped, then cpuid is present 309 * and enabled. 310 */ 311 pushfl 312 popl %ecx 313 movl %ecx, %eax 314 xorl $PS_ID, %eax / try complemented bit 315 pushl %eax 316 popfl 317 pushfl 318 popl %eax 319 cmpl %eax, %ecx 320 jne have_cpuid 321 322 /* 323 * cpuid may be disabled on Cyrix, try to detect Cyrix by the 5/2 test 324 * div does not modify the cc flags on Cyrix, even though this may 325 * also be true for other vendors, this is generally true only for 326 * newer models from those vendors that support and do not disable 327 * cpuid (usually because cpuid cannot be disabled) 328 */ 329 330 /* 331 * clear cc flags 332 */ 333 xorb %ah, %ah 334 sahf 335 336 /* 337 * perform 5/2 test 338 */ 339 movw $5, %ax 340 movb $2, %bl 341 divb %bl 342 343 lahf 344 cmpb $2, %ah 345 jne cpu_486 346 347 /* 348 * div did not modify the cc flags, chances are the vendor is Cyrix 349 * assume the vendor is Cyrix and use the CCR's to enable cpuid 350 */ 351 .set CYRIX_CRI, 0x22 / CR Index Register 352 .set CYRIX_CRD, 0x23 / CR Data Register 353 354 .set CYRIX_CCR3, 0xc3 / Config Control Reg 3 355 .set CYRIX_CCR4, 0xe8 / Config Control Reg 4 356 .set CYRIX_DIR0, 0xfe / Device Identification Reg 0 357 .set CYRIX_DIR1, 0xff / Device Identification Reg 1 358 359 /* 360 * even if the cpu vendor is Cyrix and the motherboard/chipset 361 * vendor decided to ignore lines A1-A4 for I/O addresses, I/O port 362 * 0x21 corresponds with 0x23 and since 0x22 is still untouched, 363 * the reads and writes of 0x21 are guaranteed to be off-chip of 364 * the cpu 365 */ 366 367 /* 368 * enable read of ISR at I/O port 0x20 369 */ 370 movb $0xb, %al 371 outb $MCMD_PORT 372 373 /* 374 * read IMR and store in %bl 375 */ 376 inb $MIMR_PORT 377 movb %al, %bl 378 379 /* 380 * mask out all interrupts so that ISR will not change 381 */ 382 movb $0xff, %al 383 outb $MIMR_PORT 384 385 /* 386 * reads of I/O port 0x22 on Cyrix are always directed off-chip 387 * make use of I/O pull-up to test for an unknown device on 0x22 388 */ 389 inb $CYRIX_CRI 390 cmpb $0xff, %al 391 je port_22_free 392 393 /* 394 * motherboard/chipset vendor may be ignoring line A1 of I/O address 395 */ 396 movb %al, %cl 397 398 /* 399 * if the ISR and the value read from 0x22 do not match then we have 400 * detected some unknown device, probably a chipset, at 0x22 401 */ 402 inb $MCMD_PORT 403 cmpb %al, %cl 404 jne restore_IMR 405 406port_22_free: 407 /* 408 * now test to see if some unknown device is using I/O port 0x23 409 * 410 * read the external I/O port at 0x23 411 */ 412 inb $CYRIX_CRD 413 414 /* 415 * Test for pull-up at 0x23 or if I/O address line A1 is being ignored. 416 * IMR is 0xff so both tests are performed simultaneously. 417 */ 418 cmpb $0xff, %al 419 jne restore_IMR 420 421 /* 422 * We are a Cyrix part. In case we are some model of Cx486 or a Cx586, 423 * record the type and fix it later if not. 424 */ 425 movl $X86_VENDOR_Cyrix, x86_vendor 426 movl $X86_TYPE_CYRIX_486, x86_type 427 428 /* 429 * Try to read CCR3. All Cyrix cpu's which support cpuid have CCR3. 430 * 431 * load CCR3 index into CCR index register 432 */ 433 434 movb $CYRIX_CCR3, %al 435 outb $CYRIX_CRI 436 437 /* 438 * If we are not a Cyrix cpu, then we have performed an external I/O 439 * cycle. If the CCR index was not valid for this Cyrix model, we may 440 * have performed an external I/O cycle as well. In these cases and 441 * if the motherboard/chipset vendor ignores I/O address line A1, 442 * then the PIC will have IRQ3 set at the lowest priority as a side 443 * effect of the above outb. We are reasonalbly confident that there 444 * is not an unknown device on I/O port 0x22, so there should have been 445 * no unpredictable side-effect of the above outb. 446 */ 447 448 /* 449 * read CCR3 450 */ 451 inb $CYRIX_CRD 452 453 /* 454 * If we are not a Cyrix cpu the inb above produced an external I/O 455 * cycle. If we are a Cyrix model that does not support CCR3 wex 456 * produced an external I/O cycle. In all known Cyrix models 6x86 and 457 * above, bit 3 of CCR3 is reserved and cannot be set to 1. In all 458 * Cyrix models prior to the 6x86 that supported CCR3, bits 4-7 are 459 * reserved as well. It is highly unlikely that CCR3 contains the value 460 * 0xff. We test to see if I/O port 0x23 is pull-up or the IMR and 461 * deduce we are not a Cyrix with support for cpuid if so. 462 */ 463 cmpb $0xff, %al 464 je restore_PIC 465 466 /* 467 * There exist 486 ISA Cyrix chips that support CCR3 but do not support 468 * DIR0 and DIR1. If we try to read DIR0, we may generate external I/O 469 * cycles, the exact behavior is model specific and undocumented. 470 * Unfortunately these external I/O cycles may confuse some PIC's beyond 471 * recovery. Fortunatetly we can use the following undocumented trick: 472 * if bit 4 of CCR3 can be toggled, then DIR0 and DIR1 are supported. 473 * Pleasantly MAPEN contains bit 4 of CCR3, so this trick is guaranteed 474 * to work on all Cyrix cpu's which support cpuid. 475 */ 476 movb %al, %dl 477 xorb $0x10, %dl 478 movb %al, %cl 479 480 /* 481 * write back CRR3 with toggled bit 4 to CCR3 482 */ 483 movb $CYRIX_CCR3, %al 484 outb $CYRIX_CRI 485 486 movb %dl, %al 487 outb $CYRIX_CRD 488 489 /* 490 * read CCR3 491 */ 492 movb $CYRIX_CCR3, %al 493 outb $CYRIX_CRI 494 inb $CYRIX_CRD 495 movb %al, %dl 496 497 /* 498 * restore CCR3 499 */ 500 movb $CYRIX_CCR3, %al 501 outb $CYRIX_CRI 502 503 movb %cl, %al 504 outb $CYRIX_CRD 505 506 /* 507 * if bit 4 was not toggled DIR0 and DIR1 are not supported in which 508 * case we do not have cpuid anyway 509 */ 510 andb $0x10, %al 511 andb $0x10, %dl 512 cmpb %al, %dl 513 je restore_PIC 514 515 /* 516 * read DIR0 517 */ 518 movb $CYRIX_DIR0, %al 519 outb $CYRIX_CRI 520 inb $CYRIX_CRD 521 522 /* 523 * test for pull-up 524 */ 525 cmpb $0xff, %al 526 je restore_PIC 527 528 /* 529 * Values of 0x20-0x27 in DIR0 are currently reserved by Cyrix for 530 * future use. If Cyrix ever produces a cpu that supports cpuid with 531 * these ids, the following test will have to change. For now we remain 532 * pessimistic since the formats of the CRR's may be different then. 533 * 534 * test for at least a 6x86, to see if we support both MAPEN and CPUID 535 */ 536 cmpb $0x30, %al 537 jb restore_IMR 538 539 /* 540 * enable MAPEN 541 */ 542 movb $CYRIX_CCR3, %al 543 outb $CYRIX_CRI 544 545 andb $0xf, %cl 546 movb %cl, %al 547 orb $0x10, %al 548 outb $CYRIX_CRD 549 550 /* 551 * select CCR4 552 */ 553 movb $CYRIX_CCR4, %al 554 outb $CYRIX_CRI 555 556 /* 557 * read CCR4 558 */ 559 inb $CYRIX_CRD 560 561 /* 562 * enable cpuid 563 */ 564 orb $0x80, %al 565 movb %al, %dl 566 567 /* 568 * select CCR4 569 */ 570 movb $CYRIX_CCR4, %al 571 outb $CYRIX_CRI 572 573 /* 574 * write CCR4 575 */ 576 movb %dl, %al 577 outb $CYRIX_CRD 578 579 /* 580 * select CCR3 581 */ 582 movb $CYRIX_CCR3, %al 583 outb $CYRIX_CRI 584 585 /* 586 * disable MAPEN and write CCR3 587 */ 588 movb %cl, %al 589 outb $CYRIX_CRD 590 591 /* 592 * restore IMR 593 */ 594 movb %bl, %al 595 outb $MIMR_PORT 596 597 /* 598 * test to see if cpuid available 599 */ 600 pushfl 601 popl %ecx 602 movl %ecx, %eax 603 xorl $PS_ID, %eax / try complemented bit 604 pushl %eax 605 popfl 606 pushfl 607 popl %eax 608 cmpl %eax, %ecx 609 jne have_cpuid 610 jmp cpu_486 611 612restore_PIC: 613 /* 614 * In case the motherboard/chipset vendor is ignoring line A1 of the 615 * I/O address, we set the PIC priorities to sane values. 616 */ 617 movb $0xc7, %al / irq 7 lowest priority 618 outb $MCMD_PORT 619 620restore_IMR: 621 movb %bl, %al 622 outb $MIMR_PORT 623 jmp cpu_486 624 625have_cpuid: 626 /* 627 * cpuid instruction present 628 */ 629 bts $X86FSET_CPUID, x86_featureset / Just to set; Ignore the CF 630 movl $0, %eax 631 cpuid 632 633 movl %ebx, cpu_vendor 634 movl %edx, cpu_vendor+4 635 movl %ecx, cpu_vendor+8 636 637 /* 638 * early cyrix cpus are somewhat strange and need to be 639 * probed in curious ways to determine their identity 640 */ 641 642 leal cpu_vendor, %esi 643 leal CyrixInstead, %edi 644 movl $12, %ecx 645 repz 646 cmpsb 647 je vendor_is_cyrix 648 649 / let mlsetup()/cpuid_pass1() handle everything else in C 650 651 jmp cpu_done 652 653is486: 654 /* 655 * test to see if a useful cpuid 656 */ 657 testl %eax, %eax 658 jz isa486 659 660 movl $1, %eax 661 cpuid 662 663 movl %eax, %ebx 664 andl $0xF00, %ebx 665 cmpl $0x400, %ebx 666 je isa486 667 668 rep; ret /* use 2 byte return instruction */ 669 /* AMD Software Optimization Guide - Section 6.2 */ 670isa486: 671 /* 672 * lose the return address 673 */ 674 popl %eax 675 jmp cpu_486 676 677vendor_is_cyrix: 678 call is486 679 680 /* 681 * Processor signature and feature flags for Cyrix are insane. 682 * BIOS can play with semi-documented registers, so cpuid must be used 683 * cautiously. Since we are Cyrix that has cpuid, we have DIR0 and DIR1 684 * Keep the family in %ebx and feature flags in %edx until not needed 685 */ 686 687 /* 688 * read DIR0 689 */ 690 movb $CYRIX_DIR0, %al 691 outb $CYRIX_CRI 692 inb $CYRIX_CRD 693 694 /* 695 * First we handle the cases where we are a 6x86 or 6x86L. 696 * The 6x86 is basically a 486, the only reliable bit in the 697 * feature flags is for FPU. The 6x86L is better, unfortunately 698 * there is no really good way to distinguish between these two 699 * cpu's. We are pessimistic and when in doubt assume 6x86. 700 */ 701 702 cmpb $0x40, %al 703 jae maybeGX 704 705 /* 706 * We are an M1, either a 6x86 or 6x86L. 707 */ 708 cmpb $0x30, %al 709 je maybe6x86L 710 cmpb $0x31, %al 711 je maybe6x86L 712 cmpb $0x34, %al 713 je maybe6x86L 714 cmpb $0x35, %al 715 je maybe6x86L 716 717 /* 718 * although it is possible that we are a 6x86L, the cpu and 719 * documentation are so buggy, we just do not care. 720 */ 721 jmp likely6x86 722 723maybe6x86L: 724 /* 725 * read DIR1 726 */ 727 movb $CYRIX_DIR1, %al 728 outb $CYRIX_CRI 729 inb $CYRIX_CRD 730 cmpb $0x22, %al 731 jb likely6x86 732 733 /* 734 * We are a 6x86L, or at least a 6x86 with honest cpuid feature flags 735 */ 736 movl $X86_TYPE_CYRIX_6x86L, x86_type 737 jmp coma_bug 738 739likely6x86: 740 /* 741 * We are likely a 6x86, or a 6x86L without a way of knowing 742 * 743 * The 6x86 has NO Pentium or Pentium Pro compatible features even 744 * though it claims to be a Pentium Pro compatible! 745 * 746 * The 6x86 core used in the 6x86 may have most of the Pentium system 747 * registers and largely conform to the Pentium System Programming 748 * Reference. Documentation on these parts is long gone. Treat it as 749 * a crippled Pentium and hope for the best. 750 */ 751 752 movl $X86_TYPE_CYRIX_6x86, x86_type 753 jmp coma_bug 754 755maybeGX: 756 /* 757 * Now we check whether we are a MediaGX or GXm. We have particular 758 * reason for concern here. Even though most of the GXm's 759 * report having TSC in the cpuid feature flags, the TSC may be 760 * horribly broken. What is worse, is that MediaGX's are basically 761 * 486's while the good GXm's are more like Pentium Pro's! 762 */ 763 764 cmpb $0x50, %al 765 jae maybeM2 766 767 /* 768 * We are either a MediaGX (sometimes called a Gx86) or GXm 769 */ 770 771 cmpb $41, %al 772 je maybeMediaGX 773 774 cmpb $44, %al 775 jb maybeGXm 776 777 cmpb $47, %al 778 jbe maybeMediaGX 779 780 /* 781 * We do not honestly know what we are, so assume a MediaGX 782 */ 783 jmp media_gx 784 785maybeGXm: 786 /* 787 * It is still possible we are either a MediaGX or GXm, trust cpuid 788 * family should be 5 on a GXm 789 */ 790 cmpl $0x500, %ebx 791 je GXm 792 793 /* 794 * BIOS/Cyrix might set family to 6 on a GXm 795 */ 796 cmpl $0x600, %ebx 797 jne media_gx 798 799GXm: 800 movl $X86_TYPE_CYRIX_GXm, x86_type 801 jmp cpu_done 802 803maybeMediaGX: 804 /* 805 * read DIR1 806 */ 807 movb $CYRIX_DIR1, %al 808 outb $CYRIX_CRI 809 inb $CYRIX_CRD 810 811 cmpb $0x30, %al 812 jae maybeGXm 813 814 /* 815 * we are a MediaGX for which we do not trust cpuid 816 */ 817media_gx: 818 movl $X86_TYPE_CYRIX_MediaGX, x86_type 819 jmp cpu_486 820 821maybeM2: 822 /* 823 * Now we check whether we are a 6x86MX or MII. These cpu's are 824 * virtually identical, but we care because for the 6x86MX, we 825 * must work around the coma bug. Also for 6x86MX prior to revision 826 * 1.4, the TSC may have serious bugs. 827 */ 828 829 cmpb $0x60, %al 830 jae maybeM3 831 832 /* 833 * family should be 6, but BIOS/Cyrix might set it to 5 834 */ 835 cmpl $0x600, %ebx 836 ja cpu_486 837 838 /* 839 * read DIR1 840 */ 841 movb $CYRIX_DIR1, %al 842 outb $CYRIX_CRI 843 inb $CYRIX_CRD 844 845 cmpb $0x8, %al 846 jb cyrix6x86MX 847 cmpb $0x80, %al 848 jb MII 849 850cyrix6x86MX: 851 /* 852 * It is altogether unclear how the revision stamped on the cpu 853 * maps to the values in DIR0 and DIR1. Just assume TSC is broken. 854 */ 855 movl $X86_TYPE_CYRIX_6x86MX, x86_type 856 jmp coma_bug 857 858MII: 859 movl $X86_TYPE_CYRIX_MII, x86_type 860likeMII: 861 jmp cpu_done 862 863maybeM3: 864 /* 865 * We are some chip that we cannot identify yet, an MIII perhaps. 866 * We will be optimistic and hope that the chip is much like an MII, 867 * and that cpuid is sane. Cyrix seemed to have gotten it right in 868 * time for the MII, we can only hope it stayed that way. 869 * Maybe the BIOS or Cyrix is trying to hint at something 870 */ 871 cmpl $0x500, %ebx 872 je GXm 873 874 cmpb $0x80, %al 875 jae likelyM3 876 877 /* 878 * Just test for the features Cyrix is known for 879 */ 880 881 jmp MII 882 883likelyM3: 884 /* 885 * DIR0 with values from 0x80 to 0x8f indicates a VIA Cyrix III, aka 886 * the Cyrix MIII. There may be parts later that use the same ranges 887 * for DIR0 with special values in DIR1, maybe the VIA CIII, but for 888 * now we will call anything with a DIR0 of 0x80 or higher an MIII. 889 * The MIII is supposed to support large pages, but we will believe 890 * it when we see it. For now we just enable and test for MII features. 891 */ 892 movl $X86_TYPE_VIA_CYRIX_III, x86_type 893 jmp likeMII 894 895coma_bug: 896 897/* 898 * With NO_LOCK set to 0 in CCR1, the usual state that BIOS enforces, some 899 * bus cycles are issued with LOCK# asserted. With NO_LOCK set to 1, all bus 900 * cycles except page table accesses and interrupt ACK cycles do not assert 901 * LOCK#. xchgl is an instruction that asserts LOCK# if NO_LOCK is set to 0. 902 * Due to a bug in the cpu core involving over-optimization of branch 903 * prediction, register renaming, and execution of instructions down both the 904 * X and Y pipes for the xchgl instruction, short loops can be written that 905 * never de-assert LOCK# from one invocation of the loop to the next, ad 906 * infinitum. The undesirable effect of this situation is that interrupts are 907 * not serviced. The ideal workaround to this bug would be to set NO_LOCK to 908 * 1. Unfortunately bus cycles that would otherwise have asserted LOCK# no 909 * longer do, unless they are page table accesses or interrupt ACK cycles. 910 * With LOCK# not asserted, these bus cycles are now cached. This can cause 911 * undesirable behaviour if the ARR's are not configured correctly. Solaris 912 * does not configure the ARR's, nor does it provide any useful mechanism for 913 * doing so, thus the ideal workaround is not viable. Fortunately, the only 914 * known exploits for this bug involve the xchgl instruction specifically. 915 * There is a group of undocumented registers on Cyrix 6x86, 6x86L, and 916 * 6x86MX cpu's which can be used to specify one instruction as a serializing 917 * instruction. With the xchgl instruction serialized, LOCK# is still 918 * asserted, but it is the sole instruction for which LOCK# is asserted. 919 * There is now some added penalty for the xchgl instruction, but the usual 920 * bus locking is preserved. This ingenious workaround was discovered by 921 * disassembling a binary provided by Cyrix as a workaround for this bug on 922 * Windows, but its not documented anywhere by Cyrix, nor is the bug actually 923 * mentioned in any public errata! The only concern for this workaround is 924 * that there may be similar undiscovered bugs with other instructions that 925 * assert LOCK# that may be leveraged to similar ends. The fact that Cyrix 926 * fixed this bug sometime late in 1997 and no other exploits other than 927 * xchgl have been discovered is good indication that this workaround is 928 * reasonable. 929 */ 930 931 .set CYRIX_DBR0, 0x30 / Debug Register 0 932 .set CYRIX_DBR1, 0x31 / Debug Register 1 933 .set CYRIX_DBR2, 0x32 / Debug Register 2 934 .set CYRIX_DBR3, 0x33 / Debug Register 3 935 .set CYRIX_DOR, 0x3c / Debug Opcode Register 936 937 /* 938 * What is known about DBR1, DBR2, DBR3, and DOR is that for normal 939 * cpu execution DBR1, DBR2, and DBR3 are set to 0. To obtain opcode 940 * serialization, DBR1, DBR2, and DBR3 are loaded with 0xb8, 0x7f, 941 * and 0xff. Then, DOR is loaded with the one byte opcode. 942 */ 943 944 /* 945 * select CCR3 946 */ 947 movb $CYRIX_CCR3, %al 948 outb $CYRIX_CRI 949 950 /* 951 * read CCR3 and mask out MAPEN 952 */ 953 inb $CYRIX_CRD 954 andb $0xf, %al 955 956 /* 957 * save masked CCR3 in %ah 958 */ 959 movb %al, %ah 960 961 /* 962 * select CCR3 963 */ 964 movb $CYRIX_CCR3, %al 965 outb $CYRIX_CRI 966 967 /* 968 * enable MAPEN 969 */ 970 movb %ah, %al 971 orb $0x10, %al 972 outb $CYRIX_CRD 973 974 /* 975 * read DBR0 976 */ 977 movb $CYRIX_DBR0, %al 978 outb $CYRIX_CRI 979 inb $CYRIX_CRD 980 981 /* 982 * disable MATCH and save in %bh 983 */ 984 orb $0x80, %al 985 movb %al, %bh 986 987 /* 988 * write DBR0 989 */ 990 movb $CYRIX_DBR0, %al 991 outb $CYRIX_CRI 992 movb %bh, %al 993 outb $CYRIX_CRD 994 995 /* 996 * write DBR1 997 */ 998 movb $CYRIX_DBR1, %al 999 outb $CYRIX_CRI 1000 movb $0xf8, %al 1001 outb $CYRIX_CRD 1002 1003 /* 1004 * write DBR2 1005 */ 1006 movb $CYRIX_DBR2, %al 1007 outb $CYRIX_CRI 1008 movb $0x7f, %al 1009 outb $CYRIX_CRD 1010 1011 /* 1012 * write DBR3 1013 */ 1014 movb $CYRIX_DBR3, %al 1015 outb $CYRIX_CRI 1016 xorb %al, %al 1017 outb $CYRIX_CRD 1018 1019 /* 1020 * write DOR 1021 */ 1022 movb $CYRIX_DOR, %al 1023 outb $CYRIX_CRI 1024 movb $0x87, %al 1025 outb $CYRIX_CRD 1026 1027 /* 1028 * enable MATCH 1029 */ 1030 movb $CYRIX_DBR0, %al 1031 outb $CYRIX_CRI 1032 movb %bh, %al 1033 andb $0x7f, %al 1034 outb $CYRIX_CRD 1035 1036 /* 1037 * disable MAPEN 1038 */ 1039 movb $0xc3, %al 1040 outb $CYRIX_CRI 1041 movb %ah, %al 1042 outb $CYRIX_CRD 1043 1044 jmp cpu_done 1045 1046cpu_done: 1047 1048 popfl /* Restore original FLAGS */ 1049 popal /* Restore all registers */ 1050 1051#endif /* !__xpv */ 1052 1053 /* 1054 * mlsetup(%esp) gets called. 1055 */ 1056 pushl %esp 1057 call mlsetup 1058 addl $4, %esp 1059 1060 /* 1061 * We change our appearance to look like the real thread 0. 1062 * (NOTE: making ourselves to be a real thread may be a noop) 1063 * main() gets called. (NOTE: main() never returns). 1064 */ 1065 call main 1066 /* NOTREACHED */ 1067 pushl $__return_from_main 1068 call panic 1069 1070 /* NOTREACHED */ 1071cpu_486: 1072 pushl $__unsupported_cpu 1073 call panic 1074 SET_SIZE(_locore_start) 1075 1076#endif /* __lint */ 1077#endif /* !__amd64 */ 1078 1079 1080/* 1081 * For stack layout, see privregs.h 1082 * When cmntrap gets called, the error code and trap number have been pushed. 1083 * When cmntrap_pushed gets called, the entire struct regs has been pushed. 1084 */ 1085 1086#if defined(__lint) 1087 1088/* ARGSUSED */ 1089void 1090cmntrap() 1091{} 1092 1093#else /* __lint */ 1094 1095 .globl trap /* C handler called below */ 1096 1097#if defined(__amd64) 1098 1099 ENTRY_NP2(cmntrap, _cmntrap) 1100 1101 INTR_PUSH 1102 1103 ALTENTRY(cmntrap_pushed) 1104 1105 movq %rsp, %rbp 1106 1107 /* 1108 * - if this is a #pf i.e. T_PGFLT, %r15 is live 1109 * and contains the faulting address i.e. a copy of %cr2 1110 * 1111 * - if this is a #db i.e. T_SGLSTP, %r15 is live 1112 * and contains the value of %db6 1113 */ 1114 1115 TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) /* Uses labels 8 and 9 */ 1116 TRACE_REGS(%rdi, %rsp, %rbx, %rcx) /* Uses label 9 */ 1117 TRACE_STAMP(%rdi) /* Clobbers %eax, %edx, uses 9 */ 1118 1119 /* 1120 * We must first check if DTrace has set its NOFAULT bit. This 1121 * regrettably must happen before the trap stack is recorded, because 1122 * this requires a call to getpcstack() and may induce recursion if an 1123 * fbt::getpcstack: enabling is inducing the bad load. 1124 */ 1125 movl %gs:CPU_ID, %eax 1126 shlq $CPU_CORE_SHIFT, %rax 1127 leaq cpu_core(%rip), %r8 1128 addq %r8, %rax 1129 movw CPUC_DTRACE_FLAGS(%rax), %cx 1130 testw $CPU_DTRACE_NOFAULT, %cx 1131 jnz .dtrace_induced 1132 1133 TRACE_STACK(%rdi) 1134 1135 movq %rbp, %rdi 1136 movq %r15, %rsi 1137 movl %gs:CPU_ID, %edx 1138 1139 /* 1140 * We know that this isn't a DTrace non-faulting load; we can now safely 1141 * reenable interrupts. (In the case of pagefaults, we enter through an 1142 * interrupt gate.) 1143 */ 1144 ENABLE_INTR_FLAGS 1145 1146 call trap /* trap(rp, addr, cpuid) handles all traps */ 1147 jmp _sys_rtt 1148 1149.dtrace_induced: 1150 cmpw $KCS_SEL, REGOFF_CS(%rbp) /* test CS for user-mode trap */ 1151 jne 3f /* if from user, panic */ 1152 1153 cmpl $T_PGFLT, REGOFF_TRAPNO(%rbp) 1154 je 1f 1155 1156 cmpl $T_GPFLT, REGOFF_TRAPNO(%rbp) 1157 je 0f 1158 1159 cmpl $T_ILLINST, REGOFF_TRAPNO(%rbp) 1160 je 0f 1161 1162 jne 4f /* if not PF, GP or UD, panic */ 1163 1164 /* 1165 * If we've taken a GPF, we don't (unfortunately) have the address that 1166 * induced the fault. So instead of setting the fault to BADADDR, 1167 * we'll set the fault to ILLOP. 1168 */ 11690: 1170 orw $CPU_DTRACE_ILLOP, %cx 1171 movw %cx, CPUC_DTRACE_FLAGS(%rax) 1172 jmp 2f 11731: 1174 orw $CPU_DTRACE_BADADDR, %cx 1175 movw %cx, CPUC_DTRACE_FLAGS(%rax) /* set fault to bad addr */ 1176 movq %r15, CPUC_DTRACE_ILLVAL(%rax) 1177 /* fault addr is illegal value */ 11782: 1179 movq REGOFF_RIP(%rbp), %rdi 1180 movq %rdi, %r12 1181 call dtrace_instr_size 1182 addq %rax, %r12 1183 movq %r12, REGOFF_RIP(%rbp) 1184 INTR_POP 1185 IRET 1186 /*NOTREACHED*/ 11873: 1188 leaq dtrace_badflags(%rip), %rdi 1189 xorl %eax, %eax 1190 call panic 11914: 1192 leaq dtrace_badtrap(%rip), %rdi 1193 xorl %eax, %eax 1194 call panic 1195 SET_SIZE(cmntrap) 1196 SET_SIZE(_cmntrap) 1197 1198#elif defined(__i386) 1199 1200 1201 ENTRY_NP2(cmntrap, _cmntrap) 1202 1203 INTR_PUSH 1204 1205 ALTENTRY(cmntrap_pushed) 1206 1207 movl %esp, %ebp 1208 1209 /* 1210 * - if this is a #pf i.e. T_PGFLT, %esi is live 1211 * and contains the faulting address i.e. a copy of %cr2 1212 * 1213 * - if this is a #db i.e. T_SGLSTP, %esi is live 1214 * and contains the value of %db6 1215 */ 1216 1217 TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) /* Uses labels 8 and 9 */ 1218 TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ 1219 TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ 1220 1221 /* 1222 * We must first check if DTrace has set its NOFAULT bit. This 1223 * regrettably must happen before the trap stack is recorded, because 1224 * this requires a call to getpcstack() and may induce recursion if an 1225 * fbt::getpcstack: enabling is inducing the bad load. 1226 */ 1227 movl %gs:CPU_ID, %eax 1228 shll $CPU_CORE_SHIFT, %eax 1229 addl $cpu_core, %eax 1230 movw CPUC_DTRACE_FLAGS(%eax), %cx 1231 testw $CPU_DTRACE_NOFAULT, %cx 1232 jnz .dtrace_induced 1233 1234 TRACE_STACK(%edi) 1235 1236 pushl %gs:CPU_ID 1237 pushl %esi /* fault address for PGFLTs */ 1238 pushl %ebp /* ®s */ 1239 1240 /* 1241 * We know that this isn't a DTrace non-faulting load; we can now safely 1242 * reenable interrupts. (In the case of pagefaults, we enter through an 1243 * interrupt gate.) 1244 */ 1245 ENABLE_INTR_FLAGS 1246 1247 call trap /* trap(rp, addr, cpuid) handles all traps */ 1248 addl $12, %esp /* get argument off stack */ 1249 jmp _sys_rtt 1250 1251.dtrace_induced: 1252 cmpw $KCS_SEL, REGOFF_CS(%ebp) /* test CS for user-mode trap */ 1253 jne 2f /* if from user, panic */ 1254 1255 cmpl $T_PGFLT, REGOFF_TRAPNO(%ebp) 1256 je 0f 1257 1258 cmpl $T_GPFLT, REGOFF_TRAPNO(%ebp) 1259 jne 3f /* if not PF or GP, panic */ 1260 1261 /* 1262 * If we've taken a GPF, we don't (unfortunately) have the address that 1263 * induced the fault. So instead of setting the fault to BADADDR, 1264 * we'll set the fault to ILLOP. 1265 */ 1266 orw $CPU_DTRACE_ILLOP, %cx 1267 movw %cx, CPUC_DTRACE_FLAGS(%eax) 1268 jmp 1f 12690: 1270 orw $CPU_DTRACE_BADADDR, %cx 1271 movw %cx, CPUC_DTRACE_FLAGS(%eax) /* set fault to bad addr */ 1272 movl %esi, CPUC_DTRACE_ILLVAL(%eax) 1273 /* fault addr is illegal value */ 12741: 1275 pushl REGOFF_EIP(%ebp) 1276 call dtrace_instr_size 1277 addl $4, %esp 1278 movl REGOFF_EIP(%ebp), %ecx 1279 addl %eax, %ecx 1280 movl %ecx, REGOFF_EIP(%ebp) 1281 INTR_POP_KERNEL 1282 IRET 1283 /*NOTREACHED*/ 12842: 1285 pushl $dtrace_badflags 1286 call panic 12873: 1288 pushl $dtrace_badtrap 1289 call panic 1290 SET_SIZE(cmntrap) 1291 SET_SIZE(_cmntrap) 1292 1293#endif /* __i386 */ 1294 1295/* 1296 * Declare a uintptr_t which has the size of _cmntrap to enable stack 1297 * traceback code to know when a regs structure is on the stack. 1298 */ 1299 .globl _cmntrap_size 1300 .align CLONGSIZE 1301_cmntrap_size: 1302 .NWORD . - _cmntrap 1303 .type _cmntrap_size, @object 1304 1305dtrace_badflags: 1306 .string "bad DTrace flags" 1307 1308dtrace_badtrap: 1309 .string "bad DTrace trap" 1310 1311#endif /* __lint */ 1312 1313#if defined(__lint) 1314 1315/* ARGSUSED */ 1316void 1317cmninttrap() 1318{} 1319 1320#if !defined(__xpv) 1321void 1322bop_trap_handler(void) 1323{} 1324#endif 1325 1326#else /* __lint */ 1327 1328 .globl trap /* C handler called below */ 1329 1330#if defined(__amd64) 1331 1332 ENTRY_NP(cmninttrap) 1333 1334 INTR_PUSH 1335 INTGATE_INIT_KERNEL_FLAGS 1336 1337 TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) /* Uses labels 8 and 9 */ 1338 TRACE_REGS(%rdi, %rsp, %rbx, %rcx) /* Uses label 9 */ 1339 TRACE_STAMP(%rdi) /* Clobbers %eax, %edx, uses 9 */ 1340 1341 movq %rsp, %rbp 1342 1343 movl %gs:CPU_ID, %edx 1344 xorl %esi, %esi 1345 movq %rsp, %rdi 1346 call trap /* trap(rp, addr, cpuid) handles all traps */ 1347 jmp _sys_rtt 1348 SET_SIZE(cmninttrap) 1349 1350#if !defined(__xpv) 1351 /* 1352 * Handle traps early in boot. Just revectors into C quickly as 1353 * these are always fatal errors. 1354 * 1355 * Adjust %rsp to get same stack layout as in 32bit mode for bop_trap(). 1356 */ 1357 ENTRY(bop_trap_handler) 1358 movq %rsp, %rdi 1359 sub $8, %rsp 1360 call bop_trap 1361 SET_SIZE(bop_trap_handler) 1362#endif 1363 1364#elif defined(__i386) 1365 1366 ENTRY_NP(cmninttrap) 1367 1368 INTR_PUSH 1369 INTGATE_INIT_KERNEL_FLAGS 1370 1371 TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) /* Uses labels 8 and 9 */ 1372 TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ 1373 TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ 1374 1375 movl %esp, %ebp 1376 1377 TRACE_STACK(%edi) 1378 1379 pushl %gs:CPU_ID 1380 pushl $0 1381 pushl %ebp 1382 call trap /* trap(rp, addr, cpuid) handles all traps */ 1383 addl $12, %esp 1384 jmp _sys_rtt 1385 SET_SIZE(cmninttrap) 1386 1387#if !defined(__xpv) 1388 /* 1389 * Handle traps early in boot. Just revectors into C quickly as 1390 * these are always fatal errors. 1391 */ 1392 ENTRY(bop_trap_handler) 1393 movl %esp, %eax 1394 pushl %eax 1395 call bop_trap 1396 SET_SIZE(bop_trap_handler) 1397#endif 1398 1399#endif /* __i386 */ 1400 1401#endif /* __lint */ 1402 1403#if defined(__lint) 1404 1405/* ARGSUSED */ 1406void 1407dtrace_trap() 1408{} 1409 1410#else /* __lint */ 1411 1412 .globl dtrace_user_probe 1413 1414#if defined(__amd64) 1415 1416 ENTRY_NP(dtrace_trap) 1417 1418 INTR_PUSH 1419 1420 TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) /* Uses labels 8 and 9 */ 1421 TRACE_REGS(%rdi, %rsp, %rbx, %rcx) /* Uses label 9 */ 1422 TRACE_STAMP(%rdi) /* Clobbers %eax, %edx, uses 9 */ 1423 1424 movq %rsp, %rbp 1425 1426 movl %gs:CPU_ID, %edx 1427#if defined(__xpv) 1428 movq %gs:CPU_VCPU_INFO, %rsi 1429 movq VCPU_INFO_ARCH_CR2(%rsi), %rsi 1430#else 1431 movq %cr2, %rsi 1432#endif 1433 movq %rsp, %rdi 1434 1435 ENABLE_INTR_FLAGS 1436 1437 call dtrace_user_probe /* dtrace_user_probe(rp, addr, cpuid) */ 1438 jmp _sys_rtt 1439 1440 SET_SIZE(dtrace_trap) 1441 1442#elif defined(__i386) 1443 1444 ENTRY_NP(dtrace_trap) 1445 1446 INTR_PUSH 1447 1448 TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) /* Uses labels 8 and 9 */ 1449 TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ 1450 TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ 1451 1452 movl %esp, %ebp 1453 1454 pushl %gs:CPU_ID 1455#if defined(__xpv) 1456 movl %gs:CPU_VCPU_INFO, %eax 1457 movl VCPU_INFO_ARCH_CR2(%eax), %eax 1458#else 1459 movl %cr2, %eax 1460#endif 1461 pushl %eax 1462 pushl %ebp 1463 1464 ENABLE_INTR_FLAGS 1465 1466 call dtrace_user_probe /* dtrace_user_probe(rp, addr, cpuid) */ 1467 addl $12, %esp /* get argument off stack */ 1468 1469 jmp _sys_rtt 1470 SET_SIZE(dtrace_trap) 1471 1472#endif /* __i386 */ 1473 1474#endif /* __lint */ 1475 1476/* 1477 * Return from _sys_trap routine. 1478 */ 1479 1480#if defined(__lint) 1481 1482void 1483lwp_rtt_initial(void) 1484{} 1485 1486void 1487lwp_rtt(void) 1488{} 1489 1490void 1491_sys_rtt(void) 1492{} 1493 1494#else /* __lint */ 1495 1496#if defined(__amd64) 1497 1498 ENTRY_NP(lwp_rtt_initial) 1499 movq %gs:CPU_THREAD, %r15 1500 movq T_STACK(%r15), %rsp /* switch to the thread stack */ 1501 movq %rsp, %rbp 1502 call __dtrace_probe___proc_start 1503 jmp _lwp_rtt 1504 1505 ENTRY_NP(lwp_rtt) 1506 1507 /* 1508 * r14 lwp 1509 * rdx lwp->lwp_procp 1510 * r15 curthread 1511 */ 1512 1513 movq %gs:CPU_THREAD, %r15 1514 movq T_STACK(%r15), %rsp /* switch to the thread stack */ 1515 movq %rsp, %rbp 1516_lwp_rtt: 1517 call __dtrace_probe___proc_lwp__start 1518 movq %gs:CPU_LWP, %r14 1519 movq LWP_PROCP(%r14), %rdx 1520 1521 /* 1522 * XX64 Is the stack misaligned correctly at this point? 1523 * If not, we need to do a push before calling anything .. 1524 */ 1525 1526#if defined(DEBUG) 1527 /* 1528 * If we were to run lwp_savectx at this point -without- 1529 * pcb_rupdate being set to 1, we'd end up sampling the hardware 1530 * state left by the previous running lwp, rather than setting 1531 * the values requested by the lwp creator. Bad. 1532 */ 1533 testb $0x1, PCB_RUPDATE(%r14) 1534 jne 1f 1535 leaq _no_pending_updates(%rip), %rdi 1536 movl $__LINE__, %esi 1537 movq %r14, %rdx 1538 xorl %eax, %eax 1539 call panic 1540_no_pending_updates: 1541 .string "locore.s:%d lwp_rtt(lwp %p) but pcb_rupdate != 1" 15421: 1543#endif 1544 1545 /* 1546 * If agent lwp, clear %fs and %gs 1547 */ 1548 cmpq %r15, P_AGENTTP(%rdx) 1549 jne 1f 1550 xorl %ecx, %ecx 1551 movq %rcx, REGOFF_FS(%rsp) 1552 movq %rcx, REGOFF_GS(%rsp) 1553 movw %cx, LWP_PCB_FS(%r14) 1554 movw %cx, LWP_PCB_GS(%r14) 15551: 1556 call dtrace_systrace_rtt 1557 movq REGOFF_RDX(%rsp), %rsi 1558 movq REGOFF_RAX(%rsp), %rdi 1559 call post_syscall /* post_syscall(rval1, rval2) */ 1560 1561 /* 1562 * set up to take fault on first use of fp 1563 */ 1564 STTS(%rdi) 1565 1566 /* 1567 * XXX - may want a fast path that avoids sys_rtt_common in the 1568 * most common case. 1569 */ 1570 ALTENTRY(_sys_rtt) 1571 CLI(%rax) /* disable interrupts */ 1572 ALTENTRY(_sys_rtt_ints_disabled) 1573 movq %rsp, %rdi /* pass rp to sys_rtt_common */ 1574 call sys_rtt_common /* do common sys_rtt tasks */ 1575 testq %rax, %rax /* returning to userland? */ 1576 jz sr_sup 1577 1578 /* 1579 * Return to user 1580 */ 1581 ASSERT_UPCALL_MASK_IS_SET 1582 cmpw $UCS_SEL, REGOFF_CS(%rsp) /* test for native (64-bit) lwp? */ 1583 je sys_rtt_syscall 1584 1585 /* 1586 * Return to 32-bit userland 1587 */ 1588 ALTENTRY(sys_rtt_syscall32) 1589 USER32_POP 1590 IRET 1591 /*NOTREACHED*/ 1592 1593 ALTENTRY(sys_rtt_syscall) 1594 /* 1595 * Return to 64-bit userland 1596 */ 1597 USER_POP 1598 ALTENTRY(nopop_sys_rtt_syscall) 1599 IRET 1600 /*NOTREACHED*/ 1601 SET_SIZE(nopop_sys_rtt_syscall) 1602 1603 /* 1604 * Return to supervisor 1605 * NOTE: to make the check in trap() that tests if we are executing 1606 * segment register fixup/restore code work properly, sr_sup MUST be 1607 * after _sys_rtt . 1608 */ 1609 ALTENTRY(sr_sup) 1610 /* 1611 * Restore regs before doing iretq to kernel mode 1612 */ 1613 INTR_POP 1614 IRET 1615 .globl _sys_rtt_end 1616_sys_rtt_end: 1617 /*NOTREACHED*/ 1618 SET_SIZE(sr_sup) 1619 SET_SIZE(_sys_rtt_end) 1620 SET_SIZE(lwp_rtt) 1621 SET_SIZE(lwp_rtt_initial) 1622 SET_SIZE(_sys_rtt_ints_disabled) 1623 SET_SIZE(_sys_rtt) 1624 SET_SIZE(sys_rtt_syscall) 1625 SET_SIZE(sys_rtt_syscall32) 1626 1627#elif defined(__i386) 1628 1629 ENTRY_NP(lwp_rtt_initial) 1630 movl %gs:CPU_THREAD, %eax 1631 movl T_STACK(%eax), %esp /* switch to the thread stack */ 1632 movl %esp, %ebp 1633 call __dtrace_probe___proc_start 1634 jmp _lwp_rtt 1635 1636 ENTRY_NP(lwp_rtt) 1637 movl %gs:CPU_THREAD, %eax 1638 movl T_STACK(%eax), %esp /* switch to the thread stack */ 1639 movl %esp, %ebp 1640_lwp_rtt: 1641 call __dtrace_probe___proc_lwp__start 1642 1643 /* 1644 * If agent lwp, clear %fs and %gs. 1645 */ 1646 movl %gs:CPU_LWP, %eax 1647 movl LWP_PROCP(%eax), %edx 1648 1649 cmpl %eax, P_AGENTTP(%edx) 1650 jne 1f 1651 movl $0, REGOFF_FS(%esp) 1652 movl $0, REGOFF_GS(%esp) 16531: 1654 call dtrace_systrace_rtt 1655 movl REGOFF_EDX(%esp), %edx 1656 movl REGOFF_EAX(%esp), %eax 1657 pushl %edx 1658 pushl %eax 1659 call post_syscall /* post_syscall(rval1, rval2) */ 1660 addl $8, %esp 1661 1662 /* 1663 * set up to take fault on first use of fp 1664 */ 1665 STTS(%eax) 1666 1667 /* 1668 * XXX - may want a fast path that avoids sys_rtt_common in the 1669 * most common case. 1670 */ 1671 ALTENTRY(_sys_rtt) 1672 CLI(%eax) /* disable interrupts */ 1673 ALTENTRY(_sys_rtt_ints_disabled) 1674 pushl %esp /* pass rp to sys_rtt_common */ 1675 call sys_rtt_common 1676 addl $4, %esp /* pop arg */ 1677 testl %eax, %eax /* test for return to user mode */ 1678 jz sr_sup 1679 1680 /* 1681 * Return to User. 1682 */ 1683 ALTENTRY(sys_rtt_syscall) 1684 INTR_POP_USER 1685 1686 /* 1687 * There can be no instructions between this label and IRET or 1688 * we could end up breaking linux brand support. See label usage 1689 * in lx_brand_int80_callback for an example. 1690 */ 1691 ALTENTRY(nopop_sys_rtt_syscall) 1692 IRET 1693 /*NOTREACHED*/ 1694 SET_SIZE(nopop_sys_rtt_syscall) 1695 1696 ALTENTRY(_sys_rtt_end) 1697 1698 /* 1699 * Return to supervisor 1700 */ 1701 ALTENTRY(sr_sup) 1702 1703 /* 1704 * Restore regs before doing iret to kernel mode 1705 */ 1706 INTR_POP_KERNEL 1707 IRET 1708 /*NOTREACHED*/ 1709 1710 SET_SIZE(sr_sup) 1711 SET_SIZE(_sys_rtt_end) 1712 SET_SIZE(lwp_rtt) 1713 SET_SIZE(lwp_rtt_initial) 1714 SET_SIZE(_sys_rtt_ints_disabled) 1715 SET_SIZE(_sys_rtt) 1716 SET_SIZE(sys_rtt_syscall) 1717 1718#endif /* __i386 */ 1719 1720#endif /* __lint */ 1721 1722#if defined(__lint) 1723 1724/* 1725 * So why do we have to deal with all this crud in the world of ia32? 1726 * 1727 * Basically there are four classes of ia32 implementations, those that do not 1728 * have a TSC, those that have a marginal TSC that is broken to the extent 1729 * that it is useless, those that have a marginal TSC that is not quite so 1730 * horribly broken and can be used with some care, and those that have a 1731 * reliable TSC. This crud has to be here in order to sift through all the 1732 * variants. 1733 */ 1734 1735/*ARGSUSED*/ 1736uint64_t 1737freq_tsc(uint32_t *pit_counter) 1738{ 1739 return (0); 1740} 1741 1742#else /* __lint */ 1743 1744#if defined(__amd64) 1745 1746 /* 1747 * XX64 quick and dirty port from the i386 version. Since we 1748 * believe the amd64 tsc is more reliable, could this code be 1749 * simpler? 1750 */ 1751 ENTRY_NP(freq_tsc) 1752 pushq %rbp 1753 movq %rsp, %rbp 1754 movq %rdi, %r9 /* save pit_counter */ 1755 pushq %rbx 1756 1757/ We have a TSC, but we have no way in general to know how reliable it is. 1758/ Usually a marginal TSC behaves appropriately unless not enough time 1759/ elapses between reads. A reliable TSC can be read as often and as rapidly 1760/ as desired. The simplistic approach of reading the TSC counter and 1761/ correlating to the PIT counter cannot be naively followed. Instead estimates 1762/ have to be taken to successively refine a guess at the speed of the cpu 1763/ and then the TSC and PIT counter are correlated. In practice very rarely 1764/ is more than one quick loop required for an estimate. Measures have to be 1765/ taken to prevent the PIT counter from wrapping beyond its resolution and for 1766/ measuring the clock rate of very fast processors. 1767/ 1768/ The following constant can be tuned. It should be such that the loop does 1769/ not take too many nor too few PIT counts to execute. If this value is too 1770/ large, then on slow machines the loop will take a long time, or the PIT 1771/ counter may even wrap. If this value is too small, then on fast machines 1772/ the PIT counter may count so few ticks that the resolution of the PIT 1773/ itself causes a bad guess. Because this code is used in machines with 1774/ marginal TSC's and/or IO, if this value is too small on those, it may 1775/ cause the calculated cpu frequency to vary slightly from boot to boot. 1776/ 1777/ In all cases even if this constant is set inappropriately, the algorithm 1778/ will still work and the caller should be able to handle variances in the 1779/ calculation of cpu frequency, but the calculation will be inefficient and 1780/ take a disproportionate amount of time relative to a well selected value. 1781/ As the slowest supported cpu becomes faster, this constant should be 1782/ carefully increased. 1783 1784 movl $0x8000, %ecx 1785 1786 / to make sure the instruction cache has been warmed 1787 clc 1788 1789 jmp freq_tsc_loop 1790 1791/ The following block of code up to and including the latching of the PIT 1792/ counter after freq_tsc_perf_loop is very critical and very carefully 1793/ written, it should only be modified with great care. freq_tsc_loop to 1794/ freq_tsc_perf_loop fits exactly in 16 bytes as do the instructions in 1795/ freq_tsc_perf_loop up to the unlatching of the PIT counter. 1796 1797 .align 32 1798freq_tsc_loop: 1799 / save the loop count in %ebx 1800 movl %ecx, %ebx 1801 1802 / initialize the PIT counter and start a count down 1803 movb $PIT_LOADMODE, %al 1804 outb $PITCTL_PORT 1805 movb $0xff, %al 1806 outb $PITCTR0_PORT 1807 outb $PITCTR0_PORT 1808 1809 / read the TSC and store the TS in %edi:%esi 1810 rdtsc 1811 movl %eax, %esi 1812 1813freq_tsc_perf_loop: 1814 movl %edx, %edi 1815 movl %eax, %esi 1816 movl %edx, %edi 1817 loop freq_tsc_perf_loop 1818 1819 / read the TSC and store the LSW in %ecx 1820 rdtsc 1821 movl %eax, %ecx 1822 1823 / latch the PIT counter and status 1824 movb $_CONST(PIT_READBACK|PIT_READBACKC0), %al 1825 outb $PITCTL_PORT 1826 1827 / remember if the icache has been warmed 1828 setc %ah 1829 1830 / read the PIT status 1831 inb $PITCTR0_PORT 1832 shll $8, %eax 1833 1834 / read PIT count 1835 inb $PITCTR0_PORT 1836 shll $8, %eax 1837 inb $PITCTR0_PORT 1838 bswap %eax 1839 1840 / check to see if the PIT count was loaded into the CE 1841 btw $_CONST(PITSTAT_NULLCNT+8), %ax 1842 jc freq_tsc_increase_count 1843 1844 / check to see if PIT counter wrapped 1845 btw $_CONST(PITSTAT_OUTPUT+8), %ax 1846 jnc freq_tsc_pit_did_not_wrap 1847 1848 / halve count 1849 shrl $1, %ebx 1850 movl %ebx, %ecx 1851 1852 / the instruction cache has been warmed 1853 stc 1854 1855 jmp freq_tsc_loop 1856 1857freq_tsc_increase_count: 1858 shll $1, %ebx 1859 jc freq_tsc_too_fast 1860 1861 movl %ebx, %ecx 1862 1863 / the instruction cache has been warmed 1864 stc 1865 1866 jmp freq_tsc_loop 1867 1868freq_tsc_pit_did_not_wrap: 1869 roll $16, %eax 1870 1871 cmpw $0x2000, %ax 1872 notw %ax 1873 jb freq_tsc_sufficient_duration 1874 1875freq_tsc_calculate: 1876 / in mode 0, the PIT loads the count into the CE on the first CLK pulse, 1877 / then on the second CLK pulse the CE is decremented, therefore mode 0 1878 / is really a (count + 1) counter, ugh 1879 xorl %esi, %esi 1880 movw %ax, %si 1881 incl %esi 1882 1883 movl $0xf000, %eax 1884 mull %ebx 1885 1886 / tuck away (target_pit_count * loop_count) 1887 movl %edx, %ecx 1888 movl %eax, %ebx 1889 1890 movl %esi, %eax 1891 movl $0xffffffff, %edx 1892 mull %edx 1893 1894 addl %esi, %eax 1895 adcl $0, %edx 1896 1897 cmpl %ecx, %edx 1898 ja freq_tsc_div_safe 1899 jb freq_tsc_too_fast 1900 1901 cmpl %ebx, %eax 1902 jbe freq_tsc_too_fast 1903 1904freq_tsc_div_safe: 1905 movl %ecx, %edx 1906 movl %ebx, %eax 1907 1908 movl %esi, %ecx 1909 divl %ecx 1910 1911 movl %eax, %ecx 1912 1913 / the instruction cache has been warmed 1914 stc 1915 1916 jmp freq_tsc_loop 1917 1918freq_tsc_sufficient_duration: 1919 / test to see if the icache has been warmed 1920 btl $16, %eax 1921 jnc freq_tsc_calculate 1922 1923 / recall mode 0 is a (count + 1) counter 1924 andl $0xffff, %eax 1925 incl %eax 1926 1927 / save the number of PIT counts 1928 movl %eax, (%r9) 1929 1930 / calculate the number of TS's that elapsed 1931 movl %ecx, %eax 1932 subl %esi, %eax 1933 sbbl %edi, %edx 1934 1935 jmp freq_tsc_end 1936 1937freq_tsc_too_fast: 1938 / return 0 as a 64 bit quantity 1939 xorl %eax, %eax 1940 xorl %edx, %edx 1941 1942freq_tsc_end: 1943 shlq $32, %rdx 1944 orq %rdx, %rax 1945 1946 popq %rbx 1947 leaveq 1948 ret 1949 SET_SIZE(freq_tsc) 1950 1951#elif defined(__i386) 1952 1953 ENTRY_NP(freq_tsc) 1954 pushl %ebp 1955 movl %esp, %ebp 1956 pushl %edi 1957 pushl %esi 1958 pushl %ebx 1959 1960/ We have a TSC, but we have no way in general to know how reliable it is. 1961/ Usually a marginal TSC behaves appropriately unless not enough time 1962/ elapses between reads. A reliable TSC can be read as often and as rapidly 1963/ as desired. The simplistic approach of reading the TSC counter and 1964/ correlating to the PIT counter cannot be naively followed. Instead estimates 1965/ have to be taken to successively refine a guess at the speed of the cpu 1966/ and then the TSC and PIT counter are correlated. In practice very rarely 1967/ is more than one quick loop required for an estimate. Measures have to be 1968/ taken to prevent the PIT counter from wrapping beyond its resolution and for 1969/ measuring the clock rate of very fast processors. 1970/ 1971/ The following constant can be tuned. It should be such that the loop does 1972/ not take too many nor too few PIT counts to execute. If this value is too 1973/ large, then on slow machines the loop will take a long time, or the PIT 1974/ counter may even wrap. If this value is too small, then on fast machines 1975/ the PIT counter may count so few ticks that the resolution of the PIT 1976/ itself causes a bad guess. Because this code is used in machines with 1977/ marginal TSC's and/or IO, if this value is too small on those, it may 1978/ cause the calculated cpu frequency to vary slightly from boot to boot. 1979/ 1980/ In all cases even if this constant is set inappropriately, the algorithm 1981/ will still work and the caller should be able to handle variances in the 1982/ calculation of cpu frequency, but the calculation will be inefficient and 1983/ take a disproportionate amount of time relative to a well selected value. 1984/ As the slowest supported cpu becomes faster, this constant should be 1985/ carefully increased. 1986 1987 movl $0x8000, %ecx 1988 1989 / to make sure the instruction cache has been warmed 1990 clc 1991 1992 jmp freq_tsc_loop 1993 1994/ The following block of code up to and including the latching of the PIT 1995/ counter after freq_tsc_perf_loop is very critical and very carefully 1996/ written, it should only be modified with great care. freq_tsc_loop to 1997/ freq_tsc_perf_loop fits exactly in 16 bytes as do the instructions in 1998/ freq_tsc_perf_loop up to the unlatching of the PIT counter. 1999 2000 .align 32 2001freq_tsc_loop: 2002 / save the loop count in %ebx 2003 movl %ecx, %ebx 2004 2005 / initialize the PIT counter and start a count down 2006 movb $PIT_LOADMODE, %al 2007 outb $PITCTL_PORT 2008 movb $0xff, %al 2009 outb $PITCTR0_PORT 2010 outb $PITCTR0_PORT 2011 2012 / read the TSC and store the TS in %edi:%esi 2013 rdtsc 2014 movl %eax, %esi 2015 2016freq_tsc_perf_loop: 2017 movl %edx, %edi 2018 movl %eax, %esi 2019 movl %edx, %edi 2020 loop freq_tsc_perf_loop 2021 2022 / read the TSC and store the LSW in %ecx 2023 rdtsc 2024 movl %eax, %ecx 2025 2026 / latch the PIT counter and status 2027 movb $_CONST(PIT_READBACK|PIT_READBACKC0), %al 2028 outb $PITCTL_PORT 2029 2030 / remember if the icache has been warmed 2031 setc %ah 2032 2033 / read the PIT status 2034 inb $PITCTR0_PORT 2035 shll $8, %eax 2036 2037 / read PIT count 2038 inb $PITCTR0_PORT 2039 shll $8, %eax 2040 inb $PITCTR0_PORT 2041 bswap %eax 2042 2043 / check to see if the PIT count was loaded into the CE 2044 btw $_CONST(PITSTAT_NULLCNT+8), %ax 2045 jc freq_tsc_increase_count 2046 2047 / check to see if PIT counter wrapped 2048 btw $_CONST(PITSTAT_OUTPUT+8), %ax 2049 jnc freq_tsc_pit_did_not_wrap 2050 2051 / halve count 2052 shrl $1, %ebx 2053 movl %ebx, %ecx 2054 2055 / the instruction cache has been warmed 2056 stc 2057 2058 jmp freq_tsc_loop 2059 2060freq_tsc_increase_count: 2061 shll $1, %ebx 2062 jc freq_tsc_too_fast 2063 2064 movl %ebx, %ecx 2065 2066 / the instruction cache has been warmed 2067 stc 2068 2069 jmp freq_tsc_loop 2070 2071freq_tsc_pit_did_not_wrap: 2072 roll $16, %eax 2073 2074 cmpw $0x2000, %ax 2075 notw %ax 2076 jb freq_tsc_sufficient_duration 2077 2078freq_tsc_calculate: 2079 / in mode 0, the PIT loads the count into the CE on the first CLK pulse, 2080 / then on the second CLK pulse the CE is decremented, therefore mode 0 2081 / is really a (count + 1) counter, ugh 2082 xorl %esi, %esi 2083 movw %ax, %si 2084 incl %esi 2085 2086 movl $0xf000, %eax 2087 mull %ebx 2088 2089 / tuck away (target_pit_count * loop_count) 2090 movl %edx, %ecx 2091 movl %eax, %ebx 2092 2093 movl %esi, %eax 2094 movl $0xffffffff, %edx 2095 mull %edx 2096 2097 addl %esi, %eax 2098 adcl $0, %edx 2099 2100 cmpl %ecx, %edx 2101 ja freq_tsc_div_safe 2102 jb freq_tsc_too_fast 2103 2104 cmpl %ebx, %eax 2105 jbe freq_tsc_too_fast 2106 2107freq_tsc_div_safe: 2108 movl %ecx, %edx 2109 movl %ebx, %eax 2110 2111 movl %esi, %ecx 2112 divl %ecx 2113 2114 movl %eax, %ecx 2115 2116 / the instruction cache has been warmed 2117 stc 2118 2119 jmp freq_tsc_loop 2120 2121freq_tsc_sufficient_duration: 2122 / test to see if the icache has been warmed 2123 btl $16, %eax 2124 jnc freq_tsc_calculate 2125 2126 / recall mode 0 is a (count + 1) counter 2127 andl $0xffff, %eax 2128 incl %eax 2129 2130 / save the number of PIT counts 2131 movl 8(%ebp), %ebx 2132 movl %eax, (%ebx) 2133 2134 / calculate the number of TS's that elapsed 2135 movl %ecx, %eax 2136 subl %esi, %eax 2137 sbbl %edi, %edx 2138 2139 jmp freq_tsc_end 2140 2141freq_tsc_too_fast: 2142 / return 0 as a 64 bit quantity 2143 xorl %eax, %eax 2144 xorl %edx, %edx 2145 2146freq_tsc_end: 2147 popl %ebx 2148 popl %esi 2149 popl %edi 2150 popl %ebp 2151 ret 2152 SET_SIZE(freq_tsc) 2153 2154#endif /* __i386 */ 2155#endif /* __lint */ 2156 2157#if !defined(__amd64) 2158#if defined(__lint) 2159 2160/* 2161 * We do not have a TSC so we use a block of instructions with well known 2162 * timings. 2163 */ 2164 2165/*ARGSUSED*/ 2166uint64_t 2167freq_notsc(uint32_t *pit_counter) 2168{ 2169 return (0); 2170} 2171 2172#else /* __lint */ 2173 ENTRY_NP(freq_notsc) 2174 pushl %ebp 2175 movl %esp, %ebp 2176 pushl %edi 2177 pushl %esi 2178 pushl %ebx 2179 2180 / initial count for the idivl loop 2181 movl $0x1000, %ecx 2182 2183 / load the divisor 2184 movl $1, %ebx 2185 2186 jmp freq_notsc_loop 2187 2188.align 16 2189freq_notsc_loop: 2190 / set high 32 bits of dividend to zero 2191 xorl %edx, %edx 2192 2193 / save the loop count in %edi 2194 movl %ecx, %edi 2195 2196 / initialize the PIT counter and start a count down 2197 movb $PIT_LOADMODE, %al 2198 outb $PITCTL_PORT 2199 movb $0xff, %al 2200 outb $PITCTR0_PORT 2201 outb $PITCTR0_PORT 2202 2203 / set low 32 bits of dividend to zero 2204 xorl %eax, %eax 2205 2206/ It is vital that the arguments to idivl be set appropriately because on some 2207/ cpu's this instruction takes more or less clock ticks depending on its 2208/ arguments. 2209freq_notsc_perf_loop: 2210 idivl %ebx 2211 idivl %ebx 2212 idivl %ebx 2213 idivl %ebx 2214 idivl %ebx 2215 loop freq_notsc_perf_loop 2216 2217 / latch the PIT counter and status 2218 movb $_CONST(PIT_READBACK|PIT_READBACKC0), %al 2219 outb $PITCTL_PORT 2220 2221 / read the PIT status 2222 inb $PITCTR0_PORT 2223 shll $8, %eax 2224 2225 / read PIT count 2226 inb $PITCTR0_PORT 2227 shll $8, %eax 2228 inb $PITCTR0_PORT 2229 bswap %eax 2230 2231 / check to see if the PIT count was loaded into the CE 2232 btw $_CONST(PITSTAT_NULLCNT+8), %ax 2233 jc freq_notsc_increase_count 2234 2235 / check to see if PIT counter wrapped 2236 btw $_CONST(PITSTAT_OUTPUT+8), %ax 2237 jnc freq_notsc_pit_did_not_wrap 2238 2239 / halve count 2240 shrl $1, %edi 2241 movl %edi, %ecx 2242 2243 jmp freq_notsc_loop 2244 2245freq_notsc_increase_count: 2246 shll $1, %edi 2247 jc freq_notsc_too_fast 2248 2249 movl %edi, %ecx 2250 2251 jmp freq_notsc_loop 2252 2253freq_notsc_pit_did_not_wrap: 2254 shrl $16, %eax 2255 2256 cmpw $0x2000, %ax 2257 notw %ax 2258 jb freq_notsc_sufficient_duration 2259 2260freq_notsc_calculate: 2261 / in mode 0, the PIT loads the count into the CE on the first CLK pulse, 2262 / then on the second CLK pulse the CE is decremented, therefore mode 0 2263 / is really a (count + 1) counter, ugh 2264 xorl %esi, %esi 2265 movw %ax, %si 2266 incl %esi 2267 2268 movl %edi, %eax 2269 movl $0xf000, %ecx 2270 mull %ecx 2271 2272 / tuck away (target_pit_count * loop_count) 2273 movl %edx, %edi 2274 movl %eax, %ecx 2275 2276 movl %esi, %eax 2277 movl $0xffffffff, %edx 2278 mull %edx 2279 2280 addl %esi, %eax 2281 adcl $0, %edx 2282 2283 cmpl %edi, %edx 2284 ja freq_notsc_div_safe 2285 jb freq_notsc_too_fast 2286 2287 cmpl %ecx, %eax 2288 jbe freq_notsc_too_fast 2289 2290freq_notsc_div_safe: 2291 movl %edi, %edx 2292 movl %ecx, %eax 2293 2294 movl %esi, %ecx 2295 divl %ecx 2296 2297 movl %eax, %ecx 2298 2299 jmp freq_notsc_loop 2300 2301freq_notsc_sufficient_duration: 2302 / recall mode 0 is a (count + 1) counter 2303 incl %eax 2304 2305 / save the number of PIT counts 2306 movl 8(%ebp), %ebx 2307 movl %eax, (%ebx) 2308 2309 / calculate the number of cpu clock ticks that elapsed 2310 cmpl $X86_VENDOR_Cyrix, x86_vendor 2311 jz freq_notsc_notcyrix 2312 2313 / freq_notsc_perf_loop takes 86 clock cycles on Cyrix 6x86 cores 2314 movl $86, %eax 2315 jmp freq_notsc_calculate_tsc 2316 2317freq_notsc_notcyrix: 2318 / freq_notsc_perf_loop takes 237 clock cycles on Intel Pentiums 2319 movl $237, %eax 2320 2321freq_notsc_calculate_tsc: 2322 mull %edi 2323 2324 jmp freq_notsc_end 2325 2326freq_notsc_too_fast: 2327 / return 0 as a 64 bit quantity 2328 xorl %eax, %eax 2329 xorl %edx, %edx 2330 2331freq_notsc_end: 2332 popl %ebx 2333 popl %esi 2334 popl %edi 2335 popl %ebp 2336 2337 ret 2338 SET_SIZE(freq_notsc) 2339 2340#endif /* __lint */ 2341#endif /* !__amd64 */ 2342 2343#if !defined(__lint) 2344 .data 2345#if !defined(__amd64) 2346 .align 4 2347cpu_vendor: 2348 .long 0, 0, 0 /* Vendor ID string returned */ 2349 2350 .globl CyrixInstead 2351 2352 .globl x86_featureset 2353 .globl x86_type 2354 .globl x86_vendor 2355#endif 2356 2357#endif /* __lint */ 2358