mirror of
https://github.com/SmallPond/MIT6.828_OS.git
synced 2026-05-11 18:47:07 +08:00
LAB 4 IS DONE.
This commit is contained in:
97
lab/kern/mpentry.S
Normal file
97
lab/kern/mpentry.S
Normal file
@@ -0,0 +1,97 @@
|
||||
/* See COPYRIGHT for copyright information. */
|
||||
|
||||
#include <inc/mmu.h>
|
||||
#include <inc/memlayout.h>
|
||||
|
||||
###################################################################
|
||||
# entry point for APs
|
||||
###################################################################
|
||||
|
||||
# Each non-boot CPU ("AP") is started up in response to a STARTUP
|
||||
# IPI from the boot CPU. Section B.4.2 of the Multi-Processor
|
||||
# Specification says that the AP will start in real mode with CS:IP
|
||||
# set to XY00:0000, where XY is an 8-bit value sent with the
|
||||
# STARTUP. Thus this code must start at a 4096-byte boundary.
|
||||
#
|
||||
# Because this code sets DS to zero, it must run from an address in
|
||||
# the low 2^16 bytes of physical memory.
|
||||
#
|
||||
# boot_aps() (in init.c) copies this code to MPENTRY_PADDR (which
|
||||
# satisfies the above restrictions). Then, for each AP, it stores the
|
||||
# address of the pre-allocated per-core stack in mpentry_kstack, sends
|
||||
# the STARTUP IPI, and waits for this code to acknowledge that it has
|
||||
# started (which happens in mp_main in init.c).
|
||||
#
|
||||
# This code is similar to boot/boot.S except that
|
||||
# - it does not need to enable A20
|
||||
# - it uses MPBOOTPHYS to calculate absolute addresses of its
|
||||
# symbols, rather than relying on the linker to fill them
|
||||
|
||||
#define RELOC(x) ((x) - KERNBASE)
|
||||
#define MPBOOTPHYS(s) ((s) - mpentry_start + MPENTRY_PADDR)
|
||||
|
||||
.set PROT_MODE_CSEG, 0x8 # kernel code segment selector
|
||||
.set PROT_MODE_DSEG, 0x10 # kernel data segment selector
|
||||
|
||||
.code16
|
||||
.globl mpentry_start
|
||||
mpentry_start:
|
||||
cli
|
||||
|
||||
xorw %ax, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %ss
|
||||
|
||||
lgdt MPBOOTPHYS(gdtdesc)
|
||||
movl %cr0, %eax
|
||||
orl $CR0_PE, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
ljmpl $(PROT_MODE_CSEG), $(MPBOOTPHYS(start32))
|
||||
|
||||
.code32
|
||||
start32:
|
||||
movw $(PROT_MODE_DSEG), %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %ss
|
||||
movw $0, %ax
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
|
||||
# Set up initial page table. We cannot use kern_pgdir yet because
|
||||
# we are still running at a low EIP.
|
||||
movl $(RELOC(entry_pgdir)), %eax
|
||||
movl %eax, %cr3
|
||||
# Turn on paging.
|
||||
movl %cr0, %eax
|
||||
orl $(CR0_PE|CR0_PG|CR0_WP), %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
# Switch to the per-cpu stack allocated in boot_aps()
|
||||
movl mpentry_kstack, %esp
|
||||
movl $0x0, %ebp # nuke frame pointer
|
||||
|
||||
# Call mp_main(). (Exercise for the reader: why the indirect call?)
|
||||
movl $mp_main, %eax
|
||||
call *%eax
|
||||
|
||||
# If mp_main returns (it shouldn't), loop.
|
||||
spin:
|
||||
jmp spin
|
||||
|
||||
# Bootstrap GDT
|
||||
.p2align 2 # force 4 byte alignment
|
||||
gdt:
|
||||
SEG_NULL # null seg
|
||||
SEG(STA_X|STA_R, 0x0, 0xffffffff) # code seg
|
||||
SEG(STA_W, 0x0, 0xffffffff) # data seg
|
||||
|
||||
gdtdesc:
|
||||
.word 0x17 # sizeof(gdt) - 1
|
||||
.long MPBOOTPHYS(gdt) # address gdt
|
||||
|
||||
.globl mpentry_end
|
||||
mpentry_end:
|
||||
nop
|
||||
Reference in New Issue
Block a user