Re: Kernel mappings

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On May 12, 2007, at 4:49 AM, Erik Mouw wrote:

On Fri, May 11, 2007 at 03:39:08PM -0400, Michael Cashwell wrote:

In a nutshell, I have the module building and loading for 2.6 but when a user land app attempts to use the driver it fails (unable to handle kernel paging request).

The address in question is of the CPU's internal peripheral registers. The key issue is that I can access that address from kernel mode just fine. But the failure happens when the user land app down-calls via an ioctl into the driver module. The oops message says it was "Mode SVC_32 Segment user".

I thought I'd read that once the syscall happens and the driver is called by do_ioctl (which is happening) that it should be in kernel mode. I don't understand what else I need to do to allow me to access kernel mappings that I know exist.

It *is* running in kernel mode, and that's also what the Oops says: SVC_32 is ARM supervisor mode (aka kernel mode). It also says that the problem is accessing user mode memory. Without having seen the source, I guess you're probably directly dereferencing a userland address without using copy_from_user().

Interesting. The faulting instruction is the driver attempting to read the endianess mode from a CPU peripheral register. The address is 0xfffeec34 and the code (after preprocessing; and from memory) is essentially: unsigned int emode = *((volatile unsigned int *) 0xfffeec34);

So the address in question is really a physical address that the kernel (as part of the ARM init code) has mapped into kernel virtual space at the same addresses.

...

Have a look at the mmap() details in LDD3 (google for ldd3 and it will take you to the right
place).

I've looked there and will pursue it but my problem is that the driver code is written with the expectation that these addresses (constants) can be accessed as virtual addresses. The 1:1 mapping with the physical addresses (and the no-cache attribute) exist and work and seem to agree with how the rest of the mach-omap & ARM code works in the kernel. Indeed, this driver can rely on these mappings but only when running a kernel thread.

I'm still confused by being in module (kernel) code and in supervisor mode but not having access to the kernel's VM mappings.

My trouble with mmap is that it seems to want a file descriptor (which one would get from opening "/dev/mem" in a user app) which I don't have in my module. On other Unix-like systems, "files" are a user land concept and I'm hardwired to view calls that use them as off-limits in the kernel. That bias may be part of my problem. If I can just do_open() and do_mmap() during an earlier initialization ioctl call into my module then that would be a solution to my problem. Comments on this are most welcome.

I've considered using MAP_ANONYMOUS which is documented to eliminate needing the file descriptor but it also then ignores the offset argument. When I've mmaped /dev/mem in userland to get VA == PA I've found that I needed to pass the same value to both start and offset. I don't see how I specify the PA if offset is ignore. (I also don't understand what I'm mapping if there's no fd!)

As a work-around, I'm planning to try on Monday creating such a mmap in my user app before calling into the driver. But that seems like a real kludge. We have the concept of having drivers abstract the details of the hardware so user apps don't need to know them, but because that driver code doesn't seem to have access to kernel VM mappings it can't really touch the hardware on a down-call from user land. It can only do that on its own (kernel) threads.

So I must completely break the hardware abstraction and mmap in my user app? I just can't believe that's the case.

If I were controlling private hardware then a mapping where VA != PA would be OK. But as noted the driver code was written expecting to have access to the CPU-peripherals at their native addresses and this assumption is totally in keeping with the other CPU-specific parts of the kernel.

Wrapping all of those accesses such that they use a computed base VA instead would be a substantial rewrite. I'd be willing to do that, but all of this worked under 2.4.20 so I really just keep coming back to the conclusion that I'm missing something fundamental.

Thanks for reading and for any ideas.

-Mike


--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux