/*
 * Finds an active region in the address range from start_pfn to last_pfn and
 * returns its range in ei_startpfn and ei_endpfn for the e820 entry.
 */
int __init e820_find_active_region(const struct e820entry *ei,
                                  unsigned long start_pfn,
                                  unsigned long last_pfn,
                                  unsigned long *ei_startpfn,
                                  unsigned long *ei_endpfn)
{
        u64 align = PAGE_SIZE;

        *ei_startpfn = round_up(ei->addr, align) >> PAGE_SHIFT;
        *ei_endpfn = round_down(ei->addr + ei->size, align) >> PAGE_SHIFT;

        /* Skip map entries smaller than a page */
        if (*ei_startpfn >= *ei_endpfn)
                return 0;

        /* Skip if map is outside the node */
        if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
                                    *ei_startpfn >= last_pfn)
                return 0;

        /* Check for overlaps */
        if (*ei_startpfn < start_pfn)
                *ei_startpfn = start_pfn;
        if (*ei_endpfn > last_pfn)
                *ei_endpfn = last_pfn;

        return 1;
}

/* Walk the e820 map and register active regions within a node */
void __init e820_register_active_regions(int nid, unsigned long start_pfn,
                                         unsigned long last_pfn)
{
        unsigned long ei_startpfn;
        unsigned long ei_endpfn;
        int i;

        for (i = 0; i < e820.nr_map; i++)
                if (e820_find_active_region(&e820.map[i],
                                            start_pfn, last_pfn,
                                            &ei_startpfn, &ei_endpfn))
                        add_active_range(nid, ei_startpfn, ei_endpfn);
}


/*
 * Find the highest page frame number we have available
 */
static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
{
        int i;
        unsigned long last_pfn = 0;
        unsigned long max_arch_pfn = MAX_ARCH_PFN;

        for (i = 0; i < e820.nr_map; i++) {
                struct e820entry *ei = &e820.map[i];
                unsigned long start_pfn;
                unsigned long end_pfn;

                if (ei->type != type)
                        continue;

                start_pfn = ei->addr >> PAGE_SHIFT;
                end_pfn = (ei->addr + ei->size) >> PAGE_SHIFT;

                if (start_pfn >= limit_pfn)
                        continue;
                if (end_pfn > limit_pfn) {
                        last_pfn = limit_pfn;
                        break;
                }
                if (end_pfn > last_pfn)
                        last_pfn = end_pfn;
        }

        if (last_pfn > max_arch_pfn)
                last_pfn = max_arch_pfn;

        printk(KERN_INFO "last_pfn = %#lx max_arch_pfn = %#lx\n",
                         last_pfn, max_arch_pfn);
        return last_pfn;
}

Reply via email to