From owner-svn-src-head@freebsd.org Thu Mar 9 12:09:08 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id ED635D04A63; Thu, 9 Mar 2017 12:09:08 +0000 (UTC) (envelope-from dexuan@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id AF9DD131B; Thu, 9 Mar 2017 12:09:08 +0000 (UTC) (envelope-from dexuan@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v29C97Ia029976; Thu, 9 Mar 2017 12:09:07 GMT (envelope-from dexuan@FreeBSD.org) Received: (from dexuan@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v29C97Jd029975; Thu, 9 Mar 2017 12:09:07 GMT (envelope-from dexuan@FreeBSD.org) Message-Id: <201703091209.v29C97Jd029975@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: dexuan set sender to dexuan@FreeBSD.org using -f From: Dexuan Cui Date: Thu, 9 Mar 2017 12:09:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r314956 - head/sys/boot/efi/loader X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Mar 2017 12:09:09 -0000 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 +#include +#include #include #include @@ -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