/[rtmk]/rtmk/i386/smp-init.c
ViewVC logotype

Diff of /rtmk/i386/smp-init.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1.1.1 by jrydberg, Fri Dec 7 02:06:26 2001 UTC revision 1.2 by jrydberg, Mon Jan 7 01:09:57 2002 UTC
# Line 27  int cpu_mp_system = 0; Line 27  int cpu_mp_system = 0;
27    
28  #if NCPUS > 1  #if NCPUS > 1
29    
 #error "??? this code is not ready!"  
   
30  #include <rtmk/vm-param.h>  #include <rtmk/vm-param.h>
31  #include <rtmk/vm-types.h>  #include <rtmk/vm-types.h>
32    
33  #include "tm.h"  #include "tm.h"
34  #include "smp.h"  #include "smp.h"
35  #include "trace.h"  #include "trace.h"
36  #include "cpu-io.h"  #include "i386-io.h"
37  #include "cpu-regs.h"  #include "i386-regs.h"
38  #include "cpu-segment.h"  #include "i386-segment.h"
39  #include "cpu-trap.h"  #include "i386-trap.h"
40  #include "cpu-timer.h"  #include "pc-clocks.h"
41  #include "processor.h"  #include "processor.h"
42  #include "thread.h"  #include "thread.h"
43    
# Line 60  unsigned int apic_virtual_address = 0; Line 58  unsigned int apic_virtual_address = 0;
58  unsigned int ioapic_physical_address = 0;  unsigned int ioapic_physical_address = 0;
59  unsigned int ioapic_virtual_address = 0;  unsigned int ioapic_virtual_address = 0;
60    
61    unsigned int apic_timer_ticks_per_sec = 0;
62    
63  struct smp_scan_spots  struct smp_scan_spots
64  {  {
65    unsigned int start;    unsigned int start;
# Line 116  static inline void apic_write (unsigned Line 116  static inline void apic_write (unsigned
116  }  }
117    
118  void  void
119  cpu_smp_interrupt (struct exception_frame *frame)  apic_interrupt (int nr)
120  {  {
121        trace_printf ("apic intr %d", nr);
   if (frame->trapno != 251)  
     trace_printf ("apic interrupt %d on cpu %d", frame->trapno, CPU_CURRENT ());  
   
   if (frame->trapno == 251)  
     {  
       timer_interrupt (0);  
       apic_write (APIC_ICRT, 100);  
     }  
   apic_write (APIC_EOI, 0);  
122  }  }
123    
124  /* Read the value of the PIT.  */  /* Read the value of the PIT.  */
# Line 143  read_pit_timer (void) Line 134  read_pit_timer (void)
134    counter = inb (0x40);    counter = inb (0x40);
135    counter = counter + (inb (0x40) << 8);    counter = counter + (inb (0x40) << 8);
136    SPLON (spl);    SPLON (spl);
   trace_printf ("pit counter: %d", counter);  
137    return counter;    return counter;
138  }  }
139    
# Line 197  calibrate_delay (void) Line 187  calibrate_delay (void)
187    
188    loops_per_sec = 1 << 12;    loops_per_sec = 1 << 12;
189    
   printf ("Calibrating delay loop for CPU %d\n", CPU_CURRENT ());  
   
