¿Cómo asigno memoria para un módulo del kernel cargable en framebuffer (linux)?

¿Cómo asigno memoria para un módulo del kernel cargable en framebuffer (linux)?

Estoy escribiendo un dispositivo framebuffer 'falso' para poder usar mi lector electrónico como pantalla externa para mi Raspberry Pi. La parte del lector electrónico funciona bien (https://github.com/llandsmeer/inkvt), pero ahora quiero que aparezca como una pantalla externa para Linux.

Pensé que un framebuffer virtual de Linux es "más fácil", pero ¿tal vez haya otras opciones para agregar una pantalla falsa a Linux (que aparece en xrandr)?

De todos modos, aquí está el módulo del kernel actual. Crea un /dev/fbXdispositivo que, después de ser consultado, fbsetparece estar configurado correctamente. Sin embargo, cuando intento usarlo, falla y obtengo fbcat: Corrupted page table at address 7fd7d5c90000dmesg.

Creo que es porque configuré mal la región de memoria ( char mem[]). Intenté usar kallocinstream, pero tampoco funcionó. ¿Cómo debería estar haciendo las cosas?

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fb.h>

#define WIDTH 256
#define HEIGHT 256

static char mem[WIDTH*HEIGHT*3];

static void op_fillrect(struct fb_info * info, const struct fb_fillrect * rect) {
    printk(KERN_ALERT "fillrect\n");
}

static void op_copyarea(struct fb_info * info, const struct fb_copyarea * area) {
    printk(KERN_ALERT "copyarea\n");
}

static void op_imageblit(struct fb_info * info, const struct fb_image * image) {
    printk(KERN_ALERT "imageblit\n");
}

static struct fb_info * info;

static struct fb_ops ops = {
    .owner = THIS_MODULE,
    .fb_fillrect = op_fillrect,
    .fb_copyarea = op_copyarea,
    .fb_imageblit = op_imageblit,
};

static const struct fb_fix_screeninfo fix = {
    .id = "LennartFB",
    .smem_start = (unsigned long)mem,
    .smem_len = sizeof(mem),
    .type = FB_TYPE_PACKED_PIXELS,
    .visual = FB_VISUAL_TRUECOLOR,
    .line_length = 256,
};

static const struct fb_var_screeninfo var = {
    .xres = WIDTH,
    .yres = HEIGHT,
    .xres_virtual = WIDTH,
    .yres_virtual = HEIGHT,
    .bits_per_pixel = 24,
    .height = 256,
    .width = 256,
    .vmode = FB_VMODE_NONINTERLACED,
    .red = { .length = 8, .offset = 16, },
    .green = { .length = 8, .offset = 8, },
    .blue = { .length = 8, .offset = 0, }
};

static int mod_init(void) {
    int err;
    info = framebuffer_alloc(0, 0);
    if (!info) return -1;
    info->fbops = &ops;
    info->fix = fix;
    info->var = var;
    info->screen_base = mem;
    err = fb_alloc_cmap(&info->cmap, 2, 0);
    if (err < 0) return -2;
    err = register_framebuffer(info);
    if (err < 0) return -3;
    return 0;
}

static void mod_exit(void) {
    return;
}

module_init(mod_init);
module_exit(mod_exit);
MODULE_LICENSE("GPL v3");

dmesg:

[ 4984.929380] fbcat: Corrupted page table at address 7fd7d5c90000
[ 4984.929385] PGD 8000000277709067 P4D 8000000277709067 PUD 3eb108067 PMD 2c732e067 PTE 800fffffc0f5d235
[ 4984.929391] Bad pagetable: 000d [#1] SMP PTI
[ 4984.929396] CPU: 11 PID: 8076 Comm: fbcat Tainted: P           OE     5.3.0-46-generic #38~18.04.1-Ubuntu
[ 4984.929398] Hardware name: Acer Aspire A715-72G/Charmeleon_CFS, BIOS V1.19 07/13/2018
[ 4984.929403] RIP: 0033:0x55fa6cb22e98

información relacionada