Hello, in this lecture we will wrap up this section by writing setup uvm function. The setup uvm function,
as opposed to setup kvm function,
will create a virtual space for user applications. In the system,
the base of the virtual memory for user space is 400000.
And we map only one page for the user programs which means the code, data and stack of the programs
are located in the same 2m page.
OK, let's get started.
We opened the memory.c file.
The setup uvm function
returns Boolean value to tell us the status of the operation.
It takes three parameters, the address of page map level 4 table,
the location of the program.
After we allocate a page and map virtual address 400000 to this page,
we will copy the program instructions and data to it. The last parameter specifies the size of the data we need to copy
.
In the function, the first thing we will do in the function is define a variable status
and initialize it with false.
Then we allocate a page which is used to store the code and data of the program. So we call function kalloc
.
If we allocate a page successfully,
we will zero the page using function memset because it could include random values.
The next thing we are going to do is we are going to map the page using map pages.
We have seen it before.
The first argument we pass to it is the address of pml4 table. We pass map to it
in this case, the next two arguments are the start and end address of the virtual space we want map,
400000 in this case.
Because we implement only one page for user application, we add page size
to the base address.
Next one is the base of the physical page we want to map into
which is the page we allocate. We use macro v2p to convert the virtual address
to physical address.
The last one stores the attributes of the page. So we pass attribute present, writable
the last one is user
In this example, the page is used for the user program. So we add pte user in the attributes.
After the function returns, we check the status,
if it succeeds,
we just copy the data to the page. The function we use is memcpy.
The first argument is the page to which we copy the data,
next one is the address of the data.
So we pass start.
The last one is the size of the data we want to copy.
If the status is false, we will free the page as well as translation tables. So here we use
free vm.
And we pass the address of pml4 table to this function.
In the last lecture, we commented out the free pages function.
Now we can use it to free the VM.
The base of the virtual space for user program is 400000 in the system
and the end of the space is 400000
plus page size. So what it does is just free one page.
The next three functions will free the page translation tables. Note that we only free the translation tables and user pages.
The kernel pages where our kernel resides are not freed, because in our system,
we can have multiple vms and each vm is mapped to the same kernel pages,
the kernel is residing in the memory until we shut down the system.
Therefore, when we free a vm,
we will not free the kernel page because the kernel page is shared among all the vms.
Ok, at the end of setup uvm function,
we return the status.
This function is used in other modules, so we add the declaration in the header file.
Alright, we have setup uvm and free vm functions ready to use.
Before we wrap up this section, let’s focus on setup kvm function. In the next section, we will implement processes.
Each process has its own address space, any changes in one address space will not affect other address spaces
.
So in the system, we setup kernel space and user space for each process.
The setup kvm function will be called in the process module. So we add the declaration in the header file.
It returns the address of pml4 table which is used when we switch vm.
In the function, we define a variable to save the address of the new page
we still use the name page map
and we allow the allocation fails in this case.
So we use if statement to check the return value instead of assert.
If the page is valid, we zero the page just as we did before.
In this example, we don’t assume the status of the map pages either. Instead, we check the return value
,
if the operation fails, we just free the vm
and save the value 0 to variable map.
The last thing we will do is return the address of pml4 table.
Another thing we need to do after we use free vm in the if statement is that in function
free pages,
we used assert to check the present bit of the page directory entry.
At this point, we allow the page not present which means if the present bit is cleared,
we just skip this part and continue the loop.
In the initialize kvm function,
we will save the return value of function setup kvm to the variable page map.
And in this case, we don’t need global variable.
Then we assert
page map
is allocated successfully, because we are now at the kernel initialization stage. If the operation fails
,
we stop the system.
It’s worth mentioning that in the setup uvm function, we just map one page.
So if the operation fails, it means that the mapping is not done. When we call free vm function,
this page will not be freed.
Therefore, we have to free the page manually,
otherwise we will have memory leak.
Ok. When I test it on the real machine with more than 1g of ram, the assertion fails
at kfree function.
It turns out we have a typo in the free region function. The v here should be start.
So we change v
to start.
Ok, that’s it. In the next section, we will use these functions to build the process module.
See you in the next section.