Skip to content

What's mapped in the lower half? #470

Description

@mrjbom

As the kernel of the upper half, I want nothing to be displayed in the lower half.
But TLB after loading looks like this:

(qemu) info tlb
000000000013b000: 000000000013b000 ----A----
000000000013c000: 000000000013c000 ---------
00000000013ac000: 00000000013ac000 ---------
...
Higher half mapped

I realized that 13ac000 belongs to GDT, I created my GDT and can now unmap that address.
But what is mapped in the first two addresses? Can I safely unmap them?

Activity

  1. Freax13 commented on Nov 1, 2024

    @Freax13
    Member

    That's probably the context switch function of the boot loader:

    // identity-map context switch function, so that we don't get an immediate pagefault
    // after switching the active page table
    let context_switch_function = PhysAddr::new(context_switch as *const () as u64);
    let context_switch_function_start_frame: PhysFrame =
    PhysFrame::containing_address(context_switch_function);
    for frame in PhysFrame::range_inclusive(
    context_switch_function_start_frame,
    context_switch_function_start_frame + 1,
    ) {
    let page = Page::containing_address(VirtAddr::new(frame.start_address().as_u64()));
    match unsafe {
    // The parent table flags need to be both readable and writable to
    // support recursive page tables.
    // See https://github.com/rust-osdev/bootloader/issues/443#issuecomment-2130010621
    kernel_page_table.map_to_with_table_flags(
    page,
    frame,
    PageTableFlags::PRESENT,
    PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
    frame_allocator,
    )
    } {
    Ok(tlb) => tlb.flush(),
    Err(err) => panic!("failed to identity map frame {:?}: {:?}", frame, err),
    }
    }

    These pages contain a function that switches to the kernel page tables and jumps to its entry point. You can safely unmap it.

    See also #240

  2. mrjbom commented on Nov 1, 2024

    @mrjbom
    Author

    If it turns out not to be context switch function, then I suppose I can safely unmap these addresses anyway? Why does the bootloader leave these things mapped?
    For example, GDT could be safely unmapped by bootloader.

  3. Freax13 commented on Nov 1, 2024

    @Freax13
    Member

    If it turns out not to be context switch function, then I suppose I can safely unmap these addresses anyway?

    I'm pretty sure it's the context switch function. If it's not the context switch function, then it depends on the memory for whether it's safe to unmap.

    Why does the bootloader leave these things mapped?

    The context switch function needs to do two things:

    1. Switch to the kernel's page tables.
    2. Jump to the kernel's entry point.

    It needs to do these steps in that order. The problem is that if we don't map the context switch function into the kernel's page tables, we can't do the second step after switching the page tables.

    For example, GDT could be safely unmapped by bootloader.

    The GDT can't be safely unmapped before switching to a new one. Some instructions like iret read from the GDT and if the GDT is no longer mapped, this causes a page fault.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions