Skip to content

Commit d6388f4

Browse files
committed
Make SVGA-adapter use ramfd w/ revocation support
1 parent 2d26ef3 commit d6388f4

File tree

3 files changed

+72
-41
lines changed

3 files changed

+72
-41
lines changed

kos/include/libvideo/gfx/serial.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ typedef __uintptr_t video_serial_proto_t;
5454
/* Video buffer file descriptor info for implementing `VIDEO_SERIAL_PROTO_MEMFD' */
5555
struct video_buffer_fdinfo {
5656
/* Pixel data for a pixel at <X> and <Y> is accessed like this:
57-
* >> video_coord_t x = (video_coord_t)(<X> + vbfdi_cxoff);
58-
* >> video_coord_t y = (video_coord_t)(<Y> + vbfdi_cyoff);
59-
* >> if (x >= vbfdi_xdim || y >= vbfdi_ydim)
57+
* >> video_offset_t x = <X> + vbfdi_cxoff;
58+
* >> video_offset_t y = <Y> + vbfdi_cyoff;
59+
* >> if (x < 0 || x >= vbfdi_xdim || y < 0 || y >= vbfdi_ydim)
6060
* >> return OUT_OF_BOUNDS;
6161
* >> byte_t *base = mmap(NULL, vbfdi_total, MAP_FILE | MAP_SHARED, vbfdi_fd, vbfdi_bxoff);
6262
* >> byte_t *line = base + (y * vbfdi_stride);

kos/src/libvideo/driver/adapter/svga.c

Lines changed: 64 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@
3333
#include <kos/anno.h>
3434
#include <kos/aref.h>
3535
#include <kos/io.h>
36+
#include <kos/ioctl/file.h>
3637
#include <kos/ioctl/svga.h>
3738
#include <kos/sched/shared-lock.h>
3839
#include <kos/types.h>
3940
#include <sys/ioctl.h>
41+
#include <sys/mman.h>
4042
#include <sys/perm.h>
4143
#include <sys/syslog.h>
4244
#include <sys/types.h>
@@ -62,7 +64,7 @@
6264
#include <libvideo/driver/monitor.h>
6365
#include <libvideo/gfx/api.h>
6466
#include <libvideo/gfx/buffer.h>
65-
#include <libvideo/gfx/buffer/rambuffer.h>
67+
#include <libvideo/gfx/buffer/ramfdbuffer.h>
6668
#include <libvideo/gfx/codec/codec-extra.h>
6769
#include <libvideo/gfx/codec/codec.h>
6870
#include <libvideo/gfx/codec/palette.h>
@@ -85,6 +87,28 @@ DECL_BEGIN
8587
syslog(LOG_ERR, "[libvideo-driver,svga.c:%d] " format, __LINE__, ##__VA_ARGS__)
8688

8789

90+
/* Ask the kernel to create a sub-region of "fd" */
91+
PRIVATE WUNUSED fd_t CC
92+
file_newsubregion(fd_t fd,
93+
/*page-aligned*/ uint64_t minaddr,
94+
/*page-aligned*/ uint64_t num_bytes) {
95+
struct file_subregion sr;
96+
bzero(&sr, sizeof(sr));
97+
sr.fsr_minaddr = minaddr;
98+
if (OVERFLOW_UADD(minaddr, num_bytes - 1, &sr.fsr_maxaddr))
99+
goto err_range;
100+
sr.fsr_resfd.of_mode = OPENFD_MODE_AUTO;
101+
sr.fsr_resfd.of_flags = IO_CLOEXEC;
102+
if unlikely(ioctl(fd, FILE_IOC_SUBREGION, &sr) < 0)
103+
goto err;
104+
return sr.fsr_resfd.of_hint;
105+
err_range:
106+
errno = ERANGE;
107+
err:
108+
return -1;
109+
}
110+
111+
88112
PRIVATE ATTR_IN(1) ATTR_OUT(2) void CC
89113
modeinfo_to_codecspecs(struct svga_modeinfo const *__restrict modeinfo,
90114
struct video_codec_specs *__restrict specs) {
@@ -340,16 +364,6 @@ svga_noop_updaterects(struct video_display *__restrict self,
340364

341365

342366

343-
PRIVATE NONNULL((1)) void LIBVIDEO_GFX_FCC
344-
svga_buffer_destroy(struct video_buffer *__restrict self) {
345-
struct svga_buffer *me = video_buffer_assvga(self);
346-
struct svga_adapter *svga = svga_buffer_getadapter(me);
347-
(*svga->sva_libphys_unmap)(me->rb_data, me->svb_rb_total);
348-
__video_buffer_fini_common(me);
349-
free(me);
350-
}
351-
352-
353367
PRIVATE WUNUSED NONNULL((1)) REF struct video_palette *CC
354368
svga_palette_new(struct svga_adapter *__restrict self, shift_t colorbits) {
355369
video_pixel_t i, palsize;
@@ -388,43 +402,61 @@ svga_palette_new(struct svga_adapter *__restrict self, shift_t colorbits) {
388402
PRIVATE WUNUSED ATTR_INOUT(1) REF struct svga_buffer *CC
389403
svga_newbuffer(struct svga_adapter *__restrict self) {
390404
REF struct svga_buffer *result;
391-
struct video_buffer_ops const *rambuffer_ops;
392405
struct svga_modeinfo *modeinfo;
393406
physaddr_t lfb_addr;
407+
uintptr_t lfb_offset;
408+
size_t lfb_size;
409+
size_t ps = getpagesize(), pm = ps - 1;
394410
result = (REF struct svga_buffer *)malloc(sizeof(struct svga_buffer));
395411
if unlikely(!result)
396412
goto err;
397413

398-
/* Inherit all operators from "rambuffer_ops" by default. */
399-
rambuffer_ops = video_rambuffer_ops();
400-
memcpy(&result->svb_ops, rambuffer_ops, sizeof(struct video_buffer_ops));
414+
/* Inherit all operators from "rambuffer_ops" by default.
415+
* Note how we use the subregion-variant, since that one
416+
* also supports FD-revocation. Since the FD we're linking
417+
* is actually a sub-region of /dev/mem, it actually can
418+
* be consider a buffer sub-region, too. */
419+
result->svb_ops = *video_ramfdbuffer_subregion_ops();
401420

402421
/* Override certain operators */
403-
result->svb_ops.vi_destroy = &svga_buffer_destroy;
404422
if (self->sva_cs.sc_modeops.sco_hw_async_copyrect ||
405423
self->sva_cs.sc_modeops.sco_hw_async_fillrect) {
406424
/* TODO: Hook into GFX to provide hardware-accelerated fill/blit operators */
407425
}
408426

409427
/* Map LFB for "result" */
410428
modeinfo = self->sva_modeinfo;
411-
result->rb_stride = modeinfo->smi_scanline;
412-
result->svb_rb_total = modeinfo->smi_scanline * modeinfo->smi_resy;
429+
result->rb_stride = modeinfo->smi_scanline;
430+
result->rfdb_total = modeinfo->smi_scanline * modeinfo->smi_resy;
431+
432+
/* Determine address of linear frame buffer */
413433
lfb_addr = modeinfo->smi_lfb;
414434
if (!(modeinfo->smi_flags & SVGA_MODEINFO_F_LFB))
415435
lfb_addr = (physaddr_t)0xA0000;
416-
result->rb_data = (byte_t *)(*self->sva_libphys_map)(lfb_addr, result->svb_rb_total);
417-
if unlikely(result->rb_data == MAP_FAILED)
436+
lfb_offset = lfb_addr & pm;
437+
lfb_addr &= ~pm;
438+
lfb_size = (lfb_offset + result->rfdb_total + pm) & ~pm;
439+
440+
/* Create sub-region of /dev/mem for linear frame buffer */
441+
result->rfdb_fd = file_newsubregion(self->sva_devmem, lfb_addr, lfb_size);
442+
if unlikely(result->rfdb_fd < 0)
418443
goto err_r;
419444

445+
/* Map linear frame buffer into memory */
446+
result->rb_data = (byte_t *)mmap(NULL, result->rfdb_total, PROT_READ | PROT_WRITE,
447+
MAP_SHARED | MAP_FILE, result->rfdb_fd, lfb_offset);
448+
if unlikely(result->rb_data == MAP_FAILED)
449+
goto err_r_fd;
450+
assert(((uintptr_t)result->rb_data & pm) == lfb_offset);
451+
420452
/* Allocate palette (if necessary) */
421453
result->vb_surf.vs_flags = VIDEO_GFX_F_NORMAL;
422454
result->vb_surf.vs_pal = NULL;
423455
if (self->sva_mode.vmm_codec->vc_specs.vcs_flags & VIDEO_CODEC_FLAG_PAL) {
424456
shift_t cbits = self->sva_mode.vmm_codec->vc_specs.vcs_cbits;
425457
result->vb_surf.vs_pal = svga_palette_new(self, cbits);
426458
if unlikely(!result->vb_surf.vs_pal)
427-
goto err_r_data;
459+
goto err_r_fd_data;
428460
result->vb_surf.vs_flags |= VIDEO_GFX_F_PALOBJ;
429461
}
430462

@@ -437,8 +469,10 @@ svga_newbuffer(struct svga_adapter *__restrict self) {
437469
result->vb_surf.vs_buffer = result;
438470
result->vb_refcnt = 1;
439471
return result;
440-
err_r_data:
441-
(*self->sva_libphys_unmap)(result->rb_data, result->svb_rb_total);
472+
err_r_fd_data:
473+
(void)munmap(result->rb_data, result->rfdb_total);
474+
err_r_fd:
475+
(void)close(result->rfdb_fd);
442476
err_r:
443477
free(result);
444478
err:
@@ -590,6 +624,8 @@ INTERN WUNUSED struct svga_adapter *CC
590624
svga_tryopen(/*inherited(on_success)*/ fd_t fd) {
591625
char csname[SVGA_CSNAMELEN];
592626
struct svga_adapter *result;
627+
PGETDEVMEM pdyn_getdevmem;
628+
593629
{
594630
PSVGA_CHIPSET_GETDRIVERS svga_chipset_getdrivers;
595631
struct svga_chipset_driver const *result__sva_drv;
@@ -667,14 +703,14 @@ svga_tryopen(/*inherited(on_success)*/ fd_t fd) {
667703
LOGERR("dlerror: %s\n", dlerror());
668704
goto err_r_vdlck_libsvgadrv;
669705
}
670-
*(void **)&result->sva_libphys_map = dlsym(result->sva_libphys, "mmapphys");
671-
if unlikely(!result->sva_libphys_map) {
706+
*(void **)&pdyn_getdevmem = dlsym(result->sva_libphys, "getdevmem");
707+
if unlikely(!pdyn_getdevmem) {
672708
LOGERR("dlerror: %s\n", dlerror());
673709
goto err_r_vdlck_libsvgadrv_libphys;
674710
}
675-
*(void **)&result->sva_libphys_unmap = dlsym(result->sva_libphys, "munmapphys");
676-
if unlikely(!result->sva_libphys_unmap) {
677-
LOGERR("dlerror: %s\n", dlerror());
711+
result->sva_devmem = (*pdyn_getdevmem)();
712+
if unlikely(result->sva_devmem < 0) {
713+
LOGERR("Failed to obtain file descriptor for /dev/mem");
678714
goto err_r_vdlck_libsvgadrv_libphys;
679715
}
680716

kos/src/libvideo/driver/adapter/svga.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,17 @@
3434
#include <libsvgadrv/chipset.h>
3535
#include <libvideo/driver/adapter.h>
3636
#include <libvideo/driver/monitor.h>
37-
#include <libvideo/gfx/buffer/rambuffer.h>
37+
#include <libvideo/gfx/buffer/ramfdbuffer.h>
3838

3939
DECL_BEGIN
4040

4141
struct svga_adapter;
4242
struct svga_buffer;
4343
AXREF(svga_buffer_axref, svga_buffer);
4444

45-
struct svga_buffer: video_rambuffer {
46-
/* TODO: Buffer here must be derived from "video_ramfdbuffer",
47-
* since it needs to be revocable and FD-serializable */
48-
45+
struct svga_buffer: video_ramfdbuffer {
4946
/* NOTE: The buffer described here is owned and must be unmapped using `:sva_libphys_unmap' */
50-
size_t svb_rb_total; /* [const] Total buffer size */
51-
struct video_buffer_ops svb_ops; /* [const] Operator table. */
47+
struct video_buffer_ops svb_ops; /* [const] Operator table. */
5248
};
5349
#define svga_buffer_getadapter(self) \
5450
video_domain_assvga(video_buffer_getdomain(self))
@@ -71,10 +67,9 @@ struct svga_adapter: video_adapter {
7167
struct video_adapter_ops sva_adapter_ops; /* [const] Adapter operator table */
7268
struct svga_monitor sva_monitor; /* [1..1][const] The one-and-only SVGA monitor */
7369
struct video_monitor_ops sva_monitor_ops; /* [const] Monitor operator table */
74-
fd_t sva_vdlck; /* [const] Video lock file for /dev/svga */
70+
fd_t sva_vdlck; /* [owned][const] Video lock file for /dev/svga */
71+
fd_t sva_devmem; /* [const] File descriptor for /dev/mem (as returned by `libphys.so!getdevmem') */
7572
void *sva_libphys; /* [1..1][const] Handle for libphys */
76-
PMMAPPHYS sva_libphys_map; /* [1..1][const] Helper to map physical memory */
77-
PMUNMAPPHYS sva_libphys_unmap; /* [1..1][const] Helper to unmap physical memory */
7873
void *sva_libsvgadrv; /* [1..1][const] Handle for libsvgadrv */
7974
struct svga_chipset_driver const *sva_drv; /* [1..1][const] SVGA driver */
8075
#define svga_adapter_modeset(self) ((self)->sva_modeinfo != NULL)

0 commit comments

Comments
 (0)