190    while (loops_per_sec <<= 1)    while (loops_per_sec <<= 1)
191      {      {
192        outb (0x43, 0x30);        /* one-shot mode.  */        outb (0x43, 0x30);        /* one-shot mode.  */
# Line 236  calibrate_delay (void) Line 224  calibrate_delay (void)
224    /* Get loops per sec, instead of loops per 65535 - 64000 pit ticks.  */    /* Get loops per sec, instead of loops per 65535 - 64000 pit ticks.  */
225    loops_per_sec *= PIT_CLKNUM / (65535 - 64000);    loops_per_sec *= PIT_CLKNUM / (65535 - 64000);
226    
227    printf ("ok - %lu.%02lu (%d) BogoMIPS\n", (loops_per_sec+2500)/500000,    printf ("cpu #%d %u.%02u (%d) bogomips\n", CPU_CURRENT (),
228            ((loops_per_sec+2500)/5000) % 100, loops_per_sec);            (loops_per_sec+2500)/500000, ((loops_per_sec+2500)/5000) % 100, loops_per_sec);
229  }  }
230    
231    
232  static void  static void
233  calibrate_apic_timer (int this_cpu)  calibrate_apic_timer (int this_cpu)
234  {  {
# Line 259  calibrate_apic_timer (int this_cpu) Line 248  calibrate_apic_timer (int this_cpu)
248    outb (0x43, 0x34);   // loop mode    outb (0x43, 0x34);   // loop mode
249    outb (0x40, 0xff);    outb (0x40, 0xff);
250    outb (0x40, 0xff);    outb (0x40, 0xff);
251      
252    #if 0
253    wait_pit_wrap ();    wait_pit_wrap ();
254    apic_write (APIC_TMICT, ~0); // Start APIC timer    apic_write (APIC_TMICT, ~0); // Start APIC timer
255    start_perf = read_pentium_clock();    start_perf = read_pentium_clock();
256    wait_pit_wrap();    wait_pit_wrap();
257    apic_count = apic_read (APIC_TMCCT);    apic_count = apic_read (APIC_TMCCT);
258    end_perf = read_pentium_clock();    end_perf = read_pentium_clock();
259    #endif
260    
261    bus_speed =    bus_speed =
262      (unsigned int) ((unsigned long long) PIT_CLKNUM      (unsigned int) ((unsigned long long) PIT_CLKNUM
# Line 274  calibrate_apic_timer (int this_cpu) Line 265  calibrate_apic_timer (int this_cpu)
265      (unsigned int) ((unsigned long long) PIT_CLKNUM      (unsigned int) ((unsigned long long) PIT_CLKNUM
266                      * (end_perf - start_perf) / 0xffff);                      * (end_perf - start_perf) / 0xffff);
267    
268    trace_printf ("start perf = %d", start_perf & 0xffffffff);    /* ??? hardcoded to 66 MHz, since the probe thing does not seem to work.  */
269    trace_printf ("end perf = %d", end_perf & 0xffffffff);  
270  #if 0    bus_speed = core_speed = 66000000;
271    trace_printf ("bus_speed = %d", bus_speed);    apic_timer_ticks_per_sec = bus_speed;
272    trace_printf ("core_speed = %d", core_speed);  
273  #endif    printf ("cpu #%d runs at %d/%d MHz\n", this_cpu,
   printf ("CPU %d runs at %ld/%ld MHz\n", this_cpu,  
274            (bus_speed + 500000) / 1000000, (core_speed + 500000) / 1000000);            (bus_speed + 500000) / 1000000, (core_speed + 500000) / 1000000);
275  }  }
276    
# Line 292  setup_apic (void) Line 282  setup_apic (void)
282  {  {
283    unsigned int config;    unsigned int config;
284    
285    /* set spurious interrupt vector to 0xff */    /* Set spurious interrupt vector to 0xff */
286    config = apic_read (APIC_SIVR) & 0xfffffc00;    config = apic_read (APIC_SIVR) & 0xfffffc00;
287    config |= APIC_ENABLE | 0xff;    config |= APIC_ENABLE | 0xff;
288    apic_write (APIC_SIVR, config);    apic_write (APIC_SIVR, config);
289    
290  #if 0    #if 0  
291    /* setup LINT0 as ExtINT */    /* Setup LINT0 as ExtINT */
292    config = (apic_read (APIC_LINT0) & 0xffff1c00);    config = (apic_read (APIC_LINT0) & 0xffff1c00);
293    config |= APIC_LVT_DM_ExtINT | APIC_LVT_IIPP | APIC_LVT_TM;    config |= APIC_LVT_DM_ExtINT | APIC_LVT_IIPP | APIC_LVT_TM;
294    apic_write (APIC_LINT0, config);    apic_write (APIC_LINT0, config);
295    
296    /* setup LINT1 as NMI */    /* Setup LINT1 as NMI */
297    config = (apic_read (APIC_LINT1) & 0xffff1c00);    config = (apic_read (APIC_LINT1) & 0xffff1c00);
298    config |= APIC_LVT_DM_NMI | APIC_LVT_IIPP;    config |= APIC_LVT_DM_NMI | APIC_LVT_IIPP;
299    apic_write (APIC_LINT1, config);    apic_write (APIC_LINT1, config);
300  #endif  #endif
301    
   /* setup timer */  
   config = apic_read (APIC_LVTT) & ~APIC_LVTT_MASK;  
   config |= 0xfb | APIC_LVTT_M; // vector 0xfb, timer masked  
   apic_write (APIC_LVTT, config);  
           
   apic_write (APIC_ICRT, 0); // zero out the clock  
           
302    config = apic_read (APIC_TDCR) & ~0x0000000f;    config = apic_read (APIC_TDCR) & ~0x0000000f;
303    config |= APIC_TDCR_1; // clock division by 1    config |= APIC_TDCR_1; // clock division by 1
304    apic_write (APIC_TDCR, config);    apic_write (APIC_TDCR, config);
305                    
306    /* setup error vector to 0xfe */    /* Setup error vector to 0xfe */
307    config = (apic_read (APIC_LVT3) & 0xffffff00) | 0xfe;    config = (apic_read (APIC_LVT3) & 0xffffff00) | 0xfe;
308    apic_write(APIC_LVT3, config);    apic_write(APIC_LVT3, config);
309    
310    /* accept all interrupts */    /* Accept all interrupts */
311    config = apic_read (APIC_TPRI) & 0xffffff00;    config = apic_read (APIC_TPRI) & 0xffffff00;
312    apic_write (APIC_TPRI, config);    apic_write (APIC_TPRI, config);
313    
# Line 345  start_cpu (int ncpu) Line 328  start_cpu (int ncpu)
328    
329    /* clear apic errors */    /* clear apic errors */
330    
   trace_printf ("booting cpu %d with apic id %d",  
                 ncpu, apicid);  
331  #if 1  #if 1
332    if (apic_version [ncpu] & 0xf0)    if (apic_version [ncpu] & 0xf0)
333      {      {
# Line 403  start_cpu (int ncpu) Line 384  start_cpu (int ncpu)
384    
385  /* New CPU with new kernel stack.  */  /* New CPU with new kernel stack.  */
386    
387  static void  void
388  new_cpu_with_new_stack (void)  new_cpu_with_new_stack (void)
389  {  {
390    struct processor *processor;    struct processor *processor;
391    int this_cpu;    int tss_seg;
392    
393    /* Tell bootstrap CPU that we are done.  */    /* Tell bootstrap CPU that we are done.  */
394    
# Line 420  new_cpu_with_new_stack (void) Line 401  new_cpu_with_new_stack (void)
401    trace_printf ("cpu %d ready", CPU_CURRENT ());    trace_printf ("cpu %d ready", CPU_CURRENT ());
402    spin_unlock (&cpuwait_lock);    spin_unlock (&cpuwait_lock);
403    
404    apic_write(APIC_ICRT, 100); // start it up    /* Initialize APIC timer, so that we can receive interrupts.  */
405      apic_write (APIC_ICRT, apic_timer_ticks_per_sec / HZ);
406    
407  #if 0    /* Set kernel TSS.  */
408    /* ??? switch to idle thread.  */    tss_seg = KERNEL_TSS + (0x8 * CPU_CURRENT ());
409    processor = PROCESSOR_CURRENT ();    __asm__ __volatile__ ("ltr %0" :: "rm" ((unsigned short) tss_seg));
   
 #if 1  
   LOAD_CONTEXT (processor->idle_thread);  
 #else  
   for (;;)  
     ;  
 #endif  
 #else  
   /* ??? switch to idle thread.  */  
   processor = PROCESSOR_CURRENT ();  
410    
411    LOAD_CONTEXT (thread_select (processor));    /* Load first thread into processor.  */
   for (;;)  
     ;  
 #endif  
412    
413      processor = PROCESSOR_CURRENT ();
414      LOAD_CONTEXT ((struct thread *) thread_select (processor));
415  }  }
416    
417    
# Line 450  new_cpu_with_new_stack (void) Line 421  new_cpu_with_new_stack (void)
421  void  void
422  cpu_smp_cpu_in (void)  cpu_smp_cpu_in (void)
423  {  {
424    int this_cpu, reg;    int this_cpu, reg, config;
425    
426    /* Switch to paged mode by loading CR3, set PG bit and jump    /* Switch to paged mode by loading CR3, set PG bit and jump
427       a step forward to flush insn queue.  */       a step forward to flush insn queue.  */
# Line 463  cpu_smp_cpu_in (void) Line 434  cpu_smp_cpu_in (void)
434                 "1:" : : "r" (get_cr0() | 0x80000000));                 "1:" : : "r" (get_cr0() | 0x80000000));
435    
436    /* Setup local APIC.  */    /* Setup local APIC.  */
437    /*  setup_apic (); */    setup_apic ();
438    
439      /* Setup timer */
440      config = apic_read (APIC_LVTT) & ~APIC_LVTT_MASK;
441      config |= 0xfb | APIC_LVTT_TM; // vector 0xfb, timer masked
442      apic_write (APIC_LVTT, config);
443            
444    reg = apic_read (APIC_SIVR);    reg = apic_read (APIC_SIVR);
445    reg |= (1 << 8);    reg |= (1 << 8);
446    apic_write (APIC_SIVR, reg);    apic_write (APIC_SIVR, reg);
# Line 573  smp_probe (unsigned int base, unsigned i Line 549  smp_probe (unsigned int base, unsigned i
549        /* Check signature, revision and length fields.  */        /* Check signature, revision and length fields.  */
550        if (flt->signature == IMPS_FPS_SIGNATURE        if (flt->signature == IMPS_FPS_SIGNATURE
551            && (flt->mp_rev == 1 || flt->mp_rev == 4) && (flt->mpc_len == 1))            && (flt->mp_rev == 1 || flt->mp_rev == 4) && (flt->mpc_len == 1))
552          {          return flt;
           trace_printf ("found floating pointer structure at %p\n", ptr);  
           return flt;  
         }  
553      }      }
554    return 0;    return 0;
555  }        }      
# Line 584  smp_probe (unsigned int base, unsigned i Line 557  smp_probe (unsigned int base, unsigned i
557  /* First constructor; scan for floating pointer structure and parses  /* First constructor; scan for floating pointer structure and parses
558     the configuration table.  */     the configuration table.  */
559    
560  static void CTOR_FN_ATTRIBUTE  void
561  initialize_config (void)  smp_bootstrap (void)
562  {  {
563    int i;    int i;
564    
# Line 611  initialize_config (void) Line 584  initialize_config (void)
584      }      }
585  }  }
586    
587  CONSTRUCTOR_FN (initialize_config, CTOR_LEVEL_ARCH);  void
588    smp_init_cpus (void)
 /* Second constructors; initializes all cpus.  */  
   
 static void CTOR_FN_ATTRIBUTE  
 initialize_cpus (void)  
589  {  {
590    extern void cpu_smp_startup_start (), cpu_smp_startup_end ();    extern void cpu_smp_startup_start (), cpu_smp_startup_end ();
591    unsigned char oldr;    unsigned char oldr;
# Line 636  initialize_cpus (void) Line 605  initialize_cpus (void)
605    ioapic_virtual_address = (unsigned int)    ioapic_virtual_address = (unsigned int)
606      PMAP_MAP_PHYSICAL (ioapic_physical_address, VM_PAGE_SIZE);      PMAP_MAP_PHYSICAL (ioapic_physical_address, VM_PAGE_SIZE);
607    
   trace_printf ("apic virtual address %x", apic_virtual_address);  
   
608    /* Initialize the APIC.  */    /* Initialize the APIC.  */
609    
610    setup_apic ();    setup_apic ();
# Line 683  initialize_cpus (void) Line 650  initialize_cpus (void)
650        ap_kernel_stacks [i] =        ap_kernel_stacks [i] =
651          (vm_offset_t) PMAP_STEAL_MEMORY (KERNEL_STACK_SIZE);          (vm_offset_t) PMAP_STEAL_MEMORY (KERNEL_STACK_SIZE);
652        assert (ap_kernel_stacks [i]);        assert (ap_kernel_stacks [i]);
653          
654        /* Start CPU.  */              /* Start CPU.  */      
655        start_cpu (i);        start_cpu (i);
656      }      }
# Line 696  initialize_cpus (void) Line 663  initialize_cpus (void)
663    PMAP_ENTER (PMAP_KERNEL (), 0, 0, 0, true);    PMAP_ENTER (PMAP_KERNEL (), 0, 0, 0, true);
664  }  }
665    
 CONSTRUCTOR_FN (initialize_cpus, CTOR_LEVEL_BOOTSTRAP);  
   
