1) It outputs 2MB pages (i.e. the p_align property of program headers is 2MB), but my elf_x86_64_glidix.sh file in the LD source code says:
Code: Select all
MAXPAGESIZE="0x1000"
COMMONPAGESIZE="0x1000"
Any pointers to what might be wrong?
Code: Select all
MAXPAGESIZE="0x1000"
COMMONPAGESIZE="0x1000"
Oh, thanks for the advice. So where should my kernel preferably be? My memory map is currently:Icee wrote:Well, I suspect that changing the default in gcc/config/i386/i386.opt should suffice but I would strongly discourage you to follow this design of yours. I fail to see any advantage in the memory layout setup your system uses, while there are at least two problems with the large cmodel: (1) you will need more instructions in your binaries and, therefore, more instructions that go through the CPU frontend (which alone will result in measurably larger programs and somewhat slower code); and (2) the register pressure will measurably increase which is a pain for x86-64 where only 16 GPRs (at most, this is without taking into account that RSP, and RBP, and sometimes RBX are special) are available for the optimiser.
TL;DR: don't do it.
Forcing everything below 4GB would make the use of 64-bit architecture pointless.Combuster wrote:Within a 32-bit range, you have 4GB available. You'll want to have all symbols pointing within that region - that means the heap and stack can be anywhere since binaries store no pointers there. You'll also have to assign this 4GB to both the kernel and userspace, otherwise one of the two ends up with the slower code anyway.
The net result is that often 2G is given to the kernel - for everything that's part of it's binaries, and the other 2G to userspace. Any allocations by either can then happen in the remainder of userspace. By the time an application becomes large enough that all code and data sections (libraries included, but not the heap) together are larger than 2G, you already have an exceptional case, and in only that case would it make sense to use mcmodel=large.
You put the kernel at -2GB (-mcmodel=kernel). You put any statically linked userspace binaries in the bottom 2GB.mariuszp wrote:Forcing everything below 4GB would make the use of 64-bit architecture pointless.Combuster wrote:Within a 32-bit range, you have 4GB available. You'll want to have all symbols pointing within that region - that means the heap and stack can be anywhere since binaries store no pointers there. You'll also have to assign this 4GB to both the kernel and userspace, otherwise one of the two ends up with the slower code anyway.
The net result is that often 2G is given to the kernel - for everything that's part of it's binaries, and the other 2G to userspace. Any allocations by either can then happen in the remainder of userspace. By the time an application becomes large enough that all code and data sections (libraries included, but not the heap) together are larger than 2G, you already have an exceptional case, and in only that case would it make sense to use mcmodel=large.
I would encourage you to also think about where everything goes and make a memory map for your kernel before you start. I made the mistake of not doing this step and had a couple of false starts. I also had to do a major memory location do-over once I started considering recursive mapping in the paging tables.Owen wrote:You put the kernel at -2GB (-mcmodel=kernel).
I agree. It would begin something like this:eryjus wrote:I would take the time to make a memory map so you know where everything will live. It might be a living document for a while, but it's better to start with a plan.
mariuszp wrote:Forcing everything below 4GB
Before that, I wrote:have all symbols pointing within that region - that means the heap and stack can be anywhere
I'm quite curious how exactly you would split these things up. Do you have any particular locations for user mode libraries? Or page tables, PL0-stacks, other kernel relevant stuff?Brendan wrote:Of course then you'd split up each area into specific pieces (text, data, bss; shared library area, whatever).
Code: Select all
; The TSS
.TSS_limitLow: dw 0
.TSS_baseLow: dw 0
.TSS_baseMiddle: db 0
.TSS_Access: db 11101001b
.TSS_limitHigh: dw 0
.TSS_baseMiddleHigh: db 0
.TSS_baseHigh: dd 0
dd 0
Code: Select all
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, base=0x00000000, limit=0x00000000, Execute-Only, Non-Conforming, Accessed, 64-bit
GDT[0x02]=Data segment, base=0x00000000, limit=0x00000000, Read-Only, Accessed
GDT[0x03]=Code segment, base=0x0f000000, limit=0x0000ffff, Execute-Only, Non-Conforming, 64-bit
GDT[0x04]=Data segment, base=0x00000000, limit=0x00000000, Read/Write
GDT[0x05]=32-Bit TSS (Available) at 0x001001b0, length 0x000c0
GDT[0x06]=??? descriptor hi=0x000000ff, lo=0xff800000
You can list individual entries with 'info gdt [NUM]' or groups with 'info gdt [NUM] [NUM]'