Memory allocation in my OS

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.
Post Reply
Khumba

Memory allocation in my OS

Post by Khumba »

Hello. I'm writing a OS (obviously, or else I wouldn't be here), and want to add dynamic memory allocation into it, using extended memory (above FFFF:FFFF). I was wondering if this is possible in real mode, eg. without using registers, just linear addresses, like "mov [0x10FFF0], byte 1". Also, can I use the high memory area (FFFF:000F-FFFF:FFFF) in real mode? Thanks.
Schol-R-LEA

RE:Memory allocation in my OS

Post by Schol-R-LEA »

The answer to the first question is no; you use memory above FFFF:FFFF at all in real mode, with or without segments. Real mode is limited to exact that meory range by definition, as the upper word of the extended address offsets (EIP most importantly) are inaccessible. Segment offsets larger than 64K simply don't exist in real mode.

Now there is the so-called 'flat real mode' or 'unreal mode', which behaves as real mode program except with a single 4G segment space. Since accessing this requires a simplified version of the process needed to set up p-mode (the details can be found at the OSRC web page - see the 'links' page above), and it means losing the memory protection and other advantages of p-mode, it is rarely worth using.

The HMA is a different story. In the original 8088, addresses above FFFF:000F were inaccessible because the CPU itself only had 20 physical address lines (A0-A19). Since, starting with the '286, later CPUs did actually have a 21st address line (A20), it was possible to access that 16K of 'lost' addressable memory.

There's a catch, however. In order to keep the original IBM AT backwards-compatible with the earlier PCs, IBM jury-rigged the memory addressing to hide the A20 line by default, so that programs that depended on the memory space wrapping around at FFFF:000F wouldn't break. Since Backwards Compatibility At Any Cost is the sacred ideal of most PC manufacturers, this design remains enshrined in even the most powerful x86 machines today. Thus, if you ever want to access memory above FFFF:000F, it is neccessary to first perform the A20 Line Activation Ritual. Details of this can also be found at the OSRC web page.
Khumba

RE:Memory allocation in my OS

Post by Khumba »

Thx a lot! Previously I'd found no raw beginner tutorials about P-mode (well, at least that I could understand)
Khumba

Thanks!

Post by Khumba »

Thx a lot! Previously I'd found no raw beginner tutorials about P-mode (well, at least that I could understand)
DeReiter

RE:Memory allocation in my OS

Post by DeReiter »

First of all I woul recommend using Pmode... 2ndly use Linux as you development OS.

BUT HOWEBVR - if you want to access 4GB in your real mode OS... go unreal
GO PMODE and setup a 4GB segment with base 0x0...
then go bck to real and don't clean up.

4GB w00t w00t

But seriously.. stick with pmode
Khumba

RE:Memory allocation in my OS

Post by Khumba »

Thanks, but I've got pmode going already... I'll stick with that.
DeReiter

RE:Memory allocation in my OS

Post by DeReiter »

I just finished setting up a flat GDT (base @ 0x0, limit 4GB) - and I added a timer irq and cpu exceptions.

I want to concentrate now on memory management before I start tasking -
  How would i implement a simple kernel allocator? I looked aroumd and found lots of theory - none of which I understand. besides, the mallocs I found used sbrk or mmap - none of which I havent developed yet (obviously)

How do I implement SBRK?
geezer

RE:Memory allocation in my OS

Post by geezer »

Simple, eh? It doesn't get much simpler than BogoMalloc(TM):

/* end of kernel data segment/BSS, defined in linker script */
extern unsigned char _end[];

unsigned char *break_lvl = _end;

void *kmalloc(size_t size) {
void *rv = break_lvl;
break_lvl += size;
return rv; }

void kfree(void *block) { }

void *krealloc(void *block, size_t size) {
void *rv = break_lvl;
break_lvl += size;
memcpy(rv, block, size);
return rv; }

Obvious improvements to this code are left as an exercise for the reader :)
Post Reply