Skip to content

Trap guestOS to run SDL-oriented applications #551

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

Merged
merged 2 commits into from
Feb 1, 2025

Conversation

ChinYikMing
Copy link
Collaborator

@ChinYikMing ChinYikMing commented Jan 31, 2025

To trap the guest OS SDL applications, virtual memory translation should be handled when accessing the bidirectional event queues in syscall_sdl.c. Additionally, when using the guest OS, the SDL application might be launched and terminated multiple times. To enhance the user experience, it is heuristic to properly handle three main types of exits:
1, SDL application built-in exit: The source code of the SDL application should be modified to call the syscall_exit(syscall number: 93) somewhere when executing cleanup routine before exit().
2. Ctrl-c (SIGINT) exit: Detect the ctrl-c keycode.
3. SDL window Quit event: The source code of the SDL application should be modified to call the syscall_exit(syscall number: 93) when receiving SDL window Quit event.

The main reason for handling these three types of exits is that SDL2_Mixer may malfunction if not properly initialized and destroyed, as it runs on the host side not on the guest side. Additionally, when terminating an SDL application in the guest OS, the previous SDL window should be closed.

Moreover, the default audio backend of SDL2_Mixer(downloadable from brew or Linux distro pkg managers), FluidSynth, occasionally generates the warning: "fluidsynth: warning: Ringbuffer full, try increasing synth.polyphony!" This issue causes the audio to hang, leading to an unstable playback experience. Thus, dropping FluidSynth in favor of the Timidity backend, which provides a stable audio playback experience.

Known issue: Calling SDL_DestroyWindow() on macOS does not close the previous SDL window.

Close: #510

Note that the following steps are conducted on Ubuntu 22.04 x86-64 machine

Build SDL2_Mixer from source

  1. Download https://github.com/libsdl-org/SDL_mixer and checkout to commit de7b2f4d2a7e78db363cb26a66df4da1f9524e25

  2. Disable FluidSynth

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -110,7 +110,7 @@ endif()
 
 option(SDL2MIXER_MIDI "Enable MIDI music" ON)
 
-cmake_dependent_option(SDL2MIXER_MIDI_FLUIDSYNTH "Support FluidSynth MIDI output" ON "SDL2MIXER_MIDI;NOT SDL2MIXER_VENDORED" OFF)
+cmake_dependent_option(SDL2MIXER_MIDI_FLUIDSYNTH "Support FluidSynth MIDI output" OFF "SDL2MIXER_MIDI;NOT SDL2MIXER_VENDORED" OFF)
 cmake_dependent_option(SDL2MIXER_MIDI_FLUIDSYNTH_SHARED "Dynamically load libfluidsynth" "${SDL2MIXER_DEPS_SHARED}" SDL2MIXER_MIDI_FLUIDSYNTH OFF)
 
 if(WIN32 OR APPLE OR HAIKU)
  1. Build (note that this will override the pre-installed SDL2_Mixer)
    Might need to install some dependency library(see the error logs if it shows)
$ mkdir -p build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_INCLUDEDIR=include && make -j$(nproc) && sudo make install 
  1. Download timidity's GUS patches which from the README of SDL2_Mixer.
  2. Extract timidity/* into /etc/ directory.

Testing procedure

  1. Unzip Image.zip and rootfs.cpio.zip to desired path.
    Image.zip
    rootfs.cpio.zip

  2. Build rv32emu

$ make INITRD_SIZE=64 ENABLE_SYSTEM=1 ENABLE_SDL=1 -j$(nproc)
  1. Run rv32emu with provided Image and rootfs.cpio
$ build/rv32emu -k <kernel_img_path> -i <rootfs_img_path>
  1. Run SDL-oriented application in guestOS (doom-riscv or quake or smolnes)
# doom-riscv

Expectation

Three SDL-oriented applications should be runable and can be exited with all three types of exits without any crash.

Update: (SDL2_mixer build from source on macOS/arm64)

The 1, 2, 4, 5 steps are same to Linux host, but a tiny change to step 3:
3. Build (note that this will override the pre-installed SDL2_Mixer)
Might need to install some dependency library(see the error logs if it shows)

$ mkdir -p build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=/opt/homebrew -DCMAKE_INSTALL_INCLUDEDIR=include && make -j$(sysctl -n hw.logicalcpu) && sudo make install 

Copy link
Contributor

@jserv jserv left a comment

Choose a reason for hiding this comment

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

Benchmarks

Benchmark suite Current: f20b959 Previous: 515e011 Ratio
Dhrystone 1324 Average DMIPS over 10 runs 1306 Average DMIPS over 10 runs 0.99
Coremark 961.974 Average iterations/sec over 10 runs 963.25 Average iterations/sec over 10 runs 1.00

This comment was automatically generated by workflow using github-action-benchmark.

@ChinYikMing ChinYikMing force-pushed the trap-guestOS-SDL-app branch 3 times, most recently from 387e715 to a862132 Compare February 1, 2025 04:53
@jserv jserv added this to the release-2025.1 milestone Feb 1, 2025
To trap the guest OS SDL applications, virtual memory translation should
be handled when accessing the bidirectional event queues in
syscall_sdl.c. Additionally, when using the guest OS, the SDL
application might be launched and terminated multiple times. To enhance
the user experience, it is heuristic to properly handle three main types
of exits:
1, SDL application built-in exit: The source code of the SDL application
   should be modified to call the syscall_exit(syscall number: 93)
   somewhere when executing cleanup routine before exit().
2. Ctrl-c (SIGINT) exit: Detect the ctrl-c keycode.
3. SDL window Quit event: The source code of the SDL application
   should be modified to call the syscall_exit(syscall number: 93) when
   receiving SDL window Quit event.

The main reason for handling these three types of exits is that
SDL2_Mixer may malfunction if not properly initialized and destroyed, as
it runs on the host side not on the guest side. Additionally, when
terminating an SDL application in the guest OS, the previous SDL window
should be closed.

Moreover, the default audio backend of SDL2_Mixer(downloadable from brew
or Linux distro pkg managers), FluidSynth, occasionally generates the
warning: "fluidsynth: warning: Ringbuffer full, try
increasing synth.polyphony!" This issue causes the audio to hang,
leading to an unstable playback experience. Thus, dropping FluidSynth in
favor of the Timidity backend, which provides a stable audio playback
experience.

Known issue: Calling SDL_DestroyWindow() on macOS does not close the
previous SDL window.

Close: sysprog21#510
@ChinYikMing
Copy link
Collaborator Author

Once this merged, I will upload more compact rootfs.cpio to rv32emu-prebuilt.

@jserv jserv merged commit a8b202c into sysprog21:master Feb 1, 2025
9 checks passed
@jserv
Copy link
Contributor

jserv commented Feb 1, 2025

Thank @ChinYikMing for contributing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Trap-and-emulate guestOS SDL-based applications
2 participants