Skip to contentSkip to conversation

FLATMEM: allow memory to start at pfn != 0 [take #2]

PATCH In review Franck Bui-Huu 5 participants 22 messages Jan 10, 2007 – Mar 18, 2007 MIPS

lore
Share & tools
lore
#0 lore raw

cover FLATMEM: allow memory to start at pfn != 0 [take #2]

Ralf,

Here's is the second attempt to make this works on your Malta board and all other boards that have some data reserved at the start of their memories. In these cases the first patchset assumed wrongly that the start of the memory was after this reserved area.

Patch 1/2 should work alone now. the kernel should report that your mem config is wasting some memory for tracking reserved pages located at the start of the mem.

Thanks for testing

Franck

---

 arch/mips/kernel/setup.c |   40 +++++++++++++++++++++++++++++++---------
 arch/mips/mm/init.c      |   23 +++++++++++------------
 include/asm-mips/dma.h   |    1 +
 include/asm-mips/io.h    |    4 ++--
 include/asm-mips/page.h  |   25 +++++++++++++++++++++----
 5 files changed, 66 insertions(+), 27 deletions(-)
#1 lore raw

PATCH 1/2 Setup min_low_pfn/max_low_pfn correctly

From: Franck Bui-Huu <[email protected]>

This patch makes a better usage of these two globals. 'min_low_pfn' is now correctly setup for all configs, which allow us to rely on it in boot memory code init.

---
 arch/mips/kernel/setup.c |   36 +++++++++++++++++++++++++++---------
 arch/mips/mm/init.c      |   23 +++++++++++------------
 include/asm-mips/dma.h   |    1 +
 3 files changed, 39 insertions(+), 21 deletions(-)
arch/mips/kernel/setup.c +27 -9
index 89440a0..f352cd9 100644
@@ -271,8 +271,7 @@ static void __init bootmem_init(void)
 static void __init bootmem_init(void)
 {
 	unsigned long reserved_end;
-	unsigned long highest = 0;
-	unsigned long mapstart = -1UL;
+	unsigned long mapstart = ~0UL;
 	unsigned long bootmap_size;
 	int i;
 
@@ -284,6 +283,13 @@ static void __init bootmem_init(void)
 	reserved_end = max(init_initrd(), PFN_UP(__pa_symbol(&_end)));
 
 	/*
+	 * max_low_pfn is not a number of pages. The number of pages
+	 * of the system is given by 'max_low_pfn - min_low_pfn'.
+	 */
+	min_low_pfn = ~0UL;
+	max_low_pfn = 0;
+
+	/*
 	 * Find the highest page frame number we have available.
 	 */
 	for (i = 0; i < boot_mem_map.nr_map; i++) {
@@ -296,8 +302,10 @@ static void __init bootmem_init(void)
 		end = PFN_DOWN(boot_mem_map.map[i].addr
 				+ boot_mem_map.map[i].size);
 
-		if (end > highest)
-			highest = end;
+		if (end > max_low_pfn)
+			max_low_pfn = end;
+		if (start < min_low_pfn)
+			min_low_pfn = start;
 		if (end <= reserved_end)
 			continue;
 		if (start >= mapstart)
@@ -305,22 +313,32 @@ static void __init bootmem_init(void)
 		mapstart = max(reserved_end, start);
 	}
 
+	if (min_low_pfn >= max_low_pfn)
+		panic("Incorrect memory mapping !!!");
+	if (min_low_pfn > 0) {
+		printk(KERN_INFO
+		       "Wasting %lu bytes for tracking %lu unused pages\n",
+		       min_low_pfn * sizeof(struct page),
+		       min_low_pfn);
+		min_low_pfn = 0;
+	}
+
 	/*
 	 * Determine low and high memory ranges
 	 */
-	if (highest > PFN_DOWN(HIGHMEM_START)) {
+	if (max_low_pfn > PFN_DOWN(HIGHMEM_START)) {
 #ifdef CONFIG_HIGHMEM
 		highstart_pfn = PFN_DOWN(HIGHMEM_START);
-		highend_pfn = highest;
+		highend_pfn = max_low_pfn;
 #endif
-		highest = PFN_DOWN(HIGHMEM_START);
+		max_low_pfn = PFN_DOWN(HIGHMEM_START);
 	}
 
 	/*
 	 * Initialize the boot-time allocator with low memory only.
 	 */
-	bootmap_size = init_bootmem(mapstart, highest);
-
+	bootmap_size = init_bootmem_node(NODE_DATA(0), mapstart,
+					 min_low_pfn, max_low_pfn);
 	/*
 	 * Register fully available low RAM pages with the bootmem allocator.
 	 */
arch/mips/mm/init.c +11 -12
index 30245c0..cd50b7a 100644
@@ -341,7 +341,6 @@ static int __init page_is_ram(unsigned long pagenr)
 void __init paging_init(void)
 {
 	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
-	unsigned long max_dma, low;
 #ifndef CONFIG_FLATMEM
 	unsigned long zholes_size[MAX_NR_ZONES] = { 0, };
 	unsigned long i, j, pfn;
@@ -354,19 +353,19 @@ void __init paging_init(void)
 #endif
 	kmap_coherent_init();
 
-	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-	low = max_low_pfn;
-
 #ifdef CONFIG_ISA
-	if (low < max_dma)
-		zones_size[ZONE_DMA] = low;
-	else {
-		zones_size[ZONE_DMA] = max_dma;
-		zones_size[ZONE_NORMAL] = low - max_dma;
-	}
-#else
-	zones_size[ZONE_DMA] = low;
+	if (max_low_pfn >= MAX_DMA_PFN)
+		if (min_low_pfn >= MAX_DMA_PFN) {
+			zones_size[ZONE_DMA] = 0;
+			zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn;
+		} else {
+			zones_size[ZONE_DMA] = MAX_DMA_PFN - min_low_pfn;
+			zones_size[ZONE_NORMAL] = max_low_pfn - MAX_DMA_PFN;
+		}
+	else
 #endif
+	zones_size[ZONE_DMA] = max_low_pfn - min_low_pfn;
+
 #ifdef CONFIG_HIGHMEM
 	zones_size[ZONE_HIGHMEM] = highend_pfn - highstart_pfn;
 
include/asm-mips/dma.h +1 -0
index 23f789c..e06ef07 100644
@@ -91,6 +91,7 @@
 #else
 #define MAX_DMA_ADDRESS		(PAGE_OFFSET + 0x01000000)
 #endif
+#define MAX_DMA_PFN		PFN_DOWN(virt_to_phys((void *)MAX_DMA_ADDRESS))
 
 /* 8237 DMA controllers */
 #define IO_DMA1_BASE	0x00	/* 8 bit slave DMA, channels 0..3 */
Signature · 1 line
1.4.4.3.ge6d4
#2 lore raw
In reply to Franck Bui-Huu
Quoted 8 lines · Franck Bui-Huu

Here's is the second attempt to make this works on your Malta board and all other boards that have some data reserved at the start of their memories. In these cases the first patchset assumed wrongly that the start of the memory was after this reserved area.

Patch 1/2 should work alone now. the kernel should report that your mem config is wasting some memory for tracking reserved pages located at the start of the mem.

So this series now works for me, both 1/2 along and 1/2 + 2/2 applied. So I'll drop this into the 2.6.21 queue.

Ralf

#3 lore raw
Quoted 3 lines · Ralf Baechle

So this series now works for me, both 1/2 along and 1/2 + 2/2 applied. So I'll drop this into the 2.6.21 queue.

Great !

What did the console say when 1/2 was applied alone ?

Did you try to set PHYS_OFFSET to something different from 0 when 1/2, 2/2 are applied ? If so, does mem_map[] size decrease ?

Thanks for your time.

Signature · 1 line
              Franck
#4 lore raw

PATCH 2/2 FLATMEM: introduce PHYS_OFFSET.

In reply to Franck Bui-Huu

From: Franck Bui-Huu <[email protected]>

The old code was assuming that min_low_pfn was always 0. This means that platforms having a big hole at their memory start paid the price of wasting some memory for the allocation of unused entries in mem_map[].

This patch prevents this waste.

It introduces PHYS_OFFSET define which is the start of the physical memory and uses it wherever needed. Specially when converting physical/virtual addresses into virtual/physical ones.

Currently all platforms defines PHYS_OFFSET to 0.

Conflicts:

arch/mips/kernel/setup.c

---
 arch/mips/kernel/setup.c |   12 ++++++++----
 include/asm-mips/io.h    |    4 ++--
 include/asm-mips/page.h  |   25 +++++++++++++++++++++----
 3 files changed, 31 insertions(+), 10 deletions(-)
arch/mips/kernel/setup.c +8 -4
index f352cd9..e1d76b8 100644
@@ -315,13 +315,17 @@ static void __init bootmem_init(void)
 
 	if (min_low_pfn >= max_low_pfn)
 		panic("Incorrect memory mapping !!!");
-	if (min_low_pfn > 0) {
+	if (min_low_pfn > ARCH_PFN_OFFSET) {
 		printk(KERN_INFO
 		       "Wasting %lu bytes for tracking %lu unused pages\n",
-		       min_low_pfn * sizeof(struct page),
-		       min_low_pfn);
-		min_low_pfn = 0;
+		       (min_low_pfn - ARCH_PFN_OFFSET) * sizeof(struct page),
+		       min_low_pfn - ARCH_PFN_OFFSET);
+	} else if (min_low_pfn < ARCH_PFN_OFFSET) {
+		printk(KERN_INFO
+		       "%lu free pages won't be used\n",
+		       ARCH_PFN_OFFSET - min_low_pfn);
 	}
+	min_low_pfn = ARCH_PFN_OFFSET;
 
 	/*
 	 * Determine low and high memory ranges
include/asm-mips/io.h +2 -2
index 38d1399..e1592af 100644
@@ -115,7 +115,7 @@ static inline void set_io_port_base(unsigned long base)
  */
 static inline unsigned long virt_to_phys(volatile const void *address)
 {
-	return (unsigned long)address - PAGE_OFFSET;
+	return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET;
 }
 
 /*
@@ -132,7 +132,7 @@ static inline unsigned long virt_to_phys(volatile const void *address)
  */
 static inline void * phys_to_virt(unsigned long address)
 {
-	return (void *)(address + PAGE_OFFSET);
+	return (void *)(address + PAGE_OFFSET - PHYS_OFFSET);
 }
 
 /*
include/asm-mips/page.h +21 -4
index 2f9e1a9..d3fbd83 100644
@@ -34,6 +34,20 @@
 
 #ifndef __ASSEMBLY__
 
+/*
+ * This gives the physical RAM offset.
+ */
+#ifndef PHYS_OFFSET
+#define PHYS_OFFSET		0UL
+#endif
+
+/*
+ * It's normally defined only for FLATMEM config but it's
+ * used in our early mem init code for all memory models.
+ * So always define it.
+ */
+#define ARCH_PFN_OFFSET		PFN_UP(PHYS_OFFSET)
+
 #include <linux/pfn.h>
 #include <asm/io.h>
 
@@ -132,20 +146,23 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)	(((addr) + PAGE_SIZE - 1) & PAGE_MASK)
 
+/*
+ * __pa()/__va() should be used only during mem init.
+ */
 #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
 #define __pa_page_offset(x)	((unsigned long)(x) < CKSEG0 ? PAGE_OFFSET : CKSEG0)
 #else
 #define __pa_page_offset(x)	PAGE_OFFSET
 #endif
-#define __pa(x)			((unsigned long)(x) - __pa_page_offset(x))
-#define __pa_symbol(x)		__pa(RELOC_HIDE((unsigned long)(x),0))
-#define __va(x)			((void *)((unsigned long)(x) + PAGE_OFFSET))
+#define __pa(x)		((unsigned long)(x) - __pa_page_offset(x) + PHYS_OFFSET)
+#define __va(x)		((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
+#define __pa_symbol(x)	__pa(RELOC_HIDE((unsigned long)(x),0))
 
 #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 
 #ifdef CONFIG_FLATMEM
 
-#define pfn_valid(pfn)		((pfn) < max_mapnr)
+#define pfn_valid(pfn)		((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr)
 
 #elif defined(CONFIG_SPARSEMEM)
 
Signature · 1 line
1.4.4.3.ge6d4
#5 lore raw
In reply to Franck Bui-Huu

On Wed, 2007-01-10 at 09:44 +0100, Franck Bui-Huu wrote:

Hi Franck,

Quoted 3 lines

Here's is the second attempt to make this works on your Malta board and all other boards that have some data reserved at the start of their memories. In these cases the first patchset assumed wrongly that

I was happy to try this patch on my 4Kec board with memory starting at 0x10000000 but it doesn't work.

Setting PHYS_OFFSET to 0, I get the expected "Wasting 2098176 bytes for tracking 65568 unused pages" and everything works as usual.

Setting PHYS_OFFSET to 0x10000000, I get "Wasting 1024 bytes for tracking 32 unused pages", but the kernel doesn't boot and crash in init_bootmem_node().

Looking at phys_to_virt(), it looks like I also need to change PAGE_OFFSET to 0x90000000 to get correct values. This makes the kernel boot with a correct memory map, but userspace doesn't work anymore.

Just in case, I'm not using git head, but a 2.6.20 kernel with the 2 patches applied. Just tell me if you need complete dmesg.

Regards,

Signature · 1 line
Maxime
#6 lore raw

Hi,

Quoted 3 lines · Maxime Bizon

Looking at phys_to_virt(), it looks like I also need to change PAGE_OFFSET to 0x90000000 to get correct values. This makes the kernel boot with a correct memory map, but userspace doesn't work anymore.

No phys_to_virt() should already take care of that:

static inline void * phys_to_virt(unsigned long address)

{
       return (void *)(address + PAGE_OFFSET - PHYS_OFFSET);
}

Does your platform code do some address translation by using CPHYSADDR() macro or by using anything else than pa() ?

Quoted 2 lines

Just in case, I'm not using git head, but a 2.6.20 kernel with the 2

2.6.20 should be OK. This patchset need some commits which have been applied before.

Quoted 2 lines

patches applied. Just tell me if you need complete dmesg.

yes, please, it may help. Can you send your config file as well ?

Just to be sure, is your PAGE_OFFSET equal to 0x80000000 ?

Thanks

Signature · 1 line
              Franck
#7 lore raw

On Mon, 2007-03-05 at 15:15 +0100, Franck Bui-Huu wrote:

Thanks for caring Franck,

Quoted 2 lines

Does your platform code do some address translation by using CPHYSADDR() macro or by using anything else than pa() ?

Not at all, I've reduced platform code to minimum for the test, it basically registers a prom console, and do add_memory_region(0x10000000, 32 << 20), remaining is basic irq and time stuff.

Quoted 1 line

Just to be sure, is your PAGE_OFFSET equal to 0x80000000 ?

Yes, here is my spaces.h content:

#define PHYS_OFFSET 0x10000000

#define CAC_BASE                0x90000000
#define IO_BASE                 0xa0000000
#define UNCAC_BASE              0xa0000000
#define MAP_BASE                0xc0000000

#define PAGE_OFFSET 0x80000000UL

Note: The CAC_BASE value of 0x90000000 is for the linux exception code to work as-is, since there is no RAM at 0x80000000 to put vector code.

I dug a little and found the following.

My kernel is loaded at 0x9012d000, '&_end' value is 0x901d4020. In bootmem_init(), we try to compute reserved_end by using __pa_symbol(&_end), which adds PHYS_OFFSET to it, though it was already accounted.

The loop in setup.c is thus unable to compute a correct 'map_start' value since 'reserved_end' is way above all declared memory.

init_bootmem_node() is then called with a 'map_start' default value of ~0. Maybe that case should fall in the invalid memory map panic ?

I tried to set 'reserved_end' value manually and it went furter, but I end up with the following message:

Bad page state in process 'swapper'
page:81000000 flags:0x00000000 mapping:00000000 mapcount:1 count:0 Trying to fix it up, but a reboot is needed

Backtrace:
Call Trace:
[<90029f10>] dump_stack+0x8/0x34
[<9006ac58>] bad_page+0x68/0xa8
[<9006b0a4>] __free_pages_ok+0x358/0x37c
[<9013d374>] free_all_bootmem_core+0x24c/0x270
[<90134f30>] mem_init+0x40/0x19c
[<9012d828>] start_kernel+0x1d4/0x36c

Full dmesg with and without manual set of reserved_end attached.

Regards,

Signature · 1 line
Maxime

#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.20
# Mon Mar 5 15:55:02 2007
#
CONFIG_MIPS=y

#
# Machine selection
#
# CONFIG_BCM963xx is not set
CONFIG_TANGO2=y
# CONFIG_MIPS_MTX1 is not set
# CONFIG_MIPS_BOSPORUS is not set
# CONFIG_MIPS_PB1000 is not set
# CONFIG_MIPS_PB1100 is not set
# CONFIG_MIPS_PB1500 is not set
# CONFIG_MIPS_PB1550 is not set
# CONFIG_MIPS_PB1200 is not set
# CONFIG_MIPS_DB1000 is not set
# CONFIG_MIPS_DB1100 is not set
# CONFIG_MIPS_DB1500 is not set
# CONFIG_MIPS_DB1550 is not set
# CONFIG_MIPS_DB1200 is not set
# CONFIG_MIPS_MIRAGE is not set
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
# CONFIG_WR_PPMC is not set
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
# CONFIG_MOMENCO_OCELOT_3 is not set
# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_V2PCI is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
# CONFIG_DDB5477 is not set
# CONFIG_MACH_VR41XX is not set
# CONFIG_PMC_YOSEMITE is not set
# CONFIG_QEMU is not set
# CONFIG_MARKEINS is not set
# CONFIG_SGI_IP22 is not set
# CONFIG_SGI_IP27 is not set
# CONFIG_SGI_IP32 is not set
# CONFIG_SIBYTE_BIGSUR is not set
# CONFIG_SIBYTE_SWARM is not set
# CONFIG_SIBYTE_SENTOSA is not set
# CONFIG_SIBYTE_RHONE is not set
# CONFIG_SIBYTE_CARMEL is not set
# CONFIG_SIBYTE_PTSWARM is not set
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
# CONFIG_TANGO2_ES1 is not set
# CONFIG_TANGO2_ES2 is not set
# CONFIG_TANGO2_ES3 is not set
# CONFIG_TANGO2_ES4 is not set
# CONFIG_TANGO2_ES5 is not set
CONFIG_TANGO2_ES6=y
# CONFIG_KEXEC is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
CONFIG_MIPS_L1_CACHE_SHIFT=5

#
# CPU selection
#
# CONFIG_CPU_MIPS32_R1 is not set
CONFIG_CPU_MIPS32_R2=y
# CONFIG_CPU_MIPS64_R1 is not set
# CONFIG_CPU_MIPS64_R2 is not set
# CONFIG_CPU_R3000 is not set
# CONFIG_CPU_TX39XX is not set
# CONFIG_CPU_VR41XX is not set
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
# CONFIG_CPU_R5000 is not set
# CONFIG_CPU_R5432 is not set
# CONFIG_CPU_R6000 is not set
# CONFIG_CPU_NEVADA is not set
# CONFIG_CPU_R8000 is not set
# CONFIG_CPU_R10000 is not set
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_HAS_CPU_MIPS32_R2=y
CONFIG_CPU_MIPS32=y
CONFIG_CPU_MIPSR2=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y

#
# Kernel type
#
CONFIG_32BIT=y
# CONFIG_64BIT is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set CONFIG_CPU_HAS_PREFETCH=y CONFIG_MIPS_MT_DISABLED=y
# CONFIG_MIPS_MT_SMP is not set
# CONFIG_MIPS_MT_SMTC is not set
# CONFIG_MIPS_VPE_LOADER is not set
# CONFIG_64BIT_PHYS_ADDR is not set CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_CPU_SUPPORTS_HIGHMEM=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
# CONFIG_HZ_48 is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_128 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_256 is not set
# CONFIG_HZ_1000 is not set
# CONFIG_HZ_1024 is not set CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set CONFIG_LOCKDEP_SUPPORT=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"

#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32

#
# General setup
#
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
# CONFIG_IGNORE_COMPILE_INFO is not set
# CONFIG_SYSVIPC is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_UTS_NS is not set
# CONFIG_IKCONFIG is not set
# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_USE_GZIP=y CONFIG_INITRAMFS_SOURCE="../../buildroot/images/root-noversion/" CONFIG_INITRAMFS_ROOT_UID=0 CONFIG_INITRAMFS_ROOT_GID=0
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
# CONFIG_ELF_CORE is not set
CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SHMEM is not set
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set

#
# Loadable module support
#
# CONFIG_MODULES is not set

#
# Block layer
#
# CONFIG_BLOCK is not set

#
# Bus options (PCI, PCMCIA, EISA, ISA, TC)
#
CONFIG_HW_HAS_PCI=y
# CONFIG_PCI is not set
CONFIG_MMU=y

#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set

#
# PCI Hotplug Support
#

#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_TRAD_SIGNALS=y

#
# Networking
#
# CONFIG_NET is not set

#
# Device Drivers
#

#
# Generic Driver Options
#
CONFIG_STANDALONE=y
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_SYS_HYPERVISOR is not set

#
# Connector - unified userspace <-> kernelspace linker #

#
# Memory Technology Devices (MTD)
#
# CONFIG_MTD is not set

#
# Parallel port support
#
# CONFIG_PARPORT is not set

#
# Plug and Play support
#

#
# Misc devices
#
# CONFIG_TIFM_CORE is not set

#
# SCSI device support
#
# CONFIG_SCSI_NETLINK is not set

#
# Serial ATA (prod) and Parallel ATA (experimental) drivers #

#
# Fusion MPT device support
#
# CONFIG_FUSION is not set

#
# IEEE 1394 (FireWire) support
#

#
# I2O device support
#

#
# ISDN subsystem
#

#
# Telephony Support
#
# CONFIG_PHONE is not set

#
# Input device support
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set

#
# Userland interfaces
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_TSDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set

#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set

#
# Hardware I/O ports
#
# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set

#
# Character devices
#
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set

#
# Serial drivers
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=2
CONFIG_SERIAL_8250_RUNTIME_UARTS=2
# CONFIG_SERIAL_8250_EXTENDED is not set

#
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=8

#
# IPMI
#
# CONFIG_IPMI_HANDLER is not set

#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set

#
# TPM devices
#
# CONFIG_TCG_TPM is not set

#
# I2C support
#
CONFIG_I2C=y
# CONFIG_I2C_CHARDEV is not set

#
# I2C Algorithms
#
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALGOPCF is not set
# CONFIG_I2C_ALGOPCA is not set

#
# I2C Hardware Bus support
#
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PCA_ISA is not set

#
# Miscellaneous I2C Chip support
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set

#
# SPI support
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set

#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set

#
# Hardware Monitoring support
#
# CONFIG_HWMON is not set
# CONFIG_HWMON_VID is not set

#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set

#
# Digital Video Broadcasting Devices
#

#
# Graphics support
#
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set

#
# Sound
#
# CONFIG_SOUND is not set

#
# HID Devices
#
CONFIG_HID=y

#
# USB support
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
# CONFIG_USB_ARCH_HAS_EHCI is not set

#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' #

#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set

#
# MMC/SD Card support
#
# CONFIG_MMC is not set

#
# LED devices
#
# CONFIG_NEW_LEDS is not set

#
# LED drivers
#

#
# LED Triggers
#

#
# InfiniBand support
#

#
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) #

#
# Real Time Clock
#
# CONFIG_RTC_CLASS is not set

#
# Tango2 devices
#
# CONFIG_TANGO2_FIP is not set
# CONFIG_TANGO2_GPIO is not set
# CONFIG_TANGO2_IR is not set

#
# DMA Engine support
#
# CONFIG_DMA_ENGINE is not set

#
# DMA Clients
#

#
# DMA Devices
#

#
# Virtualization
#

#
# File systems
#
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set

#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
# CONFIG_PROC_KCORE is not set
CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
# CONFIG_CTMP_FS is not set

#
# Miscellaneous filesystems
#
# CONFIG_SQUASHFS is not set

#
# Native Language Support
#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
CONFIG_NLS_CODEPAGE_850=y
# CONFIG_NLS_CODEPAGE_852 is not set
# CONFIG_NLS_CODEPAGE_855 is not set
# CONFIG_NLS_CODEPAGE_857 is not set
# CONFIG_NLS_CODEPAGE_860 is not set
# CONFIG_NLS_CODEPAGE_861 is not set
# CONFIG_NLS_CODEPAGE_862 is not set
# CONFIG_NLS_CODEPAGE_863 is not set
# CONFIG_NLS_CODEPAGE_864 is not set
# CONFIG_NLS_CODEPAGE_865 is not set
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_936 is not set
# CONFIG_NLS_CODEPAGE_950 is not set
# CONFIG_NLS_CODEPAGE_932 is not set
# CONFIG_NLS_CODEPAGE_949 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
# CONFIG_NLS_ISO8859_5 is not set
# CONFIG_NLS_ISO8859_6 is not set
# CONFIG_NLS_ISO8859_7 is not set
# CONFIG_NLS_ISO8859_9 is not set
# CONFIG_NLS_ISO8859_13 is not set
# CONFIG_NLS_ISO8859_14 is not set
CONFIG_NLS_ISO8859_15=y
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
CONFIG_NLS_UTF8=y

#
# Profiling support
#
# CONFIG_PROFILING is not set

#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_PROVE_LOCKING is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="console=ttyS0 root=/dev/nfs ip=dhcp" # CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_KGDB is not set CONFIG_RUNTIME_DEBUG=y
# CONFIG_MIPS_UNCACHED is not set

#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set

#
# Cryptographic options
#
# CONFIG_CRYPTO is not set

#
# Library routines
#
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_IOMAP_COPY=y

Linux version 2.6.20 (max@sakura) (gcc version 4.1.2) #40 Mon Mar 5 17:15:57 CET 2007 prom console registered
CPU revision is: 00019068
Determined physical RAM map:
memory: 02000000 @ 10000000 (usable)
DEBUG: reserved_end: 0x000201d5
DEBUG: init_bootmem_node: mapstart:0xffffffff min_low_pfn:0x00010000 max_low_pfn:0x00012000

Linux version 2.6.20 (max@sakura) (gcc version 4.1.2) #41 Mon Mar 5 17:18:04 CET 2007 prom console registered
CPU revision is: 00019068
Determined physical RAM map:
memory: 02000000 @ 10000000 (usable)
DEBUG: reserved_end: 0x000101d5
DEBUG: init_bootmem_node: mapstart:0x000101d5 min_low_pfn:0x00010000 max_low_pfn:0x00012000 On node 0 totalpages: 8192
DMA zone: 64 pages used for memmap
DMA zone: 0 pages reserved
DMA zone: 8128 pages, LIFO batch:0
Normal zone: 0 pages used for memmap
Built 1 zonelists. Total pages: 8128
Kernel command line: console=ttyS0 root=/dev/nfs ip=dhcp
Primary instruction cache 16kB, physically tagged, 2-way, linesize 16 bytes. Primary data cache 16kB, 2-way, linesize 16 bytes.
Synthesized TLB refill handler (20 instructions).
Synthesized TLB load handler fastpath (32 instructions).
Synthesized TLB store handler fastpath (32 instructions).
Synthesized TLB modify handler fastpath (31 instructions).
PID hash table entries: 128 (order: 7, 512 bytes)
Using 150.750 MHz high precision timer.
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Bad page state in process 'swapper'
page:81000000 flags:0x00000000 mapping:00000000 mapcount:1 count:0
Trying to fix it up, but a reboot is needed

Backtrace:
Call Trace:
[<90029f10>] dump_stack+0x8/0x34
[<9006ac58>] bad_page+0x68/0xa8
[<9006b0a4>] __free_pages_ok+0x358/0x37c
[<9013d2d0>] free_all_bootmem_core+0x24c/0x270
[<90134e8c>] mem_init+0x40/0x19c
[<9012d828>] start_kernel+0x1d4/0x36c

Bad page state in process 'swapper'
page:81000020 flags:0x00000000 mapping:00000000 mapcount:1 count:0 Trying to fix it up, but a reboot is needed

Backtrace:
Call Trace:
[<90029f10>] dump_stack+0x8/0x34
[<9006ac58>] bad_page+0x68/0xa8
[<9006b0a4>] __free_pages_ok+0x358/0x37c
[<9013d2d0>] free_all_bootmem_core+0x24c/0x270
[<90134e8c>] mem_init+0x40/0x19c
[<9012d828>] start_kernel+0x1d4/0x36c
#8 lore raw
Quoted 7 lines · Maxime Bizon

I dug a little and found the following.

My kernel is loaded at 0x9012d000, '&_end' value is 0x901d4020. In bootmem_init(), we try to compute reserved_end by using __pa_symbol(&_end), which adds PHYS_OFFSET to it, though it was already accounted.

I think you missed PAGE_OFFSET meaning...

PAGE_OFFSET is the start of the kernel virtual address space and before this patchset pa(PAGE_OFFSET) was always 0.

In your case, you said:

       PAGE_OFFSET = 0x80000000
       PHYS_OFFSET = 0x10000000

this means that the first kernel virtual address is 0x80000000 and the corresponding physical address is 0x10000000. If you load your kernel at 0x9000xxxx, it will be loaded in physical memory located at 0x2000xxxx which is obviously not what you want.

So to fix this you have 2 possibilities:

- load your kernel at 0x8000xxxx addresses,
- set PAGE_OFFSET to 0x90000000.

You said that you already tried the second solution but it fails. I don't see why though...

Quoted 6 lines

The loop in setup.c is thus unable to compute a correct 'map_start' value since 'reserved_end' is way above all declared memory.

init_bootmem_node() is then called with a 'map_start' default value of ~0. Maybe that case should fall in the invalid memory map panic ?

well maybe some sanity checkings are missing here.

Sorry for responding lately but life sometimes triggers NMIs ;)

Signature · 1 line
              Franck
#9 lore raw
Quoted 7 lines · Franck Bui-Huu

I think you missed PAGE_OFFSET meaning...

PAGE_OFFSET is the start of the kernel virtual address space and before this patchset pa(PAGE_OFFSET) was always 0.

In your case, you said:

Quoted 7 lines
       PAGE_OFFSET = 0x80000000
       PHYS_OFFSET = 0x10000000

this means that the first kernel virtual address is 0x80000000 and the corresponding physical address is 0x10000000. If you load your kernel at 0x9000xxxx, it will be loaded in physical memory located at 0x2000xxxx which is obviously not what you want.

which sound like a very bogus setup for at leat 32bit MIPS. The mapping virtual 0x80000000 to physical 0x00000000 is a CPU thing and can't be changed.

Thomas.

Signature · 2 lines
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea.                                                [ RFC1925, 2.3 ]
#10 lore raw
In reply to Franck Bui-Huu
Quoted 4 lines · Franck Bui-Huu

- set PAGE_OFFSET to 0x90000000.

You said that you already tried the second solution but it fails. I don't see why though...

Ok that makes sense for me now.

Though on the opposite of other arch, on 32bits mips you will always have PAGE_OFFSET == PHYS_OFFSET + 0x80000000 because of fixed KSEG. Making it possible to change both confused me.

I found the problem, I think these two liners are missing from your patch. My board now works correctly, with 2MB more free memory, thanks for this ! (and for the free tour in mm/ ;)

Commit 6f284a2ce7b8bc49cb8455b1763357897a899abb introduced PHYS_OFFSET, but missed some virtual to physical address conversion. The following patch fixes it.

include/asm-mips/pgtable.h +1 -1
@@ -75,7 +75,7 @@
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
-#define pmd_phys(pmd)		(pmd_val(pmd) - PAGE_OFFSET)
+#define pmd_phys(pmd)		(pmd_val(pmd) - PAGE_OFFSET + PHYS_OFFSET)
 #define pmd_page(pmd)		(pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
 #define pmd_page_vaddr(pmd)	pmd_val(pmd)
 
include/asm-mips/pgtable-64.h +1 -1
@@ -199,7 +199,7 @@
 {
 	return pud_val(pud);
 }
-#define pud_phys(pud)		(pud_val(pud) - PAGE_OFFSET)
+#define pud_phys(pud)		(pud_val(pud) - PAGE_OFFSET + PHYS_OFFSET)
 #define pud_page(pud)		(pfn_to_page(pud_phys(pud) >> PAGE_SHIFT))
 
 /* Find an entry in the second-level page table.. */
Signature · 1 line
Maxime
#11 lore raw

Hi

Quoted 1 line · Maxime Bizon

I found the problem, I think these two liners are missing from your

good catch ! I dunno why this is missing from the original patch since I have this in my own tree.

Quoted 3 lines

patch. My board now works correctly, with 2MB more free memory, thanks for this ! (and for the free tour in mm/ ;)

yeah 2MB is quite a lot for embedded system.

Quoted 13 lines

Commit 6f284a2ce7b8bc49cb8455b1763357897a899abb introduced PHYS_OFFSET, but missed some virtual to physical address conversion. The following patch fixes it.

include/asm-mips/pgtable.h 2007-03-07 17:28:20.000000000 +0100 line 78

Quoted 5 lines
include/asm-mips/pgtable.h 2007-03-07 17:28:20.000000000 +0100 renamed from include/asm-mips/pgtable.h 2007-02-04 21:22:45.000000000 +0100 +1 -1
@@ -75,7 +75,7 @@
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
-#define pmd_phys(pmd)          (pmd_val(pmd) - PAGE_OFFSET)
+#define pmd_phys(pmd)          (pmd_val(pmd) - PAGE_OFFSET + PHYS_OFFSET)

please use virt_to_phys() instead plain translation...

include/asm-mips/pgtable-64.h 2007-03-07 17:28:47.000000000 +0100 line 202

Quoted 11 lines
include/asm-mips/pgtable.h 2007-03-07 17:28:20.000000000 +0100 renamed from include/asm-mips/pgtable.h 2007-02-04 21:22:45.000000000 +0100 +0 -0
 #define pmd_page(pmd)          (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
 #define pmd_page_vaddr(pmd)    pmd_val(pmd)
 
include/asm-mips/pgtable-64.h 2007-03-07 17:28:47.000000000 +0100 renamed from include/asm-mips/pgtable-64.h 2007-02-04 21:22:45.000000000 +0100 +1 -1
@@ -199,7 +199,7 @@
 {
        return pud_val(pud);
 }
-#define pud_phys(pud)          (pud_val(pud) - PAGE_OFFSET)
+#define pud_phys(pud)          (pud_val(pud) - PAGE_OFFSET + PHYS_OFFSET)

ditto

Ralf, could this patch reach ASAP your main tree ?

thanks

Signature · 1 line
              Franck
#12 lore raw
In reply to Franck Bui-Huu
Quoted 3 lines · Franck Bui-Huu

So to fix this you have 2 possibilities:

- load your kernel at 0x8000xxxx addresses,

OMG, this is totaly crap ! That's what happen when I try to answer and my brain is not working ! Even if you play with VMA/LMA in your linker script it won't work...

So forget about this point.

Signature · 1 line
              Franck
#13 lore raw
In reply to Franck Bui-Huu

to detail Thomas' note...

Quoted 9 lines · Franck Bui-Huu

Date: Tue, 6 Mar 2007 22:39:59 +0100
From: Franck Bui-Huu <[email protected]>
To: [email protected]
Cc: linux-mips <[email protected]>
Subject: Re: [PATCH 0/2] FLATMEM: allow memory to start at pfn != 0 [take

    #2]

...
In your case, you said:

Quoted 8 lines
        PAGE_OFFSET = 0x80000000
        PHYS_OFFSET = 0x10000000

this means that the first kernel virtual address is 0x80000000 and the corresponding physical address is 0x10000000. If you load your kernel at 0x9000xxxx, it will be loaded in physical memory located at 0x2000xxxx which is obviously not what you want.

Never. If the kernel virtual address is 0x80000000+off with 0 <= off <= 0x1fffffff (aka kseg0, defined by bits 31..29), the corresponding physical address is always 0+off, no matter what PHYS_OFFSET you invent. Physical memory at 0x20000000 is not reachable from kesg0/1.

Quoted 1 line

...

regards

peter

#14 lore raw
Quoted 6 lines · peter fuerst

Never. If the kernel virtual address is 0x80000000+off with 0 <= off <= 0x1fffffff (aka kseg0, defined by bits 31..29), the corresponding physical address is always 0+off, no matter what PHYS_OFFSET you invent. Physical memory at 0x20000000 is not reachable from kesg0/1.

I already answered that was bullshit and I took drugs before writing this...

thanks

Signature · 1 line
              Franck
#15 lore raw
In reply to Franck Bui-Huu

Hi,

i'm just trying to understand, what the "[PATCH 0,1,2/2] FLATMEM..." patchset does. While working through it, it appears to me that

1) Formerly min_low_pfn was never calculated, but left zero-initialized.

2) The patchset now provides proper min_low_pfn calculation from boot_mem_map (thanks !), and then discards this calculated value:
a) Patch 1/2 prints an info about wasted pagetable-entries and resets min_low_pfn to zero, retaining the former state.
b) (first part of) Patch 2/2 prints an info about differences between the the really found (boot_mem_map) and the expected (given by PHYS_OFFSET through ARCH_PFN_OFFSET) memory-offset, then resets min_low_pfn to ARCH_PFN_OFFSET.

