1
0

x86_64.rs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // Copyright 2022 The ChromiumOS Authors
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #![cfg(target_arch = "x86_64")]
  5. use devices::IrqChipX86_64;
  6. use devices::Routes;
  7. use hypervisor::IrqRoute;
  8. use hypervisor::IrqSource;
  9. use hypervisor::IrqSourceChip;
  10. use hypervisor::PicSelect;
  11. #[allow(unused)]
  12. pub fn test_get_pic(mut chip: impl IrqChipX86_64) {
  13. let state = chip
  14. .get_pic_state(PicSelect::Primary)
  15. .expect("could not get pic state");
  16. // Default is that no irq lines are asserted
  17. assert_eq!(state.irr, 0);
  18. // Assert Irq Line 0
  19. chip.service_irq(0, true).expect("could not service irq");
  20. let state = chip
  21. .get_pic_state(PicSelect::Primary)
  22. .expect("could not get pic state");
  23. // Bit 0 should now be 1
  24. assert_eq!(state.irr, 1);
  25. }
  26. pub fn test_set_pic(mut chip: impl IrqChipX86_64) {
  27. let mut state = chip
  28. .get_pic_state(PicSelect::Primary)
  29. .expect("could not get pic state");
  30. // set bits 0 and 1
  31. state.irr = 3;
  32. chip.set_pic_state(PicSelect::Primary, &state)
  33. .expect("could not set the pic state");
  34. let state = chip
  35. .get_pic_state(PicSelect::Primary)
  36. .expect("could not get pic state");
  37. // Bits 1 and 0 should now be 1
  38. assert_eq!(state.irr, 3);
  39. }
  40. pub fn test_get_ioapic(mut chip: impl IrqChipX86_64) {
  41. let state = chip.get_ioapic_state().expect("could not get ioapic state");
  42. // Default is that no irq lines are asserted
  43. assert_eq!(state.current_interrupt_level_bitmap, 0);
  44. // Default routing entries has routes 0..24 routed to vectors 0..24
  45. for i in 0..24 {
  46. // when the ioapic is reset by kvm, it defaults to all zeroes except the
  47. // interrupt mask is set to 1, which is bit 16
  48. assert_eq!(state.redirect_table[i].get(0, 64), 1 << 16);
  49. }
  50. // Assert Irq Line 1
  51. chip.service_irq(1, true).expect("could not set irq line");
  52. let state = chip.get_ioapic_state().expect("could not get ioapic state");
  53. // Bit 1 should now be 1
  54. assert_eq!(state.current_interrupt_level_bitmap, 2);
  55. }
  56. pub fn test_set_ioapic(mut chip: impl IrqChipX86_64) {
  57. let mut state = chip.get_ioapic_state().expect("could not get ioapic state");
  58. // set a vector in the redirect table
  59. state.redirect_table[2].set_vector(15);
  60. // set the irq line status on that entry
  61. state.current_interrupt_level_bitmap = 4;
  62. chip.set_ioapic_state(&state)
  63. .expect("could not set the ioapic state");
  64. let state = chip.get_ioapic_state().expect("could not get ioapic state");
  65. // verify that get_ioapic_state returns what we set
  66. assert_eq!(state.redirect_table[2].get_vector(), 15);
  67. assert_eq!(state.current_interrupt_level_bitmap, 4);
  68. }
  69. pub fn test_get_pit(chip: impl IrqChipX86_64) {
  70. let state = chip.get_pit().expect("failed to get pit state");
  71. assert_eq!(state.flags, 0);
  72. // assert reset state of pit
  73. for i in 0..3 {
  74. // initial count of 0 sets it to 0x10000;
  75. assert_eq!(state.channels[i].count, 0x10000);
  76. }
  77. }
  78. pub fn test_set_pit(mut chip: impl IrqChipX86_64) {
  79. let mut state = chip.get_pit().expect("failed to get pit state");
  80. // set some values
  81. state.channels[0].count = 500;
  82. state.channels[0].mode = 1;
  83. // Setting the pit should initialize the one-shot timer
  84. chip.set_pit(&state).expect("failed to set pit state");
  85. let state = chip.get_pit().expect("failed to get pit state");
  86. // check the values we set
  87. assert_eq!(state.channels[0].count, 500);
  88. assert_eq!(state.channels[0].mode, 1);
  89. }
  90. #[allow(unused)]
  91. pub fn test_get_lapic(chip: impl IrqChipX86_64) {
  92. let state = chip.get_lapic_state(0).expect("failed to get lapic state");
  93. // Checking some APIC reg defaults for KVM:
  94. // DFR default is 0xffffffff
  95. assert_eq!(state.regs[0xe], 0xffffffff);
  96. // SPIV default is 0xff
  97. assert_eq!(state.regs[0xf], 0xff);
  98. }
  99. #[allow(unused)]
  100. pub fn test_set_lapic(mut chip: impl IrqChipX86_64) {
  101. // Get default state
  102. let mut state = chip.get_lapic_state(0).expect("failed to get lapic state");
  103. // ESR should start out as 0
  104. assert_eq!(state.regs[8], 0);
  105. // Set a value in the ESR
  106. state.regs[8] = 1 << 8;
  107. chip.set_lapic_state(0, &state)
  108. .expect("failed to set lapic state");
  109. // check that new ESR value stuck
  110. let state = chip.get_lapic_state(0).expect("failed to get lapic state");
  111. assert_eq!(state.regs[8], 1 << 8);
  112. }
  113. /// Helper function for checking the pic interrupt status
  114. fn check_pic_interrupts(chip: &impl IrqChipX86_64, select: PicSelect, value: u8) {
  115. let state = chip
  116. .get_pic_state(select)
  117. .expect("could not get ioapic state");
  118. assert_eq!(state.irr, value);
  119. }
  120. /// Helper function for checking the ioapic interrupt status
  121. fn check_ioapic_interrupts(chip: &impl IrqChipX86_64, value: u32) {
  122. let state = chip.get_ioapic_state().expect("could not get ioapic state");
  123. // since the irq route goes nowhere the bitmap should still be 0
  124. assert_eq!(state.current_interrupt_level_bitmap, value);
  125. }
  126. pub fn test_route_irq(mut chip: impl IrqChipX86_64) {
  127. // clear out irq routes
  128. chip.set_irq_routes(&[])
  129. .expect("failed to set empty irq routes");
  130. // assert Irq Line 1
  131. chip.service_irq(1, true).expect("could not set irq line");
  132. // no pic or ioapic interrupts should be asserted
  133. check_pic_interrupts(&chip, PicSelect::Primary, 0);
  134. check_ioapic_interrupts(&chip, 0);
  135. // now we route gsi 1 to pin 3 of the ioapic and pin 6 of the primary pic
  136. chip.route_irq(IrqRoute {
  137. gsi: 1,
  138. source: IrqSource::Irqchip {
  139. chip: IrqSourceChip::Ioapic,
  140. pin: 3,
  141. },
  142. })
  143. .expect("failed to assert irq route");
  144. // re-assert Irq Line 1
  145. chip.service_irq(1, true).expect("could not set irq line");
  146. // no pic line should be asserted, ioapic pin 3 should be asserted
  147. check_pic_interrupts(&chip, PicSelect::Primary, 0);
  148. check_ioapic_interrupts(&chip, 1 << 3);
  149. // de-assert Irq Line 1
  150. chip.service_irq(1, false).expect("could not set irq line");
  151. // no pic or ioapic interrupts should be asserted
  152. check_pic_interrupts(&chip, PicSelect::Primary, 0);
  153. check_ioapic_interrupts(&chip, 0);
  154. // add pic route
  155. chip.route_irq(IrqRoute {
  156. gsi: 2,
  157. source: IrqSource::Irqchip {
  158. chip: IrqSourceChip::PicPrimary,
  159. pin: 6,
  160. },
  161. })
  162. .expect("failed to route irq");
  163. // re-assert Irq Line 1, it should still affect only the ioapic
  164. chip.service_irq(1, true).expect("could not set irq line");
  165. // no pic line should be asserted, ioapic pin 3 should be asserted
  166. check_pic_interrupts(&chip, PicSelect::Primary, 0);
  167. check_ioapic_interrupts(&chip, 1 << 3);
  168. // assert Irq Line 2
  169. chip.service_irq(2, true).expect("could not set irq line");
  170. // pic pin 6 should be asserted, ioapic pin 3 should be asserted
  171. check_pic_interrupts(&chip, PicSelect::Primary, 1 << 6);
  172. check_ioapic_interrupts(&chip, 1 << 3);
  173. }
  174. #[test]
  175. fn add_routes() {
  176. let ioapic_pins = hypervisor::NUM_IOAPIC_PINS;
  177. let mut r = Routes::new();
  178. r.replace_all(&Routes::default_pic_ioapic_routes(ioapic_pins))
  179. .unwrap();
  180. assert_eq!(r[0].len(), 2);
  181. assert_eq!(r[ioapic_pins - 1].len(), 1);
  182. r.add(IrqRoute {
  183. gsi: ioapic_pins as u32 - 1,
  184. source: IrqSource::Irqchip {
  185. chip: IrqSourceChip::Ioapic,
  186. pin: 3,
  187. },
  188. })
  189. .unwrap();
  190. assert_eq!(r[ioapic_pins - 1].len(), 1);
  191. r.add(IrqRoute {
  192. gsi: ioapic_pins as u32 - 1,
  193. source: IrqSource::Irqchip {
  194. chip: IrqSourceChip::PicPrimary,
  195. pin: 3,
  196. },
  197. })
  198. .unwrap();
  199. assert_eq!(r[ioapic_pins - 1].len(), 2);
  200. assert!(r
  201. .add(IrqRoute {
  202. gsi: ioapic_pins as u32 - 1,
  203. source: IrqSource::Msi {
  204. address: 0,
  205. data: 0
  206. },
  207. })
  208. .is_err(),);
  209. assert_eq!(r[ioapic_pins - 1].len(), 2);
  210. assert_eq!(r[ioapic_pins].len(), 0);
  211. r.add(IrqRoute {
  212. gsi: ioapic_pins as u32,
  213. source: IrqSource::Msi {
  214. address: 0,
  215. data: 0,
  216. },
  217. })
  218. .unwrap();
  219. assert_eq!(r[ioapic_pins].len(), 1);
  220. assert!(r
  221. .add(IrqRoute {
  222. gsi: ioapic_pins as u32,
  223. source: IrqSource::Irqchip {
  224. chip: IrqSourceChip::Ioapic,
  225. pin: 3
  226. },
  227. })
  228. .is_err(),);
  229. assert_eq!(r[ioapic_pins].len(), 1);
  230. assert_eq!(r[500].len(), 0);
  231. }