long dependent_swap<dtype>::write(FILE *fileptr) { sub_1d_type npages; sub_1d_type nwritten=0; sub_1d_type sub; //if the current swap file stream is null, then set it to fileptr //and advance the byte location forward the size of the dataset: if (swap == NULL) { swap=fileptr; swap_start=ftell(swap); fseek(swap, this->n_data*sizeof(dtype), SEEK_CUR); return this->n_data*sizeof(dtype); } //write out all the data: npages=this->n_data/page_size; for (sub_1d_type i=0; i<npages; i++) { sub=i*page_size; check_page(sub); nwritten+=fwrite(this->data, sizeof(dtype), page_size, fileptr); } sub=npages*page_size; if (check_page(sub) != -1) { nwritten+=fwrite(this->data, sizeof(dtype), this->n_data-sub, fileptr); } return nwritten; }
void writer(int num) { uint i; uchar *buff; PAGECACHE_BLOCK_LINK *link; for (i= 0; i < number_of_write_tests; i++) { uchar c= (uchar) rand() % 256; if (i % report_divisor == 0) diag("Writer %d - %u", num, i); buff= pagecache_read(&pagecache, &file1, 0, 3, NULL, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_WRITE, &link); check_page(buff, num); bfill(buff, TEST_PAGE_SIZE / 2, c); SLEEP; bfill(buff + TEST_PAGE_SIZE/2, TEST_PAGE_SIZE / 2, c); check_page(buff, num); pagecache_unlock_by_link(&pagecache, link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, 0, 0, 1, FALSE); SLEEP; } }
static void check_page(struct btree_page *p, const void *lbound, const void *ubound, int height) { const struct btree_def *def = p->def; int i; assert (p); assert (p->height == height); if (p != p->owner->root) { assert (p->num_children >= def->branches / 2); assert (p->num_children <= def->branches); } for (i = 0; i < p->num_children; i++) { const void *key = PAGE_KEY(p, i); const void *next_key = ubound; if (i + 1 < p->num_children) next_key = PAGE_KEY(p, i + 1); assert (def->compare(key, lbound) >= 0); if (next_key) { assert (def->compare(key, next_key) < 0); } if (ubound) { assert (def->compare(key, ubound) < 0); } if (p->height) check_page(*PAGE_PTR(p, i), key, next_key, height - 1); } }
void reader(int num) { unsigned char *buff; uint i; PAGECACHE_BLOCK_LINK *link; for (i= 0; i < number_of_read_tests; i++) { if (i % report_divisor == 0) diag("Reader %d - %u", num, i); buff= pagecache_read(&pagecache, &file1, 0, 3, NULL, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_READ, &link); check_page(buff, num); pagecache_unlock_by_link(&pagecache, link, PAGECACHE_LOCK_READ_UNLOCK, PAGECACHE_UNPIN, 0, 0, 0, FALSE); { int lim= rand() % read_sleep_limit; int j; for (j= 0; j < lim; j++) SLEEP; } } }
void writer(int num) { unsigned char *buffr= malloc(TEST_PAGE_SIZE); uint i; for (i= 0; i < number_of_tests; i++) { uint end; uint page= get_len(number_of_pages); pagecache_read(&pagecache, &file1, page, 3, buffr, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_WRITE, 0); end= check_page(buffr, page * TEST_PAGE_SIZE, 1, page, num); put_rec(buffr, end, get_len(record_length_limit), num); pagecache_write(&pagecache, &file1, page, 3, buffr, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, PAGECACHE_WRITE_DELAY, 0, LSN_IMPOSSIBLE); if (i % flush_divider == 0) flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE); } free(buffr); }
static void check_btree(btree_t bt) { assert (bt->def); if (bt->root->height) { assert (bt->root->num_children >= 2); } check_page(bt->root, bt->def->zero, NULL, bt->root->height); }
void free(void *ptr) { t_block *b; if (ptr == NULL) return ; b = search_ptr(ptr); if (b == NULL) return ; b = fusion_block(b); check_page(b); }
void reader(int num) { unsigned char buff[TEST_PAGE_SIZE]; uint i; for (i= 0; i < number_of_read_tests; i++) { if (i % report_divisor == 0) diag("Reader %d - %u", num, i); pagecache_read(&pagecache, &file1, 0, 3, buff, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_LEFT_UNLOCKED, NULL); check_page(buff, num); } }
void reader(int num) { unsigned char *buffr= malloc(TEST_PAGE_SIZE); uint i; for (i= 0; i < number_of_tests; i++) { uint page= get_len(number_of_pages); pagecache_read(&pagecache, &file1, page, 3, buffr, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_LEFT_UNLOCKED, 0); check_page(buffr, page * TEST_PAGE_SIZE, 0, page, -num); } free(buffr); }
void test_pack(const int *pl, const int **headers){ unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */ long inptr=0; long outptr=0; long deptr=0; long depacket=0; long granule_pos=7,pageno=0; int i,j,packets,pageout=0; int eosflag=0; int bosflag=0; ogg_stream_reset(&os_en); ogg_stream_reset(&os_de); ogg_sync_reset(&oy); for(packets=0;;packets++)if(pl[packets]==-1)break; for(i=0;i<packets;i++){ /* construct a test packet */ ogg_packet op; int len=pl[i]; op.packet=data+inptr; op.bytes=len; op.e_o_s=(pl[i+1]<0?1:0); op.granulepos=granule_pos; granule_pos+=1024; for(j=0;j<len;j++)data[inptr++]=i+j; /* submit the test packet */ ogg_stream_packetin(&os_en,&op); /* retrieve any finished pages */ { ogg_page og; while(ogg_stream_pageout(&os_en,&og)){ /* We have a page. Check it carefully */ fprintf(stderr,"%ld, ",pageno); if(headers[pageno]==NULL){ fprintf(stderr,"coded too many pages!\n"); exit(1); } check_page(data+outptr,headers[pageno],&og); outptr+=og.body_len; pageno++; /* have a complete page; submit it to sync/decode */ { ogg_page og_de; ogg_packet op_de,op_de2; char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len); memcpy(buf,og.header,og.header_len); memcpy(buf+og.header_len,og.body,og.body_len); ogg_sync_wrote(&oy,og.header_len+og.body_len); while(ogg_sync_pageout(&oy,&og_de)>0){ /* got a page. Happy happy. Verify that it's good. */ check_page(data+deptr,headers[pageout],&og_de); deptr+=og_de.body_len; pageout++; /* submit it to deconstitution */ ogg_stream_pagein(&os_de,&og_de); /* packets out? */ while(ogg_stream_packetpeek(&os_de,&op_de2)>0){ ogg_stream_packetpeek(&os_de,NULL); ogg_stream_packetout(&os_de,&op_de); /* just catching them all */ /* verify peek and out match */ if(memcmp(&op_de,&op_de2,sizeof(op_de))){ fprintf(stderr,"packetout != packetpeek! pos=%ld\n", depacket); exit(1); } /* verify the packet! */ /* check data */ if(memcmp(data+depacket,op_de.packet,op_de.bytes)){ fprintf(stderr,"packet data mismatch in decode! pos=%ld\n", depacket); exit(1); } /* check bos flag */ if(bosflag==0 && op_de.b_o_s==0){ fprintf(stderr,"b_o_s flag not set on packet!\n"); exit(1); } if(bosflag && op_de.b_o_s){ fprintf(stderr,"b_o_s flag incorrectly set on packet!\n"); exit(1); } bosflag=1; depacket+=op_de.bytes; /* check eos flag */ if(eosflag){ fprintf(stderr,"Multiple decoded packets with eos flag!\n"); exit(1); } if(op_de.e_o_s)eosflag=1; /* check granulepos flag */ if(op_de.granulepos!=-1){ fprintf(stderr," granule:%ld ",(long)op_de.granulepos); } } } } } } } _ogg_free(data); if(headers[pageno]!=NULL){ fprintf(stderr,"did not write last page!\n"); exit(1); } if(headers[pageout]!=NULL){ fprintf(stderr,"did not decode last page!\n"); exit(1); } if(inptr!=outptr){ fprintf(stderr,"encoded page data incomplete!\n"); exit(1); } if(inptr!=deptr){ fprintf(stderr,"decoded page data incomplete!\n"); exit(1); } if(inptr!=depacket){ fprintf(stderr,"decoded packet data incomplete!\n"); exit(1); } if(!eosflag){ fprintf(stderr,"Never got a packet with EOS set!\n"); exit(1); } fprintf(stderr,"ok.\n"); }
// Set up a two-level page table: // kern_pgdir is its linear (virtual) address of the root // // This function only sets up the kernel part of the address space // (ie. addresses >= UTOP). The user part of the address space // will be setup later. // // From UTOP to ULIM, the user is allowed to read but not write. // Above ULIM the user cannot read or write. void mem_init(void) { uint32_t cr0; size_t n; // Find out how much memory the machine has (npages & npages_basemem). i386_detect_memory(); ////////////////////////////////////////////////////////////////////// // create initial page directory. kern_pgdir = (pde_t *) boot_alloc(PGSIZE); memset(kern_pgdir, 0, PGSIZE); ////////////////////////////////////////////////////////////////////// // Recursively insert PD in itself as a page table, to form // a virtual page table at virtual address UVPT. // (For now, you don't have understand the greater purpose of the // following line.) // Permissions: kernel R, user R kern_pgdir[PDX(UVPT)] = PADDR(kern_pgdir) | PTE_U | PTE_P; ////////////////////////////////////////////////////////////////////// // Allocate an array of npages 'struct Page's and store it in 'pages'. // The kernel uses this array to keep track of physical pages: for // each physical page, there is a corresponding struct Page in this // array. 'npages' is the number of physical pages in memory. // Your code goes here: pages = boot_alloc(npages*sizeof(* pages)); ////////////////////////////////////////////////////////////////////// // Make 'envs' point to an array of size 'NENV' of 'struct Env'. // LAB 3: Your code here. envs = boot_alloc(NENV * sizeof(* envs)); ////////////////////////////////////////////////////////////////////// // Now that we've allocated the initial kernel data structures, we set // up the list of free physical pages. Once we've done so, all further // memory management will go through the page_* functions. In // particular, we can now map memory using boot_map_region // or page_insert page_init(); check_page_free_list(1); check_page_alloc(); check_page(); ////////////////////////////////////////////////////////////////////// // Now we set up virtual memory ////////////////////////////////////////////////////////////////////// // Map 'pages' read-only by the user at linear address UPAGES // Permissions: // - the new image at UPAGES -- kernel R, user R // (ie. perm = PTE_U | PTE_P) // - pages itself -- kernel RW, user NONE // Your code goes here: boot_map_region( kern_pgdir, (uintptr_t) UPAGES, npages*(sizeof(* pages)), PADDR(pages), PTE_U | PTE_P); boot_map_region( kern_pgdir, (uintptr_t) pages, npages*(sizeof(* pages)), PADDR(pages), PTE_W | PTE_P); ////////////////////////////////////////////////////////////////////// // Map the 'envs' array read-only by the user at linear address UENVS // (ie. perm = PTE_U | PTE_P). // Permissions: // - the new image at UENVS -- kernel R, user R // - envs itself -- kernel RW, user NONE // LAB 3: Your code here. boot_map_region( kern_pgdir, (uintptr_t) UENVS, npages*(sizeof(* envs)), PADDR(envs), PTE_U | PTE_P); boot_map_region( kern_pgdir, (uintptr_t) envs, npages*(sizeof(* envs)), PADDR(envs), PTE_W | PTE_P); ////////////////////////////////////////////////////////////////////// // Use the physical memory that 'bootstack' refers to as the kernel // stack. The kernel stack grows down from virtual address KSTACKTOP. // We consider the entire range from [KSTACKTOP-PTSIZE, KSTACKTOP) // to be the kernel stack, but break this into two pieces: // * [KSTACKTOP-KSTKSIZE, KSTACKTOP) -- backed by physical memory // * [KSTACKTOP-PTSIZE, KSTACKTOP-KSTKSIZE) -- not backed; so if // the kernel overflows its stack, it will fault rather than // overwrite memory. Known as a "guard page". // Permissions: kernel RW, user NONE // Your code goes here: boot_map_region( kern_pgdir, KSTACKTOP-KSTKSIZE, KSTKSIZE, PADDR(bootstack), PTE_W | PTE_P ); ////////////////////////////////////////////////////////////////////// // Map all of physical memory at KERNBASE. // Ie. the VA range [KERNBASE, 2^32) should map to // the PA range [0, 2^32 - KERNBASE) // We might not have 2^32 - KERNBASE bytes of physical memory, but // we just set up the mapping anyway. // Permissions: kernel RW, user NONE // Your code goes here: boot_map_region( kern_pgdir, (uintptr_t) KERNBASE, 0xFFFFFFFF, 0, PTE_W | PTE_P); // Initialize the SMP-related parts of the memory map mem_init_mp(); // Check that the initial page directory has been set up correctly. check_kern_pgdir(); // Switch from the minimal entry page directory to the full kern_pgdir // page table we just created. Our instruction pointer should be // somewhere between KERNBASE and KERNBASE+4MB right now, which is // mapped the same way by both page tables. // // If the machine reboots at this point, you've probably set up your // kern_pgdir wrong. lcr3(PADDR(kern_pgdir)); check_page_free_list(0); // entry.S set the really important flags in cr0 (including enabling // paging). Here we configure the rest of the flags that we care about. cr0 = rcr0(); cr0 |= CR0_PE|CR0_PG|CR0_AM|CR0_WP|CR0_NE|CR0_MP; cr0 &= ~(CR0_TS|CR0_EM); lcr0(cr0); // Some more checks, only possible after kern_pgdir is installed. check_page_installed_pgdir(); }
int main(int argc, char **argv) { int i, m, n, lim, chk, page_format; FILE *fi, *fo, *f1, *f2; /* print usage */ if (argc < 3) { printf("usage: %s <infile> <outfile> [options]\n", argv[0]); printf("options:\n"); printf(" -b <buffer-number> set buffer number, default and maximum value is 130\n"); printf(" -db enable double buffering\n"); printf(" -p output 1kb pages (task 2)\n"); printf(" -c check correctness when sort completed (debug)\n"); printf(" -l <record-number> sort first <record-number> records (debug)\n"); return -1; } /* get arguments */ k = K; lim = 0x7fffffff; db = chk = page_format = 0; for (i = 3; i < argc; i++) { if (!strcmp(argv[i], "-b")) { sscanf(argv[++i], "%d", &k); if (k > K) { fprintf(stderr, "error: too many buffer pages."); return -1; } } else if (!strcmp(argv[i], "-l")) { sscanf(argv[++i], "%d", &lim); } else if (!strcmp(argv[i], "-c")) { chk = 1; } else if (!strcmp(argv[i], "-db")) { db = 1; } else if (!strcmp(argv[i], "-p")) { page_format = 1; } } k = k / (db + 1) - 1; if (k < 2) { fprintf(stderr, "error: too few buffer pages."); return -1; } /* open files */ fi = fopen(argv[1], "rb+"); if (!fi) { fprintf(stderr, "error: file '%s' is not found.\n", argv[1]); return -1; } if (!page_format) { if (!strcmp(argv[1], argv[2])) { fprintf(stderr, "error: infile cannot be the same as outfile.\n"); return -1; } fo = fopen(argv[2], "wb+"); } f1 = tmpfile(); f2 = tmpfile(); /* confirm arguments */ printf("buffer pages: %d\n", (k + 1) * (db + 1)); printf("double buffering: %s\n", db ? "yes" : "no"); printf("output 1kb pages: %s\n", page_format ? "yes" : "no"); /* start timer */ time_t start = time(0); puts("sorting..."); /* init mutex, semaphore */ if (db) { for (i = 0; i <= K; i++) { pthread_mutex_init(&mutex[i], 0); sem_init(&sem[i], 0, 0); } } /* extract useful data, quick sort pages individualy */ struct line line; for (n = 0; !feof(fi) && n < lim;) { buffer[0][n % M].p = ftell(fi); line_read(fi, &line); buffer[0][n % M].x = line.x; buffer[0][n % M].y = line.y; n++; if (n % M == 0 || feof(fi) || n == lim) { int num = n % M ? n % M : M; qsort(buffer[0], num, S, record_cmp); fwrite(buffer[0], S, num, f1); } } /* merge sort */ if (db) merge_sort_db(f1, f2, 1, 0, n); else merge_sort(f1, f2, 1, 0, n); /* format from useful data to real data */ if (page_format) format_page(argv[2], f1, fi, n); else format(fo, f1, fi, n); /* stop timer */ time_t end = time(0); int sec = (int)difftime(end, start); printf("completed, time elapsed: %d min %d sec\n", sec / 60, sec % 60); /* check correctness */ if (chk) { printf("checking correctness: "); fflush(stdout); if (page_format ? check_page(argv[2]) : check(fo)) puts("yes"); else puts("no"); } /* close files */ fclose(f1); fclose(f2); fclose(fi); if (!page_format) fclose(fo); return 0; }
static void child(void) { size_t i; char *ptr; unsigned int usage, old_limit, old_memsw_limit; int status, pid, retries = 0; SAFE_MKDIR(cgroup_path, 0777); SAFE_FILE_PRINTF(tasks_path, "%i", getpid()); ptr = SAFE_MMAP(NULL, PAGES * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); for (i = 0; i < PAGES * page_size; i++) ptr[i] = 'a'; if (madvise(ptr, PAGES * page_size, MADV_FREE)) { if (errno == EINVAL) tst_brk(TCONF | TERRNO, "MADV_FREE is not supported"); tst_brk(TBROK | TERRNO, "MADV_FREE failed"); } if (ptr[page_size] != 'a') tst_res(TFAIL, "MADV_FREE pages were freed immediatelly"); else tst_res(TPASS, "MADV_FREE pages were not freed immediatelly"); ptr[TOUCHED_PAGE1 * page_size] = 'b'; ptr[TOUCHED_PAGE2 * page_size] = 'b'; usage = 8 * 1024 * 1024; tst_res(TINFO, "Setting memory limits to %u %u", usage, 2 * usage); SAFE_FILE_SCANF(limit_in_bytes_path, "%u", &old_limit); if (swap_accounting_enabled) SAFE_FILE_SCANF(memsw_limit_in_bytes_path, "%u", &old_memsw_limit); SAFE_FILE_PRINTF(limit_in_bytes_path, "%u", usage); if (swap_accounting_enabled) SAFE_FILE_PRINTF(memsw_limit_in_bytes_path, "%u", 2 * usage); do { sleep_between_faults++; pid = SAFE_FORK(); if (!pid) memory_pressure_child(); tst_res(TINFO, "Memory hungry child %i started, try %i", pid, retries); SAFE_WAIT(&status); } while (retries++ < 10 && count_freed(ptr) == 0); char map[PAGES+1]; unsigned int freed = 0; unsigned int corrupted = 0; for (i = 0; i < PAGES; i++) { char exp_val; if (ptr[i * page_size]) { exp_val = 'a'; map[i] = 'p'; } else { exp_val = 0; map[i] = '_'; freed++; } if (i != TOUCHED_PAGE1 && i != TOUCHED_PAGE2) { if (check_page(ptr + i * page_size, exp_val)) { map[i] = '?'; corrupted++; } } else { if (check_page_baaa(ptr + i * page_size)) { map[i] = '?'; corrupted++; } } } map[PAGES] = '\0'; tst_res(TINFO, "Memory map: %s", map); if (freed) tst_res(TPASS, "Pages MADV_FREE were freed on low memory"); else tst_res(TFAIL, "No MADV_FREE page was freed on low memory"); if (corrupted) tst_res(TFAIL, "Found corrupted page"); else tst_res(TPASS, "All pages have expected content"); if (swap_accounting_enabled) SAFE_FILE_PRINTF(memsw_limit_in_bytes_path, "%u", old_memsw_limit); SAFE_FILE_PRINTF(limit_in_bytes_path, "%u", old_limit); SAFE_MUNMAP(ptr, PAGES); exit(0); }
int spimem_write_h(uint8_t spi_chip, uint32_t addr, uint8_t* data_buff, uint32_t size) { uint32_t size1, size2, low, dirty = 0, page, sect_num, check; if (size > 256) // Invalid size to write. return -2; if (addr > 0xFFFFF) // Invalid address to write to. return -2; low = addr & 0x000000FF; if ((size + low) > 256) // Requested write flows into a second page. { size1 = 256 - low; size2 = size - size1; } else { size1 = size; size2 = 0; } if ((addr + (size - 1)) > 0xFFFFF) // Address too high, can't write all requested bytes. { size1 = 256 - low; size2 = 0; } if (xSemaphoreTake(Spi0_Mutex, (TickType_t) 1) == pdTRUE) // Only Block for a single tick. { enter_atomic(); // Atomic operation begins. if(ready_for_command_h(spi_chip) != 1) { exit_atomic(); xSemaphoreGive(Spi0_Mutex); return -4; } page = get_page(addr); dirty = check_page(page); if(dirty) { sect_num = get_sector(addr); check = load_sector_into_spibuffer(spi_chip, sect_num); // if check != 4096, FAILURE_RECOVERY. check = update_spibuffer_with_new_page(addr, data_buff, size1); // if check != size1, FAILURE_RECOVERY. check = erase_sector_on_chip(spi_chip, sect_num); // FAILURE_RECOVERY check = write_sector_back_to_spimem(spi_chip); // FAILURE_RECOVERY } else { if(write_page_h(spi_chip, addr, data_buff, size1) != 1) { exit_atomic(); // Atomic operation ends. xSemaphoreGive(Spi0_Mutex); return -1; } } if(size2) // Requested write flows into a second page. { page = get_page(addr + size1); dirty = check_page(page); if(ready_for_command_h(spi_chip) != 1) { exit_atomic(); xSemaphoreGive(Spi0_Mutex); return size1; } if(dirty) { sect_num = get_sector(addr + size1); check = load_sector_into_spibuffer(spi_chip, sect_num); // if check != 4096, FAILURE_RECOVERY. if(check != 4096) return -4; check = update_spibuffer_with_new_page(addr + size1, (data_buff + size1), size2); // if check != size1, FAILURE_RECOVERY. if(check != size1) return -4; check = erase_sector_on_chip(spi_chip, sect_num); // FAILURE_RECOVERY if(check != 1) return -4; check = write_sector_back_to_spimem(spi_chip); // FAILURE_RECOVERY if(check == 0xFFFFFFFF) return -4; } else { if(write_page_h(spi_chip, addr + size1, (data_buff + size1), size2) != 1) { exit_atomic(); xSemaphoreGive(Spi0_Mutex); return size1; } } } exit_atomic(); xSemaphoreGive(Spi0_Mutex); return (size1 + size2); } else return -3; // SPI0 is currently being used or there is an error. }
// Set up a two-level page table: // kern_pgdir is its linear (virtual) address of the root // Then turn on paging. Then effectively turn off segmentation. // (i.e., the segment base addrs are set to zero). // // This function only sets up the kernel part of the address space // (ie. addresses >= UTOP). The user part of the address space // will be setup later. // // From UTOP to ULIM, the user is allowed to read but not write. // Above ULIM the user cannot read or write. void mem_init(void) { uint32_t cr0; size_t n; // Ensure user & kernel struct Pages agree. static_assert(sizeof(struct Page) == sizeof(struct UserPage)); // Find out how much memory the machine has (npages & npages_basemem). i386_detect_memory(); // Remove this line when you're ready to test this function. //panic("mem_init: This function is not finished\n"); ////////////////////////////////////////////////////////////////////// // create initial page directory. kern_pgdir = (pde_t *) boot_alloc(PGSIZE); memset(kern_pgdir, 0, PGSIZE); ////////////////////////////////////////////////////////////////////// // Recursively insert PD in itself as a page table, to form // a virtual page table at virtual address UVPT. // (For now, you don't have understand the greater purpose of the // following line.) // Permissions: kernel R, user R kern_pgdir[PDX(UVPT)] = PADDR(kern_pgdir) | PTE_U | PTE_P; ////////////////////////////////////////////////////////////////////// // Allocate an array of npages 'struct Page's and store it in 'pages'. // The kernel uses this array to keep track of physical pages: for // each physical page, there is a corresponding struct Page in this // array. 'npages' is the number of physical pages in memory. pages = (Page *) boot_alloc(npages * sizeof(struct Page)); ////////////////////////////////////////////////////////////////////// // Make 'envs' point to an array of size 'NENV' of 'struct Env'. // LAB 3: Your code here. envs = (Env *) boot_alloc(NENV * sizeof(struct Env)); ////////////////////////////////////////////////////////////////////// // Now that we've allocated the initial kernel data structures, we set // up the list of free physical pages. Once we've done so, all further // memory management will go through the page_* functions. In // particular, we can now map memory using page_map_segment // or page_insert page_init(); check_page_free_list(true); check_page_alloc(); check_page(); ////////////////////////////////////////////////////////////////////// // Now we set up virtual memory ////////////////////////////////////////////////////////////////////// // Use the physical memory that 'entry_stack' refers to as the kernel // stack. The kernel stack grows down from virtual address KSTACKTOP. // We consider the entire range from [KSTACKTOP-PTSIZE, KSTACKTOP) // to be the kernel stack, but break this into two pieces: // * [KSTACKTOP-KSTKSIZE, KSTACKTOP) -- backed by physical memory // * [KSTACKTOP-PTSIZE, KSTACKTOP-KSTKSIZE) -- not backed; so if // the kernel overflows its stack, it will fault rather than // overwrite memory. Known as a "guard page". // Permissions: kernel RW, user NONE Page *pp = pa2page((physaddr_t)entry_stack-KERNBASE); for (uintptr_t ptr = KSTACKTOP-KSTKSIZE; ptr < KSTACKTOP; ptr += PGSIZE) { if (page_insert(kern_pgdir, pp, ptr, PTE_W | PTE_P) < 0) panic("Couldn't create page table entries for stack.\n"); pp++; } ////////////////////////////////////////////////////////////////////// // Map all of physical memory at KERNBASE. // Ie. the VA range [KERNBASE, 2^32) should map to // the PA range [0, 2^32 - KERNBASE) // We might not have 2^32 - KERNBASE bytes of physical memory, but // we just set up the mapping anyway. // Permissions: kernel RW, user NONE page_map_segment(kern_pgdir, KERNBASE, 0xFFFFFFFF-KERNBASE, 0x0, PTE_W | PTE_P); //print_page_table(kern_pgdir, false, false); ////////////////////////////////////////////////////////////////////// // Map the 'envs' array read-only by the user at linear address UENVS. // Permissions: kernel R, user R // (That's the UENVS version; 'envs' itself is kernel RW, user NONE.) // LAB 3: Your code here. page_map_segment(kern_pgdir, (uintptr_t) UENVS, ROUNDUP(NENV*sizeof(struct Env), PGSIZE), PADDR(envs), PTE_U | PTE_P); ////////////////////////////////////////////////////////////////////// // Map 'pages' read-only by the user at linear address UPAGES. // Permissions: kernel R, user R // (That's the UPAGES version; 'pages' itself is kernel RW, user NONE.) // LAB 3: Your code here. page_map_segment(kern_pgdir, UPAGES, ROUNDUP(npages*sizeof(struct Page), PGSIZE), PADDR(pages), PTE_U | PTE_P); // Check that the initial page directory has been set up correctly. check_kern_pgdir(); // Switch from the minimal entry page directory to the full kern_pgdir // page table we just created. Our instruction pointer should be // somewhere between KERNBASE and KERNBASE+4MB right now, which is // mapped the same way by both page tables. // // If the machine reboots at this point, you've probably set up your // kern_pgdir wrong. lcr3(PADDR(kern_pgdir)); // entry.S set the really important flags in cr0 (including enabling // paging). Here we configure the rest of the flags we need. cr0 = rcr0(); cr0 |= CR0_PE|CR0_PG|CR0_AM|CR0_WP|CR0_NE|CR0_MP; cr0 &= ~(CR0_TS|CR0_EM); lcr0(cr0); // Some more checks, only possible after kern_pgdir is installed. check_page_installed_pgdir(); }
void process_ibpage(page_t *page) { ulint page_id; rec_t *origin; ulint offsets[MAX_TABLE_FIELDS + 2]; ulint offset, i; int is_page_valid = 0; int comp; unsigned int expected_records = 0; unsigned int actual_records = 0; int16_t b, infimum, supremum; // Skip tables if filter used if (use_filter_id) { dulint index_id = mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID); if (index_id.low != filter_id.low || index_id.high != filter_id.high) { if (debug) { page_id = mach_read_from_4(page + FIL_PAGE_OFFSET); printf("Skipped using index id filter: %lu!\n", page_id); } return; } } // Read page id page_id = mach_read_from_4(page + FIL_PAGE_OFFSET); if (debug) printf("Page id: %lu\n", page_id); fprintf(f_result, "-- Page id: %lu", page_id); // Check requested and actual formats if (!check_page_format(page)) return; if(table_definitions_cnt == 0){ fprintf(stderr, "There are no table definitions. Please check include/table_defs.h\n"); exit(EXIT_FAILURE); } is_page_valid = check_page(page, &expected_records); // comp == 1 if page in COMPACT format and 0 if REDUNDANT comp = page_is_comp(page); fprintf(f_result, ", Format: %s", (comp ) ? "COMPACT": "REDUNDANT"); infimum = (comp) ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM; supremum = (comp) ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM; // Find possible data area start point (at least 5 bytes of utility data) if(is_page_valid){ b = mach_read_from_2(page + infimum - 2); offset = (comp) ? infimum + b : b; } else{ offset = 100 + record_extra_bytes; } fprintf(f_result, ", Records list: %s", is_page_valid? "Valid": "Invalid"); fprintf(f_result, ", Expected records: (%u %lu)", expected_records, mach_read_from_2(page + PAGE_HEADER + PAGE_N_RECS)); fprintf(f_result, "\n"); if (debug) printf("Starting offset: %lu (%lX). Checking %d table definitions.\n", offset, offset, table_definitions_cnt); // Walk through all possible positions to the end of page // (start of directory - extra bytes of the last rec) //is_page_valid = 0; while (offset < UNIV_PAGE_SIZE - record_extra_bytes && ( (offset != supremum ) || !is_page_valid) ) { // Get record pointer origin = page + offset; if (debug) printf("\nChecking offset: 0x%lX: ", offset); // Check all tables for (i = 0; i < table_definitions_cnt; i++) { // Get table info table_def_t *table = &(table_definitions[i]); if (debug) printf(" (%s) ", table->name); // Check if origin points to a valid record if (check_for_a_record(page, origin, table, offsets) && check_constraints(origin, table, offsets)) { actual_records++; if (debug) printf("\n---------------------------------------------------\n" "PAGE%lu: Found a table %s record: %p (offset = %lu)\n", \ page_id, table->name, origin, offset); if(is_page_valid){ process_ibrec(page, origin, table, offsets); b = mach_read_from_2(page + offset - 2); offset = (comp) ? offset + b : b; } else{ offset += process_ibrec(page, origin, table, offsets); } if (debug) printf("Next offset: 0x%lX", offset); break; } else{ if(is_page_valid){ b = mach_read_from_2(page + offset - 2); offset = (comp) ? offset + b : b; } else{ offset++; } if (debug) printf("\nNext offset: %lX", offset); } } } fprintf(f_result, "-- Page id: %lu", page_id); fprintf(f_result, ", Found records: %u", actual_records); fprintf(f_result, ", Lost records: %s", (actual_records != expected_records) ? "YES": "NO"); fprintf(f_result, ", Leaf page: %s", (mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL) == 0)? "YES": "NO"); fprintf(f_result, "\n"); }