When trying to set up virtual memory I'm a bit confused about where to go regarding mapping a given virtual address to a physical address. When working with x86 architecture and using IA-32E mode I have a function to map a new virtual page
int allocate_page(page_table_entry* p)
{
//Get Physical Block for this page table entry to point to
void* phys = getFreeBlock();
//Here I need to map the virtual entry to this physical page frame
}
According to the Intel Manual For a 4 level page table, the first 4 bits of the virtual address should give the Page Directory Table Pointer, the next 9 bits should give the Page Directory, the next 9 bits are used to find the Page Table, and the last 12 bits are used for the offset in the page frame, for a total of 52 bits. Does anybody have any resources or a suggestion of how I can get started implementing the rest of this function so that I can take a given virtual address and map it to a free page frame?
Related
My understanding is that the page table is already specified somewhere in memory, so I just need the page number to get frame number so I can get the physical address. How do i implement the page table so I can look up the frame number?
Given a virtual address
page_number = (virtual >> page_bits);
page_offset = (virtual & page_size);
physical = page_table[page_number] + page_offset;
How is the page table implemented?
I'm new on world of computing and computers ..I'm developing in C programming and really every time I get stuck in my thinking how really PC delete the old value if we modified it by new value, I mean:
lets assume I write on C like this
int i=6;
i=7;
then the value of i is 7, I know why because we have modified the old value by 7, but how does really the PC delete the previous value? I could believe just in "the previous value overwritten and it will be deleted" but I'm curious to know how really it's deleted by assigning modified value?
Is it like magic? still weird for me .. a good explanation would be really appreciated to convince me how PC use overwritten mode operation to delete previous values once we modifying on the same memory's address ..
Computers have a finite amount of storage. They overwrite that storage. It's not like a SSA model where every assignment creates a new variable. Computers really do change the value of an existing storage location.
The C language is defined in terms of every variable having its own memory location. Assigning a new value does not change the address. It's not a reference to a new immutable value, it's really mutating the storage for int i. Writing a new value implicitly destroys the previous contents of a variable. It doesn't go anywhere.
You can look at an example of using pointers to see that after int *p = &i; the value you get from *p changes after you do i=7; Or google up a tutorial on C pointers for more detail.
It's not "magic", just electrically how a memory cell naturally works. e.g. a single flip-flop can be changed from one state to another by applying an input signal along with a reset signal that tells it to forget its old value.
A physical analogy is a piece of paper with a pencil and eraser, not a big stack of fresh index cards. The "consumable" (pencil lead and eraser) is just electrical power. (Or more specifically, electric charge in CMOS logic. Some other kinds of digital logic require current to flow continuously, using a lot of power.)
CPU registers are typically made of SRAM (static RAM), see https://en.wikipedia.org/wiki/Static_random-access_memory#Writing. One cell is usually made of 6 transistors, for example, like a flip-flop but fancier and with no current flowing except when a new value is set. This stores 1 bit, and can be written with a new value any number of times, by applying a write-enable signal to update the SRAM cell to the value in its input line.
Actual main-memory is typically made of DRAM, where bits are stored as charge on a capacitor. Every time you read it, you have to refresh this charge, but it's still the same concept of a fixed location that can be written with new values.
I'm reading the book "Understanding the linux kernel", and this is what it says about the __count field of the page descriptor (struct page) :
_count:
A usage reference counter for the page. If it is set to - 1, the corresponding page
frame is free and can be assigned to any process or to the kernel itself. If it is set
to a value greater than or equal to 0, the page frame is assigned to one or more
processes or is used to store some kernel data structures. The page_count() func-
tion returns the value of the _count field increased by one, that is, the number of
users of the page.
My question is, if the same page is assigned to two processes, can't one process access memory assigned to the other by just decrementing/incrementing the linear address by a value smaller than PAGE_SIZE?
How can we determine the base address of the L2 page table? (Using ARM Cortex-A9)
For example, if I have a programme which requires 7KB of data space and starts at the address 0x0, I need two pages of 4KB.
To do that, I add an entry in the L1 page table which points to the L2 page table base address.
Then I add two entries in the L2 page table like that (with addr = 0x0 for the first page and 0x1000 for the second one)
u32 *ptr;
u32 small_page;
small_page = addr / 0x1000;
ptr = small_page + L2_table_base_addr;
*ptr = (addr & 0xFFFFF) | attributes;
Now there is one thing that I still do not understand.
How can I determine the L2 page table base address? Should I put the table right after the L1 page table?
Where can I store the address? I know that the base address of the L1 page table is stored in a coprocessor register but I did not find any register to store the L2 base address.
Another question to be sure, both coprocessor register TTBR0 and TTBR1 holds the base address of a L1 page. Each to its own. It is not TTBR0 for L1 and TTBR1 for L2, does it ?
I would recommend to read Chapter 9 Memory Management Unit of the Cortex-A Series Programmers Guide. There you will find clear explanation about base address storage. The base address of Level 1 TTB is stored in one of the two base registers (TTRB 0/1 depending upon whether table locates OS code or user process code). These two base registers are helpful while context switching.
The address of the L2 translation table entry that required is calculated by taking the (1KB aligned) base address of the level 2 translation table (given by the level 1 translation table entry) and using 8 bits of the virtual address (bits [19:12]) to index within the 256 entries in the L2 translation table (256 because its 4 byte per index so total bytes are 256*4bytes=1KB).
Since 1 week, I have found one interrested topic called :
Adaptive Radix Tree,
I found it is very useful techniques used to index memory specially in modern hardware architectures .
Actually I could not understand one point in page 4 , called Node48.
I have attached a picture of what I mean.
http://s30.postimg.org/nff1am2r5/xadaptive_radix.png
also this is the main page of the article : http://www-db.in.tum.de/~leis/papers/ART.pdf
So could anybody who is more smart than me to explain that for me, I would be very happy.
Thanks.
I believe that you understand how NODE_4 and NODE_16 works.
In NODE_4 and NODE_16, they put 4 to 16 8-bit keys in the first part of a node. The cost of searching a key are 32 bits and 128 bits that can fit into a regular register and a SIMD register.
However, if we use same way in NODE_48, the cost of searching is read 384 bits that cannot even fit into 256-bit SIMD register. So, Viktor Leis et al. use a child index instead of keys in the first part of NODE_48. The child index contains 256 8-bit offsets that represent the position of a pointer. Eg. If you want to search 103 (it could be 0 to 255) in a NODE_48, the program would:
jump to the 103rd slot in the child index (start from 0th)
read the value from 103rd slot and assume it is 5
jump to the 5th slot in the child pointer
read the pointer value from 5th slot and go to the next node
It does 2 offset calculations instead of 48 (SIMD) selections.
Addition:
For Accessing the 103th element in NODE_4 (or NODE_16):
read the "key" part of the NODE in which there are 4 keys (or 16 in NODE_16) which present the key of the child pointers.
execute a SIMD instruction to compare 103 with all 4 keys.
if one of the keys (let say 3rd key) is 103, follow the 3rd child pointer
if none of the keys is 103, return not found.