7
7
8
8
use std:: convert:: Infallible ;
9
9
use std:: fmt:: Debug ;
10
+ use std:: os:: unix:: prelude:: OpenOptionsExt ;
11
+ use std:: path:: PathBuf ;
10
12
use std:: sync:: { Arc , Mutex } ;
11
13
12
14
use acpi:: ACPIDeviceManager ;
@@ -125,13 +127,25 @@ impl DeviceManager {
125
127
/// Sets up the serial device.
126
128
fn setup_serial_device (
127
129
event_manager : & mut EventManager ,
130
+ output : Option < & PathBuf > ,
128
131
) -> Result < Arc < Mutex < SerialDevice > > , std:: io:: Error > {
129
- Self :: set_stdout_nonblocking ( ) ;
132
+ let ( serial_in, serial_out) = match output {
133
+ Some ( ref path) => (
134
+ None ,
135
+ std:: fs:: OpenOptions :: new ( )
136
+ . custom_flags ( libc:: O_NONBLOCK )
137
+ . write ( true )
138
+ . open ( path)
139
+ . map ( SerialOut :: File ) ?,
140
+ ) ,
141
+ None => {
142
+ Self :: set_stdout_nonblocking ( ) ;
143
+
144
+ ( Some ( std:: io:: stdin ( ) ) , SerialOut :: Stdout ( std:: io:: stdout ( ) ) )
145
+ }
146
+ } ;
130
147
131
- let serial = Arc :: new ( Mutex :: new ( SerialDevice :: new (
132
- Some ( std:: io:: stdin ( ) ) ,
133
- SerialOut :: Stdout ( std:: io:: stdout ( ) ) ,
134
- ) ?) ) ;
148
+ let serial = Arc :: new ( Mutex :: new ( SerialDevice :: new ( serial_in, serial_out) ?) ) ;
135
149
event_manager. add_subscriber ( serial. clone ( ) ) ;
136
150
Ok ( serial)
137
151
}
@@ -141,9 +155,10 @@ impl DeviceManager {
141
155
event_manager : & mut EventManager ,
142
156
vcpus_exit_evt : & EventFd ,
143
157
vm : & Vm ,
158
+ serial_output : Option < & PathBuf > ,
144
159
) -> Result < PortIODeviceManager , DeviceManagerCreateError > {
145
160
// Create serial device
146
- let serial = Self :: setup_serial_device ( event_manager) ?;
161
+ let serial = Self :: setup_serial_device ( event_manager, serial_output ) ?;
147
162
let reset_evt = vcpus_exit_evt
148
163
. try_clone ( )
149
164
. map_err ( DeviceManagerCreateError :: EventFd ) ?;
@@ -161,9 +176,11 @@ impl DeviceManager {
161
176
event_manager : & mut EventManager ,
162
177
vcpus_exit_evt : & EventFd ,
163
178
vm : & Vm ,
179
+ serial_output : Option < & PathBuf > ,
164
180
) -> Result < Self , DeviceManagerCreateError > {
165
181
#[ cfg( target_arch = "x86_64" ) ]
166
- let legacy_devices = Self :: create_legacy_devices ( event_manager, vcpus_exit_evt, vm) ?;
182
+ let legacy_devices =
183
+ Self :: create_legacy_devices ( event_manager, vcpus_exit_evt, vm, serial_output) ?;
167
184
168
185
Ok ( DeviceManager {
169
186
mmio_devices : MMIODeviceManager :: new ( ) ,
@@ -243,6 +260,7 @@ impl DeviceManager {
243
260
vm : & Vm ,
244
261
event_manager : & mut EventManager ,
245
262
cmdline : & mut Cmdline ,
263
+ serial_out_path : Option < & PathBuf > ,
246
264
) -> Result < ( ) , AttachDeviceError > {
247
265
// Serial device setup.
248
266
let cmdline_contains_console = cmdline
@@ -253,7 +271,7 @@ impl DeviceManager {
253
271
. contains ( "console=" ) ;
254
272
255
273
if cmdline_contains_console {
256
- let serial = Self :: setup_serial_device ( event_manager) ?;
274
+ let serial = Self :: setup_serial_device ( event_manager, serial_out_path ) ?;
257
275
self . mmio_devices . register_mmio_serial ( vm, serial, None ) ?;
258
276
self . mmio_devices . add_mmio_serial_to_cmdline ( cmdline) ?;
259
277
}
@@ -451,6 +469,7 @@ impl<'a> Persist<'a> for DeviceManager {
451
469
constructor_args. event_manager ,
452
470
constructor_args. vcpus_exit_evt ,
453
471
constructor_args. vm ,
472
+ constructor_args. vm_resources . serial_out_path . as_ref ( ) ,
454
473
) ?;
455
474
456
475
// Restore MMIO devices
@@ -580,15 +599,15 @@ pub(crate) mod tests {
580
599
let mut cmdline = Cmdline :: new ( 4096 ) . unwrap ( ) ;
581
600
let mut event_manager = EventManager :: new ( ) . unwrap ( ) ;
582
601
vmm. device_manager
583
- . attach_legacy_devices_aarch64 ( & vmm. vm , & mut event_manager, & mut cmdline)
602
+ . attach_legacy_devices_aarch64 ( & vmm. vm , & mut event_manager, & mut cmdline, None )
584
603
. unwrap ( ) ;
585
604
assert ! ( vmm. device_manager. mmio_devices. rtc. is_some( ) ) ;
586
605
assert ! ( vmm. device_manager. mmio_devices. serial. is_none( ) ) ;
587
606
588
607
let mut vmm = default_vmm ( ) ;
589
608
cmdline. insert ( "console" , "/dev/blah" ) . unwrap ( ) ;
590
609
vmm. device_manager
591
- . attach_legacy_devices_aarch64 ( & vmm. vm , & mut event_manager, & mut cmdline)
610
+ . attach_legacy_devices_aarch64 ( & vmm. vm , & mut event_manager, & mut cmdline, None )
592
611
. unwrap ( ) ;
593
612
assert ! ( vmm. device_manager. mmio_devices. rtc. is_some( ) ) ;
594
613
assert ! ( vmm. device_manager. mmio_devices. serial. is_some( ) ) ;
0 commit comments