khypervisor
v1
|
00001 #include <hvmm_trace.h> 00002 #include <armv7_p15.h> 00003 #include "trap.h" 00004 #include "context.h" 00005 #include "gic.h" 00006 #include "sched_policy.h" 00007 #include "trap_dabort.h" 00008 00009 #include <log/print.h> 00010 00011 /* By holding the address to the saved regs struct, 00012 context or other modules can access to this structure 00013 through trap_saved_regs() call when it's needed. 00014 For example, copying register values for context switching can be 00015 performed this way. 00016 */ 00017 00018 static struct arch_regs *_trap_hyp_saved_regs = 0; 00019 00020 hvmm_status_t _hyp_trap_dabort( struct arch_regs *regs ) 00021 { 00022 00023 _trap_hyp_saved_regs = regs; 00024 00025 context_dump_regs( regs ); 00026 hyp_abort_infinite(); 00027 00028 return HVMM_STATUS_UNKNOWN_ERROR; 00029 } 00030 00031 hvmm_status_t _hyp_trap_irq( struct arch_regs *regs ) 00032 { 00033 00034 _trap_hyp_saved_regs = regs; 00035 00036 gic_interrupt(0, regs); 00037 00038 context_perform_switch(); 00039 return HVMM_STATUS_SUCCESS; 00040 } 00041 00042 hvmm_status_t _hyp_trap_unhandled( struct arch_regs *regs ) 00043 { 00044 _trap_hyp_saved_regs = regs; 00045 00046 context_dump_regs( regs ); 00047 hyp_abort_infinite(); 00048 00049 return HVMM_STATUS_UNKNOWN_ERROR; 00050 } 00051 00052 static void _trap_dump_bregs(void) 00053 { 00054 uint32_t spsr, lr, sp; 00055 printh( " - banked regs\n" ); 00056 asm volatile (" mrs %0, sp_usr\n\t" :"=r" (sp)::"memory", "cc"); 00057 asm volatile (" mrs %0, lr_usr\n\t" :"=r" (lr)::"memory", "cc"); 00058 printh( " - usr: sp:%x lr:%x\n", sp, lr ); 00059 00060 asm volatile (" mrs %0, spsr_svc\n\t" :"=r" (spsr)::"memory", "cc"); 00061 asm volatile (" mrs %0, sp_svc\n\t" :"=r" (sp)::"memory", "cc"); 00062 asm volatile (" mrs %0, lr_svc\n\t" :"=r" (lr)::"memory", "cc"); 00063 printh( " - svc: spsr:%x sp:%x lr:%x\n", spsr, sp, lr ); 00064 00065 asm volatile (" mrs %0, spsr_irq\n\t" :"=r" (spsr)::"memory", "cc"); 00066 asm volatile (" mrs %0, sp_irq\n\t" :"=r" (sp)::"memory", "cc"); 00067 asm volatile (" mrs %0, lr_irq\n\t" :"=r" (lr)::"memory", "cc"); 00068 printh( " - irq: spsr:%x sp:%x lr:%x\n", spsr, sp, lr ); 00069 } 00070 00071 /* 00072 * hvc #imm handler 00073 * 00074 * HYP Syndrome Register(HSR) 00075 * EC[31:26] is an exception class for the exception that is taken to HYP mode 00076 * IL[25] is an instruction length for the trapped insruction that is 16 bit or 32 bit 00077 * ISS[24:0] is an instruction-specific syndrome for the instruction information included. It depends on EC field. 00078 * END OF HSR DESCRIPTION FROM ARM DDI0406_C ARCHITECTURE MANUAL 00079 */ 00080 hyp_hvc_result_t _hyp_hvc_service(struct arch_regs *regs) 00081 { 00082 unsigned int hsr = read_hsr(); 00083 unsigned int iss = hsr & 0x1FFFFFF; 00084 unsigned int ec = (hsr >> 26); 00085 00086 _trap_hyp_saved_regs = regs; 00087 00088 printh("[hvc] _hyp_hvc_service: enter\n\r"); 00089 00090 if ( ec == 0x12 && ((iss & 0xFFFF) == 0xFFFF) ) { 00091 /* Internal request to stay in hyp mode */ 00092 printh("[hvc] enter hyp\n\r"); 00093 context_dump_regs( regs ); 00094 return HYP_RESULT_STAY; 00095 } 00096 00097 if ( ec == 0x24) { 00098 /* Handle data abort at the priority */ 00099 printh("[hyp] data abort handler: hsr.iss=%x\n", iss); 00100 _trap_dump_bregs(); 00101 00102 if ( trap_hvc_dabort(iss, regs) != HVMM_STATUS_SUCCESS ) { 00103 printh( "[hyp] === Unhandled dabort ===\n" ); 00104 printh( "[hyp] current guest vmid:%d\n", context_current_vmid() ); 00105 context_dump_regs( regs ); 00106 00107 _trap_dump_bregs(); 00108 00109 hyp_abort_infinite(); 00110 } 00111 _trap_dump_bregs(); 00112 } else { 00113 /* Handle the other cases */ 00114 switch( iss ) { 00115 case 0xFFFE: 00116 /* hyp_ping */ 00117 printh("[hyp] _hyp_hvc_service:ping\n\r"); 00118 context_dump_regs( regs ); 00119 break; 00120 case 0xFFFD: 00121 { 00122 /* hsvc_yield() */ 00123 printh("[hyp] _hyp_hvc_service:yield\n\r"); 00124 context_dump_regs( regs ); 00125 context_switchto(sched_policy_determ_next()); 00126 } 00127 break; 00128 default: 00129 if ( ec == 0x20 ) { 00130 // Prefetch Abort routed to Hyp mode 00131 printh( "[hyp]: prefetch abort routed to Hyp mode\n"); 00132 } 00133 00134 printh("[hyp] _hyp_hvc_service:unknown hsr.iss= %x\n", iss); 00135 printh("[hyp] hsr.ec= %x\n", ec); 00136 printh("[hyp] hsr= %x\n", hsr); 00137 context_dump_regs( regs ); 00138 _trap_dump_bregs(); 00139 hyp_abort_infinite(); 00140 break; 00141 } 00142 } 00143 printh("[hyp] _hyp_hvc_service: done\n\r"); 00144 00145 context_perform_switch(); 00146 return HYP_RESULT_ERET; 00147 } 00148 00149 /* API */ 00150 00151 struct arch_regs * trap_saved_regs(void) 00152 { 00153 return _trap_hyp_saved_regs; 00154 }