Who divides the main memory into page frames? From my current understanding it's OS that maintains the frame table, so it's not MMU for this job?
The MMU is just a hardware thing. Today, it is a part of the CPU chip. Details about the MMU are instruction set architecture specific (so different on x86 and on PowerPc or ARM or RISC-V).
The MMU needs to be configured, to implement suitable virtual address to physical address translation.
That MMU configuration (a privileged operation) is done by the operating system kernel which manages the page table. From the user-space point of view, the OS would provide system calls (such as mmap(2) on Linux) to change the virtual address space of the process.
Read Operating Systems: Three Easy Pieces for more (freely downloadable). There are several chapters (12 to 24) explaining all this.
PS. If you have a Linux system, try the cat /proc/$$/maps command (it "shows" the virtual address space of your shell process, since your shell would expand $$ to its pid), and read more about proc(5).
Who divides the main memory into page frames?
The system hardware divides the main memory into physical page frames.
From my current understanding it's OS that maintains the frame table, so it's not MMU for this job?
No. The operating system maps a process's logical pages to the physical page frames. The underlying hardware divides the memory into page frames. This may or may not be done by the MMU. It would all depend upon how the chipset is designed.
Related
I was reading the textbook:Computer Systems A Programmer’s Perspective, in chapter 9.7.2:Linux Virtual Memory System (third edition) that talks about virtual memory.
I was a bit confused by the structure of virtual memory for linux process as shown below:
My question is: does kernel virtual memory preserve for kernel to run
and rest of the virtual memory preserve for user process? What does kernel code and data do? And what does the physical memory in kernel virtual memory?
does kernel virtual memory preserve for kernel to run and rest of the virtual memory preserve for user process?
Yes, there is a part of virtual memory that is always reserved for the kernel and another part that is left available to userspace processes. Every single process has its own virtual memory, but the kernel is always mapped in the higher part (higher addresses) of virtual memory. Whether or not this mapping is visible to the process depends on Kernel Page Table Isolation.
See also: Do the virtual address spaces of all the processes have the same content in their “Kernel” parts?
What does kernel code and data do?
Part of the high virtual memory is a direct mapping of the actual kernel image. That is, the kernel executable and all its data. You can see it in more detail here in this page of the kernel documentation, marked as "kernel text mapping, mapped to physical address 0".
See also: What's the use of having a kernel part in the virtual memory space of Linux processes?
And what does the physical memory in kernel virtual memory?
That part of the image is totally misleading. I don't know precisely what information the authors of the book were trying to convey, but physical memory is definitely not a part of kernel virtual memory. They were probably trying to address the fact that there is a direct mapping of all physical memory in the kernel virtual memory, which can be seen again on the same page of the kernel documentation, marked as "direct mapping of all physical memory".
Physical memory refers to the real memory of the system (i.e. the RAM). Each region of virtual memory is mapped to some region of physical memory. This virtual-to-physical mapping is totally transparent to processes and is managed by the kernel. For example, two executables that have the same file open in read-only mode are usually sharing the same physical memory region, while seeing two different virtual address.
This is a more accurate depiction of the relationship between virtual and physical memory:
Source: https://computationstructures.org/lectures/vm/vm.html
cited from the CSAPP book, 3rd version, section 9.7.2, where the picture is shown.
Interestingly, Linux also maps a set of contiguous virtual pages (equal in size to the total amount of DRAM in the system) to the corresponding set of contiguous physical pages. This provides the kernel with a convenient way to access any specific location in physical memory—for example, when it needs to access page tables or to perform memory-mapped I/O operations on devices that are mapped to particular physical memory locations.
I think the Physical memory in the picture just reflects what's described above: a virtual memory area that maps to the entire physical memory.
An operating system itself has resources it needs to access, like block I/O cache and process control blocks. Does it use virtual memory addresses or physical memory addresses?
I feel like it should be the former since it prevents the need to keep a large area of physical memory for a purpose, even when it is mostly empty. The mechanism of page tables/virtual memory would do a much better job at keeping those resources that the OS really needs.
So which is it?
10 randomly selected operating systems will do virtual memory management in 10 different ways. There's no answer that applies to all operating systems.
Some (e.g. MS-DOS) don't support or use virtual memory management for anything, some (e.g. Linux) just map all of physical memory into kernel space and don't bother using virtual memory management tricks for the kernel itself (it's almost as if the kernel is in physical memory even though it's technically both), and some may do any number of virtual memory tricks in kernel space.
How does an operating system ensure that a process won't access the memory of another process? How is this stuff done?
There are a number of approaches that have been used. The most common is logical memory addressing. The address space is divided into two zones: user and kernel.
Every process has its own user memory zone. All processes share the same kernel memory zone. A process has no means for accessing the user mode address space of another process. All user mode memory references go to the process's own memory space, and cannot reference those of another process.
The kernel address space is restricted so that it can only be accessed in kernel mode. The OS restricts the ways in which a process can enter kernel mode.
Consider the following CPU instruction which takes the memory at address 16777386 (decimal) and stores it in Register 1:
Move &0x010000AA, R1
Traditionally programs are translated to assembly (machine code) at compile time. (Let's ignore more complex modern systems like jitting).
However, if this address allocation is completed statically at compile time, how does the OS ensure that two processes do not use the same memory? (eg if you ran the same compiled program twice concurrently).
Question:
How, and when, does a program get its memory addresses assigned?
Virtual Memory:
I understand most (if not all) modern systems use Memory Management Units in hardware to allow for the use of virtual memory. The first few octets of an address space being used to reference which page. This would allow for memory protection if each process used different pages. However, if this is how memory protection is enforced, the original question still persists, only this time with how page numbers are assigned?
EDIT:
CPU:
One possibility is the CPU can handle memory protection by enforcing that a process id be assigned by the OS before executing memory based instructions. However, this is only speculation, and requires support in hardware by the CPU architecture, something I'm not sure RISC ISAs would be designed to do.
With virtual memory each process has separate address space, so 0x010000AA in one process will refer to different value than in another process.
Address spaces are implemented with kernel-controlled page tables that processor uses to translate virtual page addresses to physical ones. Having two processes using the same address page number is not an issue, since the processes have separate page tables and physical memory mapped can be different.
Usually executable code and global variables will be mapped statically, stack will be mapped at random address (some exploits are more difficult that way) and dynamic allocation routines will use syscalls to map more pages.
(ignoring the Unix fork) The initial state of a processes memory is set up by the executable loader. The linker defines the initial memory state and the loader creates it. That state usually includes memory to static data, executable code, writeable data, and the stack.
In most systems a process can modify the address space by adding pages (possibly removing them as well).
[Ignoring system addresses] In virtual (logical) memory systems each process has an address space starting at zero (usually the first page is not mapped). The address space is divided into pages. The operating system maps (and remaps) logical pages to physical pages.
Address 0x010000AA in one process is then a difference physical memory address in each process.
I've recently started getting into low level stuff and looking into bootloaders and operating systems etc...
As I understand it, for ARM processors at least, peripherals are initialized by the bootloader and then they are mapped into the physical memory space. From here, code can access the peripherals by simply writing values to the memory space mapped to the peripherals registers. Later if the chip has a MMU, it can be used to further remap into virtual memory spaces. Am I right?
What I don't understand are (assuming what I have said above is correct):
How does the bootloader initialize the peripherals if they haven't been mapped to an address space yet?
With virtual memory mapping, there are tables that tell the MMU where to map what. But what determines where peripherals are mapped in physical memory?
When a device boots, the MMU is turned off and you will be typically running in supervisor mode. This means that any addresses provide are physical addresses.
Each ARM SOC (system on Chip) will have a memory map. The correspondece of addresses to devices is determined by which physical data and address line are connect to which parts of the processor. All this information can be found in a Technical reference manual. For OMAP4 chips this can be found here.
There are several ways to connect off-chip device. One is using the GPMC. Here you will need to sepcify the address in the GPMC that you want to use on the chip.
When the MMU is then turned on, these addresses may change depending on how the MMU is programmed. Typically direct access to hardware will also only be available in kernel mode.
Though this is an old question, thought of answering this as it might help some others like me trying to get sufficient answers from stackoverflow.
you explanation is almost correct but want to give little explanation on this one:
peripherals are initialized by the bootloader and then they are mapped into the physical memory space
Onchip peripherals already have a predefined physical address space. For other external IO mapped peripherals (like PCIe), we need to config a physical addr space, but their physical address space range is still predefined. They cannot be configured at random address space.
Now to your questions, here are my answers..
How does the bootloader initialize the peripherals if they haven't been mapped to an address space yet?
As I mentioned above, all (on-chip)peripherals have physical address space predefined (usually will be listed in Memory map chapter of processor RM). So, boot loaders (assuming MMU is off) can directly access them.
With virtual memory mapping, there are tables that tell the MMU where to map what. But what determines where peripherals are mapped in physical memory?
With VMM, there are page tables (created and stored in physical DRAM by kernel) that tells MMU to map virtual addr to physical addr. In linux kernel with 1G kernel virt space (say kernel virtual addrs from 0xc0000000-0xffffffff), on-chip peripherals will need to have a VM space from within the above kernel VM space (so that kernel & only kernel can access it); and page tables will be setup to map that peripheral virt addr to its actual physical addr (the ones defined in RM)
You can't remap peripherals in ARM processor, all peripheral devices correspond to fixed positions in memory map. Even registers are mapped to internal RAM memory that has permanent fixed positions. The only things you can remap are memory devices like SRAM, FLASH, etc. via FSMC or similar core feature. You can however remap a memory mapped add-on custom peripheral that is not part of the core itself, lets say a hard disk controller for instance, but what is inside ARM core its fixed.
A good start is to take a look at processor datasheets at company sites like Philips and ST, or ARM architecture itself at www.arm.com.