Date: Tue, 13 Mar 2018 17:10:52 +0000 (UTC) From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r330868 - in head: stand/efi/loader sys/amd64/amd64 sys/arm64/arm64 Message-ID: <201803131710.w2DHAq4s026325@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kevans Date: Tue Mar 13 17:10:52 2018 New Revision: 330868 URL: https://svnweb.freebsd.org/changeset/base/330868 Log: EFIRT: SetVirtualAddressMap with 1:1 mapping after exiting boot services This fixes a problem encountered on the Lenovo Thinkpad X220/Yoga 11e where runtime services would try to inexplicably jump to other parts of memory where it shouldn't be when attempting to enumerate EFI vars, causing a panic. The virtual mapping is enabled by default and can be disabled by setting efi_disable_vmap in loader.conf(5). Reviewed by: kib (earlier version) MFC after: 3 weeks Differential Revision: https://reviews.freebsd.org/D14677 Modified: head/stand/efi/loader/bootinfo.c head/sys/amd64/amd64/efirt_machdep.c head/sys/arm64/arm64/efirt_machdep.c Modified: head/stand/efi/loader/bootinfo.c ============================================================================== --- head/stand/efi/loader/bootinfo.c Tue Mar 13 17:04:14 2018 (r330867) +++ head/stand/efi/loader/bootinfo.c Tue Mar 13 17:10:52 2018 (r330868) @@ -236,17 +236,48 @@ bi_copymodules(vm_offset_t addr) return(addr); } +static EFI_STATUS +efi_do_vmap(EFI_MEMORY_DESCRIPTOR *mm, UINTN sz, UINTN mmsz, UINT32 mmver) +{ + EFI_MEMORY_DESCRIPTOR *desc, *viter, *vmap; + EFI_STATUS ret; + int curr, ndesc, nset; + + nset = 0; + desc = mm; + ndesc = sz / mmsz; + vmap = malloc(sz); + if (vmap == NULL) + /* This isn't really an EFI error case, but pretend it is */ + return (EFI_OUT_OF_RESOURCES); + viter = vmap; + for (curr = 0; curr < ndesc; + curr++, desc = NextMemoryDescriptor(desc, mmsz)) { + if ((desc->Attribute & EFI_MEMORY_RUNTIME) != 0) { + ++nset; + desc->VirtualStart = desc->PhysicalStart; + *viter = *desc; + viter = NextMemoryDescriptor(viter, mmsz); + } + } + ret = RS->SetVirtualAddressMap(nset * mmsz, mmsz, mmver, vmap); + free(vmap); + return (ret); +} + static int bi_load_efi_data(struct preloaded_file *kfp) { EFI_MEMORY_DESCRIPTOR *mm; EFI_PHYSICAL_ADDRESS addr; EFI_STATUS status; + const char *efi_novmap; size_t efisz; UINTN efi_mapkey; UINTN mmsz, pages, retry, sz; UINT32 mmver; struct efi_map_header *efihdr; + bool do_vmap; #if defined(__amd64__) || defined(__aarch64__) struct efi_fb efifb; @@ -266,6 +297,11 @@ bi_load_efi_data(struct preloaded_file *kfp) } #endif + do_vmap = true; + efi_novmap = getenv("efi_disable_vmap"); + if (efi_novmap != NULL) + do_vmap = strcasecmp(efi_novmap, "YES") != 0; + efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf; /* @@ -321,6 +357,13 @@ bi_load_efi_data(struct preloaded_file *kfp) } status = BS->ExitBootServices(IH, efi_mapkey); if (EFI_ERROR(status) == 0) { + /* + * This may be disabled by setting efi_disable_vmap in + * loader.conf(5). By default we will setup the virtual + * map entries. + */ + if (do_vmap) + efi_do_vmap(mm, sz, mmsz, mmver); efihdr->memory_size = sz; efihdr->descriptor_size = mmsz; efihdr->descriptor_version = mmver; Modified: head/sys/amd64/amd64/efirt_machdep.c ============================================================================== --- head/sys/amd64/amd64/efirt_machdep.c Tue Mar 13 17:04:14 2018 (r330867) +++ head/sys/amd64/amd64/efirt_machdep.c Tue Mar 13 17:10:52 2018 (r330868) @@ -165,7 +165,7 @@ efi_create_1t1_map(struct efi_md *map, int ndesc, int descsz)) { if ((p->md_attr & EFI_MD_ATTR_RT) == 0) continue; - if (p->md_virt != NULL) { + if (p->md_virt != NULL && (uint64_t)p->md_virt != p->md_phys) { if (bootverbose) printf("EFI Runtime entry %d is mapped\n", i); goto fail; Modified: head/sys/arm64/arm64/efirt_machdep.c ============================================================================== --- head/sys/arm64/arm64/efirt_machdep.c Tue Mar 13 17:04:14 2018 (r330867) +++ head/sys/arm64/arm64/efirt_machdep.c Tue Mar 13 17:10:52 2018 (r330868) @@ -169,7 +169,7 @@ efi_create_1t1_map(struct efi_md *map, int ndesc, int descsz)) { if ((p->md_attr & EFI_MD_ATTR_RT) == 0) continue; - if (p->md_virt != NULL) { + if (p->md_virt != NULL && (uint64_t)p->md_virt != p->md_phys) { if (bootverbose) printf("EFI Runtime entry %d is mapped\n", i); goto fail;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803131710.w2DHAq4s026325>