Skip to content

Commit

Permalink
feat: make VirtIO devices optional when compiling
Browse files Browse the repository at this point in the history
  • Loading branch information
edubart committed Jan 23, 2024
1 parent 84c4cd1 commit c5edf93
Show file tree
Hide file tree
Showing 13 changed files with 177 additions and 48 deletions.
33 changes: 21 additions & 12 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ UARCH_RAM_IMAGE ?= ../uarch/uarch-ram.bin
release?=no
sanitize?=no
coverage?=no
nothreads?=no
threads?=yes
slirp?=yes

COVERAGE_TOOLCHAIN?=gcc
COVERAGE_OUTPUT_DIR?=coverage
Expand Down Expand Up @@ -132,15 +133,23 @@ PROFILE_DATA=

endif

LIBCARTESI_LIBS=$(SLIRP_LIB)
LIBCARTESI_GRPC_LIBS=$(SLIRP_LIB) $(GRPC_PROTOBUF_LIB)
LIBCARTESI_JSONRPC_LIBS=$(SLIRP_LIB)
LUACARTESI_LIBS=$(SLIRP_LIB)
LUACARTESI_GRPC_LIBS=$(SLIRP_LIB) $(GRPC_PROTOBUF_LIB)
LUACARTESI_JSONRPC_LIBS=$(SLIRP_LIB)
REMOTE_CARTESI_MACHINE_LIBS=$(SLIRP_LIB) $(GRPC_PROTOBUF_LIB)
JSONRPC_REMOTE_CARTESI_MACHINE_LIBS=$(SLIRP_LIB)
TEST_MACHINE_C_API_LIBS=$(SLIRP_LIB) $(GRPC_PROTOBUF_LIB)
ifeq ($(slirp),yes)
INCS+=$(SLIRP_INC)
LIBLDFLAGS+=$(SLIRP_LIB)
EXELDFLAGS+=$(SLIRP_LIB)
else
DEFS+=-DNO_SLIRP
endif

LIBCARTESI_LIBS=
LIBCARTESI_GRPC_LIBS=$(GRPC_PROTOBUF_LIB)
LIBCARTESI_JSONRPC_LIBS=
LUACARTESI_LIBS=
LUACARTESI_GRPC_LIBS=$(GRPC_PROTOBUF_LIB)
LUACARTESI_JSONRPC_LIBS=
REMOTE_CARTESI_MACHINE_LIBS=$(GRPC_PROTOBUF_LIB)
JSONRPC_REMOTE_CARTESI_MACHINE_LIBS=
TEST_MACHINE_C_API_LIBS=$(GRPC_PROTOBUF_LIB)
HASH_LIBS=

#DEFS+= -DMT_ALL_DIRTY
Expand All @@ -153,7 +162,7 @@ INCS+= \
-I../third-party/tiny_sha3 \
-I../third-party/downloads \
-I../third-party/mongoose-7.12 \
$(SLIRP_INC) $(BOOST_INC)
$(BOOST_INC)

# Use 64-bit offsets for file operations in POSIX APIs
DEFS+=-D_FILE_OFFSET_BITS=64
Expand Down Expand Up @@ -271,7 +280,7 @@ EMPTY:=
SPACE:=$(EMPTY) $(EMPTY)
CLANG_TIDY_HEADER_FILTER=$(PWD)/($(subst $(SPACE),|,$(LINTER_HEADERS)))

ifeq ($(nothreads),no)
ifeq ($(threads),yes)
CFLAGS+=$(PTHREAD_CFLAGS)
CXXFLAGS+=$(PTHREAD_CFLAGS)
LDFLAGS+=$(PTHREAD_LDFLAGS)
Expand Down
14 changes: 14 additions & 0 deletions src/machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,17 +462,31 @@ machine::machine(const machine_config &c, const machine_runtime_config &r) :
pma_name = "VirtIO Console";
vdev = std::make_unique<virtio_console>(m_vdevs.size());
} else if constexpr (std::is_same_v<T, cartesi::virtio_p9fs_config>) {
#ifdef HAVE_POSIX_FS
pma_name = "VirtIO 9P";
vdev = std::make_unique<virtio_p9fs_device>(m_vdevs.size(), vdev_config.tag,
vdev_config.host_directory);
#else
throw std::invalid_argument("virtio 9p device is unsupported in this platform");
#endif
} else if constexpr (std::is_same_v<T, cartesi::virtio_net_user_config>) {
#ifdef HAVE_SLIRP
pma_name = "VirtIO Net User";
vdev = std::make_unique<virtio_net>(m_vdevs.size(),
std::make_unique<virtio_net_carrier_slirp>(vdev_config));
#else
throw std::invalid_argument("virtio network user device is unsupported in this platform");

#endif
} else if constexpr (std::is_same_v<T, cartesi::virtio_net_tuntap_config>) {
#ifdef HAVE_TUNTAP
pma_name = "VirtIO Net TUN/TAP";
vdev = std::make_unique<virtio_net>(m_vdevs.size(),
std::make_unique<virtio_net_carrier_tuntap>(vdev_config.iface));
#else

throw std::invalid_argument("virtio network TUN/TAP device is unsupported in this platform");
#endif
} else {
throw std::invalid_argument("invalid virtio device configuration");
}
Expand Down
68 changes: 68 additions & 0 deletions src/os-features.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
//

