#uDRM - a portable Direct Rendering Manager
1 messages · Page 2 of 1
i'm lost
#ifndef __UAPI_PCI_H__
#define __UAPI_PCI_H__
#ifndef UAPI_NEEDS_PCI
#error u dont need me
#endif
#endif
even tho even tho
I guess agragtor header is a bit nicer
since you can in your kernel_api.h do the defines and then include
#ifndef UAPI_PCI_VERSION
#define UAPI_PCI_VERSION 1
#endif
#if UAPI_PCI_VERSION != 1
#error uAPI headers mismatch, make sure all libraries are using the same version
#endif
@tawdry trench thoughts?
ok I talked myself into the agragator header design ngl
yeah thats the idea
lol
Marvin did we lose u or
just ignore everything I said
uhhhhhhhhhhhhhhhhhhhhhhh
Here's a summary:
- a u project layout
|- include
|- udrm
|- internal
|- {uAPI module}
|- kernel_api.h
- kernel_api.h header aka the aggregator
$ cat include/udrm/kernel_api.h
#define UAPI_WANTS_MEMORY
#include <udrm/internal/uapi/memory.h>
#define UAPI_WANTS_PCI
#include <udrm/internal/uapi/pci.h>
#define UAPI_WANTS_IRQ
#include <udrm/internal/uapi/irq.h>
- an api header
#ifndef UAPI_PCI_VERSION
#define UAPI_PCI_VERSION 1
#endif
#if UAPI_PCI_VERSION != 1
#error uAPI pci.h mismatch, make sure all libraries are using the same version
#endif
#ifndef UAPI_PCI_INCLUDED
#define UAPI_PCI_INCLUDED
#ifndef UAPI_WANTS_PCI
#error pci.h header included but not actually needed
#endif
void pci_idk();
#endif
what's the UAPI_*_INCLUDED for
it can be dropped ig
I think the kernel_api.h I would make would be more like ```c
#define UAPI_WANTS_MEMORY
#define UAPI_WANTS_PCI
#define UAPI_WANTS_IRQ
#include <udrm/internal/uapi/uapi.h>
so one giant header?
the included is the include guard no?
just use this as include guard
which just has ```c
#ifdef UAPI_WANTS_PCI
#include <uapi/pci.h>
#endif
fair
so you don't need to include all the headers manually
yea this tbh
do we drop the include guard
it doesnt hurt i guess but its useless
its a bit cleaner to have it seprate
structs can't
yeah then the guard must be kept nvm
yeah you must guard
anyway let me redo the summary
Here's a summary:
- a u project layout
|- include
|- udrm
|- internal
|- {uAPI module}
|- kernel_api.h
- kernel_api.h header aka the aggregator
$ cat include/udrm/kernel_api.h
#define UAPI_WANTS_MEMORY
#define UAPI_WANTS_PCI
#define UAPI_WANTS_IRQ
#include <udrm/internal/uapi/uapi.h>
- uapi.h header
#ifdef UAPI_WANTS_MEMORY
#include "memory.h"
#endif
#ifdef UAPI_WANTS_PCI
#include "pci.h"
#endif
...
- an api header
#ifndef UAPI_PCI_VERSION
#define UAPI_PCI_VERSION 1
#endif
#if UAPI_PCI_VERSION != 1
#error uAPI pci.h mismatch, make sure all libraries are using the same version
#endif
#ifndef UAPI_PCI_INCLUDED
#define UAPI_PCI_INCLUDED
#ifndef UAPI_WANTS_PCI
#error pci.h header included but not actually needed
#endif
void pci_idk();
#endif
do we agree as far as this is concerned
looks good
looks good
nice
@agile halo take a look once u have time
now we have the harder job of working on the apis and carefully splitting them into headers

