Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

X2apic #288

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion Documentation/virtual/kvm/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1461,6 +1461,7 @@ struct kvm_irq_routing_entry {
#define KVM_IRQ_ROUTING_MSI 2
#define KVM_IRQ_ROUTING_S390_ADAPTER 3
#define KVM_IRQ_ROUTING_HV_SINT 4
#define KVM_IRQ_ROUTING_MSI_X2APIC 5

No flags are specified so far, the corresponding field must be set to zero.

Expand Down Expand Up @@ -1489,6 +1490,11 @@ struct kvm_irq_routing_hv_sint {
__u32 sint;
};

KVM_IRQ_ROUTING_MSI_X2APIC can be used if KVM_CAP_MSI_X2APIC is present.
The entry uses struct kvm_irq_routing_msi and stores APIC ID bits 8-31 in
address_hi bits 8-31.


4.53 KVM_ASSIGN_SET_MSIX_NR (deprecated)

Capability: none
Expand Down Expand Up @@ -1577,6 +1583,11 @@ struct kvm_lapic_state {
Reads the Local APIC registers and copies them into the input argument. The
data format and layout are the same as documented in the architecture manual.

Note that the APIC ID is stored in APIC_ID register in big endian format.
This makes no difference for xAPIC APIC ID, which is still in the top 8 bits,
but x2APIC ID needs to be byteswapped. The reason is compatibility with KVM's
definition of x2APIC. (The hardware stores x2APIC ID as little endian.)


4.58 KVM_SET_LAPIC

Expand All @@ -1594,6 +1605,7 @@ struct kvm_lapic_state {
Copies the input argument into the Local APIC registers. The data format
and layout are the same as documented in the architecture manual.

See the note about APIC_ID register in KVM_GET_LAPIC.

4.59 KVM_IOEVENTFD

Expand Down Expand Up @@ -2166,7 +2178,10 @@ struct kvm_msi {
__u8 pad[16];
};

No flags are defined so far. The corresponding field must be 0.
Valid flags are 0 and bitwise OR of any following:
* KVM_SIGNAL_MSI_X2APIC
- valid with capability KVM_CAP_MSI_X2APIC
- address_hi bits 8-31 contain APIC ID bits 8-31


4.71 KVM_CREATE_PIT2
Expand Down
11 changes: 7 additions & 4 deletions arch/x86/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#include <asm/asm.h>
#include <asm/kvm_page_track.h>

#define KVM_MAX_VCPUS 255
#define KVM_MAX_VCPUS 288
#define KVM_SOFT_MAX_VCPUS 160
#define KVM_USER_MEM_SLOTS 509
/* memory slots that are not exposed to userspace */
Expand Down Expand Up @@ -682,9 +682,12 @@ struct kvm_arch_memory_slot {
struct kvm_apic_map {
struct rcu_head rcu;
u8 mode;
struct kvm_lapic *phys_map[256];
/* first index is cluster id second is cpu id in a cluster */
struct kvm_lapic *logical_map[16][16];
u32 size;
union {
struct kvm_lapic *xapic_flat_map[8];
struct kvm_lapic *xapic_cluster_map[16][4];
};
struct kvm_lapic *phys_map[];
};

/* Hyper-V emulation context */
Expand Down
28 changes: 14 additions & 14 deletions arch/x86/kvm/irq_comm.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ void kvm_set_msi_irq(struct kvm_kernel_irq_routing_entry *e,

irq->dest_id = (e->msi.address_lo &
MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
if (e->type == KVM_IRQ_ROUTING_MSI_X2APIC)
irq->dest_id |= MSI_ADDR_EXT_DEST_ID(e->msi.address_hi);
irq->vector = (e->msi.data &
MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
irq->dest_mode = (1 << MSI_ADDR_DEST_MODE_SHIFT) & e->msi.address_lo;
Expand Down Expand Up @@ -150,7 +152,8 @@ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
struct kvm_lapic_irq irq;
int r;

if (unlikely(e->type != KVM_IRQ_ROUTING_MSI))
if (unlikely(e->type != KVM_IRQ_ROUTING_MSI &&
e->type != KVM_IRQ_ROUTING_MSI_X2APIC))
return -EWOULDBLOCK;

kvm_set_msi_irq(e, &irq);
Expand Down Expand Up @@ -281,6 +284,7 @@ int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
goto out;
break;
case KVM_IRQ_ROUTING_MSI:
case KVM_IRQ_ROUTING_MSI_X2APIC:
e->set = kvm_set_msi;
e->msi.address_lo = ue->u.msi.address_lo;
e->msi.address_hi = ue->u.msi.address_hi;
Expand Down Expand Up @@ -391,21 +395,17 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
kvm->arch.nr_reserved_ioapic_pins);
for (i = 0; i < nr_ioapic_pins; ++i) {
hlist_for_each_entry(entry, &table->map[i], link) {
u32 dest_id, dest_mode;
bool level;
struct kvm_lapic_irq irq;

if (entry->type != KVM_IRQ_ROUTING_MSI)
if (entry->type != KVM_IRQ_ROUTING_MSI &&
entry->type != KVM_IRQ_ROUTING_MSI_X2APIC)
continue;
dest_id = (entry->msi.address_lo >> 12) & 0xff;
dest_mode = (entry->msi.address_lo >> 2) & 0x1;
level = entry->msi.data & MSI_DATA_TRIGGER_LEVEL;
if (level && kvm_apic_match_dest(vcpu, NULL, 0,
dest_id, dest_mode)) {
u32 vector = entry->msi.data & 0xff;

__set_bit(vector,
ioapic_handled_vectors);
}

kvm_set_msi_irq(entry, &irq);

if (irq.level && kvm_apic_match_dest(vcpu, NULL, 0,
irq.dest_id, irq.dest_mode))
__set_bit(irq.vector, ioapic_handled_vectors);
}
}
srcu_read_unlock(&kvm->irq_srcu, idx);
Expand Down
Loading