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
This commit is contained in:
parent
f621c2cd39
commit
047ff56626
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=314956
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user