Skip to content

Commit b124e0d

Browse files
YadongQijren1
authored andcommitted
trusty: implement hypercall to initialize trusty
UOS_Loader will trigger boot of Trusty-OS by HC_INITIALIZE_TRUSTY. UOS_Loader will load trusty image and alloc runtime memory for trusty. UOS_Loader will transfer these information include trusty runtime memory base address, entry address and memory size to hypervisor by trusty_boot_param structure. In hypervisor, once HC_INITIALIZE_TRUSTY received, it will create EPT for Secure World, save Normal World vCPU context, init Secure World vCPU context and switch World state to Secure World. Signed-off-by: Qi Yadong <yadong.qi@intel.com>
1 parent 1fd07ba commit b124e0d

File tree

7 files changed

+208
-11
lines changed

7 files changed

+208
-11
lines changed

hypervisor/Documentation/Trusty.txt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ Note: Trusty OS is running in Secure World in the architecture above.
4949
**************************
5050
Trusty specific Hypercalls
5151
**************************
52-
1. HC_LAUNCH_TRUSTY
53-
->This Hypercall is used by UOSloader (User OS Bootloader) to request ACRN to launch Trusty.
52+
1. HC_INITIALIZE_TRUSTY
53+
->This Hypercall is used by UOS_Loader to request ACRN to initialize Trusty.
5454
->The Trusty memory region range, entry point must be specified.
5555
->Hypervisor needs to save current vCPU contexts (Normal World).
5656
2. HC_WORLD_SWITCH
@@ -60,7 +60,7 @@ Trusty specific Hypercalls
6060

6161
API
6262
---
63-
1. hcall_launch_trusty(vm_t *vm);
63+
1. hcall_initialize_trusty(vm_t *vm);
6464
2. hcall_world_switch(vm_t *vm);
6565

6666

@@ -71,12 +71,12 @@ Per design, UOSloader will trigger boot of Trusty. So the boot flow will be:
7171
UOSloader --> ACRN --> Trusty --> ACRN --> UOSloader
7272

7373
Detail:
74-
1. UOSloader
74+
1. UOS_Loader
7575
1.1 load and verify trusty image from virtual disk.
7676
1.2 allocate runtime memory for trusty.
7777
1.3 do ELF relocation of trusty image and get entry address.
78-
1.4 call HC_LAUNCH_TRUSTY with trusty memory base and entry address.
79-
2. ACRN(HC_LAUNCH_TRUSTY)
78+
1.4 call HC_INITIALIZE_TRUSTY with trusty memory base and entry address.
79+
2. ACRN(HC_INITIALIZE_TRUSTY)
8080
2.1 save World context for Normal World.
8181
2.2 init World context for Secure World(RIP, RSP, EPT, etc.).
8282
2.3 resume to Secure World.
@@ -85,9 +85,9 @@ Detail:
8585
3.2 call HC_WORLD_SWITCH to switch back to Normal World if boot completed.
8686
4. ACRN(HC_WORLD_SWITCH)
8787
4.1 save World context for the World which caused this vmexit(Secure World)
88-
4.2 restore World context for next World(Normal World(UOSloader))
89-
4.3 resume to next World(UOSloader)
90-
5. UOSloader
88+
4.2 restore World context for next World(Normal World(UOS_Loader))
89+
4.3 resume to next World(UOS_Loader)
90+
5. UOS_Loader
9191
5.1 continue to boot.
9292

9393

hypervisor/arch/x86/guest/vmcall.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ int vmcall_handler(struct vcpu *vcpu)
138138
ret = hcall_world_switch(vcpu);
139139
break;
140140

141+
case HC_INITIALIZE_TRUSTY:
142+
ret = hcall_initialize_trusty(vcpu, param1);
143+
break;
144+
141145
default:
142146
pr_err("op %d: Invalid hypercall\n", hypcall_id);
143147
ret = -1;

hypervisor/arch/x86/trusty.c

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,38 @@ _Static_assert(NR_WORLD == 2, "Only 2 Worlds supported!");
3939
/* Trusty EPT rebase gpa: 511G */
4040
#define TRUSTY_EPT_REBASE_GPA (511ULL*1024ULL*1024ULL*1024ULL)
4141

42+
#define TRUSTY_VERSION 1
43+
44+
struct trusty_startup_param {
45+
uint32_t size_of_this_struct;
46+
uint32_t mem_size;
47+
uint64_t tsc_per_ms;
48+
uint64_t trusty_mem_base;
49+
uint32_t reserved;
50+
uint8_t padding[4];
51+
};
52+
53+
struct trusty_mem {
54+
/* The first page of trusty memory is reserved for key_info and
55+
* trusty_startup_param.
56+
*/
57+
union {
58+
struct {
59+
struct key_info key_info;
60+
struct trusty_startup_param startup_param;
61+
};
62+
uint8_t page[CPU_PAGE_SIZE];
63+
} first_page;
64+
65+
/* The left memory is for trusty's code/data/heap/stack
66+
*/
67+
uint8_t left_mem[0];
68+
};
69+
70+
_Static_assert(sizeof(struct trusty_startup_param)
71+
+ sizeof(struct key_info) < 0x1000,
72+
"trusty_startup_param + key_info > 1Page size(4KB)!");
73+
4274
#define save_segment(seg, SEG_NAME) \
4375
{ \
4476
seg.selector = exec_vmread(VMX_GUEST_##SEG_NAME##_SEL); \
@@ -239,3 +271,104 @@ void switch_world(struct vcpu *vcpu, int next_world)
239271
/* Update world index */
240272
arch_vcpu->cur_context = next_world;
241273
}
274+
275+
/* Put key_info and trusty_startup_param in the first Page of Trusty
276+
* runtime memory
277+
*/
278+
static void setup_trusty_info(struct vcpu *vcpu,
279+
uint32_t mem_size, uint64_t mem_base_hpa)
280+
{
281+
struct trusty_mem *mem;
282+
283+
mem = (struct trusty_mem *)(HPA2HVA(mem_base_hpa));
284+
285+
/* TODO: prepare vkey_info */
286+
287+
/* Prepare trusty startup info */
288+
mem->first_page.startup_param.size_of_this_struct =
289+
sizeof(struct trusty_startup_param);
290+
mem->first_page.startup_param.mem_size = mem_size;
291+
mem->first_page.startup_param.tsc_per_ms = TIME_MS_DELTA;
292+
mem->first_page.startup_param.trusty_mem_base = TRUSTY_EPT_REBASE_GPA;
293+
294+
/* According to trusty boot protocol, it will use RDI as the
295+
* address(GPA) of startup_param on boot. Currently, the startup_param
296+
* is put in the first page of trusty memory just followed by key_info.
297+
*/
298+
vcpu->arch_vcpu.contexts[SECURE_WORLD].guest_cpu_regs.regs.rdi
299+
= (uint64_t)TRUSTY_EPT_REBASE_GPA + sizeof(struct key_info);
300+
}
301+
302+
/* Secure World will reuse environment of UOS_Loder since they are
303+
* both booting from and running in 64bit mode, except GP registers.
304+
* RIP, RSP and RDI are specified below, other GP registers are leaved
305+
* as 0.
306+
*/
307+
static void init_secure_world_env(struct vcpu *vcpu,
308+
uint64_t entry_gpa,
309+
uint64_t base_hpa,
310+
uint32_t size)
311+
{
312+
vcpu->arch_vcpu.inst_len = 0;
313+
vcpu->arch_vcpu.contexts[SECURE_WORLD].rip = entry_gpa;
314+
vcpu->arch_vcpu.contexts[SECURE_WORLD].rsp =
315+
TRUSTY_EPT_REBASE_GPA + size;
316+
exec_vmwrite(VMX_GUEST_RSP,
317+
TRUSTY_EPT_REBASE_GPA + size);
318+
319+
setup_trusty_info(vcpu, size, base_hpa);
320+
}
321+
322+
bool initialize_trusty(struct vcpu *vcpu, uint64_t param)
323+
{
324+
uint64_t trusty_entry_gpa, trusty_base_gpa, trusty_base_hpa;
325+
struct vm *vm = vcpu->vm;
326+
struct trusty_boot_param *boot_param =
327+
(struct trusty_boot_param *)(gpa2hpa(vm, param));
328+
329+
if (sizeof(struct trusty_boot_param) !=
330+
boot_param->size_of_this_struct) {
331+
pr_err("%s: sizeof(struct trusty_boot_param) mismatch!\n",
332+
__func__);
333+
return false;
334+
}
335+
336+
if (boot_param->version != TRUSTY_VERSION) {
337+
pr_err("%s: version of(trusty_boot_param) mismatch!\n",
338+
__func__);
339+
return false;
340+
}
341+
342+
if (!boot_param->entry_point) {
343+
pr_err("%s: Invalid entry point\n", __func__);
344+
return false;
345+
}
346+
347+
if (!boot_param->base_addr) {
348+
pr_err("%s: Invalid memory base address\n", __func__);
349+
return false;
350+
}
351+
352+
trusty_entry_gpa = (uint64_t)boot_param->entry_point;
353+
trusty_base_gpa = (uint64_t)boot_param->base_addr;
354+
355+
create_secure_world_ept(vm, trusty_base_gpa, boot_param->mem_size,
356+
TRUSTY_EPT_REBASE_GPA);
357+
trusty_base_hpa = vm->sworld_control.sworld_memory.base_hpa;
358+
359+
exec_vmwrite64(VMX_EPT_POINTER_FULL,
360+
((uint64_t)vm->arch_vm.sworld_eptp) | (3<<3) | 6);
361+
362+
/* save Normal World context */
363+
save_world_ctx(&vcpu->arch_vcpu.contexts[NORMAL_WORLD]);
364+
365+
/* init secure world environment */
366+
init_secure_world_env(vcpu,
367+
trusty_entry_gpa - trusty_base_gpa + TRUSTY_EPT_REBASE_GPA,
368+
trusty_base_hpa, boot_param->mem_size);
369+
370+
/* switch to Secure World */
371+
vcpu->arch_vcpu.cur_context = SECURE_WORLD;
372+
373+
return true;
374+
}

hypervisor/common/trusty_hypercall.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ int64_t hcall_world_switch(struct vcpu *vcpu)
5151
}
5252

