00001
00002
00003 #ifndef cpu_h
00004 #define cpu_h
00005
00006 #include "types.h"
00007 #include "initcalls.h"
00008
00009 #include "l4_types.h"
00010 #include "initcalls.h"
00011
00012
00013
00014
00015
00016
00017 class Gdt;
00018 class Tss;
00019
00020 class Cpu
00021 {
00022 public:
00023
00024 enum Vendor
00025 {
00026 Vendor_unknown = 0,
00027 Vendor_intel,
00028 Vendor_amd,
00029 Vendor_cyrix,
00030 Vendor_via,
00031 Vendor_umc,
00032 Vendor_nexgen,
00033 Vendor_rise,
00034 Vendor_transmeta,
00035 Vendor_sis,
00036 Vensor_nsc
00037 };
00038
00039 enum CacheTLB
00040 {
00041 Cache_unknown = 0,
00042 Cache_l1_data,
00043 Cache_l1_inst,
00044 Cache_l1_trace,
00045 Cache_l2,
00046 Cache_l3,
00047 Tlb_data_4k,
00048 Tlb_inst_4k,
00049 Tlb_data_4M,
00050 Tlb_inst_4M,
00051 Tlb_data_4k_4M,
00052 Tlb_inst_4k_4M,
00053 };
00054
00055 enum
00056 {
00057 Ldt_entry_size = 8,
00058 };
00059
00060 enum Local_features
00061 {
00062 Lf_rdpmc = 0x00000001,
00063 Lf_rdpmc32 = 0x00000002,
00064 };
00065
00066 static void init();
00067 static Unsigned64 time_us();
00068 static int can_wrmsr();
00069
00070 private:
00071
00072 struct Vendor_table {
00073 Unsigned32 vendor_mask;
00074 Unsigned32 vendor_code;
00075 Unsigned16 l2_cache;
00076 char vendor_string[32];
00077 } __attribute__((packed));
00078
00079 struct Cache_table {
00080 Unsigned8 desc;
00081 Unsigned8 level;
00082 Unsigned16 size;
00083 Unsigned8 asso;
00084 Unsigned8 line_size;
00085 };
00086
00087 static Unsigned64 _frequency;
00088 static Unsigned32 _version;
00089 static Unsigned32 _brand;
00090 static Unsigned32 _features;
00091 static Unsigned32 _ext_features;
00092 static Unsigned32 _ext_amd_features;
00093 static Unsigned32 _local_features;
00094
00095 static Unsigned16 _inst_tlb_4k_entries;
00096 static Unsigned16 _data_tlb_4k_entries;
00097 static Unsigned16 _inst_tlb_4m_entries;
00098 static Unsigned16 _data_tlb_4m_entries;
00099 static Unsigned16 _inst_tlb_4k_4m_entries;
00100 static Unsigned16 _data_tlb_4k_4m_entries;
00101 static Unsigned16 _l2_inst_tlb_4k_entries;
00102 static Unsigned16 _l2_data_tlb_4k_entries;
00103 static Unsigned16 _l2_inst_tlb_4m_entries;
00104 static Unsigned16 _l2_data_tlb_4m_entries;
00105
00106 static Unsigned16 _l1_trace_cache_size;
00107 static Unsigned16 _l1_trace_cache_asso;
00108
00109 static Unsigned16 _l1_data_cache_size;
00110 static Unsigned16 _l1_data_cache_asso;
00111 static Unsigned16 _l1_data_cache_line_size;
00112
00113 static Unsigned16 _l1_inst_cache_size;
00114 static Unsigned16 _l1_inst_cache_asso;
00115 static Unsigned16 _l1_inst_cache_line_size;
00116
00117 static Unsigned16 _l2_cache_size;
00118 static Unsigned16 _l2_cache_asso;
00119 static Unsigned16 _l2_cache_line_size;
00120
00121 static Vendor _vendor;
00122 static char _model_str[32];
00123
00124 static Vendor_table const intel_table[];
00125 static Vendor_table const amd_table[];
00126 static Vendor_table const cyrix_table[];
00127 static Vendor_table const via_table[];
00128 static Vendor_table const umc_table[];
00129 static Vendor_table const nexgen_table[];
00130 static Vendor_table const rise_table[];
00131 static Vendor_table const transmeta_table[];
00132 static Vendor_table const sis_table[];
00133 static Vendor_table const nsc_table[];
00134
00135 static Cache_table const intel_cache_table[];
00136
00137 static char * const vendor_ident[];
00138 static Vendor_table const * const vendor_table[];
00139
00140 static Unsigned32 scaler_tsc_to_ns;
00141 static Unsigned32 scaler_tsc_to_us;
00142 static Unsigned32 scaler_ns_to_tsc;
00143 private:
00144
00145 public:
00146 enum Lbr
00147 {
00148 LBR_UNINITIALIZED = 0,
00149 LBR_NONE,
00150 LBR_P6,
00151 LBR_P4,
00152 };
00153
00154 private:
00155 static Lbr lbr asm ("CPU_LBR");
00156 typedef void (Sysenter)(void);
00157 static Sysenter *current_sysenter asm ("CURRENT_SYSENTER");
00158 static Gdt *gdt asm ("CPU_GDT");
00159 static Tss *tss asm ("CPU_TSS");
00160 static Tss *tss_dbf;
00161
00162 public:
00163 static inline char const * vendor_str();
00164
00165 static inline char const* model_str();
00166
00167 static inline Cpu::Vendor const vendor();
00168
00169 static inline unsigned int const family();
00170
00171 static inline unsigned int const model();
00172
00173 static inline unsigned int const stepping();
00174
00175 static inline unsigned int const type();
00176
00177 static inline Unsigned64 frequency();
00178
00179 static inline unsigned int const brand();
00180
00181 static inline unsigned int const features();
00182
00183 static inline unsigned int const ext_features();
00184
00185 static inline unsigned int const ext_amd_features();
00186
00187 static inline unsigned int const local_features();
00188
00189 static inline bool have_superpages();
00190
00191 static inline bool have_tsc();
00192
00193 static inline bool have_sysenter();
00194
00201 static FIASCO_INIT void identify();
00202
00203 static inline Unsigned32 muldiv(Unsigned32 val, Unsigned32 mul, Unsigned32 div);
00204
00205 static inline Unsigned64 ns_to_tsc(Unsigned64 ns);
00206
00207 static inline Unsigned64 tsc_to_ns(Unsigned64 tsc);
00208
00209 static inline Unsigned64 tsc_to_us(Unsigned64 tsc);
00210
00211 static inline void tsc_to_s_and_ns(Unsigned64 tsc, Unsigned32 *s, Unsigned32 *ns);
00212
00213 static inline void busy_wait_ns(Unsigned64 ns);
00214
00215 static inline Unsigned64 rdtsc(void);
00216
00217 static inline Unsigned32 get_scaler_tsc_to_ns();
00218
00219 static inline Unsigned32 get_scaler_tsc_to_us();
00220
00221 static inline Unsigned32 get_scaler_ns_to_tsc();
00222
00223 static inline Unsigned32 get_flags();
00224
00225 static inline void set_flags(Unsigned32 efl);
00226
00227 static inline Unsigned32 get_es();
00228
00229 static inline Unsigned32 get_ss();
00230
00231 static inline Unsigned32 get_fs();
00232
00233 static inline Unsigned32 get_gs();
00234
00235 static inline void set_ds(Unsigned32 val);
00236
00237 static inline void set_es(Unsigned32 val);
00238
00239 static inline void set_fs(Unsigned32 val);
00240
00241 static inline void set_gs(Unsigned32 val);
00242
00243 static void show_cache_tlb_info(const char *indent);
00244
00245 static inline void memcpy_bytes(void *dst, void const *src, size_t n);
00246
00247 static inline void memcpy_mwords(void *dst, void const *src, size_t n);
00248
00249 static inline void memcpy_bytes_fs(void *dst, void const *src, size_t n);
00250
00251 static inline void memcpy_mwords_fs(void *dst, void const *src, size_t n);
00252
00253 static inline void set_cr0(Unsigned32 val);
00254
00255 static inline void set_pdbr(Address addr);
00256
00257 static inline void set_cr4(Unsigned32 val);
00258
00259 static inline void set_ldt(Unsigned16 val);
00260
00261 static inline void set_cs();
00262
00263 static inline void set_ss(Unsigned32 val);
00264
00265 static inline void set_tr(Unsigned16 val);
00266
00267 static inline Mword get_cr0();
00268
00269 static inline Address get_pdbr();
00270
00271 static inline Mword get_cr4();
00272
00273 static inline Unsigned16 get_ldt();
00274
00275 static inline Unsigned16 get_tr();
00276
00277 static inline Unsigned64 rdmsr(Unsigned32 reg);
00278
00279 static inline Unsigned64 rdpmc(Unsigned32 idx, Unsigned32);
00280
00281 static inline void wrmsr(Unsigned32 low, Unsigned32 high, Unsigned32 reg);
00282
00283 static inline void wrmsr(Unsigned64 msr, Unsigned32 reg);
00284
00285 static inline void enable_rdpmc();
00286
00287 static Cpu::Lbr const lbr_type();
00288
00289 static inline void enable_lbr(void);
00290
00291 static inline void disable_lbr(void);
00292
00293 static FIASCO_INIT void init_sysenter(Address kernel_esp);
00294
00295 static void set_sysenter(void (*func)(void));
00296
00297 static void get_sysenter(void (**func)(void));
00298
00299 static FIASCO_INIT void init_gdt(Address gdt_mem, Address user_max);
00300
00301 static FIASCO_INIT void init_tss(Address tss_mem, size_t tss_size);
00302
00303 static FIASCO_INIT void init_tss_dbf(Address tss_dbf_mem, Address kdir);
00304
00305 static inline void set_gdt();
00306
00307 static inline void set_tss();
00308
00309 static inline Gdt* get_gdt();
00310
00311 static inline Tss* get_tss();
00312
00313 static inline void enable_ldt(Address addr, int size);
00314
00315 private:
00316 static inline FIASCO_INIT void cpuid(Unsigned32 const mode, Unsigned32 *const eax, Unsigned32 *const ebx, Unsigned32 *const ecx, Unsigned32 *const edx);
00317
00318 static FIASCO_INIT void cache_tlb_intel();
00319
00320 static FIASCO_INIT void cache_tlb_l1();
00321
00322 static FIASCO_INIT void cache_tlb_l2(Cpu::Vendor vendor);
00323
00324 static FIASCO_INIT void set_model_str(Cpu::Vendor const vendor, unsigned const version, Unsigned16 const l2_cache);
00325
00326
00327 static FIASCO_INIT void calibrate_tsc();
00328 };
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 #include "gdt.h"
00340 #include "processor.h"
00341 #include "regdefs.h"
00342
00343
00344
00345
00346
00347
00348
00349
00350 inline char const *
00351 Cpu::vendor_str()
00352 {
00353 return _vendor == Vendor_unknown ? "Unknown" : vendor_ident[_vendor];
00354 }
00355
00356
00357
00358 inline char const*
00359 Cpu::model_str()
00360 { return _model_str; }
00361
00362
00363
00364 inline Cpu::Vendor const
00365 Cpu::vendor()
00366 { return _vendor; }
00367
00368
00369
00370 inline unsigned int const
00371 Cpu::family()
00372 {
00373 unsigned int val = (_version >> 8) & 0xF;
00374
00375 return val == 0xF ? val + ((_version >> 16) & 0xF0) : val;
00376 }
00377
00378
00379
00380 inline unsigned int const
00381 Cpu::model()
00382 {
00383 unsigned int val = (_version >> 4) & 0xF;
00384
00385 return val == 0xF ? val + ((_version >> 12) & 0xF0) : val;
00386 }
00387
00388
00389
00390 inline unsigned int const
00391 Cpu::stepping()
00392 { return _version & 0xF; }
00393
00394
00395
00396 inline unsigned int const
00397 Cpu::type()
00398 { return (_version >> 12) & 0x3; }
00399
00400
00401
00402 inline Unsigned64
00403 Cpu::frequency()
00404 { return _frequency; }
00405
00406
00407
00408 inline unsigned int const
00409 Cpu::brand()
00410 { return _brand & 0xFF; }
00411
00412
00413
00414 inline unsigned int const
00415 Cpu::features()
00416 { return _features; }
00417
00418
00419
00420 inline unsigned int const
00421 Cpu::ext_features()
00422 { return _ext_features; }
00423
00424
00425
00426 inline unsigned int const
00427 Cpu::ext_amd_features()
00428 { return _ext_amd_features; }
00429
00430
00431
00432 inline unsigned int const
00433 Cpu::local_features()
00434 { return _local_features; }
00435
00436
00437
00438 inline bool
00439 Cpu::have_superpages()
00440 { return features() & FEAT_PSE; }
00441
00442
00443
00444 inline bool
00445 Cpu::have_tsc()
00446 { return features() & FEAT_TSC; }
00447
00448
00449
00450 inline bool
00451 Cpu::have_sysenter()
00452 { return features() & FEAT_SEP; }
00453
00454
00455
00456 inline Unsigned32
00457 Cpu::muldiv(Unsigned32 val, Unsigned32 mul, Unsigned32 div)
00458 {
00459 Unsigned32 dummy;
00460
00461 asm volatile ("mull %3 ; divl %4\n\t"
00462 :"=a" (val), "=d" (dummy)
00463 : "0" (val), "d" (mul), "c" (div));
00464 return val;
00465 }
00466
00467
00468
00469 inline Unsigned64
00470 Cpu::ns_to_tsc(Unsigned64 ns)
00471 {
00472 Unsigned32 dummy;
00473 Unsigned64 tsc;
00474 asm volatile
00475 ("movl %%edx, %%ecx \n\t"
00476 "mull %3 \n\t"
00477 "movl %%ecx, %%eax \n\t"
00478 "movl %%edx, %%ecx \n\t"
00479 "mull %3 \n\t"
00480 "addl %%ecx, %%eax \n\t"
00481 "adcl $0, %%edx \n\t"
00482 "shld $5, %%eax, %%edx \n\t"
00483 "shll $5, %%eax \n\t"
00484 :"=A" (tsc), "=c" (dummy)
00485 : "0" (ns), "b" (scaler_ns_to_tsc)
00486 );
00487 return tsc;
00488 }
00489
00490
00491
00492 inline Unsigned64
00493 Cpu::tsc_to_ns(Unsigned64 tsc)
00494 {
00495 Unsigned32 dummy;
00496 Unsigned64 ns;
00497 asm volatile
00498 ("movl %%edx, %%ecx \n\t"
00499 "mull %3 \n\t"
00500 "movl %%ecx, %%eax \n\t"
00501 "movl %%edx, %%ecx \n\t"
00502 "mull %3 \n\t"
00503 "addl %%ecx, %%eax \n\t"
00504 "adcl $0, %%edx \n\t"
00505 "shld $5, %%eax, %%edx \n\t"
00506 "shll $5, %%eax \n\t"
00507 :"=A" (ns), "=c" (dummy)
00508 : "0" (tsc), "b" (scaler_tsc_to_ns)
00509 );
00510 return ns;
00511 }
00512
00513
00514
00515 inline Unsigned64
00516 Cpu::tsc_to_us(Unsigned64 tsc)
00517 {
00518 Unsigned32 dummy;
00519 Unsigned64 us;
00520 asm volatile
00521 ("movl %%edx, %%ecx \n\t"
00522 "mull %3 \n\t"
00523 "movl %%ecx, %%eax \n\t"
00524 "movl %%edx, %%ecx \n\t"
00525 "mull %3 \n\t"
00526 "addl %%ecx, %%eax \n\t"
00527 "adcl $0, %%edx \n\t"
00528 :"=A" (us), "=c" (dummy)
00529 : "0" (tsc), "S" (scaler_tsc_to_us)
00530 );
00531 return us;
00532 }
00533
00534
00535
00536 inline void
00537 Cpu::tsc_to_s_and_ns(Unsigned64 tsc, Unsigned32 *s, Unsigned32 *ns)
00538 {
00539 Unsigned32 dummy;
00540 __asm__
00541 (" \n\t"
00542 "movl %%edx, %%ecx \n\t"
00543 "mull %4 \n\t"
00544 "movl %%ecx, %%eax \n\t"
00545 "movl %%edx, %%ecx \n\t"
00546 "mull %4 \n\t"
00547 "addl %%ecx, %%eax \n\t"
00548 "adcl $0, %%edx \n\t"
00549 "movl $1000000000, %%ecx \n\t"
00550 "shld $5, %%eax, %%edx \n\t"
00551 "shll $5, %%eax \n\t"
00552 "divl %%ecx \n\t"
00553 :"=a" (*s), "=d" (*ns), "=c" (dummy)
00554 : "A" (tsc), "g" (scaler_tsc_to_ns)
00555 );
00556 }
00557
00558
00559
00560 inline void
00561 Cpu::busy_wait_ns(Unsigned64 ns)
00562 {
00563 Unsigned64 stop = rdtsc () + ns_to_tsc(ns);
00564
00565 while (rdtsc() < stop)
00566 Proc::pause();
00567 }
00568
00569
00570
00571 inline Unsigned64
00572 Cpu::rdtsc(void)
00573 {
00574 Unsigned64 tsc;
00575 asm volatile ("rdtsc" : "=A" (tsc));
00576 return tsc;
00577 }
00578
00579
00580
00581 inline Unsigned32
00582 Cpu::get_scaler_tsc_to_ns()
00583 { return scaler_tsc_to_ns; }
00584
00585
00586
00587 inline Unsigned32
00588 Cpu::get_scaler_tsc_to_us()
00589 { return scaler_tsc_to_us; }
00590
00591
00592
00593 inline Unsigned32
00594 Cpu::get_scaler_ns_to_tsc()
00595 { return scaler_ns_to_tsc; }
00596
00597
00598
00599 inline Unsigned32
00600 Cpu::get_flags()
00601 { Unsigned32 efl; asm volatile ("pushfl ; popl %0" : "=rm"(efl)); return efl; }
00602
00603
00604
00605 inline void
00606 Cpu::set_flags(Unsigned32 efl)
00607 { asm volatile ("pushl %0 ; popfl" : : "rm" (efl) : "memory"); }
00608
00609
00610
00611 inline Unsigned32
00612 Cpu::get_es()
00613 { Unsigned32 val; asm volatile ("mov %%es, %0" : "=rm" (val)); return val; }
00614
00615
00616
00617 inline Unsigned32
00618 Cpu::get_ss()
00619 { Unsigned32 val; asm volatile ("mov %%ss, %0" : "=rm" (val)); return val; }
00620
00621
00622
00623 inline Unsigned32
00624 Cpu::get_fs()
00625 { Unsigned32 val; asm volatile ("mov %%fs, %0" : "=rm" (val)); return val; }
00626
00627
00628
00629 inline Unsigned32
00630 Cpu::get_gs()
00631 { Unsigned32 val; asm volatile ("mov %%gs, %0" : "=rm" (val)); return val; }
00632
00633
00634
00635 inline void
00636 Cpu::set_ds(Unsigned32 val)
00637 { asm volatile ("mov %0, %%ds" : : "rm" (val)); }
00638
00639
00640
00641 inline void
00642 Cpu::set_es(Unsigned32 val)
00643 { asm volatile ("mov %0, %%es" : : "rm" (val)); }
00644
00645
00646
00647 inline void
00648 Cpu::set_fs(Unsigned32 val)
00649 { asm volatile ("mov %0, %%fs" : : "rm" (val)); }
00650
00651
00652
00653 inline void
00654 Cpu::set_gs(Unsigned32 val)
00655 { asm volatile ("mov %0, %%gs" : : "rm" (val)); }
00656
00657
00658
00659 inline void
00660 Cpu::memcpy_bytes(void *dst, void const *src, size_t n)
00661 {
00662 unsigned dummy1, dummy2, dummy3;
00663
00664 asm volatile ("cld \n\t"
00665 "repz movsl %%ds:(%%esi), %%es:(%%edi) \n\t"
00666 "mov %%edx, %%ecx \n\t"
00667 "repz movsb %%ds:(%%esi), %%es:(%%edi) \n\t"
00668 : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3)
00669 : "c" (n >> 2), "d" (n & 3), "S" (src), "D" (dst)
00670 : "memory");
00671 }
00672
00673
00674
00675 inline void
00676 Cpu::memcpy_mwords(void *dst, void const *src, size_t n)
00677 {
00678 unsigned dummy1, dummy2, dummy3;
00679
00680 asm volatile ("cld \n\t"
00681 "rep movsl %%ds:(%%esi), %%es:(%%edi) \n\t"
00682 : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3)
00683 : "c" (n), "S" (src), "D" (dst)
00684 : "memory");
00685 }
00686
00687
00688
00689 inline void
00690 Cpu::memcpy_bytes_fs(void *dst, void const *src, size_t n)
00691 {
00692 unsigned dummy1, dummy2, dummy3;
00693
00694 asm volatile ("cld \n\t"
00695 "rep movsl %%fs:(%%esi), %%es:(%%edi) \n\t"
00696 "mov %%edx, %%ecx \n\t"
00697 "repz movsb %%fs:(%%esi), %%es:(%%edi) \n\t"
00698 : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3)
00699 : "c" (n >> 2), "d" (n & 3), "S" (src), "D" (dst)
00700 : "memory");
00701 }
00702
00703
00704
00705 inline void
00706 Cpu::memcpy_mwords_fs(void *dst, void const *src, size_t n)
00707 {
00708 unsigned dummy1, dummy2, dummy3;
00709
00710 asm volatile ("cld \n\t"
00711 "rep movsl %%fs:(%%esi), %%es:(%%edi) \n\t"
00712 : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3)
00713 : "c" (n), "S" (src), "D" (dst)
00714 : "memory");
00715 }
00716
00717
00718
00719 inline void
00720 Cpu::set_cr0(Unsigned32 val)
00721 { asm volatile ("movl %0, %%cr0" : : "r" (val)); }
00722
00723
00724
00725 inline void
00726 Cpu::set_pdbr(Address addr)
00727 { asm volatile ("movl %0, %%cr3" : : "r" (addr)); }
00728
00729
00730
00731 inline void
00732 Cpu::set_cr4(Unsigned32 val)
00733 { asm volatile ("movl %0, %%cr4" : : "r" (val)); }
00734
00735
00736
00737 inline void
00738 Cpu::set_ldt(Unsigned16 val)
00739 { asm volatile ("lldt %0" : : "rm" (val)); }
00740
00741
00742
00743 inline void
00744 Cpu::set_cs()
00745 {
00746 asm volatile ("ljmp %0,$1f ; 1:"
00747 : : "i"(Gdt::gdt_code_kernel | Gdt::Selector_kernel));
00748 }
00749
00750
00751
00752 inline void
00753 Cpu::set_ss(Unsigned32 val)
00754 { asm volatile ("movl %0, %%ss" : : "rm" (val)); }
00755
00756
00757
00758 inline void
00759 Cpu::set_tr(Unsigned16 val)
00760 { asm volatile ("ltr %0" : : "rm" (val)); }
00761
00762
00763
00764 inline Mword
00765 Cpu::get_cr0()
00766 { Mword val; asm volatile ("movl %%cr0, %0" : "=r" (val)); return val; }
00767
00768
00769
00770 inline Address
00771 Cpu::get_pdbr()
00772 { Address addr; asm volatile ("movl %%cr3, %0" : "=r" (addr)); return addr; }
00773
00774
00775
00776 inline Mword
00777 Cpu::get_cr4()
00778 { Mword val; asm volatile ("movl %%cr4, %0" : "=r" (val)); return val; }
00779
00780
00781
00782 inline Unsigned16
00783 Cpu::get_ldt()
00784 { Unsigned16 val; asm volatile ("sldt %0" : "=rm" (val)); return val; }
00785
00786
00787
00788 inline Unsigned16
00789 Cpu::get_tr()
00790 { Unsigned16 val; asm volatile ("str %0" : "=rm" (val)); return val; }
00791
00792
00793
00794 inline Unsigned64
00795 Cpu::rdmsr(Unsigned32 reg)
00796 {
00797 Unsigned64 msr;
00798
00799 asm volatile ("rdmsr" : "=A" (msr) : "c" (reg));
00800 return msr;
00801 }
00802
00803
00804
00805 inline Unsigned64
00806 Cpu::rdpmc(Unsigned32 idx, Unsigned32)
00807 {
00808 Unsigned64 pmc;
00809
00810 asm volatile ("rdpmc" : "=A" (pmc) : "c" (idx));
00811 return pmc;
00812 }
00813
00814
00815
00816 inline void
00817 Cpu::wrmsr(Unsigned32 low, Unsigned32 high, Unsigned32 reg)
00818 { asm volatile ("wrmsr" : : "a" (low), "d" (high), "c" (reg)); }
00819
00820
00821
00822 inline void
00823 Cpu::wrmsr(Unsigned64 msr, Unsigned32 reg)
00824 { asm volatile ("wrmsr" : : "A" (msr), "c" (reg)); }
00825
00826
00827
00828 inline void
00829 Cpu::enable_rdpmc()
00830 { set_cr4(get_cr4() | CR4_PCE); }
00831
00832
00833
00834 inline void
00835 Cpu::enable_lbr(void)
00836 {
00837 if (lbr_type() != LBR_NONE)
00838 {
00839 Unsigned64 lbr_ctrl = rdmsr (0x1d9);
00840 wrmsr (lbr_ctrl | 1, 0x1d9);
00841 }
00842 }
00843
00844
00845
00846 inline void
00847 Cpu::disable_lbr(void)
00848 {
00849 if (lbr_type() != LBR_NONE)
00850 {
00851 Unsigned64 lbr_ctrl = rdmsr (0x1d9);
00852 wrmsr (lbr_ctrl & ~1, 0x1d9);
00853 }
00854 }
00855
00856
00857
00858 inline void
00859 Cpu::set_gdt()
00860 {
00861 Pseudo_descriptor desc((Address)gdt, Gdt::gdt_max-1);
00862 Gdt::set (&desc);
00863 }
00864
00865
00866
00867 inline void
00868 Cpu::set_tss()
00869 {
00870 set_tr (Gdt::gdt_tss);
00871 }
00872
00873
00874
00875 inline Gdt*
00876 Cpu::get_gdt()
00877 { return gdt; }
00878
00879
00880
00881 inline Tss*
00882 Cpu::get_tss()
00883 { return tss; }
00884
00885
00886
00887 inline void
00888 Cpu::enable_ldt(Address addr, int size)
00889 {
00890 if (!size)
00891 {
00892 get_gdt()->clear_entry (Gdt::gdt_ldt / 8);
00893 set_ldt(0);
00894 }
00895 else
00896 {
00897 get_gdt()->set_entry_byte (Gdt::gdt_ldt / 8, addr, size-1, 2, 0);
00898 set_ldt(Gdt::gdt_ldt);
00899 }
00900 }
00901
00902
00903
00904 inline int
00905 Cpu::can_wrmsr()
00906 { return features() & FEAT_MSR; }
00907
00908
00909
00910 inline Unsigned64
00911 Cpu::time_us()
00912 {
00913 return tsc_to_us (rdtsc());
00914 }
00915
00916 #endif // cpu_h