• H. Peter Anvin's avatar
    x86, 64bit: Use a #PF handler to materialize early mappings on demand · 8170e6be
    H. Peter Anvin authored
    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: default avatarYinghai Lu <yinghai@kernel.org>
    Link: http://lkml.kernel.org/r/1359058816-7615-12-git-send-email-yinghai@kernel.orgSigned-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
    8170e6be
traps.c 20.1 KB