aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Documentation/translations/sp_SP/process/adding-syscalls.rst
blob: f21504c612b25d4e6deca869b7932680f32e9949 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
.. include:: ../disclaimer-sp.rst

:Original: :ref:`Documentation/process/adding-syscalls.rst <addsyscalls>`
:Translator: Mauricio Fuentes <mauriciofb@gmail.com>

.. _sp_addsyscalls:

Agregando una Nueva Llamada del Sistema
=======================================

Este documento describe qué involucra agregar una nueva llamada del sistema
al kernel Linux, más allá de la presentación y consejos normales en
:ref:`Documentation/process/submitting-patches.rst <submittingpatches>` que
también puede encontrar traducido a este idioma.

Alternativas a Llamadas del Sistema
-----------------------------------

La primera cosa a considerar cuando se agrega una llamada al sistema es si
alguna alternativa es adecuada en su lugar. Aunque las llamadas al sistema
son los puntos de interacción entre el userspace y el kernel más obvios y
tradicionales, existen otras posibilidades -- elija la que mejor se adecúe
a su interfaz.

 - Si se puede hacer que la operación se parezca a un objeto filesystem,
   podría tener más sentido crear un nuevo sistema de ficheros o
   dispositivo. Esto también hará más fácil encapsular la nueva
   funcionalidad en un módulo del kernel en vez de requerir que sea
   construido junto al kernel principal.

     - Si la nueva funcionalidad involucra operaciones donde el kernel
       notifica al userspace que algo ha pasado, entonces retornar un nuevo
       descriptor de archivo para el objeto relevante permite al userspace
       usar ``poll``/``select``/``epoll`` para recibir esta notificación.

     - Sin embargo, operaciones que no mapean a operaciones similares a
       :manpage:`read(2)`/:manpage:`write(2)` tienen que ser implementadas
       como solicitudes :manpage:`ioctl(2)`, las cuales pueden llevar a un
       API algo opaca.

 - Si sólo está exponiendo información del runtime, un nuevo nodo en sysfs
   (mire ``Documentation/filesystems/sysfs.rst``) o el filesystem ``/proc``
   podría ser más adecuado. Sin embargo, acceder a estos mecanismos
   requiere que el filesystem relevante esté montado, lo que podría no ser
   siempre el caso (e.g. en un ambiente namespaced/sandboxed/chrooted).
   Evite agregar cualquier API a debugfs, ya que no se considera una
   interfaz (interface) de 'producción' para el userspace.

 - Si la operación es específica a un archivo o descriptor de archivo
   específico, entonces la opción de comando adicional :manpage:`fcntl(2)`
   podría ser más apropiada. Sin embargo, :manpage:`fcntl(2)` es una
   llamada al sistema multiplexada que esconde mucha complejidad, así que
   esta opción es mejor cuando la nueva funcion es analogamente cercana a
   la funcionalidad existente :manpage:`fcntl(2)`, o la nueva funcionalidad
   es muy simple (por ejemplo, definir/obtener un flag simple relacionado a
   un descriptor de archivo).

 - Si la operación es específica a un proceso o tarea particular, entonces
   un comando adicional :manpage:`prctl(2)` podría ser más apropiado. Tal
   como con :manpage:`fcntl(2)`, esta llamada al sistema es un multiplexor
   complicado así que está reservado para comandos análogamente cercanos
   del existente ``prctl()`` u obtener/definir un flag simple relacionado a
   un proceso.

Diseñando el API: Planeando para extensiones
--------------------------------------------

Una nueva llamada del sistema forma parte del API del kernel, y tiene que
ser soportada indefinidamente. Como tal, es una muy buena idea discutir
explícitamente el interface en las listas de correo del kernel, y es
importante planear para futuras extensiones del interface.

(La tabla syscall está poblada con ejemplos históricos donde esto no se
hizo, junto con los correspondientes seguimientos de los system calls --
``eventfd``/``eventfd2``, ``dup2``/``dup3``, ``inotify_init``/``inotify_init1``,
``pipe``/``pipe2``, ``renameat``/``renameat2`` -- así que aprenda de la
historia del kernel y planee extensiones desde el inicio.)

Para llamadas al sistema más simples que sólo toman un par de argumentos,
la forma preferida de permitir futuras extensiones es incluir un argumento
flag a la llamada al sistema. Para asegurarse que el userspace pueda usar
de forma segura estos flags entre versiones del kernel, revise si los flags
contienen cualquier flag desconocido, y rechace la llamada al sistema (con
``EINVAL``) si ocurre::

    if (flags & ~(THING_FLAG1 | THINGFLAG2 | THING_FLAG3))
        return -EINVAL;

(Si no hay valores de flags usados aún, revise que los argumentos del flag
sean cero.)

Para llamadas al sistema más sofisticadas que involucran un gran número de
argumentos, es preferible encapsular la mayoría de los argumentos en una
estructura que sea pasada a través de un puntero. Tal estructura puede
hacer frente a futuras extensiones mediante la inclusión de un argumento de
tamaño en la estructura::

    struct xyzzy_params {
        u32 size; /* userspace define p->size = sizeof(struct xyzzy_params) */
        u32 param_1;
        u64 param_2;
        u64 param_3;
    };

Siempre que cualquier campo añadido subsecuente, digamos ``param_4``, sea
diseñado de forma tal que un valor cero, devuelva el comportamiento previo,
entonces permite versiones no coincidentes en ambos sentidos:

 - Para hacer frente a programas del userspace más modernos, haciendo
   llamadas a un kernel más antiguo, el código del kernel debe revisar que
   cualquier memoria más allá del tamaño de la estructura sea cero (revisar
   de manera efectiva que ``param_4 == 0``).
 - Para hacer frente a programas antiguos del userspace haciendo llamadas a
   un kernel más nuevo, el código del kernel puede extender con ceros, una
   instancia más pequeña de la estructura (definiendo efectivamente
   ``param_4 == 0``).

Revise :manpage:`perf_event_open(2)` y la función ``perf_copy_attr()`` (en
``kernel/events/code.c``) para un ejemplo de esta aproximación.


Diseñando el API: Otras consideraciones
---------------------------------------

Si su nueva llamada al sistema permite al userspace hacer referencia a un
objeto del kernel, esta debería usar un descriptor de archivo como el
manipulador de ese objeto -- no invente un nuevo tipo de objeto manipulador
userspace cuando el kernel ya tiene mecanismos y semánticas bien definidas
para usar los descriptores de archivos.

Si su nueva llamada a sistema :manpage:`xyzzy(2)` retorna un nuevo
descriptor de archivo, entonces el argumento flag debe incluir un valor que
sea equivalente a definir ``O_CLOEXEC`` en el nuevo FD. Esto hace posible
al userspace acortar la brecha de tiempo entre ``xyzzy()`` y la llamada a
``fcntl(fd, F_SETFD, FD_CLOEXEC)``, donde un ``fork()`` inesperado y
``execve()`` en otro hilo podrían filtrar un descriptor al programa
ejecutado. (Sin embargo, resista la tentación de reusar el valor actual de
la constante ``O_CLOEXEC``, ya que es específica de la arquitectura y es
parte de un espacio numerado de flags ``O_*`` que está bastante lleno.)

Si su llamada de sistema retorna un nuevo descriptor de archivo, debería
considerar también que significa usar la familia de llamadas de sistema
:manpage:`poll(2)` en ese descriptor de archivo. Hacer un descriptor de
archivo listo para leer o escribir es la forma normal para que el kernel
indique al espacio de usuario que un evento ha ocurrido en el
correspondiente objeto del kernel.

Si su nueva llamada de sistema :manpage:`xyzzy(2)` involucra algún nombre
de archivo como argumento::

    int sys_xyzzy(const char __user *path, ..., unsigned int flags);

debería considerar también si una versión :manpage:`xyzzyat(2)` es mas
apropiada::

    int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags);

