diff options
author | Yu Ning <yu.ning@intel.com> | 2015-07-13 19:46:39 +0800 |
---|---|---|
committer | Yu Ning <yu.ning@intel.com> | 2015-07-13 19:46:39 +0800 |
commit | b47f0f3709343eb02ca5c6d2c9b609346f34e85f (patch) | |
tree | 0efd38a1bfa63930028db030bb56101d96a1a0f6 | |
parent | da066f54a0a41cf90bb0b27753dcefeb172c010c (diff) | |
download | qemu-pc-bios-b47f0f3709343eb02ca5c6d2c9b609346f34e85f.tar.gz |
bochs/bios: Fix the mask value used when writing to MTRR_PHYSMASK MSR
In bochs/bios/rombios32.c, setup_mtrr() configures the vCPU via the
memory type range registers (MTRRs) to use different methods of caching
(uncached, write-through, write-back, etc.) for different regions of
physical memory. For example, it marks the 3.5-4GiB region (0xE0000000
through 0xFFFFFFFF) as uncached, by writing to the following pair of
model-specific registers (MSRs):
- IA32_MTRR_PHYSBASE0 (value=0x00000000_E0000000)
- IA32_MTRR_PHYSMASK0 (value=0xFFFFFFFF_E0000800)
However, in the case of IA32_MTRR_PHYSMASK0, the current implementation
fails to honor reserved bits (e.g. bit 63). According to Figure 11-7 of
Intel(R) 64 and IA-32 Architectures Software Developer's Manual, Volume
3A [1], bits 63 through MAXPHYADDR are reserved. Moreover, according to
Section 11.11.2.3, "the processor generates a general-protection
exception (#GP) if software attempts to write to them".
This requirement has been enforced by KVM since Linux kernel 3.18 [2].
As a result, the classic Android x86_64 emulator does not boot on Linux
hosts with a 3.18+ kernel (e.g. Ubuntu 15.04). A bug has been opened at:
https://code.google.com/p/android/issues/detail?id=174557
Fix this issue by using the correct mask value. In fact, the upstream
Bochs codebase has already done that, so just back-port all the relevant
patches:
------------------------------------------------------------------------
r9613 | sshwarts | 2009-12-11 15:44:48 +0800 (Fri, 11 Dec 2009) [3]
Commit "fix for BIOS bug" changed MSR_MTRRdefType to MTRR_MEMTYPE_UC.
Change it back to MTRR_MEMTYPE_WB.
------------------------------------------------------------------------
r9515 | vruppert | 2009-10-25 18:25:38 +0800 (Sun, 25 Oct 2009) | [4]
- fixed MTRR mask write bug and enabled check in msr.cc
------------------------------------------------------------------------
r9504 | sshwarts | 2009-10-23 23:32:45 +0800 (Fri, 23 Oct 2009) | [5]
fix for BIOS bug
------------------------------------------------------------------------
[1] http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf
[2] Commit d7a2a24 of Linux kernel
[3] http://sourceforge.net/p/bochs/code/9613
[4] http://sourceforge.net/p/bochs/code/9515
[5] http://sourceforge.net/p/bochs/code/9504
Change-Id: Ice960cbe557f986b001764783c215417e02897c6
Signed-off-by: Yu Ning <yu.ning@intel.com>
-rw-r--r-- | bochs/bios/rombios32.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/bochs/bios/rombios32.c b/bochs/bios/rombios32.c index f8de96d..c0e85a0 100644 --- a/bochs/bios/rombios32.c +++ b/bochs/bios/rombios32.c @@ -83,6 +83,12 @@ typedef unsigned long long uint64_t; #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) +#define MTRR_MEMTYPE_UC 0 +#define MTRR_MEMTYPE_WC 1 +#define MTRR_MEMTYPE_WT 4 +#define MTRR_MEMTYPE_WP 5 +#define MTRR_MEMTYPE_WB 6 + static inline void outl(int addr, int val) { asm volatile ("outl %1, %w0" : : "d" (addr), "a" (val)); @@ -604,9 +610,10 @@ void setup_mtrr(void) wrmsr_smp(MSR_MTRRfix4K_F0000, 0); wrmsr_smp(MSR_MTRRfix4K_F8000, 0); /* Mark 3.5-4GB as UC, anything not specified defaults to WB */ - wrmsr_smp(MTRRphysBase_MSR(0), 0xe0000000ull | 0); - wrmsr_smp(MTRRphysMask_MSR(0), ~(0x20000000ull - 1) | 0x800); - wrmsr_smp(MSR_MTRRdefType, 0xc06); + wrmsr_smp(MTRRphysBase_MSR(0), 0xe0000000 | MTRR_MEMTYPE_UC); + /* Make sure no reserved bit set to '1 in MTRRphysMask_MSR */ + wrmsr_smp(MTRRphysMask_MSR(0), (uint32_t)(~(0x20000000 - 1)) | 0x800); + wrmsr_smp(MSR_MTRRdefType, 0xc00 | MTRR_MEMTYPE_WB); } void ram_probe(void) |