Kernel requests via page faults

Discussions on more advanced topics such as monolithic vs micro-kernels, transactional memory models, and paging vs segmentation should go here. Use this forum to expand and improve the wiki!
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Kernel requests via page faults

Post by NickJohnson »

I just got this interesting idea, and wondered how practical it would be. What if, instead of using direct software interrupts, system calls were made by causing page faults at certain addresses? It would almost be like memory mapped I/O to the kernel: instead of calling a function, data could be read and written from the kernel just like addressing an array. For simple system calls which access indexed information, such as calls for memory management, or process metadata access, this would be a very nice interface. If the type of system call were encoded in the frame address bits, and these pseudo-frames were themselves subject to memory management, it would even be possible to pass them around like capabilities, granting other processes the ability to make system calls as if they were the granting process. Even further, the kernel could offer routing of page faults from shared pseudo-frames back to the original process, allowing any process to provide a memory mapped interface to itself. I'm sure there are quite a few interesting things that could be derived from this mechanism.

Anyway, the major hurdle would obviously be deciding to/from which register or memory location the result/argument for the "system call" should be stored/loaded. The pseudo-memory-access has to be transparent, so it could be done from ordinary code. Unless I'm mistaken, the faulting instruction would have to be decoded to figure this information out. How many different instructions does the x86 have to read/write memory?

Are there any other issues with this (other than the fact that it would be easy to accidentally make a series of a hundred system calls)?
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Kernel requests via page faults

Post by NickJohnson »

Well, I can't imagine it would be much slower than a normal system call, since it's basically the same mechanism (excluding the decoding of the faulting instruction). It would only be useful if you only had to send or receive one register of data at a time, which would still be fine for most system calls about memory and process management; anything more complex would warrant a normal software interrupt.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Kernel requests via page faults

Post by Brendan »

Hi,
NickJohnson wrote:Unless I'm mistaken, the faulting instruction would have to be decoded to figure this information out. How many different instructions does the x86 have to read/write memory?
Surely you'd use CR2 to determine which address was used to cause the fault?
NickJohnson wrote:Well, I can't imagine it would be much slower than a normal system call, since it's basically the same mechanism (excluding the decoding of the faulting instruction).
Compared to SYSCALL and SYSENTER, a software interrupt is slow. An exception would be slower than software interrupts, because you need to figure out whether the cause of the exception was a programming error or was deliberate (e.g. several potential branch mispredictions before you can know it was a kernel API call) and you have to assume it was caused by a programming error until you know it wasn't (e.g. use an interrupt gate rather than a trap gate, store CR2 somewhere in case a second page fault occurs and trashes CR2, etc).

You forgot to say what you thought the advantage might be. Are there any?
NickJohnson wrote:It would only be useful if you only had to send or receive one register of data at a time, which would still be fine for most system calls about memory and process management; anything more complex would warrant a normal software interrupt.
Why? You'd be able to use all registers to pass data to the "syscall" and use all registers to return data from the "syscall".


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Kernel requests via page faults

Post by NickJohnson »

What I meant was not to have a fault at a specific address simply be a way of numbering system calls (just one software interrupt is enough), but instead to be a way of transparently giving and taking data from the program, just like memory mapped I/O. For example, if you tried to load from one of these special addresses into register ECX, the kernel would not only realize that an fault at that address meant a system call, but also would store the result of that system call in ECX without modifying the other registers. That way you could write C code that seems to be simply dereferencing pointers but is actually performing system calls behind the scenes.

I suppose it really doesn't do much other than allow "renumbering" of system calls by moving around pages. However, I still don't think it would be significantly slower than software interrupts (SYSENTER/SYSRET obviously beat it, though), because decisions about which sort of fault it is could be made with a single branch on the page fault error code. I guess it's not so great either way.

(Edit: typo in last sentence)
Last edited by NickJohnson on Wed Sep 15, 2010 4:05 am, edited 1 time in total.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re: Kernel requests via page faults

Post by Candy »

That allows you to hide syscalls behind memcpy, memset... For non-assembly programmers though, how do you pass arguments to a "syscall" ?
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: Kernel requests via page faults

Post by qw »

Interesting idea. I figure it would be something like this:

Code: Select all

#include <special_memory_locations>

