Warning, cross-references for /kernel/arch/i386/percpu.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <kernel.h>
0032 #include <util/debug.h>
0033 #include <mem/physical.h>
0034 #include <mem/virtual.h>
0035 #include <arch/i386-percpu.h>
0036 #include <smp/apic.h>
0037
0038
0039
0040 #ifdef DEBUG_PERCPU
0041 #define DLOG(fmt,...) DLOG_PREFIX("percpu",fmt,##__VA_ARGS__)
0042 #else
0043 #define DLOG(fmt,...) ;
0044 #endif
0045
0046 uint global_pcpu_id = 0;
0047
0048
0049
0050 DEF_PER_CPU (uint, pcpu_id);
0051 INIT_PER_CPU (pcpu_id) {
0052 percpu_write (pcpu_id, global_pcpu_id++);
0053 }
0054 extern uint
0055 get_pcpu_id (void)
0056 {
0057 return percpu_read (pcpu_id);
0058 }
0059
0060 extern s8 _percpu_pages_plus_one;
0061 extern void (*_percpu_ctor_list)();
0062
0063 u8 *percpu_virt[MAX_CPUS];
0064
0065
0066 extern void
0067 percpu_per_cpu_init (void)
0068 {
0069 descriptor *ad = (descriptor *)KERN_GDT;
0070 int i, pages = (int) &_percpu_pages_plus_one;
0071 int limit = pages * 0x1000 - 1;
0072
0073
0074
0075
0076
0077 if (pages == 1) {
0078 DLOG ("no per-CPU variables in system");
0079
0080 asm volatile ("movw %%ds, %%ax\n"
0081 "movw %%ax, %%"PER_CPU_SEG_STR"\n"
0082 "movzwl %%ax, %%eax\n"
0083 "movl %%eax, %%"PER_CPU_DBG_STR"":::"eax");
0084 return;
0085 }
0086
0087 pages--;
0088
0089 for (i=1; i<256; i++)
0090 if (ad[i].fPresent == 0)
0091 break;
0092 if (i == 256) panic ("out of GDT");
0093
0094 uint start_frame = alloc_phys_frames (pages);
0095 if (start_frame == -1) panic ("out of physical RAM");
0096 uint start_virt = (uint) map_contiguous_virtual_pages (start_frame | 3, pages);
0097 if (start_virt == 0) panic ("out of virtual RAM");
0098
0099 DLOG ("LAPIC_get_physical_ID=0x%X", LAPIC_get_physical_ID ());
0100
0101
0102 percpu_virt[global_pcpu_id] = (u8 *) start_virt;
0103
0104 descriptor seg = {
0105 .pBase0 = start_virt & 0xFFFF,
0106 .pBase1 = (start_virt >> 16) & 0xFF,
0107 .pBase2 = (start_virt >> 24) & 0xFF,
0108 .uLimit0 = limit & 0xFFFF,
0109 .uType = 0x12,
0110 .uDPL = 0,
0111 .fPresent = 1,
0112 .uLimit1 = (limit >> 16) & 0xF,
0113 .f = 0,
0114 .f0 = 0,
0115 .fX = 1,
0116 .fGranularity = 0
0117 };
0118
0119 memcpy (&ad[i], &seg, sizeof (seg));
0120
0121 i <<= 3;
0122
0123 asm volatile ("mov %0, %%"PER_CPU_SEG_STR"\n"
0124 "mov %0, %%"PER_CPU_DBG_STR :: "r" (i));
0125
0126
0127 void (**ctor) ();
0128 for (ctor = &_percpu_ctor_list; *ctor; ctor++)
0129 (*ctor) ();
0130
0131 DLOG ("init n=%d percpu_pages=%d segsel=0x%X start_frame=%p start_virt=%p",
0132 percpu_read (pcpu_id), pages, i, start_frame, start_virt);
0133 }
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144