3) Finally the (rather set than) calculated values are completely passed on to init_bootmem by replacing the former call (mm/bootmem.c)

       max_low_pfn = highest;
       min_low_pfn = mapstart;
       init_bootmem_core(NODE_DATA(0), mapstart, 0,           highest);
   with
       init_bootmem_core(NODE_DATA(0), mapstart, min_low_pfn, max_low_pfn);

Right ?

So far, i can't avoid the impression, that this patchset would work perfectly without using PHYS_OFFSET at all, even better IMHO, since it would use the *really* detected memory-offset instead of some should-be-value. (Providing an override-option for critical cases is another topic).

The second part of Patch 2/2 introduces PHYS_OFFSET to __pa/__va and to virt_to_phys/phys_to_virt (writing "page_offset" shorthand for PAGE_OFFSET and __pa_page_offset() here):

pa: address - page_offset + PHYS_OFFSET

va: address + page_offset - PHYS_OFFSET

1) Since the relation between kernel virtual address and physical address is fixed (we agreed about that earlier), introducing PHYS_OFFSET in this places is a nop at best: (page_offset - PHYS_OFFSET) is constant, whenever we introduce/change PHYS_OFFSET we must adjust page_offset accordingly (what's about CKSEG0 in __pa_page_offset() ?).

2) Because of 1) we get the same conversions, if we don't use PHYS_OFFSET anywhere.

