xref: /linux/Documentation/translations/pt_BR/process/adding-syscalls.rst (revision 72fdff1416e280e2baaa3cca69574defb998437e)
1.. SPDX-License-Identifier: GPL-2.0
2
3=======================================
4Adicionando uma Nova Chamada de Sistema
5=======================================
6
7Este documento descreve o que está envolvido na adição de uma nova chamada de
8sistema (system call) ao kernel Linux, indo além dos conselhos normais de
9submissão em
10:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`.
11
12
13Alternativas às Chamadas de Sistema
14-----------------------------------
15
16A primeira coisa a se considerar ao adicionar uma nova chamada de sistema é se
17uma das alternativas poderia ser mais adequada. Embora as chamadas de sistema
18sejam os pontos de interação mais tradicionais e óbvios entre o espaço do
19usuário (userspace) e o kernel, existem outras possibilidades -- escolha o que
20melhor se adapta à sua interface.
21
22 - Se as operações envolvidas puderem ser moldadas para se parecerem com um
23   objeto do tipo arquivo, pode fazer mais sentido criar um novo sistema de
24   arquivos ou dispositivo. Isso também torna mais fácil encapsular a nova
25   funcionalidade em um módulo de kernel, em vez de exigir que ela seja
26   incorporada ao kernel principal.
27
28     - Se a nova funcionalidade envolver operações em que o kernel notifica o
29       espaço do usuário de que algo aconteceu, retornar um novo descritor de
30       arquivo (file descriptor) para o objeto relevante permite que o espaço
31       do usuário use ``poll``/``select``/``epoll`` para receber essa
32       notificação.
33     - No entanto, as operações que não se mapeiam para operações do tipo
34       :manpage:`read(2)`/:manpage:`write(2)` precisam ser implementadas como
35       requisições :manpage:`ioctl(2)`, o que pode levar a uma API um tanto
36       quanto opaca.
37
38 - Se você estiver apenas expondo informações do sistema em tempo de execução,
39   um novo nó no sysfs (veja ``Documentation/filesystems/sysfs.rst``) ou no
40   sistema de arquivos ``/proc`` pode ser mais apropriado. No entanto, o acesso
41   a esses mecanismos exige que o sistema de arquivos relevante esteja montado,
42   o que pode não ser sempre o caso (por exemplo, em um ambiente com namespaces,
43   sandboxed ou chrooted). Evite adicionar qualquer API ao debugfs, pois este
44   não é considerado uma interface de "produção" para o espaço do usuário.
45 - Se a operação for específica para um arquivo ou descritor de arquivo de um
46   determinado objeto, então uma opção de comando adicional para :manpage:`fcntl(2)`
47   pode ser mais adequada. Contudo, o :manpage:`fcntl(2)` é uma chamada de sistema
48   de multiplexação que oculta muita complexidade, portanto, esta opção é melhor
49   para quando a nova função for intimamente análoga à funcionalidade existente
50   do :manpage:`fcntl(2)`, ou se a nova funcionalidade for muito simples (por
51   exemplo, obter/definir uma flag simples relacionada a um descritor de arquivo).
52 - Se a operação for específica para uma tarefa (task) ou processo específico,
53   então uma opção de comando adicional para :manpage:`prctl(2)` pode ser mais
54   apropriada. Assim como no caso do :manpage:`fcntl(2)`, esta chamada de sistema
55   é um multiplexador complicado, sendo melhor reservá-la para análogos próximos
56   de comandos ``prctl()`` existentes ou para obter/definir uma flag simples
57   relacionada a um processo.
58
59
60Projetando a API: Planejando a Extensibilidade
61----------------------------------------------
62
63Uma nova chamada de sistema faz parte da API do kernel e deve ser suportada
64indefinidamente. Sendo assim, é uma excelente ideia discutir explicitamente a
65interface na lista de discussão do kernel (LKML), e é crucial planejar extensões
66futuras para essa interface.
67
68(A tabela de chamadas de sistema está repleta de exemplos históricos onde isso
69não foi feito, juntamente com as respectivas chamadas de sistema de acompanhamento
70-- ``eventfd``/``eventfd2``, ``dup2``/``dup3``, ``inotify_init``/``inotify_init1``,
71``pipe``/``pipe2``, ``renameat``/``renameat2`` -- portanto, aprenda com a história
72do kernel e planeje as extensões desde o início.)
73
74Para chamadas de sistema mais simples que recebem apenas alguns argumentos, a
75maneira preferencial de permitir extensibilidade futura é incluir um argumento de
76flags na chamada de sistema. Para garantir que os programas do espaço do usuário
77possam usar flags de forma segura entre diferentes versões do kernel, verifique
78se o valor de flags contém qualquer flag desconhecida e rejeite a chamada de
79sistema (com ``EINVAL``) se contiver::
80
81    if (flags & ~(THING_FLAG1 | THING_FLAG2 | THING_FLAG3))
82        return -EINVAL;
83
84(Se nenhum valor de flag for utilizado ainda, verifique se o argumento de flags
85é zero.)
86
87Para chamadas de sistema mais sofisticadas que envolvem um número maior de
88argumentos, prefere-se encapsular a maioria dos argumentos em uma estrutura
89(struct) que é passada por meio de um ponteiro. Esse tipo de estrutura pode
90lidar com extensões futuras incluindo um argumento de tamanho (size) na própria
91estrutura::
92
93    struct xyzzy_params {
94        u32 size; /* o espaço do usuário define p->size = sizeof(struct xyzzy_params) */
95        u32 param_1;
96        u64 param_2;
97        u64 param_3;
98    };
99
100Desde que qualquer campo adicionado subsequentemente, digamos ``param_4``, seja
101projetado de forma que um valor zero mantenha o comportamento anterior, isso
102permitirá lidar com a divergência de versões em ambas as direções:
103
104 - Para lidar com um programa de espaço do usuário mais novo chamando um kernel
105   mais antigo, o código do kernel deve verificar se qualquer memória além do
106   tamanho da estrutura que ele espera está zerada (efetivamente verificando
107   se ``param_4 == 0``).
108 - Para lidar com um programa de espaço do usuário mais antigo chamando um kernel
109   mais novo, o código do kernel pode preencher com zero (zero-extend) a
110   instância menor da estrutura (efetivamente definindo ``param_4 = 0``).
111
112Veja :manpage:`perf_event_open(2)` e a função ``perf_copy_attr()`` (em
113``kernel/events/core.c``) para um exemplo desta abordagem.
114
115
116Projetando a API: Outras Considerações
117--------------------------------------
118
119Se a sua nova chamada de sistema permitir que o espaço do usuário se refira a
120um objeto do kernel, ela deve usar um descritor de arquivo (file descriptor)
121como o handle (identificador) para esse objeto -- não invente um novo tipo de
122handle de objeto para o espaço do usuário quando o kernel já possui mecanismos
123e semânticas bem definidas para o uso de descritores de arquivo.
124
125Se a sua nova chamada de sistema (2) de fato retornar un novo descritor de
126arquivo, então o argumento de flags deve incluir um valor que seja equivalente
127a definir ``O_CLOEXEC`` no novo FD. Isso torna possível para o espaço do usuário
128fechar a janela de tempo entre a chamada ``()`` e a execução de
129``fcntl(fd, F_SETFD, FD_CLOEXEC)``, onde um ``fork()`` e ``execve()`` inesperados
130em outra thread poderiam vazar um descritor para o programa executado. (Contudo,
131resista à tentação de reutilizar o valor real da constante ``O_CLOEXEC``, pois
132ela é específica de cada arquitetura e faz parte de um espaço de numeração de
133flags ``O_*`` que está bastante cheio.)
134
135Se a sua chamada de sistema retornar um novo descritor de arquivo, você também
136deve considerar o que significa usar a família de chamadas de sistema
137:manpage:`poll(2)` nesse descritor de arquivo. Tornar um descritor de arquivo
138pronto para leitura ou escrita é a maneira normal de o kernel indicar ao espaço
139do usuário que um evento ocorreu no objeto correspondente do kernel.
140
141Se a sua nova chamada de sistema (2) envolver um argumento de nome de arquivo
142(filename)::
143
144    int sys_xyzzy(const char __user *path, ..., unsigned int flags);
145
146você também deve considerar se uma versão xyzzyat(2) seria mais apropriada::
147
148    int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags);
149
150Isso permite maior flexibilidade para a forma como o espaço do usuário especifica
151o arquivo em questão; em particular, permite que o espaço do usuário solicite a
152funcionalidade para um descritor de arquivo já aberto usando a flag
153``AT_EMPTY_PATH``, fornecendo efetivamente uma operação fxyzzy(3) de graça::
154
155 - xyzzyat(AT_FDCWD, path, ..., 0) é equivalente a (path,...)
156 - xyzzyat(fd, "", ..., AT_EMPTY_PATH) é equivalente a fxyzzy(fd, ...)
157
158(Para mais detalhes sobre a justificativa das chamadas \*at(), veja a página de
159manual :manpage:`openat(2)`; para um exemplo de AT_EMPTY_PATH, veja a página de
160manual :manpage:`fstatat(2)`.)
161
162Se a sua nova chamada de sistema (2) envolver um parâmetro que descreve um
163deslocamento (offset) dentro de um arquivo, mude o seu tipo para ``loff_t`` para
164que offsets de 64 bits possam ser suportados mesmo em arquiteturas de 32 bits.
165
166Se a sua nova chamada de sistema (2) envolver funcionalidades privilegiadas,
167ela precisa ser governada pelo bit de capacidade (capability) do Linux apropriado
168(verificado com uma chamada a ``capable()``), conforme descrito na página de
169manual :manpage:`capabilities(7)`. Escolha um bit de capacidade existente que governe
170funcionalidades relacionadas, mas tente evitar combinar muitas funções que tenham
171apenas uma vaga relação sob o mesmo bit, pois isso vai contra o propósito das
172capabilities de dividir o poder do root. Em particular, evite adicionar novos
173usos para a capacidade ``CAP_SYS_ADMIN``, que já é excessivamente generalista.
174
175Se a sua nova chamada de sistema (2) manipular um processo diferente do
176processo que a chamou, ela deve ser restrita (usando uma chamada a
177``ptrace_may_access()``) para que apenas um processo chamador com as mesmas
178permissões do processo alvo, ou com as capacidades necessárias, possa manipular
179o processo alvo.
180
181Finalmente, esteja ciente de que algumas arquiteturas não-x86 lidam melhor se os
182parâmetros da chamada de sistema que são explicitamente de 64 bits caírem em
183argumentos de numeração ímpar (ou seja, parâmetro 1, 3, 5), para permitir o uso
184de pares contíguos de registradores de 32 bits. (Esta preocupação não se aplica
185se os argumentos fizerem parte de uma estrutura que é passada por meio de um
186ponteiro.)
187
188
189Propondo a API
190--------------
191
192Para tornar as novas chamadas de sistema fáceis de revisar, é melhor dividir o
193conjunto de patches (patchset) em blocos separados. Estes devem incluir, pelo
194menos, os seguintes itens como commits distintos (cada um dos quais é descrito
195mais adiante):
196
197 - A implementação central da chamada de sistema, juntamente com protótipos,
198   numeração genérica, alterações no Kconfig e a implementação de stub de realinhamento (fallback stub).
199 - A fiação (wiring up) da nova chamada de sistema para uma arquitetura em
200   particular, geralmente x86 (incluindo todas as variantes x86_64, x86_32 e x32).
201 - Uma demonstração do uso da nova chamada de sistema no espaço do usuário por
202   meio de um selftest em ``tools/testing/selftests/``.
203 - Um rascunho da página de manual (man-page) para a nova chamada de sistema,
204   seja como texto simples na carta de apresentação (cover letter) ou como um
205   patch para o repositório (separado) de man-pages.
206
207Novas propostas de chamadas de sistema, como qualquer alteração na API do
208kernel, devem sempre ser enviadas com cópia (cc'ed) para linux-api@vger.kernel.org.
209
210
211Implementação Genérica de Chamadas de Sistema
212---------------------------------------------
213
214O ponto de entrada principal para a sua nova chamada de sistema (2) será chamado
215de ``sys_xyzzy()``, mas você deve adicionar esse ponto de entrada com a macro
216``SYSCALL_DEFINEn()`` apropriada, em vez de fazer isso explicitamente. O 'n'
217indica o número de argumentos da chamada de sistema, e a macro recebe o nome da
218chamada de sistema seguido pelos pares (tipo, nome) para os parâmetros como
219argumentos. O uso dessa macro permite que os metadados sobre a nova chamada de
220sistema fiquem disponíveis para outras ferramentas.
221
222O novo ponto de entrada também precisa de um protótipo de função correspondente
223em ``include/linux/syscalls.h``, marcado como asmlinkage para corresponder à
224maneira como as chamadas de sistema são invocadas::
225
226    asmlinkage long sys_xyzzy(...);
227
228Algumas arquiteturas (por exemplo, x86) possuem suas próprias tabelas de syscall
229específicas da arquitetura, mas várias outras arquiteturas compartilham uma tabela
230de syscall genérica. Adicione a sua nova chamada de sistema à lista genérica
231adicionando uma entrada na lista em ``include/uapi/asm-generic/unistd.h``::
232
233    #define __NR_xyzzy 292
234    __SYSCALL(__NR_xyzzy, sys_xyzzy)
235
236Atualize também a contagem de __NR_syscalls para refletir a chamada de sistema
237adicional, e observe que se múltiplas novas chamadas de sistema forem adicionadas
238na mesma janela de mesclagem (merge window), o número da sua nova syscall poderá
239ser ajustado para resolver conflitos.
240
241O arquivo ``kernel/sys_ni.c`` fornece uma implementação de stub de fallback para
242cada chamada de sistema, retornando ``-ENOSYS``. Adicione a sua nova chamada de
243sistema aqui também::
244
245    COND_SYSCALL(sys_xyzzy);
246
247A sua nova funcionalidade de kernel, e a chamada de sistema que a controla, deve
248normalmente ser opcional, portanto adicione uma opção ``CONFIG`` (tipicamente em
249``init/Kconfig``) para ela. Como de costume para novas opções ``CONFIG``:
250
251 - Inclua uma descrição da nova funcionalidade e da chamada de sistema controlada
252   pela opção.
253 - Faça a opção depender de EXPERT se ela deve ser ocultada dos usuários normais.
254 - Faça com que quaisquer novos arquivos de código-fonte que implementem a função
255   sejam dependentes da opção CONFIG no Makefile (por exemplo,
256   ``obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.o``).
257 - Verifique duas vezes se o kernel ainda compila com a nova opção CONFIG desativada.
258
259Para resumir, você precisa de um commit que inclua:
260
261 - Opção ``CONFIG`` para a nova função, normalmente em ``init/Kconfig``
262 - ``SYSCALL_DEFINEn(, ...)`` para o ponto de entrada
263 - Protótipo correspondente em ``include/linux/syscalls.h``
264 - Entrada na tabela genérica em ``include/uapi/asm-generic/unistd.h``
265 - Stub de fallback em ``kernel/sys_ni.c``
266
267
268.. _pt_BR_syscall_generic_6_11:
269
270Desde a versão 6.11
271~~~~~~~~~~~~~~~~~~~
272
273A partir da versão 6.11 do kernel, a implementação de chamadas de sistema
274genéricas para as seguintes arquiteturas não requer mais modificações em
275``include/uapi/asm-generic/unistd.h``:
276
277 - arc
278 - arm64
279 - csky
280 - hexagon
281 - loongarch
282 - nios2
283 - openrisc
284 - riscv
285
286Em vez disso, você precisa atualizar ``scripts/syscall.tbl`` e, se aplicável,
287ajustar ``arch/*/kernel/Makefile.syscalls``.
288
289Como o ``scripts/syscall.tbl`` serve como uma tabela de syscall comum para
290múltiplas arquiteturas, uma nova entrada é necessária nesta tabela::
291
292    468   common        sys_xyzzy
293
294Note que adicionar uma entrada ao ``scripts/syscall.tbl`` com a ABI "common"
295também afeta todas as arquiteturas que compartilham essa tabela. Para alterações
296mais limitadas ou específicas de uma arquitetura, considere usar uma ABI
297específica da arquitetura ou definir uma nova.
298
299Se uma nova ABI, digamos ``xyz``, for introduzida, as atualizações
300correspondentes também devem ser feitas em ``arch/*/kernel/Makefile.syscalls``::
301
302    syscall_abis_{32,64} += xyz (...)
303
304Para resumir, você precisa de um commit que inclua:
305
306 - Opção ``CONFIG`` para a nova função, normalmente em ``init/Kconfig``
307 - ``SYSCALL_DEFINEn(, ...)`` para o ponto de entrada
308 - Protótipo correspondente em ``include/linux/syscalls.h``
309 - Nova entrada em ``scripts/syscall.tbl``
310 - (Se necessário) Atualizações de Makefile em ``arch/*/kernel/Makefile.syscalls``
311 - Stub de fallback em ``kernel/sys_ni.c``
312
313
314Implementação de Chamadas de Sistema em x86
315-------------------------------------------
316
317Para interligar (wire up) a sua nova chamada de sistema nas plataformas x86, você
318precisa atualizar as tabelas mestras de syscall. Assumindo que a sua nova chamada
319de sistema não seja especial de alguma forma (veja abaixo), isso envolve uma
320entrada "common" (para x86_64 e x32) em
321``arch/x86/entry/syscalls/syscall_64.tbl``::
322
323    333   common        sys_xyzzy
324
325e uma entrada "i386" em ``arch/x86/entry/syscalls/syscall_32.tbl``::
326
327    380   i386          sys_xyzzy
328
329Novamente, esses números estão sujeitos a alterações caso ocorram conflitos na
330janela de mesclagem (merge window) relevante.
331
332Chamadas de Sistema de Compatibilidade (Genéricas)
333--------------------------------------------------
334
335Para a maioria das chamadas de sistema, a mesma implementação de 64 bits pode
336ser invocada mesmo quando o programa do espaço do usuário é, ele próprio, de 32
337bits; mesmo se os parâmetros da chamada de sistema incluírem um ponteiro
338explícito, isso é tratado de forma transparente.
339
340No entanto, existem algumas situações em que uma camada de compatibilidade
341(compatibility layer) é necessária para lidar com as diferenças de tamanho entre
34232 bits e 64 bits.
343
344A primeira é se o kernel de 64 bits também suportar programas de espaço do
345usuário de 32 bits e, portanto, precisar analisar áreas de memória
346(``__user``) que poderiam conter valores de 32 bits ou 64 bits. Em particular,
347isso é necessário sempre que um argumento de chamada de sistema for:
348
349 - um ponteiro para um ponteiro
350 - um ponteiro para uma struct que contém um ponteiro (por exemplo,
351   ``struct iovec __user *``)
352 - um ponteiro para um tipo integral de tamanho variável (``time_t``,
353   ``off_t``, ``long``, ...)
354 - um ponteiro para uma struct que contém um tipo integral de tamanho variável.
355
356A segunda situação que requer uma camada de compatibilidade é se um dos
357argumentos da chamada de sistema tiver um tipo que é explicitamente de 64 bits,
358mesmo em uma arquitetura de 32 bits, por exemplo, ``loff_t`` ou ``__u64``. Neste
359caso, um valor que chega ao kernel de 64 bits vindo de uma aplicação de 32 bits
360será dividido em dois valores de 32 bits, que precisarão ser remontados na
361camada de compatibilidade.
362
363(Note que um argumento de chamada de sistema que seja um ponteiro para um tipo
364explícito de 64 bits **não** precisa de uma camada de compatibilidade; por
365exemplo, os argumentos do :manpage:`splice(2)` do tipo ``loff_t __user *`` não
366disparam a necessidade de uma chamada de sistema ``compat_``.)
367
368A versão de compatibilidade da chamada de sistema é chamada de
369``compat_sys_xyzzy()`` e é adicionada com a macro ``COMPAT_SYSCALL_DEFINEn()``,
370de forma análoga à macro SYSCALL_DEFINEn. Esta versão da implementação roda como
371parte de um kernel de 64 bits, mas espera receber valores de parâmetros de 32
372bits e faz o que for necessário para lidar com eles. (Tipicamente, a versão
373``compat_sys_`` converte os valores para versões de 64 bits e chama a versão
374``sys_``, ou ambas chamam uma função interna comum de implementação).
375
376O ponto de entrada compat também precisa de um protótipo de função
377correspondente em ``include/linux/compat.h``, marcado como asmlinkage para
378corresponder à maneira como as chamadas de sistema são invocadas::
379
380    asmlinkage long compat_sys_xyzzy(...);
381
382Se a chamada de sistema envolver uma estrutura cujo layout seja diferente em
383sistemas de 32 bits e 64 bits, digamos ``struct xyzzy_args``, então o arquivo de
384cabeçalho ``include/linux/compat.h`` também deve incluir uma versão compat da
385estrutura (``struct compat_xyzzy_args``), onde cada campo de tamanho variável
386tenha o tipo ``compat_`` correspondente ao tipo na ``struct xyzzy_args``. A
387rotina ``compat_sys_xyzzy()`` pode então usar essa estrutura ``compat_`` para
388analisar os argumentos vindos de uma invocação de 32 bits.
389
390Por exemplo, se existirem os campos::
391
392    struct xyzzy_args {
393        const char __user *ptr;
394        __kernel_long_t varying_val;
395        u64 fixed_val;
396        /* ... */
397    };
398
399na struct xyzzy_args, então a struct compat_xyzzy_args teria::
400
401    struct compat_xyzzy_args {
402        compat_uptr_t ptr;
403        compat_long_t varying_val;
404        u64 fixed_val;
405        /* ... */
406    };
407
408A lista genérica de chamadas de sistema também precisa de ajustes para permitir
409a versão compat; a entrada em ``include/uapi/asm-generic/unistd.h`` deve usar
410``__SC_COMP`` em vez de ``__SYSCALL``::
411
412    #define __NR_xyzzy 292
413    __SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy)
414
415Para resumir, você precisa de:
416
417 - uma macro ``COMPAT_SYSCALL_DEFINEn(, ...)`` para o ponto de entrada compat
418 - protótipo correspondente em ``include/linux/compat.h``
419 - (se necessário) struct de mapeamento de 32 bits em ``include/linux/compat.h``
420 - instância de ``__SC_COMP``, e não de ``__SYSCALL``, em
421   ``include/uapi/asm-generic/unistd.h``
422
423Desde a versão 6.11
424~~~~~~~~~~~~~~~~~~~
425
426Isso se aplica a todas as arquiteturas listadas em
427:ref:`Desde a versão 6.11<pt_BR_syscall_generic_6_11>` sob "Implementação Genérica de
428Chamadas de Sistema", exceto arm64. Veja
429:ref:`Chamadas de Sistema de Compatibilidade (arm64)<pt_BR_compat_arm64>` para mais
430informações.
431
432Você precisa estender a entrada em ``scripts/syscall.tbl`` com uma coluna extra
433para indicar que um programa de espaço do usuário de 32 bits rodando em um
434kernel de 64 bits deve atingir o ponto de entrada compat::
435
436    468   common          sys_xyzzy    compat_sys_xyzzy
437
438Para resumir, você precisa de:
439
440 - ``COMPAT_SYSCALL_DEFINEn(, ...)`` para o ponto de entrada compat
441 - Protótipo correspondente em ``include/linux/compat.h``
442 - Modificação da entrada em ``scripts/syscall.tbl`` para incluir uma coluna
443   "compat" extra
444 - (Se necessário) Struct de mapeamento de 32 bits em ``include/linux/compat.h``
445
446
447.. _pt_BR_compat_arm64:
448
449Chamadas de Sistema de Compatibilidade (arm64)
450^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
451
452No arm64, existe uma tabela de syscall dedicada para chamadas de sistema de
453compatibilidade voltadas para o espaço do usuário de 32 bits (AArch32):
454``arch/arm64/tools/syscall_32.tbl``. Você precisa adicionar uma linha adicional
455a esta tabela especificando o ponto de entrada compat::
456
457    468   common          sys_xyzzy    compat_sys_xyzzy
458
459
460Chamadas de Sistema de Compatibilidade (x86)
461--------------------------------------------
462
463Para interligar a arquitetura x86 de uma chamada de sistema com uma versão de
464compatibilidade, as entradas nas tabelas de syscall precisam ser ajustadas.
465
466Primeiro, a entrada em ``arch/x86/entry/syscalls/syscall_32.tbl`` ganha uma
467coluna extra para indicar que um programa de espaço do usuário de 32 bits rodando
468em um kernel de 64 bits deve atingir o ponto de entrada compat::
469
470    380   i386          sys_xyzzy    __ia32_compat_sys_xyzzy
471
472Segundo, você precisa definir o que deve acontecer para a versão da ABI x32 da
473nova chamada de sistema. Há uma escolha aqui: o layout dos argumentos deve
474corresponder à versão de 64 bits ou à versão de 32 bits.
475
476Se houver um ponteiro para um ponteiro envolvido, a decisão é fácil: x32 é
477ILP32 (inteiro, long e ponteiro possuem 32 bits), portanto o layout deve
478corresponder à versão de 32 bits, e a entrada em
479``arch/x86/entry/syscalls/syscall_64.tbl`` é dividida para que os programas x32
480atinjam o wrapper de compatibilidade::
481
482    333   64            sys_xyzzy
483    ...
484    555   x32           __x32_compat_sys_xyzzy
485
486Se não houver ponteiros envolvidos, então é preferível reutilizar a chamada de
487sistema de 64 bits para a ABI x32 (e, consequentemente, a entrada em
488``arch/x86/entry/syscalls/syscall_64.tbl`` permanece inalterada).
489
490Em qualquer um dos casos, você deve verificar se os tipos envolvidos no layout
491dos seus argumentos de fato se mapeiam exatamente do x32 (-mx32) para os seus
492equivalentes de 32 bits (-m32) ou 64 bits (-m64).
493
494
495Chamadas de Sistema com Retorno para Outro Local
496------------------------------------------------
497
498Para a maioria das chamadas de sistema (syscalls), assim que a execução é
499concluída, o programa do usuário continua exatamente de onde parou -- na
500próxima instrução, com a pilha idêntica e a maior parte dos registradores no
501mesmo estado de antes da chamada, além do mesmo espaço de memória virtual.
502
503No entanto, algumas poucas chamadas de sistema agem de forma diferente. Elas
504podem retornar para um local distinto (``rt_sigreturn``), alterar o espaço de
505memória (``fork``/``vfork``/``clone``) ou até mesmo modificar a arquitetura
506(``execve``/``execveat``) do programa.
507
508Para permitir isso, a implementação da chamada de sistema no kernel pode
509precisar salvar e restaurar registradores adicionais na pilha do kernel,
510garantindo controle total de onde e como a execução continuará após a syscall.
511
512Isso é específico de cada arquitetura (arch-specific), mas tipicamente envolve
513a definição de pontos de entrada em assembly que salvam/restauram esses
514registradores adicionais e invocam o ponto de entrada real da chamada de
515sistema.
516
517Para x86_64, isso é implementado como um ponto de entrada ``stub_xyzzy`` em
518``arch/x86/entry/entry_64.S``, e a entrada correspondente na tabela de syscalls
519(``arch/x86/entry/syscalls/syscall_64.tbl``) é ajustada para refletir::
520
521    333   common        stub_xyzzy
522
523O equivalente para programas de 32 bits executados em um kernel de 64 bits é
524normalmente chamado de ``stub32_xyzzy`` e implementado em
525``arch/x86/entry/entry_64_compat.S``, com o respectivo ajuste na tabela de
526syscalls em ``arch/x86/entry/syscalls/syscall_32.tbl``::
527
528    380   i386          sys_xyzzy    stub32_xyzzy
529
530Se a chamada de sistema precisar de uma camada de compatibilidade (como na
531seção anterior), a versão ``stub32_`` precisará chamar a versão
532``compat_sys_`` da chamada de sistema em vez da versão nativa de 64 bits. Além
533disso, se a implementação da ABI x32 não for compartilhada com a versão
534x86_64, sua tabela de syscalls também precisará invocar um stub que direcione
535para a versão ``compat_sys_``.
536
537Por questões de integridade, também é recomendado configurar um mapeamento para
538que o User-Mode Linux (UML) continue funcionando -- sua tabela de syscalls fará
539referência a ``stub_xyzzy``, mas o build do UML não inclui a implementação de
540``arch/x86/entry/entry_64.S`` (já que o UML simula registradores, etc.). Corrigir
541isso é tão simples quanto adicionar um #define em
542``arch/x86/um/sys_call_table_64.c``::
543
544    #define stub_xyzzy sys_xyzzy
545
546
547Outros Detalhes
548---------------
549
550A maior parte do kernel trata as chamadas de sistema de maneira genérica, mas
551há exceções ocasionais que podem precisar de atualização para a sua chamada
552de sistema específica.
553
554O subsistema de auditoria (audit) é um desses casos especiais; ele inclui
555funções (específicas de cada arquitetura) que classificam alguns tipos
556especiais de chamada de sistema -- especificamente operações de abertura de
557arquivo (``open``/``openat``), execução de programa (``execve``/``exeveat``) ou
558multiplexador de socket (``socketcall``). Se a sua nova chamada de sistema for
559análoga a uma dessas, o sistema de auditoria deverá ser atualizado.
560
561De forma mais geral, se existir uma chamada de sistema atual que seja análoga
562à sua nova chamada de sistema, vale a pena fazer um grep em todo o kernel pela
563chamada existente para verificar se não há outros casos especiais.
564
565
566Testes
567------
568
569Uma nova chamada de sistema deve, obviamente, ser testada; também é útil
570fornecer aos revisores uma demonstração de como os programas do espaço do
571usuário (user space) usarão a chamada de sistema. Uma boa maneira de combinar
572esses objetivos é incluir um programa simples de autoteste em um novo diretório
573sob ``tools/testing/selftests/``.
574
575Para uma nova chamada de sistema, obviamente não haverá uma função de wrapper
576na libc e, portanto, o teste precisará invocá-la usando ``syscall()``; além
577disso, se a chamada de sistema envolver uma nova estrutura visível para o
578espaço do usuário, o cabeçalho correspondente precisará ser instalado para
579compilar o teste.
580
581Certifique-se de que o autoteste seja executado com sucesso em todas as
582arquiteturas suportadas. Por exemplo, verifique se ele funciona quando compitado
583como um programa ABI x86_64 (-m64), x86_32 (-m32) e x32 (-mx32).
584
585Para testes mais extensos e minuciosos de novas funcionalidades, você também
586deve considerar a adição de testes ao Linux Test Project ou ao projeto
587xfstests para alterações relacionadas
588
589Página de Manual (Man Page)
590---------------------------
591
592Todas as novas chamadas de sistema devem vir acompanhadas de uma página de
593manual completa, idealmente usando a marcação groff, mas texto simples também
594é aceitável. Se o groff for utilizado, é útil incluir uma versão ASCII pré-
595renderizada da página de manual no e-mail de apresentação (cover letter) do
596conjunto de patches (patchset), para a conveniência dos revisores.
597
598A página de manual deve ser enviada com cópia (cc) para
599linux-man@vger.kernel.org. Para mais detalhes, consulte
600https://www.kernel.org/doc/man-pages/patches.html
601
602
603Não invoque Chamadas de Sistema dentro do Kernel
604------------------------------------------------
605
606As chamadas de sistema são, como mencionado acima, pontos de interação entre o
607espaço do usuário (userspace) e o kernel. Portanto, funções de chamada de
608sistema como ``sys_xyzzy()`` ou ``compat_sys_xyzzy()`` só devem ser chamadas a
609partir do espaço do usuário por meio da tabela de syscalls, e não de outros
610lugares do kernel. Se a funcionalidade da syscall for útil para ser utilizada
611dentro do kernel, precisar ser compartilhada entre uma syscall antiga e uma
612nova, ou precisar ser compartilhada entre uma syscall e sua variante de
613compatibilidade, ela deve ser implementada por meio de uma função auxiliadora
614("helper", como ``ksys_xyzzy()``). Essa função do kernel poderá então ser
615chamada dentro do stub da syscall (``sys_xyzzy()``), do stub da syscall de
616compatibilidade (``compat_sys_xyzzy()``) e/ou de outro código do kernel.
617
618Pelo menos em x86 de 64 bits, será um requisito rígido a partir da versão v4.17
619em diante não chamar funções de chamadas de sistema no kernel. Essa arquitetura
620utiliza uma convenção de chamada diferente para chamadas de sistema na qual a
621``struct pt_regs`` é decodificada dinamicamente em um wrapper de syscall, que
622então repassa o processamento para a função real da syscall. Isso significa que
623apenas os parâmetros realmente necessários para uma syscall específica são
624passados durante a entrada da syscall, em vez de preencher seis registradores da
625CPU com conteúdos aleatórios do espaço do usuário o tempo todo (o que poderia
626causar problemas sérios no decorrer da cadeia de chamadas).
627
628Além disso, as regras sobre como os dados podem ser acessados diferem entre os
629dados do kernel e os dados do usuário. Essa é outra razão pela qual chamar
630``sys_xyzzy()`` geralmente é uma má ideia.
631
632Exceções a essa regra são permitidas apenas em substituições (overrides)
633específicas de cada arquitetura, wrappers de compatibilidade específicos de cada
634arquitetura ou outros códigos dentro do diretório arch/.
635
636Referências e Fontes
637--------------------
638
639 - Artigo da LWN por Michael Kerrisk sobre o uso do argumento flags em chamadas
640   de sistema:
641   https://lwn.net/Articles/585415/
642 - Artigo da LWN por Michael Kerrisk sobre como lidar com flags desconhecidas
643   em uma chamada de sistema: https://lwn.net/Articles/588444/
644 - Artigo da LWN por Jake Edge descrevendo restrições em argumentos de chamadas
645   de sistema de 64 bits: https://lwn.net/Articles/311630/
646 - Par de artigos da LWN por David Drysdale que descrevem detalhadamente os
647   caminhos de implementação de chamadas de sistema para a v3.14:
648
649    - https://lwn.net/Articles/604287/
650    - https://lwn.net/Articles/604515/
651
652 - Os requisitos específicos de arquitetura para chamadas de sistema são
653   discutidos na página de manual :manpage:`syscall(2)`:
654   http://man7.org/linux/man-pages/man2/syscall.2.html#NOTES
655 - E-mails compilados de Linus Torvalds discutindo os problemas com ``ioctl()``:
656   https://yarchive.net/comp/linux/ioctl.html
657 - "How to not invent kernel interfaces", Arnd Bergmann,
658   https://www.ukuug.org/events/linux2007/2007/papers/Bergmann.pdf
659 - Artigo da LWN por Michael Kerrisk sobre evitar novos usos de CAP_SYS_ADMIN:
660   https://lwn.net/Articles/486306/
661 - Recomendação de Andrew Morton para que todas as informações relacionadas a
662   uma nova chamada de sistema venham na mesma thread de e-mail:
663   https://lore.kernel.org/r/20140724144747.3041b208832bbdf9fbce5d96@linux-foundation.org
664 - Recomendação de Michael Kerrisk para que uma nova chamada de sistema venha
665   acompanhada de uma página de manual:
666   https://lore.kernel.org/r/CAKgNAkgMA39AfoSoA5Pe1r9N+ZzfYQNvNPvcRN7tOvRb8+v06Q@mail.gmail.com
667 - Sugestão de Thomas Gleixner para que a vinculação (wire-up) do x86 esteja em
668   um commit separado:
669   https://lore.kernel.org/r/alpine.DEB.2.11.1411191249560.3909@nanos
670 - Sugestão de Greg Kroah-Hartman de que é bom que novas chamadas de sistema
671   venham acompanhadas de uma página de manual e um autoteste:
672   https://lore.kernel.org/r/20140320025530.GA25469@kroah.com
673 - Discussão de Michael Kerrisk sobre uma nova chamada de sistema versus a
674   extensão de :manpage:`prctl(2)`:
675   https://lore.kernel.org/r/CAHO5Pa3F2MjfTtfNxa8LbnkeeU8=YJ+9tDqxZpw7Gz59E-4AUg@mail.gmail.com
676 - Sugestão de Ingo Molnar de que as chamadas de sistema que envolvem múltiplos
677   argumentos devem encapsular esses argumentos em uma struct, a qual inclua um
678   campo de tamanho (size) para fins de extensibilidade futura:
679   https://lore.kernel.org/r/20150730083831.GA22182@gmail.com
680 - Excentricidades de numeração decorrentes do uso (e reuso) de flags do espaço
681   de numeração O_*:
682
683    - commit 75069f2b5bfb ("vfs: renumber FMODE_NONOTIFY and add to uniqueness
684      check")
685    - commit 12ed2e36c98a ("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc
686      conflict")
687    - commit bb458c644a59 ("Safer ABI for O_TMPFILE")
688
689 - Discussão de Matthew Wilcox sobre restrições em argumentos de 64 bits:
690   https://lore.kernel.org/r/20081212152929.GM26095@parisc-linux.org
691 - Recomendação de Greg Kroah-Hartman de que flags desconhecidas devem ser
692   fiscalizadas/policiadas:
693   https://lore.kernel.org/r/20140717193330.GB4703@kroah.com
694 - Recomendação de Linus Torvalds de que as chamadas de sistema x32 devem
695   preferir a compatibilidade com as versões de 64 bits em vez das versões de
696   32 bits:
697   https://lore.kernel.org/r/CA+55aFxfmwfB7jbbrXxa=K7VBYPfAvmu3XOkGrLbB1UFjX1+Ew@mail.gmail.com
698 - Série de patches revisando a infraestrutura da tabela de chamadas de sistema
699   para utilizar scripts/syscall.tbl em múltiplas arquiteturas:
700   https://lore.kernel.org/lkml/20240704143611.2979589-1-arnd@kernel.org
701