Page 1 of 3

mmap_addr and mmap_length constant?

Posted: Sun Jun 14, 2015 5:12 pm
by ThisMayWork
I am trying to get memory management to work on my operating system. I have my multiboot info passed to the kernel by my bootloader (data received by int 15h, ax = e881h). After some weird crashes when trying to copy over the mmap to a new location I decided to print both mmap_addr and mmap_length to see their values. Apparently, they both stay the same every time I boot my os. Any idea why that is? Thanks in advance :)

Re: mmap_addr and mmap_length constant?

Posted: Sun Jun 14, 2015 9:02 pm
by Brendan
Hi,
ThisMayWork wrote:I am trying to get memory management to work on my operating system. I have my multiboot info passed to the kernel by my bootloader (data received by int 15h, ax = e881h). After some weird crashes when trying to copy over the mmap to a new location I decided to print both mmap_addr and mmap_length to see their values. Apparently, they both stay the same every time I boot my os. Any idea why that is?
It's because you're reading values from the BIOS's "interrupt vector table" (in the area between 0x00000000 and 0x000000400) and not reading the "mmap_addr" and "mmap_length" fields from the multiboot info structure at all.

My guess is that you're doing something like "address = myStructurePointer->mmap_addr" and your "myStructurePointer" is NULL.


Cheers,

Brendan

Re: mmap_addr and mmap_length constant?

Posted: Mon Jun 15, 2015 3:51 am
by ThisMayWork
Your guess was correct but I still cannot figure out the problem. I accidentally moved the stack pointer and now I have corrected it but the new values are both 0. I think the problem is in the way I pass boot info to my kernel. On my stage 2 bootloader i push the address of the info struct on the stack and jump to stage 3 which is just a "front end" binary, linked to my kernel. All stage 3 does is to call the kernel_entry function. The kernel entry has a bootinfo* as a parameter (which is the exact same struct, but in C code). Either my understanding on how parameters are passed is incorrect or somehow my stack is modified when jumping from stage 2 to stage 3.

P.S. That jump is literally a jump, not a call.

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 5:06 am
by ThisMayWork
Update: Explaining the problem better. After the kernel is loaded i push my multiboot info pointer on the stack. From there, I jump to the first part of the kernel (an assembly file that contains "jmp kernel_main"). kernel_main has a parameter for a multiboot info pointer but apparently it is set to 0 meaning I am not passing it correctly. Any ideas why this might be? If you want me to provide code I will be happy to do so. :)

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 5:15 am
by Brendan
Hi,
ThisMayWork wrote:If you want me to provide code I will be happy to do so. :)
It's impossible to see anything wrong when you can't see anything... ;)


Cheers,

Brendan

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 5:24 am
by ThisMayWork
I was afraid this might turn into "here's the code, solve my problems and port gcc to my os" kind of thing and this definitely not what I am asking for. Here we go...

Code: Select all

;*******************************************************
;
;	Stage3.asm
;		THEMOS Kernel Entry
;       Stage3 is linked against the kernel.
;*******************************************************

;org 	0x100000 

bits	32				; 32 bit code

extern kernel_entry

jmp	Stage3				

%include "paging.inc" 

Stage3:

    call kernel_entry
	;---------------------------------------;
	;   Stop execution			;
	;---------------------------------------;
      
	cli
	hlt

Code: Select all

main:
        ;This is stage 2. The kernel is loaded into memory, we gather memory info and pass it to the kernel.
	;-------------------------------;
	;   Setup segments and stack	;
	;-------------------------------;

	cli				; Clear interrupts
	xor	ax, ax			; Null segments
	mov	ds, ax
	mov	es, ax
	mov	ax, 0x0			; Stack begins at 0x9000-0xffff
	mov	ss, ax
	mov	sp, 0xFFFF
	sti				; Enable interrupts

	mov     	[boot_info+multiboot_info.bootDevice], dl

	;-------------------------------;
	;   Install GDT		;
	;-------------------------------;

	call	InstallGDT		; Install GDT

	;-------------------------------;
	;   Enable A20			;
	;-------------------------------;

	call	EnableA20_KKbrd_Out

	;-------------------------------;
	;   Setup memory info	;
	;-------------------------------;

	xor		eax, eax
	xor		ebx, ebx
	call		BiosGetMemorySize64MB_32bit

	push		eax
	mov		eax, 64
	mul		ebx
	mov		ecx, eax
	pop		eax
	add		eax, ecx
	add		eax, 1024		; the routine doesnt add the KB between 0-1MB; add it

	mov		dword [boot_info+multiboot_info.memoryHi], 0
	mov		dword [boot_info+multiboot_info.memoryLo], eax

	mov		eax, 0x0
	mov		ds, ax
	mov		di, 0x1000
	call		BiosGetMemoryMap

	;-------------------------------;
	;   Print loading message	;
	;-------------------------------;

	mov	si, LoadingMsg
	call	Puts16

        ;-------------------------------;
        ; Initialize filesystem		;
        ;-------------------------------;

	call	LoadRoot		; Load root directory table

        ;-------------------------------;
        ; Load Kernel			;
        ;-------------------------------;

	mov	ebx, 0			; BX:BP points to buffer to load to
    mov	bp, IMAGE_RMODE_BASE
	mov	si, ImageName		; File to load
	call	LoadFile		; Load file
	mov	dword [ImageSize], ecx	; Save size of kernel
	cmp	ax, 0			; Test for success
	je	EnterStage3		; Yep--onto Stage 3!
	mov	si, msgFailure		; Nope--print error
	call	Puts16
	mov	ah, 0
	int     0x16                    ; Await keypress
	int     0x19                    ; Warm boot computer
   	cli				             ; Overkill...
	hlt

	;-------------------------------;
	;   Go into pmode		;
	;-------------------------------;

