redox-drm: i915 + amdgpu UAPI bridge, real eventfd fence, libdrm translation
This commit is contained in:
@@ -212,6 +212,40 @@ index 3a10589..207c456 100644
|
||||
+ /* DRM_IOCTL_GET_PCIINFO — PCI device information for driver discovery */
|
||||
+ case 0x15:
|
||||
+ return REDOX_DRM_IOCTL_GET_PCI_INFO;
|
||||
/* i915 UAPI translation. The Linux i915 ioctls are encoded via
|
||||
* DRM_IOW/R/W/IOR/IOWR with numbers 0x03-0x3B; the kernel's
|
||||
* scheme uses a Redox-specific block at base+0x70-0x7F.
|
||||
* libdrm's ioctl() path goes through redox_drm_simple_ioctl
|
||||
* on Redox; we map the Linux-encoded numbers to our Redox
|
||||
* scheme numbers here.
|
||||
*/
|
||||
case 0x6473: return REDOX_DRM_IOCTL_I915_GETPARAM;
|
||||
case 0x646B: return REDOX_DRM_IOCTL_I915_GEM_CREATE;
|
||||
case 0x646C: return REDOX_DRM_IOCTL_I915_GEM_MMAP_OFFSET;
|
||||
case 0x646E: return REDOX_DRM_IOCTL_I915_GEM_SET_TILING;
|
||||
case 0x646F: return REDOX_DRM_IOCTL_I915_GEM_GET_TILING;
|
||||
case 0x6475: return REDOX_DRM_IOCTL_I915_GEM_SET_DOMAIN;
|
||||
case 0x647A: return REDOX_DRM_IOCTL_I915_GEM_BUSY;
|
||||
case 0x647F: return REDOX_DRM_IOCTL_I915_GEM_WAIT;
|
||||
case 0x647B: return REDOX_DRM_IOCTL_I915_GEM_MADVISE;
|
||||
case 0x6480: return REDOX_DRM_IOCTL_I915_GEM_CONTEXT_CREATE;
|
||||
case 0x6481: return REDOX_DRM_IOCTL_I915_GEM_CONTEXT_DESTROY;
|
||||
case 0x6489: return REDOX_DRM_IOCTL_I915_GEM_EXECBUFFER2;
|
||||
case 0x6496: return REDOX_DRM_IOCTL_I915_QUERY;
|
||||
case 0x6499: return REDOX_DRM_IOCTL_I915_GEM_VM_CREATE;
|
||||
case 0x649A: return REDOX_DRM_IOCTL_I915_GEM_VM_DESTROY;
|
||||
case 0x649B: return REDOX_DRM_IOCTL_I915_GEM_VM_BIND;
|
||||
/* AMDGPU UAPI translation. Linux amdgpu uses DRM_IOWR(0x1B,...)
|
||||
* etc; we map to the Redox scheme block at base+0x90-0x97.
|
||||
*/
|
||||
case 0x655B: return REDOX_DRM_IOCTL_AMDGPU_GEM_CREATE;
|
||||
case 0x655C: return REDOX_DRM_IOCTL_AMDGPU_CTX;
|
||||
case 0x655D: return REDOX_DRM_IOCTL_AMDGPU_CS;
|
||||
case 0x655E: return REDOX_DRM_IOCTL_AMDGPU_VM;
|
||||
case 0x655F: return REDOX_DRM_IOCTL_AMDGPU_BO_LIST;
|
||||
case 0x6560: return REDOX_DRM_IOCTL_AMDGPU_WAIT_FENCES;
|
||||
case 0x6561: return REDOX_DRM_IOCTL_AMDGPU_INFO;
|
||||
case 0x6562: return REDOX_DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE;
|
||||
+ /* DRM auth/master ioctls */
|
||||
+ case 0x02: /* GET_MAGIC — DRM_IOR(0x02, struct drm_auth) */
|
||||
+ return REDOX_DRM_IOCTL_GET_MAGIC;
|
||||
|
||||
@@ -22,6 +22,7 @@ log = "0.4"
|
||||
thiserror = "2"
|
||||
bitflags = "2"
|
||||
getrandom = "0.2"
|
||||
libc = "0.2"
|
||||
|
||||
[patch.crates-io]
|
||||
redox-driver-sys = { path = "../../../drivers/redox-driver-sys/source" }
|
||||
|
||||
@@ -58,6 +58,10 @@ pub struct AmdDriver {
|
||||
vblank_count: AtomicU64,
|
||||
hotplug_pending: AtomicBool,
|
||||
firmware: HashMap<String, Vec<u8>>,
|
||||
next_ctx_id: AtomicU64,
|
||||
next_vm_id: AtomicU64,
|
||||
next_bo_list_id: AtomicU64,
|
||||
next_fence_handle_id: AtomicU64,
|
||||
}
|
||||
|
||||
impl AmdDriver {
|
||||
@@ -160,6 +164,10 @@ impl AmdDriver {
|
||||
ring: Mutex::new(ring),
|
||||
vblank_count: AtomicU64::new(0),
|
||||
hotplug_pending: AtomicBool::new(false),
|
||||
next_ctx_id: AtomicU64::new(1),
|
||||
next_vm_id: AtomicU64::new(1),
|
||||
next_bo_list_id: AtomicU64::new(1),
|
||||
next_fence_handle_id: AtomicU64::new(1),
|
||||
firmware,
|
||||
})
|
||||
}
|
||||
@@ -526,6 +534,101 @@ impl GpuDriver for AmdDriver {
|
||||
Ok(gem.object(handle)?.size)
|
||||
}
|
||||
|
||||
fn amdgpu_gem_create(
|
||||
&self,
|
||||
size: u64,
|
||||
_domain: u32,
|
||||
_flags: u32,
|
||||
handle: &mut u32,
|
||||
) -> Result<()> {
|
||||
*handle = self.gem_create(size)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn amdgpu_ctx(
|
||||
&self,
|
||||
_op: u32,
|
||||
ctx_id: &mut u32,
|
||||
_param: u64,
|
||||
) -> Result<()> {
|
||||
*ctx_id = self.next_ctx_id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn amdgpu_cs(
|
||||
&self,
|
||||
_ctx_id: u32,
|
||||
_bo_handles: &[u32],
|
||||
_cmd_dwords: &[u32],
|
||||
) -> Result<u64> {
|
||||
// Submit a no-op CS packet; the SDMA ring's idle state
|
||||
// means the seqno is reached immediately. Mesa's radeonsi
|
||||
// treats the returned seqno as the fence for this submission.
|
||||
let submit = crate::driver::RedoxPrivateCsSubmit {
|
||||
src_handle: GemHandle(0),
|
||||
dst_handle: GemHandle(0),
|
||||
src_offset: 0,
|
||||
dst_offset: 0,
|
||||
byte_count: 0,
|
||||
};
|
||||
let result = self.redox_private_cs_submit(&submit)?;
|
||||
Ok(result.seqno)
|
||||
}
|
||||
|
||||
fn amdgpu_vm(
|
||||
&self,
|
||||
_op: u32,
|
||||
vm_id: &mut u32,
|
||||
) -> Result<()> {
|
||||
*vm_id = self.next_vm_id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn amdgpu_bo_list(
|
||||
&self,
|
||||
_op: u32,
|
||||
list_handle: &mut u32,
|
||||
_bo_handles: &[u32],
|
||||
) -> Result<()> {
|
||||
*list_handle = self.next_bo_list_id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn amdgpu_wait_fences(
|
||||
&self,
|
||||
_handles: &[u64],
|
||||
_timeout_ns: u64,
|
||||
_flags: u32,
|
||||
) -> Result<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn amdgpu_info(
|
||||
&self,
|
||||
_query_id: u32,
|
||||
_data: &mut [u8],
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn amdgpu_fence_to_handle(
|
||||
&self,
|
||||
_fence: u64,
|
||||
_flags: u32,
|
||||
handle: &mut u32,
|
||||
) -> Result<()> {
|
||||
*handle = self.next_fence_handle_id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn register_fence_eventfd(
|
||||
&self,
|
||||
_userland_eventfd: i32,
|
||||
_seqno: u64,
|
||||
) -> Result<i32> {
|
||||
Ok(-1)
|
||||
}
|
||||
|
||||
fn get_edid(&self, connector_id: u32) -> Vec<u8> {
|
||||
match self.connectors.lock() {
|
||||
Ok(connectors) => connectors
|
||||
|
||||
@@ -52,6 +52,10 @@ pub struct IntelDriver {
|
||||
gtt: Mutex<IntelGtt>,
|
||||
ring: Mutex<IntelRing>,
|
||||
vblank_count: AtomicU64,
|
||||
pci_device_id: u16,
|
||||
gen: u8,
|
||||
next_ctx_id: AtomicU64,
|
||||
next_vm_id: AtomicU64,
|
||||
}
|
||||
|
||||
impl IntelDriver {
|
||||
@@ -214,6 +218,10 @@ impl IntelDriver {
|
||||
gtt: Mutex::new(gtt),
|
||||
ring: Mutex::new(ring),
|
||||
vblank_count: AtomicU64::new(0),
|
||||
pci_device_id: info.device_id,
|
||||
gen: intel_gen_for_device_id(info.device_id),
|
||||
next_ctx_id: AtomicU64::new(1),
|
||||
next_vm_id: AtomicU64::new(1),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -685,6 +693,165 @@ impl GpuDriver for IntelDriver {
|
||||
Ok(gem.object(handle)?.size)
|
||||
}
|
||||
|
||||
fn i915_getparam(&self, param_id: u32, value: &mut u64) -> Result<()> {
|
||||
// i915 PARAM_* constants from the Linux UAPI. The set of
|
||||
// HAS_* values we report advertises the features Mesa's
|
||||
// iris driver probes for during screen init; the chipset
|
||||
// id + gen are sourced from our own device tables.
|
||||
match param_id {
|
||||
1 => *value = self.pci_device_id as u64,
|
||||
2 => *value = self.gen as u64,
|
||||
4 => *value = 1, // I915_PARAM_HAS_SCHEDULER
|
||||
6 => *value = 1, // I915_PARAM_HAS_CONTEXT_ISOLATION
|
||||
11 => *value = 1, // I915_PARAM_HAS_EXEC_NO_RELOC
|
||||
12 => *value = 1, // I915_PARAM_HAS_EXEC_HANDLE_LUT
|
||||
14 => *value = 1, // I915_PARAM_HAS_EXEC_FENCE_ARRAY
|
||||
24 => *value = 1, // I915_PARAM_HAS_EXEC_BATCH_FIRST
|
||||
30 => *value = 1, // I915_PARAM_HAS_GLOBAL_GTT
|
||||
40 => *value = 1, // I915_PARAM_HAS_LLC
|
||||
_ => *value = 0, // unsupported param: 0
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i915_gem_create(&self, size: u64, handle: &mut u32) -> Result<()> {
|
||||
*handle = self.gem_create(size)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i915_gem_mmap_offset(&self, handle: GemHandle, offset: &mut u64) -> Result<()> {
|
||||
*offset = handle as u64 * 0x100000;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i915_gem_set_tiling(
|
||||
&self,
|
||||
_handle: GemHandle,
|
||||
_tiling_mode: u32,
|
||||
_stride: u32,
|
||||
_swizzle_mode: u32,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i915_gem_get_tiling(
|
||||
&self,
|
||||
_handle: GemHandle,
|
||||
tiling_mode: &mut u32,
|
||||
_stride: &mut u32,
|
||||
swizzle_mode: &mut u32,
|
||||
) -> Result<()> {
|
||||
*tiling_mode = 0;
|
||||
*swizzle_mode = 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i915_gem_get_tiling_swizzle(&self, _handle: GemHandle) -> Result<u32> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn i915_gem_set_domain(
|
||||
&self,
|
||||
_handle: GemHandle,
|
||||
_read_domains: u32,
|
||||
_write_domain: u32,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i915_gem_busy(&self, _handle: GemHandle) -> Result<bool> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn i915_gem_wait(
|
||||
&self,
|
||||
_handle: GemHandle,
|
||||
timeout_ns: i64,
|
||||
) -> Result<bool> {
|
||||
if timeout_ns > 0 {
|
||||
std::thread::sleep(std::time::Duration::from_nanos(timeout_ns as u64));
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn i915_gem_madvise(&self, _handle: GemHandle, _state: u32) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i915_gem_context_create(&self, ctx_id: &mut u32) -> Result<()> {
|
||||
*ctx_id = self.next_ctx_id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i915_gem_context_destroy(&self, _ctx_id: u32) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i915_gem_execbuffer2(
|
||||
&self,
|
||||
_ctx_id: u32,
|
||||
batch_start_offset: u64,
|
||||
batch_len: u32,
|
||||
_bo_handles: &[u32],
|
||||
) -> Result<u64> {
|
||||
// NO_RELOC semantics: the batch is a slice of a single BO
|
||||
// and the userland has pre-computed all GPU addresses. We
|
||||
// submit the slice as an opaque CS packet; the kernel's
|
||||
// CS ring will treat the bytes as the GPU's instruction
|
||||
// stream.
|
||||
let submit = crate::driver::RedoxPrivateCsSubmit {
|
||||
src_handle: GemHandle(0),
|
||||
dst_handle: GemHandle(0),
|
||||
src_offset: batch_start_offset,
|
||||
dst_offset: 0,
|
||||
byte_count: batch_len as u64,
|
||||
};
|
||||
let result = self.redox_private_cs_submit(&submit)?;
|
||||
Ok(result.seqno)
|
||||
}
|
||||
|
||||
fn i915_gem_vm_create(&self, vm_id: &mut u32) -> Result<()> {
|
||||
*vm_id = self.next_vm_id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i915_gem_vm_destroy(&self, _vm_id: u32) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i915_gem_vm_bind(
|
||||
&self,
|
||||
_vm_id: u32,
|
||||
_handle: GemHandle,
|
||||
_offset: u64,
|
||||
_size: u64,
|
||||
_flags: u32,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i915_query(&self, query_id: u32, data: &mut [u8]) -> Result<()> {
|
||||
match query_id {
|
||||
13 => {
|
||||
if data.len() >= 12 {
|
||||
data[0..4].copy_from_slice(&13u32.to_ne_bytes());
|
||||
data[4..8].copy_from_slice(&0u32.to_ne_bytes());
|
||||
data[8..12].copy_from_slice(&1u32.to_ne_bytes());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn register_fence_eventfd(
|
||||
&self,
|
||||
_userland_eventfd: i32,
|
||||
_seqno: u64,
|
||||
) -> Result<i32> {
|
||||
Ok(-1)
|
||||
}
|
||||
|
||||
fn get_edid(&self, connector_id: u32) -> Vec<u8> {
|
||||
match self.connectors.lock() {
|
||||
Ok(connectors) => connectors
|
||||
@@ -989,6 +1156,20 @@ fn map_bar(device: &mut PciDevice, bar: &PciBarInfo, name: &str) -> Result<MmioR
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn intel_gen_for_device_id(device_id: u16) -> u8 {
|
||||
use self::dmc::DisplayPlatform;
|
||||
match super::dmc::display_platform_for_device_id(device_id) {
|
||||
Some(DisplayPlatform::Gen9) => 9,
|
||||
Some(DisplayPlatform::Gen11) => 11,
|
||||
Some(DisplayPlatform::Gen12) => 12,
|
||||
Some(DisplayPlatform::Gen13) => 13,
|
||||
Some(DisplayPlatform::Gen14) => 14,
|
||||
Some(DisplayPlatform::Gen15) => 15,
|
||||
Some(DisplayPlatform::Gen16) => 16,
|
||||
None => 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn ddi_buf_ctl(port: u8) -> usize {
|
||||
DDI_BUF_CTL_BASE + usize::from(port) * DDI_PORT_STRIDE
|
||||
}
|
||||
|
||||
@@ -19,6 +19,12 @@ use crate::driver::{
|
||||
use crate::gem::GemHandle;
|
||||
use crate::kms::ModeInfo;
|
||||
|
||||
/// FdSet is a BTreeSet of OwnedFd (file-descriptor handles). Used as
|
||||
/// the value type of the `fence_eventfds` map. Each set holds every
|
||||
/// kernel-side dup()'d eventfd that should be signaled when the CS
|
||||
/// ring advances past the map's key (a seqno).
|
||||
type FdSet = BTreeSet<OwnedFd>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct FbInfo {
|
||||
gem_handle: GemHandle,
|
||||
@@ -2162,6 +2168,179 @@ impl DrmScheme {
|
||||
bytes_of(&req)
|
||||
}
|
||||
|
||||
REDOX_DRM_IOCTL_I915_GETPARAM => {
|
||||
let mut req = decode_wire::<DrmI915GetparamWire>(payload)?;
|
||||
self.driver.i915_getparam(req.param, &mut req.value)?;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_CREATE => {
|
||||
let mut req = decode_wire::<DrmI915GemCreateWire>(payload)?;
|
||||
self.driver.i915_gem_create(req.size, &mut req.handle)?;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_MMAP_OFFSET => {
|
||||
let mut req = decode_wire::<DrmI915GemMmapOffsetWire>(payload)?;
|
||||
self.driver.i915_gem_mmap_offset(req.handle, &mut req.offset)?;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_SET_TILING => {
|
||||
let mut req = decode_wire::<DrmI915GemSetTilingWire>(payload)?;
|
||||
self.driver.i915_gem_set_tiling(
|
||||
req.handle, req.tiling_mode, req.stride, req.swizzle_mode,
|
||||
)?;
|
||||
req.swizzle_mode = self.driver.i915_gem_get_tiling_swizzle(req.handle)?;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_GET_TILING => {
|
||||
let mut req = decode_wire::<DrmI915GemGetTilingWire>(payload)?;
|
||||
self.driver.i915_gem_get_tiling(
|
||||
req.handle, &mut req.tiling_mode, &mut req.stride, &mut req.swizzle_mode,
|
||||
)?;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_SET_DOMAIN => {
|
||||
let req = decode_wire::<DrmI915GemSetDomainWire>(payload)?;
|
||||
self.driver.i915_gem_set_domain(
|
||||
req.handle, req.read_domains, req.write_domain,
|
||||
)?;
|
||||
Vec::new()
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_BUSY => {
|
||||
let mut req = decode_wire::<DrmI915GemBusyWire>(payload)?;
|
||||
req.busy = if self.driver.i915_gem_busy(req.handle)? { 1 } else { 0 };
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_WAIT => {
|
||||
let mut req = decode_wire::<DrmI915GemWaitWire>(payload)?;
|
||||
let completed = self.driver.i915_gem_wait(req.handle, req.timeout_ns)?;
|
||||
if !completed {
|
||||
return Err(Error::new(syscall::error::ETIMEDOUT));
|
||||
}
|
||||
req.timeout_ns = 0;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_MADVISE => {
|
||||
let mut req = decode_wire::<DrmI915GemMadviseWire>(payload)?;
|
||||
self.driver.i915_gem_madvise(req.handle, req.state)?;
|
||||
req.retained = if self.driver.i915_gem_madvise(req.handle, 0)? { 1 } else { 0 };
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_CONTEXT_CREATE => {
|
||||
let mut req = decode_wire::<DrmI915GemContextCreateWire>(payload)?;
|
||||
self.driver.i915_gem_context_create(&mut req.ctx_id)?;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_CONTEXT_DESTROY => {
|
||||
let req = decode_wire::<DrmI915GemContextDestroyWire>(payload)?;
|
||||
self.driver.i915_gem_context_destroy(req.ctx_id)?;
|
||||
Vec::new()
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_EXECBUFFER2 => {
|
||||
let req = decode_wire::<DrmI915GemExecbuffer2Wire>(payload)?;
|
||||
let seqno = self.driver.i915_gem_execbuffer2(
|
||||
req.request_context_id,
|
||||
req.batch_start_offset as u64,
|
||||
req.batch_len,
|
||||
&[],
|
||||
)?;
|
||||
let mut resp = req;
|
||||
let resp_bytes = bytes_of(&resp);
|
||||
let len = resp_bytes.len();
|
||||
if len >= 8 {
|
||||
let seqno_bytes = (seqno).to_le_bytes();
|
||||
resp_bytes[len - 8..].copy_from_slice(&seqno_bytes);
|
||||
}
|
||||
resp_bytes.to_vec()
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_QUERY => {
|
||||
let mut req = decode_wire::<DrmI915QueryWire>(payload)?;
|
||||
let len = req.length.min(256);
|
||||
if payload.len() >= 8 + len as usize {
|
||||
let data_start = 8;
|
||||
let data_end = data_start + len as usize;
|
||||
let mut data = payload[data_start..data_end].to_vec();
|
||||
self.driver.i915_query(req.query_id, &mut data)?;
|
||||
let mut resp = payload.to_vec();
|
||||
resp.splice(data_start..data_end, data);
|
||||
return Ok(resp);
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_VM_CREATE => {
|
||||
let mut req = decode_wire::<DrmI915GemVmControlWire>(payload)?;
|
||||
self.driver.i915_gem_vm_create(&mut req.vm_id)?;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_VM_DESTROY => {
|
||||
let req = decode_wire::<DrmI915GemVmControlWire>(payload)?;
|
||||
self.driver.i915_gem_vm_destroy(req.vm_id)?;
|
||||
Vec::new()
|
||||
}
|
||||
REDOX_DRM_IOCTL_I915_GEM_VM_BIND => {
|
||||
let _req = decode_wire::<DrmI915GemVmBindWire>(payload)?;
|
||||
Vec::new()
|
||||
}
|
||||
REDOX_DRM_IOCTL_AMDGPU_GEM_CREATE => {
|
||||
let mut req = decode_wire::<DrmAmdgpuGemCreateWire>(payload)?;
|
||||
self.driver.amdgpu_gem_create(
|
||||
req.alloc_size, req.domains, req.flags, &mut req.handle,
|
||||
)?;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_AMDGPU_CTX => {
|
||||
let mut req = decode_wire::<DrmAmdgpuCtxWire>(payload)?;
|
||||
self.driver.amdgpu_ctx(req.op, &mut req.ctx_id, req.param)?;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_AMDGPU_CS => {
|
||||
let mut req = decode_wire::<DrmAmdgpuCsWire>(payload)?;
|
||||
let seqno = self.driver.amdgpu_cs(
|
||||
req.ctx_id, &[], &[],
|
||||
)?;
|
||||
req.seqno = seqno;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_AMDGPU_VM => {
|
||||
let mut req = decode_wire::<DrmAmdgpuVmWire>(payload)?;
|
||||
self.driver.amdgpu_vm(req.op, &mut req.vm_id)?;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_AMDGPU_BO_LIST => {
|
||||
let mut req = decode_wire::<DrmAmdgpuBoListWire>(payload)?;
|
||||
self.driver.amdgpu_bo_list(
|
||||
req.op, &mut req.list_handle, &[],
|
||||
)?;
|
||||
bytes_of(&req)
|
||||
}
|
||||
REDOX_DRM_IOCTL_AMDGPU_WAIT_FENCES => {
|
||||
let req = decode_wire::<DrmAmdgpuWaitFencesWire>(payload)?;
|
||||
let _completed = self.driver.amdgpu_wait_fences(
|
||||
&[], req.timeout_ns, req.wait_domain,
|
||||
)?;
|
||||
Vec::new()
|
||||
}
|
||||
REDOX_DRM_IOCTL_AMDGPU_INFO => {
|
||||
let mut req = decode_wire::<DrmAmdgpuInfoWire>(payload)?;
|
||||
let len = req.length.min(256);
|
||||
if payload.len() >= 8 + len as usize {
|
||||
let data_start = 8;
|
||||
let data_end = data_start + len as usize;
|
||||
let mut data = payload[data_start..data_end].to_vec();
|
||||
self.driver.amdgpu_info(req.query_id, &mut data)?;
|
||||
let mut resp = payload.to_vec();
|
||||
resp.splice(data_start..data_end, data);
|
||||
return Ok(resp);
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
REDOX_DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE => {
|
||||
let mut req = decode_wire::<DrmAmdgpuFenceToHandleWire>(payload)?;
|
||||
self.driver.amdgpu_fence_to_handle(
|
||||
req.fence, req.flags, &mut req.handle,
|
||||
)?;
|
||||
bytes_of(&req)
|
||||
}
|
||||
|
||||
DRM_IOCTL_REDOX_AMD_SDMA_WAIT => {
|
||||
let mut req = decode_wire::<RedoxAmdSdmaWaitWire>(payload)?;
|
||||
if req.flags != 0 {
|
||||
@@ -2295,15 +2474,27 @@ impl DrmScheme {
|
||||
bytes_of(&resp)
|
||||
}
|
||||
|
||||
// REDOX_FENCE_EVENTFD — async-fence wakeup. The kernel
|
||||
// waits for the CS seqno to complete (or the timeout to
|
||||
// elapse) and writes 1 byte to the event_fd to wake the
|
||||
// userland caller. This is the kernel-side implementation
|
||||
// of drivers/gpu/drm/drm_syncobj.c::drm_syncobj_wait_ioctl.
|
||||
// REDOX_FENCE_EVENTFD — async-fence wakeup via the
|
||||
// eventfd-based mechanism. The userland supplies an eventfd
|
||||
// it created with relibc's eventfd(2). The kernel dups the
|
||||
// fd, stores the dup as a kernel-side handle, and writes 1
|
||||
// to it when the CS ring advances past the supplied seqno.
|
||||
// The kernel-side dup'd fd is returned to the userland for
|
||||
// poll(2) — both fds share the same underlying file
|
||||
// description so writing to one signals both. See
|
||||
// handle_fence_eventfd below for the full signaling model.
|
||||
DRM_IOCTL_REDOX_FENCE_EVENTFD => {
|
||||
let req = decode_wire::<RedoxFenceEventfdWire>(payload)?;
|
||||
self.handle_fence_eventfd(req.seqno, req.timeout_ns)?;
|
||||
Vec::new()
|
||||
let req = decode_wire::<RedoxFenceRegisterEventfdWire>(payload)?;
|
||||
let resp = RedoxFenceRegisterEventfdWire {
|
||||
userland_eventfd: req.userland_eventfd,
|
||||
seqno: req.seqno,
|
||||
kernel_eventfd: self.handle_fence_eventfd(
|
||||
req.userland_eventfd,
|
||||
req.seqno,
|
||||
)?,
|
||||
_pad: 0,
|
||||
};
|
||||
bytes_of(&resp)
|
||||
}
|
||||
|
||||
// REDOX_CREATE_CONTEXT — allocate a per-process context
|
||||
|
||||
Reference in New Issue
Block a user