Skip to content

Commit a12cc7e

Browse files
author
Claudio Imbrenda
committed
KVM: s390: vsie: Fix guest page tables protection
When shadowing, the guest page tables are write-protected, in order to trap changes and properly unshadow the shadow mapping for the nested guest. Already shadowed levels are skipped, so that only the needed levels are write protected. Currently the levels that get write protected are exactly one level too deep: the last level (nested guest memory) gets protected in the wrong way, and will be protected again correctly a few lines afterwards; most importantly, the highest non-shadowed level does *not* get write protected. Moreover, if the nested guest is running in a real address space, there are no DAT tables to shadow. Write protect the correct levels, so that all the levels that need to be protected are protected, and avoid double protecting the last level; skip attempting to shadow the DAT tables when the nested guest is running in a real address space. Fixes: e38c884 ("KVM: s390: Switch to new gmap") Tested-by: Christian Borntraeger <borntraeger@linux.ibm.com> Reviewed-by: Janosch Frank <frankja@linux.ibm.com> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
1 parent 19d6c5b commit a12cc7e

1 file changed

Lines changed: 10 additions & 2 deletions

File tree

arch/s390/kvm/gaccess.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,13 +1529,20 @@ static int _gaccess_do_shadow(struct kvm_s390_mmu_cache *mc, struct gmap *sg,
15291529

15301530
gl = get_level(table, ptep);
15311531

1532+
/* In case of a real address space */
1533+
if (w->level <= LEVEL_MEM) {
1534+
l = TABLE_TYPE_PAGE_TABLE;
1535+
hl = TABLE_TYPE_REGION1;
1536+
goto real_address_space;
1537+
}
1538+
15321539
/*
15331540
* Skip levels that are already protected. For each level, protect
15341541
* only the page containing the entry, not the whole table.
15351542
*/
15361543
for (i = gl ; i >= w->level; i--) {
1537-
rc = gmap_protect_rmap(mc, sg, entries[i - 1].gfn, gpa_to_gfn(saddr),
1538-
entries[i - 1].pfn, i, entries[i - 1].writable);
1544+
rc = gmap_protect_rmap(mc, sg, entries[i].gfn, gpa_to_gfn(saddr),
1545+
entries[i].pfn, i + 1, entries[i].writable);
15391546
if (rc)
15401547
return rc;
15411548
if (!sg->parent)
@@ -1551,6 +1558,7 @@ static int _gaccess_do_shadow(struct kvm_s390_mmu_cache *mc, struct gmap *sg,
15511558
/* Get the smallest granularity */
15521559
l = min3(gl, hl, w->level);
15531560

1561+
real_address_space:
15541562
flags = DAT_WALK_SPLIT_ALLOC | (uses_skeys(sg->parent) ? DAT_WALK_USES_SKEYS : 0);
15551563
/* If necessary, create the shadow mapping */
15561564
if (l < gl) {

0 commit comments

Comments
 (0)