From: Keir Fraser Date: Mon, 26 May 2008 07:24:55 +0000 (+0100) Subject: VT-d: remove Xen and tboot range from dom0's VT-d table X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14207^2~36 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=7fefb0d6ae2b0949523e2933ac59d363450a9543;p=xen.git VT-d: remove Xen and tboot range from dom0's VT-d table This a step forward to fix the security hole introduced by dom0's 1:1 mapping VT-d table: remove the critical code and data from it. The more flexible solution is to update dom0's VT-d table on demand as what will be done for other PV domains. However, there could bring a performance issue even with software optimization. Iotlb flush of some hardware is time-consuming. Signed-off-by: Yang, Xiaowei --- diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index bdf3866e01..94504c5561 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -1100,6 +1100,14 @@ void arch_get_xen_caps(xen_capabilities_info_t *info) #endif } +int xen_in_range(unsigned long start, unsigned long end) +{ + start = max_t(unsigned long, start, xenheap_phys_start); + end = min_t(unsigned long, end, xenheap_phys_end); + + return start < end; +} + /* * Local variables: * mode: C diff --git a/xen/arch/x86/tboot.c b/xen/arch/x86/tboot.c index 697ca9f461..37841c41fa 100644 --- a/xen/arch/x86/tboot.c +++ b/xen/arch/x86/tboot.c @@ -96,6 +96,18 @@ int tboot_in_measured_env(void) return (g_tboot_shared != NULL); } +int tboot_in_range(unsigned long start, unsigned long end) +{ + if ( g_tboot_shared == NULL || g_tboot_shared->version < 0x02 ) + return 0; + + start = max_t(unsigned long, start, g_tboot_shared->tboot_base); + end = min_t(unsigned long, end, + g_tboot_shared->tboot_base + g_tboot_shared->tboot_size); + + return start < end; +} + /* * Local variables: * mode: C diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index 0e5186e255..1c831279ba 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -1097,9 +1097,21 @@ static int intel_iommu_domain_init(struct domain *d) if ( d->domain_id == 0 ) { - /* Set up 1:1 page table for dom0. */ + extern int xen_in_range(unsigned long start, unsigned long end); + extern int tboot_in_range(unsigned long start, unsigned long end); + + /* + * Set up 1:1 page table for dom0 except the critical segments + * like Xen and tboot. + */ for ( i = 0; i < max_page; i++ ) + { + if ( xen_in_range(i << PAGE_SHIFT_4K, (i + 1) << PAGE_SHIFT_4K) || + tboot_in_range(i << PAGE_SHIFT_4K, (i + 1) << PAGE_SHIFT_4K) ) + continue; + iommu_map_page(d, i, i); + } setup_dom0_devices(d); setup_dom0_rmrr(d);