1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
7 #include <linux/module.h>
8 #include <linux/kvm_host.h>
9 #include <asm/cacheflush.h>
10 #include <asm/cpufeature.h>
11 #include <asm/kvm_csr.h>
12 #include <asm/kvm_eiointc.h>
13 #include <asm/kvm_pch_pic.h>
16 unsigned long vpid_mask
;
17 struct kvm_world_switch
*kvm_loongarch_ops
;
18 static int gcsr_flag
[CSR_MAX_NUMS
];
19 static struct kvm_context __percpu
*vmcs
;
21 int get_gcsr_flag(int csr
)
23 if (csr
< CSR_MAX_NUMS
)
24 return gcsr_flag
[csr
];
29 static inline void set_gcsr_sw_flag(int csr
)
31 if (csr
< CSR_MAX_NUMS
)
32 gcsr_flag
[csr
] |= SW_GCSR
;
35 static inline void set_gcsr_hw_flag(int csr
)
37 if (csr
< CSR_MAX_NUMS
)
38 gcsr_flag
[csr
] |= HW_GCSR
;
42 * The default value of gcsr_flag[CSR] is 0, and we use this
43 * function to set the flag to 1 (SW_GCSR) or 2 (HW_GCSR) if the
44 * gcsr is software or hardware. It will be used by get/set_gcsr,
45 * if gcsr_flag is HW we should use gcsrrd/gcsrwr to access it,
46 * else use software csr to emulate it.
48 static void kvm_init_gcsr_flag(void)
50 set_gcsr_hw_flag(LOONGARCH_CSR_CRMD
);
51 set_gcsr_hw_flag(LOONGARCH_CSR_PRMD
);
52 set_gcsr_hw_flag(LOONGARCH_CSR_EUEN
);
53 set_gcsr_hw_flag(LOONGARCH_CSR_MISC
);
54 set_gcsr_hw_flag(LOONGARCH_CSR_ECFG
);
55 set_gcsr_hw_flag(LOONGARCH_CSR_ESTAT
);
56 set_gcsr_hw_flag(LOONGARCH_CSR_ERA
);
57 set_gcsr_hw_flag(LOONGARCH_CSR_BADV
);
58 set_gcsr_hw_flag(LOONGARCH_CSR_BADI
);
59 set_gcsr_hw_flag(LOONGARCH_CSR_EENTRY
);
60 set_gcsr_hw_flag(LOONGARCH_CSR_TLBIDX
);
61 set_gcsr_hw_flag(LOONGARCH_CSR_TLBEHI
);
62 set_gcsr_hw_flag(LOONGARCH_CSR_TLBELO0
);
63 set_gcsr_hw_flag(LOONGARCH_CSR_TLBELO1
);
64 set_gcsr_hw_flag(LOONGARCH_CSR_ASID
);
65 set_gcsr_hw_flag(LOONGARCH_CSR_PGDL
);
66 set_gcsr_hw_flag(LOONGARCH_CSR_PGDH
);
67 set_gcsr_hw_flag(LOONGARCH_CSR_PGD
);
68 set_gcsr_hw_flag(LOONGARCH_CSR_PWCTL0
);
69 set_gcsr_hw_flag(LOONGARCH_CSR_PWCTL1
);
70 set_gcsr_hw_flag(LOONGARCH_CSR_STLBPGSIZE
);
71 set_gcsr_hw_flag(LOONGARCH_CSR_RVACFG
);
72 set_gcsr_hw_flag(LOONGARCH_CSR_CPUID
);
73 set_gcsr_hw_flag(LOONGARCH_CSR_PRCFG1
);
74 set_gcsr_hw_flag(LOONGARCH_CSR_PRCFG2
);
75 set_gcsr_hw_flag(LOONGARCH_CSR_PRCFG3
);
76 set_gcsr_hw_flag(LOONGARCH_CSR_KS0
);
77 set_gcsr_hw_flag(LOONGARCH_CSR_KS1
);
78 set_gcsr_hw_flag(LOONGARCH_CSR_KS2
);
79 set_gcsr_hw_flag(LOONGARCH_CSR_KS3
);
80 set_gcsr_hw_flag(LOONGARCH_CSR_KS4
);
81 set_gcsr_hw_flag(LOONGARCH_CSR_KS5
);
82 set_gcsr_hw_flag(LOONGARCH_CSR_KS6
);
83 set_gcsr_hw_flag(LOONGARCH_CSR_KS7
);
84 set_gcsr_hw_flag(LOONGARCH_CSR_TMID
);
85 set_gcsr_hw_flag(LOONGARCH_CSR_TCFG
);
86 set_gcsr_hw_flag(LOONGARCH_CSR_TVAL
);
87 set_gcsr_hw_flag(LOONGARCH_CSR_TINTCLR
);
88 set_gcsr_hw_flag(LOONGARCH_CSR_CNTC
);
89 set_gcsr_hw_flag(LOONGARCH_CSR_LLBCTL
);
90 set_gcsr_hw_flag(LOONGARCH_CSR_TLBRENTRY
);
91 set_gcsr_hw_flag(LOONGARCH_CSR_TLBRBADV
);
92 set_gcsr_hw_flag(LOONGARCH_CSR_TLBRERA
);
93 set_gcsr_hw_flag(LOONGARCH_CSR_TLBRSAVE
);
94 set_gcsr_hw_flag(LOONGARCH_CSR_TLBRELO0
);
95 set_gcsr_hw_flag(LOONGARCH_CSR_TLBRELO1
);
96 set_gcsr_hw_flag(LOONGARCH_CSR_TLBREHI
);
97 set_gcsr_hw_flag(LOONGARCH_CSR_TLBRPRMD
);
98 set_gcsr_hw_flag(LOONGARCH_CSR_DMWIN0
);
99 set_gcsr_hw_flag(LOONGARCH_CSR_DMWIN1
);
100 set_gcsr_hw_flag(LOONGARCH_CSR_DMWIN2
);
101 set_gcsr_hw_flag(LOONGARCH_CSR_DMWIN3
);
103 set_gcsr_sw_flag(LOONGARCH_CSR_IMPCTL1
);
104 set_gcsr_sw_flag(LOONGARCH_CSR_IMPCTL2
);
105 set_gcsr_sw_flag(LOONGARCH_CSR_MERRCTL
);
106 set_gcsr_sw_flag(LOONGARCH_CSR_MERRINFO1
);
107 set_gcsr_sw_flag(LOONGARCH_CSR_MERRINFO2
);
108 set_gcsr_sw_flag(LOONGARCH_CSR_MERRENTRY
);
109 set_gcsr_sw_flag(LOONGARCH_CSR_MERRERA
);
110 set_gcsr_sw_flag(LOONGARCH_CSR_MERRSAVE
);
111 set_gcsr_sw_flag(LOONGARCH_CSR_CTAG
);
112 set_gcsr_sw_flag(LOONGARCH_CSR_DEBUG
);
113 set_gcsr_sw_flag(LOONGARCH_CSR_DERA
);
114 set_gcsr_sw_flag(LOONGARCH_CSR_DESAVE
);
116 set_gcsr_sw_flag(LOONGARCH_CSR_FWPC
);
117 set_gcsr_sw_flag(LOONGARCH_CSR_FWPS
);
118 set_gcsr_sw_flag(LOONGARCH_CSR_MWPC
);
119 set_gcsr_sw_flag(LOONGARCH_CSR_MWPS
);
121 set_gcsr_sw_flag(LOONGARCH_CSR_DB0ADDR
);
122 set_gcsr_sw_flag(LOONGARCH_CSR_DB0MASK
);
123 set_gcsr_sw_flag(LOONGARCH_CSR_DB0CTRL
);
124 set_gcsr_sw_flag(LOONGARCH_CSR_DB0ASID
);
125 set_gcsr_sw_flag(LOONGARCH_CSR_DB1ADDR
);
126 set_gcsr_sw_flag(LOONGARCH_CSR_DB1MASK
);
127 set_gcsr_sw_flag(LOONGARCH_CSR_DB1CTRL
);
128 set_gcsr_sw_flag(LOONGARCH_CSR_DB1ASID
);
129 set_gcsr_sw_flag(LOONGARCH_CSR_DB2ADDR
);
130 set_gcsr_sw_flag(LOONGARCH_CSR_DB2MASK
);
131 set_gcsr_sw_flag(LOONGARCH_CSR_DB2CTRL
);
132 set_gcsr_sw_flag(LOONGARCH_CSR_DB2ASID
);
133 set_gcsr_sw_flag(LOONGARCH_CSR_DB3ADDR
);
134 set_gcsr_sw_flag(LOONGARCH_CSR_DB3MASK
);
135 set_gcsr_sw_flag(LOONGARCH_CSR_DB3CTRL
);
136 set_gcsr_sw_flag(LOONGARCH_CSR_DB3ASID
);
137 set_gcsr_sw_flag(LOONGARCH_CSR_DB4ADDR
);
138 set_gcsr_sw_flag(LOONGARCH_CSR_DB4MASK
);
139 set_gcsr_sw_flag(LOONGARCH_CSR_DB4CTRL
);
140 set_gcsr_sw_flag(LOONGARCH_CSR_DB4ASID
);
141 set_gcsr_sw_flag(LOONGARCH_CSR_DB5ADDR
);
142 set_gcsr_sw_flag(LOONGARCH_CSR_DB5MASK
);
143 set_gcsr_sw_flag(LOONGARCH_CSR_DB5CTRL
);
144 set_gcsr_sw_flag(LOONGARCH_CSR_DB5ASID
);
145 set_gcsr_sw_flag(LOONGARCH_CSR_DB6ADDR
);
146 set_gcsr_sw_flag(LOONGARCH_CSR_DB6MASK
);
147 set_gcsr_sw_flag(LOONGARCH_CSR_DB6CTRL
);
148 set_gcsr_sw_flag(LOONGARCH_CSR_DB6ASID
);
149 set_gcsr_sw_flag(LOONGARCH_CSR_DB7ADDR
);
150 set_gcsr_sw_flag(LOONGARCH_CSR_DB7MASK
);
151 set_gcsr_sw_flag(LOONGARCH_CSR_DB7CTRL
);
152 set_gcsr_sw_flag(LOONGARCH_CSR_DB7ASID
);
154 set_gcsr_sw_flag(LOONGARCH_CSR_IB0ADDR
);
155 set_gcsr_sw_flag(LOONGARCH_CSR_IB0MASK
);
156 set_gcsr_sw_flag(LOONGARCH_CSR_IB0CTRL
);
157 set_gcsr_sw_flag(LOONGARCH_CSR_IB0ASID
);
158 set_gcsr_sw_flag(LOONGARCH_CSR_IB1ADDR
);
159 set_gcsr_sw_flag(LOONGARCH_CSR_IB1MASK
);
160 set_gcsr_sw_flag(LOONGARCH_CSR_IB1CTRL
);
161 set_gcsr_sw_flag(LOONGARCH_CSR_IB1ASID
);
162 set_gcsr_sw_flag(LOONGARCH_CSR_IB2ADDR
);
163 set_gcsr_sw_flag(LOONGARCH_CSR_IB2MASK
);
164 set_gcsr_sw_flag(LOONGARCH_CSR_IB2CTRL
);
165 set_gcsr_sw_flag(LOONGARCH_CSR_IB2ASID
);
166 set_gcsr_sw_flag(LOONGARCH_CSR_IB3ADDR
);
167 set_gcsr_sw_flag(LOONGARCH_CSR_IB3MASK
);
168 set_gcsr_sw_flag(LOONGARCH_CSR_IB3CTRL
);
169 set_gcsr_sw_flag(LOONGARCH_CSR_IB3ASID
);
170 set_gcsr_sw_flag(LOONGARCH_CSR_IB4ADDR
);
171 set_gcsr_sw_flag(LOONGARCH_CSR_IB4MASK
);
172 set_gcsr_sw_flag(LOONGARCH_CSR_IB4CTRL
);
173 set_gcsr_sw_flag(LOONGARCH_CSR_IB4ASID
);
174 set_gcsr_sw_flag(LOONGARCH_CSR_IB5ADDR
);
175 set_gcsr_sw_flag(LOONGARCH_CSR_IB5MASK
);
176 set_gcsr_sw_flag(LOONGARCH_CSR_IB5CTRL
);
177 set_gcsr_sw_flag(LOONGARCH_CSR_IB5ASID
);
178 set_gcsr_sw_flag(LOONGARCH_CSR_IB6ADDR
);
179 set_gcsr_sw_flag(LOONGARCH_CSR_IB6MASK
);
180 set_gcsr_sw_flag(LOONGARCH_CSR_IB6CTRL
);
181 set_gcsr_sw_flag(LOONGARCH_CSR_IB6ASID
);
182 set_gcsr_sw_flag(LOONGARCH_CSR_IB7ADDR
);
183 set_gcsr_sw_flag(LOONGARCH_CSR_IB7MASK
);
184 set_gcsr_sw_flag(LOONGARCH_CSR_IB7CTRL
);
185 set_gcsr_sw_flag(LOONGARCH_CSR_IB7ASID
);
187 set_gcsr_sw_flag(LOONGARCH_CSR_PERFCTRL0
);
188 set_gcsr_sw_flag(LOONGARCH_CSR_PERFCNTR0
);
189 set_gcsr_sw_flag(LOONGARCH_CSR_PERFCTRL1
);
190 set_gcsr_sw_flag(LOONGARCH_CSR_PERFCNTR1
);
191 set_gcsr_sw_flag(LOONGARCH_CSR_PERFCTRL2
);
192 set_gcsr_sw_flag(LOONGARCH_CSR_PERFCNTR2
);
193 set_gcsr_sw_flag(LOONGARCH_CSR_PERFCTRL3
);
194 set_gcsr_sw_flag(LOONGARCH_CSR_PERFCNTR3
);
197 static void kvm_update_vpid(struct kvm_vcpu
*vcpu
, int cpu
)
200 struct kvm_context
*context
;
202 context
= per_cpu_ptr(vcpu
->kvm
->arch
.vmcs
, cpu
);
203 vpid
= context
->vpid_cache
+ 1;
204 if (!(vpid
& vpid_mask
)) {
205 /* finish round of vpid loop */
207 vpid
= vpid_mask
+ 1;
209 ++vpid
; /* vpid 0 reserved for root */
211 /* start new vpid cycle */
215 context
->vpid_cache
= vpid
;
216 vcpu
->arch
.vpid
= vpid
;
219 void kvm_check_vpid(struct kvm_vcpu
*vcpu
)
223 unsigned long ver
, old
, vpid
;
224 struct kvm_context
*context
;
226 cpu
= smp_processor_id();
228 * Are we entering guest context on a different CPU to last time?
229 * If so, the vCPU's guest TLB state on this CPU may be stale.
231 context
= per_cpu_ptr(vcpu
->kvm
->arch
.vmcs
, cpu
);
232 migrated
= (vcpu
->cpu
!= cpu
);
235 * Check if our vpid is of an older version
237 * We also discard the stored vpid if we've executed on
238 * another CPU, as the guest mappings may have changed without
239 * hypervisor knowledge.
241 ver
= vcpu
->arch
.vpid
& ~vpid_mask
;
242 old
= context
->vpid_cache
& ~vpid_mask
;
243 if (migrated
|| (ver
!= old
)) {
244 kvm_update_vpid(vcpu
, cpu
);
245 trace_kvm_vpid_change(vcpu
, vcpu
->arch
.vpid
);
247 kvm_clear_request(KVM_REQ_TLB_FLUSH_GPA
, vcpu
);
250 /* Restore GSTAT(0x50).vpid */
251 vpid
= (vcpu
->arch
.vpid
& vpid_mask
) << CSR_GSTAT_GID_SHIFT
;
252 change_csr_gstat(vpid_mask
<< CSR_GSTAT_GID_SHIFT
, vpid
);
255 void kvm_init_vmcs(struct kvm
*kvm
)
257 kvm
->arch
.vmcs
= vmcs
;
260 long kvm_arch_dev_ioctl(struct file
*filp
,
261 unsigned int ioctl
, unsigned long arg
)
266 int kvm_arch_enable_virtualization_cpu(void)
268 unsigned long env
, gcfg
= 0;
270 env
= read_csr_gcfg();
272 /* First init gcfg, gstat, gintc, gtlbc. All guest use the same config */
276 clear_csr_gtlbc(CSR_GTLBC_USETGID
| CSR_GTLBC_TOTI
);
279 * Enable virtualization features granting guest direct control of
281 * GCI=2: Trap on init or unimplement cache instruction.
282 * TORU=0: Trap on Root Unimplement.
283 * CACTRL=1: Root control cache.
284 * TOP=0: Trap on Previlege.
285 * TOE=0: Trap on Exception.
286 * TIT=0: Trap on Timer.
288 if (env
& CSR_GCFG_GCIP_ALL
)
289 gcfg
|= CSR_GCFG_GCI_SECURE
;
290 if (env
& CSR_GCFG_MATC_ROOT
)
291 gcfg
|= CSR_GCFG_MATC_ROOT
;
293 write_csr_gcfg(gcfg
);
297 /* Enable using TGID */
298 set_csr_gtlbc(CSR_GTLBC_USETGID
);
299 kvm_debug("GCFG:%lx GSTAT:%lx GINTC:%lx GTLBC:%lx",
300 read_csr_gcfg(), read_csr_gstat(), read_csr_gintc(), read_csr_gtlbc());
305 void kvm_arch_disable_virtualization_cpu(void)
310 clear_csr_gtlbc(CSR_GTLBC_USETGID
| CSR_GTLBC_TOTI
);
312 /* Flush any remaining guest TLB entries */
316 static int kvm_loongarch_env_init(void)
320 struct kvm_context
*context
;
322 vmcs
= alloc_percpu(struct kvm_context
);
324 pr_err("kvm: failed to allocate percpu kvm_context\n");
328 kvm_loongarch_ops
= kzalloc(sizeof(*kvm_loongarch_ops
), GFP_KERNEL
);
329 if (!kvm_loongarch_ops
) {
336 * PGD register is shared between root kernel and kvm hypervisor.
337 * So world switch entry should be in DMW area rather than TLB area
338 * to avoid page fault reenter.
340 * In future if hardware pagetable walking is supported, we won't
341 * need to copy world switch code to DMW area.
343 order
= get_order(kvm_exception_size
+ kvm_enter_guest_size
);
344 addr
= (void *)__get_free_pages(GFP_KERNEL
, order
);
348 kfree(kvm_loongarch_ops
);
349 kvm_loongarch_ops
= NULL
;
353 memcpy(addr
, kvm_exc_entry
, kvm_exception_size
);
354 memcpy(addr
+ kvm_exception_size
, kvm_enter_guest
, kvm_enter_guest_size
);
355 flush_icache_range((unsigned long)addr
, (unsigned long)addr
+ kvm_exception_size
+ kvm_enter_guest_size
);
356 kvm_loongarch_ops
->exc_entry
= addr
;
357 kvm_loongarch_ops
->enter_guest
= addr
+ kvm_exception_size
;
358 kvm_loongarch_ops
->page_order
= order
;
360 vpid_mask
= read_csr_gstat();
361 vpid_mask
= (vpid_mask
& CSR_GSTAT_GIDBIT
) >> CSR_GSTAT_GIDBIT_SHIFT
;
363 vpid_mask
= GENMASK(vpid_mask
- 1, 0);
365 for_each_possible_cpu(cpu
) {
366 context
= per_cpu_ptr(vmcs
, cpu
);
367 context
->vpid_cache
= vpid_mask
+ 1;
368 context
->last_vcpu
= NULL
;
371 kvm_init_gcsr_flag();
373 /* Register LoongArch IPI interrupt controller interface. */
374 ret
= kvm_loongarch_register_ipi_device();
378 /* Register LoongArch EIOINTC interrupt controller interface. */
379 ret
= kvm_loongarch_register_eiointc_device();
383 /* Register LoongArch PCH-PIC interrupt controller interface. */
384 ret
= kvm_loongarch_register_pch_pic_device();
389 static void kvm_loongarch_env_exit(void)
396 if (kvm_loongarch_ops
) {
397 if (kvm_loongarch_ops
->exc_entry
) {
398 addr
= (unsigned long)kvm_loongarch_ops
->exc_entry
;
399 free_pages(addr
, kvm_loongarch_ops
->page_order
);
401 kfree(kvm_loongarch_ops
);
405 static int kvm_loongarch_init(void)
410 kvm_info("Hardware virtualization not available\n");
413 r
= kvm_loongarch_env_init();
417 return kvm_init(sizeof(struct kvm_vcpu
), 0, THIS_MODULE
);
420 static void kvm_loongarch_exit(void)
423 kvm_loongarch_env_exit();
426 module_init(kvm_loongarch_init
);
427 module_exit(kvm_loongarch_exit
);
430 static const struct cpu_feature kvm_feature
[] = {
431 { .feature
= cpu_feature(LOONGARCH_LVZ
) },
434 MODULE_DEVICE_TABLE(cpu
, kvm_feature
);