so im thinking:
- malloc.h -> malloc/calloc/free
- map.h -> map/unmap
- io.h -> pio r/w, raw memory r/w
- work_queue.h -> create_workqueue, submit_work, idk
- pci.h -> pci r/w
- pci_bar.h -> get_bar, map_bar, idk, bus_master shit
- irq.h -> irq alloc, affinity
- msi.h -> msi related stuff
- log.h -> logging
hm?
whats the need for multiple work queues and not let the kernel manage it?
the drm driver needs a lot of those
What if a device does not use MSI, how would a library then register an irw
and careful low level management for them as well
*irq
like, what is the difference between using one work queue and two work queues?
One
what is physically the difference between creating two different work queues and just submitting into one work queue
contention
imagine having 2 gpus
very common
and also uacpi work spammed there too for example
yeah but you will have contention at the scheduler eventually either way no?
Like, if a device uses legacy irq pins instead of MSI, how would the u whatever library get an irq
well one work queue can only be dequeued on one cpu at a time
multiple can run in parallel
idk yet
so you expect each work queue to essentially be a single thread?
yeah
it could be implemented entirely in udrm as well
but it needs a lot of primitives for that
like atomics, linked lists etc
tbh maybe just make the header thread.h
it feels like a weird abstraction tbh
also i forgot about mutex.h and spinlock.h
like trying to combine threads and dpcs into one
We should just make it based off OBOS' api /j
linux is not really the thing you want to look at for inspiration given they have like 3 mechanisms for bottom halfs lol
true
threaded irqs, work queues, tasklets
maybe just a create_thread api would be enough
looks good
and there are probably more
what about a pci irq alloc/dealloc/enable api similar to the one I have in uhda? (and its also similar to linux)
irq.h
then i guess we should do thread.h with low level threading primitives and build whatever we want on top
or whatever udrm wants
like, it can be fine to create the work queue primitive in uapi, I just feel that its so specific in how it wants to be implemented that it might as well be part of the provided shim
yeah
the kernel is the one that needs to compile it tho, since otherwise you would have multiple defs of objects
or well not exactly the same because the one in uhda is limited to one irq, something like ```c
typedef uapi_handle uapi_pci_device; // idk, it would be nicer to pass a handle instead of an address to these functions (and then you don't necessarily need a way to associate an address with a pci device struct)
typedef uapi_handle uapi_pci_irq;
uapi_error uapi_pci_alloc_irqs(uapi_pci_device dev, uapi_pci_irq_types preferred_types, u32 min, u32 max, u32 count);
void uapi_pci_free_irqs(uapi_pci_device dev);
uapi_error uapi_pci_get_irq(uapi_pci_device dev, u32 num, uapi_pci_irq irq);
void uapi_pci_install_irq_handler(uapi_pci_device dev, uapi_pci_irq irq, uapi_irq_handler irq_handler);
void uapi_pci_enable_irq(uapi_pci_device dev, uapi_pci_irq irq, bool enable);
i was thinking of a uapi_pci_device_open(address)
and then all apis would operate on that handle
I mean can't the address just be the handle
the kernel will likely have an object representing that device
@agile halo what was the reason u went with this design initially?
yeah handles are better, worst case the kernel will implement it by returning its handle as an address
the fact that my kernel doesn't really have any way to associate an address to a device (I mean it could be added but I haven't had a reason for it)
true true
yeah there u go
u would force the kernel to have an address -> object lookup table
also I think I prefer ```c
typedef struct uapi_pci_device {
uapi_handle_t handle;
} uapi_pci_device_t;
for type safety
yeah maybe
tbh this also requires a lookup table, I am not sure if there are any other ways to do it without needing it than to directly provide the handle to the driver init function
disregard this
its the other way around
we will give the kernel the list of properties to match a compatible device
just require uacpi and fully use acpi for all object stuff :^)
ah yeah address from handle
also rename io.h to generic_address.h and remove all the apis that are included under it :^)
lmao
#1316457641353936956 message
this is the convo
so yeah i think it makes sense to make the kernel just pass an opaque handle to udrm_device_probe
that can then be used to address the device and do r/w with it
given you don't want to design the kernel but just the driver api yeah
but we will need raw pci api anyways, because uacpi and aml
but thats just read/write
how do we know that someone won't put a backdoor in one of these libs
read the code
have it signed by infy
what if it's really well hidden

read it really well
actually, how do we know infy didn't put a backdoor in uACPI
read it after macro expansion
uacpi has async https apis to send all info
xz utils backdoor repeat
infy casually checking if uacpi running under obos and finding symbols and shit to have a network backdoor
that would mean u have to run some uacpi scripts
it doesnt have any
also for the pci irq api I am not sure if passing the device handle to all those functions is necessary, for an example the irq object handle could store the device handle in the kernel impl if its needed for eg. enabling a pci irq (though when the device is passed directly then the handle may be able to be implemented without allocations as eg. a pci irq number for the device)
yeah idk
we'll have to design it

