Skip to content

Commit

Permalink
Allow cgp to be larger.
Browse files Browse the repository at this point in the history
We store the size of globals as a shifted value, which extends the
maximum size of globals in a compartment from 64 KiB to 256 KiB.

This adds two new tests.  One is added to the misc test and just checks
that we correctly handle globals that are larger than the range of a
csetbounds with an immediate offset.

The second checks that much larger globals work.  This test is disabled
because it uses so much RAM that we don't have enough for the allocator
tests.

At some point, we should refactor the test suite to allow subsets of the
test suite to be built.

Add test for large objects.

Fixes #230
  • Loading branch information
davidchisnall committed May 28, 2024
1 parent b043906 commit 7d9e2ef
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 10 deletions.
13 changes: 8 additions & 5 deletions sdk/core/loader/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ namespace loader
/**
* Helper for encapsulating an address range.
*/
struct __packed AddressRange
template<size_t Shift>
struct __packed ShiftedAddressRange
{
/**
* Start address.
Expand All @@ -325,10 +326,12 @@ namespace loader
*/
[[nodiscard]] size_t size() const
{
return smallSize;
return size_t(smallSize) << Shift;
}
};

using AddressRange = ShiftedAddressRange<0>;

static_assert(RawAddressRange<AddressRange>,
"AddressRange should be a raw address range");

Expand Down Expand Up @@ -441,7 +444,7 @@ namespace loader
/**
* The compartment's globals.
*/
AddressRange data;
ShiftedAddressRange<2> data;

/**
* The distance from the start of the code region to the end of the
Expand Down Expand Up @@ -612,7 +615,7 @@ namespace loader
// This is a random 32-bit number and should be changed whenever
// the compartment header layout changes to provide some sanity
// checking.
return magic == 0x6cef3879;
return magic == 0x46391da0;
}

/**
Expand Down Expand Up @@ -707,7 +710,7 @@ namespace loader
/**
* The (mutable) data section for this compartment.
*/
AddressRange data;
ShiftedAddressRange<2> data;

/**
* The size in bytes of the data section that is initialised
Expand Down
6 changes: 3 additions & 3 deletions sdk/firmware.ldscript.in
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ SECTIONS
# Scheduler globals start address
LONG(.scheduler_globals);
# Scheduler globals end size
SHORT(SIZEOF(.scheduler_globals));
SHORT(SIZEOF(.scheduler_globals) / 4);
# Size of the scheduler import table
SHORT(.scheduler_import_end - .scheduler_start);
# Address of scheduler export table
Expand All @@ -200,7 +200,7 @@ SECTIONS
# Allocator globals start address
LONG(.allocator_globals);
# Allocator globals end
SHORT(SIZEOF(.allocator_globals));
SHORT(SIZEOF(.allocator_globals) / 4);
# Size of the allocator import table
SHORT(.allocator_import_end - .allocator_start);
# Address of allocator export table
Expand Down Expand Up @@ -236,7 +236,7 @@ SECTIONS
# loader versions.
# New versions of this can be generated with:
# head /dev/random | shasum | cut -c 0-8
LONG(0x6cef3879);
LONG(0x46391da0);
# Number of library headers.
SHORT(@library_count@);
# Number of compartment headers.
Expand Down
5 changes: 3 additions & 2 deletions sdk/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,8 @@ rule("firmware")
"\n\t\tLONG(.${compartment}_export_table);" ..
"\n\t\tSHORT(.${compartment}_export_table_end - .${compartment}_export_table);" ..
"\n\t\tLONG(.${compartment}_globals);" ..
"\n\t\tSHORT(SIZEOF(.${compartment}_globals));" ..
"\n\t\tSHORT(SIZEOF(.${compartment}_globals)/4);" ..
"\n\t\tASSERT(SIZEOF(.${compartment}_globals) < 0x40000, \"${compartment}'s globals are too large\");" ..
"\n\t\tSHORT(.${compartment}_bss_start - .${compartment}_globals);" ..
"\n\t\tLONG(.${compartment}_cap_relocs_start);" ..
"\n\t\tSHORT(.${compartment}_cap_relocs_end - .${compartment}_cap_relocs_start);" ..
Expand Down Expand Up @@ -652,7 +653,7 @@ rule("firmware")
"\n\t\tLONG(.software_revoker_start);" ..
"\n\t\tSHORT(.software_revoker_end - .software_revoker_start);" ..
"\n\t\tLONG(.software_revoker_globals);" ..
"\n\t\tSHORT(SIZEOF(.software_revoker_globals));" ..
"\n\t\tSHORT(SIZEOF(.software_revoker_globals) / 4);" ..
-- The import table offset is computed from the start by code
-- that assumes that the first two words are space for sealing
-- keys, so we set it to 16 here to provide a computed size of
Expand Down
26 changes: 26 additions & 0 deletions tests/bigdata-test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "cheri.hh"
#define TEST_NAME "Big Data"
#include "tests.hh"

extern "C" enum ErrorRecoveryBehaviour
compartment_error_handler(struct ErrorState *frame, size_t mcause, size_t mtval)
{
debug_log("Detected error in instruction {}", frame->pcc);
debug_log("Error cause: {}, mtval: {}", mcause, mtval);
auto [reg, cause] = CHERI::extract_cheri_mtval(mtval);
debug_log("Error {} in register {}", reg, cause);
return ErrorRecoveryBehaviour::ForceUnwind;
}

void test_big_data()
{
register char *cgpRegister asm("cgp");
asm("" : "=C"(cgpRegister));
static uint32_t data[16384];
debug_log("Data: {}", data);
debug_log("CGP: {}", cgpRegister);
debug_log("Fill with for oop");
for (int i = 0; i < 16000; ++i) { data[i] = 0x01020304; }
debug_log( "Fill with memset");
memset(data, 0x5a, sizeof(data));
}
20 changes: 20 additions & 0 deletions tests/misc-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
#include <string.h>
#include <timeout.h>

namespace
{
char largeBuffer[4096];
const char largeConstBuffer[4096] = "This is a large const buffer buffer.";
} // namespace

/**
* Test timeouts.
*
Expand Down Expand Up @@ -87,6 +93,20 @@ void check_memchr()

void test_misc()
{
CHERI::Capability largeRW{largeBuffer};
CHERI::Capability largeRO{largeConstBuffer};
debug_log("RW: {}", largeRW);
debug_log("RO: {}", largeRO);
TEST(largeRW.length() == sizeof(largeBuffer),
"Large buffer has the wrong size: {}", largeRW.length());
TEST(largeRO.length() == sizeof(largeConstBuffer),
"Large const buffer has the wrong size: {}", largeRO.length());
TEST(largeRW.is_valid(), "Large buffer is untagged");
TEST(largeRO.is_valid(), "Large const buffer is untagged");
TEST(largeRW.permissions().contains(CHERI::Permission::Store),
"Large buffer is not writable: {}", largeRW);
TEST(!largeRO.permissions().contains(CHERI::Permission::Store),
"Large const buffer is writable");
check_timeouts();
check_memchr();
}
3 changes: 3 additions & 0 deletions tests/test-runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ void __cheri_compartment("test_runner") run_tests()
debug_log("Trying to print string: {}", std::string_view{testString, 13});

run_timed("All tests", []() {
// This test is disabled because it uses too much memory for the heap
// tests to work.
// run_timed("big data in globals", test_big_data);
run_timed("Debug helpers (C++)", test_debug_cxx);
run_timed("Debug helpers (C)", test_debug_c);
run_timed("MMIO", test_mmio);
Expand Down
1 change: 1 addition & 0 deletions tests/tests.hh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ __cheri_compartment("static_sealing_test") void test_static_sealing();
__cheri_compartment("stdio_test") void test_stdio();
__cheri_compartment("debug_test") void test_debug_cxx();
__cheri_compartment("debug_test") void test_debug_c();
__cheri_compartment("bigdata_test") void test_big_data();

// Simple tests don't need a separate compartment.
void test_global_constructors();
Expand Down
1 change: 1 addition & 0 deletions tests/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ test("stdio")
-- Test the debug helpers.
test("debug")
add_files("debug-test.c")
-- test("bigdata")
-- Test the static sealing types
test("static_sealing")
compartment("static_sealing_inner")
Expand Down

0 comments on commit 7d9e2ef

Please sign in to comment.