Page 18 of 20
Re: How to make a GDT?
Posted: Thu Nov 10, 2022 12:21 pm
by zap8600
Octocontrabass wrote:
Limine provides direct access to all memory with either identity mapping or a fixed offset in the higher half. If you're not going to use paging, you can use one of these ranges to access memory and you won't have any page faults unless there's a problem with your code.
How does your OS manage memory without using paging? That's a very unusual design choice.
I'm using this simple
bitmap heap implementation. I'm dumb, so I went with a simple option, one I can understand.
Octocontrabass wrote:
If you want to set up your own paging structures, you would probably need to create all four levels from scratch. In theory you could use Limine's paging structures, but Limine doesn't make any promises about their contents beyond the attributes and address ranges. (Paging structures have 4096-byte alignment.)
Which one is recommended?
Re: How to make a GDT?
Posted: Thu Nov 10, 2022 1:33 pm
by Octocontrabass
That code should never cause page faults. Either you're using it incorrectly or you've found a bug.
It's also not a complete memory manager. You still need some way to keep track of which physical memory is available; userspace won't be able to use the kernel heap.
zap8600 wrote:Which one is recommended?
Setting up your own four-level page structures from scratch. You'll need to do that at some point, unless your OS is meant to follow a very non-traditional design.
Re: How to make a GDT?
Posted: Thu Nov 10, 2022 2:39 pm
by zap8600
Octocontrabass wrote:
That code should never cause page faults. Either you're using it incorrectly or you've found a bug.
It's also not a complete memory manager. You still need some way to keep track of which physical memory is available; userspace won't be able to use the kernel heap.
The page fault happens when I add a block. The starting address is
_kernel_end, which is defined in my linker script.
Octocontrabass wrote:
Setting up your own four-level page structures from scratch. You'll need to do that at some point, unless your OS is meant to follow a very non-traditional design.
I guess I'll do this. Is setting up paging while in long mode any different than setting up paging while in protected mode? I guess I'll also figure out how to make a decent memory manager.
Re: How to make a GDT?
Posted: Thu Nov 10, 2022 3:06 pm
by Octocontrabass
zap8600 wrote:The page fault happens when I add a block. The starting address is _kernel_end, which is defined in my linker script.
Limine doesn't map any memory at that address. Either use the memory map provided by Limine to find some available memory or set up your physical and virtual memory managers before you set up your heap.
zap8600 wrote:Is setting up paging while in long mode any different than setting up paging while in protected mode?
Paging is already enabled, so you just need to set up the structures somewhere in memory and update CR3 to point to your structures instead of Limine's structures.
Re: How to make a GDT?
Posted: Fri Nov 11, 2022 8:16 am
by zap8600
Octocontrabass wrote:
Limine doesn't map any memory at that address. Either use the memory map provided by Limine to find some available memory or set up your physical and virtual memory managers before you set up your heap.
Paging is already enabled, so you just need to set up the structures somewhere in memory and update CR3 to point to your structures instead of Limine's structures.
I think I'll just use Limine's memory map. Does the PMM make pages or does it just allocate memory?
Re: How to make a GDT?
Posted: Fri Nov 11, 2022 3:02 pm
by Octocontrabass
The PMM only allocates physical memory, it doesn't touch the paging structures.
Re: How to make a GDT?
Posted: Wed Nov 16, 2022 12:31 pm
by zap8600
I am now less of an idiot than I once was. I understand how my memory managing system needs to work. The simple bitmap heap implementation I am using allocates virtual memory for the heap. In order to use the memory after the kernel's end, I will need to create a new page table entry. Is this correct?
Re: How to make a GDT?
Posted: Wed Nov 16, 2022 12:50 pm
by Octocontrabass
There is no memory after the kernel's end until you create a new page table entry.
Why does your heap need to go there? Limine has already mapped all physical memory to virtual addresses.
Re: How to make a GDT?
Posted: Thu Dec 01, 2022 8:26 am
by zap8600
Before I continue trying to get a memory manager working, I'm going to switch to using the Multiboot protocol so that my OS can be booted by a variety of bootloaders.
Re: How to make a GDT?
Posted: Thu Dec 01, 2022 11:09 am
by Octocontrabass
Multiboot loads your OS in protected mode, not long mode, so you'll need additional code to switch to long mode.
Re: How to make a GDT?
Posted: Thu Dec 01, 2022 12:06 pm
by kzinti
Switching bootloader is only going to slow you down. But if you like writing bootloaders more than kernels, go for it.
Re: How to make a GDT?
Posted: Tue Dec 13, 2022 12:50 pm
by zap8600
kzinti wrote:Switching bootloader is only going to slow you down. But if you like writing bootloaders more than kernels, go for it.
I'm not switching bootloaders; I'm just switching boot protocols. It also allows me to use my OS with multiple bootloaders.
How do I make a framebuffer with multiboot?
Re: How to make a GDT?
Posted: Tue Dec 13, 2022 1:04 pm
by iansjack
Re: How to make a GDT?
Posted: Tue Dec 13, 2022 1:31 pm
by zap8600
Thanks. I guess I should ask how to jump to long mode from my
boot.S file first.
How do I do that? I think I can use something similar to
this.
Re: How to make a GDT?
Posted: Tue Dec 13, 2022 5:15 pm
by zap8600
Would something like the following be good for a multiboot
boot.S file?
Code: Select all
/* Multiboot 1 header */
.set MB_MAGIC, 0x1BADB002
.set MB_FLAG_PAGE_ALIGN, 1 << 0
.set MB_FLAG_MEMORY_INFO, 1 << 1
.set MB_FLAG_GRAPHICS, 1 << 2
.set MB_FLAG_AOUT, 1 << 16
.set MB_FLAGS, MB_FLAG_PAGE_ALIGN | MB_FLAG_MEMORY_INFO
.set MB_CHECKSUM, -(MB_MAGIC + MB_FLAGS)
/* Multiboot section */
.section .multiboot
.code32
.align 4
multiboot_header:
.long MB_MAGIC
.long MB_FLAGS
.long MB_CHECKSUM
.long multiboot_header /* header_addr */
.long phys /* load_addr */
.long bss_start /* load_end_addr */
.long end /* bss_end_addr */
.long _start
/* Request linear graphics mode */
.long 0x00000000
.long 1024
.long 768
.long 32
.section .stack, "aw", @nobits
stack_bottom:
.skip 16384 /* 16KiB */
.global stack_top
stack_top:
.section .bootstrap
.code32
.align 4
.extern jmp_to_long
.type jmp_to_long, @function
.extern kernel_main
.type kernel_main, @function
.global _start
.type _start, @function
_start:
/* Setup our stack */
mov $stack_top, %esp
/* Make sure our stack is 16-byte aligned */
and $-16, %esp
pushl $0
pushl %esp
pushl $0
pushl %eax /* Multiboot header magic */
pushl $0
pushl %ebx /* Multiboot header pointer */
jmp jmp_to_long
.align 4
jmp_to_long:
/* Set up initial page region, which was zero'd for us by the loader */
mov $0x1000, %edi
mov %edi, %cr3
/* PML4[0] = &PDP[0] | (PRESENT, WRITABLE, USER) */
mov $0x1007, %eax
add %edi, %eax
mov %eax, (%edi)
/* PDP[0] = &PD[0] | (PRESENT, WRITABLE, USER) */
add $0x1000, %edi
mov $0x1003, %eax
add %edi, %eax
mov %eax, (%edi)
/* Set 32 2MiB pages to map 64MiB of low memory temporarily, which should
be enough to get us through our C MMU initialization where we then
use 2MiB pages to map all of the 4GiB standard memory space and map
a much more restricted subset of the kernel in the lower address space. */
add $0x1000, %edi
mov $0x87, %ebx
mov $32, %ecx
.set_entry:
mov %ebx, (%edi)
add $0x200000, %ebx
add $8, %edi
loop .set_entry
/* Enable PAE */
mov %cr4, %eax
or $32, %eax
mov %eax, %cr4
/* EFER */
mov $0xC0000080, %ecx
rdmsr
or $256, %eax
wrmsr
/* Set PG */
mov %cr0, %eax
or $0x80000000, %eax
mov %eax, %cr0
lgdt gdtr
ljmp $0x08,$realm64
.align 8
gdtr:
.word gdt_end-gdt_base
.quad gdt_base
gdt_base:
/* Null */
.quad 0
/* Code */
.word 0
.word 0
.byte 0
.byte 0x9a
.byte 0x20
.byte 0
/* Data */
.word 0xffff
.word 0
.byte 0
.byte 0x92
.byte 0
.byte 0
gdt_end:
.code64
.align 8
.section .bootstrap
realm64:
cli
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
pop %rdi
pop %rsi
pop %rdx
callq kernel_main
halt:
cli
hlt
jmp halt