]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ux/cpu-ux.cpp
b8d9026572c20e7b8e04b809c8a7752a4e265997
[l4.git] / kernel / fiasco / src / kern / ux / cpu-ux.cpp
1 /*
2  * Fiasco-UX
3  * Architecture specific cpu init code
4  */
5
6 INTERFACE[ux]:
7
8 class Tss;
9
10 EXTENSION class Cpu
11 {
12 public:
13   static Mword kern_ds() { return _kern_ds; }
14   static Mword kern_es() { return _kern_es; }
15 private:
16   static Tss *tss asm ("CPU_TSS");
17   static int msr_dev;
18   static unsigned long _gs asm ("CPU_GS");
19   static unsigned long _fs asm ("CPU_FS");
20   static Mword _kern_ds asm ("KERN_DS");
21   static Mword _kern_es asm ("KERN_ES");
22
23   int _tid;
24 };
25
26 // -----------------------------------------------------------------------
27 IMPLEMENTATION[ux]:
28
29 #include <cerrno>
30 #include <cstdio>
31 #include <unistd.h>
32 #include <fcntl.h>
33
34 #include "div32.h"
35 #include "emulation.h"
36 #include "gdt.h"
37 #include "initcalls.h"
38 #include "processor.h"
39 #include "regdefs.h"
40 #include "tss.h"
41
42 Proc::Status volatile Proc::virtual_processor_state = 0;
43 Tss *Cpu::tss;
44 int Cpu::msr_dev = -1;
45 unsigned long Cpu::_gs; // for mp: percpu
46 unsigned long Cpu::_fs; // for mp: percpu
47 unsigned long Cpu::_kern_ds;
48 unsigned long Cpu::_kern_es;
49
50 IMPLEMENT FIASCO_INIT_CPU
51 void
52 Cpu::init()
53 {
54   identify();
55
56   // Get original es and ds to be used for RESET_KERNEL_SEGMENTS_FORCE_DS_ES
57   _kern_ds = get_ds();
58   _kern_es = get_es();
59
60   // No Sysenter Support for Fiasco-UX
61   _features &= ~FEAT_SEP;
62
63   // Determine CPU frequency
64   FILE *fp;
65   if ((fp = fopen ("/proc/cpuinfo", "r")) != NULL)
66     {
67       char buffer[128];
68       float val;
69
70       while (fgets (buffer, sizeof (buffer), fp))
71         if (sscanf (buffer, "cpu MHz%*[^:]: %f", &val) == 1)
72           {
73             _frequency    = (Unsigned64)(val * 1000) * 1000;
74             scaler_tsc_to_ns = muldiv (1 << 27, 1000000000,    _frequency);
75             scaler_tsc_to_us = muldiv (1 << 27, 32 * 1000000,  _frequency);
76             scaler_ns_to_tsc = muldiv (1 << 27, _frequency, 1000000000);
77             break;
78           }
79
80       fclose (fp);
81     }
82
83   if (this == _boot_cpu)
84     {
85       // XXX hardcoded
86       msr_dev = open("/dev/msr", O_RDWR);
87       if (msr_dev == -1)
88         msr_dev = open("/dev/cpu/0/msr", O_RDWR);
89     }
90
91   _tid = phys_id_direct();
92 }
93
94 PUBLIC
95 void
96 Cpu::print() const
97 {
98   printf ("CPU[%u:%u]: %s (%X:%X:%X:%X) Model: %s at %llu MHz\n\n",
99           id(), phys_id(),
100           vendor_str(), family(), model(), stepping(), brand(), model_str(),
101           div32(frequency(), 1000000));
102 }
103
104 PUBLIC inline
105 unsigned
106 Cpu::phys_id() const
107 { return _tid; }
108
109 PUBLIC static inline
110 void
111 Cpu::set_fast_entry (void (*)(void))
112 {}
113
114 PUBLIC static FIASCO_INIT
115 void
116 Cpu::init_tss (Address tss_mem)
117 {
118   tss = reinterpret_cast<Tss*>(tss_mem);
119   tss->_ss0 = Gdt::gdt_data_kernel;
120 }
121
122 PUBLIC static inline
123 Tss*
124 Cpu::get_tss ()
125 { return tss; }
126
127 PUBLIC static inline
128 void
129 Cpu::enable_rdpmc()
130 {
131 }
132
133 IMPLEMENT inline
134 int
135 Cpu::can_wrmsr() const
136 {
137   return msr_dev != -1;
138 }
139
140 PUBLIC static
141 Unsigned64
142 Cpu::rdmsr (Unsigned32 reg)
143 {
144   Unsigned64 msr;
145
146   if (lseek(msr_dev, reg, SEEK_SET) >= 0)
147     read(msr_dev, &msr, sizeof(msr));
148
149   return msr;
150 }
151
152 PUBLIC static inline
153 Unsigned64
154 Cpu::rdpmc (Unsigned32, Unsigned32 reg)
155 {
156   return rdmsr(reg);
157 }
158
159 PUBLIC static
160 void
161 Cpu::wrmsr (Unsigned64 msr, Unsigned32 reg)
162 {
163   if (lseek(msr_dev, reg, SEEK_SET) >= 0)
164     write(msr_dev, &msr, sizeof(msr));
165 }
166
167 PUBLIC static inline
168 void
169 Cpu::wrmsr (Unsigned32 low, Unsigned32 high, Unsigned32 reg)
170 {
171   Unsigned64 msr = ((Unsigned64)high << 32) | low;
172   wrmsr(msr, reg);
173 }
174
175 PUBLIC static inline
176 void
177 Cpu::debugctl_enable()
178 {}
179
180 PUBLIC static inline
181 void
182 Cpu::debugctl_disable()
183 {}
184
185 PUBLIC static inline
186 void
187 Cpu::set_fs(Unsigned32 val)
188 { _fs = val; }
189
190 PUBLIC static inline
191 void
192 Cpu::set_gs(Unsigned32 val)
193 { _gs = val; }
194
195 PUBLIC static inline
196 Unsigned32
197 Cpu::get_fs()
198 { return _fs; }
199
200 PUBLIC static inline
201 Unsigned32
202 Cpu::get_gs()
203 { return _gs; }
204
205 // ------------------------------------------------------------------------
206 IMPLEMENTATION[ux && !mp]:
207
208 PUBLIC static inline
209 unsigned
210 Cpu::phys_id_direct()
211 { return 0; }
212
213 // ------------------------------------------------------------------------
214 IMPLEMENTATION[ux && mp]:
215
216 PUBLIC static inline NEEDS["emulation.h"]
217 unsigned
218 Cpu::phys_id_direct()
219 { return Emulation::gettid(); }
220