@@ -340,8 +340,38 @@ pub struct InterruptDescriptorTable {
340
340
/// vector nr. 20
341
341
pub virtualization : Entry < HandlerFunc > ,
342
342
343
- /// vector nr. 21-28
344
- reserved_2 : [ Entry < HandlerFunc > ; 8 ] ,
343
+ /// A #CP exception is generated when shadow stacks are enabled and mismatch
344
+ /// scenarios are detected (possible error code cases below).
345
+ ///
346
+ /// The error code is the #CP error code, for each of the following situations:
347
+ /// - A RET (near) instruction encountered a return address mismatch.
348
+ /// - A RET (far) instruction encountered a return address mismatch.
349
+ /// - A RSTORSSP instruction encountered an invalid shadow stack restore token.
350
+ /// - A SETSSBY instruction encountered an invalid supervisor shadow stack token.
351
+ /// - A missing ENDBRANCH instruction if indirect branch tracking is enabled.
352
+ ///
353
+ /// vector nr. 21
354
+ pub cp_protection_exception : Entry < HandlerFuncWithErrCode > ,
355
+
356
+ /// vector nr. 22-27
357
+ reserved_2 : [ Entry < HandlerFunc > ; 6 ] ,
358
+
359
+ /// The Hypervisor Injection Exception (`#HV`) is injected by a hypervisor
360
+ /// as a doorbell to inform an `SEV-SNP` enabled guest running with the
361
+ /// `Restricted Injection` feature of events to be processed.
362
+ ///
363
+ /// `SEV-SNP` stands for the _"Secure Nested Paging"_ feature of the _"AMD
364
+ /// Secure Encrypted Virtualization"_ technology. The `Restricted
365
+ /// Injection` feature disables all hypervisor-based interrupt queuing
366
+ /// and event injection of all vectors except #HV.
367
+ ///
368
+ /// The `#HV` exception is a benign exception and can only be injected as
369
+ /// an exception and without an error code. `SEV-SNP` enabled guests are
370
+ /// expected to communicate with the hypervisor about events via a
371
+ /// software-managed para-virtualization interface.
372
+ ///
373
+ /// The vector number of the ``#HV`` exception is 28.
374
+ pub hv_injection_exception : Entry < HandlerFunc > ,
345
375
346
376
/// The VMM Communication Exception (`#VC`) is always generated by hardware when an `SEV-ES`
347
377
/// enabled guest is running and an `NAE` event occurs.
@@ -436,7 +466,9 @@ impl InterruptDescriptorTable {
436
466
machine_check : Entry :: missing ( ) ,
437
467
simd_floating_point : Entry :: missing ( ) ,
438
468
virtualization : Entry :: missing ( ) ,
439
- reserved_2 : [ Entry :: missing ( ) ; 8 ] ,
469
+ cp_protection_exception : Entry :: missing ( ) ,
470
+ reserved_2 : [ Entry :: missing ( ) ; 6 ] ,
471
+ hv_injection_exception : Entry :: missing ( ) ,
440
472
vmm_communication_exception : Entry :: missing ( ) ,
441
473
security_exception : Entry :: missing ( ) ,
442
474
reserved_3 : Entry :: missing ( ) ,
@@ -555,9 +587,10 @@ impl Index<usize> for InterruptDescriptorTable {
555
587
16 => & self . x87_floating_point ,
556
588
19 => & self . simd_floating_point ,
557
589
20 => & self . virtualization ,
590
+ 28 => & self . hv_injection_exception ,
558
591
i @ 32 ..=255 => & self . interrupts [ i - 32 ] ,
559
- i @ 15 | i @ 31 | i @ 21 ..=28 => panic ! ( "entry {} is reserved" , i) ,
560
- i @ 8 | i @ 10 ..=14 | i @ 17 | i @ 29 | i @ 30 => {
592
+ i @ 15 | i @ 31 | i @ 22 ..=27 => panic ! ( "entry {} is reserved" , i) ,
593
+ i @ 8 | i @ 10 ..=14 | i @ 17 | i @ 21 | i @ 29 | i @ 30 => {
561
594
panic ! ( "entry {} is an exception with error code" , i)
562
595
}
563
596
i @ 18 => panic ! ( "entry {} is an diverging exception (must not return)" , i) ,
@@ -586,9 +619,10 @@ impl IndexMut<usize> for InterruptDescriptorTable {
586
619
16 => & mut self . x87_floating_point ,
587
620
19 => & mut self . simd_floating_point ,
588
621
20 => & mut self . virtualization ,
622
+ 28 => & mut self . hv_injection_exception ,
589
623
i @ 32 ..=255 => & mut self . interrupts [ i - 32 ] ,
590
- i @ 15 | i @ 31 | i @ 21 ..=28 => panic ! ( "entry {} is reserved" , i) ,
591
- i @ 8 | i @ 10 ..=14 | i @ 17 | i @ 29 | i @ 30 => {
624
+ i @ 15 | i @ 31 | i @ 22 ..=27 => panic ! ( "entry {} is reserved" , i) ,
625
+ i @ 8 | i @ 10 ..=14 | i @ 17 | i @ 21 | i @ 29 | i @ 30 => {
592
626
panic ! ( "entry {} is an exception with error code" , i)
593
627
}
594
628
i @ 18 => panic ! ( "entry {} is an diverging exception (must not return)" , i) ,
@@ -1290,6 +1324,15 @@ macro_rules! set_general_handler_entry {
1290
1324
}
1291
1325
$idt. machine_check. set_handler_fn( handler) ;
1292
1326
} } ;
1327
+ ( $idt: expr, $handler: ident, $idx: ident, 0 , 0 , 0 , 1 , 0 , 1 , 0 , 1 ) => { {
1328
+ extern "x86-interrupt" fn handler(
1329
+ frame: $crate:: structures:: idt:: InterruptStackFrame ,
1330
+ error_code: u64 ,
1331
+ ) {
1332
+ $handler( frame, $idx. into( ) , Some ( error_code) ) ;
1333
+ }
1334
+ $idt. cp_protection_exception. set_handler_fn( handler) ;
1335
+ } } ;
1293
1336
( $idt: expr, $handler: ident, $idx: ident, 0 , 0 , 0 , 1 , 1 , 1 , 0 , 1 ) => {
1294
1337
extern "x86-interrupt" fn handler(
1295
1338
frame: $crate:: structures:: idt:: InterruptStackFrame ,
@@ -1312,14 +1355,12 @@ macro_rules! set_general_handler_entry {
1312
1355
// reserved_1
1313
1356
( $idt: expr, $handler: ident, $idx: ident, 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 ) => { } ;
1314
1357
// reserved_2
1315
- ( $idt: expr, $handler: ident, $idx: ident, 0 , 0 , 0 , 1 , 0 , 1 , 0 , 1 ) => { } ;
1316
1358
( $idt: expr, $handler: ident, $idx: ident, 0 , 0 , 0 , 1 , 0 , 1 , 1 , 0 ) => { } ;
1317
1359
( $idt: expr, $handler: ident, $idx: ident, 0 , 0 , 0 , 1 , 0 , 1 , 1 , 1 ) => { } ;
1318
1360
( $idt: expr, $handler: ident, $idx: ident, 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 ) => { } ;
1319
1361
( $idt: expr, $handler: ident, $idx: ident, 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 ) => { } ;
1320
1362
( $idt: expr, $handler: ident, $idx: ident, 0 , 0 , 0 , 1 , 1 , 0 , 1 , 0 ) => { } ;
1321
1363
( $idt: expr, $handler: ident, $idx: ident, 0 , 0 , 0 , 1 , 1 , 0 , 1 , 1 ) => { } ;
1322
- ( $idt: expr, $handler: ident, $idx: ident, 0 , 0 , 0 , 1 , 1 , 1 , 0 , 0 ) => { } ;
1323
1364
// reserved_3
1324
1365
( $idt: expr, $handler: ident, $idx: ident, 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 ) => { } ;
1325
1366
@@ -1348,7 +1389,9 @@ mod test {
1348
1389
15 => & idt. reserved_1 . options ,
1349
1390
17 => & idt. alignment_check . options ,
1350
1391
18 => & idt. machine_check . options ,
1351
- i @ 21 ..=28 => & idt. reserved_2 [ i - 21 ] . options ,
1392
+ 21 => & idt. cp_protection_exception . options ,
1393
+ i @ 22 ..=27 => & idt. reserved_2 [ i - 22 ] . options ,
1394
+ 28 => & idt. hv_injection_exception . options ,
1352
1395
29 => & idt. vmm_communication_exception . options ,
1353
1396
30 => & idt. security_exception . options ,
1354
1397
31 => & idt. reserved_3 . options ,
@@ -1404,7 +1447,7 @@ mod test {
1404
1447
}
1405
1448
set_general_handler ! ( & mut idt, general_handler) ;
1406
1449
for i in 0 ..256 {
1407
- if i == 15 || i == 31 || ( 21 ..=28 ) . contains ( & i) {
1450
+ if i == 15 || i == 31 || ( 22 ..=27 ) . contains ( & i) {
1408
1451
// reserved entries should not be set
1409
1452
assert ! ( !entry_present( & idt, i) ) ;
1410
1453
} else {
0 commit comments