Skip to content

Commit 89d4743

Browse files
committed
Implement virtio-gpu device
1 parent 6dbe25e commit 89d4743

File tree

10 files changed

+1912
-7
lines changed

10 files changed

+1912
-7
lines changed

Makefile

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ include mk/check-libs.mk
44
CC ?= gcc
55
CFLAGS := -O2 -g -Wall -Wextra
66
CFLAGS += -include common.h
7+
LDFLAGS :=
78

89
# clock frequency
910
CLOCK_FREQ ?= 65000000
@@ -14,7 +15,7 @@ OBJS_EXTRA :=
1415
# command line option
1516
OPTS :=
1617

17-
LDFLAGS := -lm
18+
LDFLAGS := -lm -lpthread
1819

1920
# virtio-blk
2021
ENABLE_VIRTIOBLK ?= 1
@@ -91,6 +92,33 @@ endif
9192
# after git submodule.
9293
.DEFAULT_GOAL := all
9394

95+
# virtio-gpu
96+
ENABLE_VIRTIOGPU ?= 1
97+
ifneq ($(UNAME_S),Linux)
98+
ENABLE_VIRTIOGPU := 0
99+
endif
100+
101+
# SDL2
102+
ENABLE_SDL ?= 1
103+
ifeq (, $(shell which sdl2-config))
104+
$(warning No sdl2-config in $$PATH. Check SDL2 installation in advance)
105+
override ENABLE_SDL := 0
106+
endif
107+
108+
ifeq ($(ENABLE_SDL),1)
109+
CFLAGS += $(shell sdl2-config --cflags)
110+
LDFLAGS += $(shell sdl2-config --libs)
111+
else
112+
override ENABLE_VIRTIOGPU := 0
113+
endif
114+
115+
ifeq ($(ENABLE_VIRTIOGPU),1)
116+
OBJS_EXTRA += window.o
117+
OBJS_EXTRA += virtio-gpu.o
118+
endif
119+
120+
$(call set-feature, VIRTIOGPU)
121+
94122
BIN = semu
95123
all: $(BIN) minimal.dtb
96124

device.h

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
#define RAM_SIZE (512 * 1024 * 1024)
1212
#define DTB_SIZE (1 * 1024 * 1024)
13-
#define INITRD_SIZE (8 * 1024 * 1024)
13+
#define INITRD_SIZE (65 * 1024 * 1024)
1414

