Skip to content

Commit 31ed024

Browse files
yanzhao56rpedgeco
authored andcommitted
KVM: TDX: Add a method to ignore updating CPU dirty logging request for TDs
Add a method to ignore requests to update CPU dirty logging for TDs, as basic TDX does not support the PML feature, and KVM TDX does not allocate or flush PML buffers for TDs. Do not invoke vmx_update_cpu_dirty_logging() for TDs, and doing so would cause a NULL pointer access error. This is to fix the issue first reported in [1], where QEMU attaches an emulated VGA device to a TD, resulting in a "kernel NULL pointer dereference" in the host. In QEMU, vga_common_init() sets the vram memory region to have a dirty_log_mask with bit DIRTY_MEMORY_VGA. pci_cirrus_vga_realize vga_common_init vga_dirty_log_start memory_region_set_log mr->dirty_log_mask = 1 << DIRTY_MEMORY_VGA; QEMU's KVM acceleration code checks if mr->dirty_log_mask is non-zero before setting the KVM_MEM_LOG_DIRTY_PAGES flag for the corresponding memslot (which has no flag KVM_MEM_GUEST_MEMFD) in KVM. This causes KVM to detect that a memslot has the KVM_MEM_LOG_DIRTY_PAGES flag and invoke kvm_mmu_update_cpu_dirty_logging() --> vmx_update_cpu_dirty_logging() to turn on PML, leading to the NULL pointer access error. Reported-by: ANAND NARSHINHA PATIL <[email protected]> Reported-by: Pedro Principeza <[email protected]> Reported-by: Farrah Chen <[email protected]> Closes: canonical/tdx#202 Link: canonical/tdx#202 [1] Signed-off-by: Yan Zhao <[email protected]>
1 parent f197627 commit 31ed024

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

arch/x86/kvm/vmx/main.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,18 @@ static int vt_handle_exit(struct kvm_vcpu *vcpu,
182182
return vmx_handle_exit(vcpu, fastpath);
183183
}
184184

185+
static void vt_update_cpu_dirty_logging(struct kvm_vcpu *vcpu)
186+
{
187+
/*
188+
* Basic TDX does not support feature PML. KVM does not enable PML in
189+
* TD's VMCS, nor does it allocate or flush PML buffer for TDX.
190+
*/
191+
if (WARN_ON_ONCE(is_td_vcpu(vcpu)))
192+
return;
193+
194+
vmx_update_cpu_dirty_logging(vcpu);
195+
}
196+
185197
static int vt_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
186198
{
187199
if (unlikely(is_td_vcpu(vcpu)))
@@ -993,7 +1005,7 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
9931005
.handle_exit_irqoff = vmx_handle_exit_irqoff,
9941006

9951007
.cpu_dirty_log_size = PML_LOG_NR_ENTRIES,
996-
.update_cpu_dirty_logging = vmx_update_cpu_dirty_logging,
1008+
.update_cpu_dirty_logging = vt_update_cpu_dirty_logging,
9971009

9981010
.nested_ops = &vmx_nested_ops,
9991011

0 commit comments

Comments
 (0)