:Parameters: address of a buffer in user space to store the data (u8) to
 :Returns:   -EFAULT if the given address is not accessible from kernel space;
            -EINVAL if setting the TOD clock extension to != 0 is not supported
+           -EOPNOTSUPP for a PV guest (TOD managed by the ultravisor)
 
 3.2. ATTRIBUTE: KVM_S390_VM_TOD_LOW
 -----------------------------------
 
 :Parameters: address of a buffer in user space to store the data (u64) to
 :Returns:    -EFAULT if the given address is not accessible from kernel space
+            -EOPNOTSUPP for a PV guest (TOD managed by the ultravisor)
 
 3.3. ATTRIBUTE: KVM_S390_VM_TOD_EXT
 -----------------------------------
             (kvm_s390_vm_tod_clock) to
 :Returns:   -EFAULT if the given address is not accessible from kernel space;
            -EINVAL if setting the TOD clock extension to != 0 is not supported
+           -EOPNOTSUPP for a PV guest (TOD managed by the ultravisor)
 
 4. GROUP: KVM_S390_VM_CRYPTO
 ============================
 
        return 0;
 }
 
+static void __kvm_s390_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod);
+
 static int kvm_s390_set_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr)
 {
        struct kvm_s390_vm_tod_clock gtod;
 
        if (!test_kvm_facility(kvm, 139) && gtod.epoch_idx)
                return -EINVAL;
-       kvm_s390_set_tod_clock(kvm, >od);
+       __kvm_s390_set_tod_clock(kvm, >od);
 
        VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x, TOD base: 0x%llx",
                gtod.epoch_idx, gtod.tod);
                           sizeof(gtod.tod)))
                return -EFAULT;
 
-       kvm_s390_set_tod_clock(kvm, >od);
+       __kvm_s390_set_tod_clock(kvm, >od);
        VM_EVENT(kvm, 3, "SET: TOD base: 0x%llx", gtod.tod);
        return 0;
 }
        if (attr->flags)
                return -EINVAL;
 
+       mutex_lock(&kvm->lock);
+       /*
+        * For protected guests, the TOD is managed by the ultravisor, so trying
+        * to change it will never bring the expected results.
+        */
+       if (kvm_s390_pv_is_protected(kvm)) {
+               ret = -EOPNOTSUPP;
+               goto out_unlock;
+       }
+
        switch (attr->attr) {
        case KVM_S390_VM_TOD_EXT:
                ret = kvm_s390_set_tod_ext(kvm, attr);
                ret = -ENXIO;
                break;
        }
+
+out_unlock:
+       mutex_unlock(&kvm->lock);
        return ret;
 }
 
        preempt_enable();
 }
 
-void kvm_s390_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod)
-{
-       mutex_lock(&kvm->lock);
-       __kvm_s390_set_tod_clock(kvm, gtod);
-       mutex_unlock(&kvm->lock);
-}
-
 int kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod)
 {
        if (!mutex_trylock(&kvm->lock))
 
 int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu);
 
 /* implemented in kvm-s390.c */
-void kvm_s390_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod);
 int kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod);
 long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable);
 int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr);