diff mbox series

[2/4] WIP: drm: Introduce rvkms

Message ID 20240322221305.1403600-3-lyude@redhat.com (mailing list archive)
State New, archived
Headers show
Series Rust bindings for KMS + RVKMS | expand

Commit Message

Lyude Paul March 22, 2024, 10:03 p.m. UTC
This introduces a work in progress port of the VKMS driver to rust to
provide a user of the kernel's new rust bindings for KMS drivers! This
driver is very incomplete, I'm not even sure if it loads right now without
crashing (but it did at one point, and I'll be checking very soon!).

Squash into rvkms introduction

Signed-off-by: Lyude Paul <lyude@redhat.com>
---
 drivers/gpu/drm/Kconfig            |   2 +
 drivers/gpu/drm/Makefile           |   1 +
 drivers/gpu/drm/rvkms/Kconfig      |   3 +
 drivers/gpu/drm/rvkms/Makefile     |   1 +
 drivers/gpu/drm/rvkms/connector.rs |  55 +++++++++++
 drivers/gpu/drm/rvkms/crtc.rs      |  40 ++++++++
 drivers/gpu/drm/rvkms/encoder.rs   |  26 +++++
 drivers/gpu/drm/rvkms/file.rs      |  22 +++++
 drivers/gpu/drm/rvkms/gem.rs       |  32 +++++++
 drivers/gpu/drm/rvkms/output.rs    |  72 ++++++++++++++
 drivers/gpu/drm/rvkms/plane.rs     |  39 ++++++++
 drivers/gpu/drm/rvkms/rvkms.rs     | 146 +++++++++++++++++++++++++++++
 12 files changed, 439 insertions(+)
 create mode 100644 drivers/gpu/drm/rvkms/Kconfig
 create mode 100644 drivers/gpu/drm/rvkms/Makefile
 create mode 100644 drivers/gpu/drm/rvkms/connector.rs
 create mode 100644 drivers/gpu/drm/rvkms/crtc.rs
 create mode 100644 drivers/gpu/drm/rvkms/encoder.rs
 create mode 100644 drivers/gpu/drm/rvkms/file.rs
 create mode 100644 drivers/gpu/drm/rvkms/gem.rs
 create mode 100644 drivers/gpu/drm/rvkms/output.rs
 create mode 100644 drivers/gpu/drm/rvkms/plane.rs
 create mode 100644 drivers/gpu/drm/rvkms/rvkms.rs

Comments

Benno Lossin March 27, 2024, 9:06 p.m. UTC | #1
On 22.03.24 23:03, Lyude Paul wrote:
> diff --git a/drivers/gpu/drm/rvkms/connector.rs b/drivers/gpu/drm/rvkms/connector.rs
> new file mode 100644
> index 0000000000000..40f84d38437ee
> --- /dev/null
> +++ b/drivers/gpu/drm/rvkms/connector.rs
> @@ -0,0 +1,55 @@
> +// TODO: License and stuff
> +// Contain's rvkms's drm_connector implementation
> +
> +use super::{RvkmsDriver, RvkmsDevice, MAX_RES, DEFAULT_RES};
> +use kernel::{
> +    prelude::*,
> +    drm::{
> +        device::Device,
> +        kms::{
> +            connector::{self, ConnectorGuard},
> +            ModeConfigGuard
> +        }
> +    },
> +    prelude::*
> +};
> +use core::marker::PhantomPinned;
> +
> +#[pin_data]
> +pub(crate) struct DriverConnector {
> +    #[pin]
> +    _p: PhantomPinned
> +}

This struct does not need to be annotated with `#[pin_data]`, this
should just work:

pub(crate) struct DriverConnector;

> +
> +pub(crate) type Connector = connector::Connector<DriverConnector>;
> +
> +impl connector::DriverConnector for DriverConnector {
> +    type Initializer = impl PinInit<Self, Error>;
> +
> +    type State = ConnectorState;
> +
> +    type Driver = RvkmsDriver;
> +
> +    type Args = ();
> +
> +    fn new(dev: &Device<Self::Driver>, args: Self::Args) -> Self::Initializer {

And then here just return `Self`.

This works, since there is a blanket impl `PinInit<T, E> for T`.

Looking at how you use this API, I am not sure if you actually need
pin-init for the type that implements `DriverConnector`.
Do you need to store eg `Mutex<T>` or something else that needs
pin-init in here in a more complex driver?
Lyude Paul April 22, 2024, 1:54 a.m. UTC | #2
On Wed, 2024-03-27 at 21:06 +0000, Benno Lossin wrote:
> On 22.03.24 23:03, Lyude Paul wrote:
> > diff --git a/drivers/gpu/drm/rvkms/connector.rs
> > b/drivers/gpu/drm/rvkms/connector.rs
> > new file mode 100644
> > index 0000000000000..40f84d38437ee
> > --- /dev/null
> > +++ b/drivers/gpu/drm/rvkms/connector.rs
> > @@ -0,0 +1,55 @@
> > +// TODO: License and stuff
> > +// Contain's rvkms's drm_connector implementation
> > +
> > +use super::{RvkmsDriver, RvkmsDevice, MAX_RES, DEFAULT_RES};
> > +use kernel::{
> > +    prelude::*,
> > +    drm::{
> > +        device::Device,
> > +        kms::{
> > +            connector::{self, ConnectorGuard},
> > +            ModeConfigGuard
> > +        }
> > +    },
> > +    prelude::*
> > +};
> > +use core::marker::PhantomPinned;
> > +
> > +#[pin_data]
> > +pub(crate) struct DriverConnector {
> > +    #[pin]
> > +    _p: PhantomPinned
> > +}
> 
> This struct does not need to be annotated with `#[pin_data]`, this
> should just work:
> 
> pub(crate) struct DriverConnector;
> 
> > +
> > +pub(crate) type Connector = connector::Connector<DriverConnector>;
> > +
> > +impl connector::DriverConnector for DriverConnector {
> > +    type Initializer = impl PinInit<Self, Error>;
> > +
> > +    type State = ConnectorState;
> > +
> > +    type Driver = RvkmsDriver;
> > +
> > +    type Args = ();
> > +
> > +    fn new(dev: &Device<Self::Driver>, args: Self::Args) ->
> > Self::Initializer {
> 
> And then here just return `Self`.
> 
> This works, since there is a blanket impl `PinInit<T, E> for T`.
> 
> Looking at how you use this API, I am not sure if you actually need
> pin-init for the type that implements `DriverConnector`.
> Do you need to store eg `Mutex<T>` or something else that needs
> pin-init in here in a more complex driver?

Most likely yes - a lot of drivers have various private locks contained
within their subclassed mode objects. I'm not sure we will in rvkms's
connector since vkms doesn't really do much with connectors - but we at
a minimum be using pinned types (spinlocks and hrtimers) in our
DriverCrtc implementation once I've started implementing support for
vblanks[1]

[1]
https://www.kernel.org/doc/html/v6.9-rc5/gpu/drm-kms.html?highlight=vblank#vertical-blanking

In nova (the main reason I'm working on rvkms in the first place),
we'll definitely have locks in our connectors and possibly other types.

>
Benno Lossin April 25, 2024, 3:46 p.m. UTC | #3
On 22.04.24 03:54, Lyude Paul wrote:
> On Wed, 2024-03-27 at 21:06 +0000, Benno Lossin wrote:
>> On 22.03.24 23:03, Lyude Paul wrote:
>>> +
>>> +pub(crate) type Connector = connector::Connector<DriverConnector>;
>>> +
>>> +impl connector::DriverConnector for DriverConnector {
>>> +    type Initializer = impl PinInit<Self, Error>;
>>> +
>>> +    type State = ConnectorState;
>>> +
>>> +    type Driver = RvkmsDriver;
>>> +
>>> +    type Args = ();
>>> +
>>> +    fn new(dev: &Device<Self::Driver>, args: Self::Args) ->
>>> Self::Initializer {
>>
>> And then here just return `Self`.
>>
>> This works, since there is a blanket impl `PinInit<T, E> for T`.
>>
>> Looking at how you use this API, I am not sure if you actually need
>> pin-init for the type that implements `DriverConnector`.
>> Do you need to store eg `Mutex<T>` or something else that needs
>> pin-init in here in a more complex driver?
> 
> Most likely yes - a lot of drivers have various private locks contained
> within their subclassed mode objects. I'm not sure we will in rvkms's
> connector since vkms doesn't really do much with connectors - but we at
> a minimum be using pinned types (spinlocks and hrtimers) in our
> DriverCrtc implementation once I've started implementing support for
> vblanks[1]
> 
> [1]
> https://www.kernel.org/doc/html/v6.9-rc5/gpu/drm-kms.html?highlight=vblank#vertical-blanking
> 
> In nova (the main reason I'm working on rvkms in the first place),
> we'll definitely have locks in our connectors and possibly other types.

I see, in that case it would be a good idea to either have an RFC of
the nova driver (or something else that needs pinned types) as
motivation for why it needs to be pin-initialized.
Lyude Paul April 29, 2024, 7:54 p.m. UTC | #4
On Thu, 2024-04-25 at 15:46 +0000, Benno Lossin wrote:
> On 22.04.24 03:54, Lyude Paul wrote:
> > On Wed, 2024-03-27 at 21:06 +0000, Benno Lossin wrote:
> > > On 22.03.24 23:03, Lyude Paul wrote:
> > > > +
> > > > +pub(crate) type Connector =
> > > > connector::Connector<DriverConnector>;
> > > > +
> > > > +impl connector::DriverConnector for DriverConnector {
> > > > +    type Initializer = impl PinInit<Self, Error>;
> > > > +
> > > > +    type State = ConnectorState;
> > > > +
> > > > +    type Driver = RvkmsDriver;
> > > > +
> > > > +    type Args = ();
> > > > +
> > > > +    fn new(dev: &Device<Self::Driver>, args: Self::Args) ->
> > > > Self::Initializer {
> > > 
> > > And then here just return `Self`.
> > > 
> > > This works, since there is a blanket impl `PinInit<T, E> for T`.
> > > 
> > > Looking at how you use this API, I am not sure if you actually
> > > need
> > > pin-init for the type that implements `DriverConnector`.
> > > Do you need to store eg `Mutex<T>` or something else that needs
> > > pin-init in here in a more complex driver?
> > 
> > Most likely yes - a lot of drivers have various private locks
> > contained
> > within their subclassed mode objects. I'm not sure we will in
> > rvkms's
> > connector since vkms doesn't really do much with connectors - but
> > we at
> > a minimum be using pinned types (spinlocks and hrtimers) in our
> > DriverCrtc implementation once I've started implementing support
> > for
> > vblanks[1]
> > 
> > [1]
> > https://www.kernel.org/doc/html/v6.9-rc5/gpu/drm-kms.html?highlight=vblank#vertical-blanking
> > 
> > In nova (the main reason I'm working on rvkms in the first place),
> > we'll definitely have locks in our connectors and possibly other
> > types.
> 
> I see, in that case it would be a good idea to either have an RFC of
> the nova driver (or something else that needs pinned types) as
> motivation for why it needs to be pin-initialized.

I mean - I'll happily include this with the RFC of nova if nova is
ready at that point, but the purpose of rvkms is to exercise enough of
this API to justify merging it :P - and I think it's a lot likely rvkm
is probably going to be ready well before nova gets to the point of
modesetting. And we will definitely have some uses of pinned types in
rvkms once the driver's ready for submission.

>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index c7edba18a6f09..48c140f943356 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -275,6 +275,8 @@  source "drivers/gpu/drm/amd/amdgpu/Kconfig"
 
 source "drivers/gpu/drm/nouveau/Kconfig"
 
+source "drivers/gpu/drm/rvkms/Kconfig"
+
 source "drivers/gpu/drm/i915/Kconfig"
 
 source "drivers/gpu/drm/xe/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 104b42df2e956..91a18c8290fa4 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -143,6 +143,7 @@  obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
 obj-$(CONFIG_DRM_VGEM)	+= vgem/
 obj-$(CONFIG_DRM_VKMS)	+= vkms/
 obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
+obj-$(CONFIG_DRM_RVKMS) += rvkms/
 obj-$(CONFIG_DRM_EXYNOS) +=exynos/
 obj-$(CONFIG_DRM_ROCKCHIP) +=rockchip/
 obj-$(CONFIG_DRM_GMA500) += gma500/
diff --git a/drivers/gpu/drm/rvkms/Kconfig b/drivers/gpu/drm/rvkms/Kconfig
new file mode 100644
index 0000000000000..d888aa4ffc84c
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/Kconfig
@@ -0,0 +1,3 @@ 
+config DRM_RVKMS
+        tristate "Rust VKMS PoC driver (EXPERIMENTAL)"
+        depends on RUST && DRM && DRM_GEM_SHMEM_HELPER
diff --git a/drivers/gpu/drm/rvkms/Makefile b/drivers/gpu/drm/rvkms/Makefile
new file mode 100644
index 0000000000000..18e06fc3343c6
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/Makefile
@@ -0,0 +1 @@ 
+obj-$(CONFIG_DRM_RVKMS) += rvkms.o
diff --git a/drivers/gpu/drm/rvkms/connector.rs b/drivers/gpu/drm/rvkms/connector.rs
new file mode 100644
index 0000000000000..40f84d38437ee
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/connector.rs
@@ -0,0 +1,55 @@ 
+// TODO: License and stuff
+// Contain's rvkms's drm_connector implementation
+
+use super::{RvkmsDriver, RvkmsDevice, MAX_RES, DEFAULT_RES};
+use kernel::{
+    prelude::*,
+    drm::{
+        device::Device,
+        kms::{
+            connector::{self, ConnectorGuard},
+            ModeConfigGuard
+        }
+    },
+    prelude::*
+};
+use core::marker::PhantomPinned;
+
+#[pin_data]
+pub(crate) struct DriverConnector {
+    #[pin]
+    _p: PhantomPinned
+}
+
+pub(crate) type Connector = connector::Connector<DriverConnector>;
+
+impl connector::DriverConnector for DriverConnector {
+    type Initializer = impl PinInit<Self, Error>;
+
+    type State = ConnectorState;
+
+    type Driver = RvkmsDriver;
+
+    type Args = ();
+
+    fn new(dev: &Device<Self::Driver>, args: Self::Args) -> Self::Initializer {
+        try_pin_init!(Self { _p: PhantomPinned })
+    }
+
+    fn get_modes(
+        connector: ConnectorGuard<'_, Self>,
+        _guard: &ModeConfigGuard<'_, Self::Driver>
+    ) -> i32 {
+        let count = connector.add_modes_noedid(MAX_RES);
+
+        connector.set_preferred_mode(DEFAULT_RES);
+        count
+    }
+}
+
+#[derive(Clone, Default)]
+pub(crate) struct ConnectorState;
+
+impl connector::DriverConnectorState for ConnectorState {
+    type Connector = DriverConnector;
+}
diff --git a/drivers/gpu/drm/rvkms/crtc.rs b/drivers/gpu/drm/rvkms/crtc.rs
new file mode 100644
index 0000000000000..2998f288b88e6
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/crtc.rs
@@ -0,0 +1,40 @@ 
+// TODO: License and stuff
+// Contain's rvkms's drm_crtc implementation
+use core::marker::PhantomPinned;
+use super::RvkmsDriver;
+use kernel::{
+    prelude::*,
+    drm::{
+        device::Device,
+        kms::crtc,
+    },
+};
+
+pub(crate) type Crtc = crtc::Crtc<DriverCrtc>;
+
+#[pin_data]
+pub(crate) struct DriverCrtc {
+    #[pin]
+    _p: PhantomPinned
+}
+
+impl crtc::DriverCrtc for DriverCrtc {
+    type Initializer = impl PinInit<Self, Error>;
+
+    type Args = ();
+
+    type State = CrtcState;
+
+    type Driver = RvkmsDriver;
+
+    fn new(device: &Device<Self::Driver>, args: Self::Args) -> Self::Initializer {
+        try_pin_init!(Self { _p: PhantomPinned })
+    }
+}
+
+#[derive(Clone, Default)]
+pub(crate) struct CrtcState;
+
+impl crtc::DriverCrtcState for CrtcState {
+    type Crtc = DriverCrtc;
+}
diff --git a/drivers/gpu/drm/rvkms/encoder.rs b/drivers/gpu/drm/rvkms/encoder.rs
new file mode 100644
index 0000000000000..72d8b43d9107e
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/encoder.rs
@@ -0,0 +1,26 @@ 
+use core::marker::PhantomPinned;
+use kernel::{
+    drm::{device::Device, kms},
+    prelude::*
+};
+use crate::RvkmsDriver;
+
+#[pin_data]
+pub(crate) struct DriverEncoder {
+    #[pin]
+    _p: PhantomPinned,
+}
+
+pub(crate) type Encoder = kms::encoder::Encoder<DriverEncoder>;
+
+impl kms::encoder::DriverEncoder for DriverEncoder {
+    type Initializer = impl PinInit<Self, Error>;
+
+    type Driver = RvkmsDriver;
+
+    type Args = ();
+
+    fn new(device: &Device<Self::Driver>, args: Self::Args) -> Self::Initializer {
+        try_pin_init!(Self { _p: PhantomPinned })
+    }
+}
diff --git a/drivers/gpu/drm/rvkms/file.rs b/drivers/gpu/drm/rvkms/file.rs
new file mode 100644
index 0000000000000..24b1b53b78238
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/file.rs
@@ -0,0 +1,22 @@ 
+use super::RvkmsDriver;
+
+use kernel::{
+    drm::{
+        self,
+        device::Device as DrmDevice
+    },
+    prelude::*,
+};
+use core::option::*;
+
+pub(crate) struct File();
+
+impl drm::file::DriverFile for File {
+    type Driver = RvkmsDriver;
+
+    fn open(device: &DrmDevice<Self::Driver>) -> Result<Pin<Box<Self>>> {
+        pr_info!("Someone opened a file! But I do not yet know which one...\n");
+
+        Ok(Box::into_pin(Box::try_new(Self())?))
+    }
+}
diff --git a/drivers/gpu/drm/rvkms/gem.rs b/drivers/gpu/drm/rvkms/gem.rs
new file mode 100644
index 0000000000000..b789a1c2170c7
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/gem.rs
@@ -0,0 +1,32 @@ 
+use crate::{RvkmsDriver, RvkmsDevice};
+use core::sync::atomic::{AtomicU64, Ordering};
+use kernel::{
+    drm::{self, gem},
+    prelude::*,
+};
+
+static GEM_ID: AtomicU64 = AtomicU64::new(0);
+
+/// GEM Object implementation
+#[pin_data]
+pub(crate) struct DriverObject {
+    /// ID for debugging
+    id: u64,
+}
+
+pub(crate) type Object = gem::shmem::Object<DriverObject>;
+
+impl gem::BaseDriverObject<Object> for DriverObject {
+    type Initializer = impl PinInit<Self, Error>;
+
+    fn new(dev: &RvkmsDevice, size: usize) -> Self::Initializer {
+        let id = GEM_ID.fetch_add(1, Ordering::Relaxed);
+
+        pr_debug!("DriverObject::new id={id}\n");
+        DriverObject { id }
+    }
+}
+
+impl gem::shmem::DriverObject for DriverObject {
+    type Driver = RvkmsDriver;
+}
diff --git a/drivers/gpu/drm/rvkms/output.rs b/drivers/gpu/drm/rvkms/output.rs
new file mode 100644
index 0000000000000..227d6c3d719a0
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/output.rs
@@ -0,0 +1,72 @@ 
+use crate::{
+    crtc::Crtc,
+    plane::Plane,
+    connector::Connector,
+    encoder::Encoder,
+    RvkmsDevice
+};
+use kernel::{
+    drm::{
+        fourcc::Format,
+        kms::{
+            connector::DRM_MODE_CONNECTOR_VIRTUAL,
+            encoder::DRM_MODE_ENCODER_VIRTUAL,
+            plane::PlaneType,
+            KmsRef
+        },
+    },
+    sync::Arc,
+    prelude::*,
+    types::ARef,
+    drm_format_list,
+};
+
+pub(crate) struct Output {
+    crtc: KmsRef<Crtc>,
+    primary: KmsRef<Plane>,
+    // TODO: overlay, cursor
+    connector: ARef<Connector>,
+    encoder: KmsRef<Encoder>,
+}
+
+impl Output {
+    pub(crate) fn new(dev: &RvkmsDevice, index: u8) -> Result<Self> {
+        let primary = Plane::new(
+            dev,
+            1 << index,
+            &drm_format_list![Format::XRGB888],
+            None,
+            PlaneType::PRIMARY,
+            None,
+            ()
+        )?;
+
+        let crtc = Crtc::new(
+            dev,
+            &primary,
+            Option::<&Plane>::None,
+            None,
+            ()
+        )?;
+
+        let connector = Connector::new(dev, DRM_MODE_CONNECTOR_VIRTUAL, ())?;
+
+        let encoder = Encoder::new(
+            dev,
+            DRM_MODE_ENCODER_VIRTUAL,
+            1 << index,
+            0,
+            None,
+            ()
+        )?;
+
+        connector.attach_encoder(&encoder)?;
+
+        Ok(Self {
+            crtc: crtc.into(),
+            primary: primary.into(),
+            connector,
+            encoder: encoder.into()
+        })
+    }
+}
diff --git a/drivers/gpu/drm/rvkms/plane.rs b/drivers/gpu/drm/rvkms/plane.rs
new file mode 100644
index 0000000000000..54c4bbda64d8e
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/plane.rs
@@ -0,0 +1,39 @@ 
+use core::marker::PhantomPinned;
+use super::RvkmsDriver;
+use kernel::{
+    prelude::*,
+    drm::{
+        device::Device,
+        kms::plane::{self, DriverPlaneState},
+    },
+};
+
+#[pin_data]
+pub(crate) struct DriverPlane {
+    #[pin]
+    _p: PhantomPinned,
+}
+
+pub(crate) type Plane = plane::Plane<DriverPlane>;
+pub(crate) type PlaneState = plane::PlaneState<RvkmsPlaneState>;
+
+impl plane::DriverPlane for DriverPlane {
+    type Initializer = impl PinInit<Self, Error>;
+
+    type State = RvkmsPlaneState;
+
+    type Driver = RvkmsDriver;
+
+    type Args = ();
+
+    fn new(device: &Device<Self::Driver>, args: Self::Args) -> Self::Initializer {
+        try_pin_init!(Self { _p: PhantomPinned })
+    }
+}
+
+#[derive(Clone, Default)]
+pub(crate) struct RvkmsPlaneState;
+
+impl DriverPlaneState for RvkmsPlaneState {
+    type Plane = DriverPlane;
+}
diff --git a/drivers/gpu/drm/rvkms/rvkms.rs b/drivers/gpu/drm/rvkms/rvkms.rs
new file mode 100644
index 0000000000000..0b14aca7f77d4
--- /dev/null
+++ b/drivers/gpu/drm/rvkms/rvkms.rs
@@ -0,0 +1,146 @@ 
+// Rust VKMS Proof of Concept driver
+// Written by Lyude Paul
+// Enormous thanks to:
+// - Maira Canal
+// - Asahi Lina
+// - Probably lots of other wonderful people whose names aren't here
+
+mod connector;
+mod crtc;
+mod file;
+mod gem;
+mod plane;
+mod output;
+mod encoder;
+
+use alloc::boxed::Box;
+
+use core::option::*;
+
+use kernel::{
+    c_str,
+    str::CStr,
+    device::{self, RawDevice},
+    drm::{
+        self,
+        drv,
+        kms::{
+            KmsDriver,
+            ModeConfigInfo,
+        },
+    },
+    platform,
+    prelude::*,
+    sync::Arc,
+    types::ARef,
+};
+
+use crate::output::Output;
+
+pub(crate) struct RvkmsDriver;
+pub(crate) struct Resources;
+
+pub(crate) type DeviceData = device::Data<drv::Registration<RvkmsDriver>, Resources, Data>;
+
+/// Convienence type alias for the DRM device type for this driver
+pub(crate) type RvkmsDevice = drm::device::Device<RvkmsDriver>;
+
+/// Driver metadata
+const INFO: drv::DriverInfo = drv::DriverInfo {
+    major: 0,
+    minor: 0,
+    patchlevel: 0,
+    name: c_str!("rvkms"),
+    desc: c_str!("Rust VKMS PoC"),
+    date: c_str!("20240115"),
+};
+
+/// The minimum supported resolution
+const MIN_RES: (i32, i32) = (10, 10);
+
+/// The maximum supported resolution
+const MAX_RES: (i32, i32) = (8192, 8192);
+
+/// The "preferred" resolution
+const DEFAULT_RES: (i32, i32) = (1024, 768);
+
+pub(crate) struct Data {
+}
+
+/// DRM Driver implementation for `RvkmsDriver`
+#[vtable]
+impl drv::Driver for RvkmsDriver {
+    type Data = Arc<DeviceData>;
+    type Object = gem::Object;
+    type File = file::File;
+
+    const INFO: drv::DriverInfo = INFO;
+    const FEATURES:u32 = drv::FEAT_GEM | drv::FEAT_MODESET | drv::FEAT_ATOMIC;
+
+    kernel::declare_drm_ioctls! {}
+}
+
+impl KmsDriver for RvkmsDriver {}
+
+pub(crate) struct Rvkms {
+    output: Output,
+    drm: ARef<RvkmsDevice>,
+    _resource: device::Resource,
+    _pdev: platform::Device,
+}
+
+const MODE_CONFIG_INFO: ModeConfigInfo = ModeConfigInfo {
+    min_resolution: MIN_RES,
+    max_resolution: MAX_RES,
+    max_cursor: (512, 512),
+    preferred_depth: 0,
+};
+
+impl kernel::Module for Rvkms {
+    fn init(name: &'static CStr, module: &'static ThisModule) -> Result<Self> {
+        // We need to handle all of this from the true module_init, as we're a platform driver that
+        // binds to nothing - so we have to handle that portion of init ourselves like the real vkms
+        let mut pdev = platform::Device::register(c_str!("rvkms"), -1)?;
+        let dev = device::Device::from_dev(&pdev);
+
+        dev.pr_info(format_args!("Initializing RVKMS\n"));
+
+        // TODO: I wonder if there's any way we could get rid of having to pass raw pointers to
+        // this?
+        // no idea
+        let resource = dev.open_group(core::ptr::null_mut() as *mut core::ffi::c_void)?;
+
+        let reg: drv::Registration<RvkmsDriver> =
+            drv::Registration::new(&dev, Option::Some(MODE_CONFIG_INFO), module)?;
+        let drm_dev: ARef<RvkmsDevice> = ARef::from(reg.device());
+        let reg_info = reg.registration_info();
+        let output = Output::new(&drm_dev, 0)?;
+        let data = kernel::new_device_data!(
+            reg,
+            Resources,
+            Data { },
+            "RvkmsDeviceData"
+        )?;
+
+        drm_dev.mode_config_reset();
+
+        dev.dma_coerce_mask_and_coherent(kernel::dma::dma_bit_mask(64))?;
+
+        drv::Registration::register(reg_info, data.into(), 0, module)?;
+
+        Ok(Self {
+            drm: drm_dev,
+            output,
+            _resource: resource,
+            _pdev: pdev,
+        })
+    }
+}
+
+module! {
+    type: Rvkms,
+    name: "rvkms",
+    author: "Lyude Paul",
+    description: "Rust VKMS Proof of Concept driver",
+    license: "GPL v2",
+}