From 961ba9ec6c0fb053558cbbbb381d981f9ee7100c Mon Sep 17 00:00:00 2001 From: Meisaka Yukara Date: Sun, 20 Sep 2015 14:57:47 +0900 Subject: [PATCH] Add cache-aware memory mapping functions. This commit is joint work by Meisaka Yukara and Jonas 'Sortie' Termansen . --- kernel/disk/ahci/hba.cpp | 5 +- kernel/gpu/bga/bga.cpp | 8 ++- .../include/sortix/kernel/memorymanagement.h | 11 +++- kernel/include/sortix/kernel/pci-mmio.h | 16 ++++-- kernel/log.cpp | 5 +- kernel/pci-mmio.cpp | 51 +++++++++++++++---- kernel/x86-family/memorymanagement.cpp | 2 +- kernel/x86-family/memorymanagement.h | 12 ++--- kernel/x86-family/vbox.cpp | 4 +- 9 files changed, 78 insertions(+), 36 deletions(-) diff --git a/kernel/disk/ahci/hba.cpp b/kernel/disk/ahci/hba.cpp index 5d4c4062..6190bd9b 100644 --- a/kernel/disk/ahci/hba.cpp +++ b/kernel/disk/ahci/hba.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen. + * Copyright (c) 2013, 2014, 2015, 2016, 2017 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -141,7 +142,7 @@ bool HBA::Initialize(Ref dev, const char* devpath) return errno = EINVAL, false; } - if ( !MapPCIBAR(&mmio_alloc, mmio_bar, 0) ) + if ( !MapPCIBAR(&mmio_alloc, mmio_bar, Memory::PAT_UC) ) { LogF("error: registers could not be mapped: %m"); return false; diff --git a/kernel/gpu/bga/bga.cpp b/kernel/gpu/bga/bga.cpp index 40828d22..de9cf601 100644 --- a/kernel/gpu/bga/bga.cpp +++ b/kernel/gpu/bga/bga.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, 2016 Jonas 'Sortie' Termansen. + * Copyright (c) 2012, 2014, 2016, 2017 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -39,7 +39,6 @@ #include #if defined(__i386__) || defined(__x86_64__) -#include "x86-family/memorymanagement.h" #include "x86-family/vbox.h" #endif @@ -521,7 +520,6 @@ TextBuffer* BGADevice::CreateTextBuffer(uint64_t connector, { if ( !Supports(connector, mode) ) return NULL; - if ( connector != 0 ) return errno = EINVAL, (TextBuffer*) NULL; @@ -549,7 +547,7 @@ static void TryInitializeDevice(uint32_t devaddr) bool fallback_ioport = false; fb_bar = PCI::GetBAR(devaddr, 0); - if ( !MapPCIBAR(&fb_alloc, fb_bar, MAP_PCI_BAR_WRITE_COMBINE) ) + if ( !MapPCIBAR(&fb_alloc, fb_bar, Memory::PAT_WC) ) { Log::PrintF("[BGA device @ PCI:0x%X] Framebuffer could not be mapped: %s\n", devaddr, strerror(errno)); @@ -563,7 +561,7 @@ static void TryInitializeDevice(uint32_t devaddr) { has_mmio = true; - if ( !MapPCIBAR(&mmio_alloc, mmio_bar, MAP_PCI_BAR_WRITE_COMBINE) ) + if ( !MapPCIBAR(&mmio_alloc, mmio_bar, Memory::PAT_UC) ) { Log::PrintF("[BGA device @ PCI:0x%X] Memory-mapped registers could not be mapped: %s\n", devaddr, strerror(errno)); diff --git a/kernel/include/sortix/kernel/memorymanagement.h b/kernel/include/sortix/kernel/memorymanagement.h index e49cbd4b..9e39fa13 100644 --- a/kernel/include/sortix/kernel/memorymanagement.h +++ b/kernel/include/sortix/kernel/memorymanagement.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, 2014, 2015 Jonas 'Sortie' Termansen. + * Copyright (c) 2011, 2012, 2014, 2015, 2017 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -82,6 +82,14 @@ inline bool IsAligned(addr_t page) { return AlignDown(page) == page; } namespace Sortix { namespace Memory { +const addr_t PAT_UC = 0x00; // Uncacheable +const addr_t PAT_WC = 0x01; // Write-Combine +const addr_t PAT_WT = 0x04; // Writethrough +const addr_t PAT_WP = 0x05; // Write-Protect +const addr_t PAT_WB = 0x06; // Writeback +const addr_t PAT_UCM = 0x07; // Uncacheable, overruled by MTRR. +const addr_t PAT_NUM = 0x08; + void Init(multiboot_info_t* bootinfo); void InvalidatePage(addr_t addr); void Flush(); @@ -90,6 +98,7 @@ addr_t GetAddressSpace(); addr_t SwitchAddressSpace(addr_t addrspace); void DestroyAddressSpace(addr_t fallback); bool Map(addr_t physical, addr_t mapto, int prot); +bool MapPAT(addr_t physical, addr_t mapto, int prot, addr_t mtype); addr_t Unmap(addr_t mapto); addr_t Physical(addr_t mapto); int PageProtection(addr_t mapto); diff --git a/kernel/include/sortix/kernel/pci-mmio.h b/kernel/include/sortix/kernel/pci-mmio.h index 52b40016..ef635bc5 100644 --- a/kernel/include/sortix/kernel/pci-mmio.h +++ b/kernel/include/sortix/kernel/pci-mmio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Jonas 'Sortie' Termansen. + * Copyright (c) 2014, 2017 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -21,14 +21,24 @@ #define INCLUDE_SORTIX_KERNEL_PCI_MMIO_H #include +#include #include namespace Sortix { -const int MAP_PCI_BAR_WRITE_COMBINE = 1 << 0; +struct paddrmapped_t +{ + addr_t from; + addr_t phys; + size_t size; + enum page_usage usage; +}; -bool MapPCIBAR(addralloc_t* allocation, pcibar_t bar, int flags = 0); +bool MapPCIBAR(addralloc_t* allocation, pcibar_t bar, addr_t mtype); void UnmapPCIBar(addralloc_t* allocation); +bool AllocateAndMapPage(paddrmapped_t* ret, enum page_usage usage, + addr_t mtype = Memory::PAT_WB); +void FreeAllocatedAndMappedPage(paddrmapped_t* alloc); } // namespace Sortix diff --git a/kernel/log.cpp b/kernel/log.cpp index 7ee575f1..a00ccf86 100644 --- a/kernel/log.cpp +++ b/kernel/log.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen. + * Copyright (c) 2011-2017 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -165,7 +166,7 @@ void Init(multiboot_info_t* bootinfo) fakebar.size_raw = (uint64_t) bootinfo->framebuffer_pitch * bootinfo->framebuffer_height; fakebar.addr_raw |= PCIBAR_TYPE_64BIT; addralloc_t fb_alloc; - if ( !MapPCIBAR(&fb_alloc, fakebar, MAP_PCI_BAR_WRITE_COMBINE) ) + if ( !MapPCIBAR(&fb_alloc, fakebar, Memory::PAT_WC) ) Panic("Framebuffer setup failure."); uint8_t* lfb = (uint8_t*) fb_alloc.from; uint32_t lfbformat = bootinfo->framebuffer_bpp; diff --git a/kernel/pci-mmio.cpp b/kernel/pci-mmio.cpp index 509b62c7..9bb9edf8 100644 --- a/kernel/pci-mmio.cpp +++ b/kernel/pci-mmio.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Jonas 'Sortie' Termansen. + * Copyright (c) 2014, 2016, 2017 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -35,7 +35,7 @@ namespace Sortix { -bool MapPCIBAR(addralloc_t* allocation, pcibar_t bar, int flags) +bool MapPCIBAR(addralloc_t* allocation, pcibar_t bar, addr_t mtype) { if ( !bar.is_mmio() ) return errno = EINVAL, false; @@ -78,17 +78,9 @@ bool MapPCIBAR(addralloc_t* allocation, pcibar_t bar, int flags) if ( sizeof(void*) <= 4 && 0x100000000 <= phys_addr + i ) errno = EOVERFLOW, failure = true; -#if defined(__i386__) || defined(__x86_64__) - else if ( flags & MAP_PCI_BAR_WRITE_COMBINE ) - { - const addr_t mtype = Memory::PAT_WC; - if ( !Memory::MapPAT(phys_addr + i, mapat, prot, mtype) ) - failure = true; - } -#endif else { - if ( !Memory::Map(phys_addr + i, mapat, prot) ) + if ( !Memory::MapPAT(phys_addr + i, mapat, prot, mtype) ) failure = true; } @@ -122,4 +114,41 @@ void UnmapPCIBar(addralloc_t* allocation) memset(allocation, 0, sizeof(*allocation)); } +bool AllocateAndMapPage(paddrmapped_t* ret, enum page_usage usage, addr_t mtype) +{ + addralloc_t kmem_virt; + if ( !ret ) + return errno = EINVAL, false; + if ( !AllocateKernelAddress(&kmem_virt, Page::Size()) ) + return errno = ENOMEM, false; + addr_t page = Page::Get(usage); + if ( !page ) + { + FreeKernelAddress(&kmem_virt); + return errno = ENOMEM, false; + } + int prot = PROT_KREAD | PROT_KWRITE; + if ( !Memory::MapPAT(page, kmem_virt.from, prot, mtype) ) + { + Page::Put(page, usage); + FreeKernelAddress(&kmem_virt); + return false; + } + ret->from = kmem_virt.from; + ret->size = kmem_virt.size; + ret->phys = page; + ret->usage = usage; + return true; +} + +void FreeAllocatedAndMappedPage(paddrmapped_t* alloc) +{ + if ( alloc->size == 0 ) + return; + Memory::Unmap(alloc->from); + Memory::Flush(); + Page::Put(alloc->phys, alloc->usage); + alloc->size = 0; +} + } // namespace Sortix diff --git a/kernel/x86-family/memorymanagement.cpp b/kernel/x86-family/memorymanagement.cpp index 6eaf04b3..72666370 100644 --- a/kernel/x86-family/memorymanagement.cpp +++ b/kernel/x86-family/memorymanagement.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, 2014, 2015 Jonas 'Sortie' Termansen. + * Copyright (c) 2011, 2012, 2014, 2015, 2017 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/kernel/x86-family/memorymanagement.h b/kernel/x86-family/memorymanagement.h index a1b71c80..002db5ce 100644 --- a/kernel/x86-family/memorymanagement.h +++ b/kernel/x86-family/memorymanagement.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, 2014, 2015 Jonas 'Sortie' Termansen. + * Copyright (c) 2011, 2012, 2014, 2015, 2017 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -20,6 +20,8 @@ #ifndef SORTIX_X86_FAMILY_MEMORYMANAGEMENT_H #define SORTIX_X86_FAMILY_MEMORYMANAGEMENT_H +#include + namespace Sortix { struct PML @@ -49,13 +51,6 @@ const addr_t PML_NX = 0; #endif const addr_t PML_FLAGS = 0xFFFUL | PML_NX; // Bits used for the flags. const addr_t PML_ADDRESS = ~PML_FLAGS; // Bits used for the address. -const addr_t PAT_UC = 0x00; // Uncacheable -const addr_t PAT_WC = 0x01; // Write-Combine -const addr_t PAT_WT = 0x04; // Writethrough -const addr_t PAT_WP = 0x05; // Write-Protect -const addr_t PAT_WB = 0x06; // Writeback -const addr_t PAT_UCM = 0x07; // Uncacheable, overruled by MTRR. -const addr_t PAT_NUM = 0x08; // Desired PAT-Register PA-Field Indexing (different from BIOS defaults) const addr_t PA[PAT_NUM] = @@ -93,7 +88,6 @@ static inline addr_t EncodePATAsPMLFlag(addr_t pat) return result; } -bool MapPAT(addr_t physical, addr_t mapto, int prot, addr_t mtype); addr_t ProtectionToPMLFlags(int prot); int PMLFlagsToProtection(addr_t flags); diff --git a/kernel/x86-family/vbox.cpp b/kernel/x86-family/vbox.cpp index 022d01f0..8043106d 100644 --- a/kernel/x86-family/vbox.cpp +++ b/kernel/x86-family/vbox.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Jonas 'Sortie' Termansen. + * Copyright (c) 2016, 2017 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -263,7 +263,7 @@ bool VBoxDevice::Initialize() return false; } port = port_bar.ioaddr(); - if ( !MapPCIBAR(&mmio_alloc, mmio_bar, 0) ) + if ( !MapPCIBAR(&mmio_alloc, mmio_bar, Memory::PAT_UC) ) { LogF("error: failed to memory map BAR 1: %m"); return false;