From: Ross Philipson Date: Wed, 4 Feb 2009 16:11:34 +0000 (-0500) Subject: tboot patch 3/5 - protect TXT ranges X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=b6c256305fadd6b514e51b1f47f2e8dbcf8e4cdc;p=xenclient%2Fxen.git tboot patch 3/5 - protect TXT ranges tboot no longer marks the TXT heap/SINIT/private config space as E820_UNUSABLE in the e820 table, so Xen must mark them so (to disallow them from dom0). Changes to be committed: modified: xen/arch/x86/e820.c modified: xen/arch/x86/setup.c modified: xen/arch/x86/tboot.c modified: xen/include/asm-x86/e820.h modified: xen/include/asm-x86/tboot.h --- diff --git a/xen/arch/x86/e820.c b/xen/arch/x86/e820.c index 8b79c5e..e884c4f 100644 --- a/xen/arch/x86/e820.c +++ b/xen/arch/x86/e820.c @@ -391,11 +391,14 @@ static void __init machine_specific_memory_setup( reserve_dmi_region(); } -/* Reserve RAM area (@s,@e) in the specified e820 map. */ -int __init reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e) +static int reserve_e820(struct e820map *e820, uint64_t s, uint64_t e, + uint32_t orig_type, uint32_t new_type) { uint64_t rs = 0, re = 0; - int i; + int i, remove; + + /* if reserving region, can delete instead */ + remove = (new_type == E820_RESERVED); for ( i = 0; i < e820->nr_map; i++ ) { @@ -406,37 +409,89 @@ int __init reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e) break; } - if ( (i == e820->nr_map) || (e820->map[i].type != E820_RAM) ) + if ( (i == e820->nr_map) || (e820->map[i].type != orig_type) ) return 0; if ( (s == rs) && (e == re) ) { /* Complete excision. */ - memmove(&e820->map[i], &e820->map[i+1], - (e820->nr_map-i-1) * sizeof(e820->map[0])); - e820->nr_map--; + if ( remove ) + { + memmove(&e820->map[i], &e820->map[i+1], + (e820->nr_map-i-1) * sizeof(e820->map[0])); + e820->nr_map--; + } + else + e820->map[i].type = new_type; } else if ( s == rs ) { - /* Truncate start. */ + /* Truncate start or split. */ + if ( !remove ) + { + /* split */ + if ( e820->nr_map+1 > ARRAY_SIZE(e820->map) ) + { + printk("e820 overflow\n"); + return 0; + } + memmove(&e820->map[i+1], &e820->map[i], + (e820->nr_map-i) * sizeof(e820->map[0])); + e820->nr_map++; + e820->map[i].addr = s; + e820->map[i].size = e - s; + e820->map[i].type = new_type; + i++; + } e820->map[i].addr += e - s; e820->map[i].size -= e - s; } else if ( e == re ) { - /* Truncate end. */ + /* Truncate end or split. */ + if ( !remove ) + { + if ( e820->nr_map+1 > ARRAY_SIZE(e820->map) ) + { + printk("e820 overflow\n"); + return 0; + } + memmove(&e820->map[i+1], &e820->map[i], + (e820->nr_map-i) * sizeof(e820->map[0])); + e820->nr_map++; + e820->map[i+1].addr = s; + e820->map[i+1].size = e - s; + e820->map[i+1].type = new_type; + } e820->map[i].size -= e - s; } - else if ( e820->nr_map < ARRAY_SIZE(e820->map) ) + else if ( e820->nr_map+1 < ARRAY_SIZE(e820->map) ) { - /* Split in two. */ - memmove(&e820->map[i+1], &e820->map[i], - (e820->nr_map-i) * sizeof(e820->map[0])); - e820->nr_map++; - e820->map[i].size = s - rs; - i++; - e820->map[i].addr = e; - e820->map[i].size = re - e; + /* Split in two or three. */ + if ( !remove ) + { + memmove(&e820->map[i+2], &e820->map[i], + (e820->nr_map-i) * sizeof(e820->map[0])); + e820->nr_map += 2; + e820->map[i].size = s - rs; + i++; + e820->map[i].addr = s; + e820->map[i].size = e - s; + e820->map[i].type = new_type; + i++; + e820->map[i].addr = e; + e820->map[i].size = re - e; + } + else + { + memmove(&e820->map[i+1], &e820->map[i], + (e820->nr_map-i) * sizeof(e820->map[0])); + e820->nr_map++; + e820->map[i].size = s - rs; + i++; + e820->map[i].addr = e; + e820->map[i].size = re - e; + } } else { @@ -457,6 +512,18 @@ int __init reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e) return 1; } +/* Set E820_RAM area (@s,@e) as RESERVED (or delete) in specified e820 map. */ +int __init reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e) +{ + return reserve_e820(e820, s, e, E820_RAM, E820_RESERVED); +} + +/* Set E820_RESERVED area (@s, @e) as UNUSABLE in specified e820 map. */ +int reserve_e820_unusable(struct e820map *e820, uint64_t s, uint64_t e) +{ + return reserve_e820(e820, s, e, E820_RESERVED, E820_UNUSABLE); +} + unsigned long __init init_e820( const char *str, struct e820entry *raw, int *raw_nr) { diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 6c039b0..b8694e8 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -1047,6 +1047,9 @@ void __init __start_xen(unsigned long mbi_p) if ( xen_cpuidle ) xen_processor_pmbits |= XEN_PROCESSOR_PM_CX; + if ( !tboot_protect_mem_regions() ) + panic("Could not protect TXT memory regions\n"); + /* * We're going to setup domain0 using the module(s) that we stashed safely * above our heap. The second module, if present, is an initrd ramdisk. diff --git a/xen/arch/x86/tboot.c b/xen/arch/x86/tboot.c index 9e14196..603f330 100644 --- a/xen/arch/x86/tboot.c +++ b/xen/arch/x86/tboot.c @@ -6,6 +6,7 @@ #include #include #include +#include #include /* tboot= */ @@ -17,6 +18,23 @@ tboot_shared_t *g_tboot_shared; static const uuid_t tboot_shared_uuid = TBOOT_SHARED_UUID; +/* + * TXT configuration registers (offsets from TXT_{PUB, PRIV}_CONFIG_REGS_BASE) + */ + +#define TXT_PUB_CONFIG_REGS_BASE 0xfed30000 +#define TXT_PRIV_CONFIG_REGS_BASE 0xfed20000 + +/* # pages for each config regs space - used by fixmap */ +#define NR_TXT_CONFIG_PAGES ((TXT_PUB_CONFIG_REGS_BASE - \ + TXT_PRIV_CONFIG_REGS_BASE) >> PAGE_SHIFT) + +/* offsets from pub/priv config space */ +#define TXTCR_SINIT_BASE 0x0270 +#define TXTCR_SINIT_SIZE 0x0278 +#define TXTCR_HEAP_BASE 0x0300 +#define TXTCR_HEAP_SIZE 0x0308 + void __init tboot_probe(void) { tboot_shared_t *tboot_shared; @@ -84,6 +102,44 @@ int tboot_in_measured_env(void) return (g_tboot_shared != NULL); } +int tboot_protect_mem_regions(void) +{ + uint64_t base, size; + uint32_t map_base, map_size; + unsigned long map_addr; + + if ( !tboot_in_measured_env() ) + return 1; + + map_base = PFN_DOWN(TXT_PUB_CONFIG_REGS_BASE); + map_size = PFN_UP(NR_TXT_CONFIG_PAGES * PAGE_SIZE); + map_addr = (unsigned long)__va(map_base << PAGE_SHIFT); + if ( map_pages_to_xen(map_addr, map_base, map_size, __PAGE_HYPERVISOR) ) + return 0; + + /* TXT Heap */ + base = *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_HEAP_BASE); + size = *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_HEAP_SIZE); + if ( !reserve_e820_unusable(&e820, base, base + size) ) + return 0; + + /* SINIT */ + base = *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_SINIT_BASE); + size = *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_SINIT_SIZE); + if ( !reserve_e820_unusable(&e820, base, base + size) ) + return 0; + + /* TXT Private Space */ + if ( !reserve_e820_unusable(&e820, TXT_PRIV_CONFIG_REGS_BASE, + TXT_PRIV_CONFIG_REGS_BASE + NR_TXT_CONFIG_PAGES * PAGE_SIZE) ) + return 0; + + destroy_xen_mappings((unsigned long)__va(map_base << PAGE_SHIFT), + (unsigned long)__va((map_base + map_size) << PAGE_SHIFT)); + + return 1; +} + /* * Local variables: * mode: C diff --git a/xen/include/asm-x86/e820.h b/xen/include/asm-x86/e820.h index 8602ca8..1fba42f 100644 --- a/xen/include/asm-x86/e820.h +++ b/xen/include/asm-x86/e820.h @@ -24,6 +24,7 @@ struct e820map { }; extern int reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e); +extern int reserve_e820_unusable(struct e820map *e820, uint64_t s, uint64_t e); extern unsigned long init_e820(const char *, struct e820entry *, int *); extern struct e820map e820; diff --git a/xen/include/asm-x86/tboot.h b/xen/include/asm-x86/tboot.h index 07ee9a7..65a9cfe 100644 --- a/xen/include/asm-x86/tboot.h +++ b/xen/include/asm-x86/tboot.h @@ -100,6 +100,7 @@ extern tboot_shared_t *g_tboot_shared; void tboot_probe(void); void tboot_shutdown(uint32_t shutdown_type); int tboot_in_measured_env(void); +int tboot_protect_mem_regions(void); #endif /* __TBOOT_H__ */