提交 4ac6d908 编写于 作者: L Linus Torvalds

Merge tag 'docs-5.15' of git://git.lwn.net/linux

Pull documentation updates from Jonathan Corbet:
 "Yet another set of documentation changes:

   - A reworking of PDF generation to yield better results for documents
     using CJK fonts in particular.

   - A new set of translations into traditional Chinese, a dialect for
     which I am assured there is a community of interested readers.

   - A lot more regular Chinese translation work as well.

  ... plus the usual assortment of updates, fixes, typo tweaks, etc"

* tag 'docs-5.15' of git://git.lwn.net/linux: (55 commits)
  docs: sphinx-requirements: Move sphinx_rtd_theme to top
  docs: pdfdocs: Enable language-specific font choice of zh_TW translations
  docs: pdfdocs: Teach xeCJK about character classes of quotation marks
  docs: pdfdocs: Permit AutoFakeSlant for CJK fonts
  docs: pdfdocs: One-half spacing for CJK translations
  docs: pdfdocs: Add conf.py local to translations for ascii-art alignment
  docs: pdfdocs: Preserve inter-phrase space in Korean translations
  docs: pdfdocs: Choose Serif font as CJK mainfont if possible
  docs: pdfdocs: Add CJK-language-specific font settings
  docs: pdfdocs: Refactor config for CJK document
  scripts/kernel-doc: Override -Werror from KCFLAGS with KDOC_WERROR
  docs/zh_CN: Add zh_CN/accounting/psi.rst
  doc: align Italian translation
  Documentation/features/vm: riscv supports THP now
  docs/zh_CN: add infiniband user_verbs translation
  docs/zh_CN: add infiniband user_mad translation
  docs/zh_CN: add infiniband tag_matching translation
  docs/zh_CN: add infiniband sysfs translation
  docs/zh_CN: add infiniband opa_vnic translation
  docs/zh_CN: add infiniband ipoib translation
  ...
......@@ -58,9 +58,9 @@ source for the output is in brackets ("[]").
[NR_CPUS-1]
offline: CPUs that are not online because they have been
HOTPLUGGED off (see cpu-hotplug.txt) or exceed the limit
of CPUs allowed by the kernel configuration (kernel_max
above). [~cpu_online_mask + cpus >= NR_CPUS]
HOTPLUGGED off or exceed the limit of CPUs allowed by the
kernel configuration (kernel_max above).
[~cpu_online_mask + cpus >= NR_CPUS]
online: CPUs that are online and being scheduled [cpu_online_mask]
......@@ -96,5 +96,5 @@ online.)::
possible: 0-127
present: 0-3
See cpu-hotplug.txt for the possible_cpus=NUM kernel start parameter
as well as more information on the various cpumasks.
See Documentation/core-api/cpu_hotplug.rst for the possible_cpus=NUM
kernel start parameter as well as more information on the various cpumasks.
......@@ -181,10 +181,12 @@ Open cross-HT issues that core scheduling does not solve
--------------------------------------------------------
1. For MDS
~~~~~~~~~~
Core scheduling cannot protect against MDS attacks between an HT running in
user mode and another running in kernel mode. Even though both HTs run tasks
which trust each other, kernel memory is still considered untrusted. Such
attacks are possible for any combination of sibling CPU modes (host or guest mode).
Core scheduling cannot protect against MDS attacks between the siblings
running in user mode and the others running in kernel mode. Even though all
siblings run tasks which trust each other, when the kernel is executing
code on behalf of a task, it cannot trust the code running in the
sibling. Such attacks are possible for any combination of sibling CPU modes
(host or guest mode).
2. For L1TF
~~~~~~~~~~~
......
......@@ -72,7 +72,7 @@ On PowerPC
On other
If you know of the key combos for other architectures, please
let me know so I can add them to this section.
submit a patch to be included in this section.
On all
Write a character to /proc/sysrq-trigger. e.g.::
......@@ -205,10 +205,12 @@ frozen (probably root) filesystem via the FIFREEZE ioctl.
Sometimes SysRq seems to get 'stuck' after using it, what can I do?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
That happens to me, also. I've found that tapping shift, alt, and control
on both sides of the keyboard, and hitting an invalid sysrq sequence again
will fix the problem. (i.e., something like :kbd:`alt-sysrq-z`). Switching to
another virtual console (:kbd:`ALT+Fn`) and then back again should also help.
When this happens, try tapping shift, alt and control on both sides of the
keyboard, and hitting an invalid sysrq sequence again. (i.e., something like
:kbd:`alt-sysrq-z`).
Switching to another virtual console (:kbd:`ALT+Fn`) and then back again
should also help.
I hit SysRq, but nothing seems to happen, what's wrong?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......
......@@ -58,11 +58,19 @@ Kirkwood family
- Product Brief : https://web.archive.org/web/20120616201621/http://www.marvell.com/embedded-processors/kirkwood/assets/88F6180-003_ver1.pdf
- Hardware Spec : https://web.archive.org/web/20130730091654/http://www.marvell.com/embedded-processors/kirkwood/assets/HW_88F6180_OpenSource.pdf
- Functional Spec: https://web.archive.org/web/20130730091033/http://www.marvell.com/embedded-processors/kirkwood/assets/FS_88F6180_9x_6281_OpenSource.pdf
- 88F6280
- Product Brief : https://web.archive.org/web/20130730091058/http://www.marvell.com/embedded-processors/kirkwood/assets/88F6280_SoC_PB-001.pdf
- 88F6281
- Product Brief : https://web.archive.org/web/20120131133709/http://www.marvell.com/embedded-processors/kirkwood/assets/88F6281-004_ver1.pdf
- Hardware Spec : https://web.archive.org/web/20120620073511/http://www.marvell.com/embedded-processors/kirkwood/assets/HW_88F6281_OpenSource.pdf
- Functional Spec: https://web.archive.org/web/20130730091033/http://www.marvell.com/embedded-processors/kirkwood/assets/FS_88F6180_9x_6281_OpenSource.pdf
- 88F6321
- 88F6322
- 88F6323
- Product Brief : https://web.archive.org/web/20120616201639/http://www.marvell.com/embedded-processors/kirkwood/assets/88f632x_pb.pdf
Homepage:
https://web.archive.org/web/20160513194943/http://www.marvell.com/embedded-processors/kirkwood/
Core:
......@@ -89,6 +97,10 @@ Discovery family
- MV76100
- Product Brief : https://web.archive.org/web/20140722064429/http://www.marvell.com/embedded-processors/discovery-innovation/assets/MV76100-002_WEB.pdf
- Hardware Spec : https://web.archive.org/web/20140722064425/http://www.marvell.com/embedded-processors/discovery-innovation/assets/HW_MV76100_OpenSource.pdf
- Functional Spec: https://web.archive.org/web/20111110081125/http://www.marvell.com/embedded-processors/discovery-innovation/assets/FS_MV76100_78100_78200_OpenSource.pdf
Not supported by the Linux kernel.
Core:
......@@ -124,17 +136,23 @@ EBU Armada family
Armada 38x Flavors:
- 88F6810 Armada 380
- 88F6811 Armada 381
- 88F6821 Armada 382
- 88F6W21 Armada 383
- 88F6820 Armada 385
- 88F6828 Armada 388
- Product infos: https://web.archive.org/web/20181006144616/http://www.marvell.com/embedded-processors/armada-38x/
- Functional Spec: https://web.archive.org/web/20200420191927/https://www.marvell.com/content/dam/marvell/en/public-collateral/embedded-processors/marvell-embedded-processors-armada-38x-functional-specifications-2015-11.pdf
- Hardware Spec: https://web.archive.org/web/20180713105318/https://www.marvell.com/docs/embedded-processors/assets/marvell-embedded-processors-armada-38x-hardware-specifications-2017-03.pdf
- Design guide: https://web.archive.org/web/20180712231737/https://www.marvell.com/docs/embedded-processors/assets/marvell-embedded-processors-armada-38x-hardware-design-guide-2017-08.pdf
Core:
ARM Cortex-A9
Armada 39x Flavors:
- 88F6920 Armada 390
- 88F6925 Armada 395
- 88F6928 Armada 398
- Product infos: https://web.archive.org/web/20181020222559/http://www.marvell.com/embedded-processors/armada-39x/
......
......@@ -16,8 +16,6 @@ import sys
import os
import sphinx
from subprocess import check_output
# Get Sphinx version
major, minor, patch = sphinx.version_info[:3]
......@@ -343,6 +341,9 @@ latex_elements = {
verbatimhintsturnover=false,
''',
# For CJK One-half spacing, need to be in front of hyperref
'extrapackages': r'\usepackage{setspace}',
# Additional stuff for the LaTeX preamble.
'preamble': '''
% Prevent column squeezing of tabulary.
......@@ -355,29 +356,117 @@ latex_elements = {
''',
}
# At least one book (translations) may have Asian characters
# with are only displayed if xeCJK is used
# Translations have Asian (CJK) characters which are only displayed if
# xeCJK is used
cjk_cmd = check_output(['fc-list', '--format="%{family[0]}\n"']).decode('utf-8', 'ignore')
if cjk_cmd.find("Noto Sans CJK SC") >= 0:
latex_elements['preamble'] += '''
latex_elements['preamble'] += '''
\\IfFontExistsTF{Noto Sans CJK SC}{
% This is needed for translations
\\usepackage{xeCJK}
\\setCJKmainfont{Noto Sans CJK SC}
\\usepackage{xeCJK}
\\IfFontExistsTF{Noto Serif CJK SC}{
\\setCJKmainfont{Noto Serif CJK SC}[AutoFakeSlant]
}{
\\setCJKmainfont{Noto Sans CJK SC}[AutoFakeSlant]
}
\\setCJKsansfont{Noto Sans CJK SC}[AutoFakeSlant]
\\setCJKmonofont{Noto Sans Mono CJK SC}[AutoFakeSlant]
% CJK Language-specific font choices
\\IfFontExistsTF{Noto Serif CJK SC}{
\\newCJKfontfamily[SCmain]\\scmain{Noto Serif CJK SC}[AutoFakeSlant]
\\newCJKfontfamily[SCserif]\\scserif{Noto Serif CJK SC}[AutoFakeSlant]
}{
\\newCJKfontfamily[SCmain]\\scmain{Noto Sans CJK SC}[AutoFakeSlant]
\\newCJKfontfamily[SCserif]\\scserif{Noto Sans CJK SC}[AutoFakeSlant]
}
\\newCJKfontfamily[SCsans]\\scsans{Noto Sans CJK SC}[AutoFakeSlant]
\\newCJKfontfamily[SCmono]\\scmono{Noto Sans Mono CJK SC}[AutoFakeSlant]
\\IfFontExistsTF{Noto Serif CJK TC}{
\\newCJKfontfamily[TCmain]\\tcmain{Noto Serif CJK TC}[AutoFakeSlant]
\\newCJKfontfamily[TCserif]\\tcserif{Noto Serif CJK TC}[AutoFakeSlant]
}{
\\newCJKfontfamily[TCmain]\\tcmain{Noto Sans CJK TC}[AutoFakeSlant]
\\newCJKfontfamily[TCserif]\\tcserif{Noto Sans CJK TC}[AutoFakeSlant]
}
\\newCJKfontfamily[TCsans]\\tcsans{Noto Sans CJK TC}[AutoFakeSlant]
\\newCJKfontfamily[TCmono]\\tcmono{Noto Sans Mono CJK TC}[AutoFakeSlant]
\\IfFontExistsTF{Noto Serif CJK KR}{
\\newCJKfontfamily[KRmain]\\krmain{Noto Serif CJK KR}[AutoFakeSlant]
\\newCJKfontfamily[KRserif]\\krserif{Noto Serif CJK KR}[AutoFakeSlant]
}{
\\newCJKfontfamily[KRmain]\\krmain{Noto Sans CJK KR}[AutoFakeSlant]
\\newCJKfontfamily[KRserif]\\krserif{Noto Sans CJK KR}[AutoFakeSlant]
}
\\newCJKfontfamily[KRsans]\\krsans{Noto Sans CJK KR}[AutoFakeSlant]
\\newCJKfontfamily[KRmono]\\krmono{Noto Sans Mono CJK KR}[AutoFakeSlant]
\\IfFontExistsTF{Noto Serif CJK JP}{
\\newCJKfontfamily[JPmain]\\jpmain{Noto Serif CJK JP}[AutoFakeSlant]
\\newCJKfontfamily[JPserif]\\jpserif{Noto Serif CJK JP}[AutoFakeSlant]
}{
\\newCJKfontfamily[JPmain]\\jpmain{Noto Sans CJK JP}[AutoFakeSlant]
\\newCJKfontfamily[JPserif]\\jpserif{Noto Sans CJK JP}[AutoFakeSlant]
}
\\newCJKfontfamily[JPsans]\\jpsans{Noto Sans CJK JP}[AutoFakeSlant]
\\newCJKfontfamily[JPmono]\\jpmono{Noto Sans Mono CJK JP}[AutoFakeSlant]
% Dummy commands for Sphinx < 2.3 (no 'extrapackages' support)
\\providecommand{\\onehalfspacing}{}
\\providecommand{\\singlespacing}{}
% Define custom macros to on/off CJK
\\newcommand{\\kerneldocCJKon}{\\makexeCJKactive}
\\newcommand{\\kerneldocCJKoff}{\\makexeCJKinactive}
% To customize \sphinxtableofcontents
\\newcommand{\\kerneldocCJKon}{\\makexeCJKactive\\onehalfspacing}
\\newcommand{\\kerneldocCJKoff}{\\makexeCJKinactive\\singlespacing}
\\newcommand{\\kerneldocBeginSC}{%
\\begingroup%
\\scmain%
}
\\newcommand{\\kerneldocEndSC}{\\endgroup}
\\newcommand{\\kerneldocBeginTC}{%
\\begingroup%
\\tcmain%
\\renewcommand{\\CJKrmdefault}{TCserif}%
\\renewcommand{\\CJKsfdefault}{TCsans}%
\\renewcommand{\\CJKttdefault}{TCmono}%
}
\\newcommand{\\kerneldocEndTC}{\\endgroup}
\\newcommand{\\kerneldocBeginKR}{%
\\begingroup%
\\xeCJKDeclareCharClass{HalfLeft}{`“,`‘}%
\\xeCJKDeclareCharClass{HalfRight}{`”,`’}%
\\krmain%
\\renewcommand{\\CJKrmdefault}{KRserif}%
\\renewcommand{\\CJKsfdefault}{KRsans}%
\\renewcommand{\\CJKttdefault}{KRmono}%
\\xeCJKsetup{CJKspace = true} % For inter-phrase space
}
\\newcommand{\\kerneldocEndKR}{\\endgroup}
\\newcommand{\\kerneldocBeginJP}{%
\\begingroup%
\\xeCJKDeclareCharClass{HalfLeft}{`“,`‘}%
\\xeCJKDeclareCharClass{HalfRight}{`”,`’}%
\\jpmain%
\\renewcommand{\\CJKrmdefault}{JPserif}%
\\renewcommand{\\CJKsfdefault}{JPsans}%
\\renewcommand{\\CJKttdefault}{JPmono}%
}
\\newcommand{\\kerneldocEndJP}{\\endgroup}
% Single spacing in literal blocks
\\fvset{baselinestretch=1}
% To customize \\sphinxtableofcontents
\\usepackage{etoolbox}
% Inactivate CJK after tableofcontents
\\apptocmd{\\sphinxtableofcontents}{\\kerneldocCJKoff}{}{}
'''
else:
latex_elements['preamble'] += '''
}{ % No CJK font found
% Custom macros to on/off CJK (Dummy)
\\newcommand{\\kerneldocCJKon}{}
\\newcommand{\\kerneldocCJKoff}{}
'''
\\newcommand{\\kerneldocBeginSC}{}
\\newcommand{\\kerneldocEndSC}{}
\\newcommand{\\kerneldocBeginTC}{}
\\newcommand{\\kerneldocEndTC}{}
\\newcommand{\\kerneldocBeginKR}{}
\\newcommand{\\kerneldocEndKR}{}
\\newcommand{\\kerneldocBeginSC}{}
\\newcommand{\\kerneldocEndKR}{}
}
'''
# Fix reference escape troubles with Sphinx 1.4.x
if major == 1:
......
......@@ -91,9 +91,10 @@ Never use anything other than ``cpumask_t`` to represent bitmap of CPUs.
Using CPU hotplug
=================
The kernel option *CONFIG_HOTPLUG_CPU* needs to be enabled. It is currently
available on multiple architectures including ARM, MIPS, PowerPC and X86. The
configuration is done via the sysfs interface: ::
configuration is done via the sysfs interface::
$ ls -lh /sys/devices/system/cpu
total 0
......@@ -113,14 +114,14 @@ configuration is done via the sysfs interface: ::
The files *offline*, *online*, *possible*, *present* represent the CPU masks.
Each CPU folder contains an *online* file which controls the logical on (1) and
off (0) state. To logically shutdown CPU4: ::
off (0) state. To logically shutdown CPU4::
$ echo 0 > /sys/devices/system/cpu/cpu4/online
smpboot: CPU 4 is now offline
Once the CPU is shutdown, it will be removed from */proc/interrupts*,
*/proc/cpuinfo* and should also not be shown visible by the *top* command. To
bring CPU4 back online: ::
bring CPU4 back online::
$ echo 1 > /sys/devices/system/cpu/cpu4/online
smpboot: Booting Node 0 Processor 4 APIC 0x1
......@@ -142,6 +143,7 @@ The CPU hotplug coordination
The offline case
----------------
Once a CPU has been logically shutdown the teardown callbacks of registered
hotplug states will be invoked, starting with ``CPUHP_ONLINE`` and terminating
at state ``CPUHP_OFFLINE``. This includes:
......@@ -158,9 +160,10 @@ at state ``CPUHP_OFFLINE``. This includes:
Using the hotplug API
---------------------
It is possible to receive notifications once a CPU is offline or onlined. This
might be important to certain drivers which need to perform some kind of setup
or clean up functions based on the number of available CPUs: ::
or clean up functions based on the number of available CPUs::
#include <linux/cpuhotplug.h>
......@@ -186,9 +189,10 @@ During the removal of a hotplug state the teardown callback will be invoked.
Multiple instances
~~~~~~~~~~~~~~~~~~
If a driver has multiple instances and each instance needs to perform the
callback independently then it is likely that a ''multi-state'' should be used.
First a multi-state state needs to be registered: ::
First a multi-state state needs to be registered::
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "X/Y:online,
Y_online, Y_prepare_down);
......@@ -197,7 +201,7 @@ First a multi-state state needs to be registered: ::
The ``cpuhp_setup_state_multi()`` behaves similar to ``cpuhp_setup_state()``
except it prepares the callbacks for a multi state and does not invoke
the callbacks. This is a one time setup.
Once a new instance is allocated, you need to register this new instance: ::
Once a new instance is allocated, you need to register this new instance::
ret = cpuhp_state_add_instance(Y_hp_online, &d->node);
......@@ -206,7 +210,8 @@ This function will add this instance to your previously allocated
(*Y_online*) on all online CPUs. The *node* element is a ``struct
hlist_node`` member of your per-instance data structure.
On removal of the instance: ::
On removal of the instance::
cpuhp_state_remove_instance(Y_hp_online, &d->node)
should be invoked which will invoke the teardown callback on all online
......@@ -214,6 +219,7 @@ CPUs.
Manual setup
~~~~~~~~~~~~
Usually it is handy to invoke setup and teardown callbacks on registration or
removal of a state because usually the operation needs to performed once a CPU
goes online (offline) and during initial setup (shutdown) of the driver. However
......@@ -226,6 +232,7 @@ hotplug operations.
The ordering of the events
--------------------------
The hotplug states are defined in ``include/linux/cpuhotplug.h``:
* The states *CPUHP_OFFLINE* … *CPUHP_AP_OFFLINE* are invoked before the
......@@ -248,13 +255,14 @@ another hotplug event.
Testing of hotplug states
=========================
One way to verify whether a custom state is working as expected or not is to
shutdown a CPU and then put it online again. It is also possible to put the CPU
to certain state (for instance *CPUHP_AP_ONLINE*) and then go back to
*CPUHP_ONLINE*. This would simulate an error one state after *CPUHP_AP_ONLINE*
which would lead to rollback to the online state.
All registered states are enumerated in ``/sys/devices/system/cpu/hotplug/states``: ::
All registered states are enumerated in ``/sys/devices/system/cpu/hotplug/states`` ::
$ tail /sys/devices/system/cpu/hotplug/states
138: mm/vmscan:online
......@@ -268,7 +276,7 @@ All registered states are enumerated in ``/sys/devices/system/cpu/hotplug/states
168: sched:active
169: online
To rollback CPU4 to ``lib/percpu_cnt:online`` and back online just issue: ::
To rollback CPU4 to ``lib/percpu_cnt:online`` and back online just issue::
$ cat /sys/devices/system/cpu/cpu4/hotplug/state
169
......@@ -276,14 +284,14 @@ To rollback CPU4 to ``lib/percpu_cnt:online`` and back online just issue: ::
$ cat /sys/devices/system/cpu/cpu4/hotplug/state
140
It is important to note that the teardown callbac of state 140 have been
invoked. And now get back online: ::
It is important to note that the teardown callback of state 140 have been
invoked. And now get back online::
$ echo 169 > /sys/devices/system/cpu/cpu4/hotplug/target
$ cat /sys/devices/system/cpu/cpu4/hotplug/state
169
With trace events enabled, the individual steps are visible, too: ::
With trace events enabled, the individual steps are visible, too::
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
......@@ -318,6 +326,7 @@ trace.
Architecture's requirements
===========================
The following functions and configurations are required:
``CONFIG_HOTPLUG_CPU``
......@@ -339,11 +348,12 @@ The following functions and configurations are required:
User Space Notification
=======================
After CPU successfully onlined or offline udev events are sent. A udev rule like: ::
After CPU successfully onlined or offline udev events are sent. A udev rule like::
SUBSYSTEM=="cpu", DRIVERS=="processor", DEVPATH=="/devices/system/cpu/*", RUN+="the_hotplug_receiver.sh"
will receive all events. A script like: ::
will receive all events. A script like::
#!/bin/sh
......
......@@ -130,6 +130,7 @@ printed after the symbol name with an extra ``b`` appended to the end of the
specifier.
::
%pS versatile_init+0x0/0x110 [module_name]
%pSb versatile_init+0x0/0x110 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]
%pSRb versatile_init+0x9/0x110 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]
......
......@@ -22,7 +22,7 @@
| openrisc: | .. |
| parisc: | TODO |
| powerpc: | ok |
| riscv: | TODO |
| riscv: | ok |
| s390: | ok |
| sh: | .. |
| sparc: | ok |
......
......@@ -159,7 +159,7 @@ References
[2] Devicetree. https://www.devicetree.org, referenced 2016-10-03.
[3] Documentation/devicetree/bindings/graph.txt
[3] Documentation/devicetree/bindings/graph.txt
[4] Device Properties UUID For _DSD.
https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf,
......
.. include:: <isonum.txt>
===================================
DPAA2 DPIO (Data Path I/O) Overview
===================================
......
......@@ -164,7 +164,9 @@ Paraphrasing Linus's current `guidance <https://lore.kernel.org/lkml/CA+55aFwQEd
up to Linus's scrutiny, maybe you can use "%px", along with making sure
you have sensible permissions.
And finally, know that a toggle for "%p" hashing will `not be accepted <https://lore.kernel.org/lkml/CA+55aFwieC1-nAs+NFq9RTwaR8ef9hWa4MjNBWL41F-8wM49eA@mail.gmail.com/>`_.
If you are debugging something where "%p" hashing is causing problems,
you can temporarily boot with the debug flag "`no_hash_pointers
<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_".
Variable Length Arrays (VLAs)
-----------------------------
......
......@@ -216,11 +216,11 @@ cannot find a maintainer for the subsystem you are working on, Andrew
Morton (akpm@linux-foundation.org) serves as a maintainer of last resort.
You should also normally choose at least one mailing list to receive a copy
of your patch set. linux-kernel@vger.kernel.org functions as a list of
last resort, but the volume on that list has caused a number of developers
to tune it out. Look in the MAINTAINERS file for a subsystem-specific
list; your patch will probably get more attention there. Please do not
spam unrelated lists, though.
of your patch set. linux-kernel@vger.kernel.org should be used by default
for all patches, but the volume on that list has caused a number of
developers to tune it out. Look in the MAINTAINERS file for a
subsystem-specific list; your patch will probably get more attention there.
Please do not spam unrelated lists, though.
Many kernel-related lists are hosted on vger.kernel.org; you can find a
list of them at http://vger.kernel.org/vger-lists.html. There are
......
......@@ -3368,7 +3368,7 @@ This ensures that the device can be closed and the driver unloaded
without losing data.
This callback is optional. If you do not set ``drain`` in the struct
snd_rawmidi_ops structure, ALSA will simply wait for 50 milliseconds
snd_rawmidi_ops structure, ALSA will simply wait for 50 milliseconds
instead.
Miscellaneous Devices
......
docutils
Sphinx==2.4.4
sphinx_rtd_theme
Sphinx==2.4.4
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: GPL-2.0
# -- Additinal options for LaTeX output ----------------------------------
# font config for ascii-art alignment
latex_elements['preamble'] += '''
\\IfFontExistsTF{Noto Sans CJK SC}{
% For CJK ascii-art alignment
\\setmonofont{Noto Sans Mono CJK SC}[AutoFakeSlant]
}{}
'''
......@@ -8,6 +8,7 @@ Translations
:maxdepth: 1
zh_CN/index
zh_TW/index
it_IT/index
ko_KR/index
ja_JP/index
......
......@@ -42,15 +42,15 @@ nomi: EXPORT_SYMBOL_NS() ed EXPORT_SYMBOL_NS_GPL(). Queste macro richiedono un
argomento aggiuntivo: lo spazio dei nomi.
Tenete presente che per via dell'espansione delle macro questo argomento deve
essere un simbolo di preprocessore. Per esempio per esportare il
simbolo `usb_stor_suspend` nello spazio dei nomi `USB_STORAGE` usate::
simbolo ``usb_stor_suspend`` nello spazio dei nomi ``USB_STORAGE`` usate::
EXPORT_SYMBOL_NS(usb_stor_suspend, USB_STORAGE);
Di conseguenza, nella tabella dei simboli del kernel ci sarà una voce
rappresentata dalla struttura `kernel_symbol` che avrà il campo
`namespace` (spazio dei nomi) impostato. Un simbolo esportato senza uno spazio
dei nomi avrà questo campo impostato a `NULL`. Non esiste uno spazio dei nomi
di base. Il programma `modpost` e il codice in kernel/module.c usano lo spazio
rappresentata dalla struttura ``kernel_symbol`` che avrà il campo
``namespace`` (spazio dei nomi) impostato. Un simbolo esportato senza uno spazio
dei nomi avrà questo campo impostato a ``NULL``. Non esiste uno spazio dei nomi
di base. Il programma ``modpost`` e il codice in kernel/module.c usano lo spazio
dei nomi, rispettivamente, durante la compilazione e durante il caricamento
di un modulo.
......@@ -65,7 +65,7 @@ ed EXPORT_SYMBOL_GPL() che non specificano esplicitamente uno spazio dei nomi.
Ci sono molti modi per specificare questo simbolo di preprocessore e il loro
uso dipende dalle preferenze del manutentore di un sottosistema. La prima
possibilità è quella di definire il simbolo nel `Makefile` del sottosistema.
possibilità è quella di definire il simbolo nel ``Makefile`` del sottosistema.
Per esempio per esportare tutti i simboli definiti in usb-common nello spazio
dei nomi USB_COMMON, si può aggiungere la seguente linea in
drivers/usb/common/Makefile::
......@@ -97,7 +97,7 @@ USB_STORAGE usando la seguente dichiarazione::
MODULE_IMPORT_NS(USB_STORAGE);
Questo creerà un'etichetta `modinfo` per ogni spazio dei nomi
Questo creerà un'etichetta ``modinfo`` per ogni spazio dei nomi
importato. Un risvolto di questo fatto è che gli spazi dei
nomi importati da un modulo possono essere ispezionati tramite
modinfo::
......@@ -116,7 +116,7 @@ mancanti.
4. Caricare moduli che usano simboli provenienti da spazi dei nomi
==================================================================
Quando un modulo viene caricato (per esempio usando `insmod`), il kernel
Quando un modulo viene caricato (per esempio usando ``insmod``), il kernel
verificherà la disponibilità di ogni simbolo usato e se lo spazio dei nomi
che potrebbe contenerli è stato importato. Il comportamento di base del kernel
è di rifiutarsi di caricare quei moduli che non importano tutti gli spazi dei
......@@ -144,22 +144,22 @@ Lo scenario tipico di chi scrive un modulo potrebbe essere::
- scrivere codice che dipende da un simbolo appartenente ad uno spazio
dei nomi non importato
- eseguire `make`
- eseguire ``make``
- aver notato un avviso da modpost che parla di un'importazione
mancante
- eseguire `make nsdeps` per aggiungere import nel posto giusto
- eseguire ``make nsdeps`` per aggiungere import nel posto giusto
Per i manutentori di sottosistemi che vogliono aggiungere uno spazio dei nomi,
l'approccio è simile. Di nuovo, eseguendo `make nsdeps` aggiungerà le
l'approccio è simile. Di nuovo, eseguendo ``make nsdeps`` aggiungerà le
importazioni mancanti nei moduli inclusi nel kernel::
- spostare o aggiungere simboli ad uno spazio dei nomi (per esempio
usando EXPORT_SYMBOL_NS())
- eseguire `make` (preferibilmente con allmodconfig per coprire tutti
- eseguire ``make`` (preferibilmente con allmodconfig per coprire tutti
i moduli del kernel)
- aver notato un avviso da modpost che parla di un'importazione
mancante
- eseguire `make nsdeps` per aggiungere import nel posto giusto
- eseguire ``make nsdeps`` per aggiungere import nel posto giusto
Potete anche eseguire nsdeps per moduli esterni. Solitamente si usa così::
......
......@@ -634,7 +634,7 @@ Definita in ``include/linux/export.h``
Questa è una variate di `EXPORT_SYMBOL()` che permette di specificare uno
spazio dei nomi. Lo spazio dei nomi è documentato in
:doc:`../core-api/symbol-namespaces`
Documentation/translations/it_IT/core-api/symbol-namespaces.rst.
:c:func:`EXPORT_SYMBOL_NS_GPL()`
--------------------------------
......@@ -643,7 +643,7 @@ Definita in ``include/linux/export.h``
Questa è una variate di `EXPORT_SYMBOL_GPL()` che permette di specificare uno
spazio dei nomi. Lo spazio dei nomi è documentato in
:doc:`../core-api/symbol-namespaces`
Documentation/translations/it_IT/core-api/symbol-namespaces.rst.
Procedure e convenzioni
=======================
......
......@@ -183,9 +183,11 @@ di Linus:
affrontare il giudizio di Linus, allora forse potrai usare "%px",
assicurandosi anche di averne il permesso.
Infine, sappi che un cambio in favore di "%p" con hash `non verrà
accettato
<https://lore.kernel.org/lkml/CA+55aFwieC1-nAs+NFq9RTwaR8ef9hWa4MjNBWL41F-8wM49eA@mail.gmail.com/>`_.
Potete disabilitare temporaneamente l'hashing di "%p" nel caso in cui questa
funzionalità vi sia d'ostacolo durante una sessione di debug. Per farlo
aggiungete l'opzione di debug "`no_hash_pointers
<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_" alla
riga di comando del kernel.
Vettori a dimensione variabile (VLA)
------------------------------------
......
......@@ -41,12 +41,6 @@ Regole sul tipo di patch che vengono o non vengono accettate nei sorgenti
Procedura per sottomettere patch per i sorgenti -stable
-------------------------------------------------------
- Se la patch contiene modifiche a dei file nelle cartelle net/ o drivers/net,
allora seguite le linee guida descritte in
:ref:`Documentation/translations/it_IT/networking/netdev-FAQ.rst <it_netdev-FAQ>`;
ma solo dopo aver verificato al seguente indirizzo che la patch non sia
già in coda:
https://patchwork.kernel.org/bundle/netdev/stable/?state=*
- Una patch di sicurezza non dovrebbero essere gestite (solamente) dal processo
di revisione -stable, ma dovrebbe seguire le procedure descritte in
:ref:`Documentation/translations/it_IT/admin-guide/security-bugs.rst <it_securitybugs>`.
......
......@@ -14,14 +14,15 @@ una certa familiarità col "sistema". Questo testo è una raccolta di
suggerimenti che aumenteranno significativamente le probabilità di vedere le
vostre patch accettate.
Questo documento contiene un vasto numero di suggerimenti concisi. Per
maggiori dettagli su come funziona il processo di sviluppo del kernel leggete
:doc:`development-process`.
Leggete anche :doc:`submit-checklist` per una lista di punti da
verificare prima di inviare del codice. Se state inviando un driver,
allora leggete anche :doc:`submitting-drivers`; per delle patch
Questo documento contiene un vasto numero di suggerimenti concisi. Per maggiori
dettagli su come funziona il processo di sviluppo del kernel leggete
Documentation/translations/it_IT/process/development-process.rst. Leggete anche
Documentation/translations/it_IT/process/submit-checklist.rst per una lista di
punti da verificare prima di inviare del codice. Se state inviando un driver,
allora leggete anche
Documentation/translations/it_IT/process/submitting-drivers.rst; per delle patch
relative alle associazioni per Device Tree leggete
:doc:`submitting-patches`.
Documentation/translations/it_IT/process/submitting-patches.rst.
Questa documentazione assume che sappiate usare ``git`` per preparare le patch.
Se non siete pratici di ``git``, allora è bene che lo impariate;
......@@ -193,7 +194,7 @@ ed integrate.
---------------------------------------------
Controllate che la vostra patch non violi lo stile del codice, maggiori
dettagli sono disponibili in :ref:`Documentation/translations/it_IT/process/coding-style.rst <it_codingstyle>`.
dettagli sono disponibili in Documentation/translations/it_IT/process/coding-style.rst.
Non farlo porta semplicemente a una perdita di tempo da parte dei revisori e
voi vedrete la vostra patch rifiutata, probabilmente senza nemmeno essere stata
letta.
......@@ -230,13 +231,13 @@ scripts/get_maintainer.pl può esservi d'aiuto. Se non riuscite a trovare un
manutentore per il sottosistema su cui state lavorando, allora Andrew Morton
(akpm@linux-foundation.org) sarà la vostra ultima possibilità.
Normalmente, dovreste anche scegliere una lista di discussione a cui inviare
la vostra serie di patch. La lista di discussione linux-kernel@vger.kernel.org
è proprio l'ultima spiaggia, il volume di email su questa lista fa si che
diversi sviluppatori non la seguano. Guardate nel file MAINTAINERS per trovare
la lista di discussione dedicata ad un sottosistema; probabilmente lì la vostra
patch riceverà molta più attenzione. Tuttavia, per favore, non spammate le
liste di discussione che non sono interessate al vostro lavoro.
Normalmente, dovreste anche scegliere una lista di discussione a cui inviare la
vostra serie di patch. La lista di discussione linux-kernel@vger.kernel.org
dovrebbe essere usata per inviare tutte le patch, ma il traffico è tale per cui
diversi sviluppatori la trascurano. Guardate nel file MAINTAINERS per trovare la
lista di discussione dedicata ad un sottosistema; probabilmente lì la vostra
patch riceverà molta più attenzione. Tuttavia, per favore, non spammate le liste
di discussione che non sono interessate al vostro lavoro.
Molte delle liste di discussione relative al kernel vengono ospitate su
vger.kernel.org; potete trovare un loro elenco alla pagina
......@@ -257,7 +258,7 @@ embargo potrebbe essere preso in considerazione per dare il tempo alle
distribuzioni di prendere la patch e renderla disponibile ai loro utenti;
in questo caso, ovviamente, la patch non dovrebbe essere inviata su alcuna
lista di discussione pubblica. Leggete anche
:doc:`/admin-guide/security-bugs`.
Documentation/admin-guide/security-bugs.rst.
Patch che correggono bachi importanti su un kernel già rilasciato, dovrebbero
essere inviate ai manutentori dei kernel stabili aggiungendo la seguente riga::
......@@ -266,12 +267,7 @@ essere inviate ai manutentori dei kernel stabili aggiungendo la seguente riga::
nella vostra patch, nell'area dedicata alle firme (notate, NON come destinatario
delle e-mail). In aggiunta a questo file, dovreste leggere anche
:ref:`Documentation/translations/it_IT/process/stable-kernel-rules.rst <it_stable_kernel_rules>`
Tuttavia, notate, che alcuni manutentori di sottosistema preferiscono avere
l'ultima parola su quali patch dovrebbero essere aggiunte ai kernel stabili.
La rete di manutentori, in particolare, non vorrebbe vedere i singoli
sviluppatori aggiungere alle loro patch delle righe come quella sopracitata.
Documentation/translations/it_IT/process/stable-kernel-rules.rst.
Se le modifiche hanno effetti sull'interfaccia con lo spazio utente, per favore
inviate una patch per le pagine man ai manutentori di suddette pagine (elencati
......@@ -330,7 +326,7 @@ così la possibilità che il vostro allegato-MIME venga accettato.
Eccezione: se il vostro servizio di posta storpia le patch, allora qualcuno
potrebbe chiedervi di rinviarle come allegato MIME.
Leggete :doc:`/translations/it_IT/process/email-clients`
Leggete Documentation/translations/it_IT/process/email-clients.rst
per dei suggerimenti sulla configurazione del programmi di posta elettronica
per l'invio di patch intatte.
......@@ -351,7 +347,7 @@ richiede molto tempo, e a volte i revisori diventano burberi. Tuttavia, anche
in questo caso, rispondete con educazione e concentratevi sul problema che
hanno evidenziato.
Leggete :doc:`/translations/it_IT/process/email-clients` per
Leggete Documentation/translations/it_IT/process/email-clients.rst per
le raccomandazioni sui programmi di posta elettronica e l'etichetta da usare
sulle liste di discussione.
......@@ -369,6 +365,16 @@ aver inviato le patch correttamente. Aspettate almeno una settimana prima di
rinviare le modifiche o sollecitare i revisori - probabilmente anche di più
durante la finestra d'integrazione.
Potete anche rinviare la patch, o la serie di patch, dopo un paio di settimane
aggiungendo la parola "RESEND" nel titolo::
[PATCH Vx RESEND] sub/sys: Condensed patch summary
Ma non aggiungete "RESEND" quando state sottomettendo una versione modificata
della vostra patch, o serie di patch - "RESEND" si applica solo alla
sottomissione di patch, o serie di patch, che non hanno subito modifiche
dall'ultima volta che sono state inviate.
Aggiungete PATCH nell'oggetto
-----------------------------
......@@ -795,8 +801,7 @@ Greg Kroah-Hartman, "Come scocciare un manutentore di un sottosistema"
No!!!! Basta gigantesche bombe patch alle persone sulla lista linux-kernel@vger.kernel.org!
<https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
Kernel Documentation/translations/it_IT/process/coding-style.rst:
:ref:`Documentation/translations/it_IT/process/coding-style.rst <it_codingstyle>`
Kernel Documentation/translations/it_IT/process/coding-style.rst.
E-mail di Linus Torvalds sul formato canonico di una patch:
<https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>
......
.. raw:: latex
\kerneldocCJKoff
NOTE:
This is a version of Documentation/process/howto.rst translated into Japanese.
This document is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com>
......@@ -11,6 +15,10 @@ try to update the original English file first.
----------------------------------
.. raw:: latex
\kerneldocCJKon
この文書は、
Documentation/process/howto.rst
の和訳です。
......
......@@ -3,6 +3,7 @@
\renewcommand\thesection*
\renewcommand\thesubsection*
\kerneldocCJKon
\kerneldocBeginJP
Japanese translations
=====================
......@@ -11,3 +12,7 @@ Japanese translations
:maxdepth: 1
howto
.. raw:: latex
\kerneldocEndJP
.. raw:: latex
\kerneldocCJKoff
NOTE:
This is a version of Documentation/process/howto.rst translated into korean
This document is maintained by Minchan Kim <minchan@kernel.org>
......@@ -11,6 +15,10 @@ try to update the original English file first.
----------------------------------
.. raw:: latex
\kerneldocCJKon
이 문서는
Documentation/process/howto.rst
의 한글 번역입니다.
......
......@@ -3,6 +3,7 @@
\renewcommand\thesection*
\renewcommand\thesubsection*
\kerneldocCJKon
\kerneldocBeginKR
한국어 번역
===========
......@@ -26,3 +27,4 @@
.. raw:: latex
\normalsize
\kerneldocEndKR
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/accounting/index.rst
:Translator: Yang Yang <yang.yang29@zte.com.cn>
.. _cn_accounting_index.rst:
====
计数
====
.. toctree::
:maxdepth: 1
psi
Todolist:
cgroupstats
delay-accounting
taskstats
taskstats-struct
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/accounting/psi.rst
:Translator: Yang Yang <yang.yang29@zte.com.cn>
.. _cn_psi.rst:
=================
PSI——压力阻塞信息
=================
:日期: April, 2018
:作者: Johannes Weiner <hannes@cmpxchg.org>
当CPU、memory或IO设备处于竞争状态,业务负载会遭受时延毛刺、吞吐量降低,
及面临OOM的风险。
如果没有一种准确的方法度量系统竞争程度,则有两种后果:一种是用户过于节制,
未充分利用系统资源;另一种是过度使用,经常性面临业务中断的风险。
psi特性能够识别和量化资源竞争导致的业务中断,及其对复杂负载乃至整个系统在
时间上的影响。
准确度量因资源不足造成的生产力损失,有助于用户基于硬件调整业务负载,或基
于业务负载配置硬件。
psi能够实时的提供相关信息,因此系统可基于psi实现动态的负载管理。如实施
卸载、迁移、策略性的停止或杀死低优先级或可重启的批处理任务。
psi帮助用户实现硬件资源利用率的最大化。同时无需牺牲业务负载健康度,也无需
面临OOM等造成业务中断的风险。
压力接口
========
压力信息可通过/proc/pressure/ --cpu、memory、io文件分别获取。
CPU相关信息格式如下:
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
内存和IO相关信息如下:
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
full avg10=0.00 avg60=0.00 avg300=0.00 total=0
some行代表至少有一个任务阻塞于特定资源的时间占比。
full行代表所有非idle任务同时阻塞于特定资源的时间占比。在这种状态下CPU资源
完全被浪费,相对于正常运行,业务负载由于耗费更多时间等待而受到严重影响。
由于此情况严重影响系统性能,因此清楚的识别本情况并与some行所代表的情况区分开,
将有助于分析及提升系统性能。这就是full独立于some行的原因。
avg代表阻塞时间占比(百分比),为最近10秒、60秒、300秒内的均值。这样我们
既可观察到短期事件的影响,也可看到中等及长时间内的趋势。total代表总阻塞
时间(单位微秒),可用于观察时延毛刺,这种毛刺可能在均值中无法体现。
监控压力门限
============
用户可注册触发器,通过poll()监控资源压力是否超过门限。
触发器定义:指定时间窗口期内累积阻塞时间的最大值。比如可定义500ms内积累
100ms阻塞,即触发一次唤醒事件。
触发器注册方法:用户打开代表特定资源的psi接口文件,写入门限、时间窗口的值。
所打开的文件描述符用于等待事件,可使用select()、poll()、epoll()。
写入信息的格式如下:
<some|full> <stall amount in us> <time window in us>
示例:向/proc/pressure/memory写入"some 150000 1000000"将新增触发器,将在
1秒内至少一个任务阻塞于内存的总时间超过150ms时触发。向/proc/pressure/io写入
"full 50000 1000000"将新增触发器,将在1秒内所有任务都阻塞于io的总时间超过50ms时触发。
触发器可针对多个psi度量值设置,同一个psi度量值可设置多个触发器。每个触发器需要
单独的文件描述符用于轮询,以区分于其他触发器。所以即使对于同一个psi接口文件,
每个触发器也需要单独的调用open()。
监控器在被监控资源进入阻塞状态时启动,在系统退出阻塞状态后停用。系统进入阻塞
状态后,监控psi增长的频率为每监控窗口刷新10次。
内核接受的窗口为500ms~10s,所以监控间隔为50ms~1s。设置窗口下限目的是为了
防止过于频繁的轮询。设置窗口上限的目的是因为窗口过长则无意义,此时查看
psi接口提供的均值即可。
监控器在激活后,至少在跟踪窗口期间将保持活动状态。以避免随着系统进入和退出
阻塞状态,监控器过于频繁的进入和退出活动状态。
用户态通知在监控窗口内会受到速率限制。当对应的文件描述符关闭,触发器会自动注销。
用户态监控器使用示例
====================
::
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h>
#include <string.h>
#include <unistd.h>
/* 监控内存部分阻塞,监控时间窗口为1秒、阻塞门限为150毫秒。*/
int main() {
const char trig[] = "some 150000 1000000";
struct pollfd fds;
int n;
fds.fd = open("/proc/pressure/memory", O_RDWR | O_NONBLOCK);
if (fds.fd < 0) {
printf("/proc/pressure/memory open error: %s\n",
strerror(errno));
return 1;
}
fds.events = POLLPRI;
if (write(fds.fd, trig, strlen(trig) + 1) < 0) {
printf("/proc/pressure/memory write error: %s\n",
strerror(errno));
return 1;
}
printf("waiting for events...\n");
while (1) {
n = poll(&fds, 1, -1);
if (n < 0) {
printf("poll error: %s\n", strerror(errno));
return 1;
}
if (fds.revents & POLLERR) {
printf("got POLLERR, event source is gone\n");
return 0;
}
if (fds.revents & POLLPRI) {
printf("event triggered!\n");
} else {
printf("unknown event received: 0x%x\n", fds.revents);
return 1;
}
}
return 0;
}
Cgroup2接口
===========
对于CONFIG_CGROUP=y及挂载了cgroup2文件系统的系统,能够获取cgroups内任务的psi。
此场景下cgroupfs挂载点的子目录包含cpu.pressure、memory.pressure、io.pressure文件,
内容格式与/proc/pressure/下的文件相同。
可设置基于cgroup的psi监控器,方法与系统级psi监控器相同。
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/core-api/cpu_hotplug.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
吴想成 Wu XiangCheng <bobwxc@email.cn>
.. _cn_core_api_cpu_hotplug:
=================
内核中的CPU热拔插
=================
:时间: 2016年12月
:作者: Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Rusty Russell <rusty@rustcorp.com.au>,
Srivatsa Vaddagiri <vatsa@in.ibm.com>,
Ashok Raj <ashok.raj@intel.com>,
Joel Schopp <jschopp@austin.ibm.com>
简介
====
现代系统架构的演进已经在处理器中引入了先进的错误报告和纠正能力。有一些OEM也支
持可热拔插的NUMA(Non Uniform Memory Access,非统一内存访问)硬件,其中物理
节点的插入和移除需要支持CPU热插拔。
这样的进步要求内核可用的CPU被移除,要么是出于配置的原因,要么是出于RAS的目的,
以保持一个不需要的CPU不在系统执行路径。因此需要在Linux内核中支持CPU热拔插。
CPU热拔插支持的一个更新颖的用途是它在SMP的暂停恢复支持中的应用。双核和超线程支
持使得即使是笔记本电脑也能运行不支持这些方法的SMP内核。
命令行开关
==========
``maxcpus=n``
限制启动时的CPU为 *n* 个。例如,如果你有四个CPU,使用 ``maxcpus=2`` 将只能启
动两个。你可以选择稍后让其他CPU上线。
``nr_cpus=n``
限制内核将支持的CPU总量。如果这里提供的数量低于实际可用的CPU数量,那么其他CPU
以后就不能上线了。
``additional_cpus=n``
使用它来限制可热插拔的CPU。该选项设置
``cpu_possible_mask = cpu_present_mask + additional_cpus``
这个选项只限于IA64架构。
``possible_cpus=n``
这个选项设置 ``cpu_possible_mask`` 中的 ``possible_cpus`` 位。
这个选项只限于X86和S390架构。
``cpu0_hotplug``
允许关闭CPU0。
这个选项只限于X86架构。
CPU位图
=======
``cpu_possible_mask``
系统中可能可用CPU的位图。这是用来为per_cpu变量分配一些启动时的内存,这些变量
不会随着CPU的可用或移除而增加/减少。一旦在启动时的发现阶段被设置,该映射就是静态
的,也就是说,任何时候都不会增加或删除任何位。根据你的系统需求提前准确地调整它
可以节省一些启动时的内存。
``cpu_online_mask``
当前在线的所有CPU的位图。在一个CPU可用于内核调度并准备接收设备的中断后,它被
设置在 ``__cpu_up()`` 中。当使用 ``__cpu_disable()`` 关闭一个CPU时,它被清
空,在此之前,所有的操作系统服务包括中断都被迁移到另一个目标CPU。
``cpu_present_mask``
系统中当前存在的CPU的位图。它们并非全部在线。当物理热拔插被相关的子系统
(如ACPI)处理时,可以改变和添加新的位或从位图中删除,这取决于事件是
hot-add/hot-remove。目前还没有定死规定。典型的用法是在启动时启动拓扑结构,这时
热插拔被禁用。
你真的不需要操作任何系统的CPU映射。在大多数情况下,它们应该是只读的。当设置每个
CPU资源时,几乎总是使用 ``cpu_possible_mask`` 或 ``for_each_possible_cpu()``
来进行迭代。宏 ``for_each_cpu()`` 可以用来迭代一个自定义的CPU掩码。
不要使用 ``cpumask_t`` 以外的任何东西来表示CPU的位图。
使用CPU热拔插
=============
内核选项 *CONFIG_HOTPLUG_CPU* 需要被启用。它目前可用于多种架构,包括ARM、MIPS、
PowerPC和X86。配置是通过sysfs接口完成的::
$ ls -lh /sys/devices/system/cpu
total 0
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu0
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu1
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu2
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu3
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu4
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu5
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu6
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu7
drwxr-xr-x 2 root root 0 Dec 21 16:33 hotplug
-r--r--r-- 1 root root 4.0K Dec 21 16:33 offline
-r--r--r-- 1 root root 4.0K Dec 21 16:33 online
-r--r--r-- 1 root root 4.0K Dec 21 16:33 possible
-r--r--r-- 1 root root 4.0K Dec 21 16:33 present
文件 *offline* 、 *online* 、*possible* 、*present* 代表CPU掩码。每个CPU文件
夹包含一个 *online* 文件,控制逻辑上的开(1)和关(0)状态。要在逻辑上关闭CPU4::
$ echo 0 > /sys/devices/system/cpu/cpu4/online
smpboot: CPU 4 is now offline
一旦CPU被关闭,它将从 */proc/interrupts* 、*/proc/cpuinfo* 中被删除,也不应该
被 *top* 命令显示出来。要让CPU4重新上线::
$ echo 1 > /sys/devices/system/cpu/cpu4/online
smpboot: Booting Node 0 Processor 4 APIC 0x1
CPU又可以使用了。这应该对所有的CPU都有效。CPU0通常比较特殊,被排除在CPU热拔插之外。
在X86上,内核选项 *CONFIG_BOOTPARAM_HOTPLUG_CPU0* 必须被启用,以便能够关闭CPU0。
或者,可以使用内核命令选项 *cpu0_hotplug* 。CPU0的一些已知的依赖性:
* 从休眠/暂停中恢复。如果CPU0处于离线状态,休眠/暂停将失败。
* PIC中断。如果检测到PIC中断,CPU0就不能被移除。
如果你发现CPU0上有任何依赖性,请告知Fenghua Yu <fenghua.yu@intel.com>。
CPU的热拔插协作
===============
下线情况
--------
一旦CPU被逻辑关闭,注册的热插拔状态的清除回调将被调用,从 ``CPUHP_ONLINE`` 开始,在
``CPUHP_OFFLINE`` 状态结束。这包括:
* 如果任务因暂停操作而被冻结,那么 *cpuhp_tasks_frozen* 将被设置为true。
* 所有进程都会从这个将要离线的CPU迁移到新的CPU上。新的CPU是从每个进程的当前cpuset中
选择的,它可能是所有在线CPU的一个子集。
* 所有针对这个CPU的中断都被迁移到新的CPU上。
* 计时器也会被迁移到新的CPU上。
* 一旦所有的服务被迁移,内核会调用一个特定的例程 ``__cpu_disable()`` 来进行特定的清
理。
使用热插拔API
-------------
一旦一个CPU下线或上线,就有可能收到通知。这对某些需要根据可用CPU数量执行某种设置或清
理功能的驱动程序来说可能很重要::
#include <linux/cpuhotplug.h>
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "X/Y:online",
Y_online, Y_prepare_down);
*X* 是子系统, *Y* 是特定的驱动程序。 *Y_online* 回调将在所有在线CPU的注册过程中被调用。
如果在线回调期间发生错误, *Y_prepare_down* 回调将在所有之前调用过在线回调的CPU上调
用。注册完成后,一旦有CPU上线, *Y_online* 回调将被调用,当CPU关闭时, *Y_prepare_down*
将被调用。所有之前在 *Y_online* 中分配的资源都应该在 *Y_prepare_down* 中释放。如果在
注册过程中发生错误,返回值 *ret* 为负值。否则会返回一个正值,其中包含动态分配状态
( *CPUHP_AP_ONLINE_DYN* )的分配热拔插。对于预定义的状态,它将返回0。
该回调可以通过调用 ``cpuhp_remove_state()`` 来删除。如果是动态分配的状态
( *CPUHP_AP_ONLINE_DYN* ),则使用返回的状态。在移除热插拔状态的过程中,将调用拆解回调。
多个实例
~~~~~~~~
如果一个驱动程序有多个实例,并且每个实例都需要独立执行回调,那么很可能应该使用
``multi-state`` 。首先需要注册一个多状态的状态::
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "X/Y:online,
Y_online, Y_prepare_down);
Y_hp_online = ret;
``cpuhp_setup_state_multi()`` 的行为与 ``cpuhp_setup_state()`` 类似,只是它
为多状态准备了回调,但不调用回调。这是一个一次性的设置。
一旦分配了一个新的实例,你需要注册这个新实例::
ret = cpuhp_state_add_instance(Y_hp_online, &d->node);
这个函数将把这个实例添加到你先前分配的 ``Y_hp_online`` 状态,并在所有在线的
CPU上调用先前注册的回调( ``Y_online`` )。 *node* 元素是你的每个实例数据结构
中的一个 ``struct hlist_node`` 成员。
在移除该实例时::
cpuhp_state_remove_instance(Y_hp_online, &d->node)
应该被调用,这将在所有在线CPU上调用拆分回调。
手动设置
~~~~~~~~
通常情况下,在注册或移除状态时调用setup和teamdown回调是很方便的,因为通常在CPU上线
(下线)和驱动的初始设置(关闭)时需要执行该操作。然而,每个注册和删除功能也有一个
_nocalls的后缀,如果不希望调用回调,则不调用所提供的回调。在手动设置(或关闭)期间,
应该使用 ``get_online_cpus()`` 和 ``put_online_cpus()`` 函数来抑制CPU热插拔操作。
事件的顺序
----------
热插拔状态被定义在 ``include/linux/cpuhotplug.h``:
* ``CPUHP_OFFLINE`` ... ``CPUHP_AP_OFFLINE`` 状态是在CPU启动前调用的。
* ``CPUHP_AP_OFFLINE`` ... ``CPUHP_AP_ONLINE`` 状态是在CPU被启动后被调用的。
中断是关闭的,调度程序还没有在这个CPU上活动。从 ``CPUHP_AP_OFFLINE`` 开始,
回调被调用到目标CPU上。
* ``CPUHP_AP_ONLINE_DYN`` 和 ``CPUHP_AP_ONLINE_DYN_END`` 之间的状态被保留
给动态分配。
* 这些状态在CPU关闭时以相反的顺序调用,从 ``CPUHP_ONLINE`` 开始,在 ``CPUHP_OFFLINE``
停止。这里的回调是在将被关闭的CPU上调用的,直到 ``CPUHP_AP_OFFLINE`` 。
通过 ``CPUHP_AP_ONLINE_DYN`` 动态分配的状态通常已经足够了。然而,如果在启动或关闭
期间需要更早的调用,那么应该获得一个显式状态。如果热拔插事件需要相对于另一个热拔插事
件的特定排序,也可能需要一个显式状态。
测试热拔插状态
==============
验证自定义状态是否按预期工作的一个方法是关闭一个CPU,然后再把它上线。也可以把CPU放到某
些状态(例如 ``CPUHP_AP_ONLINE`` ),然后再回到 ``CPUHP_ONLINE`` 。这将模拟在
``CPUHP_AP_ONLINE`` 之后的一个状态出现错误,从而导致回滚到在线状态。
所有注册的状态都被列举在 ``/sys/devices/system/cpu/hotplug/states`` ::
$ tail /sys/devices/system/cpu/hotplug/states
138: mm/vmscan:online
139: mm/vmstat:online
140: lib/percpu_cnt:online
141: acpi/cpu-drv:online
142: base/cacheinfo:online
143: virtio/net:online
144: x86/mce:online
145: printk:online
168: sched:active
169: online
要将CPU4回滚到 ``lib/percpu_cnt:online`` ,再回到在线状态,只需发出::
$ cat /sys/devices/system/cpu/cpu4/hotplug/state
169
$ echo 140 > /sys/devices/system/cpu/cpu4/hotplug/target
$ cat /sys/devices/system/cpu/cpu4/hotplug/state
140
需要注意的是,状态140的清除回调已经被调用。现在重新上线::
$ echo 169 > /sys/devices/system/cpu/cpu4/hotplug/target
$ cat /sys/devices/system/cpu/cpu4/hotplug/state
169
启用追踪事件后,单个步骤也是可见的::
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
bash-394 [001] 22.976: cpuhp_enter: cpu: 0004 target: 140 step: 169 (cpuhp_kick_ap_work)
cpuhp/4-31 [004] 22.977: cpuhp_enter: cpu: 0004 target: 140 step: 168 (sched_cpu_deactivate)
cpuhp/4-31 [004] 22.990: cpuhp_exit: cpu: 0004 state: 168 step: 168 ret: 0
cpuhp/4-31 [004] 22.991: cpuhp_enter: cpu: 0004 target: 140 step: 144 (mce_cpu_pre_down)
cpuhp/4-31 [004] 22.992: cpuhp_exit: cpu: 0004 state: 144 step: 144 ret: 0
cpuhp/4-31 [004] 22.993: cpuhp_multi_enter: cpu: 0004 target: 140 step: 143 (virtnet_cpu_down_prep)
cpuhp/4-31 [004] 22.994: cpuhp_exit: cpu: 0004 state: 143 step: 143 ret: 0
cpuhp/4-31 [004] 22.995: cpuhp_enter: cpu: 0004 target: 140 step: 142 (cacheinfo_cpu_pre_down)
cpuhp/4-31 [004] 22.996: cpuhp_exit: cpu: 0004 state: 142 step: 142 ret: 0
bash-394 [001] 22.997: cpuhp_exit: cpu: 0004 state: 140 step: 169 ret: 0
bash-394 [005] 95.540: cpuhp_enter: cpu: 0004 target: 169 step: 140 (cpuhp_kick_ap_work)
cpuhp/4-31 [004] 95.541: cpuhp_enter: cpu: 0004 target: 169 step: 141 (acpi_soft_cpu_online)
cpuhp/4-31 [004] 95.542: cpuhp_exit: cpu: 0004 state: 141 step: 141 ret: 0
cpuhp/4-31 [004] 95.543: cpuhp_enter: cpu: 0004 target: 169 step: 142 (cacheinfo_cpu_online)
cpuhp/4-31 [004] 95.544: cpuhp_exit: cpu: 0004 state: 142 step: 142 ret: 0
cpuhp/4-31 [004] 95.545: cpuhp_multi_enter: cpu: 0004 target: 169 step: 143 (virtnet_cpu_online)
cpuhp/4-31 [004] 95.546: cpuhp_exit: cpu: 0004 state: 143 step: 143 ret: 0
cpuhp/4-31 [004] 95.547: cpuhp_enter: cpu: 0004 target: 169 step: 144 (mce_cpu_online)
cpuhp/4-31 [004] 95.548: cpuhp_exit: cpu: 0004 state: 144 step: 144 ret: 0
cpuhp/4-31 [004] 95.549: cpuhp_enter: cpu: 0004 target: 169 step: 145 (console_cpu_notify)
cpuhp/4-31 [004] 95.550: cpuhp_exit: cpu: 0004 state: 145 step: 145 ret: 0
cpuhp/4-31 [004] 95.551: cpuhp_enter: cpu: 0004 target: 169 step: 168 (sched_cpu_activate)
cpuhp/4-31 [004] 95.552: cpuhp_exit: cpu: 0004 state: 168 step: 168 ret: 0
bash-394 [005] 95.553: cpuhp_exit: cpu: 0004 state: 169 step: 140 ret: 0
可以看到,CPU4一直下降到时间戳22.996,然后又上升到95.552。所有被调用的回调,
包括它们的返回代码都可以在跟踪中看到。
架构的要求
==========
需要具备以下功能和配置:
``CONFIG_HOTPLUG_CPU``
这个配置项需要在Kconfig中启用
``__cpu_up()``
调出一个cpu的架构接口
``__cpu_disable()``
关闭CPU的架构接口,在此程序返回后,内核不能再处理任何中断。这包括定时器的关闭。
``__cpu_die()``
这实际上是为了确保CPU的死亡。实际上,看看其他架构中实现CPU热拔插的一些示例代
码。对于那个特定的架构,处理器被从 ``idle()`` 循环中拿下来。 ``__cpu_die()``
通常会等待一些per_cpu状态的设置,以确保处理器的死亡例程被调用来保持活跃。
用户空间通知
============
在CPU成功上线或下线后,udev事件被发送。一个udev规则,比如::
SUBSYSTEM=="cpu", DRIVERS=="processor", DEVPATH=="/devices/system/cpu/*", RUN+="the_hotplug_receiver.sh"
将接收所有事件。一个像这样的脚本::
#!/bin/sh
if [ "${ACTION}" = "offline" ]
then
echo "CPU ${DEVPATH##*/} offline"
elif [ "${ACTION}" = "online" ]
then
echo "CPU ${DEVPATH##*/} online"
fi
可以进一步处理该事件。
内核内联文档参考
================
该API在以下内核代码中:
include/linux/cpuhotplug.h
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/core-api/genericirq.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
吴想成 Wu XiangCheng <bobwxc@email.cn>
.. include:: <isonum.txt>
.. _cn_core-api_genericirq:
================
Linux通用IRQ处理
================
:版权: |copy| 2005-2010: Thomas Gleixner
:版权: |copy| 2005-2006: Ingo Molnar
简介
====
通用中断处理层是为了给设备驱动程序提供一个完整的中断处理抽象(层)。它能够处
理所有不同类型的中断控制器硬件。设备驱动程序使用通用API函数来请求、启用、禁
用和释放中断。驱动程序不需要知道任何关于硬件处理中断的细节,所以它们可以在不同的
平台上使用而不需要修改代码。
本文档提供给那些希望在通用IRQ处理层的帮助下实现基于其架构的中断子系统的开发
者。
理论依据
========
Linux中中断处理的原始实现使用__do_IRQ()超级处理程序,它能够处理每种类型的
中断逻辑。
最初,Russell King确定了不同类型的处理程序,以便为Linux 2.5/2.6中的ARM中
断处理程序实现建立一个相当通用的集合。他区分了以下几种类型:
- 电平触发型
- 边沿触发型
- 简单型
在实现过程中,我们发现了另一种类型:
- 响应EOI(end of interrupt)型
在SMP的__do_IRQ()超级处理程序中,还需定义一种类型:
-  每cpu型(针对CPU SMP)
这种高层IRQ处理程序的拆分实现使我们能够为每个特定的中断类型优化中断处理的流
程。这减少了该特定代码路径的复杂性,并允许对特定类型进行优化处理。
最初的通用IRQ实现使用hw_interrupt_type结构体及其 ``->ack`` ``->end`` 等回
调来区分超级处理程序中的流控制。这导致了流逻辑和低级硬件逻辑的混合,也导致了
不必要的代码重复:例如i386中的 ``ioapic_level_irq`` 和 ``ioapic_edge_irq`` ,
这两个IRQ类型共享许多低级的细节,但有不同的流处理。
一个更自然的抽象是“irq流”和“芯片细节”的干净分离。
分析一些架构的IRQ子系统的实现可以发现,他们中的大多数可以使用一套通用的“irq
流”方法,只需要添加芯片级的特定代码。这种分离对于那些需要IRQ流本身而不需要芯
片细节的特定(子)架构也很有价值——以提供了一个更透明的IRQ子系统设计。
每个中断描述符都被分配给它自己的高层流程处理程序,这通常是一个通用的实现。(这
种高层次的流程处理程序的实现也使得提供解复用处理程序变得简单,这可以在各种架
构的嵌入式平台上找到。)
这种分离使得通用中断处理层更加灵活和可扩展。例如,一个(子)架构可以使用通用
的IRQ流实现“电平触发型”中断,并添加一个(子)架构特定的“边沿型”实现。
为了使向新模型的过渡更容易,并防止破坏现有实现,__do_IRQ()超级处理程序仍然
可用。这导致了一种暂时的双重性。随着时间的推移,新的模型应该在越来越多的架构中
被使用,因为它能使IRQ子系统更小更干净。它已经被废弃三年了,即将被删除。
已知的缺陷和假设
================
没有(但愿如此)。
抽象层
======
中断代码中主要有三个抽象层次:
1. 高级别的驱动API
2. 高级别的IRQ流处理器
3. 芯片级的硬件封装
中断控制流
----------
每个中断都由一个中断描述符结构体irq_desc来描述。中断是由一个“无符号整型”的数值来
引用的,它在描述符结构体数组中选择相应的中断描述符结构体。描述符结构体包含状态
信息和指向中断流方法和中断芯片结构的指针,这些都是分配给这个中断的。
每当中断触发时,低级架构代码通过调用desc->handle_irq()调用到通用中断代码中。
这个高层IRQ处理函数只使用由分配的芯片描述符结构体引用的desc->irq_data.chip
基元。
高级驱动程序API
---------------
高层驱动API由以下函数组成:
- request_irq()
- request_threaded_irq()
- free_irq()
- disable_irq()
- enable_irq()
- disable_irq_nosync() (SMP only)
- synchronize_irq() (SMP only)
- irq_set_irq_type()
- irq_set_irq_wake()
- irq_set_handler_data()
- irq_set_chip()
- irq_set_chip_data()
详见自动生成的函数文档。
.. note::
由于文档构建流程所限,中文文档中并没有引入自动生成的函数文档,所以请读者直接
阅读源码注释。
电平触发型IRQ流处理程序
-----------------------
通用层提供了一套预定义的irq-flow方法:
- handle_level_irq()
- handle_edge_irq()
- handle_fasteoi_irq()
- handle_simple_irq()
- handle_percpu_irq()
- handle_edge_eoi_irq()
- handle_bad_irq()
中断流处理程序(无论是预定义的还是架构特定的)由架构在启动期间或设备初始化期间分配给
特定中断。
默认流实现
~~~~~~~~~~
辅助函数
^^^^^^^^
辅助函数调用芯片基元,并被默认流实现所使用。以下是实现的辅助函数(简化摘录)::
default_enable(struct irq_data *data)
{
desc->irq_data.chip->irq_unmask(data);
}
default_disable(struct irq_data *data)
{
if (!delay_disable(data))
desc->irq_data.chip->irq_mask(data);
}
default_ack(struct irq_data *data)
{
chip->irq_ack(data);
}
default_mask_ack(struct irq_data *data)
{
if (chip->irq_mask_ack) {
chip->irq_mask_ack(data);
} else {
chip->irq_mask(data);
chip->irq_ack(data);
}
}
noop(struct irq_data *data))
{
}
默认流处理程序的实现
~~~~~~~~~~~~~~~~~~~~
电平触发型IRQ流处理器
^^^^^^^^^^^^^^^^^^^^^
handle_level_irq为电平触发型的中断提供了一个通用实现。
实现的控制流如下(简化摘录)::
desc->irq_data.chip->irq_mask_ack();
handle_irq_event(desc->action);
desc->irq_data.chip->irq_unmask();
默认的需回应IRQ流处理器
^^^^^^^^^^^^^^^^^^^^^^^
handle_fasteoi_irq为中断提供了一个通用的实现,它只需要在处理程序的末端有一个EOI。
实现的控制流如下(简化摘录)::
handle_irq_event(desc->action);
desc->irq_data.chip->irq_eoi();
默认的边沿触发型IRQ流处理器
^^^^^^^^^^^^^^^^^^^^^^^^^^^
handle_edge_irq为边沿触发型的中断提供了一个通用的实现。
实现的控制流如下(简化摘录)::
if (desc->status & running) {
desc->irq_data.chip->irq_mask_ack();
desc->status |= pending | masked;
return;
}
desc->irq_data.chip->irq_ack();
desc->status |= running;
do {
if (desc->status & masked)
desc->irq_data.chip->irq_unmask();
desc->status &= ~pending;
handle_irq_event(desc->action);
} while (status & pending);
desc->status &= ~running;
默认的简单型IRQ流处理器
^^^^^^^^^^^^^^^^^^^^^^^
handle_simple_irq提供了一个简单型中断的通用实现。
.. note::
简单型的流处理程序不调用任何处理程序/芯片基元。
实现的控制流程如下(简化摘录)::
handle_irq_event(desc->action);
默认的每CPU型流处理程序
^^^^^^^^^^^^^^^^^^^^^^^
handle_percpu_irq为每CPU型中断提供一个通用的实现。
每个CPU中断只在SMP上可用,该处理程序提供了一个没有锁的简化版本。
以下是控制流的实现(简化摘录)::
if (desc->irq_data.chip->irq_ack)
desc->irq_data.chip->irq_ack();
handle_irq_event(desc->action);
if (desc->irq_data.chip->irq_eoi)
desc->irq_data.chip->irq_eoi();
EOI边沿型IRQ流处理器
^^^^^^^^^^^^^^^^^^^^
handle_edge_eoi_irq提供了一个异常的边沿触发型处理程序,它只用于拯救powerpc/cell
上的一个严重失控的irq控制器。
坏的IRQ流处理器
^^^^^^^^^^^^^^^
handle_bad_irq用于处理没有真正分配处理程序的假中断。
特殊性和优化
~~~~~~~~~~~~
通用函数是为“干净”的架构和芯片设计的,它们没有平台特定的IRQ处理特殊性。如果一
个架构需要在“流”的层面上实现特殊性,那么它可以通过覆盖高层的IRQ-流处理程序来实
现。
延迟中断禁用
~~~~~~~~~~~~
每个中断可选择的功能是由Russell King在ARM中断实现中引入的,当调用disable_irq()
时,不会在硬件层面上屏蔽中断。中断保持启用状态,而在中断事件发生时在流处理器中被
屏蔽。这可以防止在硬件上丢失边沿中断,因为硬件上不存储边沿中断事件,而中断在硬件
级被禁用。当一个中断在IRQ_DISABLED标志被设置时到达,那么该中断在硬件层面被屏蔽,
IRQ_PENDING位被设置。当中断被enable_irq()重新启用时,将检查挂起位,如果它被设置,
中断将通过硬件或软件重发机制重新发送。(当你想使用延迟中断禁用功能,而你的硬件又不
能重新触发中断时,有必要启用CONFIG_HARDIRQS_SW_RESEND。) 延迟中断禁止功能是不可
配置的。
芯片级硬件封装
--------------
芯片级硬件描述符结构体 :c:type:`irq_chip` 包含了所有与芯片直接相关的功能,这些功
能可以被irq流实现所利用。
- ``irq_ack``
- ``irq_mask_ack`` - 可选的,建议使用的性能
- ``irq_mask``
- ``irq_unmask``
- ``irq_eoi`` - 可选的,EOI流处理程序需要
- ``irq_retrigger`` - 可选的
- ``irq_set_type`` - 可选的
- ``irq_set_wake`` - 可选的
这些基元的意思是严格意义上的:ack是指ACK,masking是指对IRQ线的屏蔽,等等。这取决
于流处理器如何使用这些基本的低级功能单元。
__do_IRQ入口点
==============
最初的实现__do_IRQ()是所有类型中断的替代入口点。它已经不存在了。
这个处理程序被证明不适合所有的中断硬件,因此被重新实现了边沿/级别/简单/超高速中断
的拆分功能。这不仅是一个功能优化。它也缩短了中断的代码路径。
在SMP上的锁
===========
芯片寄存器的锁定是由定义芯片基元的架构决定的。每个寄存器的结构通过desc->lock,由
通用层保护。
通用中断芯片
============
为了避免复制相同的IRQ芯片实现,核心提供了一个可配置的通用中断芯片实现。开发者在自
己实现相同的功能之前,应该仔细检查通用芯片是否符合他们的需求,并以稍微不同的方式实
现相同的功能。
该API在以下内核代码中:
kernel/irq/generic-chip.c
结构体
======
本章包含自动生成的结构体文档,这些结构体在通用IRQ层中使用。
该API在以下内核代码中:
include/linux/irq.h
include/linux/interrupt.h
提供的通用函数
==============
这一章包含了自动生成的内核API函数的文档,这些函数被导出。
该API在以下内核代码中:
kernel/irq/manage.c
kernel/irq/chip.c
提供的内部函数
==============
本章包含自动生成的内部函数的文档。
该API在以下内核代码中:
kernel/irq/irqdesc.c
kernel/irq/handle.c
kernel/irq/chip.c
鸣谢
====
感谢以下人士对本文档作出的贡献:
1. Thomas Gleixner tglx@linutronix.de
2. Ingo Molnar mingo@elte.hu
......@@ -80,14 +80,17 @@ Todolist:
:maxdepth: 1
cachetlb
cpu_hotplug
genericirq
memory-hotplug
protection-keys
Todolist:
cpu_hotplug
memory-hotplug
cpu_hotplug
genericirq
protection-keys
内存管理
......
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/core-api/memory_hotplug.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
吴想成 Wu XiangCheng <bobwxc@email.cn>
.. _cn_core-api_memory-hotplug:
==========
内存热插拔
==========
内存热拔插事件通知器
====================
热插拔事件被发送到一个通知队列中。
在 ``include/linux/memory.h`` 中定义了六种类型的通知:
MEM_GOING_ONLINE
在新内存可用之前生成,以便能够为子系统处理内存做准备。页面分配器仍然无法从新
的内存中进行分配。
MEM_CANCEL_ONLINE
如果MEM_GOING_ONLINE失败,则生成。
MEM_ONLINE
当内存成功上线时产生。回调可以从新的内存中分配页面。
MEM_GOING_OFFLINE
在开始对内存进行下线处理时生成。从内存中的分配不再可能,但是一些要下线的内存
仍然在使用。回调可以用来释放一个子系统在指定内存块中已知的内存。
MEM_CANCEL_OFFLINE
如果MEM_GOING_OFFLINE失败,则生成。来自我们试图离线的内存块中的内存又可以使
用了。
MEM_OFFLINE
在内存下线完成后生成。
可以通过调用如下函数来注册一个回调程序:
hotplug_memory_notifier(callback_func, priority)
优先级数值较高的回调函数在数值较低的回调函数之前被调用。
一个回调函数必须有以下原型::
int callback_func(
struct notifier_block *self, unsigned long action, void *arg);
回调函数的第一个参数(self)是指向回调函数本身的通知器链块的一个指针。第二个参
数(action)是上述的事件类型之一。第三个参数(arg)传递一个指向
memory_notify结构体的指针::
struct memory_notify {
unsigned long start_pfn;
unsigned long nr_pages;
int status_change_nid_normal;
int status_change_nid_high;
int status_change_nid;
}
- start_pfn是在线/离线内存的start_pfn。
- nr_pages是在线/离线内存的页数。
- status_change_nid_normal是当nodemask的N_NORMAL_MEMORY被设置/清除时设置节
点id,如果是-1,则nodemask状态不改变。
- status_change_nid_high是当nodemask的N_HIGH_MEMORY被设置/清除时设置的节点
id,如果这个值为-1,那么nodemask状态不会改变。
- status_change_nid是当nodemask的N_MEMORY被(将)设置/清除时设置的节点id。这
意味着一个新的(没上线的)节点通过联机获得新的内存,而一个节点失去了所有的内
存。如果这个值为-1,那么nodemask的状态就不会改变。
如果 status_changed_nid* >= 0,回调应该在必要时为节点创建/丢弃结构体。
回调程序应返回 ``include/linux/notifier.h`` 中定义的NOTIFY_DONE, NOTIFY_OK,
NOTIFY_BAD, NOTIFY_STOP中的一个值。
NOTIFY_DONE和NOTIFY_OK对进一步处理没有影响。
NOTIFY_BAD是作为对MEM_GOING_ONLINE、MEM_GOING_OFFLINE、MEM_ONLINE或MEM_OFFLINE
动作的回应,用于取消热插拔。它停止对通知队列的进一步处理。
NOTIFY_STOP停止对通知队列的进一步处理。
内部锁
======
当添加/删除使用内存块设备(即普通RAM)的内存时,device_hotplug_lock应该被保持
为:
- 针对在线/离线请求进行同步(例如,通过sysfs)。这样一来,内存块设备只有在内存
被完全添加后才能被用户空间访问(.online/.state属性)。而在删除内存时,我们知
道没有人在临界区。
- 与CPU热拔插或类似操作同步(例如ACPI和PPC相关操作)
特别是,在添加内存和用户空间试图以比预期更快的速度上线该内存时,有可能出现锁反转,
使用device_hotplug_lock可以避免此情况:
- device_online()将首先接受device_lock(),然后是mem_hotplug_lock。
- add_memory_resource()将首先使用mem_hotplug_lock,然后是device_lock()(在创
建设备时,在bus_add_device()期间)。
由于在使用device_lock()之前,设备对用户空间是可见的,这可能导致锁的反转。
内存的上线/下线应该通过device_online()/device_offline()完成————确保它与通过
sysfs进行的操作正确同步。建议持有device_hotplug_lock(例如,保护online_type)。
当添加/删除/上线/下线内存或者添加/删除异构或设备内存时,我们应该始终持有写模式的
mem_hotplug_lock,以序列化内存热插拔(例如访问全局/区域变量)。
此外,mem_hotplug_lock(与device_hotplug_lock相反)在读取模式下允许一个相当
有效的get_online_mems/put_online_mems实现,所以访问内存的代码可以防止该内存
消失。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/core-api/protection-keys.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
吴想成 Wu XiangCheng <bobwxc@email.cn>
.. _cn_core-api_protection-keys:
============
内存保护密钥
============
用户空间的内存保护密钥(Memory Protection Keys for Userspace,PKU,亦
即PKEYs)是英特尔Skylake(及以后)“可扩展处理器”服务器CPU上的一项功能。
它将在未来的非服务器英特尔处理器和未来的AMD处理器中可用。
对于任何希望测试或使用该功能的人来说,它在亚马逊的EC2 C5实例中是可用的,
并且已知可以在那里使用Ubuntu 17.04镜像运行。
内存保护密钥提供了一种机制来执行基于页面的保护,但在应用程序改变保护域
时不需要修改页表。它的工作原理是在每个页表项中为“保护密钥”分配4个以
前被忽略的位,从而提供16个可能的密钥。
还有一个新的用户可访问寄存器(PKRU),为每个密钥提供两个单独的位(访
问禁止和写入禁止)。作为一个CPU寄存器,PKRU在本质上是线程本地的,可能
会给每个线程提供一套不同于其他线程的保护措施。
有两条新指令(RDPKRU/WRPKRU)用于读取和写入新的寄存器。该功能仅在64位
模式下可用,尽管物理地址扩展页表中理论上有空间。这些权限只在数据访问上
强制执行,对指令获取没有影响。
系统调用
========
有3个系统调用可以直接与pkeys进行交互::
int pkey_alloc(unsigned long flags, unsigned long init_access_rights)
int pkey_free(int pkey);
int pkey_mprotect(unsigned long start, size_t len,
unsigned long prot, int pkey);
在使用一个pkey之前,必须先用pkey_alloc()分配它。一个应用程序直接调用
WRPKRU指令,以改变一个密钥覆盖的内存的访问权限。在这个例子中,WRPKRU
被一个叫做pkey_set()的C函数所封装::
int real_prot = PROT_READ|PROT_WRITE;
pkey = pkey_alloc(0, PKEY_DISABLE_WRITE);
ptr = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
ret = pkey_mprotect(ptr, PAGE_SIZE, real_prot, pkey);
... application runs here
现在,如果应用程序需要更新'ptr'处的数据,它可以获得访问权,进行更新,
然后取消其写访问权::
pkey_set(pkey, 0); // clear PKEY_DISABLE_WRITE
*ptr = foo; // assign something
pkey_set(pkey, PKEY_DISABLE_WRITE); // set PKEY_DISABLE_WRITE again
现在,当它释放内存时,它也将释放pkey,因为它不再被使用了::
munmap(ptr, PAGE_SIZE);
pkey_free(pkey);
.. note:: pkey_set()是RDPKRU和WRPKRU指令的一个封装器。在tools/testing/selftests/x86/protection_keys.c中可以找到一个实现实例。
tools/testing/selftests/x86/protection_keys.c.
行为
====
内核试图使保护密钥与普通的mprotect()的行为一致。例如,如果你这样做::
mprotect(ptr, size, PROT_NONE);
something(ptr);
这样做的时候,你可以期待保护密钥的相同效果::
pkey = pkey_alloc(0, PKEY_DISABLE_WRITE | PKEY_DISABLE_READ);
pkey_mprotect(ptr, size, PROT_READ|PROT_WRITE, pkey);
something(ptr);
无论something()是否是对'ptr'的直接访问,这都应该为真。
如::
*ptr = foo;
或者当内核代表应用程序进行访问时,比如read()::
read(fd, ptr, 1);
在这两种情况下,内核都会发送一个SIGSEGV,但当违反保护密钥时,si_code
将被设置为SEGV_PKERR,而当违反普通的mprotect()权限时,则是SEGV_ACCERR。
......@@ -11,6 +11,9 @@
目前这些文档已经整理在一起,不需要再花费额外的精力。
欢迎任何补丁。
有关测试专用工具的简要概述,参见
Documentation/translations/zh_CN/dev-tools/testing-overview.rst
.. class:: toc-title
目录
......@@ -18,6 +21,7 @@
.. toctree::
:maxdepth: 2
testing-overview
gcov
kasan
......@@ -29,6 +33,7 @@ Todolist:
- ubsan
- kmemleak
- kcsan
- kfence
- gdb-kernel-debugging
- kgdb
- kselftest
......
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/dev-tools/testing-overview.rst
:Translator: 胡皓文 Hu Haowen <src.res@email.cn>
============
内核测试指南
============
有许多不同的工具可以用于测试Linux内核,因此了解什么时候使用它们可能
很困难。本文档粗略概述了它们之间的区别,并阐释了它们是怎样糅合在一起
的。
编写和运行测试
==============
大多数内核测试都是用kselftest或KUnit框架之一编写的。它们都让运行测试
更加简化,并为编写新测试提供帮助。
如果你想验证内核的行为——尤其是内核的特定部分——那你就要使用kUnit或
kselftest。
KUnit和kselftest的区别
----------------------
.. note::
由于本文段中部分术语尚无较好的对应中文释义,可能导致与原文含义
存在些许差异,因此建议读者结合原文
(Documentation/dev-tools/testing-overview.rst)辅助阅读。
如对部分翻译有异议或有更好的翻译意见,欢迎联系译者进行修订。
KUnit(Documentation/dev-tools/kunit/index.rst)是用于“白箱”测
试的一个完整的内核内部系统:因为测试代码是内核的一部分,所以它能够访
问用户空间不能访问到的内部结构和功能。
因此,KUnit测试最好针对内核中较小的、自包含的部分,以便能够独立地测
试。“单元”测试的概念亦是如此。
比如,一个KUnit测试可能测试一个单独的内核功能(甚至通过一个函数测试
一个单一的代码路径,例如一个错误处理案例),而不是整个地测试一个特性。
这也使得KUnit测试构建和运行非常地快,从而能够作为开发流程的一部分被
频繁地运行。
有关更详细的介绍,请参阅KUnit测试代码风格指南
Documentation/dev-tools/kunit/style.rst
kselftest(Documentation/dev-tools/kselftest.rst),相对来说,大量用
于用户空间,并且通常测试用户空间的脚本或程序。
这使得编写复杂的测试,或者需要操作更多全局系统状态的测试更加容易(诸
如生成进程之类)。然而,从kselftest直接调用内核函数是不行的。这也就
意味着只有通过某种方式(如系统调用、驱动设备、文件系统等)导出到了用
户空间的内核功能才能使用kselftest来测试。为此,有些测试包含了一个伴
生的内核模块用于导出更多的信息和功能。不过,对于基本上或者完全在内核
中运行的测试,KUnit可能是更佳工具。
kselftest也因此非常适合于全部功能的测试,因为这些功能会将接口暴露到
用户空间,从而能够被测试,而不是展现实现细节。“system”测试和
“end-to-end”测试亦是如此。
比如,一个新的系统调用应该伴随有新的kselftest测试。
代码覆盖率工具
==============
支持两种不同代码之间的覆盖率测量工具。它们可以用来验证一项测试执行的
确切函数或代码行。这有助于决定内核被测试了多少,或用来查找合适的测试
中没有覆盖到的极端情况。
Documentation/translations/zh_CN/dev-tools/gcov.rst 是GCC的覆盖率测试
工具,能用于获取内核的全局或每个模块的覆盖率。与KCOV不同的是,这个工具
不记录每个任务的覆盖率。覆盖率数据可以通过debugfs读取,并通过常规的
gcov工具进行解释。
Documentation/dev-tools/kcov.rst 是能够构建在内核之中,用于在每个任务
的层面捕捉覆盖率的一个功能。因此,它对于模糊测试和关于代码执行期间信
息的其它情况非常有用,比如在一个单一系统调用里使用它就很有用。
动态分析工具
============
内核也支持许多动态分析工具,用以检测正在运行的内核中出现的多种类型的
问题。这些工具通常每个去寻找一类不同的缺陷,比如非法内存访问,数据竞
争等并发问题,或整型溢出等其他未定义行为。
如下所示:
* kmemleak检测可能的内存泄漏。参阅
Documentation/dev-tools/kmemleak.rst
* KASAN检测非法内存访问,如数组越界和释放后重用(UAF)。参阅
Documentation/dev-tools/kasan.rst
* UBSAN检测C标准中未定义的行为,如整型溢出。参阅
Documentation/dev-tools/ubsan.rst
* KCSAN检测数据竞争。参阅 Documentation/dev-tools/kcsan.rst
* KFENCE是一个低开销的内存问题检测器,比KASAN更快且能被用于批量构建。
参阅 Documentation/dev-tools/kfence.rst
* lockdep是一个锁定正确性检测器。参阅
Documentation/locking/lockdep-design.rst
* 除此以外,在内核中还有一些其它的调试工具,大多数能在
lib/Kconfig.debug 中找到。
这些工具倾向于对内核进行整体测试,并且不像kselftest和KUnit一样“传递”。
它们可以通过在启用这些工具时运行内核测试以与kselftest或KUnit结合起来:
之后你就能确保这些错误在测试过程中都不会发生了。
一些工具与KUnit和kselftest集成,并且在检测到问题时会自动打断测试。
......@@ -5,6 +5,7 @@
\renewcommand\thesection*
\renewcommand\thesubsection*
\kerneldocCJKon
\kerneldocBeginSC
.. _linux_doc_zh:
......@@ -17,6 +18,11 @@
**翻译计划:**
内核中文文档欢迎任何翻译投稿,特别是关于内核用户和管理员指南部分。
这是中文内核文档树的顶级目录。内核文档,就像内核本身一样,在很大程度上是一
项正在进行的工作;当我们努力将许多分散的文件整合成一个连贯的整体时尤其如此。
另外,随时欢迎您对内核文档进行改进;如果您想提供帮助,请加入vger.kernel.org
上的linux-doc邮件列表。
许可证文档
----------
......@@ -97,12 +103,14 @@ TODOList:
iio/index
sound/index
filesystems/index
virt/index
infiniband/index
accounting/index
TODOList:
* driver-api/index
* locking/index
* accounting/index
* block/index
* cdrom/index
* ide/index
......@@ -111,7 +119,6 @@ TODOList:
* hid/index
* i2c/index
* isdn/index
* infiniband/index
* leds/index
* netlabel/index
* networking/index
......@@ -122,7 +129,6 @@ TODOList:
* spi/index
* w1/index
* watchdog/index
* virt/index
* input/index
* hwmon/index
* gpu/index
......@@ -184,3 +190,7 @@ TODOList:
----------
* :ref:`genindex`
.. raw:: latex
\kerneldocEndSC
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/infiniband/core_locking.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
王普宇 Puyu Wang <realpuyuwang@gmail.com>
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_infiniband_core_locking:
==================
infiniband中间层锁
==================
本指南试图明确infiniband中间层的锁假设。它描述了对位于中间层以下的低
级驱动程序和使用中间层的上层协议的要求。
睡眠和中断环境
==============
除了以下异常情况,ib_device结构体中所有方法的低级驱动实现都可以睡眠。
这些异常情况是列表中的任意的方法:
- create_ah
- modify_ah
- query_ah
- destroy_ah
- post_send
- post_recv
- poll_cq
- req_notify_cq
他们可能不可以睡眠,而且必须可以从任何上下文中调用。
向上层协议使用者输出的相应函数:
- rdma_create_ah
- rdma_modify_ah
- rdma_query_ah
- rdma_destroy_ah
- ib_post_send
- ib_post_recv
- ib_req_notify_cq
因此,在任何情况下都可以安全调用(它们)。
此外,该函数
- ib_dispatch_event
被底层驱动用来通过中间层调度异步事件的“A”,也可以从任何上下文中安全调
用。
可重入性
--------
由低级驱动程序导出的ib_device结构体中的所有方法必须是完全可重入的。
即使使用同一对象的多个函数调用被同时运行,低级驱动程序也需要执行所有
必要的同步以保持一致性。
IB中间层不执行任何函数调用的序列化。
因为低级驱动程序是可重入的,所以不要求上层协议使用者任何顺序执行。然
而,为了得到合理的结果,可能需要一些顺序。例如,一个使用者可以在多个
CPU上同时安全地调用ib_poll_cq()。然而,不同的ib_poll_cq()调用之间
的工作完成信息的顺序没有被定义。
回调
----
低级驱动程序不得直接从与ib_device方法调用相同的调用链中执行回调。例
如,低级驱动程序不允许从post_send方法直接调用使用者的完成事件处理程
序。相反,低级驱动程序应该推迟这个回调,例如,调度一个tasklet来执行
这个回调。
低层驱动负责确保同一CQ的多个完成事件处理程序不被同时调用。驱动程序必
须保证一个给定的CQ的事件处理程序在同一时间只有一个在运行。换句话说,
以下情况是不允许的::
CPU1 CPU2
low-level driver ->
consumer CQ event callback:
/* ... */
ib_req_notify_cq(cq, ...);
low-level driver ->
/* ... */ consumer CQ event callback:
/* ... */
return from CQ event handler
完成事件和异步事件回调的运行环境没有被定义。 根据低级别的驱动程序,它可能是
进程上下文、softirq上下文或中断上下文。上层协议使用者可能不会在回调中睡眠。
热插拔
------
当一个低级驱动程序调用ib_register_device()时,它宣布一个设备已经
准备好供使用者使用,所有的初始化必须在这个调用之前完成。设备必须保
持可用,直到驱动对ib_unregister_device()的调用返回。
低级驱动程序必须从进程上下文调用ib_register_device()和
ib_unregister_device()。如果使用者在这些调用中回调到驱动程序,它
不能持有任何可能导致死锁的semaphores。
一旦其结构体ib_client的add方法被调用,上层协议使用者就可以开始使用
一个IB设备。使用者必须在从移除方法返回之前完成所有的清理工作并释放
与设备相关的所有资源。
使用者被允许在其添加和删除方法中睡眠。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/infiniband/index.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
王普宇 Puyu Wang <realpuyuwang@gmail.com>
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_infiniband_index:
==========
infiniband
==========
.. toctree::
:maxdepth: 1
core_locking
ipoib
opa_vnic
sysfs
tag_matching
user_mad
user_verbs
.. only:: subproject and html
Indices
=======
* :ref:`genindex`
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/infiniband/ipoib.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
王普宇 Puyu Wang <realpuyuwang@gmail.com>
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_infiniband_ipoib:
=========================
infiniband上的IP(IPoIB)
=========================
ib_ipoib驱动是IETF ipoib工作组发布的RFC 4391和4392所规定的
infiniband上IP协议的一个实现。它是一个“本地”实现,即把接口类型设置为
ARPHRD_INFINIBAND,硬件地址长度为20(早期的专有实现向内核伪装为以太网
接口)。
分区和P_Keys
============
当IPoIB驱动被加载时,它会使用索引为0的P_Key给每个端口创建一个接口。要用
不同的P_Key创建一个接口,将所需的P_Key写入主接口的
/sys/class/net/<intf name>/create_child文件里面。比如说::
echo 0x8001 > /sys/class/net/ib0/create_child
这将用P_Key 0x8001创建一个名为ib0.8001的接口。要删除一个子接口,使用
``delete_child`` 文件::
echo 0x8001 > /sys/class/net/ib0/delete_child
任何接口的P_Key都由“pkey”文件给出,而子接口的主接口在“parent”中。
子接口的创建/删除也可以使用IPoIB的rtnl_link_ops来完成,使用两种
方式创建的子接口的行为是一样的。
数据报与连接模式
================
IPoIB驱动支持两种操作模式:数据报和连接。模式是通过接口的
/sys/class/net/<intf name>/mode文件设置和读取的。
在数据报模式下,使用IB UD(不可靠数据报)传输,因此接口MTU等于IB L2 MTU
减去IPoIB封装头(4字节)。例如,在一个典型的具有2K MTU的IB结构中,IPoIB
MTU将是2048 - 4 = 2044字节。
在连接模式下,使用IB RC(可靠的连接)传输。连接模式利用IB传输的连接特性,
允许MTU达到最大的IP包大小64K,这减少了处理大型UDP数据包、TCP段等所需的
IP包数量,提高了大型信息的性能。
在连接模式下,接口的UD QP仍被用于组播和与不支持连接模式的对等体的通信。
在这种情况下,ICMP PMTU数据包的RX仿真被用来使网络堆栈对这些邻居使用较
小的UD MTU。
无状态卸载
==========
如果IB HW支持IPoIB无状态卸载,IPoIB会向网络堆栈广播TCP/IP校验和/或大量
传送(LSO)负载转移能力。
大量传送(LSO)负载转移也已实现,可以使用ethtool调用打开/关闭。目前,LRO
只支持具有校验和卸载能力的设备。
无状态卸载只在数据报模式下支持。
中断管理
========
如果底层IB设备支持CQ事件管理,可以使用ethtool来设置中断缓解参数,从而减少
处理中断产生的开销。IPoIB的主要代码路径不使用TX完成信号的事件,所以只支持
RX管理。
调试信息
========
通过将CONFIG_INFINIBAND_IPOIB_DEBUG设置为“y”来编译IPoIB驱动,跟踪信
息被编译到驱动中。通过将模块参数debug_level和mcast_debug_level设置为1来
打开它们。这些参数可以在运行时通过/sys/module/ib_ipoib/的文件来控制。
CONFIG_INFINIBAND_IPOIB_DEBUG也启用debugfs虚拟文件系统中的文件。通过挂
载这个文件系统,例如用::
mount -t debugfs none /sys/kernel/debug
可以从/sys/kernel/debug/ipoib/ib0_mcg等文件中获得关于多播组的统计数据。
这个选项对性能的影响可以忽略不计,所以在正常运行时,在debug_level设置为
0的情况下启用这个选项是安全的。
CONFIG_INFINIBAND_IPOIB_DEBUG_DATA当data_debug_level设置为1时,可以
在数据路径中启用更多的调试输出。 然而,即使禁用输出,启用这个配置选项也
会影响性能,因为它在快速路径中增加了测试。
引用
====
在InfiniBand上传输IP(IPoIB)(RFC 4391)。
http://ietf.org/rfc/rfc4391.txt
infiniband上的IP:上的IP架构(RFC 4392)。
http://ietf.org/rfc/rfc4392.txt
infiniband上的IP: 连接模式 (RFC 4755)
http://ietf.org/rfc/rfc4755.txt
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/infiniband/opa_vnic.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
王普宇 Puyu Wang <realpuyuwang@gmail.com>
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_infiniband_opa_vnic:
=============================================
英特尔全路径(OPA)虚拟网络接口控制器(VNIC)
=============================================
英特尔全路径(OPA)虚拟网络接口控制器(VNIC)功能通过封装HFI节点之间的以
太网数据包,支持Omni-Path结构上的以太网功能。
体系结构
========
Omni-Path封装的以太网数据包的交换模式涉及Omni-Path结构拓扑上覆盖的一个或
多个虚拟以太网交换机。Omni-Path结构上的HFI节点的一个子集被允许在特定的虚
拟以太网交换机上交换封装的以太网数据包。虚拟以太网交换机是通过配置结构上的
HFI节点实现的逻辑抽象,用于生成和处理报头。在最简单的配置中,整个结构的所有
HFI节点通过一个虚拟以太网交换机交换封装的以太网数据包。一个虚拟以太网交换机,
实际上是一个独立的以太网网络。该配置由以太网管理器(EM)执行,它是可信的结
构管理器(FM)应用程序的一部分。HFI节点可以有多个VNIC,每个连接到不同的虚
拟以太网交换机。下图介绍了两个虚拟以太网交换机与两个HFI节点的情况::
+-------------------+
| 子网/ |
| 以太网 |
| 管理 |
+-------------------+
/ /
/ /
/ /
/ /
+-----------------------------+ +------------------------------+
| 虚拟以太网切换 | | 虚拟以太网切换 |
| +---------+ +---------+ | | +---------+ +---------+ |
| | VPORT | | VPORT | | | | VPORT | | VPORT | |
+--+---------+----+---------+-+ +-+---------+----+---------+---+
| \ / |
| \ / |
| \/ |
| / \ |
| / \ |
+-----------+------------+ +-----------+------------+
| VNIC | VNIC | | VNIC | VNIC |
+-----------+------------+ +-----------+------------+
| HFI | | HFI |
+------------------------+ +------------------------+
Omni-Path封装的以太网数据包格式如下所述。
==================== ================================
位 域
==================== ================================
Quad Word 0:
0-19 SLID (低20位)
20-30 长度 (以四字为单位)
31 BECN 位
32-51 DLID (低20位)
52-56 SC (服务级别)
57-59 RC (路由控制)
60 FECN 位
61-62 L2 (=10, 16B 格式)
63 LT (=1, 链路传输头 Flit)
Quad Word 1:
0-7 L4 type (=0x78 ETHERNET)
8-11 SLID[23:20]
12-15 DLID[23:20]
16-31 PKEY
32-47 熵
48-63 保留
Quad Word 2:
0-15 保留
16-31 L4 头
32-63 以太网数据包
Quad Words 3 to N-1:
0-63 以太网数据包 (pad拓展)
Quad Word N (last):
0-23 以太网数据包 (pad拓展)
24-55 ICRC
56-61 尾
62-63 LT (=01, 链路传输尾 Flit)
==================== ================================
以太网数据包在传输端被填充,以确保VNIC OPA数据包是四字对齐的。“尾”字段
包含填充的字节数。在接收端,“尾”字段被读取,在将数据包向上传递到网络堆
栈之前,填充物被移除(与ICRC、尾和OPA头一起)。
L4头字段包含VNIC端口所属的虚拟以太网交换机ID。在接收端,该字段用于将收
到的VNIC数据包去多路复用到不同的VNIC端口。
驱动设计
========
英特尔OPA VNIC的软件设计如下图所示。OPA VNIC功能有一个依赖于硬件的部分
和一个独立于硬件的部分。
对IB设备分配和释放RDMA netdev设备的支持已经被加入。RDMA netdev支持与
网络堆栈的对接,从而创建标准的网络接口。OPA_VNIC是一个RDMA netdev设备
类型。
依赖于HW的VNIC功能是HFI1驱动的一部分。它实现了分配和释放OPA_VNIC RDMA
netdev的动作。它涉及VNIC功能的HW资源分配/管理。它与网络堆栈接口并实现所
需的net_device_ops功能。它在传输路径中期待Omni-Path封装的以太网数据包,
并提供对它们的HW访问。在将数据包向上传递到网络堆栈之前,它把Omni-Path头
从接收的数据包中剥离。它还实现了RDMA netdev控制操作。
OPA VNIC模块实现了独立于硬件的VNIC功能。它由两部分组成。VNIC以太网管理
代理(VEMA)作为一个IB客户端向IB核心注册,并与IB MAD栈接口。它与以太网
管理器(EM)和VNIC netdev交换管理信息。VNIC netdev部分分配和释放OPA_VNIC
RDMA netdev设备。它在需要时覆盖由依赖HW的VNIC驱动设置的net_device_ops函数,
以适应任何控制操作。它还处理以太网数据包的封装,在传输路径中使用Omni-Path头。
对于每个VNIC接口,封装所需的信息是由EM通过VEMA MAD接口配置的。它还通过调用
RDMA netdev控制操作将任何控制信息传递给依赖于HW的驱动程序::
+-------------------+ +----------------------+
| | | Linux |
| IB MAD | | 网络 |
| | | 栈 |
+-------------------+ +----------------------+
| | |
| | |
+----------------------------+ |
| | |
| OPA VNIC 模块 | |
| (OPA VNIC RDMA Netdev | |
| & EMA 函数) | |
| | |
+----------------------------+ |
| |
| |
+------------------+ |
| IB 核心 | |
+------------------+ |
| |
| |
+--------------------------------------------+
| |
| HFI1 驱动和 VNIC 支持 |
| |
+--------------------------------------------+
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/infiniband/sysfs.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
王普宇 Puyu Wang <realpuyuwang@gmail.com>
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_infiniband_sysfs:
=========
Sysfs文件
=========
sysfs接口已移至
Documentation/ABI/stable/sysfs-class-infiniband.
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/infiniband/tag_matching.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
王普宇 Puyu Wang <realpuyuwang@gmail.com>
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_infiniband_tag_matching:
============
标签匹配逻辑
============
MPI标准定义了一套规则,称为标签匹配,用于将源发送操作与目的接收匹配。以下参数必
须与以下源和目的参数相匹配:
* 沟通者
* 用户标签--通配符(wild card)可由接收方指定
* 来源等级--通配符可由接收方指定
* 目的地等级 – wild
排序规则要求,当一对以上的发送和接收消息信封可能匹配时,包括最早发布-发送和最早
发布-接收的一对是必须用来满足匹配操作的一对。然而,这并不意味着标签是按照它们被
创建的顺序消耗的,例如,如果早期的标签不能用来满足匹配规则,那么后来生成的标签
可能被消耗。
当消息从发送方发送到接收方时,通信库可能试图在相应的匹配接收被发布之后或之前处
理该操作。如果匹配的接收被发布,这就是一个预期的消息,否则就被称为一个意外的消
息。实现时经常为这两种不同的匹配实例使用不同的匹配方案。
为了减少MPI库的内存占用,MPI实现通常使用两种不同的协议来实现这一目的:
1. Eager协议--当发送方处理完发送时,完整的信息就会被发送。在send_cq中会收到
一个完成发送的通知,通知缓冲区可以被重新使用。
2. Rendezvous协议--发送方在第一次通知接收方时发送标签匹配头,也许还有一部分
数据。当相应的缓冲区被发布时,响应者将使用头中的信息,直接向匹配的缓冲区发起
RDMA读取操作。为了使缓冲区得到重用,需要收到一个fin消息。
标签匹配的实现
==============
使用的匹配对象有两种类型,即发布的接收列表和意外消息列表。应用程序通过调用发布
的接收列表中的MPI接收例程发布接收缓冲区,并使用MPI发送例程发布发送消息。发布的
接收列表的头部可以由硬件来维护,而软件则要对这个列表进行跟踪。
当发送开始并到达接收端时,如果没有为这个到达的消息预先发布接收,它将被传递给软
件并被放在意外(unexpect)消息列表中。否则,将对该匹配进行处理,包括交会处理,
如果合适的话,将数据传送到指定的接收缓冲区。这允许接收方MPI标签匹配与计算重叠。
当一个接收信息被发布时,通信库将首先检查软件的意外信息列表,以寻找一个匹配的接
收信息。如果找到一个匹配的,数据就会被送到用户缓冲区,使用一个软件控制的协议。
UCX的实现根据数据大小,使用急切或交会协议。如果没有找到匹配,整个预置的接收列
表由硬件维护,并且有空间在这个列表中增加一个预置的接收,这个接收被传递给硬件。
软件要对这个列表进行跟踪,以帮助处理MPI取消操作。此外,由于硬件和软件在标签匹
配操作方面预计不会紧密同步,这个影子列表被用来检测预先发布的接收被传递到硬件的
情况,因为匹配的意外消息正在从硬件传递到软件。
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/infiniband/user_mad.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
王普宇 Puyu Wang <realpuyuwang@gmail.com>
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_infiniband_user_mad:
===============
用户空间MAD访问
===============
设备文件
========
每个InfiniBand设备的每个端口都有一个“umad”设备和一个“issm”设备连接。
例如,一个双端口的HCA将有两个umad设备和两个issm设备,而一个交换机将
有每个类型的一个设备(对于交换机端口0)。
创建MAD代理
===========
一个MAD代理可以通过填写一个结构体ib_user_mad_reg_req来创建,然后在
适当的设备文件的文件描述符上调用IB_USER_MAD_REGISTER_AGENT ioctl。
如果注册请求成功,结构体中会返回一个32位的ID。比如说::
struct ib_user_mad_reg_req req = { /* ... */ };
ret = ioctl(fd, IB_USER_MAD_REGISTER_AGENT, (char *) &req);
if (!ret)
my_agent = req.id;
else
perror("agent register");
代理可以通过IB_USER_MAD_UNREGISTER_AGENT ioctl取消注册。另外,所有
通过文件描述符注册的代理在描述符关闭时将被取消注册。
2014
现在提供了一个新的注册IOctl,允许在注册时提供额外的字段。这个注册
调用的用户隐含了对pkey_index的使用(见下文)。现在提供了一个新的
注册IOctl,允许在注册时提供额外的字段。这个注册调用的用户隐含了对
pkey_index的使用(见下文)。
接收MADs
========
使用read()接收MAD。现在接收端支持RMPP。传给read()的缓冲区必须至少是
一个struct ib_user_mad + 256字节。比如说:
如果传递的缓冲区不足以容纳收到的MAD(RMPP),errno被设置为ENOSPC,需
要的缓冲区长度被设置在mad.length中。
正常MAD(非RMPP)的读取示例::
struct ib_user_mad *mad;
mad = malloc(sizeof *mad + 256);
ret = read(fd, mad, sizeof *mad + 256);
if (ret != sizeof mad + 256) {
perror("read");
free(mad);
}
RMPP读取示例::
struct ib_user_mad *mad;
mad = malloc(sizeof *mad + 256);
ret = read(fd, mad, sizeof *mad + 256);
if (ret == -ENOSPC)) {
length = mad.length;
free(mad);
mad = malloc(sizeof *mad + length);
ret = read(fd, mad, sizeof *mad + length);
}
if (ret < 0) {
perror("read");
free(mad);
}
除了实际的MAD内容外,其他结构体ib_user_mad字段将被填入收到的MAD的信
息。例如,远程LID将在mad.lid中。
如果发送超时,将产生一个接收,mad.status设置为ETIMEDOUT。否则,当一个
MAD被成功接收后,mad.status将是0。
poll()/select()可以用来等待一个MAD可以被读取。
poll()/select()可以用来等待,直到可以读取一个MAD。
发送MADs
========
MADs是用write()发送的。发送的代理ID应该填入MAD的id字段,目的地LID应该
填入lid字段,以此类推。发送端确实支持RMPP,所以可以发送任意长度的MAD。
比如说::
struct ib_user_mad *mad;
mad = malloc(sizeof *mad + mad_length);
/* fill in mad->data */
mad->hdr.id = my_agent; /* req.id from agent registration */
mad->hdr.lid = my_dest; /* in network byte order... */
/* etc. */
ret = write(fd, &mad, sizeof *mad + mad_length);
if (ret != sizeof *mad + mad_length)
perror("write");
交换IDs
=======
umad设备的用户可以在发送的MAD中使用交换ID字段的低32位(也就是网络字节顺序中
最小有效的一半字段)来匹配请求/响应对。上面的32位是保留给内核使用的,在发送
MAD之前会被改写。
P_Key索引处理
=============
旧的ib_umad接口不允许为发送的MAD设置P_Key索引,也没有提供获取接收的MAD的
P_Key索引的方法。一个带有pkey_index成员的struct ib_user_mad_hdr的新布局已
经被定义;然而,为了保持与旧的应用程序的二进制兼容性,除非在文件描述符被用于
其他用途之前调用IB_USER_MAD_ENABLE_PKEY或IB_USER_MAD_REGISTER_AGENT2 ioctl
之一,否则不会使用这种新布局。
在2008年9月,IB_USER_MAD_ABI_VERSION将被增加到6,默认使用新的ib_user_mad_hdr
结构布局,并且IB_USER_MAD_ENABLE_PKEY ioctl将被删除。
设置IsSM功能位
==============
要为一个端口设置IsSM功能位,只需打开相应的issm设备文件。如果IsSM位已经被设置,那
么打开调用将阻塞,直到该位被清除(或者如果O_NONBLOCK标志被传递给open(),则立即返
回,errno设置为EAGAIN)。当issm文件被关闭时,IsSM位将被清除。在issm文件上不能进
行任何读、写或其他操作。
/dev文件
========
为了用 udev自动创建相应的字符设备文件,一个类似::
KERNEL=="umad*", NAME="infiniband/%k"
KERNEL=="issm*", NAME="infiniband/%k"
的规则可以被使用。它将创建节点的名字::
/dev/infiniband/umad0
/dev/infiniband/issm0
为第一个端口,以此类推。与这些设备相关的infiniband设备和端口可以从以下文件中确定::
/sys/class/infiniband_mad/umad0/ibdev
/sys/class/infiniband_mad/umad0/port
和::
/sys/class/infiniband_mad/issm0/ibdev
/sys/class/infiniband_mad/issm0/port
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/infiniband/user_verbs.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
王普宇 Puyu Wang <realpuyuwang@gmail.com>
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_infiniband_user_verbs:
=================
用户空间verbs访问
=================
ib_uverbs模块,通过启用CONFIG_INFINIBAND_USER_VERBS构建,使用户空间
通过“verbs”直接访问IB硬件,如InfiniBand架构规范第11章所述。
要使用verbs,需要libibverbs库,可从https://github.com/linux-rdma/rdma-core。
libibverbs包含一个独立于设备的API,用于使用ib_uverbs接口。libibverbs
还需要为你的InfiniBand硬件提供适当的独立于设备的内核和用户空间驱动。例如,
要使用Mellanox HCA,你需要安装ib_mthca内核模块和libmthca用户空间驱动。
用户-内核通信
=============
用户空间通过/dev/infiniband/uverbsN字符设备与内核进行慢速路径、资源管理
操作的通信。快速路径操作通常是通过直接写入硬件寄存器mmap()到用户空间来完成
的,没有系统调用或上下文切换到内核。
命令是通过在这些设备文件上的write()s发送给内核的。ABI在
drivers/infiniband/include/ib_user_verbs.h中定义。需要内核响应的命令的结
构包含一个64位字段,用来传递一个指向输出缓冲区的指针。状态作为write()系统调
用的返回值被返回到用户空间。
资源管理
========
由于所有IB资源的创建和销毁都是通过文件描述符传递的命令完成的,所以内核可以跟
踪那些被附加到给定用户空间上下文的资源。ib_uverbs模块维护着idr表,用来在
内核指针和不透明的用户空间句柄之间进行转换,这样内核指针就不会暴露给用户空间,
而用户空间也无法欺骗内核去跟踪一个假的指针。
这也允许内核在一个进程退出时进行清理,并防止一个进程触及另一个进程的资源。
内存固定
========
直接的用户空间I/O要求与作为潜在I/O目标的内存区域保持在同一物理地址上。ib_uverbs
模块通过get_user_pages()和put_page()调用来管理内存区域的固定和解除固定。它还核
算进程的pinned_vm中被固定的内存量,并检查非特权进程是否超过其RLIMIT_MEMLOCK限制。
被多次固定的页面在每次被固定时都会被计数,所以pinned_vm的值可能会高估一个进程所
固定的页面数量。
/dev文件
========
要想用udev自动创建适当的字符设备文件,可以采用如下规则::
KERNEL=="uverbs*", NAME="infiniband/%k"
可以使用。 这将创建设备节点,名为::
/dev/infiniband/uverbs0
等等。由于InfiniBand的用户空间verbs对于非特权进程来说应该是安全的,因此在udev规
则中加入适当的MODE或GROUP可能是有用的。
......@@ -268,8 +268,7 @@ C 程序员不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字
``count_active_users()`` 或者类似的名字,你不应该叫它 ``cntuser()`` 。
在函数名中包含函数类型 (所谓的匈牙利命名法) 是脑子出了问题——编译器知道那些类
型而且能够检查那些类型,这样做只能把程序员弄糊涂了。难怪微软总是制造出有问题
的程序。
型而且能够检查那些类型,这样做只能把程序员弄糊涂了。
本地变量名应该简短,而且能够表达相关的含义。如果你有一些随机的整数型的循环计
数器,它应该被称为 ``i`` 。叫它 ``loop_counter`` 并无益处,如果它没有被误解的
......
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../disclaimer-zh_CN.rst
:Original: Documentation/virt/acrn/cpuid.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_virt_acrn_cpuid:
==============
ACRN CPUID位域
==============
在ACRN超级管理器上运行的客户虚拟机可以使用CPUID检查其一些功能。
ACRN的cpuid函数是:
函数: 0x40000000
返回::
eax = 0x40000010
ebx = 0x4e524341
ecx = 0x4e524341
edx = 0x4e524341
注意,ebx,ecx和edx中的这个值对应于字符串“ACRNACRNACRN”。eax中的值对应于这个叶子
中存在的最大cpuid函数,如果将来有更多的函数加入,将被更新。
函数: define ACRN_CPUID_FEATURES (0x40000001)
返回::
ebx, ecx, edx
eax = an OR'ed group of (1 << flag)
其中 ``flag`` 的定义如下:
================================= =========== ================================
标志 值 描述
================================= =========== ================================
ACRN_FEATURE_PRIVILEGED_VM 0 客户虚拟机是一个有特权的虚拟机
================================= =========== ================================
函数: 0x40000010
返回::
ebx, ecx, edx
eax = (Virtual) TSC frequency in kHz.
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../disclaimer-zh_CN.rst
:Original: Documentation/virt/acrn/index.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_virt_acrn_index:
==============
ACRN超级管理器
==============
.. toctree::
:maxdepth: 1
introduction
io-request
cpuid
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../disclaimer-zh_CN.rst
:Original: Documentation/virt/acrn/introduction.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_virt_acrn_introduction:
ACRN超级管理器介绍
==================
ACRN超级管理器是一个第一类超级管理器,直接在裸机硬件上运行。它有一个特权管理虚拟机,称为服
务虚拟机,用于管理用户虚拟机和进行I/O仿真。
ACRN用户空间是一个运行在服务虚拟机中的应用程序,它根据命令行配置为用户虚拟机仿真设备。
ACRN管理程序服务模块(HSM)是服务虚拟机中的一个内核模块,为ACRN用户空间提供管理程序服
务。
下图展示了该架构。
::
服务端VM 用户端VM
+----------------------------+ | +------------------+
| +--------------+ | | | |
| |ACRN用户空间 | | | | |
| +--------------+ | | | |
|-----------------ioctl------| | | | ...
|内核空间 +----------+ | | | |
| | HSM | | | | 驱动 |
| +----------+ | | | |
+--------------------|-------+ | +------------------+
+---------------------hypercall----------------------------------------+
| ACRN超级管理器 |
+----------------------------------------------------------------------+
| 硬件 |
+----------------------------------------------------------------------+
ACRN用户空间为用户虚拟机分配内存,配置和初始化用户虚拟机使用的设备,加载虚拟引导程序,
初始化虚拟CPU状态,处理来自用户虚拟机的I/O请求访问。它使用ioctls来与HSM通信。HSM通过
与ACRN超级管理器的hypercalls进行交互来实现管理服务。HSM向用户空间输出一个char设备接口
(/dev/acrn_hsm)。
ACRN超级管理器是开源的,任何人都可以贡献。源码库在
https://github.com/projectacrn/acrn-hypervisor。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../disclaimer-zh_CN.rst
:Original: Documentation/virt/acrn/io-request.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_virt_acrn_io-request:
I/O请求处理
===========
客户虚拟机的I/O请求由超级管理器构建,由ACRN超级管理器服务模块分发到与I/O请求的地址范
围相对应的I/O客户端。I/O请求处理的细节将在以下章节描述。
1. I/O请求
----------
对于每个客户虚拟机,有一个共享的4KB字节的内存区域,用于超级管理器和服务虚拟机之间的
I/O请求通信。一个I/O请求是一个256字节的结构体缓冲区,它是 "acrn_io_request" 结构
体,当客户虚拟机中发生被困的I/O访问时,由超级管理器的I/O处理器填充。服务虚拟机中的
ACRN用户空间首先分配一个4KB字节的页面,并将缓冲区的GPA(客户物理地址)传递给管理平
台。缓冲区被用作16个I/O请求槽的数组,每个I/O请求槽为256字节。这个数组是按vCPU ID
索引的。
2. I/O客户端
------------
一个I/O客户端负责处理客户虚拟机的I/O请求,其访问的GPA在一定范围内。每个客户虚拟机
可以关联多个I/O客户端。每个客户虚拟机都有一个特殊的客户端,称为默认客户端,负责处理
所有不在其他客户端范围内的I/O请求。ACRN用户空间充当每个客户虚拟机的默认客户端。
下面的图示显示了I/O请求共享缓冲区、I/O请求和I/O客户端之间的关系。
::
+------------------------------------------------------+
| 服务VM |
|+--------------------------------------------------+ |
|| +----------------------------------------+ | |
|| | 共享页 ACRN用户空间 | | |
|| | +-----------------+ +------------+ | | |
|| +----+->| acrn_io_request |<-+ 默认 | | | |
|| | | | +-----------------+ | I/O客户端 | | | |
|| | | | | ... | +------------+ | | |
|| | | | +-----------------+ | | |
|| | +-|--------------------------------------+ | |
||---|----|-----------------------------------------| |
|| | | 内核 | |
|| | | +----------------------+ | |
|| | | | +-------------+ HSM | | |
|| | +--------------+ | | | |
|| | | | I/O客户端 | | | |
|| | | | | | | |
|| | | +-------------+ | | |
|| | +----------------------+ | |
|+---|----------------------------------------------+ |
+----|-------------------------------------------------+
|
+----|-------------------------------------------------+
| +-+-----------+ |
| | I/O处理 | ACRN超级管理器 |
| +-------------+ |
+------------------------------------------------------+
3. I/O请求状态转换
------------------
一个ACRN I/O请求的状态转换如下。
::
FREE -> PENDING -> PROCESSING -> COMPLETE -> FREE -> ...
- FREE: 这个I/O请求槽是空的
- PENDING: 在这个槽位上有一个有效的I/O请求正在等待
- PROCESSING: 正在处理I/O请求
- COMPLETE: 该I/O请求已被处理
处于COMPLETE或FREE状态的I/O请求是由超级管理器拥有的。HSM和ACRN用户空间负责处理其
他的。
4. I/O请求的处理流程
--------------------
a. 当客户虚拟机中发生被陷入的I/O访问时,超级管理器的I/O处理程序将把I/O请求填充为
PENDING状态。
b. 超级管理器向服务虚拟机发出一个向上调用,这是一个通知中断。
c. upcall处理程序会安排一个工作者来调度I/O请求。
d. 工作者寻找PENDING I/O请求,根据I/O访问的地址将其分配给不同的注册客户,将其
状态更新为PROCESSING,并通知相应的客户进行处理。
e. 被通知的客户端处理指定的I/O请求。
f. HSM将I/O请求状态更新为COMPLETE,并通过hypercalls通知超级管理器完成。
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/virt/guest-halt-polling.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_virt_guest-halt-polling:
========================================
客户机停机轮询机制(Guest halt polling)
========================================
cpuidle_haltpoll驱动,与haltpoll管理器一起,允许客户机vcpus在停机前轮询
一定的时间。
这为物理机侧的轮询提供了以下好处:
1) 在执行轮询时,POLL标志被设置,这允许远程vCPU在执行唤醒时避免发送
IPI(以及处理IPI的相关成本)。
2) 可以避免虚拟机退出的成本。
客户机侧轮询的缺点是,即使在物理机中的其他可运行任务中也会进行轮询。
其基本逻辑如下。一个全局值,即guest_halt_poll_ns,是由用户配置的,表示允
许轮询的最大时间量。这个值是固定的。
每个vcpu都有一个可调整的guest_halt_poll_ns("per-cpu guest_halt_poll_ns"),
它由算法响应事件进行调整(解释如下)。
模块参数
========
haltpoll管理器有5个可调整的模块参数:
1) guest_halt_poll_ns:
轮询停机前执行的最大时间,以纳秒为单位。
默认值: 200000
2) guest_halt_poll_shrink:
当唤醒事件发生在全局的guest_halt_poll_ns之后,用于缩减每个CPU的guest_halt_poll_ns
的划分系数。
默认值: 2
3) guest_halt_poll_grow:
当事件发生在per-cpu guest_halt_poll_ns之后但在global guest_halt_poll_ns之前,
用于增长per-cpu guest_halt_poll_ns的乘法系数。
默认值: 2
4) guest_halt_poll_grow_start:
在系统空闲的情况下,每个cpu guest_halt_poll_ns最终达到零。这个值设置了增长时的
初始每cpu guest_halt_poll_ns。这个值可以从10000开始增加,以避免在最初的增长阶
段出现失误。:
10k, 20k, 40k, ... (例如,假设guest_halt_poll_grow=2).
默认值: 50000
5) guest_halt_poll_allow_shrink:
允许缩减的Bool参数。设置为N以避免它(一旦达到全局的guest_halt_poll_ns值,每CPU的
guest_halt_poll_ns将保持高位)。
默认值: Y
模块参数可以从Debugfs文件中设置,在::
/sys/module/haltpoll/parameters/
进一步说明
==========
- 在设置guest_halt_poll_ns参数时应该小心,因为一个大的值有可能使几乎是完全空闲机
器上的cpu使用率达到100%。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/virt/index.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_virt_index:
===============
Linux虚拟化支持
===============
.. toctree::
:maxdepth: 2
paravirt_ops
guest-halt-polling
ne_overview
acrn/index
TODOLIST:
kvm/index
uml/user_mode_linux_howto_v2
.. only:: html and subproject
Indices
=======
* :ref:`genindex`
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/virt/ne_overview.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_virt_ne_overview:
==============
Nitro Enclaves
==============
概述
====
Nitro Enclaves(NE)是亚马逊弹性计算云(EC2)的一项新功能,允许客户在EC2实
例中划分出孤立的计算环境[1]。
例如,一个处理敏感数据并在虚拟机中运行的应用程序,可以与在同一虚拟机中运行的
其他应用程序分开。然后,这个应用程序在一个独立于主虚拟机的虚拟机中运行,即
enclave。
一个enclave与催生它的虚拟机一起运行。这种设置符合低延迟应用的需要。为enclave
分配的资源,如内存和CPU,是从主虚拟机中分割出来的。每个enclave都被映射到一
个运行在主虚拟机中的进程,该进程通过一个ioctl接口与NE驱动进行通信。
在这个意义上,有两个组成部分。
1. 一个enclave抽象进程——一个运行在主虚拟机客体中的用户空间进程,它使用NE驱动
提供的ioctl接口来生成一个enclave虚拟机(这就是下面的2)。
有一个NE模拟的PCI设备暴露给主虚拟机。这个新的PCI设备的驱动被包含在NE驱动中。
ioctl逻辑被映射到PCI设备命令,例如,NE_START_ENCLAVE ioctl映射到一个enclave
启动PCI命令。然后,PCI设备命令被翻译成在管理程序方面采取的行动;也就是在运
行主虚拟机的主机上运行的Nitro管理程序。Nitro管理程序是基于KVM核心技术的。
2. enclave本身——一个运行在与催生它的主虚拟机相同的主机上的虚拟机。内存和CPU
从主虚拟机中分割出来,专门用于enclave虚拟机。enclave没有连接持久性存储。
从主虚拟机中分割出来并给enclave的内存区域需要对齐2 MiB/1 GiB物理连续的内存
区域(或这个大小的倍数,如8 MiB)。该内存可以通过使用hugetlbfs从用户空间分
配[2][3]。一个enclave的内存大小需要至少64 MiB。enclave内存和CPU需要来自同
一个NUMA节点。
一个enclave在专用的核心上运行。CPU 0及其同级别的CPU需要保持对主虚拟机的可用
性。CPU池必须由具有管理能力的用户为NE目的进行设置。关于CPU池的格式,请看内核
文档[4]中的cpu list部分。
enclave通过本地通信通道与主虚拟机进行通信,使用virtio-vsock[5]。主虚拟机有
virtio-pci vsock模拟设备,而飞地虚拟机有virtio-mmio vsock模拟设备。vsock
设备使用eventfd作为信令。enclave虚拟机看到通常的接口——本地APIC和IOAPIC——从
virtio-vsock设备获得中断。virtio-mmio设备被放置在典型的4 GiB以下的内存中。
在enclave中运行的应用程序需要和将在enclave虚拟机中运行的操作系统(如内核、
ramdisk、init)一起被打包到enclave镜像中。enclave虚拟机有自己的内核并遵循标
准的Linux启动协议[6]。
内核bzImage、内核命令行、ramdisk(s)是enclave镜像格式(EIF)的一部分;另外
还有一个EIF头,包括元数据,如magic number、eif版本、镜像大小和CRC。
哈希值是为整个enclave镜像(EIF)、内核和ramdisk(s)计算的。例如,这被用来检
查在enclave虚拟机中加载的enclave镜像是否是打算运行的那个。
这些加密测量包括在由Nitro超级管理器成的签名证明文件中,并进一步用来证明enclave
的身份;KMS是NE集成的服务的一个例子,它检查证明文件。
enclave镜像(EIF)被加载到enclave内存中,偏移量为8 MiB。enclave中的初始进程
连接到主虚拟机的vsock CID和一个预定义的端口--9000,以发送一个心跳值--0xb7。这
个机制用于在主虚拟机中检查enclave是否已经启动。主虚拟机的CID是3。
如果enclave虚拟机崩溃或优雅地退出,NE驱动会收到一个中断事件。这个事件会通过轮询
通知机制进一步发送到运行在主虚拟机中的用户空间enclave进程。然后,用户空间enclave
进程就可以退出了。
[1] https://aws.amazon.com/ec2/nitro/nitro-enclaves/
[2] https://www.kernel.org/doc/html/latest/admin-guide/mm/hugetlbpage.html
[3] https://lwn.net/Articles/807108/
[4] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
[5] https://man7.org/linux/man-pages/man7/vsock.7.html
[6] https://www.kernel.org/doc/html/latest/x86/boot.html
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/virt/paravirt_ops.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
陈飞杨 Feiyang Chen <chenfeiyang@loongson.cn>
时奎亮 Alex Shi <alexs@kernel.org>
.. _cn_virt_paravirt_ops:
============
半虚拟化操作
============
Linux提供了对不同管理程序虚拟化技术的支持。历史上,为了支持不同的虚拟机超级管理器
(hypervisor,下文简称超级管理器),需要不同的二进制内核,这个限制已经被pv_ops移
除了。Linux pv_ops是一个虚拟化API,它能够支持不同的管理程序。它允许每个管理程序
优先于关键操作,并允许单一的内核二进制文件在所有支持的执行环境中运行,包括本机——没
有任何管理程序。
pv_ops提供了一组函数指针,代表了与低级关键指令和各领域高级功能相对应的操作。
pv-ops允许在运行时进行优化,在启动时对低级关键操作进行二进制修补。
pv_ops操作被分为三类:
- 简单的间接调用
这些操作对应于高水平的函数,众所周知,间接调用的开销并不十分重要。
- 间接调用,允许用二进制补丁进行优化
通常情况下,这些操作对应于低级别的关键指令。它们被频繁地调用,并且是对性能关
键。开销是非常重要的。
- 一套用于手写汇编代码的宏程序
手写的汇编代码(.S文件)也需要半虚拟化,因为它们包括敏感指令或其中的一些代
码路径对性能非常关键。
Chinese translated version of Documentation/core-api/irq/index.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
communicating in English you can also ask the Chinese maintainer for
help. Contact the Chinese maintainer if this translation is outdated
or if there is a problem with the translation.
Maintainer: Eric W. Biederman <ebiederman@xmission.com>
Traditional Chinese maintainer: Hu Haowen <src.res@email.cn>
---------------------------------------------------------------------
Documentation/core-api/irq/index.rst 的繁體中文翻譯
如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
交流有困難的話,也可以向繁體中文版維護者求助。如果本翻譯更新不及時或
者翻譯存在問題,請聯繫繁體中文版維護者。
英文版維護者: Eric W. Biederman <ebiederman@xmission.com>
繁體中文版維護者: 胡皓文 Hu Haowen <src.res@email.cn>
繁體中文版翻譯者: 胡皓文 Hu Haowen <src.res@email.cn>
繁體中文版校譯者: 胡皓文 Hu Haowen <src.res@email.cn>
以下爲正文
---------------------------------------------------------------------
何爲 IRQ?
一個 IRQ 是來自某個設備的一個中斷請求。目前,它們可以來自一個硬體引腳,
或來自一個數據包。多個設備可能連接到同個硬體引腳,從而共享一個 IRQ。
一個 IRQ 編號是用於告知硬體中斷源的內核標識。通常情況下,這是一個
全局 irq_desc 數組的索引,但是除了在 linux/interrupt.h 中的實現,
具體的細節是體系結構特定的。
一個 IRQ 編號是設備上某個可能的中斷源的枚舉。通常情況下,枚舉的編號是
該引腳在系統內中斷控制器的所有輸入引腳中的編號。對於 ISA 總線中的情況,
枚舉的是在兩個 i8259 中斷控制器中 16 個輸入引腳。
架構可以對 IRQ 編號指定額外的含義,在硬體涉及任何手工配置的情況下,
是被提倡的。ISA 的 IRQ 是一個分配這類額外含義的典型例子。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/README.rst
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <src.res@email.cn>
Linux內核5.x版本 <http://kernel.org/>
=========================================
以下是Linux版本5的發行註記。仔細閱讀它們,
它們會告訴你這些都是什麼,解釋如何安裝內核,以及遇到問題時該如何做。
什麼是Linux?
---------------
Linux是Unix作業系統的克隆版本,由Linus Torvalds在一個鬆散的網絡黑客
(Hacker,無貶義)團隊的幫助下從頭開始編寫。它旨在實現兼容POSIX和
單一UNIX規範。
它具有在現代成熟的Unix中應當具有的所有功能,包括真正的多任務處理、虛擬內存、
共享庫、按需加載、共享的寫時拷貝(COW)可執行文件、恰當的內存管理以及包括
IPv4和IPv6在內的複合網絡棧。
Linux在GNU通用公共許可證,版本2(GNU GPLv2)下分發,詳見隨附的COPYING文件。
它能在什麼樣的硬體上運行?
-----------------------------
雖然Linux最初是爲32位的x86 PC機(386或更高版本)開發的,但今天它也能運行在
(至少)Compaq Alpha AXP、Sun SPARC與UltraSPARC、Motorola 68000、PowerPC、
PowerPC64、ARM、Hitachi SuperH、Cell、IBM S/390、MIPS、HP PA-RISC、Intel
IA-64、DEC VAX、AMD x86-64 Xtensa和ARC架構上。
Linux很容易移植到大多數通用的32位或64位體系架構,只要它們有一個分頁內存管理
單元(PMMU)和一個移植的GNU C編譯器(gcc;GNU Compiler Collection,GCC的一
部分)。Linux也被移植到許多沒有PMMU的體系架構中,儘管功能顯然受到了一定的
限制。
Linux也被移植到了其自己上。現在可以將內核作爲用戶空間應用程式運行——這被
稱爲用戶模式Linux(UML)。
文檔
-----
網際網路上和書籍上都有大量的電子文檔,既有Linux專屬文檔,也有與一般UNIX問題相關
的文檔。我建議在任何Linux FTP站點上查找LDP(Linux文檔項目)書籍的文檔子目錄。
本自述文件並不是關於系統的文檔:有更好的可用資源。
- 網際網路上和書籍上都有大量的(電子)文檔,既有Linux專屬文檔,也有與普通
UNIX問題相關的文檔。我建議在任何有LDP(Linux文檔項目)書籍的Linux FTP
站點上查找文檔子目錄。本自述文件並不是關於系統的文檔:有更好的可用資源。
- 文檔/子目錄中有各種自述文件:例如,這些文件通常包含一些特定驅動程序的
內核安裝說明。請閱讀
:ref:`Documentation/process/changes.rst <changes>` 文件,它包含了升級內核
可能會導致的問題的相關信息。
安裝內核原始碼
---------------
- 如果您要安裝完整的原始碼,請把內核tar檔案包放在您有權限的目錄中(例如您
的主目錄)並將其解包::
xz -cd linux-5.x.tar.xz | tar xvf -
將「X」替換成最新內核的版本號。
【不要】使用 /usr/src/linux 目錄!這裡有一組庫頭文件使用的內核頭文件
(通常是不完整的)。它們應該與庫匹配,而不是被內核的變化搞得一團糟。
- 您還可以通過打補丁在5.x版本之間升級。補丁以xz格式分發。要通過打補丁進行
安裝,請獲取所有較新的補丁文件,進入內核原始碼(linux-5.x)的目錄並
執行::
xz -cd ../patch-5.x.xz | patch -p1
請【按順序】替換所有大於當前原始碼樹版本的「x」,這樣就可以了。您可能想要
刪除備份文件(文件名類似xxx~ 或 xxx.orig),並確保沒有失敗的補丁(文件名
類似xxx# 或 xxx.rej)。如果有,不是你就是我犯了錯誤。
與5.x內核的補丁不同,5.x.y內核(也稱爲穩定版內核)的補丁不是增量的,而是
直接應用於基本的5.x內核。例如,如果您的基本內核是5.0,並且希望應用5.0.3
補丁,則不應先應用5.0.1和5.0.2的補丁。類似地,如果您運行的是5.0.2內核,
並且希望跳轉到5.0.3,那麼在應用5.0.3補丁之前,必須首先撤銷5.0.2補丁
(即patch -R)。更多關於這方面的內容,請閱讀
:ref:`Documentation/process/applying-patches.rst <applying_patches>` 。
或者,腳本 patch-kernel 可以用來自動化這個過程。它能確定當前內核版本並
應用找到的所有補丁::
linux/scripts/patch-kernel linux
上面命令中的第一個參數是內核原始碼的位置。補丁是在當前目錄應用的,但是
可以將另一個目錄指定爲第二個參數。
- 確保沒有過時的 .o 文件和依賴項::
cd linux
make mrproper
現在您應該已經正確安裝了原始碼。
軟體要求
---------
編譯和運行5.x內核需要各種軟體包的最新版本。請參考
:ref:`Documentation/process/changes.rst <changes>`
來了解最低版本要求以及如何升級軟體包。請注意,使用過舊版本的這些包可能會
導致很難追蹤的間接錯誤,因此不要以爲在生成或操作過程中出現明顯問題時可以
只更新包。
爲內核建立目錄
---------------
編譯內核時,默認情況下所有輸出文件都將與內核原始碼放在一起。使用
``make O=output/dir`` 選項可以爲輸出文件(包括 .config)指定備用位置。
例如::
kernel source code: /usr/src/linux-5.x
build directory: /home/name/build/kernel
要配置和構建內核,請使用::
cd /usr/src/linux-5.x
make O=/home/name/build/kernel menuconfig
make O=/home/name/build/kernel
sudo make O=/home/name/build/kernel modules_install install
請注意:如果使用了 ``O=output/dir`` 選項,那麼它必須用於make的所有調用。
配置內核
---------
即使只升級一個小版本,也不要跳過此步驟。每個版本中都會添加新的配置選項,
如果配置文件沒有按預定設置,就會出現奇怪的問題。如果您想以最少的工作量
將現有配置升級到新版本,請使用 ``makeoldconfig`` ,它只會詢問您新配置
選項的答案。
- 其他配置命令包括::
"make config" 純文本界面。
"make menuconfig" 基於文本的彩色菜單、選項列表和對話框。
"make nconfig" 增強的基於文本的彩色菜單。
"make xconfig" 基於Qt的配置工具。
"make gconfig" 基於GTK+的配置工具。
"make oldconfig" 基於現有的 ./.config 文件選擇所有選項,並詢問
新配置選項。
"make olddefconfig"
類似上一個,但不詢問直接將新選項設置爲默認值。
"make defconfig" 根據體系架構,使用arch/$arch/defconfig或
arch/$arch/configs/${PLATFORM}_defconfig中的
默認選項值創建./.config文件。
"make ${PLATFORM}_defconfig"
使用arch/$arch/configs/${PLATFORM}_defconfig中
的默認選項值創建一個./.config文件。
用「makehelp」來獲取您體系架構中所有可用平台的列表。
"make allyesconfig"
通過儘可能將選項值設置爲「y」,創建一個
./.config文件。
"make allmodconfig"
通過儘可能將選項值設置爲「m」,創建一個
./.config文件。
"make allnoconfig" 通過儘可能將選項值設置爲「n」,創建一個
./.config文件。
"make randconfig" 通過隨機設置選項值來創建./.config文件。
"make localmodconfig" 基於當前配置和加載的模塊(lsmod)創建配置。禁用
已加載的模塊不需要的任何模塊選項。
要爲另一台計算機創建localmodconfig,請將該計算機
的lsmod存儲到一個文件中,並將其作爲lsmod參數傳入。
此外,通過在參數LMC_KEEP中指定模塊的路徑,可以將
模塊保留在某些文件夾或kconfig文件中。
target$ lsmod > /tmp/mylsmod
target$ scp /tmp/mylsmod host:/tmp
host$ make LSMOD=/tmp/mylsmod \
LMC_KEEP="drivers/usb:drivers/gpu:fs" \
localmodconfig
上述方法在交叉編譯時也適用。
"make localyesconfig" 與localmodconfig類似,只是它會將所有模塊選項轉換
爲內置(=y)。你可以同時通過LMC_KEEP保留模塊。
"make kvmconfig" 爲kvm客體內核支持啓用其他選項。
"make xenconfig" 爲xen dom0客體內核支持啓用其他選項。
"make tinyconfig" 配置儘可能小的內核。
更多關於使用Linux內核配置工具的信息,見文檔
Documentation/kbuild/kconfig.rst。
- ``make config`` 注意事項:
- 包含不必要的驅動程序會使內核變大,並且在某些情況下會導致問題:
探測不存在的控制器卡可能會混淆其他控制器。
- 如果存在協處理器,則編譯了數學仿真的內核仍將使用協處理器:在
這種情況下,數學仿真永遠不會被使用。內核會稍微大一點,但不管
是否有數學協處理器,都可以在不同的機器上工作。
- 「kernel hacking」配置細節通常會導致更大或更慢的內核(或兩者
兼而有之),甚至可以通過配置一些例程來主動嘗試破壞壞代碼以發現
內核問題,從而降低內核的穩定性(kmalloc())。因此,您可能應該
用於研究「開發」、「實驗」或「調試」特性相關問題。
編譯內核
---------
- 確保您至少有gcc 4.9可用。
有關更多信息,請參閱 :ref:`Documentation/process/changes.rst <changes>` 。
請注意,您仍然可以使用此內核運行a.out用戶程序。
- 執行 ``make`` 來創建壓縮內核映像。如果您安裝了lilo以適配內核makefile,
那麼也可以進行 ``makeinstall`` ,但是您可能需要先檢查特定的lilo設置。
實際安裝必須以root身份執行,但任何正常構建都不需要。
無須徒然使用root身份。
- 如果您將內核的任何部分配置爲模塊,那麼還必須執行 ``make modules_install`` 。
- 詳細的內核編譯/生成輸出:
通常,內核構建系統在相當安靜的模式下運行(但不是完全安靜)。但是有時您或
其他內核開發人員需要看到編譯、連結或其他命令的執行過程。爲此,可使用
「verbose(詳細)」構建模式。
向 ``make`` 命令傳遞 ``V=1`` 來實現,例如::
make V=1 all
如需構建系統也給出內個目標重建的願意,請使用 ``V=2`` 。默認爲 ``V=0`` 。
- 準備一個備份內核以防出錯。對於開發版本尤其如此,因爲每個新版本都包含
尚未調試的新代碼。也要確保保留與該內核對應的模塊的備份。如果要安裝
與工作內核版本號相同的新內核,請在進行 ``make modules_install`` 安裝
之前備份modules目錄。
或者,在編譯之前,使用內核配置選項「LOCALVERSION」向常規內核版本附加
一個唯一的後綴。LOCALVERSION可以在「General Setup」菜單中設置。
- 爲了引導新內核,您需要將內核映像(例如編譯後的
.../linux/arch/x86/boot/bzImage)複製到常規可引導內核的位置。
- 不再支持在沒有LILO等啓動裝載程序幫助的情況下直接從軟盤引導內核。
如果從硬碟引導Linux,很可能使用LILO,它使用/etc/lilo.conf文件中
指定的內核映像文件。內核映像文件通常是/vmlinuz、/boot/vmlinuz、
/bzImage或/boot/bzImage。使用新內核前,請保存舊映像的副本,並複製
新映像覆蓋舊映像。然後您【必須重新運行LILO】來更新加載映射!否則,
將無法啓動新的內核映像。
重新安裝LILO通常需要運行/sbin/LILO。您可能希望編輯/etc/lilo.conf
文件爲舊內核映像指定一個條目(例如/vmlinux.old)防止新的不能正常
工作。有關更多信息,請參閱LILO文檔。
重新安裝LILO之後,您應該就已經準備好了。關閉系統,重新啓動,盡情
享受吧!
如果需要更改內核映像中的默認根設備、視頻模式等,請在適當的地方使用
啓動裝載程序的引導選項。無需重新編譯內核即可更改這些參數。
- 使用新內核重新啓動並享受它吧。
若遇到問題
-----------
- 如果您發現了一些可能由於內核缺陷所導致的問題,請檢查MAINTAINERS(維護者)
文件看看是否有人與令您遇到麻煩的內核部分相關。如果無人在此列出,那麼第二
個最好的方案就是把它們發給我(torvalds@linux-foundation.org),也可能發送
到任何其他相關的郵件列表或新聞組。
- 在所有的缺陷報告中,【請】告訴我們您在說什麼內核,如何復現問題,以及您的
設置是什麼的(使用您的常識)。如果問題是新的,請告訴我;如果問題是舊的,
請嘗試告訴我您什麼時候首次注意到它。
- 如果缺陷導致如下消息::
unable to handle kernel paging request at address C0000010
Oops: 0002
EIP: 0010:XXXXXXXX
eax: xxxxxxxx ebx: xxxxxxxx ecx: xxxxxxxx edx: xxxxxxxx
esi: xxxxxxxx edi: xxxxxxxx ebp: xxxxxxxx
ds: xxxx es: xxxx fs: xxxx gs: xxxx
Pid: xx, process nr: xx
xx xx xx xx xx xx xx xx xx xx
或者類似的內核調試信息顯示在屏幕上或在系統日誌里,請【如實】複製它。
可能對你來說轉儲(dump)看起來不可理解,但它確實包含可能有助於調試問題的
信息。轉儲上方的文本也很重要:它說明了內核轉儲代碼的原因(在上面的示例中,
是由於內核指針錯誤)。更多關於如何理解轉儲的信息,請參見
Documentation/admin-guide/bug-hunting.rst。
- 如果使用 CONFIG_KALLSYMS 編譯內核,則可以按原樣發送轉儲,否則必須使用
``ksymoops`` 程序來理解轉儲(但通常首選使用CONFIG_KALLSYMS編譯)。
此實用程序可從
https://www.kernel.org/pub/linux/utils/kernel/ksymoops/ 下載。
或者,您可以手動執行轉儲查找:
- 在調試像上面這樣的轉儲時,如果您可以查找EIP值的含義,這將非常有幫助。
十六進位值本身對我或其他任何人都沒有太大幫助:它會取決於特定的內核設置。
您應該做的是從EIP行獲取十六進位值(忽略 ``0010:`` ),然後在內核名字列表
中查找它,以查看哪個內核函數包含有問題的地址。
要找到內核函數名,您需要找到與顯示症狀的內核相關聯的系統二進位文件。就是
文件「linux/vmlinux」。要提取名字列表並將其與內核崩潰中的EIP進行匹配,
請執行::
nm vmlinux | sort | less
這將爲您提供一個按升序排序的內核地址列表,從中很容易找到包含有問題的地址
的函數。請注意,內核調試消息提供的地址不一定與函數地址完全匹配(事實上,
這是不可能的),因此您不能只「grep」列表:不過列表將爲您提供每個內核函數
的起點,因此通過查找起始地址低於你正在搜索的地址,但後一個函數的高於的
函數,你會找到您想要的。實際上,在您的問題報告中加入一些「上下文」可能是
一個好主意,給出相關的上下幾行。
如果您由於某些原因無法完成上述操作(如您使用預編譯的內核映像或類似的映像),
請儘可能多地告訴我您的相關設置信息,這會有所幫助。有關詳細信息請閱讀
『Documentation/admin-guide/reporting-issues.rst』。
- 或者,您可以在正在運行的內核上使用gdb(只讀的;即不能更改值或設置斷點)。
爲此,請首先使用-g編譯內核;適當地編輯arch/x86/Makefile,然後執行 ``make
clean`` 。您還需要啓用CONFIG_PROC_FS(通過 ``make config`` )。
使用新內核重新啓動後,執行 ``gdb vmlinux /proc/kcore`` 。現在可以使用所有
普通的gdb命令。查找系統崩潰點的命令是 ``l *0xXXXXXXXX`` (將xxx替換爲EIP
值)。
用gdb無法調試一個當前未運行的內核是由於gdb(錯誤地)忽略了編譯內核的起始
偏移量。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../admin-guide/bug-bisect`
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <src.res@email.cn>
二分(bisect)缺陷
+++++++++++++++++++
(英文版)最後更新:2016年10月28日
引言
=====
始終嘗試由來自kernel.org的原始碼構建的最新內核。如果您沒有信心這樣做,請將
錯誤報告給您的發行版供應商,而不是內核開發人員。
找到缺陷(bug)並不總是那麼容易,不過仍然得去找。如果你找不到它,不要放棄。
儘可能多的向相關維護人員報告您發現的信息。請參閱MAINTAINERS文件以了解您所
關注的子系統的維護人員。
在提交錯誤報告之前,請閱讀「Documentation/admin-guide/reporting-issues.rst」。
設備未出現(Devices not appearing)
====================================
這通常是由udev/systemd引起的。在將其歸咎於內核之前先檢查一下。
查找導致缺陷的補丁
===================
使用 ``git`` 提供的工具可以很容易地找到缺陷,只要缺陷是可復現的。
操作步驟:
- 從git原始碼構建內核
- 以此開始二分 [#f1]_::
$ git bisect start
- 標記損壞的變更集::
$ git bisect bad [commit]
- 標記正常工作的變更集::
$ git bisect good [commit]
- 重新構建內核並測試
- 使用以下任一與git bisect進行交互::
$ git bisect good
或::
$ git bisect bad
這取決於您測試的變更集上是否有缺陷
- 在一些交互之後,git bisect將給出可能導致缺陷的變更集。
- 例如,如果您知道當前版本有問題,而4.8版本是正常的,則可以執行以下操作::
$ git bisect start
$ git bisect bad # Current version is bad
$ git bisect good v4.8
.. [#f1] 您可以(可選地)在開始git bisect的時候提供good或bad參數
``git bisect start [BAD] [GOOD]``
如需進一步參考,請閱讀:
- ``git-bisect`` 的手冊頁
- `Fighting regressions with git bisect(用git bisect解決回歸)
<https://www.kernel.org/pub/software/scm/git/docs/git-bisect-lk2009.html>`_
- `Fully automated bisecting with "git bisect run"(使用git bisect run
來全自動二分) <https://lwn.net/Articles/317154>`_
- `Using Git bisect to figure out when brokenness was introduced
(使用Git二分來找出何時引入了錯誤) <http://webchick.net/node/99>`_
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../admin-guide/bug-hunting`
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <src.res@email.cn>
追蹤缺陷
=========
內核錯誤報告通常附帶如下堆棧轉儲::
------------[ cut here ]------------
WARNING: CPU: 1 PID: 28102 at kernel/module.c:1108 module_put+0x57/0x70
Modules linked in: dvb_usb_gp8psk(-) dvb_usb dvb_core nvidia_drm(PO) nvidia_modeset(PO) snd_hda_codec_hdmi snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm snd_timer snd soundcore nvidia(PO) [last unloaded: rc_core]
CPU: 1 PID: 28102 Comm: rmmod Tainted: P WC O 4.8.4-build.1 #1
Hardware name: MSI MS-7309/MS-7309, BIOS V1.12 02/23/2009
00000000 c12ba080 00000000 00000000 c103ed6a c1616014 00000001 00006dc6
c1615862 00000454 c109e8a7 c109e8a7 00000009 ffffffff 00000000 f13f6a10
f5f5a600 c103ee33 00000009 00000000 00000000 c109e8a7 f80ca4d0 c109f617
Call Trace:
[<c12ba080>] ? dump_stack+0x44/0x64
[<c103ed6a>] ? __warn+0xfa/0x120
[<c109e8a7>] ? module_put+0x57/0x70
[<c109e8a7>] ? module_put+0x57/0x70
[<c103ee33>] ? warn_slowpath_null+0x23/0x30
[<c109e8a7>] ? module_put+0x57/0x70
[<f80ca4d0>] ? gp8psk_fe_set_frontend+0x460/0x460 [dvb_usb_gp8psk]
[<c109f617>] ? symbol_put_addr+0x27/0x50
[<f80bc9ca>] ? dvb_usb_adapter_frontend_exit+0x3a/0x70 [dvb_usb]
[<f80bb3bf>] ? dvb_usb_exit+0x2f/0xd0 [dvb_usb]
[<c13d03bc>] ? usb_disable_endpoint+0x7c/0xb0
[<f80bb48a>] ? dvb_usb_device_exit+0x2a/0x50 [dvb_usb]
[<c13d2882>] ? usb_unbind_interface+0x62/0x250
[<c136b514>] ? __pm_runtime_idle+0x44/0x70
[<c13620d8>] ? __device_release_driver+0x78/0x120
[<c1362907>] ? driver_detach+0x87/0x90
[<c1361c48>] ? bus_remove_driver+0x38/0x90
[<c13d1c18>] ? usb_deregister+0x58/0xb0
[<c109fbb0>] ? SyS_delete_module+0x130/0x1f0
[<c1055654>] ? task_work_run+0x64/0x80
[<c1000fa5>] ? exit_to_usermode_loop+0x85/0x90
[<c10013f0>] ? do_fast_syscall_32+0x80/0x130
[<c1549f43>] ? sysenter_past_esp+0x40/0x6a
---[ end trace 6ebc60ef3981792f ]---
這樣的堆棧跟蹤提供了足夠的信息來識別內核原始碼中發生錯誤的那一行。根據問題的
嚴重性,它還可能包含 **「Oops」** 一詞,比如::
BUG: unable to handle kernel NULL pointer dereference at (null)
IP: [<c06969d4>] iret_exc+0x7d0/0xa59
*pdpt = 000000002258a001 *pde = 0000000000000000
Oops: 0002 [#1] PREEMPT SMP
...
儘管有 **Oops** 或其他類型的堆棧跟蹤,但通常需要找到出問題的行來識別和處理缺
陷。在本章中,我們將參考「Oops」來了解需要分析的各種堆棧跟蹤。
如果內核是用 ``CONFIG_DEBUG_INFO`` 編譯的,那麼可以使用文件:
`scripts/decode_stacktrace.sh` 。
連結的模塊
-----------
受到汙染或正在加載/卸載的模塊用「(…)」標記,汙染標誌在
`Documentation/admin-guide/tainted-kernels.rst` 文件中進行了描述,「正在被加
載」用「+」標註,「正在被卸載」用「-」標註。
Oops消息在哪?
---------------
通常,Oops文本由klogd從內核緩衝區讀取,然後交給 ``syslogd`` ,後者將其寫入
syslog文件,通常是 ``/var/log/messages`` (取決於 ``/etc/syslog.conf`` )。
在使用systemd的系統上,它也可以由 ``journald`` 守護進程存儲,並通過運行
``journalctl`` 命令進行訪問。
有時 ``klogd`` 會掛掉,這種情況下您可以運行 ``dmesg > file`` 從內核緩衝區
讀取數據並保存它。或者您可以 ``cat /proc/kmsg > file`` ,但是您必須適時
中斷以停止傳輸,因爲 ``kmsg`` 是一個「永無止境的文件」。
如果機器嚴重崩潰,無法輸入命令或磁碟不可用,那還有三個選項:
(1) 手動複製屏幕上的文本,並在機器重新啓動後輸入。很難受,但這是突然崩潰下
唯一的選擇。或者你可以用數位相機拍下屏幕——雖然不那麼好,但總比什麼都沒
有好。如果消息滾動超出控制台頂部,使用更高解析度(例如 ``vga=791`` )
引導啓動將允許您閱讀更多文本。(警告:這需要 ``vesafb`` ,因此對「早期」
的Oppses沒有幫助)
(2) 從串口終端啓動(參見
:ref:`Documentation/admin-guide/serial-console.rst <serial_console>` ),
在另一台機器上運行數據機然後用你喜歡的通信程序捕獲輸出。
Minicom運行良好。
(3) 使用Kdump(參閱 Documentation/admin-guide/kdump/kdump.rst ),使用
Documentation/admin-guide/kdump/gdbmacros.txt 中的dmesg gdbmacro從舊內存
中提取內核環形緩衝區。
找到缺陷位置
-------------
如果你能指出缺陷在內核原始碼中的位置,則報告缺陷的效果會非常好。這有兩種方法。
通常來說使用 ``gdb`` 會比較容易,不過內核需要用調試信息來預編譯。
gdb
^^^^
GNU 調試器(GNU debugger, ``gdb`` )是從 ``vmlinux`` 文件中找出OOPS的確切
文件和行號的最佳方法。
在使用 ``CONFIG_DEBUG_INFO`` 編譯的內核上使用gdb效果最好。可通過運行以下命令
進行設置::
$ ./scripts/config -d COMPILE_TEST -e DEBUG_KERNEL -e DEBUG_INFO
在用 ``CONFIG_DEBUG_INFO`` 編譯的內核上,你可以直接從OOPS複製EIP值::
EIP: 0060:[<c021e50e>] Not tainted VLI
並使用GDB來將其翻譯成可讀形式::
$ gdb vmlinux
(gdb) l *0xc021e50e
如果沒有啓用 ``CONFIG_DEBUG_INFO`` ,則使用OOPS的函數偏移::
EIP is at vt_ioctl+0xda8/0x1482
並在啓用 ``CONFIG_DEBUG_INFO`` 的情況下重新編譯內核::
$ ./scripts/config -d COMPILE_TEST -e DEBUG_KERNEL -e DEBUG_INFO
$ make vmlinux
$ gdb vmlinux
(gdb) l *vt_ioctl+0xda8
0x1888 is in vt_ioctl (drivers/tty/vt/vt_ioctl.c:293).
288 {
289 struct vc_data *vc = NULL;
290 int ret = 0;
291
292 console_lock();
293 if (VT_BUSY(vc_num))
294 ret = -EBUSY;
295 else if (vc_num)
296 vc = vc_deallocate(vc_num);
297 console_unlock();
或者若您想要更詳細的顯示::
(gdb) p vt_ioctl
$1 = {int (struct tty_struct *, unsigned int, unsigned long)} 0xae0 <vt_ioctl>
(gdb) l *0xae0+0xda8
您也可以使用對象文件作爲替代::
$ make drivers/tty/
$ gdb drivers/tty/vt/vt_ioctl.o
(gdb) l *vt_ioctl+0xda8
如果你有調用跟蹤,類似::
Call Trace:
[<ffffffff8802c8e9>] :jbd:log_wait_commit+0xa3/0xf5
[<ffffffff810482d9>] autoremove_wake_function+0x0/0x2e
[<ffffffff8802770b>] :jbd:journal_stop+0x1be/0x1ee
...
這表明問題可能在 :jbd: 模塊中。您可以在gdb中加載該模塊並列出相關代碼::
$ gdb fs/jbd/jbd.ko
(gdb) l *log_wait_commit+0xa3
.. note::
您還可以對堆棧跟蹤處的任何函數調用執行相同的操作,例如::
[<f80bc9ca>] ? dvb_usb_adapter_frontend_exit+0x3a/0x70 [dvb_usb]
上述調用發生的位置可以通過以下方式看到::
$ gdb drivers/media/usb/dvb-usb/dvb-usb.o
(gdb) l *dvb_usb_adapter_frontend_exit+0x3a
objdump
^^^^^^^^
要調試內核,請使用objdump並從崩潰輸出中查找十六進位偏移,以找到有效的代碼/匯
編行。如果沒有調試符號,您將看到所示例程的彙編程序代碼,但是如果內核有調試
符號,C代碼也將可見(調試符號可以在內核配置菜單的hacking項中啓用)。例如::
$ objdump -r -S -l --disassemble net/dccp/ipv4.o
.. note::
您需要處於內核樹的頂層以便此獲得您的C文件。
如果您無法訪問原始碼,仍然可以使用以下方法調試一些崩潰轉儲(如Dave Miller的
示例崩潰轉儲輸出所示)::
EIP is at +0x14/0x4c0
...
Code: 44 24 04 e8 6f 05 00 00 e9 e8 fe ff ff 8d 76 00 8d bc 27 00 00
00 00 55 57 56 53 81 ec bc 00 00 00 8b ac 24 d0 00 00 00 8b 5d 08
<8b> 83 3c 01 00 00 89 44 24 14 8b 45 28 85 c0 89 44 24 18 0f 85
Put the bytes into a "foo.s" file like this:
.text
.globl foo
foo:
.byte .... /* bytes from Code: part of OOPS dump */
Compile it with "gcc -c -o foo.o foo.s" then look at the output of
"objdump --disassemble foo.o".
Output:
ip_queue_xmit:
push %ebp
push %edi
push %esi
push %ebx
sub $0xbc, %esp
mov 0xd0(%esp), %ebp ! %ebp = arg0 (skb)
mov 0x8(%ebp), %ebx ! %ebx = skb->sk
mov 0x13c(%ebx), %eax ! %eax = inet_sk(sk)->opt
`scripts/decodecode` 文件可以用來自動完成大部分工作,這取決於正在調試的CPU
體系結構。
報告缺陷
---------
一旦你通過定位缺陷找到了其發生的地方,你可以嘗試自己修復它或者向上游報告它。
爲了向上游報告,您應該找出用於開發受影響代碼的郵件列表。這可以使用 ``get_maintainer.pl`` 。
例如,您在gspca的sonixj.c文件中發現一個缺陷,則可以通過以下方法找到它的維護者::
$ ./scripts/get_maintainer.pl -f drivers/media/usb/gspca/sonixj.c
Hans Verkuil <hverkuil@xs4all.nl> (odd fixer:GSPCA USB WEBCAM DRIVER,commit_signer:1/1=100%)
Mauro Carvalho Chehab <mchehab@kernel.org> (maintainer:MEDIA INPUT INFRASTRUCTURE (V4L/DVB),commit_signer:1/1=100%)
Tejun Heo <tj@kernel.org> (commit_signer:1/1=100%)
Bhaktipriya Shridhar <bhaktipriya96@gmail.com> (commit_signer:1/1=100%,authored:1/1=100%,added_lines:4/4=100%,removed_lines:9/9=100%)
linux-media@vger.kernel.org (open list:GSPCA USB WEBCAM DRIVER)
linux-kernel@vger.kernel.org (open list)
請注意它將指出:
- 最後接觸原始碼的開發人員(如果這是在git樹中完成的)。在上面的例子中是Tejun
和Bhaktipriya(在這個特定的案例中,沒有人真正參與這個文件的開發);
- 驅動維護人員(Hans Verkuil);
- 子系統維護人員(Mauro Carvalho Chehab);
- 驅動程序和/或子系統郵件列表(linux-media@vger.kernel.org);
- Linux內核郵件列表(linux-kernel@vger.kernel.org)。
通常,修復缺陷的最快方法是將它報告給用於開發相關代碼的郵件列表(linux-media
ML),抄送驅動程序維護者(Hans)。
如果你完全不知道該把報告寄給誰,且 ``get_maintainer.pl`` 也沒有提供任何有用
的信息,請發送到linux-kernel@vger.kernel.org。
感謝您的幫助,這使Linux儘可能穩定:-)
修復缺陷
---------
如果你懂得編程,你不僅可以通過報告錯誤來幫助我們,還可以提供一個解決方案。
畢竟,開源就是分享你的工作,你不想因爲你的天才而被認可嗎?
如果你決定這樣做,請在制定解決方案後將其提交到上游。
請務必閱讀
:ref:`Documentation/process/submitting-patches.rst <submittingpatches>` ,
以幫助您的代碼被接受。
---------------------------------------------------------------------------
用 ``klogd`` 進行Oops跟蹤的注意事項
------------------------------------
爲了幫助Linus和其他內核開發人員, ``klogd`` 對保護故障的處理提供了大量支持。
爲了完整支持地址解析,至少應該使用 ``sysklogd`` 包的1.3-pl3版本。
當發生保護故障時, ``klogd`` 守護進程會自動將內核日誌消息中的重要地址轉換爲
它們的等效符號。然後通過 ``klogd`` 使用的任何報告機制來轉發這個已翻譯的內核
消息。保護錯誤消息可以直接從消息文件中剪切出來並轉發給內核開發人員。
``klogd`` 執行兩種類型的地址解析,靜態翻譯和動態翻譯。靜態翻譯使用System.map
文件。爲了進行靜態轉換, ``klogd`` 守護進程必須能夠在守護進程初始化時找到系
統映射文件。有關 ``klogd`` 如何搜索映射文件的信息,請參見klogd手冊頁。
當使用內核可加載模塊時,動態地址轉換非常重要。由於內核模塊的內存是從內核的
動態內存池中分配的,因此無論是模塊的開頭還是模塊中的函數和符號都沒有固定的
位置。
內核支持系統調用,允許程序確定加載哪些模塊及其在內存中的位置。klogd守護進程
使用這些系統調用構建了一個符號表,可用於調試可加載內核模塊中發生的保護錯誤。
klogd至少會提供產生保護故障的模塊的名稱。如果可加載模塊的開發人員選擇從模塊
導出符號信息,則可能會有其他可用的符號信息。
由於內核模塊環境可以是動態的,因此當模塊環境發生變化時,必須有一種通知
``klogd`` 守護進程的機制。有一些可用的命令行選項允許klogd向當前正在執行的守
護進程發出信號示意應該刷新符號信息。有關更多信息,請參閱 ``klogd`` 手冊頁。
sysklogd發行版附帶了一個補丁,它修改了 ``modules-2.0.0`` 包,以便在加載或
卸載模塊時自動向klogd發送信號。應用此補丁基本上可無縫支持調試內核可加載模塊
發生的保護故障。
以下是 ``klogd`` 處理的可加載模塊中的保護故障示例::
Aug 29 09:51:01 blizard kernel: Unable to handle kernel paging request at virtual address f15e97cc
Aug 29 09:51:01 blizard kernel: current->tss.cr3 = 0062d000, %cr3 = 0062d000
Aug 29 09:51:01 blizard kernel: *pde = 00000000
Aug 29 09:51:01 blizard kernel: Oops: 0002
Aug 29 09:51:01 blizard kernel: CPU: 0
Aug 29 09:51:01 blizard kernel: EIP: 0010:[oops:_oops+16/3868]
Aug 29 09:51:01 blizard kernel: EFLAGS: 00010212
Aug 29 09:51:01 blizard kernel: eax: 315e97cc ebx: 003a6f80 ecx: 001be77b edx: 00237c0c
Aug 29 09:51:01 blizard kernel: esi: 00000000 edi: bffffdb3 ebp: 00589f90 esp: 00589f8c
Aug 29 09:51:01 blizard kernel: ds: 0018 es: 0018 fs: 002b gs: 002b ss: 0018
Aug 29 09:51:01 blizard kernel: Process oops_test (pid: 3374, process nr: 21, stackpage=00589000)
Aug 29 09:51:01 blizard kernel: Stack: 315e97cc 00589f98 0100b0b4 bffffed4 0012e38e 00240c64 003a6f80 00000001
Aug 29 09:51:01 blizard kernel: 00000000 00237810 bfffff00 0010a7fa 00000003 00000001 00000000 bfffff00
Aug 29 09:51:01 blizard kernel: bffffdb3 bffffed4 ffffffda 0000002b 0007002b 0000002b 0000002b 00000036
Aug 29 09:51:01 blizard kernel: Call Trace: [oops:_oops_ioctl+48/80] [_sys_ioctl+254/272] [_system_call+82/128]
Aug 29 09:51:01 blizard kernel: Code: c7 00 05 00 00 00 eb 08 90 90 90 90 90 90 90 90 89 ec 5d c3
---------------------------------------------------------------------------
::
Dr. G.W. Wettstein Oncology Research Div. Computing Facility
Roger Maris Cancer Center INTERNET: greg@wind.rmcc.com
820 4th St. N.
Fargo, ND 58122
Phone: 701-234-7556
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Translator: 胡皓文 Hu Haowen <src.res@email.cn>
清除 WARN_ONCE
--------------
WARN_ONCE / WARN_ON_ONCE / printk_once 僅僅列印一次消息.
echo 1 > /sys/kernel/debug/clear_warn_once
可以清除這種狀態並且再次允許列印一次告警信息,這對於運行測試集後重現問題
很有用。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Translator: 胡皓文 Hu Haowen <src.res@email.cn>
========
CPU 負載
========
Linux通過``/proc/stat``和``/proc/uptime``導出各種信息,用戶空間工具
如top(1)使用這些信息計算系統花費在某個特定狀態的平均時間。
例如:
$ iostat
Linux 2.6.18.3-exp (linmac) 02/20/2007
avg-cpu: %user %nice %system %iowait %steal %idle
10.01 0.00 2.92 5.44 0.00 81.63
...
這裡系統認爲在默認採樣周期內有10.01%的時間工作在用戶空間,2.92%的時
間用在系統空間,總體上有81.63%的時間是空閒的。
大多數情況下``/proc/stat``的信息幾乎真實反映了系統信息,然而,由於內
核採集這些數據的方式/時間的特點,有時這些信息根本不可靠。
那麼這些信息是如何被搜集的呢?每當時間中斷觸發時,內核查看此刻運行的
進程類型,並增加與此類型/狀態進程對應的計數器的值。這種方法的問題是
在兩次時間中斷之間系統(進程)能夠在多種狀態之間切換多次,而計數器只
增加最後一種狀態下的計數。
舉例
---
假設系統有一個進程以如下方式周期性地占用cpu::
兩個時鐘中斷之間的時間線
|-----------------------|
^ ^
|_ 開始運行 |
|_ 開始睡眠
(很快會被喚醒)
在上面的情況下,根據``/proc/stat``的信息(由於當系統處於空閒狀態時,
時間中斷經常會發生)系統的負載將會是0
大家能夠想像內核的這種行爲會發生在許多情況下,這將導致``/proc/stat``
中存在相當古怪的信息::
/* gcc -o hog smallhog.c */
#include <time.h>
#include <limits.h>
#include <signal.h>
#include <sys/time.h>
#define HIST 10
static volatile sig_atomic_t stop;
static void sighandler (int signr)
{
(void) signr;
stop = 1;
}
static unsigned long hog (unsigned long niters)
{
stop = 0;
while (!stop && --niters);
return niters;
}
int main (void)
{
int i;
struct itimerval it = { .it_interval = { .tv_sec = 0, .tv_usec = 1 },
.it_value = { .tv_sec = 0, .tv_usec = 1 } };
sigset_t set;
unsigned long v[HIST];
double tmp = 0.0;
unsigned long n;
signal (SIGALRM, &sighandler);
setitimer (ITIMER_REAL, &it, NULL);
hog (ULONG_MAX);
for (i = 0; i < HIST; ++i) v[i] = ULONG_MAX - hog (ULONG_MAX);
for (i = 0; i < HIST; ++i) tmp += v[i];
tmp /= HIST;
n = tmp - (tmp / 3.0);
sigemptyset (&set);
sigaddset (&set, SIGALRM);
for (;;) {
hog (n);
sigwait (&set, &i);
}
return 0;
}
參考
---
- https://lore.kernel.org/r/loom.20070212T063225-663@post.gmane.org
- Documentation/filesystems/proc.rst (1.8)
謝謝
---
Con Kolivas, Pavel Machek
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../admin-guide/index`
:Translator: 胡皓文 Hu Haowen <src.res@email.cn>
Linux 內核用戶和管理員指南
==========================
下面是一組隨時間添加到內核中的面向用戶的文檔的集合。到目前爲止,還沒有一個
整體的順序或組織 - 這些材料不是一個單一的,連貫的文件!幸運的話,情況會隨著
時間的推移而迅速改善。
這個初始部分包含總體信息,包括描述內核的README, 關於內核參數的文檔等。
.. toctree::
:maxdepth: 1
README
Todolist:
kernel-parameters
devices
sysctl/index
本節介紹CPU漏洞及其緩解措施。
Todolist:
hw-vuln/index
下面的一組文檔,針對的是試圖跟蹤問題和bug的用戶。
.. toctree::
:maxdepth: 1
reporting-issues
security-bugs
bug-hunting
bug-bisect
tainted-kernels
init
Todolist:
reporting-bugs
ramoops
dynamic-debug-howto
kdump/index
perf/index
這是應用程式開發人員感興趣的章節的開始。可以在這裡找到涵蓋內核ABI各個
方面的文檔。
Todolist:
sysfs-rules
本手冊的其餘部分包括各種指南,介紹如何根據您的喜好配置內核的特定行爲。
.. toctree::
:maxdepth: 1
clearing-warn-once
cpu-load
unicode
Todolist:
acpi/index
aoe/index
auxdisplay/index
bcache
binderfs
binfmt-misc
blockdev/index
bootconfig
braille-console
btmrvl
cgroup-v1/index
cgroup-v2
cifs/index
cputopology
dell_rbu
device-mapper/index
edid
efi-stub
ext4
nfs/index
gpio/index
highuid
hw_random
initrd
iostats
java
jfs
kernel-per-CPU-kthreads
laptops/index
lcd-panel-cgram
ldm
lockup-watchdogs
LSM/index
md
media/index
mm/index
module-signing
mono
namespaces/index
numastat
parport
perf-security
pm/index
pnp
rapidio
ras
rtc
serial-console
svga
sysrq
thunderbolt
ufs
vga-softcursor
video-output
xfs
.. only:: subproject and html
Indices
=======
* :ref:`genindex`
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../admin-guide/init`
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <src.res@email.cn>
解釋「No working init found.」啓動掛起消息
==========================================
:作者:
Andreas Mohr <andi at lisas period de>
Cristian Souza <cristianmsbr at gmail period com>
本文檔提供了加載初始化二進位(init binary)失敗的一些高層級原因(大致按執行
順序列出)。
1) **無法掛載根文件系統Unable to mount root FS** :請設置「debug」內核參數(在
引導加載程序bootloader配置文件或CONFIG_CMDLINE)以獲取更詳細的內核消息。
2) **初始化二進位不存在於根文件系統上init binary doesn't exist on rootfs** :
確保您的根文件系統類型正確(並且 ``root=`` 內核參數指向正確的分區);擁有
所需的驅動程序,例如SCSI或USB等存儲硬體;文件系統(ext3、jffs2等)是內建的
(或者作爲模塊由initrd預加載)。
3) **控制台設備損壞Broken console device** : ``console= setup`` 中可能存在
衝突 --> 初始控制台不可用(initial console unavailable)。例如,由於串行
IRQ問題(如缺少基於中斷的配置)導致的某些串行控制台不可靠。嘗試使用不同的
``console= device`` 或像 ``netconsole=`` 。
4) **二進位存在但依賴項不可用Binary exists but dependencies not available** :
例如初始化二進位的必需庫依賴項,像 ``/lib/ld-linux.so.2`` 丟失或損壞。使用
``readelf -d <INIT>|grep NEEDED`` 找出需要哪些庫。
5) **無法加載二進位Binary cannot be loaded** :請確保二進位的體系結構與您的
硬體匹配。例如i386不匹配x86_64,或者嘗試在ARM硬體上加載x86。如果您嘗試在
此處加載非二進位文件(shell腳本?),您應該確保腳本在其工作頭(shebang
header)行 ``#!/...`` 中指定能正常工作的解釋器(包括其庫依賴項)。在處理
腳本之前,最好先測試一個簡單的非腳本二進位文件,比如 ``/bin/sh`` ,並確認
它能成功執行。要了解更多信息,請將代碼添加到 ``init/main.c`` 以顯示
kernel_execve()的返回值。
當您發現新的失敗原因時,請擴展本解釋(畢竟加載初始化二進位是一個 **關鍵** 且
艱難的過渡步驟,需要儘可能無痛地進行),然後向LKML提交一個補丁。
待辦事項:
- 通過一個可以存儲 ``kernel_execve()`` 結果值的結構體數組實現各種
``run_init_process()`` 調用,並在失敗時通過疊代 **所有** 結果來記錄一切
(非常重要的可用性修復)。
- 試著使實現本身在一般情況下更有幫助,例如在受影響的地方提供額外的錯誤消息。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../admin-guide/security-bugs`
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <src.res@email.cn>
安全缺陷
=========
Linux內核開發人員非常重視安全性。因此我們想知道何時發現了安全漏洞,以便儘快
修復和披露。請向Linux內核安全團隊報告安全漏洞。
聯絡
-----
可以通過電子郵件<security@kernel.org>聯繫Linux內核安全團隊。這是一個安全人員
的私有列表,他們將幫助驗證錯誤報告並開發和發布修復程序。如果您已經有了一個
修復,請將其包含在您的報告中,這樣可以大大加快進程。安全團隊可能會從區域維護
人員那裡獲得額外的幫助,以理解和修復安全漏洞。
與任何缺陷一樣,提供的信息越多,診斷和修復就越容易。如果您不清楚哪些信息有用,
請查看「Documentation/translations/zh_TW/admin-guide/reporting-issues.rst」中
概述的步驟。任何利用漏洞的攻擊代碼都非常有用,未經報告者同意不會對外發布,除
非已經公開。
請儘可能發送無附件的純文本電子郵件。如果所有的細節都藏在附件里,那麼就很難對
一個複雜的問題進行上下文引用的討論。把它想像成一個
:doc:`常規的補丁提交 <../process/submitting-patches>` (即使你還沒有補丁):
描述問題和影響,列出復現步驟,然後給出一個建議的解決方案,所有這些都是純文本的。
披露和限制信息
---------------
安全列表不是公開渠道。爲此,請參見下面的協作。
一旦開發出了健壯的補丁,發布過程就開始了。對公開的缺陷的修復會立即發布。
儘管我們傾向於在未公開缺陷的修復可用時即發布補丁,但應報告者或受影響方的請求,
這可能會被推遲到發布過程開始後的7日內,如果根據缺陷的嚴重性需要更多的時間,
則可額外延長到14天。推遲發布修復的唯一有效原因是爲了適應QA的邏輯和需要發布
協調的大規模部署。
雖然可能與受信任的個人共享受限信息以開發修復,但未經報告者許可,此類信息不會
與修復程序一起發布或發布在任何其他披露渠道上。這包括但不限於原始錯誤報告和
後續討論(如有)、漏洞、CVE信息或報告者的身份。
換句話說,我們唯一感興趣的是修復缺陷。提交給安全列表的所有其他資料以及對報告
的任何後續討論,即使在解除限制之後,也將永久保密。
協調
------
對敏感缺陷(例如那些可能導致權限提升的缺陷)的修復可能需要與私有郵件列表
<linux-distros@vs.openwall.org>進行協調,以便分發供應商做好準備,在公開披露
上游補丁時發布一個已修復的內核。發行版將需要一些時間來測試建議的補丁,通常
會要求至少幾天的限制,而供應商更新發布更傾向於周二至周四。若合適,安全團隊
可以協助這種協調,或者報告者可以從一開始就包括linux發行版。在這種情況下,請
記住在電子郵件主題行前面加上「[vs]」,如linux發行版wiki中所述:
<http://oss-security.openwall.org/wiki/mailing-lists/distros#how-to-use-the-lists>。
CVE分配
--------
安全團隊通常不分配CVE,我們也不需要它們來進行報告或修復,因爲這會使過程不必
要的複雜化,並可能耽誤缺陷處理。如果報告者希望在公開披露之前分配一個CVE編號,
他們需要聯繫上述的私有linux-distros列表。當在提供補丁之前已有這樣的CVE編號時,
如報告者願意,最好在提交消息中提及它。
保密協議
---------
Linux內核安全團隊不是一個正式的機構實體,因此無法簽訂任何保密協議。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../admin-guide/tainted-kernels`
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <src.res@email.cn>
受汙染的內核
-------------
當發生一些在稍後調查問題時可能相關的事件時,內核會將自己標記爲「受汙染
(tainted)」的。不用太過擔心,大多數情況下運行受汙染的內核沒有問題;這些信息
主要在有人想調查某個問題時才有意義的,因爲問題的真正原因可能是導致內核受汙染
的事件。這就是爲什麼來自受汙染內核的缺陷報告常常被開發人員忽略,因此請嘗試用
未受汙染的內核重現問題。
請注意,即使在您消除導致汙染的原因(亦即卸載專有內核模塊)之後,內核仍將保持
汙染狀態,以表示內核仍然不可信。這也是爲什麼內核在注意到內部問題(「kernel
bug」)、可恢復錯誤(「kernel oops」)或不可恢復錯誤(「kernel panic」)時會列印
受汙染狀態,並將有關此的調試信息寫入日誌 ``dmesg`` 輸出。也可以通過
``/proc/`` 中的文件在運行時檢查受汙染的狀態。
BUG、Oops或Panics消息中的汙染標誌
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在頂部以「CPU:」開頭的一行中可以找到受汙染的狀態;內核是否受到汙染和原因會顯示
在進程ID(「PID:」)和觸發事件命令的縮寫名稱(「Comm:」)之後::
BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
Oops: 0002 [#1] SMP PTI
CPU: 0 PID: 4424 Comm: insmod Tainted: P W O 4.20.0-0.rc6.fc30 #1
Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
RIP: 0010:my_oops_init+0x13/0x1000 [kpanic]
[...]
如果內核在事件發生時沒有被汙染,您將在那裡看到「Not-tainted:」;如果被汙染,那
麼它將是「Tainted:」以及字母或空格。在上面的例子中,它看起來是這樣的::
Tainted: P W O
下表解釋了這些字符的含義。在本例中,由於加載了專有模塊( ``P`` ),出現了
警告( ``W`` ),並且加載了外部構建的模塊( ``O`` ),所以內核早些時候受到
了汙染。要解碼其他字符,請使用下表。
解碼運行時的汙染狀態
~~~~~~~~~~~~~~~~~~~~~
在運行時,您可以通過讀取 ``cat /proc/sys/kernel/tainted`` 來查詢受汙染狀態。
如果返回 ``0`` ,則內核沒有受到汙染;任何其他數字都表示受到汙染的原因。解碼
這個數字的最簡單方法是使用腳本 ``tools/debugging/kernel-chktaint`` ,您的
發行版可能會將其作爲名爲 ``linux-tools`` 或 ``kernel-tools`` 的包的一部分提
供;如果沒有,您可以從
`git.kernel.org <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/tools/debugging/kernel-chktaint>`_
網站下載此腳本並用 ``sh kernel-chktaint`` 執行,它會在上面引用的日誌中有類似
語句的機器上列印這樣的內容::
Kernel is Tainted for following reasons:
* Proprietary module was loaded (#0)
* Kernel issued warning (#9)
* Externally-built ('out-of-tree') module was loaded (#12)
See Documentation/admin-guide/tainted-kernels.rst in the Linux kernel or
https://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html for
a more details explanation of the various taint flags.
Raw taint value as int/string: 4609/'P W O '
你也可以試著自己解碼這個數字。如果內核被汙染的原因只有一個,那麼這很簡單,
在本例中您可以通過下表找到數字。如果你需要解碼有多個原因的數字,因爲它是一
個位域(bitfield),其中每個位表示一個特定類型的汙染的存在或不存在,最好讓
前面提到的腳本來處理。但是如果您需要快速看一下,可以使用這個shell命令來檢查
設置了哪些位::
$ for i in $(seq 18); do echo $(($i-1)) $(($(cat /proc/sys/kernel/tainted)>>($i-1)&1));done
汙染狀態代碼表
~~~~~~~~~~~~~~~
=== ===== ====== ========================================================
位 日誌 數字 內核被汙染的原因
=== ===== ====== ========================================================
0 G/P 1 已加載專用模塊
1 _/F 2 模塊被強制加載
2 _/S 4 內核運行在不合規範的系統上
3 _/R 8 模塊被強制卸載
4 _/M 16 處理器報告了機器檢測異常(MCE)
5 _/B 32 引用了錯誤的頁或某些意外的頁標誌
6 _/U 64 用戶空間應用程式請求的汙染
7 _/D 128 內核最近死機了,即曾出現OOPS或BUG
8 _/A 256 ACPI表被用戶覆蓋
9 _/W 512 內核發出警告
10 _/C 1024 已加載staging驅動程序
11 _/I 2048 已應用平台固件缺陷的解決方案
12 _/O 4096 已加載外部構建(「樹外」)模塊
13 _/E 8192 已加載未簽名的模塊
14 _/L 16384 發生軟鎖定
15 _/K 32768 內核已實時打補丁
16 _/X 65536 備用汙染,爲發行版定義並使用
17 _/T 131072 內核是用結構隨機化插件構建的
=== ===== ====== ========================================================
註:字符 ``_`` 表示空白,以便於閱讀表。
汙染的更詳細解釋
~~~~~~~~~~~~~~~~~
0) ``G`` 加載的所有模塊都有GPL或兼容許可證, ``P`` 加載了任何專有模塊。
沒有MODULE_LICENSE(模塊許可證)或MODULE_LICENSE未被insmod認可爲GPL
兼容的模塊被認爲是專有的。
1) ``F`` 任何模塊被 ``insmod -f`` 強制加載, ``' '`` 所有模塊正常加載。
2) ``S`` 內核運行在不合規範的處理器或系統上:硬體已運行在不受支持的配置中,
因此無法保證正確執行。內核將被汙染,例如:
- 在x86上:PAE是通過intel CPU(如Pentium M)上的forcepae強制執行的,這些
CPU不報告PAE,但可能有功能實現,SMP內核在非官方支持的SMP Athlon CPU上
運行,MSR被暴露到用戶空間中。
- 在arm上:在某些CPU(如Keystone 2)上運行的內核,沒有啓用某些內核特性。
- 在arm64上:CPU之間存在不匹配的硬體特性,引導加載程序以不同的模式引導CPU。
- 某些驅動程序正在被用在不受支持的體系結構上(例如x86_64以外的其他系統
上的scsi/snic,非x86/x86_64/itanium上的scsi/ips,已經損壞了arm64上
irqchip/irq-gic的固件設置…)。
3) ``R`` 模塊被 ``rmmod -f`` 強制卸載, ``' '`` 所有模塊都正常卸載。
4) ``M`` 任何處理器報告了機器檢測異常, ``' '`` 未發生機器檢測異常。
5) ``B`` 頁面釋放函數發現錯誤的頁面引用或某些意外的頁面標誌。這表示硬體問題
或內核錯誤;日誌中應該有其他信息指示發生此汙染的原因。
6) ``U`` 用戶或用戶應用程式特意請求設置受汙染標誌,否則應爲 ``' '`` 。
7) ``D`` 內核最近死機了,即出現了OOPS或BUG。
8) ``A`` ACPI表被重寫。
9) ``W`` 內核之前已發出過警告(儘管有些警告可能會設置更具體的汙染標誌)。
10) ``C`` 已加載staging驅動程序。
11) ``I`` 內核正在處理平台固件(BIOS或類似軟體)中的嚴重錯誤。
12) ``O`` 已加載外部構建(「樹外」)模塊。
13) ``E`` 在支持模塊簽名的內核中加載了未簽名的模塊。
14) ``L`` 系統上先前發生過軟鎖定。
15) ``K`` 內核已經實時打了補丁。
16) ``X`` 備用汙染,由Linux發行版定義和使用。
17) ``T`` 內核構建時使用了randstruct插件,它可以有意生成非常不尋常的內核結構
布局(甚至是性能病態的布局),這在調試時非常有用。於構建時設置。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/unicode.rst
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <src.res@email.cn>
Unicode(統一碼)支持
======================
(英文版)上次更新:2005-01-17,版本號 1.4
此文檔由H. Peter Anvin <unicode@lanana.org>管理,是Linux註冊名稱與編號管理局
(Linux Assigned Names And Numbers Authority,LANANA)項目的一部分。
現行版本請見:
http://www.lanana.org/docs/unicode/admin-guide/unicode.rst
簡介
-----
Linux內核代碼已被重寫以使用Unicode來將字符映射到字體。下載一個Unicode到字體
(Unicode-to-font)表,八位字符集與UTF-8模式都將改用此字體來顯示。
這微妙地改變了八位字符表的語義。現在的四個字符表是:
=============== =============================== ================
映射代號 映射名稱 Escape代碼 (G0)
=============== =============================== ================
LAT1_MAP Latin-1 (ISO 8859-1) ESC ( B
GRAF_MAP DEC VT100 pseudographics ESC ( 0
IBMPC_MAP IBM code page 437 ESC ( U
USER_MAP User defined ESC ( K
=============== =============================== ================
特別是 ESC ( U 不再是「直通字體」,因爲字體可能與IBM字符集完全不同。
例如,即使加載了一個Latin-1字體,也允許使用塊圖形(block graphics)。
請注意,儘管這些代碼與ISO 2022類似,但這些代碼及其用途都與ISO 2022不匹配;
Linux有兩個八位代碼(G0和G1),而ISO 2022有四個七位代碼(G0-G3)。
根據Unicode標準/ISO 10646,U+F000到U+F8FF被保留用於作業系統範圍內的分配
(Unicode標準將其稱爲「團體區域(Corporate Zone)」,因爲這對於Linux是不準確
的,所以我們稱之爲「Linux區域」)。選擇U+F000作爲起點,因爲它允許直接映射
區域以2的大倍數開始(以防需要1024或2048個字符的字體)。這就留下U+E000到
U+EFFF作爲最終用戶區。
[v1.2]:Unicodes範圍從U+F000到U+F7FF已經被硬編碼爲直接映射到加載的字體,
繞過了翻譯表。用戶定義的映射現在默認爲U+F000到U+F0FF,模擬前述行爲。實際上,
此範圍可能較短;例如,vgacon只能處理256字符(U+F000..U+F0FF)或512字符
(U+F000..U+F1FF)字體。
Linux 區域中定義的實際字符
---------------------------
此外,還定義了Unicode 1.1.4中不存在的以下字符;這些字符由DEC VT圖形映射使用。
[v1.2]此用法已過時,不應再使用;請參見下文。
====== ======================================
U+F800 DEC VT GRAPHICS HORIZONTAL LINE SCAN 1
U+F801 DEC VT GRAPHICS HORIZONTAL LINE SCAN 3
U+F803 DEC VT GRAPHICS HORIZONTAL LINE SCAN 7
U+F804 DEC VT GRAPHICS HORIZONTAL LINE SCAN 9
====== ======================================
DEC VT220使用6x10字符矩陣,這些字符在DEC VT圖形字符集中形成一個平滑的過渡。
我省略了掃描5行,因爲它也被用作塊圖形字符,因此被編碼爲U+2500 FORMS LIGHT
HORIZONTAL。
[v1.3]:這些字符已正式添加到Unicode 3.2.0中;它們在U+23BA、U+23BB、U+23BC、
U+23BD處添加。Linux現在使用新值。
[v1.2]:添加了以下字符來表示常見的鍵盤符號,這些符號不太可能被添加到Unicode
中,因爲它們非常討厭地取決於特定供應商。當然,這是糟糕設計的一個好例子。
====== ======================================
U+F810 KEYBOARD SYMBOL FLYING FLAG
U+F811 KEYBOARD SYMBOL PULLDOWN MENU
U+F812 KEYBOARD SYMBOL OPEN APPLE
U+F813 KEYBOARD SYMBOL SOLID APPLE
====== ======================================
克林貢(Klingon)語支持
------------------------
1996年,Linux是世界上第一個添加對人工語言克林貢支持的作業系統,克林貢是由
Marc Okrand爲《星際迷航》電視連續劇創造的。這種編碼後來被徵募Unicode註冊表
(ConScript Unicode Registry,CSUR)採用,並建議(但最終被拒絕)納入Unicode
平面一。不過,它仍然是Linux區域中的Linux/CSUR私有分配。
這種編碼已經得到克林貢語言研究所(Klingon Language Institute)的認可。
有關更多信息,請聯繫他們:
http://www.kli.org/
由於Linux CZ開頭部分的字符大多是dingbats/symbols/forms類型,而且這是一種
語言,因此根據標準Unicode慣例,我將它放置在16單元的邊界上。
.. note::
這個範圍現在由徵募Unicode註冊表正式管理。規範性引用文件爲:
https://www.evertype.com/standards/csur/klingon.html
克林貢語有一個26個字符的字母表,一個10位數的位置數字書寫系統,從左到右
,從上到下書寫。
克林貢字母的幾種字形已經被提出。但是由於這組符號看起來始終是一致的,只有實際
的形狀不同,因此按照標準Unicode慣例,這些差異被認爲是字體變體。
====== =======================================================
U+F8D0 KLINGON LETTER A
U+F8D1 KLINGON LETTER B
U+F8D2 KLINGON LETTER CH
U+F8D3 KLINGON LETTER D
U+F8D4 KLINGON LETTER E
U+F8D5 KLINGON LETTER GH
U+F8D6 KLINGON LETTER H
U+F8D7 KLINGON LETTER I
U+F8D8 KLINGON LETTER J
U+F8D9 KLINGON LETTER L
U+F8DA KLINGON LETTER M
U+F8DB KLINGON LETTER N
U+F8DC KLINGON LETTER NG
U+F8DD KLINGON LETTER O
U+F8DE KLINGON LETTER P
U+F8DF KLINGON LETTER Q
- Written <q> in standard Okrand Latin transliteration
U+F8E0 KLINGON LETTER QH
- Written <Q> in standard Okrand Latin transliteration
U+F8E1 KLINGON LETTER R
U+F8E2 KLINGON LETTER S
U+F8E3 KLINGON LETTER T
U+F8E4 KLINGON LETTER TLH
U+F8E5 KLINGON LETTER U
U+F8E6 KLINGON LETTER V
U+F8E7 KLINGON LETTER W
U+F8E8 KLINGON LETTER Y
U+F8E9 KLINGON LETTER GLOTTAL STOP
U+F8F0 KLINGON DIGIT ZERO
U+F8F1 KLINGON DIGIT ONE
U+F8F2 KLINGON DIGIT TWO
U+F8F3 KLINGON DIGIT THREE
U+F8F4 KLINGON DIGIT FOUR
U+F8F5 KLINGON DIGIT FIVE
U+F8F6 KLINGON DIGIT SIX
U+F8F7 KLINGON DIGIT SEVEN
U+F8F8 KLINGON DIGIT EIGHT
U+F8F9 KLINGON DIGIT NINE
U+F8FD KLINGON COMMA
U+F8FE KLINGON FULL STOP
U+F8FF KLINGON SYMBOL FOR EMPIRE
====== =======================================================
其他虛構和人工字母
-------------------
自從分配了克林貢Linux Unicode塊之後,John Cowan <jcowan@reutershealth.com>
和 Michael Everson <everson@evertype.com> 建立了一個虛構和人工字母的註冊表。
徵募Unicode註冊表請訪問:
https://www.evertype.com/standards/csur/
所使用的範圍位於最終用戶區域的低端,因此無法進行規範化分配,但建議希望對虛構
字母進行編碼的人員使用這些代碼,以實現互操作性。對於克林貢語,CSUR採用了Linux
編碼。CSUR的人正在推動將Tengwar和Cirth添加到Unicode平面一;將克林貢添加到
Unicode平面一被拒絕,因此上述編碼仍然是官方的。
:orphan:
.. warning::
此文件的目的是爲讓中文讀者更容易閱讀和理解,而不是作爲一個分支。因此,
如果您對此文件有任何意見或改動,請先嘗試更新原始英文文件。如果要更改或
修正某處翻譯文件,請將意見或補丁發送給維護者(聯繫方式見下)。
.. note::
如果您發現本文檔與原始文件有任何不同或者有翻譯問題,請聯繫該文件的譯者,
或者發送電子郵件給胡皓文以獲取幫助:<src.res@email.cn>。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :ref:`Documentation/process/development-process.rst <development_process_main>`
:Translator: Alex Shi <alex.shi@linux.alibaba.com>
Hu Haowen <src.res@email.cn>
.. _tw_development_process_main:
內核開發過程指南
================
內容:
.. toctree::
:numbered:
:maxdepth: 2
1.Intro
2.Process
3.Early-stage
4.Coding
5.Posting
6.Followthrough
7.AdvancedTopics
8.Conclusion
本文檔的目的是幫助開發人員(及其經理)以最小的挫折感與開發社區合作。它試圖記錄這個社區如何以一種不熟悉Linux內核開發(或者實際上是自由軟體開發)的人可以訪問的方式工作。雖然這裡有一些技術資料,但這是一個面向過程的討論,不需要深入了解內核編程就可以理解。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -18940,6 +18940,14 @@ F: arch/x86/mm/testmmiotrace.c
F: include/linux/mmiotrace.h
F: kernel/trace/trace_mmiotrace.c
TRADITIONAL CHINESE DOCUMENTATION
M: Hu Haowen <src.res@email.cn>
L: linux-doc-tw-discuss@lists.sourceforge.net
S: Maintained
W: https://github.com/srcres258/linux-doc
T: git git://github.com/srcres258/linux-doc.git doc-zh-tw
F: Documentation/translations/zh_TW/
TRIVIAL PATCHES
M: Jiri Kosina <trivial@kernel.org>
S: Maintained
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册