SMC whitelist from the manifest.
This works for a small number of SMCs. `smc_whitelist` is a list of the
SMCs a VM is allowed to make. `smc_whitelist_permissive` can be set to
allow SMCs through even if they are not whitelisted (for development and
debug).
Bug: 132421503
Change-Id: I64b243d551da35f7625368a72a5a3980d63752f9
diff --git a/src/manifest_test.cc b/src/manifest_test.cc
index 902cf21..ec38a56 100644
--- a/src/manifest_test.cc
+++ b/src/manifest_test.cc
@@ -16,6 +16,7 @@
#include <array>
#include <cstdio>
+#include <span>
#include <sstream>
#include <gmock/gmock.h>
@@ -26,7 +27,9 @@
namespace
{
+using ::testing::ElementsAre;
using ::testing::Eq;
+using ::testing::IsEmpty;
using ::testing::NotNull;
template <typename T>
@@ -120,7 +123,7 @@
StartChild("/");
}
- std::vector<char> Build()
+ std::vector<char> Build(bool dump = false)
{
const char *program = "./build/image/dtc.py";
const char *dtc_args[] = {program, "compile", NULL};
@@ -129,10 +132,19 @@
/* Finish root node. */
EndChild();
+ if (dump) {
+ Dump();
+ }
+
exec(program, dtc_args, dts_.str(), &dtc_stdout);
return dtc_stdout;
}
+ void Dump()
+ {
+ std::cerr << dts_.str() << std::endl;
+ }
+
ManifestDtBuilder &StartChild(const std::string_view &name)
{
dts_ << name << " {" << std::endl;
@@ -166,16 +178,33 @@
return StringProperty("ramdisk_filename", value);
}
- ManifestDtBuilder &VcpuCount(uint64_t value)
+ ManifestDtBuilder &VcpuCount(uint32_t value)
{
return IntegerProperty("vcpu_count", value);
}
- ManifestDtBuilder &MemSize(uint64_t value)
+ ManifestDtBuilder &MemSize(uint32_t value)
{
return IntegerProperty("mem_size", value);
}
+ ManifestDtBuilder &SmcWhitelist(const std::vector<uint32_t> &value)
+ {
+ return IntegerListProperty("smc_whitelist", value);
+ }
+
+ ManifestDtBuilder &SmcWhitelistPermissive()
+ {
+ return BooleanProperty("smc_whitelist_permissive");
+ }
+
+ ManifestDtBuilder &Property(const std::string_view &name,
+ const std::string_view &value)
+ {
+ dts_ << name << " = " << value << ";" << std::endl;
+ return *this;
+ }
+
private:
ManifestDtBuilder &StringProperty(const std::string_view &name,
const std::string_view &value)
@@ -204,12 +233,29 @@
}
ManifestDtBuilder &IntegerProperty(const std::string_view &name,
- uint64_t value)
+ uint32_t value)
{
dts_ << name << " = <" << value << ">;" << std::endl;
return *this;
}
+ ManifestDtBuilder &IntegerListProperty(
+ const std::string_view &name,
+ const std::vector<uint32_t> &value)
+ {
+ dts_ << name << " = < ";
+ for (const uint32_t entry : value) {
+ dts_ << entry << " ";
+ }
+ dts_ << ">;" << std::endl;
+ return *this;
+ }
+
+ ManifestDtBuilder &BooleanProperty(const std::string_view &name)
+ {
+ return IntegerProperty(name, 1);
+ }
+
std::stringstream dts_;
};
@@ -365,7 +411,7 @@
ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_RESERVED_VM_ID);
}
-static std::vector<char> gen_vcpu_count_limit_dtb(uint64_t vcpu_count)
+static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
{
/* clang-format off */
return ManifestDtBuilder()
@@ -426,6 +472,51 @@
ASSERT_STREQ(string_data(&m.vm[0].primary.ramdisk_filename), "");
}
+TEST(manifest, valid_true_booleans)
+{
+ struct manifest m;
+ struct manifest_vm *vm;
+ struct fdt_node fdt_root;
+
+ /* clang-format off */
+ std::vector<char> dtb = ManifestDtBuilder()
+ .StartChild("hypervisor")
+ .Compatible()
+ .StartChild("vm1")
+ .DebugName("primary_vm")
+ .Property("smc_whitelist_permissive", "\"false\"")
+ .EndChild()
+ .StartChild("vm2")
+ .DebugName("first_secondary_vm")
+ .VcpuCount(42)
+ .MemSize(12345)
+ .Property("smc_whitelist_permissive", "<0>")
+ .EndChild()
+ .StartChild("vm3")
+ .DebugName("second_secondary_vm")
+ .VcpuCount(43)
+ .MemSize(0x12345)
+ .Property("smc_whitelist_permissive", "\"true\"")
+ .EndChild()
+ .EndChild()
+ .Build();
+ /* clang-format on */
+
+ ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
+
+ ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
+ ASSERT_EQ(m.vm_count, 3);
+
+ vm = &m.vm[0];
+ ASSERT_TRUE(vm->smc_whitelist.permissive);
+
+ vm = &m.vm[1];
+ ASSERT_TRUE(vm->smc_whitelist.permissive);
+
+ vm = &m.vm[2];
+ ASSERT_TRUE(vm->smc_whitelist.permissive);
+}
+
TEST(manifest, valid)
{
struct manifest m;
@@ -440,6 +531,7 @@
.DebugName("primary_vm")
.KernelFilename("primary_kernel")
.RamdiskFilename("primary_ramdisk")
+ .SmcWhitelist({0x32000000, 0x33001111})
.EndChild()
.StartChild("vm3")
.DebugName("second_secondary_vm")
@@ -451,6 +543,8 @@
.DebugName("first_secondary_vm")
.VcpuCount(42)
.MemSize(12345)
+ .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
+ .SmcWhitelistPermissive()
.EndChild()
.EndChild()
.Build();
@@ -466,12 +560,20 @@
ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
"primary_ramdisk");
+ ASSERT_THAT(
+ std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
+ ElementsAre(0x32000000, 0x33001111));
+ ASSERT_FALSE(vm->smc_whitelist.permissive);
vm = &m.vm[1];
ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
ASSERT_STREQ(string_data(&vm->kernel_filename), "");
ASSERT_EQ(vm->secondary.vcpu_count, 42);
ASSERT_EQ(vm->secondary.mem_size, 12345);
+ ASSERT_THAT(
+ std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
+ ElementsAre(0x04000000, 0x30002222, 0x31445566));
+ ASSERT_TRUE(vm->smc_whitelist.permissive);
vm = &m.vm[2];
ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
@@ -479,6 +581,10 @@
"second_secondary_kernel");
ASSERT_EQ(vm->secondary.vcpu_count, 43);
ASSERT_EQ(vm->secondary.mem_size, 0x12345);
+ ASSERT_THAT(
+ std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
+ IsEmpty());
+ ASSERT_FALSE(vm->smc_whitelist.permissive);
}
} /* namespace */