Xv6 with picoc & Linkage editor
v1.0
The project delineate mutual cohesion between c library, linkage editor ( linker), interpreter and operating system by porting the same on xv6 kernel
|
00001 // Multiprocessor support 00002 // Search memory for MP description structures. 00003 // http://developer.intel.com/design/pentium/datashts/24201606.pdf 00004 00005 #include "types.h" 00006 #include "defs.h" 00007 #include "param.h" 00008 #include "memlayout.h" 00009 #include "mp.h" 00010 #include "x86.h" 00011 #include "mmu.h" 00012 #include "proc.h" 00013 00014 struct cpu cpus[NCPU]; 00015 static struct cpu *bcpu; 00016 int ismp; 00017 int ncpu; 00018 uchar ioapicid; 00019 00020 int 00021 mpbcpu(void) 00022 { 00023 return bcpu-cpus; 00024 } 00025 00026 static uchar 00027 sum(uchar *addr, int len) 00028 { 00029 int i, sum; 00030 00031 sum = 0; 00032 for(i=0; i<len; i++) 00033 sum += addr[i]; 00034 return sum; 00035 } 00036 00037 // Look for an MP structure in the len bytes at addr. 00038 static struct mp* 00039 mpsearch1(uint a, int len) 00040 { 00041 uchar *e, *p, *addr; 00042 00043 addr = p2v(a); 00044 e = addr+len; 00045 for(p = addr; p < e; p += sizeof(struct mp)) 00046 if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0) 00047 return (struct mp*)p; 00048 return 0; 00049 } 00050 00051 // Search for the MP Floating Pointer Structure, which according to the 00052 // spec is in one of the following three locations: 00053 // 1) in the first KB of the EBDA; 00054 // 2) in the last KB of system base memory; 00055 // 3) in the BIOS ROM between 0xE0000 and 0xFFFFF. 00056 static struct mp* 00057 mpsearch(void) 00058 { 00059 uchar *bda; 00060 uint p; 00061 struct mp *mp; 00062 00063 bda = (uchar *) P2V(0x400); 00064 if((p = ((bda[0x0F]<<8)| bda[0x0E]) << 4)){ 00065 if((mp = mpsearch1(p, 1024))) 00066 return mp; 00067 } else { 00068 p = ((bda[0x14]<<8)|bda[0x13])*1024; 00069 if((mp = mpsearch1(p-1024, 1024))) 00070 return mp; 00071 } 00072 return mpsearch1(0xF0000, 0x10000); 00073 } 00074 00075 // Search for an MP configuration table. For now, 00076 // don't accept the default configurations (physaddr == 0). 00077 // Check for correct signature, calculate the checksum and, 00078 // if correct, check the version. 00079 // To do: check extended table checksum. 00080 static struct mpconf* 00081 mpconfig(struct mp **pmp) 00082 { 00083 struct mpconf *conf; 00084 struct mp *mp; 00085 00086 if((mp = mpsearch()) == 0 || mp->physaddr == 0) 00087 return 0; 00088 conf = (struct mpconf*) p2v((uint) mp->physaddr); 00089 if(memcmp(conf, "PCMP", 4) != 0) 00090 return 0; 00091 if(conf->version != 1 && conf->version != 4) 00092 return 0; 00093 if(sum((uchar*)conf, conf->length) != 0) 00094 return 0; 00095 *pmp = mp; 00096 return conf; 00097 } 00098 00099 void 00100 mpinit(void) 00101 { 00102 uchar *p, *e; 00103 struct mp *mp; 00104 struct mpconf *conf; 00105 struct mpproc *proc; 00106 struct mpioapic *ioapic; 00107 00108 bcpu = &cpus[0]; 00109 if((conf = mpconfig(&mp)) == 0) 00110 return; 00111 ismp = 1; 00112 lapic = (uint*)conf->lapicaddr; 00113 for(p=(uchar*)(conf+1), e=(uchar*)conf+conf->length; p<e; ){ 00114 switch(*p){ 00115 case MPPROC: 00116 proc = (struct mpproc*)p; 00117 if(ncpu != proc->apicid){ 00118 cprintf("mpinit: ncpu=%d apicid=%d\n", ncpu, proc->apicid); 00119 ismp = 0; 00120 } 00121 if(proc->flags & MPBOOT) 00122 bcpu = &cpus[ncpu]; 00123 cpus[ncpu].id = ncpu; 00124 ncpu++; 00125 p += sizeof(struct mpproc); 00126 continue; 00127 case MPIOAPIC: 00128 ioapic = (struct mpioapic*)p; 00129 ioapicid = ioapic->apicno; 00130 p += sizeof(struct mpioapic); 00131 continue; 00132 case MPBUS: 00133 case MPIOINTR: 00134 case MPLINTR: 00135 p += 8; 00136 continue; 00137 default: 00138 cprintf("mpinit: unknown config type %x\n", *p); 00139 ismp = 0; 00140 } 00141 } 00142 if(!ismp){ 00143 // Didn't like what we found; fall back to no MP. 00144 ncpu = 1; 00145 lapic = 0; 00146 ioapicid = 0; 00147 return; 00148 } 00149 00150 if(mp->imcrp){ 00151 // Bochs doesn't support IMCR, so this doesn't run on Bochs. 00152 // But it would on real hardware. 00153 outb(0x22, 0x70); // Select IMCR 00154 outb(0x23, inb(0x23) | 1); // Mask external interrupts. 00155 } 00156 }