mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
KVM: s390: provide general purpose guest registers via kvm_run
This patch adds the general purpose registers to the kvm_run structure. Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
parent
60b413c924
commit
5a32c1af56
7 changed files with 37 additions and 36 deletions
|
@ -42,8 +42,10 @@ struct kvm_guest_debug_arch {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define KVM_SYNC_PREFIX (1UL << 0)
|
#define KVM_SYNC_PREFIX (1UL << 0)
|
||||||
|
#define KVM_SYNC_GPRS (1UL << 1)
|
||||||
/* definition of registers in kvm_run */
|
/* definition of registers in kvm_run */
|
||||||
struct kvm_sync_regs {
|
struct kvm_sync_regs {
|
||||||
__u64 prefix; /* prefix register */
|
__u64 prefix; /* prefix register */
|
||||||
|
__u64 gprs[16]; /* general purpose registers */
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -228,7 +228,6 @@ struct kvm_s390_float_interrupt {
|
||||||
|
|
||||||
struct kvm_vcpu_arch {
|
struct kvm_vcpu_arch {
|
||||||
struct kvm_s390_sie_block *sie_block;
|
struct kvm_s390_sie_block *sie_block;
|
||||||
unsigned long guest_gprs[16];
|
|
||||||
s390_fp_regs host_fpregs;
|
s390_fp_regs host_fpregs;
|
||||||
unsigned int host_acrs[NUM_ACRS];
|
unsigned int host_acrs[NUM_ACRS];
|
||||||
s390_fp_regs guest_fpregs;
|
s390_fp_regs guest_fpregs;
|
||||||
|
@ -254,5 +253,5 @@ struct kvm_arch{
|
||||||
struct gmap *gmap;
|
struct gmap *gmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int sie64a(struct kvm_s390_sie_block *, unsigned long *);
|
extern int sie64a(struct kvm_s390_sie_block *, u64 *);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,8 +20,8 @@ static int diag_release_pages(struct kvm_vcpu *vcpu)
|
||||||
unsigned long start, end;
|
unsigned long start, end;
|
||||||
unsigned long prefix = vcpu->arch.sie_block->prefix;
|
unsigned long prefix = vcpu->arch.sie_block->prefix;
|
||||||
|
|
||||||
start = vcpu->arch.guest_gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
|
start = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
|
||||||
end = vcpu->arch.guest_gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096;
|
end = vcpu->run->s.regs.gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096;
|
||||||
|
|
||||||
if (start & ~PAGE_MASK || end & ~PAGE_MASK || start > end
|
if (start & ~PAGE_MASK || end & ~PAGE_MASK || start > end
|
||||||
|| start < 2 * PAGE_SIZE)
|
|| start < 2 * PAGE_SIZE)
|
||||||
|
@ -56,7 +56,7 @@ static int __diag_time_slice_end(struct kvm_vcpu *vcpu)
|
||||||
static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
|
static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
unsigned int reg = vcpu->arch.sie_block->ipa & 0xf;
|
unsigned int reg = vcpu->arch.sie_block->ipa & 0xf;
|
||||||
unsigned long subcode = vcpu->arch.guest_gprs[reg] & 0xffff;
|
unsigned long subcode = vcpu->run->s.regs.gprs[reg] & 0xffff;
|
||||||
|
|
||||||
VCPU_EVENT(vcpu, 5, "diag ipl functions, subcode %lx", subcode);
|
VCPU_EVENT(vcpu, 5, "diag ipl functions, subcode %lx", subcode);
|
||||||
switch (subcode) {
|
switch (subcode) {
|
||||||
|
|
|
@ -36,7 +36,7 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
useraddr = disp2;
|
useraddr = disp2;
|
||||||
if (base2)
|
if (base2)
|
||||||
useraddr += vcpu->arch.guest_gprs[base2];
|
useraddr += vcpu->run->s.regs.gprs[base2];
|
||||||
|
|
||||||
if (useraddr & 7)
|
if (useraddr & 7)
|
||||||
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
||||||
|
@ -75,7 +75,7 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
useraddr = disp2;
|
useraddr = disp2;
|
||||||
if (base2)
|
if (base2)
|
||||||
useraddr += vcpu->arch.guest_gprs[base2];
|
useraddr += vcpu->run->s.regs.gprs[base2];
|
||||||
|
|
||||||
if (useraddr & 3)
|
if (useraddr & 3)
|
||||||
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
||||||
|
|
|
@ -289,7 +289,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
vcpu->arch.gmap = vcpu->kvm->arch.gmap;
|
vcpu->arch.gmap = vcpu->kvm->arch.gmap;
|
||||||
vcpu->run->kvm_valid_regs = KVM_SYNC_PREFIX;
|
vcpu->run->kvm_valid_regs = KVM_SYNC_PREFIX | KVM_SYNC_GPRS;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,13 +428,13 @@ static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
|
int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
|
||||||
{
|
{
|
||||||
memcpy(&vcpu->arch.guest_gprs, ®s->gprs, sizeof(regs->gprs));
|
memcpy(&vcpu->run->s.regs.gprs, ®s->gprs, sizeof(regs->gprs));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
|
int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
|
||||||
{
|
{
|
||||||
memcpy(®s->gprs, &vcpu->arch.guest_gprs, sizeof(regs->gprs));
|
memcpy(®s->gprs, &vcpu->run->s.regs.gprs, sizeof(regs->gprs));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,7 +511,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
|
memcpy(&vcpu->arch.sie_block->gg14, &vcpu->run->s.regs.gprs[14], 16);
|
||||||
|
|
||||||
if (need_resched())
|
if (need_resched())
|
||||||
schedule();
|
schedule();
|
||||||
|
@ -528,7 +528,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
VCPU_EVENT(vcpu, 6, "entering sie flags %x",
|
VCPU_EVENT(vcpu, 6, "entering sie flags %x",
|
||||||
atomic_read(&vcpu->arch.sie_block->cpuflags));
|
atomic_read(&vcpu->arch.sie_block->cpuflags));
|
||||||
rc = sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs);
|
rc = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (kvm_is_ucontrol(vcpu->kvm)) {
|
if (kvm_is_ucontrol(vcpu->kvm)) {
|
||||||
rc = SIE_INTERCEPT_UCONTROL;
|
rc = SIE_INTERCEPT_UCONTROL;
|
||||||
|
@ -544,7 +544,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
|
||||||
kvm_guest_exit();
|
kvm_guest_exit();
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
|
||||||
memcpy(&vcpu->arch.guest_gprs[14], &vcpu->arch.sie_block->gg14, 16);
|
memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,7 +673,7 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if (__guestcopy(vcpu, addr + offsetof(struct save_area, gp_regs),
|
if (__guestcopy(vcpu, addr + offsetof(struct save_area, gp_regs),
|
||||||
vcpu->arch.guest_gprs, 128, prefix))
|
vcpu->run->s.regs.gprs, 128, prefix))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if (__guestcopy(vcpu, addr + offsetof(struct save_area, psw),
|
if (__guestcopy(vcpu, addr + offsetof(struct save_area, psw),
|
||||||
|
|
|
@ -33,7 +33,7 @@ static int handle_set_prefix(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
operand2 = disp2;
|
operand2 = disp2;
|
||||||
if (base2)
|
if (base2)
|
||||||
operand2 += vcpu->arch.guest_gprs[base2];
|
operand2 += vcpu->run->s.regs.gprs[base2];
|
||||||
|
|
||||||
/* must be word boundary */
|
/* must be word boundary */
|
||||||
if (operand2 & 3) {
|
if (operand2 & 3) {
|
||||||
|
@ -73,7 +73,7 @@ static int handle_store_prefix(struct kvm_vcpu *vcpu)
|
||||||
vcpu->stat.instruction_stpx++;
|
vcpu->stat.instruction_stpx++;
|
||||||
operand2 = disp2;
|
operand2 = disp2;
|
||||||
if (base2)
|
if (base2)
|
||||||
operand2 += vcpu->arch.guest_gprs[base2];
|
operand2 += vcpu->run->s.regs.gprs[base2];
|
||||||
|
|
||||||
/* must be word boundary */
|
/* must be word boundary */
|
||||||
if (operand2 & 3) {
|
if (operand2 & 3) {
|
||||||
|
@ -105,7 +105,7 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
|
||||||
vcpu->stat.instruction_stap++;
|
vcpu->stat.instruction_stap++;
|
||||||
useraddr = disp2;
|
useraddr = disp2;
|
||||||
if (base2)
|
if (base2)
|
||||||
useraddr += vcpu->arch.guest_gprs[base2];
|
useraddr += vcpu->run->s.regs.gprs[base2];
|
||||||
|
|
||||||
if (useraddr & 1) {
|
if (useraddr & 1) {
|
||||||
kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
||||||
|
@ -180,7 +180,7 @@ static int handle_stidp(struct kvm_vcpu *vcpu)
|
||||||
vcpu->stat.instruction_stidp++;
|
vcpu->stat.instruction_stidp++;
|
||||||
operand2 = disp2;
|
operand2 = disp2;
|
||||||
if (base2)
|
if (base2)
|
||||||
operand2 += vcpu->arch.guest_gprs[base2];
|
operand2 += vcpu->run->s.regs.gprs[base2];
|
||||||
|
|
||||||
if (operand2 & 7) {
|
if (operand2 & 7) {
|
||||||
kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
||||||
|
@ -231,9 +231,9 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
|
||||||
|
|
||||||
static int handle_stsi(struct kvm_vcpu *vcpu)
|
static int handle_stsi(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
int fc = (vcpu->arch.guest_gprs[0] & 0xf0000000) >> 28;
|
int fc = (vcpu->run->s.regs.gprs[0] & 0xf0000000) >> 28;
|
||||||
int sel1 = vcpu->arch.guest_gprs[0] & 0xff;
|
int sel1 = vcpu->run->s.regs.gprs[0] & 0xff;
|
||||||
int sel2 = vcpu->arch.guest_gprs[1] & 0xffff;
|
int sel2 = vcpu->run->s.regs.gprs[1] & 0xffff;
|
||||||
int base2 = vcpu->arch.sie_block->ipb >> 28;
|
int base2 = vcpu->arch.sie_block->ipb >> 28;
|
||||||
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
|
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
|
||||||
u64 operand2;
|
u64 operand2;
|
||||||
|
@ -244,14 +244,14 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
operand2 = disp2;
|
operand2 = disp2;
|
||||||
if (base2)
|
if (base2)
|
||||||
operand2 += vcpu->arch.guest_gprs[base2];
|
operand2 += vcpu->run->s.regs.gprs[base2];
|
||||||
|
|
||||||
if (operand2 & 0xfff && fc > 0)
|
if (operand2 & 0xfff && fc > 0)
|
||||||
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
||||||
|
|
||||||
switch (fc) {
|
switch (fc) {
|
||||||
case 0:
|
case 0:
|
||||||
vcpu->arch.guest_gprs[0] = 3 << 28;
|
vcpu->run->s.regs.gprs[0] = 3 << 28;
|
||||||
vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
|
vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
|
||||||
return 0;
|
return 0;
|
||||||
case 1: /* same handling for 1 and 2 */
|
case 1: /* same handling for 1 and 2 */
|
||||||
|
@ -280,7 +280,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
|
||||||
}
|
}
|
||||||
free_page(mem);
|
free_page(mem);
|
||||||
vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
|
vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
|
||||||
vcpu->arch.guest_gprs[0] = 0;
|
vcpu->run->s.regs.gprs[0] = 0;
|
||||||
return 0;
|
return 0;
|
||||||
out_mem:
|
out_mem:
|
||||||
free_page(mem);
|
free_page(mem);
|
||||||
|
@ -332,8 +332,8 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
|
||||||
int disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16;
|
int disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16;
|
||||||
int base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12;
|
int base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12;
|
||||||
int disp2 = vcpu->arch.sie_block->ipb & 0x0fff;
|
int disp2 = vcpu->arch.sie_block->ipb & 0x0fff;
|
||||||
u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0;
|
u64 address1 = disp1 + base1 ? vcpu->run->s.regs.gprs[base1] : 0;
|
||||||
u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0;
|
u64 address2 = disp2 + base2 ? vcpu->run->s.regs.gprs[base2] : 0;
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
unsigned long user_address;
|
unsigned long user_address;
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
|
|
||||||
|
|
||||||
static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
|
static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
|
||||||
unsigned long *reg)
|
u64 *reg)
|
||||||
{
|
{
|
||||||
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -220,7 +220,7 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
|
static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
|
||||||
unsigned long *reg)
|
u64 *reg)
|
||||||
{
|
{
|
||||||
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||||
struct kvm_s390_local_interrupt *li = NULL;
|
struct kvm_s390_local_interrupt *li = NULL;
|
||||||
|
@ -278,7 +278,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
|
static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
|
||||||
unsigned long *reg)
|
u64 *reg)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||||
|
@ -316,7 +316,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
|
||||||
int base2 = vcpu->arch.sie_block->ipb >> 28;
|
int base2 = vcpu->arch.sie_block->ipb >> 28;
|
||||||
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
|
int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
|
||||||
u32 parameter;
|
u32 parameter;
|
||||||
u16 cpu_addr = vcpu->arch.guest_gprs[r3];
|
u16 cpu_addr = vcpu->run->s.regs.gprs[r3];
|
||||||
u8 order_code;
|
u8 order_code;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -327,18 +327,18 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
order_code = disp2;
|
order_code = disp2;
|
||||||
if (base2)
|
if (base2)
|
||||||
order_code += vcpu->arch.guest_gprs[base2];
|
order_code += vcpu->run->s.regs.gprs[base2];
|
||||||
|
|
||||||
if (r1 % 2)
|
if (r1 % 2)
|
||||||
parameter = vcpu->arch.guest_gprs[r1];
|
parameter = vcpu->run->s.regs.gprs[r1];
|
||||||
else
|
else
|
||||||
parameter = vcpu->arch.guest_gprs[r1 + 1];
|
parameter = vcpu->run->s.regs.gprs[r1 + 1];
|
||||||
|
|
||||||
switch (order_code) {
|
switch (order_code) {
|
||||||
case SIGP_SENSE:
|
case SIGP_SENSE:
|
||||||
vcpu->stat.instruction_sigp_sense++;
|
vcpu->stat.instruction_sigp_sense++;
|
||||||
rc = __sigp_sense(vcpu, cpu_addr,
|
rc = __sigp_sense(vcpu, cpu_addr,
|
||||||
&vcpu->arch.guest_gprs[r1]);
|
&vcpu->run->s.regs.gprs[r1]);
|
||||||
break;
|
break;
|
||||||
case SIGP_EXTERNAL_CALL:
|
case SIGP_EXTERNAL_CALL:
|
||||||
vcpu->stat.instruction_sigp_external_call++;
|
vcpu->stat.instruction_sigp_external_call++;
|
||||||
|
@ -363,12 +363,12 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
|
||||||
case SIGP_SET_PREFIX:
|
case SIGP_SET_PREFIX:
|
||||||
vcpu->stat.instruction_sigp_prefix++;
|
vcpu->stat.instruction_sigp_prefix++;
|
||||||
rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
|
rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
|
||||||
&vcpu->arch.guest_gprs[r1]);
|
&vcpu->run->s.regs.gprs[r1]);
|
||||||
break;
|
break;
|
||||||
case SIGP_SENSE_RUNNING:
|
case SIGP_SENSE_RUNNING:
|
||||||
vcpu->stat.instruction_sigp_sense_running++;
|
vcpu->stat.instruction_sigp_sense_running++;
|
||||||
rc = __sigp_sense_running(vcpu, cpu_addr,
|
rc = __sigp_sense_running(vcpu, cpu_addr,
|
||||||
&vcpu->arch.guest_gprs[r1]);
|
&vcpu->run->s.regs.gprs[r1]);
|
||||||
break;
|
break;
|
||||||
case SIGP_RESTART:
|
case SIGP_RESTART:
|
||||||
vcpu->stat.instruction_sigp_restart++;
|
vcpu->stat.instruction_sigp_restart++;
|
||||||
|
|
Loading…
Reference in a new issue