|
1 | 1 | use {
|
2 | 2 | alloc::alloc::{alloc_zeroed, handle_alloc_error},
|
3 |
| - alloc::boxed::Box, |
4 |
| - core::ffi::c_void, |
5 | 3 | core::{alloc::Layout, arch::global_asm},
|
6 |
| - hypervisor::{ |
7 |
| - intel::{capture::GuestRegisters, page::Page, shared_data::SharedData}, |
8 |
| - vmm::start_hypervisor, |
9 |
| - }, |
| 4 | + hypervisor::{global::GlobalState, intel::page::Page, vmm::start_hypervisor}, |
10 | 5 | log::debug,
|
11 | 6 | uefi::{
|
12 | 7 | proto::loaded_image::LoadedImage,
|
13 | 8 | table::{Boot, SystemTable},
|
14 | 9 | },
|
15 | 10 | };
|
16 | 11 |
|
17 |
| -pub struct Virtualize { |
18 |
| - guest_registers: GuestRegisters, |
19 |
| - shared_data: Box<SharedData>, |
20 |
| - landing_code: usize, |
21 |
| - stack_base: u64, |
22 |
| -} |
23 |
| - |
24 |
| -impl Virtualize { |
25 |
| - pub fn new( |
26 |
| - guest_registers: GuestRegisters, |
27 |
| - shared_data: Box<SharedData>, |
28 |
| - system_table: &SystemTable<Boot>, |
29 |
| - ) -> Self { |
30 |
| - debug!("Zapping the Relocation Table and allocating separate stack space"); |
31 |
| - |
32 |
| - let boot_service = system_table.boot_services(); |
33 |
| - |
34 |
| - // Open the loaded image protocol to get the current image base and image size. |
35 |
| - let loaded_image = boot_service |
36 |
| - .open_protocol_exclusive::<LoadedImage>(boot_service.image_handle()) |
37 |
| - .unwrap(); |
38 |
| - |
39 |
| - // Get the current image base and image size. |
40 |
| - let (image_base, image_size) = loaded_image.info(); |
41 |
| - |
42 |
| - let image_base = image_base as usize; |
| 12 | +pub fn virtualize_system(global_state: &mut GlobalState, system_table: &SystemTable<Boot>) -> ! { |
| 13 | + let boot_service = system_table.boot_services(); |
43 | 14 |
|
44 |
| - let image_range = image_base..image_base + image_size as usize; |
45 |
| - debug!("Image base: {:#x?}", image_range); |
| 15 | + // Open the loaded image protocol to get the current image base and image size. |
| 16 | + let loaded_image = boot_service |
| 17 | + .open_protocol_exclusive::<LoadedImage>(boot_service.image_handle()) |
| 18 | + .unwrap(); |
46 | 19 |
|
47 |
| - // Prevent relocation by zapping the Relocation Table in the PE header. UEFI |
48 |
| - // keeps the list of runtime drivers and applies patches into their code and |
49 |
| - // data according to relocation information, as address translation switches |
50 |
| - // from physical-mode to virtual-mode when the OS starts. This causes a problem |
51 |
| - // with us because the host part keeps running under physical-mode, as the |
52 |
| - // host has its own page tables. Relocation ends up breaking the host code. |
53 |
| - // The easiest way is prevented this from happening is to nullify the relocation |
54 |
| - // table. |
55 |
| - unsafe { |
56 |
| - *((image_base + 0x128) as *mut u32) = 0; |
57 |
| - *((image_base + 0x12c) as *mut u32) = 0; |
58 |
| - } |
| 20 | + // Get the current image base and image size. |
| 21 | + let (image_base, image_size) = loaded_image.info(); |
59 | 22 |
|
60 |
| - // Allocate separate stack space. This is never freed. |
61 |
| - let layout = Layout::array::<Page>(0x10).unwrap(); |
| 23 | + let image_base = image_base as usize; |
62 | 24 |
|
63 |
| - let stack = unsafe { alloc_zeroed(layout) }; |
| 25 | + let image_range = image_base..image_base + image_size as usize; |
| 26 | + debug!("Image base: {:#x?}", image_range); |
64 | 27 |
|
65 |
| - if stack.is_null() { |
66 |
| - handle_alloc_error(layout); |
67 |
| - } |
| 28 | + // Prevent relocation by zapping the Relocation Table in the PE header. UEFI |
| 29 | + // keeps the list of runtime drivers and applies patches into their code and |
| 30 | + // data according to relocation information, as address translation switches |
| 31 | + // from physical-mode to virtual-mode when the OS starts. This causes a problem |
| 32 | + // with us because the host part keeps running under physical-mode, as the |
| 33 | + // host has its own page tables. Relocation ends up breaking the host code. |
| 34 | + // The easiest way is prevented this from happening is to nullify the relocation |
| 35 | + // table. |
| 36 | + unsafe { |
| 37 | + *((image_base + 0x128) as *mut u32) = 0; |
| 38 | + *((image_base + 0x12c) as *mut u32) = 0; |
| 39 | + } |
68 | 40 |
|
69 |
| - let stack_base = stack as u64 + layout.size() as u64 - 0x10; |
70 |
| - debug!("Stack range: {:#x?}", stack_base..stack as u64); |
| 41 | + // Allocate separate stack space. This is never freed. |
| 42 | + let layout = Layout::array::<Page>(0x10).unwrap(); |
71 | 43 |
|
72 |
| - debug!("Relocation Table zapped and separate stack space allocated successfully!"); |
| 44 | + let stack = unsafe { alloc_zeroed(layout) }; |
73 | 45 |
|
74 |
| - Self { |
75 |
| - guest_registers, |
76 |
| - shared_data, |
77 |
| - landing_code: start_hypervisor as usize, |
78 |
| - stack_base, |
79 |
| - } |
| 46 | + if stack.is_null() { |
| 47 | + handle_alloc_error(layout); |
80 | 48 | }
|
81 |
| -} |
82 |
| - |
83 |
| -pub extern "efiapi" fn switch_stack_and_virtualize_core(procedure_argument: *mut c_void) { |
84 |
| - let virtualize: &mut Virtualize = unsafe { &mut *(procedure_argument as *mut Virtualize) }; |
85 | 49 |
|
86 |
| - debug!("Switching stack and virtualizing core"); |
| 50 | + let stack_base = stack as u64 + layout.size() as u64 - 0x10; |
| 51 | + debug!("Stack range: {:#x?}", stack_base..stack as u64); |
87 | 52 |
|
88 |
| - // Call `switch_stack` with the context data. |
89 |
| - // Assuming `switch_stack` never returns, similar to the original `virtualize_system` behavior. |
90 |
| - unsafe { |
91 |
| - switch_stack( |
92 |
| - &virtualize.guest_registers, |
93 |
| - &mut virtualize.shared_data, |
94 |
| - virtualize.landing_code, |
95 |
| - virtualize.stack_base, |
96 |
| - ); |
97 |
| - } |
| 53 | + unsafe { switch_stack(global_state, start_hypervisor as usize, stack_base) }; |
98 | 54 | }
|
99 | 55 |
|
100 | 56 | extern "efiapi" {
|
101 | 57 | /// Jumps to the landing code with the new stack pointer.
|
102 |
| - fn switch_stack( |
103 |
| - guest_registers: &GuestRegisters, |
104 |
| - shared_data: &mut SharedData, |
105 |
| - landing_code: usize, |
106 |
| - stack_base: u64, |
107 |
| - ) -> !; |
| 58 | + fn switch_stack(global_state: &mut GlobalState, landing_code: usize, stack_base: u64) -> !; |
108 | 59 | }
|
109 | 60 |
|
110 | 61 | global_asm!(
|
111 | 62 | r#"
|
112 | 63 | // The module containing the `switch_stack` function.
|
113 |
| -
|
114 | 64 | // Jumps to the landing code with the new stack pointer.
|
115 | 65 | //
|
116 |
| -// fn switch_stack(guest_registers: &GuestRegisters, shared_data: &mut SharedData, landing_code: usize, stack_base: u64) -> ! |
| 66 | +// fn switch_stack(global_state: &mut GlobalState, landing_code: usize, stack_base: u64) -> ! |
117 | 67 | .global switch_stack
|
118 | 68 | switch_stack:
|
119 | 69 | xchg bx, bx
|
120 |
| - mov rsp, r9 |
121 |
| - jmp r8 |
| 70 | + mov rsp, r8 |
| 71 | + jmp rdx |
122 | 72 | "#
|
123 | 73 | );
|
0 commit comments