666  /* Just releases the CPU wait lock.  */  /* Just releases the CPU wait lock.  */
667    
668  void  void
669  cpu_smp_release_cpus (void)  cpu_smp_release_cpus (void)
670  {  {
 #if 0  
671    spin_unlock (&cpuwait_lock);    spin_unlock (&cpuwait_lock);
 #endif  
672  }  }
673    
674  /* Return current CPU number.  ??? this should be optimized.  */  /* Return current CPU number.  ??? this should be optimized.  */
# Line 721  cpu_cpu_current (void) Line 684  cpu_cpu_current (void)
684    return apic_id_to_cpu_map [apic_id];    return apic_id_to_cpu_map [apic_id];
685  }  }
686    
687    /* Assert a interprocess interrupt on all CPU's, except the one
688       that raises the interrupt.  */
689    
690    void
691    smp_ipi_broadcast (void)
692    {
693      unsigned int config;
694      SPL_T spl;
695    
696      spl = SPLOFF ();
697    
698      config = apic_read (APIC_ICR1) & APIC_ICR1_WRITE_MASK;
699      apic_write (APIC_ICR1, config | 0xfd | APIC_ICR1_DELMODE_FIXED
700                  | APIC_ICR1_DESTMODE_PHYS | APIC_ICR1_DEST_ALL_BUT_SELF);
701      SPLON (spl);
702    }
703    
704    /* Raise interprocess interrupt on TARGET_CPU.  */
705    
706    void
707    smp_ipi_send (int target_cpu)
708    {
709      unsigned int config;
710      SPL_T spl;
711    
712      spl = SPLOFF ();
713    
714      config = apic_read(APIC_ICR2) & APIC_ICR2_MASK;
715      apic_write(APIC_ICR2, config | cpu_id_to_apic_map [target_cpu] << 24);
716    
717      config = apic_read(APIC_ICR1) & APIC_ICR1_WRITE_MASK;
718      apic_write(APIC_ICR1, config | 0xfd | APIC_ICR1_DELMODE_FIXED
719                 | APIC_ICR1_DESTMODE_PHYS | APIC_ICR1_DEST_FIELD);
720    
721      SPLON (spl);
722    }
723    
724    
725  #endif /* NCPUS > 1 */  #endif /* NCPUS > 1 */

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26