switching to new pagemap causes 0xe and more exceptions

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
RayanMargham
Member
Member
Posts: 29
Joined: Tue Jul 05, 2022 12:37 pm

switching to new pagemap causes 0xe and more exceptions

Post by RayanMargham »

Hey,

I'm trying to create the kernel a new pagemap but when switching to it, it 0xe's when it switches to the new pagemap and the error code is 0x10

Code: Select all

#define EXECUTEDISABLE (1ul << 63)
#define PRESENT (1ul)
#define RWALLOWED (1ul << 1)
#define USERMODE (1ul << 2)
#define CACHEDISABLE (1ul << 4)
#define PATBIT4096 (1ul << 7)
#define PATBIT2MB (1ul << 12)
#define PAGE2MB (1ul << 7)
#define WRITETHROUGH (1ul << 3)

uint64_t *find_pte_and_allocate(uint64_t *pt, uint64_t virt) {
  uint64_t shift = 48;
  for (int i = 0; i < 4; i++) {
    shift -= 9;
    uint64_t idx = (virt >> shift) & 0x1ff;
    uint64_t *page_table =
        (uint64_t *)((uint64_t)pt + hhdm_request.response->offset);
    if (i == 3) {
      return (uint64_t *)((uint64_t)page_table + idx);
    }
    if (page_table[idx] & ~PRESENT) {
      uint64_t *guy =
          (uint64_t *)((uint64_t)pmm_alloc() - hhdm_request.response->offset);
      page_table[idx] = (uint64_t)guy | PRESENT | RWALLOWED;
      pt = guy;
    } else if (page_table[idx] & PAGE2MB) {
      uint64_t *guy =
          (uint64_t *)((uint64_t)pmm_alloc() - hhdm_request.response->offset);
      uint64_t old_phys = page_table[idx] & 0x000ffffffffff000;
      uint64_t old_flags = page_table[idx] & ~0x000ffffffffff000;
      for (int j = 0; j < 512; j++) {
        guy[j] = (old_phys + j * 4096) | (old_flags & ~PAGE2MB);
      }
    } else {
      pt = (uint64_t *)(page_table[idx] & 0x000ffffffffff000);
    }
  }
  return 0;
}
uint64_t *find_pte_and_allocate2mb(uint64_t *pt, uint64_t virt) {
  uint64_t shift = 48;
  for (int i = 0; i < 4; i++) {
    shift -= 9;
    uint64_t idx = (virt >> shift) & 0x1ff;
    uint64_t *page_table =
        (uint64_t *)((uint64_t)pt + hhdm_request.response->offset);
    if (i == 2) {
      return (uint64_t *)((uint64_t)page_table + idx);
    }
    if (page_table[idx] & ~PRESENT) {
      uint64_t *guy =
          (uint64_t *)((uint64_t)pmm_alloc() - hhdm_request.response->offset);
      page_table[idx] = (uint64_t)guy | PRESENT | RWALLOWED;
      pt = guy;
    } else {
      pt = (uint64_t *)(page_table[idx] & 0x000ffffffffff000);
    }
  }
  return 0;
}
uint64_t *find_pte(uint64_t *pt, uint64_t virt) {
  uint64_t shift = 48;
  for (int i = 0; i < 4; i++) {
    shift -= 9;
    uint64_t idx = (virt >> shift) & 0x1ff;
    uint64_t *page_table =
        (uint64_t *)((uint64_t)pt + hhdm_request.response->offset);
    if (i == 2) {
      return (uint64_t *)((uint64_t)page_table + idx);
    }
    if (page_table[idx] & ~PRESENT) {
      return (uint64_t *)((uint64_t)page_table + idx);
    } else {
      pt = (uint64_t *)(page_table[idx] & 0x000ffffffffff000);
    }
  }
  return 0;
}
void map(uint64_t *pt, uint64_t phys, uint64_t virt, uint64_t flags) {
  uint64_t *f = find_pte_and_allocate(pt, virt);
  *f = phys | flags;
}
void map2mb(uint64_t *pt, uint64_t phys, uint64_t virt, uint64_t flags) {
  uint64_t *f = find_pte_and_allocate2mb(pt, virt);
  *f = (phys & ~0x1ffffful) | flags | PAGE2MB;
}
my code ^

https://github.com/rayanmargham/NyauxKC ... /mem/vmm.c
more context and code here
Octocontrabass
Member
Member
Posts: 5492
Joined: Mon Mar 25, 2013 7:01 pm

Re: switching to new pagemap causes 0xe and more exceptions

Post by Octocontrabass »

RayanMargham wrote: Sun Oct 27, 2024 8:32 pm0xe
It's a page fault.
RayanMargham wrote: Sun Oct 27, 2024 8:32 pmerror code is 0x10
The CPU tried to execute code from a page that wasn't present. You can check CR2 for the address.

What other debugging have you tried? You can use "info mem" and "info tlb" in the QEMU monitor to examine your page tables after you've set CR3. You can also use a debugger or the QEMU monitor to dump the contents of your page tables and find exactly which part isn't correct. Oh, and make sure CR3 is correct too.
RayanMargham
Member
Member
Posts: 29
Joined: Tue Jul 05, 2022 12:37 pm

Re: switching to new pagemap causes 0xe and more exceptions

Post by RayanMargham »

info mem and info tlb produce no output showing that the page tables itself are broken

check_exception old: 0xffffffff new 0xe
94: v=0e e=0010 i=0 cpl=0 IP=0028:ffffffff8000e1c7 pc=ffffffff8000e1c7 SP=0030:ffff800006683f98 CR2=ffffffff8000e1c7
RAX=000000000000000d RBX=00000000efe00083 RCX=0000000000000000 RDX=0000000000000000
RSI=ffff80008014a308 RDI=0000000000008000 RBP=ffff800006683fe0 RSP=ffff800006683f98
R8 =ffffffff80012b3b R9 =0000000000000010 R10=00000000000528b9 R11=0000000000000500
R12=ffff800003c17390 R13=0000000000000000 R14=0000000000000027 R15=0000000000000080
RIP=ffffffff8000e1c7 RFL=00000082 [--S----] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
CS =0028 0000000000000000 ffffffff 00af9b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
DS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
FS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
GS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT= ffffffff800e9260 00000047
IDT= ffffffff800e9ac0 00000fff
CR0=80010011 CR2=ffffffff8000e1c7 CR3=0000000000008000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000000000a8 CCD=ffff800006683f68 CCO=ADDQ
EFER=0000000000000d00
check_exception old: 0xe new 0xe
95: v=08 e=0000 i=0 cpl=0 IP=0028:ffffffff8000e1c7 pc=ffffffff8000e1c7 SP=0030:ffff800006683f98 env->regs[R_EAX]=000000000000000d
RAX=000000000000000d RBX=00000000efe00083 RCX=0000000000000000 RDX=0000000000000000
RSI=ffff80008014a308 RDI=0000000000008000 RBP=ffff800006683fe0 RSP=ffff800006683f98
R8 =ffffffff80012b3b R9 =0000000000000010 R10=00000000000528b9 R11=0000000000000500
R12=ffff800003c17390 R13=0000000000000000 R14=0000000000000027 R15=0000000000000080
RIP=ffffffff8000e1c7 RFL=00000082 [--S----] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
CS =0028 0000000000000000 ffffffff 00af9b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
DS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
FS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
GS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT= ffffffff800e9260 00000047
IDT= ffffffff800e9ac0 00000fff
CR0=80010011 CR2=ffffffff800e9ba0 CR3=0000000000008000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000000000a8 CCD=ffff800006683f68 CCO=ADDQ
EFER=0000000000000d00
check_exception old: 0x8 new 0xe
full output of qemu
RayanMargham
Member
Member
Posts: 29
Joined: Tue Jul 05, 2022 12:37 pm

Re: switching to new pagemap causes 0xe and more exceptions

Post by RayanMargham »

and yes i have a page fault handler which doesnt execute showing the page tables themselves are broken
Octocontrabass
Member
Member
Posts: 5492
Joined: Mon Mar 25, 2013 7:01 pm

Re: switching to new pagemap causes 0xe and more exceptions

Post by Octocontrabass »

RayanMargham wrote: Sun Oct 27, 2024 10:56 pmCR3=0000000000008000
Is this a reasonable address for CR3? Does the memory at that address contain your PML4? Are the entries in the PML4 correct?
RayanMargham
Member
Member
Posts: 29
Joined: Tue Jul 05, 2022 12:37 pm

Re: switching to new pagemap causes 0xe and more exceptions

Post by RayanMargham »

yea thats resonable.

no the page table itself is fucked. i dont understand why tho
Octocontrabass
Member
Member
Posts: 5492
Joined: Mon Mar 25, 2013 7:01 pm

Re: switching to new pagemap causes 0xe and more exceptions

Post by Octocontrabass »

Use a debugger or the QEMU monitor to dump the contents of your PML4. Decode it by hand. Work your way through the page table until you find the problem (or until you're sure you can't find the problem). If you still need help after that, share what you've found.

That's how I'd debug it, anyway. There are other things you can do to debug a problem like this.
MichaelPetch
Member
Member
Posts: 770
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: switching to new pagemap causes 0xe and more exceptions

Post by MichaelPetch »

When I run your kernel I get slightly different results but I think it because of the same problem as you are experiencing. Using the QEMU monitor I issue the command `info tlb` and see (yours may be slightly different):

Code: Select all

ffff800000000000: 0003838300800000 XGP-----W
ffff800000200000: 0003838383800000 XGP-----W
ffff800000400000: 0003838383800000 XGP-----W
ffff800000600000: 0003838383800000 -GP-----W
...
ffffffff80000000: 0003030303030000 -G------W
ffffffff80001000: 0003030303030000 -G------W
ffffffff80002000: 0003030303030000 -G------W
ffffffff80003000: 0003030303030000 -G------W
ffffffff80004000: 0003030303030000 -G------W
ffffffff80005000: 0003030303030000 -G------W
ffffffff80006000: 0003030303030000 -G------W
ffffffff80007000: 0003030303030000 -G------W
ffffffff80008000: 0003030303030000 -G------W
ffffffff80009000: 0003030303030000 -G------W
ffffffff8000a000: 0003030303030000 -G------W
ffffffff8000b000: 0003030303030000 -G------W
ffffffff8000c000: 0003030303030000 -G------W
ffffffff8000d000: 0003030303030000 -G------W
ffffffff8000e000: 0003030303030000 -G------W
Clearly all the physical addresses (second column) are wrong. The value 0x03 and 0x83 don't seem random, and it is probably no coincidence that 0x83 denotes the flags in a 2MiB page directory entry and 0x03 for flags in a page table entry.

When I follow your PML4 in the QEMU monitor using `xp/512g 0x8000` (display 512 quadwords starting at physical address 0x8000) and then follow entries down to a page table I see garbage like:

Code: Select all

(qemu) xp/512g 0xb000
000000000000b000: 0x0303030303030303 0x0303030303030303
000000000000b010: 0x0303030303030303 0x0303030303030303
000000000000b020: 0x0303030303030303 0x0303030303030303
000000000000b030: 0x0303030303030303 0x0303030303030303
000000000000b040: 0x0303030303030303 0x0303030303030303
000000000000b050: 0x0303030303030303 0x0303030303030303
000000000000b060: 0x0303030303030303 0x0303030303030303
000000000000b070: 0x0303030303030303 0x0303030303030303
000000000000b080: 0x0303030303030303 0x0303030303030303
000000000000b090: 0x0303030303030303 0x0303030303030303
000000000000b0a0: 0x0303030303030303 0x0303030303030303
000000000000b0b0: 0x0303030303030303 0x0303030303030303
000000000000b0c0: 0x0303030303030303 0x0303030303030303
000000000000b0d0: 0x0303030303030303 0x0303030303030303
000000000000b0e0: 0x0303030303030303 0x0000023350030303
000000000000b0f0: 0x0000000000000000 0x0000000000000000
000000000000b100: 0x0000000000000000 0x0000000000000000
...
000000000000bfe0: 0x0000000000000000 0x0000000000000000
000000000000bff0: 0x0000000000000000 0x0000000000000000
When I follow down to a Page Directory with entries that have a 2MiB page size I see something like:

Code: Select all

(qemu) xp/512g 0xd000
000000000000d000: 0x8383838300838383 0x8383838383838383
000000000000d010: 0x8383838383838383 0x0083838383838383
000000000000d020: 0x8383838383838383 0x8383838383838383
000000000000d030: 0x8383838383838383 0x8300838300838383
000000000000d040: 0x830000000007e000 0x8383838383838383
000000000000d050: 0x8383838383838383 0x8383838383838383
000000000000d060: 0x8383838383838383 0x8383838383838383
000000000000d070: 0x8383838383838383 0x8383838383838383
000000000000d080: 0x8383838383838383 0x8383838383838383
000000000000d090: 0x8383838383838383 0x8383838383838383
000000000000d0a0: 0x8383838383838383 0x8383838383838383
000000000000d0b0: 0x8383838383838383 0x8383838383838383
000000000000d0c0: 0x8383838383838383 0x8383838383838383
000000000000d0d0: 0x8383838383838383 0x8383838383838383
000000000000d0e0: 0x8383838383838383 0x8383838383838383
000000000000d0f0: 0x8383838383838383 0x8383838383838383
000000000000d100: 0x8383838383838383 0x8383838383838383
000000000000d110: 0x8383838383838383 0x8383838383838383
000000000000d120: 0x8383838383838383 0x8383838383838383
000000000000d130: 0x8383838383838383 0x8383838383838383
000000000000d140: 0x8383838383838383 0x8383838383838383
000000000000d150: 0x8383838383838383 0x8383838383838383
000000000000d160: 0x8383838383838383 0x8383838383838383
000000000000d170: 0x8383838383838383 0x8383838383838383
000000000000d180: 0x8383838383838383 0x8383838383838383
000000000000d190: 0x8383838383838383 0x8383838383838383
000000000000d1a0: 0x8383838383838383 0x8383838383838383
000000000000d1b0: 0x8383838383838383 0x8383838383838383
000000000000d1c0: 0x8383838383838383 0x8383838383838383
000000000000d1d0: 0x8383838383838383 0x8383838383838383
000000000000d1e0: 0x8383838383838383 0x8383838383838383
000000000000d1f0: 0x8383838383838383 0x8383838383838383
000000000000d200: 0x00000000003fe000 0x0000000000000000
...
000000000000dfe0: 0x0000000000000000 0x0000000000000000
000000000000dff0: 0x0000000000000000 0x0000000000000000
This suggests to me that when you loop through these entries to fill them in your indexing is not correct. Upon looking at your code in vmm.c I see this in `find_pte_and_allocate2mb`:

