2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm.h>
21 #include <palacios/vmm_extensions.h>
22 #include <palacios/vmm_msr.h>
28 #define MTRR_PHYS_BASE_0 0x200
29 #define MTRR_PHYS_MASK_0 0x201
30 #define MTRR_PHYS_BASE_1 0x202
31 #define MTRR_PHYS_MASK_1 0x203
32 #define MTRR_PHYS_BASE_2 0x204
33 #define MTRR_PHYS_MASK_2 0x205
34 #define MTRR_PHYS_BASE_3 0x206
35 #define MTRR_PHYS_MASK_3 0x207
36 #define MTRR_PHYS_BASE_4 0x208
37 #define MTRR_PHYS_MASK_4 0x209
38 #define MTRR_PHYS_BASE_5 0x20a
39 #define MTRR_PHYS_MASK_5 0x20b
40 #define MTRR_PHYS_BASE_6 0x20c
41 #define MTRR_PHYS_MASK_6 0x20d
42 #define MTRR_PHYS_BASE_7 0x20e
43 #define MTRR_PHYS_MASK_7 0x20f
45 #define MTRR_FIX_64K_00000 0x250
46 #define MTRR_FIX_16K_80000 0x258
47 #define MTRR_FIX_16K_A0000 0x259
48 #define MTRR_FIX_4K_C0000 0x268
49 #define MTRR_FIX_4K_C8000 0x269
50 #define MTRR_FIX_4K_D0000 0x26a
51 #define MTRR_FIX_4K_D8000 0x26b
52 #define MTRR_FIX_4K_E0000 0x26c
53 #define MTRR_FIX_4K_E8000 0x26d
54 #define MTRR_FIX_4K_F0000 0x26e
55 #define MTRR_FIX_4K_F8000 0x26f
59 #define MTRR_DEF_TYPE 0x2ff
85 } __attribute__((packed));
86 } __attribute__((packed));
87 } __attribute__((packed));
95 uint64_t var_reg_cnt : 8;
98 uint64_t wr_combine : 1;
100 } __attribute__((packed));
101 } __attribute__((packed));
102 } __attribute__((packed));
104 struct mtrr_def_type {
109 uint64_t def_type : 8;
111 uint64_t fixed_enable : 1;
112 uint64_t mtrr_emable : 1;
114 } __attribute__((packed));
115 } __attribute__((packed));
116 } __attribute__((packed));
119 struct mtrr_phys_base {
128 } __attribute__((packed));
129 } __attribute__((packed));
130 } __attribute__((packed));
133 struct mtrr_phys_mask {
142 } __attribute__((packed));
143 } __attribute__((packed));
144 } __attribute__((packed));
150 } __attribute__((packed));
151 } __attribute__((packed));
155 /* AMD Specific Registers */
156 #define SYSCONFIG 0xc0010010
157 #define TOP_MEM 0xc001001a
158 #define TOP_MEM2 0xc001001d
160 #define IORR_BASE0 0xc0010016
161 #define IORR_MASK0 0xc0010017
162 #define IORR_BASE1 0xc0010018
163 #define IORR_MASK1 0xc0010019
171 uint64_t mfde : 1; // 1 = enables RdMem and WrMem bits in fixed-range MTRRs
172 uint64_t mfdm : 1; // 1 = software can modify RdMem and WrMem bits
173 uint64_t mvdm : 1; // 1 = enables TOP_MEM reg and var range MTRRs
174 uint64_t tom2 : 1; // 1 = enables TOP_MEM2 reg
175 uint64_t tom2_force_wb : 1; // 1 = enables default mem type for 4GB-TOP_MEM2 range
177 } __attribute__((packed));
178 } __attribute__((packed));
179 } __attribute__((packed));
181 struct top_of_mem_reg {
187 uint64_t phys_addr : 29;
189 } __attribute__((packed));
190 } __attribute__((packed));
191 } __attribute__((packed));
200 uint64_t wrmem : 1; // 1 = writes go to memory, 0 = writes go to mmap IO
201 uint64_t rdmem : 1; // 1 = reads go to memory, 0 = reads go to mmap IO
205 } __attribute__((packed));
206 } __attribute__((packed));
207 } __attribute__((packed));
218 } __attribute__((packed));
219 } __attribute__((packed));
220 } __attribute__((packed));
222 /* Intel Specific Registers */
223 #define SMRR_PHYS_BASE 0x1f2
224 #define SMRR_PHYS_MASK 0x1f3
226 struct smrr_phys_base {
235 } __attribute__((packed));
236 } __attribute__((packed));
237 } __attribute__((packed));
239 struct smrr_phys_mask {
248 } __attribute__((packed));
249 } __attribute__((packed));
250 } __attribute__((packed));
257 struct mtrr_def_type def_type;
258 struct mtrr_phys_base bases[8];
259 struct mtrr_phys_mask masks[8];
261 struct mtrr_fixed fixed_64k;
262 struct mtrr_fixed fixed_16k[2];
263 struct mtrr_fixed fixed_4k[8];
265 /* AMD specific registers */
266 struct syscfg_reg amd_syscfg;
267 struct top_of_mem_reg amd_tom;
268 struct top_of_mem_reg amd_tom2;
270 struct iorr_base iorr_bases[2];
271 struct iorr_mask iorr_masks[2];
273 /* Intel Specific registers */
274 struct smrr_phys_base intel_smrr_base;
275 struct smrr_phys_mask intel_smrr_mask;
279 static void init_state(struct mtrr_state * state) {
280 state->pat.value = 0x0007040600070406LL;
281 state->cap.value = 0x0000000000000508LL;
283 state->amd_syscfg.value = 0x0000000000020601LL;
284 state->amd_tom.value = 0x0000000004000000LL;
289 static int mtrr_cap_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
290 struct mtrr_state * state = (struct mtrr_state *)priv_data;
291 dst->value = state->cap.value;
295 static int mtrr_cap_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
296 struct mtrr_state * state = (struct mtrr_state *)priv_data;
297 state->cap.value = src.value;
301 static int pat_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
302 struct mtrr_state * state = (struct mtrr_state *)priv_data;
303 dst->value = state->pat.value;
307 static int pat_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
308 struct mtrr_state * state = (struct mtrr_state *)priv_data;
309 state->pat.value = src.value;
313 static int def_type_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
314 struct mtrr_state * state = (struct mtrr_state *)priv_data;
315 dst->value = state->def_type.value;
319 static int def_type_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
320 struct mtrr_state * state = (struct mtrr_state *)priv_data;
321 state->def_type.value = src.value;
326 static int mtrr_phys_base_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
327 struct mtrr_state * state = (struct mtrr_state *)priv_data;
328 int base_index = (msr - MTRR_PHYS_BASE_0) / 2;
329 dst->value = state->bases[base_index].value;
333 static int mtrr_phys_base_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
334 struct mtrr_state * state = (struct mtrr_state *)priv_data;
335 int base_index = (msr - MTRR_PHYS_BASE_0) / 2;
336 state->bases[base_index].value = src.value;
340 static int mtrr_phys_mask_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
341 struct mtrr_state * state = (struct mtrr_state *)priv_data;
342 int mask_index = (msr - MTRR_PHYS_MASK_0) / 2;
343 dst->value = state->masks[mask_index].value;
347 static int mtrr_phys_mask_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
348 struct mtrr_state * state = (struct mtrr_state *)priv_data;
349 int mask_index = (msr - MTRR_PHYS_MASK_0) / 2;
350 state->masks[mask_index].value = src.value;
354 static int mtrr_fix_64k_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
355 struct mtrr_state * state = (struct mtrr_state *)priv_data;
356 dst->value = state->fixed_64k.value;
360 static int mtrr_fix_64k_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
361 struct mtrr_state * state = (struct mtrr_state *)priv_data;
362 state->fixed_64k.value = src.value;
366 static int mtrr_fix_16k_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
367 struct mtrr_state * state = (struct mtrr_state *)priv_data;
368 int index = msr - MTRR_FIX_16K_80000;
369 dst->value = state->fixed_16k[index].value;
373 static int mtrr_fix_16k_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
374 struct mtrr_state * state = (struct mtrr_state *)priv_data;
375 int index = msr - MTRR_FIX_16K_80000;
376 state->fixed_16k[index].value = src.value;
380 static int mtrr_fix_4k_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
381 struct mtrr_state * state = (struct mtrr_state *)priv_data;
382 int index = msr - MTRR_FIX_4K_C0000;
383 dst->value = state->fixed_4k[index].value;
387 static int mtrr_fix_4k_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
388 struct mtrr_state * state = (struct mtrr_state *)priv_data;
389 int index = msr - MTRR_FIX_4K_C0000;
390 state->fixed_4k[index].value = src.value;
394 /* AMD specific registers */
395 static int amd_syscfg_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
396 struct mtrr_state * state = (struct mtrr_state *)priv_data;
397 dst->value = state->amd_syscfg.value;
401 static int amd_syscfg_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
402 struct mtrr_state * state = (struct mtrr_state *)priv_data;
403 state->amd_syscfg.value = src.value;
407 static int amd_top_mem_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
408 struct mtrr_state * state = (struct mtrr_state *)priv_data;
410 if (msr == TOP_MEM) {
411 dst->value = state->amd_tom.value;
412 } else if (msr == TOP_MEM2) {
413 dst->value = state->amd_tom2.value;
419 static int amd_top_mem_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
420 struct mtrr_state * state = (struct mtrr_state *)priv_data;
422 if (msr == TOP_MEM) {
423 state->amd_tom.value = src.value;
424 } else if (msr == TOP_MEM2) {
425 state->amd_tom2.value = src.value;
432 static int amd_iorr_base_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
433 struct mtrr_state * state = (struct mtrr_state *)priv_data;
434 int base_index = (msr - IORR_BASE0) / 2;
435 dst->value = state->iorr_bases[base_index].value;
439 static int amd_iorr_base_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
440 struct mtrr_state * state = (struct mtrr_state *)priv_data;
441 int base_index = (msr - IORR_BASE0) / 2;
442 state->iorr_bases[base_index].value = src.value;
446 static int amd_iorr_mask_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
447 struct mtrr_state * state = (struct mtrr_state *)priv_data;
448 int mask_index = (msr - IORR_MASK0) / 2;
449 dst->value = state->iorr_masks[mask_index].value;
453 static int amd_iorr_mask_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
454 struct mtrr_state * state = (struct mtrr_state *)priv_data;
455 int mask_index = (msr - IORR_MASK0) / 2;
456 state->iorr_masks[mask_index].value = src.value;
461 static int intel_smrr_base_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
462 struct mtrr_state * state = (struct mtrr_state *)priv_data;
463 dst->value = state->intel_smrr_base.value;
467 static int intel_smrr_base_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
468 struct mtrr_state * state = (struct mtrr_state *)priv_data;
469 state->intel_smrr_base.value = src.value;
473 static int intel_smrr_mask_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
474 struct mtrr_state * state = (struct mtrr_state *)priv_data;
475 dst->value = state->intel_smrr_mask.value;
479 static int intel_smrr_mask_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
480 struct mtrr_state * state = (struct mtrr_state *)priv_data;
481 state->intel_smrr_mask.value = src.value;
486 static int deinit_mtrrs(struct v3_vm_info * vm, void * priv_data) {
487 struct mtrr_state * state = (struct mtrr_state *)priv_data;
489 v3_unhook_msr(vm, MTRR_CAP);
490 v3_unhook_msr(vm, PAT);
491 v3_unhook_msr(vm, MTRR_DEF_TYPE);
493 v3_unhook_msr(vm, MTRR_PHYS_BASE_0);
494 v3_unhook_msr(vm, MTRR_PHYS_BASE_1);
495 v3_unhook_msr(vm, MTRR_PHYS_BASE_2);
496 v3_unhook_msr(vm, MTRR_PHYS_BASE_3);
497 v3_unhook_msr(vm, MTRR_PHYS_BASE_4);
498 v3_unhook_msr(vm, MTRR_PHYS_BASE_5);
499 v3_unhook_msr(vm, MTRR_PHYS_BASE_6);
500 v3_unhook_msr(vm, MTRR_PHYS_BASE_7);
501 v3_unhook_msr(vm, MTRR_PHYS_MASK_0);
502 v3_unhook_msr(vm, MTRR_PHYS_MASK_1);
503 v3_unhook_msr(vm, MTRR_PHYS_MASK_2);
504 v3_unhook_msr(vm, MTRR_PHYS_MASK_3);
505 v3_unhook_msr(vm, MTRR_PHYS_MASK_4);
506 v3_unhook_msr(vm, MTRR_PHYS_MASK_5);
507 v3_unhook_msr(vm, MTRR_PHYS_MASK_6);
508 v3_unhook_msr(vm, MTRR_PHYS_MASK_7);
510 v3_unhook_msr(vm, MTRR_FIX_64K_00000);
511 v3_unhook_msr(vm, MTRR_FIX_16K_80000);
512 v3_unhook_msr(vm, MTRR_FIX_16K_A0000);
513 v3_unhook_msr(vm, MTRR_FIX_4K_C0000);
514 v3_unhook_msr(vm, MTRR_FIX_4K_C8000);
515 v3_unhook_msr(vm, MTRR_FIX_4K_D0000);
516 v3_unhook_msr(vm, MTRR_FIX_4K_D8000);
517 v3_unhook_msr(vm, MTRR_FIX_4K_E0000);
518 v3_unhook_msr(vm, MTRR_FIX_4K_E8000);
519 v3_unhook_msr(vm, MTRR_FIX_4K_F0000);
520 v3_unhook_msr(vm, MTRR_FIX_4K_F8000);
523 v3_unhook_msr(vm, SYSCONFIG);
524 v3_unhook_msr(vm, TOP_MEM);
525 v3_unhook_msr(vm, TOP_MEM2);
527 v3_unhook_msr(vm, IORR_BASE0);
528 v3_unhook_msr(vm, IORR_BASE1);
529 v3_unhook_msr(vm, IORR_MASK0);
530 v3_unhook_msr(vm, IORR_MASK1);
533 v3_unhook_msr(vm, SMRR_PHYS_BASE);
534 v3_unhook_msr(vm, SMRR_PHYS_MASK);
542 static int init_mtrrs(struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
543 struct mtrr_state * state = NULL;
546 state = V3_Malloc(sizeof(struct mtrr_state));
549 PrintError("Cannot allocate in initializing MTRRs\n");
554 memset(state, 0, sizeof(struct mtrr_state));
561 ret |= v3_hook_msr(vm, MTRR_CAP, mtrr_cap_read, mtrr_cap_write, state);
562 ret |= v3_hook_msr(vm, PAT, pat_read, pat_write, state);
563 ret |= v3_hook_msr(vm, MTRR_DEF_TYPE, def_type_read, def_type_write, state);
565 ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_0, mtrr_phys_base_read, mtrr_phys_base_write, state);
566 ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_1, mtrr_phys_base_read, mtrr_phys_base_write, state);
567 ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_2, mtrr_phys_base_read, mtrr_phys_base_write, state);
568 ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_3, mtrr_phys_base_read, mtrr_phys_base_write, state);
569 ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_4, mtrr_phys_base_read, mtrr_phys_base_write, state);
570 ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_5, mtrr_phys_base_read, mtrr_phys_base_write, state);
571 ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_6, mtrr_phys_base_read, mtrr_phys_base_write, state);
572 ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_7, mtrr_phys_base_read, mtrr_phys_base_write, state);
573 ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_0, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
574 ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_1, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
575 ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_2, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
576 ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_3, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
577 ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_4, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
578 ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_5, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
579 ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_6, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
580 ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_7, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
582 ret |= v3_hook_msr(vm, MTRR_FIX_64K_00000, mtrr_fix_64k_read, mtrr_fix_64k_write, state);
583 ret |= v3_hook_msr(vm, MTRR_FIX_16K_80000, mtrr_fix_16k_read, mtrr_fix_16k_write, state);
584 ret |= v3_hook_msr(vm, MTRR_FIX_16K_A0000, mtrr_fix_16k_read, mtrr_fix_16k_write, state);
585 ret |= v3_hook_msr(vm, MTRR_FIX_4K_C0000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
586 ret |= v3_hook_msr(vm, MTRR_FIX_4K_C8000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
587 ret |= v3_hook_msr(vm, MTRR_FIX_4K_D0000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
588 ret |= v3_hook_msr(vm, MTRR_FIX_4K_D8000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
589 ret |= v3_hook_msr(vm, MTRR_FIX_4K_E0000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
590 ret |= v3_hook_msr(vm, MTRR_FIX_4K_E8000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
591 ret |= v3_hook_msr(vm, MTRR_FIX_4K_F0000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
592 ret |= v3_hook_msr(vm, MTRR_FIX_4K_F8000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
595 ret |= v3_hook_msr(vm, SYSCONFIG, amd_syscfg_read, amd_syscfg_write, state);
596 ret |= v3_hook_msr(vm, TOP_MEM, amd_top_mem_read, amd_top_mem_write, state);
597 ret |= v3_hook_msr(vm, TOP_MEM2, amd_top_mem_read, amd_top_mem_write, state);
599 ret |= v3_hook_msr(vm, IORR_BASE0, amd_iorr_base_read, amd_iorr_base_write, state);
600 ret |= v3_hook_msr(vm, IORR_BASE1, amd_iorr_base_read, amd_iorr_base_write, state);
601 ret |= v3_hook_msr(vm, IORR_MASK0, amd_iorr_mask_read, amd_iorr_mask_write, state);
602 ret |= v3_hook_msr(vm, IORR_MASK1, amd_iorr_mask_read, amd_iorr_mask_write, state);
606 ret |= v3_hook_msr(vm, SMRR_PHYS_BASE, intel_smrr_base_read, intel_smrr_base_write, state);
607 ret |= v3_hook_msr(vm, SMRR_PHYS_MASK, intel_smrr_mask_read, intel_smrr_mask_write, state);
610 PrintError("Failed to hook all MTRR MSRs. Aborting...\n");
611 deinit_mtrrs(vm, state);
622 static struct v3_extension_impl mtrr_impl = {
625 .deinit = deinit_mtrrs,
632 register_extension(&mtrr_impl);