aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Ning <yu.ning@intel.com>2015-07-13 19:46:39 +0800
committerYu Ning <yu.ning@intel.com>2015-07-13 19:46:39 +0800
commitb47f0f3709343eb02ca5c6d2c9b609346f34e85f (patch)
tree0efd38a1bfa63930028db030bb56101d96a1a0f6
parentda066f54a0a41cf90bb0b27753dcefeb172c010c (diff)
downloadqemu-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.c13
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)