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.

Merge tag 'x86_urgent_for_v5.13_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Borislav Petkov:

- Fix how SEV handles MMIO accesses by forwarding potential page faults
instead of killing the machine and by using the accessors with the
exact functionality needed when accessing memory.

- Fix a confusion with Clang LTO compiler switches passed to the it

- Handle the case gracefully when VMGEXIT has been executed in
userspace

* tag 'x86_urgent_for_v5.13_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/sev-es: Use __put_user()/__get_user() for data accesses
x86/sev-es: Forward page-faults which happen during emulation
x86/sev-es: Don't return NULL from sev_es_get_ghcb()
x86/build: Fix location of '-plugin-opt=' flags
x86/sev-es: Invalidate the GHCB after completing VMGEXIT
x86/sev-es: Move sev_es_put_ghcb() in prep for follow on patch

+92 -57
+6 -6
arch/x86/Makefile
··· 178 178 KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args,) 179 179 endif 180 180 181 - ifdef CONFIG_LTO_CLANG 182 - KBUILD_LDFLAGS += -plugin-opt=-code-model=kernel \ 183 - -plugin-opt=-stack-alignment=$(if $(CONFIG_X86_32),4,8) 184 - endif 185 - 186 181 # Workaround for a gcc prelease that unfortunately was shipped in a suse release 187 182 KBUILD_CFLAGS += -Wno-sign-compare 188 183 # ··· 197 202 endif 198 203 endif 199 204 200 - KBUILD_LDFLAGS := -m elf_$(UTS_MACHINE) 205 + KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE) 206 + 207 + ifdef CONFIG_LTO_CLANG 208 + KBUILD_LDFLAGS += -plugin-opt=-code-model=kernel \ 209 + -plugin-opt=-stack-alignment=$(if $(CONFIG_X86_32),4,8) 210 + endif 201 211 202 212 ifdef CONFIG_X86_NEED_RELOCS 203 213 LDFLAGS_vmlinux := --emit-relocs --discard-none
+1
arch/x86/kernel/sev-shared.c
··· 63 63 64 64 static __always_inline void vc_ghcb_invalidate(struct ghcb *ghcb) 65 65 { 66 + ghcb->save.sw_exit_code = 0; 66 67 memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap)); 67 68 } 68 69
+85 -51
arch/x86/kernel/sev.c
··· 203 203 if (unlikely(data->ghcb_active)) { 204 204 /* GHCB is already in use - save its contents */ 205 205 206 - if (unlikely(data->backup_ghcb_active)) 207 - return NULL; 206 + if (unlikely(data->backup_ghcb_active)) { 207 + /* 208 + * Backup-GHCB is also already in use. There is no way 209 + * to continue here so just kill the machine. To make 210 + * panic() work, mark GHCBs inactive so that messages 211 + * can be printed out. 212 + */ 213 + data->ghcb_active = false; 214 + data->backup_ghcb_active = false; 215 + 216 + panic("Unable to handle #VC exception! GHCB and Backup GHCB are already in use"); 217 + } 208 218 209 219 /* Mark backup_ghcb active before writing to it */ 210 220 data->backup_ghcb_active = true; ··· 229 219 } 230 220 231 221 return ghcb; 232 - } 233 - 234 - static __always_inline void sev_es_put_ghcb(struct ghcb_state *state) 235 - { 236 - struct sev_es_runtime_data *data; 237 - struct ghcb *ghcb; 238 - 239 - data = this_cpu_read(runtime_data); 240 - ghcb = &data->ghcb_page; 241 - 242 - if (state->ghcb) { 243 - /* Restore GHCB from Backup */ 244 - *ghcb = *state->ghcb; 245 - data->backup_ghcb_active = false; 246 - state->ghcb = NULL; 247 - } else { 248 - data->ghcb_active = false; 249 - } 250 222 } 251 223 252 224 /* Needed in vc_early_forward_exception */ ··· 315 323 u16 d2; 316 324 u8 d1; 317 325 318 - /* If instruction ran in kernel mode and the I/O buffer is in kernel space */ 319 - if (!user_mode(ctxt->regs) && !access_ok(target, size)) { 320 - memcpy(dst, buf, size); 321 - return ES_OK; 322 - } 323 - 326 + /* 327 + * This function uses __put_user() independent of whether kernel or user 328 + * memory is accessed. This works fine because __put_user() does no 329 + * sanity checks of the pointer being accessed. All that it does is 330 + * to report when the access failed. 331 + * 332 + * Also, this function runs in atomic context, so __put_user() is not 333 + * allowed to sleep. The page-fault handler detects that it is running 334 + * in atomic context and will not try to take mmap_sem and handle the 335 + * fault, so additional pagefault_enable()/disable() calls are not 336 + * needed. 337 + * 338 + * The access can't be done via copy_to_user() here because 339 + * vc_write_mem() must not use string instructions to access unsafe 340 + * memory. The reason is that MOVS is emulated by the #VC handler by 341 + * splitting the move up into a read and a write and taking a nested #VC 342 + * exception on whatever of them is the MMIO access. Using string 343 + * instructions here would cause infinite nesting. 344 + */ 324 345 switch (size) { 325 346 case 1: 326 347 memcpy(&d1, buf, 1); 327 - if (put_user(d1, target)) 348 + if (__put_user(d1, target)) 328 349 goto fault; 329 350 break; 330 351 case 2: 331 352 memcpy(&d2, buf, 2); 332 - if (put_user(d2, target)) 353 + if (__put_user(d2, target)) 333 354 goto fault; 334 355 break; 335 356 case 4: 336 357 memcpy(&d4, buf, 4); 337 - if (put_user(d4, target)) 358 + if (__put_user(d4, target)) 338 359 goto fault; 339 360 break; 340 361 case 8: 341 362 memcpy(&d8, buf, 8); 342 - if (put_user(d8, target)) 363 + if (__put_user(d8, target)) 343 364 goto fault; 344 365 break; 345 366 default: ··· 383 378 u16 d2; 384 379 u8 d1; 385 380 386 - /* If instruction ran in kernel mode and the I/O buffer is in kernel space */ 387 - if (!user_mode(ctxt->regs) && !access_ok(s, size)) { 388 - memcpy(buf, src, size); 389 - return ES_OK; 390 - } 391 - 381 + /* 382 + * This function uses __get_user() independent of whether kernel or user 383 + * memory is accessed. This works fine because __get_user() does no 384 + * sanity checks of the pointer being accessed. All that it does is 385 + * to report when the access failed. 386 + * 387 + * Also, this function runs in atomic context, so __get_user() is not 388 + * allowed to sleep. The page-fault handler detects that it is running 389 + * in atomic context and will not try to take mmap_sem and handle the 390 + * fault, so additional pagefault_enable()/disable() calls are not 391 + * needed. 392 + * 393 + * The access can't be done via copy_from_user() here because 394 + * vc_read_mem() must not use string instructions to access unsafe 395 + * memory. The reason is that MOVS is emulated by the #VC handler by 396 + * splitting the move up into a read and a write and taking a nested #VC 397 + * exception on whatever of them is the MMIO access. Using string 398 + * instructions here would cause infinite nesting. 399 + */ 392 400 switch (size) { 393 401 case 1: 394 - if (get_user(d1, s)) 402 + if (__get_user(d1, s)) 395 403 goto fault; 396 404 memcpy(buf, &d1, 1); 397 405 break; 398 406 case 2: 399 - if (get_user(d2, s)) 407 + if (__get_user(d2, s)) 400 408 goto fault; 401 409 memcpy(buf, &d2, 2); 402 410 break; 403 411 case 4: 404 - if (get_user(d4, s)) 412 + if (__get_user(d4, s)) 405 413 goto fault; 406 414 memcpy(buf, &d4, 4); 407 415 break; 408 416 case 8: 409 - if (get_user(d8, s)) 417 + if (__get_user(d8, s)) 410 418 goto fault; 411 419 memcpy(buf, &d8, 8); 412 420 break; ··· 478 460 479 461 /* Include code shared with pre-decompression boot stage */ 480 462 #include "sev-shared.c" 463 + 464 + static __always_inline void sev_es_put_ghcb(struct ghcb_state *state) 465 + { 466 + struct sev_es_runtime_data *data; 467 + struct ghcb *ghcb; 468 + 469 + data = this_cpu_read(runtime_data); 470 + ghcb = &data->ghcb_page; 471 + 472 + if (state->ghcb) { 473 + /* Restore GHCB from Backup */ 474 + *ghcb = *state->ghcb; 475 + data->backup_ghcb_active = false; 476 + state->ghcb = NULL; 477 + } else { 478 + /* 479 + * Invalidate the GHCB so a VMGEXIT instruction issued 480 + * from userspace won't appear to be valid. 481 + */ 482 + vc_ghcb_invalidate(ghcb); 483 + data->ghcb_active = false; 484 + } 485 + } 481 486 482 487 void noinstr __sev_es_nmi_complete(void) 483 488 { ··· 1296 1255 case X86_TRAP_UD: 1297 1256 exc_invalid_op(ctxt->regs); 1298 1257 break; 1258 + case X86_TRAP_PF: 1259 + write_cr2(ctxt->fi.cr2); 1260 + exc_page_fault(ctxt->regs, error_code); 1261 + break; 1299 1262 case X86_TRAP_AC: 1300 1263 exc_alignment_check(ctxt->regs, error_code); 1301 1264 break; ··· 1329 1284 */ 1330 1285 DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication) 1331 1286 { 1332 - struct sev_es_runtime_data *data = this_cpu_read(runtime_data); 1333 1287 irqentry_state_t irq_state; 1334 1288 struct ghcb_state state; 1335 1289 struct es_em_ctxt ctxt; ··· 1354 1310 */ 1355 1311 1356 1312 ghcb = sev_es_get_ghcb(&state); 1357 - if (!ghcb) { 1358 - /* 1359 - * Mark GHCBs inactive so that panic() is able to print the 1360 - * message. 1361 - */ 1362 - data->ghcb_active = false; 1363 - data->backup_ghcb_active = false; 1364 - 1365 - panic("Unable to handle #VC exception! GHCB and Backup GHCB are already in use"); 1366 - } 1367 1313 1368 1314 vc_ghcb_invalidate(ghcb); 1369 1315 result = vc_init_em_ctxt(&ctxt, regs, error_code);