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.
MikyBart
Posts: 21 Joined: Tue Sep 03, 2024 9:21 am
Libera.chat IRC: MikyBart
Post
by MikyBart » Fri May 23, 2025 11:40 am
Hi all, I have a problem with limine reading memory blocks, for my kernel in assembly.
In the code block I posted the instruction:
Code: Select all
mov rax, [limine_memmap_request_instance + limine_memmap_request.response]
resets qemu.
I tried other ways but the problem persists.
Code: Select all
BITS 64
struc limine_memmap_request
.id: resq 4
.revision: resq 1
.response: resq 1
endstruc
struc limine_memmap_entry
.base: resq 1
.length: resq 1
.type: resq 1
endstruc
struc limine_memmap_response
.revision: resq 1
.entry_count: resq 1
.entries: resq 1
endstruc
struc pmm_block_info
.base_addr: resq 1
.length: resq 1
endstruc
%define LIMINE_MEMMAP_USABLE 0x0
%define LIMINE_MEMMAP_RESERVED 0x1
%define LIMINE_MEMMAP_ACPI_RECLAIMABLE 0x3
%define LIMINE_MEMMAP_RESERVED_HIBERNATE 0x4
%define LIMINE_MEMMAP_BAD_MEMORY 0x5
%define LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 0x6
%define LIMINE_MEMMAP_KERNEL_AND_MODULES 0x7
%define LIMINE_MEMMAP_FRAMEBUFFER 0x8
SECTION .data
;align 8
limine_memmap_request_instance:
istruc limine_memmap_request
at limine_memmap_request.id, dq 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b, 0x67cf3d9d378a806f, 0xe304acdfc50c3c62
at limine_memmap_request.revision, dq 0
at limine_memmap_request.response, dq 0
iend
SECTION .text
GLOBAL init_physical_memory_manager
init_physical_memory_manager:
push rbp
mov rbp, rsp
mov rax, [limine_memmap_request_instance + limine_memmap_request.response]
.exit_pmm_init:
pop rbp
iansjack
Member
Posts: 4779 Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK
Post
by iansjack » Fri May 23, 2025 12:35 pm
This is only a fragment of code; do you have a link to all of your code right from when the boot manager hands over control, and your limine config file? (Presumably you are using the limine boot manager?)
MikyBart
Posts: 21 Joined: Tue Sep 03, 2024 9:21 am
Libera.chat IRC: MikyBart
Post
by MikyBart » Fri May 23, 2025 1:59 pm
the full code:
Code: Select all
BITS 64
struc limine_memmap_request
.id: resq 4
.revision: resq 1
.response: resq 1
endsstruc
struc limine_memmap_entry
.base: resq 1
.length: resq 1
.type: resq 1
endsstruc
struc limine_memmap_response
.revision: resq 1
.entry_count: resq 1
.entries: resq 1
endsstruc
struc pmm_block_info
.base_addr: resq 1
.length: resq 1
endsstruc
%define LIMINE_MEMMAP_USABLE 0x0
%define LIMINE_MEMMAP_RESERVED 0x1
%define LIMINE_MEMMAP_ACPI_RECLAIMABLE 0x3
%define LIMINE_MEMMAP_RESERVED_HIBERNATE 0x4
%define LIMINE_MEMMAP_BAD_MEMORY 0x5
%define LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 0x6
%define LIMINE_MEMMAP_KERNEL_AND_MODULES 0x7
%define LIMINE_MEMMAP_FRAMEBUFFER 0x8
%define MAX_PMM_BLOCKS 256
%define PMM_BLOCK_INFO_SIZE 16
%define limine_memmap_entry_size 24
section .data
align 8
limine_memmap_request_instance:
istruc limine_memmap_request
at limine_memmap_request.id, dq 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b, 0x67cf3d9d378a806f, 0xe304acdfc50c3c62
at limine_memmap_request.revision, dq 0
at limine_memmap_request.response, dq 0
iend
section .bss
align 8
pmm_usable_blocks:
resb MAX_PMM_BLOCKS * PMM_BLOCK_INFO_SIZE
pmm_usable_block_count:
resq 1
total_usable_memory_bytes:
resq 1
section .text
global init_physical_memory_manager
init_physical_memory_manager:
push rbp
mov rbp, rsp
push rbx
push r12
push r13
push r14
push r15
xor rbx, rbx
xor r15, r15
mov rax, [rel limine_memmap_request_instance + limine_memmap_request.response]
cmp rax, 0
je .error_no_memmap_response
mov r13, [rax + limine_memmap_response.entry_count]
mov r12, [rax + limine_memmap_response.entries]
cmp r13, 0
je .no_memmap_entries
xor r10, r10
.loop_memmap_entries:
cmp r10, r13
jge .end_memmap_scan
mov rax, r10
imul rax, limine_memmap_entry_size
add rax, r12
mov rdi, [rax + limine_memmap_entry.base]
mov rsi, [rax + limine_memmap_entry.length]
mov rdx, [rax + limine_memmap_entry.type]
cmp rdx, LIMINE_MEMMAP_USABLE
jne .skip_block_save
add rbx, rsi
cmp r15, MAX_PMM_BLOCKS
jge .skip_block_save
mov r14, r15
imul r14, PMM_BLOCK_INFO_SIZE
lea r14, [rel pmm_usable_blocks + r14]
mov [r14 + pmm_block_info.base_addr], rdi
mov [r14 + pmm_block_info.length], rsi
inc r15
.skip_block_save:
inc r10
jmp .loop_memmap_entries
.end_memmap_scan:
mov [rel pmm_usable_block_count], r15
mov [rel total_usable_memory_bytes], rbx
jmp .exit_pmm_init
.error_no_memmap_response:
xor r15, r15
xor rbx, rbx
mov [rel pmm_usable_block_count], r15
mov [rel total_usable_memory_bytes], rbx
.no_memmap_entries:
xor r15, r15
xor rbx, rbx
mov [rel pmm_usable_block_count], r15
mov [rel total_usable_memory_bytes], rbx
.exit_pmm_init:
pop r15
pop r14
pop r13
pop r12
pop rbx
pop rbp
ret
iansjack
Member
Posts: 4779 Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK
Post
by iansjack » Fri May 23, 2025 2:48 pm
And when you link your code you are placing it in the upper half of memory?
Octocontrabass
Member
Posts: 5805 Joined: Mon Mar 25, 2013 7:01 pm
Post
by Octocontrabass » Fri May 23, 2025 6:57 pm
MikyBart wrote: ↑ Fri May 23, 2025 11:40 am resets qemu.
Sounds like a triple fault. Run QEMU with "-d int" (and maybe also "-no-reboot") and share the log.
MikyBart
Posts: 21 Joined: Tue Sep 03, 2024 9:21 am
Libera.chat IRC: MikyBart
Post
by MikyBart » Fri May 23, 2025 10:40 pm
Yes, in the upper half of memory
Qemu keeps resetting.
iansjack
Member
Posts: 4779 Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK
Post
by iansjack » Fri May 23, 2025 11:28 pm
As you are running in qemu I would use gdb to single step your code from the entry point. You can then determine exactly where it is faulting and what the machine state is at that point (including the faulting address if it’s a page fault). You might like to first use objdump to produce a disassembly listing to make sure the code is what you think it is.
MikyBart
Posts: 21 Joined: Tue Sep 03, 2024 9:21 am
Libera.chat IRC: MikyBart
Post
by MikyBart » Sat May 31, 2025 1:06 pm
the routine that tries to fetch data from limine is as follows:
Code: Select all
BITS 64
%include "include/macros.inc"
EXTERN debug_msg
GLOBAL get_limine_memory_info
section .data
align 8
limine_hhdm_request:
; ID (4 x uint64_t = 32 bytes totali)
; Offset 0: LIMINE_COMMON_MAGIC_0
; Offset 8: LIMINE_COMMON_MAGIC_1
; Offset 16: LIMINE_HHDM_REQUEST_ID_0
; Offset 24: LIMINE_HHDM_REQUEST_ID_1
dq 0xc7b1dd30df4c8b88
dq 0x0a82e883a194f07b
dq 0x48dcf1cb8ad2b852
dq 0x63984e959a98244b
; Revision (1 x uint64_t = 8 bytes)
; Offset 32
dq 0
; Response pointer (1 x uint64_t* = 8 bytes)
; Offset 40
dq 0
align 8
limine_paging_request:
; ID (4 x uint64_t = 32 bytes totali)
; Offset 0: LIMINE_COMMON_MAGIC_0
; Offset 8: LIMINE_COMMON_MAGIC_1
; Offset 16: LIMINE_PAGING_REQUEST_ID_0
; Offset 24: LIMINE_PAGING_REQUEST_ID_1
dq 0xc7b1dd30df4c8b88
dq 0x0a82e883a194f07b
dq 0x95c1a0edab0944cb
dq 0xa4e5cb3842f7488a
; Revision (1 x uint64_t = 8 bytes)
; Offset 32
dq 0
; Response pointer (1 x uint64_t* = 8 bytes)
; Offset 40
dq 0
align 8
limine_requests_ptr:
dq limine_hhdm_request
dq limine_paging_request
dq 0
debug_msg_hhdm_offset_str: db "HHDM Offset", 13, 10, 0
debug_msg_pml4_addr_str: db "PML4 Address", 13, 10, 0
section .bss
align 8
global_hhdm_offset: resq 1
global_pml4_addr: resq 1
section .text
get_limine_memory_info:
pusha64
mov rdi, limine_hhdm_request
mov rax, [rdi + 40]
mov rax, [rax]
test rax, rax
jz .done_get_memory
mov [global_hhdm_offset], rax
mov rsi, debug_msg_hhdm_offset_str
call debug_msg
mov rdi, limine_paging_request
mov rax, [rdi + 40]
mov rax, [rax]
test rax, rax
jz .done_get_memory
mov [global_pml4_addr], rax
mov rsi, rax
mov rsi, debug_msg_pml4_addr_str
call debug_msg
.done_get_memory:
popa64
ret
and this is the linker script:
Code: Select all
/* Tell the linker that we want an x86_64 ELF64 output file */
OUTPUT_FORMAT(elf64-x86-64)
OUTPUT_ARCH(i386:x86-64)
/* We want the symbol _start to be our entry point */
ENTRY(_start)
/* Define the program headers we want so the bootloader gives us the right */
/* MMU permissions */
PHDRS
{
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
vm_data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
}
SECTIONS
{
/* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
/* and because that is what the Limine spec mandates. */
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
/* that is the beginning of the region. */
. = 0xffffffff80000000;
.text : {
*(.text .text.*)
} :text
/* Move to the next memory page for .rodata */
. += CONSTANT(MAXPAGESIZE);
.rodata : {
*(.rodata .rodata.*)
} :rodata
/* Move to the next memory page for .data */
. += CONSTANT(MAXPAGESIZE);
.data : {
*(.data .data.*)
} :data
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
/* unnecessary zeros will be written to the binary. */
/* If you need, for example, .init_array and .fini_array, those should be placed */
/* above this. */
.bss : {
*(COMMON)
*(.bss .bss.*)
} :data
.vm_data (NOLOAD) : {
*(.vm_data)
}
vm_data_start = .;
vm_data_end = . + SIZEOF(.vm_data);
/* Discard .note.* and .eh_frame since they may cause issues on some hosts. */
/DISCARD/ : {
*(.eh_frame)
*(.note .note.*)
}
}