Commit 165d9b82eb8c877ee691a7b7bde5930bc2d07037

Authored by aliguori
1 parent 249aa745

MTRR support on x86 (Carl-Daniel Hailfinger)

The current codebase ignores MTRR (Memory Type Range Register)
configuration writes and reads because Qemu does not implement caching.
All BIOS/firmware in know of for x86 do implement a mode called
Cache-as-RAM (CAR) which locks down the CPU cache lines and uses the CPU
cache like RAM before RAM is enabled. Qemu assumes RAM is accessible
from the start, but it would be nice to be able to run real
BIOS/firmware in Qemu. For that, we need CAR support and for CAR support
we have to support MTRRs.

This patch is a first step in that direction. MTRRs are MSRs supported
by all recent x86 CPUs, even old i586. Besides influencing cache, the
MTRRs can be written and read back, so discarding MTRR writes violates
the expectations of existing code out there.

An added benefit of this patch is that it fixes the following Linux
kernel error message present in recent kernels (provided the BIOS has
the recent MTRR patches applied):
 ------------[ cut here ]------------
WARNING: at arch/x86/kernel/cpu/mtrr/main.c:1500 mtrr_trim_uncached_memory+0x382/0x384()
WARNING: strange, CPU MTRRs all blank?
Modules linked in:
Supported: Yes
Pid: 0, comm: swapper Not tainted 2.6.27.7-9-default #1
 [<c0106570>] dump_trace+0x6b/0x249
 [<c01070a5>] show_trace+0x20/0x39
 [<c0343c02>] dump_stack+0x71/0x76
 [<c012acb2>] warn_slowpath+0x6f/0x90
 [<c0542f8f>] mtrr_trim_uncached_memory+0x382/0x384
 [<c053f24d>] setup_arch+0x40d/0x639
 [<c053a6ac>] start_kernel+0x6b/0x31f
 =======================
 ---[ end trace 4eaa2a86a8e2da22 ]---

Handle common x86 MTRR reads and writes, but don't act on them.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6449 c046a42c-6fe2-441c-8c8c-71466251a162
target-i386/cpu.h
... ... @@ -261,8 +261,25 @@
261 261  
262 262 #define MSR_IA32_PERF_STATUS 0x198
263 263  
  264 +#define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg))
  265 +#define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1)
  266 +
  267 +#define MSR_MTRRfix64K_00000 0x250
  268 +#define MSR_MTRRfix16K_80000 0x258
  269 +#define MSR_MTRRfix16K_A0000 0x259
  270 +#define MSR_MTRRfix4K_C0000 0x268
  271 +#define MSR_MTRRfix4K_C8000 0x269
  272 +#define MSR_MTRRfix4K_D0000 0x26a
  273 +#define MSR_MTRRfix4K_D8000 0x26b
  274 +#define MSR_MTRRfix4K_E0000 0x26c
  275 +#define MSR_MTRRfix4K_E8000 0x26d
  276 +#define MSR_MTRRfix4K_F0000 0x26e
  277 +#define MSR_MTRRfix4K_F8000 0x26f
  278 +
264 279 #define MSR_PAT 0x277
265 280  
  281 +#define MSR_MTRRdefType 0x2ff
  282 +
266 283 #define MSR_EFER 0xc0000080
267 284  
268 285 #define MSR_EFER_SCE (1 << 0)
... ... @@ -629,6 +646,14 @@ typedef struct CPUX86State {
629 646 uint32_t cpuid_ext3_features;
630 647 uint32_t cpuid_apic_id;
631 648  
  649 + /* MTRRs */
  650 + uint64_t mtrr_fixed[11];
  651 + uint64_t mtrr_deftype;
  652 + struct {
  653 + uint64_t base;
  654 + uint64_t mask;
  655 + } mtrr_var[8];
  656 +
632 657 #ifdef USE_KQEMU
633 658 int kqemu_enabled;
634 659 int last_io_time;
... ... @@ -805,7 +830,7 @@ static inline int cpu_get_time_fast(void)
805 830 #define cpu_signal_handler cpu_x86_signal_handler
806 831 #define cpu_list x86_cpu_list
807 832  
808   -#define CPU_SAVE_VERSION 7
  833 +#define CPU_SAVE_VERSION 8
809 834  
810 835 /* MMU modes definitions */
811 836 #define MMU_MODE0_SUFFIX _kernel
... ...
target-i386/op_helper.c
... ... @@ -3050,6 +3050,46 @@ void helper_wrmsr(void)
3050 3050 env->kernelgsbase = val;
3051 3051 break;
3052 3052 #endif
  3053 + case MSR_MTRRphysBase(0):
  3054 + case MSR_MTRRphysBase(1):
  3055 + case MSR_MTRRphysBase(2):
  3056 + case MSR_MTRRphysBase(3):
  3057 + case MSR_MTRRphysBase(4):
  3058 + case MSR_MTRRphysBase(5):
  3059 + case MSR_MTRRphysBase(6):
  3060 + case MSR_MTRRphysBase(7):
  3061 + env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base = val;
  3062 + break;
  3063 + case MSR_MTRRphysMask(0):
  3064 + case MSR_MTRRphysMask(1):
  3065 + case MSR_MTRRphysMask(2):
  3066 + case MSR_MTRRphysMask(3):
  3067 + case MSR_MTRRphysMask(4):
  3068 + case MSR_MTRRphysMask(5):
  3069 + case MSR_MTRRphysMask(6):
  3070 + case MSR_MTRRphysMask(7):
  3071 + env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask = val;
  3072 + break;
  3073 + case MSR_MTRRfix64K_00000:
  3074 + env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix64K_00000] = val;
  3075 + break;
  3076 + case MSR_MTRRfix16K_80000:
  3077 + case MSR_MTRRfix16K_A0000:
  3078 + env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1] = val;
  3079 + break;
  3080 + case MSR_MTRRfix4K_C0000:
  3081 + case MSR_MTRRfix4K_C8000:
  3082 + case MSR_MTRRfix4K_D0000:
  3083 + case MSR_MTRRfix4K_D8000:
  3084 + case MSR_MTRRfix4K_E0000:
  3085 + case MSR_MTRRfix4K_E8000:
  3086 + case MSR_MTRRfix4K_F0000:
  3087 + case MSR_MTRRfix4K_F8000:
  3088 + env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3] = val;
  3089 + break;
  3090 + case MSR_MTRRdefType:
  3091 + env->mtrr_deftype = val;
  3092 + break;
3053 3093 default:
3054 3094 /* XXX: exception ? */
3055 3095 break;
... ... @@ -3122,6 +3162,46 @@ void helper_rdmsr(void)
3122 3162 }
3123 3163 break;
3124 3164 #endif
  3165 + case MSR_MTRRphysBase(0):
  3166 + case MSR_MTRRphysBase(1):
  3167 + case MSR_MTRRphysBase(2):
  3168 + case MSR_MTRRphysBase(3):
  3169 + case MSR_MTRRphysBase(4):
  3170 + case MSR_MTRRphysBase(5):
  3171 + case MSR_MTRRphysBase(6):
  3172 + case MSR_MTRRphysBase(7):
  3173 + val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base;
  3174 + break;
  3175 + case MSR_MTRRphysMask(0):
  3176 + case MSR_MTRRphysMask(1):
  3177 + case MSR_MTRRphysMask(2):
  3178 + case MSR_MTRRphysMask(3):
  3179 + case MSR_MTRRphysMask(4):
  3180 + case MSR_MTRRphysMask(5):
  3181 + case MSR_MTRRphysMask(6):
  3182 + case MSR_MTRRphysMask(7):
  3183 + val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask;
  3184 + break;
  3185 + case MSR_MTRRfix64K_00000:
  3186 + val = env->mtrr_fixed[0];
  3187 + break;
  3188 + case MSR_MTRRfix16K_80000:
  3189 + case MSR_MTRRfix16K_A0000:
  3190 + val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1];
  3191 + break;
  3192 + case MSR_MTRRfix4K_C0000:
  3193 + case MSR_MTRRfix4K_C8000:
  3194 + case MSR_MTRRfix4K_D0000:
  3195 + case MSR_MTRRfix4K_D8000:
  3196 + case MSR_MTRRfix4K_E0000:
  3197 + case MSR_MTRRfix4K_E8000:
  3198 + case MSR_MTRRfix4K_F0000:
  3199 + case MSR_MTRRfix4K_F8000:
  3200 + val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3];
  3201 + break;
  3202 + case MSR_MTRRdefType:
  3203 + val = env->mtrr_deftype;
  3204 + break;
3125 3205 default:
3126 3206 /* XXX: exception ? */
3127 3207 val = 0;
... ...