% Exam Template for UMTYMP and Math Department courses
%
% Using Philip Hirschhorn's exam.cls: http://www-math.mit.edu/~psh/#ExamCls
%
% run pdflatex on a finished exam at least three times to do the grading table on front page.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% These lines can probably stay unchanged, although you can remove the last
% two packages if you're not making pictures with tikz.
\documentclass[11pt]{exam}
\RequirePackage{amssymb, amsfonts, amsmath, latexsym, verbatim, xspace, setspace}
\RequirePackage{tikz, pgflibraryplotmarks}

% By default LaTeX uses large margins.  This doesn't work well on exams; problems
% end up in the "middle" of the page, reducing the amount of space for students
% to work on them.
\usepackage[margin=1in]{geometry}
\usepackage{afterpage}

% Here's where you edit the Class, Exam, Date, etc.
\newcommand{\class}{CS 238P}
\newcommand{\term}{Spring 2019}
\newcommand{\examnum}{Midterm}
\newcommand{\examdate}{05/15/2018}
\newcommand{\timelimit}{6:30pm - 7:50pm}

% For an exam, single spacing is most appropriate
\singlespacing
% \onehalfspacing
% \doublespacing

% For an exam, we generally want to turn off paragraph indentation
\parindent 0ex

\begin{document} 

% These commands set up the running header on the top of the exam pages
\pagestyle{head}
\firstpageheader{}{}{}
\runningheader{\class}{\examnum\ - Page \thepage\ of
\numpages}{\fbox{\rule{2in}{0pt}\rule[-0.5ex]{0pt}{5ex}}}
\runningheadrule

\begin{flushright}
\begin{tabular}{p{2.8in} r l}
%\textbf{\class} & \textbf{Name (Print):} & \makebox[2in]{\hrulefill}\\
  \textbf{\class} & \textbf{Name (Print):} &
  \fbox{\rule{2in}{0pt}\rule[-0.5ex]{0pt}{5ex}}\\
\textbf{\term} &&\\
\textbf{\examnum} &&\\
\textbf{\examdate} &&\\
\textbf{Time Limit: \timelimit} & & \\
\end{tabular}\\
\end{flushright}
\rule[1ex]{\textwidth}{.1pt}




%\begin{minipage}[t]{3.7in}
%\vspace{0pt}
\begin{itemize}

