 48e74378c7
			
		
	
	
		48e74378c7
		
	
	
	
	
		
			
			. so that memory of such regions can be deallocated in any order Change-Id: I34013d6085cf19a482412cf9bed6b7f96e60e1e6
		
			
				
	
	
		
			133 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
 | |
| /* This file implements the methods of physically contiguous anonymous memory. */
 | |
| 
 | |
| #include <assert.h>
 | |
| 
 | |
| #include "proto.h"
 | |
| #include "vm.h"
 | |
| #include "region.h"
 | |
| #include "glo.h"
 | |
| 
 | |
| static int anon_contig_reference(struct phys_region *, struct phys_region *);
 | |
| static int anon_contig_unreference(struct phys_region *pr);
 | |
| static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region, 
 | |
| 	struct phys_region *ph, int write, vfs_callback_t cb, void *state,
 | |
| 	int len, int *io);
 | |
| static int anon_contig_sanitycheck(struct phys_region *pr, const char *file, int line);
 | |
| static int anon_contig_writable(struct phys_region *pr);
 | |
| static void anon_contig_split(struct vmproc *vmp, struct vir_region *vr,
 | |
|                         struct vir_region *r1, struct vir_region *r2);
 | |
| static int anon_contig_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l);
 | |
| static int anon_contig_new(struct vir_region *vr);
 | |
| static int anon_contig_pt_flags(struct vir_region *vr);
 | |
| 
 | |
| struct mem_type mem_type_anon_contig = {
 | |
| 	.name = "anonymous memory (physically contiguous)",
 | |
| 	.ev_new = anon_contig_new,
 | |
| 	.ev_reference = anon_contig_reference,
 | |
| 	.ev_unreference = anon_contig_unreference,
 | |
| 	.ev_pagefault = anon_contig_pagefault,
 | |
| 	.ev_resize = anon_contig_resize,
 | |
| 	.ev_split = anon_contig_split,
 | |
| 	.ev_sanitycheck = anon_contig_sanitycheck,
 | |
| 	.writable = anon_contig_writable,
 | |
| 	.pt_flags = anon_contig_pt_flags,
 | |
| };
 | |
| 
 | |
| static int anon_contig_pt_flags(struct vir_region *vr){
 | |
| #if defined(__arm__)
 | |
| 	return  ARM_VM_PTE_DEVICE;
 | |
| #else
 | |
| 	return  0;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region,
 | |
| 	struct phys_region *ph, int write, vfs_callback_t cb, void *state,
 | |
| 	int len, int *io)
 | |
| {
 | |
| 	panic("anon_contig_pagefault: pagefault cannot happen");
 | |
| }
 | |
| 
 | |
| static int anon_contig_new(struct vir_region *region)
 | |
| {
 | |
|         u32_t allocflags;
 | |
| 	phys_bytes new_pages, new_page_cl, cur_ph;
 | |
| 	phys_bytes p, pages;
 | |
| 
 | |
|         allocflags = vrallocflags(region->flags);
 | |
| 
 | |
| 	pages = region->length/VM_PAGE_SIZE;
 | |
| 
 | |
| 	assert(physregions(region) == 0);
 | |
| 
 | |
| 	for(p = 0; p < pages; p++) {
 | |
| 		struct phys_block *pb = pb_new(MAP_NONE);
 | |
| 		struct phys_region *pr = NULL;
 | |
| 		if(pb)
 | |
| 			pr = pb_reference(pb, p * VM_PAGE_SIZE, region, &mem_type_anon_contig);
 | |
| 		if(!pr) {
 | |
| 			if(pb) pb_free(pb);
 | |
| 			map_free(region);
 | |
| 			return ENOMEM;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	assert(physregions(region) == pages);
 | |
| 
 | |
| 	if((new_page_cl = alloc_mem(pages, allocflags)) == NO_MEM) {
 | |
| 		map_free(region);
 | |
| 		return ENOMEM;
 | |
| 	}
 | |
| 
 | |
| 	cur_ph = new_pages = CLICK2ABS(new_page_cl);
 | |
| 
 | |
| 	for(p = 0; p < pages; p++) {
 | |
| 		struct phys_region *pr = physblock_get(region, p * VM_PAGE_SIZE);
 | |
| 		assert(pr);
 | |
| 		assert(pr->ph);
 | |
| 		assert(pr->ph->phys == MAP_NONE);
 | |
| 		assert(pr->offset == p * VM_PAGE_SIZE);
 | |
| 		pr->ph->phys = cur_ph + pr->offset;
 | |
| 	}
 | |
| 
 | |
| 	return OK;
 | |
| }
 | |
| 
 | |
| static int anon_contig_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l)
 | |
| {
 | |
| 	printf("VM: cannot resize physically contiguous memory.\n");
 | |
| 	return ENOMEM;
 | |
| }
 | |
| 
 | |
| static int anon_contig_reference(struct phys_region *pr,
 | |
| 	struct phys_region *newpr)
 | |
| {
 | |
| 	printf("VM: cannot fork with physically contig memory.\n");
 | |
| 	return ENOMEM;
 | |
| }
 | |
| 
 | |
| /* Methods inherited from the anonymous memory methods. */
 | |
| 
 | |
| static int anon_contig_unreference(struct phys_region *pr)
 | |
| {
 | |
| 	return mem_type_anon.ev_unreference(pr);
 | |
| }
 | |
| 
 | |
| static int anon_contig_sanitycheck(struct phys_region *pr, const char *file, int line)
 | |
| {
 | |
| 	return mem_type_anon.ev_sanitycheck(pr, file, line);
 | |
| }
 | |
| 
 | |
| static int anon_contig_writable(struct phys_region *pr)
 | |
| {
 | |
| 	return mem_type_anon.writable(pr);
 | |
| }
 | |
| 
 | |
| static void anon_contig_split(struct vmproc *vmp, struct vir_region *vr,
 | |
|                         struct vir_region *r1, struct vir_region *r2)
 | |
| {
 | |
| 	return;
 | |
| }
 | |
| 
 |