@@ -677,3 +677,57 @@ bool acpi_hmat_present(void)
acpi_put_table(tbl);
return true;
}
+
+static int mktme_parse_proximity_domains(union acpi_subtable_headers *header,
+ const unsigned long end)
+{
+ struct acpi_hmat_proximity_domain *mar = (void *)header;
+ struct acpi_hmat_structure *hdr = (void *)header;
+
+ const struct cpumask *tmp_mask;
+
+ if (!hdr || hdr->type != ACPI_HMAT_TYPE_PROXIMITY)
+ return -EINVAL;
+
+ if (mar->header.length != sizeof(*mar)) {
+ pr_warn("MKTME: invalid header length in HMAT\n");
+ return -1;
+ }
+ /*
+ * Require a valid processor proximity domain.
+ * This will catch memory only physical packages with
+ * no processor capable of programming the key table.
+ */
+ if (!(mar->flags & ACPI_HMAT_PROCESSOR_PD_VALID)) {
+ pr_warn("MKTME: no valid processor proximity domain\n");
+ return -1;
+ }
+ /* Require an online CPU in the processor proximity domain. */
+ tmp_mask = cpumask_of_node(pxm_to_node(mar->processor_PD));
+ if (!cpumask_intersects(tmp_mask, cpu_online_mask)) {
+ pr_warn("MKTME: no online CPU in proximity domain\n");
+ return -1;
+ }
+ return 0;
+}
+
+/* Returns true if topology is safe for MKTME key creation */
+bool mktme_hmat_evaluate(void)
+{
+ struct acpi_table_header *tbl;
+ bool ret = true;
+ acpi_status status;
+
+ status = acpi_get_table(ACPI_SIG_HMAT, 0, &tbl);
+ if (ACPI_FAILURE(status))
+ return -EINVAL;
+
+ if (acpi_table_parse_entries(ACPI_SIG_HMAT,
+ sizeof(struct acpi_table_hmat),
+ ACPI_HMAT_TYPE_PROXIMITY,
+ mktme_parse_proximity_domains, 0) < 0) {
+ ret = false;
+ }
+ acpi_put_table(tbl);
+ return ret;
+}
@@ -1337,6 +1337,7 @@ acpi_platform_notify(struct device *dev, enum kobject_action action)
#ifdef CONFIG_X86_INTEL_MKTME
extern bool acpi_hmat_present(void);
+extern bool mktme_hmat_evaluate(void);
#endif /* CONFIG_X86_INTEL_MKTME */
#endif /*_LINUX_ACPI_H*/