2008-10-07 20:35:23

by Joseph Cihula

[permalink] [raw]
Subject: [RFC][PATCH 3/3] TXT: Intel(R) TXT and tboot kernel support

Linux kernel changes to support tboot and Intel TXT.

Signed-off-by: Shane Wang <[email protected]>
Signed-off-by: Joseph Cihula <[email protected]>
Signed-off-by: Gang Wei <[email protected]>


Attachments:
txt-linux-tboot.patch (18.06 kB)
txt-linux-tboot.patch

2008-10-07 21:06:47

by James Morris

[permalink] [raw]
Subject: Re: [RFC][PATCH 3/3] TXT: Intel(R) TXT and tboot kernel support

On Tue, 7 Oct 2008, Cihula, Joseph wrote:

> Content-Type: application/octet-stream;

Please include your patches as inline text and not as attachments, so
people can review and respond.

See Documentation/SubmittingPatches in the kernel tree.


- James
--
James Morris
<[email protected]>

2008-10-07 21:10:46

by Joseph Cihula

[permalink] [raw]
Subject: RE: [RFC][PATCH 3/3] TXT: Intel(R) TXT and tboot kernel support

(large) Patch inline below (and still attached for those who prefer it).

Linux kernel changes to support tboot and Intel TXT.

Signed-off-by: Shane Wang <[email protected]>
Signed-off-by: Joseph Cihula <[email protected]>
Signed-off-by: Gang Wei <[email protected]>

diff -r 29cfdc52a076 arch/x86/configs/i386_defconfig
--- a/arch/x86/configs/i386_defconfig Mon Oct 06 12:50:47 2008 -0700
+++ b/arch/x86/configs/i386_defconfig Tue Oct 07 00:13:02 2008 -0700
@@ -54,6 +54,7 @@ CONFIG_X86_TRAMPOLINE=y
CONFIG_X86_TRAMPOLINE=y
CONFIG_KTIME_SCALAR=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+# CONFIG_TXT is not set

#
# General setup
diff -r 29cfdc52a076 arch/x86/configs/x86_64_defconfig
--- a/arch/x86/configs/x86_64_defconfig Mon Oct 06 12:50:47 2008 -0700
+++ b/arch/x86/configs/x86_64_defconfig Tue Oct 07 00:13:02 2008 -0700
@@ -54,6 +54,7 @@ CONFIG_X86_TRAMPOLINE=y
CONFIG_X86_TRAMPOLINE=y
# CONFIG_KTIME_SCALAR is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+# CONFIG_TXT is not set

#
# General setup
diff -r 29cfdc52a076 arch/x86/kernel/Makefile
--- a/arch/x86/kernel/Makefile Mon Oct 06 12:50:47 2008 -0700
+++ b/arch/x86/kernel/Makefile Tue Oct 07 00:13:02 2008 -0700
@@ -44,6 +44,7 @@ obj-$(CONFIG_X86_32) += tls.o
obj-$(CONFIG_X86_32) += tls.o
obj-$(CONFIG_IA32_EMULATION) += tls.o
obj-y += step.o
+obj-$(CONFIG_TXT) += tboot.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += cpu/
obj-y += acpi/
diff -r 29cfdc52a076 arch/x86/kernel/reboot.c
--- a/arch/x86/kernel/reboot.c Mon Oct 06 12:50:47 2008 -0700
+++ b/arch/x86/kernel/reboot.c Tue Oct 07 00:13:02 2008 -0700
@@ -20,6 +20,8 @@
#else
# include <asm/iommu.h>
#endif
+
+#include <asm/tboot.h>

/*
* Power off function, if any
@@ -456,11 +458,13 @@ static void native_machine_restart(char

if (!reboot_force)
machine_shutdown();
+ tboot_shutdown(TB_SHUTDOWN_REBOOT);
machine_emergency_restart();
}

static void native_machine_halt(void)
{
+ tboot_shutdown(TB_SHUTDOWN_HALT);
}

static void native_machine_power_off(void)
@@ -470,6 +474,8 @@ static void native_machine_power_off(voi
machine_shutdown();
pm_power_off();
}
+ /* a fallback in case there is no PM info available */
+ tboot_shutdown(TB_SHUTDOWN_HALT);
}

