I have an issue where I think I just misunderstands how this works.
In low-level C code (aka running C code without an OS) I have to create a way for memory to be managed, providing my own malloc function so to say. While writing the algorithm and data structure is relatively straight forward, I am confused on how this should work.
First of all, inside of the codebase I have modified from the os-series repo, they have code doing the following steps in order (see src/impl/x86_64/boot/main.asm):
- Setting up the stack via the esp register in 32 bit mode
- Checking multiboot/cpuid/long_mode availability
- Creating and initializing the page tables (the first whole gigabyte is mapped for the kernel)
- Creating and loading and empty gdt table
- Entering 64 Bit mode / longmode
- Emptying all registers (ax, ss, ds, es, fs, gs) and calling kernel_main (a function written in C)
This setup works, I have a printf implementation and can output data to the screen and so on.
However, since paging is setup, I am already using virtual addresses after step 3. Even though they are mapped without change (e.g. virtual address 0x000...0001234 is mapped to 0x000...0001234), the kernel wont have access after the first gigabyte of memory due to the pagetables not being setup.
Now I am wondering, how I can even address the remaining (lets say if my VM has 4GB RAM) 3 gigs of RAM, when paging is already setup?
Does the kernel typically use a different pagetable or does it even disable paging while its running?
Is my understanding correct, that all code (assembler and C code) is using virtual addresses after step 3?
If so, I can't see how the kernel manages to access and manage and allocate the remaining memory without using some tricks. All access to virtual addresses after the first gigabyte of memory isn't mapped in the page tables and therefore dont return a valid physical address.
Do I need to disable paging while the kernel is being executed?