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 sound device #53

Draft
wants to merge 5 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
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
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
48 changes: 48 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
include mk/common.mk
include mk/check-libs.mk

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

LDFLAGS := -lm

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

# virtio-snd
ENABLE_VIRTIOSND ?= 1
ifneq ($(UNAME_S),$(filter $(UNAME_S),Linux Darwin))
ENABLE_VIRTIOSND := 0
endif

# Check ALSA installation
ifeq ($(UNAME_S),Linux)
ifeq (0, $(call check-alsa))
$(warning No libasound installed. Check libasound in advance.)
ENABLE_VIRTIOSND := 0
endif
endif
# Check core audio installation
ifeq ($(UNAME_S),Darwin)
ifeq (0, $(call check-coreaudio))
$(warning No CoreAudio framework installed.)
ENABLE_VIRTIOSND := 0
endif
endif
$(call set-feature, VIRTIOSND)
ifeq ($(call has, VIRTIOSND), 1)
OBJS_EXTRA += virtio-snd.o

ifeq ($(UNAME_S),Linux)
LDFLAGS += -lasound -lpthread
else ifeq ($(UNAME_S),Darwin)
LDFLAGS += -framework AudioToolbox -lpthread
endif
CFLAGS += -Icnfa

cnfa/Makefile:
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
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
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST required and functioned?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The speaker-test (in buildroot it is enabled by BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST) is required for testing the speaker (the virtio-snd).

For functionality, though it can't play sound as the sound playing feature in virtio-snd is not implemented yet, it can function as shows in the following:

Welcome to Buildroot
buildroot login: root
# speaker-test

speaker-test 1.2.11

Playback device is default
Stream parameters are 48000Hz, S16_LE, 1 channels
Using 16 octaves of pink noise
ALSA lib pcm_direct.c:2188:(_snd_pcm_direct_new) unable to create IPC semaphore
Playback open error: -38,Function not implemented

Copy link
Collaborator

Choose a reason for hiding this comment

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

You should clarify the limitations and known issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mention the question for implementation in #50 (comment).

# BR2_PACKAGE_URANDOM_SCRIPTS is not set
BR2_TARGET_ROOTFS_CPIO=y
BR2_TARGET_ROOTFS_CPIO_FULL=y
Expand Down
10 changes: 8 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,12 @@ 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_VIRTIO=y
CONFIG_SND_VERBOSE_PRINTK=y
CONFIG_SND_DEBUG=y
jserv marked this conversation as resolved.
Show resolved Hide resolved
CONFIG_SND_DEBUG_VERBOSE=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 */

Cuda-Chen marked this conversation as resolved.
Show resolved Hide resolved
#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);
jserv marked this conversation as resolved.
Show resolved Hide resolved
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
};
};
35 changes: 35 additions & 0 deletions mk/check-libs.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Create a mininal ALSA program
jserv marked this conversation as resolved.
Show resolved Hide resolved
define create-alsa-prog
echo '\
#include <alsa/asoundlib.h>\n\
int main(){\n\
snd_pcm_t *pcm;\n\
snd_pcm_open(&pcm, "default", SND_PCM_STREAM_PLAYBACK, 0);\n\
snd_pcm_close(pcm);\n\
return 0;\n\
}\n'
endef

# Create a mininal Core Audio program
define create-coreaudio-prog
echo '\
#include <CoreAudio/CoreAudio.h>\n\
int main(){\n\
AudioComponent comp;\n\
comp = AudioComponentFindNext(NULL, &desc);\n\
if (comp == NULL) exit (-1);\n\
return 0;\n\
}\n'
endef

# Check ALSA installation
define check-alsa
$(shell $(call create-alsa-prog) | $(CC) -x c -lasound -o /dev/null > /dev/null 2> /dev/null -
&& echo $$?)
endef

# Check Core Audio installation
define check-coreaudio
$(shell $(call create-coreaudio-prog) | $(CC) -x c -framework CoreAudio -o /dev/null > /dev/null 2> /dev/null -
&& echo $$?)
endef
Loading
Loading