| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: locore.S,v 1.104 2013/06/22 15:13:55 uebayasi Exp $ */ | | 1 | /* $NetBSD: locore.S,v 1.105 2013/06/23 03:16:46 uebayasi Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright-o-rama! | | 4 | * Copyright-o-rama! |
5 | */ | | 5 | */ |
6 | | | 6 | |
7 | /* | | 7 | /* |
8 | * Copyright (c) 2006 Manuel Bouyer. | | 8 | * Copyright (c) 2006 Manuel Bouyer. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -119,27 +119,27 @@ | | | @@ -119,27 +119,27 @@ |
119 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 119 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
120 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 120 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
121 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 121 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
122 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 122 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
123 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 123 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
124 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 124 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
125 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 125 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
126 | * SUCH DAMAGE. | | 126 | * SUCH DAMAGE. |
127 | * | | 127 | * |
128 | * @(#)locore.s 7.3 (Berkeley) 5/13/91 | | 128 | * @(#)locore.s 7.3 (Berkeley) 5/13/91 |
129 | */ | | 129 | */ |
130 | | | 130 | |
131 | #include <machine/asm.h> | | 131 | #include <machine/asm.h> |
132 | __KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.104 2013/06/22 15:13:55 uebayasi Exp $"); | | 132 | __KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.105 2013/06/23 03:16:46 uebayasi Exp $"); |
133 | | | 133 | |
134 | #include "opt_compat_oldboot.h" | | 134 | #include "opt_compat_oldboot.h" |
135 | #include "opt_ddb.h" | | 135 | #include "opt_ddb.h" |
136 | #include "opt_modular.h" | | 136 | #include "opt_modular.h" |
137 | #include "opt_multiboot.h" | | 137 | #include "opt_multiboot.h" |
138 | #include "opt_realmem.h" | | 138 | #include "opt_realmem.h" |
139 | #include "opt_vm86.h" | | 139 | #include "opt_vm86.h" |
140 | #include "opt_xen.h" | | 140 | #include "opt_xen.h" |
141 | | | 141 | |
142 | #include "npx.h" | | 142 | #include "npx.h" |
143 | #include "assym.h" | | 143 | #include "assym.h" |
144 | #include "lapic.h" | | 144 | #include "lapic.h" |
145 | #include "ioapic.h" | | 145 | #include "ioapic.h" |
| @@ -582,100 +582,100 @@ try586: /* Use the `cpuid' instruction. | | | @@ -582,100 +582,100 @@ try586: /* Use the `cpuid' instruction. |
582 | #else | | 582 | #else |
583 | shll $PGSHIFT,%eax | | 583 | shll $PGSHIFT,%eax |
584 | #endif | | 584 | #endif |
585 | movl %eax,RELOC(tablesize) | | 585 | movl %eax,RELOC(tablesize) |
586 | | | 586 | |
587 | /* ensure that nkptp covers bootstrap tables */ | | 587 | /* ensure that nkptp covers bootstrap tables */ |
588 | addl %esi,%eax | | 588 | addl %esi,%eax |
589 | addl $~L2_FRAME,%eax | | 589 | addl $~L2_FRAME,%eax |
590 | shrl $L2_SHIFT,%eax | | 590 | shrl $L2_SHIFT,%eax |
591 | incl %eax | | 591 | incl %eax |
592 | cmpl %eax,RELOC(nkptp)+1*4 | | 592 | cmpl %eax,RELOC(nkptp)+1*4 |
593 | jnz 1b | | 593 | jnz 1b |
594 | | | 594 | |
595 | /* Clear tables */ | | 595 | /* Clear tables */ |
596 | movl %esi,%edi | | 596 | movl %esi,%edi |
597 | xorl %eax,%eax | | 597 | xorl %eax,%eax |
598 | cld | | 598 | cld |
599 | movl RELOC(tablesize),%ecx | | 599 | movl RELOC(tablesize),%ecx |
600 | shrl $2,%ecx | | 600 | shrl $2,%ecx |
601 | rep | | 601 | rep |
602 | stosl | | 602 | stosl |
603 | | | 603 | |
604 | leal (PROC0_PTP1_OFF)(%esi), %ebx | | 604 | leal (PROC0_PTP1_OFF)(%esi), %ebx |
605 | | | 605 | |
606 | /* | | 606 | /* |
607 | * Build initial page tables. | | 607 | * Build initial page tables. |
608 | */ | | 608 | */ |
609 | /* | | 609 | /* |
610 | * Compute &__data_start - KERNBASE. This can't be > 4G, | | 610 | * Compute &__data_start - KERNBASE. This can't be > 4G, |
611 | * or we can't deal with it anyway, since we can't load it in | | 611 | * or we can't deal with it anyway, since we can't load it in |
612 | * 32 bit mode. So use the bottom 32 bits. | | 612 | * 32 bit mode. So use the bottom 32 bits. |
613 | */ | | 613 | */ |
614 | movl $RELOC(__data_start),%edx | | 614 | movl $RELOC(__data_start),%edx |
615 | andl $~PGOFSET,%edx | | 615 | andl $~PGOFSET,%edx |
616 | | | 616 | |
617 | /* | | 617 | /* |
618 | * Skip the first MB. | | 618 | * Skip the first MB. |
619 | */ | | 619 | */ |
620 | movl $_RELOC(KERNTEXTOFF),%eax | | 620 | movl $_RELOC(KERNTEXTOFF),%eax |
621 | movl %eax,%ecx | | 621 | movl %eax,%ecx |
622 | shrl $(PGSHIFT-2),%ecx /* ((n >> PGSHIFT) << 2) for # pdes */ | | 622 | shrl $(PGSHIFT-2),%ecx /* ((n >> PGSHIFT) << 2) for # pdes */ |
623 | #ifdef PAE | | 623 | #ifdef PAE |
624 | shll $1,%ecx /* pdes are twice larger with PAE */ | | 624 | shll $1,%ecx /* pdes are twice larger with PAE */ |
625 | #endif | | 625 | #endif |
626 | addl %ecx,%ebx | | 626 | addl %ecx,%ebx |
627 | | | 627 | |
628 | /* Map the kernel text read-only. */ | | 628 | /* Map the kernel text read-only. */ |
629 | movl %edx,%ecx | | 629 | movl %edx,%ecx |
630 | subl %eax,%ecx | | 630 | subl %eax,%ecx |
631 | shrl $PGSHIFT,%ecx | | 631 | shrl $PGSHIFT,%ecx |
632 | orl $(PG_V|PG_KR),%eax | | 632 | orl $(PG_V|PG_KR),%eax |
633 | fillkpt | | 633 | fillkpt |
634 | | | 634 | |
635 | /* Map the data, BSS, and bootstrap tables read-write. */ | | 635 | /* Map the data, BSS, and bootstrap tables read-write. */ |
636 | leal (PG_V|PG_KW)(%edx),%eax | | 636 | leal (PG_V|PG_KW)(%edx),%eax |
637 | movl RELOC(tablesize),%ecx | | 637 | movl RELOC(tablesize),%ecx |
638 | addl %esi,%ecx # end of tables | | 638 | addl %esi,%ecx # end of tables |
639 | subl %edx,%ecx # subtract end of text | | 639 | subl %edx,%ecx # subtract end of text |
640 | shrl $PGSHIFT,%ecx | | 640 | shrl $PGSHIFT,%ecx |
641 | fillkpt | | 641 | fillkpt |
642 | | | 642 | |
643 | /* Map ISA I/O mem (later atdevbase) */ | | 643 | /* Map ISA I/O mem (later atdevbase) */ |
644 | movl $(IOM_BEGIN|PG_V|PG_KW/*|PG_N*/),%eax # having these bits set | | 644 | movl $(IOM_BEGIN|PG_V|PG_KW/*|PG_N*/),%eax # having these bits set |
645 | movl $(IOM_SIZE>>PGSHIFT),%ecx # for this many pte s, | | 645 | movl $(IOM_SIZE>>PGSHIFT),%ecx # for this many pte s, |
646 | fillkpt | | 646 | fillkpt |
647 | | | 647 | |
648 | /* | | 648 | /* |
649 | * Construct a page table directory. | | 649 | * Construct a page table directory. |
650 | */ | | 650 | */ |
651 | /* Set up top level entries for identity mapping */ | | 651 | /* Set up top level entries for identity mapping */ |
652 | leal (PROC0_PDIR_OFF)(%esi),%ebx | | 652 | leal (PROC0_PDIR_OFF)(%esi),%ebx |
653 | leal (PROC0_PTP1_OFF)(%esi),%eax | | 653 | leal (PROC0_PTP1_OFF)(%esi),%eax |
654 | orl $(PG_V|PG_KW), %eax | | 654 | orl $(PG_V|PG_KW), %eax |
655 | movl RELOC(nkptp)+1*4,%ecx | | 655 | movl RELOC(nkptp)+1*4,%ecx |
656 | fillkpt | | 656 | fillkpt |
657 | | | 657 | |
658 | /* Set up top level entries for actual kernel mapping */ | | 658 | /* Set up top level entries for actual kernel mapping */ |
659 | leal (PROC0_PDIR_OFF + L2_SLOT_KERNBASE*PDE_SIZE)(%esi),%ebx | | 659 | leal (PROC0_PDIR_OFF + L2_SLOT_KERNBASE*PDE_SIZE)(%esi),%ebx |
660 | leal (PROC0_PTP1_OFF)(%esi),%eax | | 660 | leal (PROC0_PTP1_OFF)(%esi),%eax |
661 | orl $(PG_V|PG_KW), %eax | | 661 | orl $(PG_V|PG_KW), %eax |
662 | movl RELOC(nkptp)+1*4,%ecx | | 662 | movl RELOC(nkptp)+1*4,%ecx |
663 | fillkpt | | 663 | fillkpt |
664 | | | 664 | |
665 | /* Install a PDE recursively mapping page directory as a page table! */ | | 665 | /* Install a PDE recursively mapping page directory as a page table! */ |
666 | leal (PROC0_PDIR_OFF + PDIR_SLOT_PTE*PDE_SIZE)(%esi),%ebx | | 666 | leal (PROC0_PDIR_OFF + PDIR_SLOT_PTE*PDE_SIZE)(%esi),%ebx |
667 | leal (PROC0_PDIR_OFF)(%esi),%eax | | 667 | leal (PROC0_PDIR_OFF)(%esi),%eax |
668 | orl $(PG_V|PG_KW),%eax | | 668 | orl $(PG_V|PG_KW),%eax |
669 | movl $PDP_SIZE,%ecx | | 669 | movl $PDP_SIZE,%ecx |
670 | fillkpt | | 670 | fillkpt |
671 | | | 671 | |
672 | #ifdef PAE | | 672 | #ifdef PAE |
673 | /* Fill in proc0 L3 page with entries pointing to the page dirs */ | | 673 | /* Fill in proc0 L3 page with entries pointing to the page dirs */ |
674 | leal (PROC0_L3_OFF)(%esi),%ebx | | 674 | leal (PROC0_L3_OFF)(%esi),%ebx |
675 | leal (PROC0_PDIR_OFF)(%esi),%eax | | 675 | leal (PROC0_PDIR_OFF)(%esi),%eax |
676 | orl $(PG_V),%eax | | 676 | orl $(PG_V),%eax |
677 | movl $PDP_SIZE,%ecx | | 677 | movl $PDP_SIZE,%ecx |
678 | fillkpt | | 678 | fillkpt |
679 | | | 679 | |
680 | /* Enable PAE mode */ | | 680 | /* Enable PAE mode */ |
681 | movl %cr4,%eax | | 681 | movl %cr4,%eax |
| @@ -684,78 +684,78 @@ try586: /* Use the `cpuid' instruction. | | | @@ -684,78 +684,78 @@ try586: /* Use the `cpuid' instruction. |
684 | #endif | | 684 | #endif |
685 | | | 685 | |
686 | /* Save phys. addr of PDP, for libkvm. */ | | 686 | /* Save phys. addr of PDP, for libkvm. */ |
687 | leal (PROC0_PDIR_OFF)(%esi),%eax | | 687 | leal (PROC0_PDIR_OFF)(%esi),%eax |
688 | movl %eax,RELOC(PDPpaddr) | | 688 | movl %eax,RELOC(PDPpaddr) |
689 | | | 689 | |
690 | /* | | 690 | /* |
691 | * Startup checklist: | | 691 | * Startup checklist: |
692 | * 1. Load %cr3 with pointer to PDIR (or L3 PD page for PAE). | | 692 | * 1. Load %cr3 with pointer to PDIR (or L3 PD page for PAE). |
693 | */ | | 693 | */ |
694 | movl %esi,%eax # phys address of ptd in proc 0 | | 694 | movl %esi,%eax # phys address of ptd in proc 0 |
695 | movl %eax,%cr3 # load ptd addr into mmu | | 695 | movl %eax,%cr3 # load ptd addr into mmu |
696 | | | 696 | |
697 | /* | | 697 | /* |
698 | * 2. Enable paging and the rest of it. | | 698 | * 2. Enable paging and the rest of it. |
699 | */ | | 699 | */ |
700 | movl %cr0,%eax # get control word | | 700 | movl %cr0,%eax # get control word |
701 | # enable paging & NPX emulation | | 701 | # enable paging & NPX emulation |
702 | orl $(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_EM|CR0_MP|CR0_WP|CR0_AM),%eax | | 702 | orl $(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_EM|CR0_MP|CR0_WP|CR0_AM),%eax |
703 | movl %eax,%cr0 # and page NOW! | | 703 | movl %eax,%cr0 # and page NOW! |
704 | | | 704 | |
705 | pushl $begin # jump to high mem | | 705 | pushl $begin # jump to high mem |
706 | ret | | 706 | ret |
707 | | | 707 | |
708 | begin: | | 708 | begin: |
709 | /* | | 709 | /* |
710 | * We have arrived. | | 710 | * We have arrived. |
711 | * There's no need anymore for the identity mapping in low | | 711 | * There's no need anymore for the identity mapping in low |
712 | * memory, remove it. | | 712 | * memory, remove it. |
713 | */ | | 713 | */ |
714 | movl _C_LABEL(nkptp)+1*4,%ecx | | 714 | movl _C_LABEL(nkptp)+1*4,%ecx |
715 | leal (PROC0_PDIR_OFF)(%esi),%ebx # old, phys address of PDIR | | 715 | leal (PROC0_PDIR_OFF)(%esi),%ebx # old, phys address of PDIR |
716 | addl $(KERNBASE), %ebx # new, virtual address of PDIR | | 716 | addl $(KERNBASE), %ebx # new, virtual address of PDIR |
717 | 1: movl $0,(PDE_SIZE-4)(%ebx) # Upper bits (for PAE) | | 717 | 1: movl $0,(PDE_SIZE-4)(%ebx) # Upper bits (for PAE) |
718 | movl $0,(%ebx) | | 718 | movl $0,(%ebx) |
719 | addl $PDE_SIZE,%ebx | | 719 | addl $PDE_SIZE,%ebx |
720 | loop 1b | | 720 | loop 1b |
721 | | | 721 | |
722 | /* Relocate atdevbase. */ | | 722 | /* Relocate atdevbase. */ |
723 | movl $KERNBASE,%edx | | 723 | movl $KERNBASE,%edx |
724 | addl _C_LABEL(tablesize),%edx | | 724 | addl _C_LABEL(tablesize),%edx |
725 | addl %esi,%edx | | 725 | addl %esi,%edx |
726 | movl %edx,_C_LABEL(atdevbase) | | 726 | movl %edx,_C_LABEL(atdevbase) |
727 | | | 727 | |
728 | /* Set up bootstrap stack. */ | | 728 | /* Set up bootstrap stack. */ |
729 | leal (PROC0_STK_OFF+KERNBASE)(%esi),%eax | | 729 | leal (PROC0_STK_OFF+KERNBASE)(%esi),%eax |
730 | movl %eax,_C_LABEL(lwp0uarea) | | 730 | movl %eax,_C_LABEL(lwp0uarea) |
731 | leal (KSTACK_SIZE-FRAMESIZE)(%eax),%esp | | 731 | leal (KSTACK_SIZE-FRAMESIZE)(%eax),%esp |
732 | movl %esi,(KSTACK_SIZE+PCB_CR3)(%eax) # pcb->pcb_cr3 | | 732 | movl %esi,(KSTACK_SIZE+PCB_CR3)(%eax) # pcb->pcb_cr3 |
733 | xorl %ebp,%ebp # mark end of frames | | 733 | xorl %ebp,%ebp # mark end of frames |
734 | | | 734 | |
735 | #if defined(MULTIBOOT) | | 735 | #if defined(MULTIBOOT) |
736 | /* It is now safe to parse the Multiboot information structure | | 736 | /* It is now safe to parse the Multiboot information structure |
737 | * we saved before from C code. Note that we cannot delay its | | 737 | * we saved before from C code. Note that we cannot delay its |
738 | * parsing any more because initgdt (called below) needs to make | | 738 | * parsing any more because initgdt (called below) needs to make |
739 | * use of this information. */ | | 739 | * use of this information. */ |
740 | call _C_LABEL(multiboot_post_reloc) | | 740 | call _C_LABEL(multiboot_post_reloc) |
741 | #endif | | 741 | #endif |
742 | | | 742 | |
743 | subl $NGDT*8, %esp # space for temporary gdt | | 743 | subl $NGDT*8, %esp # space for temporary gdt |
744 | pushl %esp | | 744 | pushl %esp |
745 | call _C_LABEL(initgdt) | | 745 | call _C_LABEL(initgdt) |
746 | addl $4,%esp | | 746 | addl $4,%esp |
747 | | | 747 | |
748 | movl _C_LABEL(tablesize),%eax | | 748 | movl _C_LABEL(tablesize),%eax |
749 | addl %esi,%eax # skip past stack and page tables | | 749 | addl %esi,%eax # skip past stack and page tables |
750 | | | 750 | |
751 | #ifdef PAE | | 751 | #ifdef PAE |
752 | pushl $0 # init386() expects a 64 bits paddr_t with PAE | | 752 | pushl $0 # init386() expects a 64 bits paddr_t with PAE |
753 | #endif | | 753 | #endif |
754 | pushl %eax | | 754 | pushl %eax |
755 | call _C_LABEL(init386) # wire 386 chip for unix operation | | 755 | call _C_LABEL(init386) # wire 386 chip for unix operation |
756 | addl $PDE_SIZE,%esp # pop paddr_t | | 756 | addl $PDE_SIZE,%esp # pop paddr_t |
757 | addl $NGDT*8,%esp # pop temporary gdt | | 757 | addl $NGDT*8,%esp # pop temporary gdt |
758 | | | 758 | |
759 | #ifdef SAFARI_FIFO_HACK | | 759 | #ifdef SAFARI_FIFO_HACK |
760 | movb $5,%al | | 760 | movb $5,%al |
761 | movw $0x37b,%dx | | 761 | movw $0x37b,%dx |
| @@ -774,35 +774,35 @@ begin: | | | @@ -774,35 +774,35 @@ begin: |
774 | outb %al,%dx | | 774 | outb %al,%dx |
775 | #endif /* SAFARI_FIFO_HACK */ | | 775 | #endif /* SAFARI_FIFO_HACK */ |
776 | | | 776 | |
777 | call _C_LABEL(main) | | 777 | call _C_LABEL(main) |
778 | #else /* XEN */ | | 778 | #else /* XEN */ |
779 | /* First, reset the PSL. */ | | 779 | /* First, reset the PSL. */ |
780 | pushl $PSL_MBO | | 780 | pushl $PSL_MBO |
781 | popfl | | 781 | popfl |
782 | | | 782 | |
783 | cld | | 783 | cld |
784 | movl %esp, %ebx # save start of available space | | 784 | movl %esp, %ebx # save start of available space |
785 | movl $_RELOC(tmpstk),%esp # bootstrap stack end location | | 785 | movl $_RELOC(tmpstk),%esp # bootstrap stack end location |
786 | | | 786 | |
787 | /* Clear BSS first so that there are no surprises... */ | | 787 | /* Clear BSS first so that there are no surprises... */ |
788 | xorl %eax,%eax | | 788 | xorl %eax,%eax |
789 | movl $RELOC(__bss_start),%edi | | 789 | movl $RELOC(__bss_start),%edi |
790 | movl $RELOC(_end),%ecx | | 790 | movl $RELOC(_end),%ecx |
791 | subl %edi,%ecx | | 791 | subl %edi,%ecx |
792 | rep stosb | | 792 | rep stosb |
793 | | | 793 | |
794 | /* Copy the necessary stuff from start_info structure. */ | | 794 | /* Copy the necessary stuff from start_info structure. */ |
795 | /* We need to copy shared_info early, so that sti/cli work */ | | 795 | /* We need to copy shared_info early, so that sti/cli work */ |
796 | movl $RELOC(start_info_union),%edi | | 796 | movl $RELOC(start_info_union),%edi |
797 | movl $128,%ecx | | 797 | movl $128,%ecx |
798 | rep movsl | | 798 | rep movsl |
799 | | | 799 | |
800 | /* Clear segment registers; always null in proc0. */ | | 800 | /* Clear segment registers; always null in proc0. */ |
801 | xorl %eax,%eax | | 801 | xorl %eax,%eax |
802 | movw %ax,%fs | | 802 | movw %ax,%fs |
803 | movw %ax,%gs | | 803 | movw %ax,%gs |
804 | decl %eax | | 804 | decl %eax |
805 | movl %eax,RELOC(cpuid_level) | | 805 | movl %eax,RELOC(cpuid_level) |
806 | | | 806 | |
807 | xorl %eax,%eax | | 807 | xorl %eax,%eax |
808 | cpuid | | 808 | cpuid |