00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <utility/elf.h>
00015 #include <utility/string.h>
00016 #include <utility/ostream.h>
00017 #include <utility/debug.h>
00018 #include <mach/pc/pc.h>
00019
00020 ASM("jmp _start");
00021
00022 __USING_SYS
00023
00024
00025 typedef CPU::Reg8 Reg8;
00026 typedef CPU::Reg16 Reg16;
00027 typedef CPU::Reg32 Reg32;
00028 typedef CPU::Reg64 Reg64;
00029 typedef CPU::Phy_Addr Phy_Addr;
00030 typedef CPU::Log_Addr Log_Addr;
00031 typedef MMU::Page Page;
00032 typedef MMU::Page_Table Page_Table;
00033 typedef MMU::Page_Directory Page_Directory;
00034 typedef MMU::PT_Entry PT_Entry;
00035 typedef MMU::PD_Entry PD_Entry;
00036 typedef MMU::IA32_Flags Flags;
00037
00038
00039 typedef System_Info::Physical_Memory_Map PMM;
00040 typedef System_Info::Logical_Memory_Map LMM;
00041 typedef System_Info::Boot_Map BM;
00042 typedef Memory_Map<PC> MM;
00043 typedef Traits<PC> TR;
00044
00045
00046 extern "C" { void _start(); }
00047 int main(char *, unsigned int, char *);
00048 void setup_pci(Phy_Addr *, unsigned int *, System_Info *);
00049 void setup_gdt(Phy_Addr);
00050 void setup_idt(Phy_Addr);
00051 void setup_sys_pt(PMM *, int, int);
00052 void setup_sys_pd(PMM *, unsigned int, Phy_Addr, unsigned int);
00053 void setup_lmm(LMM *, Log_Addr, Log_Addr);
00054 void copy_sys_info(System_Info *, System_Info *);
00055 void call_next(Log_Addr);
00056 void page_fault(Reg32, Reg32, Reg32, Reg32, Reg32, Reg32);
00057 void gpf(Reg32, Reg32, Reg32, Reg32, Reg32, Reg32);
00058 void fpu();
00059 void syscall();
00060 void panic();
00061
00062 __BEGIN_SYS
00063
00064 OStream kout, kerr;
00065 bool has_system;
00066
00067 __END_SYS
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 void _start()
00086 {
00087 IA32 cpu;
00088
00089
00090 cpu.flags(cpu.flags() & CPU::FLAG_CLEAR);
00091
00092
00093 char * bi = reinterpret_cast<char *>(TR::BOOT_IMAGE_ADDR);
00094
00095
00096 System_Info * si = reinterpret_cast<System_Info *>(bi);
00097
00098
00099 ELF * elf = reinterpret_cast<ELF *>(&bi[si->bm.setup_off]);
00100 if(!elf->valid())
00101 panic();
00102 char * entry = reinterpret_cast<char *>(elf->entry());
00103
00104
00105
00106
00107 *entry = 'G';
00108 if(*entry != 'G')
00109 panic();
00110
00111
00112
00113 register char * addr = reinterpret_cast<char *>(elf->segment_address(0));
00114 register int size = elf->segment_size(0);
00115 if(addr <= &bi[si->bm.img_size])
00116 panic();
00117 if(elf->load_segment(0) < 0)
00118 panic();
00119
00120
00121
00122
00123 register char * dst = entry + size + sizeof(Page);
00124 memcpy(dst, bi, si->bm.img_size);
00125
00126
00127
00128
00129 ASM("movl %0, %%esp" : : "r" (dst));
00130
00131
00132 ASM("pushl %0" : : "r" (dst));
00133
00134
00135 ASM("pushl %0" : : "r" (size));
00136
00137
00138 ASM("pushl %0" : : "r" (addr));
00139
00140
00141
00142 ASM("call *%0" : : "r" (&main));
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 int main(char * setup_addr, unsigned int setup_size, char * bi)
00157 {
00158 IA32 cpu;
00159 ELF * elf;
00160
00161
00162 db<Setup>(INF) << "SETUP(bi=" << (void *)bi << ")\n";
00163
00164
00165 System_Info * si = reinterpret_cast<System_Info *>(bi);
00166 has_system = (si->bm.system_off != -1);
00167 if(!has_system)
00168 db<Setup>(WRN) << "No SYSTEM in boot image, assuming EPOS is a library!\n";
00169
00170
00171
00172
00173
00174 PC_IC ic;
00175 ic.remap();
00176 ic.disable();
00177
00178
00179 Phy_Addr io_mem_phy_addr;
00180 unsigned int io_mem_size;
00181 setup_pci(&io_mem_phy_addr, &io_mem_size, si);
00182 db<Setup>(INF) << "PCI address space={base="
00183 << (void *)io_mem_phy_addr << ",size="
00184 << (void *)io_mem_size << "}\n";
00185
00186 // If we didn't get our node's id in the boot image, we'll to try to
00187 // get if from an eventual BOOPT reply used to boot up the system before
00188 // we allocate more memory
00189 // if(si->bm.host_id == (unsigned short) -1)
00190 // get_bootp_info(&si->bm.host_id);
00191
00192 // Check OS integrity and get the size of its code and data segments
00193 Log_Addr sys_entry = 0;
00194 unsigned int sys_segments = 0;
00195 unsigned int sys_code_size = 0;
00196 unsigned int sys_data_size = 0;
00197 if(has_system) {
00198 elf = reinterpret_cast<ELF *>(&bi[si->bm.system_off]);
00199 if(elf->valid()) {
00200 sys_entry = elf->entry();
00201 sys_segments = elf->segments();
00202 sys_code_size = elf->segment_size(0);
00203 for(unsigned int i = 1; i < sys_segments; i++)
00204 sys_data_size += elf->segment_size(i);
00205 } else {
00206 db<Setup>(ERR) << "OS ELF image is corrupted!\n";
00207 panic();
00208 }
00209 }
00210
00211 // Check APP integrity and get the size of all its segments
00212 elf = (ELF *) &bi[si->bm.loader_off];
00213 if(!elf->valid()) {
00214 db<Setup>(ERR) << "Application ELF image is corrupted!\n";
00215 panic();
00216 }
00217 Log_Addr app_entry = elf->entry();
00218 unsigned int app_segments = elf->segments();
00219 Log_Addr app_code = elf->segment_address(0);
00220 unsigned int app_code_size = elf->segment_size(0);
00221 Log_Addr app_data;
00222 unsigned int app_data_size = 0;
00223 if(elf->segments() > 1) {
00224 for(int i = 1; i < elf->segments(); i++) {
00225 if(elf->segment_type(i) != PT_LOAD)
00226 continue;
00227 unsigned int *addr = (unsigned int *) elf->segment_address(i);
00228 if((*addr) < si->lmm.app_data)
00229 app_data = elf->segment_address(i);
00230 app_data_size += elf->segment_size(i);
00231 }
00232 }
00233
00234 // Say hi! :-)
00235 kout << "Setting up this machine as follows: \n";
00236 kout << " Processor: IA32\n";
00237 kout << " Memory: " << si->bm.mem_size/1024 << " Kbytes\n";
00238 kout << " Host Id: ";
00239 if(si->bm.host_id != (unsigned short) -1)
00240 kout << si->bm.host_id << "\n";
00241 else
00242 kout << "will get from the network!\n";
00243 kout << " Tasks: " << si->bm.n_tasks << " (max)\n";
00244 kout << " Threads: " << si->bm.n_threads << " (max)\n";
00245 kout << " Setup: " << setup_size << " bytes\n";
00246 kout << " OS code: " << sys_code_size << " bytes";
00247 kout << "\t\tOS data: " << sys_data_size << " bytes\n";
00248 kout << " APP code: " << app_code_size << " bytes";
00249 kout << "\t\tAPP data: " << app_data_size << " bytes\n";
00250
00251 // Align and convert the following sizes to pages
00252 io_mem_size = MMU::pages(io_mem_size);
00253 sys_code_size = MMU::pages(sys_code_size);
00254 sys_data_size = MMU::pages(sys_data_size);
00255 app_code_size = MMU::pages(app_code_size);
00256 app_data_size = MMU::pages(app_data_size);
00257 si->mem_size = MMU::pages(si->bm.mem_size);
00258 si->mem_free = si->mem_size;
00259
00260 // Allocate (reserve) memory for all entities we have to setup.
00261 // We'll start at the highest address to make possible a memory model
00262 // on which the application's logical and physical address spaces match.
00263
00264 // IDT (1 x sizeof(Page))
00265 si->mem_free -= 1;
00266 si->pmm.int_vec = si->mem_free * sizeof(Page);
00267
00268 // GDT (1 x sizeof(Page))
00269 si->mem_free -= 1;
00270 si->pmm.mach1 = si->mem_free * sizeof(Page);
00271
00272 // System Page Table (1 x sizeof(Page))
00273 si->mem_free -= 1;
00274 si->pmm.sys_pt = si->mem_free * sizeof(Page);
00275
00276 // System Page Directory (1 x sizeof(Page))
00277 si->mem_free -= 1;
00278 si->pmm.sys_pd = si->mem_free * sizeof(Page);
00279
00280 // System Info (1 x sizeof(Page))
00281 si->mem_free -= 1;
00282 si->pmm.sys_info = si->mem_free * sizeof(Page);
00283
00284 // Page tables to map the whole physical memory
00285 // = NP/NPTE_PT * sizeof(Page)
00286 // NP = size of physical memory in pages
00287 // NPTE_PT = number of page table entries per page table
00288 si->mem_free -= (si->mem_size + MMU::PT_ENTRIES - 1) / MMU::PT_ENTRIES;
00289 si->pmm.phy_mem_pts = si->mem_free * sizeof(Page);
00290
00291 // Page tables to map the IO address space
00292 // = NP/NPTE_PT * sizeof(Page)
00293 // NP = size of PCI address space in pages
00294 // NPTE_PT = number of page table entries per page table
00295 si->mem_free -= (io_mem_size + MMU::PT_ENTRIES - 1) / MMU::PT_ENTRIES;
00296 si->pmm.io_mem_pts = si->mem_free * sizeof(Page);
00297
00298 // OS code segment (in pages)
00299 si->mem_free -= sys_code_size;
00300 si->pmm.sys_code = si->mem_free * sizeof(Page);
00301
00302 // OS data segment (in pages)
00303 si->mem_free -= sys_data_size;
00304 si->pmm.sys_data = si->mem_free * sizeof(Page);
00305
00306 // OS stack segment (1 x sizeof(Page))
00307 si->mem_free -= 1;
00308 si->pmm.sys_stack = si->mem_free * sizeof(Page);
00309
00310 // All memory bolow this is free to applications
00311 si->pmm.app_lo = si->bm.mem_base;
00312 si->pmm.app_hi = si->mem_free * sizeof(Page);
00313 si->pmm.mach2 = app_code + app_code_size * sizeof(Page);
00314 si->pmm.mach3 = MMU::pages(app_data - app_code) - app_code_size;
00315 si->pmm.free = app_data + app_data_size * sizeof(Page);
00316 si->pmm.free_size = MMU::pages(si->pmm.app_hi - app_data) - app_data_size;
00317
00318
00319 // Test if we didn't overlap SETUP and the boot image
00320 if(si->mem_free * sizeof(Page) <= (unsigned int)setup_addr + setup_size) {
00321 db<Setup>(ERR) << "SETUP would have been overwritten!\n";
00322 panic();
00323 }
00324
00325 // Zero the memory allocated to the system
00326 memset((void *)(si->mem_free * sizeof(Page)), 0,
00327 (si->mem_size - si->mem_free) * sizeof(Page));
00328
00329 // Setup the IDT
00330 setup_idt(si->pmm.int_vec);
00331
00332 // Setup the GDT
00333 setup_gdt(si->pmm.mach1);
00334
00335 // Setup the System Page Table
00336 setup_sys_pt(&si->pmm, sys_code_size, sys_data_size);
00337
00338 // Setup the System Page Directory and map physical memory
00339 setup_sys_pd(&si->pmm, si->mem_size, io_mem_phy_addr, io_mem_size);
00340
00341 // Set IDTR (limit = 1 x sizeof(Page))
00342 cpu.idtr(sizeof(Page) - 1, MM::INT_VEC);
00343
00344 // Reload GDTR with its linear address (one more absurd from Intel!)
00345 cpu.gdtr(sizeof(Page) - 1, MM::MACH1);
00346
00347 // Set CR3 (PDBR) register
00348 cpu.cr3(si->pmm.sys_pd);
00349
00350 // Enable paging
00351 Reg32 aux = cpu.cr0();
00352 aux &= CPU::CR0_CLEAR;
00353 aux |= CPU::CR0_SET;
00354 cpu.cr0(aux);
00355
00356 db<Setup>(INF) << "CR0=" << (void *)cpu.cr0() << "\n";
00357 db<Setup>(INF) << "CR3=" << (void *)cpu.cr3() << "\n";
00358
00359 // The following relative jump is to break the IA32 pre-fetch queue
00360 // (in case cr0() was a macro and didn't do it when returning)
00361 // and also to start using logical addresses
00362 ASM("ljmp %0, %1 + next" : : "i"(CPU::SEL_FLT_CODE), "i"(MM::PHY_MEM));
00363 ASM("next:");
00364
00365 // Reload segment registers with GDT_FLT_DATA
00366 ASM("" : : "a" (CPU::SEL_FLT_DATA));
00367 ASM("movw %ax, %ds");
00368 ASM("movw %ax, %es");
00369 ASM("movw %ax, %fs");
00370 ASM("movw %ax, %gs");
00371 ASM("movw %ax, %ss");
00372
00373 // Set stack pointer to its logical address
00374 ASM("orl %0, %%esp" : : "i" (MM::PHY_MEM));
00375
00376 // Adjust pointers that will still be used to their logical addresses
00377 bi = reinterpret_cast<char *>(reinterpret_cast<unsigned int>(bi)
00378 | MM::PHY_MEM);
00379
00380 // Flush TLB to ensure we've got the right memory organization
00381 MMU mmu;
00382 mmu.flush_tlb();
00383
00384 // Load OS (if it exists)
00385 if(has_system) {
00386 elf = reinterpret_cast<ELF *>(&bi[si->bm.system_off]);
00387 if(elf->load_segment(0) < 0) {
00388 db<Setup>(ERR) << "OS code segment was corrupted during SETUP!\n";
00389 panic();
00390 }
00391 unsigned int i;
00392 for(i = 1; i < sys_segments; i++) {
00393 if(elf->load_segment(i) < 0 && elf->segment_type(i) == PT_LOAD) {
00394 db<Setup>(ERR) << "OS data segment was corrupted during SETUP! i = " << i << " sys_segments = " << sys_segments << "\n";
00395 panic();
00396 }
00397 }
00398 }
00399
00400 // Load APP
00401 elf = reinterpret_cast<ELF *>(&bi[si->bm.loader_off]);
00402 if(elf->load_segment(0) < 0) {
00403 db<Setup>(ERR) << "Application code segment was corrupted during SETUP!\n";
00404 panic();
00405 }
00406 for(unsigned int i = 1; i < app_segments; i++)
00407 if(elf->load_segment(i) < 0 && elf->segment_type(i) == PT_LOAD) {
00408 db<Setup>(ERR) << "Application data segment was corrupted during SETUP!\n";
00409 panic();
00410 }
00411
00412 // Setup System Info
00413 si = reinterpret_cast<System_Info *>(MM::SYS_INFO);
00414 copy_sys_info(reinterpret_cast<System_Info *>(bi), si);
00415 setup_lmm(&si->lmm, app_entry, si->pmm.app_hi);
00416
00417 // Startup the FPU
00418 // cpu.init_fpu();
00419
00420 // Enable the Interrupt Controller to propagate interrups but keep
00421 // them disabled on the CPU
00422 cpu.int_disable();
00423 ic.enable();
00424
00425 // SETUP ends here
00426 if(has_system)
00427 call_next(sys_entry);
00428 else
00429 call_next(app_entry);
00430
00431 // SETUP is now part of the free memory and this point should never be
00432 // reached, but, just for ... :-)
00433 panic();
00434
00435 // Just to avoid the warning
00436 return -1;
00437 }
00438
00439 //========================================================================
00440 // setup_pci
00441 //
00442 // Desc: Calculate the PCI address space apperture.
00443 //
00444 // Parm: addr <- PCI address space base
00445 // size <- PCI address space size
00446 // si <- IO map
00447 //------------------------------------------------------------------------
00448 void setup_pci(Phy_Addr * addr, unsigned int * size, System_Info * si)
00449 {
00450 si->iomm_size = 0;
00451
00452 PC_PCI pci;
00453 if(pci.init(si)) {
00454 db<Setup>(WRN) << "Can't initialize the PCI bus!\n";
00455 *addr = (void *)0;
00456 *size = 0;
00457 return;
00458 }
00459
00460 // Scan the PCI bus looking for devices with memory mapped regions
00461 Phy_Addr base = ~0U;
00462 Phy_Addr top = (void *)0;
00463 for(int bus = 0; bus <= Traits<PC_PCI>::MAX_BUS; bus++) {
00464 for(int dev_fn = 0; dev_fn <= Traits<PC_PCI>::MAX_DEV_FN; dev_fn++) {
00465 PC_PCI::Header hdr;
00466 pci.header(PC_PCI::Locator(bus, dev_fn), &hdr);
00467 if(hdr) {
00468 db<Setup>(INF) << "PCI[" << bus << ":" << (dev_fn >> 3)
00469 << "." << (dev_fn & 7)
00470 << "]={cls=" << hdr.class_id
00471 << ",vid=" << hdr.vendor_id
00472 << ",did=" << hdr.device_id
00473 << ",rev=" << (int)hdr.revision_id;
00474 int i;
00475 for(i = 0; i < PC_PCI::Region::N; i++) {
00476 if(hdr.region[i].memory && hdr.region[i].size) {
00477 db<Setup>(INF) << ",reg[" << i << "]={b="
00478 << (void *)hdr.region[i].phy_addr
00479 << ",s="
00480 << (void *)hdr.region[i].size << "}";
00481 si->iomm[si->iomm_size].locator
00482 = hdr.locator.bus << 8 | hdr.locator.dev_fn;
00483 si->iomm[si->iomm_size].phy_addr
00484 = hdr.region[i].phy_addr;
00485 si->iomm[si->iomm_size].size
00486 = hdr.region[i].size;
00487 si->iomm_size++;
00488 if(hdr.region[i].phy_addr < base)
00489 base = hdr.region[i].phy_addr;
00490 if((hdr.region[i].phy_addr + hdr.region[i].size) >
00491 top)
00492 top = hdr.region[i].phy_addr
00493 + hdr.region[i].size;
00494 }
00495 }
00496 db<Setup>(INF) << "}\n";
00497 }
00498 }
00499 }
00500 *addr = base;
00501 *size = top - base;
00502
00503 // Fill the IO_Memory_Map in System_Info
00504 for(unsigned int i = 0; i < si->iomm_size; i++)
00505 si->iomm[i].log_addr = MM::IO_MEM + (si->iomm[i].phy_addr - base);
00506 }
00507
00508 //========================================================================
00509 // setup_idt
00510 //
00511 // Desc: Setup the IDT with panic for all entries but GPF and page-fault.
00512 //
00513 // Parm: addr -> IDT PHYSICAL address
00514 //------------------------------------------------------------------------
00515 void setup_idt(Phy_Addr addr)
00516 {
00517 typedef CPU::IDT_Entry IDT_Entry;
00518
00519 db<Setup>(TRC) << "setup_idt(idt=" << (void *)addr << ")\n";
00520
00521 // Adjust handler addresses to logical addresses
00522 Log_Addr panic_h = (unsigned int)&panic | MM::PHY_MEM;
00523 Log_Addr gpf_h = (unsigned int)&gpf | MM::PHY_MEM;
00524 Log_Addr page_fault_h = (unsigned int)&page_fault | MM::PHY_MEM;
00525 Log_Addr fpu_h = (unsigned int)&fpu | MM::PHY_MEM;
00526 Log_Addr syscall_h = (unsigned int)&syscall | MM::PHY_MEM;
00527
00528 // Map all handlers to panic()
00529 IDT_Entry * idt = (IDT_Entry *)(unsigned int)addr;
00530 for(int i = 0; i < CPU::IDT_ENTRIES; i++)
00531 idt[i] = IDT_Entry(CPU::GDT_SYS_CODE, panic_h, CPU::SEG_IDT_ENTRY);
00532
00533 // Catch GPF, PAGE_FAULT and FPU
00534 idt[CPU::EXC_GPF] = IDT_Entry(CPU::GDT_SYS_CODE, gpf_h,
00535 CPU::SEG_IDT_ENTRY);
00536 idt[CPU::EXC_PF] = IDT_Entry(CPU::GDT_SYS_CODE, page_fault_h,
00537 CPU::SEG_IDT_ENTRY);
00538 idt[CPU::EXC_NODEV] = IDT_Entry(CPU::GDT_SYS_CODE, fpu_h,
00539 CPU::SEG_IDT_ENTRY);
00540
00541 // Catch system calls generated by accident
00542 idt[Traits<PC>::SYSCALL_INT] = IDT_Entry(CPU::GDT_SYS_CODE, syscall_h,
00543 CPU::SEG_IDT_ENTRY);
00544
00545 db<Setup>(INF) << "IDT[0]=" << idt[0] << " (" << (void *)&panic << ")\n";
00546 }
00547
00548 //========================================================================
00549 // setup_gdt
00550 //
00551 // Desc: Setup the GDT, including entries for application and system
00552 // code, data and stack.
00553 //
00554 // Parm: addr -> GDT PHYSICAL address
00555 //------------------------------------------------------------------------
00556 void setup_gdt(Phy_Addr addr)
00557 {
00558 typedef CPU::GDT_Entry GDT_Entry;
00559
00560 db<Setup>(TRC) << "setup_gdt(gdt=" << (void *)addr << ")\n";
00561
00562 GDT_Entry * gdt = (GDT_Entry *)(unsigned int)addr;
00563
00564 // GDT_Entry(base, limit, {P,DPL,S,TYPE})
00565 gdt[CPU::GDT_NULL] = GDT_Entry(0, 0, 0);
00566 gdt[CPU::GDT_FLT_CODE] = GDT_Entry(0, 0xfffff, CPU::SEG_FLT_CODE);
00567 gdt[CPU::GDT_FLT_DATA] = GDT_Entry(0, 0xfffff, CPU::SEG_FLT_DATA);
00568 gdt[CPU::GDT_APP_CODE] = GDT_Entry(0, 0xfffff, CPU::SEG_APP_CODE);
00569 gdt[CPU::GDT_APP_DATA] = GDT_Entry(0, 0xfffff, CPU::SEG_APP_DATA);
00570 gdt[CPU::GDT_APP_STACK] = GDT_Entry(0, 0xfffff, CPU::SEG_APP_DATA);
00571 gdt[CPU::GDT_SYS_CODE] = GDT_Entry(0, 0xfffff, CPU::SEG_SYS_CODE);
00572 gdt[CPU::GDT_SYS_DATA] = GDT_Entry(0, 0xfffff, CPU::SEG_SYS_DATA);
00573 gdt[CPU::GDT_SYS_STACK] = GDT_Entry(0, 0xfffff, CPU::SEG_SYS_DATA);
00574
00575 db<Setup>(INF) << "GDT[NULL=" << CPU::GDT_NULL << "]="
00576 << gdt[CPU::GDT_NULL] << "\n";
00577 db<Setup>(INF) << "GDT[FLCD=" << CPU::GDT_FLT_CODE << "]="
00578 << gdt[CPU::GDT_FLT_CODE] << "\n";
00579 db<Setup>(INF) << "GDT[FLDT=" << CPU::GDT_FLT_DATA << "]="
00580 << gdt[CPU::GDT_FLT_DATA] << "\n";
00581 db<Setup>(INF) << "GDT[APCD=" << CPU::GDT_APP_CODE << "]="
00582 << gdt[CPU::GDT_APP_CODE] << "\n";
00583 db<Setup>(INF) << "GDT[APDT=" << CPU::GDT_APP_DATA << "]="
00584 << gdt[CPU::GDT_APP_DATA] << "\n";
00585 db<Setup>(INF) << "GDT[APST=" << CPU::GDT_APP_STACK << "]="
00586 << gdt[CPU::GDT_APP_STACK] << "\n";
00587 db<Setup>(INF) << "GDT[SYCD=" << CPU::GDT_SYS_CODE << "]="
00588 << gdt[CPU::GDT_SYS_CODE] << "\n";
00589 db<Setup>(INF) << "GDT[SYDT=" << CPU::GDT_SYS_DATA << "]="
00590 << gdt[CPU::GDT_SYS_DATA] << "\n";
00591 db<Setup>(INF) << "GDT[SYST=" << CPU::GDT_SYS_STACK << "]="
00592 << gdt[CPU::GDT_SYS_STACK] << "\n";
00593 }
00594
00595 //========================================================================
00596 // setup_sys_pt
00597 //
00598 // Desc: Setup the System Page Table
00599 //
00600 // Parm: pmm -> physical memory map
00601 // sys_code_size -> system code size in Ix86_Pages
00602 // sys_data_size -> system data size in Ix86_Pages
00603 //------------------------------------------------------------------------
00604 void setup_sys_pt(PMM * pmm, int sys_code_size, int sys_data_size)
00605 {
00606 db<Setup>(TRC) << "setup_sys_pt(pmm={idt=" << (void *)pmm->int_vec
00607 << ",gdt=" << (void *)pmm->mach1
00608 << ",pt=" << (void *)pmm->sys_pt
00609 << ",pd=" << (void *)pmm->sys_pd
00610 << ",info=" << (void *)pmm->sys_info
00611 << ",mem=" << (void *)pmm->phy_mem_pts
00612 << ",io=" << (void *)pmm->io_mem_pts
00613 << ",cod=" << (void *)pmm->sys_code
00614 << ",dat=" << (void *)pmm->sys_data
00615 << ",stk=" << (void *)pmm->sys_stack
00616 << ",apl=" << (void *)pmm->app_lo
00617 << ",aph=" << (void *)pmm->app_hi
00618 << ",fr1b=" << (void *)pmm->mach2
00619 << ",fr1s=" << (void *)pmm->mach3
00620 << ",fr2b=" << (void *)pmm->free
00621 << ",fr2s=" << (void *)pmm->free_size
00622 << "}"
00623 << ",code_size=" << sys_code_size
00624 << ",data_size=" << sys_data_size << ")\n";
00625
00626 // Get the physical address for the System Page Table */
00627 PT_Entry * sys_pt = (PT_Entry *)pmm->sys_pt;
00628
00629 // Clear the System Page Table
00630 memset(sys_pt, 0, MMU::PT_ENTRIES);
00631
00632 // IDT
00633 sys_pt[MMU::page(MM::INT_VEC)] = pmm->int_vec | Flags::SYS;
00634
00635 // GDT
00636 sys_pt[MMU::page(MM::MACH1)] = pmm->mach1 | Flags::SYS;
00637
00638 // Set an entry to this page table, so the system can access it later
00639 sys_pt[MMU::page(MM::SYS_PT)] = pmm->sys_pt | Flags::SYS;
00640
00641 // System Page Directory
00642 sys_pt[MMU::page(MM::SYS_PD)] = pmm->sys_pd | Flags::SYS;
00643
00644 // System Info
00645 sys_pt[MMU::page(MM::SYS_INFO)] = pmm->sys_info | Flags::SYS;
00646
00647 int i;
00648 PT_Entry aux;
00649
00650 // OS code
00651 for(i = 0, aux = pmm->sys_code;
00652 i < sys_code_size;
00653 i++, aux = aux + sizeof(Page))
00654 sys_pt[MMU::page(MM::SYS_CODE) + i]
00655 = aux | Flags::SYS;
00656
00657 // OS data
00658 for(i = 0, aux = pmm->sys_data;
00659 i < sys_data_size;
00660 i++, aux = aux + sizeof(Page))
00661 sys_pt[MMU::page(MM::SYS_DATA) + i]
00662 = aux | Flags::SYS;
00663
00664 // Set a single page for OS stack (who needs a stack?)
00665 sys_pt[MMU::page(MM::SYS_STACK)] = pmm->sys_stack | Flags::SYS;
00666
00667 for(unsigned int i = 0; i < MMU::PT_ENTRIES; i++)
00668 if(sys_pt[i])
00669 db<Setup>(INF) << "SPT[" << i << "]=" << (void *)sys_pt[i] << "\n";
00670 }
00671
00672 //========================================================================
00673 // setup_sys_pd
00674 //
00675 // Desc: Setup the System Page Directory and maps the whole physical
00676 // memory at both MM::PHY_MEM and "pmm->app_lo".
00677 //
00678 // Parm: pmm -> physical memory map
00679 // phy_mem_size -> size of physical memory in Pages
00680 // phy_mem_phy_addr -> PCI address space physical address
00681 // io_mem_size -> size of PCI address space in Pages
00682 //------------------------------------------------------------------------
00683 void setup_sys_pd(PMM * pmm, unsigned int phy_mem_size,
00684 Phy_Addr io_mem_phy_addr, unsigned int io_mem_size)
00685 {
00686 int n_pts;
00687 PT_Entry *pts, *sys_pd;
00688
00689 db<Setup>(TRC) << "setup_sys_pd(pmm={idt=" << (void *)pmm->int_vec
00690 << ",...},mem_sz=" << phy_mem_size * sizeof(Page)
00691 << ",pci=" << (void *)io_mem_phy_addr
00692 << ",pci_sz=" << io_mem_size * sizeof(Page)
00693 << ")\n";
00694
00695 // Calculate the number of page tables needed to map the physical memory
00696 n_pts = (phy_mem_size + MMU::PT_ENTRIES - 1) / MMU::PT_ENTRIES;
00697
00698 // Map all physical memory into the page tables pointed by phy_mem_pts
00699 // These will be attached at both MM::PHY_MEM and MM::APP_LO thus flags
00700 // must consider application access
00701 pts = reinterpret_cast<PT_Entry *>(pmm->phy_mem_pts);
00702 for(unsigned int i = 0; i < phy_mem_size; i++)
00703 pts[i] = (i * sizeof(Page)) | Flags::APP;
00704
00705 // Setup the System Page Directory
00706 sys_pd = reinterpret_cast<PT_Entry *>(pmm->sys_pd);
00707
00708 // Attach all physical memory starting at MM::PHY_MEM
00709 for(int i = 0; i < n_pts; i++)
00710 sys_pd[MMU::directory(MM::PHY_MEM) + i] =
00711 (pmm->phy_mem_pts + i * sizeof(Page)) | Flags::SYS;
00712
00713 // Attach application memory starting at "pmm->app_lo"
00714 for(unsigned int i = MMU::directory(
00715 MMU::align_directory(pmm->app_lo));
00716 i < MMU::directory(MMU::align_directory(pmm->app_hi));
00717 i++)
00718 sys_pd[i] = (pmm->phy_mem_pts + i * sizeof(Page)) |
00719 Flags::APP;
00720
00721 // Calculate the number of page tables needed to map the PCI AS
00722 n_pts = (io_mem_size + MMU::PT_ENTRIES - 1) / MMU::PT_ENTRIES;
00723
00724 // Map PCI addres space into the page tables pointed by io_mem_pts
00725 pts = (PT_Entry *)pmm->io_mem_pts;
00726 for(unsigned int i = 0; i < io_mem_size; i++)
00727 pts[i] = (io_mem_phy_addr + i * sizeof(Page)) | Flags::PCI;
00728
00729 // Attach PCI devices' memory to MM::IO_MEM
00730 for(int i = 0; i < n_pts; i++)
00731 sys_pd[MMU::directory(MM::IO_MEM) + i] =
00732 (pmm->io_mem_pts + i * sizeof(Page)) | Flags::PCI;
00733
00734
00735 sys_pd[MMU::directory(MM::SYS_CODE)] = pmm->sys_pt | Flags::SYS;
00736
00737 for(unsigned int i = 0; i < MMU::PT_ENTRIES; i++)
00738 if(sys_pd[i])
00739 db<Setup>(INF) << "PD[" << i << "]=" << (void *)sys_pd[i] << "\n";
00740 }
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 void setup_lmm(LMM * lmm, Log_Addr app_entry, Log_Addr app_hi)
00751 {
00752 lmm->int_vec = MM::INT_VEC;
00753 lmm->sys_pt = MM::SYS_PT;
00754 lmm->sys_pd = MM::SYS_PD;
00755 lmm->sys_info = MM::SYS_INFO;
00756 lmm->phy_mem = MM::PHY_MEM;
00757 lmm->io_mem = MM::IO_MEM;
00758 lmm->sys_code = MM::SYS_CODE;
00759 lmm->sys_data = MM::SYS_DATA;
00760 lmm->sys_stack = MM::SYS_STACK;
00761 lmm->app_lo = MM::APP_LO;
00762 lmm->app_entry = app_entry;
00763 lmm->app_code = MM::APP_CODE;
00764 lmm->app_data = MM::APP_DATA;
00765 lmm->app_hi = app_hi;
00766 lmm->mach1 = MM::MACH1;
00767 lmm->mach2 = MM::MACH2;
00768 lmm->mach3 = MM::MACH2;
00769
00770 db<Setup>(INF) << "lmm={int=" << (void *)lmm->int_vec
00771 << ",gdt=" << (void *)lmm->mach1
00772 << ",pt=" << (void *)lmm->sys_pt
00773 << ",pd=" << (void *)lmm->sys_pd
00774 << ",info=" << (void *)lmm->sys_info
00775 << ",mem=" << (void *)lmm->phy_mem
00776 << ",io=" << (void *)lmm->io_mem
00777 << ",cod=" << (void *)lmm->sys_code
00778 << ",dat=" << (void *)lmm->sys_data
00779 << ",stk=" << (void *)lmm->sys_stack
00780 << ",apl=" << (void *)lmm->app_lo
00781 << ",ape=" << (void *)lmm->app_entry
00782 << ",apc=" << (void *)lmm->app_code
00783 << ",apd=" << (void *)lmm->app_data
00784 << ",aph=" << (void *)lmm->app_hi
00785 << "})\n";
00786 }
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 void copy_sys_info(System_Info * from, System_Info * to)
00798 {
00799 unsigned int size = sizeof(System_Info) + from->iomm_size
00800 * sizeof(System_Info::IO_Memory_Map);
00801
00802 db<Setup>(TRC) << "copy_sys_info(from=" << (void *)from
00803 << ",to=" << (void *)to
00804 << ",size=" << size << ")\n";
00805
00806 if(size > sizeof(Page))
00807 db<Setup>(WRN) << "System_Info is bigger than a page ("
00808 << size << ")!\n";
00809
00810 memcpy((void *)to, (void *)from, size);
00811 }
00812
00813
00814
00815
00816
00817
00818
00819
00820 void call_next(Log_Addr entry)
00821 {
00822 db<Setup>(TRC) << "call_next(e=" << (void *)entry << ")\n";
00823
00824
00825
00826
00827 ASM("movl %0, %%esp \n"
00828 "call *%%ebx \n"
00829 : : "i"(MM::SYS_STACK + TR::SYSTEM_STACK_SIZE - 2 * sizeof(int)),
00830 "b"(static_cast<unsigned int>(entry)));
00831
00832
00833
00834
00835
00836
00837
00838 }
00839
00840
00841
00842
00843
00844
00845
00846
00847 void page_fault(Reg32 eip, Reg32 cs, Reg32 eflags, Reg32 esp3, Reg32 ss,
00848 Reg32 error)
00849 {
00850 IA32 cpu;
00851
00852 db<Setup>(ERR) << "this thread generated an invalid address and will be terminated!\n";
00853 db<Setup>(ERR) << "address=" << (void *)cpu.cr2() << "\n";
00854 db<Setup>(ERR) << "context={cs=" << cs
00855 << ",ip=" << (void *)eip
00856 << ",flg=" << (void *)eflags
00857 << ",ss=" << (void *)ss
00858 << ",sp=" << (void *)esp3
00859 << ",err=" << (void *)error << "}\n";
00860
00861 panic();
00862 }
00863
00864 //========================================================================
00865 // gpf
00866 //
00867 // Desc: GPF exception handler (what a handling! :-)).
00868 //
00869 // Parm: exception stack and error code pushed by the CPU
00870 //------------------------------------------------------------------------
00871 void gpf(Reg32 eip, Reg32 cs, Reg32 eflags, Reg32 esp3, Reg32 ss, Reg32 error)
00872 {
00873 short ds;
00874 ASM("movw %%ds, %0" : "=o" (ds) : );
00875
00876 db<Setup>(ERR) << "this thread caused a GPF and will be terminated!\n";
00877 db<Setup>(ERR) << "context={cs=" << cs
00878 << ",ds=" << ds
00879 << ",ip=" << (void *)eip
00880 << ",flg=" << (void *)eflags
00881 << ",ss=" << (void *)ss
00882 << ",sp=" << (void *)esp3
00883 << ",err=" << (void *)error << "}\n",
00884
00885 panic();
00886 }
00887
00888 //========================================================================
00889 // fpu
00890 //
00891 // Desc: FPU exception handler.
00892 //------------------------------------------------------------------------
00893 void fpu()
00894 {
00895 db<Setup>(ERR) << "FPU generated an interrupt!\n";
00896
00897 // ASM("clts");
00898
00899 panic();
00900 }
00901
00902 //========================================================================
00903 // syscall
00904 //
00905 // Desc: FPU exception handler.
00906 //------------------------------------------------------------------------
00907 void syscall()
00908 {
00909 db<Setup>(ERR) << "System call invoked but no OS kernel loaded (yet)!\n";
00910
00911 panic();
00912 }
00913
00914 //========================================================================
00915 // panic
00916 //
00917 // Desc: This function is called if something goes wrong during setup,
00918 // including uncaught interrupts.
00919 //------------------------------------------------------------------------
00920 void panic()
00921 {
00922 unsigned short *video;
00923
00924 // Set a pointer to GCA text frame buffer so we can say something
00925 video = reinterpret_cast<unsigned short *>(
00926 Traits<PC_Display>::FRAME_BUFFER_ADDRESS);
00927
00928 video [0] = 'P' | 0x1f00;
00929 video [1] = 'A' | 0x1f00;
00930 video [2] = 'N' | 0x1f00;
00931 video [3] = 'I' | 0x1f00;
00932 video [4] = 'C' | 0x1f00;
00933 video [5] = '!' | 0x1f00;
00934
00935 ASM("hlt");
00936 }
00937
00938 // This might be very useful for debugging!
00939 // register int sp;
00940 // ASM("movl %%esp, %0" : "=r"(sp) : );
00941 // unsigned short * video = (unsigned short *) CGA_FBUF_PHY_ADDR;
00942 // video [10] = ((sp >> 12) & 0xf) | 0x1f30;
00943 // video [11] = ((sp >> 8) & 0xf) | 0x1f30;
00944 // video [12] = ((sp >> 4) & 0xf) | 0x1f30;
00945 // video [13] = (sp & 0xf) | 0x1f30;
00946 // video [14] = 'O' | 0x1f00;
00947 // video [15] = 'K' | 0x1f00;
00948 // for(;;);