5353
if (!vcpu->vm->arch_vm.sworld_eptp) {
54-
pr_err("Trusty is not launched!\n");
54+
pr_err("Trusty is not initialized!\n");
5555
return -1;
5656
}
5757

@@ -61,3 +61,31 @@ int64_t hcall_world_switch(struct vcpu *vcpu)
6161
switch_world(vcpu, next_world_id);
6262
return 0;
6363
}
64+
65+
int64_t hcall_initialize_trusty(struct vcpu *vcpu, uint64_t param)
66+
{
67+
if (!is_hypercall_from_ring0()) {
68+
pr_err("%s() is only allowed from RING-0!\n", __func__);
69+
return -1;
70+
}
71+
72+
if (!vcpu->vm->sworld_control.sworld_enabled) {
73+
pr_err("Secure World is not enabled!\n");
74+
return -1;
75+
}
76+
77+
if (vcpu->vm->arch_vm.sworld_eptp) {
78+
pr_err("Trusty already initialized!\n");
79+
return -1;
80+
}
81+
82+
ASSERT(vcpu->arch_vcpu.cur_context == NORMAL_WORLD,
83+
"The Trusty Initialize hypercall must be from Normal World");
84+
85+
if (!initialize_trusty(vcpu, param)) {
86+
pr_err("Failed to initialize trusty!\n");
87+
return -1;
88+
}
89+
90+
return 0;
91+
}

hypervisor/include/arch/x86/trusty.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ struct secure_world_control {
129129
};
130130

131131
void switch_world(struct vcpu *vcpu, int next_world);
132+
bool initialize_trusty(struct vcpu *vcpu, uint64_t param);
132133

133134
#endif /* TRUSTY_H_ */
134135

hypervisor/include/common/hypercall.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,17 @@ int64_t hcall_setup_sbuf(struct vm *vm, uint64_t param);
335335
*/
336336
int64_t hcall_world_switch(struct vcpu *vcpu);
337337

338+
/**
339+
* @brief Initialize environment for Trusty-OS on a VCPU.
340+
*
341+
* @param VCPU Pointer to VCPU data structure
342+
* @param param's guest physical address. This gpa points to
343+
* struct trusty_boot_param
344+
*
345+
* @return 0 on success, non-zero on error.
346+
*/
347+
int64_t hcall_initialize_trusty(struct vcpu *vcpu, uint64_t param);
348+
338349
/**
339350
* @}
340351
*/

hypervisor/include/public/acrn_hv_defs.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595

9696
/* Trusty */
9797
#define HC_ID_TRUSTY_BASE 0x70UL
98-
#define HC_LAUNCH_TRUSTY _HC_ID(HC_ID, HC_ID_TRUSTY_BASE + 0x00)
98+
#define HC_INITIALIZE_TRUSTY _HC_ID(HC_ID, HC_ID_TRUSTY_BASE + 0x00)
9999
#define HC_WORLD_SWITCH _HC_ID(HC_ID, HC_ID_TRUSTY_BASE + 0x01)
100100
#define HC_GET_SEC_INFO _HC_ID(HC_ID, HC_ID_TRUSTY_BASE + 0x02)
101101

@@ -226,6 +226,26 @@ struct hc_api_version {
226226
uint32_t minor_version;
227227
} __aligned(8);
228228

229+
/**
230+
* Trusty boot params, used for HC_INITIALIZE_TRUSTY
231+
*/
232+
struct trusty_boot_param {
233+
/** sizeof this structure */
234+
uint32_t size_of_this_struct;
235+
236+
/** version of this structure */
237+
uint32_t version;
238+
239+
/** trusty runtime memory base address */
240+
uint32_t base_addr;
241+
242+
/** trusty entry point */
243+
uint32_t entry_point;
244+
245+
/** trusty runtime memory size */
246+
uint32_t mem_size;
247+
} __aligned(8);
248+
229249
/**
230250
* @}
231251
*/

0 commit comments

Comments
 (0)