3) The page_offset adjustment may force fixes in other, not yet blown up, places (pmd_phys() cried out lately...).

Hard to see, what we gain by introducing PHYS_OFFSET here.

What can PHYS_OFFSET achieve here - besides obfuscating ? Are there future uses for it, that justify the contortions ?

with best regards

peter

Quoted 29 lines · Franck Bui-Huu

Date: Wed, 10 Jan 2007 09:44:03 +0100
From: Franck Bui-Huu <[email protected]>
To: [email protected]
Cc: [email protected]
Subject: [PATCH 0/2] FLATMEM: allow memory to start at pfn != 0 [take #2]

Ralf,

Here's is the second attempt to make this works on your Malta board and all other boards that have some data reserved at the start of their memories. In these cases the first patchset assumed wrongly that the start of the memory was after this reserved area.

Patch 1/2 should work alone now. the kernel should report that your mem config is wasting some memory for tracking reserved pages located at the start of the mem.

Thanks for testing

Franck

---

 arch/mips/kernel/setup.c |   40 +++++++++++++++++++++++++++++++---------
 arch/mips/mm/init.c      |   23 +++++++++++------------
 include/asm-mips/dma.h   |    1 +
 include/asm-mips/io.h    |    4 ++--
 include/asm-mips/page.h  |   25 +++++++++++++++++++++----
 5 files changed, 66 insertions(+), 27 deletions(-)
#16 lore raw

Hi,

Quoted 3 lines · peter fuerst

3) The page_offset adjustment may force fixes in other, not yet blown up, places (pmd_phys() cried out lately...).

Not really fair. It crashed lately because until now I was the only one to use it. And unfortunately I failed to give back this change to Ralf's tree.

BUT, note that the root cause of this bug is that we did _plain_ address translation instead of using dedicated macro.

So I would say that this patch helps to fix these buggy places.

Quoted 3 lines

What can PHYS_OFFSET achieve here - besides obfuscating ? Are there future uses for it, that justify the contortions ?

How do you deal with fancy cases such as physical memory starting at 0x20000000 for example ?

Signature · 1 line
              Franck
#17 lore raw

Hi!

Quoted 7 lines · Franck Bui-Huu

Date: Mon, 12 Mar 2007 10:47:01 +0100
From: Franck Bui-Huu <[email protected]>
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH 0/2] FLATMEM: allow memory to start at pfn != 0 [take

    #2]
Quoted 8 lines

Hi,

Quoted 3 lines · peter fuerst

3) The page_offset adjustment may force fixes in other, not yet blown up, places (pmd_phys() cried out lately...).

Not really fair. It crashed lately because until now I was the only

May be, so i apologize.

Quoted 2 lines

one to use it. And unfortunately I failed to give back this change to Ralf's tree.

You see the problem. Any occurrence of PAGE_OFFSET must be checked.

Quoted 5 lines

BUT, note that the root cause of this bug is that we did _plain_ address translation instead of using dedicated macro.

