AMD IOMMU: Defer IO pagetable construction until device assignment
PATCH 1/1 AMD IOMMU: Defer IO pagetable construction until device assignment
During HVM domain creation, I/O page tables are filled by coping p2m entries from p2m table, which is a useless step for non-passthru domain. This patch defers I/O page table construction until the moment of device assignment. In case that pci devices are never assigned or hot plugged, the unnecessary duplication will be avoid.
Wei
Signature · 12 lines
AMD Saxony, Dresden, Germany Operating System Research Center Legal Information: AMD Saxony Limited Liability Company & Co. KG Sitz (Geschäftsanschrift): Wilschdorfer Landstr. 101, 01109 Dresden, Deutschland Registergericht Dresden: HRA 4896 vertretungsberechtigter Komplementär: AMD Saxony LLC (Sitz Wilmington, Delaware, USA) Geschäftsführer der AMD Saxony LLC: Dr. Hans-R. Deppe, Thomas McCoy
xen/arch/x86/mm/p2m.c +7 -4
@@ -264,10 +264,13 @@ set_p2m_entry(struct domain *d, unsigned }else if ( boot_cpu_data.x86_vendor ==X86_VENDOR_AMD ) { -if ( p2mt == p2m_ram_rw ) -iommu_map_page (d, gfn,mfn_x (mfn)); -else -iommu_unmap_page (d, gfn); +if ( !list_empty (&domain_hvm_iommu (d)->pdev_list) ) + { +if ( p2mt == p2m_ram_rw ) +iommu_map_page (d, gfn,mfn_x (mfn)); +else +iommu_unmap_page (d, gfn); + } } }
xen/drivers/passthrough/amd/pci_amd_iommu.c +26 -2
@@ -23,6 +23,8 @@#include <asm/hvm/svm/amd-iommu-acpi.h> #include <xen/sched.h> #include <asm/mm.h> +#include <asm/paging.h> +#include <asm/p2m.h> #include "../pci-direct.h" #include "../pci_regs.h"
@@ -550,11 +552,33 @@ static int reassign_device( struct domaireturn 0 ; } +static int construct_p2m_mapping (struct domain *d) +{ +p2m_type_t type; +mfn_t mfn; +unsigned long gfn; + +p2m_lock (d); + +for ( gfn =0 ; gfn < d->tot_pages; gfn++ ) + { + mfn =gfn_to_mfn (d, gfn, &type); +if ( type == p2m_ram_rw ) +amd_iommu_map_page (d, gfn,mfn_x (mfn)); + } + +p2m_unlock (d); +return 0 ; +} +int amd_iommu_assign_device (struct domain *d,u8 bus,u8 devfn) {int bdf = (bus <<8 ) | devfn; -int req_id; - req_id = ivrs_mappings[bdf].dte_requestor_id; +int req_id = ivrs_mappings[bdf].dte_requestor_id; +struct hvm_iommu *hd =domain_hvm_iommu (d); + +if (is_hvm_domain (d) &&list_empty (&hd->pdev_list) ) +construct_p2m_mapping (d);if ( ivrs_mappings[req_id].unity_map_enable ) {
xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +24 -0
@@ -109,4 +109,28 @@ static inline unsigned long region_to_pa return (PAGE_ALIGN(addr + size) - (addr & PAGE_MASK)) >> PAGE_SHIFT; } +/* copy p2m_lock definition from p2m.c */ + +#define p2m_lock (_d) \ + do { \ + if ( unlikely((_d)->arch.p2m.locker == current->processor) )\ + { \ + printk("Error: p2m lock held by %s\n", \ + (_d)->arch.p2m.locker_function); \ + BUG(); \ + } \ + spin_lock(&(_d)->arch.p2m.lock); \ + ASSERT((_d)->arch.p2m.locker == -1); \ + (_d)->arch.p2m.locker = current->processor; \ + (_d)->arch.p2m.locker_function = __func__; \ + } while (0) + +#define p2m_unlock (_d) \ + do { \ + ASSERT((_d)->arch.p2m.locker == current->processor); \ + (_d)->arch.p2m.locker = -1; \ + (_d)->arch.p2m.locker_function = "nobody"; \ + spin_unlock(&(_d)->arch.p2m.lock); \ + } while (0) +#endif /* _ASM_X86_64_AMD_IOMMU_PROTO_H */
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Quoted 5 lines · On 2/4/08 15:13, "Wei Wang2" <[email protected]> wrote:
During HVM domain creation, I/O page tables are filled by coping p2m entries from p2m table, which is a useless step for non-passthru domain. This patch defers I/O page table construction until the moment of device assignment. In case that pci devices are never assigned or hot plugged, the unnecessary duplication will be avoid.
You can't duplicate p2m_lock() and p2m_unlock(). Why do you need to protect your new function with that lock anyway?
-- Keir