12 static void init() FIASCO_INIT;
17 APIC_P6, // Intel PPro, PIII
19 APIC_K7 // AMD Athlon Model 2
23 Apic(); // default constructors are undefined
25 static void error_interrupt(Return_frame *regs)
26 asm ("apic_error_interrupt") FIASCO_FASTCALL;
30 static const Address io_base;
31 static Address phys_base;
32 static unsigned timer_divisor;
33 static Apic_type type;
34 static unsigned frequency_khz;
35 static Unsigned64 scaler_us_to_apic;
42 APIC_tpri_mask = 0xFF,
45 APIC_ldr_mask = (0xFF<<24),
56 APIC_timer_base_div = 0x2,
63 APIC_snd_pending = (1<<12),
64 APIC_input_polarity = (1<<13),
65 APIC_lvt_remote_irr = (1<<14),
66 APIC_lvt_level_trigger = (1<<15),
67 APIC_lvt_masked = (1<<16),
68 APIC_lvt_timer_periodic = (1<<17),
73 APIC_tdr_div_16 = 0x3,
74 APIC_tdr_div_32 = 0x8,
75 APIC_tdr_div_64 = 0x9,
76 APIC_tdr_div_128 = 0xA,
95 extern unsigned apic_spurious_interrupt_bug_cnt;
96 extern unsigned apic_spurious_interrupt_cnt;
97 extern unsigned apic_error_cnt;
100 //----------------------------------------------------------------------------
106 Apic::cpu() { return *Cpu::boot_cpu(); }
109 //----------------------------------------------------------------------------
110 IMPLEMENTATION[ia32]:
114 Apic::us_to_apic(Unsigned64 us)
116 Unsigned32 apic, dummy1, dummy2;
117 asm ("movl %%edx, %%ecx \n\t"
119 "movl %%ecx, %%eax \n\t"
120 "movl %%edx, %%ecx \n\t"
122 "addl %%ecx, %%eax \n\t"
123 "shll $11, %%eax \n\t"
124 :"=a" (apic), "=d" (dummy1), "=&c" (dummy2)
125 : "A" (us), "g" (scaler_us_to_apic)
130 IMPLEMENTATION[amd64]:
134 Apic::us_to_apic(Unsigned64 us)
136 Unsigned32 apic, dummy;
138 "shrq $21,%%rax \n\t"
139 :"=a"(apic), "=d"(dummy)
140 :"a"(us), "g"(scaler_us_to_apic)
145 IMPLEMENTATION[ia32,amd64]:
154 #include "cpu_lock.h"
155 #include "entry_frame.h"
160 #include "lock_guard.h"
162 #include "processor.h"
167 unsigned apic_spurious_interrupt_bug_cnt;
168 unsigned apic_spurious_interrupt_cnt;
169 unsigned apic_error_cnt;
170 Address apic_io_base;
174 const Address Apic::io_base = Mem_layout::Local_apic_page;
175 Address Apic::phys_base;
176 unsigned Apic::timer_divisor = 1;
177 Apic::Apic_type Apic::type = APIC_NONE;
178 unsigned Apic::frequency_khz;
179 Unsigned64 Apic::scaler_us_to_apic;
181 int ignore_invalid_apic_reg_access;
187 return reg_read(APIC_id) & 0xff000000;
190 PRIVATE static inline
194 return reg_read(APIC_lvr) & 0xFF;
197 PRIVATE static inline NOEXPORT
199 Apic::is_integrated()
201 return reg_read(APIC_lvr) & 0xF0;
204 PRIVATE static inline NOEXPORT
206 Apic::get_max_lvt_local()
208 return ((reg_read(APIC_lvr) >> 16) & 0xFF);
211 PRIVATE static inline NOEXPORT
213 Apic::get_num_errors()
215 return reg_read(APIC_esr);
218 PRIVATE static inline NOEXPORT
220 Apic::clear_num_errors()
222 reg_write(APIC_esr, 0);
227 Apic::get_frequency_khz()
229 return frequency_khz;
234 Apic::reg_read(unsigned reg)
236 return *((volatile Unsigned32*)(io_base + reg));
241 Apic::reg_write(unsigned reg, Unsigned32 val)
243 *((volatile Unsigned32*)(io_base + reg)) = val;
248 Apic::reg_delivery_mode(Unsigned32 val)
250 return (val >> 8) & 7;
255 Apic::reg_lvt_vector(Unsigned32 val)
262 Apic::timer_reg_read()
264 return reg_read(APIC_tmcct);
269 Apic::timer_reg_read_initial()
271 return reg_read(APIC_tmict);
276 Apic::timer_reg_write(Unsigned32 val)
278 reg_read(APIC_tmict);
279 reg_write(APIC_tmict, val);
282 PUBLIC static inline NEEDS["cpu.h"]
284 Apic::apic_page_phys()
285 { return Cpu::rdmsr(APIC_base_msr) & 0xfffff000; }
287 // set the global pagetable entry for the Local APIC device registers
291 Apic::map_apic_page()
294 Address base = Cpu::rdmsr(APIC_base_msr) & 0xfffff000;
295 // We should not change the physical address of the Local APIC page if
296 // possible since some versions of VMware would complain about a
297 // non-implemented feature
298 Kmem::map_phys_page(base, Mem_layout::Local_apic_page,
301 Kip::k()->add_mem_region(Mem_desc(base, base + Config::PAGE_SIZE - 1, Mem_desc::Reserved));
306 // check CPU type if APIC could be present
311 if (!cpu().can_wrmsr() || !(cpu().features() & FEAT_TSC))
314 if (cpu().vendor() == Cpu::Vendor_intel)
316 if (cpu().family() == 15)
322 else if (cpu().family() >= 6)
329 if (cpu().vendor() == Cpu::Vendor_amd && cpu().family() >= 6)
339 // test if APIC present
344 return cpu().features() & FEAT_APIC;
349 Apic::timer_enable_irq()
353 tmp_val = reg_read(APIC_lvtt);
354 tmp_val &= ~(APIC_lvt_masked);
355 reg_write(APIC_lvtt, tmp_val);
360 Apic::timer_disable_irq()
364 tmp_val = reg_read(APIC_lvtt);
365 tmp_val |= APIC_lvt_masked;
366 reg_write(APIC_lvtt, tmp_val);
371 Apic::timer_is_irq_enabled()
373 return ~reg_read(APIC_lvtt) & APIC_lvt_masked;
378 Apic::timer_set_periodic()
380 Unsigned32 tmp_val = reg_read(APIC_lvtt);
381 tmp_val |= APIC_lvt_timer_periodic;
382 reg_write(APIC_lvtt, tmp_val);
387 Apic::timer_set_one_shot()
389 Unsigned32 tmp_val = reg_read(APIC_lvtt);
390 tmp_val &= ~APIC_lvt_timer_periodic;
391 reg_write(APIC_lvtt, tmp_val);
396 Apic::timer_assign_irq_vector(unsigned vector)
398 Unsigned32 tmp_val = reg_read(APIC_lvtt);
399 tmp_val &= 0xffffff00;
401 reg_write(APIC_lvtt, tmp_val);
409 reg_write(APIC_eoi, 0);
414 Apic::timer_set_divisor(unsigned newdiv)
419 Unsigned32 tmp_value;
421 static int divisor_tab[8] =
423 APIC_tdr_div_1, APIC_tdr_div_2, APIC_tdr_div_4, APIC_tdr_div_8,
424 APIC_tdr_div_16, APIC_tdr_div_32, APIC_tdr_div_64, APIC_tdr_div_128
433 printf("bad APIC divisor %d\n", newdiv);
436 div = divisor_tab[i];
444 timer_divisor = newdiv;
445 tmp_value = reg_read(APIC_tdcr);
448 reg_write(APIC_tdcr, tmp_value);
456 return is_integrated() ? get_max_lvt_local() : 2;
463 return (present && (get_max_lvt() >= 4));
470 return (present && (get_max_lvt() >= 5));
473 // check if APIC is working (check timer functionality)
476 Apic::check_working()
478 Unsigned64 tsc_until;
481 timer_set_divisor(1);
482 timer_reg_write(0x10000000);
484 tsc_until = Cpu::rdtsc() + 0x100; // we only have to wait for one bus cycle
488 if (timer_reg_read() != 0x10000000)
490 } while (Cpu::rdtsc() < tsc_until);
495 static FIASCO_INIT_CPU
501 tmp_val = reg_read(APIC_spiv);
502 tmp_val |= (1<<8); // enable APIC
503 tmp_val &= ~(1<<9); // enable Focus Processor Checking
505 tmp_val |= APIC_IRQ_BASE + 0xf; // Set spurious IRQ vector to 0x3f
506 // bit 0..3 are hardwired to 1 on PPro!
507 reg_write(APIC_spiv, tmp_val);
510 PUBLIC static inline NEEDS[Apic::reg_write]
512 Apic::tpr(unsigned prio)
513 { reg_write(APIC_tpr, prio); }
515 PUBLIC static inline NEEDS[Apic::reg_read]
518 { return reg_read(APIC_tpr); }
520 static FIASCO_INIT_CPU
524 reg_write (APIC_tpr, 0);
527 // activate APIC error interrupt
528 static FIASCO_INIT_CPU
530 Apic::enable_errors()
534 Unsigned32 tmp_val, before, after;
536 if (get_max_lvt() > 3)
538 before = get_num_errors();
540 tmp_val = reg_read(APIC_lvterr);
541 tmp_val &= 0xfffeff00; // unmask error IRQ vector
542 tmp_val |= APIC_IRQ_BASE + 3; // Set error IRQ vector to 0x63
543 reg_write(APIC_lvterr, tmp_val);
545 if (get_max_lvt() > 3)
547 after = get_num_errors();
548 printf("APIC ESR value before/after enabling: %08x/%08x\n",
553 // activate APIC after activating by MSR was successful
554 // see "Intel Architecture Software Developer's Manual,
555 // Volume 3: System Programming Guide, Appendix E"
558 Apic::route_pic_through_apic()
561 Lock_guard <Cpu_lock> guard(&cpu_lock);
563 // mask 8259 interrupts
564 Pic::Status old_irqs = Pic::disable_all_save();
566 // set LINT0 to ExtINT, edge triggered
567 tmp_val = reg_read(APIC_lvt0);
568 tmp_val &= 0xfffe5800;
569 tmp_val |= 0x00000700;
570 reg_write(APIC_lvt0, tmp_val);
572 // set LINT1 to NMI, edge triggered
573 tmp_val = reg_read(APIC_lvt1);
574 tmp_val &= 0xfffe5800;
575 tmp_val |= 0x00000400;
576 reg_write(APIC_lvt1, tmp_val);
578 // unmask 8259 interrupts
579 Pic::restore_all(old_irqs);
581 printf("APIC was disabled --- routing PIC through APIC\n");
584 static FIASCO_INIT_CPU
589 Lock_guard <Cpu_lock> guard(&cpu_lock);
591 // mask timer interrupt and set vector to _not_ invalid value
592 tmp_val = reg_read(APIC_lvtt);
593 tmp_val |= APIC_lvt_masked;
595 reg_write(APIC_lvtt, tmp_val);
598 // mask performance interrupt and set vector to a valid value
599 tmp_val = reg_read(APIC_lvtpc);
600 tmp_val |= APIC_lvt_masked;
602 reg_write(APIC_lvtpc, tmp_val);
606 // mask thermal sensor interrupt and set vector to a valid value
607 tmp_val = reg_read(APIC_lvtthmr);
608 tmp_val |= APIC_lvt_masked;
610 reg_write(APIC_lvtthmr, tmp_val);
614 // give us a hint if we have an APIC but it is disabled
617 Apic::test_present_but_disabled()
622 Unsigned64 msr = Cpu::rdmsr(APIC_base_msr);
623 return ((msr & 0xffffff000ULL) == 0xfee00000ULL);
626 // activate APIC by writing to appropriate MSR
627 static FIASCO_INIT_CPU
629 Apic::activate_by_msr()
633 msr = Cpu::rdmsr(APIC_base_msr);
634 phys_base = msr & 0xfffff000;
636 Cpu::wrmsr(msr, APIC_base_msr);
638 // now the CPU feature flags may have changed
642 // check if we still receive interrupts after we changed the IRQ routing
643 PUBLIC static FIASCO_INIT_CPU
645 Apic::check_still_getting_interrupts()
650 Unsigned64 tsc_until;
651 Cpu_time clock_start = Kip::k()->clock;
653 tsc_until = Cpu::rdtsc();
654 tsc_until += 0x01000000; // > 10 Mio cycles should be sufficient until
655 // we have processors with more than 10 GHz
658 // kernel clock by timer interrupt updated?
659 if (Kip::k()->clock != clock_start)
662 } while (Cpu::rdtsc() < tsc_until);
687 reg_write(APIC_lvtpc, 0x400);
690 static FIASCO_INIT_CPU
692 Apic::calibrate_timer()
694 const unsigned calibrate_time = 50;
695 Unsigned32 count, tt1, tt2, result, dummy;
696 Unsigned32 runs = 0, frequency_ok;
703 timer_set_divisor(1);
704 timer_reg_write(1000000000);
707 Lock_guard <Cpu_lock> guard(&cpu_lock);
709 Pit::setup_channel2_to_20hz();
713 tt1 = timer_reg_read();
718 while ((Io::in8(0x61) & 0x20) == 0);
719 tt2 = timer_reg_read();
722 result = (tt1 - tt2) * timer_divisor;
729 :"=a" (frequency_khz), "=d" (dummy)
730 : "r" (calibrate_time), "a" (result), "d" (0));
732 frequency_ok = (frequency_khz < (1000<<11));
734 while (++runs < 10 && !frequency_ok);
737 panic("APIC frequency too high, adapt Apic::scaler_us_to_apic");
739 Kip::k()->frequency_bus = frequency_khz;
740 scaler_us_to_apic = Cpu::muldiv(1<<21, frequency_khz, 1000);
745 Apic::error_interrupt(Return_frame *regs)
747 Unsigned32 err1, err2;
749 // we are entering with disabled interrupts
750 err1 = Apic::get_num_errors();
751 Apic::clear_num_errors();
752 err2 = Apic::get_num_errors();
757 if (err1 == 0x80 || err2 == 0x80)
759 // ignore possible invalid access which may happen in
760 // jdb::do_dump_memory()
761 if (ignore_invalid_apic_reg_access)
764 printf("APIC invalid register access error at "L4_PTR_FMT"\n",
770 printf("APIC error %08x(%08x)\n", err1, err2);
773 // deactivate APIC by writing to appropriate MSR
783 val = reg_read(APIC_spiv);
785 reg_write(APIC_spiv, val);
787 val = Cpu::rdmsr(APIC_base_msr);
789 Cpu::wrmsr(val, APIC_base_msr);
792 PRIVATE static FIASCO_INIT_CPU
797 timer_set_divisor(1);
805 printf("Local APIC[%02x]: version=%02x max_lvt=%d\n",
806 get_id() >> 24, get_version(), get_max_lvt());
816 good_cpu = test_cpu();
822 if ((present = good_cpu))
824 // check cpu features of cpuid
825 was_present = test_present();
827 // activate; this could lead an disabled APIC to appear
828 // set base address of I/O registers to be able to access the registers
831 // previous test_present() could have failed but we could have it
832 // activated by writing the msr so we have to test again
833 if ((present = test_present()))
835 // map the Local APIC device registers
838 // set some interrupt vectors to appropriate values
841 // initialize APIC_spiv register
844 // initialize task-priority register
847 // test if local timer counts down
848 if ((present = check_working()))
851 // APIC _was_ not present before writing to msr so we have
852 // to set APIC_lvt0 and APIC_lvt1 to appropriate values
853 route_pic_through_apic();
859 panic("Local APIC not found");
863 apic_io_base = Mem_layout::Local_apic_page;