not very many
only ones that attempt to reach posix compatibility
there are many that don't fall under that category
yeah, ODR is one definition rule, you can declare anything as many times are you want, as long as the decls are the same. You can even declare the same thing differently in some circumstances, if you crave a little a excitement.
you can get some crazy bugs too if you somehow get an implicit declaration of a function (the return type defaults to int).
granted, your compiler should warn you about that
I would be a big fan of this, it would let me remove a hack I have in place specifically for uacpi's pci accesses.
given that memory and io space accesses have map/unmap functions before/after use, it would be nice for pci (and anything else that fits into that category) to follow that style. Imo its a nice hook for the kernel to be able to track resource usage.
alright I'll start creating the virtio headers now
can't do any real setup yet because of uapi
I added all the stuff we talked about into the readme
it's currently a PR
Take a look before i start adding new headers as well
@tawdry trench
I guess we also need a platform/ directory in there
similar to this idea from uacpi
ah im blind
ill review in a few mins
uacpi has platform-specific headers that can be overriden by the host if they want to
take a look how it works there and if u agree with this idea as well
#ifdef UACPI_OVERRIDE_TYPES
#include "uacpi_types.h"
#else
// the actual header
#endif
so the host would create a uapi_types.h header
and define UAPI_OVERRIDE_TYPES
for libc specifically I allow both
reviewing the thing now
nice
LGTM
#error foo.h API version mismatch, make sure all libraries are using the base typo
the same
and should probably be u-lbiraries
or uDrivers
yeah
theres already this
so how do we spell it
u-drivers or uDrivers or u drivers
technically not all u drivers have to live in the org
a u-driver is anything that uses uapi
use uapi in native drivers too 😡

so uDrivers?
ye
fixed
one thing that i dont like
e.g. in uacpi not a single internal header is propagated into public headers
vice versa, sure
maybe uapi should be in udrv/
then it should define the format that'll be used for loading them
but then this breaks the assumption about headers in udrv/ intended to be included standalone
all options suck
in uacpi platform/ is a part of public api
but since this is one repo we cant split it in halves
im not faimiliar with it
it's basically what we're doing but way more abstracted (in a bad way)
to the point where it's almost impossible to implement in a hobby kernel
sheer amount of complexity
the core spec is 250 pages
and that's really just the base
damn
by uefi-like u mean at least as buggy
7000 page spec with protocols a core services table and so on
OSDev Inc.
lmao
🥭
How does udi looks like anyways
wtf
It's like taking Linux exported functions and saying "hey look at this generic driver interface"
Might as well do WDK at that point
(ignore the fact that the entirety of gnu was against it)
driver interface aka random bullshit go
void udi_channel_anchor (
udi_channel_anchor_call_t *callback,
udi_cb_t *gcb,
udi_channel_t channel,
udi_index_t ops_idx,
void *channel_context );
typedef void udi_channel_anchor_call_t (
udi_cb_t *gcb,
udi_channel_t anchored_channel );
wtf is it talking about
It's fine if the kernel shim does more than just call the entry point on the driver lol

need to add platform headers
but idk how to do it cleanly
because of the reasons i mentioned
just come up with anything and we can iron it out
yes
maybe we should also add
#ifndef UAPI_KERNEL_API
#error this header shouldn't be included directly, use kernel_api.h
#endif
because otherwise directly including the header will result in "this header is not needed..." etc
which may or may not be false
probably
but doesn't that really convolute the headers
Maybe
But they're already convoluted
So idk
yea who cares
anyways, i'm porting the spec structs now
that's the one thing i can do while i wait
Ill get basic headers done today a bit later
W
But u can stub stuff out atm
Like add fake uapi_uX types etc
Or uapi_kernel_alloc etc
Then you can replace those once I add the headers
If that's blocking you
@maiden birch so do we want to go through with the unity builds idea
i have nothing against it
As I mentioned I dont control how the project is built and you shouldn't either imo
You just provide a list of c files to build
well, i kinda want lsp support bc this is a nontrivial amount of code
ah
So my test runner is like a uacpi host
Yup
ig i can do stuff like edid validation
You can have a fake config space
And emulate a device in userspace
Verify that stuff that it submits is expected etc
ah true
just make sure that the stuff first works on real hw so you don't emulate wrong behaviour 
Virtio GPU is nice for that
Or your test runner could be a small test kernel
"small"
That you run in qemu and take screenshots to verify the fb state etc
only needs a fully fledged feature set
how about pushing the fb thru the serial console or hash the fb and compare?
@tawdry trench I just realized, u can literally test as part of a Linux module, just unload virtio GPU and load your own instead
Sure
true lol
uapi linux bindings 
You can maybe use the uACPI-OS as a base, given it already runs uacpi
It is missing threads but has other stuff
Yeah
Or that
But that doesnt have mesa
uKernel 
i guess we could try porting to managarm or astral
managarm i have to do either way
Managarm already has mesa so that would be helpful
yeop
True
i'll be in vc if anyone wants to watch me seethe with virtiogpu
@maiden birch can we have a common HEADER_START or whatever
for c++
Yes
cool
UAPI_BEGIN_DECLS?
Ye
Ansi
but _Static_assert
Jk
C89
ye
Why not C23 
Like if you're writing a hobby os in 2024, why are you using an old compiler

