Skip to content
Snippets Groups Projects
Commit cc3d517a authored by Glauber Costa's avatar Glauber Costa
Browse files

work around xen x2apic bug

The x2APIC specification says that reading from the X2APIC_ID MSR should return
the physical apic id of the current processor. However, the Xen implementation
(as of 4.2.2) is broken, and reads actually return old style xAPIC id. Even if
they fix it, we still have HVs deployed around that will return the wrong ID.
We can work around this by testing if the returned APIC id is in the form (id
<< 24), since in that case, the first 24 bits will all be zeroed. Then at least
we can get this working everywhere. This may pose a problem if we want to ever
support more than 1 << 24 vCPUs (or if any other HV has some random x2apic
ids), but that is highly unlikely anyway.
parent 5cb16020
No related branches found
No related tags found
No related merge requests found
#include "apic.hh" #include "apic.hh"
#include "msr.hh" #include "msr.hh"
#include "xen.hh"
#include <osv/percpu.hh> #include <osv/percpu.hh>
#include <cpuid.hh> #include <cpuid.hh>
#include <processor.hh> #include <processor.hh>
...@@ -118,7 +119,24 @@ void x2apic::write(apicreg reg, u32 value) ...@@ -118,7 +119,24 @@ void x2apic::write(apicreg reg, u32 value)
u32 x2apic::id() u32 x2apic::id()
{ {
return processor::rdmsr(msr::X2APIC_ID); u32 id = processor::rdmsr(msr::X2APIC_ID);
if (!is_xen())
return id;
// The x2APIC specification says that reading from the X2APIC_ID MSR should
// return the physical apic id of the current processor. However, the Xen
// implementation (as of 4.2.2) is broken, and reads actually return old
// style xAPIC id. Even if they fix it, we still have HVs deployed around
// that will return the wrong ID. We can work around this by testing if the
// returned APIC id is in the form (id << 24), since in that case, the
// first 24 bits will all be zeroed. Then at least we can get this working
// everywhere. This may pose a problem if we want to ever support more than
// 1 << 24 vCPUs (or if any other HV has some random x2apic ids), but that
// is highly unlikely anyway.
if (((id & 0xffffff) == 0) && ((id >> 24) != 0)) {
id = (id >> 24);
}
return id;
} }
apic_driver* create_apic_driver() apic_driver* create_apic_driver()
......
...@@ -12,8 +12,10 @@ ...@@ -12,8 +12,10 @@
extern char hypercall_page[]; extern char hypercall_page[];
extern uint8_t xen_features[]; extern uint8_t xen_features[];
extern struct start_info* xen_start_info; extern struct start_info* xen_start_info;
extern "C" shared_info_t *HYPERVISOR_shared_info;
#define XENPV_ALTERNATIVE(x, y) ALTERNATIVE((xen_start_info != nullptr), x, y) #define XENPV_ALTERNATIVE(x, y) ALTERNATIVE((xen_start_info != nullptr), x, y)
#define is_xen() (HYPERVISOR_shared_info != nullptr)
// We don't support 32 bit // We don't support 32 bit
struct xen_vcpu_info { struct xen_vcpu_info {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment