Mali OpenGL support on Allwinner platforms with mainline Linux

As most people know, getting GPU-based 3D acceleration to work on ARM platforms has always been difficult, due to the closed nature of the support for such GPUs. Most vendors provide closed-source binary-only OpenGL implementations in the form of binary blobs, whose quality depend on the vendor.

This situation is getting better and better through vendor-funded initiatives like for the Broadcom VC4 and VC5, or through reverse engineering projects like Nouveau on Tegra SoCs, Etnaviv on Vivante GPUs, Freedreno on Qualcomm’s. However there are still GPUs where you do not have the option to use a free software stack: PowerVR from Imagination Technologies and Mali from ARM (even though there is some progress on the reverse engineering effort).

Allwinner SoCs are using either a Mali GPU from ARM or a PowerVR from Imagination Technologies, and therefore, support for OpenGL on those platforms using a mainline Linux kernel has always been a problem. This is also further complicated by the fact that Allwinner is mostly interested in Android, which uses a different C library that avoids its use in traditional glibc-based systems (or through the use of libhybris).

However, we are happy to announce that Allwinner gave us clearance to publish the userspace binary blobs that allows to get OpenGL supported on Allwinner platforms that use a Mali GPU from ARM, using a recent mainline Linux kernel. Of course, those are closed source binary blobs and not a nice fully open-source solution, but it nonetheless allows everyone to have OpenGL support working, while taking advantage of all the benefits of a recent mainline Linux kernel. We have successfully used those binary blobs on customer projects involving the Allwinner A33 SoCs, and they should work on all Allwinner SoCs using the Mali GPU.

In order to get GPU support to work on your Allwinner platform, you will need:

  • The kernel-side driver, available on Maxime Ripard’s Github repository. This is essentially the Mali kernel-side driver from ARM, plus a number of build and bug fixes to make it work with recent mainline Linux kernels.
  • The Device Tree description of the GPU. We introduced Device Tree bindings for Mali GPUs in the mainline kernel a while ago, so that Device Trees can describe such GPUs. Such description has been added for the Allwinner A23 and A33 SoCs as part of this commit.
  • The userspace blob, which is available on Bootlin GitHub repository. It currently provides the r6p2 version of the driver, with support for both fbdev and X11 systems. Hopefully, we’ll gain access to newer versions in the future, with additional features (such as GBM support).

If you want to use it in your system, the first step is to have the GPU definition in your device tree if it’s not already there. Then, you need to compile the kernel module:

git clone https://github.com/mripard/sunxi-mali.git
cd sunxi-mali
export CROSS_COMPILE=$TOOLCHAIN_PREFIX
export KDIR=$KERNEL_BUILD_DIR
export INSTALL_MOD_PATH=$TARGET_DIR
./build.sh -r r6p2 -b
./build.sh -r r6p2 -i

It should install the mali.ko Linux kernel module into the target filesystem.

Now, you can copy the OpenGL userspace blobs that match your setup, most likely the fbdev or X11-dma-buf variant. For example, for fbdev:

git clone https://github.com/bootlin/mali-blobs.git
cd mali-blobs
cp -a r6p2/fbdev/lib/lib_fb_dev/lib* $TARGET_DIR/usr/lib

You should be all set. Of course, you will have to link your OpenGL applications or libraries against those user-space blobs. You can check that everything works using OpenGL test programs such as es2_gears for example.

Author: Maxime Ripard

Maxime Ripard was an engineer at Bootlin between 2011 and 2019. More details...