\item \textbf{Don't forget to write your name on this exam.} 

\item \textbf{This is an open book, open notes exam. But no online or 
    in-class chatting.  } 

    
\item \textbf{Ask us if you something is confusing in the questions.}

\item \textbf{Organize your work}, in a reasonably neat and coherent way, in
the space provided. Work scattered all over the page without a clear ordering will 
receive very little credit.  

\item \textbf{Mysterious or unsupported answers will not receive full
credit}.  A correct answer, unsupported by explanation will receive no credit; 
an incorrect answer supported by substantially correct explanations might still 
receive partial credit.

\item If you need more space, use the back of the pages; clearly indicate when you have done this.
\end{itemize}

%Do not write in the table to the right.
%\end{minipage}
%\hfill

%\begin{minipage}[t]{2.3in}
%\vspace{0pt}
%\cellwidth{3em}
%\gradetablestretch{2}
\vqword{Problem}
\addpoints % required here by exam.cls, even though questions haven't started yet.	
\gradetable[v]%[pages]  % Use [pages] to have grading table by page instead of question

%\end{minipage}
\newpage % End of cover page

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% See http://www-math.mit.edu/~psh/#ExamCls for full documentation, but the questions
% below give an idea of how to write questions [with parts] and have the points
% tracked automatically on the cover page.
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{questions}

% Basic question
\addpoints
\question OS Interfaces 

Xv6 imlements the PIPE case in its shell in the following way:
\begin{verbatim}
8650   case PIPE:
8651     pcmd = (struct pipecmd*)cmd;
8652     if(pipe(p) < 0)
8653       panic("pipe");
8654     if(fork1() == 0){
8655       close(1);
8656       dup(p[1]);
8657       close(p[0]);
8658       close(p[1]);
8659       runcmd(pcmd−>left);
8660     }
8661     if(fork1() == 0){
8662       close(0);
8663       dup(p[0]);
8664       close(p[0]);
8665       close(p[1]);
8666       runcmd(pcmd−>right);
8667     }
8668     close(p[0]);
8669     close(p[1]);
8670     wait();
8671     wait();
8672     break;
\end{verbatim}


\begin{parts} 
\part[5] Explain what lines 8654--8659 are doing? 

\textbf{Answer:} Line 8654 forks a new process and checks if execution is inside the ``child''. If yes the 
code closes the standard output (descriptor 1) (line 8655), duplicates the write and of the pipe into the 
standard output (line 8656), and closes both read and write ends of the pipe (lines 8657 and 8658). It then 
execs the left part of the ``pipe'' with the \texttt{runcmd} function (line 8659). 

\vfill

\newpage

\part[10] Bob who likes to optimize his code decides that it's not necessary to fork twice, after all 
the \texttt{fork()} system call takes time. He re-writes his xv6 shell like this
\begin{verbatim}
8650   case PIPE:
8651     pcmd = (struct pipecmd*)cmd;
8652     if(pipe(p) < 0)
8653       panic("pipe");
8654     if(fork1() == 0){
8655       close(1);
8656       dup(p[1]);
8657       close(p[0]);
8658       close(p[1]);
8659       runcmd(pcmd−>left);
8660     }
8661     wait()
8662     close(0);
8663     dup(p[0]);
8664     close(p[0]);
8665     close(p[1]);
8666     runcmd(pcmd−>right);
8672     break;
\end{verbatim}

He runs it a couple of times and everything seems to work, so he shows his optimization to Alice, an 
experienced UNIX hacker. Alice however says that Bob's code is horribly wrong. 
Can you explain what she means, and what is wrong with Bob's code? 

\textbf{Answer:} Bob's code waits for the left side of the pipe to finish. Since pipes have finite capacity, 
e.g., 512 bytes in xv6, some left sides finish successfully, but longer outputs fill the pipe completely before finishing. 
In this case, the left side will be waiting for the right side to clean up some space by reading data from the pipe. However, 
since the right side of the pipe does not start before the left finishes this never happens. TLDR: if left side of the 
pipe produces an output larger than the size of the pipe's buffer, Bob's code gets stuck forever.  



\vfill

\newpage

\part [15]
 
Write a program that uses the UNIX system call API, as described in Chapter 0
of the xv6 book. The program \texttt{tee} that reads from standard input and 
writes to standard output and to a file that is passed as a command line argument.

\vfill 


\end{parts} 


\newpage
% Basic question
\addpoints
\question Basic page tables.


Consider the following 32-bit x86 page table setup.

\begin{verbatim}
%cr3 holds 0x00000000.
\end{verbatim}

The Page Directory Page at physical address 0x00000000:

\begin{verbatim}
PDE 0: PPN=0x00001, PTE_P, PTE_U, PTE_W
\end{verbatim}

... all other PDEs are zero

The Page Table Page at physical address 0x00001000 (which is PPN 0x00001):

\begin{verbatim}
PTE 0: PPN=0x00000, PTE_P, PTE_U, PTE_W
PTE 1: PPN=0x00001, PTE_P, PTE_U, PTE_W
\end{verbatim}

... all other PTEs are zero

\begin{parts}
\part[5] 

What are all virtual addresses mapped by this page table? 

\textbf{Answer:} The page table maps two consequtive virtual pages (addresses 0x0-0x2000) to 
two consequtive physical pages (physical addresses 0x0-0x2000).  


\vfill 


\part[5] Extend this page table to map virtual address 0x100000 which is 1MB. 


\textbf{Answer:} Lets assume that we would like to map the virtual address 0x100000 to physical 
address 0x0. Then we need to convert 0x100000 into 10:10:12 form to see which entries of the 
page table we need to use for this mapping. The top 10 bits are 0x0, middle ten are 0x100 (this 
is 1, and the 
lower 12 bits are 0x0. The page table should be extended with the following entry: 

\begin{verbatim}
PTE 256: PPN=0x00000, PTE_P, PTE_U, PTE_W
\end{verbatim}

\vfill
\end{parts} 


\newpage \addpoints

\question Stack and calling conventions. 

xv6 implements exec() system call like this: 
\begin{verbatim}
6600 #include "types.h"
6601 #include "param.h"
6602 #include "memlayout.h"
6603 #include "mmu.h"
6604 #include "proc.h"
6605 #include "defs.h"
6606 #include "x86.h"
6607 #include "elf.h"
6608 
6609 int
6610 exec(char *path, char **argv)
6611 {
6612   char *s, *last;
6613   int i, off;
6614   uint argc, sz, sp, ustack[3+MAXARG+1];
6615   struct elfhdr elf;
6616   struct inode *ip;
6617   struct proghdr ph;
6618   pde_t *pgdir, *oldpgdir;
6619   struct proc *curproc = myproc();
6620 
6621   begin_op();
6622 
6623   if((ip = namei(path)) == 0){
6624     end_op();
6625     cprintf("exec: fail\n");
6626     return −1;
6627   }
6628   ilock(ip);
6629   pgdir = 0;
6630 
6631   // Check ELF header
6632   if(readi(ip, (char*)&elf, 0, sizeof(elf)) != sizeof(elf))
6633     goto bad;
6634   if(elf.magic != ELF_MAGIC)
6635     goto bad;
6636 
6637   if((pgdir = setupkvm()) == 0)
6638     goto bad;
6639 
6640   // Load program into memory.
6641   sz = 0;
6642   for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
6643     if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
6644       goto bad;
6645     if(ph.type != ELF_PROG_LOAD)
6646       continue;
6647     if(ph.memsz < ph.filesz)6648       goto bad;
6649     if(ph.vaddr + ph.memsz < ph.vaddr)
6650       goto bad;
6651     if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0)
6652       goto bad;
6653     if(ph.vaddr % PGSIZE != 0)
6654       goto bad;
6655     if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0)
6656       goto bad;
6657   }
6658   iunlockput(ip);
6659   end_op();
6660   ip = 0;
6661 
6662   // Allocate two pages at the next page boundary.
6663   // Make the first inaccessible.  Use the second as the user stack.
6664   sz = PGROUNDUP(sz);
6665   if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0)
6666     goto bad;
6667   clearpteu(pgdir, (char*)(sz − 2*PGSIZE));
6668   sp = sz;
6669 
6670   // Push argument strings, prepare rest of stack in ustack.
6671   for(argc = 0; argv[argc]; argc++) {
6672     if(argc >= MAXARG)
6673       goto bad;
6674     sp = (sp − (strlen(argv[argc]) + 1)) & ~3;
6675     if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
6676       goto bad;
6677     ustack[3+argc] = sp;
6678   }
6679   ustack[3+argc] = 0;
6680 
6681   ustack[0] = 0xffffffff;  // fake return PC
6682   ustack[1] = argc;
6683   ustack[2] = sp − (argc+1)*4;  // argv pointer
6684 
6685   sp −= (3+argc+1) * 4;
6686   if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0)
6687     goto bad;
6688 
6689   // Save program name for debugging.
6690   for(last=s=path; *s; s++)
6691     if(*s == ’/’)
6692       last = s+1;
6693   safestrcpy(curproc−>name, last, sizeof(curproc−>name));
6694 
6695   // Commit to the user image.
6696   oldpgdir = curproc−>pgdir;
6697   curproc−>pgdir = pgdir;
6698   curproc−>sz = sz;
6699   curproc−>tf−>eip = elf.entry
6700   curproc−>tf−>esp = sp;
6701   switchuvm(curproc);
6702   freevm(oldpgdir);
6703   return 0;
6704 
6705  bad:
6706   if(pgdir)
6707     freevm(pgdir);
6708   if(ip){
6709     iunlockput(ip);
6710     end_op();
6711   }
6712   return −1;
6713 }
\end{verbatim}