So I would say that this patch helps to fix these buggy places.

Sure, a dedicated macro or function is the correct way to handle all the kernel-addresses. Moreover it would be desirable, if this macro really could be used throughout the kernel, e.g. by drivers, handling any reasonable kernel-address, which isn't possible in the page_offset scheme anyway.

Quoted 7 lines
Quoted 4 lines

What can PHYS_OFFSET achieve here - besides obfuscating ? Are there future uses for it, that justify the contortions ?

How do you deal with fancy cases such as physical memory starting at 0x20000000 for example ?

With XKPHYS and exactly this offset ;-)
To be serious again:
O.K. i see the future use is to support TLB-mapped 32bit kernels.

In this case, with respect to unmapped kernels, the min_low_pfn stuff should be decoupled from the PHYS_OFFSET setting, to let the unmapped kernels keep it zero and benefit from memory savings though. Otherwise, for each different non-zero PHYS_OFFSET, there must be an accordingly adjusted PAGE_OFFSET (the CKSEG0 part in __pa_page_offset is still to be prepared for this).

Quoted 5 lines

--
Franck

kind regards

peter

#18 lore raw
Quoted 3 lines · peter fuerst

You see the problem. Any occurrence of PAGE_OFFSET must be checked.

yes and whatever the scheme you propose...

