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: Janis Schoetterl-Glausch <scgl@linux.ibm.com> Reviewed-by: Janosch Frank <frankja@linux.ibm.com> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com> Link: https://lore.kernel.org/r/20220211182215.2730017-4-scgl@linux.ibm.com Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
This commit is contained in:
Родитель
e613d83454
Коммит
61380a7adf
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче