Weird Memory Outputs after Loading Kernel Higher Half
Posted: Sat Nov 11, 2023 6:56 am
Hello, I just loaded my kernel as a higher half one. And every thing works fine, i can able to write VGA buffer, interrupts and exceptions work, except when i dump the memory information my kernel, i get weird outcomes. Here is the screenshot of it:
as you can see in the attachment some uint32_t variables retuns negative outputs and weird characters when i want to print them hexedecimal. I touth this is a simple integer overflow issiue related with my stdio implementations since everything works fine and expected in the kernel but i can't be sure.
I have very simle/generic higher half and memory information code. Here is the related part of the code in my kernel:
loader.asm:
multiboot_util.c (responsible for printing memory information etc.) :
this is my code that responsible for making my kernel higher half and printing the memory information but again im not sure why i am getting the weird outcomes especially when the size of the memory is increases. I think it's related with that how i print the values on screen but i need to ask and get further information why this is happening. Thank you!
as you can see in the attachment some uint32_t variables retuns negative outputs and weird characters when i want to print them hexedecimal. I touth this is a simple integer overflow issiue related with my stdio implementations since everything works fine and expected in the kernel but i can't be sure.
I have very simle/generic higher half and memory information code. Here is the related part of the code in my kernel:
loader.asm:
Code: Select all
[BITS 32]
global loader ; the entry point for the linker
global boot_page_directory
extern kernel_main ; kmain is defined in kmain.c
extern end_of_kernel
extern kernel_virtual_end ; these are defined in the link script
extern kernel_virtual_start
extern kernel_physical_end
extern kernel_physical_start
; setting up the multiboot headers for GRUB
MODULEALIGN equ 1<<0 ; align loaded modules on page
; boundaries
MEMINFO equ 1<<1 ; provide memory map
FLAGS equ MODULEALIGN | MEMINFO ; the multiboot flag field
MAGIC equ 0x1BADB002 ; magic number for bootloader to
; find the header
CHECKSUM equ -(MAGIC + FLAGS) ; checksum required
; paging for the kernel
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; we start at 3GB
KERNEL_PAGE_IDX equ (KERNEL_VIRTUAL_BASE >> 22) ; PDT index for 4MB PDE
; the page directory used to boot the kernel into the higher half
section .data
align 4096 ; align on 4kB blocks
boot_page_directory:
dd 00000000000000000000000010001011b ; identity mapped first 4MB
times (KERNEL_PAGE_IDX-1) dd 0 ; no pages here
dd 00000000000000000000000010001011b ; map 0xC0000000 to the first 4MB
times (1024-KERNEL_PAGE_IDX-1) dd 0 ; no more pages
section .text
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM
; the entry point, called by GRUB
loader:
mov ecx, (boot_page_directory-KERNEL_VIRTUAL_BASE)
and ecx, 0xFFFFF000 ; we only care about the upper 20 bits
or ecx, 0x08 ; PWT, enable page write through?
mov cr3, ecx ; load pdt
mov ecx, cr4 ; read current config from cr4
or ecx, 0x00000010 ; set bit enabling 4MB pages
mov cr4, ecx ; enable it by writing to cr4
mov ecx, cr0 ; read current config from cr0
or ecx, 0x80000000 ; the highest bit controls paging
mov cr0, ecx ; enable paging by writing config to cr0
lea ecx, [higher_half] ; store the address higher_half in ecx
jmp ecx ; now we jump into 0xC0100000
; code executing from here on uses the page table, and is accessed through
; the upper half, 0xC0100000
higher_half:
mov DWORD [boot_page_directory], 0 ; erase identity mapping of kernel
invlpg [0] ; and flush any tlb-references to it
mov esp, stack+STACKSIZE ; sets up the stack pointer
push boot_page_directory
push kernel_virtual_end ; these are used by kmain, see
push kernel_virtual_start ; kernel_limits_t in kmain.c
push kernel_physical_end
push kernel_physical_start
push eax ; eax contains the MAGIC number
push ebx ; ebx contains the multiboot data
; structure
call kernel_main ; call the main function of the kernel
hang:
jmp hang ; loop forever
; reserve initial stack space
STACKSIZE equ 0x4000 ; 16kB
section .bss
align 4
stack:
resb STACKSIZE ; reserve memory for stack on
; doubleworded memory
Code: Select all
void display_memory_info(multiboot_info_t *mbinfo,
kernel_mem_limits_t *kmlimits)
{
qemu_write_string("\n%s %s START\n", DEBUG_OUTPUT, MEMORY_OUTPUT);
/* From the GRUB multiboot manual section 3.3 boot information format
* If flags[0] is set, then the fields mem_lower and mem_upper can be
* accessed.
* If flags[6] is set, then the fields mmap_length and mmap_addr can be
* accessed, which contains a complete memory map.
*/
if (mbinfo->flags & 0x00000001) {
qemu_write_string("%s Size of the lower memory: %d kB\n",
INFORMATION_OUTPUT, mbinfo->mem_lower);
qemu_write_string("%s Size of the upper memory: %d kB\n",
INFORMATION_OUTPUT, mbinfo->mem_upper);
}
if (mbinfo->flags & 0x00000020) {
multiboot_memory_map_t *entry =
(multiboot_memory_map_t *)mbinfo->mmap_addr;
while ((uint32_t)entry <
mbinfo->mmap_addr + mbinfo->mmap_length) {
if (entry->type == MULTIBOOT_MEMORY_AVAILABLE) {
qemu_write_string("%s Avaliable memory: ",
INFORMATION_OUTPUT);
} else {
qemu_write_string("%s Reserved memory: ",
INFORMATION_OUTPUT);
}
/*
* FIX: lld needed, %d overflows
*/
qemu_write_string("address: %d", (uint32_t)entry->addr);
qemu_write_string(", length: %d\n",
(uint32_t)entry->len);
entry = (multiboot_memory_map_t *)(((uint32_t)entry) +
entry->size +
sizeof(entry->size));
}
}
qemu_write_string("%s Kernel physical start: 0x%x\n",
INFORMATION_OUTPUT, kmlimits->kernel_physical_start);
qemu_write_string("%s Kernel physical end: 0x%x\n", INFORMATION_OUTPUT,
kmlimits->kernel_physical_end);
qemu_write_string("%s Kernel virtual start: 0x%x\n", INFORMATION_OUTPUT,
kmlimits->kernel_virtual_start);
qemu_write_string("%s Kernel virtual end: 0x%x\n", INFORMATION_OUTPUT,
kmlimits->kernel_virtual_end);
qemu_write_string("%s %s END\n\n", DEBUG_OUTPUT, MEMORY_OUTPUT);
}