Enable PCI passthru for HVM guest
PATCH 1/4 Enable PCI passthru for HVM guest
1-cleanup.patch:
code cleanup, bug fix, minor enhancements to exsiting amd-iommu codes
Signed-off-by Wei Wang <[email protected]>
xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c +47 -22
@@ -49,14 +49,16 @@ int __init get_iommu_last_downstream_bus iommu->downstream_bus_present[bus] =1 ; dev =PCI_SLOT (iommu->first_devfn); multi_func =PCI_FUNC (iommu->first_devfn) >0 ; -for ( devfn = iommu->first_devfn; devfn <= iommu->last_devfn; ++devfn ) { +for ( devfn = iommu->first_devfn; devfn <= iommu->last_devfn; ++devfn ) + {/* skipping to next device#? */ -if ( dev !=PCI_SLOT (devfn) ) { +if ( dev !=PCI_SLOT (devfn) ) + { dev =PCI_SLOT (devfn); multi_func =0 ; } func =PCI_FUNC (devfn); - +if ( !VALID_PCI_VENDOR_ID (read_pci_config_16 (bus, dev, func,PCI_VENDOR_ID )) )continue ;
@@ -67,7 +69,8 @@ int __init get_iommu_last_downstream_bus multi_func =IS_PCI_MULTI_FUNCTION (hdr_type);if ( (func ==0 || multi_func) && -IS_PCI_TYPE1_HEADER (hdr_type) ) { +IS_PCI_TYPE1_HEADER (hdr_type) ) + {if (!valid_bridge_bus_config (bus, dev, func, &sec_bus, &sub_bus))return -ENODEV ;
@@ -86,28 +89,37 @@ int __init get_iommu_capabilities(u8 busint __init get_iommu_capabilities (u8 bus,u8 dev,u8 func,u8 cap_ptr,struct amd_iommu *iommu) { -u32 cap_header, cap_range; +u32 cap_header, cap_range, misc_info;u64 mmio_bar;/* remove it when BIOS available */ +#if HACK_BIOS_SETTINGS +/* set MMIO base address for IOMMU */ +static u32 mmio_hi =0x0 ; +static u32 mmio_lo =0xF0010001 ; +write_pci_config (bus, dev, func, - cap_ptr +PCI_CAP_MMIO_BAR_HIGH_OFFSET ,0x00000000 ); + cap_ptr +PCI_CAP_MMIO_BAR_HIGH_OFFSET , mmio_hi);write_pci_config (bus, dev, func, - cap_ptr +PCI_CAP_MMIO_BAR_LOW_OFFSET ,0x40000001 ); + cap_ptr +PCI_CAP_MMIO_BAR_LOW_OFFSET , mmio_lo); + mmio_lo +=0x10000 ; +#endif /* remove it when BIOS available */ mmio_bar = (u64 )read_pci_config (bus, dev, func, cap_ptr +PCI_CAP_MMIO_BAR_HIGH_OFFSET ) <<32 ; mmio_bar |=read_pci_config (bus, dev, func, - cap_ptr +PCI_CAP_MMIO_BAR_LOW_OFFSET ) & -PCI_CAP_MMIO_BAR_LOW_MASK ; - iommu->mmio_base_phys = (unsigned long )mmio_bar; - -if ( (mmio_bar ==0 ) || ( (mmio_bar &0x3FFF ) !=0 ) ) { -dprintk (XENLOG_ERR , -"AMD IOMMU: Invalid MMIO_BAR = 0x%" PRIx64"\n" , mmio_bar); + cap_ptr +PCI_CAP_MMIO_BAR_LOW_OFFSET ); + iommu->mmio_base_phys = mmio_bar & (u64 )~0x3FFF ; + +if ((mmio_bar &0x1 ) ==0 || iommu->mmio_base_phys ==0 ) + { + IOV_DPRINTK(XENLOG_ERR IOVPREFIX, + "Invalid MMIO_BAR = 0x%"PRIx64"\n", mmio_bar);return -ENODEV ; } + + iommu->device_id = (bus <<8 ) |PCI_DEVFN (dev, func); cap_header =read_pci_config (bus, dev, func, cap_ptr); iommu->revision = get_field_from_reg_u32(cap_header,
@@ -133,6 +145,11 @@ int __init get_iommu_capabilities(u8 busPCI_CAP_LAST_DEVICE_MASK , PCI_CAP_LAST_DEVICE_SHIFT); + misc_info =read_pci_config (bus, dev, func, + cap_ptr +PCI_CAP_MISC_INFO_OFFSET ); + iommu->msi_number =get_field_from_reg_u32 (misc_info, +PCI_CAP_MSI_NUMBER_MASK , +PCI_CAP_MSI_NUMBER_SHIFT );return 0 ; }
@@ -147,16 +164,19 @@ static int __init scan_caps_for_iommu(in cap_ptr =read_pci_config_byte (bus, dev, func,PCI_CAPABILITY_LIST );while ( cap_ptr >=PCI_MIN_CAP_OFFSET && - count <PCI_MAX_CAP_BLOCKS && !error ) { + count <PCI_MAX_CAP_BLOCKS && !error ) + { cap_ptr &=PCI_CAP_PTR_MASK ; cap_header =read_pci_config (bus, dev, func, cap_ptr); cap_id =get_field_from_reg_u32 (cap_header,PCI_CAP_ID_MASK ,PCI_CAP_ID_SHIFT ); -if ( cap_id ==PCI_CAP_ID_SECURE_DEVICE ) { +if ( cap_id ==PCI_CAP_ID_SECURE_DEVICE ) + { cap_type =get_field_from_reg_u32 (cap_header,PCI_CAP_TYPE_MASK ,PCI_CAP_TYPE_SHIFT ); -if ( cap_type ==PCI_CAP_TYPE_IOMMU ) { +if ( cap_type ==PCI_CAP_TYPE_IOMMU ) + { error =iommu_detect_callback ( bus, dev, func, cap_ptr); }
@@ -164,7 +184,8 @@ static int __init scan_caps_for_iommu(in cap_ptr =get_field_from_reg_u32 (cap_header,PCI_CAP_NEXT_PTR_MASK ,PCI_CAP_NEXT_PTR_SHIFT ); - ++count; } + ++count; + }return error; }
@@ -178,7 +199,8 @@ static int __init scan_functions_for_iom func =0 ; count =1 ;while (VALID_PCI_VENDOR_ID (read_pci_config_16 (bus, dev, func, -PCI_VENDOR_ID )) && !error && func < count ) { +PCI_VENDOR_ID )) && !error && func < count ) + { hdr_type =read_pci_config_byte (bus, dev, func,PCI_HEADER_TYPE );
@@ -186,7 +208,8 @@ static int __init scan_functions_for_iom count =PCI_MAX_FUNC_COUNT ;if (IS_PCI_TYPE0_HEADER (hdr_type) || -IS_PCI_TYPE1_HEADER (hdr_type) ) { +IS_PCI_TYPE1_HEADER (hdr_type) ) + { error =scan_caps_for_iommu (bus, dev, func, iommu_detect_callback); }
@@ -201,8 +224,10 @@ int __init scan_for_iommu(iommu_detect_c {int bus, dev, error =0 ; -for ( bus =0 ; bus <PCI_MAX_BUS_COUNT && !error; ++bus ) { -for ( dev =0 ; dev <PCI_MAX_DEV_COUNT && !error; ++dev ) { +for ( bus =0 ; bus <PCI_MAX_BUS_COUNT && !error; ++bus ) + { +for ( dev =0 ; dev <PCI_MAX_DEV_COUNT && !error; ++dev ) + { error =scan_functions_for_iommu (bus, dev, iommu_detect_callback); }
xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-init.c +75 -11
120 lines not on this page · raw message
xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c +82 -31
224 lines not on this page · raw message
xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c +215 -103
497 lines not on this page · raw message
xen/include/asm-x86/amd-iommu.h +10 -0
@@ -32,6 +32,11 @@ extern struct list_head amd_iommu_head;extern struct list_head amd_iommu_head;extern int __init amd_iommu_detect (void ); +extern int amd_iommu_domain_init (struct domain *domain); +extern int amd_iommu_map_page (struct domain *d,unsigned long gfn, +unsigned long mfn); +extern int amd_iommu_unmap_page (struct domain *d,unsigned long gfn); +struct table_struct {void *buffer;
@@ -47,6 +52,9 @@ struct amd_iommu {int ht_tunnel_support;int not_present_cached;u8 revision; +u8 msi_number; + +u16 device_id;u8 root_bus;u8 first_devfn;
@@ -61,6 +69,8 @@ struct amd_iommu {struct table_struct dev_table;struct table_struct cmd_buffer;u32 cmd_buffer_tail; +struct table_struct event_log; +u32 event_log_head;int exclusion_enabled;unsigned long exclusion_base;
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +22 -0
@@ -35,6 +35,9 @@/* IOMMU Command Buffer entries: in power of 2 increments, minimum of 256 */ #define IOMMU_CMD_BUFFER_DEFAULT_ENTRIES 512 +/* IOMMU Event Log entries: in power of 2 increments, minimum of 256 */ +#define IOMMU_EVENT_LOG_DEFAULT_ENTRIES 512 +#define BITMAP_ENTRIES_PER_BYTE 8#define PTE_PER_TABLE_SHIFT 9
@@ -118,6 +121,10 @@#define PCI_CAP_LAST_DEVICE_MASK 0xFF000000#define PCI_CAP_LAST_DEVICE_SHIFT 24 +#define PCI_CAP_MISC_INFO_OFFSET 0x10 +#define PCI_CAP_MSI_NUMBER_MASK 0x0000001F +#define PCI_CAP_MSI_NUMBER_SHIFT 0 +/* Device Table */ #define IOMMU_DEV_TABLE_BASE_LOW_OFFSET 0x00#define IOMMU_DEV_TABLE_BASE_HIGH_OFFSET 0x04
@@ -262,6 +269,10 @@#define IOMMU_INV_IOMMU_PAGES_ADDR_LOW_SHIFT 12#define IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK 0xFFFFFFFF#define IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT 0 + +/* INVALIDATE_DEVTAB_ENTRY command */ +#define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_MASK 0x0000FFFF +#define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_SHIFT 0/* Event Log */ #define IOMMU_EVENT_LOG_BASE_LOW_OFFSET 0x10
@@ -415,5 +426,16 @@#define IOMMU_PAGE_TABLE_LEVEL_4 4#define IOMMU_IO_WRITE_ENABLED 1#define IOMMU_IO_READ_ENABLED 1 +#define IOVPREFIX "AMD IOV: " +#define CONFIG_AMD_IOMMU_DEBUG 1 + +/* HT1100 enablement */ +#define ENABLE_HT1100 1 +#define SET_FC_IN_PTE 1 +#define HACK_BIOS_SETTINGS 1 +#define HACK_MMIO_ON_CPU1 0 +#define HACK_ISOC_SETTINGS 0 +#define HACK_ISOC_ON_CPU1 0 +/* HT1100 enablement */ #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */
xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +19 -8
@@ -27,11 +27,23 @@list_for_each_entry (amd_iommu, \ &amd_iommu_head, list) +#define for_each_pdev (domain, pdev) \ + list_for_each_entry(pdev, \ + &(domain->arch.hvm_domain.hvm_iommu.pdev_list), list) +#define DMA_32BIT_MASK 0x00000000ffffffffULL#define PAGE_ALIGN (addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)#define PAGE_SHIFT_4K (12)#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K)#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K) + +#ifdef CONFIG_AMD_IOMMU_DEBUG +#define IOV_DPRINTK dprintk +#define IOV_GDPRINTK gdprintk +#else +#define IOV_DPRINTK(s, a...) +#define IOV_GDPRINTK(s, a...) +#endif typedef int (*iommu_detect_callback_ptr_t )(u8 bus,u8 dev,u8 func,u8 cap_ptr);
@@ -46,24 +58,23 @@ void __init unmap_iommu_mmio_region(struvoid __init unmap_iommu_mmio_region (struct amd_iommu *iommu);void __init register_iommu_dev_table_in_mmio_space (struct amd_iommu *iommu);void __init register_iommu_cmd_buffer_in_mmio_space (struct amd_iommu *iommu); +void __init register_iommu_event_log_in_mmio_space (struct amd_iommu *iommu); +void __init enable_iommu (struct amd_iommu *iommu);/* mapping functions */ -int amd_iommu_map_page (struct domain *d,unsigned long gfn, -unsigned long mfn); -int amd_iommu_unmap_page (struct domain *d,unsigned long gfn); +void *amd_iommu_get_vptr_from_page_table_entry (u32 *entry);/* device table functions */ void amd_iommu_set_dev_table_entry (u32 *dte,u64 root_ptr,u16 domain_id,u8 paging_mode); +void invalidate_dev_table_entry (struct amd_iommu *iommu, +u16 devic_id); +int amd_iommu_is_dte_page_translation_valid (u32 *entry);/* send cmd to iommu */ int send_iommu_command (struct amd_iommu *iommu,u32 cmd[]); - -/* iommu domain funtions */ -int amd_iommu_domain_init (struct domain *domain); -void amd_iommu_setup_domain_device (struct domain *domain, -struct amd_iommu *iommu,int requestor_id); +void flush_command_buffer (struct amd_iommu *iommu);/* find iommu for bdf */ struct amd_iommu *find_iommu_for_device (int bus,int devfn);
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel