Skip to content

Commit

Permalink
KVM: s390/mm: Make pages accessible before destroying the guest
Browse files Browse the repository at this point in the history
Before we destroy the secure configuration, we better make all
pages accessible again. This also happens during reboot, where we reboot
into a non-secure guest that then can go again into secure mode. As
this "new" secure guest will have a new ID we cannot reuse the old page
state.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
  • Loading branch information
Christian Borntraeger committed Feb 27, 2020
1 parent fa0c5ea commit 1274800
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/s390/include/asm/gmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,5 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start,
void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long dirty_bitmap[4],
unsigned long gaddr, unsigned long vmaddr);
int gmap_mark_unmergeable(void);
void s390_reset_acc(struct mm_struct *mm);
#endif /* _ASM_S390_GMAP_H */
3 changes: 3 additions & 0 deletions arch/s390/kvm/pv.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ int kvm_s390_pv_deinit_vm(struct kvm *kvm, u16 *rc, u16 *rrc)
{
int cc;

/* make all pages accessible before destroying the guest */
s390_reset_acc(kvm->mm);

cc = uv_cmd_nodata(kvm_s390_pv_get_handle(kvm),
UVC_CMD_DESTROY_SEC_CONF, rc, rrc);
WRITE_ONCE(kvm->arch.gmap->guest_handle, 0);
Expand Down
35 changes: 35 additions & 0 deletions arch/s390/mm/gmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2650,3 +2650,38 @@ void s390_reset_cmma(struct mm_struct *mm)
up_write(&mm->mmap_sem);
}
EXPORT_SYMBOL_GPL(s390_reset_cmma);

/*
* make inaccessible pages accessible again
*/
static int __s390_reset_acc(pte_t *ptep, unsigned long addr,
unsigned long next, struct mm_walk *walk)
{
pte_t pte = READ_ONCE(*ptep);

if (pte_present(pte))
WARN_ON_ONCE(uv_convert_from_secure(pte_val(pte) & PAGE_MASK));
return 0;
}

static const struct mm_walk_ops reset_acc_walk_ops = {
.pte_entry = __s390_reset_acc,
};

#include <linux/sched/mm.h>
void s390_reset_acc(struct mm_struct *mm)
{
/*
* we might be called during
* reset: we walk the pages and clear
* close of all kvm file descriptors: we walk the pages and clear
* exit of process on fd closure: vma already gone, do nothing
*/
if (!mmget_not_zero(mm))
return;
down_read(&mm->mmap_sem);
walk_page_range(mm, 0, TASK_SIZE, &reset_acc_walk_ops, NULL);
up_read(&mm->mmap_sem);
mmput(mm);
}
EXPORT_SYMBOL_GPL(s390_reset_acc);

0 comments on commit 1274800

Please sign in to comment.