Kernel: Implement bare boness DMA Region

This does nothing but allocate contiguous physical and virtual memory
and map it as CacheDisable. Also memory is automatically freed RAII style.
This commit is contained in:
2023-10-08 02:56:01 +03:00
parent 8a9816d6e0
commit 211cad03ff
3 changed files with 74 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
#include <BAN/ScopeGuard.h>
#include <kernel/Memory/DMARegion.h>
#include <kernel/Memory/Heap.h>
namespace Kernel
{
BAN::ErrorOr<BAN::UniqPtr<DMARegion>> DMARegion::create(size_t size)
{
size_t needed_pages = BAN::Math::div_round_up<size_t>(size, PAGE_SIZE);
vaddr_t vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET);
if (vaddr == 0)
return BAN::Error::from_errno(ENOMEM);
BAN::ScopeGuard vaddr_guard([vaddr, size] { PageTable::kernel().unmap_range(vaddr, size); });
paddr_t paddr = Heap::get().take_free_contiguous_pages(needed_pages);
if (paddr == 0)
return BAN::Error::from_errno(ENOMEM);
BAN::ScopeGuard paddr_guard([paddr, needed_pages] { Heap::get().release_contiguous_pages(paddr, needed_pages); });
auto* region_ptr = new DMARegion(size, vaddr, paddr);
if (region_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
vaddr_guard.disable();
paddr_guard.disable();
PageTable::kernel().map_range_at(paddr, vaddr, size, PageTable::Flags::CacheDisable | PageTable::Flags::ReadWrite | PageTable::Flags::Reserved);
return BAN::UniqPtr<DMARegion>::adopt(region_ptr);
}
DMARegion::DMARegion(size_t size, vaddr_t vaddr, paddr_t paddr)
: m_size(size)
, m_vaddr(vaddr)
, m_paddr(paddr)
{ }
DMARegion::~DMARegion()
{
PageTable::kernel().unmap_range(m_vaddr, m_size);
Heap::get().release_contiguous_pages(m_vaddr, BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE));
}
}