antoni wrote:
There are various structures in memory (multiboot info, ACPI, etc.) that I know the physical address of. I could simply map this same physical address to this same virtual address, but if I want a consistent address space without holes then I need to map virtual addresses to different physical addresses. But in such case I need to know their virtual addresses.
(My kernel only has one address space.)
The idea is you have a chain reverse references, rooted in the description of your physical page structure. When you add a virtual mapping to a physical page, a record of that reverse mapping is added to the chain of such references:
Code:
struct rmap {
process_address_space asid;
void * address;
struct rmap * next;
};
struct p_page {
/* Stuff describing this physical page */
/* Mappings of this physical page */
struct rmap * rmaps;
};
void add_reverse_mapping(page_t pagenum, process_address_space asid, void * address)
{
struct p_page * page = getpagestruct(pagenum);
struct rmap * rmap = malloc(sizeof(*rmap));
enter_critical_section(page);
rmap->next = page->rmaps;
rmap->asid = asid;
rmap->address = address;
page->rmaps = next;
leave_critical_section(page);
}
void walk_reverse_mapping(page_t pagenum, void (*callback)(process_address_space asid, void * address))
{
struct p_page * page = getpagestruct(pagenum);
enter_critical_section(page);
struct rmap * rmap = page->rmaps;
while(rmap) {
struct rmap * next = rmap->next;
callback(rmap->asid, rmap->address);
rmap = next;
}
leave_critical_section(page);
}
Then, when you want to do something to each mapping of a physical page, you call walk_reverse_mapping() with your page identifier and a callback, and that callback can do whatever you want, including removing the mapping:
Code:
void unmap_virtual_address(process_address_space asid, void * address);
void unmap_page(page_t pagenum)
{
walk_reverse_mapping(pagenum, unmap_virtual_address);
}
iansjack wrote:
But the physical address won't have a corresponding virtual address until you have created the mapping. And that means you already know the virtual address as you chose it.
Exactly. You don't tend to need reverse mappings until you have to manage multiple mappings to pages. Until that time, if you have a one to one virtual to physical mapping, as you probably will do for structures such as ACPI data, then you just need the virtual address.
In which case you need either:
- A virtual memory address space allocator. This can be a simple bump pointer, dolling out segments of virtual address space on demand, or something more elaborate if you envisage free'ing and reusing regions of virtual address spaces. You allocate some virtual address space for your physical memory, and map it.
- A direct map of virtual->physical memory. This is more practical when the physical address spaces easily fits within the virtual address space (used by early Linux, for example, up until the point that physical memory started to exceed ~896MB.) Given your physical memory address, you just index into your virtual memory mapping of physical memory to access the physical page using the direct virtual address mapping.