Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix higher half kernels by identity mapping context switch fn earlier #161

Merged
merged 3 commits into from
May 14, 2021

Conversation

phil-opp
Copy link
Member

We used to reverve two frames to allow the context switch function to identity-map itself after creating the boot info. This works for kernels that use the standard mapping since they don't need to create new level 3/2 page tables for that. For kernels that are mapped differently (e.g. to the higher half), two frames aren't enough and a frame allocation error occurs. While we could fix this by reserving a larger number of frames, this would result in lost frames for normally-mapped kernels. So we instead do the identity-mapping already in the set_up_mappings function, where the normal frame allocator still exists. This way, we no longer need the TwoFrames workaaround at all.

To ensure that this all works as intended, this PR also adds a new higher_half test kernel that maps itself to address 0xFFFF800000000000 via its custom target. By reading the rip register, the test kernel can verify that it was indeed loaded to the higher half.

Fixes #159

@Andy-Python-Programmer
Copy link

@phil-opp now it works perfectly!

Though setting the physical memory offset to 0xFFFF800000000000 does not work. It does work when it picks the offset by itself.

image

@phil-opp
Copy link
Member Author

Great to hear that!

Though setting the physical memory offset to 0xFFFF800000000000 does not work. It does work when it picks the offset by itself.

Hmm, could you show the ELF program header of your kernel, e.g. via readelf --segments?

We used to reverve two frames to allow the context switch function to identity-map itself after creating the boot info. This works for kernels that use the standard mapping since they don't need to create new level 3/2 page tables for that. For kernels that are mapped differently (e.g. to the higher half), two frames aren't enough and a frame allocation error occurs. While we could fix this by reserving a larger number of frames, this would result in lost frames for normally-mapped kernels. So we instead do the identity-mapping already in the `set_up_mappings` function, where the normal frame allocator still exists. This way, we no longer need the `TwoFrames` workaaround at all.

To ensure that this all works as intended, this PR also adds a new `higher_half` test kernel that maps itself to address `0xFFFF800000000000` via its custom target. By reading the `rip` register, the test kernel can verify that it was indeed loaded to the higher half.
@Andy-Python-Programmer
Copy link

Andy-Python-Programmer commented May 14, 2021

Elf file type is EXEC (Executable file)
Entry point 0xffff8000001020d0
There are 5 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000001000 0xffff800000101000 0x0000000000001000
                 0x000000000000b000 0x000000000000b000  R E    0x1000
  LOAD           0x000000000000c000 0xffff80000010c000 0x000000000000c000
                 0x0000000000004000 0x0000000000004000  R      0x1000
  LOAD           0x0000000000010000 0xffff800000110000 0x0000000000010000
                 0x0000000000004000 0x0000000000004000  RW     0x1000
  LOAD           0x0000000000014000 0xffff800000114000 0x0000000000014000
                 0x0000000000001000 0x0000000000001000  RW     0x1000
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x0

 Section to Segment mapping:
  Segment Sections...
   00     .text
   01     .rodata
   02     .data
   03     .tdata
   04
ENTRY(_start)
OUTPUT_FORMAT(elf64-x86-64)

KERNEL_OFFSET = 0xFFFF800000100000;

SECTIONS {
    . = KERNEL_OFFSET;

    . += SIZEOF_HEADERS;
    . = ALIGN(4096);

    .text : AT(ADDR(.text) - KERNEL_OFFSET) {
        __text_start = .;
        *(.text*)
        . = ALIGN(4096);
        __text_end = .;
    }

    .rodata : AT(ADDR(.rodata) - KERNEL_OFFSET) {
        __rodata_start = .;
        *(.rodata*)
        . = ALIGN(4096);
        __rodata_end = .;
    }

    .data : AT(ADDR(.data) - KERNEL_OFFSET) {
        __data_start = .;
        *(.data*)
        . = ALIGN(4096);
        __data_end = .;
        __bss_start = .;
        *(.bss*)
        . = ALIGN(4096);
        __bss_end = .;
    }

    .tdata : AT(ADDR(.tdata) - KERNEL_OFFSET) {
        __tdata_start = .;
        *(.tdata*)
        . = ALIGN(4096);
        __tdata_end = .;
        __tbss_start = .;
        *(.tbss*)
        . += 8;
        . = ALIGN(4096);
        __tbss_end = .;
    }

    __kernel_end = .;

    /DISCARD/ : {
        *(.comment*)
        *(.eh_frame*)
        *(.gcc_except_table*)
        *(.note*)
        *(.rel.eh_frame*)
    }
}

@Andy-Python-Programmer
Copy link

Now:
image

@phil-opp
Copy link
Member Author

@Andy-Python-Programmer Thanks! I don't see anything problematic. Normally the bootloader should just ignore the PhysAddr of segments, so I'm not sure what's going wrong here. I just pushed a new commit to improve the reporting of mapping errors. Could you retry it with this commit? This should tell us which page was already mapped.

@phil-opp
Copy link
Member Author

Thanks a lot, that was quick :D. It looks like you tried to map both the kernel and the physical memory mapping at address 0xFFFF800000100000. So the error makes sense because your kernel is already mapped at that address. You need to choose a different address range for the physical memory map that doesn't overlap with your kernel mapping.

@phil-opp phil-opp enabled auto-merge May 14, 2021 09:15
@Andy-Python-Programmer
Copy link

Ah all good! Thanks @phil-opp!

@phil-opp
Copy link
Member Author

You're welcome! Thanks for the help in debugging this!

@phil-opp phil-opp merged commit a2d52a3 into main May 14, 2021
@phil-opp phil-opp deleted the fix-higher-half-kernels branch May 14, 2021 09:19
@phil-opp
Copy link
Member Author

Published as v0.10.4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Higher Half?
2 participants