head64.c 2.9 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
D
Dave Jones 已提交
2
 *  prepare to run common code
L
Linus Torvalds 已提交
3 4 5 6 7 8 9 10 11 12
 *
 *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
 */

#include <linux/init.h>
#include <linux/linkage.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/percpu.h>
13
#include <linux/start_kernel.h>
L
Linus Torvalds 已提交
14 15 16 17 18 19

#include <asm/processor.h>
#include <asm/proto.h>
#include <asm/smp.h>
#include <asm/setup.h>
#include <asm/desc.h>
20
#include <asm/pgtable.h>
21
#include <asm/tlbflush.h>
22
#include <asm/sections.h>
23
#include <asm/kdebug.h>
24
#include <asm/e820.h>
L
Linus Torvalds 已提交
25

26 27 28 29
static void __init zap_identity_mappings(void)
{
	pgd_t *pgd = pgd_offset_k(0UL);
	pgd_clear(pgd);
30
	__flush_tlb_all();
31 32
}

L
Linus Torvalds 已提交
33 34 35 36 37
/* 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,
38
	       (unsigned long) __bss_stop - (unsigned long) __bss_start);
L
Linus Torvalds 已提交
39 40 41 42 43 44
}

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

45 46 47 48
	memcpy(&boot_params, real_mode_data, sizeof boot_params);
	if (boot_params.hdr.cmd_line_ptr) {
		command_line = __va(boot_params.hdr.cmd_line_ptr);
		memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
L
Linus Torvalds 已提交
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
#define EBDA_ADDR_POINTER 0x40E

static __init void reserve_ebda(void)
{
	unsigned ebda_addr, ebda_size;

	/*
	 * there is a real-mode segmented pointer pointing to the
	 * 4K EBDA area at 0x40E
	 */
	ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
	ebda_addr <<= 4;

	if (!ebda_addr)
		return;

	ebda_size = *(unsigned short *)__va(ebda_addr);

	/* Round EBDA up to pages */
	if (ebda_size == 0)
		ebda_size = 1;
	ebda_size <<= 10;
	ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
	if (ebda_size > 64*1024)
		ebda_size = 64*1024;

	reserve_early(ebda_addr, ebda_addr + ebda_size);
}

L
Linus Torvalds 已提交
81 82 83 84
void __init x86_64_start_kernel(char * real_mode_data)
{
	int i;

85 86 87
	/* clear bss before set_intr_gate with early_idt_handler */
	clear_bss();

88 89 90
	/* Make NULL pointers segfault */
	zap_identity_mappings();

91 92
	for (i = 0; i < IDT_ENTRIES; i++) {
#ifdef CONFIG_EARLY_PRINTK
93
		set_intr_gate(i, &early_idt_handlers[i]);
94 95 96 97
#else
		set_intr_gate(i, early_idt_handler);
#endif
	}
98
	load_idt((const struct desc_ptr *)&idt_descr);
99

100
	early_printk("Kernel alive\n");
I
Ingo Molnar 已提交
101

102 103 104
 	for (i = 0; i < NR_CPUS; i++)
 		cpu_pda(i) = &boot_cpu_pda[i];

L
Linus Torvalds 已提交
105
	pda_init(0);
106
	copy_bootdata(__va(real_mode_data));
107

108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end));

	/* Reserve INITRD */
	if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
		unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
		unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
		unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
		reserve_early(ramdisk_image, ramdisk_end);
	}

	reserve_ebda();

	/*
	 * At this point everything still needed from the boot loader
	 * or BIOS or kernel text should be early reserved or marked not
	 * RAM in e820. All other memory is free game.
	 */

L
Linus Torvalds 已提交
126 127
	start_kernel();
}