Memory manager by Memory Map

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
cklie97
Posts: 18
Joined: Tue Apr 19, 2016 2:11 am

Memory manager by Memory Map

Post by cklie97 »

Hello there,
while I tried to make a memory manager I wanted to use the mbs_mmap_* tags of the multiboot structure.
But there is something problematic in it.

While using the folowing code I got a mysterious output.

start.S

Code: Select all

.section multiboot
#define MB_MAGIC 0x1badb002
#define MB_FLAGS 0x0
#define MB_CHECKSUM -(MB_MAGIC + MB_FLAGS)

// Der Multiboot-Header
.align 4
.int    MB_MAGIC
.int    MB_FLAGS
.int    MB_CHECKSUM

.section .text

.extern main

.global _start
_start:
    mov $kernel_stack, %esp

    call main

_stop:
    cli
    hlt

    jmp _stop

.section .bss
.space 8192
kernel_stack:
main.c

Code: Select all

#include "descriptor_tables.h"

static void init(void);

int main(void)
{
    init();
    while(1);
    return 0;
}

static void init(void)
{
    asm volatile("push %ebx");
    init_gdt();
    init_idt();
    asm volatile("pop %ebx");
  clear();
    asm volatile("int $0x30");
}
Annotation: The interrupt 0x30 calls "init_memory" with the ebx as parameter.

memory_manager.c

Code: Select all

#include "memory_manager.h"
#include "console.h"

struct map_entry
{
    uint32_t size;
    uint64_t base_addr;
    uint64_t length;
    uint32_t type;
}__attribute__((packed));

void init_memory(void *pointer)
{
    uint32_t flags;
    uint32_t length;
    struct map_entry *map;

    uint8_t i;

    flags = *(uint32_t *)pointer;
    if(flags | 0x40)
    {
        length = *(uint32_t *)(pointer + 0x2c);
        map = *(struct map_entry **)(pointer + 0x30);
        kprintf("%d\n\r", map->length);
        do
        {
            kprintf("%d\n\r", map->size);
            kprintf("0x%x-0x%x-%d\n\r", map->base_addr, map->length, map->type);
            map++;
            i++;
        }
        while(i<7);
    }
    while(1);
}
Output of "init_memory"

Code: Select all

654336
20
0x0-0x0-654336
20
0x9fc00-0x0-1024
20
0xf0000-0x0-65536
20
0x100000-0x0-133160960
20
0x7ffe000-0x0-8192
20
0xfffc0000-0x0-262144
0
0x0-0x0-0
So there is no "free" ram and every ram block has a size of zero?
User avatar
BASICFreak
Member
Member
Posts: 284
Joined: Fri Jan 16, 2009 8:34 pm
Location: Louisiana, USA

Re: Memory manager by Memory Map

Post by BASICFreak »

You are doing it wrong

Use the multiboot.h's structure, not a hard-codded and wrong offset.

e.g. should be 0x40 not 0x30 for "map" and 0x3C not 0x2C for "length" - there are 15 uint32_ts before mmap_length (if I counted correctly)
So your offsets into multiboot_info_t is off by 0x10 bytes.

Also do not use inline ASM to push and pop a register!
In fact you should have pushed ebx then called main(multiboot_info_t*), it would be in a place the compiler could handle and wouldn't have to rely on "hacks".




Best regards,

B!


P.S. I don't mean for this to come off offensively :wink:
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.
User avatar
Velko
Member
Member
Posts: 153
Joined: Fri Oct 03, 2008 4:13 am
Location: Ogre, Latvia, EU

Re: Memory manager by Memory Map

Post by Velko »

Another probable cause: are you sure your kprintf() handles 64-bit integers correctly?

If it interprets %x as 32-bit, then your second %x will print upper 32-bits from map->base_addr, not lowest from map->length.

Correct format specifier should be %llx, but if your kprintf() is not able to handle that, you may temporary try to down-cast the arguments: (uint32_t)map->base_addr
If something looks overcomplicated, most likely it is.
cklie97
Posts: 18
Joined: Tue Apr 19, 2016 2:11 am

Re: Memory manager by Memory Map

Post by cklie97 »

Velko wrote: Another probable cause: are you sure your kprintf() handles 64-bit integers correctly?

If it interprets %x as 32-bit, then your second %x will print upper 32-bits from map->base_addr, not lowest from map->length.
Thanks. That solved my problem. But in the memory map are several ram blocks missing.
Here is the memory map.

Code: Select all

start_addr  length     resulting_end
0x0         0x9fc00    0x9fc00
0x9fc00     0x400      0xa0000
0xf0000     0x10000    0x100000
0x100000    0x7efe000  0x7ffe000
0x7ffe000   0x2000     0x8000000
0xfffc0000  0x40000    0x0
The missing blocks are

Code: Select all

start_addr  length     resulting_end
0xa0000     0x50000    0xf0000
0x8000000   0xf7fc0000 0xfffc0000
Has anyone an idea why they are missing?
FallenAvatar
Member
Member
Posts: 283
Joined: Mon Jan 03, 2011 6:58 pm

Re: Memory manager by Memory Map

Post by FallenAvatar »

1) Memory need not be contiguous.
2) There is almost always a hole at 0xa0000, it is the memory region reserved for the old graphics modes.

- Monk
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Memory manager by Memory Map

Post by Combuster »

There is "Memory" in RAM and ROM, but not in peripherals. Memory maps can't cover the entire space because the firmware doesn't know how to label all what devices do.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply