Unverified Commit c2f75fa5 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!13997 Add interrupt controller emulation in the kernel

parents e1c03dd9 bd254ad9
Loading
Loading
Loading
Loading
+95 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2024 Loongson Technology Corporation Limited
 */

#ifndef LOONGARCH_EXTIOI_H
#define LOONGARCH_EXTIOI_H

#include <kvm/iodev.h>

#define EXTIOI_IRQS			256
#define EXTIOI_ROUTE_MAX_VCPUS		256
#define EXTIOI_IRQS_U8_NUMS		(EXTIOI_IRQS / 8)
#define EXTIOI_IRQS_U32_NUMS		(EXTIOI_IRQS_U8_NUMS / 4)
#define EXTIOI_IRQS_U64_NUMS		(EXTIOI_IRQS_U32_NUMS / 2)
/* map to ipnum per 32 irqs */
#define EXTIOI_IRQS_NODETYPE_COUNT	16

#define EXTIOI_BASE			0x1400
#define EXTIOI_SIZE			0x900

#define EXTIOI_NODETYPE_START		0xa0
#define EXTIOI_NODETYPE_END		0xbf
#define EXTIOI_IPMAP_START		0xc0
#define EXTIOI_IPMAP_END		0xc7
#define EXTIOI_ENABLE_START		0x200
#define EXTIOI_ENABLE_END		0x21f
#define EXTIOI_BOUNCE_START		0x280
#define EXTIOI_BOUNCE_END		0x29f
#define EXTIOI_ISR_START		0x300
#define EXTIOI_ISR_END			0x31f
#define EXTIOI_COREISR_START		0x400
#define EXTIOI_COREISR_END		0x71f
#define EXTIOI_COREMAP_START		0x800
#define EXTIOI_COREMAP_END		0x8ff

#define LS3A_INTC_IP			8

#define EXTIOI_SW_COREMAP_FLAG		(1 << 0)

struct loongarch_extioi {
	spinlock_t lock;
	struct kvm *kvm;
	struct kvm_io_device device;
	/* hardware state */
	union nodetype {
		u64 reg_u64[EXTIOI_IRQS_NODETYPE_COUNT / 4];
		u32 reg_u32[EXTIOI_IRQS_NODETYPE_COUNT / 2];
		uint16_t reg_u16[EXTIOI_IRQS_NODETYPE_COUNT];
		u8 reg_u8[EXTIOI_IRQS_NODETYPE_COUNT * 2];
	} nodetype;

	/* one bit shows the state of one irq */
	union bounce {
		u64 reg_u64[EXTIOI_IRQS_U64_NUMS];
		u32 reg_u32[EXTIOI_IRQS_U32_NUMS];
		u8 reg_u8[EXTIOI_IRQS_U8_NUMS];
	} bounce;

	union isr {
		u64 reg_u64[EXTIOI_IRQS_U64_NUMS];
		u32 reg_u32[EXTIOI_IRQS_U32_NUMS];
		u8 reg_u8[EXTIOI_IRQS_U8_NUMS];
	} isr;
	union coreisr {
		u64 reg_u64[EXTIOI_ROUTE_MAX_VCPUS][EXTIOI_IRQS_U64_NUMS];
		u32 reg_u32[EXTIOI_ROUTE_MAX_VCPUS][EXTIOI_IRQS_U32_NUMS];
		u8 reg_u8[EXTIOI_ROUTE_MAX_VCPUS][EXTIOI_IRQS_U8_NUMS];
	} coreisr;
	union enable {
		u64 reg_u64[EXTIOI_IRQS_U64_NUMS];
		u32 reg_u32[EXTIOI_IRQS_U32_NUMS];
		u8 reg_u8[EXTIOI_IRQS_U8_NUMS];
	} enable;

	/* use one byte to config ipmap for 32 irqs at once */
	union ipmap {
		u64 reg_u64;
		u32 reg_u32[EXTIOI_IRQS_U32_NUMS / 4];
		u8 reg_u8[EXTIOI_IRQS_U8_NUMS / 4];
	} ipmap;
	/* use one byte to config coremap for one irq */
	union coremap {
		u64 reg_u64[EXTIOI_IRQS / 8];
		u32 reg_u32[EXTIOI_IRQS / 4];
		u8 reg_u8[EXTIOI_IRQS];
	} coremap;

	DECLARE_BITMAP(sw_coreisr[EXTIOI_ROUTE_MAX_VCPUS][LS3A_INTC_IP], EXTIOI_IRQS);
	uint8_t  sw_coremap[EXTIOI_IRQS];
};

void extioi_set_irq(struct loongarch_extioi *s, int irq, int level);
int kvm_loongarch_register_extioi_device(void);
#endif /* LOONGARCH_EXTIOI_H */
+30 −0
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@
#include <asm/inst.h>
#include <asm/kvm_mmu.h>
#include <asm/loongarch.h>
#include <asm/kvm_ipi.h>
#include <asm/kvm_extioi.h>
#include <asm/kvm_pch_pic.h>

/* Loongarch KVM register ids */
#define KVM_GET_IOC_CSR_IDX(id)		((id & KVM_CSR_IDX_MASK) >> LOONGARCH_REG_SHIFT)
@@ -32,12 +35,34 @@
#define KVM_HALT_POLL_NS_DEFAULT	500000
#define KVM_REQ_RECORD_STEAL		KVM_ARCH_REQ(1)

/* KVM_IRQ_LINE irq field index values */
#define KVM_LOONGARCH_IRQ_TYPE_SHIFT	24
#define KVM_LOONGARCH_IRQ_TYPE_MASK	0xff
#define KVM_LOONGARCH_IRQ_VCPU_SHIFT	16
#define KVM_LOONGARCH_IRQ_VCPU_MASK	0xff
#define KVM_LOONGARCH_IRQ_NUM_SHIFT	0
#define KVM_LOONGARCH_IRQ_NUM_MASK	0xffff

/* irq_type field */
#define KVM_LOONGARCH_IRQ_TYPE_CPU_IP	0
#define KVM_LOONGARCH_IRQ_TYPE_CPU_IO	1
#define KVM_LOONGARCH_IRQ_TYPE_HT	2
#define KVM_LOONGARCH_IRQ_TYPE_MSI	3
#define KVM_LOONGARCH_IRQ_TYPE_IOAPIC	4
#define KVM_LOONGARCH_IRQ_TYPE_ROUTE	5

#define KVM_GUESTDBG_VALID_MASK		(KVM_GUESTDBG_ENABLE | \
			KVM_GUESTDBG_USE_SW_BP | KVM_GUESTDBG_SINGLESTEP)
struct kvm_vm_stat {
	struct kvm_vm_stat_generic generic;
	u64 pages;
	u64 hugepages;
	u64 ipi_read_exits;
	u64 ipi_write_exits;
	u64 extioi_read_exits;
	u64 extioi_write_exits;
	u64 pch_pic_read_exits;
	u64 pch_pic_write_exits;
};

