Sometimes while debugging problems related to how kernel and devices are memory-mapped it is helpful to see it in some form in gdb or by reading a procfs file just like we can do with mmap-ed VMAs. In addition we need to know where linear VMAs are located so that we can avoid collisions with mmap() as described by the issue #1135.
To that end this patch adds new struct - linear_vma and collection of those - linear_vma_set - to track how memory gets mapped using linear_map(). It also modifies all places calling linear_map() to pass new argument - name. Please note that we can not re-use existing vma class, as it holds much richer information and lots of it is not applicable to linear map which is quite static and is simply a pre-populated mapping between some area of virtual and physical memory. Upcoming patches will add new 'osv linear_mmap' to loader.py and implementation of new sysfs pseudo file. Signed-off-by: Waldemar Kozaczuk <[email protected]> --- arch/aarch64/arch-setup.cc | 20 +++++++++++--------- arch/x64/apic.cc | 2 +- arch/x64/arch-setup.cc | 11 ++++++++--- arch/x64/dmi.cc | 4 ++-- arch/x64/ioapic.cc | 2 +- bsd/porting/mmu.cc | 2 +- core/mmio.cc | 4 ++-- core/mmu.cc | 28 +++++++++++++++++++++++++++- drivers/acpi.cc | 2 +- drivers/hpet.cc | 2 +- drivers/mmio-isa-serial.cc | 2 +- drivers/pci-function.cc | 2 +- drivers/pl031.cc | 2 +- drivers/virtio-mmio.cc | 2 +- drivers/xenconsole.cc | 2 +- include/osv/mmio.hh | 2 +- include/osv/mmu.hh | 16 +++++++++++++++- include/osv/prio.hh | 1 + 18 files changed, 77 insertions(+), 29 deletions(-) diff --git a/arch/aarch64/arch-setup.cc b/arch/aarch64/arch-setup.cc index f9854b6a..622fb75f 100644 --- a/arch/aarch64/arch-setup.cc +++ b/arch/aarch64/arch-setup.cc @@ -61,7 +61,7 @@ void arch_setup_pci() pci::set_pci_cfg(pci_cfg, pci_cfg_len); pci_cfg = pci::get_pci_cfg(&pci_cfg_len); mmu::linear_map((void *)pci_cfg, (mmu::phys)pci_cfg, pci_cfg_len, - mmu::page_size, mmu::mattr::dev); + "pci_cfg", mmu::page_size, mmu::mattr::dev); /* linear_map [TTBR0 - PCI I/O and memory ranges] */ u64 ranges[2]; size_t ranges_len[2]; @@ -73,9 +73,9 @@ void arch_setup_pci() ranges[0] = pci::get_pci_io(&ranges_len[0]); ranges[1] = pci::get_pci_mem(&ranges_len[1]); mmu::linear_map((void *)ranges[0], (mmu::phys)ranges[0], ranges_len[0], - mmu::page_size, mmu::mattr::dev); + "pci_io", mmu::page_size, mmu::mattr::dev); mmu::linear_map((void *)ranges[1], (mmu::phys)ranges[1], ranges_len[1], - mmu::page_size, mmu::mattr::dev); + "pci_mem", mmu::page_size, mmu::mattr::dev); } #endif @@ -94,17 +94,19 @@ void arch_setup_free_memory() /* linear_map [TTBR1] */ for (auto&& area : mmu::identity_mapped_areas) { auto base = reinterpret_cast<void*>(get_mem_area_base(area)); - mmu::linear_map(base + addr, addr, memory::phys_mem_size); + mmu::linear_map(base + addr, addr, memory::phys_mem_size, + area == mmu::mem_area::main ? "main" : + area == mmu::mem_area::page ? "page" : "mempool"); } /* linear_map [TTBR0 - boot, DTB and ELF] */ mmu::linear_map((void *)mmu::mem_addr, (mmu::phys)mmu::mem_addr, - addr - mmu::mem_addr); + addr - mmu::mem_addr, "kernel"); if (console::PL011_Console::active) { /* linear_map [TTBR0 - UART] */ addr = (mmu::phys)console::aarch64_console.pl011.get_base_addr(); - mmu::linear_map((void *)addr, addr, 0x1000, mmu::page_size, + mmu::linear_map((void *)addr, addr, 0x1000, "pl011", mmu::page_size, mmu::mattr::dev); } @@ -112,7 +114,7 @@ void arch_setup_free_memory() if (console::Cadence_Console::active) { // linear_map [TTBR0 - UART] addr = (mmu::phys)console::aarch64_console.cadence.get_base_addr(); - mmu::linear_map((void *)addr, addr, 0x1000, mmu::page_size, + mmu::linear_map((void *)addr, addr, 0x1000, "cadence", mmu::page_size, mmu::mattr::dev); } #endif @@ -124,9 +126,9 @@ void arch_setup_free_memory() abort("arch-setup: failed to get GICv2 information from dtb.\n"); } gic::gic = new gic::gic_driver(dist, cpu); - mmu::linear_map((void *)dist, (mmu::phys)dist, dist_len, mmu::page_size, + mmu::linear_map((void *)dist, (mmu::phys)dist, dist_len, "gic_dist", mmu::page_size, mmu::mattr::dev); - mmu::linear_map((void *)cpu, (mmu::phys)cpu, cpu_len, mmu::page_size, + mmu::linear_map((void *)cpu, (mmu::phys)cpu, cpu_len, "gic_cpu", mmu::page_size, mmu::mattr::dev); #if CONF_drivers_pci diff --git a/arch/x64/apic.cc b/arch/x64/apic.cc index 03518deb..a026ab7b 100644 --- a/arch/x64/apic.cc +++ b/arch/x64/apic.cc @@ -103,7 +103,7 @@ void apic_driver::read_base() xapic::xapic() : apic_driver() { - mmu::linear_map(static_cast<void*>(_base_virt), _apic_base, 4096); + mmu::linear_map(static_cast<void*>(_base_virt), _apic_base, 4096, "xapic"); xapic::enable(); } diff --git a/arch/x64/arch-setup.cc b/arch/x64/arch-setup.cc index 582cb1b5..e1fb5380 100644 --- a/arch/x64/arch-setup.cc +++ b/arch/x64/arch-setup.cc @@ -164,7 +164,10 @@ void arch_setup_free_memory() }); for (auto&& area : mmu::identity_mapped_areas) { auto base = reinterpret_cast<void*>(get_mem_area_base(area)); - mmu::linear_map(base, 0, initial_map, initial_map); + mmu::linear_map(base, 0, initial_map, + area == mmu::mem_area::main ? "main" : + area == mmu::mem_area::page ? "page" : "mempool", + initial_map); } // Map the core, loaded by the boot loader // In order to properly setup mapping between virtual @@ -176,7 +179,7 @@ void arch_setup_free_memory() // as expressed by the assignment below elf_start = reinterpret_cast<void*>(elf_phys_start + OSV_KERNEL_VM_SHIFT); elf_size = edata_phys - elf_phys_start; - mmu::linear_map(elf_start, elf_phys_start, elf_size, OSV_KERNEL_BASE); + mmu::linear_map(elf_start, elf_phys_start, elf_size, "kernel", OSV_KERNEL_BASE); // get rid of the command line, before low memory is unmapped parse_cmdline(mb); // now that we have some free memory, we can start mapping the rest @@ -205,7 +208,9 @@ void arch_setup_free_memory() } for (auto&& area : mmu::identity_mapped_areas) { auto base = reinterpret_cast<void*>(get_mem_area_base(area)); - mmu::linear_map(base + ent.addr, ent.addr, ent.size, ~0); + mmu::linear_map(base + ent.addr, ent.addr, ent.size, + area == mmu::mem_area::main ? "main" : + area == mmu::mem_area::page ? "page" : "mempool", ~0); } mmu::free_initial_memory_range(ent.addr, ent.size); }); diff --git a/arch/x64/dmi.cc b/arch/x64/dmi.cc index f28e480a..9a5a510c 100644 --- a/arch/x64/dmi.cc +++ b/arch/x64/dmi.cc @@ -53,7 +53,7 @@ static void dmi_table(u32 base, u16 len, u16 num) { u8* const table_virt = mmu::phys_cast<u8>(base); - mmu::linear_map(static_cast<void*>(table_virt), base, len); + mmu::linear_map(static_cast<void*>(table_virt), base, len, "smbios"); auto start = reinterpret_cast<const char*>(table_virt); @@ -131,7 +131,7 @@ void dmi_probe() u8* const dmi_virt = mmu::phys_cast<u8>(dmi_base); - mmu::linear_map(static_cast<void*>(dmi_virt), dmi_base, 0x10000); + mmu::linear_map(static_cast<void*>(dmi_virt), dmi_base, 0x10000, "dmi"); auto start = reinterpret_cast<const char*>(dmi_virt); diff --git a/arch/x64/ioapic.cc b/arch/x64/ioapic.cc index 339949a3..bd7a5ac5 100644 --- a/arch/x64/ioapic.cc +++ b/arch/x64/ioapic.cc @@ -43,7 +43,7 @@ void write(unsigned reg, u32 data) void init() { - mmu::linear_map(const_cast<void*>(base), base_phys, 4096); + mmu::linear_map(const_cast<void*>(base), base_phys, 4096, "ioapic"); } } diff --git a/bsd/porting/mmu.cc b/bsd/porting/mmu.cc index e810f238..89aeb084 100644 --- a/bsd/porting/mmu.cc +++ b/bsd/porting/mmu.cc @@ -15,7 +15,7 @@ void *pmap_mapdev(uint64_t paddr, size_t size) { - return (void *)mmio_map(paddr, size); + return (void *)mmio_map(paddr, size, "xen_store"); } uint64_t virt_to_phys(void *virt) diff --git a/core/mmio.cc b/core/mmio.cc index cebd2cc8..67f8a69e 100644 --- a/core/mmio.cc +++ b/core/mmio.cc @@ -51,10 +51,10 @@ u64 mmio_getq(mmioaddr_t addr) return (*reinterpret_cast<volatile u64*>(addr)); } -mmioaddr_t mmio_map(u64 paddr, size_t size_bytes) +mmioaddr_t mmio_map(u64 paddr, size_t size_bytes, const char* name) { char* map_to = mmu::phys_mem + paddr; - linear_map(map_to, paddr, size_bytes); + linear_map(map_to, paddr, size_bytes, name); return map_to; } diff --git a/core/mmu.cc b/core/mmu.cc index 3125a8aa..7c78ac5b 100644 --- a/core/mmu.cc +++ b/core/mmu.cc @@ -28,6 +28,7 @@ #include <osv/rcu.hh> #include <osv/rwlock.h> #include <numeric> +#include <set> // FIXME: Without this pragma, we get a lot of warnings that I don't know // how to explain or fix. For now, let's just ignore them :-( @@ -46,6 +47,16 @@ extern const char text_start[], text_end[]; namespace mmu { +struct linear_vma_compare { + bool operator()(const linear_vma* a, const linear_vma* b) { + return a->_virt_addr < b->_virt_addr; + } +}; + +__attribute__((init_priority((int)init_prio::linear_vma_set))) +std::set<linear_vma*, linear_vma_compare> linear_vma_set; +rwlock_t linear_vma_set_mutex; + namespace bi = boost::intrusive; class vma_compare { @@ -1857,7 +1868,18 @@ int shm_file::close() return 0; } -void linear_map(void* _virt, phys addr, size_t size, +linear_vma::linear_vma(void* virt, phys phys, size_t size, mattr mem_attr, const char* name) { + _virt_addr = virt; + _phys_addr = phys; + _size = size; + _mem_attr = mem_attr; + _name = name; +} + +linear_vma::~linear_vma() { +} + +void linear_map(void* _virt, phys addr, size_t size, const char* name, size_t slop, mattr mem_attr) { uintptr_t virt = reinterpret_cast<uintptr_t>(_virt); @@ -1865,6 +1887,10 @@ void linear_map(void* _virt, phys addr, size_t size, assert((virt & (slop - 1)) == (addr & (slop - 1))); linear_page_mapper phys_map(addr, size, mem_attr); map_range(virt, virt, size, phys_map, slop); + auto _vma = new linear_vma(_virt, addr, size, mem_attr, name); + WITH_LOCK(linear_vma_set_mutex.for_write()) { + linear_vma_set.insert(_vma); + } } void free_initial_memory_range(uintptr_t addr, size_t size) diff --git a/drivers/acpi.cc b/drivers/acpi.cc index d1f5f422..af4140a4 100644 --- a/drivers/acpi.cc +++ b/drivers/acpi.cc @@ -175,7 +175,7 @@ void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS Where, ACPI_SIZE Length) uint64_t _where = align_down(Where, mmu::huge_page_size); size_t map_size = align_up(Length + Where - _where, mmu::huge_page_size); - mmu::linear_map(mmu::phys_to_virt(_where), _where, map_size); + mmu::linear_map(mmu::phys_to_virt(_where), _where, map_size, "acpi"); return mmu::phys_to_virt(Where); } diff --git a/drivers/hpet.cc b/drivers/hpet.cc index f0828b89..f0985df1 100644 --- a/drivers/hpet.cc +++ b/drivers/hpet.cc @@ -174,7 +174,7 @@ void __attribute__((constructor(init_prio::hpet))) hpet_init() // Check what type of main counter - 32-bit or 64-bit - is available and // construct relevant hpet clock instance - mmioaddr_t hpet_mmio_address = mmio_map(hpet_address.Address, 4096); + mmioaddr_t hpet_mmio_address = mmio_map(hpet_address.Address, 4096, "hpet"); auto cap = mmio_getl(hpet_mmio_address + HPET_CAP); if (cap & HPET_CAP_COUNT_SIZE) { diff --git a/drivers/mmio-isa-serial.cc b/drivers/mmio-isa-serial.cc index 3675ec5f..8bce1814 100644 --- a/drivers/mmio-isa-serial.cc +++ b/drivers/mmio-isa-serial.cc @@ -31,7 +31,7 @@ void mmio_isa_serial_console::early_init(u64 mmio_phys_address) void mmio_isa_serial_console::memory_map() { if (_phys_mmio_address) { - _addr_mmio = mmio_map(_phys_mmio_address, mmu::page_size); + _addr_mmio = mmio_map(_phys_mmio_address, mmu::page_size, "isa_serial_console"); } } diff --git a/drivers/pci-function.cc b/drivers/pci-function.cc index 9d3641eb..46286128 100644 --- a/drivers/pci-function.cc +++ b/drivers/pci-function.cc @@ -84,7 +84,7 @@ namespace pci { void bar::map() { if (_is_mmio) { - _addr_mmio = mmio_map(get_addr64(), get_size()); + _addr_mmio = mmio_map(get_addr64(), get_size(), "pci_bar"); } } diff --git a/drivers/pl031.cc b/drivers/pl031.cc index b81b38b9..4daee666 100644 --- a/drivers/pl031.cc +++ b/drivers/pl031.cc @@ -21,7 +21,7 @@ pl031::pl031(u64 address) { _address = address; - mmu::linear_map((void *)_address, _address, mmu::page_size, mmu::page_size, + mmu::linear_map((void *)_address, _address, mmu::page_size, "pl031", mmu::page_size, mmu::mattr::dev); } diff --git a/drivers/virtio-mmio.cc b/drivers/virtio-mmio.cc index 91f88d89..5731b858 100644 --- a/drivers/virtio-mmio.cc +++ b/drivers/virtio-mmio.cc @@ -112,7 +112,7 @@ void mmio_device::register_interrupt(interrupt_factory irq_factory) bool mmio_device::parse_config() { - _addr_mmio = mmio_map(_dev_info._address, _dev_info._size); + _addr_mmio = mmio_map(_dev_info._address, _dev_info._size, "virtio_mmio_cfg"); u32 magic = mmio_getl(_addr_mmio + VIRTIO_MMIO_MAGIC_VALUE); if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) { diff --git a/drivers/xenconsole.cc b/drivers/xenconsole.cc index 92a76b69..f180cd67 100644 --- a/drivers/xenconsole.cc +++ b/drivers/xenconsole.cc @@ -83,7 +83,7 @@ void XEN_Console::dev_start() INTR_TYPE_MISC, &_irq) != 0) throw std::runtime_error("fail to bind evtchn"); - _interface = (xencons_interface*)mmio_map(_pfn << PAGE_SHIFT, PAGE_SIZE); + _interface = (xencons_interface*)mmio_map(_pfn << PAGE_SHIFT, PAGE_SIZE, "xen_console"); } void XEN_Console::flush() diff --git a/include/osv/mmio.hh b/include/osv/mmio.hh index 64e5d05d..586a56cf 100644 --- a/include/osv/mmio.hh +++ b/include/osv/mmio.hh @@ -25,7 +25,7 @@ u32 mmio_getl(mmioaddr_t addr); u64 mmio_getq(mmioaddr_t addr); // Map mmio regions -mmioaddr_t mmio_map(u64 paddr, size_t size_bytes); +mmioaddr_t mmio_map(u64 paddr, size_t size_bytes, const char* name); void mmio_unmap(mmioaddr_t addr, size_t size_bytes); #endif // MMIO_HH diff --git a/include/osv/mmu.hh b/include/osv/mmu.hh index 12fcb8a4..463f2001 100644 --- a/include/osv/mmu.hh +++ b/include/osv/mmu.hh @@ -43,6 +43,20 @@ constexpr inline unsigned pt_index(void *virt, unsigned level) struct page_allocator; +struct linear_vma { + void* _virt_addr; + phys _phys_addr; + size_t _size; + mattr _mem_attr; + std::string _name; + + linear_vma(void* virt, phys phys, size_t size, mattr mem_attr, const char* name); + ~linear_vma(); + + uintptr_t v_start() const { return reinterpret_cast<uintptr_t>(_virt_addr); } + uintptr_t v_end() const { return reinterpret_cast<uintptr_t>(_virt_addr + _size); } +}; + class vma { public: vma(addr_range range, unsigned perm, unsigned flags, bool map_dirty, page_allocator *page_ops = nullptr); @@ -298,7 +312,7 @@ bool is_page_aligned(void* addr) // an architecture-specific meaning. // Currently mem_attr is ignored on x86_64. For aarch64 specifics see // definitions in arch/aarch64/arch-mmu.hh -void linear_map(void* virt, phys addr, size_t size, +void linear_map(void* virt, phys addr, size_t size, const char* name, size_t slop = mmu::page_size, mattr mem_attr = mmu::mattr_default); diff --git a/include/osv/prio.hh b/include/osv/prio.hh index c3cb4742..23adc08f 100644 --- a/include/osv/prio.hh +++ b/include/osv/prio.hh @@ -16,6 +16,7 @@ enum { cpus, fpranges, pt_root, + linear_vma_set, mempool, routecache, pagecache, -- 2.31.1 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/20220317012333.871483-1-jwkozaczuk%40gmail.com.
