mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-01 14:52:32 +00:00
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: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
This commit is contained in:
parent
ef23e7790e
commit
4799b557c9
@ -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)
|
|||||||
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user