inteltool: Add support to print TME/MKTME status

Print whether the SOC supports TME/MKTME. If the SOC supports the
feature, print the status of enable and lock bit from TME_ACTIVATE
MSR. -t option prints this status.

Sample output:

If TME/MKTME is supported:
============= Dumping INTEL TME/MKTME status =============
TME supported : YES
TME locked    : YES
TME enabled   : YES
====================================================

If TME/MKTME is not supported:
============= Dumping INTEL TME status =============
TME supported : NO
====================================================

Signed-off-by: Pratik Prajapati <pratikkumar.v.prajapati@intel.com>
Change-Id: I584ac4b045ba80998d454283e02d3f28ef45692d
Reviewed-on: https://review.coreboot.org/c/coreboot/+/45088
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
diff --git a/util/inteltool/cpu.c b/util/inteltool/cpu.c
index 284e90b..db63d36 100644
--- a/util/inteltool/cpu.c
+++ b/util/inteltool/cpu.c
@@ -22,6 +22,10 @@
 #define MTRR_CAP_MSR		0xfe
 #define PRMRR_SUPPORTED		(1 << 12)
 #define SGX_SUPPORTED		(1 << 2)
+#define IA32_TME_ACTIVATE	0x982
+#define TME_SUPPORTED		(1 << 13)
+#define TME_LOCKED		(1)
+#define TME_ENABLED		(1 << 1)
 
 int fd_msr;
 
@@ -212,6 +216,55 @@
 	return error;
 }
 
+static int is_tme_supported()
+{
+	cpuid_result_t cpuid_regs;
+
+	/*
+	 * CPUID leaf 0x7 subleaf 0x0 to detect TME support
+	 * https://software.intel.com/sites/default/files/managed/a5/16/Multi-Key
+	 * -Total-Memory-Encryption-Spec.pdf
+	 */
+
+	cpuid_regs = cpuid_ext(0x7, 0x0);
+        return (cpuid_regs.ecx & TME_SUPPORTED);
+}
+
+static msr_t read_tme_activate_msr(){
+	return rdmsr_from_cpu(0, IA32_TME_ACTIVATE);
+}
+
+static int is_tme_locked()
+{
+	msr_t data = read_tme_activate_msr();
+	return (data.lo & TME_LOCKED);
+}
+
+static int is_tme_enabled()
+{
+	msr_t data = read_tme_activate_msr();
+	return (data.lo & TME_ENABLED);
+}
+
+void print_tme(void)
+{
+#ifndef __DARWIN__
+	int tme_supported = is_tme_supported();
+
+	printf("\n============= Dumping INTEL TME status =============\n");
+
+	printf("TME supported : %s\n", tme_supported ? "YES" : "NO");
+
+	if (tme_supported) {
+		printf("TME locked    : %s\n", is_tme_locked() ? "YES" : "NO");
+		printf("TME enabled   : %s\n", is_tme_enabled() ? "YES" : "NO");
+	}
+	printf("====================================================\n");
+#else
+	printf("Not Implemented\n");
+#endif
+}
+
 int print_intel_core_msrs(void)
 {
 	unsigned int i, core, id, core_num = get_number_of_cores();
diff --git a/util/inteltool/inteltool.c b/util/inteltool/inteltool.c
index 5ecd8ca..d7415b0 100644
--- a/util/inteltool/inteltool.c
+++ b/util/inteltool/inteltool.c
@@ -515,6 +515,7 @@
 	     "   -M | --msrs:                      dump CPU MSRs\n"
 	     "   -A | --ambs:                      dump AMB registers\n"
 	     "   -x | --sgx:                       dump SGX status\n"
+	     "   -t | --tme:                       dump TME status\n"
 	     "   -a | --all:                       dump all known (safe) registers\n"
 	     "        --pcr=PORT_ID:               dump all registers of a PCR port\n"
 	     "                                     (may be specified max %d times)\n"
@@ -575,7 +576,7 @@
 	int dump_gpios = 0, dump_mchbar = 0, dump_rcba = 0;
 	int dump_pmbase = 0, dump_epbar = 0, dump_dmibar = 0;
 	int dump_pciexbar = 0, dump_coremsrs = 0, dump_ambs = 0;
-	int dump_spi = 0, dump_gfx = 0, dump_ahci = 0, dump_sgx = 0;
+	int dump_spi = 0, dump_gfx = 0, dump_ahci = 0, dump_sgx = 0, dump_tme = 0;
 	int dump_lpc = 0;
 	int show_gpio_diffs = 0;
 	size_t pcr_count = 0;
@@ -602,10 +603,11 @@
 		{"ahci", 0, 0, 'R'},
 		{"sgx", 0, 0, 'x'},
 		{"pcr", required_argument, 0, LONG_OPT_PCR},
+		{"tme", 0, 0, 't'},
 		{0, 0, 0, 0}
 	};
 
-	while ((opt = getopt_long(argc, argv, "vh?gGrplmedPMaAsfRS:x",
+	while ((opt = getopt_long(argc, argv, "vh?gGrplmedPMaAsfRS:xt",
                                   long_options, &option_index)) != EOF) {
 		switch (opt) {
 		case 'v':
@@ -667,6 +669,7 @@
 			dump_spi = 1;
 			dump_ahci = 1;
 			dump_sgx = 1;
+			dump_tme = 1;
 			break;
 		case 'A':
 			dump_ambs = 1;
@@ -677,6 +680,9 @@
 		case 'x':
 			dump_sgx = 1;
 			break;
+		case 't':
+			dump_tme = 1;
+			break;
 		case LONG_OPT_PCR:
 			if (pcr_count < MAX_PCR_PORTS) {
 				errno = 0;
@@ -869,6 +875,9 @@
 	if (dump_sgx)
 		print_sgx();
 
+	if (dump_tme)
+		print_tme();
+
 	if (pcr_count)
 		print_pcr_ports(sb, dump_pcr, pcr_count);
 
diff --git a/util/inteltool/inteltool.h b/util/inteltool/inteltool.h
index b3253e7..a528485 100644
--- a/util/inteltool/inteltool.h
+++ b/util/inteltool/inteltool.h
@@ -411,6 +411,7 @@
 int print_gfx(struct pci_dev *gfx);
 int print_ahci(struct pci_dev *ahci);
 int print_sgx(void);
+void print_tme(void);
 void ivybridge_dump_timings(const char *dump_spd_file);
 
 #endif