#ifndef OS_FEATURES_H
#define OS_FEATURES_H

#if !defined(NO_TTY)
#define HAVE_TTY
#endif

#if !defined(NO_THREADS)
#define HAVE_THREADS
#endif

#if !defined(NO_TERMIOS) && !defined(_WIN32) && !defined(__wasi__)
#define HAVE_TERMIOS
#endif

#if !defined(NO_IOCTL) && !defined(_WIN32) && !defined(__wasi__)
#define HAVE_IOCTL
#endif

#if !defined(NO_MMAP) && !defined(_WIN32) && !defined(__wasi__)
#define HAVE_MMAP
#endif

#if !defined(NO_MKDIR)
#define HAVE_MKDIR
#endif

#if !defined(NO_TUNTAP) && defined(__linux__)
#define HAVE_TUNTAP
#endif

#if !defined(NO_SLIRP) && !defined(__wasi__)
#define HAVE_SLIRP
#endif

#if !defined(NO_SIGACTION) && !defined(__wasi__) && !defined(_WIN32)
#define HAVE_SIGACTION
#endif

#if !defined(NO_SELECT)
#define HAVE_SELECT
#endif

#if !defined(NO_POSIX_FILE) && !defined(__wasi__) && !defined(_WIN32)
#define HAVE_POSIX_FS
#endif

#if !defined(NO_USLEEP) && defined(__unix__)
#define HAVE_USLEEP
#endif

#endif
67 changes: 34 additions & 33 deletions src/os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,8 @@
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
//

#if !defined(NO_TTY)
#define HAVE_TTY
#endif

#if !defined(NO_THREADS)
#define HAVE_THREADS
#endif

#if !defined(_WIN32) && !defined(__wasi__) && !defined(NO_TERMIOS)
#define HAVE_TERMIOS
#endif

#if !defined(_WIN32) && !defined(__wasi__) && !defined(NO_IOCTL)
#define HAVE_IOCTL
#endif

#if !defined(_WIN32) && !defined(__wasi__) && !defined(NO_MMAP)
#define HAVE_MMAP
#endif

#if !defined(NO_MKDIR)
#define HAVE_MKDIR
#endif

#include <array>
#include <chrono>
#include <csignal>
#include <cstdint>
#include <cstdio>
#include <cstring>
Expand All @@ -49,9 +24,14 @@
#include <system_error>
#include <vector>

#include "os-features.h"
#include "os.h"
#include "unique-c-ptr.h"

#ifdef HAVE_SIGACTION
#include <csignal>
#endif

#ifdef HAVE_THREADS
#include <future>
#include <mutex>
Expand Down Expand Up @@ -98,13 +78,17 @@
#define plat_write _write
#define plat_mkdir(a, mode) _mkdir(a)

#if defined(HAVE_SELECT)
#include <winsock2.h> // select
#endif

#else // not _WIN32

#if defined(HAVE_TTY) || defined(HAVE_MMAP) || defined(HAVE_TERMIOS)
#if defined(HAVE_TTY) || defined(HAVE_MMAP) || defined(HAVE_TERMIOS) || defined(HAVE_USLEEP)
#include <unistd.h> // write/read/close
#endif

#if defined(HAVE_TTY)
#if defined(HAVE_SELECT)
#include <sys/select.h> // select
#endif

Expand Down Expand Up @@ -174,6 +158,7 @@ static int get_ttyfd(void) {
}
#endif // HAVE_TERMIOS

#ifdef HAVE_SIGACTION
/// \brief Signal raised whenever TTY size changes
static void os_SIGWINCH_handler(int sig) {
(void) sig;
Expand All @@ -185,6 +170,7 @@ static void os_SIGWINCH_handler(int sig) {
// therefore we will actually update the console size in the next get size request.
s->resize_pending = true;
}
#endif

bool os_update_tty_size(tty_state *s) {
#ifdef HAVE_TTY
Expand All @@ -203,7 +189,7 @@ bool os_update_tty_size(tty_state *s) {
}

#else
// TODO(edubart): what to do on Windows and MacOS?
// TODO(edubart): what to do on Windows?

#endif // defined(HAVE_TERMIOS) && defined(HAVE_IOCTL)
#endif // HAVE_TTY
Expand Down Expand Up @@ -299,7 +285,7 @@ void os_open_tty(void) {
// Get tty initial size
os_update_tty_size(s);

// TODO(edubart): does this handler works on Windows and MacOS?
#ifdef HAVE_SIGACTION
// Install console resize signal handler
struct sigaction sigact {};
sigact.sa_flags = SA_RESTART;
Expand All @@ -309,6 +295,7 @@ void os_open_tty(void) {
(void) fprintf(stderr, "os_open_tty(): failed to install SIGWINCH handler\n");
#endif
}
#endif

#else
throw std::runtime_error("unable to open console input, stdin is unsupported in this platform");
Expand Down Expand Up @@ -369,7 +356,7 @@ void os_prepare_tty_select(select_fd_sets *fds) {
fds->maxfd = STDIN_FILENO;
}
#else
(void) data;
(void) fds;
#endif
#endif
}
Expand Down Expand Up @@ -438,8 +425,8 @@ bool os_poll_tty(uint64_t timeout_us) {
}
if (s->hStdin) {
// Wait for an input event
const uint64_t wait_millis = (wait_us + 999) / 1000;
if (WaitForSingleObject(s->hStdin, wait_millis) != WAIT_OBJECT_0) {
const uint64_t wait_ms = (timeout_us + 999) / 1000;
if (WaitForSingleObject(s->hStdin, wait_ms) != WAIT_OBJECT_0) {
// No input events
return false;
}
Expand Down Expand Up @@ -722,6 +709,7 @@ bool os_select_fds(const os_select_before_callback &before_cb, const os_select_a
// Create empty fd sets
select_fd_sets fds{};
fds.maxfd = -1;
#ifdef HAVE_SELECT
fd_set readfds{};
fd_set writefds{};
fd_set exceptfds{};
Expand All @@ -738,13 +726,19 @@ bool os_select_fds(const os_select_before_callback &before_cb, const os_select_a
tv.tv_sec = static_cast<decltype(tv.tv_sec)>(*timeout_us / 1000000);
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(*timeout_us % 1000000);
// Wait for events
// TODO(edubart): consider supporting other OSes
const int select_ret = select(fds.maxfd + 1, &readfds, &writefds, &exceptfds, &tv);
return after_cb(select_ret, &fds);
#else
// Act like select failed
before_cb(&fds, timeout_us);
const int select_ret = -1;
#endif
// Process ready fds
return after_cb(select_ret, &fds);
}

void os_disable_sigpipe() {
#ifdef HAVE_SIGACTION
struct sigaction sigact {};
sigact.sa_handler = SIG_IGN;
sigact.sa_flags = SA_RESTART;
Expand All @@ -753,12 +747,14 @@ void os_disable_sigpipe() {
(void) fprintf(stderr, "os_disable_sigpipe(): failed to disable SIGPIPE handler\n");
#endif
}
#endif
}

void os_sleep_us(uint64_t timeout_us) {
if (timeout_us == 0) {
return;
}
#ifdef HAVE_SELECT
// Select without fds just to sleep
os_select_fds(
[](select_fd_sets *fds, const uint64_t *timeout_us) -> void {
Expand All @@ -771,5 +767,10 @@ void os_sleep_us(uint64_t timeout_us) {
return false;
},
&timeout_us);
#elif defined(HAVE_USLEEP)
usleep(static_cast<useconds_t>(*timeout_us));
#elif defined(_WIN32)
Sleep(timeout_us / 1000);
#endif
}
} // namespace cartesi
2 changes: 0 additions & 2 deletions src/virtio-device.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
#include <cstdint>
#include <cstring>

#include <sys/select.h>

#include "i-device-state-access.h"
#include "os.h"
#include "pma.h"
Expand Down
4 changes: 4 additions & 0 deletions src/virtio-net-carrier-slirp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@

#include "virtio-net-carrier-slirp.h"

#ifdef HAVE_SLIRP

#include <cerrno>
#include <chrono>
#include <cstring>
Expand Down Expand Up @@ -380,3 +382,5 @@ bool virtio_net_carrier_slirp::read_packet_from_host(i_device_state_access *a, v
}

} // namespace cartesi

#endif // HAVE_SLIRP
6 changes: 6 additions & 0 deletions src/virtio-net-carrier-slirp.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
#ifndef VIRTIO_NET_CARRIER_SLIRP_H
#define VIRTIO_NET_CARRIER_SLIRP_H

#include "os-features.h"

#ifdef HAVE_SLIRP

#include "machine-config.h"
#include "virtio-net.h"

Expand Down Expand Up @@ -85,4 +89,6 @@ class virtio_net_carrier_slirp final : public virtio_net_carrier {

} // namespace cartesi

#endif // HAVE_SLIRP

#endif
Loading

0 comments on commit c5edf93

Please sign in to comment.