1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2/*
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License.  See the file "COPYING" in the main directory of this archive
5 * for more details.
6 *
7 * Copyright (C) 2020  Loongson Technologies, Inc.  All rights reserved.
8 * Authors: Sanjay Lal <sanjayl@kymasys.com>
9 * Authors: Xing Li <lixing@loongson.cn>
10 */
11
12#ifndef __LINUX_KVM_LOONGARCH_H
13#define __LINUX_KVM_LOONGARCH_H
14
15#include <linux/types.h>
16
17#ifndef __KERNEL__
18#include <stdint.h>
19#endif
20
21#define __KVM_HAVE_GUEST_DEBUG
22#define KVM_GUESTDBG_USE_SW_BP 0x00010000
23#define KVM_GUESTDBG_USE_HW_BP 0x00020000
24#define KVM_DATA_HW_BREAKPOINT_NUM 8
25#define KVM_INST_HW_BREAKPOINT_NUM 8
26
27/*
28 * KVM Loongarch specific structures and definitions.
29 *
30 * Some parts derived from the x86 version of this file.
31 */
32
33#define __KVM_HAVE_READONLY_MEM
34
35#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
36
37/*
38 * for KVM_GET_REGS and KVM_SET_REGS
39 */
40struct kvm_regs {
41	/* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
42	__u64 gpr[32];
43	__u64 pc;
44};
45
46/*
47 * for KVM_GET_CPUCFG
48 */
49struct kvm_cpucfg {
50	/* out (KVM_GET_CPUCFG) */
51	__u32 cpucfg[64];
52};
53
54/*
55 * for KVM_GET_FPU and KVM_SET_FPU
56 */
57struct kvm_fpu {
58	__u32 fcsr;
59	__u64 fcc;    /* 8x8 */
60	struct kvm_fpureg {
61		__u64 val64[4];	//support max 256 bits
62	} fpr[32];
63};
64
65/*
66 * For LOONGARCH, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various
67 * registers.  The id field is broken down as follows:
68 *
69 *  bits[63..52] - As per linux/kvm.h
70 *  bits[51..32] - Must be zero.
71 *  bits[31..16] - Register set.
72 *
73 * Register set = 0: GP registers from kvm_regs (see definitions below).
74 * Register set = 1: CSR registers.
75 * Register set = 2: KVM specific registers (see definitions below).
76 * Register set = 3: FPU / SIMD registers (see definitions below).
77 * Register set = 4: LBT registers (see definitions below).
78 *
79 * Other sets registers may be added in the future.  Each set would
80 * have its own identifier in bits[31..16].
81 */
82
83#define KVM_REG_LOONGARCH_GP		(KVM_REG_LOONGARCH | 0x00000ULL)
84#define KVM_REG_LOONGARCH_CSR		(KVM_REG_LOONGARCH | 0x10000ULL)
85#define KVM_REG_LOONGARCH_KVM		(KVM_REG_LOONGARCH | 0x20000ULL)
86#define KVM_REG_LOONGARCH_FPU		(KVM_REG_LOONGARCH | 0x30000ULL)
87#define KVM_REG_LOONGARCH_LBT		(KVM_REG_LOONGARCH | 0x40000ULL)
88#define KVM_REG_LOONGARCH_MASK		(KVM_REG_LOONGARCH | 0x70000ULL)
89#define KVM_CSR_IDX_MASK		(0x10000 - 1)
90
91/*
92 * KVM_REG_LOONGARCH_KVM - KVM specific control registers.
93 */
94#define KVM_REG_LOONGARCH_COUNTER	(KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 3)
95#define KVM_REG_LOONGARCH_VCPU_RESET	(KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 4)
96
97#define KVM_REG_LBT_SCR0	(KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 1)
98#define KVM_REG_LBT_SCR1	(KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 2)
99#define KVM_REG_LBT_SCR2	(KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 3)
100#define KVM_REG_LBT_SCR3	(KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 4)
101#define KVM_REG_LBT_FLAGS	(KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 5)
102#define KVM_REG_LBT_FTOP	(KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 6)
103
104#define __KVM_HAVE_IRQ_LINE
105
106struct kvm_debug_exit_arch {
107	__u64 era;
108	__u32 fwps;
109	__u32 mwps;
110	__u32 exception;
111};
112
113/* for KVM_SET_GUEST_DEBUG */
114struct hw_breakpoint {
115    __u64 addr;
116    __u64 mask;
117    __u32 asid;
118    __u32 ctrl;
119};
120
121struct kvm_guest_debug_arch {
122	struct hw_breakpoint data_breakpoint[KVM_DATA_HW_BREAKPOINT_NUM];
123	struct hw_breakpoint inst_breakpoint[KVM_INST_HW_BREAKPOINT_NUM];
124	int inst_bp_nums, data_bp_nums;
125};
126
127/* definition of registers in kvm_run */
128struct kvm_sync_regs {
129};
130
131/* dummy definition */
132struct kvm_sregs {
133};
134
135struct kvm_iocsr_entry {
136	__u32 addr;
137	__u32 pad;
138	__u64 data;
139};
140
141struct kvm_csr_entry {
142	__u32 index;
143	__u32 reserved;
144	__u64 data;
145};
146
147/* for KVM_GET_MSRS and KVM_SET_MSRS */
148struct kvm_msrs {
149	__u32 ncsrs; /* number of msrs in entries */
150	__u32 pad;
151
152	struct kvm_csr_entry entries[0];
153};
154
155struct kvm_loongarch_interrupt {
156	/* in */
157	__u32 cpu;
158	__u32 irq;
159};
160
161#define KVM_IRQCHIP_LS7A_IOAPIC	0x0
162#define KVM_IRQCHIP_LS3A_GIPI	0x1
163#define KVM_IRQCHIP_LS3A_HT_IRQ	0x2
164#define KVM_IRQCHIP_LS3A_ROUTE	0x3
165#define KVM_IRQCHIP_LS3A_EXTIRQ	0x4
166#define KVM_IRQCHIP_LS3A_IPMASK	0x5
167#define KVM_NR_IRQCHIPS          1
168#define KVM_IRQCHIP_NUM_PINS    64
169
170#define KVM_MAX_CORES			256
171#define KVM_EXTIOI_IRQS			(256)
172#define KVM_EXTIOI_IRQS_BITMAP_SIZE	(KVM_EXTIOI_IRQS / 8)
173/* map to ipnum per 32 irqs */
174#define KVM_EXTIOI_IRQS_IPMAP_SIZE	(KVM_EXTIOI_IRQS / 32)
175#define KVM_EXTIOI_IRQS_PER_GROUP	32
176#define KVM_EXTIOI_IRQS_COREMAP_SIZE	(KVM_EXTIOI_IRQS)
177#define KVM_EXTIOI_IRQS_NODETYPE_SIZE	16
178
179struct ls7a_ioapic_state {
180	/* 0x000 interrupt id register */
181	__u64 int_id;
182	/* 0x020 interrupt mask register */
183	__u64 int_mask;
184	/* 0x040 1=msi */
185	__u64 htmsi_en;
186	/* 0x060 edge=1 level  =0 */
187	__u64 intedge;
188	/* 0x080 for clean edge int,set 1 clean,set 0 is noused */
189	__u64 intclr;
190	/* 0x0c0 */
191	__u64 auto_crtl0;
192	/* 0x0e0 */
193	__u64 auto_crtl1;
194	/* 0x100 - 0x140 */
195	__u8 route_entry[64];
196	/* 0x200 - 0x240 */
197	__u8 htmsi_vector[64];
198	/* 0x300 */
199	__u64 intisr_chip0;
200	/* 0x320 */
201	__u64 intisr_chip1;
202	/* edge detection */
203	__u64 last_intirr;
204	/* 0x380 interrupt request register */
205	__u64 intirr;
206	/* 0x3a0 interrupt service register */
207	__u64 intisr;
208	/* 0x3e0 interrupt level polarity selection register,
209	 * 0 for high level tirgger
210	 */
211	__u64 int_polarity;
212};
213
214struct loongarch_gipi_single {
215	__u32 status;
216	__u32 en;
217	__u32 set;
218	__u32 clear;
219	__u64 buf[4];
220};
221
222struct loongarch_gipiState {
223	struct loongarch_gipi_single core[KVM_MAX_CORES];
224};
225
226struct kvm_loongarch_ls3a_extirq_state {
227	union ext_en_r {
228		uint64_t reg_u64[KVM_EXTIOI_IRQS_BITMAP_SIZE / 8];
229		uint32_t reg_u32[KVM_EXTIOI_IRQS_BITMAP_SIZE / 4];
230		uint8_t reg_u8[KVM_EXTIOI_IRQS_BITMAP_SIZE];
231	} ext_en_r;
232	union bounce_r {
233		uint64_t reg_u64[KVM_EXTIOI_IRQS_BITMAP_SIZE / 8];
234		uint32_t reg_u32[KVM_EXTIOI_IRQS_BITMAP_SIZE / 4];
235		uint8_t reg_u8[KVM_EXTIOI_IRQS_BITMAP_SIZE];
236	} bounce_r;
237	union ext_isr_r {
238		uint64_t reg_u64[KVM_EXTIOI_IRQS_BITMAP_SIZE / 8];
239		uint32_t reg_u32[KVM_EXTIOI_IRQS_BITMAP_SIZE / 4];
240		uint8_t reg_u8[KVM_EXTIOI_IRQS_BITMAP_SIZE];
241	} ext_isr_r;
242	union ext_core_isr_r {
243		uint64_t reg_u64[KVM_MAX_CORES][KVM_EXTIOI_IRQS_BITMAP_SIZE / 8];
244		uint32_t reg_u32[KVM_MAX_CORES][KVM_EXTIOI_IRQS_BITMAP_SIZE / 4];
245		uint8_t reg_u8[KVM_MAX_CORES][KVM_EXTIOI_IRQS_BITMAP_SIZE];
246	} ext_core_isr_r;
247	union ip_map_r {
248		uint64_t reg_u64;
249		uint32_t reg_u32[KVM_EXTIOI_IRQS_IPMAP_SIZE / 4];
250		uint8_t reg_u8[KVM_EXTIOI_IRQS_IPMAP_SIZE];
251	} ip_map_r;
252	union core_map_r {
253		uint64_t reg_u64[KVM_EXTIOI_IRQS_COREMAP_SIZE / 8];
254		uint32_t reg_u32[KVM_EXTIOI_IRQS_COREMAP_SIZE / 4];
255		uint8_t reg_u8[KVM_EXTIOI_IRQS_COREMAP_SIZE];
256	} core_map_r;
257	union node_type_r {
258		uint64_t reg_u64[KVM_EXTIOI_IRQS_NODETYPE_SIZE / 4];
259		uint32_t reg_u32[KVM_EXTIOI_IRQS_NODETYPE_SIZE / 2];
260		uint16_t reg_u16[KVM_EXTIOI_IRQS_NODETYPE_SIZE];
261		uint8_t reg_u8[KVM_EXTIOI_IRQS_NODETYPE_SIZE * 2];
262	} node_type_r;
263};
264
265struct loongarch_kvm_irqchip {
266	__u16 chip_id;
267	__u16 len;
268	__u16 vcpu_id;
269	__u16 reserved;
270	char data[0];
271};
272
273#endif /* __LINUX_KVM_LOONGARCH_H */
274