Commit 61380a7a authored by Janis Schoetterl-Glausch's avatar Janis Schoetterl-Glausch Committed by Christian Borntraeger

KVM: s390: handle_tprot: Honor storage keys

Use the access key operand to check for key protection when
translating guest addresses.
Since the translation code checks for accessing exceptions/error hvas,
we can remove the check here and simplify the control flow.
Keep checking if the memory is read-only even if such memslots are
currently not supported.

handle_tprot was the last user of guest_translate_address,
so remove it.
Signed-off-by: default avatarJanis Schoetterl-Glausch <scgl@linux.ibm.com>
Reviewed-by: default avatarJanosch Frank <frankja@linux.ibm.com>
Reviewed-by: default avatarClaudio Imbrenda <imbrenda@linux.ibm.com>
Link: https://lore.kernel.org/r/20220211182215.2730017-4-scgl@linux.ibm.comSigned-off-by: default avatarChristian Borntraeger <borntraeger@linux.ibm.com>
parent e613d834
......@@ -1118,15 +1118,6 @@ int guest_translate_address_with_key(struct kvm_vcpu *vcpu, unsigned long gva, u
access_key);
}
int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
unsigned long *gpa, enum gacc_mode mode)
{
u8 access_key = psw_bits(vcpu->arch.sie_block->gpsw).key;
return guest_translate_address_with_key(vcpu, gva, ar, gpa, mode,
access_key);
}
/**
* check_gva_range - test a range of guest virtual addresses for accessibility
* @vcpu: virtual cpu
......
......@@ -190,9 +190,6 @@ int guest_translate_address_with_key(struct kvm_vcpu *vcpu, unsigned long gva, u
unsigned long *gpa, enum gacc_mode mode,
u8 access_key);
int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva,
u8 ar, unsigned long *gpa, enum gacc_mode mode);
int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
unsigned long length, enum gacc_mode mode, u8 access_key);
......
......@@ -1443,10 +1443,11 @@ int kvm_s390_handle_eb(struct kvm_vcpu *vcpu)
static int handle_tprot(struct kvm_vcpu *vcpu)
{
u64 address1, address2;
unsigned long hva, gpa;
int ret = 0, cc = 0;
u64 address, operand2;
unsigned long gpa;
u8 access_key;
bool writable;
int ret, cc;
u8 ar;
vcpu->stat.instruction_tprot++;
......@@ -1454,43 +1455,46 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
kvm_s390_get_base_disp_sse(vcpu, &address1, &address2, &ar, NULL);
kvm_s390_get_base_disp_sse(vcpu, &address, &operand2, &ar, NULL);
access_key = (operand2 & 0xf0) >> 4;
/* we only handle the Linux memory detection case:
* access key == 0
* everything else goes to userspace. */
if (address2 & 0xf0)
return -EOPNOTSUPP;
if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
ipte_lock(vcpu);
ret = guest_translate_address(vcpu, address1, ar, &gpa, GACC_STORE);
if (ret == PGM_PROTECTION) {
ret = guest_translate_address_with_key(vcpu, address, ar, &gpa,
GACC_STORE, access_key);
if (ret == 0) {
gfn_to_hva_prot(vcpu->kvm, gpa_to_gfn(gpa), &writable);
} else if (ret == PGM_PROTECTION) {
writable = false;
/* Write protected? Try again with read-only... */
cc = 1;
ret = guest_translate_address(vcpu, address1, ar, &gpa,
GACC_FETCH);
ret = guest_translate_address_with_key(vcpu, address, ar, &gpa,
GACC_FETCH, access_key);
}
if (ret) {
if (ret == PGM_ADDRESSING || ret == PGM_TRANSLATION_SPEC) {
ret = kvm_s390_inject_program_int(vcpu, ret);
} else if (ret > 0) {
/* Translation not available */
kvm_s390_set_psw_cc(vcpu, 3);
if (ret >= 0) {
cc = -1;
/* Fetching permitted; storing permitted */
if (ret == 0 && writable)
cc = 0;
/* Fetching permitted; storing not permitted */
else if (ret == 0 && !writable)
cc = 1;
/* Fetching not permitted; storing not permitted */
else if (ret == PGM_PROTECTION)
cc = 2;
/* Translation not available */
else if (ret != PGM_ADDRESSING && ret != PGM_TRANSLATION_SPEC)
cc = 3;
if (cc != -1) {
kvm_s390_set_psw_cc(vcpu, cc);
ret = 0;
} else {
ret = kvm_s390_inject_program_int(vcpu, ret);
}
goto out_unlock;
}
hva = gfn_to_hva_prot(vcpu->kvm, gpa_to_gfn(gpa), &writable);
if (kvm_is_error_hva(hva)) {
ret = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
} else {
if (!writable)
cc = 1; /* Write not permitted ==> read-only */
kvm_s390_set_psw_cc(vcpu, cc);
/* Note: CC2 only occurs for storage keys (not supported yet) */
}
out_unlock:
if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
ipte_unlock(vcpu);
return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment