|
khypervisor
v1
|
#include <armv7_p15.h>#include <arch_types.h>#include <k-hypervisor-config.h>#include <mm.h>#include <gic.h>#include <interrupt.h>#include <context.h>#include <scheduler.h>#include <hvmm_trace.h>#include <vdev.h>#include <vdev/vdev_gicd.h>#include <gic_regs.h>#include <virqmap.h>#include <trap.h>#include <vmm.h>#include <string.h>#include "loadlinux.h"#include <config/cfg_platform.h>#include <log/uart_print.h>#include <log/print.h>#include <test/tests.h>#include <version.h>
Go to the source code of this file.
| #define __CONTEXT_TRACE_VERBOSE__ |
| #define _valid_vmid | ( | vmid | ) | ( context_first_vmid() <= vmid && context_last_vmid() >= vmid ) |
| #define CPSR_MODE_ABT 0x17 |
| #define CPSR_MODE_FIQ 0x11 |
| #define CPSR_MODE_HYP 0x1A |
| #define CPSR_MODE_IRQ 0x12 |
| #define CPSR_MODE_MON 0x16 |
| #define CPSR_MODE_SVC 0x13 |
| #define CPSR_MODE_SYS 0x1F |
| #define CPSR_MODE_UND 0x1B |
| #define CPSR_MODE_USER 0x10 |
| #define NUM_GUEST_CONTEXTS NUM_GUESTS_STATIC |
| void __mon_switch_to_guest_context | ( | struct arch_regs * | regs | ) |
| static void _hyp_guest0_copy_zimage | ( | void | ) | [static] |
Definition at line 59 of file context.c.
{
extern uint32_t guest_bin_start;
extern uint32_t guest_bin_end;
uint32_t *src = &guest_bin_start;
uint32_t *end = &guest_bin_end;
uint32_t *dst = &guest_bin_start + (0x20008000/4);
HVMM_TRACE_ENTER();
uart_print("Copying guest0 image to guest1\n\r");
uart_print(" src:");uart_print_hex32((uint32_t)src);
uart_print(" dst:");uart_print_hex32((uint32_t)dst);
uart_print(" size:");uart_print_hex32( (uint32_t)(end - src) * sizeof(uint32_t));uart_print("\n\r");
while(src < end ) {
*dst++ = *src++;
}
uart_print("=== done ===\n\r");
HVMM_TRACE_EXIT();
}
| struct hyp_guest_context* context_atvmid | ( | vmid_t | vmid | ) | [read] |
Definition at line 526 of file context.c.
{
struct hyp_guest_context * result = 0;
if ( vmid < NUM_GUEST_CONTEXTS ) {
result = &guest_contexts[vmid];
}
return result;
}
| static void context_copy_regs | ( | struct arch_regs * | regs_dst, |
| struct arch_regs * | regs_src | ||
| ) | [static] |
| vmid_t context_current_vmid | ( | void | ) |
Definition at line 562 of file context.c.
{
return _current_guest_vmid;
}
| void context_dump_regs | ( | struct arch_regs * | regs | ) |
Definition at line 145 of file context.c.
{
#ifdef DEBUG
uart_print( "cpsr:" ); uart_print_hex32( regs->cpsr ); uart_print( "\n\r" );
uart_print( " pc:" ); uart_print_hex32( regs->pc ); uart_print( "\n\r" );
uart_print( " lr:" ); uart_print_hex32( regs->lr ); uart_print( "\n\r" );
#ifdef __CONTEXT_TRACE_VERBOSE__
{
int i;
uart_print( " gpr:\n\r" );
for( i = 0; i < ARCH_REGS_NUM_GPR; i++) {
uart_print( " " ); uart_print_hex32( regs->gpr[i] ); uart_print( "\n\r" );
}
}
#endif
#endif
}
| vmid_t context_first_vmid | ( | void | ) |
| void context_init_banked | ( | struct arch_regs_banked * | regs_banked | ) |
Definition at line 176 of file context.c.
{
regs_banked->sp_usr = 0;
regs_banked->spsr_svc = 0;
regs_banked->sp_svc = 0;
regs_banked->lr_svc = 0;
regs_banked->spsr_abt = 0;
regs_banked->sp_abt = 0;
regs_banked->lr_abt = 0;
regs_banked->spsr_und = 0;
regs_banked->sp_und = 0;
regs_banked->lr_und = 0;
regs_banked->spsr_irq = 0;
regs_banked->sp_irq = 0;
regs_banked->lr_irq = 0;
regs_banked->spsr_fiq = 0;
regs_banked->lr_fiq = 0;
regs_banked->r8_fiq = 0;
regs_banked->r9_fiq = 0;
regs_banked->r10_fiq = 0;
regs_banked->r11_fiq = 0;
regs_banked->r12_fiq = 0;
//Cortex-A15 processor does not support sp_fiq
}
| void context_init_cops | ( | struct arch_regs_cop * | regs_cop | ) |
| void context_init_guests | ( | void | ) |
Definition at line 468 of file context.c.
{
struct hyp_guest_context *context;
struct arch_regs *regs = 0;
uart_print("[hyp] init_guests: enter\n\r");
/* Guest 1 @guest_bin_start */
context = &guest_contexts[0];
regs = &context->regs;
regs->cpsr = 0x1d3; // supervisor, interrupt disabled
#if defined (LINUX_GUEST)
regs->pc = 0xA0008000; // PA:0xA0008000, where zImage is
regs->gpr[1] = CFG_MACHINE_NUMBER;
regs->gpr[2] = 0x80000100; //src+(0x100/4);
#else
regs->pc = 0x80000000; // PA:0xA0000000, default entry for bmguest
#endif
/* regs->gpr[] = whatever */
context->vmid = 0;
context->ttbl = vmm_vmid_ttbl(context->vmid);
context_init_cops( &context->regs_cop );
context_init_banked( &context->regs_banked );
vgic_init_status( &context->vgic_status, context->vmid );
/* Guest 2 @guest2_bin_start */
context = &guest_contexts[1];
regs = &context->regs;
regs->pc = 0x80000000; // PA: 0xB0000000
regs->cpsr = 0x1d3; // supervisor, interrupt disabled
/* regs->gpr[] = whatever */
context->vmid = 1;
context->ttbl = vmm_vmid_ttbl(context->vmid);
context_init_cops( &context->regs_cop );
context_init_banked( &context->regs_banked );
vgic_init_status( &context->vgic_status, context->vmid );
#if defined (LINUX_GUEST)
_hyp_guest0_copy_zimage();
#elif defined (BAREMETAL_GUEST)
/* Workaround for unloaded bmguest.bin at 0xB0000000@PA */
_hyp_fixup_unloaded_guest();
#endif
#if defined (LINUX_GUEST)
{
extern uint32_t guest_bin_start;
uint32_t *src = &guest_bin_start;
loadlinux_setup_tags(src);
}
#endif
uart_print("[hyp] init_guests: return\n\r");
}

