rdos wrote:
Many modern hardware devices are built on setting up physical memory schedules, like network cards, AHCI, and USB controllers. There is no direct way of accessing physical memory when using paging with a non-unity mapping. Many of these drivers tend to need extra entries in the schedules for virtual addresses, and when having a physical address it's hard to translate it to a virtual without maping it with paging, something that is slow and inefficient.
You know, in 64-bit mode, you could just map all physical memory into kernel space, thereby giving you a linear mapping for all physical memory, making translation between physical and virtual memory entirely trivial. But I suppose you'd just be lazy if you did that.
rdos wrote:
Another problem with using physical memory is that simple mistakes can lead to devices corrupting kernel or application memory. It's easy enough to do this with malicious code in a PCI device, but even well-behaved PCI devices can corrupt things in kernel by handing them corrupt schedules.
There is a solution to that as well, and it is called IOMMU. It allows you to intercept transactions from external devices before they reach the memory, and determine if something went wrong. And halt the system as needed.
rdos wrote:
For a segmented OS (like mine), it would be a good idea to allocate a selector with the linear base and a 2M limit. This way kernel software cannot exceed the limits of the 2M area and thus cannot access linear or physical memory that doesn't belong to the object. The translation between physical address and offset would then just subtract the physical base. If the offset is above 2M, a protection fault will result rather than accessing invalid memory.
How does that address either of the problems you mentioned? When a PCI device corrupts your kernel, the OS is not performing a mistaken memory access, the device is (being made to by the OS). The PCI devices still write into your kernel, and you haven't solved the translation issue unless you are also mapping that segment linearly, in which case congratulations, you have invented linear memory mappings.
rdos wrote:
There are a few challenges though. One is that it must be possible to allocate both 2M and 4M physical pages from both below 4G and anywhere in memory.
It's called zoning and it isn't hard. Fundamentally, you run independent memory allocators on each zone you wish to differentiate (I have a 1MB zone, a 4GB zone, and a zone beyond). They don't even need to all be the same allocator. And the overarching allocator just calls each of these in turn (first allocating from the zone beyond, then the 4GB zone, then the 1MB zone, as they get progressively more valuable). Then a restriction to a given maximum address is achieved by just allocating from one zone.
Or, like Linux, you maintain a list of physical memory blocks, and when a request for memory comes in, you iterate over the holes between the allocated chunks to see if you can find a hole that fits whatever criteria you need (size, alignment, maximum address, maybe even "does not cross 64kB line" if you are doing ISA DMA).
I admit that I fail to see a question in your post. Did you want to ask something or are you just bouncing ideas off a wall?