├── Makefile ├── README ├── arm_asm.h ├── entry.S ├── guest ├── Makefile ├── entry.S ├── kernel.ld ├── libgcc.a └── start.c ├── hyp_asm.S ├── image.S ├── kernel.ld ├── libgcc.a ├── pagetable.S ├── run.sh ├── start.c ├── uart.c └── uart.h /Makefile: -------------------------------------------------------------------------------- 1 | CROSS_PREFIX = arm-linux-gnueabihf- 2 | 3 | AS = $(CROSS_PREFIX)as 4 | CC = $(CROSS_PREFIX)gcc 5 | LD = $(CROSS_PREFIX)ld 6 | OBJDUMP = $(CROSS_PREFIX)objdump 7 | 8 | CFLAGS += -DSMP 9 | #CFLAGS += -march=armv7-a -mcpu=cortex-a15 -marm 10 | CFLAGS += -mcpu=cortex-a15 -marm 11 | 12 | OBJS = \ 13 | entry.o \ 14 | start.o \ 15 | hyp_asm.o \ 16 | pagetable.o \ 17 | uart.o \ 18 | image.o 19 | 20 | all: kernel.elf 21 | 22 | kernel.elf: $(OBJS) kernel.ld 23 | $(LD) $(OBJS) libgcc.a -T kernel.ld -o kernel.elf 24 | $(OBJDUMP) -D kernel.elf > kernel.asm 25 | $(OBJDUMP) -t kernel.elf | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym 26 | 27 | #entry.o: entry.S 28 | # $(CC) $(CFLAGS) -c -o entry.o $< 29 | 30 | #guest.img: 31 | # make -C guest 32 | 33 | %.o: %.c 34 | make -C guest 35 | $(CC) $(CFLAGS) -O2 -ffreestanding -c -o $@ $< 36 | 37 | clean distclean: 38 | rm -f $(OBJS) kernel.elf kernel.asm kernel.sym 39 | make clean -C guest 40 | 41 | 42 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a sample ARM hardware virtualization code on Fast Models (Cortex A15x1) 2 | 3 | To run Fast Models with the program, run: 4 | make 5 | sh run.sh 6 | 7 | For any question, please contact Dongli Zhang (dongli.zhang0129@gmail.com) 8 | -------------------------------------------------------------------------------- /arm_asm.h: -------------------------------------------------------------------------------- 1 | #ifndef __ARM_ASM_H__ 2 | #define __ARM_ASM_H__ 3 | 4 | typedef unsigned long u32; 5 | typedef unsigned short u16; 6 | typedef unsigned char u8; 7 | 8 | #define Mode_USR 0x10 9 | #define Mode_FIQ 0x11 10 | #define Mode_IRQ 0x12 11 | #define Mode_SVC 0x13 12 | #define Mode_ABT 0x17 13 | #define Mode_SYS 0x1F 14 | #define Mode_SVP 0x13 15 | #define Mode_UNDEF 0x1B 16 | #define Mode_HYP 0x1A 17 | #define Mode_MON 0x16 18 | 19 | #define REASON_UNKNOWN 0x00 20 | #define REASON_MCR_CP15 0x03 21 | #define REASON_SVC 0x11 22 | #define REASON_HVC 0x12 23 | #define REASON_SMC 0x13 24 | 25 | struct cpu_t 26 | { 27 | //general registers 28 | u32 r0; 29 | u32 r1; 30 | u32 r2; 31 | u32 r3; 32 | u32 r4; 33 | u32 r5; 34 | u32 r6; 35 | u32 r7; 36 | u32 r8; 37 | u32 r9; 38 | u32 r10; 39 | u32 r11; 40 | u32 r12; 41 | u32 lr; 42 | }; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /entry.S: -------------------------------------------------------------------------------- 1 | 2 | .syntax unified 3 | 4 | .equ Mode_USR, 0x10 5 | .equ Mode_FIQ, 0x11 6 | .equ Mode_IRQ, 0x12 7 | .equ Mode_SVC, 0x13 8 | .equ Mode_ABT, 0x17 9 | .equ Mode_SYS, 0x1f 10 | .equ Mode_SVP, 0x13 11 | .equ Mode_UNDEF, 0x1B 12 | .equ Mode_HYP, 0x1A 13 | .equ Mode_MON, 0x16 14 | 15 | .text 16 | 17 | .globl start 18 | start: 19 | @ 20 | @ Program architected timer frequency 21 | @ 22 | mrc p15, 0, r0, c0, c1, 1 @ CPUID_EXT_PFR1 23 | lsr r0, r0, #16 24 | and r0, r0, #1 @ Check generic timer support 25 | beq 1f 26 | ldr r0, =24000000 @ 24MHz timer frequency 27 | mcr p15, 0, r0, c14, c0, 0 @ CNTFRQ 28 | 1: 29 | @ 30 | @ CPU initialisation 31 | @ 32 | mrc p15, 0, r4, c0, c0, 5 @ MPIDR (ARMv7 only) 33 | and r4, r4, #15 @ CPU number 34 | 35 | 2: 36 | @ 37 | @ UART initialisation (38400 8N1) 38 | @ 39 | ldr r0, =0x1c090000 @ UART base (Versatile Express) 40 | mov r1, #0x10 @ ibrd 41 | str r1, [r0, #0x24] 42 | mov r1, #0xc300 43 | orr r1, #0x0001 @ cr 44 | str r1, [r0, #0x30] 45 | 46 | @ Set all interrupts to be non-secure 47 | ldr r0, =0x2c001000 @ Dist GIC base 48 | ldr r1, [r0, #0x04] @ Type Register 49 | cmp r4, #0 50 | andeq r1, r1, #0x1f 51 | movne r1, #0 52 | add r2, r0, #0x080 @ Security Register 0 53 | mvn r3, #0 54 | 2: str r3, [r2] 55 | sub r1, r1, #1 56 | add r2, r2, #4 @ Next security register 57 | cmp r1, #-1 58 | bne 2b 59 | 60 | @ Set GIC priority mask bit [7] = 1 61 | ldr r0, =0x2c002000 @ CPU GIC base 62 | mov r1, #0x80 63 | str r1, [r0, #0x4] @ GIC ICCPMR 64 | 65 | @ Set NSACR to allow coprocessor access from non-secure 66 | mrc p15, 0, r0, c1, c1, 2 67 | ldr r1, =0x43fff 68 | orr r0, r0, r1 69 | mcr p15, 0, r0, c1, c1, 2 70 | 71 | @ Now we've got rid of the secondary CPUs, set up a stack 72 | @ for CPU 0 so we can write most of this in C. 73 | ldr sp, =stacktop 74 | 75 | # change stack for monitor mode 76 | cps #Mode_MON 77 | ldr sp, =monitor_stack_top 78 | 79 | // Allow non-secure access to FPU/NEON and ACTLR.SMP (Non-Secure Access Control Register (NSACR)) 80 | mrc p15, 0, r0, c1, c1, 2 81 | orr r0, r0, #(1 << 10) //CP10 access 82 | orr r0, r0, #(1 << 11) //CP11 83 | orr r0, r0, #(1 << 18) //ACTLR.SMP access 84 | mcr p15, 0, r0, c1, c1, 2 //Write 85 | 86 | //Go to non-secure world (Secure Configuration Register (SCR)) 87 | mrc p15, 0, r1, c1, c1, 0 88 | orr r1, r1, #(1 << 0) //Set SCR.NS 89 | bic r1, r1, #(1 << 7) //Clear SCR.SCD 90 | orr r1, r1, #(1 << 8) //Set SCR.HCE (HVC in Non-Secure kernel modes causes move to Hyp mode) 91 | mcr p15, 0, r1, c1, c1, 0 //Write 92 | 93 | //Set up HVBAR 94 | LDR r0, =hypervisor_vector 95 | MCR p15, 4, r0, c12, c0, 0 //Write HVBAR 96 | 97 | //go to hypervisor mode 98 | ldr lr, =hypervisor_vector 99 | msr spsr_cxsf, #Mode_HYP //prepare going to the Hypervisor mode 100 | movs pc, lr //go to the Hypervisor Mode 101 | 102 | b . 103 | 104 | .global raise 105 | raise: 106 | mov pc, lr 107 | 108 | .section ".stack" 109 | monitor_stack_bottom: 110 | .rept 0x100 111 | .long 0x00 112 | .endr 113 | monitor_stack_top: 114 | -------------------------------------------------------------------------------- /guest/Makefile: -------------------------------------------------------------------------------- 1 | CROSS_PREFIX = arm-linux-gnueabihf- 2 | 3 | AS = $(CROSS_PREFIX)as 4 | CC = $(CROSS_PREFIX)gcc 5 | LD = $(CROSS_PREFIX)ld 6 | OBJDUMP = $(CROSS_PREFIX)objdump 7 | OBJCOPY = $(CROSS_PREFIX)objcopy 8 | 9 | CFLAGS += -DSMP 10 | CFLAGS += -march=armv7-a -marm 11 | #CFLAGS += -mcpu=cortex-a15 -marm 12 | 13 | OBJS = \ 14 | entry.o \ 15 | start.o 16 | 17 | all: kernel.elf 18 | 19 | kernel.elf: $(OBJS) kernel.ld 20 | $(LD) $(OBJS) libgcc.a -T kernel.ld -o kernel.elf 21 | $(OBJDUMP) -D kernel.elf > kernel.asm 22 | $(OBJDUMP) -t kernel.elf | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym 23 | $(OBJCOPY) kernel.elf -O binary guest.img 24 | 25 | #entry.o: entry.S 26 | # $(CC) $(CFLAGS) -c -o entry.o $< 27 | 28 | %.o: %.c 29 | $(CC) $(CFLAGS) -O2 -ffreestanding -I. -Ilibfdt -c -o $@ $< 30 | 31 | clean distclean: 32 | rm -f $(OBJS) kernel.elf kernel.asm kernel.sym guest.img 33 | 34 | 35 | -------------------------------------------------------------------------------- /guest/entry.S: -------------------------------------------------------------------------------- 1 | .syntax unified 2 | .arch_extension sec 3 | .arch_extension virt 4 | 5 | .text 6 | 7 | .globl start 8 | start: 9 | b reset 10 | ldr pc, UndefAddr 11 | ldr pc, SWIAddr 12 | ldr pc, PAbortAddr 13 | ldr pc, DAbortAddr 14 | ldr pc, ReservedAddr 15 | ldr pc, IRQAddr 16 | ldr pc, FIQAddr 17 | 18 | UndefAddr: .word UndefHandler 19 | SWIAddr: .word SWIHandler 20 | PAbortAddr: .word PAbortHandler 21 | DAbortAddr: .word DAbortHandler 22 | ReservedAddr: .word 0 23 | IRQAddr: .word IRQHandler 24 | FIQAddr: .word FIQHandler 25 | 26 | reset: 27 | @ 28 | @ Program architected timer frequency 29 | @ 30 | /*mrc p15, 0, r0, c0, c1, 1 @ CPUID_EXT_PFR1 31 | lsr r0, r0, #16 32 | and r0, r0, #1 @ Check generic timer support 33 | beq 1f 34 | ldr r0, =24000000 @ 24MHz timer frequency 35 | mcr p15, 0, r0, c14, c0, 0 @ CNTFRQ*/ 36 | 1: 37 | @ 38 | @ CPU initialisation 39 | @ 40 | mrc p15, 0, r4, c0, c0, 5 @ MPIDR (ARMv7 only) 41 | and r4, r4, #15 @ CPU number 42 | 43 | 2: 44 | @ 45 | @ UART initialisation (38400 8N1) 46 | @ 47 | ldr r0, =0x1c090000 @ UART base (Versatile Express) 48 | mov r1, #0x10 @ ibrd 49 | str r1, [r0, #0x24] 50 | mov r1, #0xc300 51 | orr r1, #0x0001 @ cr 52 | str r1, [r0, #0x30] 53 | 54 | @ Now we've got rid of the secondary CPUs, set up a stack 55 | @ for CPU 0 so we can write most of this in C. 56 | ldr sp, =stacktop 57 | 58 | @Write Secure World Vector Base Address 59 | @ --------------------------------------- 60 | LDR r0, =start 61 | MCR p15, 0, r0, c12, c0, 0 62 | 63 | @ And call the C entrypoint 64 | bl c_start 65 | @ Never reached 66 | 1: b 1b 67 | 68 | @------------------------------------------------------------ 69 | @ Vector handler 70 | @ ----------------------------------------------------------- 71 | UndefHandler: 72 | b UndefHandler 73 | 74 | SWIHandler: 75 | push {lr} 76 | bl swi_handler 77 | pop {lr} 78 | mov pc, lr 79 | 80 | PAbortHandler: 81 | b PAbortHandler 82 | 83 | DAbortHandler: 84 | b DAbortHandler 85 | 86 | IRQHandler: 87 | b IRQHandler 88 | 89 | FIQHandler: 90 | b FIQHandler 91 | 92 | .global raise 93 | raise: 94 | mov pc, lr 95 | -------------------------------------------------------------------------------- /guest/kernel.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * model.lds.S - simple linker script for stand-alone Linux booting 3 | * 4 | * Copyright (C) 2011 ARM Limited. All rights reserved. 5 | * 6 | * Use of this source code is governed by a BSD-style license that can be 7 | * found in the LICENSE.txt file. 8 | */ 9 | 10 | OUTPUT_FORMAT("elf32-littlearm") 11 | OUTPUT_ARCH(arm) 12 | TARGET(binary) 13 | 14 | ENTRY_SVC_STACK_SIZE = 0x1000; 15 | 16 | SECTIONS 17 | { 18 | . = 0x80008000; 19 | .text : { *(.text) } 20 | .data : { *(.data) } 21 | .bss : { *(.bss) } 22 | 23 | /*define a stack for the entry*/ 24 | . = ALIGN(0x1000); 25 | . += ENTRY_SVC_STACK_SIZE; 26 | stacktop = .; 27 | } 28 | -------------------------------------------------------------------------------- /guest/libgcc.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/finallyjustice/armvisor/2e5523c29b5d43723b1b10d48f4d5639a6b5627d/guest/libgcc.a -------------------------------------------------------------------------------- /guest/start.c: -------------------------------------------------------------------------------- 1 | 2 | volatile unsigned char * const UART0_BASE = (unsigned char *)0x1c090000; 3 | 4 | void uart_send(unsigned int c) 5 | { 6 | *UART0_BASE = c; 7 | if(c == '\n') 8 | *UART0_BASE = '\r'; 9 | } 10 | 11 | void printstr(char *s) 12 | { 13 | int i = 0; 14 | while(s[i]) 15 | { 16 | uart_send(s[i]); 17 | i++; 18 | } 19 | } 20 | 21 | void printint(int xx, int base, int sign) 22 | { 23 | static char digits[] = "0123456789abcdef"; 24 | char buf[16]; 25 | int i; 26 | unsigned int x; 27 | 28 | if(sign && (sign = xx < 0)) 29 | x = -xx; 30 | else 31 | x = xx; 32 | 33 | i = 0; 34 | do{ 35 | buf[i++] = digits[x % base]; 36 | }while((x /= base) != 0); 37 | 38 | if(sign) 39 | buf[i++] = '-'; 40 | 41 | while(--i >= 0) 42 | uart_send(buf[i]); 43 | } 44 | 45 | void cprintf(char *fmt, ...) 46 | { 47 | int i, c; 48 | unsigned int *argp; 49 | char *s; 50 | 51 | argp = (unsigned int*)(void*)(&fmt + 1); 52 | for(i = 0; (c = fmt[i] & 0xff) != 0; i++) 53 | { 54 | if(c != '%') 55 | { 56 | uart_send(c); 57 | continue; 58 | } 59 | c = fmt[++i] & 0xff; 60 | if(c == 0) 61 | break; 62 | switch(c) 63 | { 64 | case 'd': 65 | printint(*argp++, 10, 1); 66 | break; 67 | case 'x': 68 | case 'p': 69 | printint(*argp++, 16, 0); 70 | break; 71 | case 's': 72 | if((s = (char*)*argp++) == 0) 73 | s = "(null)"; 74 | for(; *s; s++) 75 | uart_send(*s); 76 | break; 77 | case '%': 78 | uart_send('%'); 79 | break; 80 | default: 81 | // Print unknown % sequence to draw attention. 82 | uart_send('%'); 83 | uart_send(c); 84 | break; 85 | } 86 | } 87 | } 88 | 89 | void swi_handler() 90 | { 91 | cprintf("[GUEST] Handle SWI instruction\n"); 92 | } 93 | 94 | void c_start(void) 95 | { 96 | printstr("[GUEST] Guest OS is booted\n"); 97 | 98 | // guest call hypervisor call 99 | cprintf("[GUEST] Call HVC instruction\n"); 100 | asm volatile(".arch_extension virt\n" 101 | "hvc #0"); 102 | cprintf("[GUEST] Finish HVC instruction\n"); 103 | 104 | // guest call system call 105 | cprintf("[GUEST] Call SWI instruction\n"); 106 | asm volatile("swi #7"); 107 | cprintf("[GUEST] Finish SWI instruction\n"); 108 | 109 | // guest call smc call 110 | cprintf("[GUEST] Call SMC instruction\n"); 111 | asm volatile(".arch_extension sec\n" 112 | "smc #0"); 113 | cprintf("[GUEST] Finish SMC instruction\n"); 114 | 115 | while(1); 116 | } 117 | -------------------------------------------------------------------------------- /hyp_asm.S: -------------------------------------------------------------------------------- 1 | .arch_extension sec 2 | .arch_extension virt 3 | 4 | .equ Mode_USR, 0x10 5 | .equ Mode_FIQ, 0x11 6 | .equ Mode_IRQ, 0x12 7 | .equ Mode_SVC, 0x13 8 | .equ Mode_ABT, 0x17 9 | .equ Mode_SYS, 0x1f 10 | .equ Mode_SVP, 0x13 11 | .equ Mode_UNDEF, 0x1B 12 | .equ Mode_HYP, 0x1A 13 | .equ Mode_MON, 0x16 14 | 15 | 16 | .align 5 17 | 18 | .globl hypervisor_vector 19 | hypervisor_vector: 20 | b hyp_reset_handler 21 | b . 22 | b . 23 | b . 24 | b . 25 | b hyp_handler 26 | b . 27 | b . 28 | 29 | hyp_reset_handler: 30 | // Set hypervisor mode stack pointer 31 | ldr sp,=hyp_stack_top 32 | 33 | // Configure Kernel mode SMCs to enter Hypervisor via the Hyp Configuration Register (HCR) 34 | mrc p15, 4, r0, c1, c1, 0 35 | orr r0, r0, #(1 << 19) //set hcr.tsc (bit 19) 36 | mcr p15, 4, r0, c1, c1, 0 //write hcr 37 | 38 | //Set up MMU for the hypervisor 39 | //Hypervisor Memory Attribute Indirection Register 0 (HMAIR0) 40 | // 0 - 01000100 41 | // 1 - 11111111 42 | // 3 - 00000100 43 | ldr r0, =0x0004ff44 44 | mcr p15, 4, r0, c10, c2, 0 //Write HMAIR0 45 | 46 | mov r0, #0x80000000 //Use LPAE format, covers entire address space 47 | mcr p15, 4, r0, c2, c0, 2 //Write HTCR 48 | 49 | ldr r1, =0x0 50 | ldr r0, =hypervisor_page_table 51 | mcrr p15, 4, r0, r1, c2 //rite HTTBR 52 | 53 | //Turn MMU on for the Hypervisor 54 | mrc p15, 4, r0, c1, c0, 0 55 | orr r0, r0, #1 //Set HSCTLR.M (bit 0), enables the MMU for Hyp mode 56 | mcr p15, 4, r0, c1, c0, 0 //Write HSCTLR 57 | 58 | LDR r1, =0x0 // ; Set high word of physical address 59 | LDR r0, =stage2_page_table // ; Set low word of physical address 60 | MCRR p15, 6, r0, r1, c2 // ; Write VTTBR 61 | 62 | LDR r0, =0x80000040 // ; Use LPAE format, start at level 1, entire address space 63 | MCR p15, 4, r0, c2, c1, 2 // ; Write VTCR 64 | 65 | MRC p15, 4, r0, c1, c1, 0 // ; Read HCR 66 | ORR r0, r0, #(1 << 19) // ; Set the HCR.TSC (bit 19) to enable SMC trapping 67 | ORR r0, r0, #1 // ; Set the HCR.VM (bit 0) to enable stage 2 translation 68 | ORR r0, r0, #(1 << 27) // ; Set the HCR.TGE (bit 27) to enable SVC trapping 69 | MCR p15, 4, r0, c1, c1, 0 // ; Write HCR 70 | 71 | b hypervisor_main 72 | 73 | .globl guest_setup 74 | guest_setup: 75 | LDR r0, =0x80008000 // destination 76 | LDR r1, =os_image // Beginning of source data 77 | LDR r2, =os_image_end //End of source data 78 | hyp_copy_guest_loop: 79 | ldmia r1!, {r3-r6} 80 | stmia r0!, {r3-r6} 81 | cmp r1, r2 82 | blt hyp_copy_guest_loop 83 | mov pc, lr 84 | 85 | .globl guest_boot 86 | guest_boot: 87 | ldr r11, =0x80008000 88 | msr elr_hyp, r11 89 | msr spsr_cxsf, #Mode_SVC 90 | eret 91 | 92 | .globl hyp_handler 93 | hyp_handler: 94 | push {r12} //r12 : general purpose register 95 | ldr r12, =vcpu 96 | stmia r12!, {r0-r11} 97 | pop {r0} 98 | stmia r12!, {r0, lr} 99 | 100 | ldr r0, =reason 101 | mrc p15, 4, r1, c5, c2, 0 102 | str r1, [r0, #0x00] 103 | ldr r0, =ret_addr 104 | mrs r1, elr_hyp 105 | str r1, [r0, #0x00] 106 | #add r1, #0x4 107 | #msr elr_hyp, r1 108 | 109 | bl do_hvc_handler 110 | ldr r12, =vcpu 111 | ldmia r12!, {r0-r11} 112 | push {r0} 113 | mov r0, r12 114 | ldmia r0!, {r12, lr} 115 | pop {r0} 116 | eret 117 | b . 118 | 119 | .section ".stack" 120 | hyp_stack_bottom: 121 | .rept 0x100 122 | .long 0x00 123 | .endr 124 | hyp_stack_top: 125 | -------------------------------------------------------------------------------- /image.S: -------------------------------------------------------------------------------- 1 | .section .main,#alloc 2 | .globl os_image 3 | os_image: 4 | .incbin "guest/guest.img" 5 | .globl os_image_end 6 | os_image_end: 7 | -------------------------------------------------------------------------------- /kernel.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * model.lds.S - simple linker script for stand-alone Linux booting 3 | * 4 | * Copyright (C) 2011 ARM Limited. All rights reserved. 5 | * 6 | * Use of this source code is governed by a BSD-style license that can be 7 | * found in the LICENSE.txt file. 8 | */ 9 | 10 | OUTPUT_FORMAT("elf32-littlearm") 11 | OUTPUT_ARCH(arm) 12 | TARGET(binary) 13 | 14 | ENTRY_SVC_STACK_SIZE = 0x1000; 15 | 16 | SECTIONS 17 | { 18 | . = 0xC0000000; 19 | .text : { *(.text) } 20 | .os_image : { *(.os_image)} 21 | . = ALIGN(8); /* the stack must be 64-bit aligned */ 22 | .stack : { *(.stack) } 23 | .data : { *(.data) } 24 | .bss : { *(.bss) } 25 | 26 | /*define a stack for the entry*/ 27 | . = ALIGN(0x1000); 28 | . += ENTRY_SVC_STACK_SIZE; 29 | stacktop = .; 30 | } 31 | -------------------------------------------------------------------------------- /libgcc.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/finallyjustice/armvisor/2e5523c29b5d43723b1b10d48f4d5639a6b5627d/libgcc.a -------------------------------------------------------------------------------- /pagetable.S: -------------------------------------------------------------------------------- 1 | .align 14 2 | .globl hypervisor_page_table 3 | hypervisor_page_table: 4 | //0x0040000000000449 5 | .long 0x00000449 6 | .long 0x00400000 7 | 8 | .long 0x40000449 9 | .long 0x00400000 10 | 11 | .long 0x80000745 12 | .long 0x00000000 13 | 14 | .long 0xC0000745 15 | .long 0x00000000 16 | 17 | .align 14 18 | .globl stage2_page_table 19 | stage2_page_table: 20 | //0x00400000000004C9 21 | .long 0x000004C9 22 | .long 0x00400000 23 | 24 | .long 0x40000449 25 | .long 0x00400000 26 | 27 | .long 0x800007C5 28 | .long 0x00000000 29 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | ~/ARM/FastModelsTools_9.1/bin/model_shell -m ~/ARM/FastModelsPortfolio_9.1/examples/FVP_VE/Build_Cortex-A15x1/Linux64-Release-GCC-4.4/cadi_system_Linux64-Release-GCC-4.4.so ./kernel.elf 2 | -------------------------------------------------------------------------------- /start.c: -------------------------------------------------------------------------------- 1 | #include "uart.h" 2 | #include "arm_asm.h" 3 | 4 | struct cpu_t vcpu; 5 | unsigned int reason; 6 | unsigned int ret_addr; 7 | 8 | void do_hvc_handler() 9 | { 10 | //cprintf("Exception class (0x%x): 0x%x - 0x%x\n", reason>>26, reason, ret_addr); 11 | 12 | switch (reason>>26) 13 | { 14 | case REASON_MCR_CP15: 15 | cprintf("[VMM] MCR or MRC access to CP15: 0x%x\n", ret_addr); 16 | while(1); 17 | break; 18 | 19 | case REASON_SVC: 20 | cprintf("[VMM] Supervisor Call Exception routed to hyper mode: 0x%x\n", ret_addr); 21 | while(1); 22 | break; 23 | 24 | case REASON_HVC: 25 | cprintf("[VMM] Hypervisor Call: 0x%x\n", ret_addr); 26 | break; 27 | 28 | case REASON_SMC: 29 | cprintf("[VMM] Trapped SMC Instruction: 0x%x\n", ret_addr); 30 | asm volatile(".arch_extension sec\n" 31 | ".arch_extension virt\n" 32 | "mrs r1, elr_hyp\n" 33 | "add r1, #0x4\n" 34 | "msr elr_hyp, r1\n"); 35 | break; 36 | 37 | case REASON_UNKNOWN: 38 | cprintf("[VMM] Unknown Reason: 0x%x\n", ret_addr); 39 | while(1); 40 | break; 41 | 42 | default: 43 | cprintf("[VMM] Other Reasons(0x%x): 0x%x\n", reason>>26, ret_addr); 44 | while(1); 45 | } 46 | 47 | //while(1); 48 | } 49 | 50 | void hypervisor_main() 51 | { 52 | cprintf("[VMM] init armvisor\n"); 53 | cprintf("[VMM] setup the guest image\n"); 54 | guest_setup(); 55 | cprintf("[VMM] start the guest VM\n"); 56 | guest_boot(); 57 | 58 | cprintf("You should never come here!\n"); 59 | //while(1); 60 | } 61 | -------------------------------------------------------------------------------- /uart.c: -------------------------------------------------------------------------------- 1 | volatile unsigned char * const UART0_BASE = (unsigned char *)0x1c090000; 2 | 3 | void uart_send(unsigned int c) 4 | { 5 | *UART0_BASE = c; 6 | if(c == '\n') 7 | *UART0_BASE = '\r'; 8 | } 9 | 10 | void printstr(char *s) 11 | { 12 | int i = 0; 13 | while(s[i]) 14 | { 15 | uart_send(s[i]); 16 | i++; 17 | } 18 | } 19 | 20 | void printint(int xx, int base, int sign) 21 | { 22 | static char digits[] = "0123456789abcdef"; 23 | char buf[16]; 24 | int i; 25 | unsigned int x; 26 | 27 | if(sign && (sign = xx < 0)) 28 | x = -xx; 29 | else 30 | x = xx; 31 | 32 | i = 0; 33 | do{ 34 | buf[i++] = digits[x % base]; 35 | }while((x /= base) != 0); 36 | 37 | if(sign) 38 | buf[i++] = '-'; 39 | 40 | while(--i >= 0) 41 | uart_send(buf[i]); 42 | } 43 | 44 | void cprintf(char *fmt, ...) 45 | { 46 | int i, c; 47 | unsigned int *argp; 48 | char *s; 49 | 50 | argp = (unsigned int*)(void*)(&fmt + 1); 51 | for(i = 0; (c = fmt[i] & 0xff) != 0; i++) 52 | { 53 | if(c != '%') 54 | { 55 | uart_send(c); 56 | continue; 57 | } 58 | c = fmt[++i] & 0xff; 59 | if(c == 0) 60 | break; 61 | switch(c) 62 | { 63 | case 'd': 64 | printint(*argp++, 10, 1); 65 | break; 66 | case 'x': 67 | case 'p': 68 | printint(*argp++, 16, 0); 69 | break; 70 | case 's': 71 | if((s = (char*)*argp++) == 0) 72 | s = "(null)"; 73 | for(; *s; s++) 74 | uart_send(*s); 75 | break; 76 | case '%': 77 | uart_send('%'); 78 | break; 79 | default: 80 | // Print unknown % sequence to draw attention. 81 | uart_send('%'); 82 | uart_send(c); 83 | break; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /uart.h: -------------------------------------------------------------------------------- 1 | #ifndef __UART_H__ 2 | #define __UART_H__ 3 | 4 | void uart_send(unsigned int c); 5 | void printstr(char *s); 6 | void printint(int xx, int base, int sign); 7 | void cprintf(char *fmt, ...); 8 | 9 | #endif 10 | --------------------------------------------------------------------------------