1 /* 2 * VMM startup file. 3 * 4 * COPYRIGHT (C) 2013-2014, Real-Thread Information Technology Ltd 5 * All rights reserved 6 * 7 * SPDX-License-Identifier: Apache-2.0 8 * 9 * Change Logs: 10 * Date Author Notes 11 * 2013-06-15 Bernard the first verion 12 */ 13 14 #include <rthw.h> 15 #include <rtthread.h> 16 17 #include "board.h" 18 19 #include "vmm.h" 20 #include "vmm_context.h" 21 22 extern void rt_hw_interrupt_init(void); 23 extern void rt_application_init(void); 24 25 void vmm_entry(struct vmm_entry_param* param) SECTION(".vmm_init"); 26 27 #ifdef RT_USING_LOGTRACE 28 #include <log_trace.h> 29 static struct log_trace_session _lgs = { 30 .id = {.name = "vmm"}, 31 .lvl = LOG_TRACE_LEVEL_VERBOSE, 32 }; 33 #endif 34 35 struct rt_thread vmm_thread SECTION(".bss.share.vmm"); 36 extern rt_uint8_t vmm_stack_start; 37 extern rt_uint8_t vmm_stack_end; 38 39 void vmm_thread_init(struct rt_thread *thread, const char *name) 40 { 41 extern struct rt_thread *rt_current_thread; 42 43 rt_thread_init(thread, name, RT_NULL, RT_NULL, 44 &vmm_stack_start, &vmm_stack_end - &vmm_stack_start, 45 RT_THREAD_PRIORITY_MAX - 1, 10); 46 47 /* set thread to ready status but not switch to */ 48 rt_thread_startup(thread); 49 50 /* set current thread as vmm thread */ 51 rt_current_thread = thread; 52 } 53 54 #ifdef VMM_VERIFY_GUEST 55 static void _verify_guest(void *p) 56 { 57 while (1) 58 { 59 rt_thread_delay(RT_TICK_PER_SECOND/4); 60 vmm_verify_guest_status(vmm_thread.sp); 61 } 62 } 63 64 static void vmm_create_monitor(void) 65 { 66 rt_thread_t tid; 67 68 tid = rt_thread_create("vmon", 69 _verify_guest, RT_NULL, 70 1024, 8, 20); 71 if (tid) 72 rt_thread_startup(tid); 73 } 74 #endif 75 76 #ifdef RT_VMM_USING_DOMAIN 77 extern unsigned long guest_domain_val; 78 extern unsigned long vmm_domain_val; 79 #endif 80 81 static void vmm_entry_glue(rt_uint32_t level, 82 unsigned int vmm_domain, 83 unsigned int kernel_domain) 84 /* inline would make the section setting meaningless */ 85 __attribute__((noinline)) 86 SECTION(".vmm_glue"); 87 static void vmm_entry_glue(rt_uint32_t level, 88 unsigned int vmm_domain, 89 unsigned int kernel_domain) 90 { 91 rt_schedule(); 92 93 #ifdef RT_VMM_USING_DOMAIN 94 /* protect us from the guest code, but leave the shared region permission 95 */ 96 guest_domain_val &= ~(0x3 << (vmm_domain * 2)); 97 98 /* don't touch the guest kernel space */ 99 vmm_domain_val &= ~(0x3 << (kernel_domain * 2)); 100 #endif 101 102 rt_hw_interrupt_enable(level); 103 } 104 105 void vmm_entry(struct vmm_entry_param *param) 106 { 107 rt_uint32_t level; 108 109 level = rt_hw_interrupt_disable(); 110 111 /* set iomap */ 112 vmm_iomap_init(param->iomap); 113 114 /* set VMM context address */ 115 vmm_context_init(&RT_VMM_SHARE->ctx); 116 117 /* init hardware interrupt */ 118 rt_hw_interrupt_init(); 119 120 vmm_vector_init(); 121 122 /* init board */ 123 rt_hw_board_init(); 124 125 #ifdef RT_USING_LOGTRACE 126 /* Some parts of VMM use log_trace, so we need to init it right after 127 * board_init. */ 128 log_trace_init(); 129 log_trace_set_device(RT_CONSOLE_DEVICE_NAME); 130 131 log_trace_register_session(&_lgs); 132 #endif 133 134 /* show version */ 135 rt_show_version(); 136 rt_kprintf("share ctx: %p(%x)\n", 137 &RT_VMM_SHARE->ctx, sizeof(RT_VMM_SHARE->ctx)); 138 139 /* init timer system */ 140 rt_system_timer_init(); 141 142 { 143 rt_uint32_t ttbr; 144 asm volatile ("mrc p15, 0, %0, c2, c0, 0\n" 145 : "=r"(ttbr)); 146 rt_kprintf("Linux TTBR: 0x%08x\n", ttbr); 147 /* 148 *rt_hw_cpu_dump_page_table((void*)((ttbr & (0xffffc000)) 149 * - 0x80000000 + 0xC0000000)); 150 */ 151 /*rt_hw_cpu_dump_page_table((void*)(0xc0004000));*/ 152 } 153 154 #ifdef RT_VMM_USING_DOMAIN 155 vmm_context_init_domain(param->domain); 156 #endif 157 158 rt_kprintf("heap: 0x%p - 0x%p, %dKi bytes\n", 159 (void*)HEAP_BEGIN, (void*)HEAP_END, 160 ((int)HEAP_END - (int)HEAP_BEGIN) / 1024); 161 /* init heap memory system */ 162 rt_system_heap_init((void*)HEAP_BEGIN, (void*)HEAP_END); 163 164 /* init scheduler system */ 165 rt_system_scheduler_init(); 166 167 rt_kprintf("user application init.\n"); 168 /* init application */ 169 rt_application_init(); 170 171 #ifdef VMM_VERIFY_GUEST 172 vmm_create_monitor(); 173 #endif 174 175 rt_system_timer_thread_init(); 176 177 vmm_thread_init(&vmm_thread, "vmm"); 178 179 #ifdef RT_VMM_USING_DOMAIN 180 rt_kprintf("domain protect present\n"); 181 #endif 182 /* start scheduler */ 183 rt_kprintf("do the first scheduling...\n"); 184 185 vmm_entry_glue(level, 186 param->domain->vmm, 187 param->domain->kernel); 188 } 189 190