| // Copyright Microsoft and CHERIoT Contributors. | |
| // SPDX-License-Identifier: MIT | |
| #include "hello.h" | |
| #include <debug.hh> | |
| #include <fail-simulator-on-error.h> | |
| #include <futex.h> | |
| #include <string_view> | |
| /// Expose debugging features unconditionally for this compartment. | |
| using Debug = ConditionalDebug<true, "UART compartment">; | |
| // Import some useful things from the CHERI namespace. | |
| using namespace CHERI; | |
| /// Write a message to the UART. | |
| void write(const char *msg) | |
| { | |
| // Word containing the lock, this is 0 for unlocked, 1 for locked. | |
| static uint32_t lockWord = 0; | |
| with_interrupts_disabled([]() { | |
| // Check the word is 0, if it isn't then yield. We may be woken after | |
| // another thread that manages to get the lock and so we need to retry | |
| // in a loop. | |
| while (lockWord != 0) | |
| { | |
| futex_wait(&lockWord, 0); | |
| } | |
| lockWord = 1; | |
| }); | |
| // Make sure that this is a valid readable capability. | |
| if (check_pointer<PermissionSet{Permission::Load}>(msg)) | |
| { | |
| // Don't assume that there's a null terminator. | |
| std::string_view message{msg, | |
| static_cast<size_t>(Capability{msg}.bounds())}; | |
| Debug::log("{}", message); | |
| } | |
| // Release the lock. | |
| lockWord = 0; | |
| futex_wake(&lockWord, -1); | |
| } |