mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
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:
parent
307223a5a7
commit
961ba9ec6c
9 changed files with 78 additions and 36 deletions
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue