Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement VirtIO GPU and input devices #34

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
sudo apt-get install build-essential device-tree-compiler
sudo apt-get install expect
- name: default build
run: make
run: make ENABLE_SDL=0
shell: bash
- name: automated test
run: .ci/autorun.sh
Expand Down
49 changes: 49 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ include mk/common.mk
CC ?= gcc
CFLAGS := -O2 -g -Wall -Wextra
CFLAGS += -include common.h
LDFLAGS :=

# clock frequency
CLOCK_FREQ ?= 65000000
Expand All @@ -13,6 +14,8 @@ OBJS_EXTRA :=
# command line option
OPTS :=

LDFLAGS += -lpthread

# virtio-blk
ENABLE_VIRTIOBLK ?= 1
$(call set-feature, VIRTIOBLK)
Expand Down Expand Up @@ -41,6 +44,52 @@ ifeq ($(call has, VIRTIONET), 1)
OBJS_EXTRA += virtio-net.o
endif

# virtio-input
ENABLE_VIRTIOINPUT ?= 1
ifneq ($(UNAME_S),Linux)
ENABLE_VIRTIOINPUT := 0
endif
$(call set-feature, VIRTIOINPUT)
ifeq ($(call has, VIRTIOINPUT), 1)
OBJS_EXTRA += virtio-input.o
endif

# virtio-gpu
ENABLE_VIRTIOGPU ?= 1
ifneq ($(UNAME_S),Linux)
ENABLE_VIRTIOGPU := 0
endif

# VirGL
ENABLE_VIRGL ?= 1
ifneq (ENABLE_VIRTIOGPU,0)
CFLAGS += $(shell pkg-config virglrenderer --cflags)
LDFLAGS += $(shell pkg-config virglrenderer --libs)
endif

$(call set-feature, VIRGL)

# SDL2
ENABLE_SDL ?= 1
jserv marked this conversation as resolved.
Show resolved Hide resolved
ifeq (, $(shell which sdl2-config))
$(warning No sdl2-config in $$PATH. Check SDL2 installation in advance)
override ENABLE_SDL := 0
endif

ifeq ($(ENABLE_SDL),1)
CFLAGS += $(shell sdl2-config --cflags)
LDFLAGS += $(shell sdl2-config --libs)
else
override ENABLE_VIRTIOGPU := 0
endif

ifeq ($(ENABLE_VIRTIOGPU),1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you check ENABLE_SDL here?

OBJS_EXTRA += window.o
OBJS_EXTRA += virtio-gpu.o
endif

$(call set-feature, VIRTIOGPU)

BIN = semu
all: $(BIN) minimal.dtb

Expand Down
13 changes: 13 additions & 0 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

#include "feature.h"

#define BITS_PER_CHAR 8
#define BITS_PER_LONG (BITS_PER_CHAR * sizeof(long))

#define unlikely(x) __builtin_expect((x), 0)
#define likely(x) __builtin_expect((x), 1)

Expand All @@ -17,6 +20,16 @@ static inline int ilog2(int x)
return 31 - __builtin_clz(x | 1);
}

static inline void set_bit(unsigned long bit, unsigned long *word)
{
*word |= (1 << bit);
}

static inline void bitmap_set_bit(unsigned long *map, unsigned long bit)
{
set_bit(bit % BITS_PER_LONG, &map[bit / BITS_PER_LONG]);
}

