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