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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
#include <sortix/kernel/interrupt.h>
|
#include <sortix/kernel/interrupt.h>
|
||||||
#include <sortix/kernel/ioctx.h>
|
#include <sortix/kernel/ioctx.h>
|
||||||
#include <sortix/kernel/log.h>
|
#include <sortix/kernel/log.h>
|
||||||
|
#include <sortix/kernel/memorymanagement.h>
|
||||||
#include <sortix/kernel/panic.h>
|
#include <sortix/kernel/panic.h>
|
||||||
#include <sortix/kernel/pci.h>
|
#include <sortix/kernel/pci.h>
|
||||||
#include <sortix/kernel/pci-mmio.h>
|
#include <sortix/kernel/pci-mmio.h>
|
||||||
|
@ -141,7 +142,7 @@ bool HBA::Initialize(Ref<Descriptor> dev, const char* devpath)
|
||||||
return errno = EINVAL, false;
|
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");
|
LogF("error: registers could not be mapped: %m");
|
||||||
return false;
|
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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -39,7 +39,6 @@
|
||||||
#include <sortix/kernel/video.h>
|
#include <sortix/kernel/video.h>
|
||||||
|
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
#include "x86-family/memorymanagement.h"
|
|
||||||
#include "x86-family/vbox.h"
|
#include "x86-family/vbox.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -521,7 +520,6 @@ TextBuffer* BGADevice::CreateTextBuffer(uint64_t connector,
|
||||||
{
|
{
|
||||||
if ( !Supports(connector, mode) )
|
if ( !Supports(connector, mode) )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if ( connector != 0 )
|
if ( connector != 0 )
|
||||||
return errno = EINVAL, (TextBuffer*) NULL;
|
return errno = EINVAL, (TextBuffer*) NULL;
|
||||||
|
|
||||||
|
@ -549,7 +547,7 @@ static void TryInitializeDevice(uint32_t devaddr)
|
||||||
bool fallback_ioport = false;
|
bool fallback_ioport = false;
|
||||||
|
|
||||||
fb_bar = PCI::GetBAR(devaddr, 0);
|
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",
|
Log::PrintF("[BGA device @ PCI:0x%X] Framebuffer could not be mapped: %s\n",
|
||||||
devaddr, strerror(errno));
|
devaddr, strerror(errno));
|
||||||
|
@ -563,7 +561,7 @@ static void TryInitializeDevice(uint32_t devaddr)
|
||||||
{
|
{
|
||||||
has_mmio = true;
|
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",
|
Log::PrintF("[BGA device @ PCI:0x%X] Memory-mapped registers could not be mapped: %s\n",
|
||||||
devaddr, strerror(errno));
|
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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* 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 Sortix {
|
||||||
namespace Memory {
|
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 Init(multiboot_info_t* bootinfo);
|
||||||
void InvalidatePage(addr_t addr);
|
void InvalidatePage(addr_t addr);
|
||||||
void Flush();
|
void Flush();
|
||||||
|
@ -90,6 +98,7 @@ addr_t GetAddressSpace();
|
||||||
addr_t SwitchAddressSpace(addr_t addrspace);
|
addr_t SwitchAddressSpace(addr_t addrspace);
|
||||||
void DestroyAddressSpace(addr_t fallback);
|
void DestroyAddressSpace(addr_t fallback);
|
||||||
bool Map(addr_t physical, addr_t mapto, int prot);
|
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 Unmap(addr_t mapto);
|
||||||
addr_t Physical(addr_t mapto);
|
addr_t Physical(addr_t mapto);
|
||||||
int PageProtection(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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -21,14 +21,24 @@
|
||||||
#define INCLUDE_SORTIX_KERNEL_PCI_MMIO_H
|
#define INCLUDE_SORTIX_KERNEL_PCI_MMIO_H
|
||||||
|
|
||||||
#include <sortix/kernel/addralloc.h>
|
#include <sortix/kernel/addralloc.h>
|
||||||
|
#include <sortix/kernel/memorymanagement.h>
|
||||||
#include <sortix/kernel/pci.h>
|
#include <sortix/kernel/pci.h>
|
||||||
|
|
||||||
namespace Sortix {
|
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);
|
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
|
} // 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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
#include <sortix/kernel/addralloc.h>
|
#include <sortix/kernel/addralloc.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
#include <sortix/kernel/log.h>
|
#include <sortix/kernel/log.h>
|
||||||
|
#include <sortix/kernel/memorymanagement.h>
|
||||||
#include <sortix/kernel/pci.h>
|
#include <sortix/kernel/pci.h>
|
||||||
#include <sortix/kernel/pci-mmio.h>
|
#include <sortix/kernel/pci-mmio.h>
|
||||||
#include <sortix/kernel/textbuffer.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.size_raw = (uint64_t) bootinfo->framebuffer_pitch * bootinfo->framebuffer_height;
|
||||||
fakebar.addr_raw |= PCIBAR_TYPE_64BIT;
|
fakebar.addr_raw |= PCIBAR_TYPE_64BIT;
|
||||||
addralloc_t fb_alloc;
|
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.");
|
Panic("Framebuffer setup failure.");
|
||||||
uint8_t* lfb = (uint8_t*) fb_alloc.from;
|
uint8_t* lfb = (uint8_t*) fb_alloc.from;
|
||||||
uint32_t lfbformat = bootinfo->framebuffer_bpp;
|
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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
namespace Sortix {
|
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() )
|
if ( !bar.is_mmio() )
|
||||||
return errno = EINVAL, false;
|
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 )
|
if ( sizeof(void*) <= 4 && 0x100000000 <= phys_addr + i )
|
||||||
errno = EOVERFLOW, failure = true;
|
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
|
else
|
||||||
{
|
{
|
||||||
if ( !Memory::Map(phys_addr + i, mapat, prot) )
|
if ( !Memory::MapPAT(phys_addr + i, mapat, prot, mtype) )
|
||||||
failure = true;
|
failure = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,4 +114,41 @@ void UnmapPCIBar(addralloc_t* allocation)
|
||||||
memset(allocation, 0, sizeof(*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
|
} // 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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* 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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -20,6 +20,8 @@
|
||||||
#ifndef SORTIX_X86_FAMILY_MEMORYMANAGEMENT_H
|
#ifndef SORTIX_X86_FAMILY_MEMORYMANAGEMENT_H
|
||||||
#define SORTIX_X86_FAMILY_MEMORYMANAGEMENT_H
|
#define SORTIX_X86_FAMILY_MEMORYMANAGEMENT_H
|
||||||
|
|
||||||
|
#include <sortix/kernel/memorymanagement.h>
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
|
|
||||||
struct PML
|
struct PML
|
||||||
|
@ -49,13 +51,6 @@ const addr_t PML_NX = 0;
|
||||||
#endif
|
#endif
|
||||||
const addr_t PML_FLAGS = 0xFFFUL | PML_NX; // Bits used for the flags.
|
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 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)
|
// Desired PAT-Register PA-Field Indexing (different from BIOS defaults)
|
||||||
const addr_t PA[PAT_NUM] =
|
const addr_t PA[PAT_NUM] =
|
||||||
|
@ -93,7 +88,6 @@ static inline addr_t EncodePATAsPMLFlag(addr_t pat)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MapPAT(addr_t physical, addr_t mapto, int prot, addr_t mtype);
|
|
||||||
addr_t ProtectionToPMLFlags(int prot);
|
addr_t ProtectionToPMLFlags(int prot);
|
||||||
int PMLFlagsToProtection(addr_t flags);
|
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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -263,7 +263,7 @@ bool VBoxDevice::Initialize()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
port = port_bar.ioaddr();
|
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");
|
LogF("error: failed to memory map BAR 1: %m");
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in a new issue