Code: Select all

    if (i == 2) {
      return (uint64_t *)((uint64_t)page_table + idx);
This should be:

Code: Select all

    if (i == 2) {
      return page_table + idx;
Similarly in `find_pte_and_allocate` you use:

Code: Select all

    if (i == 3) {
      return (uint64_t *)((uint64_t)page_table + idx);
when it should be:

Code: Select all

    if (i == 3) {
      return page_table + idx;
You also have similar issues in both `return` statements in `find_pte` that need to be fixed in a similar way.
RayanMargham
Member
Member
Posts: 29
Joined: Tue Jul 05, 2022 12:37 pm

Re: switching to new pagemap causes 0xe and more exceptions

Post by RayanMargham »

THANK YOU THAT SOLVED MY ISSUE !!!
MichaelPetch
Member
Member
Posts: 770
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: switching to new pagemap causes 0xe and more exceptions

Post by MichaelPetch »

No problem. Please note: I think there might be a similar issue with `find_pte` as I mentioned at the bottom of my post in the last sentence. I mention it because I noticed that changes put away in your repository only included the first 2 problems I identified.
RayanMargham
Member
Member
Posts: 29
Joined: Tue Jul 05, 2022 12:37 pm

Re: switching to new pagemap causes 0xe and more exceptions

Post by RayanMargham »

check the github repo again, also now im having memory corruption and page faults when trying to use an external library acpi library to stress test the heap :noo:
MichaelPetch
Member
Member
Posts: 770
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: switching to new pagemap causes 0xe and more exceptions

Post by MichaelPetch »

Not sure this will help you. But I ran your code until it page faulted. In the QEMU output I had:

Code: Select all

Allocated slab with base: 0xffff80000030c010
Allocated slab with base: 0xffff80000030d010
Allocated slab with base: 0xffff80000030e010
Allocated slab with base: 0xffff80000030f010
Allocated slab with base: 0xffff800000310010
Allocated slab with base: 0xffff800000311010
Allocated slab with base: 0xffff800000312010
Allocated slab with base: 0xffff800000313010
Allocated slab with base: 0xffff800000314010
Allocated slab with base: 0xffff800000315010
Allocated slab with base: 0xffff800000316010
Allocated slab with base: 0xffff800000317010
deallocing vmm region address of base: 0xffff80000030a010
deallocing vmm region address of base: 0xffff800000315010
Allocated with base: 0xffff800000804000
deallocing vmm region address of base: 0xffff8000002f5010
Allocated with base: 0xffff800000805000
deallocing vmm region address of base: 0xffff800000804000
check_exception old: 0xffffffff new 0xe
  1346: v=0e e=0002 i=0 cpl=0 IP=0028:ffffffff800057f0 pc=ffffffff800057f0 SP=0030:ffff800006468e28 CR2=ffff800000800000
RAX=ffff800000800000 RBX=ffff800000800000 RCX=ffff800000800000 RDX=0000000000000000
RSI=0000000000000000 RDI=ffff800000801000 RBP=ffff800006468e40 RSP=ffff800006468e28
R8 =0000000000000000 R9 =0000000000000010 R10=00000000000e8a33 R11=0000000000000500
R12=0000000000001000 R13=ffff8000002fc010 R14=0000000000001000 R15=0000000000800000
RIP=ffffffff800057f0 RFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS   [-WA]
CS =0028 0000000000000000 ffffffff 00af9b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS   [-WA]
DS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS   [-WA]
FS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS   [-WA]
GS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT=     ffffffff80105860 00000047
IDT=     ffffffff801060c0 00000fff
CR0=80010011 CR2=ffff800000800000 CR3=0000000000008000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=ffff800000000000 CCD=0000000000000000 CCO=LOGICL
EFER=0000000000000d00
Page Fault! CR2 0xffff800000800000
RIP is 0xffffffff800057f0
NYAUX Panic! Reason: Page Fault:c
oopsie uwu :3
I got a page fault with e=0002 and CR2=ffff800000800000 from an instruction at pc=ffffffff800057f0 . That is a page fault while attempting to do a write to 0xffff800000800000. See
https://wiki.osdev.org/Exceptions#Page_Fault for page fault error decoding. When I do `info mem` in the QEMU monitor I see:

Code: Select all

ffff800000000000-ffff800000800000 0000000000800000 -rw
ffff800000a00000-ffff800100000000 00000000ff600000 -rw
ffffffff80000000-ffffffff80108000 0000000000108000 -rw
0xffff800000800000 (CR2) is not mapped into memory and you have attempted to write to it. In my build 0xffffffff800057f0 is in `memset` . I think this is worth noting in the output:

Code: Select all

Allocated with base: 0xffff800000804000
deallocing vmm region address of base: 0xffff8000002f5010
Allocated with base: 0xffff800000805000
deallocing vmm region address of base: 0xffff800000804000
You started allocating memory that wasn't mapped and it appears the failure was at the point memory was dealloced in the unmapped address space.

I didn't actually do any debugging beyond seeing why it crashed. Not sure that is helful to you or not.
RayanMargham
Member
Member
Posts: 29
Joined: Tue Jul 05, 2022 12:37 pm

Re: switching to new pagemap causes 0xe and more exceptions

Post by RayanMargham »

that was because the hhdm pages were 2mb pages counted not 4096

i have solved a new one but a new one has occured where i page fault with 0xa

meaning theres something wrong with my page tables :(
MichaelPetch
Member
Member
Posts: 770
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: switching to new pagemap causes 0xe and more exceptions

Post by MichaelPetch »

Yeah e=000a would be a page error on a write but a reserved bit is set somewhere in the paging hierarchy. The value in CR2 should help you understand which pages you'd have to look at for a problem. The QEMU monitor would probably be helpful to look through the page structure as I did in an earlier comment where I was dumping physical memory to look at the page tables directly.

I think it is about time you start building with debug information (use -g when assembling NASM and compiling with GCC) and then connect GDB to QEMU so that you can actually see where in the source code the failures are happening. You'd also be able to use stack traces to see the chain of functions called.
RayanMargham
Member
Member
Posts: 29
Joined: Tue Jul 05, 2022 12:37 pm

Re: switching to new pagemap causes 0xe and more exceptions

Post by RayanMargham »

stack trace doesnt work for some reason

i cant paste the output of info mem or info tlb but u can look at it on github and run it for yourself, i did attach gdb and i couldnt find much
Post Reply