Skip to content

Commit 9d2c720

Browse files
joergroedelbp3tk0v
authored andcommitted
x86/debug: Fix stack recursion caused by wrongly ordered DR7 accesses
In kernels compiled with CONFIG_PARAVIRT=n, the compiler re-orders the DR7 read in exc_nmi() to happen before the call to sev_es_ist_enter(). This is problematic when running as an SEV-ES guest because in this environment the DR7 read might cause a #VC exception, and taking #VC exceptions is not safe in exc_nmi() before sev_es_ist_enter() has run. The result is stack recursion if the NMI was caused on the #VC IST stack, because a subsequent #VC exception in the NMI handler will overwrite the stack frame of the interrupted #VC handler. As there are no compiler barriers affecting the ordering of DR7 reads/writes, make the accesses to this register volatile, forbidding the compiler to re-order them. [ bp: Massage text, make them volatile too, to make sure some aggressive compiler optimization pass doesn't discard them. ] Fixes: 315562c ("x86/sev-es: Adjust #VC IST Stack on entering NMI handler") Reported-by: Alexey Kardashevskiy <[email protected]> Signed-off-by: Joerg Roedel <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected]
1 parent 6d796c5 commit 9d2c720

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

arch/x86/include/asm/debugreg.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,20 @@ static __always_inline unsigned long native_get_debugreg(int regno)
3939
asm("mov %%db6, %0" :"=r" (val));
4040
break;
4141
case 7:
42-
asm("mov %%db7, %0" :"=r" (val));
42+
/*
43+
* Apply __FORCE_ORDER to DR7 reads to forbid re-ordering them
44+
* with other code.
45+
*
46+
* This is needed because a DR7 access can cause a #VC exception
47+
* when running under SEV-ES. Taking a #VC exception is not a
48+
* safe thing to do just anywhere in the entry code and
49+
* re-ordering might place the access into an unsafe location.
50+
*
51+
* This happened in the NMI handler, where the DR7 read was
52+
* re-ordered to happen before the call to sev_es_ist_enter(),
53+
* causing stack recursion.
54+
*/
55+
asm volatile("mov %%db7, %0" : "=r" (val) : __FORCE_ORDER);
4356
break;
4457
default:
4558
BUG();
@@ -66,7 +79,16 @@ static __always_inline void native_set_debugreg(int regno, unsigned long value)
6679
asm("mov %0, %%db6" ::"r" (value));
6780
break;
6881
case 7:
69-
asm("mov %0, %%db7" ::"r" (value));
82+
/*
83+
* Apply __FORCE_ORDER to DR7 writes to forbid re-ordering them
84+
* with other code.
85+
*
86+
* While is didn't happen with a DR7 write (see the DR7 read
87+
* comment above which explains where it happened), add the
88+
* __FORCE_ORDER here too to avoid similar problems in the
89+
* future.
90+
*/
91+
asm volatile("mov %0, %%db7" ::"r" (value), __FORCE_ORDER);
7092
break;
7193
default:
7294
BUG();

0 commit comments

Comments
 (0)