Initial commit: Schunix as it stands before the SchOS rename
An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
This commit is contained in:
commit
d0f7acf9eb
275 changed files with 51417 additions and 0 deletions
43
include/dma.h
Normal file
43
include/dma.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
// Physically contiguous memory for devices that read and write it themselves.
|
||||
//
|
||||
// kalloc() hands out 4 KB pages from a free list, in whatever order they were
|
||||
// released. That is exactly what a page table wants and exactly what a device
|
||||
// cannot use: an xHCI command ring, a NIC's descriptor array or a virtio
|
||||
// queue is a single physically contiguous object that the hardware walks
|
||||
// without any idea that paging exists. Two kalloc'd pages are adjacent in the
|
||||
// kernel's address space only by luck.
|
||||
//
|
||||
// So DMA memory comes from an arena carved out of the top of physical memory
|
||||
// before kalloc ever sees it, and is handed out contiguous and aligned.
|
||||
//
|
||||
// On x86 this memory needs no special cacheability. The PCI bus is cache
|
||||
// coherent: a device's write invalidates the corresponding cache line, and a
|
||||
// CPU write is snooped out of the store buffer before the device sees stale
|
||||
// data. Architectures without that guarantee need explicit cache maintenance
|
||||
// around every descriptor access, and porting this file is where that would
|
||||
// go. What is *not* free even here is ordering -- the compiler and the CPU
|
||||
// will happily reorder stores to a ring, so a driver still needs a barrier
|
||||
// between filling a descriptor and telling the device about it.
|
||||
|
||||
#define DMA_ARENA_BYTES (4*1024*1024)
|
||||
|
||||
void dma_init(void *vstart, void *vend);
|
||||
|
||||
// Zeroed, physically contiguous, at least `align`-aligned (align must be a
|
||||
// power of two). Returns a kernel virtual address, or 0.
|
||||
void *dma_alloc(uint64 size, uint64 align);
|
||||
|
||||
// `size` must be the size the allocation was made with, as in Linux's
|
||||
// dma_free_coherent(). Tracking it here would mean a second table whose only
|
||||
// job is to remember something the caller already knows.
|
||||
void dma_free(void *p, uint64 size);
|
||||
|
||||
// The address to give the device. Kernel memory is direct-mapped, so this is
|
||||
// just V2P -- but drivers should say what they mean, because on a machine
|
||||
// with an IOMMU these stop being the same number.
|
||||
addr_t dma_phys(const void *p);
|
||||
|
||||
uint64 dma_free_bytes(void);
|
||||
uint64 dma_total_bytes(void);
|
||||
Loading…
Reference in a new issue