diff --git a/hypervisor/arch/x86/ept.c b/hypervisor/arch/x86/ept.c index 0371d6621..a3b7ce0a9 100644 --- a/hypervisor/arch/x86/ept.c +++ b/hypervisor/arch/x86/ept.c @@ -187,7 +187,7 @@ void ept_mr_add(struct acrn_vm *vm, uint64_t *pml4_page, * to force snooping of PCIe devices if the page * is cachable */ - if ((prot & EPT_MT_MASK) != EPT_UNCACHED) { + if (((prot & EPT_MT_MASK) != EPT_UNCACHED) && vm->snoopy_mem) { prot |= EPT_SNOOP_CTRL; } @@ -207,7 +207,7 @@ void ept_mr_modify(struct acrn_vm *vm, uint64_t *pml4_page, dev_dbg(ACRN_DBG_EPT, "%s,vm[%d] gpa 0x%llx size 0x%llx\n", __func__, vm->vm_id, gpa, size); - if ((prot_set & EPT_MT_MASK) != EPT_UNCACHED) { + if (((prot_set & EPT_MT_MASK) != EPT_UNCACHED) && vm->snoopy_mem) { prot_set |= EPT_SNOOP_CTRL; } diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 3f0ebb376..6d2d7b5cd 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -87,6 +87,7 @@ int32_t create_vm(struct vm_description *vm_desc, struct acrn_vm **rtn_vm) #endif vm->hw.created_vcpus = 0U; vm->emul_mmio_regions = 0U; + vm->snoopy_mem = true; /* gpa_lowtop are used for system start up */ vm->hw.gpa_lowtop = 0UL; @@ -98,6 +99,7 @@ int32_t create_vm(struct vm_description *vm_desc, struct acrn_vm **rtn_vm) /* Only for SOS: Configure VM software information */ /* For UOS: This VM software information is configure in DM */ if (is_vm0(vm)) { + vm->snoopy_mem = false; rebuild_vm0_e820(); status = prepare_vm0_memmap(vm); if (status != 0) { diff --git a/hypervisor/arch/x86/vtd.c b/hypervisor/arch/x86/vtd.c index 8b82ce05e..ed84a438a 100644 --- a/hypervisor/arch/x86/vtd.c +++ b/hypervisor/arch/x86/vtd.c @@ -834,6 +834,7 @@ static int32_t add_iommu_device(struct iommu_domain *domain, uint16_t segment, u struct dmar_context_entry *context_entry; uint64_t upper; uint64_t lower = 0UL; + struct acrn_vm *vm; dmar_unit = device_to_dmaru(segment, bus, devfun); if (dmar_unit == NULL) { @@ -852,6 +853,11 @@ static int32_t add_iommu_device(struct iommu_domain *domain, uint16_t segment, u } if (iommu_ecap_sc(dmar_unit->ecap) == 0U) { + vm = get_vm_from_vmid(domain->vm_id); + if (vm != NULL) { + vm->snoopy_mem = false; + } + // TODO: remove iommu_snoop from iommu_domain domain->iommu_snoop = false; dev_dbg(ACRN_DBG_IOMMU, "vm=%d add %x:%x no snoop control!", domain->vm_id, bus, devfun); } diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index ebccbd30d..8ac7a89ab 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -160,6 +160,7 @@ struct acrn_vm { spinlock_t softirq_dev_lock; struct list_head softirq_dev_entry_list; uint64_t intr_inject_delay_delta; /* delay of intr injection */ + bool snoopy_mem; } __aligned(PAGE_SIZE); #ifdef CONFIG_PARTITION_MODE