@@ -57,6 +57,27 @@ fn frequency() -> u64 {
5757 TIME_SRC . frequency ( )
5858}
5959
60+ /// An interrupt to be delivered by a timer
61+ #[ derive( Clone ) ]
62+ pub enum TimerInterruptType {
63+ /// An interrupt to be delivered to the core that is running the timer.
64+ /// For example, when virtualizing the guest local apic timer, the
65+ /// generated interrupt is _not_ a guest GSI, but a directly delivered
66+ /// interrupt.
67+ Direct {
68+ /// The interrupt vector to be delivered by the timer
69+ vector : u8 ,
70+
71+ /// The kind of interrupt to be delivered by the timer
72+ kind : vcpu:: InjectedInterruptType ,
73+ } ,
74+
75+ /// An interrupt to be delivered to the guest via a GSI.
76+ /// For example, any hardware timer external to the core will generate
77+ /// a GSI and be routed to a vector through the guest IO APIC
78+ GSI ( u32 ) ,
79+ }
80+
6081/// A point in time on the system in terms of the global system `TimeSource`
6182///
6283/// An `Instant` can be added/subtracted with a `Duration` to produce an
@@ -123,38 +144,33 @@ enum TimerMode {
123144pub struct ReadyTimer {
124145 duration : Duration ,
125146 mode : TimerMode ,
126-
127- // The interrupt vector to deliver to the guest when this timer
128- // expires.
129- // TODO: Not all timers represent interrupts to deliver to the guest,
130- // so we will need to make this more abstract.
131- vector : u8 ,
147+ kind : TimerInterruptType ,
132148}
133149
134150/// A started one-shot or periodic timer
135151pub struct RunningTimer {
136152 duration : Duration ,
137153 mode : TimerMode ,
138154 started : Instant ,
139- vector : u8 ,
155+ kind : TimerInterruptType ,
140156}
141157
142158impl ReadyTimer {
143159 /// Create a new one-shot timer.
144- pub fn one_shot ( duration : Duration , vector : u8 ) -> Self {
160+ pub fn one_shot ( duration : Duration , kind : TimerInterruptType ) -> Self {
145161 Self {
146- duration : duration ,
162+ duration,
147163 mode : TimerMode :: OneShot ,
148- vector : vector ,
164+ kind ,
149165 }
150166 }
151167
152168 /// Create a new periodic timer.
153- pub fn periodic ( period : Duration , vector : u8 ) -> Self {
169+ pub fn periodic ( period : Duration , kind : TimerInterruptType ) -> Self {
154170 Self {
155171 duration : period,
156172 mode : TimerMode :: Periodic ,
157- vector : vector ,
173+ kind ,
158174 }
159175 }
160176
@@ -164,7 +180,7 @@ impl ReadyTimer {
164180 duration : self . duration ,
165181 mode : self . mode ,
166182 started : now ( ) ,
167- vector : self . vector ,
183+ kind : self . kind ,
168184 }
169185 }
170186
@@ -183,7 +199,7 @@ impl RunningTimer {
183199 ReadyTimer {
184200 duration : self . duration ,
185201 mode : self . mode ,
186- vector : self . vector ,
202+ kind : self . kind ,
187203 }
188204 }
189205
@@ -273,7 +289,7 @@ impl TimerWheel {
273289 /// expired and will reset any periodic timers.
274290 pub fn expire_elapsed_timers (
275291 & mut self ,
276- ) -> Result < vec:: Vec < ( u8 , vcpu :: InjectedInterruptType ) > > {
292+ ) -> Result < vec:: Vec < TimerInterruptType > > {
277293 let mut interrupts = vec ! [ ] ;
278294 let elapsed_oneshots = self
279295 . timers
@@ -288,10 +304,7 @@ impl TimerWheel {
288304 . collect :: < vec:: Vec < _ > > ( ) ;
289305
290306 for id in elapsed_oneshots {
291- interrupts. push ( (
292- self . timers [ & id] . vector ,
293- vcpu:: InjectedInterruptType :: ExternalInterrupt ,
294- ) ) ;
307+ interrupts. push ( self . timers [ & id] . kind . clone ( ) ) ;
295308 self . timers . remove ( & id) ;
296309 }
297310
@@ -300,10 +313,7 @@ impl TimerWheel {
300313 . iter_mut ( )
301314 . filter ( |( _, timer) | timer. elapsed ( ) && timer. is_periodic ( ) )
302315 {
303- interrupts. push ( (
304- timer. vector ,
305- vcpu:: InjectedInterruptType :: ExternalInterrupt ,
306- ) ) ;
316+ interrupts. push ( timer. kind . clone ( ) ) ;
307317 timer. reset ( ) ;
308318 }
309319
@@ -315,8 +325,8 @@ impl TimerWheel {
315325 let soonest = self
316326 . timers
317327 . values ( )
318- . map ( |timer| ( timer. elapses_at ( ) , timer. vector ) )
319- . min ( ) ;
328+ . map ( |timer| ( timer. elapses_at ( ) , & timer. kind ) )
329+ . min_by ( | ( time1 , _ ) , ( time2 , _ ) | time1 . cmp ( time2 ) ) ;
320330
321331 // TODO: we should only actually reset this if the new time
322332 // is sooner than the last time we set
@@ -407,19 +417,19 @@ pub fn cancel_timer(id: &TimerId) -> Result<()> {
407417/// Set a one shot timer on this core
408418pub fn set_oneshot_timer (
409419 duration : core:: time:: Duration ,
410- vector : u8 ,
420+ kind : TimerInterruptType ,
411421) -> TimerId {
412422 let wheel = unsafe { get_timer_wheel_mut ( ) } ;
413- let timer = ReadyTimer :: one_shot ( duration, vector ) ;
423+ let timer = ReadyTimer :: one_shot ( duration, kind ) ;
414424 wheel. register_timer ( timer)
415425}
416426
417427/// Set a periodic timer on this core
418428pub fn set_periodic_timer (
419429 interval : core:: time:: Duration ,
420- vector : u8 ,
430+ kind : TimerInterruptType ,
421431) -> TimerId {
422432 let wheel = unsafe { get_timer_wheel_mut ( ) } ;
423- let timer = ReadyTimer :: periodic ( interval, vector ) ;
433+ let timer = ReadyTimer :: periodic ( interval, kind ) ;
424434 wheel. register_timer ( timer)
425435}
0 commit comments