\begin{parts} 

\part[5] Which lines in this code create the guard page? Explain what these lines do.

\textbf{Answer:} The following lines create the guard and stack pages:  

\begin{verbatim}
6662   // Allocate two pages at the next page boundary.
6663   // Make the first inaccessible.  Use the second as the user stack.
6664   sz = PGROUNDUP(sz);
6665   if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0)
6666     goto bad;
6667   clearpteu(pgdir, (char*)(sz − 2*PGSIZE));
6668   sp = sz;
\end{verbatim}

Line 6665 allocates two pages right above the address \texttt{sz} that is used by the 
process for text and data (loaded from the ELF file). The \texttt{clearpteu()} function 
clears the ``user accessible'' flag for one of the pages making it a guard page. Line 
6668 remembers where the stack memory is allocated by saving it into the 
\texttt{sp} pointer. 

\vfill

\newpage
\part[5] What is the purpose of the guard page? 


\textbf{Answer:} The guard page allows the operating system to catch an exception when the program 
runs out of memory on the page allocated for the stack. Without the guard page the program would 
silently corrupt it's own data section that would overlap with the stack and would crash in some 
misterious ways. 
 
\vfill

\part[5] Bob decides that he wants to allocate the stack in the first page of the process' virtual address space (i.e., 0x0 - 0xfff). What does he need to change in the \texttt{exec()}'s implementation above? Write the code for the new lines.  

