security/intel/stm: Provide MSEG too small diagnostic information

This patch provides diagnostic information during the STM setup to
indicate when the MSEG is too small for what the STM requires.
The error message includes the configured MSEG size and the MSEG
area that the STM needs.

Change-Id: I88d947e3a0495089be886f6557e4d4d7993e2508
Signed-off-by: Eugene Myers <edmyers@tycho.nsa.gov>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/55630
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Eugene Myers 2021-06-17 04:59:27 -04:00 committed by Stefan Reinauer
parent 34010e8adb
commit 92c1a19c79
1 changed files with 60 additions and 94 deletions

View File

@ -39,8 +39,7 @@
#define STM_PAGE_SHIFT 12 #define STM_PAGE_SHIFT 12
#define STM_PAGE_MASK 0xFFF #define STM_PAGE_MASK 0xFFF
#define STM_SIZE_TO_PAGES(a) \ #define STM_SIZE_TO_PAGES(a) (((a) >> STM_PAGE_SHIFT) + (((a)&STM_PAGE_MASK) ? 1 : 0))
(((a) >> STM_PAGE_SHIFT) + (((a)&STM_PAGE_MASK) ? 1 : 0))
#define STM_PAGES_TO_SIZE(a) ((a) << STM_PAGE_SHIFT) #define STM_PAGES_TO_SIZE(a) ((a) << STM_PAGE_SHIFT)
#define STM_ACCESS_DENIED 15 #define STM_ACCESS_DENIED 15
@ -137,12 +136,9 @@ static bool handle_single_resource(STM_RSC *resource, STM_RSC *record)
resource_hi = resource->mem.base + resource->mem.length; resource_hi = resource->mem.base + resource->mem.length;
record_lo = record->mem.base; record_lo = record->mem.base;
record_hi = record->mem.base + record->mem.length; record_hi = record->mem.base + record->mem.length;
if (resource->mem.rwx_attributes if (resource->mem.rwx_attributes != record->mem.rwx_attributes) {
!= record->mem.rwx_attributes) { if ((resource_lo == record_lo) && (resource_hi == record_hi)) {
if ((resource_lo == record_lo) record->mem.rwx_attributes = resource->mem.rwx_attributes
&& (resource_hi == record_hi)) {
record->mem.rwx_attributes =
resource->mem.rwx_attributes
| record->mem.rwx_attributes; | record->mem.rwx_attributes;
return true; return true;
} else { } else {
@ -153,38 +149,30 @@ static bool handle_single_resource(STM_RSC *resource, STM_RSC *record)
case IO_RANGE: case IO_RANGE:
case TRAPPED_IO_RANGE: case TRAPPED_IO_RANGE:
resource_lo = (uint64_t)resource->io.base; resource_lo = (uint64_t)resource->io.base;
resource_hi = (uint64_t)resource->io.base resource_hi = (uint64_t)resource->io.base + (uint64_t)resource->io.length;
+ (uint64_t)resource->io.length;
record_lo = (uint64_t)record->io.base; record_lo = (uint64_t)record->io.base;
record_hi = record_hi = (uint64_t)record->io.base + (uint64_t)record->io.length;
(uint64_t)record->io.base + (uint64_t)record->io.length;
break; break;
case PCI_CFG_RANGE: case PCI_CFG_RANGE:
if ((resource->pci_cfg.originating_bus_number if ((resource->pci_cfg.originating_bus_number
!= record->pci_cfg.originating_bus_number) != record->pci_cfg.originating_bus_number)
|| (resource->pci_cfg.last_node_index || (resource->pci_cfg.last_node_index != record->pci_cfg.last_node_index))
!= record->pci_cfg.last_node_index))
return false; return false;
if (memcmp(resource->pci_cfg.pci_device_path, if (memcmp(resource->pci_cfg.pci_device_path, record->pci_cfg.pci_device_path,
record->pci_cfg.pci_device_path,
sizeof(STM_PCI_DEVICE_PATH_NODE) sizeof(STM_PCI_DEVICE_PATH_NODE)
* (resource->pci_cfg.last_node_index + 1)) * (resource->pci_cfg.last_node_index + 1))
!= 0) { != 0) {
return false; return false;
} }
resource_lo = (uint64_t)resource->pci_cfg.base; resource_lo = (uint64_t)resource->pci_cfg.base;
resource_hi = (uint64_t)resource->pci_cfg.base resource_hi =
+ (uint64_t)resource->pci_cfg.length; (uint64_t)resource->pci_cfg.base + (uint64_t)resource->pci_cfg.length;
record_lo = (uint64_t)record->pci_cfg.base; record_lo = (uint64_t)record->pci_cfg.base;
record_hi = (uint64_t)record->pci_cfg.base record_hi = (uint64_t)record->pci_cfg.base + (uint64_t)record->pci_cfg.length;
+ (uint64_t)record->pci_cfg.length; if (resource->pci_cfg.rw_attributes != record->pci_cfg.rw_attributes) {
if (resource->pci_cfg.rw_attributes if ((resource_lo == record_lo) && (resource_hi == record_hi)) {
!= record->pci_cfg.rw_attributes) { record->pci_cfg.rw_attributes = resource->pci_cfg.rw_attributes
if ((resource_lo == record_lo)
&& (resource_hi == record_hi)) {
record->pci_cfg.rw_attributes =
resource->pci_cfg.rw_attributes
| record->pci_cfg.rw_attributes; | record->pci_cfg.rw_attributes;
return true; return true;
} else { } else {
@ -256,8 +244,7 @@ static void add_single_resource(STM_RSC *resource)
// Go to next record if resource and record types don't match. // Go to next record if resource and record types don't match.
if (resource->header.rsc_type != record->header.rsc_type) { if (resource->header.rsc_type != record->header.rsc_type) {
record = (STM_RSC *)((void *)record record = (STM_RSC *)((void *)record + record->header.length);
+ record->header.length);
continue; continue;
} }
@ -268,15 +255,13 @@ static void add_single_resource(STM_RSC *resource)
} }
// Add resource to the end of area. // Add resource to the end of area.
memcpy(m_stm_resources_ptr + m_stm_resource_size_used memcpy(m_stm_resources_ptr + m_stm_resource_size_used - sizeof(m_rsc_end_node),
- sizeof(m_rsc_end_node),
resource, resource->header.length); resource, resource->header.length);
memcpy(m_stm_resources_ptr + m_stm_resource_size_used memcpy(m_stm_resources_ptr + m_stm_resource_size_used - sizeof(m_rsc_end_node)
- sizeof(m_rsc_end_node) + resource->header.length, + resource->header.length,
&m_rsc_end_node, sizeof(m_rsc_end_node)); &m_rsc_end_node, sizeof(m_rsc_end_node));
m_stm_resource_size_used += resource->header.length; m_stm_resource_size_used += resource->header.length;
m_stm_resource_size_available = m_stm_resource_size_available = m_stm_resource_total_size - m_stm_resource_size_used;
m_stm_resource_total_size - m_stm_resource_size_used;
} }
/* /*
@ -303,8 +288,7 @@ static void add_resource(STM_RSC *resource_list, uint32_t num_entries)
if (resource->header.rsc_type == END_OF_RESOURCES) if (resource->header.rsc_type == END_OF_RESOURCES)
return; return;
add_single_resource(resource); add_single_resource(resource);
resource = resource = (STM_RSC *)((void *)resource + resource->header.length);
(STM_RSC *)((void *)resource + resource->header.length);
} }
} }
@ -336,11 +320,8 @@ static bool validate_resource(STM_RSC *resource_list, uint32_t num_entries)
resource = resource_list; resource = resource_list;
for (index = 0; index < count; index++) { for (index = 0; index < count; index++) {
printk(BIOS_DEBUG, "STM: %s (%u) - RscType(%x) length(0x%x)\n", printk(BIOS_DEBUG, "STM: %s (%u) - RscType(%x) length(0x%x)\n", __func__, index,
__func__, resource->header.rsc_type, resource->header.length);
index,
resource->header.rsc_type,
resource->header.length);
// Validate resource. // Validate resource.
switch (resource->header.rsc_type) { switch (resource->header.rsc_type) {
case END_OF_RESOURCES: case END_OF_RESOURCES:
@ -360,11 +341,8 @@ static bool validate_resource(STM_RSC *resource_list, uint32_t num_entries)
case MEM_RANGE: case MEM_RANGE:
case MMIO_RANGE: case MMIO_RANGE:
printk(BIOS_DEBUG, printk(BIOS_DEBUG, "STM: %s - MEM (0x%0llx, 0x%0llx)\n", __func__,
"STM: %s - MEM (0x%0llx, 0x%0llx)\n", resource->mem.base, resource->mem.length);
__func__,
resource->mem.base,
resource->mem.length);
if (resource->header.length != sizeof(STM_RSC_MEM_DESC)) if (resource->header.length != sizeof(STM_RSC_MEM_DESC))
return false; return false;
@ -383,34 +361,26 @@ static bool validate_resource(STM_RSC *resource_list, uint32_t num_entries)
break; break;
case PCI_CFG_RANGE: case PCI_CFG_RANGE:
printk(BIOS_DEBUG, printk(BIOS_DEBUG, "STM: %s - PCI (0x%02x, 0x%08x, 0x%02x, 0x%02x)\n",
"STM: %s - PCI (0x%02x, 0x%08x, 0x%02x, 0x%02x)\n", __func__, resource->pci_cfg.originating_bus_number,
__func__,
resource->pci_cfg.originating_bus_number,
resource->pci_cfg.last_node_index, resource->pci_cfg.last_node_index,
resource->pci_cfg.pci_device_path[0].pci_device, resource->pci_cfg.pci_device_path[0].pci_device,
resource->pci_cfg.pci_device_path[0] resource->pci_cfg.pci_device_path[0].pci_function);
.pci_function);
if (resource->header.length if (resource->header.length
!= sizeof(STM_RSC_PCI_CFG_DESC) != sizeof(STM_RSC_PCI_CFG_DESC)
+ (sizeof(STM_PCI_DEVICE_PATH_NODE) + (sizeof(STM_PCI_DEVICE_PATH_NODE)
* resource->pci_cfg.last_node_index)) * resource->pci_cfg.last_node_index))
return false; return false;
for (sub_index = 0; for (sub_index = 0; sub_index <= resource->pci_cfg.last_node_index;
sub_index <= resource->pci_cfg.last_node_index;
sub_index++) { sub_index++) {
if ((resource->pci_cfg if ((resource->pci_cfg.pci_device_path[sub_index].pci_device
.pci_device_path[sub_index]
.pci_device
> 0x1F) > 0x1F)
|| (resource->pci_cfg || (resource->pci_cfg.pci_device_path[sub_index]
.pci_device_path[sub_index]
.pci_function .pci_function
> 7)) > 7))
return false; return false;
} }
if ((resource->pci_cfg.base + resource->pci_cfg.length) if ((resource->pci_cfg.base + resource->pci_cfg.length) > 0x1000)
> 0x1000)
return false; return false;
break; break;
@ -420,12 +390,11 @@ static bool validate_resource(STM_RSC *resource_list, uint32_t num_entries)
break; break;
default: default:
printk(BIOS_DEBUG, "STM: %s - Unknown RscType(%x)\n", printk(BIOS_DEBUG, "STM: %s - Unknown RscType(%x)\n", __func__,
__func__, resource->header.rsc_type); resource->header.rsc_type);
return false; return false;
} }
resource = resource = (STM_RSC *)((void *)resource + resource->header.length);
(STM_RSC *)((void *)resource + resource->header.length);
} }
return true; return true;
} }
@ -462,8 +431,7 @@ static uint32_t get_resource_size(STM_RSC *resource_list, uint32_t num_entries)
for (index = 0; index < count; index++) { for (index = 0; index < count; index++) {
if (resource->header.rsc_type == END_OF_RESOURCES) if (resource->header.rsc_type == END_OF_RESOURCES)
break; break;
resource = resource = (STM_RSC *)((void *)resource + resource->header.length);
(STM_RSC *)((void *)resource + resource->header.length);
} }
return (uint32_t)((uint32_t)resource - (uint32_t)resource_list); return (uint32_t)((uint32_t)resource - (uint32_t)resource_list);
} }
@ -490,7 +458,7 @@ int add_pi_resource(STM_RSC *resource_list, uint32_t num_entries)
return -1; // INVALID_PARAMETER; return -1; // INVALID_PARAMETER;
resource_size = get_resource_size(resource_list, num_entries); resource_size = get_resource_size(resource_list, num_entries);
printk(BIOS_DEBUG, "STM: ResourceSize - 0x%08x\n", (int) resource_size); printk(BIOS_DEBUG, "STM: ResourceSize - 0x%08x\n", (int)resource_size);
if (resource_size == 0) if (resource_size == 0)
return -1; // INVALID_PARAMETER; return -1; // INVALID_PARAMETER;
@ -501,8 +469,7 @@ int add_pi_resource(STM_RSC *resource_list, uint32_t num_entries)
m_stm_resource_total_size = CONFIG_BIOS_RESOURCE_LIST_SIZE; m_stm_resource_total_size = CONFIG_BIOS_RESOURCE_LIST_SIZE;
memset(m_stm_resources_ptr, 0, CONFIG_BIOS_RESOURCE_LIST_SIZE); memset(m_stm_resources_ptr, 0, CONFIG_BIOS_RESOURCE_LIST_SIZE);
memcpy(m_stm_resources_ptr, &m_rsc_end_node, memcpy(m_stm_resources_ptr, &m_rsc_end_node, sizeof(m_rsc_end_node));
sizeof(m_rsc_end_node));
m_stm_resource_size_used = sizeof(m_rsc_end_node); m_stm_resource_size_used = sizeof(m_rsc_end_node);
m_stm_resource_size_available = m_stm_resource_size_available =
m_stm_resource_total_size - sizeof(m_rsc_end_node); m_stm_resource_total_size - sizeof(m_rsc_end_node);
@ -543,8 +510,7 @@ int32_t delete_pi_resource(STM_RSC *resource_list, uint32_t num_entries)
// Delete all // Delete all
memcpy(m_stm_resources_ptr, &m_rsc_end_node, sizeof(m_rsc_end_node)); memcpy(m_stm_resources_ptr, &m_rsc_end_node, sizeof(m_rsc_end_node));
m_stm_resource_size_used = sizeof(m_rsc_end_node); m_stm_resource_size_used = sizeof(m_rsc_end_node);
m_stm_resource_size_available = m_stm_resource_size_available = m_stm_resource_total_size - sizeof(m_rsc_end_node);
m_stm_resource_total_size - sizeof(m_rsc_end_node);
return 0; // SUCCESS; return 0; // SUCCESS;
} }
@ -587,8 +553,8 @@ static uint32_t get_vmcs_size(void)
this_vmcs_size = msr_data64.bits.vmcs_size; this_vmcs_size = msr_data64.bits.vmcs_size;
stm_support = msr_data64.bits.stm_supported; stm_support = msr_data64.bits.stm_supported;
printk(BIOS_DEBUG, "STM: %s: Size %d StmSupport %d\n", __func__, printk(BIOS_DEBUG, "STM: %s: Size %d StmSupport %d\n", __func__, this_vmcs_size,
this_vmcs_size, stm_support); stm_support);
// VMCS require 0x1000 alignment // VMCS require 0x1000 alignment
this_vmcs_size = STM_PAGES_TO_SIZE(STM_SIZE_TO_PAGES(this_vmcs_size)); this_vmcs_size = STM_PAGES_TO_SIZE(STM_SIZE_TO_PAGES(this_vmcs_size));
@ -623,10 +589,9 @@ void stm_gen_4g_pagetable_x64(uint32_t pagetable_base)
pde++; pde++;
pagetable_base += PTP_SIZE; pagetable_base += PTP_SIZE;
for (sub_index = 0; sub_index < SIZE_4KB / sizeof(*pte); for (sub_index = 0; sub_index < SIZE_4KB / sizeof(*pte); sub_index++) {
sub_index++) { *pte = (((index << 9) + sub_index) << 21) | IA32_PG_PS | IA32_PG_RW
*pte = (((index << 9) + sub_index) << 21) | IA32_PG_PS | IA32_PG_P;
| IA32_PG_RW | IA32_PG_P;
pte++; pte++;
} }
} }
@ -650,30 +615,31 @@ bool stm_check_stm_image(void *stm_image, uint32_t stm_imagesize)
stm_header = (STM_HEADER *)stm_image; stm_header = (STM_HEADER *)stm_image;
// Get Minimal required Mseg size // Get Minimal required Mseg size
min_mseg_size = (STM_PAGES_TO_SIZE(STM_SIZE_TO_PAGES( min_mseg_size =
stm_header->sw_stm_hdr.static_image_size)) (STM_PAGES_TO_SIZE(STM_SIZE_TO_PAGES(stm_header->sw_stm_hdr.static_image_size))
+ stm_header->sw_stm_hdr.additional_dynamic_memory_size + stm_header->sw_stm_hdr.additional_dynamic_memory_size
+ (stm_header->sw_stm_hdr.per_proc_dynamic_memory_size + (stm_header->sw_stm_hdr.per_proc_dynamic_memory_size + get_vmcs_size() * 2)
+ get_vmcs_size() * 2)
* mp_state.cpu_count); * mp_state.cpu_count);
if (min_mseg_size < stm_imagesize) if (min_mseg_size < stm_imagesize)
min_mseg_size = stm_imagesize; min_mseg_size = stm_imagesize;
if (stm_header->hw_stm_hdr.cr3_offset if (stm_header->hw_stm_hdr.cr3_offset >= stm_header->sw_stm_hdr.static_image_size) {
>= stm_header->sw_stm_hdr.static_image_size) {
// We will create page table, just in case that SINIT does not // We will create page table, just in case that SINIT does not
// create it. // create it.
if (min_mseg_size < stm_header->hw_stm_hdr.cr3_offset if (min_mseg_size < stm_header->hw_stm_hdr.cr3_offset + STM_PAGES_TO_SIZE(6)) {
+ STM_PAGES_TO_SIZE(6)) { min_mseg_size =
min_mseg_size = stm_header->hw_stm_hdr.cr3_offset stm_header->hw_stm_hdr.cr3_offset + STM_PAGES_TO_SIZE(6);
+ STM_PAGES_TO_SIZE(6);
} }
} }
// Check if it exceeds MSEG size // Check if it exceeds MSEG size
if (min_mseg_size > CONFIG_MSEG_SIZE) if (min_mseg_size > CONFIG_MSEG_SIZE) {
printk(BIOS_ERR,
"STM: ERROR - Configured MSEG size 0x%x less than required MSEG size 0x%x\n",
CONFIG_MSEG_SIZE, min_mseg_size);
return false; return false;
}
return true; return true;
} }