s390 and POWER bug fixes, plus enabling the KVM-VFIO interface on s390.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEcBAABAgAGBQJWp5FIAAoJEL/70l94x66DozoIAKWFLnwi6PQ7Sm+Tvr0Sl/mp yGDM+PuVyG4C6bPS66xd4XkXEFIwfpIJQzq1Zt7Xg0m27t50DRtmInLJU4ql7MFD vYn3h6lOudtUR0i5kPYSy6SMehFjx8wS0GX+O+iX9tMlYI0vGWEJ+7C06FmnqpGP RUUjnVvljAMih8wsAHLOjH8rwZHnO+EfHNi+V7Q+eFBHJnn2R06IqK8z5DmTBeTQ ZecNdZslX5qZvMNulTo7nC2P6VShkdRuMJkLEFeSaTlCqx5WcnzgwEiMMavUeYI8 aIWuE51v0RMxRhsvRXUQOeRpRgU0AF2OYJEKXBRbO3P6IRikFohJq4QH67zN2HA= =54tv -----END PGP SIGNATURE----- Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm Pull KVM fixes from Paolo Bonzini: "s390 and POWER bug fixes, plus enabling the KVM-VFIO interface on s390" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM doc: Fix KVM_SMI chapter number KVM: s390: fix memory overwrites when vx is disabled KVM: s390: Enable the KVM-VFIO device KVM: s390: fix guest fprs memory leak KVM: PPC: Fix ONE_REG AltiVec support KVM: PPC: Increase memslots to 512 KVM: PPC: Book3S PR: Remove unused variable 'vcpu_book3s' KVM: PPC: Fix emulation of H_SET_DABR/X on POWER8 KVM: PPC: Book3S HV: Handle unexpected traps in guest entry/exit code better
This commit is contained in:
commit
f0ce3ff42e
@ -3025,7 +3025,7 @@ len must be a multiple of sizeof(struct kvm_s390_irq). It must be > 0
|
||||
and it must not exceed (max_vcpus + 32) * sizeof(struct kvm_s390_irq),
|
||||
which is the maximum number of possibly pending cpu-local interrupts.
|
||||
|
||||
4.90 KVM_SMI
|
||||
4.96 KVM_SMI
|
||||
|
||||
Capability: KVM_CAP_X86_SMM
|
||||
Architectures: x86
|
||||
|
@ -38,8 +38,7 @@
|
||||
|
||||
#define KVM_MAX_VCPUS NR_CPUS
|
||||
#define KVM_MAX_VCORES NR_CPUS
|
||||
#define KVM_USER_MEM_SLOTS 32
|
||||
#define KVM_MEM_SLOTS_NUM KVM_USER_MEM_SLOTS
|
||||
#define KVM_USER_MEM_SLOTS 512
|
||||
|
||||
#ifdef CONFIG_KVM_MMIO
|
||||
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
|
||||
|
@ -377,15 +377,12 @@ no_seg_found:
|
||||
|
||||
static void kvmppc_mmu_book3s_64_slbmte(struct kvm_vcpu *vcpu, u64 rs, u64 rb)
|
||||
{
|
||||
struct kvmppc_vcpu_book3s *vcpu_book3s;
|
||||
u64 esid, esid_1t;
|
||||
int slb_nr;
|
||||
struct kvmppc_slb *slbe;
|
||||
|
||||
dprintk("KVM MMU: slbmte(0x%llx, 0x%llx)\n", rs, rb);
|
||||
|
||||
vcpu_book3s = to_book3s(vcpu);
|
||||
|
||||
esid = GET_ESID(rb);
|
||||
esid_1t = GET_ESID_1T(rb);
|
||||
slb_nr = rb & 0xfff;
|
||||
|
@ -833,6 +833,24 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
|
||||
vcpu->stat.sum_exits++;
|
||||
|
||||
/*
|
||||
* This can happen if an interrupt occurs in the last stages
|
||||
* of guest entry or the first stages of guest exit (i.e. after
|
||||
* setting paca->kvm_hstate.in_guest to KVM_GUEST_MODE_GUEST_HV
|
||||
* and before setting it to KVM_GUEST_MODE_HOST_HV).
|
||||
* That can happen due to a bug, or due to a machine check
|
||||
* occurring at just the wrong time.
|
||||
*/
|
||||
if (vcpu->arch.shregs.msr & MSR_HV) {
|
||||
printk(KERN_EMERG "KVM trap in HV mode!\n");
|
||||
printk(KERN_EMERG "trap=0x%x | pc=0x%lx | msr=0x%llx\n",
|
||||
vcpu->arch.trap, kvmppc_get_pc(vcpu),
|
||||
vcpu->arch.shregs.msr);
|
||||
kvmppc_dump_regs(vcpu);
|
||||
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
|
||||
run->hw.hardware_exit_reason = vcpu->arch.trap;
|
||||
return RESUME_HOST;
|
||||
}
|
||||
run->exit_reason = KVM_EXIT_UNKNOWN;
|
||||
run->ready_for_interrupt_injection = 1;
|
||||
switch (vcpu->arch.trap) {
|
||||
|
@ -2153,7 +2153,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||
|
||||
/* Emulate H_SET_DABR/X on P8 for the sake of compat mode guests */
|
||||
2: rlwimi r5, r4, 5, DAWRX_DR | DAWRX_DW
|
||||
rlwimi r5, r4, 1, DAWRX_WT
|
||||
rlwimi r5, r4, 2, DAWRX_WT
|
||||
clrrdi r4, r4, 3
|
||||
std r4, VCPU_DAWR(r3)
|
||||
std r5, VCPU_DAWRX(r3)
|
||||
@ -2404,6 +2404,8 @@ machine_check_realmode:
|
||||
* guest as machine check causing guest to crash.
|
||||
*/
|
||||
ld r11, VCPU_MSR(r9)
|
||||
rldicl. r0, r11, 64-MSR_HV_LG, 63 /* check if it happened in HV mode */
|
||||
bne mc_cont /* if so, exit to host */
|
||||
andi. r10, r11, MSR_RI /* check for unrecoverable exception */
|
||||
beq 1f /* Deliver a machine check to guest */
|
||||
ld r10, VCPU_PC(r9)
|
||||
|
@ -919,21 +919,17 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
|
||||
r = -ENXIO;
|
||||
break;
|
||||
}
|
||||
vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
|
||||
val.vval = vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0];
|
||||
break;
|
||||
case KVM_REG_PPC_VSCR:
|
||||
if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
|
||||
r = -ENXIO;
|
||||
break;
|
||||
}
|
||||
vcpu->arch.vr.vscr.u[3] = set_reg_val(reg->id, val);
|
||||
val = get_reg_val(reg->id, vcpu->arch.vr.vscr.u[3]);
|
||||
break;
|
||||
case KVM_REG_PPC_VRSAVE:
|
||||
if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
|
||||
r = -ENXIO;
|
||||
break;
|
||||
}
|
||||
vcpu->arch.vrsave = set_reg_val(reg->id, val);
|
||||
val = get_reg_val(reg->id, vcpu->arch.vrsave);
|
||||
break;
|
||||
#endif /* CONFIG_ALTIVEC */
|
||||
default:
|
||||
@ -974,17 +970,21 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
|
||||
r = -ENXIO;
|
||||
break;
|
||||
}
|
||||
val.vval = vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0];
|
||||
vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
|
||||
break;
|
||||
case KVM_REG_PPC_VSCR:
|
||||
if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
|
||||
r = -ENXIO;
|
||||
break;
|
||||
}
|
||||
val = get_reg_val(reg->id, vcpu->arch.vr.vscr.u[3]);
|
||||
vcpu->arch.vr.vscr.u[3] = set_reg_val(reg->id, val);
|
||||
break;
|
||||
case KVM_REG_PPC_VRSAVE:
|
||||
val = get_reg_val(reg->id, vcpu->arch.vrsave);
|
||||
if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
|
||||
r = -ENXIO;
|
||||
break;
|
||||
}
|
||||
vcpu->arch.vrsave = set_reg_val(reg->id, val);
|
||||
break;
|
||||
#endif /* CONFIG_ALTIVEC */
|
||||
default:
|
||||
|
@ -546,7 +546,6 @@ struct kvm_vcpu_arch {
|
||||
struct kvm_s390_sie_block *sie_block;
|
||||
unsigned int host_acrs[NUM_ACRS];
|
||||
struct fpu host_fpregs;
|
||||
struct fpu guest_fpregs;
|
||||
struct kvm_s390_local_interrupt local_int;
|
||||
struct hrtimer ckc_timer;
|
||||
struct kvm_s390_pgm_info pgm;
|
||||
|
@ -29,6 +29,7 @@ config KVM
|
||||
select HAVE_KVM_IRQFD
|
||||
select HAVE_KVM_IRQ_ROUTING
|
||||
select SRCU
|
||||
select KVM_VFIO
|
||||
---help---
|
||||
Support hosting paravirtualized guest machines using the SIE
|
||||
virtualization capability on the mainframe. This should work
|
||||
|
@ -7,7 +7,7 @@
|
||||
# as published by the Free Software Foundation.
|
||||
|
||||
KVM := ../../../virt/kvm
|
||||
common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o $(KVM)/irqchip.o
|
||||
common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o $(KVM)/irqchip.o $(KVM)/vfio.o
|
||||
|
||||
ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
|
||||
|
||||
|
@ -1423,44 +1423,18 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Backs up the current FP/VX register save area on a particular
|
||||
* destination. Used to switch between different register save
|
||||
* areas.
|
||||
*/
|
||||
static inline void save_fpu_to(struct fpu *dst)
|
||||
{
|
||||
dst->fpc = current->thread.fpu.fpc;
|
||||
dst->regs = current->thread.fpu.regs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Switches the FP/VX register save area from which to lazy
|
||||
* restore register contents.
|
||||
*/
|
||||
static inline void load_fpu_from(struct fpu *from)
|
||||
{
|
||||
current->thread.fpu.fpc = from->fpc;
|
||||
current->thread.fpu.regs = from->regs;
|
||||
}
|
||||
|
||||
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||
{
|
||||
/* Save host register state */
|
||||
save_fpu_regs();
|
||||
save_fpu_to(&vcpu->arch.host_fpregs);
|
||||
|
||||
if (test_kvm_facility(vcpu->kvm, 129)) {
|
||||
current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
|
||||
/*
|
||||
* Use the register save area in the SIE-control block
|
||||
* for register restore and save in kvm_arch_vcpu_put()
|
||||
*/
|
||||
current->thread.fpu.vxrs =
|
||||
(__vector128 *)&vcpu->run->s.regs.vrs;
|
||||
} else
|
||||
load_fpu_from(&vcpu->arch.guest_fpregs);
|
||||
vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
|
||||
vcpu->arch.host_fpregs.regs = current->thread.fpu.regs;
|
||||
|
||||
/* Depending on MACHINE_HAS_VX, data stored to vrs either
|
||||
* has vector register or floating point register format.
|
||||
*/
|
||||
current->thread.fpu.regs = vcpu->run->s.regs.vrs;
|
||||
current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
|
||||
if (test_fp_ctl(current->thread.fpu.fpc))
|
||||
/* User space provided an invalid FPC, let's clear it */
|
||||
current->thread.fpu.fpc = 0;
|
||||
@ -1476,19 +1450,13 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
atomic_andnot(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
|
||||
gmap_disable(vcpu->arch.gmap);
|
||||
|
||||
/* Save guest register state */
|
||||
save_fpu_regs();
|
||||
vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
|
||||
|
||||
if (test_kvm_facility(vcpu->kvm, 129))
|
||||
/*
|
||||
* kvm_arch_vcpu_load() set up the register save area to
|
||||
* the &vcpu->run->s.regs.vrs and, thus, the vector registers
|
||||
* are already saved. Only the floating-point control must be
|
||||
* copied.
|
||||
*/
|
||||
vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
|
||||
else
|
||||
save_fpu_to(&vcpu->arch.guest_fpregs);
|
||||
load_fpu_from(&vcpu->arch.host_fpregs);
|
||||
/* Restore host register state */
|
||||
current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
|
||||
current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
|
||||
|
||||
save_access_regs(vcpu->run->s.regs.acrs);
|
||||
restore_access_regs(vcpu->arch.host_acrs);
|
||||
@ -1506,8 +1474,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
|
||||
memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
|
||||
vcpu->arch.sie_block->gcr[0] = 0xE0UL;
|
||||
vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
|
||||
vcpu->arch.guest_fpregs.fpc = 0;
|
||||
asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc));
|
||||
/* make sure the new fpc will be lazily loaded */
|
||||
save_fpu_regs();
|
||||
current->thread.fpu.fpc = 0;
|
||||
vcpu->arch.sie_block->gbea = 1;
|
||||
vcpu->arch.sie_block->pp = 0;
|
||||
vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
|
||||
@ -1648,17 +1617,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
|
||||
vcpu->arch.local_int.wq = &vcpu->wq;
|
||||
vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
|
||||
|
||||
/*
|
||||
* Allocate a save area for floating-point registers. If the vector
|
||||
* extension is available, register contents are saved in the SIE
|
||||
* control block. The allocated save area is still required in
|
||||
* particular places, for example, in kvm_s390_vcpu_store_status().
|
||||
*/
|
||||
vcpu->arch.guest_fpregs.fprs = kzalloc(sizeof(freg_t) * __NUM_FPRS,
|
||||
GFP_KERNEL);
|
||||
if (!vcpu->arch.guest_fpregs.fprs)
|
||||
goto out_free_sie_block;
|
||||
|
||||
rc = kvm_vcpu_init(vcpu, kvm, id);
|
||||
if (rc)
|
||||
goto out_free_sie_block;
|
||||
@ -1879,19 +1837,27 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
|
||||
|
||||
int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
|
||||
{
|
||||
/* make sure the new values will be lazily loaded */
|
||||
save_fpu_regs();
|
||||
if (test_fp_ctl(fpu->fpc))
|
||||
return -EINVAL;
|
||||
memcpy(vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
|
||||
vcpu->arch.guest_fpregs.fpc = fpu->fpc;
|
||||
save_fpu_regs();
|
||||
load_fpu_from(&vcpu->arch.guest_fpregs);
|
||||
current->thread.fpu.fpc = fpu->fpc;
|
||||
if (MACHINE_HAS_VX)
|
||||
convert_fp_to_vx(current->thread.fpu.vxrs, (freg_t *)fpu->fprs);
|
||||
else
|
||||
memcpy(current->thread.fpu.fprs, &fpu->fprs, sizeof(fpu->fprs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
|
||||
{
|
||||
memcpy(&fpu->fprs, vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
|
||||
fpu->fpc = vcpu->arch.guest_fpregs.fpc;
|
||||
/* make sure we have the latest values */
|
||||
save_fpu_regs();
|
||||
if (MACHINE_HAS_VX)
|
||||
convert_vx_to_fp((freg_t *)fpu->fprs, current->thread.fpu.vxrs);
|
||||
else
|
||||
memcpy(fpu->fprs, current->thread.fpu.fprs, sizeof(fpu->fprs));
|
||||
fpu->fpc = current->thread.fpu.fpc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2396,6 +2362,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
|
||||
int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
|
||||
{
|
||||
unsigned char archmode = 1;
|
||||
freg_t fprs[NUM_FPRS];
|
||||
unsigned int px;
|
||||
u64 clkcomp;
|
||||
int rc;
|
||||
@ -2411,8 +2378,16 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
|
||||
gpa = px;
|
||||
} else
|
||||
gpa -= __LC_FPREGS_SAVE_AREA;
|
||||
rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
|
||||
vcpu->arch.guest_fpregs.fprs, 128);
|
||||
|
||||
/* manually convert vector registers if necessary */
|
||||
if (MACHINE_HAS_VX) {
|
||||
convert_vx_to_fp(fprs, current->thread.fpu.vxrs);
|
||||
rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
|
||||
fprs, 128);
|
||||
} else {
|
||||
rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
|
||||
vcpu->run->s.regs.vrs, 128);
|
||||
}
|
||||
rc |= write_guest_abs(vcpu, gpa + __LC_GPREGS_SAVE_AREA,
|
||||
vcpu->run->s.regs.gprs, 128);
|
||||
rc |= write_guest_abs(vcpu, gpa + __LC_PSW_SAVE_AREA,
|
||||
@ -2420,7 +2395,7 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
|
||||
rc |= write_guest_abs(vcpu, gpa + __LC_PREFIX_SAVE_AREA,
|
||||
&px, 4);
|
||||
rc |= write_guest_abs(vcpu, gpa + __LC_FP_CREG_SAVE_AREA,
|
||||
&vcpu->arch.guest_fpregs.fpc, 4);
|
||||
&vcpu->run->s.regs.fpc, 4);
|
||||
rc |= write_guest_abs(vcpu, gpa + __LC_TOD_PROGREG_SAVE_AREA,
|
||||
&vcpu->arch.sie_block->todpr, 4);
|
||||
rc |= write_guest_abs(vcpu, gpa + __LC_CPU_TIMER_SAVE_AREA,
|
||||
@ -2443,19 +2418,7 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
|
||||
* it into the save area
|
||||
*/
|
||||
save_fpu_regs();
|
||||
if (test_kvm_facility(vcpu->kvm, 129)) {
|
||||
/*
|
||||
* If the vector extension is available, the vector registers
|
||||
* which overlaps with floating-point registers are saved in
|
||||
* the SIE-control block. Hence, extract the floating-point
|
||||
* registers and the FPC value and store them in the
|
||||
* guest_fpregs structure.
|
||||
*/
|
||||
vcpu->arch.guest_fpregs.fpc = current->thread.fpu.fpc;
|
||||
convert_vx_to_fp(vcpu->arch.guest_fpregs.fprs,
|
||||
current->thread.fpu.vxrs);
|
||||
} else
|
||||
save_fpu_to(&vcpu->arch.guest_fpregs);
|
||||
vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
|
||||
save_access_regs(vcpu->run->s.regs.acrs);
|
||||
|
||||
return kvm_s390_store_status_unloaded(vcpu, addr);
|
||||
|
Loading…
Reference in New Issue
Block a user