/* dccvmm_read retorna a palavra de 32-bits apontada pelo endereco virtual * address na tabela de paginas atual. * OU SEJA, dccvmm_read devolve a entrada da tabela de paginas apontada pelo endereço virtual address * OU SEJA, dccvmm_read vai na tabela de pagina, no endereco apontado por address e devolve o frame daquela pagina (16 bits) */ uint32_t dccvmm_read(uint32_t address) { //printf("\n\n(RETIRAR ESTE PRINT) Entrando na função \"dccvmm_read\"\n"); //printf("(RETIRAR ESTE PRINT) address: %X\n", address); uint32_t perms = PTE_RW | PTE_INMEM | PTE_VALID; /* A operação acima eh uma combinação de: * PTE_RW 0x00800000 o quadro apontado pelo pte tem permissao de leitura e escrita * PTE_VALID 0x00100000 o endereco virtual foi alocado pelo processo * PTE_INMEM 0x00400000 o quadro apontado pelo pte esta na memoria * resultado 0x00D00000 ou seja, a permissao eh de leitura e escrita + é do processo + está na memória */ /*PTE1OFF(address) = Separa os bitos 23 a 16 de address e os coloca na posição 7 a 0 dccvmm_get_pte(uint32_t frame, uint8_t ptenum, uint32_t perms, uint32_t address) */ //printf("(RETIRAR ESTE PRINT) __pagetable: 0x%X\n", __pagetable); //printf("(RETIRAR ESTE PRINT) PTE1OFF(address): %X\n", PTE1OFF(address)); //printf("(RETIRAR ESTE PRINT) perms: 0x%X\n", perms); uint32_t pte1 = dccvmm_get_pte(__pagetable, PTE1OFF(address), perms, address); if (pte1 == VM_ABORT) return 0; uint32_t pte1frame = PTEFRAME(pte1); /*Separa os 12 bits menos significativos de pte1*/ /*PTE2OFF(address) = Separa os bitos 15 a 8 de address e os coloca na posição 7 a 0 dccvmm_get_pte(uint32_t frame, uint8_t ptenum, uint32_t perms, uint32_t address) */ uint32_t pte2 = dccvmm_get_pte(pte1frame, PTE2OFF(address), perms, address); if (pte2 == VM_ABORT) return 0; uint32_t pte2frame = PTEFRAME(pte2); /*Separa os 12 bits menos significativos de pte2*/ uint32_t data = __frames[pte2frame].words[PAGEOFFSET(address)]; /*Separa os bitos 7 a 0 de address*/ printf("vmm %x phy %x read %x\n", address, (pte2frame << 8) + PAGEOFFSET(address), data); /*Separa os bitos 7 a 0 de address*/ return data; }
/* fetch the pages addr resides in into pg and initialise sg with them */ int __get_userbuf(uint8_t __user *addr, uint32_t len, int write, unsigned int pgcount, struct page **pg, struct scatterlist *sg, struct task_struct *task, struct mm_struct *mm) { int ret, pglen, i = 0; struct scatterlist *sgp; if (unlikely(!pgcount || !len || !addr)) { sg_mark_end(sg); return 0; } down_read(&mm->mmap_sem); ret = get_user_pages(task, mm, (unsigned long)addr, pgcount, write, 0, pg, NULL); up_read(&mm->mmap_sem); if (ret != pgcount) return -EINVAL; sg_init_table(sg, pgcount); pglen = min((ptrdiff_t)(PAGE_SIZE - PAGEOFFSET(addr)), (ptrdiff_t)len); sg_set_page(sg, pg[i++], pglen, PAGEOFFSET(addr)); len -= pglen; for (sgp = sg_next(sg); len; sgp = sg_next(sgp)) { pglen = min((uint32_t)PAGE_SIZE, len); sg_set_page(sgp, pg[i++], pglen, 0); len -= pglen; } sg_mark_end(sg_last(sg, pgcount)); return 0; }
void os_alloc(uint32_t addr) { //search for a free frame if (PAGEOFFSET(addr)) { // offset must be *00; fprintf(stderr, "Invalid Alloc on address :[%x]\n", addr); return; } uint32_t dir, dirFrame, pt, ptFrame; //make page table point to the found frame dir = dccvmm_phy_read(procTable_ << 8 | currentPID_); dirFrame = PTEFRAME(dir); pt = dccvmm_phy_read( dirFrame << 8 | PTE1OFF(addr)); ptFrame = PTEFRAME(pt); if ((pt & PTE_VALID) != PTE_VALID) { //pointed frame is not a valid frame ptFrame = getFreeFrame(); dccvmm_phy_write(dirFrame << 8 | PTE1OFF(addr), ptFrame | PTE_VALID | PTE_INMEM | PTE_RW); } if (dccvmm_phy_read(ptFrame << 8 | PTE2OFF(addr)) & PTE_VALID) { fprintf(stderr, "\tDouble Alloc Detected\n"); return; } uint32_t freeFrame = getFreeFrame(); // frame is not avaliable anymore; //write on the page table the allocated Frame dccvmm_phy_write(ptFrame << 8 | PTE2OFF(addr), freeFrame | PTE_VALID | PTE_INMEM | PTE_RW); }
dccvmm_get_pte(uint32_t frame, uint8_t ptenum, uint32_t perms, uint32_t address) */ uint32_t pte2 = dccvmm_get_pte(pte1frame, PTE2OFF(address), perms, address); if (pte2 == VM_ABORT) return 0; uint32_t pte2frame = PTEFRAME(pte2); /*Separa os 12 bits menos significativos de pte2*/ uint32_t data = __frames[pte2frame].words[PAGEOFFSET(address)]; /*Separa os bitos 7 a 0 de address*/ printf("vmm %x phy %x read %x\n", address, (pte2frame << 8) + PAGEOFFSET(address), data); /*Separa os bitos 7 a 0 de address*/ return data; } /* dccvmm_phy_read retorna a palavra de 32-bits apontada pelo endereco * fisico phyaddr, transpassando o sistema de memoria */ uint32_t dccvmm_phy_read(uint32_t phyaddr) { assert((phyaddr >> 8) < NUMFRAMES); uint32_t data = __frames[phyaddr >> 8].words[PAGEOFFSET(phyaddr)]; printf("vmm phy %x read %x\n", phyaddr, data); return data; } /* dccvmm_write escreve data na palavra de 32-bits apontada pelo endereco * virtual address na tabela de paginas atual. */ void dccvmm_write(uint32_t address, uint32_t data) { //printf("\n\n(RETIRAR ESTE PRINT) Entrando na função \"dccvmm_write\"\n"); uint32_t perms = PTE_RW | PTE_INMEM | PTE_VALID; uint32_t pte1 = dccvmm_get_pte(__pagetable, PTE1OFF(address), perms, address); if (pte1 == VM_ABORT) return; uint32_t pte1frame = PTEFRAME(pte1); uint32_t pte2 = dccvmm_get_pte(pte1frame, PTE2OFF(address), perms, address); if (pte2 == VM_ABORT) return; uint32_t pte2frame = PTEFRAME(pte2);
/* * Translate a virtual address to a physical address by using 4 levels paging. */ unsigned long long vtop4_x86_64(unsigned long vaddr) { unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte; unsigned long pte_paddr, pte; if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) { ERRMSG("Can't get the symbol of init_level4_pgt.\n"); return NOT_PADDR; } /* * Get PGD. */ page_dir = SYMBOL(init_level4_pgt); page_dir += pml4_index(vaddr) * sizeof(unsigned long); if (!readmem(VADDR, page_dir, &pml4, sizeof pml4)) { ERRMSG("Can't get pml4 (page_dir:%lx).\n", page_dir); return NOT_PADDR; } if (info->vaddr_for_vtop == vaddr) MSG(" PGD : %16lx => %16lx\n", page_dir, pml4); if (!(pml4 & _PAGE_PRESENT)) { ERRMSG("Can't get a valid pml4.\n"); return NOT_PADDR; } /* * Get PUD. */ pgd_paddr = pml4 & PHYSICAL_PAGE_MASK; pgd_paddr += pgd_index(vaddr) * sizeof(unsigned long); if (!readmem(PADDR, pgd_paddr, &pgd_pte, sizeof pgd_pte)) { ERRMSG("Can't get pgd_pte (pgd_paddr:%lx).\n", pgd_paddr); return NOT_PADDR; } if (info->vaddr_for_vtop == vaddr) MSG(" PUD : %16lx => %16lx\n", pgd_paddr, pgd_pte); if (!(pgd_pte & _PAGE_PRESENT)) { ERRMSG("Can't get a valid pgd_pte.\n"); return NOT_PADDR; } /* * Get PMD. */ pmd_paddr = pgd_pte & PHYSICAL_PAGE_MASK; pmd_paddr += pmd_index(vaddr) * sizeof(unsigned long); if (!readmem(PADDR, pmd_paddr, &pmd_pte, sizeof pmd_pte)) { ERRMSG("Can't get pmd_pte (pmd_paddr:%lx).\n", pmd_paddr); return NOT_PADDR; } if (info->vaddr_for_vtop == vaddr) MSG(" PMD : %16lx => %16lx\n", pmd_paddr, pmd_pte); if (!(pmd_pte & _PAGE_PRESENT)) { ERRMSG("Can't get a valid pmd_pte.\n"); return NOT_PADDR; } if (pmd_pte & _PAGE_PSE) return (PAGEBASE(pmd_pte) & PHYSICAL_PAGE_MASK) + (vaddr & ~_2MB_PAGE_MASK); /* * Get PTE. */ pte_paddr = pmd_pte & PHYSICAL_PAGE_MASK; pte_paddr += pte_index(vaddr) * sizeof(unsigned long); if (!readmem(PADDR, pte_paddr, &pte, sizeof pte)) { ERRMSG("Can't get pte (pte_paddr:%lx).\n", pte_paddr); return NOT_PADDR; } if (info->vaddr_for_vtop == vaddr) MSG(" PTE : %16lx => %16lx\n", pte_paddr, pte); if (!(pte & _PAGE_PRESENT)) { ERRMSG("Can't get a valid pte.\n"); return NOT_PADDR; } return (PAGEBASE(pte) & PHYSICAL_PAGE_MASK) + PAGEOFFSET(vaddr); }
static void init_ram_segments(void) { int i, errflag; FILE *iomem; char buf[BUFSIZE], *p1, *p2; physaddr_t start, end; if ((iomem = fopen("/proc/iomem", "r")) == NULL) goto fail_iomem; while (fgets(buf, BUFSIZE, iomem)) { if (strstr(buf, "System RAM")) { console(buf); nr_segments++; } } if (!nr_segments) goto fail_iomem; ram_segments = (struct ram_segments *) GETBUF(sizeof(struct ram_segments) * nr_segments); rewind(iomem); i = 0; while (fgets(buf, BUFSIZE, iomem)) { if (strstr(buf, "System RAM")) { if (!(p1 = strstr(buf, ":"))) goto fail_iomem; *p1 = NULLCHAR; clean_line(buf); if (strstr(buf, " ")) goto fail_iomem; p1 = buf; if (!(p2 = strstr(buf, "-"))) goto fail_iomem; *p2 = NULLCHAR; p2++; errflag = 0; start = htoll(p1, RETURN_ON_ERROR|QUIET, &errflag); end = htoll(p2, RETURN_ON_ERROR|QUIET, &errflag); if (errflag) goto fail_iomem; ram_segments[i].start = PHYSPAGEBASE(start); if (PAGEOFFSET(start)) ram_segments[i].start += PAGESIZE(); ram_segments[i].end = PHYSPAGEBASE(end); if (PAGEOFFSET(end) == (PAGESIZE()-1)) ram_segments[i].end += PAGESIZE(); console("ram_segments[%d]: %016llx %016llx [%s-%s]\n", i, (ulonglong)ram_segments[i].start, (ulonglong)ram_segments[i].end, p1, p2); i++; } } fclose(iomem); return; fail_iomem: fclose(iomem); nr_segments = 0; if (ram_segments) FREEBUF(ram_segments); return; }