Skip to content

Commit b29f377

Browse files
committed
Merge tag 'x86-boot-2024-03-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 boot updates from Ingo Molnar: - Continuing work by Ard Biesheuvel to improve the x86 early startup code, with the long-term goal to make it position independent: - Get rid of early accesses to global objects, either by moving them to the stack, deferring the access until later, or dropping the globals entirely - Move all code that runs early via the 1:1 mapping into .head.text, and move code that does not out of it, so that build time checks can be added later to ensure that no inadvertent absolute references were emitted into code that does not tolerate them - Remove fixup_pointer() and occurrences of __pa_symbol(), which rely on the compiler emitting absolute references, which is not guaranteed - Improve the early console code - Add early console message about ignored NMIs, so that users are at least warned about their existence - even if we cannot do anything about them - Improve the kexec code's kernel load address handling - Enable more X86S (simplified x86) bits - Simplify early boot GDT handling - Micro-optimize the boot code a bit - Misc cleanups * tag 'x86-boot-2024-03-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (22 commits) x86/sev: Move early startup code into .head.text section x86/sme: Move early SME kernel encryption handling into .head.text x86/boot: Move mem_encrypt= parsing to the decompressor efi/libstub: Add generic support for parsing mem_encrypt= x86/startup_64: Simplify virtual switch on primary boot x86/startup_64: Simplify calculation of initial page table address x86/startup_64: Defer assignment of 5-level paging global variables x86/startup_64: Simplify CR4 handling in startup code x86/boot: Use 32-bit XOR to clear registers efi/x86: Set the PE/COFF header's NX compat flag unconditionally x86/boot/64: Load the final kernel GDT during early boot directly, remove startup_gdt[] x86/boot/64: Use RIP_REL_REF() to access early_top_pgt[] x86/boot/64: Use RIP_REL_REF() to access early page tables x86/boot/64: Use RIP_REL_REF() to access '__supported_pte_mask' x86/boot/64: Use RIP_REL_REF() to access early_dynamic_pgts[] x86/boot/64: Use RIP_REL_REF() to assign 'phys_base' x86/boot/64: Simplify global variable accesses in GDT/IDT programming x86/trampoline: Bypass compat mode in trampoline_start64() if not needed kexec: Allocate kernel above bzImage's pref_address x86/boot: Add a message about ignored early NMIs ...
2 parents e66c58f + 2e2bc42 commit b29f377

File tree

25 files changed

+273
-331
lines changed

25 files changed

+273
-331
lines changed

Documentation/arch/x86/boot.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,8 @@ Protocol: 2.10+
878878
address if possible.
879879

880880
A non-relocatable kernel will unconditionally move itself and to run
881-
at this address.
881+
at this address. A relocatable kernel will move itself to this address if it
882+
loaded below this address.
882883

883884
============ =======
884885
Field name: init_size

arch/x86/Kconfig

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,11 +2111,11 @@ config PHYSICAL_START
21112111
help
21122112
This gives the physical address where the kernel is loaded.
21132113

2114-
If kernel is a not relocatable (CONFIG_RELOCATABLE=n) then
2115-
bzImage will decompress itself to above physical address and
2116-
run from there. Otherwise, bzImage will run from the address where
2117-
it has been loaded by the boot loader and will ignore above physical
2118-
address.
2114+
If the kernel is not relocatable (CONFIG_RELOCATABLE=n) then bzImage
2115+
will decompress itself to above physical address and run from there.
2116+
Otherwise, bzImage will run from the address where it has been loaded
2117+
by the boot loader. The only exception is if it is loaded below the
2118+
above physical address, in which case it will relocate itself there.
21192119

21202120
In normal kdump cases one does not have to set/change this option
21212121
as now bzImage can be compiled as a completely relocatable image

arch/x86/boot/compressed/ident_map_64.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,5 +389,5 @@ void do_boot_page_fault(struct pt_regs *regs, unsigned long error_code)
389389

390390
void do_boot_nmi_trap(struct pt_regs *regs, unsigned long error_code)
391391
{
392-
/* Empty handler to ignore NMI during early boot */
392+
spurious_nmi_count++;
393393
}

arch/x86/boot/compressed/misc.c

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct port_io_ops pio_ops;
5252

5353
memptr free_mem_ptr;
5454
memptr free_mem_end_ptr;
55+
int spurious_nmi_count;
5556

5657
static char *vidmem;
5758
static int vidport;
@@ -164,21 +165,34 @@ void __putstr(const char *s)
164165
outb(0xff & (pos >> 1), vidport+1);
165166
}
166167

167-
void __puthex(unsigned long value)
168+
static noinline void __putnum(unsigned long value, unsigned int base,
169+
int mindig)
168170
{
169-
char alpha[2] = "0";
170-
int bits;
171+
char buf[8*sizeof(value)+1];
172+
char *p;
171173

172-
for (bits = sizeof(value) * 8 - 4; bits >= 0; bits -= 4) {
173-
unsigned long digit = (value >> bits) & 0xf;
174+
p = buf + sizeof(buf);
175+
*--p = '\0';
174176

175-
if (digit < 0xA)
176-
alpha[0] = '0' + digit;
177-
else
178-
alpha[0] = 'a' + (digit - 0xA);
177+
while (mindig-- > 0 || value) {
178+
unsigned char digit = value % base;
179+
digit += (digit >= 10) ? ('a'-10) : '0';
180+
*--p = digit;
179181

180-
__putstr(alpha);
182+
value /= base;
181183
}
184+
185+
__putstr(p);
186+
}
187+
188+
void __puthex(unsigned long value)
189+
{
190+
__putnum(value, 16, sizeof(value)*2);
191+
}
192+
193+
void __putdec(unsigned long value)
194+
{
195+
__putnum(value, 10, 1);
182196
}
183197

184198
#ifdef CONFIG_X86_NEED_RELOCS
@@ -357,6 +371,19 @@ unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr,
357371
return entry;
358372
}
359373

