11use std:: cmp;
2- use std:: collections:: VecDeque ;
3- use std:: io;
42use std:: io:: Write ;
53use std:: mem:: { size_of, size_of_val} ;
64use std:: os:: unix:: io:: { AsRawFd , RawFd } ;
7- use std:: result;
8- use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
5+ use std:: sync:: atomic:: AtomicUsize ;
96use std:: sync:: { Arc , Mutex } ;
107
118use libc:: TIOCGWINSZ ;
129use utils:: eventfd:: EventFd ;
13- use vm_memory:: { ByteValued , Bytes , GuestMemory , GuestMemoryMmap } ;
10+ use vm_memory:: { ByteValued , Bytes , GuestMemoryMmap } ;
1411
15- use super :: super :: super :: legacy:: ReadableFd ;
1612use super :: super :: {
1713 ActivateError , ActivateResult , ConsoleError , DeviceState , Queue as VirtQueue , VirtioDevice ,
18- VIRTIO_MMIO_INT_CONFIG , VIRTIO_MMIO_INT_VRING ,
1914} ;
2015use super :: { defs, defs:: control_event, defs:: uapi} ;
2116use crate :: legacy:: Gic ;
2217use crate :: virtio:: console:: console_control:: {
2318 ConsoleControl , VirtioConsoleControl , VirtioConsoleResize ,
2419} ;
2520use crate :: virtio:: console:: defs:: NUM_PORTS ;
26- use crate :: Error as DeviceError ;
21+ use crate :: virtio:: console:: irq_signaler:: IRQSignaler ;
22+ use crate :: virtio:: console:: port:: Port ;
23+ use crate :: virtio:: PortDescription ;
2724
2825pub ( crate ) const RXQ_INDEX : usize = 0 ;
2926pub ( crate ) const TXQ_INDEX : usize = 1 ;
30-
3127pub ( crate ) const CONTROL_RXQ_INDEX : usize = 2 ;
3228pub ( crate ) const CONTROL_TXQ_INDEX : usize = 3 ;
3329
@@ -66,131 +62,79 @@ pub struct VirtioConsoleConfig {
6662unsafe impl ByteValued for VirtioConsoleConfig { }
6763
6864impl VirtioConsoleConfig {
69- pub fn new ( cols : u16 , rows : u16 ) -> Self {
65+ pub fn new ( cols : u16 , rows : u16 , max_nr_ports : u32 ) -> Self {
7066 VirtioConsoleConfig {
7167 cols,
7268 rows,
73- max_nr_ports : NUM_PORTS as u32 ,
69+ max_nr_ports,
7470 emerg_wr : 0u32 ,
7571 }
7672 }
7773}
7874
7975pub struct Console {
76+ pub ( crate ) device_state : DeviceState ,
77+ pub ( crate ) irq : IRQSignaler ,
78+ pub ( crate ) control : Arc < ConsoleControl > ,
79+ pub ( crate ) port : Port ,
80+
8081 pub ( crate ) queues : Vec < VirtQueue > ,
8182 pub ( crate ) queue_events : Vec < EventFd > ,
82- pub ( crate ) control : Arc < ConsoleControl > ,
83+
8384 pub ( crate ) avail_features : u64 ,
8485 pub ( crate ) acked_features : u64 ,
85- pub ( crate ) interrupt_status : Arc < AtomicUsize > ,
86- pub ( crate ) interrupt_evt : EventFd ,
86+
8787 pub ( crate ) activate_evt : EventFd ,
8888 pub ( crate ) sigwinch_evt : EventFd ,
89- pub ( crate ) device_state : DeviceState ,
90- pub ( crate ) in_buffer : VecDeque < u8 > ,
89+
9190 config : VirtioConsoleConfig ,
92- pub ( crate ) input : Box < dyn ReadableFd + Send > ,
93- output : Box < dyn io:: Write + Send > ,
94- configured : bool ,
95- pub ( crate ) interactive : bool ,
96- intc : Option < Arc < Mutex < Gic > > > ,
97- irq_line : Option < u32 > ,
9891}
9992
10093impl Console {
101- pub ( crate ) fn with_queues (
102- input : Box < dyn ReadableFd + Send > ,
103- output : Box < dyn io:: Write + Send > ,
104- queues : Vec < VirtQueue > ,
105- ) -> super :: Result < Console > {
94+ pub fn new ( port : PortDescription ) -> super :: Result < Console > {
95+ let queues: Vec < VirtQueue > = defs:: QUEUE_SIZES
96+ . iter ( )
97+ . map ( |& max_size| VirtQueue :: new ( max_size) )
98+ . collect ( ) ;
99+
106100 let mut queue_events = Vec :: new ( ) ;
107101 for _ in 0 ..queues. len ( ) {
108102 queue_events
109103 . push ( EventFd :: new ( utils:: eventfd:: EFD_NONBLOCK ) . map_err ( ConsoleError :: EventFd ) ?) ;
110104 }
111105
112106 let ( cols, rows) = get_win_size ( ) ;
113- let config = VirtioConsoleConfig :: new ( cols, rows) ;
107+ let config = VirtioConsoleConfig :: new ( cols, rows, NUM_PORTS as u32 ) ;
114108
115109 Ok ( Console {
110+ irq : IRQSignaler :: new ( ) ,
116111 control : ConsoleControl :: new ( ) ,
112+ port : Port :: new ( 0 , port) ,
117113 queues,
118114 queue_events,
119115 avail_features : AVAIL_FEATURES ,
120116 acked_features : 0 ,
121- interrupt_status : Arc :: new ( AtomicUsize :: new ( 0 ) ) ,
122- interrupt_evt : EventFd :: new ( utils:: eventfd:: EFD_NONBLOCK )
123- . map_err ( ConsoleError :: EventFd ) ?,
124117 activate_evt : EventFd :: new ( utils:: eventfd:: EFD_NONBLOCK )
125118 . map_err ( ConsoleError :: EventFd ) ?,
126119 sigwinch_evt : EventFd :: new ( utils:: eventfd:: EFD_NONBLOCK )
127120 . map_err ( ConsoleError :: EventFd ) ?,
128121 device_state : DeviceState :: Inactive ,
129- in_buffer : VecDeque :: new ( ) ,
130122 config,
131- input,
132- output,
133- configured : false ,
134- interactive : true ,
135- intc : None ,
136- irq_line : None ,
137123 } )
138124 }
139125
140- pub fn new (
141- input : Box < dyn ReadableFd + Send > ,
142- output : Box < dyn io:: Write + Send > ,
143- ) -> super :: Result < Console > {
144- let queues: Vec < VirtQueue > = defs:: QUEUE_SIZES
145- . iter ( )
146- . map ( |& max_size| VirtQueue :: new ( max_size) )
147- . collect ( ) ;
148- Self :: with_queues ( input, output, queues)
149- }
150-
151126 pub fn id ( & self ) -> & str {
152127 defs:: CONSOLE_DEV_ID
153128 }
154129
155130 pub fn set_intc ( & mut self , intc : Arc < Mutex < Gic > > ) {
156- self . intc = Some ( intc) ;
131+ self . irq . set_intc ( intc)
157132 }
158133
159134 pub fn get_sigwinch_fd ( & self ) -> RawFd {
160135 self . sigwinch_evt . as_raw_fd ( )
161136 }
162137
163- pub fn set_interactive ( & mut self , interactive : bool ) {
164- self . interactive = interactive;
165- }
166-
167- /// Signal the guest driver that we've used some virtio buffers that it had previously made
168- /// available.
169- pub fn signal_used_queue ( & self ) -> result:: Result < ( ) , DeviceError > {
170- debug ! ( "console: raising IRQ" ) ;
171- self . interrupt_status
172- . fetch_or ( VIRTIO_MMIO_INT_VRING as usize , Ordering :: SeqCst ) ;
173- if let Some ( intc) = & self . intc {
174- intc. lock ( ) . unwrap ( ) . set_irq ( self . irq_line . unwrap ( ) ) ;
175- Ok ( ( ) )
176- } else {
177- self . interrupt_evt . write ( 1 ) . map_err ( |e| {
178- error ! ( "Failed to signal used queue: {:?}" , e) ;
179- DeviceError :: FailedSignalingUsedQueue ( e)
180- } )
181- }
182- }
183-
184- pub fn signal_config_update ( & self ) -> result:: Result < ( ) , DeviceError > {
185- debug ! ( "console: raising IRQ for config update" ) ;
186- self . interrupt_status
187- . fetch_or ( VIRTIO_MMIO_INT_CONFIG as usize , Ordering :: SeqCst ) ;
188- self . interrupt_evt . write ( 1 ) . map_err ( |e| {
189- error ! ( "Failed to signal used queue: {:?}" , e) ;
190- DeviceError :: FailedSignalingUsedQueue ( e)
191- } )
192- }
193-
194138 pub fn update_console_size ( & mut self , cols : u16 , rows : u16 ) {
195139 log:: debug!( "update_console_size: {} {}" , cols, rows) ;
196140 // Note that we currently only support resizing on the first/main console
@@ -229,15 +173,16 @@ impl Console {
229173 }
230174
231175 pub ( crate ) fn process_control_tx ( & mut self ) -> bool {
232- let mem = match self . device_state {
233- DeviceState :: Activated ( ref mem) => mem,
234- // This should never happen, it's been already validated in the event handler.
235- DeviceState :: Inactive => unreachable ! ( ) ,
176+ log:: trace!( "process_control_tx" ) ;
177+ let DeviceState :: Activated ( ref mem) = self . device_state else {
178+ unreachable ! ( )
236179 } ;
237180
238181 let tx_queue = & mut self . queues [ CONTROL_TXQ_INDEX ] ;
239182 let mut raise_irq = false ;
240183
184+ let mut start_port = false ;
185+
241186 while let Some ( head) = tx_queue. pop ( mem) {
242187 raise_irq = true ;
243188
@@ -268,9 +213,7 @@ impl Console {
268213 log:: error!( "Port initialization failed: {:?}" , cmd) ;
269214 continue ;
270215 }
271- if cmd. id == 0 {
272- self . control . mark_console_port ( mem, 0 ) ;
273- }
216+ self . control . mark_console_port ( mem, cmd. id ) ;
274217 }
275218 control_event:: VIRTIO_CONSOLE_PORT_OPEN => {
276219 let opened = match cmd. value {
@@ -290,76 +233,25 @@ impl Console {
290233 log:: debug!( "Guest closed port {}" , cmd. id) ;
291234 continue ;
292235 }
236+
237+ start_port = true ;
293238 }
294239 _ => log:: warn!( "Unknown console control event {:x}" , cmd. event) ,
295240 }
296241 }
297242
298- raise_irq
299- }
300-
301- pub ( crate ) fn process_rx ( & mut self ) -> bool {
302- //debug!("console: RXQ queue event");
303- let mem = match self . device_state {
304- DeviceState :: Activated ( ref mem) => mem,
305- // This should never happen, it's been already validated in the event handler.
306- DeviceState :: Inactive => unreachable ! ( ) ,
307- } ;
308-
309- if self . in_buffer . is_empty ( ) {
310- return false ;
311- }
312-
313- let queue = & mut self . queues [ RXQ_INDEX ] ;
314- let mut used_any = false ;
315- while let Some ( head) = queue. pop ( mem) {
316- let len = cmp:: min ( head. len , self . in_buffer . len ( ) as u32 ) ;
317- let source_slice = self . in_buffer . drain ( ..len as usize ) . collect :: < Vec < u8 > > ( ) ;
318- if let Err ( e) = mem. write_slice ( & source_slice[ ..] , head. addr ) {
319- error ! ( "Failed to write slice: {:?}" , e) ;
320- queue. go_to_previous_position ( ) ;
321- break ;
322- }
323-
324- queue. add_used ( mem, head. index , len) ;
325- used_any = true ;
326-
327- if self . in_buffer . is_empty ( ) {
328- break ;
329- }
330- }
331-
332- used_any
333- }
334-
335- pub ( crate ) fn process_tx ( & mut self ) -> bool {
336- //debug!("console: TXQ queue event");
337- let mem = match self . device_state {
338- DeviceState :: Activated ( ref mem) => mem,
339- // This should never happen, it's been already validated in the event handler.
340- DeviceState :: Inactive => unreachable ! ( ) ,
341- } ;
342-
343- // This won't be needed once we support multiport
344- if !self . configured {
345- self . configured = true ;
346- self . signal_config_update ( ) . unwrap ( ) ;
347- }
348-
349- let queue = & mut self . queues [ TXQ_INDEX ] ;
350- let mut used_any = false ;
351- while let Some ( head) = queue. pop ( mem) {
352- let mut buf = vec ! [ 0 ; head. len as usize ] ;
353- mem. write_volatile_to ( head. addr , & mut buf, head. len as usize )
354- . unwrap ( ) ;
355- self . output . write_all ( & buf) . unwrap ( ) ;
356- self . output . flush ( ) . unwrap ( ) ;
357-
358- queue. add_used ( mem, head. index , head. len ) ;
359- used_any = true ;
243+ if start_port {
244+ log:: trace!( "Starting port" ) ;
245+ self . port . start (
246+ mem. clone ( ) ,
247+ self . queues [ RXQ_INDEX ] . clone ( ) ,
248+ self . queues [ TXQ_INDEX ] . clone ( ) ,
249+ self . irq . clone ( ) ,
250+ self . control . clone ( ) ,
251+ ) ;
360252 }
361253
362- used_any
254+ raise_irq
363255 }
364256}
365257
@@ -393,15 +285,15 @@ impl VirtioDevice for Console {
393285 }
394286
395287 fn interrupt_evt ( & self ) -> & EventFd {
396- & self . interrupt_evt
288+ self . irq . interrupt_evt ( )
397289 }
398290
399291 fn interrupt_status ( & self ) -> Arc < AtomicUsize > {
400- self . interrupt_status . clone ( )
292+ self . irq . interrupt_status ( )
401293 }
402294
403295 fn set_irq_line ( & mut self , irq : u32 ) {
404- self . irq_line = Some ( irq) ;
296+ self . irq . set_irq_line ( irq)
405297 }
406298
407299 fn read_config ( & self , offset : u64 , mut data : & mut [ u8 ] ) {
@@ -427,17 +319,8 @@ impl VirtioDevice for Console {
427319 }
428320
429321 fn activate ( & mut self , mem : GuestMemoryMmap ) -> ActivateResult {
430- if self . queues . len ( ) != defs:: NUM_QUEUES {
431- error ! (
432- "Cannot perform activate. Expected {} queue(s), got {}" ,
433- defs:: NUM_QUEUES ,
434- self . queues. len( )
435- ) ;
436- return Err ( ActivateError :: BadActivate ) ;
437- }
438-
439322 if self . activate_evt . write ( 1 ) . is_err ( ) {
440- error ! ( "Cannot write to activate_evt" , ) ;
323+ error ! ( "Cannot write to activate_evt" ) ;
441324 return Err ( ActivateError :: BadActivate ) ;
442325 }
443326
0 commit comments