\textbf{Answer:} Bob deletes lines 6662-6668, and instead adds the following lines right between 
lines 6641-6642

\begin{verbatim}
if((sz = allocuvm(pgdir, sz, sz + PGSIZE)) == 0)
  goto bad;
sp = sz;
\end{verbatim}

\vfill

\newpage

\part[10] Bob shows his new code to Alice, but she again says that it's horribly wrong. Can you explain what is wrong with Bob's code and why even if it works on some programs it will sooner or later fail. 

\textbf{Answer:} Bob's code boots and shell starts, and even some commands like 

\begin{verbatim}
cat README
\end{verbatim}

work, but something like \texttt{ls} doesn't. This is because user-level programs 
in xv6 are linked to have their text section at address 0x0, right where Bob wants to 
have stack. For some lucky programs the fact that stack overwrites part of the program 
at the top of the first page (or when the program text is smaller than one page) the code 
runs. But in general as soon as the stack modifies the program's code (text section) the program 
fails in some unpredictable manner. 

\vfill


\part[10] After working for a while Alice and Bob fix Bob's implementation of \texttt{exec()}. Bob is happy, he also says that his code is better since it saves one page that is normally wasted for the guard page. Do you think he is right, and if you allocate the stack at address 0x0-0xfff (which is 4KB) the guard page is not needed? Explain your answer. 

\textbf{Answer:} Alice fixes the Makefile to link all xv6 programs to start at the second page, e.g., 

\begin{verbatim}
 _%: %.o $(ULIB)
-       $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $@ $^
+       $(LD) $(LDFLAGS) -N -e main -Ttext 0x1000 -o $@ $^
\end{verbatim}

Now Bob's code works, and he is right, his code doesn't need a guard page since even if stack overflows it wraps around the address space and tries to write addresses near the very top of the address space (e.g., 0xfffffffc). These addresses however are mapped by the kernel as not ``user-accessible'' (they are mapped as part of the 4th region in the memory map, i.e., the I/O region), and hence the kernel catches an exception and kills the process. 



\vfill




\end{parts}


\newpage \addpoints

\question Physical and virtual memory allocation

\begin{parts} 

\part[5] Xv6 uses 234MB of physical memory. But how does it keep track of
available physical memory? Specifically, explain the following: the xv6 memory
allocator (kalloc()) always returns a virtual address, but how does the
allocator know which physical page to use for each virtual address it
allocates? 

\textbf{Answer:} The allocator always returns one of the virtual addresses from the 
pool of virtual pages that was constructed when the kernel booted (i.e., \texttt{kinit1()} and 
\texttt{kinit2()} functions). These functions map these virtual pages one-to-one to physical 
pages, but with a 2GB shift, i.e., the virtual address is always equals physical address of the 
page plus 2GB. The allocator itself does not know anything about physical addresses of the pages 
it manages, however, the rest of the kernel knows that this is how the pool was constructed and 
hence it uses the 2GB shift for converting between physical and virtual page addresses. 

\vfill

\end{parts}

\newpage \addpoints

\end{questions}
\afterpage{\null\newpage}
\afterpage{\null\newpage}
\end{document}
