Commit fb06dbb1 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] x86-64 - new memory map handling

New e820 memory map handling for x86-64.  Move it all to a new file and
clean it up a lot.  Add some simple allocator functions to deal with
holey e820 mappings cleanly A lot of this is preparation for NUMA (which
works in 2.4, but is not ported to 2.5 yet)
parent dbb2ae18
This diff is collapsed.
This diff is collapsed.
...@@ -20,10 +20,11 @@ ...@@ -20,10 +20,11 @@
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/i387.h> #include <asm/i387.h>
#include <asm/percpu.h>
char x86_boot_params[2048] __initdata = {0,}; char x86_boot_params[2048] __initdata = {0,};
static unsigned long cpu_initialized __initdata = 0; unsigned long cpu_initialized __initdata = 0;
struct x8664_pda cpu_pda[NR_CPUS] __cacheline_aligned; struct x8664_pda cpu_pda[NR_CPUS] __cacheline_aligned;
...@@ -34,11 +35,15 @@ extern struct task_struct init_task; ...@@ -34,11 +35,15 @@ extern struct task_struct init_task;
extern unsigned char __per_cpu_start[], __per_cpu_end[]; extern unsigned char __per_cpu_start[], __per_cpu_end[];
struct desc_ptr gdt_descr = { 0 /* filled in */, (unsigned long) gdt_table }; extern struct desc_ptr cpu_gdt_descr[];
struct desc_ptr idt_descr = { 256 * 16, (unsigned long) idt_table }; struct desc_ptr idt_descr = { 256 * 16, (unsigned long) idt_table };
char boot_cpu_stack[IRQSTACKSIZE] __cacheline_aligned; char boot_cpu_stack[IRQSTACKSIZE] __cacheline_aligned;
#ifndef __GENERIC_PER_CPU
unsigned long __per_cpu_offset[NR_CPUS];
void __init setup_per_cpu_areas(void) void __init setup_per_cpu_areas(void)
{ {
unsigned long size, i; unsigned long size, i;
...@@ -52,10 +57,15 @@ void __init setup_per_cpu_areas(void) ...@@ -52,10 +57,15 @@ void __init setup_per_cpu_areas(void)
ptr = alloc_bootmem(size * NR_CPUS); ptr = alloc_bootmem(size * NR_CPUS);
for (i = 0; i < NR_CPUS; i++, ptr += size) { for (i = 0; i < NR_CPUS; i++, ptr += size) {
cpu_pda[cpu_logical_map(i)].cpudata_offset = ptr - __per_cpu_start; /* hide this from the compiler to avoid problems */
unsigned long offset;
asm("subq %[b],%0" : "=r" (offset) : "0" (ptr), [b] "r" (&__per_cpu_start));
__per_cpu_offset[i] = offset;
cpu_pda[i].cpudata_offset = offset;
memcpy(ptr, __per_cpu_start, size); memcpy(ptr, __per_cpu_start, size);
} }
} }
#endif
void pda_init(int cpu) void pda_init(int cpu)
{ {
...@@ -111,38 +121,48 @@ char boot_exception_stacks[N_EXCEPTION_STACKS*EXCEPTION_STKSZ]; ...@@ -111,38 +121,48 @@ char boot_exception_stacks[N_EXCEPTION_STACKS*EXCEPTION_STKSZ];
void __init cpu_init (void) void __init cpu_init (void)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int nr = stack_smp_processor_id(); int cpu = stack_smp_processor_id();
#else #else
int nr = smp_processor_id(); int cpu = smp_processor_id();
#endif #endif
struct tss_struct * t = &init_tss[nr]; struct tss_struct * t = &init_tss[cpu];
unsigned long v; unsigned long v;
char *estacks; char *estacks;
struct task_struct *me; struct task_struct *me;
/* CPU 0 is initialised in head64.c */ /* CPU 0 is initialised in head64.c */
if (nr != 0) { if (cpu != 0) {
estacks = (char *)__get_free_pages(GFP_ATOMIC, 0); estacks = (char *)__get_free_pages(GFP_ATOMIC, 0);
if (!estacks) if (!estacks)
panic("Can't allocate exception stacks for CPU %d\n",nr); panic("Can't allocate exception stacks for CPU %d\n",cpu);
pda_init(nr); pda_init(cpu);
} else } else
estacks = boot_exception_stacks; estacks = boot_exception_stacks;
me = current; me = current;
if (test_and_set_bit(nr, &cpu_initialized)) if (test_and_set_bit(cpu, &cpu_initialized))
panic("CPU#%d already initialized!\n", nr); panic("CPU#%d already initialized!\n", cpu);
printk("Initializing CPU#%d\n", nr); printk("Initializing CPU#%d\n", cpu);
clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
gdt_descr.size = (__u8*) gdt_end - (__u8*)gdt_table; /*
* Initialize the per-CPU GDT with the boot GDT,
* and set up the GDT descriptor:
*/
if (cpu) {
memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE);
}
__asm__ __volatile__("lgdt %0": "=m" (gdt_descr)); cpu_gdt_descr[cpu].size = GDT_SIZE;
cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu];
__asm__ __volatile__("lgdt %0": "=m" (cpu_gdt_descr[cpu]));
__asm__ __volatile__("lidt %0": "=m" (idt_descr)); __asm__ __volatile__("lidt %0": "=m" (idt_descr));
memcpy(me->thread.tls_array, cpu_gdt_table[cpu], GDT_ENTRY_TLS_ENTRIES * 8);
/* /*
* Delete NT * Delete NT
*/ */
...@@ -177,14 +197,16 @@ void __init cpu_init (void) ...@@ -177,14 +197,16 @@ void __init cpu_init (void)
estacks += EXCEPTION_STKSZ; estacks += EXCEPTION_STKSZ;
} }
t->io_map_base = INVALID_IO_BITMAP_OFFSET;
atomic_inc(&init_mm.mm_count); atomic_inc(&init_mm.mm_count);
me->active_mm = &init_mm; me->active_mm = &init_mm;
if (me->mm) if (me->mm)
BUG(); BUG();
enter_lazy_tlb(&init_mm, me, nr); enter_lazy_tlb(&init_mm, me, cpu);
set_tss_desc(nr, t); set_tss_desc(cpu, t);
load_TR(nr); load_TR_desc();
load_LDT(&init_mm.context); load_LDT(&init_mm.context);
/* /*
......
...@@ -2,16 +2,17 @@ ...@@ -2,16 +2,17 @@
* structures and definitions for the int 15, ax=e820 memory map * structures and definitions for the int 15, ax=e820 memory map
* scheme. * scheme.
* *
* In a nutshell, arch/x86_64/boot/setup.S populates a scratch table * In a nutshell, setup.S populates a scratch table in the
* in the empty_zero_block that contains a list of usable address/size * empty_zero_block that contains a list of usable address/size
* duples. In arch/x86_64/kernel/setup.c, this information is * duples. setup.c, this information is transferred into the e820map,
* transferred into the e820map, and in arch/i386/x86_64/init.c, that * and in init.c/numa.c, that new information is used to mark pages
* new information is used to mark pages reserved or not. * reserved or not.
*
*/ */
#ifndef __E820_HEADER #ifndef __E820_HEADER
#define __E820_HEADER #define __E820_HEADER
#include <linux/mmzone.h>
#define E820MAP 0x2d0 /* our map */ #define E820MAP 0x2d0 /* our map */
#define E820MAX 32 /* number of entries in E820MAP */ #define E820MAX 32 /* number of entries in E820MAP */
#define E820NR 0x1e8 /* # entries in E820MAP */ #define E820NR 0x1e8 /* # entries in E820MAP */
...@@ -23,17 +24,39 @@ ...@@ -23,17 +24,39 @@
#define HIGH_MEMORY (1024*1024) #define HIGH_MEMORY (1024*1024)
#define LOWMEMSIZE() (0x9f000)
#define MAXMEM (120UL * 1024 * 1024 * 1024 * 1024) /* 120TB */
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
struct e820entry {
u64 addr; /* start of memory segment */
u64 size; /* size of memory segment */
u32 type; /* type of memory segment */
} __attribute__((packed));
struct e820map { struct e820map {
int nr_map; int nr_map;
struct e820entry { struct e820entry map[E820MAX];
u64 addr __attribute__((packed)); /* start of memory segment */
u64 size __attribute__((packed)); /* size of memory segment */
u32 type __attribute__((packed)); /* type of memory segment */
} map[E820MAX];
}; };
extern unsigned long find_e820_area(unsigned long start, unsigned long end,
unsigned size);
extern void add_memory_region(unsigned long start, unsigned long size,
int type);
extern void setup_memory_region(void);
extern void contig_e820_setup(void);
extern void e820_end_of_ram(void);
extern void e820_reserve_resources(void);
extern void e820_print_map(char *who);
extern int e820_mapped(unsigned long start, unsigned long end, int type);
extern void e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end);
extern void __init parse_memopt(char *p);
extern void __init print_user_map(void);
extern struct e820map e820; extern struct e820map e820;
#endif/*!__ASSEMBLY__*/ #endif/*!__ASSEMBLY__*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment