这是indexloc提供的服务,不要输入任何密码
Skip to content

x86_64: local APIC page is already mapped by bootloader when running in KVM #506

@hawkw

Description

@hawkw

after updating bootloader to v0.11.9 in 7301300, it seems that running the kernel in KVM results in the local APIC page already having been mapped by the bootloader to...some other thing.

running with

$ cargo run-x64 --serial  -- -machine accel=kvm -cpu host,migratable=no,+invtsc

gets a crash like this:

[     ?.??????][?] ├hal_x86_64::interrupt::apic::local: mapping local APIC MMIO page... virt=Page {
                   │     base: VAddr(0xffff8180fee00000),
                   │     size: 4KB,
                   │ },
                   │ phys=Page {
                   │     base: PAddr(0xfee00000),
                   │     size: 4KB,
                   │ }
[     ?.??????][?] │┌map_page: virt=Page { base: VAddr(0xffff8180fee00000), size: 4KB }, phys=Page 
                   ││ { base: PAddr(0xfee00000), size: 4KB }
[     ?.??????][*] │├hal_x86_64::mm: vaddr=VAddr(0xffff8180fee00000)
[     ?.??????][*] ││┌create_next_table: idx=Page { base: VAddr(0xffff8180fee00000), size: 4KB },
                   │││  self.level=PML4, next.level=PDPT
[     ?.??????][?] │││┌next_table: idx=Page { base: VAddr(0xffff8180fee00000), size: 4KB }, 
                   ││││ self.level=PML4, next.level=PDPT, self.addr=0xffff808000014558
[     ?.??????][*] │││├hal_x86_64::mm: entry=Entry {
                   ││││     level: PML4,
                   ││││     addr: PAddr(0x134000),
                   ││││     flags: PRESENT | WRITABLE | ACCESSED,
                   ││││ }
[     ?.??????][*] │││├hal_x86_64::mm::level: v=VAddr(0xffff8180fee00000), pml4_idx=259
[     ?.??????][*] │││├hal_x86_64::mm: found next table virtual address, next.addr=VAddr(0x
                   ││││ fffffffffff03000)
[     ?.??????][*] ││├hal_x86_64::mm: next table already exists
[     ?.??????][?] │││┌next_table_mut: idx=Page { base: VAddr(0xffff8180fee00000), size: 4KB },
                   ││││  self.level=PML4, next.level=PDPT, self.addr=0xffff8080000142b0
[     ?.??????][*] │││├hal_x86_64::mm: entry=Entry {
                   ││││     level: PML4,
                   ││││     addr: PAddr(0x134000),
                   ││││     flags: PRESENT | WRITABLE | ACCESSED,
                   ││││ }
[     ?.??????][*] │││├hal_x86_64::mm::level: v=VAddr(0xffff8180fee00000), pml4_idx=259
[     ?.??????][*] │││├hal_x86_64::mm: found next table virtual address, next.addr=VAddr(0x
                   ││││ fffffffffff03000)
[     ?.??????][*] ││┌create_next_table: idx=Page { base: VAddr(0xffff8180fee00000), size: 4KB },
                   │││  self.level=PDPT, next.level=PD
[     ?.??????][?] │││┌next_table: idx=Page { base: VAddr(0xffff8180fee00000), size: 4KB }, 
                   ││││ self.level=PDPT, next.level=PD, self.addr=0xffff808000014558
[     ?.??????][*] │││├hal_x86_64::mm: entry=Entry {
                   ││││     level: PDPT,
                   ││││     addr: PAddr(0x138000),
                   ││││     flags: PRESENT | WRITABLE | ACCESSED,
                   ││││ }
[     ?.??????][*] │││├hal_x86_64::mm::level: v=VAddr(0xffff8180fee00000), pml4_idx=259, 
                   ││││ pdpt_idx=3
[     ?.??????][*] │││├hal_x86_64::mm: found next table virtual address, next.addr=VAddr(0x
                   ││││ ffffffffe0603000)
[     ?.??????][*] ││├hal_x86_64::mm: next table already exists
[     ?.??????][?] │││┌next_table_mut: idx=Page { base: VAddr(0xffff8180fee00000), size: 4KB },
                   ││││  self.level=PDPT, next.level=PD, self.addr=0xffff8080000142b0
