ARMv7M y privileged/unprivileged

75 views
Skip to first unread message

martin ribelotta

unread,
Dec 21, 2017, 3:05:30 PM12/21/17
to embebidos32@
Buenas gente, alguno conoce alguna forma de separar elegantemente codigo privilegiado de no privilegiado en los cortex-m? (armv7m)
Estoy estudiando la posiblidad de hacer un system monitor residente que provea separacion de usuario supervisor independientemente de si hay tareas involucradas o no.

No me gusta el metodo de FreeRTOS:
Porque basicamente deja ligado al usuario entrar y salir del modo privilegiado.
Preferiria algo como
  • UNPRIV/Thread/(User SP): llama a SVC con "svc #n"
  • PRIV/Handler(Sys SP): SVC se ejecuta
  • PRIV/Handler(Sys SP): SVC cambia a modo PRIV/Thread
  • PRIV/Thread(Sys SP): SVC, ya en modo thread ejecuta el syscall especificado
  • PRIV/Thread(Sys SP): El syscall retorna al modo handler???? y retorna al llamante
  • UNPRIV/Thread(User SP): Se continua con la ejecucion del codigo de usuario
El tema es que no se como hacer el cambio a PRIV/Thread. Se me ocurre hacer un interrupt context fake pero se me ocurre que se romperian muchas cosas si lo hago mal y seguramente hay algo hecho.

PD: Ya mire uVisor de ARM pero me parecio excesivamente complejo.
PD2: Nada propietario pls

martin ribelotta

unread,
Dec 21, 2017, 3:09:17 PM12/21/17
to embebidos32@
Otro punto de hacerlo asi es separar completamente user de system ya que user podria tener codigo potencialmente malicioso y quiero frenar cualquier acceso indevido fuera del API usando como entry point el SVC Handler en modo interrupcion.
Tampoco creo que sea buena idea ejecutar SVC en modo handler con la minima prioridad (o una menos que pendsv si uso un context switcher). Realmente creo que switchear a task en la interrupción y luego retornar a unprivileged desde privileged/thread es la mejor opcion, pero no doy con la tecla de como hacerlo

Christian N

unread,
Dec 27, 2017, 12:36:55 PM12/27/17
to Embebidos32
Hola

Para entender el contexto
Estas tratando de
¿implementar una syscall?
¿Operar en los dos niveles desde el user space?
¿Estas haciendo algo Bare metal o basado en algun OS?

martin ribelotta

unread,
Dec 27, 2017, 1:03:46 PM12/27/17
to embebidos32@
El 27 de diciembre de 2017, 14:36, Christian N <cneg...@gmail.com> escribió:
Hola

Para entender el contexto
Estas tratando de
¿implementar una syscall?
Correcto, esa es la idea. Ocurre que las syscall en ARMv7M se ejecutan (por diseño) en modo handler. El cual solo admite interrupciones de mayor prioridad a la actual. Ademas, hay otras limitaciones menores en cuanto a manejo de interrupciones lo cual no es ideal si hablamos de un modo user/supervisor puro.
La idea es emular las trap gates de ia32/amd64. Es decir, entrar en modo supervisor pero mantener el modo thread (o entrar al modo supervisor como handler, pasar a modo thread y luego volver a modo handler para retornar normalmente de la interrupción hacia modo thread/unprivileged)

Por ejemplo, FreeRTOS toma el mecanismo de tener una syscall para cambiar voluntariamente a modo supervisor. Eso es factible en contextos donde el codigo de usuario sea thrusted y uno este seguro de que no va a ejecutar nada malicioso. Pero en este contexto la idea es "no se que va a ejecutar userland, asi que le restrinjo todo a las trap call para poder tener control de lo que se hace"

Quien implemente las trap calls seria un monitor, un RTOS o una libreria, es irrelevante al contexto.

¿Operar en los dos niveles desde el user space?
No, el userspace debe estar totalmente abstraido de esto. La aplicacion de usuario es no-confiable en mi contexto por lo que debo restringir totalmente el acceso a los recursos del procesador (via MPU para la memoria, via user/system para las instrucciones)
 
¿Estas haciendo algo Bare metal o basado en algun OS?

Bare metal en principio... pero deberia ser portable a la mayoria de los RTOS existentes porque la gran mayoria, o usan SVC como entry point de peticiones al usuario (multiplexable con mi syscall) o directamente no la usan.
 

--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32+unsubscribe@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es
---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32+unsubscribe@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

Christian N

unread,
Jan 3, 2018, 6:45:18 PM1/3/18
to Embebidos32
Hola

Le hechaste una mirada a
https://github.com/fuchsia-mirror/zircon/tree/master/kernel/syscalls

Independientemente de esto, entiendo que si lo implementas de la forma que planteas vas a consumir mas tiempo,,,

--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32...@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es

---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32...@googlegroups.com.

martin ribelotta

unread,
Jan 3, 2018, 7:16:34 PM1/3/18
to embebidos32@
El 3 de enero de 2018, 20:45, Christian N <cneg...@gmail.com> escribió:
Hola

Hola si, sigo el proyecto Fuxia y Magenta (ahora enterandome que lo renombraron a Zircon) desde hace rato, pero esto es para ARMv7A o AARCH32/AARCH64 que es radicalmente distinto en el manejo de excepciones/interrupciones que los cortex-m. Basicamente son ARM classic con IRQ/FIQ y otros vectores de interrupcion de sistemas (entre ellos contexto y stack separado para SWI -systemcall- lo que simplifica muchisimo el proceso)
 
Independientemente de esto, entiendo que si lo implementas de la forma que planteas vas a consumir mas tiempo,,,

Toda llamada al sistema es un overhead...  pero comparado conque?
  • Con una llamada clasica es oviamente un overhead (blx r<n> o bl <#offset>) pero no hay cambio de contexto en este caso... no es aplicable la separación
  • Contra un SWI clasico de ARM es relativo, el save/restore context al entrar/salir de userspace/kernelspace existe y es mayor haciendolo por software (basicamente hay que ejecutar un LDM {r0-r9}/STM {r0-r9} lo cual es mas lento que el clasico nvic)
  • Con respecto a ejecutar en modo handler la rutina, si obviamente es levemente mas lento, pero cuanto?
Si nos fijamos en el mecanismo mas optimo que seria:
  1. Preparar los registros (1-4 cycles) (r4 funcion a llamar, r0....r3 parametros)
  2. ejecutar SWD #n (3 cycles ya que vacia el pipe)
  3. Entrar a modo handler a traves del trabajo del nvic (12 clk)
    -------------- Hasta aqui es independiente del metodo ---------
  4. Tomar el stack pointer de los registros pusheados y ponerlo en un registro no restaurado por el nvic (r5) (3 clk acceso a RAM, posiblemente sin retardos en el bus)
  5. Reemplazar el stack pointer pusheado con mi fake call (3 clk)
  6. Hacer un fake de LR para retornar a thread+supervisor (1 clk)
    -------------- Lo siguiente es independiente del metodo --------
  7. Ejecutar el retorno (12 clk)
    -------------- Ahora continuamos con la cuenta del overhead ------
    El retorno en realidad llamo a un stub que sabe:
    1. r0...r3 AAPCS convention call parameters
    2. r4 puntero a la funcion a llamar
    3. r5 real return stack pointer
  8. El stub mueve r5 a lr para simular una llamada normal a funcion (1clk)
  9. llama a la funcion con bx (en vez de un blx para preservar el lr ya restaurado) (4 clk)
  10. Retorno normalmente con mov pc, lr ya que es una (esto ya no pertenece al overhead)
En total a mi me da un overhead de 8 clk mas sobre los 27 de ejecutar esto en modo handler. Esto es un 30% mas aprox. Creo que es aceptable para lo que se gana, siempre teniendo en cuenta que separar user/system es un overhead en si mismo.
 

--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32+unsubscribe@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es

---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32+unsubscribe@googlegroups.com.

martin ribelotta

unread,
Jan 3, 2018, 7:17:49 PM1/3/18
to embebidos32@
Como veras, en SVC rompo el AAPCS convention call de ARM, y hay que escribirla enteramente en ensamblador (posiblemente anteponiendola a la del sisema operativo y multiplexando de ser necesario y usarse uno)
Reply all
Reply to author
Forward
0 new messages