5
5
// Use of this source code is governed by a BSD-style license that can be
6
6
// found in the THIRD-PARTY file.
7
7
8
- use std:: mem;
8
+ use std:: { fmt , mem} ;
9
9
10
10
use kvm_bindings:: { kvm_fpu, kvm_regs, kvm_sregs} ;
11
11
use kvm_ioctls:: VcpuFd ;
@@ -19,42 +19,76 @@ const PDPTE_START: u64 = 0xa000;
19
19
const PDE_START : u64 = 0xb000 ;
20
20
21
21
/// Errors thrown while setting up x86_64 registers.
22
- #[ derive( Debug ) ]
22
+ #[ derive( Debug , thiserror :: Error ) ]
23
23
pub enum Error {
24
24
/// Failed to get SREGs for this CPU.
25
+ #[ error( "Failed to get SREGs for this CPU: {0}" ) ]
25
26
GetStatusRegisters ( kvm_ioctls:: Error ) ,
26
27
/// Failed to set base registers for this CPU.
28
+ #[ error( "Failed to set base registers for this CPU: {0}" ) ]
27
29
SetBaseRegisters ( kvm_ioctls:: Error ) ,
28
30
/// Failed to configure the FPU.
31
+ #[ error( "Failed to configure the FPU: {0}" ) ]
29
32
SetFPURegisters ( kvm_ioctls:: Error ) ,
30
33
/// Failed to set SREGs for this CPU.
34
+ #[ error( "Failed to set SREGs for this CPU: {0}" ) ]
31
35
SetStatusRegisters ( kvm_ioctls:: Error ) ,
32
36
/// Writing the GDT to RAM failed.
37
+ #[ error( "Writing the GDT to RAM failed." ) ]
33
38
WriteGDT ,
34
39
/// Writing the IDT to RAM failed.
40
+ #[ error( "Writing the IDT to RAM failed" ) ]
35
41
WriteIDT ,
36
42
/// Writing PDPTE to RAM failed.
43
+ #[ error( "WritePDPTEAddress" ) ]
37
44
WritePDPTEAddress ,
38
45
/// Writing PDE to RAM failed.
46
+ #[ error( "WritePDEAddress" ) ]
39
47
WritePDEAddress ,
40
48
/// Writing PML4 to RAM failed.
49
+ #[ error( "WritePML4Address" ) ]
41
50
WritePML4Address ,
42
51
}
43
52
type Result < T > = std:: result:: Result < T , Error > ;
44
53
54
+ /// Error type for [`setup_fpu`].
55
+ #[ derive( Debug , derive_more:: From ) ]
56
+ pub struct SetupFpuError ( vmm_sys_util:: errno:: Error ) ;
57
+ impl std:: error:: Error for SetupFpuError { }
58
+ impl fmt:: Display for SetupFpuError {
59
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
60
+ write ! ( f, "Failed to setup FPU: {}" , self . 0 )
61
+ }
62
+ }
63
+
45
64
/// Configure Floating-Point Unit (FPU) registers for a given CPU.
46
65
///
47
66
/// # Arguments
48
67
///
49
68
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
50
- pub fn setup_fpu ( vcpu : & VcpuFd ) -> Result < ( ) > {
69
+ ///
70
+ /// # Errors
71
+ ///
72
+ /// When [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_fpu`] errors.
73
+ pub fn setup_fpu ( vcpu : & VcpuFd ) -> std:: result:: Result < ( ) , SetupFpuError > {
51
74
let fpu: kvm_fpu = kvm_fpu {
52
75
fcw : 0x37f ,
53
76
mxcsr : 0x1f80 ,
54
77
..Default :: default ( )
55
78
} ;
56
79
57
- vcpu. set_fpu ( & fpu) . map_err ( Error :: SetFPURegisters )
80
+ let res = vcpu. set_fpu ( & fpu) ?;
81
+ Ok ( res)
82
+ }
83
+
84
+ /// Error type of [`setup_regs`].
85
+ #[ derive( Debug , derive_more:: From ) ]
86
+ pub struct SetupRegistersError ( vmm_sys_util:: errno:: Error ) ;
87
+ impl std:: error:: Error for SetupRegistersError { }
88
+ impl fmt:: Display for SetupRegistersError {
89
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
90
+ write ! ( f, "Failed to setup registers:{}" , self . 0 )
91
+ }
58
92
}
59
93
60
94
/// Configure base registers for a given CPU.
@@ -63,7 +97,11 @@ pub fn setup_fpu(vcpu: &VcpuFd) -> Result<()> {
63
97
///
64
98
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
65
99
/// * `boot_ip` - Starting instruction pointer.
66
- pub fn setup_regs ( vcpu : & VcpuFd , boot_ip : u64 ) -> Result < ( ) > {
100
+ ///
101
+ /// # Errors
102
+ ///
103
+ /// When [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_regs`] errors.
104
+ pub fn setup_regs ( vcpu : & VcpuFd , boot_ip : u64 ) -> std:: result:: Result < ( ) , SetupRegistersError > {
67
105
let regs: kvm_regs = kvm_regs {
68
106
rflags : 0x0000_0000_0000_0002u64 ,
69
107
rip : boot_ip,
@@ -79,7 +117,24 @@ pub fn setup_regs(vcpu: &VcpuFd, boot_ip: u64) -> Result<()> {
79
117
..Default :: default ( )
80
118
} ;
81
119
82
- vcpu. set_regs ( & regs) . map_err ( Error :: SetBaseRegisters )
120
+ vcpu. set_regs ( & regs) . map_err ( SetupRegistersError )
121
+ }
122
+
123
+ /// Error type for [`setup_sregs`].
124
+ #[ derive( Debug , thiserror:: Error ) ]
125
+ pub enum SetupSegmentRegistersError {
126
+ /// Failed to get segment registers
127
+ #[ error( "Failed to get segment registers: {0}" ) ]
128
+ GetSegmentRegisters ( vmm_sys_util:: errno:: Error ) ,
129
+ /// Failed to configure segments and segment registers
130
+ #[ error( "Failed to configure segments and segment registers: {0}" ) ]
131
+ ConfigureSegmentsAndSegmentRegisters ( Error ) ,
132
+ /// Failed to setup page tables
133
+ #[ error( "Failed to setup page tables: {0}" ) ]
134
+ SetupPageTables ( Error ) ,
135
+ /// Failed to set segment registers
136
+ #[ error( "Failed to set segment registers: {0}" ) ]
137
+ SetSegmentRegisters ( vmm_sys_util:: errno:: Error ) ,
83
138
}
84
139
85
140
/// Configures the segment registers and system page tables for a given CPU.
@@ -88,13 +143,28 @@ pub fn setup_regs(vcpu: &VcpuFd, boot_ip: u64) -> Result<()> {
88
143
///
89
144
/// * `mem` - The memory that will be passed to the guest.
90
145
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
91
- pub fn setup_sregs ( mem : & GuestMemoryMmap , vcpu : & VcpuFd ) -> Result < ( ) > {
92
- let mut sregs: kvm_sregs = vcpu. get_sregs ( ) . map_err ( Error :: GetStatusRegisters ) ?;
93
-
94
- configure_segments_and_sregs ( mem, & mut sregs) ?;
95
- setup_page_tables ( mem, & mut sregs) ?; // TODO(dgreid) - Can this be done once per system instead?
96
-
97
- vcpu. set_sregs ( & sregs) . map_err ( Error :: SetStatusRegisters )
146
+ ///
147
+ /// # Errors
148
+ ///
149
+ /// When:
150
+ /// - [`kvm_ioctls::ioctls::vcpu::VcpuFd::get_sregs`] errors.
151
+ /// - [`configure_segments_and_sregs`] errors.
152
+ /// - [`setup_page_tables`] errors
153
+ /// - [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_sregs`] errors.
154
+ pub fn setup_sregs (
155
+ mem : & GuestMemoryMmap ,
156
+ vcpu : & VcpuFd ,
157
+ ) -> std:: result:: Result < ( ) , SetupSegmentRegistersError > {
158
+ let mut sregs: kvm_sregs = vcpu
159
+ . get_sregs ( )
160
+ . map_err ( SetupSegmentRegistersError :: GetSegmentRegisters ) ?;
161
+
162
+ configure_segments_and_sregs ( mem, & mut sregs)
163
+ . map_err ( SetupSegmentRegistersError :: ConfigureSegmentsAndSegmentRegisters ) ?;
164
+ setup_page_tables ( mem, & mut sregs) . map_err ( SetupSegmentRegistersError :: SetupPageTables ) ?; // TODO(dgreid) - Can this be done once per system instead?
165
+
166
+ vcpu. set_sregs ( & sregs)
167
+ . map_err ( SetupSegmentRegistersError :: SetSegmentRegisters )
98
168
}
99
169
100
170
const BOOT_GDT_OFFSET : u64 = 0x500 ;
0 commit comments