lkml.org 
[lkml]   [1998]   [Jul]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
From
Subjectauto-probe memory size during boot
Date
Linux gets memory configuration from BIOS. Due to lousy design, standard
BIOS can only report 64MB memory at most. Well, Linux can only
automatically found 64MB. When there is more memory, you have to add
"mem=xxx[MmKk]", then kernel knows that there is more memory available.
It
is not convenient for flexible configuration, system may crash during
boot.
To make kernel automatically probe memory size need adding into kernel.
I
hacked the booting code and added such support. Patches for RedHat5.0 &
RedHat5.1 (kernel 2.0.32 & kernel 2.0.34) and installation are here:

installation steps:
1. patching
cd /usr/src/linux/arch/i386/kernel
patch < mem-2.0.xx.patch
2. re-compile your kernel
3. edit lilo, remove "mem=xxx[MmKk]"
3. run lilo and reboot your box

patches:
-------------------8<-----mem-2.0.32.patch-----------8<-------------------
diff -c -r -N setup.c.orig setup.c
*** setup.c.orig Sat Jul 18 21:54:40 1998
--- setup.c Sun Jul 19 16:34:02 1998
***************
*** 32,37 ****
--- 32,38 ----
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/smp.h>
+ #include <asm/pgtable.h>

/*
* Tell us the machine setup..
***************
*** 76,87 ****
extern int root_mountflags;
extern int _etext, _edata, _end;

extern char empty_zero_page[PAGE_SIZE];

/*
* This is set up by the setup-routine at boot-time
*/
! #define PARAM empty_zero_page
#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
#ifdef CONFIG_APM
#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+64))
--- 77,90 ----
extern int root_mountflags;
extern int _etext, _edata, _end;

+ #if 0
extern char empty_zero_page[PAGE_SIZE];
+ #endif

