Red Bear OS — microkernel OS in Rust, based on Redox
Derivative of Redox OS (https://www.redox-os.org) adding: - AMD GPU driver (amdgpu) via LinuxKPI compat layer - ext4 filesystem support (ext4d scheme daemon) - ACPI fixes for AMD bare metal (x2APIC, DMAR, IVRS, MCFG) - Custom branding (hostname, os-release, boot identity) Build system is full upstream Redox with RBOS overlay in local/. Patches for kernel, base, and relibc are symlinked from local/patches/ and protected from make clean/distclean. Custom recipes live in local/recipes/ with symlinks into the recipes/ search path. Build: make all CONFIG_NAME=redbear-full Sync: ./local/scripts/sync-upstream.sh
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use log::{debug, warn};
|
||||
use redox_driver_sys::dma::DmaBuffer;
|
||||
|
||||
use crate::dmabuf::DmabufManager;
|
||||
use crate::driver::{DriverError, Result};
|
||||
|
||||
pub type GemHandle = u32;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct GemObject {
|
||||
#[allow(dead_code)]
|
||||
pub handle: GemHandle,
|
||||
#[allow(dead_code)]
|
||||
pub size: u64,
|
||||
pub phys_addr: usize,
|
||||
pub virt_addr: usize,
|
||||
pub gpu_addr: Option<u64>,
|
||||
}
|
||||
|
||||
struct GemAllocation {
|
||||
object: GemObject,
|
||||
#[allow(dead_code)]
|
||||
dma: DmaBuffer,
|
||||
}
|
||||
|
||||
pub struct GemManager {
|
||||
next_handle: GemHandle,
|
||||
objects: BTreeMap<GemHandle, GemAllocation>,
|
||||
dmabuf: DmabufManager,
|
||||
}
|
||||
|
||||
impl GemManager {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
next_handle: 1,
|
||||
objects: BTreeMap::new(),
|
||||
dmabuf: DmabufManager::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create(&mut self, size: u64) -> Result<GemHandle> {
|
||||
if size == 0 {
|
||||
return Err(DriverError::InvalidArgument(
|
||||
"GEM create size must be non-zero",
|
||||
));
|
||||
}
|
||||
|
||||
let handle = self.next_handle;
|
||||
self.next_handle = self.next_handle.saturating_add(1);
|
||||
|
||||
let dma = DmaBuffer::allocate(size as usize, 4096)
|
||||
.map_err(|e| DriverError::Buffer(format!("DMA allocation failed: {e}")))?;
|
||||
if !dma.is_physically_contiguous() {
|
||||
warn!(
|
||||
"redox-drm: GEM handle {} allocated without physically contiguous backing",
|
||||
handle
|
||||
);
|
||||
}
|
||||
|
||||
let object = GemObject {
|
||||
handle,
|
||||
size,
|
||||
phys_addr: dma.physical_address(),
|
||||
virt_addr: dma.as_ptr() as usize,
|
||||
gpu_addr: None,
|
||||
};
|
||||
|
||||
debug!(
|
||||
"redox-drm: created GEM handle {} size={} phys={:#x} virt={:#x}",
|
||||
handle, size, object.phys_addr, object.virt_addr
|
||||
);
|
||||
|
||||
self.objects.insert(handle, GemAllocation { object, dma });
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
pub fn close(&mut self, handle: GemHandle) -> Result<()> {
|
||||
if self.objects.remove(&handle).is_none() {
|
||||
return Err(DriverError::NotFound(format!(
|
||||
"unknown GEM handle {handle}"
|
||||
)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn mmap(&self, handle: GemHandle) -> Result<usize> {
|
||||
let allocation = self
|
||||
.objects
|
||||
.get(&handle)
|
||||
.ok_or_else(|| DriverError::NotFound(format!("unknown GEM handle {handle}")))?;
|
||||
Ok(allocation.object.virt_addr)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn export_dmafd(&mut self, handle: GemHandle) -> Result<i32> {
|
||||
let allocation = self
|
||||
.objects
|
||||
.get(&handle)
|
||||
.ok_or_else(|| DriverError::NotFound(format!("unknown GEM handle {handle}")))?;
|
||||
|
||||
self.dmabuf
|
||||
.export_with_info(handle, allocation.object.phys_addr, allocation.object.size)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn import_dmafd(&self, fd: i32) -> Result<GemHandle> {
|
||||
let handle = self.dmabuf.import(fd)?;
|
||||
let _ = self.object(handle)?;
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
pub fn object(&self, handle: GemHandle) -> Result<&GemObject> {
|
||||
self.objects
|
||||
.get(&handle)
|
||||
.map(|allocation| &allocation.object)
|
||||
.ok_or_else(|| DriverError::NotFound(format!("unknown GEM handle {handle}")))
|
||||
}
|
||||
|
||||
pub fn phys_addr(&self, handle: GemHandle) -> Result<usize> {
|
||||
Ok(self.object(handle)?.phys_addr)
|
||||
}
|
||||
|
||||
pub fn set_gpu_addr(&mut self, handle: GemHandle, gpu_addr: u64) -> Result<()> {
|
||||
let allocation = self
|
||||
.objects
|
||||
.get_mut(&handle)
|
||||
.ok_or_else(|| DriverError::NotFound(format!("unknown GEM handle {handle}")))?;
|
||||
allocation.object.gpu_addr = Some(gpu_addr);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn gpu_addr(&self, handle: GemHandle) -> Result<Option<u64>> {
|
||||
Ok(self.object(handle)?.gpu_addr)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn object_mut_ptr(&mut self, handle: GemHandle) -> Result<usize> {
|
||||
let allocation = self
|
||||
.objects
|
||||
.get_mut(&handle)
|
||||
.ok_or_else(|| DriverError::NotFound(format!("unknown GEM handle {handle}")))?;
|
||||
Ok(allocation.dma.as_mut_ptr() as usize)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user