コード例 #1
0
ファイル: init.c プロジェクト: wwffcc/ThuMips32
int
kern_init(void) {
    extern char edata[], end[];
    memset(edata, 0, end - edata);

    cons_init();                // init the console

    const char *message = "(THU.CST) os is loading ...";
    cprintf("%s\n\n", message);

    print_kerninfo();

    grade_backtrace();

    pic_init();                 // init interrupt controller
    idt_init();                 // init interrupt descriptor table

    pmm_init();                 // init physical memory management

    vmm_init();                 // init virtual memory management
    sched_init();               // init scheduler
    proc_init();                // init process table
    
    swap_init();                // init swap
    fs_init();                  // init fs
    
    clock_init();               // init clock interrupt
    intr_enable();              // enable irq interrupt

    //LAB1: CAHLLENGE 1 If you try to do it, uncomment lab1_switch_test()
    // user/kernel mode switch test
    //lab1_switch_test();
    
    cpu_idle();                 // run idle process
}
コード例 #2
0
ファイル: main.c プロジェクト: argsno/ucore_os_plus
/**
 * The entry.
 */
int main(int argc, char *argv[], char *envp[])
{
    if (ginfo->status == STATUS_DEBUG)
        raise(SIGTRAP);

    cons_init();

    const char *message = "(THU.CST) os is loading ...";
    kprintf("%s\n\n", message);

    intr_init();
    ide_init();

    host_signal_init();

    /* Only to initialize lcpu_count. */
    mp_init();

    pmm_init();
    pmm_init_ap();
    vmm_init();
    sched_init();
    proc_init();

    swap_init();
    fs_init();
    sync_init();

    umclock_init();
    cpu_idle();

    host_exit(SIGINT);

    return 0;
}
コード例 #3
0
ファイル: init.c プロジェクト: PungiZhang/ucore_plus-next
int
kern_init(void) {
    extern char edata[], end[];
    memset(edata, 0, end - edata);
	
    cons_init();                // init the console

    const char *message = "(THU.CST) os is loading ...";
    kprintf ("%s\n\n", message);

	/* Only to initialize lcpu_count. */
	mp_init ();

	pmm_init();                 // init physical memory management
	pmm_init_ap ();

    pic_init();                 // init interrupt controller

	vmm_init();                 // init virtual memory management
    sched_init();               // init scheduler
	proc_init();                // init process table
    sync_init();                // init sync struct
	
	ide_init();                 // init ide devices
    swap_init();                // init swap
    fs_init();                  // init fs

    clock_init();               // init clock interrupt
    intr_enable();              // enable irq interrupt    

    cpu_idle();                 // run idle process
}
コード例 #4
0
ファイル: init.c プロジェクト: spinlock/ucore
int __noreturn
kern_init(void) {
    extern char edata[], end[];
    memset(edata, 0, end - edata);

    cons_init();                // init the console

    const char *message = "(THU.CST) os is loading ...";
    cprintf("%s\n\n", message);

    print_kerninfo();

    pmm_init();                 // init physical memory management

    pic_init();                 // init interrupt controller
    idt_init();                 // init interrupt descriptor table

    vmm_init();                 // init virtual memory management
    sched_init();               // init scheduler
    proc_init();                // init process table
    sync_init();                // init sync struct

    ide_init();                 // init ide devices
    swap_init();                // init swap
    fs_init();                  // init fs

    clock_init();               // init clock interrupt
    intr_enable();              // enable irq interrupt

    cpu_idle();                 // run idle process
}
コード例 #5
0
void frame_init(){
  lock_init(&framelock);
    /* SPT_init(); */
  lock_init(&filesys_lock2);
  lock_init (&mapids_lock);
  list_init (&framelist);
  swap_init();
}
コード例 #6
0
ファイル: mivm.c プロジェクト: ginobuzz/os161
int evict_page(struct page* p) {	// removes page from coremap
	if (!swap_initialized) {
		int err = swap_init();
		if (err) {
			return err;
		}
	}

	spinlock_acquire(&p->pg_lock);
	
	KASSERT(p->is_dirty==0);	// page should be clean
	KASSERT(p->status==IN_MEM);	// page should be in memory, but not tlb

	coremap_ufree(p->ram_addr);	// free the coremap entry
	
	spinlock_acquire(&p->pg_lock);

	return 0;
}
コード例 #7
0
void
umain(void)
{
	static_assert(sizeof(struct File) == 256);
	binaryname = "fs";
	cprintf("FS is running\n");

	// Check that we are able to do I/O
	outw(0x8A00, 0x8A00);
	cprintf("FS can do I/O\n");

	serve_init();
	fs_init();
	swap_init();
	fs_test();
	check_SwapBlock();
	
	serve();
}
コード例 #8
0
ファイル: init.c プロジェクト: Aresthu/ucore_plus
int kern_init(void)
{
	extern char edata[], end[];
	memset(edata, 0, end - edata);

	cons_init();		// init the console

	const char *message = "(THU.CST) os is loading ...";
	kprintf("%s\n\n", message);

	print_kerninfo();

	/* Only to initialize lcpu_count. */
	mp_init();

	debug_init();		// init debug registers
	pmm_init();		// init physical memory management
	pmm_init_ap();

	pic_init();		// init interrupt controller
	idt_init();		// init interrupt descriptor table

	vmm_init();		// init virtual memory management
	sched_init();		// init scheduler
	proc_init();		// init process table
	sync_init();		// init sync struct

	ide_init();		// init ide devices
#ifdef UCONFIG_SWAP
	swap_init();		// init swap
#endif
	fs_init();		// init fs

	clock_init();		// init clock interrupt
	mod_init();

	intr_enable();		// enable irq interrupt

	/* do nothing */
	cpu_idle();		// run idle process
}
コード例 #9
0
ファイル: swap.c プロジェクト: cctv2206/Pintos-project-3
//swap out to disk
size_t swap_out_of_memory (void * upage)
{
	swap_init ();
	
	if (swap_block == NULL || &swap_list == NULL)
	{
		return -1;
	}

	lock_acquire(&swap_lock); 
	struct list_elem * e = list_begin(&swap_list);
	
	int index;
	int i;
	for(e; e != list_end(&swap_list); e = list_next(e))
	{
		index++;
		struct swap_item * item = list_entry(e, struct swap_item, elem);
		if(item->available == true)
		{
			item->available = false;
			index = item->index;
			break;
		}
	}

	if(index == list_size(&swap_list)) 
	{
		lock_release(&swap_lock);
		return -1;
	}

	for (i = 0; i < SECTORS_PER_PAGE; i++) 
	{
		block_write (swap_block, index * SECTORS_PER_PAGE + i, (uint8_t *) upage + i * BLOCK_SECTOR_SIZE);
	}
	lock_release(&swap_lock);
	return index;
}
コード例 #10
0
ファイル: mivm.c プロジェクト: ginobuzz/os161
int swap_in_page(struct page* p) {
	if (!swap_initialized) {
		int err = swap_init();
		if (err)
			return err;
	}

	spinlock_acquire(&p->pg_lock);

	paddr_t pa = coremap_ualloc(p);
	while (pa==0) {
		swap_out_page();
		pa = coremap_ualloc(p);
	}

	p->ram_addr = pa;
	read_in_page(p);
	p->status = IN_MEM;
	p->is_dirty = 0;
	
	spinlock_release(&p->pg_lock);
	return 0;
}
コード例 #11
0
ファイル: mivm.c プロジェクト: ginobuzz/os161
int swap_out_page(void) {
	if (!swap_initialized) {
		int err = swap_init();
		if (err)
			return err;
	}

	struct page* p = find_swapout();

	if (p==NULL)
		panic("Could not find a page to swap out");
	
	spinlock_acquire(&p->pg_lock);
	
	if (p->is_dirty)
		write_out_page(p);

	evict_page(p);
	p->status = IN_SWAP;
	p->ram_addr = 31;
	
	spinlock_release(&p->pg_lock);
	return 0;
}
コード例 #12
0
ファイル: main.cpp プロジェクト: mariuz/haiku
extern "C" int
_start(kernel_args *bootKernelArgs, int currentCPU)
{
	if (bootKernelArgs->kernel_args_size != sizeof(kernel_args)
		|| bootKernelArgs->version != CURRENT_KERNEL_ARGS_VERSION) {
		// This is something we cannot handle right now - release kernels
		// should always be able to handle the kernel_args of earlier
		// released kernels.
		debug_early_boot_message("Version mismatch between boot loader and "
			"kernel!\n");
		return -1;
	}

	smp_set_num_cpus(bootKernelArgs->num_cpus);

	// wait for all the cpus to get here
	smp_cpu_rendezvous(&sCpuRendezvous, currentCPU);

	// the passed in kernel args are in a non-allocated range of memory
	if (currentCPU == 0)
		memcpy(&sKernelArgs, bootKernelArgs, sizeof(kernel_args));

	smp_cpu_rendezvous(&sCpuRendezvous2, currentCPU);

	// do any pre-booting cpu config
	cpu_preboot_init_percpu(&sKernelArgs, currentCPU);
	thread_preboot_init_percpu(&sKernelArgs, currentCPU);

	// if we're not a boot cpu, spin here until someone wakes us up
	if (smp_trap_non_boot_cpus(currentCPU, &sCpuRendezvous3)) {
		// init platform
		arch_platform_init(&sKernelArgs);

		// setup debug output
		debug_init(&sKernelArgs);
		set_dprintf_enabled(true);
		dprintf("Welcome to kernel debugger output!\n");
		dprintf("Haiku revision: %lu\n", get_haiku_revision());

		// init modules
		TRACE("init CPU\n");
		cpu_init(&sKernelArgs);
		cpu_init_percpu(&sKernelArgs, currentCPU);
		TRACE("init interrupts\n");
		int_init(&sKernelArgs);

		TRACE("init VM\n");
		vm_init(&sKernelArgs);
			// Before vm_init_post_sem() is called, we have to make sure that
			// the boot loader allocated region is not used anymore
		boot_item_init();
		debug_init_post_vm(&sKernelArgs);
		low_resource_manager_init();

		// now we can use the heap and create areas
		arch_platform_init_post_vm(&sKernelArgs);
		lock_debug_init();
		TRACE("init driver_settings\n");
		driver_settings_init(&sKernelArgs);
		debug_init_post_settings(&sKernelArgs);
		TRACE("init notification services\n");
		notifications_init();
		TRACE("init teams\n");
		team_init(&sKernelArgs);
		TRACE("init ELF loader\n");
		elf_init(&sKernelArgs);
		TRACE("init modules\n");
		module_init(&sKernelArgs);
		TRACE("init semaphores\n");
		haiku_sem_init(&sKernelArgs);
		TRACE("init interrupts post vm\n");
		int_init_post_vm(&sKernelArgs);
		cpu_init_post_vm(&sKernelArgs);
		commpage_init();
		TRACE("init system info\n");
		system_info_init(&sKernelArgs);

		TRACE("init SMP\n");
		smp_init(&sKernelArgs);
		TRACE("init timer\n");
		timer_init(&sKernelArgs);
		TRACE("init real time clock\n");
		rtc_init(&sKernelArgs);

		TRACE("init condition variables\n");
		condition_variable_init();

		// now we can create and use semaphores
		TRACE("init VM semaphores\n");
		vm_init_post_sem(&sKernelArgs);
		TRACE("init generic syscall\n");
		generic_syscall_init();
		smp_init_post_generic_syscalls();
		TRACE("init scheduler\n");
		scheduler_init();
		TRACE("init threads\n");
		thread_init(&sKernelArgs);
		TRACE("init kernel daemons\n");
		kernel_daemon_init();
		arch_platform_init_post_thread(&sKernelArgs);

		TRACE("init I/O interrupts\n");
		int_init_io(&sKernelArgs);
		TRACE("init VM threads\n");
		vm_init_post_thread(&sKernelArgs);
		low_resource_manager_init_post_thread();
		TRACE("init VFS\n");
		vfs_init(&sKernelArgs);
#if ENABLE_SWAP_SUPPORT
		TRACE("init swap support\n");
		swap_init();
#endif
		TRACE("init POSIX semaphores\n");
		realtime_sem_init();
		xsi_sem_init();
		xsi_msg_init();

		// Start a thread to finish initializing the rest of the system. Note,
		// it won't be scheduled before calling scheduler_start() (on any CPU).
		TRACE("spawning main2 thread\n");
		thread_id thread = spawn_kernel_thread(&main2, "main2",
			B_NORMAL_PRIORITY, NULL);
		resume_thread(thread);

		// We're ready to start the scheduler and enable interrupts on all CPUs.
		scheduler_enable_scheduling();

		// bring up the AP cpus in a lock step fashion
		TRACE("waking up AP cpus\n");
		sCpuRendezvous = sCpuRendezvous2 = 0;
		smp_wake_up_non_boot_cpus();
		smp_cpu_rendezvous(&sCpuRendezvous, 0); // wait until they're booted

		// exit the kernel startup phase (mutexes, etc work from now on out)
		TRACE("exiting kernel startup\n");
		gKernelStartup = false;

		smp_cpu_rendezvous(&sCpuRendezvous2, 0);
			// release the AP cpus to go enter the scheduler

		TRACE("starting scheduler on cpu 0 and enabling interrupts\n");
		scheduler_start();
		enable_interrupts();
	} else {
		// lets make sure we're in sync with the main cpu
		// the boot processor has probably been sending us
		// tlb sync messages all along the way, but we've
		// been ignoring them
		arch_cpu_global_TLB_invalidate();

		// this is run for each non boot processor after they've been set loose
		cpu_init_percpu(&sKernelArgs, currentCPU);
		smp_per_cpu_init(&sKernelArgs, currentCPU);

		// wait for all other AP cpus to get to this point
		smp_cpu_rendezvous(&sCpuRendezvous, currentCPU);
		smp_cpu_rendezvous(&sCpuRendezvous2, currentCPU);

		// welcome to the machine
		scheduler_start();
		enable_interrupts();
	}

#ifdef TRACE_BOOT
	// We disable interrupts for this dprintf(), since otherwise dprintf()
	// would acquires a mutex, which is something we must not do in an idle
	// thread, or otherwise the scheduler would be seriously unhappy.
	disable_interrupts();
	TRACE("main: done... begin idle loop on cpu %d\n", currentCPU);
	enable_interrupts();
#endif

	for (;;)
		arch_cpu_idle();

	return 0;
}
コード例 #13
0
ファイル: sim.c プロジェクト: jpaprakis/projects
int main(int argc, char *argv[]) {
	int opt;
	unsigned swapsize;
	FILE *tfp = stdin;
	char *replacement_alg = NULL;
	char *usage = "USAGE: sim -f tracefile -m memorysize -s swapsize -a algorithm\n";

	while ((opt = getopt(argc, argv, "f:m:a:s:")) != -1) {
		switch (opt) {
		case 'f':
			tracefile = optarg;
			break;
		case 'm':
			memsize = (unsigned)strtoul(optarg, NULL, 10);
			break;
		case 'a':
			replacement_alg = optarg;
			break;
		case 's':
			swapsize = (unsigned)strtoul(optarg, NULL, 10);
			break;
		default:
			fprintf(stderr, "%s", usage);
			exit(1);
		}
	}
	if(tracefile != NULL) {
		if((tfp = fopen(tracefile, "r")) == NULL) {
			perror("Error opening tracefile:");
			exit(1);
		}
	}

	// Initialize main data structures for simulation.
	// This happens before calling the replacement algorithm init function
	// so that the init_fcn can refer to the coremap if needed.

	//coremap is the amount of memory needed to hold all physical frame structs 
	coremap = malloc(memsize * sizeof(struct frame));

	//physmem is the bits/bytes in the total physical memory, a large array of bytes
	physmem = malloc(memsize * SIMPAGESIZE);

	swap_init(swapsize);
	init_pagetable();

	// Initialize replacement algorithm functions.
	if(replacement_alg == NULL) {
		fprintf(stderr, "%s", usage);
		exit(1);
	} else {
		int i;
		for (i = 0; i < num_algs; i++) {
			if(strcmp(algs[i].name, replacement_alg) == 0) {
				init_fcn = algs[i].init;
				ref_fcn = algs[i].ref;
				evict_fcn = algs[i].evict;
				break;
			}
		}
		if(evict_fcn == NULL) {
			fprintf(stderr, "Error: invalid replacement algorithm - %s\n", 
					replacement_alg);
			exit(1);
		}
	}
	// Call replacement algorithm's init_fcn before replaying trace.
	init_fcn();

	replay_trace(tfp);
	print_pagedirectory();

	// Cleanup - removes temporary swapfile.
	swap_destroy();

	printf("\n");
	printf("Hit count: %d\n", hit_count);
	printf("Miss count: %d\n", miss_count);
	printf("Clean evictions: %d\n",evict_clean_count);
	printf("Dirty evictions: %d\n",evict_dirty_count); 
	printf("Total references : %d\n", ref_count);
	printf("Hit rate: %.4f\n", (double)hit_count/ref_count * 100);
	printf("Miss rate: %.4f\n", (double)miss_count/ref_count *100);
		
	return(0);
}
コード例 #14
0
ファイル: stram.c プロジェクト: chinnyannieb/empeg-hijack
/*
 * This function is called from mem_init() to reserve the pages needed for
 * ST-RAM management.
 */
void __init atari_stram_reserve_pages(unsigned long start_mem)
{
#ifdef CONFIG_STRAM_SWAP
	/* if max_swap_size is negative (i.e. no stram_swap= option given),
	 * determine at run time whether to use ST-RAM swapping */
	if (max_swap_size < 0)
		/* Use swapping if ST-RAM doesn't make up more than MAX_STRAM_FRACTION
		 * of total memory. In that case, the max. size is set to 16 MB,
		 * because ST-RAM can never be bigger than that.
		 * Also, never use swapping on a Hades, there's no separate ST-RAM in
		 * that machine. */
		max_swap_size =
			(!MACH_IS_HADES &&
			 (N_PAGES(stram_end-stram_start)*MAX_STRAM_FRACTION_DENOM <=
			  max_mapnr*MAX_STRAM_FRACTION_NOM)) ? 16*1024*1024 : 0;
	DPRINTK( "atari_stram_reserve_pages: max_swap_size = %d\n", max_swap_size );
#endif

	/* always reserve first page of ST-RAM, the first 2 kB are
	 * supervisor-only! */
	set_bit( PG_reserved, &mem_map[MAP_NR(stram_start)].flags );

#ifdef CONFIG_STRAM_SWAP
	if (!max_swap_size) {
	  fallback:
#endif
		DPRINTK( "atari_stram_reserve_pages: swapping disabled\n" );
		if (!kernel_in_stram) {
			/* Reserve all pages that have been marked by pre-mem_init
			 * stram_alloc() (e.g. for the screen memory). */
			reserve_region( rsvd_stram_beg, rsvd_stram_end );
			DPRINTK( "atari_stram_reserve_pages: reseverved %08lx-%08lx\n",
					 rsvd_stram_beg, rsvd_stram_end );
		}
		/* else (kernel in ST-RAM): nothing to do, ST-RAM buffers are
		 * kernel data */
#ifdef CONFIG_STRAM_SWAP
	}
	else {
		unsigned long swap_data;
		BLOCK *p;

		/* determine first page to use as swap:
		 * if the kernel is in TT-RAM, this is the first page of (usable)
		 * ST-RAM; else if there were already some allocations (probable...),
		 * use the lowest address of these (the list is sorted by address!);
		 * otherwise just use the end of kernel data (= start_mem) */
		swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE :
					 alloc_list ? alloc_list->start :
					 start_mem;
		/* decrement by one page, rest of kernel assumes that first swap page
		 * is always reserved and maybe doesn't handle SWP_ENTRY == 0
		 * correctly */
		swap_start -= PAGE_SIZE;
		swap_end = stram_end;
		if (swap_end-swap_start > max_swap_size)
			swap_end =  swap_start + max_swap_size;
		DPRINTK( "atari_stram_reserve_pages: swapping enabled; "
				 "swap=%08lx-%08lx\n", swap_start, swap_end );
		
		/* reserve some amount of memory for maintainance of
		 * swapping itself: 1 page for the lockmap, and one page
		 * for each 2048 (PAGE_SIZE/2) swap pages. (2 bytes for
		 * each page) */
		swap_data = start_mem;
		start_mem += (((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1)
			       >> (PAGE_SHIFT-1)) + 1) << PAGE_SHIFT;
		/* correct swap_start if necessary */
		if (swap_start == swap_data)
			swap_start = start_mem;
		
		if (!swap_init( start_mem, swap_data )) {
			printk( KERN_ERR "ST-RAM swap space initialization failed\n" );
			max_swap_size = 0;
			goto fallback;
		}
		/* reserve region for swapping meta-data */
		reserve_region( swap_data, start_mem );
		/* reserve swapping area itself */
		reserve_region( swap_start+PAGE_SIZE, swap_end );

		/* Formerly static areas have been included in the swap area. */
		for( p = alloc_list; p; p = p->next ) {
			if (p->flags & BLOCK_STATIC)
				p->flags = (p->flags & ~BLOCK_STATIC) | BLOCK_INSWAP;
		}

		/*
		 * If the whole ST-RAM is used for swapping, there are no allocatable
		 * dma pages left. But unfortunately, some shared parts of the kernel
		 * (particularily the SCSI mid-level) call __get_dma_pages()
		 * unconditionally :-( These calls then fail, and scsi.c even doesn't
		 * check for NULL return values and just crashes. The quick fix for
		 * this (instead of doing much clean up work in the SCSI code) is to
		 * pretend all pages are DMA-able by setting mach_max_dma_address to
		 * ULONG_MAX. This doesn't change any functionality so far, since
		 * get_dma_pages() shouldn't be used on Atari anyway anymore (better
		 * use atari_stram_alloc()), and the Atari SCSI drivers don't need DMA
		 * memory. But unfortunately there's now no kind of warning (even not
		 * a NULL return value) if you use get_dma_pages() nevertheless :-(
		 * You just will get non-DMA-able memory...
		 */
		mach_max_dma_address = 0xffffffff;

		/*
		 * Ok, num_physpages needs not be really exact, but it's better to
		 * subtract the pages set aside for swapping.
		 */
		num_physpages -= SWAP_NR(swap_end)-1;
	}
#endif
	
	mem_init_done = 1;
}
コード例 #15
0
ファイル: init.c プロジェクト: Aresthu/ucore_plus
int kern_init(uint64_t mbmagic, uint64_t mbmem)
{
	extern char edata[], end[];
	memset(edata, 0, end - edata);

	/* percpu variable for CPU0 is preallocated */
	percpu_offsets[0] = __percpu_start;

	cons_init();		// init the console

	const char *message = "(THU.CST) os is loading ...";
	kprintf("%s\n\n", message);
	if(mbmagic == MULTIBOOT_BOOTLOADER_MAGIC){
		kprintf("Multiboot dectected: param %p\n", (void*)mbmem);
		mbmem2e820((Mbdata*)VADDR_DIRECT(mbmem));
		parse_initrd((Mbdata*)VADDR_DIRECT(mbmem));
	}

	print_kerninfo();

	/* get_cpu_var not available before tls_init() */
	hz_init();
	gdt_init(per_cpu_ptr(cpus, 0));
	tls_init(per_cpu_ptr(cpus, 0));
	acpitables_init();
	lapic_init();
	numa_init();

	pmm_init_numa();		// init physical memory management, numa awared
	/* map the lapic */
	lapic_init_late();

	//init the acpi stuff

	idt_init();		// init interrupt descriptor table
	pic_init();		// init interrupt controller

//	acpi_conf_init();


	percpu_init();
	cpus_init();
#ifdef UCONFIG_ENABLE_IPI
	ipi_init();
#endif

	refcache_init();

	vmm_init();		// init virtual memory management
	sched_init();		// init scheduler
	proc_init();		// init process table
	sync_init();		// init sync struct

	/* ext int */
	ioapic_init();
	acpi_init();

	ide_init();		// init ide devices
#ifdef UCONFIG_SWAP
	swap_init();		// init swap
#endif
	fs_init();		// init fs

	clock_init();		// init clock interrupt
	mod_init();

	trap_init();

	//XXX put here?
	bootaps();

	intr_enable();		// enable irq interrupt

#ifdef UCONFIG_HAVE_LINUX_DDE36_BASE
	dde_kit_init();
#endif

	/* do nothing */
	cpu_idle();		// run idle process
}
コード例 #16
0
/*
 * Initial boot sequence.
 */
