Subject: uaccess ramblings

From: Philip Blundell <[email-masked]>
Date: Wed, 29 Apr 1998 11:18:39 +0100

Hi,

I was thinking about the code we use for user accesses on ARM2/3 machines just 
now (can you tell I'm not having a particularly busy day?)

At the moment all the get_user calls translate into a function call to one of 
two addresses depending on whether we are in `kernel' or `user' mode 
(indirected through current->tss).  I was wondering whether we could actually 
press the MEMC hardware into service to avoid the need for this.

If we always use LDRT/STRT instructions for get_user() and put_user() then the 
ARM will ask for translation every time.  If I remember right, though I don't 
have a MEMC datasheet here to check, you can set the privilege level that will 
be used for translated accesses by writing to a MEMC register.  All we need to 
do is arrange for set_fs(KERNEL_DS) to set the privilege level to 1, and 
set_fs(USER_DS) to set it to 0, and arrange the page tables such that level 1 
allows access to anything.  This is closer to the ARM6 implementation, and I 
suspect it should be faster.

Incidentally, I think the `wp_works_ok' macros in processor.h are probably 
completely redundant and can be removed -- the armv one is also set to the 
wrong value. :-)

p.

unsubscribe: body of `unsubscribe linux-arm' to [email-masked]

---

From: Russell King - ARM Linux Admin <[email-masked]>
Date: Wed, 29 Apr 1998 23:52:14 +0100 (BST)

> now (can you tell I'm not having a particularly busy day?)

Hmm, how did I tell?

> press the MEMC hardware into service to avoid the need for this.

Unfortunately, the MEMC hardware is very restrictive in this respect.

> be used for translated accesses by writing to a MEMC register.

This will not work.  LDRT does not enable logical translation - it just turns
on the user protection (by asserting the TRAN output).  The control register
does not allow the checks to be turned off.  I quote:

  Supervisor Mode - ... is selected while the SPMD input is held high.

(and SPMD is generally connected to -TRAN).

  Operating System Mode (OS) - OS mode is selected by setting a control bit
  in the MEMC Control Register (which may only be done from SVC mode).  OS
  mode is more privileged than User mode <<<when accessing logically mapped
  RAM, but acts as User mode in all other cases.>>>

Since the kernel accesses physical RAM from time to time using the get_user and
put_user macros, replacing them with a LDRT/STRT instruction will cause a fault.

However, one way to improve things would be for the compiler to allow you to
control what registers were used to pass data into the inline assembly fragment.
Without this, it produces around 3 redundant mov instructions per get_user/put_user
macro.

> completely redundant and can be removed -- the armv one is also set to the 

They are redundant and have now been removed.
   _____
  |_____| ------------------------------------------------- ---+---+-
  |   |        Russell King       [email-masked]      --- ---
  | | | |  http://www.arm.uk.linux.org/~rmk/armlinux.html    /  /  |
  | +-+-+                                                     --- -+-
  /   |               THE developer of ARM Linux              |+| /|\
 /  | | |                                                     ---  |
    +-+-+ -------------------------------------------------  /\\\  |

---

From: Philip Blundell <[email-masked]>
Date: Thu, 30 Apr 1998 08:53:18 +0100

Russell King wrote:

>Since the kernel accesses physical RAM from time to time using the get_user
>and put_user macros, replacing them with a LDRT/STRT instruction will cause
>a fault.

That's a shame.  In fact I think I have a plan that will still allow quite an 
improvement.  I'll try to implement it today and make a patch.  Access to 
physical RAM is never allowed in USER_DS (I assume) and the access_ok() check 
will catch that.  So in put_user() we can check whether the address being 
accessed is above 0x02000000 - if so it must be a kernel access to physical 
RAM and can never fault so we can just do a plain STR (don't even have to 
stack the link register in fact).  If it's below 0x02000000 it's an access to 
logical RAM; we can use STRT and let MEMC signal an exception if it's a bad 
access.  This check will cost us a TST/BNE but that's still less than the 
current scheme by quite a way since it avoids all this fiddling with registers 
and getting values out of current->tss.uaccess->* (which requires two pointer 
dereferences).

Does that sound reasonable or am I still overlooking something?  I suppose 
there's a slight danger of taking an address exception in the "physical RAM" 
case I described but I imagine we can allow that to go untrapped and cause an 
Oops to be honest since only a kernel bug could cause it.

Out of interest, where does the kernel access physical RAM with get_user()?

>They are redundant and have now been removed.

Thanks.

p.