acpi 表占用memory的释放

一般将apci表中的信息存到kernel的中后好释放acpi表占用的内存。
一般调用early_acpi_os_unmap_memory((char *)table_header, tbl_size);
输入参数是这个acpi的都指针和size
void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
{
    if (!acpi_gbl_permanent_mmap)
        __acpi_unmap_table(virt, size);
}
在kernel中如果acpi_gbl_permanent_mmap不等于0,则不释放acpi占用的memory
void __init __acpi_unmap_table(char *map, unsigned long size)
{
    if (!map || !size)
        return;
    early_iounmap(map, size);
}
继续调用early_iounmap

void __init early_iounmap(void __iomem *addr, unsigned long size)
{
    unsigned long virt_addr;
    unsigned long offset;
    unsigned int nrpages;
    enum fixed_addresses idx;
    int i, slot;
    slot = -1;
    for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
看这个addr释放在prev_map中,如果是的话,最终把prev_map[slot] = NULL;
        if (prev_map[i] == addr) {
            slot = i;
            break;
        }
    }
    if (WARN(slot < 0, "early_iounmap(%p, %08lx) not found slot\n",
         addr, size))
        return;
    if (WARN(prev_size[slot] != size,
         "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n",
         addr, size, slot, prev_size[slot]))
        return;
    WARN(early_ioremap_debug, "early_iounmap(%p, %08lx) [%d]\n",
         addr, size, slot);
    virt_addr = (unsigned long)addr;
    if (WARN_ON(virt_addr < fix_to_virt(FIX_BTMAP_BEGIN)))
        return;
    offset = offset_in_page(virt_addr);
    nrpages = PAGE_ALIGN(offset + size) >> PAGE_SHIFT;
    idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
    while (nrpages > 0) {
释放的时候又分别paging_init 前和后
        if (after_paging_init)
            __late_clear_fixmap(idx);
        else
            __early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR);
        --idx;
        --nrpages;
    }
    prev_map[slot] = NULL;
}
我们先看after_paging_init == 1的case
#define __late_clear_fixmap(idx) __set_fixmap(idx, 0, __pgprot(0))
static inline void __set_fixmap(enum fixed_addresses idx,
                phys_addr_t phys, pgprot_t flags)
{
    native_set_fixmap(idx, phys, flags);
}
void __native_set_fixmap(enum fixed_addresses idx, pte_t pte)
{
    unsigned long address = __fix_to_virt(idx);
    if (idx >= __end_of_fixed_addresses) {
        BUG();
        return;
    }
    set_pte_vaddr(address, pte);
    fixmaps_set++;
}
最终就是将idx表示的地址设置成__pgprot(0),也就是clean pte
而paging_init前
void __init __early_set_fixmap(enum fixed_addresses idx,
                   phys_addr_t phys, pgprot_t flags)
{
    unsigned long addr = __fix_to_virt(idx);
    pte_t *pte;
    if (idx >= __end_of_fixed_addresses) {
        BUG();
        return;
    }
    pte = early_ioremap_pte(addr);
    if (pgprot_val(flags))
        set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags));
    else
        pte_clear(&init_mm, addr, pte);
    __flush_tlb_one(addr);
}
就是直接clean pte.

你可能感兴趣的:(Linux,源码分析)