Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull documentation updates from Jonathan Corbet:
"It has been a reasonably busy cycle for docs...

- Significant changes throughout the tree to bring Python code up to
current standards and raise the minimum Python required to 3.9

Much of this is preparatory to replacing the ancient Perl
scripts/kernel-doc horror with a slightly less horrifying Python
implementation, expected for 6.16

- Update the minimum Sphinx required to 3.4.3, allowing us to remove
a bunch of older compatibility code

- Rework and improve the generation of the ABI documentation

(All of the above done by Mauro)

- Lots of translation updates. Alex Shi and Yanteng Si are taking on
responsibility for the Chinese translations going forward; that
work will still get to you via docs-next

- Try to standardize the format for indicating a developer's
affiliation in commit tags

- Clarify the TAB's role in CoC enforcement actions

- Try to spell out the rules for when a commit tag can name another
developer without their explicit permission

Plus lots of other typo fixes and updates"

* tag 'docs-6.15' of git://git.lwn.net/linux: (98 commits)
docs/zh_CN: fix spelling mistake
docs/Chinese: change the disclaimer words
docs/zh_CN: Add snp-tdx-threat-model index Chinese translation
docs: driver-api: firmware: clarify userspace requirements
docs: clarify rules wrt tagging other people
docs: Remove outdated highuid.rst documentation
Documentation: dma-buf: heaps: Add heap name definitions
docs/.../submit-checklist: Use Documentation/admin-guide/abi.rst for cross-ref of README
docs: Correct installation instruction
Documentation: kcsan: fix "Plain Accesses and Data Races" URL in kcsan.rst
Documentation/CoC: Spell out the TAB role in enforcement decisions
Documentation: ocxl.rst: Update consortium site
scripts: get_feat.pl: substitute s390x with s390
scripts/kernel-doc: drop dead code for Wcontents_before_sections
scripts/kernel-doc: don't add not needed new lines
docs: driver-api/infiniband.rst: fix Kerneldoc markup
drivers: firewire: firewire-cdev.h: fix identation on a kernel-doc markup
drivers: media: intel-ipu3.h: fix identation on a kernel-doc markup
include/asm-generic/io.h: fix kerneldoc markup
Docs/arch/arm64: Fix spelling in amu.rst
...

+3802 -1919
+2 -1
Documentation/ABI/README
··· 1 - This directory attempts to document the ABI between the Linux kernel and 1 + This part of the documentation inside Documentation/ABI directory 2 + attempts to document the ABI between the Linux kernel and 2 3 userspace, and the relative stability of these interfaces. Due to the 3 4 everchanging nature of Linux, and the differing maturity levels, these 4 5 interfaces should be used by userspace programs in different ways.
+1 -1
Documentation/ABI/removed/sysfs-class-rfkill
··· 4 4 5 5 What: /sys/class/rfkill/rfkill[0-9]+/claim 6 6 Date: 09-Jul-2007 7 - KernelVersion v2.6.22 7 + KernelVersion: v2.6.22 8 8 Contact: linux-wireless@vger.kernel.org 9 9 Description: This file was deprecated because there no longer was a way to 10 10 claim just control over a single rfkill instance.
+6 -6
Documentation/ABI/stable/sysfs-class-rfkill
··· 16 16 17 17 What: /sys/class/rfkill/rfkill[0-9]+/name 18 18 Date: 09-Jul-2007 19 - KernelVersion v2.6.22 19 + KernelVersion: v2.6.22 20 20 Contact: linux-wireless@vger.kernel.org 21 21 Description: Name assigned by driver to this key (interface or driver name). 22 22 Values: arbitrary string. ··· 24 24 25 25 What: /sys/class/rfkill/rfkill[0-9]+/type 26 26 Date: 09-Jul-2007 27 - KernelVersion v2.6.22 27 + KernelVersion: v2.6.22 28 28 Contact: linux-wireless@vger.kernel.org 29 29 Description: Driver type string ("wlan", "bluetooth", etc). 30 30 Values: See include/linux/rfkill.h. ··· 32 32 33 33 What: /sys/class/rfkill/rfkill[0-9]+/persistent 34 34 Date: 09-Jul-2007 35 - KernelVersion v2.6.22 35 + KernelVersion: v2.6.22 36 36 Contact: linux-wireless@vger.kernel.org 37 37 Description: Whether the soft blocked state is initialised from non-volatile 38 38 storage at startup. ··· 44 44 45 45 What: /sys/class/rfkill/rfkill[0-9]+/state 46 46 Date: 09-Jul-2007 47 - KernelVersion v2.6.22 47 + KernelVersion: v2.6.22 48 48 Contact: linux-wireless@vger.kernel.org 49 49 Description: Current state of the transmitter. 50 50 This file was scheduled to be removed in 2014, but due to its ··· 67 67 68 68 What: /sys/class/rfkill/rfkill[0-9]+/hard 69 69 Date: 12-March-2010 70 - KernelVersion v2.6.34 70 + KernelVersion: v2.6.34 71 71 Contact: linux-wireless@vger.kernel.org 72 72 Description: Current hardblock state. This file is read only. 73 73 Values: A numeric value. ··· 81 81 82 82 What: /sys/class/rfkill/rfkill[0-9]+/soft 83 83 Date: 12-March-2010 84 - KernelVersion v2.6.34 84 + KernelVersion: v2.6.34 85 85 Contact: linux-wireless@vger.kernel.org 86 86 Description: Current softblock state. This file is read and write. 87 87 Values: A numeric value.
-10
Documentation/ABI/stable/sysfs-devices-system-cpu
··· 24 24 If set by a process it will be inherited by child processes. 25 25 Values: 64 bit unsigned integer (bit field) 26 26 27 - What: /sys/devices/system/cpu/cpuX/topology/physical_package_id 28 - Description: physical package id of cpuX. Typically corresponds to a physical 29 - socket number, but the actual value is architecture and platform 30 - dependent. 31 - Values: integer 32 - 33 27 What: /sys/devices/system/cpu/cpuX/topology/die_id 34 28 Description: the CPU die ID of cpuX. Typically it is the hardware platform's 35 29 identifier (rather than the kernel's). The actual value is ··· 79 85 What: /sys/devices/system/cpu/cpuX/topology/die_cpus 80 86 Description: internal kernel map of CPUs within the same die. 81 87 Values: hexadecimal bitmask. 82 - 83 - What: /sys/devices/system/cpu/cpuX/topology/ppin 84 - Description: per-socket protected processor inventory number 85 - Values: hexadecimal. 86 88 87 89 What: /sys/devices/system/cpu/cpuX/topology/die_cpus_list 88 90 Description: human-readable list of CPUs within the same die.
+2 -2
Documentation/ABI/stable/sysfs-driver-dma-idxd
··· 246 246 capability. 247 247 248 248 What: /sys/bus/dsa/devices/wq<m>.<n>/occupancy 249 - Date May 25, 2021 249 + Date: May 25, 2021 250 250 KernelVersion: 5.14.0 251 251 Contact: dmaengine@vger.kernel.org 252 252 Description: Show the current number of entries in this WQ if WQ Occupancy 253 253 Support bit WQ capabilities is 1. 254 254 255 255 What: /sys/bus/dsa/devices/wq<m>.<n>/enqcmds_retries 256 - Date Oct 29, 2021 256 + Date: Oct 29, 2021 257 257 KernelVersion: 5.17.0 258 258 Contact: dmaengine@vger.kernel.org 259 259 Description: Indicate the number of retires for an enqcmds submission on a sharedwq.
+1 -1
Documentation/ABI/testing/configfs-usb-gadget-midi2
··· 47 47 midi1_first_group The first UMP Group number for MIDI 1.0 (0-15) 48 48 midi1_num_groups The number of groups for MIDI 1.0 (0-16) 49 49 ui_hint 0: unknown, 1: receiver, 2: sender, 3: both 50 - midi_ci_verison Supported MIDI-CI version number (8 bit) 50 + midi_ci_version Supported MIDI-CI version number (8 bit) 51 51 is_midi1 Legacy MIDI 1.0 device (0, 1 or 2) 52 52 sysex8_streams Max number of SysEx8 streams (8 bit) 53 53 active Active FB flag (0 or 1)
+39 -39
Documentation/ABI/testing/sysfs-bus-coresight-devices-cti
··· 1 1 What: /sys/bus/coresight/devices/<cti-name>/enable 2 2 Date: March 2020 3 - KernelVersion 5.7 3 + KernelVersion: 5.7 4 4 Contact: Mike Leach or Mathieu Poirier 5 5 Description: (RW) Enable/Disable the CTI hardware. 6 6 7 7 What: /sys/bus/coresight/devices/<cti-name>/powered 8 8 Date: March 2020 9 - KernelVersion 5.7 9 + KernelVersion: 5.7 10 10 Contact: Mike Leach or Mathieu Poirier 11 11 Description: (Read) Indicate if the CTI hardware is powered. 12 12 13 13 What: /sys/bus/coresight/devices/<cti-name>/ctmid 14 14 Date: March 2020 15 - KernelVersion 5.7 15 + KernelVersion: 5.7 16 16 Contact: Mike Leach or Mathieu Poirier 17 17 Description: (Read) Display the associated CTM ID 18 18 19 19 What: /sys/bus/coresight/devices/<cti-name>/nr_trigger_cons 20 20 Date: March 2020 21 - KernelVersion 5.7 21 + KernelVersion: 5.7 22 22 Contact: Mike Leach or Mathieu Poirier 23 23 Description: (Read) Number of devices connected to triggers on this CTI 24 24 25 25 What: /sys/bus/coresight/devices/<cti-name>/triggers<N>/name 26 26 Date: March 2020 27 - KernelVersion 5.7 27 + KernelVersion: 5.7 28 28 Contact: Mike Leach or Mathieu Poirier 29 29 Description: (Read) Name of connected device <N> 30 30 31 31 What: /sys/bus/coresight/devices/<cti-name>/triggers<N>/in_signals 32 32 Date: March 2020 33 - KernelVersion 5.7 33 + KernelVersion: 5.7 34 34 Contact: Mike Leach or Mathieu Poirier 35 35 Description: (Read) Input trigger signals from connected device <N> 36 36 37 37 What: /sys/bus/coresight/devices/<cti-name>/triggers<N>/in_types 38 38 Date: March 2020 39 - KernelVersion 5.7 39 + KernelVersion: 5.7 40 40 Contact: Mike Leach or Mathieu Poirier 41 41 Description: (Read) Functional types for the input trigger signals 42 42 from connected device <N> 43 43 44 44 What: /sys/bus/coresight/devices/<cti-name>/triggers<N>/out_signals 45 45 Date: March 2020 46 - KernelVersion 5.7 46 + KernelVersion: 5.7 47 47 Contact: Mike Leach or Mathieu Poirier 48 48 Description: (Read) Output trigger signals to connected device <N> 49 49 50 50 What: /sys/bus/coresight/devices/<cti-name>/triggers<N>/out_types 51 51 Date: March 2020 52 - KernelVersion 5.7 52 + KernelVersion: 5.7 53 53 Contact: Mike Leach or Mathieu Poirier 54 54 Description: (Read) Functional types for the output trigger signals 55 55 to connected device <N> 56 56 57 57 What: /sys/bus/coresight/devices/<cti-name>/regs/inout_sel 58 58 Date: March 2020 59 - KernelVersion 5.7 59 + KernelVersion: 5.7 60 60 Contact: Mike Leach or Mathieu Poirier 61 61 Description: (RW) Select the index for inen and outen registers. 62 62 63 63 What: /sys/bus/coresight/devices/<cti-name>/regs/inen 64 64 Date: March 2020 65 - KernelVersion 5.7 65 + KernelVersion: 5.7 66 66 Contact: Mike Leach or Mathieu Poirier 67 67 Description: (RW) Read or write the CTIINEN register selected by inout_sel. 68 68 69 69 What: /sys/bus/coresight/devices/<cti-name>/regs/outen 70 70 Date: March 2020 71 - KernelVersion 5.7 71 + KernelVersion: 5.7 72 72 Contact: Mike Leach or Mathieu Poirier 73 73 Description: (RW) Read or write the CTIOUTEN register selected by inout_sel. 74 74 75 75 What: /sys/bus/coresight/devices/<cti-name>/regs/gate 76 76 Date: March 2020 77 - KernelVersion 5.7 77 + KernelVersion: 5.7 78 78 Contact: Mike Leach or Mathieu Poirier 79 79 Description: (RW) Read or write CTIGATE register. 80 80 81 81 What: /sys/bus/coresight/devices/<cti-name>/regs/asicctl 82 82 Date: March 2020 83 - KernelVersion 5.7 83 + KernelVersion: 5.7 84 84 Contact: Mike Leach or Mathieu Poirier 85 85 Description: (RW) Read or write ASICCTL register. 86 86 87 87 What: /sys/bus/coresight/devices/<cti-name>/regs/intack 88 88 Date: March 2020 89 - KernelVersion 5.7 89 + KernelVersion: 5.7 90 90 Contact: Mike Leach or Mathieu Poirier 91 91 Description: (Write) Write the INTACK register. 92 92 93 93 What: /sys/bus/coresight/devices/<cti-name>/regs/appset 94 94 Date: March 2020 95 - KernelVersion 5.7 95 + KernelVersion: 5.7 96 96 Contact: Mike Leach or Mathieu Poirier 97 97 Description: (RW) Set CTIAPPSET register to activate channel. Read back to 98 98 determine current value of register. 99 99 100 100 What: /sys/bus/coresight/devices/<cti-name>/regs/appclear 101 101 Date: March 2020 102 - KernelVersion 5.7 102 + KernelVersion: 5.7 103 103 Contact: Mike Leach or Mathieu Poirier 104 104 Description: (Write) Write APPCLEAR register to deactivate channel. 105 105 106 106 What: /sys/bus/coresight/devices/<cti-name>/regs/apppulse 107 107 Date: March 2020 108 - KernelVersion 5.7 108 + KernelVersion: 5.7 109 109 Contact: Mike Leach or Mathieu Poirier 110 110 Description: (Write) Write APPPULSE to pulse a channel active for one clock 111 111 cycle. 112 112 113 113 What: /sys/bus/coresight/devices/<cti-name>/regs/chinstatus 114 114 Date: March 2020 115 - KernelVersion 5.7 115 + KernelVersion: 5.7 116 116 Contact: Mike Leach or Mathieu Poirier 117 117 Description: (Read) Read current status of channel inputs. 118 118 119 119 What: /sys/bus/coresight/devices/<cti-name>/regs/choutstatus 120 120 Date: March 2020 121 - KernelVersion 5.7 121 + KernelVersion: 5.7 122 122 Contact: Mike Leach or Mathieu Poirier 123 123 Description: (Read) read current status of channel outputs. 124 124 125 125 What: /sys/bus/coresight/devices/<cti-name>/regs/triginstatus 126 126 Date: March 2020 127 - KernelVersion 5.7 127 + KernelVersion: 5.7 128 128 Contact: Mike Leach or Mathieu Poirier 129 129 Description: (Read) read current status of input trigger signals 130 130 131 131 What: /sys/bus/coresight/devices/<cti-name>/regs/trigoutstatus 132 132 Date: March 2020 133 - KernelVersion 5.7 133 + KernelVersion: 5.7 134 134 Contact: Mike Leach or Mathieu Poirier 135 135 Description: (Read) read current status of output trigger signals. 136 136 137 137 What: /sys/bus/coresight/devices/<cti-name>/channels/trigin_attach 138 138 Date: March 2020 139 - KernelVersion 5.7 139 + KernelVersion: 5.7 140 140 Contact: Mike Leach or Mathieu Poirier 141 141 Description: (Write) Attach a CTI input trigger to a CTM channel. 142 142 143 143 What: /sys/bus/coresight/devices/<cti-name>/channels/trigin_detach 144 144 Date: March 2020 145 - KernelVersion 5.7 145 + KernelVersion: 5.7 146 146 Contact: Mike Leach or Mathieu Poirier 147 147 Description: (Write) Detach a CTI input trigger from a CTM channel. 148 148 149 149 What: /sys/bus/coresight/devices/<cti-name>/channels/trigout_attach 150 150 Date: March 2020 151 - KernelVersion 5.7 151 + KernelVersion: 5.7 152 152 Contact: Mike Leach or Mathieu Poirier 153 153 Description: (Write) Attach a CTI output trigger to a CTM channel. 154 154 155 155 What: /sys/bus/coresight/devices/<cti-name>/channels/trigout_detach 156 156 Date: March 2020 157 - KernelVersion 5.7 157 + KernelVersion: 5.7 158 158 Contact: Mike Leach or Mathieu Poirier 159 159 Description: (Write) Detach a CTI output trigger from a CTM channel. 160 160 161 161 What: /sys/bus/coresight/devices/<cti-name>/channels/chan_gate_enable 162 162 Date: March 2020 163 - KernelVersion 5.7 163 + KernelVersion: 5.7 164 164 Contact: Mike Leach or Mathieu Poirier 165 165 Description: (RW) Enable CTIGATE for single channel (Write) or list enabled 166 166 channels through the gate (R). 167 167 168 168 What: /sys/bus/coresight/devices/<cti-name>/channels/chan_gate_disable 169 169 Date: March 2020 170 - KernelVersion 5.7 170 + KernelVersion: 5.7 171 171 Contact: Mike Leach or Mathieu Poirier 172 172 Description: (Write) Disable CTIGATE for single channel. 173 173 174 174 What: /sys/bus/coresight/devices/<cti-name>/channels/chan_set 175 175 Date: March 2020 176 - KernelVersion 5.7 176 + KernelVersion: 5.7 177 177 Contact: Mike Leach or Mathieu Poirier 178 178 Description: (Write) Activate a single channel. 179 179 180 180 What: /sys/bus/coresight/devices/<cti-name>/channels/chan_clear 181 181 Date: March 2020 182 - KernelVersion 5.7 182 + KernelVersion: 5.7 183 183 Contact: Mike Leach or Mathieu Poirier 184 184 Description: (Write) Deactivate a single channel. 185 185 186 186 What: /sys/bus/coresight/devices/<cti-name>/channels/chan_pulse 187 187 Date: March 2020 188 - KernelVersion 5.7 188 + KernelVersion: 5.7 189 189 Contact: Mike Leach or Mathieu Poirier 190 190 Description: (Write) Pulse a single channel - activate for a single clock cycle. 191 191 192 192 What: /sys/bus/coresight/devices/<cti-name>/channels/trigout_filtered 193 193 Date: March 2020 194 - KernelVersion 5.7 194 + KernelVersion: 5.7 195 195 Contact: Mike Leach or Mathieu Poirier 196 196 Description: (Read) List of output triggers filtered across all connections. 197 197 198 198 What: /sys/bus/coresight/devices/<cti-name>/channels/trig_filter_enable 199 199 Date: March 2020 200 - KernelVersion 5.7 200 + KernelVersion: 5.7 201 201 Contact: Mike Leach or Mathieu Poirier 202 202 Description: (RW) Enable or disable trigger output signal filtering. 203 203 204 204 What: /sys/bus/coresight/devices/<cti-name>/channels/chan_inuse 205 205 Date: March 2020 206 - KernelVersion 5.7 206 + KernelVersion: 5.7 207 207 Contact: Mike Leach or Mathieu Poirier 208 208 Description: (Read) show channels with at least one attached trigger signal. 209 209 210 210 What: /sys/bus/coresight/devices/<cti-name>/channels/chan_free 211 211 Date: March 2020 212 - KernelVersion 5.7 212 + KernelVersion: 5.7 213 213 Contact: Mike Leach or Mathieu Poirier 214 214 Description: (Read) show channels with no attached trigger signals. 215 215 216 216 What: /sys/bus/coresight/devices/<cti-name>/channels/chan_xtrigs_sel 217 217 Date: March 2020 218 - KernelVersion 5.7 218 + KernelVersion: 5.7 219 219 Contact: Mike Leach or Mathieu Poirier 220 220 Description: (RW) Write channel number to select a channel to view, read to 221 221 see selected channel number. 222 222 223 223 What: /sys/bus/coresight/devices/<cti-name>/channels/chan_xtrigs_in 224 224 Date: March 2020 225 - KernelVersion 5.7 225 + KernelVersion: 5.7 226 226 Contact: Mike Leach or Mathieu Poirier 227 227 Description: (Read) Read to see input triggers connected to selected view 228 228 channel. 229 229 230 230 What: /sys/bus/coresight/devices/<cti-name>/channels/chan_xtrigs_out 231 231 Date: March 2020 232 - KernelVersion 5.7 232 + KernelVersion: 5.7 233 233 Contact: Mike Leach or Mathieu Poirier 234 234 Description: (Read) Read to see output triggers connected to selected view 235 235 channel. 236 236 237 237 What: /sys/bus/coresight/devices/<cti-name>/channels/chan_xtrigs_reset 238 238 Date: March 2020 239 - KernelVersion 5.7 239 + KernelVersion: 5.7 240 240 Contact: Mike Leach or Mathieu Poirier 241 241 Description: (Write) Clear all channel / trigger programming.
+26 -26
Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
··· 1 1 What: /sys/bus/coresight/devices/<tpdm-name>/integration_test 2 2 Date: January 2023 3 - KernelVersion 6.2 3 + KernelVersion: 6.2 4 4 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 5 5 Description: 6 6 (Write) Run integration test for tpdm. Integration test ··· 14 14 15 15 What: /sys/bus/coresight/devices/<tpdm-name>/reset_dataset 16 16 Date: March 2023 17 - KernelVersion 6.7 17 + KernelVersion: 6.7 18 18 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 19 19 Description: 20 20 (Write) Reset the dataset of the tpdm. ··· 24 24 25 25 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_type 26 26 Date: March 2023 27 - KernelVersion 6.7 27 + KernelVersion: 6.7 28 28 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 29 29 Description: 30 30 (RW) Set/Get the trigger type of the DSB for tpdm. ··· 35 35 36 36 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_ts 37 37 Date: March 2023 38 - KernelVersion 6.7 38 + KernelVersion: 6.7 39 39 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 40 40 Description: 41 41 (RW) Set/Get the trigger timestamp of the DSB for tpdm. ··· 46 46 47 47 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_mode 48 48 Date: March 2023 49 - KernelVersion 6.7 49 + KernelVersion: 6.7 50 50 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 51 51 Description: 52 52 (RW) Set/Get the programming mode of the DSB for tpdm. ··· 60 60 61 61 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/ctrl_idx 62 62 Date: March 2023 63 - KernelVersion 6.7 63 + KernelVersion: 6.7 64 64 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 65 65 Description: 66 66 (RW) Set/Get the index number of the edge detection for the DSB ··· 69 69 70 70 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/ctrl_val 71 71 Date: March 2023 72 - KernelVersion 6.7 72 + KernelVersion: 6.7 73 73 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 74 74 Description: 75 75 Write a data to control the edge detection corresponding to ··· 85 85 86 86 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/ctrl_mask 87 87 Date: March 2023 88 - KernelVersion 6.7 88 + KernelVersion: 6.7 89 89 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 90 90 Description: 91 91 Write a data to mask the edge detection corresponding to the index ··· 97 97 98 98 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/edcr[0:15] 99 99 Date: March 2023 100 - KernelVersion 6.7 100 + KernelVersion: 6.7 101 101 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 102 102 Description: 103 103 Read a set of the edge control value of the DSB in TPDM. 104 104 105 105 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/edcmr[0:7] 106 106 Date: March 2023 107 - KernelVersion 6.7 107 + KernelVersion: 6.7 108 108 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 109 109 Description: 110 110 Read a set of the edge control mask of the DSB in TPDM. 111 111 112 112 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt/xpr[0:7] 113 113 Date: March 2023 114 - KernelVersion 6.7 114 + KernelVersion: 6.7 115 115 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 116 116 Description: 117 117 (RW) Set/Get the value of the trigger pattern for the DSB ··· 119 119 120 120 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt/xpmr[0:7] 121 121 Date: March 2023 122 - KernelVersion 6.7 122 + KernelVersion: 6.7 123 123 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 124 124 Description: 125 125 (RW) Set/Get the mask of the trigger pattern for the DSB ··· 127 127 128 128 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpr[0:7] 129 129 Date: March 2023 130 - KernelVersion 6.7 130 + KernelVersion: 6.7 131 131 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 132 132 Description: 133 133 (RW) Set/Get the value of the pattern for the DSB subunit TPDM. 134 134 135 135 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpmr[0:7] 136 136 Date: March 2023 137 - KernelVersion 6.7 137 + KernelVersion: 6.7 138 138 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 139 139 Description: 140 140 (RW) Set/Get the mask of the pattern for the DSB subunit TPDM. 141 141 142 142 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/enable_ts 143 143 Date: March 2023 144 - KernelVersion 6.7 144 + KernelVersion: 6.7 145 145 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 146 146 Description: 147 147 (Write) Set the pattern timestamp of DSB tpdm. Read ··· 153 153 154 154 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/set_type 155 155 Date: March 2023 156 - KernelVersion 6.7 156 + KernelVersion: 6.7 157 157 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 158 158 Description: 159 159 (Write) Set the pattern type of DSB tpdm. Read ··· 165 165 166 166 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr/msr[0:31] 167 167 Date: March 2023 168 - KernelVersion 6.7 168 + KernelVersion: 6.7 169 169 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 170 170 Description: 171 171 (RW) Set/Get the MSR(mux select register) for the DSB subunit ··· 173 173 174 174 What: /sys/bus/coresight/devices/<tpdm-name>/cmb_mode 175 175 Date: January 2024 176 - KernelVersion 6.9 176 + KernelVersion: 6.9 177 177 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 178 178 Description: (Write) Set the data collection mode of CMB tpdm. Continuous 179 179 change creates CMB data set elements on every CMBCLK edge. ··· 187 187 188 188 What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_patt/xpr[0:1] 189 189 Date: January 2024 190 - KernelVersion 6.9 190 + KernelVersion: 6.9 191 191 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 192 192 Description: 193 193 (RW) Set/Get the value of the trigger pattern for the CMB ··· 195 195 196 196 What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_patt/xpmr[0:1] 197 197 Date: January 2024 198 - KernelVersion 6.9 198 + KernelVersion: 6.9 199 199 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 200 200 Description: 201 201 (RW) Set/Get the mask of the trigger pattern for the CMB ··· 203 203 204 204 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpr[0:1] 205 205 Date: January 2024 206 - KernelVersion 6.9 206 + KernelVersion: 6.9 207 207 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 208 208 Description: 209 209 (RW) Set/Get the value of the pattern for the CMB subunit TPDM. 210 210 211 211 What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpmr[0:1] 212 212 Date: January 2024 213 - KernelVersion 6.9 213 + KernelVersion: 6.9 214 214 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 215 215 Description: 216 216 (RW) Set/Get the mask of the pattern for the CMB subunit TPDM. 217 217 218 218 What: /sys/bus/coresight/devices/<tpdm-name>/cmb_patt/enable_ts 219 219 Date: January 2024 220 - KernelVersion 6.9 220 + KernelVersion: 6.9 221 221 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 222 222 Description: 223 223 (Write) Set the pattern timestamp of CMB tpdm. Read ··· 229 229 230 230 What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_ts 231 231 Date: January 2024 232 - KernelVersion 6.9 232 + KernelVersion: 6.9 233 233 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 234 234 Description: 235 235 (RW) Set/Get the trigger timestamp of the CMB for tpdm. ··· 240 240 241 241 What: /sys/bus/coresight/devices/<tpdm-name>/cmb_ts_all 242 242 Date: January 2024 243 - KernelVersion 6.9 243 + KernelVersion: 6.9 244 244 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 245 245 Description: 246 246 (RW) Read or write the status of timestamp upon all interface. ··· 252 252 253 253 What: /sys/bus/coresight/devices/<tpdm-name>/cmb_msr/msr[0:31] 254 254 Date: January 2024 255 - KernelVersion 6.9 255 + KernelVersion: 6.9 256 256 Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com> 257 257 Description: 258 258 (RW) Set/Get the MSR(mux select register) for the CMB subunit
+2 -2
Documentation/ABI/testing/sysfs-fs-f2fs
··· 347 347 - [c] means add/del cold file extension 348 348 349 349 What: /sys/fs/f2fs/<disk>/unusable 350 - Date April 2019 350 + Date: April 2019 351 351 Contact: "Daniel Rosenberg" <drosen@google.com> 352 352 Description: If checkpoint=disable, it displays the number of blocks that 353 353 are unusable. ··· 355 355 would be unusable if checkpoint=disable were to be set. 356 356 357 357 What: /sys/fs/f2fs/<disk>/encoding 358 - Date July 2019 358 + Date: July 2019 359 359 Contact: "Daniel Rosenberg" <drosen@google.com> 360 360 Description: Displays name and version of the encoding set for the filesystem. 361 361 If no encoding is set, displays (none)
+1 -1
Documentation/ABI/testing/sysfs-power
··· 131 131 CAUTION: Using it will cause your machine's real-time (CMOS) 132 132 clock to be set to a random invalid time after a resume. 133 133 134 - What; /sys/power/pm_trace_dev_match 134 + What: /sys/power/pm_trace_dev_match 135 135 Date: October 2010 136 136 Contact: James Hogan <jhogan@kernel.org> 137 137 Description:
+1 -1
Documentation/Makefile
··· 12 12 13 13 # Check for broken ABI files 14 14 ifeq ($(CONFIG_WARN_ABI_ERRORS),y) 15 - $(shell $(srctree)/scripts/get_abi.pl validate --dir $(srctree)/Documentation/ABI) 15 + $(shell $(srctree)/scripts/get_abi.py --dir $(srctree)/Documentation/ABI validate) 16 16 endif 17 17 18 18 # You can set these variables from the command line.
+1 -1
Documentation/admin-guide/README.rst
··· 165 165 166 166 "make xconfig" Qt based configuration tool. 167 167 168 - "make gconfig" GTK+ based configuration tool. 168 + "make gconfig" GTK based configuration tool. 169 169 170 170 "make oldconfig" Default all questions based on the contents of 171 171 your existing ./.config file and asking about
+7
Documentation/admin-guide/abi-obsolete-files.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + Obsolete ABI Files 4 + ================== 5 + 6 + .. kernel-abi:: obsolete 7 + :no-symbols:
+4 -2
Documentation/admin-guide/abi-obsolete.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 1 3 ABI obsolete symbols 2 4 ==================== 3 5 ··· 9 7 The description of the interface will document the reason why it is 10 8 obsolete and when it can be expected to be removed. 11 9 12 - .. kernel-abi:: ABI/obsolete 13 - :rst: 10 + .. kernel-abi:: obsolete 11 + :no-files:
+7
Documentation/admin-guide/abi-removed-files.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + Removed ABI Files 4 + ================= 5 + 6 + .. kernel-abi:: removed 7 + :no-symbols:
+4 -2
Documentation/admin-guide/abi-removed.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 1 3 ABI removed symbols 2 4 =================== 3 5 4 - .. kernel-abi:: ABI/removed 5 - :rst: 6 + .. kernel-abi:: removed 7 + :no-files:
+7
Documentation/admin-guide/abi-stable-files.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + Stable ABI Files 4 + ================ 5 + 6 + .. kernel-abi:: stable 7 + :no-symbols:
+4 -2
Documentation/admin-guide/abi-stable.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 1 3 ABI stable symbols 2 4 ================== 3 5 ··· 12 10 Most interfaces (like syscalls) are expected to never change and always 13 11 be available. 14 12 15 - .. kernel-abi:: ABI/stable 16 - :rst: 13 + .. kernel-abi:: stable 14 + :no-files:
+7
Documentation/admin-guide/abi-testing-files.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + Testing ABI Files 4 + ================= 5 + 6 + .. kernel-abi:: testing 7 + :no-symbols:
+4 -2
Documentation/admin-guide/abi-testing.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 1 3 ABI testing symbols 2 4 =================== 3 5 ··· 18 16 name to the description of these interfaces, so that the kernel 19 17 developers can easily notify them if any changes occur. 20 18 21 - .. kernel-abi:: ABI/testing 22 - :rst: 19 + .. kernel-abi:: testing 20 + :no-files:
+18
Documentation/admin-guide/abi.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 1 3 ===================== 2 4 Linux ABI description 3 5 ===================== 6 + 7 + .. kernel-abi:: README 8 + 9 + ABI symbols 10 + ----------- 4 11 5 12 .. toctree:: 6 13 :maxdepth: 2 ··· 16 9 abi-testing 17 10 abi-obsolete 18 11 abi-removed 12 + 13 + ABI files 14 + --------- 15 + 16 + .. toctree:: 17 + :maxdepth: 2 18 + 19 + abi-stable-files 20 + abi-testing-files 21 + abi-obsolete-files 22 + abi-removed-files
+1 -1
Documentation/admin-guide/gpio/gpio-sim.rst
··· 71 71 ``'line<offset>'`` (e.g. ``'line0'``, ``'line20'``, etc.) as the name will be 72 72 used by the module to assign the config to the specific line at given offset. 73 73 74 - Once the confiuration is complete, the ``'live'`` attribute must be set to 1 in 74 + Once the configuration is complete, the ``'live'`` attribute must be set to 1 in 75 75 order to instantiate the chip. It can be set back to 0 to destroy the simulated 76 76 chip. The module will synchronously wait for the new simulated device to be 77 77 successfully probed and if this doesn't happen, writing to ``'live'`` will
+1 -1
Documentation/admin-guide/gpio/gpio-virtuser.rst
··· 92 92 Activating GPIO consumers 93 93 ------------------------- 94 94 95 - Once the confiuration is complete, the ``'live'`` attribute must be set to 1 in 95 + Once the configuration is complete, the ``'live'`` attribute must be set to 1 in 96 96 order to instantiate the consumer. It can be set back to 0 to destroy the 97 97 virtual device. The module will synchronously wait for the new simulated device 98 98 to be successfully probed and if this doesn't happen, writing to ``'live'`` will
-80
Documentation/admin-guide/highuid.rst
··· 1 - =================================================== 2 - Notes on the change from 16-bit UIDs to 32-bit UIDs 3 - =================================================== 4 - 5 - :Author: Chris Wing <wingc@umich.edu> 6 - :Last updated: January 11, 2000 7 - 8 - - kernel code MUST take into account __kernel_uid_t and __kernel_uid32_t 9 - when communicating between user and kernel space in an ioctl or data 10 - structure. 11 - 12 - - kernel code should use uid_t and gid_t in kernel-private structures and 13 - code. 14 - 15 - What's left to be done for 32-bit UIDs on all Linux architectures: 16 - 17 - - Disk quotas have an interesting limitation that is not related to the 18 - maximum UID/GID. They are limited by the maximum file size on the 19 - underlying filesystem, because quota records are written at offsets 20 - corresponding to the UID in question. 21 - Further investigation is needed to see if the quota system can cope 22 - properly with huge UIDs. If it can deal with 64-bit file offsets on all 23 - architectures, this should not be a problem. 24 - 25 - - Decide whether or not to keep backwards compatibility with the system 26 - accounting file, or if we should break it as the comments suggest 27 - (currently, the old 16-bit UID and GID are still written to disk, and 28 - part of the former pad space is used to store separate 32-bit UID and 29 - GID) 30 - 31 - - Need to validate that OS emulation calls the 16-bit UID 32 - compatibility syscalls, if the OS being emulated used 16-bit UIDs, or 33 - uses the 32-bit UID system calls properly otherwise. 34 - 35 - This affects at least: 36 - 37 - - iBCS on Intel 38 - 39 - - sparc32 emulation on sparc64 40 - (need to support whatever new 32-bit UID system calls are added to 41 - sparc32) 42 - 43 - - Validate that all filesystems behave properly. 44 - 45 - At present, 32-bit UIDs _should_ work for: 46 - 47 - - ext2 48 - - ufs 49 - - isofs 50 - - nfs 51 - - coda 52 - - udf 53 - 54 - Ioctl() fixups have been made for: 55 - 56 - - ncpfs 57 - - smbfs 58 - 59 - Filesystems with simple fixups to prevent 16-bit UID wraparound: 60 - 61 - - minix 62 - - sysv 63 - - qnx4 64 - 65 - Other filesystems have not been checked yet. 66 - 67 - - The ncpfs and smpfs filesystems cannot presently use 32-bit UIDs in 68 - all ioctl()s. Some new ioctl()s have been added with 32-bit UIDs, but 69 - more are needed. (as well as new user<->kernel data structures) 70 - 71 - - The ELF core dump format only supports 16-bit UIDs on arm, i386, m68k, 72 - sh, and sparc32. Fixing this is probably not that important, but would 73 - require adding a new ELF section. 74 - 75 - - The ioctl()s used to control the in-kernel NFS server only support 76 - 16-bit UIDs on arm, i386, m68k, sh, and sparc32. 77 - 78 - - make sure that the UID mapping feature of AX25 networking works properly 79 - (it should be safe because it's always used a 32-bit integer to 80 - communicate between user and kernel)
-1
Documentation/admin-guide/index.rst
··· 187 187 .. toctree:: 188 188 :maxdepth: 1 189 189 190 - highuid 191 190 ldm 192 191 unicode 193 192
+26 -49
Documentation/admin-guide/iostats.rst
··· 2 2 I/O statistics fields 3 3 ===================== 4 4 5 - Since 2.4.20 (and some versions before, with patches), and 2.5.45, 6 - more extensive disk statistics have been introduced to help measure disk 7 - activity. Tools such as ``sar`` and ``iostat`` typically interpret these and do 8 - the work for you, but in case you are interested in creating your own 9 - tools, the fields are explained here. 5 + The kernel exposes disk statistics via ``/proc/diskstats`` and 6 + ``/sys/block/<device>/stat``. These stats are usually accessed via tools 7 + such as ``sar`` and ``iostat``. 10 8 11 - In 2.4 now, the information is found as additional fields in 12 - ``/proc/partitions``. In 2.6 and upper, the same information is found in two 13 - places: one is in the file ``/proc/diskstats``, and the other is within 14 - the sysfs file system, which must be mounted in order to obtain 15 - the information. Throughout this document we'll assume that sysfs 16 - is mounted on ``/sys``, although of course it may be mounted anywhere. 17 - Both ``/proc/diskstats`` and sysfs use the same source for the information 18 - and so should not differ. 9 + Here are examples using a disk with two partitions:: 19 10 20 - Here are examples of these different formats:: 11 + /proc/diskstats: 12 + 259 0 nvme0n1 255999 814 12369153 47919 996852 81 36123024 425995 0 301795 580470 0 0 0 0 60602 106555 13 + 259 1 nvme0n1p1 492 813 17572 96 848 81 108288 210 0 76 307 0 0 0 0 0 0 14 + 259 2 nvme0n1p2 255401 1 12343477 47799 996004 0 36014736 425784 0 344336 473584 0 0 0 0 0 0 21 15 22 - 2.4: 23 - 3 0 39082680 hda 446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160 24 - 3 1 9221278 hda1 35486 0 35496 38030 0 0 0 0 0 38030 38030 16 + /sys/block/nvme0n1/stat: 17 + 255999 814 12369153 47919 996858 81 36123056 426009 0 301809 580491 0 0 0 0 60605 106562 25 18 26 - 2.6+ sysfs: 27 - 446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160 28 - 35486 38030 38030 38030 19 + /sys/block/nvme0n1/nvme0n1p1/stat: 20 + 492 813 17572 96 848 81 108288 210 0 76 307 0 0 0 0 0 0 29 21 30 - 2.6+ diskstats: 31 - 3 0 hda 446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160 32 - 3 1 hda1 35486 38030 38030 38030 22 + Both files contain the same 17 statistics. ``/sys/block/<device>/stat`` 23 + contains the fields for ``<device>``. In ``/proc/diskstats`` the fields 24 + are prefixed with the major and minor device numbers and the device 25 + name. In the example above, the first stat value for ``nvme0n1`` is 26 + 255999 in both files. 33 27 34 - 4.18+ diskstats: 35 - 3 0 hda 446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160 0 0 0 0 28 + The sysfs ``stat`` file is efficient for monitoring a small, known set 29 + of disks. If you're tracking a large number of devices, 30 + ``/proc/diskstats`` is often the better choice since it avoids the 31 + overhead of opening and closing multiple files for each snapshot. 36 32 37 - On 2.4 you might execute ``grep 'hda ' /proc/partitions``. On 2.6+, you have 38 - a choice of ``cat /sys/block/hda/stat`` or ``grep 'hda ' /proc/diskstats``. 39 - 40 - The advantage of one over the other is that the sysfs choice works well 41 - if you are watching a known, small set of disks. ``/proc/diskstats`` may 42 - be a better choice if you are watching a large number of disks because 43 - you'll avoid the overhead of 50, 100, or 500 or more opens/closes with 44 - each snapshot of your disk statistics. 45 - 46 - In 2.4, the statistics fields are those after the device name. In 47 - the above example, the first field of statistics would be 446216. 48 - By contrast, in 2.6+ if you look at ``/sys/block/hda/stat``, you'll 49 - find just the 15 fields, beginning with 446216. If you look at 50 - ``/proc/diskstats``, the 15 fields will be preceded by the major and 51 - minor device numbers, and device name. Each of these formats provides 52 - 15 fields of statistics, each meaning exactly the same things. 53 - All fields except field 9 are cumulative since boot. Field 9 should 54 - go to zero as I/Os complete; all others only increase (unless they 55 - overflow and wrap). Wrapping might eventually occur on a very busy 56 - or long-lived system; so applications should be prepared to deal with 57 - it. Regarding wrapping, the types of the fields are either unsigned 58 - int (32 bit) or unsigned long (32-bit or 64-bit, depending on your 59 - machine) as noted per-field below. Unless your observations are very 60 - spread in time, these fields should not wrap twice before you notice it. 33 + All fields are cumulative, monotonic counters, except for field 9, which 34 + resets to zero as I/Os complete. The remaining fields reset at boot, on 35 + device reattachment or reinitialization, or when the underlying counter 36 + overflows. Applications reading these counters should detect and handle 37 + resets when comparing stat snapshots. 61 38 62 39 Each set of stats only applies to the indicated device; if you want 63 40 system-wide stats you'll have to find all the devices and sum them all up.
+1 -1
Documentation/admin-guide/kernel-parameters.txt
··· 6084 6084 is assumed to be I/O ports; otherwise it is memory. 6085 6085 6086 6086 reserve_mem= [RAM] 6087 - Format: nn[KNG]:<align>:<label> 6087 + Format: nn[KMG]:<align>:<label> 6088 6088 Reserve physical memory and label it with a name that 6089 6089 other subsystems can use to access it. This is typically 6090 6090 used for systems that do not wipe the RAM, and this command
+1 -1
Documentation/admin-guide/thunderbolt.rst
··· 28 28 a database of the authorized devices and prompts users for new connections. 29 29 30 30 More details about the sysfs interface for Thunderbolt devices can be 31 - found in ``Documentation/ABI/testing/sysfs-bus-thunderbolt``. 31 + found in Documentation/ABI/testing/sysfs-bus-thunderbolt. 32 32 33 33 Those users who just want to connect any device without any sort of 34 34 manual work can add following line to
+1 -1
Documentation/admin-guide/workload-tracing.rst
··· 82 82 scripts/ver_linux is a good way to check if your system already has 83 83 the necessary tools:: 84 84 85 - sudo apt-get build-essentials flex bison yacc 85 + sudo apt-get install build-essential flex bison yacc 86 86 sudo apt install libelf-dev systemtap-sdt-dev libslang2-dev libperl-dev libdw-dev 87 87 88 88 cscope is a good tool to browse kernel sources. Let's install it now::
+1 -1
Documentation/arch/arm64/amu.rst
··· 80 80 EL1 (kernel). Therefore, firmware should still ensure accesses to AMU registers 81 81 are not trapped in EL2/EL3. 82 82 83 - The fixed counters of AMUv1 are accessible though the following system 83 + The fixed counters of AMUv1 are accessible through the following system 84 84 register definitions: 85 85 86 86 - SYS_AMEVCNTR0_CORE_EL0
+1 -1
Documentation/arch/arm64/asymmetric-32bit.rst
··· 55 55 56 56 The subset of CPUs capable of running 32-bit tasks is described in 57 57 ``/sys/devices/system/cpu/aarch32_el0`` and is documented further in 58 - ``Documentation/ABI/testing/sysfs-devices-system-cpu``. 58 + Documentation/ABI/testing/sysfs-devices-system-cpu. 59 59 60 60 **Note:** CPUs are advertised by this file as they are detected and so 61 61 late-onlining of 32-bit-capable CPUs can result in the file contents
+1 -1
Documentation/conf.py
··· 47 47 # -- General configuration ------------------------------------------------ 48 48 49 49 # If your documentation needs a minimal Sphinx version, state it here. 50 - needs_sphinx = '2.4.4' 50 + needs_sphinx = '3.4.3' 51 51 52 52 # Add any Sphinx extension module names here, as strings. They can be 53 53 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+2 -2
Documentation/core-api/min_heap.rst
··· 47 47 48 48 #define MIN_HEAP_PREALLOCATED(_type, _name, _nr) 49 49 struct _name { 50 - int nr; /* Number of elements in the heap */ 51 - int size; /* Maximum number of elements that can be held */ 50 + size_t nr; /* Number of elements in the heap */ 51 + size_t size; /* Maximum number of elements that can be held */ 52 52 _type *data; /* Pointer to the heap data */ 53 53 _type preallocated[_nr]; /* Static preallocated array */ 54 54 }
+1 -1
Documentation/dev-tools/kcsan.rst
··· 203 203 least one is a write. For a more thorough discussion and definition, see `"Plain 204 204 Accesses and Data Races" in the LKMM`_. 205 205 206 - .. _"Plain Accesses and Data Races" in the LKMM: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/memory-model/Documentation/explanation.txt#n1922 206 + .. _"Plain Accesses and Data Races" in the LKMM: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/memory-model/Documentation/explanation.txt?id=8f6629c004b193d23612641c3607e785819e97ab#n2164 207 207 208 208 Relationship with the Linux-Kernel Memory Consistency Model (LKMM) 209 209 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1 -1
Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml
··· 40 40 41 41 microchip,rx-int-gpios: 42 42 description: 43 - GPIO phandle of GPIO connected to to INT1 pin of the MCP251XFD, which 43 + GPIO phandle of GPIO connected to INT1 pin of the MCP251XFD, which 44 44 signals a pending RX interrupt. 45 45 maxItems: 1 46 46
+5
Documentation/driver-api/firmware/firmware-usage-guidelines.rst
··· 42 42 deprecating old major versions, then this should only be done as a 43 43 last option, and be stated clearly in all communications. 44 44 45 + * Firmware files that affect the User API (UAPI) shall not introduce 46 + changes that break existing userspace programs. Updates to such firmware 47 + must ensure backward compatibility with existing userspace applications. 48 + This includes maintaining consistent interfaces and behaviors that 49 + userspace programs rely on.
+2 -2
Documentation/driver-api/generic-counter.rst
··· 467 467 Translates counter data to the standard Counter sysfs interface format 468 468 and vice versa. 469 469 470 - Please refer to the ``Documentation/ABI/testing/sysfs-bus-counter`` file 470 + Please refer to the Documentation/ABI/testing/sysfs-bus-counter file 471 471 for a detailed breakdown of the available Generic Counter interface 472 472 sysfs attributes. 473 473 ··· 483 483 Several sysfs attributes are generated by the Generic Counter interface, 484 484 and reside under the ``/sys/bus/counter/devices/counterX`` directory, 485 485 where ``X`` is to the respective counter device id. Please see 486 - ``Documentation/ABI/testing/sysfs-bus-counter`` for detailed information 486 + Documentation/ABI/testing/sysfs-bus-counter for detailed information 487 487 on each Generic Counter interface sysfs attribute. 488 488 489 489 Through these sysfs attributes, programs and scripts may interact with
+1 -1
Documentation/driver-api/iio/core.rst
··· 60 60 * :file:`sampling_frequency_available`, available discrete set of sampling 61 61 frequency values for device. 62 62 * Available standard attributes for IIO devices are described in the 63 - :file:`Documentation/ABI/testing/sysfs-bus-iio` file in the Linux kernel 63 + :file:Documentation/ABI/testing/sysfs-bus-iio file in the Linux kernel 64 64 sources. 65 65 66 66 IIO device channels
+8 -8
Documentation/driver-api/infiniband.rst
··· 77 77 :internal: 78 78 79 79 .. kernel-doc:: drivers/infiniband/ulp/iser/iscsi_iser.c 80 - :functions: iscsi_iser_pdu_alloc iser_initialize_task_headers \ 81 - iscsi_iser_task_init iscsi_iser_mtask_xmit iscsi_iser_task_xmit \ 82 - iscsi_iser_cleanup_task iscsi_iser_check_protection \ 83 - iscsi_iser_conn_create iscsi_iser_conn_bind \ 84 - iscsi_iser_conn_start iscsi_iser_conn_stop \ 85 - iscsi_iser_session_destroy iscsi_iser_session_create \ 86 - iscsi_iser_set_param iscsi_iser_ep_connect iscsi_iser_ep_poll \ 87 - iscsi_iser_ep_disconnect 80 + :functions: iscsi_iser_pdu_alloc iser_initialize_task_headers 81 + iscsi_iser_task_init iscsi_iser_mtask_xmit iscsi_iser_task_xmit 82 + iscsi_iser_cleanup_task iscsi_iser_check_protection 83 + iscsi_iser_conn_create iscsi_iser_conn_bind 84 + iscsi_iser_conn_start iscsi_iser_conn_stop 85 + iscsi_iser_session_destroy iscsi_iser_session_create 86 + iscsi_iser_set_param iscsi_iser_ep_connect iscsi_iser_ep_poll 87 + iscsi_iser_ep_disconnect 88 88 89 89 .. kernel-doc:: drivers/infiniband/ulp/iser/iser_initiator.c 90 90 :internal:
+1 -1
Documentation/driver-api/media/drivers/zoran.rst
··· 222 222 Ireland, Nigeria, South Africa. 223 223 224 224 The CCIR - N uses the PAL colorsystem and PAL frame size but the NTSC framerate, 225 - and is used in Argentinia, Uruguay, an a few others 225 + and is used in Argentina, Uruguay, an a few others 226 226 227 227 We do not talk about how the audio is broadcast ! 228 228
+1 -1
Documentation/driver-api/media/maintainer-entry-profile.rst
··· 116 116 .. [3] The ``v4l2-compliance`` also covers the media controller usage inside 117 117 V4L2 drivers. 118 118 119 - Other compilance tools are under development to check other parts of the 119 + Other compliance tools are under development to check other parts of the 120 120 subsystem. 121 121 122 122 Those tests need to pass before the patches go upstream.
+3 -3
Documentation/driver-api/nvdimm/nvdimm.rst
··· 535 535 char devname[50]; 536 536 537 537 snprintf(devname, sizeof(devname), "namespace%d.%d", 538 - ndctl_region_get_id(region), paramaters->id); 538 + ndctl_region_get_id(region), parameters->id); 539 539 540 540 ndctl_namespace_set_alt_name(ndns, devname); 541 541 /* 'uuid' must be set prior to setting size! */ 542 - ndctl_namespace_set_uuid(ndns, paramaters->uuid); 543 - ndctl_namespace_set_size(ndns, paramaters->size); 542 + ndctl_namespace_set_uuid(ndns, parameters->uuid); 543 + ndctl_namespace_set_size(ndns, parameters->size); 544 544 /* unlike pmem namespaces, blk namespaces have a sector size */ 545 545 if (parameters->lbasize) 546 546 ndctl_namespace_set_sector_size(ndns, parameters->lbasize);
+1 -1
Documentation/driver-api/pm/devices.rst
··· 358 358 is probed against the device in question by passing them to the 359 359 :c:func:`dev_pm_set_driver_flags` helper function.] If the first of 360 360 these flags is set, the PM core will not apply the direct-complete 361 - procedure described above to the given device and, consequenty, to any 361 + procedure described above to the given device and, consequently, to any 362 362 of its ancestors. The second flag, when set, informs the middle layer 363 363 code (bus types, device types, PM domains, classes) that it should take 364 364 the return value of the ``->prepare`` callback provided by the driver
+1 -1
Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
··· 20 20 | openrisc: | TODO | 21 21 | parisc: | ok | 22 22 | powerpc: | ok | 23 - | riscv: | ok | 23 + | riscv: | TODO | 24 24 | s390: | ok | 25 25 | sh: | TODO | 26 26 | sparc: | TODO |
+1 -1
Documentation/features/list-arch.sh
··· 6 6 # (If no arguments are given then it will print the host architecture's status.) 7 7 # 8 8 9 - ARCH=${1:-$(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/')} 9 + ARCH=${1:-$(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/' | sed 's/s390x/s390/')} 10 10 11 11 $(dirname $0)/../../scripts/get_feat.pl list --arch $ARCH
+1 -1
Documentation/filesystems/9p.rst
··· 90 90 91 91 $ diod -f -n -d 0 -S -l 0.0.0.0:9999 -e $PWD 92 92 93 - Optionaly scan your bus if there are more then one usbg gadgets to find their path:: 93 + Optionally scan your bus if there are more then one usbg gadgets to find their path:: 94 94 95 95 $ python $kernel_dir/tools/usb/p9_fwd.py list 96 96
+2 -2
Documentation/filesystems/bcachefs/SubmittingPatches.rst
··· 30 30 === 31 31 32 32 Instead of running your tests locally, when running the full test suite it's 33 - prefereable to let a server farm do it in parallel, and then have the results 33 + preferable to let a server farm do it in parallel, and then have the results 34 34 in a nice test dashboard (which can tell you which failures are new, and 35 35 presents results in a git log view, avoiding the need for most bisecting). 36 36 ··· 68 68 land - use them. Use them judiciously, and not as a replacement for proper 69 69 error handling, but use them. 70 70 71 - - Does it need to be performance tested? Should we add new peformance counters? 71 + - Does it need to be performance tested? Should we add new performance counters? 72 72 73 73 bcachefs has a set of persistent runtime counters which can be viewed with 74 74 the 'bcachefs fs top' command; this should give users a basic idea of what
+1 -1
Documentation/filesystems/coda.rst
··· 141 141 a process P which accessing a Coda file. It makes a system call which 142 142 traps to the OS kernel. Examples of such calls trapping to the kernel 143 143 are ``read``, ``write``, ``open``, ``close``, ``create``, ``mkdir``, 144 - ``rmdir``, ``chmod`` in a Unix ontext. Similar calls exist in the Win32 144 + ``rmdir``, ``chmod`` in a Unix context. Similar calls exist in the Win32 145 145 environment, and are named ``CreateFile``. 146 146 147 147 Generally the operating system handles the request in a virtual
+1 -1
Documentation/filesystems/debugfs.rst
··· 220 220 221 221 A call to debugfs_change_name() will give a new name to an existing debugfs 222 222 file, always in the same directory. The new_name must not exist prior 223 - to the call; the return value is 0 on success and -E... on failuer. 223 + to the call; the return value is 0 on success and -E... on failure. 224 224 Symbolic links can be created with debugfs_create_symlink(). 225 225 226 226 There is one important thing that all debugfs users must take into account:
+1 -1
Documentation/filesystems/netfs_library.rst
··· 515 515 the cache to expand a request in either direction. This allows the cache to 516 516 size the request appropriately for the cache granularity. 517 517 518 - The function is passed poiners to the start and length in its parameters, 518 + The function is passed pointers to the start and length in its parameters, 519 519 plus the size of the file for reference, and adjusts the start and length 520 520 appropriately. It should return one of: 521 521
+1 -1
Documentation/filesystems/xfs/xfs-delayed-logging-design.rst
··· 219 219 of a cycle number - the number of times the log has been overwritten - and the 220 220 offset into the log. A LSN carries the cycle in the upper 32 bits and the 221 221 offset in the lower 32 bits. The offset is in units of "basic blocks" (512 222 - bytes). Hence we can do realtively simple LSN based math to keep track of 222 + bytes). Hence we can do relatively simple LSN based math to keep track of 223 223 available space in the log. 224 224 225 225 Log space accounting is done via a pair of constructs called "grant heads". The
+1 -1
Documentation/filesystems/xfs/xfs-maintainer-entry-profile.rst
··· 93 93 sponsoring work on any part of XFS. 94 94 95 95 - **LTS Maintainer**: Someone who backports and tests bug fixes from 96 - uptream to the LTS kernels. 96 + upstream to the LTS kernels. 97 97 There tend to be six separate LTS trees at any given time. 98 98 99 99 The maintainer for a given LTS release should identify themselves with an
+2 -2
Documentation/filesystems/xfs/xfs-online-fsck-design.rst
··· 4521 4521 | For this second effort, the ondisk parent pointer format as originally | 4522 4522 | proposed was ``(parent_inum, parent_gen, dirent_pos) → (dirent_name)``. | 4523 4523 | The format was changed during development to eliminate the requirement | 4524 - | of repair tools needing to to ensure that the ``dirent_pos`` field | 4525 - | always matched when reconstructing a directory. | 4524 + | of repair tools needing to ensure that the ``dirent_pos`` field always | 4525 + | matched when reconstructing a directory. | 4526 4526 | | 4527 4527 | There were a few other ways to have solved that problem: | 4528 4528 | |
+1 -1
Documentation/iio/iio_devbuf.rst
··· 148 148 in a processed form. Please note that these corner cases are not addressed by 149 149 this documentation. 150 150 151 - Please see ``Documentation/ABI/testing/sysfs-bus-iio`` for a complete 151 + Please see Documentation/ABI/testing/sysfs-bus-iio for a complete 152 152 description of the attributes.
+1 -1
Documentation/input/devices/elantech.rst
··· 556 556 In case the box has unstable power supply or other electricity issues, or 557 557 when number of finger changes, F/W would send "debounce packet" to inform 558 558 driver that the hardware is in debounce status. 559 - The debouce packet has the following signature:: 559 + The debounce packet has the following signature:: 560 560 561 561 byte 0: 0xc4 562 562 byte 1: 0xff
+19
Documentation/input/input-programming.rst
··· 346 346 347 347 This callback routine can be called from an interrupt or a BH (although that 348 348 isn't a rule), and thus must not sleep, and must not take too long to finish. 349 + 350 + Polled input devices 351 + ~~~~~~~~~~~~~~~~~~~~ 352 + 353 + Input polling is set up by passing an input device struct and a callback to 354 + the function:: 355 + 356 + int input_setup_polling(struct input_dev *dev, 357 + void (*poll_fn)(struct input_dev *dev)) 358 + 359 + Within the callback, devices should use the regular input_report_* functions 360 + and input_sync as is used by other devices. 361 + 362 + There is also the function:: 363 + 364 + void input_set_poll_interval(struct input_dev *dev, unsigned int interval) 365 + 366 + which is used to configure the interval, in milliseconds, that the device will 367 + be polled at.
+1 -1
Documentation/mm/split_page_table_lock.rst
··· 4 4 5 5 Originally, mm->page_table_lock spinlock protected all page tables of the 6 6 mm_struct. But this approach leads to poor page fault scalability of 7 - multi-threaded applications due high contention on the lock. To improve 7 + multi-threaded applications due to high contention on the lock. To improve 8 8 scalability, split page table lock was introduced. 9 9 10 10 With split page table lock we have separate per-table lock to serialize
+1 -1
Documentation/networking/statistics.rst
··· 143 143 and reports only the stat corresponding to the accessed file. 144 144 145 145 Sysfs files are documented in 146 - `Documentation/ABI/testing/sysfs-class-net-statistics`. 146 + Documentation/ABI/testing/sysfs-class-net-statistics. 147 147 148 148 149 149 netlink
+1 -1
Documentation/nvme/nvme-pci-endpoint-target.rst
··· 86 86 with excessive local memory usage for executing commands, MDTS defaults to 512 87 87 KB and is limited to a maximum of 2 MB (arbitrary limit). 88 88 89 - Mimimum number of PCI Address Mapping Windows Required 89 + Minimum number of PCI Address Mapping Windows Required 90 90 ------------------------------------------------------ 91 91 92 92 Most PCI endpoint controllers provide a limited number of mapping windows for
+9 -4
Documentation/process/5.Posting.rst
··· 268 268 - Cc: the named person received a copy of the patch and had the 269 269 opportunity to comment on it. 270 270 271 - Be careful in the addition of tags to your patches, as only Cc: is appropriate 272 - for addition without the explicit permission of the person named; using 273 - Reported-by: is fine most of the time as well, but ask for permission if 274 - the bug was reported in private. 271 + Be careful in the addition of the aforementioned tags to your patches, as all 272 + except for Cc:, Reported-by:, and Suggested-by: need explicit permission of the 273 + person named. For those three implicit permission is sufficient if the person 274 + contributed to the Linux kernel using that name and email address according 275 + to the lore archives or the commit history -- and in case of Reported-by: 276 + and Suggested-by: did the reporting or suggestion in public. Note, 277 + bugzilla.kernel.org is a public place in this sense, but email addresses 278 + used there are private; so do not expose them in tags, unless the person 279 + used them in earlier contributions. 275 280 276 281 277 282 Sending the patch
+2 -2
Documentation/process/changes.rst
··· 58 58 iptables 1.4.2 iptables -V 59 59 openssl & libcrypto 1.0.0 openssl version 60 60 bc 1.06.95 bc --version 61 - Sphinx\ [#f1]_ 2.4.4 sphinx-build --version 61 + Sphinx\ [#f1]_ 3.4.3 sphinx-build --version 62 62 GNU tar 1.28 tar --version 63 63 gtags (optional) 6.6.5 gtags --version 64 64 mkimage (optional) 2017.01 mkimage --version 65 - Python (optional) 3.5.x python3 --version 65 + Python (optional) 3.9.x python3 --version 66 66 GNU AWK (optional) 5.1.0 gawk --version 67 67 ====================== =============== ======================================== 68 68
+11 -6
Documentation/process/code-of-conduct-interpretation.rst
··· 145 145 146 146 Any decisions regarding enforcement recommendations will be brought to 147 147 the TAB for implementation of enforcement with the relevant maintainers 148 - if needed. A decision by the Code of Conduct Committee can be overturned 149 - by the TAB by a two-thirds vote. 148 + if needed. Once the TAB approves one or more of the measures outlined 149 + in the scope of the ban by two-thirds of the members voting for the 150 + measures, the Code of Conduct Committee will enforce the TAB approved 151 + measures. Any Code of Conduct Committee members serving on the TAB will 152 + not vote on the measures. 150 153 151 154 At quarterly intervals, the Code of Conduct Committee and TAB will 152 155 provide a report summarizing the anonymised reports that the Code of 153 156 Conduct committee has received and their status, as well details of any 154 - overridden decisions including complete and identifiable voting details. 157 + TAB approved decisions including complete and identifiable voting details. 155 158 156 159 Because how we interpret and enforce the Code of Conduct will evolve over 157 160 time, this document will be updated when necessary to reflect any ··· 230 227 such as mailing lists and social media sites 231 228 232 229 Once the TAB approves one or more of the measures outlined in the scope of 233 - the ban by a two-thirds vote, the Code of Conduct Committee will enforce 234 - the TAB approved measure(s) in collaboration with the community, maintainers, 235 - sub-maintainers, and kernel.org administrators. 230 + the ban by two-thirds of the members voting for the measures, the Code of 231 + Conduct Committee will enforce the TAB approved measure(s) in collaboration 232 + with the community, maintainers, sub-maintainers, and kernel.org 233 + administrators. Any Code of Conduct Committee members serving on the TAB 234 + will not vote on the measures. 236 235 237 236 The Code of Conduct Committee is mindful of the negative impact of seeking 238 237 public apology and instituting ban could have on individuals. It is also
+11
Documentation/process/kernel-docs.rst
··· 75 75 Published books 76 76 --------------- 77 77 78 + * Title: **The Linux Memory Manager** 79 + 80 + :Author: Lorenzo Stoakes 81 + :Publisher: No Starch Press 82 + :Date: February 2025 83 + :Pages: 1300 84 + :ISBN: 978-1718504462 85 + :Notes: Memory management. Full draft available as early access for 86 + pre-order, full release scheduled for Fall 2025. See 87 + https://nostarch.com/linux-memory-manager for further info. 88 + 78 89 * Title: **Practical Linux System Administration: A Guide to Installation, Configuration, and Management, 1st Edition** 79 90 80 91 :Author: Kenneth Hess
+8 -4
Documentation/process/submit-checklist.rst
··· 52 52 4) All new module parameters are documented with ``MODULE_PARM_DESC()`` 53 53 54 54 5) All new userspace interfaces are documented in ``Documentation/ABI/``. 55 - See ``Documentation/ABI/README`` for more information. 55 + See Documentation/admin-guide/abi.rst (or ``Documentation/ABI/README``) 56 + for more information. 56 57 Patches that change userspace interfaces should be CCed to 57 58 linux-api@vger.kernel.org. 58 59 ··· 92 91 fix any issues. 93 92 94 93 2) Builds on multiple CPU architectures by using local cross-compile tools 95 - or some other build farm. Note that ppc64 is a good architecture for 96 - cross-compilation checking because it tends to use ``unsigned long`` for 97 - 64-bit quantities. 94 + or some other build farm. 95 + Note that testing against architectures of different word sizes 96 + (32- and 64-bit) and different endianness (big- and little-) is effective 97 + in catching various portability issues due to false assumptions on 98 + representable quantity range, data alignment, or endianness, among 99 + others. 98 100 99 101 3) Newly-added code has been compiled with ``gcc -W`` (use 100 102 ``make KCFLAGS=-W``). This will generate lots of noise, but is good
+33 -12
Documentation/process/submitting-patches.rst
··· 495 495 496 496 If a person has had the opportunity to comment on a patch, but has not 497 497 provided such comments, you may optionally add a ``Cc:`` tag to the patch. 498 - This is the only tag which might be added without an explicit action by the 499 - person it names - but it should indicate that this person was copied on the 500 - patch. This tag documents that potentially interested parties 501 - have been included in the discussion. 498 + This tag documents that potentially interested parties have been included in 499 + the discussion. Note, this is one of only three tags you might be able to use 500 + without explicit permission of the person named (see 'Tagging people requires 501 + permission' below for details). 502 502 503 503 Co-developed-by: states that the patch was co-created by multiple developers; 504 504 it is used to give attribution to co-authors (in addition to the author ··· 544 544 bugs; please do not use it to credit feature requests. The tag should be 545 545 followed by a Closes: tag pointing to the report, unless the report is not 546 546 available on the web. The Link: tag can be used instead of Closes: if the patch 547 - fixes a part of the issue(s) being reported. Please note that if the bug was 548 - reported in private, then ask for permission first before using the Reported-by 549 - tag. 547 + fixes a part of the issue(s) being reported. Note, the Reported-by tag is one 548 + of only three tags you might be able to use without explicit permission of the 549 + person named (see 'Tagging people requires permission' below for details). 550 550 551 551 A Tested-by: tag indicates that the patch has been successfully tested (in 552 552 some environment) by the person named. This tag informs maintainers that ··· 596 596 in the patch changelog (after the '---' separator). 597 597 598 598 A Suggested-by: tag indicates that the patch idea is suggested by the person 599 - named and ensures credit to the person for the idea. Please note that this 600 - tag should not be added without the reporter's permission, especially if the 601 - idea was not posted in a public forum. That said, if we diligently credit our 602 - idea reporters, they will, hopefully, be inspired to help us again in the 603 - future. 599 + named and ensures credit to the person for the idea: if we diligently credit 600 + our idea reporters, they will, hopefully, be inspired to help us again in the 601 + future. Note, this is one of only three tags you might be able to use without 602 + explicit permission of the person named (see 'Tagging people requires 603 + permission' below for details). 604 604 605 605 A Fixes: tag indicates that the patch fixes an issue in a previous commit. It 606 606 is used to make it easy to determine where a bug originated, which can help ··· 617 617 Finally, while providing tags is welcome and typically very appreciated, please 618 618 note that signers (i.e. submitters and maintainers) may use their discretion in 619 619 applying offered tags. 620 + 621 + .. _tagging_people: 622 + 623 + Tagging people requires permission 624 + ---------------------------------- 625 + 626 + Be careful in the addition of the aforementioned tags to your patches, as all 627 + except for Cc:, Reported-by:, and Suggested-by: need explicit permission of the 628 + person named. For those three implicit permission is sufficient if the person 629 + contributed to the Linux kernel using that name and email address according 630 + to the lore archives or the commit history -- and in case of Reported-by: 631 + and Suggested-by: did the reporting or suggestion in public. Note, 632 + bugzilla.kernel.org is a public place in this sense, but email addresses 633 + used there are private; so do not expose them in tags, unless the person 634 + used them in earlier contributions. 620 635 621 636 .. _the_canonical_patch_format: 622 637 ··· 731 716 patch in the permanent changelog. If the ``from`` line is missing, 732 717 then the ``From:`` line from the email header will be used to determine 733 718 the patch author in the changelog. 719 + 720 + The author may indicate their affiliation or the sponsor of the work 721 + by adding the name of an organization to the ``from`` and ``SoB`` lines, 722 + e.g.: 723 + 724 + From: Patch Author (Company) <author@example.com> 734 725 735 726 Explanation Body 736 727 ^^^^^^^^^^^^^^^^
+1 -1
Documentation/scheduler/sched-bwc.rst
··· 59 59 \Sum e_i; that is, there is a bounded tardiness (under the assumption 60 60 that x+e is indeed WCET). 61 61 62 - The interferenece when using burst is valued by the possibilities for 62 + The interference when using burst is valued by the possibilities for 63 63 missing the deadline and the average WCET. Test results showed that when 64 64 there many cgroups or CPU is under utilized, the interference is 65 65 limited. More details are shown in:
+1 -1
Documentation/sound/soc/machine.rst
··· 75 75 either dai name or device tree node but not both. Also, names used here 76 76 for cpu/codec/platform dais should be globally unique. 77 77 78 - Additionaly below example macro can be used to register cpu, codec and 78 + Additionally below example macro can be used to register cpu, codec and 79 79 platform dai:: 80 80 81 81 SND_SOC_DAILINK_DEFS(wm2200_cpu_dsp,
+60 -22
Documentation/sphinx/automarkup.py
··· 11 11 import re 12 12 from itertools import chain 13 13 14 - # 15 - # Python 2 lacks re.ASCII... 16 - # 17 - try: 18 - ascii_p3 = re.ASCII 19 - except AttributeError: 20 - ascii_p3 = 0 14 + from kernel_abi import get_kernel_abi 21 15 22 16 # 23 17 # Regex nastiness. Of course. ··· 20 26 # :c:func: block (i.e. ":c:func:`mmap()`s" flakes out), so the last 21 27 # bit tries to restrict matches to things that won't create trouble. 22 28 # 23 - RE_function = re.compile(r'\b(([a-zA-Z_]\w+)\(\))', flags=ascii_p3) 29 + RE_function = re.compile(r'\b(([a-zA-Z_]\w+)\(\))', flags=re.ASCII) 24 30 25 31 # 26 32 # Sphinx 2 uses the same :c:type role for struct, union, enum and typedef 27 33 # 28 34 RE_generic_type = re.compile(r'\b(struct|union|enum|typedef)\s+([a-zA-Z_]\w+)', 29 - flags=ascii_p3) 35 + flags=re.ASCII) 30 36 31 37 # 32 38 # Sphinx 3 uses a different C role for each one of struct, union, enum and 33 39 # typedef 34 40 # 35 - RE_struct = re.compile(r'\b(struct)\s+([a-zA-Z_]\w+)', flags=ascii_p3) 36 - RE_union = re.compile(r'\b(union)\s+([a-zA-Z_]\w+)', flags=ascii_p3) 37 - RE_enum = re.compile(r'\b(enum)\s+([a-zA-Z_]\w+)', flags=ascii_p3) 38 - RE_typedef = re.compile(r'\b(typedef)\s+([a-zA-Z_]\w+)', flags=ascii_p3) 41 + RE_struct = re.compile(r'\b(struct)\s+([a-zA-Z_]\w+)', flags=re.ASCII) 42 + RE_union = re.compile(r'\b(union)\s+([a-zA-Z_]\w+)', flags=re.ASCII) 43 + RE_enum = re.compile(r'\b(enum)\s+([a-zA-Z_]\w+)', flags=re.ASCII) 44 + RE_typedef = re.compile(r'\b(typedef)\s+([a-zA-Z_]\w+)', flags=re.ASCII) 39 45 40 46 # 41 47 # Detects a reference to a documentation page of the form Documentation/... with 42 48 # an optional extension 43 49 # 44 50 RE_doc = re.compile(r'(\bDocumentation/)?((\.\./)*[\w\-/]+)\.(rst|txt)') 51 + RE_abi_file = re.compile(r'(\bDocumentation/ABI/[\w\-/]+)') 52 + RE_abi_symbol = re.compile(r'(\b/(sys|config|proc)/[\w\-/]+)') 45 53 46 54 RE_namespace = re.compile(r'^\s*..\s*c:namespace::\s*(\S+)\s*$') 47 55 ··· 79 83 # 80 84 # Associate each regex with the function that will markup its matches 81 85 # 82 - markup_func_sphinx2 = {RE_doc: markup_doc_ref, 83 - RE_function: markup_c_ref, 84 - RE_generic_type: markup_c_ref} 85 86 86 - markup_func_sphinx3 = {RE_doc: markup_doc_ref, 87 + markup_func = {RE_doc: markup_doc_ref, 88 + RE_abi_file: markup_abi_file_ref, 89 + RE_abi_symbol: markup_abi_ref, 87 90 RE_function: markup_func_ref_sphinx3, 88 91 RE_struct: markup_c_ref, 89 92 RE_union: markup_c_ref, 90 93 RE_enum: markup_c_ref, 91 94 RE_typedef: markup_c_ref, 92 95 RE_git: markup_git} 93 - 94 - if sphinx.version_info[0] >= 3: 95 - markup_func = markup_func_sphinx3 96 - else: 97 - markup_func = markup_func_sphinx2 98 96 99 97 match_iterators = [regex.finditer(t) for regex in markup_func] 100 98 # ··· 259 269 return xref 260 270 else: 261 271 return nodes.Text(match.group(0)) 272 + 273 + # 274 + # Try to replace a documentation reference for ABI symbols and files 275 + # with a cross reference to that page 276 + # 277 + def markup_abi_ref(docname, app, match, warning=False): 278 + stddom = app.env.domains['std'] 279 + # 280 + # Go through the dance of getting an xref out of the std domain 281 + # 282 + kernel_abi = get_kernel_abi() 283 + 284 + fname = match.group(1) 285 + target = kernel_abi.xref(fname) 286 + 287 + # Kernel ABI doesn't describe such file or symbol 288 + if not target: 289 + if warning: 290 + kernel_abi.log.warning("%s not found", fname) 291 + return nodes.Text(match.group(0)) 292 + 293 + pxref = addnodes.pending_xref('', refdomain = 'std', reftype = 'ref', 294 + reftarget = target, modname = None, 295 + classname = None, refexplicit = False) 296 + 297 + # 298 + # XXX The Latex builder will throw NoUri exceptions here, 299 + # work around that by ignoring them. 300 + # 301 + try: 302 + xref = stddom.resolve_xref(app.env, docname, app.builder, 'ref', 303 + target, pxref, None) 304 + except NoUri: 305 + xref = None 306 + # 307 + # Return the xref if we got it; otherwise just return the plain text. 308 + # 309 + if xref: 310 + return xref 311 + else: 312 + return nodes.Text(match.group(0)) 313 + 314 + # 315 + # Variant of markup_abi_ref() that warns whan a reference is not found 316 + # 317 + def markup_abi_file_ref(docname, app, match): 318 + return markup_abi_ref(docname, app, match, warning=True) 319 + 262 320 263 321 def get_c_namespace(app, docname): 264 322 source = app.env.doc2path(docname)
+2 -5
Documentation/sphinx/cdomain.py
··· 1 1 # -*- coding: utf-8; mode: python -*- 2 2 # pylint: disable=W0141,C0113,C0103,C0325 3 - u""" 3 + """ 4 4 cdomain 5 5 ~~~~~~~ 6 6 ··· 44 44 import re 45 45 46 46 __version__ = '1.1' 47 - 48 - # Get Sphinx version 49 - major, minor, patch = sphinx.version_info[:3] 50 47 51 48 # Namespace to be prepended to the full name 52 49 namespace = None ··· 142 145 } 143 146 144 147 def handle_func_like_macro(self, sig, signode): 145 - u"""Handles signatures of function-like macros. 148 + """Handles signatures of function-like macros. 146 149 147 150 If the objtype is 'function' and the signature ``sig`` is a 148 151 function-like macro, the name of the macro is returned. Otherwise
+97 -67
Documentation/sphinx/kernel_abi.py
··· 2 2 # coding=utf-8 3 3 # SPDX-License-Identifier: GPL-2.0 4 4 # 5 - u""" 5 + """ 6 6 kernel-abi 7 7 ~~~~~~~~~~ 8 8 ··· 14 14 :license: GPL Version 2, June 1991 see Linux/COPYING for details. 15 15 16 16 The ``kernel-abi`` (:py:class:`KernelCmd`) directive calls the 17 - scripts/get_abi.pl script to parse the Kernel ABI files. 17 + scripts/get_abi.py script to parse the Kernel ABI files. 18 18 19 19 Overview of directive's argument and options. 20 20 ··· 32 32 33 33 """ 34 34 35 - import codecs 36 35 import os 37 - import subprocess 38 - import sys 39 36 import re 40 - import kernellog 37 + import sys 41 38 42 39 from docutils import nodes, statemachine 43 40 from docutils.statemachine import ViewList 44 41 from docutils.parsers.rst import directives, Directive 45 - from docutils.utils.error_reporting import ErrorString 46 42 from sphinx.util.docutils import switch_source_input 43 + from sphinx.util import logging 47 44 48 - __version__ = '1.0' 45 + srctree = os.path.abspath(os.environ["srctree"]) 46 + sys.path.insert(0, os.path.join(srctree, "scripts/lib/abi")) 47 + 48 + from abi_parser import AbiParser 49 + 50 + __version__ = "1.0" 51 + 52 + logger = logging.getLogger('kernel_abi') 53 + path = os.path.join(srctree, "Documentation/ABI") 54 + 55 + _kernel_abi = None 56 + 57 + def get_kernel_abi(): 58 + """ 59 + Initialize kernel_abi global var, if not initialized yet. 60 + 61 + This is needed to avoid warnings during Sphinx module initialization. 62 + """ 63 + global _kernel_abi 64 + 65 + if not _kernel_abi: 66 + # Parse ABI symbols only once 67 + _kernel_abi = AbiParser(path, logger=logger) 68 + _kernel_abi.parse_abi() 69 + _kernel_abi.check_issues() 70 + 71 + return _kernel_abi 49 72 50 73 def setup(app): 51 74 52 75 app.add_directive("kernel-abi", KernelCmd) 53 - return dict( 54 - version = __version__ 55 - , parallel_read_safe = True 56 - , parallel_write_safe = True 57 - ) 76 + return { 77 + "version": __version__, 78 + "parallel_read_safe": True, 79 + "parallel_write_safe": True 80 + } 81 + 58 82 59 83 class KernelCmd(Directive): 60 - 61 - u"""KernelABI (``kernel-abi``) directive""" 84 + """KernelABI (``kernel-abi``) directive""" 62 85 63 86 required_arguments = 1 64 - optional_arguments = 2 87 + optional_arguments = 3 65 88 has_content = False 66 89 final_argument_whitespace = True 90 + parser = None 67 91 68 92 option_spec = { 69 - "debug" : directives.flag, 70 - "rst" : directives.unchanged 93 + "debug": directives.flag, 94 + "no-symbols": directives.flag, 95 + "no-files": directives.flag, 71 96 } 72 97 73 98 def run(self): 99 + kernel_abi = get_kernel_abi() 100 + 74 101 doc = self.state.document 75 102 if not doc.settings.file_insertion_enabled: 76 103 raise self.warning("docutils: file insertion disabled") 77 104 78 - srctree = os.path.abspath(os.environ["srctree"]) 79 - 80 - args = [ 81 - os.path.join(srctree, 'scripts/get_abi.pl'), 82 - 'rest', 83 - '--enable-lineno', 84 - '--dir', os.path.join(srctree, 'Documentation', self.arguments[0]), 85 - ] 86 - 87 - if 'rst' in self.options: 88 - args.append('--rst-source') 89 - 90 - lines = subprocess.check_output(args, cwd=os.path.dirname(doc.current_source)).decode('utf-8') 91 - nodeList = self.nestedParse(lines, self.arguments[0]) 92 - return nodeList 93 - 94 - def nestedParse(self, lines, fname): 95 105 env = self.state.document.settings.env 96 106 content = ViewList() 97 107 node = nodes.section() 98 108 99 - if "debug" in self.options: 100 - code_block = "\n\n.. code-block:: rst\n :linenos:\n" 101 - for l in lines.split("\n"): 102 - code_block += "\n " + l 103 - lines = code_block + "\n\n" 109 + abi_type = self.arguments[0] 104 110 105 - line_regex = re.compile(r"^\.\. LINENO (\S+)\#([0-9]+)$") 106 - ln = 0 111 + if "no-symbols" in self.options: 112 + show_symbols = False 113 + else: 114 + show_symbols = True 115 + 116 + if "no-files" in self.options: 117 + show_file = False 118 + else: 119 + show_file = True 120 + 121 + tab_width = self.options.get('tab-width', 122 + self.state.document.settings.tab_width) 123 + 124 + old_f = None 107 125 n = 0 108 - f = fname 109 - 110 - for line in lines.split("\n"): 111 - n = n + 1 112 - match = line_regex.search(line) 113 - if match: 114 - new_f = match.group(1) 115 - 116 - # Sphinx parser is lazy: it stops parsing contents in the 117 - # middle, if it is too big. So, handle it per input file 118 - if new_f != f and content: 119 - self.do_parse(content, node) 120 - content = ViewList() 121 - 122 - # Add the file to Sphinx build dependencies 123 - env.note_dependency(os.path.abspath(f)) 124 - 125 - f = new_f 126 - 127 - # sphinx counts lines from 0 128 - ln = int(match.group(2)) - 1 126 + n_sym = 0 127 + for msg, f, ln in kernel_abi.doc(show_file=show_file, 128 + show_symbols=show_symbols, 129 + filter_path=abi_type): 130 + n_sym += 1 131 + msg_list = statemachine.string2lines(msg, tab_width, 132 + convert_whitespace=True) 133 + if "debug" in self.options: 134 + lines = [ 135 + "", "", ".. code-block:: rst", 136 + " :linenos:", "" 137 + ] 138 + for m in msg_list: 139 + lines.append(" " + m) 129 140 else: 130 - content.append(line, f, ln) 141 + lines = msg_list 131 142 132 - kernellog.info(self.state.document.settings.env.app, "%s: parsed %i lines" % (fname, n)) 143 + for line in lines: 144 + # sphinx counts lines from 0 145 + content.append(line, f, ln - 1) 146 + n += 1 133 147 134 - if content: 135 - self.do_parse(content, node) 148 + if f != old_f: 149 + # Add the file to Sphinx build dependencies 150 + env.note_dependency(os.path.abspath(f)) 151 + 152 + old_f = f 153 + 154 + # Sphinx doesn't like to parse big messages. So, let's 155 + # add content symbol by symbol 156 + if content: 157 + self.do_parse(content, node) 158 + content = ViewList() 159 + 160 + if show_symbols and not show_file: 161 + logger.verbose("%s ABI: %i symbols (%i ReST lines)" % (abi_type, n_sym, n)) 162 + elif not show_symbols and show_file: 163 + logger.verbose("%s ABI: %i files (%i ReST lines)" % (abi_type, n_sym, n)) 164 + else: 165 + logger.verbose("%s ABI: %i data (%i ReST lines)" % (abi_type, n_sym, n)) 136 166 137 167 return node.children 138 168
+2 -2
Documentation/sphinx/kernel_feat.py
··· 1 1 # coding=utf-8 2 2 # SPDX-License-Identifier: GPL-2.0 3 3 # 4 - u""" 4 + """ 5 5 kernel-feat 6 6 ~~~~~~~~~~~ 7 7 ··· 56 56 57 57 class KernelFeat(Directive): 58 58 59 - u"""KernelFeat (``kernel-feat``) directive""" 59 + """KernelFeat (``kernel-feat``) directive""" 60 60 61 61 required_arguments = 1 62 62 optional_arguments = 2
+2 -2
Documentation/sphinx/kernel_include.py
··· 2 2 # -*- coding: utf-8; mode: python -*- 3 3 # pylint: disable=R0903, C0330, R0914, R0912, E0401 4 4 5 - u""" 5 + """ 6 6 kernel-include 7 7 ~~~~~~~~~~~~~~ 8 8 ··· 56 56 class KernelInclude(Include): 57 57 # ============================================================================== 58 58 59 - u"""KernelInclude (``kernel-include``) directive""" 59 + """KernelInclude (``kernel-include``) directive""" 60 60 61 61 def run(self): 62 62 env = self.state.document.settings.env
+7 -12
Documentation/sphinx/kerneldoc.py
··· 39 39 from docutils.parsers.rst import directives, Directive 40 40 import sphinx 41 41 from sphinx.util.docutils import switch_source_input 42 - import kernellog 42 + from sphinx.util import logging 43 43 44 44 __version__ = '1.0' 45 45 ··· 56 56 'functions': directives.unchanged, 57 57 } 58 58 has_content = False 59 + logger = logging.getLogger('kerneldoc') 59 60 60 61 def run(self): 61 62 env = self.state.document.settings.env 62 63 cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno'] 63 - 64 - # Pass the version string to kernel-doc, as it needs to use a different 65 - # dialect, depending what the C domain supports for each specific 66 - # Sphinx versions 67 - cmd += ['-sphinx-version', sphinx.__version__] 68 64 69 65 filename = env.config.kerneldoc_srctree + '/' + self.arguments[0] 70 66 export_file_patterns = [] ··· 105 109 cmd += [filename] 106 110 107 111 try: 108 - kernellog.verbose(env.app, 109 - 'calling kernel-doc \'%s\'' % (" ".join(cmd))) 112 + self.logger.verbose("calling kernel-doc '%s'" % (" ".join(cmd))) 110 113 111 114 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 112 115 out, err = p.communicate() ··· 115 120 if p.returncode != 0: 116 121 sys.stderr.write(err) 117 122 118 - kernellog.warn(env.app, 119 - 'kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode)) 123 + self.logger.warning("kernel-doc '%s' failed with return code %d" 124 + % (" ".join(cmd), p.returncode)) 120 125 return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] 121 126 elif env.config.kerneldoc_verbosity > 0: 122 127 sys.stderr.write(err) ··· 143 148 return node.children 144 149 145 150 except Exception as e: # pylint: disable=W0703 146 - kernellog.warn(env.app, 'kernel-doc \'%s\' processing failed with: %s' % 147 - (" ".join(cmd), str(e))) 151 + self.logger.warning("kernel-doc '%s' processing failed with: %s" % 152 + (" ".join(cmd), str(e))) 148 153 return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] 149 154 150 155 def do_parse(self, result, node):
-22
Documentation/sphinx/kernellog.py
··· 1 - # SPDX-License-Identifier: GPL-2.0 2 - # 3 - # Sphinx has deprecated its older logging interface, but the replacement 4 - # only goes back to 1.6. So here's a wrapper layer to keep around for 5 - # as long as we support 1.4. 6 - # 7 - # We don't support 1.4 anymore, but we'll keep the wrappers around until 8 - # we change all the code to not use them anymore :) 9 - # 10 - import sphinx 11 - from sphinx.util import logging 12 - 13 - logger = logging.getLogger('kerneldoc') 14 - 15 - def warn(app, message): 16 - logger.warning(message) 17 - 18 - def verbose(app, message): 19 - logger.verbose(message) 20 - 21 - def info(app, message): 22 - logger.info(message)
+48 -43
Documentation/sphinx/kfigure.py
··· 1 1 # -*- coding: utf-8; mode: python -*- 2 2 # pylint: disable=C0103, R0903, R0912, R0915 3 - u""" 3 + """ 4 4 scalable figure and image handling 5 5 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 6 ··· 59 59 from docutils.parsers.rst.directives import images 60 60 import sphinx 61 61 from sphinx.util.nodes import clean_astext 62 - import kernellog 62 + from sphinx.util import logging 63 63 64 64 Figure = images.Figure 65 65 66 66 __version__ = '1.0.0' 67 + 68 + logger = logging.getLogger('kfigure') 67 69 68 70 # simple helper 69 71 # ------------- ··· 165 163 166 164 167 165 def setupTools(app): 168 - u""" 166 + """ 169 167 Check available build tools and log some *verbose* messages. 170 168 171 169 This function is called once, when the builder is initiated. 172 170 """ 173 171 global dot_cmd, dot_Tpdf, convert_cmd, rsvg_convert_cmd # pylint: disable=W0603 174 172 global inkscape_cmd, inkscape_ver_one # pylint: disable=W0603 175 - kernellog.verbose(app, "kfigure: check installed tools ...") 173 + logger.verbose("kfigure: check installed tools ...") 176 174 177 175 dot_cmd = which('dot') 178 176 convert_cmd = which('convert') ··· 180 178 inkscape_cmd = which('inkscape') 181 179 182 180 if dot_cmd: 183 - kernellog.verbose(app, "use dot(1) from: " + dot_cmd) 181 + logger.verbose("use dot(1) from: " + dot_cmd) 184 182 185 183 try: 186 184 dot_Thelp_list = subprocess.check_output([dot_cmd, '-Thelp'], ··· 192 190 dot_Tpdf_ptn = b'pdf' 193 191 dot_Tpdf = re.search(dot_Tpdf_ptn, dot_Thelp_list) 194 192 else: 195 - kernellog.warn(app, "dot(1) not found, for better output quality install " 196 - "graphviz from https://www.graphviz.org") 193 + logger.warning( 194 + "dot(1) not found, for better output quality install graphviz from https://www.graphviz.org" 195 + ) 197 196 if inkscape_cmd: 198 - kernellog.verbose(app, "use inkscape(1) from: " + inkscape_cmd) 197 + logger.verbose("use inkscape(1) from: " + inkscape_cmd) 199 198 inkscape_ver = subprocess.check_output([inkscape_cmd, '--version'], 200 199 stderr=subprocess.DEVNULL) 201 200 ver_one_ptn = b'Inkscape 1' ··· 207 204 208 205 else: 209 206 if convert_cmd: 210 - kernellog.verbose(app, "use convert(1) from: " + convert_cmd) 207 + logger.verbose("use convert(1) from: " + convert_cmd) 211 208 else: 212 - kernellog.verbose(app, 209 + logger.verbose( 213 210 "Neither inkscape(1) nor convert(1) found.\n" 214 - "For SVG to PDF conversion, " 215 - "install either Inkscape (https://inkscape.org/) (preferred) or\n" 216 - "ImageMagick (https://www.imagemagick.org)") 211 + "For SVG to PDF conversion, install either Inkscape (https://inkscape.org/) (preferred) or\n" 212 + "ImageMagick (https://www.imagemagick.org)" 213 + ) 217 214 218 215 if rsvg_convert_cmd: 219 - kernellog.verbose(app, "use rsvg-convert(1) from: " + rsvg_convert_cmd) 220 - kernellog.verbose(app, "use 'dot -Tsvg' and rsvg-convert(1) for DOT -> PDF conversion") 216 + logger.verbose("use rsvg-convert(1) from: " + rsvg_convert_cmd) 217 + logger.verbose("use 'dot -Tsvg' and rsvg-convert(1) for DOT -> PDF conversion") 221 218 dot_Tpdf = False 222 219 else: 223 - kernellog.verbose(app, 220 + logger.verbose( 224 221 "rsvg-convert(1) not found.\n" 225 - " SVG rendering of convert(1) is done by ImageMagick-native renderer.") 222 + " SVG rendering of convert(1) is done by ImageMagick-native renderer." 223 + ) 226 224 if dot_Tpdf: 227 - kernellog.verbose(app, "use 'dot -Tpdf' for DOT -> PDF conversion") 225 + logger.verbose("use 'dot -Tpdf' for DOT -> PDF conversion") 228 226 else: 229 - kernellog.verbose(app, "use 'dot -Tsvg' and convert(1) for DOT -> PDF conversion") 227 + logger.verbose("use 'dot -Tsvg' and convert(1) for DOT -> PDF conversion") 230 228 231 229 232 230 # integrate conversion tools ··· 261 257 262 258 # in kernel builds, use 'make SPHINXOPTS=-v' to see verbose messages 263 259 264 - kernellog.verbose(app, 'assert best format for: ' + img_node['uri']) 260 + logger.verbose('assert best format for: ' + img_node['uri']) 265 261 266 262 if in_ext == '.dot': 267 263 268 264 if not dot_cmd: 269 - kernellog.verbose(app, 270 - "dot from graphviz not available / include DOT raw.") 265 + logger.verbose("dot from graphviz not available / include DOT raw.") 271 266 img_node.replace_self(file2literal(src_fname)) 272 267 273 268 elif translator.builder.format == 'latex': ··· 293 290 294 291 if translator.builder.format == 'latex': 295 292 if not inkscape_cmd and convert_cmd is None: 296 - kernellog.warn(app, 297 - "no SVG to PDF conversion available / include SVG raw." 298 - "\nIncluding large raw SVGs can cause xelatex error." 299 - "\nInstall Inkscape (preferred) or ImageMagick.") 293 + logger.warning( 294 + "no SVG to PDF conversion available / include SVG raw.\n" 295 + "Including large raw SVGs can cause xelatex error.\n" 296 + "Install Inkscape (preferred) or ImageMagick." 297 + ) 300 298 img_node.replace_self(file2literal(src_fname)) 301 299 else: 302 300 dst_fname = path.join(translator.builder.outdir, fname + '.pdf') ··· 310 306 _name = dst_fname[len(str(translator.builder.outdir)) + 1:] 311 307 312 308 if isNewer(dst_fname, src_fname): 313 - kernellog.verbose(app, 314 - "convert: {out}/%s already exists and is newer" % _name) 309 + logger.verbose("convert: {out}/%s already exists and is newer" % _name) 315 310 316 311 else: 317 312 ok = False 318 313 mkdir(path.dirname(dst_fname)) 319 314 320 315 if in_ext == '.dot': 321 - kernellog.verbose(app, 'convert DOT to: {out}/' + _name) 316 + logger.verbose('convert DOT to: {out}/' + _name) 322 317 if translator.builder.format == 'latex' and not dot_Tpdf: 323 318 svg_fname = path.join(translator.builder.outdir, fname + '.svg') 324 319 ok1 = dot2format(app, src_fname, svg_fname) ··· 328 325 ok = dot2format(app, src_fname, dst_fname) 329 326 330 327 elif in_ext == '.svg': 331 - kernellog.verbose(app, 'convert SVG to: {out}/' + _name) 328 + logger.verbose('convert SVG to: {out}/' + _name) 332 329 ok = svg2pdf(app, src_fname, dst_fname) 333 330 334 331 if not ok: ··· 357 354 with open(out_fname, "w") as out: 358 355 exit_code = subprocess.call(cmd, stdout = out) 359 356 if exit_code != 0: 360 - kernellog.warn(app, 357 + logger.warning( 361 358 "Error #%d when calling: %s" % (exit_code, " ".join(cmd))) 362 359 return bool(exit_code == 0) 363 360 ··· 391 388 pass 392 389 393 390 if exit_code != 0: 394 - kernellog.warn(app, "Error #%d when calling: %s" % (exit_code, " ".join(cmd))) 391 + logger.warning("Error #%d when calling: %s" % 392 + (exit_code, " ".join(cmd))) 395 393 if warning_msg: 396 - kernellog.warn(app, "Warning msg from %s: %s" 397 - % (cmd_name, str(warning_msg, 'utf-8'))) 394 + logger.warning( "Warning msg from %s: %s" % 395 + (cmd_name, str(warning_msg, 'utf-8'))) 398 396 elif warning_msg: 399 - kernellog.verbose(app, "Warning msg from %s (likely harmless):\n%s" 400 - % (cmd_name, str(warning_msg, 'utf-8'))) 397 + logger.verbose("Warning msg from %s (likely harmless):\n%s" % 398 + (cmd_name, str(warning_msg, 'utf-8'))) 401 399 402 400 return bool(exit_code == 0) 403 401 ··· 422 418 # use stdout and stderr from parent 423 419 exit_code = subprocess.call(cmd) 424 420 if exit_code != 0: 425 - kernellog.warn(app, "Error #%d when calling: %s" % (exit_code, " ".join(cmd))) 421 + logger.warning("Error #%d when calling: %s" % 422 + (exit_code, " ".join(cmd))) 426 423 ok = bool(exit_code == 0) 427 424 428 425 return ok ··· 445 440 pass 446 441 447 442 class KernelImage(images.Image): 448 - u"""KernelImage directive 443 + """KernelImage directive 449 444 450 445 Earns everything from ``.. image::`` directive, except *remote URI* and 451 446 *glob* pattern. The KernelImage wraps a image node into a ··· 481 476 """Node for ``kernel-figure`` directive.""" 482 477 483 478 class KernelFigure(Figure): 484 - u"""KernelImage directive 479 + """KernelImage directive 485 480 486 481 Earns everything from ``.. figure::`` directive, except *remote URI* and 487 482 *glob* pattern. The KernelFigure wraps a figure node into a kernel_figure ··· 518 513 app = self.builder.app 519 514 srclang = node.get('srclang') 520 515 521 - kernellog.verbose(app, 'visit kernel-render node lang: "%s"' % (srclang)) 516 + logger.verbose('visit kernel-render node lang: "%s"' % srclang) 522 517 523 518 tmp_ext = RENDER_MARKUP_EXT.get(srclang, None) 524 519 if tmp_ext is None: 525 - kernellog.warn(app, 'kernel-render: "%s" unknown / include raw.' % (srclang)) 520 + logger.warning( 'kernel-render: "%s" unknown / include raw.' % srclang) 526 521 return 527 522 528 523 if not dot_cmd and tmp_ext == '.dot': 529 - kernellog.verbose(app, "dot from graphviz not available / include raw.") 524 + logger.verbose("dot from graphviz not available / include raw.") 530 525 return 531 526 532 527 literal_block = node[0] ··· 557 552 pass 558 553 559 554 class KernelRender(Figure): 560 - u"""KernelRender directive 555 + """KernelRender directive 561 556 562 557 Render content by external tool. Has all the options known from the 563 558 *figure* directive, plus option ``caption``. If ``caption`` has a
+1 -1
Documentation/sphinx/load_config.py
··· 9 9 def loadConfig(namespace): 10 10 # ------------------------------------------------------------------------------ 11 11 12 - u"""Load an additional configuration file into *namespace*. 12 + """Load an additional configuration file into *namespace*. 13 13 14 14 The name of the configuration file is taken from the environment 15 15 ``SPHINX_CONF``. The external configuration file extends (or overwrites) the
+2 -2
Documentation/sphinx/maintainers_include.py
··· 3 3 # -*- coding: utf-8; mode: python -*- 4 4 # pylint: disable=R0903, C0330, R0914, R0912, E0401 5 5 6 - u""" 6 + """ 7 7 maintainers-include 8 8 ~~~~~~~~~~~~~~~~~~~ 9 9 ··· 37 37 ) 38 38 39 39 class MaintainersInclude(Include): 40 - u"""MaintainersInclude (``maintainers-include``) directive""" 40 + """MaintainersInclude (``maintainers-include``) directive""" 41 41 required_arguments = 0 42 42 43 43 def parse_maintainers(self, path):
+5 -5
Documentation/sphinx/rstFlatTable.py
··· 2 2 # -*- coding: utf-8; mode: python -*- 3 3 # pylint: disable=C0330, R0903, R0912 4 4 5 - u""" 5 + """ 6 6 flat-table 7 7 ~~~~~~~~~~ 8 8 ··· 99 99 class FlatTable(Table): 100 100 # ============================================================================== 101 101 102 - u"""FlatTable (``flat-table``) directive""" 102 + """FlatTable (``flat-table``) directive""" 103 103 104 104 option_spec = { 105 105 'name': directives.unchanged ··· 135 135 class ListTableBuilder(object): 136 136 # ============================================================================== 137 137 138 - u"""Builds a table from a double-stage list""" 138 + """Builds a table from a double-stage list""" 139 139 140 140 def __init__(self, directive): 141 141 self.directive = directive ··· 212 212 raise SystemMessagePropagation(error) 213 213 214 214 def parseFlatTableNode(self, node): 215 - u"""parses the node from a :py:class:`FlatTable` directive's body""" 215 + """parses the node from a :py:class:`FlatTable` directive's body""" 216 216 217 217 if len(node) != 1 or not isinstance(node[0], nodes.bullet_list): 218 218 self.raiseError( ··· 225 225 self.roundOffTableDefinition() 226 226 227 227 def roundOffTableDefinition(self): 228 - u"""Round off the table definition. 228 + """Round off the table definition. 229 229 230 230 This method rounds off the table definition in :py:member:`rows`. 231 231
+1 -1
Documentation/trace/postprocess/decode_msr.py
··· 32 32 break 33 33 if r: 34 34 j = j.replace(" " + m.group(2), " " + r + "(" + m.group(2) + ")") 35 - print j, 35 + print(j) 36 36 37 37
+4 -3
Documentation/translations/it_IT/process/submit-checklist.rst
··· 58 58 4) Tutti i nuovi parametri dei moduli sono documentati con ``MODULE_PARM_DESC()``. 59 59 60 60 5) Tutte le nuove interfacce verso lo spazio utente sono documentate in 61 - ``Documentation/ABI/``. Leggete ``Documentation/ABI/README`` per maggiori 62 - informazioni. Le patch che modificano le interfacce utente dovrebbero 63 - essere inviate in copia anche a linux-api@vger.kernel.org. 61 + ``Documentation/ABI/``. Leggete Documentation/admin-guide/abi.rst 62 + (o ``Documentation/ABI/README``) per maggiori informazioni. 63 + Le patch che modificano le interfacce utente dovrebbero essere inviate 64 + in copia anche a linux-api@vger.kernel.org. 64 65 65 66 6) Se la patch aggiunge nuove chiamate ioctl, allora aggiornate 66 67 ``Documentation/userspace-api/ioctl/ioctl-number.rst``.
-105
Documentation/translations/ja_JP/SubmitChecklist
··· 1 - NOTE: 2 - This is a version of Documentation/process/submit-checklist.rst into Japanese. 3 - This document is maintained by Takenori Nagano <t-nagano@ah.jp.nec.com> 4 - and the JF Project team <http://www.linux.or.jp/JF/>. 5 - If you find any difference between this document and the original file 6 - or a problem with the translation, 7 - please contact the maintainer of this file or JF project. 8 - 9 - Please also note that the purpose of this file is to be easier to read 10 - for non English (read: Japanese) speakers and is not intended as a 11 - fork. So if you have any comments or updates of this file, please try 12 - to update the original English file first. 13 - 14 - Last Updated: 2008/07/14 15 - ================================== 16 - これは、 17 - linux-2.6.26/Documentation/process/submit-checklist.rst の和訳です。 18 - 19 - 翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ > 20 - 翻訳日: 2008/07/14 21 - 翻訳者: Takenori Nagano <t-nagano at ah dot jp dot nec dot com> 22 - 校正者: Masanori Kobayashi さん <zap03216 at nifty dot ne dot jp> 23 - ================================== 24 - 25 - 26 - Linux カーネルパッチ投稿者向けチェックリスト 27 - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28 - 29 - 本書では、パッチをより素早く取り込んでもらいたい開発者が実践すべき基本的な事柄 30 - をいくつか紹介します。ここにある全ての事柄は、Documentation/process/submitting-patches.rst 31 - などのLinuxカーネルパッチ投稿に際しての心得を補足するものです。 32 - 33 - 1: 妥当なCONFIGオプションや変更されたCONFIGオプション、つまり =y, =m, =n 34 - 全てで正しくビルドできることを確認してください。その際、gcc及びリンカが 35 - warningやerrorを出していないことも確認してください。 36 - 37 - 2: allnoconfig, allmodconfig オプションを用いて正しくビルドできることを 38 - 確認してください。 39 - 40 - 3: 手許のクロスコンパイルツールやOSDLのPLMのようなものを用いて、複数の 41 - アーキテクチャにおいても正しくビルドできることを確認してください。 42 - 43 - 4: 64bit長の'unsigned long'を使用しているppc64は、クロスコンパイルでの 44 - チェックに適当なアーキテクチャです。 45 - 46 - 5: カーネルコーディングスタイルに準拠しているかどうか確認してください(!) 47 - 48 - 6: CONFIGオプションの追加・変更をした場合には、CONFIGメニューが壊れていない 49 - ことを確認してください。 50 - 51 - 7: 新しくKconfigのオプションを追加する際には、必ずそのhelpも記述してください。 52 - 53 - 8: 適切なKconfigの依存関係を考えながら慎重にチェックしてください。 54 - ただし、この作業はマシンを使ったテストできちんと行うのがとても困難です。 55 - うまくやるには、自分の頭で考えることです。 56 - 57 - 9: sparseを利用してちゃんとしたコードチェックをしてください。 58 - 59 - 10: 'make checkstack' を利用し、問題が発見されたら修正してください。 60 - 'make checkstack' は明示的に問題を示しませんが、どれか 61 - 1つの関数が512バイトより大きいスタックを使っていれば、修正すべき候補と 62 - なります。 63 - 64 - 11: グローバルなkernel API を説明する kernel-doc をソースの中に含めてください。 65 - ( staticな関数においては必須ではありませんが、含めてもらっても結構です ) 66 - そして、'make htmldocs' もしくは 'make mandocs' を利用して追記した 67 - ドキュメントのチェックを行い、問題が見つかった場合には修正を行ってください。 68 - 69 - 12: CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT, CONFIG_DEBUG_SLAB, 70 - CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES, CONFIG_DEBUG_SPINLOCK, 71 - CONFIG_DEBUG_ATOMIC_SLEEP これら全てを同時に有効にして動作確認を 72 - 行ってください。 73 - 74 - 13: CONFIG_SMP, CONFIG_PREEMPT を有効にした場合と無効にした場合の両方で 75 - ビルドした上、動作確認を行ってください。 76 - 77 - 14: lockdepの機能を全て有効にした上で、全てのコードパスを評価してください。 78 - 79 - 15: /proc に新しいエントリを追加した場合には、Documentation/ 配下に 80 - 必ずドキュメントを追加してください。 81 - 82 - 16: 新しいブートパラメータを追加した場合には、 83 - 必ずDocumentation/admin-guide/kernel-parameters.rst に説明を追加してください。 84 - 85 - 17: 新しくmoduleにパラメータを追加した場合には、MODULE_PARM_DESC()を 86 - 利用して必ずその説明を記述してください。 87 - 88 - 18: 新しいuserspaceインタフェースを作成した場合には、Documentation/ABI/ に 89 - Documentation/ABI/README を参考にして必ずドキュメントを追加してください。 90 - 91 - 19: 少なくともslabアロケーションとpageアロケーションに失敗した場合の 92 - 挙動について、fault-injectionを利用して確認してください。 93 - Documentation/fault-injection/ を参照してください。 94 - 95 - 追加したコードがかなりの量であったならば、サブシステム特有の 96 - fault-injectionを追加したほうが良いかもしれません。 97 - 98 - 20: 新たに追加したコードは、`gcc -W'でコンパイルしてください。 99 - このオプションは大量の不要なメッセージを出力しますが、 100 - "warning: comparison between signed and unsigned" のようなメッセージは、 101 - バグを見つけるのに役に立ちます。 102 - 103 - 21: 投稿したパッチが -mm パッチセットにマージされた後、全ての既存のパッチや 104 - VM, VFS およびその他のサブシステムに関する様々な変更と、現時点でも共存 105 - できることを確認するテストを行ってください。
+24
Documentation/translations/ja_JP/disclaimer-ja_JP.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + .. _translations_ja_JP_disclaimer: 4 + 5 + ========================== 6 + 免責条項 (Disclaimer) 抄訳 7 + ========================== 8 + 9 + .. note:: 【訳註】 10 + この文書は、 11 + :ref:`Disclaimer (英語版) <translations_disclaimer>` 12 + の一部を翻訳したものです。全文は英語版を参照願います。 13 + 14 + Documentation/translations/ja_JP/ 以下のファイルは、対応する 15 + Documentation/ 以下のファイル (原文) の日本語訳です。 16 + 翻訳と原文との違いや翻訳上の問題を見つけたら、 17 + MAINTAINERS に記載の維持管理者に知らせてください。 18 + 翻訳が原文の更新に追いついていない場合は、それを日本語版に反映するパッチの 19 + 投稿も歓迎です。 20 + 21 + なお、この翻訳の目的は非英語 (ここでは日本語) 話者への便宜提供であり、 22 + フォークを意図したものではない事を念頭においてください。したがって、 23 + このファイルの内容に対するコメントや更新すべきことがあれば、先に原文の 24 + 更新を検討してください。
+2
Documentation/translations/ja_JP/index.rst
··· 11 11 .. toctree:: 12 12 :maxdepth: 1 13 13 14 + disclaimer-ja_JP 14 15 process/howto 16 + process/submit-checklist 15 17 16 18 .. raw:: latex 17 19
+10 -27
Documentation/translations/ja_JP/process/howto.rst
··· 1 - .. raw:: latex 1 + .. SPDX-License-Identifier: GPL-2.0 2 2 3 - \kerneldocCJKoff 4 - 5 - NOTE: 6 - This is a version of Documentation/process/howto.rst translated into Japanese. 7 - This document is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com> 8 - If you find any difference between this document and the original file or 9 - a problem with the translation, please contact the maintainer of this file. 10 - 11 - Please also note that the purpose of this file is to be easier to 12 - read for non English (read: Japanese) speakers and is not intended as 13 - a fork. So if you have any comments or updates for this file, please 14 - try to update the original English file first. 15 - 16 - ---------------------------------- 17 - 18 - .. raw:: latex 19 - 20 - \kerneldocCJKon 21 - 22 - この文書は、 23 - Documentation/process/howto.rst 24 - の和訳です。 25 - 26 - 翻訳者: Tsugikazu Shibata <tshibata@ab.jp.nec.com> 27 - 28 - ---------------------------------- 3 + .. Originally contributed by Tsugikazu Shibata 29 4 30 5 Linux カーネル開発のやり方 31 6 ========================== 7 + 8 + .. note:: 【訳註】 9 + この文書は、 10 + Documentation/process/howto.rst 11 + の翻訳です。 12 + 免責条項については、 13 + :ref:`免責条項の抄訳 <translations_ja_JP_disclaimer>` および、 14 + :ref:`Disclaimer (英語版) <translations_disclaimer>` を参照してください。 32 15 33 16 これは上のトピック( Linux カーネル開発のやり方)の重要な事柄を網羅した 34 17 ドキュメントです。ここには Linux カーネル開発者になるための方法とLinux
+163
Documentation/translations/ja_JP/process/submit-checklist.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + .. Translated by Akira Yokosawa <akiyks@gmail.com> 4 + 5 + .. An old translation of this document of a different origin was at 6 + Documentation/translations/ja_JP/SubmitChecklist, which can be found 7 + in the pre-v6.14 tree if you are interested. 8 + Please note that this translation is independent of the previous one. 9 + 10 + ====================================== 11 + Linux カーネルパッチ投稿チェックリスト 12 + ====================================== 13 + 14 + .. note:: 【訳註】 15 + この文書は、 16 + Documentation/process/submit-checklist.rst 17 + の翻訳です。 18 + 免責条項については、 19 + :ref:`免責条項の抄訳 <translations_ja_JP_disclaimer>` および、 20 + :ref:`Disclaimer (英語版) <translations_disclaimer>` を参照してください。 21 + 22 + 以下は、カーネルパッチの投稿時に、そのスムーズな受け入れのために心がける 23 + べき基本的な事項です。 24 + 25 + これは、 Documentation/process/submitting-patches.rst およびその他の 26 + Linux カーネルパッチ投稿に関する文書を踏まえ、それを補足するものです。 27 + 28 + .. note:: 【訳註】 29 + 可能な項目については、パッチもしくはパッチ内の更新を暗黙の主語として、 30 + その望ましい状態を表す文体とします。その他、原義を損なわない範囲で 31 + 係り結びを調整するなど、簡潔で把握しやすい箇条書きを目指します。 32 + 33 + 34 + コードのレビュー 35 + ================ 36 + 37 + 1) 利用する機能について、その機能を定義・宣言しているファイルを 38 + ``#include`` している。 39 + 他のヘッダーファイル経由での取り込みに依存しない。 40 + 41 + 2) Documentation/process/coding-style.rst に詳述されている一般的なスタイル 42 + についてチェック済み。 43 + 44 + 3) メモリバリアー (例, ``barrier()``, ``rmb()``, ``wmb()``) について、 45 + そのすべてに、作用と目的、及び必要理由についての説明がソースコード内の 46 + コメントとして記述されている。 47 + 48 + 49 + Kconfig 変更のレビュー 50 + ====================== 51 + 52 + 1) 新規の、もしくは変更された ``CONFIG`` オプションについて、それが関係する 53 + コンフィグメニューへの悪影響がない。また、 54 + Documentation/kbuild/kconfig-language.rst の 55 + "Menu attibutes: default value" に記載の例外条件を満たす場合を除き、 56 + そのデフォルトが無効になっている。 57 + 58 + 2) 新規の ``Kconfig`` オプションにヘルプテキストがある。 59 + 60 + 3) 妥当な ``Kconfig`` の組み合わせについて注意深くレビューされている。 61 + これをテストでやり切るのは困難で、知力が決め手となる。 62 + 63 + ドキュメンテーションの作成 64 + ========================== 65 + 66 + 1) グローバルなカーネル API が :ref:`kernel-doc <kernel_doc>` の形式で 67 + ドキュメント化されている (静的関数には求められないが、付けてもよい)。 68 + 69 + 2) 新規 ``/proc`` エントリーが、すべて ``Documentation/`` 以下に記載されて 70 + いる。 71 + 72 + 3) 新規カーネル・ブート・パラメータが、すべて 73 + ``Documentation/admin-guide/kernel-parameters.rst`` に記載されている。 74 + 75 + 4) 新規モジュール・パラメータが、すべて ``MODULE_PARM_DESC()`` によって記述 76 + されている。 77 + 78 + 5) 新規ユーザースペース・インターフェースが、すべて ``Documentaion/ABI/`` 79 + 以下に記載されている。詳しくは、 Documentation/admin-guide/abi.rst 80 + (もしくは ``Documentation/ABI/README``) を参照。 81 + ユーザースペース・インターフェースを変更するパッチは、 82 + linux-api@vger.kernel.org にも CC すべし。 83 + 84 + 6) なんらかの ioctl を追加するパッチは、 85 + ``Documentation/userspace-api/ioctl/ioctl-number.rst`` 86 + の更新を伴う。 87 + 88 + ツールによるコードのチェック 89 + ============================ 90 + 91 + 1) スタイル・チェッカー (``scripts/checkpatch.pl``) によって、犯しがちな 92 + パッチ・スタイルの違反がないことを確認済み。 93 + 指摘される違反を残す場合は、それを正当化できること。 94 + 95 + 2) sparse により入念にチェック済み。 96 + 97 + 3) ``make checkstack`` で指摘される問題があれば、それが修正済み。 98 + ``checkstack`` は問題点を明示的には指摘しないが、 スタック消費が 99 + 512 バイトを越える関数は見直しの候補。 100 + 101 + コードのビルド 102 + ============== 103 + 104 + 1) 以下の条件でクリーンにビルドできる。 105 + 106 + a) 適用可能な、および ``=y``, ``=m``, ``=n`` を変更した ``CONFIG`` 107 + オプションでのビルド。 108 + ``gcc`` およびリンカーからの警告・エラーがないこと。 109 + 110 + b) ``allnoconfig`` と ``allmodconfig`` がパス 111 + 112 + c) ``O=builddir`` を指定してのビルド 113 + 114 + d) Documentation/ 以下の変更に関して、ドキュメントのビルドで新たな警告や 115 + エラーが出ない。 116 + ``make htmldocs`` または ``make pdfdocs`` でビルドし、問題があれば修正。 117 + 118 + 2) ローカルのクロス・コンパイル・ツール、その他のビルド環境 (訳註: build farm) 119 + を使って、複数の CPU アーキテクチャ向けにビルドできる。 120 + 特に、ワードサイズ (32 ビットと 64 ビット) やエンディアン (ビッグとリトル) 121 + の異なるアーキテクチャを対象とするテストは、表現可能数値範囲・データ整列・ 122 + エンディアンなどについての誤った仮定に起因する様々な移植上の問題を捕える 123 + のに効果的。 124 + 125 + 3) 新規に追加されたコードについて (``make KCFLAGS=-W`` を使って) 126 + ``gcc -W`` でコンパイル。 127 + これは多くのノイズを伴うが、 128 + ``warning: comparison between signed and unsigned`` 129 + の類いのバグをあぶり出すのに効果的。 130 + 131 + 4) 変更されるソースコードが、下記の ``Kconfig`` シンボルに関連するカーネル 132 + API や機能に依存 (もしくは利用) する場合、それらの ``Kconfig`` シンボルが、 133 + 無効、および (可能なら) ``=m`` の場合を組み合わせた複数のビルドを 134 + (全部まとめてではなく、いろいろなランダムの組み合わせで) テスト済み。 135 + 136 + ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``, 137 + ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``, 138 + ``CONFIG_NET``, ``CONFIG_INET=n`` (ただし、後者は ``CONFIG_NET=y`` 139 + との組み合わせ)。 140 + 141 + コードのテスト 142 + ============== 143 + 144 + 1) ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``, 145 + ``CONFIG_SLUB_DEBUG``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``, 146 + ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``, 147 + ``CONFIG_PROVE_RCU`` および ``CONFIG_DEBUG_OBJECTS_RCU_HEAD`` をすべて 148 + 同時に有効にしてのテスト済み。 149 + 150 + 2) ``CONFIG_SMP`` と ``CONFIG_PREEMPT`` が有効と無効の場合について、ビルドと 151 + ランタイムのテスト済み。 152 + 153 + 3) lockdep の機能をすべて有効にしての実行で、すべてのコード経路が確認済み。 154 + 155 + 4) 最低限、slab と ページ・アロケーションの失敗に関する誤り注入 156 + (訳註: fault injection) によるチェック済み。 157 + 詳しくは、 Documentation/fault-injection/index.rst を参照。 158 + 新規のコードが多い場合は、サブシステム対象の誤り注入を追加するのが望ましい 159 + 可能性あり。 160 + 161 + 5) linux-next の最新タグに対するテストにより、他でキューイングされている 162 + パッチや、VM、VFS、その他のサブシステム内のすべての変更と組み合わせての 163 + 動作を確認済み。
+4 -3
Documentation/translations/sp_SP/process/submit-checklist.rst
··· 97 97 ``MODULE_PARM_DESC()``. 98 98 99 99 18) Todas las nuevas interfaces de espacio de usuario están documentadas 100 - en ``Documentation/ABI/``. Consulte ``Documentation/ABI/README`` para 101 - obtener más información. Los parches que cambian las interfaces del 102 - espacio de usuario deben ser CCed a linux-api@vger.kernel.org. 100 + en ``Documentation/ABI/``. Consulte Documentation/admin-guide/abi.rst 101 + (o ``Documentation/ABI/README``) para obtener más información. 102 + Los parches que cambian las interfaces del espacio de usuario deben 103 + ser CCed a linux-api@vger.kernel.org. 103 104 104 105 19) Se ha comprobado con la inyección de al menos errores de asignación 105 106 de slab y página. Consulte ``Documentation/fault-injection/``.
+1 -1
Documentation/translations/zh_CN/admin-guide/README.rst
··· 146 146 147 147 "make xconfig" 基于Qt的配置工具。 148 148 149 - "make gconfig" 基于GTK+的配置工具。 149 + "make gconfig" 基于GTK的配置工具。 150 150 151 151 "make oldconfig" 基于现有的 ./.config 文件选择所有选项,并询问 152 152 新配置选项。
+15 -18
Documentation/translations/zh_CN/dev-tools/ubsan.rst
··· 3 3 .. include:: ../disclaimer-zh_CN.rst 4 4 5 5 :Original: Documentation/dev-tools/ubsan.rst 6 - :Translator: Dongliang Mu <dzm91@hust.edu.cn> 6 + 7 + :翻译: 8 + 9 + 慕冬亮 Dongliang Mu <dzm91@hust.edu.cn> 10 + 11 + :校译: 12 + 13 + 王昱力 WangYuli <wangyuli@uniontech.com> 7 14 8 15 未定义行为消毒剂 - UBSAN 9 16 ==================================== ··· 62 55 63 56 使用如下内核配置启用UBSAN:: 64 57 65 - CONFIG_UBSAN=y 58 + CONFIG_UBSAN=y 66 59 67 - 使用如下内核配置检查整个内核:: 68 - 69 - CONFIG_UBSAN_SANITIZE_ALL=y 70 - 71 - 为了在特定文件或目录启动代码插桩,需要在相应的内核Makefile中添加一行类似内容: 72 - 73 - - 单文件(如main.o):: 74 - 75 - UBSAN_SANITIZE_main.o := y 76 - 77 - - 一个目录中的所有文件:: 78 - 79 - UBSAN_SANITIZE := y 80 - 81 - 即使设置了``CONFIG_UBSAN_SANITIZE_ALL=y``,为了避免文件被插桩,可使用:: 60 + 排除要被检测的文件:: 82 61 83 62 UBSAN_SANITIZE_main.o := n 84 63 85 - 与:: 64 + 排除一个目录中的所有文件:: 86 65 87 66 UBSAN_SANITIZE := n 67 + 68 + 当全部文件都被禁用,可通过如下方式为特定文件启用:: 69 + 70 + UBSAN_SANITIZE_main.o := y 88 71 89 72 未对齐的内存访问检测可通过开启独立选项 - CONFIG_UBSAN_ALIGNMENT 检测。 90 73 该选项在支持未对齐访问的架构上(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y)
+3 -5
Documentation/translations/zh_CN/disclaimer-zh_CN.rst
··· 1 1 :orphan: 2 2 3 - .. warning:: 3 + .. note:: 4 4 此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 5 5 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 6 - 7 - .. note:: 8 - 如果您发现本文档与原始文件有任何不同或者有翻译问题,请联系该文件的译者, 9 - 或者请求时奎亮的帮助:<alexs@kernel.org>。 6 + 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 7 + 该文件的译者,或者请求中文文档维护者和审阅者的帮助。
+7 -1
Documentation/translations/zh_CN/index.rst
··· 26 26 顺便说下,中文文档也需要遵守内核编码风格,风格中中文和英文的主要不同就是中文 27 27 的字符标点占用两个英文字符宽度,所以,当英文要求不要超过每行100个字符时, 28 28 中文就不要超过50个字符。另外,也要注意'-','='等符号与相关标题的对齐。在将 29 - 补丁提交到社区之前,一定要进行必要的 ``checkpatch.pl`` 检查和编译测试。 29 + 补丁提交到社区之前,一定要进行必要的 ``checkpatch.pl`` 检查和编译测试,确保 30 + 在 ``make htmldocs/pdfdocs`` 中不增加新的告警,最后,安装检查你生成的 31 + html/pdf 文件,确认它们看起来是正常的。 32 + 33 + 提交之前请确认你的补丁可以正常提交到中文文档维护库: 34 + https://git.kernel.org/pub/scm/linux/kernel/git/alexs/linux.git/ 35 + 如果你的补丁依赖于其他人的补丁, 可以与其他人商量后由某一个人合并提交。 30 36 31 37 与Linux 内核社区一起工作 32 38 ------------------------
+1 -1
Documentation/translations/zh_CN/mm/balance.rst
··· 64 64 如果从进程内存和shm中偷取页面可以减轻该页面节点中任何区的内存压力,而该区的内存压力 65 65 已经低于其水位,则会进行偷取。 66 66 67 - watemark[WMARK_MIN/WMARK_LOW/WMARK_HIGH]/low_on_memory/zone_wake_kswapd: 67 + watermark[WMARK_MIN/WMARK_LOW/WMARK_HIGH]/low_on_memory/zone_wake_kswapd: 68 68 这些是每个区的字段,用于确定一个区何时需要平衡。当页面数低于水位[WMARK_MIN]时, 69 69 hysteric 的字段low_on_memory被设置。这个字段会一直被设置,直到空闲页数变成水位 70 70 [WMARK_HIGH]。当low_on_memory被设置时,页面分配请求将尝试释放该区域的一些页面(如果
+2 -2
Documentation/translations/zh_CN/process/submit-checklist.rst
··· 82 82 17) 所有新的模块参数都记录在 ``MODULE_PARM_DESC()`` 83 83 84 84 18) 所有新的用户空间接口都记录在 ``Documentation/ABI/`` 中。有关详细信息, 85 - 请参阅 ``Documentation/ABI/README`` 。更改用户空间接口的补丁应该抄送 86 - linux-api@vger.kernel.org。 85 + 请参阅 Documentation/admin-guide/abi.rst (或 ``Documentation/ABI/README``)。 86 + 更改用户空间接口的补丁应该抄送 linux-api@vger.kernel.org\ 。 87 87 88 88 19) 已通过至少注入slab和page分配失败进行检查。请参阅 ``Documentation/fault-injection/`` 。 89 89 如果新代码是实质性的,那么添加子系统特定的故障注入可能是合适的。
+479
Documentation/translations/zh_CN/security/credentials.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: ../disclaimer-zh_CN.rst 3 + 4 + :Original: Documentation/security/credentials.rst 5 + 6 + :翻译: 7 + 赵硕 Shuo Zhao <zhaoshuo@cqsoftware.com.cn> 8 + 9 + ============= 10 + Linux中的凭据 11 + ============= 12 + 13 + 作者: David Howells <dhowells@redhat.com> 14 + 15 + .. contents:: :local: 16 + 17 + 概述 18 + ==== 19 + 20 + 当一个对象对另一个对象进行操作时,Linux执行的安全检查包含几个部分: 21 + 22 + 1. 对象 23 + 24 + 对象是可以直接由用户空间程序操作的系统中的实体。Linux具有多种可操作 25 + 的对象,包括: 26 + 27 + - 任务 28 + - 文件/索引节点 29 + - 套接字 30 + - 消息队列 31 + - 共享内存段 32 + - 信号量 33 + - 密钥 34 + 35 + 所有这些对象的描述的一部分是一组凭据。集合中的内容取决于对象的类型。 36 + 37 + 2. 对象所有权 38 + 39 + 大多数对象的凭据中会有一个子集用来表示该对象的所有权。 40 + 这用于资源核算和限制(如磁盘配额和任务资源限制)。 41 + 42 + 例如,在标准的UNIX文件系统中,这将由标记在索引节点上的UID定义。 43 + 44 + 3. 对象上下文 45 + 46 + 此外在这些对象的凭据中,将有一个子集表示对象的“对象上下文”。 47 + 这可能与(2)中相同,也可能不同 —— 例如,在标准的UNIX文件中, 48 + 这是由标记在索引节点上的UID和GID定义的。 49 + 50 + 对象上下文是进行安全计算的一部分,当对象被操作时会用到。 51 + 52 + 4. 主体 53 + 54 + 主体是正在对其他对象执行操作的对象。 55 + 56 + 系统中的大多数对象是不活动的:他们不会对系统中的其他对象起作用。 57 + 进程/任务是明显的例外:它们可以访问和操纵其他对象。 58 + 59 + 任务之外的其他对象在某些情况下也可以是主体。例如,打开的文件可以使用 60 + 名为 ``fcntl(F_SETOWN)`` 的任务给它的UID和EUID向一个任务发送SIGIO 61 + 信号。在这种情况下,文件结构也会有一个主体上下文。 62 + 63 + 5. 主体上下文 64 + 65 + 主体对其凭据有一个额外的解释。其凭据的一个子集形成了“主体上下文”。主体 66 + 上下文在主体执行操作时作为安全计算的一部分使用。 67 + 68 + 例如,Linux任务在操作文件时会有FSUID、FSGID和附加组列表 —— 这些凭据 69 + 与通常构成任务的对象上下文的真实UID和GID是相互独立的。 70 + 71 + 6. 操作 72 + 73 + Linux提供许多操作,主体可以对对象执行这些操作。可用的操作集取决于主体 74 + 和对象的性质。 75 + 76 + 77 + 操作包括读取、写入、创建和删除文件,以及派生(forking)或发送 78 + 信号(signalling)和跟踪(tracing)任务等。 79 + 80 + 7. 规则,访问控制列表和安全计算 81 + 82 + 当主体对对象进行操作时,会进行安全计算。这涉及到使用主体上下文、对象 83 + 上下文和操作,并搜索一个或多个规则集,以确定在给定这些上下文的情况下, 84 + 主体是否被授予或拒绝以所需方式对对象进行操作的权限。 85 + 86 + 主要有两个规则来源: 87 + 88 + a. 自主访问控制(DAC): 89 + 90 + 有时,对象的描述中会包含一组规则。这就是所谓的“访问控制列表”或‘ACL’。 91 + 一个Linux文件可以提供多个ACL。 92 + 93 + 例如,传统的UNIX文件包括一个权限掩码,它是一个简化的ACL,具有三个固定的 94 + 主体类别(“用户”、“组”和“其他”),每一个都可以被授予一定的特权(如“读取”、 95 + “写入”和“执行” —— 无论这些映射对于对象意味着什么)。然而,UNIX文件权限不 96 + 允许任意指定主体,因此用途有限。 97 + 98 + Linux文件还可以支持POSIX ACL。这是一个规则列表,为任意主体授予各种权限。 99 + 100 + b. 强制访问控制(MAC): 101 + 102 + 整个系统可能有一个或多个规则集,适用于所有主体和对象,不考虑它们的来源。 103 + SELinux和Smack就是这种情况的例子。 104 + 105 + 在SELinux和Smack的情况下,每个对象在其凭据中都被赋予一个标签。当请求执 106 + 行操作时,它们使用主体标签、对象标签和操作,寻找一个规则,该规则表示此操 107 + 作是授予还是拒绝的。 108 + 109 + 110 + 凭据类型 111 + ======== 112 + 113 + Linux内核支持以下类型的凭据: 114 + 115 + 1. 传统的UNIX凭据。 116 + 117 + - 真实用户ID 118 + - 真实组ID 119 + 120 + UID和GID由大多数(如果不是全部)Linux对象携带,即使有时它们需要被虚构出 121 + 来(例如FAT或CIFS文件,这些文件来源于Windows)。这些(通常)定义了该对象 122 + 的对象上下文,但任务在某些情况下略有不同。 123 + 124 + - 有效用户ID,保存用户ID和FS用户ID 125 + - 有效组ID,保存组ID和FS组ID 126 + - 补充组 127 + 128 + 这些是仅由任务使用的额外凭据。通常,一个EUID/EGID/GROUPS 被用作主体上下文, 129 + 而真实UID/GID 被用作对象上下文。对于任务,这并不总是正确的。 130 + 131 + 2. 能力 132 + 133 + - 允许的能力集合 134 + - 可继承的能力集合 135 + - 有效的能力集合 136 + - 能力边界集合 137 + 138 + 这些仅由任务携带,表示授予任务的超出普通任务权限的能力。这些可以通过传统 139 + UNIX凭据的更改进行隐式操作,但也可以通过 ``capset()`` 系统调用直接操作。 140 + 141 + 允许的能力是指进程可以通过 ``capset()`` 将其添加到其有效或允许集合中的 142 + 那些能力。这个可继承的集合也可能受到这样的限制。 143 + 144 + 有效能力是任务本身实际可以使用的能力。 145 + 146 + 可继承能力是那些可以通过 ``execve()`` 传递的能力。 147 + 148 + 边界集限制了通过 ``execve()`` 继承的能力,特别是在以UID 0执行二进制文件时。 149 + 150 + 3. 安全管理标记(securebits) 151 + 152 + 它们用于控制上述凭据在特定操作如execve()中的操作和继承方式。它们并不直接 153 + 用作对象或主体凭据使用。 154 + 155 + 4. 密钥和密钥环 156 + 157 + 这些仅由任务携带。它们用于携带和缓存不适合放入其他标准UNIX凭据中的安全令牌。 158 + 它们用诸如使网络文件系统密钥在进程执行的文件访问时可用,而无需让普通程序了解 159 + 涉及的安全细节。 160 + 161 + 密钥环是一种特殊类型的密钥。它们携带一组其他密钥,并可以搜索来查找所需的密钥。 162 + 每个进程可以订阅多个密钥环: 163 + 164 + 每线程密钥 165 + 每进程密钥环 166 + 每会话密钥环 167 + 168 + 当进程访问一个密钥时,若尚不存在,则通常会将其缓存在一个密钥环中,以便将来的 169 + 访问时找到该密钥。 170 + 171 + 有关密钥的更多信息,请参见 ``Documentation/translations/zh_CN/security/keys/*`` 。 172 + 173 + 5. LSM 174 + 175 + Linux安全模块允许在任务执行操作时施加额外的控制。目前,Linux支持几种LSM选项。 176 + 177 + 一些工作通过标记系统中的对象,并应用一组规则(策略)说明某个标签的任务可以对 178 + 另一标签的对象执行哪些操作。 179 + 180 + 6. AF_KEY 181 + 182 + 这是一种基于套接字网络协议栈中的凭据管理[RFC 2367]。本文档中没有讨论它,因为不 183 + 直接与任务和文件凭据进行交互,而是保留了系统级的凭据。 184 + 185 + 186 + 当打开一个文件时,打开任务的主体上下文的一部分会记录在创建的文件结构中。 187 + 这使得使用该文件结构的操作可以使用这些凭据,而不是发出操作的任务的主体上下文。 188 + 一个例子是在网络文件系统上打开的文件,打开文件的凭据应该被呈现给服务器,而不管 189 + 实际进行读取或写入操作的是谁。 190 + 191 + 192 + 文件标记 193 + ======== 194 + 195 + 存储在磁盘上或通过网络获取的文件可能具有注释,构成该文件的对象安全上下文。 196 + 根据文件系统的类型,这些注释可能包括以下一项或多项: 197 + 198 + * UNIX UID, GID, mode; 199 + * Windows user ID; 200 + * Access control list; 201 + * LSM security label; 202 + * UNIX exec privilege escalation bits (SUID/SGID); 203 + * File capabilities exec privilege escalation bits. 204 + 205 + 将这些与任务的主体安全上下文进行比较,并根据比较结果允许或禁止执行某些操作。 206 + 在execve()的情况下,特权提升位起作用,并且可能允许由可执行文件的注释决定的 207 + 进程获得额外的特权。 208 + 209 + 210 + 任务凭据 211 + ======== 212 + 213 + 在Linux中,一个任务的所有凭据都保存在一个引用计数结构体‘struct cred’中, 214 + 通过(uid, gid)或(groups, keys, LSM security)进行访问。每个任务在其 215 + task_struct中通过一个名为‘cred’的指针指向其凭据。 216 + 217 + 一旦一组凭据已经准备好并提交,除非以下几种情况,否则不能更改: 218 + 219 + 1. 其引用计数可以更改; 220 + 221 + 2. 它所指向的 group_info 结构体的引用计数可以更改; 222 + 223 + 3. 它所指向的安全数据的引用计数可以更改; 224 + 225 + 4. 它所指向的任何密钥环的引用计数可以更改; 226 + 227 + 5. 它所指向的任何密钥环可以被撤销、过期或其安全属性可以更改; 228 + 229 + 6. 它所指向的任何密钥环的内容可以更改(密钥环的整个目的就是作为一组共享凭据, 230 + 可由具有适当访问权限的任何人修改)。 231 + 232 + 要更改cred结构体中的任何内容,必须遵循复制和替换的原则。首先进行复制,然后修 233 + 改副本,最后使用RCU(读-复制-更新)将任务指针更改为指向新的副本。有一些封装可 234 + 用于帮助执行这个过程(见下文)。 235 + 236 + 一个任务只能修改自己的凭据;不再允许一个任务修改另一个任务的凭据。 237 + 这意味着 ``capset()`` 系统调用不再允许使用除当前进程之外的任何PID。 238 + 此外, ``keyctl_instantiate()`` 和 ``keyctl_negate()`` 函数也不再 239 + 允许在请求进程中附加到特定于进程的密钥环,因为实例化进程可能需要创建它们。 240 + 241 + 242 + 不可变凭据 243 + ---------- 244 + 245 + 一旦一组凭据已经被公开(例如通过调用 ``commit_creds()`` ),必须将其视为 246 + 不可变的,除了两个例外情况: 247 + 248 + 1. 引用计数可以被修改。 249 + 250 + 2. 虽然无法更改一组凭据的密钥环订阅,但订阅的密钥环的内容可以被更改。 251 + 252 + 为了在编译时捕获意外的凭据修改,struct task_struct具有_const_指针指向其凭据集, 253 + struct file也是如此。此外,某些函数如 ``get_cred()`` 和 ``put_cred()`` 在 254 + const指针上操作,因此不需要进行类型转换,但需要临时放弃const限定,以便能够修改 255 + 引用计数。 256 + 257 + 258 + 访问任务凭据 259 + ------------ 260 + 261 + 任务只能修改自己的凭据,允许当前进程可以读取或替换自己的凭据,无需任何形式锁定的 262 + 情况下 —— 这极大简化了事情。它可以调用:: 263 + 264 + const struct cred *current_cred() 265 + 266 + 获取指向其凭据结构的指针,并且之后不必释放它。 267 + 268 + 有一些方便的封装用于检索任务凭据的特定方面(在每种情况下都只返回值):: 269 + 270 + uid_t current_uid(void) Current's real UID 271 + gid_t current_gid(void) Current's real GID 272 + uid_t current_euid(void) Current's effective UID 273 + gid_t current_egid(void) Current's effective GID 274 + uid_t current_fsuid(void) Current's file access UID 275 + gid_t current_fsgid(void) Current's file access GID 276 + kernel_cap_t current_cap(void) Current's effective capabilities 277 + struct user_struct *current_user(void) Current's user account 278 + 279 + 还有一些方便的封装,用于检索任务凭据的特定关联对:: 280 + 281 + void current_uid_gid(uid_t *, gid_t *); 282 + void current_euid_egid(uid_t *, gid_t *); 283 + void current_fsuid_fsgid(uid_t *, gid_t *); 284 + 285 + 在从当前任务的凭据中检索后,通过其参数返回这些值对。 286 + 287 + 288 + 此外,还有一个函数用于获取当前进程的当前凭据集的引用:: 289 + 290 + const struct cred *get_current_cred(void); 291 + 292 + 以及用于获取对一个实际上不存在于struct cred中的凭据的引用的函数:: 293 + 294 + struct user_struct *get_current_user(void); 295 + struct group_info *get_current_groups(void); 296 + 297 + 分别获得对当前进程的 user accounting structure 和补充组列表的引用。 298 + 299 + 一旦获得引用,就必须使用 ``put_cred()``, ``free_uid()`` 或 300 + ``put_group_info()`` 来适当释放它。 301 + 302 + 303 + 访问其他任务的凭据 304 + ------------------ 305 + 306 + 虽然一个任务可以在不需要锁定的情况下访问自己的凭据,但想要访问另一个任务 307 + 的凭据的任务并非如此。它必须使用RCU读锁和 ``rcu_dereference()``。 308 + 309 + ``rcu_dereference()`` 是由:: 310 + 311 + const struct cred *__task_cred(struct task_struct *task); 312 + 313 + 这应该在RCU读锁中使用,如下例所示:: 314 + 315 + void foo(struct task_struct *t, struct foo_data *f) 316 + { 317 + const struct cred *tcred; 318 + ... 319 + rcu_read_lock(); 320 + tcred = __task_cred(t); 321 + f->uid = tcred->uid; 322 + f->gid = tcred->gid; 323 + f->groups = get_group_info(tcred->groups); 324 + rcu_read_unlock(); 325 + ... 326 + } 327 + 328 + 如果需要长时间持有另一个任务的凭据,并且可能在此过程中休眠,则调用方 329 + 应该使用以下函数来获取对这些凭据的引用:: 330 + 331 + const struct cred *get_task_cred(struct task_struct *task); 332 + 333 + 这个函数内部完成了所有的RCU操作。当使用完这些凭据时,调用方必须调用put_cred() 334 + 函数释放它们。 335 + 336 + .. note:: 337 + ``__task_cred()`` 的结果不应直接传递给 ``get_cred()`` , 338 + 因为这可能与 ``commit_cred()`` 发生竞争条件。 339 + 340 + 还有一些方便的函数可以访问另一个任务凭据的特定部分,将RCU操作对调用方隐藏起来:: 341 + 342 + uid_t task_uid(task) Task's real UID 343 + uid_t task_euid(task) Task's effective UID 344 + 345 + 如果调用方在此时已经持有RCU读锁,则应使用:: 346 + 347 + __task_cred(task)->uid 348 + __task_cred(task)->euid 349 + 350 + 类似地,如果需要访问任务凭据的多个方面,应使用RCU读锁,调用 ``__task_cred()`` 351 + 函数,将结果存储在临时指针中,然后从临时指针中调用凭据的各个方面,最后释放锁。 352 + 这样可以防止多次调用昂贵的RCU操作。 353 + 354 + 如果需要访问另一个任务凭据的其他单个方面,可以使用:: 355 + 356 + task_cred_xxx(task, member) 357 + 358 + 这里的‘member’是cred结构体的非指针成员。例如:: 359 + 360 + uid_t task_cred_xxx(task, suid); 361 + 362 + 将从任务中检索‘struct cred::suid’,并执行适当的RCU操作。对于指针成员, 363 + 不能使用这种形式,因为它们指向的内容可能在释放RCU读锁的瞬间消失。 364 + 365 + 366 + 修改凭据 367 + -------- 368 + 369 + 如先前提到的,一个任务只能修改自己的凭据,不能修改其他任务的凭据。这意味 370 + 着它不需要使用任何锁来修改自己的凭据。 371 + 372 + 要修改当前进程的凭据,函数应首先调用:: 373 + 374 + struct cred *prepare_creds(void); 375 + 376 + 这将锁定current->cred_replace_mutex,然后分配并构建当前进程凭据的副本。 377 + 如果成功,函数返回时仍然保持互斥锁。如果不成功(内存不足),则返回NULL。 378 + 379 + 互斥锁防止 ``ptrace()`` 在进行凭据构建和更改的安全检查时更改进程的ptrace 380 + 状态,因为ptrace状态可能会改变结果,特别是在 ``execve()`` 的情况下。 381 + 382 + 新的凭据集应适当地进行修改,并进行任何安全检查和挂钩。在此时,当前和建议的 383 + 凭据集都可用,因为current_cred()将返回当前的凭据集。 384 + 385 + 在替换组列表时,必须在将其添加到凭据之前对新列表进行排序,因为使用二分查找 386 + 测试成员资格。实际上,这意味着在set_groups()或set_current_groups()之 387 + 前应调用groups_sort()。groups_sort()不能在共享的 ``struct group_list`` 388 + 上调用,因为即使数组已经排序,它也可能作为排序过程的一部分对元素进行排列。 389 + 390 + 当凭据集准备好时,应通过调用以下函数将其提交给当前进程:: 391 + 392 + int commit_creds(struct cred *new); 393 + 394 + 这将修改凭据和进程的各个方面,给LSM提供机会做同样的修改,然后使用 395 + ``rcu_assign_pointer()`` 将新的凭据实际提交给 ``current->cred`` , 396 + 释放 ``current->cred_replace_mutex`` 以允许 ``ptrace()`` 进行操 397 + 作,并通知调度程序和其他组件有关更改的情况。 398 + 399 + 该函数保证返回0,以便可以在诸如 ``sys_setresuid()`` 函数的末尾进行尾调用。 400 + 401 + 请注意,该函数会消耗调用者对新凭据的引用。调用者在此之后不应调用 402 + ``put_cred()`` 释放新凭据。 403 + 404 + 此外,一旦新的凭据上调用了该函数,就不能进一步更改这些凭据。 405 + 406 + 407 + 如果在调用 ``prepare_creds()`` 之后安全检查失败或发生其他错误, 408 + 则应调用以下函数:: 409 + 410 + void abort_creds(struct cred *new); 411 + 412 + 这将释放 ``prepare_creds()`` 获取的 ``current->cred_replace_mutex`` 的锁, 413 + 并释放新的凭据。 414 + 415 + 一个典型的凭据修改函数看起来像这样:: 416 + 417 + int alter_suid(uid_t suid) 418 + { 419 + struct cred *new; 420 + int ret; 421 + 422 + new = prepare_creds(); 423 + if (!new) 424 + return -ENOMEM; 425 + 426 + new->suid = suid; 427 + ret = security_alter_suid(new); 428 + if (ret < 0) { 429 + abort_creds(new); 430 + return ret; 431 + } 432 + 433 + return commit_creds(new); 434 + } 435 + 436 + 437 + 管理凭据 438 + -------- 439 + 440 + 有一些函数用来辅助凭据管理: 441 + 442 + - ``void put_cred(const struct cred *cred);`` 443 + 444 + 这将释放对给定凭据集的引用。如果引用计数为零,凭据集将由 445 + RCU系统安排进行销毁。 446 + 447 + - ``const struct cred *get_cred(const struct cred *cred);`` 448 + 449 + 这将获取对活动凭据集的引用。返回指向凭据集的指针。 450 + 451 + - ``struct cred *get_new_cred(struct cred *cred);`` 452 + 453 + 这将获取对当前正在构建且可变的凭据集的引用。返回指向凭据集的指针。 454 + 455 + 打开文件凭据 456 + ============ 457 + 458 + 当打开新文件时,会获取对打开任务凭据的引用,并将其附加到文件结构体的 459 + ``f_cred`` 字段中,替代原来的 ``f_uid`` 和 ``f_gid`` 。原来访问 460 + ``file->f_uid`` 和 ``file->f_gid`` 的代码现在应访问 ``file->f_cred->fsuid`` 461 + 和 ``file->f_cred->fsgid`` 。 462 + 463 + 安全访问 ``f_cred`` 的情况下可以不使用RCU或加锁,因为指向凭据的指针 464 + 以及指向的凭据结构的内容在文件结构的整个生命周期中保持不变,除非是 465 + 上述列出的例外情况(参阅任务凭据部分)。 466 + 467 + 为了避免“混淆代理”权限提升攻击,在打开的文件后续操作时,访问控制检查 468 + 应该使用这些凭据,而不是使用“当前”的凭据,因为该文件可能已经被传递给 469 + 一个更具特权的进程。 470 + 471 + 覆盖VFS对凭据的使用 472 + =================== 473 + 474 + 在某些情况下,需要覆盖VFS使用的凭据,可以通过使用不同的凭据集调用 475 + 如 ``vfs_mkdir()`` 来实现。以下是一些进行此操作的位置: 476 + 477 + * ``sys_faccessat()``. 478 + * ``do_coredump()``. 479 + * nfs4recover.c.
+4 -4
Documentation/translations/zh_CN/security/index.rst
··· 15 15 .. toctree:: 16 16 :maxdepth: 1 17 17 18 + credentials 19 + snp-tdx-threat-model 18 20 lsm 19 21 sak 22 + self-protection 20 23 siphash 24 + tpm/index 21 25 digsig 22 26 landlock 23 27 24 28 TODOLIST: 25 - * credentials 26 - * snp-tdx-threat-model 27 29 * IMA-templates 28 30 * keys/index 29 31 * lsm-development 30 32 * SCTP 31 - * self-protection 32 - * tpm/index 33 33 * secrets/index 34 34 * ipe
+22
Documentation/translations/zh_CN/security/keys/index.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + .. include:: ../../disclaimer-zh_CN.rst 4 + 5 + :Original: Documentation/security/keys/index.rst 6 + 7 + :翻译: 8 + 9 + 10 + ======== 11 + 内核密钥 12 + ======== 13 + 14 + .. toctree:: 15 + :maxdepth: 1 16 + 17 + 18 + TODOLIST: 19 + * core 20 + * ecryptfs 21 + * request-key 22 + * trusted-encrypted
+17
Documentation/translations/zh_CN/security/secrets/index.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: ../../disclaimer-zh_CN.rst 3 + 4 + :Original: Documentation/security/secrets/index.rst 5 + 6 + :翻译: 7 + 8 + ===================== 9 + 密钥文档 10 + ===================== 11 + 12 + .. toctree:: 13 + 14 + 15 + TODOLIST: 16 + 17 + * coco
+271
Documentation/translations/zh_CN/security/self-protection.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: ../disclaimer-zh_CN.rst 3 + :Original: Documentation/security/self-protection.rst 4 + 5 + :翻译: 6 + 7 + 张巍 zhangwei <zhangwei@cqsoftware.com.cn> 8 + 9 + ============ 10 + 内核自我保护 11 + ============ 12 + 13 + 内核自我保护是指在Linux内核中设计与实现的各种系统与结构 14 + 以防止内核本身的安全漏洞问题。它涵盖了广泛问题,包括去除 15 + 整个类的漏洞,阻止安全漏洞利用方法,以及主动检测攻击尝 16 + 试。并非所有的话题都在本文中涉及,但它应该为了解内核自我 17 + 保护提供一个合理的起点,并解答常见的问题。(当然,欢迎提 18 + 交补丁!) 19 + 20 + 在最坏的情况下,我们假设一个非特权的本地攻击者对内核内存 21 + 有任意读写访问权限。虽然在许多情况下,漏洞被利用时并不会 22 + 提供此级别的访问权限,但如果我们能防御最坏情况,也能应对 23 + 权限较低的攻击。一个更高的标准,且需要牢记的是保护内核免 24 + 受具有特权的本地攻击者的攻击,因为root用户可以有更多权限。 25 + (尤其是当他们能够加载任意内核模块时) 26 + 27 + 成功的自我保护的目标是:有效、默认开启、不需要开发者主动 28 + 选择、没有性能影响、不妨碍内核调试、并且没有测试。虽然很 29 + 难满足所有的这些目标,但明确提到这些目标非常重要,因为这 30 + 些方面需要被探索、解决或接受。 31 + 32 + ========== 33 + 攻击面缩减 34 + ========== 35 + 36 + 防止安全漏洞最基本的防御方式是减少可以被用来重定向执行的 37 + 内核区域。这包括限制用户公开使用的API、使内核API更难被错 38 + 误使用、最小化可写内核内存区域等。 39 + 40 + 严格的内核内存权限 41 + ------------------- 42 + 43 + 当所有内核内存都是可写的,攻击者可以轻松地重定向执行流。 44 + 为了减少这种攻击目标的可用性,内核需要更严格的权限集来 45 + 保护其内存。 46 + 47 + 可执行代码和只读数据必须不可写 48 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 49 + 50 + 任何具有可执行内存的区域必须不可写,显然这也包括内核文本 51 + 本身。我们还必须考虑其他地方:内核模块、JIT内存等,(在 52 + 某些情况下,为了支持像指令替代、断点、kprobes等功能,这些 53 + 区域会暂时被设置为可写。如果这些功能必须存在于内核中,它 54 + 们的实现方式是:在更新期间将内存临时设置可写,然后再恢复 55 + 为原始权限。) 56 + 57 + 为了支持这一点,CONFIG_STRICT_KERNEL_RWX 和 58 + CONFIG_STRICT_MODULE_RWX 的设计旨在确保代码不可写,数据不 59 + 可执行,以及只读数据既不可写也不可执行。 60 + 61 + 大多数架构默认支持这些选项,且用户无法选择。对于一些像arm 62 + 这种希望能够选择这些选项的架构,可以在架构Kconfig中选择 63 + ARCH_OPTIONAL_KERNEL_RWX以启用Kconfig提示。 64 + CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT决定在启用 65 + ARCH_OPTIONAL_KERNEL_RWX时的默认设置。 66 + 67 + 函数指针和敏感变量必须不可写 68 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 69 + 70 + 内核内存中有大量的函数指针,这些指针被内核查找并用于继续执行 71 + (例如,描述符/向量表、文件/网络等操作结构等)。这些变量的数 72 + 量必须减少到最低限度 73 + 74 + 许多像这样的变量可以通过设置为"const"来实现只读,从而使它们 75 + 存放在内核的.rodata段而非.data段,从而获得内核严格内存权限的 76 + 保护。 77 + 78 + 对于在_init是仅初始化一次的变量,可以使用_ro_after_init属性 79 + 进行标记。 80 + 81 + 剩下的变量通常是那些更新频率较低的(例如GDT)。这些变量需要另 82 + 一个机制(类似于上述提到的对内核代码所做的临时例外),以便在 83 + 其余生命周期内保持只读状态。(例如,在进行更新时,只有执行 84 + 更新的CPU线程会被授予对内存的不可中断写入访问权限。) 85 + 86 + 将内核内存与用户空间内存分隔开 87 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 88 + 89 + 内核绝对不可以执行用户空间内存,同时,内核也不得在没有明确预 90 + 期的情况下访问用户内存空间。这些规则可以通过一些硬件限制来支 91 + 持(如x86的SMEP/SMAP,ARM的PXN/PAN)或通过仿真(如ARM的内存 92 + 域)来强制执行。通过这种方式阻止用户空间内存的访问,攻击者就 93 + 无法将执行和数据解析转移到易于控制的用户空间内存,从而迫使攻 94 + 击完全在内核中进行。 95 + 96 + 减少对系统调用的访问 97 + -------------------- 98 + 99 + 对于64位系统,一种消除许多系统调用最简单的方法是构建时不启用 100 + CONFIG_CONPAT。然而,这种情况通常不可行。 101 + 102 + “seccomp”系统为用户空间提供了一种可选功能,提供了一种减少可供 103 + 运行中进程使用内核入口点数量的方法。这限制了可以访问内核代码 104 + 的范围,可能降低了某个特定漏洞被攻击者利用的可能性。 105 + 106 + 一个改进的方向是创建有效的方法,仅允许受信任的进程访问例如兼 107 + 容模式、用户命名空间、BPF创建和性能分析等功能。这将把内核入口 108 + 点范围限制在通常可以被非特权用户空间进程访问的较常见集合中 109 + 110 + 限制对内核模块的访问 111 + -------------------- 112 + 113 + 内核绝不应允许非特权用户加载特定的内核模块,因为这可能为攻击者 114 + 提供一个意外扩展的可用攻击面的方法。(通过已预定义子系统按需加 115 + 载模块,如MODULE_ALIAS_*,被认为是“预期的”,但即便如此,也应对 116 + 这些情况给予更多的关注。)例如,通过非特权的套接字API加载文件 117 + 系统模块是没有意义的:只有root用户或物理本地用户应该触发文件系 118 + 统模块的加载。(在某些情况下,这甚至可能存在争议。) 119 + 120 + 为了防止特权用户的攻击,系统可能需要完全禁止模块加载(例如,通 121 + 过单体内核构建或modules_disabled sysctl),或者使用签名模块(例 122 + 如,CONFIG_MODULE_SIG_FORCE或通过LoadPin保护的dm-crypt),以防 123 + 止root用户通过模块加载器加载任意内核代码。 124 + 125 + 内存完整性 126 + ---------- 127 + 128 + 内核中有许多内存结构在攻击过程中被定期泛滥用以获取执行控制,迄今 129 + 为止,最常见的是堆栈缓冲区溢出,在这种攻击中,堆栈上存储的返回地 130 + 址被覆盖。除此之外,还有许多其他类型的攻击,防护措施也应运而生。 131 + 132 + 堆栈缓冲区溢出 133 + -------------- 134 + 135 + 经典的堆栈缓冲区溢出攻击是指超出栈上分配的变量预期大小,从而将一 136 + 个受控值写入栈帧的返回地址。最常见的防御措施是堆栈保护 137 + (CONFIG_STACKPROTECTOR),它在函数返回前会验证栈上的“stack canary”。 138 + 其他防御措施还包括影子堆栈等。 139 + 140 + 堆栈深度溢出 141 + ------------ 142 + 143 + 一个不太容易被理解的攻击方式是利用bug触发内核通过深度函数调用或 144 + 大的堆栈分配来消耗堆栈内存。通过这种攻击,攻击者可以将数据写入内 145 + 核预分配堆栈空间之外的敏感结构。为了更好的防护这种攻击,必须进行 146 + 两项重要的更改:将敏感的线程信息结构转移到其他地方,并在堆栈底部 147 + 添加一个故障内存洞,以捕获这些溢出 148 + 149 + 栈内存完整性 150 + ------------ 151 + 152 + 用于跟踪堆空闲列表的结构可以在分配和释放时进行完整性检查,以确保它 153 + 们不会被用来操作其它内存区域。 154 + 155 + 计算器完整性 156 + ------------ 157 + 158 + 内核中的许多地方使用原子计数器来跟踪对象引用或执行类似的生命周期管 159 + 理。当这些计数器可能发生溢出时(无论是上溢还是下溢),这通常会暴露 160 + 出使用后释放(use-after-free)漏洞。通过捕捉原子计数器溢出,这类漏 161 + 洞就可以消失。 162 + 163 + 大小计算溢出检测 164 + ---------------- 165 + 166 + 与计算器溢出类似,整数溢出(通常是大小计算)需要在运行时进行检测, 167 + 以防止这类在传统上会导致能够写入内核缓冲区末尾之外的漏洞。 168 + 169 + 概率性防御 170 + ---------- 171 + 172 + 尽管许多防御措施可以被认定是确定的(例如,只读内存不能写入),但 173 + 有些确保措施仅提供统计防御,即攻击者必须收集足够的关于运行系统的 174 + 信息才能突破防御。尽管这些防御并不完美,但它们确实提供了有意义的 175 + 保护。 176 + 177 + 栈保护、迷惑技术和其他秘密 178 + -------------------------- 179 + 180 + 值得注意的是,像之前讨论的栈保护这样的技术,从技术上来说是统计性防 181 + 御,因为它们依赖于一个秘密值,而这样的值可能会通过信息泄露漏洞而被 182 + 发现。 183 + 184 + 对于想JIT(及时翻译器)这样的情况,其中可执行内容可能部分由用户空间 185 + 控制,也需要类似的秘密之来迷惑。 186 + 187 + 至关重要的是,所使用的秘密值必须是独立的(例如,每个栈使用不同的栈 188 + 保护值),并且具有高熵(例如,随机数生成器(RNG)是否正常工作?), 189 + 以最大限度地提高其成功率。 190 + 191 + 内核地址空间布局随机化(KASLR) 192 + ------------------------------- 193 + 194 + 由于内核内存的位置几乎总是攻击成功的关键因素,因此使内核内存位置变 195 + 得非确定性会增加攻击的难度。(请注意,这反过来提高了信息泄露的价 196 + 值,因为泄露的信息可以用来发现目标内存位置。) 197 + 198 + 文本和模块基址 199 + -------------- 200 + 201 + 通过在启动时重新设定内核的物理基地址和虚拟基地址 202 + (CONFIG_RANDOMIZE_BASE),那些需要利用内核代码的攻击将会受阻。此外 203 + 通过偏移模块加载基地址,意味着即使系统每次启动时按相同顺序加载同一 204 + 组模块,这些模块也不会与内核文本的其余部分公用一个基地址。 205 + 206 + 堆栈基地址 207 + ---------- 208 + 209 + 如果进程之间内核堆栈的基地址不相同,甚至在不同系统调用之间也不相同, 210 + 那么栈上或超出栈的目标位置就会变得更加难以确定。 211 + 212 + 动态内存基址 213 + ------------ 214 + 215 + 很多内核的动态内存(例如kmalloc,vmalloc等)由于早期启动初始化的顺 216 + 序,最终布局是相对确定的。如果这些区域的基地址在启动之间不相同,攻 217 + 击者就无法轻易定位它们,必须依赖于针对该区域的信息泄露才能成功。 218 + 219 + 结构布局 220 + -------- 221 + 222 + 通过在每次构建时对敏感结构的布局进行随机化处理,攻击这必须将攻击调 223 + 节到已知的内核版本,或者泄露足够的内核内存来确定结构布局,然后才能 224 + 对其进行操作。 225 + 226 + 防止信息泄露 227 + ------------ 228 + 229 + 由于敏感结构的位置是攻击的主要目标,因此防止内核内存地址和内核内存 230 + 内容泄露非常重要(因为它们可能包含内核地址或者其他敏感数据,例如 231 + 栈保护值)。 232 + 233 + 内核地址 234 + -------- 235 + 236 + 将内核地址打印到用户空间会泄露有关内核内存布局的敏感信息。在使用任 237 + 何打印符号打印原始地址时,目前%px,%p[ad](和在某些情况下的%p[sSb]) 238 + 时。使用这些格式符写入的文件需要限制为只有特权进程可读。 239 + 240 + 在4.14及以前的内核版本中,使用%p格式符打印的是原始地址。从4.15-rcl 241 + 版本开始,使用%p格式符打印的地址会在打印前进行哈希处理。 242 + 243 + [*]如果启用KALLSYMS并且符号查找失败,则打印原始地址;如果没有启用 244 + KALLSYSM,则会直接打印原始地址。 245 + 246 + 唯一标识符 247 + ---------- 248 + 249 + 内核内存地址绝不可能用作向用户空间公开的标识符。相反,应该使用原子 250 + 计数器,IDR(ID映射表)或类似的唯一标识符。 251 + 252 + 内存初始化 253 + ---------- 254 + 255 + 复制到用户空间的内存必须始终被完全初始化,如果没有显式地使用memset() 256 + 函数进行初始化,那就需要修改编译器,确保清除结构中的空洞。 257 + 258 + 内存清除 259 + -------- 260 + 261 + 在释放内存时,最好对内存内容进行清除处理,以防止攻击者重用内存中以前 262 + 的内容。例如,在系统调用返回时清除堆栈(CONFIG_GCC_PLUGIN_STACKLEAK), 263 + 在释放堆内容是清除其内容。这有助于防止许多未初始化变量攻击、堆栈内容 264 + 泄露、堆内容泄露以及使用后释放攻击(user-after-free)。 265 + 266 + 目标追踪 267 + -------- 268 + 269 + 为了帮助消除导致内核地址被写入用户空间的各种错误,需要跟踪写入的目标。 270 + 如果缓冲区的目标是用户空间(例如,基于seq_file的/proc文件),则应该自 271 + 动审查敏感值。
+209
Documentation/translations/zh_CN/security/snp-tdx-threat-model.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: ../disclaimer-zh_CN.rst 3 + 4 + :Original: Documentation/security/snp-tdx-threat-model.rst 5 + 6 + :翻译: 7 + 8 + 毛玉贤 Yuxian Mao <maoyuxian@cqsoftware.com.cn> 9 + 10 + ========================== 11 + Linux中x86虚拟化的机密计算 12 + ========================== 13 + 14 + .. contents:: :local: 15 + 16 + By: Elena Reshetova <elena.reshetova@intel.com> and Carlos Bilbao <carlos.bilbao.osdev@gmail.com> 17 + 18 + 动机 19 + ==== 20 + 21 + 在x86虚拟环境中从事机密计算工作的内核开发人员,是基于一组与传统Linux内核 22 + 威胁模型有所不同的假设条件下开展工作的。传统意义上,Linux威胁模型承认攻 23 + 击者可以存在于用户空间,以及一小部分能够通过各种网络接口或有限的硬件特定 24 + 暴露接口(如USB、Thunderbolt)与内核交互的外部攻击者。本文档的目的是解释 25 + 在机密计算领域中出现的额外攻击向量,并讨论为 Linux 内核提出的保护机制。 26 + 27 + 概述与术语 28 + ========== 29 + 30 + 机密计算(Confidential Computing,简称CoCo)是一个广泛的术语,涵盖了多种 31 + 旨在保护数据在使用过程中(与静态数据或传输数据相比)的机密性和完整性的安 32 + 全技术。从本质上讲,机密计算(CoCo)解决方案提供了一个受信任执行环境(TEE), 33 + 在该环境中可以进行安全的数据处理,因此,它们通常根据预期在TEE中运行的软件 34 + 来进一步划分为不同的子类型。本文档专注于一类针对虚拟化环境的机密计算技术 35 + (Confidential Computing, CoCo),这些技术允许在可信执行环境 36 + (Trusted Execution Environment, TEE)中运行虚拟机(VM)。从现在起,本文档 37 + 将把这一类机密计算(CoCo)技术称为“虚拟化环境(VE)中的机密计算(CoCo)”。 38 + 39 + 在虚拟化环境中,机密计算(CoCo)指的是一组硬件和/或软件技术,这些技术能够 40 + 为在CoCo虚拟机(VM)内运行的软件提供更强的安全保障。具体来说,机密计算允许 41 + 其用户确认所有软件组件的可信度,从而将其包含在精简的受信任计算基(TCB)中, 42 + 这是基于机密计算具备验证这些受信组件状态的能力。 43 + 44 + 虽然不同技术之间的具体实现细节有所不同,但所有现有机制都旨在为虚拟机的客户 45 + 内存和执行状态(vCPU寄存器)提供更高的机密性和完整性,更严格地控制客户中断 46 + 注入,并提供一些额外机制来控制客户与宿主机之间的页映射。有关x86特定解决方案 47 + 的更多细节,可以参考 48 + :doc:`Intel Trust Domain Extensions (TDX) </arch/x86/tdx>` 和 49 + `AMD Memory Encryption <https://www.amd.com/system/files/techdocs/sev-snp-strengthening-vm-isolation-with-integrity-protection-and-more.pdf>`_. 50 + 51 + 基本的机密计算(CoCo)客户布局包括宿主机、客户机、用于客户机与宿主机之间通信 52 + 的接口、能够支持CoCo虚拟机(VM)的平台,以及一个在客户VM和底层平台之间充当安 53 + 全管理员的可信中介。宿主机侧的虚拟机监视器(VMM)通常由传统VMM功能的一个子集 54 + 组成,并仍然负责客户机生命周期的管理,即创建或销毁CoCo虚拟机、管理其对系统资 55 + 源的访问等。然而,由于它通常不在CoCo VM的可信计算基(TCB)内,其访问权限受到 56 + 限制,以确保实现安全目标。 57 + 58 + 在下图中,"<--->" 线表示机密计算(CoCo)安全管理员与其余组件之间的双向通信通 59 + 道或接口,这些组件包括客户机、宿主机和硬件(数据流):: 60 + 61 + +-------------------+ +-----------------------+ 62 + | CoCo guest VM |<---->| | 63 + +-------------------+ | | 64 + | Interfaces | | CoCo security manager | 65 + +-------------------+ | | 66 + | Host VMM |<---->| | 67 + +-------------------+ | | 68 + | | 69 + +--------------------+ | | 70 + | CoCo platform |<--->| | 71 + +--------------------+ +-----------------------+ 72 + 73 + 机密计算(CoCo)安全管理器的具体细节在在不同技术之间存在显著差异。例如,在某 74 + 些情况下,它可能通过硬件(HW)实现,而在其他情况下,它可能是纯软件(SW)实现。 75 + 76 + 现有的Linux内核威胁模型 77 + ======================= 78 + 79 + 当前Linux内核威胁模型的总体组件包括:: 80 + 81 + +-----------------------+ +-------------------+ 82 + | |<---->| Userspace | 83 + | | +-------------------+ 84 + | External attack | | Interfaces | 85 + | vectors | +-------------------+ 86 + | |<---->| Linux Kernel | 87 + | | +-------------------+ 88 + +-----------------------+ +-------------------+ 89 + | Bootloader/BIOS | 90 + +-------------------+ 91 + +-------------------+ 92 + | HW platform | 93 + +-------------------+ 94 + 95 + 在启动过程中,引导加载程序(bootloader)和内核之间也存在通信,但本图并未明确 96 + 表示这一点。“接口”框表示允许内核与用户空间之间通信的各种接口。 这包括系统调用、 97 + 内核 API、设备驱动程序等。 98 + 99 + 现有的 Linux 内核威胁模型通常假设其在一个受信任的硬件平台上执行,并且所有固件 100 + 和启动加载程序都包含在该平台的受信任计算基(TCB)中。主要攻击者驻留在用户空间 101 + 中,来自用户空间的所有数据通常被认为是不可信的,除非用户空间具有足够的特权来 102 + 执行受信任的操作。此外,通常还会考虑外部攻击者,包括那些能够访问启用的外部网络 103 + (例如以太网、无线网络、蓝牙)、暴露的硬件接口(例如 USB、Thunderbolt),以及 104 + 能够离线修改磁盘内容的攻击者。 105 + 106 + 关于外部攻击途径,值得注意的是,在大多数情况下,外部攻击者会首先尝试利用用户空 107 + 间的漏洞,但攻击者也可能直接针对内核,特别是在宿主机具有物理访问权限的情况下。直 108 + 接攻击内核的例子包括漏洞 CVE-2019-19524、CVE-2022-0435 和 CVE-2020-24490。 109 + 110 + 机密计算威胁模型及其安全目标 111 + ============================ 112 + 113 + 机密计算在上述攻击者列表中增加了一种新的攻击者类型:可能存在行为不当的宿主机 114 + (这可能包括传统虚拟机监视器VMM的部分组件或全部),由于其较大的软件攻击面, 115 + 通常被置于CoCo VM TCB之外。需要注意的是,这并不意味着宿主机或VMM是故意恶意的, 116 + 而是强调拥有一个较小的CoCo VM TCB具有安全价值。这种新型的攻击者可以被视为一种 117 + 更强大的外部攻击者,因为它位于同一物理机器上(与远程网络攻击者不同),并且对 118 + 客户机内核与大部分硬件的通信具有控制权:: 119 + 120 + +------------------------+ 121 + | CoCo guest VM | 122 + +-----------------------+ | +-------------------+ | 123 + | |<--->| | Userspace | | 124 + | | | +-------------------+ | 125 + | External attack | | | Interfaces | | 126 + | vectors | | +-------------------+ | 127 + | |<--->| | Linux Kernel | | 128 + | | | +-------------------+ | 129 + +-----------------------+ | +-------------------+ | 130 + | | Bootloader/BIOS | | 131 + +-----------------------+ | +-------------------+ | 132 + | |<--->+------------------------+ 133 + | | | Interfaces | 134 + | | +------------------------+ 135 + | CoCo security |<--->| Host/Host-side VMM | 136 + | manager | +------------------------+ 137 + | | +------------------------+ 138 + | |<--->| CoCo platform | 139 + +-----------------------+ +------------------------+ 140 + 141 + 传统上,宿主机对客户机数据拥有无限访问权限,并可以利用这种访问权限来攻击客户虚 142 + 拟机。然而,机密计算(CoCo)系统通过添加诸如客户数据保密性和完整性保护等安全 143 + 特性来缓解此类攻击。该威胁模型假设这些安全特性是可用且完好的。 144 + 145 + 这个 **Linux内核机密计算虚拟机(CoCo VM)的安全目标** 可以总结如下: 146 + 147 + 1. 保护CoCo客户机私有内存和寄存器的机密性和完整性。 148 + 149 + 2. 防止宿主机特权升级到CoCo客户机Linux内核。虽然宿主机(及主机端虚拟机管理程序) 150 + 确实需要一定的特权来创建、销毁或暂停访客,但防止特权升级的部分目标是确保这些 151 + 操作不会为攻击者提供获取客户机内核访问权限的途径。 152 + 153 + 上述安全目标导致了两个主要的**Linux内核机密计算虚拟机(CoCo VM)资产**: 154 + 155 + 1. 客户机内核执行上下文。 156 + 2. 客户机内核私有内存。 157 + 158 + 宿主机对CoCo客户机资源具有完全控制权,并可以随时拒绝访问这些资源。资源的示例包 159 + 括CPU时间、客户机可以消耗的内存、网络带宽等。因此,宿主机对CoCo客户机的拒绝服务 160 + (DoS)攻击超出了此威胁模型的范围。 161 + 162 + Linux CoCo虚拟机攻击面是指从CoCo客户机Linux内核暴露到不受信任的主机的任何接口, 163 + 这些接口未被CoCo技术的软硬件保护所覆盖。这包括所有可能的侧信道攻击以及瞬态执 164 + 行侧信道攻击。显式(非旁道)接口的示例包括访问端口I/O、内存映射I/O(MMIO)和 165 + 直接内存访问(DMA)接口、访问PCI配置空间、特定于虚拟机管理程序(VMM)的超调用 166 + (指向主机端VMM)、访问共享内存页、主机允许注入到访客内核的中断,以及特定于 167 + CoCo技术的超调用(如果存在)。此外,在CoCo系统中,宿主机通常控制创建CoCo客户机 168 + 的过程:它有方法将固件和引导程序镜像、内核镜像以及内核命令行加载到客户机中。所有 169 + 这些数据在通过证明机制确认其完整性和真实性之前,都应视为不可信的。 170 + 171 + 下表显示了针对CoCo客户机Linux内核的威胁矩阵,但并未讨论潜在的缓解策略。该矩阵涉 172 + 及的是CoCo特定版本的客户机、宿主机和平台。 173 + 174 + .. list-table:: CoCo Linux客户机内核威胁矩阵 175 + :widths: auto 176 + :align: center 177 + :header-rows: 1 178 + 179 + * - 威胁名称 180 + - 威胁描述 181 + 182 + * - 客户机恶意配置 183 + - 一个行为不当的主机修改了以下其中一个客户机的配置: 184 + 185 + 1. 客户机固件或引导加载程序 186 + 187 + 2. 客户机内核或模块二进制文件 188 + 189 + 3. 客户机命令行参数 190 + 191 + 这使得宿主机能够破坏在CoCo客户虚拟机内部运行代码的完整性,从而违反了机密计算 192 + (CoCo)的安全目标。 193 + 194 + * - CoCo客户机数据攻击 195 + - 一个行为不当的宿主机对CoCo客户虚拟机与宿主机管理的物理或虚拟设备之间传输的数 196 + 据拥有完全控制权。这使得宿主机可以对这类数据的保密性、完整性和新鲜性进行任何攻击。 197 + 198 + * - 格式错误的运行时输入 199 + - 一个行为不当的宿主机通过客户机内核代码使用的任意通信接口注入格式错误的输入。 200 + 如果代码没有正确处理这些输入,这可能导致从宿主机到客户机内核的特权提升。这包 201 + 括传统的侧信道攻击和/或瞬态执行攻击路径。 202 + 203 + * - 恶意运行时输入 204 + - 一个行为不当的宿主机通过客户机内核代码使用的任意通信接口注入特定的输入值。与之前 205 + 的攻击向量(格式错误的运行时输入)不同,这个输入并非格式错误,而是其值被精心设 206 + 计以影响客户机内核的安全性。这类输入的例子包括向客户机提供恶意的时间或向客户机 207 + 的随机数生成器提供熵值。此外,如果它导致客户机内核执行特定操作(例如处理主机注 208 + 入的中断),此类事件的时序本身也可能成为一种攻击路径。这种攻击是对提供的宿主机输 209 + 入具有抵抗性的一种方式。
+20
Documentation/translations/zh_CN/security/tpm/index.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: ../../disclaimer-zh_CN.rst 3 + 4 + :Original: Documentation/security/tpm/index.rst 5 + 6 + :翻译: 7 + 赵硕 Shuo Zhao <zhaoshuo@cqsoftware.com.cn> 8 + 9 + ================ 10 + 可信平台模块文档 11 + ================ 12 + 13 + .. toctree:: 14 + 15 + tpm_event_log 16 + tpm-security 17 + tpm_tis 18 + tpm_vtpm_proxy 19 + xen-tpmfront 20 + tpm_ftpm_tee
+151
Documentation/translations/zh_CN/security/tpm/tpm-security.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: ../../disclaimer-zh_CN.rst 3 + 4 + :Original: Documentation/security/tpm/tpm-security.rst 5 + 6 + :翻译: 7 + 赵硕 Shuo Zhao <zhaoshuo@cqsoftware.com.cn> 8 + 9 + TPM安全 10 + ======= 11 + 12 + 本文档的目的是描述我们如何使内核使用TPM在面对外部窥探和数据包篡改 13 + 攻击(文献中称为被动和主动中间人攻击)时保持合理的稳健性。当前的 14 + 安全文档适用于TPM2.0。 15 + 16 + 介绍 17 + ---- 18 + 19 + TPM通常是一个通过某种低带宽总线连接到PC的独立芯片。虽然有一些 20 + 例外,例如Intel PTT,它是运行在靠近CPU的软件环境中的软件TPM, 21 + 容易受到不同类型的攻击,但目前大多数强化的安全环境要求使用独立 22 + 硬件TPM,这是本文讨论的使用场景。 23 + 24 + 总线上的窥探和篡改攻击 25 + ---------------------- 26 + 27 + 当前的技术状态允许使用 `TPM Genie`_ 硬件中间人,这是一种简单的外部设备,可以在 28 + 任何系统或笔记本电脑上几秒钟内安装。最近成功演示了针对 `Windows Bitlocker TPM`_ 29 + 系统的攻击。最近同样的攻击针对 `基于TPM的Linux磁盘加密`_ 方案也遭到了同样的攻击。 30 + 下一阶段的研究似乎是入侵总线上现有的设备以充当中间人,因此攻击者需要物理访问几 31 + 秒钟的要求可能不再存在。然而,本文档的目标是尽可能在这种环境下保护TPM的机密性和 32 + 完整性,并尝试确保即使我们不能防止攻击,至少可以检测到它。 33 + 34 + 不幸的是,大多数TPM功能,包括硬件重置功能,都能被能够访问总线的攻击 35 + 者控制,因此下面我们将讨论一些可能出现的干扰情况。 36 + 37 + 测量(PCR)完整性 38 + ----------------- 39 + 40 + 由于攻击者可以向TPM发送自己的命令,他们可以发送任意的PCR扩展,从而破 41 + 坏测量系统,这将是一种烦人的拒绝服务攻击。然而,针对密封到信任测量中 42 + 的实体,有两类更严重的攻击。 43 + 44 + 1. 攻击者可以拦截来自系统的所有PCR扩展,并完全替换为自己的值,产生 45 + 一个未篡改状态的重现,这会使PCR测量证明状态是可信的,并释放密钥。 46 + 47 + 2. 攻击者可能会在某个时刻重置TPM,清除PCR,然后发送自己的测量,从而 48 + 有效地覆盖TPM已经完成的启动时间测量。 49 + 50 + 第一种攻击可以通过始终对PCR扩展和读取命令进行HMAC保护来防止,这意味着 51 + 如果没有在响应中产生可检测的HMAC失败,则测量值无法被替换。然而第二种 52 + 攻击只能通过依赖某种机制来检测,这种机制会在TPM重置后发生变化。 53 + 54 + 秘密保护 55 + -------- 56 + 57 + 某些进出TPM的信息,如密钥密封、私钥导入和随机数生成容易被拦截,而仅仅 58 + 使用HMAC保护无法防止这种情况。因此,对于这些类型的命令,我们必须使用 59 + 请求和响应加密来防止秘密信息的泄露。 60 + 61 + 与TPM建立初始信任 62 + ----------------- 63 + 64 + 为了从一开始就提供安全性,必须建立一个初始的共享或非对称秘密,并且该 65 + 秘钥必须对攻击者不可知。最明显的途径是使用背书和存储种子,这些可以用 66 + 来派生非对称密钥。然而,使用这些密钥很困难,因为将它们传递给内核的唯 67 + 一方法是通过命令行,这需要在启动系统中进行广泛的支持,而且无法保证任 68 + 何一个层次不会有任何形式的授权。 69 + 70 + Linux内核选择的机制是从空种子使用标准的存储种子参数派生出主椭圆曲线 71 + 密钥。空种子有两个优势:首先该层次物理上无法具有授权,因此我们始终可 72 + 以使用它;其次空种子在TPM重置时会发生变化,这意味着如果我们在当天开始 73 + 时基于空种子建立信任,如果TPM重置且种子变化,则所有派生的密钥进行加盐 74 + 处理的会话都将失败。 75 + 76 + 显然,在没有任何其他共享秘密的情况下使用空种子,我们必须创建并读取初始 77 + 公钥,这当然可能会被总线中间人拦截并替换。然而,TPM有一个密钥认证机制 78 + (使用EK背书证书,创建认证身份密钥,并用该密钥认证空种子主密钥),但由 79 + 于它过于复杂,无法在内核中运行,因此我们保留空主密钥名称的副本,通过 80 + sysfs导出,以便用户空间在启动时进行完整的认证。这里的明确保证是,如果空 81 + 主密钥认证成功,那么从当天开始的所有TPM交易都是安全的;如果认证失败,则 82 + 说明系统上有中间人(并且任何在启动期间使用的秘密可能已被泄露)。 83 + 84 + 信任堆叠 85 + -------- 86 + 87 + 在当前的空主密钥场景中,TPM必须在交给下一个使用者之前完全清除。然而, 88 + 内核将派生出的空种子密钥的名称传递给用户空间,用户空间可以通过认证来 89 + 验证该名称。因此,这种名称传递链也可以用于各个启动组件之间(通过未指 90 + 定的机制)。例如grub可以使用空种子方案来实现安全性,并将名称交给内核。 91 + 内核可以派生出密钥和名称,并确定如果它们与交接的版本不同,则表示发生 92 + 了篡改。因此可以通过名称传递将任意启动组件(从UEFI到grub到内核)串联 93 + 起来,只要每个后续组件知道如何收集该名称,并根据其派生的密钥进行验证。 94 + 95 + 会话属性 96 + -------- 97 + 98 + 所有内核使用的TPM命令都允许会话。HMAC会话可用于检查请求和响应的完整性, 99 + 而解密和加密标志可用于保护参数和响应。HMAC和加密密钥通常是从共享授权秘 100 + 钥推导出来的,但对于许多内核操作来说,这些密钥是已知的(通常为空)。因 101 + 此内核使用空主密钥作为盐密钥来创建每个HMAC会话,这样就为会话密钥的派生 102 + 提供了加密输入。因此内核仅需创建一次空主密钥(作为一个易失的TPM句柄), 103 + 并将其保存在tpm_chip中,用于每次在内核中使用TPM时。由于内核资源管理器缺 104 + 乏去间隙化,当前每次操作都需要创建和销毁会话,但未来可能会将单个会话重用 105 + 用于内核中的HMAC、加密和解密会话。 106 + 107 + 保护类型 108 + -------- 109 + 110 + 对于每个内核操作,我们使用空主密钥加盐的HMAC来保护完整性。此外我们使用参数 111 + 加密来保护密钥密封,并使用参数解密来保护密钥解封和随机数生成。 112 + 113 + 空主密钥认证在用户空间的实现 114 + ============================ 115 + 116 + 每个TPM都会附带几个X.509证书,通常用于主背书密钥。本文档假设存在椭圆曲线 117 + 版本的证书,位于01C00002,但也同样适用于RSA证书(位于01C00001)。 118 + 119 + 认证的第一步是使用 `TCG EK Credential Profile`_ 模板进行主密钥的创建,该 120 + 模板允许将生成的主密钥与证书中的主密钥进行比较(公钥必须匹配)。需要注意 121 + 的是,生成EK主密钥需要EK层级密码,但EC主密钥的预生成版本应位于81010002, 122 + 并且可以无需密钥授权对其执行TPM2_ReadPublic()操作。接下来,证书本身必须 123 + 经过验证,以确保其可以追溯到制造商根证书(该根证书应公开在制造商网站上)。 124 + 完成此步骤后将在TPM内部生成一个认证密钥(AK),并使用TPM2_MakeCredential、 125 + AK的名称和EK公钥加密一个秘密。然后TPM执行TPM2_ActivateCredential,只有在 126 + TPM、EK和AK之间的绑定关系成立时,才能恢复秘密。现在,生成的AK可以用于对由 127 + 内核导出的空主密钥进行认证。由于TPM2_MakeCredential/ActivateCredential操作 128 + 相对复杂,下面将描述一种涉及外部生成私钥的简化过程。 129 + 130 + 这个过程是通常基于隐私CA认证过程的简化缩写。假设此时认证由TPM所有者进行, 131 + 所有者只能访问所有者层次。所有者创建一个外部公/私钥对(假设是椭圆曲线), 132 + 并使用内部包装过程将私钥进行封装以便导入,该私钥被其父级由EC派生的存储主密 133 + 钥保护。TPM2_Import()操作使用一个以EK主密钥为盐值的参数解密HMAC会话(这也不 134 + 需要EK密钥授权),意味着内部封装密钥是加密参数,因此除非TPM拥有认证的EK,否 135 + 则无法执行导入操作。如果该命令成功执行并且HMAC在返回时通过验证,我们就知道 136 + 我们有一个只为认证TPM加载的私钥副本。现在该密钥已加载到TPM中,并且存储主密 137 + 钥已被清除(以释放空间用于生成空密钥)。 138 + 139 + 现在根据 `TCG TPM v2.0 Provisioning Guidance`_ 中的存储配置生成空EC主密钥; 140 + 该密钥的名称(即公钥区域的哈希值)被计算出来并与内核在/sys/class/tpm/tpm0/null_name 141 + 中提供的空种子名称进行比较。如果名称不匹配,TPM就被认为是受损的。如果名称匹配, 142 + 用户执行TPM2_Certify(),使用空主密钥作为对象句柄,使用加载的私钥作为签名句柄, 143 + 并提供随机的合格数据。返回的certifyInfo的签名将与加载的私钥的公钥部分进行验证, 144 + 并检查合格数据以防止重放。如果所有测试都通过,用户就可以确信TPM的完整性和隐私 145 + 性在整个内核启动过程中得到了保护。 146 + 147 + .. _TPM Genie: https://www.nccgroup.trust/globalassets/about-us/us/documents/tpm-genie.pdf 148 + .. _Windows Bitlocker TPM: https://dolosgroup.io/blog/2021/7/9/from-stolen-laptop-to-inside-the-company-network 149 + .. _基于TPM的Linux磁盘加密: https://www.secura.com/blog/tpm-sniffing-attacks-against-non-bitlocker-targets 150 + .. _TCG EK Credential Profile: https://trustedcomputinggroup.org/resource/tcg-ek-credential-profile-for-tpm-family-2-0/ 151 + .. _TCG TPM v2.0 Provisioning Guidance: https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance/
+49
Documentation/translations/zh_CN/security/tpm/tpm_event_log.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: ../../disclaimer-zh_CN.rst 3 + 4 + :Original: Documentation/security/tpm/tpm_event_log.rst 5 + 6 + :翻译: 7 + 赵硕 Shuo Zhao <zhaoshuo@cqsoftware.com.cn> 8 + 9 + =========== 10 + TPM事件日志 11 + =========== 12 + 13 + 本文档简要介绍了什么是TPM日志,以及它是如何从预启动固件移交到操作系统的。 14 + 15 + 介绍 16 + ==== 17 + 18 + 预启动固件维护一个事件日志,每当它将某些内容哈希到任何一个PCR寄存器时,该 19 + 日志会添加新条目。这些事件按类型分类,并包含哈希后的PCR寄存器值。通常,预 20 + 启动固件会哈希那些即将移交执行权或与启动过程相关的组件。 21 + 22 + 其主要应用是远程认证,而它之所以有用的原因在[1]中第一部分很好地阐述了: 23 + 24 + 认证用于向挑战者提供有关平台状态的信息。然而,PCR的内容难以解读;因此,当 25 + PCR内容附有测量日志时,认证通常会更有用。尽管测量日志本身并不可信,但它们 26 + 包含比PCR内容更为丰富的信息集。PCR内容用于对测量日志进行验证。 27 + 28 + UEFI事件日志 29 + ============ 30 + 31 + UEFI提供的事件日志有一些比较奇怪的特性。 32 + 33 + 在调用ExitBootServices()之前,Linux EFI引导加载程序会将事件日志复制到由 34 + 引导加载程序自定义的配置表中。不幸的是,通过ExitBootServices()生成的事件 35 + 并不会出现在这个表里。 36 + 37 + 固件提供了一个所谓的最终事件配置表排序来解决这个问题。事件会在第一次调用 38 + EFI_TCG2_PROTOCOL.GetEventLog()后被镜像到这个表中。 39 + 40 + 这引出了另一个问题:无法保证它不会在 Linux EFI stub 开始运行之前被调用。 41 + 因此,在 stub 运行时,它需要计算并将最终事件表的大小保存到自定义配置表中, 42 + 以便TPM驱动程序可以在稍后连接来自自定义配置表和最终事件表的两个事件日志时 43 + 跳过这些事件。 44 + 45 + 参考文献 46 + ======== 47 + 48 + - [1] https://trustedcomputinggroup.org/resource/pc-client-specific-platform-firmware-profile-specification/ 49 + - [2] The final concatenation is done in drivers/char/tpm/eventlog/efi.c
+31
Documentation/translations/zh_CN/security/tpm/tpm_ftpm_tee.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: ../../disclaimer-zh_CN.rst 3 + 4 + :Original: Documentation/security/tpm/tpm_ftpm_tee.rst 5 + 6 + :翻译: 7 + 赵硕 Shuo Zhao <zhaoshuo@cqsoftware.com.cn> 8 + 9 + =========== 10 + 固件TPM驱动 11 + =========== 12 + 13 + 本文档描述了固件可信平台模块(fTPM)设备驱动。 14 + 15 + 介绍 16 + ==== 17 + 18 + 该驱动程序是用于ARM的TrustZone环境中实现的固件的适配器。该驱动 19 + 程序允许程序以与硬件TPM相同的方式与TPM进行交互。 20 + 21 + 设计 22 + ==== 23 + 24 + 该驱动程序充当一个薄层,传递命令到固件实现的TPM并接收其响应。驱动 25 + 程序本身并不包含太多逻辑,更像是固件与内核/用户空间之间的一个管道。 26 + 27 + 固件本身基于以下论文: 28 + https://www.microsoft.com/en-us/research/wp-content/uploads/2017/06/ftpm1.pdf 29 + 30 + 当驱动程序被加载时,它会向用户空间暴露 ``/dev/tpmX`` 字符设备,允许 31 + 用户空间通过该设备与固件TPM进行通信。
+43
Documentation/translations/zh_CN/security/tpm/tpm_tis.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: ../../disclaimer-zh_CN.rst 3 + 4 + :Original: Documentation/security/tpm/tpm_tis.rst 5 + 6 + :翻译: 7 + 赵硕 Shuo Zhao <zhaoshuo@cqsoftware.com.cn> 8 + 9 + TPM FIFO接口驱动 10 + ================ 11 + 12 + TCG PTP规范定义了两种接口类型:FIFO和CRB。前者基于顺序的读写操作, 13 + 后者基于包含完整命令或响应的缓冲区。 14 + 15 + FIFO(先进先出)接口被tpm_tis_core依赖的驱动程序使用。最初,Linux只 16 + 有一个名为tpm_tis的驱动,覆盖了内存映射(即 MMIO)接口,但后来它被 17 + 扩展以支持TCG标准所支持的其他物理接口。 18 + 19 + 由于历史原因,最初的MMIO驱动被称为tpm_tis,而FIFO驱动的框架被命名为 20 + tpm_tis_core。在tpm_tis中的“tis”后缀来自TPM接口规范,这是针对TPM1.x 21 + 芯片的硬件接口规范。 22 + 23 + 通信基于一个由TPM芯片通过硬件总线或内存映射共享的20KiB 缓冲区,具体 24 + 取决于物理接线。该缓冲区进一步分为五个相等大小的4KiB缓冲区,为CPU和 25 + TPM之间的通信提供等效的寄存器集。这些通信端点在TCG术语中称为localities。 26 + 27 + 当内核想要向TPM芯片发送命令时,它首先通过在TPM_ACCESS寄存器中设置 28 + requestUse位来保留locality0。当访问被授予时,该位由芯片清除。一旦完成 29 + 通信,内核会写入TPM_ACCESS.activeLocality位。这告诉芯片该本地性已被 30 + 释放。 31 + 32 + 待处理的本地性由芯片按优先级降序逐个服务,一次一个: 33 + 34 + - Locality0优先级最低。 35 + - Locality5优先级最高。 36 + 37 + 关于localities的更多信息和含义,请参阅TCG PC客户端平台TPM 配置文件规范的第3.2节。 38 + 39 + 参考文献 40 + ======== 41 + 42 + TCG PC客户端平台TPM配置文件(PTP)规范 43 + https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
+51
Documentation/translations/zh_CN/security/tpm/tpm_vtpm_proxy.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: ../../disclaimer-zh_CN.rst 3 + 4 + :Original: Documentation/security/tpm/tpm_vtpm_proxy.rst 5 + 6 + :翻译: 7 + 赵硕 Shuo Zhao <zhaoshuo@cqsoftware.com.cn> 8 + 9 + ========================== 10 + Linux容器的虚拟TPM代理驱动 11 + ========================== 12 + 13 + | 作者: 14 + | Stefan Berger <stefanb@linux.vnet.ibm.com> 15 + 16 + 本文档描述了用于Linux容器的虚拟可信平台模块(vTPM)代理设备驱动。 17 + 18 + 介绍 19 + ==== 20 + 21 + 这项工作的目标是为每个Linux容器提供TPM功能。这使得程序能够像与物理系统 22 + 上的TPM交互一样,与容器中的TPM进行交互。每个容器都会获得一个唯一的、模 23 + 拟的软件TPM。 24 + 25 + 设计 26 + ==== 27 + 28 + 为了使每个容器都能使用模拟的软件TPM,容器管理栈需要创建一对设备,其中 29 + 包括一个客户端TPM字符设备 ``/dev/tpmX`` (X=0,1,2...)和一个‘服务器端’ 30 + 文件描述符。当文件描述符传被递给TPM模拟器时,前者通过创建具有适当主次 31 + 设备号的字符设备被移入容器,然后,容器内的软件可以使用字符设备发送TPM 32 + 命令,模拟器将通过文件描述符接收这些命令,并用它来发送响应。 33 + 34 + 为了支持这一点,虚拟TPM代理驱动程序提供了一个设备 ``/dev/vtpmx`` ,该设备 35 + 用于通过ioctl创建设备对。ioctl将其作为配置设备的输入标志,例如这些标志指示 36 + TPM模拟器是否支持TPM1.2或TPM2功能。ioctl的结果是返回‘服务器端’的文件描述符 37 + 以及创建的字符设备的主次设备号。此外,还会返回TPM字符设备的编号。例如,如果 38 + 创建了 ``/dev/tpm10`` ,则返回编号( ``dev_num`` )10。 39 + 40 + 一旦设备被创建,驱动程序将立即尝试与TPM进行通信。来自驱动程序的所有命令 41 + 都可以从ioctl返回的文件描述符中读取。这些命令应该立即得到响应。 42 + 43 + UAPI 44 + ==== 45 + 46 + 该API在以下内核代码中: 47 + 48 + include/uapi/linux/vtpm_proxy.h 49 + drivers/char/tpm/tpm_vtpm_proxy.c 50 + 51 + 函数:vtpmx_ioc_new_dev
+114
Documentation/translations/zh_CN/security/tpm/xen-tpmfront.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. include:: ../../disclaimer-zh_CN.rst 3 + 4 + :Original: Documentation/security/tpm/xen-tpmfront.rst 5 + 6 + :翻译: 7 + 赵硕 Shuo Zhao <zhaoshuo@cqsoftware.com.cn> 8 + 9 + ================ 10 + Xen的虚拟TPM接口 11 + ================ 12 + 13 + 作者:Matthew Fioravante (JHUAPL), Daniel De Graaf (NSA) 14 + 15 + 本文档描述了用于Xen的虚拟可信平台模块(vTPM)子系统。假定读者熟悉 16 + Xen和Linux的构建和安装,并对TPM和vTPM概念有基本的理解。 17 + 18 + 介绍 19 + ---- 20 + 21 + 这项工作的目标是为虚拟客户操作系统(在Xen中称为DomU)提供TPM功能。这使得 22 + 程序能够像与物理系统上的TPM交互一样,与虚拟系统中的TPM进行交互。每个客户 23 + 操作系统都会获得一个唯一的、模拟的软件TPM。然而,vTPM的所有秘密(如密钥、 24 + NVRAM 等)由vTPM管理域进行管理,该域将这些秘密封存到物理TPM中。如果创建这 25 + 些域(管理域、vTPM域和客户域)的过程是可信的,vTPM子系统就能将根植于硬件 26 + TPM的信任链扩展到Xen中的虚拟机。vTPM的每个主要组件都作为一个独立的域实现, 27 + 从而通过虚拟机监控程序(hypervisor)提供安全隔离。 28 + 29 + 这个mini-os vTPM 子系统是建立在IBM和Intel公司之前的vTPM工作基础上的。 30 + 31 + 32 + 设计概述 33 + -------- 34 + 35 + vTPM的架构描述如下:: 36 + 37 + +------------------+ 38 + | Linux DomU | ... 39 + | | ^ | 40 + | v | | 41 + | xen-tpmfront | 42 + +------------------+ 43 + | ^ 44 + v | 45 + +------------------+ 46 + | mini-os/tpmback | 47 + | | ^ | 48 + | v | | 49 + | vtpm-stubdom | ... 50 + | | ^ | 51 + | v | | 52 + | mini-os/tpmfront | 53 + +------------------+ 54 + | ^ 55 + v | 56 + +------------------+ 57 + | mini-os/tpmback | 58 + | | ^ | 59 + | v | | 60 + | vtpmmgr-stubdom | 61 + | | ^ | 62 + | v | | 63 + | mini-os/tpm_tis | 64 + +------------------+ 65 + | ^ 66 + v | 67 + +------------------+ 68 + | Hardware TPM | 69 + +------------------+ 70 + 71 + * Linux DomU: 72 + 希望使用vTPM的基于Linux的客户机。可能有多个这样的实例。 73 + 74 + * xen-tpmfront.ko: 75 + Linux内核虚拟TPM前端驱动程序。该驱动程序为基于Linux的DomU提供 76 + vTPM访问。 77 + 78 + * mini-os/tpmback: 79 + Mini-os TPM后端驱动程序。Linux前端驱动程序通过该后端驱动程序连 80 + 接,以便在Linux DomU和其vTPM之间进行通信。该驱动程序还被 81 + vtpmmgr-stubdom用于与vtpm-stubdom通信。 82 + 83 + * vtpm-stubdom: 84 + 一个实现vTPM的mini-os存根域。每个正在运行的vtpm-stubdom实例与系统 85 + 上的逻辑vTPM之间有一一对应的关系。vTPM平台配置寄存器(PCRs)通常都 86 + 初始化为零。 87 + 88 + * mini-os/tpmfront: 89 + Mini-os TPM前端驱动程序。vTPM mini-os域vtpm-stubdom使用该驱动程序 90 + 与vtpmmgr-stubdom通信。此驱动程序还用于与vTPM域通信的mini-os域,例 91 + 如 pv-grub。 92 + 93 + * vtpmmgr-stubdom: 94 + 一个实现vTPM管理器的mini-os域。系统中只有一个vTPM管理器,并且在整个 95 + 机器生命周期内应一直运行。此域调节对系统中物理TPM的访问,并确保每个 96 + vTPM的持久状态。 97 + 98 + * mini-os/tpm_tis: 99 + Mini-osTPM1.2版本TPM 接口规范(TIS)驱动程序。该驱动程序由vtpmmgr-stubdom 100 + 用于直接与硬件TPM通信。通信通过将硬件内存页映射到vtpmmgr-stubdom来实现。 101 + 102 + * 硬件TPM: 103 + 固定在主板上的物理 TPM。 104 + 105 + 与Xen的集成 106 + ----------- 107 + 108 + vTPM驱动程序的支持已在Xen4.3中通过libxl工具堆栈添加。有关设置vTPM和vTPM 109 + 管理器存根域的详细信息,请参见Xen文档(docs/misc/vtpm.txt)。一旦存根域 110 + 运行,与磁盘或网络设备相同,vTPM设备将在域的配置文件中进行设置 111 + 112 + 为了使用诸如IMA(完整性测量架构)等需要在initrd之前加载TPM的功能,必须将 113 + xen-tpmfront驱动程序编译到内核中。如果不使用这些功能,驱动程序可以作为 114 + 模块编译,并像往常一样加载。
+1 -1
Documentation/translations/zh_TW/admin-guide/README.rst
··· 149 149 150 150 "make xconfig" 基於Qt的配置工具。 151 151 152 - "make gconfig" 基於GTK+的配置工具。 152 + "make gconfig" 基於GTK的配置工具。 153 153 154 154 "make oldconfig" 基於現有的 ./.config 文件選擇所有選項,並詢問 155 155 新配置選項。
+2 -2
Documentation/translations/zh_TW/process/submit-checklist.rst
··· 85 85 17) 所有新的模塊參數都記錄在 ``MODULE_PARM_DESC()`` 86 86 87 87 18) 所有新的用戶空間接口都記錄在 ``Documentation/ABI/`` 中。有關詳細信息, 88 - 請參閱 ``Documentation/ABI/README`` 。更改用戶空間接口的補丁應該抄送 89 - linux-api@vger.kernel.org。 88 + 請參閱 Documentation/admin-guide/abi.rst (或 ``Documentation/ABI/README``)。 89 + 更改用戶空間接口的補丁應該抄送 linux-api@vger.kernel.org\ 。 90 90 91 91 19) 已通過至少注入slab和page分配失敗進行檢查。請參閱 ``Documentation/fault-injection/`` 。 92 92 如果新代碼是實質性的,那麼添加子系統特定的故障注入可能是合適的。
+1 -1
Documentation/usb/gadget-testing.rst
··· 1050 1050 midi1_num_groups The number of groups for MIDI 1.0 (0-16) 1051 1051 ui_hint UI-hint of this FB 1052 1052 0: unknown, 1: receiver, 2: sender, 3: both 1053 - midi_ci_verison Supported MIDI-CI version number (8 bit) 1053 + midi_ci_version Supported MIDI-CI version number (8 bit) 1054 1054 is_midi1 Legacy MIDI 1.0 device (0-2) 1055 1055 0: MIDI 2.0 device, 1056 1056 1: MIDI 1.0 without restriction, or
+5 -2
Documentation/userspace-api/accelerators/ocxl.rst
··· 3 3 ======================================================== 4 4 5 5 OpenCAPI is an interface between processors and accelerators. It aims 6 - at being low-latency and high-bandwidth. The specification is 7 - developed by the `OpenCAPI Consortium <http://opencapi.org/>`_. 6 + at being low-latency and high-bandwidth. 7 + 8 + The specification was developed by the OpenCAPI Consortium, and is now 9 + available from the `Compute Express Link Consortium 10 + <https://computeexpresslink.org/resource/opencapi-specification-archive/>`_. 8 11 9 12 It allows an accelerator (which could be an FPGA, ASICs, ...) to access 10 13 the host memory coherently, using virtual addresses. An OpenCAPI
+25
Documentation/userspace-api/dma-buf-heaps.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ============================== 4 + Allocating dma-buf using heaps 5 + ============================== 6 + 7 + Dma-buf Heaps are a way for userspace to allocate dma-buf objects. They are 8 + typically used to allocate buffers from a specific allocation pool, or to share 9 + buffers across frameworks. 10 + 11 + Heaps 12 + ===== 13 + 14 + A heap represents a specific allocator. The Linux kernel currently supports the 15 + following heaps: 16 + 17 + - The ``system`` heap allocates virtually contiguous, cacheable, buffers. 18 + 19 + - The ``cma`` heap allocates physically contiguous, cacheable, 20 + buffers. Only present if a CMA region is present. Such a region is 21 + usually created either through the kernel commandline through the 22 + `cma` parameter, a memory region Device-Tree node with the 23 + `linux,cma-default` property set, or through the `CMA_SIZE_MBYTES` or 24 + `CMA_SIZE_PERCENTAGE` Kconfig options. Depending on the platform, it 25 + might be called ``reserved``, ``linux,cma``, or ``default-pool``.
+1
Documentation/userspace-api/index.rst
··· 44 44 :maxdepth: 1 45 45 46 46 accelerators/ocxl 47 + dma-buf-heaps 47 48 dma-buf-alloc-exchange 48 49 gpio/index 49 50 iommufd
+1 -1
Documentation/userspace-api/media/rc/rc-sysfs-nodes.rst
··· 6 6 Remote Controller's sysfs nodes 7 7 ******************************* 8 8 9 - As defined at ``Documentation/ABI/testing/sysfs-class-rc``, those are 9 + As defined at Documentation/ABI/testing/sysfs-class-rc, those are 10 10 the sysfs nodes that control the Remote Controllers: 11 11 12 12
+3
MAINTAINERS
··· 5402 5402 CHINESE DOCUMENTATION 5403 5403 M: Alex Shi <alexs@kernel.org> 5404 5404 M: Yanteng Si <siyanteng@loongson.cn> 5405 + R: Dongliang Mu <dzm91@hust.edu.cn> 5406 + T: git git://git.kernel.org/pub/scm/linux/kernel/git/alexs/linux.git 5405 5407 S: Maintained 5406 5408 F: Documentation/translations/zh_CN/ 5407 5409 ··· 6920 6918 L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers) 6921 6919 S: Maintained 6922 6920 T: git https://gitlab.freedesktop.org/drm/misc/kernel.git 6921 + F: Documentation/userspace-api/dma-buf-heaps.rst 6923 6922 F: drivers/dma-buf/dma-heap.c 6924 6923 F: drivers/dma-buf/heaps/* 6925 6924 F: include/linux/dma-heap.h
+2 -1
drivers/staging/media/ipu3/include/uapi/intel-ipu3.h
··· 322 322 * 0: positive, 1: negative, default 0. 323 323 * @y_calc: Pre-processing that converts Bayer quad to RGB+Y values to be 324 324 * used for building histogram. Range [0, 32], default 8. 325 - * Rule: 325 + * 326 + * Rule: 326 327 * y_gen_rate_gr + y_gen_rate_r + y_gen_rate_b + y_gen_rate_gb = 32 327 328 * A single Y is calculated based on sum of Gr/R/B/Gb based on 328 329 * their contribution ratio.
+3 -3
include/asm-generic/io.h
··· 1212 1212 1213 1213 #ifndef memset_io 1214 1214 /** 1215 - * memset_io Set a range of I/O memory to a constant value 1215 + * memset_io - Set a range of I/O memory to a constant value 1216 1216 * @addr: The beginning of the I/O-memory range to set 1217 1217 * @val: The value to set the memory to 1218 1218 * @count: The number of bytes to set ··· 1224 1224 1225 1225 #ifndef memcpy_fromio 1226 1226 /** 1227 - * memcpy_fromio Copy a block of data from I/O memory 1227 + * memcpy_fromio - Copy a block of data from I/O memory 1228 1228 * @dst: The (RAM) destination for the copy 1229 1229 * @src: The (I/O memory) source for the data 1230 1230 * @count: The number of bytes to copy ··· 1236 1236 1237 1237 #ifndef memcpy_toio 1238 1238 /** 1239 - * memcpy_toio Copy a block of data into I/O memory 1239 + * memcpy_toio - Copy a block of data into I/O memory 1240 1240 * @dst: The (I/O memory) destination for the copy 1241 1241 * @src: The (RAM) source for the data 1242 1242 * @count: The number of bytes to copy
+2 -1
include/uapi/linux/firewire-cdev.h
··· 449 449 * which the packet arrived. For %FW_CDEV_EVENT_PHY_PACKET_SENT2 and non-ping packet, 450 450 * the time stamp of isochronous cycle at which the packet was sent. For ping packet, 451 451 * the tick count for round-trip time measured by 1394 OHCI controller. 452 - * The time stamp of isochronous cycle at which either the response was sent for 452 + * 453 + * The time stamp of isochronous cycle at which either the response was sent for 453 454 * %FW_CDEV_EVENT_PHY_PACKET_SENT2 or the request arrived for 454 455 * %FW_CDEV_EVENT_PHY_PACKET_RECEIVED2. 455 456 * @data: Incoming data
+1 -1
scripts/documentation-file-ref-check
··· 92 92 next if ($f =~ m,^Next/,); 93 93 94 94 # Makefiles and scripts contain nasty expressions to parse docs 95 - next if ($f =~ m/Makefile/ || $f =~ m/\.sh$/); 95 + next if ($f =~ m/Makefile/ || $f =~ m/\.(sh|py|pl|~|rej|org|orig)$/); 96 96 97 97 # It doesn't make sense to parse hidden files 98 98 next if ($f =~ m#/\.#);
-1103
scripts/get_abi.pl
··· 1 - #!/usr/bin/env perl 2 - # SPDX-License-Identifier: GPL-2.0 3 - 4 - BEGIN { $Pod::Usage::Formatter = 'Pod::Text::Termcap'; } 5 - 6 - use strict; 7 - use warnings; 8 - use utf8; 9 - use Pod::Usage qw(pod2usage); 10 - use Getopt::Long; 11 - use File::Find; 12 - use IO::Handle; 13 - use Fcntl ':mode'; 14 - use Cwd 'abs_path'; 15 - use Data::Dumper; 16 - 17 - my $help = 0; 18 - my $hint = 0; 19 - my $man = 0; 20 - my $debug = 0; 21 - my $enable_lineno = 0; 22 - my $show_warnings = 1; 23 - my $prefix="Documentation/ABI"; 24 - my $sysfs_prefix="/sys"; 25 - my $search_string; 26 - 27 - # Debug options 28 - my $dbg_what_parsing = 1; 29 - my $dbg_what_open = 2; 30 - my $dbg_dump_abi_structs = 4; 31 - my $dbg_undefined = 8; 32 - 33 - $Data::Dumper::Indent = 1; 34 - $Data::Dumper::Terse = 1; 35 - 36 - # 37 - # If true, assumes that the description is formatted with ReST 38 - # 39 - my $description_is_rst = 1; 40 - 41 - GetOptions( 42 - "debug=i" => \$debug, 43 - "enable-lineno" => \$enable_lineno, 44 - "rst-source!" => \$description_is_rst, 45 - "dir=s" => \$prefix, 46 - 'help|?' => \$help, 47 - "show-hints" => \$hint, 48 - "search-string=s" => \$search_string, 49 - man => \$man 50 - ) or pod2usage(2); 51 - 52 - pod2usage(1) if $help; 53 - pod2usage(-exitstatus => 0, -noperldoc, -verbose => 2) if $man; 54 - 55 - pod2usage(2) if (scalar @ARGV < 1 || @ARGV > 2); 56 - 57 - my ($cmd, $arg) = @ARGV; 58 - 59 - pod2usage(2) if ($cmd ne "search" && $cmd ne "rest" && $cmd ne "validate" && $cmd ne "undefined"); 60 - pod2usage(2) if ($cmd eq "search" && !$arg); 61 - 62 - require Data::Dumper if ($debug & $dbg_dump_abi_structs); 63 - 64 - my %data; 65 - my %symbols; 66 - 67 - # 68 - # Displays an error message, printing file name and line 69 - # 70 - sub parse_error($$$$) { 71 - my ($file, $ln, $msg, $data) = @_; 72 - 73 - return if (!$show_warnings); 74 - 75 - $data =~ s/\s+$/\n/; 76 - 77 - print STDERR "Warning: file $file#$ln:\n\t$msg"; 78 - 79 - if ($data ne "") { 80 - print STDERR ". Line\n\t\t$data"; 81 - } else { 82 - print STDERR "\n"; 83 - } 84 - } 85 - 86 - # 87 - # Parse an ABI file, storing its contents at %data 88 - # 89 - sub parse_abi { 90 - my $file = $File::Find::name; 91 - 92 - my $mode = (stat($file))[2]; 93 - return if ($mode & S_IFDIR); 94 - return if ($file =~ m,/README,); 95 - return if ($file =~ m,/\.,); 96 - return if ($file =~ m,\.(rej|org|orig|bak)$,); 97 - 98 - my $name = $file; 99 - $name =~ s,.*/,,; 100 - 101 - my $fn = $file; 102 - $fn =~ s,.*Documentation/ABI/,,; 103 - 104 - my $nametag = "File $fn"; 105 - $data{$nametag}->{what} = "File $name"; 106 - $data{$nametag}->{type} = "File"; 107 - $data{$nametag}->{file} = $name; 108 - $data{$nametag}->{filepath} = $file; 109 - $data{$nametag}->{is_file} = 1; 110 - $data{$nametag}->{line_no} = 1; 111 - 112 - my $type = $file; 113 - $type =~ s,.*/(.*)/.*,$1,; 114 - 115 - my $what; 116 - my $new_what; 117 - my $tag = ""; 118 - my $ln; 119 - my $xrefs; 120 - my $space; 121 - my @labels; 122 - my $label = ""; 123 - 124 - print STDERR "Opening $file\n" if ($debug & $dbg_what_open); 125 - open IN, $file; 126 - while(<IN>) { 127 - $ln++; 128 - if (m/^(\S+)(:\s*)(.*)/i) { 129 - my $new_tag = lc($1); 130 - my $sep = $2; 131 - my $content = $3; 132 - 133 - if (!($new_tag =~ m/(what|where|date|kernelversion|contact|description|users)/)) { 134 - if ($tag eq "description") { 135 - # New "tag" is actually part of 136 - # description. Don't consider it a tag 137 - $new_tag = ""; 138 - } elsif ($tag ne "") { 139 - parse_error($file, $ln, "tag '$tag' is invalid", $_); 140 - } 141 - } 142 - 143 - # Invalid, but it is a common mistake 144 - if ($new_tag eq "where") { 145 - parse_error($file, $ln, "tag 'Where' is invalid. Should be 'What:' instead", ""); 146 - $new_tag = "what"; 147 - } 148 - 149 - if ($new_tag =~ m/what/) { 150 - $space = ""; 151 - $content =~ s/[,.;]$//; 152 - 153 - push @{$symbols{$content}->{file}}, " $file:" . ($ln - 1); 154 - 155 - if ($tag =~ m/what/) { 156 - $what .= "\xac" . $content; 157 - } else { 158 - if ($what) { 159 - parse_error($file, $ln, "What '$what' doesn't have a description", "") if (!$data{$what}->{description}); 160 - 161 - foreach my $w(split /\xac/, $what) { 162 - $symbols{$w}->{xref} = $what; 163 - }; 164 - } 165 - 166 - $what = $content; 167 - $label = $content; 168 - $new_what = 1; 169 - } 170 - push @labels, [($content, $label)]; 171 - $tag = $new_tag; 172 - 173 - push @{$data{$nametag}->{symbols}}, $content if ($data{$nametag}->{what}); 174 - next; 175 - } 176 - 177 - if ($tag ne "" && $new_tag) { 178 - $tag = $new_tag; 179 - 180 - if ($new_what) { 181 - @{$data{$what}->{label_list}} = @labels if ($data{$nametag}->{what}); 182 - @labels = (); 183 - $label = ""; 184 - $new_what = 0; 185 - 186 - $data{$what}->{type} = $type; 187 - if (!defined($data{$what}->{file})) { 188 - $data{$what}->{file} = $name; 189 - $data{$what}->{filepath} = $file; 190 - } else { 191 - $data{$what}->{description} .= "\n\n" if (defined($data{$what}->{description})); 192 - if ($name ne $data{$what}->{file}) { 193 - $data{$what}->{file} .= " " . $name; 194 - $data{$what}->{filepath} .= " " . $file; 195 - } 196 - } 197 - print STDERR "\twhat: $what\n" if ($debug & $dbg_what_parsing); 198 - $data{$what}->{line_no} = $ln; 199 - } else { 200 - $data{$what}->{line_no} = $ln if (!defined($data{$what}->{line_no})); 201 - } 202 - 203 - if (!$what) { 204 - parse_error($file, $ln, "'What:' should come first:", $_); 205 - next; 206 - } 207 - if ($new_tag eq "description") { 208 - $sep =~ s,:, ,; 209 - $content = ' ' x length($new_tag) . $sep . $content; 210 - while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} 211 - if ($content =~ m/^(\s*)(\S.*)$/) { 212 - # Preserve initial spaces for the first line 213 - $space = $1; 214 - $content = "$2\n"; 215 - $data{$what}->{$tag} .= $content; 216 - } else { 217 - undef($space); 218 - } 219 - 220 - } else { 221 - $data{$what}->{$tag} = $content; 222 - } 223 - next; 224 - } 225 - } 226 - 227 - # Store any contents before tags at the database 228 - if (!$tag && $data{$nametag}->{what}) { 229 - $data{$nametag}->{description} .= $_; 230 - next; 231 - } 232 - 233 - if ($tag eq "description") { 234 - my $content = $_; 235 - while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} 236 - if (m/^\s*\n/) { 237 - $data{$what}->{$tag} .= "\n"; 238 - next; 239 - } 240 - 241 - if (!defined($space)) { 242 - # Preserve initial spaces for the first line 243 - if ($content =~ m/^(\s*)(\S.*)$/) { 244 - $space = $1; 245 - $content = "$2\n"; 246 - } 247 - } else { 248 - $space = "" if (!($content =~ s/^($space)//)); 249 - } 250 - $data{$what}->{$tag} .= $content; 251 - 252 - next; 253 - } 254 - if (m/^\s*(.*)/) { 255 - $data{$what}->{$tag} .= "\n$1"; 256 - $data{$what}->{$tag} =~ s/\n+$//; 257 - next; 258 - } 259 - 260 - # Everything else is error 261 - parse_error($file, $ln, "Unexpected content", $_); 262 - } 263 - $data{$nametag}->{description} =~ s/^\n+// if ($data{$nametag}->{description}); 264 - if ($what) { 265 - parse_error($file, $ln, "What '$what' doesn't have a description", "") if (!$data{$what}->{description}); 266 - 267 - foreach my $w(split /\xac/,$what) { 268 - $symbols{$w}->{xref} = $what; 269 - }; 270 - } 271 - close IN; 272 - } 273 - 274 - sub create_labels { 275 - my %labels; 276 - 277 - foreach my $what (keys %data) { 278 - next if ($data{$what}->{file} eq "File"); 279 - 280 - foreach my $p (@{$data{$what}->{label_list}}) { 281 - my ($content, $label) = @{$p}; 282 - $label = "abi_" . $label . " "; 283 - $label =~ tr/A-Z/a-z/; 284 - 285 - # Convert special chars to "_" 286 - $label =~s/([\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xff])/_/g; 287 - $label =~ s,_+,_,g; 288 - $label =~ s,_$,,; 289 - 290 - # Avoid duplicated labels 291 - while (defined($labels{$label})) { 292 - my @chars = ("A".."Z", "a".."z"); 293 - $label .= $chars[rand @chars]; 294 - } 295 - $labels{$label} = 1; 296 - 297 - $data{$what}->{label} = $label; 298 - 299 - # only one label is enough 300 - last; 301 - } 302 - } 303 - } 304 - 305 - # 306 - # Outputs the book on ReST format 307 - # 308 - 309 - # \b doesn't work well with paths. So, we need to define something else: 310 - # Boundaries are punct characters, spaces and end-of-line 311 - my $start = qr {(^|\s|\() }x; 312 - my $bondary = qr { ([,.:;\)\s]|\z) }x; 313 - my $xref_match = qr { $start(\/(sys|config|proc|dev|kvd)\/[^,.:;\)\s]+)$bondary }x; 314 - my $symbols = qr { ([\x01-\x08\x0e-\x1f\x21-\x2f\x3a-\x40\x7b-\xff]) }x; 315 - 316 - sub output_rest { 317 - create_labels(); 318 - 319 - my $part = ""; 320 - 321 - foreach my $what (sort { 322 - ($data{$a}->{type} eq "File") cmp ($data{$b}->{type} eq "File") || 323 - $a cmp $b 324 - } keys %data) { 325 - my $type = $data{$what}->{type}; 326 - 327 - my @file = split / /, $data{$what}->{file}; 328 - my @filepath = split / /, $data{$what}->{filepath}; 329 - 330 - if ($enable_lineno) { 331 - printf ".. LINENO %s%s#%s\n\n", 332 - $prefix, $file[0], 333 - $data{$what}->{line_no}; 334 - } 335 - 336 - my $w = $what; 337 - 338 - if ($type ne "File") { 339 - my $cur_part = $what; 340 - if ($what =~ '/') { 341 - if ($what =~ m#^(\/?(?:[\w\-]+\/?){1,2})#) { 342 - $cur_part = "Symbols under $1"; 343 - $cur_part =~ s,/$,,; 344 - } 345 - } 346 - 347 - if ($cur_part ne "" && $part ne $cur_part) { 348 - $part = $cur_part; 349 - my $bar = $part; 350 - $bar =~ s/./-/g; 351 - print "$part\n$bar\n\n"; 352 - } 353 - 354 - printf ".. _%s:\n\n", $data{$what}->{label}; 355 - 356 - my @names = split /\xac/,$w; 357 - my $len = 0; 358 - 359 - foreach my $name (@names) { 360 - $name =~ s/$symbols/\\$1/g; 361 - $name = "**$name**"; 362 - $len = length($name) if (length($name) > $len); 363 - } 364 - 365 - print "+-" . "-" x $len . "-+\n"; 366 - foreach my $name (@names) { 367 - printf "| %s", $name . " " x ($len - length($name)) . " |\n"; 368 - print "+-" . "-" x $len . "-+\n"; 369 - } 370 - 371 - print "\n"; 372 - } 373 - 374 - for (my $i = 0; $i < scalar(@filepath); $i++) { 375 - my $path = $filepath[$i]; 376 - my $f = $file[$i]; 377 - 378 - $path =~ s,.*/(.*/.*),$1,;; 379 - $path =~ s,[/\-],_,g;; 380 - my $fileref = "abi_file_".$path; 381 - 382 - if ($type eq "File") { 383 - print ".. _$fileref:\n\n"; 384 - } else { 385 - print "Defined on file :ref:`$f <$fileref>`\n\n"; 386 - } 387 - } 388 - 389 - if ($type eq "File") { 390 - my $bar = $w; 391 - $bar =~ s/./-/g; 392 - print "$w\n$bar\n\n"; 393 - } 394 - 395 - my $desc = ""; 396 - $desc = $data{$what}->{description} if (defined($data{$what}->{description})); 397 - $desc =~ s/\s+$/\n/; 398 - 399 - if (!($desc =~ /^\s*$/)) { 400 - if ($description_is_rst) { 401 - # Remove title markups from the description 402 - # Having titles inside ABI files will only work if extra 403 - # care would be taken in order to strictly follow the same 404 - # level order for each markup. 405 - $desc =~ s/\n[\-\*\=\^\~]+\n/\n\n/g; 406 - 407 - # Enrich text by creating cross-references 408 - 409 - my $new_desc = ""; 410 - my $init_indent = -1; 411 - my $literal_indent = -1; 412 - 413 - open(my $fh, "+<", \$desc); 414 - while (my $d = <$fh>) { 415 - my $indent = $d =~ m/^(\s+)/; 416 - my $spaces = length($indent); 417 - $init_indent = $indent if ($init_indent < 0); 418 - if ($literal_indent >= 0) { 419 - if ($spaces > $literal_indent) { 420 - $new_desc .= $d; 421 - next; 422 - } else { 423 - $literal_indent = -1; 424 - } 425 - } else { 426 - if ($d =~ /()::$/ && !($d =~ /^\s*\.\./)) { 427 - $literal_indent = $spaces; 428 - } 429 - } 430 - 431 - $d =~ s,Documentation/(?!devicetree)(\S+)\.rst,:doc:`/$1`,g; 432 - 433 - my @matches = $d =~ m,Documentation/ABI/([\w\/\-]+),g; 434 - foreach my $f (@matches) { 435 - my $xref = $f; 436 - my $path = $f; 437 - $path =~ s,.*/(.*/.*),$1,;; 438 - $path =~ s,[/\-],_,g;; 439 - $xref .= " <abi_file_" . $path . ">"; 440 - $d =~ s,\bDocumentation/ABI/$f\b,:ref:`$xref`,g; 441 - } 442 - 443 - # Seek for cross reference symbols like /sys/... 444 - @matches = $d =~ m/$xref_match/g; 445 - 446 - foreach my $s (@matches) { 447 - next if (!($s =~ m,/,)); 448 - if (defined($data{$s}) && defined($data{$s}->{label})) { 449 - my $xref = $s; 450 - 451 - $xref =~ s/$symbols/\\$1/g; 452 - $xref = ":ref:`$xref <" . $data{$s}->{label} . ">`"; 453 - 454 - $d =~ s,$start$s$bondary,$1$xref$2,g; 455 - } 456 - } 457 - $new_desc .= $d; 458 - } 459 - close $fh; 460 - 461 - 462 - print "$new_desc\n\n"; 463 - } else { 464 - $desc =~ s/^\s+//; 465 - 466 - # Remove title markups from the description, as they won't work 467 - $desc =~ s/\n[\-\*\=\^\~]+\n/\n\n/g; 468 - 469 - if ($desc =~ m/\:\n/ || $desc =~ m/\n[\t ]+/ || $desc =~ m/[\x00-\x08\x0b-\x1f\x7b-\xff]/) { 470 - # put everything inside a code block 471 - $desc =~ s/\n/\n /g; 472 - 473 - print "::\n\n"; 474 - print " $desc\n\n"; 475 - } else { 476 - # Escape any special chars from description 477 - $desc =~s/([\x00-\x08\x0b-\x1f\x21-\x2a\x2d\x2f\x3c-\x40\x5c\x5e-\x60\x7b-\xff])/\\$1/g; 478 - print "$desc\n\n"; 479 - } 480 - } 481 - } else { 482 - print "DESCRIPTION MISSING for $what\n\n" if (!$data{$what}->{is_file}); 483 - } 484 - 485 - if ($data{$what}->{symbols}) { 486 - printf "Has the following ABI:\n\n"; 487 - 488 - foreach my $content(@{$data{$what}->{symbols}}) { 489 - my $label = $data{$symbols{$content}->{xref}}->{label}; 490 - 491 - # Escape special chars from content 492 - $content =~s/([\x00-\x1f\x21-\x2f\x3a-\x40\x7b-\xff])/\\$1/g; 493 - 494 - print "- :ref:`$content <$label>`\n\n"; 495 - } 496 - } 497 - 498 - if (defined($data{$what}->{users})) { 499 - my $users = $data{$what}->{users}; 500 - 501 - $users =~ s/\n/\n\t/g; 502 - printf "Users:\n\t%s\n\n", $users if ($users ne ""); 503 - } 504 - 505 - } 506 - } 507 - 508 - # 509 - # Searches for ABI symbols 510 - # 511 - sub search_symbols { 512 - foreach my $what (sort keys %data) { 513 - next if (!($what =~ m/($arg)/)); 514 - 515 - my $type = $data{$what}->{type}; 516 - next if ($type eq "File"); 517 - 518 - my $file = $data{$what}->{filepath}; 519 - 520 - $what =~ s/\xac/, /g; 521 - my $bar = $what; 522 - $bar =~ s/./-/g; 523 - 524 - print "\n$what\n$bar\n\n"; 525 - 526 - my $kernelversion = $data{$what}->{kernelversion} if (defined($data{$what}->{kernelversion})); 527 - my $contact = $data{$what}->{contact} if (defined($data{$what}->{contact})); 528 - my $users = $data{$what}->{users} if (defined($data{$what}->{users})); 529 - my $date = $data{$what}->{date} if (defined($data{$what}->{date})); 530 - my $desc = $data{$what}->{description} if (defined($data{$what}->{description})); 531 - 532 - $kernelversion =~ s/^\s+// if ($kernelversion); 533 - $contact =~ s/^\s+// if ($contact); 534 - if ($users) { 535 - $users =~ s/^\s+//; 536 - $users =~ s/\n//g; 537 - } 538 - $date =~ s/^\s+// if ($date); 539 - $desc =~ s/^\s+// if ($desc); 540 - 541 - printf "Kernel version:\t\t%s\n", $kernelversion if ($kernelversion); 542 - printf "Date:\t\t\t%s\n", $date if ($date); 543 - printf "Contact:\t\t%s\n", $contact if ($contact); 544 - printf "Users:\t\t\t%s\n", $users if ($users); 545 - print "Defined on file(s):\t$file\n\n"; 546 - print "Description:\n\n$desc"; 547 - } 548 - } 549 - 550 - # Exclude /sys/kernel/debug and /sys/kernel/tracing from the search path 551 - sub dont_parse_special_attributes { 552 - if (($File::Find::dir =~ m,^/sys/kernel,)) { 553 - return grep {!/(debug|tracing)/ } @_; 554 - } 555 - 556 - if (($File::Find::dir =~ m,^/sys/fs,)) { 557 - return grep {!/(pstore|bpf|fuse)/ } @_; 558 - } 559 - 560 - return @_ 561 - } 562 - 563 - my %leaf; 564 - my %aliases; 565 - my @files; 566 - my %root; 567 - 568 - sub graph_add_file { 569 - my $file = shift; 570 - my $type = shift; 571 - 572 - my $dir = $file; 573 - $dir =~ s,^(.*/).*,$1,; 574 - $file =~ s,.*/,,; 575 - 576 - my $name; 577 - my $file_ref = \%root; 578 - foreach my $edge(split "/", $dir) { 579 - $name .= "$edge/"; 580 - if (!defined ${$file_ref}{$edge}) { 581 - ${$file_ref}{$edge} = { }; 582 - } 583 - $file_ref = \%{$$file_ref{$edge}}; 584 - ${$file_ref}{"__name"} = [ $name ]; 585 - } 586 - $name .= "$file"; 587 - ${$file_ref}{$file} = { 588 - "__name" => [ $name ] 589 - }; 590 - 591 - return \%{$$file_ref{$file}}; 592 - } 593 - 594 - sub graph_add_link { 595 - my $file = shift; 596 - my $link = shift; 597 - 598 - # Traverse graph to find the reference 599 - my $file_ref = \%root; 600 - foreach my $edge(split "/", $file) { 601 - $file_ref = \%{$$file_ref{$edge}} || die "Missing node!"; 602 - } 603 - 604 - # do a BFS 605 - 606 - my @queue; 607 - my %seen; 608 - my $st; 609 - 610 - push @queue, $file_ref; 611 - $seen{$start}++; 612 - 613 - while (@queue) { 614 - my $v = shift @queue; 615 - my @child = keys(%{$v}); 616 - 617 - foreach my $c(@child) { 618 - next if $seen{$$v{$c}}; 619 - next if ($c eq "__name"); 620 - 621 - if (!defined($$v{$c}{"__name"})) { 622 - printf STDERR "Error: Couldn't find a non-empty name on a children of $file/.*: "; 623 - print STDERR Dumper(%{$v}); 624 - exit; 625 - } 626 - 627 - # Add new name 628 - my $name = @{$$v{$c}{"__name"}}[0]; 629 - if ($name =~ s#^$file/#$link/#) { 630 - push @{$$v{$c}{"__name"}}, $name; 631 - } 632 - # Add child to the queue and mark as seen 633 - push @queue, $$v{$c}; 634 - $seen{$c}++; 635 - } 636 - } 637 - } 638 - 639 - my $escape_symbols = qr { ([\x01-\x08\x0e-\x1f\x21-\x29\x2b-\x2d\x3a-\x40\x7b-\xfe]) }x; 640 - sub parse_existing_sysfs { 641 - my $file = $File::Find::name; 642 - 643 - my $mode = (lstat($file))[2]; 644 - my $abs_file = abs_path($file); 645 - 646 - my @tmp; 647 - push @tmp, $file; 648 - push @tmp, $abs_file if ($abs_file ne $file); 649 - 650 - foreach my $f(@tmp) { 651 - # Ignore cgroup, as this is big and has zero docs under ABI 652 - return if ($f =~ m#^/sys/fs/cgroup/#); 653 - 654 - # Ignore firmware as it is documented elsewhere 655 - # Either ACPI or under Documentation/devicetree/bindings/ 656 - return if ($f =~ m#^/sys/firmware/#); 657 - 658 - # Ignore some sysfs nodes that aren't actually part of ABI 659 - return if ($f =~ m#/sections|notes/#); 660 - 661 - # Would need to check at 662 - # Documentation/admin-guide/kernel-parameters.txt, but this 663 - # is not easily parseable. 664 - return if ($f =~ m#/parameters/#); 665 - } 666 - 667 - if (S_ISLNK($mode)) { 668 - $aliases{$file} = $abs_file; 669 - return; 670 - } 671 - 672 - return if (S_ISDIR($mode)); 673 - 674 - # Trivial: file is defined exactly the same way at ABI What: 675 - return if (defined($data{$file})); 676 - return if (defined($data{$abs_file})); 677 - 678 - push @files, graph_add_file($abs_file, "file"); 679 - } 680 - 681 - sub get_leave($) 682 - { 683 - my $what = shift; 684 - my $leave; 685 - 686 - my $l = $what; 687 - my $stop = 1; 688 - 689 - $leave = $l; 690 - $leave =~ s,/$,,; 691 - $leave =~ s,.*/,,; 692 - $leave =~ s/[\(\)]//g; 693 - 694 - # $leave is used to improve search performance at 695 - # check_undefined_symbols, as the algorithm there can seek 696 - # for a small number of "what". It also allows giving a 697 - # hint about a leave with the same name somewhere else. 698 - # However, there are a few occurences where the leave is 699 - # either a wildcard or a number. Just group such cases 700 - # altogether. 701 - if ($leave =~ m/\.\*/ || $leave eq "" || $leave =~ /\\d/) { 702 - $leave = "others"; 703 - } 704 - 705 - return $leave; 706 - } 707 - 708 - my @not_found; 709 - 710 - sub check_file($$) 711 - { 712 - my $file_ref = shift; 713 - my $names_ref = shift; 714 - my @names = @{$names_ref}; 715 - my $file = $names[0]; 716 - 717 - my $found_string; 718 - 719 - my $leave = get_leave($file); 720 - if (!defined($leaf{$leave})) { 721 - $leave = "others"; 722 - } 723 - my @expr = @{$leaf{$leave}->{expr}}; 724 - die ("\rmissing rules for $leave") if (!defined($leaf{$leave})); 725 - 726 - my $path = $file; 727 - $path =~ s,(.*/).*,$1,; 728 - 729 - if ($search_string) { 730 - return if (!($file =~ m#$search_string#)); 731 - $found_string = 1; 732 - } 733 - 734 - for (my $i = 0; $i < @names; $i++) { 735 - if ($found_string && $hint) { 736 - if (!$i) { 737 - print STDERR "--> $names[$i]\n"; 738 - } else { 739 - print STDERR " $names[$i]\n"; 740 - } 741 - } 742 - foreach my $re (@expr) { 743 - print STDERR "$names[$i] =~ /^$re\$/\n" if ($debug && $dbg_undefined); 744 - if ($names[$i] =~ $re) { 745 - return; 746 - } 747 - } 748 - } 749 - 750 - if ($leave ne "others") { 751 - my @expr = @{$leaf{"others"}->{expr}}; 752 - for (my $i = 0; $i < @names; $i++) { 753 - foreach my $re (@expr) { 754 - print STDERR "$names[$i] =~ /^$re\$/\n" if ($debug && $dbg_undefined); 755 - if ($names[$i] =~ $re) { 756 - return; 757 - } 758 - } 759 - } 760 - } 761 - 762 - push @not_found, $file if (!$search_string || $found_string); 763 - 764 - if ($hint && (!$search_string || $found_string)) { 765 - my $what = $leaf{$leave}->{what}; 766 - $what =~ s/\xac/\n\t/g; 767 - if ($leave ne "others") { 768 - print STDERR "\r more likely regexes:\n\t$what\n"; 769 - } else { 770 - print STDERR "\r tested regexes:\n\t$what\n"; 771 - } 772 - } 773 - } 774 - 775 - sub check_undefined_symbols { 776 - my $num_files = scalar @files; 777 - my $next_i = 0; 778 - my $start_time = times; 779 - 780 - @files = sort @files; 781 - 782 - my $last_time = $start_time; 783 - 784 - # When either debug or hint is enabled, there's no sense showing 785 - # progress, as the progress will be overriden. 786 - if ($hint || ($debug && $dbg_undefined)) { 787 - $next_i = $num_files; 788 - } 789 - 790 - my $is_console; 791 - $is_console = 1 if (-t STDERR); 792 - 793 - for (my $i = 0; $i < $num_files; $i++) { 794 - my $file_ref = $files[$i]; 795 - my @names = @{$$file_ref{"__name"}}; 796 - 797 - check_file($file_ref, \@names); 798 - 799 - my $cur_time = times; 800 - 801 - if ($i == $next_i || $cur_time > $last_time + 1) { 802 - my $percent = $i * 100 / $num_files; 803 - 804 - my $tm = $cur_time - $start_time; 805 - my $time = sprintf "%d:%02d", int($tm), 60 * ($tm - int($tm)); 806 - 807 - printf STDERR "\33[2K\r", if ($is_console); 808 - printf STDERR "%s: processing sysfs files... %i%%: $names[0]", $time, $percent; 809 - printf STDERR "\n", if (!$is_console); 810 - STDERR->flush(); 811 - 812 - $next_i = int (($percent + 1) * $num_files / 100); 813 - $last_time = $cur_time; 814 - } 815 - } 816 - 817 - my $cur_time = times; 818 - my $tm = $cur_time - $start_time; 819 - my $time = sprintf "%d:%02d", int($tm), 60 * ($tm - int($tm)); 820 - 821 - printf STDERR "\33[2K\r", if ($is_console); 822 - printf STDERR "%s: processing sysfs files... done\n", $time; 823 - 824 - foreach my $file (@not_found) { 825 - print "$file not found.\n"; 826 - } 827 - } 828 - 829 - sub undefined_symbols { 830 - print STDERR "Reading $sysfs_prefix directory contents..."; 831 - find({ 832 - wanted =>\&parse_existing_sysfs, 833 - preprocess =>\&dont_parse_special_attributes, 834 - no_chdir => 1 835 - }, $sysfs_prefix); 836 - print STDERR "done.\n"; 837 - 838 - $leaf{"others"}->{what} = ""; 839 - 840 - print STDERR "Converting ABI What fields into regexes..."; 841 - foreach my $w (sort keys %data) { 842 - foreach my $what (split /\xac/,$w) { 843 - next if (!($what =~ m/^$sysfs_prefix/)); 844 - 845 - # Convert what into regular expressions 846 - 847 - # Escape dot characters 848 - $what =~ s/\./\xf6/g; 849 - 850 - # Temporarily change [0-9]+ type of patterns 851 - $what =~ s/\[0\-9\]\+/\xff/g; 852 - 853 - # Temporarily change [\d+-\d+] type of patterns 854 - $what =~ s/\[0\-\d+\]/\xff/g; 855 - $what =~ s/\[(\d+)\]/\xf4$1\xf5/g; 856 - 857 - # Temporarily change [0-9] type of patterns 858 - $what =~ s/\[(\d)\-(\d)\]/\xf4$1-$2\xf5/g; 859 - 860 - # Handle multiple option patterns 861 - $what =~ s/[\{\<\[]([\w_]+)(?:[,|]+([\w_]+)){1,}[\}\>\]]/($1|$2)/g; 862 - 863 - # Handle wildcards 864 - $what =~ s,\*,.*,g; 865 - $what =~ s,/\xf6..,/.*,g; 866 - $what =~ s/\<[^\>]+\>/.*/g; 867 - $what =~ s/\{[^\}]+\}/.*/g; 868 - $what =~ s/\[[^\]]+\]/.*/g; 869 - 870 - $what =~ s/[XYZ]/.*/g; 871 - 872 - # Recover [0-9] type of patterns 873 - $what =~ s/\xf4/[/g; 874 - $what =~ s/\xf5/]/g; 875 - 876 - # Remove duplicated spaces 877 - $what =~ s/\s+/ /g; 878 - 879 - # Special case: this ABI has a parenthesis on it 880 - $what =~ s/sqrt\(x^2\+y^2\+z^2\)/sqrt\(x^2\+y^2\+z^2\)/; 881 - 882 - # Special case: drop comparition as in: 883 - # What: foo = <something> 884 - # (this happens on a few IIO definitions) 885 - $what =~ s,\s*\=.*$,,; 886 - 887 - # Escape all other symbols 888 - $what =~ s/$escape_symbols/\\$1/g; 889 - $what =~ s/\\\\/\\/g; 890 - $what =~ s/\\([\[\]\(\)\|])/$1/g; 891 - $what =~ s/(\d+)\\(-\d+)/$1$2/g; 892 - 893 - $what =~ s/\xff/\\d+/g; 894 - 895 - # Special case: IIO ABI which a parenthesis. 896 - $what =~ s/sqrt(.*)/sqrt\(.*\)/; 897 - 898 - # Simplify regexes with multiple .* 899 - $what =~ s#(?:\.\*){2,}##g; 900 - # $what =~ s#\.\*/\.\*#.*#g; 901 - 902 - # Recover dot characters 903 - $what =~ s/\xf6/\./g; 904 - 905 - my $leave = get_leave($what); 906 - 907 - my $added = 0; 908 - foreach my $l (split /\|/, $leave) { 909 - if (defined($leaf{$l})) { 910 - next if ($leaf{$l}->{what} =~ m/\b$what\b/); 911 - $leaf{$l}->{what} .= "\xac" . $what; 912 - $added = 1; 913 - } else { 914 - $leaf{$l}->{what} = $what; 915 - $added = 1; 916 - } 917 - } 918 - if ($search_string && $added) { 919 - print STDERR "What: $what\n" if ($what =~ m#$search_string#); 920 - } 921 - 922 - } 923 - } 924 - # Compile regexes 925 - foreach my $l (sort keys %leaf) { 926 - my @expr; 927 - foreach my $w(sort split /\xac/, $leaf{$l}->{what}) { 928 - push @expr, qr /^$w$/; 929 - } 930 - $leaf{$l}->{expr} = \@expr; 931 - } 932 - 933 - # Take links into account 934 - foreach my $link (sort keys %aliases) { 935 - my $abs_file = $aliases{$link}; 936 - graph_add_link($abs_file, $link); 937 - } 938 - print STDERR "done.\n"; 939 - 940 - check_undefined_symbols; 941 - } 942 - 943 - # Ensure that the prefix will always end with a slash 944 - # While this is not needed for find, it makes the patch nicer 945 - # with --enable-lineno 946 - $prefix =~ s,/?$,/,; 947 - 948 - if ($cmd eq "undefined" || $cmd eq "search") { 949 - $show_warnings = 0; 950 - } 951 - # 952 - # Parses all ABI files located at $prefix dir 953 - # 954 - find({wanted =>\&parse_abi, no_chdir => 1}, $prefix); 955 - 956 - print STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug & $dbg_dump_abi_structs); 957 - 958 - # 959 - # Handles the command 960 - # 961 - if ($cmd eq "undefined") { 962 - undefined_symbols; 963 - } elsif ($cmd eq "search") { 964 - search_symbols; 965 - } else { 966 - if ($cmd eq "rest") { 967 - output_rest; 968 - } 969 - 970 - # Warn about duplicated ABI entries 971 - foreach my $what(sort keys %symbols) { 972 - my @files = @{$symbols{$what}->{file}}; 973 - 974 - next if (scalar(@files) == 1); 975 - 976 - printf STDERR "Warning: $what is defined %d times: @files\n", 977 - scalar(@files); 978 - } 979 - } 980 - 981 - __END__ 982 - 983 - =head1 NAME 984 - 985 - get_abi.pl - parse the Linux ABI files and produce a ReST book. 986 - 987 - =head1 SYNOPSIS 988 - 989 - B<get_abi.pl> [--debug <level>] [--enable-lineno] [--man] [--help] 990 - [--(no-)rst-source] [--dir=<dir>] [--show-hints] 991 - [--search-string <regex>] 992 - <COMMAND> [<ARGUMENT>] 993 - 994 - Where B<COMMAND> can be: 995 - 996 - =over 8 997 - 998 - B<search> I<SEARCH_REGEX> - search for I<SEARCH_REGEX> inside ABI 999 - 1000 - B<rest> - output the ABI in ReST markup language 1001 - 1002 - B<validate> - validate the ABI contents 1003 - 1004 - B<undefined> - existing symbols at the system that aren't 1005 - defined at Documentation/ABI 1006 - 1007 - =back 1008 - 1009 - =head1 OPTIONS 1010 - 1011 - =over 8 1012 - 1013 - =item B<--dir> 1014 - 1015 - Changes the location of the ABI search. By default, it uses 1016 - the Documentation/ABI directory. 1017 - 1018 - =item B<--rst-source> and B<--no-rst-source> 1019 - 1020 - The input file may be using ReST syntax or not. Those two options allow 1021 - selecting between a rst-compliant source ABI (B<--rst-source>), or a 1022 - plain text that may be violating ReST spec, so it requres some escaping 1023 - logic (B<--no-rst-source>). 1024 - 1025 - =item B<--enable-lineno> 1026 - 1027 - Enable output of .. LINENO lines. 1028 - 1029 - =item B<--debug> I<debug level> 1030 - 1031 - Print debug information according with the level, which is given by the 1032 - following bitmask: 1033 - 1034 - - 1: Debug parsing What entries from ABI files; 1035 - - 2: Shows what files are opened from ABI files; 1036 - - 4: Dump the structs used to store the contents of the ABI files. 1037 - 1038 - =item B<--show-hints> 1039 - 1040 - Show hints about possible definitions for the missing ABI symbols. 1041 - Used only when B<undefined>. 1042 - 1043 - =item B<--search-string> I<regex string> 1044 - 1045 - Show only occurences that match a search string. 1046 - Used only when B<undefined>. 1047 - 1048 - =item B<--help> 1049 - 1050 - Prints a brief help message and exits. 1051 - 1052 - =item B<--man> 1053 - 1054 - Prints the manual page and exits. 1055 - 1056 - =back 1057 - 1058 - =head1 DESCRIPTION 1059 - 1060 - Parse the Linux ABI files from ABI DIR (usually located at Documentation/ABI), 1061 - allowing to search for ABI symbols or to produce a ReST book containing 1062 - the Linux ABI documentation. 1063 - 1064 - =head1 EXAMPLES 1065 - 1066 - Search for all stable symbols with the word "usb": 1067 - 1068 - =over 8 1069 - 1070 - $ scripts/get_abi.pl search usb --dir Documentation/ABI/stable 1071 - 1072 - =back 1073 - 1074 - Search for all symbols that match the regex expression "usb.*cap": 1075 - 1076 - =over 8 1077 - 1078 - $ scripts/get_abi.pl search usb.*cap 1079 - 1080 - =back 1081 - 1082 - Output all obsoleted symbols in ReST format 1083 - 1084 - =over 8 1085 - 1086 - $ scripts/get_abi.pl rest --dir Documentation/ABI/obsolete 1087 - 1088 - =back 1089 - 1090 - =head1 BUGS 1091 - 1092 - Report bugs to Mauro Carvalho Chehab <mchehab+huawei@kernel.org> 1093 - 1094 - =head1 COPYRIGHT 1095 - 1096 - Copyright (c) 2016-2021 by Mauro Carvalho Chehab <mchehab+huawei@kernel.org>. 1097 - 1098 - License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>. 1099 - 1100 - This is free software: you are free to change and redistribute it. 1101 - There is NO WARRANTY, to the extent permitted by law. 1102 - 1103 - =cut
+214
scripts/get_abi.py
··· 1 + #!/usr/bin/env python3 2 + # pylint: disable=R0903 3 + # Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>. 4 + # SPDX-License-Identifier: GPL-2.0 5 + 6 + """ 7 + Parse ABI documentation and produce results from it. 8 + """ 9 + 10 + import argparse 11 + import logging 12 + import os 13 + import sys 14 + 15 + # Import Python modules 16 + 17 + LIB_DIR = "lib/abi" 18 + SRC_DIR = os.path.dirname(os.path.realpath(__file__)) 19 + 20 + sys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR)) 21 + 22 + from abi_parser import AbiParser # pylint: disable=C0413 23 + from abi_regex import AbiRegex # pylint: disable=C0413 24 + from helpers import ABI_DIR, DEBUG_HELP # pylint: disable=C0413 25 + from system_symbols import SystemSymbols # pylint: disable=C0413 26 + 27 + # Command line classes 28 + 29 + 30 + REST_DESC = """ 31 + Produce output in ReST format. 32 + 33 + The output is done on two sections: 34 + 35 + - Symbols: show all parsed symbols in alphabetic order; 36 + - Files: cross reference the content of each file with the symbols on it. 37 + """ 38 + 39 + class AbiRest: 40 + """Initialize an argparse subparser for rest output""" 41 + 42 + def __init__(self, subparsers): 43 + """Initialize argparse subparsers""" 44 + 45 + parser = subparsers.add_parser("rest", 46 + formatter_class=argparse.RawTextHelpFormatter, 47 + description=REST_DESC) 48 + 49 + parser.add_argument("--enable-lineno", action="store_true", 50 + help="enable lineno") 51 + parser.add_argument("--raw", action="store_true", 52 + help="output text as contained in the ABI files. " 53 + "It not used, output will contain dynamically" 54 + " generated cross references when possible.") 55 + parser.add_argument("--no-file", action="store_true", 56 + help="Don't the files section") 57 + parser.add_argument("--show-hints", help="Show-hints") 58 + 59 + parser.set_defaults(func=self.run) 60 + 61 + def run(self, args): 62 + """Run subparser""" 63 + 64 + parser = AbiParser(args.dir, debug=args.debug) 65 + parser.parse_abi() 66 + parser.check_issues() 67 + 68 + for t in parser.doc(args.raw, not args.no_file): 69 + if args.enable_lineno: 70 + print (f".. LINENO {t[1]}#{t[2]}\n\n") 71 + 72 + print(t[0]) 73 + 74 + class AbiValidate: 75 + """Initialize an argparse subparser for ABI validation""" 76 + 77 + def __init__(self, subparsers): 78 + """Initialize argparse subparsers""" 79 + 80 + parser = subparsers.add_parser("validate", 81 + formatter_class=argparse.ArgumentDefaultsHelpFormatter, 82 + description="list events") 83 + 84 + parser.set_defaults(func=self.run) 85 + 86 + def run(self, args): 87 + """Run subparser""" 88 + 89 + parser = AbiParser(args.dir, debug=args.debug) 90 + parser.parse_abi() 91 + parser.check_issues() 92 + 93 + 94 + class AbiSearch: 95 + """Initialize an argparse subparser for ABI search""" 96 + 97 + def __init__(self, subparsers): 98 + """Initialize argparse subparsers""" 99 + 100 + parser = subparsers.add_parser("search", 101 + formatter_class=argparse.ArgumentDefaultsHelpFormatter, 102 + description="Search ABI using a regular expression") 103 + 104 + parser.add_argument("expression", 105 + help="Case-insensitive search pattern for the ABI symbol") 106 + 107 + parser.set_defaults(func=self.run) 108 + 109 + def run(self, args): 110 + """Run subparser""" 111 + 112 + parser = AbiParser(args.dir, debug=args.debug) 113 + parser.parse_abi() 114 + parser.search_symbols(args.expression) 115 + 116 + UNDEFINED_DESC=""" 117 + Check undefined ABIs on local machine. 118 + 119 + Read sysfs devnodes and check if the devnodes there are defined inside 120 + ABI documentation. 121 + 122 + The search logic tries to minimize the number of regular expressions to 123 + search per each symbol. 124 + 125 + By default, it runs on a single CPU, as Python support for CPU threads 126 + is still experimental, and multi-process runs on Python is very slow. 127 + 128 + On experimental tests, if the number of ABI symbols to search per devnode 129 + is contained on a limit of ~150 regular expressions, using a single CPU 130 + is a lot faster than using multiple processes. However, if the number of 131 + regular expressions to check is at the order of ~30000, using multiple 132 + CPUs speeds up the check. 133 + """ 134 + 135 + class AbiUndefined: 136 + """ 137 + Initialize an argparse subparser for logic to check undefined ABI at 138 + the current machine's sysfs 139 + """ 140 + 141 + def __init__(self, subparsers): 142 + """Initialize argparse subparsers""" 143 + 144 + parser = subparsers.add_parser("undefined", 145 + formatter_class=argparse.RawTextHelpFormatter, 146 + description=UNDEFINED_DESC) 147 + 148 + parser.add_argument("-S", "--sysfs-dir", default="/sys", 149 + help="directory where sysfs is mounted") 150 + parser.add_argument("-s", "--search-string", 151 + help="search string regular expression to limit symbol search") 152 + parser.add_argument("-H", "--show-hints", action="store_true", 153 + help="Hints about definitions for missing ABI symbols.") 154 + parser.add_argument("-j", "--jobs", "--max-workers", type=int, default=1, 155 + help="If bigger than one, enables multiprocessing.") 156 + parser.add_argument("-c", "--max-chunk-size", type=int, default=50, 157 + help="Maximum number of chunk size") 158 + parser.add_argument("-f", "--found", action="store_true", 159 + help="Also show found items. " 160 + "Helpful to debug the parser."), 161 + parser.add_argument("-d", "--dry-run", action="store_true", 162 + help="Don't actually search for undefined. " 163 + "Helpful to debug the parser."), 164 + 165 + parser.set_defaults(func=self.run) 166 + 167 + def run(self, args): 168 + """Run subparser""" 169 + 170 + abi = AbiRegex(args.dir, debug=args.debug, 171 + search_string=args.search_string) 172 + 173 + abi_symbols = SystemSymbols(abi=abi, hints=args.show_hints, 174 + sysfs=args.sysfs_dir) 175 + 176 + abi_symbols.check_undefined_symbols(dry_run=args.dry_run, 177 + found=args.found, 178 + max_workers=args.jobs, 179 + chunk_size=args.max_chunk_size) 180 + 181 + 182 + def main(): 183 + """Main program""" 184 + 185 + parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) 186 + 187 + parser.add_argument("-d", "--debug", type=int, default=0, help="debug level") 188 + parser.add_argument("-D", "--dir", default=ABI_DIR, help=DEBUG_HELP) 189 + 190 + subparsers = parser.add_subparsers() 191 + 192 + AbiRest(subparsers) 193 + AbiValidate(subparsers) 194 + AbiSearch(subparsers) 195 + AbiUndefined(subparsers) 196 + 197 + args = parser.parse_args() 198 + 199 + if args.debug: 200 + level = logging.DEBUG 201 + else: 202 + level = logging.INFO 203 + 204 + logging.basicConfig(level=level, format="[%(levelname)s] %(message)s") 205 + 206 + if "func" in args: 207 + args.func(args) 208 + else: 209 + sys.exit(f"Please specify a valid command for {sys.argv[0]}") 210 + 211 + 212 + # Call main method 213 + if __name__ == "__main__": 214 + main()
+2 -2
scripts/get_feat.pl
··· 512 512 # Handles the command 513 513 # 514 514 if ($cmd eq "current") { 515 - $arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/'); 515 + $arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/' | sed 's/s390x/s390/'); 516 516 $arch =~s/\s+$//; 517 517 } 518 518 519 519 if ($cmd eq "ls" or $cmd eq "list") { 520 520 if (!$arch) { 521 - $arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/'); 521 + $arch = qx(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/' | sed 's/s390x/s390/'); 522 522 $arch =~s/\s+$//; 523 523 } 524 524
+21 -142
scripts/kernel-doc
··· 26 26 27 27 kernel-doc [-h] [-v] [-Werror] [-Wall] [-Wreturn] [-Wshort-desc[ription]] [-Wcontents-before-sections] 28 28 [ -man | 29 - -rst [-sphinx-version VERSION] [-enable-lineno] | 29 + -rst [-enable-lineno] | 30 30 -none 31 31 ] 32 32 [ ··· 130 130 } 131 131 132 132 my $kernelversion; 133 - my ($sphinx_major, $sphinx_minor, $sphinx_patch); 134 133 135 134 my $dohighlight = ""; 136 135 ··· 137 138 my $Werror = 0; 138 139 my $Wreturn = 0; 139 140 my $Wshort_desc = 0; 140 - my $Wcontents_before_sections = 0; 141 141 my $output_mode = "rst"; 142 142 my $output_preformatted = 0; 143 143 my $no_doc_sections = 0; ··· 177 179 my %nosymbol_table = (); 178 180 my $declaration_start_line; 179 181 my ($type, $declaration_name, $return_type); 180 - my ($newsection, $newcontents, $prototype, $brcount, %source_map); 182 + my ($newsection, $newcontents, $prototype, $brcount); 181 183 182 184 if (defined($ENV{'KBUILD_VERBOSE'}) && $ENV{'KBUILD_VERBOSE'} =~ '1') { 183 185 $verbose = 1; ··· 222 224 STATE_INLINE => 7, # gathering doc outside main block 223 225 }; 224 226 my $state; 225 - my $in_doc_sect; 226 227 my $leading_space; 227 228 228 229 # Inline documentation state ··· 330 333 $Wreturn = 1; 331 334 } elsif ($cmd eq "Wshort-desc" or $cmd eq "Wshort-description") { 332 335 $Wshort_desc = 1; 333 - } elsif ($cmd eq "Wcontents-before-sections") { 334 - $Wcontents_before_sections = 1; 335 336 } elsif ($cmd eq "Wall") { 336 337 $Wreturn = 1; 337 338 $Wshort_desc = 1; 338 - $Wcontents_before_sections = 1; 339 339 } elsif (($cmd eq "h") || ($cmd eq "help")) { 340 340 pod2usage(-exitval => 0, -verbose => 2); 341 341 } elsif ($cmd eq 'no-doc-sections') { ··· 341 347 $enable_lineno = 1; 342 348 } elsif ($cmd eq 'show-not-found') { 343 349 $show_not_found = 1; # A no-op but don't fail 344 - } elsif ($cmd eq "sphinx-version") { 345 - my $ver_string = shift @ARGV; 346 - if ($ver_string =~ m/^(\d+)(\.\d+)?(\.\d+)?/) { 347 - $sphinx_major = $1; 348 - if (defined($2)) { 349 - $sphinx_minor = substr($2,1); 350 - } else { 351 - $sphinx_minor = 0; 352 - } 353 - if (defined($3)) { 354 - $sphinx_patch = substr($3,1) 355 - } else { 356 - $sphinx_patch = 0; 357 - } 358 - } else { 359 - die "Sphinx version should either major.minor or major.minor.patch format\n"; 360 - } 361 350 } else { 362 351 # Unknown argument 363 352 pod2usage( ··· 364 387 365 388 # continue execution near EOF; 366 389 367 - # The C domain dialect changed on Sphinx 3. So, we need to check the 368 - # version in order to produce the right tags. 369 390 sub findprog($) 370 391 { 371 392 foreach(split(/:/, $ENV{PATH})) { 372 393 return "$_/$_[0]" if(-x "$_/$_[0]"); 373 394 } 374 - } 375 - 376 - sub get_sphinx_version() 377 - { 378 - my $ver; 379 - 380 - my $cmd = "sphinx-build"; 381 - if (!findprog($cmd)) { 382 - my $cmd = "sphinx-build3"; 383 - if (!findprog($cmd)) { 384 - $sphinx_major = 1; 385 - $sphinx_minor = 2; 386 - $sphinx_patch = 0; 387 - printf STDERR "Warning: Sphinx version not found. Using default (Sphinx version %d.%d.%d)\n", 388 - $sphinx_major, $sphinx_minor, $sphinx_patch; 389 - return; 390 - } 391 - } 392 - 393 - open IN, "$cmd --version 2>&1 |"; 394 - while (<IN>) { 395 - if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) { 396 - $sphinx_major = $1; 397 - $sphinx_minor = $2; 398 - $sphinx_patch = $3; 399 - last; 400 - } 401 - # Sphinx 1.2.x uses a different format 402 - if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) { 403 - $sphinx_major = $1; 404 - $sphinx_minor = $2; 405 - $sphinx_patch = $3; 406 - last; 407 - } 408 - } 409 - close IN; 410 395 } 411 396 412 397 # get kernel version from env ··· 755 816 if ($block) { 756 817 $output .= highlight_block($block); 757 818 } 819 + 820 + $output =~ s/^\n+//g; 821 + $output =~ s/\n+$//g; 822 + 758 823 foreach $line (split "\n", $output) { 759 824 print $lineprefix . $line . "\n"; 760 825 } ··· 802 859 $signature .= ")"; 803 860 } 804 861 805 - if ($sphinx_major < 3) { 862 + if ($args{'typedef'} || $args{'functiontype'} eq "") { 863 + print ".. c:macro:: ". $args{'function'} . "\n\n"; 864 + 806 865 if ($args{'typedef'}) { 807 - print ".. c:type:: ". $args{'function'} . "\n\n"; 808 866 print_lineno($declaration_start_line); 809 867 print " **Typedef**: "; 810 868 $lineprefix = ""; ··· 813 869 print "\n\n**Syntax**\n\n"; 814 870 print " ``$signature``\n\n"; 815 871 } else { 816 - print ".. c:function:: $signature\n\n"; 872 + print "``$signature``\n\n"; 817 873 } 818 874 } else { 819 - if ($args{'typedef'} || $args{'functiontype'} eq "") { 820 - print ".. c:macro:: ". $args{'function'} . "\n\n"; 821 - 822 - if ($args{'typedef'}) { 823 - print_lineno($declaration_start_line); 824 - print " **Typedef**: "; 825 - $lineprefix = ""; 826 - output_highlight_rst($args{'purpose'}); 827 - print "\n\n**Syntax**\n\n"; 828 - print " ``$signature``\n\n"; 829 - } else { 830 - print "``$signature``\n\n"; 831 - } 832 - } else { 833 - print ".. c:function:: $signature\n\n"; 834 - } 875 + print ".. c:function:: $signature\n\n"; 835 876 } 836 877 837 878 if (!$args{'typedef'}) { ··· 884 955 my $count; 885 956 my $outer; 886 957 887 - if ($sphinx_major < 3) { 888 - my $name = "enum " . $args{'enum'}; 889 - print "\n\n.. c:type:: " . $name . "\n\n"; 890 - } else { 891 - my $name = $args{'enum'}; 892 - print "\n\n.. c:enum:: " . $name . "\n\n"; 893 - } 958 + my $name = $args{'enum'}; 959 + print "\n\n.. c:enum:: " . $name . "\n\n"; 960 + 894 961 print_lineno($declaration_start_line); 895 962 $lineprefix = " "; 896 963 output_highlight_rst($args{'purpose'}); ··· 917 992 my $oldprefix = $lineprefix; 918 993 my $name; 919 994 920 - if ($sphinx_major < 3) { 921 - $name = "typedef " . $args{'typedef'}; 922 - } else { 923 - $name = $args{'typedef'}; 924 - } 995 + $name = $args{'typedef'}; 996 + 925 997 print "\n\n.. c:type:: " . $name . "\n\n"; 926 998 print_lineno($declaration_start_line); 927 999 $lineprefix = " "; ··· 934 1012 my ($parameter); 935 1013 my $oldprefix = $lineprefix; 936 1014 937 - if ($sphinx_major < 3) { 938 - my $name = $args{'type'} . " " . $args{'struct'}; 939 - print "\n\n.. c:type:: " . $name . "\n\n"; 1015 + my $name = $args{'struct'}; 1016 + if ($args{'type'} eq 'union') { 1017 + print "\n\n.. c:union:: " . $name . "\n\n"; 940 1018 } else { 941 - my $name = $args{'struct'}; 942 - if ($args{'type'} eq 'union') { 943 - print "\n\n.. c:union:: " . $name . "\n\n"; 944 - } else { 945 - print "\n\n.. c:struct:: " . $name . "\n\n"; 946 - } 1019 + print "\n\n.. c:struct:: " . $name . "\n\n"; 947 1020 } 1021 + 948 1022 print_lineno($declaration_start_line); 949 1023 $lineprefix = " "; 950 1024 output_highlight_rst($args{'purpose'}); ··· 1923 2005 $file = $orig_file; 1924 2006 } 1925 2007 1926 - if (defined($source_map{$file})) { 1927 - $file = $source_map{$file}; 1928 - } 1929 - 1930 2008 return $file; 1931 2009 } 1932 2010 ··· 1958 2044 sub process_normal() { 1959 2045 if (/$doc_start/o) { 1960 2046 $state = STATE_NAME; # next line is always the function name 1961 - $in_doc_sect = 0; 1962 2047 $declaration_start_line = $. + 1; 1963 2048 } 1964 2049 } ··· 2062 2149 } 2063 2150 2064 2151 if (/$doc_sect/i) { # case insensitive for supported section names 2065 - $in_doc_sect = 1; 2066 2152 $newsection = $1; 2067 2153 $newcontents = $2; 2068 2154 ··· 2078 2166 } 2079 2167 2080 2168 if (($contents ne "") && ($contents ne "\n")) { 2081 - if (!$in_doc_sect && $Wcontents_before_sections) { 2082 - emit_warning("${file}:$.", "contents before sections\n"); 2083 - } 2084 2169 dump_section($file, $section, $contents); 2085 2170 $section = $section_default; 2086 2171 } 2087 2172 2088 - $in_doc_sect = 1; 2089 2173 $state = STATE_BODY; 2090 2174 $contents = $newcontents; 2091 2175 $new_start_line = $.; ··· 2295 2387 close IN_FILE; 2296 2388 } 2297 2389 2298 - 2299 - if ($output_mode eq "rst") { 2300 - get_sphinx_version() if (!$sphinx_major); 2301 - } 2302 - 2303 2390 $kernelversion = get_kernel_version(); 2304 2391 2305 2392 # generate a sequence of code that will splice in highlighting information ··· 2304 2401 my $result = $highlights[$k][1]; 2305 2402 # print STDERR "scanning pattern:$pattern, highlight:($result)\n"; 2306 2403 $dohighlight .= "\$contents =~ s:$pattern:$result:gs;\n"; 2307 - } 2308 - 2309 - # Read the file that maps relative names to absolute names for 2310 - # separate source and object directories and for shadow trees. 2311 - if (open(SOURCE_MAP, "<.tmp_filelist.txt")) { 2312 - my ($relname, $absname); 2313 - while(<SOURCE_MAP>) { 2314 - chop(); 2315 - ($relname, $absname) = (split())[0..1]; 2316 - $relname =~ s:^/+::; 2317 - $source_map{$relname} = $absname; 2318 - } 2319 - close(SOURCE_MAP); 2320 2404 } 2321 2405 2322 2406 if ($output_selection == OUTPUT_EXPORTED || ··· 2360 2470 =head2 Output format modifiers 2361 2471 2362 2472 =head3 reStructuredText only 2363 - 2364 - =over 8 2365 - 2366 - =item -sphinx-version VERSION 2367 - 2368 - Use the ReST C domain dialect compatible with a specific Sphinx Version. 2369 - 2370 - If not specified, kernel-doc will auto-detect using the sphinx-build version 2371 - found on PATH. 2372 - 2373 - =back 2374 2473 2375 2474 =head2 Output selection (mutually exclusive): 2376 2475
+628
scripts/lib/abi/abi_parser.py
··· 1 + #!/usr/bin/env python3 2 + # pylint: disable=R0902,R0903,R0911,R0912,R0913,R0914,R0915,R0917,C0302 3 + # Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>. 4 + # SPDX-License-Identifier: GPL-2.0 5 + 6 + """ 7 + Parse ABI documentation and produce results from it. 8 + """ 9 + 10 + from argparse import Namespace 11 + import logging 12 + import os 13 + import re 14 + 15 + from pprint import pformat 16 + from random import randrange, seed 17 + 18 + # Import Python modules 19 + 20 + from helpers import AbiDebug, ABI_DIR 21 + 22 + 23 + class AbiParser: 24 + """Main class to parse ABI files""" 25 + 26 + TAGS = r"(what|where|date|kernelversion|contact|description|users)" 27 + XREF = r"(?:^|\s|\()(\/(?:sys|config|proc|dev|kvd)\/[^,.:;\)\s]+)(?:[,.:;\)\s]|\Z)" 28 + 29 + def __init__(self, directory, logger=None, 30 + enable_lineno=False, show_warnings=True, debug=0): 31 + """Stores arguments for the class and initialize class vars""" 32 + 33 + self.directory = directory 34 + self.enable_lineno = enable_lineno 35 + self.show_warnings = show_warnings 36 + self.debug = debug 37 + 38 + if not logger: 39 + self.log = logging.getLogger("get_abi") 40 + else: 41 + self.log = logger 42 + 43 + self.data = {} 44 + self.what_symbols = {} 45 + self.file_refs = {} 46 + self.what_refs = {} 47 + 48 + # Ignore files that contain such suffixes 49 + self.ignore_suffixes = (".rej", ".org", ".orig", ".bak", "~") 50 + 51 + # Regular expressions used on parser 52 + self.re_abi_dir = re.compile(r"(.*)" + ABI_DIR) 53 + self.re_tag = re.compile(r"(\S+)(:\s*)(.*)", re.I) 54 + self.re_valid = re.compile(self.TAGS) 55 + self.re_start_spc = re.compile(r"(\s*)(\S.*)") 56 + self.re_whitespace = re.compile(r"^\s+") 57 + 58 + # Regular used on print 59 + self.re_what = re.compile(r"(\/?(?:[\w\-]+\/?){1,2})") 60 + self.re_escape = re.compile(r"([\.\x01-\x08\x0e-\x1f\x21-\x2f\x3a-\x40\x7b-\xff])") 61 + self.re_unprintable = re.compile(r"([\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xff]+)") 62 + self.re_title_mark = re.compile(r"\n[\-\*\=\^\~]+\n") 63 + self.re_doc = re.compile(r"Documentation/(?!devicetree)(\S+)\.rst") 64 + self.re_abi = re.compile(r"(Documentation/ABI/)([\w\/\-]+)") 65 + self.re_xref_node = re.compile(self.XREF) 66 + 67 + def warn(self, fdata, msg, extra=None): 68 + """Displays a parse error if warning is enabled""" 69 + 70 + if not self.show_warnings: 71 + return 72 + 73 + msg = f"{fdata.fname}:{fdata.ln}: {msg}" 74 + if extra: 75 + msg += "\n\t\t" + extra 76 + 77 + self.log.warning(msg) 78 + 79 + def add_symbol(self, what, fname, ln=None, xref=None): 80 + """Create a reference table describing where each 'what' is located""" 81 + 82 + if what not in self.what_symbols: 83 + self.what_symbols[what] = {"file": {}} 84 + 85 + if fname not in self.what_symbols[what]["file"]: 86 + self.what_symbols[what]["file"][fname] = [] 87 + 88 + if ln and ln not in self.what_symbols[what]["file"][fname]: 89 + self.what_symbols[what]["file"][fname].append(ln) 90 + 91 + if xref: 92 + self.what_symbols[what]["xref"] = xref 93 + 94 + def _parse_line(self, fdata, line): 95 + """Parse a single line of an ABI file""" 96 + 97 + new_what = False 98 + new_tag = False 99 + content = None 100 + 101 + match = self.re_tag.match(line) 102 + if match: 103 + new = match.group(1).lower() 104 + sep = match.group(2) 105 + content = match.group(3) 106 + 107 + match = self.re_valid.search(new) 108 + if match: 109 + new_tag = match.group(1) 110 + else: 111 + if fdata.tag == "description": 112 + # New "tag" is actually part of description. 113 + # Don't consider it a tag 114 + new_tag = False 115 + elif fdata.tag != "": 116 + self.warn(fdata, f"tag '{fdata.tag}' is invalid", line) 117 + 118 + if new_tag: 119 + # "where" is Invalid, but was a common mistake. Warn if found 120 + if new_tag == "where": 121 + self.warn(fdata, "tag 'Where' is invalid. Should be 'What:' instead") 122 + new_tag = "what" 123 + 124 + if new_tag == "what": 125 + fdata.space = None 126 + 127 + if content not in self.what_symbols: 128 + self.add_symbol(what=content, fname=fdata.fname, ln=fdata.ln) 129 + 130 + if fdata.tag == "what": 131 + fdata.what.append(content.strip("\n")) 132 + else: 133 + if fdata.key: 134 + if "description" not in self.data.get(fdata.key, {}): 135 + self.warn(fdata, f"{fdata.key} doesn't have a description") 136 + 137 + for w in fdata.what: 138 + self.add_symbol(what=w, fname=fdata.fname, 139 + ln=fdata.what_ln, xref=fdata.key) 140 + 141 + fdata.label = content 142 + new_what = True 143 + 144 + key = "abi_" + content.lower() 145 + fdata.key = self.re_unprintable.sub("_", key).strip("_") 146 + 147 + # Avoid duplicated keys but using a defined seed, to make 148 + # the namespace identical if there aren't changes at the 149 + # ABI symbols 150 + seed(42) 151 + 152 + while fdata.key in self.data: 153 + char = randrange(0, 51) + ord("A") 154 + if char > ord("Z"): 155 + char += ord("a") - ord("Z") - 1 156 + 157 + fdata.key += chr(char) 158 + 159 + if fdata.key and fdata.key not in self.data: 160 + self.data[fdata.key] = { 161 + "what": [content], 162 + "file": [fdata.file_ref], 163 + "path": fdata.ftype, 164 + "line_no": fdata.ln, 165 + } 166 + 167 + fdata.what = self.data[fdata.key]["what"] 168 + 169 + self.what_refs[content] = fdata.key 170 + fdata.tag = new_tag 171 + fdata.what_ln = fdata.ln 172 + 173 + if fdata.nametag["what"]: 174 + t = (content, fdata.key) 175 + if t not in fdata.nametag["symbols"]: 176 + fdata.nametag["symbols"].append(t) 177 + 178 + return 179 + 180 + if fdata.tag and new_tag: 181 + fdata.tag = new_tag 182 + 183 + if new_what: 184 + fdata.label = "" 185 + 186 + if "description" in self.data[fdata.key]: 187 + self.data[fdata.key]["description"] += "\n\n" 188 + 189 + if fdata.file_ref not in self.data[fdata.key]["file"]: 190 + self.data[fdata.key]["file"].append(fdata.file_ref) 191 + 192 + if self.debug == AbiDebug.WHAT_PARSING: 193 + self.log.debug("what: %s", fdata.what) 194 + 195 + if not fdata.what: 196 + self.warn(fdata, "'What:' should come first:", line) 197 + return 198 + 199 + if new_tag == "description": 200 + fdata.space = None 201 + 202 + if content: 203 + sep = sep.replace(":", " ") 204 + 205 + c = " " * len(new_tag) + sep + content 206 + c = c.expandtabs() 207 + 208 + match = self.re_start_spc.match(c) 209 + if match: 210 + # Preserve initial spaces for the first line 211 + fdata.space = match.group(1) 212 + content = match.group(2) + "\n" 213 + 214 + self.data[fdata.key][fdata.tag] = content 215 + 216 + return 217 + 218 + # Store any contents before tags at the database 219 + if not fdata.tag and "what" in fdata.nametag: 220 + fdata.nametag["description"] += line 221 + return 222 + 223 + if fdata.tag == "description": 224 + content = line.expandtabs() 225 + 226 + if self.re_whitespace.sub("", content) == "": 227 + self.data[fdata.key][fdata.tag] += "\n" 228 + return 229 + 230 + if fdata.space is None: 231 + match = self.re_start_spc.match(content) 232 + if match: 233 + # Preserve initial spaces for the first line 234 + fdata.space = match.group(1) 235 + 236 + content = match.group(2) + "\n" 237 + else: 238 + if content.startswith(fdata.space): 239 + content = content[len(fdata.space):] 240 + 241 + else: 242 + fdata.space = "" 243 + 244 + if fdata.tag == "what": 245 + w = content.strip("\n") 246 + if w: 247 + self.data[fdata.key][fdata.tag].append(w) 248 + else: 249 + self.data[fdata.key][fdata.tag] += content 250 + return 251 + 252 + content = line.strip() 253 + if fdata.tag: 254 + if fdata.tag == "what": 255 + w = content.strip("\n") 256 + if w: 257 + self.data[fdata.key][fdata.tag].append(w) 258 + else: 259 + self.data[fdata.key][fdata.tag] += "\n" + content.rstrip("\n") 260 + return 261 + 262 + # Everything else is error 263 + if content: 264 + self.warn(fdata, "Unexpected content", line) 265 + 266 + def parse_readme(self, nametag, fname): 267 + """Parse ABI README file""" 268 + 269 + nametag["what"] = ["Introduction"] 270 + nametag["path"] = "README" 271 + with open(fname, "r", encoding="utf8", errors="backslashreplace") as fp: 272 + for line in fp: 273 + match = self.re_tag.match(line) 274 + if match: 275 + new = match.group(1).lower() 276 + 277 + match = self.re_valid.search(new) 278 + if match: 279 + nametag["description"] += "\n:" + line 280 + continue 281 + 282 + nametag["description"] += line 283 + 284 + def parse_file(self, fname, path, basename): 285 + """Parse a single file""" 286 + 287 + ref = f"abi_file_{path}_{basename}" 288 + ref = self.re_unprintable.sub("_", ref).strip("_") 289 + 290 + # Store per-file state into a namespace variable. This will be used 291 + # by the per-line parser state machine and by the warning function. 292 + fdata = Namespace 293 + 294 + fdata.fname = fname 295 + fdata.name = basename 296 + 297 + pos = fname.find(ABI_DIR) 298 + if pos > 0: 299 + f = fname[pos:] 300 + else: 301 + f = fname 302 + 303 + fdata.file_ref = (f, ref) 304 + self.file_refs[f] = ref 305 + 306 + fdata.ln = 0 307 + fdata.what_ln = 0 308 + fdata.tag = "" 309 + fdata.label = "" 310 + fdata.what = [] 311 + fdata.key = None 312 + fdata.xrefs = None 313 + fdata.space = None 314 + fdata.ftype = path.split("/")[0] 315 + 316 + fdata.nametag = {} 317 + fdata.nametag["what"] = [f"ABI file {path}/{basename}"] 318 + fdata.nametag["type"] = "File" 319 + fdata.nametag["path"] = fdata.ftype 320 + fdata.nametag["file"] = [fdata.file_ref] 321 + fdata.nametag["line_no"] = 1 322 + fdata.nametag["description"] = "" 323 + fdata.nametag["symbols"] = [] 324 + 325 + self.data[ref] = fdata.nametag 326 + 327 + if self.debug & AbiDebug.WHAT_OPEN: 328 + self.log.debug("Opening file %s", fname) 329 + 330 + if basename == "README": 331 + self.parse_readme(fdata.nametag, fname) 332 + return 333 + 334 + with open(fname, "r", encoding="utf8", errors="backslashreplace") as fp: 335 + for line in fp: 336 + fdata.ln += 1 337 + 338 + self._parse_line(fdata, line) 339 + 340 + if "description" in fdata.nametag: 341 + fdata.nametag["description"] = fdata.nametag["description"].lstrip("\n") 342 + 343 + if fdata.key: 344 + if "description" not in self.data.get(fdata.key, {}): 345 + self.warn(fdata, f"{fdata.key} doesn't have a description") 346 + 347 + for w in fdata.what: 348 + self.add_symbol(what=w, fname=fname, xref=fdata.key) 349 + 350 + def _parse_abi(self, root=None): 351 + """Internal function to parse documentation ABI recursively""" 352 + 353 + if not root: 354 + root = self.directory 355 + 356 + with os.scandir(root) as obj: 357 + for entry in obj: 358 + name = os.path.join(root, entry.name) 359 + 360 + if entry.is_dir(): 361 + self._parse_abi(name) 362 + continue 363 + 364 + if not entry.is_file(): 365 + continue 366 + 367 + basename = os.path.basename(name) 368 + 369 + if basename.startswith("."): 370 + continue 371 + 372 + if basename.endswith(self.ignore_suffixes): 373 + continue 374 + 375 + path = self.re_abi_dir.sub("", os.path.dirname(name)) 376 + 377 + self.parse_file(name, path, basename) 378 + 379 + def parse_abi(self, root=None): 380 + """Parse documentation ABI""" 381 + 382 + self._parse_abi(root) 383 + 384 + if self.debug & AbiDebug.DUMP_ABI_STRUCTS: 385 + self.log.debug(pformat(self.data)) 386 + 387 + def desc_txt(self, desc): 388 + """Print description as found inside ABI files""" 389 + 390 + desc = desc.strip(" \t\n") 391 + 392 + return desc + "\n\n" 393 + 394 + def xref(self, fname): 395 + """ 396 + Converts a Documentation/ABI + basename into a ReST cross-reference 397 + """ 398 + 399 + xref = self.file_refs.get(fname) 400 + if not xref: 401 + return None 402 + else: 403 + return xref 404 + 405 + def desc_rst(self, desc): 406 + """Enrich ReST output by creating cross-references""" 407 + 408 + # Remove title markups from the description 409 + # Having titles inside ABI files will only work if extra 410 + # care would be taken in order to strictly follow the same 411 + # level order for each markup. 412 + desc = self.re_title_mark.sub("\n\n", "\n" + desc) 413 + desc = desc.rstrip(" \t\n").lstrip("\n") 414 + 415 + # Python's regex performance for non-compiled expressions is a lot 416 + # than Perl, as Perl automatically caches them at their 417 + # first usage. Here, we'll need to do the same, as otherwise the 418 + # performance penalty is be high 419 + 420 + new_desc = "" 421 + for d in desc.split("\n"): 422 + if d == "": 423 + new_desc += "\n" 424 + continue 425 + 426 + # Use cross-references for doc files where needed 427 + d = self.re_doc.sub(r":doc:`/\1`", d) 428 + 429 + # Use cross-references for ABI generated docs where needed 430 + matches = self.re_abi.findall(d) 431 + for m in matches: 432 + abi = m[0] + m[1] 433 + 434 + xref = self.file_refs.get(abi) 435 + if not xref: 436 + # This may happen if ABI is on a separate directory, 437 + # like parsing ABI testing and symbol is at stable. 438 + # The proper solution is to move this part of the code 439 + # for it to be inside sphinx/kernel_abi.py 440 + self.log.info("Didn't find ABI reference for '%s'", abi) 441 + else: 442 + new = self.re_escape.sub(r"\\\1", m[1]) 443 + d = re.sub(fr"\b{abi}\b", f":ref:`{new} <{xref}>`", d) 444 + 445 + # Seek for cross reference symbols like /sys/... 446 + # Need to be careful to avoid doing it on a code block 447 + if d[0] not in [" ", "\t"]: 448 + matches = self.re_xref_node.findall(d) 449 + for m in matches: 450 + # Finding ABI here is more complex due to wildcards 451 + xref = self.what_refs.get(m) 452 + if xref: 453 + new = self.re_escape.sub(r"\\\1", m) 454 + d = re.sub(fr"\b{m}\b", f":ref:`{new} <{xref}>`", d) 455 + 456 + new_desc += d + "\n" 457 + 458 + return new_desc + "\n\n" 459 + 460 + def doc(self, output_in_txt=False, show_symbols=True, show_file=True, 461 + filter_path=None): 462 + """Print ABI at stdout""" 463 + 464 + part = None 465 + for key, v in sorted(self.data.items(), 466 + key=lambda x: (x[1].get("type", ""), 467 + x[1].get("what"))): 468 + 469 + wtype = v.get("type", "Symbol") 470 + file_ref = v.get("file") 471 + names = v.get("what", [""]) 472 + 473 + if wtype == "File": 474 + if not show_file: 475 + continue 476 + else: 477 + if not show_symbols: 478 + continue 479 + 480 + if filter_path: 481 + if v.get("path") != filter_path: 482 + continue 483 + 484 + msg = "" 485 + 486 + if wtype != "File": 487 + cur_part = names[0] 488 + if cur_part.find("/") >= 0: 489 + match = self.re_what.match(cur_part) 490 + if match: 491 + symbol = match.group(1).rstrip("/") 492 + cur_part = "Symbols under " + symbol 493 + 494 + if cur_part and cur_part != part: 495 + part = cur_part 496 + msg += part + "\n"+ "-" * len(part) +"\n\n" 497 + 498 + msg += f".. _{key}:\n\n" 499 + 500 + max_len = 0 501 + for i in range(0, len(names)): # pylint: disable=C0200 502 + names[i] = "**" + self.re_escape.sub(r"\\\1", names[i]) + "**" 503 + 504 + max_len = max(max_len, len(names[i])) 505 + 506 + msg += "+-" + "-" * max_len + "-+\n" 507 + for name in names: 508 + msg += f"| {name}" + " " * (max_len - len(name)) + " |\n" 509 + msg += "+-" + "-" * max_len + "-+\n" 510 + msg += "\n" 511 + 512 + for ref in file_ref: 513 + if wtype == "File": 514 + msg += f".. _{ref[1]}:\n\n" 515 + else: 516 + base = os.path.basename(ref[0]) 517 + msg += f"Defined on file :ref:`{base} <{ref[1]}>`\n\n" 518 + 519 + if wtype == "File": 520 + msg += names[0] +"\n" + "-" * len(names[0]) +"\n\n" 521 + 522 + desc = v.get("description") 523 + if not desc and wtype != "File": 524 + msg += f"DESCRIPTION MISSING for {names[0]}\n\n" 525 + 526 + if desc: 527 + if output_in_txt: 528 + msg += self.desc_txt(desc) 529 + else: 530 + msg += self.desc_rst(desc) 531 + 532 + symbols = v.get("symbols") 533 + if symbols: 534 + msg += "Has the following ABI:\n\n" 535 + 536 + for w, label in symbols: 537 + # Escape special chars from content 538 + content = self.re_escape.sub(r"\\\1", w) 539 + 540 + msg += f"- :ref:`{content} <{label}>`\n\n" 541 + 542 + users = v.get("users") 543 + if users and users.strip(" \t\n"): 544 + users = users.strip("\n").replace('\n', '\n\t') 545 + msg += f"Users:\n\t{users}\n\n" 546 + 547 + ln = v.get("line_no", 1) 548 + 549 + yield (msg, file_ref[0][0], ln) 550 + 551 + def check_issues(self): 552 + """Warn about duplicated ABI entries""" 553 + 554 + for what, v in self.what_symbols.items(): 555 + files = v.get("file") 556 + if not files: 557 + # Should never happen if the parser works properly 558 + self.log.warning("%s doesn't have a file associated", what) 559 + continue 560 + 561 + if len(files) == 1: 562 + continue 563 + 564 + f = [] 565 + for fname, lines in sorted(files.items()): 566 + if not lines: 567 + f.append(f"{fname}") 568 + elif len(lines) == 1: 569 + f.append(f"{fname}:{lines[0]}") 570 + else: 571 + m = fname + "lines " 572 + m += ", ".join(str(x) for x in lines) 573 + f.append(m) 574 + 575 + self.log.warning("%s is defined %d times: %s", what, len(f), "; ".join(f)) 576 + 577 + def search_symbols(self, expr): 578 + """ Searches for ABI symbols """ 579 + 580 + regex = re.compile(expr, re.I) 581 + 582 + found_keys = 0 583 + for t in sorted(self.data.items(), key=lambda x: [0]): 584 + v = t[1] 585 + 586 + wtype = v.get("type", "") 587 + if wtype == "File": 588 + continue 589 + 590 + for what in v.get("what", [""]): 591 + if regex.search(what): 592 + found_keys += 1 593 + 594 + kernelversion = v.get("kernelversion", "").strip(" \t\n") 595 + date = v.get("date", "").strip(" \t\n") 596 + contact = v.get("contact", "").strip(" \t\n") 597 + users = v.get("users", "").strip(" \t\n") 598 + desc = v.get("description", "").strip(" \t\n") 599 + 600 + files = [] 601 + for f in v.get("file", ()): 602 + files.append(f[0]) 603 + 604 + what = str(found_keys) + ". " + what 605 + title_tag = "-" * len(what) 606 + 607 + print(f"\n{what}\n{title_tag}\n") 608 + 609 + if kernelversion: 610 + print(f"Kernel version:\t\t{kernelversion}") 611 + 612 + if date: 613 + print(f"Date:\t\t\t{date}") 614 + 615 + if contact: 616 + print(f"Contact:\t\t{contact}") 617 + 618 + if users: 619 + print(f"Users:\t\t\t{users}") 620 + 621 + print("Defined on file(s):\t" + ", ".join(files)) 622 + 623 + if desc: 624 + desc = desc.strip("\n") 625 + print(f"\n{desc}\n") 626 + 627 + if not found_keys: 628 + print(f"Regular expression /{expr}/ not found.")
+234
scripts/lib/abi/abi_regex.py
··· 1 + #!/usr/bin/env python3 2 + # xxpylint: disable=R0903 3 + # Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>. 4 + # SPDX-License-Identifier: GPL-2.0 5 + 6 + """ 7 + Convert ABI what into regular expressions 8 + """ 9 + 10 + import re 11 + import sys 12 + 13 + from pprint import pformat 14 + 15 + from abi_parser import AbiParser 16 + from helpers import AbiDebug 17 + 18 + class AbiRegex(AbiParser): 19 + """Extends AbiParser to search ABI nodes with regular expressions""" 20 + 21 + # Escape only ASCII visible characters 22 + escape_symbols = r"([\x21-\x29\x2b-\x2d\x3a-\x40\x5c\x60\x7b-\x7e])" 23 + leave_others = "others" 24 + 25 + # Tuples with regular expressions to be compiled and replacement data 26 + re_whats = [ 27 + # Drop escape characters that might exist 28 + (re.compile("\\\\"), ""), 29 + 30 + # Temporarily escape dot characters 31 + (re.compile(r"\."), "\xf6"), 32 + 33 + # Temporarily change [0-9]+ type of patterns 34 + (re.compile(r"\[0\-9\]\+"), "\xff"), 35 + 36 + # Temporarily change [\d+-\d+] type of patterns 37 + (re.compile(r"\[0\-\d+\]"), "\xff"), 38 + (re.compile(r"\[0:\d+\]"), "\xff"), 39 + (re.compile(r"\[(\d+)\]"), "\xf4\\\\d+\xf5"), 40 + 41 + # Temporarily change [0-9] type of patterns 42 + (re.compile(r"\[(\d)\-(\d)\]"), "\xf4\1-\2\xf5"), 43 + 44 + # Handle multiple option patterns 45 + (re.compile(r"[\{\<\[]([\w_]+)(?:[,|]+([\w_]+)){1,}[\}\>\]]"), r"(\1|\2)"), 46 + 47 + # Handle wildcards 48 + (re.compile(r"([^\/])\*"), "\\1\\\\w\xf7"), 49 + (re.compile(r"/\*/"), "/.*/"), 50 + (re.compile(r"/\xf6\xf6\xf6"), "/.*"), 51 + (re.compile(r"\<[^\>]+\>"), "\\\\w\xf7"), 52 + (re.compile(r"\{[^\}]+\}"), "\\\\w\xf7"), 53 + (re.compile(r"\[[^\]]+\]"), "\\\\w\xf7"), 54 + 55 + (re.compile(r"XX+"), "\\\\w\xf7"), 56 + (re.compile(r"([^A-Z])[XYZ]([^A-Z])"), "\\1\\\\w\xf7\\2"), 57 + (re.compile(r"([^A-Z])[XYZ]$"), "\\1\\\\w\xf7"), 58 + (re.compile(r"_[AB]_"), "_\\\\w\xf7_"), 59 + 60 + # Recover [0-9] type of patterns 61 + (re.compile(r"\xf4"), "["), 62 + (re.compile(r"\xf5"), "]"), 63 + 64 + # Remove duplicated spaces 65 + (re.compile(r"\s+"), r" "), 66 + 67 + # Special case: drop comparison as in: 68 + # What: foo = <something> 69 + # (this happens on a few IIO definitions) 70 + (re.compile(r"\s*\=.*$"), ""), 71 + 72 + # Escape all other symbols 73 + (re.compile(escape_symbols), r"\\\1"), 74 + (re.compile(r"\\\\"), r"\\"), 75 + (re.compile(r"\\([\[\]\(\)\|])"), r"\1"), 76 + (re.compile(r"(\d+)\\(-\d+)"), r"\1\2"), 77 + 78 + (re.compile(r"\xff"), r"\\d+"), 79 + 80 + # Special case: IIO ABI which a parenthesis. 81 + (re.compile(r"sqrt(.*)"), r"sqrt(.*)"), 82 + 83 + # Simplify regexes with multiple .* 84 + (re.compile(r"(?:\.\*){2,}"), ""), 85 + 86 + # Recover dot characters 87 + (re.compile(r"\xf6"), "\\."), 88 + # Recover plus characters 89 + (re.compile(r"\xf7"), "+"), 90 + ] 91 + re_has_num = re.compile(r"\\d") 92 + 93 + # Symbol name after escape_chars that are considered a devnode basename 94 + re_symbol_name = re.compile(r"(\w|\\[\.\-\:])+$") 95 + 96 + # List of popular group names to be skipped to minimize regex group size 97 + # Use AbiDebug.SUBGROUP_SIZE to detect those 98 + skip_names = set(["devices", "hwmon"]) 99 + 100 + def regex_append(self, what, new): 101 + """ 102 + Get a search group for a subset of regular expressions. 103 + 104 + As ABI may have thousands of symbols, using a for to search all 105 + regular expressions is at least O(n^2). When there are wildcards, 106 + the complexity increases substantially, eventually becoming exponential. 107 + 108 + To avoid spending too much time on them, use a logic to split 109 + them into groups. The smaller the group, the better, as it would 110 + mean that searches will be confined to a small number of regular 111 + expressions. 112 + 113 + The conversion to a regex subset is tricky, as we need something 114 + that can be easily obtained from the sysfs symbol and from the 115 + regular expression. So, we need to discard nodes that have 116 + wildcards. 117 + 118 + If it can't obtain a subgroup, place the regular expression inside 119 + a special group (self.leave_others). 120 + """ 121 + 122 + search_group = None 123 + 124 + for search_group in reversed(new.split("/")): 125 + if not search_group or search_group in self.skip_names: 126 + continue 127 + if self.re_symbol_name.match(search_group): 128 + break 129 + 130 + if not search_group: 131 + search_group = self.leave_others 132 + 133 + if self.debug & AbiDebug.SUBGROUP_MAP: 134 + self.log.debug("%s: mapped as %s", what, search_group) 135 + 136 + try: 137 + if search_group not in self.regex_group: 138 + self.regex_group[search_group] = [] 139 + 140 + self.regex_group[search_group].append(re.compile(new)) 141 + if self.search_string: 142 + if what.find(self.search_string) >= 0: 143 + print(f"What: {what}") 144 + except re.PatternError: 145 + self.log.warning("Ignoring '%s' as it produced an invalid regex:\n" 146 + " '%s'", what, new) 147 + 148 + def get_regexes(self, what): 149 + """ 150 + Given an ABI devnode, return a list of all regular expressions that 151 + may match it, based on the sub-groups created by regex_append() 152 + """ 153 + 154 + re_list = [] 155 + 156 + patches = what.split("/") 157 + patches.reverse() 158 + patches.append(self.leave_others) 159 + 160 + for search_group in patches: 161 + if search_group in self.regex_group: 162 + re_list += self.regex_group[search_group] 163 + 164 + return re_list 165 + 166 + def __init__(self, *args, **kwargs): 167 + """ 168 + Override init method to get verbose argument 169 + """ 170 + 171 + self.regex_group = None 172 + self.search_string = None 173 + self.re_string = None 174 + 175 + if "search_string" in kwargs: 176 + self.search_string = kwargs.get("search_string") 177 + del kwargs["search_string"] 178 + 179 + if self.search_string: 180 + 181 + try: 182 + self.re_string = re.compile(self.search_string) 183 + except re.PatternError as e: 184 + msg = f"{self.search_string} is not a valid regular expression" 185 + raise ValueError(msg) from e 186 + 187 + super().__init__(*args, **kwargs) 188 + 189 + def parse_abi(self, *args, **kwargs): 190 + 191 + super().parse_abi(*args, **kwargs) 192 + 193 + self.regex_group = {} 194 + 195 + print("Converting ABI What fields into regexes...", file=sys.stderr) 196 + 197 + for t in sorted(self.data.items(), key=lambda x: x[0]): 198 + v = t[1] 199 + if v.get("type") == "File": 200 + continue 201 + 202 + v["regex"] = [] 203 + 204 + for what in v.get("what", []): 205 + if not what.startswith("/sys"): 206 + continue 207 + 208 + new = what 209 + for r, s in self.re_whats: 210 + try: 211 + new = r.sub(s, new) 212 + except re.PatternError as e: 213 + # Help debugging troubles with new regexes 214 + raise re.PatternError(f"{e}\nwhile re.sub('{r.pattern}', {s}, str)") from e 215 + 216 + v["regex"].append(new) 217 + 218 + if self.debug & AbiDebug.REGEX: 219 + self.log.debug("%-90s <== %s", new, what) 220 + 221 + # Store regex into a subgroup to speedup searches 222 + self.regex_append(what, new) 223 + 224 + if self.debug & AbiDebug.SUBGROUP_DICT: 225 + self.log.debug("%s", pformat(self.regex_group)) 226 + 227 + if self.debug & AbiDebug.SUBGROUP_SIZE: 228 + biggestd_keys = sorted(self.regex_group.keys(), 229 + key= lambda k: len(self.regex_group[k]), 230 + reverse=True) 231 + 232 + print("Top regex subgroups:", file=sys.stderr) 233 + for k in biggestd_keys[:10]: 234 + print(f"{k} has {len(self.regex_group[k])} elements", file=sys.stderr)
+38
scripts/lib/abi/helpers.py
··· 1 + #!/usr/bin/env python3 2 + # Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>. 3 + # pylint: disable=R0903 4 + # SPDX-License-Identifier: GPL-2.0 5 + 6 + """ 7 + Helper classes for ABI parser 8 + """ 9 + 10 + ABI_DIR = "Documentation/ABI/" 11 + 12 + 13 + class AbiDebug: 14 + """Debug levels""" 15 + 16 + WHAT_PARSING = 1 17 + WHAT_OPEN = 2 18 + DUMP_ABI_STRUCTS = 4 19 + UNDEFINED = 8 20 + REGEX = 16 21 + SUBGROUP_MAP = 32 22 + SUBGROUP_DICT = 64 23 + SUBGROUP_SIZE = 128 24 + GRAPH = 256 25 + 26 + 27 + DEBUG_HELP = """ 28 + 1 - enable debug parsing logic 29 + 2 - enable debug messages on file open 30 + 4 - enable debug for ABI parse data 31 + 8 - enable extra debug information to identify troubles 32 + with ABI symbols found at the local machine that 33 + weren't found on ABI documentation (used only for 34 + undefined subcommand) 35 + 16 - enable debug for what to regex conversion 36 + 32 - enable debug for symbol regex subgroups 37 + 64 - enable debug for sysfs graph tree variable 38 + """
+378
scripts/lib/abi/system_symbols.py
··· 1 + #!/usr/bin/env python3 2 + # pylint: disable=R0902,R0912,R0914,R0915,R1702 3 + # Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>. 4 + # SPDX-License-Identifier: GPL-2.0 5 + 6 + """ 7 + Parse ABI documentation and produce results from it. 8 + """ 9 + 10 + import os 11 + import re 12 + import sys 13 + 14 + from concurrent import futures 15 + from datetime import datetime 16 + from random import shuffle 17 + 18 + from helpers import AbiDebug 19 + 20 + class SystemSymbols: 21 + """Stores arguments for the class and initialize class vars""" 22 + 23 + def graph_add_file(self, path, link=None): 24 + """ 25 + add a file path to the sysfs graph stored at self.root 26 + """ 27 + 28 + if path in self.files: 29 + return 30 + 31 + name = "" 32 + ref = self.root 33 + for edge in path.split("/"): 34 + name += edge + "/" 35 + if edge not in ref: 36 + ref[edge] = {"__name": [name.rstrip("/")]} 37 + 38 + ref = ref[edge] 39 + 40 + if link and link not in ref["__name"]: 41 + ref["__name"].append(link.rstrip("/")) 42 + 43 + self.files.add(path) 44 + 45 + def print_graph(self, root_prefix="", root=None, level=0): 46 + """Prints a reference tree graph using UTF-8 characters""" 47 + 48 + if not root: 49 + root = self.root 50 + level = 0 51 + 52 + # Prevent endless traverse 53 + if level > 5: 54 + return 55 + 56 + if level > 0: 57 + prefix = "├──" 58 + last_prefix = "└──" 59 + else: 60 + prefix = "" 61 + last_prefix = "" 62 + 63 + items = list(root.items()) 64 + 65 + names = root.get("__name", []) 66 + for k, edge in items: 67 + if k == "__name": 68 + continue 69 + 70 + if not k: 71 + k = "/" 72 + 73 + if len(names) > 1: 74 + k += " links: " + ",".join(names[1:]) 75 + 76 + if edge == items[-1][1]: 77 + print(root_prefix + last_prefix + k) 78 + p = root_prefix 79 + if level > 0: 80 + p += " " 81 + self.print_graph(p, edge, level + 1) 82 + else: 83 + print(root_prefix + prefix + k) 84 + p = root_prefix + "│ " 85 + self.print_graph(p, edge, level + 1) 86 + 87 + def _walk(self, root): 88 + """ 89 + Walk through sysfs to get all devnodes that aren't ignored. 90 + 91 + By default, uses /sys as sysfs mounting point. If another 92 + directory is used, it replaces them to /sys at the patches. 93 + """ 94 + 95 + with os.scandir(root) as obj: 96 + for entry in obj: 97 + path = os.path.join(root, entry.name) 98 + if self.sysfs: 99 + p = path.replace(self.sysfs, "/sys", count=1) 100 + else: 101 + p = path 102 + 103 + if self.re_ignore.search(p): 104 + return 105 + 106 + # Handle link first to avoid directory recursion 107 + if entry.is_symlink(): 108 + real = os.path.realpath(path) 109 + if not self.sysfs: 110 + self.aliases[path] = real 111 + else: 112 + real = real.replace(self.sysfs, "/sys", count=1) 113 + 114 + # Add absfile location to graph if it doesn't exist 115 + if not self.re_ignore.search(real): 116 + # Add link to the graph 117 + self.graph_add_file(real, p) 118 + 119 + elif entry.is_file(): 120 + self.graph_add_file(p) 121 + 122 + elif entry.is_dir(): 123 + self._walk(path) 124 + 125 + def __init__(self, abi, sysfs="/sys", hints=False): 126 + """ 127 + Initialize internal variables and get a list of all files inside 128 + sysfs that can currently be parsed. 129 + 130 + Please notice that there are several entries on sysfs that aren't 131 + documented as ABI. Ignore those. 132 + 133 + The real paths will be stored under self.files. Aliases will be 134 + stored in separate, as self.aliases. 135 + """ 136 + 137 + self.abi = abi 138 + self.log = abi.log 139 + 140 + if sysfs != "/sys": 141 + self.sysfs = sysfs.rstrip("/") 142 + else: 143 + self.sysfs = None 144 + 145 + self.hints = hints 146 + 147 + self.root = {} 148 + self.aliases = {} 149 + self.files = set() 150 + 151 + dont_walk = [ 152 + # Those require root access and aren't documented at ABI 153 + f"^{sysfs}/kernel/debug", 154 + f"^{sysfs}/kernel/tracing", 155 + f"^{sysfs}/fs/pstore", 156 + f"^{sysfs}/fs/bpf", 157 + f"^{sysfs}/fs/fuse", 158 + 159 + # This is not documented at ABI 160 + f"^{sysfs}/module", 161 + 162 + f"^{sysfs}/fs/cgroup", # this is big and has zero docs under ABI 163 + f"^{sysfs}/firmware", # documented elsewhere: ACPI, DT bindings 164 + "sections|notes", # aren't actually part of ABI 165 + 166 + # kernel-parameters.txt - not easy to parse 167 + "parameters", 168 + ] 169 + 170 + self.re_ignore = re.compile("|".join(dont_walk)) 171 + 172 + print(f"Reading {sysfs} directory contents...", file=sys.stderr) 173 + self._walk(sysfs) 174 + 175 + def check_file(self, refs, found): 176 + """Check missing ABI symbols for a given sysfs file""" 177 + 178 + res_list = [] 179 + 180 + try: 181 + for names in refs: 182 + fname = names[0] 183 + 184 + res = { 185 + "found": False, 186 + "fname": fname, 187 + "msg": "", 188 + } 189 + res_list.append(res) 190 + 191 + re_what = self.abi.get_regexes(fname) 192 + if not re_what: 193 + self.abi.log.warning(f"missing rules for {fname}") 194 + continue 195 + 196 + for name in names: 197 + for r in re_what: 198 + if self.abi.debug & AbiDebug.UNDEFINED: 199 + self.log.debug("check if %s matches '%s'", name, r.pattern) 200 + if r.match(name): 201 + res["found"] = True 202 + if found: 203 + res["msg"] += f" {fname}: regex:\n\t" 204 + continue 205 + 206 + if self.hints and not res["found"]: 207 + res["msg"] += f" {fname} not found. Tested regexes:\n" 208 + for r in re_what: 209 + res["msg"] += " " + r.pattern + "\n" 210 + 211 + except KeyboardInterrupt: 212 + pass 213 + 214 + return res_list 215 + 216 + def _ref_interactor(self, root): 217 + """Recursive function to interact over the sysfs tree""" 218 + 219 + for k, v in root.items(): 220 + if isinstance(v, dict): 221 + yield from self._ref_interactor(v) 222 + 223 + if root == self.root or k == "__name": 224 + continue 225 + 226 + if self.abi.re_string: 227 + fname = v["__name"][0] 228 + if self.abi.re_string.search(fname): 229 + yield v 230 + else: 231 + yield v 232 + 233 + 234 + def get_fileref(self, all_refs, chunk_size): 235 + """Interactor to group refs into chunks""" 236 + 237 + n = 0 238 + refs = [] 239 + 240 + for ref in all_refs: 241 + refs.append(ref) 242 + 243 + n += 1 244 + if n >= chunk_size: 245 + yield refs 246 + n = 0 247 + refs = [] 248 + 249 + yield refs 250 + 251 + def check_undefined_symbols(self, max_workers=None, chunk_size=50, 252 + found=None, dry_run=None): 253 + """Seach ABI for sysfs symbols missing documentation""" 254 + 255 + self.abi.parse_abi() 256 + 257 + if self.abi.debug & AbiDebug.GRAPH: 258 + self.print_graph() 259 + 260 + all_refs = [] 261 + for ref in self._ref_interactor(self.root): 262 + all_refs.append(ref["__name"]) 263 + 264 + if dry_run: 265 + print("Would check", file=sys.stderr) 266 + for ref in all_refs: 267 + print(", ".join(ref)) 268 + 269 + return 270 + 271 + print("Starting to search symbols (it may take several minutes):", 272 + file=sys.stderr) 273 + start = datetime.now() 274 + old_elapsed = None 275 + 276 + # Python doesn't support multithreading due to limitations on its 277 + # global lock (GIL). While Python 3.13 finally made GIL optional, 278 + # there are still issues related to it. Also, we want to have 279 + # backward compatibility with older versions of Python. 280 + # 281 + # So, use instead multiprocess. However, Python is very slow passing 282 + # data from/to multiple processes. Also, it may consume lots of memory 283 + # if the data to be shared is not small. So, we need to group workload 284 + # in chunks that are big enough to generate performance gains while 285 + # not being so big that would cause out-of-memory. 286 + 287 + num_refs = len(all_refs) 288 + print(f"Number of references to parse: {num_refs}", file=sys.stderr) 289 + 290 + if not max_workers: 291 + max_workers = os.cpu_count() 292 + elif max_workers > os.cpu_count(): 293 + max_workers = os.cpu_count() 294 + 295 + max_workers = max(max_workers, 1) 296 + 297 + max_chunk_size = int((num_refs + max_workers - 1) / max_workers) 298 + chunk_size = min(chunk_size, max_chunk_size) 299 + chunk_size = max(1, chunk_size) 300 + 301 + if max_workers > 1: 302 + executor = futures.ProcessPoolExecutor 303 + 304 + # Place references in a random order. This may help improving 305 + # performance, by mixing complex/simple expressions when creating 306 + # chunks 307 + shuffle(all_refs) 308 + else: 309 + # Python has a high overhead with processes. When there's just 310 + # one worker, it is faster to not create a new process. 311 + # Yet, User still deserves to have a progress print. So, use 312 + # python's "thread", which is actually a single process, using 313 + # an internal schedule to switch between tasks. No performance 314 + # gains for non-IO tasks, but still it can be quickly interrupted 315 + # from time to time to display progress. 316 + executor = futures.ThreadPoolExecutor 317 + 318 + not_found = [] 319 + f_list = [] 320 + with executor(max_workers=max_workers) as exe: 321 + for refs in self.get_fileref(all_refs, chunk_size): 322 + if refs: 323 + try: 324 + f_list.append(exe.submit(self.check_file, refs, found)) 325 + 326 + except KeyboardInterrupt: 327 + return 328 + 329 + total = len(f_list) 330 + 331 + if not total: 332 + if self.abi.re_string: 333 + print(f"No ABI symbol matches {self.abi.search_string}") 334 + else: 335 + self.abi.log.warning("No ABI symbols found") 336 + return 337 + 338 + print(f"{len(f_list):6d} jobs queued on {max_workers} workers", 339 + file=sys.stderr) 340 + 341 + while f_list: 342 + try: 343 + t = futures.wait(f_list, timeout=1, 344 + return_when=futures.FIRST_COMPLETED) 345 + 346 + done = t[0] 347 + 348 + for fut in done: 349 + res_list = fut.result() 350 + 351 + for res in res_list: 352 + if not res["found"]: 353 + not_found.append(res["fname"]) 354 + if res["msg"]: 355 + print(res["msg"]) 356 + 357 + f_list.remove(fut) 358 + except KeyboardInterrupt: 359 + return 360 + 361 + except RuntimeError as e: 362 + self.abi.log.warning(f"Future: {e}") 363 + break 364 + 365 + if sys.stderr.isatty(): 366 + elapsed = str(datetime.now() - start).split(".", maxsplit=1)[0] 367 + if len(f_list) < total: 368 + elapsed += f" ({total - len(f_list)}/{total} jobs completed). " 369 + if elapsed != old_elapsed: 370 + print(elapsed + "\r", end="", flush=True, 371 + file=sys.stderr) 372 + old_elapsed = elapsed 373 + 374 + elapsed = str(datetime.now() - start).split(".", maxsplit=1)[0] 375 + print(elapsed, file=sys.stderr) 376 + 377 + for f in sorted(not_found): 378 + print(f"{f} not found.")