struct kvm_vcpu_stat {
@@ -109,6 +134,9 @@ struct kvm_arch {

	s64 time_offset;
	struct kvm_context __percpu *vmcs;
	struct loongarch_ipi *ipi;
	struct loongarch_extioi *extioi;
	struct loongarch_pch_pic *pch_pic;
};

#define CSR_MAX_NUMS		0x800
@@ -206,6 +234,8 @@ struct kvm_vcpu_arch {
	int last_sched_cpu;
	/* mp state */
	struct kvm_mp_state mp_state;
	/* ipi state */
	struct ipi_state ipi_state;
	/* cpucfg */
	u32 cpucfg[KVM_MAX_CPUCFG_REGS];
	/* paravirt steal time */
+52 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2024 Loongson Technology Corporation Limited
 */

#ifndef __LS3A_KVM_IPI_H
#define __LS3A_KVM_IPI_H

#include <kvm/iodev.h>

#define LARCH_INT_IPI			12

struct loongarch_ipi {
	spinlock_t lock;
	struct kvm *kvm;
	struct kvm_io_device device;
	struct kvm_io_device mail_dev;
};

struct ipi_state {
	spinlock_t lock;
	uint32_t status;
	uint32_t en;
	uint32_t set;
	uint32_t clear;
	uint64_t buf[4];
};

#define SMP_MAILBOX			0x1000
#define KVM_IOCSR_IPI_ADDR_SIZE		0x48

#define CORE_STATUS_OFF			0x000
#define CORE_EN_OFF			0x004
#define CORE_SET_OFF			0x008
#define CORE_CLEAR_OFF			0x00c
#define CORE_BUF_20			0x020
#define CORE_BUF_28			0x028
#define CORE_BUF_30			0x030
#define CORE_BUF_38			0x038
#define IOCSR_IPI_SEND			0x040

#define IOCSR_MAIL_SEND			0x048
#define IOCSR_ANY_SEND			0x158

#define MAIL_SEND_ADDR			(SMP_MAILBOX + IOCSR_MAIL_SEND)
#define KVM_IOCSR_MAIL_ADDR_SIZE	0x118

#define MAIL_SEND_OFFSET		0
#define ANY_SEND_OFFSET			(IOCSR_ANY_SEND - IOCSR_MAIL_SEND)

int kvm_loongarch_register_ipi_device(void);
#endif
+61 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2024 Loongson Technology Corporation Limited
 */

#ifndef LOONGARCH_PCH_PIC_H
#define LOONGARCH_PCH_PIC_H

#include <kvm/iodev.h>

#define PCH_PIC_SIZE			0x3e8

#define PCH_PIC_INT_ID_START		0x0
#define PCH_PIC_INT_ID_END		0x7
#define PCH_PIC_MASK_START		0x20
#define PCH_PIC_MASK_END		0x27
#define PCH_PIC_HTMSI_EN_START		0x40
#define PCH_PIC_HTMSI_EN_END		0x47
#define PCH_PIC_EDGE_START		0x60
#define PCH_PIC_EDGE_END		0x67
#define PCH_PIC_CLEAR_START		0x80
#define PCH_PIC_CLEAR_END		0x87
#define PCH_PIC_AUTO_CTRL0_START	0xc0
#define PCH_PIC_AUTO_CTRL0_END		0xc7
#define PCH_PIC_AUTO_CTRL1_START	0xe0
#define PCH_PIC_AUTO_CTRL1_END		0xe7
#define PCH_PIC_ROUTE_ENTRY_START	0x100
#define PCH_PIC_ROUTE_ENTRY_END		0x13f
#define PCH_PIC_HTMSI_VEC_START		0x200
#define PCH_PIC_HTMSI_VEC_END		0x23f
#define PCH_PIC_INT_IRR_START		0x380
#define PCH_PIC_INT_IRR_END		0x38f
#define PCH_PIC_INT_ISR_START		0x3a0
#define PCH_PIC_INT_ISR_END		0x3af
#define PCH_PIC_POLARITY_START		0x3e0
#define PCH_PIC_POLARITY_END		0x3e7
#define PCH_PIC_INT_ID_VAL		0x7000000UL
#define PCH_PIC_INT_ID_VER		0x1UL

struct loongarch_pch_pic {
	spinlock_t lock;
	struct kvm *kvm;
	struct kvm_io_device device;
	uint64_t mask; /* 1:disable irq, 0:enable irq */
	uint64_t htmsi_en; /* 1:msi */
	uint64_t edge; /* 1:edge triggered, 0:level triggered */
	uint64_t auto_ctrl0; /* only use default value 00b */
	uint64_t auto_ctrl1; /* only use default value 00b */
	uint64_t last_intirr; /* edge detection */
	uint64_t irr; /* interrupt request register */
	uint64_t isr; /* interrupt service register */
	uint64_t polarity; /* 0: high level trigger, 1: low level trigger */
	uint8_t  route_entry[64]; /* default value 0, route to int0: extioi */
	uint8_t  htmsi_vector[64]; /* irq route table for routing to extioi */
	uint64_t pch_pic_base;
};

void pch_pic_set_irq(struct loongarch_pch_pic *s, int irq, int level);
void pch_msi_set_irq(struct kvm *kvm, int irq, int level);
int kvm_loongarch_register_pch_pic_device(void);
#endif /* LOONGARCH_PCH_PIC_H */
+12 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#define KVM_COALESCED_MMIO_PAGE_OFFSET	1
#define KVM_DIRTY_LOG_PAGE_OFFSET	64
#define __KVM_HAVE_IRQ_LINE

#define KVM_GUESTDBG_USE_SW_BP		0x00010000
/*
@@ -114,4 +115,15 @@ struct kvm_iocsr_entry {
#define KVM_IRQCHIP_NUM_PINS	64
#define KVM_MAX_CORES		256

#define KVM_LOONGARCH_VM_HAVE_IRQCHIP		0x40000001

#define KVM_DEV_LOONGARCH_IPI_GRP_REGS		0x40000002

#define KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS	0x40000003

#define KVM_DEV_LOONGARCH_PCH_PIC_GRP_CTRL	0x40000004
#define KVM_DEV_LOONGARCH_PCH_PIC_CTRL_INIT	0

#define KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS	0x40000005

#endif /* __UAPI_ASM_LOONGARCH_KVM_H */
Loading