@@ -21,20 +21,86 @@ use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
2121use  hyperlight_common:: outb:: Exception ; 
2222use  hyperlight_guest:: exit:: abort_with_code_and_message; 
2323
24+ use  crate :: paging; 
25+ 
26+ /// See AMD64 Architecture Programmer's Manual, Volume 2 
27+ ///     §8.9.3 Interrupt Stack Frame, pp. 283--284 
28+ ///       Figure 8-14: Long-Mode Stack After Interrupt---Same Privilege, 
29+ ///       Figure 8-15: Long-Mode Stack After Interrupt---Higher Privilege 
30+ /// Subject to the proviso that we push a dummy error code of 0 for exceptions 
31+ /// for which the processor does not provide one 
32+ #[ repr( C ) ]  
33+ pub  struct  ExceptionInfo  { 
34+     pub  error_code :  u64 , 
35+     pub  rip :  u64 , 
36+     pub  cs :  u64 , 
37+     pub  rflags :  u64 , 
38+     pub  rsp :  u64 , 
39+     pub  ss :  u64 , 
40+ } 
41+ const  _:  ( )  = assert ! ( core:: mem:: offset_of!( ExceptionInfo ,  rip)  == 8 ) ; 
42+ const  _:  ( )  = assert ! ( core:: mem:: offset_of!( ExceptionInfo ,  rsp)  == 32 ) ; 
43+ 
44+ #[ repr( C ) ]  
45+ /// Saved context, pushed onto the stack by exception entry code 
46+ pub  struct  Context  { 
47+     /// in order: gs, fs, es 
48+ pub  segments :  [ u64 ;  3 ] , 
49+     pub  fxsave :  [ u8 ;  512 ] , 
50+     pub  ds :  u64 , 
51+     /// no `rsp`, since the processor saved it 
52+ /// `rax` is at the top, `r15` the bottom 
53+ pub  gprs :  [ u64 ;  15 ] , 
54+ } 
55+ const  _:  ( )  = assert ! ( size_of:: <Context >( )  == 152  + 512 ) ; 
56+ 
57+ // TODO: This will eventually need to end up in a per-thread context, 
58+ // when there are threads. 
59+ pub  static  handlers:  [ core:: sync:: atomic:: AtomicU64 ;  31 ]  =
60+     [ const  {  core:: sync:: atomic:: AtomicU64 :: new ( 0 )  } ;  31 ] ; 
61+ type  handler_t  = fn ( n :  u64 ,  info :  * mut  ExceptionInfo ,  ctx :  * mut  Context ,  pf_addr :  u64 )  -> bool ; 
62+ 
2463/// Exception handler 
2564#[ unsafe( no_mangle) ]  
2665pub  extern  "C"  fn  hl_exception_handler ( 
2766    stack_pointer :  u64 , 
2867    exception_number :  u64 , 
2968    page_fault_address :  u64 , 
3069)  { 
70+     let  ctx = stack_pointer as  * mut  Context ; 
71+     let  exn_info = ( stack_pointer + size_of :: < Context > ( )  as  u64 )  as  * mut  ExceptionInfo ; 
72+ 
3173    let  exception = Exception :: try_from ( exception_number as  u8 ) . expect ( "Invalid exception number" ) ; 
74+ 
75+     let  saved_rip = unsafe  {  ( & raw  const  ( * exn_info) . rip ) . read_volatile ( )  } ; 
76+     let  error_code = unsafe  {  ( & raw  const  ( * exn_info) . error_code ) . read_volatile ( )  } ; 
77+ 
3278    let  msg = format ! ( 
33-         "Page Fault Address: {:#x}\n \  
34- , 
35-         page_fault_address,  stack_pointer
79+         "Exception vector: {:#}\n \  
80+ \n \ 
81+ \n \ 
82+ \n \ 
83+ , 
84+         exception_number,  saved_rip,  page_fault_address,  error_code,  stack_pointer
3685    ) ; 
3786
87+     if  exception_number < 31  { 
88+         let  handler =
89+             handlers[ exception_number as  usize ] . load ( core:: sync:: atomic:: Ordering :: Acquire ) ; 
90+         if  handler != 0 
91+             && unsafe  { 
92+                 core:: mem:: transmute :: < _ ,  handler_t > ( handler) ( 
93+                     exception_number, 
94+                     exn_info, 
95+                     ctx, 
96+                     page_fault_address, 
97+                 ) 
98+             } 
99+         { 
100+             return ; 
101+         } 
102+     } 
103+ 
38104    unsafe  { 
39105        abort_with_code_and_message ( 
40106            & [ ErrorCode :: GuestError  as  u8 ,  exception as  u8 ] , 
0 commit comments