Esto permite más flexibilidad en como el userspace especifica el archivo en
cuestión; en particular esto permite al userspace pedir la funcionalidad a
un descriptor de archivo ya abierto usando el flag ``AT_EMPTY_PATH``,
efectivamente dando una operación :manpage:`fxyzzy(3)` gratis::

 - xyzzyat(AT_FDCWD, path, ..., 0) es equivalente a xyzzy(path, ...)
 - xyzzyat(fd, "", ..., AT_EMPTY_PATH) es equivalente a fxyzzy(fd, ...)

(Para más detalles sobre la explicación racional de las llamadas \*at(),
revise el man page :manpage:`openat(2)`; para un ejemplo de AT_EMPTY_PATH,
mire el man page :manpage:`fstatat(2)` manpage.)

Si su nueva llamada de sistema :manpage:`xyzzy(2)` involucra un parámetro
describiendo un describiendo un movimiento dentro de un archivo, ponga de
tipo ``loff_t`` para que movimientos de 64-bit puedan ser soportados
incluso en arquitecturas de 32-bit.

Si su nueva llamada de sistema  :manpage:`xyzzy` involucra una
funcionalidad privilegiada, esta necesita ser gobernada por la capability
bit linux apropiada (revisado con una llamada a ``capable()``), como se
describe en el man page :manpage:`capabilities(7)`. Elija una parte de
capability linux que govierne las funcionalidades relacionadas, pero trate
de evitar combinar muchas funciones sólo relacionadas vagamente bajo la
misma sección, ya que va en contra de los propósitos de las capabilities de
dividir el poder del usuario root. En particular, evite agregar nuevos usos
de la capacidad ya demasiado general de la capabilities ``CAP_SYS_ADMIN``.

Si su nueva llamada de sistema :manpage:`xyzzy(2)` manipula un proceso que
no es el proceso invocado, este debería ser restringido (usando una llamada
a ``ptrace_may_access()``) de forma que el único proceso con los mismos
permisos del proceso objetivo, o con las capacidades (capabilities)
necesarias, pueda manipulador el proceso objetivo.

Finalmente, debe ser conciente de que algunas arquitecturas no-x86 tienen
un manejo más sencillo si los parámetros que son explícitamente 64-bit
caigan en argumentos enumerados impares (i.e. parámetros 1,3,5), para
permitir el uso de pares contiguos de registros 32-bits. (Este cuidado no
aplica si el argumento es parte de una estructura que se pasa a través de
un puntero.)

Proponiendo el API
------------------

Para hacer una nueva llamada al sistema fácil de revisar, es mejor dividir
el patchset (conjunto de parches) en trozos separados. Estos deberían
incluir al menos los siguientes items como commits distintos (cada uno de
los cuales se describirá más abajo):

 - La implementación central de la llamada al sistema, junto con
   prototipos, numeración genérica, cambios Kconfig e implementaciones de
   rutinas de respaldo (fallback stub)
 - Conectar la nueva llamada a sistema a una arquitectura particular,
   usualmente x86 (incluyendo todas las x86_64, x86_32 y x32).
 - Una demostración del use de la nueva llamada a sistema en el userspace
   vía un selftest en ``tools/testing/selftest/``.
 - Un borrador de man-page para la nueva llamada a sistema, ya sea como
   texto plano en la carta de presentación, o como un parche (separado)
   para el repositorio man-pages.

Nuevas propuestas de llamadas de sistema, como cualquier cambio al API del
kernel, debería siempre ser copiado a linux-api@vger.kernel.org.


Implementation de Llamada de Sistema Generica
---------------------------------------------

La entrada principal a su nueva llamada de sistema :manpage:`xyzzy(2)` será
llamada ``sys_xyzzy()``, pero incluya este punto de entrada con la macro
``SYSCALL_DEFINEn()`` apropiada en vez de explicitamente. El 'n' indica el
numero de argumentos de la llamada de sistema, y la macro toma el nombre de
la llamada de sistema seguida por el par (tipo, nombre) para los parámetros
como argumentos. Usar esta macro permite a la metadata de la nueva llamada
de sistema estar disponible para otras herramientas.