struct machine_ops machine_ops = {
diff -r 29cfdc52a076 arch/x86/kernel/setup.c
--- a/arch/x86/kernel/setup.c Mon Oct 06 12:50:47 2008 -0700
+++ b/arch/x86/kernel/setup.c Tue Oct 07 00:13:02 2008 -0700
@@ -115,6 +115,8 @@ struct boot_params __initdata boot_param
#else
struct boot_params boot_params;
#endif
+
+#include <asm/tboot.h>

/*
* Machine setup..
@@ -833,6 +835,8 @@ void __init setup_arch(char **cmdline_p)
paravirt_pagetable_setup_done(swapper_pg_dir);
paravirt_post_allocator_init();

+ tboot_probe();
+
#ifdef CONFIG_X86_64
map_vsyscall();
#endif
diff -r 29cfdc52a076 arch/x86/kernel/tboot.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/x86/kernel/tboot.c Tue Oct 07 00:13:02 2008 -0700
@@ -0,0 +1,258 @@
+/*
+ * tboot.c: main implementation of helper functions used by kernel for
+ * runtime support
+ *
+ * Copyright (c) 2006-2008, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but
WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/pfn.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/bootparam.h>
+#include <asm/tboot.h>
+
+/* Global pointer to shared data; NULL means no measured launch. */
+struct tboot_shared *tboot_shared;
+
+void __init tboot_probe(void)
+{
+ extern struct boot_params boot_params;
+
+ /* Look for valid page-aligned address for shared page. */
+ if (boot_params.hdr.tboot_shared_addr == 0)
+ return;
+
+ /* Map and check for tboot UUID. */
+ set_fixmap(FIX_TBOOT_SHARED_BASE,
boot_params.hdr.tboot_shared_addr);
+ tboot_shared = (struct tboot_shared *)
+ fix_to_virt(FIX_TBOOT_SHARED_BASE);
+ if (memcmp(&TBOOT_SHARED_UUID, &tboot_shared->uuid,
+ sizeof(struct tboot_uuid))) {
+ printk(KERN_WARNING "tboot_shared at %lxP/%pV is
invalid\n",
+ (unsigned long)boot_params.hdr.tboot_shared_addr,
+ tboot_shared);
+ tboot_shared = NULL;
+ return;
+ }
+ if (tboot_shared->version < 2) {
+ printk(KERN_WARNING "tboot_shared version is invalid:
%d\n",
+ tboot_shared->version);
+ tboot_shared = NULL;
+ return;
+ }
+
+ printk(KERN_INFO "TBOOT: found shared page at phys addr
0x%lx:\n",
+ (unsigned long)boot_params.hdr.tboot_shared_addr);
+ printk(KERN_DEBUG " version: %d\n", tboot_shared->version);
+ printk(KERN_DEBUG " log_addr: 0x%08x\n",
tboot_shared->log_addr);
+ printk(KERN_DEBUG " shutdown_entry32: 0x%08x\n",
+ tboot_shared->shutdown_entry32);
+ printk(KERN_DEBUG " shutdown_entry64: 0x%08x\n",
+ tboot_shared->shutdown_entry64);
+ printk(KERN_DEBUG " shutdown_type: %d\n",
tboot_shared->shutdown_type);
+ printk(KERN_DEBUG " s3_tb_wakeup_entry: 0x%08x\n",
+ tboot_shared->s3_tb_wakeup_entry);
+ printk(KERN_DEBUG " s3_k_wakeup_entry: 0x%08x\n",
+ tboot_shared->s3_k_wakeup_entry);
+ printk(KERN_DEBUG " &acpi_sinfo: 0x%p\n",
&tboot_shared->acpi_sinfo);
+ printk(KERN_DEBUG " tboot_base: 0x%08x\n",
tboot_shared->tboot_base);
+ printk(KERN_DEBUG " tboot_size: 0x%x\n",
tboot_shared->tboot_size);
+}
+
+static pgd_t *tboot_pg_dir;
+static inline void switch_to_tboot_pt(void)
+{
+ native_write_cr3(__pa(tboot_pg_dir));
+}
+
+struct tboot_pgt_struct {
+ unsigned long ptr;
+ struct tboot_pgt_struct *next;
+};
+static struct tboot_pgt_struct *tboot_pgt;
+
+/* Allocate (and save for later release) a page */
+static unsigned long alloc_tboot_page(void)
+{
+ unsigned long ptr;
+ struct tboot_pgt_struct *pgt;
+
+ ptr = get_zeroed_page(GFP_ATOMIC);
+ if (ptr) {
+ pgt = kmalloc(sizeof(*pgt), GFP_ATOMIC);
+ if (!pgt) {
+ free_page(ptr);
+ return 0;
+ }
+ pgt->ptr = ptr;
+ pgt->next = tboot_pgt;
+ tboot_pgt = pgt;
+ }
+ return ptr;
+}
+
+/* Clean up memory used for tboot mapping */
+void clean_up_tboot_mapping(void)
+{
+ struct tboot_pgt_struct *pgt;
+
+ if (!tboot_in_measured_env())
+ return;
+
+ pgt = tboot_pgt;
+ while (pgt) {
+ free_page(pgt->ptr);
+ tboot_pgt = pgt->next;
+ kfree(pgt);
+ pgt = tboot_pgt;
+ }
+}
+
+static int map_page_for_tboot(unsigned long vaddr, unsigned long pfn,
+ pgprot_t prot)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte, new_pte;
+
+ pgd = tboot_pg_dir + pgd_index(vaddr);
+#ifdef __x86_64__
+ if (!pgd_val(*pgd)) {
+ pud = (pud_t *)alloc_tboot_page();
+ if (!pud)
+ return -1;
+ set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
+ }
+ pud = pud_offset(pgd, vaddr);
+ if (!pud_val(*pud)) {
+ pmd = (pmd_t *)alloc_tboot_page();
+ if (!pmd)
+ return -1;
+ set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
+ }
+ pmd = pmd_offset(pud, vaddr);
+#else
+#ifdef CONFIG_X86_PAE
+ if (!pgd_val(*pgd)) {
+ pmd = (pmd_t *)alloc_tboot_page();
+ if (!pmd)
+ return -1;
+ set_pgd(pgd, __pgd(__pa(pmd) | _PAGE_PRESENT));
+ pud = pud_offset(pgd, 0);
+ }
+ pud = pud_offset(pgd, 0);
+ pmd = pmd_offset(pud, vaddr);
+#else
+ pud = pud_offset(pgd, 0);
+ pmd = pmd_offset(pud, 0);
+#endif
+#endif
+ if (!pmd_val(*pmd)) {
+ pte = (pte_t *)alloc_tboot_page();
+ if (!pte)
+ return -1;
+ set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE));
+ }
+ new_pte = pfn_pte(pfn, prot);
+
+ pte = pte_offset_kernel(pmd, vaddr);
+
+ if (pte_val(*pte) &&
+#if defined(CONFIG_X86_PAE) || defined(__x86_64__)
+ pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask)
+#else
+ pte_val(*pte) != pte_val(new_pte)
+#endif
+ ) {
+ pte_ERROR(*pte);
+ return -1;
+ }
+
+ set_pte(pte, new_pte);
+
+ return 0;
+}
+
+static int map_pages_for_tboot(unsigned long vaddr, unsigned long
start_pfn,
+ unsigned long nr)
+{
+ printk(KERN_DEBUG "map_pages_for_tboot %lx to %lx (%lx)\n",
+ vaddr, start_pfn << PAGE_SHIFT, nr << PAGE_SHIFT);
+
+ /* Reuse the original kernel mapping */
+ tboot_pg_dir = (pgd_t *)alloc_tboot_page();
+ if (!tboot_pg_dir)
+ return -1;
+
+#ifdef __x86_64__
+ set_pgd(tboot_pg_dir + pgd_index(__START_KERNEL_map),
+ swapper_pg_dir[pgd_index(__START_KERNEL_map)]);
+#else
+ memcpy(tboot_pg_dir + KERNEL_PGD_BOUNDARY,
+ swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+ sizeof(swapper_pg_dir[0]) * KERNEL_PGD_PTRS);
+#endif
+
+ for (; nr > 0; nr--, vaddr += PAGE_SIZE, start_pfn++) {
+ if (map_page_for_tboot(vaddr, start_pfn,
+ __pgprot(__PAGE_KERNEL_EXEC)))
+ return -1;
+ }
+
+ return 0;
+}
+
+void tboot_shutdown(u32 shutdown_type)
+{
+ u32 map_base, map_size;
+
+ if (!tboot_in_measured_env())
+ return;
+
+ tboot_shared->shutdown_type = shutdown_type;
+
+ local_irq_disable();
+
+ /* Create identity map for tboot shutdown code. */
+ if (tboot_shared->version >= 0x02) {
+ map_base = PFN_DOWN(tboot_shared->tboot_base);
+ map_size = PFN_UP(tboot_shared->tboot_size);
+ } else {
+ map_base = 0;
+ map_size = PFN_UP(0xa0000);
+ }
+
+ if (map_pages_for_tboot(map_base << PAGE_SHIFT, map_base,
map_size)) {
+ printk(KERN_DEBUG "error mapping tboot pages "
+ "(mfns) @ 0x%x, 0x%x\n", map_base,
map_size);
+ clean_up_tboot_mapping();
+ return;
+ }
+
+ switch_to_tboot_pt();
+
+#ifdef __x86_64__
+ asm volatile ("jmp *%%rdi" : : "D"
(tboot_shared->shutdown_entry64));
+#else
+ asm volatile ("jmp *%%edi" : : "D"
(tboot_shared->shutdown_entry32));
+#endif
+
+ BUG(); /* should not reach here */
+}
diff -r 29cfdc52a076 arch/x86/power/cpu_32.c
--- a/arch/x86/power/cpu_32.c Mon Oct 06 12:50:47 2008 -0700
+++ b/arch/x86/power/cpu_32.c Tue Oct 07 00:13:02 2008 -0700
@@ -11,6 +11,7 @@
#include <linux/suspend.h>
#include <asm/mtrr.h>
#include <asm/mce.h>
+#include <asm/tboot.h>

