4
4
5
5
extern crate kvm;
6
6
extern crate memmap;
7
+ extern crate x86;
7
8
8
9
use kvm:: { Capability , Exit , IoDirection , System , Vcpu , VirtualMachine } ;
10
+ use std:: mem;
11
+ use memmap:: { Mmap , Protection } ;
9
12
use std:: fs:: File ;
10
13
use std:: io:: { BufRead , BufReader } ;
11
14
15
+ use x86:: shared:: control_regs;
16
+ use x86:: bits64:: paging;
17
+
12
18
#[ naked]
13
19
unsafe extern "C" fn use_the_port ( ) {
14
20
asm ! ( "inb $0, %al" :: "i" ( 0x01 ) :: "volatile" ) ;
@@ -71,13 +77,34 @@ fn io_example() {
71
77
72
78
// We don't need to populate the GDT if we have our segments setup
73
79
// cr0 - protected mode on, paging disabled
74
- sregs. cr0 = 0x50033 ;
80
+
81
+ let cr0 = control_regs:: CR0_ENABLE_PAGING | control_regs:: CR0_ALIGNMENT_MASK | control_regs:: CR0_WRITE_PROTECT | control_regs:: CR0_NUMERIC_ERROR | control_regs:: CR0_EXTENSION_TYPE | control_regs:: CR0_MONITOR_COPROCESSOR | control_regs:: CR0_PROTECTED_MODE ;
82
+ sregs. cr0 = cr0. bits ( ) as u64 ;
83
+
84
+ let cr4 = control_regs:: CR4_ENABLE_GLOBAL_PAGES | control_regs:: CR4_ENABLE_PAE | control_regs:: CR4_ENABLE_PSE ;
85
+ sregs. cr4 = cr4. bits ( ) as u64 ;
86
+
87
+ // Construct identity map
88
+ let mut allocations = Vec :: with_capacity ( 512 +1 ) ;
89
+ let mut pml4_mem = Mmap :: anonymous ( 4096 , Protection :: ReadWrite ) . unwrap ( ) ;
90
+ let pml4 = unsafe { mem:: transmute :: < * mut u8 , & mut paging:: PML4 > ( pml4_mem. mut_ptr ( ) ) } ;
91
+ allocations. push ( pml4_mem) ;
92
+ for i in 0 ..512 {
93
+ let mut pdpt_mem = Mmap :: anonymous ( 4096 , Protection :: ReadWrite ) . unwrap ( ) ;
94
+ let pdpt = unsafe { mem:: transmute :: < * mut u8 , & mut paging:: PDPT > ( pdpt_mem. mut_ptr ( ) ) } ;
95
+ for j in 0 ..512 {
96
+ let offset = j * ( 1024 * 1024 * 1024 ) + i * 512 * ( 1024 * 1024 * 1024 ) ;
97
+ pdpt[ j] = paging:: PDPTEntry :: new ( paging:: PAddr :: from_u64 ( offset as u64 ) , paging:: PDPT_P | paging:: PDPT_RW | paging:: PDPT_PS ) ;
98
+ }
99
+ pml4[ i] = paging:: PML4Entry :: new ( paging:: PAddr :: from_u64 ( pdpt as * const _ as u64 ) , paging:: PML4_P | paging:: PML4_RW ) ;
100
+ allocations. push ( pdpt_mem) ;
101
+ }
102
+ sregs. cr3 = & pml4 as * const _ as _ ;
75
103
76
104
// Set the special registers
77
105
vcpu. set_sregs ( & sregs) . unwrap ( ) ;
78
106
79
107
let mut regs = vcpu. get_regs ( ) . unwrap ( ) ;
80
- // set the instruction pointer to 1 MB
81
108
regs. rip = & use_the_port as * const _ as _ ;
82
109
println ! ( "regs.rip = {:X}" , regs. rip) ;
83
110
regs. rflags = 0x2 ;
@@ -88,6 +115,7 @@ fn io_example() {
88
115
89
116
// Ensure that the exit reason we get back indicates that the I/O
90
117
// instruction was executed
118
+ println ! ( "{:?}" , run) ;
91
119
assert ! ( run. exit_reason == Exit :: Io ) ;
92
120
let io = unsafe { * run. io ( ) } ;
93
121
assert ! ( io. direction == IoDirection :: In ) ;
0 commit comments