head64.c 3.21 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
 *  linux/arch/x86_64/kernel/head64.c -- prepare to run common code
 *
 *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
 *
 *  $Id: head64.c,v 1.22 2001/07/06 14:28:20 ak Exp $
 */

#include <linux/init.h>
#include <linux/linkage.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/percpu.h>

#include <asm/processor.h>
#include <asm/proto.h>
#include <asm/smp.h>
#include <asm/bootsetup.h>
#include <asm/setup.h>
#include <asm/desc.h>
22
#include <asm/pgtable.h>
23
#include <asm/sections.h>
Linus Torvalds's avatar
Linus Torvalds committed
24
25
26
27
28
29

/* Don't add a printk in there. printk relies on the PDA which is not initialized 
   yet. */
static void __init clear_bss(void)
{
	memset(__bss_start, 0,
30
	       (unsigned long) __bss_stop - (unsigned long) __bss_start);
Linus Torvalds's avatar
Linus Torvalds committed
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
}

#define NEW_CL_POINTER		0x228	/* Relative to real mode data */
#define OLD_CL_MAGIC_ADDR	0x90020
#define OLD_CL_MAGIC            0xA33F
#define OLD_CL_BASE_ADDR        0x90000
#define OLD_CL_OFFSET           0x90022

extern char saved_command_line[];

static void __init copy_bootdata(char *real_mode_data)
{
	int new_data;
	char * command_line;

46
	memcpy(x86_boot_params, real_mode_data, BOOT_PARAM_SIZE);
Linus Torvalds's avatar
Linus Torvalds committed
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
	new_data = *(int *) (x86_boot_params + NEW_CL_POINTER);
	if (!new_data) {
		if (OLD_CL_MAGIC != * (u16 *) OLD_CL_MAGIC_ADDR) {
			printk("so old bootloader that it does not support commandline?!\n");
			return;
		}
		new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET;
		printk("old bootloader convention, maybe loadlin?\n");
	}
	command_line = (char *) ((u64)(new_data));
	memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
	printk("Bootdata ok (command line is %s)\n", saved_command_line);	
}

static void __init setup_boot_cpu_data(void)
{
	unsigned int dummy, eax;

	/* get vendor info */
	cpuid(0, (unsigned int *)&boot_cpu_data.cpuid_level,
	      (unsigned int *)&boot_cpu_data.x86_vendor_id[0],
	      (unsigned int *)&boot_cpu_data.x86_vendor_id[8],
	      (unsigned int *)&boot_cpu_data.x86_vendor_id[4]);

	/* get cpu type */
	cpuid(1, &eax, &dummy, &dummy,
		(unsigned int *) &boot_cpu_data.x86_capability);
	boot_cpu_data.x86 = (eax >> 8) & 0xf;
	boot_cpu_data.x86_model = (eax >> 4) & 0xf;
	boot_cpu_data.x86_mask = eax & 0xf;
}

void __init x86_64_start_kernel(char * real_mode_data)
{
	char *s;
	int i;

	for (i = 0; i < 256; i++)
		set_intr_gate(i, early_idt_handler);
	asm volatile("lidt %0" :: "m" (idt_descr));
	clear_bss();
88
89
90
91
92
93
94

	/*
	 * switch to init_level4_pgt from boot_level4_pgt
	 */
	memcpy(init_level4_pgt, boot_level4_pgt, PTRS_PER_PGD*sizeof(pgd_t));
	asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt)));

95
96
97
 	for (i = 0; i < NR_CPUS; i++)
 		cpu_pda(i) = &boot_cpu_pda[i];

Linus Torvalds's avatar
Linus Torvalds committed
98
99
100
101
102
103
104
105
	pda_init(0);
	copy_bootdata(real_mode_data);
#ifdef CONFIG_SMP
	cpu_set(0, cpu_online_map);
#endif
	s = strstr(saved_command_line, "earlyprintk=");
	if (s != NULL)
		setup_early_printk(s);
106
#ifdef CONFIG_NUMA
Linus Torvalds's avatar
Linus Torvalds committed
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
	s = strstr(saved_command_line, "numa=");
	if (s != NULL)
		numa_setup(s+5);
#endif
#ifdef CONFIG_X86_IO_APIC
	if (strstr(saved_command_line, "disableapic"))
		disable_apic = 1;
#endif
	/* You need early console to see that */
	if (__pa_symbol(&_end) >= KERNEL_TEXT_SIZE)
		panic("Kernel too big for kernel mapping\n");

	setup_boot_cpu_data();
	start_kernel();
}