| /* Copyright Google, Inc. 2017 | 
 |  * Author: Zach Zimmerman | 
 |  * mmap_vmm_test: tests mmap with fd's with access from | 
 |  * vmthreads */ | 
 |  | 
 | #include <stdio.h> | 
 | #include <pthread.h> | 
 | #include <stdlib.h> | 
 | #include <unistd.h> | 
 | #include <sys/time.h> | 
 |  | 
 | #include <sys/mman.h> | 
 | #include <fcntl.h> | 
 | #include <parlib/parlib.h> | 
 | #include <parlib/timing.h> | 
 | #include <parlib/ros_debug.h> | 
 |  | 
 | #include <sys/types.h> | 
 | #include <sys/stat.h> | 
 | #include <unistd.h> | 
 |  | 
 | #include <vmm/vmm.h> | 
 | #include <vmm/vthread.h> | 
 |  | 
 | static struct virtual_machine vm = {.mtx = UTH_MUTEX_INIT}; | 
 |  | 
 | int safe_to_exit; | 
 | void *addr; | 
 | size_t nr_pgs = 1; | 
 | #define STRIDE 1 | 
 | #define NUM_ITERS 100 | 
 |  | 
 | static void mmap_testz(void) | 
 | { | 
 | 	assert(addr); | 
 | 	for (char *i = addr; (void*)i < addr + nr_pgs * PGSIZE; i += STRIDE) | 
 | 		*i = 'z'; | 
 | } | 
 |  | 
 | static void mmap_testy(void) | 
 | { | 
 | 	assert(addr); | 
 | 	for (char *i = addr; (void*)i < addr + nr_pgs * PGSIZE; i += STRIDE) | 
 | 		*i = 'y'; | 
 | } | 
 |  | 
 | void *worker_thread(void *arg) | 
 | { | 
 | 	int i; | 
 |  | 
 | 	for (i = 0; i < NUM_ITERS; ++i) | 
 | 		mmap_testy(); | 
 |  | 
 | 	safe_to_exit = true; | 
 | 	__asm__ __volatile__("hlt\n\t"); | 
 | 	return 0; | 
 | } | 
 |  | 
 | int main(void) | 
 | { | 
 | 	int fd, pid, ret; | 
 | 	char inputfile[50]; | 
 |  | 
 | 	pid = getpid(); | 
 | 	sprintf(inputfile, "/tmp/mmap-test-%d", pid); | 
 |  | 
 | 	fd = open(inputfile, O_RDWR | O_CREAT, 0666); | 
 | 	if (fd < 0) { | 
 | 		perror("Unable to open file"); | 
 | 		exit(-1); | 
 | 	} | 
 |  | 
 | 	ret = unlink(inputfile); | 
 | 	if (ret == -1) { | 
 | 		perror("UNLINK error"); | 
 | 		exit(-1); | 
 | 	} | 
 |  | 
 | 	//Increase the file size with ftruncate | 
 | 	ret = ftruncate(fd, nr_pgs * PGSIZE); | 
 | 	if (ret == -1) { | 
 | 		perror("FTRUNCATE error"); | 
 | 		exit(-1); | 
 | 	} | 
 |  | 
 | 	nr_pgs = 1; | 
 | 	void *loc = (void*) 0x1000000; | 
 |  | 
 | 	addr = mmap(loc, nr_pgs * PGSIZE, PROT_WRITE | PROT_READ | PROT_EXEC, | 
 | 		    MAP_SHARED, fd, 0); | 
 | 	if (addr == MAP_FAILED) { | 
 | 		perror("mmap failed"); | 
 | 		exit(-1); | 
 | 	} | 
 |  | 
 | 	printf("MMap got addr %p\n", addr); | 
 | 	printf("Spawning worker vmthread thread, etc...\n"); | 
 | 	vthread_create(&vm, (void*)&worker_thread, NULL); | 
 |  | 
 | 	while (!safe_to_exit) | 
 | 		cpu_relax(); | 
 |  | 
 | 	for (char *i = addr; (void*)i < addr + nr_pgs * PGSIZE; i += STRIDE) | 
 | 		assert(*i == 'y'); | 
 |  | 
 | 	printf("mmap_file_vmm: test finished, doing teardown\n"); | 
 |  | 
 | 	ret = munmap(addr, nr_pgs * PGSIZE); | 
 | 	if (ret == -1) { | 
 | 		perror("mmap_file_vmm: problem unmapping memory after test\n"); | 
 | 		exit(-1); | 
 | 	} | 
 |  | 
 | 	ret = close(fd); | 
 | 	if (ret == -1) { | 
 | 		perror("mmap_file_vmm: problem closing file after test\n"); | 
 | 		exit(-1); | 
 | 	} | 
 |  | 
 | 	printf("mmap_file_vmm: PASSED\n"); | 
 | 	return 0; | 
 | } |