amount of memory

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
ncsu121978

amount of memory

Post by ncsu121978 »

how can i get the total amount of memory installed on the system. I have seen some code that will read values from CMOS and it works fine but will only report up to 64MB. How can i determine more memory then this ?
Does someone have any code they would like to share ?
Tom

Re:amount of memory

Post by Tom »

wondering if you saw DF's OS Dev FAQS about RAM
ncsu121978

Re:amount of memory

Post by ncsu121978 »

Code: Select all

/*
 * void count_memory (void)
 *
 * probes memory above 1mb
 *
 * last mod : 05sep98 - stuart george
 *            08dec98 - ""     ""
 *            21feb99 - removed dummy calls
 *
 */
void count_memory(void)
{
   register ULONG *mem;
   ULONG   mem_count, a;
   USHORT   memkb;
   UCHAR   irq1, irq2;
   ULONG   cr0;

   /* save IRQ's */
   irq1=inb(0x21);
   irq2=inb(0xA1);

   /* kill all irq's */
   outb(0x21, 0xFF);
   outb(0xA1, 0xFF);

   mem_count=0;
   memkb=0;

   // store a copy of CR0
   __asm__ __volatile("movl %%cr0, %%eax":"=a"(cr0))::"eax");

   // invalidate the cache
   // write-back and invalidate the cache
   __asm__ __volatile__ ("wbinvd");

   // plug cr0 with just PE/CD/NW
   // cache disable(486+), no-writeback(486+), 32bit mode(386+)
   __asm__ __volatile__("movl %%eax, %%cr0", :: "a" (cr0 | 0x00000001 | 0x40000000 | 0x20000000) : "eax");

   do
   {
      memkb++;
      mem_count+=1024*1024;
      mem=(ULONG*)mem_count;

      a=*mem;

      *mem=0x55AA55AA;
      
      // the empty asm calls tell gcc not to rely on whats in its registers
      // as saved variables (this gets us around GCC optimisations)
      asm("":::"memory");
      if(*mem!=0x55AA55AA)
         mem_count=0;
      else
      {
         *mem=0xAA55AA55;
         asm("":::"memory");
         if(*mem!=0xAA55AA55)
            mem_count=0;
      }

      asm("":::"memory");
      *mem=a;
   }while(memkb<4096 && mem_count!=0);

   __asm__ __volatile__("movl %%eax, %%cr0", :: "a" (cr0) : "eax");

   mem_end=memkb<<20;
   mem=(ULONG*)0x413;
   bse_end=((*mem)&0xFFFF)<<6;

   outb(0x21, irq1);
   outb(0xA1, irq2);
}
i tried compiling that off of the link you gave me
here are the errors

kernel/kernel.c:183: parse error before ':' token
kernel/kernel.c:191: parse error before ':' token
kernel/kernel.c:220: parse error before ':' token
kernel/kernel.c:222: `mem_end' undeclared (first use in this function)
kernel/kernel.c:222: (Each undeclared identifier is reported only once
kernel/kernel.c:222: for each function it appears in.)
kernel/kernel.c:223: `ULONG' undeclared (first use in this function)
kernel/kernel.c:223: parse error before ')' token
kernel/kernel.c:224: `bse_end' undeclared (first use in this function)

the only ones i have problems with are the stuff in the asm(...)
i can work out the rest myself....but am unfamiliar with inline assembly in gcc.
i do understand you put assembly instructions in the asm(...) but all the other symbols confuse me
Tom

Re:amount of memory

Post by Tom »

try getting rid of the "'s with the :: and :'s and getting rid of all the : and :: without the quotes too...
ncsu121978

Re:amount of memory

Post by ncsu121978 »

sorry but i dont really understand what you are trying to say there.....could you just type out those couple of asm lines and how they should look ?
Paul

Re:amount of memory

Post by Paul »

If you are in protected mode, just probe the memory directly.... Start at 0x100000 and write a known byte sequence to memory and try reading it back to see if it changed. Once you can no longer write something and read the same thing back, you must have hit the end of memory. It's good to write two different values to make sure the first value wasn't already there. So like write 0x00ff00ff and then 0xff00ff00 to every dword.

Paul
ncsu121978

Re:amount of memory

Post by ncsu121978 »

ok.....i fixed the errors i mentioned in my previous post
but now the compiler gives me this

kernel/kernel.c:202: can't find a register in class `AREG' while reloading `asm

kernel/kernel.c:209: can't find a register in class `AREG' while reloading `asm

kernel/kernel.c:238: can't find a register in class `AREG' while reloading `asm

and i have no idea what that is
those lines refer to

Code: Select all

   __asm__ __volatile("movl %%cr0, %%eax" : "=a"(cr0) : /* no input registers */ : "eax");

   __asm__ __volatile__("movl %%eax, %%cr0": /* no output registers */ : "a" (cr0 | 0x00000001 | 0x40000000 | 0x20000000) : "eax");


   __asm__ __volatile__("movl %%eax, %%cr0": /* no output registers */ : "a" (cr0) : "eax");

ncsu121978

Re:amount of memory

Post by ncsu121978 »

ok....i got it working using a different example that i found in straight assembly code that i link with my c code
so you guys dont need to answer any more questions about it for me
thanks for all the help thus far
PlayOS

Re:amount of memory

Post by PlayOS »

Would you like to share that code, please.
ncsu121978

Re:amount of memory

Post by ncsu121978 »

certainly

Code: Select all

// in the assembly file
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name:         get_amount_of_ram
; in:         AL = 5
; out:         (nothing)
; modifies:      (nothing)
; minimum CPU:      '386
; notes:      gets the amount of ram on the system
;         void get_amount_of_memory()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EXPORT get_amount_of_ram
   push ebx
   push ecx
   push edx
   push es
   push eax

   mov ax, LINEAR_SEL
   mov es, ax
   xor eax, eax

   cli            ; make SURE interrupts are off
               ; this is only called once on system startup
               ; so interrupts should already be disabled
               ; but this will make SURE
   @loop05:
   add eax, 100000H      ; 1MB
   mov ebx, [es:eax]
   mov edx, ebx
   not ebx
   mov [es:eax], ebx
   mov ecx, [es:eax]
   mov [es:eax], edx
   cmp ebx, ecx
   je @loop05
   mov [_kernel_system_ram], eax   ; _kernel_system_ram points to where you want
               ; the value containing the number of bytes stored

   pop eax
   pop es
   pop edx
   pop ecx
   pop ebx
   ret

// in the calling "C" file
uint kernel_system_ram; // as a global
/***********************************************************
  gets amount of system memory
  done on startup and amount stored in kernel_system_memory
 ***********************************************************/
void kernel_probe_memory()
{
   kernel_system_ram = &kernel_system_ram;
   get_amount_of_ram();
}
at the beginning of the execution of my kernel i call the kernel_probe_memory() function
where i set kernel_system_ram equal to its address is kind of a hack i guess
because the function in assembly stores the number of bytes into the memory location pointed to by kernel_system_ram....so i just make it point to itself so after the function kernel_system_ram is the number of bytes and no longer a pointer to itself. Does that make sense to anyone but me ?
Tim

Re:amount of memory

Post by Tim »

I'm going to go against what the FAQ says, and what the others have been writing in this thread. Direct probing is a bad way to detect memory -- sure, it might tell you how much you have, but arbitrarily writing bytes into memory is bad.

Instead, you should ask the BIOS how much memory is installed, since it is the only piece of software which can interact directly with the motherboard. The best function to call is E820h, and you can do it in your boot loader. See "How do I determine RAM size with BIOS?" in the FAQ.
pskyboy

Re:amount of memory

Post by pskyboy »

Im sorry Tim i disagree.

You are relying on the BIOS having the newer functions in order to be able to tell you how much memory it has and this can not be guaranteed. Also direct probing allows you to know how much memory you can actually get hold off. Ie if you have a dodgy memory chip and it doesn't work the bios might detect it (Depends how teh bios works out memory) where as probing tells you how much you can actually get hold of. Also its much more portable for moving between different platforms a must for my OS.

Peter
User avatar
df
Member
Member
Posts: 1076
Joined: Fri Oct 22, 2004 11:00 pm
Contact:

Re:amount of memory

Post by df »

I also go against direct memory probing ;) those nice PCI cards etc with mapped memory and memory mapped IO ports!!

i use the bios. (well I use grub, which uses the bios).

the next version of the faq (being written) removes the direct probing code. :)
-- Stu --
Tim

Re:amount of memory

Post by Tim »

pskyboy: The BIOS is the ultimate source of information about motherboard devices, memory included. It knows all the backdoor methods of interfacing with the chipset logic. If the BIOS says something, then treat that as correct -- if you can't trust the BIOS then you can't trust the motherboard.

Furthermore, any motherboard capable of using more than 64MB of RAM will support the new interfaces.
K.J.

Re:amount of memory

Post by K.J. »

You are relying on the BIOS having the newer functions in order to be able to tell you how much memory it has and this can not be guaranteed.
I don't think Tim is planning for his OS to run primarrly on Pentiums or 486s.
I also go against direct memory probing those nice PCI cards etc with mapped memory and memory mapped IO ports!!
Yup. Unless your OS is gonna be run on 386/486, PCI memory mapped stuff is rare.

K.J.
Post Reply