khypervisor  v1
trap.c
Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines