1 2 /* This file implements the methods of physically contiguous anonymous memory. */ 3 4 #include <assert.h> 5 6 #include "proto.h" 7 #include "vm.h" 8 #include "region.h" 9 #include "glo.h" 10 11 static int anon_contig_reference(struct phys_region *, struct phys_region *); 12 static int anon_contig_unreference(struct phys_region *pr); 13 static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region, 14 struct phys_region *ph, int write, vfs_callback_t cb, void *state, 15 int len, int *io); 16 static int anon_contig_sanitycheck(struct phys_region *pr, const char *file, int line); 17 static int anon_contig_writable(struct phys_region *pr); 18 static int anon_contig_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l); 19 static int anon_contig_new(struct vir_region *vr); 20 static int anon_contig_pt_flags(struct vir_region *vr); 21 22 struct mem_type mem_type_anon_contig = { 23 .name = "anonymous memory (physically contiguous)", 24 .ev_new = anon_contig_new, 25 .ev_reference = anon_contig_reference, 26 .ev_unreference = anon_contig_unreference, 27 .ev_pagefault = anon_contig_pagefault, 28 .ev_resize = anon_contig_resize, 29 .ev_sanitycheck = anon_contig_sanitycheck, 30 .writable = anon_contig_writable, 31 .pt_flags = anon_contig_pt_flags, 32 }; 33 34 static int anon_contig_pt_flags(struct vir_region *vr){ 35 #if defined(__arm__) 36 return ARM_VM_PTE_DEVICE; 37 #else 38 return 0; 39 #endif 40 } 41 42 static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region, 43 struct phys_region *ph, int write, vfs_callback_t cb, void *state, 44 int len, int *io) 45 { 46 panic("anon_contig_pagefault: pagefault cannot happen"); 47 } 48 49 static int anon_contig_new(struct vir_region *region) 50 { 51 u32_t allocflags; 52 phys_bytes new_pages, new_page_cl, cur_ph; 53 phys_bytes p, pages; 54 55 allocflags = vrallocflags(region->flags); 56 57 pages = region->length/VM_PAGE_SIZE; 58 59 assert(physregions(region) == 0); 60 61 for(p = 0; p < pages; p++) { 62 struct phys_block *pb = pb_new(MAP_NONE); 63 struct phys_region *pr = NULL; 64 if(pb) 65 pr = pb_reference(pb, p * VM_PAGE_SIZE, region, &mem_type_anon_contig); 66 if(!pr) { 67 if(pb) pb_free(pb); 68 map_free(region); 69 return ENOMEM; 70 } 71 } 72 73 assert(physregions(region) == pages); 74 75 if((new_page_cl = alloc_mem(pages, allocflags)) == NO_MEM) { 76 map_free(region); 77 return ENOMEM; 78 } 79 80 cur_ph = new_pages = CLICK2ABS(new_page_cl); 81 82 for(p = 0; p < pages; p++) { 83 struct phys_region *pr = physblock_get(region, p * VM_PAGE_SIZE); 84 assert(pr); 85 assert(pr->ph); 86 assert(pr->ph->phys == MAP_NONE); 87 assert(pr->offset == p * VM_PAGE_SIZE); 88 pr->ph->phys = cur_ph + pr->offset; 89 } 90 91 return OK; 92 } 93 94 static int anon_contig_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l) 95 { 96 printf("VM: cannot resize physically contiguous memory.\n"); 97 return ENOMEM; 98 } 99 100 static int anon_contig_reference(struct phys_region *pr, 101 struct phys_region *newpr) 102 { 103 printf("VM: cannot fork with physically contig memory.\n"); 104 return ENOMEM; 105 } 106 107 /* Methods inherited from the anonymous memory methods. */ 108 109 static int anon_contig_unreference(struct phys_region *pr) 110 { 111 return mem_type_anon.ev_unreference(pr); 112 } 113 114 static int anon_contig_sanitycheck(struct phys_region *pr, const char *file, int line) 115 { 116 return mem_type_anon.ev_sanitycheck(pr, file, line); 117 } 118 119 static int anon_contig_writable(struct phys_region *pr) 120 { 121 return mem_type_anon.writable(pr); 122 } 123 124