Re: Kernel mappings

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

 



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Sat, May 12, 2007 at 10:46:21AM -0400, Michael Cashwell wrote:
> 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);

That sounds like a broken driver to me. ARM CPU endianess is a compile
time decision, not a run time one. Trying to detect it at runtime is
broken: if the module is compiled LE, testing for that will always tell
you the system runs LE because a LE module will not even run on a BE
system. Just remove the test.

Oh, btw the use of volatile is considered harmful. See
http://lkml.org/lkml/2007/5/11/193 (this patch or an improved version
will likely be merged in the future).

> 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.

There is no 1:1 mapping in kernel and there was also never a 1:1
mapping in 2.4 kernels. There were some changes in the ARM kernel
mapping during 2.5 development, it could be that your CPU registers were
1:1 mapped in 2.4 and are no longer right now. Most ARM platforms have
special macro's to access CPU registers that deal with the mapping.

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

Supervisor mode only means you have access to priviledged instructions,
it doesn't mean you don't have to deal with the MMU.

> 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.

The mmap() file method is for mapping memory into userspace, not for
mapping random physical addresses into the kernel.

> 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!)

It maps anonymous memory, i.e.: just memory. Libc uses this for its
memory allocator (malloc() etc).

> 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.

That is indeed a kludge and unnecessary.

> 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.

That assumption is flawed. There is and never has been a 1:1 VA:PA
mapping in 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.

I think it worked in 2.4.20 by sheer luck.


Erik

- -- 
They're all fools. Don't worry. Darwin may be slow, but he'll
eventually get them. -- Matthew Lammers in alt.sysadmin.recovery
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFGSFyA/PlVHJtIto0RAvsBAJ9KP5L4F0ix8lge/RqeRAZVc9VxDgCfd/ss
5Roh9imfjoZZczjKHvvqdEo=
=Wxc6
-----END PGP SIGNATURE-----

--
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