Esempio n. 1
0
void
cpu_reset(void)
{

	disable_intr();

	/*
	 * The keyboard controller has 4 random output pins, one of which is
	 * connected to the RESET pin on the CPU in many PCs.  We tell the
	 * keyboard controller to pulse this line a couple of times.
	 */
	outb(IO_KBD + KBCMDP, KBC_PULSE0);
	delay(100000);
	outb(IO_KBD + KBCMDP, KBC_PULSE0);
	delay(100000);

	/*
	 * Try to cause a triple fault and watchdog reset by making the IDT
	 * invalid and causing a fault.
	 */
	memset((caddr_t)idt, 0, NIDT * sizeof(idt[0]));
	__asm __volatile("divl %0,%1" : : "q" (0), "a" (0)); 

#if 0
	/*
	 * Try to cause a triple fault and watchdog reset by unmapping the
	 * entire address space and doing a TLB flush.
	 */
	memset((caddr_t)PTD, 0, PAGE_SIZE);
	tlbflush(); 
#endif

	for (;;);
}
Esempio n. 2
0
/*
 * Move pages from one kernel virtual address to another.
 * Both addresses are assumed to reside in the Sysmap.
 */
void
pagemove(caddr_t from, caddr_t to, size_t size)
{
    pt_entry_t *fpte, *tpte, *mafpte, *matpte;
    pt_entry_t ofpte, otpte;
#ifdef MULTIPROCESSOR
    u_int32_t cpumask = 0;
#endif

#ifdef DIAGNOSTIC
    if ((size & PAGE_MASK) != 0)
        panic("pagemove");
#endif
    fpte = kvtopte((vaddr_t)from);
    tpte = kvtopte((vaddr_t)to);
    while (size > 0) {
        mafpte = (pt_entry_t *)vtomach((vaddr_t)fpte);
        matpte = (pt_entry_t *)vtomach((vaddr_t)tpte);
        otpte = pte_atomic_update(tpte, matpte, *fpte);
        ofpte = pte_atomic_update(fpte, mafpte, 0);
        tpte++;
        fpte++;
#if defined(I386_CPU) && !defined(MULTIPROCESSOR)
        if (cpu_class != CPUCLASS_386)
#endif
        {
            if (otpte & PG_V)
#ifdef MULTIPROCESSOR
                pmap_tlb_shootdown(pmap_kernel(), (vaddr_t)to,
                                   otpte, &cpumask);
#else
                pmap_update_pg((vaddr_t)to);
#endif
            if (ofpte & PG_V)
#ifdef MULTIPROCESSOR
                pmap_tlb_shootdown(pmap_kernel(),
                                   (vaddr_t)from, ofpte, &cpumask);
#else
                pmap_update_pg((vaddr_t)from);
#endif
        }

        from += PAGE_SIZE;
        to += PAGE_SIZE;
        size -= PAGE_SIZE;
    }
#ifdef MULTIPROCESSOR
    pmap_tlb_shootnow(cpumask);
#else
#if defined(I386_CPU)
    if (cpu_class == CPUCLASS_386)
        tlbflush();
#endif
#endif
}
Esempio n. 3
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;
}
Esempio n. 4
0
/*
 * Write bytes to kernel address space for debugger.
 */
