glMapBuffer may hang kernel with vaapi on radeon e8860
System information
System: Host: uos-PC Kernel: 4.19.90-arm64-desktop-generic aarch64 bits: 64 compiler: gcc v: 8.3.0 Console: tty 0
dm: LightDM Distro: uos 20
CPU: Topology: 16-Core (4-Die) model: FT1500A 16cores variant: armv8 bits: 64 type: MCP MCM arch: ARMv8 rev: 1
features: Use -f option to see features bogomips: 1600
Speed: N/A min/max: N/A Core speeds (MHz): No speed data found for 16 cores.
Graphics: Device-1: Advanced Micro Devices [AMD/ATI] Venus PRO [Radeon E8860] driver: radeon v: kernel bus ID: 09:00.0
chip ID: 1002:6822
Display: tty server: X.org 1.20.4 driver: ati,radeon unloaded: fbdev,modesetting tty: 206x50
Message: Advanced graphics data unavailable in console. Try -G --display
Describe the issue
When I run glmark2 on this board, it always hung the whole system, kernel has no serial port dmesg output even with drm.debug=0x2
. Single debug with the help of gdb, I found it crashed on stp
instruction inside glibc's memset aarch64 implementation. dest_start is returned from
glMapBuffer`:
if (vbo_update_method_ == VBOUpdateMethodMap) {
dest_start = reinterpret_cast<float *>(
GLExtensions::MapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY)
);
}
...
float *dest(dest_start + nfloats * iter->first);
std::copy(src, src_end, dest);
...
}
I write a simple demo to easily reproduce this bug:
// g++ c.cpp -lGL -lGLEW -lSDL
#include <iostream>
#define GL3_PROTOTYPES 1
#include <GL/gl.h>
#include <GL/glew.h>
#include <GL/glu.h>
#include <SDL/SDL.h>
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
#define MAX_FRAMEBUFFER_WIDTH 2048
#define MAX_FRAMEBUFFER_HEIGHT 2048
GLuint fuck;
int main() {
SDL_Init(SDL_INIT_EVERYTHING);
SDL_SetVideoMode(640, 480, 32, SDL_OPENGL);
glewInit();
GLuint *data;
glGenBuffers(1, &fuck);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, fuck);
int size;
glGetBufferParameteriv(GL_PIXEL_UNPACK_BUFFER, GL_BUFFER_SIZE, &size);
std::cout << "size: " << size << '\n';
glBufferData(GL_PIXEL_UNPACK_BUFFER,
MAX_FRAMEBUFFER_WIDTH * MAX_FRAMEBUFFER_HEIGHT * sizeof(GLuint),
NULL, GL_STATIC_DRAW);
data = (GLuint *)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
memset(data, 0x00, 0 * sizeof(GLuint));
memset(data, 0x00, 1 * sizeof(GLuint));
memset(data, 0x00, 2 * sizeof(GLuint));
memset(data, 0x00, 4 * sizeof(GLuint));
memset(data, 0x00, 8 * sizeof(GLuint));
memset(data, 0x00,
MAX_FRAMEBUFFER_WIDTH * MAX_FRAMEBUFFER_HEIGHT * sizeof(GLuint));
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)
When execute memset(data, 0x00, 4 * sizeof(GLuint));
, glibc's memset implementation uses str
NEON
, in this size, and it crash my system.
The data here is returned by glMapBuffer
too, and its value is:
(gdb) p data
$1 = (GLunit *)0x7fa17fc00
Examine this process's address map(dump /proc/pid/maps
), I found:
7fa17fc000-7fa27fd000 rw-s 108ac8000 00:06 3094 /dev/dri/renderD128
This device file is for vaapi
3d acceleration.
Besides, I also found when smplayer uses vdpau
, my system crash either.