| vmid_t context_last_vmid | ( | void | ) |
| vmid_t context_next_vmid | ( | vmid_t | ofvmid | ) |
Definition at line 550 of file context.c.
{
vmid_t next = VMID_INVALID;
if ( ofvmid == VMID_INVALID ) {
next = context_first_vmid();
} else if ( ofvmid < context_last_vmid() ) {
/* FIXME:Hardcoded */
next = ofvmid + 1;
}
return next;
}

| hvmm_status_t context_perform_switch | ( | void | ) |
Definition at line 419 of file context.c.
{
hvmm_status_t result = HVMM_STATUS_IGNORED;
if ( _current_guest_vmid == VMID_INVALID ) {
printh("context: launching the first guest\n");
/* very first time, to the default first guest */
result = context_perform_switch_to_guest_regs( 0, _next_guest_vmid );
/* DOES NOT COME BACK HERE */
} else if ( _next_guest_vmid != VMID_INVALID && _current_guest_vmid != _next_guest_vmid ) {
struct arch_regs *regs = trap_saved_regs();
if ( (regs->cpsr & 0x1F) != 0x1A ) {
printh("curr: %x\n", _current_guest_vmid);
printh("next: %x\n", _next_guest_vmid);
/* Only if not from Hyp */
result = context_perform_switch_to_guest_regs( regs, _next_guest_vmid );
_next_guest_vmid = VMID_INVALID;
}
} else {
/* 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 */
vgic_flush_virqs(_current_guest_vmid);
}
_switch_locked = 0;
return result;
}