void
db_write_bytes(vaddr_t addr, size_t size, char *data)
{
	char	*dst;

	pt_entry_t *ptep0 = 0;
	pt_entry_t	oldmap0 = { 0 };
	vaddr_t	addr1;
	pt_entry_t *ptep1 = 0;
	pt_entry_t	oldmap1 = { 0 };
	extern char	etext;

	if (addr >= VM_MIN_KERNEL_ADDRESS &&
	    addr < (vaddr_t)&etext) {
		ptep0 = kvtopte(addr);
		oldmap0 = *ptep0;
		*(int *)ptep0 |= /* INTEL_PTE_WRITE */ PG_RW;

		addr1 = trunc_page(addr + size - 1);
		if (trunc_page(addr) != addr1) {
			/* data crosses a page boundary */
			ptep1 = kvtopte(addr1);
			oldmap1 = *ptep1;
			*(int *)ptep1 |= /* INTEL_PTE_WRITE */ PG_RW;
		}
		tlbflush();
	}

	dst = (char *)addr;

	while (size-- > 0)
		*dst++ = *data++;

	if (ptep0) {
		*ptep0 = oldmap0;
		if (ptep1)
			*ptep1 = oldmap1;
		tlbflush();
	}
}
Esempio n. 5
0
//Pre: existe la pagina a desmapear
//Post: se desmapea la pagina, queda no presente en la tabla de paginas correspondiente.
void mmu_unmapear_pagina(unsigned int virtual, pagedir_entry* pageDirBase){
    //obtengo los indices del dir de paginas y las tablas
    unsigned int pdIndex = (unsigned int)(virtual >> 22);//me quedo con los bits 31 a 22
    unsigned int ptIndex = (unsigned int)((virtual >> 12) & 0x03FF);//con la mascara me quedo unicamente con 10 bits de los bits 21 a 12    
    
    //obtengo la tabla de paginas desde el directorio de paginas
    //shifteo 12 bits la direccion para completar el puntero de 32 bits a la tabla de paginas apuntada por la entrada del directorio
    pagetable_entry* pageTable = (pagetable_entry*) (pageDirBase[pdIndex].pageBase << 12);

    //indexo la pagina en cuestion de la tabla y la seteo como no presente
    pageTable[ptIndex].present=0;//la marco como no presente
    //si no quedaron mas paginas presentes en toda la tabla, seteo como no presente la entrada del directorio?
    tlbflush();
}
Esempio n. 6
0
//esta funcion inicializa el directorio de paginas y las 2 tablas de paginas necesarias que se piden por enunciado en el ej 3b.
//para el ejercicio 3b del tp me piden mapear los primeros 7.5mb entre 0x00000000 y 0x0077FFFF, necesito 2 entradas en el directorio de paginas, 
//la primera de 1024 entradas de 4k => 4mb y la segunda con 896 entradas de 4k => 3584 = 3.5mb
//las primeras 1024 paginas las puedo clavar en la tabla de paginas del kernel en 0x28000 segun el mapa de memoria
//las proximas 896 las voy a poner momentaneamente a partir de KERNEL_SECOND_PAGETABLE_POINTER por lo consultado a los ayudantes que realizaron el mapa de memoria
void mmu_inicializar_dir_kernel() {
	//marco todas como no presentes en el directorio de paginas, son 1024 entradas
	pageDirectoryInitialize(krnPageDir, 0, 0, 1023);
	//inicializo 1024 paginas con direcciones entre 0 y 1023*4096 marcandolas como presentes
	pageTableInitialize(krnFirstPageTable, 1, 0, 1023, 0);
	//marco las 1024 paginas como no presentes en la segunda tabla de paginas
	pageTableInitialize(krnSecondPageTable, 0, 0, 1023, 1024/*comenzar a mapear desde aqui*/);
	//inicializo las primeras 896 paginas para llenar 3.5mb como presentes
	pageTableInitialize(krnSecondPageTable, 1, 0, 895, 1024/*comenzar a mapear desde 1024 inclusive*/);
	
	//activo las primeras 2 paginas del directorio y les seteo las direcciones de las 2 tablas de paginas
	PAGEDIR_ENTRY(krnPageDir, 0/*index*/, 1/*present*/, 1/*read+write*/, 0/*supervisor*/, 0, 0, 0, 0, 0, 0, 0, (((unsigned int)(krnFirstPageTable))  >> 12) );
	PAGEDIR_ENTRY(krnPageDir, 1/*index*/, 1/*present*/, 1/*read+write*/, 0/*supervisor*/, 0, 0, 0, 0, 0, 0, 0, (((unsigned int)(krnSecondPageTable))  >> 12) );	
    //invalido la cache de traduccion de direcciones
    tlbflush();    
}
Esempio n. 7
0
//Pre: todas las entradas del dir de paginas y de todas las tablas de paginas que se acceden estan previamente inicializadas
//es decir, cuando accedo a las pageBase los punteros son validos y los bits tienen algun valor inicializado a conciencia
//&& dir fisica esta alineada a 4k
//Post: pisa la pagina si existia anteriormente con el mapeo
void mmu_mapear_pagina(unsigned int virtual, pagedir_entry* pageDirBase, unsigned int fisica, unsigned char readWriteb, unsigned char userSupervisorb){
    //obtengo los indices del dir de paginas y las tablas
    unsigned int pdIndex = (unsigned int)(virtual >> 22);//me quedo con los bits 31 a 22
    unsigned int ptIndex = (unsigned int)((virtual >> 12) & 0x03FF);//con la mascara me quedo unicamente con 10 bits de los bits 21 a 12    
    //obtengo el offset de la pagina
    unsigned int pageOffset = (unsigned int)(virtual & 0x0FFF);//me quedo con los primeros 12 bits

    //obtengo la tabla de paginas desde el directorio de paginas
    //shifteo 12 bits la direccion para completar el puntero de 32 bits a la tabla de paginas apuntada por la entrada del directorio
    
    //esto es un acceso valido por precondicion!
    pagetable_entry* pageTable = (pagetable_entry*) (pageDirBase[pdIndex].pageBase << 12);
    //PARAMETROS MACRO: pageTableTarget, index, userSupervisorb, pageLevelWriteThroughb, pageLevelCacheDisableb, accesedb, dirtyBitb, disponibleb, pageBased
    PAGETABLE_ENTRY(pageTable, ptIndex, 1/*present*/, readWriteb/*read+write*/, userSupervisorb/*supervisor*/, 0/*pageLevelWriteThroughb*/, 0/*pageLevelCacheDisableb*/, 0/*accesedb*/, 0/*dirtyBitb*/, 0/*disponibleb*/, ((fisica + pageOffset) >> 12)/*direccion >> 12 pues es multiplo de 4k*/);
    //seteo como presente la entrada en el directorio de paginas(podria pasar que no hubiera ninguna pagina todavia y ahora la hay)
    pageDirBase[pdIndex].present = 1;
    tlbflush();
}
Esempio n. 8
0
File: env.c Progetto: anandab/akaros
/* Frees (decrefs) all memory mapped in the given range */
void env_user_mem_free(env_t* e, void* start, size_t len)
{
	assert((uintptr_t)start + len <= UVPT); //since this keeps f*****g happening
	int user_page_free(env_t* e, pte_t pte, void* va, void* arg)
	{
		if (!pte_is_mapped(pte))
			return 0;
		page_t *page = pa2page(pte_get_paddr(pte));
		pte_clear(pte);
		page_decref(page);
		/* TODO: consider other states here (like !P, yet still tracking a page,
		 * for VM tricks, page map stuff, etc.  Should be okay: once we're
		 * freeing, everything else about this proc is dead. */
		return 0;
	}

	env_user_mem_walk(e,start,len,&user_page_free,NULL);
	tlbflush();
}
Esempio n. 9
0
void mmu_unmapear_pagina(unsigned int virtual, unsigned int cr3){
	
	int *page_directory = (int*) (ALIGN(cr3));
	int *page_table = (int*) (page_directory[PDE_INDEX(virtual)] & 0xFFFFF000);	
	int presente = (page_directory[PDE_INDEX(virtual)] & 0x01);
	int tablaVacia = 1;
	if(presente){
		page_table[PTE_INDEX(virtual)] = 0;
		int i = 0;
		while(tablaVacia && i < 1024){
			int entradaNoPresente = (page_table[i] & 0x01);
			// Aca usamos and logico. La tabla esta vacia
			// si ya estaba vacia y la i-esima entrada no esta presente
			tablaVacia = tablaVacia && entradaNoPresente;
			i++;
		}
		if(tablaVacia){
			page_directory[PDE_INDEX(virtual)] = 0;
		}
	}
	tlbflush();
}
Esempio n. 10
0
static inline void
pmap_tlb_invalidate(const pmap_tlb_packet_t *tp)
{
	int i;

	/* Find out what we need to invalidate. */
	if (tp->tp_count == (uint16_t)-1) {
		u_int egen = uvm_emap_gen_return();
		if (tp->tp_pte & PG_G) {
			/* Invalidating user and kernel TLB entries. */
			tlbflushg();
		} else {
			/* Invalidating user TLB entries only. */
			tlbflush();
		}
		uvm_emap_update(egen);
	} else {
		/* Invalidating a single page or a range of pages. */
		for (i = tp->tp_count - 1; i >= 0; i--) {
			pmap_update_pg(tp->tp_va[i]);
		}
	}
}
Esempio n. 11
0
void mmu_mapear_pagina( unsigned int virtual, unsigned int cr3, unsigned int fisica, short attr){
	unsigned int pageDirIndex = PDE_INDEX(virtual);	//ebp-12
	unsigned int pageDirTableIndex = PTE_INDEX(virtual); //ebp-16
	unsigned int page_table_entry = fisica | attr; //ebp-20
	int* page_directory = (int*) (ALIGN(cr3));
	int* page_table = 0;

	int presente = (page_directory[pageDirIndex] & 0x01);
	if(!presente){ // chequeo presente! 
		page_table = mmu_proxima_pagina_fisica_libre();
		page_directory[pageDirIndex] = ( (unsigned int) page_table ) | attr; 
		int i = 0;
		while(i < 1024) {// Limpiamos la tabla nueva
			page_table[i] = 0; 
			i++;
		}
	}else{
		page_table = ((int*) (page_directory[pageDirIndex] & 0xFFFFF000));
	}
	
	page_table[pageDirTableIndex] = page_table_entry;

	tlbflush();
}
Esempio n. 12
0
// Free the EPT table entries and the EPT tables.
// NOTE: Does not deallocate EPT PML4 page.
void free_guest_mem(epte_t* eptrt) {
    free_ept_level(eptrt, EPT_LEVELS - 1);
    tlbflush();
}
Esempio n. 13
0
File: loader.c Progetto: emancu/pso
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;
}
Esempio n. 14
0
File: loader.c Progetto: emancu/pso
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;
}