struct monitor * monitor_init(void) { struct monitor *mon; int pair[2]; mon = xmalloc(sizeof(*mon)); mon->m_pid = 0; monitor_socketpair(pair); mon->m_recvfd = pair[0]; mon->m_sendfd = pair[1]; /* Used to share zlib space across processes */ if (options.compression) { mon->m_zback = mm_create(NULL, MM_MEMSIZE); mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); /* Compression needs to share state across borders */ mm_init_compression(mon->m_zlib); } return mon; }
static void check_vma_struct(void) { size_t nr_used_pages_store = nr_used_pages(); size_t slab_allocated_store = slab_allocated(); struct mm_struct *mm = mm_create(); assert(mm != NULL); int step1 = RB_MIN_MAP_COUNT * 2, step2 = step1 * 10; // int step1 = 2, step2 = step1 * 10; int i; for (i = step1; i >= 1; i--) { struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0); assert(vma != NULL); insert_vma_struct(mm, vma); } for (i = step1 + 1; i <= step2; i++) { struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0); assert(vma != NULL); insert_vma_struct(mm, vma); } list_entry_t *le = list_next(&(mm->mmap_list)); for (i = 1; i <= step2; i++) { assert(le != &(mm->mmap_list)); struct vma_struct *mmap = le2vma(le, list_link); assert(mmap->vm_start == i * 5 && mmap->vm_end == i * 5 + 2); le = list_next(le); } for (i = 5; i <= 5 * step2; i+=5) { struct vma_struct *vma1 = find_vma(mm, i); assert(vma1 != NULL); struct vma_struct *vma2 = find_vma(mm, i+1); assert(vma2 != NULL); struct vma_struct *vma3 = find_vma(mm, i+2); assert(vma3 == NULL); struct vma_struct *vma4 = find_vma(mm, i+3); assert(vma4 == NULL); struct vma_struct *vma5 = find_vma(mm, i+4); assert(vma5 == NULL); assert(vma1->vm_start == i && vma1->vm_end == i + 2); assert(vma2->vm_start == i && vma2->vm_end == i + 2); } for (i =4; i>=0; i--) { struct vma_struct *vma_below_5= find_vma(mm,i); assert(vma_below_5 == NULL); } mm_destroy(mm); __CHECK_MEMORY_LEAK(); kprintf("check_vma_struct() succeeded!\n"); }
static void check_vma_struct(void) { size_t nr_free_pages_store = nr_free_pages(); struct mm_struct *mm = mm_create(); assert(mm != NULL); int step1 = 10, step2 = step1 * 10; int i; for (i = step1; i >= 1; i --) { struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0); assert(vma != NULL); insert_vma_struct(mm, vma); } for (i = step1 + 1; i <= step2; i ++) { struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0); assert(vma != NULL); insert_vma_struct(mm, vma); } list_entry_t *le = list_next(&(mm->mmap_list)); for (i = 1; i <= step2; i ++) { assert(le != &(mm->mmap_list)); struct vma_struct *mmap = le2vma(le, list_link); assert(mmap->vm_start == i * 5 && mmap->vm_end == i * 5 + 2); le = list_next(le); } for (i = 5; i <= 5 * step2; i +=5) { struct vma_struct *vma1 = find_vma(mm, i); assert(vma1 != NULL); struct vma_struct *vma2 = find_vma(mm, i+1); assert(vma2 != NULL); struct vma_struct *vma3 = find_vma(mm, i+2); assert(vma3 == NULL); struct vma_struct *vma4 = find_vma(mm, i+3); assert(vma4 == NULL); struct vma_struct *vma5 = find_vma(mm, i+4); assert(vma5 == NULL); assert(vma1->vm_start == i && vma1->vm_end == i + 2); assert(vma2->vm_start == i && vma2->vm_end == i + 2); } for (i =4; i>=0; i--) { struct vma_struct *vma_below_5= find_vma(mm,i); if (vma_below_5 != NULL ) { cprintf("vma_below_5: i %x, start %x, end %x\n",i, vma_below_5->vm_start, vma_below_5->vm_end); } assert(vma_below_5 == NULL); } mm_destroy(mm); cprintf("check_vma_struct() succeeded!\n"); }
int MM_create(size_t size, const char *file) { if (mm_global != NULL) return FALSE; if ((mm_global = mm_create(size, file)) == NULL) return FALSE; return TRUE; }
// copy_mm - process "proc" duplicate OR share process "current"'s mm according clone_flags // - if clone_flags & CLONE_VM, then "share" ; else "duplicate" static int copy_mm(uint32_t clone_flags, struct proc_struct *proc) { struct mm_struct *mm, *oldmm = current->mm; /* current is a kernel thread */ if (oldmm == NULL) { return 0; } if (clone_flags & CLONE_VM) { mm = oldmm; goto good_mm; } int ret = -E_NO_MEM; if ((mm = mm_create()) == NULL) { goto bad_mm; } if (setup_pgdir(mm) != 0) { goto bad_pgdir_cleanup_mm; } lock_mm(oldmm); { ret = dup_mmap(mm, oldmm); } unlock_mm(oldmm); if (ret != 0) { goto bad_dup_cleanup_mmap; } good_mm: if (mm != oldmm) { mm->brk_start = oldmm->brk_start; mm->brk = oldmm->brk; bool intr_flag; local_intr_save(intr_flag); { list_add(&(proc_mm_list), &(mm->proc_mm_link)); } local_intr_restore(intr_flag); } mm_count_inc(mm); proc->mm = mm; set_pgdir (proc, mm->pgdir); return 0; bad_dup_cleanup_mmap: exit_mmap(mm); put_pgdir(mm); bad_pgdir_cleanup_mm: mm_destroy(mm); bad_mm: return ret; }
// check_pgfault - check correctness of pgfault handler static void check_pgfault(void) { #ifdef UCONFIG_CHECK_PGFAULT kprintf("starting check_pgfault()\n"); size_t nr_used_pages_store = nr_used_pages(); size_t slab_allocated_store = slab_allocated(); check_mm_struct = mm_create(); assert(check_mm_struct != NULL); struct mm_struct *mm = check_mm_struct; pgd_t *pgdir = mm->pgdir = init_pgdir_get(); assert(pgdir[PGX(TEST_PAGE)] == 0); struct vma_struct *vma = vma_create(TEST_PAGE, TEST_PAGE + PTSIZE, VM_WRITE); assert(vma != NULL); insert_vma_struct(mm, vma); uintptr_t addr = TEST_PAGE + 0x100; assert(find_vma(mm, addr) == vma); int i, sum = 0; for (i = 0; i < 100; i++) { *(char *)(addr + i) = i; sum += i; } for (i = 0; i < 100; i++) { sum -= *(char *)(addr + i); } assert(sum == 0); page_remove(pgdir, ROUNDDOWN(addr, PGSIZE)); #if PMXSHIFT != PUXSHIFT free_page(pa2page(PMD_ADDR(*get_pmd(pgdir, addr, 0)))); #endif #if PUXSHIFT != PGXSHIFT free_page(pa2page(PUD_ADDR(*get_pud(pgdir, addr, 0)))); #endif free_page(pa2page(PGD_ADDR(*get_pgd(pgdir, addr, 0)))); pgdir[PGX(TEST_PAGE)] = 0; mm->pgdir = NULL; mm_destroy(mm); check_mm_struct = NULL; assert(nr_used_pages_store == nr_used_pages()); assert(slab_allocated_store == slab_allocated()); kprintf("check_pgfault() succeeded!\n"); #endif }
struct monitor * monitor_init(void) { struct ssh *ssh = active_state; /* XXX */ struct monitor *mon; mon = xcalloc(1, sizeof(*mon)); monitor_openfds(mon, 1); /* Used to share zlib space across processes */ if (options.compression) { mon->m_zback = mm_create(NULL, MM_MEMSIZE); mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); /* Compression needs to share state across borders */ ssh_packet_set_compress_hooks(ssh, mon->m_zlib, (ssh_packet_comp_alloc_func *)mm_zalloc, (ssh_packet_comp_free_func *)mm_zfree); } return mon; }
static void check_vma_struct(void) { size_t nr_free_pages_store = nr_free_pages(); size_t slab_allocated_store = slab_allocated(); struct mm_struct *mm = mm_create(); assert(mm != NULL); int step1 = RB_MIN_MAP_COUNT * 2, step2 = step1 * 10; int i; for (i = step1; i >= 0; i --) { struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0); assert(vma != NULL); insert_vma_struct(mm, vma); } for (i = step1 + 1; i <= step2; i ++) { struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0); assert(vma != NULL); insert_vma_struct(mm, vma); } list_entry_t *le = list_next(&(mm->mmap_list)); for (i = 0; i <= step2; i ++) { assert(le != &(mm->mmap_list)); struct vma_struct *mmap = le2vma(le, list_link); assert(mmap->vm_start == i * 5 && mmap->vm_end == i * 5 + 2); le = list_next(le); } for (i = 0; i < 5 * step2 + 2; i ++) { struct vma_struct *vma = find_vma(mm, i); assert(vma != NULL); int j = i / 5; if (i >= 5 * j + 2) { j ++; } assert(vma->vm_start == j * 5 && vma->vm_end == j * 5 + 2); } mm_destroy(mm); assert(nr_free_pages_store == nr_free_pages()); assert(slab_allocated_store == slab_allocated()); cprintf("check_vma_struct() succeeded!\n"); }
STATE(char *filename) { this->alive = false; this->filename = strdup(filename); this->mm_file = new char[strlen(this->filename) + 4]; strcpy(this->mm_file, filename); strcat(this->mm_file, "_mm"); this->mm = mm_create(LOGFILE_CHUNK_SIZE * 2, this->mm_file); this->length = (long *) mm_malloc(mm, sizeof (long)); *this->length = 0; this->logBuffer = (char *) mm_malloc(mm, LOGFILE_CHUNK_SIZE); *this->logBuffer = '\0'; this->logFd = 0; this->alive = true; int fd = open(this->filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); close(fd); }
// check_pgfault - check correctness of pgfault handler static void check_pgfault(void) { size_t nr_free_pages_store = nr_free_pages(); size_t slab_allocated_store = slab_allocated(); check_mm_struct = mm_create(); assert(check_mm_struct != NULL); struct mm_struct *mm = check_mm_struct; pgd_t *pgdir = mm->pgdir = boot_pgdir; assert(pgdir[0] == 0); struct vma_struct *vma = vma_create(0, PTSIZE, VM_WRITE); assert(vma != NULL); insert_vma_struct(mm, vma); uintptr_t addr = 0x100; assert(find_vma(mm, addr) == vma); int i, sum = 0; for (i = 0; i < 100; i ++) { *(char *)(addr + i) = i; sum += i; } for (i = 0; i < 100; i ++) { sum -= *(char *)(addr + i); } assert(sum == 0); page_remove(pgdir, ROUNDDOWN(addr, PGSIZE)); free_page(pa2page(PMD_ADDR(*get_pmd(pgdir, addr, 0)))); free_page(pa2page(PUD_ADDR(*get_pud(pgdir, addr, 0)))); free_page(pa2page(PGD_ADDR(*get_pgd(pgdir, addr, 0)))); pgdir[0] = 0; mm->pgdir = NULL; mm_destroy(mm); check_mm_struct = NULL; assert(nr_free_pages_store == nr_free_pages()); assert(slab_allocated_store == slab_allocated()); cprintf("check_pgfault() succeeded!\n"); }
static int ps_mm_initialize(ps_mm *data, const char *path) { data->owner = getpid(); data->mm = mm_create(0, path); if (!data->mm) { return FAILURE; } data->hash_cnt = 0; data->hash_max = 511; data->hash = mm_calloc(data->mm, data->hash_max + 1, sizeof(ps_sd *)); if (!data->hash) { mm_destroy(data->mm); return FAILURE; } return SUCCESS; }
// check_pgfault - check correctness of pgfault handler static void check_pgfault(void) { size_t nr_free_pages_store = nr_free_pages(); check_mm_struct = mm_create(); assert(check_mm_struct != NULL); struct mm_struct *mm = check_mm_struct; pde_t *pgdir = mm->pgdir = boot_pgdir; assert(pgdir[0] == 0); struct vma_struct *vma = vma_create(0, PTSIZE, VM_WRITE); assert(vma != NULL); insert_vma_struct(mm, vma); uintptr_t addr = 0x100; assert(find_vma(mm, addr) == vma); int i, sum = 0; for (i = 0; i < 100; i ++) { // cprintf("%d\n", i); *(char *)(addr + i) = i; sum += i; } // assert(0); for (i = 0; i < 100; i ++) { sum -= *(char *)(addr + i); } assert(sum == 0); page_remove(pgdir, ROUNDDOWN(addr, PGSIZE)); free_page(pde2page(pgdir[0])); pgdir[0] = 0; mm->pgdir = NULL; mm_destroy(mm); check_mm_struct = NULL; assert(nr_free_pages_store == nr_free_pages()); cprintf("check_pgfault() succeeded!\n"); }
ExploreModule explore_create() { // init the module ExploreModule em; em.mazeMap = mm_create(); // zero out the search array for (int row = 0; row < MAZE_WIDTH; row++) { for(int col = 0; col < MAZE_HEIGHT; col++) { em.exHistory[row][col] = FALSE; } } em.returning = FALSE; em.prevTravelPos = -1; return em; }
STATE(char *filename) { this->alive = false; this->filename = strdup(filename); this->mm_file = new char[strlen(this->filename) + 4]; strcpy(this->mm_file, filename); strcat(this->mm_file, "_mm"); this->mm = mm_create(LOGFILE_CHUNK_SIZE * 2, this->mm_file); if (!this->mm) { return; } this->length = (long *) mm_malloc(mm, sizeof (long)); *this->length = 0; this->logBuffer = (char *) mm_malloc(mm, LOGFILE_CHUNK_SIZE); *this->logBuffer = '\0'; this->logFd = 0; this->alive = true; // setting file mode to 0666 so child processes with user,group // changed by calls to setuid/setgid can flush() mode_t omask = umask(0); int fd = open(this->filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); close(fd); chmod(this->filename, 0666); umask(omask); }
int main(int argc, char *argv[]) { unsigned char *core; int i; size_t s, s2; pid_t pid; int size; MM *mm; int n; char *cp[1025]; int version; struct count_test { int count; int prev; } *ct; setbuf(stderr, NULL); /* ** ** Test Global Library API ** */ fprintf(stderr, "\n*** TESTING GLOBAL LIBRARY API ***\n\n"); fprintf(stderr, "Fetching library version\n"); version = mm_lib_version(); FAILED_IF(version == 0x0); fprintf(stderr, "version = 0x%X\n", version); /* ** ** Test Low-Level Shared Memory API ** */ fprintf(stderr, "\n*** TESTING LOW-LEVEL SHARED MEMORY API ***\n"); fprintf(stderr, "\n=== Testing Memory Segment Access ===\n"); fprintf(stderr, "Creating 16KB shared memory core area\n"); core = mm_core_create(1024*16, NULL); FAILED_IF(core == NULL); s = mm_core_size(core); FAILED_IF(s == 0); fprintf(stderr, "actually allocated core size = %d\n", s); fprintf(stderr, "Writing 0xF5 bytes to shared memory core area\n"); for (i = 0; i < s; i++) { fprintf(stderr, "write to core[%06d]\r", i); core[i] = 0xF5; } fprintf(stderr, "\n"); fprintf(stderr, "Reading back 0xF5 bytes from shared memory core area\n"); for (i = 0; i < s; i++) { fprintf(stderr, "read from core[%06d]\r", i); if (core[i] != 0xF5) { fprintf(stderr, "Offset %d: 0xF5 not found (found 0x%X\n", i, core[i]); exit(0); } } fprintf(stderr, "\n"); fprintf(stderr, "Destroying shared memory core area\n"); mm_core_delete(core); fprintf(stderr, "\n=== Testing Memory Locking ===\n"); fprintf(stderr, "Creating small shared memory core area\n"); ct = mm_core_create(sizeof(struct count_test), NULL); FAILED_IF(ct == NULL); s = mm_core_size(ct); FAILED_IF(s == 0); fprintf(stderr, "actually allocated core size = %d\n", s); ct->prev = 0; ct->count = 1; if ((pid = fork()) == 0) { /* child */ while (ct->count < 32768) { if (!mm_core_lock(ct, MM_LOCK_RW)) { fprintf(stderr, "locking failed (child)\n"); FAILED_IF(1); } if (ct->prev != (ct->count-1)) { fprintf(stderr, "Failed, prev=%d != count=%d\n", ct->prev, ct->count); exit(1); } ct->count += 1; fprintf(stderr, "count=%06d (child )\r", ct->count); ct->prev += 1; if (!mm_core_unlock(ct)) { fprintf(stderr, "locking failed (child)\n"); FAILED_IF(1); } } exit(0); } /* parent ... */ while (ct->count < 32768) { if (!mm_core_lock(ct, MM_LOCK_RW)) { fprintf(stderr, "locking failed (parent)\n"); FAILED_IF(1); } if (ct->prev != (ct->count-1)) { fprintf(stderr, "Failed, prev=%d != count=%d\n", ct->prev, ct->count); exit(1); } ct->count += 1; fprintf(stderr, "count=%06d (parent)\r", ct->count); ct->prev += 1; if (!mm_core_unlock(ct)) { fprintf(stderr, "locking failed (parent)\n"); kill(pid, SIGTERM); FAILED_IF(1); } } waitpid(pid, NULL, 0); fprintf(stderr, "\n"); fprintf(stderr, "Destroying shared memory core area\n"); mm_core_delete(ct); /* ** ** Test Standard Malloc-style API ** */ fprintf(stderr, "\n*** TESTING STANDARD MALLOC-STYLE API ***\n"); fprintf(stderr, "\n=== Testing Allocation ===\n"); fprintf(stderr, "Creating MM object\n"); size = mm_maxsize(); if (size > 1024*1024*1) size = 1024*1024*1; mm = mm_create(size, NULL); FAILED_IF(mm == NULL) mm_display_info(mm); s = mm_available(mm); FAILED_IF(s == 0); fprintf(stderr, "actually available bytes = %d\n", s); fprintf(stderr, "Allocating areas inside MM\n"); n = 0; for (i = 0; i < 1024; i++) cp[i] = NULL; for (i = 0; i < 1024; i++) { fprintf(stderr, "total=%09d allocated=%09d add=%06d\r", s, n, (i+1)*(i+1)); s2 = mm_available(mm); if ((i+1)*(i+1) > s2) { cp[i] = mm_malloc(mm, (i+1)*(i+1)); if (cp[i] != NULL) { fprintf(stderr, "\nExpected an out of memory situation. Hmmmmm\n"); FAILED_IF(1); } break; } cp[i] = mm_malloc(mm, (i+1)*(i+1)); n += (i+1)*(i+1); FAILED_IF(cp[i] == NULL) memset(cp[i], 0xF5, (i+1)*(i+1)); } mm_display_info(mm); fprintf(stderr, "\n=== Testing Defragmentation ===\n"); fprintf(stderr, "Fragmenting memory area by freeing some selected areas\n"); for (i = 0; i < 1024; i++) { if (i % 2 == 0) continue; if (cp[i] != NULL) mm_free(mm, cp[i]); cp[i] = NULL; } mm_display_info(mm); fprintf(stderr, "Freeing all areas\n"); for (i = 0; i < 1024; i++) { mm_free(mm, cp[i]); } mm_display_info(mm); fprintf(stderr, "Checking for memory leaks\n"); s2 = mm_available(mm); if (s != s2) { fprintf(stderr, "Something is leaking, we've lost %d bytes\n", s - s2); FAILED_IF(1); } else { fprintf(stderr, "Fine, we have again %d bytes available\n", s2); } fprintf(stderr, "Destroying MM object\n"); mm_destroy(mm); /******/ fprintf(stderr, "\nOK - ALL TESTS SUCCESSFULLY PASSED.\n\n"); exit(0); }
static int load_icode(int fd, int argc, char **kargv, int envc, char **kenvp) { assert(argc >= 0 && argc <= EXEC_MAX_ARG_NUM); assert(envc >= 0 && envc <= EXEC_MAX_ENV_NUM); if (current->mm != NULL) { panic("load_icode: current->mm must be empty.\n"); } int ret = -E_NO_MEM; //#ifdef UCONFIG_BIONIC_LIBC uint32_t real_entry; //#endif //UCONFIG_BIONIC_LIBC struct mm_struct *mm; if ((mm = mm_create()) == NULL) { goto bad_mm; } if (setup_pgdir(mm) != 0) { goto bad_pgdir_cleanup_mm; } mm->brk_start = 0; struct Page *page; struct elfhdr __elf, *elf = &__elf; if ((ret = load_icode_read(fd, elf, sizeof(struct elfhdr), 0)) != 0) { goto bad_elf_cleanup_pgdir; } if (elf->e_magic != ELF_MAGIC) { ret = -E_INVAL_ELF; goto bad_elf_cleanup_pgdir; } //#ifdef UCONFIG_BIONIC_LIBC real_entry = elf->e_entry; uint32_t load_address, load_address_flag = 0; //#endif //UCONFIG_BIONIC_LIBC struct proghdr __ph, *ph = &__ph; uint32_t vm_flags, phnum; pte_perm_t perm = 0; //#ifdef UCONFIG_BIONIC_LIBC uint32_t is_dynamic = 0, interp_idx; uint32_t bias = 0; //#endif //UCONFIG_BIONIC_LIBC for (phnum = 0; phnum < elf->e_phnum; phnum++) { off_t phoff = elf->e_phoff + sizeof(struct proghdr) * phnum; if ((ret = load_icode_read(fd, ph, sizeof(struct proghdr), phoff)) != 0) { goto bad_cleanup_mmap; } if (ph->p_type == ELF_PT_INTERP) { is_dynamic = 1; interp_idx = phnum; continue; } if (ph->p_type != ELF_PT_LOAD) { continue; } if (ph->p_filesz > ph->p_memsz) { ret = -E_INVAL_ELF; goto bad_cleanup_mmap; } if (ph->p_va == 0 && !bias) { bias = 0x00008000; } if ((ret = map_ph(fd, ph, mm, &bias, 0)) != 0) { kprintf("load address: 0x%08x size: %d\n", ph->p_va, ph->p_memsz); goto bad_cleanup_mmap; } if (load_address_flag == 0) load_address = ph->p_va + bias; ++load_address_flag; /*********************************************/ /* vm_flags = 0; ptep_set_u_read(&perm); if (ph->p_flags & ELF_PF_X) vm_flags |= VM_EXEC; if (ph->p_flags & ELF_PF_W) vm_flags |= VM_WRITE; if (ph->p_flags & ELF_PF_R) vm_flags |= VM_READ; if (vm_flags & VM_WRITE) ptep_set_u_write(&perm); if ((ret = mm_map(mm, ph->p_va, ph->p_memsz, vm_flags, NULL)) != 0) { goto bad_cleanup_mmap; } if (mm->brk_start < ph->p_va + ph->p_memsz) { mm->brk_start = ph->p_va + ph->p_memsz; } off_t offset = ph->p_offset; size_t off, size; uintptr_t start = ph->p_va, end, la = ROUNDDOWN(start, PGSIZE); end = ph->p_va + ph->p_filesz; while (start < end) { if ((page = pgdir_alloc_page(mm->pgdir, la, perm)) == NULL) { ret = -E_NO_MEM; goto bad_cleanup_mmap; } off = start - la, size = PGSIZE - off, la += PGSIZE; if (end < la) { size -= la - end; } if ((ret = load_icode_read(fd, page2kva(page) + off, size, offset)) != 0) { goto bad_cleanup_mmap; } start += size, offset += size; } end = ph->p_va + ph->p_memsz; if (start < la) { // ph->p_memsz == ph->p_filesz if (start == end) { continue ; } off = start + PGSIZE - la, size = PGSIZE - off; if (end < la) { size -= la - end; } memset(page2kva(page) + off, 0, size); start += size; assert((end < la && start == end) || (end >= la && start == la)); } while (start < end) { if ((page = pgdir_alloc_page(mm->pgdir, la, perm)) == NULL) { ret = -E_NO_MEM; goto bad_cleanup_mmap; } off = start - la, size = PGSIZE - off, la += PGSIZE; if (end < la) { size -= la - end; } memset(page2kva(page) + off, 0, size); start += size; } */ /**************************************/ } mm->brk_start = mm->brk = ROUNDUP(mm->brk_start, PGSIZE); /* setup user stack */ vm_flags = VM_READ | VM_WRITE | VM_STACK; if ((ret = mm_map(mm, USTACKTOP - USTACKSIZE, USTACKSIZE, vm_flags, NULL)) != 0) { goto bad_cleanup_mmap; } if (is_dynamic) { elf->e_entry += bias; bias = 0; off_t phoff = elf->e_phoff + sizeof(struct proghdr) * interp_idx; if ((ret = load_icode_read(fd, ph, sizeof(struct proghdr), phoff)) != 0) { goto bad_cleanup_mmap; } char *interp_path = (char *)kmalloc(ph->p_filesz); load_icode_read(fd, interp_path, ph->p_filesz, ph->p_offset); int interp_fd = sysfile_open(interp_path, O_RDONLY); assert(interp_fd >= 0); struct elfhdr interp___elf, *interp_elf = &interp___elf; assert((ret = load_icode_read(interp_fd, interp_elf, sizeof(struct elfhdr), 0)) == 0); assert(interp_elf->e_magic == ELF_MAGIC); struct proghdr interp___ph, *interp_ph = &interp___ph; uint32_t interp_phnum; uint32_t va_min = 0xffffffff, va_max = 0; for (interp_phnum = 0; interp_phnum < interp_elf->e_phnum; ++interp_phnum) { off_t interp_phoff = interp_elf->e_phoff + sizeof(struct proghdr) * interp_phnum; assert((ret = load_icode_read(interp_fd, interp_ph, sizeof(struct proghdr), interp_phoff)) == 0); if (interp_ph->p_type != ELF_PT_LOAD) { continue; } if (va_min > interp_ph->p_va) va_min = interp_ph->p_va; if (va_max < interp_ph->p_va + interp_ph->p_memsz) va_max = interp_ph->p_va + interp_ph->p_memsz; } bias = get_unmapped_area(mm, va_max - va_min + 1 + PGSIZE); bias = ROUNDUP(bias, PGSIZE); for (interp_phnum = 0; interp_phnum < interp_elf->e_phnum; ++interp_phnum) { off_t interp_phoff = interp_elf->e_phoff + sizeof(struct proghdr) * interp_phnum; assert((ret = load_icode_read(interp_fd, interp_ph, sizeof(struct proghdr), interp_phoff)) == 0); if (interp_ph->p_type != ELF_PT_LOAD) { continue; } assert((ret = map_ph(interp_fd, interp_ph, mm, &bias, 1)) == 0); } real_entry = interp_elf->e_entry + bias; sysfile_close(interp_fd); kfree(interp_path); } sysfile_close(fd); bool intr_flag; local_intr_save(intr_flag); { list_add(&(proc_mm_list), &(mm->proc_mm_link)); } local_intr_restore(intr_flag); mm_count_inc(mm); current->mm = mm; set_pgdir(current, mm->pgdir); mm->cpuid = myid(); mp_set_mm_pagetable(mm); if (!is_dynamic) { real_entry += bias; } #ifdef UCONFIG_BIONIC_LIBC if (init_new_context_dynamic(current, elf, argc, kargv, envc, kenvp, is_dynamic, real_entry, load_address, bias) < 0) goto bad_cleanup_mmap; #else if (init_new_context(current, elf, argc, kargv, envc, kenvp) < 0) goto bad_cleanup_mmap; #endif //UCONFIG_BIONIC_LIBC ret = 0; out: return ret; bad_cleanup_mmap: exit_mmap(mm); bad_elf_cleanup_pgdir: put_pgdir(mm); bad_pgdir_cleanup_mm: mm_destroy(mm); bad_mm: goto out; }
static void check_swap(void) { //backup mem env int ret, count = 0, total = 0, i; list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); assert(PageProperty(p)); count++, total += p->property; } assert(total == nr_free_pages()); cprintf("BEGIN check_swap: count %d, total %d\n", count, total); //now we set the phy pages env struct mm_struct *mm = mm_create(); assert(mm != NULL); extern struct mm_struct *check_mm_struct; assert(check_mm_struct == NULL); check_mm_struct = mm; pde_t *pgdir = mm->pgdir = boot_pgdir; assert(pgdir[0] == 0); struct vma_struct *vma = vma_create(BEING_CHECK_VALID_VADDR, CHECK_VALID_VADDR, VM_WRITE | VM_READ); assert(vma != NULL); insert_vma_struct(mm, vma); //setup the temp Page Table vaddr 0~4MB cprintf("setup Page Table for vaddr 0X1000, so alloc a page\n"); pte_t *temp_ptep = NULL; temp_ptep = get_pte(mm->pgdir, BEING_CHECK_VALID_VADDR, 1); assert(temp_ptep!= NULL); cprintf("setup Page Table vaddr 0~4MB OVER!\n"); for (i = 0; i < CHECK_VALID_PHY_PAGE_NUM; i++) { check_rp[i] = alloc_page(); assert(check_rp[i] != NULL); assert(!PageProperty(check_rp[i])); } list_entry_t free_list_store = free_list; list_init(&free_list); assert(list_empty(&free_list)); //assert(alloc_page() == NULL); unsigned int nr_free_store = nr_free; nr_free = 0; for (i = 0; i < CHECK_VALID_PHY_PAGE_NUM; i++) { free_pages(check_rp[i], 1); } assert(nr_free==CHECK_VALID_PHY_PAGE_NUM); cprintf("set up init env for check_swap begin!\n"); //setup initial vir_page<->phy_page environment for page relpacement algorithm pgfault_num = 0; check_content_set(); assert(nr_free == 0); for (i = 0; i < MAX_SEQ_NO; i++) swap_out_seq_no[i] = swap_in_seq_no[i] = -1; for (i = 0; i < CHECK_VALID_PHY_PAGE_NUM; i++) { check_ptep[i] = 0; check_ptep[i] = get_pte(pgdir, (i + 1) * 0x1000, 0); //cprintf("i %d, check_ptep addr %x, value %x\n", i, check_ptep[i], *check_ptep[i]); assert(check_ptep[i] != NULL); assert(pte2page(*check_ptep[i]) == check_rp[i]); assert((*check_ptep[i] & PTE_P)); } cprintf("set up init env for check_swap over!\n"); // now access the virt pages to test page relpacement algorithm ret = check_content_access(); assert(ret == 0); //restore kernel mem env for (i = 0; i < CHECK_VALID_PHY_PAGE_NUM; i++) { free_pages(check_rp[i], 1); } //free_page(pte2page(*temp_ptep)); free_page(pde2page(pgdir[0])); pgdir[0] = 0; mm->pgdir = NULL; mm_destroy(mm); check_mm_struct = NULL; nr_free = nr_free_store; free_list = free_list_store; le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); count--, total -= p->property; } cprintf("count is %d, total is %d\n", count, total); //assert(count == 0); cprintf("check_swap() succeeded!\n"); }
int main( int argc, char** argv ) { uint64_t i; // pointers for casting pq_op_create *op_create; pq_op_destroy *op_destroy; pq_op_clear *op_clear; pq_op_get_key *op_get_key; pq_op_get_item *op_get_item; pq_op_get_size *op_get_size; pq_op_insert *op_insert; pq_op_find_min *op_find_min; pq_op_delete *op_delete; pq_op_delete_min *op_delete_min; pq_op_decrease_key *op_decrease_key; //pq_op_meld *op_meld; pq_op_empty *op_empty; // temp dummies for readability pq_type *q;//, *r; pq_node_type *n; if( argc < 2 ) exit( -1 ); int trace_file = open( argv[1], O_RDONLY ); if( trace_file < 0 ) { fprintf( stderr, "Could not open file.\n" ); return -1; } pq_trace_header header; pq_trace_read_header( trace_file, &header ); close( trace_file ); //printf("Header: (%llu,%lu,%lu)\n",header.op_count,header.pq_ids, // header.node_ids); pq_op_blank *ops = calloc( MIN( header.op_count, CHUNK_SIZE ), sizeof( pq_op_blank ) ); pq_type **pq_index = calloc( header.pq_ids, sizeof( pq_type* ) ); pq_node_type **node_index = calloc( header.node_ids, sizeof( pq_node_type* ) ); if( ops == NULL || pq_index == NULL || node_index == NULL ) { fprintf( stderr, "Calloc fail.\n" ); return -1; } #ifdef USE_QUAKE mem_capacities[0] = header.node_ids << 2; #else mem_capacities[0] = header.node_ids; #endif #ifdef USE_EAGER mem_map *map = mm_create( mem_types, mem_sizes, mem_capacities ); #else mem_map *map = mm_create( mem_types, mem_sizes ); #endif uint64_t op_remaining, op_chunk; int status; struct timeval t0, t1; uint32_t iterations = 0; uint32_t total_time = 0; key_type k; //pq_node_type *min; #ifndef CACHEGRIND while( iterations < 5 || total_time < PQ_MIN_USEC ) { mm_clear( map ); iterations++; #endif trace_file = open( argv[1], O_RDONLY ); if( trace_file < 0 ) { fprintf( stderr, "Could not open file.\n" ); return -1; } pq_trace_read_header( trace_file, &header ); op_remaining = header.op_count; while( op_remaining > 0 ) { op_chunk = MIN( CHUNK_SIZE, op_remaining ); op_remaining -= op_chunk; for( i = 0; i < op_chunk; i++ ) { status = pq_trace_read_op( trace_file, ops + i ); if( status == -1 ) { fprintf( stderr, "Invalid operation!" ); return -1; } } #ifndef CACHEGRIND gettimeofday(&t0, NULL); #endif for( i = 0; i < op_chunk; i++ ) { switch( ops[i].code ) { case PQ_OP_CREATE: op_create = (pq_op_create*) ( ops + i ); //printf("pq_create(%d)\n", op_create->pq_id); pq_index[op_create->pq_id] = pq_create( map ); break; case PQ_OP_DESTROY: op_destroy = (pq_op_destroy*) ( ops + i ); //printf("pq_destroy(%d)\n", op_destroy->pq_id); q = pq_index[op_destroy->pq_id]; pq_destroy( q ); pq_index[op_destroy->pq_id] = NULL; break; case PQ_OP_CLEAR: op_clear = (pq_op_clear*) ( ops + i ); //printf("pq_clear(%d)\n", op_clear->pq_id ); q = pq_index[op_clear->pq_id]; pq_clear( q ); break; case PQ_OP_GET_KEY: op_get_key = (pq_op_get_key*) ( ops + i ); //printf("pq_get_key(%d,%d)\n", op_get_key->pq_id, // op_get_key->node_id ); q = pq_index[op_get_key->pq_id]; n = node_index[op_get_key->node_id]; pq_get_key( q, n ); break; case PQ_OP_GET_ITEM: op_get_item = (pq_op_get_item*) ( ops + i ); //printf("pq_get_item(%d,%d)\n", op_get_item->pq_id, // op_get_item->node_id); q = pq_index[op_get_item->pq_id]; n = node_index[op_get_item->node_id]; pq_get_item( q, n ); break; case PQ_OP_GET_SIZE: op_get_size = (pq_op_get_size*) ( ops + i ); //printf("pq_get_size(%d)\n", op_get_size->pq_id); q = pq_index[op_get_size->pq_id]; pq_get_size( q ); break; case PQ_OP_INSERT: op_insert = (pq_op_insert*) ( ops + i ); //printf("pq_insert(%d,%d,%llu,%d)\n", op_insert->pq_id, // op_insert->node_id, op_insert->key, op_insert->item ); q = pq_index[op_insert->pq_id]; node_index[op_insert->node_id] = pq_insert( q, op_insert->item, op_insert->key ); break; case PQ_OP_FIND_MIN: op_find_min = (pq_op_find_min*) ( ops + i ); //printf("pq_find_min(%d)\n", op_find_min->pq_id ); q = pq_index[op_find_min->pq_id]; pq_find_min( q ); break; case PQ_OP_DELETE: op_delete = (pq_op_delete*) ( ops + i ); //printf("pq_delete(%d,%d)\n", op_delete->pq_id, // op_delete->node_id ); q = pq_index[op_delete->pq_id]; n = node_index[op_delete->node_id]; pq_delete( q, n ); break; case PQ_OP_DELETE_MIN: op_delete_min = (pq_op_delete_min*) ( ops + i ); //printf("pq_delete_min(%d)\n", op_delete_min->pq_id); q = pq_index[op_delete_min->pq_id]; //min = pq_find_min( q ); k = pq_delete_min( q ); #ifdef CACHEGRIND if( argc > 2 ) printf("%llu\n",k); #endif break; case PQ_OP_DECREASE_KEY: op_decrease_key = (pq_op_decrease_key*) ( ops + i ); //printf("pq_decrease_key(%d,%d,%llu)\n", op_decrease_key->pq_id, // op_decrease_key->node_id, op_decrease_key->key); q = pq_index[op_decrease_key->pq_id]; n = node_index[op_decrease_key->node_id]; pq_decrease_key( q, n, op_decrease_key->key ); break; /*case PQ_OP_MELD: printf("Meld.\n"); op_meld = (pq_op_meld*) ( ops + i ); q = pq_index[op_meld->pq_src1_id]; r = pq_index[op_meld->pq_src2_id]; pq_index[op_meld->pq_dst_id] = pq_meld( q, r ); break;*/ case PQ_OP_EMPTY: op_empty = (pq_op_empty*) ( ops + i ); //printf("pq_empty(%d)\n", op_empty->pq_id); q = pq_index[op_empty->pq_id]; pq_empty( q ); break; default: break; } //verify_queue( pq_index[0], header.node_ids ); } #ifndef CACHEGRIND gettimeofday(&t1, NULL); total_time += (t1.tv_sec - t0.tv_sec) * 1000000 + (t1.tv_usec - t0.tv_usec); #endif } close( trace_file ); #ifndef CACHEGRIND } #endif for( i = 0; i < header.pq_ids; i++ ) { if( pq_index[i] != NULL ) pq_destroy( pq_index[i] ); } mm_destroy( map ); free( pq_index ); free( node_index ); free( ops ); #ifndef CACHEGRIND printf( "%d\n", total_time / iterations ); #endif return 0; }
static int load_icode(int fd, int argc, char **kargv, int envc, char **kenvp) { assert(argc >= 0 && argc <= EXEC_MAX_ARG_NUM); assert(envc >= 0 && envc <= EXEC_MAX_ENV_NUM); if (current->mm != NULL) { panic("load_icode: current->mm must be empty.\n"); } int ret = -E_NO_MEM; struct mm_struct *mm; if ((mm = mm_create()) == NULL) { goto bad_mm; } if (setup_pgdir(mm) != 0) { goto bad_pgdir_cleanup_mm; } mm->brk_start = 0; struct Page *page; struct elfhdr __elf, *elf = &__elf; if ((ret = load_icode_read(fd, elf, sizeof(struct elfhdr), 0)) != 0) { goto bad_elf_cleanup_pgdir; } if (elf->e_magic != ELF_MAGIC) { ret = -E_INVAL_ELF; goto bad_elf_cleanup_pgdir; } struct proghdr __ph, *ph = &__ph; uint32_t vm_flags, phnum; pte_perm_t perm = 0; for (phnum = 0; phnum < elf->e_phnum; phnum ++) { off_t phoff = elf->e_phoff + sizeof(struct proghdr) * phnum; if ((ret = load_icode_read(fd, ph, sizeof(struct proghdr), phoff)) != 0) { goto bad_cleanup_mmap; } if (ph->p_type != ELF_PT_LOAD) { continue ; } if (ph->p_filesz > ph->p_memsz) { ret = -E_INVAL_ELF; goto bad_cleanup_mmap; } vm_flags = 0; ptep_set_u_read(&perm); if (ph->p_flags & ELF_PF_X) vm_flags |= VM_EXEC; if (ph->p_flags & ELF_PF_W) vm_flags |= VM_WRITE; if (ph->p_flags & ELF_PF_R) vm_flags |= VM_READ; if (vm_flags & VM_WRITE) ptep_set_u_write(&perm); if ((ret = mm_map(mm, ph->p_va, ph->p_memsz, vm_flags, NULL)) != 0) { goto bad_cleanup_mmap; } if (mm->brk_start < ph->p_va + ph->p_memsz) { mm->brk_start = ph->p_va + ph->p_memsz; } off_t offset = ph->p_offset; size_t off, size; uintptr_t start = ph->p_va, end, la = ROUNDDOWN(start, PGSIZE); end = ph->p_va + ph->p_filesz; while (start < end) { if ((page = pgdir_alloc_page(mm->pgdir, la, perm)) == NULL) { ret = -E_NO_MEM; goto bad_cleanup_mmap; } off = start - la, size = PGSIZE - off, la += PGSIZE; if (end < la) { size -= la - end; } if ((ret = load_icode_read(fd, page2kva(page) + off, size, offset)) != 0) { goto bad_cleanup_mmap; } start += size, offset += size; } end = ph->p_va + ph->p_memsz; if (start < la) { /* ph->p_memsz == ph->p_filesz */ if (start == end) { continue ; } off = start + PGSIZE - la, size = PGSIZE - off; if (end < la) { size -= la - end; } memset(page2kva(page) + off, 0, size); start += size; assert((end < la && start == end) || (end >= la && start == la)); } while (start < end) { if ((page = pgdir_alloc_page(mm->pgdir, la, perm)) == NULL) { ret = -E_NO_MEM; goto bad_cleanup_mmap; } off = start - la, size = PGSIZE - off, la += PGSIZE; if (end < la) { size -= la - end; } memset(page2kva(page) + off, 0, size); start += size; } } sysfile_close(fd); mm->brk_start = mm->brk = ROUNDUP(mm->brk_start, PGSIZE); /* setup user stack */ vm_flags = VM_READ | VM_WRITE | VM_STACK; if ((ret = mm_map(mm, USTACKTOP - USTACKSIZE, USTACKSIZE, vm_flags, NULL)) != 0) { goto bad_cleanup_mmap; } bool intr_flag; local_intr_save(intr_flag); { list_add(&(proc_mm_list), &(mm->proc_mm_link)); } local_intr_restore(intr_flag); mm_count_inc(mm); current->mm = mm; set_pgdir(current, mm->pgdir); mm->lapic = pls_read(lapic_id); mp_set_mm_pagetable(mm); if (init_new_context (current, elf, argc, kargv, envc, kenvp) < 0) goto bad_cleanup_mmap; ret = 0; out: return ret; bad_cleanup_mmap: exit_mmap(mm); bad_elf_cleanup_pgdir: put_pgdir(mm); bad_pgdir_cleanup_mm: mm_destroy(mm); bad_mm: goto out; }
void vector_init () { mm = mm_create (sizeof (vector_t), &vector_clear); out_of_bounds = c_sym ("index-out-of-bounds"); }
// check_swap - check the correctness of swap & page replacement algorithm static void check_swap(void) { size_t nr_used_pages_store = nr_used_pages(); size_t slab_allocated_store = slab_allocated(); size_t offset; for (offset = 2; offset < max_swap_offset; offset ++) { mem_map[offset] = 1; } struct mm_struct *mm = mm_create(); assert(mm != NULL); extern struct mm_struct *check_mm_struct; assert(check_mm_struct == NULL); check_mm_struct = mm; pgd_t *pgdir = mm->pgdir = init_pgdir_get(); assert(pgdir[PGX(TEST_PAGE)] == 0); struct vma_struct *vma = vma_create(TEST_PAGE, TEST_PAGE + PTSIZE, VM_WRITE | VM_READ); assert(vma != NULL); insert_vma_struct(mm, vma); struct Page *rp0 = alloc_page(), *rp1 = alloc_page(); assert(rp0 != NULL && rp1 != NULL); pte_perm_t perm; ptep_unmap (&perm); ptep_set_u_write(&perm); int ret = page_insert(pgdir, rp1, TEST_PAGE, perm); assert(ret == 0 && page_ref(rp1) == 1); page_ref_inc(rp1); ret = page_insert(pgdir, rp0, TEST_PAGE, perm); assert(ret == 0 && page_ref(rp1) == 1 && page_ref(rp0) == 1); // check try_alloc_swap_entry swap_entry_t entry = try_alloc_swap_entry(); assert(swap_offset(entry) == 1); mem_map[1] = 1; assert(try_alloc_swap_entry() == 0); // set rp1, Swap, Active, add to hash_list, active_list swap_page_add(rp1, entry); swap_active_list_add(rp1); assert(PageSwap(rp1)); mem_map[1] = 0; entry = try_alloc_swap_entry(); assert(swap_offset(entry) == 1); assert(!PageSwap(rp1)); // check swap_remove_entry assert(swap_hash_find(entry) == NULL); mem_map[1] = 2; swap_remove_entry(entry); assert(mem_map[1] == 1); swap_page_add(rp1, entry); swap_inactive_list_add(rp1); swap_remove_entry(entry); assert(PageSwap(rp1)); assert(rp1->index == entry && mem_map[1] == 0); // check page_launder, move page from inactive_list to active_list assert(page_ref(rp1) == 1); assert(nr_active_pages == 0 && nr_inactive_pages == 1); assert(list_next(&(inactive_list.swap_list)) == &(rp1->swap_link)); page_launder(); assert(nr_active_pages == 1 && nr_inactive_pages == 0); assert(PageSwap(rp1) && PageActive(rp1)); entry = try_alloc_swap_entry(); assert(swap_offset(entry) == 1); assert(!PageSwap(rp1) && nr_active_pages == 0); assert(list_empty(&(active_list.swap_list))); // set rp1 inactive again assert(page_ref(rp1) == 1); swap_page_add(rp1, 0); assert(PageSwap(rp1) && swap_offset(rp1->index) == 1); swap_inactive_list_add(rp1); mem_map[1] = 1; assert(nr_inactive_pages == 1); page_ref_dec(rp1); size_t count = nr_used_pages(); swap_remove_entry(entry); assert(nr_inactive_pages == 0 && nr_used_pages() == count - 1); // check swap_out_mm pte_t *ptep0 = get_pte(pgdir, TEST_PAGE, 0), *ptep1; assert(ptep0 != NULL && pte2page(*ptep0) == rp0); ret = swap_out_mm(mm, 0); assert(ret == 0); ret = swap_out_mm(mm, 10); assert(ret == 1 && mm->swap_address == TEST_PAGE + PGSIZE); ret = swap_out_mm(mm, 10); assert(ret == 0 && *ptep0 == entry && mem_map[1] == 1); assert(PageDirty(rp0) && PageActive(rp0) && page_ref(rp0) == 0); assert(nr_active_pages == 1 && list_next(&(active_list.swap_list)) == &(rp0->swap_link)); // check refill_inactive_scan() refill_inactive_scan(); assert(!PageActive(rp0) && page_ref(rp0) == 0); assert(nr_inactive_pages == 1 && list_next(&(inactive_list.swap_list)) == &(rp0->swap_link)); page_ref_inc(rp0); page_launder(); assert(PageActive(rp0) && page_ref(rp0) == 1); assert(nr_active_pages == 1 && list_next(&(active_list.swap_list)) == &(rp0->swap_link)); page_ref_dec(rp0); refill_inactive_scan(); assert(!PageActive(rp0)); // save data in rp0 int i; for (i = 0; i < PGSIZE; i ++) { ((char *)page2kva(rp0))[i] = (char)i; } page_launder(); assert(nr_inactive_pages == 0 && list_empty(&(inactive_list.swap_list))); assert(mem_map[1] == 1); rp1 = alloc_page(); assert(rp1 != NULL); ret = swapfs_read(entry, rp1); assert(ret == 0); for (i = 0; i < PGSIZE; i ++) { assert(((char *)page2kva(rp1))[i] == (char)i); } // page fault now *(char *)(TEST_PAGE) = 0xEF; rp0 = pte2page(*ptep0); assert(page_ref(rp0) == 1); assert(PageSwap(rp0) && PageActive(rp0)); entry = try_alloc_swap_entry(); assert(swap_offset(entry) == 1 && mem_map[1] == SWAP_UNUSED); assert(!PageSwap(rp0) && nr_active_pages == 0 && nr_inactive_pages == 0); // clear accessed flag assert(rp0 == pte2page(*ptep0)); assert(!PageSwap(rp0)); ret = swap_out_mm(mm, 10); assert(ret == 0); assert(!PageSwap(rp0) && ptep_present(ptep0)); // change page table ret = swap_out_mm(mm, 10); assert(ret == 1); assert(*ptep0 == entry && page_ref(rp0) == 0 && mem_map[1] == 1); count = nr_used_pages(); refill_inactive_scan(); page_launder(); assert(count - 1 == nr_used_pages()); ret = swapfs_read(entry, rp1); assert(ret == 0 && *(char *)(page2kva(rp1)) == (char)0xEF); free_page(rp1); // duplictate *ptep0 ptep1 = get_pte(pgdir, TEST_PAGE + PGSIZE, 0); assert(ptep1 != NULL && ptep_invalid(ptep1)); swap_duplicate(*ptep0); ptep_copy(ptep1, ptep0); mp_tlb_invalidate (pgdir, TEST_PAGE + PGSIZE); // page fault again // update for copy on write *(char *)(TEST_PAGE + 1) = 0x88; *(char *)(TEST_PAGE + PGSIZE) = 0x8F; *(char *)(TEST_PAGE + PGSIZE + 1) = 0xFF; assert(pte2page(*ptep0) != pte2page(*ptep1)); assert(*(char *)(TEST_PAGE) == (char)0xEF); assert(*(char *)(TEST_PAGE + 1) == (char)0x88); assert(*(char *)(TEST_PAGE + PGSIZE) == (char)0x8F); assert(*(char *)(TEST_PAGE + PGSIZE + 1) == (char)0xFF); rp0 = pte2page(*ptep0); rp1 = pte2page(*ptep1); assert(!PageSwap(rp0) && PageSwap(rp1) && PageActive(rp1)); entry = try_alloc_swap_entry(); assert(!PageSwap(rp0) && !PageSwap(rp1)); assert(swap_offset(entry) == 1 && mem_map[1] == SWAP_UNUSED); assert(list_empty(&(active_list.swap_list))); assert(list_empty(&(inactive_list.swap_list))); ptep_set_accessed(&perm); page_insert(pgdir, rp0, TEST_PAGE + PGSIZE, perm); // check swap_out_mm *(char *)(TEST_PAGE) = *(char *)(TEST_PAGE + PGSIZE) = 0xEE; mm->swap_address = TEST_PAGE + PGSIZE * 2; ret = swap_out_mm(mm, 2); assert(ret == 0); assert(ptep_present(ptep0) && ! ptep_accessed(ptep0)); assert(ptep_present(ptep1) && ! ptep_accessed(ptep1)); ret = swap_out_mm(mm, 2); assert(ret == 2); assert(mem_map[1] == 2 && page_ref(rp0) == 0); refill_inactive_scan(); page_launder(); assert(mem_map[1] == 2 && swap_hash_find(entry) == NULL); // check copy entry swap_remove_entry(entry); ptep_unmap(ptep1); assert(mem_map[1] == 1); swap_entry_t store; ret = swap_copy_entry(entry, &store); assert(ret == -E_NO_MEM); mem_map[2] = SWAP_UNUSED; ret = swap_copy_entry(entry, &store); assert(ret == 0 && swap_offset(store) == 2 && mem_map[2] == 0); mem_map[2] = 1; ptep_copy(ptep1, &store); assert(*(char *)(TEST_PAGE + PGSIZE) == (char)0xEE && *(char *)(TEST_PAGE + PGSIZE + 1)== (char)0x88); *(char *)(TEST_PAGE + PGSIZE) = 1, *(char *)(TEST_PAGE + PGSIZE + 1) = 2; assert(*(char *)TEST_PAGE == (char)0xEE && *(char *)(TEST_PAGE + 1) == (char)0x88); ret = swap_in_page(entry, &rp0); assert(ret == 0); ret = swap_in_page(store, &rp1); assert(ret == 0); assert(rp1 != rp0); // free memory swap_list_del(rp0), swap_list_del(rp1); swap_page_del(rp0), swap_page_del(rp1); assert(page_ref(rp0) == 1 && page_ref(rp1) == 1); assert(nr_active_pages == 0 && list_empty(&(active_list.swap_list))); assert(nr_inactive_pages == 0 && list_empty(&(inactive_list.swap_list))); for (i = 0; i < HASH_LIST_SIZE; i ++) { assert(list_empty(hash_list + i)); } page_remove(pgdir, TEST_PAGE); page_remove(pgdir, (TEST_PAGE + PGSIZE)); #if PMXSHIFT != PUXSHIFT free_page(pa2page(PMD_ADDR(*get_pmd(pgdir, TEST_PAGE, 0)))); #endif #if PUXSHIFT != PGXSHIFT free_page(pa2page(PUD_ADDR(*get_pud(pgdir, TEST_PAGE, 0)))); #endif free_page(pa2page(PGD_ADDR(*get_pgd(pgdir, TEST_PAGE, 0)))); pgdir[PGX(TEST_PAGE)] = 0; mm->pgdir = NULL; mm_destroy(mm); check_mm_struct = NULL; assert(nr_active_pages == 0 && nr_inactive_pages == 0); for (offset = 0; offset < max_swap_offset; offset ++) { mem_map[offset] = SWAP_UNUSED; } assert(nr_used_pages_store == nr_used_pages()); assert(slab_allocated_store == slab_allocated()); kprintf("check_swap() succeeded.\n"); }
static void check_mm_swap(void) { size_t nr_free_pages_store = nr_free_pages(); size_t slab_allocated_store = slab_allocated(); int ret, i, j; for (i = 0; i < max_swap_offset; i ++) { assert(mem_map[i] == SWAP_UNUSED); } extern struct mm_struct *check_mm_struct; assert(check_mm_struct == NULL); // step1: check mm_map struct mm_struct *mm0 = mm_create(), *mm1; assert(mm0 != NULL && list_empty(&(mm0->mmap_list))); uintptr_t addr0, addr1; addr0 = 0; do { ret = mm_map(mm0, addr0, PTSIZE, 0, NULL); assert(ret == (USER_ACCESS(addr0, addr0 + PTSIZE)) ? 0 : -E_INVAL); addr0 += PTSIZE; } while (addr0 != 0); addr0 = 0; for (i = 0; i < 1024; i ++, addr0 += PTSIZE) { ret = mm_map(mm0, addr0, PGSIZE, 0, NULL); assert(ret == -E_INVAL); } mm_destroy(mm0); mm0 = mm_create(); assert(mm0 != NULL && list_empty(&(mm0->mmap_list))); addr0 = 0, i = 0; do { ret = mm_map(mm0, addr0, PTSIZE - PGSIZE, 0, NULL); assert(ret == (USER_ACCESS(addr0, addr0 + PTSIZE)) ? 0 : -E_INVAL); if (ret == 0) { i ++; } addr0 += PTSIZE; } while (addr0 != 0); addr0 = 0, j = 0; do { addr0 += PTSIZE - PGSIZE; ret = mm_map(mm0, addr0, PGSIZE, 0, NULL); assert(ret == (USER_ACCESS(addr0, addr0 + PGSIZE)) ? 0 : -E_INVAL); if (ret == 0) { j ++; } addr0 += PGSIZE; } while (addr0 != 0); assert(j + 1 >= i); mm_destroy(mm0); assert(nr_free_pages_store == nr_free_pages()); assert(slab_allocated_store == slab_allocated()); cprintf("check_mm_swap: step1, mm_map ok.\n"); // step2: check page fault mm0 = mm_create(); assert(mm0 != NULL && list_empty(&(mm0->mmap_list))); // setup page table struct Page *page = alloc_page(); assert(page != NULL); pde_t *pgdir = page2kva(page); memcpy(pgdir, boot_pgdir, PGSIZE); pgdir[PDX(VPT)] = PADDR(pgdir) | PTE_P | PTE_W; // prepare for page fault mm0->pgdir = pgdir; check_mm_struct = mm0; lcr3(PADDR(mm0->pgdir)); uint32_t vm_flags = VM_WRITE | VM_READ; struct vma_struct *vma; addr0 = 0; do { if ((ret = mm_map(mm0, addr0, PTSIZE, vm_flags, &vma)) == 0) { break; } addr0 += PTSIZE; } while (addr0 != 0); assert(ret == 0 && addr0 != 0 && mm0->map_count == 1); assert(vma->vm_start == addr0 && vma->vm_end == addr0 + PTSIZE); // check pte entry pte_t *ptep; for (addr1 = addr0; addr1 < addr0 + PTSIZE; addr1 += PGSIZE) { ptep = get_pte(pgdir, addr1, 0); assert(ptep == NULL); } memset((void *)addr0, 0xEF, PGSIZE * 2); ptep = get_pte(pgdir, addr0, 0); assert(ptep != NULL && (*ptep & PTE_P)); ptep = get_pte(pgdir, addr0 + PGSIZE, 0); assert(ptep != NULL && (*ptep & PTE_P)); ret = mm_unmap(mm0, - PTSIZE, PTSIZE); assert(ret == -E_INVAL); ret = mm_unmap(mm0, addr0 + PTSIZE, PGSIZE); assert(ret == 0); addr1 = addr0 + PTSIZE / 2; ret = mm_unmap(mm0, addr1, PGSIZE); assert(ret == 0 && mm0->map_count == 2); ret = mm_unmap(mm0, addr1 + 2 * PGSIZE, PGSIZE * 4); assert(ret == 0 && mm0->map_count == 3); ret = mm_map(mm0, addr1, PGSIZE * 6, 0, NULL); assert(ret == -E_INVAL); ret = mm_map(mm0, addr1, PGSIZE, 0, NULL); assert(ret == 0 && mm0->map_count == 4); ret = mm_map(mm0, addr1 + 2 * PGSIZE, PGSIZE * 4, 0, NULL); assert(ret == 0 && mm0->map_count == 5); ret = mm_unmap(mm0, addr1 + PGSIZE / 2, PTSIZE / 2 - PGSIZE); assert(ret == 0 && mm0->map_count == 1); addr1 = addr0 + PGSIZE; for (i = 0; i < PGSIZE; i ++) { assert(*(char *)(addr1 + i) == (char)0xEF); } ret = mm_unmap(mm0, addr1 + PGSIZE / 2, PGSIZE / 4); assert(ret == 0 && mm0->map_count == 2); ptep = get_pte(pgdir, addr0, 0); assert(ptep != NULL && (*ptep & PTE_P)); ptep = get_pte(pgdir, addr0 + PGSIZE, 0); assert(ptep != NULL && *ptep == 0); ret = mm_map(mm0, addr1, PGSIZE, vm_flags, NULL); memset((void *)addr1, 0x88, PGSIZE); assert(*(char *)addr1 == (char)0x88 && mm0->map_count == 3); for (i = 1; i < 16; i += 2) { ret = mm_unmap(mm0, addr0 + PGSIZE * i, PGSIZE); assert(ret == 0); if (i < 8) { ret = mm_map(mm0, addr0 + PGSIZE * i, PGSIZE, 0, NULL); assert(ret == 0); } } assert(mm0->map_count == 13); ret = mm_unmap(mm0, addr0 + PGSIZE * 2, PTSIZE - PGSIZE * 2); assert(ret == 0 && mm0->map_count == 2); ret = mm_unmap(mm0, addr0, PGSIZE * 2); assert(ret == 0 && mm0->map_count == 0); cprintf("check_mm_swap: step2, mm_unmap ok.\n"); // step3: check exit_mmap ret = mm_map(mm0, addr0, PTSIZE, vm_flags, NULL); assert(ret == 0); for (i = 0, addr1 = addr0; i < 4; i ++, addr1 += PGSIZE) { *(char *)addr1 = (char)0xFF; } exit_mmap(mm0); for (i = 0; i < PDX(KERNBASE); i ++) { assert(pgdir[i] == 0); } cprintf("check_mm_swap: step3, exit_mmap ok.\n"); // step4: check dup_mmap for (i = 0; i < max_swap_offset; i ++) { assert(mem_map[i] == SWAP_UNUSED); } ret = mm_map(mm0, addr0, PTSIZE, vm_flags, NULL); assert(ret != 0); addr1 = addr0; for (i = 0; i < 4; i ++, addr1 += PGSIZE) { *(char *)addr1 = (char)(i * i); } ret = 0; ret += swap_out_mm(mm0, 10); ret += swap_out_mm(mm0, 10); assert(ret == 4); for (; i < 8; i ++, addr1 += PGSIZE) { *(char *)addr1 = (char)(i * i); } // setup mm1 mm1 = mm_create(); assert(mm1 != NULL); page = alloc_page(); assert(page != NULL); pgdir = page2kva(page); memcpy(pgdir, boot_pgdir, PGSIZE); pgdir[PDX(VPT)] = PADDR(pgdir) | PTE_P | PTE_W; mm1->pgdir = pgdir; ret = dup_mmap(mm1, mm0); assert(ret == 0); // switch to mm1 check_mm_struct = mm1; lcr3(PADDR(mm1->pgdir)); addr1 = addr0; for (i = 0; i < 8; i ++, addr1 += PGSIZE) { assert(*(char *)addr1 == (char)(i * i)); *(char *)addr1 = (char)0x88; } // switch to mm0 check_mm_struct = mm0; lcr3(PADDR(mm0->pgdir)); addr1 = addr0; for (i = 0; i < 8; i ++, addr1 += PGSIZE) { assert(*(char *)addr1 == (char)(i * i)); } // switch to boot_cr3 check_mm_struct = NULL; lcr3(boot_cr3); // free memory exit_mmap(mm0); exit_mmap(mm1); free_page(kva2page(mm0->pgdir)); mm_destroy(mm0); free_page(kva2page(mm1->pgdir)); mm_destroy(mm1); cprintf("check_mm_swap: step4, dup_mmap ok.\n"); refill_inactive_scan(); page_launder(); for (i = 0; i < max_swap_offset; i ++) { assert(mem_map[i] == SWAP_UNUSED); } assert(nr_free_pages_store == nr_free_pages()); assert(slab_allocated_store == slab_allocated()); cprintf("check_mm_swap() succeeded.\n"); }
// check_swap - check the correctness of swap & page replacement algorithm static void check_swap(void) { size_t nr_free_pages_store = nr_free_pages(); size_t slab_allocated_store = slab_allocated(); size_t offset; for (offset = 2; offset < max_swap_offset; offset ++) { mem_map[offset] = 1; } struct mm_struct *mm = mm_create(); assert(mm != NULL); extern struct mm_struct *check_mm_struct; assert(check_mm_struct == NULL); check_mm_struct = mm; pde_t *pgdir = mm->pgdir = boot_pgdir; assert(pgdir[0] == 0); struct vma_struct *vma = vma_create(0, PTSIZE, VM_WRITE | VM_READ); assert(vma != NULL); insert_vma_struct(mm, vma); struct Page *rp0 = alloc_page(), *rp1 = alloc_page(); assert(rp0 != NULL && rp1 != NULL); uint32_t perm = PTE_U | PTE_W; int ret = page_insert(pgdir, rp1, 0, perm); assert(ret == 0 && page_ref(rp1) == 1); page_ref_inc(rp1); ret = page_insert(pgdir, rp0, 0, perm); assert(ret == 0 && page_ref(rp1) == 1 && page_ref(rp0) == 1); // check try_alloc_swap_entry swap_entry_t entry = try_alloc_swap_entry(); assert(swap_offset(entry) == 1); mem_map[1] = 1; assert(try_alloc_swap_entry() == 0); // set rp1, Swap, Active, add to hash_list, active_list swap_page_add(rp1, entry); swap_active_list_add(rp1); assert(PageSwap(rp1)); mem_map[1] = 0; entry = try_alloc_swap_entry(); assert(swap_offset(entry) == 1); assert(!PageSwap(rp1)); // check swap_remove_entry assert(swap_hash_find(entry) == NULL); mem_map[1] = 2; swap_remove_entry(entry); assert(mem_map[1] == 1); swap_page_add(rp1, entry); swap_inactive_list_add(rp1); swap_remove_entry(entry); assert(PageSwap(rp1)); assert(rp1->index == entry && mem_map[1] == 0); // check page_launder, move page from inactive_list to active_list assert(page_ref(rp1) == 1); assert(nr_active_pages == 0 && nr_inactive_pages == 1); assert(list_next(&(inactive_list.swap_list)) == &(rp1->swap_link)); page_launder(); assert(nr_active_pages == 1 && nr_inactive_pages == 0); assert(PageSwap(rp1) && PageActive(rp1)); entry = try_alloc_swap_entry(); assert(swap_offset(entry) == 1); assert(!PageSwap(rp1) && nr_active_pages == 0); assert(list_empty(&(active_list.swap_list))); // set rp1 inactive again assert(page_ref(rp1) == 1); swap_page_add(rp1, 0); assert(PageSwap(rp1) && swap_offset(rp1->index) == 1); swap_inactive_list_add(rp1); mem_map[1] = 1; assert(nr_inactive_pages == 1); page_ref_dec(rp1); size_t count = nr_free_pages(); swap_remove_entry(entry); assert(nr_inactive_pages == 0 && nr_free_pages() == count + 1); // check swap_out_mm pte_t *ptep0 = get_pte(pgdir, 0, 0), *ptep1; assert(ptep0 != NULL && pte2page(*ptep0) == rp0); ret = swap_out_mm(mm, 0); assert(ret == 0); ret = swap_out_mm(mm, 10); assert(ret == 1 && mm->swap_address == PGSIZE); ret = swap_out_mm(mm, 10); assert(ret == 0 && *ptep0 == entry && mem_map[1] == 1); assert(PageDirty(rp0) && PageActive(rp0) && page_ref(rp0) == 0); assert(nr_active_pages == 1 && list_next(&(active_list.swap_list)) == &(rp0->swap_link)); // check refill_inactive_scan() refill_inactive_scan(); assert(!PageActive(rp0) && page_ref(rp0) == 0); assert(nr_inactive_pages == 1 && list_next(&(inactive_list.swap_list)) == &(rp0->swap_link)); page_ref_inc(rp0); page_launder(); assert(PageActive(rp0) && page_ref(rp0) == 1); assert(nr_active_pages == 1 && list_next(&(active_list.swap_list)) == &(rp0->swap_link)); page_ref_dec(rp0); refill_inactive_scan(); assert(!PageActive(rp0)); // save data in rp0 int i; for (i = 0; i < PGSIZE; i ++) { ((char *)page2kva(rp0))[i] = (char)i; } page_launder(); assert(nr_inactive_pages == 0 && list_empty(&(inactive_list.swap_list))); assert(mem_map[1] == 1); rp1 = alloc_page(); assert(rp1 != NULL); ret = swapfs_read(entry, rp1); assert(ret == 0); for (i = 0; i < PGSIZE; i ++) { assert(((char *)page2kva(rp1))[i] == (char)i); } // page fault now *(char *)0 = 0xEF; rp0 = pte2page(*ptep0); assert(page_ref(rp0) == 1); assert(PageSwap(rp0) && PageActive(rp0)); entry = try_alloc_swap_entry(); assert(swap_offset(entry) == 1 && mem_map[1] == SWAP_UNUSED); assert(!PageSwap(rp0) && nr_active_pages == 0 && nr_inactive_pages == 0); // clear accessed flag assert(rp0 == pte2page(*ptep0)); assert(!PageSwap(rp0)); ret = swap_out_mm(mm, 10); assert(ret == 0); assert(!PageSwap(rp0) && (*ptep0 & PTE_P)); // change page table ret = swap_out_mm(mm, 10); assert(ret == 1); assert(*ptep0 == entry && page_ref(rp0) == 0 && mem_map[1] == 1); count = nr_free_pages(); refill_inactive_scan(); page_launder(); assert(count + 1 == nr_free_pages()); ret = swapfs_read(entry, rp1); assert(ret == 0 && *(char *)(page2kva(rp1)) == (char)0xEF); free_page(rp1); // duplictate *ptep0 ptep1 = get_pte(pgdir, PGSIZE, 0); assert(ptep1 != NULL && *ptep1 == 0); swap_duplicate(*ptep0); *ptep1 = *ptep0; // page fault again *(char *)0 = 0xFF; *(char *)(PGSIZE + 1) = 0x88; assert(pte2page(*ptep0) == pte2page(*ptep1)); rp0 = pte2page(*ptep0); assert(*(char *)1 == (char)0x88 && *(char *)PGSIZE == (char)0xFF); assert(page_ref(rp0) == 2 && rp0->index == entry && mem_map[1] == 0); assert(PageSwap(rp0) && PageActive(rp0)); entry = try_alloc_swap_entry(); assert(swap_offset(entry) == 1 && mem_map[1] == SWAP_UNUSED); assert(!PageSwap(rp0)); assert(list_empty(&(active_list.swap_list))); assert(list_empty(&(inactive_list.swap_list))); // check swap_out_mm *(char *)0 = *(char *)PGSIZE = 0xEE; mm->swap_address = PGSIZE * 2; ret = swap_out_mm(mm, 2); assert(ret == 0); assert((*ptep0 & PTE_P) && !(*ptep0 & PTE_A)); assert((*ptep1 & PTE_P) && !(*ptep1 & PTE_A)); ret = swap_out_mm(mm, 2); assert(ret == 2); assert(mem_map[1] == 2 && page_ref(rp0) == 0); refill_inactive_scan(); page_launder(); assert(mem_map[1] == 2 && swap_hash_find(entry) == NULL); // check copy entry swap_remove_entry(entry); *ptep1 = 0; assert(mem_map[1] == 1); swap_entry_t store; ret = swap_copy_entry(entry, &store); assert(ret == -E_NO_MEM); mem_map[2] = SWAP_UNUSED; ret = swap_copy_entry(entry, &store); assert(ret == 0 && swap_offset(store) == 2 && mem_map[2] == 0); mem_map[2] = 1; *ptep1 = store; assert(*(char *)PGSIZE == (char)0xEE && *(char *)(PGSIZE + 1)== (char)0x88); *(char *)PGSIZE = 1, *(char *)(PGSIZE + 1) = 2; assert(*(char *)0 == (char)0xEE && *(char *)1 == (char)0x88); ret = swap_in_page(entry, &rp0); assert(ret == 0); ret = swap_in_page(store, &rp1); assert(ret == 0); assert(rp1 != rp0); // free memory swap_list_del(rp0), swap_list_del(rp1); swap_page_del(rp0), swap_page_del(rp1); assert(page_ref(rp0) == 1 && page_ref(rp1) == 1); assert(nr_active_pages == 0 && list_empty(&(active_list.swap_list))); assert(nr_inactive_pages == 0 && list_empty(&(inactive_list.swap_list))); for (i = 0; i < HASH_LIST_SIZE; i ++) { assert(list_empty(hash_list + i)); } page_remove(pgdir, 0); page_remove(pgdir, PGSIZE); free_page(pa2page(pgdir[0])); pgdir[0] = 0; mm->pgdir = NULL; mm_destroy(mm); check_mm_struct = NULL; assert(nr_active_pages == 0 && nr_inactive_pages == 0); for (offset = 0; offset < max_swap_offset; offset ++) { mem_map[offset] = SWAP_UNUSED; } assert(nr_free_pages_store == nr_free_pages()); assert(slab_allocated_store == slab_allocated()); cprintf("check_swap() succeeded.\n"); }
static void check_mm_shm_swap(void) { size_t nr_free_pages_store = nr_free_pages(); size_t slab_allocated_store = slab_allocated(); int ret, i; for (i = 0; i < max_swap_offset; i ++) { assert(mem_map[i] == SWAP_UNUSED); } extern struct mm_struct *check_mm_struct; assert(check_mm_struct == NULL); struct mm_struct *mm0 = mm_create(), *mm1; assert(mm0 != NULL && list_empty(&(mm0->mmap_list))); struct Page *page = alloc_page(); assert(page != NULL); pde_t *pgdir = page2kva(page); memcpy(pgdir, boot_pgdir, PGSIZE); pgdir[PDX(VPT)] = PADDR(pgdir) | PTE_P | PTE_W; mm0->pgdir = pgdir; check_mm_struct = mm0; lcr3(PADDR(mm0->pgdir)); uint32_t vm_flags = VM_WRITE | VM_READ; uintptr_t addr0, addr1; addr0 = 0; do { if ((ret = mm_map(mm0, addr0, PTSIZE * 4, vm_flags, NULL)) == 0) { break; } addr0 += PTSIZE; } while (addr0 != 0); assert(ret == 0 && addr0 != 0 && mm0->map_count == 1); ret = mm_unmap(mm0, addr0, PTSIZE * 4); assert(ret == 0 && mm0->map_count == 0); struct shmem_struct *shmem = shmem_create(PTSIZE * 2); assert(shmem != NULL && shmem_ref(shmem) == 0); // step1: check share memory struct vma_struct *vma; addr1 = addr0 + PTSIZE * 2; ret = mm_map_shmem(mm0, addr0, vm_flags, shmem, &vma); assert(ret == 0); assert((vma->vm_flags & VM_SHARE) && vma->shmem == shmem && shmem_ref(shmem) == 1); ret = mm_map_shmem(mm0, addr1, vm_flags, shmem, &vma); assert(ret == 0); assert((vma->vm_flags & VM_SHARE) && vma->shmem == shmem && shmem_ref(shmem) == 2); // page fault for (i = 0; i < 4; i ++) { *(char *)(addr0 + i * PGSIZE) = (char)(i * i); } for (i = 0; i < 4; i ++) { assert(*(char *)(addr1 + i * PGSIZE) == (char)(i * i)); } for (i = 0; i < 4; i ++) { *(char *)(addr1 + i * PGSIZE) = (char)(- i * i); } for (i = 0; i < 4; i ++) { assert(*(char *)(addr1 + i * PGSIZE) == (char)(- i * i)); } // check swap ret = swap_out_mm(mm0, 8) + swap_out_mm(mm0, 8); assert(ret == 8 && nr_active_pages == 4 && nr_inactive_pages == 0); refill_inactive_scan(); assert(nr_active_pages == 0 && nr_inactive_pages == 4); // write & read again memset((void *)addr0, 0x77, PGSIZE); for (i = 0; i < PGSIZE; i ++) { assert(*(char *)(addr1 + i) == (char)0x77); } // check unmap ret = mm_unmap(mm0, addr1, PGSIZE * 4); assert(ret == 0); addr0 += 4 * PGSIZE, addr1 += 4 * PGSIZE; *(char *)(addr0) = (char)(0xDC); assert(*(char *)(addr1) == (char)(0xDC)); *(char *)(addr1 + PTSIZE) = (char)(0xDC); assert(*(char *)(addr0 + PTSIZE) == (char)(0xDC)); cprintf("check_mm_shm_swap: step1, share memory ok.\n"); // setup mm1 mm1 = mm_create(); assert(mm1 != NULL); page = alloc_page(); assert(page != NULL); pgdir = page2kva(page); memcpy(pgdir, boot_pgdir, PGSIZE); pgdir[PDX(VPT)] = PADDR(pgdir) | PTE_P | PTE_W; mm1->pgdir = pgdir; ret = dup_mmap(mm1, mm0); assert(ret == 0 && shmem_ref(shmem) == 4); // switch to mm1 check_mm_struct = mm1; lcr3(PADDR(mm1->pgdir)); for (i = 0; i < 4; i ++) { *(char *)(addr0 + i * PGSIZE) = (char)(0x57 + i); } for (i = 0; i < 4; i ++) { assert(*(char *)(addr1 + i * PGSIZE) == (char)(0x57 + i)); } check_mm_struct = mm0; lcr3(PADDR(mm0->pgdir)); for (i = 0; i < 4; i ++) { assert(*(char *)(addr0 + i * PGSIZE) == (char)(0x57 + i)); assert(*(char *)(addr1 + i * PGSIZE) == (char)(0x57 + i)); } swap_out_mm(mm1, 4); exit_mmap(mm1); free_page(kva2page(mm1->pgdir)); mm_destroy(mm1); assert(shmem_ref(shmem) == 2); cprintf("check_mm_shm_swap: step2, dup_mmap ok.\n"); // free memory check_mm_struct = NULL; lcr3(boot_cr3); exit_mmap(mm0); free_page(kva2page(mm0->pgdir)); mm_destroy(mm0); refill_inactive_scan(); page_launder(); for (i = 0; i < max_swap_offset; i ++) { assert(mem_map[i] == SWAP_UNUSED); } assert(nr_free_pages_store == nr_free_pages()); assert(slab_allocated_store == slab_allocated()); cprintf("check_mm_shm_swap() succeeded.\n"); }
static int ak47_write_proc(struct file *file, const char __user * buffer, unsigned long count, void *data) { #define MAX_INPUT_LEN 128 unsigned char buf[MAX_INPUT_LEN] = { 0 }; unsigned char bufCMD[MAX_INPUT_LEN] = { 0 }; int i; printk(KERN_ERR "SRT AK47 12.10! \n"); if (ak47_dev) { memset(buf, 0, MAX_INPUT_LEN); if (count > 0 && count < MAX_INPUT_LEN) { copy_from_user(buf, buffer, count); printk(KERN_ERR "SRT AK47 buffer: %s \n", buf); unsigned char *sep = strstr(buf, " "); if (NULL == sep) { printk(KERN_ERR "SRT AK47 error 1! \n"); return; } strncpy(bufCMD, buf, sep - buf); printk(KERN_ERR "SRT AK47 %s! \n", bufCMD); if (strcmp(bufCMD, "plugin") == 0) { /*sprd_srt_sdcard_plug(0);*/ } if (strcmp(bufCMD, "plugout") == 0) { /*sprd_srt_sdcard_plug(1);*/ } if (strcmp(bufCMD, "emmcpm") == 0) { printk(KERN_ERR "SRT do EMMCPM test! \n"); char cmd[32] = { 0 }; strcpy(cmd, sep + 1); /*sprd_srt_emmc_test(1,simple_strtol(sep + 1, NULL,10));*/ } if (strcmp(bufCMD, "emmcpmrt") == 0) { char cmd[32] = { 0 }; strcpy(cmd, sep + 1); /*sprd_srt_emmc_test(0,simple_strtol(sep + 1, NULL,10));*/ } if (strcmp(bufCMD, "getfreepage") == 0) { printk(KERN_ERR "AK47 getfreepage \n"); void *p = __get_free_page(GFP_KERNEL); if (NULL == p) { printk(KERN_ERR "AK47 getfreepage [%d] k failed\n", 1); } else { pagec++; printk("AK47 getfreepage addr=%x", p); } } if (strcmp(bufCMD, "kmalloc") == 0) { printk(KERN_ERR "AK47 kmalloc [%d] k\n", simple_strtol(sep + 1, NULL, 10) * 4); void *p = kmalloc(simple_strtol(sep + 1, NULL, 10) * 1024 * 4, GFP_KERNEL); if (NULL == p) { printk(KERN_ERR "AK47 kmalloc [%d] k failed\n", simple_strtol(sep + 1, NULL, 10) * 4); } else { char *pc = (char *)p; memset(pc, 0, 255); strcpy(pc, "kmallocstring"); printk("AK47 kmalloc addr=%x,%s", p, pc); } } if (strcmp(bufCMD, "vmalloc") == 0) { printk(KERN_ERR "AK47 vmalloc [%d] k\n", simple_strtol(sep + 1, NULL, 10) * 4); void *p = vmalloc(simple_strtol(sep + 1, NULL, 10) * 1024 * 4); if (NULL == p) { printk(KERN_ERR "AK47 vmalloc [%d] k failed\n", simple_strtol(sep + 1, NULL, 10) * 4); } else { printk("AK47 vmalloc addr=%x", p); } } if (strcmp(bufCMD, "kstart") == 0) { printk(KERN_ERR "AK47 ksatrt [%s] \n", sep + 1); int s = simple_strtol(sep + 1, NULL, 10); { struct task_struct *my_thread = NULL; int rc; my_thread = kthread_run(thread_func, s, "srtkot"); if (IS_ERR(my_thread)) { rc = PTR_ERR(my_thread); printk ("AK47 error %d create kthread thread\n", rc); } else { printk ("AK47 create kthread ok\n"); } } } if (strcmp(bufCMD, "printk") == 0) { printk(KERN_ERR "AK47 printk [%s] \n", sep + 1); } if (strcmp(bufCMD, "inputkey") == 0) { printk(KERN_ERR "AK47 inputkey [%s] \n", sep + 1); int param_size = strlen(sep + 1); unsigned char *keyBuf = sep + 1; for (i = 0; i < param_size; i++) { int key = 0; if ('u' == keyBuf[i]) { key = KEY_VOLUMEUP; } if ('d' == keyBuf[i]) { key = KEY_VOLUMEDOWN; } input_report_key(ak47_dev, key, 1); input_report_key(ak47_dev, key, 0); input_sync(ak47_dev); printk(KERN_ERR "AK47 inputkey ok"); } } if (strcmp(bufCMD, "slub") == 0) { mm_create(); mm_destroy(); } } } return count; }