maybe some weird code generator that can't cope with latest standards
U gotta be kidding lol
wat
hmm?
did you not know about that
stdatomic is the best thing since bread
Implicit seq cst, overrides default behavior of operators, doesnt work with normal types
Absolute crap
bruh no
it has explicit memory ordering
the defaults are seq cst but who cares no one uses the defaults
Implicit with operators
Also u have to use _Atomic and u cant use normal types
meh, I never use the operator versions
I mean, that is the same in C++, you have to use std::atomic<type>
of course operator overloading so lol
Yeah
In this case its like java with strings and operator ==
Secret special case u have to know about
but anyone who needs to touch stdatomic.h knows what to do
and if he doesn't he failed before even trying
Anyway not a fan but to each their own
meh, I only take it for the _explicit versions of stuff
and I prefer it over using compiler specific variants
currently 4 layers deep into a struct declaration
the people who use the operator stuff are the same ones who use __sync_synchronize to tell themselves everything is now atomic
Lol
who the fuck made the edid struct
how to most inconveniently organize data
kill me
@maiden birch EDID is done
aaaaaaaaaa
Also everything inside a packed struct is packed
pls no macro bullshit 😢
apparently not
Same bullshit but slightly different
Take a look at acpi.h in uacpi
There's also EXPECT_SIZEOF which I recommend u use
Its nice to verify spec structs

To make sure u didnt mess up
i did this
Yeah basically
I typedef public structs
Internal ones are not
Also all public macros and functions with external linkage are prefixed with uacpi
Same goes for structs
But u already do this ig
@maiden birch
#pragma once
#include "common.h"
UAPI_BEGIN_DECLS
// Extended Display Identification Data
UAPI_PACKED(struct drm_edid {
uint8_t header[8]; // 00 FF FF FF FF FF FF 00
// Vendor & Product Identification
uint16_t mfr_name;
uint16_t product_id;
uint32_t serial_id;
uint8_t model_week;
uint8_t model_year;
// EDID Structure Version & Revision
uint8_t version;
uint8_t revision;
// Basic Display Parameters & Features
uint8_t video_input;
uint8_t h_screen_cm;
uint8_t v_screen_cm;
uint8_t gamma;
uint8_t features;
// Color Characteristics
uint8_t red_green_low;
uint8_t blue_white_low;
uint8_t red_x;
uint8_t red_y;
uint8_t green_x;
uint8_t green_y;
uint8_t blue_x;
uint8_t blue_y;
uint8_t white_x;
uint8_t white_y;
// Timings
struct
{
uint8_t time_1;
uint8_t time_2;
uint8_t time_mfr;
} established_timings;
struct
{
uint8_t h_resoution; // (Horizontal addressable pixels ÷ 8) – 31
uint8_t aspect_and_ref; // See 3.19
} standard_timings[8];
struct
{
// Pixel clock frequency divided by 10000.
// If 0, don't use `data.pixel`.
uint16_t pix_clock;
union
{
struct
{
uint8_t h_video_low;
uint8_t h_blank_low;
uint8_t h_video_blank_high;
uint8_t v_video_low;
uint8_t v_blank_low;
uint8_t v_video_blank_high;
uint8_t h_sync_offset_low;
uint8_t h_sync_pulse_width_low;
uint8_t v_sync_offset_pulse_width_low;
uint8_t bit_definitons; // High order bits for the previous 4 fields
uint8_t h_video_mm_low;
uint8_t v_video_mm_low;
uint8_t hv_video_mm_high;
uint8_t h_border;
uint8_t v_border;
uint8_t misc;
} pixel;
struct
{
uint8_t _reserved1;
uint8_t tag;
uint8_t _reserved2;
union
{
char serial_number[13];
char alnum_string[13];
} data;
} other;
} data;
} detailed_timings[4];
uint8_t extension_block_count;
uint8_t checksum;
})
UAPI_EXPECT_SIZEOF(struct drm_edid, 0x80);
UAPI_END_DECLS
Wrong types but yea
Hm?
Well I was gonna import a platform/types.h
Which creates uapi_uX based on stdinth
.
But it doesnt have to be
.
What would that do
Sure yeah we can add explicit endianness types to types.h
nice
uapi_le_u8?
uapi_u8_le
Sure
if only limine didn't pass a null pointer for the EDID i could see if it worked
Well, the le/be versions are only really needed for packed structs where you assume endianness, the rest could be just uxx
Thats the idea
it's more a hint for the user
Just don't forget to ntos
and/or compile time checker
We wanted to do uapi_le_u8
Linux has a checker iirc
yep
Im saying we don't need the u part
hm
what if you want to convey "this is a signed integer which first has to be converted"
U aren't really supposed to use them directly
U should be doing be_to_cpu etc
Yes
Wut
What
let me try something
Im not sure what youre doing
adding a submodule
git submodule add https://github.com/uDrivers/uAPI include/
Thats not how u uh
really?
cd include
Got submodule add link uapi
The second arg is the name of the new directory
no
indentation
Huh
why should they be in src
Your vscode sure looks like they are lol
Ah lmao
oh i see what's happening
i changed my indent width
for the subdirs
okay so
is this right
public headers in <udrm/...>
Yup
internal ones in <udrm/internal/....>
U dont have any public ones right?
well, edid.h at least
Your indent is impossible for me to understand
Wait edid.h isn't under internal lol
Apparently
marvin@pc0 ~/r/u/udrm (master)> tree include
include
├── uapi
│ ├── LICENSE
│ └── README.md
└── udrm
├── common.h
├── edid.h
├── internal
│ ├── virtio
│ └── xe
└── udrm.h
6 directories, 5 files
marvin@pc0 ~/r/u/udrm (master)>
Yeah looks good for now barring the stray common thing
Yeye
The assumption is that you would -Iudrm/include right? Would would having multiple uapi dirs in the path play out?
No
Oh? So how is the include supposed to work
So in your project you would do <edid.h>?
i think you two are talking around each other
Yes you're right


