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 
54 typedef 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 
98 struct 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 
ls3a_ext_irqchip(struct kvm *kvm)105 static inline struct ls3a_kvm_extirq *ls3a_ext_irqchip(struct kvm *kvm)
106 {
107 	return kvm->arch.v_extirq;
108 }
109 
ls3a_extirq_in_kernel(struct kvm *kvm)110 static 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 
119 void ext_irq_handler(struct kvm *kvm, int irq, int level);
120 int kvm_create_ls3a_ext_irq(struct kvm *kvm);
121 int kvm_get_ls3a_extirq(struct kvm *kvm,
122 			struct kvm_loongarch_ls3a_extirq_state *state);
123 int kvm_set_ls3a_extirq(struct kvm *kvm,
124 			struct kvm_loongarch_ls3a_extirq_state *state);
125 void kvm_destroy_ls3a_ext_irq(struct kvm *kvm);
126 void msi_irq_handler(struct kvm *kvm, int irq, int level);
127 int kvm_setup_ls3a_extirq(struct kvm *kvm);
128 void kvm_dump_ls3a_extirq_state(struct seq_file *m, struct ls3a_kvm_extirq *irqchip);
129 #endif
130