Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
Enable ALSA driver and System V IPC in Linux Kernel.

Implement VIRTIO_SND_R_PCM_* prototypes.
  • Loading branch information
Cuda-Chen committed Sep 20, 2024
1 parent a0ad61b commit bed52cf
Show file tree
Hide file tree
Showing 14 changed files with 872 additions and 4 deletions.
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jobs:
- name: install-dependencies
run: |
sudo apt-get install build-essential device-tree-compiler expect
sudo apt-get install libasound2-dev libudev-dev
- name: default build
run: make
shell: bash
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ rootfs.cpio

# intermediate
riscv-harts.dtsi
check-alsa.c
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule "cnfa"]
path = cnfa
url = https://github.com/cntools/cnfa
shallow = true
38 changes: 37 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
include mk/common.mk
include mk/check_lib.mk

CC ?= gcc
CFLAGS := -O2 -g -Wall -Wextra
Expand All @@ -13,6 +14,8 @@ OBJS_EXTRA :=
# command line option
OPTS :=

LDFLAGS :=

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

# virtio-snd
ENABLE_VIRTIOSND ?= 1
ifneq ($(UNAME_S),Linux)
ENABLE_VIRTIOSND := 0
endif
.PHONY: check-alsa.c
check-alsa.c:
$(call create-alsa-prog) > $@

ifeq (0, $(shell gcc check-alsa.c -x c -lasound -o /dev/null > /dev/null 2> /dev/null && echo $$?))
$(warning No libasound installed. Check libasound in advance.)
ENABLE_VIRTIOSND := 0
endif
$(call set-feature, VIRTIOSND)
ifeq ($(call has, VIRTIOSND), 1)
OBJS_EXTRA += virtio-snd.o
LDFLAGS += -lasound -lpthread
CFLAGS += -Icnfa

cnfa/Makefile: check-alsa.c
git submodule update --init cnfa
cnfa/os_generic: cnfa/Makefile
$(MAKE) -C $(dir $<) os_generic.h
CNFA_LIB := cnfa/CNFA_sf.h
$(CNFA_LIB): cnfa/Makefile cnfa/os_generic
$(MAKE) -C $(dir $<) CNFA_sf.h
main.o: $(CNFA_LIB)
endif

# .DEFAULT_GOAL should be set to all since the very first target is not all
# after git submodule.
.DEFAULT_GOAL := all

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

Expand Down Expand Up @@ -102,7 +138,7 @@ build-image:
scripts/build-image.sh

clean:
$(Q)$(RM) $(BIN) $(OBJS) $(deps)
$(Q)$(RM) $(BIN) $(OBJS) $(deps) check-alsa.c

distclean: clean
$(Q)$(RM) riscv-harts.dtsi
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ A minimalist RISC-V system emulator capable of running Linux the kernel and corr
- UART: 8250/16550
- PLIC (platform-level interrupt controller): 32 interrupts, no priority
- Standard SBI, with the timer extension
- VirtIO: virtio-blk acquires disk image from the host, and virtio-net is mapped as TAP interface
- Three types of I/O support using VirtIO standard:
- virtio-blk acquires disk image from the host.
- virtio-net is mapped as TAP interface.
- virtio-snd uses ALSA for sound operation.

## Prerequisites

Expand Down
1 change: 1 addition & 0 deletions cnfa
Submodule cnfa added at 60bcdd
3 changes: 3 additions & 0 deletions configs/buildroot.config
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ BR2_RELRO_NONE=y
# BR2_RELRO_PARTIAL is not set
# BR2_RELRO_FULL is not set
BR2_FORTIFY_SOURCE_1=y
BR2_PACKAGE_ALSA_UTILS=y
BR2_PACKAGE_ALSA_UTILS_APLAY=y
BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST=y
# BR2_PACKAGE_URANDOM_SCRIPTS is not set
BR2_TARGET_ROOTFS_CPIO=y
BR2_TARGET_ROOTFS_CPIO_FULL=y
Expand Down
8 changes: 6 additions & 2 deletions configs/linux.config
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
CONFIG_DEFAULT_HOSTNAME="(none)"
# CONFIG_SYSVIPC is not set
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_WATCH_QUEUE is not set
# CONFIG_CROSS_MEMORY_ATTACH is not set
Expand Down Expand Up @@ -936,7 +937,10 @@ CONFIG_DUMMY_CONSOLE_ROWS=25
# end of Console display driver support
# end of Graphics support

# CONFIG_SOUND is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_ALOOP=y
CONFIG_SND_VIRTIO=y

#
# HID support
Expand Down
51 changes: 51 additions & 0 deletions device.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,53 @@ void clint_write(hart_t *vm,
uint8_t width,
uint32_t value);

/* VirtIO-Sound */

