Skip to content

Commit 1575767

Browse files
davidhildenbrandborntraeger
authored andcommitted
KVM: s390: consider epoch index on TOD clock syncs
For now, we don't take care of over/underflows. Especially underflows are critical: Assume the epoch is currently 0 and we get a sync request for delta=1, meaning the TOD is moved forward by 1 and we have to fix it up by subtracting 1 from the epoch. Right now, this will leave the epoch index untouched, resulting in epoch=-1, epoch_idx=0, which is wrong. We have to take care of over and underflows, also for the VSIE case. So let's factor out calculation into a separate function. Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20180207114647.6220-5-david@redhat.com> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> Fixes: 8fa1696 ("KVM: s390: Multiple Epoch Facility support") Cc: stable@vger.kernel.org Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> [use u8 for idx]
1 parent d16b52c commit 1575767

File tree

1 file changed

+29
-3
lines changed

1 file changed

+29
-3
lines changed

arch/s390/kvm/kvm-s390.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,28 @@ int kvm_arch_hardware_enable(void)
179179
static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start,
180180
unsigned long end);
181181

182+
static void kvm_clock_sync_scb(struct kvm_s390_sie_block *scb, u64 delta)
183+
{
184+
u8 delta_idx = 0;
185+
186+
/*
187+
* The TOD jumps by delta, we have to compensate this by adding
188+
* -delta to the epoch.
189+
*/
190+
delta = -delta;
191+
192+
/* sign-extension - we're adding to signed values below */
193+
if ((s64)delta < 0)
194+
delta_idx = -1;
195+
196+
scb->epoch += delta;
197+
if (scb->ecd & ECD_MEF) {
198+
scb->epdx += delta_idx;
199+
if (scb->epoch < delta)
200+
scb->epdx += 1;
201+
}
202+
}
203+
182204
/*
183205
* This callback is executed during stop_machine(). All CPUs are therefore
184206
* temporarily stopped. In order not to change guest behavior, we have to
@@ -194,13 +216,17 @@ static int kvm_clock_sync(struct notifier_block *notifier, unsigned long val,
194216
unsigned long long *delta = v;
195217

196218
list_for_each_entry(kvm, &vm_list, vm_list) {
197-
kvm->arch.epoch -= *delta;
198219
kvm_for_each_vcpu(i, vcpu, kvm) {
199-
vcpu->arch.sie_block->epoch -= *delta;
220+
kvm_clock_sync_scb(vcpu->arch.sie_block, *delta);
221+
if (i == 0) {
222+
kvm->arch.epoch = vcpu->arch.sie_block->epoch;
223+
kvm->arch.epdx = vcpu->arch.sie_block->epdx;
224+
}
200225
if (vcpu->arch.cputm_enabled)
201226
vcpu->arch.cputm_start += *delta;
202227
if (vcpu->arch.vsie_block)
203-
vcpu->arch.vsie_block->epoch -= *delta;
228+
kvm_clock_sync_scb(vcpu->arch.vsie_block,
229+
*delta);
204230
}
205231
}
206232
return NOTIFY_OK;

0 commit comments

Comments
 (0)