static
void
boot(void)
{
	/*
	 * The order of these is important!
	 * Don't go changing it without thinking about the consequences.
	 *
	 * Among other things, be aware that console output gets
	 * buffered up at first and does not actually appear until
	 * mainbus_bootstrap() attaches the console device. This can
	 * be remarkably confusing if a bug occurs at this point. So
	 * don't put new code before mainbus_bootstrap if you don't
	 * absolutely have to.
	 *
	 * Also note that the buffer for this is only 1k. If you
	 * overflow it, the system will crash without printing
	 * anything at all. You can make it larger though (it's in
	 * dev/generic/console.c).
	 */

	kprintf("\n");
	kprintf("OS/161 base system version %s\n", BASE_VERSION);
	kprintf("%s", harvard_copyright);
	kprintf("\n");

	kprintf("Bala&Barry's system version %s (%s #%d)\n",
		GROUP_VERSION, buildconfig, buildversion);
	kprintf("\n");

	/* Early initialization. */
	ram_bootstrap();
	vm_bootstrap();
	proc_bootstrap();
	thread_bootstrap();
	hardclock_bootstrap();
	vfs_bootstrap();
	kheap_nextgeneration();

	/* Probe and initialize devices. Interrupts should come on. */
	kprintf("Device probe...\n");
	KASSERT(curthread->t_curspl > 0);
	mainbus_bootstrap();
	KASSERT(curthread->t_curspl == 0);
	/* Now do pseudo-devices. */
	pseudoconfig();
	kprintf("\n");

	kheap_nextgeneration();

	/* Late phase of initialization. */
	kprintf_bootstrap();
	thread_start_cpus();
	test161_bootstrap();

	swap_init();

	/* Default bootfs - but ignore failure, in case emu0 doesn't exist */
	vfs_setbootfs("emu0");

	kheap_nextgeneration();

	/*
	 * Make sure various things aren't screwed up.
	 */
	COMPILE_ASSERT(sizeof(userptr_t) == sizeof(char *));
	COMPILE_ASSERT(sizeof(*(userptr_t)0) == sizeof(char));
}