From 9dabe01545644dd78448d8d489616872f14d964b Mon Sep 17 00:00:00 2001 From: Miguel Date: Sun, 9 Sep 2018 00:26:30 +0200 Subject: lapic bus speed probing and starting switch to ioapic --- kernel/smp.c | 58 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 17 deletions(-) (limited to 'kernel/smp.c') diff --git a/kernel/smp.c b/kernel/smp.c index da91148..b2ce6b0 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -43,6 +43,7 @@ volatile uint8_t proc; uint32_t cpu_counter[SMP_MAX_PROC]; uint32_t local_apic_addr; +uint32_t countdown; void writeAPIC(uint32_t offset, uint32_t value) { @@ -81,6 +82,35 @@ void apicEnable() } +/** select mode : divisor. + * 0 - 1 + * 1 - 2 + * 2 - 4 + * 3 - 8 + * 4 - 16 + * 5 - 32 + * 6 - 64 + * 7 - 128 + */ + +uint32_t probeBusSpeed(uint32_t sel) +{ + uint32_t div[]={1,2,4,8,16,32,64,128}; + uint32_t reg[]={0b1011,0,1,2,3,0b1000,0b1001,0b1010}; + + uint32_t divisor=div[sel]; + + klog("Probing bus speed for 50ms (div=%d)) ...",divisor); + writeAPIC(APIC_TMRDIV, reg[sel]); + writeAPIC(APIC_TMRINITCNT, 0xFFFFFFFF); +// for(int i=0;i<20;i++) + asm_pit_sleep_50ms(); + //writeAPIC(APIC_LVT_TMR, APIC_LVT_INT_MASKED); //?? + uint32_t ticksInS = 0xFFFFFFFF - readAPIC(APIC_TMRCURRCNT); + ticksInS*=20; // adjust to one full second. + klog("%d MHz (%d Hz) bus speed (ticks=%d)",ticksInS/(1000000/divisor),ticksInS*divisor,ticksInS/20); + return ticksInS*divisor; +} void smp_main() { // setup stack @@ -99,7 +129,6 @@ void kernel_ap() int_install(); gdt_init(); - uint32_t countdown=0x0fffffff; // TODO: calc to be constant, depending on bus speed. (use pit for measurement?) writeAPIC(APIC_TMRDIV, 0x3); writeAPIC(APIC_LVT_TMR, 200 | TMR_PERIODIC); writeAPIC(APIC_TMRINITCNT, countdown); @@ -151,9 +180,18 @@ void smp_start_aps(smp_processors *pros) { // TODO: check if local APIC is present via CPUID (P6 (i686) and above) local_apic_addr=pros->local_apic_address; - klog("bsp local apic id: 0x%08X",apicID()); + apicEnable(); // bsp apic seems to be enabled anyway. + + uint32_t speed=probeBusSpeed(4); // get bus speed (divisor: 16) + + // setup apic timer + countdown=speed/16; // tick once a second + writeAPIC(APIC_TMRDIV, 0x3); // divisor 16 + writeAPIC(APIC_LVT_TMR, 200 | TMR_PERIODIC); // on interrupt 200 + writeAPIC(APIC_TMRINITCNT, countdown); + for(int i=0;iprocessors;i++) { if(pros->boot==i)continue; @@ -177,19 +215,5 @@ void smp_start_aps(smp_processors *pros) // TODO retry 110 SIPI with 1s timeout } - - apicEnable(); // bsp seems to be enabled anyway. - - writeAPIC(APIC_TMRDIV, 0x3); - writeAPIC(APIC_TMRINITCNT, 0xFFFFFFFF); - //asm_pit_sleep_1ms(); - //writeAPIC(APIC_LVT_TMR, APIC_LVT_INT_MASKED); //?? - uint32_t ticksInS = 0xFFFFFFFF - readAPIC(APIC_TMRCURRCNT); - - klog("%d MHz bus speed",ticksInS/1000); - - uint32_t countdown=0x0fffffff; // TODO: calc to be constant, depending on bus speed. (use pit for measurement?) - writeAPIC(APIC_TMRDIV, 0x3); - writeAPIC(APIC_LVT_TMR, 200 | TMR_PERIODIC); - writeAPIC(APIC_TMRINITCNT, countdown); } + -- cgit v1.2.3