static struct saved_context saved_context;

@@ -136,5 +137,8 @@ void restore_processor_state(void)
void restore_processor_state(void)
{
__restore_processor_state(&saved_context);
+
+ /* Clean up memory mapping for tboot range */
+ clean_up_tboot_mapping();
}
EXPORT_SYMBOL(restore_processor_state);
diff -r 29cfdc52a076 arch/x86/power/cpu_64.c
--- a/arch/x86/power/cpu_64.c Mon Oct 06 12:50:47 2008 -0700
+++ b/arch/x86/power/cpu_64.c Tue Oct 07 00:13:02 2008 -0700
@@ -14,6 +14,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/mtrr.h>
+#include <asm/tboot.h>

static void fix_processor_context(void);

@@ -131,6 +132,9 @@ void restore_processor_state(void)
void restore_processor_state(void)
{
__restore_processor_state(&saved_context);
+
+ /* Clean up memory mapping for tboot range */
+ clean_up_tboot_mapping();
}

static void fix_processor_context(void)
diff -r 29cfdc52a076 drivers/acpi/hardware/hwsleep.c
--- a/drivers/acpi/hardware/hwsleep.c Mon Oct 06 12:50:47 2008 -0700
+++ b/drivers/acpi/hardware/hwsleep.c Tue Oct 07 00:13:02 2008 -0700
@@ -44,6 +44,7 @@

#include <acpi/acpi.h>
#include <acpi/actables.h>
+#include <asm/tboot.h>