/*
* This is set up by the setup-routine at boot-time
*/
! #define PARAM ((char *)empty_zero_page)
#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
#ifdef CONFIG_APM
#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+64))
***************
*** 109,117 ****
void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p)
{
! unsigned long memory_start, memory_end;
char c = ' ', *to = command_line, *from = COMMAND_LINE;
! int len = 0;
static unsigned char smptrap=0;

if(smptrap==1)
--- 112,120 ----
void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p)
{
! unsigned long memory_start, memory_end, cfg;
char c = ' ', *to = command_line, *from = COMMAND_LINE;
! int len = 0, page_ok;
static unsigned char smptrap=0;

if(smptrap==1)
***************
*** 128,133 ****
--- 131,182 ----
#endif
aux_device_present = AUX_DEVICE_INFO;
memory_end = (1<<20) + (EXT_MEM_K<<10);
+ if (EXT_MEM_K >= 63 * 1024) {
+ printk("BIOS report extended memory %d\n", EXT_MEM_K);
+ /* 63MB extended memory (totally 64MB memory) is the largest
+ * amount that BIOS can currently report. Probe real amount
+ * of memory when BIOS report us there is totally 64MB memory
+ */
+ /* store PTE0, linux kernel store all 0's in PTE0 to
+ * catch NULL references */
+ cfg = pg0[0];
+ page_ok = 1;
+ do {
+ /* mmap address 0 to where we will test */
+ pg0[0] = (memory_end |
+ _PAGE_PRESENT |
+ _PAGE_RW |
+ _PAGE_PCD); /* uncachable */
+ local_flush_tlb(); /* invalidate local TLB */
+
+ /* test for alternating 1's and 0's */
+ *((volatile unsigned long *)0) = 0xaaaaaaaa;
+ if (*((volatile unsigned long *)0) != 0xaaaaaaaa)
+ page_ok = 0;
+
+ /* test for alternating 0's and 1's */
+ *((volatile unsigned long *)0) = 0x55555555;
+ if (*((volatile unsigned long *)0) != 0x55555555)
+ page_ok = 0;
+
+ /* test for all 1's */
+ *((volatile unsigned long *)0) = 0xffffffff;
+ if (*((volatile unsigned long *)0) != 0xffffffff)
+ page_ok = 0;
+
+ /* test for all 0's */
+ *((volatile unsigned long *)0) = 0x00000000;
+ if (*((volatile unsigned long *)0) != 0x00000000)
+ page_ok = 0;
+
+ if (page_ok)
+ memory_end += PAGE_SIZE;
+ } while (page_ok);
+
+ /* restore PTE0 */
+ pg0[0] = cfg;
+ local_flush_tlb(); /* invalidate local TLB */
+ }
memory_end &= PAGE_MASK;
#ifdef CONFIG_BLK_DEV_RAM
rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
-------------------8<-----mem-2.0.32.patch-----------8<-------------------

-------------------8<-----mem-2.0.34.patch-----------8<-------------------
diff -c -r -N setup.c.orig setup.c
*** setup.c.orig Sat Jul 18 17:40:35 1998
--- setup.c Sun Jul 19 16:08:16 1998
***************
*** 32,37 ****
--- 32,38 ----
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/smp.h>
+ #include <asm/pgtable.h>

/*
* Tell us the machine setup..
***************
*** 81,92 ****
extern int root_mountflags;
extern int _etext, _edata, _end;

extern char empty_zero_page[PAGE_SIZE];

/*
* This is set up by the setup-routine at boot-time
*/
! #define PARAM empty_zero_page
#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
#ifdef CONFIG_APM
#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+64))
--- 82,95 ----
extern int root_mountflags;
extern int _etext, _edata, _end;

+ #if 0
extern char empty_zero_page[PAGE_SIZE];
+ #endif

/*
* This is set up by the setup-routine at boot-time
*/
! #define PARAM ((char *)empty_zero_page)
#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
#ifdef CONFIG_APM
#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+64))
***************
*** 114,122 ****
void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p)
{
! unsigned long memory_start, memory_end;
char c = ' ', *to = command_line, *from = COMMAND_LINE;
! int len = 0;
static unsigned char smptrap=0;

if(smptrap==1)
--- 117,125 ----
void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p)
{
! unsigned long memory_start, memory_end, cfg;
char c = ' ', *to = command_line, *from = COMMAND_LINE;
! int len = 0, page_ok;
static unsigned char smptrap=0;

if(smptrap==1)
***************
*** 133,138 ****
--- 136,187 ----
#endif
aux_device_present = AUX_DEVICE_INFO;
memory_end = (1<<20) + (EXT_MEM_K<<10);
+ if (EXT_MEM_K >= 63 * 1024) {
+ printk("BIOS report extened memory %d\n", EXT_MEM_K);
+ /* 63MB extended memory (totally 64MB memory) is the largest
+ * amount that BIOS can currently report. Probe real amount
+ * of memory when BIOS report us there is totally 64MB memory
+ */
+ /* store PTE0, linux kernel store all 0's in PTE0 to
+ * catch NULL references */
+ cfg = pg0[0];
+ page_ok = 1;
+ do {
+ /* mmap address 0 to where we will test */
+ pg0[0] = (memory_end |
+ _PAGE_PRESENT |
+ _PAGE_RW |
+ _PAGE_PCD); /* uncachable */
+ local_flush_tlb(); /* invalidate local TLB */
+
+ /* test for alternating 1's and 0's */
+ *((volatile unsigned long *)0) = 0xaaaaaaaa;
+ if (*((volatile unsigned long *)0) != 0xaaaaaaaa)
+ page_ok = 0;
+
+ /* test for alternating 0's and 1's */
+ *((volatile unsigned long *)0) = 0x55555555;
+ if (*((volatile unsigned long *)0) != 0x55555555)
+ page_ok = 0;
+
+ /* test for all 1's */
+ *((volatile unsigned long *)0) = 0xffffffff;
+ if (*((volatile unsigned long *)0) != 0xffffffff)
+ page_ok = 0;
+
+ /* test for all 0's */
+ *((volatile unsigned long *)0) = 0x00000000;
+ if (*((volatile unsigned long *)0) != 0x00000000)
+ page_ok = 0;
+
+ /* if this page is available, try the next one */
+ if (page_ok)
+ memory_end += PAGE_SIZE;
+ } while (page_ok);
+ /* restore PTE0 */
+ pg0[0] = cfg;
+ local_flush_tlb(); /* invalidate local TLB */
+ }
memory_end &= PAGE_MASK;
#ifdef CONFIG_BLK_DEV_RAM
rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
-------------------8<-----mem-2.0.34.patch-----------8<-------------------

If your kernel is not 2.0.32 or 2.0.34, you can modify
arch/kernel/setup.c manually by the following steps.

1. add '#include <asm/pgtable.h>'
2. comment out the line 'extern char empty_zero_page[PAGE_SIZE];'
3. re-define PARAM to '((char *)empty_zero_page)'
4. in function setup_arch(), add declarations of cfg(unsigned long)
and page_ok(int)
5. still in function setup_arch() find two line likes this
'memory_end = (1<<20) + (EXT_MEM_K<<10);
memory_end &= PAGE_MASK;', now insert the following codes between
the two lines

if (EXT_MEM_K >= 63 * 1024) {
printk("BIOS report extened memory %d\n", EXT_MEM_K);
/* 63MB extended memory (totally 64MB memory) is the largest
* amount that BIOS can currently report. Probe real amount
* of memory when BIOS report us there is totally 64MB memory
*/
/* store PTE0, linux kernel store all 0's in PTE0 to
* catch NULL references */
cfg = pg0[0];
page_ok = 1;
do {
/* mmap address 0 to where we will test */
pg0[0] = (memory_end |
_PAGE_PRESENT |
_PAGE_RW |
_PAGE_PCD); /* uncachable */
local_flush_tlb(); /* invalidate local TLB */

/* test for alternating 1's and 0's */
*((volatile unsigned long *)0) = 0xaaaaaaaa;
if (*((volatile unsigned long *)0) != 0xaaaaaaaa)
page_ok = 0;

/* test for alternating 0's and 1's */
*((volatile unsigned long *)0) = 0x55555555;
if (*((volatile unsigned long *)0) != 0x55555555)
page_ok = 0;

/* test for all 1's */
*((volatile unsigned long *)0) = 0xffffffff;
if (*((volatile unsigned long *)0) != 0xffffffff)
page_ok = 0;

/* test for all 0's */
*((volatile unsigned long *)0) = 0x00000000;
if (*((volatile unsigned long *)0) != 0x00000000)
page_ok = 0;

/* if this page is available, try the next one */
if (page_ok)
memory_end += PAGE_SIZE;
} while (page_ok);
/* restore PTE0 */
pg0[0] = cfg;
local_flush_tlb(); /* invalidate local TLB */
}

Codes for automatical probing memory size is inspired by booting codes
of FreeBSD. Wish you can enjoy it.

I have test it on two machines, one is PentiumIIx2/128MB/6GB, the other
is PentiumIIx2/196MB/6GB, it works. I want to know whether it works on
other machine ( 386, 486, Pentium, PentiumPro, especially 386 boxes). If
you encounter some problem, please contract me at para@cs.sebuaa.ac.cn.

More strict way to describe physical memory is using set of <base,size>
pairs. Instead Linux use a single <memory_start, memory_end>. It may
crash system on some motherboard and BIOS. But, fortunately, most system
apply to the Linux' way, it works very well.

Michael Liao
1998/7/19


______________________________________________________
Get Your Private, Free Email at http://www.hotmail.com

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html

\
 
 \ /
  Last update: 2005-03-22 13:43    [W:1.519 / U:0.016 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site