@@ -141,6 +141,267 @@ static int kvm_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
141
141
return RESUME_GUEST ;
142
142
}
143
143
144
+ static int _kvm_getcsr (struct kvm_vcpu * vcpu , unsigned int id , u64 * val )
145
+ {
146
+ unsigned long gintc ;
147
+ struct loongarch_csrs * csr = vcpu -> arch .csr ;
148
+
149
+ if (get_gcsr_flag (id ) & INVALID_GCSR )
150
+ return - EINVAL ;
151
+
152
+ if (id == LOONGARCH_CSR_ESTAT ) {
153
+ /* ESTAT IP0~IP7 get from GINTC */
154
+ gintc = kvm_read_sw_gcsr (csr , LOONGARCH_CSR_GINTC ) & 0xff ;
155
+ * val = kvm_read_sw_gcsr (csr , LOONGARCH_CSR_ESTAT ) | (gintc << 2 );
156
+ return 0 ;
157
+ }
158
+
159
+ /*
160
+ * Get software CSR state since software state is consistent
161
+ * with hardware for synchronous ioctl
162
+ */
163
+ * val = kvm_read_sw_gcsr (csr , id );
164
+
165
+ return 0 ;
166
+ }
167
+
168
+ static int _kvm_setcsr (struct kvm_vcpu * vcpu , unsigned int id , u64 val )
169
+ {
170
+ int ret = 0 , gintc ;
171
+ struct loongarch_csrs * csr = vcpu -> arch .csr ;
172
+
173
+ if (get_gcsr_flag (id ) & INVALID_GCSR )
174
+ return - EINVAL ;
175
+
176
+ if (id == LOONGARCH_CSR_ESTAT ) {
177
+ /* ESTAT IP0~IP7 inject through GINTC */
178
+ gintc = (val >> 2 ) & 0xff ;
179
+ kvm_set_sw_gcsr (csr , LOONGARCH_CSR_GINTC , gintc );
180
+
181
+ gintc = val & ~(0xffUL << 2 );
182
+ kvm_set_sw_gcsr (csr , LOONGARCH_CSR_ESTAT , gintc );
183
+
184
+ return ret ;
185
+ }
186
+
187
+ kvm_write_sw_gcsr (csr , id , val );
188
+
189
+ return ret ;
190
+ }
191
+
192
+ static int kvm_get_one_reg (struct kvm_vcpu * vcpu ,
193
+ const struct kvm_one_reg * reg , u64 * v )
194
+ {
195
+ int id , ret = 0 ;
196
+ u64 type = reg -> id & KVM_REG_LOONGARCH_MASK ;
197
+
198
+ switch (type ) {
199
+ case KVM_REG_LOONGARCH_CSR :
200
+ id = KVM_GET_IOC_CSR_IDX (reg -> id );
201
+ ret = _kvm_getcsr (vcpu , id , v );
202
+ break ;
203
+ case KVM_REG_LOONGARCH_CPUCFG :
204
+ id = KVM_GET_IOC_CPUCFG_IDX (reg -> id );
205
+ if (id >= 0 && id < KVM_MAX_CPUCFG_REGS )
206
+ * v = vcpu -> arch .cpucfg [id ];
207
+ else
208
+ ret = - EINVAL ;
209
+ break ;
210
+ case KVM_REG_LOONGARCH_KVM :
211
+ switch (reg -> id ) {
212
+ case KVM_REG_LOONGARCH_COUNTER :
213
+ * v = drdtime () + vcpu -> kvm -> arch .time_offset ;
214
+ break ;
215
+ default :
216
+ ret = - EINVAL ;
217
+ break ;
218
+ }
219
+ break ;
220
+ default :
221
+ ret = - EINVAL ;
222
+ break ;
223
+ }
224
+
225
+ return ret ;
226
+ }
227
+
228
+ static int kvm_get_reg (struct kvm_vcpu * vcpu , const struct kvm_one_reg * reg )
229
+ {
230
+ int ret = 0 ;
231
+ u64 v , size = reg -> id & KVM_REG_SIZE_MASK ;
232
+
233
+ switch (size ) {
234
+ case KVM_REG_SIZE_U64 :
235
+ ret = kvm_get_one_reg (vcpu , reg , & v );
236
+ if (ret )
237
+ return ret ;
238
+ ret = put_user (v , (u64 __user * )(long )reg -> addr );
239
+ break ;
240
+ default :
241
+ ret = - EINVAL ;
242
+ break ;
243
+ }
244
+
245
+ return ret ;
246
+ }
247
+
248
+ static int kvm_set_one_reg (struct kvm_vcpu * vcpu ,
249
+ const struct kvm_one_reg * reg , u64 v )
250
+ {
251
+ int id , ret = 0 ;
252
+ u64 type = reg -> id & KVM_REG_LOONGARCH_MASK ;
253
+
254
+ switch (type ) {
255
+ case KVM_REG_LOONGARCH_CSR :
256
+ id = KVM_GET_IOC_CSR_IDX (reg -> id );
257
+ ret = _kvm_setcsr (vcpu , id , v );
258
+ break ;
259
+ case KVM_REG_LOONGARCH_CPUCFG :
260
+ id = KVM_GET_IOC_CPUCFG_IDX (reg -> id );
261
+ if (id >= 0 && id < KVM_MAX_CPUCFG_REGS )
262
+ vcpu -> arch .cpucfg [id ] = (u32 )v ;
263
+ else
264
+ ret = - EINVAL ;
265
+ break ;
266
+ case KVM_REG_LOONGARCH_KVM :
267
+ switch (reg -> id ) {
268
+ case KVM_REG_LOONGARCH_COUNTER :
269
+ /*
270
+ * gftoffset is relative with board, not vcpu
271
+ * only set for the first time for smp system
272
+ */
273
+ if (vcpu -> vcpu_id == 0 )
274
+ vcpu -> kvm -> arch .time_offset = (signed long )(v - drdtime ());
275
+ break ;
276
+ case KVM_REG_LOONGARCH_VCPU_RESET :
277
+ kvm_reset_timer (vcpu );
278
+ memset (& vcpu -> arch .irq_pending , 0 , sizeof (vcpu -> arch .irq_pending ));
279
+ memset (& vcpu -> arch .irq_clear , 0 , sizeof (vcpu -> arch .irq_clear ));
280
+ break ;
281
+ default :
282
+ ret = - EINVAL ;
283
+ break ;
284
+ }
285
+ break ;
286
+ default :
287
+ ret = - EINVAL ;
288
+ break ;
289
+ }
290
+
291
+ return ret ;
292
+ }
293
+
294
+ static int kvm_set_reg (struct kvm_vcpu * vcpu , const struct kvm_one_reg * reg )
295
+ {
296
+ int ret = 0 ;
297
+ u64 v , size = reg -> id & KVM_REG_SIZE_MASK ;
298
+
299
+ switch (size ) {
300
+ case KVM_REG_SIZE_U64 :
301
+ ret = get_user (v , (u64 __user * )(long )reg -> addr );
302
+ if (ret )
303
+ return ret ;
304
+ break ;
305
+ default :
306
+ return - EINVAL ;
307
+ }
308
+
309
+ return kvm_set_one_reg (vcpu , reg , v );
310
+ }
311
+
312
+ int kvm_arch_vcpu_ioctl_get_sregs (struct kvm_vcpu * vcpu , struct kvm_sregs * sregs )
313
+ {
314
+ return - ENOIOCTLCMD ;
315
+ }
316
+
317
+ int kvm_arch_vcpu_ioctl_set_sregs (struct kvm_vcpu * vcpu , struct kvm_sregs * sregs )
318
+ {
319
+ return - ENOIOCTLCMD ;
320
+ }
321
+
322
+ int kvm_arch_vcpu_ioctl_get_regs (struct kvm_vcpu * vcpu , struct kvm_regs * regs )
323
+ {
324
+ int i ;
325
+
326
+ for (i = 0 ; i < ARRAY_SIZE (vcpu -> arch .gprs ); i ++ )
327
+ regs -> gpr [i ] = vcpu -> arch .gprs [i ];
328
+
329
+ regs -> pc = vcpu -> arch .pc ;
330
+
331
+ return 0 ;
332
+ }
333
+
334
+ int kvm_arch_vcpu_ioctl_set_regs (struct kvm_vcpu * vcpu , struct kvm_regs * regs )
335
+ {
336
+ int i ;
337
+
338
+ for (i = 1 ; i < ARRAY_SIZE (vcpu -> arch .gprs ); i ++ )
339
+ vcpu -> arch .gprs [i ] = regs -> gpr [i ];
340
+
341
+ vcpu -> arch .gprs [0 ] = 0 ; /* zero is special, and cannot be set. */
342
+ vcpu -> arch .pc = regs -> pc ;
343
+
344
+ return 0 ;
345
+ }
346
+
347
+ static int kvm_vcpu_ioctl_enable_cap (struct kvm_vcpu * vcpu ,
348
+ struct kvm_enable_cap * cap )
349
+ {
350
+ /* FPU is enabled by default, will support LSX/LASX later. */
351
+ return - EINVAL ;
352
+ }
353
+
354
+ long kvm_arch_vcpu_ioctl (struct file * filp ,
355
+ unsigned int ioctl , unsigned long arg )
356
+ {
357
+ long r ;
358
+ void __user * argp = (void __user * )arg ;
359
+ struct kvm_vcpu * vcpu = filp -> private_data ;
360
+
361
+ /*
362
+ * Only software CSR should be modified
363
+ *
364
+ * If any hardware CSR register is modified, vcpu_load/vcpu_put pair
365
+ * should be used. Since CSR registers owns by this vcpu, if switch
366
+ * to other vcpus, other vcpus need reload CSR registers.
367
+ *
368
+ * If software CSR is modified, bit KVM_LARCH_HWCSR_USABLE should
369
+ * be clear in vcpu->arch.aux_inuse, and vcpu_load will check
370
+ * aux_inuse flag and reload CSR registers form software.
371
+ */
372
+
373
+ switch (ioctl ) {
374
+ case KVM_SET_ONE_REG :
375
+ case KVM_GET_ONE_REG : {
376
+ struct kvm_one_reg reg ;
377
+
378
+ r = - EFAULT ;
379
+ if (copy_from_user (& reg , argp , sizeof (reg )))
380
+ break ;
381
+ if (ioctl == KVM_SET_ONE_REG ) {
382
+ r = kvm_set_reg (vcpu , & reg );
383
+ vcpu -> arch .aux_inuse &= ~KVM_LARCH_HWCSR_USABLE ;
384
+ } else
385
+ r = kvm_get_reg (vcpu , & reg );
386
+ break ;
387
+ }
388
+ case KVM_ENABLE_CAP : {
389
+ struct kvm_enable_cap cap ;
390
+
391
+ r = - EFAULT ;
392
+ if (copy_from_user (& cap , argp , sizeof (cap )))
393
+ break ;
394
+ r = kvm_vcpu_ioctl_enable_cap (vcpu , & cap );
395
+ break ;
396
+ }
397
+ default :
398
+ r = - ENOIOCTLCMD ;
399
+ break ;
400
+ }
401
+
402
+ return r ;
403
+ }
404
+
144
405
int kvm_arch_vcpu_precreate (struct kvm * kvm , unsigned int id )
145
406
{
146
407
return 0 ;
0 commit comments