Compare commits
7 Commits
03b296f7e1
...
lab3
| Author | SHA1 | Date | |
|---|---|---|---|
| 7965d399dc | |||
| 5e04fb305e | |||
| d943a2be37 | |||
| 34e9433d15 | |||
| 9bec3d83bd | |||
| 0289ec3b3e | |||
| 46cc5c9478 |
22
answers-lab2.txt
Normal file
22
answers-lab2.txt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
1. The entry given by PDX(UVPT) is mapped to the page directory itself,
|
||||||
|
to allow programs to read existing memory mappings. The entry at PDX(UPAGES)
|
||||||
|
is mapped to the pages variable in memory so that the kernel (and potentially other ring 0 programs) can access it. The entry pointed to by PDX(KSTACKTOP-KSTACKSIZE) is mapped
|
||||||
|
to the bootstack location. Finally, both the memory pointed to by 0 and PDX(KERNBASE) are mapped to kernel memory. However, the mappings at VA 0 are read-only, so user programs can't touch them, while the mappings at PDX(KERNBASE) are kernel-private and RW.
|
||||||
|
|
||||||
|
A table could be as follows:
|
||||||
|
|
||||||
|
400 - Kernel memory
|
||||||
|
... - Kernel memory
|
||||||
|
3c0 - Kernel memory
|
||||||
|
3bf - Kernel Stack
|
||||||
|
3bd - UVPT
|
||||||
|
3bc - UPAGES
|
||||||
|
|
||||||
|
|
||||||
|
2. The kernel memory is mapped as kernel read write. This means there are several flags set in the kernel page directory and page table entries, which indicate that this is restricted memory. The lower 3 bits of the CS register will be checked when an access to this memory is made, and, if they are not 0 or 1 (indicating kernel code), the CPU generates a fault, and the user program gives up control back to the OS. Thus, unless a program is started in ring 0, it will not be able to read or write kernel memory, as it should.
|
||||||
|
|
||||||
|
3. The absolute maximum is 4GB, since we use 32-bit integers for referencing memory. Some of this memory is used for the kernel itself, as well as for the page directory and tables.
|
||||||
|
|
||||||
|
4. The page directory and the corresponding pages are all 4kb. The page directory can have 1024 entries, and each of these point to a page table. Thus, we use approximatey 4MB (slightly more than that, actually, due to the size of the page directory itself) of memory. Additionally, the "pages" structs (which are used to keep track of available physical pages), will require ~1000000 entries, each of which is between 6 and 8 bytes (depending on whether GCC aligns struct sizes). This means another 8MB is used to keep track of free pages, to a total of around 12MB.
|
||||||
|
|
||||||
|
5. We switch to high EIP when we jump to "relocated". Relocated is a label, and a symbol that's inserted by the linker. Since the linker is configured to link the kernel high, relocated points to the upper portion of memory, where KERNBASE is. However, the entry page directory, just like our full page directory later on, sets up two mappings, one starting at 0 (creating a one to one mapping between some of the virtual addresses and their physical counterparts), and one starting at KERNBASE. Thus, we can continue to run at a low EIP. The only reason I can think of as to why we NEED to make the switch, besides the elementary "the kernel links high", is that we need to be able to write to various symbols, also linked above KERNBASE.
|
||||||
18
answers-lab3.txt
Normal file
18
answers-lab3.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
1. Some interrupts receive a different "shape" of stack frame - the kernel pushes
|
||||||
|
an error code for some, but not for the others. We thus need individual handlers
|
||||||
|
that would make sure that what we have on the stack is consistent, and
|
||||||
|
then call one centralized function for that. The handlers additionally
|
||||||
|
are able to pass in a trap number to that centrallized function. This way, a lot
|
||||||
|
of code can be re-used.
|
||||||
|
|
||||||
|
Conceptually, each trap has a different semantic meaning. Thus, it makes no sense
|
||||||
|
to perform the same action for both traps - they don't mean the same thing.
|
||||||
|
|
||||||
|
2. The general protection fault occurs when a process can access memory, but not do something else with it. We do not want page faults to be trigger-able by users (this is the case for many other traps). Thus, when the user tries to invoke int 14,
|
||||||
|
it's not allowed to execute it from userspace, so it is thrown a general protection fault, which it then prints.
|
||||||
|
|
||||||
|
3. Unlike most other traps, the debugging trap should be possible to trigger from user code. If the "privillege level" is set to 0 in the IDT, when the INT3 occurs, the user does not have permission to call that interrupt,
|
||||||
|
and thus, a general protection fault occurs. In order to make it work correctly, the privillege level needs to be 3 (for userland).
|
||||||
|
|
||||||
|
4. It's probably so that users cannot deliberately trigger certain faults for malicious purposes. It doesn't make sense to trigger a page fault without properly setting up CR2, and even then, though I can't think
|
||||||
|
of anything right now, there's likely security issues that could arise if users can deliberately page fault their own process.
|
||||||
@@ -185,8 +185,6 @@ mem_init(void)
|
|||||||
boot_map_region(kern_pgdir,
|
boot_map_region(kern_pgdir,
|
||||||
UPAGES, ROUNDUP(pages_size, PGSIZE),
|
UPAGES, ROUNDUP(pages_size, PGSIZE),
|
||||||
PADDR(pages), PTE_U);
|
PADDR(pages), PTE_U);
|
||||||
kern_pgdir[PDX(UPAGES)] |= PTE_U;
|
|
||||||
kern_pgdir[PDX(UPAGES)] &= ~PTE_W;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Map the 'envs' array read-only by the user at linear address UENVS
|
// Map the 'envs' array read-only by the user at linear address UENVS
|
||||||
@@ -198,8 +196,6 @@ mem_init(void)
|
|||||||
boot_map_region(kern_pgdir,
|
boot_map_region(kern_pgdir,
|
||||||
UENVS, ROUNDUP(envs_size, PGSIZE),
|
UENVS, ROUNDUP(envs_size, PGSIZE),
|
||||||
PADDR(envs), PTE_U);
|
PADDR(envs), PTE_U);
|
||||||
kern_pgdir[PDX(UENVS)] |= PTE_U;
|
|
||||||
kern_pgdir[PDX(UPAGES)] &= ~PTE_W;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Use the physical memory that 'bootstack' refers to as the kernel
|
// Use the physical memory that 'bootstack' refers to as the kernel
|
||||||
@@ -215,8 +211,6 @@ mem_init(void)
|
|||||||
boot_map_region(kern_pgdir,
|
boot_map_region(kern_pgdir,
|
||||||
KSTACKTOP-KSTKSIZE, KSTKSIZE,
|
KSTACKTOP-KSTKSIZE, KSTKSIZE,
|
||||||
PADDR(bootstack), PTE_W);
|
PADDR(bootstack), PTE_W);
|
||||||
kern_pgdir[PDX(KSTACKTOP-KSTKSIZE)] |= PTE_W;
|
|
||||||
kern_pgdir[PDX(KSTACKTOP-KSTKSIZE)] &= ~PTE_U;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Map all of physical memory at KERNBASE.
|
// Map all of physical memory at KERNBASE.
|
||||||
@@ -229,9 +223,6 @@ mem_init(void)
|
|||||||
boot_map_region(kern_pgdir,
|
boot_map_region(kern_pgdir,
|
||||||
KERNBASE, 0x100000000 - KERNBASE,
|
KERNBASE, 0x100000000 - KERNBASE,
|
||||||
0, PTE_W);
|
0, PTE_W);
|
||||||
kern_pgdir[PDX(KERNBASE)] |= PTE_W | PTE_P;
|
|
||||||
kern_pgdir[PDX(KERNBASE)] &= ~PTE_U;
|
|
||||||
|
|
||||||
|
|
||||||
// Check that the initial page directory has been set up correctly.
|
// Check that the initial page directory has been set up correctly.
|
||||||
check_kern_pgdir();
|
check_kern_pgdir();
|
||||||
|
|||||||
Reference in New Issue
Block a user