Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull kvm fixes from Paolo Bonzini: - Allow again loading KVM on 32-bit non-PAE builds - Fixes for host SMIs on AMD - Fixes for guest SMIs on AMD - Fixes for selftests on s390 and ARM - Fix memory leak - Enforce no-instrumentation area on vmentry when hardware breakpoints are in use. * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (25 commits) KVM: selftests: smm_test: Test SMM enter from L2 KVM: nSVM: Restore nested control upon leaving SMM KVM: nSVM: Fix L1 state corruption upon return from SMM KVM: nSVM: Introduce svm_copy_vmrun_state() KVM: nSVM: Check that VM_HSAVE_PA MSR was set before VMRUN KVM: nSVM: Check the value written to MSR_VM_HSAVE_PA KVM: SVM: Fix sev_pin_memory() error checks in SEV migration utilities KVM: SVM: Return -EFAULT if copy_to_user() for SEV mig packet header fails KVM: SVM: add module param to control the #SMI interception KVM: SVM: remove INIT intercept handler KVM: SVM: #SMI interception must not skip the instruction KVM: VMX: Remove vmx_msr_index from vmx.h KVM: X86: Disable hardware breakpoints unconditionally before kvm_x86->run() KVM: selftests: Address extra memslot parameters in vm_vaddr_alloc kvm: debugfs: fix memory leak in kvm_create_vm_debugfs KVM: x86/pmu: Clear anythread deprecated bit when 0xa leaf is unsupported on the SVM KVM: mmio: Fix use-after-free Read in kvm_vm_ioctl_unregister_coalesced_mmio KVM: SVM: Revert clearing of C-bit on GPA in #NPF handler KVM: x86/mmu: Do not apply HPA (memory encryption) mask to GPAs KVM: x86: Use kernel's x86_phys_bits to handle reduced MAXPHYADDR ...
This commit is contained in:
@@ -45,6 +45,7 @@ enum vm_guest_mode {
|
||||
VM_MODE_P40V48_64K,
|
||||
VM_MODE_PXXV48_4K, /* For 48bits VA but ANY bits PA */
|
||||
VM_MODE_P47V64_4K,
|
||||
VM_MODE_P44V64_4K,
|
||||
NUM_VM_MODES,
|
||||
};
|
||||
|
||||
@@ -62,7 +63,7 @@ enum vm_guest_mode {
|
||||
|
||||
#elif defined(__s390x__)
|
||||
|
||||
#define VM_MODE_DEFAULT VM_MODE_P47V64_4K
|
||||
#define VM_MODE_DEFAULT VM_MODE_P44V64_4K
|
||||
#define MIN_PAGE_SHIFT 12U
|
||||
#define ptes_per_page(page_size) ((page_size) / 16)
|
||||
|
||||
|
||||
@@ -401,7 +401,7 @@ unexpected_exception:
|
||||
void vm_init_descriptor_tables(struct kvm_vm *vm)
|
||||
{
|
||||
vm->handlers = vm_vaddr_alloc(vm, sizeof(struct handlers),
|
||||
vm->page_size, 0, 0);
|
||||
vm->page_size);
|
||||
|
||||
*(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,22 @@ void guest_modes_append_default(void)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef __s390x__
|
||||
{
|
||||
int kvm_fd, vm_fd;
|
||||
struct kvm_s390_vm_cpu_processor info;
|
||||
|
||||
kvm_fd = open_kvm_dev_path_or_exit();
|
||||
vm_fd = ioctl(kvm_fd, KVM_CREATE_VM, 0);
|
||||
kvm_device_access(vm_fd, KVM_S390_VM_CPU_MODEL,
|
||||
KVM_S390_VM_CPU_PROCESSOR, &info, false);
|
||||
close(vm_fd);
|
||||
close(kvm_fd);
|
||||
/* Starting with z13 we have 47bits of physical address */
|
||||
if (info.ibc >= 0x30)
|
||||
guest_mode_append(VM_MODE_P47V64_4K, true, true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void for_each_guest_mode(void (*func)(enum vm_guest_mode, void *), void *arg)
|
||||
|
||||
@@ -176,6 +176,7 @@ const char *vm_guest_mode_string(uint32_t i)
|
||||
[VM_MODE_P40V48_64K] = "PA-bits:40, VA-bits:48, 64K pages",
|
||||
[VM_MODE_PXXV48_4K] = "PA-bits:ANY, VA-bits:48, 4K pages",
|
||||
[VM_MODE_P47V64_4K] = "PA-bits:47, VA-bits:64, 4K pages",
|
||||
[VM_MODE_P44V64_4K] = "PA-bits:44, VA-bits:64, 4K pages",
|
||||
};
|
||||
_Static_assert(sizeof(strings)/sizeof(char *) == NUM_VM_MODES,
|
||||
"Missing new mode strings?");
|
||||
@@ -194,6 +195,7 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = {
|
||||
{ 40, 48, 0x10000, 16 },
|
||||
{ 0, 0, 0x1000, 12 },
|
||||
{ 47, 64, 0x1000, 12 },
|
||||
{ 44, 64, 0x1000, 12 },
|
||||
};
|
||||
_Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES,
|
||||
"Missing new mode params?");
|
||||
@@ -282,6 +284,9 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
|
||||
case VM_MODE_P47V64_4K:
|
||||
vm->pgtable_levels = 5;
|
||||
break;
|
||||
case VM_MODE_P44V64_4K:
|
||||
vm->pgtable_levels = 5;
|
||||
break;
|
||||
default:
|
||||
TEST_FAIL("Unknown guest mode, mode: 0x%x", mode);
|
||||
}
|
||||
|
||||
@@ -377,7 +377,8 @@ static void test_add_max_memory_regions(void)
|
||||
(max_mem_slots - 1), MEM_REGION_SIZE >> 10);
|
||||
|
||||
mem = mmap(NULL, (size_t)max_mem_slots * MEM_REGION_SIZE + alignment,
|
||||
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
|
||||
TEST_ASSERT(mem != MAP_FAILED, "Failed to mmap() host");
|
||||
mem_aligned = (void *)(((size_t) mem + alignment - 1) & ~(alignment - 1));
|
||||
|
||||
|
||||
@@ -615,7 +615,7 @@ int main(void)
|
||||
|
||||
vm_init_descriptor_tables(vm);
|
||||
vcpu_init_descriptor_tables(vm, VCPU_ID);
|
||||
vm_handle_exception(vm, GP_VECTOR, guest_gp_handler);
|
||||
vm_install_exception_handler(vm, GP_VECTOR, guest_gp_handler);
|
||||
|
||||
pr_info("Testing access to Hyper-V specific MSRs\n");
|
||||
guest_test_msrs_access(vm, addr_gva2hva(vm, msr_gva),
|
||||
|
||||
@@ -71,7 +71,7 @@ static void mmu_role_test(u32 *cpuid_reg, u32 evil_cpuid_val)
|
||||
/* Set up a #PF handler to eat the RSVD #PF and signal all done! */
|
||||
vm_init_descriptor_tables(vm);
|
||||
vcpu_init_descriptor_tables(vm, VCPU_ID);
|
||||
vm_handle_exception(vm, PF_VECTOR, guest_pf_handler);
|
||||
vm_install_exception_handler(vm, PF_VECTOR, guest_pf_handler);
|
||||
|
||||
r = _vcpu_run(vm, VCPU_ID);
|
||||
TEST_ASSERT(r == 0, "vcpu_run failed: %d\n", r);
|
||||
|
||||
@@ -53,15 +53,28 @@ static inline void sync_with_host(uint64_t phase)
|
||||
: "+a" (phase));
|
||||
}
|
||||
|
||||
void self_smi(void)
|
||||
static void self_smi(void)
|
||||
{
|
||||
x2apic_write_reg(APIC_ICR,
|
||||
APIC_DEST_SELF | APIC_INT_ASSERT | APIC_DM_SMI);
|
||||
}
|
||||
|
||||
void guest_code(void *arg)
|
||||
static void l2_guest_code(void)
|
||||
{
|
||||
sync_with_host(8);
|
||||
|
||||
sync_with_host(10);
|
||||
|
||||
vmcall();
|
||||
}
|
||||
|
||||
static void guest_code(void *arg)
|
||||
{
|
||||
#define L2_GUEST_STACK_SIZE 64
|
||||
unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
|
||||
uint64_t apicbase = rdmsr(MSR_IA32_APICBASE);
|
||||
struct svm_test_data *svm = arg;
|
||||
struct vmx_pages *vmx_pages = arg;
|
||||
|
||||
sync_with_host(1);
|
||||
|
||||
@@ -74,21 +87,50 @@ void guest_code(void *arg)
|
||||
sync_with_host(4);
|
||||
|
||||
if (arg) {
|
||||
if (cpu_has_svm())
|
||||
generic_svm_setup(arg, NULL, NULL);
|
||||
else
|
||||
GUEST_ASSERT(prepare_for_vmx_operation(arg));
|
||||
if (cpu_has_svm()) {
|
||||
generic_svm_setup(svm, l2_guest_code,
|
||||
&l2_guest_stack[L2_GUEST_STACK_SIZE]);
|
||||
} else {
|
||||
GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
|
||||
GUEST_ASSERT(load_vmcs(vmx_pages));
|
||||
prepare_vmcs(vmx_pages, l2_guest_code,
|
||||
&l2_guest_stack[L2_GUEST_STACK_SIZE]);
|
||||
}
|
||||
|
||||
sync_with_host(5);
|
||||
|
||||
self_smi();
|
||||
|
||||
sync_with_host(7);
|
||||
|
||||
if (cpu_has_svm()) {
|
||||
run_guest(svm->vmcb, svm->vmcb_gpa);
|
||||
svm->vmcb->save.rip += 3;
|
||||
run_guest(svm->vmcb, svm->vmcb_gpa);
|
||||
} else {
|
||||
vmlaunch();
|
||||
vmresume();
|
||||
}
|
||||
|
||||
/* Stages 8-11 are eaten by SMM (SMRAM_STAGE reported instead) */
|
||||
sync_with_host(12);
|
||||
}
|
||||
|
||||
sync_with_host(DONE);
|
||||
}
|
||||
|
||||
void inject_smi(struct kvm_vm *vm)
|
||||
{
|
||||
struct kvm_vcpu_events events;
|
||||
|
||||
vcpu_events_get(vm, VCPU_ID, &events);
|
||||
|
||||
events.smi.pending = 1;
|
||||
events.flags |= KVM_VCPUEVENT_VALID_SMM;
|
||||
|
||||
vcpu_events_set(vm, VCPU_ID, &events);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
vm_vaddr_t nested_gva = 0;
|
||||
@@ -147,6 +189,22 @@ int main(int argc, char *argv[])
|
||||
"Unexpected stage: #%x, got %x",
|
||||
stage, stage_reported);
|
||||
|
||||
/*
|
||||
* Enter SMM during L2 execution and check that we correctly
|
||||
* return from it. Do not perform save/restore while in SMM yet.
|
||||
*/
|
||||
if (stage == 8) {
|
||||
inject_smi(vm);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform save/restore while the guest is in SMM triggered
|
||||
* during L2 execution.
|
||||
*/
|
||||
if (stage == 10)
|
||||
inject_smi(vm);
|
||||
|
||||
state = vcpu_save_state(vm, VCPU_ID);
|
||||
kvm_vm_release(vm);
|
||||
kvm_vm_restart(vm, O_RDWR);
|
||||
|
||||
Reference in New Issue
Block a user