Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/boot: Port I/O: Allow to hook up alternative helpers

Port I/O instructions trigger #VE in the TDX environment. In response to
the exception, kernel emulates these instructions using hypercalls.

But during early boot, on the decompression stage, it is cumbersome to
deal with #VE. It is cleaner to go to hypercalls directly, bypassing #VE
handling.

Add a way to hook up alternative port I/O helpers in the boot stub with
a new pio_ops structure. For now, set the ops structure to just call
the normal I/O operation functions.

out*()/in*() macros redefined to use pio_ops callbacks. It eliminates
need in changing call sites. io_delay() changed to use port I/O helper
instead of inline assembly.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Link: https://lkml.kernel.org/r/20220405232939.73860-16-kirill.shutemov@linux.intel.com

authored by

Kirill A. Shutemov and committed by
Dave Hansen
eb4ea1ae 1e8f93e1

+56 -3
+2 -2
arch/x86/boot/boot.h
··· 23 23 #include <linux/edd.h> 24 24 #include <asm/setup.h> 25 25 #include <asm/asm.h> 26 - #include <asm/shared/io.h> 27 26 #include "bitops.h" 28 27 #include "ctype.h" 29 28 #include "cpuflags.h" 29 + #include "io.h" 30 30 31 31 /* Useful macros */ 32 32 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) ··· 39 39 static inline void io_delay(void) 40 40 { 41 41 const u16 DELAY_PORT = 0x80; 42 - asm volatile("outb %%al,%0" : : "dN" (DELAY_PORT)); 42 + outb(0, DELAY_PORT); 43 43 } 44 44 45 45 /* These functions are used to reference data in other segments. */
+4
arch/x86/boot/compressed/misc.c
··· 48 48 */ 49 49 struct boot_params *boot_params; 50 50 51 + struct port_io_ops pio_ops; 52 + 51 53 memptr free_mem_ptr; 52 54 memptr free_mem_end_ptr; 53 55 ··· 372 370 373 371 lines = boot_params->screen_info.orig_video_lines; 374 372 cols = boot_params->screen_info.orig_video_cols; 373 + 374 + init_default_io_ops(); 375 375 376 376 /* 377 377 * Detect TDX guest environment.
+1 -1
arch/x86/boot/compressed/misc.h
··· 26 26 #include <asm/boot.h> 27 27 #include <asm/bootparam.h> 28 28 #include <asm/desc_defs.h> 29 - #include <asm/shared/io.h> 30 29 31 30 #include "tdx.h" 32 31 ··· 34 35 35 36 #define BOOT_BOOT_H 36 37 #include "../ctype.h" 38 + #include "../io.h" 37 39 38 40 #ifdef CONFIG_X86_64 39 41 #define memptr long
+41
arch/x86/boot/io.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef BOOT_IO_H 3 + #define BOOT_IO_H 4 + 5 + #include <asm/shared/io.h> 6 + 7 + #undef inb 8 + #undef inw 9 + #undef inl 10 + #undef outb 11 + #undef outw 12 + #undef outl 13 + 14 + struct port_io_ops { 15 + u8 (*f_inb)(u16 port); 16 + void (*f_outb)(u8 v, u16 port); 17 + void (*f_outw)(u16 v, u16 port); 18 + }; 19 + 20 + extern struct port_io_ops pio_ops; 21 + 22 + /* 23 + * Use the normal I/O instructions by default. 24 + * TDX guests override these to use hypercalls. 25 + */ 26 + static inline void init_default_io_ops(void) 27 + { 28 + pio_ops.f_inb = __inb; 29 + pio_ops.f_outb = __outb; 30 + pio_ops.f_outw = __outw; 31 + } 32 + 33 + /* 34 + * Redirect port I/O operations via pio_ops callbacks. 35 + * TDX guests override these callbacks with TDX-specific helpers. 36 + */ 37 + #define inb pio_ops.f_inb 38 + #define outb pio_ops.f_outb 39 + #define outw pio_ops.f_outw 40 + 41 + #endif
+4
arch/x86/boot/main.c
··· 17 17 18 18 struct boot_params boot_params __attribute__((aligned(16))); 19 19 20 + struct port_io_ops pio_ops; 21 + 20 22 char *HEAP = _end; 21 23 char *heap_end = _end; /* Default end of heap = no heap */ 22 24 ··· 135 133 136 134 void main(void) 137 135 { 136 + init_default_io_ops(); 137 + 138 138 /* First, copy the boot header into the "zeropage" */ 139 139 copy_boot_params(); 140 140
+4
arch/x86/realmode/rm/wakemain.c
··· 62 62 } 63 63 } 64 64 65 + struct port_io_ops pio_ops; 66 + 65 67 void main(void) 66 68 { 69 + init_default_io_ops(); 70 + 67 71 /* Kill machine if structures are wrong */ 68 72 if (wakeup_header.real_magic != 0x12345678) 69 73 while (1)