Date: Thu, 9 Mar 2017 12:09:07 +0000 (UTC) From: Dexuan Cui <dexuan@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r314956 - head/sys/boot/efi/loader Message-ID: <201703091209.v29C97Jd029975@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dexuan Date: Thu Mar 9 12:09:07 2017 New Revision: 314956 URL: https://svnweb.freebsd.org/changeset/base/314956 Log: loader.efi: only reduce the size of the staging area on Hyper-V Doing this on physical hosts turns out to be problematic, e.g. see comment 24 and 28 in https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=211746. To fix the real underlying issue correctly & thoroughly, IMO we need a relocatable kernel, but that would require a lot of complicated long term work: https://reviews.freebsd.org/D9686?id=25414#inline-56969 For now, let's only apply efi_verify_staging_size() to VMs running on Hyper-V, and restore the old behavior on physical machines since that has been working for people for a long period of time, though that's potentially unsafe... MFC after: 2 weeks Sponsored by: Microsoft Modified: head/sys/boot/efi/loader/copy.c Modified: head/sys/boot/efi/loader/copy.c ============================================================================== --- head/sys/boot/efi/loader/copy.c Thu Mar 9 09:54:23 2017 (r314955) +++ head/sys/boot/efi/loader/copy.c Thu Mar 9 12:09:07 2017 (r314956) @@ -30,6 +30,8 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <machine/cpufunc.h> +#include <machine/specialreg.h> #include <stand.h> #include <bootstrap.h> @@ -41,6 +43,47 @@ __FBSDID("$FreeBSD$"); #if defined(__i386__) || defined(__amd64__) +/* + * The code is excerpted from sys/x86/x86/identcpu.c: identify_cpu(), + * identify_hypervisor(), and dev/hyperv/vmbus/hyperv.c: hyperv_identify(). + */ +#define CPUID_LEAF_HV_MAXLEAF 0x40000000 +#define CPUID_LEAF_HV_INTERFACE 0x40000001 +#define CPUID_LEAF_HV_FEATURES 0x40000003 +#define CPUID_LEAF_HV_LIMITS 0x40000005 +#define CPUID_HV_IFACE_HYPERV 0x31237648 /* HV#1 */ +#define CPUID_HV_MSR_HYPERCALL 0x0020 +static int running_on_hyperv(void) +{ + char hv_vendor[16]; + uint32_t regs[4]; + + do_cpuid(1, regs); + if ((regs[2] & CPUID2_HV) == 0) + return (0); + + do_cpuid(CPUID_LEAF_HV_MAXLEAF, regs); + if (regs[0] < CPUID_LEAF_HV_LIMITS) + return (0); + + ((uint32_t *)&hv_vendor)[0] = regs[1]; + ((uint32_t *)&hv_vendor)[1] = regs[2]; + ((uint32_t *)&hv_vendor)[2] = regs[3]; + hv_vendor[12] = '\0'; + if (strcmp(hv_vendor, "Microsoft Hv") != 0) + return (0); + + do_cpuid(CPUID_LEAF_HV_INTERFACE, regs); + if (regs[0] != CPUID_HV_IFACE_HYPERV) + return (0); + + do_cpuid(CPUID_LEAF_HV_FEATURES, regs); + if ((regs[0] & CPUID_HV_MSR_HYPERCALL) == 0) + return (0); + + return (1); +} + #define KERNEL_PHYSICAL_BASE (2*1024*1024) static void @@ -134,8 +177,13 @@ efi_copy_init(void) nr_pages = EFI_SIZE_TO_PAGES((EFI_STAGING_SIZE) * 1024 * 1024); #if defined(__i386__) || defined(__amd64__) - /* We'll decrease nr_pages, if it's too big. */ - efi_verify_staging_size(&nr_pages); + /* + * We'll decrease nr_pages, if it's too big. Currently we only + * apply this to FreeBSD VM running on Hyper-V. Why? Please see + * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=211746#c28 + */ + if (running_on_hyperv()) + efi_verify_staging_size(&nr_pages); /* * The staging area must reside in the the first 1GB physical
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703091209.v29C97Jd029975>