Lec17 vm for app
課程連結:6.S081 Lecture 17: Virtual Memory for Applications
課程連結:6.S081 Lecture 17: Virtual Memory for Applications
Lab 連結:Lab: mmap Lab: mmap (hard) The mmap and munmap system calls allow UNIX programs to exert detailed control over their address spaces. They can be used to share memory among processes, to map files into process address spaces, and as part of user-level page fault schemes such as the garbage-collection algorithms discussed in lecture. In this lab you’ll add mmap and munmap to xv6, focusing on memory-mapped files. 目前的理解會像是把 memory address map 到一個 file 中,可以有多個 process share 同一份資料的好處 ...
課程連結:6.S081 Fall 2020 Lecture 21: Networking Protocal nesting header 的 type 決定了之後的內容要如何解讀 The OS network stack tcpdump 的解析 Queue 的使用 影片中有提及不管是在那一個層級的 stack 當中,queue 的使用都是很常見的 可能會有一個 buffer allocator MBUF E1000 NIC 這在 lab: network driver 中會運用的一個 NIC, 影片中有提及跟現代的 NIC 比較起來 現在的 NIC 當中有做一些 check Livelock Problem 最後的結論是用 Polling 來解決
這一篇筆記主要是為了 lab: network driver 中,要我們先讀一下 xv6 book ch5: Interrupts and device drivers,這篇文章是我自己的筆記 Interrupts and device drivers Driver 需要了解 device 的 interface,可能很複雜或是文件寫得很差 Device 通常可以製造一些 interrupt, 在 xv6 中,這在 devintr() 中處理 kernel/trap.c: devintr(): 像是這裡回傳是否為 device interrupt // check if it's an external interrupt or software interrupt, // and handle it. // returns 2 if timer interrupt, // 1 if other device, // 0 if not recognized. int devintr() { uint64 scause = r_scause(); if((scause & 0x8000000000000000L) && (scause & 0xff) == 9){ // this is a supervisor external interrupt, via PLIC. // irq indicates which device interrupted. int irq = plic_claim(); if(irq == UART0_IRQ){ uartintr(); } else if(irq == VIRTIO0_IRQ){ virtio_disk_intr(); } #ifdef LAB_NET else if(irq == E1000_IRQ){ e1000_intr(); } #endif else if(irq){ printf("unexpected interrupt irq=%d\n", irq); } // the PLIC allows each device to raise at most one // interrupt at a time; tell the PLIC the device is // now allowed to interrupt again. if(irq) plic_complete(irq); return 1; } else if(scause == 0x8000000000000001L){ // software interrupt from a machine-mode timer interrupt, // forwarded by timervec in kernelvec.S. if(cpuid() == 0){ clockintr(); } // acknowledge the software interrupt by clearing // the SSIP bit in sip. w_sip(r_sip() & ~2); return 2; } else { return 0; } } 許多 device driver 分為兩個部份: process’s kernel thread interrupt time 接著分別使用 Console input/output 來看 driver 如何運作 ...
Initialize 我們首先觀察 lab net 所提供的初始化過程,大致上了解要如何從 E1000 manual 轉換到程式碼 kernel/main.c: main() kernel/pci.c: pci_init() kernel/e1000.c: e1000_init(uint32 *xregs) regs[XXX] = OOO kernel/sysnet.c: sockinit() initlock() kernel/pci.c: pci_init() void pci_init() { // we'll place the e1000 registers at this address. // vm.c maps this range. // 我們會把 e1000 registers 放到這個位置 // 如下圖,他會被放在 unused and other I/O devices 的區塊 // vm.c 會負責做這個 mapping uint64 e1000_regs = 0x40000000L; // qemu -machine virt puts PCIe config space here. // vm.c maps this range. // 這裡則是在 mapping PCIe config // 跟前面一樣,是放在 unused and other I/O devices 的區塊 // ECAM for Extended Configuration Access Mechanism uint32 *ecam = (uint32 *) 0x30000000L; // look at each possible PCI device on bus 0. // bus == 0 是固定的,只掃描 Primary Bus // dev: 0 ~ 31 設備號碼,每一個代表一個獨立設備例如 E1000 網卡、顯示卡,現在要尋找 E1000 // func: 功能號碼,每一個設備可以有多個 function, 這裡只需要尋找第 0 個功能,E1000 也只有一個功能 // offset: 指向配置空間中特定 4 位元組暫存器的偏移量, 設為 0 // off: 透過上面的資訊取得總 offset for(int dev = 0; dev < 32; dev++){ int bus = 0; int func = 0; int offset = 0; uint32 off = (bus << 16) | (dev << 11) | (func << 8) | (offset); volatile uint32 *base = ecam + off; uint32 id = base[0]; // 100e:8086 is an e1000 if(id == 0x100e8086){ // command and status register. // bit 0 : I/O access enable // bit 1 : memory access enable // bit 2 : enable mastering base[1] = 7; __sync_synchronize(); for(int i = 0; i < 6; i++){ uint32 old = base[4+i]; // writing all 1's to the BAR causes it to be // replaced with its size. base[4+i] = 0xffffffff; __sync_synchronize(); base[4+i] = old; } // tell the e1000 to reveal its registers at // physical address 0x40000000. base[4+0] = e1000_regs; e1000_init((uint32*)e1000_regs); } } } ...
Lab 連結:Lab net: Network driver Background You’ll use a network device called the E1000 to handle network communication. To xv6 (and the driver you write), the E1000 looks like a real piece of hardware connected to a real Ethernet local area network (LAN). In fact, the E1000 your driver will talk to is an emulation provided by qemu, connected to a LAN that is also emulated by qemu. On this emulated LAN, xv6 (the “guest”) has an IP address of 10.0.2.15. Qemu also arranges for the computer running qemu to appear on the LAN with IP address 10.0.2.2. When xv6 uses the E1000 to send a packet to 10.0.2.2, qemu delivers the packet to the appropriate application on the (real) computer on which you’re running qemu (the “host”). ...