1 IMPLEMENTATION [ia32,ux]:
3 #include "mem_layout.h"
8 Cpu::stack_align(Mword stack)
9 { return stack & ~0x3; }
14 Cpu::ns_to_tsc(Unsigned64 ns) const
19 ("movl %%edx, %%ecx \n\t"
21 "movl %%ecx, %%eax \n\t"
22 "movl %%edx, %%ecx \n\t"
24 "addl %%ecx, %%eax \n\t"
26 "shld $5, %%eax, %%edx \n\t"
28 :"=A" (tsc), "=&c" (dummy)
29 : "0" (ns), "b" (scaler_ns_to_tsc)
36 Cpu::tsc_to_ns(Unsigned64 tsc) const
41 ("movl %%edx, %%ecx \n\t"
43 "movl %%ecx, %%eax \n\t"
44 "movl %%edx, %%ecx \n\t"
46 "addl %%ecx, %%eax \n\t"
48 "shld $5, %%eax, %%edx \n\t"
50 :"=A" (ns), "=&c" (dummy)
51 : "0" (tsc), "b" (scaler_tsc_to_ns)
58 Cpu::tsc_to_us(Unsigned64 tsc) const
63 ("movl %%edx, %%ecx \n\t"
65 "movl %%ecx, %%eax \n\t"
66 "movl %%edx, %%ecx \n\t"
68 "addl %%ecx, %%eax \n\t"
70 :"=A" (us), "=&c" (dummy)
71 : "0" (tsc), "S" (scaler_tsc_to_us)
79 Cpu::tsc_to_s_and_ns(Unsigned64 tsc, Unsigned32 *s, Unsigned32 *ns) const
84 "movl %%edx, %%ecx \n\t"
86 "movl %%ecx, %%eax \n\t"
87 "movl %%edx, %%ecx \n\t"
89 "addl %%ecx, %%eax \n\t"
91 "movl $1000000000, %%ecx \n\t"
92 "shld $5, %%eax, %%edx \n\t"
95 :"=a" (*s), "=d" (*ns), "=&c" (dummy)
96 : "A" (tsc), "g" (scaler_tsc_to_ns)
106 asm volatile ("rdtsc" : "=A" (tsc));
113 { Unsigned32 efl; asm volatile ("pushfl ; popl %0" : "=r"(efl)); return efl; }
117 Cpu::set_flags(Unsigned32 efl)
118 { asm volatile ("pushl %0 ; popfl" : : "rm" (efl) : "memory"); }
120 IMPLEMENT inline NEEDS["tss.h"]
122 Cpu::kernel_sp() const
123 { return *reinterpret_cast<Address volatile *>(&get_tss()->_esp0); }
125 //----------------------------------------------------------------------------
126 IMPLEMENTATION[ia32]:
132 asm volatile("ljmp %0, $1f ; 1:"
133 : : "i"(Gdt::gdt_code_kernel | Gdt::Selector_kernel));
136 extern "C" void entry_vec08_dbf();
137 extern "C" Address dbf_stack_top;
139 PUBLIC FIASCO_INIT_CPU
141 Cpu::init_tss_dbf(Address tss_dbf_mem, Address kdir)
143 tss_dbf = reinterpret_cast<Tss*>(tss_dbf_mem);
145 gdt->set_entry_byte(Gdt::gdt_tss_dbf / 8, tss_dbf_mem, sizeof(Tss) - 1,
146 Gdt_entry::Access_kernel | Gdt_entry::Access_tss |
147 Gdt_entry::Accessed, 0);
149 tss_dbf->_cs = Gdt::gdt_code_kernel;
150 tss_dbf->_ss = Gdt::gdt_data_kernel;
151 tss_dbf->_ds = Gdt::gdt_data_kernel;
152 tss_dbf->_es = Gdt::gdt_data_kernel;
153 tss_dbf->_fs = Gdt::gdt_data_kernel;
154 tss_dbf->_gs = Gdt::gdt_data_kernel;
155 tss_dbf->_eip = (Address)entry_vec08_dbf;
156 tss_dbf->_esp = (Address)&dbf_stack_top;
158 tss_dbf->_eflags = 0x00000082;
159 tss_dbf->_cr3 = kdir;
160 tss_dbf->_io_bit_map_offset = 0x8000;
164 PUBLIC FIASCO_INIT_CPU
166 Cpu::init_tss(Address tss_mem, size_t tss_size)
168 tss = reinterpret_cast<Tss*>(tss_mem);
170 gdt->set_entry_byte(Gdt::gdt_tss / 8, tss_mem, tss_size,
171 Gdt_entry::Access_kernel | Gdt_entry::Access_tss, 0);
173 tss->set_ss0(Gdt::gdt_data_kernel);
174 tss->_io_bit_map_offset = Mem_layout::Io_bitmap - tss_mem;
178 PUBLIC FIASCO_INIT_CPU
180 Cpu::init_gdt(Address gdt_mem, Address user_max)
182 gdt = reinterpret_cast<Gdt*>(gdt_mem);
184 // make sure kernel cs/ds and user cs/ds are placed in the same
185 // cache line, respectively; pre-set all "accessed" flags so that
186 // the CPU doesn't need to do this later
188 gdt->set_entry_4k(Gdt::gdt_code_kernel / 8, 0, 0xffffffff,
189 Gdt_entry::Access_kernel |
190 Gdt_entry::Access_code_read |
191 Gdt_entry::Accessed, Gdt_entry::Size_32);
192 gdt->set_entry_4k(Gdt::gdt_data_kernel / 8, 0, 0xffffffff,
193 Gdt_entry::Access_kernel |
194 Gdt_entry::Access_data_write |
195 Gdt_entry::Accessed, Gdt_entry::Size_32);
196 gdt->set_entry_4k(Gdt::gdt_code_user / 8, 0, user_max,
197 Gdt_entry::Access_user |
198 Gdt_entry::Access_code_read |
199 Gdt_entry::Accessed, Gdt_entry::Size_32);
200 gdt->set_entry_4k(Gdt::gdt_data_user / 8, 0, user_max,
201 Gdt_entry::Access_user |
202 Gdt_entry::Access_data_write |
203 Gdt_entry::Accessed, Gdt_entry::Size_32);