Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

跨架構 DMA 內存分配差異:x86 與 PowerPC 實現對比

編輯:Linux 教學

DMA(直接內存訪問)要求物理地址連續且通常不可緩存。Linux 提供 dma_alloc_coherent 分配此類內存,但不同架構實現差異巨大。本文對比 x86 與 PowerPC(以 Freescale MPC5121 為例)的實現差異,幫助驅動移植時避坑。

x86 架構實現

void *dma_alloc_coherent(struct device *dev, size_t size,
                         dma_addr_t *dma_handle, gfp_t gfp)
{
    void *ret = (void *)__get_free_pages(gfp, get_order(size));
    if (ret) {
        memset(ret, 0, size);
        *dma_handle = virt_to_bus(ret);  // 邏輯地址 → 總線地址
    }
    return ret;  // 返回內核線性地址
}

特點:

  • 內存區域分為 ZONE_DMA(16MB)、ZONE_NORMAL、ZONE_HIGHMEM
  • DMA 區與 Normal 區採用線性映射(邏輯地址 = 物理地址 + PAGE_OFFSET)
  • 返回值為內核虛擬地址,便於驅動 mmap 實現

PowerPC (MPC5121) 實現

void *__dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp)
{
    struct page *page = alloc_pages(gfp, order);
    // 清零並刷新 cache
    unsigned long kaddr = (unsigned long)page_address(page);
    memset(page_address(page), 0, size);
    flush_dcache_range(kaddr, kaddr + size);

    // 從 consistent 區分配虛擬地址空間
    struct vm_region *c = vm_region_alloc(&consistent_head, size, ...);
    unsigned long vaddr = c->vm_start;
    pte_t *pte = consistent_pte + CONSISTENT_OFFSET(vaddr);

    split_page(page, order);
    *handle = page_to_bus(page);  // 設置 DMA handle

    do {
        SetPageReserved(page);
        set_pte_at(&init_mm, vaddr, pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
        page++; pte++; vaddr += PAGE_SIZE;
    } while (size -= PAGE_SIZE);

    return (void *)c->vm_start;  // 返回內核虛擬地址
}

關鍵差異:

  1. 無邏輯地址概念:PowerPC 不使用線性映射,必須顯式建立頁表映射(set_pte_at)
  2. 雙重分配:先分配物理頁(alloc_pages),再分配虛擬區域(vm_region_alloc),最後建立映射
  3. Cache 一致性:顯式調用 flush_dcache_range 並設置 pgprot_noncached 頁保護屬性
  4. Consistent 內存池:從專用的 consistent_head 區域分配虛擬地址

移植建議

  • 不要假設 virt_to_phys/phys_to_virt 可用於 DMA 緩衝區
  • 始終使用 dma_alloc_coherent/dma_free_coherent API
  • 注意 dma_handle 為總線地址,而非 CPU 物理地址
  • 跨架構代碼避免直接操作頁表或假設地址映射關係

總結

x86 依賴線性映射簡化 DMA 分配,PowerPC 則通過顯式頁表構建一致性映射區。理解這一本質差異,對編寫可移植驅動至關重要。

Copyright © Windows教程網 All Rights Reserved