summaryrefslogtreecommitdiffstats
path: root/Documentation/translations/zh_CN
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-12-12 17:18:50 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2022-12-12 17:18:50 -0800
commita7cacfb0688e3988660e90fad7017cc9a18ab390 (patch)
tree90dc3a868ece1794f7a671aa3b5a51d1be9025cf /Documentation/translations/zh_CN
parent96f42635684739cb563aa48d92d0d16b8dc9bda8 (diff)
parentcc8c418b4fc09ed58ddd27b8e90ec797e9ca1e67 (diff)
downloadlinux-a7cacfb0688e3988660e90fad7017cc9a18ab390.tar.bz2
Merge tag 'docs-6.2' of git://git.lwn.net/linux
Pull documentation updates from Jonathan Corbet: "This was a not-too-busy cycle for documentation; highlights include: - The beginnings of a set of translations into Spanish, headed up by Carlos Bilbao - More Chinese translations - A change to the Sphinx "alabaster" theme by default for HTML generation. Unlike the previous default (Read the Docs), alabaster is shipped with Sphinx by default, reducing the number of other dependencies that need to be installed. It also (IMO) produces a cleaner and more readable result. - The ability to render the documentation into the texinfo format (something Sphinx could always do, we just never wired it up until now) Plus the usual collection of typo fixes, build-warning fixes, and minor updates" * tag 'docs-6.2' of git://git.lwn.net/linux: (67 commits) Documentation/features: Use loongarch instead of loong Documentation/features-refresh.sh: Only sed the beginning "arch" of ARCH_DIR docs/zh_CN: Fix '.. only::' directive's expression docs/sp_SP: Add memory-barriers.txt Spanish translation docs/zh_CN/LoongArch: Update links of LoongArch ISA Vol1 and ELF psABI docs/LoongArch: Update links of LoongArch ISA Vol1 and ELF psABI Documentation/features: Update feature lists for 6.1 Documentation: Fixed a typo in bootconfig.rst docs/sp_SP: Add process coding-style translation docs/sp_SP: Add kernel-docs.rst Spanish translation docs: Create translations/sp_SP/process/, move submitting-patches.rst docs: Add book to process/kernel-docs.rst docs: Retire old resources from kernel-docs.rst docs: Update maintainer of kernel-docs.rst Documentation: riscv: Document the sv57 VM layout Documentation: USB: correct possessive "its" usage math64: fix kernel-doc return value warnings math64: add kernel-doc for DIV64_U64_ROUND_UP math64: favor kernel-doc from header files doc: add texinfodocs and infodocs targets ...
Diffstat (limited to 'Documentation/translations/zh_CN')
-rw-r--r--Documentation/translations/zh_CN/core-api/errseq.rst145
-rw-r--r--Documentation/translations/zh_CN/core-api/index.rst6
-rw-r--r--Documentation/translations/zh_CN/core-api/this_cpu_ops.rst285
-rw-r--r--Documentation/translations/zh_CN/doc-guide/index.rst2
-rw-r--r--Documentation/translations/zh_CN/index.rst11
-rw-r--r--Documentation/translations/zh_CN/loongarch/introduction.rst8
-rw-r--r--Documentation/translations/zh_CN/rust/arch-support.rst23
-rw-r--r--Documentation/translations/zh_CN/rust/coding-guidelines.rst192
-rw-r--r--Documentation/translations/zh_CN/rust/general-information.rst75
-rw-r--r--Documentation/translations/zh_CN/rust/index.rst28
-rw-r--r--Documentation/translations/zh_CN/rust/quick-start.rst211
-rw-r--r--Documentation/translations/zh_CN/staging/index.rst26
-rw-r--r--Documentation/translations/zh_CN/staging/xz.rst100
-rw-r--r--Documentation/translations/zh_CN/userspace-api/accelerators/ocxl.rst168
-rw-r--r--Documentation/translations/zh_CN/userspace-api/ebpf/index.rst22
-rw-r--r--Documentation/translations/zh_CN/userspace-api/ebpf/syscall.rst29
-rw-r--r--Documentation/translations/zh_CN/userspace-api/futex2.rst80
-rw-r--r--Documentation/translations/zh_CN/userspace-api/index.rst50
-rw-r--r--Documentation/translations/zh_CN/userspace-api/no_new_privs.rst57
-rw-r--r--Documentation/translations/zh_CN/userspace-api/seccomp_filter.rst293
-rw-r--r--Documentation/translations/zh_CN/userspace-api/sysfs-platform_profile.rst40
21 files changed, 1838 insertions, 13 deletions
diff --git a/Documentation/translations/zh_CN/core-api/errseq.rst b/Documentation/translations/zh_CN/core-api/errseq.rst
new file mode 100644
index 000000000000..815fb303ea2f
--- /dev/null
+++ b/Documentation/translations/zh_CN/core-api/errseq.rst
@@ -0,0 +1,145 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/core-api/errseq.rst
+
+:翻译:
+
+ 周彬彬 Binbin Zhou <zhoubinbin@loongson.cn>
+
+:校译:
+
+ 吴想成 Wu Xiangcheng <bobwxc@email.cn>
+
+================
+errseq_t数据类型
+================
+
+``errseq_t`` 是一种在一个地方记录错误的方法,并允许任意数量的 ``订阅者`` 判断自上
+次采样点以来是否发生了变化。
+
+最初的用例是跟踪文件同步系统调用( ``fsync``, ``fdatasync``, ``msync`` 和
+``sync_file_range`` )的错误,但它也可以用于其他情况。
+
+它被实现为一个无符号的32位值。低位被指定保存错误代码(在1和MAX_ERRNO之间)。高位
+用作计数器。这里是用原子操作而不是锁来完成的,因此可以从任何上下文中调用这些函数。
+
+请注意,如果频繁记录新错误,则存在冲突风险,因为我们用作计数器的位很少。
+
+为了缓解这种情况,错误值和计数器之间的位被用作一个标志,以判断自记录新值以来是否
+对该值进行了采样。这使我们能够避免在上次记录错误后没有人取样的情况下碰撞计数器。
+
+因此,我们得到了一个类似这样的值:
+
++--------------------------------------+------+------------------------+
+| 31..13 | 12 | 11..0 |
++--------------------------------------+------+------------------------+
+| 计数器 | 标志 | 错误值 |
++--------------------------------------+------+------------------------+
+
+总体思路是让 ``观察者`` 对errseq_t值进行采样,并将其保留为运行游标。该值稍后可用
+于判断自采样完成后是否发生了任何新错误,并原子地记录检查时的状态。这使得我们能在
+一个地方记录错误,然后有许多 ``观察者`` 可以判断自上次检查以来该值是否发生了变化。
+
+新的errseq_t应始终清零。全零的errseq_t值是从未出现错误的特殊(但常见)情况。因此,
+如果您希望知道自首次初始化以来是否曾经有过错误集,则全零值被用作 ``纪元`` 。
+
+API的使用方法
+=============
+
+让我给你们讲一个关于员工drone的故事。现在,他总体上是个好员工,但公司有点...管理
+繁重。他今天必须向77名主管汇报,明天 ``大老板`` 要从外地赶来,他肯定也会考验这个
+可怜的家伙。
+
+他们都把工作交给他去做---多到他都记不住谁交给他什么了,但这并不是什么大问题。主管
+们只想知道他什么时候完成他们迄今为止交给他的所有工作,以及自从他们上次询问以来他
+是否犯了任何错误。
+
+他可能在他们实际上并没有交给他的工作上犯了错误,但他无法在那么详细的层面上记录事
+情,他所能记得的只是他最近犯的错误。
+
+下面是我们 ``worker_drone`` 的表达式::
+
+ struct worker_drone {
+ errseq_t wd_err; /* 用来记录错误 */
+ };
+
+每天, ``worker_drone`` 都是以一张白纸开始的::
+
+ struct worker_drone wd;
+
+ wd.wd_err = (errseq_t)0;
+
+主管们进来后对当天的工作进行初步了解。他们并不关心在他们观察开始之前发生的任何事
+情::
+
+ struct supervisor {
+ errseq_t s_wd_err; /* wd_err的私有“游标” */
+ spinlock_t s_wd_err_lock; /* 保护s_wd_err */
+ }
+
+ struct supervisor su;
+
+ su.s_wd_err = errseq_sample(&wd.wd_err);
+ spin_lock_init(&su.s_wd_err_lock);
+
+现在他们开始给他布置任务。每隔几分钟,他们就要求他完成迄今为止交给他的所有工作。
+然后问他是否有犯任何错误::
+
+ spin_lock(&su.su_wd_err_lock);
+ err = errseq_check_and_advance(&wd.wd_err, &su.s_wd_err);
+ spin_unlock(&su.su_wd_err_lock);
+
+到目前为止,它只是不断返回0。
+
+现在,这家公司的老板非常吝啬,给了他不合格的设备来完成他的工作。偶尔设备会出现故
+障,导致他犯错。他重重地叹了一口气,并把它记录下来::
+
+ errseq_set(&wd.wd_err, -EIO);
+
+...然后继续工作。主管们最终会再次检查,他们在下次检查时都会发现这个错误。后续的调
+用将返回0,直到记录下另一个错误,此时将向每个调用报告一次。
+
+请注意,主管们无法知道他们犯了多少错误,只能知道自上次检查以来是否犯了一个错误,
+以及记录的最新值。
+
+偶尔,大老板会来抽查,要求员工为他做一次性的工作。他并不像主管们那样全职观察员工,
+但他确实需要知道在他的工作处理过程中是否发生了错误。
+
+他只需对员工当前的errseq_t进行采样,然后用它来判断后来是否发生了错误::
+
+ errseq_t since = errseq_sample(&wd.wd_err);
+ /* 提交一些工作,等待完成 */
+ err = errseq_check(&wd.wd_err, since);
+
+由于他只是要在那个点之后丢弃 ``since`` ,所以他不需要在这里推进它。同时他也不需要
+任何锁,因为它不能被其他人使用。
+
+序列化更新errseq_t游标
+======================
+
+请注意,errseq_t API在check_and_advance_operation期间不保护errseq_t游标。只有典型
+的错误代码是被原子化处理的。在多任务同时使用同一个errseq_t游标的情况下,对该游标
+的更新进行序列化是很重要的。
+
+如果不这样做,那么游标就有可能向后移动。在这种情况下,同一个错误可能被报告多次。
+
+因此,通常先执行errseq_check检查是否有任何变化,然后在获取锁后才执行
+errseq_check_and_advance。例如::
+
+ if (errseq_check(&wd.wd_err, READ_ONCE(su.s_wd_err)) {
+ /* su.s_wd_err被s_wd_err_lock保护 */
+ spin_lock(&su.s_wd_err_lock);
+ err = errseq_check_and_advance(&wd.wd_err, &su.s_wd_err);
+ spin_unlock(&su.s_wd_err_lock);
+ }
+
+这就避免了自上次检查以来没有任何变化的常见情况下的自旋锁。
+
+函数
+====
+
+该API在以下内核代码中:
+
+lib/errseq.c
diff --git a/Documentation/translations/zh_CN/core-api/index.rst b/Documentation/translations/zh_CN/core-api/index.rst
index 37756d240b5e..922cabf7b5dd 100644
--- a/Documentation/translations/zh_CN/core-api/index.rst
+++ b/Documentation/translations/zh_CN/core-api/index.rst
@@ -48,12 +48,12 @@
circular-buffers
generic-radix-tree
packing
+ this_cpu_ops
-Todolist:
-
+=======
+Todolist:
- this_cpu_ops
timekeeping
errseq
diff --git a/Documentation/translations/zh_CN/core-api/this_cpu_ops.rst b/Documentation/translations/zh_CN/core-api/this_cpu_ops.rst
new file mode 100644
index 000000000000..bea5ee8eb8a0
--- /dev/null
+++ b/Documentation/translations/zh_CN/core-api/this_cpu_ops.rst
@@ -0,0 +1,285 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/core-api/this_cpu_ops.rst
+
+:翻译:
+
+ 周彬彬 Binbin Zhou <zhoubinbin@loongson.cn>
+
+:校译:
+
+ 吴想成 Wu Xiangcheng <bobwxc@email.cn>
+
+============
+this_cpu操作
+============
+
+:作者: Christoph Lameter, 2014年8月4日
+:作者: Pranith Kumar, 2014年8月2日
+
+this_cpu操作是一种优化访问与当前执行处理器相关的每CPU变量的方法。这是通过使用段寄
+存器(或专用寄存器,cpu在其中永久存储特定处理器的每CPU区域的起始)来完成的。
+
+this_cpu操作将每CPU变量的偏移量添加到处理器特定的每CPU基址上,并将该操作编码到对
+每CPU变量进行操作的指令中。
+
+这意味着在偏移量的计算和对数据的操作之间不存在原子性问题。因此,没有必要禁用抢占
+或中断来确保处理器在计算地址和数据操作之间不被改变。
+
+读取-修改-写入操作特别值得关注。通常处理器具有特殊的低延迟指令,可以在没有典型同
+步开销的情况下运行,但仍提供某种宽松的原子性保证。例如,x86可以执行RMW(读取,
+修改,写入)指令,如同inc/dec/cmpxchg,而无需锁前缀和相关的延迟损失。
+
+对没有锁前缀的变量的访问是不同步的,也不需要同步,因为我们处理的是当前执行的处理
+器所特有的每CPU数据。只有当前的处理器可以访问该变量,因此系统中的其他处理器不存在
+并发性问题。
+
+请注意,远程处理器对每CPU区域的访问是特殊情况,可能会影响通过 ``this_cpu_*`` 的本
+地RMW操作的性能和正确性(远程写操作)。
+
+this_cpu操作的主要用途是优化计数器操作。
+
+定义了以下具有隐含抢占保护的this_cpu()操作。可以使用这些操作而不用担心抢占和中断::
+
+ this_cpu_read(pcp)
+ this_cpu_write(pcp, val)
+ this_cpu_add(pcp, val)
+ this_cpu_and(pcp, val)
+ this_cpu_or(pcp, val)
+ this_cpu_add_return(pcp, val)
+ this_cpu_xchg(pcp, nval)
+ this_cpu_cmpxchg(pcp, oval, nval)
+ this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+ this_cpu_sub(pcp, val)
+ this_cpu_inc(pcp)
+ this_cpu_dec(pcp)
+ this_cpu_sub_return(pcp, val)
+ this_cpu_inc_return(pcp)
+ this_cpu_dec_return(pcp)
+
+
+this_cpu操作的内部工作
+----------------------
+
+在x86上,fs:或gs:段寄存器包含每CPU区域的基址。这样就可以简单地使用段覆盖,将每CPU
+相对地址重定位到处理器适当的每CPU区域。所以对每CPU基址的重定位是通过段寄存器前缀
+在指令中编码完成的。
+
+例如::
+
+ DEFINE_PER_CPU(int, x);
+ int z;
+
+ z = this_cpu_read(x);
+
+产生的单指令为::
+
+ mov ax, gs:[x]
+
+而不是像每CPU操作那样,先是一系列的地址计算,然后从该地址获取。在this_cpu_ops之前,
+这样的序列还需要先禁用/启用抢占功能,以防止内核在计算过程中将线程移动到不同的处理
+器上。
+
+请思考下面this_cpu操作::
+
+ this_cpu_inc(x)
+
+这将产生如下单指令(无锁前缀!)::
+
+ inc gs:[x]
+
+而不是在没有段寄存器的情况下所需要的以下操作::
+
+ int *y;
+ int cpu;
+
+ cpu = get_cpu();
+ y = per_cpu_ptr(&x, cpu);
+ (*y)++;
+ put_cpu();
+
+请注意,这些操作只能用于为特定处理器保留的每CPU数据。如果不在上下文代码中禁用抢占,
+``this_cpu_inc()`` 将仅保证每CPU的某一个计数器被正确地递增,但不能保证操作系统不
+会在this_cpu指令执行的前后直接移动该进程。一般来说,这意味着每个处理器的单个计数
+器的值是没有意义的。所有每CPU计数器的总和才是唯一有意义的值。
+
+每CPU变量的使用是出于性能的考虑。如果多个处理器同时处理相同的代码路径,可以避免缓
+存行跳转。每个处理器都有自己的每CPU变量,因此不会发生并发缓存行更新。为这种优化必
+须付出的代价是,当需要计数器的值时要将每CPU计数器相加。
+
+
+特殊的操作
+----------
+
+::
+
+ y = this_cpu_ptr(&x)
+
+使用每CPU变量的偏移量(&x!),并返回属于当前执行处理器的每CPU变量的地址。
+``this_cpu_ptr`` 避免了通用 ``get_cpu``/``put_cpu`` 序列所需的多个步骤。没有可用
+的处理器编号。相反,本地每CPU区域的偏移量只是简单地添加到每CPU偏移量上。
+
+请注意,这个操作通常是在抢占被禁用后再在代码段中使用。然后该指针用来访问临界区中
+的本地每CPU数据。当重新启用抢占时,此指针通常不再有用,因为它可能不再指向当前处理
+器的每CPU数据。
+
+每CPU变量和偏移量
+-----------------
+
+每CPU变量相对于每CPU区域的起始点是有偏移的。它们没有地址,尽管代码里看起来像有一
+样。不能直接对偏移量解引用,必须用处理器每CPU区域基指针加上偏移量,以构成有效地址。
+
+因此,在每CPU操作的上下文之外使用x或&x是无效的,这种行为通常会被当作一个空指针的
+解引用来处理。
+
+::
+
+ DEFINE_PER_CPU(int, x);
+
+在每CPU操作的上下文中,上面表达式说明x是一个每CPU变量。大多数this_cpu操作都需要一
+个cpu变量。
+
+::
+
+ int __percpu *p = &x;
+
+&x和p是每CPU变量的偏移量。 ``this_cpu_ptr()`` 使用每CPU变量的偏移量,这让它看起来
+有点奇怪。
+
+
+每CPU结构体字段的操作
+---------------------
+
+假设我们有一个每CPU结构::
+
+ struct s {
+ int n,m;
+ };
+
+ DEFINE_PER_CPU(struct s, p);
+
+
+这些字段的操作非常简单::
+
+ this_cpu_inc(p.m)
+
+ z = this_cpu_cmpxchg(p.m, 0, 1);
+
+
+如果我们有一个相对于结构体s的偏移量::
+
+ struct s __percpu *ps = &p;
+
+ this_cpu_dec(ps->m);
+
+ z = this_cpu_inc_return(ps->n);
+
+
+如果我们后面不使用 ``this_cpu ops`` 来操作字段,则指针的计算可能需要使用
+``this_cpu_ptr()``::
+
+ struct s *pp;
+
+ pp = this_cpu_ptr(&p);
+
+ pp->m--;
+
+ z = pp->n++;
+
+
+this_cpu ops的变体
+------------------
+
+this_cpu的操作是中断安全的。一些架构不支持这些每CPU的本地操作。在这种情况下,该操
+作必须被禁用中断的代码所取代,然后做那些保证是原子的操作,再重新启用中断。当然这
+样做是很昂贵的。如果有其他原因导致调度器不能改变我们正在执行的处理器,那么就没有
+理由禁用中断了。为此,我们提供了以下__this_cpu操作。
+
+这些操作不能保证并发中断或抢占。如果在中断上下文中不使用每CPU变量并且调度程序无法
+抢占,那么它们是安全的。如果在操作进行时仍有中断发生,并且中断也修改了变量,则无
+法保证RMW操作是安全的::
+
+ __this_cpu_read(pcp)
+ __this_cpu_write(pcp, val)
+ __this_cpu_add(pcp, val)
+ __this_cpu_and(pcp, val)
+ __this_cpu_or(pcp, val)
+ __this_cpu_add_return(pcp, val)
+ __this_cpu_xchg(pcp, nval)
+ __this_cpu_cmpxchg(pcp, oval, nval)
+ __this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+ __this_cpu_sub(pcp, val)
+ __this_cpu_inc(pcp)
+ __this_cpu_dec(pcp)
+ __this_cpu_sub_return(pcp, val)
+ __this_cpu_inc_return(pcp)
+ __this_cpu_dec_return(pcp)
+
+
+将增加x,并且不会回退到在无法通过地址重定位和同一指令中的读取-修改-写入操作实现原
+子性的平台上禁用中断的代码。
+
+
+&this_cpu_ptr(pp)->n 对比 this_cpu_ptr(&pp->n)
+----------------------------------------------
+
+第一个操作使用偏移量并形成一个地址,然后再加上n字段的偏移量。这可能会导致编译器产
+生两条加法指令。
+
+第二个操作先加上两个偏移量,然后进行重定位。恕我直言,第二种形式看起来更干净,而
+且更容易与 ``()`` 结合。第二种形式也与 ``this_cpu_read()`` 和大家的使用方式一致。
+
+
+远程访问每CPU数据
+-----------------
+
+每CPU数据结构被设计为由一个CPU独占使用。如果您按预期使用变量,则 ``this_cpu_ops()``
+保证是 ``原子的`` ,因为没有其他CPU可以访问这些数据结构。
+
+在某些特殊情况下,您可能需要远程访问每CPU数据结构。通常情况下,进行远程读访问是安
+全的,这经常是为了统计计数器值。远程写访问可能会出现问题,因为this_cpu操作没有锁
+语义。远程写可能会干扰this_cpu RMW操作。
+
+除非绝对必要,否则强烈建议不要对每CPU数据结构进行远程写访问。请考虑使用IPI来唤醒
+远程CPU,并对其每CPU区域进行更新。
+
+要远程访问每CPU数据结构,通常使用 ``per_cpu_ptr()`` 函数::
+
+
+ DEFINE_PER_CPU(struct data, datap);
+
+ struct data *p = per_cpu_ptr(&datap, cpu);
+
+这清楚地表明,我们正准备远程访问每CPU区域。
+
+您还可以执行以下操作以将datap偏移量转换为地址::
+
+ struct data *p = this_cpu_ptr(&datap);
+
+但是,将通过this_cpu_ptr计算的指针传递给其他cpu是不寻常的,应该避免。
+
+远程访问通常只用于读取另一个cpu的每CPU数据状态。由于this_cpu操作宽松的同步要求,
+写访问可能会导致奇特的问题。
+
+下面的情况说明了写入操作的一些问题,由于两个每CPU变量共享一个缓存行,但宽松的同步
+仅应用于更新缓存行的一个进程。
+
+考虑以下示例::
+
+
+ struct test {
+ atomic_t a;
+ int b;
+ };
+
+ DEFINE_PER_CPU(struct test, onecacheline);
+
+如果一个处理器远程更新字段 ``a`` ,而本地处理器将使用this_cpu ops来更新字段 ``b`` ,
+会发生什么情况,这一点值得注意。应避免在同一缓存行内同时访问数据。此外,可能还需
+要进行代价高昂的同步。在这种情况下,通常建议使用IPI,而不是远程写入另一个处理器的
+每CPU区域。
+
+即使在远程写很少的情况下,请记住远程写将从最有可能访问它的处理器中逐出缓存行。如
+果处理器唤醒时发现每CPU区域缺少本地缓存行,其性能和唤醒时间将受到影响。
diff --git a/Documentation/translations/zh_CN/doc-guide/index.rst b/Documentation/translations/zh_CN/doc-guide/index.rst
index 5151953c196f..78c2e9a1697f 100644
--- a/Documentation/translations/zh_CN/doc-guide/index.rst
+++ b/Documentation/translations/zh_CN/doc-guide/index.rst
@@ -19,7 +19,7 @@
contributing
maintainer-profile
-.. only:: 子项目与HTML
+.. only:: subproject and html
目录
====
diff --git a/Documentation/translations/zh_CN/index.rst b/Documentation/translations/zh_CN/index.rst
index ec99ef5fe990..3660a3451c86 100644
--- a/Documentation/translations/zh_CN/index.rst
+++ b/Documentation/translations/zh_CN/index.rst
@@ -71,6 +71,7 @@ TODOList:
dev-tools/index
dev-tools/testing-overview
kernel-hacking/index
+ rust/index
TODOList:
@@ -90,12 +91,12 @@ TODOList:
admin-guide/index
admin-guide/reporting-issues.rst
+ userspace-api/index
TODOList:
* 内核构建系统 <kbuild/index>
* 用户空间工具 <tools/index>
-* userspace-api/index
也可参考独立于内核文档的 `Linux 手册页 <https://www.kernel.org/doc/man-pages/>`_ 。
@@ -124,13 +125,13 @@ TODOList:
其他文档
--------
-有几份未排序的文档似乎不适合放在文档的其他部分,或者可能需要进行一些调整和/或
+有几份未分类的文档似乎不适合放在文档的其他部分,或者可能需要进行一些调整和/或
转换为reStructureText格式,也有可能太旧。
-TODOList:
-
-* staging/index
+.. toctree::
+ :maxdepth: 2
+ staging/index
索引和表格
----------
diff --git a/Documentation/translations/zh_CN/loongarch/introduction.rst b/Documentation/translations/zh_CN/loongarch/introduction.rst
index f3ec25b163d7..470c38ae2caf 100644
--- a/Documentation/translations/zh_CN/loongarch/introduction.rst
+++ b/Documentation/translations/zh_CN/loongarch/introduction.rst
@@ -338,15 +338,15 @@ Loongson与LoongArch的开发者网站(软件与文档资源):
LoongArch指令集架构的文档:
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-CN.pdf (中文版)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-CN.pdf (中文版)
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-EN.pdf (英文版)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-EN.pdf (英文版)
LoongArch的ELF psABI文档:
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-CN.pdf (中文版)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-CN.pdf (中文版)
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-EN.pdf (英文版)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-EN.pdf (英文版)
Loongson与LoongArch的Linux内核源码仓库:
diff --git a/Documentation/translations/zh_CN/rust/arch-support.rst b/Documentation/translations/zh_CN/rust/arch-support.rst
new file mode 100644
index 000000000000..afbd02afec45
--- /dev/null
+++ b/Documentation/translations/zh_CN/rust/arch-support.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/rust/arch-support.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+架构支持
+========
+
+目前,Rust编译器(``rustc``)使用LLVM进行代码生成,这限制了可以支持的目标架构。此外,对
+使用LLVM/Clang构建内核的支持也有所不同(请参见 Documentation/kbuild/llvm.rst )。这
+种支持对于使用 ``libclang`` 的 ``bindgen`` 来说是必需的。
+
+下面是目前可以工作的架构的一般总结。支持程度与 ``MAINTAINERS`` 文件中的``S`` 值相对应:
+
+============ ================ ==============================================
+架构 支持水平 限制因素
+============ ================ ==============================================
+``x86`` Maintained 只有 ``x86_64``
+============ ================ ==============================================
diff --git a/Documentation/translations/zh_CN/rust/coding-guidelines.rst b/Documentation/translations/zh_CN/rust/coding-guidelines.rst
new file mode 100644
index 000000000000..6c0bdbbc5a2a
--- /dev/null
+++ b/Documentation/translations/zh_CN/rust/coding-guidelines.rst
@@ -0,0 +1,192 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/rust/coding-guidelines.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+编码指南
+========
+
+本文档描述了如何在内核中编写Rust代码。
+
+
+风格和格式化
+------------
+
+代码应该使用 ``rustfmt`` 进行格式化。这样一来,一个不时为内核做贡献的人就不需要再去学
+习和记忆一个样式指南了。更重要的是,审阅者和维护者不需要再花时间指出风格问题,这样就可以
+减少补丁落地所需的邮件往返。
+
+.. note:: ``rustfmt`` 不检查注释和文档的约定。因此,这些仍然需要照顾到。
+
+使用 ``rustfmt`` 的默认设置。这意味着遵循Rust的习惯性风格。例如,缩进时使用4个空格而
+不是制表符。
+
+在输入、保存或提交时告知编辑器/IDE进行格式化是很方便的。然而,如果因为某些原因需要在某
+个时候重新格式化整个内核Rust的源代码,可以运行以下程序::
+
+ make LLVM=1 rustfmt
+
+也可以检查所有的东西是否都是格式化的(否则就打印一个差异),例如对于一个CI,用::
+
+ make LLVM=1 rustfmtcheck
+
+像内核其他部分的 ``clang-format`` 一样, ``rustfmt`` 在单个文件上工作,并且不需要
+内核配置。有时,它甚至可以与破碎的代码一起工作。
+
+
+注释
+----
+
+“普通”注释(即以 ``//`` 开头,而不是 ``///`` 或 ``//!`` 开头的代码文档)的写法与文
+档注释相同,使用Markdown语法,尽管它们不会被渲染。这提高了一致性,简化了规则,并允许在
+这两种注释之间更容易地移动内容。比如说:
+
+.. code-block:: rust
+
+ // `object` is ready to be handled now.
+ f(object);
+
+此外,就像文档一样,注释在句子的开头要大写,并以句号结束(即使是单句)。这包括 ``// SAFETY:``,
+``// TODO:`` 和其他“标记”的注释,例如:
+
+.. code-block:: rust
+
+ // FIXME: The error should be handled properly.
+
+注释不应该被用于文档的目的:注释是为了实现细节,而不是为了用户。即使源文件的读者既是API
+的实现者又是用户,这种区分也是有用的。事实上,有时同时使用注释和文档是很有用的。例如,用
+于 ``TODO`` 列表或对文档本身的注释。对于后一种情况,注释可以插在中间;也就是说,离要注
+释的文档行更近。对于其他情况,注释会写在文档之后,例如:
+
+.. code-block:: rust
+
+ /// Returns a new [`Foo`].
+ ///
+ /// # Examples
+ ///
+ // TODO: Find a better example.
+ /// ```
+ /// let foo = f(42);
+ /// ```
+ // FIXME: Use fallible approach.
+ pub fn f(x: i32) -> Foo {
+ // ...
+ }
+
+一种特殊的注释是 ``// SAFETY:`` 注释。这些注释必须出现在每个 ``unsafe`` 块之前,它们
+解释了为什么该块内的代码是正确/健全的,即为什么它在任何情况下都不会触发未定义行为,例如:
+
+.. code-block:: rust
+
+ // SAFETY: `p` is valid by the safety requirements.
+ unsafe { *p = 0; }
+
+``// SAFETY:`` 注释不能与代码文档中的 ``# Safety`` 部分相混淆。 ``# Safety`` 部
+分指定了(函数)调用者或(特性)实现者需要遵守的契约。
+``// SAFETY:`` 注释显示了为什么一个(函数)调用者或(特性)实现者实际上尊重了
+``# Safety`` 部分或语言参考中的前提条件。
+
+
+代码文档
+--------
+
+Rust内核代码不像C内核代码那样被记录下来(即通过kernel-doc)。取而代之的是用于记录Rust
+代码的常用系统:rustdoc工具,它使用Markdown(一种轻量级的标记语言)。
+
+要学习Markdown,外面有很多指南。例如:
+
+https://commonmark.org/help/
+
+一个记录良好的Rust函数可能是这样的:
+
+.. code-block:: rust
+
+ /// Returns the contained [`Some`] value, consuming the `self` value,
+ /// without checking that the value is not [`None`].
+ ///
+ /// # Safety
+ ///
+ /// Calling this method on [`None`] is *[undefined behavior]*.
+ ///
+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let x = Some("air");
+ /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air");
+ /// ```
+ pub unsafe fn unwrap_unchecked(self) -> T {
+ match self {
+ Some(val) => val,
+
+ // SAFETY: The safety contract must be upheld by the caller.
+ None => unsafe { hint::unreachable_unchecked() },
+ }
+ }
+
+这个例子展示了一些 ``rustdoc`` 的特性和内核中遵循的一些惯例:
+
+ - 第一段必须是一个简单的句子,简要地描述被记录的项目的作用。进一步的解释必须放在额
+ 外的段落中。
+
+ - 不安全的函数必须在 ``# Safety`` 部分记录其安全前提条件。
+
+ - 虽然这里没有显示,但如果一个函数可能会恐慌,那么必须在 ``# Panics`` 部分描述发
+ 生这种情况的条件。
+
+ 请注意,恐慌应该是非常少见的,只有在有充分理由的情况下才会使用。几乎在所有的情况下,
+ 都应该使用一个可失败的方法,通常是返回一个 ``Result``。
+
+ - 如果提供使用实例对读者有帮助的话,必须写在一个叫做``# Examples``的部分。
+
+ - Rust项目(函数、类型、常量……)必须有适当的链接(``rustdoc`` 会自动创建一个
+ 链接)。
+
+ - 任何 ``unsafe`` 的代码块都必须在前面加上一个 ``// SAFETY:`` 的注释,描述里面
+ 的代码为什么是正确的。
+
+ 虽然有时原因可能看起来微不足道,但写这些注释不仅是记录已经考虑到的问题的好方法,
+ 最重要的是,它提供了一种知道没有额外隐含约束的方法。
+
+要了解更多关于如何编写Rust和拓展功能的文档,请看看 ``rustdoc`` 这本书,网址是:
+
+ https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html
+
+
+命名
+----
+
+Rust内核代码遵循通常的Rust命名空间:
+
+ https://rust-lang.github.io/api-guidelines/naming.html
+
+当现有的C语言概念(如宏、函数、对象......)被包装成Rust抽象时,应该使用尽可能接近C语
+言的名称,以避免混淆,并在C语言和Rust语言之间来回切换时提高可读性。例如,C语言中的
+``pr_info`` 这样的宏在Rust中的命名是一样的。
+
+说到这里,应该调整大小写以遵循Rust的命名惯例,模块和类型引入的命名间隔不应该在项目名称
+中重复。例如,在包装常量时,如:
+
+.. code-block:: c
+
+ #define GPIO_LINE_DIRECTION_IN 0
+ #define GPIO_LINE_DIRECTION_OUT 1
+
+在Rust中的等价物可能是这样的(忽略文档)。:
+
+.. code-block:: rust
+
+ pub mod gpio {
+ pub enum LineDirection {
+ In = bindings::GPIO_LINE_DIRECTION_IN as _,
+ Out = bindings::GPIO_LINE_DIRECTION_OUT as _,
+ }
+ }
+
+也就是说, ``GPIO_LINE_DIRECTION_IN`` 的等价物将被称为 ``gpio::LineDirection::In`` 。
+特别是,它不应该被命名为 ``gpio::gpio_line_direction::GPIO_LINE_DIRECTION_IN`` 。
diff --git a/Documentation/translations/zh_CN/rust/general-information.rst b/Documentation/translations/zh_CN/rust/general-information.rst
new file mode 100644
index 000000000000..6b91dfe1834a
--- /dev/null
+++ b/Documentation/translations/zh_CN/rust/general-information.rst
@@ -0,0 +1,75 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/rust/general-information.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+
+基本信息
+========
+
+本文档包含了在内核中使用Rust支持时需要了解的有用信息。
+
+
+代码文档
+--------
+
+Rust内核代码使用其内置的文档生成器 ``rustdoc`` 进行记录。
+
+生成的HTML文档包括集成搜索、链接项(如类型、函数、常量)、源代码等。它们可以在以下地址阅读
+(TODO:当在主线中时链接,与其他文档一起生成):
+
+ http://kernel.org/
+
+这些文档也可以很容易地在本地生成和阅读。这相当快(与编译代码本身的顺序相同),而且不需要特
+殊的工具或环境。这有一个额外的好处,那就是它们将根据所使用的特定内核配置进行定制。要生成它
+们,请使用 ``rustdoc`` 目标,并使用编译时使用的相同调用,例如::
+
+ make LLVM=1 rustdoc
+
+要在你的网络浏览器中本地阅读该文档,请运行如::
+
+ xdg-open rust/doc/kernel/index.html
+
+要了解如何编写文档,请看 coding-guidelines.rst 。
+
+
+额外的lints
+-----------
+
+虽然 ``rustc`` 是一个非常有用的编译器,但一些额外的lints和分析可以通过 ``clippy``
+(一个Rust linter)来实现。要启用它,请将CLIPPY=1传递到用于编译的同一调用中,例如::
+
+ make LLVM=1 CLIPPY=1
+
+请注意,Clippy可能会改变代码生成,因此在构建产品内核时不应该启用它。
+
+抽象和绑定
+----------
+
+抽象是用Rust代码包装来自C端的内核功能。
+
+为了使用来自C端的函数和类型,需要创建绑定。绑定是Rust对那些来自C端的函数和类型的声明。
+
+例如,人们可以在Rust中写一个 ``Mutex`` 抽象,它从C端包装一个 ``Mutex结构体`` ,并
+通过绑定调用其函数。
+
+抽象并不能用于所有的内核内部API和概念,但随着时间的推移,我们打算扩大覆盖范围。“Leaf”
+模块(例如,驱动程序)不应该直接使用C语言的绑定。相反,子系统应该根据需要提供尽可能安
+全的抽象。
+
+
+有条件的编译
+------------
+
+Rust代码可以访问基于内核配置的条件性编译:
+
+.. code-block:: rust
+
+ #[cfg(CONFIG_X)] // Enabled (`y` or `m`)
+ #[cfg(CONFIG_X="y")] // Enabled as a built-in (`y`)
+ #[cfg(CONFIG_X="m")] // Enabled as a module (`m`)
+ #[cfg(not(CONFIG_X))] // Disabled
diff --git a/Documentation/translations/zh_CN/rust/index.rst b/Documentation/translations/zh_CN/rust/index.rst
new file mode 100644
index 000000000000..b01f887e7167
--- /dev/null
+++ b/Documentation/translations/zh_CN/rust/index.rst
@@ -0,0 +1,28 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/rust/index.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+Rust
+====
+
+与内核中的Rust有关的文档。若要开始在内核中使用Rust,请阅读quick-start.rst指南。
+
+.. toctree::
+ :maxdepth: 1
+
+ quick-start
+ general-information
+ coding-guidelines
+ arch-support
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/translations/zh_CN/rust/quick-start.rst b/Documentation/translations/zh_CN/rust/quick-start.rst
new file mode 100644
index 000000000000..a4b8e8a50a89
--- /dev/null
+++ b/Documentation/translations/zh_CN/rust/quick-start.rst
@@ -0,0 +1,211 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/rust/quick-start.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+
+快速入门
+========
+
+本文介绍了如何开始使用Rust进行内核开发。
+
+
+构建依赖
+--------
+
+本节描述了如何获取构建所需的工具。
+
+其中一些依赖也许可以从Linux发行版中获得,包名可能是 ``rustc`` , ``rust-src`` ,
+``rust-bindgen`` 等。然而,在写这篇文章的时候,它们很可能还不够新,除非发行版跟踪最
+新的版本。
+
+为了方便检查是否满足要求,可以使用以下目标::
+
+ make LLVM=1 rustavailable
+
+这会触发与Kconfig用来确定是否应该启用 ``RUST_IS_AVAILABLE`` 相同的逻辑;不过,如
+果Kconfig认为不该启用,它会列出未满足的条件。
+
+
+rustc
+*****
+
+需要一个特定版本的Rust编译器。较新的版本可能会也可能不会工作,因为就目前而言,内核依赖
+于一些不稳定的Rust特性。
+
+如果使用的是 ``rustup`` ,请进入检出的源代码目录并运行::
+
+ rustup override set $(scripts/min-tool-version.sh rustc)
+
+或者从以下网址获取一个独立的安装程序或安装 ``rustup`` :
+
+ https://www.rust-lang.org
+
+
+Rust标准库源代码
+****************
+
+Rust标准库的源代码是必需的,因为构建系统会交叉编译 ``core`` 和 ``alloc`` 。
+
+如果正在使用 ``rustup`` ,请运行::
+
+ rustup component add rust-src
+
+这些组件是按工具链安装的,因此以后升级Rust编译器版本需要重新添加组件。
+
+否则,如果使用独立的安装程序,可以将Rust仓库克隆到工具链的安装文件夹中::
+
+ git clone --recurse-submodules \
+ --branch $(scripts/min-tool-version.sh rustc) \
+ https://github.com/rust-lang/rust \
+ $(rustc --print sysroot)/lib/rustlib/src/rust
+
+在这种情况下,以后升级Rust编译器版本需要手动更新这个克隆的仓库。
+
+
+libclang
+********
+
+``bindgen`` 使用 ``libclang`` (LLVM的一部分)来理解内核中的C代码,这意味着需要安
+装LLVM;同在开启 ``CC=clang`` 或 ``LLVM=1`` 时编译内核一样。
+
+Linux发行版中可能会有合适的包,所以最好先检查一下。
+
+适用于部分系统和架构的二进制文件也可到以下网址下载:
+
+ https://releases.llvm.org/download.html
+
+或者自行构建LLVM,这需要相当长的时间,但并不是一个复杂的过程:
+
+ https://llvm.org/docs/GettingStarted.html#getting-the-source-code-and-building-llvm
+
+请参阅 Documentation/kbuild/llvm.rst 了解更多信息,以及获取预构建版本和发行包
+的进一步方法。
+
+
+bindgen
+*******
+
+内核的C端绑定是在构建时使用 ``bindgen`` 工具生成的。这需要特定的版本。
+
+通过以下方式安装它(注意,这将从源码下载并构建该工具)::
+
+ cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen
+
+
+开发依赖
+--------
+
+本节解释了如何获取开发所需的工具。也就是说,在构建内核时不需要这些工具。
+
+
+rustfmt
+*******
+
+``rustfmt`` 工具被用来自动格式化所有的Rust内核代码,包括生成的C绑定(详情请见
+coding-guidelines.rst )。
+
+如果使用的是 ``rustup`` ,它的 ``默认`` 配置文件已经安装了这个工具,因此不需要做什么。
+如果使用的是其他配置文件,可以手动安装该组件::
+
+ rustup component add rustfmt
+
+独立的安装程序也带有 ``rustfmt`` 。
+
+
+clippy
+******
+
+``clippy`` 是一个Rust linter。运行它可以为Rust代码提供额外的警告。它可以通过向 ``make``
+传递 ``CLIPPY=1`` 来运行(关于细节,详见 general-information.rst )。
+
+如果正在使用 ``rustup`` ,它的 ``默认`` 配置文件已经安装了这个工具,因此不需要做什么。
+如果使用的是另一个配置文件,该组件可以被手动安装::
+
+ rustup component add clippy
+
+独立的安装程序也带有 ``clippy`` 。
+
+
+cargo
+*****
+
+``cargo`` 是Rust的本地构建系统。目前需要它来运行测试,因为它被用来构建一个自定义的标准
+库,其中包含了内核中自定义 ``alloc`` 所提供的设施。测试可以使用 ``rusttest`` Make 目标
+来运行。
+
+如果使用的是 ``rustup`` ,所有的配置文件都已经安装了该工具,因此不需要再做什么。
+
+独立的安装程序也带有 ``cargo`` 。
+
+
+rustdoc
+*******
+
+``rustdoc`` 是Rust的文档工具。它为Rust代码生成漂亮的HTML文档(详情请见 general-information.rst )。
+
+``rustdoc`` 也被用来测试文档化的Rust代码中提供的例子(称为doctests或文档测试)。
+``rusttest`` 是本功能的Make目标。
+
+如果使用的是 ``rustup`` ,所有的配置文件都已经安装了这个工具,因此不需要做什么。
+
+独立的安装程序也带有 ``rustdoc`` 。
+
+
+rust-analyzer
+*************
+
+`rust-analyzer <https://rust-analyzer.github.io/>`_ 语言服务器可以和许多编辑器
+一起使用,以实现语法高亮、补全、转到定义和其他功能。
+
+``rust-analyzer`` 需要一个配置文件, ``rust-project.json``, 它可以由 ``rust-analyzer``
+Make 目标生成。
+
+
+配置
+----
+
+Rust支持(CONFIG_RUST)需要在 ``General setup`` 菜单中启用。在其他要求得到满足的情
+况下,该选项只有在找到合适的Rust工具链时才会显示(见上文)。相应的,这将使依赖Rust的其
+他选项可见。
+
+之后,进入::
+
+ Kernel hacking
+ -> Sample kernel code
+ -> Rust samples
+
+并启用一些内置或可加载的样例模块。
+
+
+构建
+----
+
+用完整的LLVM工具链构建内核是目前支持的最佳设置。即::
+
+ make LLVM=1
+
+对于不支持完整LLVM工具链的架构,使用::
+
+ make CC=clang
+
+使用GCC对某些配置也是可行的,但目前它是非常试验性的。
+
+
+折腾
+----
+
+要想深入了解,请看 ``samples/rust/`` 下的样例源代码、 ``rust/`` 下的Rust支持代码和
+``Kernel hacking`` 下的 ``Rust hacking`` 菜单。
+
+如果使用的是GDB/Binutils,而Rust符号没有被demangled,原因是工具链还不支持Rust的新v0
+mangling方案。有几个办法可以解决:
+
+ - 安装一个较新的版本(GDB >= 10.2, Binutils >= 2.36)。
+
+ - 一些版本的GDB(例如vanilla GDB 10.1)能够使用嵌入在调试信息(``CONFIG_DEBUG_INFO``)
+ 中的pre-demangled的名字。
diff --git a/Documentation/translations/zh_CN/staging/index.rst b/Documentation/translations/zh_CN/staging/index.rst
new file mode 100644
index 000000000000..bb55c81c84a3
--- /dev/null
+++ b/Documentation/translations/zh_CN/staging/index.rst
@@ -0,0 +1,26 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/staging/index.rst
+
+:翻译:
+
+ 李睿 Rui Li <me@lirui.org>
+
+未分类文档
+==========
+
+.. toctree::
+ :maxdepth: 2
+
+ xz
+
+TODOList:
+
+* crc32
+* lzo
+* remoteproc
+* rpmsg
+* speculation
+* static-keys
+* tee
diff --git a/Documentation/translations/zh_CN/staging/xz.rst b/Documentation/translations/zh_CN/staging/xz.rst
new file mode 100644
index 000000000000..211c487bcb62
--- /dev/null
+++ b/Documentation/translations/zh_CN/staging/xz.rst
@@ -0,0 +1,100 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/staging/xz.rst
+
+:翻译:
+
+ 李睿 Rui Li <me@lirui.org>
+
+===================
+Linux中的XZ数据压缩
+===================
+
+介绍
+====
+
+XZ是一种通用的数据压缩格式,其具有高压缩率和相对快的解压速度。主要的压缩算法(
+过滤器)是LZMA2。额外的过滤器可以被用来进一步提高压缩率,比如用来提高可执行数据
+压缩率的Branch/Call/Jump (BCJ)过滤器。
+
+XZ解压器在Linux中被称作XZ Embedded。它支持LZMA2过滤器和可选的BCJ过滤器,并支持
+CRC32完整性校验。你可以在XZ Embedded的主页<https://tukaani.org/xz/embedded.html>
+中找到最新版本和关于在Linux内核之外使用源码的信息。
+
+对于用户空间来说,XZ Utils提供了类似于zlib的压缩库和类似于gzip的命令行工具。
+XZ Utils可以从<https://tukaani.org/xz/>下载。
+
+内核中的XZ相关组件
+==================
+
+xz_dec模块为XZ解压器提供了单次调用(缓冲区到缓冲区)和多次调用(有状态)的
+API。xz_dec模块的用法记录在include/linux/xz.h中。
+
+xz_dec_test模块用于测试xz_dec。除非你想魔改XZ解压器,否则xz_dec_test是
+没有用的。xz_dec_test会动态分配一个字符设备主设备号,你可以从用户空间向它
+写入.xz文件,解压的输出会被丢弃。关注dmesg可以找到xz_dec_test输出的诊断信息。
+详细内容请查看xz_dec_test的源码。
+
+为了解压内核镜像、初始ram文件系统和初始ram磁盘,lib/decompress_unxz.c实现
+了一个包装函数。它的API与其他 decompress_*.c 文件相同,那些API定义在
+include/linux/decompress/generic.h中。
+
+scripts/xz_wrap.sh是一个XZ Utils中的xz命令行工具包装器。这个包装器会
+设置合适的压缩选项来压缩内核镜像。
+
+在内核的makefiles中,提供了使用$(call if_needed)的两个命令。内核镜像应该
+使用$(call if_needed,xzkern)来压缩,它会使用BCJ过滤器和一个大LZMA2字典。
+它还会附加一个四字节的包含源文件大小的预告,这会在启动代码中被用到。其他文件
+应该使用$(call if_needed,xzmisc)来压缩,它会使用1 MiB的LZMA2字典并禁用
+BCJ过滤器。
+
+关于压缩选项的说明
+==================
+
+因为XZ Embedded只支持没有完整性校验的数据流或者CRC32,请确保你在编码未来将被
+内核解码的文件时没有使用其他完整性校验方式。使用liblzma时,你需要使用LZMA_CHECK_NONE
+或LZMA_CHECK_CRC32。使用xz命令行工具时,使用--check=none或--check=crc32。
+
+除非有其他环节会验证解压数据的完整性,否则强烈使用CRC32。双重验证可能会浪费
+CPU周期。请注意头部总是会包含用于解压器验证的CRC32,你只能修改或禁用解压后数据
+的完整性校验方式。
+
+在用户中间中,LZMA2通常使用几兆字节大小的字典。解码器需要在RAM中放置字典,
+因此大字典不能被用于那些意在被内核解码的文件。1 MiB在内核中大概是可接受的最大
+字典大小(可能对初始ram文件系统也适用)。XZ Utils中的预设值可能并不适合创建
+内核文件,所以请别犹豫使用自定义设置。比如::
+
+ xz --check=crc32 --lzma2=dict=512KiB inputfile
+
+使用上面字典大小的一个例外是在单一调用模式下使用解码器。解压内核自身就是一个例
+子。在单一调用模式下,内存用量并不和字典大小有关,这种情况就是使用大字典的好地
+方:为了最大化压缩,字典至少应该和解压后的数据一样大。
+
+未来计划
+========
+
+如果有人认为有用的话,可能会考虑创建一个受限的XZ编码器。LZMA2的压缩速率比Deflate
+或LZO等要慢,即使在最快的配置选项下。所以并不清楚LZMA2编码器是否需要并入内核。
+
+有计划在解压代码中支持有限的随机访问读数据。不知道这能否在内核中有任何用,但是我
+知道这会在一些Linux内核以外的嵌入式项目中有用。
+
+.xz文件格式规范的一致性
+=======================
+
+在一些边缘情况下,为了简化事情牺牲了尽早地检测错误。因为并不会导致安全问题,实际
+上是没有关系的。但在测试代码的时候知道这一点很好,比如测试来自XZ Utils的文件。
+
+报告错误
+========
+
+请在报告错误前确认是否已经在上游修复。可以从<https://tukaani.org/xz/embedded.html>
+获取最新的源码。
+
+可以通过联系<lasse.collin@tukaani.org>或者访问Freenode上的#tukaani
+联系Larhzu。我并不经常阅读LKML或者其他内核相关的邮件列表,所以如果要告知我什么事情
+,你应该通过我的私人邮箱或者IRC联系我。
+
+请不要因为内核中XZ的实现或关于XZ Utils的问题打扰Igor Pavlov。虽然这两种实现
+包含了建立在Igor Pavlov的代码上的重要源码,但并不由他维护和提供支持。
diff --git a/Documentation/translations/zh_CN/userspace-api/accelerators/ocxl.rst b/Documentation/translations/zh_CN/userspace-api/accelerators/ocxl.rst
new file mode 100644
index 000000000000..845b932bf935
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/accelerators/ocxl.rst
@@ -0,0 +1,168 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/accelerators/ocxl.rst
+
+:翻译:
+
+ 李睿 Rui Li <me@lirui.org>
+
+=====================================
+OpenCAPI (开放相干加速器处理器接口)
+=====================================
+
+*OpenCAPI: Open Coherent Accelerator Processor Interface*
+
+OpenCAPI是处理器和加速器之间的一个接口,致力于达到低延迟和高带宽。该规范
+由 `OpenCAPI Consortium <http://opencapi.org/>`_ 开发。
+
+它允许加速器(可以是FPGA、ASIC等)使用虚拟地址连贯地访问主机内存。一个OpenCAPI
+设备也可以托管它自己的内存,并可以由主机访问。
+
+OpenCAPI在Linux中称为“ocxl”,它作为“cxl”(用于powerpc的IBM CAPI接口的驱动)的
+开放、处理器无关的演进,这么命名是为了避免与ISDN CAPI子系统相混淆。
+
+
+高层视角
+========
+
+OpenCAPI定义了一个在物理链路层上实现的数据链路层(TL)和传输层(TL)。任何
+实现DL和TL的处理器或者设备都可以开始共享内存。
+
+::
+
+ +-----------+ +-------------+
+ | | | |
+ | | | Accelerated |
+ | Processor | | Function |
+ | | +--------+ | Unit | +--------+
+ | |--| Memory | | (AFU) |--| Memory |
+ | | +--------+ | | +--------+
+ +-----------+ +-------------+
+ | |
+ +-----------+ +-------------+
+ | TL | | TLX |
+ +-----------+ +-------------+
+ | |
+ +-----------+ +-------------+
+ | DL | | DLX |
+ +-----------+ +-------------+
+ | |
+ | PHY |
+ +---------------------------------------+
+
+ Processor:处理器
+ Memory:内存
+ Accelerated Function Unit:加速函数单元
+
+
+
+设备发现
+========
+
+OpenCAPI依赖一个在设备上实现的与PCI类似的配置空间。因此主机可以通过查询
+配置空间来发现AFU。
+
+OpenCAPI设备在Linux中被当作类PCI设备(有一些注意事项)。固件需要对硬件进行
+抽象,就好像它是一个PCI链路。许多已有的PCI架构被重用:在模拟标准PCI时,
+设备被扫描并且BAR(基址寄存器)被分配。像“lspci”的命令因此可以被用于查看
+哪些设备可用。
+
+配置空间定义了可以在物理适配器上可以被找到的AFU,比如它的名字、支持多少内
+存上下文、内存映射IO(MMIO)区域的大小等。
+
+
+
+MMIO
+====
+
+OpenCAPI为每个AFU定义了两个MMIO区域:
+
+* 全局MMIO区域,保存和整个AFU相关的寄存器。
+* 每个进程的MMIO区域,对于每个上下文固定大小。
+
+
+
+AFU中断
+=======
+
+OpenCAPI拥有AFU向主机进程发送中断的可能性。它通过定义在传输层的“intrp_req”
+来完成,指定一个定义中断的64位对象句柄。
+
+驱动允许一个进程分配中断并获取可以传递给AFU的64位对象句柄。
+
+
+
+字符设备
+========
+
+驱动为每个在物理设备上发现的AFU创建一个字符设备。一个物理设备可能拥有多个
+函数,一个函数可以拥有多个AFU。不过编写这篇文档之时,只对导出一个AFU的设备
+测试过。
+
+字符设备可以在 /dev/ocxl/ 中被找到,其命名为:
+/dev/ocxl/<AFU 名称>.<位置>.<索引>
+
+<AFU 名称> 是一个最长20个字符的名称,和在AFU配置空间中找到的相同。
+<位置>由驱动添加,可在系统有不止一个相同的OpenCAPI设备时帮助区分设备。
+<索引>也是为了在少见情况下帮助区分AFU,即设备携带多个同样的AFU副本时。
+
+
+
+Sysfs类
+=======
+
+添加了代表AFU的ocxl类。查看/sys/class/ocxl。布局在
+Documentation/ABI/testing/sysfs-class-ocxl 中描述。
+
+
+
+用户API
+=======
+
+打开
+----
+
+基于在配置空间中找到的AFU定义,AFU可能支持在多个内存上下文中工作,这种情况
+下相关的字符设备可以被不同进程多次打开。
+
+
+ioctl
+-----
+
+OCXL_IOCTL_ATTACH:
+
+ 附加调用进程的内存上下文到AFU,以允许AFU访问其内存。
+
+OCXL_IOCTL_IRQ_ALLOC:
+
+ 分配AFU中断,返回标识符。
+
+OCXL_IOCTL_IRQ_FREE:
+
+ 释放之前分配的AFU中断。
+
+OCXL_IOCTL_IRQ_SET_FD:
+
+ 将一个事件文件描述符和AFU中断关联,因此用户进程可以在AFU发送中断时收到通
+ 知。
+
+OCXL_IOCTL_GET_METADATA:
+
+ 从卡中获取配置信息,比如内存映射IO区域的大小、AFU版本和当前上下文的进程
+ 地址空间ID(PASID)。
+
+OCXL_IOCTL_ENABLE_P9_WAIT:
+
+ 允许AFU唤醒执行“等待”的用户空间进程。返回信息给用户空间,允许其配置AFU。
+ 注意这只在POWER9上可用。
+
+OCXL_IOCTL_GET_FEATURES:
+
+ 报告用户空间可用的影响OpenCAPI的CPU特性。
+
+
+mmap
+----
+
+一个进程可以mmap每个进程的MMIO区域来和AFU交互。
diff --git a/Documentation/translations/zh_CN/userspace-api/ebpf/index.rst b/Documentation/translations/zh_CN/userspace-api/ebpf/index.rst
new file mode 100644
index 000000000000..d52c7052f101
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/ebpf/index.rst
@@ -0,0 +1,22 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/ebpf/index.rst
+
+:翻译:
+
+ 李睿 Rui Li <me@lirui.org>
+
+eBPF 用户空间API
+================
+
+eBPF是一种在Linux内核中提供沙箱化运行环境的机制,它可以在不改变内核源码或加载
+内核模块的情况下扩展运行时和编写工具。eBPF程序能够被附加到各种内核子系统中,包
+括网络,跟踪和Linux安全模块(LSM)等。
+
+关于eBPF的内部内核文档,请查看 Documentation/bpf/index.rst 。
+
+.. toctree::
+ :maxdepth: 1
+
+ syscall
diff --git a/Documentation/translations/zh_CN/userspace-api/ebpf/syscall.rst b/Documentation/translations/zh_CN/userspace-api/ebpf/syscall.rst
new file mode 100644
index 000000000000..47e2a59ae45d
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/ebpf/syscall.rst
@@ -0,0 +1,29 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/ebpf/syscall.rst
+
+:翻译:
+
+ 李睿 Rui Li <me@lirui.org>
+
+eBPF Syscall
+------------
+
+:作者:
+ - Alexei Starovoitov <ast@kernel.org>
+ - Joe Stringer <joe@wand.net.nz>
+ - Michael Kerrisk <mtk.manpages@gmail.com>
+
+bpf syscall的主要信息可以在 `man-pages`_ 中的 `bpf(2)`_ 找到。
+
+bpf() 子命令参考
+~~~~~~~~~~~~~~~~
+
+子命令在以下内核代码中:
+
+include/uapi/linux/bpf.h
+
+.. Links:
+.. _man-pages: https://www.kernel.org/doc/man-pages/
+.. _bpf(2): https://man7.org/linux/man-pages/man2/bpf.2.html
diff --git a/Documentation/translations/zh_CN/userspace-api/futex2.rst b/Documentation/translations/zh_CN/userspace-api/futex2.rst
new file mode 100644
index 000000000000..04f9d62db1f7
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/futex2.rst
@@ -0,0 +1,80 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/futex2.rst
+
+:翻译:
+
+ 李睿 Rui Li <me@lirui.org>
+
+======
+futex2
+======
+
+:作者: André Almeida <andrealmeid@collabora.com>
+
+futex,或者称为快速用户互斥锁(fast user mutex),是一组允许用户空间创建高性能同步
+机制的系统调用,比如用户空间中的互斥锁,信号量和条件变量。C标准库,如glibc,使用它作
+为实现更多高级接口的方式,如pthreads。
+
+futex2是初代futex系统调用的后续版本,旨在克服原有接口的限制。
+
+用户API
+=======
+
+``futex_waitv()``
+-----------------
+
+等待一个futex数组,可由其中任意一个唤醒::
+
+ futex_waitv(struct futex_waitv *waiters, unsigned int nr_futexes,
+ unsigned int flags, struct timespec *timeout, clockid_t clockid)
+
+ struct futex_waitv {
+ __u64 val;
+ __u64 uaddr;
+ __u32 flags;
+ __u32 __reserved;
+ };
+
+用户空间设置一个struct futex_waitv数组(最多128项),设置 ``uaddr`` 为等待的
+地址, ``val`` 为期望值, ``flags`` 为指定的类型(如private)和futex的大小。
+``__reserved`` 需要置为0,但是它可用作未来扩展。指向数组第一个元素的指针作为
+``waiters`` 传递。如果 ``waiters`` 或任何的 ``uaddr`` 地址无效,将返回 ``-EFAULT`` 。
+
+如果用户空间拥有32位的指针,那么需要做显式转换来保证高位清零。 ``uintptr_t`` 设计
+得很精巧,在32/64位的指针上都正常工作。
+
+``nr_futexes`` 指定了数组的大小。不在[1,128]区间内的值会使系统调用返回 ``-EINVAL`` 。
+
+系统调用的 ``flags`` 参数需要置0,但可用作未来扩展。
+
+对于每个 ``waiters`` 数组中的项,在 ``uaddr`` 的当前值会和 ``val`` 比较。如果
+不一致,系统调用会撤销截至目前完成的所有工作,并返回 ``-EAGAIN`` 。如果所有测试
+和验证都通过,系统调用会等待直到以下情况之一发生:
+
+- 指定的timeout超时,返回 ``-ETIMEOUT`` 。
+- 一个信号被传递给睡眠中的任务,返回 ``-ERESTARTSYS`` 。
+- 某个列表中的futex被唤醒,返回那个被唤醒的futex的索引。
+
+关于如何使用接口的例子可以在 ``tools/testing/selftests/futex/functional/futex_waitv.c``
+中找到。
+
+超时
+----
+
+``struct timespec *timeout`` 是一个指向绝对超时时间的可选参数。你需要在 ``clockid``
+参数中指定要使用的时钟类型。支持 ``CLOCK_MONOTONIC`` 和 ``CLOCK_REALTIME`` 。这个
+系统调用只接受64位的timespec结构体。
+
+futex的类型
+-----------
+
+futex既可以是私有的也可以是共享的。私有用于多个进程共享同样的内存空间,并且futex的虚拟
+地址对所有进程都是一样的。这允许在内核中进行优化。要使用私有futex,需要在futex标志中指定
+``FUTEX_PRIVATE_FLAG`` 。对于那些不在同一内存空间共享的进程,可以让同一个futex拥有不同
+的虚拟地址(例如使用基于文件的共享内存),这需要不同的内部机制来使得正确进入队列。这是默认
+的行为,而且对私有futex和共享futex都适用。
+
+futex可以是不同的大小:8,16,32或64位。目前只支持32位大小的futex,并且需要通过 ``FUTEX_32``
+标志指定。
diff --git a/Documentation/translations/zh_CN/userspace-api/index.rst b/Documentation/translations/zh_CN/userspace-api/index.rst
new file mode 100644
index 000000000000..5dc0f2e69c17
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/index.rst
@@ -0,0 +1,50 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/index.rst
+
+:翻译:
+
+ 李睿 Rui Li <me@lirui.org>
+
+=========================
+Linux 内核用户空间API指南
+=========================
+
+.. _man-pages: https://www.kernel.org/doc/man-pages/
+
+尽管许多用户空间API的文档被记录在别处(特别是在 man-pages_ 项目中),
+在代码树中仍然可以找到有关用户空间的部分信息。这个手册意在成为这些信息
+聚集的地方。
+
+.. class:: toc-title
+
+ 目录
+
+.. toctree::
+ :maxdepth: 2
+
+ no_new_privs
+ seccomp_filter
+ accelerators/ocxl
+ ebpf/index
+ sysfs-platform_profile
+ futex2
+
+TODOList:
+
+* landlock
+* unshare
+* spec_ctrl
+* ioctl/index
+* iommu
+* media/index
+* netlink/index
+* vduse
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/translations/zh_CN/userspace-api/no_new_privs.rst b/Documentation/translations/zh_CN/userspace-api/no_new_privs.rst
new file mode 100644
index 000000000000..81bd16ce3ad2
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/no_new_privs.rst
@@ -0,0 +1,57 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/no_new_privs.rst
+
+:翻译:
+
+ 李睿 Rui Li <me@lirui.org>
+
+============
+无新权限标志
+============
+
+execve系统调用可以给一个新启动的程序授予它的父程序本没有的权限。最明显的两个
+例子就是setuid/setgid控制程序和文件的能力。为了避免父程序也获得这些权限,内
+核和用户代码必须小心避免任何父程序可以颠覆子程序的情况。比如:
+
+ - 程序在setuid后,动态装载器处理 ``LD_*`` 环境变量的不同方式。
+
+ - 对于非特权程序,chroot是不允许的,因为这会允许 ``/etc/passwd`` 在继承
+ chroot的程序眼中被替换。
+
+ - 执行代码对ptrace有特殊处理。
+
+这些都是临时性的修复。 ``no_new_privs`` 位(从 Linux 3.5 起)是一个新的通
+用的机制来保证一个进程安全地修改其执行环境并跨execve持久化。任何任务都可以设
+置 ``no_new_privs`` 。一旦该位被设置,它会在fork、clone和execve中继承下去
+,并且不能被撤销。在 ``no_new_privs`` 被设置的情况下, ``execve()`` 将保证
+不会授予权限去做任何没有execve调用就不能做的事情。比如, setuid 和 setgid
+位不会再改变 uid 或 gid;文件能力不会被添加到授权集合中,并且Linux安全模块(
+LSM)不会在execve调用后放松限制。
+
+设置 ``no_new_privs`` 使用::
+
+ prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+
+不过要小心,Linux安全模块(LSM)也可能不会在 ``no_new_privs`` 模式下收紧约束。
+(这意味着一个一般的服务启动器在执行守护进程前就去设置 ``no_new_privs`` 可能
+会干扰基于LSM的沙箱。)
+
+请注意, ``no_new_privs`` 并不能阻止不涉及 ``execve()`` 的权限变化。一个拥有
+适当权限的任务仍然可以调用 ``setuid(2)`` 并接收 SCM_RIGHTS 数据报。
+
+目前来说, ``no_new_privs`` 有两大使用场景:
+
+ - 为seccomp模式2沙箱安装的过滤器会跨execve持久化,并能够改变新执行程序的行为。
+ 非特权用户因此在 ``no_new_privs`` 被设置的情况下只允许安装这样的过滤器。
+
+ - ``no_new_privs`` 本身就能被用于减少非特权用户的攻击面。如果所有以某个 uid
+ 运行的程序都设置了 ``no_new_privs`` ,那么那个 uid 将无法通过攻击 setuid,
+ setgid 和使用文件能力的二进制来提权;它需要先攻击一些没有被设置 ``no_new_privs``
+ 位的东西。
+
+将来,其他潜在的危险的内核特性可能被非特权任务利用,即使 ``no_new_privs`` 被置位。
+原则上,当 ``no_new_privs`` 被置位时, ``unshare(2)`` 和 ``clone(2)`` 的几个选
+项将是安全的,并且 ``no_new_privs`` 加上 ``chroot`` 是可以被认为比 chroot本身危
+险性小得多的。
diff --git a/Documentation/translations/zh_CN/userspace-api/seccomp_filter.rst b/Documentation/translations/zh_CN/userspace-api/seccomp_filter.rst
new file mode 100644
index 000000000000..ede8b37c953f
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/seccomp_filter.rst
@@ -0,0 +1,293 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/seccomp_filter.rst
+
+:翻译:
+
+ 李睿 Rui Li <me@lirui.org>
+
+==================================
+Seccomp BPF (基于过滤器的安全计算)
+==================================
+
+*Seccomp: SECure COMPuting*
+
+介绍
+====
+
+大量系统调用被暴露给每个用户空间进程,但其中又有许多系统调用在进程的整个生命
+周期中都没被使用。随着系统调用的改变和成熟,缺陷被找到并消除。允许某一部分应
+用程序仅能访问一部分系统调用是有好处的,这会缩小内核暴露给应用程序的面积。
+系统调用过滤器就是为这些应用程序而生的。
+
+Seccomp过滤提供了一种为进程指定一个处理系统调用的过滤器的方法。这个过滤器体
+现为一个伯克利包过滤器(BPF)程序,就像套接字过滤器一样,不同在于前者处理的
+数据和正在进行的系统调用有关:系统调用号和系统调用参数。这样使用一种长期与
+用户空间和直接数据打交道的语言来表达系统调用过滤成为了可能。
+
+此外,BPF让seccomp用户不再成为在系统调用干预框架(system call interposition
+frameworks)中常见的检查-使用竞态攻击(TOCTOU)的受害者。BPF程序可能无法解引
+用指针,这就限制了所有过滤器仅能直接评估系统调用参数。
+
+这不是什么
+==========
+
+系统调用过滤并不是一个沙箱。它提供了一种明确定义的机制来最小化内核暴露面。它
+旨在成为一个沙箱开发者使用的工具。除此之外,逻辑行为和信息流的策略应该结合其他
+系统加固手段或者可能由你选择的内核安全模块(LSM)来管理。易于表达的动态过滤器
+为这条路提供了更多选择(比如避免病态的大小或者选择允许 socketcall() 中的多路
+系统调用),但将其理解为更完整的沙箱解决方案是错误的。
+
+用法
+====
+
+添加了一个额外的seccomp模式,它可以使用和严格seccomp相同的 prctl(2) 调用来启用。
+如果架构有 ``CONFIG_HAVE_ARCH_SECCOMP_FILTER`` 标志,那么可以添加以下过滤器:
+
+``PR_SET_SECCOMP``:
+ 现在需要添加一个额外的参数来指定使用BPF程序的新过滤器。
+ BPF程序将在反应系统调用号、参数和其他元数据的seccomp_data结构体之上执行。
+ BPF程序必须返回允许的值之一来告知内核应该采取什么行动。
+
+ 用法::
+
+ prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog);
+
+ 'prog' 参数是一个指向 sock_fprog 结构体的指针,其中包含了过滤器程序。如
+ 果程序是无效的,该调用会返回 -1 并设置 errno 为 ``EINVAL`` 。
+
+ 如果 ``fork`` / ``clone`` 和 ``execve`` 被 @prog 所允许,任何子进程都将
+ 受到和父进程相同的过滤器和系统调用ABI的约束。
+
+ 在调用之前,进程必须调用 ``prctl(PR_SET_NO_NEW_PRIVS, 1)`` 或者在它的
+ 命名空间内以 ``CAP_SYS_ADMIN`` 权限运行。如果以上条件不满足,会返回
+ ``-EACCES`` 。这一要求保证了过滤器程序不能用于比安装过滤器的进程拥有更高
+ 权限的子进程。
+
+ 另外,如果 ``prctl(2)`` 被安装的过滤器所允许,就可以叠加额外的过滤器。这会增
+ 加评估时间,但是可以进一步降低执行进程时的攻击面。
+
+以上调用在成功时返回0,失败时返回一个非零的值。
+
+返回值
+======
+
+一个seccomp过滤器可能返回下列任意值。如果多个过滤器存在,评估一个指定系统调用的
+返回值总会使用最高优先级的值。(比如 ``SECCOMP_RET_KILL_PROCESS`` 总是被优先
+返回。)
+
+按照优先级排序,它们是:
+
+``SECCOMP_RET_KILL_PROCESS``:
+ 使得整个进程立即结束而不执行系统调用。进程的退出状态 (``status & 0x7f``) 将
+ 是 ``SIGSYS`` ,而不是 ``SIGKILL`` 。
+
+``SECCOMP_RET_KILL_THREAD``:
+ 使得线程立即结束而不执行系统调用。线程的退出状态 (``status & 0x7f``) 将是
+ 是 ``SIGSYS`` ,而不是 ``SIGKILL`` 。
+
+``SECCOMP_RET_TRAP``:
+ 使得内核向触发进程发送一个 ``SIGSYS`` 信号而不执行系统调用。
+ ``siginfo->si_call_addr`` 会展示系统调用指令的位置, ``siginfo->si_syscall``
+ 和 ``siginfo->si_arch`` 会指出试图进行的系统调用。程序计数器会和发生了系统
+ 调用的一样(即它不会指向系统调用指令)。返回值寄存器会包含一个与架构相关的值——
+ 如果恢复执行,需要将其设为合理的值。(架构依赖性是因为将其替换为 ``-ENOSYS``
+ 会导致一些有用的信息被覆盖。)
+
+ 返回值的 ``SECCOMP_RET_DATA`` 部分会作为 ``si_errno`` 传递。
+
+ 由seccomp触发的 ``SIGSYS`` 会有一个 ``SYS_SECCOMP`` 的 si_code 。
+
+``SECCOMP_RET_ERRNO``:
+ 使得返回值的低16位作为errno传递给用户空间,而不执行系统调用。
+
+``SECCOMP_RET_USER_NOTIF``:
+ 使得一个 ``struct seccomp_notif`` 消息被发送到已附加的用户空间通知文件描述
+ 符。如果没有被附加则返回 ``-ENOSYS`` 。下面会讨论如何处理用户通知。
+
+``SECCOMP_RET_TRACE``:
+ 当返回的时候,这个值会使得内核在执行系统调用前尝试去通知一个基于 ``ptrace()``
+ 的追踪器。如果没有追踪器, ``-ENOSYS`` 会返回给用户空间,并且系统调用不会执行。
+
+ 如果追踪器通过 ``ptrace(PTRACE_SETOPTIONS)`` 请求了 ``PTRACE_O_TRACESECCOMP``,
+ 那么它会收到 ``PTRACE_EVENT_SECCOMP`` 通知。BPF程序返回值的 ``SECCOMP_RET_DATA``
+ 部分会通过 ``PTRACE_GETEVENTMSG`` 提供给追踪器。
+
+ 追踪器可以通过改变系统调用号到-1来跳过系统调用。或者追踪器可以改变系统调用号到
+ 一个有效值来改变请求的系统调用。如果追踪器请求跳过系统调用,那么系统调用将返回
+ 追踪器放在返回值寄存器中的值。
+
+ 在追踪器被通知后,seccomp检查不会再次运行。(这意味着基于seccomp的沙箱必须禁止
+ ptrace的使用,甚至其他沙箱进程也不行,除非非常小心;ptrace可以通过这个机制来逃
+ 逸。)
+
+``SECCOMP_RET_LOG``:
+ 使得系统调用在被记录之后再运行。这应该被应用开发者用来检查他们的程序需要哪些
+ 系统调用,而不需要反复通过多个测试和开发周期来建立清单。
+
+ 只有在 actions_logged sysctl 字符串中出现 "log" 时,这个操作才会被记录。
+
+``SECCOMP_RET_ALLOW``:
+ 使得系统调用被执行。
+
+如果多个追踪器存在,评估系统调用的返回值将永远使用最高优先级的值。
+
+优先级只通过 ``SECCOMP_RET_ACTION`` 掩码来决定。当多个过滤器返回相同优先级的返回
+值时,只有来自最近安装的过滤器的 ``SECCOMP_RET_DATA`` 会被返回。
+
+隐患
+====
+
+最需要避免的隐患是在过滤系统调用号时却不检查架构值。因为在任何支持多个系统调用
+约定的架构上,系统调用号可能根据具体调用而不同。如果不同调用约定中的调用号有重叠,
+那么过滤器的检查可能被滥用。请总是检查架构值!
+
+例子
+====
+
+``samples/seccomp/`` 文件夹包含了x86专用和更通用的使用高层宏接口来生成BPF程序的
+例子。
+
+用户空间通知
+============
+
+``SECCOMP_RET_USER_NOTIF`` 返回值会让seccomp过滤器传递一个特定的系统调用给用户
+空间处理。这可能会对像容器管理器的程序有用,它们希望拦截特定的系统调用(如 ``mount()``,
+``finit_module()`` 等等)并改变其行为。
+
+传递 ``SECCOMP_FILTER_FLAG_NEW_LISTENER`` 参数给 ``seccomp()`` 系统调用可以取
+得通知文件描述符:
+
+.. code-block:: c
+
+ fd = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_NEW_LISTENER, &prog);
+
+成功情况下会返回一个对过滤器监听的文件描述符,然后可以通过 ``SCM_RIGHTS`` 或类似
+的方式传递。需要注意的是,过滤器文件描述符针对的是一个特定的过滤器而不是特定的进程。
+所以如果这个进程后来fork了,来自两个进程的通知都会出现在同一个过滤器文件描述符中。
+对于过滤器文件描述符的读写也是同步的,所以一个过滤器文件描述符可以安全地拥有多个读者。
+
+seccomp通知文件描述符由两个结构体组成:
+
+.. code-block:: c
+
+ struct seccomp_notif_sizes {
+ __u16 seccomp_notif;
+ __u16 seccomp_notif_resp;
+ __u16 seccomp_data;
+ };
+
+ struct seccomp_notif {
+ __u64 id;
+ __u32 pid;
+ __u32 flags;
+ struct seccomp_data data;
+ };
+
+ struct seccomp_notif_resp {
+ __u64 id;
+ __s64 val;
+ __s32 error;
+ __u32 flags;
+ };
+
+``struct seccomp_notif_sizes`` 结构体可以用于确定seccomp通知中各种结构体的大小。
+``struct seccomp_data`` 的大小可能未来会改变,所以需要使用下面的代码:
+
+.. code-block:: c
+
+ struct seccomp_notif_sizes sizes;
+ seccomp(SECCOMP_GET_NOTIF_SIZES, 0, &sizes);
+
+来决定需要分配的多种结构体的大小。请查看 samples/seccomp/user-trap.c 中的例子。
+
+用户可以通过 ``ioctl(SECCOMP_IOCTL_NOTIF_RECV)`` (或 ``poll()``) 读取seccomp
+通知文件描述符来接收一个 ``struct seccomp_notif`` ,其中包含五个成员:结构体的
+输入长度,每个过滤器唯一的 ``id`` , 触发请求进程的 ``pid`` (如果进程的pid命名空
+间对于监听者的pid命名空间不可见的话,可能为0)。通知还包含传递给seccomp的 ``data``
+和一个过滤器标志。在调用ioctl前结构体应该被清空。
+
+之后用户空间可以根据这些信息决定做什么,并通过 ``ioctl(SECCOMP_IOCTL_NOTIF_SEND)``
+发送一个响应,表示应该给用户空间返回什么。 ``struct seccomp_notif_resp`` 的 ``id``
+成员应该和 ``struct seccomp_notif`` 的 ``id`` 一致。
+
+用户空间也可以通过 ``ioctl(SECCOMP_IOCTL_NOTIF_ADDFD)`` 向通知进程添加文件描述
+符。 ``struct seccomp_notif_addfd`` 的 ``id`` 成员应该和 ``struct seccomp_notif``
+的 ``id`` 保持一致。 ``newfd_flags`` 标志可以被用于在通知进程的文件描述符上设置
+O_CLOEXEC 等标志。如果监督者(supervisor)向文件描述符注入一个特定的数字,可以使用
+``SECCOMP_ADDFD_FLAG_SETFD`` 标志,并设置 ``newfd`` 成员为要使用的特定数字。
+如果文件描述符已经在通知进程中打开,那它将被替换。监督者也可以添加一个文件描述符,
+并使用 ``SECCOMP_ADDFD_FLAG_SEND`` 标志原子响应,返回值将是注入的文件描述符编号。
+
+通知进程可以被抢占,导致通知被终止。这可能在尝试代表通知进程执行长时间且通常可重试
+(如挂载文件系统)的操作时导致问题。另外,在安装过滤器的时候,
+``SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV`` 可以被设置。这个标志使得当监督者收到用
+户通知时,通知进程会忽略非致命信号,直到响应被发送。在用户空间收到通知之前发出的信号
+将被正常处理。
+
+值得注意的是, ``struct seccomp_data`` 包含了系统调用寄存器参数的值,但是不包含指向
+内存的指针。进程的内存可以通过 ``ptrace()`` 或 ``/proc/pid/mem`` 由合适的特权跟踪
+访问。但是,需要注意避免之前提到的TOCTOU攻击:所有从被跟踪者内存中读到的参数都应该先
+读到追踪器的内存中,再做出策略决定。这样就可以对系统调用的参数做原子决定。
+
+Sysctls
+=======
+
+Seccomp的sysctl文件可以在 ``/proc/sys/kernel/seccomp/`` 文件夹中找到。这里有对文件
+夹中每个文件的描述:
+
+``actions_avail``:
+ 以字符串形式保存seccomp返回值(参考上文的 ``SECCOMP_RET_*`` 宏)的只读有序
+ 列表。从左往右按照最少许可返回值到最多许可返回值排序。
+
+ 这个列表代表了内核支持的seccomp返回值集合。一个用户空间程序可以使用这个列表来在
+ 程序建立时确定在 ``seccomp.h`` 中找到的动作是否和当前运行内核实际支持的动作有所
+ 不同。
+
+``actions_logged``:
+ 允许被记录的seccomp返回值(参考上文的 ``SECCOMP_RET_*`` 宏)的可读写有序列表。
+ 对文件写入不需要是有序的,但从文件读取将采用与actions_avail sysctl一致的方式排序。
+
+ ``allow`` 字符串在 ``actions_logged`` sysctl中不被接收,因为不可能记录
+ ``SECCOMP_RET_ALLOW`` 动作。尝试向sysctl写入 ``allow`` 会导致返回一个EINVAL。
+
+添加架构支持
+============
+
+请查看 ``arch/Kconfig`` 了解权威要求。总的来说如果一个架构同时支持ptrace_event和
+seccomp,那么它将可以通过较小的修改支持seccomp过滤器: ``SIGSYS`` 支持和seccomp
+返回值检查。然后必须将 ``CONFIG_HAVE_ARCH_SECCOMP_FILTER`` 添加到它的架构特定
+的Kconfig中。
+
+注意事项
+========
+
+vDSO可能导致一些系统调用完全在用户空间中运行,当你在不同机器上跑程序时可能导致回退
+到真正系统调用的意外发生。为了在x86上最小化这些意外的发生,请确保你在测试时把
+``/sys/devices/system/clocksource/clocksource0/current_clocksource`` 设置为
+``acpi_pm`` 之类的值。
+
+在x86-64上,vsyscall模拟默认开启。(vsyscalls是vDSO调用的传统变体。)目前,模拟
+vsyscalls会遵守seccomp,但是有一些奇怪情况:
+
+- ``SECCOMP_RET_TRAP`` 的返回值会设置一个指向给定vsyscall入口的 ``si_call_addr``,
+ 而不是'syscall'指令之后的地址。任何想重新开始调用的代码都需要注意 (a) ret指令
+ 已被模拟,(b) 试图恢复系统调用将再次触发标准vsyscall模拟安全检查,使得恢复系统
+ 调用在大部分情况下没有意义。
+
+- ``SECCOMP_RET_TRACE`` 的返回值将像往常一样给追踪器发出信号,但是系统调用可能不能
+ 使用orig_rax寄存器改变为另一个系统调用。可能只能改变为-1来跳过当前模拟的调用。
+ 任何其他改变都可能终止进程。追踪器看到的rip值将是系统调用的入口地址;这和正常行为
+ 不同。追踪器禁止修改rip或者rsp。(不要依赖其他改变来终止进程,它们可能正常工作。
+ 比如在一些内核中,选择一个只存在于未来内核中的系统调用将被正确模拟,返回一个
+ ``-ENOSYS`` 。)
+
+要检测这个古怪的行为,可以检查 ``addr & ~0x0C00 == 0xFFFFFFFFFF600000``。(对于
+``SECCOMP_RET_TRACE`` ,使用rip。对于 ``SECCOMP_RET_TRAP`` ,使用
+``siginfo->si_call_addr`` 。)不要检测其他条件:未来内核可能会改进vsyscall模拟,
+当前内核在vsyscall=native模式下会有不同表现,但在这些情况下, ``0xF...F600{0,4,8,C}00``
+处的指令将不是系统调用。
+
+请注意,现代系统根本不可能使用vsyscalls —— 它们是一种遗留功能,而且比标准系统调用
+慢得多。 新的代码将使用vDSO,而vDSO发出的系统调用与正常的系统调用没有区别。
diff --git a/Documentation/translations/zh_CN/userspace-api/sysfs-platform_profile.rst b/Documentation/translations/zh_CN/userspace-api/sysfs-platform_profile.rst
new file mode 100644
index 000000000000..7d21740db125
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/sysfs-platform_profile.rst
@@ -0,0 +1,40 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/sysfs-platform_profile.rst
+
+:翻译:
+
+ 李睿 Rui Li <me@lirui.org>
+
+==========================================================
+平台配置文件选择(如 /sys/firmware/acpi/platform_profile)
+==========================================================
+
+现代系统中平台性能、温度、风扇和其他硬件相关的特性通常是可以动态配置的。平台
+配置通常会根据当前的状态由一些自动机制(很可能存在于内核之外)来自动调整。
+
+这些平台自动调整机制通常能够被配置成多个平台配置文件中的一个,要么偏向节能运
+行,要么偏向性能运行。
+
+platform_profile属性的目的是提供一个通用的sysfs API来选择这些平台自动配置
+机制的配置文件。
+
+需要注意的是,这个API只能用作选择平台配置文件,用来监测所产生的性能特征并不
+是其目标。监测性能最好使用设备/供应商提供的工具,比如turbostat。
+
+具体来说,当选择高性能配置文件时,真实能达到的性能可能受制于多种因素,比如:
+其他组件的发热,房间温度,笔记本底部的自由空气流动等。让用户空间知道任何阻碍
+达到要求性能水平的局部最优条件,显然不是这个API的目标。
+
+由于数字本身并不能代表一个配置文件会调整的多个变量(功耗,发热等),这个API
+使用字符串来描述多种配置文件。为了保证用户空间能够获得一致的体验,
+sysfs-platform_profile ABI 文档定义了一个固定的配置文件名集合。驱动程序
+*必须* 将它们内置的配置文件表示映射到这个固定的集合中。
+
+如果映射时没有很好的匹配,可以添加一个新的配置文件名称。驱动希望引入的新配置
+文件名称时必须:
+
+ 1. 解释为什么无法使用已有的配置文件名称。
+ 2. 添加一个新的配置文件名称,以及预期行为的清晰描述,保存到
+ sysfs-platform_profile ABI文档中。