EnterStage3:

	cli				; Clear interrupts
	mov	eax, cr0		; Set bit 0 in cr0--enter pmode
	or	eax, 1
	mov	cr0, eax
	
	jmp	CODE_DESC:Stage3	; Far jump to fix CS. Code selector is 0x8!

;******************************************************
;	ENTRY POINT FOR STAGE 3
;******************************************************

bits 32

Stage3:

	;-------------------------------;
	;   Set registers		;
	;-------------------------------;

	mov	ax, DATA_DESC	; Set data segments to data selector (0x10)
	mov	ds, ax
	mov	ss, ax
	mov	es, ax
	mov	esp, 90000h		; Stack begins from 90000h

	;-------------------------------;
	; Copy kernel to 1MB		;
	;-------------------------------;

CopyImage:
  	 mov	eax, dword [ImageSize]
  	 movzx	ebx, word [bpbBytesPerSector]
  	 mul	ebx
  	 mov	ebx, 4
  	 div	ebx
   	 cld
   	 mov    esi, IMAGE_RMODE_BASE
   	 mov	edi, IMAGE_PMODE_BASE
   	 mov	ecx, eax
   	 rep	movsd                   ; Copy image to its protected mode address

	;-------------------------------;
	; Push boot info	;
	;-------------------------------;

	push dword boot_info

	;---------------------------------------;
	;   Execute Kernel			;
	;---------------------------------------;

	jmp	CODE_DESC:IMAGE_PMODE_BASE; Jump to kernel! Note: This assumes Kernel's entry point is at 1 MB

	;---------------------------------------;
	;   Stop execution			;
	;---------------------------------------;

	cli
	hlt
The kernel_entry looks like this:

Code: Select all

void kernel_entry(multiboot_info* bootinfo)
{
}
Thanks in advance :)

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 5:26 am
by glauxosdev
Hi,

What do you have in paging.inc ?

Regards,
glauxosdev

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 5:41 am
by ThisMayWork
glauxosdev wrote:Hi,

What do you have in paging.inc ?

Regards,
glauxosdev
Here is paging.inc.

Code: Select all


;*******************************************************
;
;	paging.inc
;		Common Paging Methods
;*******************************************************

%ifndef __PAGING_INC_INCLUDED__
%define __PAGING_INC_INCLUDED__

bits 32

; Read the CR0 register.
global read_cr0
read_cr0:
    mov eax, cr0
    retn

; Write the CR0 register.
global write_cr0
write_cr0:
    push ebp
    mov ebp, esp
    mov eax, [ebp+8]
    mov cr0, eax
    pop ebp
    retn

; Read the CR3 register.
global read_cr3
read_cr3:
    mov eax, cr3
    retn

; Write the CR3 register.
global write_cr3
write_cr3:
    push ebp
    mov ebp, esp
    mov eax, [ebp+8]
    mov cr3, eax
    pop ebp
    retn


%endif

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 5:42 am
by Octocontrabass
I'm no expert on the System V ABI, but I'm pretty sure the compiler expects a return address (or something the same size as a return address) on the stack. :wink:

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 5:45 am
by glauxosdev
It's simpler to do this, instead of doing so many calls that are prone to breakage:

Code: Select all

mov eax, cr0
or eax, 1
mov cr0, eax

mov eax, cr0
or eax, 0x80000000
mov cr0, eax

mov eax, page_directory
mov cr3, eax
Regards,
glauxosdev

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 5:47 am
by ThisMayWork
Octocontrabass wrote:I'm no expert on the System V ABI, but I'm pretty sure the compiler expects a return address (or something the same size as a return address) on the stack. :wink:
I think you are correct, the first item of the stack should be a return address, then the parameters in reverse order, but that still does not explain why it ends up being 0x0. The return address for sure is not 0x0... :?

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 5:49 am
by ThisMayWork
glauxosdev wrote:It's simpler to do this, instead of doing so many calls that are prone to breakage:

Code: Select all

mov eax, cr0
or eax, 1
mov cr0, eax

mov eax, cr0
or eax, 0x80000000
mov cr0, eax

mov eax, page_directory
mov cr3, eax
Regards,
glauxosdev
Indeed, but when I wrote those I meant them to be accessible in the kernel, just in case. My whole code base is poorly written, but apparently it works and until I have time to fully rewrite it I don't feel like touching anything. Just in case it breaks :P

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 5:52 am
by glauxosdev
For goodness sake! Can't you just read and write crx registers with 2-3 instructions? Do you need calls, with 2 additional instructions (call, ret) and additional pushes and pops?

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 5:55 am
by ThisMayWork
If I didn't use calls I would have to use labels and goto, wouldn't I? Otherwise, I would have no way to execute that "part" of code through the kernel without calls.

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 5:57 am
by glauxosdev
(facepalm) Just write is again when needed, it is not that complicated. More instructions you need for pushes and pops, as I said, than for reading or writing to crx registers.