/* 将inode写入到分区part */ void inode_sync(struct partition* part, struct inode* inode, void* io_buf) { // io_buf是用于硬盘io的缓冲区 uint8_t inode_no = inode->i_no; struct inode_position inode_pos; inode_locate(part, inode_no, &inode_pos); // inode位置信息会存入inode_pos ASSERT(inode_pos.sec_lba <= (part->start_lba + part->sec_cnt)); /* 硬盘中的inode中的成员inode_tag和i_open_cnts是不需要的, * 它们只在内存中记录链表位置和被多少进程共享 */ struct inode pure_inode; memcpy(&pure_inode, inode, sizeof(struct inode)); /* 以下inode的三个成员只存在于内存中,现在将inode同步到硬盘,清掉这三项即可 */ pure_inode.i_open_cnts = 0; pure_inode.write_deny = false; // 置为false,以保证在硬盘中读出时为可写 pure_inode.inode_tag.prev = pure_inode.inode_tag.next = NULL; char* inode_buf = (char*)io_buf; if (inode_pos.two_sec) { // 若是跨了两个扇区,就要读出两个扇区再写入两个扇区 /* 读写硬盘是以扇区为单位,若写入的数据小于一扇区,要将原硬盘上的内容先读出来再和新数据拼成一扇区后再写入 */ ide_read(part->my_disk, inode_pos.sec_lba, inode_buf, 2); // inode在format中写入硬盘时是连续写入的,所以读入2块扇区 /* 开始将待写入的inode拼入到这2个扇区中的相应位置 */ memcpy((inode_buf + inode_pos.off_size), &pure_inode, sizeof(struct inode)); /* 将拼接好的数据再写入磁盘 */ ide_write(part->my_disk, inode_pos.sec_lba, inode_buf, 2); } else { // 若只是一个扇区 ide_read(part->my_disk, inode_pos.sec_lba, inode_buf, 1); memcpy((inode_buf + inode_pos.off_size), &pure_inode, sizeof(struct inode)); ide_write(part->my_disk, inode_pos.sec_lba, inode_buf, 1); } }
int fs_write(int fd, void *buf, int len) { int i=fd; if(file_state[i].offset+len>file_table[i-3].size) { int len_new=file_table[i-3].size-file_state[i].offset; ide_write(buf,file_table[i-3].disk_offset+file_state[i].offset,len_new); return len_new; } ide_write(buf,file_table[i-3].disk_offset+file_state[i].offset,len); return len; }
void ide_write(unsigned char channel, unsigned char reg, unsigned char data) { if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); if (reg < 0x08) outb(data, channels[channel].base + reg - 0x00); else if (reg < 0x0C) outb(data, channels[channel].base + reg - 0x06); else if (reg < 0x0E) outb(data, channels[channel].ctrl + reg - 0x0A); else if (reg < 0x16) outb(data, channels[channel].bmide + reg - 0x0E); if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); }
int32_t ide_pio_readwrite(uint8_t rw, uint8_t drive, uint64_t lba, uint8_t *buf, uint32_t numsectors) { /* Sanity */ if(rw > 1 || buf == 0) return 0; /* Vars */ uint64_t addr = lba; uint8_t lba_mode = 1; /* 1 - 28, 2 - 48 */ uint8_t cmd = 0; uint8_t channel = ide_devices[drive].channel; uint32_t slave = ide_devices[drive].drive; uint32_t bus = ide_channels[channel].base; uint32_t words = (numsectors * 512) / 2; /* Make sure IRQs are disabled */ _outb(bus + IDE_REGISTER_CTRL, 0x02); /* Wait for it to acknowledge */ ide_wait(channel, 0); /* Determine LBA mode */ if(ide_devices[drive].flags & 0x1) lba_mode = 2; /* Read or write? */ if(rw == IDE_READ) cmd = IDE_COMMAND_PIO_READ; else cmd = IDE_COMMAND_PIO_WRITE; /* Reset IRQ counter */ ide_channels[channel].irq_wait = 0; /* Now, send the command */ if(lba_mode == 2) { /* LBA48 */ cmd += 0x04; /* Send it */ ide_write(channel, IDE_REGISTER_HDDSEL, (0x40 | (slave << 4))); ide_wait(channel, 0); ide_write(channel, IDE_REGISTER_SECCOUNT0, 0x00); ide_write(channel, IDE_REGISTER_LBA0, (uint8_t)((addr >> 24) & 0xFF)); ide_write(channel, IDE_REGISTER_LBA1, (uint8_t)((addr >> 32) & 0xFF)); ide_write(channel, IDE_REGISTER_LBA2, (uint8_t)((addr >> 40) & 0xFF)); }
// Copy the current contents of the block out to disk. // Then clear the PTE_D bit using sys_page_map. // Hint: Use ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. void write_block(uint32_t blockno) { char *addr; if (!block_is_mapped(blockno)) panic("write unmapped block %08x", blockno); // Write the disk block and clear PTE_D. // LAB 5: Your code here. // We will use the VM hardware to keep track of whether a // disk block has been modified since it was last read from // or written to disk. To see whether a block needs writing, // we can just look to see if the PTE_D "dirty" bit is set // in the vpt entry. addr = diskaddr(blockno); if(!va_is_dirty(addr)) return; int error; int secno = blockno*BLKSECTS; error = ide_write(secno, addr, BLKSECTS); if(error<0) panic("write block error on writing"); int env_id = sys_getenvid(); error = sys_page_map(env_id, addr, env_id, addr, ((PTE_U|PTE_P|PTE_W) & ~PTE_D)); if(error<0) panic("write block error on clearing PTE_D"); // panic("write_block not implemented"); }
int fs_write(int fd, void *buf, int len) { if(!state_array[fd].opened) return -1; assert(state_array[fd].offset + len < file_table[fd - 3].size); ide_write(buf, file_table[fd-3].disk_offset + state_array[fd].offset, len); state_array[fd].offset += len; return len; }
// Flush the contents of the block containing VA out to disk if // necessary, then clear the PTE_D bit using sys_page_map. // If the block is not in the block cache or is not dirty, does // nothing. // Hint: Use va_is_mapped, va_is_dirty, and ide_write. // Hint: Use the PTE_SYSCALL constant when calling sys_page_map. // Hint: Don't forget to round addr down. void flush_block(void *addr) { uint64_t blockno = ((uint64_t)addr - DISKMAP) / BLKSIZE; int r; if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("flush_block of bad va %08x", addr); // LAB 5: Your code here. //panic("flush_block not implemented"); if(va_is_mapped(addr) == false || va_is_dirty(addr) == false) { return; } addr = ROUNDDOWN(addr, PGSIZE); #ifdef VMM_GUEST if(0 != host_write((uint32_t) (blockno * BLKSECTS), (void*)addr, BLKSECTS)) { panic("ide read failed in Page Fault Handling"); } #else if(0 != ide_write((uint32_t) (blockno * BLKSECTS), (void*)addr, BLKSECTS)) { panic("ide write failed in Flush Block"); } #endif if ((r = sys_page_map(0, addr, 0, addr, PTE_SYSCALL)) < 0) { panic("in flush_block, sys_page_map: %e", r); } }
// Flush the contents of the block containing VA out to disk if // necessary, then clear the PTE_D bit using sys_page_map. // If the block is not in the block cache or is not dirty, does // nothing. // Hint: Use va_is_mapped, va_is_dirty, and ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. // Hint: Don't forget to round addr down. void flush_block(void *addr) { uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; uint32_t secno, r; if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("flush_block of bad va %08x", addr); // LAB 5: Your code here. addr = ROUNDDOWN(addr,PGSIZE); secno = blockno*BLKSECTS; if(va_is_mapped(addr) && va_is_dirty(addr)) { r = ide_write(secno, addr, BLKSECTS); if(r) panic("IDE write failed: %e", r); //cprintf("\nClearing PTE_D : 0x%08x\n", vpt[VPN(addr)] & (~PTE_D)); r = sys_page_map(0,addr,0,addr, ((vpt[VPN(addr)] | PTE_USER) & (~PTE_D))); // & PTE_USER if(r) cprintf("\nPage Mapping failed %e\n", r); } //panic("flush_block not implemented"); }
void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int buffer,unsigned int quads) { if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); asm("pushw %es; movw %ds, %ax; movw %ax, %es"); //if (reg < 0x08) // insl(channels[channel].base + reg - 0x00, buffer, quads); //else if (reg < 0x0C) //insl(channels[channel].base + reg - 0x06, buffer, quads); //else if (reg < 0x0E) //insl(channels[channel].ctrl + reg - 0x0A, buffer, quads); // else if (reg < 0x16) //insl(channels[channel].bmide + reg - 0x0E, buffer, quads); asm("popw %es;"); if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); }
// Flush the contents of the block containing VA out to disk if // necessary, then clear the PTE_D bit using sys_page_map. // If the block is not in the block cache or is not dirty, does // nothing. // Hint: Use va_is_mapped, va_is_dirty, and ide_write. // Hint: Use the PTE_SYSCALL constant when calling sys_page_map. // Hint: Don't forget to round addr down. void flush_block(void *addr) { uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; int r; if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("flush_block of bad va %08x", addr); // LAB 5: Your code here. addr = (void *)ROUNDDOWN(addr, PGSIZE); if (!va_is_mapped(addr) || !va_is_dirty(addr)) return; if ((r = ide_write(BLKSECTS * blockno, addr, BLKSECTS)) < 0) { panic("flush_block: ide_write error %e\n", r); } if ((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL & ~PTE_D))) { panic("flush_block: sys_page_map error %e\n", r); } return; }
unsigned char ide_read(unsigned char channel, unsigned char reg) { unsigned char result; if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); if (reg < 0x08) result = inb(channels[channel].base + reg - 0x00); else if (reg < 0x0C) result = inb(channels[channel].base + reg - 0x06); else if (reg < 0x0E) result = inb(channels[channel].ctrl + reg - 0x0A); else if (reg < 0x16) result = inb(channels[channel].bmide + reg - 0x0E); if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); return result; }
/** * Initialize disk device driver. Reserves memory for data structures * and register driver to the interrupt handler. * * @param desc Pointer to the PCI IO device descriptor of the controller * * @return Pointer to the device structure of the controller */ void ide_write(uint8_t channel, uint8_t reg, uint8_t data) { /* */ if(reg > 0x07 && reg < 0x0C) ide_write(channel, IDE_REGISTER_CTRL, 0x80 | ide_channels[channel].irq); /* */ if(reg < 0x08) _outb((uint16_t)(ide_channels[channel].base + reg), data); else if(reg < 0x0C) _outb((uint16_t)(ide_channels[channel].base + reg - 0x06), data); else if(reg < 0x0E) _outb((uint16_t)(ide_channels[channel].ctrl + reg - 0x0A), data); else if(reg < 0x16) _outb((uint16_t)(ide_channels[channel].busm + reg - 0x0E), data); if(reg > 0x07 && reg < 0x0C) ide_write(channel, IDE_REGISTER_CTRL, ide_channels[channel].irq); }
int fs_write(int fd, const void *buf, size_t len) { if (fd < 3) return -1; assert(fd < NR_FILES + 3); assert(f_state[fd].opened); int max_len = file_table[fd - 3].size - f_state[fd].offset; assert(max_len >= 0); if (max_len < len) len = max_len; ide_write(buf, file_table[fd - 3].disk_offset + f_state[fd].offset, len); f_state[fd].offset += len; return len; }
// Flush the contents of the block containing VA out to disk if // necessary, then clear the PTE_D bit using sys_page_map. // If the block is not in the block cache or is not dirty, does // nothing. // Hint: Use va_is_mapped, va_is_dirty, and ide_write. // Hint: Use the PTE_SYSCALL constant when calling sys_page_map. // Hint: Don't forget to round addr down. void flush_block(void *addr) { uint64_t blockno = ((uint64_t)addr - DISKMAP) / BLKSIZE; int r; if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("flush_block of bad va %08x", addr); // LAB 5: Your code here. void *dst_addr = (void *)(ROUNDDOWN(addr, PGSIZE)); // Project addition --> Transparent disk encryption. if(va_is_mapped(dst_addr)) { if(va_is_dirty(dst_addr)) { if((blockno == 0) || (blockno == 2)) ide_write(blockno * BLKSECTS, dst_addr, BLKSECTS); else if((blockno == 1)) { if(!s_encrypted) ide_write(blockno * BLKSECTS, dst_addr, BLKSECTS); else { r = transparent_disk_encrypt(blockno, dst_addr); if(r) return; } } else { r = transparent_disk_encrypt(blockno, dst_addr); if(r) return; } sys_page_map(thisenv->env_id, dst_addr, thisenv->env_id, dst_addr, PTE_SYSCALL); } } // panic("flush_block not implemented"); }
/* 将硬盘分区part上的inode清空 */ void inode_delete(struct partition* part, uint32_t inode_no, void* io_buf) { ASSERT(inode_no < 4096); struct inode_position inode_pos; inode_locate(part, inode_no, &inode_pos); // inode位置信息会存入inode_pos ASSERT(inode_pos.sec_lba <= (part->start_lba + part->sec_cnt)); char* inode_buf = (char*)io_buf; if (inode_pos.two_sec) { // inode跨扇区,读入2个扇区 /* 将原硬盘上的内容先读出来 */ ide_read(part->my_disk, inode_pos.sec_lba, inode_buf, 2); /* 将inode_buf清0 */ memset((inode_buf + inode_pos.off_size), 0, sizeof(struct inode)); /* 用清0的内存数据覆盖磁盘 */ ide_write(part->my_disk, inode_pos.sec_lba, inode_buf, 2); } else { // 未跨扇区,只读入1个扇区就好 /* 将原硬盘上的内容先读出来 */ ide_read(part->my_disk, inode_pos.sec_lba, inode_buf, 1); /* 将inode_buf清0 */ memset((inode_buf + inode_pos.off_size), 0, sizeof(struct inode)); /* 用清0的内存数据覆盖磁盘 */ ide_write(part->my_disk, inode_pos.sec_lba, inode_buf, 1); } }
uint8_t ide_read(uint8_t channel, uint8_t reg) { /* */ uint8_t data = 0;; if(reg > 0x07 && reg < 0x0C) ide_write(channel, IDE_REGISTER_CTRL, 0x80 | ide_channels[channel].irq); /* */ if(reg < 0x08) data = _inb((uint16_t)(ide_channels[channel].base + reg)); else if(reg < 0x0C) data = _inb((uint16_t)(ide_channels[channel].base + reg - 0x06)); else if(reg < 0x0E) data = _inb((uint16_t)(ide_channels[channel].ctrl + reg - 0x0A)); else if(reg < 0x16) data = _inb((uint16_t)(ide_channels[channel].busm + reg - 0x0E)); if(reg > 0x07 && reg < 0x0C) ide_write(channel, IDE_REGISTER_CTRL, ide_channels[channel].irq); return data; }
// Write the contents of DISKMAP block 'blocknum' to disk. // Returns 0 on success, < 0 on failure. Error codes include -E_INVAL // (blocknum out of range), -E_FAULT (block not in memory), -E_IO. // static int flush_block(blocknum_t blocknum) { uintptr_t va = DISKMAP + blocknum * BLKSIZE; BlockInfo *bip; int r; if (blocknum >= (blocknum_t) (DISKSIZE / BLKSIZE)) return -E_INVAL; if (!(vpd[PDX(va)] & PTE_P) || !(vpt[PGNUM(va)] & PTE_P)) return -E_FAULT; return ide_write(blocknum * BLKSECTS, (void *) va, BLKSECTS); }
int fs_write(int fd, void *buf, int len) { if ((fd == 1)||(fd == 2)) { int i; for (i = 0; i < len; i++) serial_printc(((char*)buf)[i]); } if (fd < 3) return 0; assert(file_state[fd].opened); if (file_state[fd].offset+len >= file_table[fd-3].size) len = file_table[fd-3].size-file_state[fd].offset-1; if (len <= 0) return 0; ide_write(buf, file_table[fd-3].disk_offset+file_state[fd].offset, len); file_state[fd].offset += len; return len; }
// Flush the contents of the block containing VA out to disk if // necessary, then clear the PTE_D bit using sys_page_map. // If the block is not in the block cache or is not dirty, does // nothing. // Hint: Use va_is_mapped, va_is_dirty, and ide_write. // Hint: Use the PTE_SYSCALL constant when calling sys_page_map. // Hint: Don't forget to round addr down. void flush_block(void *addr) { uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("flush_block of bad va %08x", addr); // LAB 5: Your code here. addr = ROUNDDOWN(addr, PGSIZE); if (!va_is_mapped(addr) || !va_is_dirty(addr)) return; ide_write(blockno * BLKSECTS, addr, BLKSECTS); sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL); }
/* Write n sectors to the hard disk using PIO mode */ int ide_write(uint32 linear, uint32 numsects, void *bufptr) { int i; uint32 cyl,head,sector; if (numsects > 1) { for (i=0; i<numsects; i++) { if (ide_write(linear+i, 1, ((uint8 *)bufptr)+i*512) < 0) return -1; } } else { linear_to_chs(linear, &cyl, &head, §or); ide_write_chs(cyl, head, sector, numsects, (uint8*)bufptr); } return 0; }
// Copy the current contents of the block out to disk. // Then clear the PTE_D bit using sys_page_map. // Hint: Use ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. void write_block(uint32_t blockno) { int r; char *addr; if (!block_is_mapped(blockno)) panic("write unmapped block %08x", blockno); // Write the disk block and clear PTE_D. // LAB 5: Your code here. addr = diskaddr(blockno); if ((r = ide_write(blockno * BLKSECTS, addr, BLKSECTS)) < 0) panic("write_block: ide_write failed: %e.\n", r); if ((r = sys_page_map(0, addr, 0, addr, PTE_USER)) < 0) panic("write_block: sys_page_map failed: %e.\n", r); }
// Flush the contents of the block containing VA out to disk if // necessary, then clear the PTE_D bit using sys_page_map. // If the block is not in the block cache or is not dirty, does // nothing. // Hint: Use va_is_mapped, va_is_dirty, and ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. // Hint: Don't forget to round addr down. void flush_block(void *addr) { uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; int r; if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("flush_block of bad va %08x", addr); // LAB 5: Your code here. addr = ROUNDDOWN(addr, PGSIZE); if (!va_is_mapped(addr) || !va_is_dirty(addr)) return; if (ide_write(blockno * BLKSECTS, addr, BLKSECTS) < 0) panic("ide_write failed"); if ((r = sys_page_map(0, addr, 0, addr, PTE_USER)) < 0) panic("sys_page_map: %e", r); }
// Flush the contents of the block containing VA out to disk if // necessary, then clear the PTE_D bit using sys_page_map. // If the block is not in the block cache or is not dirty, does // nothing. // Hint: Use va_is_mapped, va_is_dirty, and ide_write. // Hint: Use the PTE_SYSCALL constant when calling sys_page_map. // Hint: Don't forget to round addr down. void flush_block(void *addr) { addr = (void *) ROUNDDOWN(addr, PGSIZE); uint32_t sectno = ((uint32_t)addr - DISKMAP) / SECTSIZE; uint32_t blockno = (sectno / BLKSECTS); if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("flush_block of bad va %08x", addr); // LAB 5: Your code here. if(va_is_dirty(addr) && va_is_mapped(addr)) { ide_write(sectno, addr, BLKSECTS); sys_page_map(0, addr, 0, addr, (PTE_SYSCALL)); BC_DEBUG("Wrote block %08x, now mapped r/o\n", blockno); } }
// Flush the contents of the block containing VA out to disk if // necessary, then clear the PTE_D bit using sys_page_map. // If the block is not in the block cache or is not dirty, does // nothing. // Hint: Use va_is_mapped, va_is_dirty, and ide_write. // Hint: Use the PTE_SYSCALL constant when calling sys_page_map. // Hint: Don't forget to round addr down. void flush_block(void *addr) { uint64_t blockno = ((uint64_t)addr - DISKMAP) / BLKSIZE; int r; if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("flush_block of bad va %08x", addr); // LAB 5: Your code here. if((va_is_mapped(addr))&&(va_is_dirty(addr))) #ifndef VMM_GUEST ide_write(blockno*BLKSECTS, ROUNDDOWN(addr,BLKSIZE), BLKSECTS); #else host_write(blockno*BLKSECTS, ROUNDDOWN(addr,BLKSIZE), BLKSECTS); #endif if((va_is_mapped(addr)) && ((r = sys_page_map(0, ROUNDDOWN(addr,PGSIZE), 0, ROUNDDOWN(addr,PGSIZE), PTE_SYSCALL&~PTE_D)) < 0)) panic("Couldn't flush disk page%e",r); }
// Flush the contents of the block containing VA out to disk if // necessary, then clear the PTE_D bit using sys_page_map. // If the block is not in the block cache or is not dirty, does // nothing. // Hint: Use va_is_mapped, va_is_dirty, and ide_write. // Hint: Use the PTE_SYSCALL constant when calling sys_page_map. // Hint: Don't forget to round addr down. void flush_block(void *addr) { uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("flush_block of bad va %08x", addr); // LAB 5: Your code here. addr = ROUNDDOWN(addr, PGSIZE); if (!va_is_mapped(addr) || !va_is_dirty(addr)) return; ide_write(blockno * BLKSECTS, addr, BLKSECTS); if (sys_page_map(0, addr, 0, addr, PTE_SYSCALL) < 0) panic("bc.c/flush_block: map page failed.\n"); //panic("flush_block not implemented"); }
/* 将内存中bitmap第bit_idx位所在的512字节同步到硬盘 */ void bitmap_sync(struct partition* part, uint32_t bit_idx, uint8_t btmp_type) { uint32_t off_sec = bit_idx / 4096; // 本i结点索引相对于位图的扇区偏移量 uint32_t off_size = off_sec * BLOCK_SIZE; // 本i结点索引相对于位图的字节偏移量 uint32_t sec_lba; uint8_t* bitmap_off; /* 需要被同步到硬盘的位图只有inode_bitmap和block_bitmap */ switch (btmp_type) { case INODE_BITMAP: sec_lba = part->sb->inode_bitmap_lba + off_sec; bitmap_off = part->inode_bitmap.bits + off_size; break; case BLOCK_BITMAP: sec_lba = part->sb->block_bitmap_lba + off_sec; bitmap_off = part->block_bitmap.bits + off_size; break; } ide_write(part->my_disk, sec_lba, bitmap_off, 1); }
// Flush the contents of the block containing VA out to disk if // necessary, then clear the PTE_D bit using sys_page_map. // If the block is not in the block cache or is not dirty, does // nothing. // Hint: Use va_is_mapped, va_is_dirty, and ide_write. // Hint: Use the PTE_SYSCALL constant when calling sys_page_map. // Hint: Don't forget to round addr down. void flush_block(void *addr) { uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("flush_block of bad va %08x", addr); // LAB 5: Your code here. if( !va_is_mapped(addr) || !(uvpt[PGNUM(addr)] & PTE_D)) { /* no need to flush */ return; } int r; addr = ROUNDDOWN(addr, PGSIZE); if( (r = ide_write(blockno * BLKSECTS, addr, (PGSIZE/SECTSIZE))) != 0) { panic("in flush_block, ide_write: %e", r); } if ((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL)) < 0) panic("in sys_page_map, sys_page_map: %e", r); }
// Copy the current contents of the block out to disk. // Then clear the PTE_D bit using sys_page_map. // Hint: Use ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. void write_block(uint32_t blockno) { int r; char *addr; if (!block_is_mapped(blockno)) panic("write unmapped block %08x", blockno); // Write the disk block and clear PTE_D. // LAB 5: Your code here. addr = diskaddr(blockno); r = ide_write(blockno * BLKSECTS, addr, BLKSECTS); if (r) panic("write_block(): ide_write() failed: %e\n", r); r = sys_page_map(0, addr, 0, addr, vpt[VPN(addr)] & PTE_USER); if (r) panic("write_block(): sys_page_map() failed: %e\n", r); }
// Copy the current contents of the block out to disk. // Then clear the PTE_D bit using sys_page_map. // Hint: Use ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. void write_block(uint32_t blockno) { char *addr; if (!block_is_mapped(blockno)) panic("write unmapped block %08x", blockno); // Write the disk block and clear PTE_D. // LAB 5: Your code here. addr = diskaddr(blockno); if(va_is_dirty(addr) == 0){ cprintf("va isn't dirty!\n"); return; } if(ide_write(blockno * BLKSECTS, addr, BLKSECTS) < 0) panic("write_block ide_write fail!\n"); if(sys_page_map(0,addr,0,addr, PTE_USER) < 0) panic("write_block sys_page_map fail!\n"); return; }
// Flush the contents of the block containing VA out to disk if // necessary, then clear the PTE_D bit using sys_page_map. // If the block is not in the block cache or is not dirty, does // nothing. // Hint: Use va_is_mapped, va_is_dirty, and ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. // Hint: Don't forget to round addr down. void flush_block(void *addr) { uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("flush_block of bad va %08x", addr); // LAB 5: Your code here. int r; void *blkva; blkva=ROUNDDOWN(addr,BLKSIZE); if(va_is_mapped(addr)&&va_is_dirty(addr)) { ide_write(blockno*BLKSECTS,blkva,BLKSECTS); if((r=sys_page_map(0,blkva,0,blkva,PTE_USER))<0) panic("page mapping failed:%e\n",r); } //panic("flush_block not implemented"); }