Re: [RFC][PATCH 3/7] i386 code for the physmem map

From: Hariprasad Nellitheertha
Date: Thu Mar 24 2005 - 01:01:42 EST


Regards, Hari
---

This patch contains the i386 specific code to generate the
/proc/physmem view.

Signed-off-by: Hariprasad Nellitheertha <hari@xxxxxxxxxx>
---

linux-2.6.12-rc1-hari/arch/i386/kernel/efi.c | 134 +++++++++++++++----------
linux-2.6.12-rc1-hari/arch/i386/kernel/setup.c | 82 +++++++++++++--
linux-2.6.12-rc1-hari/include/linux/efi.h | 2
linux-2.6.12-rc1-hari/include/linux/ioport.h | 1
4 files changed, 156 insertions(+), 63 deletions(-)

diff -puN arch/i386/kernel/efi.c~physmem-i386 arch/i386/kernel/efi.c
--- linux-2.6.12-rc1/arch/i386/kernel/efi.c~physmem-i386 2005-03-23 17:48:06.000000000 +0530
+++ linux-2.6.12-rc1-hari/arch/i386/kernel/efi.c 2005-03-23 17:48:06.000000000 +0530
@@ -49,6 +49,7 @@ struct efi efi;
EXPORT_SYMBOL(efi);
static struct efi efi_phys __initdata;
struct efi_memory_map memmap __initdata;
+struct efi_memory_map memmapcopy __initdata;