El nuevo punto de entrada también necesita un prototipo de función
correspondiente en ``include/linux/syscalls.h``,  marcado como asmlinkage
para calzar en la manera en que las llamadas de sistema son invocadas::

    asmlinkage long sys_xyzzy(...);

Algunas arquitecturas (e.g. x86) tienen sus propias tablas de syscall
específicas para la arquitectura, pero muchas otras arquitecturas comparten
una tabla de syscall genéricas. Agrega su nueva llamada de sistema a la
lista genérica agregando una entrada a la lista en
``include/uapi/asm-generic/unistd.h``::

    #define __NR_xyzzy 292
    __SYSCALL(__NR_xyzzy, sys_xyzzy )

También actualice el conteo de __NR_syscalls para reflejar la llamada de
sistema adicional, y note que si multiples llamadas de sistema nuevas son
añadidas en la misma ventana unida, su nueva llamada de sistema podría
tener que ser ajustada para resolver conflictos.

El archivo ``kernel/sys_ni.c`` provee una implementación fallback stub
(rutina de respaldo) para cada llamada de sistema, retornando ``-ENOSYS``.
Incluya su nueva llamada a sistema aquí también::

    COND_SYSCALL(xyzzy);

Su nueva funcionalidad del kernel, y la llamada de sistema que la controla,
debería normalmente ser opcional, así que incluya una opción ``CONFIG``
(tipicamente en ``init/Kconfig``) para ella. Como es usual para opciones
``CONFIG`` nuevas:

 - Incluya una descripción para la nueva funcionalidad y llamada al sistema
   controlada por la opción.
 - Haga la opción dependiendo de EXPERT si esta debe estar escondida de los
   usuarios normales.
 - Haga que cualquier nuevo archivo fuente que implemente la función
   dependa de la opción CONFIG en el Makefile (e.g.
   ``obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.o``).
 - Revise dos veces que el kernel se siga compilando con la nueva opción
   CONFIG apagada.

Para resumir, necesita un commit que incluya:

 - una opción ``CONFIG`` para la nueva función, normalmente en ``init/Kconfig``
 - ``SYSCALL_DEFINEn(xyzzy, ...)`` para el punto de entrada
 - El correspondiente prototipo en ``include/linux/syscalls.h``
 - Una entrada genérica en ``include/uapi/asm-generic/unistd.h``
 - fallback stub en ``kernel/sys_ni.c``


Implementación de Llamada de Sistema x86
----------------------------------------

Para conectar su nueva llamada de sistema a plataformas x86, necesita
actualizar las tablas maestras syscall. Asumiendo que su nueva llamada de
sistema ni es especial de alguna manera (revise abajo), esto involucra una
entrada "común" (para x86_64 y x86_32) en
arch/x86/entry/syscalls/syscall_64.tbl::

    333   common   xyzz     sys_xyzzy

y una entrada "i386" en ``arch/x86/entry/syscalls/syscall_32.tbl``::

    380   i386     xyzz     sys_xyzzy

De nuevo, estos número son propensos de ser cambiados si hay conflictos en
la ventana de integración relevante.


Compatibilidad de Llamadas de Sistema (Genérica)
------------------------------------------------

Para la mayoría de llamadas al sistema la misma implementación 64-bit puede
ser invocada incluso cuando el programa de userspace es en si mismo 32-bit;
incluso si los parámetros de la llamada de sistema incluyen un puntero
explícito, esto es manipulado de forma transparente.

Sin embargo, existe un par de situaciones donde se necesita una capa de
compatibilidad para lidiar con las diferencias de tamaño entre 32-bit y
64-bit.

La primera es si el kernel 64-bit también soporta programas del userspace
32-bit, y por lo tanto necesita analizar areas de memoria del (``__user``)
que podrían tener valores tanto 32-bit como 64-bit. En particular esto se
necesita siempre que un argumento de la llamada a sistema es:

 - un puntero a un puntero
 - un puntero a un struc conteniendo un puntero (por ejemplo
   ``struct iovec __user *``)
 - un puntero a un type entero de tamaño entero variable (``time_t``,
   ``off_t``, ``long``, ...)
 - un puntero a un struct conteniendo un type entero de tamaño variable.

La segunda situación que requiere una capa de compatibilidad es cuando uno
de los argumentos de la llamada a sistema tiene un argumento que es
explícitamente 64-bit incluso sobre arquitectura 32-bit, por ejemplo
``loff_t`` o ``__u64``. En este caso, el valor que llega a un kernel 64-bit
desde una aplicación de 32-bit se separará en dos valores de 32-bit, los
que luego necesitan ser reensamblados en la capa de compatibilidad.

(Note que un argumento de una llamada a sistema que sea un puntero a un
type explicitamente de 64-bit **no** necesita una capa de compatibilidad;
por ejemplo, los argumentos de :manpage:`splice(2)`) del tipo
``loff_t __user *`` no significan la necesidad de una llamada a sistema
``compat_``.)

La versión compatible de la llamada de sistema se llama
``compat_sys_xyzzy()``, y se agrega con la macro
``COMPAT_SYSCALL_DEFINEn``, de manera análoga a SYSCALL_DEFINEn. Esta
versión de la implementación se ejecuta como parte de un kernel de 64-bit,
pero espera recibir parametros con valores 32-bit y hace lo que tenga que
hacer para tratar con ellos. (Típicamente, la versión ``compat_sys_``
convierte los valores a versiones de 64 bits y llama a la versión ``sys_``
o ambas llaman a una función de implementación interna común.)

El punto de entrada compat también necesita un prototipo de función
correspondiente, en ``include/linux/compat.h``, marcado como asmlinkage
para igualar la forma en que las llamadas al sistema son invocadas::

    asmlinkage long compat_sys_xyzzy(...);

Si la nueva llamada al sistema involucra una estructura que que se dispone
de forma distinta en sistema de 32-bit y 64-bit, digamos
``struct xyzzy_args``, entonces el archivo de cabecera
include/linux/compat.h también debería incluir una versión compatible de la
estructura (``struct compat_xyzzy_args``) donde cada campo de tamaño
variable tiene el tipo ``compat_`` apropiado que corresponde al tipo en
``struct xyzzy_args``. La rutina ``compat_sys_xyzzy()`` puede entonces usar
esta estructura ``compat_`` para analizar los argumentos de una invocación
de 32-bit.

Por ejemplo, si hay campos::

    struct xyzzy_args {
      const char __user *ptr;
      __kernel_long_t varying_val;
      u64 fixed_val;
      /* ... */
    };

en struct xyzzy_args, entonces struct compat_xyzzy_args debe tener::

    struct compat_xyzzy_args {
      compat_uptr_t ptr;
      compat_long_t varying_val;
      u64 fixed_val;
      /* ... */
    };

la lista genérica de llamadas al sistema también necesita ajustes para
permitir la versión compat; la entrada en
``include/uapi/asm-generic/unistd.h`` debería usar ``__SC_COMP`` en vez de
``__SYSCALL``::

    #define __NR_xyzzy 292
    __SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy)

Para resumir, necesita:

  - una ``COMPAT_SYSCALL_DEFINEn(xyzzy, ...)`` para el punto de entrada de compat.
  - el prototipo correspondiente en ``include/linux/compat.h``
  - (en caso de ser necesario) un struct de mapeo de 32-bit en ``include/linux/compat.h``
  - una instancia de ``__SC_COMP`` no ``__SYSCALL`` en ``include/uapi/asm-generic/unistd.h``

Compatibilidad de Llamadas de Sistema (x86)
-------------------------------------------

Para conectar la arquitectura x86 de una llamada al sistema con una versión
de compatibilidad, las entradas en las tablas de syscall deben ser
ajustadas.

Primero, la entrada en ``arch/x86/entry/syscalls/syscall_32.tbl`` recibe
una columna extra para indicar que un programa del userspace de 32-bit
corriendo en un kernel de 64-bit debe llegar al punto de entrada compat::

    380  i386     xyzzy      sys_xyzzy    __ia32_compat_sys_xyzzy

Segundo, tienes que averiguar qué debería pasar para la versión x32 ABI de
la nueva llamada al sistema. Aquí hay una elección: el diseño de los
argumentos debería coincidir con la versión de 64-bit o la versión de
32-bit.

Si hay involucrado un puntero-a-puntero, la decisión es fácil: x32 es
ILP32, por lo que el diseño debe coincidir con la versión 32-bit, y la
entrada en ``arch/x86/entry/syscalls/syscall_64.tbl`` se divide para que
progamas 32-bit lleguen al envoltorio de compatibilidad::

    333   64        xyzzy       sys_xyzzy
    ...
    555   x32       xyzzy       __x32_compat_sys_xyzzy

Si no hay punteros involucrados, entonces es preferible reutilizar el system
call 64-bit para el x32 ABI  (y consecuentemente la entrada en
arch/x86/entry/syscalls/syscall_64.tbl no se cambia).

En cualquier caso, debes revisar que lo tipos involucrados en su diseño de
argumentos de hecho asigne exactamente de x32 (-mx32) a 32-bit(-m32) o
equivalentes 64-bit (-m64).


Llamadas de Sistema Retornando a Otros Lugares
----------------------------------------------

Para la mayoría de las llamadas al sistema, una vez que se la llamada al
sistema se ha completado el programa de usuario continúa exactamente donde
quedó -- en la siguiente instrucción, con el stack igual y la mayoría de
los registros igual que antes de la llamada al sistema, y con el mismo
espacio en la memoria virtual.

Sin embargo, unas pocas llamadas al sistema hacen las cosas diferente.
Estas podrían retornar a una ubicación distinta (``rt_sigreturn``) o
cambiar el espacio de memoria (``fork``/``vfork``/``clone``) o incluso de
arquitectura (``execve``/``execveat``) del programa.

Para permitir esto, la implementación del kernel de la llamada al sistema
podría necesitar guardar y restaurar registros adicionales al stak del
kernel, brindandole control completo de donde y cómo la ejecución continúa
después de la llamada a sistema.

Esto es arch-specific, pero típicamente involucra definir puntos de entrada
assembly que guardan/restauran registros adicionales e invocan el punto de
entrada real de la llamada a sistema.

Para x86_64, esto es implementado como un punto de entrada ``stub_xyzzy``
en ``arch/x86/entry/entry_64.S``, y la entrada en la tabla syscall
(``arch/x86/entry/syscalls/syscall_32.tbl``) es ajustada para calzar::

    333   common  xyzzy     stub_xyzzy

El equivalente para programas 32-bit corriendo en un kernel 64-bit es
normalmente llamado ``stub32_xyzzy`` e implementado en
``arch/x86/entry/entry_64_compat.S``, con el correspondiente ajuste en la
tabla syscall en ``arch/x86/syscalls/syscall_32.tbl``::

    380    i386       xyzzy     sys_xyzzy     stub32_xyzzy

Si la llamada a sistema necesita una capa de compatibilidad (como en la
sección anterior) entonces la versión ``stub32_`` necesita llamar a la
versión ``compat_sys_`` de la llamada a sistema, en vez de la versión
nativa de 64-bit. También, si la implementación de la versión x32 ABI no es
comun con la versión x86_64, entonces su tabla syscall también necesitará
invocar un stub que llame a la versión ``compat_sys_``

Para completar, también es agradable configurar un mapeo de modo que el
user-mode linux todavía funcione -- su tabla syscall referenciará
stub_xyzzy, pero el UML construido no incluye una implementación
``arch/x86/entry/entry_64.S``. Arreglar esto es tan simple como agregar un
#define a ``arch/x86/um/sys_call_table_64.c``::

    #define stub_xyzzy sys_xyzzy


Otros detalles
--------------

La mayoría del kernel trata las llamadas a sistema de manera genérica, pero
está la excepción ocasional que pueda requerir actualización para su
llamada a sistema particular.

El subsistema de auditoría es un caso especial; este incluye funciones
(arch-specific) que clasifican algunos tipos especiales de llamadas al
sistema -- específicamente file open (``open``/``openat``), program
execution (``execve`` /``execveat``) o operaciones multiplexores de socket
(``socketcall``). Si su nueva llamada de sistema es análoga a alguna de
estas, entonces el sistema auditor debe ser actualizado.

Más generalmente, si existe una llamada al sistema que sea análoga a su
nueva llamada al sistema, entonces vale la pena hacer un grep a todo el
kernel de la llamada a sistema existente, para revisar que no exista otro
caso especial.


Testing
-------

Una nueva llamada al sistema debe obviamente ser probada; también es útil
proveer a los revisores con una demostración de cómo los programas del
userspace usarán la llamada al sistema. Una buena forma de combinar estos
objetivos es incluir un simple programa self-test en un nuevo directorio
bajo ``tools/testing/selftests/``.

Para una nueva llamada al sistema, obviamente no habrá una función
envoltorio libc por lo que el test necesitará ser invocado usando
``syscall()``; también, si la llamada al sistema involucra una nueva
estructura userspace-visible, el encabezado correspondiente necesitará ser
instalado para compilar el test.

Asegure que selftest corra satisfactoriamente en todas las arquitecturas
soportadas. Por ejemplo, revise si funciona cuando es compilado como un
x86_64 (-m64), x86_32 (-m32) y x32 (-mx32) programa ABI.

Para pruebas más amplias y exhautivas de la nueva funcionalidad, también
debería considerar agregar tests al Linus Test Project, o al proyecto
xfstests para cambios filesystem-related

  - https://linux-test-project.github.io/
  - git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git


Man Page
--------

Todas las llamada al sistema nueva deben venir con un man page completo,
idealmente usando groff markup, pero texto plano también funciona. Si se
usa groff, es útil incluir una versión ASCII pre-renderizada del man-page
en el cover del email para el patchset, para la conveniencia de los
revisores.

El man page debe ser cc'do a linux-man@vger.kernel.org
Para más detalles, revise https://www.kernel.org/doc/man-pages/patches.html


No invoque las llamadas de sistemas en el kernel
------------------------------------------------

Las llamadas al sistema son, cómo se declaró más arriba, puntos de
interacción entre el userspace y el kernel. Por lo tanto, las funciones de
llamada al sistema como ``sys_xyzzy()`` o ``compat_sys_xyzzy()`` deberían
ser llamadas sólo desde el userspace vía la tabla de syscall, pero no de
otro lugar en el kernel. Si la funcionalidad syscall es útil para ser usada
dentro del kernel, necesita ser compartida entre syscalls nuevas o
antiguas, o necesita ser compartida entre una syscall y su variante de
compatibilidad, esta debería ser implementada mediante una función "helper"
(como ``ksys_xyzzy()``). Esta función del kernel puede ahora ser llamada
dentro del syscall stub (``sys_xyzzy()``), la syscall stub de
compatibilidad (``compat_sys_xyzzy()``), y/o otro código del kernel.

Al menos en 64-bit x86, será un requerimiento duro desde la v4.17 en
adelante no invocar funciones de llamada al sistema (system call) en el
kernel. Este usa una convención de llamada diferente para llamadas al
sistema donde ``struct pt_regs`` es decodificado on-the-fly en un
envoltorio syscall que luego entrega el procesamiento al syscall real. Esto
significa que sólo aquellos parámetros que son realmente necesarios para
una syscall específica son pasados durante la entrada del syscall, en vez
de llenar en seis registros de CPU con contenido random del userspace todo
el tiempo (los cuales podrían causar serios problemas bajando la cadena de
llamadas).

Más aún, reglas sobre cómo se debería acceder a la data pueden diferir
entre la data del kernel y la data de usuario. Esta es otra razón por la
cual llamar a ``sys_xyzzy()`` es generalmente una mala idea.

Excepciones a esta regla están permitidas solamente en overrides
específicos de arquitectura, envoltorios de compatibilidad específicos de
arquitectura, u otro código en arch/.


Referencias y fuentes
---------------------

 - Artículo LWN de Michael Kerrisk sobre el uso de argumentos flags en llamadas al
   sistema:
   https://lwn.net/Articles/585415/
 - Artículo LWN de Michael Kerrisk sobre cómo manejar flags desconocidos en una
   llamada al sistema: https://lwn.net/Articles/588444/
 - Artículo LWN de Jake Edge describiendo restricciones en argumentos en
   64-bit system call: https://lwn.net/Articles/311630/
 - Par de artículos LWN de David Drysdale que describen la ruta de implementación
   de llamadas al sistema en detalle para v3.14:

    - https://lwn.net/Articles/604287/
    - https://lwn.net/Articles/604515/

 - Requerimientos arquitectura-específicos para llamadas al sistema son discutidos en el
   :manpage:`syscall(2)` man-page:
   http://man7.org/linux/man-pages/man2/syscall.2.html#NOTES
 - Recopilación de emails de Linus Torvalds discutiendo problemas con ``ioctl()``:
   https://yarchive.net/comp/linux/ioctl.html
 - "How to not invent kernel interfaces", Arnd Bergmann,
   https://www.ukuug.org/events/linux2007/2007/papers/Bergmann.pdf
 - Artículo LWN de Michael Kerrisk sobre evitar nuevos usos de CAP_SYS_ADMIN:
   https://lwn.net/Articles/486306/
 - Recomendaciones de Andrew Morton que toda la información relacionada a una nueva
   llamada al sistema debe venir en el mismo hilo de correos:
   https://lore.kernel.org/r/20140724144747.3041b208832bbdf9fbce5d96@linux-foundation.org
 - Recomendaciones de Michael Kerrisk que una nueva llamada al sistema debe venir
   con un man-page: https://lore.kernel.org/r/CAKgNAkgMA39AfoSoA5Pe1r9N+ZzfYQNvNPvcRN7tOvRb8+v06Q@mail.gmail.com
 - Sugerencias de Thomas Gleixner que conexiones x86 deben ir en commits
   separados: https://lore.kernel.org/r/alpine.DEB.2.11.1411191249560.3909@nanos
 - Sugerencias de Greg Kroah-Hartman que es bueno para las nueva llamadas al sistema
   que vengan con man-page y selftest: https://lore.kernel.org/r/20140320025530.GA25469@kroah.com
 - Discusión de Michael Kerrisk de nuevas system call vs. extensiones :manpage:`prctl(2)`:
   https://lore.kernel.org/r/CAHO5Pa3F2MjfTtfNxa8LbnkeeU8=YJ+9tDqxZpw7Gz59E-4AUg@mail.gmail.com
 - Sugerencias de Ingo Molnar que llamadas al sistema que involucran múltiples
   argumentos deben encapsular estos argumentos en una estructura, la cual incluye
   un campo de tamaño para futura extensibilidad: https://lore.kernel.org/r/20150730083831.GA22182@gmail.com
 - Enumerando rarezas por la (re-)utilización de O_* numbering space flags:

    - commit 75069f2b5bfb ("vfs: renumber FMODE_NONOTIFY and add to uniqueness
      check")
    - commit 12ed2e36c98a ("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc
      conflict")
    - commit bb458c644a59 ("Safer ABI for O_TMPFILE")

 - Discusión de Matthew Wilcox sobre las restricciones en argumentos 64-bit:
   https://lore.kernel.org/r/20081212152929.GM26095@parisc-linux.org
 - Recomendaciones de Greg Kroah-Hartman sobre flags desconocidos deben ser
   vigilados: https://lore.kernel.org/r/20140717193330.GB4703@kroah.com
 - Recomendaciones de Linus Torvalds que las llamadas al sistema x32 deben favorecer
   compatibilidad con versiones 64-bit sobre versiones 32-bit:
   https://lore.kernel.org/r/CA+55aFxfmwfB7jbbrXxa=K7VBYPfAvmu3XOkGrLbB1UFjX1+Ew@mail.gmail.com