add: PRINT(("finding and booting other cpus...\n"));
context: void _start(unsigned int mem, int in_vesa, unsigned int vesa_ptr){	unsigned int *idt;	unsigned int *gdt;	unsigned int next_vaddr;	unsigned int next_paddr;	unsigned int i;	unsigned int kernel_entry;	asm("cld");			// Ain't nothing but a GCC thang.	asm("fninit");		// initialize floating point unit	clearscreen();	dprintf("stage2 bootloader entry.\n");	dprintf("memsize = 0x%x, in_vesa %d, vesa_ptr 0x%x\n", mem, in_vesa, vesa_ptr);	// verify we can run on this cpu	if(check_cpu() < 0) {		dprintf("\nSorry, this computer appears to be lacking some of the features\n");		dprintf("needed by OpenBeOS. It is currently only able to run on\n");		dprintf("Pentium class cpus and above, with a few exceptions to\n");		dprintf("that rule.\n");		dprintf("\nPlease reset your computer to continue.");		for(;;);	}	// calculate the conversion factor that translates rdtsc time to real microseconds	calculate_cpu_conversion_factor();	// calculate how big the bootdir is so we know where we can start grabbing pages	{		int entry;		for (entry = 0; entry < 64; entry++) {			if (bootdir[entry].be_type == BE_TYPE_NONE)				break;			bootdir_pages += bootdir[entry].be_size;		}//		nmessage("bootdir is ", bootdir_pages, " pages long\n");	}	ka->bootdir_addr.start = (unsigned long)bootdir;	ka->bootdir_addr.size = bootdir_pages * PAGE_SIZE;	next_paddr = BOOTDIR_ADDR + bootdir_pages * PAGE_SIZE;	if(in_vesa) {		struct VBEModeInfoBlock *mode_info = (struct VBEModeInfoBlock *)(vesa_ptr + 0x200);		ka->fb.enabled = 1;		ka->fb.x_size = mode_info->x_resolution;		ka->fb.y_size = mode_info->y_resolution;		ka->fb.bit_depth = mode_info->bits_per_pixel;		ka->fb.mapping.start = mode_info->phys_base_ptr;		ka->fb.mapping.size = ka->fb.x_size * ka->fb.y_size * (ka->fb.bit_depth/8);		ka->fb.already_mapped = 0;	} else {		ka->fb.enabled = 0;	}	mmu_init(ka, &next_paddr);	// load the kernel (3rd entry in the bootdir)	load_elf_image((void *)(bootdir[2].be_offset * PAGE_SIZE + BOOTDIR_ADDR), &next_paddr,			&ka->kernel_seg0_addr, &ka->kernel_seg1_addr, &kernel_entry, &ka->kernel_dynamic_section_addr);	if(ka->kernel_seg1_addr.size > 0)		next_vaddr = ROUNDUP(ka->kernel_seg1_addr.start + ka->kernel_seg1_addr.size, PAGE_SIZE);	else		next_vaddr = ROUNDUP(ka->kernel_seg0_addr.start + ka->kernel_seg0_addr.size, PAGE_SIZE);	// map in a kernel stack	ka->cpu_kstack[0].start = next_vaddr;	for(i=0; i<STACK_SIZE; i++) {		mmu_map_page(next_vaddr, next_paddr);		next_vaddr += PAGE_SIZE;		next_paddr += PAGE_SIZE;	}	ka->cpu_kstack[0].size = next_vaddr - ka->cpu_kstack[0].start;//	dprintf("new stack at 0x%x to 0x%x\n", ka->cpu_kstack[0].start, ka->cpu_kstack[0].start + ka->cpu_kstack[0].size);	// set up a new idt	{		struct gdt_idt_descr idt_descr;		// find a new idt		idt = (unsigned int *)next_paddr;		ka->arch_args.phys_idt = (unsigned int)idt;		next_paddr += PAGE_SIZE;//		nmessage("idt at ", (unsigned int)idt, "\n");		// clear it out		for(i=0; i<IDT_LIMIT/4; i++) {			idt[i] = 0;		}		// map the idt into virtual space		mmu_map_page(next_vaddr, (unsigned int)idt);		ka->arch_args.vir_idt = (unsigned int)next_vaddr;		next_vaddr += PAGE_SIZE;		// load the idt		idt_descr.a = IDT_LIMIT - 1;		idt_descr.b = (unsigned int *)ka->arch_args.vir_idt;		asm("lidt	%0;"			: : "m" (idt_descr));//		nmessage("idt at virtual address ", next_vpage, "\n");	}	// set up a new gdt	{		struct gdt_idt_descr gdt_descr;		// find a new gdt		gdt = (unsigned int *)next_paddr;		ka->arch_args.phys_gdt = (unsigned int)gdt;		next_paddr += PAGE_SIZE;//		nmessage("gdt at ", (unsigned int)gdt, "\n");		// put segment descriptors in it		gdt[0] = 0;		gdt[1] = 0;		gdt[2] = 0x0000ffff; // seg 0x8  -- kernel 4GB code		gdt[3] = 0x00cf9a00;		gdt[4] = 0x0000ffff; // seg 0x10 -- kernel 4GB data		gdt[5] = 0x00cf9200;		gdt[6] = 0x0000ffff; // seg 0x1b -- ring 3 4GB code		gdt[7] = 0x00cffa00;		gdt[8] = 0x0000ffff; // seg 0x23 -- ring 3 4GB data		gdt[9] = 0x00cff200;		// gdt[10] & gdt[11] will be filled later by the kernel		// map the gdt into virtual space		mmu_map_page(next_vaddr, (unsigned int)gdt);		ka->arch_args.vir_gdt = (unsigned int)next_vaddr;		next_vaddr += PAGE_SIZE;		// load the GDT		gdt_descr.a = GDT_LIMIT - 1;		gdt_descr.b = (unsigned int *)ka->arch_args.vir_gdt;		asm("lgdt	%0;"			: : "m" (gdt_descr));//		nmessage("gdt at virtual address ", next_vpage, "\n");	}	// Map the pg_dir into kernel space at 0xffc00000-0xffffffff	// this enables a mmu trick where the 4 MB region that this pgdir entry	// represents now maps the 4MB of potential pagetables that the pgdir	// points to. Thrown away later in VM bringup, but useful for now.	pgdir[1023] = (unsigned int)pgdir | DEFAULT_PAGE_FLAGS;	// also map it on the next vpage	mmu_map_page(next_vaddr, (unsigned int)pgdir);	ka->arch_args.vir_pgdir = next_vaddr;	next_vaddr += PAGE_SIZE;	// save the kernel args	ka->arch_args.system_time_cv_factor = cv_factor;	ka->phys_mem_range[0].start = 0;	ka->phys_mem_range[0].size = mem;	ka->num_phys_mem_ranges = 1;	ka->str = NULL;	ka->phys_alloc_range[0].start = BOOTDIR_ADDR;	ka->phys_alloc_range[0].size = next_paddr - BOOTDIR_ADDR;	ka->num_phys_alloc_ranges = 1;	ka->virt_alloc_range[0].start = KERNEL_BASE;	ka->virt_alloc_range[0].size = next_vaddr - KERNEL_BASE;	ka->num_virt_alloc_ranges = 1;	ka->arch_args.page_hole = 0xffc00000;	ka->num_cpus = 1;#if 0	dprintf("kernel args at 0x%x\n", ka);	dprintf("pgdir = 0x%x\n", ka->pgdir);	dprintf("pgtables[0] = 0x%x\n", ka->pgtables[0]);	dprintf("phys_idt = 0x%x\n", ka->phys_idt);	dprintf("vir_idt = 0x%x\n", ka->vir_idt);	dprintf("phys_gdt = 0x%x\n", ka->phys_gdt);	dprintf("vir_gdt = 0x%x\n", ka->vir_gdt);	dprintf("mem_size = 0x%x\n", ka->mem_size);	dprintf("str = 0x%x\n", ka->str);	dprintf("bootdir = 0x%x\n", ka->bootdir);	dprintf("bootdir_size = 0x%x\n", ka->bootdir_size);	dprintf("phys_alloc_range_low = 0x%x\n", ka->phys_alloc_range_low);	dprintf("phys_alloc_range_high = 0x%x\n", ka->phys_alloc_range_high);	dprintf("virt_alloc_range_low = 0x%x\n", ka->virt_alloc_range_low);	dprintf("virt_alloc_range_high = 0x%x\n", ka->virt_alloc_range_high);	dprintf("page_hole = 0x%x\n", ka->page_hole);#endif//	dprintf("finding and booting other cpus...\n");	smp_boot(ka, kernel_entry);	dprintf("jumping into kernel at 0x%x\n", kernel_entry);	ka->cons_line = line;	asm("movl	%0, %%eax;	"			// move stack out of way		"movl	%%eax, %%esp; "		: : "m" (ka->cpu_kstack[0].start + ka->cpu_kstack[0].size));	asm("pushl  $0x0; "					// we're the BSP cpu (0)		"pushl 	%0;	"					// kernel args		"pushl 	$0x0;"					// dummy retval for call to main		"pushl 	%1;	"					// this is the start address		"ret;		"					// jump.		: : "g" (ka), "g" (kernel_entry));}