Commit 88f6a504 authored by Zhang Yi's avatar Zhang Yi Committed by guzitao
Browse files

sw64: kvm: optimize external interrupts assignment for guest

Sunway inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I56WV8



--------------------------------

Target cpu for all external interrupts of guest os was assigned by
hypervisor. However, it's not a common solution and it will cause
system crash in cpu hotplug.

This patch optimizes the assignment policy. Target cpu and target
vector for MSI of guest are assigned by itself. Target cpu of other
external interrupts is bound to vCPU0 by hypervisor.

Signed-off-by: default avatarZhang Yi <zhangyi@wxiat.com>
Reviewed-by: default avatarHe Sheng <hesheng@wxiat.com>
Signed-off-by: default avatarGu Zitao <guzitao@wxiat.com>
parent ba044d2f
Loading
Loading
Loading
Loading
+66 −68
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include <linux/irqdomain.h>

#include <asm/irq_impl.h>
#include <asm/kvm_emulate.h>

static struct irq_domain *msi_default_domain;
static DEFINE_RAW_SPINLOCK(vector_lock);
@@ -12,19 +13,6 @@ DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
	[0 ... PERCPU_MSI_IRQS - 1] = 0,
};

struct sw64_msi_chip_data {
	spinlock_t cdata_lock;
	unsigned long msi_config;
	unsigned long rc_node;
	unsigned long rc_index;
	unsigned int msi_config_index;
	unsigned int dst_coreid;
	unsigned int vector;
	unsigned int prev_coreid;
	unsigned int prev_vector;
	bool move_in_progress;
};

static struct sw64_msi_chip_data *alloc_sw_msi_chip_data(struct irq_data *irq_data)
{
	struct sw64_msi_chip_data *data;
@@ -48,52 +36,59 @@ static void irq_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
	msg->data = chip_data->msi_config_index;
}

static bool find_free_core_vector(const struct cpumask *search_mask, int *found_coreid, int *found_vector)
bool find_free_cpu_vector(const struct cpumask *search_mask,
			  int *found_cpu, int *found_vector)
{
	int vector, coreid;
	bool found = false, find_once_global = false;
	int vector, max_vector, cpu;
	bool find_once_global = false;

	coreid = cpumask_first(search_mask);
	cpu = cpumask_first(search_mask);
try_again:
	for (vector = 0; vector < 256; vector++) {
		while (per_cpu(vector_irq, coreid)[vector]) {
			coreid = cpumask_next(coreid, search_mask);
			if (coreid >= nr_cpu_ids) {
	if (is_guest_or_emul()) {
		vector = IRQ_PENDING_MSI_VECTORS_SHIFT;
		max_vector = SWVM_IRQS;
	} else {
		vector = 0;
		max_vector = 256;
	}
	for (; vector < max_vector; vector++) {
		while (per_cpu(vector_irq, cpu)[vector]) {
			cpu = cpumask_next(cpu, search_mask);
			if (cpu >= nr_cpu_ids) {
				if (vector == 255) {
					if (find_once_global) {
						printk("No global free vector\n");
						return found;
						return false;
					}
					printk("No local free vector\n");
					search_mask = cpu_online_mask;
					coreid = cpumask_first(search_mask);
					cpu = cpumask_first(search_mask);
					find_once_global = true;
					goto try_again;
				}
				coreid = cpumask_first(search_mask);
				cpu = cpumask_first(search_mask);
				break;
			}
		}
		if (!per_cpu(vector_irq, coreid)[vector])
		if (!per_cpu(vector_irq, cpu)[vector])
			break;
	}

	found = true;
	*found_coreid = coreid;
	*found_cpu = cpu;
	*found_vector = vector;
	return found;
	return true;
}

static unsigned long set_piu_msi_config(struct pci_controller *hose, int found_coreid,
		int msiconf_index, int found_vector)
static unsigned long set_piu_msi_config(struct pci_controller *hose, int cpu,
		int msiconf_index, int vector)
{
	unsigned int reg;
	unsigned long msi_config;
	int phy_coreid;
	int phy_cpu;

	msi_config = (1UL << 62) | ((unsigned long)found_vector << 10);
	phy_coreid = cpu_to_rcid(found_coreid);
	msi_config |= ((phy_coreid >> 5) << 6) | (phy_coreid & 0x1f);
	msi_config = (1UL << 62) | ((unsigned long)vector << 10);
	phy_cpu = cpu_to_rcid(cpu);
	msi_config |= ((phy_cpu >> 5) << 6) | (phy_cpu & 0x1f);
	reg = MSICONFIG0 + (unsigned long)(msiconf_index << 7);
	write_piu_ior0(hose->node, hose->index, reg, msi_config);
	msi_config = read_piu_ior0(hose->node, hose->index, reg);
@@ -110,7 +105,7 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
	struct msi_desc *entry;
	struct cpumask searchmask;
	unsigned long flags, msi_config;
	int found_vector, found_coreid;
	int vector, cpu;

	/* Is this valid ? */
	if (cpumask_any_and(cpumask, cpu_online_mask) >= nr_cpu_ids)
@@ -125,14 +120,17 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
	if (!cdata)
		return -ENOMEM;

	/* If existing target coreid is already in the new mask, and is online then do nothing.*/
	if (cpu_online(cdata->dst_coreid) && cpumask_test_cpu(cdata->dst_coreid, cpumask))
	/*
	 * If existing target cpu is already in the new mask and is online
	 * then do nothing.
	 */
	if (cpu_online(cdata->dst_cpu) && cpumask_test_cpu(cdata->dst_cpu, cpumask))
		return IRQ_SET_MASK_OK;

	raw_spin_lock_irqsave(&vector_lock, flags);

	cpumask_and(&searchmask, cpumask, cpu_online_mask);
	if (!find_free_core_vector(&searchmask, &found_coreid, &found_vector)) {
	if (!find_free_cpu_vector(&searchmask, &cpu, &vector)) {
		raw_spin_unlock_irqrestore(&vector_lock, flags);
		return -ENOSPC;
	}
@@ -141,12 +139,12 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
	entry = irq_get_msi_desc(irqd->irq);
	hose = (struct pci_controller *)msi_desc_to_pci_sysdata(entry);
	spin_lock(&cdata->cdata_lock);
	per_cpu(vector_irq, found_coreid)[found_vector] = irqd->irq;
	msi_config = set_piu_msi_config(hose, found_coreid, cdata->msi_config_index, found_vector);
	per_cpu(vector_irq, cpu)[vector] = irqd->irq;
	msi_config = set_piu_msi_config(hose, cpu, cdata->msi_config_index, vector);
	cdata->prev_vector = cdata->vector;
	cdata->prev_coreid = cdata->dst_coreid;
	cdata->dst_coreid = found_coreid;
	cdata->vector = found_vector;
	cdata->prev_cpu = cdata->dst_cpu;
	cdata->dst_cpu = cpu;
	cdata->vector = vector;
	cdata->msi_config = msi_config;
	cdata->move_in_progress = true;
	spin_unlock(&cdata->cdata_lock);
@@ -178,8 +176,8 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs,
	const struct cpumask *mask;
	struct cpumask searchmask;
	struct sw64_msi_chip_data *cdata;
	int msiconf_index, coreid, node;
	int i, found_vector, found_coreid;
	int msiconf_index, node;
	int i, vector, cpu;
	unsigned long msi_config;
	int start_index;

@@ -207,15 +205,14 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs,
		cpumask_copy(&searchmask, cpumask_of_node(node));
	}

	coreid = cpumask_first(&searchmask);
	if (coreid >= nr_cpu_ids)
	if (cpumask_first(&searchmask) >= nr_cpu_ids)
		cpumask_copy(&searchmask, cpu_online_mask);

	for (i = 0; i < nr_irqs; i++) {
		if (!find_free_core_vector(&searchmask, &found_coreid, &found_vector))
		if (!find_free_cpu_vector(&searchmask, &cpu, &vector))
			return -ENOSPC;

		per_cpu(vector_irq, found_coreid)[found_vector] = virq + i;
		per_cpu(vector_irq, cpu)[vector] = virq + i;

		if (i) {
			irq_data = irq_domain_get_irq_data(domain, virq + i);
@@ -230,16 +227,16 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs,

		irq_data->chip_data = cdata;
		msiconf_index = start_index + i;
		msi_config = set_piu_msi_config(hose, found_coreid, msiconf_index, found_vector);
		msi_config = set_piu_msi_config(hose, cpu, msiconf_index, vector);

		cdata->dst_coreid = found_coreid;
		cdata->vector = found_vector;
		cdata->dst_cpu = cpu;
		cdata->vector = vector;
		cdata->rc_index = hose->index;
		cdata->rc_node = hose->node;
		cdata->msi_config = msi_config;
		cdata->msi_config_index = msiconf_index;
		cdata->prev_coreid = found_coreid;
		cdata->prev_vector = found_vector;
		cdata->prev_cpu = cpu;
		cdata->prev_vector = vector;
		cdata->move_in_progress = false;
	}
	return 0;
@@ -279,7 +276,7 @@ static void sw64_vector_free_irqs(struct irq_domain *domain,
				clear_bit(cdata->msi_config_index, hose->piu_msiconfig);
			}
			irq_domain_reset_irq_data(irq_data);
			per_cpu(vector_irq, cdata->dst_coreid)[cdata->vector] = 0;
			per_cpu(vector_irq, cdata->dst_cpu)[cdata->vector] = 0;
			kfree(cdata);
			raw_spin_unlock_irqrestore(&vector_lock, flags);
		}
@@ -288,8 +285,10 @@ static void sw64_vector_free_irqs(struct irq_domain *domain,

static void sw64_irq_free_descs(unsigned int virq, unsigned int nr_irqs)
{
	if (is_guest_or_emul())
	if (is_guest_or_emul()) {
		vt_sw64_vector_free_irqs(virq, nr_irqs);
		return irq_free_descs(virq, nr_irqs);
	}

	return irq_domain_free_irqs(virq, nr_irqs);
}
@@ -399,22 +398,22 @@ void arch_init_msi_domain(struct irq_domain *parent)
		pr_warn("failed to initialize irqdomain for MSI/MSI-x.\n");
}

static void irq_move_complete(struct sw64_msi_chip_data *cdata, int coreid, int vector)
static void irq_move_complete(struct sw64_msi_chip_data *cdata, int cpu, int vector)
{
	if (likely(!cdata->move_in_progress))
		return;
	if (vector == cdata->vector && cdata->dst_coreid == coreid) {
	if (vector == cdata->vector && cdata->dst_cpu == cpu) {
		raw_spin_lock(&vector_lock);
		cdata->move_in_progress = 0;
		per_cpu(vector_irq, cdata->prev_coreid)[cdata->prev_vector] = 0;
		per_cpu(vector_irq, cdata->prev_cpu)[cdata->prev_vector] = 0;
		raw_spin_unlock(&vector_lock);
	}
}

void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned long pci_msi1_addr)
{
	int i, msi_index = 0;
	int vector_index = 0, logical_cid;
	int i, irq, piu_index, msi_index = 0;
	int cpu, vector_index = 0;
	unsigned long value = 0;
	unsigned long int_pci_msi[3];
	unsigned long *ptr;
@@ -422,7 +421,9 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned
	struct sw64_msi_chip_data *cdata;

	if (is_guest_or_emul()) {
		handle_irq(vector);
		cpu = smp_processor_id();
		irq = per_cpu(vector_irq, cpu)[vector];
		handle_irq(irq);
		return;
	}

@@ -431,25 +432,22 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned
	int_pci_msi[1] = *(ptr + 1);
	int_pci_msi[2] = *(ptr + 2);

	logical_cid = smp_processor_id();
	cpu = smp_processor_id();

	for (i = 0; i < 4; i++) {
		vector_index = i * 64;
		while (vector != 0) {
			int irq = 0;
			int piu_index = 0;

			msi_index = find_next_bit(&vector, 64, msi_index);
			if (msi_index == 64) {
				msi_index = 0;
				continue;
			}

			irq = per_cpu(vector_irq, logical_cid)[vector_index + msi_index];
			irq = per_cpu(vector_irq, cpu)[vector_index + msi_index];
			irq_data = irq_domain_get_irq_data(msi_default_domain->parent, irq);
			cdata = irq_data_get_irq_chip_data(irq_data);
			spin_lock(&cdata->cdata_lock);
			irq_move_complete(cdata, logical_cid, vector_index + msi_index);
			irq_move_complete(cdata, cpu, vector_index + msi_index);
			piu_index = cdata->msi_config_index;
			value = cdata->msi_config | (1UL << 63);
			write_piu_ior0(cdata->rc_node, cdata->rc_index, MSICONFIG0 + (piu_index << 7), value);
+122 −28
Original line number Diff line number Diff line
@@ -4,35 +4,54 @@
#include <linux/module.h>
#include <linux/msi.h>

#define QEMU_MSIX_MSG_ADDR     (0x8000fee00000UL)

static DEFINE_RAW_SPINLOCK(vector_lock);

static struct irq_chip msi_chip = {
static void __vt_irq_msi_compose_msg(struct sw64_msi_chip_data *cdata,
				     struct msi_msg *msg)
{
	msg->address_hi = (u32)(VT_MSIX_MSG_ADDR >> 32);
	msg->address_lo = (u32)(VT_MSIX_MSG_ADDR & 0xffffffff)
				| VT_MSIX_ADDR_DEST_ID(cdata->dst_cpu);
	msg->data = cdata->vector;
}

static void vt_irq_msi_compose_msg(struct irq_data *irqd, struct msi_msg *msg)
{
	struct sw64_msi_chip_data *cdata;

	cdata = irqd->chip_data;
	__vt_irq_msi_compose_msg(cdata, msg);
}

static void vt_irq_msi_update_msg(struct irq_data *irqd,
				  struct sw64_msi_chip_data *cdata)
{
	struct msi_msg msg[2] = { [1] = { }, };

	__vt_irq_msi_compose_msg(cdata, msg);
	pci_write_msi_msg(irqd->irq, msg);
}

static struct irq_chip vt_pci_msi_controller = {
	.name = "PCI-MSI",
	.irq_unmask = pci_msi_unmask_irq,
	.irq_mask = pci_msi_mask_irq,
	.irq_ack = sw64_irq_noop,
	.irq_compose_msi_msg = vt_irq_msi_compose_msg,
};

static int qemu_msi_compose_msg(unsigned int irq, struct msi_msg *msg)
{
	msg->address_hi = (unsigned int)(QEMU_MSIX_MSG_ADDR >> 32);
	msg->address_lo = (unsigned int)(QEMU_MSIX_MSG_ADDR & 0xffffffff);
	msg->data = irq;
	return irq;
}

int chip_setup_vt_msix_irq(struct pci_dev *dev, struct msi_desc *desc)
{
	struct msi_msg msg;
	int virq, val_node = 0;
	struct irq_data *irq_data;
	struct sw6_msi_chip_data *cdata;
	struct sw64_msi_chip_data *cdata;
	struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
	unsigned long flags, node, rc_index;
	const struct cpumask *mask;

	struct cpumask searchmask;
	int cpu, vector;

	node = hose->node;
	rc_index = hose->index;
	mask = cpumask_of_node(node);
@@ -46,20 +65,46 @@ int chip_setup_vt_msix_irq(struct pci_dev *dev, struct msi_desc *desc)

	virq = irq_alloc_descs_from(NR_IRQS_LEGACY, desc->nvec_used, val_node);
	if (virq < 0) {
		pr_debug("cannot allocate IRQ(base 16, count %d)\n", desc->nvec_used);
		pr_err("Failed to allocate IRQ(base 16, count %d)\n", desc->nvec_used);
		raw_spin_unlock_irqrestore(&vector_lock, flags);
		return virq;
	}

	qemu_msi_compose_msg(virq, &msg);
	irq_set_msi_desc(virq, desc);
	pci_write_msi_msg((virq), &msg);
	irq_set_chip_and_handler_name(virq, &msi_chip, handle_edge_irq, "edge");
	irq_data = irq_get_irq_data(virq);

	if (irqd_affinity_is_managed(irq_data)) {
		mask = irq_data_get_affinity_mask(irq_data);
		cpumask_and(&searchmask, mask, cpu_online_mask);
	} else {
		node = irq_data_get_node(irq_data);
		cpumask_copy(&searchmask, cpumask_of_node(node));
	}
	if (cpumask_first(&searchmask) >= nr_cpu_ids)
		cpumask_copy(&searchmask, cpu_online_mask);

	if (!find_free_cpu_vector(&searchmask, &cpu, &vector))
		return -ENOSPC;

	cdata = kzalloc(sizeof(*cdata), GFP_KERNEL);
	if (!cdata)
		return -ENOMEM;

	per_cpu(vector_irq, cpu)[vector] = virq;

	irq_set_msi_desc(virq, desc);
	irq_set_chip_and_handler_name(virq, &vt_pci_msi_controller,
				      handle_edge_irq, "edge");

	cdata->dst_cpu = cpu;
	cdata->vector = vector;
	cdata->rc_index = hose->index;
	cdata->rc_node = hose->node;
	cdata->prev_cpu = cpu;
	cdata->prev_vector = vector;

	irq_data->chip_data = cdata;

	vt_irq_msi_update_msg(irq_data, irq_data->chip_data);
	raw_spin_unlock_irqrestore(&vector_lock, flags);
	return 0;
}
@@ -68,15 +113,17 @@ EXPORT_SYMBOL(chip_setup_vt_msix_irq);
int chip_setup_vt_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
	struct msi_desc *desc;
	struct msi_msg msg;
	struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
	struct irq_data *irq_data;
	struct sw6_msi_chip_data *cdata;
	int i = 0;
	struct sw64_msi_chip_data *cdata;
	unsigned long node, rc_index;
	int virq = -1, val_node = 0;
	unsigned long flags;

	const struct cpumask *mask;
	struct cpumask searchmask;
	int i, vector, cpu;

	if (type == PCI_CAP_ID_MSI && nvec > 32)
		return 1;

@@ -91,21 +138,46 @@ int chip_setup_vt_msi_irqs(struct pci_dev *dev, int nvec, int type)
			val_node = node;
		virq = irq_alloc_descs_from(NR_IRQS_LEGACY, desc->nvec_used, val_node);
		if (virq < 0) {
			pr_debug("cannot allocate IRQ(base 16, count %d)\n", desc->nvec_used);
			pr_err("Failed to allocate IRQ(base 16, count %d)\n", desc->nvec_used);
			raw_spin_unlock_irqrestore(&vector_lock, flags);
			return virq;
		}
		qemu_msi_compose_msg(virq, &msg);

		irq_data = irq_get_irq_data(virq);
		if (irqd_affinity_is_managed(irq_data)) {
			mask = irq_data_get_affinity_mask(irq_data);
			cpumask_and(&searchmask, mask, cpu_online_mask);
		} else {
			node = irq_data_get_node(irq_data);
			cpumask_copy(&searchmask, cpumask_of_node(node));
		}
		if (cpumask_first(&searchmask) >= nr_cpu_ids)
			cpumask_copy(&searchmask, cpu_online_mask);

		for (i = 0; i < desc->nvec_used; i++) {
			irq_set_msi_desc_off(virq, i, desc);
			pci_write_msi_msg((virq + i), &msg);
			desc->msi_attrib.multiple = ilog2(__roundup_pow_of_two(nvec));
			irq_set_chip_and_handler_name(virq + i, &msi_chip, handle_edge_irq, "edge");
			irq_data = irq_get_irq_data(virq + i);
			if (!find_free_cpu_vector(&searchmask, &cpu, &vector))
				return -ENOSPC;

			cdata = kzalloc(sizeof(*cdata), GFP_KERNEL);
			if (!cdata)
				return -ENOMEM;

			per_cpu(vector_irq, cpu)[vector] =  virq + i;
			irq_set_msi_desc_off(virq, i, desc);
			desc->msi_attrib.multiple = ilog2(__roundup_pow_of_two(nvec));
			irq_set_chip_and_handler_name(virq + i, &vt_pci_msi_controller, handle_edge_irq, "edge");
			irq_data = irq_get_irq_data(virq + i);

			cdata->dst_cpu = cpu;
			cdata->vector = vector;
			cdata->rc_index = hose->index;
			cdata->rc_node = hose->node;
			cdata->prev_cpu = cpu;
			cdata->prev_vector = vector;

			irq_data->chip_data = cdata;

			vt_irq_msi_update_msg(irq_data, irq_data->chip_data);
		}
	}

@@ -114,6 +186,28 @@ int chip_setup_vt_msi_irqs(struct pci_dev *dev, int nvec, int type)
}
EXPORT_SYMBOL(chip_setup_vt_msi_irqs);

void vt_sw64_vector_free_irqs(unsigned int virq, unsigned int nr_irqs)
{
	int i;
	unsigned long flags;
	struct irq_data *irq_data;
	struct sw64_msi_chip_data *cdata;

	for (i = 0; i < nr_irqs; i++) {
		irq_data = irq_get_irq_data(virq + i);
		if (irq_data && irq_data->chip_data) {
			raw_spin_lock_irqsave(&vector_lock, flags);
			cdata = irq_data->chip_data;
			irq_data->hwirq = 0;
			irq_data->chip = &no_irq_chip;
			irq_data->chip_data = NULL;
			per_cpu(vector_irq, cdata->dst_cpu)[cdata->vector] = 0;
			kfree(cdata);
			raw_spin_unlock_irqrestore(&vector_lock, flags);
		}
	}
}

int __arch_setup_vt_msix_irqs(struct pci_dev *dev, int nvec, int type)
{
	struct msi_desc *entry;
+22 −1
Original line number Diff line number Diff line
@@ -17,8 +17,18 @@

#define MSIX_MSG_ADDR		(0x91abc0UL)

#define VT_MSIX_MSG_ADDR	(0x8000fee00000UL)
#define VT_MSIX_ADDR_DEST_ID_SHIFT	12
#define VT_MSIX_ADDR_DEST_ID_MASK	(0xff << VT_MSIX_ADDR_DEST_ID_SHIFT)
#define VT_MSIX_ADDR_DEST_ID(dest)	\
	(((dest) << VT_MSIX_ADDR_DEST_ID_SHIFT) & VT_MSIX_ADDR_DEST_ID_MASK)


#ifdef CONFIG_PCI_MSI
extern void vt_sw64_vector_free_irqs(unsigned int virq, unsigned int nr_irqs);
extern int sw64_setup_vt_msi_irqs(struct pci_dev *dev, int nvec, int type);
extern bool find_free_cpu_vector(const struct cpumask *search_mask,
				 int *found_cpu, int *found_vector);
extern int msi_compose_msg(unsigned int irq, struct msi_msg *msg);
extern void sw64_irq_noop(struct irq_data *d);
extern struct irq_chip sw64_irq_chip;
@@ -26,9 +36,20 @@ extern struct irq_chip sw64_irq_chip;
#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
#define MSI_ADDR_BASE_HI	0
#define MSI_ADDR_BASE_LO	0x91abc0
struct sw6_msi_chip_data {

struct sw64_msi_chip_data {
	spinlock_t cdata_lock;
	unsigned long msi_config;
	unsigned long rc_node;
	unsigned long rc_index;
	unsigned int msi_config_index;
	unsigned int dst_cpu;
	unsigned int vector;
	unsigned int prev_cpu;
	unsigned int prev_vector;
	bool move_in_progress;
};

extern void arch_init_msi_domain(struct irq_domain *domain);
enum irq_alloc_type {
	IRQ_ALLOC_TYPE_MSI,
+3 −0
Original line number Diff line number Diff line
@@ -6,6 +6,9 @@
 * KVM SW specific structures and definitions.
 */
#define SWVM_IRQS 256
#define IRQ_PENDING_INTX_SHIFT		16
#define IRQ_PENDING_MSI_VECTORS_SHIFT	17

enum SW64_KVM_IRQ {
	SW64_KVM_IRQ_IPI = 27,
	SW64_KVM_IRQ_TIMER = 9,
+8 −6
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/kvm.h>
#include <linux/uaccess.h>
#include <linux/sched.h>
#include <linux/msi.h>
#include <asm/kvm_timer.h>
#include <asm/kvm_emulate.h>

@@ -62,11 +63,13 @@ int vcpu_interrupt_line(struct kvm_vcpu *vcpu, int number, bool level)
int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm, int irq_source_id,
		int level, bool line_status)
{
	int irq = e->msi.data & 0xff;
	unsigned int vcid;
	unsigned int vcpu_idx;
	struct kvm_vcpu *vcpu = NULL;
	int irq = e->msi.data & 0xff;

	vcpu_idx = irq % atomic_read(&kvm->online_vcpus);
	vcid = (e->msi.address_lo & VT_MSIX_ADDR_DEST_ID_MASK) >> VT_MSIX_ADDR_DEST_ID_SHIFT;
	vcpu_idx = vcid & 0x1f;
	vcpu = kvm_get_vcpu(kvm, vcpu_idx);

	if (!vcpu)
@@ -962,14 +965,13 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
		bool line_status)
{
	u32 irq = irq_level->irq;
	unsigned int vcpu_idx, irq_num;
	unsigned int irq_num;
	struct kvm_vcpu *vcpu = NULL;
	bool level = irq_level->level;

	vcpu_idx = irq % atomic_read(&kvm->online_vcpus);
	irq_num = irq;

	vcpu = kvm_get_vcpu(kvm, vcpu_idx);
	/* target core for Intx is core0 */
	vcpu = kvm_get_vcpu(kvm, 0);
	if (!vcpu)
		return -EINVAL;