SayoriOS  0.3.3
mtrr.c
1 #include "common.h"
2 #include "sys/cpuid.h"
3 #include "io/ports.h"
4 #include "sys/msr.h"
5 #include "sys/mtrr.h"
6 #include "io/tty.h"
7 
8 #define UNCACHED 0
9 #define WRITECOMBINING 1
10 #define WRITETHROUGH 4
11 #define WRITEPROTECT 5
12 #define WRITEBACK 6
13 
14 bool mtrr_is_supported = false;
15 bool mtrr_wc_available = false;
16 bool mtrr_fixed_size_available = false;
17 size_t variable_size_mtrrs = 0;
18 
19 #define CALC_MASK(size) (~(size - 1) & 0xffffffff)
20 
21 void mtrr_init() {
22  uint32_t unused, eax, edx;
23 
24  cpuid(1, unused, unused, unused, edx);
25 
26  qemu_log("%x", edx & (1 << 12));
27 
28  if(edx & (1 << 12)) {
29  mtrr_is_supported = true;
30  } else {
31  return;
32  }
33 
34  rdmsr(0xFE, eax, unused);
35 
36  variable_size_mtrrs = eax & 0xff;
37  mtrr_fixed_size_available = eax & (1 << 8) ? true : false;
38  mtrr_wc_available = eax & (1 << 10) ? true : false;
39 
40  qemu_log("Variable size MTRRs count: %d", variable_size_mtrrs);
41  qemu_log("Fixed size available: %d", mtrr_fixed_size_available);
42  qemu_log("Writecombining available: %d", mtrr_wc_available);
43 
44  for(size_t i = 0; i < variable_size_mtrrs; i++) {
45  uint32_t base, mask;
46 
47  read_mtrr(i, &base, &mask);
48 
49  qemu_log("[%d] MTRR: base: %x; mask: %x", i, base, mask);
50  }
51 }
52 
53 void list_mtrrs() {
54  tty_printf("Physical FB is: %x", getDisplayAddr());
55 
56  for(size_t i = 0; i < variable_size_mtrrs; i++) {
57  uint32_t base, mask;
58 
59  read_mtrr(i, &base, &mask);
60 
61  qemu_log("[%d] MTRR: base: %x; mask: %x", i, base, mask);
62  tty_printf("[%d] MTRR: base: %x; mask: %x\n", i, base, mask);
63  }
64 }
65 
66 uint32_t get_mtrr_index(uint32_t address) {
67  for(size_t i = 0; i < variable_size_mtrrs; i++) {
68  uint32_t base, mask;
69 
70  read_mtrr(i, &base, &mask);
71 
72  if((mask & (1 << 11)) && (base & ~0xfff) == ALIGN(address, 4096)) {
73  return i;
74  }
75  }
76 
77  return 0xffffffff;
78 }
79 
80 
81 void read_mtrr(size_t index, uint32_t* base, uint32_t* mask) {
82  uint32_t unused;
83 
84  if(index >= variable_size_mtrrs)
85  return;
86 
87  rdmsr(0x200 + (index * 2), *base, unused);
88  rdmsr(0x201 + (index * 2), *mask, unused);
89 }
90 
91 void write_mtrr(size_t index, uint32_t base, uint32_t mask) {
92  uint32_t unused = 0;
93 
94  if(index >= variable_size_mtrrs)
95  return;
96 
97  wrmsr(0x200 + (index * 2), base, unused);
98  wrmsr(0x201 + (index * 2), mask, unused);
99 }
100 
101 void write_mtrr_size(size_t index, uint32_t base, uint32_t size, size_t type) {
102  uint32_t unused = 0;
103 
104  if(index >= variable_size_mtrrs)
105  return;
106 
107  wrmsr(0x200 + (index * 2), ALIGN(base, 4096) | type, unused);
108  wrmsr(0x201 + (index * 2), CALC_MASK(ALIGN(size, 4096)) | (1 << 11), unused);
109 }
110 
111 size_t find_free_mtrr() {
112  for(size_t i = 0; i < variable_size_mtrrs; i++) {
113  uint32_t base, mask;
114 
115  read_mtrr(i, &base, &mask);
116 
117  if((mask & (1 << 11)) == 0) {
118  return i;
119  }
120  }
121 
122  return 0xffffffff; // Not found
123 }
Основные определения ядра