@@ -71,7 +71,12 @@ core::arch::global_asm!(
7171///
7272pub fn handle_exception_sync ( ctx : & mut TrapFrame ) -> AxResult < AxVCpuExitReason > {
7373 match exception_class ( ) {
74- Some ( ESR_EL2 :: EC :: Value :: DataAbortLowerEL ) => handle_data_abort ( ctx) ,
74+ Some ( ESR_EL2 :: EC :: Value :: DataAbortLowerEL ) => {
75+ let elr = ctx. exception_pc ( ) ;
76+ let val = elr + exception_next_instruction_step ( ) ;
77+ ctx. set_exception_pc ( val) ;
78+ handle_data_abort ( ctx)
79+ }
7580 Some ( ESR_EL2 :: EC :: Value :: HVC64 ) => {
7681 // The `#imm`` argument when triggering a hvc call, currently not used.
7782 let _hvc_arg_imm16 = ESR_EL2 . read ( ESR_EL2 :: ISS ) ;
@@ -96,6 +101,12 @@ pub fn handle_exception_sync(ctx: &mut TrapFrame) -> AxResult<AxVCpuExitReason>
96101 } )
97102 }
98103 Some ( ESR_EL2 :: EC :: Value :: TrappedMsrMrs ) => handle_system_register ( ctx) ,
104+ Some ( ESR_EL2 :: EC :: Value :: SMC64 ) => {
105+ let elr = ctx. exception_pc ( ) ;
106+ let val = elr + exception_next_instruction_step ( ) ;
107+ ctx. set_exception_pc ( val) ;
108+ handle_smc64_exception ( ctx)
109+ }
99110 _ => {
100111 panic ! (
101112 "handler not presents for EC_{} @ipa 0x{:x}, @pc 0x{:x}, @esr 0x{:x},
@@ -116,17 +127,18 @@ pub fn handle_exception_sync(ctx: &mut TrapFrame) -> AxResult<AxVCpuExitReason>
116127
117128fn handle_data_abort ( context_frame : & mut TrapFrame ) -> AxResult < AxVCpuExitReason > {
118129 let addr = exception_fault_addr ( ) ?;
119- debug ! ( "data fault addr {:?}, esr: 0x{:x}" , addr, exception_esr( ) ) ;
120-
121130 let access_width = exception_data_abort_access_width ( ) ;
122131 let is_write = exception_data_abort_access_is_write ( ) ;
123132 //let sign_ext = exception_data_abort_access_is_sign_ext();
124133 let reg = exception_data_abort_access_reg ( ) ;
125134 let reg_width = exception_data_abort_access_reg_width ( ) ;
126135
127- let elr = context_frame. exception_pc ( ) ;
128- let val = elr + exception_next_instruction_step ( ) ;
129- context_frame. set_exception_pc ( val) ;
136+ trace ! (
137+ "Data fault @{:?}, ELR {:#x}, esr: 0x{:x}" ,
138+ addr,
139+ context_frame. exception_pc( ) ,
140+ exception_esr( ) ,
141+ ) ;
130142
131143 let width = match AccessWidth :: try_from ( access_width) {
132144 Ok ( access_width) => access_width,
@@ -209,12 +221,14 @@ fn handle_psci_call(ctx: &mut TrapFrame) -> Option<AxResult<AxVCpuExitReason>> {
209221 const PSCI_FN_RANGE_32 : core:: ops:: RangeInclusive < u64 > = 0x8400_0000 ..=0x8400_001F ;
210222 const PSCI_FN_RANGE_64 : core:: ops:: RangeInclusive < u64 > = 0xC400_0000 ..=0xC400_001F ;
211223
224+ const PSCI_FN_VERSION : u64 = 0x0 ;
212225 const _PSCI_FN_CPU_SUSPEND: u64 = 0x1 ;
213226 const PSCI_FN_CPU_OFF : u64 = 0x2 ;
214227 const PSCI_FN_CPU_ON : u64 = 0x3 ;
215228 const _PSCI_FN_MIGRATE: u64 = 0x5 ;
216229 const PSCI_FN_SYSTEM_OFF : u64 = 0x8 ;
217230 const _PSCI_FN_SYSTEM_RESET: u64 = 0x9 ;
231+ const PSCI_FN_END : u64 = 0x1f ;
218232
219233 let fn_ = ctx. gpr [ 0 ] ;
220234 let fn_offset = if PSCI_FN_RANGE_32 . contains ( & fn_) {
@@ -225,16 +239,35 @@ fn handle_psci_call(ctx: &mut TrapFrame) -> Option<AxResult<AxVCpuExitReason>> {
225239 None
226240 } ;
227241
228- fn_offset . map ( |fn_offset| match fn_offset {
229- PSCI_FN_CPU_OFF => Ok ( AxVCpuExitReason :: CpuDown { _state : ctx. gpr [ 1 ] } ) ,
230- PSCI_FN_CPU_ON => Ok ( AxVCpuExitReason :: CpuUp {
242+ match fn_offset {
243+ Some ( PSCI_FN_CPU_OFF ) => Some ( Ok ( AxVCpuExitReason :: CpuDown { _state : ctx. gpr [ 1 ] } ) ) ,
244+ Some ( PSCI_FN_CPU_ON ) => Some ( Ok ( AxVCpuExitReason :: CpuUp {
231245 target_cpu : ctx. gpr [ 1 ] ,
232246 entry_point : GuestPhysAddr :: from ( ctx. gpr [ 2 ] as usize ) ,
233247 arg : ctx. gpr [ 3 ] ,
234- } ) ,
235- PSCI_FN_SYSTEM_OFF => Ok ( AxVCpuExitReason :: SystemDown ) ,
236- _ => Err ( AxError :: Unsupported ) ,
237- } )
248+ } ) ) ,
249+ Some ( PSCI_FN_SYSTEM_OFF ) => Some ( Ok ( AxVCpuExitReason :: SystemDown ) ) ,
250+ // We just forward these request to the ATF directly.
251+ Some ( PSCI_FN_VERSION ..PSCI_FN_END ) => None ,
252+ _ => None ,
253+ }
254+ }
255+
256+ /// Handles SMC (Secure Monitor Call) exceptions.
257+ ///
258+ /// This function will judge if the SMC call is a PSCI call, if so, it will handle it as a PSCI call.
259+ /// Otherwise, it will forward the SMC call to the ATF directly.
260+ fn handle_smc64_exception ( ctx : & mut TrapFrame ) -> AxResult < AxVCpuExitReason > {
261+ // Is this a psci call?
262+ if let Some ( result) = handle_psci_call ( ctx) {
263+ return result;
264+ } else {
265+ // We just forward the SMC call to the ATF directly.
266+ // The args are from lower EL, so it is safe to call the ATF.
267+ ( ctx. gpr [ 0 ] , ctx. gpr [ 1 ] , ctx. gpr [ 2 ] , ctx. gpr [ 3 ] ) =
268+ unsafe { crate :: smc:: smc_call ( ctx. gpr [ 0 ] , ctx. gpr [ 1 ] , ctx. gpr [ 2 ] , ctx. gpr [ 3 ] ) } ;
269+ Ok ( AxVCpuExitReason :: Nothing )
270+ }
238271}
239272
240273/// Dispatches IRQs to the appropriate handler provided by the underlying host OS,
0 commit comments