2222#include < hw/apic_revenant.hpp>
2323#include < hw/cpu.hpp>
2424#include < hw/pic.hpp>
25+ #include < kernel/cpuid.hpp>
2526#include < kernel/irq_manager.hpp>
2627#include < cstdio>
2728#include < debug>
@@ -104,7 +105,8 @@ namespace hw {
104105 }
105106
106107 // use KVMs paravirt EOI if supported
107- // kvm_pv_eoi_init();
108+ if (CPUID::kvm_feature (KVM_FEATURE_PV_EOI))
109+ kvm_pv_eoi_init ();
108110
109111 // subscribe to APIC-related interrupts
110112 setup_subs ();
@@ -210,14 +212,14 @@ namespace hw {
210212
211213 uint8_t APIC::get_isr ()
212214 {
213- for (uint8_t i = 0 ; i < 8 ; i++ )
215+ for (int i = 8 ; i >= 0 ; i-- )
214216 if (lapic.regs ->isr [i].reg )
215217 return 32 * i + __builtin_ffs (lapic.regs ->isr [i].reg ) - 1 ;
216218 return 255 ;
217219 }
218220 uint8_t APIC::get_irr ()
219221 {
220- for (uint8_t i = 0 ; i < 8 ; i++ )
222+ for (int i = 8 ; i >= 0 ; i-- )
221223 if (lapic.regs ->irr [i].reg )
222224 return 32 * i + __builtin_ffs (lapic.regs ->irr [i].reg ) - 1 ;
223225 return 255 ;
@@ -318,7 +320,6 @@ namespace hw {
318320// http://choon.net/forum/read.php?21,1123399
319321// https://www.kernel.org/doc/Documentation/virtual/kvm/cpuid.txt
320322
321- #define KVM_FEATURE_PV_EOI 6
322323#define KVM_MSR_ENABLED 1
323324#define MSR_KVM_PV_EOI_EN 0x4b564d04
324325#define KVM_PV_EOI_BIT 0
@@ -341,7 +342,7 @@ int __test_and_clear_bit(long nr, volatile unsigned long* addr)
341342static volatile unsigned long kvm_apic_eoi = KVM_PV_EOI_DISABLED;
342343void kvm_pv_eoi () {
343344
344- // printf("BEFOR: %#lx intr %u irr %u\n", kvm_apic_eoi, hw::APIC::get_isr(), hw::APIC::get_irr());
345+ printf (" BEFOR: %#lx intr %u irr %u\n " , kvm_apic_eoi, hw::APIC::get_isr (), hw::APIC::get_irr ());
345346 // fast EOI by KVM
346347 if (__test_and_clear_bit (KVM_PV_EOI_BIT, &kvm_apic_eoi)) {
347348 printf (" avoided\n " );
@@ -350,14 +351,18 @@ void kvm_pv_eoi() {
350351 // fallback to normal APIC EOI
351352 hw::lapic.regs ->eoi .reg = 0 ;
352353 // check after
353- // printf("AFTER: %#lx intr %u irr %u\n", kvm_apic_eoi, hw::APIC::get_isr(), hw::APIC::get_irr());
354+ printf (" AFTER: %#lx intr %u irr %u\n " , kvm_apic_eoi, hw::APIC::get_isr (), hw::APIC::get_irr ());
354355}
355356void kvm_pv_eoi_init () {
357+ printf (" * Enabling KVM paravirtual EOI\n " );
358+ // set new EOI handler
359+ current_eoi_mechanism = kvm_pv_eoi;
360+ // setup PV EOI using local variable
356361 kvm_apic_eoi = 0 ;
357362 auto pv_eoi = (uintptr_t ) &kvm_apic_eoi;
358- printf (" MSR %#x pv_eoi = %#x\n " , MSR_KVM_PV_EOI_EN, pv_eoi);
363+ printf (" MSR %#x pv_eoi = %#x\n " , MSR_KVM_PV_EOI_EN, pv_eoi);
359364 hw::CPU::write_msr (MSR_KVM_PV_EOI_EN, pv_eoi | KVM_MSR_ENABLED, 0 );
360- // set new EOI handler
361- current_eoi_mechanism = kvm_pv_eoi ;
362- kvm_apic_eoi = KVM_PV_EOI_ENABLED ;
365+ // verify that the feature was enabled
366+ auto res = hw::CPU::read_msr (MSR_KVM_PV_EOI_EN) ;
367+ assert (res == (pv_eoi | KVM_MSR_ENABLED)) ;
363368}
0 commit comments