khypervisor  v1
context.c
Go to the documentation of this file.
00001 #include <armv7_p15.h>
00002 #include <arch_types.h>
00003 #include <k-hypervisor-config.h>
00004 #include <mm.h>
00005 #include <gic.h>
00006 #include <interrupt.h>
00007 #include <context.h>
00008 #include <scheduler.h>
00009 #include <hvmm_trace.h>
00010 #include <vdev.h>
00011 #include <vdev/vdev_gicd.h>
00012 #include <gic_regs.h>
00013 #include <virqmap.h>
00014 #include <trap.h>
00015 #include <vmm.h>
00016 
00017 #include <string.h>
00018 #if defined (LINUX_GUEST)
00019 #include "loadlinux.h"
00020 #endif
00021 
00022 #include <config/cfg_platform.h>
00023 
00024 #include <log/uart_print.h>
00025 #include <log/print.h>
00026 #include <test/tests.h>
00027 
00028 #include <log/uart_print.h>
00029 #include <log/print.h>
00030 #include <version.h>
00031 
00032 #define NUM_GUEST_CONTEXTS      NUM_GUESTS_STATIC
00033 
00034 #define CPSR_MODE_USER  0x10
00035 #define CPSR_MODE_FIQ   0x11
00036 #define CPSR_MODE_IRQ   0x12
00037 #define CPSR_MODE_SVC   0x13
00038 #define CPSR_MODE_MON   0x16
00039 #define CPSR_MODE_ABT   0x17
00040 #define CPSR_MODE_HYP   0x1A
00041 #define CPSR_MODE_UND   0x1B
00042 #define CPSR_MODE_SYS   0x1F
00043 
00044 #define __CONTEXT_TRACE_VERBOSE__
00045 #define _valid_vmid(vmid)   ( context_first_vmid() <= vmid && context_last_vmid() >= vmid )
00046 
00047 extern void __mon_switch_to_guest_context( struct arch_regs *regs );
00048 
00049 static struct hyp_guest_context guest_contexts[NUM_GUEST_CONTEXTS];
00050 static int _current_guest_vmid = VMID_INVALID;
00051 static int _next_guest_vmid = VMID_INVALID;
00052 static uint8_t _switch_locked = 0;  /* further switch request will be ignored if set */
00053 
00054 #if defined (BAREMETAL_GUEST) && !defined (LINUX_GUEST)
00055 #define FIXUP_BMGUEST_LOAD_AT_GUEST1
00056 #endif
00057 
00058 #if defined (LINUX_GUEST)
00059 static void _hyp_guest0_copy_zimage(void)
00060 {
00061     extern uint32_t guest_bin_start;
00062     extern uint32_t guest_bin_end;
00063 
00064     uint32_t *src = &guest_bin_start;
00065     uint32_t *end = &guest_bin_end;
00066     uint32_t *dst = &guest_bin_start + (0x20008000/4);
00067 
00068     HVMM_TRACE_ENTER();
00069 
00070     uart_print("Copying guest0 image to guest1\n\r");
00071     uart_print(" src:");uart_print_hex32((uint32_t)src); 
00072     uart_print(" dst:");uart_print_hex32((uint32_t)dst); 
00073     uart_print(" size:");uart_print_hex32( (uint32_t)(end - src) * sizeof(uint32_t));uart_print("\n\r");
00074 
00075     while(src < end ) {
00076         *dst++ = *src++;
00077     }
00078     uart_print("=== done ===\n\r");
00079     HVMM_TRACE_EXIT();
00080 }
00081 #endif
00082 
00083 #if defined (FIXUP_BMGUEST_LOAD_AT_GUEST1) 
00084 static void _hyp_fixup_unloaded_guest(void)
00085 {
00086     extern uint32_t guest_bin_start;
00087     extern uint32_t guest_bin_end;
00088     extern uint32_t guest2_bin_start;
00089 
00090     uint32_t *src = &guest_bin_start;
00091     uint32_t *end = &guest_bin_end;
00092     uint32_t *dst = &guest2_bin_start;
00093 
00094     HVMM_TRACE_ENTER();
00095 
00096     uart_print("Copying guest0 image to guest1\n\r");
00097     uart_print(" src:");uart_print_hex32((uint32_t)src); 
00098     uart_print(" dst:");uart_print_hex32((uint32_t)dst); 
00099     uart_print(" size:");uart_print_hex32( (uint32_t)(end - src) * sizeof(uint32_t));uart_print("\n\r");
00100 
00101     while(src < end ) {
00102         *dst++ = *src++;
00103     }
00104     uart_print("=== done ===\n\r");
00105     HVMM_TRACE_EXIT();
00106 }
00107 #endif
00108 
00109 #ifdef DEBUG
00110 static char *_modename(uint8_t mode)
00111 {
00112     char *name = "Unknown";
00113     switch(mode) {
00114         case CPSR_MODE_USER:
00115             name = "User";
00116             break;
00117         case CPSR_MODE_FIQ:
00118             name = "FIQ";
00119             break;
00120         case CPSR_MODE_IRQ:
00121             name = "IRQ";
00122             break;
00123         case CPSR_MODE_SVC:
00124             name = "Supervisor";
00125             break;
00126         case CPSR_MODE_MON:
00127             name = "Monitor";
00128             break;
00129         case CPSR_MODE_ABT:
00130             name = "Abort";
00131             break;
00132         case CPSR_MODE_HYP:
00133             name = "Hyp";
00134             break;
00135         case CPSR_MODE_UND:
00136             name = "Undefined";
00137             break;
00138         case CPSR_MODE_SYS:
00139             name = "System";
00140             break;
00141     }
00142     return name;
00143 }
00144 #endif
00145 void context_dump_regs( struct arch_regs *regs )
00146 {
00147 #ifdef DEBUG
00148     uart_print( "cpsr:" ); uart_print_hex32( regs->cpsr ); uart_print( "\n\r" );
00149     uart_print( "  pc:" ); uart_print_hex32( regs->pc ); uart_print( "\n\r" );
00150     uart_print( "  lr:" ); uart_print_hex32( regs->lr ); uart_print( "\n\r" );
00151 
00152 #ifdef __CONTEXT_TRACE_VERBOSE__
00153     {
00154         int i;
00155         uart_print( " gpr:\n\r" );
00156         for( i = 0; i < ARCH_REGS_NUM_GPR; i++) {
00157             uart_print( "     " ); uart_print_hex32( regs->gpr[i] ); uart_print( "\n\r" );
00158         }
00159     }
00160 #endif
00161 #endif
00162 }
00163 static void context_copy_regs( struct arch_regs *regs_dst, struct arch_regs *regs_src )
00164 {
00165     int i;
00166     regs_dst->cpsr = regs_src->cpsr;
00167     regs_dst->pc = regs_src->pc;
00168     regs_dst->lr = regs_src->lr;
00169     for( i = 0; i < ARCH_REGS_NUM_GPR; i++) {
00170         regs_dst->gpr[i] = regs_src->gpr[i];
00171     }
00172 }
00173 
00174 /* banked registers */
00175 
00176 void context_init_banked(struct arch_regs_banked *regs_banked)
00177 {
00178     regs_banked->sp_usr = 0;
00179     regs_banked->spsr_svc = 0;
00180     regs_banked->sp_svc = 0;
00181     regs_banked->lr_svc = 0;
00182     regs_banked->spsr_abt = 0;
00183     regs_banked->sp_abt = 0;
00184     regs_banked->lr_abt = 0;
00185     regs_banked->spsr_und = 0;
00186     regs_banked->sp_und = 0;
00187     regs_banked->lr_und = 0;
00188     regs_banked->spsr_irq = 0;
00189     regs_banked->sp_irq = 0;
00190     regs_banked->lr_irq = 0;
00191     regs_banked->spsr_fiq = 0;
00192     regs_banked->lr_fiq = 0;
00193     regs_banked->r8_fiq = 0;
00194     regs_banked->r9_fiq = 0;
00195     regs_banked->r10_fiq = 0;
00196     regs_banked->r11_fiq = 0;
00197     regs_banked->r12_fiq = 0;
00198     //Cortex-A15 processor does not support sp_fiq
00199 }
00200 
00201 void context_save_banked(struct arch_regs_banked *regs_banked)
00202 {
00203     /* USR banked register */
00204     asm volatile (" mrs     %0, sp_usr\n\t"
00205                           :"=r" (regs_banked->sp_usr)::"memory", "cc");
00206 
00207     /* SVC banked register */
00208     asm volatile (" mrs     %0, spsr_svc\n\t"
00209                           :"=r" (regs_banked->spsr_svc)::"memory", "cc");
00210     asm volatile (" mrs     %0, sp_svc\n\t"
00211                           :"=r" (regs_banked->sp_svc)::"memory", "cc");
00212     asm volatile (" mrs     %0, lr_svc\n\t"
00213                           :"=r" (regs_banked->lr_svc)::"memory", "cc");
00214 
00215     /* ABT banked register */
00216     asm volatile (" mrs     %0, spsr_abt\n\t"
00217                           :"=r" (regs_banked->spsr_abt)::"memory", "cc");
00218     asm volatile (" mrs     %0, sp_abt\n\t"
00219                           :"=r" (regs_banked->sp_abt)::"memory", "cc");
00220     asm volatile (" mrs     %0, lr_abt\n\t"
00221                           :"=r" (regs_banked->lr_abt)::"memory", "cc");
00222 
00223     /* UND banked register */
00224     asm volatile (" mrs     %0, spsr_und\n\t"
00225                           :"=r" (regs_banked->spsr_und)::"memory", "cc");
00226     asm volatile (" mrs     %0, sp_und\n\t"
00227                           :"=r" (regs_banked->sp_und)::"memory", "cc");
00228     asm volatile (" mrs     %0, lr_und\n\t"
00229                           :"=r" (regs_banked->lr_und)::"memory", "cc");
00230 
00231     /* IRQ banked register */
00232     asm volatile (" mrs     %0, spsr_irq\n\t"
00233                           :"=r" (regs_banked->spsr_irq)::"memory", "cc");
00234     asm volatile (" mrs     %0, sp_irq\n\t"
00235                           :"=r" (regs_banked->sp_irq)::"memory", "cc");
00236     asm volatile (" mrs     %0, lr_irq\n\t"
00237                           :"=r" (regs_banked->lr_irq)::"memory", "cc");
00238 
00239     /* FIQ banked register  R8_fiq ~ R12_fiq, LR and SPSR */
00240     asm volatile (" mrs     %0, spsr_fiq\n\t"
00241                           :"=r" (regs_banked->spsr_fiq)::"memory", "cc");
00242     asm volatile (" mrs     %0, lr_fiq\n\t"
00243                           :"=r" (regs_banked->lr_fiq)::"memory", "cc");
00244     asm volatile (" mrs     %0, r8_fiq\n\t"
00245                           :"=r" (regs_banked->r8_fiq)::"memory", "cc");
00246     asm volatile (" mrs     %0, r9_fiq\n\t"
00247                           :"=r" (regs_banked->r9_fiq)::"memory", "cc");
00248     asm volatile (" mrs     %0, r10_fiq\n\t"
00249                           :"=r" (regs_banked->r10_fiq)::"memory", "cc");
00250     asm volatile (" mrs     %0, r11_fiq\n\t"
00251                           :"=r" (regs_banked->r11_fiq)::"memory", "cc");
00252     asm volatile (" mrs     %0, r12_fiq\n\t"
00253                           :"=r" (regs_banked->r12_fiq)::"memory", "cc");
00254 
00255 }
00256 
00257 void context_restore_banked(struct arch_regs_banked *regs_banked)
00258 {
00259     /* USR banked register */
00260     asm volatile (" msr    sp_usr, %0\n\t"
00261                           ::"r" (regs_banked->sp_usr) :"memory", "cc");
00262 
00263     /* SVC banked register */
00264     asm volatile (" msr    spsr_svc, %0\n\t"
00265                           ::"r" (regs_banked->spsr_svc) :"memory", "cc");
00266     asm volatile (" msr    sp_svc, %0\n\t"
00267                           ::"r" (regs_banked->sp_svc) :"memory", "cc");
00268     asm volatile (" msr    lr_svc, %0\n\t"
00269                           ::"r" (regs_banked->lr_svc) :"memory", "cc");
00270 
00271     /* ABT banked register */
00272     asm volatile (" msr    spsr_abt, %0\n\t"
00273                           ::"r" (regs_banked->spsr_abt) :"memory", "cc");
00274     asm volatile (" msr    sp_abt, %0\n\t"
00275                           ::"r" (regs_banked->sp_abt) :"memory", "cc");
00276     asm volatile (" msr    lr_abt, %0\n\t"
00277                           ::"r" (regs_banked->lr_abt) :"memory", "cc");
00278 
00279     /* UND banked register */
00280     asm volatile (" msr    spsr_und, %0\n\t"
00281                           ::"r" (regs_banked->spsr_und) :"memory", "cc");
00282     asm volatile (" msr    sp_und, %0\n\t"
00283                           ::"r" (regs_banked->sp_und) :"memory", "cc");
00284     asm volatile (" msr    lr_und, %0\n\t"
00285                           ::"r" (regs_banked->lr_und) :"memory", "cc");
00286 
00287     /* IRQ banked register */
00288     asm volatile (" msr     spsr_irq, %0\n\t"
00289                           ::"r" (regs_banked->spsr_irq) :"memory", "cc");
00290     asm volatile (" msr     sp_irq, %0\n\t"
00291                           ::"r" (regs_banked->sp_irq) :"memory", "cc");
00292     asm volatile (" msr     lr_irq, %0\n\t"
00293                           ::"r" (regs_banked->lr_irq) :"memory", "cc");
00294 
00295     /* FIQ banked register */
00296     asm volatile (" msr     spsr_fiq, %0\n\t"
00297                           ::"r" (regs_banked->spsr_fiq) :"memory", "cc");
00298     asm volatile (" msr     lr_fiq, %0\n\t"
00299                           ::"r" (regs_banked->lr_fiq) :"memory", "cc");
00300     asm volatile (" msr    r8_fiq, %0\n\t"
00301                           ::"r" (regs_banked->r8_fiq) :"memory", "cc");
00302     asm volatile (" msr    r9_fiq, %0\n\t"
00303                           ::"r" (regs_banked->r9_fiq) :"memory", "cc");
00304     asm volatile (" msr    r10_fiq, %0\n\t"
00305                           ::"r" (regs_banked->r10_fiq) :"memory", "cc");
00306     asm volatile (" msr    r11_fiq, %0\n\t"
00307                           ::"r" (regs_banked->r11_fiq) :"memory", "cc");
00308     asm volatile (" msr    r12_fiq, %0\n\t"
00309                           ::"r" (regs_banked->r12_fiq) :"memory", "cc");
00310 }
00311 
00312 /* Co-processor state management: init/save/restore */
00313 void context_init_cops(struct arch_regs_cop *regs_cop)
00314 {
00315     regs_cop->vbar = 0;
00316     regs_cop->ttbr0 = 0;
00317     regs_cop->ttbr1 = 0;
00318     regs_cop->ttbcr = 0;
00319     regs_cop->sctlr = 0;
00320 }
00321 
00322 void context_save_cops(struct arch_regs_cop *regs_cop)
00323 {
00324     regs_cop->vbar = read_vbar();
00325     regs_cop->ttbr0 = read_ttbr0();
00326     regs_cop->ttbr1 = read_ttbr1();
00327     regs_cop->ttbcr = read_ttbcr();
00328     regs_cop->sctlr = read_sctlr();
00329 }
00330 
00331 void context_restore_cops(struct arch_regs_cop *regs_cop)
00332 {
00333     write_vbar(regs_cop->vbar);
00334     write_ttbr0(regs_cop->ttbr0);
00335     write_ttbr1(regs_cop->ttbr1);
00336     write_ttbcr(regs_cop->ttbcr);
00337     write_sctlr(regs_cop->sctlr);
00338 }
00339 
00340 
00341 /* DEPRECATED: use context_switchto(vmid) and context_perform_switch() 
00342    void context_switch_to_next_guest(struct arch_regs *regs_current)
00343  */
00344 
00345 static hvmm_status_t context_perform_switch_to_guest_regs(struct arch_regs *regs_current, vmid_t next_vmid)
00346 {
00347     /* _curreng_guest_vmid -> next_vmid */
00348 
00349     hvmm_status_t result = HVMM_STATUS_UNKNOWN_ERROR;
00350     struct hyp_guest_context *context = 0;
00351     struct arch_regs *regs = 0;
00352     
00353     HVMM_TRACE_ENTER();
00354 
00355     if ( _current_guest_vmid == next_vmid ) {
00356         /* the same guest? WTF? */
00357         return HVMM_STATUS_IGNORED;
00358     }
00359 
00360     /*
00361      * We assume VTCR has been configured and initialized in the memory management module
00362      */
00363     /* Disable Stage 2 Translation: HCR.VM = 0 */
00364     vmm_stage2_enable(0);
00365 
00366     if ( regs_current != 0 ) {
00367         /* save the current guest's context */
00368         context = &guest_contexts[_current_guest_vmid];
00369         regs = &context->regs;
00370         context_copy_regs( regs, regs_current );
00371         context_save_cops( &context->regs_cop );
00372         context_save_banked( &context->regs_banked );
00373         vgic_save_status( &context->vgic_status, context->vmid );
00374         printh( "context: saving vmid[%d] mode(%x):%s pc:0x%x\n", 
00375                 _current_guest_vmid, 
00376                 regs->cpsr & 0x1F, 
00377                 _modename(regs->cpsr & 0x1F),
00378                 regs->pc
00379        );
00380     }
00381 
00382     /* The context of the next guest */
00383     context = &guest_contexts[next_vmid];
00384 
00385     /* Restore Translation Table for the next guest and Enable Stage 2 Translation */
00386     vmm_set_vmid_ttbl( context->vmid, context->ttbl );
00387     vmm_stage2_enable(1);
00388     vgic_restore_status( &context->vgic_status, context->vmid );
00389     
00390     {
00391         uint32_t lr = 0;
00392         asm volatile( "mov  %0, lr" : "=r" (lr) : : "memory", "cc");
00393         printh( "context: restoring vmid[%d] mode(%x):%s pc:0x%x lr:0x%x\n", 
00394             next_vmid, 
00395             context->regs.cpsr & 0x1F, 
00396             _modename(context->regs.cpsr & 0x1F),
00397             context->regs.pc, lr
00398         );
00399     }
00400 
00401     /* The next becomes the current */
00402     _current_guest_vmid = next_vmid;
00403     if ( regs_current == 0 ) {
00404         /* init -> hyp mode -> guest */
00405         /* The actual context switching (Hyp to Normal mode) handled in the asm code */
00406         __mon_switch_to_guest_context( &context->regs );
00407     } else {
00408         /* guest -> hyp -> guest */
00409         context_copy_regs( regs_current, &context->regs );
00410         context_restore_cops( &context->regs_cop );
00411         context_restore_banked( &context->regs_banked );
00412     }
00413 
00414     result = HVMM_STATUS_SUCCESS;
00415     HVMM_TRACE_EXIT();
00416     return result;
00417 }
00418 
00419 hvmm_status_t context_perform_switch(void)
00420 {
00421     hvmm_status_t result = HVMM_STATUS_IGNORED;
00422 
00423     if ( _current_guest_vmid == VMID_INVALID ) {
00424         printh("context: launching the first guest\n");
00425         /* very first time, to the default first guest */
00426         result = context_perform_switch_to_guest_regs( 0, _next_guest_vmid );
00427         /* DOES NOT COME BACK HERE */
00428     } else if ( _next_guest_vmid != VMID_INVALID && _current_guest_vmid != _next_guest_vmid ) {
00429         struct arch_regs *regs = trap_saved_regs();
00430         if ( (regs->cpsr & 0x1F) != 0x1A ) {
00431             printh("curr: %x\n", _current_guest_vmid);
00432             printh("next: %x\n", _next_guest_vmid);
00433 
00434             /* Only if not from Hyp */
00435             result = context_perform_switch_to_guest_regs( regs, _next_guest_vmid );
00436             _next_guest_vmid = VMID_INVALID;
00437         }
00438     } else {
00439         /* Staying at the currently active guest. Flush out queued virqs since we didn't have a chance to switch the context, where virq flush takes place,  this time */
00440         vgic_flush_virqs(_current_guest_vmid);
00441     }
00442 
00443     _switch_locked = 0;
00444     return result;
00445 }
00446 
00447 void context_switch_to_initial_guest(void)
00448 {
00449     struct hyp_guest_context *context = 0;
00450     struct arch_regs *regs = 0;
00451 
00452     uart_print("[hyp] switch_to_initial_guest:\n\r");
00453 
00454     /* Select the first guest context to switch to. */
00455     _current_guest_vmid = VMID_INVALID;
00456     context = &guest_contexts[0];
00457 
00458     /* Dump the initial register values of the guest for debugging purpose */
00459     regs = &context->regs;
00460     context_dump_regs( regs );
00461 
00462     /* Context Switch with current context == none */
00463     context_switchto(0);
00464     context_perform_switch();
00465 }
00466 
00467 
00468 void context_init_guests(void)
00469 {
00470     struct hyp_guest_context *context;
00471     struct arch_regs *regs = 0;
00472 
00473     
00474     uart_print("[hyp] init_guests: enter\n\r");
00475 
00476 
00477     /* Guest 1 @guest_bin_start */
00478     context = &guest_contexts[0];
00479     regs = &context->regs;
00480     regs->cpsr = 0x1d3;         // supervisor, interrupt disabled
00481 #if defined (LINUX_GUEST)
00482     regs->pc = 0xA0008000;      // PA:0xA0008000, where zImage is
00483     regs->gpr[1] = CFG_MACHINE_NUMBER;
00484     regs->gpr[2] = 0x80000100;  //src+(0x100/4);
00485 #else
00486     regs->pc = 0x80000000;      // PA:0xA0000000, default entry for bmguest
00487 #endif
00488 
00489     /* regs->gpr[] = whatever */
00490     context->vmid = 0;
00491     context->ttbl = vmm_vmid_ttbl(context->vmid);
00492     context_init_cops( &context->regs_cop );
00493     context_init_banked( &context->regs_banked );
00494     vgic_init_status( &context->vgic_status, context->vmid );
00495 
00496     /* Guest 2 @guest2_bin_start */
00497     context = &guest_contexts[1];
00498     regs = &context->regs;
00499     regs->pc = 0x80000000;  // PA: 0xB0000000
00500     regs->cpsr = 0x1d3; // supervisor, interrupt disabled
00501 
00502     /* regs->gpr[] = whatever */
00503     context->vmid = 1;
00504     context->ttbl = vmm_vmid_ttbl(context->vmid);
00505     context_init_cops( &context->regs_cop );
00506     context_init_banked( &context->regs_banked );
00507     vgic_init_status( &context->vgic_status, context->vmid );
00508 
00509 #if defined (LINUX_GUEST)
00510     _hyp_guest0_copy_zimage();
00511 #elif defined (BAREMETAL_GUEST) 
00512     /* Workaround for unloaded bmguest.bin at 0xB0000000@PA */
00513     _hyp_fixup_unloaded_guest();
00514 #endif
00515 
00516 #if defined (LINUX_GUEST)
00517     {
00518         extern uint32_t guest_bin_start;
00519         uint32_t *src = &guest_bin_start;
00520         loadlinux_setup_tags(src);
00521     }
00522 #endif
00523     uart_print("[hyp] init_guests: return\n\r");
00524 }
00525 
00526 struct hyp_guest_context *context_atvmid(vmid_t vmid)
00527 {
00528     struct hyp_guest_context * result = 0;
00529 
00530     if ( vmid < NUM_GUEST_CONTEXTS ) {
00531         result = &guest_contexts[vmid];
00532     }
00533 
00534     return result;
00535 }
00536 
00537 
00538 vmid_t context_first_vmid(void)
00539 {
00540     /* FIXME:Hardcoded for now */
00541     return 0;
00542 }
00543 
00544 vmid_t context_last_vmid(void)
00545 {
00546     /* FIXME:Hardcoded for now */
00547     return 1;
00548 }
00549 
00550 vmid_t context_next_vmid(vmid_t ofvmid)
00551 {
00552     vmid_t next = VMID_INVALID;
00553     if ( ofvmid == VMID_INVALID ) {
00554         next = context_first_vmid();
00555     } else if ( ofvmid < context_last_vmid() ) {
00556         /* FIXME:Hardcoded */
00557         next = ofvmid + 1;
00558     }
00559     return next;
00560 }
00561 
00562 vmid_t context_current_vmid(void)
00563 {
00564     return _current_guest_vmid;
00565 }
00566 
00567 vmid_t context_waiting_vmid(void)
00568 {
00569     return _next_guest_vmid;
00570 }
00571 
00572 hvmm_status_t context_switchto(vmid_t vmid)
00573 {
00574     return context_switchto_lock(vmid, 0);
00575 }
00576 
00577 hvmm_status_t context_switchto_lock(vmid_t vmid, uint8_t locked)
00578 {
00579     hvmm_status_t result = HVMM_STATUS_IGNORED;
00580 
00581     HVMM_TRACE_ENTER();
00582 
00583     /* valid and not current vmid, switch */
00584     if (_switch_locked == 0) {
00585         if ( !_valid_vmid(vmid) ) {
00586             result = HVMM_STATUS_BAD_ACCESS;
00587         } else {
00588             _next_guest_vmid = vmid;
00589             result = HVMM_STATUS_SUCCESS;
00590 
00591             printh("switching to vmid: %x\n", (uint32_t)vmid);
00592         }
00593     } else {
00594         printh("context: next vmid locked to %d\n", _next_guest_vmid );
00595     }
00596 
00597     if ( locked )
00598         _switch_locked = locked;
00599 
00600     HVMM_TRACE_EXIT();
00601     return result;
00602 }
00603 
00604 void start_guest_os(void)
00605 {
00606     init_print();
00607 
00608     hvmm_status_t ret = HVMM_STATUS_UNKNOWN_ERROR;
00609     printh("[%s : %d] Starting...\n", __FUNCTION__, __LINE__);
00610 
00611     /* Initialize Memory Management */
00612     ret = hvmm_mm_init();
00613 
00614     /* Initialize Interrupt Management */
00615     ret = hvmm_interrupt_init();
00616     if ( ret != HVMM_STATUS_SUCCESS ) {
00617         uart_print("[hyp_main] interrupt initialization failed...\n\r");
00618     }
00619 
00620     /* Initialize Guests */
00621     context_init_guests();
00622 
00623     /* Initialize Virtual Devices */
00624     vdev_init();
00625 
00626     /* Virtual GIC Distributor */
00627     printh( "tests: Registering sample vdev:'vgicd' at %x\n", CFG_GIC_BASE_PA | GIC_OFFSET_GICD);
00628     vdev_gicd_init(CFG_GIC_BASE_PA | GIC_OFFSET_GICD);
00629 
00630     /* Initialize PIRQ to VIRQ mapping */
00631     virqmap_init();
00632 
00633     /* Start Scheduling */
00634     scheduler_test_scheduling();
00635 
00636     /* Begin running test code for newly implemented features */
00637     hvmm_tests_main();
00638 
00639     /* Print Banner */
00640     printH("%s", BANNER_STRING);
00641 
00642     /* Switch to the first guest */
00643     context_switch_to_initial_guest();
00644 
00645     /* The code flow must not reach here */
00646     uart_print("[hyp_main] ERROR: CODE MUST NOT REACH HERE\n\r");
00647     hyp_abort_infinite();
00648 }
00649 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines