2017-12-04 15:40:55 +03:00
# include <asm/processor.h>
2018-02-26 21:04:48 +03:00
# include "pgtable.h"
2017-12-04 15:40:55 +03:00
/*
* __force_order is used by special_insns . h asm code to force instruction
* serialization .
*
* It is not referenced from the code , but GCC < 5 with - fPIE would fail
* due to an undefined symbol . Define it to make these ancient GCCs work .
*/
unsigned long __force_order ;
2018-02-26 21:04:48 +03:00
# define BIOS_START_MIN 0x20000U /* 128K, less than this is insane */
# define BIOS_START_MAX 0x9f000U /* 640K, absolute maximum */
2018-02-09 17:22:26 +03:00
struct paging_config {
unsigned long trampoline_start ;
unsigned long l5_required ;
} ;
2017-12-04 15:40:55 +03:00
2018-02-26 21:04:48 +03:00
/*
* Trampoline address will be printed by extract_kernel ( ) for debugging
* purposes .
*
* Avoid putting the pointer into . bss as it will be cleared between
* paging_prepare ( ) and extract_kernel ( ) .
*/
unsigned long * trampoline_32bit __section ( . data ) ;
2018-02-09 17:22:26 +03:00
struct paging_config paging_prepare ( void )
{
struct paging_config paging_config = { } ;
2018-02-26 21:04:48 +03:00
unsigned long bios_start , ebda_start ;
2017-12-04 15:40:55 +03:00
2018-02-26 21:04:47 +03:00
/*
* Check if LA57 is desired and supported .
*
* There are two parts to the check :
* - if the kernel supports 5 - level paging : CONFIG_X86_5LEVEL = y
* - if the machine supports 5 - level paging :
* + CPUID leaf 7 is supported
* + the leaf has the feature bit set
*
* That ' s substitute for boot_cpu_has ( ) in early boot code .
*/
if ( IS_ENABLED ( CONFIG_X86_5LEVEL ) & &
native_cpuid_eax ( 0 ) > = 7 & &
( native_cpuid_ecx ( 7 ) & ( 1 < < ( X86_FEATURE_LA57 & 31 ) ) ) ) {
2018-02-09 17:22:26 +03:00
paging_config . l5_required = 1 ;
2018-02-26 21:04:47 +03:00
}
2017-12-04 15:40:55 +03:00
2018-02-26 21:04:48 +03:00
/*
* Find a suitable spot for the trampoline .
* This code is based on reserve_bios_regions ( ) .
*/
ebda_start = * ( unsigned short * ) 0x40e < < 4 ;
bios_start = * ( unsigned short * ) 0x413 < < 10 ;
if ( bios_start < BIOS_START_MIN | | bios_start > BIOS_START_MAX )
bios_start = BIOS_START_MAX ;
if ( ebda_start > BIOS_START_MIN & & ebda_start < bios_start )
bios_start = ebda_start ;
/* Place the trampoline just below the end of low memory, aligned to 4k */
paging_config . trampoline_start = bios_start - TRAMPOLINE_32BIT_SIZE ;
paging_config . trampoline_start = round_down ( paging_config . trampoline_start , PAGE_SIZE ) ;
trampoline_32bit = ( unsigned long * ) paging_config . trampoline_start ;
2018-02-09 17:22:26 +03:00
return paging_config ;
2017-12-04 15:40:55 +03:00
}