Add cache-aware memory mapping functions.

This commit is joint work by Meisaka Yukara <Meisaka.Yukara@gmail.com> and
Jonas 'Sortie' Termansen <sortie@maxsi.org>.
This commit is contained in:
Meisaka Yukara 2015-09-20 14:57:47 +09:00 committed by Jonas 'Sortie' Termansen
parent 307223a5a7
commit 961ba9ec6c
9 changed files with 78 additions and 36 deletions

View File

@ -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 <sortix/kernel/interrupt.h>
#include <sortix/kernel/ioctx.h>
#include <sortix/kernel/log.h>
#include <sortix/kernel/memorymanagement.h>
#include <sortix/kernel/panic.h>
#include <sortix/kernel/pci.h>
#include <sortix/kernel/pci-mmio.h>
@ -141,7 +142,7 @@ bool HBA::Initialize(Ref<Descriptor> 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;

View File

@ -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 <sortix/kernel/video.h>
#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));

View File

@ -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);

View File

@ -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 <sortix/kernel/addralloc.h>
#include <sortix/kernel/memorymanagement.h>
#include <sortix/kernel/pci.h>
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

View File

@ -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 <sortix/kernel/addralloc.h>
#include <sortix/kernel/kernel.h>
#include <sortix/kernel/log.h>
#include <sortix/kernel/memorymanagement.h>
#include <sortix/kernel/pci.h>
#include <sortix/kernel/pci-mmio.h>
#include <sortix/kernel/textbuffer.h>
@ -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;

View File

@ -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

View File

@ -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

View File

@ -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 <sortix/kernel/memorymanagement.h>
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);

View File

@ -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;