| static hvmm_status_t context_perform_switch_to_guest_regs | ( | struct arch_regs * | regs_current, |
| vmid_t | next_vmid | ||
| ) | [static] |
Definition at line 345 of file context.c.
{
/* _curreng_guest_vmid -> next_vmid */
hvmm_status_t result = HVMM_STATUS_UNKNOWN_ERROR;
struct hyp_guest_context *context = 0;
struct arch_regs *regs = 0;
HVMM_TRACE_ENTER();
if ( _current_guest_vmid == next_vmid ) {
/* the same guest? WTF? */
return HVMM_STATUS_IGNORED;
}
/*
* We assume VTCR has been configured and initialized in the memory management module
*/
/* Disable Stage 2 Translation: HCR.VM = 0 */
vmm_stage2_enable(0);
if ( regs_current != 0 ) {
/* save the current guest's context */
context = &guest_contexts[_current_guest_vmid];
regs = &context->regs;
context_copy_regs( regs, regs_current );
context_save_cops( &context->regs_cop );
context_save_banked( &context->regs_banked );
vgic_save_status( &context->vgic_status, context->vmid );
printh( "context: saving vmid[%d] mode(%x):%s pc:0x%x\n",
_current_guest_vmid,
regs->cpsr & 0x1F,
_modename(regs->cpsr & 0x1F),
regs->pc
);
}
/* The context of the next guest */
context = &guest_contexts[next_vmid];
/* Restore Translation Table for the next guest and Enable Stage 2 Translation */
vmm_set_vmid_ttbl( context->vmid, context->ttbl );
vmm_stage2_enable(1);
vgic_restore_status( &context->vgic_status, context->vmid );
{
uint32_t lr = 0;
asm volatile( "mov %0, lr" : "=r" (lr) : : "memory", "cc");
printh( "context: restoring vmid[%d] mode(%x):%s pc:0x%x lr:0x%x\n",
next_vmid,
context->regs.cpsr & 0x1F,
_modename(context->regs.cpsr & 0x1F),
context->regs.pc, lr
);
}
/* The next becomes the current */
_current_guest_vmid = next_vmid;
if ( regs_current == 0 ) {
/* init -> hyp mode -> guest */
/* The actual context switching (Hyp to Normal mode) handled in the asm code */
__mon_switch_to_guest_context( &context->regs );
} else {
/* guest -> hyp -> guest */
context_copy_regs( regs_current, &context->regs );
context_restore_cops( &context->regs_cop );
context_restore_banked( &context->regs_banked );
}
result = HVMM_STATUS_SUCCESS;
HVMM_TRACE_EXIT();
return result;
}

| void context_restore_banked | ( | struct arch_regs_banked * | regs_banked | ) |
Definition at line 257 of file context.c.
{
/* USR banked register */
asm volatile (" msr sp_usr, %0\n\t"
::"r" (regs_banked->sp_usr) :"memory", "cc");
/* SVC banked register */
asm volatile (" msr spsr_svc, %0\n\t"
::"r" (regs_banked->spsr_svc) :"memory", "cc");
asm volatile (" msr sp_svc, %0\n\t"
::"r" (regs_banked->sp_svc) :"memory", "cc");
asm volatile (" msr lr_svc, %0\n\t"
::"r" (regs_banked->lr_svc) :"memory", "cc");
/* ABT banked register */
asm volatile (" msr spsr_abt, %0\n\t"
::"r" (regs_banked->spsr_abt) :"memory", "cc");
asm volatile (" msr sp_abt, %0\n\t"
::"r" (regs_banked->sp_abt) :"memory", "cc");
asm volatile (" msr lr_abt, %0\n\t"
::"r" (regs_banked->lr_abt) :"memory", "cc");
/* UND banked register */
asm volatile (" msr spsr_und, %0\n\t"
::"r" (regs_banked->spsr_und) :"memory", "cc");
asm volatile (" msr sp_und, %0\n\t"
::"r" (regs_banked->sp_und) :"memory", "cc");
asm volatile (" msr lr_und, %0\n\t"
::"r" (regs_banked->lr_und) :"memory", "cc");
/* IRQ banked register */
asm volatile (" msr spsr_irq, %0\n\t"
::"r" (regs_banked->spsr_irq) :"memory", "cc");
asm volatile (" msr sp_irq, %0\n\t"
::"r" (regs_banked->sp_irq) :"memory", "cc");
asm volatile (" msr lr_irq, %0\n\t"
::"r" (regs_banked->lr_irq) :"memory", "cc");
/* FIQ banked register */
asm volatile (" msr spsr_fiq, %0\n\t"
::"r" (regs_banked->spsr_fiq) :"memory", "cc");
asm volatile (" msr lr_fiq, %0\n\t"
::"r" (regs_banked->lr_fiq) :"memory", "cc");
asm volatile (" msr r8_fiq, %0\n\t"
::"r" (regs_banked->r8_fiq) :"memory", "cc");
asm volatile (" msr r9_fiq, %0\n\t"
::"r" (regs_banked->r9_fiq) :"memory", "cc");
asm volatile (" msr r10_fiq, %0\n\t"
::"r" (regs_banked->r10_fiq) :"memory", "cc");
asm volatile (" msr r11_fiq, %0\n\t"
::"r" (regs_banked->r11_fiq) :"memory", "cc");
asm volatile (" msr r12_fiq, %0\n\t"
::"r" (regs_banked->r12_fiq) :"memory", "cc");
}
| void context_restore_cops | ( | struct arch_regs_cop * | regs_cop | ) |
Definition at line 331 of file context.c.
{
write_vbar(regs_cop->vbar);
write_ttbr0(regs_cop->ttbr0);
write_ttbr1(regs_cop->ttbr1);
write_ttbcr(regs_cop->ttbcr);
write_sctlr(regs_cop->sctlr);
}
| void context_save_banked | ( | struct arch_regs_banked * | regs_banked | ) |
Definition at line 201 of file context.c.
{
/* USR banked register */
asm volatile (" mrs %0, sp_usr\n\t"
:"=r" (regs_banked->sp_usr)::"memory", "cc");
/* SVC banked register */
asm volatile (" mrs %0, spsr_svc\n\t"
:"=r" (regs_banked->spsr_svc)::"memory", "cc");
asm volatile (" mrs %0, sp_svc\n\t"
:"=r" (regs_banked->sp_svc)::"memory", "cc");
asm volatile (" mrs %0, lr_svc\n\t"
:"=r" (regs_banked->lr_svc)::"memory", "cc");
/* ABT banked register */
asm volatile (" mrs %0, spsr_abt\n\t"
:"=r" (regs_banked->spsr_abt)::"memory", "cc");
asm volatile (" mrs %0, sp_abt\n\t"
:"=r" (regs_banked->sp_abt)::"memory", "cc");
asm volatile (" mrs %0, lr_abt\n\t"
:"=r" (regs_banked->lr_abt)::"memory", "cc");
/* UND banked register */
asm volatile (" mrs %0, spsr_und\n\t"
:"=r" (regs_banked->spsr_und)::"memory", "cc");
asm volatile (" mrs %0, sp_und\n\t"
:"=r" (regs_banked->sp_und)::"memory", "cc");
asm volatile (" mrs %0, lr_und\n\t"
:"=r" (regs_banked->lr_und)::"memory", "cc");
/* IRQ banked register */
asm volatile (" mrs %0, spsr_irq\n\t"
:"=r" (regs_banked->spsr_irq)::"memory", "cc");
asm volatile (" mrs %0, sp_irq\n\t"
:"=r" (regs_banked->sp_irq)::"memory", "cc");
asm volatile (" mrs %0, lr_irq\n\t"
:"=r" (regs_banked->lr_irq)::"memory", "cc");
/* FIQ banked register R8_fiq ~ R12_fiq, LR and SPSR */
asm volatile (" mrs %0, spsr_fiq\n\t"
:"=r" (regs_banked->spsr_fiq)::"memory", "cc");
asm volatile (" mrs %0, lr_fiq\n\t"
:"=r" (regs_banked->lr_fiq)::"memory", "cc");
asm volatile (" mrs %0, r8_fiq\n\t"
:"=r" (regs_banked->r8_fiq)::"memory", "cc");
asm volatile (" mrs %0, r9_fiq\n\t"
:"=r" (regs_banked->r9_fiq)::"memory", "cc");
asm volatile (" mrs %0, r10_fiq\n\t"
:"=r" (regs_banked->r10_fiq)::"memory", "cc");
asm volatile (" mrs %0, r11_fiq\n\t"
:"=r" (regs_banked->r11_fiq)::"memory", "cc");
asm volatile (" mrs %0, r12_fiq\n\t"
:"=r" (regs_banked->r12_fiq)::"memory", "cc");
}
| void context_save_cops | ( | struct arch_regs_cop * | regs_cop | ) |
Definition at line 322 of file context.c.
{
regs_cop->vbar = read_vbar();
regs_cop->ttbr0 = read_ttbr0();
regs_cop->ttbr1 = read_ttbr1();
regs_cop->ttbcr = read_ttbcr();
regs_cop->sctlr = read_sctlr();
}
| void context_switch_to_initial_guest | ( | void | ) |
Definition at line 447 of file context.c.
{
struct hyp_guest_context *context = 0;
struct arch_regs *regs = 0;
uart_print("[hyp] switch_to_initial_guest:\n\r");
/* Select the first guest context to switch to. */
_current_guest_vmid = VMID_INVALID;
context = &guest_contexts[0];
/* Dump the initial register values of the guest for debugging purpose */
regs = &context->regs;
context_dump_regs( regs );
/* Context Switch with current context == none */
context_switchto(0);
context_perform_switch();
}

