2005-04-17 05:20:36 +07:00
|
|
|
/*
|
2015-01-28 01:16:28 +07:00
|
|
|
* linux/arch/x86/kernel/head_64.S -- start in 32bit and switch to 64bit
|
2005-04-17 05:20:36 +07:00
|
|
|
*
|
|
|
|
* Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
|
|
|
|
* Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
|
|
|
|
* Copyright (C) 2000 Karsten Keil <kkeil@suse.de>
|
|
|
|
* Copyright (C) 2001,2002 Andi Kleen <ak@suse.de>
|
2007-05-03 00:27:07 +07:00
|
|
|
* Copyright (C) 2005 Eric Biederman <ebiederm@xmission.com>
|
2005-04-17 05:20:36 +07:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <linux/linkage.h>
|
|
|
|
#include <linux/threads.h>
|
2005-11-05 23:25:53 +07:00
|
|
|
#include <linux/init.h>
|
2005-04-17 05:20:36 +07:00
|
|
|
#include <asm/segment.h>
|
2007-05-03 00:27:06 +07:00
|
|
|
#include <asm/pgtable.h>
|
2005-04-17 05:20:36 +07:00
|
|
|
#include <asm/page.h>
|
|
|
|
#include <asm/msr.h>
|
|
|
|
#include <asm/cache.h>
|
2008-05-12 20:43:38 +07:00
|
|
|
#include <asm/processor-flags.h>
|
2009-01-13 18:41:35 +07:00
|
|
|
#include <asm/percpu.h>
|
2012-04-19 07:16:49 +07:00
|
|
|
#include <asm/nops.h>
|
2016-04-02 21:01:32 +07:00
|
|
|
#include "../entry/calling.h"
|
2016-01-11 23:04:34 +07:00
|
|
|
#include <asm/export.h>
|
2007-05-03 00:27:07 +07:00
|
|
|
|
2008-01-30 19:31:10 +07:00
|
|
|
#ifdef CONFIG_PARAVIRT
|
|
|
|
#include <asm/asm-offsets.h>
|
|
|
|
#include <asm/paravirt.h>
|
2012-04-19 07:16:48 +07:00
|
|
|
#define GET_CR2_INTO(reg) GET_CR2_INTO_RAX ; movq %rax, reg
|
2008-01-30 19:31:10 +07:00
|
|
|
#else
|
2012-04-19 07:16:48 +07:00
|
|
|
#define GET_CR2_INTO(reg) movq %cr2, reg
|
2012-04-19 07:16:49 +07:00
|
|
|
#define INTERRUPT_RETURN iretq
|
2008-01-30 19:31:10 +07:00
|
|
|
#endif
|
|
|
|
|
tree-wide: Assorted spelling fixes
In particular, several occurances of funny versions of 'success',
'unknown', 'therefore', 'acknowledge', 'argument', 'achieve', 'address',
'beginning', 'desirable', 'separate' and 'necessary' are fixed.
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Joe Perches <joe@perches.com>
Cc: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2010-02-03 07:01:28 +07:00
|
|
|
/* we are not able to switch in one step to the final KERNEL ADDRESS SPACE
|
2007-05-03 00:27:07 +07:00
|
|
|
* because we need identity-mapped pages.
|
|
|
|
*
|
2005-04-17 05:20:36 +07:00
|
|
|
*/
|
|
|
|
|
2017-06-06 18:31:28 +07:00
|
|
|
#define p4d_index(x) (((x) >> P4D_SHIFT) & (PTRS_PER_P4D-1))
|
2008-06-25 11:19:16 +07:00
|
|
|
#define pud_index(x) (((x) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
|
|
|
|
|
2017-06-06 18:31:28 +07:00
|
|
|
PGD_PAGE_OFFSET = pgd_index(__PAGE_OFFSET_BASE)
|
|
|
|
PGD_START_KERNEL = pgd_index(__START_KERNEL_map)
|
2008-06-25 11:19:16 +07:00
|
|
|
L3_START_KERNEL = pud_index(__START_KERNEL_map)
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
.text
|
2009-09-17 03:44:28 +07:00
|
|
|
__HEAD
|
2007-05-03 00:27:07 +07:00
|
|
|
.code64
|
|
|
|
.globl startup_64
|
|
|
|
startup_64:
|
2005-04-17 05:20:36 +07:00
|
|
|
/*
|
2013-02-26 03:54:10 +07:00
|
|
|
* At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0,
|
2007-05-03 00:27:07 +07:00
|
|
|
* and someone has loaded an identity mapped page table
|
|
|
|
* for us. These identity mapped page tables map all of the
|
|
|
|
* kernel pages and possibly all of memory.
|
|
|
|
*
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
* %rsi holds a physical pointer to real_mode_data.
|
2007-05-03 00:27:07 +07:00
|
|
|
*
|
|
|
|
* We come here either directly from a 64bit bootloader, or from
|
2015-01-28 01:16:28 +07:00
|
|
|
* arch/x86/boot/compressed/head_64.S.
|
2007-05-03 00:27:07 +07:00
|
|
|
*
|
|
|
|
* We only come here initially at boot nothing else comes here.
|
|
|
|
*
|
|
|
|
* Since we may be loaded at an address different from what we were
|
|
|
|
* compiled to run at we first fixup the physical addresses in our page
|
|
|
|
* tables and then reload them.
|
2005-04-17 05:20:36 +07:00
|
|
|
*/
|
|
|
|
|
2016-09-22 04:04:06 +07:00
|
|
|
/* Set up the stack for verify_cpu(), similar to initial_stack below */
|
|
|
|
leaq (__end_init_task - SIZEOF_PTREGS)(%rip), %rsp
|
2016-03-31 21:21:02 +07:00
|
|
|
|
2015-11-05 22:57:56 +07:00
|
|
|
/* Sanitize CPU configuration */
|
|
|
|
call verify_cpu
|
|
|
|
|
2017-07-18 04:10:05 +07:00
|
|
|
/*
|
|
|
|
* Perform pagetable fixups. Additionally, if SME is active, encrypt
|
|
|
|
* the kernel and retrieve the modifier (SME encryption mask if SME
|
|
|
|
* is active) to be added to the initial pgdir entry that will be
|
|
|
|
* programmed into CR3.
|
|
|
|
*/
|
2007-05-03 00:27:07 +07:00
|
|
|
leaq _text(%rip), %rdi
|
2017-06-06 18:31:26 +07:00
|
|
|
pushq %rsi
|
|
|
|
call __startup_64
|
|
|
|
popq %rsi
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2017-07-18 04:10:05 +07:00
|
|
|
/* Form the CR3 value being sure to include the CR3 modifier */
|
|
|
|
addq $(early_top_pgt - __START_KERNEL_map), %rax
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
jmp 1f
|
2007-05-03 00:27:07 +07:00
|
|
|
ENTRY(secondary_startup_64)
|
2007-05-03 00:27:07 +07:00
|
|
|
/*
|
2013-02-26 03:54:10 +07:00
|
|
|
* At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0,
|
2007-05-03 00:27:07 +07:00
|
|
|
* and someone has loaded a mapped page table.
|
|
|
|
*
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
* %rsi holds a physical pointer to real_mode_data.
|
2007-05-03 00:27:07 +07:00
|
|
|
*
|
|
|
|
* We come here either from startup_64 (using physical addresses)
|
|
|
|
* or from trampoline.S (using virtual addresses).
|
|
|
|
*
|
|
|
|
* Using virtual addresses from trampoline.S removes the need
|
|
|
|
* to have any identity mapped pages in the kernel page table
|
|
|
|
* after the boot processor executes this code.
|
2005-04-17 05:20:36 +07:00
|
|
|
*/
|
|
|
|
|
2015-11-05 22:57:56 +07:00
|
|
|
/* Sanitize CPU configuration */
|
|
|
|
call verify_cpu
|
|
|
|
|
2017-07-18 04:10:05 +07:00
|
|
|
/*
|
|
|
|
* Retrieve the modifier (SME encryption mask if SME is active) to be
|
|
|
|
* added to the initial pgdir entry that will be programmed into CR3.
|
|
|
|
*/
|
|
|
|
pushq %rsi
|
|
|
|
call __startup_secondary_64
|
|
|
|
popq %rsi
|
|
|
|
|
|
|
|
/* Form the CR3 value being sure to include the CR3 modifier */
|
|
|
|
addq $(init_top_pgt - __START_KERNEL_map), %rax
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
1:
|
|
|
|
|
2017-06-06 18:31:28 +07:00
|
|
|
/* Enable PAE mode, PGE and LA57 */
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
movl $(X86_CR4_PAE | X86_CR4_PGE), %ecx
|
2017-06-06 18:31:28 +07:00
|
|
|
#ifdef CONFIG_X86_5LEVEL
|
|
|
|
orl $X86_CR4_LA57, %ecx
|
|
|
|
#endif
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
movq %rcx, %cr4
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2017-06-06 18:31:28 +07:00
|
|
|
/* Setup early boot stage 4-/5-level pagetables. */
|
2007-05-03 00:27:07 +07:00
|
|
|
addq phys_base(%rip), %rax
|
2005-04-17 05:20:36 +07:00
|
|
|
movq %rax, %cr3
|
|
|
|
|
2007-05-03 00:27:07 +07:00
|
|
|
/* Ensure I am executing from virtual addresses */
|
|
|
|
movq $1f, %rax
|
|
|
|
jmp *%rax
|
|
|
|
1:
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/* Check if nx is implemented */
|
|
|
|
movl $0x80000001, %eax
|
|
|
|
cpuid
|
|
|
|
movl %edx,%edi
|
|
|
|
|
|
|
|
/* Setup EFER (Extended Feature Enable Register) */
|
|
|
|
movl $MSR_EFER, %ecx
|
|
|
|
rdmsr
|
2007-05-03 00:27:07 +07:00
|
|
|
btsl $_EFER_SCE, %eax /* Enable System Call */
|
|
|
|
btl $20,%edi /* No Execute supported? */
|
2005-04-17 05:20:36 +07:00
|
|
|
jnc 1f
|
|
|
|
btsl $_EFER_NX, %eax
|
2013-05-03 00:33:46 +07:00
|
|
|
btsq $_PAGE_BIT_NX,early_pmd_flags(%rip)
|
2007-05-03 00:27:07 +07:00
|
|
|
1: wrmsr /* Make changes effective */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/* Setup cr0 */
|
2008-05-12 20:43:38 +07:00
|
|
|
#define CR0_STATE (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
|
|
|
|
X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
|
|
|
|
X86_CR0_PG)
|
|
|
|
movl $CR0_STATE, %eax
|
2005-04-17 05:20:36 +07:00
|
|
|
/* Make changes effective */
|
|
|
|
movq %rax, %cr0
|
|
|
|
|
|
|
|
/* Setup a boot time stack */
|
2016-08-18 22:59:03 +07:00
|
|
|
movq initial_stack(%rip), %rsp
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/* zero EFLAGS after setting rsp */
|
|
|
|
pushq $0
|
|
|
|
popfq
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We must switch to a new descriptor in kernel space for the GDT
|
|
|
|
* because soon the kernel won't have access anymore to the userspace
|
|
|
|
* addresses where we're currently running on. We have to do that here
|
|
|
|
* because in 32bit we couldn't load a 64bit linear address.
|
|
|
|
*/
|
2008-05-29 06:19:53 +07:00
|
|
|
lgdt early_gdt_descr(%rip)
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2009-11-25 23:17:36 +07:00
|
|
|
/* set up data segments */
|
|
|
|
xorl %eax,%eax
|
2007-02-13 19:26:24 +07:00
|
|
|
movl %eax,%ds
|
|
|
|
movl %eax,%ss
|
|
|
|
movl %eax,%es
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't really need to load %fs or %gs, but load them anyway
|
|
|
|
* to kill any stale realmode selectors. This allows execution
|
|
|
|
* under VT hardware.
|
|
|
|
*/
|
|
|
|
movl %eax,%fs
|
|
|
|
movl %eax,%gs
|
|
|
|
|
2009-01-13 18:41:35 +07:00
|
|
|
/* Set up %gs.
|
|
|
|
*
|
2009-01-19 10:21:28 +07:00
|
|
|
* The base of %gs always points to the bottom of the irqstack
|
|
|
|
* union. If the stack protector canary is enabled, it is
|
|
|
|
* located at %gs:40. Note that, on SMP, the boot cpu uses
|
|
|
|
* init data section till per cpu areas are set up.
|
2009-01-13 18:41:35 +07:00
|
|
|
*/
|
2005-04-17 05:20:36 +07:00
|
|
|
movl $MSR_GS_BASE,%ecx
|
2010-07-17 20:03:28 +07:00
|
|
|
movl initial_gs(%rip),%eax
|
|
|
|
movl initial_gs+4(%rip),%edx
|
2016-09-22 04:04:04 +07:00
|
|
|
wrmsr
|
2005-04-17 05:20:36 +07:00
|
|
|
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
/* rsi is pointer to real mode structure with interesting info.
|
2005-04-17 05:20:36 +07:00
|
|
|
pass it to C */
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
movq %rsi, %rdi
|
2016-09-22 04:04:04 +07:00
|
|
|
|
2017-03-04 16:56:10 +07:00
|
|
|
.Ljump_to_C_code:
|
2016-09-22 04:04:04 +07:00
|
|
|
/*
|
|
|
|
* Jump to run C code and to be on a real kernel address.
|
2005-04-17 05:20:36 +07:00
|
|
|
* Since we are running on identity-mapped space we have to jump
|
2006-09-26 15:52:38 +07:00
|
|
|
* to the full 64bit address, this is only possible as indirect
|
|
|
|
* jump. In addition we need to ensure %cs is set so we make this
|
|
|
|
* a far return.
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
*
|
|
|
|
* Note: do not change to far jump indirect with 64bit offset.
|
|
|
|
*
|
|
|
|
* AMD does not support far jump indirect with 64bit offset.
|
|
|
|
* AMD64 Architecture Programmer's Manual, Volume 3: states only
|
|
|
|
* JMP FAR mem16:16 FF /5 Far jump indirect,
|
|
|
|
* with the target specified by a far pointer in memory.
|
|
|
|
* JMP FAR mem16:32 FF /5 Far jump indirect,
|
|
|
|
* with the target specified by a far pointer in memory.
|
|
|
|
*
|
|
|
|
* Intel64 does support 64bit offset.
|
|
|
|
* Software Developer Manual Vol 2: states:
|
|
|
|
* FF /5 JMP m16:16 Jump far, absolute indirect,
|
|
|
|
* address given in m16:16
|
|
|
|
* FF /5 JMP m16:32 Jump far, absolute indirect,
|
|
|
|
* address given in m16:32.
|
|
|
|
* REX.W + FF /5 JMP m16:64 Jump far, absolute indirect,
|
|
|
|
* address given in m16:64.
|
2005-04-17 05:20:36 +07:00
|
|
|
*/
|
2016-12-14 10:25:36 +07:00
|
|
|
pushq $.Lafter_lret # put return address on stack for unwinder
|
|
|
|
xorq %rbp, %rbp # clear frame pointer
|
2016-09-22 04:04:05 +07:00
|
|
|
movq initial_code(%rip), %rax
|
2006-09-26 15:52:38 +07:00
|
|
|
pushq $__KERNEL_CS # set correct cs
|
|
|
|
pushq %rax # target address in negative space
|
|
|
|
lretq
|
2016-12-14 10:25:36 +07:00
|
|
|
.Lafter_lret:
|
2017-09-19 09:43:33 +07:00
|
|
|
END(secondary_startup_64)
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2015-11-05 22:57:56 +07:00
|
|
|
#include "verify_cpu.S"
|
|
|
|
|
2012-11-14 02:32:44 +07:00
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
|
|
/*
|
|
|
|
* Boot CPU0 entry point. It's called from play_dead(). Everything has been set
|
|
|
|
* up already except stack. We just set up stack here. Then call
|
2017-03-04 16:56:10 +07:00
|
|
|
* start_secondary() via .Ljump_to_C_code.
|
2012-11-14 02:32:44 +07:00
|
|
|
*/
|
|
|
|
ENTRY(start_cpu0)
|
2016-09-22 04:04:04 +07:00
|
|
|
movq initial_stack(%rip), %rsp
|
2017-03-04 16:56:10 +07:00
|
|
|
jmp .Ljump_to_C_code
|
2012-11-14 02:32:44 +07:00
|
|
|
ENDPROC(start_cpu0)
|
|
|
|
#endif
|
|
|
|
|
2016-08-18 22:59:03 +07:00
|
|
|
/* Both SMP bootup and ACPI suspend change these variables */
|
2008-02-17 19:22:59 +07:00
|
|
|
__REFDATA
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
.balign 8
|
|
|
|
GLOBAL(initial_code)
|
2005-04-17 05:20:36 +07:00
|
|
|
.quad x86_64_start_kernel
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
GLOBAL(initial_gs)
|
2009-02-08 21:58:39 +07:00
|
|
|
.quad INIT_PER_CPU_VAR(irq_stack_union)
|
2016-08-18 22:59:03 +07:00
|
|
|
GLOBAL(initial_stack)
|
2016-09-22 04:04:06 +07:00
|
|
|
/*
|
|
|
|
* The SIZEOF_PTREGS gap is a convention which helps the in-kernel
|
|
|
|
* unwinder reliably detect the end of the stack.
|
|
|
|
*/
|
|
|
|
.quad init_thread_union + THREAD_SIZE - SIZEOF_PTREGS
|
2009-10-15 04:46:55 +07:00
|
|
|
__FINITDATA
|
2005-04-17 05:20:36 +07:00
|
|
|
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
__INIT
|
2015-05-23 06:15:47 +07:00
|
|
|
ENTRY(early_idt_handler_array)
|
2008-03-11 08:23:22 +07:00
|
|
|
i = 0
|
|
|
|
.rept NUM_EXCEPTION_VECTORS
|
2015-05-23 06:15:47 +07:00
|
|
|
.ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1
|
2012-04-19 07:16:49 +07:00
|
|
|
pushq $0 # Dummy error code, to make stack frame uniform
|
|
|
|
.endif
|
|
|
|
pushq $i # 72(%rsp) Vector number
|
2015-05-23 06:15:47 +07:00
|
|
|
jmp early_idt_handler_common
|
2008-03-11 08:23:22 +07:00
|
|
|
i = i + 1
|
2015-05-23 06:15:47 +07:00
|
|
|
.fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
|
2008-03-11 08:23:22 +07:00
|
|
|
.endr
|
2017-09-19 09:43:33 +07:00
|
|
|
END(early_idt_handler_array)
|
2008-01-30 19:33:06 +07:00
|
|
|
|
2015-05-23 06:15:47 +07:00
|
|
|
early_idt_handler_common:
|
|
|
|
/*
|
|
|
|
* The stack is the hardware frame, an error code or zero, and the
|
|
|
|
* vector number.
|
|
|
|
*/
|
2012-04-19 07:16:49 +07:00
|
|
|
cld
|
|
|
|
|
2005-04-17 05:25:00 +07:00
|
|
|
incl early_recursion_flag(%rip)
|
2012-04-19 07:16:49 +07:00
|
|
|
|
2016-04-02 21:01:32 +07:00
|
|
|
/* The vector number is currently in the pt_regs->di slot. */
|
|
|
|
pushq %rsi /* pt_regs->si */
|
|
|
|
movq 8(%rsp), %rsi /* RSI = vector number */
|
|
|
|
movq %rdi, 8(%rsp) /* pt_regs->di = RDI */
|
|
|
|
pushq %rdx /* pt_regs->dx */
|
|
|
|
pushq %rcx /* pt_regs->cx */
|
|
|
|
pushq %rax /* pt_regs->ax */
|
|
|
|
pushq %r8 /* pt_regs->r8 */
|
|
|
|
pushq %r9 /* pt_regs->r9 */
|
|
|
|
pushq %r10 /* pt_regs->r10 */
|
|
|
|
pushq %r11 /* pt_regs->r11 */
|
|
|
|
pushq %rbx /* pt_regs->bx */
|
|
|
|
pushq %rbp /* pt_regs->bp */
|
|
|
|
pushq %r12 /* pt_regs->r12 */
|
|
|
|
pushq %r13 /* pt_regs->r13 */
|
|
|
|
pushq %r14 /* pt_regs->r14 */
|
|
|
|
pushq %r15 /* pt_regs->r15 */
|
|
|
|
|
|
|
|
cmpq $14,%rsi /* Page fault? */
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
jnz 10f
|
2016-04-02 21:01:32 +07:00
|
|
|
GET_CR2_INTO(%rdi) /* Can clobber any volatile register if pv */
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
call early_make_pgtable
|
|
|
|
andl %eax,%eax
|
2016-04-02 21:01:32 +07:00
|
|
|
jz 20f /* All good */
|
2012-04-19 07:16:49 +07:00
|
|
|
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
10:
|
2016-04-02 21:01:32 +07:00
|
|
|
movq %rsp,%rdi /* RDI = pt_regs; RSI is already trapnr */
|
2012-04-19 07:16:49 +07:00
|
|
|
call early_fixup_exception
|
2008-01-30 19:33:06 +07:00
|
|
|
|
2016-04-02 21:01:34 +07:00
|
|
|
20:
|
2012-04-19 07:16:49 +07:00
|
|
|
decl early_recursion_flag(%rip)
|
2016-04-02 21:01:32 +07:00
|
|
|
jmp restore_regs_and_iret
|
2017-09-19 09:43:33 +07:00
|
|
|
END(early_idt_handler_common)
|
2012-04-19 07:16:49 +07:00
|
|
|
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
__INITDATA
|
|
|
|
|
2012-04-19 07:16:49 +07:00
|
|
|
.balign 4
|
2016-04-02 21:01:34 +07:00
|
|
|
GLOBAL(early_recursion_flag)
|
2005-04-17 05:25:00 +07:00
|
|
|
.long 0
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2006-01-17 13:03:32 +07:00
|
|
|
#define NEXT_PAGE(name) \
|
2007-05-03 00:27:06 +07:00
|
|
|
.balign PAGE_SIZE; \
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
GLOBAL(name)
|
2006-01-17 13:03:32 +07:00
|
|
|
|
2007-05-03 00:27:06 +07:00
|
|
|
/* Automate the creation of 1 to 1 mapping pmd entries */
|
2008-05-13 23:55:40 +07:00
|
|
|
#define PMDS(START, PERM, COUNT) \
|
|
|
|
i = 0 ; \
|
|
|
|
.rept (COUNT) ; \
|
|
|
|
.quad (START) + (i << PMD_SHIFT) + (PERM) ; \
|
|
|
|
i = i + 1 ; \
|
2007-05-03 00:27:06 +07:00
|
|
|
.endr
|
|
|
|
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
__INITDATA
|
2017-06-06 18:31:27 +07:00
|
|
|
NEXT_PAGE(early_top_pgt)
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
.fill 511,8,0
|
2017-06-06 18:31:28 +07:00
|
|
|
#ifdef CONFIG_X86_5LEVEL
|
2017-07-18 04:10:07 +07:00
|
|
|
.quad level4_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC
|
2017-06-06 18:31:28 +07:00
|
|
|
#else
|
2017-07-18 04:10:07 +07:00
|
|
|
.quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC
|
2017-06-06 18:31:28 +07:00
|
|
|
#endif
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
|
|
|
|
NEXT_PAGE(early_dynamic_pgts)
|
|
|
|
.fill 512*EARLY_DYNAMIC_PAGE_TABLES,8,0
|
|
|
|
|
2009-10-15 04:46:55 +07:00
|
|
|
.data
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
|
|
|
|
#ifndef CONFIG_XEN
|
2017-06-06 18:31:27 +07:00
|
|
|
NEXT_PAGE(init_top_pgt)
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
.fill 512,8,0
|
|
|
|
#else
|
2017-06-06 18:31:27 +07:00
|
|
|
NEXT_PAGE(init_top_pgt)
|
2017-07-18 04:10:07 +07:00
|
|
|
.quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC
|
2017-06-06 18:31:28 +07:00
|
|
|
.org init_top_pgt + PGD_PAGE_OFFSET*8, 0
|
2017-07-18 04:10:07 +07:00
|
|
|
.quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC
|
2017-06-06 18:31:28 +07:00
|
|
|
.org init_top_pgt + PGD_START_KERNEL*8, 0
|
2007-05-03 00:27:07 +07:00
|
|
|
/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
|
2017-07-18 04:10:07 +07:00
|
|
|
.quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2006-01-17 13:03:32 +07:00
|
|
|
NEXT_PAGE(level3_ident_pgt)
|
2017-07-18 04:10:07 +07:00
|
|
|
.quad level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
.fill 511, 8, 0
|
|
|
|
NEXT_PAGE(level2_ident_pgt)
|
|
|
|
/* Since I easily can, map the first 1G.
|
|
|
|
* Don't set NX because code runs from these pages.
|
|
|
|
*/
|
|
|
|
PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, PTRS_PER_PMD)
|
|
|
|
#endif
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2017-06-06 18:31:28 +07:00
|
|
|
#ifdef CONFIG_X86_5LEVEL
|
|
|
|
NEXT_PAGE(level4_kernel_pgt)
|
|
|
|
.fill 511,8,0
|
2017-07-18 04:10:07 +07:00
|
|
|
.quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC
|
2017-06-06 18:31:28 +07:00
|
|
|
#endif
|
|
|
|
|
2006-01-17 13:03:32 +07:00
|
|
|
NEXT_PAGE(level3_kernel_pgt)
|
2008-06-25 11:19:16 +07:00
|
|
|
.fill L3_START_KERNEL,8,0
|
2005-04-17 05:20:36 +07:00
|
|
|
/* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
|
2017-07-18 04:10:07 +07:00
|
|
|
.quad level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC
|
|
|
|
.quad level2_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC
|
2007-07-16 13:37:28 +07:00
|
|
|
|
2006-01-17 13:03:32 +07:00
|
|
|
NEXT_PAGE(level2_kernel_pgt)
|
2008-02-21 17:04:11 +07:00
|
|
|
/*
|
2008-02-21 18:50:51 +07:00
|
|
|
* 512 MB kernel mapping. We spend a full page on this pagetable
|
2008-02-21 17:04:11 +07:00
|
|
|
* anyway.
|
|
|
|
*
|
|
|
|
* The kernel code+data+bss must not be bigger than that.
|
|
|
|
*
|
2008-02-21 18:50:51 +07:00
|
|
|
* (NOTE: at +512MB starts the module area, see MODULES_VADDR.
|
2008-02-21 17:04:11 +07:00
|
|
|
* If you want to increase this then increase MODULES_VADDR
|
|
|
|
* too.)
|
|
|
|
*/
|
2008-07-02 06:46:35 +07:00
|
|
|
PMDS(0, __PAGE_KERNEL_LARGE_EXEC,
|
2008-02-21 19:39:30 +07:00
|
|
|
KERNEL_IMAGE_SIZE/PMD_SIZE)
|
2005-04-17 05:20:36 +07:00
|
|
|
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
NEXT_PAGE(level2_fixmap_pgt)
|
|
|
|
.fill 506,8,0
|
2017-07-18 04:10:07 +07:00
|
|
|
.quad level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
/* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */
|
|
|
|
.fill 5,8,0
|
|
|
|
|
|
|
|
NEXT_PAGE(level1_fixmap_pgt)
|
|
|
|
.fill 512,8,0
|
2007-05-03 00:27:07 +07:00
|
|
|
|
2007-05-03 00:27:06 +07:00
|
|
|
#undef PMDS
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2006-01-17 13:03:32 +07:00
|
|
|
.data
|
2005-04-17 05:20:36 +07:00
|
|
|
.align 16
|
2008-05-29 06:19:53 +07:00
|
|
|
.globl early_gdt_descr
|
|
|
|
early_gdt_descr:
|
|
|
|
.word GDT_ENTRIES*8-1
|
2009-01-13 18:41:35 +07:00
|
|
|
early_gdt_descr_base:
|
2009-02-08 21:58:39 +07:00
|
|
|
.quad INIT_PER_CPU_VAR(gdt_page)
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2007-05-03 00:27:07 +07:00
|
|
|
ENTRY(phys_base)
|
|
|
|
/* This must match the first entry in level2_kernel_pgt */
|
|
|
|
.quad 0x0000000000000000
|
2016-01-11 23:04:34 +07:00
|
|
|
EXPORT_SYMBOL(phys_base)
|
2007-05-03 00:27:07 +07:00
|
|
|
|
2008-07-09 05:06:44 +07:00
|
|
|
#include "../../x86/xen/xen-head.S"
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2009-09-21 05:14:14 +07:00
|
|
|
__PAGE_ALIGNED_BSS
|
x86, 64bit: Use a #PF handler to materialize early mappings on demand
Linear mode (CR0.PG = 0) is mutually exclusive with 64-bit mode; all
64-bit code has to use page tables. This makes it awkward before we
have first set up properly all-covering page tables to access objects
that are outside the static kernel range.
So far we have dealt with that simply by mapping a fixed amount of
low memory, but that fails in at least two upcoming use cases:
1. We will support load and run kernel, struct boot_params, ramdisk,
command line, etc. above the 4 GiB mark.
2. need to access ramdisk early to get microcode to update that as
early possible.
We could use early_iomap to access them too, but it will make code to
messy and hard to be unified with 32 bit.
Hence, set up a #PF table and use a fixed number of buffers to set up
page tables on demand. If the buffers fill up then we simply flush
them and start over. These buffers are all in __initdata, so it does
not increase RAM usage at runtime.
Thus, with the help of the #PF handler, we can set the final kernel
mapping from blank, and switch to init_level4_pgt later.
During the switchover in head_64.S, before #PF handler is available,
we use three pages to handle kernel crossing 1G, 512G boundaries with
sharing page by playing games with page aliasing: the same page is
mapped twice in the higher-level tables with appropriate wraparound.
The kernel region itself will be properly mapped; other mappings may
be spurious.
early_make_pgtable is using kernel high mapping address to access pages
to set page table.
-v4: Add phys_base offset to make kexec happy, and add
init_mapping_kernel() - Yinghai
-v5: fix compiling with xen, and add back ident level3 and level2 for xen
also move back init_level4_pgt from BSS to DATA again.
because we have to clear it anyway. - Yinghai
-v6: switch to init_level4_pgt in init_mem_mapping. - Yinghai
-v7: remove not needed clear_page for init_level4_page
it is with fill 512,8,0 already in head_64.S - Yinghai
-v8: we need to keep that handler alive until init_mem_mapping and don't
let early_trap_init to trash that early #PF handler.
So split early_trap_pf_init out and move it down. - Yinghai
-v9: switchover only cover kernel space instead of 1G so could avoid
touch possible mem holes. - Yinghai
-v11: change far jmp back to far return to initial_code, that is needed
to fix failure that is reported by Konrad on AMD systems. - Yinghai
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2013-01-25 03:19:52 +07:00
|
|
|
NEXT_PAGE(empty_zero_page)
|
2006-03-25 22:30:01 +07:00
|
|
|
.skip PAGE_SIZE
|
2016-01-11 23:04:34 +07:00
|
|
|
EXPORT_SYMBOL(empty_zero_page)
|
2015-02-14 05:39:25 +07:00
|
|
|
|