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 reg_write(APIC_esr, 0);
216 return reg_read(APIC_esr);
219 PRIVATE static inline NOEXPORT
221 Apic::clear_num_errors()
223 reg_write(APIC_esr, 0);
224 reg_write(APIC_esr, 0);
229 Apic::get_frequency_khz()
231 return frequency_khz;
236 Apic::reg_read(unsigned reg)
238 return *((volatile Unsigned32*)(io_base + reg));
243 Apic::reg_write(unsigned reg, Unsigned32 val)
245 *((volatile Unsigned32*)(io_base + reg)) = val;
250 Apic::reg_delivery_mode(Unsigned32 val)
252 return (val >> 8) & 7;
257 Apic::reg_lvt_vector(Unsigned32 val)
264 Apic::timer_reg_read()
266 return reg_read(APIC_tmcct);
271 Apic::timer_reg_read_initial()
273 return reg_read(APIC_tmict);
278 Apic::timer_reg_write(Unsigned32 val)
280 reg_read(APIC_tmict);
281 reg_write(APIC_tmict, val);
284 PUBLIC static inline NEEDS["cpu.h"]
286 Apic::apic_page_phys()
287 { return Cpu::rdmsr(APIC_base_msr) & 0xfffff000; }
289 // set the global pagetable entry for the Local APIC device registers
293 Apic::map_apic_page()
296 Address base = apic_page_phys();
297 // We should not change the physical address of the Local APIC page if
298 // possible since some versions of VMware would complain about a
299 // non-implemented feature
300 Kmem::map_phys_page(base, Mem_layout::Local_apic_page,
303 Kip::k()->add_mem_region(Mem_desc(base, base + Config::PAGE_SIZE - 1, Mem_desc::Reserved));
308 // check CPU type if APIC could be present
313 if (!cpu().can_wrmsr() || !(cpu().features() & FEAT_TSC))
316 if (cpu().vendor() == Cpu::Vendor_intel)
318 if (cpu().family() == 15)
324 else if (cpu().family() >= 6)
331 if (cpu().vendor() == Cpu::Vendor_amd && cpu().family() >= 6)
341 // test if APIC present
346 return cpu().features() & FEAT_APIC;
351 Apic::timer_enable_irq()
355 tmp_val = reg_read(APIC_lvtt);
356 tmp_val &= ~(APIC_lvt_masked);
357 reg_write(APIC_lvtt, tmp_val);
362 Apic::timer_disable_irq()
366 tmp_val = reg_read(APIC_lvtt);
367 tmp_val |= APIC_lvt_masked;
368 reg_write(APIC_lvtt, tmp_val);
373 Apic::timer_is_irq_enabled()
375 return ~reg_read(APIC_lvtt) & APIC_lvt_masked;
380 Apic::timer_set_periodic()
382 Unsigned32 tmp_val = reg_read(APIC_lvtt);
383 tmp_val |= APIC_lvt_timer_periodic;
384 reg_write(APIC_lvtt, tmp_val);
389 Apic::timer_set_one_shot()
391 Unsigned32 tmp_val = reg_read(APIC_lvtt);
392 tmp_val &= ~APIC_lvt_timer_periodic;
393 reg_write(APIC_lvtt, tmp_val);
398 Apic::timer_assign_irq_vector(unsigned vector)
400 Unsigned32 tmp_val = reg_read(APIC_lvtt);
401 tmp_val &= 0xffffff00;
403 reg_write(APIC_lvtt, tmp_val);
411 reg_write(APIC_eoi, 0);
416 Apic::timer_set_divisor(unsigned newdiv)
421 Unsigned32 tmp_value;
423 static int divisor_tab[8] =
425 APIC_tdr_div_1, APIC_tdr_div_2, APIC_tdr_div_4, APIC_tdr_div_8,
426 APIC_tdr_div_16, APIC_tdr_div_32, APIC_tdr_div_64, APIC_tdr_div_128
435 printf("bad APIC divisor %d\n", newdiv);
438 div = divisor_tab[i];
446 timer_divisor = newdiv;
447 tmp_value = reg_read(APIC_tdcr);
450 reg_write(APIC_tdcr, tmp_value);
458 return is_integrated() ? get_max_lvt_local() : 2;
465 return (present && (get_max_lvt() >= 4));
472 return (present && (get_max_lvt() >= 5));
475 // check if APIC is working (check timer functionality)
478 Apic::check_working()
480 Unsigned64 tsc_until;
483 timer_set_divisor(1);
484 timer_reg_write(0x10000000);
486 tsc_until = Cpu::rdtsc() + 0x100; // we only have to wait for one bus cycle
490 if (timer_reg_read() != 0x10000000)
492 } while (Cpu::rdtsc() < tsc_until);
497 static FIASCO_INIT_CPU
503 tmp_val = reg_read(APIC_spiv);
504 tmp_val |= (1<<8); // enable APIC
505 tmp_val &= ~(1<<9); // enable Focus Processor Checking
507 tmp_val |= APIC_IRQ_BASE + 0xf; // Set spurious IRQ vector to 0x3f
508 // bit 0..3 are hardwired to 1 on PPro!
509 reg_write(APIC_spiv, tmp_val);
512 PUBLIC static inline NEEDS[Apic::reg_write]
514 Apic::tpr(unsigned prio)
515 { reg_write(APIC_tpr, prio); }
517 PUBLIC static inline NEEDS[Apic::reg_read]
520 { return reg_read(APIC_tpr); }
522 static FIASCO_INIT_CPU
526 reg_write (APIC_tpr, 0);
529 // activate APIC error interrupt
530 static FIASCO_INIT_CPU
532 Apic::enable_errors()
536 Unsigned32 tmp_val, before, after;
538 if (get_max_lvt() > 3)
540 before = get_num_errors();
542 tmp_val = reg_read(APIC_lvterr);
543 tmp_val &= 0xfffeff00; // unmask error IRQ vector
544 tmp_val |= APIC_IRQ_BASE + 3; // Set error IRQ vector to 0x63
545 reg_write(APIC_lvterr, tmp_val);
547 if (get_max_lvt() > 3)
549 after = get_num_errors();
550 printf("APIC ESR value before/after enabling: %08x/%08x\n",
555 // activate APIC after activating by MSR was successful
556 // see "Intel Architecture Software Developer's Manual,
557 // Volume 3: System Programming Guide, Appendix E"
560 Apic::route_pic_through_apic()
563 Lock_guard <Cpu_lock> guard(&cpu_lock);
565 // mask 8259 interrupts
566 Pic::Status old_irqs = Pic::disable_all_save();
568 // set LINT0 to ExtINT, edge triggered
569 tmp_val = reg_read(APIC_lvt0);
570 tmp_val &= 0xfffe5800;
571 tmp_val |= 0x00000700;
572 reg_write(APIC_lvt0, tmp_val);
574 // set LINT1 to NMI, edge triggered
575 tmp_val = reg_read(APIC_lvt1);
576 tmp_val &= 0xfffe5800;
577 tmp_val |= 0x00000400;
578 reg_write(APIC_lvt1, tmp_val);
580 // unmask 8259 interrupts
581 Pic::restore_all(old_irqs);
583 printf("APIC was disabled --- routing PIC through APIC\n");
586 static FIASCO_INIT_CPU
591 Lock_guard <Cpu_lock> guard(&cpu_lock);
593 // mask timer interrupt and set vector to _not_ invalid value
594 tmp_val = reg_read(APIC_lvtt);
595 tmp_val |= APIC_lvt_masked;
597 reg_write(APIC_lvtt, tmp_val);
600 // mask performance interrupt and set vector to a valid value
601 tmp_val = reg_read(APIC_lvtpc);
602 tmp_val |= APIC_lvt_masked;
604 reg_write(APIC_lvtpc, tmp_val);
608 // mask thermal sensor interrupt and set vector to a valid value
609 tmp_val = reg_read(APIC_lvtthmr);
610 tmp_val |= APIC_lvt_masked;
612 reg_write(APIC_lvtthmr, tmp_val);
616 // give us a hint if we have an APIC but it is disabled
619 Apic::test_present_but_disabled()
624 Unsigned64 msr = Cpu::rdmsr(APIC_base_msr);
625 return ((msr & 0xffffff000ULL) == 0xfee00000ULL);
628 // activate APIC by writing to appropriate MSR
629 static FIASCO_INIT_CPU
631 Apic::activate_by_msr()
635 msr = Cpu::rdmsr(APIC_base_msr);
636 phys_base = msr & 0xfffff000;
638 Cpu::wrmsr(msr, APIC_base_msr);
640 // now the CPU feature flags may have changed
644 // check if we still receive interrupts after we changed the IRQ routing
645 PUBLIC static FIASCO_INIT_CPU
647 Apic::check_still_getting_interrupts()
652 Unsigned64 tsc_until;
653 Cpu_time clock_start = Kip::k()->clock;
655 tsc_until = Cpu::rdtsc();
656 tsc_until += 0x01000000; // > 10 Mio cycles should be sufficient until
657 // we have processors with more than 10 GHz
660 // kernel clock by timer interrupt updated?
661 if (Kip::k()->clock != clock_start)
664 } while (Cpu::rdtsc() < tsc_until);
689 reg_write(APIC_lvtpc, 0x400);
692 static FIASCO_INIT_CPU
694 Apic::calibrate_timer()
696 const unsigned calibrate_time = 50;
697 Unsigned32 count, tt1, tt2, result, dummy;
698 Unsigned32 runs = 0, frequency_ok;
705 timer_set_divisor(1);
706 timer_reg_write(1000000000);
709 Lock_guard <Cpu_lock> guard(&cpu_lock);
711 Pit::setup_channel2_to_20hz();
715 tt1 = timer_reg_read();
720 while ((Io::in8(0x61) & 0x20) == 0);
721 tt2 = timer_reg_read();
724 result = (tt1 - tt2) * timer_divisor;
731 :"=a" (frequency_khz), "=d" (dummy)
732 : "r" (calibrate_time), "a" (result), "d" (0));
734 frequency_ok = (frequency_khz < (1000<<11));
736 while (++runs < 10 && !frequency_ok);
739 panic("APIC frequency too high, adapt Apic::scaler_us_to_apic");
741 Kip::k()->frequency_bus = frequency_khz;
742 scaler_us_to_apic = Cpu::muldiv(1<<21, frequency_khz, 1000);
747 Apic::error_interrupt(Return_frame *regs)
749 Unsigned32 err1, err2;
751 // we are entering with disabled interrupts
752 err1 = Apic::get_num_errors();
753 Apic::clear_num_errors();
754 err2 = Apic::get_num_errors();
759 if (err1 == 0x80 || err2 == 0x80)
761 // ignore possible invalid access which may happen in
762 // jdb::do_dump_memory()
763 if (ignore_invalid_apic_reg_access)
766 printf("cpu%d: APIC invalid register access error at "L4_PTR_FMT"\n",
767 current_cpu(), regs->ip());
772 printf("cpu%d: APIC error %08x(%08x)\n", current_cpu(), err1, err2);
775 // deactivate APIC by writing to appropriate MSR
785 val = reg_read(APIC_spiv);
787 reg_write(APIC_spiv, val);
789 val = Cpu::rdmsr(APIC_base_msr);
791 Cpu::wrmsr(val, APIC_base_msr);
794 PRIVATE static FIASCO_INIT_CPU
799 timer_set_divisor(1);
807 printf("Local APIC[%02x]: version=%02x max_lvt=%d\n",
808 get_id() >> 24, get_version(), get_max_lvt());
818 good_cpu = test_cpu();
824 if ((present = good_cpu))
826 // check cpu features of cpuid
827 was_present = test_present();
829 // activate; this could lead an disabled APIC to appear
830 // set base address of I/O registers to be able to access the registers
833 // previous test_present() could have failed but we could have it
834 // activated by writing the msr so we have to test again
835 if ((present = test_present()))
837 // map the Local APIC device registers
840 // set some interrupt vectors to appropriate values
843 // initialize APIC_spiv register
846 // initialize task-priority register
849 // test if local timer counts down
850 if ((present = check_working()))
853 // APIC _was_ not present before writing to msr so we have
854 // to set APIC_lvt0 and APIC_lvt1 to appropriate values
855 route_pic_through_apic();
861 panic("Local APIC not found");
865 apic_io_base = Mem_layout::Local_apic_page;