[9] | 1 | /* The system call implemented in this file:
|
---|
| 2 | * m_type: SYS_VM_MAP
|
---|
| 3 | *
|
---|
| 4 | * The parameters for this system call are:
|
---|
| 5 | * m4_l1: Process that requests map (VM_MAP_ENDPT)
|
---|
| 6 | * m4_l2: Map (TRUE) or unmap (FALSE) (VM_MAP_MAPUNMAP)
|
---|
| 7 | * m4_l3: Base address (VM_MAP_BASE)
|
---|
| 8 | * m4_l4: Size (VM_MAP_SIZE)
|
---|
| 9 | * m4_l5: Memory address (VM_MAP_ADDR)
|
---|
| 10 | */
|
---|
| 11 | #include "../system.h"
|
---|
| 12 |
|
---|
| 13 | #include <sys/vm.h>
|
---|
| 14 |
|
---|
| 15 | PRIVATE int vm_needs_init= 1;
|
---|
| 16 | PRIVATE u32_t vm_cr3;
|
---|
| 17 |
|
---|
| 18 | FORWARD _PROTOTYPE( void vm_init, (void) );
|
---|
| 19 | FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value) );
|
---|
| 20 | FORWARD _PROTOTYPE( u32_t phys_get32, (phys_bytes addr) );
|
---|
| 21 | FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value) );
|
---|
| 22 | FORWARD _PROTOTYPE( void set_cr3, (void) );
|
---|
| 23 | FORWARD _PROTOTYPE( void vm_enable_paging, (void) );
|
---|
| 24 | FORWARD _PROTOTYPE( void map_range, (u32_t base, u32_t size,
|
---|
| 25 | u32_t offset) );
|
---|
| 26 |
|
---|
| 27 | /*===========================================================================*
|
---|
| 28 | * do_vm_map *
|
---|
| 29 | *===========================================================================*/
|
---|
| 30 | PUBLIC int do_vm_map(m_ptr)
|
---|
| 31 | message *m_ptr; /* pointer to request message */
|
---|
| 32 | {
|
---|
| 33 | int proc_nr, do_map;
|
---|
| 34 | phys_bytes base, size, offset, p_phys;
|
---|
| 35 | struct proc *pp;
|
---|
| 36 |
|
---|
| 37 | /* do_serial_debug= 1; */
|
---|
| 38 |
|
---|
| 39 | if (vm_needs_init)
|
---|
| 40 | {
|
---|
| 41 | vm_needs_init= 0;
|
---|
| 42 | vm_init();
|
---|
| 43 | }
|
---|
| 44 |
|
---|
| 45 | if (m_ptr->VM_MAP_ENDPT == SELF) {
|
---|
| 46 | proc_nr = who_p;
|
---|
| 47 | } else {
|
---|
| 48 | if(!isokendpt(m_ptr->VM_MAP_ENDPT, &proc_nr))
|
---|
| 49 | return EINVAL;
|
---|
| 50 | }
|
---|
| 51 |
|
---|
| 52 | do_map= m_ptr->VM_MAP_MAPUNMAP;
|
---|
| 53 | base= m_ptr->VM_MAP_BASE;
|
---|
| 54 | size= m_ptr->VM_MAP_SIZE;
|
---|
| 55 | offset= m_ptr->VM_MAP_ADDR;
|
---|
| 56 |
|
---|
| 57 | pp= proc_addr(proc_nr);
|
---|
| 58 | p_phys= umap_local(pp, D, base, size);
|
---|
| 59 | if (p_phys == 0)
|
---|
| 60 | return EFAULT;
|
---|
| 61 |
|
---|
| 62 | if (do_map)
|
---|
| 63 | {
|
---|
| 64 | pp->p_misc_flags |= MF_VM;
|
---|
| 65 |
|
---|
| 66 | map_range(p_phys, size, offset);
|
---|
| 67 | }
|
---|
| 68 | else
|
---|
| 69 | {
|
---|
| 70 | map_range(p_phys, size, p_phys);
|
---|
| 71 | }
|
---|
| 72 | vm_set_cr3(vm_cr3);
|
---|
| 73 |
|
---|
| 74 | return OK;
|
---|
| 75 | }
|
---|
| 76 |
|
---|
| 77 | /*===========================================================================*
|
---|
| 78 | * vm_map_default *
|
---|
| 79 | *===========================================================================*/
|
---|
| 80 | PUBLIC void vm_map_default(pp)
|
---|
| 81 | struct proc *pp;
|
---|
| 82 | {
|
---|
| 83 | phys_bytes base_clicks, size_clicks;
|
---|
| 84 |
|
---|
| 85 | if (vm_needs_init)
|
---|
| 86 | panic("vm_map_default: VM not initialized?", NO_NUM);
|
---|
| 87 | pp->p_misc_flags &= ~MF_VM;
|
---|
| 88 | base_clicks= pp->p_memmap[D].mem_phys;
|
---|
| 89 | size_clicks= pp->p_memmap[S].mem_phys+pp->p_memmap[S].mem_len -
|
---|
| 90 | base_clicks;
|
---|
| 91 | map_range(base_clicks << CLICK_SHIFT, size_clicks << CLICK_SHIFT,
|
---|
| 92 | base_clicks << CLICK_SHIFT);
|
---|
| 93 | vm_set_cr3(vm_cr3);
|
---|
| 94 | }
|
---|
| 95 |
|
---|
| 96 | PRIVATE void vm_init(void)
|
---|
| 97 | {
|
---|
| 98 | int o;
|
---|
| 99 | phys_bytes p, pt_size;
|
---|
| 100 | phys_bytes vm_dir_base, vm_pt_base, phys_mem;
|
---|
| 101 | u32_t entry;
|
---|
| 102 | unsigned pages;
|
---|
| 103 |
|
---|
| 104 | if (!vm_size)
|
---|
| 105 | panic("vm_init: no space for page tables", NO_NUM);
|
---|
| 106 |
|
---|
| 107 | /* Align page directory */
|
---|
| 108 | o= (vm_base % PAGE_SIZE);
|
---|
| 109 | if (o != 0)
|
---|
| 110 | o= PAGE_SIZE-o;
|
---|
| 111 | vm_dir_base= vm_base+o;
|
---|
| 112 |
|
---|
| 113 | /* Page tables start after the page directory */
|
---|
| 114 | vm_pt_base= vm_dir_base+PAGE_SIZE;
|
---|
| 115 |
|
---|
| 116 | pt_size= (vm_base+vm_size)-vm_pt_base;
|
---|
| 117 | pt_size -= (pt_size % PAGE_SIZE);
|
---|
| 118 |
|
---|
| 119 | /* Compute the number of pages based on vm_mem_high */
|
---|
| 120 | pages= (vm_mem_high-1)/PAGE_SIZE + 1;
|
---|
| 121 |
|
---|
| 122 | if (pages * I386_VM_PT_ENT_SIZE > pt_size)
|
---|
| 123 | panic("vm_init: page table too small", NO_NUM);
|
---|
| 124 |
|
---|
| 125 | for (p= 0; p*I386_VM_PT_ENT_SIZE < pt_size; p++)
|
---|
| 126 | {
|
---|
| 127 | phys_mem= p*PAGE_SIZE;
|
---|
| 128 | entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
|
---|
| 129 | I386_VM_PRESENT;
|
---|
| 130 | if (phys_mem >= vm_mem_high)
|
---|
| 131 | entry= 0;
|
---|
| 132 | phys_put32(vm_pt_base + p*I386_VM_PT_ENT_SIZE, entry);
|
---|
| 133 | }
|
---|
| 134 |
|
---|
| 135 | for (p= 0; p < I386_VM_DIR_ENTRIES; p++)
|
---|
| 136 | {
|
---|
| 137 | phys_mem= vm_pt_base + p*PAGE_SIZE;
|
---|
| 138 | entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
|
---|
| 139 | I386_VM_PRESENT;
|
---|
| 140 | if (phys_mem >= vm_pt_base + pt_size)
|
---|
| 141 | entry= 0;
|
---|
| 142 | phys_put32(vm_dir_base + p*I386_VM_PT_ENT_SIZE, entry);
|
---|
| 143 | }
|
---|
| 144 | vm_set_cr3(vm_dir_base);
|
---|
| 145 | level0(vm_enable_paging);
|
---|
| 146 | }
|
---|
| 147 |
|
---|
| 148 | PRIVATE void phys_put32(addr, value)
|
---|
| 149 | phys_bytes addr;
|
---|
| 150 | u32_t value;
|
---|
| 151 | {
|
---|
| 152 | phys_copy(vir2phys((vir_bytes)&value), addr, sizeof(value));
|
---|
| 153 | }
|
---|
| 154 |
|
---|
| 155 | PRIVATE u32_t phys_get32(addr)
|
---|
| 156 | phys_bytes addr;
|
---|
| 157 | {
|
---|
| 158 | u32_t value;
|
---|
| 159 |
|
---|
| 160 | phys_copy(addr, vir2phys((vir_bytes)&value), sizeof(value));
|
---|
| 161 |
|
---|
| 162 | return value;
|
---|
| 163 | }
|
---|
| 164 |
|
---|
| 165 | PRIVATE void vm_set_cr3(value)
|
---|
| 166 | u32_t value;
|
---|
| 167 | {
|
---|
| 168 | vm_cr3= value;
|
---|
| 169 | level0(set_cr3);
|
---|
| 170 | }
|
---|
| 171 |
|
---|
| 172 | PRIVATE void set_cr3()
|
---|
| 173 | {
|
---|
| 174 | write_cr3(vm_cr3);
|
---|
| 175 | }
|
---|
| 176 |
|
---|
| 177 | PRIVATE void vm_enable_paging(void)
|
---|
| 178 | {
|
---|
| 179 | u32_t cr0;
|
---|
| 180 |
|
---|
| 181 | cr0= read_cr0();
|
---|
| 182 | write_cr0(cr0 | I386_CR0_PG);
|
---|
| 183 | }
|
---|
| 184 |
|
---|
| 185 | PRIVATE void map_range(base, size, offset)
|
---|
| 186 | u32_t base;
|
---|
| 187 | u32_t size;
|
---|
| 188 | u32_t offset;
|
---|
| 189 | {
|
---|
| 190 | u32_t curr_pt, curr_pt_addr, entry;
|
---|
| 191 | int dir_ent, pt_ent;
|
---|
| 192 |
|
---|
| 193 | if (base % PAGE_SIZE != 0)
|
---|
| 194 | panic("map_range: bad base", base);
|
---|
| 195 | if (size % PAGE_SIZE != 0)
|
---|
| 196 | panic("map_range: bad size", size);
|
---|
| 197 | if (offset % PAGE_SIZE != 0)
|
---|
| 198 | panic("map_range: bad offset", offset);
|
---|
| 199 |
|
---|
| 200 | curr_pt= -1;
|
---|
| 201 | curr_pt_addr= 0;
|
---|
| 202 | while (size != 0)
|
---|
| 203 | {
|
---|
| 204 | dir_ent= (base >> I386_VM_DIR_ENT_SHIFT);
|
---|
| 205 | pt_ent= (base >> I386_VM_PT_ENT_SHIFT) & I386_VM_PT_ENT_MASK;
|
---|
| 206 | if (dir_ent != curr_pt)
|
---|
| 207 | {
|
---|
| 208 | /* Get address of page table */
|
---|
| 209 | curr_pt= dir_ent;
|
---|
| 210 | curr_pt_addr= phys_get32(vm_cr3 +
|
---|
| 211 | dir_ent * I386_VM_PT_ENT_SIZE);
|
---|
| 212 | curr_pt_addr &= I386_VM_ADDR_MASK;
|
---|
| 213 | }
|
---|
| 214 | entry= offset | I386_VM_USER | I386_VM_WRITE |
|
---|
| 215 | I386_VM_PRESENT;
|
---|
| 216 | #if 0 /* Do we need this for memory mapped I/O? */
|
---|
| 217 | entry |= I386_VM_PCD | I386_VM_PWT;
|
---|
| 218 | #endif
|
---|
| 219 | phys_put32(curr_pt_addr + pt_ent * I386_VM_PT_ENT_SIZE, entry);
|
---|
| 220 | offset += PAGE_SIZE;
|
---|
| 221 | base += PAGE_SIZE;
|
---|
| 222 | size -= PAGE_SIZE;
|
---|
| 223 | }
|
---|
| 224 | }
|
---|