Page 3 of 4

Re: Page Fault and General Protection Fault

Posted: Fri Feb 11, 2022 6:19 pm
by 22OsC
Octocontrabass wrote:
22OsC wrote:After a few tweaks the only Page Fault I get now is CR2=0000000000900041.
You might be using a physical address somewhere instead of a virtual address. (This is why it's a good idea to use uintptr_t for physical addresses instead of a pointer.)
22OsC wrote:I made the mapping be similar as possible.
Since I can't see your current code, all I have for reference is your earlier code where you definitely were not setting up the HHDM area the same way the bootloader did.
22OsC wrote:Where I should place my heap then? Sorry if I sound stupid but I'm not sure where I can place it. The heap can be anywhere? Like I don't have to use a canonical address or stuff like that?
You can pick any canonical address that isn't already being used for something else. Make sure there's enough unused virtual address space for your heap to grow.

If you don't want a HHDM area, you don't need to have one, but it means it'll be harder to access arbitrary physical addresses.
well... I did what I could, this is the PML4
Image
i see that "info mem" it's different, I must have it the same?

and also my uintptr_t implementation is

Code: Select all

typedef unsigned long int uintptr_t;
in stdint.h is like this but on some forums it was void* and I'm not sure if it's right.

Re: Page Fault and General Protection Fault

Posted: Fri Feb 11, 2022 6:47 pm
by Octocontrabass
22OsC wrote:i see that "info mem" it's different, I must have it the same?
The only differences are the page R/W/X attributes. Making it the same will improve security and maybe help catch bugs, but it will work fine the way it is now.
22OsC wrote:and also my uintptr_t implementation is

Code: Select all

typedef unsigned long int uintptr_t;
in stdint.h is like this but on some forums it was void* and I'm not sure if it's right.
You should use the stdint.h provided by your cross-compiler instead of trying to implement your own.

It doesn't really make a difference whether you use uintptr_t or void*, but it's easier to keep physical and virtual addresses separate if physical addresses are always uintptr_t and virtual addresses are always void*.

Re: Page Fault and General Protection Fault

Posted: Fri Feb 11, 2022 7:07 pm
by 22OsC
Octocontrabass wrote:
22OsC wrote:i see that "info mem" it's different, I must have it the same?
The only differences are the page R/W/X attributes. Making it the same will improve security and maybe help catch bugs, but it will work fine the way it is now.
22OsC wrote:and also my uintptr_t implementation is

Code: Select all

typedef unsigned long int uintptr_t;
in stdint.h is like this but on some forums it was void* and I'm not sure if it's right.
You should use the stdint.h provided by your cross-compiler instead of trying to implement your own.

It doesn't really make a difference whether you use uintptr_t or void*, but it's easier to keep physical and virtual addresses separate if physical addresses are always uintptr_t and virtual addresses are always void*.
For now I won't add any page attributes only the required ones, but I mentioned earlier the problem that I have now:
22OsC wrote:I made the mapping be similar as possible. I did the kernel mapping the same as how bootloader did but, the CR2 address is 0000000000900041. And this is happening after I changed the PML4 in bitmap get function. Before this, it wasn't a problem. Do I have to re-initialize the bitmap after applying the new PML4?
if the problem is not about re-initializing the bitmap, then the bitmap initialization is broken (maybe?)

the bitmap initialization code is:

Code: Select all

void PageFrameAllocator::ReadMemoryMap()
{
    void *LargestFreeMemorySegment = NULL;
    size_t LargestFreeMemorySegmentSize = 0;
    for (int i = 0; i < bootparams.mem.Entries; i++)
    {
        if (bootparams.mem.memmap[i].Type == GBP_Free)
        {
            if (bootparams.mem.memmap[i].Pages * 4096 > LargestFreeMemorySegmentSize)
            {
                LargestFreeMemorySegment = (void *)bootparams.mem.memmap[i].PhysicalAddress;
                LargestFreeMemorySegmentSize = bootparams.mem.memmap[i].Pages * 4096;
            }
        }
    }
    uint64_t MemorySize = GetMemorySize(bootparams.mem);
    FreeMemory = MemorySize;
    uint64_t BitmapSize = ALIGN_UP((MemorySize / 0x1000) / 8, 0x1000);
    InitBitmap(BitmapSize, LargestFreeMemorySegment);
    ReservePages(0, MemorySize / 4096 + 1);
    for (int i = 0; i < bootparams.mem.Entries; i++)
    {
        if (bootparams.mem.memmap[i].Type == GBP_Free)
        {
            UnreservePages((void *)bootparams.mem.memmap[i].PhysicalAddress, bootparams.mem.memmap[i].Pages);
        }
    }
    ReservePages(0, 0x100);
    LockPages(PageBitmap.Buffer, PageBitmap.Size / 4096 + 1);
}

void PageFrameAllocator::InitBitmap(size_t BitmapSize, void *BufferAddress)
{
    PageBitmap.Size = BitmapSize;
    PageBitmap.Buffer = (uint8_t *)BufferAddress;
    for (int i = 0; i < BitmapSize; i++)
    {
        *(uint8_t *)(PageBitmap.Buffer + i) = 0;
    }
}
and requesting a page function:

Code: Select all

void *PageFrameAllocator::RequestPage()
{
    for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
    {
        if (PageBitmap[PageBitmapIndex] == true)
            continue;
        LockPage((void *)(PageBitmapIndex * 4096));
        return (void *)(PageBitmapIndex * 4096);
    }
    return NULL;
}
the rest of the code is the same as here:
vmm.cpp
vmm.h
pmm.cpp
pmm.h
(same links from the previous reply)

Re: Page Fault and General Protection Fault

Posted: Fri Feb 11, 2022 7:42 pm
by Octocontrabass
22OsC wrote:

Code: Select all

LargestFreeMemorySegment = (void *)bootparams.mem.memmap[i].PhysicalAddress;
...
InitBitmap(BitmapSize, LargestFreeMemorySegment);
...
void PageFrameAllocator::InitBitmap(size_t BitmapSize, void *BufferAddress)
{
    PageBitmap.Size = BitmapSize;
    PageBitmap.Buffer = (uint8_t *)BufferAddress;
    for (int i = 0; i < BitmapSize; i++)
    {
        *(uint8_t *)(PageBitmap.Buffer + i) = 0;
    }
}
Only pointers to virtual addresses can be dereferenced.

Since you have a HHDM area, you can translate that physical address to a virtual address very easily.

Re: Page Fault and General Protection Fault

Posted: Fri Feb 11, 2022 7:49 pm
by Ethin
Octocontrabass wrote:
Ethin wrote:So I have absolutely no idea how to catch Limine altering CR3 or anything because I'll always end up catching the firmware doing it first.
Hold on, back up. Why are you trying to catch Limine altering CR3? The triple fault is happening after Limine hands control to your kernel, isn't it?
Yes, it is. I was trying to determine if my page tables changed after my kernel booted, because they shouldn't be changing, and if they are, that would explain the triple fault. But even if that test yields nothing, it still doesn't resolve my initial problem of GDB hardware breakpoints not functioning.

Re: Page Fault and General Protection Fault

Posted: Fri Feb 11, 2022 9:03 pm
by Octocontrabass
Ethin wrote:I was trying to determine if my page tables changed after my kernel booted, because they shouldn't be changing, and if they are, that would explain the triple fault.
I would expect memory corruption before a stray write to CR3. Have you tried using "info registers" or "info mem" in the QEMU console after the CPU triple faults? (Or disabling KVM acceleration so QEMU will provide accurate exception logs.)
Ethin wrote:But even if that test yields nothing, it still doesn't resolve my initial problem of GDB hardware breakpoints not functioning.
This might be due to KVM acceleration, or it might be a QEMU/GDB bug where hardware breakpoints have to be set in long mode if you want the CPU to hit them in long mode.

Re: Page Fault and General Protection Fault

Posted: Fri Feb 11, 2022 10:45 pm
by Ethin
Octocontrabass wrote:
Ethin wrote:I was trying to determine if my page tables changed after my kernel booted, because they shouldn't be changing, and if they are, that would explain the triple fault.
I would expect memory corruption before a stray write to CR3. Have you tried using "info registers" or "info mem" in the QEMU console after the CPU triple faults? (Or disabling KVM acceleration so QEMU will provide accurate exception logs.)
I just did. Here's what Qemu says:
info registers:

Code: Select all

RAX=0000000000060020 RBX=ffffffffc209b0b0 RCX=ffffffffc202e408 RDX=0000000000000025
RSI=ff0000007ff4e018 RDI=ffffffffc203b008 RBP=ffffffffc1fe372f RSP=ffffffffc1f8572f
R8 =ffffffffc2024087 R9 =0000000000000001 R10=00000000000003f8 R11=0000000000003020
R12=0000000000000000 R13=ff0000007ff4e000 R14=ffffffffc2023890 R15=0000000000000000
RIP=ffffffffc1fd3f83 RFL=00000082 [--S----] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
CS =0008 0000000000000000 ffffffff 00af9b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
DS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
FS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
GS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0010 ffffffffc202e5e1 00000067 00008900 DPL=0 TSS64-avl
GDT=     ffffffffc202e650 0000001f
IDT=     ffffffffc202f050 00000fff
CR0=80000011 CR2=ffffffffc1f85737 CR3=0000000078521000 CR4=00001020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
EFER=0000000000000d00
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=0000000000000000 0000000000000000 XMM01=0000000000000000 0000000000000000
XMM02=0000000000000000 0000000000000000 XMM03=0000000000000000 0000000000000000
XMM04=0000000000000000 0000000000000000 XMM05=0000000000000000 0000000000000000
XMM06=0000000000000000 0000000000000000 XMM07=0000000000000000 0000000000000000
XMM08=0000000000000000 0000000000000000 XMM09=0000000000000000 0000000000000000
XMM10=0000000000000000 0000000000000000 XMM11=0000000000000000 0000000000000000
XMM12=0000000000000000 0000000000000000 XMM13=0000000000000000 0000000000000000
XMM14=0000000000000000 0000000000000000 XMM15=0000000000000000 0000000000000000
For some reason, info mem returns nothing -- it waits for a while, maxes out my CPU for a bit and then returns me to the qemu monitor.
Octocontrabass wrote:
Ethin wrote:But even if that test yields nothing, it still doesn't resolve my initial problem of GDB hardware breakpoints not functioning.
This might be due to KVM acceleration, or it might be a QEMU/GDB bug where hardware breakpoints have to be set in long mode if you want the CPU to hit them in long mode.
For reference, the interrupt dump is as follows:

Code: Select all

check_exception old: 0xffffffff new 0xe
  1678: v=0e e=0000 i=0 cpl=0 IP=0008:ffffffffc1fd3f83 pc=ffffffffc1fd3f83 SP=0030:ffffffffc1f8572f CR2=ffffffffc1f85737
RAX=0000000000060020 RBX=ffffffffc209b0b0 RCX=ffffffffc202e408 RDX=0000000000000025
RSI=ff0000007ff4e018 RDI=ffffffffc203b008 RBP=ffffffffc1fe372f RSP=ffffffffc1f8572f
R8 =ffffffffc2024087 R9 =0000000000000001 R10=00000000000003f8 R11=0000000000003020
R12=0000000000000000 R13=ff0000007ff4e000 R14=ffffffffc2023890 R15=0000000000000000
RIP=ffffffffc1fd3f83 RFL=00000082 [--S----] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
CS =0008 0000000000000000 ffffffff 00af9b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
DS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
FS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
GS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0010 ffffffffc202e5e1 00000067 00008900 DPL=0 TSS64-avl
GDT=     ffffffffc202e650 0000001f
IDT=     ffffffffc202f050 00000fff
CR0=80000011 CR2=ffffffffc1f85737 CR3=0000000078521000 CR4=00001020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000001000 CCD=ffffffffc1f8572f CCO=SUBQ
EFER=0000000000000d00
check_exception old: 0xe new 0xd
  1679: v=08 e=0000 i=0 cpl=0 IP=0008:ffffffffc1fd3f83 pc=ffffffffc1fd3f83 SP=0030:ffffffffc1f8572f env->regs[R_EAX]=0000000000060020
RAX=0000000000060020 RBX=ffffffffc209b0b0 RCX=ffffffffc202e408 RDX=0000000000000025
RSI=ff0000007ff4e018 RDI=ffffffffc203b008 RBP=ffffffffc1fe372f RSP=ffffffffc1f8572f
R8 =ffffffffc2024087 R9 =0000000000000001 R10=00000000000003f8 R11=0000000000003020
R12=0000000000000000 R13=ff0000007ff4e000 R14=ffffffffc2023890 R15=0000000000000000
RIP=ffffffffc1fd3f83 RFL=00000082 [--S----] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
CS =0008 0000000000000000 ffffffff 00af9b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
DS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
FS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
GS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0010 ffffffffc202e5e1 00000067 00008900 DPL=0 TSS64-avl
GDT=     ffffffffc202e650 0000001f
IDT=     ffffffffc202f050 00000fff
CR0=80000011 CR2=ffffffffc1f85737 CR3=0000000078521000 CR4=00001020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000001000 CCD=ffffffffc1f8572f CCO=SUBQ
EFER=0000000000000d00
check_exception old: 0x8 new 0xd
And my limine configuration:

Code: Select all

TIMEOUT=0
DEFAULT_ENTRY=1
GRAPHICS=yes
MENU_FONT_SCALE=2x2
EDITOR_ENABLED=no
VERBOSE=yes
RANDOMIZE_MEMORY=yes
:Kernel
PROTOCOL=stivale2
KASLR=yes
KERNEL_PATH=boot:///EFI/BOOT/kernel

Re: Page Fault and General Protection Fault

Posted: Fri Feb 11, 2022 11:15 pm
by Octocontrabass
Ethin wrote:For some reason, info mem returns nothing -- it waits for a while, maxes out my CPU for a bit and then returns me to the qemu monitor.
Does "info tlb" do the same thing? It sounds an awful lot like you've zero-filled your page tables.

Where is your stack, how big is it, and why isn't it aligned correctly?

Re: Page Fault and General Protection Fault

Posted: Fri Feb 11, 2022 11:29 pm
by Ethin
Octocontrabass wrote:
Ethin wrote:For some reason, info mem returns nothing -- it waits for a while, maxes out my CPU for a bit and then returns me to the qemu monitor.
Does "info tlb" do the same thing? It sounds an awful lot like you've zero-filled your page tables.

Where is your stack, how big is it, and why isn't it aligned correctly?
The "info tlb" command doesn't do the same thing; it returns a fully populated TLB with over 2000 entries. I followed the stivale bear bones for declaring the stack, so I have it declared like so:

Code: Select all

const MAX_STACK_SIZE: usize = 1024 * 256;
static STACK: [u8; MAX_STACK_SIZE] = [0; MAX_STACK_SIZE];
I can't apply the repr attribute to specify an alignment of a raw array. I could put it in a struct, and align it that way.
Edit: just redeclared the stack like so:

Code: Select all

#[repr(C, align(4))]
struct Stack([u8; MAX_STACK_SIZE]);
static STACK: Stack = Stack([0; MAX_STACK_SIZE]);

Re: Page Fault and General Protection Fault

Posted: Fri Feb 11, 2022 11:42 pm
by Octocontrabass
What is the address of your STACK array? What is the stack address in your Stivale2 header? The addresses in your register dump look a bit funny, and I'm not talking about the alignment.

Re: Page Fault and General Protection Fault

Posted: Sat Feb 12, 2022 4:19 am
by Ethin
Octocontrabass wrote:What is the address of your STACK array? What is the stack address in your Stivale2 header? The addresses in your register dump look a bit funny, and I'm not talking about the alignment.
So I told my kernel to print the location of STACK.0, STACK, and the stack in the header. All of them are at FFFFFFFF99100A50h this run (they change every time the kernel boots as a part of KASLR).

Re: Page Fault and General Protection Fault

Posted: Sat Feb 12, 2022 8:44 am
by 22OsC
Octocontrabass wrote:
22OsC wrote:

Code: Select all

LargestFreeMemorySegment = (void *)bootparams.mem.memmap[i].PhysicalAddress;
...
InitBitmap(BitmapSize, LargestFreeMemorySegment);
...
void PageFrameAllocator::InitBitmap(size_t BitmapSize, void *BufferAddress)
{
    PageBitmap.Size = BitmapSize;
    PageBitmap.Buffer = (uint8_t *)BufferAddress;
    for (int i = 0; i < BitmapSize; i++)
    {
        *(uint8_t *)(PageBitmap.Buffer + i) = 0;
    }
}
Only pointers to virtual addresses can be dereferenced.

Since you have a HHDM area, you can translate that physical address to a virtual address very easily.
I think I found the problem, the Bitmap buffer address is not a present page. #-o

Re: Page Fault and General Protection Fault

Posted: Sat Feb 12, 2022 4:22 pm
by Octocontrabass
Ethin wrote:So I told my kernel to print the location of STACK.0, STACK, and the stack in the header. All of them are at FFFFFFFF99100A50h this run (they change every time the kernel boots as a part of KASLR).
If it changes every time, then I can't compare it to the addresses in the earlier QEMU log to see if your stack has overflowed and overwritten your kernel.

However, if you really do have the address of the bottom of the stack in your stivale2 header instead of the address of the top of your stack, then the stack is definitely overwriting your kernel.

Re: Page Fault and General Protection Fault

Posted: Sat Feb 12, 2022 4:44 pm
by Ethin
Octocontrabass wrote:
Ethin wrote:So I told my kernel to print the location of STACK.0, STACK, and the stack in the header. All of them are at FFFFFFFF99100A50h this run (they change every time the kernel boots as a part of KASLR).
If it changes every time, then I can't compare it to the addresses in the earlier QEMU log to see if your stack has overflowed and overwritten your kernel.

However, if you really do have the address of the bottom of the stack in your stivale2 header instead of the address of the top of your stack, then the stack is definitely overwriting your kernel.
Damn, I didn't think of that. As a sample run, I changed it to this:

Code: Select all

#[link_section = ".stivale2hdr"]
#[used]
static BOOT_LOADER_HEADER: StivaleHeader = StivaleHeader::new()
    .stack(&STACK.0[MAX_STACK_SIZE - 1] as *const u8)
    .flags(0x1E)
    .tags(&FB_TAG as *const StivaleFramebufferHeaderTag as *const ());
And then I had it (once again) print stack information. The information plus exception and register info is as follows:
Stack locations: bottom: 0xffffffffb9920a50, top: 0xFFFFFFFFB9960A4F
Registers:
RAX=0000000000000000 RBX=ff0000007ff4e018 RCX=0000000000009f0d RDX=ffffffffb99008e7
RSI=0000000000000000 RDI=ffffffffb9911087 RBP=ffffffffb99d8300 RSP=ffffffffb99008c7
R8 =ffffffffb9961267 R9 =0000000000000001 R10=00000000000003f8 R11=0000000000000020
R12=ff0000007ff4e000 R13=0000000000000000 R14=ffffffffb9978258 R15=0000000000000025
RIP=ffffffffb9911081 RFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
CS =0008 0000000000000000 ffffffff 00af9b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
DS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
FS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
GS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0010 ffffffffb996b829 00000067 00008900 DPL=0 TSS64-avl
GDT= ffffffffb996b898 0000001f
IDT= ffffffffb996c2a0 00000fff
CR0=80000011 CR2=0000000000000000 CR3=000000007851d000 CR4=00001020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
EFER=0000000000000d00
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=0000000000000000 0000000000000000 XMM01=0000000000000000 0000000000000000
XMM02=0000000000000000 0000000000000000 XMM03=0000000000000000 0000000000000000
XMM04=0000000000000000 0000000000000000 XMM05=0000000000000000 0000000000000000
XMM06=0000000000000000 0000000000000000 XMM07=0000000000000000 0000000000000000
XMM08=0000000000000000 0000000000000000 XMM09=0000000000000000 0000000000000000
XMM10=0000000000000000 0000000000000000 XMM11=0000000000000000 0000000000000000
XMM12=0000000000000000 0000000000000000 XMM13=0000000000000000 0000000000000000
XMM14=0000000000000000 0000000000000000 XMM15=0000000000000000 0000000000000000
Exception dump:
check_exception old: 0xffffffff new 0xe
1692: v=0e e=0000 i=0 cpl=0 IP=0008:ffffffffb9911081 pc=ffffffffb9911081 SP=0030:ffffffffb99008c7 CR2=0000000000000000
RAX=0000000000000000 RBX=ff0000007ff4e018 RCX=0000000000009f0d RDX=ffffffffb99008e7
RSI=0000000000000000 RDI=ffffffffb9911087 RBP=ffffffffb99d8300 RSP=ffffffffb99008c7
R8 =ffffffffb9961267 R9 =0000000000000001 R10=00000000000003f8 R11=0000000000000020
R12=ff0000007ff4e000 R13=0000000000000000 R14=ffffffffb9978258 R15=0000000000000025
RIP=ffffffffb9911081 RFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
CS =0008 0000000000000000 ffffffff 00af9b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
DS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
FS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
GS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0010 ffffffffb996b829 00000067 00008900 DPL=0 TSS64-avl
GDT= ffffffffb996b898 0000001f
IDT= ffffffffb996c2a0 00000fff
CR0=80000011 CR2=0000000000000000 CR3=000000007851d000 CR4=00001020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000000 CCD=000000000000c001 CCO=EFLAGS
EFER=0000000000000d00
check_exception old: 0xe new 0xd
1693: v=08 e=0000 i=0 cpl=0 IP=0008:ffffffffb9911081 pc=ffffffffb9911081 SP=0030:ffffffffb99008c7 env->regs[R_EAX]=0000000000000000
RAX=0000000000000000 RBX=ff0000007ff4e018 RCX=0000000000009f0d RDX=ffffffffb99008e7
RSI=0000000000000000 RDI=ffffffffb9911087 RBP=ffffffffb99d8300 RSP=ffffffffb99008c7
R8 =ffffffffb9961267 R9 =0000000000000001 R10=00000000000003f8 R11=0000000000000020
R12=ff0000007ff4e000 R13=0000000000000000 R14=ffffffffb9978258 R15=0000000000000025
RIP=ffffffffb9911081 RFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
CS =0008 0000000000000000 ffffffff 00af9b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
DS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
FS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
GS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0010 ffffffffb996b829 00000067 00008900 DPL=0 TSS64-avl
GDT= ffffffffb996b898 0000001f
IDT= ffffffffb996c2a0 00000fff
CR0=80000011 CR2=0000000000000000 CR3=000000007851d000 CR4=00001020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000000 CCD=000000000000c001 CCO=EFLAGS
EFER=0000000000000d00
check_exception old: 0x8 new 0xd
The odd thing is that I (think) that ffffffffb99008c7h is beyond my stack, and I don't understand why. I've even reserved it properly in my linker script (I think):

Code: Select all

OUTPUT_FORMAT(elf64-x86-64)
OUTPUT_ARCH(i386:x86-64)

ENTRY(_start)

/* Define the program headers we want so the bootloader gives us the right */
/* MMU permissions */
PHDRS
{
    null    PT_NULL    FLAGS(0);
    text    PT_LOAD    FLAGS(0x5);
    rodata  PT_LOAD    FLAGS(0x4);
    data    PT_LOAD    FLAGS(0x6);
}

SECTIONS
{
    /* We wanna be placed in the topmost 2GiB of the address space, for optimizations */
    /* and because that is what the stivale2 spec mandates. */
    . = 0xffffffff80000000;

    .text : {
        *(.text .text.*)
    } :text

    /* Move to the next memory page for .rodata */
    . += CONSTANT(MAXPAGESIZE);

    /* We place the .stivale2hdr section containing the header in its own section, */
    /* and we use the KEEP directive on it to make sure it doesn't get discarded. */
    .stivale2hdr : {
        KEEP(*(.stivale2hdr))
    } :rodata

    .rodata : {
        *(.rodata .rodata.*)
    } :rodata

    /* Move to the next memory page for .data */
    . += CONSTANT(MAXPAGESIZE);

    .data : {
        *(.data .data.*)
    } :data

    .bss : {
        *(COMMON)
        *(.bss .bss.*)
    } :data
}

Re: Page Fault and General Protection Fault

Posted: Sat Feb 12, 2022 5:31 pm
by Octocontrabass
Ethin wrote:

Code: Select all

    .stack(&STACK.0[MAX_STACK_SIZE - 1] as *const u8)
Subtracting 1 results in a value that's 1 below what you should use for the stack pointer, and misaligns your stack. I don't know if Rust allows pointers past the end of an array the way C does, but that's basically what you need here.

It looks like your stack will be correctly 16-byte aligned once you fix that.
Ethin wrote:The odd thing is that I (think) that ffffffffb99008c7h is beyond my stack, and I don't understand why. I've even reserved it properly in my linker script (I think):
Other than the off-by-one error above, it looks like everything is set up correctly. Your stack just isn't big enough for whatever it is you're doing. You could make it bigger, but I'm really curious why 256kB isn't enough already.