mirror of
https://github.com/SmallPond/MIT6.828_OS.git
synced 2026-04-24 10:50:27 +08:00
LAB 4 IS DONE.
This commit is contained in:
170
lab/kern/init.c
Normal file
170
lab/kern/init.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/* See COPYRIGHT for copyright information. */
|
||||
|
||||
#include <inc/stdio.h>
|
||||
#include <inc/string.h>
|
||||
#include <inc/assert.h>
|
||||
|
||||
#include <kern/monitor.h>
|
||||
#include <kern/console.h>
|
||||
#include <kern/pmap.h>
|
||||
#include <kern/kclock.h>
|
||||
#include <kern/env.h>
|
||||
#include <kern/trap.h>
|
||||
#include <kern/sched.h>
|
||||
#include <kern/picirq.h>
|
||||
#include <kern/cpu.h>
|
||||
#include <kern/spinlock.h>
|
||||
|
||||
static void boot_aps(void);
|
||||
|
||||
|
||||
void
|
||||
i386_init(void)
|
||||
{
|
||||
// Initialize the console.
|
||||
// Can't call cprintf until after we do this!
|
||||
cons_init();
|
||||
|
||||
cprintf("6828 decimal is %o octal!\n", 6828);
|
||||
|
||||
// Lab 2 memory management initialization functions
|
||||
mem_init();
|
||||
|
||||
// Lab 3 user environment initialization functions
|
||||
env_init();
|
||||
trap_init();
|
||||
|
||||
// Lab 4 multiprocessor initialization functions
|
||||
mp_init();
|
||||
lapic_init();
|
||||
|
||||
// Lab 4 multitasking initialization functions
|
||||
pic_init();
|
||||
|
||||
// Acquire the big kernel lock before waking up APs
|
||||
// Your code here:
|
||||
lock_kernel();
|
||||
// Starting non-boot CPUs
|
||||
boot_aps();
|
||||
|
||||
#if defined(TEST)
|
||||
// Don't touch -- used by grading script!
|
||||
ENV_CREATE(TEST, ENV_TYPE_USER);
|
||||
#else
|
||||
// Touch all you want.
|
||||
//ENV_CREATE(user_primes, ENV_TYPE_USER);
|
||||
ENV_CREATE(user_yield, ENV_TYPE_USER);
|
||||
ENV_CREATE(user_yield, ENV_TYPE_USER);
|
||||
ENV_CREATE(user_yield, ENV_TYPE_USER);
|
||||
ENV_CREATE(user_yield, ENV_TYPE_USER);
|
||||
|
||||
|
||||
#endif // TEST*
|
||||
|
||||
// Schedule and run the first user environment!
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
// While boot_aps is booting a given CPU, it communicates the per-core
|
||||
// stack pointer that should be loaded by mpentry.S to that CPU in
|
||||
// this variable.
|
||||
void *mpentry_kstack;
|
||||
|
||||
// Start the non-boot (AP) processors.
|
||||
static void
|
||||
boot_aps(void)
|
||||
{
|
||||
extern unsigned char mpentry_start[], mpentry_end[];
|
||||
void *code;
|
||||
struct CpuInfo *c;
|
||||
|
||||
// Write entry code to unused memory at MPENTRY_PADDR
|
||||
code = KADDR(MPENTRY_PADDR);
|
||||
memmove(code, mpentry_start, mpentry_end - mpentry_start);
|
||||
|
||||
// Boot each AP one at a time
|
||||
for (c = cpus; c < cpus + ncpu; c++) {
|
||||
if (c == cpus + cpunum()) // We've started already.
|
||||
continue;
|
||||
|
||||
// Tell mpentry.S what stack to use
|
||||
mpentry_kstack = percpu_kstacks[c - cpus] + KSTKSIZE;
|
||||
// Start the CPU at mpentry_start
|
||||
lapic_startap(c->cpu_id, PADDR(code));
|
||||
// Wait for the CPU to finish some basic setup in mp_main()
|
||||
while(c->cpu_status != CPU_STARTED)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
// Setup code for APs
|
||||
void
|
||||
mp_main(void)
|
||||
{
|
||||
// We are in high EIP now, safe to switch to kern_pgdir
|
||||
lcr3(PADDR(kern_pgdir));
|
||||
cprintf("SMP: CPU %d starting\n", cpunum());
|
||||
|
||||
lapic_init();
|
||||
env_init_percpu();
|
||||
trap_init_percpu();
|
||||
xchg(&thiscpu->cpu_status, CPU_STARTED); // tell boot_aps() we're up
|
||||
|
||||
// Now that we have finished some basic setup, call sched_yield()
|
||||
// to start running processes on this CPU. But make sure that
|
||||
// only one CPU can enter the scheduler at a time!
|
||||
//
|
||||
// Your code here:
|
||||
lock_kernel();
|
||||
|
||||
sched_yield();
|
||||
// Remove this after you finish Exercise 6
|
||||
for (;;);
|
||||
}
|
||||
|
||||
/*
|
||||
* Variable panicstr contains argument to first call to panic; used as flag
|
||||
* to indicate that the kernel has already called panic.
|
||||
*/
|
||||
const char *panicstr;
|
||||
|
||||
/*
|
||||
* Panic is called on unresolvable fatal errors.
|
||||
* It prints "panic: mesg", and then enters the kernel monitor.
|
||||
*/
|
||||
void
|
||||
_panic(const char *file, int line, const char *fmt,...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (panicstr)
|
||||
goto dead;
|
||||
panicstr = fmt;
|
||||
|
||||
// Be extra sure that the machine is in as reasonable state
|
||||
asm volatile("cli; cld");
|
||||
|
||||
va_start(ap, fmt);
|
||||
cprintf("kernel panic on CPU %d at %s:%d: ", cpunum(), file, line);
|
||||
vcprintf(fmt, ap);
|
||||
cprintf("\n");
|
||||
va_end(ap);
|
||||
|
||||
dead:
|
||||
/* break into the kernel monitor */
|
||||
while (1)
|
||||
monitor(NULL);
|
||||
}
|
||||
|
||||
/* like panic, but don't */
|
||||
void
|
||||
_warn(const char *file, int line, const char *fmt,...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
cprintf("kernel warning at %s:%d: ", file, line);
|
||||
vcprintf(fmt, ap);
|
||||
cprintf("\n");
|
||||
va_end(ap);
|
||||
}
|
||||
Reference in New Issue
Block a user