Udrm/uapi
Its under right
Well, right now in his path it's under his direct include dir

Yeah that's what I remembered
Good catch
We moved it from internal, but its still inside udrm not literal include root
so move down to include/udrm/uapi?
done
include
└── udrm
├── common.h
├── connector.h
├── crtc.h
├── edid.h
├── encoder.h
├── internal
│ ├── virtio
│ └── xe
├── plane.h
└── uapi
├── LICENSE
└── README.md
6 directories, 8 files
Correct
Where's udrm.h?
Ah
misclick
yea
Nice
the idea is to have two layers of abstraction
one for just the drivers
one for the DRM system
because i know at least 2 kernels with their own DRM system
isn't DRM like some sorta syscall thing
so that can plug right into there
what even is DRM
An API
it's exposed to userspace via ioctl right
yes
/Dev/dri
You are still expected to use a usermode driver like mesa to actually do stuff
Given it only manages contexts and memory management of the GPU
ah ok
Yeah it only exposes modeset, scanout, memory management, and command submission
The rest is userspace
And command submission is a GPU specific ioctl
There are a bunch of GPU specific stuff
Yeah
which mesa deals with, right?
Yes
And xorg or weston
They're DRM masters
And can submit admin commands
Like modeset
on which step are the user programm windows managed?
These usually have compositors, which draw windows as textures on a canvas
That canvas is then give to GPU for scanout
what about stuff like running shaders
Hm?
after compiling them or whatever
how are they rab
*ran
on the gpu
is that DRM's problem
or mesa's
All the work your application does for drawing is done into its own anonymous buffer
Which may be shared with the window manager
If you want it displayed on the screen
Thats the idea of dri
You talk to the GPU directly and it renders stuff into your own buffers
But then you talk to the window manager and ask it to take the buffer and display it
Yeah
Idk about Linux user space but in windows when in full screen mode the idea is that you control the framebuffer of the actual display and why it can reduce latency
that's why tabbing out kills everything 
Yeah lol
This is new tech right
Iirc before it would copy shit
I think that's how it always worked in windows
When using exclusive full screen mode
Yeah
Well the drawing is done via opengl and vulkan right
Mesa provides implementations of those apis
Mesa has the shader compiler
Iirc they even have their entirely own IR and optimizations since they felt llvm wasn't really the best for it
Yeah
There is some cool blog where they explain why they have their own IR
uVulkan when :^)
its also interesting how you get access to the ir inside gl programs 
uMesa
or well not officially but you can use glGetProgramBinary to get the ir, modify the ir, recalculate a crc in the header and then create a new program + use glProgramBinary to load the modified ir to there
Sadge it's not giving you the direct shader binary meant for the exact gpu :^)
Why does gl even have that
For faster loading
Ah
for caching shaders I'd think yeah
Doesn't even save that much
mesa already does shader caching anyway
I mean it does save the glsl compilation + the nir generation + optimizations that it does in that process
mesa's shader compilation + caching is actually really fast, like when CS2 first came out people were complaining about shader compilation stutters but on mesa it was not perceptible
Like saving the raw machine code for the GPU
even when skipping steam's shader precompilation
Yeah but no gl api for that
The GetProgramBinary could give you that no? If the implementor decided to
yes
Well idk how the spec defines it
The format of the program binary written into binary is returned in the variable whose address is given by binaryFormat, and may be implementation dependent. The binary produced by the GL may subsequently be returned to the GL by calling glProgramBinary, with binaryFormat and length set to the values returned by glGetProgramBinary, and passing the returned binary data in the binary parameter.
from there
Damn
If you link multiple shader objects in the same program, then either all of them must be SPIR-V shaders or none of them may be SPIR-V shaders. You cannot link SPIR-V to non-SPIR-V shaders in a program.
interesting
Lmao
The way mesa does linking is just copy paste I think
So makes sense
interesting
this says i should have uapi in include/udrm/internal/uapi
not include/udrm/uapi
Yeah ill change that
oh ok
Ill get to this pr in about a few hours
This version is before we agreed on moving out of internal
yea i forgot most things yesterday because i was on like 2h of sleep
This was today lol
fml
Lmao
alright time to add the goddamn headers
lets go
updated the readme with all of the things we have talked about today
cool
that was a call to re-review
on it
lol
.
actually i cant even make it a header guard
because there will be multiple kernel_api.h
and this #define UAPI_WANTS_MEMORY should also be under ifndef
do we agree?
yeah sounds fine to me
for cases like
glue.c:
#include <udrm/kernel_api.h>
#include <uacpi/kernel_api.h>
sounds good
@tawdry trench pushed a bunch of base platform headers
👍
Petition to drop msvc support so you can use statement expressions in relevant macros 😔
Like at this point even Microsoft are ditching msvc in favor of clang 
still kinda the defacto default windows compiler
but yeah im sad about the crappy minmax and align
Btw visual studio actually has built in support for clang these days, full drop in replacement (especially with the clang-cl frontend)
As simple as a drop-down option in the build options
It's pretty cool
nice
Maybe games will finally stop shipping with code that looks like a GCC 4 debug output
lmao
Like man, msvc got an ssa only in the last couple years
And before that it didn't even have a proper ast
Optimizations that anyone reading the dragon book could do were missing
Anyways im waiting for more uapi headers to look at
Are you going to move uacpi to use uapi as well?
eventually yes
Nice
since i have more uprojects planned once i finish it
ill have to do that
pushed 3 uapi headers
Won't the sized frees cause weird collisions if some drivers use one and some the other?
yeah
Nice
maybe tahts too much we could talk about it
I assume the same for formatted logs
yup
UAPI_CACHING_WB,
UAPI_CACHING_WT,
UAPI_CACHING_WC,
UAPI_CACHING_UC,
how do u cover NgNrE crap with this
tbh for most cases it wouldn't be that hard to support both frees (as the size is known either statically or otherwise) so you can just define eg a macro ```c
#ifdef UAPI_SIZED_FREES
#define uhda_free(ptr, size) uapi_kernel_free(ptr, size)
#else
#define uhda_free(ptr, size) uapi_kernel_free(ptr)
#endif
literally what uacpi does
#ifdef UACPI_SIZED_FREES
#define uacpi_free(mem, size) uacpi_kernel_free(mem, size)
#else
#define uacpi_free(mem, _) uacpi_kernel_free(mem)
#endif
just internally
rofl
is that really necessary tho? like sure it might not be the most optimal to use nGnRnE but eh, I kinda doubt it matters
ok so heres what linux does
ill just give u a TLDR
The default ioremap does nGnRE which will work with most devices
but it also has a strong _np version
which does nGnRnE
* ioremap_np needs an explicit architecture implementation, as it
* requests stronger semantics than regular ioremap()
ill just add a UAPI_CACHING_MMIO and UAPI_CACHING_MMIO_STRONG
typedef enum uapi_caching {
/*
* Automatically deduce caching type by inspecting the system memory map.
* (e.g. if the region happens to reside inside normal RAM, map as WB)
*/
UAPI_CACHING_AUTO = 0,
UAPI_CACHING_WB,
UAPI_CACHING_WT,
UAPI_CACHING_WC,
UAPI_CACHING_UC,
UAPI_CACHING_MMIO,
/*
* A stronger version of CACHING_MMIO, with an arch-specific implementation.
* E.g. for the ARM architecture you may map MMIO as follows:
* CACHING_MMIO -> nGnRE
* CACHING_MMIO_STRONG -> nGnRnE
*/
UAPI_CACHING_MMIO_STRONG,
} uapi_caching;
thoughts?
anyway pushed to pr
i am indifferent
@tawdry trench any other headers u desperately need now that are blocking you?
well only IRQ and PCI are really missing
yeah these ones are non-trivial
- phys mem alloc
we'll have to design how we want to approach that
this
phys mem i can add right now
/*
* Allocate 2^'order' physical pages with an alignment of 'align'.
* 'max_phys_addr' specifies the maximum acceptible address of the
* end of the last allocated page.
*/
uapi_phys_addr uapi_allocate_pages(
uapi_size order, uapi_size align, uapi_phys_addr max_phys_addr
);
#ifndef UAPI_SIZED_FREES
void uapi_free_pages(uapi_phys_addr);
#else
void uapi_free_pages(uapi_phys_addr, uapi_size order_hint);
#endif
Do we agree with this api
maybe order -> plain count
what about hinting for huge pages
align?
true
yeah maybe, it could still have the power of 2 guarantee (though ofc its not really needed but most if not all allocated things will be that)
well yeah ig it can be removed and be up to the kernel
anyone with a buddy allocator won't be able to hand you non-power-of-2 amounts of pages
contiguous that is
idk if that's really necessary, imo the kernel can do that if it only supports that kind of sizes
btw will uapi be the new kernel api for uacpi too?
ah
or maybe sooner since i have plans for more uprojects
and integrating two into one kernel will be annoying
btw we're gonna have an acpi.h header as well probably for evaluation of acpi methods
but optionally i guess
i know igpus use acpi extensively for various gpu/screen related events
would it be specific to uacpi or a generic interface?
that could also be nice for abstracting other kernel acpi usage though it kinda depends on how much it would support in terms of eg. node discovery or whatever
yeah it would be an interesting excercise
alright i pushed page allocation as well
pci.h and irq.h we'll solve tomorrow since that's very non-trivial
@tawdry trench feel free to add extra helpers or w/e while u work on your stuff, and drop as a pr
ok
Are u still reviewing my pr?
theres also the other misc api like spinlocks, mutexes, events, sleeps/stalls that you had in the draft
yeah ill add those in later, those need a uapi_status which i still havent added
im following the discussion rn
ah
i cant comment on the caching stuff but rest lgtm
since our map callback is ioremap + normal map we kinda have to do this i think
alright thanks, merging then
I made a ruleset
that requires linear history and prevents force pushes
lmao
(removing the c everywhere)
Well I want to support both versions
So I dont break people's osses
Mfw last repo update 3 days ago

