Add the advisories to go with the updates.

Approved by:	so
This commit is contained in:
Gordon Tetlow 2019-11-12 18:48:44 +00:00
parent 15e75c5b82
commit eccf9265a4
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=53592
11 changed files with 1204 additions and 0 deletions

View file

@ -0,0 +1,133 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
=============================================================================
FreeBSD-EN-19:19.loader Errata Notice
The FreeBSD Project
Topic: UEFI Loader Memory Fragmentation
Category: core
Module: loader
Announced: 2019-11-12
Credits: Rebecca Cran
Affects: FreeBSD 12.0 and later
Corrected: 2019-09-27 05:12:28 UTC (stable/12, 12.1-STABLE)
2019-11-12 18:10:26 UTC (releng/12.1, 12.1-RELEASE-p1)
2019-11-12 18:10:26 UTC (releng/12.0, 12.0-RELEASE-p12)
For general information regarding FreeBSD Errata Notices and Security
Advisories, including descriptions of the fields above, security
branches, and the following sections, please visit
<URL:https://security.FreeBSD.org/>.
I. Background
Prior to executing the kernel, the UEFI loader must obtain the final memory
map from the firmware and pass it to the kernel for consumption.
II. Problem Description
Allocating memory to retrieve the memory map may cause further fragmentation
in the memory map. This fragmentation may cause the memory map to grow
enough for the previously allocated memory to no longer be sufficient to
hold the memory map. In this case, the UEFI loader would simply fail to
boot the kernel instead of reallocating and attempting to fetch the memory
map again.
III. Impact
Some systems may intermittently fail to boot due to this fragmentation, and
require a restart.
IV. Workaround
No workaround is available. Systems that are not configured to boot via the
UEFI loader are not affected, and not all systems that are configured to
boot via the UEFI loader will exhibit this behavior.
V. Solution
Upgrade your system to a supported FreeBSD stable or release / security
branch (releng) dated after the correction date.
Perform one of the following:
1) To update your system via a binary patch:
Systems running a RELEASE version of FreeBSD on the i386 or amd64
platforms can be updated via the freebsd-update(8) utility:
# freebsd-update fetch
# freebsd-update install
2) To update your system via a source code patch:
The following patches have been verified to apply to the applicable
FreeBSD release branches.
a) Download the relevant patch from the location below, and verify the
detached PGP signature using your PGP utility.
[FreeBSD 12.x]
# fetch https://security.FreeBSD.org/patches/EN-19:19/loader.patch
# fetch https://security.FreeBSD.org/patches/EN-19:19/loader.patch.asc
# gpg --verify loader.patch.asc
b) Apply the patch. Execute the following commands as root:
# cd /usr/src
# patch < /path/to/patch
c) Recompile the operating system using buildworld and installworld as
described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>.
If the system was first installed with FreeBSD 12.0 or later a copy of the
EFI loader is installed as \EFI\freebsd\loader.efi on the EFI System
Partition (ESP). In that case mount the ESP and copy /boot/loader.efi to
\EFI\freebsd\loader.efi.
VI. Correction details
The following list contains the correction revision numbers for each
affected branch.
Branch/path Revision
- -------------------------------------------------------------------------
stable/12/ r352788
releng/12.1/ r354652
releng/12.0/ r354652
- -------------------------------------------------------------------------
To see which files were modified by a particular revision, run the
following command, replacing NNNNNN with the revision number, on a
machine with Subversion installed:
# svn diff -cNNNNNN --summarize svn://svn.freebsd.org/base
Or visit the following URL, replacing NNNNNN with the revision number:
<URL:https://svnweb.freebsd.org/base?view=revision&revision=NNNNNN>
VII. References
The latest revision of this advisory is available at
<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-19:19.loader.asc>
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAl3K+jlfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD
MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n
5cKo6hAAlrPVQSTQ+PGu9YtAdLG/0NZlIRdFNyjqKekkQDSEQnh35MKzVrZW4mmu
12pM2ELRU3e4HZbZEXi0B98HAqGrbSrlXHKAwosMMmhrkNBXU+fUQcjbxHfEiRoE
oXPhYNTQD+7ph3A2CO0mGi5d5aSdMeZqr6ayJvmlEzg/Btd0v/SnB5XWRw0c3xP2
bCfXqS8ne2Nc0LCMzAoC69b/HQr/hi45ukbkexON+vUH0wB8N3QzwtjtZYXNMCoD
T7w5FsW6ZnPqTFVNfQfIT9DUZCE0TJ4HD3D2GNX9rs8tvetgWpE7sXbRbRb87MIR
zt85nwyriVjovbi24oyMgmjFgIqteRqDBG96XEWWB6YhHrOPoXd76RaOStX2r4yj
q01i+lNNb5P0mqTvHQWx7XyDlhzVJsZEK6UyeFKT8WWarrFQ5FzLU3Fdr3G9pRAb
1VZJCW6GgEYlOxMBVHANtUJi3JTCWSG7vw2GNLkpwHfhpPDSV8wSKNVcpTjzHS5K
9u5iLsfNl3RtA1qD2/PPVyz12au045+WjAzlWzR8ioivRF8KwqKuwFdSUpVGcIDm
+y5YOanAgT2LxpNLf0ZbHmAZaR5kCtBDGuDFW6+z2zPHaea9opIprutgqERzc9Es
XHh3M29OeO457JiU/yTliLraObpf0rEFUG7d30TDO1wywR/ehlM=
=ayk8
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,145 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
=============================================================================
FreeBSD-SA-19:25.mcepsc Security Advisory
The FreeBSD Project
Topic: Machine Check Exception on Page Size Change
Category: core
Module: kernel
Announced: 2019-11-12
Credits: Intel
Affects: All supported versions of FreeBSD.
Corrected: 2019-11-12 18:03:26 UTC (stable/12, 12.1-STABLE)
2019-11-12 18:13:04 UTC (releng/12.1, 12.1-RELEASE-p1)
2019-11-12 18:13:04 UTC (releng/12.0, 12.0-RELEASE-p12)
2019-11-12 18:04:28 UTC (stable/11, 11.3-STABLE)
2019-11-12 18:13:04 UTC (releng/11.3, 11.3-RELEASE-p5)
CVE Name: CVE-2018-12207
For general information regarding FreeBSD Security Advisories,
including descriptions of the fields above, security branches, and the
following sections, please visit <URL:https://security.FreeBSD.org/>.
I. Background
The Intel machine check architecture is a mechanism to detect and report
hardware errors, such as system bus errors, ECC errors, parity errors, and
others. This allows the processor to signal the detection of a machine
check error to the operating system.
II. Problem Description
Intel discovered a previously published erratum on some Intel platforms can
be exploited by malicious software to potentially cause a denial of service
by triggering a machine check that will crash or hang the system.
III. Impact
Malicious guest operating systems may be able to crash the host.
IV. Workaround
No workaround is available. Systems not running untrusted guest virtual
machines are not impacted.
V. Solution
Upgrade your vulnerable system to a supported FreeBSD stable or
release / security branch (releng) dated after the correction date,
and reboot.
Perform one of the following:
1) To update your vulnerable system via a binary patch:
Systems running a RELEASE version of FreeBSD on the i386 or amd64
platforms can be updated via the freebsd-update(8) utility:
# freebsd-update fetch
# freebsd-update install
# shutdown -r +10min "Rebooting for a security update"
2) To update your vulnerable system via a source code patch:
The following patches have been verified to apply to the applicable
FreeBSD release branches.
a) Download the relevant patch from the location below, and verify the
detached PGP signature using your PGP utility.
[FreeBSD 12.1]
# fetch https://security.FreeBSD.org/patches/SA-19:25/mcepsc.12.1.patch
# fetch https://security.FreeBSD.org/patches/SA-19:25/mcepsc.12.1.patch.asc
# gpg --verify mcepsc.12.1.patch.asc
[FreeBSD 12.0]
# fetch https://security.FreeBSD.org/patches/SA-19:25/mcepsc.12.0.patch
# fetch https://security.FreeBSD.org/patches/SA-19:25/mcepsc.12.0.patch.asc
# gpg --verify mcepsc.12.0.patch.asc
[FreeBSD 11.3]
# fetch https://security.FreeBSD.org/patches/SA-19:25/mcepsc.11.patch
# fetch https://security.FreeBSD.org/patches/SA-19:25/mcepsc.11.patch.asc
# gpg --verify mcepsc.11.patch.asc
b) Apply the patch. Execute the following commands as root:
# cd /usr/src
# patch < /path/to/patch
c) Recompile your kernel as described in
<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the
system.
VI. Correction details
The following list contains the correction revision numbers for each
affected branch.
Branch/path Revision
- -------------------------------------------------------------------------
stable/12/ r354650
releng/12.1/ r354653
releng/12.0/ r354653
stable/11/ r354651
releng/11.3/ r354653
- -------------------------------------------------------------------------
To see which files were modified by a particular revision, run the
following command, replacing NNNNNN with the revision number, on a
machine with Subversion installed:
# svn diff -cNNNNNN --summarize svn://svn.freebsd.org/base
Or visit the following URL, replacing NNNNNN with the revision number:
<URL:https://svnweb.freebsd.org/base?view=revision&revision=NNNNNN>
VII. References
<URL:https://software.intel.com/security-software-guidance/software-guidance/machine-check-error-avoidance-page-size-change>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12207>
The latest revision of this advisory is available at
<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-19:25.mcepsc.asc>
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAl3K+khfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD
MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n
5cIWdA//dTBwRIejd8vkgB/6wCLfXARU2Nw9je69JwfvpC/3BzkV+oD9rwoL7ltk
NtOIu6otRmGnGHvC19WQ/JdlHUgtoxaxB26ROoU5BCYPJL7dU48T6l6RLbNXdMC4
MxU3mgbiDrVw9hhh42qKNVQ+ZzpMjgUPN1WRCyKQNlG7jNm5a8BvBaK0mFYkLdEw
9u+kNpXdaC9Ip45JI4QVS+jyK5JqFYWZw4SlB6AggcMO93QySzWWx4ZjXafw+0EK
VoS8ByQ5nTlCVqq+hok+yVEz42mZ9AFSE1E1n3pe5TFZZmxF+NcDVMw324eLWUY3
pVX3S6Y0dCtKKvpyy2WIMrBV4Ro5BX3nQXJINdwCo2IlBRvJgK7u0wK3P0ionsJk
Hc4x3sjZQm9Rhb8qqOh01wb7MjmGMWX/nlyishF6MAmnIV3dXctMaG00CSsIMbv9
jtx5v8uSGUHXb8bGYa6QLxaNN1gV6ZLMne1HLunkP7sCX9NYfibjkBXSIfNAkQTn
MFrz9LLgy1K+8s2D1yFJZeyAZMWZ82yc14FSbux21pZS8MURpFt0OBYymAlzn0/J
fhFEKg7rjKBuIBKjDycu9K8+s8h5TIGDROmgQojeqHm6wmlqyGVIPsREyBcCEvwM
16pasZC9s5C7aoSvzDExekR+LQOc8jVZ80KjNGmMga41tSANKTQ=
=9nRn
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,172 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
=============================================================================
FreeBSD-SA-19:26.mcu Security Advisory
The FreeBSD Project
Topic: Intel CPU Microcode Update
Category: 3rd party
Module: Intel CPU microcode
Announced: 2019-11-12
Credits: Intel
Affects: All supported versions of FreeBSD running on certain
Intel CPUs.
CVE Name: CVE-2019-11135, CVE-2019-11139, CVE-2018-12126,
CVE-2018-12127, CVE-2018-12130, CVE-2018-11091,
CVE-2017-5715
For general information regarding FreeBSD Security Advisories,
including descriptions of the fields above, security branches, and the
following sections, please visit <URL:https://security.FreeBSD.org/>.
I. Background
- From time to time Intel releases new CPU microcode to address functional
issues and security vulnerabilities. Such a release is also known as a
Micro Code Update (MCU), and is a component of a broader Intel Platform
Update (IPU). FreeBSD distributes CPU microcode via the devcpu-data port
and package.
II. Problem Description
Starting with version 1.26, the devcpu-data port/package includes updates and
mitigations for the following technical and security advisories (depending
on CPU model).
Intel TSX Updates (TAA) CVE-2019-11135
Voltage Modulation Vulnerability CVE-2019-11139
MD_CLEAR Operations CVE-2018-12126
CVE-2018-12127
CVE-2018-12130
CVE-2018-11091
TA Indirect Sharing CVE-2017-5715
EGETKEY CVE-2018-12126
CVE-2018-12127
CVE-2018-12130
CVE-2018-11091
JCC SKX102 Erratum
Updated microcode includes mitigations for CPU issues, but may also cause a
performance regression due to the JCC erratum mitigation. Please visit
http://www.intel.com/benchmarks for further information.
Please visit http://www.intel.com/security for detailed information on
these advisories as well as a list of CPUs that are affected.
III. Impact
Operating a CPU without the latest microcode may result in erratic or
unpredictable behavior, including system crashes and lock ups. Certain
issues listed in this advisory may result in the leakage of privileged
system information to unprivileged users. Please refer to the security
advisories listed above for detailed information.
IV. Workaround
To determine if TSX is present in your system, run the following:
1. kldload cpuctl
2. cpucontrol -i 7 /dev/cpuctl0
If bits 4 (0x10) and 11 (0x800) are set in the second response word (EBX),
TSX is present.
In the absence of updated microcode, TAA can be mitigated by enabling the
MDS mitigation:
3. sysctl hw.mds_disable=1
Systems must be running FreeBSD 11.3, FreeBSD 12.1, or later for this to
work.
*IMPORTANT*
If your use case can tolerate leaving the CPU issues unmitigated and cannot
tolerate a performance regression, ensure that the devcpu-data package is
not installed or is locked at 1.25 or earlier.
# pkg delete devcpu-data
or
# pkg lock devcpu-data
Later versions of the LLVM and GCC compilers will include changes that
partially relieve the peformance impact.
V. Solution
Install the latest Intel Microcode Update via the devcpu-data port/package,
version 1.26 or later.
Updated microcode adds the ability to disable TSX. With updated microcode
the issue can still be mitigated by enabling the MDS mitigation as
described in the workaround section, or by disabling TSX instead:
1. kldload cpuctl
2. cpucontrol -i 7 /dev/cpuctl0
If bit 29 (0x20000000) is set in the fourth response word (EDX), then the
0x10a MSR is present.
3. cpucontrol -m 0x10a /dev/cpuctl0
If bit 8 (0x100) of the response word is set, your CPU is not vulnerable to
TAA and no further action is required.
If bit 7 (0x80) is cleared, then your CPU does not have updated microcode
that facilitates TSX to be disabled. The only remedy available is to
enable the MDS mitigation, as documented above.
4. cpucontrol -m 0x122=3 /dev/cpuctl0
Repeat step 4 for each numbered CPU that is present.
A future kernel change to FreeBSD will provide automatic detection and
mitigation for TAA.
LLVM 9.0 will be updated in FreeBSD 13-current to address the JCC
peformance impact. Updates to prior versions of LLVM are currently being
evaluated.
VI. Correction details
There are currently no changes in FreeBSD to address this issue.
VII. References
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11135>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11139>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12126>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12127>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12130>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11091>
<URL:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715>
<URL:https://blogs.intel.com/technology/2019/11/ipas-november-2019-intel-platform-update-ipu/
<URL:https://software.intel.com/security-software-guidance/software-guidance/intel-transactional-synchronization-extensions-intel-tsx-asynchronous-abort>
<URL:https://www.intel.com/content/www/us/en/support/articles/000055650.html>
The latest revision of this advisory is available at
<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-19:26.mcu.asc>
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAl3K/DRfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD
MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n
5cL4Yg/9Gzuj6w3Gj7oToaaxMWkMHqFgVj45WlLi1zH/Ccz2XsszPXt5+eCGrsuE
z6EjHb/egPtOZOat3elJLwflfPJ68AMYcEke2IUAt4NpPg9LH9tP+fQshBHFKpvx
iwjWmXy9cxajS7oVq3n44m5/ac9Z9EdFfGGP7T32PUASV3nk+4IqWGSvCwAOQ+rO
CAfYB/TEbD6CqXkLiaH5mc+Mrb02jl2NyfX3LcSJptSMV1gtlHt9IOlB6RM/Rtjf
x0q4L5dBTrpnZTs9a9O4OePxD0EajpfbCtoPRPQM37fcW19J1shooziV1C0fBhcg
ZHIrxt9x8q4EeBY28BVFKf+j8CM6W+2NXe6ysI4jrE8j21zG5EDVKXU+gmy8Qxuw
d9gWXLw431RB5XJaTCZtUE8ymxj2G6rxzynUaycJ2CrcuZQSNKMJOblx527TiCFF
lp8Gat2JpqH1J08EXlGxAVDXnQuiN3lOOZ/NkiU9Qp4cqJgcnVs0nA+CtKbccHIb
nwdAQJxBPvdWLr4UcFDIs7as0rMTZI02vHbM+a9Z1urm/UgcnXdzAbeISLkhmQ+A
CjKK+h89Z9h51xG+4Nyu0jGQqTO6U4ihbKTmOqpWj9nocL/uyMiXr0wD0UuOQD/J
WTR3lPhyQGOJmOR++8WVsmL/h2mdS1rFWocHFoLRRoPcs0zM2c8=
=kYQh
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,219 @@
--- stand/efi/loader/bootinfo.c.orig
+++ stand/efi/loader/bootinfo.c
@@ -287,12 +287,12 @@
bi_load_efi_data(struct preloaded_file *kfp)
{
EFI_MEMORY_DESCRIPTOR *mm;
- EFI_PHYSICAL_ADDRESS addr;
+ EFI_PHYSICAL_ADDRESS addr = 0;
EFI_STATUS status;
const char *efi_novmap;
size_t efisz;
UINTN efi_mapkey;
- UINTN mmsz, pages, retry, sz;
+ UINTN dsz, pages, retry, sz;
UINT32 mmver;
struct efi_map_header *efihdr;
bool do_vmap;
@@ -323,76 +323,94 @@
efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
/*
- * Assgin size of EFI_MEMORY_DESCRIPTOR to keep compatible with
+ * Assign size of EFI_MEMORY_DESCRIPTOR to keep compatible with
* u-boot which doesn't fill this value when buffer for memory
* descriptors is too small (eg. 0 to obtain memory map size)
*/
- mmsz = sizeof(EFI_MEMORY_DESCRIPTOR);
+ dsz = sizeof(EFI_MEMORY_DESCRIPTOR);
/*
- * It is possible that the first call to ExitBootServices may change
- * the map key. Fetch a new map key and retry ExitBootServices in that
- * case.
+ * Allocate enough pages to hold the bootinfo block and the
+ * memory map EFI will return to us. The memory map has an
+ * unknown size, so we have to determine that first. Note that
+ * the AllocatePages call can itself modify the memory map, so
+ * we have to take that into account as well. The changes to
+ * the memory map are caused by splitting a range of free
+ * memory into two, so that one is marked as being loader
+ * data.
+ */
+
+ sz = 0;
+
+ /*
+ * Matthew Garrett has observed at least one system changing the
+ * memory map when calling ExitBootServices, causing it to return an
+ * error, probably because callbacks are allocating memory.
+ * So we need to retry calling it at least once.
*/
for (retry = 2; retry > 0; retry--) {
- /*
- * Allocate enough pages to hold the bootinfo block and the
- * memory map EFI will return to us. The memory map has an
- * unknown size, so we have to determine that first. Note that
- * the AllocatePages call can itself modify the memory map, so
- * we have to take that into account as well. The changes to
- * the memory map are caused by splitting a range of free
- * memory into two (AFAICT), so that one is marked as being
- * loader data.
- */
- sz = 0;
- BS->GetMemoryMap(&sz, NULL, &efi_mapkey, &mmsz, &mmver);
- sz += mmsz;
- sz = (sz + 0xf) & ~0xf;
- pages = EFI_SIZE_TO_PAGES(sz + efisz);
- status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
- pages, &addr);
- if (EFI_ERROR(status)) {
- printf("%s: AllocatePages error %lu\n", __func__,
- EFI_ERROR_CODE(status));
- return (ENOMEM);
- }
+ for (;;) {
+ status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &dsz, &mmver);
+ if (!EFI_ERROR(status))
+ break;
+
+ if (status != EFI_BUFFER_TOO_SMALL) {
+ printf("%s: GetMemoryMap error %lu\n", __func__,
+ EFI_ERROR_CODE(status));
+ return (EINVAL);
+ }
+
+ if (addr != 0)
+ BS->FreePages(addr, pages);
+
+ /* Add 10 descriptors to the size to allow for
+ * fragmentation caused by calling AllocatePages */
+ sz += (10 * dsz);
+ pages = EFI_SIZE_TO_PAGES(sz + efisz);
+ status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
+ pages, &addr);
+ if (EFI_ERROR(status)) {
+ printf("%s: AllocatePages error %lu\n", __func__,
+ EFI_ERROR_CODE(status));
+ return (ENOMEM);
+ }
- /*
- * Read the memory map and stash it after bootinfo. Align the
- * memory map on a 16-byte boundary (the bootinfo block is page
- * aligned).
- */
- efihdr = (struct efi_map_header *)(uintptr_t)addr;
- mm = (void *)((uint8_t *)efihdr + efisz);
- sz = (EFI_PAGE_SIZE * pages) - efisz;
-
- status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &mmsz, &mmver);
- if (EFI_ERROR(status)) {
- printf("%s: GetMemoryMap error %lu\n", __func__,
- EFI_ERROR_CODE(status));
- return (EINVAL);
- }
- 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.
+ * Read the memory map and stash it after bootinfo. Align the
+ * memory map on a 16-byte boundary (the bootinfo block is page
+ * aligned).
*/
- if (do_vmap)
- efi_do_vmap(mm, sz, mmsz, mmver);
- efihdr->memory_size = sz;
- efihdr->descriptor_size = mmsz;
- efihdr->descriptor_version = mmver;
- file_addmetadata(kfp, MODINFOMD_EFI_MAP, efisz + sz,
- efihdr);
- return (0);
+ efihdr = (struct efi_map_header *)(uintptr_t)addr;
+ mm = (void *)((uint8_t *)efihdr + efisz);
+ sz = (EFI_PAGE_SIZE * pages) - efisz;
}
+
+ status = BS->ExitBootServices(IH, efi_mapkey);
+ if (!EFI_ERROR(status))
+ break;
+ }
+
+ if (retry == 0) {
BS->FreePages(addr, pages);
+ printf("ExitBootServices error %lu\n", EFI_ERROR_CODE(status));
+ return (EINVAL);
}
- printf("ExitBootServices error %lu\n", EFI_ERROR_CODE(status));
- return (EINVAL);
+
+ /*
+ * 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, dsz, mmver);
+ efihdr->memory_size = sz;
+ efihdr->descriptor_size = dsz;
+ efihdr->descriptor_version = mmver;
+ file_addmetadata(kfp, MODINFOMD_EFI_MAP, efisz + sz,
+ efihdr);
+
+ return (0);
}
/*
--- stand/efi/loader/copy.c.orig
+++ stand/efi/loader/copy.c
@@ -95,7 +95,7 @@
efi_verify_staging_size(unsigned long *nr_pages)
{
UINTN sz;
- EFI_MEMORY_DESCRIPTOR *map, *p;
+ EFI_MEMORY_DESCRIPTOR *map = NULL, *p;
EFI_PHYSICAL_ADDRESS start, end;
UINTN key, dsz;
UINT32 dver;
@@ -104,17 +104,28 @@
unsigned long available_pages = 0;
sz = 0;
- status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
- if (status != EFI_BUFFER_TOO_SMALL) {
- printf("Can't determine memory map size\n");
- return;
- }
- map = malloc(sz);
- status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
- if (EFI_ERROR(status)) {
- printf("Can't read memory map\n");
- goto out;
+ for (;;) {
+ status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
+ if (!EFI_ERROR(status))
+ break;
+
+ if (status != EFI_BUFFER_TOO_SMALL) {
+ printf("Can't read memory map: %lu\n",
+ EFI_ERROR_CODE(status));
+ goto out;
+ }
+
+ free(map);
+
+ /* Allocate 10 descriptors more than the size reported,
+ * to allow for any fragmentation caused by calling
+ * malloc */
+ map = malloc(sz + (10 * dsz));
+ if (map == NULL) {
+ printf("Unable to allocate memory\n");
+ goto out;
+ }
}
ndesc = sz / dsz;

View file

@ -0,0 +1,18 @@
-----BEGIN PGP SIGNATURE-----
iQKTBAABCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAl3K+llfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD
MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n
5cKQDA//UrHA7uTNrdGlLotWJQfCnFyeso3/jgOV/9eouJ4x0Ci81ubXqjFGs8co
/lx2PVkFJoJpPHrQOeReYAKiHhvygCilh/04wA9fiVVsrt7Clb4hAY1v4qr4hu32
lBVZCBLBsWBsWppoN88Xmm6QbQrF1IuVLPxEw55gR/4G9cHUi13WcHrIB68YiBNI
S3cHqWpPawoLAZcfaEbiMYtEFpnhaVXxPgzNUsmu16pzlZRSof44x9cOP0d5j70c
3UUqsoO0fT3PQBSoU4xIGg7c6ZAg+iLQEnLnC2PWFMKSov8OFcVF7XbygaLniOc5
fYXPZWyDw+4T3GDfiftj9j6pXkTcYUJhFz+Ukb0CEJZtV2Pzb6PLS0U4W0+4fyUA
7vT7WBdkcN5GrMXilu3se6/F/BEGUMC3WvSxpGZv81LyAOZ1j+Sta3uGoBJycJw5
gX61kDwc2BpzAPrPbIQs0TRxfKaAjDaMYMUmAqXaZWLQDegatqIJ/VMXKiTUSznA
9lIgQCXaviHXTuBEOCe1NmFmCuYFzVqgzcxq4KrgRbFzTBK0KYcjOoWsTGzjzwdi
TnQPFsnITZvRqybSMxQDGOcOp3m5WW2jpXzKIsc4E7o4UBEgrPVJFvadhSjnTEAC
KmzFYMBMKxjdTK0c/B92vADoqOInQD8h5f99cUsu5qT8xM98A3c=
=U6/A
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,155 @@
--- sys/amd64/amd64/pmap.c.orig
+++ sys/amd64/amd64/pmap.c
@@ -1226,6 +1226,51 @@
m->md.pat_mode = PAT_WRITE_BACK;
}
+static int pmap_allow_2m_x_ept;
+SYSCTL_INT(_vm_pmap, OID_AUTO, allow_2m_x_ept, CTLFLAG_RWTUN | CTLFLAG_NOFETCH,
+ &pmap_allow_2m_x_ept, 0,
+ "Allow executable superpage mappings in EPT");
+
+void
+pmap_allow_2m_x_ept_recalculate(void)
+{
+ /*
+ * SKL002, SKL012S. Since the EPT format is only used by
+ * Intel CPUs, the vendor check is merely a formality.
+ */
+ if (!(cpu_vendor_id != CPU_VENDOR_INTEL ||
+ (cpu_ia32_arch_caps & IA32_ARCH_CAP_IF_PSCHANGE_MC_NO) != 0 ||
+ (CPUID_TO_FAMILY(cpu_id) == 0x6 &&
+ (CPUID_TO_MODEL(cpu_id) == 0x26 || /* Atoms */
+ CPUID_TO_MODEL(cpu_id) == 0x27 ||
+ CPUID_TO_MODEL(cpu_id) == 0x35 ||
+ CPUID_TO_MODEL(cpu_id) == 0x36 ||
+ CPUID_TO_MODEL(cpu_id) == 0x37 ||
+ CPUID_TO_MODEL(cpu_id) == 0x86 ||
+ CPUID_TO_MODEL(cpu_id) == 0x1c ||
+ CPUID_TO_MODEL(cpu_id) == 0x4a ||
+ CPUID_TO_MODEL(cpu_id) == 0x4c ||
+ CPUID_TO_MODEL(cpu_id) == 0x4d ||
+ CPUID_TO_MODEL(cpu_id) == 0x5a ||
+ CPUID_TO_MODEL(cpu_id) == 0x5c ||
+ CPUID_TO_MODEL(cpu_id) == 0x5d ||
+ CPUID_TO_MODEL(cpu_id) == 0x5f ||
+ CPUID_TO_MODEL(cpu_id) == 0x6e ||
+ CPUID_TO_MODEL(cpu_id) == 0x7a ||
+ CPUID_TO_MODEL(cpu_id) == 0x57 || /* Knights */
+ CPUID_TO_MODEL(cpu_id) == 0x85))))
+ pmap_allow_2m_x_ept = 1;
+ TUNABLE_INT_FETCH("hw.allow_2m_x_ept", &pmap_allow_2m_x_ept);
+}
+
+static bool
+pmap_allow_2m_x_page(pmap_t pmap, bool executable)
+{
+
+ return (pmap->pm_type != PT_EPT || !executable ||
+ !pmap_allow_2m_x_ept);
+}
+
/*
* Initialize the pmap module.
* Called by vm_init, to initialize any structures that the pmap
@@ -1270,6 +1315,9 @@
}
}
+ /* IFU */
+ pmap_allow_2m_x_ept_recalculate();
+
/*
* Initialize the vm page array entries for the kernel pmap's
* page table pages.
@@ -4550,6 +4598,15 @@
}
#if VM_NRESERVLEVEL > 0
+static bool
+pmap_pde_ept_executable(pmap_t pmap, pd_entry_t pde)
+{
+
+ if (pmap->pm_type != PT_EPT)
+ return (false);
+ return ((pde & EPT_PG_EXECUTE) != 0);
+}
+
/*
* Tries to promote the 512, contiguous 4KB page mappings that are within a
* single page table page (PTP) to a single 2MB page mapping. For promotion
@@ -4584,7 +4641,9 @@
firstpte = (pt_entry_t *)PHYS_TO_DMAP(*pde & PG_FRAME);
setpde:
newpde = *firstpte;
- if ((newpde & ((PG_FRAME & PDRMASK) | PG_A | PG_V)) != (PG_A | PG_V)) {
+ if ((newpde & ((PG_FRAME & PDRMASK) | PG_A | PG_V)) != (PG_A | PG_V) ||
+ !pmap_allow_2m_x_page(pmap, pmap_pde_ept_executable(pmap,
+ newpde))) {
atomic_add_long(&pmap_pde_p_failures, 1);
CTR2(KTR_PMAP, "pmap_promote_pde: failure for va %#lx"
" in pmap %p", va, pmap);
@@ -5010,6 +5069,12 @@
PG_V = pmap_valid_bit(pmap);
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ if (!pmap_allow_2m_x_page(pmap, pmap_pde_ept_executable(pmap,
+ newpde))) {
+ CTR2(KTR_PMAP, "pmap_enter_pde: 2m x blocked for va %#lx"
+ " in pmap %p", va, pmap);
+ return (KERN_FAILURE);
+ }
if ((pdpg = pmap_allocpde(pmap, va, (flags & PMAP_ENTER_NOSLEEP) != 0 ?
NULL : lockp)) == NULL) {
CTR2(KTR_PMAP, "pmap_enter_pde: failure for va %#lx"
@@ -5139,6 +5204,7 @@
va = start + ptoa(diff);
if ((va & PDRMASK) == 0 && va + NBPDR <= end &&
m->psind == 1 && pmap_ps_enabled(pmap) &&
+ pmap_allow_2m_x_page(pmap, (prot & VM_PROT_EXECUTE) != 0) &&
pmap_enter_2mpage(pmap, va, m, prot, &lock))
m = &m[NBPDR / PAGE_SIZE - 1];
else
--- sys/amd64/include/pmap.h.orig
+++ sys/amd64/include/pmap.h
@@ -407,6 +407,7 @@
void pmap_activate_boot(pmap_t pmap);
void pmap_activate_sw(struct thread *);
+void pmap_allow_2m_x_ept_recalculate(void);
void pmap_bootstrap(vm_paddr_t *);
int pmap_cache_bits(pmap_t pmap, int mode, boolean_t is_pde);
int pmap_change_attr(vm_offset_t, vm_size_t, int);
--- sys/dev/cpuctl/cpuctl.c.orig
+++ sys/dev/cpuctl/cpuctl.c
@@ -48,6 +48,10 @@
#include <sys/pmckern.h>
#include <sys/cpuctl.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
#include <machine/cpufunc.h>
#include <machine/md_var.h>
#include <machine/specialreg.h>
@@ -535,6 +539,9 @@
hw_ibrs_recalculate();
restore_cpu(oldcpu, is_bound, td);
hw_ssb_recalculate(true);
+#ifdef __amd64__
+ pmap_allow_2m_x_ept_recalculate();
+#endif
hw_mds_recalculate();
printcpuinfo();
return (0);
--- sys/x86/include/specialreg.h.orig
+++ sys/x86/include/specialreg.h
@@ -406,6 +406,7 @@
#define IA32_ARCH_CAP_SKIP_L1DFL_VMENTRY 0x00000008
#define IA32_ARCH_CAP_SSB_NO 0x00000010
#define IA32_ARCH_CAP_MDS_NO 0x00000020
+#define IA32_ARCH_CAP_IF_PSCHANGE_MC_NO 0x00000040
/*
* CPUID manufacturers identifiers

View file

@ -0,0 +1,18 @@
-----BEGIN PGP SIGNATURE-----
iQKTBAABCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAl3K+mJfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD
MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n
5cJLsg/7BAKmJMh9yd59hixizqFtK2yCPybFOiYau1gsO9FyELIb0PG6Ofb+OnaT
72tiextc4NIOhsKqayi0+AaIM2nmJfX/AvzrjT/jn7kVvEK5VZuRcXloISvtqwhG
aIT6OuMdJcCEEorGC3lhK0jjvtakb/OxIqqYuQ45F99lh0I9EtZ0SCP/7d7thIkh
saXvSXTr93ShDXQPLb25nz5Q9/fGh6TZRLhrwiWi7E1leZlnk8sLMrJMh+7g/ZlQ
DwjS/E7JRQ+UJ4BSfqDeRppCVs6lT7tCKZbqiptO/KPSx/yoO/fxq+N0wzWB9+I0
fqoppNNzo8ulmqQ/kclIRxadBDALWB2R9cvQU99nkorkQJ8xvOJLgHBw5o38ZvKO
E93Fbv0okrO6Pa4FHQlHxVqjmr2ayDILHGN+bLsQL08k86FhpE2Z7YB8IWEtrsuh
2mHEgzn3IoUg0iPEHUNN5gjv8X8loUeHppLDvIibpVlKfsiqXS0OfbEly9EJz358
JEr2lc8+IXm2incrsGCZj+To49Gt/6voD6IsPrE01gpevhWmYXL/tXF/QLTPTVSE
LbAcyddsIXx8Nc++LIUvHiwyk3wNA+coz6wi0DXXluM8l/idwKIWWU8vnWTA0o/L
D6+G+92yyhp0bNq8okLe1W+UlBZvWJybwKpbetkq23KveqLOUmk=
=ru3c
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,155 @@
--- sys/amd64/amd64/pmap.c.orig
+++ sys/amd64/amd64/pmap.c
@@ -1309,6 +1309,51 @@
m->md.pat_mode = PAT_WRITE_BACK;
}
+static int pmap_allow_2m_x_ept;
+SYSCTL_INT(_vm_pmap, OID_AUTO, allow_2m_x_ept, CTLFLAG_RWTUN | CTLFLAG_NOFETCH,
+ &pmap_allow_2m_x_ept, 0,
+ "Allow executable superpage mappings in EPT");
+
+void
+pmap_allow_2m_x_ept_recalculate(void)
+{
+ /*
+ * SKL002, SKL012S. Since the EPT format is only used by
+ * Intel CPUs, the vendor check is merely a formality.
+ */
+ if (!(cpu_vendor_id != CPU_VENDOR_INTEL ||
+ (cpu_ia32_arch_caps & IA32_ARCH_CAP_IF_PSCHANGE_MC_NO) != 0 ||
+ (CPUID_TO_FAMILY(cpu_id) == 0x6 &&
+ (CPUID_TO_MODEL(cpu_id) == 0x26 || /* Atoms */
+ CPUID_TO_MODEL(cpu_id) == 0x27 ||
+ CPUID_TO_MODEL(cpu_id) == 0x35 ||
+ CPUID_TO_MODEL(cpu_id) == 0x36 ||
+ CPUID_TO_MODEL(cpu_id) == 0x37 ||
+ CPUID_TO_MODEL(cpu_id) == 0x86 ||
+ CPUID_TO_MODEL(cpu_id) == 0x1c ||
+ CPUID_TO_MODEL(cpu_id) == 0x4a ||
+ CPUID_TO_MODEL(cpu_id) == 0x4c ||
+ CPUID_TO_MODEL(cpu_id) == 0x4d ||
+ CPUID_TO_MODEL(cpu_id) == 0x5a ||
+ CPUID_TO_MODEL(cpu_id) == 0x5c ||
+ CPUID_TO_MODEL(cpu_id) == 0x5d ||
+ CPUID_TO_MODEL(cpu_id) == 0x5f ||
+ CPUID_TO_MODEL(cpu_id) == 0x6e ||
+ CPUID_TO_MODEL(cpu_id) == 0x7a ||
+ CPUID_TO_MODEL(cpu_id) == 0x57 || /* Knights */
+ CPUID_TO_MODEL(cpu_id) == 0x85))))
+ pmap_allow_2m_x_ept = 1;
+ TUNABLE_INT_FETCH("hw.allow_2m_x_ept", &pmap_allow_2m_x_ept);
+}
+
+static bool
+pmap_allow_2m_x_page(pmap_t pmap, bool executable)
+{
+
+ return (pmap->pm_type != PT_EPT || !executable ||
+ !pmap_allow_2m_x_ept);
+}
+
/*
* Initialize the pmap module.
* Called by vm_init, to initialize any structures that the pmap
@@ -1353,6 +1398,9 @@
}
}
+ /* IFU */
+ pmap_allow_2m_x_ept_recalculate();
+
/*
* Initialize the vm page array entries for the kernel pmap's
* page table pages.
@@ -4823,6 +4871,15 @@
}
#if VM_NRESERVLEVEL > 0
+static bool
+pmap_pde_ept_executable(pmap_t pmap, pd_entry_t pde)
+{
+
+ if (pmap->pm_type != PT_EPT)
+ return (false);
+ return ((pde & EPT_PG_EXECUTE) != 0);
+}
+
/*
* Tries to promote the 512, contiguous 4KB page mappings that are within a
* single page table page (PTP) to a single 2MB page mapping. For promotion
@@ -4857,7 +4914,9 @@
firstpte = (pt_entry_t *)PHYS_TO_DMAP(*pde & PG_FRAME);
setpde:
newpde = *firstpte;
- if ((newpde & ((PG_FRAME & PDRMASK) | PG_A | PG_V)) != (PG_A | PG_V)) {
+ if ((newpde & ((PG_FRAME & PDRMASK) | PG_A | PG_V)) != (PG_A | PG_V) ||
+ !pmap_allow_2m_x_page(pmap, pmap_pde_ept_executable(pmap,
+ newpde))) {
atomic_add_long(&pmap_pde_p_failures, 1);
CTR2(KTR_PMAP, "pmap_promote_pde: failure for va %#lx"
" in pmap %p", va, pmap);
@@ -5283,6 +5342,12 @@
PG_V = pmap_valid_bit(pmap);
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ if (!pmap_allow_2m_x_page(pmap, pmap_pde_ept_executable(pmap,
+ newpde))) {
+ CTR2(KTR_PMAP, "pmap_enter_pde: 2m x blocked for va %#lx"
+ " in pmap %p", va, pmap);
+ return (KERN_FAILURE);
+ }
if ((pdpg = pmap_allocpde(pmap, va, (flags & PMAP_ENTER_NOSLEEP) != 0 ?
NULL : lockp)) == NULL) {
CTR2(KTR_PMAP, "pmap_enter_pde: failure for va %#lx"
@@ -5412,6 +5477,7 @@
va = start + ptoa(diff);
if ((va & PDRMASK) == 0 && va + NBPDR <= end &&
m->psind == 1 && pmap_ps_enabled(pmap) &&
+ pmap_allow_2m_x_page(pmap, (prot & VM_PROT_EXECUTE) != 0) &&
pmap_enter_2mpage(pmap, va, m, prot, &lock))
m = &m[NBPDR / PAGE_SIZE - 1];
else
--- sys/amd64/include/pmap.h.orig
+++ sys/amd64/include/pmap.h
@@ -413,6 +413,7 @@
void pmap_activate_boot(pmap_t pmap);
void pmap_activate_sw(struct thread *);
+void pmap_allow_2m_x_ept_recalculate(void);
void pmap_bootstrap(vm_paddr_t *);
int pmap_cache_bits(pmap_t pmap, int mode, boolean_t is_pde);
int pmap_change_attr(vm_offset_t, vm_size_t, int);
--- sys/dev/cpuctl/cpuctl.c.orig
+++ sys/dev/cpuctl/cpuctl.c
@@ -50,6 +50,10 @@
#include <sys/pmckern.h>
#include <sys/cpuctl.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
#include <machine/cpufunc.h>
#include <machine/md_var.h>
#include <machine/specialreg.h>
@@ -521,6 +525,9 @@
hw_ibrs_recalculate();
restore_cpu(oldcpu, is_bound, td);
hw_ssb_recalculate(true);
+#ifdef __amd64__
+ pmap_allow_2m_x_ept_recalculate();
+#endif
hw_mds_recalculate();
printcpuinfo();
return (0);
--- sys/x86/include/specialreg.h.orig
+++ sys/x86/include/specialreg.h
@@ -439,6 +439,7 @@
#define IA32_ARCH_CAP_SKIP_L1DFL_VMENTRY 0x00000008
#define IA32_ARCH_CAP_SSB_NO 0x00000010
#define IA32_ARCH_CAP_MDS_NO 0x00000020
+#define IA32_ARCH_CAP_IF_PSCHANGE_MC_NO 0x00000040
/*
* CPUID manufacturers identifiers

View file

@ -0,0 +1,18 @@
-----BEGIN PGP SIGNATURE-----
iQKTBAABCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAl3K+mZfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD
MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n
5cIg8Q//U0cJ4V5bX7tw3IPDS/FHXUXSjCgdQt4pTQoCQ3eNRp3+LNvl4VQDac0N
wUf3FLoeicFKKrysYVf3uEOElk0IfpFb2hqhs1Sp2BhcMlo3YydoQMyDFwZTCh32
vKV+iSD3mvQKCbIdaD1iErNuoxDogPG89ViPiSvQLPFtfY9UBl6CbQuAJooiqHk9
P8ESHnoACsnYkxve5asP6Qxckf/YBbP/4EIZjMHPnb3l1QB/5aMkpEr1BL4Q+02Y
VlRKPZLXXzWQSDBNe9WWEpod/3uHAFMZ036+gQgTkoJIl68ulZd2wQA4F7ZMar2t
Jj+ik1PD7ciQxzszi6lrbHGmbfAKMht+SVQO8VTfKGIzIS0i54RJVVMFRG5O0Qth
SqY+e0LjlfmzYjpgIQPi4pxKqIqshA/Fa5aXiEVEpIsi6/JJwSz+NonPtY1EC+Xl
wXGIvqEBByWvrg/XCUDu5e1W+qstHHjbWZL3z1eaRXj52S4ZyjJBmTGsVW6Zga3y
q1Yp1S60fRrGiD9I1ksIVuE2PTlAVeu311B86OGFVFyhpa51TJsZ8CEPZEd0fYfu
pS80U69ePvjHf+lctiQsRw+DgLm6u+TtviZDoKwFp/r3KWIEbcY+oLMf/maCb/8Y
SnI32ivm75JNe4VrGn8Xshb18GqAMa1OJSI00x6E21teBng/CIw=
=CTY6
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,153 @@
--- sys/amd64/amd64/pmap.c.orig
+++ sys/amd64/amd64/pmap.c
@@ -1805,6 +1805,51 @@
m->md.pat_mode = PAT_WRITE_BACK;
}
+static int pmap_allow_2m_x_ept;
+SYSCTL_INT(_vm_pmap, OID_AUTO, allow_2m_x_ept, CTLFLAG_RWTUN | CTLFLAG_NOFETCH,
+ &pmap_allow_2m_x_ept, 0,
+ "Allow executable superpage mappings in EPT");
+
+void
+pmap_allow_2m_x_ept_recalculate(void)
+{
+ /*
+ * SKL002, SKL012S. Since the EPT format is only used by
+ * Intel CPUs, the vendor check is merely a formality.
+ */
+ if (!(cpu_vendor_id != CPU_VENDOR_INTEL ||
+ (cpu_ia32_arch_caps & IA32_ARCH_CAP_IF_PSCHANGE_MC_NO) != 0 ||
+ (CPUID_TO_FAMILY(cpu_id) == 0x6 &&
+ (CPUID_TO_MODEL(cpu_id) == 0x26 || /* Atoms */
+ CPUID_TO_MODEL(cpu_id) == 0x27 ||
+ CPUID_TO_MODEL(cpu_id) == 0x35 ||
+ CPUID_TO_MODEL(cpu_id) == 0x36 ||
+ CPUID_TO_MODEL(cpu_id) == 0x37 ||
+ CPUID_TO_MODEL(cpu_id) == 0x86 ||
+ CPUID_TO_MODEL(cpu_id) == 0x1c ||
+ CPUID_TO_MODEL(cpu_id) == 0x4a ||
+ CPUID_TO_MODEL(cpu_id) == 0x4c ||
+ CPUID_TO_MODEL(cpu_id) == 0x4d ||
+ CPUID_TO_MODEL(cpu_id) == 0x5a ||
+ CPUID_TO_MODEL(cpu_id) == 0x5c ||
+ CPUID_TO_MODEL(cpu_id) == 0x5d ||
+ CPUID_TO_MODEL(cpu_id) == 0x5f ||
+ CPUID_TO_MODEL(cpu_id) == 0x6e ||
+ CPUID_TO_MODEL(cpu_id) == 0x7a ||
+ CPUID_TO_MODEL(cpu_id) == 0x57 || /* Knights */
+ CPUID_TO_MODEL(cpu_id) == 0x85))))
+ pmap_allow_2m_x_ept = 1;
+ TUNABLE_INT_FETCH("hw.allow_2m_x_ept", &pmap_allow_2m_x_ept);
+}
+
+static bool
+pmap_allow_2m_x_page(pmap_t pmap, bool executable)
+{
+
+ return (pmap->pm_type != PT_EPT || !executable ||
+ !pmap_allow_2m_x_ept);
+}
+
/*
* Initialize the pmap module.
* Called by vm_init, to initialize any structures that the pmap
@@ -1849,6 +1894,9 @@
}
}
+ /* IFU */
+ pmap_allow_2m_x_ept_recalculate();
+
/*
* Initialize the vm page array entries for the kernel pmap's
* page table pages.
@@ -5452,6 +5500,15 @@
}
#if VM_NRESERVLEVEL > 0
+static bool
+pmap_pde_ept_executable(pmap_t pmap, pd_entry_t pde)
+{
+
+ if (pmap->pm_type != PT_EPT)
+ return (false);
+ return ((pde & EPT_PG_EXECUTE) != 0);
+}
+
/*
* Tries to promote the 512, contiguous 4KB page mappings that are within a
* single page table page (PTP) to a single 2MB page mapping. For promotion
@@ -5487,7 +5544,9 @@
firstpte = (pt_entry_t *)PHYS_TO_DMAP(*pde & PG_FRAME);
setpde:
newpde = *firstpte;
- if ((newpde & ((PG_FRAME & PDRMASK) | PG_A | PG_V)) != (PG_A | PG_V)) {
+ if ((newpde & ((PG_FRAME & PDRMASK) | PG_A | PG_V)) != (PG_A | PG_V) ||
+ !pmap_allow_2m_x_page(pmap, pmap_pde_ept_executable(pmap,
+ newpde))) {
atomic_add_long(&pmap_pde_p_failures, 1);
CTR2(KTR_PMAP, "pmap_promote_pde: failure for va %#lx"
" in pmap %p", va, pmap);
@@ -5917,6 +5976,12 @@
PG_V = pmap_valid_bit(pmap);
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ if (!pmap_allow_2m_x_page(pmap, pmap_pde_ept_executable(pmap,
+ newpde))) {
+ CTR2(KTR_PMAP, "pmap_enter_pde: 2m x blocked for va %#lx"
+ " in pmap %p", va, pmap);
+ return (KERN_FAILURE);
+ }
if ((pdpg = pmap_allocpde(pmap, va, (flags & PMAP_ENTER_NOSLEEP) != 0 ?
NULL : lockp)) == NULL) {
CTR2(KTR_PMAP, "pmap_enter_pde: failure for va %#lx"
@@ -6063,6 +6128,7 @@
va = start + ptoa(diff);
if ((va & PDRMASK) == 0 && va + NBPDR <= end &&
m->psind == 1 && pmap_ps_enabled(pmap) &&
+ pmap_allow_2m_x_page(pmap, (prot & VM_PROT_EXECUTE) != 0) &&
pmap_enter_2mpage(pmap, va, m, prot, &lock))
m = &m[NBPDR / PAGE_SIZE - 1];
else
--- sys/amd64/include/pmap.h.orig
+++ sys/amd64/include/pmap.h
@@ -424,6 +424,7 @@
void pmap_activate_boot(pmap_t pmap);
void pmap_activate_sw(struct thread *);
+void pmap_allow_2m_x_ept_recalculate(void);
void pmap_bootstrap(vm_paddr_t *);
int pmap_cache_bits(pmap_t pmap, int mode, boolean_t is_pde);
int pmap_change_attr(vm_offset_t, vm_size_t, int);
--- sys/dev/cpuctl/cpuctl.c.orig
+++ sys/dev/cpuctl/cpuctl.c
@@ -50,6 +50,10 @@
#include <sys/pmckern.h>
#include <sys/cpuctl.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
#include <machine/cpufunc.h>
#include <machine/md_var.h>
#include <machine/specialreg.h>
@@ -539,6 +543,7 @@
hw_ssb_recalculate(true);
#ifdef __amd64__
amd64_syscall_ret_flush_l1d_recalc();
+ pmap_allow_2m_x_ept_recalculate();
#endif
hw_mds_recalculate();
printcpuinfo();
--- sys/x86/include/specialreg.h.orig
+++ sys/x86/include/specialreg.h
@@ -447,6 +447,7 @@
#define IA32_ARCH_CAP_SKIP_L1DFL_VMENTRY 0x00000008
#define IA32_ARCH_CAP_SSB_NO 0x00000010
#define IA32_ARCH_CAP_MDS_NO 0x00000020
+#define IA32_ARCH_CAP_IF_PSCHANGE_MC_NO 0x00000040
/*
* CPUID manufacturers identifiers

View file

@ -0,0 +1,18 @@
-----BEGIN PGP SIGNATURE-----
iQKTBAABCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAl3K+mxfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD
MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n
5cKPwA/+LlSVXDK44aW1dsb9xkoOuyQZXQ+YYi1yhprodMflUhUz+Kno9qK9FL9t
BPeYonV5K9I7Pknjvgd6XpEEPAzPHwuLxH7AQ0y6TT5nAsRc3CxfnhmoII/JKGtx
ufKoiZAmpaPHQv8s+5CAof+f/CbCByzGOlfLHXIidp+3ULxPZ/r4hIRs8HiW+Jgb
kadbMdUtAdwV4gJR1PAFgBOoASLZJbShnvVewa8G3QP9kI2u5kz0Ed7AT6WvY2uT
gTltGuEE2PWjzeWya1ip4k2PidMJwA5Gw8SpajWV/jERsx9E75oEAM3ZQCETAdfR
Y4vCtADnDeczFHfCBKLnrW1gXaejGXG+2uzDwsBooz079ubLWog9Yy7mer9mf47Q
xk28xEDIi+BHjAuALaRdUvPtp4O/jvxQPAtHbxFAToe5OMAH761c2lAN2xOHN2w0
79mMlih9sIGbdKTRDtYqe3U8fOLmoG63KUagYBw1uXoLqmwXnoWVQCeU58CI8Is1
NQBSHErnSbSpr74JThIwFqHt2/b6PpQHXwJuQZlH6XCXSrPLXOZxjBIxzwDfVwW3
62voo7nATyhTWEwZyJrswxjbsgsYDKY0iMZcO3VMi3hY5haX9EGdISRibzdlyAsj
lbcSjApmHRgn55krzJNcG0Vg+u5GQaXw89u3LecY3Td2clgfLZQ=
=rfju
-----END PGP SIGNATURE-----