]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
LoongArch: KVM: Fix GPA size issue about VM
authorBibo Mao <maobibo@loongson.cn>
Sat, 8 Mar 2025 05:52:04 +0000 (13:52 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Mar 2025 12:01:50 +0000 (13:01 +0100)
commit 6bdbb73dc8d99fbb77f5db79dbb6f108708090b4 upstream.

Physical address space is 48 bit on Loongson-3A5000 physical machine,
however it is 47 bit for VM on Loongson-3A5000 system. Size of physical
address space of VM is the same with the size of virtual user space (a
half) of physical machine.

Variable cpu_vabits represents user address space, kernel address space
is not included (user space and kernel space are both a half of total).
Here cpu_vabits, rather than cpu_vabits - 1, is to represent the size of
guest physical address space.

Also there is strict checking about page fault GPA address, inject error
if it is larger than maximum GPA address of VM.

Cc: stable@vger.kernel.org
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/loongarch/kvm/exit.c
arch/loongarch/kvm/vm.c

index 90894f70ff4a50083799648cb71ffbbb10f5fcc4..add52e927f1530cfc8b3d31f04d192d6a238c702 100644 (file)
@@ -624,6 +624,12 @@ static int kvm_handle_rdwr_fault(struct kvm_vcpu *vcpu, bool write)
        struct kvm_run *run = vcpu->run;
        unsigned long badv = vcpu->arch.badv;
 
+       /* Inject ADE exception if exceed max GPA size */
+       if (unlikely(badv >= vcpu->kvm->arch.gpa_size)) {
+               kvm_queue_exception(vcpu, EXCCODE_ADE, EXSUBCODE_ADEM);
+               return RESUME_GUEST;
+       }
+
        ret = kvm_handle_mm_fault(vcpu, badv, write);
        if (ret) {
                /* Treat as MMIO */
index 4ba734aaef87a796da4d97e67dcb3fb680b6cef2..fe9e973912d440868d4d98a08dc44b3c6eddcfb5 100644 (file)
@@ -46,7 +46,11 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        if (kvm_pvtime_supported())
                kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME);
 
-       kvm->arch.gpa_size = BIT(cpu_vabits - 1);
+       /*
+        * cpu_vabits means user address space only (a half of total).
+        * GPA size of VM is the same with the size of user address space.
+        */
+       kvm->arch.gpa_size = BIT(cpu_vabits);
        kvm->arch.root_level = CONFIG_PGTABLE_LEVELS - 1;
        kvm->arch.invalid_ptes[0] = 0;
        kvm->arch.invalid_ptes[1] = (unsigned long)invalid_pte_table;