Commit e5185a76 authored by Ingo Molnar's avatar Ingo Molnar

Merge branch 'x86/boot' into x86/mm, to avoid conflict

There's a conflict between ongoing level-5 paging support and
the E820 rewrite. Since the E820 rewrite is essentially ready,
merge it into x86/mm to reduce tree conflicts.
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents b678c91a 47292771
......@@ -27,7 +27,7 @@ Offset Proto Name Meaning
1C0/020 ALL efi_info EFI 32 information (struct efi_info)
1E0/004 ALL alk_mem_k Alternative mem check, in KB
1E4/004 ALL scratch Scratch field for the kernel setup code
1E8/001 ALL e820_entries Number of entries in e820_map (below)
1E8/001 ALL e820_entries Number of entries in e820_table (below)
1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below)
1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer
(below)
......@@ -35,6 +35,6 @@ Offset Proto Name Meaning
1EC/001 ALL secure_boot Secure boot is enabled in the firmware
1EF/001 ALL sentinel Used to detect broken bootloaders
290/040 ALL edd_mbr_sig_buffer EDD MBR signatures
2D0/A00 ALL e820_map E820 memory map table
(array of struct e820entry)
2D0/A00 ALL e820_table E820 memory map table
(array of struct e820_entry)
D00/1EC ALL eddbuf EDD data (array of struct edd_info)
......@@ -9,7 +9,9 @@
#include <linux/efi.h>
#include <linux/pci.h>
#include <asm/efi.h>
#include <asm/e820/types.h>
#include <asm/setup.h>
#include <asm/desc.h>
......@@ -729,7 +731,7 @@ static void add_e820ext(struct boot_params *params,
unsigned long size;
e820ext->type = SETUP_E820_EXT;
e820ext->len = nr_entries * sizeof(struct e820entry);
e820ext->len = nr_entries * sizeof(struct boot_e820_entry);
e820ext->next = 0;
data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
......@@ -746,9 +748,9 @@ static void add_e820ext(struct boot_params *params,
static efi_status_t setup_e820(struct boot_params *params,
struct setup_data *e820ext, u32 e820ext_size)
{
struct e820entry *e820_map = &params->e820_map[0];
struct boot_e820_entry *entry = params->e820_table;
struct efi_info *efi = &params->efi_info;
struct e820entry *prev = NULL;
struct boot_e820_entry *prev = NULL;
u32 nr_entries;
u32 nr_desc;
int i;
......@@ -773,15 +775,15 @@ static efi_status_t setup_e820(struct boot_params *params,
case EFI_MEMORY_MAPPED_IO:
case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
case EFI_PAL_CODE:
e820_type = E820_RESERVED;
e820_type = E820_TYPE_RESERVED;
break;
case EFI_UNUSABLE_MEMORY:
e820_type = E820_UNUSABLE;
e820_type = E820_TYPE_UNUSABLE;
break;
case EFI_ACPI_RECLAIM_MEMORY:
e820_type = E820_ACPI;
e820_type = E820_TYPE_ACPI;
break;
case EFI_LOADER_CODE:
......@@ -789,15 +791,15 @@ static efi_status_t setup_e820(struct boot_params *params,
case EFI_BOOT_SERVICES_CODE:
case EFI_BOOT_SERVICES_DATA:
case EFI_CONVENTIONAL_MEMORY:
e820_type = E820_RAM;
e820_type = E820_TYPE_RAM;
break;
case EFI_ACPI_MEMORY_NVS:
e820_type = E820_NVS;
e820_type = E820_TYPE_NVS;
break;
case EFI_PERSISTENT_MEMORY:
e820_type = E820_PMEM;
e820_type = E820_TYPE_PMEM;
break;
default:
......@@ -811,26 +813,26 @@ static efi_status_t setup_e820(struct boot_params *params,
continue;
}
if (nr_entries == ARRAY_SIZE(params->e820_map)) {
u32 need = (nr_desc - i) * sizeof(struct e820entry) +
if (nr_entries == ARRAY_SIZE(params->e820_table)) {
u32 need = (nr_desc - i) * sizeof(struct e820_entry) +
sizeof(struct setup_data);
if (!e820ext || e820ext_size < need)
return EFI_BUFFER_TOO_SMALL;
/* boot_params map full, switch to e820 extended */
e820_map = (struct e820entry *)e820ext->data;
entry = (struct boot_e820_entry *)e820ext->data;
}
e820_map->addr = d->phys_addr;
e820_map->size = d->num_pages << PAGE_SHIFT;
e820_map->type = e820_type;
prev = e820_map++;
entry->addr = d->phys_addr;
entry->size = d->num_pages << PAGE_SHIFT;
entry->type = e820_type;
prev = entry++;
nr_entries++;
}
if (nr_entries > ARRAY_SIZE(params->e820_map)) {
u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_map);
if (nr_entries > ARRAY_SIZE(params->e820_table)) {
u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_table);
add_e820ext(params, e820ext, nr_e820ext);
nr_entries -= nr_e820ext;
......@@ -848,7 +850,7 @@ static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext,
unsigned long size;
size = sizeof(struct setup_data) +
sizeof(struct e820entry) * nr_desc;
sizeof(struct e820_entry) * nr_desc;
if (*e820ext) {
efi_call_early(free_pool, *e820ext);
......@@ -884,9 +886,9 @@ static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
if (first) {
nr_desc = *map->buff_size / *map->desc_size;
if (nr_desc > ARRAY_SIZE(p->boot_params->e820_map)) {
if (nr_desc > ARRAY_SIZE(p->boot_params->e820_table)) {
u32 nr_e820ext = nr_desc -
ARRAY_SIZE(p->boot_params->e820_map);
ARRAY_SIZE(p->boot_params->e820_table);
status = alloc_e820ext(nr_e820ext, &p->e820ext,
&p->e820ext_size);
......
......@@ -426,7 +426,7 @@ static unsigned long slots_fetch_random(void)
return 0;
}
static void process_e820_entry(struct e820entry *entry,
static void process_e820_entry(struct boot_e820_entry *entry,
unsigned long minimum,
unsigned long image_size)
{
......@@ -435,7 +435,7 @@ static void process_e820_entry(struct e820entry *entry,
unsigned long start_orig;
/* Skip non-RAM entries. */
if (entry->type != E820_RAM)
if (entry->type != E820_TYPE_RAM)
return;
/* On 32-bit, ignore entries entirely above our maximum. */
......@@ -518,7 +518,7 @@ static unsigned long find_random_phys_addr(unsigned long minimum,
/* Verify potential e820 positions, appending to slots list. */
for (i = 0; i < boot_params->e820_entries; i++) {
process_e820_entry(&boot_params->e820_map[i], minimum,
process_e820_entry(&boot_params->e820_table[i], minimum,
image_size);
if (slot_area_index == MAX_SLOT_AREA) {
debug_putstr("Aborted e820 scan (slot_areas full)!\n");
......
......@@ -18,7 +18,6 @@
#include <asm/segment.h>
#include <generated/utsrelease.h>
#include <asm/boot.h>
#include <asm/e820.h>
#include <asm/page_types.h>
#include <asm/setup.h>
#include <asm/bootparam.h>
......
......@@ -21,8 +21,8 @@ static int detect_memory_e820(void)
{
int count = 0;
struct biosregs ireg, oreg;
struct e820entry *desc = boot_params.e820_map;
static struct e820entry buf; /* static so it is zeroed */
struct boot_e820_entry *desc = boot_params.e820_table;
static struct boot_e820_entry buf; /* static so it is zeroed */
initregs(&ireg);
ireg.ax = 0xe820;
......@@ -66,7 +66,7 @@ static int detect_memory_e820(void)
*desc++ = buf;
count++;
} while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map));
} while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_table));
return boot_params.e820_entries = count;
}
......
......@@ -52,6 +52,8 @@ extern u8 acpi_sci_flags;
extern int acpi_sci_override_gsi;
void acpi_pic_sci_set_trigger(unsigned int, u16);
struct device;
extern int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
int trigger, int polarity);
extern void (*__acpi_unregister_gsi)(u32 gsi);
......
#ifndef _ASM_X86_E820_H
#define _ASM_X86_E820_H
/*
* E820_X_MAX is the maximum size of the extended E820 table. The extended
* table may contain up to 3 extra E820 entries per possible NUMA node, so we
* make room for 3 * MAX_NUMNODES possible entries, beyond the standard 128.
* Also note that E820_X_MAX *must* be defined before we include uapi/asm/e820.h.
*/
#include <linux/numa.h>
#define E820_X_MAX (E820MAX + 3 * MAX_NUMNODES)
#include <uapi/asm/e820.h>
#ifndef __ASSEMBLY__
/* see comment in arch/x86/kernel/e820.c */
extern struct e820map *e820;
extern struct e820map *e820_saved;
extern unsigned long pci_mem_start;
extern int e820_any_mapped(u64 start, u64 end, unsigned type);
extern int e820_all_mapped(u64 start, u64 end, unsigned type);
extern void e820_add_region(u64 start, u64 size, int type);
extern void e820_print_map(char *who);
extern int
sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, u32 *pnr_map);
extern u64 e820_update_range(u64 start, u64 size, unsigned old_type,
unsigned new_type);
extern u64 e820_remove_range(u64 start, u64 size, unsigned old_type,
int checktype);
extern void update_e820(void);
extern void e820_setup_gap(void);
struct setup_data;
extern void parse_e820_ext(u64 phys_addr, u32 data_len);
#if defined(CONFIG_X86_64) || \
(defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION))
extern void e820_mark_nosave_regions(unsigned long limit_pfn);
#else
static inline void e820_mark_nosave_regions(unsigned long limit_pfn)
{
}
#endif
extern unsigned long e820_end_of_ram_pfn(void);
extern unsigned long e820_end_of_low_ram_pfn(void);
extern u64 early_reserve_e820(u64 sizet, u64 align);
void memblock_x86_fill(void);
void memblock_find_dma_reserve(void);
extern void finish_e820_parsing(void);
extern void e820_reserve_resources(void);
extern void e820_reserve_resources_late(void);
extern void setup_memory_map(void);
extern char *default_machine_specific_memory_setup(void);
extern void e820_reallocate_tables(void);
/*
* Returns true iff the specified range [s,e) is completely contained inside
* the ISA region.
*/
static inline bool is_ISA_range(u64 s, u64 e)
{
return s >= ISA_START_ADDRESS && e <= ISA_END_ADDRESS;
}
#endif /* __ASSEMBLY__ */
#include <linux/ioport.h>
#define HIGH_MEMORY (1024*1024)
#endif /* _ASM_X86_E820_H */
#ifndef _ASM_E820_API_H
#define _ASM_E820_API_H
#include <asm/e820/types.h>
extern struct e820_table *e820_table;
extern struct e820_table *e820_table_firmware;
extern unsigned long pci_mem_start;
extern bool e820__mapped_any(u64 start, u64 end, enum e820_type type);
extern bool e820__mapped_all(u64 start, u64 end, enum e820_type type);
extern void e820__range_add (u64 start, u64 size, enum e820_type type);
extern u64 e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type);
extern u64 e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type);
extern void e820__print_table(char *who);
extern int e820__update_table(struct e820_table *table);
extern void e820__update_table_print(void);
extern unsigned long e820__end_of_ram_pfn(void);
extern unsigned long e820__end_of_low_ram_pfn(void);
extern u64 e820__memblock_alloc_reserved(u64 size, u64 align);
extern void e820__memblock_setup(void);
extern void e820__reserve_setup_data(void);
extern void e820__finish_early_params(void);
extern void e820__reserve_resources(void);
extern void e820__reserve_resources_late(void);
extern void e820__memory_setup(void);
extern void e820__memory_setup_extended(u64 phys_addr, u32 data_len);
extern char *e820__memory_setup_default(void);
extern void e820__setup_pci_gap(void);
extern void e820__reallocate_tables(void);
extern void e820__register_nosave_regions(unsigned long limit_pfn);
/*
* Returns true iff the specified range [start,end) is completely contained inside
* the ISA region.
*/
static inline bool is_ISA_range(u64 start, u64 end)
{
return start >= ISA_START_ADDRESS && end <= ISA_END_ADDRESS;
}
#endif /* _ASM_E820_API_H */
#ifndef _ASM_E820_TYPES_H
#define _ASM_E820_TYPES_H
#include <uapi/asm/bootparam.h>
/*
* These are the E820 types known to the kernel:
*/
enum e820_type {
E820_TYPE_RAM = 1,
E820_TYPE_RESERVED = 2,
E820_TYPE_ACPI = 3,
E820_TYPE_NVS = 4,
E820_TYPE_UNUSABLE = 5,
E820_TYPE_PMEM = 7,
/*
* This is a non-standardized way to represent ADR or
* NVDIMM regions that persist over a reboot.
*
* The kernel will ignore their special capabilities
* unless the CONFIG_X86_PMEM_LEGACY=y option is set.
*
* ( Note that older platforms also used 6 for the same
* type of memory, but newer versions switched to 12 as
* 6 was assigned differently. Some time they will learn... )
*/
E820_TYPE_PRAM = 12,
/*
* Reserved RAM used by the kernel itself if
* CONFIG_INTEL_TXT=y is enabled, memory of this type
* will be included in the S3 integrity calculation
* and so should not include any memory that the BIOS
* might alter over the S3 transition:
*/
E820_TYPE_RESERVED_KERN = 128,
};
/*
* A single E820 map entry, describing a memory range of [addr...addr+size-1],
* of 'type' memory type:
*
* (We pack it because there can be thousands of them on large systems.)
*/
struct e820_entry {
u64 addr;
u64 size;
enum e820_type type;
} __attribute__((packed));
/*
* The legacy E820 BIOS limits us to 128 (E820_MAX_ENTRIES_ZEROPAGE) nodes
* due to the constrained space in the zeropage.
*
* On large systems we can easily have thousands of nodes with RAM,
* which cannot be fit into so few entries - so we have a mechanism
* to extend the e820 table size at build-time, via the E820_MAX_ENTRIES
* define below.
*
* ( Those extra entries are enumerated via the EFI memory map, not
* via the legacy zeropage mechanism. )
*
* Size our internal memory map tables to have room for these additional
* entries, based on a heuristic calculation: up to three entries per
* NUMA node, plus E820_MAX_ENTRIES_ZEROPAGE for some extra space.
*
* This allows for bootstrap/firmware quirks such as possible duplicate
* E820 entries that might need room in the same arrays, prior to the
* call to e820__update_table() to remove duplicates. The allowance
* of three memory map entries per node is "enough" entries for
* the initial hardware platform motivating this mechanism to make
* use of additional EFI map entries. Future platforms may want
* to allow more than three entries per node or otherwise refine
* this size.
*/
#include <linux/numa.h>
#define E820_MAX_ENTRIES (E820_MAX_ENTRIES_ZEROPAGE + 3*MAX_NUMNODES)
/*
* The whole array of E820 entries:
*/
struct e820_table {
__u32 nr_entries;
struct e820_entry entries[E820_MAX_ENTRIES];
};
/*
* Various well-known legacy memory ranges in physical memory:
*/
#define ISA_START_ADDRESS 0x000a0000
#define ISA_END_ADDRESS 0x00100000
#define BIOS_BEGIN 0x000a0000
#define BIOS_END 0x00100000
#define HIGH_MEMORY 0x00100000
#define BIOS_ROM_BASE 0xffe00000
#define BIOS_ROM_END 0xffffffff
#endif /* _ASM_E820_TYPES_H */
#ifndef _ASM_X86_GART_H
#define _ASM_X86_GART_H
#include <asm/e820.h>
#include <asm/e820/api.h>
extern void set_up_gart_resume(u32, u32);
......@@ -97,7 +97,7 @@ static inline int aperture_valid(u64 aper_base, u32 aper_size, u32 min_size)
printk(KERN_INFO "Aperture beyond 4GB. Ignoring.\n");
return 0;
}
if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
if (e820__mapped_any(aper_base, aper_base + aper_size, E820_TYPE_RAM)) {
printk(KERN_INFO "Aperture pointing to e820 RAM. Ignoring.\n");
return 0;
}
......
......@@ -64,7 +64,7 @@ static inline void find_smp_config(void)
}
#ifdef CONFIG_X86_MPPARSE
extern void early_reserve_e820_mpc_new(void);
extern void e820__memblock_alloc_reserved_mpc_new(void);
extern int enable_update_mptable;
extern int default_mpc_apic_id(struct mpc_cpu *m);
extern void default_smp_read_mpc_oem(struct mpc_table *mpc);
......@@ -76,7 +76,7 @@ extern void default_mpc_oem_bus_info(struct mpc_bus *m, char *str);
extern void default_find_smp_config(void);
extern void default_get_smp_config(unsigned int early);
#else
static inline void early_reserve_e820_mpc_new(void) { }
static inline void e820__memblock_alloc_reserved_mpc_new(void) { }
#define enable_update_mptable 0
#define default_mpc_apic_id NULL
#define default_smp_read_mpc_oem NULL
......
......@@ -4,6 +4,8 @@
* (c) 1999 Martin Mares <mj@ucw.cz>
*/
#include <linux/ioport.h>
#undef DEBUG
#ifdef DEBUG
......
......@@ -2,8 +2,6 @@
#define _ASM_X86_PGTABLE_H
#include <asm/page.h>
#include <asm/e820.h>
#include <asm/pgtable_types.h>
/*
......@@ -916,6 +914,7 @@ static inline int pgd_none(pgd_t pgd)
extern int direct_gbpages;
void init_mem_mapping(void);
void early_alloc_pgt_buf(void);
extern void memblock_find_dma_reserve(void);
#ifdef CONFIG_X86_64
/* Realmode trampoline initialization. */
......
......@@ -6,6 +6,7 @@
#include <linux/spinlock.h>
#include <linux/pfn.h>
#include <linux/mm.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <asm/page.h>
......
......@@ -34,7 +34,6 @@
#include <linux/screen_info.h>
#include <linux/apm_bios.h>
#include <linux/edd.h>
#include <asm/e820.h>
#include <asm/ist.h>
#include <video/edid.h>
......@@ -111,6 +110,21 @@ struct efi_info {
__u32 efi_memmap_hi;
};
/*
* This is the maximum number of entries in struct boot_params::e820_table
* (the zeropage), which is part of the x86 boot protocol ABI:
*/
#define E820_MAX_ENTRIES_ZEROPAGE 128
/*
* The E820 memory region entry of the boot protocol ABI:
*/
struct boot_e820_entry {
__u64 addr;
__u64 size;
__u32 type;
} __attribute__((packed));
/* The so-called "zeropage" */
struct boot_params {
struct screen_info screen_info; /* 0x000 */
......@@ -153,7 +167,7 @@ struct boot_params {
struct setup_header hdr; /* setup header */ /* 0x1f1 */
__u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)];
__u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */
struct e820entry e820_map[E820MAX]; /* 0x2d0 */
struct boot_e820_entry e820_table[E820_MAX_ENTRIES_ZEROPAGE]; /* 0x2d0 */
__u8 _pad8[48]; /* 0xcd0 */
struct edd_info eddbuf[EDDMAXNR]; /* 0xd00 */
__u8 _pad9[276]; /* 0xeec */
......
......@@ -37,6 +37,7 @@
#include <linux/pci.h>
#include <linux/efi-bgrt.h>
#include <asm/e820/api.h>
#include <asm/irqdomain.h>
#include <asm/pci_x86.h>
#include <asm/pgtable.h>
......@@ -1729,6 +1730,6 @@ int __acpi_release_global_lock(unsigned int *lock)
void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size)
{
e820_add_region(addr, size, E820_ACPI);
update_e820();
e820__range_add(addr, size, E820_TYPE_ACPI);
e820__update_table_print();
}
......@@ -21,7 +21,7 @@
#include <linux/pci.h>
#include <linux/bitops.h>
#include <linux/suspend.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/io.h>
#include <asm/iommu.h>
#include <asm/gart.h>
......@@ -306,13 +306,13 @@ void __init early_gart_iommu_check(void)
fix = 1;
if (gart_fix_e820 && !fix && aper_enabled) {
if (e820_any_mapped(aper_base, aper_base + aper_size,
E820_RAM)) {
if (e820__mapped_any(aper_base, aper_base + aper_size,
E820_TYPE_RAM)) {
/* reserve it, so we can reuse it in second kernel */
pr_info("e820: reserve [mem %#010Lx-%#010Lx] for GART\n",
aper_base, aper_base + aper_size - 1);
e820_add_region(aper_base, aper_size, E820_RESERVED);
update_e820();
e820__range_add(aper_base, aper_size, E820_TYPE_RESERVED);
e820__update_table_print();
}
}
......
......@@ -2627,7 +2627,7 @@ static int __init lapic_insert_resource(void)
}
/*
* need call insert after e820_reserve_resources()
* need call insert after e820__reserve_resources()
* that is using request_resource
*/
late_initcall(lapic_insert_resource);
......
......@@ -26,7 +26,7 @@
#include <linux/interrupt.h>
#include <asm/acpi.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
static void noop_init_apic_ldr(void) { }
static void noop_send_IPI(int cpu, int vector) { }
......
......@@ -25,7 +25,7 @@
#include <linux/interrupt.h>
#include <asm/acpi.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#ifdef CONFIG_HOTPLUG_CPU
#define DEFAULT_SEND_IPI (1)
......
......@@ -34,6 +34,7 @@
#include <asm/uv/bios.h>
#include <asm/uv/uv.h>
#include <asm/apic.h>
#include <asm/e820/api.h>
#include <asm/ipi.h>
#include <asm/smp.h>
#include <asm/x86_init.h>
......
......@@ -3,7 +3,7 @@
#include <linux/sched/clock.h>
#include <asm/cpufeature.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/mtrr.h>
#include <asm/msr.h>
......
......@@ -27,7 +27,7 @@
#include <linux/range.h>
#include <asm/processor.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/mtrr.h>
#include <asm/msr.h>
......@@ -860,7 +860,7 @@ real_trim_memory(unsigned long start_pfn, unsigned long limit_pfn)
trim_size <<= PAGE_SHIFT;
trim_size -= trim_start;
return e820_update_range(trim_start, trim_size, E820_RAM, E820_RESERVED);
return e820__range_update(trim_start, trim_size, E820_TYPE_RAM, E820_TYPE_RESERVED);
}
/**
......@@ -978,7 +978,7 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
WARN_ON(1);
pr_info("update e820 for mtrr\n");
update_e820();
e820__update_table_print();
return 1;
}
......
......@@ -48,7 +48,7 @@
#include <linux/syscore_ops.h>
#include <asm/cpufeature.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/mtrr.h>
#include <asm/msr.h>
#include <asm/pat.h>
......
......@@ -29,6 +29,7 @@
#include <asm/nmi.h>
#include <asm/hw_irq.h>
#include <asm/apic.h>
#include <asm/e820/types.h>
#include <asm/io_apic.h>
#include <asm/hpet.h>
#include <linux/kdebug.h>
......@@ -503,16 +504,16 @@ static int prepare_elf_headers(struct kimage *image, void **addr,
return ret;
}
static int add_e820_entry(struct boot_params *params, struct e820entry *entry)
static int add_e820_entry(struct boot_params *params, struct e820_entry *entry)
{
unsigned int nr_e820_entries;
nr_e820_entries = params->e820_entries;
if (nr_e820_entries >= E820MAX)
if (nr_e820_entries >= E820_MAX_ENTRIES_ZEROPAGE)
return 1;
memcpy(&params->e820_map[nr_e820_entries], entry,
sizeof(struct e820entry));
memcpy(&params->e820_table[nr_e820_entries], entry,
sizeof(struct e820_entry));
params->e820_entries++;
return 0;
}
......@@ -521,7 +522,7 @@ static int memmap_entry_callback(u64 start, u64 end, void *arg)
{
struct crash_memmap_data *cmd = arg;
struct boot_params *params = cmd->params;
struct e820entry ei;
struct e820_entry ei;
ei.addr = start;
ei.size = end - start + 1;
......@@ -560,7 +561,7 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params)
{
int i, ret = 0;
unsigned long flags;
struct e820entry ei;
struct e820_entry ei;
struct crash_memmap_data cmd;
struct crash_mem *cmem;
......@@ -574,17 +575,17 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params)
/* Add first 640K segment */
ei.addr = image->arch.backup_src_start;
ei.size = image->arch.backup_src_sz;
ei.type = E820_RAM;
ei.type = E820_TYPE_RAM;
add_e820_entry(params, &ei);
/* Add ACPI tables */
cmd.type = E820_ACPI;
cmd.type = E820_TYPE_ACPI;
flags = IORESOURCE_MEM | IORESOURCE_BUSY;
walk_iomem_res_desc(IORES_DESC_ACPI_TABLES, flags, 0, -1, &cmd,
memmap_entry_callback);
/* Add ACPI Non-volatile Storage */
cmd.type = E820_NVS;
cmd.type = E820_TYPE_NVS;
walk_iomem_res_desc(IORES_DESC_ACPI_NV_STORAGE, flags, 0, -1, &cmd,
memmap_entry_callback);
......@@ -592,7 +593,7 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params)
if (crashk_low_res.end) {
ei.addr = crashk_low_res.start;
ei.size = crashk_low_res.end - crashk_low_res.start + 1;
ei.type = E820_RAM;
ei.type = E820_TYPE_RAM;
add_e820_entry(params, &ei);
}
......@@ -609,7 +610,7 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params)
if (ei.size < PAGE_SIZE)
continue;
ei.addr = cmem->ranges[i].start;
ei.type = E820_RAM;
ei.type = E820_TYPE_RAM;
add_e820_entry(params, &ei);
}
......
/*
* Handle the memory map.
* The functions here do the job until bootmem takes over.
* Low level x86 E820 memory map handling functions.
*
* Getting sanitize_e820_map() in sync with i386 version by applying change:
* - Provisions for empty E820 memory regions (reported by certain BIOSes).
* Alex Achenbach <xela@slit.de>, December 2002.
* Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
* The firmware and bootloader passes us the "E820 table", which is the primary
* physical memory layout description available about x86 systems.
*
* The kernel takes the E820 memory layout and optionally modifies it with
* quirks and other tweaks, and feeds that into the generic Linux memory
* allocation code routines via a platform independent interface (memblock, etc.).
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/crash_dump.h>
#include <linux/export.h>
#include <linux/bootmem.h>
#include <linux/pfn.h>
#include <linux/suspend.h>
#include <linux/acpi.h>
#include <linux/firmware-map.h>
#include <linux/memblock.h>
#include <linux/sort.h>
#include <asm/e820.h>
#include <asm/proto.h>
#include <asm/e820/api.h>
#include <asm/setup.h>
#include <asm/cpufeature.h>
/*
* The e820 map is the map that gets modified e.g. with command line parameters
* and that is also registered with modifications in the kernel resource tree
* with the iomem_resource as parent.
* We organize the E820 table into two main data structures:
*
* The e820_saved is directly saved after the BIOS-provided memory map is
* copied. It doesn't get modified afterwards. It's registered for the
* /sys/firmware/memmap interface.
* - 'e820_table_firmware': the original firmware version passed to us by the
* bootloader - not modified by the kernel. We use this to:
*
* That memory map is not modified and is used as base for kexec. The kexec'd
* kernel should get the same memory map as the firmware provides. Then the
* user can e.g. boot the original kernel with mem=1G while still booting the
* next kernel with full memory.
* - inform the user about the firmware's notion of memory layout
* via /sys/firmware/memmap
*
* - the hibernation code uses it to generate a kernel-independent MD5
* fingerprint of the physical memory layout of a system.
*
* - kexec, which is a bootloader in disguise, uses the original E820
* layout to pass to the kexec-ed kernel. This way the original kernel
* can have a restricted E820 map while the kexec()-ed kexec-kernel
* can have access to full memory - etc.
*
* - 'e820_table': this is the main E820 table that is massaged by the
* low level x86 platform code, or modified by boot parameters, before
* passed on to higher level MM layers.
*
* Once the E820 map has been converted to the standard Linux memory layout
* information its role stops - modifying it has no effect and does not get
* re-propagated. So itsmain role is a temporary bootstrap storage of firmware
* specific memory layout data during early bootup.
*/
static struct e820map initial_e820 __initdata;
static struct e820map initial_e820_saved __initdata;
struct e820map *e820 __refdata = &initial_e820;
struct e820map *e820_saved __refdata = &initial_e820_saved;
static struct e820_table e820_table_init __initdata;
static struct e820_table e820_table_firmware_init __initdata;
struct e820_table *e820_table __refdata = &e820_table_init;
struct e820_table *e820_table_firmware __refdata = &e820_table_firmware_init;
/* For PCI or other memory-mapped resources */
unsigned long pci_mem_start = 0xaeedbabe;
......@@ -55,51 +61,53 @@ EXPORT_SYMBOL(pci_mem_start);
* This function checks if any part of the range <start,end> is mapped
* with type.
*/
int
e820_any_mapped(u64 start, u64 end, unsigned type)
bool e820__mapped_any(u64 start, u64 end, enum e820_type type)
{
int i;
for (i = 0; i < e820->nr_map; i++) {
struct e820entry *ei = &e820->map[i];
for (i = 0; i < e820_table->nr_entries; i++) {
struct e820_entry *entry = &e820_table->entries[i];
if (type && ei->type != type)
if (type && entry->type != type)
continue;
if (ei->addr >= end || ei->addr + ei->size <= start)
if (entry->addr >= end || entry->addr + entry->size <= start)
continue;
return 1;
}
return 0;
}
EXPORT_SYMBOL_GPL(e820_any_mapped);
EXPORT_SYMBOL_GPL(e820__mapped_any);
/*
* This function checks if the entire range <start,end> is mapped with type.
* This function checks if the entire <start,end> range is mapped with 'type'.
*
* Note: this function only works correct if the e820 table is sorted and
* not-overlapping, which is the case
* Note: this function only works correctly once the E820 table is sorted and
* not-overlapping (at least for the range specified), which is the case normally.
*/
int __init e820_all_mapped(u64 start, u64 end, unsigned type)
bool __init e820__mapped_all(u64 start, u64 end, enum e820_type type)
{
int i;
for (i = 0; i < e820->nr_map; i++) {
struct e820entry *ei = &e820->map[i];
for (i = 0; i < e820_table->nr_entries; i++) {
struct e820_entry *entry = &e820_table->entries[i];
if (type && ei->type != type)
if (type && entry->type != type)
continue;
/* is the region (part) in overlap with the current region ?*/
if (ei->addr >= end || ei->addr + ei->size <= start)
/* Is the region (part) in overlap with the current region? */
if (entry->addr >= end || entry->addr + entry->size <= start)
continue;
/* if the region is at the beginning of <start,end> we move
* start to the end of the region since it's ok until there
/*
* If the region is at the beginning of <start,end> we move
* 'start' to the end of the region since it's ok until there
*/
if (ei->addr <= start)
start = ei->addr + ei->size;
if (entry->addr <= start)
start = entry->addr + entry->size;
/*
* if start is now at or beyond end, we're done, full
* coverage
* If 'start' is now at or beyond 'end', we're done, full
* coverage of the desired range exists:
*/
if (start >= end)
return 1;
......@@ -108,94 +116,77 @@ int __init e820_all_mapped(u64 start, u64 end, unsigned type)
}
/*
* Add a memory region to the kernel e820 map.
* Add a memory region to the kernel E820 map.
*/
static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
int type)
static void __init __e820__range_add(struct e820_table *table, u64 start, u64 size, enum e820_type type)
{
int x = e820x->nr_map;
int x = table->nr_entries;
if (x >= ARRAY_SIZE(e820x->map)) {
printk(KERN_ERR "e820: too many entries; ignoring [mem %#010llx-%#010llx]\n",
(unsigned long long) start,
(unsigned long long) (start + size - 1));
if (x >= ARRAY_SIZE(table->entries)) {
pr_err("e820: too many entries; ignoring [mem %#010llx-%#010llx]\n", start, start + size - 1);
return;
}
e820x->map[x].addr = start;
e820x->map[x].size = size;
e820x->map[x].type = type;
e820x->nr_map++;
table->entries[x].addr = start;
table->entries[x].size = size;
table->entries[x].type = type;
table->nr_entries++;
}
void __init e820_add_region(u64 start, u64 size, int type)
void __init e820__range_add(u64 start, u64 size, enum e820_type type)
{
__e820_add_region(e820, start, size, type);
__e820__range_add(e820_table, start, size, type);
}
static void __init e820_print_type(u32 type)
static void __init e820_print_type(enum e820_type type)
{
switch (type) {
case E820_RAM:
case E820_RESERVED_KERN:
printk(KERN_CONT "usable");
break;
case E820_RESERVED:
printk(KERN_CONT "reserved");
break;
case E820_ACPI:
printk(KERN_CONT "ACPI data");
break;
case E820_NVS:
printk(KERN_CONT "ACPI NVS");
break;
case E820_UNUSABLE:
printk(KERN_CONT "unusable");
break;
case E820_PMEM:
case E820_PRAM:
printk(KERN_CONT "persistent (type %u)", type);
break;
default:
printk(KERN_CONT "type %u", type);
break;
case E820_TYPE_RAM: /* Fall through: */
case E820_TYPE_RESERVED_KERN: pr_cont("usable"); break;
case E820_TYPE_RESERVED: pr_cont("reserved"); break;
case E820_TYPE_ACPI: pr_cont("ACPI data"); break;
case E820_TYPE_NVS: pr_cont("ACPI NVS"); break;
case E820_TYPE_UNUSABLE: pr_cont("unusable"); break;
case E820_TYPE_PMEM: /* Fall through: */
case E820_TYPE_PRAM: pr_cont("persistent (type %u)", type); break;
default: pr_cont("type %u", type); break;
}
}
void __init e820_print_map(char *who)
void __init e820__print_table(char *who)
{
int i;
for (i = 0; i < e820->nr_map; i++) {
printk(KERN_INFO "%s: [mem %#018Lx-%#018Lx] ", who,
(unsigned long long) e820->map[i].addr,
(unsigned long long)
(e820->map[i].addr + e820->map[i].size - 1));
e820_print_type(e820->map[i].type);
printk(KERN_CONT "\n");
for (i = 0; i < e820_table->nr_entries; i++) {
pr_info("%s: [mem %#018Lx-%#018Lx] ", who,
e820_table->entries[i].addr,
e820_table->entries[i].addr + e820_table->entries[i].size - 1);
e820_print_type(e820_table->entries[i].type);
pr_cont("\n");
}
}
/*
* Sanitize the BIOS e820 map.
* Sanitize an E820 map.
*
* Some e820 responses include overlapping entries. The following
* replaces the original e820 map with a new one, removing overlaps,
* Some E820 layouts include overlapping entries. The following
* replaces the original E820 map with a new one, removing overlaps,
* and resolving conflicting memory types in favor of highest
* numbered type.
*
* The input parameter biosmap points to an array of 'struct
* e820entry' which on entry has elements in the range [0, *pnr_map)
* valid, and which has space for up to max_nr_map entries.
* On return, the resulting sanitized e820 map entries will be in
* overwritten in the same location, starting at biosmap.
* The input parameter 'entries' points to an array of 'struct
* e820_entry' which on entry has elements in the range [0, *nr_entries)
* valid, and which has space for up to max_nr_entries entries.
* On return, the resulting sanitized E820 map entries will be in
* overwritten in the same location, starting at 'entries'.
*
* The integer pointed to by pnr_map must be valid on entry (the
* current number of valid entries located at biosmap). If the
* sanitizing succeeds the *pnr_map will be updated with the new
* number of valid entries (something no more than max_nr_map).
* The integer pointed to by nr_entries must be valid on entry (the
* current number of valid entries located at 'entries'). If the
* sanitizing succeeds the *nr_entries will be updated with the new
* number of valid entries (something no more than max_nr_entries).
*
* The return value from sanitize_e820_map() is zero if it
* The return value from e820__update_table() is zero if it
* successfully 'sanitized' the map entries passed in, and is -1
* if it did nothing, which can happen if either of (1) it was
* only passed one map entry, or (2) any of the input map entries
......@@ -238,10 +229,17 @@ void __init e820_print_map(char *who)
* ______________________4_
*/
struct change_member {
struct e820entry *pbios; /* pointer to original bios entry */
unsigned long long addr; /* address for this change point */
/* Pointer to the original entry: */
struct e820_entry *entry;
/* Address for this change point: */
unsigned long long addr;
};
static struct change_member change_point_list[2*E820_MAX_ENTRIES] __initdata;
static struct change_member *change_point[2*E820_MAX_ENTRIES] __initdata;
static struct e820_entry *overlap_list[E820_MAX_ENTRIES] __initdata;
static struct e820_entry new_entries[E820_MAX_ENTRIES] __initdata;
static int __init cpcompare(const void *a, const void *b)
{
struct change_member * const *app = a, * const *bpp = b;
......@@ -249,164 +247,141 @@ static int __init cpcompare(const void *a, const void *b)
/*
* Inputs are pointers to two elements of change_point[]. If their
* addresses are unequal, their difference dominates. If the addresses
* addresses are not equal, their difference dominates. If the addresses
* are equal, then consider one that represents the end of its region
* to be greater than one that does not.
*/
if (ap->addr != bp->addr)
return ap->addr > bp->addr ? 1 : -1;
return (ap->addr != ap->pbios->addr) - (bp->addr != bp->pbios->addr);
return (ap->addr != ap->entry->addr) - (bp->addr != bp->entry->addr);
}
int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map,
u32 *pnr_map)
int __init e820__update_table(struct e820_table *table)
{
static struct change_member change_point_list[2*E820_X_MAX] __initdata;
static struct change_member *change_point[2*E820_X_MAX] __initdata;
static struct e820entry *overlap_list[E820_X_MAX] __initdata;
static struct e820entry new_bios[E820_X_MAX] __initdata;
unsigned long current_type, last_type;
struct e820_entry *entries = table->entries;
u32 max_nr_entries = ARRAY_SIZE(table->entries);
enum e820_type current_type, last_type;
unsigned long long last_addr;
int chgidx;
int overlap_entries;
int new_bios_entry;
int old_nr, new_nr, chg_nr;
int i;
u32 new_nr_entries, overlap_entries;
u32 i, chg_idx, chg_nr;
/* if there's only one memory region, don't bother */
if (*pnr_map < 2)
/* If there's only one memory region, don't bother: */
if (table->nr_entries < 2)
return -1;
old_nr = *pnr_map;
BUG_ON(old_nr > max_nr_map);
table->nr_entries = table->nr_entries;
BUG_ON(table->nr_entries > max_nr_entries);
/* bail out if we find any unreasonable addresses in bios map */
for (i = 0; i < old_nr; i++)
if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
/* Bail out if we find any unreasonable addresses in the map: */
for (i = 0; i < table->nr_entries; i++) {
if (entries[i].addr + entries[i].size < entries[i].addr)
return -1;
}
/* create pointers for initial change-point information (for sorting) */
for (i = 0; i < 2 * old_nr; i++)
/* Create pointers for initial change-point information (for sorting): */
for (i = 0; i < 2 * table->nr_entries; i++)
change_point[i] = &change_point_list[i];
/* record all known change-points (starting and ending addresses),
omitting those that are for empty memory regions */
chgidx = 0;
for (i = 0; i < old_nr; i++) {
if (biosmap[i].size != 0) {
change_point[chgidx]->addr = biosmap[i].addr;
change_point[chgidx++]->pbios = &biosmap[i];
change_point[chgidx]->addr = biosmap[i].addr +
biosmap[i].size;
change_point[chgidx++]->pbios = &biosmap[i];
/*
* Record all known change-points (starting and ending addresses),
* omitting empty memory regions:
*/
chg_idx = 0;
for (i = 0; i < table->nr_entries; i++) {
if (entries[i].size != 0) {
change_point[chg_idx]->addr = entries[i].addr;
change_point[chg_idx++]->entry = &entries[i];
change_point[chg_idx]->addr = entries[i].addr + entries[i].size;
change_point[chg_idx++]->entry = &entries[i];
}
}
chg_nr = chgidx;
/* sort change-point list by memory addresses (low -> high) */
sort(change_point, chg_nr, sizeof *change_point, cpcompare, NULL);
/* create a new bios memory map, removing overlaps */
overlap_entries = 0; /* number of entries in the overlap table */
new_bios_entry = 0; /* index for creating new bios map entries */
last_type = 0; /* start with undefined memory type */
last_addr = 0; /* start with 0 as last starting address */
/* loop through change-points, determining affect on the new bios map */
for (chgidx = 0; chgidx < chg_nr; chgidx++) {
/* keep track of all overlapping bios entries */
if (change_point[chgidx]->addr ==
change_point[chgidx]->pbios->addr) {
/*
* add map entry to overlap list (> 1 entry
* implies an overlap)
*/
overlap_list[overlap_entries++] =
change_point[chgidx]->pbios;
chg_nr = chg_idx;
/* Sort change-point list by memory addresses (low -> high): */
sort(change_point, chg_nr, sizeof(*change_point), cpcompare, NULL);
/* Create a new memory map, removing overlaps: */
overlap_entries = 0; /* Number of entries in the overlap table */
new_nr_entries = 0; /* Index for creating new map entries */
last_type = 0; /* Start with undefined memory type */
last_addr = 0; /* Start with 0 as last starting address */
/* Loop through change-points, determining effect on the new map: */
for (chg_idx = 0; chg_idx < chg_nr; chg_idx++) {
/* Keep track of all overlapping entries */
if (change_point[chg_idx]->addr == change_point[chg_idx]->entry->addr) {
/* Add map entry to overlap list (> 1 entry implies an overlap) */
overlap_list[overlap_entries++] = change_point[chg_idx]->entry;
} else {
/*
* remove entry from list (order independent,
* so swap with last)
*/
/* Remove entry from list (order independent, so swap with last): */
for (i = 0; i < overlap_entries; i++) {
if (overlap_list[i] ==
change_point[chgidx]->pbios)
overlap_list[i] =
overlap_list[overlap_entries-1];
if (overlap_list[i] == change_point[chg_idx]->entry)
overlap_list[i] = overlap_list[overlap_entries-1];
}
overlap_entries--;
}
/*
* if there are overlapping entries, decide which
* If there are overlapping entries, decide which
* "type" to use (larger value takes precedence --
* 1=usable, 2,3,4,4+=unusable)
*/
current_type = 0;
for (i = 0; i < overlap_entries; i++)
for (i = 0; i < overlap_entries; i++) {
if (overlap_list[i]->type > current_type)
current_type = overlap_list[i]->type;
/*
* continue building up new bios map based on this
* information
*/
if (current_type != last_type || current_type == E820_PRAM) {
}
/* Continue building up new map based on this information: */
if (current_type != last_type || current_type == E820_TYPE_PRAM) {
if (last_type != 0) {
new_bios[new_bios_entry].size =
change_point[chgidx]->addr - last_addr;
/*
* move forward only if the new size
* was non-zero
*/
if (new_bios[new_bios_entry].size != 0)
/*
* no more space left for new
* bios entries ?
*/
if (++new_bios_entry >= max_nr_map)
new_entries[new_nr_entries].size = change_point[chg_idx]->addr - last_addr;
/* Move forward only if the new size was non-zero: */
if (new_entries[new_nr_entries].size != 0)
/* No more space left for new entries? */
if (++new_nr_entries >= max_nr_entries)
break;
}
if (current_type != 0) {
new_bios[new_bios_entry].addr =
change_point[chgidx]->addr;
new_bios[new_bios_entry].type = current_type;
last_addr = change_point[chgidx]->addr;
new_entries[new_nr_entries].addr = change_point[chg_idx]->addr;
new_entries[new_nr_entries].type = current_type;
last_addr = change_point[chg_idx]->addr;
}
last_type = current_type;
}
}
/* retain count for new bios entries */
new_nr = new_bios_entry;
/* copy new bios mapping into original location */
memcpy(biosmap, new_bios, new_nr * sizeof(struct e820entry));
*pnr_map = new_nr;
/* Copy the new entries into the original location: */
memcpy(entries, new_entries, new_nr_entries*sizeof(*entries));
table->nr_entries = new_nr_entries;
return 0;
}
static int __init __append_e820_map(struct e820entry *biosmap, int nr_map)
static int __init __append_e820_table(struct boot_e820_entry *entries, u32 nr_entries)
{
while (nr_map) {
u64 start = biosmap->addr;
u64 size = biosmap->size;
struct boot_e820_entry *entry = entries;
while (nr_entries) {
u64 start = entry->addr;
u64 size = entry->size;
u64 end = start + size - 1;
u32 type = biosmap->type;
u32 type = entry->type;
/* Overflow in 64 bits? Ignore the memory map. */
/* Ignore the entry on 64-bit overflow: */
if (start > end && likely(size))
return -1;
e820_add_region(start, size, type);
e820__range_add(start, size, type);
biosmap++;
nr_map--;
entry++;
nr_entries--;
}
return 0;
}
/*
* Copy the BIOS e820 map into a safe place.
* Copy the BIOS E820 map into a safe place.
*
* Sanity-check it while we're at it..
*
......@@ -414,18 +389,17 @@ static int __init __append_e820_map(struct e820entry *biosmap, int nr_map)
* will have given us a memory map that we can use to properly
* set up memory. If we aren't, we'll fake a memory map.
*/
static int __init append_e820_map(struct e820entry *biosmap, int nr_map)
static int __init append_e820_table(struct boot_e820_entry *entries, u32 nr_entries)
{
/* Only one memory region (or negative)? Ignore it */
if (nr_map < 2)
if (nr_entries < 2)
return -1;
return __append_e820_map(biosmap, nr_map);
return __append_e820_table(entries, nr_entries);
}
static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
u64 size, unsigned old_type,
unsigned new_type)
static u64 __init
__e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
{
u64 end;
unsigned int i;
......@@ -437,77 +411,73 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
size = ULLONG_MAX - start;
end = start + size;
printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ",
(unsigned long long) start, (unsigned long long) (end - 1));
printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ", start, end - 1);
e820_print_type(old_type);
printk(KERN_CONT " ==> ");
pr_cont(" ==> ");
e820_print_type(new_type);
printk(KERN_CONT "\n");
pr_cont("\n");
for (i = 0; i < e820x->nr_map; i++) {
struct e820entry *ei = &e820x->map[i];
for (i = 0; i < table->nr_entries; i++) {
struct e820_entry *entry = &table->entries[i];
u64 final_start, final_end;
u64 ei_end;
u64 entry_end;
if (ei->type != old_type)
if (entry->type != old_type)
continue;
ei_end = ei->addr + ei->size;
/* totally covered by new range? */
if (ei->addr >= start && ei_end <= end) {
ei->type = new_type;
real_updated_size += ei->size;
entry_end = entry->addr + entry->size;
/* Completely covered by new range? */
if (entry->addr >= start && entry_end <= end) {
entry->type = new_type;
real_updated_size += entry->size;
continue;
}
/* new range is totally covered? */
if (ei->addr < start && ei_end > end) {
__e820_add_region(e820x, start, size, new_type);
__e820_add_region(e820x, end, ei_end - end, ei->type);
ei->size = start - ei->addr;
/* New range is completely covered? */
if (entry->addr < start && entry_end > end) {
__e820__range_add(table, start, size, new_type);
__e820__range_add(table, end, entry_end - end, entry->type);
entry->size = start - entry->addr;
real_updated_size += size;
continue;
}
/* partially covered */
final_start = max(start, ei->addr);
final_end = min(end, ei_end);
/* Partially covered: */
final_start = max(start, entry->addr);
final_end = min(end, entry_end);
if (final_start >= final_end)
continue;
__e820_add_region(e820x, final_start, final_end - final_start,
new_type);
__e820__range_add(table, final_start, final_end - final_start, new_type);
real_updated_size += final_end - final_start;
/*
* left range could be head or tail, so need to update
* size at first.
* Left range could be head or tail, so need to update
* its size first:
*/
ei->size -= final_end - final_start;
if (ei->addr < final_start)
entry->size -= final_end - final_start;
if (entry->addr < final_start)
continue;
ei->addr = final_end;
entry->addr = final_end;
}
return real_updated_size;
}
u64 __init e820_update_range(u64 start, u64 size, unsigned old_type,
unsigned new_type)
u64 __init e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
{
return __e820_update_range(e820, start, size, old_type, new_type);
return __e820__range_update(e820_table, start, size, old_type, new_type);
}
static u64 __init e820_update_range_saved(u64 start, u64 size,
unsigned old_type, unsigned new_type)
static u64 __init e820__range_update_firmware(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
{
return __e820_update_range(e820_saved, start, size, old_type,
new_type);
return __e820__range_update(e820_table_firmware, start, size, old_type, new_type);
}
/* make e820 not cover the range */
u64 __init e820_remove_range(u64 start, u64 size, unsigned old_type,
int checktype)
/* Remove a range of memory from the E820 table: */
u64 __init e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type)
{
int i;
u64 end;
......@@ -517,85 +487,89 @@ u64 __init e820_remove_range(u64 start, u64 size, unsigned old_type,
size = ULLONG_MAX - start;
end = start + size;
printk(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ",
(unsigned long long) start, (unsigned long long) (end - 1));
if (checktype)
printk(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ", start, end - 1);
if (check_type)
e820_print_type(old_type);
printk(KERN_CONT "\n");
pr_cont("\n");
for (i = 0; i < e820->nr_map; i++) {
struct e820entry *ei = &e820->map[i];
for (i = 0; i < e820_table->nr_entries; i++) {
struct e820_entry *entry = &e820_table->entries[i];
u64 final_start, final_end;
u64 ei_end;
u64 entry_end;
if (checktype && ei->type != old_type)
if (check_type && entry->type != old_type)
continue;
ei_end = ei->addr + ei->size;
/* totally covered? */
if (ei->addr >= start && ei_end <= end) {
real_removed_size += ei->size;
memset(ei, 0, sizeof(struct e820entry));
entry_end = entry->addr + entry->size;
/* Completely covered? */
if (entry->addr >= start && entry_end <= end) {
real_removed_size += entry->size;
memset(entry, 0, sizeof(*entry));
continue;
}
/* new range is totally covered? */
if (ei->addr < start && ei_end > end) {
e820_add_region(end, ei_end - end, ei->type);
ei->size = start - ei->addr;
/* Is the new range completely covered? */
if (entry->addr < start && entry_end > end) {
e820__range_add(end, entry_end - end, entry->type);
entry->size = start - entry->addr;
real_removed_size += size;
continue;
}
/* partially covered */
final_start = max(start, ei->addr);
final_end = min(end, ei_end);
/* Partially covered: */
final_start = max(start, entry->addr);
final_end = min(end, entry_end);
if (final_start >= final_end)
continue;
real_removed_size += final_end - final_start;
/*
* left range could be head or tail, so need to update
* size at first.
* Left range could be head or tail, so need to update
* the size first:
*/
ei->size -= final_end - final_start;
if (ei->addr < final_start)
entry->size -= final_end - final_start;
if (entry->addr < final_start)
continue;
ei->addr = final_end;
entry->addr = final_end;
}
return real_removed_size;
}
void __init update_e820(void)
void __init e820__update_table_print(void)
{
if (sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map))
if (e820__update_table(e820_table))
return;
printk(KERN_INFO "e820: modified physical RAM map:\n");
e820_print_map("modified");
pr_info("e820: modified physical RAM map:\n");
e820__print_table("modified");
}
static void __init update_e820_saved(void)
static void __init e820__update_table_firmware(void)
{
sanitize_e820_map(e820_saved->map, ARRAY_SIZE(e820_saved->map),
&e820_saved->nr_map);
e820__update_table(e820_table_firmware);
}
#define MAX_GAP_END 0x100000000ull
/*
* Search for a gap in the e820 memory space from 0 to MAX_GAP_END.
* Search for a gap in the E820 memory space from 0 to MAX_GAP_END (4GB).
*/
static int __init e820_search_gap(unsigned long *gapstart,
unsigned long *gapsize)
static int __init e820_search_gap(unsigned long *gapstart, unsigned long *gapsize)
{
unsigned long long last = MAX_GAP_END;
int i = e820->nr_map;
int i = e820_table->nr_entries;
int found = 0;
while (--i >= 0) {
unsigned long long start = e820->map[i].addr;
unsigned long long end = start + e820->map[i].size;
unsigned long long start = e820_table->entries[i].addr;
unsigned long long end = start + e820_table->entries[i].size;
/*
* Since "last" is at most 4GB, we know we'll
* fit in 32 bits if this condition is true
* fit in 32 bits if this condition is true:
*/
if (last > end) {
unsigned long gap = last - end;
......@@ -613,12 +587,14 @@ static int __init e820_search_gap(unsigned long *gapstart,
}
/*
* Search for the biggest gap in the low 32 bits of the e820
* memory space. We pass this space to PCI to assign MMIO resources
* for hotplug or unconfigured devices in.
* Search for the biggest gap in the low 32 bits of the E820
* memory space. We pass this space to the PCI subsystem, so
* that it can assign MMIO resources for hotplug or
* unconfigured devices in.
*
* Hopefully the BIOS let enough space left.
*/
__init void e820_setup_gap(void)
__init void e820__setup_pci_gap(void)
{
unsigned long gapstart, gapsize;
int found;
......@@ -629,138 +605,143 @@ __init void e820_setup_gap(void)
if (!found) {
#ifdef CONFIG_X86_64
gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024;
printk(KERN_ERR
"e820: cannot find a gap in the 32bit address range\n"
"e820: PCI devices with unassigned 32bit BARs may break!\n");
pr_err(
"e820: Cannot find an available gap in the 32-bit address range\n"
"e820: PCI devices with unassigned 32-bit BARs may not work!\n");
#else
gapstart = 0x10000000;
#endif
}
/*
* e820_reserve_resources_late protect stolen RAM already
* e820__reserve_resources_late() protects stolen RAM already:
*/
pci_mem_start = gapstart;
printk(KERN_INFO
"e820: [mem %#010lx-%#010lx] available for PCI devices\n",
gapstart, gapstart + gapsize - 1);
pr_info("e820: [mem %#010lx-%#010lx] available for PCI devices\n", gapstart, gapstart + gapsize - 1);
}
/*
* Called late during init, in free_initmem().
*
* Initial e820 and e820_saved are largish __initdata arrays.
* Copy them to (usually much smaller) dynamically allocated area.
* This is done after all tweaks we ever do to them:
* all functions which modify them are __init functions,
* they won't exist after this point.
* Initial e820_table and e820_table_firmware are largish __initdata arrays.
*
* Copy them to a (usually much smaller) dynamically allocated area that is
* sized precisely after the number of e820 entries.
*
* This is done after we've performed all the fixes and tweaks to the tables.
* All functions which modify them are __init functions, which won't exist
* after free_initmem().
*/
__init void e820_reallocate_tables(void)
__init void e820__reallocate_tables(void)
{
struct e820map *n;
struct e820_table *n;
int size;
size = offsetof(struct e820map, map) + sizeof(struct e820entry) * e820->nr_map;
size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry)*e820_table->nr_entries;
n = kmalloc(size, GFP_KERNEL);
BUG_ON(!n);
memcpy(n, e820, size);
e820 = n;
memcpy(n, e820_table, size);
e820_table = n;
size = offsetof(struct e820map, map) + sizeof(struct e820entry) * e820_saved->nr_map;
size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry)*e820_table_firmware->nr_entries;
n = kmalloc(size, GFP_KERNEL);
BUG_ON(!n);
memcpy(n, e820_saved, size);
e820_saved = n;
memcpy(n, e820_table_firmware, size);
e820_table_firmware = n;
}
/**
* Because of the size limitation of struct boot_params, only first
* 128 E820 memory entries are passed to kernel via
* boot_params.e820_map, others are passed via SETUP_E820_EXT node of
* linked list of struct setup_data, which is parsed here.
/*
* Because of the small fixed size of struct boot_params, only the first
* 128 E820 memory entries are passed to the kernel via boot_params.e820_table,
* the remaining (if any) entries are passed via the SETUP_E820_EXT node of
* struct setup_data, which is parsed here.
*/
void __init parse_e820_ext(u64 phys_addr, u32 data_len)
void __init e820__memory_setup_extended(u64 phys_addr, u32 data_len)
{
int entries;
struct e820entry *extmap;
struct boot_e820_entry *extmap;
struct setup_data *sdata;
sdata = early_memremap(phys_addr, data_len);
entries = sdata->len / sizeof(struct e820entry);
extmap = (struct e820entry *)(sdata->data);
__append_e820_map(extmap, entries);
sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map);
entries = sdata->len / sizeof(*extmap);
extmap = (struct boot_e820_entry *)(sdata->data);
__append_e820_table(extmap, entries);
e820__update_table(e820_table);
early_memunmap(sdata, data_len);
printk(KERN_INFO "e820: extended physical RAM map:\n");
e820_print_map("extended");
pr_info("e820: extended physical RAM map:\n");
e820__print_table("extended");
}
#if defined(CONFIG_X86_64) || \
(defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION))
/**
/*
* Find the ranges of physical addresses that do not correspond to
* e820 RAM areas and mark the corresponding pages as nosave for
* hibernation (32 bit) or software suspend and suspend to RAM (64 bit).
* E820 RAM areas and register the corresponding pages as 'nosave' for
* hibernation (32-bit) or software suspend and suspend to RAM (64-bit).
*
* This function requires the e820 map to be sorted and without any
* This function requires the E820 map to be sorted and without any
* overlapping entries.
*/
void __init e820_mark_nosave_regions(unsigned long limit_pfn)
void __init e820__register_nosave_regions(unsigned long limit_pfn)
{
int i;
unsigned long pfn = 0;
for (i = 0; i < e820->nr_map; i++) {
struct e820entry *ei = &e820->map[i];
for (i = 0; i < e820_table->nr_entries; i++) {
struct e820_entry *entry = &e820_table->entries[i];
if (pfn < PFN_UP(ei->addr))
register_nosave_region(pfn, PFN_UP(ei->addr));
if (pfn < PFN_UP(entry->addr))
register_nosave_region(pfn, PFN_UP(entry->addr));
pfn = PFN_DOWN(ei->addr + ei->size);
pfn = PFN_DOWN(entry->addr + entry->size);
if (ei->type != E820_RAM && ei->type != E820_RESERVED_KERN)
register_nosave_region(PFN_UP(ei->addr), pfn);
if (entry->type != E820_TYPE_RAM && entry->type != E820_TYPE_RESERVED_KERN)
register_nosave_region(PFN_UP(entry->addr), pfn);
if (pfn >= limit_pfn)
break;
}
}
#endif
#ifdef CONFIG_ACPI
/**
* Mark ACPI NVS memory region, so that we can save/restore it during
* hibernation and the subsequent resume.
/*
* Register ACPI NVS memory regions, so that we can save/restore them during
* hibernation and the subsequent resume:
*/
static int __init e820_mark_nvs_memory(void)
static int __init e820__register_nvs_regions(void)
{
int i;
for (i = 0; i < e820->nr_map; i++) {
struct e820entry *ei = &e820->map[i];
for (i = 0; i < e820_table->nr_entries; i++) {
struct e820_entry *entry = &e820_table->entries[i];
if (ei->type == E820_NVS)
acpi_nvs_register(ei->addr, ei->size);
if (entry->type == E820_TYPE_NVS)
acpi_nvs_register(entry->addr, entry->size);
}
return 0;
}
core_initcall(e820_mark_nvs_memory);
core_initcall(e820__register_nvs_regions);
#endif
/*
* pre allocated 4k and reserved it in memblock and e820_saved
* Allocate the requested number of bytes with the requsted alignment
* and return (the physical address) to the caller. Also register this
* range in the 'firmware' E820 table as a reserved range.
*
* This allows kexec to fake a new mptable, as if it came from the real
* system.
*/
u64 __init early_reserve_e820(u64 size, u64 align)
u64 __init e820__memblock_alloc_reserved(u64 size, u64 align)
{
u64 addr;
addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
if (addr) {
e820_update_range_saved(addr, size, E820_RAM, E820_RESERVED);
printk(KERN_INFO "e820: update e820_saved for early_reserve_e820\n");
update_e820_saved();
e820__range_update_firmware(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED);
pr_info("e820: update e820_table_firmware for e820__memblock_alloc_reserved()\n");
e820__update_table_firmware();
}
return addr;
......@@ -779,22 +760,22 @@ u64 __init early_reserve_e820(u64 size, u64 align)
/*
* Find the highest page frame number we have available
*/
static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
static unsigned long __init e820_end_pfn(unsigned long limit_pfn, enum e820_type 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];
for (i = 0; i < e820_table->nr_entries; i++) {
struct e820_entry *entry = &e820_table->entries[i];
unsigned long start_pfn;
unsigned long end_pfn;
if (ei->type != type)
if (entry->type != type)
continue;
start_pfn = ei->addr >> PAGE_SHIFT;
end_pfn = (ei->addr + ei->size) >> PAGE_SHIFT;
start_pfn = entry->addr >> PAGE_SHIFT;
end_pfn = (entry->addr + entry->size) >> PAGE_SHIFT;
if (start_pfn >= limit_pfn)
continue;
......@@ -809,18 +790,19 @@ static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
if (last_pfn > max_arch_pfn)
last_pfn = max_arch_pfn;
printk(KERN_INFO "e820: last_pfn = %#lx max_arch_pfn = %#lx\n",
pr_info("e820: last_pfn = %#lx max_arch_pfn = %#lx\n",
last_pfn, max_arch_pfn);
return last_pfn;
}
unsigned long __init e820_end_of_ram_pfn(void)
unsigned long __init e820__end_of_ram_pfn(void)
{
return e820_end_pfn(MAX_ARCH_PFN, E820_RAM);
return e820_end_pfn(MAX_ARCH_PFN, E820_TYPE_RAM);
}
unsigned long __init e820_end_of_low_ram_pfn(void)
unsigned long __init e820__end_of_low_ram_pfn(void)
{
return e820_end_pfn(1UL << (32 - PAGE_SHIFT), E820_RAM);
return e820_end_pfn(1UL << (32 - PAGE_SHIFT), E820_TYPE_RAM);
}
static void __init early_panic(char *msg)
......@@ -831,7 +813,7 @@ static void __init early_panic(char *msg)
static int userdef __initdata;
/* "mem=nopentium" disables the 4MB page tables. */
/* The "mem=nopentium" boot option disables 4MB page tables on 32-bit kernels: */
static int __init parse_memopt(char *p)
{
u64 mem_size;
......@@ -844,17 +826,19 @@ static int __init parse_memopt(char *p)
setup_clear_cpu_cap(X86_FEATURE_PSE);
return 0;
#else
printk(KERN_WARNING "mem=nopentium ignored! (only supported on x86_32)\n");
pr_warn("mem=nopentium ignored! (only supported on x86_32)\n");
return -EINVAL;
#endif
}
userdef = 1;
mem_size = memparse(p, &p);
/* don't remove all of memory when handling "mem={invalid}" param */
/* Don't remove all memory when getting "mem={invalid}" parameter: */
if (mem_size == 0)
return -EINVAL;
e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
e820__range_remove(mem_size, ULLONG_MAX - mem_size, E820_TYPE_RAM, 1);
return 0;
}
......@@ -872,12 +856,12 @@ static int __init parse_memmap_one(char *p)
#ifdef CONFIG_CRASH_DUMP
/*
* If we are doing a crash dump, we still need to know
* the real mem size before original memory map is
* the real memory size before the original memory map is
* reset.
*/
saved_max_pfn = e820_end_of_ram_pfn();
saved_max_pfn = e820__end_of_ram_pfn();
#endif
e820->nr_map = 0;
e820_table->nr_entries = 0;
userdef = 1;
return 0;
}
......@@ -890,21 +874,23 @@ static int __init parse_memmap_one(char *p)
userdef = 1;
if (*p == '@') {
start_at = memparse(p+1, &p);
e820_add_region(start_at, mem_size, E820_RAM);
e820__range_add(start_at, mem_size, E820_TYPE_RAM);
} else if (*p == '#') {
start_at = memparse(p+1, &p);
e820_add_region(start_at, mem_size, E820_ACPI);
e820__range_add(start_at, mem_size, E820_TYPE_ACPI);
} else if (*p == '$') {
start_at = memparse(p+1, &p);
e820_add_region(start_at, mem_size, E820_RESERVED);
e820__range_add(start_at, mem_size, E820_TYPE_RESERVED);
} else if (*p == '!') {
start_at = memparse(p+1, &p);
e820_add_region(start_at, mem_size, E820_PRAM);
} else
e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
e820__range_add(start_at, mem_size, E820_TYPE_PRAM);
} else {
e820__range_remove(mem_size, ULLONG_MAX - mem_size, E820_TYPE_RAM, 1);
}
return *p == '\0' ? 0 : -EINVAL;
}
static int __init parse_memmap_opt(char *str)
{
while (str) {
......@@ -921,68 +907,97 @@ static int __init parse_memmap_opt(char *str)
}
early_param("memmap", parse_memmap_opt);
void __init finish_e820_parsing(void)
/*
* Reserve all entries from the bootloader's extensible data nodes list,
* because if present we are going to use it later on to fetch e820
* entries from it:
*/
void __init e820__reserve_setup_data(void)
{
struct setup_data *data;
u64 pa_data;
pa_data = boot_params.hdr.setup_data;
if (!pa_data)
return;
while (pa_data) {
data = early_memremap(pa_data, sizeof(*data));
e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
pa_data = data->next;
early_memunmap(data, sizeof(*data));
}
e820__update_table(e820_table);
memcpy(e820_table_firmware, e820_table, sizeof(*e820_table_firmware));
pr_info("extended physical RAM map:\n");
e820__print_table("reserve setup_data");
}
/*
* Called after parse_early_param(), after early parameters (such as mem=)
* have been processed, in which case we already have an E820 table filled in
* via the parameter callback function(s), but it's not sorted and printed yet:
*/
void __init e820__finish_early_params(void)
{
if (userdef) {
if (sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map),
&e820->nr_map) < 0)
if (e820__update_table(e820_table) < 0)
early_panic("Invalid user supplied memory map");
printk(KERN_INFO "e820: user-defined physical RAM map:\n");
e820_print_map("user");
pr_info("e820: user-defined physical RAM map:\n");
e820__print_table("user");
}
}
static const char *__init e820_type_to_string(int e820_type)
static const char *__init e820_type_to_string(struct e820_entry *entry)
{
switch (e820_type) {
case E820_RESERVED_KERN:
case E820_RAM: return "System RAM";
case E820_ACPI: return "ACPI Tables";
case E820_NVS: return "ACPI Non-volatile Storage";
case E820_UNUSABLE: return "Unusable memory";
case E820_PRAM: return "Persistent Memory (legacy)";
case E820_PMEM: return "Persistent Memory";
default: return "reserved";
switch (entry->type) {
case E820_TYPE_RESERVED_KERN: /* Fall-through: */
case E820_TYPE_RAM: return "System RAM";
case E820_TYPE_ACPI: return "ACPI Tables";
case E820_TYPE_NVS: return "ACPI Non-volatile Storage";
case E820_TYPE_UNUSABLE: return "Unusable memory";
case E820_TYPE_PRAM: return "Persistent Memory (legacy)";
case E820_TYPE_PMEM: return "Persistent Memory";
case E820_TYPE_RESERVED: return "Reserved";
default: return "Unknown E820 type";
}
}
static unsigned long __init e820_type_to_iomem_type(int e820_type)
static unsigned long __init e820_type_to_iomem_type(struct e820_entry *entry)
{
switch (e820_type) {
case E820_RESERVED_KERN:
case E820_RAM:
return IORESOURCE_SYSTEM_RAM;
case E820_ACPI:
case E820_NVS:
case E820_UNUSABLE:
case E820_PRAM:
case E820_PMEM:
default:
return IORESOURCE_MEM;
switch (entry->type) {
case E820_TYPE_RESERVED_KERN: /* Fall-through: */
case E820_TYPE_RAM: return IORESOURCE_SYSTEM_RAM;
case E820_TYPE_ACPI: /* Fall-through: */
case E820_TYPE_NVS: /* Fall-through: */
case E820_TYPE_UNUSABLE: /* Fall-through: */
case E820_TYPE_PRAM: /* Fall-through: */
case E820_TYPE_PMEM: /* Fall-through: */
case E820_TYPE_RESERVED: /* Fall-through: */
default: return IORESOURCE_MEM;
}
}
static unsigned long __init e820_type_to_iores_desc(int e820_type)
static unsigned long __init e820_type_to_iores_desc(struct e820_entry *entry)
{
switch (e820_type) {
case E820_ACPI:
return IORES_DESC_ACPI_TABLES;
case E820_NVS:
return IORES_DESC_ACPI_NV_STORAGE;
case E820_PMEM:
return IORES_DESC_PERSISTENT_MEMORY;
case E820_PRAM:
return IORES_DESC_PERSISTENT_MEMORY_LEGACY;
case E820_RESERVED_KERN:
case E820_RAM:
case E820_UNUSABLE:
default:
return IORES_DESC_NONE;
switch (entry->type) {
case E820_TYPE_ACPI: return IORES_DESC_ACPI_TABLES;
case E820_TYPE_NVS: return IORES_DESC_ACPI_NV_STORAGE;
case E820_TYPE_PMEM: return IORES_DESC_PERSISTENT_MEMORY;
case E820_TYPE_PRAM: return IORES_DESC_PERSISTENT_MEMORY_LEGACY;
case E820_TYPE_RESERVED_KERN: /* Fall-through: */
case E820_TYPE_RAM: /* Fall-through: */
case E820_TYPE_UNUSABLE: /* Fall-through: */
case E820_TYPE_RESERVED: /* Fall-through: */
default: return IORES_DESC_NONE;
}
}
static bool __init do_mark_busy(u32 type, struct resource *res)
static bool __init do_mark_busy(enum e820_type type, struct resource *res)
{
/* this is the legacy bios/dos rom-shadow + mmio region */
if (res->start < (1ULL<<20))
......@@ -993,61 +1008,71 @@ static bool __init do_mark_busy(u32 type, struct resource *res)
* for exclusive use of a driver
*/
switch (type) {
case E820_RESERVED:
case E820_PRAM:
case E820_PMEM:
case E820_TYPE_RESERVED:
case E820_TYPE_PRAM:
case E820_TYPE_PMEM:
return false;
case E820_TYPE_RESERVED_KERN:
case E820_TYPE_RAM:
case E820_TYPE_ACPI:
case E820_TYPE_NVS:
case E820_TYPE_UNUSABLE:
default:
return true;
}
}
/*
* Mark e820 reserved areas as busy for the resource manager.
* Mark E820 reserved areas as busy for the resource manager:
*/
static struct resource __initdata *e820_res;
void __init e820_reserve_resources(void)
void __init e820__reserve_resources(void)
{
int i;
struct resource *res;
u64 end;
res = alloc_bootmem(sizeof(struct resource) * e820->nr_map);
res = alloc_bootmem(sizeof(*res) * e820_table->nr_entries);
e820_res = res;
for (i = 0; i < e820->nr_map; i++) {
end = e820->map[i].addr + e820->map[i].size - 1;
for (i = 0; i < e820_table->nr_entries; i++) {
struct e820_entry *entry = e820_table->entries + i;
end = entry->addr + entry->size - 1;
if (end != (resource_size_t)end) {
res++;
continue;
}
res->name = e820_type_to_string(e820->map[i].type);
res->start = e820->map[i].addr;
res->end = end;
res->flags = e820_type_to_iomem_type(e820->map[i].type);
res->desc = e820_type_to_iores_desc(e820->map[i].type);
res->start = entry->addr;
res->end = end;
res->name = e820_type_to_string(entry);
res->flags = e820_type_to_iomem_type(entry);
res->desc = e820_type_to_iores_desc(entry);
/*
* don't register the region that could be conflicted with
* pci device BAR resource and insert them later in
* pcibios_resource_survey()
* Don't register the region that could be conflicted with
* PCI device BAR resources and insert them later in
* pcibios_resource_survey():
*/
if (do_mark_busy(e820->map[i].type, res)) {
if (do_mark_busy(entry->type, res)) {
res->flags |= IORESOURCE_BUSY;
insert_resource(&iomem_resource, res);
}
res++;
}
for (i = 0; i < e820_saved->nr_map; i++) {
struct e820entry *entry = &e820_saved->map[i];
firmware_map_add_early(entry->addr,
entry->addr + entry->size,
e820_type_to_string(entry->type));
for (i = 0; i < e820_table_firmware->nr_entries; i++) {
struct e820_entry *entry = e820_table_firmware->entries + i;
firmware_map_add_early(entry->addr, entry->addr + entry->size, e820_type_to_string(entry));
}
}
/* How much should we pad RAM ending depending on where it is? */
/*
* How much should we pad the end of RAM, depending on where it is?
*/
static unsigned long __init ram_alignment(resource_size_t pos)
{
unsigned long mb = pos >> 20;
......@@ -1066,64 +1091,59 @@ static unsigned long __init ram_alignment(resource_size_t pos)
#define MAX_RESOURCE_SIZE ((resource_size_t)-1)
void __init e820_reserve_resources_late(void)
void __init e820__reserve_resources_late(void)
{
int i;
struct resource *res;
res = e820_res;
for (i = 0; i < e820->nr_map; i++) {
for (i = 0; i < e820_table->nr_entries; i++) {
if (!res->parent && res->end)
insert_resource_expand_to_fit(&iomem_resource, res);
res++;
}
/*
* Try to bump up RAM regions to reasonable boundaries to
* Try to bump up RAM regions to reasonable boundaries, to
* avoid stolen RAM:
*/
for (i = 0; i < e820->nr_map; i++) {
struct e820entry *entry = &e820->map[i];
for (i = 0; i < e820_table->nr_entries; i++) {
struct e820_entry *entry = &e820_table->entries[i];
u64 start, end;
if (entry->type != E820_RAM)
if (entry->type != E820_TYPE_RAM)
continue;
start = entry->addr + entry->size;
end = round_up(start, ram_alignment(start)) - 1;
if (end > MAX_RESOURCE_SIZE)
end = MAX_RESOURCE_SIZE;
if (start >= end)
continue;
printk(KERN_DEBUG
"e820: reserve RAM buffer [mem %#010llx-%#010llx]\n",
start, end);
reserve_region_with_split(&iomem_resource, start, end,
"RAM buffer");
printk(KERN_DEBUG "e820: reserve RAM buffer [mem %#010llx-%#010llx]\n", start, end);
reserve_region_with_split(&iomem_resource, start, end, "RAM buffer");
}
}
char *__init default_machine_specific_memory_setup(void)
/*
* Pass the firmware (bootloader) E820 map to the kernel and process it:
*/
char *__init e820__memory_setup_default(void)
{
char *who = "BIOS-e820";
u32 new_nr;
/*
* Try to copy the BIOS-supplied E820-map.
*
* Otherwise fake a memory map; one section from 0k->640k,
* the next section from 1mb->appropriate_mem_k
*/
new_nr = boot_params.e820_entries;
sanitize_e820_map(boot_params.e820_map,
ARRAY_SIZE(boot_params.e820_map),
&new_nr);
boot_params.e820_entries = new_nr;
if (append_e820_map(boot_params.e820_map, boot_params.e820_entries)
< 0) {
if (append_e820_table(boot_params.e820_table, boot_params.e820_entries) < 0) {
u64 mem_size;
/* compare results from other methods and take the greater */
if (boot_params.alt_mem_k
< boot_params.screen_info.ext_mem_k) {
/* Compare results from other methods and take the one that gives more RAM: */
if (boot_params.alt_mem_k < boot_params.screen_info.ext_mem_k) {
mem_size = boot_params.screen_info.ext_mem_k;
who = "BIOS-88";
} else {
......@@ -1131,84 +1151,68 @@ char *__init default_machine_specific_memory_setup(void)
who = "BIOS-e801";
}
e820->nr_map = 0;
e820_add_region(0, LOWMEMSIZE(), E820_RAM);
e820_add_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
e820_table->nr_entries = 0;
e820__range_add(0, LOWMEMSIZE(), E820_TYPE_RAM);
e820__range_add(HIGH_MEMORY, mem_size << 10, E820_TYPE_RAM);
}
/* In case someone cares... */
/* We just appended a lot of ranges, sanitize the table: */
e820__update_table(e820_table);
return who;
}
void __init setup_memory_map(void)
/*
* Calls e820__memory_setup_default() in essence to pick up the firmware/bootloader
* E820 map - with an optional platform quirk available for virtual platforms
* to override this method of boot environment processing:
*/
void __init e820__memory_setup(void)
{
char *who;
/* This is a firmware interface ABI - make sure we don't break it: */
BUILD_BUG_ON(sizeof(struct boot_e820_entry) != 20);
who = x86_init.resources.memory_setup();
memcpy(e820_saved, e820, sizeof(struct e820map));
printk(KERN_INFO "e820: BIOS-provided physical RAM map:\n");
e820_print_map(who);
memcpy(e820_table_firmware, e820_table, sizeof(*e820_table_firmware));
pr_info("e820: BIOS-provided physical RAM map:\n");
e820__print_table(who);
}
void __init memblock_x86_fill(void)
void __init e820__memblock_setup(void)
{
int i;
u64 end;
/*
* EFI may have more than 128 entries
* We are safe to enable resizing, beause memblock_x86_fill()
* is rather later for x86
* The bootstrap memblock region count maximum is 128 entries
* (INIT_MEMBLOCK_REGIONS), but EFI might pass us more E820 entries
* than that - so allow memblock resizing.
*
* This is safe, because this call happens pretty late during x86 setup,
* so we know about reserved memory regions already. (This is important
* so that memblock resizing does no stomp over reserved areas.)
*/
memblock_allow_resize();
for (i = 0; i < e820->nr_map; i++) {
struct e820entry *ei = &e820->map[i];
for (i = 0; i < e820_table->nr_entries; i++) {
struct e820_entry *entry = &e820_table->entries[i];
end = ei->addr + ei->size;
end = entry->addr + entry->size;
if (end != (resource_size_t)end)
continue;
if (ei->type != E820_RAM && ei->type != E820_RESERVED_KERN)
if (entry->type != E820_TYPE_RAM && entry->type != E820_TYPE_RESERVED_KERN)
continue;
memblock_add(ei->addr, ei->size);
memblock_add(entry->addr, entry->size);
}
/* throw away partial pages */
/* Throw away partial pages: */
memblock_trim_memory(PAGE_SIZE);
memblock_dump_all();
}
void __init memblock_find_dma_reserve(void)
{
#ifdef CONFIG_X86_64
u64 nr_pages = 0, nr_free_pages = 0;
unsigned long start_pfn, end_pfn;
phys_addr_t start, end;
int i;
u64 u;
/*
* need to find out used area below MAX_DMA_PFN
* need to use memblock to get free size in [0, MAX_DMA_PFN]
* at first, and assume boot_mem will not take below MAX_DMA_PFN
*/
for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, NULL) {
start_pfn = min(start_pfn, MAX_DMA_PFN);
end_pfn = min(end_pfn, MAX_DMA_PFN);
nr_pages += end_pfn - start_pfn;
}
for_each_free_mem_range(u, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end,
NULL) {
start_pfn = min_t(unsigned long, PFN_UP(start), MAX_DMA_PFN);
end_pfn = min_t(unsigned long, PFN_DOWN(end), MAX_DMA_PFN);
if (start_pfn < end_pfn)
nr_free_pages += end_pfn - start_pfn;
}
set_dma_reserve(nr_pages - nr_free_pages);
#endif
}
......@@ -546,8 +546,8 @@ intel_graphics_stolen(int num, int slot, int func,
&base, &end);
/* Mark this space as reserved */
e820_add_region(base, size, E820_RESERVED);
sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map);
e820__range_add(base, size, E820_TYPE_RESERVED);
e820__update_table(e820_table);
}
static void __init intel_graphics_quirks(int num, int slot, int func)
......
......@@ -12,7 +12,7 @@
#include <asm/setup.h>
#include <asm/sections.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/page.h>
#include <asm/apic.h>
#include <asm/io_apic.h>
......
......@@ -24,7 +24,7 @@
#include <asm/tlbflush.h>
#include <asm/sections.h>
#include <asm/kdebug.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/bios_ebda.h>
#include <asm/bootparam_utils.h>
#include <asm/microcode.h>
......
......@@ -269,10 +269,8 @@ ENTRY(secondary_startup_64)
/* rsi is pointer to real mode structure with interesting info.
pass it to C */
movq %rsi, %rdi
jmp start_cpu
ENDPROC(secondary_startup_64)
ENTRY(start_cpu)
.Ljump_to_C_code:
/*
* Jump to run C code and to be on a real kernel address.
* Since we are running on identity-mapped space we have to jump
......@@ -305,7 +303,7 @@ ENTRY(start_cpu)
pushq %rax # target address in negative space
lretq
.Lafter_lret:
ENDPROC(start_cpu)
ENDPROC(secondary_startup_64)
#include "verify_cpu.S"
......@@ -313,11 +311,11 @@ ENDPROC(start_cpu)
/*
* Boot CPU0 entry point. It's called from play_dead(). Everything has been set
* up already except stack. We just set up stack here. Then call
* start_secondary() via start_cpu().
* start_secondary() via .Ljump_to_C_code.
*/
ENTRY(start_cpu0)
movq initial_stack(%rip), %rsp
jmp start_cpu
jmp .Ljump_to_C_code
ENDPROC(start_cpu0)
#endif
......
......@@ -25,6 +25,7 @@
#include <asm/setup.h>
#include <asm/crash.h>
#include <asm/efi.h>
#include <asm/e820/api.h>
#include <asm/kexec-bzimage64.h>
#define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */
......@@ -99,15 +100,14 @@ static int setup_e820_entries(struct boot_params *params)
{
unsigned int nr_e820_entries;
nr_e820_entries = e820_saved->nr_map;
nr_e820_entries = e820_table_firmware->nr_entries;
/* TODO: Pass entries more than E820MAX in bootparams setup data */
if (nr_e820_entries > E820MAX)
nr_e820_entries = E820MAX;
/* TODO: Pass entries more than E820_MAX_ENTRIES_ZEROPAGE in bootparams setup data */
if (nr_e820_entries > E820_MAX_ENTRIES_ZEROPAGE)
nr_e820_entries = E820_MAX_ENTRIES_ZEROPAGE;
params->e820_entries = nr_e820_entries;
memcpy(&params->e820_map, &e820_saved->map,
nr_e820_entries * sizeof(struct e820entry));
memcpy(&params->e820_table, &e820_table_firmware->entries, nr_e820_entries*sizeof(struct e820_entry));
return 0;
}
......@@ -232,10 +232,10 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params,
nr_e820_entries = params->e820_entries;
for (i = 0; i < nr_e820_entries; i++) {
if (params->e820_map[i].type != E820_RAM)
if (params->e820_table[i].type != E820_TYPE_RAM)
continue;
start = params->e820_map[i].addr;
end = params->e820_map[i].addr + params->e820_map[i].size - 1;
start = params->e820_table[i].addr;
end = params->e820_table[i].addr + params->e820_table[i].size - 1;
if ((start <= 0x100000) && end > 0x100000) {
mem_k = (end >> 10) - (0x100000 >> 10);
......
......@@ -26,7 +26,7 @@
#include <asm/io_apic.h>
#include <asm/proto.h>
#include <asm/bios_ebda.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/setup.h>
#include <asm/smp.h>
......@@ -826,10 +826,10 @@ static int __init parse_alloc_mptable_opt(char *p)
}
early_param("alloc_mptable", parse_alloc_mptable_opt);
void __init early_reserve_e820_mpc_new(void)
void __init e820__memblock_alloc_reserved_mpc_new(void)
{
if (enable_update_mptable && alloc_mptable)
mpc_new_phys = early_reserve_e820(mpc_new_length, 4);
mpc_new_phys = e820__memblock_alloc_reserved(mpc_new_length, 4);
}
static int __init update_mp_table(void)
......
......@@ -14,7 +14,7 @@
#include <asm/probe_roms.h>
#include <asm/pci-direct.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/mmzone.h>
#include <asm/setup.h>
#include <asm/sections.h>
......
#include <linux/ioport.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
static void resource_clip(struct resource *res, resource_size_t start,
resource_size_t end)
......@@ -25,10 +25,10 @@ static void resource_clip(struct resource *res, resource_size_t start,
static void remove_e820_regions(struct resource *avail)
{
int i;
struct e820entry *entry;
struct e820_entry *entry;
for (i = 0; i < e820->nr_map; i++) {
entry = &e820->map[i];
for (i = 0; i < e820_table->nr_entries; i++) {
entry = &e820_table->entries[i];
resource_clip(avail, entry->addr,
entry->addr + entry->size - 1);
......
......@@ -75,7 +75,7 @@
#include <asm/mtrr.h>
#include <asm/apic.h>
#include <asm/realmode.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/mpspec.h>
#include <asm/setup.h>
#include <asm/efi.h>
......@@ -119,7 +119,7 @@
* max_low_pfn_mapped: highest direct mapped pfn under 4GB
* max_pfn_mapped: highest direct mapped pfn over 4GB
*
* The direct mapping only covers E820_RAM regions, so the ranges and gaps are
* The direct mapping only covers E820_TYPE_RAM regions, so the ranges and gaps are
* represented by pfn_mapped
*/
unsigned long max_low_pfn_mapped;
......@@ -423,7 +423,7 @@ static void __init parse_setup_data(void)
switch (data_type) {
case SETUP_E820_EXT:
parse_e820_ext(pa_data, data_len);
e820__memory_setup_extended(pa_data, data_len);
break;
case SETUP_DTB:
add_dtb(pa_data);
......@@ -438,29 +438,6 @@ static void __init parse_setup_data(void)
}
}
static void __init e820_reserve_setup_data(void)
{
struct setup_data *data;
u64 pa_data;
pa_data = boot_params.hdr.setup_data;
if (!pa_data)
return;
while (pa_data) {
data = early_memremap(pa_data, sizeof(*data));
e820_update_range(pa_data, sizeof(*data)+data->len,
E820_RAM, E820_RESERVED_KERN);
pa_data = data->next;
early_memunmap(data, sizeof(*data));
}
sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map);
memcpy(e820_saved, e820, sizeof(struct e820map));
printk(KERN_INFO "extended physical RAM map:\n");
e820_print_map("reserve setup_data");
}
static void __init memblock_x86_reserve_range_setup_data(void)
{
struct setup_data *data;
......@@ -753,16 +730,16 @@ static void __init trim_bios_range(void)
* since some BIOSes are known to corrupt low memory. See the
* Kconfig help text for X86_RESERVE_LOW.
*/
e820_update_range(0, PAGE_SIZE, E820_RAM, E820_RESERVED);
e820__range_update(0, PAGE_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
/*
* special case: Some BIOSen report the PC BIOS
* area (640->1Mb) as ram even though it is not.
* take them out.
*/
e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1);
e820__range_remove(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_TYPE_RAM, 1);
sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map);
e820__update_table(e820_table);
}
/* called before trim_bios_range() to spare extra sanitize */
......@@ -772,18 +749,18 @@ static void __init e820_add_kernel_range(void)
u64 size = __pa_symbol(_end) - start;
/*
* Complain if .text .data and .bss are not marked as E820_RAM and
* Complain if .text .data and .bss are not marked as E820_TYPE_RAM and
* attempt to fix it by adding the range. We may have a confused BIOS,
* or the user may have used memmap=exactmap or memmap=xxM$yyM to
* exclude kernel range. If we really are running on top non-RAM,
* we will crash later anyways.
*/
if (e820_all_mapped(start, start + size, E820_RAM))
if (e820__mapped_all(start, start + size, E820_TYPE_RAM))
return;
pr_warn(".text .data .bss are not marked as E820_RAM!\n");
e820_remove_range(start, size, E820_RAM, 0);
e820_add_region(start, size, E820_RAM);
pr_warn(".text .data .bss are not marked as E820_TYPE_RAM!\n");
e820__range_remove(start, size, E820_TYPE_RAM, 0);
e820__range_add(start, size, E820_TYPE_RAM);
}
static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10;
......@@ -936,7 +913,7 @@ void __init setup_arch(char **cmdline_p)
x86_init.oem.arch_setup();
iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1;
setup_memory_map();
e820__memory_setup();
parse_setup_data();
copy_edd();
......@@ -1025,9 +1002,8 @@ void __init setup_arch(char **cmdline_p)
early_dump_pci_devices();
#endif
/* update the e820_saved too */
e820_reserve_setup_data();
finish_e820_parsing();
e820__reserve_setup_data();
e820__finish_early_params();
if (efi_enabled(EFI_BOOT))
efi_init();
......@@ -1053,11 +1029,11 @@ void __init setup_arch(char **cmdline_p)
trim_bios_range();
#ifdef CONFIG_X86_32
if (ppro_with_ram_bug()) {
e820_update_range(0x70000000ULL, 0x40000ULL, E820_RAM,
E820_RESERVED);
sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map);
e820__range_update(0x70000000ULL, 0x40000ULL, E820_TYPE_RAM,
E820_TYPE_RESERVED);
e820__update_table(e820_table);
printk(KERN_INFO "fixed physical RAM map:\n");
e820_print_map("bad_ppro");
e820__print_table("bad_ppro");
}
#else
early_gart_iommu_check();
......@@ -1067,12 +1043,12 @@ void __init setup_arch(char **cmdline_p)
* partially used pages are not usable - thus
* we are rounding upwards:
*/
max_pfn = e820_end_of_ram_pfn();
max_pfn = e820__end_of_ram_pfn();
/* update e820 for memory not covered by WB MTRRs */
mtrr_bp_init();
if (mtrr_trim_uncached_memory(max_pfn))
max_pfn = e820_end_of_ram_pfn();
max_pfn = e820__end_of_ram_pfn();
max_possible_pfn = max_pfn;
......@@ -1091,7 +1067,7 @@ void __init setup_arch(char **cmdline_p)
/* How many end-of-memory variables you have, grandma! */
/* need this before calling reserve_initrd */
if (max_pfn > (1UL<<(32 - PAGE_SHIFT)))
max_low_pfn = e820_end_of_low_ram_pfn();
max_low_pfn = e820__end_of_low_ram_pfn();
else
max_low_pfn = max_pfn;
......@@ -1108,7 +1084,7 @@ void __init setup_arch(char **cmdline_p)
early_alloc_pgt_buf();
/*
* Need to conclude brk, before memblock_x86_fill()
* Need to conclude brk, before e820__memblock_setup()
* it could use memblock_find_in_range, could overlap with
* brk area.
*/
......@@ -1117,7 +1093,7 @@ void __init setup_arch(char **cmdline_p)
cleanup_highmap();
memblock_set_current_limit(ISA_END_ADDRESS);
memblock_x86_fill();
e820__memblock_setup();
reserve_bios_regions();
......@@ -1134,7 +1110,7 @@ void __init setup_arch(char **cmdline_p)
}
/* preallocate 4k for mptable mpc */
early_reserve_e820_mpc_new();
e820__memblock_alloc_reserved_mpc_new();
#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
setup_bios_corruption_check();
......@@ -1257,12 +1233,12 @@ void __init setup_arch(char **cmdline_p)
kvm_guest_init();
e820_reserve_resources();
e820_mark_nosave_regions(max_low_pfn);
e820__reserve_resources();
e820__register_nosave_regions(max_low_pfn);
x86_init.resources.reserve_resources();
e820_setup_gap();
e820__setup_pci_gap();
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
......
......@@ -42,7 +42,7 @@
#include <asm/fixmap.h>
#include <asm/proto.h>
#include <asm/setup.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/io.h>
#include "../realmode/rm/wakeup.h"
......@@ -68,9 +68,9 @@ void __init tboot_probe(void)
* also verify that it is mapped as we expect it before calling
* set_fixmap(), to reduce chance of garbage value causing crash
*/
if (!e820_any_mapped(boot_params.tboot_addr,
boot_params.tboot_addr, E820_RESERVED)) {
pr_warning("non-0 tboot_addr but it is not of type E820_RESERVED\n");
if (!e820__mapped_any(boot_params.tboot_addr,
boot_params.tboot_addr, E820_TYPE_RESERVED)) {
pr_warning("non-0 tboot_addr but it is not of type E820_TYPE_RESERVED\n");
return;
}
......@@ -192,12 +192,12 @@ static int tboot_setup_sleep(void)
tboot->num_mac_regions = 0;
for (i = 0; i < e820->nr_map; i++) {
if ((e820->map[i].type != E820_RAM)
&& (e820->map[i].type != E820_RESERVED_KERN))
for (i = 0; i < e820_table->nr_entries; i++) {
if ((e820_table->entries[i].type != E820_TYPE_RAM)
&& (e820_table->entries[i].type != E820_TYPE_RESERVED_KERN))
continue;
add_mac_region(e820->map[i].addr, e820->map[i].size);
add_mac_region(e820_table->entries[i].addr, e820_table->entries[i].size);
}
tboot->acpi_sinfo.kernel_s3_resume_vector =
......
......@@ -14,7 +14,7 @@
#include <asm/mpspec.h>
#include <asm/setup.h>
#include <asm/apic.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/time.h>
#include <asm/irq.h>
#include <asm/io_apic.h>
......@@ -38,7 +38,7 @@ struct x86_init_ops x86_init __initdata = {
.resources = {
.probe_roms = probe_roms,
.reserve_resources = reserve_standard_io_resources,
.memory_setup = default_machine_specific_memory_setup,
.memory_setup = e820__memory_setup_default,
},
.mpparse = {
......
......@@ -67,7 +67,7 @@
#include <asm/pgtable.h>
#include <asm/desc.h>
#include <asm/setup.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/mce.h>
#include <asm/io.h>
#include <asm/fpu/api.h>
......@@ -1178,9 +1178,9 @@ static __init char *lguest_memory_setup(void)
* The Linux bootloader header contains an "e820" memory map: the
* Launcher populated the first entry with our memory limit.
*/
e820_add_region(boot_params.e820_map[0].addr,
boot_params.e820_map[0].size,
boot_params.e820_map[0].type);
e820__range_add(boot_params.e820_table[0].addr,
boot_params.e820_table[0].size,
boot_params.e820_table[0].type);
/* This string is for the boot messages. */
return "LGUEST";
......
......@@ -8,7 +8,7 @@
#include <asm/kaslr.h>
#include <asm/msr.h>
#include <asm/archrandom.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/io.h>
/*
......
......@@ -19,7 +19,7 @@
#include <asm/types.h>
#include <asm/mmzone.h>
#include <asm/proto.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/pci-direct.h>
#include <asm/numa.h>
#include <asm/mpspec.h>
......
......@@ -6,7 +6,7 @@
#include <linux/bootmem.h> /* for max_low_pfn */
#include <asm/cacheflush.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/init.h>
#include <asm/page.h>
#include <asm/page_types.h>
......@@ -373,14 +373,14 @@ static int __meminit split_mem_range(struct map_range *mr, int nr_range,
return nr_range;
}
struct range pfn_mapped[E820_X_MAX];
struct range pfn_mapped[E820_MAX_ENTRIES];
int nr_pfn_mapped;
static void add_pfn_range_mapped(unsigned long start_pfn, unsigned long end_pfn)
{
nr_pfn_mapped = add_range_with_merge(pfn_mapped, E820_X_MAX,
nr_pfn_mapped = add_range_with_merge(pfn_mapped, E820_MAX_ENTRIES,
nr_pfn_mapped, start_pfn, end_pfn);
nr_pfn_mapped = clean_sort_range(pfn_mapped, E820_X_MAX);
nr_pfn_mapped = clean_sort_range(pfn_mapped, E820_MAX_ENTRIES);
max_pfn_mapped = max(max_pfn_mapped, end_pfn);
......@@ -430,7 +430,7 @@ unsigned long __ref init_memory_mapping(unsigned long start,
/*
* We need to iterate through the E820 memory map and create direct mappings
* for only E820_RAM and E820_KERN_RESERVED regions. We cannot simply
* for only E820_TYPE_RAM and E820_KERN_RESERVED regions. We cannot simply
* create direct mappings for all pfns from [0 to max_low_pfn) and
* [4GB to max_pfn) because of possible memory holes in high addresses
* that cannot be marked as UC by fixed/variable range MTRRs.
......@@ -701,7 +701,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
void __ref free_initmem(void)
{
e820_reallocate_tables();
e820__reallocate_tables();
free_init_pages("unused kernel",
(unsigned long)(&__init_begin),
......@@ -724,6 +724,53 @@ void __init free_initrd_mem(unsigned long start, unsigned long end)
}
#endif
/*
* Calculate the precise size of the DMA zone (first 16 MB of RAM),
* and pass it to the MM layer - to help it set zone watermarks more
* accurately.
*
* Done on 64-bit systems only for the time being, although 32-bit systems
* might benefit from this as well.
*/
void __init memblock_find_dma_reserve(void)
{
#ifdef CONFIG_X86_64
u64 nr_pages = 0, nr_free_pages = 0;
unsigned long start_pfn, end_pfn;
phys_addr_t start_addr, end_addr;
int i;
u64 u;
/*
* Iterate over all memory ranges (free and reserved ones alike),
* to calculate the total number of pages in the first 16 MB of RAM:
*/
nr_pages = 0;
for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, NULL) {
start_pfn = min(start_pfn, MAX_DMA_PFN);
end_pfn = min(end_pfn, MAX_DMA_PFN);
nr_pages += end_pfn - start_pfn;
}
/*
* Iterate over free memory ranges to calculate the number of free
* pages in the DMA zone, while not counting potential partial
* pages at the beginning or the end of the range:
*/
nr_free_pages = 0;
for_each_free_mem_range(u, NUMA_NO_NODE, MEMBLOCK_NONE, &start_addr, &end_addr, NULL) {
start_pfn = min_t(unsigned long, PFN_UP(start_addr), MAX_DMA_PFN);
end_pfn = min_t(unsigned long, PFN_DOWN(end_addr), MAX_DMA_PFN);
if (start_pfn < end_pfn)
nr_free_pages += end_pfn - start_pfn;
}
set_dma_reserve(nr_pages - nr_free_pages);
#endif
}
void __init zone_sizes_init(void)
{
unsigned long max_zone_pfns[MAX_NR_ZONES];
......
......@@ -38,7 +38,7 @@
#include <asm/pgtable.h>
#include <asm/dma.h>
#include <asm/fixmap.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/apic.h>
#include <asm/bugs.h>
#include <asm/tlb.h>
......
......@@ -41,7 +41,7 @@
#include <asm/pgalloc.h>
#include <asm/dma.h>
#include <asm/fixmap.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/apic.h>
#include <asm/tlb.h>
#include <asm/mmu_context.h>
......@@ -379,10 +379,10 @@ phys_pte_init(pte_t *pte_page, unsigned long paddr, unsigned long paddr_end,
paddr_next = (paddr & PAGE_MASK) + PAGE_SIZE;
if (paddr >= paddr_end) {
if (!after_bootmem &&
!e820_any_mapped(paddr & PAGE_MASK, paddr_next,
E820_RAM) &&
!e820_any_mapped(paddr & PAGE_MASK, paddr_next,
E820_RESERVED_KERN))
!e820__mapped_any(paddr & PAGE_MASK, paddr_next,
E820_TYPE_RAM) &&
!e820__mapped_any(paddr & PAGE_MASK, paddr_next,
E820_TYPE_RESERVED_KERN))
set_pte(pte, __pte(0));
continue;
}
......@@ -434,10 +434,10 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long paddr, unsigned long paddr_end,
paddr_next = (paddr & PMD_MASK) + PMD_SIZE;
if (paddr >= paddr_end) {
if (!after_bootmem &&
!e820_any_mapped(paddr & PMD_MASK, paddr_next,
E820_RAM) &&
!e820_any_mapped(paddr & PMD_MASK, paddr_next,
E820_RESERVED_KERN))
!e820__mapped_any(paddr & PMD_MASK, paddr_next,
E820_TYPE_RAM) &&
!e820__mapped_any(paddr & PMD_MASK, paddr_next,
E820_TYPE_RESERVED_KERN))
set_pmd(pmd, __pmd(0));
continue;
}
......@@ -520,10 +520,10 @@ phys_pud_init(pud_t *pud_page, unsigned long paddr, unsigned long paddr_end,
if (paddr >= paddr_end) {
if (!after_bootmem &&
!e820_any_mapped(paddr & PUD_MASK, paddr_next,
E820_RAM) &&
!e820_any_mapped(paddr & PUD_MASK, paddr_next,
E820_RESERVED_KERN))
!e820__mapped_any(paddr & PUD_MASK, paddr_next,
E820_TYPE_RAM) &&
!e820__mapped_any(paddr & PUD_MASK, paddr_next,
E820_TYPE_RESERVED_KERN))
set_pud(pud, __pud(0));
continue;
}
......
......@@ -9,12 +9,13 @@
#include <linux/bootmem.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mmiotrace.h>
#include <asm/cacheflush.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/fixmap.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
......
......@@ -8,11 +8,12 @@
#include <linux/sched/task.h>
#include <linux/vmalloc.h>
#include <asm/e820/types.h>
#include <asm/tlbflush.h>
#include <asm/sections.h>
extern pgd_t early_level4_pgt[PTRS_PER_PGD];
extern struct range pfn_mapped[E820_X_MAX];
extern struct range pfn_mapped[E820_MAX_ENTRIES];
static int __init map_range(struct range *range)
{
......@@ -129,7 +130,7 @@ void __init kasan_init(void)
kasan_populate_zero_shadow((void *)KASAN_SHADOW_START,
kasan_mem_to_shadow((void *)PAGE_OFFSET));
for (i = 0; i < E820_X_MAX; i++) {
for (i = 0; i < E820_MAX_ENTRIES; i++) {
if (pfn_mapped[i].end == 0)
break;
......
......@@ -32,7 +32,7 @@
#include <linux/kallsyms.h>
#include <asm/pgtable.h>
#include <linux/mmiotrace.h>
#include <asm/e820.h> /* for ISA_START_ADDRESS */
#include <asm/e820/api.h> /* for ISA_START_ADDRESS */
#include <linux/atomic.h>
#include <linux/percpu.h>
#include <linux/cpu.h>
......
......@@ -12,7 +12,7 @@
#include <linux/sched.h>
#include <linux/topology.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/proto.h>
#include <asm/dma.h>
#include <asm/amd_nb.h>
......
......@@ -15,7 +15,7 @@
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/processor.h>
#include <asm/tlbflush.h>
#include <asm/sections.h>
......
......@@ -10,6 +10,7 @@
#include <linux/seq_file.h>
#include <linux/bootmem.h>
#include <linux/debugfs.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/pfn_t.h>
#include <linux/slab.h>
......@@ -23,7 +24,7 @@
#include <asm/x86_init.h>
#include <asm/pgtable.h>
#include <asm/fcntl.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/mtrr.h>
#include <asm/page.h>
#include <asm/msr.h>
......
......@@ -12,7 +12,7 @@
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/fixmap.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/tlb.h>
#include <asm/tlbflush.h>
#include <asm/io.h>
......
......@@ -18,7 +18,7 @@
#include <linux/mm.h>
#include <asm/proto.h>
#include <asm/numa.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/apic.h>
#include <asm/uv/uv.h>
......
......@@ -34,7 +34,7 @@
#include <linux/bootmem.h>
#include <asm/pat.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/pci_x86.h>
#include <asm/io_apic.h>
......@@ -398,7 +398,7 @@ void __init pcibios_resource_survey(void)
list_for_each_entry(bus, &pci_root_buses, node)
pcibios_allocate_resources(bus, 1);
e820_reserve_resources_late();
e820__reserve_resources_late();
/*
* Insert the IO APIC resources after PCI initialization has
* occurred to handle IO APICS that are mapped in on a BAR in
......
......@@ -18,7 +18,7 @@
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/rculist.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/pci_x86.h>
#include <asm/acpi.h>
......@@ -423,7 +423,7 @@ static acpi_status find_mboard_resource(acpi_handle handle, u32 lvl,
return AE_OK;
}
static int is_acpi_reserved(u64 start, u64 end, unsigned not_used)
static bool is_acpi_reserved(u64 start, u64 end, unsigned not_used)
{
struct resource mcfg_res;
......@@ -440,11 +440,11 @@ static int is_acpi_reserved(u64 start, u64 end, unsigned not_used)
return mcfg_res.flags;
}
typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type);
typedef bool (*check_reserved_t)(u64 start, u64 end, unsigned type);
static int __ref is_mmconf_reserved(check_reserved_t is_reserved,
struct pci_mmcfg_region *cfg,
struct device *dev, int with_e820)
static bool __ref is_mmconf_reserved(check_reserved_t is_reserved,
struct pci_mmcfg_region *cfg,
struct device *dev, int with_e820)
{
u64 addr = cfg->res.start;
u64 size = resource_size(&cfg->res);
......@@ -452,7 +452,7 @@ static int __ref is_mmconf_reserved(check_reserved_t is_reserved,
int num_buses;
char *method = with_e820 ? "E820" : "ACPI motherboard resources";
while (!is_reserved(addr, addr + size, E820_RESERVED)) {
while (!is_reserved(addr, addr + size, E820_TYPE_RESERVED)) {
size >>= 1;
if (size < (16UL<<20))
break;
......@@ -494,8 +494,8 @@ static int __ref is_mmconf_reserved(check_reserved_t is_reserved,
return 1;
}
static int __ref pci_mmcfg_check_reserved(struct device *dev,
struct pci_mmcfg_region *cfg, int early)
static bool __ref
pci_mmcfg_check_reserved(struct device *dev, struct pci_mmcfg_region *cfg, int early)
{
if (!early && !acpi_disabled) {
if (is_mmconf_reserved(is_acpi_reserved, cfg, dev, 0))
......@@ -514,7 +514,7 @@ static int __ref pci_mmcfg_check_reserved(struct device *dev,
}
/*
* e820_all_mapped() is marked as __init.
* e820__mapped_all() is marked as __init.
* All entries from ACPI MCFG table have been checked at boot time.
* For MCFG information constructed from hotpluggable host bridge's
* _CBA method, just assume it's reserved.
......@@ -525,7 +525,7 @@ static int __ref pci_mmcfg_check_reserved(struct device *dev,
/* Don't try to do this check unless configuration
type 1 is available. how about type 2 ?*/
if (raw_pci_ops)
return is_mmconf_reserved(e820_all_mapped, cfg, dev, 1);
return is_mmconf_reserved(e820__mapped_all, cfg, dev, 1);
return 0;
}
......
......@@ -12,7 +12,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/rcupdate.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/pci_x86.h>
/* Assume systems with more busses have correct MCFG */
......
......@@ -10,7 +10,7 @@
#include <linux/acpi.h>
#include <linux/bitmap.h>
#include <linux/rcupdate.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/pci_x86.h>
#define PREFIX "PCI: "
......
......@@ -7,7 +7,9 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <asm/pci_x86.h>
#include <asm/e820/types.h>
#include <asm/pci-functions.h>
#include <asm/cacheflush.h>
......
......@@ -47,6 +47,7 @@
#include <asm/setup.h>
#include <asm/efi.h>
#include <asm/e820/api.h>
#include <asm/time.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
......@@ -139,21 +140,21 @@ static void __init do_add_efi_memmap(void)
case EFI_BOOT_SERVICES_DATA:
case EFI_CONVENTIONAL_MEMORY:
if (md->attribute & EFI_MEMORY_WB)
e820_type = E820_RAM;
e820_type = E820_TYPE_RAM;
else
e820_type = E820_RESERVED;
e820_type = E820_TYPE_RESERVED;
break;
case EFI_ACPI_RECLAIM_MEMORY:
e820_type = E820_ACPI;
e820_type = E820_TYPE_ACPI;
break;
case EFI_ACPI_MEMORY_NVS:
e820_type = E820_NVS;
e820_type = E820_TYPE_NVS;
break;
case EFI_UNUSABLE_MEMORY:
e820_type = E820_UNUSABLE;
e820_type = E820_TYPE_UNUSABLE;
break;
case EFI_PERSISTENT_MEMORY:
e820_type = E820_PMEM;
e820_type = E820_TYPE_PMEM;
break;
default:
/*
......@@ -161,12 +162,12 @@ static void __init do_add_efi_memmap(void)
* EFI_RUNTIME_SERVICES_DATA EFI_MEMORY_MAPPED_IO
* EFI_MEMORY_MAPPED_IO_PORT_SPACE EFI_PAL_CODE
*/
e820_type = E820_RESERVED;
e820_type = E820_TYPE_RESERVED;
break;
}
e820_add_region(start, size, e820_type);
e820__range_add(start, size, e820_type);
}
sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map);
e820__update_table(e820_table);
}
int __init efi_memblock_x86_reserve_range(void)
......
......@@ -35,7 +35,7 @@
#include <asm/setup.h>
#include <asm/page.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/proto.h>
......
......@@ -11,6 +11,8 @@
#include <linux/bootmem.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <asm/e820/api.h>
#include <asm/efi.h>
#include <asm/uv/uv.h>
......@@ -240,14 +242,14 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
* else. We must only reserve (and then free) regions:
*
* - Not within any part of the kernel
* - Not the BIOS reserved area (E820_RESERVED, E820_NVS, etc)
* - Not the BIOS reserved area (E820_TYPE_RESERVED, E820_TYPE_NVS, etc)
*/
static bool can_free_region(u64 start, u64 size)
{
if (start + size > __pa_symbol(_text) && start <= __pa_symbol(_end))
return false;
if (!e820_all_mapped(start, start+size, E820_RAM))
if (!e820__mapped_all(start, start+size, E820_TYPE_RAM))
return false;
return true;
......@@ -280,7 +282,7 @@ void __init efi_reserve_boot_services(void)
* A good example of a critical region that must not be
* freed is page zero (first 4Kb of memory), which may
* contain boot services code/data but is marked
* E820_RESERVED by trim_bios_range().
* E820_TYPE_RESERVED by trim_bios_range().
*/
if (!already_reserved) {
memblock_reserve(start, size);
......
......@@ -16,6 +16,7 @@
#include <crypto/hash.h>
#include <asm/e820/api.h>
#include <asm/init.h>
#include <asm/proto.h>
#include <asm/page.h>
......@@ -214,12 +215,12 @@ struct restore_data_record {
#if IS_BUILTIN(CONFIG_CRYPTO_MD5)
/**
* get_e820_md5 - calculate md5 according to given e820 map
* get_e820_md5 - calculate md5 according to given e820 table
*
* @map: the e820 map to be calculated
* @table: the e820 table to be calculated
* @buf: the md5 result to be stored to
*/
static int get_e820_md5(struct e820map *map, void *buf)
static int get_e820_md5(struct e820_table *table, void *buf)
{
struct scatterlist sg;
struct crypto_ahash *tfm;
......@@ -232,10 +233,9 @@ static int get_e820_md5(struct e820map *map, void *buf)
{
AHASH_REQUEST_ON_STACK(req, tfm);
size = offsetof(struct e820map, map)
+ sizeof(struct e820entry) * map->nr_map;
size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry) * table->nr_entries;
ahash_request_set_tfm(req, tfm);
sg_init_one(&sg, (u8 *)map, size);
sg_init_one(&sg, (u8 *)table, size);
ahash_request_set_callback(req, 0, NULL, NULL);
ahash_request_set_crypt(req, &sg, buf, size);
......@@ -250,7 +250,7 @@ static int get_e820_md5(struct e820map *map, void *buf)
static void hibernation_e820_save(void *buf)
{
get_e820_md5(e820_saved, buf);
get_e820_md5(e820_table_firmware, buf);
}
static bool hibernation_e820_mismatch(void *buf)
......@@ -263,7 +263,7 @@ static bool hibernation_e820_mismatch(void *buf)
if (!memcmp(result, buf, MD5_DIGEST_SIZE))
return false;
ret = get_e820_md5(e820_saved, result);
ret = get_e820_md5(e820_table_firmware, result);
if (ret)
return true;
......
......@@ -76,6 +76,7 @@
#include <asm/mwait.h>
#include <asm/pci_x86.h>
#include <asm/cpu.h>
#include <asm/e820/api.h>
#ifdef CONFIG_ACPI
#include <linux/acpi.h>
......@@ -1689,34 +1690,32 @@ static void __init init_pvh_bootparams(void)
memset(&pvh_bootparams, 0, sizeof(pvh_bootparams));
memmap.nr_entries = ARRAY_SIZE(pvh_bootparams.e820_map);
set_xen_guest_handle(memmap.buffer, pvh_bootparams.e820_map);
memmap.nr_entries = ARRAY_SIZE(pvh_bootparams.e820_table);
set_xen_guest_handle(memmap.buffer, pvh_bootparams.e820_table);
rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
if (rc) {
xen_raw_printk("XENMEM_memory_map failed (%d)\n", rc);
BUG();
}
if (memmap.nr_entries < E820MAX - 1) {
pvh_bootparams.e820_map[memmap.nr_entries].addr =
if (memmap.nr_entries < E820_MAX_ENTRIES_ZEROPAGE - 1) {
pvh_bootparams.e820_table[memmap.nr_entries].addr =
ISA_START_ADDRESS;
pvh_bootparams.e820_map[memmap.nr_entries].size =
pvh_bootparams.e820_table[memmap.nr_entries].size =
ISA_END_ADDRESS - ISA_START_ADDRESS;
pvh_bootparams.e820_map[memmap.nr_entries].type =
E820_RESERVED;
pvh_bootparams.e820_table[memmap.nr_entries].type =
E820_TYPE_RESERVED;
memmap.nr_entries++;
} else
xen_raw_printk("Warning: Can fit ISA range into e820\n");
sanitize_e820_map(pvh_bootparams.e820_map,
ARRAY_SIZE(pvh_bootparams.e820_map),
&memmap.nr_entries);
pvh_bootparams.e820_entries = memmap.nr_entries;
for (i = 0; i < pvh_bootparams.e820_entries; i++)
e820_add_region(pvh_bootparams.e820_map[i].addr,
pvh_bootparams.e820_map[i].size,
pvh_bootparams.e820_map[i].type);
e820__range_add(pvh_bootparams.e820_table[i].addr,
pvh_bootparams.e820_table[i].size,
pvh_bootparams.e820_table[i].type);
e820__update_table(e820_table);
pvh_bootparams.hdr.cmd_line_ptr =
pvh_start_info.cmdline_paddr;
......
......@@ -58,7 +58,7 @@
#include <asm/mmu_context.h>
#include <asm/setup.h>
#include <asm/paravirt.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/linkage.h>
#include <asm/page.h>
#include <asm/init.h>
......
......@@ -14,7 +14,7 @@
#include <asm/elf.h>
#include <asm/vdso.h>
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/setup.h>
#include <asm/acpi.h>
#include <asm/numa.h>
......@@ -41,8 +41,7 @@ struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
unsigned long xen_released_pages;
/* E820 map used during setting up memory. */
static struct e820entry xen_e820_map[E820_X_MAX] __initdata;
static u32 xen_e820_map_entries __initdata;
static struct e820_table xen_e820_table __initdata;
/*
* Buffer used to remap identity mapped pages. We only need the virtual space.
......@@ -198,15 +197,15 @@ void __init xen_inv_extra_mem(void)
*/
static unsigned long __init xen_find_pfn_range(unsigned long *min_pfn)
{
const struct e820entry *entry = xen_e820_map;
const struct e820_entry *entry = xen_e820_table.entries;
unsigned int i;
unsigned long done = 0;
for (i = 0; i < xen_e820_map_entries; i++, entry++) {
for (i = 0; i < xen_e820_table.nr_entries; i++, entry++) {
unsigned long s_pfn;
unsigned long e_pfn;
if (entry->type != E820_RAM)
if (entry->type != E820_TYPE_RAM)
continue;
e_pfn = PFN_DOWN(entry->addr + entry->size);
......@@ -457,7 +456,7 @@ static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages,
{
phys_addr_t start = 0;
unsigned long ret_val = 0;
const struct e820entry *entry = xen_e820_map;
const struct e820_entry *entry = xen_e820_table.entries;
int i;
/*
......@@ -471,13 +470,13 @@ static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages,
* example) the DMI tables in a reserved region that begins on
* a non-page boundary.
*/
for (i = 0; i < xen_e820_map_entries; i++, entry++) {
for (i = 0; i < xen_e820_table.nr_entries; i++, entry++) {
phys_addr_t end = entry->addr + entry->size;
if (entry->type == E820_RAM || i == xen_e820_map_entries - 1) {
if (entry->type == E820_TYPE_RAM || i == xen_e820_table.nr_entries - 1) {
unsigned long start_pfn = PFN_DOWN(start);
unsigned long end_pfn = PFN_UP(end);
if (entry->type == E820_RAM)
if (entry->type == E820_TYPE_RAM)
end_pfn = PFN_UP(entry->addr);
if (start_pfn < end_pfn)
......@@ -591,28 +590,28 @@ static void __init xen_align_and_add_e820_region(phys_addr_t start,
phys_addr_t end = start + size;
/* Align RAM regions to page boundaries. */
if (type == E820_RAM) {
if (type == E820_TYPE_RAM) {
start = PAGE_ALIGN(start);
end &= ~((phys_addr_t)PAGE_SIZE - 1);
}
e820_add_region(start, end - start, type);
e820__range_add(start, end - start, type);
}
static void __init xen_ignore_unusable(void)
{
struct e820entry *entry = xen_e820_map;
struct e820_entry *entry = xen_e820_table.entries;
unsigned int i;
for (i = 0; i < xen_e820_map_entries; i++, entry++) {
if (entry->type == E820_UNUSABLE)
entry->type = E820_RAM;
for (i = 0; i < xen_e820_table.nr_entries; i++, entry++) {
if (entry->type == E820_TYPE_UNUSABLE)
entry->type = E820_TYPE_RAM;
}
}
bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size)
{
struct e820entry *entry;
struct e820_entry *entry;
unsigned mapcnt;
phys_addr_t end;
......@@ -620,10 +619,10 @@ bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size)
return false;
end = start + size;
entry = xen_e820_map;
entry = xen_e820_table.entries;
for (mapcnt = 0; mapcnt < xen_e820_map_entries; mapcnt++) {
if (entry->type == E820_RAM && entry->addr <= start &&
for (mapcnt = 0; mapcnt < xen_e820_table.nr_entries; mapcnt++) {
if (entry->type == E820_TYPE_RAM && entry->addr <= start &&
(entry->addr + entry->size) >= end)
return false;
......@@ -645,10 +644,10 @@ phys_addr_t __init xen_find_free_area(phys_addr_t size)
{
unsigned mapcnt;
phys_addr_t addr, start;
struct e820entry *entry = xen_e820_map;
struct e820_entry *entry = xen_e820_table.entries;
for (mapcnt = 0; mapcnt < xen_e820_map_entries; mapcnt++, entry++) {
if (entry->type != E820_RAM || entry->size < size)
for (mapcnt = 0; mapcnt < xen_e820_table.nr_entries; mapcnt++, entry++) {
if (entry->type != E820_TYPE_RAM || entry->size < size)
continue;
start = entry->addr;
for (addr = start; addr < start + size; addr += PAGE_SIZE) {
......@@ -750,8 +749,8 @@ char * __init xen_memory_setup(void)
max_pfn = min(max_pfn, xen_start_info->nr_pages);
mem_end = PFN_PHYS(max_pfn);
memmap.nr_entries = ARRAY_SIZE(xen_e820_map);
set_xen_guest_handle(memmap.buffer, xen_e820_map);
memmap.nr_entries = ARRAY_SIZE(xen_e820_table.entries);
set_xen_guest_handle(memmap.buffer, xen_e820_table.entries);
op = xen_initial_domain() ?
XENMEM_machine_memory_map :
......@@ -760,16 +759,16 @@ char * __init xen_memory_setup(void)
if (rc == -ENOSYS) {
BUG_ON(xen_initial_domain());
memmap.nr_entries = 1;
xen_e820_map[0].addr = 0ULL;
xen_e820_map[0].size = mem_end;
xen_e820_table.entries[0].addr = 0ULL;
xen_e820_table.entries[0].size = mem_end;
/* 8MB slack (to balance backend allocations). */
xen_e820_map[0].size += 8ULL << 20;
xen_e820_map[0].type = E820_RAM;
xen_e820_table.entries[0].size += 8ULL << 20;
xen_e820_table.entries[0].type = E820_TYPE_RAM;
rc = 0;
}
BUG_ON(rc);
BUG_ON(memmap.nr_entries == 0);
xen_e820_map_entries = memmap.nr_entries;
xen_e820_table.nr_entries = memmap.nr_entries;
/*
* Xen won't allow a 1:1 mapping to be created to UNUSABLE
......@@ -783,8 +782,7 @@ char * __init xen_memory_setup(void)
xen_ignore_unusable();
/* Make sure the Xen-supplied memory map is well-ordered. */
sanitize_e820_map(xen_e820_map, ARRAY_SIZE(xen_e820_map),
&xen_e820_map_entries);
e820__update_table(&xen_e820_table);
max_pages = xen_get_max_pages();
......@@ -811,15 +809,15 @@ char * __init xen_memory_setup(void)
extra_pages = min3(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)),
extra_pages, max_pages - max_pfn);
i = 0;
addr = xen_e820_map[0].addr;
size = xen_e820_map[0].size;
while (i < xen_e820_map_entries) {
addr = xen_e820_table.entries[0].addr;
size = xen_e820_table.entries[0].size;
while (i < xen_e820_table.nr_entries) {
bool discard = false;
chunk_size = size;
type = xen_e820_map[i].type;
type = xen_e820_table.entries[i].type;
if (type == E820_RAM) {
if (type == E820_TYPE_RAM) {
if (addr < mem_end) {
chunk_size = min(size, mem_end - addr);
} else if (extra_pages) {
......@@ -840,9 +838,9 @@ char * __init xen_memory_setup(void)
size -= chunk_size;
if (size == 0) {
i++;
if (i < xen_e820_map_entries) {
addr = xen_e820_map[i].addr;
size = xen_e820_map[i].size;
if (i < xen_e820_table.nr_entries) {
addr = xen_e820_table.entries[i].addr;
size = xen_e820_table.entries[i].size;
}
}
}
......@@ -858,10 +856,9 @@ char * __init xen_memory_setup(void)
* reserve ISA memory anyway because too many things poke
* about in there.
*/
e820_add_region(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS,
E820_RESERVED);
e820__range_add(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS, E820_TYPE_RESERVED);
sanitize_e820_map(e820->map, ARRAY_SIZE(e820->map), &e820->nr_map);
e820__update_table(e820_table);
/*
* Check whether the kernel itself conflicts with the target E820 map.
......@@ -914,6 +911,37 @@ char * __init xen_memory_setup(void)
return "Xen";
}
/*
* Machine specific memory setup for auto-translated guests.
*/
char * __init xen_auto_xlated_memory_setup(void)
{
struct xen_memory_map memmap;
int i;
int rc;
memmap.nr_entries = ARRAY_SIZE(xen_e820_table.entries);
set_xen_guest_handle(memmap.buffer, xen_e820_table.entries);
rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
if (rc < 0)
panic("No memory map (%d)\n", rc);
xen_e820_table.nr_entries = memmap.nr_entries;
e820__update_table(&xen_e820_table);
for (i = 0; i < xen_e820_table.nr_entries; i++)
e820__range_add(xen_e820_table.entries[i].addr, xen_e820_table.entries[i].size, xen_e820_table.entries[i].type);
/* Remove p2m info, it is not needed. */
xen_start_info->mfn_list = 0;
xen_start_info->first_p2m_pfn = 0;
xen_start_info->nr_p2m_frames = 0;
return "Xen";
}
/*
* Set the bit indicating "nosegneg" library variants should be used.
* We only need to bother in pure 32-bit mode; compat 32-bit processes
......@@ -999,8 +1027,8 @@ void __init xen_pvmmu_arch_setup(void)
void __init xen_arch_setup(void)
{
xen_panic_handler_init();
xen_pvmmu_arch_setup();
if (!xen_feature(XENFEAT_auto_translated_physmap))
xen_pvmmu_arch_setup();
#ifdef CONFIG_ACPI
if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
......
......@@ -556,7 +556,7 @@ void __init acpi_table_upgrade(void)
* But it's not enough on X86 because ioremap will
* complain later (used by acpi_os_map_memory) that the pages
* that should get mapped are not marked "reserved".
* Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
* Both memblock_reserve and e820__range_add (via arch_reserve_mem_area)
* works fine.
*/
memblock_reserve(acpi_tables_addr, all_tables_size);
......
......@@ -14,7 +14,7 @@
#include <linux/agp_backend.h>
#include <linux/mmzone.h>
#include <asm/page.h> /* PAGE_SIZE */
#include <asm/e820.h>
#include <asm/e820/api.h>
#include <asm/amd_nb.h>
#include <asm/gart.h>
#include "agp.h"
......
......@@ -38,7 +38,7 @@ struct xen_memory_region {
unsigned long n_pfns;
};
#define XEN_EXTRA_MEM_MAX_REGIONS 128 /* == E820MAX */
#define XEN_EXTRA_MEM_MAX_REGIONS 128 /* == E820_MAX_ENTRIES_ZEROPAGE */
extern __initdata
struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS];
......
......@@ -3339,7 +3339,7 @@ int main(int argc, char *argv[])
* simple, single region.
*/
boot->e820_entries = 1;
boot->e820_map[0] = ((struct e820entry) { 0, mem, E820_RAM });
boot->e820_table[0] = ((struct e820_entry) { 0, mem, E820_TYPE_RAM });
/*
* The boot header contains a command line pointer: we put the command
* line after the boot header.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment