1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4 */
5
6#ifndef __LS3A_KVM_EXT_IRQ_H
7#define __LS3A_KVM_EXT_IRQ_H
8
9#include <linux/mm_types.h>
10#include <linux/hrtimer.h>
11#include <linux/kvm_host.h>
12#include <linux/spinlock.h>
13#include <linux/seq_file.h>
14
15#include <kvm/iodev.h>
16
17#define IOCSR_EXTIOI_ADDR		KVM_IOCSR_EXTIOI_NODEMAP_BASE
18
19#define EXTIOI_ADDR_OFF			0x10000
20#define EXTIOI_REG_BASE			(LOONGSON_VIRT_REG_BASE + EXTIOI_ADDR_OFF)
21#define EXTIOI_REG_END			(EXTIOI_REG_BASE + 0x20000)
22#define EXTIOI_ADDR_SIZE		(EXTIOI_REG_END - EXTIOI_REG_BASE)
23#define EXTIOI_PERCORE_REG_OFF		0x10000
24#define EXTIOI_PERCORE_REG_END		(EXTIOI_PERCORE_REG_OFF + 0x10000)
25
26#define EXTIOI_ADDR(off)		(EXTIOI_REG_BASE + (off) - IOCSR_EXTIOI_ADDR)
27#define EXTIOI_PERCORE_ADDR(id, off) \
28	(EXTIOI_REG_BASE + EXTIOI_PERCORE_REG_OFF + ((id) << 8) + (off))
29
30#define EXTIOI_NODETYPE_START		(KVM_IOCSR_EXTIOI_NODEMAP_BASE - IOCSR_EXTIOI_ADDR)
31#define EXTIOI_NODETYPE_END		(EXTIOI_NODETYPE_START + 0x20)
32#define EXTIOI_IPMAP_START		(KVM_IOCSR_EXTIOI_IPMAP_BASE - IOCSR_EXTIOI_ADDR)
33#define EXTIOI_IPMAP_END		(EXTIOI_IPMAP_START + 0x8)
34#define EXTIOI_ENABLE_START		(KVM_IOCSR_EXTIOI_EN_BASE - IOCSR_EXTIOI_ADDR)
35#define EXTIOI_ENABLE_END		(EXTIOI_ENABLE_START + 0x20)
36#define EXTIOI_BOUNCE_START		(KVM_IOCSR_EXTIOI_BOUNCE_BASE - IOCSR_EXTIOI_ADDR)
37#define EXTIOI_BOUNCE_END		(EXTIOI_BOUNCE_START + 0x20)
38#define EXTIOI_ISR_START		(0x1700 - IOCSR_EXTIOI_ADDR)
39#define EXTIOI_ISR_END			(EXTIOI_ISR_START + 0x20)
40#define EXTIOI_COREMAP_START		(KVM_IOCSR_EXTIOI_ROUTE_BASE - IOCSR_EXTIOI_ADDR)
41#define EXTIOI_COREMAP_END		(EXTIOI_COREMAP_START + 0x100)
42#define EXTIOI_COREISR_START		(EXTIOI_PERCORE_REG_OFF)
43#define EXTIOI_COREISR_END		(EXTIOI_PERCORE_REG_END)
44
45#define LS3A_INTC_IP			8
46#define EXTIOI_IRQS			KVM_EXTIOI_IRQS
47#define EXTIOI_IRQS_BITMAP_SIZE		(EXTIOI_IRQS / 8)
48/* map to ipnum per 32 irqs */
49#define EXTIOI_IRQS_IPMAP_SIZE		(EXTIOI_IRQS / 32)
50#define EXTIOI_IRQS_PER_GROUP		KVM_EXTIOI_IRQS_PER_GROUP
51#define EXTIOI_IRQS_COREMAP_SIZE	(EXTIOI_IRQS)
52#define EXTIOI_IRQS_NODETYPE_SIZE	KVM_EXTIOI_IRQS_NODETYPE_SIZE
53
54typedef struct kvm_ls3a_extirq_state {
55	union ext_en {
56		uint64_t reg_u64[EXTIOI_IRQS_BITMAP_SIZE / 8];
57		uint32_t reg_u32[EXTIOI_IRQS_BITMAP_SIZE / 4];
58		uint8_t reg_u8[EXTIOI_IRQS_BITMAP_SIZE];
59	} ext_en;
60	union bounce {
61		uint64_t reg_u64[EXTIOI_IRQS_BITMAP_SIZE / 8];
62		uint32_t reg_u32[EXTIOI_IRQS_BITMAP_SIZE / 4];
63		uint8_t reg_u8[EXTIOI_IRQS_BITMAP_SIZE];
64	} bounce;
65	union ext_isr {
66		uint64_t reg_u64[EXTIOI_IRQS_BITMAP_SIZE / 8];
67		uint32_t reg_u32[EXTIOI_IRQS_BITMAP_SIZE / 4];
68		uint8_t reg_u8[EXTIOI_IRQS_BITMAP_SIZE];
69	} ext_isr;
70	union ext_core_isr {
71		uint64_t reg_u64[KVM_MAX_VCPUS][EXTIOI_IRQS_BITMAP_SIZE / 8];
72		uint32_t reg_u32[KVM_MAX_VCPUS][EXTIOI_IRQS_BITMAP_SIZE / 4];
73		uint8_t reg_u8[KVM_MAX_VCPUS][EXTIOI_IRQS_BITMAP_SIZE];
74	} ext_core_isr;
75	union ip_map {
76		uint64_t reg_u64;
77		uint32_t reg_u32[EXTIOI_IRQS_IPMAP_SIZE / 4];
78		uint8_t reg_u8[EXTIOI_IRQS_IPMAP_SIZE];
79	} ip_map;
80	union core_map {
81		uint64_t reg_u64[EXTIOI_IRQS_COREMAP_SIZE / 8];
82		uint32_t reg_u32[EXTIOI_IRQS_COREMAP_SIZE / 4];
83		uint8_t reg_u8[EXTIOI_IRQS_COREMAP_SIZE];
84	} core_map;
85	union node_type {
86		uint64_t reg_u64[EXTIOI_IRQS_NODETYPE_SIZE / 4];
87		uint32_t reg_u32[EXTIOI_IRQS_NODETYPE_SIZE / 2];
88		uint16_t reg_u16[EXTIOI_IRQS_NODETYPE_SIZE];
89		uint8_t reg_u8[EXTIOI_IRQS_NODETYPE_SIZE * 2];
90	} node_type;
91
92	/*software state */
93	uint8_t ext_sw_ipmap[EXTIOI_IRQS];
94	uint8_t ext_sw_coremap[EXTIOI_IRQS];
95	uint8_t ext_sw_ipisr[KVM_MAX_VCPUS][LS3A_INTC_IP][EXTIOI_IRQS_BITMAP_SIZE];
96} LS3AExtirqState;
97
98struct ls3a_kvm_extirq {
99	spinlock_t lock;
100	struct kvm *kvm;
101	struct kvm_io_device device;
102	struct kvm_ls3a_extirq_state ls3a_ext_irq;
103};
104
105static inline struct ls3a_kvm_extirq *ls3a_ext_irqchip(struct kvm *kvm)
106{
107	return kvm->arch.v_extirq;
108}
109
110static inline int ls3a_extirq_in_kernel(struct kvm *kvm)
111{
112	int ret;
113
114	ret = (ls3a_ext_irqchip(kvm) != NULL);
115	return ret;
116}
117
118
119void ext_irq_handler(struct kvm *kvm, int irq, int level);
120int kvm_create_ls3a_ext_irq(struct kvm *kvm);
121int kvm_get_ls3a_extirq(struct kvm *kvm,
122			struct kvm_loongarch_ls3a_extirq_state *state);
123int kvm_set_ls3a_extirq(struct kvm *kvm,
124			struct kvm_loongarch_ls3a_extirq_state *state);
125void kvm_destroy_ls3a_ext_irq(struct kvm *kvm);
126void msi_irq_handler(struct kvm *kvm, int irq, int level);
127int kvm_setup_ls3a_extirq(struct kvm *kvm);
128void kvm_dump_ls3a_extirq_state(struct seq_file *m, struct ls3a_kvm_extirq *irqchip);
129#endif
130