Skip to content

Commit

Permalink
KVM: s390: gaccess: fix real-space designation asce handling for gmap…
Browse files Browse the repository at this point in the history
… shadows

For real-space designation asces the asce origin part is only a token.
The asce token origin must not be used to generate an effective
address for storage references. This however is erroneously done
within kvm_s390_shadow_tables().

Furthermore within the same function the wrong parts of virtual
addresses are used to generate a corresponding real address
(e.g. the region second index is used as region first index).

Both of the above can result in incorrect address translations. Only
for real space designations with a token origin of zero and addresses
below one megabyte the translation was correct.

Furthermore replace a "!asce.r" statement with a "!*fake" statement to
make it more obvious that a specific condition has nothing to do with
the architecture, but with the fake handling of real space designations.

Fixes: 3218f70 ("s390/mm: support real-space for gmap shadows")
Cc: David Hildenbrand <[email protected]>
Cc: [email protected]
Signed-off-by: Heiko Carstens <[email protected]>
Reviewed-by: Martin Schwidefsky <[email protected]>
Signed-off-by: Christian Borntraeger <[email protected]>
  • Loading branch information
heicarst authored and borntraeger committed Jun 22, 2017
1 parent 1ba15b2 commit addb63c
Showing 1 changed file with 6 additions and 9 deletions.
15 changes: 6 additions & 9 deletions arch/s390/kvm/gaccess.c
Original file line number Diff line number Diff line change
Expand Up @@ -977,11 +977,12 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
ptr = asce.origin * 4096;
if (asce.r) {
*fake = 1;
ptr = 0;
asce.dt = ASCE_TYPE_REGION1;
}
switch (asce.dt) {
case ASCE_TYPE_REGION1:
if (vaddr.rfx01 > asce.tl && !asce.r)
if (vaddr.rfx01 > asce.tl && !*fake)
return PGM_REGION_FIRST_TRANS;
break;
case ASCE_TYPE_REGION2:
Expand Down Expand Up @@ -1009,8 +1010,7 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
union region1_table_entry rfte;

if (*fake) {
/* offset in 16EB guest memory block */
ptr = ptr + ((unsigned long) vaddr.rsx << 53UL);
ptr += (unsigned long) vaddr.rfx << 53;
rfte.val = ptr;
goto shadow_r2t;
}
Expand All @@ -1036,8 +1036,7 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
union region2_table_entry rste;

if (*fake) {
/* offset in 8PB guest memory block */
ptr = ptr + ((unsigned long) vaddr.rtx << 42UL);
ptr += (unsigned long) vaddr.rsx << 42;
rste.val = ptr;
goto shadow_r3t;
}
Expand All @@ -1064,8 +1063,7 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
union region3_table_entry rtte;

if (*fake) {
/* offset in 4TB guest memory block */
ptr = ptr + ((unsigned long) vaddr.sx << 31UL);
ptr += (unsigned long) vaddr.rtx << 31;
rtte.val = ptr;
goto shadow_sgt;
}
Expand Down Expand Up @@ -1101,8 +1099,7 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
union segment_table_entry ste;

if (*fake) {
/* offset in 2G guest memory block */
ptr = ptr + ((unsigned long) vaddr.sx << 20UL);
ptr += (unsigned long) vaddr.sx << 20;
ste.val = ptr;
goto shadow_pgt;
}
Expand Down

0 comments on commit addb63c

Please sign in to comment.