aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/time.c
diff options
context:
space:
mode:
authorFan Zhang <zhangfan@linux.vnet.ibm.com>2015-05-13 04:58:41 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2015-08-04 08:38:37 -0400
commitfdf036507f1fc036d5a06753e9e8b13f46de73e8 (patch)
treeb9533136fecbd73e24f9e955edcd261060ee5957 /arch/s390/kernel/time.c
parent554726d33c20791653dbd1c047c83f93459bc586 (diff)
KVM: s390: host STP toleration for VMs
If the host has STP enabled, the TOD of the host will be changed during synchronization phases. These are performed during a stop_machine() call. As the guest TOD is based on the host TOD, we have to make sure that: - no VCPU is in the SIE (implicitly guaranteed via stop_machine()) - manual guest TOD calculations are not affected "Epoch" is the guest TOD clock delta to the host TOD clock. We have to adjust that value during the STP synchronization and make sure that code that accesses the epoch won't get interrupted in between (via disabling preemption). Signed-off-by: Fan Zhang <zhangfan@linux.vnet.ibm.com> Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/time.c')
-rw-r--r--arch/s390/kernel/time.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 9e733d965e08..627887b075a7 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -58,6 +58,9 @@ EXPORT_SYMBOL_GPL(sched_clock_base_cc);
58 58
59static DEFINE_PER_CPU(struct clock_event_device, comparators); 59static DEFINE_PER_CPU(struct clock_event_device, comparators);
60 60
61ATOMIC_NOTIFIER_HEAD(s390_epoch_delta_notifier);
62EXPORT_SYMBOL(s390_epoch_delta_notifier);
63
61/* 64/*
62 * Scheduler clock - returns current time in nanosec units. 65 * Scheduler clock - returns current time in nanosec units.
63 */ 66 */
@@ -752,7 +755,7 @@ static void clock_sync_cpu(struct clock_sync_data *sync)
752static int etr_sync_clock(void *data) 755static int etr_sync_clock(void *data)
753{ 756{
754 static int first; 757 static int first;
755 unsigned long long clock, old_clock, delay, delta; 758 unsigned long long clock, old_clock, clock_delta, delay, delta;
756 struct clock_sync_data *etr_sync; 759 struct clock_sync_data *etr_sync;
757 struct etr_aib *sync_port, *aib; 760 struct etr_aib *sync_port, *aib;
758 int port; 761 int port;
@@ -789,6 +792,9 @@ static int etr_sync_clock(void *data)
789 delay = (unsigned long long) 792 delay = (unsigned long long)
790 (aib->edf2.etv - sync_port->edf2.etv) << 32; 793 (aib->edf2.etv - sync_port->edf2.etv) << 32;
791 delta = adjust_time(old_clock, clock, delay); 794 delta = adjust_time(old_clock, clock, delay);
795 clock_delta = clock - old_clock;
796 atomic_notifier_call_chain(&s390_epoch_delta_notifier, 0,
797 &clock_delta);
792 etr_sync->fixup_cc = delta; 798 etr_sync->fixup_cc = delta;
793 fixup_clock_comparator(delta); 799 fixup_clock_comparator(delta);
794 /* Verify that the clock is properly set. */ 800 /* Verify that the clock is properly set. */
@@ -1526,7 +1532,7 @@ void stp_island_check(void)
1526static int stp_sync_clock(void *data) 1532static int stp_sync_clock(void *data)
1527{ 1533{
1528 static int first; 1534 static int first;
1529 unsigned long long old_clock, delta; 1535 unsigned long long old_clock, delta, new_clock, clock_delta;
1530 struct clock_sync_data *stp_sync; 1536 struct clock_sync_data *stp_sync;
1531 int rc; 1537 int rc;
1532 1538
@@ -1551,7 +1557,11 @@ static int stp_sync_clock(void *data)
1551 old_clock = get_tod_clock(); 1557 old_clock = get_tod_clock();
1552 rc = chsc_sstpc(stp_page, STP_OP_SYNC, 0); 1558 rc = chsc_sstpc(stp_page, STP_OP_SYNC, 0);
1553 if (rc == 0) { 1559 if (rc == 0) {
1554 delta = adjust_time(old_clock, get_tod_clock(), 0); 1560 new_clock = get_tod_clock();
1561 delta = adjust_time(old_clock, new_clock, 0);
1562 clock_delta = new_clock - old_clock;
1563 atomic_notifier_call_chain(&s390_epoch_delta_notifier,
1564 0, &clock_delta);
1555 fixup_clock_comparator(delta); 1565 fixup_clock_comparator(delta);
1556 rc = chsc_sstpi(stp_page, &stp_info, 1566 rc = chsc_sstpi(stp_page, &stp_info,
1557 sizeof(struct stp_sstpi)); 1567 sizeof(struct stp_sstpi));