aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason J. Herne <jjherne@linux.vnet.ibm.com>2014-11-25 09:46:02 -0500
committerChristian Borntraeger <borntraeger@de.ibm.com>2015-01-23 07:25:40 -0500
commit72f250206f0f291190ab7f54e4d92ab211779929 (patch)
tree26e1d8b82e4ff5dd59822f5c849364de4b82d5a1
parent556cc0dab1f65f40b755da556a462ae68d6b57a1 (diff)
KVM: s390: Provide guest TOD Clock Get/Set Controls
Provide controls for setting/getting the guest TOD clock based on the VM attribute interface. Provide TOD and TOD_HIGH vm attributes on s390 for managing guest Time Of Day clock value. TOD_HIGH is presently always set to 0. In the future it will contain a high order expansion of the tod clock value after it overflows the 64-bits of the TOD. Signed-off-by: Jason J. Herne <jjherne@linux.vnet.ibm.com> Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
-rw-r--r--arch/s390/include/asm/kvm_host.h1
-rw-r--r--arch/s390/include/uapi/asm/kvm.h5
-rw-r--r--arch/s390/kvm/kvm-s390.c128
3 files changed, 134 insertions, 0 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index a2dcd0e099f7..8e22aa0f97fd 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -528,6 +528,7 @@ struct kvm_arch{
528 struct mutex ipte_mutex; 528 struct mutex ipte_mutex;
529 spinlock_t start_stop_lock; 529 spinlock_t start_stop_lock;
530 struct kvm_s390_crypto crypto; 530 struct kvm_s390_crypto crypto;
531 u64 epoch;
531}; 532};
532 533
533#define KVM_HVA_ERR_BAD (-1UL) 534#define KVM_HVA_ERR_BAD (-1UL)
diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h
index 7e9165e1bec5..cb64319d3e51 100644
--- a/arch/s390/include/uapi/asm/kvm.h
+++ b/arch/s390/include/uapi/asm/kvm.h
@@ -57,12 +57,17 @@ struct kvm_s390_io_adapter_req {
57 57
58/* kvm attr_group on vm fd */ 58/* kvm attr_group on vm fd */
59#define KVM_S390_VM_MEM_CTRL 0 59#define KVM_S390_VM_MEM_CTRL 0
60#define KVM_S390_VM_TOD 1
60 61
61/* kvm attributes for mem_ctrl */ 62/* kvm attributes for mem_ctrl */
62#define KVM_S390_VM_MEM_ENABLE_CMMA 0 63#define KVM_S390_VM_MEM_ENABLE_CMMA 0
63#define KVM_S390_VM_MEM_CLR_CMMA 1 64#define KVM_S390_VM_MEM_CLR_CMMA 1
64#define KVM_S390_VM_MEM_LIMIT_SIZE 2 65#define KVM_S390_VM_MEM_LIMIT_SIZE 2
65 66
67/* kvm attributes for KVM_S390_VM_TOD */
68#define KVM_S390_VM_TOD_LOW 0
69#define KVM_S390_VM_TOD_HIGH 1
70
66/* for KVM_GET_REGS and KVM_SET_REGS */ 71/* for KVM_GET_REGS and KVM_SET_REGS */
67struct kvm_regs { 72struct kvm_regs {
68 /* general purpose regs for s390 */ 73 /* general purpose regs for s390 */
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 3677b8ca647f..9cf899e9a5d4 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -342,6 +342,113 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
342 return ret; 342 return ret;
343} 343}
344 344
345static int kvm_s390_set_tod_high(struct kvm *kvm, struct kvm_device_attr *attr)
346{
347 u8 gtod_high;
348
349 if (copy_from_user(&gtod_high, (void __user *)attr->addr,
350 sizeof(gtod_high)))
351 return -EFAULT;
352
353 if (gtod_high != 0)
354 return -EINVAL;
355
356 return 0;
357}
358
359static int kvm_s390_set_tod_low(struct kvm *kvm, struct kvm_device_attr *attr)
360{
361 struct kvm_vcpu *cur_vcpu;
362 unsigned int vcpu_idx;
363 u64 host_tod, gtod;
364 int r;
365
366 if (copy_from_user(&gtod, (void __user *)attr->addr, sizeof(gtod)))
367 return -EFAULT;
368
369 r = store_tod_clock(&host_tod);
370 if (r)
371 return r;
372
373 mutex_lock(&kvm->lock);
374 kvm->arch.epoch = gtod - host_tod;
375 kvm_for_each_vcpu(vcpu_idx, cur_vcpu, kvm) {
376 cur_vcpu->arch.sie_block->epoch = kvm->arch.epoch;
377 exit_sie(cur_vcpu);
378 }
379 mutex_unlock(&kvm->lock);
380 return 0;
381}
382
383static int kvm_s390_set_tod(struct kvm *kvm, struct kvm_device_attr *attr)
384{
385 int ret;
386
387 if (attr->flags)
388 return -EINVAL;
389
390 switch (attr->attr) {
391 case KVM_S390_VM_TOD_HIGH:
392 ret = kvm_s390_set_tod_high(kvm, attr);
393 break;
394 case KVM_S390_VM_TOD_LOW:
395 ret = kvm_s390_set_tod_low(kvm, attr);
396 break;
397 default:
398 ret = -ENXIO;
399 break;
400 }
401 return ret;
402}
403
404static int kvm_s390_get_tod_high(struct kvm *kvm, struct kvm_device_attr *attr)
405{
406 u8 gtod_high = 0;
407
408 if (copy_to_user((void __user *)attr->addr, &gtod_high,
409 sizeof(gtod_high)))
410 return -EFAULT;
411
412 return 0;
413}
414
415static int kvm_s390_get_tod_low(struct kvm *kvm, struct kvm_device_attr *attr)
416{
417 u64 host_tod, gtod;
418 int r;
419
420 r = store_tod_clock(&host_tod);
421 if (r)
422 return r;
423
424 gtod = host_tod + kvm->arch.epoch;
425 if (copy_to_user((void __user *)attr->addr, &gtod, sizeof(gtod)))
426 return -EFAULT;
427
428 return 0;
429}
430
431static int kvm_s390_get_tod(struct kvm *kvm, struct kvm_device_attr *attr)
432{
433 int ret;
434
435 if (attr->flags)
436 return -EINVAL;
437
438 switch (attr->attr) {
439 case KVM_S390_VM_TOD_HIGH:
440 ret = kvm_s390_get_tod_high(kvm, attr);
441 break;
442 case KVM_S390_VM_TOD_LOW:
443 ret = kvm_s390_get_tod_low(kvm, attr);
444 break;
445 default:
446 ret = -ENXIO;
447 break;
448 }
449 return ret;
450}
451
345static int kvm_s390_vm_set_attr(struct kvm *kvm, struct kvm_device_attr *attr) 452static int kvm_s390_vm_set_attr(struct kvm *kvm, struct kvm_device_attr *attr)
346{ 453{
347 int ret; 454 int ret;
@@ -350,6 +457,9 @@ static int kvm_s390_vm_set_attr(struct kvm *kvm, struct kvm_device_attr *attr)
350 case KVM_S390_VM_MEM_CTRL: 457 case KVM_S390_VM_MEM_CTRL:
351 ret = kvm_s390_set_mem_control(kvm, attr); 458 ret = kvm_s390_set_mem_control(kvm, attr);
352 break; 459 break;
460 case KVM_S390_VM_TOD:
461 ret = kvm_s390_set_tod(kvm, attr);
462 break;
353 default: 463 default:
354 ret = -ENXIO; 464 ret = -ENXIO;
355 break; 465 break;
@@ -366,6 +476,9 @@ static int kvm_s390_vm_get_attr(struct kvm *kvm, struct kvm_device_attr *attr)
366 case KVM_S390_VM_MEM_CTRL: 476 case KVM_S390_VM_MEM_CTRL:
367 ret = kvm_s390_get_mem_control(kvm, attr); 477 ret = kvm_s390_get_mem_control(kvm, attr);
368 break; 478 break;
479 case KVM_S390_VM_TOD:
480 ret = kvm_s390_get_tod(kvm, attr);
481 break;
369 default: 482 default:
370 ret = -ENXIO; 483 ret = -ENXIO;
371 break; 484 break;
@@ -391,6 +504,17 @@ static int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
391 break; 504 break;
392 } 505 }
393 break; 506 break;
507 case KVM_S390_VM_TOD:
508 switch (attr->attr) {
509 case KVM_S390_VM_TOD_LOW:
510 case KVM_S390_VM_TOD_HIGH:
511 ret = 0;
512 break;
513 default:
514 ret = -ENXIO;
515 break;
516 }
517 break;
394 default: 518 default:
395 ret = -ENXIO; 519 ret = -ENXIO;
396 break; 520 break;
@@ -541,6 +665,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
541 665
542 kvm->arch.css_support = 0; 666 kvm->arch.css_support = 0;
543 kvm->arch.use_irqchip = 0; 667 kvm->arch.use_irqchip = 0;
668 kvm->arch.epoch = 0;
544 669
545 spin_lock_init(&kvm->arch.start_stop_lock); 670 spin_lock_init(&kvm->arch.start_stop_lock);
546 671
@@ -686,6 +811,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
686 811
687void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) 812void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
688{ 813{
814 mutex_lock(&vcpu->kvm->lock);
815 vcpu->arch.sie_block->epoch = vcpu->kvm->arch.epoch;
816 mutex_unlock(&vcpu->kvm->lock);
689 if (!kvm_is_ucontrol(vcpu->kvm)) 817 if (!kvm_is_ucontrol(vcpu->kvm))
690 vcpu->arch.gmap = vcpu->kvm->arch.gmap; 818 vcpu->arch.gmap = vcpu->kvm->arch.gmap;
691} 819}