meanwhile last uhda update: 1 month ago
Any plans to continue it?
move uhda to udrivers 
That too
yes I just have had other things
i can add you as an admin
sure
pog
just make a uapi->uacpi compat layer
kinda isnt no
i mean you need to deal with the fact that the device phys addr != host phys addr
etc
Most things can just be a macro rename
So yeah
exactly
Some callbacks are more generic now
also your kernel api is kinda shit for binding authors
U mean that it’s not a vtable?
and you don't pass around context pointers either
Which context
what context
are you talking about uacpi?
like a user data pointer that is global to all state
Huh why would anyone need that
its super common in almost all libraries to pass around data
to avoid global state?
Which global state
yea
any of it
Callbacks pass around a user pointer
uapi_free_pages does not
and neither does uapi_allocate_pages
none of the log things do
Why in the world would that need context
so that you know what the real callback is
like, think about how youd write an e.g. rust binding for that
So u sacrifice performance and add useless parameters to everything to satisfy rust binding authors?
you lose like no performance
and anyway you can make that an ifdef
also I don't see an issue with the current api for rust bindings?
Yeah idk man
like you are going to be having a global allocator/log anyway
Why cant the rust implementation call rust_alloc_pages directly
because the bindings crate cant call the "os" crate directly
it has to do it through a function pointer
because you cant have cycles like that
Well what current uacpi bindings do is wrap it in a class
And that class obviously has function pointers
so... you add another indirection?
Just like u do with context lol
true
but at least its not global state with context
just pass around context pointers its not like that expensive, and the drivers arent that hot anyway
Like I get the idea, but damn making the whole API ugly af and feeling very un-c-like just to make it better for bindings
Idk man
Like its a c library first and foremost
What is this?
is this not all you have to do for rust bindings
i don't get it
yes but you cant call to the caller crate
okay so like
the talk was about a generic abstraction crate and not a raw bindings crate
crate uacpi_bindings {
fn uacpi_malloc() { /* you cant put anything here to call real_kernel (except a global function pointer which is ugly) */ }
}
crate real_kernel {
fn stuff() { uacpi_bindings::do_anything() }
}
Btw would like uacpi_set_context/get_context work? @main crow
that kinds doesnt solve the problem tho
Hm?
the problem isnt that there isn't a way to have global state, because there is
the point is that global state bad
and you should avoid it if it's trivially possible
The context pointer is the exact same thing lol
Just passed through a function
How would u set it exactly
During uacpi_init?
That would save it globally
well uacpi also has other global state
Its fundamentally a global state library
that's cringe too tbh
for drivers ig it would be saved inside the device
Yeah u cant have multiple acpi instances
Even in non normal cases?
what about the non normal case of running tests in parallel 😛
Well my test cases are run by python
anyway imo you should not have global state if the user asks you for
It can spawn as many runners as it wants
Its easy to move global state out into a struct
Its just pointless work and redundant parameter to every uacpi function that will always have the same value
you can ifdef around it trivially
Most of it already lives in one struct
U cant
Its literally every existing uacpi public api
Which there's hundreds of functions
#ifndef UAPI_PASS_CONTEXT
#define UAPI_CONTEXT
#else
#define UAPI_CONTEXT ,void *ctx
#endif
void *uapi_malloc(uapi_size size UAPI_CONTEXT);
yeah that
Won't compile
you can put a leading comma on the UAPI_CONTEXT define
oh yeah the comma needs to be inside there
and that does compile
That does
Anyway per driver state is fine, but kernel api is global and as such not stateful
So I wouldnt go there
But we could talk about it later if someone disagrees
Why not? You allocate 4 pages and free 1 at the end
(my PMM for example can allocate any size)
I agree with that, passing useless context parameters everywhere is just not useful, and if it's going to hold it as a global context anyways internally might as well let the kernel do it if it needs to
The only case I can think is maybe if you want a different allocator per driver for whatever reason
But any place where the context would be saved globally I think you might as well not have it at all
@maiden birch how should init happen? do we have a central "initialize everything" function, or should there be specific functions to initialize each driver
yes
ok
i'd have a one per driver and one per each device
so udrm_init and the udrm_device_probe
similar to module_init/module_fini and then per device stuff
are the probe funcs like the linux pci probe callbacks?
yes
great
its basically: i found a device that matches your list, try to see if you can initialize it and bind to it
yea that's what i thought
i'm just going to make up the IRQ/PCI bindings for now until they are finalized
yeah
i'll comment them out
ill see what edge cases need to be handled in the irq bindings
like linux has request_irq with just one number but i know thats not all there is
and im not sure how that handles msi
uAPI/vm.h:
void *uapi_kernel_map(
uapi_phys_addr addr, uapi_size len,
uapi_caching, uapi_access_type
);
might not work under certain oses if they deny user setable executable memory
sure, return a null
none of the current libraries need executable memory, this is more for the future
also like "user" setable? this is a kernel level driver
i plan to put it into userspace
everything that doesnt have a strong reason for kernel level permissions goes into userspace
userspace level drivers should still be considered more priveleged than a normal application
yea they get access to physical hardware but not access to rwx memory the only thing they can do is ask to get a library loaded
anyways this is just for the api completeness, no current use cases exist
also if i understand correctly this function requests specific physical memory?



