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

Configure Feed

Select the types of activity you want to include in your feed.

x86/sev: Move __sev_[get|put]_ghcb() into separate noinstr object

Rename sev-nmi.c to noinstr.c, and move the get/put GHCB routines into it too,
which are also annotated as 'noinstr' and suffer from the same problem as the
NMI code, i.e., that GCC may ignore the __no_sanitize_address__ function
attribute implied by 'noinstr' and insert KASAN instrumentation anyway.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/20250828102202.1849035-37-ardb+git@google.com

authored by

Ard Biesheuvel and committed by
Borislav Petkov (AMD)
d4077e6a 9723dd0c

+78 -78
-74
arch/x86/boot/startup/sev-startup.c
··· 41 41 #include <asm/cpuid/api.h> 42 42 #include <asm/cmdline.h> 43 43 44 - /* 45 - * Nothing shall interrupt this code path while holding the per-CPU 46 - * GHCB. The backup GHCB is only for NMIs interrupting this path. 47 - * 48 - * Callers must disable local interrupts around it. 49 - */ 50 - noinstr struct ghcb *__sev_get_ghcb(struct ghcb_state *state) 51 - { 52 - struct sev_es_runtime_data *data; 53 - struct ghcb *ghcb; 54 - 55 - WARN_ON(!irqs_disabled()); 56 - 57 - data = this_cpu_read(runtime_data); 58 - ghcb = &data->ghcb_page; 59 - 60 - if (unlikely(data->ghcb_active)) { 61 - /* GHCB is already in use - save its contents */ 62 - 63 - if (unlikely(data->backup_ghcb_active)) { 64 - /* 65 - * Backup-GHCB is also already in use. There is no way 66 - * to continue here so just kill the machine. To make 67 - * panic() work, mark GHCBs inactive so that messages 68 - * can be printed out. 69 - */ 70 - data->ghcb_active = false; 71 - data->backup_ghcb_active = false; 72 - 73 - instrumentation_begin(); 74 - panic("Unable to handle #VC exception! GHCB and Backup GHCB are already in use"); 75 - instrumentation_end(); 76 - } 77 - 78 - /* Mark backup_ghcb active before writing to it */ 79 - data->backup_ghcb_active = true; 80 - 81 - state->ghcb = &data->backup_ghcb; 82 - 83 - /* Backup GHCB content */ 84 - *state->ghcb = *ghcb; 85 - } else { 86 - state->ghcb = NULL; 87 - data->ghcb_active = true; 88 - } 89 - 90 - return ghcb; 91 - } 92 - 93 44 /* Include code shared with pre-decompression boot stage */ 94 45 #include "sev-shared.c" 95 - 96 - noinstr void __sev_put_ghcb(struct ghcb_state *state) 97 - { 98 - struct sev_es_runtime_data *data; 99 - struct ghcb *ghcb; 100 - 101 - WARN_ON(!irqs_disabled()); 102 - 103 - data = this_cpu_read(runtime_data); 104 - ghcb = &data->ghcb_page; 105 - 106 - if (state->ghcb) { 107 - /* Restore GHCB from Backup */ 108 - *ghcb = *state->ghcb; 109 - data->backup_ghcb_active = false; 110 - state->ghcb = NULL; 111 - } else { 112 - /* 113 - * Invalidate the GHCB so a VMGEXIT instruction issued 114 - * from userspace won't appear to be valid. 115 - */ 116 - vc_ghcb_invalidate(ghcb); 117 - data->ghcb_active = false; 118 - } 119 - } 120 46 121 47 void __head 122 48 early_set_pages_state(unsigned long vaddr, unsigned long paddr,
+4 -4
arch/x86/coco/sev/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 - obj-y += core.o sev-nmi.o vc-handle.o 3 + obj-y += core.o noinstr.o vc-handle.o 4 4 5 5 # Clang 14 and older may fail to respect __no_sanitize_undefined when inlining 6 - UBSAN_SANITIZE_sev-nmi.o := n 6 + UBSAN_SANITIZE_noinstr.o := n 7 7 8 8 # GCC may fail to respect __no_sanitize_address or __no_kcsan when inlining 9 - KASAN_SANITIZE_sev-nmi.o := n 10 - KCSAN_SANITIZE_sev-nmi.o := n 9 + KASAN_SANITIZE_noinstr.o := n 10 + KCSAN_SANITIZE_noinstr.o := n
+74
arch/x86/coco/sev/sev-nmi.c arch/x86/coco/sev/noinstr.c
··· 106 106 107 107 __sev_put_ghcb(&state); 108 108 } 109 + 110 + /* 111 + * Nothing shall interrupt this code path while holding the per-CPU 112 + * GHCB. The backup GHCB is only for NMIs interrupting this path. 113 + * 114 + * Callers must disable local interrupts around it. 115 + */ 116 + noinstr struct ghcb *__sev_get_ghcb(struct ghcb_state *state) 117 + { 118 + struct sev_es_runtime_data *data; 119 + struct ghcb *ghcb; 120 + 121 + WARN_ON(!irqs_disabled()); 122 + 123 + data = this_cpu_read(runtime_data); 124 + ghcb = &data->ghcb_page; 125 + 126 + if (unlikely(data->ghcb_active)) { 127 + /* GHCB is already in use - save its contents */ 128 + 129 + if (unlikely(data->backup_ghcb_active)) { 130 + /* 131 + * Backup-GHCB is also already in use. There is no way 132 + * to continue here so just kill the machine. To make 133 + * panic() work, mark GHCBs inactive so that messages 134 + * can be printed out. 135 + */ 136 + data->ghcb_active = false; 137 + data->backup_ghcb_active = false; 138 + 139 + instrumentation_begin(); 140 + panic("Unable to handle #VC exception! GHCB and Backup GHCB are already in use"); 141 + instrumentation_end(); 142 + } 143 + 144 + /* Mark backup_ghcb active before writing to it */ 145 + data->backup_ghcb_active = true; 146 + 147 + state->ghcb = &data->backup_ghcb; 148 + 149 + /* Backup GHCB content */ 150 + *state->ghcb = *ghcb; 151 + } else { 152 + state->ghcb = NULL; 153 + data->ghcb_active = true; 154 + } 155 + 156 + return ghcb; 157 + } 158 + 159 + noinstr void __sev_put_ghcb(struct ghcb_state *state) 160 + { 161 + struct sev_es_runtime_data *data; 162 + struct ghcb *ghcb; 163 + 164 + WARN_ON(!irqs_disabled()); 165 + 166 + data = this_cpu_read(runtime_data); 167 + ghcb = &data->ghcb_page; 168 + 169 + if (state->ghcb) { 170 + /* Restore GHCB from Backup */ 171 + *ghcb = *state->ghcb; 172 + data->backup_ghcb_active = false; 173 + state->ghcb = NULL; 174 + } else { 175 + /* 176 + * Invalidate the GHCB so a VMGEXIT instruction issued 177 + * from userspace won't appear to be valid. 178 + */ 179 + vc_ghcb_invalidate(ghcb); 180 + data->ghcb_active = false; 181 + } 182 + }