khypervisor
v1
|
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