Quoted 5 lines

the kernel-addresses. Moreover it would be desirable, if this macro really could be used throughout the kernel, e.g. by drivers, handling any reasonable kernel-address, which isn't possible in the page_offset scheme anyway.

Can you explain why the current use of pa() failed to handle all kernel address with a real example ?

A few people reported that they had problem with KPHYS/CKSEG0 address mix for 64 bit kernels but as far I can see it was due to a miss configuration of their kernels. Of course I can be wrong but these people haven't given any feedbacks so far...

Thanks

Signature · 1 line
              Franck
#19 lore raw

Hi!

Quoted 14 lines · Franck Bui-Huu

Date: Mon, 12 Mar 2007 18:05:10 +0100
From: Franck Bui-Huu <[email protected]>
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH 0/2] FLATMEM: allow memory to start at pfn != 0 [take

    #2]
Quoted 3 lines · peter fuerst

You see the problem. Any occurrence of PAGE_OFFSET must be checked.

yes and whatever the scheme you propose...

Quoted 8 lines
Quoted 5 lines

the kernel-addresses. Moreover it would be desirable, if this macro really could be used throughout the kernel, e.g. by drivers, handling any reasonable kernel-address, which isn't possible in the page_offset scheme anyway.

Can you explain why the current use of pa() failed to handle all kernel address with a real example ?

Simply, when you convert between cached (kseg0, ckseg0, several xkphys- regions) and uncached (kseg1, ckseg1, several xkphys-regions) addresses and the other way round, you need the physical address as an intermediate value and __pa() or virt_to_phys() can support only one direction.

Of course a scheme, that supports all unmapped spaces (kseg0/1, ckseg0/1, xkphys) simultaneously, or even xkphys alone, can't support TLB-mapped spaces (kseg3, ckseg3, ..., xkseg) - at which your patch seems to aim - and vice versa.

Quoted 4 lines

A few people reported that they had problem with KPHYS/CKSEG0 address mix for 64 bit kernels but as far I can see it was due to a miss configuration of their kernels. Of course I canbe wrong but these

Hmm, i don't remember actually mis-configured kernels, but allright, have to skim the eMail-archive again.

Quoted 5 lines

people haven't given any feedbacks so far...

Thanks
--
Franck

kind regards

peter

#20 lore raw
Quoted 9 lines · peter fuerst
Quoted 2 lines · Franck Bui-Huu

Can you explain why the current use of pa() failed to handle all kernel address with a real example ?

Simply, when you convert between cached (kseg0, ckseg0, several xkphys- regions) and uncached (kseg1, ckseg1, several xkphys-regions) addresses and the other way round, you need the physical address as an intermediate value and __pa() or virt_to_phys() can support only one direction.

I was asking for _real_ uses. Can you point out some code where these convertion are needed ?

I'm asking that because your uses of __pa()/virt_to_phys() to convert cached address into uncached address and vice versa is weird. You talked about drivers but I would think that drivers have physical addresses of the device they control. And they get a virtual address by using ioremap() and Co. And using __pa() on such addresses is simply buggy whatever the implementation of __pa().

Signature · 1 line
              Franck
#21 lore raw

Hi,

after traveling several kernel areas (for more or less related reasons), it's now clear that you got no other choice than to introduce phys_offset. (I let your reasoning for it mislead me before. Sorry.)

Two conditions must be met:
1) __pfn_to_page(x) == &mem_map[x - ARCH_PFN_OFFSET]
2) PAGE_OFFSET is not "the start of the kernel virtual address space", but the virtual address of the first page, handled by the table, as is set in free_area_init():
__pfn_to_page(__pa(PAGE_OFFSET) >> PAGE_SHIFT) == &mem_map[0]

These are met if and only if
__pa(PAGE_OFFSET) == ARCH_PFN_OFFSET<<PAGE_SHIFT + r, 0 <= r < 1<<PAGE_SHIFT

Using the simpliest arithmetic formula for __pa()
"__pa(x) := x - PAGE_OFFSET + d",
we get d = ARCH_PFN_OFFSET << PAGE_SHIFT, and use the descriptive name PHYS_OFFSET for this "d".

(Of course, i could have guessed and tried and defined PHYS_OFFSET in the first place...)

On the other hand, "__pa(kseg) == 0" must be met for kseg in {KSEG0,KSEG1, CKSEG0,CKSEG1,any XKPHYS-region}. This enforces:
PAGE_OFFSET = kseg + (ARCH_PFN_OFFSET << PAGE_SHIFT)

Perhaps you could have pointed to the above relations, and thus saved several "users" from a bit of trial and error :-)

My suggestion, to use the detected offset (min_low_pfn), instead of a predefined constant, may be too expensive. The flexibility gained by "#define ARCH_PFN_OFFSET min_low_pfn" and hence "#define PHYS_OFFSET (min_low_pfn << PAGE_SHIFT)" is probably not worth the cost, that arises when these must be evaluated in so many places.

kind regards

peter