| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  *  linux/arch/x86_64/kernel/head64.c -- prepare to run common code | 
 | 3 |  * | 
 | 4 |  *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE | 
 | 5 |  * | 
 | 6 |  *  $Id: head64.c,v 1.22 2001/07/06 14:28:20 ak Exp $ | 
 | 7 |  */ | 
 | 8 |  | 
 | 9 | #include <linux/init.h> | 
 | 10 | #include <linux/linkage.h> | 
 | 11 | #include <linux/types.h> | 
 | 12 | #include <linux/kernel.h> | 
 | 13 | #include <linux/string.h> | 
 | 14 | #include <linux/percpu.h> | 
 | 15 |  | 
 | 16 | #include <asm/processor.h> | 
 | 17 | #include <asm/proto.h> | 
 | 18 | #include <asm/smp.h> | 
 | 19 | #include <asm/bootsetup.h> | 
 | 20 | #include <asm/setup.h> | 
 | 21 | #include <asm/desc.h> | 
 | 22 |  | 
 | 23 | /* Don't add a printk in there. printk relies on the PDA which is not initialized  | 
 | 24 |    yet. */ | 
 | 25 | static void __init clear_bss(void) | 
 | 26 | { | 
 | 27 | 	extern char __bss_start[], __bss_end[]; | 
 | 28 | 	memset(__bss_start, 0, | 
 | 29 | 	       (unsigned long) __bss_end - (unsigned long) __bss_start); | 
 | 30 | } | 
 | 31 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 32 | #define NEW_CL_POINTER		0x228	/* Relative to real mode data */ | 
 | 33 | #define OLD_CL_MAGIC_ADDR	0x90020 | 
 | 34 | #define OLD_CL_MAGIC            0xA33F | 
 | 35 | #define OLD_CL_BASE_ADDR        0x90000 | 
 | 36 | #define OLD_CL_OFFSET           0x90022 | 
 | 37 |  | 
 | 38 | extern char saved_command_line[]; | 
 | 39 |  | 
 | 40 | static void __init copy_bootdata(char *real_mode_data) | 
 | 41 | { | 
 | 42 | 	int new_data; | 
 | 43 | 	char * command_line; | 
 | 44 |  | 
| Venkatesh Pallipadi | f9ba705 | 2005-05-01 08:58:51 -0700 | [diff] [blame] | 45 | 	memcpy(x86_boot_params, real_mode_data, BOOT_PARAM_SIZE); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 46 | 	new_data = *(int *) (x86_boot_params + NEW_CL_POINTER); | 
 | 47 | 	if (!new_data) { | 
 | 48 | 		if (OLD_CL_MAGIC != * (u16 *) OLD_CL_MAGIC_ADDR) { | 
 | 49 | 			printk("so old bootloader that it does not support commandline?!\n"); | 
 | 50 | 			return; | 
 | 51 | 		} | 
 | 52 | 		new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET; | 
 | 53 | 		printk("old bootloader convention, maybe loadlin?\n"); | 
 | 54 | 	} | 
 | 55 | 	command_line = (char *) ((u64)(new_data)); | 
 | 56 | 	memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); | 
 | 57 | 	printk("Bootdata ok (command line is %s)\n", saved_command_line);	 | 
 | 58 | } | 
 | 59 |  | 
 | 60 | static void __init setup_boot_cpu_data(void) | 
 | 61 | { | 
 | 62 | 	unsigned int dummy, eax; | 
 | 63 |  | 
 | 64 | 	/* get vendor info */ | 
 | 65 | 	cpuid(0, (unsigned int *)&boot_cpu_data.cpuid_level, | 
 | 66 | 	      (unsigned int *)&boot_cpu_data.x86_vendor_id[0], | 
 | 67 | 	      (unsigned int *)&boot_cpu_data.x86_vendor_id[8], | 
 | 68 | 	      (unsigned int *)&boot_cpu_data.x86_vendor_id[4]); | 
 | 69 |  | 
 | 70 | 	/* get cpu type */ | 
 | 71 | 	cpuid(1, &eax, &dummy, &dummy, | 
 | 72 | 		(unsigned int *) &boot_cpu_data.x86_capability); | 
 | 73 | 	boot_cpu_data.x86 = (eax >> 8) & 0xf; | 
 | 74 | 	boot_cpu_data.x86_model = (eax >> 4) & 0xf; | 
 | 75 | 	boot_cpu_data.x86_mask = eax & 0xf; | 
 | 76 | } | 
 | 77 |  | 
 | 78 | extern char _end[]; | 
 | 79 |  | 
 | 80 | void __init x86_64_start_kernel(char * real_mode_data) | 
 | 81 | { | 
 | 82 | 	char *s; | 
 | 83 | 	int i; | 
 | 84 |  | 
 | 85 | 	for (i = 0; i < 256; i++) | 
 | 86 | 		set_intr_gate(i, early_idt_handler); | 
 | 87 | 	asm volatile("lidt %0" :: "m" (idt_descr)); | 
 | 88 | 	clear_bss(); | 
 | 89 | 	pda_init(0); | 
 | 90 | 	copy_bootdata(real_mode_data); | 
 | 91 | #ifdef CONFIG_SMP | 
 | 92 | 	cpu_set(0, cpu_online_map); | 
 | 93 | #endif | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 94 | 	s = strstr(saved_command_line, "earlyprintk="); | 
 | 95 | 	if (s != NULL) | 
 | 96 | 		setup_early_printk(s); | 
| Matt Tolentino | 2b97690 | 2005-06-23 00:08:06 -0700 | [diff] [blame] | 97 | #ifdef CONFIG_NUMA | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 98 | 	s = strstr(saved_command_line, "numa="); | 
 | 99 | 	if (s != NULL) | 
 | 100 | 		numa_setup(s+5); | 
 | 101 | #endif | 
 | 102 | #ifdef CONFIG_X86_IO_APIC | 
 | 103 | 	if (strstr(saved_command_line, "disableapic")) | 
 | 104 | 		disable_apic = 1; | 
 | 105 | #endif | 
 | 106 | 	/* You need early console to see that */ | 
 | 107 | 	if (__pa_symbol(&_end) >= KERNEL_TEXT_SIZE) | 
 | 108 | 		panic("Kernel too big for kernel mapping\n"); | 
 | 109 |  | 
 | 110 | 	setup_boot_cpu_data(); | 
 | 111 | 	start_kernel(); | 
 | 112 | } |