55// Use of this source code is governed by a BSD-style license that can be
66// found in the THIRD-PARTY file.
77
8- use std:: mem;
8+ use std:: { fmt , mem} ;
99
1010use kvm_bindings:: { kvm_fpu, kvm_regs, kvm_sregs} ;
1111use kvm_ioctls:: VcpuFd ;
@@ -19,42 +19,76 @@ const PDPTE_START: u64 = 0xa000;
1919const PDE_START : u64 = 0xb000 ;
2020
2121/// Errors thrown while setting up x86_64 registers.
22- #[ derive( Debug ) ]
22+ #[ derive( Debug , thiserror :: Error ) ]
2323pub enum Error {
2424 /// Failed to get SREGs for this CPU.
25+ #[ error( "Failed to get SREGs for this CPU: {0}" ) ]
2526 GetStatusRegisters ( kvm_ioctls:: Error ) ,
2627 /// Failed to set base registers for this CPU.
28+ #[ error( "Failed to set base registers for this CPU: {0}" ) ]
2729 SetBaseRegisters ( kvm_ioctls:: Error ) ,
2830 /// Failed to configure the FPU.
31+ #[ error( "Failed to configure the FPU: {0}" ) ]
2932 SetFPURegisters ( kvm_ioctls:: Error ) ,
3033 /// Failed to set SREGs for this CPU.
34+ #[ error( "Failed to set SREGs for this CPU: {0}" ) ]
3135 SetStatusRegisters ( kvm_ioctls:: Error ) ,
3236 /// Writing the GDT to RAM failed.
37+ #[ error( "Writing the GDT to RAM failed." ) ]
3338 WriteGDT ,
3439 /// Writing the IDT to RAM failed.
40+ #[ error( "Writing the IDT to RAM failed" ) ]
3541 WriteIDT ,
3642 /// Writing PDPTE to RAM failed.
43+ #[ error( "WritePDPTEAddress" ) ]
3744 WritePDPTEAddress ,
3845 /// Writing PDE to RAM failed.
46+ #[ error( "WritePDEAddress" ) ]
3947 WritePDEAddress ,
4048 /// Writing PML4 to RAM failed.
49+ #[ error( "WritePML4Address" ) ]
4150 WritePML4Address ,
4251}
4352type Result < T > = std:: result:: Result < T , Error > ;
4453
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+
4564/// Configure Floating-Point Unit (FPU) registers for a given CPU.
4665///
4766/// # Arguments
4867///
4968/// * `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 > {
5174 let fpu: kvm_fpu = kvm_fpu {
5275 fcw : 0x37f ,
5376 mxcsr : 0x1f80 ,
5477 ..Default :: default ( )
5578 } ;
5679
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+ }
5892}
5993
6094/// Configure base registers for a given CPU.
@@ -63,7 +97,11 @@ pub fn setup_fpu(vcpu: &VcpuFd) -> Result<()> {
6397///
6498/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
6599/// * `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 > {
67105 let regs: kvm_regs = kvm_regs {
68106 rflags : 0x0000_0000_0000_0002u64 ,
69107 rip : boot_ip,
@@ -79,7 +117,24 @@ pub fn setup_regs(vcpu: &VcpuFd, boot_ip: u64) -> Result<()> {
79117 ..Default :: default ( )
80118 } ;
81119
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 ) ,
83138}
84139
85140/// 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<()> {
88143///
89144/// * `mem` - The memory that will be passed to the guest.
90145/// * `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 )
98168}
99169
100170const BOOT_GDT_OFFSET : u64 = 0x500 ;
0 commit comments