Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/boot/boot.S need to be fixed.

0001 /* -*- Mode: asm; comment-start: "\/*"; comment-end: "*\/"; indent-tabs-mode: nil -*- */
0002 /*                    The Quest Operating System
0003  *  Copyright (C) 2005-2010  Richard West, Boston University
0004  *
0005  *  This program is free software: you can redistribute it and/or modify
0006  *  it under the terms of the GNU General Public License as published by
0007  *  the Free Software Foundation, either version 3 of the License, or
0008  *  (at your option) any later version.
0009  *
0010  *  This program is distributed in the hope that it will be useful,
0011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013  *  GNU General Public License for more details.
0014  *
0015  *  You should have received a copy of the GNU General Public License
0016  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0017  */
0018 
0019 /*
0020  * boot.S
0021  *
0022  *
0023  * NOTE:         All references to Intel documentation are from the manuals
0024  *               dated 1997-2001. Updated book versions may be on-line.
0025  */
0026 
0027 
0028 #include "kernel.h"
0029 
0030         .globl initial_gdt
0031 
0032         .bss
0033         .align 0x1000 /* align page directory on 4K boundary - 2-12 Manual vol 3 */
0034         .comm pgd, 0x1000   /* setup 4Kbytes for page global directory */
0035 
0036         .align 0x1000
0037         .comm idt, 0x1000   /* setup 4Kbytes for IDT+GDT */
0038 
0039         .align 0x1000
0040         .comm kern_pg_table, 0x1000 /* setup 4Kbytes for kernel page table */
0041 
0042         .align 0x1000
0043         .comm tmp_stack, 0x1000
0044 
0045         .data
0046         .align 4
0047 initial_gdt:
0048         /* null descriptor -- 1st entry not used -- see Manual 3-16 vol 3 */
0049         .long 0
0050         .long 0
0051 
0052         /* Kernel CS */
0053         /* code descriptor - base 0, limit 0xFFFFFFFF, 32-bit, readable, ring 0 */
0054         .long 0x0000FFFF
0055         .long 0x00CF9A00
0056 
0057         /* Kernel DS */
0058         /* data descriptor - base 0, limit 0xFFFFFFFF, 32-bit, writable, ring 0 */
0059         .long 0x0000FFFF
0060         .long 0x00CF9200
0061 
0062         /* User CS */
0063         /* code descriptor - base 0, limit 0xBFFFFFFF, 32-bit, readable, ring 3 */
0064         .long 0x0000FFFF
0065         .long 0x00CBFA00
0066         /* User DS */
0067         /* data descriptor - base 0, limit 0xBFFFFFFF, 32-bit, writable, ring 3 */
0068         .long 0x0000FFFF
0069         .long 0x00CBF200
0070 
0071 gdt_ptr:
0072         .short 0x7FF     /* length in bytes - 256 descriptors */
0073         .long KERN_GDT   /* linear address */
0074 
0075         .globl idt_ptr
0076 idt_ptr:
0077         .short 0x7FF     /* length - 256 descriptors */
0078         .long KERN_IDT   /* linear address */
0079 
0080 
0081         .text
0082         .globl _start
0083 
0084 _start:
0085         jmp real_start
0086 
0087         /* Multiboot header -- Safe to place this header in 1st page for GRUB */
0088         .align 4
0089         .long 0x1BADB002 /* Multiboot magic number */
0090         .long 0x00000003 /* Align modules to 4KB, req. mem size */
0091                          /* See 'info multiboot' for further info */
0092         .long 0xE4524FFB /* Checksum */
0093 
0094 real_start:
0095 
0096         /* turn on Bochs debugging using I/O ports */
0097         movw $0x8A00, %ax
0098         movw $0x8A00, %dx
0099         outw %ax, (%dx)
0100         
0101         /* set up stack */
0102         movl $tmp_stack+0x1000, %esp /* setup temp stack */
0103 
0104         /* save multiboot parameter, for eventual call to C code */
0105         pushl %ebx
0106 
0107         /* initialise EFLAGS */
0108         pushl $2 /* Bit 1 always set to 1 in EFLAGS -- all other bits set to 0 */
0109         popf     /* See 2-8 Manual vol 3 */
0110 
0111         /* set up GDT */
0112         movl $idt, %edi
0113         addl $0x800, %edi /* 2KB offset of GDT from IDT */
0114         movl $initial_gdt, %esi
0115         movl $10, %ecx /* setup 5 segment descriptors of 64-bits each */
0116         rep movsl
0117         lgdt gdt_ptr /* pass address of 6-byte object */
0118 
0119         /* call realmodetest */
0120 
0121         /* set up support for 4MB paging */
0122         movl %cr4, %eax /* EAX is temporary for CR4 */
0123         orl $0x10, %eax /* Set PSE bit of CR4 */
0124         movl %eax, %cr4
0125 
0126         /* Setup 1st page directory entry for super-paging */
0127         movl $0x83, %eax
0128         movl %eax, pgd
0129 
0130         /* LAPIC address mapping - 4MB page @ 0xFEC00000 */
0131         movl $0xFEC00083, %eax
0132         movl %eax, pgd+0xFEC
0133 
0134         /* Set 1024th (top) entry in PGD to reference kern_pg_table
0135          * Here, we have 1 4MB superpage for the entire kernel
0136          */
0137         movl $kern_pg_table+3, %eax /* +3=>present and r/w */
0138         movl %eax, pgd+0xFFC /* --WARN-- Hardcoded pgd offset */
0139 
0140         /* Add page table entries for kernel portion at high virtual addresses
0141          * Here, we have 1024x4KB page table entries for the kernel
0142          */
0143         movl $kern_pg_table, %edi
0144         movl $_physicalkernelstart, %eax
0145         orl $0x1, %eax /* present bit set in page */
0146         movl $_readonly_pages, %ecx
0147 1:      stosl
0148         addl $0x1000, %eax
0149         loop 1b
0150 
0151         orl $0x3, %eax /* present and read/write bits set in each page */
0152         movl $_readwrite_pages, %ecx
0153 1:      stosl
0154         addl $0x1000, %eax
0155         loop 1b
0156 
0157         /* Setup entry in kernel page table for KERNEL IDT/GDT */
0158         movl $idt+3, %eax /* idt is page aligned in bss -
0159                            * set physical address in
0160                            * kernel page table:
0161                            * +3 indicates present/write-enabled
0162                            */
0163 
0164         /* NOTE: shift 10 bits rather than 12 due to kern_pg_table being
0165            array of ints */
0166         movl %eax, kern_pg_table + ( ( KERN_IDT >> 10 ) & 0x0FFF )
0167 
0168         /* Here, remap kern_pg_table to high virtual memory to be
0169            accessible later by user-level code via syscalls */
0170         movl $kern_pg_table+3, %eax
0171         movl %eax, kern_pg_table + ( ( KERN_PGT >> 10 ) & 0x0FFF )
0172 
0173         /* This is for mapping screen memory into kernel for screen dumps */
0174         movl $0x000B8003, %eax
0175         movl %eax, kern_pg_table + ( ( KERN_SCR >> 10 ) & 0x0FFF )
0176 
0177         /* enable paging */
0178         movl $pgd, %eax
0179         movl %eax, %cr3
0180         movl %cr0, %eax /* need to set bit 31 of CR0 - see 3-18 in Manual vol 3 */
0181         orl $0x80000000, %eax
0182         movl %eax, %cr0
0183 
0184         /* Manual vol 3 pg 8-14: Need a far jump after initializing CR0 */
0185         ljmp $0x08,$1f /* Seg selector: index=1,TI=0,RPL=00 for Kernel CS
0186                                         AT&T syntax req'res comma-separated offset */
0187 1:
0188 
0189         /* Setup remaining segment selectors */
0190         movw $0x10, %ax /* Set DS-SS to refer to KERNEL DS */
0191         movw %ax, %ds
0192         movw %ax, %es
0193         movw %ax, %fs
0194         movw %ax, %gs
0195         movw %ax, %ss
0196 
0197         /* no LDT */
0198         xorw %ax, %ax
0199         lldt %ax
0200 
0201         /* set up IDT by constructing 64-bit interrupt descriptors */
0202         movl $KERN_IDT, %edi
0203         movl $0x100, %ecx /* Set counter for 256 IDT entries */
0204         movl $0x080000,%edx /* Used to index KERNEL CS */
0205         movl $int_table,%esi
0206 
0207         /* For now populate int_table w/ interrupt gate descriptors.
0208          * These clear the IF flag when invoked
0209          */
0210 1:
0211         lodsl
0212         movw %ax,%dx
0213         movw $0xEE00,%ax /* DPL = 11 -- is that right? */
0214         movl %edx,(%edi) /* Store bottom 32-bits of descriptor in EDX into IDT */
0215         addl $4,%edi
0216         stosl /* Store top 32-bits of descriptor held in EAX into IDT */
0217         loop 1b
0218 
0219         lidt idt_ptr
0220 
0221         popl %ebx
0222         movl $stack+0x1000, %esp      /* setup real C stack */
0223         pushl %ebx                      /* pass GRUB multiboot info */
0224         call init /* start of C code */
0225 
0226 realmodetest:
0227         push %ebp
0228         movl %esp, %ebp
0229         movl $_code16physicalstart, %esi
0230         movl $_code16start, %edi
0231         movl $_code16_pages, %ecx
0232         shll $12, %ecx
0233         rep movsb
0234 
0235         movl $realmodestub, %esi
0236         movl $0x7c00, %edi
0237         movl realmodestub_len, %ecx
0238         rep movsb
0239 
0240         lgdt 0x7c00 + realmodegdtdesc - realmodestub
0241         movw $0x20, %ax
0242         movw %ax, %ds
0243         movw %ax, %es
0244         movw %ax, %fs
0245         movw %ax, %gs
0246         movw %ax, %ss
0247 
0248         ljmp $0x18, $0x7c00
0249 
0250 1:      jmp 1b
0251         ret
0252 
0253         .code16
0254 realmodestub:
0255         /* disable pmode */
0256         movl %cr0, %eax
0257         andb $0xFE, %al
0258         movl %eax, %cr0
0259 
0260         data32 ljmp $0x0, $1f
0261 1:
0262         xorw %ax, %ax
0263         movw %ax, %ds
0264         movw %ax, %es
0265         movw %ax, %fs
0266         movw %ax, %gs
0267         movw %ax, %ss
0268         movw $0x9000, %sp
0269         lidt 0x7c00 + ivt - realmodestub
0270         sti
0271         ljmp $0x0, $_code16start
0272 ivt:    .short 0x3ff
0273         .long  0x0
0274         .p2align        2       /* force 4-byte alignment */
0275 realmodegdt:
0276         .word   0, 0
0277         .byte   0, 0, 0, 0
0278 
0279         /* -- code segment --
0280          * base = 0x00000000, limit = 0xFFFFF (4 KiB Granularity), present
0281          * type = 32bit code execute/read, DPL = 0
0282          */
0283         .word   0xFFFF, 0
0284         .byte   0, 0x9A, 0xCF, 0
0285 
0286         /* -- data segment --
0287          * base = 0x00000000, limit 0xFFFFF (4 KiB Granularity), present
0288          * type = 32 bit data read/write, DPL = 0
0289          */
0290         .word   0xFFFF, 0
0291         .byte   0, 0x92, 0xCF, 0
0292 
0293         /* -- 16 bit real mode CS --
0294          * base = 0x00000000, limit 0x0FFFF (1 B Granularity), present
0295          * type = 16 bit code execute/read only/conforming, DPL = 0
0296          */
0297         .word   0xFFFF, 0
0298         .byte   0, 0x9E, 0, 0
0299 
0300         /* -- 16 bit real mode DS --
0301          * base = 0x00000000, limit 0x0FFFF (1 B Granularity), present
0302          * type = 16 bit data read/write, DPL = 0
0303          */
0304         .word   0xFFFF, 0
0305         .byte   0, 0x92, 0, 0
0306 realmodegdtdesc:
0307         .word   0x27                    /* limit */
0308         .long   realmodegdt             /* addr */
0309 realmodestub_len:
0310         .long . - realmodestub
0311         .code32
0312 
0313 int_table:
0314         /* interrupts 0x00-0x1F - processor traps */
0315         .long interrupt0
0316         .long interrupt1
0317         .long interrupt2
0318         .long interrupt3
0319         .long interrupt4
0320         .long interrupt5
0321         .long interrupt6
0322         .long interrupt7
0323         .long interrupt8
0324         .long interrupt9
0325         .long interrupta
0326         .long interruptb
0327         .long interruptc
0328         .long interruptd
0329         .long interrupte
0330         .long interruptIGN      /* spurious interrupt */
0331         .long interrupt10
0332         .long interrupt11
0333         .long interrupt12
0334         .long interrupt13
0335         .long interrupt14
0336         .long interrupt15
0337         .long interrupt16
0338         .long interrupt17
0339         .long interrupt18
0340         .long interrupt19
0341         .long interrupt1a
0342         .long interrupt1b
0343         .long interrupt1c
0344         .long interrupt1d
0345         .long interrupt1e
0346         .long interrupt1f
0347 
0348         /* interrupts 0x20-0x2F - PIC/IRQ interrupt requests */
0349         .long timer             /* PIT */
0350         .long interrupt21
0351         .long interrupt22
0352         .long interrupt23
0353         .long interrupt24
0354         .long soundcard         /* soundcard --??-- in future,
0355                                    don't hardcode IRQ of soundcard */
0356         .long interrupt26
0357         .long interrupt27
0358         .long interrupt28
0359         .long interrupt29
0360         .long interrupt2a
0361         .long interrupt2b
0362         .long interrupt2c
0363         .long interrupt2d
0364         .long interrupt2e      /* not sure why 2E gets triggered sometimes */
0365         .long interrupt2f
0366 
0367         /* interrupts 0x30-0x3F - system calls */
0368         .long syscall0          /* putchar style call to video server */
0369         .long syscall1          /* fork */
0370         .long syscall2          /* switch_to -- co-routine-style context-switching */
0371         .long syscall3          /* exec */
0372         .long syscall4          /* getchar style call to keyboard driver */
0373         .long syscall5          /* open */
0374         .long syscall6          /* read */
0375         .long syscall7          /* uname */
0376         .long syscall8          /* meminfo */
0377         .long syscall9          /* time */
0378         .long syscalla          /* _exit */
0379         .long syscallb          /* waitpid */
0380         .long syscallc          /* sched_setparam -- not totally POSIX compliant */
0381         .long interrupt3d
0382         .long interrupt3e
0383         .long interrupt3f
0384 #define INT(n)     .long interrupt##n
0385 INT(40)
0386 INT(41)
0387 INT(42)
0388 INT(43)
0389 INT(44)
0390 INT(45)
0391 INT(46)
0392 INT(47)
0393 INT(48)
0394 INT(49)
0395 INT(4a)
0396 INT(4b)
0397 INT(4c)
0398 INT(4d)
0399 INT(4e)
0400 INT(4f)
0401 INT(50)
0402 INT(51)
0403 INT(52)
0404 INT(53)
0405 INT(54)
0406 INT(55)
0407 INT(56)
0408 INT(57)
0409 INT(58)
0410 INT(59)
0411 INT(5a)
0412 INT(5b)
0413 INT(5c)
0414 INT(5d)
0415 INT(5e)
0416 INT(5f)
0417 INT(60)
0418 INT(61)
0419 INT(62)
0420 INT(63)
0421 INT(64)
0422 INT(65)
0423 INT(66)
0424 INT(67)
0425 INT(68)
0426 INT(69)
0427 INT(6a)
0428 INT(6b)
0429 INT(6c)
0430 INT(6d)
0431 INT(6e)
0432 INT(6f)
0433 INT(70)
0434 INT(71)
0435 INT(72)
0436 INT(73)
0437 INT(74)
0438 INT(75)
0439 INT(76)
0440 INT(77)
0441 INT(78)
0442 INT(79)
0443 INT(7a)
0444 INT(7b)
0445 INT(7c)
0446 INT(7d)
0447 INT(7e)
0448 INT(7f)
0449 INT(80)
0450 INT(81)
0451 INT(82)
0452 INT(83)
0453 INT(84)
0454 INT(85)
0455 INT(86)
0456 INT(87)
0457 INT(88)
0458 INT(89)
0459 INT(8a)
0460 INT(8b)
0461 INT(8c)
0462 INT(8d)
0463 INT(8e)
0464 INT(8f)
0465 INT(90)
0466 INT(91)
0467 INT(92)
0468 INT(93)
0469 INT(94)
0470 INT(95)
0471 INT(96)
0472 INT(97)
0473 INT(98)
0474 INT(99)
0475 INT(9a)
0476 INT(9b)
0477 INT(9c)
0478 INT(9d)
0479 INT(9e)
0480 INT(9f)
0481 INT(a0)
0482 INT(a1)
0483 INT(a2)
0484 INT(a3)
0485 INT(a4)
0486 INT(a5)
0487 INT(a6)
0488 INT(a7)
0489 INT(a8)
0490 INT(a9)
0491 INT(aa)
0492 INT(ab)
0493 INT(ac)
0494 INT(ad)
0495 INT(ae)
0496 INT(af)
0497 INT(b0)
0498 INT(b1)
0499 INT(b2)
0500 INT(b3)
0501 INT(b4)
0502 INT(b5)
0503 INT(b6)
0504 INT(b7)
0505 INT(b8)
0506 INT(b9)
0507 INT(ba)
0508 INT(bb)
0509 INT(bc)
0510 INT(bd)
0511 INT(be)
0512 INT(bf)
0513 INT(c0)
0514 INT(c1)
0515 INT(c2)
0516 INT(c3)
0517 INT(c4)
0518 INT(c5)
0519 INT(c6)
0520 INT(c7)
0521 INT(c8)
0522 INT(c9)
0523 INT(ca)
0524 INT(cb)
0525 INT(cc)
0526 INT(cd)
0527 INT(ce)
0528 INT(cf)
0529 INT(d0)
0530 INT(d1)
0531 INT(d2)
0532 INT(d3)
0533 INT(d4)
0534 INT(d5)
0535 INT(d6)
0536 INT(d7)
0537 INT(d8)
0538 INT(d9)
0539 INT(da)
0540 INT(db)
0541 INT(dc)
0542 INT(dd)
0543 INT(de)
0544 INT(df)
0545 INT(e0)
0546 INT(e1)
0547 INT(e2)
0548 INT(e3)
0549 INT(e4)
0550 INT(e5)
0551 INT(e6)
0552 INT(e7)
0553 INT(e8)
0554 INT(e9)
0555 INT(ea)
0556 INT(eb)
0557 INT(ec)
0558 INT(ed)
0559 INT(ee)
0560 INT(ef)
0561 INT(f0)
0562 INT(f1)
0563 INT(f2)
0564 INT(f3)
0565 INT(f4)
0566 INT(f5)
0567 INT(f6)
0568 INT(f7)
0569 INT(f8)
0570 INT(f9)
0571 INT(fa)
0572 INT(fb)
0573 INT(fc)
0574 INT(fd)
0575 INT(fe)
0576 INT(ff)
0577 #undef INT
0578 
0579 /* vi: set et sw=8 sts=8: */