374+
/*
375+
* Set the memory encryption xloadflag based on the mem_encrypt= command line
376+
* parameter, if provided.
377+
*/
378+
static void parse_mem_encrypt(struct setup_header *hdr)
379+
{
380+
int on = cmdline_find_option_bool("mem_encrypt=on");
381+
int off = cmdline_find_option_bool("mem_encrypt=off");
382+
383+
if (on > off)
384+
hdr->xloadflags |= XLF_MEM_ENCRYPTION;
385+
}
386+
360387
/*
361388
* The compressed kernel image (ZO), has been moved so that its position
362389
* is against the end of the buffer used to hold the uncompressed kernel
@@ -387,6 +414,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
387414
/* Clear flags intended for solely in-kernel use. */
388415
boot_params_ptr->hdr.loadflags &= ~KASLR_FLAG;
389416

417+
parse_mem_encrypt(&boot_params_ptr->hdr);
418+
390419
sanitize_boot_params(boot_params_ptr);
391420

392421
if (boot_params_ptr->screen_info.orig_video_mode == 7) {
@@ -493,6 +522,12 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
493522
/* Disable exception handling before booting the kernel */
494523
cleanup_exception_handling();
495524

525+
if (spurious_nmi_count) {
526+
error_putstr("Spurious early NMIs ignored: ");
527+
error_putdec(spurious_nmi_count);
528+
error_putstr("\n");
529+
}
530+
496531
return output + entry_offset;
497532
}
498533

arch/x86/boot/compressed/misc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,15 @@ extern char _head[], _end[];
5959
/* misc.c */
6060
extern memptr free_mem_ptr;
6161
extern memptr free_mem_end_ptr;
62+
extern int spurious_nmi_count;
6263
void *malloc(int size);
6364
void free(void *where);
6465
void __putstr(const char *s);
6566
void __puthex(unsigned long value);
67+
void __putdec(unsigned long value);
6668
#define error_putstr(__x) __putstr(__x)
6769
#define error_puthex(__x) __puthex(__x)
70+
#define error_putdec(__x) __putdec(__x)
6871

6972
#ifdef CONFIG_X86_VERBOSE_BOOTUP
7073

arch/x86/boot/compressed/sev.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ static bool fault_in_kernel_space(unsigned long address)
117117
#undef __init
118118
#define __init
119119

120+
#undef __head
121+
#define __head
122+
120123
#define __BOOT_COMPRESSED
121124

122125
/* Basic instruction decoding support needed */

arch/x86/boot/header.S

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,7 @@ extra_header_fields:
111111
.long salign # SizeOfHeaders
112112
.long 0 # CheckSum
113113
.word IMAGE_SUBSYSTEM_EFI_APPLICATION # Subsystem (EFI application)
114-
#ifdef CONFIG_EFI_DXE_MEM_ATTRIBUTES
115114
.word IMAGE_DLL_CHARACTERISTICS_NX_COMPAT # DllCharacteristics
116-
#else
117-
.word 0 # DllCharacteristics
118-
#endif
119115
#ifdef CONFIG_X86_32
120116
.long 0 # SizeOfStackReserve
121117
.long 0 # SizeOfStackCommit

arch/x86/include/asm/desc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct gdt_page {
4646
} __attribute__((aligned(PAGE_SIZE)));
4747

4848
DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page);
49+
DECLARE_INIT_PER_CPU(gdt_page);
4950

5051
/* Provide the original GDT */
5152
static inline struct desc_struct *get_cpu_gdt_rw(unsigned int cpu)

arch/x86/include/asm/mem_encrypt.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ void __init sme_unmap_bootdata(char *real_mode_data);
4747

4848
void __init sme_early_init(void);
4949

50-
void __init sme_encrypt_kernel(struct boot_params *bp);
51-
void __init sme_enable(struct boot_params *bp);
50+
void sme_encrypt_kernel(struct boot_params *bp);
51+
void sme_enable(struct boot_params *bp);
5252

5353
int __init early_set_memory_decrypted(unsigned long vaddr, unsigned long size);
5454
int __init early_set_memory_encrypted(unsigned long vaddr, unsigned long size);
@@ -81,8 +81,8 @@ static inline void __init sme_unmap_bootdata(char *real_mode_data) { }
8181

8282
static inline void __init sme_early_init(void) { }
8383

84-
static inline void __init sme_encrypt_kernel(struct boot_params *bp) { }
85-
static inline void __init sme_enable(struct boot_params *bp) { }
84+
static inline void sme_encrypt_kernel(struct boot_params *bp) { }
85+
static inline void sme_enable(struct boot_params *bp) { }
8686

8787
static inline void sev_es_init_vc_handling(void) { }
8888

arch/x86/include/asm/pgtable_64_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ typedef unsigned long pgprotval_t;
2121
typedef struct { pteval_t pte; } pte_t;
2222
typedef struct { pmdval_t pmd; } pmd_t;
2323

24-
#ifdef CONFIG_X86_5LEVEL
2524
extern unsigned int __pgtable_l5_enabled;
2625

26+
#ifdef CONFIG_X86_5LEVEL
2727
#ifdef USE_EARLY_PGTABLE_L5
2828
/*
2929
* cpu_feature_enabled() is not available in early boot code.

0 commit comments

Comments
 (0)