Post deleted
Posted: Sat Feb 27, 2021 7:16 am
Post deleted
That's the thing... You cannot access the full 64 bit address space. You can only access 48 bits of it, which means 256 TB (2^48).ngx wrote:I can't really understand how the FFFFFFFF80000000h - FFFFFFFFFFFFFFFF can be addresses if the 48-64 should be copies of 47 that adds only two addresses to the address space(with 48(48-64 as they are all the same) off and with it on)? How can one extra bit that should be the same as 47 add access to full 64-Bit address space
Yes, you have to provide valid addresses and anything between the 2 halves is not a valid address.ngx wrote:And also when I implement VMM should it always set the bits 48-64 if bit 47 is set?
The act of copying bit 47 into positions 48..64 results in what is called a canonical address. Confusing name, I know. But this is the language picked up by Intel to say that the address is valid.ngx wrote:What is are the canonical addresses?
That's wrong. Higher half kernels are mapped at the top of the virtual address space, this has nothing to do with how much RAM you have. The fact that C0000000 virtual address just happens to be at 3G and 32 bit machines can only have 4G (without PAE) is just a coincidence.ngx wrote:My understanding of higher half kernel - it is a kernel that is remapped to a virtual memory region that leaves just enough space to fit the kernel before the end of RAM
Well, it's just a matter of perspective. If you think about address space with signed addresses, where the higher half are actually negative addresses, then you have one region only (-256Tb to +256Tb):ngx wrote:1. What does it mean that it is divided in two halves, what are these halves?
Code: Select all
FFFF8000 00000000 - 00007FFF FFFFFFFFCode: Select all
00000000 00000000 - 00007FFF FFFFFFFF (lower half)
00008000 00000000 - FFFF7FFF FFFFFFFF (not valid)
FFFF8000 00000000 - FFFFFFFF FFFFFFFF (higher half)Because not all the 64 bits are used, only the least significant 39 or 47 bits. The remaining most significant bits must be the same; addresses where those top bits are not all 0s or 1s are in the (not valid) region. With the signed addresses example, those are either less than FFFF8000 00000000 (-256Tb) or bigger than 00007FFF FFFFFFFF (+256Tb).ngx wrote:2. How can halves be 39 and 39 or 47 and 47 if there are only 64 bits available?
An address with all the most significant bits all 0s or 1s. In other words, addresses that are either in the (lower half) or in the (higher half) region, but not in the (not valid) region.ngx wrote:3. What is are the canonical addresses?
You are mixing address space with memory bus size. An address space can be 48 bits wide (with PML4, not using PML5), and it might be expanded further in the future. This means your address space might grow, and the (not valid) region will shrink. If all 64 bits were used, there would be no (not valid) region at all. On the other hand, 56 bit memory bus size won't change, that's an architectural limit, which means you cannot use more physical RAM than that.ngx wrote:4. Where am I wrong with my thoughts about 48/57 bit limitation?
Your question makes no sense from technical point of view. You cannot access anything freely, all memory access goes through the MMU where the virtual address is translated into physical address. And since paging is mandatory in long mode, then yes, you must set up paging tables, but those ain't hacks just normal operation.ngx wrote:1. Can the memory of the so called second half after the FFFF8000 00000000 be accessed freely(just map it to the physical RAM) or do I need to have some address calculation/page table hacks to access it?
You implement a PMM. You probably want to take a look at the big picture.ngx wrote:2. How to I know which page(what entries to use in tables) I should map to be able to access 1 GB starting from this point(start of second half)?
No. Applications can access any address that's mapped in the page table. It is usual to map lower half for user access, and higher half for kernel access only, but page security is completely independent to the addresses.ngx wrote:3. Does the 2 half division mean that the applications would only be able to access the first half ?
It does not grow anywhere. You have a virtual address region you must map, it's completely up to you how you set up the paging tables.ngx wrote:4. Does the 2 half division mean that the higher half kernel will grow upwards, which I think is bad because on other platforms it would grow down?
In that case no special bits.ngx wrote:1. You have probably misunderstood me because I didn't call paging hacks, I just meant that maybe I should do some bit changing or something like that to access the address of the higher half
The virtual address is splited into sign+9+9+9+9+offs bits, which are then used to index the paging tables. Read the Intel or AMD documentations.ngx wrote:2. The PMM gives out the areas of physical memory that I could map the virtual memory to, but I want to know how do I calculate the entry in each table(PML4, PDPT, PDT...) to correspond to the virtual FFFF8000 00000000 address
That's one thing, but you should also set up the security bits in the paging tables to mark pages as supervisor or user page.ngx wrote:3. Here I expressed myself in a wrong way - I meant that how should I handle applications accessing the area, should I somehow make the memory manager not touch this area for the heap, stack...?
That's totally up to you. The MMU does not know about the kernel heap, you are in charge where you put that and to map pages in that region.ngx wrote:4. Actually the kernel grows, as it needs memory for stuff like the PMM bitmap(in my case), maybe drivers... so maybe I should remap the kernel to right the last 2GB of VRAM so that I could put the things I described before under it?
That's not the best way to do it. I'd recommend to link your kernel at it's VMA address, and do not care what the LMA actually is. In long mode you'll use paging, so your code only needs to know about VMA addresses (with the exception of the init code, which maps your kernel in the higher half and jumps to the VMA start address).ngx wrote:Also I wanted to ask about some implementation details
In the tutorials about the higher half kernel I looked at(which were for i686) - they linked the kernel as if it is at the higher half address(0xC000...), but the LMA(load memory addresses) was set to 1MB so the kernel will be loaded there. And when calling/jumping to labels in assembly the assembler would substitute them as if they were to the addresses in the higher half when the kernel is still at 1MB so the 0xC000... was subtracted from every label for calls/jumps/access to the correct addresses
Just a suggestion on my part, but I wouldn't try to cram things into the last part of anything. The 64-bit linear space is huge. Feel free to spread things around.ngx wrote:4. Actually the kernel grows, as it needs memory for stuff like the PMM bitmap(in my case), maybe drivers... so maybe I should remap the kernel to right the last 2GB of VRAM so that I could put the things I described before under it?