<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es">
		<id>https://1984.lsi.us.es/wiki-ssoo/index.php?action=history&amp;feed=atom&amp;title=Memoria_virtual</id>
		<title>Memoria virtual - Historial de revisiones</title>
		<link rel="self" type="application/atom+xml" href="https://1984.lsi.us.es/wiki-ssoo/index.php?action=history&amp;feed=atom&amp;title=Memoria_virtual"/>
		<link rel="alternate" type="text/html" href="https://1984.lsi.us.es/wiki-ssoo/index.php?title=Memoria_virtual&amp;action=history"/>
		<updated>2026-06-26T20:43:07Z</updated>
		<subtitle>Historial de revisiones para esta página en el wiki</subtitle>
		<generator>MediaWiki 1.29.0</generator>

	<entry>
		<id>https://1984.lsi.us.es/wiki-ssoo/index.php?title=Memoria_virtual&amp;diff=3294&amp;oldid=prev</id>
		<title>Alemarmar5: Página creada con «= Introducción =  La memoria virtual se encuentra principalmente en el archivo '''''vm.c'''''. En él están los métodos que implementan la memoria virtual tal y como la ...»</title>
		<link rel="alternate" type="text/html" href="https://1984.lsi.us.es/wiki-ssoo/index.php?title=Memoria_virtual&amp;diff=3294&amp;oldid=prev"/>
				<updated>2016-01-21T18:49:05Z</updated>
		
		<summary type="html">&lt;p&gt;Página creada con «= Introducción =  La memoria virtual se encuentra principalmente en el archivo &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;vm.c&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;. En él están los métodos que implementan la memoria virtual tal y como la ...»&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Página nueva&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= Introducción =&lt;br /&gt;
&lt;br /&gt;
La memoria virtual se encuentra principalmente en el archivo '''''vm.c'''''. En él están los métodos que implementan la memoria virtual tal y como la hemos visto en teoría. Como pasaba en el planificador de procesos, ''vm.c'' también llama a otros archivos en los cuales se implementa código necesario, como por ejemplo '''''mmu.h'''''. Dicho archivo implementa en ''C'' el dispositivo hardware conocido como [https://en.wikipedia.org/wiki/Memory_management_unit mmu], el cual lleva a cabo el manejo de la memoria virtual.&lt;br /&gt;
A continuación se muestran los archivos citados anteriormente:&lt;br /&gt;
&lt;br /&gt;
Archivo '''''vm.c''''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;param.h&amp;quot;&lt;br /&gt;
#include &amp;quot;types.h&amp;quot;&lt;br /&gt;
#include &amp;quot;defs.h&amp;quot;&lt;br /&gt;
#include &amp;quot;x86.h&amp;quot;&lt;br /&gt;
#include &amp;quot;memlayout.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmu.h&amp;quot;&lt;br /&gt;
#include &amp;quot;proc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;elf.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
extern char data[];  // defined by kernel.ld&lt;br /&gt;
pde_t *kpgdir;  // for use in scheduler()&lt;br /&gt;
struct segdesc gdt[NSEGS];&lt;br /&gt;
&lt;br /&gt;
// Set up CPU's kernel segment descriptors.&lt;br /&gt;
// Run once on entry on each CPU.&lt;br /&gt;
void&lt;br /&gt;
seginit(void)&lt;br /&gt;
{&lt;br /&gt;
  struct cpu *c;&lt;br /&gt;
&lt;br /&gt;
  // Map &amp;quot;logical&amp;quot; addresses to virtual addresses using identity map.&lt;br /&gt;
  // Cannot share a CODE descriptor for both kernel and user&lt;br /&gt;
  // because it would have to have DPL_USR, but the CPU forbids&lt;br /&gt;
  // an interrupt from CPL=0 to DPL=3.&lt;br /&gt;
  c = &amp;amp;cpus[cpunum()];&lt;br /&gt;
  c-&amp;gt;gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0);&lt;br /&gt;
  c-&amp;gt;gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);&lt;br /&gt;
  c-&amp;gt;gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER);&lt;br /&gt;
  c-&amp;gt;gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);&lt;br /&gt;
&lt;br /&gt;
  // Map cpu, and curproc&lt;br /&gt;
  c-&amp;gt;gdt[SEG_KCPU] = SEG(STA_W, &amp;amp;c-&amp;gt;cpu, 8, 0);&lt;br /&gt;
&lt;br /&gt;
  lgdt(c-&amp;gt;gdt, sizeof(c-&amp;gt;gdt));&lt;br /&gt;
  loadgs(SEG_KCPU &amp;lt;&amp;lt; 3);&lt;br /&gt;
  &lt;br /&gt;
  // Initialize cpu-local storage.&lt;br /&gt;
  cpu = c;&lt;br /&gt;
  proc = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Return the address of the PTE in page table pgdir&lt;br /&gt;
// that corresponds to virtual address va.  If !=0,&lt;br /&gt;
// create any required page table pages.&lt;br /&gt;
static pte_t *&lt;br /&gt;
walkpgdir(pde_t *pgdir, const void *va, int alloc)&lt;br /&gt;
{&lt;br /&gt;
  pde_t *pde;&lt;br /&gt;
  pte_t *pgtab;&lt;br /&gt;
&lt;br /&gt;
  pde = &amp;amp;pgdir[PDX(va)];&lt;br /&gt;
  if(*pde &amp;amp; PTE_P){&lt;br /&gt;
    pgtab = (pte_t*)p2v(PTE_ADDR(*pde));&lt;br /&gt;
  } else {&lt;br /&gt;
    if(!alloc || (pgtab = (pte_t*)kalloc()) == 0)&lt;br /&gt;
      return 0;&lt;br /&gt;
    // Make sure all those PTE_P bits are zero.&lt;br /&gt;
    memset(pgtab, 0, PGSIZE);&lt;br /&gt;
    // The permissions here are overly generous, but they can&lt;br /&gt;
    // be further restricted by the permissions in the page table &lt;br /&gt;
    // entries, if necessary.&lt;br /&gt;
    *pde = v2p(pgtab) | PTE_P | PTE_W | PTE_U;&lt;br /&gt;
  }&lt;br /&gt;
  return &amp;amp;pgtab[PTX(va)];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Create PTEs for virtual addresses starting at va that refer to&lt;br /&gt;
// physical addresses starting at pa. va and size might not&lt;br /&gt;
// be page-aligned.&lt;br /&gt;
static int&lt;br /&gt;
mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm)&lt;br /&gt;
{&lt;br /&gt;
  char *a, *last;&lt;br /&gt;
  pte_t *pte;&lt;br /&gt;
  &lt;br /&gt;
  a = (char*)PGROUNDDOWN((uint)va);&lt;br /&gt;
  last = (char*)PGROUNDDOWN(((uint)va) + size - 1);&lt;br /&gt;
  for(;;){&lt;br /&gt;
    if((pte = walkpgdir(pgdir, a, 1)) == 0)&lt;br /&gt;
      return -1;&lt;br /&gt;
    if(*pte &amp;amp; PTE_P)&lt;br /&gt;
      panic(&amp;quot;remap&amp;quot;);&lt;br /&gt;
    *pte = pa | perm | PTE_P;&lt;br /&gt;
    if(a == last)&lt;br /&gt;
      break;&lt;br /&gt;
    a += PGSIZE;&lt;br /&gt;
    pa += PGSIZE;&lt;br /&gt;
  }&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// There is one page table per process, plus one that's used when&lt;br /&gt;
// a CPU is not running any process (kpgdir). The kernel uses the&lt;br /&gt;
// current process's page table during system calls and interrupts;&lt;br /&gt;
// page protection bits prevent user code from using the kernel's&lt;br /&gt;
// mappings.&lt;br /&gt;
// &lt;br /&gt;
// setupkvm() and exec() set up every page table like this:&lt;br /&gt;
//&lt;br /&gt;
//   0..KERNBASE: user memory (text+data+stack+heap), mapped to&lt;br /&gt;
//                phys memory allocated by the kernel&lt;br /&gt;
//   KERNBASE..KERNBASE+EXTMEM: mapped to 0..EXTMEM (for I/O space)&lt;br /&gt;
//   KERNBASE+EXTMEM..data: mapped to EXTMEM..V2P(data)&lt;br /&gt;
//                for the kernel's instructions and r/o data&lt;br /&gt;
//   data..KERNBASE+PHYSTOP: mapped to V2P(data)..PHYSTOP, &lt;br /&gt;
//                                  rw data + free physical memory&lt;br /&gt;
//   0xfe000000..0: mapped direct (devices such as ioapic)&lt;br /&gt;
//&lt;br /&gt;
// The kernel allocates physical memory for its heap and for user memory&lt;br /&gt;
// between V2P(end) and the end of physical memory (PHYSTOP)&lt;br /&gt;
// (directly addressable from end..P2V(PHYSTOP)).&lt;br /&gt;
&lt;br /&gt;
// This table defines the kernel's mappings, which are present in&lt;br /&gt;
// every process's page table.&lt;br /&gt;
static struct kmap {&lt;br /&gt;
  void *virt;&lt;br /&gt;
  uint phys_start;&lt;br /&gt;
  uint phys_end;&lt;br /&gt;
  int perm;&lt;br /&gt;
} kmap[] = {&lt;br /&gt;
 { (void*)KERNBASE, 0,             EXTMEM,    PTE_W}, // I/O space&lt;br /&gt;
 { (void*)KERNLINK, V2P(KERNLINK), V2P(data), 0},     // kern text+rodata&lt;br /&gt;
 { (void*)data,     V2P(data),     PHYSTOP,   PTE_W}, // kern data+memory&lt;br /&gt;
 { (void*)DEVSPACE, DEVSPACE,      0,         PTE_W}, // more devices&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// Set up kernel part of a page table.&lt;br /&gt;
pde_t*&lt;br /&gt;
setupkvm(void)&lt;br /&gt;
{&lt;br /&gt;
  pde_t *pgdir;&lt;br /&gt;
  struct kmap *k;&lt;br /&gt;
&lt;br /&gt;
  if((pgdir = (pde_t*)kalloc()) == 0)&lt;br /&gt;
    return 0;&lt;br /&gt;
  memset(pgdir, 0, PGSIZE);&lt;br /&gt;
  if (p2v(PHYSTOP) &amp;gt; (void*)DEVSPACE)&lt;br /&gt;
    panic(&amp;quot;PHYSTOP too high&amp;quot;);&lt;br /&gt;
  for(k = kmap; k &amp;lt; &amp;amp;kmap[NELEM(kmap)]; k++)&lt;br /&gt;
    if(mappages(pgdir, k-&amp;gt;virt, k-&amp;gt;phys_end - k-&amp;gt;phys_start, &lt;br /&gt;
                (uint)k-&amp;gt;phys_start, k-&amp;gt;perm) &amp;lt; 0)&lt;br /&gt;
      return 0;&lt;br /&gt;
  return pgdir;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Allocate one page table for the machine for the kernel address&lt;br /&gt;
// space for scheduler processes.&lt;br /&gt;
void&lt;br /&gt;
kvmalloc(void)&lt;br /&gt;
{&lt;br /&gt;
  kpgdir = setupkvm();&lt;br /&gt;
  switchkvm();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Switch h/w page table register to the kernel-only page table,&lt;br /&gt;
// for when no process is running.&lt;br /&gt;
void&lt;br /&gt;
switchkvm(void)&lt;br /&gt;
{&lt;br /&gt;
  lcr3(v2p(kpgdir));   // switch to the kernel page table&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Switch TSS and h/w page table to correspond to process p.&lt;br /&gt;
void&lt;br /&gt;
switchuvm(struct proc *p)&lt;br /&gt;
{&lt;br /&gt;
  pushcli();&lt;br /&gt;
  cpu-&amp;gt;gdt[SEG_TSS] = SEG16(STS_T32A, &amp;amp;cpu-&amp;gt;ts, sizeof(cpu-&amp;gt;ts)-1, 0);&lt;br /&gt;
  cpu-&amp;gt;gdt[SEG_TSS].s = 0;&lt;br /&gt;
  cpu-&amp;gt;ts.ss0 = SEG_KDATA &amp;lt;&amp;lt; 3;&lt;br /&gt;
  cpu-&amp;gt;ts.esp0 = (uint)proc-&amp;gt;kstack + KSTACKSIZE;&lt;br /&gt;
  ltr(SEG_TSS &amp;lt;&amp;lt; 3);&lt;br /&gt;
  if(p-&amp;gt;pgdir == 0)&lt;br /&gt;
    panic(&amp;quot;switchuvm: no pgdir&amp;quot;);&lt;br /&gt;
  lcr3(v2p(p-&amp;gt;pgdir));  // switch to new address space&lt;br /&gt;
  popcli();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Load the initcode into address 0 of pgdir.&lt;br /&gt;
// sz must be less than a page.&lt;br /&gt;
void&lt;br /&gt;
inituvm(pde_t *pgdir, char *init, uint sz)&lt;br /&gt;
{&lt;br /&gt;
  char *mem;&lt;br /&gt;
  &lt;br /&gt;
  if(sz &amp;gt;= PGSIZE)&lt;br /&gt;
    panic(&amp;quot;inituvm: more than a page&amp;quot;);&lt;br /&gt;
  mem = kalloc();&lt;br /&gt;
  memset(mem, 0, PGSIZE);&lt;br /&gt;
  mappages(pgdir, 0, PGSIZE, v2p(mem), PTE_W|PTE_U);&lt;br /&gt;
  memmove(mem, init, sz);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Load a program segment into pgdir.  addr must be page-aligned&lt;br /&gt;
// and the pages from addr to addr+sz must already be mapped.&lt;br /&gt;
int&lt;br /&gt;
loaduvm(pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz)&lt;br /&gt;
{&lt;br /&gt;
  uint i, pa, n;&lt;br /&gt;
  pte_t *pte;&lt;br /&gt;
&lt;br /&gt;
  if((uint) addr % PGSIZE != 0)&lt;br /&gt;
    panic(&amp;quot;loaduvm: addr must be page aligned&amp;quot;);&lt;br /&gt;
  for(i = 0; i &amp;lt; sz; i += PGSIZE){&lt;br /&gt;
    if((pte = walkpgdir(pgdir, addr+i, 0)) == 0)&lt;br /&gt;
      panic(&amp;quot;loaduvm: address should exist&amp;quot;);&lt;br /&gt;
    pa = PTE_ADDR(*pte);&lt;br /&gt;
    if(sz - i &amp;lt; PGSIZE)&lt;br /&gt;
      n = sz - i;&lt;br /&gt;
    else&lt;br /&gt;
      n = PGSIZE;&lt;br /&gt;
    if(readi(ip, p2v(pa), offset+i, n) != n)&lt;br /&gt;
      return -1;&lt;br /&gt;
  }&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Allocate page tables and physical memory to grow process from oldsz to&lt;br /&gt;
// newsz, which need not be page aligned.  Returns new size or 0 on error.&lt;br /&gt;
int&lt;br /&gt;
allocuvm(pde_t *pgdir, uint oldsz, uint newsz)&lt;br /&gt;
{&lt;br /&gt;
  char *mem;&lt;br /&gt;
  uint a;&lt;br /&gt;
&lt;br /&gt;
  if(newsz &amp;gt;= KERNBASE)&lt;br /&gt;
    return 0;&lt;br /&gt;
  if(newsz &amp;lt; oldsz)&lt;br /&gt;
    return oldsz;&lt;br /&gt;
&lt;br /&gt;
  a = PGROUNDUP(oldsz);&lt;br /&gt;
  for(; a &amp;lt; newsz; a += PGSIZE){&lt;br /&gt;
    mem = kalloc();&lt;br /&gt;
    if(mem == 0){&lt;br /&gt;
      cprintf(&amp;quot;allocuvm out of memory\n&amp;quot;);&lt;br /&gt;
      deallocuvm(pgdir, newsz, oldsz);&lt;br /&gt;
      return 0;&lt;br /&gt;
    }&lt;br /&gt;
    memset(mem, 0, PGSIZE);&lt;br /&gt;
    mappages(pgdir, (char*)a, PGSIZE, v2p(mem), PTE_W|PTE_U);&lt;br /&gt;
  }&lt;br /&gt;
  return newsz;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Deallocate user pages to bring the process size from oldsz to&lt;br /&gt;
// newsz.  oldsz and newsz need not be page-aligned, nor does newsz&lt;br /&gt;
// need to be less than oldsz.  oldsz can be larger than the actual&lt;br /&gt;
// process size.  Returns the new process size.&lt;br /&gt;
int&lt;br /&gt;
deallocuvm(pde_t *pgdir, uint oldsz, uint newsz)&lt;br /&gt;
{&lt;br /&gt;
  pte_t *pte;&lt;br /&gt;
  uint a, pa;&lt;br /&gt;
&lt;br /&gt;
  if(newsz &amp;gt;= oldsz)&lt;br /&gt;
    return oldsz;&lt;br /&gt;
&lt;br /&gt;
  a = PGROUNDUP(newsz);&lt;br /&gt;
  for(; a  &amp;lt; oldsz; a += PGSIZE){&lt;br /&gt;
    pte = walkpgdir(pgdir, (char*)a, 0);&lt;br /&gt;
    if(!pte)&lt;br /&gt;
      a += (NPTENTRIES - 1) * PGSIZE;&lt;br /&gt;
    else if((*pte &amp;amp; PTE_P) != 0){&lt;br /&gt;
      pa = PTE_ADDR(*pte);&lt;br /&gt;
      if(pa == 0)&lt;br /&gt;
        panic(&amp;quot;kfree&amp;quot;);&lt;br /&gt;
      char *v = p2v(pa);&lt;br /&gt;
      kfree(v);&lt;br /&gt;
      *pte = 0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return newsz;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Free a page table and all the physical memory pages&lt;br /&gt;
// in the user part.&lt;br /&gt;
void&lt;br /&gt;
freevm(pde_t *pgdir)&lt;br /&gt;
{&lt;br /&gt;
  uint i;&lt;br /&gt;
&lt;br /&gt;
  if(pgdir == 0)&lt;br /&gt;
    panic(&amp;quot;freevm: no pgdir&amp;quot;);&lt;br /&gt;
  deallocuvm(pgdir, KERNBASE, 0);&lt;br /&gt;
  for(i = 0; i &amp;lt; NPDENTRIES; i++){&lt;br /&gt;
    if(pgdir[i] &amp;amp; PTE_P){&lt;br /&gt;
      char * v = p2v(PTE_ADDR(pgdir[i]));&lt;br /&gt;
      kfree(v);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  kfree((char*)pgdir);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Clear PTE_U on a page. Used to create an inaccessible&lt;br /&gt;
// page beneath the user stack.&lt;br /&gt;
void&lt;br /&gt;
clearpteu(pde_t *pgdir, char *uva)&lt;br /&gt;
{&lt;br /&gt;
  pte_t *pte;&lt;br /&gt;
&lt;br /&gt;
  pte = walkpgdir(pgdir, uva, 0);&lt;br /&gt;
  if(pte == 0)&lt;br /&gt;
    panic(&amp;quot;clearpteu&amp;quot;);&lt;br /&gt;
  *pte &amp;amp;= ~PTE_U;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Given a parent process's page table, create a copy&lt;br /&gt;
// of it for a child.&lt;br /&gt;
pde_t*&lt;br /&gt;
copyuvm(pde_t *pgdir, uint sz)&lt;br /&gt;
{&lt;br /&gt;
  pde_t *d;&lt;br /&gt;
  pte_t *pte;&lt;br /&gt;
  uint pa, i, flags;&lt;br /&gt;
  char *mem;&lt;br /&gt;
&lt;br /&gt;
  if((d = setupkvm()) == 0)&lt;br /&gt;
    return 0;&lt;br /&gt;
  for(i = 0; i &amp;lt; sz; i += PGSIZE){&lt;br /&gt;
    if((pte = walkpgdir(pgdir, (void *) i, 0)) == 0)&lt;br /&gt;
      panic(&amp;quot;copyuvm: pte should exist&amp;quot;);&lt;br /&gt;
    if(!(*pte &amp;amp; PTE_P))&lt;br /&gt;
      panic(&amp;quot;copyuvm: page not present&amp;quot;);&lt;br /&gt;
    pa = PTE_ADDR(*pte);&lt;br /&gt;
    flags = PTE_FLAGS(*pte);&lt;br /&gt;
    if((mem = kalloc()) == 0)&lt;br /&gt;
      goto bad;&lt;br /&gt;
    memmove(mem, (char*)p2v(pa), PGSIZE);&lt;br /&gt;
    if(mappages(d, (void*)i, PGSIZE, v2p(mem), flags) &amp;lt; 0)&lt;br /&gt;
      goto bad;&lt;br /&gt;
  }&lt;br /&gt;
  return d;&lt;br /&gt;
&lt;br /&gt;
bad:&lt;br /&gt;
  freevm(d);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//PAGEBREAK!&lt;br /&gt;
// Map user virtual address to kernel address.&lt;br /&gt;
char*&lt;br /&gt;
uva2ka(pde_t *pgdir, char *uva)&lt;br /&gt;
{&lt;br /&gt;
  pte_t *pte;&lt;br /&gt;
&lt;br /&gt;
  pte = walkpgdir(pgdir, uva, 0);&lt;br /&gt;
  if((*pte &amp;amp; PTE_P) == 0)&lt;br /&gt;
    return 0;&lt;br /&gt;
  if((*pte &amp;amp; PTE_U) == 0)&lt;br /&gt;
    return 0;&lt;br /&gt;
  return (char*)p2v(PTE_ADDR(*pte));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Copy len bytes from p to user address va in page table pgdir.&lt;br /&gt;
// Most useful when pgdir is not the current page table.&lt;br /&gt;
// uva2ka ensures this only works for PTE_U pages.&lt;br /&gt;
int&lt;br /&gt;
copyout(pde_t *pgdir, uint va, void *p, uint len)&lt;br /&gt;
{&lt;br /&gt;
  char *buf, *pa0;&lt;br /&gt;
  uint n, va0;&lt;br /&gt;
&lt;br /&gt;
  buf = (char*)p;&lt;br /&gt;
  while(len &amp;gt; 0){&lt;br /&gt;
    va0 = (uint)PGROUNDDOWN(va);&lt;br /&gt;
    pa0 = uva2ka(pgdir, (char*)va0);&lt;br /&gt;
    if(pa0 == 0)&lt;br /&gt;
      return -1;&lt;br /&gt;
    n = PGSIZE - (va - va0);&lt;br /&gt;
    if(n &amp;gt; len)&lt;br /&gt;
      n = len;&lt;br /&gt;
    memmove(pa0 + (va - va0), buf, n);&lt;br /&gt;
    len -= n;&lt;br /&gt;
    buf += n;&lt;br /&gt;
    va = va0 + PGSIZE;&lt;br /&gt;
  }&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//PAGEBREAK!&lt;br /&gt;
// Blank page.&lt;br /&gt;
//PAGEBREAK!&lt;br /&gt;
// Blank page.&lt;br /&gt;
//PAGEBREAK!&lt;br /&gt;
// Blank page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Archivo '''''mmu.h''''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// This file contains definitions for the &lt;br /&gt;
// x86 memory management unit (MMU).&lt;br /&gt;
&lt;br /&gt;
// Eflags register&lt;br /&gt;
#define FL_CF           0x00000001      // Carry Flag&lt;br /&gt;
#define FL_PF           0x00000004      // Parity Flag&lt;br /&gt;
#define FL_AF           0x00000010      // Auxiliary carry Flag&lt;br /&gt;
#define FL_ZF           0x00000040      // Zero Flag&lt;br /&gt;
#define FL_SF           0x00000080      // Sign Flag&lt;br /&gt;
#define FL_TF           0x00000100      // Trap Flag&lt;br /&gt;
#define FL_IF           0x00000200      // Interrupt Enable&lt;br /&gt;
#define FL_DF           0x00000400      // Direction Flag&lt;br /&gt;
#define FL_OF           0x00000800      // Overflow Flag&lt;br /&gt;
#define FL_IOPL_MASK    0x00003000      // I/O Privilege Level bitmask&lt;br /&gt;
#define FL_IOPL_0       0x00000000      //   IOPL == 0&lt;br /&gt;
#define FL_IOPL_1       0x00001000      //   IOPL == 1&lt;br /&gt;
#define FL_IOPL_2       0x00002000      //   IOPL == 2&lt;br /&gt;
#define FL_IOPL_3       0x00003000      //   IOPL == 3&lt;br /&gt;
#define FL_NT           0x00004000      // Nested Task&lt;br /&gt;
#define FL_RF           0x00010000      // Resume Flag&lt;br /&gt;
#define FL_VM           0x00020000      // Virtual 8086 mode&lt;br /&gt;
#define FL_AC           0x00040000      // Alignment Check&lt;br /&gt;
#define FL_VIF          0x00080000      // Virtual Interrupt Flag&lt;br /&gt;
#define FL_VIP          0x00100000      // Virtual Interrupt Pending&lt;br /&gt;
#define FL_ID           0x00200000      // ID flag&lt;br /&gt;
&lt;br /&gt;
// Control Register flags&lt;br /&gt;
#define CR0_PE          0x00000001      // Protection Enable&lt;br /&gt;
#define CR0_MP          0x00000002      // Monitor coProcessor&lt;br /&gt;
#define CR0_EM          0x00000004      // Emulation&lt;br /&gt;
#define CR0_TS          0x00000008      // Task Switched&lt;br /&gt;
#define CR0_ET          0x00000010      // Extension Type&lt;br /&gt;
#define CR0_NE          0x00000020      // Numeric Errror&lt;br /&gt;
#define CR0_WP          0x00010000      // Write Protect&lt;br /&gt;
#define CR0_AM          0x00040000      // Alignment Mask&lt;br /&gt;
#define CR0_NW          0x20000000      // Not Writethrough&lt;br /&gt;
#define CR0_CD          0x40000000      // Cache Disable&lt;br /&gt;
#define CR0_PG          0x80000000      // Paging&lt;br /&gt;
&lt;br /&gt;
#define CR4_PSE         0x00000010      // Page size extension&lt;br /&gt;
&lt;br /&gt;
#define SEG_KCODE 1  // kernel code&lt;br /&gt;
#define SEG_KDATA 2  // kernel data+stack&lt;br /&gt;
#define SEG_KCPU  3  // kernel per-cpu data&lt;br /&gt;
#define SEG_UCODE 4  // user code&lt;br /&gt;
#define SEG_UDATA 5  // user data+stack&lt;br /&gt;
#define SEG_TSS   6  // this process's task state&lt;br /&gt;
&lt;br /&gt;
//PAGEBREAK!&lt;br /&gt;
#ifndef __ASSEMBLER__&lt;br /&gt;
// Segment Descriptor&lt;br /&gt;
struct segdesc {&lt;br /&gt;
  uint lim_15_0 : 16;  // Low bits of segment limit&lt;br /&gt;
  uint base_15_0 : 16; // Low bits of segment base address&lt;br /&gt;
  uint base_23_16 : 8; // Middle bits of segment base address&lt;br /&gt;
  uint type : 4;       // Segment type (see STS_ constants)&lt;br /&gt;
  uint s : 1;          // 0 = system, 1 = application&lt;br /&gt;
  uint dpl : 2;        // Descriptor Privilege Level&lt;br /&gt;
  uint p : 1;          // Present&lt;br /&gt;
  uint lim_19_16 : 4;  // High bits of segment limit&lt;br /&gt;
  uint avl : 1;        // Unused (available for software use)&lt;br /&gt;
  uint rsv1 : 1;       // Reserved&lt;br /&gt;
  uint db : 1;         // 0 = 16-bit segment, 1 = 32-bit segment&lt;br /&gt;
  uint g : 1;          // Granularity: limit scaled by 4K when set&lt;br /&gt;
  uint base_31_24 : 8; // High bits of segment base address&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// Normal segment&lt;br /&gt;
#define SEG(type, base, lim, dpl) (struct segdesc)    \&lt;br /&gt;
{ ((lim) &amp;gt;&amp;gt; 12) &amp;amp; 0xffff, (uint)(base) &amp;amp; 0xffff,      \&lt;br /&gt;
  ((uint)(base) &amp;gt;&amp;gt; 16) &amp;amp; 0xff, type, 1, dpl, 1,       \&lt;br /&gt;
  (uint)(lim) &amp;gt;&amp;gt; 28, 0, 0, 1, 1, (uint)(base) &amp;gt;&amp;gt; 24 }&lt;br /&gt;
#define SEG16(type, base, lim, dpl) (struct segdesc)  \&lt;br /&gt;
{ (lim) &amp;amp; 0xffff, (uint)(base) &amp;amp; 0xffff,              \&lt;br /&gt;
  ((uint)(base) &amp;gt;&amp;gt; 16) &amp;amp; 0xff, type, 1, dpl, 1,       \&lt;br /&gt;
  (uint)(lim) &amp;gt;&amp;gt; 16, 0, 0, 1, 0, (uint)(base) &amp;gt;&amp;gt; 24 }&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define DPL_USER    0x3     // User DPL&lt;br /&gt;
&lt;br /&gt;
// Application segment type bits&lt;br /&gt;
#define STA_X       0x8     // Executable segment&lt;br /&gt;
#define STA_E       0x4     // Expand down (non-executable segments)&lt;br /&gt;
#define STA_C       0x4     // Conforming code segment (executable only)&lt;br /&gt;
#define STA_W       0x2     // Writeable (non-executable segments)&lt;br /&gt;
#define STA_R       0x2     // Readable (executable segments)&lt;br /&gt;
#define STA_A       0x1     // Accessed&lt;br /&gt;
&lt;br /&gt;
// System segment type bits&lt;br /&gt;
#define STS_T16A    0x1     // Available 16-bit TSS&lt;br /&gt;
#define STS_LDT     0x2     // Local Descriptor Table&lt;br /&gt;
#define STS_T16B    0x3     // Busy 16-bit TSS&lt;br /&gt;
#define STS_CG16    0x4     // 16-bit Call Gate&lt;br /&gt;
#define STS_TG      0x5     // Task Gate / Coum Transmitions&lt;br /&gt;
#define STS_IG16    0x6     // 16-bit Interrupt Gate&lt;br /&gt;
#define STS_TG16    0x7     // 16-bit Trap Gate&lt;br /&gt;
#define STS_T32A    0x9     // Available 32-bit TSS&lt;br /&gt;
#define STS_T32B    0xB     // Busy 32-bit TSS&lt;br /&gt;
#define STS_CG32    0xC     // 32-bit Call Gate&lt;br /&gt;
#define STS_IG32    0xE     // 32-bit Interrupt Gate&lt;br /&gt;
#define STS_TG32    0xF     // 32-bit Trap Gate&lt;br /&gt;
&lt;br /&gt;
// A virtual address 'la' has a three-part structure as follows:&lt;br /&gt;
//&lt;br /&gt;
// +--------10------+-------10-------+---------12----------+&lt;br /&gt;
// | Page Directory |   Page Table   | Offset within Page  |&lt;br /&gt;
// |      Index     |      Index     |                     |&lt;br /&gt;
// +----------------+----------------+---------------------+&lt;br /&gt;
//  \--- PDX(va) --/ \--- PTX(va) --/ &lt;br /&gt;
&lt;br /&gt;
// page directory index&lt;br /&gt;
#define PDX(va)         (((uint)(va) &amp;gt;&amp;gt; PDXSHIFT) &amp;amp; 0x3FF)&lt;br /&gt;
&lt;br /&gt;
// page table index&lt;br /&gt;
#define PTX(va)         (((uint)(va) &amp;gt;&amp;gt; PTXSHIFT) &amp;amp; 0x3FF)&lt;br /&gt;
&lt;br /&gt;
// construct virtual address from indexes and offset&lt;br /&gt;
#define PGADDR(d, t, o) ((uint)((d) &amp;lt;&amp;lt; PDXSHIFT | (t) &amp;lt;&amp;lt; PTXSHIFT | (o)))&lt;br /&gt;
&lt;br /&gt;
// Page directory and page table constants.&lt;br /&gt;
#define NPDENTRIES      1024    // # directory entries per page directory&lt;br /&gt;
#define NPTENTRIES      1024    // # PTEs per page table&lt;br /&gt;
#define PGSIZE          4096    // bytes mapped by a page&lt;br /&gt;
&lt;br /&gt;
#define PGSHIFT         12      // log2(PGSIZE)&lt;br /&gt;
#define PTXSHIFT        12      // offset of PTX in a linear address&lt;br /&gt;
#define PDXSHIFT        22      // offset of PDX in a linear address&lt;br /&gt;
&lt;br /&gt;
#define PGROUNDUP(sz)  (((sz)+PGSIZE-1) &amp;amp; ~(PGSIZE-1))&lt;br /&gt;
#define PGROUNDDOWN(a) (((a)) &amp;amp; ~(PGSIZE-1))&lt;br /&gt;
&lt;br /&gt;
// Page table/directory entry flags.&lt;br /&gt;
#define PTE_P           0x001   // Present&lt;br /&gt;
#define PTE_W           0x002   // Writeable&lt;br /&gt;
#define PTE_U           0x004   // User&lt;br /&gt;
#define PTE_PWT         0x008   // Write-Through&lt;br /&gt;
#define PTE_PCD         0x010   // Cache-Disable&lt;br /&gt;
#define PTE_A           0x020   // Accessed&lt;br /&gt;
#define PTE_D           0x040   // Dirty&lt;br /&gt;
#define PTE_PS          0x080   // Page Size&lt;br /&gt;
#define PTE_MBZ         0x180   // Bits must be zero&lt;br /&gt;
&lt;br /&gt;
// Address in page table or page directory entry&lt;br /&gt;
#define PTE_ADDR(pte)   ((uint)(pte) &amp;amp; ~0xFFF)&lt;br /&gt;
#define PTE_FLAGS(pte)  ((uint)(pte) &amp;amp;  0xFFF)&lt;br /&gt;
&lt;br /&gt;
#ifndef __ASSEMBLER__&lt;br /&gt;
typedef uint pte_t;&lt;br /&gt;
&lt;br /&gt;
// Task state segment format&lt;br /&gt;
struct taskstate {&lt;br /&gt;
  uint link;         // Old ts selector&lt;br /&gt;
  uint esp0;         // Stack pointers and segment selectors&lt;br /&gt;
  ushort ss0;        //   after an increase in privilege level&lt;br /&gt;
  ushort padding1;&lt;br /&gt;
  uint *esp1;&lt;br /&gt;
  ushort ss1;&lt;br /&gt;
  ushort padding2;&lt;br /&gt;
  uint *esp2;&lt;br /&gt;
  ushort ss2;&lt;br /&gt;
  ushort padding3;&lt;br /&gt;
  void *cr3;         // Page directory base&lt;br /&gt;
  uint *eip;         // Saved state from last task switch&lt;br /&gt;
  uint eflags;&lt;br /&gt;
  uint eax;          // More saved state (registers)&lt;br /&gt;
  uint ecx;&lt;br /&gt;
  uint edx;&lt;br /&gt;
  uint ebx;&lt;br /&gt;
  uint *esp;&lt;br /&gt;
  uint *ebp;&lt;br /&gt;
  uint esi;&lt;br /&gt;
  uint edi;&lt;br /&gt;
  ushort es;         // Even more saved state (segment selectors)&lt;br /&gt;
  ushort padding4;&lt;br /&gt;
  ushort cs;&lt;br /&gt;
  ushort padding5;&lt;br /&gt;
  ushort ss;&lt;br /&gt;
  ushort padding6;&lt;br /&gt;
  ushort ds;&lt;br /&gt;
  ushort padding7;&lt;br /&gt;
  ushort fs;&lt;br /&gt;
  ushort padding8;&lt;br /&gt;
  ushort gs;&lt;br /&gt;
  ushort padding9;&lt;br /&gt;
  ushort ldt;&lt;br /&gt;
  ushort padding10;&lt;br /&gt;
  ushort t;          // Trap on task switch&lt;br /&gt;
  ushort iomb;       // I/O map base address&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// PAGEBREAK: 12&lt;br /&gt;
// Gate descriptors for interrupts and traps&lt;br /&gt;
struct gatedesc {&lt;br /&gt;
  uint off_15_0 : 16;   // low 16 bits of offset in segment&lt;br /&gt;
  uint cs : 16;         // code segment selector&lt;br /&gt;
  uint args : 5;        // # args, 0 for interrupt/trap gates&lt;br /&gt;
  uint rsv1 : 3;        // reserved(should be zero I guess)&lt;br /&gt;
  uint type : 4;        // type(STS_{TG,IG32,TG32})&lt;br /&gt;
  uint s : 1;           // must be 0 (system)&lt;br /&gt;
  uint dpl : 2;         // descriptor(meaning new) privilege level&lt;br /&gt;
  uint p : 1;           // Present&lt;br /&gt;
  uint off_31_16 : 16;  // high bits of offset in segment&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// Set up a normal interrupt/trap gate descriptor.&lt;br /&gt;
// - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate.&lt;br /&gt;
//   interrupt gate clears FL_IF, trap gate leaves FL_IF alone&lt;br /&gt;
// - sel: Code segment selector for interrupt/trap handler&lt;br /&gt;
// - off: Offset in code segment for interrupt/trap handler&lt;br /&gt;
// - dpl: Descriptor Privilege Level -&lt;br /&gt;
//        the privilege level required for software to invoke&lt;br /&gt;
//        this interrupt/trap gate explicitly using an int instruction.&lt;br /&gt;
#define SETGATE(gate, istrap, sel, off, d)                \&lt;br /&gt;
{                                                         \&lt;br /&gt;
  (gate).off_15_0 = (uint)(off) &amp;amp; 0xffff;                \&lt;br /&gt;
  (gate).cs = (sel);                                      \&lt;br /&gt;
  (gate).args = 0;                                        \&lt;br /&gt;
  (gate).rsv1 = 0;                                        \&lt;br /&gt;
  (gate).type = (istrap) ? STS_TG32 : STS_IG32;           \&lt;br /&gt;
  (gate).s = 0;                                           \&lt;br /&gt;
  (gate).dpl = (d);                                       \&lt;br /&gt;
  (gate).p = 1;                                           \&lt;br /&gt;
  (gate).off_31_16 = (uint)(off) &amp;gt;&amp;gt; 16;                  \&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Analisis = &lt;br /&gt;
&lt;br /&gt;
Aunque solo se muestran dos archivos, el proceso de manejo de memoria es mas complejo, hay muchos mas archivos y métodos que forman parte de esto. Si se quiere indagar mas a fondo lo ideal es fijarse en los archivos que son llamados en ''vm.c'' por ejemplo, y ver que métodos de estos archivos estan siendo utilizados. Para consultar estos archivos dirigete a la sección de ''Descarga e instalación de XV6''&lt;/div&gt;</summary>
		<author><name>Alemarmar5</name></author>	</entry>

	</feed>