Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49df6397 authored by Steve Rutherford's avatar Steve Rutherford Committed by Paolo Bonzini
Browse files

KVM: x86: Split the APIC from the rest of IRQCHIP.



First patch in a series which enables the relocation of the
PIC/IOAPIC to userspace.

Adds capability KVM_CAP_SPLIT_IRQCHIP;

KVM_CAP_SPLIT_IRQCHIP enables the construction of LAPICs without the
rest of the irqchip.

Compile tested for x86.

Signed-off-by: default avatarSteve Rutherford <srutherford@google.com>
Suggested-by: default avatarAndrew Honig <ahonig@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 4ca7dd8c
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -3627,6 +3627,23 @@ struct {

KVM handlers should exit to userspace with rc = -EREMOTE.

7.5 KVM_CAP_SPLIT_IRQCHIP

Architectures: x86
Parameters: None
Returns: 0 on success, -1 on error

Create a local apic for each processor in the kernel. This can be used
instead of KVM_CREATE_IRQCHIP if the userspace VMM wishes to emulate the
IOAPIC and PIC (and also the PIT, even though this has to be enabled
separately).

This supersedes KVM_CREATE_IRQCHIP, creating only local APICs, but no in kernel
IOAPIC or PIC. This also enables in kernel routing of interrupt requests.

Fails if VCPU has already been created, or if the irqchip is already in the
kernel (i.e. KVM_CREATE_IRQCHIP has already been called).


8. Other capabilities.
----------------------
+2 −0
Original line number Diff line number Diff line
@@ -684,6 +684,8 @@ struct kvm_arch {
	u32 bsp_vcpu_id;

	u64 disabled_quirks;

	bool irqchip_split;
};

struct kvm_vm_stat {
+3 −1
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include <linux/kvm_host.h>
#include <linux/slab.h>

#include "ioapic.h"
#include "irq.h"
#include "i8254.h"
#include "x86.h"
@@ -333,7 +334,8 @@ static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)
	struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
	s64 interval;

	if (!irqchip_in_kernel(kvm) || ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)
	if (!ioapic_in_kernel(kvm) ||
	    ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)
		return;

	interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
+8 −0
Original line number Diff line number Diff line
@@ -97,6 +97,14 @@ static inline struct kvm_ioapic *ioapic_irqchip(struct kvm *kvm)
	return kvm->arch.vioapic;
}

static inline int ioapic_in_kernel(struct kvm *kvm)
{
	int ret;

	ret = (ioapic_irqchip(kvm) != NULL);
	return ret;
}

void kvm_rtc_eoi_tracking_restore_one(struct kvm_vcpu *vcpu);
bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
		int short_hand, unsigned int dest, int dest_mode);
+10 −1
Original line number Diff line number Diff line
@@ -83,13 +83,22 @@ static inline struct kvm_pic *pic_irqchip(struct kvm *kvm)
	return kvm->arch.vpic;
}

static inline int irqchip_split(struct kvm *kvm)
{
	return kvm->arch.irqchip_split;
}

static inline int irqchip_in_kernel(struct kvm *kvm)
{
	struct kvm_pic *vpic = pic_irqchip(kvm);
	bool ret;

	ret = (vpic != NULL);
	ret |= irqchip_split(kvm);

	/* Read vpic before kvm->irq_routing.  */
	smp_rmb();
	return vpic != NULL;
	return ret;
}

static inline int lapic_in_kernel(struct kvm_vcpu *vcpu)
Loading