diff --git a/GNUmakefile b/GNUmakefile index e168853..9cc46a7 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -100,7 +100,7 @@ install-opam-%: all opam/solo5-bindings-%.pc force-install $(PREFIX)/lib/solo5-bindings-$* \ $(PREFIX)/include/solo5-bindings-$*/solo5 \ $(PREFIX)/include/solo5-bindings-$*/crt - cp -R include/solo5 include/crt $(PREFIX)/include/solo5-bindings-$* + cp -R include/solo5 $(PREFIX)/include/solo5-bindings-$* ifndef CONFIG_GENODE cp bindings/$*/solo5_$*.o bindings/$*/solo5_$*.lds \ $(PREFIX)/lib/solo5-bindings-$* @@ -109,7 +109,6 @@ else $(PREFIX)/lib/solo5-bindings-$* endif cp opam/solo5-bindings-$*.pc $(PREFIX)/lib/pkgconfig - cp elftool/solo5-elftool $(PREFIX)/bin ifdef CONFIG_HVT cp tenders/hvt/solo5-hvt tenders/hvt/solo5-hvt-configure $(PREFIX)/bin - [ -f tenders/hvt/solo5-hvt-debug ] && \ diff --git a/Makefile.common b/Makefile.common index 5ccc2ea..a7d5671 100644 --- a/Makefile.common +++ b/Makefile.common @@ -31,6 +31,7 @@ include $(TOPDIR)/Makeconf # CC := $(MAKECONF_CC) CFLAGS := -std=c11 -Wall -Wextra -Werror -O2 -g +CXXLAGS += -std=gnu++17 -Wall -Wextra -Werror -O2 -g CFLAGS += -ffreestanding -fstack-protector-strong $(MAKECONF_CFLAGS) CPPFLAGS := -isystem $(TOPDIR)/include/crt -I$(TOPDIR)/include/solo5 LD := $(MAKECONF_LD) @@ -53,6 +54,12 @@ define COMPILE.c mv -f $*.Td $*.d && touch $@ endef +define COMPILE.cc + @echo "CXX $<" + $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@ + mv -f $*.Td $*.d && touch $@ +endef + define COMPILE.S @echo "AS $<" $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -DASM_FILE -c $< -o $@ @@ -63,7 +70,7 @@ endef # The following variables and recpies apply to building tenders, i.e. # artifacts built to run on the (Solo5 tender's) *host*. # -HOSTCC := $(MAKECONF_CC) +HOSTCC := $(MAKECONF_HOSTCC) HOSTCFLAGS := -Wall -Werror -std=c11 -fstack-protector-strong -O2 -g HOSTCPPFLAGS := -I$(TOPDIR)/include/solo5 HOSTLDFLAGS := @@ -71,7 +78,7 @@ HOSTLDLIBS := HOSTAR := ar define HOSTCOMPILE.c - @echo "HOSTCC $<" + @echo "HOSTCC $(HOSTCC) $(DEPFLAGS) $(HOSTCFLAGS) $(HOSTCPPFLAGS) -c $< -o $@" $(HOSTCC) $(DEPFLAGS) $(HOSTCFLAGS) $(HOSTCPPFLAGS) -c $< -o $@ mv -f $*.Td $*.d && touch $@ endef diff --git a/bindings/GNUmakefile b/bindings/GNUmakefile index 147c245..d3efb36 100644 --- a/bindings/GNUmakefile +++ b/bindings/GNUmakefile @@ -57,7 +57,7 @@ muen_SRCS := muen/start.c $(common_SRCS) $(common_hvt_SRCS) \ muen/muen-clock.c muen/muen-console.c muen/muen-net.c \ muen/muen-platform_lifecycle.c muen/muen-yield.c muen/muen-sinfo.c -genode_SRCS := genode/stubs.c +genode_SRCS := genode/bindings.cc CPPFLAGS+=-D__SOLO5_BINDINGS__ @@ -70,6 +70,9 @@ endif %.o: %.c %.d $(COMPILE.c) +%.o: %.cc %.d + $(COMPILE.cc) + %.o: %.S %.d $(COMPILE.S) @@ -139,9 +142,7 @@ muen/solo5_muen.o: $(muen_OBJS) endif ifdef CONFIG_GENODE - genode_OBJS := $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(genode_SRCS))) - -$(genode_OBJS): CFLAGS += -Wno-unused-parameter + genode_OBJS := $(patsubst %.cc,%.o,$(patsubst %.S,%.o,$(genode_SRCS))) GENODE_LDFLAGS := -nostdlib -z max-page-size=$(CONFIG_GUEST_PAGE_SIZE) -shared \ -gc-sections --eh-frame-hdr --entry=0x0 -T genode/genode_rel.ld diff --git a/bindings/genode/bindings.cc b/bindings/genode/bindings.cc index eb55ffb..1c1d082 100644 --- a/bindings/genode/bindings.cc +++ b/bindings/genode/bindings.cc @@ -35,10 +35,12 @@ #include #include +#define restrict __restrict__ + /* Solo5 includes */ extern "C" { #include "../bindings.h" -extern struct mft_note __solo5_manifest_note; +extern struct mft1_note __solo5_mft1_note; } // Compile the MFT utilities as C++ @@ -162,7 +164,7 @@ struct Solo5::Net_device final : Device Net_device(struct mft_entry &me, Genode::Env &env, Range_allocator &alloc, - solo5_handle_set_t ready_set, + solo5_handle_set_t &ready_set, solo5_handle_t handle) : _nic(env, &alloc, NIC_BUFFER_SIZE, NIC_BUFFER_SIZE, me.name) , _signal_handler(env.ep(), *this, &Net_device::_handle_signal) @@ -330,7 +332,7 @@ struct Solo5::Platform static Platform *instance; static Device *devices[MFT_MAX_ENTRIES]; - struct mft &mft; + struct mft const &mft; /** * Reference to the Genode base enviroment @@ -376,7 +378,7 @@ struct Solo5::Platform * * TODO: periodic RTC synchronization */ - Genode::uint64_t _initial_epoch { rtc_epoch(env) }; + Genode::uint64_t _initial_epoch { 0 }; /** * Commandline buffer @@ -387,7 +389,8 @@ struct Solo5::Platform /** * Constructor */ - Platform(struct mft &mft, Genode::Env &env) : mft(mft), env(env) + Platform(struct mft const &mft, Genode::Env &env) + : mft(mft), env(env) { /** * Acquire and attach a ROM dataspace (shared @@ -400,7 +403,7 @@ struct Solo5::Platform // Copy-out the cmdline if configured. try { cmdline = config.sub_node("cmdline").decoded_content(); } - catch (...) { } + catch (Genode::Xml_node::Nonexistent_sub_node) { } for (solo5_handle_t i = 0U; i < MFT_MAX_ENTRIES; ++i) { devices[i] = &invalid_device; @@ -422,6 +425,20 @@ struct Solo5::Platform ** Solo5 bindings ** ********************/ + solo5_time_t clock_wall() + { + if (_initial_epoch == 0) { + try { _initial_epoch = rtc_epoch(env); } + catch (Genode::Service_denied) { + Genode::error("Solo5: RTC time service not available. Aborting."); + solo5_abort(); + } + } + + return _initial_epoch * 1000000000ULL + + timer.curr_time().trunc_to_plain_us().value * 1000ULL; + } + void yield(solo5_time_t deadline_ns, solo5_handle_set_t *ready_set) { @@ -526,9 +543,7 @@ solo5_time_t solo5_clock_monotonic(void) solo5_time_t solo5_clock_wall(void) { - return Platform::instance->_initial_epoch * 1000000000ULL - + Platform::instance->timer.curr_time() - .trunc_to_plain_us().value * 1000ULL; + return Platform::instance->clock_wall(); } @@ -616,16 +631,19 @@ solo5_set_tls_base(uintptr_t base) void Component::construct(Genode::Env &env) { /* Validate the device manifest */ - struct mft &mft = __solo5_manifest_note.m; - size_t mft_size = __solo5_manifest_note.h.descsz; - if (mft_validate(&mft, mft_size) != 0) { - Genode::error("Solo5: Built-in manifest validation failed. Aborting"); + const struct mft *mft; + size_t mft_size; + + mft_get_builtin_mft1(&__solo5_mft1_note, &mft, &mft_size); + + if (mft_validate(mft, mft_size) != 0) { + Genode::error("Solo5: Built-in manifest validation failed. Aborting."); env.parent().exit(~0); return; } /* Construct a statically allocated platform object */ - static Solo5::Platform inst(mft, env); + static Solo5::Platform inst(*mft, env); Platform::instance = &inst; static struct solo5_start_info si { @@ -641,12 +659,14 @@ void Component::construct(Genode::Env &env) if (si.heap_size > 1<<20) si.heap_size -= 1<<19; - /* allocate a contiguous memory region for the application */ - Genode::Dataspace_capability heap_ds = - env.pd().alloc(si.heap_size); + { + /* allocate a contiguous memory region for the application */ + Genode::Dataspace_capability heap_ds = + env.pd().alloc(si.heap_size); - /* attach into our address-space */ - si.heap_start = env.rm().attach(heap_ds); + /* attach into our address-space */ + si.heap_start = env.rm().attach(heap_ds); + } /* block for application then exit */ env.parent().exit(solo5_app_main(&si)); diff --git a/configure.sh b/configure.sh index d5afdab..ab5419f 100755 --- a/configure.sh +++ b/configure.sh @@ -142,6 +142,10 @@ case ${CC_MACHINE} in CONFIG_ARCH=x86_64 CONFIG_HOST=OpenBSD CONFIG_GUEST_PAGE_SIZE=0x1000 ;; + x86_64-*genode*) + CONFIG_ARCH=x86_64 CONFIG_HOST=Genode + CONFIG_GUEST_PAGE_SIZE=0x1000 + ;; *) die "Unsupported toolchain target: ${CC_MACHINE}" ;; @@ -287,6 +291,21 @@ case "${CONFIG_HOST}" in [ "${CONFIG_ARCH}" = "x86_64" ] && CONFIG_MUEN=1 CONFIG_GENODE= ;; + Genode) + cc_is_clang || die "Only 'clang' is supported on Genode" + [ "${CONFIG_ARCH}" = "x86_64" ] || + die "Only 'x86_64' is supported on Genode" + ld_is_lld || die "Using GNU 'ld' is not supported on Genode" + + MAKECONF_CFLAGS="-mno-retpoline -nostdlibinc" + MAKECONF_LDFLAGS="-nopie" + + CONFIG_HVT= + CONFIG_SPT= + CONFIG_VIRTIO= + CONFIG_MUEN= + CONFIG_GENODE=1 + ;; *) die "Unsupported build OS: ${CONFIG_HOST}" ;; @@ -299,7 +318,7 @@ esac # GNU make. Given the differences in quoting rules between the two # (unable to sensibly use VAR="VALUE"), our convention is as follows: # -# 1. GNU make parses the entire file, i.e. all variables defined below are +# 1. GNU make parses the entire file, i.e. all variables defined below are # available to Makefiles. # # 2. Shell scripts parse the subset of *lines* starting with "CONFIG_". I.e. @@ -323,6 +342,7 @@ CONFIG_HOST=${CONFIG_HOST} CONFIG_GUEST_PAGE_SIZE=${CONFIG_GUEST_PAGE_SIZE} MAKECONF_CC=${CC} MAKECONF_LD=${LD} +MAKECONF_HOSTCC=${HOSTCC} CONFIG_SPT_NO_PIE=${CONFIG_SPT_NO_PIE} EOM diff --git a/include/solo5/mft_abi.h b/include/solo5/mft_abi.h index 537c7bc..c51c90e 100644 --- a/include/solo5/mft_abi.h +++ b/include/solo5/mft_abi.h @@ -154,7 +154,8 @@ struct mft1_note { * Internal alignment of (m) within struct mft1_note. Must be passed to * elf_load_note() as note_align when loading. */ -#define MFT1_NOTE_ALIGN offsetof(struct { char c; struct mft m; }, m) +struct foo { char c; struct mft m; }; +#define MFT1_NOTE_ALIGN offsetof(struct foo, m) _Static_assert((offsetof(struct mft1_note, m) & (MFT1_NOTE_ALIGN - 1)) == 0, "struct mft1_note.m is not aligned to a MFT1_NOTE_ALIGN boundary"); diff --git a/tenders/common/mft.c b/tenders/common/mft.c index 56024ab..7d05713 100644 --- a/tenders/common/mft.c +++ b/tenders/common/mft.c @@ -37,11 +37,11 @@ int mft_validate(const struct mft *mft, size_t mft_size) * as untrusted data. */ if (mft_size < sizeof(*mft)) - return -1; + return __LINE__; if (mft->version != MFT_VERSION) - return -1; + return __LINE__; if (mft->entries > MFT_MAX_ENTRIES) - return -1; + return __LINE__; /* * mft_size must be the exact expected structure size, including the space * required for manifest entires. @@ -51,17 +51,17 @@ int mft_validate(const struct mft *mft, size_t mft_size) */ if (mft_size != (sizeof(struct mft) + (mft->entries * sizeof(struct mft_entry)))) - return -1; + return __LINE__; /* * The manifest must contain at least one entry, and the first entry must * be of type MFT_RESERVED_FIRST with an empty name. */ if (mft->entries < 1) - return -1; + return __LINE__; if (mft->e[0].type != MFT_RESERVED_FIRST) - return -1; + return __LINE__; if (mft->e[0].name[0] != 0) - return -1; + return __LINE__; for (unsigned i = 0; i != mft->entries; i++) { /* @@ -69,7 +69,7 @@ int mft_validate(const struct mft *mft, size_t mft_size) * in the array itself. */ if (mft->e[i].name[MFT_NAME_MAX] != 0) - return -1; + return __LINE__; /* * Sanitize private fields (to be used by the tender/bindings): * @@ -77,7 +77,7 @@ int mft_validate(const struct mft *mft, size_t mft_size) * uninitialised). */ if (mft->e[i].attached != false) - return -1; + return __LINE__; } return 0; diff --git a/tests/test_tls/GNUmakefile b/tests/test_tls/GNUmakefile deleted file mode 100644 index cc7f951..0000000 --- a/tests/test_tls/GNUmakefile +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2015-2019 Contributors as noted in the AUTHORS file -# -# This file is part of Solo5, a sandboxed execution environment. -# -# Permission to use, copy, modify, and/or distribute this software -# for any purpose with or without fee is hereby granted, provided -# that the above copyright notice and this permission notice appear -# in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE -# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR -# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -include $(TOPDIR)/Makefile.common - -test_NAME := test_tls - -include ../Makefile.tests diff --git a/tests/test_tls/manifest.json b/tests/test_tls/manifest.json deleted file mode 100644 index 1100fc5..0000000 --- a/tests/test_tls/manifest.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "type": "solo5.manifest", - "version": 1, - "devices": [ ] -} diff --git a/tests/test_tls/test_tls.c b/tests/test_tls/test_tls.c deleted file mode 100644 index ce441b9..0000000 --- a/tests/test_tls/test_tls.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2015-2019 Contributors as noted in the AUTHORS file - * - * This file is part of Solo5, a sandboxed execution environment. - * - * Permission to use, copy, modify, and/or distribute this software - * for any purpose with or without fee is hereby granted, provided - * that the above copyright notice and this permission notice appear - * in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "solo5.h" -#include "../../bindings/lib.c" - -#if defined(__x86_64__) || defined(__powerpc64__) -/* Variant II */ -struct tcb { - volatile uint64_t _data; - void *tp; -}; - -#define PPC64_TLS_OFFSET 0x7000 - -#elif defined(__aarch64__) -/* Variant I */ -struct tcb { - void *tp; - void *pad; - volatile uint64_t _data; -}; -#else -#error Unsupported architecture -#endif - -struct tcb tcb1; -struct tcb tcb2; - -static void puts(const char *s) -{ - solo5_console_write(s, strlen(s)); -} - -#if defined(__OpenBSD__) -/* __thread is not supported in OpenBSD (this test fails on it). */ -volatile uint64_t _data; -#else -__thread volatile uint64_t _data; -#endif - -uint64_t __attribute__ ((noinline)) get_data() -{ - return _data; -} - -void __attribute__ ((noinline)) set_data(uint64_t data) -{ - _data = data; -} - -int solo5_app_main(const struct solo5_start_info *si __attribute__((unused))) -{ - puts("\n**** Solo5 standalone test_tls ****\n\n"); - -#if defined (__powerpc64__) - tcb1.tp = (void *)&tcb1._data + PPC64_TLS_OFFSET; - tcb2.tp = (void *)&tcb2._data + PPC64_TLS_OFFSET; -#else - tcb1.tp = &tcb1.tp; - tcb2.tp = &tcb2.tp; -#endif - - if (solo5_set_tls_base((uintptr_t)tcb1.tp) != SOLO5_R_OK) - return 1; - set_data(1); - - if (solo5_set_tls_base((uintptr_t)tcb2.tp) != SOLO5_R_OK) - return 2; - set_data(2); - - if (solo5_set_tls_base((uintptr_t)tcb1.tp) != SOLO5_R_OK) - return 3; - if (get_data() != 1) - return 4; - - if (solo5_set_tls_base((uintptr_t)tcb2.tp) != SOLO5_R_OK) - return 5; - if (get_data() != 2) - return 6; - - puts("SUCCESS\n"); - return SOLO5_EXIT_SUCCESS; -}