#if SEMU_HAS(VIRTIOSND)
#define IRQ_VSND 4
#define IRQ_VSND_BIT (1 << IRQ_VSND)

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

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

void virtio_snd_read(hart_t *core,
virtio_snd_state_t *vsnd,
uint32_t addr,
uint8_t width,
uint32_t *value);

void virtio_snd_write(hart_t *core,
virtio_snd_state_t *vsnd,
uint32_t addr,
uint8_t width,
uint32_t value);

bool virtio_snd_init(virtio_snd_state_t *vsnd);
#endif /* SEMU_HAS(VIRTIOSND) */

/* memory mapping */

typedef struct {
Expand All @@ -205,4 +252,8 @@ typedef struct {
virtio_blk_state_t vblk;
#endif
clint_state_t clint;
#if SEMU_HAS(VIRTIOSND)
virtio_snd_state_t vsnd;
#endif
uint64_t timer;
} emu_state_t;
5 changes: 5 additions & 0 deletions feature.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,10 @@
#define SEMU_FEATURE_VIRTIONET 1
#endif

/* virtio-snd */
#ifndef SEMU_FEATURE_VIRTIOSND
#define SEMU_FEATURE_VIRTIOSND 1
#endif

/* Feature test macro */
#define SEMU_HAS(x) SEMU_FEATURE_##x
35 changes: 35 additions & 0 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,18 @@ static void emu_update_timer_interrupt(hart_t *hart)
clint_update_interrupts(hart, &data->clint);
}

#if SEMU_HAS(VIRTIOSND)
static void emu_update_vsnd_interrupts(vm_t *vm)
{
emu_state_t *data = PRIV(vm->hart[0]);
if (data->vsnd.InterruptStatus)
data->plic.active |= IRQ_VSND_BIT;
else
data->plic.active &= ~IRQ_VSND_BIT;
plic_update_interrupts(vm, &data->plic);
}
#endif

static void mem_load(hart_t *hart,
uint32_t addr,
uint8_t width,
Expand Down Expand Up @@ -121,6 +133,13 @@ static void mem_load(hart_t *hart,
clint_read(hart, &data->clint, addr & 0xFFFFF, width, value);
clint_update_interrupts(hart, &data->clint);
return;

#if SEMU_HAS(VIRTIOSND)
case 0x44: /* virtio-snd */
virtio_snd_read(hart, &data->vsnd, addr & 0xFFFFF, width, value);
emu_update_vsnd_interrupts(hart->vm);
return;
#endif
}
}
vm_set_exception(hart, RV_EXC_LOAD_FAULT, hart->exc_val);
Expand Down Expand Up @@ -166,6 +185,12 @@ static void mem_store(hart_t *hart,
clint_write(hart, &data->clint, addr & 0xFFFFF, width, value);
clint_update_interrupts(hart, &data->clint);
return;
#if SEMU_HAS(VIRTIOSND)
case 0x44: /* virtio-snd */
virtio_snd_write(hart, &data->vsnd, addr & 0xFFFFF, width, value);
emu_update_vsnd_interrupts(hart->vm);
return;
#endif
}
}
vm_set_exception(hart, RV_EXC_STORE_FAULT, hart->exc_val);
Expand Down Expand Up @@ -581,6 +606,11 @@ static int semu_start(int argc, char **argv)
emu.vblk.ram = emu.ram;
emu.disk = virtio_blk_init(&(emu.vblk), disk_file);
#endif
#if SEMU_HAS(VIRTIOSND)
if (!virtio_snd_init(&(emu.vsnd)))
fprintf(stderr, "No virtio-snd functioned\n");
emu.vsnd.ram = emu.ram;
#endif

/* Emulate */
uint32_t peripheral_update_ctr = 0;
Expand All @@ -603,6 +633,11 @@ static int semu_start(int argc, char **argv)
if (emu.vblk.InterruptStatus)
emu_update_vblk_interrupts(&vm);
#endif

#if SEMU_HAS(VIRTIOSND)
if (emu.vsnd.InterruptStatus)
emu_update_vsnd_interrupts(&vm);
#endif
}

emu_update_timer_interrupt(vm.hart[i]);
Expand Down
8 changes: 8 additions & 0 deletions minimal.dts
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,13 @@
interrupts = <3>;
};
#endif

#if SEMU_FEATURE_VIRTIOSND
snd0: virtio@4400000 {
compatible = "virtio,mmio";
reg = <0x4400000 0x200>;
interrupts = <4>;
};
#endif
};
};
9 changes: 9 additions & 0 deletions mk/check_lib.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
create-alsa-prog = \
$(Q)$(PRINTF) \
"/* Check ALSA is installed or not */\n$\
\#include <alsa/asoundlib.h>\n$\
int main\(\)\n$\
{\n$\
return 0;\n$\
}\n$\
"
Loading

0 comments on commit bed52cf

Please sign in to comment.