Re: [GIT PULL 1/6] KVM: s390: Handle MVPG partial execution interception
On Tue, Apr 29, 2014 at 03:36:43PM +0200, Christian Borntraeger wrote: +static int handle_mvpg_pei(struct kvm_vcpu *vcpu) +{ + unsigned long hostaddr, srcaddr, dstaddr; + psw_t *psw = vcpu-arch.sie_block-gpsw; + struct mm_struct *mm = current-mm; + int reg1, reg2, rc; + + kvm_s390_get_regs_rre(vcpu, reg1, reg2); + srcaddr = kvm_s390_real_to_abs(vcpu, vcpu-run-s.regs.gprs[reg2]); + dstaddr = kvm_s390_real_to_abs(vcpu, vcpu-run-s.regs.gprs[reg1]); + + /* Make sure that the source is paged-in */ + hostaddr = gmap_fault(srcaddr, vcpu-arch.gmap); + if (IS_ERR_VALUE(hostaddr)) + return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); FWIW (and nothing that should keep this code from going upstream), this is not entirely correct, since gmap_fault() may return -ENOMEM. So a host out-of-memory situation will incorrectly result in a guest addressing exception, which is most likely not what we want. -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [GIT PULL 1/6] KVM: s390: Handle MVPG partial execution interception
On Wed, 30 Apr 2014 10:07:09 +0200 Heiko Carstens heiko.carst...@de.ibm.com wrote: On Tue, Apr 29, 2014 at 03:36:43PM +0200, Christian Borntraeger wrote: +static int handle_mvpg_pei(struct kvm_vcpu *vcpu) +{ + unsigned long hostaddr, srcaddr, dstaddr; + psw_t *psw = vcpu-arch.sie_block-gpsw; + struct mm_struct *mm = current-mm; + int reg1, reg2, rc; + + kvm_s390_get_regs_rre(vcpu, reg1, reg2); + srcaddr = kvm_s390_real_to_abs(vcpu, vcpu-run-s.regs.gprs[reg2]); + dstaddr = kvm_s390_real_to_abs(vcpu, vcpu-run-s.regs.gprs[reg1]); + + /* Make sure that the source is paged-in */ + hostaddr = gmap_fault(srcaddr, vcpu-arch.gmap); + if (IS_ERR_VALUE(hostaddr)) + return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); FWIW (and nothing that should keep this code from going upstream), this is not entirely correct, since gmap_fault() may return -ENOMEM. So a host out-of-memory situation will incorrectly result in a guest addressing exception, which is most likely not what we want. Ah, ... good point, thanks for the hint! (BTW: That's why I personally prefer some more comments in the source code - by just looking at gmap_fault() and __gmap_fault(), this is quite hard to see unless you step through these functions and called functions line by line). Anyway, I'll assemble a follow-up patch that addresses this problem with handle_mvpg_pei(). Thomas -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [GIT PULL 1/6] KVM: s390: Handle MVPG partial execution interception
On 30/04/14 10:07, Heiko Carstens wrote: On Tue, Apr 29, 2014 at 03:36:43PM +0200, Christian Borntraeger wrote: +static int handle_mvpg_pei(struct kvm_vcpu *vcpu) +{ +unsigned long hostaddr, srcaddr, dstaddr; +psw_t *psw = vcpu-arch.sie_block-gpsw; +struct mm_struct *mm = current-mm; +int reg1, reg2, rc; + +kvm_s390_get_regs_rre(vcpu, reg1, reg2); +srcaddr = kvm_s390_real_to_abs(vcpu, vcpu-run-s.regs.gprs[reg2]); +dstaddr = kvm_s390_real_to_abs(vcpu, vcpu-run-s.regs.gprs[reg1]); + +/* Make sure that the source is paged-in */ +hostaddr = gmap_fault(srcaddr, vcpu-arch.gmap); +if (IS_ERR_VALUE(hostaddr)) +return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); FWIW (and nothing that should keep this code from going upstream), this is not entirely correct, since gmap_fault() may return -ENOMEM. So a host out-of-memory situation will incorrectly result in a guest addressing exception, which is most likely not what we want. Indeed, host out-of-memory situation will cause architectural non-compliance in some areas of KVM/s390. The proper Linux way (returning -ENOMEM (or EFAULT?) in the KVM_RUN ioctl) will cause qemu to print an error and abort(), which is also not ideal. The s390 way, should probably be to inject an uncorrectable storage error machine check. So the question is what is the right thing to do for these cases? Paolo, what is the x86 way of dealing with situations like this (here we fail to allocate a pud,pmd,pte or helper structure). Looks like you return -ENOMEM to qemu. Is that true for all cases? Christian -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[GIT PULL 1/6] KVM: s390: Handle MVPG partial execution interception
From: Thomas Huth th...@linux.vnet.ibm.com When the guest executes the MVPG instruction with DAT disabled, and the source or destination page is not mapped in the host, the so-called partial execution interception occurs. We need to handle this event by setting up a mapping for the corresponding user pages. Signed-off-by: Thomas Huth th...@linux.vnet.ibm.com Reviewed-by: Cornelia Huck cornelia.h...@de.ibm.com Signed-off-by: Christian Borntraeger borntrae...@de.ibm.com --- arch/s390/kvm/intercept.c | 55 ++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 30e1c5e..54313fe 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -1,7 +1,7 @@ /* * in-kernel handling for sie intercepts * - * Copyright IBM Corp. 2008, 2009 + * Copyright IBM Corp. 2008, 2014 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License (version 2 only) @@ -234,6 +234,58 @@ static int handle_instruction_and_prog(struct kvm_vcpu *vcpu) return rc2; } +/** + * Handle MOVE PAGE partial execution interception. + * + * This interception can only happen for guests with DAT disabled and + * addresses that are currently not mapped in the host. Thus we try to + * set up the mappings for the corresponding user pages here (or throw + * addressing exceptions in case of illegal guest addresses). + */ +static int handle_mvpg_pei(struct kvm_vcpu *vcpu) +{ + unsigned long hostaddr, srcaddr, dstaddr; + psw_t *psw = vcpu-arch.sie_block-gpsw; + struct mm_struct *mm = current-mm; + int reg1, reg2, rc; + + kvm_s390_get_regs_rre(vcpu, reg1, reg2); + srcaddr = kvm_s390_real_to_abs(vcpu, vcpu-run-s.regs.gprs[reg2]); + dstaddr = kvm_s390_real_to_abs(vcpu, vcpu-run-s.regs.gprs[reg1]); + + /* Make sure that the source is paged-in */ + hostaddr = gmap_fault(srcaddr, vcpu-arch.gmap); + if (IS_ERR_VALUE(hostaddr)) + return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); + down_read(mm-mmap_sem); + rc = get_user_pages(current, mm, hostaddr, 1, 0, 0, NULL, NULL); + up_read(mm-mmap_sem); + if (rc 0) + return rc; + + /* Make sure that the destination is paged-in */ + hostaddr = gmap_fault(dstaddr, vcpu-arch.gmap); + if (IS_ERR_VALUE(hostaddr)) + return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); + down_read(mm-mmap_sem); + rc = get_user_pages(current, mm, hostaddr, 1, 1, 0, NULL, NULL); + up_read(mm-mmap_sem); + if (rc 0) + return rc; + + psw-addr = __rewind_psw(*psw, 4); + + return 0; +} + +static int handle_partial_execution(struct kvm_vcpu *vcpu) +{ + if (vcpu-arch.sie_block-ipa == 0xb254)/* MVPG */ + return handle_mvpg_pei(vcpu); + + return -EOPNOTSUPP; +} + static const intercept_handler_t intercept_funcs[] = { [0x00 2] = handle_noop, [0x04 2] = handle_instruction, @@ -245,6 +297,7 @@ static const intercept_handler_t intercept_funcs[] = { [0x1C 2] = kvm_s390_handle_wait, [0x20 2] = handle_validity, [0x28 2] = handle_stop, + [0x38 2] = handle_partial_execution, }; int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) -- 1.8.4.2 -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html