Commit a02b493f authored by Lei Yilong's avatar Lei Yilong Committed by guzitao
Browse files

sw64: fix msi interrupt for guest os

Sunway inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBDJNZ



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

This patch:
 - Add msi_domain for guset os, including vt_pci_msi_domain_ops and
   pci_vt_msi_domain_info which support msi interrupt initialization
   in a standard way.
 - Modify the method to find free cpu vector to ensure that msi irq
   number can be set on the proper cpu. When migrate an interrupt,
   it can find the vector which was used before but not cleaned up.
 - Add vt_irq_move_complete() for guest os. If the interrupt migration
   has completed, it is necessory to clear its information on previous
   cpu before irq is handled.

After that, it can handle msi interrupt correctly during cpu hotplug.
Besides, move guset related code into irq-sunway-msi-vt.c.

Signed-off-by: default avatarLei Yilong <leiyilong@wxiat.com>
Reviewed-by: default avatarHe Sheng <hesheng@wxiat.com>
Signed-off-by: default avatarGu Zitao <guzitao@wxiat.com>
parent 985bab23
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@
 */
#define SWVM_IRQS 256
#define IRQ_PENDING_INTX_SHIFT		16
#define IRQ_PENDING_MSI_VECTORS_SHIFT	17
#define IRQ_PENDING_MSI_VECTORS_SHIFT	18

#define SWVM_NUM_NUMA_MEMBANKS	1

+6 −2
Original line number Diff line number Diff line
@@ -23,10 +23,14 @@
#define VT_MSIX_ADDR_DEST_ID(dest)	\
	(((dest) << VT_MSIX_ADDR_DEST_ID_SHIFT) & VT_MSIX_ADDR_DEST_ID_MASK)

enum irq_alloc_type;

#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 void vt_handle_pci_msi_interrupt(unsigned long type,
					unsigned long vector,
					unsigned long pci_msi1_addr);
extern void sw64_init_vt_msi_domain(struct irq_domain *parent);
extern int sw64_setup_vt_msi_irqs(struct pci_dev *pdev, 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);
+1 −1
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
 */
#define SWVM_IRQS 256
#define IRQ_PENDING_INTX_SHIFT		16
#define IRQ_PENDING_MSI_VECTORS_SHIFT	17
#define IRQ_PENDING_MSI_VECTORS_SHIFT	18

enum SW64_KVM_IRQ {
	SW64_KVM_IRQ_IPI = 27,
+5 −2
Original line number Diff line number Diff line
@@ -185,7 +185,7 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector,
	if (is_guest_or_emul()) {
		if ((type & 0xffff) > 15) {
			vector = type;
			if (vector == 16)
			if (vector == 16 || vector == 17)
				type = INT_INTx;
			else
				type = INT_MSI;
@@ -199,6 +199,9 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector,
	switch (type & 0xffff) {
	case INT_MSI:
		old_regs = set_irq_regs(regs);
		if (is_guest_or_emul())
			vt_handle_pci_msi_interrupt(type, vector, irq_arg);
		else
			handle_pci_msi_interrupt(type, vector, irq_arg);
		set_irq_regs(old_regs);
		return;
+3 −20
Original line number Diff line number Diff line
@@ -52,13 +52,8 @@ bool find_free_cpu_vector(const struct cpumask *search_mask,

	cpu = cpumask_first(search_mask);
try_again:
	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);
@@ -335,11 +330,6 @@ 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()) {
		vt_sw64_vector_free_irqs(virq, nr_irqs);
		return irq_free_descs(virq, nr_irqs);
	}

	return irq_domain_free_irqs(virq, nr_irqs);
}

@@ -437,7 +427,7 @@ void arch_init_msi_domain(struct irq_domain *parent)
	struct irq_domain *sw64_irq_domain;

	if (is_guest_or_emul())
		return;
		return sw64_init_vt_msi_domain(parent);

	sw64_irq_domain = irq_domain_add_tree(NULL, &sw64_msi_domain_ops, NULL);
	BUG_ON(sw64_irq_domain == NULL);
@@ -475,13 +465,6 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned
	struct irq_data *irq_data;
	struct sw64_msi_chip_data *cdata;

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

	ptr = (unsigned long *)pci_msi1_addr;
	int_pci_msi[0] = *ptr;
	int_pci_msi[1] = *(ptr + 1);
Loading