| hvmm_status_t context_switchto | ( | vmid_t | vmid | ) |
Definition at line 572 of file context.c.
{
return context_switchto_lock(vmid, 0);
}

| hvmm_status_t context_switchto_lock | ( | vmid_t | vmid, |
| uint8_t | locked | ||
| ) |
Definition at line 577 of file context.c.
{
hvmm_status_t result = HVMM_STATUS_IGNORED;
HVMM_TRACE_ENTER();
/* valid and not current vmid, switch */
if (_switch_locked == 0) {
if ( !_valid_vmid(vmid) ) {
result = HVMM_STATUS_BAD_ACCESS;
} else {
_next_guest_vmid = vmid;
result = HVMM_STATUS_SUCCESS;
printh("switching to vmid: %x\n", (uint32_t)vmid);
}
} else {
printh("context: next vmid locked to %d\n", _next_guest_vmid );
}
if ( locked )
_switch_locked = locked;
HVMM_TRACE_EXIT();
return result;
}
| vmid_t context_waiting_vmid | ( | void | ) |
Definition at line 567 of file context.c.
{
return _next_guest_vmid;
}
| void start_guest_os | ( | void | ) |
Definition at line 604 of file context.c.
{
init_print();
hvmm_status_t ret = HVMM_STATUS_UNKNOWN_ERROR;
printh("[%s : %d] Starting...\n", __FUNCTION__, __LINE__);
/* Initialize Memory Management */
ret = hvmm_mm_init();
/* Initialize Interrupt Management */
ret = hvmm_interrupt_init();
if ( ret != HVMM_STATUS_SUCCESS ) {
uart_print("[hyp_main] interrupt initialization failed...\n\r");
}
/* Initialize Guests */
context_init_guests();
/* Initialize Virtual Devices */
vdev_init();
/* Virtual GIC Distributor */
printh( "tests: Registering sample vdev:'vgicd' at %x\n", CFG_GIC_BASE_PA | GIC_OFFSET_GICD);
vdev_gicd_init(CFG_GIC_BASE_PA | GIC_OFFSET_GICD);
/* Initialize PIRQ to VIRQ mapping */
virqmap_init();
/* Start Scheduling */
scheduler_test_scheduling();
/* Begin running test code for newly implemented features */
hvmm_tests_main();
/* Print Banner */
printH("%s", BANNER_STRING);
/* Switch to the first guest */
context_switch_to_initial_guest();
/* The code flow must not reach here */
uart_print("[hyp_main] ERROR: CODE MUST NOT REACH HERE\n\r");
hyp_abort_infinite();
}

int _current_guest_vmid = VMID_INVALID [static] |
int _next_guest_vmid = VMID_INVALID [static] |
uint8_t _switch_locked = 0 [static] |
struct hyp_guest_context guest_contexts[NUM_GUEST_CONTEXTS] [static] |
1.7.6.1