Intel IOMMU在Linux上的实现架构

本文详细介绍了Linux系统中Intel IOMMU的实现过程,包括检测DMAR设备、初始化IOMMU设备的具体步骤。文章强调了dmar_table_init函数在解析DMAR表格中的作用,解析了不同类型的结构体,如DRHD和RMRR。同时,文章还讨论了如何处理无映射设备以及DMA操作的注册。最后,概述了DMAR ACPI表格的结构及其在BIOS中的报告方式。
摘要由CSDN通过智能技术生成

1.检测平台是否支持DMAR设备

./drivers/pci/dmar.c->int __init early_dmar_detect(void)

{

        acpi_status status = AE_OK;

 

        /* if we could find DMAR table, then there are DMAR devices */

        status = acpi_get_table(ACPI_SIG_DMAR, 0,

                                (struct acpi_table_header **)&dmar_tbl);

 

        if (ACPI_SUCCESS(status) && !dmar_tbl) {

                printk (KERN_WARNING PREFIX "Unable to map DMAR/n");

                status = AE_NOT_FOUND;

        }

 

        return (ACPI_SUCCESS(status) ? 1 : 0);

}

该函数在内存初始化的时候调用:

 

./arch/x86_64/mm/init.c:528:    pci_iommu_alloc();

 

通过读取 DMA Remapping table,来判断判断是否支持DMAR设备。

 

./include/acpi/actbl1.h:64:#define ACPI_SIG_DMAR           "DMAR"       /* DMA Remapping table */

 

/*******************************************************************************

*

* FUNCTION:    acpi_get_table

*

* PARAMETERS:  table_type      - one of the defined table types

*              Instance        - the non zero instance of the table, allows

*                                support for multiple tables of the same type

*                                see acpi_gbl_acpi_table_flag

*              ret_buffer      - pointer to a structure containing a buffer to

*                                receive the table

*

* RETURN:      Status

*

* DESCRIPTION: This function is called to get an ACPI table.  The caller

*              supplies an out_buffer large enough to contain the entire ACPI

*              table.  The caller should call the acpi_get_table_header function

*              first to determine the buffer size needed.  Upon completion

*              the out_buffer->Length field will indicate the number of bytes

*              copied into the out_buffer->buf_ptr buffer. This table will be

*              a complete table including the header.

*

********************************************************************************/

 

2.初始化Intel IOMMU设备

./drivers/pci/intel-iommu.c

int __init intel_iommu_init(void)

{

        int ret = 0;

 

        if (no_iommu || swiotlb || dmar_disabled)

                return -ENODEV;

 

        if (dmar_table_init())

                return  -ENODEV;

 

        iommu_init_mempool();

        dmar_init_reserved_ranges();

 

        init_no_remapping_devices();

 

        ret = init_dmars();

        if (ret) {

                printk(KERN_ERR "IOMMU: dmar init failed/n");

                put_iova_domain(&reserved_iova_list);

                iommu_exit_mempool();

                return ret;

        }

        printk(KERN_INFO

        "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O/n");

 

        force_iommu = 1;

        dma_ops = &intel_dma_ops;

        return 0;

}

该函数在arch/x86_64/kernel/pci-dma.c

static int __init pci_iommu_init(void)

{

#ifdef CONFIG_CALGARY_IOMMU

        calgary_iommu_init();

#endif

 

        intel_iommu_init();

 

#ifdef CONFIG_IOMMU

        gart_iommu_init();

#endif

 

        no_iommu_init();

        return 0;

}

 

中被调用,同时在该文件中注册为初始化函数:

 

/* Must execute after PCI subsystem */

fs_initcall(pci_iommu_init);

2.1 dmar_table_init

解析DMAR table。逐一打印每个dmar项,

 

dmar_table_print_dmar_entry(entry_header);

 

类似如下的信息在dmesg中出现:

ACPI DMAR:Host address width 36
ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed90000
ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed91000
ACPI DMAR:DRHD (flags: 0x00000001)base: 0x00000000fed93000
ACPI DMAR:RMRR base: 0x00000000000ed000 end: 0x00000000000effff
ACPI DMAR:RMRR base: 0x000000007f600000 end: 0x000000007fffffff

 

switch (entry_header->type) {

case ACPI_DMAR_TYPE_HARDWARE_UNIT:

           ret = dmar_parse_one_drhd(entry_header);

        break;

    case ACPI_DMAR_TYPE_RESERVED_MEMORY:

        ret = dmar_parse_one_rmrr(entry_header);

        break;

    default:

         printk(KERN_WARNING PREFIX

                 "Unknown DMAR structure type/n");

         ret = 0; /* for forward compatibility */

              break;

}

 

解析如下两个表项:

 

DRHD - DMA Engine Reporting Structure

RMRR - Reserved memory Region Reporting Structure

 

对于DRHD表项,通过register函数,将每个DMA的物理设备放到一个list中。对于每个RMRR,同样放到一个全局列表中。

2.2 iommu_init_mempool

创建几个常用结构的slab_cache

struct iova

struct iommu_domain

struct device_domain_info

2.3 dmar_init_reserved_ranges

初始化保留的区域。下面两种range是需要保留的:

1.  IOAPIC ranges shouldn't be accessed by DMA

2.  Reserve all PCI MMIO to avoid peer-to-peer access

2.4 init_no_remapping_devices

Graphics driver workarounds to provide unity map

Digg This

 

Most GFX drivers don't call standard PCI DMA APIs to allocate DMA buffer,

Such drivers will be broken with IOMMU enabled. To workaround this issue,

we added two options.

 

Once graphics devices are converted over to use the DMA-API's this entire

patch can be removed...

 

a. intel_iommu=igfx_off. With this option, DMAR who has just gfx devices

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值