Subversion Repositories HelenOS

Rev

Rev 11 | Rev 13 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2001-2004 Jakub Jermar
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. #ifdef __SMP__
  30.  
  31. #include <arch/pm.h>
  32. #include <config.h>
  33. #include <print.h>
  34. #include <panic.h>
  35. #include <arch/smp/mp.h>
  36. #include <arch/smp/ap.h>
  37. #include <arch/smp/apic.h>
  38. #include <func.h>
  39. #include <arch/types.h>
  40. #include <typedefs.h>
  41. #include <synch/waitq.h>
  42. #include <time/delay.h>
  43. #include <mm/heap.h>
  44. #include <mm/page.h>
  45. #include <mm/frame.h>
  46. #include <cpu.h>
  47. #include <arch/i8259.h>
  48. #include <arch/asm.h>
  49.  
  50. /*
  51.  * Multi-Processor Specification detection code.
  52.  */
  53.  
  54. #define FS_SIGNATURE    0x5f504d5f
  55. #define CT_SIGNATURE    0x504d4350
  56.  
  57. int mp_fs_check(__u8 *base);
  58. int mp_ct_check(void);
  59.  
  60. int configure_via_ct(void);
  61. int configure_via_default(__u8 n);
  62.  
  63. int ct_processor_entry(struct __processor_entry *pr);
  64. void ct_bus_entry(struct __bus_entry *bus);
  65. void ct_io_apic_entry(struct __io_apic_entry *ioa);
  66. void ct_io_intr_entry(struct __io_intr_entry *iointr);
  67. void ct_l_intr_entry(struct __l_intr_entry *lintr);
  68.  
  69. void ct_extended_entries(void);
  70.  
  71. static struct __mpfs *fs;
  72. static struct __mpct *ct;
  73.  
  74. struct __processor_entry *processor_entries = NULL;
  75. struct __bus_entry *bus_entries = NULL;
  76. struct __io_apic_entry *io_apic_entries = NULL;
  77. struct __io_intr_entry *io_intr_entries = NULL;
  78. struct __l_intr_entry *l_intr_entries = NULL;
  79.  
  80. int processor_entry_cnt = 0;
  81. int bus_entry_cnt = 0;
  82. int io_apic_entry_cnt = 0;
  83. int io_intr_entry_cnt = 0;
  84. int l_intr_entry_cnt = 0;
  85.  
  86. waitq_t ap_completion_wq;
  87. waitq_t kmp_completion_wq;
  88.  
  89. /*
  90.  * Used to check the integrity of the MP Floating Structure.
  91.  */
  92. int mp_fs_check(__u8 *base)
  93. {
  94.     int i;
  95.     __u8 sum;
  96.    
  97.     for (i = 0, sum = 0; i < 16; i++)
  98.         sum += base[i];
  99.    
  100.     return !sum;
  101. }
  102.  
  103. /*
  104.  * Used to check the integrity of the MP Configuration Table.
  105.  */
  106. int mp_ct_check(void)
  107. {
  108.     __u8 *base = (__u8 *) ct;
  109.     __u8 *ext = base + ct->base_table_length;
  110.     __u8 sum;
  111.     int i; 
  112.    
  113.     /* count the checksum for the base table */
  114.     for (i=0,sum=0; i < ct->base_table_length; i++)
  115.         sum += base[i];
  116.        
  117.     if (sum)
  118.         return 0;
  119.        
  120.     /* count the checksum for the extended table */
  121.     for (i=0,sum=0; i < ct->ext_table_length; i++)
  122.         sum += ext[i];
  123.        
  124.     return sum == ct->ext_table_checksum;
  125. }
  126.  
  127. void mp_init(void)
  128. {
  129.     __address addr, frame;
  130.     int cnt, n;
  131.    
  132.  
  133.     /*
  134.      * First place to search the MP Floating Pointer Structure is the Extended
  135.      * BIOS Data Area. We have to read EBDA segment address from the BIOS Data
  136.      * Area. Unfortunatelly, this memory is in page 0, which has intentionally no
  137.      * mapping.
  138.      */
  139.     frame = frame_alloc(FRAME_KA);
  140.     map_page_to_frame(frame,0,PAGE_CACHEABLE,0);
  141.     addr = *((__u16 *) (frame + 0x40e)) * 16;
  142.     map_page_to_frame(frame,frame,PAGE_CACHEABLE,0);
  143.     frame_free(frame); 
  144.  
  145.     /*
  146.      * EBDA can be undefined. In that case addr would be 0.
  147.      */
  148.     if (addr >= 0x1000) {
  149.         cnt = 1024;
  150.         while (addr = __u32_search(addr,cnt,FS_SIGNATURE)) {
  151.             if (mp_fs_check((__u8 *) addr))
  152.                 goto fs_found;
  153.             addr++;
  154.             cnt--;
  155.         }
  156.     }
  157.    
  158.     /*
  159.      * Second place where the MP Floating Pointer Structure may live is the last
  160.      * kilobyte of base memory.
  161.      */
  162.     addr = 639*1024;
  163.     cnt = 1024;
  164.     while (addr = __u32_search(addr,cnt,FS_SIGNATURE)) {
  165.         if (mp_fs_check((__u8 *) addr))
  166.             goto fs_found;
  167.         addr++;
  168.         cnt--;
  169.     }
  170.  
  171.     /*
  172.      * As the last resort, MP Floating Pointer Structure is searched in the BIOS
  173.      * ROM.
  174.      */
  175.     addr = 0xf0000;
  176.     cnt = 64*1024;
  177.     while (addr = __u32_search(addr,cnt,FS_SIGNATURE)) {
  178.         if (mp_fs_check((__u8 *) addr))
  179.             goto fs_found;
  180.         addr++;
  181.         cnt--;
  182.     }
  183.  
  184.     return;
  185.    
  186. fs_found:
  187.     printf("%L: MP Floating Pointer Structure\n", addr);
  188.  
  189.     fs = (struct __mpfs *) addr;
  190.     frame_not_free((__address) fs);
  191.    
  192.     if (fs->config_type == 0 && fs->configuration_table) {
  193.         if (fs->mpfib2 >> 7) {
  194.             printf("mp_init: PIC mode not supported\n");
  195.             return;
  196.         }
  197.  
  198.         ct = fs->configuration_table;
  199.         frame_not_free((__address) ct);
  200.         config.cpu_count = configure_via_ct();
  201.     }
  202.     else
  203.         config.cpu_count = configure_via_default(fs->config_type);
  204.  
  205.     if (config.cpu_count > 1) {
  206.         map_page_to_frame((__address) l_apic, (__address) l_apic, PAGE_NOT_CACHEABLE, 0);
  207.     }      
  208.    
  209.    
  210.     /*
  211.      * Must be initialized outside the kmp thread, since it is waited
  212.      * on before the kmp thread is created.
  213.      */
  214.     waitq_initialize(&kmp_completion_wq);
  215.     return;
  216. }
  217.  
  218. int configure_via_ct(void)
  219. {
  220.     __u8 *cur;
  221.     int i, cnt;
  222.        
  223.     if (ct->signature != CT_SIGNATURE) {
  224.         printf("configure_via_ct: bad ct->signature\n");
  225.         return 1;
  226.     }
  227.     if (!mp_ct_check()) {
  228.         printf("configure_via_ct: bad ct checksum\n");
  229.         return 1;
  230.     }
  231.     if (ct->oem_table) {
  232.         printf("configure_via_ct: ct->oem_table not supported\n");
  233.         return 1;
  234.     }
  235.    
  236.     l_apic = ct->l_apic;
  237.  
  238.     cnt = 0;
  239.     cur = &ct->base_table[0];
  240.     for (i=0; i < ct->entry_count; i++) {
  241.         switch (*cur) {
  242.             /* Processor entry */
  243.             case 0:
  244.                 processor_entries = processor_entries ? processor_entries : (struct __processor_entry *) cur;
  245.                 processor_entry_cnt++;
  246.                 cnt += ct_processor_entry((struct __processor_entry *) cur);
  247.                 cur += 20;
  248.                 break;
  249.  
  250.             /* Bus entry */
  251.             case 1:
  252.                 bus_entries = bus_entries ? bus_entries : (struct __bus_entry *) cur;
  253.                 bus_entry_cnt++;
  254.                 ct_bus_entry((struct __bus_entry *) cur);
  255.                 cur += 8;
  256.                 break;
  257.                
  258.             /* I/O Apic */
  259.             case 2:
  260.                 io_apic_entries = io_apic_entries ? io_apic_entries : (struct __io_apic_entry *) cur;
  261.                 io_apic_entry_cnt++;
  262.                 ct_io_apic_entry((struct __io_apic_entry *) cur);
  263.                 cur += 8;
  264.                 break;
  265.                
  266.             /* I/O Interrupt Assignment */
  267.             case 3:
  268.                 io_intr_entries = io_intr_entries ? io_intr_entries : (struct __io_intr_entry *) cur;
  269.                 io_intr_entry_cnt++;
  270.                 ct_io_intr_entry((struct __io_intr_entry *) cur);
  271.                 cur += 8;
  272.                 break;
  273.  
  274.             /* Local Interrupt Assignment */
  275.             case 4:
  276.                 l_intr_entries = l_intr_entries ? l_intr_entries : (struct __l_intr_entry *) cur;
  277.                 l_intr_entry_cnt++;
  278.                 ct_l_intr_entry((struct __l_intr_entry *) cur);
  279.                     cur += 8;
  280.                 break;
  281.        
  282.             default:
  283.                 /*
  284.                  * Something is wrong. Fallback to UP mode.
  285.                  */
  286.                  
  287.                 printf("configure_via_ct: ct badness\n");
  288.                 return 1;
  289.         }
  290.     }
  291.    
  292.     /*
  293.      * Process extended entries.
  294.      */
  295.     ct_extended_entries();
  296.     return cnt;
  297. }
  298.  
  299. int configure_via_default(__u8 n)
  300. {
  301.     /*
  302.      * Not yet implemented.
  303.      */
  304.     printf("configure_via_default: not supported\n");
  305.     return 1;
  306. }
  307.  
  308.  
  309. int ct_processor_entry(struct __processor_entry *pr)
  310. {
  311.     /*
  312.      * Ignore processors which are not marked enabled.
  313.      */
  314.     if ((pr->cpu_flags & (1<<0)) == 0)
  315.         return 0;
  316.    
  317.     apic_id_mask |= (1<<pr->l_apic_id);
  318.     return 1;
  319. }
  320.  
  321. void ct_bus_entry(struct __bus_entry *bus)
  322. {
  323. #ifdef MPCT_VERBOSE
  324.     char buf[7];
  325.     memcopy((__address) bus->bus_type, (__address) buf,6);
  326.     buf[6] = 0;
  327.     printf("bus%d: %s\n", bus->bus_id, buf);
  328. #endif
  329. }
  330.  
  331. void ct_io_apic_entry(struct __io_apic_entry *ioa)
  332. {
  333.     static int io_apic_count = 0;
  334.  
  335.     /* this ioapic is marked unusable */
  336.     if (ioa->io_apic_flags & 1 == 0)
  337.         return;
  338.    
  339.     if (io_apic_count++ > 0) {
  340.         /*
  341.          * Multiple IO APIC's are currently not supported.
  342.          */
  343.         return;
  344.     }
  345.    
  346.     map_page_to_frame((__address) ioa->io_apic, (__address) ioa->io_apic, PAGE_NOT_CACHEABLE, 0);
  347.    
  348.     io_apic = ioa->io_apic;
  349. }
  350.  
  351. //#define MPCT_VERBOSE
  352. void ct_io_intr_entry(struct __io_intr_entry *iointr)
  353. {
  354. #ifdef MPCT_VERBOSE
  355.     switch (iointr->intr_type) {
  356.         case 0: printf("INT"); break;
  357.         case 1: printf("NMI"); break;
  358.         case 2: printf("SMI"); break;
  359.         case 3: printf("ExtINT"); break;
  360.     }
  361.     putchar(',');
  362.     switch (iointr->poel&3) {
  363.         case 0: printf("bus-like"); break;
  364.         case 1: printf("active high"); break;
  365.         case 2: printf("reserved"); break;
  366.         case 3: printf("active low"); break;
  367.     }
  368.     putchar(',');
  369.     switch ((iointr->poel>>2)&3) {
  370.         case 0: printf("bus-like"); break;
  371.         case 1: printf("edge-triggered"); break;
  372.         case 2: printf("reserved"); break;
  373.         case 3: printf("level-triggered"); break;
  374.     }
  375.     putchar(',');
  376.     printf("bus%d,irq%d", iointr->src_bus_id, iointr->src_bus_irq);
  377.     putchar(',');
  378.     printf("io_apic%d,pin%d", iointr->dst_io_apic_id, iointr->dst_io_apic_pin);
  379.     putchar('\n'); 
  380. #endif
  381. }
  382.  
  383. void ct_l_intr_entry(struct __l_intr_entry *lintr)
  384. {
  385. #ifdef MPCT_VERBOSE
  386.     switch (lintr->intr_type) {
  387.         case 0: printf("INT"); break;
  388.         case 1: printf("NMI"); break;
  389.         case 2: printf("SMI"); break;
  390.         case 3: printf("ExtINT"); break;
  391.     }
  392.     putchar(',');
  393.     switch (lintr->poel&3) {
  394.         case 0: printf("bus-like"); break;
  395.         case 1: printf("active high"); break;
  396.         case 2: printf("reserved"); break;
  397.         case 3: printf("active low"); break;
  398.     }
  399.     putchar(',');
  400.     switch ((lintr->poel>>2)&3) {
  401.         case 0: printf("bus-like"); break;
  402.         case 1: printf("edge-triggered"); break;
  403.         case 2: printf("reserved"); break;
  404.         case 3: printf("level-triggered"); break;
  405.     }
  406.     putchar(',');
  407.     printf("bus%d,irq%d", lintr->src_bus_id, lintr->src_bus_irq);
  408.     putchar(',');
  409.     printf("l_apic%d,pin%d", lintr->dst_l_apic_id, lintr->dst_l_apic_pin);
  410.     putchar('\n');
  411. #endif
  412. }
  413.  
  414. void ct_extended_entries(void)
  415. {
  416.     /*
  417.      * Not yet implemented.
  418.      */
  419.     if (ct->ext_table_length)
  420.         panic("ct_extended_entries: not supported\n");
  421. }
  422.  
  423. /*
  424.  * Kernel thread for bringing up application processors. It becomes clear
  425.  * that we need an arrangement like this (AP's being initialized by a kernel
  426.  * thread), for a thread has its dedicated stack. (The stack used during the
  427.  * BSP initialization (prior the very first call to scheduler()) will be used
  428.  * as an initialization stack for each AP.)
  429.  */
  430. void kmp(void *arg)
  431. {
  432.     struct __processor_entry *pr;
  433.     __address src, dst;
  434.     __address frame;
  435.     int i;
  436.  
  437.     waitq_initialize(&ap_completion_wq);
  438.  
  439.     /*
  440.      * Processor entries immediately follow the configuration table header.
  441.      */
  442.     pr = processor_entries;
  443.  
  444.     /*
  445.      * Grab a frame and map its address to page 0. This is a hack which
  446.      * accesses data in frame 0. Note that page 0 is not present because
  447.      * of nil reference bug catching.
  448.      */
  449.     frame = frame_alloc(FRAME_KA);
  450.     map_page_to_frame(frame,0,PAGE_CACHEABLE,0);
  451.  
  452.     /*
  453.      * Set the warm-reset vector to the real-mode address of 4K-aligned ap_boot()
  454.      */
  455.     *((__u16 *) (frame + 0x467+0)) =  ((__address) ap_boot) >> 4;   /* segment */
  456.     *((__u16 *) (frame + 0x467+2)) =  0x0;  /* offset */
  457.    
  458.     /*
  459.      * Give back the borrowed frame and restore identity mapping for it.
  460.      */
  461.     map_page_to_frame(frame,frame,PAGE_CACHEABLE,0);
  462.     frame_free(frame);
  463.  
  464.     /*
  465.      * Save 0xa to address 0xf of the CMOS RAM.
  466.      * BIOS will not do the POST after the INIT signal.
  467.      */
  468.     outb(0x70,0xf);
  469.     outb(0x71,0xa);
  470.  
  471.     cpu_priority_high();
  472.  
  473.     pic_disable_irqs(0xffff);
  474.     apic_init();
  475.  
  476.     for (i = 0; i < processor_entry_cnt; i++) {
  477.         struct descriptor *gdt_new;
  478.    
  479.         /*
  480.          * Skip processors marked unusable.
  481.          */
  482.         if (pr[i].cpu_flags & (1<<0) == 0)
  483.             continue;
  484.    
  485.         /*
  486.          * The bootstrap processor is already up.
  487.          */
  488.         if (pr[i].cpu_flags & (1<<1))
  489.             continue;
  490.        
  491.         /*
  492.          * Prepare new GDT for CPU in question.
  493.          */
  494.         if (!(gdt_new = (struct descriptor *) malloc(GDT_ITEMS*sizeof(struct descriptor))))
  495.             panic(PANIC "couldn't allocate memory for GDT\n");
  496.  
  497.         memcopy(gdt, gdt_new, GDT_ITEMS*sizeof(struct descriptor));
  498.         gdtr.base = (__address) gdt_new;
  499.        
  500.         if (l_apic_send_init_ipi(pr[i].l_apic_id)) {
  501.             /*
  502.                  * There may be just one AP being initialized at
  503.              * the time. After it comes completely up, it is
  504.              * supposed to wake us up.
  505.                  */
  506.             waitq_sleep(&ap_completion_wq);
  507.             cpu_priority_high();
  508.         }
  509.         else {
  510.             printf("INIT IPI for l_apic%d failed\n", pr[i].l_apic_id);
  511.         }
  512.     }
  513.  
  514.     /*
  515.      * Wakeup the kinit thread so that
  516.      * system initialization can go on.
  517.      */
  518.     waitq_wakeup(&kmp_completion_wq, WAKEUP_FIRST);
  519. }
  520.  
  521. int mp_irq_to_pin(int irq)
  522. {
  523.     int i;
  524.    
  525.     for(i=0;i<io_intr_entry_cnt;i++) {
  526.         if (io_intr_entries[i].src_bus_irq == irq && io_intr_entries[i].intr_type == 0)
  527.             return io_intr_entries[i].dst_io_apic_pin;
  528.     }
  529.    
  530.     return -1;
  531. }
  532.  
  533. #endif /* __SMP__ */
  534.