/* Range check
* For any variable range checking:
* if (x >= minx && x <= maxx) ...
Expand Down
13 changes: 12 additions & 1 deletion configs/buildroot.config
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS="--enable-softfloat"
BR2_TOOLCHAIN_HEADERS_AT_LEAST="6.1"
BR2_TOOLCHAIN_GCC_AT_LEAST_14=y
BR2_TOOLCHAIN_GCC_AT_LEAST="14"
BR2_TOOLCHAIN_BUILDROOT_CXX=y
BR2_INSTALL_LIBSTDCPP=y
BR2_SSP_NONE=y
# BR2_SSP_REGULAR is not set
# BR2_SSP_STRONG is not set
Expand All @@ -42,4 +44,13 @@ BR2_TARGET_ROOTFS_CPIO_FULL=y
# BR2_TARGET_ROOTFS_CPIO_DRACUT is not set
BR2_TARGET_ROOTFS_CPIO_NONE=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_PACKAGE_BUSYBOX_CONFIG="busybox.config"
BR2_PACKAGE_LIBDRM=y
BR2_PACKAGE_LIBDRM_HAS_ATOMIC=y
BR2_PACKAGE_PROVIDES_LIBEGL="mesa3d"
BR2_PACKAGE_MESA3D=y
BR2_PACKAGE_MESA3D_GALLIUM_DRIVER=y
BR2_PACKAGE_MESA3D_DRIVER=y
BR2_PACKAGE_MESA3D_GALLIUM_DRIVER_VIRGL=y
BR2_PACKAGE_MESA3D_GBM=y
BR2_PACKAGE_MESA3D_OPENGL_EGL=y
BR2_PACKAGE_PROVIDES_LIBGBM="mesa3d"
43 changes: 37 additions & 6 deletions configs/linux.config
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ CONFIG_ALLOW_DEV_COREDUMP=y
# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set
CONFIG_REGMAP=y
CONFIG_REGMAP_MMIO=y
CONFIG_DMA_SHARED_BUFFER=y
CONFIG_GENERIC_ARCH_TOPOLOGY=y
# end of Generic Driver Options

Expand Down Expand Up @@ -754,7 +755,7 @@ CONFIG_INPUT=y
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_EVDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set

#
Expand Down Expand Up @@ -842,7 +843,11 @@ CONFIG_DEVMEM=y
#
# I2C support
#
# CONFIG_I2C is not set
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_COMPAT=y
CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_ALGOBIT=y
# end of I2C support

# CONFIG_I3C is not set
Expand Down Expand Up @@ -905,18 +910,41 @@ CONFIG_MFD_SYSCON=y
#
# Graphics support
#
# CONFIG_DRM is not set
CONFIG_DRM=y
CONFIG_DRM_KMS_HELPER=y
# CONFIG_DRM_DEBUG_MODESET_LOCK is not set
CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_DRM_FBDEV_OVERALLOC=100
CONFIG_DRM_GEM_SHMEM_HELPER=y

#
# ARM devices
#
# end of ARM devices

CONFIG_DRM_VIRTIO_GPU=y
CONFIG_DRM_PANEL=y

CONFIG_DRM_BRIDGE=y
CONFIG_DRM_PANEL_BRIDGE=y

CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y
CONFIG_DRM_NOMODESET=y

#
# Frame buffer Devices
#
# CONFIG_FB is not set
CONFIG_FB_CMDLINE=y
CONFIG_FB_NOTIFY=y
CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_SYS_FILLRECT=y
CONFIG_FB_SYS_COPYAREA=y
CONFIG_FB_SYS_IMAGEBLIT=y
CONFIG_FB_SYS_FOPS=y
CONFIG_FB_DEFERRED_IO=y
# end of Frame buffer Devices

#
Expand All @@ -926,6 +954,8 @@ CONFIG_MFD_SYSCON=y
# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
# end of Backlight & LCD device support

CONFIG_HDMI=y

#
# Console display driver support
#
Expand Down Expand Up @@ -1032,7 +1062,7 @@ CONFIG_EDAC_SUPPORT=y
#
# DMABUF options
#
# CONFIG_SYNC_FILE is not set
CONFIG_SYNC_FILE=y
# CONFIG_DMABUF_HEAPS is not set
# end of DMABUF options

Expand All @@ -1044,9 +1074,10 @@ CONFIG_VIRTIO_ANCHOR=y
CONFIG_VIRTIO=y
CONFIG_VIRTIO_MENU=y
# CONFIG_VIRTIO_BALLOON is not set
# CONFIG_VIRTIO_INPUT is not set
CONFIG_VIRTIO_INPUT=y
CONFIG_VIRTIO_MMIO=y
# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set
CONFIG_VIRTIO_DMA_SHARED_BUFFER=y
# CONFIG_VDPA is not set
# CONFIG_VHOST_MENU is not set

Expand Down
123 changes: 122 additions & 1 deletion device.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@

#define RAM_SIZE (512 * 1024 * 1024)
#define DTB_SIZE (1 * 1024 * 1024)
#define INITRD_SIZE (8 * 1024 * 1024)
#define INITRD_SIZE (65 * 1024 * 1024)

#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 768

void ram_read(hart_t *core,
uint32_t *mem,
Expand Down Expand Up @@ -171,6 +174,117 @@ void virtio_blk_write(hart_t *vm,
uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, char *disk_file);
#endif /* SEMU_HAS(VIRTIOBLK) */

/* VirtIO-GPU */

#if SEMU_HAS(VIRTIOGPU)

#define IRQ_VGPU 4
#define IRQ_VGPU_BIT (1 << IRQ_VGPU)

typedef struct {
uint32_t QueueNum;
uint32_t QueueDesc;
uint32_t QueueAvail;
uint32_t QueueUsed;
uint16_t last_avail;
bool ready;
} virtio_gpu_queue_t;

typedef struct {
/* feature negotiation */
uint32_t DeviceFeaturesSel;
uint32_t DriverFeatures;
uint32_t DriverFeaturesSel;
/* queue config */
uint32_t QueueSel;
virtio_gpu_queue_t queues[2];
/* status */
uint32_t Status;
uint32_t InterruptStatus;
/* supplied by environment */
uint32_t *ram;
/* implementation-specific */
void *priv;
} virtio_gpu_state_t;

void virtio_gpu_read(hart_t *vm,
virtio_gpu_state_t *vgpu,
uint32_t addr,
uint8_t width,
uint32_t *value);

void virtio_gpu_write(hart_t *vm,
virtio_gpu_state_t *vgpu,
uint32_t addr,
uint8_t width,
uint32_t value);

void semu_virgl_init(void);

void virtio_gpu_init(virtio_gpu_state_t *vgpu);
void virtio_gpu_add_scanout(virtio_gpu_state_t *vgpu,
uint32_t width,
uint32_t height);
#endif /* SEMU_HAS(VIRTIOGPU) */

/* VirtIO Input */

#if SEMU_HAS(VIRTIOINPUT)

#define IRQ_VINPUT_KEYBOARD 5
#define IRQ_VINPUT_KEYBOARD_BIT (1 << IRQ_VINPUT_KEYBOARD)

#define IRQ_VINPUT_MOUSE 6
#define IRQ_VINPUT_MOUSE_BIT (1 << IRQ_VINPUT_MOUSE)

typedef struct {
uint32_t QueueNum;
uint32_t QueueDesc;
uint32_t QueueAvail;
uint32_t QueueUsed;
uint16_t last_avail;
bool ready;
} virtio_input_queue_t;

typedef struct {
/* feature negotiation */
uint32_t DeviceFeaturesSel;
uint32_t DriverFeatures;
uint32_t DriverFeaturesSel;
/* queue config */
uint32_t QueueSel;
virtio_input_queue_t queues[2];
/* status */
uint32_t Status;
uint32_t InterruptStatus;
/* supplied by environment */
uint32_t *ram;
/* implementation-specific */
int id; // FIXME
void *priv;
} virtio_input_state_t;

void virtio_input_read(hart_t *vm,
virtio_input_state_t *vinput,
uint32_t addr,
uint8_t width,
uint32_t *value);

void virtio_input_write(hart_t *vm,
virtio_input_state_t *vinput,
uint32_t addr,
uint8_t width,
uint32_t value);

void virtio_input_init(virtio_input_state_t *vinput);

void virtio_input_update_key(uint32_t key, uint32_t state);

void virtio_input_update_mouse_button_state(uint32_t button, bool pressed);

void virtio_input_update_cursor(uint32_t x, uint32_t y);
#endif /* SEMU_HAS(VIRTIOINPUT) */

/* clint */
typedef struct {
uint32_t msip[4096];
Expand Down Expand Up @@ -203,6 +317,13 @@ typedef struct {
#endif
#if SEMU_HAS(VIRTIOBLK)
virtio_blk_state_t vblk;
#endif
#if SEMU_HAS(VIRTIOGPU)
virtio_gpu_state_t vgpu;
#endif
#if SEMU_HAS(VIRTIOINPUT)
virtio_input_state_t vkeyboard;
virtio_input_state_t vmouse;
#endif
clint_state_t clint;
} emu_state_t;
15 changes: 15 additions & 0 deletions feature.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,20 @@
#define SEMU_FEATURE_VIRTIONET 1
#endif

/* virtio-gpu */
#ifndef SEMU_FEATURE_VIRTIOGPU
#define SEMU_FEATURE_VIRTIOGPU 1
#endif

/* VirGL */
#ifndef SEMU_FEATURE_VIRGL
#define SEMU_FEATURE_VIRGL 1
#endif

/* virtio-input */
#ifndef SEMU_FEATURE_VIRTIOINPUT
#define SEMU_FEATURE_VIRTIOINPUT 1
#endif

/* Feature test macro */
#define SEMU_HAS(x) SEMU_FEATURE_##x
Loading
Loading