1515
void ram_read(hart_t *core,
1616
uint32_t *mem,
@@ -222,6 +222,59 @@ void virtio_rng_write(hart_t *vm,
222222
void virtio_rng_init(void);
223223
#endif /* SEMU_HAS(VIRTIORNG) */
224224

225+
/* VirtIO-GPU */
226+
227+
#if SEMU_HAS(VIRTIOGPU)
228+
229+
#define IRQ_VGPU 6
230+
#define IRQ_VGPU_BIT (1 << IRQ_VGPU)
231+
232+
typedef struct {
233+
uint32_t QueueNum;
234+
uint32_t QueueDesc;
235+
uint32_t QueueAvail;
236+
uint32_t QueueUsed;
237+
uint16_t last_avail;
238+
bool ready;
239+
} virtio_gpu_queue_t;
240+
241+
typedef struct {
242+
/* feature negotiation */
243+
uint32_t DeviceFeaturesSel;
244+
uint32_t DriverFeatures;
245+
uint32_t DriverFeaturesSel;
246+
/* queue config */
247+
uint32_t QueueSel;
248+
virtio_gpu_queue_t queues[2];
249+
/* status */
250+
uint32_t Status;
251+
uint32_t InterruptStatus;
252+
/* supplied by environment */
253+
uint32_t *ram;
254+
/* implementation-specific */
255+
void *priv;
256+
} virtio_gpu_state_t;
257+
258+
void virtio_gpu_read(hart_t *vm,
259+
virtio_gpu_state_t *vgpu,
260+
uint32_t addr,
261+
uint8_t width,
262+
uint32_t *value);
263+
264+
void virtio_gpu_write(hart_t *vm,
265+
virtio_gpu_state_t *vgpu,
266+
uint32_t addr,
267+
uint8_t width,
268+
uint32_t value);
269+
270+
void semu_virgl_init(virtio_gpu_state_t *vgpu);
271+
272+
void virtio_gpu_init(virtio_gpu_state_t *vgpu);
273+
void virtio_gpu_add_scanout(virtio_gpu_state_t *vgpu,
274+
uint32_t width,
275+
uint32_t height);
276+
#endif /* SEMU_HAS(VIRTIOGPU) */
277+
225278
/* ACLINT MTIMER */
226279
typedef struct {
227280
/* A MTIMER device has two separate base addresses: one for the MTIME
@@ -374,6 +427,9 @@ typedef struct {
374427
#endif
375428
#if SEMU_HAS(VIRTIORNG)
376429
virtio_rng_state_t vrng;
430+
#endif
431+
#if SEMU_HAS(VIRTIOGPU)
432+
virtio_gpu_state_t vgpu;
377433
#endif
378434
/* ACLINT */
379435
mtimer_state_t mtimer;

feature.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,10 @@
1717
#define SEMU_FEATURE_VIRTIOSND 1
1818
#endif
1919

20+
/* virtio-gpu */
21+
#ifndef SEMU_FEATURE_VIRTIOGPU
22+
#define SEMU_FEATURE_VIRTIOGPU 1
23+
#endif
24+
2025
/* Feature test macro */
2126
#define SEMU_HAS(x) SEMU_FEATURE_##x

main.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include "mini-gdbstub/include/gdbstub.h"
1414
#include "riscv.h"
1515
#include "riscv_private.h"
16+
#include "window.h"
17+
1618
#define PRIV(x) ((emu_state_t *) x->priv)
1719

1820
/* Define fetch separately since it is simpler (fixed width, already checked
@@ -85,6 +87,18 @@ static void emu_update_vrng_interrupts(vm_t *vm)
8587
}
8688
#endif
8789

90+
#if SEMU_HAS(VIRTIOGPU)
91+
static void emu_update_vgpu_interrupts(vm_t *vm)
92+
{
93+
emu_state_t *data = PRIV(vm->hart[0]);
94+
if (data->vgpu.InterruptStatus)
95+
data->plic.active |= IRQ_VGPU_BIT;
96+
else
97+
data->plic.active &= ~IRQ_VGPU_BIT;
98+
plic_update_interrupts(vm, &data->plic);
99+
}
100+
#endif
101+
88102
static void emu_update_timer_interrupt(hart_t *hart)
89103
{
90104
emu_state_t *data = PRIV(hart);
@@ -168,12 +182,17 @@ static void mem_load(hart_t *hart,
168182
emu_update_vrng_interrupts(hart->vm);
169183
return;
170184
#endif
171-
172185
#if SEMU_HAS(VIRTIOSND)
173186
case 0x47: /* virtio-snd */
174187
virtio_snd_read(hart, &data->vsnd, addr & 0xFFFFF, width, value);
175188
emu_update_vsnd_interrupts(hart->vm);
176189
return;
190+
#endif
191+
#if SEMU_HAS(VIRTIOGPU)
192+
case 0x48: /* virtio-gpu */
193+
virtio_gpu_read(hart, &data->vgpu, addr & 0xFFFFF, width, value);
194+
emu_update_vgpu_interrupts(hart->vm);
195+
return;
177196
#endif
178197
}
179198
}
@@ -229,19 +248,23 @@ static void mem_store(hart_t *hart,
229248
aclint_sswi_write(hart, &data->sswi, addr & 0xFFFFF, width, value);
230249
aclint_sswi_update_interrupts(hart, &data->sswi);
231250
return;
232-
233251
#if SEMU_HAS(VIRTIORNG)
234252
case 0x46: /* virtio-rng */
235253
virtio_rng_write(hart, &data->vrng, addr & 0xFFFFF, width, value);
236254
emu_update_vrng_interrupts(hart->vm);
237255
return;
238256
#endif
239-
240257
#if SEMU_HAS(VIRTIOSND)
241258
case 0x47: /* virtio-snd */
242259
virtio_snd_write(hart, &data->vsnd, addr & 0xFFFFF, width, value);
243260
emu_update_vsnd_interrupts(hart->vm);
244261
return;
262+
#endif
263+
#if SEMU_HAS(VIRTIOGPU)
264+
case 0x48: /* virtio-gpu */
265+
virtio_gpu_write(hart, &data->vgpu, addr & 0xFFFFF, width, value);
266+
emu_update_vgpu_interrupts(hart->vm);
267+
return;
245268
#endif
246269
}
247270
}
@@ -691,6 +714,12 @@ static int semu_init(emu_state_t *emu, int argc, char **argv)
691714
fprintf(stderr, "No virtio-snd functioned\n");
692715
emu->vsnd.ram = emu->ram;
693716
#endif
717+
#if SEMU_HAS(VIRTIOGPU)
718+
emu->vgpu.ram = emu->ram;
719+
virtio_gpu_init(&(emu->vgpu));
720+
virtio_gpu_add_scanout(&(emu->vgpu), 1024, 768);
721+
window_init();
722+
#endif
694723

695724
emu->peripheral_update_ctr = 0;
696725
emu->debug = debug;
@@ -728,6 +757,11 @@ static int semu_step(emu_state_t *emu)
728757
if (emu->vsnd.InterruptStatus)
729758
emu_update_vsnd_interrupts(vm);
730759
#endif
760+
761+
#if SEMU_HAS(VIRTIOGPU)
762+
if (emu->vgpu.InterruptStatus)
763+
emu_update_vgpu_interrupts(vm);
764+
#endif
731765
}
732766

733767
emu_update_timer_interrupt(vm->hart[i]);

minimal.dts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
chosen {
1818
bootargs = "earlycon console=ttyS0";
1919
stdout-path = "serial0";
20-
linux,initrd-start = <0x1f700000>; /* @403 MiB (503 * 1024 * 1024) */
20+
/* Reserve 65MiB for initrd image */
21+
linux,initrd-start = <0x1be00000>; /* @406 MiB (446 * 1024 * 1024) */
2122
linux,initrd-end = <0x1fefffff>; /* @511 MiB (511 * 1024 * 1024 - 1) */
2223
};
2324

@@ -79,5 +80,13 @@
7980
interrupts = <5>;
8081
};
8182
#endif
83+
84+
#if SEMU_FEATURE_VIRTIOGPU
85+
gpu0: virtio@4800000 {
86+
compatible = "virtio,mmio";
87+
reg = <0x4800000 0x200>;
88+
interrupts = <6>;
89+
};
90+
#endif
8291
};
8392
};

utils.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ static inline void list_del_init(struct list_head *node)
7979
INIT_LIST_HEAD(node);
8080
}
8181

82+
#define LIST_HEAD_INIT(name) \
83+
{ \
84+
.prev = (&name), .next = (&name) \
85+
}
86+
87+
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
88+
8289
#ifndef container_of
8390
#define container_of(ptr, type, member) \
8491
__extension__({ \
@@ -87,7 +94,7 @@ static inline void list_del_init(struct list_head *node)
8794
})
8895
#else
8996
#define container_of(ptr, type, member) \
90-
((type *) ((char *) (ptr) - offsetof(type, member)))
97+
((type *) ((char *) (ptr) -offsetof(type, member)))
9198
#endif
9299

93100
#define list_entry(node, type, member) container_of(node, type, member)

0 commit comments

Comments
 (0)