int mon_showvm(int argc, char **argv, struct Trapframe *tf) { uintptr_t begin_va, end_va, va, next_va; pde_t *pgdir; pte_t *pte; int i, j; if (argc != 3) { cprintf("usage: dumpvm begin_va end_va\n"); return 0; } begin_va = (uintptr_t) strtol(argv[1], NULL, 0); end_va = (uintptr_t) strtol(argv[2], NULL, 0); if (begin_va > end_va) { cprintf("begin va (0x%x) is greater than end va (0x%x)\n", begin_va, end_va); return 0; } pgdir = (pde_t *) KADDR(rcr3()); for (i = j = 0, va = begin_va; va <= end_va; va += PGSIZE) { pte = pgdir_walk(pgdir, (void *) va, 0); next_va = MIN(ROUNDDOWN(va + PGSIZE, PGSIZE) - 1, end_va); show_page(pgdir, va, next_va, *pte && (*pte & PTE_P), &i, &j); } if (i) cprintf("\n"); return 0; }
int mon_modpageperms(int argc, char **argv, struct Trapframe *tf) { uintptr_t va_arg; int perms; pde_t *pgdir; pte_t *pte; if (argc != 3) { cprintf("usage: modpageperms va perms\n"); return 0; } va_arg = (uintptr_t) strtol(argv[1], NULL, 0); perms = (uintptr_t) strtol(argv[2], NULL, 0); if (PTE_ADDR(perms)) { cprintf("perms 0x%03x is invalid\n", perms); return 0; } pgdir = (pde_t *) KADDR(rcr3()); pte = pgdir_walk(pgdir, (void *) va_arg, 0); if (!pte) { cprintf("va 0x%x is not mapped\n", va_arg); return 0; } cprintf("va 0x%x existing pte "); pte_show(*pte); *pte = PTE_ADDR(*pte) | perms; cprintf("va 0x%x changed pte "); pte_show(*pte); return 0; }
int MPTIntro_test1() { set_pdir_base(0); if ((unsigned int)PDirPool[0] != rcr3()) { dprintf("test 1 failed.\n"); return 1; } set_pdir_entry_identity(1, 1); set_pdir_entry(1, 2, 100); if (get_pdir_entry(1, 1) != (unsigned int)IDPTbl[1] + 7) { dprintf("test 1 failed.\n"); return 1; } if (get_pdir_entry(1, 2) != 409607) { dprintf("test 1 failed.\n"); return 1; } rmv_pdir_entry(1, 1); rmv_pdir_entry(1, 2); if (get_pdir_entry(1, 1) != 0 || get_pdir_entry(1, 2) != 0) { dprintf("test 1 failed.\n"); return 1; } dprintf("test 1 passed.\n"); return 0; }
// map physcical memory [0,PGSIZE*npages] to [KERNBASE,KERNBASE+PGSIZE*npages] ,in case // one physical memory can't find its virtual address static void boot_phys_map() { uintptr_t sp=KERNBASE+0X400000; int i,j; pte_t* pgtable; pde_t* entry_pgdir=(pde_t*)(rcr3()+KERNBASE); int npts= (npages / 1024)+1; int actual_top=KERNBASE+npages*PGSIZE; for(i=0; i<npts && sp<actual_top; i++){ pgtable=boot_alloc(PGSIZE); memset(pgtable, 0, PGSIZE); entry_pgdir[PDX(sp)]=((int)pgtable-KERNBASE) | PTE_P | PTE_U | PTE_W; // cprintf("the entry_pgdir'%dth pde is %x\n ",PDX(sp),(int)entry_pgdir[PDX(sp)]); for(j=0;j<1024 && sp<actual_top;j++){ pgtable[j]=((uint32_t)sp-KERNBASE) | PTE_P | PTE_U | PTE_W; sp+=PGSIZE; } } }
void refresh_tlb(pgd_t *pgdir, viraddr_t va) { // Flush the entry only if we're modifying the current address space. //if (!curenv || curenv->env_pgdir == pgdir) invlpg((void*)va); int cr3 = rcr3(); lcr3(cr3); }
void kmm_pgfault(struct trapframe *tf) { // uint64_t err = tf->tf_err; uintptr_t addr = rcr2(); if (addr >= PBASE && addr < PBASE + PSIZE) { pgd_t *pgd = KADDR_DIRECT(PTE_ADDR(rcr3())); pud_t *pud; pmd_t *pmd; pte_t *ptd; /* PHYSICAL ADDRRESS ACCESSING */ if (last_pgd != NULL) { pud = KADDR_DIRECT(PGD_ADDR(last_pgd[PGX(last_addr)])); pmd = KADDR_DIRECT(PUD_ADDR(pud[PUX(last_addr)])); ptd = KADDR_DIRECT(PMD_ADDR(pmd[PMX(last_addr)])); ptd[PTX(last_addr)] = 0; if (ptd == temp_ptd) { pmd[PUX(last_addr)] = 0; if (pmd == temp_pmd) { pud[PUX(last_addr)] = 0; if (pud == temp_pud) last_pgd[PGX(last_addr)] = 0; } if (last_pgd == pgd) { invlpg((void *)last_addr); } } } if (pgd[PGX(last_addr)] == 0) pgd[PGX(last_addr)] = PADDR_DIRECT(temp_pud) | PTE_W | PTE_P; pud = KADDR_DIRECT(PGD_ADDR(pgd[PGX(last_addr)])); if (pud[PUX(last_addr)] == 0) pud[PUX(last_addr)] = PADDR_DIRECT(temp_pmd) | PTE_W | PTE_P; pmd = KADDR_DIRECT(PUD_ADDR(pud[PUX(last_addr)])); if (pmd[PMX(last_addr)] == 0) pmd[PMX(last_addr)] = PADDR_DIRECT(temp_ptd) | PTE_W | PTE_P; ptd = KADDR_DIRECT(PMD_ADDR(pmd[PMX(last_addr)])); ptd[PTX(last_addr)] = PADDR_DIRECT(addr) | PTE_W | PTE_P; last_pgd = pgd; last_addr = addr; /* XXX? */ // invlpg((void *)addr); } }
/* Flushes a TLB, including global pages. We should always have the CR4_PGE * flag set, but just in case, we'll check. Toggling this bit flushes the TLB. */ void tlb_flush_global(void) { uint32_t cr4 = rcr4(); if (cr4 & CR4_PGE) { lcr4(cr4 & ~CR4_PGE); lcr4(cr4); } else lcr3(rcr3()); }
unsigned int mmu_inicializar_dir_tarea(taskType tipo, unsigned int fisica){ int *page_directory = mmu_proxima_pagina_fisica_libre(); // Limpiamos el directorio int i = 0; while (i < 1024) { page_directory[i] = 0; i++; } // Registramos la primer pagina en el directorio int *page_table = mmu_proxima_pagina_fisica_libre(); page_directory[0] = (int)page_table + ATTR_KERN; // En la tabla de paginas registramos las primeras 1024 con bloques // de 4kb int base_page_addr = 0; i = 0; while(i < 1024) { page_table[i] = base_page_addr + ATTR_KERN; base_page_addr += 4096; i++; } unsigned int cr3Tarea = (int) page_directory; mmu_mapear_pagina(fisica, rcr3(), fisica, ATTR_KERN); //tipo de tarea int* codigo_fuente = (int*) (IDLE_TASK + (inMemoryCodeOrder(tipo) * PAGE_SIZE)); mmu_copiar_pagina(codigo_fuente, (int*) fisica); mmu_unmapear_pagina(fisica, rcr3()); mmu_mapear_pagina(TASK_CODE, cr3Tarea, fisica, ATTR_USER); //En principio se mapea a si misma //No esta atacando a nadie mmu_mapear_pagina(TASK_CODE + PAGE_SIZE, cr3Tarea, fisica, ATTR_USER); return cr3Tarea; }
void mover_pirata(uint pos_orig, uint pos_nueva, pirata_t* pirata){ if (pirata->type == PIRATA_MINERO) { if ( posicion_mapeada(pos_nueva, pirata->jugador) ) { mmu_mover_codigo_pirata(rcr3(), game_pos2mem_fisica(pos_nueva), game_pos2mem_fisica(pos_orig)); pintar_pirata(pos_nueva, pos_orig, pirata->type); pirata->pos = pos_nueva; } else { tarea_suicidarse(); } } else { mmu_mover_codigo_pirata(rcr3(), game_pos2mem_fisica(pos_nueva), game_pos2mem_fisica(pos_orig)); pirata->pos = pos_nueva; pintar_pirata(pos_nueva, pos_orig, pirata->type); int x = 0, y = 0; game_lineal2xy(pos_nueva, &x, &y); //transformo a x e y game_explorar_posicion(pirata, x, y); } }
// Allocate a page of memory and map it at 'va' with permission // 'perm' in the address space of 'envid'. // The page's contents are set to 0. // If a page is already mapped at 'va', that page is unmapped as a // side effect. // // perm -- PTE_U | PTE_P must be set, PTE_AVAIL | PTE_W may or may not be set, // but no other bits may be set. // // Return 0 on success, < 0 on error. Errors are: // -E_BAD_ENV if environment envid doesn't currently exist, // or the caller doesn't have permission to change envid. // -E_INVAL if va >= UTOP, or va is not page-aligned. // -E_INVAL if perm is inappropriate (see above). // -E_NO_MEM if there's no memory to allocate the new page, // or to allocate any necessary page tables. static int sys_page_alloc(envid_t envid, void *va, int perm) { // Hint: This function is a wrapper around page_alloc() and // page_insert() from kern/pmap.c. // Most of the new code you write should be to check the // parameters for correctness. // If page_insert() fails, remember to free the page you // allocated! // LAB 4: Your code here. struct Env *e; int r; struct Page *p; uint32_t cr3; if ((r = envid2env(envid, &e, 1)) < 0) return r; if ((uintptr_t)va >= UTOP || (uintptr_t)va % PGSIZE != 0) return -E_INVAL; if ( (perm & (PTE_U | PTE_P) ) != (PTE_U | PTE_P) ) //PTE_U | PTE_P MUST be set - ren return -E_INVAL; if(perm & ~PTE_USER) return -E_INVAL; //some disallowed bits are set - ren if (page_alloc(&p) < 0) return -E_NO_MEM; if (page_insert(e->env_pgdir, p, va, perm) < 0){ page_free(p); return -E_NO_MEM; } //sets physical page's contents to 0 - ren //switch to envid's page directory - ren cr3 = rcr3(); lcr3(e->env_cr3); //now we can use known va to get to physical page - ren memset(va, 0, PGSIZE); //switch back to curenv page directory - ren lcr3(cr3); return 0; }
//cambia el contexto del directorio de paginas, invalida la cache de direcciones y retorna el contenido viejo de CR3 unsigned int changePaginationContext(pagedir_entry* newDirContext){ //usando estos "getters" y "setters" del registro del cpu CR3 voy a cambiar el contexto de memoria virtual //void lcr3(unsigned int val); => escribe a CR3 //unsigned int rcr3(void); => lee el contenido de CR3 unsigned int oldCR3 = rcr3(); lcr3((unsigned int) newDirContext); //invalido la cache de traduccion de direcciones tlbflush(); return oldCR3; }
static void addr_info(uintptr_t va) { extern pte_t entry_pgdir[]; uint32_t cr3=rcr3(); pde_t pde=((pde_t*)cr3)[PDX(va)]; pte_t pte; cprintf("mem Page info:\n"); cprintf("cr3=%x\n",cr3); cprintf("KERNBASE=%x \n",KERNBASE); cprintf("entry_pgdir=%x\n",(int)entry_pgdir); cprintf("va=%x\n",va); cprintf("correspond pde = %x\n",pde); }
void init_idle(){ tarea_idle.ss = 0x10; tarea_idle.ds = 0x10; tarea_idle.es = 0x10; tarea_idle.fs = 0x10; tarea_idle.gs = 0x10; tarea_idle.cs = 0x8; tarea_idle.cr3 = (unsigned int) rcr3(); tarea_idle.eip = TASK_CODE; tarea_idle.ebp = 0; tarea_idle.esp = TASK_STACK + 0x1000; tarea_idle.eflags = 0x202; //Bit obligado, con interrupciones tarea_idle.iomap = 0xFFFF; tarea_idle.dtrap = 0x0; }
int mon_showmappings(int argc, char **argv, struct Trapframe *tf) { int i; uintptr_t va_arg[2], va; pde_t *pgdir; pte_t *pte; if (argc != 3) { cprintf("usage: showmappings begin_va end_va\n"); return 0; } for (i = 1; i < argc; i++) { va_arg[i - 1] = (uintptr_t) strtol(argv[i], NULL, 0); } if (va_arg[0] > va_arg[1]) { cprintf("begin va (0x%x) is greater than end va (0x%x)\n", va_arg[0], va_arg[1]); return 0; } pgdir = (pde_t *) KADDR(rcr3()); for (va = va_arg[0]; va <= va_arg[1]; va += PGSIZE) { pte = pgdir_walk(pgdir, (void *) va, 0); if (!pte || !(*pte & PTE_P)) { cprintf("va 0x%x is not mapped\n", va); } else { cprintf("va 0x%x ", va); pte_show(*pte); } if (va + PGSIZE < va) break; } return 0; }
void loader_init(void) { int i; // Inicializamos la cola de peeds libres free_pids[0] = -1; // La IDLE ocupa la 0, nadie deberia apuntar a la 0 for (i = 1; i < MAX_PID - 1; i++) free_pids[i] = i + 1; free_pids[MAX_PID - 1] = -1; // es la ultima next_free = 1; cur_pid = 0; //NOTE: Deberiamos contar la IDLE Task? tasks_running = tasks_blocked = 0; for(i=0; i < MAX_PID; i++) task_table[i].cr3 = 0; //hay que generar la tarea actual.. que dps se convierte en idle task_table[0].cr3 = rcr3(); //registro las syscalls (UNIFICAR UN LUGAR O CADA UNA EN SU MODULO) syscall_list[0x31] = (uint_32) &sys_getpid; syscall_list[0x32] = (uint_32) &sys_exit; syscall_list[0x38] = (uint_32) &sys_fork; }
// invalidate a TLB entry, but only if the page tables being // edited are the ones currently in use by the processor. void tlb_invalidate(pde_t *pgdir, uintptr_t la) { if (rcr3() == PADDR(pgdir)) { invlpg((void *)la); } }
// Allocates a new env and loads the named user program into it. struct Env* env_create(char* user_program_name, unsigned int page_WS_size) { //[1] get pointer to the start of the "user_program_name" program in memory // Hint: use "get_user_program_info" function, // you should set the following "ptr_program_start" by the start address of the user program uint8* ptr_program_start = 0; struct UserProgramInfo* ptr_user_program_info = get_user_program_info(user_program_name); if(ptr_user_program_info == 0) return NULL; ptr_program_start = ptr_user_program_info->ptr_start ; // if(ptr_user_program_info->environment != NULL) // { // cprintf("env_create: an old environment already exist for [%s]!! \nfreeing the old one by calling start_env_free....\n", ptr_user_program_info->environment->prog_name); // start_env_free(ptr_user_program_info->environment); // // //return ptr_user_program_info; // } //[2] allocate new environment, (from the free environment list) //if there's no one, return NULL // Hint: use "allocate_environment" function struct Env* e = NULL; if(allocate_environment(&e) < 0) { return 0; } //[2.5 - 2012] Set program name inside the environment e->prog_name = ptr_user_program_info->name ; //[3] allocate a frame for the page directory, Don't forget to set the references of the allocated frame. //REMEMBER: "allocate_frame" should always return a free frame uint32* ptr_user_page_directory; unsigned int phys_user_page_directory; if(USE_KHEAP) { ptr_user_page_directory = create_user_directory(); phys_user_page_directory = kheap_physical_address((uint32)ptr_user_page_directory); } else { int r; struct Frame_Info *p = NULL; allocate_frame(&p) ; p->references = 1; ptr_user_page_directory = STATIC_KERNEL_VIRTUAL_ADDRESS(to_physical_address(p)); phys_user_page_directory = to_physical_address(p); } //[4] initialize the new environment by the virtual address of the page directory // Hint: use "initialize_environment" function //2016 e->page_WS_max_size = page_WS_size; initialize_environment(e, ptr_user_page_directory, phys_user_page_directory); // We want to load the program into the user virtual space // each program is constructed from one or more segments, // each segment has the following information grouped in "struct ProgramSegment" // 1- uint8 *ptr_start: start address of this segment in memory // 2- uint32 size_in_file: size occupied by this segment inside the program file, // 3- uint32 size_in_memory: actual size required by this segment in memory // usually size_in_file < or = size_in_memory // 4- uint8 *virtual_address: start virtual address that this segment should be copied to it //[6] switch to user page directory // Hint: use rcr3() and lcr3() uint32 kern_phys_pgdir = rcr3() ; lcr3(e->env_cr3) ; //[7] load each program segment into user virtual space struct ProgramSegment* seg = NULL; //use inside PROGRAM_SEGMENT_FOREACH as current segment information int segment_counter=0; uint32 remaining_ws_pages = (e->page_WS_max_size)-1; // we are reserving 1 page of WS for the stack that will be allocated just before the end of this function uint32 lastTableNumber=0xffffffff; PROGRAM_SEGMENT_FOREACH(seg, ptr_program_start) { segment_counter++; //allocate space for current program segment and map it at seg->virtual_address then copy its content // from seg->ptr_start to seg->virtual_address //Hint: use program_segment_alloc_map_copy_workingset() //cprintf("SEGMENT #%d, dest start va = %x, dest end va = %x\n",segment_counter, seg->virtual_address, (seg->virtual_address + seg->size_in_memory)); LOG_STRING("==============================================================================="); LOG_STATMENT(cprintf("SEGMENT #%d, size_in_file = %d, size_in_memory= %d, dest va = %x",segment_counter,seg->size_in_file, seg->size_in_memory, seg->virtual_address)); LOG_STRING("==============================================================================="); uint32 allocated_pages=0; program_segment_alloc_map_copy_workingset(e, seg, &allocated_pages, remaining_ws_pages, &lastTableNumber); remaining_ws_pages -= allocated_pages; LOG_STATMENT(cprintf("SEGMENT: allocated pages in WS = %d",allocated_pages)); LOG_STATMENT(cprintf("SEGMENT: remaining WS pages after allocation = %d",remaining_ws_pages)); ///[1] temporary initialize 1st page in memory then writing it on page file uint32 dataSrc_va = (uint32) seg->ptr_start; uint32 seg_va = (uint32) seg->virtual_address ; uint32 start_first_page = ROUNDDOWN(seg_va , PAGE_SIZE); uint32 end_first_page = ROUNDUP(seg_va , PAGE_SIZE); uint32 offset_first_page = seg_va - start_first_page ; memset(ptr_temp_page , 0, PAGE_SIZE); uint8 *src_ptr = (uint8*) dataSrc_va; uint8 *dst_ptr = (uint8*) (ptr_temp_page + offset_first_page); int i; for (i = seg_va ; i < end_first_page ; i++, src_ptr++,dst_ptr++ ) { *dst_ptr = *src_ptr ; } if (pf_add_env_page(e, start_first_page, ptr_temp_page) == E_NO_PAGE_FILE_SPACE) panic("ERROR: Page File OUT OF SPACE. can't load the program in Page file!!"); //LOG_STRING(" -------------------- PAGE FILE: 1st page is written"); ///[2] Start writing the segment ,from 2nd page until before last page, to page file ... uint32 start_last_page = ROUNDDOWN(seg_va + seg->size_in_file, PAGE_SIZE) ; uint32 end_last_page = seg_va + seg->size_in_file; for (i = end_first_page ; i < start_last_page ; i+= PAGE_SIZE, src_ptr+= PAGE_SIZE) { if (pf_add_env_page(e, i, src_ptr) == E_NO_PAGE_FILE_SPACE) panic("ERROR: Page File OUT OF SPACE. can't load the program in Page file!!"); } //LOG_STRING(" -------------------- PAGE FILE: 2nd page --> before last page are written"); ///[3] temporary initialize last page in memory then writing it on page file dst_ptr = (uint8*) ptr_temp_page; memset(dst_ptr, 0, PAGE_SIZE); for (i = start_last_page ; i < end_last_page ; i++, src_ptr++,dst_ptr++ ) { *dst_ptr = *src_ptr; } if (pf_add_env_page(e, start_last_page, ptr_temp_page) == E_NO_PAGE_FILE_SPACE) panic("ERROR: Page File OUT OF SPACE. can't load the program in Page file!!"); //LOG_STRING(" -------------------- PAGE FILE: last page is written"); ///[4] writing the remaining seg->size_in_memory pages to disk uint32 start_remaining_area = ROUNDUP(seg_va + seg->size_in_file,PAGE_SIZE) ; uint32 remainingLength = (seg_va + seg->size_in_memory) - start_remaining_area ; for (i=0 ; i < ROUNDUP(remainingLength,PAGE_SIZE) ;i+= PAGE_SIZE, start_remaining_area += PAGE_SIZE) { if (pf_add_empty_env_page(e, start_remaining_area, 1) == E_NO_PAGE_FILE_SPACE) panic("ERROR: Page File OUT OF SPACE. can't load the program in Page file!!"); } //LOG_STRING(" -------------------- PAGE FILE: segment remaining area is written (the zeros) "); }
int acpi_sleep_machdep(struct acpi_softc *sc, int state) { ACPI_STATUS status; struct pmap *pm; int ret; uint32_t cr3; u_long ef; ret = 0; if (sc->acpi_wakeaddr == 0) return (0); AcpiSetFirmwareWakingVector(sc->acpi_wakephys); ef = read_eflags(); /* * Temporarily switch to the kernel pmap because it provides an * identity mapping (setup at boot) for the low physical memory * region containing the wakeup code. */ pm = kernel_pmap; cr3 = rcr3(); #ifdef PAE load_cr3(vtophys(pm->pm_pdpt)); #else load_cr3(vtophys(pm->pm_pdir)); #endif ret_addr = 0; ACPI_DISABLE_IRQS(); if (acpi_savecpu()) { /* Execute Sleep */ intr_suspend(); p_gdt = (struct region_descriptor *) (sc->acpi_wakeaddr + physical_gdt); p_gdt->rd_limit = saved_gdt.rd_limit; p_gdt->rd_base = vtophys(saved_gdt.rd_base); WAKECODE_FIXUP(physical_esp, uint32_t, vtophys(r_esp)); WAKECODE_FIXUP(previous_cr0, uint32_t, r_cr0); WAKECODE_FIXUP(previous_cr2, uint32_t, r_cr2); WAKECODE_FIXUP(previous_cr3, uint32_t, r_cr3); WAKECODE_FIXUP(previous_cr4, uint32_t, r_cr4); WAKECODE_FIXUP(resume_beep, uint32_t, acpi_resume_beep); WAKECODE_FIXUP(reset_video, uint32_t, acpi_reset_video); WAKECODE_FIXUP(previous_tr, uint16_t, r_tr); WAKECODE_BCOPY(previous_gdt, struct region_descriptor, saved_gdt); WAKECODE_FIXUP(previous_ldt, uint16_t, saved_ldt); WAKECODE_BCOPY(previous_idt, struct region_descriptor, saved_idt); WAKECODE_FIXUP(where_to_recover, void *, acpi_restorecpu); WAKECODE_FIXUP(previous_ds, uint16_t, r_ds); WAKECODE_FIXUP(previous_es, uint16_t, r_es); WAKECODE_FIXUP(previous_fs, uint16_t, r_fs); WAKECODE_FIXUP(previous_gs, uint16_t, r_gs); WAKECODE_FIXUP(previous_ss, uint16_t, r_ss); if (bootverbose) acpi_printcpu(); /* Call ACPICA to enter the desired sleep state */ if (state == ACPI_STATE_S4 && sc->acpi_s4bios) status = AcpiEnterSleepStateS4bios(); else status = AcpiEnterSleepState(state); if (status != AE_OK) { device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", AcpiFormatException(status)); ret = -1; goto out; } for (;;) ; } else { /* Execute Wakeup */ intr_resume(); if (bootverbose) { acpi_savecpu(); acpi_printcpu(); } } out: load_cr3(cr3); write_eflags(ef); /* If we beeped, turn it off after a delay. */ if (acpi_resume_beep) timeout(acpi_stop_beep, NULL, 3 * hz); return (ret); }
// // Set up the initial program binary, stack, and processor flags // for a user process. // This function is ONLY called during kernel initialization, // before running the first user-mode environment. // // This function loads all loadable segments from the ELF binary image // into the environment's user memory, starting at the appropriate // virtual addresses indicated in the ELF program header. // At the same time it clears to zero any portions of these segments // that are marked in the program header as being mapped // but not actually present in the ELF file - i.e., the program's bss section. // // All this is very similar to what our boot loader does, except the boot // loader also needs to read the code from disk. Take a look at // boot/main.c to get ideas. // // Finally, this function maps one page for the program's initial stack. // // load_icode panics if it encounters problems. // - How might load_icode fail? What might be wrong with the given input? // static void load_icode(struct Env *e, uint8_t *binary, size_t size) { // Hints: // Load each program segment into virtual memory // at the address specified in the ELF section header. // You should only load segments with ph->p_type == ELF_PROG_LOAD. // Each segment's virtual address can be found in ph->p_va // and its size in memory can be found in ph->p_memsz. // The ph->p_filesz bytes from the ELF binary, starting at // 'binary + ph->p_offset', should be copied to virtual address // ph->p_va. Any remaining memory bytes should be cleared to zero. // (The ELF header should have ph->p_filesz <= ph->p_memsz.) // Use functions from the previous lab to allocate and map pages. // // All page protection bits should be user read/write for now. // ELF segments are not necessarily page-aligned, but you can // assume for this function that no two segments will touch // the same virtual page. // // You may find a function like segment_alloc useful. // // Loading the segments is much simpler if you can move data // directly into the virtual addresses stored in the ELF binary. // So which page directory should be in force during // this function? // // Hint: // You must also do something with the program's entry point, // to make sure that the environment starts executing there. // What? (See env_run() and env_pop_tf() below.) // LAB 3: Your code here. struct Proghdr *ph, *eph; struct Elf * header = (struct Elf *)binary; int i; uint32_t cr3; //switch to environment's page directory // (kernel part of which is the same as kernel's page directory's (except vpt, hm)) -ren cr3 = rcr3(); lcr3(e->env_cr3); // is this a valid ELF? if (header->e_magic != ELF_MAGIC) panic("load_icode - magic number is bad!"); ph = (struct Proghdr *) (binary + header->e_phoff); eph = ph + header->e_phnum; for (; ph < eph; ph++){ if (ph->p_type == ELF_PROG_LOAD){ segment_alloc(e, (void *)ph->p_va, (size_t) ph->p_memsz); memset( (void *) ph->p_va, 0, ph->p_memsz); memcpy( (void *) ph->p_va, binary + ph->p_offset, ph->p_filesz); } } e->env_tf.tf_eip=header->e_entry; //what about processor flags? (don't know) - ren //e->env_tf.tf_eflags // Now map one page for the program's initial stack // at virtual address USTACKTOP - PGSIZE. // LAB 3: Your code here. segment_alloc(e, (void *)USTACKTOP - PGSIZE, PGSIZE); //switch back to kernel's page directory - ren lcr3(cr3); }
// // Set up the initial program binary, stack, and processor flags // for a user process. // This function is ONLY called during kernel initialization, // before running the first user-mode environment. // // This function loads all loadable segments from the ELF binary image // into the environment's user memory, starting at the appropriate // virtual addresses indicated in the ELF program header. // At the same time it clears to zero any portions of these segments // that are marked in the program header as being mapped // but not actually present in the ELF file - i.e., the program's bss section. // // All this is very similar to what our boot loader does, except the boot // loader also needs to read the code from disk. Take a look at // boot/main.c to get ideas. // // Finally, this function maps one page for the program's initial stack. // // load_icode panics if it encounters problems. // - How might load_icode fail? What might be wrong with the given input? // static void load_icode(struct Env *e, uint8_t *binary, size_t size) { // Hints: // Load each program segment into virtual memory // at the address specified in the ELF section header. // You should only load segments with ph->p_type == ELF_PROG_LOAD. // Each segment's virtual address can be found in ph->p_va // and its size in memory can be found in ph->p_memsz. // The ph->p_filesz bytes from the ELF binary, starting at // 'binary + ph->p_offset', should be copied to virtual address // ph->p_va. Any remaining memory bytes should be cleared to zero. // (The ELF header should have ph->p_filesz <= ph->p_memsz.) // Use functions from the previous lab to allocate and map pages. // // All page protection bits should be user read/write for now. // ELF segments are not necessarily page-aligned, but you can // assume for this function that no two segments will touch // the same virtual page. // // You may find a function like segment_alloc useful. // // Loading the segments is much simpler if you can move data // directly into the virtual addresses stored in the ELF binary. // So which page directory should be in force during // this function? // // Hint: // You must also do something with the program's entry point, // to make sure that the environment starts executing there. // What? (See env_run() and env_pop_tf() below.) // LAB 3: Your code here. struct Elf *env_elf = (struct Elf *)binary; struct Proghdr *ph, *eph; struct Page *pg; uint32_t old_cr3; // store the current cr3 and // switch cr3 to the pgdir of the env old_cr3 = rcr3(); lcr3(PADDR(e->env_pgdir)); if(env_elf->e_magic != ELF_MAGIC){ panic("elf header's magic is not correct\n"); } ph = (struct Proghdr *)((uint8_t *)env_elf + env_elf->e_phoff); eph = ph + env_elf->e_phnum; for( ; ph < eph; ph++){ if(ph->p_type == ELF_PROG_LOAD){ segment_alloc(e, (void *)ph->p_va, ph->p_memsz); // cprintf("load_icode segment_alloc succeeded!\n"); memset((void *)ph->p_va, 0, ph->p_memsz); memmove((void*)ph->p_va, (void *)((uint32_t) env_elf + ph->p_offset), ph->p_filesz); } } // cprintf("load_icode while loop succeeded!\n"); e->env_tf.tf_eip = env_elf->e_entry; // cprintf("load_icode program entry point: %x\n", elf->e_entry); // Now map one page for the program's initial stack // at virtual address USTACKTOP - PGSIZE. // LAB 3: Your code here. if(page_alloc(&pg) != 0){ panic("load_icode page_alloc fail!!!\n"); } if(page_insert(e->env_pgdir, pg, (void *)(USTACKTOP - PGSIZE), PTE_U|PTE_W) != 0){ panic("load_icode page_insert fail!!!\n"); } lcr3(old_cr3); //cprintf("load_icode success!\n"); }
void screen_pintar_info_debug(uint eax, uint ebx, uint ecx, uint edx, uint esi, uint edi, uint ebp, uint cs, uint ds, uint fs, uint gs, uint ss, uint eflags, uint esp, uint eip, uint stack0, uint stack1, uint stack2, uint stack3, uint stack4){ screen_guardar_atras_debug(); screen_pintar_rect(' ', C_BG_BLACK, POSICION_CUADRO_DEBUG_Y, POSICION_CUADRO_DEBUG_X, ALTO_CUADRO_DEBUG, ANCHO_CUADRO_DEBUG); screen_pintar_rect(' ', C_BG_RED, POSICION_CUADRO_DEBUG_Y + 1, POSICION_CUADRO_DEBUG_X + 1, ALTO_BANDA_DEBUG, ANCHO_CUADRO_DEBUG - 2); screen_pintar_rect(' ', C_BG_LIGHT_GREY, POSICION_CUADRO_DEBUG_Y + 1 + ALTO_BANDA_DEBUG, POSICION_CUADRO_DEBUG_X + 1, ALTO_CUADRO_DEBUG - ALTO_BANDA_DEBUG - 2, ANCHO_CUADRO_DEBUG - 2); print("eax", POSICION_CUADRO_DEBUG_X + 2, POSICION_CUADRO_DEBUG_Y + 3, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(eax, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 3, C_BG_LIGHT_GREY | C_FG_WHITE); print("ebx", POSICION_CUADRO_DEBUG_X + 2, POSICION_CUADRO_DEBUG_Y + 5, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(ebx, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 5, C_BG_LIGHT_GREY | C_FG_WHITE); print("ecx", POSICION_CUADRO_DEBUG_X + 2, POSICION_CUADRO_DEBUG_Y + 7, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(ecx, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 7, C_BG_LIGHT_GREY | C_FG_WHITE); print("edx", POSICION_CUADRO_DEBUG_X + 2, POSICION_CUADRO_DEBUG_Y + 9, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(edx, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 9, C_BG_LIGHT_GREY | C_FG_WHITE); print("esi", POSICION_CUADRO_DEBUG_X + 2, POSICION_CUADRO_DEBUG_Y + 11, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(esi, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 11, C_BG_LIGHT_GREY | C_FG_WHITE); print("edi", POSICION_CUADRO_DEBUG_X + 2, POSICION_CUADRO_DEBUG_Y + 13, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(edi, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 13, C_BG_LIGHT_GREY | C_FG_WHITE); print("ebp", POSICION_CUADRO_DEBUG_X + 2, POSICION_CUADRO_DEBUG_Y + 15, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(ebp, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 15, C_BG_LIGHT_GREY | C_FG_WHITE); print("esp", POSICION_CUADRO_DEBUG_X + 2, POSICION_CUADRO_DEBUG_Y + 17, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(esp, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 17, C_BG_LIGHT_GREY | C_FG_WHITE); print("eip", POSICION_CUADRO_DEBUG_X + 2, POSICION_CUADRO_DEBUG_Y + 19, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(eip, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 19, C_BG_LIGHT_GREY | C_FG_WHITE); print("cs", POSICION_CUADRO_DEBUG_X + 3, POSICION_CUADRO_DEBUG_Y + 21, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(cs, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 21, C_BG_LIGHT_GREY | C_FG_WHITE); print("ds", POSICION_CUADRO_DEBUG_X + 3, POSICION_CUADRO_DEBUG_Y + 23, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(ds, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 23, C_BG_LIGHT_GREY | C_FG_WHITE); print("fs", POSICION_CUADRO_DEBUG_X + 3, POSICION_CUADRO_DEBUG_Y + 25, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(fs, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 25, C_BG_LIGHT_GREY | C_FG_WHITE); print("gs", POSICION_CUADRO_DEBUG_X + 3, POSICION_CUADRO_DEBUG_Y + 27, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(gs, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 27, C_BG_LIGHT_GREY | C_FG_WHITE); print("ss", POSICION_CUADRO_DEBUG_X + 3, POSICION_CUADRO_DEBUG_Y + 29, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(ss, 8, POSICION_CUADRO_DEBUG_X + 6, POSICION_CUADRO_DEBUG_Y + 29, C_BG_LIGHT_GREY | C_FG_WHITE); print("eflags", POSICION_CUADRO_DEBUG_X + 3, POSICION_CUADRO_DEBUG_Y + 31, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(eflags, 8, POSICION_CUADRO_DEBUG_X + 10, POSICION_CUADRO_DEBUG_Y + 31, C_BG_LIGHT_GREY | C_FG_WHITE); print("cr0", POSICION_CUADRO_DEBUG_X + 16, POSICION_CUADRO_DEBUG_Y + 3, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(rcr0(), 8, POSICION_CUADRO_DEBUG_X + 20, POSICION_CUADRO_DEBUG_Y + 3, C_BG_LIGHT_GREY | C_FG_WHITE); print("cr2", POSICION_CUADRO_DEBUG_X + 16, POSICION_CUADRO_DEBUG_Y + 5, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(rcr2(), 8, POSICION_CUADRO_DEBUG_X + 20, POSICION_CUADRO_DEBUG_Y + 5, C_BG_LIGHT_GREY | C_FG_WHITE); print("cr3", POSICION_CUADRO_DEBUG_X + 16, POSICION_CUADRO_DEBUG_Y + 7, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(rcr3(), 8, POSICION_CUADRO_DEBUG_X + 20, POSICION_CUADRO_DEBUG_Y + 7, C_BG_LIGHT_GREY | C_FG_WHITE); print("cr4", POSICION_CUADRO_DEBUG_X + 16, POSICION_CUADRO_DEBUG_Y + 9, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(rcr4(), 8, POSICION_CUADRO_DEBUG_X + 20, POSICION_CUADRO_DEBUG_Y + 9, C_BG_LIGHT_GREY | C_FG_WHITE); print("stack", POSICION_CUADRO_DEBUG_X + 16, POSICION_CUADRO_DEBUG_Y + 20, C_BG_LIGHT_GREY | C_FG_BLACK); print_hex(stack0, 8, POSICION_CUADRO_DEBUG_X + 16, POSICION_CUADRO_DEBUG_Y + 23, C_BG_LIGHT_GREY | C_FG_WHITE); print_hex(stack1, 8, POSICION_CUADRO_DEBUG_X + 16, POSICION_CUADRO_DEBUG_Y + 24, C_BG_LIGHT_GREY | C_FG_WHITE); print_hex(stack2, 8, POSICION_CUADRO_DEBUG_X + 16, POSICION_CUADRO_DEBUG_Y + 25, C_BG_LIGHT_GREY | C_FG_WHITE); print_hex(stack3, 8, POSICION_CUADRO_DEBUG_X + 16, POSICION_CUADRO_DEBUG_Y + 26, C_BG_LIGHT_GREY | C_FG_WHITE); print_hex(stack4, 8, POSICION_CUADRO_DEBUG_X + 16, POSICION_CUADRO_DEBUG_Y + 27, C_BG_LIGHT_GREY | C_FG_WHITE); }
int acpi_sleep_machdep(struct acpi_softc *sc, int state) { struct savefpu *stopfpu; #ifdef SMP cpumask_t wakeup_cpus; #endif register_t cr3, rf; ACPI_STATUS status; int ret; ret = -1; if (sc->acpi_wakeaddr == 0ul) return (ret); #ifdef SMP wakeup_cpus = PCPU_GET(other_cpus); #endif AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc)); rf = intr_disable(); intr_suspend(); /* * Temporarily switch to the kernel pmap because it provides * an identity mapping (setup at boot) for the low physical * memory region containing the wakeup code. */ cr3 = rcr3(); load_cr3(KPML4phys); stopfpu = &stopxpcbs[0].xpcb_pcb.pcb_save; if (acpi_savecpu(&stopxpcbs[0])) { fpugetregs(curthread, stopfpu); #ifdef SMP if (wakeup_cpus != 0 && suspend_cpus(wakeup_cpus) == 0) { device_printf(sc->acpi_dev, "Failed to suspend APs: CPU mask = 0x%jx\n", (uintmax_t)(wakeup_cpus & ~stopped_cpus)); goto out; } #endif WAKECODE_FIXUP(resume_beep, uint8_t, (acpi_resume_beep != 0)); WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0)); WAKECODE_FIXUP(wakeup_xpcb, struct xpcb *, &stopxpcbs[0]); WAKECODE_FIXUP(wakeup_gdt, uint16_t, stopxpcbs[0].xpcb_gdt.rd_limit); WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t, stopxpcbs[0].xpcb_gdt.rd_base); WAKECODE_FIXUP(wakeup_cpu, int, 0); /* Call ACPICA to enter the desired sleep state */ if (state == ACPI_STATE_S4 && sc->acpi_s4bios) status = AcpiEnterSleepStateS4bios(); else status = AcpiEnterSleepState(state); if (status != AE_OK) { device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", AcpiFormatException(status)); goto out; } for (;;) ia32_pause(); } else {
uint_32 sys_fork(uint_32 org_eip, uint_32 org_esp) { //me guardo el cr3 viejo. uint_32 old_cr3 = rcr3(); printf(" >sys_fork: org_eip (%x), org_esp (%x)", org_eip, org_esp); //pido un directorio para la nueva tarea void* new_cr3 = mm_dir_fork((mm_page*) old_cr3); if (new_cr3 == NULL) { //No pudo hacerse fork de la estrucutra de paginación printf("! >sys_fork: no se pudo crear el directorio de la nueva tarea"); return -1; } printf(" >sys_fork: new_cr3 = %x", new_cr3); //stacks de anillo 3 y 0 para la tarea void* task_stack3 = mm_mem_alloc(); void* task_stack0 = mm_mem_alloc(); printf(" >sys_fork: paginas stack_ kernel %x | usr %x", task_stack0, task_stack3); //ver esto donde van mapeados los stacks mm_page_map(STACK_3_VIRTUAL, new_cr3, (uint_32) task_stack3, 0, USR_STD_ATTR); mm_page_map(STACK_0_VIRTUAL, new_cr3, (uint_32) task_stack0, 0, MM_ATTR_RW | MM_ATTR_US_S); //TODO ver estas direcciones temporales donde ponerlas mm_page_map(KERNEL_TEMP_PAGE,(mm_page *) old_cr3, (uint_32) task_stack0, 0, MM_ATTR_RW | MM_ATTR_US_S); //inicializamos la pila de nivel 0 para que tenga el contexto para //poder volver del switchto uint_32* stack0 = (uint_32*) (KERNEL_TEMP_PAGE + 0xffC); *stack0-- = 0x23; *stack0-- = org_esp; *stack0-- = 0x202; *stack0-- = 0x1B; *stack0-- = org_eip; *stack0-- = (uint_32) &fork_ret; *stack0-- = resp(); *stack0-- = 0x0; *stack0-- = 0x0; *stack0-- = 0x0; //Copio la pila de usuario como está //Innecesario, ya lo hace el fork mm_copy_vf((uint_32*)STACK_3_VIRTUAL, (uint_32)task_stack3, PAGE_SIZE); mm_page_free(KERNEL_TEMP_PAGE, (mm_page*) old_cr3); tlbflush(); //tengo que armar la estructura de proceso uint_32 requested_pid = get_new_pid(); task_table[requested_pid].cr3 = (uint_32) new_cr3; task_table[requested_pid].esp0 = STACK_0_VIRTUAL + 0xFD8; //Duplico los file descriptor actualizando referencias device_fork_descriptors(cur_pid, requested_pid); // esto esta mal.. tiene q decidir q numero devolver creo q necesitamos un semaforo! sched_load(requested_pid); tasks_running++; printf(" >sys_fork: forkeo finalizado en pid %d", requested_pid); mm_dump(); return requested_pid; }
pid loader_load(pso_file* f, int pl) { //me guardo el cr3 viejo. uint_32 old_cr3 = rcr3(); //pido un directorio para la nueva tarea void* task_dir = mm_dir_new(); printf(" >loader_load: task_dir = %x", task_dir); //TODO VER CUANTA MEMORIA NECESITA REALMENTE void* puntero_page_tarea = mm_mem_alloc(); printf(" >loader_load: puntero page tarea : %x", (uint_32) puntero_page_tarea); //stacks de anillo 3 y 0 para la tarea void* task_stack3 = mm_mem_alloc(); void* task_stack0 = mm_mem_alloc(); printf(" >loader_load: pfi after allocs: kernel = %x | usr = %x", *kernel_pf_info, *usr_pf_info); //ver esto donde van mapeados los stacks mm_page_map(STACK_3_VIRTUAL, task_dir, (uint_32) task_stack3, 0, USR_STD_ATTR); mm_page_map(STACK_0_VIRTUAL, task_dir, (uint_32) task_stack0, 0, MM_ATTR_RW | MM_ATTR_US_S); //TODO ver estas direcciones temporales donde ponerlas mm_page_map(KERNEL_TEMP_PAGE,(mm_page *) old_cr3, (uint_32) task_stack0, 0, MM_ATTR_RW | MM_ATTR_US_S); //inicializamos la pila de nivel 0 para que tenga el contexto para //poder volver del switchto uint_32* stack0 = (uint_32*) (KERNEL_TEMP_PAGE + 0xffC); *stack0-- = 0x23; *stack0-- = STACK_3_VIRTUAL + 0x1000; *stack0-- = 0x202; *stack0-- = (pl)? 0x1B : 0x08; //Elijo el selector de segmento según el privilegio de la tarea *stack0-- = (uint_32) f->_main; *stack0-- = (uint_32) &task_ret; *stack0-- = resp(); *stack0-- = 0x0; *stack0-- = 0x0; *stack0-- = 0x0; mm_page_map((uint_32) f->mem_start, task_dir, (uint_32) puntero_page_tarea, 0, USR_STD_ATTR); //mapeo la direccion virtual temporal para copiar en la pagina que recien se me asigno. mm_page_map((uint_32) KERNEL_TEMP_PAGE,(mm_page *) old_cr3, (uint_32) puntero_page_tarea, 0, USR_STD_ATTR); tlbflush(); //copio la tarea desde donde esta a la pagina que acabo de mapear. uint_8* addr_to_copy = (uint_8*) KERNEL_TEMP_PAGE; uint_8* task_to_copy = (uint_8*) f; uint_32 cant_to_copy = f->mem_end_disk - f->mem_start; int i; printf(" >loader_load: task_to_copy = %x", task_to_copy); for (i = 0; i < cant_to_copy; i++) { *addr_to_copy++ = *task_to_copy++; } //tengo que armar la estreuctura uint_32 requested_pid = get_new_pid(); task_table[requested_pid].cr3 = (uint_32) task_dir; task_table[requested_pid].esp0 = STACK_0_VIRTUAL + 0xFD8; mm_page_free(KERNEL_TEMP_PAGE, (mm_page *) old_cr3); tlbflush(); sched_load(requested_pid); tasks_running++; printf(" >loader_load: finished loading to new pid %d", requested_pid); return requested_pid; }