Overview of address space handling: -For simplicity (so that kernel code doesn't need to change) we map kernel memory directly from logical to physical addresses. -Threads are part of the kernel; they use the kernel's page directory and page table. -Use each logical address only once over all processes. That should simplify some things. HOWEVER: -Screen memory will be mapped into each process's address space at the same address for each process. -Kernel memory will be mapped from logical to physical without translation everywhere. While a process rarely needs direct access to kernel memory, this will probably simplify some things like system calls. -As the stack is pinned we don't need to handle it in paging code. For simplicity we can have the stack at the same logical address in each process. If there are problems with that we give it a logical address resulting from adding a fixed offset to the stack's *physical* address. -I'm not sure yet how to handle concurrency. We need one spinlock for each group of data structures that needs internal consistency. -I have not said anything about privilege bits. The kernel would still work if every process was allowed access to every memory location. Protection would be a "nice to have". In a real OS it is vital, of course. init_memory(): -Set up the page directory and page table for kernel space. We will only need one page table as it can cover 4 MB which is enough. -Set the paging flag in CR0 to enable paging -Set up a data structure to keep track of free pages. As we only have 29 pages to take care of, a simple bitmap in a (32 bit) integer might suffice. setup_page_table(): -Set up the page directory, page table, and pages for code and data. -Mark the code and data pages as not present. -page_alloc(TRUE) a physical page for the stack and set up a page for the stack. -Mark the stack page as present. page_fault_handler(): -ASSERT() that the fault address actually belongs to the process using the pcb's swap_size entry. In a real OS we'd terminate the process if that happened (SIGSEGV on Linux). -Call page_swap_in() page_alloc(): -page_swap_out() a random page to floppy if no physical page is available. To do this we might need to search through all pcbs if we don't keep track of allocations in some other way. See description of init_memory(). -It is simpler to first choose a random process and then a random page in that process than to choose a truly random page. The simpler method has the disadvantage that not every page will have the same chance of getting swapped out. page_swap_in(): -We can assume that the page belongs to the current_running process. -Call page_alloc() to allocate physical page. -Find the sectors we need to swap in using the pcb's fault_addr and swap_loc entries. -Read the sectors from floppy -Mark the page as present. page_swap_out(): -Find the process to which the page belongs. This is simplified by the fact that every logical address in the address range of processes is only mapped in one process. Still, we usually need to search through some pcbs until we find the right one. This can be improved by some special data structure in the kernel... -Write the page to diskette -In the data structure keeping track of free pages, mark the physical page as free. (In practice we can leave it marked as busy because it will be reused right away.) -In the page table of the process whose page we swapped out, mark the page as not present.