Commit 4799b557 authored by Heiko Carstens's avatar Heiko Carstens Committed by Christian Borntraeger

KVM: s390: convert handle_tpi()

Convert handle_tpi() to new guest access functions.

The code now sets up a structure which is copied with a single call to
guest space instead of issuing several separate guest access calls.
This is necessary since the to be copied data may cross a page boundary.
If a protection exception happens while accessing any of the pages, the
instruction is suppressed and may not have modified any memory contents.
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent ef23e779
...@@ -224,9 +224,12 @@ static int handle_test_block(struct kvm_vcpu *vcpu) ...@@ -224,9 +224,12 @@ static int handle_test_block(struct kvm_vcpu *vcpu)
static int handle_tpi(struct kvm_vcpu *vcpu) static int handle_tpi(struct kvm_vcpu *vcpu)
{ {
struct kvm_s390_interrupt_info *inti; struct kvm_s390_interrupt_info *inti;
unsigned long len;
u32 tpi_data[3];
int cc, rc;
u64 addr; u64 addr;
int cc;
rc = 0;
addr = kvm_s390_get_base_disp_s(vcpu); addr = kvm_s390_get_base_disp_s(vcpu);
if (addr & 3) if (addr & 3)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
...@@ -235,30 +238,33 @@ static int handle_tpi(struct kvm_vcpu *vcpu) ...@@ -235,30 +238,33 @@ static int handle_tpi(struct kvm_vcpu *vcpu)
if (!inti) if (!inti)
goto no_interrupt; goto no_interrupt;
cc = 1; cc = 1;
tpi_data[0] = inti->io.subchannel_id << 16 | inti->io.subchannel_nr;
tpi_data[1] = inti->io.io_int_parm;
tpi_data[2] = inti->io.io_int_word;
if (addr) { if (addr) {
/* /*
* Store the two-word I/O interruption code into the * Store the two-word I/O interruption code into the
* provided area. * provided area.
*/ */
if (put_guest(vcpu, inti->io.subchannel_id, (u16 __user *)addr) len = sizeof(tpi_data) - 4;
|| put_guest(vcpu, inti->io.subchannel_nr, (u16 __user *)(addr + 2)) rc = write_guest(vcpu, addr, &tpi_data, len);
|| put_guest(vcpu, inti->io.io_int_parm, (u32 __user *)(addr + 4))) if (rc)
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); return kvm_s390_inject_prog_cond(vcpu, rc);
} else { } else {
/* /*
* Store the three-word I/O interruption code into * Store the three-word I/O interruption code into
* the appropriate lowcore area. * the appropriate lowcore area.
*/ */
put_guest(vcpu, inti->io.subchannel_id, (u16 __user *) __LC_SUBCHANNEL_ID); len = sizeof(tpi_data);
put_guest(vcpu, inti->io.subchannel_nr, (u16 __user *) __LC_SUBCHANNEL_NR); if (write_guest_lc(vcpu, __LC_SUBCHANNEL_ID, &tpi_data, len))
put_guest(vcpu, inti->io.io_int_parm, (u32 __user *) __LC_IO_INT_PARM); rc = -EFAULT;
put_guest(vcpu, inti->io.io_int_word, (u32 __user *) __LC_IO_INT_WORD);
} }
kfree(inti); kfree(inti);
no_interrupt: no_interrupt:
/* Set condition code and we're done. */ /* Set condition code and we're done. */
kvm_s390_set_psw_cc(vcpu, cc); if (!rc)
return 0; kvm_s390_set_psw_cc(vcpu, cc);
return rc ? -EFAULT : 0;
} }
static int handle_tsch(struct kvm_vcpu *vcpu) static int handle_tsch(struct kvm_vcpu *vcpu)
......
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