| /* |
| * Copyright 2019 The Hafnium Authors. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <gmock/gmock.h> |
| |
| extern "C" { |
| #include "hf/manifest.h" |
| } |
| |
| namespace |
| { |
| using ::testing::Eq; |
| using ::testing::NotNull; |
| |
| /* |
| * DTB files compiled with: |
| * $ dtc -I dts -O dtb --out-version 17 test.dts | xxd -i |
| */ |
| |
| /* |
| * /dts-v1/; |
| * |
| * / { |
| * }; |
| * |
| */ |
| constexpr uint8_t dtb_empty_root[] = { |
| 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x38, |
| 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11, |
| 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09}; |
| |
| TEST(manifest, empty_root) |
| { |
| struct manifest m; |
| struct memiter it; |
| |
| memiter_init(&it, dtb_empty_root, sizeof(dtb_empty_root)); |
| ASSERT_EQ(manifest_init(&m, &it), |
| MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE); |
| } |
| |
| /* |
| * /dts-v1/; |
| * |
| * / { |
| * hypervisor { |
| * }; |
| * }; |
| * |
| */ |
| constexpr uint8_t dtb_no_vms[] = { |
| 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x38, |
| 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11, |
| 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0x79, 0x70, 0x65, |
| 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, |
| 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09}; |
| |
| TEST(manifest, no_vms) |
| { |
| struct manifest m; |
| struct memiter it; |
| |
| memiter_init(&it, dtb_no_vms, sizeof(dtb_no_vms)); |
| ASSERT_EQ(manifest_init(&m, &it), MANIFEST_ERROR_NO_PRIMARY_VM); |
| } |
| |
| /* |
| * /dts-v1/; |
| * |
| * / { |
| * hypervisor { |
| * vm1 { |
| * debug_name = "primary_vm"; |
| * }; |
| * vm0 { |
| * debug_name = "reserved_vm"; |
| * vcpu_count = <1>; |
| * mem_size = <4096>; |
| * kernel_filename = "kernel"; |
| * }; |
| * }; |
| * }; |
| * |
| */ |
| constexpr uint8_t dtb_reserved_vmid[] = { |
| 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x00, 0x38, |
| 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11, |
| 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, |
| 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0x79, 0x70, 0x65, |
| 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
| 0x76, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, |
| 0x00, 0x00, 0x00, 0x00, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, |
| 0x76, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, |
| 0x76, 0x6d, 0x30, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, |
| 0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, |
| 0x5f, 0x76, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, |
| 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, |
| 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x10, 0x00, |
| 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1f, |
| 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, |
| 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, |
| 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x76, |
| 0x63, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x6d, 0x65, |
| 0x6d, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x6b, 0x65, 0x72, 0x6e, 0x65, |
| 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x00}; |
| |
| TEST(manifest, reserved_vmid) |
| { |
| struct manifest m; |
| struct memiter it; |
| |
| memiter_init(&it, dtb_reserved_vmid, sizeof(dtb_reserved_vmid)); |
| ASSERT_EQ(manifest_init(&m, &it), MANIFEST_ERROR_RESERVED_VM_ID); |
| } |
| |
| /* |
| * /dts-v1/; |
| * |
| * / { |
| * hypervisor { |
| * vm1 { |
| * debug_name = ""; |
| * }; |
| * vm2 { |
| * debug_name = ""; |
| * vcpu_count = <65535>; |
| * mem_size = <0>; |
| * kernel_filename = ""; |
| * }; |
| * }; |
| * }; |
| * |
| */ |
| constexpr uint8_t dtb_last_valid_vcpu_count[] = { |
| 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x38, |
| 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11, |
| 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, |
| 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0x79, 0x70, 0x65, |
| 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
| 0x76, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, |
| 0x00, 0x00, 0x00, 0x01, 0x76, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x03, |
| 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0b, |
| 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, |
| 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, |
| 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, |
| 0x00, 0x00, 0x00, 0x09, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x6e, 0x61, |
| 0x6d, 0x65, 0x00, 0x76, 0x63, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x75, 0x6e, |
| 0x74, 0x00, 0x6d, 0x65, 0x6d, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x6b, |
| 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, |
| 0x6d, 0x65, 0x00}; |
| |
| /* Same as above, set "vcpu_count" to 65536. */ |
| constexpr uint8_t dtb_first_invalid_vcpu_count[] = { |
| 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x38, |
| 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11, |
| 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, |
| 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0x79, 0x70, 0x65, |
| 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
| 0x76, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, |
| 0x00, 0x00, 0x00, 0x01, 0x76, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x03, |
| 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0b, |
| 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, |
| 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, |
| 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, |
| 0x00, 0x00, 0x00, 0x09, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x6e, 0x61, |
| 0x6d, 0x65, 0x00, 0x76, 0x63, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x75, 0x6e, |
| 0x74, 0x00, 0x6d, 0x65, 0x6d, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x6b, |
| 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, |
| 0x6d, 0x65, 0x00}; |
| |
| TEST(manifest, vcpu_count_limit) |
| { |
| struct manifest m; |
| struct memiter it; |
| |
| memiter_init(&it, dtb_last_valid_vcpu_count, |
| sizeof(dtb_last_valid_vcpu_count)); |
| ASSERT_EQ(manifest_init(&m, &it), MANIFEST_SUCCESS); |
| ASSERT_EQ(m.num_vms, 2); |
| ASSERT_EQ(m.vm[1].secondary.vcpu_count, UINT16_MAX); |
| |
| memiter_init(&it, dtb_first_invalid_vcpu_count, |
| sizeof(dtb_first_invalid_vcpu_count)); |
| ASSERT_EQ(manifest_init(&m, &it), MANIFEST_ERROR_INTEGER_OVERFLOW); |
| } |
| |
| /* |
| * /dts-v1/; |
| * |
| * / { |
| * hypervisor { |
| * vm1 { |
| * debug_name = "primary_vm"; |
| * }; |
| * vm3 { |
| * debug_name = "second_secondary_vm"; |
| * vcpu_count = <43>; |
| * mem_size = <0x12345>; |
| * kernel_filename = "second_kernel"; |
| * }; |
| * vm2 { |
| * debug_name = "first_secondary_vm"; |
| * vcpu_count = <42>; |
| * mem_size = <12345>; |
| * kernel_filename = "first_kernel"; |
| * }; |
| * }; |
| * }; |
| * |
| */ |
| constexpr uint8_t dtb_valid[] = { |
| 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x00, 0x38, |
| 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11, |
| 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, |
| 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0x79, 0x70, 0x65, |
| 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
| 0x76, 0x6d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, |
| 0x00, 0x00, 0x00, 0x00, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, |
| 0x76, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, |
| 0x76, 0x6d, 0x33, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, |
| 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x5f, 0x73, |
| 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x76, 0x6d, 0x00, |
| 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0b, |
| 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, |
| 0x00, 0x00, 0x00, 0x16, 0x00, 0x01, 0x23, 0x45, 0x00, 0x00, 0x00, 0x03, |
| 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1f, 0x73, 0x65, 0x63, 0x6f, |
| 0x6e, 0x64, 0x5f, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x76, 0x6d, 0x32, 0x00, |
| 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, |
| 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, |
| 0x61, 0x72, 0x79, 0x5f, 0x76, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, |
| 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2a, |
| 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x16, |
| 0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, |
| 0x00, 0x00, 0x00, 0x1f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x6b, 0x65, |
| 0x72, 0x6e, 0x65, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, |
| 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, |
| 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x76, |
| 0x63, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x6d, 0x65, |
| 0x6d, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x6b, 0x65, 0x72, 0x6e, 0x65, |
| 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x00}; |
| |
| TEST(manifest, valid) |
| { |
| struct manifest m; |
| struct manifest_vm *vm; |
| struct memiter it; |
| |
| memiter_init(&it, dtb_valid, sizeof(dtb_valid)); |
| |
| ASSERT_EQ(manifest_init(&m, &it), MANIFEST_SUCCESS); |
| ASSERT_EQ(m.num_vms, 3); |
| |
| vm = &m.vm[0]; |
| ASSERT_TRUE(memiter_iseq(&vm->debug_name, "primary_vm")); |
| |
| vm = &m.vm[1]; |
| ASSERT_TRUE(memiter_iseq(&vm->debug_name, "first_secondary_vm")); |
| ASSERT_EQ(vm->secondary.vcpu_count, 42); |
| ASSERT_EQ(vm->secondary.mem_size, 12345); |
| ASSERT_TRUE( |
| memiter_iseq(&vm->secondary.kernel_filename, "first_kernel")); |
| |
| vm = &m.vm[2]; |
| ASSERT_TRUE(memiter_iseq(&vm->debug_name, "second_secondary_vm")); |
| ASSERT_EQ(vm->secondary.vcpu_count, 43); |
| ASSERT_EQ(vm->secondary.mem_size, 0x12345); |
| ASSERT_TRUE( |
| memiter_iseq(&vm->secondary.kernel_filename, "second_kernel")); |
| } |
| |
| } /* namespace */ |