Skip to content

Commit 4e71187

Browse files
committed
kexec: Secure Launch kexec SEXIT support
Prior to running the next kernel via kexec, the Secure Launch code closes down private SMX resources and does an SEXIT. This allows the next kernel to start normally, effectively exiting the DRTM environment. The function slaunch_finalize() takes a boolean argument that controls whether a GETSEC[SEXIT] can be issued. When true, the finalize code can completely shutdown and exit the DRTM. This allows another kernel to start normally and in turn can re-establish another DRTM session. In cases where the machine has not been fully shutdown (e.g. machione_shutdown() was not called), the SEXIT step cannot be done (SEXIT will fail if other processors are busy). In these cases SEXIT is not attempted. This normally occurs on power off or reboot operations where it doesn't really matter. Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com> Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
1 parent c9e12eb commit 4e71187

2 files changed

Lines changed: 88 additions & 0 deletions

File tree

arch/x86/kernel/slaunch.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,3 +533,83 @@ void __init slaunch_fixup_ap_wake_vector(void)
533533

534534
pr_info("TXT AP startup vector address updated\n");
535535
}
536+
537+
static inline void smx_getsec_sexit(void)
538+
{
539+
asm volatile ("getsec\n" : : "a" (SMX_X86_GETSEC_SEXIT));
540+
}
541+
542+
/*
543+
* Used during kexec and on reboot paths to finalize the TXT state
544+
* and do an SEXIT SMX operation, exiting the DRTM and disabling SMX mode.
545+
*/
546+
void slaunch_finalize(int do_sexit)
547+
{
548+
u64 one = TXT_REGVALUE_ONE, val;
549+
void __iomem *config;
550+
551+
if (!slaunch_is_txt_launch())
552+
return;
553+
554+
config = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
555+
if (!config) {
556+
pr_emerg("TXT: SEXIT failed to ioremap TXT private registers\n");
557+
return;
558+
}
559+
560+
/* Clear secrets bit for SEXIT */
561+
memcpy_toio(config + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
562+
memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
563+
564+
/* Unlock memory configurations */
565+
memcpy_toio(config + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
566+
memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
567+
568+
/* Close the TXT private register space */
569+
memcpy_toio(config + TXT_CR_CMD_CLOSE_PRIVATE, &one, sizeof(one));
570+
memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
571+
572+
/*
573+
* Calls to iounmap are skipped due to the system state this late in the
574+
* kexec process. Local IRQs are disabled and iounmap causes a TLB flush
575+
* which in turn causes a warning. Leaving these mappings is not an issue
576+
* since the next kernel is going to completely re-setup memory management.
577+
*/
578+
579+
/* Map public registers and do a final read fence */
580+
config = ioremap(TXT_PUB_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
581+
PAGE_SIZE);
582+
if (!config) {
583+
pr_emerg("TXT: SEXIT failed to ioremap TXT public registers\n");
584+
return;
585+
}
586+
587+
memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
588+
589+
pr_emerg("TXT clear secrets bit and unlock memory complete.\n");
590+
591+
/*
592+
* Mostly finalized but the system is still in SMX mode. At this point if the
593+
* system has been quiesced, the APs are halted and the current process is
594+
* running on the BSP, a final GETSEC(SEXIT) can be done exiting DRTM/SMX mode.
595+
* This cannot be done on certain boot paths where the system has not been quiesced
596+
* (e.g. where machine_shutdown() has not been called).
597+
*/
598+
if (!do_sexit)
599+
return;
600+
601+
if (smp_processor_id() != 0)
602+
panic("TXT: SEXIT must be called on CPU 0\n");
603+
604+
/*
605+
* In case SMX mode was disabled, enable it for SEXIT. Clearing the bit
606+
* anytime during DRTM operation will not have an affect until the next
607+
* GETSEC() op is performed.
608+
*/
609+
cr4_set_bits(X86_CR4_SMXE);
610+
611+
/* Do the SEXIT SMX operation */
612+
smx_getsec_sexit();
613+
614+
pr_info("TXT SEXIT complete.\n");
615+
}

kernel/kexec_core.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <linux/objtool.h>
4242
#include <linux/kmsg_dump.h>
4343
#include <linux/dma-map-ops.h>
44+
#include <linux/slaunch.h>
4445

4546
#include <asm/page.h>
4647
#include <asm/sections.h>
@@ -1196,6 +1197,13 @@ int kernel_kexec(void)
11961197
cpu_hotplug_enable();
11971198
pr_notice("Starting new kernel\n");
11981199
machine_shutdown();
1200+
1201+
/*
1202+
* If a Secure Launch is in progress and the current kernel is
1203+
* running as a DRTM with TXT, finalize the Secure Launch state
1204+
* and do the GETSEC(SEXIT) returning from SMX mode to do the KEXEC.
1205+
*/
1206+
slaunch_finalize(1);
11991207
}
12001208

12011209
kmsg_dump(KMSG_DUMP_SHUTDOWN);

0 commit comments

Comments
 (0)