@@ -50,7 +50,6 @@ interrupt_exception!(fn debug() => "Debug");
50
50
interrupt_exception ! ( fn non_maskable( ) => "Non Maskable" ) ;
51
51
interrupt_exception ! ( fn overflow( ) => "Stack Overflow" ) ;
52
52
interrupt_exception ! ( fn bound_range( ) => "Out of Bounds" ) ;
53
- interrupt_exception ! ( fn invalid_opcode( ) => "Invalid Opcode" ) ;
54
53
interrupt_exception ! ( fn device_not_available( ) => "Device not Avaliable" ) ;
55
54
interrupt_exception ! ( fn double_fault( ) => "Double Fault" ) ;
56
55
interrupt_exception ! ( fn invalid_tss( ) => "Invalid TSS" ) ;
@@ -64,6 +63,38 @@ interrupt_exception!(fn simd() => "SIMD floating point fault");
64
63
interrupt_exception ! ( fn virtualization( ) => "Virtualization fault" ) ;
65
64
interrupt_exception ! ( fn security( ) => "Security exception" ) ;
66
65
66
+ pub fn invalid_opcode ( stack : & mut InterruptErrorStack ) {
67
+ // Catch SYSENTER on AMD CPUs.
68
+ //
69
+ // The RIP on the stack for #UD points to the instruction which generated the exception.
70
+ // The return RIP and RSP need to be changed to the user-provided values in RCX and R11.
71
+ const SYSENTER_OPCODE : [ u8 ; 2 ] = [ 0x0f , 0x34 ] ;
72
+
73
+ let opcode = unsafe { * ( stack. stack . iret . rip as * const [ u8 ; 2 ] ) } ;
74
+ if opcode == SYSENTER_OPCODE {
75
+ stack. stack . iret . rip = stack. stack . scratch . rcx ;
76
+ stack. stack . iret . rsp = stack. stack . scratch . r11 ;
77
+
78
+ super :: super :: syscall:: x86_64_do_syscall ( stack) ;
79
+ return ;
80
+ }
81
+
82
+ // Otherwise handle the exception as normal.
83
+
84
+ unwind:: prepare_panic ( ) ;
85
+
86
+ log:: error!( "EXCEPTION: Invalid Opcode" ) ;
87
+ log:: error!( "Stack: {:#x?}" , stack) ;
88
+
89
+ unwind:: unwind_stack_trace ( ) ;
90
+
91
+ unsafe {
92
+ loop {
93
+ super :: halt ( ) ;
94
+ }
95
+ }
96
+ }
97
+
67
98
pub fn breakpoint ( stack : & mut InterruptErrorStack ) {
68
99
// We will need to prevent RIP from going out of sync with
69
100
// instructions.
0 commit comments