66 thoughts on “Mali OpenGL support on Allwinner platforms with mainline Linux”

    1. It’s limited to Allwinner Chips because Mali implementation varies througout every different Soc producer.
      Mali can be the same, but bus, interrupts, features etc. can be different.
      Someone correct me if I’m wrong.

  1. Nice work !!!

    I tried to build against kernel 4.9.20 but got compiler error:

    /home/build/test-mail/sunxi-mali/r6p2/src/devicedrv/mali/platform/sunxi/sunxi.c: In function ‘mali_platform_device_register’:
    /home/build/test-mail/sunxi-mali/r6p2/src/devicedrv/mali/platform/sunxi/sunxi.c:221:11: error: ‘struct device’ has no member named ‘cma_area’
    cma = dev->cma_area;
    ^
    make[2]: *** [/home/build/test-mail/sunxi-mali/r6p2/src/devicedrv/mali/platform/sunxi/sunxi.o] Error 1

    Any idea what can be the clue ??

    Thanks,
    Timo
    http://www.openvario.org

      1. i have try with 4.14-rc3, same error
        /home/build/test-mail/sunxi-mali/r6p2/src/devicedrv/mali/platform/sunxi/sunxi.c:221:11: error: ‘struct device’ has no member named ‘cma_area’

  2. Thank you, Maxime!
    Can you provide any hint about configuring dts for h3/sun8i, please ? I found only example for a20/sun7i and I am not too good with dts yet (;

    1. Thanks anyone for not-answering!
      The problem is resolved by Armbian guys – I found a new patch for “next” to add the required DT node for sun8i.

      1. Hi Sergey,

        first of all, please be patient, Maxime did this work for open source.
        You can’t expect it to be answered in 5 days…
        Anyway, if you join linux-sunxi google group,
        you will find my patch that supports A20/Dts and a patch for mali clock.
        Anyway, everything ends with error 0x3003 on malitest,
        so it takes some more time to fix this.
        Let’s cooperate all together.

        Thanks

        1. Ok, I’ll try to be )) Sorry.
          I am just a bit disappointed by spending my time on a solution which is not tested and is not working. We all have been waiting such news about Mali support and I was expecting a bit more (at least a tested and working solution).

  3. Hi Maxime,

    with kernel 4.13.4, trying to insmod mali.ko,
    it gives me “Couldn’t reserve our memory region”.
    So I’ve seen you’ve released a patch time ago to define a memory-region in dts.
    But now it’s not there anymore.
    Am I on right path?
    I’ve also tried to extend cma with bootargs “cma=128M”

    Thanks in advance

    1. Ok, added memory-region for mali 128M to keep large.
      Driver insmod works.
      But then malitest and Qt5 gives me:
      Error: eglCreateWindowSurface failed: 0x00003003

      What could it be?
      Thanks

      1. Getting the same error from Qt5 built with EGLFS support.
        EGL_BAD_ALLOC = 0x3003
        But seems like nobody is answering in this thread…

      2. Here is my dmesg output regarding mali on orangepi pc:
        ——————————————————-
        [ 8.301918] mali: loading out-of-tree module taints kernel.
        [ 8.305874] Linux cec interface: v0.10
        [ 8.307287] mali-utgard: assigned reserved memory node linux,cma
        [ 8.307867] Allwinner sunXi mali glue initialized
        [ 8.308464] Mali:
        [ 8.308472] Found Mali GPU Mali-400 MP r1p1
        [ 8.309163] Mali:
        [ 8.309170] 2+0 PP cores initialized
        [ 8.309800] Mali:
        [ 8.309806] Mali device driver loaded

          1. This is strace with malitest:

            insmod mali.ko
            [ 84.957002] mali: loading out-of-tree module taints kernel.
            [ 84.968459] mali-utgard: assigned reserved memory node cma
            [ 84.975101] Allwinner sunXi mali glue initialized
            [ 84.980940] Mali:
            [ 84.980953] Found Mali GPU Mali-400 MP r1p1
            [ 84.987907] Mali:
            [ 84.987919] 2+0 PP cores initialized
            [ 84.994620] Mali:
            [ 84.994635] Mali device driver loaded
            # strace -v -C /root/
            .ash_history mali.ko
            # strace -v -C malitest
            execve(“/usr/bin/malitest”, [“malitest”], [“USER=root”, “SHLVL=1”, “HOME=/root”, “PAGER=/bin/more “, “PS1=# “, “LOGNAME=root”, “TERM=vt100”, “PATH=/bin:/sbin:/usr/bin:/usr/sb”…, “SHELL=/bin/sh”, “PWD=/root”, “EDITOR=/bin/vi”]) = 0
            brk(NULL) = 0x23000
            uname({sysname=”Linux”, nodename=”micronova”, release=”4.13.4″, version=”#1 SMP Sat Oct 14 15:19:06 CEST 2017″, machine=”armv7l”, domainname=”(none)”}) = 0
            mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f21000
            access(“/etc/ld.so.preload”, R_OK) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/etc/ld.so.cache”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/tls/v7l/neon/vfp/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/tls/v7l/neon/vfp”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/tls/v7l/neon/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/tls/v7l/neon”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/tls/v7l/vfp/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/tls/v7l/vfp”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/tls/v7l/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/tls/v7l”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/tls/neon/vfp/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/tls/neon/vfp”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/tls/neon/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/tls/neon”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/tls/vfp/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/tls/vfp”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/tls/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/tls”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/v7l/neon/vfp/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/v7l/neon/vfp”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/v7l/neon/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/v7l/neon”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/v7l/vfp/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/v7l/vfp”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/v7l/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/v7l”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/neon/vfp/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/neon/vfp”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/neon/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/neon”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/vfp/libm.so.6”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/lib/vfp”, 0xbedb0680) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/lib/libm.so.6”, O_RDONLY|O_CLOEXEC) = 3
            read(3, “177ELF1113(1300E004″…, 512) = 512
            fstat64(3, {st_dev=makedev(179, 1), st_ino=191, st_mode=S_IFREG|0755, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=896, st_size=456100, st_atime=116 /* 1970-01-01T00:01:56.880000050+0000 */, st_atime_nsec=880000050, st_mtime=1507987156 /* 2017-10-14T13:19:16+0000 */, st_mtime_nsec=0, st_ctime=1507987178 /* 2017-10-14T13:19:38.548217606+0000 */, st_ctime_nsec=548217606}) = 0
            mmap2(NULL, 520316, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6e73000
            mprotect(0xb6ee2000, 61440, PROT_NONE) = 0
            mmap2(0xb6ef1000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6e000) = 0xb6ef1000
            close(3) = 0
            openat(AT_FDCWD, “/lib/libdl.so.2”, O_RDONLY|O_CLOEXEC) = 3
            read(3, “177ELF1113(1230t004″…, 512) = 512
            fstat64(3, {st_dev=makedev(179, 1), st_ino=187, st_mode=S_IFREG|0755, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=24, st_size=9660, st_atime=117 /* 1970-01-01T00:01:57.210000050+0000 */, st_atime_nsec=210000050, st_mtime=1507987156 /* 2017-10-14T13:19:16+0000 */, st_mtime_nsec=0, st_ctime=1507987178 /* 2017-10-14T13:19:38.548217606+0000 */, st_ctime_nsec=548217606}) = 0
            mmap2(NULL, 73920, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6e60000
            mprotect(0xb6e62000, 61440, PROT_NONE) = 0
            mmap2(0xb6e71000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1000) = 0xb6e71000
            close(3) = 0
            openat(AT_FDCWD, “/lib/libpthread.so.0”, O_RDONLY|O_CLOEXEC) = 3
            read(3, “177ELF11133(1`I004″…, 512) = 512
            fstat64(3, {st_dev=makedev(179, 1), st_ino=201, st_mode=S_IFREG|0755, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=256, st_size=128784, st_atime=117 /* 1970-01-01T00:01:57.210000050+0000 */, st_atime_nsec=210000050, st_mtime=1507987156 /* 2017-10-14T13:19:16+0000 */, st_mtime_nsec=0, st_ctime=1507987178 /* 2017-10-14T13:19:38.548217606+0000 */, st_ctime_nsec=548217606}) = 0
            mmap2(NULL, 168524, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6e36000
            mprotect(0xb6e4c000, 65536, PROT_NONE) = 0
            mmap2(0xb6e5c000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16000) = 0xb6e5c000
            mmap2(0xb6e5e000, 4684, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb6e5e000
            close(3) = 0
            openat(AT_FDCWD, “/lib/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/tls/v7l/neon/vfp/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/tls/v7l/neon/vfp”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/tls/v7l/neon/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/tls/v7l/neon”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/tls/v7l/vfp/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/tls/v7l/vfp”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/tls/v7l/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/tls/v7l”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/tls/neon/vfp/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/tls/neon/vfp”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/tls/neon/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/tls/neon”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/tls/vfp/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/tls/vfp”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/tls/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/tls”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/v7l/neon/vfp/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/v7l/neon/vfp”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/v7l/neon/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/v7l/neon”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/v7l/vfp/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/v7l/vfp”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/v7l/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/v7l”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/neon/vfp/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/neon/vfp”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/neon/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/neon”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/vfp/libEGL.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat64(“/usr/lib/vfp”, 0xbedb0638) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/libEGL.so”, O_RDONLY|O_CLOEXEC) = 3
            read(3, “177ELF1113(1302022004″…, 512) = 512
            fstat64(3, {st_dev=makedev(179, 1), st_ino=555, st_mode=S_IFREG|0644, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=2232, st_size=1141720, st_atime=117 /* 1970-01-01T00:01:57.550000051+0000 */, st_atime_nsec=550000051, st_mtime=1507987156 /* 2017-10-14T13:19:16+0000 */, st_mtime_nsec=0, st_ctime=1507987178 /* 2017-10-14T13:19:38.576217689+0000 */, st_ctime_nsec=576217689}) = 0
            mmap2(NULL, 1176880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6d16000
            mprotect(0xb6e27000, 32768, PROT_NONE) = 0
            mmap2(0xb6e2f000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x111000) = 0xb6e2f000
            mmap2(0xb6e35000, 1328, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb6e35000
            mprotect(0xbedb0000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC|PROT_GROWSDOWN) = 0
            close(3) = 0
            openat(AT_FDCWD, “/lib/libGLESv2.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/libGLESv2.so”, O_RDONLY|O_CLOEXEC) = 3
            read(3, “177ELF1113(1302022004″…, 512) = 512
            fstat64(3, {st_dev=makedev(179, 1), st_ino=555, st_mode=S_IFREG|0644, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=2232, st_size=1141720, st_atime=117 /* 1970-01-01T00:01:57.560000051+0000 */, st_atime_nsec=560000051, st_mtime=1507987156 /* 2017-10-14T13:19:16+0000 */, st_mtime_nsec=0, st_ctime=1507987178 /* 2017-10-14T13:19:38.576217689+0000 */, st_ctime_nsec=576217689}) = 0
            close(3) = 0
            openat(AT_FDCWD, “/lib/libc.so.6”, O_RDONLY|O_CLOEXEC) = 3
            read(3, “177ELF1113(1lm1004″…, 512) = 512
            fstat64(3, {st_dev=makedev(179, 1), st_ino=183, st_mode=S_IFREG|0755, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=2400, st_size=1226452, st_atime=117 /* 1970-01-01T00:01:57.560000051+0000 */, st_atime_nsec=560000051, st_mtime=1507987156 /* 2017-10-14T13:19:16+0000 */, st_mtime_nsec=0, st_ctime=1507987178 /* 2017-10-14T13:19:38.544217594+0000 */, st_ctime_nsec=544217594}) = 0
            mmap2(NULL, 1295748, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6bd9000
            mprotect(0xb6d01000, 61440, PROT_NONE) = 0
            mmap2(0xb6d10000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x127000) = 0xb6d10000
            mmap2(0xb6d13000, 9604, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb6d13000
            close(3) = 0
            openat(AT_FDCWD, “/lib/librt.so.1”, O_RDONLY|O_CLOEXEC) = 3
            read(3, “177ELF11133(1`27004″…, 512) = 512
            fstat64(3, {st_dev=makedev(179, 1), st_ino=205, st_mode=S_IFREG|0755, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=56, st_size=26492, st_atime=117 /* 1970-01-01T00:01:57.570000051+0000 */, st_atime_nsec=570000051, st_mtime=1507987156 /* 2017-10-14T13:19:16+0000 */, st_mtime_nsec=0, st_ctime=1507987178 /* 2017-10-14T13:19:38.548217606+0000 */, st_ctime_nsec=548217606}) = 0
            mmap2(NULL, 90648, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6bc2000
            mprotect(0xb6bc8000, 61440, PROT_NONE) = 0
            mmap2(0xb6bd7000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x5000) = 0xb6bd7000
            close(3) = 0
            mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f1f000
            set_tls(0xb6f1f4d0, 0xb6f1fbc0, 0xb6f24058, 0xb6f1f4d0, 0xb6f24058) = 0
            mprotect(0xb6d10000, 8192, PROT_READ) = 0
            mprotect(0xb6e5c000, 4096, PROT_READ) = 0
            mprotect(0xb6bd7000, 4096, PROT_READ) = 0
            mprotect(0xb6ef1000, 4096, PROT_READ) = 0
            mprotect(0xb6e71000, 4096, PROT_READ) = 0
            mprotect(0xb6e2f000, 12288, PROT_READ) = 0
            mprotect(0x21000, 4096, PROT_READ) = 0
            mprotect(0xb6f23000, 4096, PROT_READ) = 0
            set_tid_address(0xb6f1f078) = 207
            set_robust_list(0xb6f1f080, 12) = 0
            rt_sigaction(SIGRTMIN, {sa_handler=0xb6e3a2ec, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0xb6c04fc0}, NULL, 8) = 0
            rt_sigaction(SIGRT_1, {sa_handler=0xb6e3a3cc, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0xb6c04fc0}, NULL, 8) = 0
            rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
            ugetrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM_INFINITY}) = 0
            brk(NULL) = 0x23000
            brk(0x44000) = 0x44000
            futex(0xb6e720b4, FUTEX_WAKE_PRIVATE, 2147483647) = 0
            openat(AT_FDCWD, “/lib/libGLESv1_CM.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/libGLESv1_CM.so”, O_RDONLY|O_CLOEXEC) = 3
            read(3, “177ELF1113(1302022004″…, 512) = 512
            fstat64(3, {st_dev=makedev(179, 1), st_ino=555, st_mode=S_IFREG|0644, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=2232, st_size=1141720, st_atime=117 /* 1970-01-01T00:01:57.930000051+0000 */, st_atime_nsec=930000051, st_mtime=1507987156 /* 2017-10-14T13:19:16+0000 */, st_mtime_nsec=0, st_ctime=1507987178 /* 2017-10-14T13:19:38.576217689+0000 */, st_ctime_nsec=576217689}) = 0
            close(3) = 0
            openat(AT_FDCWD, “/lib/libMali.so”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/usr/lib/libMali.so”, O_RDONLY|O_CLOEXEC) = 3
            read(3, “177ELF1113(1302022004″…, 512) = 512
            fstat64(3, {st_dev=makedev(179, 1), st_ino=555, st_mode=S_IFREG|0644, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=2232, st_size=1141720, st_atime=117 /* 1970-01-01T00:01:57.940000051+0000 */, st_atime_nsec=940000051, st_mtime=1507987156 /* 2017-10-14T13:19:16+0000 */, st_mtime_nsec=0, st_ctime=1507987178 /* 2017-10-14T13:19:38.576217689+0000 */, st_ctime_nsec=576217689}) = 0
            close(3) = 0
            openat(AT_FDCWD, “/dev/mali”, O_RDWR) = 3
            fstat64(3, {st_dev=makedev(0, 6), st_ino=3971, st_mode=S_IFCHR|0600, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=0, st_rdev=makedev(10, 59), st_atime=93 /* 1970-01-01T00:01:33.720000039+0000 */, st_atime_nsec=720000039, st_mtime=93 /* 1970-01-01T00:01:33.720000039+0000 */, st_mtime_nsec=720000039, st_ctime=93 /* 1970-01-01T00:01:33.720000039+0000 */, st_ctime_nsec=720000039}) = 0
            ioctl(3, _IOC(_IOC_READ|_IOC_WRITE, 0x82, 0x3, 0x10), 0xbedb0be0) = 0
            ioctl(3, _IOC(_IOC_READ|_IOC_WRITE, 0x82, 0x6, 0x38), 0xbedb0ba0) = 0
            mmap2(NULL, 8388608, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0xb63c2000
            mprotect(0xb63c3000, 8384512, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
            clone(child_stack=0xb6bc0f98, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb6bc14c8, tls=0xb6bc1920, child_tidptr=0xb6bc14c8) = 208
            ioctl(3, _IOC(_IOC_READ, 0x84, 0x2, 0x10), 0xbedb0c20) = 0
            rt_sigprocmask(SIG_SETMASK, ~[RT_1], [], 8) = 0
            mmap2(NULL, 26336, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0xb6f18000
            mprotect(0xb6f19000, 22240, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
            clone(child_stack=0xb6f1d678, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb6f1dba8, tls=0xb6f1e000, child_tidptr=0xb6f1dba8) = 209
            rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
            futex(0xb6bd8210, FUTEX_WAKE_PRIVATE, 2147483647) = 0
            timer_create(CLOCK_MONOTONIC, {sigev_value={sival_int=156024, sival_ptr=0x26178}, sigev_signo=SIGRTMIN, sigev_notify=SIGEV_THREAD_ID, sigev_notify_thread_id=209}, [0]) = 0
            openat(AT_FDCWD, “/tmp/enable_mali_userspace_cinstr”, O_RDONLY) = -1 ENOENT (No such file or directory)
            openat(AT_FDCWD, “/dev/fb0″, O_RDWR) = 4
            ioctl(4, FBIOGET_VSCREENINFO, 0xbedb0b10) = 0
            mmap2(NULL, 8294400, PROT_WRITE, MAP_SHARED, 4, 0) = 0xb5bd9000
            ioctl(4, FBIOGET_VSCREENINFO, 0x26364) = 0
            ioctl(4, FBIOGET_FSCREENINFO, 0x26404) = 0
            fstat64(1, {st_dev=makedev(0, 6), st_ino=1035, st_mode=S_IFCHR|0600, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=0, st_rdev=makedev(5, 1), st_atime=112 /* 1970-01-01T00:01:52.510000000+0000 */, st_atime_nsec=510000000, st_mtime=112 /* 1970-01-01T00:01:52.510000000+0000 */, st_mtime_nsec=510000000, st_ctime=88 /* 1970-01-01T00:01:28.940000037+0000 */, st_ctime_nsec=940000037}) = 0
            ioctl(1, TCGETS, {c_iflags=0x1500, c_oflags=0x5, c_cflags=0x1cb2, c_lflags=0xa3b, c_line=0, c_cc=”x03x1cx7fx15x04x00x01x00x11x13x1ax0ax12x0fx17x16x00x00x00”}) = 0
            write(1, “EGL Version: “1.4 Linux-r6p2-01r”…, 37EGL Version: “1.4 Linux-r6p2-01rel0”
            ) = 37
            write(1, “EGL Vendor: “ARM”n”, 18EGL Vendor: “ARM”
            ) = 18
            write(1, “EGL Extensions: “EGL_KHR_image E”…, 383EGL Extensions: “EGL_KHR_image EGL_KHR_image_base EGL_KHR_image_pixmap EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_gl_renderbuffer_image EGL_KHR_reusable_sync EGL_KHR_fence_sync EGL_KHR_lock_surface EGL_KHR_lock_surface2 EGL_EXT_create_context_robustness EGL_ANDROID_blob_cache EGL_KHR_create_context EGL_KHR_partial_update EGL_KHR_create_context_no_error ”
            ) = 383
            ioctl(3, _IOC(_IOC_READ, 0x84, 0x2, 0x10), 0xbedb0bc0) = 0
            ioctl(3, _IOC(_IOC_READ|_IOC_WRITE, 0x83, 0, 0x28), 0xbedb0a40) = 0
            mmap2(NULL, 262144, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0x10000000) = 0xb5b99000
            write(2, “Error: eglCreateWindowSurface fa”…, 49Error: eglCreateWindowSurface failed: 0x00003003
            ) = 49
            munmap(0xb5b99000, 262144) = 0
            ioctl(3, _IOC(_IOC_READ|_IOC_WRITE, 0x83, 0x1, 0x10), 0xbedb0b18) = 0
            munmap(0xb5bd9000, 8294400) = 0
            close(4) = 0
            timer_delete(0) = 0
            ioctl(3, _IOC(_IOC_READ|_IOC_WRITE, 0x82, 0x4, 0x10), 0xbedb0bc0) = 0
            close(3) = 0
            exit_group(-1) = ?
            +++ exited with 255 +++
            % time seconds usecs/call calls errors syscall
            —— ———– ———– ——— ——— —————-
            30.75 0.001976 42 47 36 openat
            16.63 0.001069 51 21 mmap2
            14.08 0.000905 82 11 ioctl
            9.10 0.000585 65 9 read
            7.16 0.000460 27 17 mprotect
            6.75 0.000434 39 11 close
            5.12 0.000329 165 2 munmap
            2.16 0.000139 70 2 clone
            1.99 0.000128 4 30 30 stat64
            1.42 0.000091 8 11 fstat64
            0.86 0.000055 18 3 brk
            0.81 0.000052 13 4 write
            0.68 0.000044 44 1 timer_create
            0.59 0.000038 38 1 1 access
            0.45 0.000029 15 2 futex
            0.28 0.000018 9 2 rt_sigaction
            0.28 0.000018 6 3 rt_sigprocmask
            0.22 0.000014 14 1 timer_delete
            0.19 0.000012 12 1 execve
            0.14 0.000009 9 1 uname
            0.12 0.000008 8 1 ugetrlimit
            0.08 0.000005 5 1 set_tid_address
            0.08 0.000005 5 1 set_robust_list
            0.06 0.000004 4 1 set_tls
            —— ———– ———– ——— ——— —————-
            100.00 0.006427 184 67 total
            # [ 147.111360] random: crng init done

          2. But on fd = 4(/dev/mali) don’t seem to be syscalls with errors.
            The only thing strange to me is mmap2 on mali with offset 0x10000000.
            But it returns a valid virtual memory address and I don’t how normally works Mali.

        1. Try to recompile r6p2 kernel driver mali.ko with BUILD=debug instead of release.
          At least it is more verbose and can give more informations.
          I have to give it a try before debugging into mali.so assembly tomorrow.

          1. With driver compiled in debug nothing new.
            I’m debugging Mali.so through malitest in assembler.
            At the moment found where it gets to error 0x3003.
            Now I have to dig more.

  4. Setting Kernel Driver more verbose,
    compiling with debug instead of release,
    I get:
    EGL Version: “1.4 Linux-r6p2-01rel0”
    [ 5625.350397] Mali: ERR: /home/giuliobenetti/Projects/Sunxi_Mainline/mali-kernel-driver/r6p2/src/devicedrv/mali/common/mali_mem_validation.c
    EGL Vendor: “ARM”
    EGL Extensions: “EGL_KHR_image EGL_KHR_image_[ 5625.365291] mali_mem_validation_check() 62
    [ 5625.365291]
    base EGL_KHR_image_pixmap EGL_KHR_gl_texture_2D_image EGL_KHR_gl[ 5625.365299] MALI PHYSICAL RANGE VALIDATION ERROR: The range supplied was: phys_base=0x5F817000, size=0x007E9000
    _texture_cubemap_image EGL_KHR_gl_renderbuffer_image EGL_KHR_reu[ 5625.393993]
    sable_sync EGL_KHR_fence_sync EGL_KHR_lock_surface EGL_KHR_lock_[ 5625.401085] Mali:
    [ 5625.401091] Bind external buf failed
    surface2 EGL_EXT_create_context_robustness EGL_ANDROID_blob_cach[ 5625.412415] Mali:
    e EGL_KHR_create_context EGL_KHR_partial_update EGL_KHR_create_c[ 5625.412420] _mali_ukk_mem_bind, return ERROR!
    ontext_no_error ”
    Error: eglCreateWindowSurface failed: 0x00003003
    —————————————————
    This means it is a problem on how it is configured on kernel side with dt-bindings,
    since it says “MALI PHYSICAL RANGE VALIDATION ERROR”

  5. I’ve noticed that if surface is not created, it doesn’t free cma memory.
    This is why I get error from Kernel Mali Driver.
    So it’s not clear where is the problem.
    Anyway inserting driver with
    “insmod mali.ko mali_debug_level=6”
    makes it very verbose and can help

    1. Hi Giulio,
      you did good findings but it seems to take a very loooong time to make it work.
      I am just wondering again what was the reason for Maxime to advertise this unfinished work.?
      Just let us know if you are lucky to fix this.
      Thanks

      1. Hi Sergey,

        at this time I’ve found that basically Mali can’t find a display,
        this is why it gives me 0x3003 BAD_ALLOC.
        I’ve tried both fbdev and wayland versions.
        I’m interfacing more with open-source.
        You can join IRC channel #linux-sunxi.
        There you can find help if you’re patient to have an answer.
        Maxime made it work, its work is finished.
        The point is that we’re missing something at kernel level.

        Linux-sunxi team is doing a huge effort,
        you can see it on git commits on linux-sunxi github sunxi-next branch.
        And Maxime is the Maintainer.

      2. Hi Sergey,
        I’m trying to recompile all buildroot with an older toolchain(4.9),
        because you can notice that libMali is compiled with 4.8.2.
        Maybe that could cause such problem.
        And also it’s not clear vfp/neon.
        I give it a try.

      3. Finally works! Thanks to Net147 on #linux-sunxi IRC channel,
        you have to compile linux with at least:
        CONFIG_DRM_FBDEV_OVERALLOC=200
        to achieve double buffer,
        since libMali.so r6p2 can’t support single buffer.
        Now malitest works.
        I try with Qt5 now.

        1. It works also with Qt5,
          keep cma area size as big as 128M.
          Kernel can take that memory if unused,
          so don’t worry to waste it.
          In that memory you have to put all your framebuffers but also all egl stuff, that is not few.

        1. Ho Giulio,
          no I didn’t…
          I did all things but still getting 0x3003. I rebuilt the kernel with CONFIG_DRM_FBDEV_OVERALLOC=200.
          I set cma=128M in boot args.
          Qt5 says:

          qt.qpa.egldeviceintegration: Using EGL device integration “eglfs_mali”
          Unable to set double buffer mode! (Invalid argument)

          and 0x3003 in the end….

    1. That’s right,
      the point is setting CONFIG_DRM_FBDEV_OVERALLOC=200 or 300 to give libMali.so at least double buffer.

  6. This is great; wondering about Allwinner aarch64 SoCs – does this agreement extend to (or are there available) libraries for sun50i models (A64 with Mali 400, H5 with Mali 450) under 64-bit Linux? This would be really great for boards like the PINE64/Orange Pi Prime.

    Thanks!

  7. This is indeed great news. As a linux noob, question is: Will be/is there a distro, which already contains everything needed for the Allwinner/A2x SOC based GPU being accelerated? EG all multimedia dsitros like openelec, kodi based, etc..? I am searching for this for quite a while, since i own a Cubietruck (A20)… And i can say: it has been a pain the a….

    1. I would point you to buildroot and build your own.
      Soon there will be packages for Qt5+r6p2 and later X11+r6p2+Qt5.
      Check out buildroot mailing list on nabble.

  8. Thank you, Maxime! But I’m very new for allwinner A33, I just have one office building package, kernel version is 3.4, Only I can do is follow the steps of office release, would you please provide me some basic article which can help me understand how to build in my way? as you know, it is hard to get documents from Allwinner. Thanks!

    1. Hi, unfortunately, we have close to no experience with Allwinner’s 3.4 kernel, so we can’t really help you with that.

  9. I try to get the Mali devicetree bindings setup for a bog standard ancient Cubieboard2 with A20 chip.

    So this might the worlds dumbest, but pretty fundamental question:
    I see no relation between the IRQ numbers floating around in the internet in various device-tree snippets and the documentation from the Allwinner A20 user manual.

    All A20 manuals i found say, the GPU interrupts are from IRQ 101 – 107… In none of the snippets in the internet i found those numbers.. 97-103 seems to be popular… Out of desperation i checked an alternate device A23… Same problem. Interrupt in the user manual and in the devicetrees out in the field do not match. What am i missing? … It’s not a decimal/hex issue.

    Thank you,
    Tobias

    P.S.: Follow up problem is then to assemble a cunningly created DTS entry for an AOU 800×480 parallel LCD display (cubiescreen)… Works with u-boot 2018.03 and on the console with simplefb, but i guess that’s not enough. Well one thing after the other…

  10. Ok after a good nights sleep the IRQ mystery is solved 🙂
    Devicetree says GIC_SPI, but the Datasheet starts just listing them in incremental order.
    So i guess i have to substract the PPI and SGI interrupts as there is probably an offset burried somewhere. So i guess for Allwinner A20 that is 32.. *sigh* Ok.. on to the next challenge to assemble a DT entry that connects an LCD panel.

  11. Hi Maxime,

    I am pretty new with ARM platform and compile kernel module.
    I tried to follow your guide, researching information here and there to fill my knowledge gap. After cloning the repo and entering the directory, I extracted the linux-source-X.X.X-sunxi into a folder, which pass I use for KDIR. I set $TARGET_DIR to rootfs (/). I tried to set the CROSS_COMPILE variable to different toolchain_prefix such as ‘arm-linux-gnueabihf-‘, ‘arm-none-eabi’, however I always end up with the same error log.
    When running `./build.sh -r r6p2 -b`, I got this following error:
    “`
    building…
    ~/sunxi-mali/r6p2 ~/sunxi-mali
    File series fully applied, ends at patch ../patches/r6p2/0016-mali-support-building-against-4.16.patch
    Error applying patch
    “`
    Ignoring it, and running the next command `./build.sh -r r6p2 -b`, I run into this issue:
    “`

    /bin/sh: 1: scripts/basic/fixdep: Exec format error
    scripts/Makefile.build:320: recipe for target ‘/root/sunxi-mali/r6p2/src/devicedrv/mali/linux/mali_osk_locks.o’ failed
    make[2]: *** [/root/sunxi-mali/r6p2/src/devicedrv/mali/linux/mali_osk_locks.o] Error 2
    make[2]: *** Waiting for unfinished jobs….
    /bin/sh: 1: scripts/basic/fixdep: Exec format error
    scripts/Makefile.build:320: recipe for target ‘/root/sunxi-mali/r6p2/src/devicedrv/mali/linux/mali_osk_atomics.o’ failed
    make[2]: *** [/root/sunxi-mali/r6p2/src/devicedrv/mali/linux/mali_osk_atomics.o] Error 2
    /bin/sh: 1: scripts/basic/fixdep: Exec format error
    scripts/Makefile.build:320: recipe for target ‘/root/sunxi-mali/r6p2/src/devicedrv/mali/linux/mali_osk_irq.o’ failed
    make[2]: *** [/root/sunxi-mali/r6p2/src/devicedrv/mali/linux/mali_osk_irq.o] Error 2
    /bin/sh: 1: scripts/basic/fixdep: Exec format error
    scripts/Makefile.build:320: recipe for target ‘/root/sunxi-mali/r6p2/src/devicedrv/mali/linux/mali_osk_wq.o’ failed
    make[2]: *** [/root/sunxi-mali/r6p2/src/devicedrv/mali/linux/mali_osk_wq.o] Error 2
    Makefile:1507: recipe for target ‘_module_/root/sunxi-mali/r6p2/src/devicedrv/mali’ failed
    make[1]: *** [_module_/root/sunxi-mali/r6p2/src/devicedrv/mali] Error 2
    make[1]: Leaving directory ‘/usr/src’
    Makefile:197: recipe for target ‘modules’ failed
    make: *** [modules] Error 2
    make: Leaving directory ‘/root/sunxi-mali/r6p2/src/devicedrv/mali’
    “`
    It would be great if you can help me, or at least point me in the good direction.
    Cheers
    Marc

  12. It is great to see someone working on that! Frankly the only alternative I have seen working before is using sinxi 3.4 kernel. And that is just way too old 🙂

    Unfortunately I was unable to get this to run. Tried with mainline 4.18-rc3, fbdev MALI blob and r6p2. Tried the instructions several times on clean installs (including dropping to older kernel), tried increasing CMA memory, the overallocation of the buffer and what not, but still stuck with “unable to open display”. Even tried r8p1 version, just in case 🙂
    My setup is with a simplefb (on a 480×272 parallel LCD, no X), mainline u-boot on a custom A20-based board. Testing with es2_info from mesa-utils-extra from the debian stretch repository.

    Anyone any hints why it can’t find the fb? I am interested in that because I want to run heavy memory testing on the board (lima-memtester) and the best way is to have the GPU working as hard as it can. Not sure if getting MALI working will be sufficient (lima-memtester is ages old) but seems like the right path to go.

    Cheers!

    1. After some trial and error I figured it is all working properly, except that the tools I am trying to use just need X11. So I went and wrote some code on my own to try the drivers with a fbdev device and it all worked perfectly! Great stuff 🙂
      For anyone interested I have used these libraries to make a DRAM testing procedure on Allwinner boards and have published the code at https://github.com/dimitar-kunchev/mali-memtester
      Cheers

  13. Bit late but I’m integrating mainline kernel driver + blobs to yocto meta-sunxi. I have kernel driver up & running fine (also mali blobs are copied properly). I’m trying to use qt5 cinematicexperience. Build went fine but when run binary on orangepi-pc-plus with -platform eglfs I just get no output and program is aborted with:
    ./Qt5_CinematicExperience -platform eglfs
    QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to ‘/tmp/runtime-root’
    EGL library doesn’t support Emulator extensions
    Aborted

    when add: export QT_QPA_EGLFS_INTEGRATION=none as suggested here: https://forum.qt.io/topic/79887/eglfs-problems-with-qt-5-9/3

    board hangs with multiple lines like:
    QFontDatabase: Cannot find font directory /usr/lib/fonts.
    Note that Qt no longer ships fonts. Deploy some (from https://dejavu-fonts.github.io/ for example) or switch to fontconfig.

    but it’s really dead. I have cma=128M parameter + cma + dma_cma are compiled to kernel. Kernel version is 4.19 LTS. Driver + blobs are from github master. Any ideas what to check? Thanks.

    1. I also tried using kernel version 4.19, but unfortunately there is a kernel panic as soon as mali_test is accessing the OpenGL functions.
      I reverted to kernel version 4.17 to get it running …

  14. Hi all,
    sorry if I go a bit off-topic but above I read how it was difficult to have userspace binary blobs from Allwinner even because “Allwinner is mostly interested in Android, which uses a different C library that avoids its use in traditional glibc-based systems”.

    I’m building an Android image for an Olimex A20 board but the manufacturer provide only a very old userspace driver blob r3p2. I’ve build the kernel side module for more recent versions (r8 – r9) but I’m unable to find the userspace driver compiled for Android.

    How are you able to obtain these? Do you have some suggestions?

    Many thanks

      1. Hi Thomas,
        Thank you anyway. I actually don’t think Allwinner may answer to my requests. I’ve already try to ask Olimex for their help…hope to have an answer soon or later.

  15. “If you want to use it in your system, the first step is to have the GPU definition in your device tree if it’s not already there. ”

    Could someone please explain how? I downloaded the kernel source and I have found the .dts file for my board, is this the right place to put it? Now what do I need to add and where? And when I’m done, how do I load the modified .dts file into the kernel? I have an Allwinner A20 and Mali MP400 GPU. Thank you in advance.

      1. Thank you, Thomas. In the meantime, I checked and yes, it has indeed been added in the kernel I’m using (5.4.43-sunxi). For anyone interested, here’s how you can check if the device tree on your system already contains the GPU:

        – Go to “/boot/dtb-your_kernel_name/”
        – Find your board name as .dtb file, for example “sun7i-A20-bananapi.dtb”
        – Convert this dtb file back to a dts source file: “dtc -I dtb -O dts -f devicetree_file_name.dtb -o devicetree_file_name.dts”
        – Open the resulting dts file with a text editor and search “gpu” to see if it already exists.

        I don’t know if there’s an easier way, but this is how I did it.

  16. I was able to successfully compile the driver and load the module, but there is no /dev/fb0 device available after that. From what I understand, it’s not the mali.ko driver that is responsible for this device, but something else. Which module creates the fb0 device? Has anyone ever gotten this to work? If so, could you please post your output of ‘dmesg’ and ‘lsmod’ somewhere?

    Also, there are two other drivers in the sunxi-mali folder, ‘mali_drm’ and ‘ump’, which are not compiled in the process. I have read some documentation about them, but this is all very confusing to me. Are these drivers also needed to make the basic framebuffer stuff work, or are they specific to the X11 environment?

    1. After some testing, I found out this only happens in newer linux kernels. Systems that use the old linux sunxi kernel (3.x) have /dev/fb0 available, but kernels from 4.x upwards do not have it anymore. If anyone has gotten this to work using an Allwinner A20 and new kernel, please post it here!

  17. The above instructions lack explanations of the KDIR and CROSS_COMPILE variables. This may be obvious to experienced users, but to me it wasn’t. In case it helps anyone, here are the specific instructions how I compiled the mali.ko driver on an Allwinner A20 board:

    export KDIR=/usr/src/linux-headers-$(uname -r)
    export CROSS_COMPILE=arm-linux-gnueabihf-
    ./build.sh -r r6p2 -b
    ./build.sh -r r6p2 -i
    cp mali.ko /lib/modules/$(uname -r)/extra/mali.ko
    depmod
    modprobe -r lima
    modprobe mali

    modprobe -r lima is needed on systems that already have the alternate lima driver loaded, which will make the mali module fail to load with the message “Device or resource busy”.

    If you get an error message “Error applying patch” at the build step and the script just exits, try to run the script with the clean option:
    ./build.sh -r r6p2 -c
    And then build again.

  18. The source code will not compile on the legacy sunxi kernels 3.4.x. Here is how to compile the driver on these old kernels:

    Clone the repository, but do not run the build script (build.sh). It will apply newer kernel patches that break compatibility. The source code will compile without any patches on the old kernel. The only thing that’s missing is a kernel compatible platform file (platform/sunxi.c). For that, we can simply use the platform file for the older r3p2 driver from ssvb’s sunxi repository.

    Create the sunxi platform directory and download the platform file:

    cd sunxi-mali/r6p2/src/devicedrv/mali/platform
    mkdir sunxi
    cd sunxi
    wget https://github.com/ssvb/linux-sunxi/blob/20140116-mali-r3p2-01rel2/drivers/gpu/mali_r3p2-01rel2/mali/platform/sunxi/sunxi.c

    A few additional lines of code are needed for this file to compile. Open it in an editor, then add the following include directive:

    #include

    then go to line 155 and replace the following definition:

    static struct platform_device mali_gpu_device =

    With this:

    static struct platform_device mali_gpu_device =
    {
    .name = MALI_GPU_NAME_UTGARD,
    .id = 0,
    .dev.release = mali_platform_device_release,
    .dev.dma_mask = &mali_gpu_device.dev.coherent_dma_mask,
    .dev.coherent_dma_mask = DMA_BIT_MASK(32),
    };

    Setting the DMA mask values was missing before.
    Then you should be able to compile the driver with these instructions:

    cd sunxi-mali/r6p2/src/devicedrv/mali
    export KDIR=/usr/src/linux-headers-$(uname -r)
    export CROSS_COMPILE=arm-linux-gnueabihf-
    USING_UMP=0 MALI_PLATFORM=sunxi BUILD=debug make

    If you need to compile the UMP module, you need to replace two incorrect include directives in the following files:

    linux/mali_memory_ump.c
    linux/mali_memory_types.h

    Replace

    #include “ump_kernel_interface.h”

    With:

    #include “../../../ump/include/ump/ump_kernel_interface.h”

    1. Thanks for your comment. It should however be noted that the whole point of the work presented in this blog post is NOT to support the old Allwinner 3.4 kernel, but recent mainline Linux kernels.

      1. Thomas, yes I do understand that. It is certainly a rare use case, but some people are stuck with the old kernel for whatever reason and might still want to try the updated drivers.

    2. “following include directive:

      #include

      then go to line 155 and replace the following definition:”

      missing part?

    3. A few additional lines of code are needed for this file to compile. Open it in an editor, then add the following include directive:

      #include

      you are missing something?

      1. The path was removed from my post, probably by an input sanitizer because it was enclosed in square brackets. Here it is without the brackets:

        #include linux/dma-mapping.h

        Add this line to “sunxi.c” in your platform directory. Just remember to enclose the include path in square brackets like the other include directives in this file.

Leave a Reply