Google Groups Home
Help | Sign in
Message from discussion /proc/cpumem
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
Itsuro Oda  
View profile
 More options Feb 16 2005, 4:00 am
Newsgroups: linux.kernel
From: Itsuro Oda <o...@valinux.co.jp>
Date: Wed, 16 Feb 2005 10:00:20 +0100
Local: Wed, Feb 16 2005 4:00 am
Subject: [PATCH] /proc/cpumem
Hi, Eric and all

Attached is an implementation of /proc/cpumem.
/proc/cpumem shows the valid physical memory ranges.

* i386 and x86_64
* implement valid_phys_addr_range() and use it.
  (the first argument of the i386 version is little uncomfortable.)
* /dev/mem of the i386 version should be mofified. but not yet.

example: amd64 8GB Mem
# cat /proc/cpumem
0000000000000000 000000000009b800
0000000000100000 00000000fbe70000
0000000100000000 0000000100000000
#
start address and size. hex digit.

Any comments, recomendations and suggestions are welcom.

BTW, does not kexec/kdump run on 2.6.11-rc3-mm2 ?
How do I get and examine the latest kexec/kdump ?

Thanks.
--
Itsuro ODA <o...@valinux.co.jp>

---
--- linux-2.6.11-rc3-mm2/drivers/char/mem.c     2005-02-16 15:36:31.000000000 +0900
+++ linux-2.6.11-rc3-mm2-test/drivers/char/mem.c        2005-02-16 23:32:15.244876816 +0900
@@ -25,6 +25,9 @@
 #include <linux/device.h>
 #include <linux/highmem.h>
 #include <linux/crash_dump.h>
+#include <linux/bootmem.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>

 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -759,3 +762,125 @@
 }

 fs_initcall(chr_dev_init);
+
+#ifdef CONFIG_PROC_FS
+/*
+ *  /proc/cpumem: show valid physical address range
+ */
+struct cpumem_info {
+       unsigned long long addr;
+       unsigned long long size;
+};
+
+static void *cpumem_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       struct cpumem_info *p = m->private;
+       unsigned long long end = (unsigned long long)max_pfn << PAGE_SHIFT;
+       unsigned long long addr;
+       size_t size;
+       int found = 0;
+
+       (*pos)++;
+
+       if (p->addr >= end) {
+               return NULL;
+       }
+
+       /* always start page boundary */
+       addr = ((p->addr + p->size + PAGE_SIZE - 1) >> PAGE_SHIFT) << PAGE_SHIFT;
+       size = 0xf0000000;
+
+       while (addr < end) {
+               if (valid_phys_addr_range(addr, &size)) {
+                       if (!found) {
+                               found = 1;
+                               p->addr = addr;
+                               p->size = size;
+                       } else {
+                               p->size += size;
+                       }
+                       addr += size;
+                       size = 0xf0000000;
+               } else {
+                       if (found) {
+                               return p;
+                       }
+                       addr += PAGE_SIZE;
+               }
+       }
+
+       return found ? p : NULL;
+}
+
+static void *cpumem_start(struct seq_file *m, loff_t *pos)
+{
+       struct cpumem_info *p = m->private;
+       loff_t n = 0;
+
+       p->addr = 0;
+       p->size = 0;
+
+       while (n <= *pos) {
+               if (!cpumem_next(m, NULL, &n)) {
+                       return NULL;
+               }
+       }
+
+       return p;
+}
+
+static void cpumem_stop(struct seq_file *m, void *v)
+{
+}
+
+static int cpumem_show(struct seq_file *m, void *v)
+{
+       struct cpumem_info *p = m->private;
+       unsigned long long end = (unsigned long long)max_pfn << PAGE_SHIFT;
+
+       if (p->addr < end) {
+               seq_printf(m, "%016llx %016llx\n", p->addr, p->size);
+       }
+       return 0;
+}
+
+struct seq_operations cpumem_op = {
+       .start  = cpumem_start,
+       .next   = cpumem_next,
+       .stop   = cpumem_stop,
+       .show   = cpumem_show
+};
+
+static int cpumem_open(struct inode *inode, struct file *file)
+{
+       int res = seq_open(file, &cpumem_op);
+       if (!res) {
+               struct seq_file *m = file->private_data;
+               m->private = kmalloc(sizeof(struct cpumem_info), GFP_KERNEL);
+               if (!m->private) {
+                       seq_release(inode, file);
+                       return -ENOMEM;
+               }
+       }
+       return res;
+}
+
+static struct file_operations proc_cpumem_operations = {
+       .open           = cpumem_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release_private
+};
+
+static int __init cpumem_init(void)
+{
+       struct proc_dir_entry *entry;
+
+       entry = create_proc_entry("cpumem", 0, NULL);
+       if (entry) {
+               entry->proc_fops = &proc_cpumem_operations;
+       }
+       return 0;
+}
+__initcall(cpumem_init);
+#endif /* CONFIG_PROC_FS */

---
--- linux-2.6.11-rc3-mm2/arch/i386/mm/init.c    2005-02-16 15:36:29.000000000 +0900
+++ linux-2.6.11-rc3-mm2-test/arch/i386/mm/init.c       2005-02-16 23:32:29.499709752 +0900
@@ -248,6 +248,47 @@
        return 0;
 }

+int valid_phys_addr_range(unsigned long long phys_addr, size_t *size)
+{
+       int i;
+       unsigned long long addr, end;
+       efi_memory_desc_t *md;
+
+       if (efi_enabled) {
+               for (i = 0; i < memmap.nr_map; i++) {
+                       md = &memmap.map[i];
+                       if (!is_available_memory(md)) {
+                               continue;
+                       }
+                       addr = md->phys_addr;
+                       end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+                       if ((phys_addr >= addr) && (phys_addr < end)) {
+                               if (*size > end - phys_addr) {
+                                       *size = end - phys_addr;
+                               }
+                               return 1;
+                       }
+               }
+               return 0;
+       }
+
+       for (i = 0; i < e820.nr_map; i++) {
+               if (e820.map[i].type != E820_RAM) {
+                       continue;
+               }
+               addr = e820.map[i].addr;
+               end = e820.map[i].addr + e820.map[i].size;
+               if ((phys_addr >= addr) && (phys_addr < end)) {
+                       if (*size > end - phys_addr) {
+                               *size = end - phys_addr;
+                       }
+                       return 1;
+               }
+       }
+       return 0;
+}
+EXPORT_SYMBOL(valid_phys_addr_range);
+
 #ifdef CONFIG_HIGHMEM
 pte_t *kmap_pte;
 pgprot_t kmap_prot;

---
--- linux-2.6.11-rc3-mm2/include/asm-i386/io.h  2004-12-25 06:35:40.000000000 +0900
+++ linux-2.6.11-rc3-mm2-test/include/asm-i386/io.h     2005-02-16 23:36:24.454991120 +0900
@@ -90,6 +90,12 @@
  */
 #define page_to_phys(page)    ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)

+/*
+ * for /dev/mem
+ */
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(unsigned long long, size_t *);
+
 extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);

 /**

---
--- linux-2.6.11-rc3-mm2/arch/x86_64/mm/init.c  2005-02-16 15:36:30.000000000 +0900
+++ linux-2.6.11-rc3-mm2-test/arch/x86_64/mm/init.c     2005-02-16 16:23:08.000000000 +0900
@@ -22,6 +22,7 @@
 #include <linux/pagemap.h>
 #include <linux/bootmem.h>
 #include <linux/proc_fs.h>
+#include <linux/module.h>

 #include <asm/processor.h>
 #include <asm/system.h>
@@ -395,6 +396,27 @@
        return 0;
 }

+int valid_phys_addr_range(unsigned long phys_addr, size_t *size)
+{
+       int i;
+       unsigned long end;
+
+       for (i = 0; i < e820.nr_map; i++) {
+               if (e820.map[i].type != E820_RAM) {
+                       continue;
+               }
+               end = e820.map[i].addr + e820.map[i].size;
+               if (phys_addr >= e820.map[i].addr && phys_addr < end) {
+                       if (*size > end - phys_addr) {
+                               *size = end - phys_addr;
+                       }
+                       return 1;
+               }
+       }
+       return 0;
+}
+EXPORT_SYMBOL(valid_phys_addr_range);
+
 extern int swiotlb_force;

 /*

---
--- linux-2.6.11-rc3-mm2/include/asm-x86_64/io.h        2005-02-16 15:36:12.000000000 +0900
+++ linux-2.6.11-rc3-mm2-test/include/asm-x86_64/io.h   2005-02-16 16:23:59.000000000 +0900
@@ -123,6 +123,9 @@
 {
        return __va(address);
 }
+
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(unsigned long, size_t *);
 #endif

 /*

---

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2008 Google