#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwsleep")
@@ -77,6 +78,13 @@ acpi_set_firmware_waking_vector(acpi_phy
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
+
+#ifdef CONFIG_TXT
+ if (tboot_in_measured_env()) {
+ tboot_shared->s3_k_wakeup_entry =
(uint32_t)physical_address;
+ physical_address = tboot_shared->s3_tb_wakeup_entry;
+ }
+#endif

/* Set the vector */

@@ -238,6 +246,29 @@ acpi_status acpi_enter_sleep_state_prep(

ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)

+#ifdef CONFIG_TXT
+static void tboot_sleep(u8 sleep_state)
+{
+ uint32_t shutdown_type;
+
+ switch (sleep_state) {
+ case ACPI_STATE_S3:
+ shutdown_type = TB_SHUTDOWN_S3;
+ break;
+ case ACPI_STATE_S4:
+ shutdown_type = TB_SHUTDOWN_S4;
+ break;
+ case ACPI_STATE_S5:
+ shutdown_type = TB_SHUTDOWN_S5;
+ break;
+ default:
+ return;
+ }
+
+ tboot_shutdown(shutdown_type);
+}
+#endif
+

/***********************************************************************
********
*
* FUNCTION: acpi_enter_sleep_state
@@ -361,6 +392,20 @@ acpi_status asmlinkage acpi_enter_sleep_

PM1Acontrol |= sleep_enable_reg_info->access_bit_mask;
PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask;
+
+#ifdef CONFIG_TXT
+ if (tboot_in_measured_env()) {
+ tboot_shared->acpi_sinfo.pm1a_cnt =
+
(uint16_t)acpi_gbl_FADT.xpm1a_control_block.address;
+ tboot_shared->acpi_sinfo.pm1b_cnt =
+
(uint16_t)acpi_gbl_FADT.xpm1b_control_block.address;
+ tboot_shared->acpi_sinfo.pm1a_cnt_val = PM1Acontrol;
+ tboot_shared->acpi_sinfo.pm1b_cnt_val = PM1Bcontrol;
+ tboot_sleep(sleep_state);
+ printk(KERN_DEBUG "TBOOT failed entering s3 state\n");
+ return_ACPI_STATUS(AE_ERROR);
+ }
+#endif

/* Write #2: SLP_TYP + SLP_EN */

diff -r 29cfdc52a076 include/asm-x86/bootparam.h
--- a/include/asm-x86/bootparam.h Mon Oct 06 12:50:47 2008 -0700
+++ b/include/asm-x86/bootparam.h Tue Oct 07 00:13:02 2008 -0700
@@ -62,6 +62,7 @@ struct setup_header {
__u32 payload_offset;
__u32 payload_length;
__u64 setup_data;
+ __u32 tboot_shared_addr;
} __attribute__((packed));

struct sys_desc_table {
diff -r 29cfdc52a076 include/asm-x86/fixmap_32.h
--- a/include/asm-x86/fixmap_32.h Mon Oct 06 12:50:47 2008 -0700
+++ b/include/asm-x86/fixmap_32.h Tue Oct 07 00:13:02 2008 -0700
@@ -85,6 +85,9 @@ enum fixed_addresses {
#ifdef CONFIG_PARAVIRT
FIX_PARAVIRT_BOOTMAP,
#endif
+#ifdef CONFIG_TXT
+ FIX_TBOOT_SHARED_BASE,
+#endif
__end_of_permanent_fixed_addresses,
/*
* 256 temporary boot-time mappings, used by early_ioremap(),
diff -r 29cfdc52a076 include/asm-x86/fixmap_64.h
--- a/include/asm-x86/fixmap_64.h Mon Oct 06 12:50:47 2008 -0700
+++ b/include/asm-x86/fixmap_64.h Tue Oct 07 00:13:02 2008 -0700
@@ -56,6 +56,9 @@ enum fixed_addresses {
#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
FIX_OHCI1394_BASE,
#endif
+#ifdef CONFIG_TXT
+ FIX_TBOOT_SHARED_BASE,
+#endif
__end_of_permanent_fixed_addresses,
/*
* 256 temporary boot-time mappings, used by early_ioremap(),
diff -r 29cfdc52a076 include/asm-x86/tboot.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/asm-x86/tboot.h Tue Oct 07 00:13:02 2008 -0700
@@ -0,0 +1,101 @@
+/*
+ * tboot.h: shared data structure with MLE and kernel and functions
+ * used by kernel for runtime support
+ *
+ * Copyright (c) 2006-2008, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but
WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _ASM_TBOOT_H
+#define _ASM_TBOOT_H
+
+#define TB_SHUTDOWN_REBOOT 0
+#define TB_SHUTDOWN_S5 1
+#define TB_SHUTDOWN_S4 2
+#define TB_SHUTDOWN_S3 3
+#define TB_SHUTDOWN_HALT 4
+
+#ifdef CONFIG_TXT
+struct tboot_uuid {
+ u32 data1;
+ u16 data2;
+ u16 data3;
+ u16 data4;
+ u8 data5[6];
+} __attribute__ ((__packed__));
+
+/* used to communicate between tboot and the launched kernel */
+
+struct tboot_acpi_sleep_info {
+ u16 pm1a_cnt;
+ u16 pm1b_cnt;
+ u16 pm1a_evt;
+ u16 pm1b_evt;
+ u16 pm1a_cnt_val;
+ u16 pm1b_cnt_val;
+} __attribute__ ((__packed__));
+
+struct tboot_shared {
+ /* version 0x01+ fields: */
+ struct tboot_uuid uuid; /* TBOOT_SHARED_UUID */
+ u32 version; /* Version number: 2 is current */
+ u32 log_addr; /* physical addr of tb_log_t log */
+ u32 shutdown_entry32; /* entry point for tboot shutdown from
32b */
+ u32 shutdown_entry64; /* entry point for tboot shutdown from
64b */
+ u32 shutdown_type; /* type of shutdown (TB_SHUTDOWN_*) */
+ u32 s3_tb_wakeup_entry;/* entry point for tboot s3 wake up */
+ u32 s3_k_wakeup_entry; /* entry point for kernel s3 wake up */
+ struct tboot_acpi_sleep_info
+ acpi_sinfo; /* where kernel put acpi sleep info in
Sx */
+ u8 reserved[52]; /* this pad is for compat with old field
*/
+ /* version 0x02+ fields: */
+ u32 tboot_base; /* starting addr for tboot */
+ u32 tboot_size; /* size of tboot */
+} __attribute__ ((__packed__));
+
+/* {663C8DFF-E8B3-4b82-AABF-19EA4D057A08} */
+#define TBOOT_SHARED_UUID \
+ ((struct tboot_uuid){ 0x663c8dff, 0xe8b3, 0x4b82,
0xaabf, \
+ { 0x19, 0xea, 0x4d, 0x5, 0x7a, 0x8 } })
+
+extern struct tboot_shared *tboot_shared;
+
+static inline int tboot_in_measured_env(void)
+{
+ return tboot_shared != NULL;
+}
+
+extern void clean_up_tboot_mapping(void);
+extern void tboot_probe(void);
+extern void tboot_shutdown(u32 shutdown_type);
+
+#else /* CONFIG_TXT */
+
+static inline void clean_up_tboot_mapping(void)
+{
+}
+
+static inline void tboot_probe(void)
+{
+}
+
+static inline void tboot_shutdown(u32 shutdown_type)
+{
+}
+
+#endif /* !CONFIG_TXT */
+
+#endif /* _ASM_TBOOT_H */
diff -r 29cfdc52a076 security/Kconfig
--- a/security/Kconfig Mon Oct 06 12:50:47 2008 -0700
+++ b/security/Kconfig Tue Oct 07 00:13:02 2008 -0700
@@ -115,6 +115,23 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
/proc/sys/vm/mmap_min_addr tunable.


+config TXT
+ bool "Enable Intel(R) Trusted Execution Technology (TXT)"
+ depends on EXPERIMENTAL && X86
+ help
+ This option enables support for booting the kernel with
+ the Trusted Boot (tboot) module. This will utilize
+ Intel(R) Trusted Execution Technology (TXT) to perform a
+ measured launch of the kernel. If the system does not
+ support TXT, this will have no effect.
+
+ See <http://www.intel.com/technology/security/> for more
+ information about Intel(R) TXT.
+ And see <http://tboot.sourceforge.net> for more information
+ about tboot.
+
+ If you are unsure as to whether this is required, answer N.
+
source security/selinux/Kconfig
source security/smack/Kconfig


Attachments:
txt-linux-tboot.patch (18.06 kB)
txt-linux-tboot.patch

2008-10-07 21:46:42

by James Morris

[permalink] [raw]
Subject: RE: [RFC][PATCH 3/3] TXT: Intel(R) TXT and tboot kernel support

On Tue, 7 Oct 2008, Cihula, Joseph wrote:

> (large) Patch inline below (and still attached for those who prefer it).

It's now wordwrapped, and the other patches don't appear to have been
resent at all.

Here's the appropriate section from SubmittingPatches. Note the section
on configuring your mailer.

----

7) No MIME, no links, no compression, no attachments. Just plain text.

Linus and other kernel developers need to be able to read and comment
on the changes you are submitting. It is important for a kernel
developer to be able to "quote" your changes, using standard e-mail
tools, so that they may comment on specific portions of your code.

For this reason, all patches should be submitting e-mail "inline".
WARNING: Be wary of your editor's word-wrap corrupting your patch,
if you choose to cut-n-paste your patch.

Do not attach the patch as a MIME attachment, compressed or not.
Many popular e-mail applications will not always transmit a MIME
attachment as plain text, making it impossible to comment on your
code. A MIME attachment also takes Linus a bit more time to process,
decreasing the likelihood of your MIME-attached change being accepted.

Exception: If your mailer is mangling patches then someone may ask
you to re-send them using MIME.

See Documentation/email-clients.txt for hints about configuring
your e-mail client so that it sends your patches untouched.

----


--
James Morris
<[email protected]>

2008-10-08 00:52:53

by Andi Kleen

[permalink] [raw]
Subject: Re: [RFC][PATCH 3/3] TXT: Intel(R) TXT and tboot kernel support

"Cihula, Joseph" <[email protected]> writes:

Quick review, not very deep (as in just Linux interfaces not design)

> @@ -0,0 +1,258 @@
> +/*
> + * tboot.c: main implementation of helper functions used by kernel for
> + * runtime support

This description is not very helpful for someone who doesn't know
what tboot is.

There should be at least a short paragraph here describing what it is
Better more.

> + extern struct boot_params boot_params;

That should be in some include

> + printk(KERN_INFO "TBOOT: found shared page at phys addr 0x%lx:\n",
> + (unsigned long)boot_params.hdr.tboot_shared_addr);
> + printk(KERN_DEBUG " version: %d\n", tboot_shared->version);
> + printk(KERN_DEBUG " log_addr: 0x%08x\n", tboot_shared->log_addr);
> + printk(KERN_DEBUG " shutdown_entry32: 0x%08x\n",
> + tboot_shared->shutdown_entry32);
> + printk(KERN_DEBUG " shutdown_entry64: 0x%08x\n",
> + tboot_shared->shutdown_entry64);
> + printk(KERN_DEBUG " shutdown_type: %d\n", tboot_shared->shutdown_type);
> + printk(KERN_DEBUG " s3_tb_wakeup_entry: 0x%08x\n",
> + tboot_shared->s3_tb_wakeup_entry);
> + printk(KERN_DEBUG " s3_k_wakeup_entry: 0x%08x\n",
> + tboot_shared->s3_k_wakeup_entry);
> + printk(KERN_DEBUG " &acpi_sinfo: 0x%p\n", &tboot_shared->acpi_sinfo);
> + printk(KERN_DEBUG " tboot_base: 0x%08x\n", tboot_shared->tboot_base);
> + printk(KERN_DEBUG " tboot_size: 0x%x\n", tboot_shared->tboot_size);

Having that much debug output by default is not nice.

> +}
> +
> +static pgd_t *tboot_pg_dir;
> +static inline void switch_to_tboot_pt(void)
> +{
> + native_write_cr3(__pa(tboot_pg_dir));
> +}
> +
> +struct tboot_pgt_struct {
> + unsigned long ptr;
> + struct tboot_pgt_struct *next;
> +};
> +static struct tboot_pgt_struct *tboot_pgt;
> +
> +/* Allocate (and save for later release) a page */
> +static unsigned long alloc_tboot_page(void)

Passing pointers around as unsigned long is not nice.

> +{
> + unsigned long ptr;
> + struct tboot_pgt_struct *pgt;
> +
> + ptr = get_zeroed_page(GFP_ATOMIC);

In general GFP_ATOMIC is nasty and should be avoided if possible.

> + if (ptr) {
> + pgt = kmalloc(sizeof(*pgt), GFP_ATOMIC);
> + if (!pgt) {
> + free_page(ptr);
> + return 0;
> + }
> + pgt->ptr = ptr;
> + pgt->next = tboot_pgt;
> + tboot_pgt = pgt;

Instead of allocating something here you could just use
the list_head in struct page

> + pgd = tboot_pg_dir + pgd_index(vaddr);
> +#ifdef __x86_64__

Is there any reason you cannot use the generic pgalloc.h allocators?
Is it only for tracking the pages? Why not track it using
the page tables? Or insert it into the list (if you really
need one, i'm not sure what the list is actually good for)
based on the page tables after the fact.

That would avoid the ifdefery and clean this function up
greatly.
> +
> + /* Create identity map for tboot shutdown code. */
> + if (tboot_shared->version >= 0x02) {
> + map_base = PFN_DOWN(tboot_shared->tboot_base);
> + map_size = PFN_UP(tboot_shared->tboot_size);
> + } else {
> + map_base = 0;
> + map_size = PFN_UP(0xa0000);

Avoid magic numbers like this.

> + }
> +
> + if (map_pages_for_tboot(map_base << PAGE_SHIFT, map_base, map_size)) {
> + printk(KERN_DEBUG "error mapping tboot pages "
> + "(mfns) @ 0x%x, 0x%x\n", map_base, map_size);
> + clean_up_tboot_mapping();
> + return;
> + }
> +
> + switch_to_tboot_pt();
> +
> +#ifdef __x86_64__
> + asm volatile ("jmp *%%rdi" : : "D" (tboot_shared->shutdown_entry64));
> +#else
> + asm volatile ("jmp *%%edi" : : "D" (tboot_shared->shutdown_entry32));
> +#endif

Why not just use a C indirect function call?

> +#ifdef CONFIG_TXT
> +static void tboot_sleep(u8 sleep_state)
> +{
> + uint32_t shutdown_type;
> +
> + switch (sleep_state) {
> + case ACPI_STATE_S3:
> + shutdown_type = TB_SHUTDOWN_S3;
> + break;
> + case ACPI_STATE_S4:
> + shutdown_type = TB_SHUTDOWN_S4;
> + break;
> + case ACPI_STATE_S5:
> + shutdown_type = TB_SHUTDOWN_S5;
> + break;

This could be much shorter with just an array lookup

> + default:
> + return;
> + }
> +
> + tboot_shutdown(shutdown_type);
> +}
> +#endif
> +
> /*******************************************************************************
> *
> * FUNCTION: acpi_enter_sleep_state
> @@ -361,6 +392,20 @@ acpi_status asmlinkage acpi_enter_sleep_
>
> PM1Acontrol |= sleep_enable_reg_info->access_bit_mask;
> PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask;
> +
> +#ifdef CONFIG_TXT
> + if (tboot_in_measured_env()) {
> + tboot_shared->acpi_sinfo.pm1a_cnt =
> + (uint16_t)acpi_gbl_FADT.xpm1a_control_block.address;
> + tboot_shared->acpi_sinfo.pm1b_cnt =
> + (uint16_t)acpi_gbl_FADT.xpm1b_control_block.address;

Why are the addresses truncated to 16bit?

> + tboot_shared->acpi_sinfo.pm1a_cnt_val = PM1Acontrol;
> + tboot_shared->acpi_sinfo.pm1b_cnt_val = PM1Bcontrol;
> + tboot_sleep(sleep_state);
> + printk(KERN_DEBUG "TBOOT failed entering s3 state\n");

That should not be KERN_DEBUG

> +
> +#define TB_SHUTDOWN_REBOOT 0
> +#define TB_SHUTDOWN_S5 1
> +#define TB_SHUTDOWN_S4 2
> +#define TB_SHUTDOWN_S3 3
> +#define TB_SHUTDOWN_HALT 4

If you use the same values as ACPI you perhaps
don't even need a lookup table above.


> +/* {663C8DFF-E8B3-4b82-AABF-19EA4D057A08} */
> +#define TBOOT_SHARED_UUID \
> + ((struct tboot_uuid){ 0x663c8dff, 0xe8b3, 0x4b82, 0xaabf, \
> + { 0x19, 0xea, 0x4d, 0x5, 0x7a, 0x8 } })

Some comment where this magic number comes from?


-Andi
--
[email protected]

2008-10-09 13:05:43

by Pavel Machek

[permalink] [raw]
Subject: Re: [RFC][PATCH 3/3] TXT: Intel(R) TXT and tboot kernel support

Hi!

> (large) Patch inline below (and still attached for those who prefer it).
>
> Linux kernel changes to support tboot and Intel TXT.

Please pick a better acronym. TXT is already taken.

> +struct tboot_acpi_sleep_info {
> + u16 pm1a_cnt;
> + u16 pm1b_cnt;
> + u16 pm1a_evt;
> + u16 pm1b_evt;
> + u16 pm1a_cnt_val;
> + u16 pm1b_cnt_val;
> +} __attribute__ ((__packed__));
> +
> +struct tboot_shared {
> + /* version 0x01+ fields: */
> + struct tboot_uuid uuid; /* TBOOT_SHARED_UUID */
> + u32 version; /* Version number: 2 is current */
> + u32 log_addr; /* physical addr of tb_log_t log */
> + u32 shutdown_entry32; /* entry point for tboot shutdown from
> 32b */
> + u32 shutdown_entry64; /* entry point for tboot shutdown from
> 64b */

should these be function pointers?

> + u32 shutdown_type; /* type of shutdown (TB_SHUTDOWN_*) */
> + u32 s3_tb_wakeup_entry;/* entry point for tboot s3 wake up */
> + u32 s3_k_wakeup_entry; /* entry point for kernel s3 wake up */
> + struct tboot_acpi_sleep_info
> + acpi_sinfo; /* where kernel put acpi sleep info in
> Sx */
> + u8 reserved[52]; /* this pad is for compat with old field
> */
> + /* version 0x02+ fields: */
> + u32 tboot_base; /* starting addr for tboot */
> + u32 tboot_size; /* size of tboot */
> +} __attribute__ ((__packed__));
> +
> +/* {663C8DFF-E8B3-4b82-AABF-19EA4D057A08} */
> +#define TBOOT_SHARED_UUID \
> + ((struct tboot_uuid){ 0x663c8dff, 0xe8b3, 0x4b82,
> 0xaabf, \
> + { 0x19, 0xea, 0x4d, 0x5, 0x7a, 0x8 } })

Can we use normal magic number like rest of kernel does?
Pavel

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2008-10-09 17:25:24

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: Re: [RFC][PATCH 3/3] TXT: Intel(R) TXT and tboot kernel support

Cihula, Joseph wrote:
> --- a/security/Kconfig Mon Oct 06 12:50:47 2008 -0700
> +++ b/security/Kconfig Tue Oct 07 00:13:02 2008 -0700
> @@ -115,6 +115,23 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
> /proc/sys/vm/mmap_min_addr tunable.
>
>
> +config TXT
>

This should be X86_TXT; perhaps even X86_INTEL_TXT unless someone else
is likely to implement this stuff. ("TXT" is awfully generic.)


> + bool "Enable Intel(R) Trusted Execution Technology (TXT)"
> + depends on EXPERIMENTAL && X86
> + help
> + This option enables support for booting the kernel with
> + the Trusted Boot (tboot) module. This will utilize
> + Intel(R) Trusted Execution Technology (TXT) to perform a
> + measured launch of the kernel. If the system does not
> + support TXT, this will have no effect.
> +
> + See <http://www.intel.com/technology/security/> for more
> + information about Intel(R) TXT.
> + And see <http://tboot.sourceforge.net> for more information
> + about tboot.
> +
> + If you are unsure as to whether this is required, answer N.
> +
> source security/selinux/Kconfig
> source security/smack/Kconfig
>

J

2008-10-09 17:51:16

by Chris Wright

[permalink] [raw]
Subject: Re: [RFC][PATCH 3/3] TXT: Intel(R) TXT and tboot kernel support

* Pavel Machek ([email protected]) wrote:
> > +struct tboot_acpi_sleep_info {
> > + u16 pm1a_cnt;
> > + u16 pm1b_cnt;
> > + u16 pm1a_evt;
> > + u16 pm1b_evt;
> > + u16 pm1a_cnt_val;
> > + u16 pm1b_cnt_val;
> > +} __attribute__ ((__packed__));
> > +
> > +struct tboot_shared {
> > + /* version 0x01+ fields: */
> > + struct tboot_uuid uuid; /* TBOOT_SHARED_UUID */
> > + u32 version; /* Version number: 2 is current */
> > + u32 log_addr; /* physical addr of tb_log_t log */
> > + u32 shutdown_entry32; /* entry point for tboot shutdown from
> > 32b */
> > + u32 shutdown_entry64; /* entry point for tboot shutdown from
> > 64b */
>
> should these be function pointers?

I asked earlier, I didn't understand why it needs to be 2 fields, since
it's u32 in both cases and can't both be used at once.

2008-10-09 18:29:17

by Chris Wright

[permalink] [raw]
Subject: Re: [RFC][PATCH 3/3] TXT: Intel(R) TXT and tboot kernel support

* Jeremy Fitzhardinge ([email protected]) wrote:
> Cihula, Joseph wrote:
>> --- a/security/Kconfig Mon Oct 06 12:50:47 2008 -0700
>> +++ b/security/Kconfig Tue Oct 07 00:13:02 2008 -0700
>> @@ -115,6 +115,23 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
>> /proc/sys/vm/mmap_min_addr tunable.
>> +config TXT
>
> This should be X86_TXT; perhaps even X86_INTEL_TXT unless someone else
> is likely to implement this stuff. ("TXT" is awfully generic.)

config NOTEPAD_EXE? (sorry, couldn't resist ;-)

Is there anything for ia64?

2008-10-09 18:40:03

by Joseph Cihula

[permalink] [raw]
Subject: RE: [RFC][PATCH 3/3] TXT: Intel(R) TXT and tboot kernel support

> From: Chris Wright [mailto:[email protected]]
> Sent: Thursday, October 09, 2008 11:28 AM
>
> * Jeremy Fitzhardinge ([email protected]) wrote:
> > Cihula, Joseph wrote:
> >> --- a/security/Kconfig Mon Oct 06 12:50:47 2008 -0700
> >> +++ b/security/Kconfig Tue Oct 07 00:13:02 2008 -0700
> >> @@ -115,6 +115,23 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
> >> /proc/sys/vm/mmap_min_addr tunable.
> >> +config TXT
> >
> > This should be X86_TXT; perhaps even X86_INTEL_TXT unless someone
else
> > is likely to implement this stuff. ("TXT" is awfully generic.)
>
> config NOTEPAD_EXE? (sorry, couldn't resist ;-)

Nobody in Linux-land uses the .txt file extension, so no conflicts,
right ;-)

We'll add some prefix for the next version, as Jeremy suggests.

> Is there anything for ia64?

Not at this time, but we're taking requests ;-)

Joe

2008-10-09 20:37:08

by Joseph Cihula

[permalink] [raw]
Subject: RE: [RFC][PATCH 3/3] TXT: Intel(R) TXT and tboot kernel support

> From: Chris Wright [mailto:[email protected]]
> Sent: Thursday, October 09, 2008 10:50 AM
>
> * Pavel Machek ([email protected]) wrote:
> > > +struct tboot_acpi_sleep_info {
> > > + u16 pm1a_cnt;
> > > + u16 pm1b_cnt;
> > > + u16 pm1a_evt;
> > > + u16 pm1b_evt;
> > > + u16 pm1a_cnt_val;
> > > + u16 pm1b_cnt_val;
> > > +} __attribute__ ((__packed__));
> > > +
> > > +struct tboot_shared {
> > > + /* version 0x01+ fields: */
> > > + struct tboot_uuid uuid; /* TBOOT_SHARED_UUID */
> > > + u32 version; /* Version number: 2 is current */
> > > + u32 log_addr; /* physical addr of tb_log_t log */
> > > + u32 shutdown_entry32; /* entry point for tboot shutdown from
> > > 32b */
> > > + u32 shutdown_entry64; /* entry point for tboot shutdown from
> > > 64b */
> >
> > should these be function pointers?

Function ptrs don't work for an ABI since they are different sizes for
32b and 64b binaries.

> I asked earlier, I didn't understand why it needs to be 2 fields,
since
> it's u32 in both cases and can't both be used at once.

We will look at seeing if we can make a single entry point that detects
if it was called by 64b code, disable IA32e mode, and then jumps to the
32b code. We did it this way initially because it was easier code to
keep them separate and has been working for some time. We'll also have
to adjust Xen if/when we do this.

Joe

2008-10-09 21:35:50

by Chris Wright

[permalink] [raw]
Subject: Re: [RFC][PATCH 3/3] TXT: Intel(R) TXT and tboot kernel support

* Cihula, Joseph ([email protected]) wrote:
> > From: Chris Wright [mailto:[email protected]]
> > I asked earlier, I didn't understand why it needs to be 2 fields, since
> > it's u32 in both cases and can't both be used at once.
>
> We will look at seeing if we can make a single entry point that detects
> if it was called by 64b code, disable IA32e mode, and then jumps to the
> 32b code.

Yeah, that's exactly what I was thinking. I assumed I missed a piece...

> We did it this way initially because it was easier code to
> keep them separate and has been working for some time. We'll also have
> to adjust Xen if/when we do this.

...which is just this ease of implementation, thanks.

thanks,
-chris