aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/s390x/cpu.c26
-rw-r--r--target/s390x/kvm-stub.c10
-rw-r--r--target/s390x/kvm.c33
-rw-r--r--target/s390x/kvm_s390x.h2
4 files changed, 63 insertions, 8 deletions
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index f42e28ea25..4e1823a3e0 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -347,22 +347,34 @@ unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
{
+ int r = 0;
+
if (kvm_enabled()) {
- return kvm_s390_get_clock(tod_high, tod_low);
+ r = kvm_s390_get_clock_ext(tod_high, tod_low);
+ if (r == -ENXIO) {
+ return kvm_s390_get_clock(tod_high, tod_low);
+ }
+ } else {
+ /* Fixme TCG */
+ *tod_high = 0;
+ *tod_low = 0;
}
- /* Fixme TCG */
- *tod_high = 0;
- *tod_low = 0;
- return 0;
+
+ return r;
}
int s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
{
+ int r = 0;
+
if (kvm_enabled()) {
- return kvm_s390_set_clock(tod_high, tod_low);
+ r = kvm_s390_set_clock_ext(tod_high, tod_low);
+ if (r == -ENXIO) {
+ return kvm_s390_set_clock(tod_high, tod_low);
+ }
}
/* Fixme TCG */
- return 0;
+ return r;
}
int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit)
diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c
index 261e1cdc44..43f02c2d69 100644
--- a/target/s390x/kvm-stub.c
+++ b/target/s390x/kvm-stub.c
@@ -68,11 +68,21 @@ int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
return -ENOSYS;
}
+int kvm_s390_get_clock_ext(uint8_t *tod_high, uint64_t *tod_low)
+{
+ return -ENOSYS;
+}
+
int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
{
return -ENOSYS;
}
+int kvm_s390_set_clock_ext(uint8_t *tod_high, uint64_t *tod_low)
+{
+ return -ENOSYS;
+}
+
void kvm_s390_enable_css_support(S390CPU *cpu)
{
}
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index 7f8c6c4993..d3700fc2c2 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -646,10 +646,26 @@ int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
return kvm_vm_ioctl(kvm_state, KVM_GET_DEVICE_ATTR, &attr);
}
-int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
+int kvm_s390_get_clock_ext(uint8_t *tod_high, uint64_t *tod_low)
{
int r;
+ struct kvm_s390_vm_tod_clock gtod;
+ struct kvm_device_attr attr = {
+ .group = KVM_S390_VM_TOD,
+ .attr = KVM_S390_VM_TOD_EXT,
+ .addr = (uint64_t)&gtod,
+ };
+
+ r = kvm_vm_ioctl(kvm_state, KVM_GET_DEVICE_ATTR, &attr);
+ *tod_high = gtod.epoch_idx;
+ *tod_low = gtod.tod;
+ return r;
+}
+
+int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
+{
+ int r;
struct kvm_device_attr attr = {
.group = KVM_S390_VM_TOD,
.attr = KVM_S390_VM_TOD_LOW,
@@ -666,6 +682,21 @@ int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
}
+int kvm_s390_set_clock_ext(uint8_t *tod_high, uint64_t *tod_low)
+{
+ struct kvm_s390_vm_tod_clock gtod = {
+ .epoch_idx = *tod_high,
+ .tod = *tod_low,
+ };
+ struct kvm_device_attr attr = {
+ .group = KVM_S390_VM_TOD,
+ .attr = KVM_S390_VM_TOD_EXT,
+ .addr = (uint64_t)&gtod,
+ };
+
+ return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
+}
+
/**
* kvm_s390_mem_op:
* @addr: the logical start address in guest memory
diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h
index 2d594bd4ee..501fc5aabd 100644
--- a/target/s390x/kvm_s390x.h
+++ b/target/s390x/kvm_s390x.h
@@ -29,7 +29,9 @@ int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu);
int kvm_s390_get_ri(void);
int kvm_s390_get_gs(void);
int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock);
+int kvm_s390_get_clock_ext(uint8_t *tod_high, uint64_t *tod_clock);
int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock);
+int kvm_s390_set_clock_ext(uint8_t *tod_high, uint64_t *tod_clock);
void kvm_s390_enable_css_support(S390CPU *cpu);
int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
int vq, bool assign);