KVM: s390: Allocate and save/restore vector registers
Define and allocate space for both the host and guest views of the vector registers for a given vcpu. The 32 vector registers occupy 128 bits each (512 bytes total), but architecturally are paired with 512 additional bytes of reserved space for future expansion. The kvm_sync_regs structs containing the registers are union'ed with 1024 bytes of padding in the common kvm_run struct. The addition of 1024 bytes of new register information clearly exceeds the existing union, so an expansion of that padding is required. When changing environments, we need to appropriately save and restore the vector registers viewed by both the host and guest, into and out of the sync_regs space. The floating point registers overlay the upper half of vector registers 0-15, so there's a bit of data duplication here that needs to be carefully avoided. Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com> Acked-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
This commit is contained in:

committed by
Christian Borntraeger

parent
1f289a8429
commit
68c557501b
@@ -185,6 +185,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
case KVM_CAP_S390_COW:
|
||||
r = MACHINE_HAS_ESOP;
|
||||
break;
|
||||
case KVM_CAP_S390_VECTOR_REGISTERS:
|
||||
r = MACHINE_HAS_VX;
|
||||
break;
|
||||
default:
|
||||
r = 0;
|
||||
}
|
||||
@@ -265,6 +268,10 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
|
||||
kvm->arch.user_sigp = 1;
|
||||
r = 0;
|
||||
break;
|
||||
case KVM_CAP_S390_VECTOR_REGISTERS:
|
||||
kvm->arch.use_vectors = MACHINE_HAS_VX;
|
||||
r = MACHINE_HAS_VX ? 0 : -EINVAL;
|
||||
break;
|
||||
default:
|
||||
r = -EINVAL;
|
||||
break;
|
||||
@@ -942,6 +949,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||
|
||||
kvm->arch.css_support = 0;
|
||||
kvm->arch.use_irqchip = 0;
|
||||
kvm->arch.use_vectors = 0;
|
||||
kvm->arch.epoch = 0;
|
||||
|
||||
spin_lock_init(&kvm->arch.start_stop_lock);
|
||||
@@ -1035,6 +1043,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
|
||||
KVM_SYNC_CRS |
|
||||
KVM_SYNC_ARCH0 |
|
||||
KVM_SYNC_PFAULT;
|
||||
if (test_kvm_facility(vcpu->kvm, 129))
|
||||
vcpu->run->kvm_valid_regs |= KVM_SYNC_VRS;
|
||||
|
||||
if (kvm_is_ucontrol(vcpu->kvm))
|
||||
return __kvm_ucontrol_vcpu_init(vcpu);
|
||||
@@ -1045,10 +1055,18 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
|
||||
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||
{
|
||||
save_fp_ctl(&vcpu->arch.host_fpregs.fpc);
|
||||
save_fp_regs(vcpu->arch.host_fpregs.fprs);
|
||||
if (vcpu->kvm->arch.use_vectors)
|
||||
save_vx_regs((__vector128 *)&vcpu->arch.host_vregs->vrs);
|
||||
else
|
||||
save_fp_regs(vcpu->arch.host_fpregs.fprs);
|
||||
save_access_regs(vcpu->arch.host_acrs);
|
||||
restore_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
|
||||
restore_fp_regs(vcpu->arch.guest_fpregs.fprs);
|
||||
if (vcpu->kvm->arch.use_vectors) {
|
||||
restore_fp_ctl(&vcpu->run->s.regs.fpc);
|
||||
restore_vx_regs((__vector128 *)&vcpu->run->s.regs.vrs);
|
||||
} else {
|
||||
restore_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
|
||||
restore_fp_regs(vcpu->arch.guest_fpregs.fprs);
|
||||
}
|
||||
restore_access_regs(vcpu->run->s.regs.acrs);
|
||||
gmap_enable(vcpu->arch.gmap);
|
||||
atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
|
||||
@@ -1058,11 +1076,19 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
|
||||
gmap_disable(vcpu->arch.gmap);
|
||||
save_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
|
||||
save_fp_regs(vcpu->arch.guest_fpregs.fprs);
|
||||
if (vcpu->kvm->arch.use_vectors) {
|
||||
save_fp_ctl(&vcpu->run->s.regs.fpc);
|
||||
save_vx_regs((__vector128 *)&vcpu->run->s.regs.vrs);
|
||||
} else {
|
||||
save_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
|
||||
save_fp_regs(vcpu->arch.guest_fpregs.fprs);
|
||||
}
|
||||
save_access_regs(vcpu->run->s.regs.acrs);
|
||||
restore_fp_ctl(&vcpu->arch.host_fpregs.fpc);
|
||||
restore_fp_regs(vcpu->arch.host_fpregs.fprs);
|
||||
if (vcpu->kvm->arch.use_vectors)
|
||||
restore_vx_regs((__vector128 *)&vcpu->arch.host_vregs->vrs);
|
||||
else
|
||||
restore_fp_regs(vcpu->arch.host_fpregs.fprs);
|
||||
restore_access_regs(vcpu->arch.host_acrs);
|
||||
}
|
||||
|
||||
@@ -1196,6 +1222,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
|
||||
|
||||
vcpu->arch.sie_block = &sie_page->sie_block;
|
||||
vcpu->arch.sie_block->itdba = (unsigned long) &sie_page->itdb;
|
||||
vcpu->arch.host_vregs = &sie_page->vregs;
|
||||
|
||||
vcpu->arch.sie_block->icpua = id;
|
||||
if (!kvm_is_ucontrol(kvm)) {
|
||||
|
Reference in New Issue
Block a user