/*
* We require an early boot_ioremap mapping mechanism initially
@@ -527,6 +528,67 @@ void __init efi_enter_virtual_mode(void)
efi.systab->runtime->reset_system;
}

+static struct resource * __init alloc_efi_resource(efi_memory_desc_t *md,
+ struct resource *resource,
+ int i)
+{
+ struct resource *res;
+
+ res = alloc_bootmem_low(sizeof(struct resource));
+ switch (md->type) {
+ case EFI_RESERVED_TYPE:
+ res->name = "Reserved Memory";
+ break;
+ case EFI_LOADER_CODE:
+ res->name = "Loader Code";
+ break;
+ case EFI_LOADER_DATA:
+ res->name = "Loader Data";
+ break;
+ case EFI_BOOT_SERVICES_DATA:
+ res->name = "BootServices Data";
+ break;
+ case EFI_BOOT_SERVICES_CODE:
+ res->name = "BootServices Code";
+ break;
+ case EFI_RUNTIME_SERVICES_CODE:
+ res->name = "Runtime Service Code";
+ break;
+ case EFI_RUNTIME_SERVICES_DATA:
+ res->name = "Runtime Service Data";
+ break;
+ case EFI_CONVENTIONAL_MEMORY:
+ res->name = "Conventional Memory";
+ break;
+ case EFI_UNUSABLE_MEMORY:
+ res->name = "Unusable Memory";
+ break;
+ case EFI_ACPI_RECLAIM_MEMORY:
+ res->name = "ACPI Reclaim";
+ break;
+ case EFI_ACPI_MEMORY_NVS:
+ res->name = "ACPI NVS";
+ break;
+ case EFI_MEMORY_MAPPED_IO:
+ res->name = "Memory Mapped IO";
+ break;
+ case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
+ res->name = "Memory Mapped IO Port Space";
+ break;
+ default:
+ res->name = "Reserved";
+ break;
+ }
+
+ res->start = md->phys_addr;
+ res->end = res->start + ((md->num_pages << EFI_PAGE_SHIFT) - 1);
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ if (request_resource(resource, res) < 0)
+ printk(KERN_ERR PFX "Failed to allocate res %s : 0x%llx-0x%llx\n",
+ res->name, res->start, res->end);
+ return res;
+}
+
void __init
efi_initialize_iomem_resources(struct resource *code_resource,
struct resource *data_resource)
@@ -541,57 +603,7 @@ efi_initialize_iomem_resources(struct re
if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >
0x100000000ULL)
continue;
- res = alloc_bootmem_low(sizeof(struct resource));
- switch (md->type) {
- case EFI_RESERVED_TYPE:
- res->name = "Reserved Memory";
- break;
- case EFI_LOADER_CODE:
- res->name = "Loader Code";
- break;
- case EFI_LOADER_DATA:
- res->name = "Loader Data";
- break;
- case EFI_BOOT_SERVICES_DATA:
- res->name = "BootServices Data";
- break;
- case EFI_BOOT_SERVICES_CODE:
- res->name = "BootServices Code";
- break;
- case EFI_RUNTIME_SERVICES_CODE:
- res->name = "Runtime Service Code";
- break;
- case EFI_RUNTIME_SERVICES_DATA:
- res->name = "Runtime Service Data";
- break;
- case EFI_CONVENTIONAL_MEMORY:
- res->name = "Conventional Memory";
- break;
- case EFI_UNUSABLE_MEMORY:
- res->name = "Unusable Memory";
- break;
- case EFI_ACPI_RECLAIM_MEMORY:
- res->name = "ACPI Reclaim";
- break;
- case EFI_ACPI_MEMORY_NVS:
- res->name = "ACPI NVS";
- break;
- case EFI_MEMORY_MAPPED_IO:
- res->name = "Memory Mapped IO";
- break;
- case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
- res->name = "Memory Mapped IO Port Space";
- break;
- default:
- res->name = "Reserved";
- break;
- }
- res->start = md->phys_addr;
- res->end = res->start + ((md->num_pages << EFI_PAGE_SHIFT) - 1);
- res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
- if (request_resource(&iomem_resource, res) < 0)
- printk(KERN_ERR PFX "Failed to allocate res %s : 0x%llx-0x%llx\n",
- res->name, res->start, res->end);
+ res = alloc_efi_resource(md, &iomem_resource, i);
/*
* We don't know which region contains kernel data so we try
* it repeatedly and let the resource manager test it.
@@ -606,6 +618,26 @@ efi_initialize_iomem_resources(struct re
}
}

+void __init efi_initialize_physmem_resources(void)
+{
+ struct resource *res;
+ efi_memory_desc_t *md;
+ int i;
+
+ for (i = 0; i < memmapcopy.nr_map; i++) {
+ md = &memmapcopy.map[i];
+ res = alloc_efi_resource(md, &physmem_resource, i);
+ }
+}
+
+/*
+ * Make a copy of memmap for creating the physmem resources later.
+ */
+void __init preserve_memmap(void)
+{
+ memcpy(&memmapcopy, &memmap, sizeof(memmap));
+}
+
/*
* Convenience functions to obtain memory types and attributes
*/
diff -puN arch/i386/kernel/setup.c~physmem-i386 arch/i386/kernel/setup.c
--- linux-2.6.12-rc1/arch/i386/kernel/setup.c~physmem-i386 2005-03-23 17:48:06.000000000 +0530
+++ linux-2.6.12-rc1-hari/arch/i386/kernel/setup.c 2005-03-23 17:48:06.000000000 +0530
@@ -121,6 +121,7 @@ struct sys_desc_table_struct {
struct edid_info edid_info;
struct ist_info ist_info;
struct e820map e820;
+struct e820map __initdata e820copy;

extern void early_cpu_init(void);
extern void dmi_scan_machine(void);
@@ -639,6 +640,14 @@ static int __init copy_e820_map(struct e
return 0;
}

+/* Copy e820 into e820copy. We later use the e820copy to create
+ * the physmem resources.
+ */
+static void __init preserve_e820_map(void)
+{
+ memcpy(&e820copy, &e820, sizeof(e820));
+}
+
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
struct edd edd;
#ifdef CONFIG_EDD_MODULE
@@ -662,6 +671,17 @@ static inline void copy_edd(void)
}
#endif

+/* Make a copy of the e820 or memmap data structure.
+ * We use this copy to setup the physmem resources later.
+ */
+static void __init copy_physmem_map(void)
+{
+ if (efi_enabled)
+ preserve_memmap();
+ else
+ preserve_e820_map();
+}
+
/*
* Do NOT EVER look at the BIOS memory size location.
* It does not work on many machines.
@@ -1218,6 +1238,27 @@ void __init remapped_pgdat_init(void)
}

/*
+ * Common routine to alloc and initialize an e820 type ROM or RAM resource.
+ */
+static struct resource * __init alloc_e820_resource(struct e820map *emap, struct resource *resource, int i)
+{
+ struct resource *res;
+
+ res = alloc_bootmem_low(sizeof(struct resource));
+ switch (emap->map[i].type) {
+ case E820_RAM: res->name = "System RAM"; break;
+ case E820_ACPI: res->name = "ACPI Tables"; break;
+ case E820_NVS: res->name = "ACPI Non-volatile Storage"; break;
+ default: res->name = "reserved";
+ }
+ res->start = emap->map[i].addr;
+ res->end = res->start + emap->map[i].size - 1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ request_resource(resource, res);
+ return res;
+}
+
+/*
* Request address space for all standard RAM and ROM resources
* and also for regions reported as reserved by the e820.
*/
@@ -1225,23 +1266,13 @@ static void __init
legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource)
{
int i;
+ struct resource *res;

probe_roms();
for (i = 0; i < e820.nr_map; i++) {
- struct resource *res;
if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
continue;
- res = alloc_bootmem_low(sizeof(struct resource));
- switch (e820.map[i].type) {
- case E820_RAM: res->name = "System RAM"; break;
- case E820_ACPI: res->name = "ACPI Tables"; break;
- case E820_NVS: res->name = "ACPI Non-volatile Storage"; break;
- default: res->name = "reserved";
- }
- res->start = e820.map[i].addr;
- res->end = res->start + e820.map[i].size - 1;
- res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
- request_resource(&iomem_resource, res);
+ res = alloc_e820_resource(&e820, &iomem_resource, i);
if (e820.map[i].type == E820_RAM) {
/*
* We don't know which RAM region contains kernel data,
@@ -1258,6 +1289,20 @@ legacy_init_iomem_resources(struct resou
}

/*
+ * Request address space for standard ROM and RAM resources. This will contain
+ * the entire e820 map even if the original map has been modified due to mem=
+ * or memmap=exactmap command line parameters
+ */
+static void __init legacy_init_physmem_resources(void)
+{
+ int i;
+ struct resource *res;
+
+ for (i = 0; i < e820copy.nr_map; i++)
+ res = alloc_e820_resource(&e820copy, &physmem_resource, i);
+}
+
+/*
* Request address space for all standard resources
*/
static void __init register_memory(void)
@@ -1438,6 +1483,15 @@ static void set_mca_bus(int x)
static void set_mca_bus(int x) { }
#endif

+static void __init register_physmem_resources(void)
+{
+ if (efi_enabled)
+ efi_initialize_physmem_resources();
+ else
+ legacy_init_physmem_resources();
+}
+
+
/*
* Determine if we were loaded by an EFI loader. If so, then we have also been
* passed the efi memmap, systab, etc., so we should use these data structures
@@ -1495,6 +1549,8 @@ void __init setup_arch(char **cmdline_p)

copy_edd();

+ copy_physmem_map();
+
if (!MOUNT_ROOT_RDONLY)
root_mountflags &= ~MS_RDONLY;
init_mm.start_code = (unsigned long) _text;
@@ -1532,6 +1588,8 @@ void __init setup_arch(char **cmdline_p)
* NOTE: at this point the bootmem allocator is fully available.
*/

+ register_physmem_resources();
+
#ifdef CONFIG_EARLY_PRINTK
{
char *s = strstr(*cmdline_p, "earlyprintk=");
diff -puN include/linux/efi.h~physmem-i386 include/linux/efi.h
--- linux-2.6.12-rc1/include/linux/efi.h~physmem-i386 2005-03-23 17:48:06.000000000 +0530
+++ linux-2.6.12-rc1-hari/include/linux/efi.h 2005-03-23 17:48:06.000000000 +0530
@@ -301,6 +301,8 @@ extern u64 efi_mem_attributes (unsigned
extern int __init efi_uart_console_only (void);
extern void efi_initialize_iomem_resources(struct resource *code_resource,
struct resource *data_resource);
+extern void efi_initialize_physmem_resources(void);
+extern void preserve_memmap(void);
extern unsigned long __init efi_get_time(void);
extern int __init efi_set_rtc_mmss(unsigned long nowtime);
extern struct efi_memory_map memmap;
diff -puN include/linux/ioport.h~physmem-i386 include/linux/ioport.h
--- linux-2.6.12-rc1/include/linux/ioport.h~physmem-i386 2005-03-23 17:48:06.000000000 +0530
+++ linux-2.6.12-rc1-hari/include/linux/ioport.h 2005-03-23 17:48:06.000000000 +0530
@@ -91,6 +91,7 @@ struct resource_list {
/* PC/ISA/whatever - the normal PC address spaces: IO and memory */
extern struct resource ioport_resource;
extern struct resource iomem_resource;
+extern struct resource physmem_resource;

extern int request_resource(struct resource *root, struct resource *new);
extern struct resource * ____request_resource(struct resource *root, struct resource *new);
_