int open(const char *name, int flags, ...)
{
    va_list ap;
    mode_t mode;
    int fd;

    va_start(ap, flags);
    mode = va_arg(ap, mode_t);
    va_end(ap);

//  Special memory locations serve as arguments for system "call"

    *ARG1 = name;
    *ARG2 = flags;
    *ARG3 = mode;

//  Extra special memory location causes fault. Handler makes sure that a new file descriptor is returned

    fd = *CALL_OPEN;

//  In case of error, handler sets another special memory location

    if (fd < 0)
        errno = *ERRNO;

    return fd;
}
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Kernel requests via page faults

Post by NickJohnson »

@Hobbes: Yeah, that is the gist of it, but I originally envisioned it for something that needs no arguments/return values other than that single register (so, not as much for fopen(), but your implementation still makes sense).

I was thinking something more like this: you reserve a 4MB area of user memory that pretends to be all of the current process' page table contents laid out sequentially. If the process tries to write to it, the kernel catches it and performs a safe write to the real page tables (a special value could be used to request a frame to be allocated), and if the process tries to read it, only the non-sensitive information would be read unless the process has permissions for the physical address, etc. This would be the whole interface to the memory manager. A similar thing could work for things like process structures or thread structures, allowing the process to think they are modifying them directly, but still keeping things secure.

It could also be used to turn the x86 I/O space into what would appear to be memory mapped ports, although that may be too slow: every port access would cause an interrupt.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Kernel requests via page faults

Post by Solar »

Possible, yes.

Desirable?

You'd be leaving any abstraction of memory access, thread handling etc. to the application / user space.

Unless you're considering something along an exokernel, that is usually not what you want. But that's just me.
Every good solution is obvious once you've found it.
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: Kernel requests via page faults

Post by qw »

I agree with Solar. Though I applaud you for thinking outside of the box so thoroughly, you'll loose all abstraction. What if you want to change the mentioned structures in later versions?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Kernel requests via page faults

Post by Combuster »

And besides, its generally faster to use a syscall than to handle an exception. (you can also concatenate many changes in one privilege change instead of having a privilege change for each change a series of consecutive accesses...)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: Kernel requests via page faults

Post by qw »

Nevertheless, you could implement it as a "proof of concept" and see how it works out in practice. My admiration guaranteed.

Roel
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Kernel requests via page faults

Post by Owen »

NickJohnson wrote:I suppose it really doesn't do much other than allow "renumbering" of system calls by moving around pages. However, I still don't think it would be significantly slower than software interrupts (SYSENTER/SYSRET obviously beat it, though), because decisions about which sort of fault it is could be made with a single branch on the page fault error code. I guess it's not so great either way.
The processor detects exceptions much later in instruction processing than it does in the processing of software interrupts, SYSCALL and SYSENTER. Call gates are probably slightly slower these days (because they're somewhat less predictable).
rdos
Member
Member
Posts: 3286
Joined: Wed Oct 01, 2008 1:55 pm

Re: Kernel requests via page faults

Post by rdos »

I think the fastest way to do syscalls on x86 is to allocate a callgate with every entrypoint. This will leave all CPU-registers available (no need to use & copy the stack in most (all) cases). It doesn't need to setup function numbers on entry, and it doesn't need decoding functions in the kernel, and eventually to do a call / jmp to the real entrypoint. The only drawback is that GDT selectors are a limited resource.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Kernel requests via page faults

Post by Owen »

rdos wrote:I think the fastest way to do syscalls on x86 is to allocate a callgate with every entrypoint. This will leave all CPU-registers available (no need to use & copy the stack in most (all) cases). It doesn't need to setup function numbers on entry, and it doesn't need decoding functions in the kernel, and eventually to do a call / jmp to the real entrypoint. The only drawback is that GDT selectors are a limited resource.
By the time you have even passed through a call gate on a modern processor, you could pretty much have been through syscall/sysret twice.
User avatar
lemonyii
Member
Member
Posts: 153
Joined: Thu Mar 25, 2010 11:28 pm
Location: China

Re: Kernel requests via page faults

Post by lemonyii »

however, nice idea.
its good for non-assembly programming, and easy to implement. but i didnt consider the speed.
any way, it's just an entrance , it varies from different platforms.
my opinion is, keep the central part of code unchanged, and choose the most practical (fastest, easiest decoding, least exceptions......) entrance on the platform.
and of course, we may have many entrance, but we dont need it i think.
Enjoy my life!------A fish with a tattooed retina
Post Reply