[     ?.??????][*] │││├hal_x86_64::mm: entry=Entry {
                   ││││     level: PDPT,
                   ││││     addr: PAddr(0x138000),
                   ││││     flags: PRESENT | WRITABLE | ACCESSED,
                   ││││ }
[     ?.??????][*] │││├hal_x86_64::mm::level: v=VAddr(0xffff8180fee00000), pml4_idx=259, 
                   ││││ pdpt_idx=3
[     ?.??????][*] │││├hal_x86_64::mm: found next table virtual address, next.addr=VAddr(0x
                   ││││ ffffffffe0603000)
[     ?.??????][*] ││┌create_next_table: idx=Page { base: VAddr(0xffff8180fee00000), size: 4KB },
                   │││  self.level=PD, next.level=PT
[     ?.??????][?] │││┌next_table: idx=Page { base: VAddr(0xffff8180fee00000), size: 4KB }, 
                   ││││ self.level=PD, next.level=PT, self.addr=0xffff808000014558
[     ?.??????][*] │││├hal_x86_64::mm: entry=Entry {
                   ││││     level: PD,
                   ││││     addr: PAddr(0xfee00000),
                   ││││     flags: PRESENT | WRITABLE | HUGE,
                   ││││ }
[     ?.??????][*] │││├hal_x86_64::mm::level: v=VAddr(0xffff8180fee00000), pml4_idx=259, 
                   ││││ pdpt_idx=3, pd_idx=503
[     ?.??????][*] │││├hal_x86_64::mm: found next table virtual address, next.addr=VAddr(0x
                   ││││ ffffffc0c07f7000)
[     ?.??????][*] ││├hal_x86_64::mm: next table already exists
[     ?.??????][?] │││┌next_table_mut: idx=Page { base: VAddr(0xffff8180fee00000), size: 4KB },
                   ││││  self.level=PD, next.level=PT, self.addr=0xffff8080000142b0
[     ?.??????][*] │││├hal_x86_64::mm: entry=Entry {
                   ││││     level: PD,
                   ││││     addr: PAddr(0xfee00000),
                   ││││     flags: PRESENT | WRITABLE | HUGE,
                   ││││ }
[     ?.??????][*] │││├hal_x86_64::mm::level: v=VAddr(0xffff8180fee00000), pml4_idx=259, 
                   ││││ pdpt_idx=3, pd_idx=503
[     ?.??????][*] │││├hal_x86_64::mm: found next table virtual address, next.addr=VAddr(0x
                   ││││ ffffffc0c07f7000)
[     ?.??????][?] │├hal_x86_64::mm: page_table=PageTable {
                   ││     level: PT,
                   ││     addr: 0xffffffc0c07f7000,
                   ││ }
[     ?.??????][*] │├hal_x86_64::mm: entry=Entry {
                   ││     level: PT,
                   ││     addr: PAddr(0x170000),
                   ││     flags: PRESENT | CACHE_DISABLE,
                   ││ }
[     ?.??????][?] │├oops: Oops {
                   ││     already_panicked: false,
                   ││     already_faulted: false,
                   ││     alloc: State {
                   ││         allocating: 0,
                   ││         deallocating: 0,
                   ││         heap_size: 100544512,
                   ││         allocated: 137792,
                   ││         min_size: 64,
                   ││         bump_mode: false,
                   ││         bump_allocated: 0,
                   ││         bump_size: 1024,
                   ││     },
                   ││     situation: OopsSituation::Panic(
                   ││         PanicInfo {
                   ││             message: mapped page table entry already in use,
                   ││             location: Location {
                   ││                 file: "/home/eliza/Code/mycelium/hal-x86_64/src/mm.rs",
                   ││                 line: 170,
                   ││                 col: 9,
                   ││             },
                   ││             can_unwind: true,
                   ││             force_no_backtrace: false,
                   ││         },
                   ││     ),
                   ││ }
qemu: terminating on signal 2

(this is the assertion that the PTE found by walking the page table doesn't have the present bit set).

so it seems that somehow PT@0xffffffc0c07f7000[503] is pointed at 0x17000, when we would like to point it at the LAPIC MMIO page at 0xfee00000. We'd really like to identity map that address (vaddr 0xffff8180fee00000), but the bootloader seems to have already mapped the VAddr to...some other thing. which is weird.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions