lkml.org 
[lkml]   [2018]   [Mar]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.15 104/122] KVM: s390: consider epoch index on TOD clock syncs
    Date
    4.15-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: David Hildenbrand <david@redhat.com>

    commit 1575767ef3cf5326701d2ae3075b7732cbc855e4 upstream.

    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: 8fa1696ea781 ("KVM: s390: Multiple Epoch Facility support")
    Cc: stable@vger.kernel.org
    Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
    [use u8 for idx]
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    arch/s390/kvm/kvm-s390.c | 32 +++++++++++++++++++++++++++++---
    1 file changed, 29 insertions(+), 3 deletions(-)

    --- a/arch/s390/kvm/kvm-s390.c
    +++ b/arch/s390/kvm/kvm-s390.c
    @@ -166,6 +166,28 @@ int kvm_arch_hardware_enable(void)
    static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start,
    unsigned long end);

    +static void kvm_clock_sync_scb(struct kvm_s390_sie_block *scb, u64 delta)
    +{
    + u8 delta_idx = 0;
    +
    + /*
    + * The TOD jumps by delta, we have to compensate this by adding
    + * -delta to the epoch.
    + */
    + delta = -delta;
    +
    + /* sign-extension - we're adding to signed values below */
    + if ((s64)delta < 0)
    + delta_idx = -1;
    +
    + scb->epoch += delta;
    + if (scb->ecd & ECD_MEF) {
    + scb->epdx += delta_idx;
    + if (scb->epoch < delta)
    + scb->epdx += 1;
    + }
    +}
    +
    /*
    * This callback is executed during stop_machine(). All CPUs are therefore
    * temporarily stopped. In order not to change guest behavior, we have to
    @@ -181,13 +203,17 @@ static int kvm_clock_sync(struct notifie
    unsigned long long *delta = v;

    list_for_each_entry(kvm, &vm_list, vm_list) {
    - kvm->arch.epoch -= *delta;
    kvm_for_each_vcpu(i, vcpu, kvm) {
    - vcpu->arch.sie_block->epoch -= *delta;
    + kvm_clock_sync_scb(vcpu->arch.sie_block, *delta);
    + if (i == 0) {
    + kvm->arch.epoch = vcpu->arch.sie_block->epoch;
    + kvm->arch.epdx = vcpu->arch.sie_block->epdx;
    + }
    if (vcpu->arch.cputm_enabled)
    vcpu->arch.cputm_start += *delta;
    if (vcpu->arch.vsie_block)
    - vcpu->arch.vsie_block->epoch -= *delta;
    + kvm_clock_sync_scb(vcpu->arch.vsie_block,
    + *delta);
    }
    }
    return NOTIFY_OK;

    \
     
     \ /
      Last update: 2018-03-07 21:22    [W:4.103 / U:0.184 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site