···673673Ross Zwisler <zwisler@kernel.org> <ross.zwisler@linux.intel.com>674674Rudolf Marek <R.Marek@sh.cvut.cz>675675Rui Saraiva <rmps@joel.ist.utl.pt>676676+Sachin Mokashi <sachin.mokashi@intel.com> <sachinx.mokashi@intel.com>676677Sachin P Sant <ssant@in.ibm.com>677678Sai Prakash Ranjan <quic_saipraka@quicinc.com> <saiprakash.ranjan@codeaurora.org>678679Sakari Ailus <sakari.ailus@linux.intel.com> <sakari.ailus@iki.fi>
+6
CREDITS
···43784378S: New York, New York 1002543794379S: USA4380438043814381+N: Masahiro Yamada43824382+E: masahiroy@kernel.org43834383+D: Kbuild Maintainer 2017-202543844384+D: Kconfig Maintainer 2018-202543854385+S: Japan43864386+43814387N: Li Yang43824388E: leoli@freescale.com43834389D: Freescale Highspeed USB device driver
+22
Documentation/ABI/testing/sysfs-fs-f2fs
···861861 SB_ENC_STRICT_MODE_FL 0x00000001862862 SB_ENC_NO_COMPAT_FALLBACK_FL 0x00000002863863 ============================ ==========864864+865865+What: /sys/fs/f2fs/<disk>/reserved_pin_section866866+Date: June 2025867867+Contact: "Chao Yu" <chao@kernel.org>868868+Description: This threshold is used to control triggering garbage collection while869869+ fallocating on pinned file, so, it can guarantee there is enough free870870+ reserved section before preallocating on pinned file.871871+ By default, the value is ovp_sections, especially, for zoned ufs, the872872+ value is 1.873873+874874+What: /sys/fs/f2fs/<disk>/gc_boost_gc_multiple875875+Date: June 2025876876+Contact: "Daeho Jeong" <daehojeong@google.com>877877+Description: Set a multiplier for the background GC migration window when F2FS GC is878878+ boosted. The range should be from 1 to the segment count in a section.879879+ Default: 5880880+881881+What: /sys/fs/f2fs/<disk>/gc_boost_gc_greedy882882+Date: June 2025883883+Contact: "Daeho Jeong" <daehojeong@google.com>884884+Description: Control GC algorithm for boost GC. 0: cost benefit, 1: greedy885885+ Default: 1
+56
Documentation/accounting/delay-accounting.rst
···131131 linuxrc: read=65536, write=0, cancelled_write=0132132133133The above command can be used with -v to get more debug information.134134+135135+After the system starts, use `delaytop` to get the system-wide delay information,136136+which includes system-wide PSI information and Top-N high-latency tasks.137137+138138+`delaytop` supports sorting by CPU latency in descending order by default,139139+displays the top 20 high-latency tasks by default, and refreshes the latency140140+data every 2 seconds by default.141141+142142+Get PSI information and Top-N tasks delay, since system boot::143143+144144+ bash# ./delaytop145145+ System Pressure Information: (avg10/avg60/avg300/total)146146+ CPU some: 0.0%/ 0.0%/ 0.0%/ 345(ms)147147+ CPU full: 0.0%/ 0.0%/ 0.0%/ 0(ms)148148+ Memory full: 0.0%/ 0.0%/ 0.0%/ 0(ms)149149+ Memory some: 0.0%/ 0.0%/ 0.0%/ 0(ms)150150+ IO full: 0.0%/ 0.0%/ 0.0%/ 65(ms)151151+ IO some: 0.0%/ 0.0%/ 0.0%/ 79(ms)152152+ IRQ full: 0.0%/ 0.0%/ 0.0%/ 0(ms)153153+ Top 20 processes (sorted by CPU delay):154154+ PID TGID COMMAND CPU(ms) IO(ms) SWAP(ms) RCL(ms) THR(ms) CMP(ms) WP(ms) IRQ(ms)155155+ ----------------------------------------------------------------------------------------------156156+ 161 161 zombie_memcg_re 1.40 0.00 0.00 0.00 0.00 0.00 0.00 0.00157157+ 130 130 blkcg_punt_bio 1.37 0.00 0.00 0.00 0.00 0.00 0.00 0.00158158+ 444 444 scsi_tmf_0 0.73 0.00 0.00 0.00 0.00 0.00 0.00 0.00159159+ 1280 1280 rsyslogd 0.53 0.04 0.00 0.00 0.00 0.00 0.00 0.00160160+ 12 12 ksoftirqd/0 0.47 0.00 0.00 0.00 0.00 0.00 0.00 0.00161161+ 1277 1277 nbd-server 0.44 0.00 0.00 0.00 0.00 0.00 0.00 0.00162162+ 308 308 kworker/2:2-sys 0.41 0.00 0.00 0.00 0.00 0.00 0.00 0.00163163+ 55 55 netns 0.36 0.00 0.00 0.00 0.00 0.00 0.00 0.00164164+ 1187 1187 acpid 0.31 0.03 0.00 0.00 0.00 0.00 0.00 0.00165165+ 6184 6184 kworker/1:2-sys 0.24 0.00 0.00 0.00 0.00 0.00 0.00 0.00166166+ 186 186 kaluad 0.24 0.00 0.00 0.00 0.00 0.00 0.00 0.00167167+ 18 18 ksoftirqd/1 0.24 0.00 0.00 0.00 0.00 0.00 0.00 0.00168168+ 185 185 kmpath_rdacd 0.23 0.00 0.00 0.00 0.00 0.00 0.00 0.00169169+ 190 190 kstrp 0.23 0.00 0.00 0.00 0.00 0.00 0.00 0.00170170+ 2759 2759 agetty 0.20 0.03 0.00 0.00 0.00 0.00 0.00 0.00171171+ 1190 1190 kworker/0:3-sys 0.19 0.00 0.00 0.00 0.00 0.00 0.00 0.00172172+ 1272 1272 sshd 0.15 0.04 0.00 0.00 0.00 0.00 0.00 0.00173173+ 1156 1156 license 0.15 0.11 0.00 0.00 0.00 0.00 0.00 0.00174174+ 134 134 md 0.13 0.00 0.00 0.00 0.00 0.00 0.00 0.00175175+ 6142 6142 kworker/3:2-xfs 0.13 0.00 0.00 0.00 0.00 0.00 0.00 0.00176176+177177+Dynamic interactive interface of delaytop::178178+179179+ # ./delaytop -p pid180180+ Print delayacct stats181181+182182+ # ./delaytop -P num183183+ Display the top N tasks184184+185185+ # ./delaytop -n num186186+ Set delaytop refresh frequency (num times)187187+188188+ # ./delaytop -d secs189189+ Specify refresh interval as secs
···80808181As a guide, we suggest you calculate the number of bytes to use in the8282metadata device as 48 * $data_dev_size / $data_block_size but round it up8383-to 2MB if the answer is smaller. If you're creating large numbers of8383+to 2MiB if the answer is smaller. If you're creating large numbers of8484snapshots which are recording large amounts of change, you may find you8585need to increase this.86868787-The largest size supported is 16GB: If the device is larger,8787+The largest size supported is 16GiB: If the device is larger,8888a warning will be issued and the excess space will not be used.89899090Reloading a pool table···107107108108$data_block_size gives the smallest unit of disk space that can be109109allocated at a time expressed in units of 512-byte sectors.110110-$data_block_size must be between 128 (64KB) and 2097152 (1GB) and a111111-multiple of 128 (64KB). $data_block_size cannot be changed after the110110+$data_block_size must be between 128 (64KiB) and 2097152 (1GiB) and a111111+multiple of 128 (64KiB). $data_block_size cannot be changed after the112112thin-pool is created. People primarily interested in thin provisioning113113-may want to use a value such as 1024 (512KB). People doing lots of114114-snapshotting may want a smaller value such as 128 (64KB). If you are113113+may want to use a value such as 1024 (512KiB). People doing lots of114114+snapshotting may want a smaller value such as 128 (64KiB). If you are115115not zeroing newly-allocated data, a larger $data_block_size in the116116-region of 256000 (128MB) is suggested.116116+region of 262144 (128MiB) is suggested.117117118118$low_water_mark is expressed in blocks of size $data_block_size. If119119free space on the data device drops below this level then a dm event···291291 error_if_no_space:292292 Error IOs, instead of queueing, if no space.293293294294- Data block size must be between 64KB (128 sectors) and 1GB294294+ Data block size must be between 64KiB (128 sectors) and 1GiB295295 (2097152 sectors) inclusive.296296297297
+21
Documentation/admin-guide/kdump/kdump.rst
···311311312312 crashkernel=0,low313313314314+4) crashkernel=size,cma315315+316316+ Reserve additional crash kernel memory from CMA. This reservation is317317+ usable by the first system's userspace memory and kernel movable318318+ allocations (memory balloon, zswap). Pages allocated from this memory319319+ range will not be included in the vmcore so this should not be used if320320+ dumping of userspace memory is intended and it has to be expected that321321+ some movable kernel pages may be missing from the dump.322322+323323+ A standard crashkernel reservation, as described above, is still needed324324+ to hold the crash kernel and initrd.325325+326326+ This option increases the risk of a kdump failure: DMA transfers327327+ configured by the first kernel may end up corrupting the second328328+ kernel's memory.329329+330330+ This reservation method is intended for systems that can't afford to331331+ sacrifice enough memory for standard crashkernel reservation and where332332+ less reliable and possibly incomplete kdump is preferable to no kdump at333333+ all.334334+314335Boot into System Kernel315336-----------------------3163371) Update the boot loader (such as grub, yaboot, or lilo) configuration
+73-13
Documentation/admin-guide/kernel-parameters.txt
···994994 0: to disable low allocation.995995 It will be ignored when crashkernel=X,high is not used996996 or memory reserved is below 4G.997997+ crashkernel=size[KMG],cma998998+ [KNL, X86] Reserve additional crash kernel memory from999999+ CMA. This reservation is usable by the first system's10001000+ userspace memory and kernel movable allocations (memory10011001+ balloon, zswap). Pages allocated from this memory range10021002+ will not be included in the vmcore so this should not10031003+ be used if dumping of userspace memory is intended and10041004+ it has to be expected that some movable kernel pages10051005+ may be missing from the dump.10061006+10071007+ A standard crashkernel reservation, as described above,10081008+ is still needed to hold the crash kernel and initrd.10091009+10101010+ This option increases the risk of a kdump failure: DMA10111011+ transfers configured by the first kernel may end up10121012+ corrupting the second kernel's memory.10131013+10141014+ This reservation method is intended for systems that10151015+ can't afford to sacrifice enough memory for standard10161016+ crashkernel reservation and where less reliable and10171017+ possibly incomplete kdump is preferable to no kdump at10181018+ all.99710199981020 cryptomgr.notests9991021 [KNL] Disable crypto self-tests···18271805 [KNL] Should the hard-lockup detector generate18281806 backtraces on all cpus.18291807 Format: 0 | 118081808+18091809+ hash_pointers=18101810+ [KNL,EARLY]18111811+ By default, when pointers are printed to the console18121812+ or buffers via the %p format string, that pointer is18131813+ "hashed", i.e. obscured by hashing the pointer value.18141814+ This is a security feature that hides actual kernel18151815+ addresses from unprivileged users, but it also makes18161816+ debugging the kernel more difficult since unequal18171817+ pointers can no longer be compared. The choices are:18181818+ Format: { auto | always | never }18191819+ Default: auto18201820+18211821+ auto - Hash pointers unless slab_debug is enabled.18221822+ always - Always hash pointers (even if slab_debug is18231823+ enabled).18241824+ never - Never hash pointers. This option should only18251825+ be specified when debugging the kernel. Do18261826+ not use on production kernels. The boot18271827+ param "no_hash_pointers" is an alias for18281828+ this mode.1830182918311830 hashdist= [KNL,NUMA] Large hashes allocated during boot18321831 are distributed across NUMA nodes. Defaults on···4237419442384195 no_hash_pointers42394196 [KNL,EARLY]42404240- Force pointers printed to the console or buffers to be42414241- unhashed. By default, when a pointer is printed via %p42424242- format string, that pointer is "hashed", i.e. obscured42434243- by hashing the pointer value. This is a security feature42444244- that hides actual kernel addresses from unprivileged42454245- users, but it also makes debugging the kernel more42464246- difficult since unequal pointers can no longer be42474247- compared. However, if this command-line option is42484248- specified, then all normal pointers will have their true42494249- value printed. This option should only be specified when42504250- debugging the kernel. Please do not use on production42514251- kernels.41974197+ Alias for "hash_pointers=never".4252419842534199 nohibernate [HIBERNATION] Disable hibernation and resume.42544200···45894557 bit 2: print timer info45904558 bit 3: print locks info if CONFIG_LOCKDEP is on45914559 bit 4: print ftrace buffer45924592- bit 5: print all printk messages in buffer45604560+ bit 5: replay all messages on consoles at the end of panic45934561 bit 6: print all CPUs backtrace (if available in the arch)45944562 bit 7: print only tasks in uninterruptible (blocked) state45954563 *Be aware* that this option may print a _lot_ of lines,45964564 so there are risks of losing older messages in the log.45974565 Use this option carefully, maybe worth to setup a45984566 bigger log buffer with "log_buf_len" along with this.45674567+45684568+ panic_sys_info= A comma separated list of extra information to be dumped45694569+ on panic.45704570+ Format: val[,val...]45714571+ Where @val can be any of the following:45724572+45734573+ tasks: print all tasks info45744574+ mem: print system memory info45754575+ timers: print timers info45764576+ locks: print locks info if CONFIG_LOCKDEP is on45774577+ ftrace: print ftrace buffer45784578+ all_bt: print all CPUs backtrace (if available in the arch)45794579+ blocked_tasks: print only tasks in uninterruptible (blocked) state45804580+45814581+ This is a human readable alternative to the 'panic_print' option.45824582+45834583+ panic_console_replay45844584+ When panic happens, replay all kernel messages on45854585+ consoles at the end of panic.4599458646004587 parkbd.port= [HW] Parallel port number the keyboard adapter is46014588 connected to, default is 0.···66546603 Documentation/admin-guide/mm/slab.rst.66556604 (slub_debug legacy name also accepted for now)6656660566066606+ Using this option implies the "no_hash_pointers"66076607+ option which can be undone by adding the66086608+ "hash_pointers=always" option.66096609+66576610 slab_max_order= [MM]66586611 Determines the maximum allowed order for slabs.66596612 A high setting may cause OOMs due to memory···70867031 disable the stack depot thereby saving the static memory70877032 consumed by the stack hash table. By default this is set70887033 to false.70347034+70357035+ stack_depot_max_pools= [KNL,EARLY]70367036+ Specify the maximum number of pools to use for storing70377037+ stack traces. Pools are allocated on-demand up to this70387038+ limit. Default value is 8191 pools.7089703970907040 stacktrace [FTRACE]70917041 Enabled the stack tracer on boot up.
+19-1
Documentation/admin-guide/sysctl/kernel.rst
···890890bit 2 print timer info891891bit 3 print locks info if ``CONFIG_LOCKDEP`` is on892892bit 4 print ftrace buffer893893-bit 5 print all printk messages in buffer893893+bit 5 replay all messages on consoles at the end of panic894894bit 6 print all CPUs backtrace (if available in the arch)895895bit 7 print only tasks in uninterruptible (blocked) state896896===== ============================================···898898So for example to print tasks and memory info on panic, user can::899899900900 echo 3 > /proc/sys/kernel/panic_print901901+902902+903903+panic_sys_info904904+==============905905+906906+A comma separated list of extra information to be dumped on panic,907907+for example, "tasks,mem,timers,...". It is a human readable alternative908908+to 'panic_print'. Possible values are:909909+910910+============= ===================================================911911+tasks print all tasks info912912+mem print system memory info913913+timer print timers info914914+lock print locks info if CONFIG_LOCKDEP is on915915+ftrace print ftrace buffer916916+all_bt print all CPUs backtrace (if available in the arch)917917+blocked_tasks print only tasks in uninterruptible (blocked) state918918+============= ===================================================901919902920903921panic_on_rcu_stall
···11+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)22+%YAML 1.233+---44+$id: http://devicetree.org/schemas/input/touchscreen/ti.tsc2007.yaml#55+$schema: http://devicetree.org/meta-schemas/core.yaml#66+77+title: Texas Instruments tsc2007 touchscreen controller88+99+maintainers:1010+ - Frank Li <Frank.Li@nxp.com>1111+1212+properties:1313+ compatible:1414+ const: ti,tsc20071515+1616+ reg:1717+ maxItems: 11818+1919+ interrupts:2020+ maxItems: 12121+2222+ ti,x-plate-ohms:2323+ description: X-plate resistance in ohms.2424+2525+ gpios: true2626+2727+ pendown-gpio: true2828+2929+ ti,max-rt:3030+ $ref: /schemas/types.yaml#/definitions/uint323131+ description: maximum pressure.3232+3333+ ti,fuzzx:3434+ $ref: /schemas/types.yaml#/definitions/uint323535+ description:3636+ specifies the absolute input fuzz x value.3737+ If set, it will permit noise in the data up to +- the value given to the fuzz3838+ parameter, that is used to filter noise from the event stream.3939+4040+ ti,fuzzy:4141+ $ref: /schemas/types.yaml#/definitions/uint324242+ description: specifies the absolute input fuzz y value.4343+4444+ ti,fuzzz:4545+ $ref: /schemas/types.yaml#/definitions/uint324646+ description: specifies the absolute input fuzz z value.4747+4848+ ti,poll-period:4949+ $ref: /schemas/types.yaml#/definitions/uint325050+ description:5151+ how much time to wait (in milliseconds) before reading again the5252+ values from the tsc2007.5353+5454+required:5555+ - compatible5656+ - reg5757+ - ti,x-plate-ohms5858+5959+additionalProperties: false6060+6161+examples:6262+ - |6363+ i2c {6464+ #address-cells = <1>;6565+ #size-cells = <0>;6666+6767+ touch@49 {6868+ compatible = "ti,tsc2007";6969+ reg = <0x49>;7070+ interrupt-parent = <&gpio4>;7171+ interrupts = <0x0 0x8>;7272+ gpios = <&gpio4 0 0>;7373+ ti,x-plate-ohms = <180>;7474+ };7575+ };
···8787 touchscreen-y-plate-ohms:8888 description: Resistance of the Y-plate in Ohms89899090+ touch-overlay:9191+ description: |9292+ List of nodes defining segments (touch areas) on the touchscreen.9393+9494+ This object can be used to describe a series of segments to restrict9595+ the region within touch events are reported or buttons with a specific9696+ functionality.9797+9898+ This is of special interest if the touchscreen is shipped with a physical9999+ overlay on top of it with a frame that hides some part of the original100100+ touchscreen area. Printed buttons on that overlay are also a typical101101+ use case.102102+103103+ A new touchscreen area is defined as a sub-node without a key code. If a104104+ key code is defined in the sub-node, it will be interpreted as a button.105105+106106+ The x-origin and y-origin properties of a touchscreen area define the107107+ offset of a new origin from where the touchscreen events are referenced.108108+ This offset is applied to the events accordingly. The x-size and y-size109109+ properties define the size of the touchscreen effective area.110110+111111+ The following example shows a new touchscreen area with the new origin112112+ (0',0') for the touch events generated by the device.113113+114114+ Touchscreen (full area)115115+ ┌────────────────────────────────────────┐116116+ │ ┌───────────────────────────────┐ │117117+ │ │ │ │118118+ │ ├ y-size │ │119119+ │ │ │ │120120+ │ │ touchscreen area │ │121121+ │ │ (no key code) │ │122122+ │ │ │ │123123+ │ │ x-size │ │124124+ │ ┌└──────────────┴────────────────┘ │125125+ │(0',0') │126126+ ┌└────────────────────────────────────────┘127127+ (0,0)128128+129129+ where (0',0') = (0+x-origin,0+y-origin)130130+131131+ Sub-nodes with key codes report the touch events on their surface as key132132+ events instead.133133+134134+ The following example shows a touchscreen with a single button on it.135135+136136+ Touchscreen (full area)137137+ ┌───────────────────────────────────┐138138+ │ │139139+ │ │140140+ │ ┌─────────┐ │141141+ │ │button 0 │ │142142+ │ │KEY_POWER│ │143143+ │ └─────────┘ │144144+ │ │145145+ │ │146146+ ┌└───────────────────────────────────┘147147+ (0,0)148148+149149+ Segments defining buttons and clipped toushcreen areas can be combined150150+ as shown in the following example.151151+ In that case only the events within the touchscreen area are reported152152+ as touch events. Events within the button areas report their associated153153+ key code. Any events outside the defined areas are ignored.154154+155155+ Touchscreen (full area)156156+ ┌─────────┬──────────────────────────────┐157157+ │ │ │158158+ │ │ ┌───────────────────────┐ │159159+ │ button 0│ │ │ │160160+ │KEY_POWER│ │ │ │161161+ │ │ │ │ │162162+ ├─────────┤ │ touchscreen area │ │163163+ │ │ │ (no key code) │ │164164+ │ │ │ │ │165165+ │ button 1│ │ │ │166166+ │ KEY_INFO│ ┌└───────────────────────┘ │167167+ │ │(0',0') │168168+ ┌└─────────┴──────────────────────────────┘169169+ (0,0)170170+171171+ type: object172172+173173+ patternProperties:174174+ '^segment-':175175+ type: object176176+ description:177177+ Each segment is represented as a sub-node.178178+ properties:179179+ x-origin:180180+ description: horizontal origin of the node area181181+ $ref: /schemas/types.yaml#/definitions/uint32182182+183183+ y-origin:184184+ description: vertical origin of the node area185185+ $ref: /schemas/types.yaml#/definitions/uint32186186+187187+ x-size:188188+ description: horizontal resolution of the node area189189+ $ref: /schemas/types.yaml#/definitions/uint32190190+191191+ y-size:192192+ description: vertical resolution of the node area193193+ $ref: /schemas/types.yaml#/definitions/uint32194194+195195+ label:196196+ description: descriptive name of the segment197197+ $ref: /schemas/types.yaml#/definitions/string198198+199199+ linux,code: true200200+201201+ required:202202+ - x-origin203203+ - y-origin204204+ - x-size205205+ - y-size206206+207207+ unevaluatedProperties: false208208+90209dependencies:91210 touchscreen-size-x: [ touchscreen-size-y ]92211 touchscreen-size-y: [ touchscreen-size-x ]
···11-* Texas Instruments tsc2007 touchscreen controller22-33-Required properties:44-- compatible: must be "ti,tsc2007".55-- reg: I2C address of the chip.66-- ti,x-plate-ohms: X-plate resistance in ohms.77-88-Optional properties:99-- gpios: the interrupt gpio the chip is connected to (through the penirq pin).1010- The penirq pin goes to low when the panel is touched.1111- (see GPIO binding[1] for more details).1212-- interrupts: (gpio) interrupt to which the chip is connected1313- (see interrupt binding[0]).1414-- ti,max-rt: maximum pressure.1515-- ti,fuzzx: specifies the absolute input fuzz x value.1616- If set, it will permit noise in the data up to +- the value given to the fuzz1717- parameter, that is used to filter noise from the event stream.1818-- ti,fuzzy: specifies the absolute input fuzz y value.1919-- ti,fuzzz: specifies the absolute input fuzz z value.2020-- ti,poll-period: how much time to wait (in milliseconds) before reading again the2121- values from the tsc2007.2222-2323-[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt2424-[1]: Documentation/devicetree/bindings/gpio/gpio.txt2525-2626-Example:2727- &i2c1 {2828- /* ... */2929- tsc2007@49 {3030- compatible = "ti,tsc2007";3131- reg = <0x49>;3232- interrupt-parent = <&gpio4>;3333- interrupts = <0x0 0x8>;3434- gpios = <&gpio4 0 0>;3535- ti,x-plate-ohms = <180>;3636- };3737-3838- /* ... */3939- };
···6363 - microcrystal,rv30296464 # Real Time Clock6565 - microcrystal,rv85236666- # NXP LPC32xx SoC Real-time Clock6767- - nxp,lpc3220-rtc6866 # I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC6967 - ricoh,r2025sd7068 # I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
···11# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)22%YAML 1.233---44-$id: http://devicetree.org/schemas/sophgo/sophgo,cv1800b-rtc.yaml#44+$id: http://devicetree.org/schemas/rtc/sophgo,cv1800b-rtc.yaml#55$schema: http://devicetree.org/meta-schemas/core.yaml#6677title: Real Time Clock of the Sophgo CV1800 SoC
···238238grpjquota=<file> information can be properly updated during recovery flow,239239prjjquota=<file> <quota file>: must be in root directory;240240jqfmt=<quota type> <quota type>: [vfsold,vfsv0,vfsv1].241241-offusrjquota Turn off user journalled quota.242242-offgrpjquota Turn off group journalled quota.243243-offprjjquota Turn off project journalled quota.241241+usrjquota= Turn off user journalled quota.242242+grpjquota= Turn off group journalled quota.243243+prjjquota= Turn off project journalled quota.244244quota Enable plain user disk quota accounting.245245noquota Disable all plain disk quota option.246246alloc_mode=%s Adjust block allocation policy, which supports "reuse"
+19-2
Documentation/input/devices/edt-ft5x06.rst
···292930303131For debugging purposes the driver provides a few files in the debug3232-filesystem (if available in the kernel). In /sys/kernel/debug/edt_ft5x063333-you'll find the following files:3232+filesystem (if available in the kernel). They are located in:3333+3434+ /sys/kernel/debug/i2c/<i2c-bus>/<i2c-device>/3535+3636+If you don't know the bus and device numbers, you can look them up with this3737+command:3838+3939+ $ ls -l /sys/bus/i2c/drivers/edt_ft5x064040+4141+The dereference of the symlink will contain the needed information. You will4242+need the last two elements of its path:4343+4444+ 0-0038 -> ../../../../devices/platform/soc/fcfee800.i2c/i2c-0/0-00384545+4646+So in this case, the location for the debug files is:4747+4848+ /sys/kernel/debug/i2c/i2c-0/0-0038/4949+5050+There, you'll find the following files:34513552num_x, num_y:3653 (readonly) contains the number of sensor fields in X- and
+16-3
Documentation/input/gamepad.rst
···190190191191 Rumble is advertised as FF_RUMBLE.192192193193+- Grip buttons:194194+195195+ Many pads include buttons on the rear, usually referred to as either grip or196196+ rear buttons, or paddles. These are often reprogrammable by the firmware to197197+ appear as "normal" buttons, but are sometimes exposed to software too. Some198198+ notable examples of this are the Steam Deck, which has R4, R5, L4, and L5 on199199+ the back; the Xbox Elite pads, which have P1-P4; and the Switch 2 Pro200200+ Controller, which has GL and GR.201201+202202+ For these controllers, BTN_GRIPR and BTN_GRIPR2 should be used for the top203203+ and bottom (if present) right grip button(s), and BTN_GRIPL and BTN_GRIPL2204204+ should be used for the top and bottom (if present) left grip button(s).205205+193206- Profile:194207195195- Some pads provide a multi-value profile selection switch. An example is the196196- XBox Adaptive and the XBox Elite 2 controllers. When the active profile is197197- switched, its newly selected value is emitted as an ABS_PROFILE event.208208+ Some pads provide a multi-value profile selection switch. Examples include209209+ the Xbox Adaptive and the Xbox Elite 2 controllers. When the active profile210210+ is switched, its newly selected value is emitted as an ABS_PROFILE event.
+4-4
Documentation/kbuild/kconfig.rst
···6767 with its value when saving the configuration, instead of using the6868 default, ``CONFIG_``.69697070-Environment variables for ``{allyes/allmod/allno/rand}config``:7070+Environment variables for ``{allyes/allmod/allno/alldef/rand}config``:71717272``KCONFIG_ALLCONFIG``7373- The allyesconfig/allmodconfig/allnoconfig/randconfig variants can also7474- use the environment variable KCONFIG_ALLCONFIG as a flag or a filename7575- that contains config symbols that the user requires to be set to a7373+ The allyesconfig/allmodconfig/alldefconfig/allnoconfig/randconfig variants7474+ can also use the environment variable KCONFIG_ALLCONFIG as a flag or a7575+ filename that contains config symbols that the user requires to be set to a7676 specific value. If KCONFIG_ALLCONFIG is used without a filename where7777 KCONFIG_ALLCONFIG == "" or KCONFIG_ALLCONFIG == "1", ``make *config``7878 checks for a file named "all{yes/mod/no/def/random}.config"
···449449xbox-dvd (RC_PROTO_XBOX_DVD)450450----------------------------451451452452-This protocol is used by XBox DVD Remote, which was made for the original453453-XBox. There is no in-kernel decoder or encoder for this protocol. The usb452452+This protocol is used by Xbox DVD Remote, which was made for the original453453+Xbox. There is no in-kernel decoder or encoder for this protocol. The usb454454device decodes the protocol. There is a BPF decoder available in v4l-utils.
+38-11
MAINTAINERS
···67136713F: drivers/input/keyboard/dlink-dir685-touchkeys.c6714671467156715DALLAS/MAXIM DS1685-FAMILY REAL TIME CLOCK67166716-M: Joshua Kinard <kumba@gentoo.org>67166716+M: Joshua Kinard <linux@kumba.dev>67176717S: Maintained67186718F: drivers/rtc/rtc-ds1685.c67196719F: include/linux/rtc/ds1685.h···1110011100F: drivers/infiniband/hw/hns/11101111011110211102HISILICON SAS Controller1110311103-M: Yihang Li <liyihang9@huawei.com>1110311103+M: Yihang Li <liyihang9@h-partners.com>1110411104S: Supported1110511105W: http://www.hisilicon.com1110611106F: Documentation/devicetree/bindings/scsi/hisilicon-sas.txt···1161211612F: Documentation/devicetree/bindings/i3c/cdns,i3c-master.yaml1161311613F: drivers/i3c/master/i3c-master-cdns.c11614116141161511615+I3C DRIVER FOR RENESAS1161611616+M: Wolfram Sang <wsa+renesas@sang-engineering.com>1161711617+M: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>1161811618+S: Supported1161911619+F: Documentation/devicetree/bindings/i3c/renesas,i3c.yaml1162011620+F: drivers/i3c/master/renesas-i3c.c1162111621+1161511622I3C DRIVER FOR SYNOPSYS DESIGNWARE1161611623S: Orphan1161711624F: Documentation/devicetree/bindings/i3c/snps,dw-i3c-master.yaml···1162911622R: Frank Li <Frank.Li@nxp.com>1163011623L: linux-i3c@lists.infradead.org (moderated for non-subscribers)1163111624S: Maintained1162511625+Q: https://patchwork.kernel.org/project/linux-i3c/list/1163211626C: irc://chat.freenode.net/linux-i3c1163311627T: git git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux.git1163411628F: Documentation/ABI/testing/sysfs-bus-i3c···1317413166F: scripts/Makefile.kasan13175131671317613168KCONFIG1317713177-M: Masahiro Yamada <masahiroy@kernel.org>1317813169L: linux-kbuild@vger.kernel.org1317913179-S: Maintained1317013170+S: Orphan1318013171Q: https://patchwork.kernel.org/project/linux-kbuild/list/1318113181-T: git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git kbuild1318213172F: Documentation/kbuild/kconfig*1318313173F: scripts/Kconfig.include1318413174F: scripts/kconfig/···1324113235F: fs/autofs/13242132361324313237KERNEL BUILD + files below scripts/ (unless maintained elsewhere)1324413244-M: Masahiro Yamada <masahiroy@kernel.org>1324513245-R: Nathan Chancellor <nathan@kernel.org>1324613246-R: Nicolas Schier <nicolas@fjasle.eu>1323813238+M: Nathan Chancellor <nathan@kernel.org>1323913239+M: Nicolas Schier <nicolas@fjasle.eu>1324713240L: linux-kbuild@vger.kernel.org1324813248-S: Maintained1324113241+S: Odd Fixes1324913242Q: https://patchwork.kernel.org/project/linux-kbuild/list/1325013250-T: git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git1324313243+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kbuild/linux.git1325113244F: Documentation/kbuild/1325213245F: Makefile1325313246F: scripts/*vmlinux*···1354113536F: Documentation/core-api/kho/*1354213537F: include/linux/kexec_handover.h1354313538F: kernel/kexec_handover.c1353913539+F: tools/testing/selftests/kho/13544135401354513541KEYS-ENCRYPTED1354613542M: Mimi Zohar <zohar@linux.ibm.com>···1973919733F: include/linux/delayacct.h1974019734F: kernel/delayacct.c19741197351973619736+TASK DELAY MONITORING TOOLS1973719737+M: Andrew Morton <akpm@linux-foundation.org>1973819738+M: Wang Yaxin <wang.yaxin@zte.com.cn>1973919739+M: Fan Yu <fan.yu9@zte.com.cn>1974019740+L: linux-kernel@vger.kernel.org1974119741+S: Maintained1974219742+F: Documentation/accounting/delay-accounting.rst1974319743+F: tools/accounting/delaytop.c1974419744+F: tools/accounting/getdelays.c1974519745+1974219746PERFORMANCE EVENTS SUBSYSTEM1974319747M: Peter Zijlstra <peterz@infradead.org>1974419748M: Ingo Molnar <mingo@redhat.com>···22048220322204922033RUST [ALLOC]2205022034M: Danilo Krummrich <dakr@kernel.org>2203522035+R: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>2203622036+R: Vlastimil Babka <vbabka@suse.cz>2203722037+R: Liam R. Howlett <Liam.Howlett@oracle.com>2203822038+R: Uladzislau Rezki <urezki@gmail.com>2205122039L: rust-for-linux@vger.kernel.org2205222040S: Maintained2205322041T: git https://github.com/Rust-for-Linux/linux.git alloc-next···2339023370F: drivers/md/raid*2339123371F: include/linux/raid/2339223372F: include/uapi/linux/raid/2337323373+F: lib/raid6/23393233742339423375SOLIDRUN CLEARFOG SUPPORT2339523376M: Russell King <linux@armlinux.org.uk>···2549925478S: Maintained2550025479F: drivers/platform/x86/toshiba-wmi.c25501254802548125481+TOUCH OVERLAY2548225482+M: Javier Carrasco <javier.carrasco@wolfvision.net>2548325483+L: linux-input@vger.kernel.org2548425484+S: Maintained2548525485+F: drivers/input/touch-overlay.c2548625486+F: include/linux/input/touch-overlay.h2548725487+2550225488TPM DEVICE DRIVER2550325489M: Peter Huewe <peterhuewe@gmx.de>2550425490M: Jarkko Sakkinen <jarkko@kernel.org>···2646226434F: drivers/vfio/platform/26463264352646426436VFIO QAT PCI DRIVER2646526465-M: Xin Zeng <xin.zeng@intel.com>2646626437M: Giovanni Cabiddu <giovanni.cabiddu@intel.com>2646726438L: kvm@vger.kernel.org2646826439L: qat-linux@intel.com
···2727 * they share a cacheline (not done yet, though... future optimization).2828 */29293030-#ifndef __ASSEMBLY__3030+#ifndef __ASSEMBLER__3131/*3232 * This struct describes how the registers are laid out on the kernel stack3333 * during a syscall or other kernel entry.···147147 return *(unsigned long *)((unsigned long)regs + offset);148148}149149150150-#endif /* __ASSEMBLY__ */150150+#endif /* __ASSEMBLER__ */151151152152/*153153 * Offsets used by 'ptrace' system call interface.
···17171818#ifdef __KERNEL__19192020-#ifndef __ASSEMBLY__2020+#ifndef __ASSEMBLER__2121#include <asm/types.h>2222#include <asm/processor.h>2323#endif···3838 * - if the contents of this structure are changed, the assembly constants3939 * must also be changed4040 */4141-#ifndef __ASSEMBLY__4141+#ifndef __ASSEMBLER__42424343struct thread_info {4444 struct task_struct *task; /* main task structure */···5858 *5959 * preempt_count needs to be 1 initially, until the scheduler is functional.6060 */6161-#ifndef __ASSEMBLY__6161+#ifndef __ASSEMBLER__6262#define INIT_THREAD_INFO(tsk) \6363{ \6464 .task = &tsk, \···7575#define get_thread_info(ti) get_task_struct((ti)->task)7676#define put_thread_info(ti) put_task_struct((ti)->task)77777878-#endif /* !__ASSEMBLY__ */7878+#endif /* !__ASSEMBLER__ */79798080/*8181 * thread information flags
+1-1
arch/openrisc/include/uapi/asm/ptrace.h
···2020#ifndef _UAPI__ASM_OPENRISC_PTRACE_H2121#define _UAPI__ASM_OPENRISC_PTRACE_H22222323-#ifndef __ASSEMBLY__2323+#ifndef __ASSEMBLER__2424/*2525 * This is the layout of the regset returned by the GETREGSET ptrace call2626 */
+1
arch/powerpc/include/asm/ppc-opcode.h
···425425#define PPC_RAW_SC() (0x44000002)426426#define PPC_RAW_SYNC() (0x7c0004ac)427427#define PPC_RAW_ISYNC() (0x4c00012c)428428+#define PPC_RAW_LWSYNC() (0x7c2004ac)428429429430/*430431 * Define what the VSX XX1 form instructions will look like, then add
···257257 struct pci_driver *driver;258258 enum pci_ers_result new_result;259259260260- pci_lock_rescan_remove();261260 pdev = edev->pdev;262261 if (pdev)263262 get_device(&pdev->dev);264264- pci_unlock_rescan_remove();265263 if (!pdev) {266264 eeh_edev_info(edev, "no device");265265+ *result = PCI_ERS_RESULT_DISCONNECT;267266 return;268267 }269268 device_lock(&pdev->dev);···303304 struct eeh_dev *edev, *tmp;304305305306 pr_info("EEH: Beginning: '%s'\n", name);306306- eeh_for_each_pe(root, pe) eeh_pe_for_each_dev(pe, edev, tmp)307307- eeh_pe_report_edev(edev, fn, result);307307+ eeh_for_each_pe(root, pe)308308+ eeh_pe_for_each_dev(pe, edev, tmp)309309+ eeh_pe_report_edev(edev, fn, result);308310 if (result)309311 pr_info("EEH: Finished:'%s' with aggregate recovery state:'%s'\n",310312 name, pci_ers_result_name(*result));···383383 if (!edev)384384 return;385385386386+ pci_lock_rescan_remove();387387+386388 /*387389 * The content in the config space isn't saved because388390 * the blocked config space on some adapters. We have···395393 if (list_is_last(&edev->entry, &edev->pe->edevs))396394 eeh_pe_restore_bars(edev->pe);397395396396+ pci_unlock_rescan_remove();398397 return;399398 }400399401400 pdev = eeh_dev_to_pci_dev(edev);402402- if (!pdev)401401+ if (!pdev) {402402+ pci_unlock_rescan_remove();403403 return;404404+ }404405405406 pci_restore_state(pdev);407407+408408+ pci_unlock_rescan_remove();406409}407410408411/**···654647 if (any_passed || driver_eeh_aware || (pe->type & EEH_PE_VF)) {655648 eeh_pe_dev_traverse(pe, eeh_rmv_device, rmv_data);656649 } else {657657- pci_lock_rescan_remove();658650 pci_hp_remove_devices(bus);659659- pci_unlock_rescan_remove();660651 }661652662653 /*···670665 if (rc)671666 return rc;672667673673- pci_lock_rescan_remove();674674-675668 /* Restore PE */676669 eeh_ops->configure_bridge(pe);677670 eeh_pe_restore_bars(pe);···677674 /* Clear frozen state */678675 rc = eeh_clear_pe_frozen_state(pe, false);679676 if (rc) {680680- pci_unlock_rescan_remove();681677 return rc;682678 }683679···711709 pe->tstamp = tstamp;712710 pe->freeze_count = cnt;713711714714- pci_unlock_rescan_remove();715712 return 0;716713}717714···844843 {LIST_HEAD_INIT(rmv_data.removed_vf_list), 0};845844 int devices = 0;846845846846+ pci_lock_rescan_remove();847847+847848 bus = eeh_pe_bus_get(pe);848849 if (!bus) {849850 pr_err("%s: Cannot find PCI bus for PHB#%x-PE#%x\n",850851 __func__, pe->phb->global_number, pe->addr);852852+ pci_unlock_rescan_remove();851853 return;852854 }853855···10981094 eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);10991095 eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);1100109611011101- pci_lock_rescan_remove();11021102- pci_hp_remove_devices(bus);11031103- pci_unlock_rescan_remove();10971097+ bus = eeh_pe_bus_get(pe);10981098+ if (bus)10991099+ pci_hp_remove_devices(bus);11001100+ else11011101+ pr_err("%s: PCI bus for PHB#%x-PE#%x disappeared\n",11021102+ __func__, pe->phb->global_number, pe->addr);11031103+11041104 /* The passed PE should no longer be used */11051105+ pci_unlock_rescan_remove();11051106 return;11061107 }11071108···11231114 eeh_clear_slot_attention(edev->pdev);1124111511251116 eeh_pe_state_clear(pe, EEH_PE_RECOVERING, true);11171117+11181118+ pci_unlock_rescan_remove();11261119}1127112011281121/**···11431132 unsigned long flags;11441133 int rc;1145113411351135+ pci_lock_rescan_remove();1146113611471137 do {11481138 rc = eeh_ops->next_error(&pe);···1183117111841172 break;11851173 case EEH_NEXT_ERR_NONE:11741174+ pci_unlock_rescan_remove();11861175 return;11871176 default:11881177 pr_warn("%s: Invalid value %d from next_error()\n",11891178 __func__, rc);11791179+ pci_unlock_rescan_remove();11901180 return;11911181 }11921182···12001186 if (rc == EEH_NEXT_ERR_FROZEN_PE ||12011187 rc == EEH_NEXT_ERR_FENCED_PHB) {12021188 eeh_pe_state_mark(pe, EEH_PE_RECOVERING);11891189+ pci_unlock_rescan_remove();12031190 eeh_handle_normal_event(pe);11911191+ pci_lock_rescan_remove();12041192 } else {12051193 eeh_for_each_pe(pe, tmp_pe)12061194 eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)···12151199 eeh_report_failure, NULL);12161200 eeh_set_channel_state(pe, pci_channel_io_perm_failure);1217120112181218- pci_lock_rescan_remove();12191202 list_for_each_entry(hose, &hose_list, list_node) {12201203 phb_pe = eeh_phb_pe_get(hose);12211204 if (!phb_pe ||···12331218 }12341219 pci_hp_remove_devices(bus);12351220 }12361236- pci_unlock_rescan_remove();12371221 }1238122212391223 /*···12421228 if (rc == EEH_NEXT_ERR_DEAD_IOC)12431229 break;12441230 } while (rc != EEH_NEXT_ERR_NONE);12311231+12321232+ pci_unlock_rescan_remove();12451233}
+6-4
arch/powerpc/kernel/eeh_pe.c
···671671 eeh_ops->write_config(edev, cap + PCI_EXP_LNKCTL, 2, val);672672673673 /* Check link */674674- if (!edev->pdev->link_active_reporting) {675675- eeh_edev_dbg(edev, "No link reporting capability\n");676676- msleep(1000);677677- return;674674+ if (edev->pdev) {675675+ if (!edev->pdev->link_active_reporting) {676676+ eeh_edev_dbg(edev, "No link reporting capability\n");677677+ msleep(1000);678678+ return;679679+ }678680 }679681680682 /* Wait the link is up until timeout (5s) */
+1-1
arch/powerpc/kernel/fadump.c
···333333 * memory at a predefined offset.334334 */335335 ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),336336- &size, &base, NULL, NULL);336336+ &size, &base, NULL, NULL, NULL);337337 if (ret == 0 && size > 0) {338338 unsigned long max_size;339339
···163163 return NULL;164164165165 /*166166- * Exclusion of crash region and/or crashk_low_res may cause167167- * another range split. So add extra two slots here.166166+ * Exclusion of crash region, crashk_low_res and/or crashk_cma_ranges167167+ * may cause range splits. So add extra slots here.168168 */169169- nr_ranges += 2;169169+ nr_ranges += 2 + crashk_cma_cnt;170170 cmem = vzalloc(struct_size(cmem, ranges, nr_ranges));171171 if (!cmem)172172 return NULL;···184184static int elf_header_exclude_ranges(struct crash_mem *cmem)185185{186186 int ret = 0;187187+ int i;187188188189 /* Exclude the low 1M because it is always reserved */189190 ret = crash_exclude_mem_range(cmem, 0, SZ_1M - 1);···199198 if (crashk_low_res.end)200199 ret = crash_exclude_mem_range(cmem, crashk_low_res.start,201200 crashk_low_res.end);201201+ if (ret)202202+ return ret;202203203203- return ret;204204+ for (i = 0; i < crashk_cma_cnt; ++i) {205205+ ret = crash_exclude_mem_range(cmem, crashk_cma_ranges[i].start,206206+ crashk_cma_ranges[i].end);207207+ if (ret)208208+ return ret;209209+ }210210+211211+ return 0;204212}205213206214static int prepare_elf64_ram_headers_callback(struct resource *res, void *arg)···380370 if (ei.size < PAGE_SIZE)381371 continue;382372 ei.addr = cmem->ranges[i].start;373373+ ei.type = E820_TYPE_RAM;374374+ add_e820_entry(params, &ei);375375+ }376376+377377+ for (i = 0; i < crashk_cma_cnt; ++i) {378378+ ei.addr = crashk_cma_ranges[i].start;379379+ ei.size = crashk_cma_ranges[i].end -380380+ crashk_cma_ranges[i].start + 1;383381 ei.type = E820_TYPE_RAM;384382 add_e820_entry(params, &ei);385383 }
···481481 return len;482482}483483484484-/* Make page to RO mode when allocate it */485485-void *alloc_insn_page(void)486486-{487487- void *page;488488-489489- page = execmem_alloc(EXECMEM_KPROBES, PAGE_SIZE);490490- if (!page)491491- return NULL;492492-493493- /*494494- * TODO: Once additional kernel code protection mechanisms are set, ensure495495- * that the page was not maliciously altered and it is still zeroed.496496- */497497- set_memory_rox((unsigned long)page, 1);498498-499499- return page;500500-}501501-502484/* Kprobe x86 instruction emulation - only regs->ip or IF flag modifiers */503485504486static void kprobe_emulate_ifmodifiers(struct kprobe *p, struct pt_regs *regs)
+3-2
arch/x86/kernel/setup.c
···603603604604static void __init arch_reserve_crashkernel(void)605605{606606- unsigned long long crash_base, crash_size, low_size = 0;606606+ unsigned long long crash_base, crash_size, low_size = 0, cma_size = 0;607607 bool high = false;608608 int ret;609609···612612613613 ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),614614 &crash_size, &crash_base,615615- &low_size, &high);615615+ &low_size, &cma_size, &high);616616 if (ret)617617 return;618618···622622 }623623624624 reserve_crashkernel_generic(crash_size, crash_base, low_size, high);625625+ reserve_crashkernel_cma(cma_size);625626}626627627628static struct resource standard_io_resources[] = {
···46024602 return AC_ERR_INVALID;4603460346044604 /* set up init dev params taskfile */46054605- ata_dev_dbg(dev, "init dev params \n");46054605+ ata_dev_dbg(dev, "init dev params\n");4606460646074607 ata_tf_init(dev, &tf);46084608 tf.command = ATA_CMD_INIT_DEV_PARAMS;
+41-12
drivers/ata/libata-sata.c
···900900 [ATA_LPM_MIN_POWER] = "min_power",901901};902902903903+/*904904+ * Check if a port supports link power management.905905+ * Must be called with the port locked.906906+ */907907+static bool ata_scsi_lpm_supported(struct ata_port *ap)908908+{909909+ struct ata_link *link;910910+ struct ata_device *dev;911911+912912+ if (ap->flags & ATA_FLAG_NO_LPM)913913+ return false;914914+915915+ ata_for_each_link(link, ap, EDGE) {916916+ ata_for_each_dev(dev, &ap->link, ENABLED) {917917+ if (dev->quirks & ATA_QUIRK_NOLPM)918918+ return false;919919+ }920920+ }921921+922922+ return true;923923+}924924+925925+static ssize_t ata_scsi_lpm_supported_show(struct device *dev,926926+ struct device_attribute *attr, char *buf)927927+{928928+ struct Scsi_Host *shost = class_to_shost(dev);929929+ struct ata_port *ap = ata_shost_to_port(shost);930930+ unsigned long flags;931931+ bool supported;932932+933933+ spin_lock_irqsave(ap->lock, flags);934934+ supported = ata_scsi_lpm_supported(ap);935935+ spin_unlock_irqrestore(ap->lock, flags);936936+937937+ return sysfs_emit(buf, "%d\n", supported);938938+}939939+DEVICE_ATTR(link_power_management_supported, S_IRUGO,940940+ ata_scsi_lpm_supported_show, NULL);941941+EXPORT_SYMBOL_GPL(dev_attr_link_power_management_supported);942942+903943static ssize_t ata_scsi_lpm_store(struct device *device,904944 struct device_attribute *attr,905945 const char *buf, size_t count)906946{907947 struct Scsi_Host *shost = class_to_shost(device);908948 struct ata_port *ap = ata_shost_to_port(shost);909909- struct ata_link *link;910910- struct ata_device *dev;911949 enum ata_lpm_policy policy;912950 unsigned long flags;913951···962924963925 spin_lock_irqsave(ap->lock, flags);964926965965- if (ap->flags & ATA_FLAG_NO_LPM) {927927+ if (!ata_scsi_lpm_supported(ap)) {966928 count = -EOPNOTSUPP;967929 goto out_unlock;968968- }969969-970970- ata_for_each_link(link, ap, EDGE) {971971- ata_for_each_dev(dev, &ap->link, ENABLED) {972972- if (dev->quirks & ATA_QUIRK_NOLPM) {973973- count = -EOPNOTSUPP;974974- goto out_unlock;975975- }976976- }977930 }978931979932 ap->target_lpm_policy = policy;
+19-19
drivers/ata/libata-scsi.c
···859859 {0xFF, 0xFF, 0xFF, 0xFF}, // END mark860860 };861861 static const unsigned char stat_table[][4] = {862862- /* Must be first because BUSY means no other bits valid */863863- {0x80, ABORTED_COMMAND, 0x47, 0x00},864864- // Busy, fake parity for now865865- {0x40, ILLEGAL_REQUEST, 0x21, 0x04},866866- // Device ready, unaligned write command867867- {0x20, HARDWARE_ERROR, 0x44, 0x00},868868- // Device fault, internal target failure869869- {0x08, ABORTED_COMMAND, 0x47, 0x00},870870- // Timed out in xfer, fake parity for now871871- {0x04, RECOVERED_ERROR, 0x11, 0x00},872872- // Recovered ECC error Medium error, recovered873873- {0xFF, 0xFF, 0xFF, 0xFF}, // END mark862862+ /* Busy: must be first because BUSY means no other bits valid */863863+ { ATA_BUSY, ABORTED_COMMAND, 0x00, 0x00 },864864+ /* Device fault: INTERNAL TARGET FAILURE */865865+ { ATA_DF, HARDWARE_ERROR, 0x44, 0x00 },866866+ /* Corrected data error */867867+ { ATA_CORR, RECOVERED_ERROR, 0x00, 0x00 },868868+869869+ { 0xFF, 0xFF, 0xFF, 0xFF }, /* END mark */874870 };875871876872 /*···938942 if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {939943 ata_dev_dbg(dev,940944 "missing result TF: can't generate ATA PT sense data\n");945945+ if (qc->err_mask)946946+ ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0);941947 return;942948 }943949···994996995997 if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {996998 ata_dev_dbg(dev,997997- "missing result TF: can't generate sense data\n");998998- return;999999+ "Missing result TF: reporting aborted command\n");10001000+ goto aborted;9991001 }1000100210011003 /* Use ata_to_sense_error() to map status register bits···10061008 ata_to_sense_error(tf->status, tf->error,10071009 &sense_key, &asc, &ascq);10081010 ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq);10091009- } else {10101010- /* Could not decode error */10111011- ata_dev_warn(dev, "could not decode error status 0x%x err_mask 0x%x\n",10121012- tf->status, qc->err_mask);10131013- ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0);10141011 return;10151012 }10131013+10141014+ /* Could not decode error */10151015+ ata_dev_warn(dev,10161016+ "Could not decode error 0x%x, status 0x%x (err_mask=0x%x)\n",10171017+ tf->error, tf->status, qc->err_mask);10181018+aborted:10191019+ ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0);10161020}1017102110181022void ata_scsi_sdev_config(struct scsi_device *sdev)
+1-1
drivers/ata/pata_macio.c
···758758759759static void pata_macio_reset_hw(struct pata_macio_priv *priv, int resume)760760{761761- dev_dbg(priv->dev, "Enabling & resetting... \n");761761+ dev_dbg(priv->dev, "Enabling & resetting...\n");762762763763 if (priv->mediabay)764764 return;
+6-6
drivers/ata/pata_pdc2027x.c
···295295 }296296297297 /* Set the PIO timing registers using value table for 133MHz */298298- ata_port_dbg(ap, "Set pio regs... \n");298298+ ata_port_dbg(ap, "Set PIO regs...\n");299299300300 ctcr0 = ioread32(dev_mmio(ap, adev, PDC_CTCR0));301301 ctcr0 &= 0xffff0000;···308308 ctcr1 |= (pdc2027x_pio_timing_tbl[pio].value2 << 24);309309 iowrite32(ctcr1, dev_mmio(ap, adev, PDC_CTCR1));310310311311- ata_port_dbg(ap, "Set to pio mode[%u] \n", pio);311311+ ata_port_dbg(ap, "Set to PIO mode[%u]\n", pio);312312}313313314314/**···341341 iowrite32(ctcr1 & ~(1 << 7), dev_mmio(ap, adev, PDC_CTCR1));342342 }343343344344- ata_port_dbg(ap, "Set udma regs... \n");344344+ ata_port_dbg(ap, "Set UDMA regs...\n");345345346346 ctcr1 = ioread32(dev_mmio(ap, adev, PDC_CTCR1));347347 ctcr1 &= 0xff000000;···350350 (pdc2027x_udma_timing_tbl[udma_mode].value2 << 16);351351 iowrite32(ctcr1, dev_mmio(ap, adev, PDC_CTCR1));352352353353- ata_port_dbg(ap, "Set to udma mode[%u] \n", udma_mode);353353+ ata_port_dbg(ap, "Set to UDMA mode[%u]\n", udma_mode);354354355355 } else if ((dma_mode >= XFER_MW_DMA_0) &&356356 (dma_mode <= XFER_MW_DMA_2)) {357357 /* Set the MDMA timing registers with value table for 133MHz */358358 unsigned int mdma_mode = dma_mode & 0x07;359359360360- ata_port_dbg(ap, "Set mdma regs... \n");360360+ ata_port_dbg(ap, "Set MDMA regs...\n");361361 ctcr0 = ioread32(dev_mmio(ap, adev, PDC_CTCR0));362362363363 ctcr0 &= 0x0000ffff;···366366367367 iowrite32(ctcr0, dev_mmio(ap, adev, PDC_CTCR0));368368369369- ata_port_dbg(ap, "Set to mdma mode[%u] \n", mdma_mode);369369+ ata_port_dbg(ap, "Set to MDMA mode[%u]\n", mdma_mode);370370 } else {371371 ata_port_err(ap, "Unknown dma mode [%u] ignored\n", dma_mode);372372 }
+4-4
drivers/char/ipmi/ipmi_msghandler.c
···46074607 * The NetFN and Command in the response is not even46084608 * marginally correct.46094609 */46104610- dev_warn(intf->si_dev,46114611- "BMC returned incorrect response, expected netfn %x cmd %x, got netfn %x cmd %x\n",46124612- (msg->data[0] >> 2) | 1, msg->data[1],46134613- msg->rsp[0] >> 2, msg->rsp[1]);46104610+ dev_warn_ratelimited(intf->si_dev,46114611+ "BMC returned incorrect response, expected netfn %x cmd %x, got netfn %x cmd %x\n",46124612+ (msg->data[0] >> 2) | 1, msg->data[1],46134613+ msg->rsp[0] >> 2, msg->rsp[1]);4614461446154615 goto return_unspecified;46164616 }
···404404 let mut out = 0;405405 let mut exp = 1;406406 for i in 0..poplen {407407- out += self.decimals[self.len + i] as u16 * exp;407407+ out += u16::from(self.decimals[self.len + i]) * exp;408408 exp *= 10;409409 }410410 Some((out, NUM_CHARS_BITS[poplen]))···425425 match self.segment {426426 Segment::Binary(data) => {427427 if self.offset < data.len() {428428- let byte = data[self.offset] as u16;428428+ let byte = u16::from(data[self.offset]);429429 self.offset += 1;430430 Some((byte, 8))431431 } else {
+1-2
drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
···220220 */221221static int subbuf_start_callback(struct rchan_buf *buf,222222 void *subbuf,223223- void *prev_subbuf,224224- size_t prev_padding)223223+ void *prev_subbuf)225224{226225 /*227226 * Use no-overwrite mode by default, where relay will stop accepting
···266266 * up for revalidation. Protected from access with the267267 * @invalidated_lock. Removing items from the list268268 * additionally requires @lock in write mode, and adding269269- * items to the list requires either the @userptr.notifer_lock in269269+ * items to the list requires either the @userptr.notifier_lock in270270 * write mode, OR @lock in write mode.271271 */272272 struct list_head invalidated;
+1-1
drivers/gpu/nova-core/driver.rs
···1919 MODULE_PCI_TABLE,2020 <NovaCore as pci::Driver>::IdInfo,2121 [(2222- pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_NVIDIA, bindings::PCI_ANY_ID as _),2222+ pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_NVIDIA, bindings::PCI_ANY_ID as u32),2323 ()2424 )]2525);
···992992 tristate "Apple SMBus platform driver"993993 depends on !I2C_PASEMI994994 depends on ARCH_APPLE || COMPILE_TEST995995- default ARCH_APPLE996995 help997996 Say Y here if you want to use the I2C controller present on Apple998997 Silicon chips such as the M1.
···134134#define I2C_MST_FIFO_STATUS_TX GENMASK(23, 16)135135#define I2C_MST_FIFO_STATUS_RX GENMASK(7, 0)136136137137+#define I2C_MASTER_RESET_CNTRL 0x0a8138138+137139/* configuration load timeout in microseconds */138140#define I2C_CONFIG_LOAD_TIMEOUT 1000000139141···186184 * @has_mst_fifo: The I2C controller contains the new MST FIFO interface that187185 * provides additional features and allows for longer messages to188186 * be transferred in one go.187187+ * @has_mst_reset: The I2C controller contains MASTER_RESET_CTRL register which188188+ * provides an alternative to controller reset when configured as189189+ * I2C master189190 * @quirks: I2C adapter quirks for limiting write/read transfer size and not190191 * allowing 0 length transfers.191192 * @supports_bus_clear: Bus Clear support to recover from bus hang during···218213 bool has_multi_master_mode;219214 bool has_slcg_override_reg;220215 bool has_mst_fifo;216216+ bool has_mst_reset;221217 const struct i2c_adapter_quirks *quirks;222218 bool supports_bus_clear;223219 bool has_apb_dma;···611605 return 0;612606}613607608608+static int tegra_i2c_master_reset(struct tegra_i2c_dev *i2c_dev)609609+{610610+ if (!i2c_dev->hw->has_mst_reset)611611+ return -EOPNOTSUPP;612612+613613+ /*614614+ * Writing 1 to I2C_MASTER_RESET_CNTRL will reset all internal state of615615+ * Master logic including FIFOs. Clear this bit to 0 for normal operation.616616+ * SW needs to wait for 2us after assertion and de-assertion of this soft617617+ * reset.618618+ */619619+ i2c_writel(i2c_dev, 0x1, I2C_MASTER_RESET_CNTRL);620620+ fsleep(2);621621+622622+ i2c_writel(i2c_dev, 0x0, I2C_MASTER_RESET_CNTRL);623623+ fsleep(2);624624+625625+ return 0;626626+}627627+614628static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)615629{616630 u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode;617631 struct i2c_timings *t = &i2c_dev->timings;618632 int err;633633+634634+ /*635635+ * Reset the controller before initializing it.636636+ * In case if device_reset() returns -ENOENT, i.e. when the reset is637637+ * not available, the internal software reset will be used if it is638638+ * supported by the controller.639639+ */640640+ err = device_reset(i2c_dev->dev);641641+ if (err == -ENOENT)642642+ err = tegra_i2c_master_reset(i2c_dev);619643620644 /*621645 * The reset shouldn't ever fail in practice. The failure will be a···655619 * emit a noisy warning on error, which won't stay unnoticed and656620 * won't hose machine entirely.657621 */658658- err = device_reset(i2c_dev->dev);659622 WARN_ON_ONCE(err);660623661624 if (IS_DVC(i2c_dev))···1301126613021267 if (i2c_dev->dma_mode) {13031268 if (i2c_dev->msg_read) {13041304- dma_sync_single_for_device(i2c_dev->dma_dev,13051305- i2c_dev->dma_phys,13061306- xfer_size, DMA_FROM_DEVICE);13071307-13081269 err = tegra_i2c_dma_submit(i2c_dev, xfer_size);13091270 if (err)13101271 return err;13111311- } else {13121312- dma_sync_single_for_cpu(i2c_dev->dma_dev,13131313- i2c_dev->dma_phys,13141314- xfer_size, DMA_TO_DEVICE);13151272 }13161273 }13171274···13131286 if (i2c_dev->dma_mode) {13141287 memcpy(i2c_dev->dma_buf + I2C_PACKET_HEADER_SIZE,13151288 msg->buf, i2c_dev->msg_len);13161316-13171317- dma_sync_single_for_device(i2c_dev->dma_dev,13181318- i2c_dev->dma_phys,13191319- xfer_size, DMA_TO_DEVICE);13201320-13211289 err = tegra_i2c_dma_submit(i2c_dev, xfer_size);13221290 if (err)13231291 return err;···13531331 return -ETIMEDOUT;13541332 }1355133313561356- if (i2c_dev->msg_read && i2c_dev->msg_err == I2C_ERR_NONE) {13571357- dma_sync_single_for_cpu(i2c_dev->dma_dev,13581358- i2c_dev->dma_phys,13591359- xfer_size, DMA_FROM_DEVICE);13601360-13341334+ if (i2c_dev->msg_read && i2c_dev->msg_err == I2C_ERR_NONE)13611335 memcpy(i2c_dev->msg_buf, i2c_dev->dma_buf, i2c_dev->msg_len);13621362- }13631336 }1364133713651338 time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete,···14851468 .has_multi_master_mode = false,14861469 .has_slcg_override_reg = false,14871470 .has_mst_fifo = false,14711471+ .has_mst_reset = false,14881472 .quirks = &tegra_i2c_quirks,14891473 .supports_bus_clear = false,14901474 .has_apb_dma = true,···15101492 .has_multi_master_mode = false,15111493 .has_slcg_override_reg = false,15121494 .has_mst_fifo = false,14951495+ .has_mst_reset = false,15131496 .quirks = &tegra_i2c_quirks,15141497 .supports_bus_clear = false,15151498 .has_apb_dma = true,···15351516 .has_multi_master_mode = false,15361517 .has_slcg_override_reg = false,15371518 .has_mst_fifo = false,15191519+ .has_mst_reset = false,15381520 .quirks = &tegra_i2c_quirks,15391521 .supports_bus_clear = true,15401522 .has_apb_dma = true,···15601540 .has_multi_master_mode = false,15611541 .has_slcg_override_reg = true,15621542 .has_mst_fifo = false,15431543+ .has_mst_reset = false,15631544 .quirks = &tegra_i2c_quirks,15641545 .supports_bus_clear = true,15651546 .has_apb_dma = true,···15851564 .has_multi_master_mode = false,15861565 .has_slcg_override_reg = true,15871566 .has_mst_fifo = false,15671567+ .has_mst_reset = false,15881568 .quirks = &tegra_i2c_quirks,15891569 .supports_bus_clear = true,15901570 .has_apb_dma = true,···16101588 .has_multi_master_mode = false,16111589 .has_slcg_override_reg = true,16121590 .has_mst_fifo = false,15911591+ .has_mst_reset = false,16131592 .quirks = &tegra_i2c_quirks,16141593 .supports_bus_clear = true,16151594 .has_apb_dma = false,···16351612 .has_multi_master_mode = true,16361613 .has_slcg_override_reg = true,16371614 .has_mst_fifo = true,16151615+ .has_mst_reset = true,16381616 .quirks = &tegra194_i2c_quirks,16391617 .supports_bus_clear = true,16401618 .has_apb_dma = false,
+1
drivers/i2c/i2c-core-acpi.c
···370370 * the device works without issues on Windows at what is expected to be371371 * a 400KHz frequency. The root cause of the issue is not known.372372 */373373+ { "DLL0945", 0 },373374 { "ELAN06FA", 0 },374375 {}375376};
···2626 *2727 * This function can sleep and thus cannot be called in atomic context.2828 *2929- * Return: 0 in case of success, a negative error core otherwise.3030- * -EAGAIN: controller lost address arbitration. Target3131- * (IBI, HJ or controller role request) win the bus. Client3232- * driver needs to resend the 'xfers' some time later.3333- * See I3C spec ver 1.1.1 09-Jun-2021. Section: 5.1.2.2.3.2929+ * Return:3030+ * * 0 in case of success, a negative error core otherwise.3131+ * * -EAGAIN: controller lost address arbitration. Target (IBI, HJ or3232+ * controller role request) win the bus. Client driver needs to resend the3333+ * 'xfers' some time later. See I3C spec ver 1.1.1 09-Jun-2021. Section:3434+ * 5.1.2.2.3.3435 */3536int i3c_device_do_priv_xfers(struct i3c_device *dev,3637 struct i3c_priv_xfer *xfers,
+38
drivers/i3c/internals.h
···99#define I3C_INTERNALS_H10101111#include <linux/i3c/master.h>1212+#include <linux/io.h>12131314void i3c_bus_normaluse_lock(struct i3c_bus *bus);1415void i3c_bus_normaluse_unlock(struct i3c_bus *bus);···2322int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,2423 const struct i3c_ibi_setup *req);2524void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev);2525+2626+/**2727+ * i3c_writel_fifo - Write data buffer to 32bit FIFO2828+ * @addr: FIFO Address to write to2929+ * @buf: Pointer to the data bytes to write3030+ * @nbytes: Number of bytes to write3131+ */3232+static inline void i3c_writel_fifo(void __iomem *addr, const void *buf,3333+ int nbytes)3434+{3535+ writesl(addr, buf, nbytes / 4);3636+ if (nbytes & 3) {3737+ u32 tmp = 0;3838+3939+ memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);4040+ writel(tmp, addr);4141+ }4242+}4343+4444+/**4545+ * i3c_readl_fifo - Read data buffer from 32bit FIFO4646+ * @addr: FIFO Address to read from4747+ * @buf: Pointer to the buffer to store read bytes4848+ * @nbytes: Number of bytes to read4949+ */5050+static inline void i3c_readl_fifo(const void __iomem *addr, void *buf,5151+ int nbytes)5252+{5353+ readsl(addr, buf, nbytes / 4);5454+ if (nbytes & 3) {5555+ u32 tmp;5656+5757+ tmp = readl(addr);5858+ memcpy(buf + (nbytes & ~3), &tmp, nbytes & 3);5959+ }6060+}6161+2662#endif /* I3C_INTERNAL_H */
+20-18
drivers/i3c/master.c
···141141142142 i3c_bus_normaluse_lock(bus);143143 desc = dev_to_i3cdesc(dev);144144- ret = sprintf(buf, "%x\n", desc->info.bcr);144144+ ret = sprintf(buf, "0x%02x\n", desc->info.bcr);145145 i3c_bus_normaluse_unlock(bus);146146147147 return ret;···158158159159 i3c_bus_normaluse_lock(bus);160160 desc = dev_to_i3cdesc(dev);161161- ret = sprintf(buf, "%x\n", desc->info.dcr);161161+ ret = sprintf(buf, "0x%02x\n", desc->info.dcr);162162 i3c_bus_normaluse_unlock(bus);163163164164 return ret;···727727 switch (i3cbus->mode) {728728 case I3C_BUS_MODE_PURE:729729 if (!i3cbus->scl_rate.i3c)730730- i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;730730+ i3cbus->scl_rate.i3c = I3C_BUS_I3C_SCL_TYP_RATE;731731 break;732732 case I3C_BUS_MODE_MIXED_FAST:733733 case I3C_BUS_MODE_MIXED_LIMITED:734734 if (!i3cbus->scl_rate.i3c)735735- i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;735735+ i3cbus->scl_rate.i3c = I3C_BUS_I3C_SCL_TYP_RATE;736736 if (!i3cbus->scl_rate.i2c)737737 i3cbus->scl_rate.i2c = max_i2c_scl_rate;738738 break;···754754 * I3C/I2C frequency may have been overridden, check that user-provided755755 * values are not exceeding max possible frequency.756756 */757757- if (i3cbus->scl_rate.i3c > I3C_BUS_MAX_I3C_SCL_RATE ||758758- i3cbus->scl_rate.i2c > I3C_BUS_I2C_FM_PLUS_SCL_RATE)757757+ if (i3cbus->scl_rate.i3c > I3C_BUS_I3C_SCL_MAX_RATE ||758758+ i3cbus->scl_rate.i2c > I3C_BUS_I2C_FM_PLUS_SCL_MAX_RATE)759759 return -EINVAL;760760761761 return 0;···837837 return -EINVAL;838838839839 if (!master->ops->send_ccc_cmd)840840- return -ENOTSUPP;840840+ return -EOPNOTSUPP;841841842842 if ((cmd->id & I3C_CCC_DIRECT) && (!cmd->dests || !cmd->ndests))843843 return -EINVAL;844844845845 if (master->ops->supports_ccc_cmd &&846846 !master->ops->supports_ccc_cmd(master, cmd))847847- return -ENOTSUPP;847847+ return -EOPNOTSUPP;848848849849 ret = master->ops->send_ccc_cmd(master, cmd);850850 if (ret) {···1439143914401440 if (dev->info.bcr & I3C_BCR_HDR_CAP) {14411441 ret = i3c_master_gethdrcap_locked(master, &dev->info);14421442- if (ret)14421442+ if (ret && ret != -EOPNOTSUPP)14431443 return ret;14441444 }14451445···22102210 */22112211 if (boardinfo->base.flags & I2C_CLIENT_TEN) {22122212 dev_err(dev, "I2C device with 10 bit address not supported.");22132213- return -ENOTSUPP;22132213+ return -EOPNOTSUPP;22142214 }2215221522162216 /* LVR is encoded in reg[2]. */···23402340 return -EINVAL;2341234123422342 if (!master->ops->i2c_xfers)23432343- return -ENOTSUPP;23432343+ return -EOPNOTSUPP;2344234423452345 /* Doing transfers to different devices is not supported. */23462346 addr = xfers[0].addr;23472347 for (i = 1; i < nxfers; i++) {23482348 if (addr != xfers[i].addr)23492349- return -ENOTSUPP;23492349+ return -EOPNOTSUPP;23502350 }2351235123522352 i3c_bus_normaluse_lock(&master->bus);···24672467 case BUS_NOTIFY_DEL_DEVICE:24682468 ret = i3c_master_i2c_detach(adap, client);24692469 break;24702470+ default:24712471+ ret = -EINVAL;24702472 }24712473 i3c_bus_maintenance_unlock(&master->bus);24722474···27682766 * controller)27692767 * @ops: the master controller operations27702768 * @secondary: true if you are registering a secondary master. Will return27712771- * -ENOTSUPP if set to true since secondary masters are not yet27692769+ * -EOPNOTSUPP if set to true since secondary masters are not yet27722770 * supported27732771 *27742772 * This function takes care of everything for you:···27872785 const struct i3c_master_controller_ops *ops,27882786 bool secondary)27892787{27902790- unsigned long i2c_scl_rate = I3C_BUS_I2C_FM_PLUS_SCL_RATE;27882788+ unsigned long i2c_scl_rate = I3C_BUS_I2C_FM_PLUS_SCL_MAX_RATE;27912789 struct i3c_bus *i3cbus = i3c_master_get_bus(master);27922790 enum i3c_bus_mode mode = I3C_BUS_MODE_PURE;27932791 struct i2c_dev_boardinfo *i2cbi;···2795279327962794 /* We do not support secondary masters yet. */27972795 if (secondary)27982798- return -ENOTSUPP;27962796+ return -EOPNOTSUPP;2799279728002798 ret = i3c_master_check_ops(ops);28012799 if (ret)···28462844 }2847284528482846 if (i2cbi->lvr & I3C_LVR_I2C_FM_MODE)28492849- i2c_scl_rate = I3C_BUS_I2C_FM_SCL_RATE;28472847+ i2c_scl_rate = I3C_BUS_I2C_FM_SCL_MAX_RATE;28502848 }2851284928522850 ret = i3c_bus_set_mode(i3cbus, mode, i2c_scl_rate);···29562954 return -EINVAL;2957295529582956 if (!master->ops->priv_xfers)29592959- return -ENOTSUPP;29572957+ return -EOPNOTSUPP;2960295829612959 return master->ops->priv_xfers(dev, xfers, nxfers);29622960}···30063004 int ret;3007300530083006 if (!master->ops->request_ibi)30093009- return -ENOTSUPP;30073007+ return -EOPNOTSUPP;3010300830113009 if (dev->ibi)30123010 return -EBUSY;
+10
drivers/i3c/master/Kconfig
···64646565 This driver can also be built as a module. If so, the module will be6666 called mipi-i3c-hci-pci.6767+6868+config RENESAS_I3C6969+ tristate "Renesas I3C controller driver"7070+ depends on HAS_IOMEM7171+ depends on ARCH_RENESAS || COMPILE_TEST7272+ help7373+ Support the Renesas I3C controller as found in some RZ variants.7474+7575+ This driver can also be built as a module. If so, the module will be7676+ called renesas-i3c.
···584584 To compile this driver as a module, choose M here. The module will585585 be called palmas_pwrbutton.586586587587-config INPUT_PCF50633_PMU588588- tristate "PCF50633 PMU events"589589- depends on MFD_PCF50633590590- help591591- Say Y to include support for delivering PMU events via input592592- layer on NXP PCF50633.593593-594587config INPUT_PCF8574595588 tristate "PCF8574 Keypad input device"596589 depends on I2C
···68686969static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic)7070{7171- struct pwm_args pargs;7272- int delta;7171+ struct pwm_state state;7372 int error;74737575- pwm_get_args(haptic->pwm_dev, &pargs);7676- delta = (pargs.period + haptic->pwm_duty) / 2;7777- error = pwm_config(haptic->pwm_dev, delta, pargs.period);7474+ pwm_init_state(haptic->pwm_dev, &state);7575+ state.duty_cycle = (state.period + haptic->pwm_duty) / 2;7676+7777+ error = pwm_apply_might_sleep(haptic->pwm_dev, &state);7878 if (error) {7979- dev_err(haptic->dev, "failed to configure pwm: %d\n", error);7979+ dev_err(haptic->dev,8080+ "failed to set pwm duty cycle: %d\n", error);8081 return error;8182 }8283···167166168167static void max77693_haptic_enable(struct max77693_haptic *haptic)169168{169169+ struct pwm_state state;170170 int error;171171172172 if (haptic->enabled)173173 return;174174175175- error = pwm_enable(haptic->pwm_dev);175175+ pwm_init_state(haptic->pwm_dev, &state);176176+ state.duty_cycle = (state.period + haptic->pwm_duty) / 2;177177+ state.enabled = true;178178+179179+ error = pwm_apply_might_sleep(haptic->pwm_dev, &state);176180 if (error) {177181 dev_err(haptic->dev,178182 "failed to enable haptic pwm device: %d\n", error);···230224{231225 struct max77693_haptic *haptic =232226 container_of(work, struct max77693_haptic, work);233233- int error;234227235235- error = max77693_haptic_set_duty_cycle(haptic);236236- if (error) {237237- dev_err(haptic->dev, "failed to set duty cycle: %d\n", error);238238- return;239239- }240240-241241- if (haptic->magnitude)242242- max77693_haptic_enable(haptic);243243- else228228+ if (!haptic->magnitude)244229 max77693_haptic_disable(haptic);230230+ else if (haptic->enabled)231231+ max77693_haptic_set_duty_cycle(haptic);232232+ else233233+ max77693_haptic_enable(haptic);245234}246235247236static int max77693_haptic_play_effect(struct input_dev *dev, void *data,···340339 dev_err(&pdev->dev, "failed to get pwm device\n");341340 return PTR_ERR(haptic->pwm_dev);342341 }343343-344344- /*345345- * FIXME: pwm_apply_args() should be removed when switching to the346346- * atomic PWM API.347347- */348348- pwm_apply_args(haptic->pwm_dev);349342350343 haptic->motor_reg = devm_regulator_get(&pdev->dev, "haptic");351344 if (IS_ERR(haptic->motor_reg)) {
+48-50
drivers/input/misc/max8997_haptic.c
···5353 unsigned int pattern_signal_period;5454};55555656-static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)5656+static void max8997_haptic_set_internal_duty_cycle(struct max8997_haptic *chip)5757{5858- int ret = 0;5858+ u8 duty_index = DIV_ROUND_UP(chip->level * 64, 100);59596060- if (chip->mode == MAX8997_EXTERNAL_MODE) {6161- unsigned int duty = chip->pwm_period * chip->level / 100;6262- ret = pwm_config(chip->pwm, duty, chip->pwm_period);6363- } else {6464- u8 duty_index = 0;6565-6666- duty_index = DIV_ROUND_UP(chip->level * 64, 100);6767-6868- switch (chip->internal_mode_pattern) {6969- case 0:7070- max8997_write_reg(chip->client,7171- MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);7272- break;7373- case 1:7474- max8997_write_reg(chip->client,7575- MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);7676- break;7777- case 2:7878- max8997_write_reg(chip->client,7979- MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);8080- break;8181- case 3:8282- max8997_write_reg(chip->client,8383- MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);8484- break;8585- default:8686- break;8787- }6060+ switch (chip->internal_mode_pattern) {6161+ case 0:6262+ max8997_write_reg(chip->client,6363+ MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);6464+ break;6565+ case 1:6666+ max8997_write_reg(chip->client,6767+ MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);6868+ break;6969+ case 2:7070+ max8997_write_reg(chip->client,7171+ MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);7272+ break;7373+ case 3:7474+ max8997_write_reg(chip->client,7575+ MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);7676+ break;7777+ default:7878+ break;8879 }8989- return ret;9080}91819282static void max8997_haptic_configure(struct max8997_haptic *chip)···145155146156 guard(mutex)(&chip->mutex);147157148148- error = max8997_haptic_set_duty_cycle(chip);149149- if (error) {150150- dev_err(chip->dev, "set_pwm_cycle failed, error: %d\n", error);151151- return;152152- }158158+ if (chip->mode != MAX8997_EXTERNAL_MODE)159159+ max8997_haptic_set_internal_duty_cycle(chip);153160154161 if (!chip->enabled) {155162 error = regulator_enable(chip->regulator);···155168 return;156169 }157170 max8997_haptic_configure(chip);158158- if (chip->mode == MAX8997_EXTERNAL_MODE) {159159- error = pwm_enable(chip->pwm);160160- if (error) {161161- dev_err(chip->dev, "Failed to enable PWM\n");162162- regulator_disable(chip->regulator);163163- return;164164- }165165- }166166- chip->enabled = true;167171 }172172+173173+ /*174174+ * It would be more straight forward to configure the external PWM175175+ * earlier i.e. when the internal duty_cycle is setup in internal mode.176176+ * But historically this is done only after the regulator was enabled177177+ * and max8997_haptic_configure() set the enable bit in178178+ * MAX8997_HAPTIC_REG_CONF2. So better keep it this way.179179+ */180180+ if (chip->mode == MAX8997_EXTERNAL_MODE) {181181+ struct pwm_state state;182182+183183+ pwm_init_state(chip->pwm, &state);184184+ state.period = chip->pwm_period;185185+ state.duty_cycle = chip->pwm_period * chip->level / 100;186186+ state.enabled = true;187187+188188+ error = pwm_apply_might_sleep(chip->pwm, &state);189189+ if (error) {190190+ dev_err(chip->dev, "Failed to enable PWM\n");191191+ regulator_disable(chip->regulator);192192+ return;193193+ }194194+ }195195+196196+ chip->enabled = true;168197}169198170199static void max8997_haptic_disable(struct max8997_haptic *chip)···285282 goto err_free_mem;286283 }287284288288- /*289289- * FIXME: pwm_apply_args() should be removed when switching to290290- * the atomic PWM API.291291- */292292- pwm_apply_args(chip->pwm);293285 break;294286295287 default:
-113
drivers/input/misc/pcf50633-input.c
···11-// SPDX-License-Identifier: GPL-2.0-or-later22-/* NXP PCF50633 Input Driver33- *44- * (C) 2006-2008 by Openmoko, Inc.55- * Author: Balaji Rao <balajirrao@openmoko.org>66- * All rights reserved.77- *88- * Broken down from monstrous PCF50633 driver mainly by99- * Harald Welte, Andy Green and Werner Almesberger1010- */1111-1212-#include <linux/kernel.h>1313-#include <linux/module.h>1414-#include <linux/device.h>1515-#include <linux/platform_device.h>1616-#include <linux/input.h>1717-#include <linux/slab.h>1818-1919-#include <linux/mfd/pcf50633/core.h>2020-2121-#define PCF50633_OOCSTAT_ONKEY 0x012222-#define PCF50633_REG_OOCSTAT 0x122323-#define PCF50633_REG_OOCMODE 0x102424-2525-struct pcf50633_input {2626- struct pcf50633 *pcf;2727- struct input_dev *input_dev;2828-};2929-3030-static void3131-pcf50633_input_irq(int irq, void *data)3232-{3333- struct pcf50633_input *input;3434- int onkey_released;3535-3636- input = data;3737-3838- /* We report only one event depending on the key press status */3939- onkey_released = pcf50633_reg_read(input->pcf, PCF50633_REG_OOCSTAT)4040- & PCF50633_OOCSTAT_ONKEY;4141-4242- if (irq == PCF50633_IRQ_ONKEYF && !onkey_released)4343- input_report_key(input->input_dev, KEY_POWER, 1);4444- else if (irq == PCF50633_IRQ_ONKEYR && onkey_released)4545- input_report_key(input->input_dev, KEY_POWER, 0);4646-4747- input_sync(input->input_dev);4848-}4949-5050-static int pcf50633_input_probe(struct platform_device *pdev)5151-{5252- struct pcf50633_input *input;5353- struct input_dev *input_dev;5454- int ret;5555-5656-5757- input = kzalloc(sizeof(*input), GFP_KERNEL);5858- if (!input)5959- return -ENOMEM;6060-6161- input_dev = input_allocate_device();6262- if (!input_dev) {6363- kfree(input);6464- return -ENOMEM;6565- }6666-6767- platform_set_drvdata(pdev, input);6868- input->pcf = dev_to_pcf50633(pdev->dev.parent);6969- input->input_dev = input_dev;7070-7171- input_dev->name = "PCF50633 PMU events";7272- input_dev->id.bustype = BUS_I2C;7373- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_PWR);7474- set_bit(KEY_POWER, input_dev->keybit);7575-7676- ret = input_register_device(input_dev);7777- if (ret) {7878- input_free_device(input_dev);7979- kfree(input);8080- return ret;8181- }8282- pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYR,8383- pcf50633_input_irq, input);8484- pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYF,8585- pcf50633_input_irq, input);8686-8787- return 0;8888-}8989-9090-static void pcf50633_input_remove(struct platform_device *pdev)9191-{9292- struct pcf50633_input *input = platform_get_drvdata(pdev);9393-9494- pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYR);9595- pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYF);9696-9797- input_unregister_device(input->input_dev);9898- kfree(input);9999-}100100-101101-static struct platform_driver pcf50633_input_driver = {102102- .driver = {103103- .name = "pcf50633-input",104104- },105105- .probe = pcf50633_input_probe,106106- .remove = pcf50633_input_remove,107107-};108108-module_platform_driver(pcf50633_input_driver);109109-110110-MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");111111-MODULE_DESCRIPTION("PCF50633 input driver");112112-MODULE_LICENSE("GPL");113113-MODULE_ALIAS("platform:pcf50633-input");
+15
drivers/input/rmi4/Kconfig
···8282 touchpads. For sensors that support relative pointing, F12 also8383 provides mouse input.84848585+config RMI4_F1A8686+ bool "RMI4 Function 1A (0D pointing)"8787+ help8888+ Say Y here if you want to add support for RMI4 function 1A.8989+9090+ Function 1A provides capacitive keys support for RMI4 devices.9191+9292+config RMI4_F219393+ bool "RMI4 Function 21 (PRESSURE)"9494+ help9595+ Say Y here if you want to add support for RMI4 function 21.9696+9797+ Function 21 provides buttons/pressure handling for RMI4 devices.9898+ This includes support for buttons/pressure on PressurePad.9999+85100config RMI4_F3086101 bool "RMI4 Function 30 (GPIO LED)"87102 help
···11+// SPDX-License-Identifier: GPL-2.0-only22+/*33+ * Copyright (c) 2012-2025 Synaptics Incorporated44+ */55+66+#include <linux/bits.h>77+#include <linux/dev_printk.h>88+#include <linux/kernel.h>99+#include <linux/rmi.h>1010+#include <linux/input.h>1111+#include <linux/slab.h>1212+#include "rmi_driver.h"1313+1414+#define RMI_F21_SENSOR_COUNT_MASK GENMASK(3, 0)1515+#define RMI_F21_FINGER_COUNT_PRESENT BIT(5)1616+#define RMI_F21_NEW_REPORT_FORMAT BIT(6)1717+1818+#define RMI_F21_FINGER_COUNT_MASK GENMASK(3, 0)1919+2020+#define RMI_F21_MAX_SENSORS 162121+#define RMI_F21_MAX_FINGERS 162222+#define RMI_F21_DATA_REGS_MAX_SIZE (RMI_F21_MAX_SENSORS * 2 + \2323+ RMI_F21_MAX_FINGERS * 2 + 1)2424+2525+#define RMI_F21_FORCE_CLICK_BIT BIT(0)2626+2727+#define RMI_F21_FORCEPAD_BUTTON_COUNT 12828+2929+struct f21_data {3030+ struct input_dev *input;3131+ u16 key_code;3232+3333+ unsigned int attn_data_size;3434+ unsigned int attn_data_button_offset;3535+3636+ unsigned int data_reg_size;3737+ unsigned int data_reg_button_offset;3838+ u8 data_regs[RMI_F21_DATA_REGS_MAX_SIZE];3939+};4040+4141+static irqreturn_t rmi_f21_attention(int irq, void *ctx)4242+{4343+ struct rmi_function *fn = ctx;4444+ struct f21_data *f21 = dev_get_drvdata(&fn->dev);4545+ struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);4646+ u8 *pdata;4747+ int error;4848+ bool pressed;4949+5050+ if (drvdata->attn_data.data) {5151+ if (drvdata->attn_data.size < f21->attn_data_size) {5252+ dev_warn(&fn->dev, "f21 interrupt, but data is missing\n");5353+ return IRQ_HANDLED;5454+ }5555+5656+ pdata = drvdata->attn_data.data + f21->attn_data_button_offset;5757+5858+ drvdata->attn_data.data += f21->attn_data_size;5959+ drvdata->attn_data.size -= f21->attn_data_size;6060+ } else {6161+ error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,6262+ f21->data_regs, f21->data_reg_size);6363+ if (error) {6464+ dev_err(&fn->dev, "failed to read f21 data registers: %d\n",6565+ error);6666+ return IRQ_RETVAL(error);6767+ }6868+6969+ pdata = f21->data_regs + f21->data_reg_button_offset;7070+ }7171+7272+ pressed = *pdata & RMI_F21_FORCE_CLICK_BIT;7373+ input_report_key(f21->input, f21->key_code, pressed);7474+7575+ return IRQ_HANDLED;7676+}7777+7878+static int rmi_f21_config(struct rmi_function *fn)7979+{8080+ struct rmi_driver *drv = fn->rmi_dev->driver;8181+8282+ drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);8383+8484+ return 0;8585+}8686+8787+static int rmi_f21_initialize(struct rmi_function *fn, struct f21_data *f21)8888+{8989+ struct input_dev *input = f21->input;9090+9191+ f21->key_code = BTN_LEFT;9292+9393+ input->keycode = &f21->key_code;9494+ input->keycodesize = sizeof(f21->key_code);9595+ input->keycodemax = RMI_F21_FORCEPAD_BUTTON_COUNT;9696+9797+ input_set_capability(input, EV_KEY, f21->key_code);9898+ __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);9999+100100+ return 0;101101+}102102+103103+static int rmi_f21_probe(struct rmi_function *fn)104104+{105105+ struct rmi_device *rmi_dev = fn->rmi_dev;106106+ struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);107107+ struct f21_data *f21;108108+ unsigned int sensor_count;109109+ unsigned int max_fingers;110110+ unsigned int query15_offset;111111+ u8 query15_data;112112+ int error;113113+114114+ if (!drv_data->input) {115115+ dev_info(&fn->dev, "f21: no input device found, ignoring\n");116116+ return -ENXIO;117117+ }118118+119119+ f21 = devm_kzalloc(&fn->dev, sizeof(*f21), GFP_KERNEL);120120+ if (!f21)121121+ return -ENOMEM;122122+123123+ f21->input = drv_data->input;124124+125125+ error = rmi_f21_initialize(fn, f21);126126+ if (error)127127+ return error;128128+129129+ dev_set_drvdata(&fn->dev, f21);130130+131131+ sensor_count = fn->fd.query_base_addr & RMI_F21_SENSOR_COUNT_MASK;132132+ if (fn->fd.query_base_addr & RMI_F21_FINGER_COUNT_PRESENT) {133133+ query15_offset = fn->fd.query_base_addr & RMI_F21_NEW_REPORT_FORMAT ? 2 : 1;134134+ error = rmi_read_block(fn->rmi_dev,135135+ fn->fd.query_base_addr + query15_offset,136136+ &query15_data, sizeof(query15_data));137137+ if (error)138138+ return dev_err_probe(&fn->dev, error,139139+ "failed to read 'query15' data");140140+141141+ max_fingers = query15_data & RMI_F21_FINGER_COUNT_MASK;142142+ } else {143143+ max_fingers = 5;144144+ }145145+146146+ if (fn->fd.query_base_addr & RMI_F21_NEW_REPORT_FORMAT) {147147+ /* Each finger uses one byte, and the button state uses one byte.*/148148+ f21->attn_data_size = max_fingers + 1;149149+ f21->attn_data_button_offset = f21->attn_data_size - 1;150150+ /*151151+ * Each sensor uses two bytes, the button state uses one byte,152152+ * and each finger uses two bytes.153153+ */154154+ f21->data_reg_size = sensor_count * 2 + 1 + max_fingers * 2;155155+ f21->data_reg_button_offset = sensor_count * 2;156156+ } else {157157+ /*158158+ * Regardless of the transport each finger uses two bytes,159159+ * and the button state uses one byte.160160+ */161161+ f21->attn_data_size = sensor_count * 2 + 1;162162+ f21->attn_data_button_offset = sensor_count * 2;163163+164164+ f21->data_reg_size = f21->attn_data_size;165165+ f21->data_reg_button_offset = f21->attn_data_button_offset;166166+ }167167+168168+ return 0;169169+}170170+171171+struct rmi_function_handler rmi_f21_handler = {172172+ .driver = {173173+ .name = "rmi4_f21",174174+ },175175+ .func = 0x21,176176+ .probe = rmi_f21_probe,177177+ .config = rmi_f21_config,178178+ .attention = rmi_f21_attention,179179+};
+277
drivers/input/touch-overlay.c
···11+// SPDX-License-Identifier: GPL-2.0-only22+/*33+ * Helper functions for overlay objects on touchscreens44+ *55+ * Copyright (c) 2023 Javier Carrasco <javier.carrasco@wolfvision.net>66+ */77+88+#include <linux/input.h>99+#include <linux/input/mt.h>1010+#include <linux/input/touch-overlay.h>1111+#include <linux/list.h>1212+#include <linux/module.h>1313+#include <linux/property.h>1414+1515+struct touch_overlay_segment {1616+ struct list_head list;1717+ u32 x_origin;1818+ u32 y_origin;1919+ u32 x_size;2020+ u32 y_size;2121+ u32 key;2222+ bool pressed;2323+ int slot;2424+};2525+2626+static int touch_overlay_get_segment(struct fwnode_handle *segment_node,2727+ struct touch_overlay_segment *segment,2828+ struct input_dev *input)2929+{3030+ int error;3131+3232+ error = fwnode_property_read_u32(segment_node, "x-origin",3333+ &segment->x_origin);3434+ if (error)3535+ return error;3636+3737+ error = fwnode_property_read_u32(segment_node, "y-origin",3838+ &segment->y_origin);3939+ if (error)4040+ return error;4141+4242+ error = fwnode_property_read_u32(segment_node, "x-size",4343+ &segment->x_size);4444+ if (error)4545+ return error;4646+4747+ error = fwnode_property_read_u32(segment_node, "y-size",4848+ &segment->y_size);4949+ if (error)5050+ return error;5151+5252+ error = fwnode_property_read_u32(segment_node, "linux,code",5353+ &segment->key);5454+ if (!error)5555+ input_set_capability(input, EV_KEY, segment->key);5656+ else if (error != -EINVAL)5757+ return error;5858+5959+ return 0;6060+}6161+6262+/**6363+ * touch_overlay_map - map overlay objects from the device tree and set6464+ * key capabilities if buttons are defined.6565+ * @list: pointer to the list that will hold the segments6666+ * @input: pointer to the already allocated input_dev6767+ *6868+ * Returns 0 on success and error number otherwise.6969+ *7070+ * If buttons are defined, key capabilities are set accordingly.7171+ */7272+int touch_overlay_map(struct list_head *list, struct input_dev *input)7373+{7474+ struct fwnode_handle *fw_segment;7575+ struct device *dev = input->dev.parent;7676+ struct touch_overlay_segment *segment;7777+ int error;7878+7979+ struct fwnode_handle *overlay __free(fwnode_handle) =8080+ device_get_named_child_node(dev, "touch-overlay");8181+ if (!overlay)8282+ return 0;8383+8484+ fwnode_for_each_available_child_node(overlay, fw_segment) {8585+ segment = devm_kzalloc(dev, sizeof(*segment), GFP_KERNEL);8686+ if (!segment) {8787+ fwnode_handle_put(fw_segment);8888+ return -ENOMEM;8989+ }9090+ error = touch_overlay_get_segment(fw_segment, segment, input);9191+ if (error) {9292+ fwnode_handle_put(fw_segment);9393+ return error;9494+ }9595+ list_add_tail(&segment->list, list);9696+ }9797+9898+ return 0;9999+}100100+EXPORT_SYMBOL(touch_overlay_map);101101+102102+/**103103+ * touch_overlay_get_touchscreen_abs - get abs size from the touchscreen area.104104+ * @list: pointer to the list that holds the segments105105+ * @x: horizontal abs106106+ * @y: vertical abs107107+ */108108+void touch_overlay_get_touchscreen_abs(struct list_head *list, u16 *x, u16 *y)109109+{110110+ struct touch_overlay_segment *segment;111111+ struct list_head *ptr;112112+113113+ list_for_each(ptr, list) {114114+ segment = list_entry(ptr, struct touch_overlay_segment, list);115115+ if (!segment->key) {116116+ *x = segment->x_size - 1;117117+ *y = segment->y_size - 1;118118+ break;119119+ }120120+ }121121+}122122+EXPORT_SYMBOL(touch_overlay_get_touchscreen_abs);123123+124124+static bool touch_overlay_segment_event(struct touch_overlay_segment *seg,125125+ struct input_mt_pos *pos)126126+{127127+ if (pos->x >= seg->x_origin && pos->x < (seg->x_origin + seg->x_size) &&128128+ pos->y >= seg->y_origin && pos->y < (seg->y_origin + seg->y_size))129129+ return true;130130+131131+ return false;132132+}133133+134134+/**135135+ * touch_overlay_mapped_touchscreen - check if a touchscreen area is mapped136136+ * @list: pointer to the list that holds the segments137137+ *138138+ * Returns true if a touchscreen area is mapped or false otherwise.139139+ */140140+bool touch_overlay_mapped_touchscreen(struct list_head *list)141141+{142142+ struct touch_overlay_segment *segment;143143+ struct list_head *ptr;144144+145145+ list_for_each(ptr, list) {146146+ segment = list_entry(ptr, struct touch_overlay_segment, list);147147+ if (!segment->key)148148+ return true;149149+ }150150+151151+ return false;152152+}153153+EXPORT_SYMBOL(touch_overlay_mapped_touchscreen);154154+155155+static bool touch_overlay_event_on_ts(struct list_head *list,156156+ struct input_mt_pos *pos)157157+{158158+ struct touch_overlay_segment *segment;159159+ struct list_head *ptr;160160+161161+ list_for_each(ptr, list) {162162+ segment = list_entry(ptr, struct touch_overlay_segment, list);163163+ if (segment->key)164164+ continue;165165+166166+ if (touch_overlay_segment_event(segment, pos)) {167167+ pos->x -= segment->x_origin;168168+ pos->y -= segment->y_origin;169169+ return true;170170+ }171171+ /* ignore touch events outside the defined area */172172+ return false;173173+ }174174+175175+ return true;176176+}177177+178178+static bool touch_overlay_button_event(struct input_dev *input,179179+ struct touch_overlay_segment *segment,180180+ struct input_mt_pos *pos, int slot)181181+{182182+ struct input_mt *mt = input->mt;183183+ struct input_mt_slot *s = &mt->slots[slot];184184+ bool button_contact = touch_overlay_segment_event(segment, pos);185185+186186+ if (segment->slot == slot && segment->pressed) {187187+ /* sliding out of the button releases it */188188+ if (!button_contact) {189189+ input_report_key(input, segment->key, false);190190+ segment->pressed = false;191191+ /* keep available for a possible touch event */192192+ return false;193193+ }194194+ /* ignore sliding on the button while pressed */195195+ s->frame = mt->frame;196196+ return true;197197+ } else if (button_contact) {198198+ input_report_key(input, segment->key, true);199199+ s->frame = mt->frame;200200+ segment->slot = slot;201201+ segment->pressed = true;202202+ return true;203203+ }204204+205205+ return false;206206+}207207+208208+/**209209+ * touch_overlay_sync_frame - update the status of the segments and report210210+ * buttons whose tracked slot is unused.211211+ * @list: pointer to the list that holds the segments212212+ * @input: pointer to the input device associated to the contact213213+ */214214+void touch_overlay_sync_frame(struct list_head *list, struct input_dev *input)215215+{216216+ struct touch_overlay_segment *segment;217217+ struct input_mt *mt = input->mt;218218+ struct input_mt_slot *s;219219+ struct list_head *ptr;220220+221221+ list_for_each(ptr, list) {222222+ segment = list_entry(ptr, struct touch_overlay_segment, list);223223+ if (!segment->key)224224+ continue;225225+226226+ s = &mt->slots[segment->slot];227227+ if (!input_mt_is_used(mt, s) && segment->pressed) {228228+ input_report_key(input, segment->key, false);229229+ segment->pressed = false;230230+ }231231+ }232232+}233233+EXPORT_SYMBOL(touch_overlay_sync_frame);234234+235235+/**236236+ * touch_overlay_process_contact - process contacts according to the overlay237237+ * mapping. This function acts as a filter to release the calling driver238238+ * from the contacts that are either related to overlay buttons or out of the239239+ * overlay touchscreen area, if defined.240240+ * @list: pointer to the list that holds the segments241241+ * @input: pointer to the input device associated to the contact242242+ * @pos: pointer to the contact position243243+ * @slot: slot associated to the contact (0 if multitouch is not supported)244244+ *245245+ * Returns true if the contact was processed (reported for valid key events246246+ * and dropped for contacts outside the overlay touchscreen area) or false247247+ * if the contact must be processed by the caller. In that case this function248248+ * shifts the (x,y) coordinates to the overlay touchscreen axis if required.249249+ */250250+bool touch_overlay_process_contact(struct list_head *list,251251+ struct input_dev *input,252252+ struct input_mt_pos *pos, int slot)253253+{254254+ struct touch_overlay_segment *segment;255255+ struct list_head *ptr;256256+257257+ /*258258+ * buttons must be prioritized over overlay touchscreens to account for259259+ * overlappings e.g. a button inside the touchscreen area.260260+ */261261+ list_for_each(ptr, list) {262262+ segment = list_entry(ptr, struct touch_overlay_segment, list);263263+ if (segment->key &&264264+ touch_overlay_button_event(input, segment, pos, slot))265265+ return true;266266+ }267267+268268+ /*269269+ * valid contacts on the overlay touchscreen are left for the client270270+ * to be processed/reported according to its (possibly) unique features.271271+ */272272+ return !touch_overlay_event_on_ts(list, pos);273273+}274274+EXPORT_SYMBOL(touch_overlay_process_contact);275275+276276+MODULE_LICENSE("GPL");277277+MODULE_DESCRIPTION("Helper functions for overlay objects on touch devices");
+7-4
drivers/input/touchscreen/ad7879.c
···444444 return !!(val & AD7879_GPIO_DATA);445445}446446447447-static void ad7879_gpio_set_value(struct gpio_chip *chip,448448- unsigned gpio, int value)447447+static int ad7879_gpio_set_value(struct gpio_chip *chip, unsigned int gpio,448448+ int value)449449{450450 struct ad7879 *ts = gpiochip_get_data(chip);451451+ int ret;451452452453 mutex_lock(&ts->mutex);453454 if (value)···456455 else457456 ts->cmd_crtl2 &= ~AD7879_GPIO_DATA;458457459459- ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);458458+ ret = ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);460459 mutex_unlock(&ts->mutex);460460+461461+ return ret;461462}462463463464static int ad7879_gpio_add(struct ad7879 *ts)···475472 ts->gc.direction_input = ad7879_gpio_direction_input;476473 ts->gc.direction_output = ad7879_gpio_direction_output;477474 ts->gc.get = ad7879_gpio_get_value;478478- ts->gc.set = ad7879_gpio_set_value;475475+ ts->gc.set_rv = ad7879_gpio_set_value;479476 ts->gc.can_sleep = 1;480477 ts->gc.base = -1;481478 ts->gc.ngpio = 1;
···252252 * This speeds up some performance tests; that "other work" might include other VDO253253 * threads.254254 */255255- if (need_resched())256256- cond_resched();255255+ cond_resched();257256 }258257259258 run_finish_hook(queue);
+2-2
drivers/md/dm-verity-fec.c
···191191 u8 *want_digest, u8 *data)192192{193193 if (unlikely(verity_hash(v, io, data, 1 << v->data_dev_block_bits,194194- verity_io_real_digest(v, io), true)))194194+ verity_io_real_digest(v, io))))195195 return 0;196196197197 return memcmp(verity_io_real_digest(v, io), want_digest,···392392393393 /* Always re-validate the corrected block against the expected hash */394394 r = verity_hash(v, io, fio->output, 1 << v->data_dev_block_bits,395395- verity_io_real_digest(v, io), true);395395+ verity_io_real_digest(v, io));396396 if (unlikely(r < 0))397397 return r;398398
+29-156
drivers/md/dm-verity-target.c
···1919#include "dm-audit.h"2020#include <linux/module.h>2121#include <linux/reboot.h>2222-#include <linux/scatterlist.h>2322#include <linux/string.h>2423#include <linux/jump_label.h>2524#include <linux/security.h>···5960module_param_array_named(use_bh_bytes, dm_verity_use_bh_bytes, uint, NULL, 0644);60616162static DEFINE_STATIC_KEY_FALSE(use_bh_wq_enabled);6262-6363-/* Is at least one dm-verity instance using ahash_tfm instead of shash_tfm? */6464-static DEFINE_STATIC_KEY_FALSE(ahash_enabled);65636664struct dm_verity_prefetch_work {6765 struct work_struct work;···114118 return block >> (level * v->hash_per_block_bits);115119}116120117117-static int verity_ahash_update(struct dm_verity *v, struct ahash_request *req,118118- const u8 *data, size_t len,119119- struct crypto_wait *wait)120120-{121121- struct scatterlist sg;122122-123123- if (likely(!is_vmalloc_addr(data))) {124124- sg_init_one(&sg, data, len);125125- ahash_request_set_crypt(req, &sg, NULL, len);126126- return crypto_wait_req(crypto_ahash_update(req), wait);127127- }128128-129129- do {130130- int r;131131- size_t this_step = min_t(size_t, len, PAGE_SIZE - offset_in_page(data));132132-133133- flush_kernel_vmap_range((void *)data, this_step);134134- sg_init_table(&sg, 1);135135- sg_set_page(&sg, vmalloc_to_page(data), this_step, offset_in_page(data));136136- ahash_request_set_crypt(req, &sg, NULL, this_step);137137- r = crypto_wait_req(crypto_ahash_update(req), wait);138138- if (unlikely(r))139139- return r;140140- data += this_step;141141- len -= this_step;142142- } while (len);143143-144144- return 0;145145-}146146-147147-/*148148- * Wrapper for crypto_ahash_init, which handles verity salting.149149- */150150-static int verity_ahash_init(struct dm_verity *v, struct ahash_request *req,151151- struct crypto_wait *wait, bool may_sleep)152152-{153153- int r;154154-155155- ahash_request_set_tfm(req, v->ahash_tfm);156156- ahash_request_set_callback(req,157157- may_sleep ? CRYPTO_TFM_REQ_MAY_SLEEP | CRYPTO_TFM_REQ_MAY_BACKLOG : 0,158158- crypto_req_done, (void *)wait);159159- crypto_init_wait(wait);160160-161161- r = crypto_wait_req(crypto_ahash_init(req), wait);162162-163163- if (unlikely(r < 0)) {164164- if (r != -ENOMEM)165165- DMERR("crypto_ahash_init failed: %d", r);166166- return r;167167- }168168-169169- if (likely(v->salt_size && (v->version >= 1)))170170- r = verity_ahash_update(v, req, v->salt, v->salt_size, wait);171171-172172- return r;173173-}174174-175175-static int verity_ahash_final(struct dm_verity *v, struct ahash_request *req,176176- u8 *digest, struct crypto_wait *wait)177177-{178178- int r;179179-180180- if (unlikely(v->salt_size && (!v->version))) {181181- r = verity_ahash_update(v, req, v->salt, v->salt_size, wait);182182-183183- if (r < 0) {184184- DMERR("%s failed updating salt: %d", __func__, r);185185- goto out;186186- }187187- }188188-189189- ahash_request_set_crypt(req, NULL, digest, 0);190190- r = crypto_wait_req(crypto_ahash_final(req), wait);191191-out:192192- return r;193193-}194194-195121int verity_hash(struct dm_verity *v, struct dm_verity_io *io,196196- const u8 *data, size_t len, u8 *digest, bool may_sleep)122122+ const u8 *data, size_t len, u8 *digest)197123{124124+ struct shash_desc *desc = &io->hash_desc;198125 int r;199126200200- if (static_branch_unlikely(&ahash_enabled) && !v->shash_tfm) {201201- struct ahash_request *req = verity_io_hash_req(v, io);202202- struct crypto_wait wait;203203-204204- r = verity_ahash_init(v, req, &wait, may_sleep) ?:205205- verity_ahash_update(v, req, data, len, &wait) ?:206206- verity_ahash_final(v, req, digest, &wait);127127+ desc->tfm = v->shash_tfm;128128+ if (unlikely(v->initial_hashstate == NULL)) {129129+ /* Version 0: salt at end */130130+ r = crypto_shash_init(desc) ?:131131+ crypto_shash_update(desc, data, len) ?:132132+ crypto_shash_update(desc, v->salt, v->salt_size) ?:133133+ crypto_shash_final(desc, digest);207134 } else {208208- struct shash_desc *desc = verity_io_hash_req(v, io);209209-210210- desc->tfm = v->shash_tfm;135135+ /* Version 1: salt at beginning */211136 r = crypto_shash_import(desc, v->initial_hashstate) ?:212137 crypto_shash_finup(desc, data, len, digest);213138 }···279362 }280363281364 r = verity_hash(v, io, data, 1 << v->hash_dev_block_bits,282282- verity_io_real_digest(v, io), !io->in_bh);365365+ verity_io_real_digest(v, io));283366 if (unlikely(r < 0))284367 goto release_ret_r;285368···382465 goto free_ret;383466384467 r = verity_hash(v, io, buffer, 1 << v->data_dev_block_bits,385385- verity_io_real_digest(v, io), true);468468+ verity_io_real_digest(v, io));386469 if (unlikely(r))387470 goto free_ret;388471···498581 }499582500583 r = verity_hash(v, io, data, block_size,501501- verity_io_real_digest(v, io), !io->in_bh);584584+ verity_io_real_digest(v, io));502585 if (unlikely(r < 0)) {503586 kunmap_local(data);504587 return r;···10091092 kfree(v->zero_digest);10101093 verity_free_sig(v);1011109410121012- if (v->ahash_tfm) {10131013- static_branch_dec(&ahash_enabled);10141014- crypto_free_ahash(v->ahash_tfm);10151015- } else {10161016- crypto_free_shash(v->shash_tfm);10171017- }10951095+ crypto_free_shash(v->shash_tfm);1018109610191097 kfree(v->alg_name);10201098···10691157 if (!v->zero_digest)10701158 return r;1071115910721072- io = kmalloc(sizeof(*io) + v->hash_reqsize, GFP_KERNEL);11601160+ io = kmalloc(sizeof(*io) + crypto_shash_descsize(v->shash_tfm),11611161+ GFP_KERNEL);1073116210741163 if (!io)10751164 return r; /* verity_dtr will free zero_digest */···10811168 goto out;1082116910831170 r = verity_hash(v, io, zero_data, 1 << v->data_dev_block_bits,10841084- v->zero_digest, true);11711171+ v->zero_digest);1085117210861173out:10871174 kfree(io);···12371324static int verity_setup_hash_alg(struct dm_verity *v, const char *alg_name)12381325{12391326 struct dm_target *ti = v->ti;12401240- struct crypto_ahash *ahash;12411241- struct crypto_shash *shash = NULL;12421242- const char *driver_name;13271327+ struct crypto_shash *shash;1243132812441329 v->alg_name = kstrdup(alg_name, GFP_KERNEL);12451330 if (!v->alg_name) {···12451334 return -ENOMEM;12461335 }1247133612481248- /*12491249- * Allocate the hash transformation object that this dm-verity instance12501250- * will use. The vast majority of dm-verity users use CPU-based12511251- * hashing, so when possible use the shash API to minimize the crypto12521252- * API overhead. If the ahash API resolves to a different driver12531253- * (likely an off-CPU hardware offload), use ahash instead. Also use12541254- * ahash if the obsolete dm-verity format with the appended salt is12551255- * being used, so that quirk only needs to be handled in one place.12561256- */12571257- ahash = crypto_alloc_ahash(alg_name, 0,12581258- v->use_bh_wq ? CRYPTO_ALG_ASYNC : 0);12591259- if (IS_ERR(ahash)) {13371337+ shash = crypto_alloc_shash(alg_name, 0, 0);13381338+ if (IS_ERR(shash)) {12601339 ti->error = "Cannot initialize hash function";12611261- return PTR_ERR(ahash);13401340+ return PTR_ERR(shash);12621341 }12631263- driver_name = crypto_ahash_driver_name(ahash);12641264- if (v->version >= 1 /* salt prepended, not appended? */) {12651265- shash = crypto_alloc_shash(alg_name, 0, 0);12661266- if (!IS_ERR(shash) &&12671267- strcmp(crypto_shash_driver_name(shash), driver_name) != 0) {12681268- /*12691269- * ahash gave a different driver than shash, so probably12701270- * this is a case of real hardware offload. Use ahash.12711271- */12721272- crypto_free_shash(shash);12731273- shash = NULL;12741274- }12751275- }12761276- if (!IS_ERR_OR_NULL(shash)) {12771277- crypto_free_ahash(ahash);12781278- ahash = NULL;12791279- v->shash_tfm = shash;12801280- v->digest_size = crypto_shash_digestsize(shash);12811281- v->hash_reqsize = sizeof(struct shash_desc) +12821282- crypto_shash_descsize(shash);12831283- DMINFO("%s using shash \"%s\"", alg_name, driver_name);12841284- } else {12851285- v->ahash_tfm = ahash;12861286- static_branch_inc(&ahash_enabled);12871287- v->digest_size = crypto_ahash_digestsize(ahash);12881288- v->hash_reqsize = sizeof(struct ahash_request) +12891289- crypto_ahash_reqsize(ahash);12901290- DMINFO("%s using ahash \"%s\"", alg_name, driver_name);12911291- }13421342+ v->shash_tfm = shash;13431343+ v->digest_size = crypto_shash_digestsize(shash);13441344+ DMINFO("%s using \"%s\"", alg_name, crypto_shash_driver_name(shash));12921345 if ((1 << v->hash_dev_block_bits) < v->digest_size * 2) {12931346 ti->error = "Digest size too big";12941347 return -EINVAL;···12771402 return -EINVAL;12781403 }12791404 }12801280- if (v->shash_tfm) {14051405+ if (v->version) { /* Version 1: salt at beginning */12811406 SHASH_DESC_ON_STACK(desc, v->shash_tfm);12821407 int r;12831408···15561681 goto bad;15571682 }1558168315591559- ti->per_io_data_size = sizeof(struct dm_verity_io) + v->hash_reqsize;16841684+ ti->per_io_data_size = sizeof(struct dm_verity_io) +16851685+ crypto_shash_descsize(v->shash_tfm);1560168615611687 r = verity_fec_ctr(v);15621688 if (r)···16641788 bdev = dm_disk(dm_table_get_md(ti->table))->part0;16651789 root_digest.digest = v->root_digest;16661790 root_digest.digest_len = v->digest_size;16671667- if (static_branch_unlikely(&ahash_enabled) && !v->shash_tfm)16681668- root_digest.alg = crypto_ahash_alg_name(v->ahash_tfm);16691669- else16701670- root_digest.alg = crypto_shash_alg_name(v->shash_tfm);17911791+ root_digest.alg = crypto_shash_alg_name(v->shash_tfm);1671179216721793 r = security_bdev_setintegrity(bdev, LSM_INT_DMVERITY_ROOTHASH, &root_digest,16731794 sizeof(root_digest));···16901817 .name = "verity",16911818/* Note: the LSMs depend on the singleton and immutable features */16921819 .features = DM_TARGET_SINGLETON | DM_TARGET_IMMUTABLE,16931693- .version = {1, 11, 0},18201820+ .version = {1, 12, 0},16941821 .module = THIS_MODULE,16951822 .ctr = verity_ctr,16961823 .dtr = verity_dtr,
+7-15
drivers/md/dm-verity.h
···3939 struct dm_target *ti;4040 struct dm_bufio_client *bufio;4141 char *alg_name;4242- struct crypto_ahash *ahash_tfm; /* either this or shash_tfm is set */4343- struct crypto_shash *shash_tfm; /* either this or ahash_tfm is set */4242+ struct crypto_shash *shash_tfm;4443 u8 *root_digest; /* digest of the root block */4544 u8 *salt; /* salt: its size is salt_size */4646- u8 *initial_hashstate; /* salted initial state, if shash_tfm is set */4545+ u8 *initial_hashstate; /* salted initial state, if version >= 1 */4746 u8 *zero_digest; /* digest for a zero block */4847#ifdef CONFIG_SECURITY4948 u8 *root_digest_sig; /* signature of the root digest */···6061 bool hash_failed:1; /* set if hash of any block failed */6162 bool use_bh_wq:1; /* try to verify in BH wq before normal work-queue */6263 unsigned int digest_size; /* digest size for the current hash algorithm */6363- unsigned int hash_reqsize; /* the size of temporary space for crypto */6464 enum verity_mode mode; /* mode for handling verification errors */6565 enum verity_mode error_mode;/* mode for handling I/O errors */6666 unsigned int corrupted_errs;/* Number of errors for corrupted blocks */···98100 u8 want_digest[HASH_MAX_DIGESTSIZE];99101100102 /*101101- * This struct is followed by a variable-sized hash request of size102102- * v->hash_reqsize, either a struct ahash_request or a struct shash_desc103103- * (depending on whether ahash_tfm or shash_tfm is being used). To104104- * access it, use verity_io_hash_req().103103+ * Temporary space for hashing. This is variable-length and must be at104104+ * the end of the struct. struct shash_desc is just the fixed part;105105+ * it's followed by a context of size crypto_shash_descsize(shash_tfm).105106 */107107+ struct shash_desc hash_desc;106108};107107-108108-static inline void *verity_io_hash_req(struct dm_verity *v,109109- struct dm_verity_io *io)110110-{111111- return io + 1;112112-}113109114110static inline u8 *verity_io_real_digest(struct dm_verity *v,115111 struct dm_verity_io *io)···118126}119127120128extern int verity_hash(struct dm_verity *v, struct dm_verity_io *io,121121- const u8 *data, size_t len, u8 *digest, bool may_sleep);129129+ const u8 *data, size_t len, u8 *digest);122130123131extern int verity_hash_for_block(struct dm_verity *v, struct dm_verity_io *io,124132 sector_t block, u8 *digest, bool *is_zero);
-2
drivers/md/dm-zone.c
···467467 bdev_offset_from_zone_start(disk->part0,468468 clone->bi_iter.bi_sector);469469 }470470-471471- return;472470}473471474472static int dm_zone_need_reset_cb(struct blk_zone *zone, unsigned int idx,
+1-1
drivers/md/dm-zoned-target.c
···10621062 struct dmz_target *dmz = ti->private;10631063 unsigned int zone_nr_sectors = dmz_zone_nr_sectors(dmz->metadata);10641064 sector_t capacity;10651065- int i, r;10651065+ int i, r = 0;1066106610671067 for (i = 0; i < dmz->nr_ddevs; i++) {10681068 capacity = dmz->dev[i].capacity & ~(zone_nr_sectors - 1);
+2-9
drivers/md/dm.c
···10241024 *10251025 * 2) io->orig_bio points to new cloned bio which matches the requeued dm_io.10261026 */10271027-static void dm_io_complete(struct dm_io *io)10271027+static inline void dm_io_complete(struct dm_io *io)10281028{10291029- bool first_requeue;10301030-10311029 /*10321030 * Only dm_io that has been split needs two stage requeue, otherwise10331031 * we may run into long bio clone chain during suspend and OOM could···10341036 * Also flush data dm_io won't be marked as DM_IO_WAS_SPLIT, so they10351037 * also aren't handled via the first stage requeue.10361038 */10371037- if (dm_io_flagged(io, DM_IO_WAS_SPLIT))10381038- first_requeue = true;10391039- else10401040- first_requeue = false;10411041-10421042- __dm_io_complete(io, first_requeue);10391039+ __dm_io_complete(io, dm_io_flagged(io, DM_IO_WAS_SPLIT));10431040}1044104110451042/*
+8-4
drivers/media/platform/qcom/venus/pm_helpers.c
···4848 int ret;49495050 opp = dev_pm_opp_find_freq_ceil(dev, &freq);5151- dev_pm_opp_put(opp);5151+ if (!IS_ERR(opp))5252+ dev_pm_opp_put(opp);52535354 for (i = 0; i < res->clks_num; i++) {5455 if (IS_V6(core)) {···661660 /*TODO : divide this inst->load by work_route */662661663662 opp = dev_pm_opp_find_freq_floor(dev, &max_freq);664664- dev_pm_opp_put(opp);663663+ if (!IS_ERR(opp))664664+ dev_pm_opp_put(opp);665665666666 min_loaded_core(inst, &min_coreid, &min_load, false);667667 min_loaded_core(inst, &min_lp_coreid, &min_lp_load, true);···11231121 freq = max(freq_core1, freq_core2);1124112211251123 opp = dev_pm_opp_find_freq_floor(dev, &max_freq);11261126- dev_pm_opp_put(opp);11241124+ if (!IS_ERR(opp))11251125+ dev_pm_opp_put(opp);1127112611281127 if (freq > max_freq) {11291128 dev_dbg(dev, VDBGL "requested clock rate: %lu scaling clock rate : %lu\n",···11341131 }1135113211361133 opp = dev_pm_opp_find_freq_ceil(dev, &freq);11371137- dev_pm_opp_put(opp);11341134+ if (!IS_ERR(opp))11351135+ dev_pm_opp_put(opp);1138113611391137set_freq:11401138
+1-1
drivers/net/ethernet/marvell/mvneta.c
···46104610 /* Inform that we are stopping so we don't want to setup the46114611 * driver for new CPUs in the notifiers. The code of the46124612 * notifier for CPU online is protected by the same spinlock,46134613- * so when we get the lock, the notifer work is done.46134613+ * so when we get the lock, the notifier work is done.46144614 */46154615 spin_lock(&pp->lock);46164616 pp->is_stopped = true;
+3-3
drivers/net/usb/usbnet.c
···11201120 if (!test_bit(EVENT_DEV_OPEN, &dev->flags))11211121 return;1122112211231123+ if (test_and_clear_bit(EVENT_LINK_CARRIER_ON, &dev->flags))11241124+ netif_carrier_on(dev->net);11251125+11231126 if (!netif_carrier_ok(dev->net)) {11241127 /* kill URBs for reading packets to save bus bandwidth */11251128 unlink_urbs(dev, &dev->rxq);···11321129 * tx queue is stopped by netcore after link becomes off11331130 */11341131 } else {11351135- if (test_and_clear_bit(EVENT_LINK_CARRIER_ON, &dev->flags))11361136- netif_carrier_on(dev->net);11371137-11381132 /* submitting URBs for reading packets */11391133 queue_work(system_bh_wq, &dev->bh_work);11401134 }
+1-2
drivers/net/wwan/iosm/iosm_ipc_trace.c
···5151}52525353static int ipc_trace_subbuf_start_handler(struct rchan_buf *buf, void *subbuf,5454- void *prev_subbuf,5555- size_t prev_padding)5454+ void *prev_subbuf)5655{5756 if (relay_buf_full(buf)) {5857 pr_err_ratelimited("Relay_buf full dropping traces");
+1-1
drivers/net/wwan/t7xx/t7xx_port_trace.c
···3333}34343535static int t7xx_trace_subbuf_start_handler(struct rchan_buf *buf, void *subbuf,3636- void *prev_subbuf, size_t prev_padding)3636+ void *prev_subbuf)3737{3838 if (relay_buf_full(buf)) {3939 pr_err_ratelimited("Relay_buf full dropping traces");
+226-24
drivers/pci/hotplug/pnv_php.c
···33 * PCI Hotplug Driver for PowerPC PowerNV platform.44 *55 * Copyright Gavin Shan, IBM Corporation 2016.66+ * Copyright (C) 2025 Raptor Engineering, LLC77+ * Copyright (C) 2025 Raptor Computing Systems, LLC68 */79810#include <linux/bitfield.h>911#include <linux/libfdt.h>1012#include <linux/module.h>1113#include <linux/pci.h>1414+#include <linux/delay.h>1215#include <linux/pci_hotplug.h>1316#include <linux/of_fdt.h>1417···3936static void pnv_php_unregister_one(struct device_node *dn);4037static void pnv_php_unregister(struct device_node *dn);41383939+static void pnv_php_enable_irq(struct pnv_php_slot *php_slot);4040+4241static void pnv_php_disable_irq(struct pnv_php_slot *php_slot,4343- bool disable_device)4242+ bool disable_device, bool disable_msi)4443{4544 struct pci_dev *pdev = php_slot->pdev;4645 u16 ctrl;···5853 php_slot->irq = 0;5954 }60556161- if (php_slot->wq) {6262- destroy_workqueue(php_slot->wq);6363- php_slot->wq = NULL;6464- }6565-6666- if (disable_device) {5656+ if (disable_device || disable_msi) {6757 if (pdev->msix_enabled)6858 pci_disable_msix(pdev);6959 else if (pdev->msi_enabled)7060 pci_disable_msi(pdev);7171-7272- pci_disable_device(pdev);7361 }6262+6363+ if (disable_device)6464+ pci_disable_device(pdev);7465}75667667static void pnv_php_free_slot(struct kref *kref)···7574 struct pnv_php_slot, kref);76757776 WARN_ON(!list_empty(&php_slot->children));7878- pnv_php_disable_irq(php_slot, false);7777+ pnv_php_disable_irq(php_slot, false, false);7878+ destroy_workqueue(php_slot->wq);7979 kfree(php_slot->name);8080 kfree(php_slot);8181}···393391 return 0;394392}395393394394+static int pcie_check_link_active(struct pci_dev *pdev)395395+{396396+ u16 lnk_status;397397+ int ret;398398+399399+ ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);400400+ if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status))401401+ return -ENODEV;402402+403403+ ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);404404+405405+ return ret;406406+}407407+396408static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state)397409{398410 struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);···419403 */420404 ret = pnv_pci_get_presence_state(php_slot->id, &presence);421405 if (ret >= 0) {406406+ if (pci_pcie_type(php_slot->pdev) == PCI_EXP_TYPE_DOWNSTREAM &&407407+ presence == OPAL_PCI_SLOT_EMPTY) {408408+ /*409409+ * Similar to pciehp_hpc, check whether the Link Active410410+ * bit is set to account for broken downstream bridges411411+ * that don't properly assert Presence Detect State, as412412+ * was observed on the Microsemi Switchtec PM8533 PFX413413+ * [11f8:8533].414414+ */415415+ if (pcie_check_link_active(php_slot->pdev) > 0)416416+ presence = OPAL_PCI_SLOT_PRESENT;417417+ }418418+422419 *state = presence;423420 ret = 0;424421 } else {···441412 return ret;442413}443414415415+static int pnv_php_get_raw_indicator_status(struct hotplug_slot *slot, u8 *state)416416+{417417+ struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);418418+ struct pci_dev *bridge = php_slot->pdev;419419+ u16 status;420420+421421+ pcie_capability_read_word(bridge, PCI_EXP_SLTCTL, &status);422422+ *state = (status & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6;423423+ return 0;424424+}425425+426426+444427static int pnv_php_get_attention_state(struct hotplug_slot *slot, u8 *state)445428{446429 struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);447430431431+ pnv_php_get_raw_indicator_status(slot, &php_slot->attention_state);448432 *state = php_slot->attention_state;449433 return 0;450434}···475433 mask = PCI_EXP_SLTCTL_AIC;476434477435 if (state)478478- new = PCI_EXP_SLTCTL_ATTN_IND_ON;436436+ new = FIELD_PREP(PCI_EXP_SLTCTL_AIC, state);479437 else480438 new = PCI_EXP_SLTCTL_ATTN_IND_OFF;481439482440 pcie_capability_clear_and_set_word(bridge, PCI_EXP_SLTCTL, mask, new);483441484442 return 0;443443+}444444+445445+static int pnv_php_activate_slot(struct pnv_php_slot *php_slot,446446+ struct hotplug_slot *slot)447447+{448448+ int ret, i;449449+450450+ /*451451+ * Issue initial slot activation command to firmware452452+ *453453+ * Firmware will power slot on, attempt to train the link, and454454+ * discover any downstream devices. If this process fails, firmware455455+ * will return an error code and an invalid device tree. Failure456456+ * can be caused for multiple reasons, including a faulty457457+ * downstream device, poor connection to the downstream device, or458458+ * a previously latched PHB fence. On failure, issue fundamental459459+ * reset up to three times before aborting.460460+ */461461+ ret = pnv_php_set_slot_power_state(slot, OPAL_PCI_SLOT_POWER_ON);462462+ if (ret) {463463+ SLOT_WARN(464464+ php_slot,465465+ "PCI slot activation failed with error code %d, possible frozen PHB",466466+ ret);467467+ SLOT_WARN(468468+ php_slot,469469+ "Attempting complete PHB reset before retrying slot activation\n");470470+ for (i = 0; i < 3; i++) {471471+ /*472472+ * Slot activation failed, PHB may be fenced from a473473+ * prior device failure.474474+ *475475+ * Use the OPAL fundamental reset call to both try a476476+ * device reset and clear any potentially active PHB477477+ * fence / freeze.478478+ */479479+ SLOT_WARN(php_slot, "Try %d...\n", i + 1);480480+ pci_set_pcie_reset_state(php_slot->pdev,481481+ pcie_warm_reset);482482+ msleep(250);483483+ pci_set_pcie_reset_state(php_slot->pdev,484484+ pcie_deassert_reset);485485+486486+ ret = pnv_php_set_slot_power_state(487487+ slot, OPAL_PCI_SLOT_POWER_ON);488488+ if (!ret)489489+ break;490490+ }491491+492492+ if (i >= 3)493493+ SLOT_WARN(php_slot,494494+ "Failed to bring slot online, aborting!\n");495495+ }496496+497497+ return ret;485498}486499487500static int pnv_php_enable(struct pnv_php_slot *php_slot, bool rescan)···601504 goto scan;602505603506 /* Power is off, turn it on and then scan the slot */604604- ret = pnv_php_set_slot_power_state(slot, OPAL_PCI_SLOT_POWER_ON);507507+ ret = pnv_php_activate_slot(php_slot, slot);605508 if (ret)606509 return ret;607510···658561static int pnv_php_enable_slot(struct hotplug_slot *slot)659562{660563 struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);564564+ u32 prop32;565565+ int ret;661566662662- return pnv_php_enable(php_slot, true);567567+ ret = pnv_php_enable(php_slot, true);568568+ if (ret)569569+ return ret;570570+571571+ /* (Re-)enable interrupt if the slot supports surprise hotplug */572572+ ret = of_property_read_u32(php_slot->dn, "ibm,slot-surprise-pluggable",573573+ &prop32);574574+ if (!ret && prop32)575575+ pnv_php_enable_irq(php_slot);576576+577577+ return 0;578578+}579579+580580+/*581581+ * Disable any hotplug interrupts for all slots on the provided bus, as well as582582+ * all downstream slots in preparation for a hot unplug.583583+ */584584+static int pnv_php_disable_all_irqs(struct pci_bus *bus)585585+{586586+ struct pci_bus *child_bus;587587+ struct pci_slot *slot;588588+589589+ /* First go down child buses */590590+ list_for_each_entry(child_bus, &bus->children, node)591591+ pnv_php_disable_all_irqs(child_bus);592592+593593+ /* Disable IRQs for all pnv_php slots on this bus */594594+ list_for_each_entry(slot, &bus->slots, list) {595595+ struct pnv_php_slot *php_slot = to_pnv_php_slot(slot->hotplug);596596+597597+ pnv_php_disable_irq(php_slot, false, true);598598+ }599599+600600+ return 0;601601+}602602+603603+/*604604+ * Disable any hotplug interrupts for all downstream slots on the provided605605+ * bus in preparation for a hot unplug.606606+ */607607+static int pnv_php_disable_all_downstream_irqs(struct pci_bus *bus)608608+{609609+ struct pci_bus *child_bus;610610+611611+ /* Go down child buses, recursively deactivating their IRQs */612612+ list_for_each_entry(child_bus, &bus->children, node)613613+ pnv_php_disable_all_irqs(child_bus);614614+615615+ return 0;663616}664617665618static int pnv_php_disable_slot(struct hotplug_slot *slot)···725578 if (php_slot->state != PNV_PHP_STATE_POPULATED &&726579 php_slot->state != PNV_PHP_STATE_REGISTERED)727580 return 0;581581+582582+ /*583583+ * Free all IRQ resources from all child slots before remove.584584+ * Note that we do not disable the root slot IRQ here as that585585+ * would also deactivate the slot hot (re)plug interrupt!586586+ */587587+ pnv_php_disable_all_downstream_irqs(php_slot->bus);728588729589 /* Remove all devices behind the slot */730590 pci_lock_rescan_remove();···797643798644 php_slot->name = kstrdup(label, GFP_KERNEL);799645 if (!php_slot->name) {646646+ kfree(php_slot);647647+ return NULL;648648+ }649649+650650+ /* Allocate workqueue for this slot's interrupt handling */651651+ php_slot->wq = alloc_workqueue("pciehp-%s", 0, 0, php_slot->name);652652+ if (!php_slot->wq) {653653+ SLOT_WARN(php_slot, "Cannot alloc workqueue\n");654654+ kfree(php_slot->name);800655 kfree(php_slot);801656 return NULL;802657 }···908745 return entry.vector;909746}910747748748+static void749749+pnv_php_detect_clear_suprise_removal_freeze(struct pnv_php_slot *php_slot)750750+{751751+ struct pci_dev *pdev = php_slot->pdev;752752+ struct eeh_dev *edev;753753+ struct eeh_pe *pe;754754+ int i, rc;755755+756756+ /*757757+ * When a device is surprise removed from a downstream bridge slot,758758+ * the upstream bridge port can still end up frozen due to related EEH759759+ * events, which will in turn block the MSI interrupts for slot hotplug760760+ * detection.761761+ *762762+ * Detect and thaw any frozen upstream PE after slot deactivation.763763+ */764764+ edev = pci_dev_to_eeh_dev(pdev);765765+ pe = edev ? edev->pe : NULL;766766+ rc = eeh_pe_get_state(pe);767767+ if ((rc == -ENODEV) || (rc == -ENOENT)) {768768+ SLOT_WARN(769769+ php_slot,770770+ "Upstream bridge PE state unknown, hotplug detect may fail\n");771771+ } else {772772+ if (pe->state & EEH_PE_ISOLATED) {773773+ SLOT_WARN(774774+ php_slot,775775+ "Upstream bridge PE %02x frozen, thawing...\n",776776+ pe->addr);777777+ for (i = 0; i < 3; i++)778778+ if (!eeh_unfreeze_pe(pe))779779+ break;780780+ if (i >= 3)781781+ SLOT_WARN(782782+ php_slot,783783+ "Unable to thaw PE %02x, hotplug detect will fail!\n",784784+ pe->addr);785785+ else786786+ SLOT_WARN(php_slot,787787+ "PE %02x thawed successfully\n",788788+ pe->addr);789789+ }790790+ }791791+}792792+911793static void pnv_php_event_handler(struct work_struct *work)912794{913795 struct pnv_php_event *event =914796 container_of(work, struct pnv_php_event, work);915797 struct pnv_php_slot *php_slot = event->php_slot;916798917917- if (event->added)799799+ if (event->added) {918800 pnv_php_enable_slot(&php_slot->slot);919919- else801801+ } else {920802 pnv_php_disable_slot(&php_slot->slot);803803+ pnv_php_detect_clear_suprise_removal_freeze(php_slot);804804+ }921805922806 kfree(event);923807}···1053843 u16 sts, ctrl;1054844 int ret;105584510561056- /* Allocate workqueue */10571057- php_slot->wq = alloc_workqueue("pciehp-%s", 0, 0, php_slot->name);10581058- if (!php_slot->wq) {10591059- SLOT_WARN(php_slot, "Cannot alloc workqueue\n");10601060- pnv_php_disable_irq(php_slot, true);10611061- return;10621062- }10631063-1064846 /* Check PDC (Presence Detection Change) is broken or not */1065847 ret = of_property_read_u32(php_slot->dn, "ibm,slot-broken-pdc",1066848 &broken_pdc);···1071869 ret = request_irq(irq, pnv_php_interrupt, IRQF_SHARED,1072870 php_slot->name, php_slot);1073871 if (ret) {10741074- pnv_php_disable_irq(php_slot, true);872872+ pnv_php_disable_irq(php_slot, true, true);1075873 SLOT_WARN(php_slot, "Error %d enabling IRQ %d\n", ret, irq);1076874 return;1077875 }
+12-9
drivers/rtc/Kconfig
···483483 This driver can also be built as a module. If so, the module484484 will be called rtc-pcf8523.485485486486-config RTC_DRV_PCF85063487487- tristate "NXP PCF85063"488488- select REGMAP_I2C489489- help490490- If you say yes here you get support for the PCF85063 RTC chip491491-492492- This driver can also be built as a module. If so, the module493493- will be called rtc-pcf85063.494494-495486config RTC_DRV_PCF85363496487 tristate "NXP PCF85363"497488 select REGMAP_I2C···961970962971 This driver can also be built as a module. If so, the module963972 will be called rtc-pcf2127.973973+974974+config RTC_DRV_PCF85063975975+ tristate "NXP PCF85063"976976+ depends on RTC_I2C_AND_SPI977977+ select REGMAP_I2C if I2C978978+ select REGMAP_SPI if SPI_MASTER979979+ help980980+ If you say yes here you get support for the PCF85063 and RV8063981981+ RTC chips.982982+983983+ This driver can also be built as a module. If so, the module984984+ will be called rtc-pcf85063.964985965986config RTC_DRV_RV3029C2966987 tristate "Micro Crystal RV3029/3049"
+1-1
drivers/rtc/Makefile
···1515rtc-core-$(CONFIG_RTC_INTF_PROC) += proc.o1616rtc-core-$(CONFIG_RTC_INTF_SYSFS) += sysfs.o17171818-obj-$(CONFIG_RTC_LIB_KUNIT_TEST) += lib_test.o1818+obj-$(CONFIG_RTC_LIB_KUNIT_TEST) += test_rtc_lib.o19192020# Keep the list ordered.2121
+19-21
drivers/rtc/lib.c
···5151 */5252void rtc_time64_to_tm(time64_t time, struct rtc_time *tm)5353{5454- int days, secs;5454+ int secs;55555656 u64 u64tmp;5757 u32 u32tmp, udays, century, day_of_century, year_of_century, year,···5959 bool is_Jan_or_Feb, is_leap_year;60606161 /*6262- * Get days and seconds while preserving the sign to6363- * handle negative time values (dates before 1970-01-01)6262+ * The time represented by `time` is given in seconds since 1970-01-016363+ * (UTC). As the division done below might misbehave for negative6464+ * values, we convert it to seconds since 0000-03-01 and then assume it6565+ * will be non-negative.6666+ * Below we do 4 * udays + 3 which should fit into a 32 bit unsigned6767+ * variable. So the latest date this algorithm works for is 10737418236868+ * days after 0000-03-01 which is in the year 2939805.6469 */6565- days = div_s64_rem(time, 86400, &secs);7070+ time += (u64)719468 * 86400;7171+7272+ udays = div_s64_rem(time, 86400, &secs);66736774 /*6868- * We need 0 <= secs < 86400 which isn't given for negative6969- * values of time. Fixup accordingly.7575+ * day of the week, 0000-03-01 was a Wednesday (in the proleptic7676+ * Gregorian calendar)7077 */7171- if (secs < 0) {7272- days -= 1;7373- secs += 86400;7474- }7575-7676- /* day of the week, 1970-01-01 was a Thursday */7777- tm->tm_wday = (days + 4) % 7;7878- /* Ensure tm_wday is always positive */7979- if (tm->tm_wday < 0)8080- tm->tm_wday += 7;7878+ tm->tm_wday = (udays + 3) % 7;81798280 /*8383- * The following algorithm is, basically, Proposition 6.3 of Neri8181+ * The following algorithm is, basically, Figure 12 of Neri8482 * and Schneider [1]. In a few words: it works on the computational8583 * (fictitious) calendar where the year starts in March, month = 28684 * (*), and finishes in February, month = 13. This calendar is···98100 * (using just arithmetics) it's easy to convert it to the99101 * corresponding date in the Gregorian calendar.100102 *101101- * [1] "Euclidean Affine Functions and Applications to Calendar102102- * Algorithms". https://arxiv.org/abs/2102.06959103103+ * [1] Neri C, Schneider L. Euclidean affine functions and their104104+ * application to calendar algorithms. Softw Pract Exper.105105+ * 2023;53(4):937-970. doi: 10.1002/spe.3172106106+ * https://doi.org/10.1002/spe.3172103107 *104108 * (*) The numbering of months follows rtc_time more closely and105109 * thus, is slightly different from [1].106110 */107107-108108- udays = days + 719468;109111110112 u32tmp = 4 * udays + 3;111113 century = u32tmp / 146097;
drivers/rtc/lib_test.c
drivers/rtc/test_rtc_lib.c
+22-8
drivers/rtc/rtc-ds1307.c
···279279 if (tmp & DS1340_BIT_OSF)280280 return -EINVAL;281281 break;282282+ case ds_1341:283283+ ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &tmp);284284+ if (ret)285285+ return ret;286286+ if (tmp & DS1337_BIT_OSF)287287+ return -EINVAL;288288+ break;282289 case ds_1388:283290 ret = regmap_read(ds1307->regmap, DS1388_REG_FLAG, &tmp);284291 if (ret)···383376 case ds_1340:384377 regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG,385378 DS1340_BIT_OSF, 0);379379+ break;380380+ case ds_1341:381381+ regmap_update_bits(ds1307->regmap, DS1337_REG_STATUS,382382+ DS1337_BIT_OSF, 0);386383 break;387384 case ds_1388:388385 regmap_update_bits(ds1307->regmap, DS1388_REG_FLAG,···14671456 return ds3231_clk_sqw_rates[rate_sel];14681457}1469145814701470-static long ds3231_clk_sqw_round_rate(struct clk_hw *hw, unsigned long rate,14711471- unsigned long *prate)14591459+static int ds3231_clk_sqw_determine_rate(struct clk_hw *hw,14601460+ struct clk_rate_request *req)14721461{14731462 int i;1474146314751464 for (i = ARRAY_SIZE(ds3231_clk_sqw_rates) - 1; i >= 0; i--) {14761476- if (ds3231_clk_sqw_rates[i] <= rate)14771477- return ds3231_clk_sqw_rates[i];14651465+ if (ds3231_clk_sqw_rates[i] <= req->rate) {14661466+ req->rate = ds3231_clk_sqw_rates[i];14671467+14681468+ return 0;14691469+ }14781470 }14711471+14721472+ req->rate = ds3231_clk_sqw_rates[ARRAY_SIZE(ds3231_clk_sqw_rates) - 1];1479147314801474 return 0;14811475}···15411525 .unprepare = ds3231_clk_sqw_unprepare,15421526 .is_prepared = ds3231_clk_sqw_is_prepared,15431527 .recalc_rate = ds3231_clk_sqw_recalc_rate,15441544- .round_rate = ds3231_clk_sqw_round_rate,15281528+ .determine_rate = ds3231_clk_sqw_determine_rate,15451529 .set_rate = ds3231_clk_sqw_set_rate,15461530};15471531···18291813 regmap_write(ds1307->regmap, DS1337_REG_CONTROL,18301814 regs[0]);1831181518321832- /* oscillator fault? clear flag, and warn */18161816+ /* oscillator fault? warn */18331817 if (regs[1] & DS1337_BIT_OSF) {18341834- regmap_write(ds1307->regmap, DS1337_REG_STATUS,18351835- regs[1] & ~DS1337_BIT_OSF);18361818 dev_warn(ds1307->dev, "SET TIME!\n");18371819 }18381820 break;
+2-2
drivers/rtc/rtc-ds1685.c
···33 * An rtc driver for the Dallas/Maxim DS1685/DS1687 and related real-time44 * chips.55 *66- * Copyright (C) 2011-2014 Joshua Kinard <kumba@gentoo.org>.66+ * Copyright (C) 2011-2014 Joshua Kinard <linux@kumba.dev>.77 * Copyright (C) 2009 Matthias Fuchs <matthias.fuchs@esd-electronics.com>.88 *99 * References:···14361436/* ----------------------------------------------------------------------- */143714371438143814391439-MODULE_AUTHOR("Joshua Kinard <kumba@gentoo.org>");14391439+MODULE_AUTHOR("Joshua Kinard <linux@kumba.dev>");14401440MODULE_AUTHOR("Matthias Fuchs <matthias.fuchs@esd-electronics.com>");14411441MODULE_DESCRIPTION("Dallas/Maxim DS1685/DS1687-series RTC driver");14421442MODULE_LICENSE("GPL");
+10-5
drivers/rtc/rtc-hym8563.c
···285285 return clkout_rates[ret];286286}287287288288-static long hym8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate,289289- unsigned long *prate)288288+static int hym8563_clkout_determine_rate(struct clk_hw *hw,289289+ struct clk_rate_request *req)290290{291291 int i;292292293293 for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)294294- if (clkout_rates[i] <= rate)295295- return clkout_rates[i];294294+ if (clkout_rates[i] <= req->rate) {295295+ req->rate = clkout_rates[i];296296+297297+ return 0;298298+ }299299+300300+ req->rate = clkout_rates[0];296301297302 return 0;298303}···368363 .unprepare = hym8563_clkout_unprepare,369364 .is_prepared = hym8563_clkout_is_prepared,370365 .recalc_rate = hym8563_clkout_recalc_rate,371371- .round_rate = hym8563_clkout_round_rate,366366+ .determine_rate = hym8563_clkout_determine_rate,372367 .set_rate = hym8563_clkout_set_rate,373368};374369
···18181818}18191819EXPORT_SYMBOL_GPL(vfio_pci_core_request);1820182018211821-static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,18221822- bool vf_token, uuid_t *uuid)18211821+int vfio_pci_core_match_token_uuid(struct vfio_device *core_vdev,18221822+ const uuid_t *uuid)18231823+18231824{18251825+ struct vfio_pci_core_device *vdev =18261826+ container_of(core_vdev, struct vfio_pci_core_device, vdev);18271827+18241828 /*18251829 * There's always some degree of trust or collaboration between SR-IOV18261830 * PF and VFs, even if just that the PF hosts the SR-IOV capability and···18551851 bool match;1856185218571853 if (!pf_vdev) {18581858- if (!vf_token)18541854+ if (!uuid)18591855 return 0; /* PF is not vfio-pci, no VF token */1860185618611857 pci_info_ratelimited(vdev->pdev,···18631859 return -EINVAL;18641860 }1865186118661866- if (!vf_token) {18621862+ if (!uuid) {18671863 pci_info_ratelimited(vdev->pdev,18681864 "VF token required to access device\n");18691865 return -EACCES;···18811877 } else if (vdev->vf_token) {18821878 mutex_lock(&vdev->vf_token->lock);18831879 if (vdev->vf_token->users) {18841884- if (!vf_token) {18801880+ if (!uuid) {18851881 mutex_unlock(&vdev->vf_token->lock);18861882 pci_info_ratelimited(vdev->pdev,18871883 "VF token required to access device\n");···18941890 "Incorrect VF token provided for device\n");18951891 return -EACCES;18961892 }18971897- } else if (vf_token) {18931893+ } else if (uuid) {18981894 uuid_copy(&vdev->vf_token->uuid, uuid);18991895 }1900189619011897 mutex_unlock(&vdev->vf_token->lock);19021902- } else if (vf_token) {18981898+ } else if (uuid) {19031899 pci_info_ratelimited(vdev->pdev,19041900 "VF token incorrectly provided, not a PF or VF\n");19051901 return -EINVAL;···1907190319081904 return 0;19091905}19061906+EXPORT_SYMBOL_GPL(vfio_pci_core_match_token_uuid);1910190719111908#define VF_TOKEN_ARG "vf_token="19121909···19541949 }19551950 }1956195119571957- ret = vfio_pci_validate_vf_token(vdev, vf_token, &uuid);19521952+ ret = core_vdev->ops->match_token_uuid(core_vdev,19531953+ vf_token ? &uuid : NULL);19581954 if (ret)19591955 return ret;19601956···21522146 return -EBUSY;21532147 }2154214821552155- if (pci_is_root_bus(pdev->bus)) {21492149+ if (pci_is_root_bus(pdev->bus) || pdev->is_virtfn) {21562150 ret = vfio_assign_device_set(&vdev->vdev, vdev);21572151 } else if (!pci_probe_reset_slot(pdev->slot)) {21582152 ret = vfio_assign_device_set(&vdev->vdev, pdev->slot);
···647647648648 while (npage) {649649 if (!batch->size) {650650+ /*651651+ * Large mappings may take a while to repeatedly refill652652+ * the batch, so conditionally relinquish the CPU when653653+ * needed to avoid stalls.654654+ */655655+ cond_resched();656656+650657 /* Empty batch, so refill it. */651658 ret = vaddr_get_pfns(mm, vaddr, npage, dma->prot,652659 &pfn, batch);
+2-1
drivers/vfio/vfio_main.c
···583583584584 lockdep_assert_held(&device->dev_set->lock);585585586586- vfio_assert_device_open(device);586586+ if (!vfio_assert_device_open(device))587587+ return;587588 if (device->open_count == 1)588589 vfio_df_device_last_close(df);589590 device->open_count--;
+30-18
fs/btrfs/tree-log.c
···321321322322 /*323323 * Ignore any items from the inode currently being processed. Needs324324- * to be set every time we find a BTRFS_INODE_ITEM_KEY and we are in325325- * the LOG_WALK_REPLAY_INODES stage.324324+ * to be set every time we find a BTRFS_INODE_ITEM_KEY.326325 */327326 bool ignore_cur_inode;328327···2464246524652466 nritems = btrfs_header_nritems(eb);24662467 for (i = 0; i < nritems; i++) {24682468+ struct btrfs_inode_item *inode_item;24692469+24672470 btrfs_item_key_to_cpu(eb, &key, i);2468247124692469- /* inode keys are done during the first stage */24702470- if (key.type == BTRFS_INODE_ITEM_KEY &&24712471- wc->stage == LOG_WALK_REPLAY_INODES) {24722472- struct btrfs_inode_item *inode_item;24732473- u32 mode;24742474-24752475- inode_item = btrfs_item_ptr(eb, i,24762476- struct btrfs_inode_item);24722472+ if (key.type == BTRFS_INODE_ITEM_KEY) {24732473+ inode_item = btrfs_item_ptr(eb, i, struct btrfs_inode_item);24772474 /*24782478- * If we have a tmpfile (O_TMPFILE) that got fsync'ed24792479- * and never got linked before the fsync, skip it, as24802480- * replaying it is pointless since it would be deleted24812481- * later. We skip logging tmpfiles, but it's always24822482- * possible we are replaying a log created with a kernel24832483- * that used to log tmpfiles.24752475+ * An inode with no links is either:24762476+ *24772477+ * 1) A tmpfile (O_TMPFILE) that got fsync'ed and never24782478+ * got linked before the fsync, skip it, as replaying24792479+ * it is pointless since it would be deleted later.24802480+ * We skip logging tmpfiles, but it's always possible24812481+ * we are replaying a log created with a kernel that24822482+ * used to log tmpfiles;24832483+ *24842484+ * 2) A non-tmpfile which got its last link deleted24852485+ * while holding an open fd on it and later got24862486+ * fsynced through that fd. We always log the24872487+ * parent inodes when inode->last_unlink_trans is24882488+ * set to the current transaction, so ignore all the24892489+ * inode items for this inode. We will delete the24902490+ * inode when processing the parent directory with24912491+ * replay_dir_deletes().24842492 */24852493 if (btrfs_inode_nlink(eb, inode_item) == 0) {24862494 wc->ignore_cur_inode = true;···24952489 } else {24962490 wc->ignore_cur_inode = false;24972491 }24982498- ret = replay_xattr_deletes(wc->trans, root, log,24992499- path, key.objectid);24922492+ }24932493+24942494+ /* Inode keys are done during the first stage. */24952495+ if (key.type == BTRFS_INODE_ITEM_KEY &&24962496+ wc->stage == LOG_WALK_REPLAY_INODES) {24972497+ u32 mode;24982498+24992499+ ret = replay_xattr_deletes(wc->trans, root, log, path, key.objectid);25002500 if (ret)25012501 break;25022502 mode = btrfs_inode_mode(eb, inode_item);
+12
fs/exfat/dir.c
···996996 struct exfat_hint_femp candi_empty;997997 struct exfat_sb_info *sbi = EXFAT_SB(sb);998998 int num_entries = exfat_calc_num_entries(p_uniname);999999+ unsigned int clu_count = 0;999100010001001 if (num_entries < 0)10011002 return num_entries;···11341133 } else {11351134 if (exfat_get_next_cluster(sb, &clu.dir))11361135 return -EIO;11361136+11371137+ /* break if the cluster chain includes a loop */11381138+ if (unlikely(++clu_count > EXFAT_DATA_CLUSTER_COUNT(sbi)))11391139+ goto not_found;11371140 }11381141 }11391142···12001195 int i, count = 0;12011196 int dentries_per_clu;12021197 unsigned int entry_type;11981198+ unsigned int clu_count = 0;12031199 struct exfat_chain clu;12041200 struct exfat_dentry *ep;12051201 struct exfat_sb_info *sbi = EXFAT_SB(sb);···12331227 } else {12341228 if (exfat_get_next_cluster(sb, &(clu.dir)))12351229 return -EIO;12301230+12311231+ if (unlikely(++clu_count > sbi->used_clusters)) {12321232+ exfat_fs_error(sb, "FAT or bitmap is corrupted");12331233+ return -EIO;12341234+ }12351235+12361236 }12371237 }12381238
+10
fs/exfat/fatent.c
···490490 }491491492492 *ret_count = count;493493+494494+ /*495495+ * since exfat_count_used_clusters() is not called, sbi->used_clusters496496+ * cannot be used here.497497+ */498498+ if (unlikely(i == sbi->num_clusters && clu != EXFAT_EOF_CLUSTER)) {499499+ exfat_fs_error(sb, "The cluster chain has a loop");500500+ return -EIO;501501+ }502502+493503 return 0;494504}
···890890{891891 int i, dentries_per_clu;892892 unsigned int type;893893+ unsigned int clu_count = 0;893894 struct exfat_chain clu;894895 struct exfat_dentry *ep;895896 struct exfat_sb_info *sbi = EXFAT_SB(sb);···927926 } else {928927 if (exfat_get_next_cluster(sb, &(clu.dir)))929928 return -EIO;929929+930930+ /* break if the cluster chain includes a loop */931931+ if (unlikely(++clu_count > EXFAT_DATA_CLUSTER_COUNT(sbi)))932932+ break;930933 }931934 }932935
+21-11
fs/exfat/super.c
···341341 INIT_HLIST_HEAD(&sbi->inode_hashtable[i]);342342}343343344344-static int exfat_read_root(struct inode *inode)344344+static int exfat_read_root(struct inode *inode, struct exfat_chain *root_clu)345345{346346 struct super_block *sb = inode->i_sb;347347 struct exfat_sb_info *sbi = EXFAT_SB(sb);348348 struct exfat_inode_info *ei = EXFAT_I(inode);349349- struct exfat_chain cdir;350350- int num_subdirs, num_clu = 0;349349+ int num_subdirs;351350352351 exfat_chain_set(&ei->dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);353352 ei->entry = -1;···359360 ei->hint_stat.clu = sbi->root_dir;360361 ei->hint_femp.eidx = EXFAT_HINT_NONE;361362362362- exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);363363- if (exfat_count_num_clusters(sb, &cdir, &num_clu))364364- return -EIO;365365- i_size_write(inode, num_clu << sbi->cluster_size_bits);363363+ i_size_write(inode, EXFAT_CLU_TO_B(root_clu->size, sbi));366364367367- num_subdirs = exfat_count_dir_entries(sb, &cdir);365365+ num_subdirs = exfat_count_dir_entries(sb, root_clu);368366 if (num_subdirs < 0)369367 return -EIO;370368 set_nlink(inode, num_subdirs + EXFAT_MIN_SUBDIR);···574578}575579576580/* mount the file system volume */577577-static int __exfat_fill_super(struct super_block *sb)581581+static int __exfat_fill_super(struct super_block *sb,582582+ struct exfat_chain *root_clu)578583{579584 int ret;580585 struct exfat_sb_info *sbi = EXFAT_SB(sb);···589592 ret = exfat_verify_boot_region(sb);590593 if (ret) {591594 exfat_err(sb, "invalid boot region");595595+ goto free_bh;596596+ }597597+598598+ /*599599+ * Call exfat_count_num_cluster() before searching for up-case and600600+ * bitmap directory entries to avoid infinite loop if they are missing601601+ * and the cluster chain includes a loop.602602+ */603603+ exfat_chain_set(root_clu, sbi->root_dir, 0, ALLOC_FAT_CHAIN);604604+ ret = exfat_count_num_clusters(sb, root_clu, &root_clu->size);605605+ if (ret) {606606+ exfat_err(sb, "failed to count the number of clusters in root");592607 goto free_bh;593608 }594609···636627 struct exfat_sb_info *sbi = sb->s_fs_info;637628 struct exfat_mount_options *opts = &sbi->options;638629 struct inode *root_inode;630630+ struct exfat_chain root_clu;639631 int err;640632641633 if (opts->allow_utime == (unsigned short)-1)···655645 sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS;656646 sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS;657647658658- err = __exfat_fill_super(sb);648648+ err = __exfat_fill_super(sb, &root_clu);659649 if (err) {660650 exfat_err(sb, "failed to recognize exfat type");661651 goto check_nls_io;···690680691681 root_inode->i_ino = EXFAT_ROOT_INO;692682 inode_set_iversion(root_inode, 1);693693- err = exfat_read_root(root_inode);683683+ err = exfat_read_root(root_inode, &root_clu);694684 if (err) {695685 exfat_err(sb, "failed to initialize root inode");696686 goto put_inode;
···798798 }799799 }800800801801+ if (le16_to_cpu(el->l_next_free_rec) == 0) {802802+ ret = ocfs2_error(inode->i_sb,803803+ "Inode %lu has empty extent list at depth %u\n",804804+ inode->i_ino,805805+ le16_to_cpu(el->l_tree_depth));806806+ goto out;807807+ }808808+801809 found = 0;802810 for (i = le16_to_cpu(el->l_next_free_rec) - 1; i >= 0; i--) {803811 rec = &el->l_recs[i];
···5050 unsigned int fi_sysfile_type;5151};52525353-static struct lock_class_key ocfs2_sysfile_lock_key[NUM_SYSTEM_INODES];5454-5553static int ocfs2_read_locked_inode(struct inode *inode,5654 struct ocfs2_find_inode_args *args);5755static int ocfs2_init_locked_inode(struct inode *inode, void *opaque);···248250static int ocfs2_init_locked_inode(struct inode *inode, void *opaque)249251{250252 struct ocfs2_find_inode_args *args = opaque;253253+#ifdef CONFIG_LOCKDEP254254+ static struct lock_class_key ocfs2_sysfile_lock_key[NUM_SYSTEM_INODES];251255 static struct lock_class_key ocfs2_quota_ip_alloc_sem_key,252256 ocfs2_file_ip_alloc_sem_key;257257+#endif253258254259 inode->i_ino = args->fi_ino;255260 OCFS2_I(inode)->ip_blkno = args->fi_blkno;256256- if (args->fi_sysfile_type != 0)261261+#ifdef CONFIG_LOCKDEP262262+ switch (args->fi_sysfile_type) {263263+ case BAD_BLOCK_SYSTEM_INODE:264264+ break;265265+ case GLOBAL_INODE_ALLOC_SYSTEM_INODE:257266 lockdep_set_class(&inode->i_rwsem,258258- &ocfs2_sysfile_lock_key[args->fi_sysfile_type]);267267+ &ocfs2_sysfile_lock_key[GLOBAL_INODE_ALLOC_SYSTEM_INODE]);268268+ break;269269+ case SLOT_MAP_SYSTEM_INODE:270270+ lockdep_set_class(&inode->i_rwsem,271271+ &ocfs2_sysfile_lock_key[SLOT_MAP_SYSTEM_INODE]);272272+ break;273273+ case HEARTBEAT_SYSTEM_INODE:274274+ lockdep_set_class(&inode->i_rwsem,275275+ &ocfs2_sysfile_lock_key[HEARTBEAT_SYSTEM_INODE]);276276+ break;277277+ case GLOBAL_BITMAP_SYSTEM_INODE:278278+ lockdep_set_class(&inode->i_rwsem,279279+ &ocfs2_sysfile_lock_key[GLOBAL_BITMAP_SYSTEM_INODE]);280280+ break;281281+ case USER_QUOTA_SYSTEM_INODE:282282+ lockdep_set_class(&inode->i_rwsem,283283+ &ocfs2_sysfile_lock_key[USER_QUOTA_SYSTEM_INODE]);284284+ break;285285+ case GROUP_QUOTA_SYSTEM_INODE:286286+ lockdep_set_class(&inode->i_rwsem,287287+ &ocfs2_sysfile_lock_key[GROUP_QUOTA_SYSTEM_INODE]);288288+ break;289289+ case ORPHAN_DIR_SYSTEM_INODE:290290+ lockdep_set_class(&inode->i_rwsem,291291+ &ocfs2_sysfile_lock_key[ORPHAN_DIR_SYSTEM_INODE]);292292+ break;293293+ case EXTENT_ALLOC_SYSTEM_INODE:294294+ lockdep_set_class(&inode->i_rwsem,295295+ &ocfs2_sysfile_lock_key[EXTENT_ALLOC_SYSTEM_INODE]);296296+ break;297297+ case INODE_ALLOC_SYSTEM_INODE:298298+ lockdep_set_class(&inode->i_rwsem,299299+ &ocfs2_sysfile_lock_key[INODE_ALLOC_SYSTEM_INODE]);300300+ break;301301+ case JOURNAL_SYSTEM_INODE:302302+ lockdep_set_class(&inode->i_rwsem,303303+ &ocfs2_sysfile_lock_key[JOURNAL_SYSTEM_INODE]);304304+ break;305305+ case LOCAL_ALLOC_SYSTEM_INODE:306306+ lockdep_set_class(&inode->i_rwsem,307307+ &ocfs2_sysfile_lock_key[LOCAL_ALLOC_SYSTEM_INODE]);308308+ break;309309+ case TRUNCATE_LOG_SYSTEM_INODE:310310+ lockdep_set_class(&inode->i_rwsem,311311+ &ocfs2_sysfile_lock_key[TRUNCATE_LOG_SYSTEM_INODE]);312312+ break;313313+ case LOCAL_USER_QUOTA_SYSTEM_INODE:314314+ lockdep_set_class(&inode->i_rwsem,315315+ &ocfs2_sysfile_lock_key[LOCAL_USER_QUOTA_SYSTEM_INODE]);316316+ break;317317+ case LOCAL_GROUP_QUOTA_SYSTEM_INODE:318318+ lockdep_set_class(&inode->i_rwsem,319319+ &ocfs2_sysfile_lock_key[LOCAL_GROUP_QUOTA_SYSTEM_INODE]);320320+ break;321321+ default:322322+ WARN_ONCE(1, "Unknown sysfile type %d\n", args->fi_sysfile_type);323323+ }259324 if (args->fi_sysfile_type == USER_QUOTA_SYSTEM_INODE ||260325 args->fi_sysfile_type == GROUP_QUOTA_SYSTEM_INODE ||261326 args->fi_sysfile_type == LOCAL_USER_QUOTA_SYSTEM_INODE ||···328267 else329268 lockdep_set_class(&OCFS2_I(inode)->ip_alloc_sem,330269 &ocfs2_file_ip_alloc_sem_key);270270+#endif331271332272 return 0;333273}
+9-10
fs/ocfs2/move_extents.c
···617617 */618618 credits += OCFS2_INODE_UPDATE_CREDITS + 1;619619620620+ inode_lock(tl_inode);621621+620622 /*621623 * ocfs2_move_extent() didn't reserve any clusters in lock_allocators()622624 * logic, while we still need to lock the global_bitmap.···628626 if (!gb_inode) {629627 mlog(ML_ERROR, "unable to get global_bitmap inode\n");630628 ret = -EIO;631631- goto out;629629+ goto out_unlock_tl_inode;632630 }633631634632 inode_lock(gb_inode);···636634 ret = ocfs2_inode_lock(gb_inode, &gb_bh, 1);637635 if (ret) {638636 mlog_errno(ret);639639- goto out_unlock_gb_mutex;637637+ goto out_unlock_gb_inode;640638 }641641-642642- inode_lock(tl_inode);643639644640 handle = ocfs2_start_trans(osb, credits);645641 if (IS_ERR(handle)) {646642 ret = PTR_ERR(handle);647643 mlog_errno(ret);648648- goto out_unlock_tl_inode;644644+ goto out_unlock;649645 }650646651647 new_phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, *new_phys_cpos);···703703out_commit:704704 ocfs2_commit_trans(osb, handle);705705 brelse(gd_bh);706706-707707-out_unlock_tl_inode:708708- inode_unlock(tl_inode);709709-706706+out_unlock:710707 ocfs2_inode_unlock(gb_inode, 1);711711-out_unlock_gb_mutex:708708+out_unlock_gb_inode:712709 inode_unlock(gb_inode);713710 brelse(gb_bh);714711 iput(gb_inode);712712+out_unlock_tl_inode:713713+ inode_unlock(tl_inode);715714716715out:717716 if (context->meta_ac) {
+7-4
fs/ocfs2/namei.c
···142142143143bail_add:144144 ret = d_splice_alias(inode, dentry);145145+ if (IS_ERR(ret))146146+ goto bail_unlock;145147146148 if (inode) {147149 /*···156154 * NOTE: This dentry already has ->d_op set from157155 * ocfs2_get_parent() and ocfs2_get_dentry()158156 */159159- if (!IS_ERR_OR_NULL(ret))157157+ if (ret)160158 dentry = ret;161159162160 status = ocfs2_dentry_attach_lock(dentry, inode,163161 OCFS2_I(dir)->ip_blkno);164162 if (status) {165163 mlog_errno(status);164164+ if (ret)165165+ dput(ret);166166 ret = ERR_PTR(status);167167- goto bail_unlock;168167 }169168 } else170169 ocfs2_dentry_attach_gen(dentry);···14551452 newfe = (struct ocfs2_dinode *) newfe_bh->b_data;1456145314571454 trace_ocfs2_rename_over_existing(14581458- (unsigned long long)newfe_blkno, newfe_bh, newfe_bh ?14591459- (unsigned long long)newfe_bh->b_blocknr : 0ULL);14551455+ (unsigned long long)newfe_blkno, newfe_bh,14561456+ (unsigned long long)newfe_bh->b_blocknr);1460145714611458 if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) {14621459 status = ocfs2_prepare_orphan_dir(osb, &orphan_dir,
+4-11
fs/ocfs2/stack_user.c
···360360 struct ocfs2_control_message_setn *msg)361361{362362 long nodenum;363363- char *ptr = NULL;364363 struct ocfs2_control_private *p = file->private_data;365364366365 if (ocfs2_control_get_handshake_state(file) !=···374375 return -EINVAL;375376 msg->space = msg->newline = '\0';376377377377- nodenum = simple_strtol(msg->nodestr, &ptr, 16);378378- if (!ptr || *ptr)378378+ if (kstrtol(msg->nodestr, 16, &nodenum))379379 return -EINVAL;380380381381 if ((nodenum == LONG_MIN) || (nodenum == LONG_MAX) ||···389391 struct ocfs2_control_message_setv *msg)390392{391393 long major, minor;392392- char *ptr = NULL;393394 struct ocfs2_control_private *p = file->private_data;394395 struct ocfs2_protocol_version *max =395396 &ocfs2_user_plugin.sp_max_proto;···406409 return -EINVAL;407410 msg->space1 = msg->space2 = msg->newline = '\0';408411409409- major = simple_strtol(msg->major, &ptr, 16);410410- if (!ptr || *ptr)412412+ if (kstrtol(msg->major, 16, &major))411413 return -EINVAL;412412- minor = simple_strtol(msg->minor, &ptr, 16);413413- if (!ptr || *ptr)414414+ if (kstrtol(msg->minor, 16, &minor))414415 return -EINVAL;415416416417 /*···436441 struct ocfs2_control_message_down *msg)437442{438443 long nodenum;439439- char *p = NULL;440444441445 if (ocfs2_control_get_handshake_state(file) !=442446 OCFS2_CONTROL_HANDSHAKE_VALID)···450456 return -EINVAL;451457 msg->space1 = msg->space2 = msg->newline = '\0';452458453453- nodenum = simple_strtol(msg->nodestr, &p, 16);454454- if (!p || *p)459459+ if (kstrtol(msg->nodestr, 16, &nodenum))455460 return -EINVAL;456461457462 if ((nodenum == LONG_MIN) || (nodenum == LONG_MAX) ||
+12-17
fs/proc/vmcore.c
···14901490 return -EINVAL;1491149114921492 dump = vzalloc(sizeof(*dump));14931493- if (!dump) {14941494- ret = -ENOMEM;14951495- goto out_err;14961496- }14931493+ if (!dump)14941494+ return -ENOMEM;1497149514981496 /* Keep size of the buffer page aligned so that it can be mmaped */14991497 data_size = roundup(sizeof(struct vmcoredd_header) + data->size,···15171519 dump->size = data_size;1518152015191521 /* Add the dump to driver sysfs list and update the elfcore hdr */15201520- mutex_lock(&vmcore_mutex);15211521- if (vmcore_opened)15221522- pr_warn_once("Unexpected adding of device dump\n");15231523- if (vmcore_open) {15241524- ret = -EBUSY;15251525- goto unlock;15221522+ scoped_guard(mutex, &vmcore_mutex) {15231523+ if (vmcore_opened)15241524+ pr_warn_once("Unexpected adding of device dump\n");15251525+ if (vmcore_open) {15261526+ ret = -EBUSY;15271527+ goto out_err;15281528+ }15291529+15301530+ list_add_tail(&dump->list, &vmcoredd_list);15311531+ vmcoredd_update_size(data_size);15261532 }15271527-15281528- list_add_tail(&dump->list, &vmcoredd_list);15291529- vmcoredd_update_size(data_size);15301530- mutex_unlock(&vmcore_mutex);15311533 return 0;15321532-15331533-unlock:15341534- mutex_unlock(&vmcore_mutex);1535153415361535out_err:15371536 vfree(buf);
+23-24
fs/squashfs/block.c
···8080 struct address_space *cache_mapping, u64 index, int length,8181 u64 read_start, u64 read_end, int page_count)8282{8383- struct page *head_to_cache = NULL, *tail_to_cache = NULL;8383+ struct folio *head_to_cache = NULL, *tail_to_cache = NULL;8484 struct block_device *bdev = fullbio->bi_bdev;8585 int start_idx = 0, end_idx = 0;8686- struct bvec_iter_all iter_all;8686+ struct folio_iter fi;8787 struct bio *bio = NULL;8888- struct bio_vec *bv;8988 int idx = 0;9089 int err = 0;9190#ifdef CONFIG_SQUASHFS_COMP_CACHE_FULL9292- struct page **cache_pages = kmalloc_array(page_count,9393- sizeof(void *), GFP_KERNEL | __GFP_ZERO);9191+ struct folio **cache_folios = kmalloc_array(page_count,9292+ sizeof(*cache_folios), GFP_KERNEL | __GFP_ZERO);9493#endif95949696- bio_for_each_segment_all(bv, fullbio, iter_all) {9797- struct page *page = bv->bv_page;9595+ bio_for_each_folio_all(fi, fullbio) {9696+ struct folio *folio = fi.folio;98979999- if (page->mapping == cache_mapping) {9898+ if (folio->mapping == cache_mapping) {10099 idx++;101100 continue;102101 }···110111 * adjacent blocks.111112 */112113 if (idx == 0 && index != read_start)113113- head_to_cache = page;114114+ head_to_cache = folio;114115 else if (idx == page_count - 1 && index + length != read_end)115115- tail_to_cache = page;116116+ tail_to_cache = folio;116117#ifdef CONFIG_SQUASHFS_COMP_CACHE_FULL117118 /* Cache all pages in the BIO for repeated reads */118118- else if (cache_pages)119119- cache_pages[idx] = page;119119+ else if (cache_folios)120120+ cache_folios[idx] = folio;120121#endif121122122123 if (!bio || idx != end_idx) {···149150 return err;150151151152 if (head_to_cache) {152152- int ret = add_to_page_cache_lru(head_to_cache, cache_mapping,153153+ int ret = filemap_add_folio(cache_mapping, head_to_cache,153154 read_start >> PAGE_SHIFT,154155 GFP_NOIO);155156156157 if (!ret) {157157- SetPageUptodate(head_to_cache);158158- unlock_page(head_to_cache);158158+ folio_mark_uptodate(head_to_cache);159159+ folio_unlock(head_to_cache);159160 }160161161162 }162163163164 if (tail_to_cache) {164164- int ret = add_to_page_cache_lru(tail_to_cache, cache_mapping,165165+ int ret = filemap_add_folio(cache_mapping, tail_to_cache,165166 (read_end >> PAGE_SHIFT) - 1,166167 GFP_NOIO);167168168169 if (!ret) {169169- SetPageUptodate(tail_to_cache);170170- unlock_page(tail_to_cache);170170+ folio_mark_uptodate(tail_to_cache);171171+ folio_unlock(tail_to_cache);171172 }172173 }173174174175#ifdef CONFIG_SQUASHFS_COMP_CACHE_FULL175175- if (!cache_pages)176176+ if (!cache_folios)176177 goto out;177178178179 for (idx = 0; idx < page_count; idx++) {179179- if (!cache_pages[idx])180180+ if (!cache_folios[idx])180181 continue;181181- int ret = add_to_page_cache_lru(cache_pages[idx], cache_mapping,182182+ int ret = filemap_add_folio(cache_mapping, cache_folios[idx],182183 (read_start >> PAGE_SHIFT) + idx,183184 GFP_NOIO);184185185186 if (!ret) {186186- SetPageUptodate(cache_pages[idx]);187187- unlock_page(cache_pages[idx]);187187+ folio_mark_uptodate(cache_folios[idx]);188188+ folio_unlock(cache_folios[idx]);188189 }189190 }190190- kfree(cache_pages);191191+ kfree(cache_folios);191192out:192193#endif193194 return 0;
+3-4
fs/squashfs/file.c
···493493 return res;494494}495495496496-static int squashfs_readahead_fragment(struct page **page,496496+static int squashfs_readahead_fragment(struct inode *inode, struct page **page,497497 unsigned int pages, unsigned int expected, loff_t start)498498{499499- struct inode *inode = page[0]->mapping->host;500499 struct squashfs_cache_entry *buffer = squashfs_get_fragment(inode->i_sb,501500 squashfs_i(inode)->fragment_block,502501 squashfs_i(inode)->fragment_size);···604605605606 if (start >> msblk->block_log == file_end &&606607 squashfs_i(inode)->fragment_block != SQUASHFS_INVALID_BLK) {607607- res = squashfs_readahead_fragment(pages, nr_pages,608608- expected, start);608608+ res = squashfs_readahead_fragment(inode, pages,609609+ nr_pages, expected, start);609610 if (res)610611 goto skip_pages;611612 continue;
···1313 */1414extern struct resource crashk_res;1515extern struct resource crashk_low_res;1616+extern struct range crashk_cma_ranges[];1717+#if defined(CONFIG_CMA) && defined(CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION)1818+#define CRASHKERNEL_CMA1919+#define CRASHKERNEL_CMA_RANGES_MAX 42020+extern int crashk_cma_cnt;2121+#else2222+#define crashk_cma_cnt 02323+#define CRASHKERNEL_CMA_RANGES_MAX 02424+#endif2525+16261727int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,1828 unsigned long long *crash_size, unsigned long long *crash_base,1919- unsigned long long *low_size, bool *high);2929+ unsigned long long *low_size, unsigned long long *cma_size,3030+ bool *high);3131+3232+void __init reserve_crashkernel_cma(unsigned long long cma_size);20332134#ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION2235#ifndef DEFAULT_CRASH_KERNEL_LOW_SIZE
+23-31
include/linux/execmem.h
···6060 * will trap6161 * @ptr: pointer to memory to fill6262 * @size: size of the range to fill6363- * @writable: is the memory poited by @ptr is writable or ROX6463 *6564 * A hook for architecures to fill execmem ranges with invalid instructions.6665 * Architectures that use EXECMEM_ROX_CACHE must implement this.6766 */6868-void execmem_fill_trapping_insns(void *ptr, size_t size, bool writable);6969-7070-/**7171- * execmem_make_temp_rw - temporarily remap region with read-write7272- * permissions7373- * @ptr: address of the region to remap7474- * @size: size of the region to remap7575- *7676- * Remaps a part of the cached large page in the ROX cache in the range7777- * [@ptr, @ptr + @size) as writable and not executable. The caller must7878- * have exclusive ownership of this range and ensure nothing will try to7979- * execute code in this range.8080- *8181- * Return: 0 on success or negative error code on failure.8282- */8383-int execmem_make_temp_rw(void *ptr, size_t size);6767+void execmem_fill_trapping_insns(void *ptr, size_t size);84688569/**8670 * execmem_restore_rox - restore read-only-execute permissions···7995 */8096int execmem_restore_rox(void *ptr, size_t size);8197#else8282-static inline int execmem_make_temp_rw(void *ptr, size_t size) { return 0; }8398static inline int execmem_restore_rox(void *ptr, size_t size) { return 0; }8499#endif85100···149166void *execmem_alloc(enum execmem_type type, size_t size);150167151168/**169169+ * execmem_alloc_rw - allocate writable executable memory170170+ * @type: type of the allocation171171+ * @size: how many bytes of memory are required172172+ *173173+ * Allocates memory that will contain executable code, either generated or174174+ * loaded from kernel modules.175175+ *176176+ * Allocates memory that will contain data coupled with executable code,177177+ * like data sections in kernel modules.178178+ *179179+ * Forces writable permissions on the allocated memory and the caller is180180+ * responsible to manage the permissions afterwards.181181+ *182182+ * For architectures that use ROX cache the permissions will be set to R+W.183183+ * For architectures that don't use ROX cache the default permissions for @type184184+ * will be used as they must be writable.185185+ *186186+ * Return: a pointer to the allocated memory or %NULL187187+ */188188+void *execmem_alloc_rw(enum execmem_type type, size_t size);189189+190190+/**152191 * execmem_free - free executable memory153192 * @ptr: pointer to the memory that should be freed154193 */···189184 */190185struct vm_struct *execmem_vmap(size_t size);191186#endif192192-193193-/**194194- * execmem_update_copy - copy an update to executable memory195195- * @dst: destination address to update196196- * @src: source address containing the data197197- * @size: how many bytes of memory shold be copied198198- *199199- * Copy @size bytes from @src to @dst using text poking if the memory at200200- * @dst is read-only.201201- *202202- * Return: a pointer to @dst or NULL on error203203- */204204-void *execmem_update_copy(void *dst, const void *src, size_t size);205187206188/**207189 * execmem_is_rox - check if execmem is read-only
···33#define _GCD_H4455#include <linux/compiler.h>66+#include <linux/jump_label.h>77+88+DECLARE_STATIC_KEY_TRUE(efficient_ffs_key);69710unsigned long gcd(unsigned long a, unsigned long b) __attribute_const__;811
+9-9
include/linux/hung_task.h
···2121 * type.2222 *2323 * Type encoding:2424- * 00 - Blocked on mutex (BLOCKER_TYPE_MUTEX)2525- * 01 - Blocked on semaphore (BLOCKER_TYPE_SEM)2626- * 10 - Blocked on rt-mutex (BLOCKER_TYPE_RTMUTEX)2727- * 11 - Blocked on rw-semaphore (BLOCKER_TYPE_RWSEM)2424+ * 00 - Blocked on mutex (BLOCKER_TYPE_MUTEX)2525+ * 01 - Blocked on semaphore (BLOCKER_TYPE_SEM)2626+ * 10 - Blocked on rw-semaphore as READER (BLOCKER_TYPE_RWSEM_READER)2727+ * 11 - Blocked on rw-semaphore as WRITER (BLOCKER_TYPE_RWSEM_WRITER)2828 */2929-#define BLOCKER_TYPE_MUTEX 0x00UL3030-#define BLOCKER_TYPE_SEM 0x01UL3131-#define BLOCKER_TYPE_RTMUTEX 0x02UL3232-#define BLOCKER_TYPE_RWSEM 0x03UL2929+#define BLOCKER_TYPE_MUTEX 0x00UL3030+#define BLOCKER_TYPE_SEM 0x01UL3131+#define BLOCKER_TYPE_RWSEM_READER 0x02UL3232+#define BLOCKER_TYPE_RWSEM_WRITER 0x03UL33333434-#define BLOCKER_TYPE_MASK 0x03UL3434+#define BLOCKER_TYPE_MASK 0x03UL35353636#ifdef CONFIG_DETECT_HUNG_TASK_BLOCKER3737static inline void hung_task_set_blocker(void *lock, unsigned long type)
+2-2
include/linux/i3c/device.h
···245245 *246246 * Return: 0 if both registrations succeeds, a negative error code otherwise.247247 */248248-static inline int i3c_i2c_driver_register(struct i3c_driver *i3cdrv,248248+static __always_inline int i3c_i2c_driver_register(struct i3c_driver *i3cdrv,249249 struct i2c_driver *i2cdrv)250250{251251 int ret;···270270 * Note that when CONFIG_I3C is not enabled, this function only unregisters the271271 * @i2cdrv.272272 */273273-static inline void i3c_i2c_driver_unregister(struct i3c_driver *i3cdrv,273273+static __always_inline void i3c_i2c_driver_unregister(struct i3c_driver *i3cdrv,274274 struct i2c_driver *i2cdrv)275275{276276 if (IS_ENABLED(CONFIG_I3C))
···225225 kfree(iomap);226226}227227228228-int io_mapping_map_user(struct io_mapping *iomap, struct vm_area_struct *vma,229229- unsigned long addr, unsigned long pfn, unsigned long size);230230-231228#endif /* _LINUX_IO_MAPPING_H */
+4-4
include/linux/jhash.h
···2424 * Jozsef2525 */2626#include <linux/bitops.h>2727-#include <linux/unaligned/packed_struct.h>2727+#include <linux/unaligned.h>28282929/* Best hash sizes are of power of two */3030#define jhash_size(n) ((u32)1<<(n))···77777878 /* All but the last block: affect some 32 bits of (a,b,c) */7979 while (length > 12) {8080- a += __get_unaligned_cpu32(k);8181- b += __get_unaligned_cpu32(k + 4);8282- c += __get_unaligned_cpu32(k + 8);8080+ a += get_unaligned((u32 *)k);8181+ b += get_unaligned((u32 *)(k + 4));8282+ c += get_unaligned((u32 *)(k + 8));8383 __jhash_mix(a, b, c);8484 length -= 12;8585 k += 12;
+10
include/linux/kexec.h
···79798080typedef unsigned long kimage_entry_t;81818282+/*8383+ * This is a copy of the UAPI struct kexec_segment and must be identical8484+ * to it because it gets copied straight from user space into kernel8585+ * memory. Do not modify this structure unless you change the way segments8686+ * get ingested from user space.8787+ */8288struct kexec_segment {8389 /*8490 * This pointer can point to user memory if kexec_load() system···178172 * @buf_align: Minimum alignment needed.179173 * @buf_min: The buffer can't be placed below this address.180174 * @buf_max: The buffer can't be placed above this address.175175+ * @cma: CMA page if the buffer is backed by CMA.181176 * @top_down: Allocate from top of memory.182177 * @random: Place the buffer at a random position.183178 */···191184 unsigned long buf_align;192185 unsigned long buf_min;193186 unsigned long buf_max;187187+ struct page *cma;194188 bool top_down;195189#ifdef CONFIG_CRASH_DUMP196190 bool random;···348340349341 unsigned long nr_segments;350342 struct kexec_segment segment[KEXEC_SEGMENT_MAX];343343+ struct page *segment_cma[KEXEC_SEGMENT_MAX];351344352345 struct list_head control_pages;353346 struct list_head dest_pages;···370361 */371362 unsigned int hotplug_support:1;372363#endif364364+ unsigned int no_cma:1;373365374366#ifdef ARCH_HAS_KIMAGE_ARCH375367 struct kimage_arch arch;
···414414#endif415415416416#ifdef CONFIG_64BIT417417-/* VM is sealed, in vm_flags */418418-#define VM_SEALED _BITUL(63)417417+#define VM_SEALED_BIT 42418418+#define VM_SEALED BIT(VM_SEALED_BIT)419419+#else420420+#define VM_SEALED VM_NONE419421#endif420422421423/* Bits set in the VMA until the stack is in its final location */
+30
include/linux/mmap_lock.h
···1212#include <linux/tracepoint-defs.h>1313#include <linux/types.h>1414#include <linux/cleanup.h>1515+#include <linux/sched/mm.h>15161617#define MMAP_LOCK_INITIALIZER(name) \1718 .mmap_lock = __RWSEM_INITIALIZER((name).mmap_lock),···155154 * reused and attached to a different mm before we lock it.156155 * Returns the vma on success, NULL on failure to lock and EAGAIN if vma got157156 * detached.157157+ *158158+ * WARNING! The vma passed to this function cannot be used if the function159159+ * fails to lock it because in certain cases RCU lock is dropped and then160160+ * reacquired. Once RCU lock is dropped the vma can be concurently freed.158161 */159162static inline struct vm_area_struct *vma_start_read(struct mm_struct *mm,160163 struct vm_area_struct *vma)···188183 }189184190185 rwsem_acquire_read(&vma->vmlock_dep_map, 0, 1, _RET_IP_);186186+187187+ /*188188+ * If vma got attached to another mm from under us, that mm is not189189+ * stable and can be freed in the narrow window after vma->vm_refcnt190190+ * is dropped and before rcuwait_wake_up(mm) is called. Grab it before191191+ * releasing vma->vm_refcnt.192192+ */193193+ if (unlikely(vma->vm_mm != mm)) {194194+ /* Use a copy of vm_mm in case vma is freed after we drop vm_refcnt */195195+ struct mm_struct *other_mm = vma->vm_mm;196196+197197+ /*198198+ * __mmdrop() is a heavy operation and we don't need RCU199199+ * protection here. Release RCU lock during these operations.200200+ * We reinstate the RCU read lock as the caller expects it to201201+ * be held when this function returns even on error.202202+ */203203+ rcu_read_unlock();204204+ mmgrab(other_mm);205205+ vma_refcount_put(vma);206206+ mmdrop(other_mm);207207+ rcu_read_lock();208208+ return NULL;209209+ }210210+191211 /*192212 * Overflow of vm_lock_seq/mm_lock_seq might produce false locked result.193213 * False unlocked result is impossible because we modify and check
+11-21
include/linux/module.h
···3333#include <linux/percpu.h>3434#include <asm/module.h>35353636-#define MODULE_NAME_LEN MAX_PARAM_PREFIX_LEN3636+#define MODULE_NAME_LEN __MODULE_NAME_LEN37373838struct modversion_info {3939 unsigned long crc;···164164#endif /*CONFIG_MODULES*/165165166166struct module_kobject *lookup_or_create_module_kobject(const char *name);167167-168168-/* Generic info of form tag = "info" */169169-#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)170167171168/* For userspace: you can also call me... */172169#define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)···299302#define MODULE_IMPORT_NS(ns) MODULE_INFO(import_ns, ns)300303301304struct notifier_block;302302-303303-#ifdef CONFIG_MODULES304304-305305-/* Get/put a kernel symbol (calls must be symmetric) */306306-void *__symbol_get(const char *symbol);307307-void *__symbol_get_gpl(const char *symbol);308308-#define symbol_get(x) ({ \309309- static const char __notrim[] \310310- __used __section(".no_trim_symbol") = __stringify(x); \311311- (typeof(&x))(__symbol_get(__stringify(x))); })312312-313313-/* modules using other modules: kdb wants to see this. */314314-struct module_use {315315- struct list_head source_list;316316- struct list_head target_list;317317- struct module *source, *target;318318-};319305320306enum module_state {321307 MODULE_STATE_LIVE, /* Normal state. */···583603#ifndef MODULE_ARCH_INIT584604#define MODULE_ARCH_INIT {}585605#endif606606+607607+#ifdef CONFIG_MODULES608608+609609+/* Get/put a kernel symbol (calls must be symmetric) */610610+void *__symbol_get(const char *symbol);611611+void *__symbol_get_gpl(const char *symbol);612612+#define symbol_get(x) ({ \613613+ static const char __notrim[] \614614+ __used __section(".no_trim_symbol") = __stringify(x); \615615+ (typeof(&x))(__symbol_get(__stringify(x))); })586616587617#ifndef HAVE_ARCH_KALLSYMS_SYMBOL_VALUE588618static inline unsigned long kallsyms_symbol_value(const Elf_Sym *sym)
+14-10
include/linux/moduleparam.h
···66#include <linux/stringify.h>77#include <linux/kernel.h>8899+/*1010+ * The maximum module name length, including the NUL byte.1111+ * Chosen so that structs with an unsigned long line up, specifically1212+ * modversion_info.1313+ */1414+#define __MODULE_NAME_LEN (64 - sizeof(unsigned long))1515+916/* You can override this manually, but generally this should match the1017 module name. */1118#ifdef MODULE···2417#define __MODULE_INFO_PREFIX KBUILD_MODNAME "."2518#endif26192727-/* Chosen so that structs with an unsigned long line up. */2828-#define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long))2929-3030-#define __MODULE_INFO(tag, name, info) \3131- static const char __UNIQUE_ID(name)[] \2020+/* Generic info of form tag = "info" */2121+#define MODULE_INFO(tag, info) \2222+ static const char __UNIQUE_ID(modinfo)[] \3223 __used __section(".modinfo") __aligned(1) \3324 = __MODULE_INFO_PREFIX __stringify(tag) "=" info34253526#define __MODULE_PARM_TYPE(name, _type) \3636- __MODULE_INFO(parmtype, name##type, #name ":" _type)2727+ MODULE_INFO(parmtype, #name ":" _type)37283829/* One for each parameter, describing how to use it. Some files do3930 multiple of these per line, so can't just use MODULE_INFO. */4031#define MODULE_PARM_DESC(_parm, desc) \4141- __MODULE_INFO(parm, _parm, #_parm ":" desc)3232+ MODULE_INFO(parm, #_parm ":" desc)42334334struct kernel_param;4435···287282#define __moduleparam_const const288283#endif289284290290-/* This is the fundamental function for registering boot/module291291- parameters. */285285+/* This is the fundamental function for registering boot/module parameters. */292286#define __module_param_call(prefix, name, ops, arg, perm, level, flags) \293293- /* Default value instead of permissions? */ \287287+ static_assert(sizeof(""prefix) - 1 <= __MODULE_NAME_LEN); \294288 static const char __param_str_##name[] = prefix #name; \295289 static struct kernel_param __moduleparam_const __param_##name \296290 __used __section("__param") \
···736736}737737#endif738738739739+/**740740+ * get_and_clear_ptes - Clear present PTEs that map consecutive pages of741741+ * the same folio, collecting dirty/accessed bits.742742+ * @mm: Address space the pages are mapped into.743743+ * @addr: Address the first page is mapped at.744744+ * @ptep: Page table pointer for the first entry.745745+ * @nr: Number of entries to clear.746746+ *747747+ * Use this instead of get_and_clear_full_ptes() if it is known that we don't748748+ * need to clear the full mm, which is mostly the case.749749+ *750750+ * Note that PTE bits in the PTE range besides the PFN can differ. For example,751751+ * some PTEs might be write-protected.752752+ *753753+ * Context: The caller holds the page table lock. The PTEs map consecutive754754+ * pages that belong to the same folio. The PTEs are all in the same PMD.755755+ */756756+static inline pte_t get_and_clear_ptes(struct mm_struct *mm, unsigned long addr,757757+ pte_t *ptep, unsigned int nr)758758+{759759+ return get_and_clear_full_ptes(mm, addr, ptep, nr, 0);760760+}761761+739762#ifndef clear_full_ptes740763/**741764 * clear_full_ptes - Clear present PTEs that map consecutive pages of the same···790767 }791768}792769#endif770770+771771+/**772772+ * clear_ptes - Clear present PTEs that map consecutive pages of the same folio.773773+ * @mm: Address space the pages are mapped into.774774+ * @addr: Address the first page is mapped at.775775+ * @ptep: Page table pointer for the first entry.776776+ * @nr: Number of entries to clear.777777+ *778778+ * Use this instead of clear_full_ptes() if it is known that we don't need to779779+ * clear the full mm, which is mostly the case.780780+ *781781+ * Note that PTE bits in the PTE range besides the PFN can differ. For example,782782+ * some PTEs might be write-protected.783783+ *784784+ * Context: The caller holds the page table lock. The PTEs map consecutive785785+ * pages that belong to the same folio. The PTEs are all in the same PMD.786786+ */787787+static inline void clear_ptes(struct mm_struct *mm, unsigned long addr,788788+ pte_t *ptep, unsigned int nr)789789+{790790+ clear_full_ptes(mm, addr, ptep, nr, 0);791791+}793792794793/*795794 * If two threads concurrently fault at the same page, the thread that
+11-1
include/linux/raid/pq.h
···1111#ifdef __KERNEL__12121313#include <linux/blkdev.h>1414+#include <linux/mm.h>14151515-extern const char raid6_empty_zero_page[PAGE_SIZE];1616+/* This should be const but the raid6 code is too convoluted for that. */1717+static inline void *raid6_get_zero_page(void)1818+{1919+ return page_address(ZERO_PAGE(0));2020+}16211722#else /* ! __KERNEL__ */1823/* Used for testing in user space */···194189 struct timeval tv;195190 gettimeofday(&tv, NULL);196191 return tv.tv_sec*1000 + tv.tv_usec/1000;192192+}193193+194194+static inline void *raid6_get_zero_page(void)195195+{196196+ return raid6_empty_zero_page;197197}198198199199#endif /* ! __KERNEL__ */
+19-5
include/linux/relay.h
···2929#define RELAYFS_CHANNEL_VERSION 730303131/*3232+ * Relay buffer statistics3333+ */3434+enum {3535+ RELAY_STATS_BUF_FULL = (1 << 0),3636+ RELAY_STATS_WRT_BIG = (1 << 1),3737+3838+ RELAY_STATS_LAST = RELAY_STATS_WRT_BIG,3939+};4040+4141+struct rchan_buf_stats4242+{4343+ unsigned int full_count; /* counter for buffer full */4444+ unsigned int big_count; /* counter for too big to write */4545+};4646+4747+/*3248 * Per-cpu relay channel buffer3349 */3450struct rchan_buf···5943 struct irq_work wakeup_work; /* reader wakeup */6044 struct dentry *dentry; /* channel file dentry */6145 struct kref kref; /* channel buffer refcount */4646+ struct rchan_buf_stats stats; /* buffer stats */6247 struct page **page_array; /* array of current buffer pages */6348 unsigned int page_count; /* number of current buffer pages */6449 unsigned int finalized; /* buffer has been finalized */6550 size_t *padding; /* padding counts per sub-buffer */6666- size_t prev_padding; /* temporary variable */6751 size_t bytes_consumed; /* bytes consumed in cur read subbuf */6852 size_t early_bytes; /* bytes consumed before VFS inited */6953 unsigned int cpu; /* this buf's cpu */···8165 const struct rchan_callbacks *cb; /* client callbacks */8266 struct kref kref; /* channel refcount */8367 void *private_data; /* for user-defined data */8484- size_t last_toobig; /* tried to log event > subbuf size */8568 struct rchan_buf * __percpu *buf; /* per-cpu channel buffers */8669 int is_global; /* One global buffer ? */8770 struct list_head list; /* for channel list */···9984 * @buf: the channel buffer containing the new sub-buffer10085 * @subbuf: the start of the new sub-buffer10186 * @prev_subbuf: the start of the previous sub-buffer102102- * @prev_padding: unused space at the end of previous sub-buffer10387 *10488 * The client should return 1 to continue logging, 0 to stop10589 * logging.···114100 */115101 int (*subbuf_start) (struct rchan_buf *buf,116102 void *subbuf,117117- void *prev_subbuf,118118- size_t prev_padding);103103+ void *prev_subbuf);119104120105 /*121106 * create_buf_file - create file to represent a relay channel buffer···174161 void *private_data);175162extern void relay_close(struct rchan *chan);176163extern void relay_flush(struct rchan *chan);164164+size_t relay_stats(struct rchan *chan, int flags);177165extern void relay_subbufs_consumed(struct rchan *chan,178166 unsigned int cpu,179167 size_t consumed);
···449449 default:450450 VM_WARN_ON_ONCE(true);451451 }452452+453453+ /*454454+ * Anon folios must have an associated live anon_vma as long as they're455455+ * mapped into userspace.456456+ * Note that the atomic_read() mainly does two things:457457+ *458458+ * 1. In KASAN builds with CONFIG_SLUB_RCU_DEBUG, it causes KASAN to459459+ * check that the associated anon_vma has not yet been freed (subject460460+ * to KASAN's usual limitations). This check will pass if the461461+ * anon_vma's refcount has already dropped to 0 but an RCU grace462462+ * period hasn't passed since then.463463+ * 2. If the anon_vma has not yet been freed, it checks that the464464+ * anon_vma still has a nonzero refcount (as opposed to being in the465465+ * middle of an RCU delay for getting freed).466466+ */467467+ if (folio_test_anon(folio) && !folio_test_ksm(folio)) {468468+ unsigned long mapping = (unsigned long)folio->mapping;469469+ struct anon_vma *anon_vma;470470+471471+ anon_vma = (void *)(mapping - FOLIO_MAPPING_ANON);472472+ VM_WARN_ON_FOLIO(atomic_read(&anon_vma->refcount) == 0, folio);473473+ }452474}453475454476/*
···132132 return !list_empty(&sem->wait_list);133133}134134135135+#if defined(CONFIG_DEBUG_RWSEMS) || defined(CONFIG_DETECT_HUNG_TASK_BLOCKER)136136+/*137137+ * Return just the real task structure pointer of the owner138138+ */139139+extern struct task_struct *rwsem_owner(struct rw_semaphore *sem);140140+141141+/*142142+ * Return true if the rwsem is owned by a reader.143143+ */144144+extern bool is_rwsem_reader_owned(struct rw_semaphore *sem);145145+#endif146146+135147#else /* !CONFIG_PREEMPT_RT */136148137149#include <linux/rwbase_rt.h>
+1-1
include/linux/sprintf.h
···23232424/* These are for specific cases, do not use without real need */2525extern bool no_hash_pointers;2626-int no_hash_pointers_enable(char *str);2626+void hash_pointers_finalize(bool slub_debug);27272828/* Used for Rust formatting ('%pA') */2929char *rust_fmt_argument(char *buf, char *end, const void *ptr);
+28
include/linux/sys_info.h
···11+/* SPDX-License-Identifier: GPL-2.0 */22+#ifndef _LINUX_SYS_INFO_H33+#define _LINUX_SYS_INFO_H44+55+#include <linux/sysctl.h>66+77+/*88+ * SYS_INFO_PANIC_CONSOLE_REPLAY is for panic case only, as it needs special99+ * handling which only fits panic case.1010+ */1111+#define SYS_INFO_TASKS 0x000000011212+#define SYS_INFO_MEM 0x000000021313+#define SYS_INFO_TIMERS 0x000000041414+#define SYS_INFO_LOCKS 0x000000081515+#define SYS_INFO_FTRACE 0x000000101616+#define SYS_INFO_PANIC_CONSOLE_REPLAY 0x000000201717+#define SYS_INFO_ALL_CPU_BT 0x000000401818+#define SYS_INFO_BLOCKED_TASKS 0x000000801919+2020+void sys_info(unsigned long si_mask);2121+unsigned long sys_info_parse_param(char *str);2222+2323+#ifdef CONFIG_SYSCTL2424+int sysctl_sys_info_handler(const struct ctl_table *ro_table, int write,2525+ void *buffer, size_t *lenp,2626+ loff_t *ppos);2727+#endif2828+#endif /* _LINUX_SYS_INFO_H */
+4
include/linux/vfio.h
···105105 * @match: Optional device name match callback (return: 0 for no-match, >0 for106106 * match, -errno for abort (ex. match with insufficient or incorrect107107 * additional args)108108+ * @match_token_uuid: Optional device token match/validation. Return 0109109+ * if the uuid is valid for the device, -errno otherwise. uuid is NULL110110+ * if none was provided.108111 * @dma_unmap: Called when userspace unmaps IOVA from the container109112 * this device is attached to.110113 * @device_feature: Optional, fill in the VFIO_DEVICE_FEATURE ioctl···135132 int (*mmap)(struct vfio_device *vdev, struct vm_area_struct *vma);136133 void (*request)(struct vfio_device *vdev, unsigned int count);137134 int (*match)(struct vfio_device *vdev, char *buf);135135+ int (*match_token_uuid)(struct vfio_device *vdev, const uuid_t *uuid);138136 void (*dma_unmap)(struct vfio_device *vdev, u64 iova, u64 length);139137 int (*device_feature)(struct vfio_device *device, u32 flags,140138 void __user *arg, size_t argsz);
···178178void xxh32_reset(struct xxh32_state *state, uint32_t seed);179179180180/**181181- * xxh32_update() - hash the data given and update the xxh32 state182182- *183183- * @state: The xxh32 state to update.184184- * @input: The data to hash.185185- * @length: The length of the data to hash.186186- *187187- * After calling xxh32_reset() call xxh32_update() as many times as necessary.188188- *189189- * Return: Zero on success, otherwise an error code.190190- */191191-int xxh32_update(struct xxh32_state *state, const void *input, size_t length);192192-193193-/**194194- * xxh32_digest() - produce the current xxh32 hash195195- *196196- * @state: Produce the current xxh32 hash of this state.197197- *198198- * A hash value can be produced at any time. It is still possible to continue199199- * inserting input into the hash state after a call to xxh32_digest(), and200200- * generate new hashes later on, by calling xxh32_digest() again.201201- *202202- * Return: The xxh32 hash stored in the state.203203- */204204-uint32_t xxh32_digest(const struct xxh32_state *state);205205-206206-/**207181 * xxh64_reset() - reset the xxh64 state to start a new hashing operation208182 *209183 * @state: The xxh64 state to reset.
···2727#define KEXEC_FILE_ON_CRASH 0x000000022828#define KEXEC_FILE_NO_INITRAMFS 0x000000042929#define KEXEC_FILE_DEBUG 0x000000083030+#define KEXEC_FILE_NO_CMA 0x0000001030313132/* These values match the ELF architecture values.3233 * Unless there is a good reason that should continue to be the case.
+11-1
include/uapi/linux/vfio.h
···905905 * VFIO_DEVICE_BIND_IOMMUFD - _IOR(VFIO_TYPE, VFIO_BASE + 18,906906 * struct vfio_device_bind_iommufd)907907 * @argsz: User filled size of this data.908908- * @flags: Must be 0.908908+ * @flags: Must be 0 or a bit flags of VFIO_DEVICE_BIND_*909909 * @iommufd: iommufd to bind.910910 * @out_devid: The device id generated by this bind. devid is a handle for911911 * this device/iommufd bond and can be used in IOMMUFD commands.912912+ * @token_uuid_ptr: Valid if VFIO_DEVICE_BIND_FLAG_TOKEN. Points to a 16 byte913913+ * UUID in the same format as VFIO_DEVICE_FEATURE_PCI_VF_TOKEN.912914 *913915 * Bind a vfio_device to the specified iommufd.914916 *···919917 *920918 * Unbind is automatically conducted when device fd is closed.921919 *920920+ * A token is sometimes required to open the device, unless this is known to be921921+ * needed VFIO_DEVICE_BIND_FLAG_TOKEN should not be set and token_uuid_ptr is922922+ * ignored. The only case today is a PF/VF relationship where the VF bind must923923+ * be provided the same token as VFIO_DEVICE_FEATURE_PCI_VF_TOKEN provided to924924+ * the PF.925925+ *922926 * Return: 0 on success, -errno on failure.923927 */924928struct vfio_device_bind_iommufd {925929 __u32 argsz;926930 __u32 flags;931931+#define VFIO_DEVICE_BIND_FLAG_TOKEN (1 << 0)927932 __s32 iommufd;928933 __u32 out_devid;934934+ __aligned_u64 token_uuid_ptr;929935};930936931937#define VFIO_DEVICE_BIND_IOMMUFD _IO(VFIO_TYPE, VFIO_BASE + 18)
+1-1
include/xen/xenbus.h
···178178 * sprintf-style type string, and pointer. Returns 0 or errno.*/179179int xenbus_gather(struct xenbus_transaction t, const char *dir, ...);180180181181-/* notifer routines for when the xenstore comes up */181181+/* notifier routines for when the xenstore comes up */182182extern int xenstored_ready;183183int register_xenstore_notifier(struct notifier_block *nb);184184void unregister_xenstore_notifier(struct notifier_block *nb);
+4
init/Kconfig
···172172173173config BROKEN174174 bool175175+ help176176+ This option allows you to choose whether you want to try to177177+ compile (and fix) old drivers that haven't been updated to178178+ new infrastructure.175179176180config BROKEN_ON_SMP177181 bool
+5-1
init/main.c
···15871587 * check if there is an early userspace init. If yes, let it do all15881588 * the work15891589 */15901590- if (init_eaccess(ramdisk_execute_command) != 0) {15901590+ int ramdisk_command_access;15911591+ ramdisk_command_access = init_eaccess(ramdisk_execute_command);15921592+ if (ramdisk_command_access != 0) {15931593+ pr_warn("check access for rdinit=%s failed: %i, ignoring\n",15941594+ ramdisk_execute_command, ramdisk_command_access);15911595 ramdisk_execute_command = NULL;15921596 prepare_namespace();15931597 }
···159159$(obj)/config_data: $(KCONFIG_CONFIG) FORCE160160 $(call filechk,cat)161161162162+# kheaders_data.tar.xz162163$(obj)/kheaders.o: $(obj)/kheaders_data.tar.xz163164164164-quiet_cmd_genikh = CHK $(obj)/kheaders_data.tar.xz165165- cmd_genikh = $(CONFIG_SHELL) $(srctree)/kernel/gen_kheaders.sh $@166166-$(obj)/kheaders_data.tar.xz: FORCE167167- $(call cmd,genikh)165165+quiet_cmd_kheaders_data = GEN $@166166+ cmd_kheaders_data = "$<" "$@" "$(obj)/kheaders-srclist" "$(obj)/kheaders-objlist" "$(KBUILD_BUILD_TIMESTAMP)"167167+ cmd_kheaders_data_dep = cat $(depfile) >> $(dot-target).cmd; rm -f $(depfile)168168169169-clean-files := kheaders_data.tar.xz kheaders.md5169169+define rule_kheaders_data170170+ $(call cmd_and_savecmd,kheaders_data)171171+ $(call cmd,kheaders_data_dep)172172+endef173173+174174+targets += kheaders_data.tar.xz175175+$(obj)/kheaders_data.tar.xz: $(src)/gen_kheaders.sh $(obj)/kheaders-srclist $(obj)/kheaders-objlist $(obj)/kheaders.md5 FORCE176176+ $(call if_changed_rule,kheaders_data)177177+178178+# generated headers in objtree179179+#180180+# include/generated/utsversion.h is ignored because it is generated181181+# after gen_kheaders.sh is executed. (utsversion.h is unneeded for kheaders)182182+filechk_kheaders_objlist = \183183+ for d in include "arch/$(SRCARCH)/include"; do \184184+ find "$${d}/generated" ! -path "include/generated/utsversion.h" -a -name "*.h" -print; \185185+ done186186+187187+$(obj)/kheaders-objlist: FORCE188188+ $(call filechk,kheaders_objlist)189189+190190+# non-generated headers in srctree191191+filechk_kheaders_srclist = \192192+ for d in include "arch/$(SRCARCH)/include"; do \193193+ find "$(srctree)/$${d}" -path "$(srctree)/$${d}/generated" -prune -o -name "*.h" -print; \194194+ done195195+196196+$(obj)/kheaders-srclist: FORCE197197+ $(call filechk,kheaders_srclist)198198+199199+# Some files are symlinks. If symlinks are changed, kheaders_data.tar.xz should200200+# be rebuilt.201201+filechk_kheaders_md5sum = xargs -r -a $< stat -c %N | md5sum202202+203203+$(obj)/kheaders.md5: $(obj)/kheaders-srclist FORCE204204+ $(call filechk,kheaders_md5sum)205205+206206+clean-files := kheaders.md5 kheaders-srclist kheaders-objlist
+15
kernel/crash_core.c
···2121#include <linux/reboot.h>2222#include <linux/btf.h>2323#include <linux/objtool.h>2424+#include <linux/delay.h>24252526#include <asm/page.h>2627#include <asm/sections.h>···33323433/* Per cpu memory for storing cpu states in case of system crash. */3534note_buf_t __percpu *crash_notes;3535+3636+/* time to wait for possible DMA to finish before starting the kdump kernel3737+ * when a CMA reservation is used3838+ */3939+#define CMA_DMA_TIMEOUT_SEC 1036403741#ifdef CONFIG_CRASH_DUMP3842···10397}10498EXPORT_SYMBOL_GPL(kexec_crash_loaded);10599100100+static void crash_cma_clear_pending_dma(void)101101+{102102+ if (!crashk_cma_cnt)103103+ return;104104+105105+ mdelay(CMA_DMA_TIMEOUT_SEC * 1000);106106+}107107+106108/*107109 * No panic_cpu check version of crash_kexec(). This function is called108110 * only when panic_cpu holds the current CPU number; this is the only CPU···133119 crash_setup_regs(&fixed_regs, regs);134120 crash_save_vmcoreinfo();135121 machine_crash_shutdown(&fixed_regs);122122+ crash_cma_clear_pending_dma();136123 machine_kexec(kexec_crash_image);137124 }138125 kexec_unlock();
+66-2
kernel/crash_reserve.c
···1414#include <linux/cpuhotplug.h>1515#include <linux/memblock.h>1616#include <linux/kmemleak.h>1717+#include <linux/cma.h>1818+#include <linux/crash_reserve.h>17191820#include <asm/page.h>1921#include <asm/sections.h>···174172175173#define SUFFIX_HIGH 0176174#define SUFFIX_LOW 1177177-#define SUFFIX_NULL 2175175+#define SUFFIX_CMA 2176176+#define SUFFIX_NULL 3178177static __initdata char *suffix_tbl[] = {179178 [SUFFIX_HIGH] = ",high",180179 [SUFFIX_LOW] = ",low",180180+ [SUFFIX_CMA] = ",cma",181181 [SUFFIX_NULL] = NULL,182182};183183184184/*185185 * That function parses "suffix" crashkernel command lines like186186 *187187- * crashkernel=size,[high|low]187187+ * crashkernel=size,[high|low|cma]188188 *189189 * It returns 0 on success and -EINVAL on failure.190190 */···302298 unsigned long long *crash_size,303299 unsigned long long *crash_base,304300 unsigned long long *low_size,301301+ unsigned long long *cma_size,305302 bool *high)306303{307304 int ret;305305+ unsigned long long __always_unused cma_base;308306309307 /* crashkernel=X[@offset] */310308 ret = __parse_crashkernel(cmdline, system_ram, crash_size,···337331338332 *high = true;339333 }334334+335335+ /*336336+ * optional CMA reservation337337+ * cma_base is ignored338338+ */339339+ if (cma_size)340340+ __parse_crashkernel(cmdline, 0, cma_size,341341+ &cma_base, suffix_tbl[SUFFIX_CMA]);340342#endif341343 if (!*crash_size)342344 ret = -EINVAL;···470456 insert_resource(&iomem_resource, &crashk_res);471457#endif472458}459459+460460+struct range crashk_cma_ranges[CRASHKERNEL_CMA_RANGES_MAX];461461+#ifdef CRASHKERNEL_CMA462462+int crashk_cma_cnt;463463+void __init reserve_crashkernel_cma(unsigned long long cma_size)464464+{465465+ unsigned long long request_size = roundup(cma_size, PAGE_SIZE);466466+ unsigned long long reserved_size = 0;467467+468468+ if (!cma_size)469469+ return;470470+471471+ while (cma_size > reserved_size &&472472+ crashk_cma_cnt < CRASHKERNEL_CMA_RANGES_MAX) {473473+474474+ struct cma *res;475475+476476+ if (cma_declare_contiguous(0, request_size, 0, 0, 0, false,477477+ "crashkernel", &res)) {478478+ /* reservation failed, try half-sized blocks */479479+ if (request_size <= PAGE_SIZE)480480+ break;481481+482482+ request_size = roundup(request_size / 2, PAGE_SIZE);483483+ continue;484484+ }485485+486486+ crashk_cma_ranges[crashk_cma_cnt].start = cma_get_base(res);487487+ crashk_cma_ranges[crashk_cma_cnt].end =488488+ crashk_cma_ranges[crashk_cma_cnt].start +489489+ cma_get_size(res) - 1;490490+ ++crashk_cma_cnt;491491+ reserved_size += request_size;492492+ }493493+494494+ if (cma_size > reserved_size)495495+ pr_warn("crashkernel CMA reservation failed: %lld MB requested, %lld MB reserved in %d ranges\n",496496+ cma_size >> 20, reserved_size >> 20, crashk_cma_cnt);497497+ else498498+ pr_info("crashkernel CMA reserved: %lld MB in %d ranges\n",499499+ reserved_size >> 20, crashk_cma_cnt);500500+}501501+502502+#else /* CRASHKERNEL_CMA */503503+void __init reserve_crashkernel_cma(unsigned long long cma_size)504504+{505505+ if (cma_size)506506+ pr_warn("crashkernel CMA reservation not supported\n");507507+}508508+#endif473509474510#ifndef HAVE_ARCH_ADD_CRASH_RES_TO_IOMEM_EARLY475511static __init int insert_crashkernel_resources(void)
+28-8
kernel/events/core.c
···68426842 return vmf->pgoff == 0 ? 0 : VM_FAULT_SIGBUS;68436843}6844684468456845+static int perf_mmap_may_split(struct vm_area_struct *vma, unsigned long addr)68466846+{68476847+ /*68486848+ * Forbid splitting perf mappings to prevent refcount leaks due to68496849+ * the resulting non-matching offsets and sizes. See open()/close().68506850+ */68516851+ return -EINVAL;68526852+}68536853+68456854static const struct vm_operations_struct perf_mmap_vmops = {68466855 .open = perf_mmap_open,68476856 .close = perf_mmap_close, /* non mergeable */68486857 .pfn_mkwrite = perf_mmap_pfn_mkwrite,68586858+ .may_split = perf_mmap_may_split,68496859};6850686068516861static int map_range(struct perf_buffer *rb, struct vm_area_struct *vma)···70617051 ret = 0;70627052 goto unlock;70637053 }70647064-70657065- atomic_set(&rb->aux_mmap_count, 1);70667054 }7067705570687056 user_lock_limit = sysctl_perf_event_mlock >> (PAGE_SHIFT - 10);···71237115 perf_event_update_time(event);71247116 perf_event_init_userpage(event);71257117 perf_event_update_userpage(event);71187118+ ret = 0;71267119 } else {71277120 ret = rb_alloc_aux(rb, event, vma->vm_pgoff, nr_pages,71287121 event->attr.aux_watermark, flags);71297129- if (!ret)71227122+ if (!ret) {71237123+ atomic_set(&rb->aux_mmap_count, 1);71307124 rb->aux_mmap_locked = extra;71257125+ }71317126 }71327132-71337133- ret = 0;7134712771357128unlock:71367129 if (!ret) {···7140713171417132 atomic_inc(&event->mmap_count);71427133 } else if (rb) {71347134+ /* AUX allocation failed */71437135 atomic_dec(&rb->mmap_count);71447136 }71457137aux_unlock:71467138 if (aux_mutex)71477139 mutex_unlock(aux_mutex);71487140 mutex_unlock(&event->mmap_mutex);71417141+71427142+ if (ret)71437143+ return ret;7149714471507145 /*71517146 * Since pinned accounting is per vm we cannot allow fork() to copy our···71587145 vm_flags_set(vma, VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP);71597146 vma->vm_ops = &perf_mmap_vmops;7160714771617161- if (!ret)71627162- ret = map_range(rb, vma);71637163-71647148 mapped = get_mapped(event, event_mapped);71657149 if (mapped)71667150 mapped(event, vma->vm_mm);71517151+71527152+ /*71537153+ * Try to map it into the page table. On fail, invoke71547154+ * perf_mmap_close() to undo the above, as the callsite expects71557155+ * full cleanup in this case and therefore does not invoke71567156+ * vmops::close().71577157+ */71587158+ ret = map_range(rb, vma);71597159+ if (ret)71607160+ perf_mmap_close(vma);7167716171687162 return ret;71697163}
+2-2
kernel/events/uprobes.c
···580580581581out:582582 /* Revert back reference counter if instruction update failed. */583583- if (ret < 0 && is_register && ref_ctr_updated)584584- update_ref_ctr(uprobe, mm, -1);583583+ if (ret < 0 && ref_ctr_updated)584584+ update_ref_ctr(uprobe, mm, is_register ? -1 : 1);585585586586 /* try collapse pmd for compound page */587587 if (ret > 0)
+1-6
kernel/exit.c
···693693}694694695695/*696696- * This does two things:697697- *698698- * A. Make init inherit all the child processes699699- * B. Check to see if any process groups have become orphaned700700- * as a result of our exiting, and if they have any stopped701701- * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)696696+ * Make init inherit all the child processes702697 */703698static void forget_original_parent(struct task_struct *father,704699 struct list_head *dead)
+53-51
kernel/fork.c
···189189 kmem_cache_free(task_struct_cachep, tsk);190190}191191192192-/*193193- * Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a194194- * kmemcache based allocator.195195- */196196-# if THREAD_SIZE >= PAGE_SIZE || defined(CONFIG_VMAP_STACK)197197-198198-# ifdef CONFIG_VMAP_STACK192192+#ifdef CONFIG_VMAP_STACK199193/*200194 * vmalloc() is a bit slow, and calling vfree() enough times will force a TLB201195 * flush. Try to minimize the number of calls by caching stacks.202196 */203197#define NR_CACHED_STACKS 2204198static DEFINE_PER_CPU(struct vm_struct *, cached_stacks[NR_CACHED_STACKS]);199199+/*200200+ * Allocated stacks are cached and later reused by new threads, so memcg201201+ * accounting is performed by the code assigning/releasing stacks to tasks.202202+ * We need a zeroed memory without __GFP_ACCOUNT.203203+ */204204+#define GFP_VMAP_STACK (GFP_KERNEL | __GFP_ZERO)205205206206struct vm_stack {207207 struct rcu_head rcu;208208 struct vm_struct *stack_vm_area;209209};210210211211-static bool try_release_thread_stack_to_cache(struct vm_struct *vm)211211+static bool try_release_thread_stack_to_cache(struct vm_struct *vm_area)212212{213213 unsigned int i;214214215215 for (i = 0; i < NR_CACHED_STACKS; i++) {216216 struct vm_struct *tmp = NULL;217217218218- if (this_cpu_try_cmpxchg(cached_stacks[i], &tmp, vm))218218+ if (this_cpu_try_cmpxchg(cached_stacks[i], &tmp, vm_area))219219 return true;220220 }221221 return false;···224224static void thread_stack_free_rcu(struct rcu_head *rh)225225{226226 struct vm_stack *vm_stack = container_of(rh, struct vm_stack, rcu);227227+ struct vm_struct *vm_area = vm_stack->stack_vm_area;227228228229 if (try_release_thread_stack_to_cache(vm_stack->stack_vm_area))229230 return;230231231231- vfree(vm_stack);232232+ vfree(vm_area->addr);232233}233234234235static void thread_stack_delayed_free(struct task_struct *tsk)···242241243242static int free_vm_stack_cache(unsigned int cpu)244243{245245- struct vm_struct **cached_vm_stacks = per_cpu_ptr(cached_stacks, cpu);244244+ struct vm_struct **cached_vm_stack_areas = per_cpu_ptr(cached_stacks, cpu);246245 int i;247246248247 for (i = 0; i < NR_CACHED_STACKS; i++) {249249- struct vm_struct *vm_stack = cached_vm_stacks[i];248248+ struct vm_struct *vm_area = cached_vm_stack_areas[i];250249251251- if (!vm_stack)250250+ if (!vm_area)252251 continue;253252254254- vfree(vm_stack->addr);255255- cached_vm_stacks[i] = NULL;253253+ vfree(vm_area->addr);254254+ cached_vm_stack_areas[i] = NULL;256255 }257256258257 return 0;259258}260259261261-static int memcg_charge_kernel_stack(struct vm_struct *vm)260260+static int memcg_charge_kernel_stack(struct vm_struct *vm_area)262261{263262 int i;264263 int ret;265264 int nr_charged = 0;266265267267- BUG_ON(vm->nr_pages != THREAD_SIZE / PAGE_SIZE);266266+ BUG_ON(vm_area->nr_pages != THREAD_SIZE / PAGE_SIZE);268267269268 for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++) {270270- ret = memcg_kmem_charge_page(vm->pages[i], GFP_KERNEL, 0);269269+ ret = memcg_kmem_charge_page(vm_area->pages[i], GFP_KERNEL, 0);271270 if (ret)272271 goto err;273272 nr_charged++;···275274 return 0;276275err:277276 for (i = 0; i < nr_charged; i++)278278- memcg_kmem_uncharge_page(vm->pages[i], 0);277277+ memcg_kmem_uncharge_page(vm_area->pages[i], 0);279278 return ret;280279}281280282281static int alloc_thread_stack_node(struct task_struct *tsk, int node)283282{284284- struct vm_struct *vm;283283+ struct vm_struct *vm_area;285284 void *stack;286285 int i;287286288287 for (i = 0; i < NR_CACHED_STACKS; i++) {289289- struct vm_struct *s;290290-291291- s = this_cpu_xchg(cached_stacks[i], NULL);292292-293293- if (!s)288288+ vm_area = this_cpu_xchg(cached_stacks[i], NULL);289289+ if (!vm_area)294290 continue;295291296292 /* Reset stack metadata. */297297- kasan_unpoison_range(s->addr, THREAD_SIZE);293293+ kasan_unpoison_range(vm_area->addr, THREAD_SIZE);298294299299- stack = kasan_reset_tag(s->addr);295295+ stack = kasan_reset_tag(vm_area->addr);300296301297 /* Clear stale pointers from reused stack. */302298 memset(stack, 0, THREAD_SIZE);303299304304- if (memcg_charge_kernel_stack(s)) {305305- vfree(s->addr);300300+ if (memcg_charge_kernel_stack(vm_area)) {301301+ vfree(vm_area->addr);306302 return -ENOMEM;307303 }308304309309- tsk->stack_vm_area = s;305305+ tsk->stack_vm_area = vm_area;310306 tsk->stack = stack;311307 return 0;312308 }313309314314- /*315315- * Allocated stacks are cached and later reused by new threads,316316- * so memcg accounting is performed manually on assigning/releasing317317- * stacks to tasks. Drop __GFP_ACCOUNT.318318- */319310 stack = __vmalloc_node(THREAD_SIZE, THREAD_ALIGN,320320- THREADINFO_GFP & ~__GFP_ACCOUNT,311311+ GFP_VMAP_STACK,321312 node, __builtin_return_address(0));322313 if (!stack)323314 return -ENOMEM;324315325325- vm = find_vm_area(stack);326326- if (memcg_charge_kernel_stack(vm)) {316316+ vm_area = find_vm_area(stack);317317+ if (memcg_charge_kernel_stack(vm_area)) {327318 vfree(stack);328319 return -ENOMEM;329320 }···324331 * free_thread_stack() can be called in interrupt context,325332 * so cache the vm_struct.326333 */327327- tsk->stack_vm_area = vm;334334+ tsk->stack_vm_area = vm_area;328335 stack = kasan_reset_tag(stack);329336 tsk->stack = stack;330337 return 0;···339346 tsk->stack_vm_area = NULL;340347}341348342342-# else /* !CONFIG_VMAP_STACK */349349+#else /* !CONFIG_VMAP_STACK */350350+351351+/*352352+ * Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a353353+ * kmemcache based allocator.354354+ */355355+#if THREAD_SIZE >= PAGE_SIZE343356344357static void thread_stack_free_rcu(struct rcu_head *rh)345358{···377378 tsk->stack = NULL;378379}379380380380-# endif /* CONFIG_VMAP_STACK */381381-# else /* !(THREAD_SIZE >= PAGE_SIZE || defined(CONFIG_VMAP_STACK)) */381381+#else /* !(THREAD_SIZE >= PAGE_SIZE) */382382383383static struct kmem_cache *thread_stack_cache;384384···416418 BUG_ON(thread_stack_cache == NULL);417419}418420419419-# endif /* THREAD_SIZE >= PAGE_SIZE || defined(CONFIG_VMAP_STACK) */421421+#endif /* THREAD_SIZE >= PAGE_SIZE */422422+#endif /* CONFIG_VMAP_STACK */420423421424/* SLAB cache for signal_struct structures (tsk->signal) */422425static struct kmem_cache *signal_cachep;···437438static void account_kernel_stack(struct task_struct *tsk, int account)438439{439440 if (IS_ENABLED(CONFIG_VMAP_STACK)) {440440- struct vm_struct *vm = task_stack_vm_area(tsk);441441+ struct vm_struct *vm_area = task_stack_vm_area(tsk);441442 int i;442443443444 for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++)444444- mod_lruvec_page_state(vm->pages[i], NR_KERNEL_STACK_KB,445445+ mod_lruvec_page_state(vm_area->pages[i], NR_KERNEL_STACK_KB,445446 account * (PAGE_SIZE / 1024));446447 } else {447448 void *stack = task_stack_page(tsk);···457458 account_kernel_stack(tsk, -1);458459459460 if (IS_ENABLED(CONFIG_VMAP_STACK)) {460460- struct vm_struct *vm;461461+ struct vm_struct *vm_area;461462 int i;462463463463- vm = task_stack_vm_area(tsk);464464+ vm_area = task_stack_vm_area(tsk);464465 for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++)465465- memcg_kmem_uncharge_page(vm->pages[i], 0);466466+ memcg_kmem_uncharge_page(vm_area->pages[i], 0);466467 }467468}468469···585586 for (i = 0; i < NR_MM_COUNTERS; i++) {586587 long x = percpu_counter_sum(&mm->rss_stat[i]);587588588588- if (unlikely(x))589589- pr_alert("BUG: Bad rss-counter state mm:%p type:%s val:%ld\n",590590- mm, resident_page_types[i], x);589589+ if (unlikely(x)) {590590+ pr_alert("BUG: Bad rss-counter state mm:%p type:%s val:%ld Comm:%s Pid:%d\n",591591+ mm, resident_page_types[i], x,592592+ current->comm,593593+ task_pid_nr(current));594594+ }591595 }592596593597 if (mm_pgtables_bytes(mm))
+22-71
kernel/gen_kheaders.sh
···44# This script generates an archive consisting of kernel headers55# for CONFIG_IKHEADERS.66set -e77-sfile="$(readlink -f "$0")"88-outdir="$(pwd)"97tarfile=$11010-tmpdir=$outdir/${tarfile%/*}/.tmp_dir88+srclist=$299+objlist=$31010+timestamp=$411111212-dir_list="1313-include/1414-arch/$SRCARCH/include/1515-"1212+dir=$(dirname "${tarfile}")1313+tmpdir=${dir}/.tmp_dir1414+depfile=${dir}/.$(basename "${tarfile}").d16151717-# Support incremental builds by skipping archive generation1818-# if timestamps of files being archived are not changed.1616+# generate dependency list.1717+{1818+ echo1919+ echo "deps_${tarfile} := \\"2020+ sed 's:\(.*\): \1 \\:' "${srclist}"2121+ sed -n '/^include\/generated\/autoconf\.h$/!s:\(.*\): \1 \\:p' "${objlist}"2222+ echo2323+ echo "${tarfile}: \$(deps_${tarfile})"2424+ echo2525+ echo "\$(deps_${tarfile}):"19262020-# This block is useful for debugging the incremental builds.2121-# Uncomment it for debugging.2222-# if [ ! -f /tmp/iter ]; then iter=1; echo 1 > /tmp/iter;2323-# else iter=$(($(cat /tmp/iter) + 1)); echo $iter > /tmp/iter; fi2424-# find $all_dirs -name "*.h" | xargs ls -l > /tmp/ls-$iter2525-2626-all_dirs=2727-if [ "$building_out_of_srctree" ]; then2828- for d in $dir_list; do2929- all_dirs="$all_dirs $srctree/$d"3030- done3131-fi3232-all_dirs="$all_dirs $dir_list"3333-3434-# include/generated/utsversion.h is ignored because it is generated after this3535-# script is executed. (utsversion.h is unneeded for kheaders)3636-#3737-# When Kconfig regenerates include/generated/autoconf.h, its timestamp is3838-# updated, but the contents might be still the same. When any CONFIG option is3939-# changed, Kconfig touches the corresponding timestamp file include/config/*.4040-# Hence, the md5sum detects the configuration change anyway. We do not need to4141-# check include/generated/autoconf.h explicitly.4242-#4343-# Ignore them for md5 calculation to avoid pointless regeneration.4444-headers_md5="$(find $all_dirs -name "*.h" -a \4545- ! -path include/generated/utsversion.h -a \4646- ! -path include/generated/autoconf.h |4747- xargs ls -l | md5sum | cut -d ' ' -f1)"4848-4949-# Any changes to this script will also cause a rebuild of the archive.5050-this_file_md5="$(ls -l $sfile | md5sum | cut -d ' ' -f1)"5151-if [ -f $tarfile ]; then tarfile_md5="$(md5sum $tarfile | cut -d ' ' -f1)"; fi5252-if [ -f kernel/kheaders.md5 ] &&5353- [ "$(head -n 1 kernel/kheaders.md5)" = "$headers_md5" ] &&5454- [ "$(head -n 2 kernel/kheaders.md5 | tail -n 1)" = "$this_file_md5" ] &&5555- [ "$(tail -n 1 kernel/kheaders.md5)" = "$tarfile_md5" ]; then5656- exit5757-fi5858-5959-echo " GEN $tarfile"2727+} > "${depfile}"60286129rm -rf "${tmpdir}"6230mkdir "${tmpdir}"63316464-if [ "$building_out_of_srctree" ]; then6565- (6666- cd $srctree6767- for f in $dir_list6868- do find "$f" -name "*.h";6969- done | tar -c -f - -T - | tar -xf - -C "${tmpdir}"7070- )7171-fi7272-7373-for f in $dir_list;7474- do find "$f" -name "*.h";7575-done | tar -c -f - -T - | tar -xf - -C "${tmpdir}"7676-7777-# Always exclude include/generated/utsversion.h7878-# Otherwise, the contents of the tarball may vary depending on the build steps.7979-rm -f "${tmpdir}/include/generated/utsversion.h"3232+# shellcheck disable=SC2154 # srctree is passed as an env variable3333+sed "s:^${srctree}/::" "${srclist}" | ${TAR} -c -f - -C "${srctree}" -T - | ${TAR} -xf - -C "${tmpdir}"3434+${TAR} -c -f - -T "${objlist}" | ${TAR} -xf - -C "${tmpdir}"80358136# Remove comments except SDPX lines8237# Use a temporary file to store directory contents to prevent find/xargs from···4388rm -f "${tmpdir}.contents.txt"44894590# Create archive and try to normalize metadata for reproducibility.4646-tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \9191+${TAR} "${timestamp:+--mtime=$timestamp}" \4792 --owner=0 --group=0 --sort=name --numeric-owner --mode=u=rw,go=r,a+X \4848- -I $XZ -cf $tarfile -C "${tmpdir}/" . > /dev/null4949-5050-echo $headers_md5 > kernel/kheaders.md55151-echo "$this_file_md5" >> kernel/kheaders.md55252-echo "$(md5sum $tarfile | cut -d ' ' -f1)" >> kernel/kheaders.md59393+ -I "${XZ}" -cf "${tarfile}" -C "${tmpdir}/" . > /dev/null53945495rm -rf "${tmpdir}"
+25-4
kernel/hung_task.c
···2323#include <linux/sched/debug.h>2424#include <linux/sched/sysctl.h>2525#include <linux/hung_task.h>2626+#include <linux/rwsem.h>26272728#include <trace/events/sched.h>2829···101100{102101 struct task_struct *g, *t;103102 unsigned long owner, blocker, blocker_type;103103+ const char *rwsem_blocked_by, *rwsem_blocked_as;104104105105 RCU_LOCKDEP_WARN(!rcu_read_lock_held(), "No rcu lock held");106106···113111114112 switch (blocker_type) {115113 case BLOCKER_TYPE_MUTEX:116116- owner = mutex_get_owner(117117- (struct mutex *)hung_task_blocker_to_lock(blocker));114114+ owner = mutex_get_owner(hung_task_blocker_to_lock(blocker));118115 break;119116 case BLOCKER_TYPE_SEM:120120- owner = sem_last_holder(121121- (struct semaphore *)hung_task_blocker_to_lock(blocker));117117+ owner = sem_last_holder(hung_task_blocker_to_lock(blocker));118118+ break;119119+ case BLOCKER_TYPE_RWSEM_READER:120120+ case BLOCKER_TYPE_RWSEM_WRITER:121121+ owner = (unsigned long)rwsem_owner(122122+ hung_task_blocker_to_lock(blocker));123123+ rwsem_blocked_as = (blocker_type == BLOCKER_TYPE_RWSEM_READER) ?124124+ "reader" : "writer";125125+ rwsem_blocked_by = is_rwsem_reader_owned(126126+ hung_task_blocker_to_lock(blocker)) ?127127+ "reader" : "writer";122128 break;123129 default:124130 WARN_ON_ONCE(1);···142132 break;143133 case BLOCKER_TYPE_SEM:144134 pr_err("INFO: task %s:%d is blocked on a semaphore, but the last holder is not found.\n",135135+ task->comm, task->pid);136136+ break;137137+ case BLOCKER_TYPE_RWSEM_READER:138138+ case BLOCKER_TYPE_RWSEM_WRITER:139139+ pr_err("INFO: task %s:%d is blocked on an rw-semaphore, but the owner is not found.\n",145140 task->comm, task->pid);146141 break;147142 }···166151 case BLOCKER_TYPE_SEM:167152 pr_err("INFO: task %s:%d blocked on a semaphore likely last held by task %s:%d\n",168153 task->comm, task->pid, t->comm, t->pid);154154+ break;155155+ case BLOCKER_TYPE_RWSEM_READER:156156+ case BLOCKER_TYPE_RWSEM_WRITER:157157+ pr_err("INFO: task %s:%d <%s> blocked on an rw-semaphore likely owned by task %s:%d <%s>\n",158158+ task->comm, task->pid, rwsem_blocked_as, t->comm,159159+ t->pid, rwsem_blocked_by);169160 break;170161 }171162 sched_show_task(t);
+1-1
kernel/kcov.c
···552552553553/*554554 * Fault in a lazily-faulted vmalloc area before it can be used by555555- * __santizer_cov_trace_pc(), to avoid recursion issues if any code on the555555+ * __sanitizer_cov_trace_pc(), to avoid recursion issues if any code on the556556 * vmalloc fault handling path is instrumented.557557 */558558static void kcov_fault_in_area(struct kcov *kcov)
+1-1
kernel/kexec.c
···152152 goto out;153153154154 for (i = 0; i < nr_segments; i++) {155155- ret = kimage_load_segment(image, &image->segment[i]);155155+ ret = kimage_load_segment(image, i);156156 if (ret)157157 goto out;158158 }
+92-8
kernel/kexec_core.c
···4040#include <linux/hugetlb.h>4141#include <linux/objtool.h>4242#include <linux/kmsg_dump.h>4343+#include <linux/dma-map-ops.h>43444445#include <asm/page.h>4546#include <asm/sections.h>···554553 kimage_free_pages(page);555554}556555556556+static void kimage_free_cma(struct kimage *image)557557+{558558+ unsigned long i;559559+560560+ for (i = 0; i < image->nr_segments; i++) {561561+ struct page *cma = image->segment_cma[i];562562+ u32 nr_pages = image->segment[i].memsz >> PAGE_SHIFT;563563+564564+ if (!cma)565565+ continue;566566+567567+ arch_kexec_pre_free_pages(page_address(cma), nr_pages);568568+ dma_release_from_contiguous(NULL, cma, nr_pages);569569+ image->segment_cma[i] = NULL;570570+ }571571+572572+}573573+557574void kimage_free(struct kimage *image)558575{559576 kimage_entry_t *ptr, entry;···609590610591 /* Free the kexec control pages... */611592 kimage_free_page_list(&image->control_pages);593593+594594+ /* Free CMA allocations */595595+ kimage_free_cma(image);612596613597 /*614598 * Free up any temporary buffers allocated. This might hit if···738716 return page;739717}740718741741-static int kimage_load_normal_segment(struct kimage *image,742742- struct kexec_segment *segment)719719+static int kimage_load_cma_segment(struct kimage *image, int idx)743720{721721+ struct kexec_segment *segment = &image->segment[idx];722722+ struct page *cma = image->segment_cma[idx];723723+ char *ptr = page_address(cma);724724+ unsigned long maddr;725725+ size_t ubytes, mbytes;726726+ int result = 0;727727+ unsigned char __user *buf = NULL;728728+ unsigned char *kbuf = NULL;729729+730730+ if (image->file_mode)731731+ kbuf = segment->kbuf;732732+ else733733+ buf = segment->buf;734734+ ubytes = segment->bufsz;735735+ mbytes = segment->memsz;736736+ maddr = segment->mem;737737+738738+ /* Then copy from source buffer to the CMA one */739739+ while (mbytes) {740740+ size_t uchunk, mchunk;741741+742742+ ptr += maddr & ~PAGE_MASK;743743+ mchunk = min_t(size_t, mbytes,744744+ PAGE_SIZE - (maddr & ~PAGE_MASK));745745+ uchunk = min(ubytes, mchunk);746746+747747+ if (uchunk) {748748+ /* For file based kexec, source pages are in kernel memory */749749+ if (image->file_mode)750750+ memcpy(ptr, kbuf, uchunk);751751+ else752752+ result = copy_from_user(ptr, buf, uchunk);753753+ ubytes -= uchunk;754754+ if (image->file_mode)755755+ kbuf += uchunk;756756+ else757757+ buf += uchunk;758758+ }759759+760760+ if (result) {761761+ result = -EFAULT;762762+ goto out;763763+ }764764+765765+ ptr += mchunk;766766+ maddr += mchunk;767767+ mbytes -= mchunk;768768+769769+ cond_resched();770770+ }771771+772772+ /* Clear any remainder */773773+ memset(ptr, 0, mbytes);774774+775775+out:776776+ return result;777777+}778778+779779+static int kimage_load_normal_segment(struct kimage *image, int idx)780780+{781781+ struct kexec_segment *segment = &image->segment[idx];744782 unsigned long maddr;745783 size_t ubytes, mbytes;746784 int result;···814732 ubytes = segment->bufsz;815733 mbytes = segment->memsz;816734 maddr = segment->mem;735735+736736+ if (image->segment_cma[idx])737737+ return kimage_load_cma_segment(image, idx);817738818739 result = kimage_set_destination(image, maddr);819740 if (result < 0)···872787}873788874789#ifdef CONFIG_CRASH_DUMP875875-static int kimage_load_crash_segment(struct kimage *image,876876- struct kexec_segment *segment)790790+static int kimage_load_crash_segment(struct kimage *image, int idx)877791{878792 /* For crash dumps kernels we simply copy the data from879793 * user space to it's destination.880794 * We do things a page at a time for the sake of kmap.881795 */796796+ struct kexec_segment *segment = &image->segment[idx];882797 unsigned long maddr;883798 size_t ubytes, mbytes;884799 int result;···943858}944859#endif945860946946-int kimage_load_segment(struct kimage *image,947947- struct kexec_segment *segment)861861+int kimage_load_segment(struct kimage *image, int idx)948862{949863 int result = -ENOMEM;950864951865 switch (image->type) {952866 case KEXEC_TYPE_DEFAULT:953953- result = kimage_load_normal_segment(image, segment);867867+ result = kimage_load_normal_segment(image, idx);954868 break;955869#ifdef CONFIG_CRASH_DUMP956870 case KEXEC_TYPE_CRASH:957957- result = kimage_load_crash_segment(image, segment);871871+ result = kimage_load_crash_segment(image, idx);958872 break;959873#endif960874 }
+50-1
kernel/kexec_file.c
···2626#include <linux/kernel_read_file.h>2727#include <linux/syscalls.h>2828#include <linux/vmalloc.h>2929+#include <linux/dma-map-ops.h>2930#include "kexec_internal.h"30313132#ifdef CONFIG_KEXEC_SIG···254253 ret = 0;255254 }256255256256+ image->no_cma = !!(flags & KEXEC_FILE_NO_CMA);257257+257258 if (cmdline_len) {258259 image->cmdline_buf = memdup_user(cmdline_ptr, cmdline_len);259260 if (IS_ERR(image->cmdline_buf)) {···437434 i, ksegment->buf, ksegment->bufsz, ksegment->mem,438435 ksegment->memsz);439436440440- ret = kimage_load_segment(image, &image->segment[i]);437437+ ret = kimage_load_segment(image, i);441438 if (ret)442439 goto out;443440 }···666663 return walk_system_ram_res(0, ULONG_MAX, kbuf, func);667664}668665666666+static int kexec_alloc_contig(struct kexec_buf *kbuf)667667+{668668+ size_t nr_pages = kbuf->memsz >> PAGE_SHIFT;669669+ unsigned long mem;670670+ struct page *p;671671+672672+ /* User space disabled CMA allocations, bail out. */673673+ if (kbuf->image->no_cma)674674+ return -EPERM;675675+676676+ /* Skip CMA logic for crash kernel */677677+ if (kbuf->image->type == KEXEC_TYPE_CRASH)678678+ return -EPERM;679679+680680+ p = dma_alloc_from_contiguous(NULL, nr_pages, get_order(kbuf->buf_align), true);681681+ if (!p)682682+ return -ENOMEM;683683+684684+ pr_debug("allocated %zu DMA pages at 0x%lx", nr_pages, page_to_boot_pfn(p));685685+686686+ mem = page_to_boot_pfn(p) << PAGE_SHIFT;687687+688688+ if (kimage_is_destination_range(kbuf->image, mem, mem + kbuf->memsz)) {689689+ /* Our region is already in use by a statically defined one. Bail out. */690690+ pr_debug("CMA overlaps existing mem: 0x%lx+0x%lx\n", mem, kbuf->memsz);691691+ dma_release_from_contiguous(NULL, p, nr_pages);692692+ return -EBUSY;693693+ }694694+695695+ kbuf->mem = page_to_boot_pfn(p) << PAGE_SHIFT;696696+ kbuf->cma = p;697697+698698+ arch_kexec_post_alloc_pages(page_address(p), (int)nr_pages, 0);699699+700700+ return 0;701701+}702702+669703/**670704 * kexec_locate_mem_hole - find free memory for the purgatory or the next kernel671705 * @kbuf: Parameters for the memory search.···726686 ret = kho_locate_mem_hole(kbuf, locate_mem_hole_callback);727687 if (ret <= 0)728688 return ret;689689+690690+ /*691691+ * Try to find a free physically contiguous block of memory first. With that, we692692+ * can avoid any copying at kexec time.693693+ */694694+ if (!kexec_alloc_contig(kbuf))695695+ return 0;729696730697 if (!IS_ENABLED(CONFIG_ARCH_KEEP_MEMBLOCK))731698 ret = kexec_walk_resources(kbuf, locate_mem_hole_callback);···779732 /* Ensure minimum alignment needed for segments. */780733 kbuf->memsz = ALIGN(kbuf->memsz, PAGE_SIZE);781734 kbuf->buf_align = max(kbuf->buf_align, PAGE_SIZE);735735+ kbuf->cma = NULL;782736783737 /* Walk the RAM ranges and allocate a suitable range for the buffer */784738 ret = arch_kexec_locate_mem_hole(kbuf);···792744 ksegment->bufsz = kbuf->bufsz;793745 ksegment->mem = kbuf->mem;794746 ksegment->memsz = kbuf->memsz;747747+ kbuf->image->segment_cma[kbuf->image->nr_segments] = kbuf->cma;795748 kbuf->image->nr_segments++;796749 return 0;797750}
···8888/*8989 * Variant of to_kthread() that doesn't assume @p is a kthread.9090 *9191- * Per construction; when:9191+ * When "(p->flags & PF_KTHREAD)" is set the task is a kthread and will9292+ * always remain a kthread. For kthreads p->worker_private always9393+ * points to a struct kthread. For tasks that are not kthreads9494+ * p->worker_private is used to point to other things.9295 *9393- * (p->flags & PF_KTHREAD) && p->worker_private9494- *9595- * the task is both a kthread and struct kthread is persistent. However9696- * PF_KTHREAD on it's own is not, kernel_thread() can exec() (See umh.c and9797- * begin_new_exec()).9696+ * Return NULL for any task that is not a kthread.9897 */9998static inline struct kthread *__to_kthread(struct task_struct *p)10099{
+23-8
kernel/locking/rwsem.c
···2727#include <linux/export.h>2828#include <linux/rwsem.h>2929#include <linux/atomic.h>3030+#include <linux/hung_task.h>3031#include <trace/events/lock.h>31323233#ifndef CONFIG_PREEMPT_RT···182181 __rwsem_set_reader_owned(sem, current);183182}184183185185-#ifdef CONFIG_DEBUG_RWSEMS184184+#if defined(CONFIG_DEBUG_RWSEMS) || defined(CONFIG_DETECT_HUNG_TASK_BLOCKER)186185/*187186 * Return just the real task structure pointer of the owner188187 */189189-static inline struct task_struct *rwsem_owner(struct rw_semaphore *sem)188188+struct task_struct *rwsem_owner(struct rw_semaphore *sem)190189{191190 return (struct task_struct *)192191 (atomic_long_read(&sem->owner) & ~RWSEM_OWNER_FLAGS_MASK);···195194/*196195 * Return true if the rwsem is owned by a reader.197196 */198198-static inline bool is_rwsem_reader_owned(struct rw_semaphore *sem)197197+bool is_rwsem_reader_owned(struct rw_semaphore *sem)199198{200199 /*201200 * Check the count to see if it is write-locked.···208207}209208210209/*211211- * With CONFIG_DEBUG_RWSEMS configured, it will make sure that if there212212- * is a task pointer in owner of a reader-owned rwsem, it will be the213213- * real owner or one of the real owners. The only exception is when the214214- * unlock is done by up_read_non_owner().210210+ * With CONFIG_DEBUG_RWSEMS or CONFIG_DETECT_HUNG_TASK_BLOCKER configured,211211+ * it will make sure that the owner field of a reader-owned rwsem either212212+ * points to a real reader-owner(s) or gets cleared. The only exception is213213+ * when the unlock is done by up_read_non_owner().215214 */216215static inline void rwsem_clear_reader_owned(struct rw_semaphore *sem)217216{···10641063 wake_up_q(&wake_q);1065106410661065 trace_contention_begin(sem, LCB_F_READ);10661066+ set_current_state(state);10671067+10681068+ if (state == TASK_UNINTERRUPTIBLE)10691069+ hung_task_set_blocker(sem, BLOCKER_TYPE_RWSEM_READER);1067107010681071 /* wait to be given the lock */10691072 for (;;) {10701070- set_current_state(state);10711073 if (!smp_load_acquire(&waiter.task)) {10721074 /* Matches rwsem_mark_wake()'s smp_store_release(). */10731075 break;···10851081 }10861082 schedule_preempt_disabled();10871083 lockevent_inc(rwsem_sleep_reader);10841084+ set_current_state(state);10881085 }10861086+10871087+ if (state == TASK_UNINTERRUPTIBLE)10881088+ hung_task_clear_blocker();1089108910901090 __set_current_state(TASK_RUNNING);10911091 lockevent_inc(rwsem_rlock);···11521144 set_current_state(state);11531145 trace_contention_begin(sem, LCB_F_WRITE);1154114611471147+ if (state == TASK_UNINTERRUPTIBLE)11481148+ hung_task_set_blocker(sem, BLOCKER_TYPE_RWSEM_WRITER);11491149+11551150 for (;;) {11561151 if (rwsem_try_write_lock(sem, &waiter)) {11571152 /* rwsem_try_write_lock() implies ACQUIRE on success */···11881177trylock_again:11891178 raw_spin_lock_irq(&sem->wait_lock);11901179 }11801180+11811181+ if (state == TASK_UNINTERRUPTIBLE)11821182+ hung_task_clear_blocker();11831183+11911184 __set_current_state(TASK_RUNNING);11921185 raw_spin_unlock_irq(&sem->wait_lock);11931186 lockevent_inc(rwsem_wlock);
···608608MODINFO_ATTR(srcversion);609609610610static struct {611611- char name[MODULE_NAME_LEN + 1];611611+ char name[MODULE_NAME_LEN];612612 char taints[MODULE_FLAGS_BUF_SIZE];613613} last_unloaded_module;614614···779779 struct module *mod;780780 char name[MODULE_NAME_LEN];781781 char buf[MODULE_FLAGS_BUF_SIZE];782782- int ret, forced = 0;782782+ int ret, len, forced = 0;783783784784 if (!capable(CAP_SYS_MODULE) || modules_disabled)785785 return -EPERM;786786787787- if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)788788- return -EFAULT;789789- name[MODULE_NAME_LEN-1] = '\0';787787+ len = strncpy_from_user(name, name_user, MODULE_NAME_LEN);788788+ if (len == 0 || len == MODULE_NAME_LEN)789789+ return -ENOENT;790790+ if (len < 0)791791+ return len;790792791793 audit_log_kern_module(name);792794···13221320 else13231321 execmem_type = EXECMEM_MODULE_TEXT;1324132213251325- ptr = execmem_alloc(execmem_type, size);13231323+ ptr = execmem_alloc_rw(execmem_type, size);13261324 if (!ptr)13271325 return -ENOMEM;1328132613291329- if (execmem_is_rox(execmem_type)) {13301330- int err = execmem_make_temp_rw(ptr, size);13311331-13321332- if (err) {13331333- execmem_free(ptr);13341334- return -ENOMEM;13351335- }13361336-13371337- mod->mem[type].is_rox = true;13381338- }13271327+ mod->mem[type].is_rox = execmem_is_rox(execmem_type);1339132813401329 /*13411330 * The pointer to these blocks of memory are stored on the module
+32-39
kernel/panic.c
···3636#include <linux/sysfs.h>3737#include <linux/context_tracking.h>3838#include <linux/seq_buf.h>3939+#include <linux/sys_info.h>3940#include <trace/events/error_report.h>4041#include <asm/sections.h>4142···6463unsigned long panic_on_taint;6564bool panic_on_taint_nousertaint = false;6665static unsigned int warn_limit __read_mostly;6666+static bool panic_console_replay;67676868bool panic_triggering_all_cpu_backtrace;69697070int panic_timeout = CONFIG_PANIC_TIMEOUT;7171EXPORT_SYMBOL_GPL(panic_timeout);72727373-#define PANIC_PRINT_TASK_INFO 0x000000017474-#define PANIC_PRINT_MEM_INFO 0x000000027575-#define PANIC_PRINT_TIMER_INFO 0x000000047676-#define PANIC_PRINT_LOCK_INFO 0x000000087777-#define PANIC_PRINT_FTRACE_INFO 0x000000107878-#define PANIC_PRINT_ALL_PRINTK_MSG 0x000000207979-#define PANIC_PRINT_ALL_CPU_BT 0x000000408080-#define PANIC_PRINT_BLOCKED_TASKS 0x000000808173unsigned long panic_print;82748375ATOMIC_NOTIFIER_HEAD(panic_notifier_list);···122128 return err;123129}124130131131+static int sysctl_panic_print_handler(const struct ctl_table *table, int write,132132+ void *buffer, size_t *lenp, loff_t *ppos)133133+{134134+ pr_info_once("Kernel: 'panic_print' sysctl interface will be obsoleted by both 'panic_sys_info' and 'panic_console_replay'\n");135135+ return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);136136+}137137+125138static const struct ctl_table kern_panic_table[] = {126139#ifdef CONFIG_SMP127140 {···166165 .data = &panic_print,167166 .maxlen = sizeof(unsigned long),168167 .mode = 0644,169169- .proc_handler = proc_doulongvec_minmax,168168+ .proc_handler = sysctl_panic_print_handler,170169 },171170 {172171 .procname = "panic_on_warn",···194193 .proc_handler = proc_dointvec,195194 },196195#endif196196+ {197197+ .procname = "panic_sys_info",198198+ .data = &panic_print,199199+ .maxlen = sizeof(panic_print),200200+ .mode = 0644,201201+ .proc_handler = sysctl_sys_info_handler,202202+ },197203};198204199205static __init int kernel_panic_sysctls_init(void)···210202}211203late_initcall(kernel_panic_sysctls_init);212204#endif205205+206206+/* The format is "panic_sys_info=tasks,mem,locks,ftrace,..." */207207+static int __init setup_panic_sys_info(char *buf)208208+{209209+ /* There is no risk of race in kernel boot phase */210210+ panic_print = sys_info_parse_param(buf);211211+ return 1;212212+}213213+__setup("panic_sys_info=", setup_panic_sys_info);213214214215static atomic_t warn_count = ATOMIC_INIT(0);215216···315298}316299EXPORT_SYMBOL(nmi_panic);317300318318-static void panic_print_sys_info(bool console_flush)319319-{320320- if (console_flush) {321321- if (panic_print & PANIC_PRINT_ALL_PRINTK_MSG)322322- console_flush_on_panic(CONSOLE_REPLAY_ALL);323323- return;324324- }325325-326326- if (panic_print & PANIC_PRINT_TASK_INFO)327327- show_state();328328-329329- if (panic_print & PANIC_PRINT_MEM_INFO)330330- show_mem();331331-332332- if (panic_print & PANIC_PRINT_TIMER_INFO)333333- sysrq_timer_list_show();334334-335335- if (panic_print & PANIC_PRINT_LOCK_INFO)336336- debug_show_all_locks();337337-338338- if (panic_print & PANIC_PRINT_FTRACE_INFO)339339- ftrace_dump(DUMP_ALL);340340-341341- if (panic_print & PANIC_PRINT_BLOCKED_TASKS)342342- show_state_filter(TASK_UNINTERRUPTIBLE);343343-}344344-345301void check_panic_on_warn(const char *origin)346302{347303 unsigned int limit;···335345 */336346static void panic_other_cpus_shutdown(bool crash_kexec)337347{338338- if (panic_print & PANIC_PRINT_ALL_CPU_BT) {348348+ if (panic_print & SYS_INFO_ALL_CPU_BT) {339349 /* Temporary allow non-panic CPUs to write their backtraces. */340350 panic_triggering_all_cpu_backtrace = true;341351 trigger_all_cpu_backtrace();···458468 */459469 atomic_notifier_call_chain(&panic_notifier_list, 0, buf);460470461461- panic_print_sys_info(false);471471+ sys_info(panic_print);462472463473 kmsg_dump_desc(KMSG_DUMP_PANIC, buf);464474···487497 debug_locks_off();488498 console_flush_on_panic(CONSOLE_FLUSH_PENDING);489499490490- panic_print_sys_info(true);500500+ if ((panic_print & SYS_INFO_PANIC_CONSOLE_REPLAY) ||501501+ panic_console_replay)502502+ console_flush_on_panic(CONSOLE_REPLAY_ALL);491503492504 if (!panic_blink)493505 panic_blink = no_blink;···941949core_param(pause_on_oops, pause_on_oops, int, 0644);942950core_param(panic_on_warn, panic_on_warn, int, 0644);943951core_param(crash_kexec_post_notifiers, crash_kexec_post_notifiers, bool, 0644);952952+core_param(panic_console_replay, panic_console_replay, bool, 0644);944953945954static int __init oops_setup(char *s)946955{
+2
kernel/printk/internal.h
···64646565extern struct printk_ringbuffer *prb;6666extern bool printk_kthreads_running;6767+extern bool printk_kthreads_ready;6768extern bool debug_non_panic_cpus;68696970__printf(4, 0)···180179#define PRINTKRB_RECORD_MAX 0181180182181#define printk_kthreads_running (false)182182+#define printk_kthreads_ready (false)183183184184/*185185 * In !PRINTK builds we still export console_sem
+65-24
kernel/printk/nbcon.c
···214214215215/**216216 * nbcon_context_try_acquire_direct - Try to acquire directly217217- * @ctxt: The context of the caller218218- * @cur: The current console state217217+ * @ctxt: The context of the caller218218+ * @cur: The current console state219219+ * @is_reacquire: This acquire is a reacquire219220 *220221 * Acquire the console when it is released. Also acquire the console when221222 * the current owner has a lower priority and the console is in a safe state.···226225 *227226 * Errors:228227 *229229- * -EPERM: A panic is in progress and this is not the panic CPU.230230- * Or the current owner or waiter has the same or higher231231- * priority. No acquire method can be successful in232232- * this case.228228+ * -EPERM: A panic is in progress and this is neither the panic229229+ * CPU nor is this a reacquire. Or the current owner or230230+ * waiter has the same or higher priority. No acquire231231+ * method can be successful in these cases.233232 *234233 * -EBUSY: The current owner has a lower priority but the console235234 * in an unsafe state. The caller should try using236235 * the handover acquire method.237236 */238237static int nbcon_context_try_acquire_direct(struct nbcon_context *ctxt,239239- struct nbcon_state *cur)238238+ struct nbcon_state *cur, bool is_reacquire)240239{241240 unsigned int cpu = smp_processor_id();242241 struct console *con = ctxt->console;···244243245244 do {246245 /*247247- * Panic does not imply that the console is owned. However, it248248- * is critical that non-panic CPUs during panic are unable to249249- * acquire ownership in order to satisfy the assumptions of250250- * nbcon_waiter_matches(). In particular, the assumption that251251- * lower priorities are ignored during panic.246246+ * Panic does not imply that the console is owned. However,247247+ * since all non-panic CPUs are stopped during panic(), it248248+ * is safer to have them avoid gaining console ownership.249249+ *250250+ * If this acquire is a reacquire (and an unsafe takeover251251+ * has not previously occurred) then it is allowed to attempt252252+ * a direct acquire in panic. This gives console drivers an253253+ * opportunity to perform any necessary cleanup if they were254254+ * interrupted by the panic CPU while printing.252255 */253253- if (other_cpu_in_panic())256256+ if (other_cpu_in_panic() &&257257+ (!is_reacquire || cur->unsafe_takeover)) {254258 return -EPERM;259259+ }255260256261 if (ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio)257262 return -EPERM;···308301 * Event #1 implies this context is EMERGENCY.309302 * Event #2 implies the new context is PANIC.310303 * Event #3 occurs when panic() has flushed the console.311311- * Events #4 and #5 are not possible due to the other_cpu_in_panic()312312- * check in nbcon_context_try_acquire_direct().304304+ * Event #4 occurs when a non-panic CPU reacquires.305305+ * Event #5 is not possible due to the other_cpu_in_panic() check306306+ * in nbcon_context_try_acquire_handover().313307 */314308315309 return (cur->req_prio == expected_prio);···439431 WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio);440432 WARN_ON_ONCE(!cur->unsafe);441433434434+ /*435435+ * Panic does not imply that the console is owned. However, it436436+ * is critical that non-panic CPUs during panic are unable to437437+ * wait for a handover in order to satisfy the assumptions of438438+ * nbcon_waiter_matches(). In particular, the assumption that439439+ * lower priorities are ignored during panic.440440+ */441441+ if (other_cpu_in_panic())442442+ return -EPERM;443443+442444 /* Handover is not possible on the same CPU. */443445 if (cur->cpu == cpu)444446 return -EBUSY;···576558577559/**578560 * nbcon_context_try_acquire - Try to acquire nbcon console579579- * @ctxt: The context of the caller561561+ * @ctxt: The context of the caller562562+ * @is_reacquire: This acquire is a reacquire580563 *581564 * Context: Under @ctxt->con->device_lock() or local_irq_save().582565 * Return: True if the console was acquired. False otherwise.···587568 * in an unsafe state. Otherwise, on success the caller may assume588569 * the console is not in an unsafe state.589570 */590590-static bool nbcon_context_try_acquire(struct nbcon_context *ctxt)571571+static bool nbcon_context_try_acquire(struct nbcon_context *ctxt, bool is_reacquire)591572{592573 unsigned int cpu = smp_processor_id();593574 struct console *con = ctxt->console;···596577597578 nbcon_state_read(con, &cur);598579try_again:599599- err = nbcon_context_try_acquire_direct(ctxt, &cur);580580+ err = nbcon_context_try_acquire_direct(ctxt, &cur, is_reacquire);600581 if (err != -EBUSY)601582 goto out;602583···932913{933914 struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);934915935935- while (!nbcon_context_try_acquire(ctxt))916916+ while (!nbcon_context_try_acquire(ctxt, true))936917 cpu_relax();937918938919 nbcon_write_context_set_buf(wctxt, NULL, 0);···11201101 cant_migrate();11211102 }1122110311231123- if (!nbcon_context_try_acquire(ctxt))11041104+ if (!nbcon_context_try_acquire(ctxt, false))11241105 goto out;1125110611261107 /*···15051486 ctxt->prio = nbcon_get_default_prio();15061487 ctxt->allow_unsafe_takeover = allow_unsafe_takeover;1507148815081508- if (!nbcon_context_try_acquire(ctxt))14891489+ if (!nbcon_context_try_acquire(ctxt, false))15091490 return -EPERM;1510149115111492 while (nbcon_seq_read(con) < stop_seq) {···16901671{16911672 struct nbcon_state state = { };1692167316741674+ /* Synchronize the kthread start. */16751675+ lockdep_assert_console_list_lock_held();16761676+16931677 /* The write_thread() callback is mandatory. */16941678 if (WARN_ON(!con->write_thread))16951679 return false;···17231701 return false;17241702 }1725170317261726- if (printk_kthreads_running) {17041704+ if (printk_kthreads_ready && !have_boot_console) {17271705 if (!nbcon_kthread_create(con)) {17281706 kfree(con->pbufs);17291707 con->pbufs = NULL;17301708 return false;17311709 }17101710+17111711+ /* Might be the first kthread. */17121712+ printk_kthreads_running = true;17321713 }17331714 }17341715···17411716/**17421717 * nbcon_free - Free and cleanup the nbcon console specific data17431718 * @con: Console to free/cleanup nbcon data17191719+ *17201720+ * Important: @have_nbcon_console must be updated before calling17211721+ * this function. In particular, it can be set only when there17221722+ * is still another nbcon console registered.17441723 */17451724void nbcon_free(struct console *con)17461725{17471726 struct nbcon_state state = { };1748172717491749- if (printk_kthreads_running)17281728+ /* Synchronize the kthread stop. */17291729+ lockdep_assert_console_list_lock_held();17301730+17311731+ if (printk_kthreads_running) {17501732 nbcon_kthread_stop(con);17331733+17341734+ /* Might be the last nbcon console.17351735+ *17361736+ * Do not rely on printk_kthreads_check_locked(). It is not17371737+ * called in some code paths, see nbcon_free() callers.17381738+ */17391739+ if (!have_nbcon_console)17401740+ printk_kthreads_running = false;17411741+ }1751174217521743 nbcon_state_set(con, &state);17531744···18031762 ctxt->console = con;18041763 ctxt->prio = NBCON_PRIO_NORMAL;1805176418061806- if (!nbcon_context_try_acquire(ctxt))17651765+ if (!nbcon_context_try_acquire(ctxt, false))18071766 return false;1808176718091768 if (!nbcon_context_enter_unsafe(ctxt))
+11-9
kernel/printk/printk.c
···35743574static int unregister_console_locked(struct console *console);3575357535763576/* True when system boot is far enough to create printer threads. */35773577-static bool printk_kthreads_ready __ro_after_init;35773577+bool printk_kthreads_ready __ro_after_init;3578357835793579static struct task_struct *printk_legacy_kthread;35803580···37133713 if (!printk_kthreads_ready)37143714 return;3715371537163716+ /* Start or stop the legacy kthread when needed. */37163717 if (have_legacy_console || have_boot_console) {37173718 if (!printk_legacy_kthread &&37183719 force_legacy_kthread() &&···42054204 */42064205 synchronize_srcu(&console_srcu);4207420642084208- if (console->flags & CON_NBCON)42094209- nbcon_free(console);42104210-42114211- console_sysfs_notify();42124212-42134213- if (console->exit)42144214- res = console->exit(console);42154215-42164207 /*42174208 * With this console gone, the global flags tracking registered42184209 * console types may have changed. Update them.···42244231 have_legacy_console = found_legacy_con;42254232 if (!found_nbcon_con)42264233 have_nbcon_console = found_nbcon_con;42344234+42354235+ /* @have_nbcon_console must be updated before calling nbcon_free(). */42364236+ if (console->flags & CON_NBCON)42374237+ nbcon_free(console);42384238+42394239+ console_sysfs_notify();42404240+42414241+ if (console->exit)42424242+ res = console->exit(console);4227424342284244 /* Changed console list, may require printer threads to start/stop. */42294245 printk_kthreads_check_locked();
+54-15
kernel/relay.c
···118118 return NULL;119119120120 for (i = 0; i < n_pages; i++) {121121- buf->page_array[i] = alloc_page(GFP_KERNEL);121121+ buf->page_array[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);122122 if (unlikely(!buf->page_array[i]))123123 goto depopulate;124124 set_page_private(buf->page_array[i], (unsigned long)buf);···127127 if (!mem)128128 goto depopulate;129129130130- memset(mem, 0, *size);131130 buf->page_count = n_pages;132131 return mem;133132···249250 */250251251252static int relay_subbuf_start(struct rchan_buf *buf, void *subbuf,252252- void *prev_subbuf, size_t prev_padding)253253+ void *prev_subbuf)253254{255255+ int full = relay_buf_full(buf);256256+257257+ if (full)258258+ buf->stats.full_count++;259259+254260 if (!buf->chan->cb->subbuf_start)255255- return !relay_buf_full(buf);261261+ return !full;256262257263 return buf->chan->cb->subbuf_start(buf, subbuf,258258- prev_subbuf, prev_padding);264264+ prev_subbuf);259265}260266261267/**···302298 buf->finalized = 0;303299 buf->data = buf->start;304300 buf->offset = 0;301301+ buf->stats.full_count = 0;302302+ buf->stats.big_count = 0;305303306304 for (i = 0; i < buf->chan->n_subbufs; i++)307305 buf->padding[i] = 0;308306309309- relay_subbuf_start(buf, buf->data, NULL, 0);307307+ relay_subbuf_start(buf, buf->data, NULL);310308}311309312310/**···561555 goto toobig;562556563557 if (buf->offset != buf->chan->subbuf_size + 1) {564564- buf->prev_padding = buf->chan->subbuf_size - buf->offset;558558+ size_t prev_padding;559559+560560+ prev_padding = buf->chan->subbuf_size - buf->offset;565561 old_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;566566- buf->padding[old_subbuf] = buf->prev_padding;562562+ buf->padding[old_subbuf] = prev_padding;567563 buf->subbufs_produced++;568564 if (buf->dentry)569565 d_inode(buf->dentry)->i_size +=···590582 new_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;591583 new = buf->start + new_subbuf * buf->chan->subbuf_size;592584 buf->offset = 0;593593- if (!relay_subbuf_start(buf, new, old, buf->prev_padding)) {585585+ if (!relay_subbuf_start(buf, new, old)) {594586 buf->offset = buf->chan->subbuf_size + 1;595587 return 0;596588 }···603595 return length;604596605597toobig:606606- buf->chan->last_toobig = length;598598+ buf->stats.big_count++;607599 return 0;608600}609601EXPORT_SYMBOL_GPL(relay_switch_subbuf);···663655 if ((buf = *per_cpu_ptr(chan->buf, i)))664656 relay_close_buf(buf);665657666666- if (chan->last_toobig)667667- printk(KERN_WARNING "relay: one or more items not logged "668668- "[item size (%zd) > sub-buffer size (%zd)]\n",669669- chan->last_toobig, chan->subbuf_size);670670-671658 list_del(&chan->list);672659 kref_put(&chan->kref, relay_destroy_channel);673660 mutex_unlock(&relay_channels_mutex);···695692 mutex_unlock(&relay_channels_mutex);696693}697694EXPORT_SYMBOL_GPL(relay_flush);695695+696696+/**697697+ * relay_stats - get channel buffer statistics698698+ * @chan: the channel699699+ * @flags: select particular information to get700700+ *701701+ * Returns the count of certain field that caller specifies.702702+ */703703+size_t relay_stats(struct rchan *chan, int flags)704704+{705705+ unsigned int i, count = 0;706706+ struct rchan_buf *rbuf;707707+708708+ if (!chan || flags > RELAY_STATS_LAST)709709+ return 0;710710+711711+ if (chan->is_global) {712712+ rbuf = *per_cpu_ptr(chan->buf, 0);713713+ if (flags & RELAY_STATS_BUF_FULL)714714+ count = rbuf->stats.full_count;715715+ else if (flags & RELAY_STATS_WRT_BIG)716716+ count = rbuf->stats.big_count;717717+ } else {718718+ for_each_online_cpu(i) {719719+ rbuf = *per_cpu_ptr(chan->buf, i);720720+ if (rbuf) {721721+ if (flags & RELAY_STATS_BUF_FULL)722722+ count += rbuf->stats.full_count;723723+ else if (flags & RELAY_STATS_WRT_BIG)724724+ count += rbuf->stats.big_count;725725+ }726726+ }727727+ }728728+729729+ return count;730730+}698731699732/**700733 * relay_file_open - open file op for relay files
···432432{433433 struct trace_export *export;434434435435- preempt_disable_notrace();435435+ guard(preempt_notrace)();436436437437 export = rcu_dereference_raw_check(ftrace_exports_list);438438 while (export) {439439 trace_process_export(export, event, flag);440440 export = rcu_dereference_raw_check(export->next);441441 }442442-443443- preempt_enable_notrace();444442}445443446444static inline void···495497 if (WARN_ON_ONCE(!export->write))496498 return -1;497499498498- mutex_lock(&ftrace_export_lock);500500+ guard(mutex)(&ftrace_export_lock);499501500502 add_ftrace_export(&ftrace_exports_list, export);501501-502502- mutex_unlock(&ftrace_export_lock);503503504504 return 0;505505}···505509506510int unregister_ftrace_export(struct trace_export *export)507511{508508- int ret;509509-510510- mutex_lock(&ftrace_export_lock);511511-512512- ret = rm_ftrace_export(&ftrace_exports_list, export);513513-514514- mutex_unlock(&ftrace_export_lock);515515-516516- return ret;512512+ guard(mutex)(&ftrace_export_lock);513513+ return rm_ftrace_export(&ftrace_exports_list, export);517514}518515EXPORT_SYMBOL_GPL(unregister_ftrace_export);519516···629640 if (!this_tr)630641 return;631642632632- mutex_lock(&trace_types_lock);643643+ guard(mutex)(&trace_types_lock);633644 __trace_array_put(this_tr);634634- mutex_unlock(&trace_types_lock);635645}636646EXPORT_SYMBOL_GPL(trace_array_put);637647···1148116011491161 trace_ctx = tracing_gen_ctx();11501162 buffer = tr->array_buffer.buffer;11511151- ring_buffer_nest_start(buffer);11631163+ guard(ring_buffer_nest)(buffer);11521164 event = __trace_buffer_lock_reserve(buffer, TRACE_PRINT, alloc,11531165 trace_ctx);11541154- if (!event) {11551155- size = 0;11561156- goto out;11571157- }11661166+ if (!event)11671167+ return 0;1158116811591169 entry = ring_buffer_event_data(event);11601170 entry->ip = ip;···1168118211691183 __buffer_unlock_commit(buffer, event);11701184 ftrace_trace_stack(tr, buffer, trace_ctx, 4, NULL);11711171- out:11721172- ring_buffer_nest_end(buffer);11731185 return size;11741186}11751187EXPORT_SYMBOL_GPL(__trace_array_puts);···11971213 struct bputs_entry *entry;11981214 unsigned int trace_ctx;11991215 int size = sizeof(struct bputs_entry);12001200- int ret = 0;1201121612021217 if (!printk_binsafe(tr))12031218 return __trace_puts(ip, str, strlen(str));···12101227 trace_ctx = tracing_gen_ctx();12111228 buffer = tr->array_buffer.buffer;1212122912131213- ring_buffer_nest_start(buffer);12301230+ guard(ring_buffer_nest)(buffer);12141231 event = __trace_buffer_lock_reserve(buffer, TRACE_BPUTS, size,12151232 trace_ctx);12161233 if (!event)12171217- goto out;12341234+ return 0;1218123512191236 entry = ring_buffer_event_data(event);12201237 entry->ip = ip;···12231240 __buffer_unlock_commit(buffer, event);12241241 ftrace_trace_stack(tr, buffer, trace_ctx, 4, NULL);1225124212261226- ret = 1;12271227- out:12281228- ring_buffer_nest_end(buffer);12291229- return ret;12431243+ return 1;12301244}12311245EXPORT_SYMBOL_GPL(__trace_bputs);12321246···1412143214131433int tracing_arm_snapshot(struct trace_array *tr)14141434{14151415- int ret;14161416-14171417- mutex_lock(&trace_types_lock);14181418- ret = tracing_arm_snapshot_locked(tr);14191419- mutex_unlock(&trace_types_lock);14201420-14211421- return ret;14351435+ guard(mutex)(&trace_types_lock);14361436+ return tracing_arm_snapshot_locked(tr);14221437}1423143814241439void tracing_disarm_snapshot(struct trace_array *tr)···1816184118171842 ret = get_user(ch, ubuf++);18181843 if (ret)18191819- goto out;18441844+ return ret;1820184518211846 read++;18221847 cnt--;···18301855 while (cnt && isspace(ch)) {18311856 ret = get_user(ch, ubuf++);18321857 if (ret)18331833- goto out;18581858+ return ret;18341859 read++;18351860 cnt--;18361861 }···18401865 /* only spaces were written */18411866 if (isspace(ch) || !ch) {18421867 *ppos += read;18431843- ret = read;18441844- goto out;18681868+ return read;18451869 }18461870 }18471871···18481874 while (cnt && !isspace(ch) && ch) {18491875 if (parser->idx < parser->size - 1)18501876 parser->buffer[parser->idx++] = ch;18511851- else {18521852- ret = -EINVAL;18531853- goto out;18541854- }18771877+ else18781878+ return -EINVAL;18791879+18551880 ret = get_user(ch, ubuf++);18561881 if (ret)18571857- goto out;18821882+ return ret;18581883 read++;18591884 cnt--;18601885 }···18681895 /* Make sure the parsed string always terminates with '\0'. */18691896 parser->buffer[parser->idx] = 0;18701897 } else {18711871- ret = -EINVAL;18721872- goto out;18981898+ return -EINVAL;18731899 }1874190018751901 *ppos += read;18761876- ret = read;18771877-18781878-out:18791879- return ret;19021902+ return read;18801903}1881190418821905/* TODO add a seq_buf_to_buffer() */···23742405 mutex_unlock(&trace_types_lock);2375240623762407 if (ret || !default_bootup_tracer)23772377- goto out_unlock;24082408+ return ret;2378240923792410 if (strncmp(default_bootup_tracer, type->name, MAX_TRACER_SIZE))23802380- goto out_unlock;24112411+ return 0;2381241223822413 printk(KERN_INFO "Starting tracer '%s'\n", type->name);23832414 /* Do we want this tracer to start on bootup? */···23892420 /* disable other selftests, since this will break it. */23902421 disable_tracing_selftest("running a tracer");2391242223922392- out_unlock:23932393- return ret;24232423+ return 0;23942424}2395242523962426static void tracing_reset_cpu(struct array_buffer *buf, int cpu)···2466249824672499void tracing_reset_all_online_cpus(void)24682500{24692469- mutex_lock(&trace_types_lock);25012501+ guard(mutex)(&trace_types_lock);24702502 tracing_reset_all_online_cpus_unlocked();24712471- mutex_unlock(&trace_types_lock);24722503}2473250424742505int is_tracing_stopped(void)···24782511static void tracing_start_tr(struct trace_array *tr)24792512{24802513 struct trace_buffer *buffer;24812481- unsigned long flags;2482251424832515 if (tracing_disabled)24842516 return;2485251724862486- raw_spin_lock_irqsave(&tr->start_lock, flags);25182518+ guard(raw_spinlock_irqsave)(&tr->start_lock);24872519 if (--tr->stop_count) {24882520 if (WARN_ON_ONCE(tr->stop_count < 0)) {24892521 /* Someone screwed up their debugging */24902522 tr->stop_count = 0;24912523 }24922492- goto out;25242524+ return;24932525 }2494252624952527 /* Prevent the buffers from switching */···25052539#endif2506254025072541 arch_spin_unlock(&tr->max_lock);25082508-25092509- out:25102510- raw_spin_unlock_irqrestore(&tr->start_lock, flags);25112542}2512254325132544/**···25222559static void tracing_stop_tr(struct trace_array *tr)25232560{25242561 struct trace_buffer *buffer;25252525- unsigned long flags;2526256225272527- raw_spin_lock_irqsave(&tr->start_lock, flags);25632563+ guard(raw_spinlock_irqsave)(&tr->start_lock);25282564 if (tr->stop_count++)25292529- goto out;25652565+ return;2530256625312567 /* Prevent the buffers from switching */25322568 arch_spin_lock(&tr->max_lock);···25412579#endif2542258025432581 arch_spin_unlock(&tr->max_lock);25442544-25452545- out:25462546- raw_spin_unlock_irqrestore(&tr->start_lock, flags);25472582}2548258325492584/**···2653269426542695 per_cpu(trace_buffered_event, cpu) = event;2655269626562656- preempt_disable();26572657- if (cpu == smp_processor_id() &&26582658- __this_cpu_read(trace_buffered_event) !=26592659- per_cpu(trace_buffered_event, cpu))26602660- WARN_ON_ONCE(1);26612661- preempt_enable();26972697+ scoped_guard(preempt,) {26982698+ if (cpu == smp_processor_id() &&26992699+ __this_cpu_read(trace_buffered_event) !=27002700+ per_cpu(trace_buffered_event, cpu))27012701+ WARN_ON_ONCE(1);27022702+ }26622703 }26632704}26642705···30033044 skip++;30043045#endif3005304630063006- preempt_disable_notrace();30473047+ guard(preempt_notrace)();3007304830083049 stackidx = __this_cpu_inc_return(ftrace_stack_reserve) - 1;30093050···30613102 /* Again, don't let gcc optimize things here */30623103 barrier();30633104 __this_cpu_dec(ftrace_stack_reserve);30643064- preempt_enable_notrace();30653065-30663105}3067310630683107static inline void ftrace_trace_stack(struct trace_array *tr,···31433186 * prevent recursion, since the user stack tracing may31443187 * trigger other kernel events.31453188 */31463146- preempt_disable();31893189+ guard(preempt)();31473190 if (__this_cpu_read(user_stack_count))31483148- goto out;31913191+ return;3149319231503193 __this_cpu_inc(user_stack_count);31513194···3163320631643207 out_drop_count:31653208 __this_cpu_dec(user_stack_count);31663166- out:31673167- preempt_enable();31683209}31693210#else /* CONFIG_USER_STACKTRACE_SUPPORT */31703211static void ftrace_trace_userstack(struct trace_array *tr,···33443389 pause_graph_tracing();3345339033463391 trace_ctx = tracing_gen_ctx();33473347- preempt_disable_notrace();33923392+ guard(preempt_notrace)();3348339333493394 tbuffer = get_trace_buf();33503395 if (!tbuffer) {···3359340433603405 size = sizeof(*entry) + sizeof(u32) * len;33613406 buffer = tr->array_buffer.buffer;33623362- ring_buffer_nest_start(buffer);33633363- event = __trace_buffer_lock_reserve(buffer, TRACE_BPRINT, size,33643364- trace_ctx);33653365- if (!event)33663366- goto out;33673367- entry = ring_buffer_event_data(event);33683368- entry->ip = ip;33693369- entry->fmt = fmt;34073407+ scoped_guard(ring_buffer_nest, buffer) {34083408+ event = __trace_buffer_lock_reserve(buffer, TRACE_BPRINT, size,34093409+ trace_ctx);34103410+ if (!event)34113411+ goto out_put;34123412+ entry = ring_buffer_event_data(event);34133413+ entry->ip = ip;34143414+ entry->fmt = fmt;3370341533713371- memcpy(entry->buf, tbuffer, sizeof(u32) * len);33723372- __buffer_unlock_commit(buffer, event);33733373- ftrace_trace_stack(tr, buffer, trace_ctx, 6, NULL);33743374-33753375-out:33763376- ring_buffer_nest_end(buffer);34163416+ memcpy(entry->buf, tbuffer, sizeof(u32) * len);34173417+ __buffer_unlock_commit(buffer, event);34183418+ ftrace_trace_stack(tr, buffer, trace_ctx, 6, NULL);34193419+ }33773420out_put:33783421 put_trace_buf();3379342233803423out_nobuffer:33813381- preempt_enable_notrace();33823424 unpause_graph_tracing();3383342533843426 return len;···33993447 pause_graph_tracing();3400344834013449 trace_ctx = tracing_gen_ctx();34023402- preempt_disable_notrace();34503450+ guard(preempt_notrace)();340334513404345234053453 tbuffer = get_trace_buf();···34113459 len = vscnprintf(tbuffer, TRACE_BUF_SIZE, fmt, args);3412346034133461 size = sizeof(*entry) + len + 1;34143414- ring_buffer_nest_start(buffer);34153415- event = __trace_buffer_lock_reserve(buffer, TRACE_PRINT, size,34163416- trace_ctx);34173417- if (!event)34183418- goto out;34193419- entry = ring_buffer_event_data(event);34203420- entry->ip = ip;34623462+ scoped_guard(ring_buffer_nest, buffer) {34633463+ event = __trace_buffer_lock_reserve(buffer, TRACE_PRINT, size,34643464+ trace_ctx);34653465+ if (!event)34663466+ goto out;34673467+ entry = ring_buffer_event_data(event);34683468+ entry->ip = ip;3421346934223422- memcpy(&entry->buf, tbuffer, len + 1);34233423- __buffer_unlock_commit(buffer, event);34243424- ftrace_trace_stack(printk_trace, buffer, trace_ctx, 6, NULL);34253425-34703470+ memcpy(&entry->buf, tbuffer, len + 1);34713471+ __buffer_unlock_commit(buffer, event);34723472+ ftrace_trace_stack(printk_trace, buffer, trace_ctx, 6, NULL);34733473+ }34263474out:34273427- ring_buffer_nest_end(buffer);34283475 put_trace_buf();3429347634303477out_nobuffer:34313431- preempt_enable_notrace();34323478 unpause_graph_tracing();3433347934343480 return len;···47504800 if (ret)47514801 return ret;4752480247534753- mutex_lock(&event_mutex);48034803+ guard(mutex)(&event_mutex);4754480447554805 /* Fail if the file is marked for removal */47564806 if (file->flags & EVENT_FILE_FL_FREED) {47574807 trace_array_put(file->tr);47584758- ret = -ENODEV;48084808+ return -ENODEV;47594809 } else {47604810 event_file_get(file);47614811 }47624762-47634763- mutex_unlock(&event_mutex);47644764- if (ret)47654765- return ret;4766481247674813 filp->private_data = inode->i_private;47684814···50365090 size_t count, loff_t *ppos)50375091{50385092 struct trace_array *tr = file_inode(filp)->i_private;50395039- char *mask_str;50935093+ char *mask_str __free(kfree) = NULL;50405094 int len;5041509550425096 len = snprintf(NULL, 0, "%*pb\n",···5047510150485102 len = snprintf(mask_str, len, "%*pb\n",50495103 cpumask_pr_args(tr->tracing_cpumask));50505050- if (len >= count) {50515051- count = -EINVAL;50525052- goto out_err;50535053- }50545054- count = simple_read_from_buffer(ubuf, count, ppos, mask_str, len);51045104+ if (len >= count)51055105+ return -EINVAL;5055510650565056-out_err:50575057- kfree(mask_str);50585058-50595059- return count;51075107+ return simple_read_from_buffer(ubuf, count, ppos, mask_str, len);50605108}5061510950625110int tracing_set_cpumask(struct trace_array *tr,···58975957 char buf[MAX_TRACER_SIZE+2];58985958 int r;5899595959005900- mutex_lock(&trace_types_lock);59015901- r = sprintf(buf, "%s\n", tr->current_trace->name);59025902- mutex_unlock(&trace_types_lock);59605960+ scoped_guard(mutex, &trace_types_lock) {59615961+ r = sprintf(buf, "%s\n", tr->current_trace->name);59625962+ }5903596359045964 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);59055965}···62016261{62026262 int ret = 0;6203626362046204- mutex_lock(&trace_types_lock);62646264+ guard(mutex)(&trace_types_lock);6205626562066266 update_last_data(tr);6207626762086268 if (!tr->ring_buffer_expanded)62096269 ret = __tracing_resize_ring_buffer(tr, trace_buf_size,62106270 RING_BUFFER_ALL_CPUS);62116211- mutex_unlock(&trace_types_lock);62126212-62136271 return ret;62146272}62156273···65046566 if (ret)65056567 return ret;6506656865076507- mutex_lock(&trace_types_lock);65696569+ guard(mutex)(&trace_types_lock);65086570 cpu = tracing_get_cpu(inode);65096571 ret = open_pipe_on_cpu(tr, cpu);65106572 if (ret)···6548661065496611 tr->trace_ref++;6550661265516551- mutex_unlock(&trace_types_lock);65526613 return ret;6553661465546615fail:···65566619 close_pipe_on_cpu(tr, cpu);65576620fail_pipe_on_cpu:65586621 __trace_array_put(tr);65596559- mutex_unlock(&trace_types_lock);65606622 return ret;65616623}65626624···65646628 struct trace_iterator *iter = file->private_data;65656629 struct trace_array *tr = inode->i_private;6566663065676567- mutex_lock(&trace_types_lock);66316631+ scoped_guard(mutex, &trace_types_lock) {66326632+ tr->trace_ref--;6568663365696569- tr->trace_ref--;65706570-65716571- if (iter->trace->pipe_close)65726572- iter->trace->pipe_close(iter);65736573- close_pipe_on_cpu(tr, iter->cpu_file);65746574- mutex_unlock(&trace_types_lock);66346634+ if (iter->trace->pipe_close)66356635+ iter->trace->pipe_close(iter);66366636+ close_pipe_on_cpu(tr, iter->cpu_file);66376637+ }6575663865766639 free_trace_iter_content(iter);65776640 kfree(iter);···73737438 if (i == ARRAY_SIZE(trace_clocks))73747439 return -EINVAL;7375744073767376- mutex_lock(&trace_types_lock);74417441+ guard(mutex)(&trace_types_lock);7377744273787443 tr->clock_id = i;73797444···7396746173977462 tscratch->clock_id = i;73987463 }73997399-74007400- mutex_unlock(&trace_types_lock);7401746474027465 return 0;74037466}···74487515{74497516 struct trace_array *tr = m->private;7450751774517451- mutex_lock(&trace_types_lock);75187518+ guard(mutex)(&trace_types_lock);7452751974537520 if (ring_buffer_time_stamp_abs(tr->array_buffer.buffer))74547521 seq_puts(m, "delta [absolute]\n");74557522 else74567523 seq_puts(m, "[delta] absolute\n");74577457-74587458- mutex_unlock(&trace_types_lock);7459752474607525 return 0;74617526}···80428111{80438112 struct tracing_log_err *err, *next;8044811380458045- mutex_lock(&tracing_err_log_lock);81148114+ guard(mutex)(&tracing_err_log_lock);81158115+80468116 list_for_each_entry_safe(err, next, &tr->err_log, list) {80478117 list_del(&err->list);80488118 free_tracing_log_err(err);80498119 }8050812080518121 tr->n_err_log_entries = 0;80528052- mutex_unlock(&tracing_err_log_lock);80538122}8054812380558124static void *tracing_err_log_seq_start(struct seq_file *m, loff_t *pos)···83208389 struct ftrace_buffer_info *info = file->private_data;83218390 struct trace_iterator *iter = &info->iter;8322839183238323- mutex_lock(&trace_types_lock);83928392+ guard(mutex)(&trace_types_lock);8324839383258394 iter->tr->trace_ref--;83268395···83308399 ring_buffer_free_read_page(iter->array_buffer->buffer,83318400 info->spare_cpu, info->spare);83328401 kvfree(info);83338333-83348334- mutex_unlock(&trace_types_lock);8335840283368403 return 0;83378404}···85388609 * An ioctl call with cmd 0 to the ring buffer file will wake up all85398610 * waiters85408611 */85418541- mutex_lock(&trace_types_lock);86128612+ guard(mutex)(&trace_types_lock);8542861385438614 /* Make sure the waiters see the new wait_index */85448615 (void)atomic_fetch_inc_release(&iter->wait_index);8545861685468617 ring_buffer_wake_waiters(iter->array_buffer->buffer, iter->cpu_file);8547861885488548- mutex_unlock(&trace_types_lock);85498619 return 0;85508620}85518621···88858957 out_reg:88868958 ret = tracing_arm_snapshot(tr);88878959 if (ret < 0)88888888- goto out;89608960+ return ret;8889896188908962 ret = register_ftrace_function_probe(glob, tr, ops, count);88918963 if (ret < 0)88928964 tracing_disarm_snapshot(tr);88938893- out:89658965+88948966 return ret < 0 ? ret : 0;88958967}88968968···90349106 return -EINVAL;9035910790369108 if (!!(topt->flags->val & topt->opt->bit) != val) {90379037- mutex_lock(&trace_types_lock);91099109+ guard(mutex)(&trace_types_lock);90389110 ret = __set_tracer_option(topt->tr, topt->flags,90399111 topt->opt, !val);90409040- mutex_unlock(&trace_types_lock);90419112 if (ret)90429113 return ret;90439114 }···93459418 return ret;9346941993479420 if (buffer) {93489348- mutex_lock(&trace_types_lock);94219421+ guard(mutex)(&trace_types_lock);93499422 if (!!val == tracer_tracing_is_on(tr)) {93509423 val = 0; /* do nothing */93519424 } else if (val) {···93599432 /* Wake up any waiters */93609433 ring_buffer_wake_waiters(buffer, RING_BUFFER_ALL_CPUS);93619434 }93629362- mutex_unlock(&trace_types_lock);93639435 }9364943693659437 (*ppos)++;···9742981697439817static void update_tracer_options(struct trace_array *tr)97449818{97459745- mutex_lock(&trace_types_lock);98199819+ guard(mutex)(&trace_types_lock);97469820 tracer_options_updated = true;97479821 __update_tracer_options(tr);97489748- mutex_unlock(&trace_types_lock);97499822}9750982397519824/* Must have trace_types_lock held */···97669841{97679842 struct trace_array *tr;9768984397699769- mutex_lock(&trace_types_lock);98449844+ guard(mutex)(&trace_types_lock);97709845 tr = trace_array_find(instance);97719846 if (tr)97729847 tr->ref++;97739773- mutex_unlock(&trace_types_lock);9774984897759849 return tr;97769850}···1030010376{1030110377 /* All modules have the symbol __this_module */1030210378 static const char this_mod[] = "__this_module";1030310303- char modname[MAX_PARAM_PREFIX_LEN + sizeof(this_mod) + 2];1037910379+ char modname[MODULE_NAME_LEN + sizeof(this_mod) + 2];1030410380 unsigned long val;1030510381 int n;1030610382···1072710803 size_t count, loff_t *ppos,1072810804 int (*createfn)(const char *))1072910805{1073010730- char *kbuf, *buf, *tmp;1080610806+ char *kbuf __free(kfree) = NULL;1080710807+ char *buf, *tmp;1073110808 int ret = 0;1073210809 size_t done = 0;1073310810 size_t size;···1074310818 if (size >= WRITE_BUFSIZE)1074410819 size = WRITE_BUFSIZE - 1;10745108201074610746- if (copy_from_user(kbuf, buffer + done, size)) {1074710747- ret = -EFAULT;1074810748- goto out;1074910749- }1082110821+ if (copy_from_user(kbuf, buffer + done, size))1082210822+ return -EFAULT;1082310823+1075010824 kbuf[size] = '\0';1075110825 buf = kbuf;1075210826 do {···1076110837 /* This can accept WRITE_BUFSIZE - 2 ('\n' + '\0') */1076210838 pr_warn("Line length is too long: Should be less than %d\n",1076310839 WRITE_BUFSIZE - 2);1076410764- ret = -EINVAL;1076510765- goto out;1084010840+ return -EINVAL;1076610841 }1076710842 }1076810843 done += size;···10774108511077510852 ret = createfn(buf);1077610853 if (ret)1077710777- goto out;1085410854+ return ret;1077810855 buf += size;10779108561078010857 } while (done < count);1078110858 }1078210782- ret = done;1078310783-1078410784-out:1078510785- kfree(kbuf);1078610786-1078710787- return ret;1085910859+ return done;1078810860}10789108611079010862#ifdef CONFIG_TRACER_MAX_TRACE···1098211064 BUILD_BUG_ON(TRACE_ITER_LAST_BIT > TRACE_FLAGS_MAX_SIZE);10983110651098411066 if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL))1098510985- goto out;1106711067+ return -ENOMEM;10986110681098711069 if (!alloc_cpumask_var(&global_trace.tracing_cpumask, GFP_KERNEL))1098811070 goto out_free_buffer_mask;···1110011182 free_cpumask_var(global_trace.tracing_cpumask);1110111183out_free_buffer_mask:1110211184 free_cpumask_var(tracing_buffer_mask);1110311103-out:1110411185 return ret;1110511186}1110611187
+2-4
kernel/trace/trace_events_synth.c
···536536 * is being performed within another event.537537 */538538 buffer = trace_file->tr->array_buffer.buffer;539539- ring_buffer_nest_start(buffer);539539+ guard(ring_buffer_nest)(buffer);540540541541 entry = trace_event_buffer_reserve(&fbuffer, trace_file,542542 sizeof(*entry) + fields_size);543543 if (!entry)544544- goto out;544544+ return;545545546546 for (i = 0, n_u64 = 0; i < event->n_fields; i++) {547547 val_idx = var_ref_idx[i];···584584 }585585586586 trace_event_buffer_commit(&fbuffer);587587-out:588588- ring_buffer_nest_end(buffer);589587}590588591589static void free_synth_event_print_fmt(struct trace_event_call *call)
+7-1
kernel/trace/trace_output.c
···701701 struct btf *btf;702702 s32 tid, nr = 0;703703 int a, p, x;704704+ u16 encode;704705705706 trace_seq_printf(s, "(");706707···745744 trace_seq_printf(s, "0x%lx", arg);746745 break;747746 case BTF_KIND_INT:748748- trace_seq_printf(s, "%ld", arg);747747+ encode = btf_int_encoding(t);748748+ /* Print unsigned ints as hex */749749+ if (encode & BTF_INT_SIGNED)750750+ trace_seq_printf(s, "%ld", arg);751751+ else752752+ trace_seq_printf(s, "0x%lx", arg);749753 break;750754 case BTF_KIND_ENUM:751755 trace_seq_printf(s, "%ld", arg);
+7-9
kernel/ucount.c
···199199 }200200}201201202202-static inline bool atomic_long_inc_below(atomic_long_t *v, int u)202202+static inline bool atomic_long_inc_below(atomic_long_t *v, long u)203203{204204- long c, old;205205- c = atomic_long_read(v);206206- for (;;) {204204+ long c = atomic_long_read(v);205205+206206+ do {207207 if (unlikely(c >= u))208208 return false;209209- old = atomic_long_cmpxchg(v, c, c+1);210210- if (likely(old == c))211211- return true;212212- c = old;213213- }209209+ } while (!atomic_long_try_cmpxchg(v, &c, c+1));210210+211211+ return true;214212}215213216214struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid,
+20
lib/Kconfig.debug
···3214321432153215 If unsure, say N.3216321632173217+config TEST_KEXEC_HANDOVER32183218+ bool "Test for Kexec HandOver"32193219+ default n32203220+ depends on KEXEC_HANDOVER32213221+ help32223222+ This option enables test for Kexec HandOver (KHO).32233223+ The test consists of two parts: saving kernel data before kexec and32243224+ restoring the data after kexec and verifying that it was properly32253225+ handed over. This test module creates and saves data on the boot of32263226+ the first kernel and restores and verifies the data on the boot of32273227+ kexec'ed kernel.32283228+32293229+ For detailed documentation about KHO, see Documentation/core-api/kho.32303230+32313231+ To run the test run:32323232+32333233+ tools/testing/selftests/kho/vmtest.sh -h32343234+32353235+ If unsure, say N.32363236+32173237config RATELIMIT_KUNIT_TEST32183238 tristate "KUnit Test for correctness and stress of ratelimit" if !KUNIT_ALL_TESTS32193239 depends on KUNIT
···212212213213#endif214214215215- /* make sure c is not zero, trigger exception otherwise */216216-#pragma GCC diagnostic push217217-#pragma GCC diagnostic ignored "-Wdiv-by-zero"218218- if (unlikely(c == 0))219219- return 1/0;220220-#pragma GCC diagnostic pop215215+ /* make sure c is not zero, trigger runtime exception otherwise */216216+ if (unlikely(c == 0)) {217217+ unsigned long zero = 0;218218+219219+ OPTIMIZER_HIDE_VAR(zero);220220+ return ~0UL/zero;221221+ }221222222223 int shift = __builtin_ctzll(c);223224
+15-12
lib/math/gcd.c
···1111 * has decent hardware division.1212 */13131414+DEFINE_STATIC_KEY_TRUE(efficient_ffs_key);1515+1416#if !defined(CONFIG_CPU_NO_EFFICIENT_FFS)15171618/* If __ffs is available, the even/odd algorithm benchmarks slower. */17191818-/**1919- * gcd - calculate and return the greatest common divisor of 2 unsigned longs2020- * @a: first value2121- * @b: second value2222- */2323-unsigned long gcd(unsigned long a, unsigned long b)2020+static unsigned long binary_gcd(unsigned long a, unsigned long b)2421{2522 unsigned long r = a | b;2626-2727- if (!a || !b)2828- return r;29233024 b >>= __ffs(b);3125 if (b == 1)···3844 }3945}40464141-#else4747+#endif42484349/* If normalization is done by loops, the even/odd algorithm is a win. */5050+5151+/**5252+ * gcd - calculate and return the greatest common divisor of 2 unsigned longs5353+ * @a: first value5454+ * @b: second value5555+ */4456unsigned long gcd(unsigned long a, unsigned long b)4557{4658 unsigned long r = a | b;47594860 if (!a || !b)4961 return r;6262+6363+#if !defined(CONFIG_CPU_NO_EFFICIENT_FFS)6464+ if (static_branch_likely(&efficient_ffs_key))6565+ return binary_gcd(a, b);6666+#endif50675168 /* Isolate lsbit of r */5269 r &= -r;···8479 a >>= 1;8580 }8681}8787-8888-#endif89829083EXPORT_SYMBOL_GPL(gcd);
-3
lib/raid6/algos.c
···1818#else1919#include <linux/module.h>2020#include <linux/gfp.h>2121-/* In .bss so it's zeroed */2222-const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256)));2323-EXPORT_SYMBOL(raid6_empty_zero_page);2421#endif25222623struct raid6_calls raid6_call;
+3-3
lib/raid6/recov.c
···3131 Use the dead data pages as temporary storage for3232 delta p and delta q */3333 dp = (u8 *)ptrs[faila];3434- ptrs[faila] = (void *)raid6_empty_zero_page;3434+ ptrs[faila] = raid6_get_zero_page();3535 ptrs[disks-2] = dp;3636 dq = (u8 *)ptrs[failb];3737- ptrs[failb] = (void *)raid6_empty_zero_page;3737+ ptrs[failb] = raid6_get_zero_page();3838 ptrs[disks-1] = dq;39394040 raid6_call.gen_syndrome(disks, bytes, ptrs);···7272 /* Compute syndrome with zero for the missing data page7373 Use the dead data page as temporary storage for delta q */7474 dq = (u8 *)ptrs[faila];7575- ptrs[faila] = (void *)raid6_empty_zero_page;7575+ ptrs[faila] = raid6_get_zero_page();7676 ptrs[disks-1] = dq;77777878 raid6_call.gen_syndrome(disks, bytes, ptrs);
+3-3
lib/raid6/recov_avx2.c
···2828 Use the dead data pages as temporary storage for2929 delta p and delta q */3030 dp = (u8 *)ptrs[faila];3131- ptrs[faila] = (void *)raid6_empty_zero_page;3131+ ptrs[faila] = raid6_get_zero_page();3232 ptrs[disks-2] = dp;3333 dq = (u8 *)ptrs[failb];3434- ptrs[failb] = (void *)raid6_empty_zero_page;3434+ ptrs[failb] = raid6_get_zero_page();3535 ptrs[disks-1] = dq;36363737 raid6_call.gen_syndrome(disks, bytes, ptrs);···196196 /* Compute syndrome with zero for the missing data page197197 Use the dead data page as temporary storage for delta q */198198 dq = (u8 *)ptrs[faila];199199- ptrs[faila] = (void *)raid6_empty_zero_page;199199+ ptrs[faila] = raid6_get_zero_page();200200 ptrs[disks-1] = dq;201201202202 raid6_call.gen_syndrome(disks, bytes, ptrs);
···4242 * delta p and delta q4343 */4444 dp = (u8 *)ptrs[faila];4545- ptrs[faila] = (void *)raid6_empty_zero_page;4545+ ptrs[faila] = raid6_get_zero_page();4646 ptrs[disks - 2] = dp;4747 dq = (u8 *)ptrs[failb];4848- ptrs[failb] = (void *)raid6_empty_zero_page;4848+ ptrs[failb] = raid6_get_zero_page();4949 ptrs[disks - 1] = dq;50505151 raid6_call.gen_syndrome(disks, bytes, ptrs);···197197 * Use the dead data page as temporary storage for delta q198198 */199199 dq = (u8 *)ptrs[faila];200200- ptrs[faila] = (void *)raid6_empty_zero_page;200200+ ptrs[faila] = raid6_get_zero_page();201201 ptrs[disks - 1] = dq;202202203203 raid6_call.gen_syndrome(disks, bytes, ptrs);···316316 * delta p and delta q317317 */318318 dp = (u8 *)ptrs[faila];319319- ptrs[faila] = (void *)raid6_empty_zero_page;319319+ ptrs[faila] = raid6_get_zero_page();320320 ptrs[disks - 2] = dp;321321 dq = (u8 *)ptrs[failb];322322- ptrs[failb] = (void *)raid6_empty_zero_page;322322+ ptrs[failb] = raid6_get_zero_page();323323 ptrs[disks - 1] = dq;324324325325 raid6_call.gen_syndrome(disks, bytes, ptrs);···436436 * Use the dead data page as temporary storage for delta q437437 */438438 dq = (u8 *)ptrs[faila];439439- ptrs[faila] = (void *)raid6_empty_zero_page;439439+ ptrs[faila] = raid6_get_zero_page();440440 ptrs[disks - 1] = dq;441441442442 raid6_call.gen_syndrome(disks, bytes, ptrs);
+3-3
lib/raid6/recov_neon.c
···3636 * delta p and delta q3737 */3838 dp = (u8 *)ptrs[faila];3939- ptrs[faila] = (void *)raid6_empty_zero_page;3939+ ptrs[faila] = raid6_get_zero_page();4040 ptrs[disks - 2] = dp;4141 dq = (u8 *)ptrs[failb];4242- ptrs[failb] = (void *)raid6_empty_zero_page;4242+ ptrs[failb] = raid6_get_zero_page();4343 ptrs[disks - 1] = dq;44444545 raid6_call.gen_syndrome(disks, bytes, ptrs);···7474 * Use the dead data page as temporary storage for delta q7575 */7676 dq = (u8 *)ptrs[faila];7777- ptrs[faila] = (void *)raid6_empty_zero_page;7777+ ptrs[faila] = raid6_get_zero_page();7878 ptrs[disks - 1] = dq;79798080 raid6_call.gen_syndrome(disks, bytes, ptrs);
+3-3
lib/raid6/recov_rvv.c
···165165 * delta p and delta q166166 */167167 dp = (u8 *)ptrs[faila];168168- ptrs[faila] = (void *)raid6_empty_zero_page;168168+ ptrs[faila] = raid6_get_zero_page();169169 ptrs[disks - 2] = dp;170170 dq = (u8 *)ptrs[failb];171171- ptrs[failb] = (void *)raid6_empty_zero_page;171171+ ptrs[failb] = raid6_get_zero_page();172172 ptrs[disks - 1] = dq;173173174174 raid6_call.gen_syndrome(disks, bytes, ptrs);···203203 * Use the dead data page as temporary storage for delta q204204 */205205 dq = (u8 *)ptrs[faila];206206- ptrs[faila] = (void *)raid6_empty_zero_page;206206+ ptrs[faila] = raid6_get_zero_page();207207 ptrs[disks - 1] = dq;208208209209 raid6_call.gen_syndrome(disks, bytes, ptrs);
+3-3
lib/raid6/recov_s390xc.c
···3434 Use the dead data pages as temporary storage for3535 delta p and delta q */3636 dp = (u8 *)ptrs[faila];3737- ptrs[faila] = (void *)raid6_empty_zero_page;3737+ ptrs[faila] = raid6_get_zero_page();3838 ptrs[disks-2] = dp;3939 dq = (u8 *)ptrs[failb];4040- ptrs[failb] = (void *)raid6_empty_zero_page;4040+ ptrs[failb] = raid6_get_zero_page();4141 ptrs[disks-1] = dq;42424343 raid6_call.gen_syndrome(disks, bytes, ptrs);···8181 /* Compute syndrome with zero for the missing data page8282 Use the dead data page as temporary storage for delta q */8383 dq = (u8 *)ptrs[faila];8484- ptrs[faila] = (void *)raid6_empty_zero_page;8484+ ptrs[faila] = raid6_get_zero_page();8585 ptrs[disks-1] = dq;86868787 raid6_call.gen_syndrome(disks, bytes, ptrs);
+3-3
lib/raid6/recov_ssse3.c
···3030 Use the dead data pages as temporary storage for3131 delta p and delta q */3232 dp = (u8 *)ptrs[faila];3333- ptrs[faila] = (void *)raid6_empty_zero_page;3333+ ptrs[faila] = raid6_get_zero_page();3434 ptrs[disks-2] = dp;3535 dq = (u8 *)ptrs[failb];3636- ptrs[failb] = (void *)raid6_empty_zero_page;3636+ ptrs[failb] = raid6_get_zero_page();3737 ptrs[disks-1] = dq;38383939 raid6_call.gen_syndrome(disks, bytes, ptrs);···203203 /* Compute syndrome with zero for the missing data page204204 Use the dead data page as temporary storage for delta q */205205 dq = (u8 *)ptrs[faila];206206- ptrs[faila] = (void *)raid6_empty_zero_page;206206+ ptrs[faila] = raid6_get_zero_page();207207 ptrs[disks-1] = dq;208208209209 raid6_call.gen_syndrome(disks, bytes, ptrs);
+58-9
lib/stackdepot.c
···3636#include <linux/memblock.h>3737#include <linux/kasan-enabled.h>38383939-#define DEPOT_POOLS_CAP 81924040-/* The pool_index is offset by 1 so the first record does not have a 0 handle. */4141-#define DEPOT_MAX_POOLS \4242- (((1LL << (DEPOT_POOL_INDEX_BITS)) - 1 < DEPOT_POOLS_CAP) ? \4343- (1LL << (DEPOT_POOL_INDEX_BITS)) - 1 : DEPOT_POOLS_CAP)3939+/*4040+ * The pool_index is offset by 1 so the first record does not have a 0 handle.4141+ */4242+static unsigned int stack_max_pools __read_mostly =4343+ MIN((1LL << DEPOT_POOL_INDEX_BITS) - 1, 8192);44444545static bool stack_depot_disabled;4646static bool __stack_depot_early_init_requested __initdata = IS_ENABLED(CONFIG_STACKDEPOT_ALWAYS_INIT);···6262static unsigned int stack_hash_mask;63636464/* Array of memory regions that store stack records. */6565-static void *stack_pools[DEPOT_MAX_POOLS];6565+static void **stack_pools;6666/* Newly allocated pool that is not yet added to stack_pools. */6767static void *new_pool;6868/* Number of pools in stack_pools. */···100100 return kstrtobool(str, &stack_depot_disabled);101101}102102early_param("stack_depot_disable", disable_stack_depot);103103+104104+static int __init parse_max_pools(char *str)105105+{106106+ const long long limit = (1LL << (DEPOT_POOL_INDEX_BITS)) - 1;107107+ unsigned int max_pools;108108+ int rv;109109+110110+ rv = kstrtouint(str, 0, &max_pools);111111+ if (rv)112112+ return rv;113113+114114+ if (max_pools < 1024) {115115+ pr_err("stack_depot_max_pools below 1024, using default of %u\n",116116+ stack_max_pools);117117+ goto out;118118+ }119119+120120+ if (max_pools > limit) {121121+ pr_err("stack_depot_max_pools exceeds %lld, using default of %u\n",122122+ limit, stack_max_pools);123123+ goto out;124124+ }125125+126126+ stack_max_pools = max_pools;127127+out:128128+ return 0;129129+}130130+early_param("stack_depot_max_pools", parse_max_pools);103131104132void __init stack_depot_request_early_init(void)105133{···210182 }211183 init_stack_table(entries);212184185185+ pr_info("allocating space for %u stack pools via memblock\n",186186+ stack_max_pools);187187+ stack_pools =188188+ memblock_alloc(stack_max_pools * sizeof(void *), PAGE_SIZE);189189+ if (!stack_pools) {190190+ pr_err("stack pools allocation failed, disabling\n");191191+ memblock_free(stack_table, entries * sizeof(struct list_head));192192+ stack_depot_disabled = true;193193+ return -ENOMEM;194194+ }195195+213196 return 0;214197}215198···270231 stack_hash_mask = entries - 1;271232 init_stack_table(entries);272233234234+ pr_info("allocating space for %u stack pools via kvcalloc\n",235235+ stack_max_pools);236236+ stack_pools = kvcalloc(stack_max_pools, sizeof(void *), GFP_KERNEL);237237+ if (!stack_pools) {238238+ pr_err("stack pools allocation failed, disabling\n");239239+ kvfree(stack_table);240240+ stack_depot_disabled = true;241241+ ret = -ENOMEM;242242+ }243243+273244out_unlock:274245 mutex_unlock(&stack_depot_init_mutex);275246···294245{295246 lockdep_assert_held(&pool_lock);296247297297- if (unlikely(pools_num >= DEPOT_MAX_POOLS)) {248248+ if (unlikely(pools_num >= stack_max_pools)) {298249 /* Bail out if we reached the pool limit. */299299- WARN_ON_ONCE(pools_num > DEPOT_MAX_POOLS); /* should never happen */250250+ WARN_ON_ONCE(pools_num > stack_max_pools); /* should never happen */300251 WARN_ON_ONCE(!new_pool); /* to avoid unnecessary pre-allocation */301252 WARN_ONCE(1, "Stack depot reached limit capacity");302253 return false;···322273 * NULL; do not reset to NULL if we have reached the maximum number of323274 * pools.324275 */325325- if (pools_num < DEPOT_MAX_POOLS)276276+ if (pools_num < stack_max_pools)326277 WRITE_ONCE(new_pool, NULL);327278 else328279 WRITE_ONCE(new_pool, STACK_DEPOT_POISON);
+122
lib/sys_info.c
···11+// SPDX-License-Identifier: GPL-2.0-only22+#include <linux/sched/debug.h>33+#include <linux/console.h>44+#include <linux/kernel.h>55+#include <linux/ftrace.h>66+#include <linux/sysctl.h>77+#include <linux/nmi.h>88+99+#include <linux/sys_info.h>1010+1111+struct sys_info_name {1212+ unsigned long bit;1313+ const char *name;1414+};1515+1616+/*1717+ * When 'si_names' gets updated, please make sure the 'sys_info_avail'1818+ * below is updated accordingly.1919+ */2020+static const struct sys_info_name si_names[] = {2121+ { SYS_INFO_TASKS, "tasks" },2222+ { SYS_INFO_MEM, "mem" },2323+ { SYS_INFO_TIMERS, "timers" },2424+ { SYS_INFO_LOCKS, "locks" },2525+ { SYS_INFO_FTRACE, "ftrace" },2626+ { SYS_INFO_ALL_CPU_BT, "all_bt" },2727+ { SYS_INFO_BLOCKED_TASKS, "blocked_tasks" },2828+};2929+3030+/* Expecting string like "xxx_sys_info=tasks,mem,timers,locks,ftrace,..." */3131+unsigned long sys_info_parse_param(char *str)3232+{3333+ unsigned long si_bits = 0;3434+ char *s, *name;3535+ int i;3636+3737+ s = str;3838+ while ((name = strsep(&s, ",")) && *name) {3939+ for (i = 0; i < ARRAY_SIZE(si_names); i++) {4040+ if (!strcmp(name, si_names[i].name)) {4141+ si_bits |= si_names[i].bit;4242+ break;4343+ }4444+ }4545+ }4646+4747+ return si_bits;4848+}4949+5050+#ifdef CONFIG_SYSCTL5151+5252+static const char sys_info_avail[] __maybe_unused = "tasks,mem,timers,locks,ftrace,all_bt,blocked_tasks";5353+5454+int sysctl_sys_info_handler(const struct ctl_table *ro_table, int write,5555+ void *buffer, size_t *lenp,5656+ loff_t *ppos)5757+{5858+ char names[sizeof(sys_info_avail) + 1];5959+ struct ctl_table table;6060+ unsigned long *si_bits_global;6161+6262+ si_bits_global = ro_table->data;6363+6464+ if (write) {6565+ unsigned long si_bits;6666+ int ret;6767+6868+ table = *ro_table;6969+ table.data = names;7070+ table.maxlen = sizeof(names);7171+ ret = proc_dostring(&table, write, buffer, lenp, ppos);7272+ if (ret)7373+ return ret;7474+7575+ si_bits = sys_info_parse_param(names);7676+ /* The access to the global value is not synchronized. */7777+ WRITE_ONCE(*si_bits_global, si_bits);7878+ return 0;7979+ } else {8080+ /* for 'read' operation */8181+ char *delim = "";8282+ int i, len = 0;8383+8484+ for (i = 0; i < ARRAY_SIZE(si_names); i++) {8585+ if (*si_bits_global & si_names[i].bit) {8686+ len += scnprintf(names + len, sizeof(names) - len,8787+ "%s%s", delim, si_names[i].name);8888+ delim = ",";8989+ }9090+ }9191+9292+ table = *ro_table;9393+ table.data = names;9494+ table.maxlen = sizeof(names);9595+ return proc_dostring(&table, write, buffer, lenp, ppos);9696+ }9797+}9898+#endif9999+100100+void sys_info(unsigned long si_mask)101101+{102102+ if (si_mask & SYS_INFO_TASKS)103103+ show_state();104104+105105+ if (si_mask & SYS_INFO_MEM)106106+ show_mem();107107+108108+ if (si_mask & SYS_INFO_TIMERS)109109+ sysrq_timer_list_show();110110+111111+ if (si_mask & SYS_INFO_LOCKS)112112+ debug_show_all_locks();113113+114114+ if (si_mask & SYS_INFO_FTRACE)115115+ ftrace_dump(DUMP_ALL);116116+117117+ if (si_mask & SYS_INFO_ALL_CPU_BT)118118+ trigger_all_cpu_backtrace();119119+120120+ if (si_mask & SYS_INFO_BLOCKED_TASKS)121121+ show_state_filter(TASK_UNINTERRUPTIBLE);122122+}
+305
lib/test_kho.c
···11+// SPDX-License-Identifier: GPL-2.0-or-later22+/*33+ * Test module for KHO44+ * Copyright (c) 2025 Microsoft Corporation.55+ *66+ * Authors:77+ * Saurabh Sengar <ssengar@microsoft.com>88+ * Mike Rapoport <rppt@kernel.org>99+ */1010+1111+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt1212+1313+#include <linux/mm.h>1414+#include <linux/gfp.h>1515+#include <linux/slab.h>1616+#include <linux/kexec.h>1717+#include <linux/libfdt.h>1818+#include <linux/module.h>1919+#include <linux/printk.h>2020+#include <linux/vmalloc.h>2121+#include <linux/kexec_handover.h>2222+2323+#include <net/checksum.h>2424+2525+#define KHO_TEST_MAGIC 0x4b484f21 /* KHO! */2626+#define KHO_TEST_FDT "kho_test"2727+#define KHO_TEST_COMPAT "kho-test-v1"2828+2929+static long max_mem = (PAGE_SIZE << MAX_PAGE_ORDER) * 2;3030+module_param(max_mem, long, 0644);3131+3232+struct kho_test_state {3333+ unsigned int nr_folios;3434+ struct folio **folios;3535+ struct folio *fdt;3636+ __wsum csum;3737+};3838+3939+static struct kho_test_state kho_test_state;4040+4141+static int kho_test_notifier(struct notifier_block *self, unsigned long cmd,4242+ void *v)4343+{4444+ struct kho_test_state *state = &kho_test_state;4545+ struct kho_serialization *ser = v;4646+ int err = 0;4747+4848+ switch (cmd) {4949+ case KEXEC_KHO_ABORT:5050+ return NOTIFY_DONE;5151+ case KEXEC_KHO_FINALIZE:5252+ /* Handled below */5353+ break;5454+ default:5555+ return NOTIFY_BAD;5656+ }5757+5858+ err |= kho_preserve_folio(state->fdt);5959+ err |= kho_add_subtree(ser, KHO_TEST_FDT, folio_address(state->fdt));6060+6161+ return err ? NOTIFY_BAD : NOTIFY_DONE;6262+}6363+6464+static struct notifier_block kho_test_nb = {6565+ .notifier_call = kho_test_notifier,6666+};6767+6868+static int kho_test_save_data(struct kho_test_state *state, void *fdt)6969+{7070+ phys_addr_t *folios_info __free(kvfree) = NULL;7171+ int err = 0;7272+7373+ folios_info = kvmalloc_array(state->nr_folios, sizeof(*folios_info),7474+ GFP_KERNEL);7575+ if (!folios_info)7676+ return -ENOMEM;7777+7878+ for (int i = 0; i < state->nr_folios; i++) {7979+ struct folio *folio = state->folios[i];8080+ unsigned int order = folio_order(folio);8181+8282+ folios_info[i] = virt_to_phys(folio_address(folio)) | order;8383+8484+ err = kho_preserve_folio(folio);8585+ if (err)8686+ return err;8787+ }8888+8989+ err |= fdt_begin_node(fdt, "data");9090+ err |= fdt_property(fdt, "nr_folios", &state->nr_folios,9191+ sizeof(state->nr_folios));9292+ err |= fdt_property(fdt, "folios_info", folios_info,9393+ state->nr_folios * sizeof(*folios_info));9494+ err |= fdt_property(fdt, "csum", &state->csum, sizeof(state->csum));9595+ err |= fdt_end_node(fdt);9696+9797+ return err;9898+}9999+100100+static int kho_test_prepare_fdt(struct kho_test_state *state)101101+{102102+ const char compatible[] = KHO_TEST_COMPAT;103103+ unsigned int magic = KHO_TEST_MAGIC;104104+ ssize_t fdt_size;105105+ int err = 0;106106+ void *fdt;107107+108108+ fdt_size = state->nr_folios * sizeof(phys_addr_t) + PAGE_SIZE;109109+ state->fdt = folio_alloc(GFP_KERNEL, get_order(fdt_size));110110+ if (!state->fdt)111111+ return -ENOMEM;112112+113113+ fdt = folio_address(state->fdt);114114+115115+ err |= fdt_create(fdt, fdt_size);116116+ err |= fdt_finish_reservemap(fdt);117117+118118+ err |= fdt_begin_node(fdt, "");119119+ err |= fdt_property(fdt, "compatible", compatible, sizeof(compatible));120120+ err |= fdt_property(fdt, "magic", &magic, sizeof(magic));121121+ err |= kho_test_save_data(state, fdt);122122+ err |= fdt_end_node(fdt);123123+124124+ err |= fdt_finish(fdt);125125+126126+ if (err)127127+ folio_put(state->fdt);128128+129129+ return err;130130+}131131+132132+static int kho_test_generate_data(struct kho_test_state *state)133133+{134134+ size_t alloc_size = 0;135135+ __wsum csum = 0;136136+137137+ while (alloc_size < max_mem) {138138+ int order = get_random_u32() % NR_PAGE_ORDERS;139139+ struct folio *folio;140140+ unsigned int size;141141+ void *addr;142142+143143+ /* cap allocation so that we won't exceed max_mem */144144+ if (alloc_size + (PAGE_SIZE << order) > max_mem) {145145+ order = get_order(max_mem - alloc_size);146146+ if (order)147147+ order--;148148+ }149149+ size = PAGE_SIZE << order;150150+151151+ folio = folio_alloc(GFP_KERNEL | __GFP_NORETRY, order);152152+ if (!folio)153153+ goto err_free_folios;154154+155155+ state->folios[state->nr_folios++] = folio;156156+ addr = folio_address(folio);157157+ get_random_bytes(addr, size);158158+ csum = csum_partial(addr, size, csum);159159+ alloc_size += size;160160+ }161161+162162+ state->csum = csum;163163+ return 0;164164+165165+err_free_folios:166166+ for (int i = 0; i < state->nr_folios; i++)167167+ folio_put(state->folios[i]);168168+ return -ENOMEM;169169+}170170+171171+static int kho_test_save(void)172172+{173173+ struct kho_test_state *state = &kho_test_state;174174+ struct folio **folios __free(kvfree) = NULL;175175+ unsigned long max_nr;176176+ int err;177177+178178+ max_mem = PAGE_ALIGN(max_mem);179179+ max_nr = max_mem >> PAGE_SHIFT;180180+181181+ folios = kvmalloc_array(max_nr, sizeof(*state->folios), GFP_KERNEL);182182+ if (!folios)183183+ return -ENOMEM;184184+ state->folios = folios;185185+186186+ err = kho_test_generate_data(state);187187+ if (err)188188+ return err;189189+190190+ err = kho_test_prepare_fdt(state);191191+ if (err)192192+ return err;193193+194194+ return register_kho_notifier(&kho_test_nb);195195+}196196+197197+static int kho_test_restore_data(const void *fdt, int node)198198+{199199+ const unsigned int *nr_folios;200200+ const phys_addr_t *folios_info;201201+ const __wsum *old_csum;202202+ __wsum csum = 0;203203+ int len;204204+205205+ node = fdt_path_offset(fdt, "/data");206206+207207+ nr_folios = fdt_getprop(fdt, node, "nr_folios", &len);208208+ if (!nr_folios || len != sizeof(*nr_folios))209209+ return -EINVAL;210210+211211+ old_csum = fdt_getprop(fdt, node, "csum", &len);212212+ if (!old_csum || len != sizeof(*old_csum))213213+ return -EINVAL;214214+215215+ folios_info = fdt_getprop(fdt, node, "folios_info", &len);216216+ if (!folios_info || len != sizeof(*folios_info) * *nr_folios)217217+ return -EINVAL;218218+219219+ for (int i = 0; i < *nr_folios; i++) {220220+ unsigned int order = folios_info[i] & ~PAGE_MASK;221221+ phys_addr_t phys = folios_info[i] & PAGE_MASK;222222+ unsigned int size = PAGE_SIZE << order;223223+ struct folio *folio;224224+225225+ folio = kho_restore_folio(phys);226226+ if (!folio)227227+ break;228228+229229+ if (folio_order(folio) != order)230230+ break;231231+232232+ csum = csum_partial(folio_address(folio), size, csum);233233+ folio_put(folio);234234+ }235235+236236+ if (csum != *old_csum)237237+ return -EINVAL;238238+239239+ return 0;240240+}241241+242242+static int kho_test_restore(phys_addr_t fdt_phys)243243+{244244+ void *fdt = phys_to_virt(fdt_phys);245245+ const unsigned int *magic;246246+ int node, len, err;247247+248248+ node = fdt_path_offset(fdt, "/");249249+ if (node < 0)250250+ return -EINVAL;251251+252252+ if (fdt_node_check_compatible(fdt, node, KHO_TEST_COMPAT))253253+ return -EINVAL;254254+255255+ magic = fdt_getprop(fdt, node, "magic", &len);256256+ if (!magic || len != sizeof(*magic))257257+ return -EINVAL;258258+259259+ if (*magic != KHO_TEST_MAGIC)260260+ return -EINVAL;261261+262262+ err = kho_test_restore_data(fdt, node);263263+ if (err)264264+ return err;265265+266266+ pr_info("KHO restore succeeded\n");267267+ return 0;268268+}269269+270270+static int __init kho_test_init(void)271271+{272272+ phys_addr_t fdt_phys;273273+ int err;274274+275275+ err = kho_retrieve_subtree(KHO_TEST_FDT, &fdt_phys);276276+ if (!err)277277+ return kho_test_restore(fdt_phys);278278+279279+ if (err != -ENOENT) {280280+ pr_warn("failed to retrieve %s FDT: %d\n", KHO_TEST_FDT, err);281281+ return err;282282+ }283283+284284+ return kho_test_save();285285+}286286+module_init(kho_test_init);287287+288288+static void kho_test_cleanup(void)289289+{290290+ for (int i = 0; i < kho_test_state.nr_folios; i++)291291+ folio_put(kho_test_state.folios[i]);292292+293293+ kvfree(kho_test_state.folios);294294+}295295+296296+static void __exit kho_test_exit(void)297297+{298298+ unregister_kho_notifier(&kho_test_nb);299299+ kho_test_cleanup();300300+}301301+module_exit(kho_test_exit);302302+303303+MODULE_AUTHOR("Mike Rapoport <rppt@kernel.org>");304304+MODULE_DESCRIPTION("KHO test module");305305+MODULE_LICENSE("GPL");
+61-9
lib/vsprintf.c
···6060bool no_hash_pointers __ro_after_init;6161EXPORT_SYMBOL_GPL(no_hash_pointers);62626363+/*6464+ * Hashed pointers policy selected by "hash_pointers=..." boot param6565+ *6666+ * `auto` - Hashed pointers enabled unless disabled by slub_debug_enabled=true6767+ * `always` - Hashed pointers enabled unconditionally6868+ * `never` - Hashed pointers disabled unconditionally6969+ */7070+enum hash_pointers_policy {7171+ HASH_PTR_AUTO = 0,7272+ HASH_PTR_ALWAYS,7373+ HASH_PTR_NEVER7474+};7575+static enum hash_pointers_policy hash_pointers_mode __initdata;7676+6377noinline6478static unsigned long long simple_strntoull(const char *startp, char **endp, unsigned int base, size_t max_chars)6579{···17131699 return buf;17141700}1715170117161716-#pragma GCC diagnostic push17171717-#ifndef __clang__17181718-#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"17191719-#endif17021702+__diag_push();17031703+__diag_ignore(GCC, all, "-Wsuggest-attribute=format",17041704+ "Not a valid __printf() conversion candidate.");17201705static char *va_format(char *buf, char *end, struct va_format *va_fmt,17211706 struct printf_spec spec)17221707{···1730171717311718 return buf;17321719}17331733-#pragma GCC diagnostic pop17201720+__diag_pop();1734172117351722static noinline_for_stack17361723char *uuid_string(char *buf, char *end, const u8 *addr,···23022289 return resource_string(buf, end, ptr, spec, fmt);23032290}2304229123052305-int __init no_hash_pointers_enable(char *str)22922292+void __init hash_pointers_finalize(bool slub_debug)23062293{23072307- if (no_hash_pointers)23082308- return 0;22942294+ switch (hash_pointers_mode) {22952295+ case HASH_PTR_ALWAYS:22962296+ no_hash_pointers = false;22972297+ break;22982298+ case HASH_PTR_NEVER:22992299+ no_hash_pointers = true;23002300+ break;23012301+ case HASH_PTR_AUTO:23022302+ default:23032303+ no_hash_pointers = slub_debug;23042304+ break;23052305+ }2309230623102310- no_hash_pointers = true;23072307+ if (!no_hash_pointers)23082308+ return;2311230923122310 pr_warn("**********************************************************\n");23132311 pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");···23312307 pr_warn("** the kernel, report this immediately to your system **\n");23322308 pr_warn("** administrator! **\n");23332309 pr_warn("** **\n");23102310+ pr_warn("** Use hash_pointers=always to force this mode off **\n");23112311+ pr_warn("** **\n");23342312 pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");23352313 pr_warn("**********************************************************\n");23142314+}23152315+23162316+static int __init hash_pointers_mode_parse(char *str)23172317+{23182318+ if (!str) {23192319+ pr_warn("Hash pointers mode empty; falling back to auto.\n");23202320+ hash_pointers_mode = HASH_PTR_AUTO;23212321+ } else if (strncmp(str, "auto", 4) == 0) {23222322+ pr_info("Hash pointers mode set to auto.\n");23232323+ hash_pointers_mode = HASH_PTR_AUTO;23242324+ } else if (strncmp(str, "never", 5) == 0) {23252325+ pr_info("Hash pointers mode set to never.\n");23262326+ hash_pointers_mode = HASH_PTR_NEVER;23272327+ } else if (strncmp(str, "always", 6) == 0) {23282328+ pr_info("Hash pointers mode set to always.\n");23292329+ hash_pointers_mode = HASH_PTR_ALWAYS;23302330+ } else {23312331+ pr_warn("Unknown hash_pointers mode '%s' specified; assuming auto.\n", str);23322332+ hash_pointers_mode = HASH_PTR_AUTO;23332333+ }2336233423372335 return 0;23362336+}23372337+early_param("hash_pointers", hash_pointers_mode_parse);23382338+23392339+static int __init no_hash_pointers_enable(char *str)23402340+{23412341+ return hash_pointers_mode_parse("never");23382342}23392343early_param("no_hash_pointers", no_hash_pointers_enable);23402344
···12421242config KMAP_LOCAL_NON_LINEAR_PTE_ARRAY12431243 bool1244124412451245-# struct io_mapping based helper. Selected by drivers that need them12461246-config IO_MAPPING12471247- bool12481248-12491245config MEMFD_CREATE12501246 bool "Enable memfd_create() system call" if EXPERT12511247
···711711 target -= dests->weight_arr[i];712712 }713713714714+ /* If the folio is already in the right node, don't do anything */715715+ if (folio_nid(folio) == dests->node_id_arr[i])716716+ return;717717+714718isolate:715719 if (!folio_isolate_lru(folio))716720 return;
+157-55
mm/execmem.c
···26262727#ifdef CONFIG_MMU2828static void *execmem_vmalloc(struct execmem_range *range, size_t size,2929- pgprot_t pgprot, vm_flags_t vm_flags)2929+ pgprot_t pgprot, unsigned long vm_flags)3030{3131 bool kasan = range->flags & EXECMEM_KASAN_SHADOW;3232 gfp_t gfp_flags = GFP_KERNEL | __GFP_NOWARN;···8282}8383#else8484static void *execmem_vmalloc(struct execmem_range *range, size_t size,8585- pgprot_t pgprot, vm_flags_t vm_flags)8585+ pgprot_t pgprot, unsigned long vm_flags)8686{8787 return vmalloc(size);8888}···9393 struct mutex mutex;9494 struct maple_tree busy_areas;9595 struct maple_tree free_areas;9696+ unsigned int pending_free_cnt; /* protected by mutex */9697};9898+9999+/* delay to schedule asynchronous free if fast path free fails */100100+#define FREE_DELAY (msecs_to_jiffies(10))101101+102102+/* mark entries in busy_areas that should be freed asynchronously */103103+#define PENDING_FREE_MASK (1 << (PAGE_SHIFT - 1))9710498105static struct execmem_cache execmem_cache = {99106 .mutex = __MUTEX_INITIALIZER(execmem_cache.mutex),···137130 return err;138131}139132133133+static int execmem_force_rw(void *ptr, size_t size)134134+{135135+ unsigned int nr = PAGE_ALIGN(size) >> PAGE_SHIFT;136136+ unsigned long addr = (unsigned long)ptr;137137+ int ret;138138+139139+ ret = set_memory_nx(addr, nr);140140+ if (ret)141141+ return ret;142142+143143+ return set_memory_rw(addr, nr);144144+}145145+146146+int execmem_restore_rox(void *ptr, size_t size)147147+{148148+ unsigned int nr = PAGE_ALIGN(size) >> PAGE_SHIFT;149149+ unsigned long addr = (unsigned long)ptr;150150+151151+ return set_memory_rox(addr, nr);152152+}153153+140154static void execmem_cache_clean(struct work_struct *work)141155{142156 struct maple_tree *free_areas = &execmem_cache.free_areas;···183155184156static DECLARE_WORK(execmem_cache_clean_work, execmem_cache_clean);185157186186-static int execmem_cache_add(void *ptr, size_t size)158158+static int execmem_cache_add_locked(void *ptr, size_t size, gfp_t gfp_mask)187159{188160 struct maple_tree *free_areas = &execmem_cache.free_areas;189189- struct mutex *mutex = &execmem_cache.mutex;190161 unsigned long addr = (unsigned long)ptr;191162 MA_STATE(mas, free_areas, addr - 1, addr + 1);192163 unsigned long lower, upper;193164 void *area = NULL;194194- int err;195165196166 lower = addr;197167 upper = addr + size - 1;198168199199- mutex_lock(mutex);200169 area = mas_walk(&mas);201170 if (area && mas.last == addr - 1)202171 lower = mas.index;···203178 upper = mas.last;204179205180 mas_set_range(&mas, lower, upper);206206- err = mas_store_gfp(&mas, (void *)lower, GFP_KERNEL);207207- mutex_unlock(mutex);208208- if (err)209209- return err;181181+ return mas_store_gfp(&mas, (void *)lower, gfp_mask);182182+}210183211211- return 0;184184+static int execmem_cache_add(void *ptr, size_t size, gfp_t gfp_mask)185185+{186186+ guard(mutex)(&execmem_cache.mutex);187187+188188+ return execmem_cache_add_locked(ptr, size, gfp_mask);212189}213190214191static bool within_range(struct execmem_range *range, struct ma_state *mas,···283256284257static int execmem_cache_populate(struct execmem_range *range, size_t size)285258{286286- vm_flags_t vm_flags = VM_ALLOW_HUGE_VMAP;259259+ unsigned long vm_flags = VM_ALLOW_HUGE_VMAP;287260 struct vm_struct *vm;288261 size_t alloc_size;289262 int err = -ENOMEM;···291264292265 alloc_size = round_up(size, PMD_SIZE);293266 p = execmem_vmalloc(range, alloc_size, PAGE_KERNEL, vm_flags);267267+ if (!p) {268268+ alloc_size = size;269269+ p = execmem_vmalloc(range, alloc_size, PAGE_KERNEL, vm_flags);270270+ }271271+294272 if (!p)295273 return err;296274···304272 goto err_free_mem;305273306274 /* fill memory with instructions that will trap */307307- execmem_fill_trapping_insns(p, alloc_size, /* writable = */ true);275275+ execmem_fill_trapping_insns(p, alloc_size);308276309277 err = set_memory_rox((unsigned long)p, vm->nr_pages);310278 if (err)311279 goto err_free_mem;312280313313- err = execmem_cache_add(p, alloc_size);281281+ err = execmem_cache_add(p, alloc_size, GFP_KERNEL);314282 if (err)315283 goto err_reset_direct_map;316284···339307 return __execmem_cache_alloc(range, size);340308}341309310310+static inline bool is_pending_free(void *ptr)311311+{312312+ return ((unsigned long)ptr & PENDING_FREE_MASK);313313+}314314+315315+static inline void *pending_free_set(void *ptr)316316+{317317+ return (void *)((unsigned long)ptr | PENDING_FREE_MASK);318318+}319319+320320+static inline void *pending_free_clear(void *ptr)321321+{322322+ return (void *)((unsigned long)ptr & ~PENDING_FREE_MASK);323323+}324324+325325+static int __execmem_cache_free(struct ma_state *mas, void *ptr, gfp_t gfp_mask)326326+{327327+ size_t size = mas_range_len(mas);328328+ int err;329329+330330+ err = execmem_force_rw(ptr, size);331331+ if (err)332332+ return err;333333+334334+ execmem_fill_trapping_insns(ptr, size);335335+ execmem_restore_rox(ptr, size);336336+337337+ err = execmem_cache_add_locked(ptr, size, gfp_mask);338338+ if (err)339339+ return err;340340+341341+ mas_store_gfp(mas, NULL, gfp_mask);342342+ return 0;343343+}344344+345345+static void execmem_cache_free_slow(struct work_struct *work);346346+static DECLARE_DELAYED_WORK(execmem_cache_free_work, execmem_cache_free_slow);347347+348348+static void execmem_cache_free_slow(struct work_struct *work)349349+{350350+ struct maple_tree *busy_areas = &execmem_cache.busy_areas;351351+ MA_STATE(mas, busy_areas, 0, ULONG_MAX);352352+ void *area;353353+354354+ guard(mutex)(&execmem_cache.mutex);355355+356356+ if (!execmem_cache.pending_free_cnt)357357+ return;358358+359359+ mas_for_each(&mas, area, ULONG_MAX) {360360+ if (!is_pending_free(area))361361+ continue;362362+363363+ area = pending_free_clear(area);364364+ if (__execmem_cache_free(&mas, area, GFP_KERNEL))365365+ continue;366366+367367+ execmem_cache.pending_free_cnt--;368368+ }369369+370370+ if (execmem_cache.pending_free_cnt)371371+ schedule_delayed_work(&execmem_cache_free_work, FREE_DELAY);372372+ else373373+ schedule_work(&execmem_cache_clean_work);374374+}375375+342376static bool execmem_cache_free(void *ptr)343377{344378 struct maple_tree *busy_areas = &execmem_cache.busy_areas;345345- struct mutex *mutex = &execmem_cache.mutex;346379 unsigned long addr = (unsigned long)ptr;347380 MA_STATE(mas, busy_areas, addr, addr);348348- size_t size;349381 void *area;382382+ int err;350383351351- mutex_lock(mutex);384384+ guard(mutex)(&execmem_cache.mutex);385385+352386 area = mas_walk(&mas);353353- if (!area) {354354- mutex_unlock(mutex);387387+ if (!area)355388 return false;389389+390390+ err = __execmem_cache_free(&mas, area, GFP_KERNEL | __GFP_NORETRY);391391+ if (err) {392392+ /*393393+ * mas points to exact slot we've got the area from, nothing394394+ * else can modify the tree because of the mutex, so there395395+ * won't be any allocations in mas_store_gfp() and it will just396396+ * change the pointer.397397+ */398398+ area = pending_free_set(area);399399+ mas_store_gfp(&mas, area, GFP_KERNEL);400400+ execmem_cache.pending_free_cnt++;401401+ schedule_delayed_work(&execmem_cache_free_work, FREE_DELAY);402402+ return true;356403 }357357- size = mas_range_len(&mas);358358-359359- mas_store_gfp(&mas, NULL, GFP_KERNEL);360360- mutex_unlock(mutex);361361-362362- execmem_fill_trapping_insns(ptr, size, /* writable = */ false);363363-364364- execmem_cache_add(ptr, size);365404366405 schedule_work(&execmem_cache_clean_work);367406368407 return true;369408}370409371371-int execmem_make_temp_rw(void *ptr, size_t size)372372-{373373- unsigned int nr = PAGE_ALIGN(size) >> PAGE_SHIFT;374374- unsigned long addr = (unsigned long)ptr;375375- int ret;376376-377377- ret = set_memory_nx(addr, nr);378378- if (ret)379379- return ret;380380-381381- return set_memory_rw(addr, nr);382382-}383383-384384-int execmem_restore_rox(void *ptr, size_t size)385385-{386386- unsigned int nr = PAGE_ALIGN(size) >> PAGE_SHIFT;387387- unsigned long addr = (unsigned long)ptr;388388-389389- return set_memory_rox(addr, nr);390390-}391391-392410#else /* CONFIG_ARCH_HAS_EXECMEM_ROX */411411+/*412412+ * when ROX cache is not used the permissions defined by architectures for413413+ * execmem ranges that are updated before use (e.g. EXECMEM_MODULE_TEXT) must414414+ * be writable anyway415415+ */416416+static inline int execmem_force_rw(void *ptr, size_t size)417417+{418418+ return 0;419419+}420420+393421static void *execmem_cache_alloc(struct execmem_range *range, size_t size)394422{395423 return NULL;···465373{466374 struct execmem_range *range = &execmem_info->ranges[type];467375 bool use_cache = range->flags & EXECMEM_ROX_CACHE;468468- vm_flags_t vm_flags = VM_FLUSH_RESET_PERMS;376376+ unsigned long vm_flags = VM_FLUSH_RESET_PERMS;469377 pgprot_t pgprot = range->pgprot;470470- void *p;378378+ void *p = NULL;471379472380 size = PAGE_ALIGN(size);473381···477385 p = execmem_vmalloc(range, size, pgprot, vm_flags);478386479387 return kasan_reset_tag(p);388388+}389389+390390+void *execmem_alloc_rw(enum execmem_type type, size_t size)391391+{392392+ void *p __free(execmem) = execmem_alloc(type, size);393393+ int err;394394+395395+ if (!p)396396+ return NULL;397397+398398+ err = execmem_force_rw(p, size);399399+ if (err)400400+ return NULL;401401+402402+ return no_free_ptr(p);480403}481404482405void execmem_free(void *ptr)···504397505398 if (!execmem_cache_free(ptr))506399 vfree(ptr);507507-}508508-509509-void *execmem_update_copy(void *dst, const void *src, size_t size)510510-{511511- return text_poke_copy(dst, src, size);512400}513401514402bool execmem_is_rox(enum execmem_type type)
+1-1
mm/internal.h
···1391139113921392struct vm_struct *__get_vm_area_node(unsigned long size,13931393 unsigned long align, unsigned long shift,13941394- vm_flags_t vm_flags, unsigned long start,13941394+ unsigned long vm_flags, unsigned long start,13951395 unsigned long end, int node, gfp_t gfp_mask,13961396 const void *caller);13971397
-30
mm/io-mapping.c
···11-// SPDX-License-Identifier: GPL-2.0-only22-33-#include <linux/mm.h>44-#include <linux/io-mapping.h>55-66-/**77- * io_mapping_map_user - remap an I/O mapping to userspace88- * @iomap: the source io_mapping99- * @vma: user vma to map to1010- * @addr: target user address to start at1111- * @pfn: physical address of kernel memory1212- * @size: size of map area1313- *1414- * Note: this is only safe if the mm semaphore is held when called.1515- */1616-int io_mapping_map_user(struct io_mapping *iomap, struct vm_area_struct *vma,1717- unsigned long addr, unsigned long pfn, unsigned long size)1818-{1919- vm_flags_t expected_flags = VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;2020-2121- if (WARN_ON_ONCE((vma->vm_flags & expected_flags) != expected_flags))2222- return -EINVAL;2323-2424- pgprot_t remap_prot = __pgprot((pgprot_val(iomap->prot) & _PAGE_CACHE_MASK) |2525- (pgprot_val(vma->vm_page_prot) & ~_PAGE_CACHE_MASK));2626-2727- /* We rely on prevalidation of the io-mapping to skip pfnmap tracking. */2828- return remap_pfn_range_notrack(vma, addr, pfn, size, remap_prot);2929-}3030-EXPORT_SYMBOL_GPL(io_mapping_map_user);
+18-7
mm/kasan/common.c
···230230}231231232232static inline void poison_slab_object(struct kmem_cache *cache, void *object,233233- bool init, bool still_accessible)233233+ bool init)234234{235235 void *tagged_object = object;236236237237 object = kasan_reset_tag(object);238238-239239- /* RCU slabs could be legally used after free within the RCU period. */240240- if (unlikely(still_accessible))241241- return;242238243239 kasan_poison(object, round_up(cache->object_size, KASAN_GRANULE_SIZE),244240 KASAN_SLAB_FREE, init);···257261 if (!kasan_arch_is_ready() || is_kfence_address(object))258262 return false;259263260260- poison_slab_object(cache, object, init, still_accessible);264264+ /*265265+ * If this point is reached with an object that must still be266266+ * accessible under RCU, we can't poison it; in that case, also skip the267267+ * quarantine. This should mostly only happen when CONFIG_SLUB_RCU_DEBUG268268+ * has been disabled manually.269269+ *270270+ * Putting the object on the quarantine wouldn't help catch UAFs (since271271+ * we can't poison it here), and it would mask bugs caused by272272+ * SLAB_TYPESAFE_BY_RCU users not being careful enough about object273273+ * reuse; so overall, putting the object into the quarantine here would274274+ * be counterproductive.275275+ */276276+ if (still_accessible)277277+ return false;278278+279279+ poison_slab_object(cache, object, init);261280262281 /*263282 * If the object is put into quarantine, do not let slab put the object···530519 if (check_slab_allocation(slab->slab_cache, ptr, ip))531520 return false;532521533533- poison_slab_object(slab->slab_cache, ptr, false, false);522522+ poison_slab_object(slab->slab_cache, ptr, false);534523 return true;535524}536525
+39-19
mm/khugepaged.c
···700700 spinlock_t *ptl,701701 struct list_head *compound_pagelist)702702{703703+ unsigned long end = address + HPAGE_PMD_SIZE;703704 struct folio *src, *tmp;704704- pte_t *_pte;705705 pte_t pteval;706706+ pte_t *_pte;707707+ unsigned int nr_ptes;706708707707- for (_pte = pte; _pte < pte + HPAGE_PMD_NR;708708- _pte++, address += PAGE_SIZE) {709709+ for (_pte = pte; _pte < pte + HPAGE_PMD_NR; _pte += nr_ptes,710710+ address += nr_ptes * PAGE_SIZE) {711711+ nr_ptes = 1;709712 pteval = ptep_get(_pte);710713 if (pte_none(pteval) || is_zero_pfn(pte_pfn(pteval))) {711714 add_mm_counter(vma->vm_mm, MM_ANONPAGES, 1);···725722 struct page *src_page = pte_page(pteval);726723727724 src = page_folio(src_page);728728- if (!folio_test_large(src))725725+726726+ if (folio_test_large(src)) {727727+ unsigned int max_nr_ptes = (end - address) >> PAGE_SHIFT;728728+729729+ nr_ptes = folio_pte_batch(src, _pte, pteval, max_nr_ptes);730730+ } else {729731 release_pte_folio(src);732732+ }733733+730734 /*731735 * ptl mostly unnecessary, but preempt has to732736 * be disabled to update the per-cpu stats733737 * inside folio_remove_rmap_pte().734738 */735739 spin_lock(ptl);736736- ptep_clear(vma->vm_mm, address, _pte);737737- folio_remove_rmap_pte(src, src_page, vma);740740+ clear_ptes(vma->vm_mm, address, _pte, nr_ptes);741741+ folio_remove_rmap_ptes(src, src_page, nr_ptes, vma);738742 spin_unlock(ptl);739739- free_folio_and_swap_cache(src);743743+ free_swap_cache(src);744744+ folio_put_refs(src, nr_ptes);740745 }741746 }742747···15031492int collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,15041493 bool install_pmd)15051494{14951495+ int nr_mapped_ptes = 0, result = SCAN_FAIL;14961496+ unsigned int nr_batch_ptes;15061497 struct mmu_notifier_range range;15071498 bool notified = false;15081499 unsigned long haddr = addr & HPAGE_PMD_MASK;15001500+ unsigned long end = haddr + HPAGE_PMD_SIZE;15091501 struct vm_area_struct *vma = vma_lookup(mm, haddr);15101502 struct folio *folio;15111503 pte_t *start_pte, *pte;15121504 pmd_t *pmd, pgt_pmd;15131505 spinlock_t *pml = NULL, *ptl;15141514- int nr_ptes = 0, result = SCAN_FAIL;15151506 int i;1516150715171508 mmap_assert_locked(mm);···16271614 goto abort;1628161516291616 /* step 2: clear page table and adjust rmap */16301630- for (i = 0, addr = haddr, pte = start_pte;16311631- i < HPAGE_PMD_NR; i++, addr += PAGE_SIZE, pte++) {16171617+ for (i = 0, addr = haddr, pte = start_pte; i < HPAGE_PMD_NR;16181618+ i += nr_batch_ptes, addr += nr_batch_ptes * PAGE_SIZE,16191619+ pte += nr_batch_ptes) {16201620+ unsigned int max_nr_batch_ptes = (end - addr) >> PAGE_SHIFT;16321621 struct page *page;16331622 pte_t ptent = ptep_get(pte);16231623+16241624+ nr_batch_ptes = 1;1634162516351626 if (pte_none(ptent))16361627 continue;···16491632 goto abort;16501633 }16511634 page = vm_normal_page(vma, addr, ptent);16351635+16521636 if (folio_page(folio, i) != page)16531637 goto abort;16381638+16391639+ nr_batch_ptes = folio_pte_batch(folio, pte, ptent, max_nr_batch_ptes);1654164016551641 /*16561642 * Must clear entry, or a racing truncate may re-remove it.16571643 * TLB flush can be left until pmdp_collapse_flush() does it.16581644 * PTE dirty? Shmem page is already dirty; file is read-only.16591645 */16601660- ptep_clear(mm, addr, pte);16611661- folio_remove_rmap_pte(folio, page, vma);16621662- nr_ptes++;16461646+ clear_ptes(mm, addr, pte, nr_batch_ptes);16471647+ folio_remove_rmap_ptes(folio, page, nr_batch_ptes, vma);16481648+ nr_mapped_ptes += nr_batch_ptes;16631649 }1664165016651651 if (!pml)16661652 spin_unlock(ptl);1667165316681654 /* step 3: set proper refcount and mm_counters. */16691669- if (nr_ptes) {16701670- folio_ref_sub(folio, nr_ptes);16711671- add_mm_counter(mm, mm_counter_file(folio), -nr_ptes);16551655+ if (nr_mapped_ptes) {16561656+ folio_ref_sub(folio, nr_mapped_ptes);16571657+ add_mm_counter(mm, mm_counter_file(folio), -nr_mapped_ptes);16721658 }1673165916741660 /* step 4: remove empty page table */···17041684 : SCAN_SUCCEED;17051685 goto drop_folio;17061686abort:17071707- if (nr_ptes) {16871687+ if (nr_mapped_ptes) {17081688 flush_tlb_mm(mm);17091709- folio_ref_sub(folio, nr_ptes);17101710- add_mm_counter(mm, mm_counter_file(folio), -nr_ptes);16891689+ folio_ref_sub(folio, nr_mapped_ptes);16901690+ add_mm_counter(mm, mm_counter_file(folio), -nr_mapped_ptes);17111691 }17121692unlock:17131693 if (start_pte)
+70-1
mm/madvise.c
···1919#include <linux/sched.h>2020#include <linux/sched/mm.h>2121#include <linux/mm_inline.h>2222+#include <linux/mmu_context.h>2223#include <linux/string.h>2324#include <linux/uio.h>2425#include <linux/ksm.h>···12571256 &guard_remove_walk_ops, NULL);12581257}1259125812591259+#ifdef CONFIG_64BIT12601260+/* Does the madvise operation result in discarding of mapped data? */12611261+static bool is_discard(int behavior)12621262+{12631263+ switch (behavior) {12641264+ case MADV_FREE:12651265+ case MADV_DONTNEED:12661266+ case MADV_DONTNEED_LOCKED:12671267+ case MADV_REMOVE:12681268+ case MADV_DONTFORK:12691269+ case MADV_WIPEONFORK:12701270+ case MADV_GUARD_INSTALL:12711271+ return true;12721272+ }12731273+12741274+ return false;12751275+}12761276+12771277+/*12781278+ * We are restricted from madvise()'ing mseal()'d VMAs only in very particular12791279+ * circumstances - discarding of data from read-only anonymous SEALED mappings.12801280+ *12811281+ * This is because users cannot trivally discard data from these VMAs, and may12821282+ * only do so via an appropriate madvise() call.12831283+ */12841284+static bool can_madvise_modify(struct madvise_behavior *madv_behavior)12851285+{12861286+ struct vm_area_struct *vma = madv_behavior->vma;12871287+12881288+ /* If the VMA isn't sealed we're good. */12891289+ if (!vma_is_sealed(vma))12901290+ return true;12911291+12921292+ /* For a sealed VMA, we only care about discard operations. */12931293+ if (!is_discard(madv_behavior->behavior))12941294+ return true;12951295+12961296+ /*12971297+ * We explicitly permit all file-backed mappings, whether MAP_SHARED or12981298+ * MAP_PRIVATE.12991299+ *13001300+ * The latter causes some complications. Because now, one can mmap()13011301+ * read/write a MAP_PRIVATE mapping, write to it, then mprotect()13021302+ * read-only, mseal() and a discard will be permitted.13031303+ *13041304+ * However, in order to avoid issues with potential use of madvise(...,13051305+ * MADV_DONTNEED) of mseal()'d .text mappings we, for the time being,13061306+ * permit this.13071307+ */13081308+ if (!vma_is_anonymous(vma))13091309+ return true;13101310+13111311+ /* If the user could write to the mapping anyway, then this is fine. */13121312+ if ((vma->vm_flags & VM_WRITE) &&13131313+ arch_vma_access_permitted(vma, /* write= */ true,13141314+ /* execute= */ false, /* foreign= */ false))13151315+ return true;13161316+13171317+ /* Otherwise, we are not permitted to perform this operation. */13181318+ return false;13191319+}13201320+#else13211321+static bool can_madvise_modify(struct madvise_behavior *madv_behavior)13221322+{13231323+ return true;13241324+}13251325+#endif13261326+12601327/*12611328 * Apply an madvise behavior to a region of a vma. madvise_update_vma12621329 * will handle splitting a vm area into separate areas, each area with its own···13381269 struct madvise_behavior_range *range = &madv_behavior->range;13391270 int error;1340127113411341- if (unlikely(!can_modify_vma_madv(madv_behavior->vma, behavior)))12721272+ if (unlikely(!can_madvise_modify(madv_behavior)))13421273 return -EPERM;1343127413441275 switch (behavior) {
···136136137137static __always_inline void add_element(mempool_t *pool, void *element)138138{139139- BUG_ON(pool->curr_nr >= pool->min_nr);139139+ BUG_ON(pool->min_nr != 0 && pool->curr_nr >= pool->min_nr);140140 poison_element(pool, element);141141 if (kasan_poison_element(pool, element))142142 pool->elements[pool->curr_nr++] = element;···202202 pool->alloc = alloc_fn;203203 pool->free = free_fn;204204 init_waitqueue_head(&pool->wait);205205-206206- pool->elements = kmalloc_array_node(min_nr, sizeof(void *),205205+ /*206206+ * max() used here to ensure storage for at least 1 element to support207207+ * zero minimum pool208208+ */209209+ pool->elements = kmalloc_array_node(max(1, min_nr), sizeof(void *),207210 gfp_mask, node_id);208211 if (!pool->elements)209212 return -ENOMEM;210213211214 /*212212- * First pre-allocate the guaranteed number of buffers.215215+ * First pre-allocate the guaranteed number of buffers,216216+ * also pre-allocate 1 element for zero minimum pool.213217 */214214- while (pool->curr_nr < pool->min_nr) {218218+ while (pool->curr_nr < max(1, pool->min_nr)) {215219 void *element;216220217221 element = pool->alloc(gfp_mask, pool->pool_data);···559555 * wake-up path of previous test. This explicit check ensures the560556 * allocation of element when both min_nr and curr_nr are 0, and561557 * any active waiters are properly awakened.562562- *563563- * Inline the same logic as previous test, add_element() cannot be564564- * directly used here since it has BUG_ON to deny if min_nr equals565565- * curr_nr, so here picked rest of add_element() to use without566566- * BUG_ON check.567558 */568559 if (unlikely(pool->min_nr == 0 &&569560 READ_ONCE(pool->curr_nr) == 0)) {570561 spin_lock_irqsave(&pool->lock, flags);571562 if (likely(pool->curr_nr == 0)) {572572- /* Inline the logic of add_element() */573573- poison_element(pool, element);574574- if (kasan_poison_element(pool, element))575575- pool->elements[pool->curr_nr++] = element;563563+ add_element(pool, element);576564 spin_unlock_irqrestore(&pool->lock, flags);577565 if (wq_has_sleeper(&pool->wait))578566 wake_up(&pool->wait);
+3
mm/mincore.c
···2929#ifdef CONFIG_HUGETLB_PAGE3030 unsigned char present;3131 unsigned char *vec = walk->private;3232+ spinlock_t *ptl;32333434+ ptl = huge_pte_lock(hstate_vma(walk->vma), walk->mm, pte);3335 /*3436 * Hugepages under user process are always in RAM and never3537 * swapped out, but theoretically it needs to be checked.···4038 for (; addr != end; vec++, addr += PAGE_SIZE)4139 *vec = present;4240 walk->private = vec;4141+ spin_unlock(ptl);4342#else4443 BUG();4544#endif
+3-7
mm/mmap_lock.c
···164164 */165165166166 /* Check if the vma we locked is the right one. */167167- if (unlikely(vma->vm_mm != mm ||168168- address < vma->vm_start || address >= vma->vm_end))167167+ if (unlikely(address < vma->vm_start || address >= vma->vm_end))169168 goto inval_end_read;170169171170 rcu_read_unlock();···235236 goto fallback;236237 }237238238238- /*239239- * Verify the vma we locked belongs to the same address space and it's240240- * not behind of the last search position.241241- */242242- if (unlikely(vma->vm_mm != mm || from_addr >= vma->vm_end))239239+ /* Verify the vma is not behind the last search position. */240240+ if (unlikely(from_addr >= vma->vm_end))243241 goto fallback_unlock;244242245243 /*
+1-1
mm/mprotect.c
···766766 unsigned long charged = 0;767767 int error;768768769769- if (!can_modify_vma(vma))769769+ if (vma_is_sealed(vma))770770 return -EPERM;771771772772 if (newflags == oldflags) {
+2-2
mm/mremap.c
···280280 old_pte, max_nr_ptes);281281 force_flush = true;282282 }283283- pte = get_and_clear_full_ptes(mm, old_addr, old_ptep, nr_ptes, 0);283283+ pte = get_and_clear_ptes(mm, old_addr, old_ptep, nr_ptes);284284 pte = move_pte(pte, old_addr, new_addr);285285 pte = move_soft_dirty_pte(pte);286286···16511651 return -EFAULT;1652165216531653 /* If mseal()'d, mremap() is prohibited. */16541654- if (!can_modify_vma(vma))16541654+ if (vma_is_sealed(vma))16551655 return -EPERM;1656165616571657 /* Align to hugetlb page size, if required. */
+46-124
mm/mseal.c
···1111#include <linux/mman.h>1212#include <linux/mm.h>1313#include <linux/mm_inline.h>1414-#include <linux/mmu_context.h>1514#include <linux/syscalls.h>1615#include <linux/sched.h>1716#include "internal.h"18171919-static inline void set_vma_sealed(struct vm_area_struct *vma)2020-{2121- vm_flags_set(vma, VM_SEALED);2222-}2323-2424-static bool is_madv_discard(int behavior)2525-{2626- switch (behavior) {2727- case MADV_FREE:2828- case MADV_DONTNEED:2929- case MADV_DONTNEED_LOCKED:3030- case MADV_REMOVE:3131- case MADV_DONTFORK:3232- case MADV_WIPEONFORK:3333- case MADV_GUARD_INSTALL:3434- return true;3535- }3636-3737- return false;3838-}3939-4040-static bool is_ro_anon(struct vm_area_struct *vma)4141-{4242- /* check anonymous mapping. */4343- if (vma->vm_file || vma->vm_flags & VM_SHARED)4444- return false;4545-4646- /*4747- * check for non-writable:4848- * PROT=RO or PKRU is not writeable.4949- */5050- if (!(vma->vm_flags & VM_WRITE) ||5151- !arch_vma_access_permitted(vma, true, false, false))5252- return true;5353-5454- return false;5555-}1818+/*1919+ * mseal() disallows an input range which contain unmapped ranges (VMA holes).2020+ *2121+ * It disallows unmapped regions from start to end whether they exist at the2222+ * start, in the middle, or at the end of the range, or any combination thereof.2323+ *2424+ * This is because after sealng a range, there's nothing to stop memory mapping2525+ * of ranges in the remaining gaps later, meaning that the user might then2626+ * wrongly consider the entirety of the mseal()'d range to be sealed when it2727+ * in fact isn't.2828+ */56295730/*5858- * Check if a vma is allowed to be modified by madvise.3131+ * Does the [start, end) range contain any unmapped memory?3232+ *3333+ * We ensure that:3434+ * - start is part of a valid VMA.3535+ * - end is part of a valid VMA.3636+ * - no gap (unallocated memory) exists between start and end.5937 */6060-bool can_modify_vma_madv(struct vm_area_struct *vma, int behavior)6161-{6262- if (!is_madv_discard(behavior))6363- return true;6464-6565- if (unlikely(!can_modify_vma(vma) && is_ro_anon(vma)))6666- return false;6767-6868- /* Allow by default. */6969- return true;7070-}7171-7272-static int mseal_fixup(struct vma_iterator *vmi, struct vm_area_struct *vma,7373- struct vm_area_struct **prev, unsigned long start,7474- unsigned long end, vm_flags_t newflags)7575-{7676- int ret = 0;7777- vm_flags_t oldflags = vma->vm_flags;7878-7979- if (newflags == oldflags)8080- goto out;8181-8282- vma = vma_modify_flags(vmi, *prev, vma, start, end, newflags);8383- if (IS_ERR(vma)) {8484- ret = PTR_ERR(vma);8585- goto out;8686- }8787-8888- set_vma_sealed(vma);8989-out:9090- *prev = vma;9191- return ret;9292-}9393-9494-/*9595- * Check for do_mseal:9696- * 1> start is part of a valid vma.9797- * 2> end is part of a valid vma.9898- * 3> No gap (unallocated address) between start and end.9999- * 4> map is sealable.100100- */101101-static int check_mm_seal(unsigned long start, unsigned long end)3838+static bool range_contains_unmapped(struct mm_struct *mm,3939+ unsigned long start, unsigned long end)10240{10341 struct vm_area_struct *vma;104104- unsigned long nstart = start;105105-4242+ unsigned long prev_end = start;10643 VMA_ITERATOR(vmi, current->mm, start);10744108108- /* going through each vma to check. */10945 for_each_vma_range(vmi, vma, end) {110110- if (vma->vm_start > nstart)111111- /* unallocated memory found. */112112- return -ENOMEM;4646+ if (vma->vm_start > prev_end)4747+ return true;11348114114- if (vma->vm_end >= end)115115- return 0;116116-117117- nstart = vma->vm_end;4949+ prev_end = vma->vm_end;11850 }11951120120- return -ENOMEM;5252+ return prev_end < end;12153}12254123123-/*124124- * Apply sealing.125125- */126126-static int apply_mm_seal(unsigned long start, unsigned long end)5555+static int mseal_apply(struct mm_struct *mm,5656+ unsigned long start, unsigned long end)12757{128128- unsigned long nstart;12958 struct vm_area_struct *vma, *prev;5959+ unsigned long curr_start = start;6060+ VMA_ITERATOR(vmi, mm, start);13061131131- VMA_ITERATOR(vmi, current->mm, start);132132-6262+ /* We know there are no gaps so this will be non-NULL. */13363 vma = vma_iter_load(&vmi);134134- /*135135- * Note: check_mm_seal should already checked ENOMEM case.136136- * so vma should not be null, same for the other ENOMEM cases.137137- */13864 prev = vma_prev(&vmi);13965 if (start > vma->vm_start)14066 prev = vma;14167142142- nstart = start;14368 for_each_vma_range(vmi, vma, end) {144144- int error;145145- unsigned long tmp;146146- vm_flags_t newflags;6969+ unsigned long curr_end = MIN(vma->vm_end, end);14770148148- newflags = vma->vm_flags | VM_SEALED;149149- tmp = vma->vm_end;150150- if (tmp > end)151151- tmp = end;152152- error = mseal_fixup(&vmi, vma, &prev, nstart, tmp, newflags);153153- if (error)154154- return error;155155- nstart = vma_iter_end(&vmi);7171+ if (!(vma->vm_flags & VM_SEALED)) {7272+ vma = vma_modify_flags(&vmi, prev, vma,7373+ curr_start, curr_end,7474+ vma->vm_flags | VM_SEALED);7575+ if (IS_ERR(vma))7676+ return PTR_ERR(vma);7777+ vm_flags_set(vma, VM_SEALED);7878+ }7979+8080+ prev = vma;8181+ curr_start = curr_end;15682 }1578315884 return 0;···166240 if (mmap_write_lock_killable(mm))167241 return -EINTR;168242169169- /*170170- * First pass, this helps to avoid171171- * partial sealing in case of error in input address range,172172- * e.g. ENOMEM error.173173- */174174- ret = check_mm_seal(start, end);175175- if (ret)243243+ if (range_contains_unmapped(mm, start, end)) {244244+ ret = -ENOMEM;176245 goto out;246246+ }177247178248 /*179249 * Second pass, this should success, unless there are errors···177255 * reaching the max supported VMAs, however, those cases shall178256 * be rare.179257 */180180- ret = apply_mm_seal(start, end);258258+ ret = mseal_apply(mm, start, end);181259182260out:183183- mmap_write_unlock(current->mm);261261+ mmap_write_unlock(mm);184262 return ret;185263}186264
+1-1
mm/nommu.c
···126126127127void *__vmalloc_node_range_noprof(unsigned long size, unsigned long align,128128 unsigned long start, unsigned long end, gfp_t gfp_mask,129129- pgprot_t prot, vm_flags_t vm_flags, int node,129129+ pgprot_t prot, unsigned long vm_flags, int node,130130 const void *caller)131131{132132 return __vmalloc_noprof(size, gfp_mask);
+1-1
mm/rmap.c
···20362036 flush_cache_range(vma, address, end_addr);2037203720382038 /* Nuke the page table entry. */20392039- pteval = get_and_clear_full_ptes(mm, address, pvmw.pte, nr_pages, 0);20392039+ pteval = get_and_clear_ptes(mm, address, pvmw.pte, nr_pages);20402040 /*20412041 * We clear the PTE but do not flush so potentially20422042 * a remote CPU could still be writing to the folio.
+155-126
mm/shmem.c
···512512513513/*514514 * Sometimes, before we decide whether to proceed or to fail, we must check515515- * that an entry was not already brought back from swap by a racing thread.515515+ * that an entry was not already brought back or split by a racing thread.516516 *517517 * Checking folio is not enough: by the time a swapcache folio is locked, it518518 * might be reused, and again be swapcache, using the same swap as before.519519+ * Returns the swap entry's order if it still presents, else returns -1.519520 */520520-static bool shmem_confirm_swap(struct address_space *mapping,521521- pgoff_t index, swp_entry_t swap)521521+static int shmem_confirm_swap(struct address_space *mapping, pgoff_t index,522522+ swp_entry_t swap)522523{523523- return xa_load(&mapping->i_pages, index) == swp_to_radix_entry(swap);524524+ XA_STATE(xas, &mapping->i_pages, index);525525+ int ret = -1;526526+ void *entry;527527+528528+ rcu_read_lock();529529+ do {530530+ entry = xas_load(&xas);531531+ if (entry == swp_to_radix_entry(swap))532532+ ret = xas_get_order(&xas);533533+ } while (xas_retry(&xas, entry));534534+ rcu_read_unlock();535535+ return ret;524536}525537526538/*···903891 pgoff_t index, void *expected, gfp_t gfp)904892{905893 XA_STATE_ORDER(xas, &mapping->i_pages, index, folio_order(folio));906906- long nr = folio_nr_pages(folio);894894+ unsigned long nr = folio_nr_pages(folio);895895+ swp_entry_t iter, swap;896896+ void *entry;907897908898 VM_BUG_ON_FOLIO(index != round_down(index, nr), folio);909899 VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);···917903918904 gfp &= GFP_RECLAIM_MASK;919905 folio_throttle_swaprate(folio, gfp);906906+ swap = radix_to_swp_entry(expected);920907921908 do {909909+ iter = swap;922910 xas_lock_irq(&xas);923923- if (expected != xas_find_conflict(&xas)) {924924- xas_set_err(&xas, -EEXIST);925925- goto unlock;911911+ xas_for_each_conflict(&xas, entry) {912912+ /*913913+ * The range must either be empty, or filled with914914+ * expected swap entries. Shmem swap entries are never915915+ * partially freed without split of both entry and916916+ * folio, so there shouldn't be any holes.917917+ */918918+ if (!expected || entry != swp_to_radix_entry(iter)) {919919+ xas_set_err(&xas, -EEXIST);920920+ goto unlock;921921+ }922922+ iter.val += 1 << xas_get_order(&xas);926923 }927927- if (expected && xas_find_conflict(&xas)) {924924+ if (expected && iter.val - nr != swap.val) {928925 xas_set_err(&xas, -EEXIST);929926 goto unlock;930927 }···20171992 swp_entry_t entry, int order, gfp_t gfp)20181993{20191994 struct shmem_inode_info *info = SHMEM_I(inode);19951995+ int nr_pages = 1 << order;20201996 struct folio *new;19971997+ gfp_t alloc_gfp;20211998 void *shadow;20222022- int nr_pages;2023199920242000 /*20252001 * We have arrived here because our zones are constrained, so don't20262002 * limit chance of success with further cpuset and node constraints.20272003 */20282004 gfp &= ~GFP_CONSTRAINT_MASK;20292029- if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && order > 0) {20302030- gfp_t huge_gfp = vma_thp_gfp_mask(vma);20052005+ alloc_gfp = gfp;20062006+ if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {20072007+ if (WARN_ON_ONCE(order))20082008+ return ERR_PTR(-EINVAL);20092009+ } else if (order) {20102010+ /*20112011+ * If uffd is active for the vma, we need per-page fault20122012+ * fidelity to maintain the uffd semantics, then fallback20132013+ * to swapin order-0 folio, as well as for zswap case.20142014+ * Any existing sub folio in the swap cache also blocks20152015+ * mTHP swapin.20162016+ */20172017+ if ((vma && unlikely(userfaultfd_armed(vma))) ||20182018+ !zswap_never_enabled() ||20192019+ non_swapcache_batch(entry, nr_pages) != nr_pages)20202020+ goto fallback;2031202120322032- gfp = limit_gfp_mask(huge_gfp, gfp);20222022+ alloc_gfp = limit_gfp_mask(vma_thp_gfp_mask(vma), gfp);20232023+ }20242024+retry:20252025+ new = shmem_alloc_folio(alloc_gfp, order, info, index);20262026+ if (!new) {20272027+ new = ERR_PTR(-ENOMEM);20282028+ goto fallback;20332029 }2034203020352035- new = shmem_alloc_folio(gfp, order, info, index);20362036- if (!new)20372037- return ERR_PTR(-ENOMEM);20382038-20392039- nr_pages = folio_nr_pages(new);20402031 if (mem_cgroup_swapin_charge_folio(new, vma ? vma->vm_mm : NULL,20412041- gfp, entry)) {20322032+ alloc_gfp, entry)) {20422033 folio_put(new);20432043- return ERR_PTR(-ENOMEM);20342034+ new = ERR_PTR(-ENOMEM);20352035+ goto fallback;20442036 }2045203720462038 /*···20722030 */20732031 if (swapcache_prepare(entry, nr_pages)) {20742032 folio_put(new);20752075- return ERR_PTR(-EEXIST);20332033+ new = ERR_PTR(-EEXIST);20342034+ /* Try smaller folio to avoid cache conflict */20352035+ goto fallback;20762036 }2077203720782038 __folio_set_locked(new);···20882044 folio_add_lru(new);20892045 swap_read_folio(new, NULL);20902046 return new;20472047+fallback:20482048+ /* Order 0 swapin failed, nothing to fallback to, abort */20492049+ if (!order)20502050+ return new;20512051+ entry.val += index - round_down(index, nr_pages);20522052+ alloc_gfp = gfp;20532053+ nr_pages = 1;20542054+ order = 0;20552055+ goto retry;20912056}2092205720932058/*···23022249 if (xas_error(&xas))23032250 return xas_error(&xas);2304225123052305- return entry_order;22522252+ return 0;23062253}2307225423082255/*···23192266 struct address_space *mapping = inode->i_mapping;23202267 struct mm_struct *fault_mm = vma ? vma->vm_mm : NULL;23212268 struct shmem_inode_info *info = SHMEM_I(inode);22692269+ swp_entry_t swap, index_entry;23222270 struct swap_info_struct *si;23232271 struct folio *folio = NULL;23242272 bool skip_swapcache = false;23252325- swp_entry_t swap;23262326- int error, nr_pages, order, split_order;22732273+ int error, nr_pages, order;22742274+ pgoff_t offset;2327227523282276 VM_BUG_ON(!*foliop || !xa_is_value(*foliop));23292329- swap = radix_to_swp_entry(*foliop);22772277+ index_entry = radix_to_swp_entry(*foliop);22782278+ swap = index_entry;23302279 *foliop = NULL;2331228023322332- if (is_poisoned_swp_entry(swap))22812281+ if (is_poisoned_swp_entry(index_entry))23332282 return -EIO;2334228323352335- si = get_swap_device(swap);23362336- if (!si) {23372337- if (!shmem_confirm_swap(mapping, index, swap))22842284+ si = get_swap_device(index_entry);22852285+ order = shmem_confirm_swap(mapping, index, index_entry);22862286+ if (unlikely(!si)) {22872287+ if (order < 0)23382288 return -EEXIST;23392289 else23402290 return -EINVAL;23412291 }22922292+ if (unlikely(order < 0)) {22932293+ put_swap_device(si);22942294+ return -EEXIST;22952295+ }22962296+22972297+ /* index may point to the middle of a large entry, get the sub entry */22982298+ if (order) {22992299+ offset = index - round_down(index, 1 << order);23002300+ swap = swp_entry(swp_type(swap), swp_offset(swap) + offset);23012301+ }2342230223432303 /* Look it up and read it in.. */23442304 folio = swap_cache_get_folio(swap, NULL, 0);23452345- order = xa_get_order(&mapping->i_pages, index);23462305 if (!folio) {23472347- int nr_pages = 1 << order;23482348- bool fallback_order0 = false;23492349-23502350- /* Or update major stats only when swapin succeeds?? */23062306+ if (data_race(si->flags & SWP_SYNCHRONOUS_IO)) {23072307+ /* Direct swapin skipping swap cache & readahead */23082308+ folio = shmem_swap_alloc_folio(inode, vma, index,23092309+ index_entry, order, gfp);23102310+ if (IS_ERR(folio)) {23112311+ error = PTR_ERR(folio);23122312+ folio = NULL;23132313+ goto failed;23142314+ }23152315+ skip_swapcache = true;23162316+ } else {23172317+ /* Cached swapin only supports order 0 folio */23182318+ folio = shmem_swapin_cluster(swap, gfp, info, index);23192319+ if (!folio) {23202320+ error = -ENOMEM;23212321+ goto failed;23222322+ }23232323+ }23512324 if (fault_type) {23522325 *fault_type |= VM_FAULT_MAJOR;23532326 count_vm_event(PGMAJFAULT);23542327 count_memcg_event_mm(fault_mm, PGMAJFAULT);23552328 }23292329+ }2356233023312331+ if (order > folio_order(folio)) {23572332 /*23582358- * If uffd is active for the vma, we need per-page fault23592359- * fidelity to maintain the uffd semantics, then fallback23602360- * to swapin order-0 folio, as well as for zswap case.23612361- * Any existing sub folio in the swap cache also blocks23622362- * mTHP swapin.23632363- */23642364- if (order > 0 && ((vma && unlikely(userfaultfd_armed(vma))) ||23652365- !zswap_never_enabled() ||23662366- non_swapcache_batch(swap, nr_pages) != nr_pages))23672367- fallback_order0 = true;23682368-23692369- /* Skip swapcache for synchronous device. */23702370- if (!fallback_order0 && data_race(si->flags & SWP_SYNCHRONOUS_IO)) {23712371- folio = shmem_swap_alloc_folio(inode, vma, index, swap, order, gfp);23722372- if (!IS_ERR(folio)) {23732373- skip_swapcache = true;23742374- goto alloced;23752375- }23762376-23772377- /*23782378- * Fallback to swapin order-0 folio unless the swap entry23792379- * already exists.23802380- */23812381- error = PTR_ERR(folio);23822382- folio = NULL;23832383- if (error == -EEXIST)23842384- goto failed;23852385- }23862386-23872387- /*23882388- * Now swap device can only swap in order 0 folio, then we23892389- * should split the large swap entry stored in the pagecache23902390- * if necessary.23912391- */23922392- split_order = shmem_split_large_entry(inode, index, swap, gfp);23932393- if (split_order < 0) {23942394- error = split_order;23952395- goto failed;23962396- }23972397-23982398- /*23992399- * If the large swap entry has already been split, it is24002400- * necessary to recalculate the new swap entry based on24012401- * the old order alignment.24022402- */24032403- if (split_order > 0) {24042404- pgoff_t offset = index - round_down(index, 1 << split_order);24052405-24062406- swap = swp_entry(swp_type(swap), swp_offset(swap) + offset);24072407- }24082408-24092409- /* Here we actually start the io */24102410- folio = shmem_swapin_cluster(swap, gfp, info, index);24112411- if (!folio) {24122412- error = -ENOMEM;24132413- goto failed;24142414- }24152415- } else if (order != folio_order(folio)) {24162416- /*24172417- * Swap readahead may swap in order 0 folios into swapcache23332333+ * Swapin may get smaller folios due to various reasons:23342334+ * It may fallback to order 0 due to memory pressure or race,23352335+ * swap readahead may swap in order 0 folios into swapcache24182336 * asynchronously, while the shmem mapping can still stores24192337 * large swap entries. In such cases, we should split the24202338 * large swap entry to prevent possible data corruption.24212339 */24222422- split_order = shmem_split_large_entry(inode, index, swap, gfp);24232423- if (split_order < 0) {24242424- folio_put(folio);24252425- folio = NULL;24262426- error = split_order;24272427- goto failed;24282428- }24292429-24302430- /*24312431- * If the large swap entry has already been split, it is24322432- * necessary to recalculate the new swap entry based on24332433- * the old order alignment.24342434- */24352435- if (split_order > 0) {24362436- pgoff_t offset = index - round_down(index, 1 << split_order);24372437-24382438- swap = swp_entry(swp_type(swap), swp_offset(swap) + offset);24392439- }23402340+ error = shmem_split_large_entry(inode, index, index_entry, gfp);23412341+ if (error)23422342+ goto failed_nolock;24402343 }2441234424422442-alloced:24432443- /* We have to do this with folio locked to prevent races */23452345+ /*23462346+ * If the folio is large, round down swap and index by folio size.23472347+ * No matter what race occurs, the swap layer ensures we either get23482348+ * a valid folio that has its swap entry aligned by size, or a23492349+ * temporarily invalid one which we'll abort very soon and retry.23502350+ *23512351+ * shmem_add_to_page_cache ensures the whole range contains expected23522352+ * entries and prevents any corruption, so any race split is fine23532353+ * too, it will succeed as long as the entries are still there.23542354+ */23552355+ nr_pages = folio_nr_pages(folio);23562356+ if (nr_pages > 1) {23572357+ swap.val = round_down(swap.val, nr_pages);23582358+ index = round_down(index, nr_pages);23592359+ }23602360+23612361+ /*23622362+ * We have to do this with the folio locked to prevent races.23632363+ * The shmem_confirm_swap below only checks if the first swap23642364+ * entry matches the folio, that's enough to ensure the folio23652365+ * is not used outside of shmem, as shmem swap entries23662366+ * and swap cache folios are never partially freed.23672367+ */24442368 folio_lock(folio);24452369 if ((!skip_swapcache && !folio_test_swapcache(folio)) ||24462446- folio->swap.val != swap.val ||24472447- !shmem_confirm_swap(mapping, index, swap) ||24482448- xa_get_order(&mapping->i_pages, index) != folio_order(folio)) {23702370+ shmem_confirm_swap(mapping, index, swap) < 0 ||23712371+ folio->swap.val != swap.val) {24492372 error = -EEXIST;24502373 goto unlock;24512374 }···24442415 goto failed;24452416 }2446241724472447- error = shmem_add_to_page_cache(folio, mapping,24482448- round_down(index, nr_pages),24182418+ error = shmem_add_to_page_cache(folio, mapping, index,24492419 swp_to_radix_entry(swap), gfp);24502420 if (error)24512421 goto failed;···24672439 *foliop = folio;24682440 return 0;24692441failed:24702470- if (!shmem_confirm_swap(mapping, index, swap))24422442+ if (shmem_confirm_swap(mapping, index, swap) < 0)24712443 error = -EEXIST;24722444 if (error == -EIO)24732445 shmem_set_folio_swapin_error(inode, index, folio, swap,24742446 skip_swapcache);24752447unlock:24762476- if (skip_swapcache)24772477- swapcache_clear(si, swap, folio_nr_pages(folio));24782478- if (folio) {24482448+ if (folio)24792449 folio_unlock(folio);24502450+failed_nolock:24512451+ if (skip_swapcache)24522452+ swapcache_clear(si, folio->swap, folio_nr_pages(folio));24532453+ if (folio)24802454 folio_put(folio);24812481- }24822455 put_swap_device(si);2483245624842457 return error;···59895960 struct folio *folio;59905961 int error;5991596259925992- error = shmem_get_folio_gfp(inode, index, 0, &folio, SGP_CACHE,59935993- gfp, NULL, NULL);59635963+ error = shmem_get_folio_gfp(inode, index, i_size_read(inode),59645964+ &folio, SGP_CACHE, gfp, NULL, NULL);59945965 if (error)59955966 return ERR_PTR(error);59965967
+2-3
mm/slub.c
···63126312 if (debug_guardpage_minorder())63136313 slub_max_order = 0;6314631463156315- /* Print slub debugging pointers without hashing */63166316- if (__slub_debug_enabled())63176317- no_hash_pointers_enable(NULL);63156315+ /* Inform pointer hashing choice about slub debugging state. */63166316+ hash_pointers_finalize(__slub_debug_enabled());6318631763196318 kmem_cache_node = &boot_kmem_cache_node;63206319 kmem_cache = &boot_kmem_cache;
+2-2
mm/vma.c
···13511351 }1352135213531353 /* Don't bother splitting the VMA if we can't unmap it anyway */13541354- if (!can_modify_vma(vms->vma)) {13541354+ if (vma_is_sealed(vms->vma)) {13551355 error = -EPERM;13561356 goto start_split_failed;13571357 }···13711371 for_each_vma_range(*(vms->vmi), next, vms->end) {13721372 long nrpages;1373137313741374- if (!can_modify_vma(next)) {13741374+ if (vma_is_sealed(next)) {13751375 error = -EPERM;13761376 goto modify_vma_failed;13771377 }
+2-25
mm/vma.h
···559559}560560561561#ifdef CONFIG_64BIT562562-563562static inline bool vma_is_sealed(struct vm_area_struct *vma)564563{565564 return (vma->vm_flags & VM_SEALED);566565}567567-568568-/*569569- * check if a vma is sealed for modification.570570- * return true, if modification is allowed.571571- */572572-static inline bool can_modify_vma(struct vm_area_struct *vma)573573-{574574- if (unlikely(vma_is_sealed(vma)))575575- return false;576576-577577- return true;578578-}579579-580580-bool can_modify_vma_madv(struct vm_area_struct *vma, int behavior);581581-582566#else583583-584584-static inline bool can_modify_vma(struct vm_area_struct *vma)567567+static inline bool vma_is_sealed(struct vm_area_struct *vma)585568{586586- return true;569569+ return false;587570}588588-589589-static inline bool can_modify_vma_madv(struct vm_area_struct *vma, int behavior)590590-{591591- return true;592592-}593593-594571#endif595572596573#if defined(CONFIG_STACK_GROWSUP)
+8
rust/Makefile
···3434obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.o35353636always-$(subst y,$(CONFIG_RUST),$(CONFIG_JUMP_LABEL)) += kernel/generated_arch_static_branch_asm.rs3737+ifndef CONFIG_UML3838+always-$(subst y,$(CONFIG_RUST),$(CONFIG_BUG)) += kernel/generated_arch_warn_asm.rs kernel/generated_arch_reachable_asm.rs3939+endif37403841# Avoids running `$(RUSTC)` when it may not be available.3942ifdef CONFIG_RUST···543540544541ifdef CONFIG_JUMP_LABEL545542$(obj)/kernel.o: $(obj)/kernel/generated_arch_static_branch_asm.rs543543+endif544544+ifndef CONFIG_UML545545+ifdef CONFIG_BUG546546+$(obj)/kernel.o: $(obj)/kernel/generated_arch_warn_asm.rs $(obj)/kernel/generated_arch_reachable_asm.rs547547+endif546548endif547549548550endif # CONFIG_RUST
···82828383 // SAFETY: Returns either NULL or a pointer to a memory allocation that satisfies or8484 // exceeds the given size and alignment requirements.8585- let dst = unsafe { libc_aligned_alloc(layout.align(), layout.size()) } as *mut u8;8585+ let dst = unsafe { libc_aligned_alloc(layout.align(), layout.size()) }.cast::<u8>();8686 let dst = NonNull::new(dst).ok_or(AllocError)?;87878888 if flags.contains(__GFP_ZERO) {
+80-18
rust/kernel/alloc/kbox.rs
···66use super::allocator::{KVmalloc, Kmalloc, Vmalloc};77use super::{AllocError, Allocator, Flags};88use core::alloc::Layout;99+use core::borrow::{Borrow, BorrowMut};910use core::fmt;1011use core::marker::PhantomData;1112use core::mem::ManuallyDrop;···1615use core::ptr::NonNull;1716use core::result::Result;18171818+use crate::ffi::c_void;1919use crate::init::InPlaceInit;2020use crate::types::ForeignOwnable;2121use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption};···400398 }401399}402400403403-// SAFETY: The `into_foreign` function returns a pointer that is well-aligned.401401+// SAFETY: The pointer returned by `into_foreign` comes from a well aligned402402+// pointer to `T`.404403unsafe impl<T: 'static, A> ForeignOwnable for Box<T, A>405404where406405 A: Allocator,407406{408408- type PointedTo = T;407407+ const FOREIGN_ALIGN: usize = core::mem::align_of::<T>();409408 type Borrowed<'a> = &'a T;410409 type BorrowedMut<'a> = &'a mut T;411410412412- fn into_foreign(self) -> *mut Self::PointedTo {413413- Box::into_raw(self)411411+ fn into_foreign(self) -> *mut c_void {412412+ Box::into_raw(self).cast()414413 }415414416416- unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self {415415+ unsafe fn from_foreign(ptr: *mut c_void) -> Self {417416 // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous418417 // call to `Self::into_foreign`.419419- unsafe { Box::from_raw(ptr) }418418+ unsafe { Box::from_raw(ptr.cast()) }420419 }421420422422- unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> &'a T {421421+ unsafe fn borrow<'a>(ptr: *mut c_void) -> &'a T {423422 // SAFETY: The safety requirements of this method ensure that the object remains alive and424423 // immutable for the duration of 'a.425425- unsafe { &*ptr }424424+ unsafe { &*ptr.cast() }426425 }427426428428- unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> &'a mut T {427427+ unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> &'a mut T {428428+ let ptr = ptr.cast();429429 // SAFETY: The safety requirements of this method ensure that the pointer is valid and that430430 // nothing else will access the value for the duration of 'a.431431 unsafe { &mut *ptr }432432 }433433}434434435435-// SAFETY: The `into_foreign` function returns a pointer that is well-aligned.435435+// SAFETY: The pointer returned by `into_foreign` comes from a well aligned436436+// pointer to `T`.436437unsafe impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>437438where438439 A: Allocator,439440{440440- type PointedTo = T;441441+ const FOREIGN_ALIGN: usize = core::mem::align_of::<T>();441442 type Borrowed<'a> = Pin<&'a T>;442443 type BorrowedMut<'a> = Pin<&'a mut T>;443444444444- fn into_foreign(self) -> *mut Self::PointedTo {445445+ fn into_foreign(self) -> *mut c_void {445446 // SAFETY: We are still treating the box as pinned.446446- Box::into_raw(unsafe { Pin::into_inner_unchecked(self) })447447+ Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }).cast()447448 }448449449449- unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self {450450+ unsafe fn from_foreign(ptr: *mut c_void) -> Self {450451 // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous451452 // call to `Self::into_foreign`.452452- unsafe { Pin::new_unchecked(Box::from_raw(ptr)) }453453+ unsafe { Pin::new_unchecked(Box::from_raw(ptr.cast())) }453454 }454455455455- unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> Pin<&'a T> {456456+ unsafe fn borrow<'a>(ptr: *mut c_void) -> Pin<&'a T> {456457 // SAFETY: The safety requirements for this function ensure that the object is still alive,457458 // so it is safe to dereference the raw pointer.458459 // The safety requirements of `from_foreign` also ensure that the object remains alive for459460 // the lifetime of the returned value.460460- let r = unsafe { &*ptr };461461+ let r = unsafe { &*ptr.cast() };461462462463 // SAFETY: This pointer originates from a `Pin<Box<T>>`.463464 unsafe { Pin::new_unchecked(r) }464465 }465466466466- unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> Pin<&'a mut T> {467467+ unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> Pin<&'a mut T> {468468+ let ptr = ptr.cast();467469 // SAFETY: The safety requirements for this function ensure that the object is still alive,468470 // so it is safe to dereference the raw pointer.469471 // The safety requirements of `from_foreign` also ensure that the object remains alive for···502496 // SAFETY: `self.0` is always properly aligned, dereferenceable and points to an initialized503497 // instance of `T`.504498 unsafe { self.0.as_mut() }499499+ }500500+}501501+502502+/// # Examples503503+///504504+/// ```505505+/// # use core::borrow::Borrow;506506+/// # use kernel::alloc::KBox;507507+/// struct Foo<B: Borrow<u32>>(B);508508+///509509+/// // Owned instance.510510+/// let owned = Foo(1);511511+///512512+/// // Owned instance using `KBox`.513513+/// let owned_kbox = Foo(KBox::new(1, GFP_KERNEL)?);514514+///515515+/// let i = 1;516516+/// // Borrowed from `i`.517517+/// let borrowed = Foo(&i);518518+/// # Ok::<(), Error>(())519519+/// ```520520+impl<T, A> Borrow<T> for Box<T, A>521521+where522522+ T: ?Sized,523523+ A: Allocator,524524+{525525+ fn borrow(&self) -> &T {526526+ self.deref()527527+ }528528+}529529+530530+/// # Examples531531+///532532+/// ```533533+/// # use core::borrow::BorrowMut;534534+/// # use kernel::alloc::KBox;535535+/// struct Foo<B: BorrowMut<u32>>(B);536536+///537537+/// // Owned instance.538538+/// let owned = Foo(1);539539+///540540+/// // Owned instance using `KBox`.541541+/// let owned_kbox = Foo(KBox::new(1, GFP_KERNEL)?);542542+///543543+/// let mut i = 1;544544+/// // Borrowed from `i`.545545+/// let borrowed = Foo(&mut i);546546+/// # Ok::<(), Error>(())547547+/// ```548548+impl<T, A> BorrowMut<T> for Box<T, A>549549+where550550+ T: ?Sized,551551+ A: Allocator,552552+{553553+ fn borrow_mut(&mut self) -> &mut T {554554+ self.deref_mut()505555 }506556}507557
+56-3
rust/kernel/alloc/kvec.rs
···88 AllocError, Allocator, Box, Flags,99};1010use core::{1111+ borrow::{Borrow, BorrowMut},1112 fmt,1213 marker::PhantomData,1314 mem::{ManuallyDrop, MaybeUninit},···289288 // - `self.len` is smaller than `self.capacity` by the type invariant and hence, the290289 // resulting pointer is guaranteed to be part of the same allocated object.291290 // - `self.len` can not overflow `isize`.292292- let ptr = unsafe { self.as_mut_ptr().add(self.len) } as *mut MaybeUninit<T>;291291+ let ptr = unsafe { self.as_mut_ptr().add(self.len) }.cast::<MaybeUninit<T>>();293292294293 // SAFETY: The memory between `self.len` and `self.capacity` is guaranteed to be allocated295294 // and valid, but uninitialized.···848847 // - `ptr` points to memory with at least a size of `size_of::<T>() * len`,849848 // - all elements within `b` are initialized values of `T`,850849 // - `len` does not exceed `isize::MAX`.851851- unsafe { Vec::from_raw_parts(ptr as _, len, len) }850850+ unsafe { Vec::from_raw_parts(ptr.cast(), len, len) }852851 }853852}854853855855-impl<T> Default for KVec<T> {854854+impl<T, A: Allocator> Default for Vec<T, A> {856855 #[inline]857856 fn default() -> Self {858857 Self::new()···888887 // SAFETY: The memory behind `self.as_ptr()` is guaranteed to contain `self.len`889888 // initialized elements of type `T`.890889 unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }890890+ }891891+}892892+893893+/// # Examples894894+///895895+/// ```896896+/// # use core::borrow::Borrow;897897+/// struct Foo<B: Borrow<[u32]>>(B);898898+///899899+/// // Owned array.900900+/// let owned_array = Foo([1, 2, 3]);901901+///902902+/// // Owned vector.903903+/// let owned_vec = Foo(KVec::from_elem(0, 3, GFP_KERNEL)?);904904+///905905+/// let arr = [1, 2, 3];906906+/// // Borrowed slice from `arr`.907907+/// let borrowed_slice = Foo(&arr[..]);908908+/// # Ok::<(), Error>(())909909+/// ```910910+impl<T, A> Borrow<[T]> for Vec<T, A>911911+where912912+ A: Allocator,913913+{914914+ fn borrow(&self) -> &[T] {915915+ self.as_slice()916916+ }917917+}918918+919919+/// # Examples920920+///921921+/// ```922922+/// # use core::borrow::BorrowMut;923923+/// struct Foo<B: BorrowMut<[u32]>>(B);924924+///925925+/// // Owned array.926926+/// let owned_array = Foo([1, 2, 3]);927927+///928928+/// // Owned vector.929929+/// let owned_vec = Foo(KVec::from_elem(0, 3, GFP_KERNEL)?);930930+///931931+/// let mut arr = [1, 2, 3];932932+/// // Borrowed slice from `arr`.933933+/// let borrowed_slice = Foo(&mut arr[..]);934934+/// # Ok::<(), Error>(())935935+/// ```936936+impl<T, A> BorrowMut<[T]> for Vec<T, A>937937+where938938+ A: Allocator,939939+{940940+ fn borrow_mut(&mut self) -> &mut [T] {941941+ self.as_mut_slice()891942 }892943}893944
+203
rust/kernel/bits.rs
···11+// SPDX-License-Identifier: GPL-2.022+33+//! Bit manipulation macros.44+//!55+//! C header: [`include/linux/bits.h`](srctree/include/linux/bits.h)66+77+use crate::prelude::*;88+use core::ops::RangeInclusive;99+use macros::paste;1010+1111+macro_rules! impl_bit_fn {1212+ (1313+ $ty:ty1414+ ) => {1515+ paste! {1616+ /// Computes `1 << n` if `n` is in bounds, i.e.: if `n` is smaller than1717+ /// the maximum number of bits supported by the type.1818+ ///1919+ /// Returns [`None`] otherwise.2020+ #[inline]2121+ pub fn [<checked_bit_ $ty>](n: u32) -> Option<$ty> {2222+ (1 as $ty).checked_shl(n)2323+ }2424+2525+ /// Computes `1 << n` by performing a compile-time assertion that `n` is2626+ /// in bounds.2727+ ///2828+ /// This version is the default and should be used if `n` is known at2929+ /// compile time.3030+ #[inline]3131+ pub const fn [<bit_ $ty>](n: u32) -> $ty {3232+ build_assert!(n < <$ty>::BITS);3333+ (1 as $ty) << n3434+ }3535+ }3636+ };3737+}3838+3939+impl_bit_fn!(u64);4040+impl_bit_fn!(u32);4141+impl_bit_fn!(u16);4242+impl_bit_fn!(u8);4343+4444+macro_rules! impl_genmask_fn {4545+ (4646+ $ty:ty,4747+ $(#[$genmask_checked_ex:meta])*,4848+ $(#[$genmask_ex:meta])*4949+ ) => {5050+ paste! {5151+ /// Creates a contiguous bitmask for the given range by validating5252+ /// the range at runtime.5353+ ///5454+ /// Returns [`None`] if the range is invalid, i.e.: if the start is5555+ /// greater than the end or if the range is outside of the5656+ /// representable range for the type.5757+ $(#[$genmask_checked_ex])*5858+ #[inline]5959+ pub fn [<genmask_checked_ $ty>](range: RangeInclusive<u32>) -> Option<$ty> {6060+ let start = *range.start();6161+ let end = *range.end();6262+6363+ if start > end {6464+ return None;6565+ }6666+6767+ let high = [<checked_bit_ $ty>](end)?;6868+ let low = [<checked_bit_ $ty>](start)?;6969+ Some((high | (high - 1)) & !(low - 1))7070+ }7171+7272+ /// Creates a compile-time contiguous bitmask for the given range by7373+ /// performing a compile-time assertion that the range is valid.7474+ ///7575+ /// This version is the default and should be used if the range is known7676+ /// at compile time.7777+ $(#[$genmask_ex])*7878+ #[inline]7979+ pub const fn [<genmask_ $ty>](range: RangeInclusive<u32>) -> $ty {8080+ let start = *range.start();8181+ let end = *range.end();8282+8383+ build_assert!(start <= end);8484+8585+ let high = [<bit_ $ty>](end);8686+ let low = [<bit_ $ty>](start);8787+ (high | (high - 1)) & !(low - 1)8888+ }8989+ }9090+ };9191+}9292+9393+impl_genmask_fn!(9494+ u64,9595+ /// # Examples9696+ ///9797+ /// ```9898+ /// # #![expect(clippy::reversed_empty_ranges)]9999+ /// # use kernel::bits::genmask_checked_u64;100100+ /// assert_eq!(genmask_checked_u64(0..=0), Some(0b1));101101+ /// assert_eq!(genmask_checked_u64(0..=63), Some(u64::MAX));102102+ /// assert_eq!(genmask_checked_u64(21..=39), Some(0x0000_00ff_ffe0_0000));103103+ ///104104+ /// // `80` is out of the supported bit range.105105+ /// assert_eq!(genmask_checked_u64(21..=80), None);106106+ ///107107+ /// // Invalid range where the start is bigger than the end.108108+ /// assert_eq!(genmask_checked_u64(15..=8), None);109109+ /// ```110110+ ,111111+ /// # Examples112112+ ///113113+ /// ```114114+ /// # use kernel::bits::genmask_u64;115115+ /// assert_eq!(genmask_u64(21..=39), 0x0000_00ff_ffe0_0000);116116+ /// assert_eq!(genmask_u64(0..=0), 0b1);117117+ /// assert_eq!(genmask_u64(0..=63), u64::MAX);118118+ /// ```119119+);120120+121121+impl_genmask_fn!(122122+ u32,123123+ /// # Examples124124+ ///125125+ /// ```126126+ /// # #![expect(clippy::reversed_empty_ranges)]127127+ /// # use kernel::bits::genmask_checked_u32;128128+ /// assert_eq!(genmask_checked_u32(0..=0), Some(0b1));129129+ /// assert_eq!(genmask_checked_u32(0..=31), Some(u32::MAX));130130+ /// assert_eq!(genmask_checked_u32(21..=31), Some(0xffe0_0000));131131+ ///132132+ /// // `40` is out of the supported bit range.133133+ /// assert_eq!(genmask_checked_u32(21..=40), None);134134+ ///135135+ /// // Invalid range where the start is bigger than the end.136136+ /// assert_eq!(genmask_checked_u32(15..=8), None);137137+ /// ```138138+ ,139139+ /// # Examples140140+ ///141141+ /// ```142142+ /// # use kernel::bits::genmask_u32;143143+ /// assert_eq!(genmask_u32(21..=31), 0xffe0_0000);144144+ /// assert_eq!(genmask_u32(0..=0), 0b1);145145+ /// assert_eq!(genmask_u32(0..=31), u32::MAX);146146+ /// ```147147+);148148+149149+impl_genmask_fn!(150150+ u16,151151+ /// # Examples152152+ ///153153+ /// ```154154+ /// # #![expect(clippy::reversed_empty_ranges)]155155+ /// # use kernel::bits::genmask_checked_u16;156156+ /// assert_eq!(genmask_checked_u16(0..=0), Some(0b1));157157+ /// assert_eq!(genmask_checked_u16(0..=15), Some(u16::MAX));158158+ /// assert_eq!(genmask_checked_u16(6..=15), Some(0xffc0));159159+ ///160160+ /// // `20` is out of the supported bit range.161161+ /// assert_eq!(genmask_checked_u16(6..=20), None);162162+ ///163163+ /// // Invalid range where the start is bigger than the end.164164+ /// assert_eq!(genmask_checked_u16(10..=5), None);165165+ /// ```166166+ ,167167+ /// # Examples168168+ ///169169+ /// ```170170+ /// # use kernel::bits::genmask_u16;171171+ /// assert_eq!(genmask_u16(6..=15), 0xffc0);172172+ /// assert_eq!(genmask_u16(0..=0), 0b1);173173+ /// assert_eq!(genmask_u16(0..=15), u16::MAX);174174+ /// ```175175+);176176+177177+impl_genmask_fn!(178178+ u8,179179+ /// # Examples180180+ ///181181+ /// ```182182+ /// # #![expect(clippy::reversed_empty_ranges)]183183+ /// # use kernel::bits::genmask_checked_u8;184184+ /// assert_eq!(genmask_checked_u8(0..=0), Some(0b1));185185+ /// assert_eq!(genmask_checked_u8(0..=7), Some(u8::MAX));186186+ /// assert_eq!(genmask_checked_u8(6..=7), Some(0xc0));187187+ ///188188+ /// // `10` is out of the supported bit range.189189+ /// assert_eq!(genmask_checked_u8(6..=10), None);190190+ ///191191+ /// // Invalid range where the start is bigger than the end.192192+ /// assert_eq!(genmask_checked_u8(5..=2), None);193193+ /// ```194194+ ,195195+ /// # Examples196196+ ///197197+ /// ```198198+ /// # use kernel::bits::genmask_u8;199199+ /// assert_eq!(genmask_u8(6..=7), 0xc0);200200+ /// assert_eq!(genmask_u8(0..=0), 0b1);201201+ /// assert_eq!(genmask_u8(0..=7), u8::MAX);202202+ /// ```203203+);
···101101 if let Err(e) = ret {102102 e.to_blk_status()103103 } else {104104- bindings::BLK_STS_OK as _104104+ bindings::BLK_STS_OK as bindings::blk_status_t105105 }106106 }107107
+8-3
rust/kernel/block/mq/request.rs
···6969 // INVARIANT: By the safety requirements of this function, invariants are upheld.7070 // SAFETY: By the safety requirement of this function, we own a7171 // reference count that we can pass to `ARef`.7272- unsafe { ARef::from_raw(NonNull::new_unchecked(ptr as *const Self as *mut Self)) }7272+ unsafe { ARef::from_raw(NonNull::new_unchecked(ptr.cast())) }7373 }74747575 /// Notify the block layer that a request is going to be processed now.···125125 // success of the call to `try_set_end` guarantees that there are no126126 // `ARef`s pointing to this request. Therefore it is safe to hand it127127 // back to the block layer.128128- unsafe { bindings::blk_mq_end_request(request_ptr, bindings::BLK_STS_OK as _) };128128+ unsafe {129129+ bindings::blk_mq_end_request(130130+ request_ptr,131131+ bindings::BLK_STS_OK as bindings::blk_status_t,132132+ )133133+ };129134130135 Ok(())131136 }···160155 // the private data associated with this request is initialized and161156 // valid. The existence of `&self` guarantees that the private data is162157 // valid as a shared reference.163163- unsafe { Self::wrapper_ptr(self as *const Self as *mut Self).as_ref() }158158+ unsafe { Self::wrapper_ptr(core::ptr::from_ref(self).cast_mut()).as_ref() }164159 }165160}166161
+126
rust/kernel/bug.rs
···11+// SPDX-License-Identifier: GPL-2.022+33+// Copyright (C) 2024, 2025 FUJITA Tomonori <fujita.tomonori@gmail.com>44+55+//! Support for BUG and WARN functionality.66+//!77+//! C header: [`include/asm-generic/bug.h`](srctree/include/asm-generic/bug.h)88+99+#[macro_export]1010+#[doc(hidden)]1111+#[cfg(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH), not(CONFIG_ARM)))]1212+#[cfg(CONFIG_DEBUG_BUGVERBOSE)]1313+macro_rules! warn_flags {1414+ ($flags:expr) => {1515+ const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;1616+ const _FILE: &[u8] = file!().as_bytes();1717+ // Plus one for null-terminator.1818+ static FILE: [u8; _FILE.len() + 1] = {1919+ let mut bytes = [0; _FILE.len() + 1];2020+ let mut i = 0;2121+ while i < _FILE.len() {2222+ bytes[i] = _FILE[i];2323+ i += 1;2424+ }2525+ bytes2626+ };2727+2828+ // SAFETY:2929+ // - `file`, `line`, `flags`, and `size` are all compile-time constants or3030+ // symbols, preventing any invalid memory access.3131+ // - The asm block has no side effects and does not modify any registers3232+ // or memory. It is purely for embedding metadata into the ELF section.3333+ unsafe {3434+ $crate::asm!(3535+ concat!(3636+ "/* {size} */",3737+ include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),3838+ include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));3939+ file = sym FILE,4040+ line = const line!(),4141+ flags = const FLAGS,4242+ size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),4343+ );4444+ }4545+ }4646+}4747+4848+#[macro_export]4949+#[doc(hidden)]5050+#[cfg(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH), not(CONFIG_ARM)))]5151+#[cfg(not(CONFIG_DEBUG_BUGVERBOSE))]5252+macro_rules! warn_flags {5353+ ($flags:expr) => {5454+ const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;5555+5656+ // SAFETY:5757+ // - `flags` and `size` are all compile-time constants, preventing5858+ // any invalid memory access.5959+ // - The asm block has no side effects and does not modify any registers6060+ // or memory. It is purely for embedding metadata into the ELF section.6161+ unsafe {6262+ $crate::asm!(6363+ concat!(6464+ "/* {size} */",6565+ include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),6666+ include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));6767+ flags = const FLAGS,6868+ size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),6969+ );7070+ }7171+ }7272+}7373+7474+#[macro_export]7575+#[doc(hidden)]7676+#[cfg(all(CONFIG_BUG, CONFIG_UML))]7777+macro_rules! warn_flags {7878+ ($flags:expr) => {7979+ // SAFETY: It is always safe to call `warn_slowpath_fmt()`8080+ // with a valid null-terminated string.8181+ unsafe {8282+ $crate::bindings::warn_slowpath_fmt(8383+ $crate::c_str!(::core::file!()).as_char_ptr(),8484+ line!() as $crate::ffi::c_int,8585+ $flags as $crate::ffi::c_uint,8686+ ::core::ptr::null(),8787+ );8888+ }8989+ };9090+}9191+9292+#[macro_export]9393+#[doc(hidden)]9494+#[cfg(all(CONFIG_BUG, any(CONFIG_LOONGARCH, CONFIG_ARM)))]9595+macro_rules! warn_flags {9696+ ($flags:expr) => {9797+ // SAFETY: It is always safe to call `WARN_ON()`.9898+ unsafe { $crate::bindings::WARN_ON(true) }9999+ };100100+}101101+102102+#[macro_export]103103+#[doc(hidden)]104104+#[cfg(not(CONFIG_BUG))]105105+macro_rules! warn_flags {106106+ ($flags:expr) => {};107107+}108108+109109+#[doc(hidden)]110110+pub const fn bugflag_taint(value: u32) -> u32 {111111+ value << 8112112+}113113+114114+/// Report a warning if `cond` is true and return the condition's evaluation result.115115+#[macro_export]116116+macro_rules! warn_on {117117+ ($cond:expr) => {{118118+ let cond = $cond;119119+ if cond {120120+ const WARN_ON_FLAGS: u32 = $crate::bug::bugflag_taint($crate::bindings::TAINT_WARN);121121+122122+ $crate::warn_flags!(WARN_ON_FLAGS);123123+ }124124+ cond125125+ }};126126+}
+3-3
rust/kernel/clk.rs
···1212///1313/// Represents a frequency in hertz, wrapping a [`c_ulong`] value.1414///1515-/// ## Examples1515+/// # Examples1616///1717/// ```1818/// use kernel::clk::Hertz;···9999 /// Instances of this type are reference-counted. Calling [`Clk::get`] ensures that the100100 /// allocation remains valid for the lifetime of the [`Clk`].101101 ///102102- /// ## Examples102102+ /// # Examples103103 ///104104 /// The following example demonstrates how to obtain and configure a clock for a device.105105 ///···266266 /// Instances of this type are reference-counted. Calling [`OptionalClk::get`] ensures that the267267 /// allocation remains valid for the lifetime of the [`OptionalClk`].268268 ///269269- /// ## Examples269269+ /// # Examples270270 ///271271 /// The following example demonstrates how to obtain and configure an optional clock for a272272 /// device. The code functions correctly whether or not the clock is available.
+11-19
rust/kernel/configfs.rs
···1717//!1818//! C header: [`include/linux/configfs.h`](srctree/include/linux/configfs.h)1919//!2020-//! # Example2020+//! # Examples2121//!2222//! ```ignore2323//! use kernel::alloc::flags;···151151 data: impl PinInit<Data, Error>,152152 ) -> impl PinInit<Self, Error> {153153 try_pin_init!(Self {154154- subsystem <- pin_init::zeroed().chain(154154+ subsystem <- pin_init::init_zeroed().chain(155155 |place: &mut Opaque<bindings::configfs_subsystem>| {156156 // SAFETY: We initialized the required fields of `place.group` above.157157 unsafe {···261261 data: impl PinInit<Data, Error>,262262 ) -> impl PinInit<Self, Error> {263263 try_pin_init!(Self {264264- group <- pin_init::zeroed().chain(|v: &mut Opaque<bindings::config_group>| {264264+ group <- pin_init::init_zeroed().chain(|v: &mut Opaque<bindings::config_group>| {265265 let place = v.get();266266 let name = name.as_bytes_with_nul().as_ptr();267267 // SAFETY: It is safe to initialize a group once it has been zeroed.···279279// within the `group` field.280280unsafe impl<Data> HasGroup<Data> for Group<Data> {281281 unsafe fn group(this: *const Self) -> *const bindings::config_group {282282- Opaque::raw_get(282282+ Opaque::cast_into(283283 // SAFETY: By impl and function safety requirements this field284284 // projection is within bounds of the allocation.285285 unsafe { &raw const (*this).group },···426426 };427427428428 const fn vtable_ptr() -> *const bindings::configfs_group_operations {429429- &Self::VTABLE as *const bindings::configfs_group_operations429429+ &Self::VTABLE430430 }431431}432432···464464 };465465466466 const fn vtable_ptr() -> *const bindings::configfs_item_operations {467467- &Self::VTABLE as *const bindings::configfs_item_operations467467+ &Self::VTABLE468468 }469469}470470···476476 };477477478478 const fn vtable_ptr() -> *const bindings::configfs_item_operations {479479- &Self::VTABLE as *const bindings::configfs_item_operations479479+ &Self::VTABLE480480 }481481}482482···561561 let data: &Data = unsafe { get_group_data(c_group) };562562563563 // SAFETY: By function safety requirements, `page` is writable for `PAGE_SIZE`.564564- let ret = O::show(data, unsafe { &mut *(page as *mut [u8; PAGE_SIZE]) });564564+ let ret = O::show(data, unsafe { &mut *(page.cast::<[u8; PAGE_SIZE]>()) });565565566566 match ret {567567 Ok(size) => size as isize,···717717718718 // SAFETY: By function safety requirements, we have exclusive access to719719 // `self` and the reference created below will be exclusive.720720- unsafe {721721- (&mut *self.0.get())[I] = (attribute as *const Attribute<ID, O, Data>)722722- .cast_mut()723723- .cast()724724- };720720+ unsafe { (&mut *self.0.get())[I] = core::ptr::from_ref(attribute).cast_mut().cast() };725721 }726722}727723···757761 ct_owner: owner.as_ptr(),758762 ct_group_ops: GroupOperationsVTable::<Data, Child>::vtable_ptr().cast_mut(),759763 ct_item_ops: ItemOperationsVTable::<$tpe, Data>::vtable_ptr().cast_mut(),760760- ct_attrs: (attributes as *const AttributeList<N, Data>)761761- .cast_mut()762762- .cast(),764764+ ct_attrs: core::ptr::from_ref(attributes).cast_mut().cast(),763765 ct_bin_attrs: core::ptr::null_mut(),764766 }),765767 _p: PhantomData,···774780 ct_owner: owner.as_ptr(),775781 ct_group_ops: core::ptr::null_mut(),776782 ct_item_ops: ItemOperationsVTable::<$tpe, Data>::vtable_ptr().cast_mut(),777777- ct_attrs: (attributes as *const AttributeList<N, Data>)778778- .cast_mut()779779- .cast(),783783+ ct_attrs: core::ptr::from_ref(attributes).cast_mut().cast(),780784 ct_bin_attrs: core::ptr::null_mut(),781785 }),782786 _p: PhantomData,
+5-5
rust/kernel/cpufreq.rs
···202202/// The callers must ensure that the `struct cpufreq_frequency_table` is valid for access and203203/// remains valid for the lifetime of the returned reference.204204///205205-/// ## Examples205205+/// # Examples206206///207207/// The following example demonstrates how to read a frequency value from [`Table`].208208///···318318///319319/// This is used by the CPU frequency drivers to build a frequency table dynamically.320320///321321-/// ## Examples321321+/// # Examples322322///323323/// The following example demonstrates how to create a CPU frequency table.324324///···395395/// The callers must ensure that the `struct cpufreq_policy` is valid for access and remains valid396396/// for the lifetime of the returned reference.397397///398398-/// ## Examples398398+/// # Examples399399///400400/// The following example demonstrates how to create a CPU frequency table.401401///···649649 fn set_data<T: ForeignOwnable>(&mut self, data: T) -> Result {650650 if self.as_ref().driver_data.is_null() {651651 // Transfer the ownership of the data to the foreign interface.652652- self.as_mut_ref().driver_data = <T as ForeignOwnable>::into_foreign(data) as _;652652+ self.as_mut_ref().driver_data = <T as ForeignOwnable>::into_foreign(data).cast();653653 Ok(())654654 } else {655655 Err(EBUSY)···834834835835/// CPU frequency driver Registration.836836///837837-/// ## Examples837837+/// # Examples838838///839839/// The following example demonstrates how to register a cpufreq driver.840840///
+2-2
rust/kernel/cpumask.rs
···2727/// The callers must ensure that the `struct cpumask` is valid for access and2828/// remains valid for the lifetime of the returned reference.2929///3030-/// ## Examples3030+/// # Examples3131///3232/// The following example demonstrates how to update a [`Cpumask`].3333///···172172/// The callers must ensure that the `struct cpumask_var_t` is valid for access and remains valid173173/// for the lifetime of [`CpumaskVar`].174174///175175-/// ## Examples175175+/// # Examples176176///177177/// The following example demonstrates how to create and update a [`CpumaskVar`].178178///
+2-2
rust/kernel/device.rs
···262262 #[cfg(CONFIG_PRINTK)]263263 unsafe {264264 bindings::_dev_printk(265265- klevel as *const _ as *const crate::ffi::c_char,265265+ klevel.as_ptr().cast::<crate::ffi::c_char>(),266266 self.as_raw(),267267 c_str!("%pA").as_char_ptr(),268268- &msg as *const _ as *const crate::ffi::c_void,268268+ core::ptr::from_ref(&msg).cast::<crate::ffi::c_void>(),269269 )270270 };271271 }
+2-2
rust/kernel/device_id.rs
···100100 unsafe {101101 raw_ids[i]102102 .as_mut_ptr()103103- .byte_offset(data_offset as _)103103+ .byte_add(data_offset)104104 .cast::<usize>()105105 .write(i);106106 }···177177 fn as_ptr(&self) -> *const T::RawType {178178 // This cannot be `self.ids.as_ptr()`, as the return pointer must have correct provenance179179 // to access the sentinel.180180- (self as *const Self).cast()180180+ core::ptr::from_ref(self).cast()181181 }182182183183 fn id(&self, index: usize) -> &T::RawType {
+5-5
rust/kernel/devres.rs
···4949/// [`Devres`] users should make sure to simply free the corresponding backing resource in `T`'s5050/// [`Drop`] implementation.5151///5252-/// # Example5252+/// # Examples5353///5454/// ```no_run5555/// # use kernel::{bindings, device::{Bound, Device}, devres::Devres, io::{Io, IoRaw}};···6666/// unsafe fn new(paddr: usize) -> Result<Self>{6767/// // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is6868/// // valid for `ioremap`.6969-/// let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };6969+/// let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };7070/// if addr.is_null() {7171/// return Err(ENOMEM);7272/// }7373///7474-/// Ok(IoMem(IoRaw::new(addr as _, SIZE)?))7474+/// Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))7575/// }7676/// }7777///7878/// impl<const SIZE: usize> Drop for IoMem<SIZE> {7979/// fn drop(&mut self) {8080/// // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.8181-/// unsafe { bindings::iounmap(self.0.addr() as _); };8181+/// unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };8282/// }8383/// }8484///···219219 /// An error is returned if `dev` does not match the same [`Device`] this [`Devres`] instance220220 /// has been created with.221221 ///222222- /// # Example222222+ /// # Examples223223 ///224224 /// ```no_run225225 /// # #![cfg(CONFIG_PCI)]
+5-5
rust/kernel/dma.rs
···180180impl Attrs {181181 /// Get the raw representation of this attribute.182182 pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {183183- self.0 as _183183+ self.0 as crate::ffi::c_ulong184184 }185185186186 /// Check whether `flags` is contained in `self`.···333333 dev: dev.into(),334334 dma_handle,335335 count,336336- cpu_addr: ret as *mut T,336336+ cpu_addr: ret.cast::<T>(),337337 dma_attrs,338338 })339339 }···436436 /// slice is live.437437 /// * Callers must ensure that this call does not race with a read or write to the same region438438 /// while the returned slice is live.439439- pub unsafe fn as_slice_mut(&self, offset: usize, count: usize) -> Result<&mut [T]> {439439+ pub unsafe fn as_slice_mut(&mut self, offset: usize, count: usize) -> Result<&mut [T]> {440440 self.validate_range(offset, count)?;441441 // SAFETY:442442 // - The pointer is valid due to type invariant on `CoherentAllocation`,···468468 /// unsafe { alloc.write(buf, 0)?; }469469 /// # Ok::<(), Error>(()) }470470 /// ```471471- pub unsafe fn write(&self, src: &[T], offset: usize) -> Result {471471+ pub unsafe fn write(&mut self, src: &[T], offset: usize) -> Result {472472 self.validate_range(offset, src.len())?;473473 // SAFETY:474474 // - The pointer is valid due to type invariant on `CoherentAllocation`···556556 bindings::dma_free_attrs(557557 self.dev.as_raw(),558558 size,559559- self.cpu_addr as _,559559+ self.cpu_addr.cast(),560560 self.dma_handle,561561 self.dma_attrs.as_raw(),562562 )
+4-6
rust/kernel/drm/device.rs
···8383 major: T::INFO.major,8484 minor: T::INFO.minor,8585 patchlevel: T::INFO.patchlevel,8686- name: T::INFO.name.as_char_ptr() as *mut _,8787- desc: T::INFO.desc.as_char_ptr() as *mut _,8686+ name: T::INFO.name.as_char_ptr().cast_mut(),8787+ desc: T::INFO.desc.as_char_ptr().cast_mut(),88888989 driver_features: drm::driver::FEAT_GEM,9090 ioctls: T::IOCTLS.as_ptr(),9191 num_ioctls: T::IOCTLS.len() as i32,9292- fops: &Self::GEM_FOPS as _,9292+ fops: &Self::GEM_FOPS,9393 };94949595 const GEM_FOPS: bindings::file_operations = drm::gem::create_fops();···135135 ///136136 /// `ptr` must be a valid pointer to a `struct device` embedded in `Self`.137137 unsafe fn from_drm_device(ptr: *const bindings::drm_device) -> *mut Self {138138- let ptr: *const Opaque<bindings::drm_device> = ptr.cast();139139-140138 // SAFETY: By the safety requirements of this function `ptr` is a valid pointer to a141139 // `struct drm_device` embedded in `Self`.142142- unsafe { crate::container_of!(ptr, Self, dev) }.cast_mut()140140+ unsafe { crate::container_of!(Opaque::cast_from(ptr), Self, dev) }.cast_mut()143141 }144142145143 /// Not intended to be called externally, except via declare_drm_ioctls!()
+1-3
rust/kernel/drm/gem/mod.rs
···125125 }126126127127 unsafe fn from_raw<'a>(self_ptr: *mut bindings::drm_gem_object) -> &'a Self {128128- let self_ptr: *mut Opaque<bindings::drm_gem_object> = self_ptr.cast();129129-130128 // SAFETY: `obj` is guaranteed to be in an `Object<T>` via the safety contract of this131129 // function132132- unsafe { &*crate::container_of!(self_ptr, Object<T>, obj) }130130+ unsafe { &*crate::container_of!(Opaque::cast_from(self_ptr), Object<T>, obj) }133131 }134132}135133
+5-5
rust/kernel/error.rs
···6677use crate::{88 alloc::{layout::LayoutError, AllocError},99+ fmt,910 str::CStr,1011};11121212-use core::fmt;1313use core::num::NonZeroI32;1414use core::num::TryFromIntError;1515use core::str::Utf8Error;···154154 /// Returns the error encoded as a pointer.155155 pub fn to_ptr<T>(self) -> *mut T {156156 // SAFETY: `self.0` is a valid error due to its invariant.157157- unsafe { bindings::ERR_PTR(self.0.get() as _) as *mut _ }157157+ unsafe { bindings::ERR_PTR(self.0.get() as crate::ffi::c_long).cast() }158158 }159159160160 /// Returns a string representing the error, if one exists.···189189 Some(name) => f190190 .debug_tuple(191191 // SAFETY: These strings are ASCII-only.192192- unsafe { core::str::from_utf8_unchecked(name) },192192+ unsafe { core::str::from_utf8_unchecked(name.to_bytes()) },193193 )194194 .finish(),195195 }···220220 }221221}222222223223-impl From<core::fmt::Error> for Error {224224- fn from(_: core::fmt::Error) -> Error {223223+impl From<fmt::Error> for Error {224224+ fn from(_: fmt::Error) -> Error {225225 code::EINVAL226226 }227227}
+5-4
rust/kernel/firmware.rs
···6262 fn request_internal(name: &CStr, dev: &Device, func: FwFunc) -> Result<Self> {6363 let mut fw: *mut bindings::firmware = core::ptr::null_mut();6464 let pfw: *mut *mut bindings::firmware = &mut fw;6565+ let pfw: *mut *const bindings::firmware = pfw.cast();65666667 // SAFETY: `pfw` is a valid pointer to a NULL initialized `bindings::firmware` pointer.6768 // `name` and `dev` are valid as by their type invariants.6868- let ret = unsafe { func.0(pfw as _, name.as_char_ptr(), dev.as_raw()) };6969+ let ret = unsafe { func.0(pfw, name.as_char_ptr(), dev.as_raw()) };6970 if ret != 0 {7071 return Err(Error::from_errno(ret));7172 }···140139/// Typically, such contracts would be enforced by a trait, however traits do not (yet) support141140/// const functions.142141///143143-/// # Example142142+/// # Examples144143///145144/// ```146145/// # mod module_firmware_test {···182181/// module! {183182/// type: MyModule,184183/// name: "module_firmware_test",185185-/// author: "Rust for Linux",184184+/// authors: ["Rust for Linux"],186185/// description: "module_firmware! test module",187186/// license: "GPL",188187/// }···262261 /// Append path components to the [`ModInfoBuilder`] instance. Paths need to be separated263262 /// with [`ModInfoBuilder::new_entry`].264263 ///265265- /// # Example264264+ /// # Examples266265 ///267266 /// ```268267 /// use kernel::firmware::ModInfoBuilder;
+7
rust/kernel/fmt.rs
···11+// SPDX-License-Identifier: GPL-2.022+33+//! Formatting utilities.44+//!55+//! This module is intended to be used in place of `core::fmt` in kernel code.66+77+pub use core::fmt::{Arguments, Debug, Display, Error, Formatter, Result, Write};
+1-1
rust/kernel/fs/file.rs
···366366 //367367 // By the type invariants, there are no `fdget_pos` calls that did not take the368368 // `f_pos_lock` mutex.369369- unsafe { LocalFile::from_raw_file(self as *const File as *const bindings::file) }369369+ unsafe { LocalFile::from_raw_file(core::ptr::from_ref(self).cast()) }370370 }371371}372372
···2929//!3030//! ## General Examples3131//!3232-//! ```rust,ignore3333-//! # #![allow(clippy::disallowed_names)]3232+//! ```rust3333+//! # #![expect(clippy::disallowed_names, clippy::undocumented_unsafe_blocks)]3434//! use kernel::types::Opaque;3535//! use pin_init::pin_init_from_closure;3636//!3737//! // assume we have some `raw_foo` type in C:3838//! #[repr(C)]3939//! struct RawFoo([u8; 16]);4040-//! extern {4040+//! extern "C" {4141//! fn init_foo(_: *mut RawFoo);4242//! }4343//!···6666//! });6767//! ```6868//!6969-//! ```rust,ignore7070-//! # #![allow(unreachable_pub, clippy::disallowed_names)]6969+//! ```rust7070+//! # #![expect(unreachable_pub, clippy::disallowed_names)]7171//! use kernel::{prelude::*, types::Opaque};7272//! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin};7373//! # mod bindings {7474-//! # #![allow(non_camel_case_types)]7474+//! # #![expect(non_camel_case_types, clippy::missing_safety_doc)]7575//! # pub struct foo;7676//! # pub unsafe fn init_foo(_ptr: *mut foo) {}7777//! # pub unsafe fn destroy_foo(_ptr: *mut foo) {}7878//! # pub unsafe fn enable_foo(_ptr: *mut foo, _flags: u32) -> i32 { 0 }7979//! # }8080-//! # // `Error::from_errno` is `pub(crate)` in the `kernel` crate, thus provide a workaround.8181-//! # trait FromErrno {8282-//! # fn from_errno(errno: core::ffi::c_int) -> Error {8383-//! # // Dummy error that can be constructed outside the `kernel` crate.8484-//! # Error::from(core::fmt::Error)8585-//! # }8686-//! # }8787-//! # impl FromErrno for Error {}8880//! /// # Invariants8981//! ///9082//! /// `foo` is always initialized···100108//! let foo = addr_of_mut!((*slot).foo);101109//!102110//! // Initialize the `foo`103103-//! bindings::init_foo(Opaque::raw_get(foo));111111+//! bindings::init_foo(Opaque::cast_into(foo));104112//!105113//! // Try to enable it.106106-//! let err = bindings::enable_foo(Opaque::raw_get(foo), flags);114114+//! let err = bindings::enable_foo(Opaque::cast_into(foo), flags);107115//! if err != 0 {108116//! // Enabling has failed, first clean up the foo and then return the error.109109-//! bindings::destroy_foo(Opaque::raw_get(foo));117117+//! bindings::destroy_foo(Opaque::cast_into(foo));110118//! return Err(Error::from_errno(err));111119//! }112120//!···198206///199207/// ```rust200208/// use kernel::error::Error;201201-/// use pin_init::zeroed;209209+/// use pin_init::init_zeroed;202210/// struct BigBuf {203211/// big: KBox<[u8; 1024 * 1024 * 1024]>,204212/// small: [u8; 1024 * 1024],···207215/// impl BigBuf {208216/// fn new() -> impl Init<Self, Error> {209217/// try_init!(Self {210210-/// big: KBox::init(zeroed(), GFP_KERNEL)?,218218+/// big: KBox::init(init_zeroed(), GFP_KERNEL)?,211219/// small: [0; 1024 * 1024],212220/// }? Error)213221/// }···256264/// ```rust257265/// # #![feature(new_uninit)]258266/// use kernel::error::Error;259259-/// use pin_init::zeroed;267267+/// use pin_init::init_zeroed;260268/// #[pin_data]261269/// struct BigBuf {262270/// big: KBox<[u8; 1024 * 1024 * 1024]>,···267275/// impl BigBuf {268276/// fn new() -> impl PinInit<Self, Error> {269277/// try_pin_init!(Self {270270-/// big: KBox::init(zeroed(), GFP_KERNEL)?,278278+/// big: KBox::init(init_zeroed(), GFP_KERNEL)?,271279/// small: [0; 1024 * 1024],272280/// ptr: core::ptr::null_mut(),273281/// }? Error)
+10-10
rust/kernel/io.rs
···55//! C header: [`include/asm-generic/io.h`](srctree/include/asm-generic/io.h)6677use crate::error::{code::EINVAL, Result};88-use crate::{bindings, build_assert};88+use crate::{bindings, build_assert, ffi::c_void};991010pub mod mem;1111pub mod resource;···4848 }4949}50505151-/// IO-mapped memory, starting at the base address @addr and spanning @maxlen bytes.5151+/// IO-mapped memory region.5252///5353/// The creator (usually a subsystem / bus such as PCI) is responsible for creating the5454/// mapping, performing an additional region request etc.···6161/// # Examples6262///6363/// ```no_run6464-/// # use kernel::{bindings, io::{Io, IoRaw}};6464+/// # use kernel::{bindings, ffi::c_void, io::{Io, IoRaw}};6565/// # use core::ops::Deref;6666///6767/// // See also [`pci::Bar`] for a real example.···7575/// unsafe fn new(paddr: usize) -> Result<Self>{7676/// // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is7777/// // valid for `ioremap`.7878-/// let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };7878+/// let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };7979/// if addr.is_null() {8080/// return Err(ENOMEM);8181/// }8282///8383-/// Ok(IoMem(IoRaw::new(addr as _, SIZE)?))8383+/// Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))8484/// }8585/// }8686///8787/// impl<const SIZE: usize> Drop for IoMem<SIZE> {8888/// fn drop(&mut self) {8989/// // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.9090-/// unsafe { bindings::iounmap(self.0.addr() as _); };9090+/// unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };9191/// }9292/// }9393///···124124 let addr = self.io_addr_assert::<$type_name>(offset);125125126126 // SAFETY: By the type invariant `addr` is a valid address for MMIO operations.127127- unsafe { bindings::$c_fn(addr as _) }127127+ unsafe { bindings::$c_fn(addr as *const c_void) }128128 }129129130130 /// Read IO data from a given offset.···136136 let addr = self.io_addr::<$type_name>(offset)?;137137138138 // SAFETY: By the type invariant `addr` is a valid address for MMIO operations.139139- Ok(unsafe { bindings::$c_fn(addr as _) })139139+ Ok(unsafe { bindings::$c_fn(addr as *const c_void) })140140 }141141 };142142}···153153 let addr = self.io_addr_assert::<$type_name>(offset);154154155155 // SAFETY: By the type invariant `addr` is a valid address for MMIO operations.156156- unsafe { bindings::$c_fn(value, addr as _, ) }156156+ unsafe { bindings::$c_fn(value, addr as *mut c_void) }157157 }158158159159 /// Write IO data from a given offset.···165165 let addr = self.io_addr::<$type_name>(offset)?;166166167167 // SAFETY: By the type invariant `addr` is a valid address for MMIO operations.168168- unsafe { bindings::$c_fn(value, addr as _) }168168+ unsafe { bindings::$c_fn(value, addr as *mut c_void) }169169 Ok(())170170 }171171 };
+8-5
rust/kernel/kunit.rs
···77//! Reference: <https://docs.kernel.org/dev-tools/kunit/index.html>8899use crate::prelude::*;1010-use core::{ffi::c_void, fmt};1010+use core::fmt;1111+1212+#[cfg(CONFIG_PRINTK)]1313+use crate::c_str;11141215/// Prints a KUnit error-level message.1316///···2219 #[cfg(CONFIG_PRINTK)]2320 unsafe {2421 bindings::_printk(2525- c"\x013%pA".as_ptr() as _,2626- &args as *const _ as *const c_void,2222+ c_str!("\x013%pA").as_char_ptr(),2323+ core::ptr::from_ref(&args).cast::<c_void>(),2724 );2825 }2926}···3835 #[cfg(CONFIG_PRINTK)]3936 unsafe {4037 bindings::_printk(4141- c"\x016%pA".as_ptr() as _,4242- &args as *const _ as *const c_void,3838+ c_str!("\x016%pA").as_char_ptr(),3939+ core::ptr::from_ref(&args).cast::<c_void>(),4340 );4441 }4542}
+10
rust/kernel/lib.rs
···6262pub mod alloc;6363#[cfg(CONFIG_AUXILIARY_BUS)]6464pub mod auxiliary;6565+pub mod bits;6566#[cfg(CONFIG_BLOCK)]6667pub mod block;6868+pub mod bug;6769#[doc(hidden)]6870pub mod build_assert;6971pub mod clk;···8785pub mod faux;8886#[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]8987pub mod firmware;8888+pub mod fmt;9089pub mod fs;9190pub mod init;9291pub mod io;···215212}216213217214/// Produces a pointer to an object from a pointer to one of its fields.215215+///216216+/// If you encounter a type mismatch due to the [`Opaque`] type, then use [`Opaque::cast_into`] or217217+/// [`Opaque::cast_from`] to resolve the mismatch.218218+///219219+/// [`Opaque`]: crate::types::Opaque220220+/// [`Opaque::cast_into`]: crate::types::Opaque::cast_into221221+/// [`Opaque::cast_from`]: crate::types::Opaque::cast_from218222///219223/// # Safety220224///
+32-31
rust/kernel/list.rs
···5757/// }5858/// }5959///6060-/// impl_has_list_links! {6161-/// impl HasListLinks<0> for BasicItem { self.links }6262-/// }6360/// impl_list_arc_safe! {6461/// impl ListArcSafe<0> for BasicItem { untracked; }6562/// }6663/// impl_list_item! {6767-/// impl ListItem<0> for BasicItem { using ListLinks; }6464+/// impl ListItem<0> for BasicItem { using ListLinks { self.links }; }6865/// }6966///7067/// // Create a new empty list.···7982/// // [15, 10, 30]8083/// {8184/// let mut iter = list.iter();8282-/// assert_eq!(iter.next().unwrap().value, 15);8383-/// assert_eq!(iter.next().unwrap().value, 10);8484-/// assert_eq!(iter.next().unwrap().value, 30);8585+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 15);8686+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 10);8787+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 30);8588/// assert!(iter.next().is_none());8689///8790/// // Verify the length of the list.···9093///9194/// // Pop the items from the list using `pop_back()` and verify the content.9295/// {9393-/// assert_eq!(list.pop_back().unwrap().value, 30);9494-/// assert_eq!(list.pop_back().unwrap().value, 10);9595-/// assert_eq!(list.pop_back().unwrap().value, 15);9696+/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value, 30);9797+/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value, 10);9898+/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value, 15);9699/// }97100///98101/// // Insert 3 elements using `push_front()`.···104107/// // [30, 10, 15]105108/// {106109/// let mut iter = list.iter();107107-/// assert_eq!(iter.next().unwrap().value, 30);108108-/// assert_eq!(iter.next().unwrap().value, 10);109109-/// assert_eq!(iter.next().unwrap().value, 15);110110+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 30);111111+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 10);112112+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 15);110113/// assert!(iter.next().is_none());111114///112115/// // Verify the length of the list.···115118///116119/// // Pop the items from the list using `pop_front()` and verify the content.117120/// {118118-/// assert_eq!(list.pop_front().unwrap().value, 30);119119-/// assert_eq!(list.pop_front().unwrap().value, 10);121121+/// assert_eq!(list.pop_front().ok_or(EINVAL)?.value, 30);122122+/// assert_eq!(list.pop_front().ok_or(EINVAL)?.value, 10);120123/// }121124///122125/// // Push `list2` to `list` through `push_all_back()`.···132135/// // list: [15, 25, 35]133136/// // list2: []134137/// let mut iter = list.iter();135135-/// assert_eq!(iter.next().unwrap().value, 15);136136-/// assert_eq!(iter.next().unwrap().value, 25);137137-/// assert_eq!(iter.next().unwrap().value, 35);138138+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 15);139139+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 25);140140+/// assert_eq!(iter.next().ok_or(EINVAL)?.value, 35);138141/// assert!(iter.next().is_none());139142/// assert!(list2.is_empty());140143/// }···281284 #[inline]282285 unsafe fn fields(me: *mut Self) -> *mut ListLinksFields {283286 // SAFETY: The caller promises that the pointer is valid.284284- unsafe { Opaque::raw_get(ptr::addr_of!((*me).inner)) }287287+ unsafe { Opaque::cast_into(ptr::addr_of!((*me).inner)) }285288 }286289287290 /// # Safety···317320unsafe impl<T: ?Sized + Sync, const ID: u64> Sync for ListLinksSelfPtr<T, ID> {}318321319322impl<T: ?Sized, const ID: u64> ListLinksSelfPtr<T, ID> {320320- /// The offset from the [`ListLinks`] to the self pointer field.321321- pub const LIST_LINKS_SELF_PTR_OFFSET: usize = core::mem::offset_of!(Self, self_ptr);322322-323323 /// Creates a new initializer for this type.324324 pub fn new() -> impl PinInit<Self> {325325 // INVARIANT: Pin-init initializers can't be used on an existing `Arc`, so this value will···330336 },331337 self_ptr: Opaque::uninit(),332338 }339339+ }340340+341341+ /// Returns a pointer to the self pointer.342342+ ///343343+ /// # Safety344344+ ///345345+ /// The provided pointer must point at a valid struct of type `Self`.346346+ pub unsafe fn raw_get_self_ptr(me: *const Self) -> *const Opaque<*const T> {347347+ // SAFETY: The caller promises that the pointer is valid.348348+ unsafe { ptr::addr_of!((*me).self_ptr) }333349 }334350}335351···715711/// }716712/// }717713///718718-/// kernel::list::impl_has_list_links! {719719-/// impl HasListLinks<0> for ListItem { self.links }720720-/// }721714/// kernel::list::impl_list_arc_safe! {722715/// impl ListArcSafe<0> for ListItem { untracked; }723716/// }724717/// kernel::list::impl_list_item! {725725-/// impl ListItem<0> for ListItem { using ListLinks; }718718+/// impl ListItem<0> for ListItem { using ListLinks { self.links }; }726719/// }727720///728721/// // Use a cursor to remove the first element with the given value.···810809/// merge_sorted(&mut list, list2);811810///812811/// let mut items = list.into_iter();813813-/// assert_eq!(items.next().unwrap().value, 10);814814-/// assert_eq!(items.next().unwrap().value, 11);815815-/// assert_eq!(items.next().unwrap().value, 12);816816-/// assert_eq!(items.next().unwrap().value, 13);817817-/// assert_eq!(items.next().unwrap().value, 14);812812+/// assert_eq!(items.next().ok_or(EINVAL)?.value, 10);813813+/// assert_eq!(items.next().ok_or(EINVAL)?.value, 11);814814+/// assert_eq!(items.next().ok_or(EINVAL)?.value, 12);815815+/// assert_eq!(items.next().ok_or(EINVAL)?.value, 13);816816+/// assert_eq!(items.next().ok_or(EINVAL)?.value, 14);818817/// assert!(items.next().is_none());819818/// # Result::<(), Error>::Ok(())820819/// ```
+158-81
rust/kernel/list/impl_list_item_mod.rs
···4455//! Helpers for implementing list traits safely.6677-use crate::list::ListLinks;88-99-/// Declares that this type has a `ListLinks<ID>` field at a fixed offset.77+/// Declares that this type has a [`ListLinks<ID>`] field.108///1111-/// This trait is only used to help implement `ListItem` safely. If `ListItem` is implemented99+/// This trait is only used to help implement [`ListItem`] safely. If [`ListItem`] is implemented1210/// manually, then this trait is not needed. Use the [`impl_has_list_links!`] macro to implement1311/// this trait.1412///1513/// # Safety1614///1717-/// All values of this type must have a `ListLinks<ID>` field at the given offset.1515+/// The methods on this trait must have exactly the behavior that the definitions given below have.1816///1919-/// The behavior of `raw_get_list_links` must not be changed.1717+/// [`ListLinks<ID>`]: crate::list::ListLinks1818+/// [`ListItem`]: crate::list::ListItem2019pub unsafe trait HasListLinks<const ID: u64 = 0> {2121- /// The offset of the `ListLinks` field.2222- const OFFSET: usize;2323-2424- /// Returns a pointer to the [`ListLinks<T, ID>`] field.2020+ /// Returns a pointer to the [`ListLinks<ID>`] field.2521 ///2622 /// # Safety2723 ///2824 /// The provided pointer must point at a valid struct of type `Self`.2925 ///3030- /// [`ListLinks<T, ID>`]: ListLinks3131- // We don't really need this method, but it's necessary for the implementation of3232- // `impl_has_list_links!` to be correct.3333- #[inline]3434- unsafe fn raw_get_list_links(ptr: *mut Self) -> *mut ListLinks<ID> {3535- // SAFETY: The caller promises that the pointer is valid. The implementer promises that the3636- // `OFFSET` constant is correct.3737- unsafe { (ptr as *mut u8).add(Self::OFFSET) as *mut ListLinks<ID> }3838- }2626+ /// [`ListLinks<ID>`]: crate::list::ListLinks2727+ unsafe fn raw_get_list_links(ptr: *mut Self) -> *mut crate::list::ListLinks<ID>;3928}40294130/// Implements the [`HasListLinks`] trait for the given type.4231#[macro_export]4332macro_rules! impl_has_list_links {4444- ($(impl$(<$($implarg:ident),*>)?3333+ ($(impl$({$($generics:tt)*})?4534 HasListLinks$(<$id:tt>)?4646- for $self:ident $(<$($selfarg:ty),*>)?3535+ for $self:ty4736 { self$(.$field:ident)* }4837 )*) => {$(4938 // SAFETY: The implementation of `raw_get_list_links` only compiles if the field has the5039 // right type.5151- //5252- // The behavior of `raw_get_list_links` is not changed since the `addr_of_mut!` macro is5353- // equivalent to the pointer offset operation in the trait definition.5454- unsafe impl$(<$($implarg),*>)? $crate::list::HasListLinks$(<$id>)? for5555- $self $(<$($selfarg),*>)?5656- {5757- const OFFSET: usize = ::core::mem::offset_of!(Self, $($field).*) as usize;5858-4040+ unsafe impl$(<$($generics)*>)? $crate::list::HasListLinks$(<$id>)? for $self {5941 #[inline]6042 unsafe fn raw_get_list_links(ptr: *mut Self) -> *mut $crate::list::ListLinks$(<$id>)? {4343+ // Statically ensure that `$(.field)*` doesn't follow any pointers.4444+ //4545+ // Cannot be `const` because `$self` may contain generics and E0401 says constants4646+ // "can't use {`Self`,generic parameters} from outer item".4747+ if false { let _: usize = ::core::mem::offset_of!(Self, $($field).*); }4848+6149 // SAFETY: The caller promises that the pointer is not dangling. We know that this6250 // expression doesn't follow any pointers, as the `offset_of!` invocation above6351 // would otherwise not compile.···5668}5769pub use impl_has_list_links;58705959-/// Declares that the `ListLinks<ID>` field in this struct is inside a `ListLinksSelfPtr<T, ID>`.7171+/// Declares that the [`ListLinks<ID>`] field in this struct is inside a7272+/// [`ListLinksSelfPtr<T, ID>`].6073///6174/// # Safety6275///6363-/// The `ListLinks<ID>` field of this struct at the offset `HasListLinks<ID>::OFFSET` must be6464-/// inside a `ListLinksSelfPtr<T, ID>`.7676+/// The [`ListLinks<ID>`] field of this struct at [`HasListLinks<ID>::raw_get_list_links`] must be7777+/// inside a [`ListLinksSelfPtr<T, ID>`].7878+///7979+/// [`ListLinks<ID>`]: crate::list::ListLinks8080+/// [`ListLinksSelfPtr<T, ID>`]: crate::list::ListLinksSelfPtr6581pub unsafe trait HasSelfPtr<T: ?Sized, const ID: u64 = 0>6682where6783 Self: HasListLinks<ID>,···7583/// Implements the [`HasListLinks`] and [`HasSelfPtr`] traits for the given type.7684#[macro_export]7785macro_rules! impl_has_list_links_self_ptr {7878- ($(impl$({$($implarg:tt)*})?8686+ ($(impl$({$($generics:tt)*})?7987 HasSelfPtr<$item_type:ty $(, $id:tt)?>8080- for $self:ident $(<$($selfarg:ty),*>)?8181- { self.$field:ident }8888+ for $self:ty8989+ { self$(.$field:ident)* }8290 )*) => {$(8391 // SAFETY: The implementation of `raw_get_list_links` only compiles if the field has the8492 // right type.8585- unsafe impl$(<$($implarg)*>)? $crate::list::HasSelfPtr<$item_type $(, $id)?> for8686- $self $(<$($selfarg),*>)?8787- {}9393+ unsafe impl$(<$($generics)*>)? $crate::list::HasSelfPtr<$item_type $(, $id)?> for $self {}88948989- unsafe impl$(<$($implarg)*>)? $crate::list::HasListLinks$(<$id>)? for9090- $self $(<$($selfarg),*>)?9191- {9292- const OFFSET: usize = ::core::mem::offset_of!(Self, $field) as usize;9393-9595+ unsafe impl$(<$($generics)*>)? $crate::list::HasListLinks$(<$id>)? for $self {9496 #[inline]9597 unsafe fn raw_get_list_links(ptr: *mut Self) -> *mut $crate::list::ListLinks$(<$id>)? {9698 // SAFETY: The caller promises that the pointer is not dangling.9799 let ptr: *mut $crate::list::ListLinksSelfPtr<$item_type $(, $id)?> =9898- unsafe { ::core::ptr::addr_of_mut!((*ptr).$field) };100100+ unsafe { ::core::ptr::addr_of_mut!((*ptr)$(.$field)*) };99101 ptr.cast()100102 }101103 }···103117/// implement that trait.104118///105119/// [`ListItem`]: crate::list::ListItem120120+///121121+/// # Examples122122+///123123+/// ```124124+/// #[pin_data]125125+/// struct SimpleListItem {126126+/// value: u32,127127+/// #[pin]128128+/// links: kernel::list::ListLinks,129129+/// }130130+///131131+/// kernel::list::impl_list_arc_safe! {132132+/// impl ListArcSafe<0> for SimpleListItem { untracked; }133133+/// }134134+///135135+/// kernel::list::impl_list_item! {136136+/// impl ListItem<0> for SimpleListItem { using ListLinks { self.links }; }137137+/// }138138+///139139+/// struct ListLinksHolder {140140+/// inner: kernel::list::ListLinks,141141+/// }142142+///143143+/// #[pin_data]144144+/// struct ComplexListItem<T, U> {145145+/// value: Result<T, U>,146146+/// #[pin]147147+/// links: ListLinksHolder,148148+/// }149149+///150150+/// kernel::list::impl_list_arc_safe! {151151+/// impl{T, U} ListArcSafe<0> for ComplexListItem<T, U> { untracked; }152152+/// }153153+///154154+/// kernel::list::impl_list_item! {155155+/// impl{T, U} ListItem<0> for ComplexListItem<T, U> { using ListLinks { self.links.inner }; }156156+/// }157157+/// ```158158+///159159+/// ```160160+/// #[pin_data]161161+/// struct SimpleListItem {162162+/// value: u32,163163+/// #[pin]164164+/// links: kernel::list::ListLinksSelfPtr<SimpleListItem>,165165+/// }166166+///167167+/// kernel::list::impl_list_arc_safe! {168168+/// impl ListArcSafe<0> for SimpleListItem { untracked; }169169+/// }170170+///171171+/// kernel::list::impl_list_item! {172172+/// impl ListItem<0> for SimpleListItem { using ListLinksSelfPtr { self.links }; }173173+/// }174174+///175175+/// struct ListLinksSelfPtrHolder<T, U> {176176+/// inner: kernel::list::ListLinksSelfPtr<ComplexListItem<T, U>>,177177+/// }178178+///179179+/// #[pin_data]180180+/// struct ComplexListItem<T, U> {181181+/// value: Result<T, U>,182182+/// #[pin]183183+/// links: ListLinksSelfPtrHolder<T, U>,184184+/// }185185+///186186+/// kernel::list::impl_list_arc_safe! {187187+/// impl{T, U} ListArcSafe<0> for ComplexListItem<T, U> { untracked; }188188+/// }189189+///190190+/// kernel::list::impl_list_item! {191191+/// impl{T, U} ListItem<0> for ComplexListItem<T, U> {192192+/// using ListLinksSelfPtr { self.links.inner };193193+/// }194194+/// }195195+/// ```106196#[macro_export]107197macro_rules! impl_list_item {108198 (109109- $(impl$({$($generics:tt)*})? ListItem<$num:tt> for $t:ty {110110- using ListLinks;199199+ $(impl$({$($generics:tt)*})? ListItem<$num:tt> for $self:ty {200200+ using ListLinks { self$(.$field:ident)* };111201 })*112202 ) => {$(203203+ $crate::list::impl_has_list_links! {204204+ impl$({$($generics)*})? HasListLinks<$num> for $self { self$(.$field)* }205205+ }206206+113207 // SAFETY: See GUARANTEES comment on each method.114114- unsafe impl$(<$($generics)*>)? $crate::list::ListItem<$num> for $t {208208+ unsafe impl$(<$($generics)*>)? $crate::list::ListItem<$num> for $self {115209 // GUARANTEES:116210 // * This returns the same pointer as `prepare_to_insert` because `prepare_to_insert`117211 // is implemented in terms of `view_links`.···205139 }206140207141 // GUARANTEES:208208- // * `me` originates from the most recent call to `prepare_to_insert`, which just added209209- // `offset` to the pointer passed to `prepare_to_insert`. This method subtracts210210- // `offset` from `me` so it returns the pointer originally passed to211211- // `prepare_to_insert`.142142+ // * `me` originates from the most recent call to `prepare_to_insert`, which calls143143+ // `raw_get_list_link`, which is implemented using `addr_of_mut!((*self)$(.$field)*)`.144144+ // This method uses `container_of` to perform the inverse operation, so it returns the145145+ // pointer originally passed to `prepare_to_insert`.212146 // * The pointer remains valid until the next call to `post_remove` because the caller213147 // of the most recent call to `prepare_to_insert` promised to retain ownership of the214148 // `ListArc` containing `Self` until the next call to `post_remove`. The value cannot215149 // be destroyed while a `ListArc` reference exists.216150 unsafe fn view_value(me: *mut $crate::list::ListLinks<$num>) -> *const Self {217217- let offset = <Self as $crate::list::HasListLinks<$num>>::OFFSET;218151 // SAFETY: `me` originates from the most recent call to `prepare_to_insert`, so it219219- // points at the field at offset `offset` in a value of type `Self`. Thus,220220- // subtracting `offset` from `me` is still in-bounds of the allocation.221221- unsafe { (me as *const u8).sub(offset) as *const Self }152152+ // points at the field `$field` in a value of type `Self`. Thus, reversing that153153+ // operation is still in-bounds of the allocation.154154+ $crate::container_of!(me, Self, $($field).*)222155 }223156224157 // GUARANTEES:···234169 }235170236171 // GUARANTEES:237237- // * `me` originates from the most recent call to `prepare_to_insert`, which just added238238- // `offset` to the pointer passed to `prepare_to_insert`. This method subtracts239239- // `offset` from `me` so it returns the pointer originally passed to240240- // `prepare_to_insert`.172172+ // * `me` originates from the most recent call to `prepare_to_insert`, which calls173173+ // `raw_get_list_link`, which is implemented using `addr_of_mut!((*self)$(.$field)*)`.174174+ // This method uses `container_of` to perform the inverse operation, so it returns the175175+ // pointer originally passed to `prepare_to_insert`.241176 unsafe fn post_remove(me: *mut $crate::list::ListLinks<$num>) -> *const Self {242242- let offset = <Self as $crate::list::HasListLinks<$num>>::OFFSET;243177 // SAFETY: `me` originates from the most recent call to `prepare_to_insert`, so it244244- // points at the field at offset `offset` in a value of type `Self`. Thus,245245- // subtracting `offset` from `me` is still in-bounds of the allocation.246246- unsafe { (me as *const u8).sub(offset) as *const Self }178178+ // points at the field `$field` in a value of type `Self`. Thus, reversing that179179+ // operation is still in-bounds of the allocation.180180+ $crate::container_of!(me, Self, $($field).*)247181 }248182 }249183 )*};250184251185 (252252- $(impl$({$($generics:tt)*})? ListItem<$num:tt> for $t:ty {253253- using ListLinksSelfPtr;186186+ $(impl$({$($generics:tt)*})? ListItem<$num:tt> for $self:ty {187187+ using ListLinksSelfPtr { self$(.$field:ident)* };254188 })*255189 ) => {$(190190+ $crate::list::impl_has_list_links_self_ptr! {191191+ impl$({$($generics)*})? HasSelfPtr<$self> for $self { self$(.$field)* }192192+ }193193+256194 // SAFETY: See GUARANTEES comment on each method.257257- unsafe impl$(<$($generics)*>)? $crate::list::ListItem<$num> for $t {195195+ unsafe impl$(<$($generics)*>)? $crate::list::ListItem<$num> for $self {258196 // GUARANTEES:259197 // This implementation of `ListItem` will not give out exclusive access to the same260198 // `ListLinks` several times because calls to `prepare_to_insert` and `post_remove`···270202 // SAFETY: The caller promises that `me` points at a valid value of type `Self`.271203 let links_field = unsafe { <Self as $crate::list::ListItem<$num>>::view_links(me) };272204273273- let spoff = $crate::list::ListLinksSelfPtr::<Self, $num>::LIST_LINKS_SELF_PTR_OFFSET;274274- // Goes via the offset as the field is private.275275- //276276- // SAFETY: The constant is equal to `offset_of!(ListLinksSelfPtr, self_ptr)`, so277277- // the pointer stays in bounds of the allocation.278278- let self_ptr = unsafe { (links_field as *const u8).add(spoff) }279279- as *const $crate::types::Opaque<*const Self>;280280- let cell_inner = $crate::types::Opaque::raw_get(self_ptr);205205+ let container = $crate::container_of!(206206+ links_field, $crate::list::ListLinksSelfPtr<Self, $num>, inner207207+ );208208+209209+ // SAFETY: By the same reasoning above, `links_field` is a valid pointer.210210+ let self_ptr = unsafe {211211+ $crate::list::ListLinksSelfPtr::raw_get_self_ptr(container)212212+ };213213+214214+ let cell_inner = $crate::types::Opaque::cast_into(self_ptr);281215282216 // SAFETY: This value is not accessed in any other places than `prepare_to_insert`,283217 // `post_remove`, or `view_value`. By the safety requirements of those methods,···298228 // this value is not in a list.299229 unsafe fn view_links(me: *const Self) -> *mut $crate::list::ListLinks<$num> {300230 // SAFETY: The caller promises that `me` points at a valid value of type `Self`.301301- unsafe { <Self as HasListLinks<$num>>::raw_get_list_links(me.cast_mut()) }231231+ unsafe {232232+ <Self as $crate::list::HasListLinks<$num>>::raw_get_list_links(me.cast_mut())233233+ }302234 }303235304236 // This function is also used as the implementation of `post_remove`, so the caller···319247 // `ListArc` containing `Self` until the next call to `post_remove`. The value cannot320248 // be destroyed while a `ListArc` reference exists.321249 unsafe fn view_value(links_field: *mut $crate::list::ListLinks<$num>) -> *const Self {322322- let spoff = $crate::list::ListLinksSelfPtr::<Self, $num>::LIST_LINKS_SELF_PTR_OFFSET;323323- // SAFETY: The constant is equal to `offset_of!(ListLinksSelfPtr, self_ptr)`, so324324- // the pointer stays in bounds of the allocation.325325- let self_ptr = unsafe { (links_field as *const u8).add(spoff) }326326- as *const ::core::cell::UnsafeCell<*const Self>;327327- let cell_inner = ::core::cell::UnsafeCell::raw_get(self_ptr);250250+ let container = $crate::container_of!(251251+ links_field, $crate::list::ListLinksSelfPtr<Self, $num>, inner252252+ );253253+254254+ // SAFETY: By the same reasoning above, `links_field` is a valid pointer.255255+ let self_ptr = unsafe {256256+ $crate::list::ListLinksSelfPtr::raw_get_self_ptr(container)257257+ };258258+259259+ let cell_inner = $crate::types::Opaque::cast_into(self_ptr);260260+328261 // SAFETY: This is not a data race, because the only function that writes to this329262 // value is `prepare_to_insert`, but by the safety requirements the330263 // `prepare_to_insert` method may not be called in parallel with `view_value` or
+6-6
rust/kernel/miscdevice.rs
···3333 pub const fn into_raw<T: MiscDevice>(self) -> bindings::miscdevice {3434 // SAFETY: All zeros is valid for this C type.3535 let mut result: bindings::miscdevice = unsafe { MaybeUninit::zeroed().assume_init() };3636- result.minor = bindings::MISC_DYNAMIC_MINOR as _;3636+ result.minor = bindings::MISC_DYNAMIC_MINOR as ffi::c_int;3737 result.name = self.name.as_char_ptr();3838 result.fops = MiscdeviceVTable::<T>::build();3939 result···222222 // type.223223 //224224 // SAFETY: The open call of a file can access the private data.225225- unsafe { (*raw_file).private_data = ptr.into_foreign().cast() };225225+ unsafe { (*raw_file).private_data = ptr.into_foreign() };226226227227 0228228 }···233233 /// must be associated with a `MiscDeviceRegistration<T>`.234234 unsafe extern "C" fn release(_inode: *mut bindings::inode, file: *mut bindings::file) -> c_int {235235 // SAFETY: The release call of a file owns the private data.236236- let private = unsafe { (*file).private_data }.cast();236236+ let private = unsafe { (*file).private_data };237237 // SAFETY: The release call of a file owns the private data.238238 let ptr = unsafe { <T::Ptr as ForeignOwnable>::from_foreign(private) };239239···277277 /// `file` must be a valid file that is associated with a `MiscDeviceRegistration<T>`.278278 unsafe extern "C" fn ioctl(file: *mut bindings::file, cmd: c_uint, arg: c_ulong) -> c_long {279279 // SAFETY: The ioctl call of a file can access the private data.280280- let private = unsafe { (*file).private_data }.cast();280280+ let private = unsafe { (*file).private_data };281281 // SAFETY: Ioctl calls can borrow the private data of the file.282282 let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };283283···302302 arg: c_ulong,303303 ) -> c_long {304304 // SAFETY: The compat ioctl call of a file can access the private data.305305- let private = unsafe { (*file).private_data }.cast();305305+ let private = unsafe { (*file).private_data };306306 // SAFETY: Ioctl calls can borrow the private data of the file.307307 let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };308308···323323 /// - `seq_file` must be a valid `struct seq_file` that we can write to.324324 unsafe extern "C" fn show_fdinfo(seq_file: *mut bindings::seq_file, file: *mut bindings::file) {325325 // SAFETY: The release call of a file owns the private data.326326- let private = unsafe { (*file).private_data }.cast();326326+ let private = unsafe { (*file).private_data };327327 // SAFETY: Ioctl calls can borrow the private data of the file.328328 let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };329329 // SAFETY:
+26-26
rust/kernel/mm/virt.rs
···392392 use crate::bindings;393393394394 /// No flags are set.395395- pub const NONE: vm_flags_t = bindings::VM_NONE as _;395395+ pub const NONE: vm_flags_t = bindings::VM_NONE as vm_flags_t;396396397397 /// Mapping allows reads.398398- pub const READ: vm_flags_t = bindings::VM_READ as _;398398+ pub const READ: vm_flags_t = bindings::VM_READ as vm_flags_t;399399400400 /// Mapping allows writes.401401- pub const WRITE: vm_flags_t = bindings::VM_WRITE as _;401401+ pub const WRITE: vm_flags_t = bindings::VM_WRITE as vm_flags_t;402402403403 /// Mapping allows execution.404404- pub const EXEC: vm_flags_t = bindings::VM_EXEC as _;404404+ pub const EXEC: vm_flags_t = bindings::VM_EXEC as vm_flags_t;405405406406 /// Mapping is shared.407407- pub const SHARED: vm_flags_t = bindings::VM_SHARED as _;407407+ pub const SHARED: vm_flags_t = bindings::VM_SHARED as vm_flags_t;408408409409 /// Mapping may be updated to allow reads.410410- pub const MAYREAD: vm_flags_t = bindings::VM_MAYREAD as _;410410+ pub const MAYREAD: vm_flags_t = bindings::VM_MAYREAD as vm_flags_t;411411412412 /// Mapping may be updated to allow writes.413413- pub const MAYWRITE: vm_flags_t = bindings::VM_MAYWRITE as _;413413+ pub const MAYWRITE: vm_flags_t = bindings::VM_MAYWRITE as vm_flags_t;414414415415 /// Mapping may be updated to allow execution.416416- pub const MAYEXEC: vm_flags_t = bindings::VM_MAYEXEC as _;416416+ pub const MAYEXEC: vm_flags_t = bindings::VM_MAYEXEC as vm_flags_t;417417418418 /// Mapping may be updated to be shared.419419- pub const MAYSHARE: vm_flags_t = bindings::VM_MAYSHARE as _;419419+ pub const MAYSHARE: vm_flags_t = bindings::VM_MAYSHARE as vm_flags_t;420420421421 /// Page-ranges managed without `struct page`, just pure PFN.422422- pub const PFNMAP: vm_flags_t = bindings::VM_PFNMAP as _;422422+ pub const PFNMAP: vm_flags_t = bindings::VM_PFNMAP as vm_flags_t;423423424424 /// Memory mapped I/O or similar.425425- pub const IO: vm_flags_t = bindings::VM_IO as _;425425+ pub const IO: vm_flags_t = bindings::VM_IO as vm_flags_t;426426427427 /// Do not copy this vma on fork.428428- pub const DONTCOPY: vm_flags_t = bindings::VM_DONTCOPY as _;428428+ pub const DONTCOPY: vm_flags_t = bindings::VM_DONTCOPY as vm_flags_t;429429430430 /// Cannot expand with mremap().431431- pub const DONTEXPAND: vm_flags_t = bindings::VM_DONTEXPAND as _;431431+ pub const DONTEXPAND: vm_flags_t = bindings::VM_DONTEXPAND as vm_flags_t;432432433433 /// Lock the pages covered when they are faulted in.434434- pub const LOCKONFAULT: vm_flags_t = bindings::VM_LOCKONFAULT as _;434434+ pub const LOCKONFAULT: vm_flags_t = bindings::VM_LOCKONFAULT as vm_flags_t;435435436436 /// Is a VM accounted object.437437- pub const ACCOUNT: vm_flags_t = bindings::VM_ACCOUNT as _;437437+ pub const ACCOUNT: vm_flags_t = bindings::VM_ACCOUNT as vm_flags_t;438438439439 /// Should the VM suppress accounting.440440- pub const NORESERVE: vm_flags_t = bindings::VM_NORESERVE as _;440440+ pub const NORESERVE: vm_flags_t = bindings::VM_NORESERVE as vm_flags_t;441441442442 /// Huge TLB Page VM.443443- pub const HUGETLB: vm_flags_t = bindings::VM_HUGETLB as _;443443+ pub const HUGETLB: vm_flags_t = bindings::VM_HUGETLB as vm_flags_t;444444445445 /// Synchronous page faults. (DAX-specific)446446- pub const SYNC: vm_flags_t = bindings::VM_SYNC as _;446446+ pub const SYNC: vm_flags_t = bindings::VM_SYNC as vm_flags_t;447447448448 /// Architecture-specific flag.449449- pub const ARCH_1: vm_flags_t = bindings::VM_ARCH_1 as _;449449+ pub const ARCH_1: vm_flags_t = bindings::VM_ARCH_1 as vm_flags_t;450450451451 /// Wipe VMA contents in child on fork.452452- pub const WIPEONFORK: vm_flags_t = bindings::VM_WIPEONFORK as _;452452+ pub const WIPEONFORK: vm_flags_t = bindings::VM_WIPEONFORK as vm_flags_t;453453454454 /// Do not include in the core dump.455455- pub const DONTDUMP: vm_flags_t = bindings::VM_DONTDUMP as _;455455+ pub const DONTDUMP: vm_flags_t = bindings::VM_DONTDUMP as vm_flags_t;456456457457 /// Not soft dirty clean area.458458- pub const SOFTDIRTY: vm_flags_t = bindings::VM_SOFTDIRTY as _;458458+ pub const SOFTDIRTY: vm_flags_t = bindings::VM_SOFTDIRTY as vm_flags_t;459459460460 /// Can contain `struct page` and pure PFN pages.461461- pub const MIXEDMAP: vm_flags_t = bindings::VM_MIXEDMAP as _;461461+ pub const MIXEDMAP: vm_flags_t = bindings::VM_MIXEDMAP as vm_flags_t;462462463463 /// MADV_HUGEPAGE marked this vma.464464- pub const HUGEPAGE: vm_flags_t = bindings::VM_HUGEPAGE as _;464464+ pub const HUGEPAGE: vm_flags_t = bindings::VM_HUGEPAGE as vm_flags_t;465465466466 /// MADV_NOHUGEPAGE marked this vma.467467- pub const NOHUGEPAGE: vm_flags_t = bindings::VM_NOHUGEPAGE as _;467467+ pub const NOHUGEPAGE: vm_flags_t = bindings::VM_NOHUGEPAGE as vm_flags_t;468468469469 /// KSM may merge identical pages.470470- pub const MERGEABLE: vm_flags_t = bindings::VM_MERGEABLE as _;470470+ pub const MERGEABLE: vm_flags_t = bindings::VM_MERGEABLE as vm_flags_t;471471}
+2-2
rust/kernel/net/phy.rs
···142142 // SAFETY: The struct invariant ensures that we may access143143 // this field without additional synchronization.144144 let bit_field = unsafe { &(*self.0.get())._bitfield_1 };145145- bit_field.get(13, 1) == bindings::AUTONEG_ENABLE as u64145145+ bit_field.get(13, 1) == u64::from(bindings::AUTONEG_ENABLE)146146 }147147148148 /// Gets the current auto-negotiation state.···419419 // where we hold `phy_device->lock`, so the accessors on420420 // `Device` are okay to call.421421 let dev = unsafe { Device::from_raw(phydev) };422422- T::match_phy_device(dev) as i32422422+ T::match_phy_device(dev).into()423423 }424424425425 /// # Safety
+3-3
rust/kernel/of.rs
···2727 const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::of_device_id, data);28282929 fn index(&self) -> usize {3030- self.0.data as _3030+ self.0.data as usize3131 }3232}3333···3939 // SAFETY: FFI type is valid to be zero-initialized.4040 let mut of: bindings::of_device_id = unsafe { core::mem::zeroed() };41414242- // TODO: Use `clone_from_slice` once the corresponding types do match.4242+ // TODO: Use `copy_from_slice` once stabilized for `const`.4343 let mut i = 0;4444 while i < src.len() {4545- of.compatible[i] = src[i] as _;4545+ of.compatible[i] = src[i];4646 i += 1;4747 }4848
+10-10
rust/kernel/opp.rs
···9292 let mut list = KVec::with_capacity(names.len() + 1, GFP_KERNEL)?;93939494 for name in names.iter() {9595- list.push(name.as_ptr() as _, GFP_KERNEL)?;9595+ list.push(name.as_ptr().cast(), GFP_KERNEL)?;9696 }97979898 list.push(ptr::null(), GFP_KERNEL)?;···103103///104104/// Represents voltage in microvolts, wrapping a [`c_ulong`] value.105105///106106-/// ## Examples106106+/// # Examples107107///108108/// ```109109/// use kernel::opp::MicroVolt;···128128///129129/// Represents power in microwatts, wrapping a [`c_ulong`] value.130130///131131-/// ## Examples131131+/// # Examples132132///133133/// ```134134/// use kernel::opp::MicroWatt;···153153///154154/// The associated [`OPP`] is automatically removed when the [`Token`] is dropped.155155///156156-/// ## Examples156156+/// # Examples157157///158158/// The following example demonstrates how to create an [`OPP`] dynamically.159159///···202202/// Rust abstraction for the C `struct dev_pm_opp_data`, used to define operating performance203203/// points (OPPs) dynamically.204204///205205-/// ## Examples205205+/// # Examples206206///207207/// The following example demonstrates how to create an [`OPP`] with [`Data`].208208///···254254255255/// [`OPP`] search options.256256///257257-/// ## Examples257257+/// # Examples258258///259259/// Defines how to search for an [`OPP`] in a [`Table`] relative to a frequency.260260///···326326///327327/// Rust abstraction for the C `struct dev_pm_opp_config`.328328///329329-/// ## Examples329329+/// # Examples330330///331331/// The following example demonstrates how to set OPP property-name configuration for a [`Device`].332332///···345345/// impl ConfigOps for Driver {}346346///347347/// fn configure(dev: &ARef<Device>) -> Result<ConfigToken> {348348-/// let name = CString::try_from_fmt(fmt!("{}", "slow"))?;348348+/// let name = CString::try_from_fmt(fmt!("slow"))?;349349///350350/// // The OPP configuration is cleared once the [`ConfigToken`] goes out of scope.351351/// Config::<Driver>::new()···569569///570570/// Instances of this type are reference-counted.571571///572572-/// ## Examples572572+/// # Examples573573///574574/// The following example demonstrates how to get OPP [`Table`] for a [`Cpumask`] and set its575575/// frequency.···10111011///10121012/// A reference to the [`OPP`], &[`OPP`], isn't refcounted by the Rust code.10131013///10141014-/// ## Examples10141014+/// # Examples10151015///10161016/// The following example demonstrates how to get [`OPP`] corresponding to a frequency value and10171017/// configure the device with it.
+8-5
rust/kernel/pci.rs
···98989999/// Declares a kernel module that exposes a single PCI driver.100100///101101-/// # Example101101+/// # Examples102102///103103///```ignore104104/// kernel::module_pci_driver! {···170170 const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::pci_device_id, driver_data);171171172172 fn index(&self) -> usize {173173- self.0.driver_data as _173173+ self.0.driver_data174174 }175175}176176···193193194194/// The PCI driver trait.195195///196196-/// # Example196196+/// # Examples197197///198198///```199199/// # use kernel::{bindings, device::Core, pci};···205205/// MODULE_PCI_TABLE,206206/// <MyDriver as pci::Driver>::IdInfo,207207/// [208208-/// (pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, bindings::PCI_ANY_ID as _), ())208208+/// (209209+/// pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, bindings::PCI_ANY_ID as u32),210210+/// (),211211+/// )209212/// ]210213/// );211214///···347344 // `ioptr` is valid by the safety requirements.348345 // `num` is valid by the safety requirements.349346 unsafe {350350- bindings::pci_iounmap(pdev.as_raw(), ioptr as _);347347+ bindings::pci_iounmap(pdev.as_raw(), ioptr as *mut kernel::ffi::c_void);351348 bindings::pci_release_region(pdev.as_raw(), num);352349 }353350 }
+1-1
rust/kernel/platform.rs
···132132///133133/// Drivers must implement this trait in order to get a platform driver registered.134134///135135-/// # Example135135+/// # Examples136136///137137///```138138/// # use kernel::{acpi, bindings, c_str, device::Core, of, platform};
+3-1
rust/kernel/prelude.rs
···3131// `super::std_vendor` is hidden, which makes the macro inline for some reason.3232#[doc(no_inline)]3333pub use super::dbg;3434-pub use super::fmt;3534pub use super::{dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info, dev_notice, dev_warn};3635pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};3636+pub use core::format_args as fmt;37373838pub use super::{try_init, try_pin_init};3939···4646pub use super::init::InPlaceInit;47474848pub use super::current;4949+5050+pub use super::uaccess::UserPtr;
+6-6
rust/kernel/print.rs
···8899use crate::{1010 ffi::{c_char, c_void},1111+ fmt,1112 prelude::*,1213 str::RawFormatter,1314};1414-use core::fmt;15151616// Called from `vsprintf` with format specifier `%pA`.1717#[expect(clippy::missing_safety_doc)]···2525 // SAFETY: The C contract guarantees that `buf` is valid if it's less than `end`.2626 let mut w = unsafe { RawFormatter::from_ptrs(buf.cast(), end.cast()) };2727 // SAFETY: TODO.2828- let _ = w.write_fmt(unsafe { *(ptr as *const fmt::Arguments<'_>) });2828+ let _ = w.write_fmt(unsafe { *ptr.cast::<fmt::Arguments<'_>>() });2929 w.pos().cast()3030}3131···109109 bindings::_printk(110110 format_string.as_ptr(),111111 module_name.as_ptr(),112112- &args as *const _ as *const c_void,112112+ core::ptr::from_ref(&args).cast::<c_void>(),113113 );114114 }115115}···129129 unsafe {130130 bindings::_printk(131131 format_strings::CONT.as_ptr(),132132- &args as *const _ as *const c_void,132132+ core::ptr::from_ref(&args).cast::<c_void>(),133133 );134134 }135135}···149149 // takes borrows on the arguments, but does not extend the scope of temporaries.150150 // Therefore, a `match` expression is used to keep them around, since151151 // the scrutinee is kept until the end of the `match`.152152- match format_args!($($arg)+) {152152+ match $crate::prelude::fmt!($($arg)+) {153153 // SAFETY: This hidden macro should only be called by the documented154154 // printing macros which ensure the format string is one of the fixed155155 // ones. All `__LOG_PREFIX`s are null-terminated as they are generated···168168 // The `CONT` case.169169 ($format_string:path, true, $($arg:tt)+) => (170170 $crate::print::call_printk_cont(171171- format_args!($($arg)+),171171+ $crate::prelude::fmt!($($arg)+),172172 );173173 );174174);
+13-16
rust/kernel/rbtree.rs
···191191 }192192 }193193194194+ /// Returns true if this tree is empty.195195+ #[inline]196196+ pub fn is_empty(&self) -> bool {197197+ self.root.rb_node.is_null()198198+ }199199+194200 /// Returns an iterator over the tree nodes, sorted by key.195201 pub fn iter(&self) -> Iter<'_, K, V> {196202 Iter {···775769 // the tree cannot change. By the tree invariant, all nodes are valid.776770 unsafe { bindings::rb_erase(&mut (*this).links, addr_of_mut!(self.tree.root)) };777771778778- let current = match (prev, next) {779779- (_, Some(next)) => next,780780- (Some(prev), None) => prev,781781- (None, None) => {782782- return (None, node);783783- }784784- };772772+ // INVARIANT:773773+ // - `current` is a valid node in the [`RBTree`] pointed to by `self.tree`.774774+ let cursor = next.or(prev).map(|current| Self {775775+ current,776776+ tree: self.tree,777777+ });785778786786- (787787- // INVARIANT:788788- // - `current` is a valid node in the [`RBTree`] pointed to by `self.tree`.789789- Some(Self {790790- current,791791- tree: self.tree,792792- }),793793- node,794794- )779779+ (cursor, node)795780 }796781797782 /// Remove the previous node, returning it if it exists.
+4
rust/kernel/revocable.rs
···233233///234234/// The RCU read-side lock is held while the guard is alive.235235pub struct RevocableGuard<'a, T> {236236+ // This can't use the `&'a T` type because references that appear in function arguments must237237+ // not become dangling during the execution of the function, which can happen if the238238+ // `RevocableGuard` is passed as a function argument and then dropped during execution of the239239+ // function.236240 data_ref: *const T,237241 _rcu_guard: rcu::Guard,238242 _p: PhantomData<&'a ()>,
+1-1
rust/kernel/seq_file.rs
···3737 bindings::seq_printf(3838 self.inner.get(),3939 c_str!("%pA").as_char_ptr(),4040- &args as *const _ as *const crate::ffi::c_void,4040+ core::ptr::from_ref(&args).cast::<crate::ffi::c_void>(),4141 );4242 }4343 }
+68-43
rust/kernel/str.rs
···33//! String representations.4455use crate::alloc::{flags::*, AllocError, KVec};66-use core::fmt::{self, Write};66+use crate::fmt::{self, Write};77use core::ops::{self, Deref, DerefMut, Index};8899use crate::prelude::*;···2929 #[inline]3030 pub const fn from_bytes(bytes: &[u8]) -> &Self {3131 // SAFETY: `BStr` is transparent to `[u8]`.3232- unsafe { &*(bytes as *const [u8] as *const BStr) }3232+ unsafe { &*(core::ptr::from_ref(bytes) as *const BStr) }3333 }34343535 /// Strip a prefix from `self`. Delegates to [`slice::strip_prefix`].···5454 /// Formats printable ASCII characters, escaping the rest.5555 ///5656 /// ```5757- /// # use kernel::{fmt, b_str, str::{BStr, CString}};5757+ /// # use kernel::{prelude::fmt, b_str, str::{BStr, CString}};5858 /// let ascii = b_str!("Hello, BStr!");5959- /// let s = CString::try_from_fmt(fmt!("{}", ascii))?;6060- /// assert_eq!(s.as_bytes(), "Hello, BStr!".as_bytes());5959+ /// let s = CString::try_from_fmt(fmt!("{ascii}"))?;6060+ /// assert_eq!(s.to_bytes(), "Hello, BStr!".as_bytes());6161 ///6262 /// let non_ascii = b_str!("🦀");6363- /// let s = CString::try_from_fmt(fmt!("{}", non_ascii))?;6464- /// assert_eq!(s.as_bytes(), "\\xf0\\x9f\\xa6\\x80".as_bytes());6363+ /// let s = CString::try_from_fmt(fmt!("{non_ascii}"))?;6464+ /// assert_eq!(s.to_bytes(), "\\xf0\\x9f\\xa6\\x80".as_bytes());6565 /// # Ok::<(), kernel::error::Error>(())6666 /// ```6767 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {···8585 /// escaping the rest.8686 ///8787 /// ```8888- /// # use kernel::{fmt, b_str, str::{BStr, CString}};8888+ /// # use kernel::{prelude::fmt, b_str, str::{BStr, CString}};8989 /// // Embedded double quotes are escaped.9090 /// let ascii = b_str!("Hello, \"BStr\"!");9191- /// let s = CString::try_from_fmt(fmt!("{:?}", ascii))?;9292- /// assert_eq!(s.as_bytes(), "\"Hello, \\\"BStr\\\"!\"".as_bytes());9191+ /// let s = CString::try_from_fmt(fmt!("{ascii:?}"))?;9292+ /// assert_eq!(s.to_bytes(), "\"Hello, \\\"BStr\\\"!\"".as_bytes());9393 ///9494 /// let non_ascii = b_str!("😺");9595- /// let s = CString::try_from_fmt(fmt!("{:?}", non_ascii))?;9696- /// assert_eq!(s.as_bytes(), "\"\\xf0\\x9f\\x98\\xba\"".as_bytes());9595+ /// let s = CString::try_from_fmt(fmt!("{non_ascii:?}"))?;9696+ /// assert_eq!(s.to_bytes(), "\"\\xf0\\x9f\\x98\\xba\"".as_bytes());9797 /// # Ok::<(), kernel::error::Error>(())9898 /// ```9999 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {···175175 }};176176}177177178178+/// Returns a C pointer to the string.179179+// It is a free function rather than a method on an extension trait because:180180+//181181+// - error[E0379]: functions in trait impls cannot be declared const182182+#[inline]183183+pub const fn as_char_ptr_in_const_context(c_str: &CStr) -> *const c_char {184184+ c_str.0.as_ptr()185185+}186186+178187/// Possible errors when using conversion functions in [`CStr`].179188#[derive(Debug, Clone, Copy)]180189pub enum CStrConvertError {···241232 /// last at least `'a`. When `CStr` is alive, the memory pointed by `ptr`242233 /// must not be mutated.243234 #[inline]244244- pub unsafe fn from_char_ptr<'a>(ptr: *const crate::ffi::c_char) -> &'a Self {235235+ pub unsafe fn from_char_ptr<'a>(ptr: *const c_char) -> &'a Self {245236 // SAFETY: The safety precondition guarantees `ptr` is a valid pointer246237 // to a `NUL`-terminated C string.247238 let len = unsafe { bindings::strlen(ptr) } + 1;248239 // SAFETY: Lifetime guaranteed by the safety precondition.249249- let bytes = unsafe { core::slice::from_raw_parts(ptr as _, len) };240240+ let bytes = unsafe { core::slice::from_raw_parts(ptr.cast(), len) };250241 // SAFETY: As `len` is returned by `strlen`, `bytes` does not contain interior `NUL`.251242 // As we have added 1 to `len`, the last byte is known to be `NUL`.252243 unsafe { Self::from_bytes_with_nul_unchecked(bytes) }···299290 #[inline]300291 pub unsafe fn from_bytes_with_nul_unchecked_mut(bytes: &mut [u8]) -> &mut CStr {301292 // SAFETY: Properties of `bytes` guaranteed by the safety precondition.302302- unsafe { &mut *(bytes as *mut [u8] as *mut CStr) }293293+ unsafe { &mut *(core::ptr::from_mut(bytes) as *mut CStr) }303294 }304295305296 /// Returns a C pointer to the string.297297+ ///298298+ /// Using this function in a const context is deprecated in favor of299299+ /// [`as_char_ptr_in_const_context`] in preparation for replacing `CStr` with `core::ffi::CStr`300300+ /// which does not have this method.306301 #[inline]307307- pub const fn as_char_ptr(&self) -> *const crate::ffi::c_char {308308- self.0.as_ptr()302302+ pub const fn as_char_ptr(&self) -> *const c_char {303303+ as_char_ptr_in_const_context(self)309304 }310305311306 /// Convert the string to a byte slice without the trailing `NUL` byte.312307 #[inline]313313- pub fn as_bytes(&self) -> &[u8] {308308+ pub fn to_bytes(&self) -> &[u8] {314309 &self.0[..self.len()]310310+ }311311+312312+ /// Convert the string to a byte slice without the trailing `NUL` byte.313313+ ///314314+ /// This function is deprecated in favor of [`Self::to_bytes`] in preparation for replacing315315+ /// `CStr` with `core::ffi::CStr` which does not have this method.316316+ #[inline]317317+ pub fn as_bytes(&self) -> &[u8] {318318+ self.to_bytes()315319 }316320317321 /// Convert the string to a byte slice containing the trailing `NUL` byte.318322 #[inline]319319- pub const fn as_bytes_with_nul(&self) -> &[u8] {323323+ pub const fn to_bytes_with_nul(&self) -> &[u8] {320324 &self.0325325+ }326326+327327+ /// Convert the string to a byte slice containing the trailing `NUL` byte.328328+ ///329329+ /// This function is deprecated in favor of [`Self::to_bytes_with_nul`] in preparation for330330+ /// replacing `CStr` with `core::ffi::CStr` which does not have this method.331331+ #[inline]332332+ pub const fn as_bytes_with_nul(&self) -> &[u8] {333333+ self.to_bytes_with_nul()321334 }322335323336 /// Yields a [`&str`] slice if the [`CStr`] contains valid UTF-8.···460429 ///461430 /// ```462431 /// # use kernel::c_str;463463- /// # use kernel::fmt;432432+ /// # use kernel::prelude::fmt;464433 /// # use kernel::str::CStr;465434 /// # use kernel::str::CString;466435 /// let penguin = c_str!("🐧");467467- /// let s = CString::try_from_fmt(fmt!("{}", penguin))?;468468- /// assert_eq!(s.as_bytes_with_nul(), "\\xf0\\x9f\\x90\\xa7\0".as_bytes());436436+ /// let s = CString::try_from_fmt(fmt!("{penguin}"))?;437437+ /// assert_eq!(s.to_bytes_with_nul(), "\\xf0\\x9f\\x90\\xa7\0".as_bytes());469438 ///470439 /// let ascii = c_str!("so \"cool\"");471471- /// let s = CString::try_from_fmt(fmt!("{}", ascii))?;472472- /// assert_eq!(s.as_bytes_with_nul(), "so \"cool\"\0".as_bytes());440440+ /// let s = CString::try_from_fmt(fmt!("{ascii}"))?;441441+ /// assert_eq!(s.to_bytes_with_nul(), "so \"cool\"\0".as_bytes());473442 /// # Ok::<(), kernel::error::Error>(())474443 /// ```475444 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {476476- for &c in self.as_bytes() {445445+ for &c in self.to_bytes() {477446 if (0x20..0x7f).contains(&c) {478447 // Printable character.479448 f.write_char(c as char)?;···490459 ///491460 /// ```492461 /// # use kernel::c_str;493493- /// # use kernel::fmt;462462+ /// # use kernel::prelude::fmt;494463 /// # use kernel::str::CStr;495464 /// # use kernel::str::CString;496465 /// let penguin = c_str!("🐧");497497- /// let s = CString::try_from_fmt(fmt!("{:?}", penguin))?;466466+ /// let s = CString::try_from_fmt(fmt!("{penguin:?}"))?;498467 /// assert_eq!(s.as_bytes_with_nul(), "\"\\xf0\\x9f\\x90\\xa7\"\0".as_bytes());499468 ///500469 /// // Embedded double quotes are escaped.501470 /// let ascii = c_str!("so \"cool\"");502502- /// let s = CString::try_from_fmt(fmt!("{:?}", ascii))?;471471+ /// let s = CString::try_from_fmt(fmt!("{ascii:?}"))?;503472 /// assert_eq!(s.as_bytes_with_nul(), "\"so \\\"cool\\\"\"\0".as_bytes());504473 /// # Ok::<(), kernel::error::Error>(())505474 /// ```···609578610579 macro_rules! format {611580 ($($f:tt)*) => ({612612- CString::try_from_fmt(::kernel::fmt!($($f)*))?.to_str()?581581+ CString::try_from_fmt(fmt!($($f)*))?.to_str()?613582 })614583 }615584···759728 pub(crate) unsafe fn from_ptrs(pos: *mut u8, end: *mut u8) -> Self {760729 // INVARIANT: The safety requirements guarantee the type invariants.761730 Self {762762- beg: pos as _,763763- pos: pos as _,764764- end: end as _,731731+ beg: pos as usize,732732+ pos: pos as usize,733733+ end: end as usize,765734 }766735 }767736···786755 ///787756 /// N.B. It may point to invalid memory.788757 pub(crate) fn pos(&self) -> *mut u8 {789789- self.pos as _758758+ self.pos as *mut u8790759 }791760792761 /// Returns the number of bytes written to the formatter.···871840/// # Examples872841///873842/// ```874874-/// use kernel::{str::CString, fmt};843843+/// use kernel::{str::CString, prelude::fmt};875844///876845/// let s = CString::try_from_fmt(fmt!("{}{}{}", "abc", 10, 20))?;877877-/// assert_eq!(s.as_bytes_with_nul(), "abc1020\0".as_bytes());846846+/// assert_eq!(s.to_bytes_with_nul(), "abc1020\0".as_bytes());878847///879848/// let tmp = "testing";880849/// let s = CString::try_from_fmt(fmt!("{tmp}{}", 123))?;881881-/// assert_eq!(s.as_bytes_with_nul(), "testing123\0".as_bytes());850850+/// assert_eq!(s.to_bytes_with_nul(), "testing123\0".as_bytes());882851///883852/// // This fails because it has an embedded `NUL` byte.884853/// let s = CString::try_from_fmt(fmt!("a\0b{}", 123));···948917 fn try_from(cstr: &'a CStr) -> Result<CString, AllocError> {949918 let mut buf = KVec::new();950919951951- buf.extend_from_slice(cstr.as_bytes_with_nul(), GFP_KERNEL)?;920920+ buf.extend_from_slice(cstr.to_bytes_with_nul(), GFP_KERNEL)?;952921953922 // INVARIANT: The `CStr` and `CString` types have the same invariants for954923 // the string data, and we copied it over without changes.···960929 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {961930 fmt::Debug::fmt(&**self, f)962931 }963963-}964964-965965-/// A convenience alias for [`core::format_args`].966966-#[macro_export]967967-macro_rules! fmt {968968- ($($f:tt)*) => ( ::core::format_args!($($f)*) )969932}
+7-3
rust/kernel/sync.rs
···1010use pin_init;11111212mod arc;1313+pub mod aref;1314pub mod completion;1415mod condvar;1516pub mod lock;···4241 /// Initializes a dynamically allocated lock class key. In the common case of using a4342 /// statically allocated lock class key, the static_lock_class! macro should be used instead.4443 ///4545- /// # Example4444+ /// # Examples4645 /// ```4746 /// # use kernel::c_str;4847 /// # use kernel::alloc::KBox;···9695macro_rules! static_lock_class {9796 () => {{9897 static CLASS: $crate::sync::LockClassKey =9999- // SAFETY: lockdep expects uninitialized memory when it's handed a statically allocated100100- // lock_class_key9898+ // Lockdep expects uninitialized memory when it's handed a statically allocated `struct9999+ // lock_class_key`.100100+ //101101+ // SAFETY: `LockClassKey` transparently wraps `Opaque` which permits uninitialized102102+ // memory.101103 unsafe { ::core::mem::MaybeUninit::uninit().assume_init() };102104 $crate::prelude::Pin::static_ref(&CLASS)103105 }};
+90-12
rust/kernel/sync/arc.rs
···1919use crate::{2020 alloc::{AllocError, Flags, KBox},2121 bindings,2222+ ffi::c_void,2223 init::InPlaceInit,2324 try_init,2425 types::{ForeignOwnable, Opaque},2526};2627use core::{2728 alloc::Layout,2929+ borrow::{Borrow, BorrowMut},2830 fmt,2931 marker::PhantomData,3032 mem::{ManuallyDrop, MaybeUninit},···142140 _p: PhantomData<ArcInner<T>>,143141}144142145145-#[doc(hidden)]146143#[pin_data]147144#[repr(C)]148148-pub struct ArcInner<T: ?Sized> {145145+struct ArcInner<T: ?Sized> {149146 refcount: Opaque<bindings::refcount_t>,150147 data: T,151148}···373372 }374373}375374376376-// SAFETY: The `into_foreign` function returns a pointer that is well-aligned.375375+// SAFETY: The pointer returned by `into_foreign` comes from a well aligned376376+// pointer to `ArcInner<T>`.377377unsafe impl<T: 'static> ForeignOwnable for Arc<T> {378378- type PointedTo = ArcInner<T>;378378+ const FOREIGN_ALIGN: usize = core::mem::align_of::<ArcInner<T>>();379379+379380 type Borrowed<'a> = ArcBorrow<'a, T>;380381 type BorrowedMut<'a> = Self::Borrowed<'a>;381382382382- fn into_foreign(self) -> *mut Self::PointedTo {383383- ManuallyDrop::new(self).ptr.as_ptr()383383+ fn into_foreign(self) -> *mut c_void {384384+ ManuallyDrop::new(self).ptr.as_ptr().cast()384385 }385386386386- unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self {387387+ unsafe fn from_foreign(ptr: *mut c_void) -> Self {387388 // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous388389 // call to `Self::into_foreign`.389389- let inner = unsafe { NonNull::new_unchecked(ptr) };390390+ let inner = unsafe { NonNull::new_unchecked(ptr.cast::<ArcInner<T>>()) };390391391392 // SAFETY: By the safety requirement of this function, we know that `ptr` came from392393 // a previous call to `Arc::into_foreign`, which guarantees that `ptr` is valid and···396393 unsafe { Self::from_inner(inner) }397394 }398395399399- unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> ArcBorrow<'a, T> {396396+ unsafe fn borrow<'a>(ptr: *mut c_void) -> ArcBorrow<'a, T> {400397 // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous401398 // call to `Self::into_foreign`.402402- let inner = unsafe { NonNull::new_unchecked(ptr) };399399+ let inner = unsafe { NonNull::new_unchecked(ptr.cast::<ArcInner<T>>()) };403400404401 // SAFETY: The safety requirements of `from_foreign` ensure that the object remains alive405402 // for the lifetime of the returned value.406403 unsafe { ArcBorrow::new(inner) }407404 }408405409409- unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> ArcBorrow<'a, T> {406406+ unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> ArcBorrow<'a, T> {410407 // SAFETY: The safety requirements for `borrow_mut` are a superset of the safety411408 // requirements for `borrow`.412412- unsafe { Self::borrow(ptr) }409409+ unsafe { <Self as ForeignOwnable>::borrow(ptr) }413410 }414411}415412···425422426423impl<T: ?Sized> AsRef<T> for Arc<T> {427424 fn as_ref(&self) -> &T {425425+ self.deref()426426+ }427427+}428428+429429+/// # Examples430430+///431431+/// ```432432+/// # use core::borrow::Borrow;433433+/// # use kernel::sync::Arc;434434+/// struct Foo<B: Borrow<u32>>(B);435435+///436436+/// // Owned instance.437437+/// let owned = Foo(1);438438+///439439+/// // Shared instance.440440+/// let arc = Arc::new(1, GFP_KERNEL)?;441441+/// let shared = Foo(arc.clone());442442+///443443+/// let i = 1;444444+/// // Borrowed from `i`.445445+/// let borrowed = Foo(&i);446446+/// # Ok::<(), Error>(())447447+/// ```448448+impl<T: ?Sized> Borrow<T> for Arc<T> {449449+ fn borrow(&self) -> &T {428450 self.deref()429451 }430452}···859831 // it is safe to dereference it. Additionally, we know there is only one reference when860832 // it's inside a `UniqueArc`, so it is safe to get a mutable reference.861833 unsafe { &mut self.inner.ptr.as_mut().data }834834+ }835835+}836836+837837+/// # Examples838838+///839839+/// ```840840+/// # use core::borrow::Borrow;841841+/// # use kernel::sync::UniqueArc;842842+/// struct Foo<B: Borrow<u32>>(B);843843+///844844+/// // Owned instance.845845+/// let owned = Foo(1);846846+///847847+/// // Owned instance using `UniqueArc`.848848+/// let arc = UniqueArc::new(1, GFP_KERNEL)?;849849+/// let shared = Foo(arc);850850+///851851+/// let i = 1;852852+/// // Borrowed from `i`.853853+/// let borrowed = Foo(&i);854854+/// # Ok::<(), Error>(())855855+/// ```856856+impl<T: ?Sized> Borrow<T> for UniqueArc<T> {857857+ fn borrow(&self) -> &T {858858+ self.deref()859859+ }860860+}861861+862862+/// # Examples863863+///864864+/// ```865865+/// # use core::borrow::BorrowMut;866866+/// # use kernel::sync::UniqueArc;867867+/// struct Foo<B: BorrowMut<u32>>(B);868868+///869869+/// // Owned instance.870870+/// let owned = Foo(1);871871+///872872+/// // Owned instance using `UniqueArc`.873873+/// let arc = UniqueArc::new(1, GFP_KERNEL)?;874874+/// let shared = Foo(arc);875875+///876876+/// let mut i = 1;877877+/// // Borrowed from `i`.878878+/// let borrowed = Foo(&mut i);879879+/// # Ok::<(), Error>(())880880+/// ```881881+impl<T: ?Sized> BorrowMut<T> for UniqueArc<T> {882882+ fn borrow_mut(&mut self) -> &mut T {883883+ self.deref_mut()862884 }863885}864886
+154
rust/kernel/sync/aref.rs
···11+// SPDX-License-Identifier: GPL-2.022+33+//! Internal reference counting support.44+55+use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull};66+77+/// Types that are _always_ reference counted.88+///99+/// It allows such types to define their own custom ref increment and decrement functions.1010+/// Additionally, it allows users to convert from a shared reference `&T` to an owned reference1111+/// [`ARef<T>`].1212+///1313+/// This is usually implemented by wrappers to existing structures on the C side of the code. For1414+/// Rust code, the recommendation is to use [`Arc`](crate::sync::Arc) to create reference-counted1515+/// instances of a type.1616+///1717+/// # Safety1818+///1919+/// Implementers must ensure that increments to the reference count keep the object alive in memory2020+/// at least until matching decrements are performed.2121+///2222+/// Implementers must also ensure that all instances are reference-counted. (Otherwise they2323+/// won't be able to honour the requirement that [`AlwaysRefCounted::inc_ref`] keep the object2424+/// alive.)2525+pub unsafe trait AlwaysRefCounted {2626+ /// Increments the reference count on the object.2727+ fn inc_ref(&self);2828+2929+ /// Decrements the reference count on the object.3030+ ///3131+ /// Frees the object when the count reaches zero.3232+ ///3333+ /// # Safety3434+ ///3535+ /// Callers must ensure that there was a previous matching increment to the reference count,3636+ /// and that the object is no longer used after its reference count is decremented (as it may3737+ /// result in the object being freed), unless the caller owns another increment on the refcount3838+ /// (e.g., it calls [`AlwaysRefCounted::inc_ref`] twice, then calls3939+ /// [`AlwaysRefCounted::dec_ref`] once).4040+ unsafe fn dec_ref(obj: NonNull<Self>);4141+}4242+4343+/// An owned reference to an always-reference-counted object.4444+///4545+/// The object's reference count is automatically decremented when an instance of [`ARef`] is4646+/// dropped. It is also automatically incremented when a new instance is created via4747+/// [`ARef::clone`].4848+///4949+/// # Invariants5050+///5151+/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`ARef`] instance. In5252+/// particular, the [`ARef`] instance owns an increment on the underlying object's reference count.5353+pub struct ARef<T: AlwaysRefCounted> {5454+ ptr: NonNull<T>,5555+ _p: PhantomData<T>,5656+}5757+5858+// SAFETY: It is safe to send `ARef<T>` to another thread when the underlying `T` is `Sync` because5959+// it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs6060+// `T` to be `Send` because any thread that has an `ARef<T>` may ultimately access `T` using a6161+// mutable reference, for example, when the reference count reaches zero and `T` is dropped.6262+unsafe impl<T: AlwaysRefCounted + Sync + Send> Send for ARef<T> {}6363+6464+// SAFETY: It is safe to send `&ARef<T>` to another thread when the underlying `T` is `Sync`6565+// because it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally,6666+// it needs `T` to be `Send` because any thread that has a `&ARef<T>` may clone it and get an6767+// `ARef<T>` on that thread, so the thread may ultimately access `T` using a mutable reference, for6868+// example, when the reference count reaches zero and `T` is dropped.6969+unsafe impl<T: AlwaysRefCounted + Sync + Send> Sync for ARef<T> {}7070+7171+impl<T: AlwaysRefCounted> ARef<T> {7272+ /// Creates a new instance of [`ARef`].7373+ ///7474+ /// It takes over an increment of the reference count on the underlying object.7575+ ///7676+ /// # Safety7777+ ///7878+ /// Callers must ensure that the reference count was incremented at least once, and that they7979+ /// are properly relinquishing one increment. That is, if there is only one increment, callers8080+ /// must not use the underlying object anymore -- it is only safe to do so via the newly8181+ /// created [`ARef`].8282+ pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {8383+ // INVARIANT: The safety requirements guarantee that the new instance now owns the8484+ // increment on the refcount.8585+ Self {8686+ ptr,8787+ _p: PhantomData,8888+ }8989+ }9090+9191+ /// Consumes the `ARef`, returning a raw pointer.9292+ ///9393+ /// This function does not change the refcount. After calling this function, the caller is9494+ /// responsible for the refcount previously managed by the `ARef`.9595+ ///9696+ /// # Examples9797+ ///9898+ /// ```9999+ /// use core::ptr::NonNull;100100+ /// use kernel::types::{ARef, AlwaysRefCounted};101101+ ///102102+ /// struct Empty {}103103+ ///104104+ /// # // SAFETY: TODO.105105+ /// unsafe impl AlwaysRefCounted for Empty {106106+ /// fn inc_ref(&self) {}107107+ /// unsafe fn dec_ref(_obj: NonNull<Self>) {}108108+ /// }109109+ ///110110+ /// let mut data = Empty {};111111+ /// let ptr = NonNull::<Empty>::new(&mut data).unwrap();112112+ /// # // SAFETY: TODO.113113+ /// let data_ref: ARef<Empty> = unsafe { ARef::from_raw(ptr) };114114+ /// let raw_ptr: NonNull<Empty> = ARef::into_raw(data_ref);115115+ ///116116+ /// assert_eq!(ptr, raw_ptr);117117+ /// ```118118+ pub fn into_raw(me: Self) -> NonNull<T> {119119+ ManuallyDrop::new(me).ptr120120+ }121121+}122122+123123+impl<T: AlwaysRefCounted> Clone for ARef<T> {124124+ fn clone(&self) -> Self {125125+ self.inc_ref();126126+ // SAFETY: We just incremented the refcount above.127127+ unsafe { Self::from_raw(self.ptr) }128128+ }129129+}130130+131131+impl<T: AlwaysRefCounted> Deref for ARef<T> {132132+ type Target = T;133133+134134+ fn deref(&self) -> &Self::Target {135135+ // SAFETY: The type invariants guarantee that the object is valid.136136+ unsafe { self.ptr.as_ref() }137137+ }138138+}139139+140140+impl<T: AlwaysRefCounted> From<&T> for ARef<T> {141141+ fn from(b: &T) -> Self {142142+ b.inc_ref();143143+ // SAFETY: We just incremented the refcount above.144144+ unsafe { Self::from_raw(NonNull::from(b)) }145145+ }146146+}147147+148148+impl<T: AlwaysRefCounted> Drop for ARef<T> {149149+ fn drop(&mut self) {150150+ // SAFETY: The type invariants guarantee that the `ARef` owns the reference we're about to151151+ // decrement.152152+ unsafe { T::dec_ref(self.ptr) };153153+ }154154+}
+154-79
rust/kernel/time.rs
···2424//! C header: [`include/linux/jiffies.h`](srctree/include/linux/jiffies.h).2525//! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h).26262727+use core::marker::PhantomData;2828+2929+pub mod delay;2730pub mod hrtimer;28312932/// The number of nanoseconds per microsecond.···5249 unsafe { bindings::__msecs_to_jiffies(msecs) }5350}54515252+/// Trait for clock sources.5353+///5454+/// Selection of the clock source depends on the use case. In some cases the usage of a5555+/// particular clock is mandatory, e.g. in network protocols, filesystems. In other5656+/// cases the user of the clock has to decide which clock is best suited for the5757+/// purpose. In most scenarios clock [`Monotonic`] is the best choice as it5858+/// provides a accurate monotonic notion of time (leap second smearing ignored).5959+pub trait ClockSource {6060+ /// The kernel clock ID associated with this clock source.6161+ ///6262+ /// This constant corresponds to the C side `clockid_t` value.6363+ const ID: bindings::clockid_t;6464+6565+ /// Get the current time from the clock source.6666+ ///6767+ /// The function must return a value in the range from 0 to `KTIME_MAX`.6868+ fn ktime_get() -> bindings::ktime_t;6969+}7070+7171+/// A monotonically increasing clock.7272+///7373+/// A nonsettable system-wide clock that represents monotonic time since as7474+/// described by POSIX, "some unspecified point in the past". On Linux, that7575+/// point corresponds to the number of seconds that the system has been7676+/// running since it was booted.7777+///7878+/// The CLOCK_MONOTONIC clock is not affected by discontinuous jumps in the7979+/// CLOCK_REAL (e.g., if the system administrator manually changes the8080+/// clock), but is affected by frequency adjustments. This clock does not8181+/// count time that the system is suspended.8282+pub struct Monotonic;8383+8484+impl ClockSource for Monotonic {8585+ const ID: bindings::clockid_t = bindings::CLOCK_MONOTONIC as bindings::clockid_t;8686+8787+ fn ktime_get() -> bindings::ktime_t {8888+ // SAFETY: It is always safe to call `ktime_get()` outside of NMI context.8989+ unsafe { bindings::ktime_get() }9090+ }9191+}9292+9393+/// A settable system-wide clock that measures real (i.e., wall-clock) time.9494+///9595+/// Setting this clock requires appropriate privileges. This clock is9696+/// affected by discontinuous jumps in the system time (e.g., if the system9797+/// administrator manually changes the clock), and by frequency adjustments9898+/// performed by NTP and similar applications via adjtime(3), adjtimex(2),9999+/// clock_adjtime(2), and ntp_adjtime(3). This clock normally counts the100100+/// number of seconds since 1970-01-01 00:00:00 Coordinated Universal Time101101+/// (UTC) except that it ignores leap seconds; near a leap second it may be102102+/// adjusted by leap second smearing to stay roughly in sync with UTC. Leap103103+/// second smearing applies frequency adjustments to the clock to speed up104104+/// or slow down the clock to account for the leap second without105105+/// discontinuities in the clock. If leap second smearing is not applied,106106+/// the clock will experience discontinuity around leap second adjustment.107107+pub struct RealTime;108108+109109+impl ClockSource for RealTime {110110+ const ID: bindings::clockid_t = bindings::CLOCK_REALTIME as bindings::clockid_t;111111+112112+ fn ktime_get() -> bindings::ktime_t {113113+ // SAFETY: It is always safe to call `ktime_get_real()` outside of NMI context.114114+ unsafe { bindings::ktime_get_real() }115115+ }116116+}117117+118118+/// A monotonic that ticks while system is suspended.119119+///120120+/// A nonsettable system-wide clock that is identical to CLOCK_MONOTONIC,121121+/// except that it also includes any time that the system is suspended. This122122+/// allows applications to get a suspend-aware monotonic clock without123123+/// having to deal with the complications of CLOCK_REALTIME, which may have124124+/// discontinuities if the time is changed using settimeofday(2) or similar.125125+pub struct BootTime;126126+127127+impl ClockSource for BootTime {128128+ const ID: bindings::clockid_t = bindings::CLOCK_BOOTTIME as bindings::clockid_t;129129+130130+ fn ktime_get() -> bindings::ktime_t {131131+ // SAFETY: It is always safe to call `ktime_get_boottime()` outside of NMI context.132132+ unsafe { bindings::ktime_get_boottime() }133133+ }134134+}135135+136136+/// International Atomic Time.137137+///138138+/// A system-wide clock derived from wall-clock time but counting leap seconds.139139+///140140+/// This clock is coupled to CLOCK_REALTIME and will be set when CLOCK_REALTIME is141141+/// set, or when the offset to CLOCK_REALTIME is changed via adjtimex(2). This142142+/// usually happens during boot and **should** not happen during normal operations.143143+/// However, if NTP or another application adjusts CLOCK_REALTIME by leap second144144+/// smearing, this clock will not be precise during leap second smearing.145145+///146146+/// The acronym TAI refers to International Atomic Time.147147+pub struct Tai;148148+149149+impl ClockSource for Tai {150150+ const ID: bindings::clockid_t = bindings::CLOCK_TAI as bindings::clockid_t;151151+152152+ fn ktime_get() -> bindings::ktime_t {153153+ // SAFETY: It is always safe to call `ktime_get_tai()` outside of NMI context.154154+ unsafe { bindings::ktime_get_clocktai() }155155+ }156156+}157157+55158/// A specific point in time.56159///57160/// # Invariants58161///59162/// The `inner` value is in the range from 0 to `KTIME_MAX`.60163#[repr(transparent)]6161-#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]6262-pub struct Instant {164164+#[derive(PartialEq, PartialOrd, Eq, Ord)]165165+pub struct Instant<C: ClockSource> {63166 inner: bindings::ktime_t,167167+ _c: PhantomData<C>,64168}651696666-impl Instant {6767- /// Get the current time using `CLOCK_MONOTONIC`.170170+impl<C: ClockSource> Clone for Instant<C> {171171+ fn clone(&self) -> Self {172172+ *self173173+ }174174+}175175+176176+impl<C: ClockSource> Copy for Instant<C> {}177177+178178+impl<C: ClockSource> Instant<C> {179179+ /// Get the current time from the clock source.68180 #[inline]69181 pub fn now() -> Self {7070- // INVARIANT: The `ktime_get()` function returns a value in the range182182+ // INVARIANT: The `ClockSource::ktime_get()` function returns a value in the range71183 // from 0 to `KTIME_MAX`.72184 Self {7373- // SAFETY: It is always safe to call `ktime_get()` outside of NMI context.7474- inner: unsafe { bindings::ktime_get() },185185+ inner: C::ktime_get(),186186+ _c: PhantomData,75187 }76188 }77189···19577 pub fn elapsed(&self) -> Delta {19678 Self::now() - *self19779 }8080+8181+ #[inline]8282+ pub(crate) fn as_nanos(&self) -> i64 {8383+ self.inner8484+ }19885}19986200200-impl core::ops::Sub for Instant {8787+impl<C: ClockSource> core::ops::Sub for Instant<C> {20188 type Output = Delta;2028920390 // By the type invariant, it never overflows.20491 #[inline]205205- fn sub(self, other: Instant) -> Delta {9292+ fn sub(self, other: Instant<C>) -> Delta {20693 Delta {20794 nanos: self.inner - other.inner,20895 }209209- }210210-}211211-212212-/// An identifier for a clock. Used when specifying clock sources.213213-///214214-///215215-/// Selection of the clock depends on the use case. In some cases the usage of a216216-/// particular clock is mandatory, e.g. in network protocols, filesystems.In other217217-/// cases the user of the clock has to decide which clock is best suited for the218218-/// purpose. In most scenarios clock [`ClockId::Monotonic`] is the best choice as it219219-/// provides a accurate monotonic notion of time (leap second smearing ignored).220220-#[derive(Clone, Copy, PartialEq, Eq, Debug)]221221-#[repr(u32)]222222-pub enum ClockId {223223- /// A settable system-wide clock that measures real (i.e., wall-clock) time.224224- ///225225- /// Setting this clock requires appropriate privileges. This clock is226226- /// affected by discontinuous jumps in the system time (e.g., if the system227227- /// administrator manually changes the clock), and by frequency adjustments228228- /// performed by NTP and similar applications via adjtime(3), adjtimex(2),229229- /// clock_adjtime(2), and ntp_adjtime(3). This clock normally counts the230230- /// number of seconds since 1970-01-01 00:00:00 Coordinated Universal Time231231- /// (UTC) except that it ignores leap seconds; near a leap second it may be232232- /// adjusted by leap second smearing to stay roughly in sync with UTC. Leap233233- /// second smearing applies frequency adjustments to the clock to speed up234234- /// or slow down the clock to account for the leap second without235235- /// discontinuities in the clock. If leap second smearing is not applied,236236- /// the clock will experience discontinuity around leap second adjustment.237237- RealTime = bindings::CLOCK_REALTIME,238238- /// A monotonically increasing clock.239239- ///240240- /// A nonsettable system-wide clock that represents monotonic time since—as241241- /// described by POSIX—"some unspecified point in the past". On Linux, that242242- /// point corresponds to the number of seconds that the system has been243243- /// running since it was booted.244244- ///245245- /// The CLOCK_MONOTONIC clock is not affected by discontinuous jumps in the246246- /// CLOCK_REAL (e.g., if the system administrator manually changes the247247- /// clock), but is affected by frequency adjustments. This clock does not248248- /// count time that the system is suspended.249249- Monotonic = bindings::CLOCK_MONOTONIC,250250- /// A monotonic that ticks while system is suspended.251251- ///252252- /// A nonsettable system-wide clock that is identical to CLOCK_MONOTONIC,253253- /// except that it also includes any time that the system is suspended. This254254- /// allows applications to get a suspend-aware monotonic clock without255255- /// having to deal with the complications of CLOCK_REALTIME, which may have256256- /// discontinuities if the time is changed using settimeofday(2) or similar.257257- BootTime = bindings::CLOCK_BOOTTIME,258258- /// International Atomic Time.259259- ///260260- /// A system-wide clock derived from wall-clock time but counting leap seconds.261261- ///262262- /// This clock is coupled to CLOCK_REALTIME and will be set when CLOCK_REALTIME is263263- /// set, or when the offset to CLOCK_REALTIME is changed via adjtimex(2). This264264- /// usually happens during boot and **should** not happen during normal operations.265265- /// However, if NTP or another application adjusts CLOCK_REALTIME by leap second266266- /// smearing, this clock will not be precise during leap second smearing.267267- ///268268- /// The acronym TAI refers to International Atomic Time.269269- TAI = bindings::CLOCK_TAI,270270-}271271-272272-impl ClockId {273273- fn into_c(self) -> bindings::clockid_t {274274- self as bindings::clockid_t27596 }27697}27798···285228 /// Return the smallest number of microseconds greater than or equal286229 /// to the value in the [`Delta`].287230 #[inline]288288- pub const fn as_micros_ceil(self) -> i64 {289289- self.as_nanos().saturating_add(NSEC_PER_USEC - 1) / NSEC_PER_USEC231231+ pub fn as_micros_ceil(self) -> i64 {232232+ #[cfg(CONFIG_64BIT)]233233+ {234234+ self.as_nanos().saturating_add(NSEC_PER_USEC - 1) / NSEC_PER_USEC235235+ }236236+237237+ #[cfg(not(CONFIG_64BIT))]238238+ // SAFETY: It is always safe to call `ktime_to_us()` with any value.239239+ unsafe {240240+ bindings::ktime_to_us(self.as_nanos().saturating_add(NSEC_PER_USEC - 1))241241+ }290242 }291243292244 /// Return the number of milliseconds in the [`Delta`].293245 #[inline]294294- pub const fn as_millis(self) -> i64 {295295- self.as_nanos() / NSEC_PER_MSEC246246+ pub fn as_millis(self) -> i64 {247247+ #[cfg(CONFIG_64BIT)]248248+ {249249+ self.as_nanos() / NSEC_PER_MSEC250250+ }251251+252252+ #[cfg(not(CONFIG_64BIT))]253253+ // SAFETY: It is always safe to call `ktime_to_ms()` with any value.254254+ unsafe {255255+ bindings::ktime_to_ms(self.as_nanos())256256+ }296257 }297258}
+49
rust/kernel/time/delay.rs
···11+// SPDX-License-Identifier: GPL-2.022+33+//! Delay and sleep primitives.44+//!55+//! This module contains the kernel APIs related to delay and sleep that66+//! have been ported or wrapped for usage by Rust code in the kernel.77+//!88+//! C header: [`include/linux/delay.h`](srctree/include/linux/delay.h).99+1010+use super::Delta;1111+use crate::prelude::*;1212+1313+/// Sleeps for a given duration at least.1414+///1515+/// Equivalent to the C side [`fsleep()`], flexible sleep function,1616+/// which automatically chooses the best sleep method based on a duration.1717+///1818+/// `delta` must be within `[0, i32::MAX]` microseconds;1919+/// otherwise, it is erroneous behavior. That is, it is considered a bug2020+/// to call this function with an out-of-range value, in which case the function2121+/// will sleep for at least the maximum value in the range and may warn2222+/// in the future.2323+///2424+/// The behavior above differs from the C side [`fsleep()`] for which out-of-range2525+/// values mean "infinite timeout" instead.2626+///2727+/// This function can only be used in a nonatomic context.2828+///2929+/// [`fsleep()`]: https://docs.kernel.org/timers/delay_sleep_functions.html#c.fsleep3030+pub fn fsleep(delta: Delta) {3131+ // The maximum value is set to `i32::MAX` microseconds to prevent integer3232+ // overflow inside fsleep, which could lead to unintentional infinite sleep.3333+ const MAX_DELTA: Delta = Delta::from_micros(i32::MAX as i64);3434+3535+ let delta = if (Delta::ZERO..=MAX_DELTA).contains(&delta) {3636+ delta3737+ } else {3838+ // TODO: Add WARN_ONCE() when it's supported.3939+ MAX_DELTA4040+ };4141+4242+ // SAFETY: It is always safe to call `fsleep()` with any duration.4343+ unsafe {4444+ // Convert the duration to microseconds and round up to preserve4545+ // the guarantee; `fsleep()` sleeps for at least the provided duration,4646+ // but that it may sleep for longer under some circumstances.4747+ bindings::fsleep(delta.as_micros_ceil() as c_ulong)4848+ }4949+}
+204-100
rust/kernel/time/hrtimer.rs
···6767//! A `restart` operation on a timer in the **stopped** state is equivalent to a6868//! `start` operation.69697070-use super::ClockId;7070+use super::{ClockSource, Delta, Instant};7171use crate::{prelude::*, types::Opaque};7272use core::marker::PhantomData;7373use pin_init::PinInit;7474-7575-/// A Rust wrapper around a `ktime_t`.7676-// NOTE: Ktime is going to be removed when hrtimer is converted to Instant/Delta.7777-#[repr(transparent)]7878-#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]7979-pub struct Ktime {8080- inner: bindings::ktime_t,8181-}8282-8383-impl Ktime {8484- /// Returns the number of nanoseconds.8585- #[inline]8686- pub fn to_ns(self) -> i64 {8787- self.inner8888- }8989-}90749175/// A timer backed by a C `struct hrtimer`.9276///···8298pub struct HrTimer<T> {8399 #[pin]84100 timer: Opaque<bindings::hrtimer>,8585- mode: HrTimerMode,86101 _t: PhantomData<T>,87102}88103···9511296113impl<T> HrTimer<T> {97114 /// Return an initializer for a new timer instance.9898- pub fn new(mode: HrTimerMode, clock: ClockId) -> impl PinInit<Self>115115+ pub fn new() -> impl PinInit<Self>99116 where100117 T: HrTimerCallback,118118+ T: HasHrTimer<T>,101119 {102120 pin_init!(Self {103121 // INVARIANT: We initialize `timer` with `hrtimer_setup` below.···110126 bindings::hrtimer_setup(111127 place,112128 Some(T::Pointer::run),113113- clock.into_c(),114114- mode.into_c(),129129+ <<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Clock::ID,130130+ <T as HasHrTimer<T>>::TimerMode::C_MODE,115131 );116132 }117133 }),118118- mode: mode,119134 _t: PhantomData,120135 })121136 }···131148 // SAFETY: The field projection to `timer` does not go out of bounds,132149 // because the caller of this function promises that `this` points to an133150 // allocation of at least the size of `Self`.134134- unsafe { Opaque::raw_get(core::ptr::addr_of!((*this).timer)) }151151+ unsafe { Opaque::cast_into(core::ptr::addr_of!((*this).timer)) }135152 }136153137154 /// Cancel an initialized and potentially running timer.···176193/// exist. A timer can be manipulated through any of the handles, and a handle177194/// may represent a cancelled timer.178195pub trait HrTimerPointer: Sync + Sized {196196+ /// The operational mode associated with this timer.197197+ ///198198+ /// This defines how the expiration value is interpreted.199199+ type TimerMode: HrTimerMode;200200+179201 /// A handle representing a started or restarted timer.180202 ///181203 /// If the timer is running or if the timer callback is executing when the···193205194206 /// Start the timer with expiry after `expires` time units. If the timer was195207 /// already running, it is restarted with the new expiry time.196196- fn start(self, expires: Ktime) -> Self::TimerHandle;208208+ fn start(self, expires: <Self::TimerMode as HrTimerMode>::Expires) -> Self::TimerHandle;197209}198210199211/// Unsafe version of [`HrTimerPointer`] for situations where leaking the···208220/// [`UnsafeHrTimerPointer`] outlives any associated [`HrTimerPointer::TimerHandle`]209221/// instances.210222pub unsafe trait UnsafeHrTimerPointer: Sync + Sized {223223+ /// The operational mode associated with this timer.224224+ ///225225+ /// This defines how the expiration value is interpreted.226226+ type TimerMode: HrTimerMode;227227+211228 /// A handle representing a running timer.212229 ///213230 /// # Safety···229236 ///230237 /// Caller promises keep the timer structure alive until the timer is dead.231238 /// Caller can ensure this by not leaking the returned [`Self::TimerHandle`].232232- unsafe fn start(self, expires: Ktime) -> Self::TimerHandle;239239+ unsafe fn start(self, expires: <Self::TimerMode as HrTimerMode>::Expires) -> Self::TimerHandle;233240}234241235242/// A trait for stack allocated timers.···239246/// Implementers must ensure that `start_scoped` does not return until the240247/// timer is dead and the timer handler is not running.241248pub unsafe trait ScopedHrTimerPointer {249249+ /// The operational mode associated with this timer.250250+ ///251251+ /// This defines how the expiration value is interpreted.252252+ type TimerMode: HrTimerMode;253253+242254 /// Start the timer to run after `expires` time units and immediately243255 /// after call `f`. When `f` returns, the timer is cancelled.244244- fn start_scoped<T, F>(self, expires: Ktime, f: F) -> T256256+ fn start_scoped<T, F>(self, expires: <Self::TimerMode as HrTimerMode>::Expires, f: F) -> T245257 where246258 F: FnOnce() -> T;247259}···258260where259261 T: UnsafeHrTimerPointer,260262{261261- fn start_scoped<U, F>(self, expires: Ktime, f: F) -> U263263+ type TimerMode = T::TimerMode;264264+265265+ fn start_scoped<U, F>(266266+ self,267267+ expires: <<T as UnsafeHrTimerPointer>::TimerMode as HrTimerMode>::Expires,268268+ f: F,269269+ ) -> U262270 where263271 F: FnOnce() -> U,264272 {···339335/// their documentation. All the methods of this trait must operate on the same340336/// field.341337pub unsafe trait HasHrTimer<T> {338338+ /// The operational mode associated with this timer.339339+ ///340340+ /// This defines how the expiration value is interpreted.341341+ type TimerMode: HrTimerMode;342342+342343 /// Return a pointer to the [`HrTimer`] within `Self`.343344 ///344345 /// This function is useful to get access to the value without creating···391382 /// - `this` must point to a valid `Self`.392383 /// - Caller must ensure that the pointee of `this` lives until the timer393384 /// fires or is canceled.394394- unsafe fn start(this: *const Self, expires: Ktime) {385385+ unsafe fn start(this: *const Self, expires: <Self::TimerMode as HrTimerMode>::Expires) {395386 // SAFETY: By function safety requirement, `this` is a valid `Self`.396387 unsafe {397388 bindings::hrtimer_start_range_ns(398389 Self::c_timer_ptr(this).cast_mut(),399399- expires.to_ns(),390390+ expires.as_nanos(),400391 0,401401- (*Self::raw_get_timer(this)).mode.into_c(),392392+ <Self::TimerMode as HrTimerMode>::C_MODE,402393 );403394 }404395 }···420411 }421412}422413423423-/// Operational mode of [`HrTimer`].424424-// NOTE: Some of these have the same encoding on the C side, so we keep425425-// `repr(Rust)` and convert elsewhere.426426-#[derive(Clone, Copy, PartialEq, Eq, Debug)]427427-pub enum HrTimerMode {428428- /// Timer expires at the given expiration time.429429- Absolute,430430- /// Timer expires after the given expiration time interpreted as a duration from now.431431- Relative,432432- /// Timer does not move between CPU cores.433433- Pinned,434434- /// Timer handler is executed in soft irq context.435435- Soft,436436- /// Timer handler is executed in hard irq context.437437- Hard,438438- /// Timer expires at the given expiration time.439439- /// Timer does not move between CPU cores.440440- AbsolutePinned,441441- /// Timer expires after the given expiration time interpreted as a duration from now.442442- /// Timer does not move between CPU cores.443443- RelativePinned,444444- /// Timer expires at the given expiration time.445445- /// Timer handler is executed in soft irq context.446446- AbsoluteSoft,447447- /// Timer expires after the given expiration time interpreted as a duration from now.448448- /// Timer handler is executed in soft irq context.449449- RelativeSoft,450450- /// Timer expires at the given expiration time.451451- /// Timer does not move between CPU cores.452452- /// Timer handler is executed in soft irq context.453453- AbsolutePinnedSoft,454454- /// Timer expires after the given expiration time interpreted as a duration from now.455455- /// Timer does not move between CPU cores.456456- /// Timer handler is executed in soft irq context.457457- RelativePinnedSoft,458458- /// Timer expires at the given expiration time.459459- /// Timer handler is executed in hard irq context.460460- AbsoluteHard,461461- /// Timer expires after the given expiration time interpreted as a duration from now.462462- /// Timer handler is executed in hard irq context.463463- RelativeHard,464464- /// Timer expires at the given expiration time.465465- /// Timer does not move between CPU cores.466466- /// Timer handler is executed in hard irq context.467467- AbsolutePinnedHard,468468- /// Timer expires after the given expiration time interpreted as a duration from now.469469- /// Timer does not move between CPU cores.470470- /// Timer handler is executed in hard irq context.471471- RelativePinnedHard,414414+/// Time representations that can be used as expiration values in [`HrTimer`].415415+pub trait HrTimerExpires {416416+ /// Converts the expiration time into a nanosecond representation.417417+ ///418418+ /// This value corresponds to a raw ktime_t value, suitable for passing to kernel419419+ /// timer functions. The interpretation (absolute vs relative) depends on the420420+ /// associated [HrTimerMode] in use.421421+ fn as_nanos(&self) -> i64;472422}473423474474-impl HrTimerMode {475475- fn into_c(self) -> bindings::hrtimer_mode {476476- use bindings::*;477477- match self {478478- HrTimerMode::Absolute => hrtimer_mode_HRTIMER_MODE_ABS,479479- HrTimerMode::Relative => hrtimer_mode_HRTIMER_MODE_REL,480480- HrTimerMode::Pinned => hrtimer_mode_HRTIMER_MODE_PINNED,481481- HrTimerMode::Soft => hrtimer_mode_HRTIMER_MODE_SOFT,482482- HrTimerMode::Hard => hrtimer_mode_HRTIMER_MODE_HARD,483483- HrTimerMode::AbsolutePinned => hrtimer_mode_HRTIMER_MODE_ABS_PINNED,484484- HrTimerMode::RelativePinned => hrtimer_mode_HRTIMER_MODE_REL_PINNED,485485- HrTimerMode::AbsoluteSoft => hrtimer_mode_HRTIMER_MODE_ABS_SOFT,486486- HrTimerMode::RelativeSoft => hrtimer_mode_HRTIMER_MODE_REL_SOFT,487487- HrTimerMode::AbsolutePinnedSoft => hrtimer_mode_HRTIMER_MODE_ABS_PINNED_SOFT,488488- HrTimerMode::RelativePinnedSoft => hrtimer_mode_HRTIMER_MODE_REL_PINNED_SOFT,489489- HrTimerMode::AbsoluteHard => hrtimer_mode_HRTIMER_MODE_ABS_HARD,490490- HrTimerMode::RelativeHard => hrtimer_mode_HRTIMER_MODE_REL_HARD,491491- HrTimerMode::AbsolutePinnedHard => hrtimer_mode_HRTIMER_MODE_ABS_PINNED_HARD,492492- HrTimerMode::RelativePinnedHard => hrtimer_mode_HRTIMER_MODE_REL_PINNED_HARD,493493- }424424+impl<C: ClockSource> HrTimerExpires for Instant<C> {425425+ #[inline]426426+ fn as_nanos(&self) -> i64 {427427+ Instant::<C>::as_nanos(self)494428 }429429+}430430+431431+impl HrTimerExpires for Delta {432432+ #[inline]433433+ fn as_nanos(&self) -> i64 {434434+ Delta::as_nanos(*self)435435+ }436436+}437437+438438+mod private {439439+ use crate::time::ClockSource;440440+441441+ pub trait Sealed {}442442+443443+ impl<C: ClockSource> Sealed for super::AbsoluteMode<C> {}444444+ impl<C: ClockSource> Sealed for super::RelativeMode<C> {}445445+ impl<C: ClockSource> Sealed for super::AbsolutePinnedMode<C> {}446446+ impl<C: ClockSource> Sealed for super::RelativePinnedMode<C> {}447447+ impl<C: ClockSource> Sealed for super::AbsoluteSoftMode<C> {}448448+ impl<C: ClockSource> Sealed for super::RelativeSoftMode<C> {}449449+ impl<C: ClockSource> Sealed for super::AbsolutePinnedSoftMode<C> {}450450+ impl<C: ClockSource> Sealed for super::RelativePinnedSoftMode<C> {}451451+ impl<C: ClockSource> Sealed for super::AbsoluteHardMode<C> {}452452+ impl<C: ClockSource> Sealed for super::RelativeHardMode<C> {}453453+ impl<C: ClockSource> Sealed for super::AbsolutePinnedHardMode<C> {}454454+ impl<C: ClockSource> Sealed for super::RelativePinnedHardMode<C> {}455455+}456456+457457+/// Operational mode of [`HrTimer`].458458+pub trait HrTimerMode: private::Sealed {459459+ /// The C representation of hrtimer mode.460460+ const C_MODE: bindings::hrtimer_mode;461461+462462+ /// Type representing the clock source.463463+ type Clock: ClockSource;464464+465465+ /// Type representing the expiration specification (absolute or relative time).466466+ type Expires: HrTimerExpires;467467+}468468+469469+/// Timer that expires at a fixed point in time.470470+pub struct AbsoluteMode<C: ClockSource>(PhantomData<C>);471471+472472+impl<C: ClockSource> HrTimerMode for AbsoluteMode<C> {473473+ const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS;474474+475475+ type Clock = C;476476+ type Expires = Instant<C>;477477+}478478+479479+/// Timer that expires after a delay from now.480480+pub struct RelativeMode<C: ClockSource>(PhantomData<C>);481481+482482+impl<C: ClockSource> HrTimerMode for RelativeMode<C> {483483+ const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL;484484+485485+ type Clock = C;486486+ type Expires = Delta;487487+}488488+489489+/// Timer with absolute expiration time, pinned to its current CPU.490490+pub struct AbsolutePinnedMode<C: ClockSource>(PhantomData<C>);491491+impl<C: ClockSource> HrTimerMode for AbsolutePinnedMode<C> {492492+ const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_PINNED;493493+494494+ type Clock = C;495495+ type Expires = Instant<C>;496496+}497497+498498+/// Timer with relative expiration time, pinned to its current CPU.499499+pub struct RelativePinnedMode<C: ClockSource>(PhantomData<C>);500500+impl<C: ClockSource> HrTimerMode for RelativePinnedMode<C> {501501+ const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_PINNED;502502+503503+ type Clock = C;504504+ type Expires = Delta;505505+}506506+507507+/// Timer with absolute expiration, handled in soft irq context.508508+pub struct AbsoluteSoftMode<C: ClockSource>(PhantomData<C>);509509+impl<C: ClockSource> HrTimerMode for AbsoluteSoftMode<C> {510510+ const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_SOFT;511511+512512+ type Clock = C;513513+ type Expires = Instant<C>;514514+}515515+516516+/// Timer with relative expiration, handled in soft irq context.517517+pub struct RelativeSoftMode<C: ClockSource>(PhantomData<C>);518518+impl<C: ClockSource> HrTimerMode for RelativeSoftMode<C> {519519+ const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_SOFT;520520+521521+ type Clock = C;522522+ type Expires = Delta;523523+}524524+525525+/// Timer with absolute expiration, pinned to CPU and handled in soft irq context.526526+pub struct AbsolutePinnedSoftMode<C: ClockSource>(PhantomData<C>);527527+impl<C: ClockSource> HrTimerMode for AbsolutePinnedSoftMode<C> {528528+ const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_PINNED_SOFT;529529+530530+ type Clock = C;531531+ type Expires = Instant<C>;532532+}533533+534534+/// Timer with absolute expiration, pinned to CPU and handled in soft irq context.535535+pub struct RelativePinnedSoftMode<C: ClockSource>(PhantomData<C>);536536+impl<C: ClockSource> HrTimerMode for RelativePinnedSoftMode<C> {537537+ const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_PINNED_SOFT;538538+539539+ type Clock = C;540540+ type Expires = Delta;541541+}542542+543543+/// Timer with absolute expiration, handled in hard irq context.544544+pub struct AbsoluteHardMode<C: ClockSource>(PhantomData<C>);545545+impl<C: ClockSource> HrTimerMode for AbsoluteHardMode<C> {546546+ const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_HARD;547547+548548+ type Clock = C;549549+ type Expires = Instant<C>;550550+}551551+552552+/// Timer with relative expiration, handled in hard irq context.553553+pub struct RelativeHardMode<C: ClockSource>(PhantomData<C>);554554+impl<C: ClockSource> HrTimerMode for RelativeHardMode<C> {555555+ const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_HARD;556556+557557+ type Clock = C;558558+ type Expires = Delta;559559+}560560+561561+/// Timer with absolute expiration, pinned to CPU and handled in hard irq context.562562+pub struct AbsolutePinnedHardMode<C: ClockSource>(PhantomData<C>);563563+impl<C: ClockSource> HrTimerMode for AbsolutePinnedHardMode<C> {564564+ const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_PINNED_HARD;565565+566566+ type Clock = C;567567+ type Expires = Instant<C>;568568+}569569+570570+/// Timer with relative expiration, pinned to CPU and handled in hard irq context.571571+pub struct RelativePinnedHardMode<C: ClockSource>(PhantomData<C>);572572+impl<C: ClockSource> HrTimerMode for RelativePinnedHardMode<C> {573573+ const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_PINNED_HARD;574574+575575+ type Clock = C;576576+ type Expires = Delta;495577}496578497579/// Use to implement the [`HasHrTimer<T>`] trait.···596496 impl$({$($generics:tt)*})?597497 HasHrTimer<$timer_type:ty>598498 for $self:ty599599- { self.$field:ident }499499+ {500500+ mode : $mode:ty,501501+ field : self.$field:ident $(,)?502502+ }600503 $($rest:tt)*601504 ) => {602505 // SAFETY: This implementation of `raw_get_timer` only compiles if the603506 // field has the right type.604507 unsafe impl$(<$($generics)*>)? $crate::time::hrtimer::HasHrTimer<$timer_type> for $self {508508+ type TimerMode = $mode;605509606510 #[inline]607511 unsafe fn raw_get_timer(
+6-2
rust/kernel/time/hrtimer/arc.rs
···44use super::HrTimer;55use super::HrTimerCallback;66use super::HrTimerHandle;77+use super::HrTimerMode;78use super::HrTimerPointer;88-use super::Ktime;99use super::RawHrTimerCallback;1010use crate::sync::Arc;1111use crate::sync::ArcBorrow;···5454 T: HasHrTimer<T>,5555 T: for<'a> HrTimerCallback<Pointer<'a> = Self>,5656{5757+ type TimerMode = <T as HasHrTimer<T>>::TimerMode;5758 type TimerHandle = ArcHrTimerHandle<T>;58595959- fn start(self, expires: Ktime) -> ArcHrTimerHandle<T> {6060+ fn start(6161+ self,6262+ expires: <<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Expires,6363+ ) -> ArcHrTimerHandle<T> {6064 // SAFETY:6165 // - We keep `self` alive by wrapping it in a handle below.6266 // - Since we generate the pointer passed to `start` from a valid
+7-3
rust/kernel/time/hrtimer/pin.rs
···44use super::HrTimer;55use super::HrTimerCallback;66use super::HrTimerHandle;77-use super::Ktime;77+use super::HrTimerMode;88use super::RawHrTimerCallback;99use super::UnsafeHrTimerPointer;1010use core::pin::Pin;···5454 T: HasHrTimer<T>,5555 T: HrTimerCallback<Pointer<'a> = Self>,5656{5757+ type TimerMode = <T as HasHrTimer<T>>::TimerMode;5758 type TimerHandle = PinHrTimerHandle<'a, T>;58595959- unsafe fn start(self, expires: Ktime) -> Self::TimerHandle {6060+ unsafe fn start(6161+ self,6262+ expires: <<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Expires,6363+ ) -> Self::TimerHandle {6064 // Cast to pointer6165 let self_ptr: *const T = self.get_ref();6266···83798480 unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart {8581 // `HrTimer` is `repr(C)`8686- let timer_ptr = ptr as *mut HrTimer<T>;8282+ let timer_ptr = ptr.cast::<HrTimer<T>>();87838884 // SAFETY: By the safety requirement of this function, `timer_ptr`8985 // points to a `HrTimer<T>` contained in an `T`.
+7-3
rust/kernel/time/hrtimer/pin_mut.rs
···11// SPDX-License-Identifier: GPL-2.02233use super::{44- HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, Ktime, RawHrTimerCallback,44+ HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, HrTimerMode, RawHrTimerCallback,55 UnsafeHrTimerPointer,66};77use core::{marker::PhantomData, pin::Pin, ptr::NonNull};···5252 T: HasHrTimer<T>,5353 T: HrTimerCallback<Pointer<'a> = Self>,5454{5555+ type TimerMode = <T as HasHrTimer<T>>::TimerMode;5556 type TimerHandle = PinMutHrTimerHandle<'a, T>;56575757- unsafe fn start(mut self, expires: Ktime) -> Self::TimerHandle {5858+ unsafe fn start(5959+ mut self,6060+ expires: <<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Expires,6161+ ) -> Self::TimerHandle {5862 // SAFETY:5963 // - We promise not to move out of `self`. We only pass `self`6064 // back to the caller as a `Pin<&mut self>`.···87838884 unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart {8985 // `HrTimer` is `repr(C)`9090- let timer_ptr = ptr as *mut HrTimer<T>;8686+ let timer_ptr = ptr.cast::<HrTimer<T>>();91879288 // SAFETY: By the safety requirement of this function, `timer_ptr`9389 // points to a `HrTimer<T>` contained in an `T`.
+6-2
rust/kernel/time/hrtimer/tbox.rs
···44use super::HrTimer;55use super::HrTimerCallback;66use super::HrTimerHandle;77+use super::HrTimerMode;78use super::HrTimerPointer;88-use super::Ktime;99use super::RawHrTimerCallback;1010use crate::prelude::*;1111use core::ptr::NonNull;···6464 T: for<'a> HrTimerCallback<Pointer<'a> = Pin<Box<T, A>>>,6565 A: crate::alloc::Allocator,6666{6767+ type TimerMode = <T as HasHrTimer<T>>::TimerMode;6768 type TimerHandle = BoxHrTimerHandle<T, A>;68696969- fn start(self, expires: Ktime) -> Self::TimerHandle {7070+ fn start(7171+ self,7272+ expires: <<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Expires,7373+ ) -> Self::TimerHandle {7074 // SAFETY:7175 // - We will not move out of this box during timer callback (we pass an7276 // immutable reference to the callback).
+34-195
rust/kernel/types.rs
···2233//! Kernel types.4455+use crate::ffi::c_void;56use core::{67 cell::UnsafeCell,78 marker::{PhantomData, PhantomPinned},88- mem::{ManuallyDrop, MaybeUninit},99+ mem::MaybeUninit,910 ops::{Deref, DerefMut},1010- ptr::NonNull,1111};1212use pin_init::{PinInit, Wrapper, Zeroable};1313+1414+pub use crate::sync::aref::{ARef, AlwaysRefCounted};13151416/// Used to transfer ownership to and from foreign (non-Rust) languages.1517///···2321///2422/// # Safety2523///2626-/// Implementers must ensure that [`into_foreign`] returns a pointer which meets the alignment2727-/// requirements of [`PointedTo`].2828-///2929-/// [`into_foreign`]: Self::into_foreign3030-/// [`PointedTo`]: Self::PointedTo2424+/// - Implementations must satisfy the guarantees of [`Self::into_foreign`].3125pub unsafe trait ForeignOwnable: Sized {3232- /// Type used when the value is foreign-owned. In practical terms only defines the alignment of3333- /// the pointer.3434- type PointedTo;2626+ /// The alignment of pointers returned by `into_foreign`.2727+ const FOREIGN_ALIGN: usize;35283629 /// Type used to immutably borrow a value that is currently foreign-owned.3730 type Borrowed<'a>;···36393740 /// Converts a Rust-owned object to a foreign-owned one.3841 ///4242+ /// The foreign representation is a pointer to void. Aside from the guarantees listed below,4343+ /// there are no other guarantees for this pointer. For example, it might be invalid, dangling4444+ /// or pointing to uninitialized memory. Using it in any way except for [`from_foreign`],4545+ /// [`try_from_foreign`], [`borrow`], or [`borrow_mut`] can result in undefined behavior.4646+ ///3947 /// # Guarantees4048 ///4141- /// The return value is guaranteed to be well-aligned, but there are no other guarantees for4242- /// this pointer. For example, it might be null, dangling, or point to uninitialized memory.4343- /// Using it in any way except for [`ForeignOwnable::from_foreign`], [`ForeignOwnable::borrow`],4444- /// [`ForeignOwnable::try_from_foreign`] can result in undefined behavior.4949+ /// - Minimum alignment of returned pointer is [`Self::FOREIGN_ALIGN`].5050+ /// - The returned pointer is not null.4551 ///4652 /// [`from_foreign`]: Self::from_foreign4753 /// [`try_from_foreign`]: Self::try_from_foreign4854 /// [`borrow`]: Self::borrow4955 /// [`borrow_mut`]: Self::borrow_mut5050- fn into_foreign(self) -> *mut Self::PointedTo;5656+ fn into_foreign(self) -> *mut c_void;51575258 /// Converts a foreign-owned object back to a Rust-owned one.5359 ///···6060 /// must not be passed to `from_foreign` more than once.6161 ///6262 /// [`into_foreign`]: Self::into_foreign6363- unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self;6363+ unsafe fn from_foreign(ptr: *mut c_void) -> Self;64646565 /// Tries to convert a foreign-owned object back to a Rust-owned one.6666 ///···7272 /// `ptr` must either be null or satisfy the safety requirements for [`from_foreign`].7373 ///7474 /// [`from_foreign`]: Self::from_foreign7575- unsafe fn try_from_foreign(ptr: *mut Self::PointedTo) -> Option<Self> {7575+ unsafe fn try_from_foreign(ptr: *mut c_void) -> Option<Self> {7676 if ptr.is_null() {7777 None7878 } else {···9595 ///9696 /// [`into_foreign`]: Self::into_foreign9797 /// [`from_foreign`]: Self::from_foreign9898- unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> Self::Borrowed<'a>;9898+ unsafe fn borrow<'a>(ptr: *mut c_void) -> Self::Borrowed<'a>;9999100100 /// Borrows a foreign-owned object mutably.101101 ///···123123 /// [`from_foreign`]: Self::from_foreign124124 /// [`borrow`]: Self::borrow125125 /// [`Arc`]: crate::sync::Arc126126- unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> Self::BorrowedMut<'a>;126126+ unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> Self::BorrowedMut<'a>;127127}128128129129-// SAFETY: The `into_foreign` function returns a pointer that is dangling, but well-aligned.129129+// SAFETY: The pointer returned by `into_foreign` comes from a well aligned130130+// pointer to `()`.130131unsafe impl ForeignOwnable for () {131131- type PointedTo = ();132132+ const FOREIGN_ALIGN: usize = core::mem::align_of::<()>();132133 type Borrowed<'a> = ();133134 type BorrowedMut<'a> = ();134135135135- fn into_foreign(self) -> *mut Self::PointedTo {136136+ fn into_foreign(self) -> *mut c_void {136137 core::ptr::NonNull::dangling().as_ptr()137138 }138139139139- unsafe fn from_foreign(_: *mut Self::PointedTo) -> Self {}140140+ unsafe fn from_foreign(_: *mut c_void) -> Self {}140141141141- unsafe fn borrow<'a>(_: *mut Self::PointedTo) -> Self::Borrowed<'a> {}142142- unsafe fn borrow_mut<'a>(_: *mut Self::PointedTo) -> Self::BorrowedMut<'a> {}142142+ unsafe fn borrow<'a>(_: *mut c_void) -> Self::Borrowed<'a> {}143143+ unsafe fn borrow_mut<'a>(_: *mut c_void) -> Self::BorrowedMut<'a> {}143144}144145145146/// Runs a cleanup function/closure when dropped.···367366 // initialize the `T`.368367 unsafe {369368 pin_init::pin_init_from_closure::<_, ::core::convert::Infallible>(move |slot| {370370- init_func(Self::raw_get(slot));369369+ init_func(Self::cast_into(slot));371370 Ok(())372371 })373372 }···387386 // SAFETY: We contain a `MaybeUninit`, so it is OK for the `init_func` to not fully388387 // initialize the `T`.389388 unsafe {390390- pin_init::pin_init_from_closure::<_, E>(move |slot| init_func(Self::raw_get(slot)))389389+ pin_init::pin_init_from_closure::<_, E>(move |slot| init_func(Self::cast_into(slot)))391390 }392391 }393392···400399 ///401400 /// This function is useful to get access to the value without creating intermediate402401 /// references.403403- pub const fn raw_get(this: *const Self) -> *mut T {402402+ pub const fn cast_into(this: *const Self) -> *mut T {404403 UnsafeCell::raw_get(this.cast::<UnsafeCell<MaybeUninit<T>>>()).cast::<T>()404404+ }405405+406406+ /// The opposite operation of [`Opaque::cast_into`].407407+ pub const fn cast_from(this: *const T) -> *const Self {408408+ this.cast()405409 }406410}407411···421415 unsafe { PinInit::<T, E>::__pinned_init(slot, ptr) }422416 })423417 }424424-}425425-426426-/// Types that are _always_ reference counted.427427-///428428-/// It allows such types to define their own custom ref increment and decrement functions.429429-/// Additionally, it allows users to convert from a shared reference `&T` to an owned reference430430-/// [`ARef<T>`].431431-///432432-/// This is usually implemented by wrappers to existing structures on the C side of the code. For433433-/// Rust code, the recommendation is to use [`Arc`](crate::sync::Arc) to create reference-counted434434-/// instances of a type.435435-///436436-/// # Safety437437-///438438-/// Implementers must ensure that increments to the reference count keep the object alive in memory439439-/// at least until matching decrements are performed.440440-///441441-/// Implementers must also ensure that all instances are reference-counted. (Otherwise they442442-/// won't be able to honour the requirement that [`AlwaysRefCounted::inc_ref`] keep the object443443-/// alive.)444444-pub unsafe trait AlwaysRefCounted {445445- /// Increments the reference count on the object.446446- fn inc_ref(&self);447447-448448- /// Decrements the reference count on the object.449449- ///450450- /// Frees the object when the count reaches zero.451451- ///452452- /// # Safety453453- ///454454- /// Callers must ensure that there was a previous matching increment to the reference count,455455- /// and that the object is no longer used after its reference count is decremented (as it may456456- /// result in the object being freed), unless the caller owns another increment on the refcount457457- /// (e.g., it calls [`AlwaysRefCounted::inc_ref`] twice, then calls458458- /// [`AlwaysRefCounted::dec_ref`] once).459459- unsafe fn dec_ref(obj: NonNull<Self>);460460-}461461-462462-/// An owned reference to an always-reference-counted object.463463-///464464-/// The object's reference count is automatically decremented when an instance of [`ARef`] is465465-/// dropped. It is also automatically incremented when a new instance is created via466466-/// [`ARef::clone`].467467-///468468-/// # Invariants469469-///470470-/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`ARef`] instance. In471471-/// particular, the [`ARef`] instance owns an increment on the underlying object's reference count.472472-pub struct ARef<T: AlwaysRefCounted> {473473- ptr: NonNull<T>,474474- _p: PhantomData<T>,475475-}476476-477477-// SAFETY: It is safe to send `ARef<T>` to another thread when the underlying `T` is `Sync` because478478-// it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs479479-// `T` to be `Send` because any thread that has an `ARef<T>` may ultimately access `T` using a480480-// mutable reference, for example, when the reference count reaches zero and `T` is dropped.481481-unsafe impl<T: AlwaysRefCounted + Sync + Send> Send for ARef<T> {}482482-483483-// SAFETY: It is safe to send `&ARef<T>` to another thread when the underlying `T` is `Sync`484484-// because it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally,485485-// it needs `T` to be `Send` because any thread that has a `&ARef<T>` may clone it and get an486486-// `ARef<T>` on that thread, so the thread may ultimately access `T` using a mutable reference, for487487-// example, when the reference count reaches zero and `T` is dropped.488488-unsafe impl<T: AlwaysRefCounted + Sync + Send> Sync for ARef<T> {}489489-490490-impl<T: AlwaysRefCounted> ARef<T> {491491- /// Creates a new instance of [`ARef`].492492- ///493493- /// It takes over an increment of the reference count on the underlying object.494494- ///495495- /// # Safety496496- ///497497- /// Callers must ensure that the reference count was incremented at least once, and that they498498- /// are properly relinquishing one increment. That is, if there is only one increment, callers499499- /// must not use the underlying object anymore -- it is only safe to do so via the newly500500- /// created [`ARef`].501501- pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {502502- // INVARIANT: The safety requirements guarantee that the new instance now owns the503503- // increment on the refcount.504504- Self {505505- ptr,506506- _p: PhantomData,507507- }508508- }509509-510510- /// Consumes the `ARef`, returning a raw pointer.511511- ///512512- /// This function does not change the refcount. After calling this function, the caller is513513- /// responsible for the refcount previously managed by the `ARef`.514514- ///515515- /// # Examples516516- ///517517- /// ```518518- /// use core::ptr::NonNull;519519- /// use kernel::types::{ARef, AlwaysRefCounted};520520- ///521521- /// struct Empty {}522522- ///523523- /// # // SAFETY: TODO.524524- /// unsafe impl AlwaysRefCounted for Empty {525525- /// fn inc_ref(&self) {}526526- /// unsafe fn dec_ref(_obj: NonNull<Self>) {}527527- /// }528528- ///529529- /// let mut data = Empty {};530530- /// let ptr = NonNull::<Empty>::new(&mut data).unwrap();531531- /// # // SAFETY: TODO.532532- /// let data_ref: ARef<Empty> = unsafe { ARef::from_raw(ptr) };533533- /// let raw_ptr: NonNull<Empty> = ARef::into_raw(data_ref);534534- ///535535- /// assert_eq!(ptr, raw_ptr);536536- /// ```537537- pub fn into_raw(me: Self) -> NonNull<T> {538538- ManuallyDrop::new(me).ptr539539- }540540-}541541-542542-impl<T: AlwaysRefCounted> Clone for ARef<T> {543543- fn clone(&self) -> Self {544544- self.inc_ref();545545- // SAFETY: We just incremented the refcount above.546546- unsafe { Self::from_raw(self.ptr) }547547- }548548-}549549-550550-impl<T: AlwaysRefCounted> Deref for ARef<T> {551551- type Target = T;552552-553553- fn deref(&self) -> &Self::Target {554554- // SAFETY: The type invariants guarantee that the object is valid.555555- unsafe { self.ptr.as_ref() }556556- }557557-}558558-559559-impl<T: AlwaysRefCounted> From<&T> for ARef<T> {560560- fn from(b: &T) -> Self {561561- b.inc_ref();562562- // SAFETY: We just incremented the refcount above.563563- unsafe { Self::from_raw(NonNull::from(b)) }564564- }565565-}566566-567567-impl<T: AlwaysRefCounted> Drop for ARef<T> {568568- fn drop(&mut self) {569569- // SAFETY: The type invariants guarantee that the `ARef` owns the reference we're about to570570- // decrement.571571- unsafe { T::dec_ref(self.ptr) };572572- }573573-}574574-575575-/// A sum type that always holds either a value of type `L` or `R`.576576-///577577-/// # Examples578578-///579579-/// ```580580-/// use kernel::types::Either;581581-///582582-/// let left_value: Either<i32, &str> = Either::Left(7);583583-/// let right_value: Either<i32, &str> = Either::Right("right value");584584-/// ```585585-pub enum Either<L, R> {586586- /// Constructs an instance of [`Either`] containing a value of type `L`.587587- Left(L),588588-589589- /// Constructs an instance of [`Either`] containing a value of type `R`.590590- Right(R),591418}592419593420/// Zero-sized type to mark types not [`Send`].
+153-14
rust/kernel/uaccess.rs
···88 alloc::{Allocator, Flags},99 bindings,1010 error::Result,1111- ffi::c_void,1111+ ffi::{c_char, c_void},1212 prelude::*,1313 transmute::{AsBytes, FromBytes},1414};1515use core::mem::{size_of, MaybeUninit};16161717-/// The type used for userspace addresses.1818-pub type UserPtr = usize;1717+/// A pointer into userspace.1818+///1919+/// This is the Rust equivalent to C pointers tagged with `__user`.2020+#[repr(transparent)]2121+#[derive(Copy, Clone)]2222+pub struct UserPtr(*mut c_void);2323+2424+impl UserPtr {2525+ /// Create a `UserPtr` from an integer representing the userspace address.2626+ #[inline]2727+ pub fn from_addr(addr: usize) -> Self {2828+ Self(addr as *mut c_void)2929+ }3030+3131+ /// Create a `UserPtr` from a pointer representing the userspace address.3232+ #[inline]3333+ pub fn from_ptr(addr: *mut c_void) -> Self {3434+ Self(addr)3535+ }3636+3737+ /// Cast this userspace pointer to a raw const void pointer.3838+ ///3939+ /// It is up to the caller to use the returned pointer correctly.4040+ #[inline]4141+ pub fn as_const_ptr(self) -> *const c_void {4242+ self.04343+ }4444+4545+ /// Cast this userspace pointer to a raw mutable void pointer.4646+ ///4747+ /// It is up to the caller to use the returned pointer correctly.4848+ #[inline]4949+ pub fn as_mut_ptr(self) -> *mut c_void {5050+ self.05151+ }5252+5353+ /// Increment this user pointer by `add` bytes.5454+ ///5555+ /// This addition is wrapping, so wrapping around the address space does not result in a panic5656+ /// even if `CONFIG_RUST_OVERFLOW_CHECKS` is enabled.5757+ #[inline]5858+ pub fn wrapping_byte_add(self, add: usize) -> UserPtr {5959+ UserPtr(self.0.wrapping_byte_add(add))6060+ }6161+}19622063/// A pointer to an area in userspace memory, which can be either read-only or read-write.2164///···220177 pub fn skip(&mut self, num_skip: usize) -> Result {221178 // Update `self.length` first since that's the fallible part of this operation.222179 self.length = self.length.checked_sub(num_skip).ok_or(EFAULT)?;223223- self.ptr = self.ptr.wrapping_add(num_skip);180180+ self.ptr = self.ptr.wrapping_byte_add(num_skip);224181 Ok(())225182 }226183···267224 }268225 // SAFETY: `out_ptr` points into a mutable slice of length `len`, so we may write269226 // that many bytes to it.270270- let res = unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len) };227227+ let res = unsafe { bindings::copy_from_user(out_ptr, self.ptr.as_const_ptr(), len) };271228 if res != 0 {272229 return Err(EFAULT);273230 }274274- self.ptr = self.ptr.wrapping_add(len);231231+ self.ptr = self.ptr.wrapping_byte_add(len);275232 self.length -= len;276233 Ok(())277234 }···283240 pub fn read_slice(&mut self, out: &mut [u8]) -> Result {284241 // SAFETY: The types are compatible and `read_raw` doesn't write uninitialized bytes to285242 // `out`.286286- let out = unsafe { &mut *(out as *mut [u8] as *mut [MaybeUninit<u8>]) };243243+ let out = unsafe { &mut *(core::ptr::from_mut(out) as *mut [MaybeUninit<u8>]) };287244 self.read_raw(out)288245 }289246···305262 let res = unsafe {306263 bindings::_copy_from_user(307264 out.as_mut_ptr().cast::<c_void>(),308308- self.ptr as *const c_void,265265+ self.ptr.as_const_ptr(),309266 len,310267 )311268 };312269 if res != 0 {313270 return Err(EFAULT);314271 }315315- self.ptr = self.ptr.wrapping_add(len);272272+ self.ptr = self.ptr.wrapping_byte_add(len);316273 self.length -= len;317274 // SAFETY: The read above has initialized all bytes in `out`, and since `T` implements318275 // `FromBytes`, any bit-pattern is a valid value for this type.···333290 // vector have been initialized.334291 unsafe { buf.inc_len(len) };335292 Ok(())293293+ }294294+295295+ /// Read a NUL-terminated string from userspace and return it.296296+ ///297297+ /// The string is read into `buf` and a NUL-terminator is added if the end of `buf` is reached.298298+ /// Since there must be space to add a NUL-terminator, the buffer must not be empty. The299299+ /// returned `&CStr` points into `buf`.300300+ ///301301+ /// Fails with [`EFAULT`] if the read happens on a bad address (some data may have been302302+ /// copied).303303+ #[doc(alias = "strncpy_from_user")]304304+ pub fn strcpy_into_buf<'buf>(self, buf: &'buf mut [u8]) -> Result<&'buf CStr> {305305+ if buf.is_empty() {306306+ return Err(EINVAL);307307+ }308308+309309+ // SAFETY: The types are compatible and `strncpy_from_user` doesn't write uninitialized310310+ // bytes to `buf`.311311+ let mut dst = unsafe { &mut *(core::ptr::from_mut(buf) as *mut [MaybeUninit<u8>]) };312312+313313+ // We never read more than `self.length` bytes.314314+ if dst.len() > self.length {315315+ dst = &mut dst[..self.length];316316+ }317317+318318+ let mut len = raw_strncpy_from_user(dst, self.ptr)?;319319+ if len < dst.len() {320320+ // Add one to include the NUL-terminator.321321+ len += 1;322322+ } else if len < buf.len() {323323+ // This implies that `len == dst.len() < buf.len()`.324324+ //325325+ // This means that we could not fill the entire buffer, but we had to stop reading326326+ // because we hit the `self.length` limit of this `UserSliceReader`. Since we did not327327+ // fill the buffer, we treat this case as if we tried to read past the `self.length`328328+ // limit and received a page fault, which is consistent with other `UserSliceReader`329329+ // methods that also return page faults when you exceed `self.length`.330330+ return Err(EFAULT);331331+ } else {332332+ // This implies that `len == buf.len()`.333333+ //334334+ // This means that we filled the buffer exactly. In this case, we add a NUL-terminator335335+ // and return it. Unlike the `len < dst.len()` branch, don't modify `len` because it336336+ // already represents the length including the NUL-terminator.337337+ //338338+ // SAFETY: Due to the check at the beginning, the buffer is not empty.339339+ unsafe { *buf.last_mut().unwrap_unchecked() = 0 };340340+ }341341+342342+ // This method consumes `self`, so it can only be called once, thus we do not need to343343+ // update `self.length`. This sidesteps concerns such as whether `self.length` should be344344+ // incremented by `len` or `len-1` in the `len == buf.len()` case.345345+346346+ // SAFETY: There are two cases:347347+ // * If we hit the `len < dst.len()` case, then `raw_strncpy_from_user` guarantees that348348+ // this slice contains exactly one NUL byte at the end of the string.349349+ // * Otherwise, `raw_strncpy_from_user` guarantees that the string contained no NUL bytes,350350+ // and we have since added a NUL byte at the end.351351+ Ok(unsafe { CStr::from_bytes_with_nul_unchecked(&buf[..len]) })336352 }337353}338354···429327 }430328 // SAFETY: `data_ptr` points into an immutable slice of length `len`, so we may read431329 // that many bytes from it.432432- let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len) };330330+ let res = unsafe { bindings::copy_to_user(self.ptr.as_mut_ptr(), data_ptr, len) };433331 if res != 0 {434332 return Err(EFAULT);435333 }436436- self.ptr = self.ptr.wrapping_add(len);334334+ self.ptr = self.ptr.wrapping_byte_add(len);437335 self.length -= len;438336 Ok(())439337 }···456354 // is a compile-time constant.457355 let res = unsafe {458356 bindings::_copy_to_user(459459- self.ptr as *mut c_void,460460- (value as *const T).cast::<c_void>(),357357+ self.ptr.as_mut_ptr(),358358+ core::ptr::from_ref(value).cast::<c_void>(),461359 len,462360 )463361 };464362 if res != 0 {465363 return Err(EFAULT);466364 }467467- self.ptr = self.ptr.wrapping_add(len);365365+ self.ptr = self.ptr.wrapping_byte_add(len);468366 self.length -= len;469367 Ok(())470368 }369369+}370370+371371+/// Reads a nul-terminated string into `dst` and returns the length.372372+///373373+/// This reads from userspace until a NUL byte is encountered, or until `dst.len()` bytes have been374374+/// read. Fails with [`EFAULT`] if a read happens on a bad address (some data may have been375375+/// copied). When the end of the buffer is encountered, no NUL byte is added, so the string is376376+/// *not* guaranteed to be NUL-terminated when `Ok(dst.len())` is returned.377377+///378378+/// # Guarantees379379+///380380+/// When this function returns `Ok(len)`, it is guaranteed that the first `len` bytes of `dst` are381381+/// initialized and non-zero. Furthermore, if `len < dst.len()`, then `dst[len]` is a NUL byte.382382+#[inline]383383+fn raw_strncpy_from_user(dst: &mut [MaybeUninit<u8>], src: UserPtr) -> Result<usize> {384384+ // CAST: Slice lengths are guaranteed to be `<= isize::MAX`.385385+ let len = dst.len() as isize;386386+387387+ // SAFETY: `dst` is valid for writing `dst.len()` bytes.388388+ let res = unsafe {389389+ bindings::strncpy_from_user(390390+ dst.as_mut_ptr().cast::<c_char>(),391391+ src.as_const_ptr().cast::<c_char>(),392392+ len,393393+ )394394+ };395395+396396+ if res < 0 {397397+ return Err(Error::from_errno(res as i32));398398+ }399399+400400+ #[cfg(CONFIG_RUST_OVERFLOW_CHECKS)]401401+ assert!(res <= len);402402+403403+ // GUARANTEES: `strncpy_from_user` was successful, so `dst` has contents in accordance with the404404+ // guarantees of this function.405405+ Ok(res as usize)471406}
+333-9
rust/kernel/workqueue.rs
···2626//! * The [`WorkItemPointer`] trait is implemented for the pointer type that points at a something2727//! that implements [`WorkItem`].2828//!2929-//! ## Example2929+//! ## Examples3030//!3131//! This example defines a struct that holds an integer and can be scheduled on the workqueue. When3232//! the struct is executed, it will print the integer. Since there is only one `work_struct` field,···131131//! # print_2_later(MyStruct::new(41, 42).unwrap());132132//! ```133133//!134134+//! This example shows how you can schedule delayed work items:135135+//!136136+//! ```137137+//! use kernel::sync::Arc;138138+//! use kernel::workqueue::{self, impl_has_delayed_work, new_delayed_work, DelayedWork, WorkItem};139139+//!140140+//! #[pin_data]141141+//! struct MyStruct {142142+//! value: i32,143143+//! #[pin]144144+//! work: DelayedWork<MyStruct>,145145+//! }146146+//!147147+//! impl_has_delayed_work! {148148+//! impl HasDelayedWork<Self> for MyStruct { self.work }149149+//! }150150+//!151151+//! impl MyStruct {152152+//! fn new(value: i32) -> Result<Arc<Self>> {153153+//! Arc::pin_init(154154+//! pin_init!(MyStruct {155155+//! value,156156+//! work <- new_delayed_work!("MyStruct::work"),157157+//! }),158158+//! GFP_KERNEL,159159+//! )160160+//! }161161+//! }162162+//!163163+//! impl WorkItem for MyStruct {164164+//! type Pointer = Arc<MyStruct>;165165+//!166166+//! fn run(this: Arc<MyStruct>) {167167+//! pr_info!("The value is: {}\n", this.value);168168+//! }169169+//! }170170+//!171171+//! /// This method will enqueue the struct for execution on the system workqueue, where its value172172+//! /// will be printed 12 jiffies later.173173+//! fn print_later(val: Arc<MyStruct>) {174174+//! let _ = workqueue::system().enqueue_delayed(val, 12);175175+//! }176176+//!177177+//! /// It is also possible to use the ordinary `enqueue` method together with `DelayedWork`. This178178+//! /// is equivalent to calling `enqueue_delayed` with a delay of zero.179179+//! fn print_now(val: Arc<MyStruct>) {180180+//! let _ = workqueue::system().enqueue(val);181181+//! }182182+//! # print_later(MyStruct::new(42).unwrap());183183+//! # print_now(MyStruct::new(42).unwrap());184184+//! ```185185+//!134186//! C header: [`include/linux/workqueue.h`](srctree/include/linux/workqueue.h)135187136136-use crate::alloc::{AllocError, Flags};137137-use crate::{prelude::*, sync::Arc, sync::LockClassKey, types::Opaque};188188+use crate::{189189+ alloc::{AllocError, Flags},190190+ container_of,191191+ prelude::*,192192+ sync::Arc,193193+ sync::LockClassKey,194194+ time::Jiffies,195195+ types::Opaque,196196+};138197use core::marker::PhantomData;139198140199/// Creates a [`Work`] initialiser with the given name and a newly-created lock class.···204145 };205146}206147pub use new_work;148148+149149+/// Creates a [`DelayedWork`] initialiser with the given name and a newly-created lock class.150150+#[macro_export]151151+macro_rules! new_delayed_work {152152+ () => {153153+ $crate::workqueue::DelayedWork::new(154154+ $crate::optional_name!(),155155+ $crate::static_lock_class!(),156156+ $crate::c_str!(::core::concat!(157157+ ::core::file!(),158158+ ":",159159+ ::core::line!(),160160+ "_timer"161161+ )),162162+ $crate::static_lock_class!(),163163+ )164164+ };165165+ ($name:literal) => {166166+ $crate::workqueue::DelayedWork::new(167167+ $crate::c_str!($name),168168+ $crate::static_lock_class!(),169169+ $crate::c_str!(::core::concat!($name, "_timer")),170170+ $crate::static_lock_class!(),171171+ )172172+ };173173+}174174+pub use new_delayed_work;207175208176/// A kernel work queue.209177///···256170 pub unsafe fn from_raw<'a>(ptr: *const bindings::workqueue_struct) -> &'a Queue {257171 // SAFETY: The `Queue` type is `#[repr(transparent)]`, so the pointer cast is valid. The258172 // caller promises that the pointer is not dangling.259259- unsafe { &*(ptr as *const Queue) }173173+ unsafe { &*ptr.cast::<Queue>() }260174 }261175262176 /// Enqueues a work item.···284198 unsafe {285199 w.__enqueue(move |work_ptr| {286200 bindings::queue_work_on(287287- bindings::wq_misc_consts_WORK_CPU_UNBOUND as _,201201+ bindings::wq_misc_consts_WORK_CPU_UNBOUND as ffi::c_int,288202 queue_ptr,289203 work_ptr,204204+ )205205+ })206206+ }207207+ }208208+209209+ /// Enqueues a delayed work item.210210+ ///211211+ /// This may fail if the work item is already enqueued in a workqueue.212212+ ///213213+ /// The work item will be submitted using `WORK_CPU_UNBOUND`.214214+ pub fn enqueue_delayed<W, const ID: u64>(&self, w: W, delay: Jiffies) -> W::EnqueueOutput215215+ where216216+ W: RawDelayedWorkItem<ID> + Send + 'static,217217+ {218218+ let queue_ptr = self.0.get();219219+220220+ // SAFETY: We only return `false` if the `work_struct` is already in a workqueue. The other221221+ // `__enqueue` requirements are not relevant since `W` is `Send` and static.222222+ //223223+ // The call to `bindings::queue_delayed_work_on` will dereference the provided raw pointer,224224+ // which is ok because `__enqueue` guarantees that the pointer is valid for the duration of225225+ // this closure, and the safety requirements of `RawDelayedWorkItem` expands this226226+ // requirement to apply to the entire `delayed_work`.227227+ //228228+ // Furthermore, if the C workqueue code accesses the pointer after this call to229229+ // `__enqueue`, then the work item was successfully enqueued, and230230+ // `bindings::queue_delayed_work_on` will have returned true. In this case, `__enqueue`231231+ // promises that the raw pointer will stay valid until we call the function pointer in the232232+ // `work_struct`, so the access is ok.233233+ unsafe {234234+ w.__enqueue(move |work_ptr| {235235+ bindings::queue_delayed_work_on(236236+ bindings::wq_misc_consts_WORK_CPU_UNBOUND as ffi::c_int,237237+ queue_ptr,238238+ container_of!(work_ptr, bindings::delayed_work, work),239239+ delay,290240 )291241 })292242 }···419297 where420298 F: FnOnce(*mut bindings::work_struct) -> bool;421299}300300+301301+/// A raw delayed work item.302302+///303303+/// # Safety304304+///305305+/// If the `__enqueue` method in the `RawWorkItem` implementation calls the closure, then the306306+/// provided pointer must point at the `work` field of a valid `delayed_work`, and the guarantees307307+/// that `__enqueue` provides about accessing the `work_struct` must also apply to the rest of the308308+/// `delayed_work` struct.309309+pub unsafe trait RawDelayedWorkItem<const ID: u64>: RawWorkItem<ID> {}422310423311/// Defines the method that should be called directly when a work item is executed.424312///···535403 //536404 // A pointer cast would also be ok due to `#[repr(transparent)]`. We use `addr_of!` so that537405 // the compiler does not complain that the `work` field is unused.538538- unsafe { Opaque::raw_get(core::ptr::addr_of!((*ptr).work)) }406406+ unsafe { Opaque::cast_into(core::ptr::addr_of!((*ptr).work)) }539407 }540408}541409542542-/// Declares that a type has a [`Work<T, ID>`] field.410410+/// Declares that a type contains a [`Work<T, ID>`].543411///544412/// The intended way of using this trait is via the [`impl_has_work!`] macro. You can use the macro545413/// like this:···638506 impl{T} HasWork<Self> for ClosureWork<T> { self.work }639507}640508509509+/// Links for a delayed work item.510510+///511511+/// This struct contains a function pointer to the [`run`] function from the [`WorkItemPointer`]512512+/// trait, and defines the linked list pointers necessary to enqueue a work item in a workqueue in513513+/// a delayed manner.514514+///515515+/// Wraps the kernel's C `struct delayed_work`.516516+///517517+/// This is a helper type used to associate a `delayed_work` with the [`WorkItem`] that uses it.518518+///519519+/// [`run`]: WorkItemPointer::run520520+#[pin_data]521521+#[repr(transparent)]522522+pub struct DelayedWork<T: ?Sized, const ID: u64 = 0> {523523+ #[pin]524524+ dwork: Opaque<bindings::delayed_work>,525525+ _inner: PhantomData<T>,526526+}527527+528528+// SAFETY: Kernel work items are usable from any thread.529529+//530530+// We do not need to constrain `T` since the work item does not actually contain a `T`.531531+unsafe impl<T: ?Sized, const ID: u64> Send for DelayedWork<T, ID> {}532532+// SAFETY: Kernel work items are usable from any thread.533533+//534534+// We do not need to constrain `T` since the work item does not actually contain a `T`.535535+unsafe impl<T: ?Sized, const ID: u64> Sync for DelayedWork<T, ID> {}536536+537537+impl<T: ?Sized, const ID: u64> DelayedWork<T, ID> {538538+ /// Creates a new instance of [`DelayedWork`].539539+ #[inline]540540+ pub fn new(541541+ work_name: &'static CStr,542542+ work_key: Pin<&'static LockClassKey>,543543+ timer_name: &'static CStr,544544+ timer_key: Pin<&'static LockClassKey>,545545+ ) -> impl PinInit<Self>546546+ where547547+ T: WorkItem<ID>,548548+ {549549+ pin_init!(Self {550550+ dwork <- Opaque::ffi_init(|slot: *mut bindings::delayed_work| {551551+ // SAFETY: The `WorkItemPointer` implementation promises that `run` can be used as552552+ // the work item function.553553+ unsafe {554554+ bindings::init_work_with_key(555555+ core::ptr::addr_of_mut!((*slot).work),556556+ Some(T::Pointer::run),557557+ false,558558+ work_name.as_char_ptr(),559559+ work_key.as_ptr(),560560+ )561561+ }562562+563563+ // SAFETY: The `delayed_work_timer_fn` function pointer can be used here because564564+ // the timer is embedded in a `struct delayed_work`, and only ever scheduled via565565+ // the core workqueue code, and configured to run in irqsafe context.566566+ unsafe {567567+ bindings::timer_init_key(568568+ core::ptr::addr_of_mut!((*slot).timer),569569+ Some(bindings::delayed_work_timer_fn),570570+ bindings::TIMER_IRQSAFE,571571+ timer_name.as_char_ptr(),572572+ timer_key.as_ptr(),573573+ )574574+ }575575+ }),576576+ _inner: PhantomData,577577+ })578578+ }579579+580580+ /// Get a pointer to the inner `delayed_work`.581581+ ///582582+ /// # Safety583583+ ///584584+ /// The provided pointer must not be dangling and must be properly aligned. (But the memory585585+ /// need not be initialized.)586586+ #[inline]587587+ pub unsafe fn raw_as_work(ptr: *const Self) -> *mut Work<T, ID> {588588+ // SAFETY: The caller promises that the pointer is aligned and not dangling.589589+ let dw: *mut bindings::delayed_work =590590+ unsafe { Opaque::cast_into(core::ptr::addr_of!((*ptr).dwork)) };591591+ // SAFETY: The caller promises that the pointer is aligned and not dangling.592592+ let wrk: *mut bindings::work_struct = unsafe { core::ptr::addr_of_mut!((*dw).work) };593593+ // CAST: Work and work_struct have compatible layouts.594594+ wrk.cast()595595+ }596596+}597597+598598+/// Declares that a type contains a [`DelayedWork<T, ID>`].599599+///600600+/// # Safety601601+///602602+/// The `HasWork<T, ID>` implementation must return a `work_struct` that is stored in the `work`603603+/// field of a `delayed_work` with the same access rules as the `work_struct`.604604+pub unsafe trait HasDelayedWork<T, const ID: u64 = 0>: HasWork<T, ID> {}605605+606606+/// Used to safely implement the [`HasDelayedWork<T, ID>`] trait.607607+///608608+/// This macro also implements the [`HasWork`] trait, so you do not need to use [`impl_has_work!`]609609+/// when using this macro.610610+///611611+/// # Examples612612+///613613+/// ```614614+/// use kernel::sync::Arc;615615+/// use kernel::workqueue::{self, impl_has_delayed_work, DelayedWork};616616+///617617+/// struct MyStruct<'a, T, const N: usize> {618618+/// work_field: DelayedWork<MyStruct<'a, T, N>, 17>,619619+/// f: fn(&'a [T; N]),620620+/// }621621+///622622+/// impl_has_delayed_work! {623623+/// impl{'a, T, const N: usize} HasDelayedWork<MyStruct<'a, T, N>, 17>624624+/// for MyStruct<'a, T, N> { self.work_field }625625+/// }626626+/// ```627627+#[macro_export]628628+macro_rules! impl_has_delayed_work {629629+ ($(impl$({$($generics:tt)*})?630630+ HasDelayedWork<$work_type:ty $(, $id:tt)?>631631+ for $self:ty632632+ { self.$field:ident }633633+ )*) => {$(634634+ // SAFETY: The implementation of `raw_get_work` only compiles if the field has the right635635+ // type.636636+ unsafe impl$(<$($generics)+>)?637637+ $crate::workqueue::HasDelayedWork<$work_type $(, $id)?> for $self {}638638+639639+ // SAFETY: The implementation of `raw_get_work` only compiles if the field has the right640640+ // type.641641+ unsafe impl$(<$($generics)+>)? $crate::workqueue::HasWork<$work_type $(, $id)?> for $self {642642+ #[inline]643643+ unsafe fn raw_get_work(644644+ ptr: *mut Self645645+ ) -> *mut $crate::workqueue::Work<$work_type $(, $id)?> {646646+ // SAFETY: The caller promises that the pointer is not dangling.647647+ let ptr: *mut $crate::workqueue::DelayedWork<$work_type $(, $id)?> = unsafe {648648+ ::core::ptr::addr_of_mut!((*ptr).$field)649649+ };650650+651651+ // SAFETY: The caller promises that the pointer is not dangling.652652+ unsafe { $crate::workqueue::DelayedWork::raw_as_work(ptr) }653653+ }654654+655655+ #[inline]656656+ unsafe fn work_container_of(657657+ ptr: *mut $crate::workqueue::Work<$work_type $(, $id)?>,658658+ ) -> *mut Self {659659+ // SAFETY: The caller promises that the pointer points at a field of the right type660660+ // in the right kind of struct.661661+ let ptr = unsafe { $crate::workqueue::Work::raw_get(ptr) };662662+663663+ // SAFETY: The caller promises that the pointer points at a field of the right type664664+ // in the right kind of struct.665665+ let delayed_work = unsafe {666666+ $crate::container_of!(ptr, $crate::bindings::delayed_work, work)667667+ };668668+669669+ let delayed_work: *mut $crate::workqueue::DelayedWork<$work_type $(, $id)?> =670670+ delayed_work.cast();671671+672672+ // SAFETY: The caller promises that the pointer points at a field of the right type673673+ // in the right kind of struct.674674+ unsafe { $crate::container_of!(delayed_work, Self, $field) }675675+ }676676+ }677677+ )*};678678+}679679+pub use impl_has_delayed_work;680680+641681// SAFETY: The `__enqueue` implementation in RawWorkItem uses a `work_struct` initialized with the642682// `run` method of this trait as the function pointer because:643683// - `__enqueue` gets the `work_struct` from the `Work` field, using `T::raw_get_work`.···826522{827523 unsafe extern "C" fn run(ptr: *mut bindings::work_struct) {828524 // The `__enqueue` method always uses a `work_struct` stored in a `Work<T, ID>`.829829- let ptr = ptr as *mut Work<T, ID>;525525+ let ptr = ptr.cast::<Work<T, ID>>();830526 // SAFETY: This computes the pointer that `__enqueue` got from `Arc::into_raw`.831527 let ptr = unsafe { T::work_container_of(ptr) };832528 // SAFETY: This pointer comes from `Arc::into_raw` and we've been given back ownership.···871567 }872568}873569570570+// SAFETY: By the safety requirements of `HasDelayedWork`, the `work_struct` returned by methods in571571+// `HasWork` provides a `work_struct` that is the `work` field of a `delayed_work`, and the rest of572572+// the `delayed_work` has the same access rules as its `work` field.573573+unsafe impl<T, const ID: u64> RawDelayedWorkItem<ID> for Arc<T>574574+where575575+ T: WorkItem<ID, Pointer = Self>,576576+ T: HasDelayedWork<T, ID>,577577+{578578+}579579+874580// SAFETY: TODO.875581unsafe impl<T, const ID: u64> WorkItemPointer<ID> for Pin<KBox<T>>876582where···889575{890576 unsafe extern "C" fn run(ptr: *mut bindings::work_struct) {891577 // The `__enqueue` method always uses a `work_struct` stored in a `Work<T, ID>`.892892- let ptr = ptr as *mut Work<T, ID>;578578+ let ptr = ptr.cast::<Work<T, ID>>();893579 // SAFETY: This computes the pointer that `__enqueue` got from `Arc::into_raw`.894580 let ptr = unsafe { T::work_container_of(ptr) };895581 // SAFETY: This pointer comes from `Arc::into_raw` and we've been given back ownership.···929615 unsafe { ::core::hint::unreachable_unchecked() }930616 }931617 }618618+}619619+620620+// SAFETY: By the safety requirements of `HasDelayedWork`, the `work_struct` returned by methods in621621+// `HasWork` provides a `work_struct` that is the `work` field of a `delayed_work`, and the rest of622622+// the `delayed_work` has the same access rules as its `work` field.623623+unsafe impl<T, const ID: u64> RawDelayedWorkItem<ID> for Pin<KBox<T>>624624+where625625+ T: WorkItem<ID, Pointer = Self>,626626+ T: HasDelayedWork<T, ID>,627627+{932628}933629934630/// Returns the system work queue (`system_wq`).
+5-4
rust/kernel/xarray.rs
···77use crate::{88 alloc, bindings, build_assert,99 error::{Error, Result},1010+ ffi::c_void,1011 types::{ForeignOwnable, NotThreadSafe, Opaque},1112};1212-use core::{iter, marker::PhantomData, mem, pin::Pin, ptr::NonNull};1313+use core::{iter, marker::PhantomData, pin::Pin, ptr::NonNull};1314use pin_init::{pin_data, pin_init, pinned_drop, PinInit};14151516/// An array which efficiently maps sparse integer indices to owned objects.···102101 })103102 }104103105105- fn iter(&self) -> impl Iterator<Item = NonNull<T::PointedTo>> + '_ {104104+ fn iter(&self) -> impl Iterator<Item = NonNull<c_void>> + '_ {106105 let mut index = 0;107106108107 // SAFETY: `self.xa` is always valid by the type invariant.···180179impl<'a, T: ForeignOwnable> Guard<'a, T> {181180 fn load<F, U>(&self, index: usize, f: F) -> Option<U>182181 where183183- F: FnOnce(NonNull<T::PointedTo>) -> U,182182+ F: FnOnce(NonNull<c_void>) -> U,184183 {185184 // SAFETY: `self.xa.xa` is always valid by the type invariant.186185 let ptr = unsafe { bindings::xa_load(self.xa.xa.get(), index) };···231230 gfp: alloc::Flags,232231 ) -> Result<Option<T>, StoreError<T>> {233232 build_assert!(234234- mem::align_of::<T::PointedTo>() >= 4,233233+ T::FOREIGN_ALIGN >= 4,235234 "pointers stored in XArray must be 4-byte aligned"236235 );237236 let new = value.into_foreign();
-6
rust/macros/module.rs
···9494 type_: String,9595 license: String,9696 name: String,9797- author: Option<String>,9897 authors: Option<Vec<String>>,9998 description: Option<String>,10099 alias: Option<Vec<String>>,···107108 const EXPECTED_KEYS: &[&str] = &[108109 "type",109110 "name",110110- "author",111111 "authors",112112 "description",113113 "license",···132134 match key.as_str() {133135 "type" => info.type_ = expect_ident(it),134136 "name" => info.name = expect_string_ascii(it),135135- "author" => info.author = Some(expect_string(it)),136137 "authors" => info.authors = Some(expect_string_array(it)),137138 "description" => info.description = Some(expect_string(it)),138139 "license" => info.license = expect_string_ascii(it),···176179 // Rust does not allow hyphens in identifiers, use underscore instead.177180 let ident = info.name.replace('-', "_");178181 let mut modinfo = ModInfoBuilder::new(ident.as_ref());179179- if let Some(author) = info.author {180180- modinfo.emit("author", &author);181181- }182182 if let Some(authors) = info.authors {183183 for author in authors {184184 modinfo.emit("author", &author);
···33#![allow(clippy::undocumented_unsafe_blocks)]44#![cfg_attr(feature = "alloc", feature(allocator_api))]55#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]66+#![allow(unused_imports)]6778use core::{89 cell::{Cell, UnsafeCell},···1312 time::Duration,1413};1514use pin_init::*;1515+#[cfg(feature = "std")]1616use std::{1717 sync::Arc,1818 thread::{sleep, Builder},1919};20202121-#[expect(unused_attributes)]2121+#[allow(unused_attributes)]2222mod mutex;2323use mutex::*;2424···84828583pub static COUNT: StaticInit<CMutex<usize>, CountInit> = StaticInit::new(CountInit);86848787-#[cfg(not(any(feature = "std", feature = "alloc")))]8888-fn main() {}8989-9090-#[cfg(any(feature = "std", feature = "alloc"))]9185fn main() {9292- let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap();9393- let mut handles = vec![];9494- let thread_count = 20;9595- let workload = 1_000;9696- for i in 0..thread_count {9797- let mtx = mtx.clone();9898- handles.push(9999- Builder::new()100100- .name(format!("worker #{i}"))101101- .spawn(move || {102102- for _ in 0..workload {103103- *COUNT.lock() += 1;104104- std::thread::sleep(std::time::Duration::from_millis(10));105105- *mtx.lock() += 1;106106- std::thread::sleep(std::time::Duration::from_millis(10));107107- *COUNT.lock() += 1;108108- }109109- println!("{i} halfway");110110- sleep(Duration::from_millis((i as u64) * 10));111111- for _ in 0..workload {112112- std::thread::sleep(std::time::Duration::from_millis(10));113113- *mtx.lock() += 1;114114- }115115- println!("{i} finished");116116- })117117- .expect("should not fail"),118118- );8686+ #[cfg(feature = "std")]8787+ {8888+ let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap();8989+ let mut handles = vec![];9090+ let thread_count = 20;9191+ let workload = 1_000;9292+ for i in 0..thread_count {9393+ let mtx = mtx.clone();9494+ handles.push(9595+ Builder::new()9696+ .name(format!("worker #{i}"))9797+ .spawn(move || {9898+ for _ in 0..workload {9999+ *COUNT.lock() += 1;100100+ std::thread::sleep(std::time::Duration::from_millis(10));101101+ *mtx.lock() += 1;102102+ std::thread::sleep(std::time::Duration::from_millis(10));103103+ *COUNT.lock() += 1;104104+ }105105+ println!("{i} halfway");106106+ sleep(Duration::from_millis((i as u64) * 10));107107+ for _ in 0..workload {108108+ std::thread::sleep(std::time::Duration::from_millis(10));109109+ *mtx.lock() += 1;110110+ }111111+ println!("{i} finished");112112+ })113113+ .expect("should not fail"),114114+ );115115+ }116116+ for h in handles {117117+ h.join().expect("thread panicked");118118+ }119119+ println!("{:?}, {:?}", &*mtx.lock(), &*COUNT.lock());120120+ assert_eq!(*mtx.lock(), workload * thread_count * 2);119121 }120120- for h in handles {121121- h.join().expect("thread panicked");122122- }123123- println!("{:?}, {:?}", &*mtx.lock(), &*COUNT.lock());124124- assert_eq!(*mtx.lock(), workload * thread_count * 2);125122}
+1
rust/pin-init/src/__internal.rs
···188188}189189190190#[test]191191+#[cfg(feature = "std")]191192fn stack_init_reuse() {192193 use ::std::{borrow::ToOwned, println, string::String};193194 use core::pin::pin;
+104-16
rust/pin-init/src/lib.rs
···148148//! fn new() -> impl PinInit<Self, Error> {149149//! try_pin_init!(Self {150150//! status <- CMutex::new(0),151151-//! buffer: Box::init(pin_init::zeroed())?,151151+//! buffer: Box::init(pin_init::init_zeroed())?,152152//! }? Error)153153//! }154154//! }···742742/// - Fields that you want to initialize in-place have to use `<-` instead of `:`.743743/// - In front of the initializer you can write `&this in` to have access to a [`NonNull<Self>`]744744/// pointer named `this` inside of the initializer.745745-/// - Using struct update syntax one can place `..Zeroable::zeroed()` at the very end of the745745+/// - Using struct update syntax one can place `..Zeroable::init_zeroed()` at the very end of the746746/// struct, this initializes every field with 0 and then runs all initializers specified in the747747/// body. This can only be done if [`Zeroable`] is implemented for the struct.748748///···769769/// });770770/// let init = pin_init!(Buf {771771/// buf: [1; 64],772772-/// ..Zeroable::zeroed()772772+/// ..Zeroable::init_zeroed()773773/// });774774/// ```775775///···805805/// ```rust806806/// # #![feature(allocator_api)]807807/// # #[path = "../examples/error.rs"] mod error; use error::Error;808808-/// use pin_init::{pin_data, try_pin_init, PinInit, InPlaceInit, zeroed};808808+/// use pin_init::{pin_data, try_pin_init, PinInit, InPlaceInit, init_zeroed};809809///810810/// #[pin_data]811811/// struct BigBuf {···817817/// impl BigBuf {818818/// fn new() -> impl PinInit<Self, Error> {819819/// try_pin_init!(Self {820820-/// big: Box::init(zeroed())?,820820+/// big: Box::init(init_zeroed())?,821821/// small: [0; 1024 * 1024],822822/// ptr: core::ptr::null_mut(),823823/// }? Error)···866866/// # #[path = "../examples/error.rs"] mod error; use error::Error;867867/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;868868/// # use pin_init::InPlaceInit;869869-/// use pin_init::{init, Init, zeroed};869869+/// use pin_init::{init, Init, init_zeroed};870870///871871/// struct BigBuf {872872/// small: [u8; 1024 * 1024],···875875/// impl BigBuf {876876/// fn new() -> impl Init<Self> {877877/// init!(Self {878878-/// small <- zeroed(),878878+/// small <- init_zeroed(),879879/// })880880/// }881881/// }···913913/// # #![feature(allocator_api)]914914/// # use core::alloc::AllocError;915915/// # use pin_init::InPlaceInit;916916-/// use pin_init::{try_init, Init, zeroed};916916+/// use pin_init::{try_init, Init, init_zeroed};917917///918918/// struct BigBuf {919919/// big: Box<[u8; 1024 * 1024 * 1024]>,···923923/// impl BigBuf {924924/// fn new() -> impl Init<Self, AllocError> {925925/// try_init!(Self {926926-/// big: Box::init(zeroed())?,926926+/// big: Box::init(init_zeroed())?,927927/// small: [0; 1024 * 1024],928928/// }? AllocError)929929/// }···953953/// Asserts that a field on a struct using `#[pin_data]` is marked with `#[pin]` ie. that it is954954/// structurally pinned.955955///956956-/// # Example956956+/// # Examples957957///958958/// This will succeed:959959/// ```···11701170 ///11711171 /// ```rust11721172 /// # #![expect(clippy::disallowed_names)]11731173- /// use pin_init::{init, zeroed, Init};11731173+ /// use pin_init::{init, init_zeroed, Init};11741174 ///11751175 /// struct Foo {11761176 /// buf: [u8; 1_000_000],···11831183 /// }11841184 ///11851185 /// let foo = init!(Foo {11861186- /// buf <- zeroed()11861186+ /// buf <- init_zeroed()11871187 /// }).chain(|foo| {11881188 /// foo.setup();11891189 /// Ok(())···14951495/// ```rust,ignore14961496/// let val: Self = unsafe { core::mem::zeroed() };14971497/// ```14981498-pub unsafe trait Zeroable {}14981498+pub unsafe trait Zeroable {14991499+ /// Create a new zeroed `Self`.15001500+ ///15011501+ /// The returned initializer will write `0x00` to every byte of the given `slot`.15021502+ #[inline]15031503+ fn init_zeroed() -> impl Init<Self>15041504+ where15051505+ Self: Sized,15061506+ {15071507+ init_zeroed()15081508+ }15091509+15101510+ /// Create a `Self` consisting of all zeroes.15111511+ ///15121512+ /// Whenever a type implements [`Zeroable`], this function should be preferred over15131513+ /// [`core::mem::zeroed()`] or using `MaybeUninit<T>::zeroed().assume_init()`.15141514+ ///15151515+ /// # Examples15161516+ ///15171517+ /// ```15181518+ /// use pin_init::{Zeroable, zeroed};15191519+ ///15201520+ /// #[derive(Zeroable)]15211521+ /// struct Point {15221522+ /// x: u32,15231523+ /// y: u32,15241524+ /// }15251525+ ///15261526+ /// let point: Point = zeroed();15271527+ /// assert_eq!(point.x, 0);15281528+ /// assert_eq!(point.y, 0);15291529+ /// ```15301530+ fn zeroed() -> Self15311531+ where15321532+ Self: Sized,15331533+ {15341534+ zeroed()15351535+ }15361536+}1499153715001538/// Marker trait for types that allow `Option<Self>` to be set to all zeroes in order to write15011539/// `None` to that location.···15461508// SAFETY: by the safety requirement of `ZeroableOption`, this is valid.15471509unsafe impl<T: ZeroableOption> Zeroable for Option<T> {}1548151015491549-/// Create a new zeroed T.15111511+// SAFETY: `Option<&T>` is part of the option layout optimization guarantee:15121512+// <https://doc.rust-lang.org/stable/std/option/index.html#representation>.15131513+unsafe impl<T> ZeroableOption for &T {}15141514+// SAFETY: `Option<&mut T>` is part of the option layout optimization guarantee:15151515+// <https://doc.rust-lang.org/stable/std/option/index.html#representation>.15161516+unsafe impl<T> ZeroableOption for &mut T {}15171517+// SAFETY: `Option<NonNull<T>>` is part of the option layout optimization guarantee:15181518+// <https://doc.rust-lang.org/stable/std/option/index.html#representation>.15191519+unsafe impl<T> ZeroableOption for NonNull<T> {}15201520+15211521+/// Create an initializer for a zeroed `T`.15501522///15511523/// The returned initializer will write `0x00` to every byte of the given `slot`.15521524#[inline]15531553-pub fn zeroed<T: Zeroable>() -> impl Init<T> {15251525+pub fn init_zeroed<T: Zeroable>() -> impl Init<T> {15541526 // SAFETY: Because `T: Zeroable`, all bytes zero is a valid bit pattern for `T`15551527 // and because we write all zeroes, the memory is initialized.15561528 unsafe {···15691521 Ok(())15701522 })15711523 }15241524+}15251525+15261526+/// Create a `T` consisting of all zeroes.15271527+///15281528+/// Whenever a type implements [`Zeroable`], this function should be preferred over15291529+/// [`core::mem::zeroed()`] or using `MaybeUninit<T>::zeroed().assume_init()`.15301530+///15311531+/// # Examples15321532+///15331533+/// ```15341534+/// use pin_init::{Zeroable, zeroed};15351535+///15361536+/// #[derive(Zeroable)]15371537+/// struct Point {15381538+/// x: u32,15391539+/// y: u32,15401540+/// }15411541+///15421542+/// let point: Point = zeroed();15431543+/// assert_eq!(point.x, 0);15441544+/// assert_eq!(point.y, 0);15451545+/// ```15461546+pub const fn zeroed<T: Zeroable>() -> T {15471547+ // SAFETY:By the type invariants of `Zeroable`, all zeroes is a valid bit pattern for `T`.15481548+ unsafe { core::mem::zeroed() }15721549}1573155015741551macro_rules! impl_zeroable {···16331560 Option<NonZeroU128>, Option<NonZeroUsize>,16341561 Option<NonZeroI8>, Option<NonZeroI16>, Option<NonZeroI32>, Option<NonZeroI64>,16351562 Option<NonZeroI128>, Option<NonZeroIsize>,16361636- {<T>} Option<NonNull<T>>,1637156316381564 // SAFETY: `null` pointer is valid.16391565 //···16611589}1662159016631591impl_tuple_zeroable!(A, B, C, D, E, F, G, H, I, J);15921592+15931593+macro_rules! impl_fn_zeroable_option {15941594+ ([$($abi:literal),* $(,)?] $args:tt) => {15951595+ $(impl_fn_zeroable_option!({extern $abi} $args);)*15961596+ $(impl_fn_zeroable_option!({unsafe extern $abi} $args);)*15971597+ };15981598+ ({$($prefix:tt)*} {$(,)?}) => {};15991599+ ({$($prefix:tt)*} {$ret:ident, $($rest:ident),* $(,)?}) => {16001600+ // SAFETY: function pointers are part of the option layout optimization:16011601+ // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.16021602+ unsafe impl<$ret, $($rest),*> ZeroableOption for $($prefix)* fn($($rest),*) -> $ret {}16031603+ impl_fn_zeroable_option!({$($prefix)*} {$($rest),*,});16041604+ };16051605+}16061606+16071607+impl_fn_zeroable_option!(["Rust", "C"] { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U });1664160816651609/// This trait allows creating an instance of `Self` which contains exactly one16661610/// [structurally pinned value](https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning).
+8-8
rust/pin-init/src/macros.rs
···10301030///10311031/// This macro has multiple internal call configurations, these are always the very first ident:10321032/// - nothing: this is the base case and called by the `{try_}{pin_}init!` macros.10331033-/// - `with_update_parsed`: when the `..Zeroable::zeroed()` syntax has been handled.10331033+/// - `with_update_parsed`: when the `..Zeroable::init_zeroed()` syntax has been handled.10341034/// - `init_slot`: recursively creates the code that initializes all fields in `slot`.10351035/// - `make_initializer`: recursively create the struct initializer that guarantees that every10361036/// field has been initialized exactly once.···10591059 @data($data, $($use_data)?),10601060 @has_data($has_data, $get_data),10611061 @construct_closure($construct_closure),10621062- @zeroed(), // Nothing means default behavior.10621062+ @init_zeroed(), // Nothing means default behavior.10631063 )10641064 };10651065 (···10741074 @has_data($has_data:ident, $get_data:ident),10751075 // `pin_init_from_closure` or `init_from_closure`.10761076 @construct_closure($construct_closure:ident),10771077- @munch_fields(..Zeroable::zeroed()),10771077+ @munch_fields(..Zeroable::init_zeroed()),10781078 ) => {10791079 $crate::__init_internal!(with_update_parsed:10801080 @this($($this)?),···10841084 @data($data, $($use_data)?),10851085 @has_data($has_data, $get_data),10861086 @construct_closure($construct_closure),10871087- @zeroed(()), // `()` means zero all fields not mentioned.10871087+ @init_zeroed(()), // `()` means zero all fields not mentioned.10881088 )10891089 };10901090 (···11241124 @has_data($has_data:ident, $get_data:ident),11251125 // `pin_init_from_closure` or `init_from_closure`.11261126 @construct_closure($construct_closure:ident),11271127- @zeroed($($init_zeroed:expr)?),11271127+ @init_zeroed($($init_zeroed:expr)?),11281128 ) => {{11291129 // We do not want to allow arbitrary returns, so we declare this type as the `Ok` return11301130 // type and shadow it later when we insert the arbitrary user code. That way there will be···11961196 @data($data:ident),11971197 @slot($slot:ident),11981198 @guards($($guards:ident,)*),11991199- @munch_fields($(..Zeroable::zeroed())? $(,)?),11991199+ @munch_fields($(..Zeroable::init_zeroed())? $(,)?),12001200 ) => {12011201 // Endpoint of munching, no fields are left. If execution reaches this point, all fields12021202 // have been initialized. Therefore we can now dismiss the guards by forgetting them.···13001300 (make_initializer:13011301 @slot($slot:ident),13021302 @type_name($t:path),13031303- @munch_fields(..Zeroable::zeroed() $(,)?),13031303+ @munch_fields(..Zeroable::init_zeroed() $(,)?),13041304 @acc($($acc:tt)*),13051305 ) => {13061306 // Endpoint, nothing more to munch, create the initializer. Since the users specified13071307- // `..Zeroable::zeroed()`, the slot will already have been zeroed and all field that have13071307+ // `..Zeroable::init_zeroed()`, the slot will already have been zeroed and all field that have13081308 // not been overwritten are thus zero and initialized. We still check that all fields are13091309 // actually accessible by using the struct update syntax ourselves.13101310 // We are inside of a closure that is never executed and thus we can abuse `slot` to
···5454 measures the time taken to invoke one function a number of times.55555656config SAMPLE_TRACE_ARRAY5757- tristate "Build sample module for kernel access to Ftrace instancess"5757+ tristate "Build sample module for kernel access to Ftrace instances"5858 depends on EVENT_TRACING && m5959 help6060 This builds a module that demonstrates the use of various APIs to···316316 depends on DETECT_HUNG_TASK && DEBUG_FS317317 help318318 Build a module that provides debugfs files (e.g., mutex, semaphore,319319- etc.) under <debugfs>/hung_task. If user reads one of these files,320320- it will sleep long time (256 seconds) with holding a lock. Thus,321321- if 2 or more processes read the same file concurrently, it will322322- be detected by the hung_task watchdog.319319+ rw_semaphore_read, rw_semaphore_write) under <debugfs>/hung_task.320320+ Reading these files with multiple processes triggers hung task321321+ detection by holding locks for a long time (256 seconds).323322324323source "samples/rust/Kconfig"325324
+74-7
samples/hung_task/hung_task_tests.c
···44 * semaphore, etc.55 *66 * Usage: Load this module and read `<debugfs>/hung_task/mutex`,77- * `<debugfs>/hung_task/semaphore`, etc., with 2 or more processes.77+ * `<debugfs>/hung_task/semaphore`, `<debugfs>/hung_task/rw_semaphore_read`,88+ * `<debugfs>/hung_task/rw_semaphore_write`, etc., with 2 or more processes.89 *910 * This is for testing kernel hung_task error messages with various locking1010- * mechanisms (e.g., mutex, semaphore, etc.). Note that this may freeze1111- * your system or cause a panic. Use only for testing purposes.1111+ * mechanisms (e.g., mutex, semaphore, rw_semaphore_read, rw_semaphore_write, etc.).1212+ * Note that this may freeze your system or cause a panic. Use only for testing purposes.1213 */13141415#include <linux/debugfs.h>···1817#include <linux/module.h>1918#include <linux/mutex.h>2019#include <linux/semaphore.h>2020+#include <linux/rwsem.h>21212222-#define HUNG_TASK_DIR "hung_task"2323-#define HUNG_TASK_MUTEX_FILE "mutex"2424-#define HUNG_TASK_SEM_FILE "semaphore"2525-#define SLEEP_SECOND 2562222+#define HUNG_TASK_DIR "hung_task"2323+#define HUNG_TASK_MUTEX_FILE "mutex"2424+#define HUNG_TASK_SEM_FILE "semaphore"2525+#define HUNG_TASK_RWSEM_READ_FILE "rw_semaphore_read"2626+#define HUNG_TASK_RWSEM_WRITE_FILE "rw_semaphore_write"2727+#define SLEEP_SECOND 25626282729static const char dummy_string[] = "This is a dummy string.";2830static DEFINE_MUTEX(dummy_mutex);2931static DEFINE_SEMAPHORE(dummy_sem, 1);3232+static DECLARE_RWSEM(dummy_rwsem);3033static struct dentry *hung_task_dir;31343235/* Mutex-based read function */3336static ssize_t read_dummy_mutex(struct file *file, char __user *user_buf,3437 size_t count, loff_t *ppos)3538{3939+ /* Check if data is already read */4040+ if (*ppos >= sizeof(dummy_string))4141+ return 0;4242+3643 /* Second task waits on mutex, entering uninterruptible sleep */3744 guard(mutex)(&dummy_mutex);3845···5546static ssize_t read_dummy_semaphore(struct file *file, char __user *user_buf,5647 size_t count, loff_t *ppos)5748{4949+ /* Check if data is already read */5050+ if (*ppos >= sizeof(dummy_string))5151+ return 0;5252+5853 /* Second task waits on semaphore, entering uninterruptible sleep */5954 down(&dummy_sem);6055···6653 msleep_interruptible(SLEEP_SECOND * 1000);67546855 up(&dummy_sem);5656+5757+ return simple_read_from_buffer(user_buf, count, ppos, dummy_string,5858+ sizeof(dummy_string));5959+}6060+6161+/* Read-write semaphore read function */6262+static ssize_t read_dummy_rwsem_read(struct file *file, char __user *user_buf,6363+ size_t count, loff_t *ppos)6464+{6565+ /* Check if data is already read */6666+ if (*ppos >= sizeof(dummy_string))6767+ return 0;6868+6969+ /* Acquires read lock, allowing concurrent readers but blocks if write lock is held */7070+ down_read(&dummy_rwsem);7171+7272+ /* Sleeps here, potentially triggering hung task detection if lock is held too long */7373+ msleep_interruptible(SLEEP_SECOND * 1000);7474+7575+ up_read(&dummy_rwsem);7676+7777+ return simple_read_from_buffer(user_buf, count, ppos, dummy_string,7878+ sizeof(dummy_string));7979+}8080+8181+/* Read-write semaphore write function */8282+static ssize_t read_dummy_rwsem_write(struct file *file, char __user *user_buf,8383+ size_t count, loff_t *ppos)8484+{8585+ /* Check if data is already read */8686+ if (*ppos >= sizeof(dummy_string))8787+ return 0;8888+8989+ /* Acquires exclusive write lock, blocking all other readers and writers */9090+ down_write(&dummy_rwsem);9191+9292+ /* Sleeps here, potentially triggering hung task detection if lock is held too long */9393+ msleep_interruptible(SLEEP_SECOND * 1000);9494+9595+ up_write(&dummy_rwsem);69967097 return simple_read_from_buffer(user_buf, count, ppos, dummy_string,7198 sizeof(dummy_string));···12168 .read = read_dummy_semaphore,12269};123707171+/* File operations for rw_semaphore read */7272+static const struct file_operations hung_task_rwsem_read_fops = {7373+ .read = read_dummy_rwsem_read,7474+};7575+7676+/* File operations for rw_semaphore write */7777+static const struct file_operations hung_task_rwsem_write_fops = {7878+ .read = read_dummy_rwsem_write,7979+};8080+12481static int __init hung_task_tests_init(void)12582{12683 hung_task_dir = debugfs_create_dir(HUNG_TASK_DIR, NULL);···14279 &hung_task_mutex_fops);14380 debugfs_create_file(HUNG_TASK_SEM_FILE, 0400, hung_task_dir, NULL,14481 &hung_task_sem_fops);8282+ debugfs_create_file(HUNG_TASK_RWSEM_READ_FILE, 0400, hung_task_dir, NULL,8383+ &hung_task_rwsem_read_fops);8484+ debugfs_create_file(HUNG_TASK_RWSEM_WRITE_FILE, 0400, hung_task_dir, NULL,8585+ &hung_task_rwsem_write_fops);1458614687 return 0;14788}
+1-1
samples/rust/rust_configfs.rs
···1414module! {1515 type: RustConfigfs,1616 name: "rust_configfs",1717- author: "Rust for Linux Contributors",1717+ authors: ["Rust for Linux Contributors"],1818 description: "Rust configfs sample",1919 license: "GPL",2020}
···176176 fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: u32, arg: usize) -> Result<isize> {177177 dev_info!(me.dev, "IOCTLing Rust Misc Device Sample\n");178178179179+ // Treat the ioctl argument as a user pointer.180180+ let arg = UserPtr::from_addr(arg);179181 let size = _IOC_SIZE(cmd);180182181183 match cmd {
+1-1
samples/rust/rust_print_main.rs
···4040 // behaviour, contract or protocol on both `i32` and `&str` into a single `Arc` of4141 // type `Arc<dyn Display>`.42424343- use core::fmt::Display;4343+ use kernel::fmt::Display;4444 fn arc_dyn_print(arc: &Arc<dyn Display>) {4545 pr_info!("Arc<dyn Display> says {arc}");4646 }
+3-2
scripts/Makefile.build
···309309# The features in this list are the ones allowed for non-`rust/` code.310310#311311# - Stable since Rust 1.81.0: `feature(lint_reasons)`.312312-# - Stable since Rust 1.82.0: `feature(asm_const)`, `feature(raw_ref_op)`.312312+# - Stable since Rust 1.82.0: `feature(asm_const)`,313313+# `feature(offset_of_nested)`, `feature(raw_ref_op)`.313314# - Stable since Rust 1.87.0: `feature(asm_goto)`.314315# - Expected to become stable: `feature(arbitrary_self_types)`.315316# - To be determined: `feature(used_with_arg)`.316317#317318# Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on318319# the unstable features in use.319319-rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,raw_ref_op,used_with_arg320320+rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,offset_of_nested,raw_ref_op,used_with_arg320321321322# `--out-dir` is required to avoid temporaries being created by `rustc` in the322323# current working directory, which may be not accessible in the out-of-tree
+31-2
scripts/checkpatch.pl
···685685 [\.\!:\s]*686686)};687687688688+# Device ID types like found in include/linux/mod_devicetable.h.689689+our $dev_id_types = qr{\b[a-z]\w*_device_id\b};690690+688691sub edit_distance_min {689692 my (@arr) = @_;690693 my $len = scalar @arr;···35033500# Check for various typo / spelling mistakes35043501 if (defined($misspellings) &&35053502 ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {35063506- while ($rawline =~ /(?:^|[^\w\-'`])($misspellings)(?:[^\w\-'`]|$)/gi) {35033503+ my $rawline_utf8 = decode("utf8", $rawline);35043504+ while ($rawline_utf8 =~ /(?:^|[^\w\-'`])($misspellings)(?:[^\w\-'`]|$)/gi) {35073505 my $typo = $1;35083508- my $blank = copy_spacing($rawline);35063506+ my $blank = copy_spacing($rawline_utf8);35093507 my $ptr = substr($blank, 0, $-[1]) . "^" x length($typo);35103508 my $hereptr = "$hereline$ptr\n";35113509 my $typo_fix = $spelling_fix{lc($typo)};···76917687 if ($line =~ /\.extra[12]\s*=\s*&(zero|one|int_max)\b/) {76927688 WARN("DUPLICATED_SYSCTL_CONST",76937689 "duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr);76907690+ }76917691+76927692+# Check that *_device_id tables have sentinel entries.76937693+ if (defined $stat && $line =~ /struct\s+$dev_id_types\s+\w+\s*\[\s*\]\s*=\s*\{/) {76947694+ my $stripped = $stat;76957695+76967696+ # Strip diff line prefixes.76977697+ $stripped =~ s/(^|\n)./$1/g;76987698+ # Line continuations.76997699+ $stripped =~ s/\\\n/\n/g;77007700+ # Strip whitespace, empty strings, zeroes, and commas.77017701+ $stripped =~ s/""//g;77027702+ $stripped =~ s/0x0//g;77037703+ $stripped =~ s/[\s$;,0]//g;77047704+ # Strip field assignments.77057705+ $stripped =~ s/\.$Ident=//g;77067706+77077707+ if (!(substr($stripped, -4) eq "{}};" ||77087708+ substr($stripped, -6) eq "{{}}};" ||77097709+ $stripped =~ /ISAPNP_DEVICE_SINGLE_END}};$/ ||77107710+ $stripped =~ /ISAPNP_CARD_END}};$/ ||77117711+ $stripped =~ /NULL};$/ ||77127712+ $stripped =~ /PCMCIA_DEVICE_NULL};$/)) {77137713+ ERROR("MISSING_SENTINEL", "missing sentinel in ID array\n" . "$here\n$stat\n");77147714+ }76947715 }76957716 }76967717
···12121313check_vmlinux()1414{1515- # Use readelf to check if it's a valid ELF1616- # TODO: find a better to way to check that it's really vmlinux1717- # and not just an elf1818- readelf -h $1 > /dev/null 2>&1 || return 11919-2020- cat $12121- exit 01515+ if file "$1" | grep -q 'Linux kernel.*boot executable' ||1616+ readelf -h "$1" > /dev/null 2>&11717+ then1818+ cat "$1"1919+ exit 02020+ fi2221}23222423try_decompress()
···634634 * Note that the user of this feature is responsible for ensuring635635 * that the structure actually remains ABI compatible.636636 */637637- memset(&state.kabi, 0, sizeof(struct kabi_state));637637+ memset(&state.kabi, 0, sizeof(state.kabi));638638639639 res = checkp(process_die_container(&state, NULL, die,640640 check_union_member_kabi_status,
···7777 if (map2 == MAP_FAILED)7878 goto close2;79798080- if (bcmp(map1, map2, st1.st_size))8080+ if (memcmp(map1, map2, st1.st_size))8181 goto close2;82828383 ret = true;
+2-9
scripts/kconfig/gconf-cfg.sh
···66cflags=$177libs=$28899-PKG="gtk+-2.0 gmodule-2.0 libglade-2.0"99+PKG=gtk+-3.010101111if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then1212 echo >&2 "*"···1818if ! ${HOSTPKG_CONFIG} --exists $PKG; then1919 echo >&2 "*"2020 echo >&2 "* Unable to find the GTK+ installation. Please make sure that"2121- echo >&2 "* the GTK+ 2.0 development package is correctly installed."2121+ echo >&2 "* the GTK 3 development package is correctly installed."2222 echo >&2 "* You need $PKG"2323- echo >&2 "*"2424- exit 12525-fi2626-2727-if ! ${HOSTPKG_CONFIG} --atleast-version=2.0.0 gtk+-2.0; then2828- echo >&2 "*"2929- echo >&2 "* GTK+ is present but version >= 2.0.0 is required."3023 echo >&2 "*"3124 exit 13225fi
···9898bool menu_has_prompt(const struct menu *menu);9999const char *menu_get_prompt(const struct menu *menu);100100struct menu *menu_get_parent_menu(struct menu *menu);101101+struct menu *menu_get_menu_or_parent_menu(struct menu *menu);101102int get_jump_key_char(void);102103struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);103104void menu_get_ext_help(struct menu *menu, struct gstr *help);105105+void menu_dump(void);104106105107/* symbol.c */106108void sym_clear_all_valid(void);
···264264 if (key < 256 && isalpha(key))265265 key = tolower(key);266266267267- if (strchr("ynmh", key))267267+ if (strchr("ynmh ", key))268268 i = max_choice;269269 else {270270 for (i = choice + 1; i < max_choice; i++) {
+1-2
scripts/kconfig/lxdialog/util.c
···345345 int prompt_len, room, wlen;346346 char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0;347347348348- strcpy(tempstr, prompt);349349-348348+ snprintf(tempstr, sizeof(tempstr), "%s", prompt);350349 prompt_len = strlen(tempstr);351350352351 if (prompt_len <= width - x * 2) { /* If prompt is short */
+94
scripts/kconfig/menu.c
···575575 return NULL;576576}577577578578+/**579579+ * menu_get_parent_menu - return the parent menu or NULL580580+ * @menu: pointer to the menu581581+ * return: the parent menu, or NULL if there is no parent.582582+ */578583struct menu *menu_get_parent_menu(struct menu *menu)584584+{585585+ for (menu = menu->parent; menu; menu = menu->parent)586586+ if (menu->type == M_MENU)587587+ return menu;588588+589589+ return NULL;590590+}591591+592592+/**593593+ * menu_get_menu_or_parent_menu - return the parent menu or the menu itself594594+ * @menu: pointer to the menu595595+ * return: the parent menu. If the given argument is already a menu, return596596+ * itself.597597+ */598598+struct menu *menu_get_menu_or_parent_menu(struct menu *menu)579599{580600 enum prop_type type;581601···787767 str_printf(help, "%s\n", help_text);788768 if (sym)789769 get_symbol_str(help, sym, NULL);770770+}771771+772772+/**773773+ * menu_dump - dump all menu entries in a tree-like format774774+ */775775+void menu_dump(void)776776+{777777+ struct menu *menu = &rootmenu;778778+ unsigned long long bits = 0;779779+ int indent = 0;780780+781781+ while (menu) {782782+783783+ for (int i = indent - 1; i >= 0; i--) {784784+ if (bits & (1ULL << i)) {785785+ if (i > 0)786786+ printf("| ");787787+ else788788+ printf("|-- ");789789+ } else {790790+ if (i > 0)791791+ printf(" ");792792+ else793793+ printf("`-- ");794794+ }795795+ }796796+797797+ switch (menu->type) {798798+ case M_CHOICE:799799+ printf("choice \"%s\"\n", menu->prompt->text);800800+ break;801801+ case M_COMMENT:802802+ printf("comment \"%s\"\n", menu->prompt->text);803803+ break;804804+ case M_IF:805805+ printf("if\n");806806+ break;807807+ case M_MENU:808808+ printf("menu \"%s\"", menu->prompt->text);809809+ if (!menu->sym) {810810+ printf("\n");811811+ break;812812+ }813813+ printf(" + ");814814+ /* fallthrough */815815+ case M_NORMAL:816816+ printf("symbol %s\n", menu->sym->name);817817+ break;818818+ }819819+ if (menu->list) {820820+ bits <<= 1;821821+ menu = menu->list;822822+ if (menu->next)823823+ bits |= 1;824824+ else825825+ bits &= ~1;826826+ indent++;827827+ continue;828828+ }829829+830830+ while (menu && !menu->next) {831831+ menu = menu->parent;832832+ bits >>= 1;833833+ indent--;834834+ }835835+836836+ if (menu) {837837+ menu = menu->next;838838+ if (menu->next)839839+ bits |= 1;840840+ else841841+ bits &= ~1;842842+ }843843+ }790844}
···195195196196 list_for_each_entry(menu, &sym->menus, link)197197 menu->flags |= MENU_CHANGED;198198+199199+ menu = sym_get_choice_menu(sym);200200+ if (menu)201201+ menu->flags |= MENU_CHANGED;198202}199203200204static void sym_set_all_changed(void)
+16-15
scripts/rustdoc_test_gen.rs
···8585 }8686 }87878888- assert!(8989- valid_paths.len() > 0,9090- "No path candidates found for `{file}`. This is likely a bug in the build system, or some \9191- files went away while compiling."9292- );8888+ match valid_paths.as_slice() {8989+ [] => panic!(9090+ "No path candidates found for `{file}`. This is likely a bug in the build system, or \9191+ some files went away while compiling."9292+ ),9393+ [valid_path] => valid_path.to_str().unwrap(),9494+ valid_paths => {9595+ use std::fmt::Write;93969494- if valid_paths.len() > 1 {9595- eprintln!("Several path candidates found:");9696- for path in valid_paths {9797- eprintln!(" {path:?}");9797+ let mut candidates = String::new();9898+ for path in valid_paths {9999+ writeln!(&mut candidates, " {path:?}").unwrap();100100+ }101101+ panic!(102102+ "Several path candidates found for `{file}`, please resolve the ambiguity by \103103+ renaming a file or folder. Candidates:\n{candidates}",104104+ );98105 }9999- panic!(100100- "Several path candidates found for `{file}`, please resolve the ambiguity by renaming \101101- a file or folder."102102- );103106 }104104-105105- valid_paths[0].to_str().unwrap()106107}107108108109fn main() {
···11+// SPDX-License-Identifier: GPL-2.0-only22+/*33+ * AppArmor security module44+ *55+ * This file contains AppArmor af_unix fine grained mediation66+ *77+ * Copyright 2023 Canonical Ltd.88+ *99+ * This program is free software; you can redistribute it and/or1010+ * modify it under the terms of the GNU General Public License as1111+ * published by the Free Software Foundation, version 2 of the1212+ * License.1313+ */1414+1515+#include <linux/fs.h>1616+#include <net/tcp_states.h>1717+1818+#include "include/audit.h"1919+#include "include/af_unix.h"2020+#include "include/apparmor.h"2121+#include "include/file.h"2222+#include "include/label.h"2323+#include "include/path.h"2424+#include "include/policy.h"2525+#include "include/cred.h"2626+2727+2828+static inline struct sock *aa_unix_sk(struct unix_sock *u)2929+{3030+ return &u->sk;3131+}3232+3333+static int unix_fs_perm(const char *op, u32 mask, const struct cred *subj_cred,3434+ struct aa_label *label, struct path *path)3535+{3636+ AA_BUG(!label);3737+ AA_BUG(!path);3838+3939+ if (unconfined(label) || !label_mediates(label, AA_CLASS_FILE))4040+ return 0;4141+4242+ mask &= NET_FS_PERMS;4343+ /* if !u->path.dentry socket is being shutdown - implicit delegation4444+ * until obj delegation is supported4545+ */4646+ if (path->dentry) {4747+ /* the sunpath may not be valid for this ns so use the path */4848+ struct inode *inode = path->dentry->d_inode;4949+ vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_idmap(path->mnt), inode);5050+ struct path_cond cond = {5151+ .uid = vfsuid_into_kuid(vfsuid),5252+ .mode = inode->i_mode,5353+ };5454+5555+ return aa_path_perm(op, subj_cred, label, path,5656+ PATH_SOCK_COND, mask, &cond);5757+ } /* else implicitly delegated */5858+5959+ return 0;6060+}6161+6262+/* match_addr special constants */6363+#define ABSTRACT_ADDR "\x00" /* abstract socket addr */6464+#define ANONYMOUS_ADDR "\x01" /* anonymous endpoint, no addr */6565+#define DISCONNECTED_ADDR "\x02" /* addr is another namespace */6666+#define SHUTDOWN_ADDR "\x03" /* path addr is shutdown and cleared */6767+#define FS_ADDR "/" /* path addr in fs */6868+6969+static aa_state_t match_addr(struct aa_dfa *dfa, aa_state_t state,7070+ struct sockaddr_un *addr, int addrlen)7171+{7272+ if (addr)7373+ /* include leading \0 */7474+ state = aa_dfa_match_len(dfa, state, addr->sun_path,7575+ unix_addr_len(addrlen));7676+ else7777+ state = aa_dfa_match_len(dfa, state, ANONYMOUS_ADDR, 1);7878+ /* todo: could change to out of band for cleaner separation */7979+ state = aa_dfa_null_transition(dfa, state);8080+8181+ return state;8282+}8383+8484+static aa_state_t match_to_local(struct aa_policydb *policy,8585+ aa_state_t state, u32 request,8686+ int type, int protocol,8787+ struct sockaddr_un *addr, int addrlen,8888+ struct aa_perms **p,8989+ const char **info)9090+{9191+ state = aa_match_to_prot(policy, state, request, PF_UNIX, type,9292+ protocol, NULL, info);9393+ if (state) {9494+ state = match_addr(policy->dfa, state, addr, addrlen);9595+ if (state) {9696+ /* todo: local label matching */9797+ state = aa_dfa_null_transition(policy->dfa, state);9898+ if (!state)9999+ *info = "failed local label match";100100+ } else {101101+ *info = "failed local address match";102102+ }103103+ }104104+105105+ return state;106106+}107107+108108+struct sockaddr_un *aa_sunaddr(const struct unix_sock *u, int *addrlen)109109+{110110+ struct unix_address *addr;111111+112112+ /* memory barrier is sufficient see note in net/unix/af_unix.c */113113+ addr = smp_load_acquire(&u->addr);114114+ if (addr) {115115+ *addrlen = addr->len;116116+ return addr->name;117117+ }118118+ *addrlen = 0;119119+ return NULL;120120+}121121+122122+static aa_state_t match_to_sk(struct aa_policydb *policy,123123+ aa_state_t state, u32 request,124124+ struct unix_sock *u, struct aa_perms **p,125125+ const char **info)126126+{127127+ int addrlen;128128+ struct sockaddr_un *addr = aa_sunaddr(u, &addrlen);129129+130130+ return match_to_local(policy, state, request, u->sk.sk_type,131131+ u->sk.sk_protocol, addr, addrlen, p, info);132132+}133133+134134+#define CMD_ADDR 1135135+#define CMD_LISTEN 2136136+#define CMD_OPT 4137137+138138+static aa_state_t match_to_cmd(struct aa_policydb *policy, aa_state_t state,139139+ u32 request, struct unix_sock *u,140140+ char cmd, struct aa_perms **p,141141+ const char **info)142142+{143143+ AA_BUG(!p);144144+145145+ state = match_to_sk(policy, state, request, u, p, info);146146+ if (state && !*p) {147147+ state = aa_dfa_match_len(policy->dfa, state, &cmd, 1);148148+ if (!state)149149+ *info = "failed cmd selection match";150150+ }151151+152152+ return state;153153+}154154+155155+static aa_state_t match_to_peer(struct aa_policydb *policy, aa_state_t state,156156+ u32 request, struct unix_sock *u,157157+ struct sockaddr_un *peer_addr, int peer_addrlen,158158+ struct aa_perms **p, const char **info)159159+{160160+ AA_BUG(!p);161161+162162+ state = match_to_cmd(policy, state, request, u, CMD_ADDR, p, info);163163+ if (state && !*p) {164164+ state = match_addr(policy->dfa, state, peer_addr, peer_addrlen);165165+ if (!state)166166+ *info = "failed peer address match";167167+ }168168+169169+ return state;170170+}171171+172172+static aa_state_t match_label(struct aa_profile *profile,173173+ struct aa_ruleset *rule, aa_state_t state,174174+ u32 request, struct aa_profile *peer,175175+ struct aa_perms *p,176176+ struct apparmor_audit_data *ad)177177+{178178+ AA_BUG(!profile);179179+ AA_BUG(!peer);180180+181181+ ad->peer = &peer->label;182182+183183+ if (state && !p) {184184+ state = aa_dfa_match(rule->policy->dfa, state,185185+ peer->base.hname);186186+ if (!state)187187+ ad->info = "failed peer label match";188188+189189+ }190190+191191+ return aa_do_perms(profile, rule->policy, state, request, p, ad);192192+}193193+194194+195195+/* unix sock creation comes before we know if the socket will be an fs196196+ * socket197197+ * v6 - semantics are handled by mapping in profile load198198+ * v7 - semantics require sock create for tasks creating an fs socket.199199+ * v8 - same as v7200200+ */201201+static int profile_create_perm(struct aa_profile *profile, int family,202202+ int type, int protocol,203203+ struct apparmor_audit_data *ad)204204+{205205+ struct aa_ruleset *rules = profile->label.rules[0];206206+ aa_state_t state;207207+208208+ AA_BUG(!profile);209209+ AA_BUG(profile_unconfined(profile));210210+211211+ state = RULE_MEDIATES_v9NET(rules);212212+ if (state) {213213+ state = aa_match_to_prot(rules->policy, state, AA_MAY_CREATE,214214+ PF_UNIX, type, protocol, NULL,215215+ &ad->info);216216+217217+ return aa_do_perms(profile, rules->policy, state, AA_MAY_CREATE,218218+ NULL, ad);219219+ }220220+221221+ return aa_profile_af_perm(profile, ad, AA_MAY_CREATE, family, type,222222+ protocol);223223+}224224+225225+static int profile_sk_perm(struct aa_profile *profile,226226+ struct apparmor_audit_data *ad,227227+ u32 request, struct sock *sk, struct path *path)228228+{229229+ struct aa_ruleset *rules = profile->label.rules[0];230230+ struct aa_perms *p = NULL;231231+ aa_state_t state;232232+233233+ AA_BUG(!profile);234234+ AA_BUG(!sk);235235+ AA_BUG(profile_unconfined(profile));236236+237237+ state = RULE_MEDIATES_v9NET(rules);238238+ if (state) {239239+ if (is_unix_fs(sk))240240+ return unix_fs_perm(ad->op, request, ad->subj_cred,241241+ &profile->label,242242+ &unix_sk(sk)->path);243243+244244+ state = match_to_sk(rules->policy, state, request, unix_sk(sk),245245+ &p, &ad->info);246246+247247+ return aa_do_perms(profile, rules->policy, state, request, p,248248+ ad);249249+ }250250+251251+ return aa_profile_af_sk_perm(profile, ad, request, sk);252252+}253253+254254+static int profile_bind_perm(struct aa_profile *profile, struct sock *sk,255255+ struct apparmor_audit_data *ad)256256+{257257+ struct aa_ruleset *rules = profile->label.rules[0];258258+ struct aa_perms *p = NULL;259259+ aa_state_t state;260260+261261+ AA_BUG(!profile);262262+ AA_BUG(!sk);263263+ AA_BUG(!ad);264264+ AA_BUG(profile_unconfined(profile));265265+266266+ state = RULE_MEDIATES_v9NET(rules);267267+ if (state) {268268+ if (is_unix_addr_fs(ad->net.addr, ad->net.addrlen))269269+ /* under v7-9 fs hook handles bind */270270+ return 0;271271+ /* bind for abstract socket */272272+ state = match_to_local(rules->policy, state, AA_MAY_BIND,273273+ sk->sk_type, sk->sk_protocol,274274+ unix_addr(ad->net.addr),275275+ ad->net.addrlen,276276+ &p, &ad->info);277277+278278+ return aa_do_perms(profile, rules->policy, state, AA_MAY_BIND,279279+ p, ad);280280+ }281281+282282+ return aa_profile_af_sk_perm(profile, ad, AA_MAY_BIND, sk);283283+}284284+285285+static int profile_listen_perm(struct aa_profile *profile, struct sock *sk,286286+ int backlog, struct apparmor_audit_data *ad)287287+{288288+ struct aa_ruleset *rules = profile->label.rules[0];289289+ struct aa_perms *p = NULL;290290+ aa_state_t state;291291+292292+ AA_BUG(!profile);293293+ AA_BUG(!sk);294294+ AA_BUG(!ad);295295+ AA_BUG(profile_unconfined(profile));296296+297297+ state = RULE_MEDIATES_v9NET(rules);298298+ if (state) {299299+ __be16 b = cpu_to_be16(backlog);300300+301301+ if (is_unix_fs(sk))302302+ return unix_fs_perm(ad->op, AA_MAY_LISTEN,303303+ ad->subj_cred, &profile->label,304304+ &unix_sk(sk)->path);305305+306306+ state = match_to_cmd(rules->policy, state, AA_MAY_LISTEN,307307+ unix_sk(sk), CMD_LISTEN, &p, &ad->info);308308+ if (state && !p) {309309+ state = aa_dfa_match_len(rules->policy->dfa, state,310310+ (char *) &b, 2);311311+ if (!state)312312+ ad->info = "failed listen backlog match";313313+ }314314+ return aa_do_perms(profile, rules->policy, state, AA_MAY_LISTEN,315315+ p, ad);316316+ }317317+318318+ return aa_profile_af_sk_perm(profile, ad, AA_MAY_LISTEN, sk);319319+}320320+321321+static int profile_accept_perm(struct aa_profile *profile,322322+ struct sock *sk,323323+ struct apparmor_audit_data *ad)324324+{325325+ struct aa_ruleset *rules = profile->label.rules[0];326326+ struct aa_perms *p = NULL;327327+ aa_state_t state;328328+329329+ AA_BUG(!profile);330330+ AA_BUG(!sk);331331+ AA_BUG(!ad);332332+ AA_BUG(profile_unconfined(profile));333333+334334+ state = RULE_MEDIATES_v9NET(rules);335335+ if (state) {336336+ if (is_unix_fs(sk))337337+ return unix_fs_perm(ad->op, AA_MAY_ACCEPT,338338+ ad->subj_cred, &profile->label,339339+ &unix_sk(sk)->path);340340+341341+ state = match_to_sk(rules->policy, state, AA_MAY_ACCEPT,342342+ unix_sk(sk), &p, &ad->info);343343+344344+ return aa_do_perms(profile, rules->policy, state, AA_MAY_ACCEPT,345345+ p, ad);346346+ }347347+348348+ return aa_profile_af_sk_perm(profile, ad, AA_MAY_ACCEPT, sk);349349+}350350+351351+static int profile_opt_perm(struct aa_profile *profile, u32 request,352352+ struct sock *sk, int optname,353353+ struct apparmor_audit_data *ad)354354+{355355+ struct aa_ruleset *rules = profile->label.rules[0];356356+ struct aa_perms *p = NULL;357357+ aa_state_t state;358358+359359+ AA_BUG(!profile);360360+ AA_BUG(!sk);361361+ AA_BUG(!ad);362362+ AA_BUG(profile_unconfined(profile));363363+364364+ state = RULE_MEDIATES_v9NET(rules);365365+ if (state) {366366+ __be16 b = cpu_to_be16(optname);367367+ if (is_unix_fs(sk))368368+ return unix_fs_perm(ad->op, request,369369+ ad->subj_cred, &profile->label,370370+ &unix_sk(sk)->path);371371+372372+ state = match_to_cmd(rules->policy, state, request, unix_sk(sk),373373+ CMD_OPT, &p, &ad->info);374374+ if (state && !p) {375375+ state = aa_dfa_match_len(rules->policy->dfa, state,376376+ (char *) &b, 2);377377+ if (!state)378378+ ad->info = "failed sockopt match";379379+ }380380+ return aa_do_perms(profile, rules->policy, state, request, p,381381+ ad);382382+ }383383+384384+ return aa_profile_af_sk_perm(profile, ad, request, sk);385385+}386386+387387+/* null peer_label is allowed, in which case the peer_sk label is used */388388+static int profile_peer_perm(struct aa_profile *profile, u32 request,389389+ struct sock *sk, struct path *path,390390+ struct sockaddr_un *peer_addr,391391+ int peer_addrlen, struct path *peer_path,392392+ struct aa_label *peer_label,393393+ struct apparmor_audit_data *ad)394394+{395395+ struct aa_ruleset *rules = profile->label.rules[0];396396+ struct aa_perms *p = NULL;397397+ aa_state_t state;398398+399399+ AA_BUG(!profile);400400+ AA_BUG(profile_unconfined(profile));401401+ AA_BUG(!sk);402402+ AA_BUG(!peer_label);403403+ AA_BUG(!ad);404404+405405+ state = RULE_MEDIATES_v9NET(rules);406406+ if (state) {407407+ struct aa_profile *peerp;408408+409409+ if (peer_path)410410+ return unix_fs_perm(ad->op, request, ad->subj_cred,411411+ &profile->label, peer_path);412412+ else if (path)413413+ return unix_fs_perm(ad->op, request, ad->subj_cred,414414+ &profile->label, path);415415+ state = match_to_peer(rules->policy, state, request,416416+ unix_sk(sk),417417+ peer_addr, peer_addrlen, &p, &ad->info);418418+419419+ return fn_for_each_in_ns(peer_label, peerp,420420+ match_label(profile, rules, state, request,421421+ peerp, p, ad));422422+ }423423+424424+ return aa_profile_af_sk_perm(profile, ad, request, sk);425425+}426426+427427+/* -------------------------------- */428428+429429+int aa_unix_create_perm(struct aa_label *label, int family, int type,430430+ int protocol)431431+{432432+ if (!unconfined(label)) {433433+ struct aa_profile *profile;434434+ DEFINE_AUDIT_NET(ad, OP_CREATE, current_cred(), NULL, family,435435+ type, protocol);436436+437437+ return fn_for_each_confined(label, profile,438438+ profile_create_perm(profile, family, type,439439+ protocol, &ad));440440+ }441441+442442+ return 0;443443+}444444+445445+static int aa_unix_label_sk_perm(const struct cred *subj_cred,446446+ struct aa_label *label,447447+ const char *op, u32 request, struct sock *sk,448448+ struct path *path)449449+{450450+ if (!unconfined(label)) {451451+ struct aa_profile *profile;452452+ DEFINE_AUDIT_SK(ad, op, subj_cred, sk);453453+454454+ return fn_for_each_confined(label, profile,455455+ profile_sk_perm(profile, &ad, request, sk,456456+ path));457457+ }458458+ return 0;459459+}460460+461461+/* revalidation, get/set attr, shutdown */462462+int aa_unix_sock_perm(const char *op, u32 request, struct socket *sock)463463+{464464+ struct aa_label *label;465465+ int error;466466+467467+ label = begin_current_label_crit_section();468468+ error = aa_unix_label_sk_perm(current_cred(), label, op,469469+ request, sock->sk,470470+ is_unix_fs(sock->sk) ? &unix_sk(sock->sk)->path : NULL);471471+ end_current_label_crit_section(label);472472+473473+ return error;474474+}475475+476476+static int valid_addr(struct sockaddr *addr, int addr_len)477477+{478478+ struct sockaddr_un *sunaddr = unix_addr(addr);479479+480480+ /* addr_len == offsetof(struct sockaddr_un, sun_path) is autobind */481481+ if (addr_len < offsetof(struct sockaddr_un, sun_path) ||482482+ addr_len > sizeof(*sunaddr))483483+ return -EINVAL;484484+ return 0;485485+}486486+487487+int aa_unix_bind_perm(struct socket *sock, struct sockaddr *addr,488488+ int addrlen)489489+{490490+ struct aa_profile *profile;491491+ struct aa_label *label;492492+ int error = 0;493493+494494+ error = valid_addr(addr, addrlen);495495+ if (error)496496+ return error;497497+498498+ label = begin_current_label_crit_section();499499+ /* fs bind is handled by mknod */500500+ if (!unconfined(label)) {501501+ DEFINE_AUDIT_SK(ad, OP_BIND, current_cred(), sock->sk);502502+503503+ ad.net.addr = unix_addr(addr);504504+ ad.net.addrlen = addrlen;505505+506506+ error = fn_for_each_confined(label, profile,507507+ profile_bind_perm(profile, sock->sk, &ad));508508+ }509509+ end_current_label_crit_section(label);510510+511511+ return error;512512+}513513+514514+/*515515+ * unix connections are covered by the516516+ * - unix_stream_connect (stream) and unix_may_send hooks (dgram)517517+ * - fs connect is handled by open518518+ * This is just here to document this is not needed for af_unix519519+ *520520+int aa_unix_connect_perm(struct socket *sock, struct sockaddr *address,521521+ int addrlen)522522+{523523+ return 0;524524+}525525+*/526526+527527+int aa_unix_listen_perm(struct socket *sock, int backlog)528528+{529529+ struct aa_profile *profile;530530+ struct aa_label *label;531531+ int error = 0;532532+533533+ label = begin_current_label_crit_section();534534+ if (!unconfined(label)) {535535+ DEFINE_AUDIT_SK(ad, OP_LISTEN, current_cred(), sock->sk);536536+537537+ error = fn_for_each_confined(label, profile,538538+ profile_listen_perm(profile, sock->sk,539539+ backlog, &ad));540540+ }541541+ end_current_label_crit_section(label);542542+543543+ return error;544544+}545545+546546+547547+/* ability of sock to connect, not peer address binding */548548+int aa_unix_accept_perm(struct socket *sock, struct socket *newsock)549549+{550550+ struct aa_profile *profile;551551+ struct aa_label *label;552552+ int error = 0;553553+554554+ label = begin_current_label_crit_section();555555+ if (!unconfined(label)) {556556+ DEFINE_AUDIT_SK(ad, OP_ACCEPT, current_cred(), sock->sk);557557+558558+ error = fn_for_each_confined(label, profile,559559+ profile_accept_perm(profile, sock->sk, &ad));560560+ }561561+ end_current_label_crit_section(label);562562+563563+ return error;564564+}565565+566566+567567+/*568568+ * dgram handled by unix_may_sendmsg, right to send on stream done at connect569569+ * could do per msg unix_stream here, but connect + socket transfer is570570+ * sufficient. This is just here to document this is not needed for af_unix571571+ *572572+ * sendmsg, recvmsg573573+int aa_unix_msg_perm(const char *op, u32 request, struct socket *sock,574574+ struct msghdr *msg, int size)575575+{576576+ return 0;577577+}578578+*/579579+580580+int aa_unix_opt_perm(const char *op, u32 request, struct socket *sock,581581+ int level, int optname)582582+{583583+ struct aa_profile *profile;584584+ struct aa_label *label;585585+ int error = 0;586586+587587+ label = begin_current_label_crit_section();588588+ if (!unconfined(label)) {589589+ DEFINE_AUDIT_SK(ad, op, current_cred(), sock->sk);590590+591591+ error = fn_for_each_confined(label, profile,592592+ profile_opt_perm(profile, request, sock->sk,593593+ optname, &ad));594594+ }595595+ end_current_label_crit_section(label);596596+597597+ return error;598598+}599599+600600+static int unix_peer_perm(const struct cred *subj_cred,601601+ struct aa_label *label, const char *op, u32 request,602602+ struct sock *sk, struct path *path,603603+ struct sockaddr_un *peer_addr, int peer_addrlen,604604+ struct path *peer_path, struct aa_label *peer_label)605605+{606606+ struct aa_profile *profile;607607+ DEFINE_AUDIT_SK(ad, op, subj_cred, sk);608608+609609+ ad.net.peer.addr = peer_addr;610610+ ad.net.peer.addrlen = peer_addrlen;611611+612612+ return fn_for_each_confined(label, profile,613613+ profile_peer_perm(profile, request, sk, path,614614+ peer_addr, peer_addrlen, peer_path,615615+ peer_label, &ad));616616+}617617+618618+/**619619+ *620620+ * Requires: lock held on both @sk and @peer_sk621621+ * called by unix_stream_connect, unix_may_send622622+ */623623+int aa_unix_peer_perm(const struct cred *subj_cred,624624+ struct aa_label *label, const char *op, u32 request,625625+ struct sock *sk, struct sock *peer_sk,626626+ struct aa_label *peer_label)627627+{628628+ struct unix_sock *peeru = unix_sk(peer_sk);629629+ struct unix_sock *u = unix_sk(sk);630630+ int plen;631631+ struct sockaddr_un *paddr = aa_sunaddr(unix_sk(peer_sk), &plen);632632+633633+ AA_BUG(!label);634634+ AA_BUG(!sk);635635+ AA_BUG(!peer_sk);636636+ AA_BUG(!peer_label);637637+638638+ return unix_peer_perm(subj_cred, label, op, request, sk,639639+ is_unix_fs(sk) ? &u->path : NULL,640640+ paddr, plen,641641+ is_unix_fs(peer_sk) ? &peeru->path : NULL,642642+ peer_label);643643+}644644+645645+/* sk_plabel for comparison only */646646+static void update_sk_ctx(struct sock *sk, struct aa_label *label,647647+ struct aa_label *plabel)648648+{649649+ struct aa_label *l, *old;650650+ struct aa_sk_ctx *ctx = aa_sock(sk);651651+ bool update_sk;652652+653653+ rcu_read_lock();654654+ update_sk = (plabel &&655655+ (plabel != rcu_access_pointer(ctx->peer_lastupdate) ||656656+ !aa_label_is_subset(plabel, rcu_dereference(ctx->peer)))) ||657657+ !__aa_subj_label_is_cached(label, rcu_dereference(ctx->label));658658+ rcu_read_unlock();659659+ if (!update_sk)660660+ return;661661+662662+ spin_lock(&unix_sk(sk)->lock);663663+ old = rcu_dereference_protected(ctx->label,664664+ lockdep_is_held(&unix_sk(sk)->lock));665665+ l = aa_label_merge(old, label, GFP_ATOMIC);666666+ if (l) {667667+ if (l != old) {668668+ rcu_assign_pointer(ctx->label, l);669669+ aa_put_label(old);670670+ } else671671+ aa_put_label(l);672672+ }673673+ if (plabel && rcu_access_pointer(ctx->peer_lastupdate) != plabel) {674674+ old = rcu_dereference_protected(ctx->peer, lockdep_is_held(&unix_sk(sk)->lock));675675+676676+ if (old == plabel) {677677+ rcu_assign_pointer(ctx->peer_lastupdate, plabel);678678+ } else if (aa_label_is_subset(plabel, old)) {679679+ rcu_assign_pointer(ctx->peer_lastupdate, plabel);680680+ rcu_assign_pointer(ctx->peer, aa_get_label(plabel));681681+ aa_put_label(old);682682+ } /* else race or a subset - don't update */683683+ }684684+ spin_unlock(&unix_sk(sk)->lock);685685+}686686+687687+static void update_peer_ctx(struct sock *sk, struct aa_sk_ctx *ctx,688688+ struct aa_label *label)689689+{690690+ struct aa_label *l, *old;691691+692692+ spin_lock(&unix_sk(sk)->lock);693693+ old = rcu_dereference_protected(ctx->peer,694694+ lockdep_is_held(&unix_sk(sk)->lock));695695+ l = aa_label_merge(old, label, GFP_ATOMIC);696696+ if (l) {697697+ if (l != old) {698698+ rcu_assign_pointer(ctx->peer, l);699699+ aa_put_label(old);700700+ } else701701+ aa_put_label(l);702702+ }703703+ spin_unlock(&unix_sk(sk)->lock);704704+}705705+706706+/* This fn is only checked if something has changed in the security707707+ * boundaries. Otherwise cached info off file is sufficient708708+ */709709+int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label,710710+ const char *op, u32 request, struct file *file)711711+{712712+ struct socket *sock = (struct socket *) file->private_data;713713+ struct sockaddr_un *addr, *peer_addr;714714+ int addrlen, peer_addrlen;715715+ struct aa_label *plabel = NULL;716716+ struct sock *peer_sk = NULL;717717+ u32 sk_req = request & ~NET_PEER_MASK;718718+ struct path path;719719+ bool is_sk_fs;720720+ int error = 0;721721+722722+ AA_BUG(!label);723723+ AA_BUG(!sock);724724+ AA_BUG(!sock->sk);725725+ AA_BUG(sock->sk->sk_family != PF_UNIX);726726+727727+ /* investigate only using lock via unix_peer_get()728728+ * addr only needs the memory barrier, but need to investigate729729+ * path730730+ */731731+ unix_state_lock(sock->sk);732732+ peer_sk = unix_peer(sock->sk);733733+ if (peer_sk)734734+ sock_hold(peer_sk);735735+736736+ is_sk_fs = is_unix_fs(sock->sk);737737+ addr = aa_sunaddr(unix_sk(sock->sk), &addrlen);738738+ path = unix_sk(sock->sk)->path;739739+ unix_state_unlock(sock->sk);740740+741741+ if (is_sk_fs && peer_sk)742742+ sk_req = request;743743+ if (sk_req) {744744+ error = aa_unix_label_sk_perm(subj_cred, label, op,745745+ sk_req, sock->sk,746746+ is_sk_fs ? &path : NULL);747747+ }748748+ if (!peer_sk)749749+ goto out;750750+751751+ peer_addr = aa_sunaddr(unix_sk(peer_sk), &peer_addrlen);752752+753753+ struct path peer_path;754754+755755+ peer_path = unix_sk(peer_sk)->path;756756+ if (!is_sk_fs && is_unix_fs(peer_sk)) {757757+ last_error(error,758758+ unix_fs_perm(op, request, subj_cred, label,759759+ is_unix_fs(peer_sk) ? &peer_path : NULL));760760+ } else if (!is_sk_fs) {761761+ struct aa_label *plabel;762762+ struct aa_sk_ctx *pctx = aa_sock(peer_sk);763763+764764+ rcu_read_lock();765765+ plabel = aa_get_label_rcu(&pctx->label);766766+ rcu_read_unlock();767767+ /* no fs check of aa_unix_peer_perm because conditions above768768+ * ensure they will never be done769769+ */770770+ last_error(error,771771+ xcheck(unix_peer_perm(subj_cred, label, op,772772+ MAY_READ | MAY_WRITE, sock->sk,773773+ is_sk_fs ? &path : NULL,774774+ peer_addr, peer_addrlen,775775+ is_unix_fs(peer_sk) ?776776+ &peer_path : NULL,777777+ plabel),778778+ unix_peer_perm(file->f_cred, plabel, op,779779+ MAY_READ | MAY_WRITE, peer_sk,780780+ is_unix_fs(peer_sk) ?781781+ &peer_path : NULL,782782+ addr, addrlen,783783+ is_sk_fs ? &path : NULL,784784+ label)));785785+ if (!error && !__aa_subj_label_is_cached(plabel, label))786786+ update_peer_ctx(peer_sk, pctx, label);787787+ }788788+ sock_put(peer_sk);789789+790790+out:791791+792792+ /* update peer cache to latest successful perm check */793793+ if (error == 0)794794+ update_sk_ctx(sock->sk, label, plabel);795795+ aa_put_label(plabel);796796+797797+ return error;798798+}799799+
+28-11
security/apparmor/apparmorfs.c
···4343 * The interface is split into two main components based on their function4444 * a securityfs component:4545 * used for static files that are always available, and which allows4646- * userspace to specificy the location of the security filesystem.4646+ * userspace to specify the location of the security filesystem.4747 *4848 * fns and data are prefixed with4949 * aa_sfs_···204204/**205205 * __aafs_setup_d_inode - basic inode setup for apparmorfs206206 * @dir: parent directory for the dentry207207- * @dentry: dentry we are seting the inode up for207207+ * @dentry: dentry we are setting the inode up for208208 * @mode: permissions the file should have209209 * @data: data to store on inode.i_private, available in open()210210 * @link: if symlink, symlink target string···612612static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,613613 const char *match_str, size_t match_len)614614{615615- struct aa_ruleset *rules = list_first_entry(&profile->rules,616616- typeof(*rules), list);615615+ struct aa_ruleset *rules = profile->label.rules[0];617616 struct aa_perms tmp = { };618617 aa_state_t state = DFA_NOMATCH;619618···625626 if (state) {626627 struct path_cond cond = { };627628628628- tmp = *(aa_lookup_fperms(rules->file, state, &cond));629629+ tmp = *(aa_lookup_condperms(current_fsuid(),630630+ rules->file, state, &cond));629631 }630632 } else if (rules->policy->dfa) {631633 if (!RULE_MEDIATES(rules, *match_str))632634 return; /* no change to current perms */635635+ /* old user space does not correctly detect dbus mediation636636+ * support so we may get dbus policy and requests when637637+ * the abi doesn't support it. This can cause mediation638638+ * regressions, so explicitly test for this situation.639639+ */640640+ if (*match_str == AA_CLASS_DBUS &&641641+ !RULE_MEDIATES_v9NET(rules))642642+ return; /* no change to current perms */633643 state = aa_dfa_match_len(rules->policy->dfa,634644 rules->policy->start[0],635645 match_str, match_len);···10059971006998 switch (fs_file->v_type) {1007999 case AA_SFS_TYPE_BOOLEAN:10081008- seq_printf(seq, "%s\n", fs_file->v.boolean ? "yes" : "no");10001000+ seq_printf(seq, "%s\n", str_yes_no(fs_file->v.boolean));10091001 break;10101002 case AA_SFS_TYPE_STRING:10111003 seq_printf(seq, "%s\n", fs_file->v.string);···10141006 seq_printf(seq, "%#08lx\n", fs_file->v.u64);10151007 break;10161008 default:10171017- /* Ignore unpritable entry types. */10091009+ /* Ignore unprintable entry types. */10181010 break;10191011 }10201012···11601152 struct aa_label *label;1161115311621154 label = begin_current_label_crit_section();11631163- seq_printf(seq, "%s\n", label->size > 1 ? "yes" : "no");11551155+ seq_printf(seq, "%s\n", str_yes_no(label->size > 1));11641156 end_current_label_crit_section(label);1165115711661158 return 0;···11831175 }11841176 }1185117711861186- seq_printf(seq, "%s\n", count > 1 ? "yes" : "no");11781178+ seq_printf(seq, "%s\n", str_yes_no(count > 1));11871179 end_current_label_crit_section(label);1188118011891181 return 0;···22522244/**22532245 * p_stop - stop depth first traversal22542246 * @f: seq_file we are filling22552255- * @p: the last profile writen22472247+ * @p: the last profile written22562248 *22572249 * Release all locking done by p_start/p_next on namespace tree22582250 */···23402332static struct aa_sfs_entry aa_sfs_entry_domain[] = {23412333 AA_SFS_FILE_BOOLEAN("change_hat", 1),23422334 AA_SFS_FILE_BOOLEAN("change_hatv", 1),23352335+ AA_SFS_FILE_BOOLEAN("unconfined_allowed_children", 1),23432336 AA_SFS_FILE_BOOLEAN("change_onexec", 1),23442337 AA_SFS_FILE_BOOLEAN("change_profile", 1),23452338 AA_SFS_FILE_BOOLEAN("stack", 1),···23492340 AA_SFS_FILE_BOOLEAN("computed_longest_left", 1),23502341 AA_SFS_DIR("attach_conditions", aa_sfs_entry_attach),23512342 AA_SFS_FILE_BOOLEAN("disconnected.path", 1),23432343+ AA_SFS_FILE_BOOLEAN("kill.signal", 1),23522344 AA_SFS_FILE_STRING("version", "1.2"),23532345 { }23542346};···23742364 AA_SFS_FILE_BOOLEAN("set_load", 1),23752365 /* number of out of band transitions supported */23762366 AA_SFS_FILE_U64("outofband", MAX_OOB_SUPPORTED),23772377- AA_SFS_FILE_U64("permstable32_version", 1),23672367+ AA_SFS_FILE_U64("permstable32_version", 3),23782368 AA_SFS_FILE_STRING("permstable32", PERMS32STR),23792369 AA_SFS_FILE_U64("state32", 1),23802370 AA_SFS_DIR("unconfined_restrictions", aa_sfs_entry_unconfined),···23912381 AA_SFS_FILE_BOOLEAN("profile", 1),23922382 AA_SFS_FILE_BOOLEAN("pivot_root", 0),23932383 AA_SFS_FILE_STRING("mask", "userns_create"),23842384+ { }23852385+};23862386+23872387+static struct aa_sfs_entry aa_sfs_entry_dbus[] = {23882388+ AA_SFS_FILE_STRING("mask", "acquire send receive"),23942389 { }23952390};23962391···24212406 AA_SFS_DIR("domain", aa_sfs_entry_domain),24222407 AA_SFS_DIR("file", aa_sfs_entry_file),24232408 AA_SFS_DIR("network_v8", aa_sfs_entry_network),24092409+ AA_SFS_DIR("network_v9", aa_sfs_entry_networkv9),24242410 AA_SFS_DIR("mount", aa_sfs_entry_mount),24252411 AA_SFS_DIR("namespaces", aa_sfs_entry_ns),24262412 AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),···24292413 AA_SFS_DIR("caps", aa_sfs_entry_caps),24302414 AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace),24312415 AA_SFS_DIR("signal", aa_sfs_entry_signal),24162416+ AA_SFS_DIR("dbus", aa_sfs_entry_dbus),24322417 AA_SFS_DIR("query", aa_sfs_entry_query),24332418 AA_SFS_DIR("io_uring", aa_sfs_entry_io_uring),24342419 { }
···36363737extern struct aa_sfs_entry aa_sfs_entry_caps[];38383939+kernel_cap_t aa_profile_capget(struct aa_profile *profile);3940int aa_capable(const struct cred *subj_cred, struct aa_label *label,4041 int cap, unsigned int opts);4142
+24-7
security/apparmor/include/cred.h
···114114 return aa_get_label(l);115115}116116117117-#define __end_current_label_crit_section(X) end_current_label_crit_section(X)117117+/**118118+ * __end_current_label_crit_section - end crit section begun with __begin_...119119+ * @label: label obtained from __begin_current_label_crit_section120120+ * @needput: output: bool set by __begin_current_label_crit_section121121+ *122122+ * Returns: label to use for this crit section123123+ */124124+static inline void __end_current_label_crit_section(struct aa_label *label,125125+ bool needput)126126+{127127+ if (unlikely(needput))128128+ aa_put_label(label);129129+}118130119131/**120120- * end_label_crit_section - put a reference found with begin_current_label..132132+ * end_current_label_crit_section - put a reference found with begin_current_label..121133 * @label: label reference to put122134 *123135 * Should only be used with a reference obtained with···144132145133/**146134 * __begin_current_label_crit_section - current's confining label135135+ * @needput: store whether the label needs to be put when ending crit section147136 *148137 * Returns: up to date confining label or the ns unconfined label (NOT NULL)149138 *···155142 * critical section between __begin_current_label_crit_section() ..156143 * __end_current_label_crit_section()157144 */158158-static inline struct aa_label *__begin_current_label_crit_section(void)145145+static inline struct aa_label *__begin_current_label_crit_section(bool *needput)159146{160147 struct aa_label *label = aa_current_raw_label();161148162162- if (label_is_stale(label))163163- label = aa_get_newest_label(label);149149+ if (label_is_stale(label)) {150150+ *needput = true;151151+ return aa_get_newest_label(label);152152+ }164153154154+ *needput = false;165155 return label;166156}167157···200184{201185 struct aa_label *label;202186 struct aa_ns *ns;187187+ bool needput;203188204204- label = __begin_current_label_crit_section();189189+ label = __begin_current_label_crit_section(&needput);205190 ns = aa_get_ns(labels_ns(label));206206- __end_current_label_crit_section(label);191191+ __end_current_label_crit_section(label, needput);207192208193 return ns;209194}
···1919#include "lib.h"20202121struct aa_ns;2222+struct aa_ruleset;22232324#define LOCAL_VEC_ENTRIES 82425#define DEFINE_VEC(T, V) \···110109 int i, j;111110};112111113113-/* struct aa_label - lazy labeling struct112112+/* struct aa_label_base - base info of label114113 * @count: ref count of active users115114 * @node: rbtree position116115 * @rcu: rcu callback struct···119118 * @flags: stale and other flags - values may change under label set lock120119 * @secid: secid that references this label121120 * @size: number of entries in @ent[]122122- * @ent: set of profiles for label, actual size determined by @size121121+ * @mediates: bitmask for label_mediates122122+ * profile: label vec when embedded in a profile FLAG_PROFILE is set123123+ * rules: variable length rules in a profile FLAG_PROFILE is set124124+ * vec: vector of profiles comprising the compound label123125 */124126struct aa_label {125127 struct kref count;···133129 long flags;134130 u32 secid;135131 int size;136136- struct aa_profile *vec[];132132+ u64 mediates;133133+ union {134134+ struct {135135+ /* only used is the label is a profile, size of136136+ * rules[] is determined by the profile137137+ * profile[1] is poison or null as guard138138+ */139139+ struct aa_profile *profile[2];140140+ DECLARE_FLEX_ARRAY(struct aa_ruleset *, rules);141141+ };142142+ DECLARE_FLEX_ARRAY(struct aa_profile *, vec);143143+ };137144};138145139146#define last_error(E, FN) \···246231#define fn_for_each_not_in_set(L1, L2, P, FN) \247232 fn_for_each2_XXX((L1), (L2), P, FN, _not_in_set)248233249249-#define LABEL_MEDIATES(L, C) \250250-({ \251251- struct aa_profile *profile; \252252- struct label_it i; \253253- int ret = 0; \254254- label_for_each(i, (L), profile) { \255255- if (RULE_MEDIATES(&profile->rules, (C))) { \256256- ret = 1; \257257- break; \258258- } \259259- } \260260- ret; \261261-})234234+static inline bool label_mediates(struct aa_label *L, unsigned char C)235235+{236236+ return (L)->mediates & (((u64) 1) << (C));237237+}262238239239+static inline bool label_mediates_safe(struct aa_label *L, unsigned char C)240240+{241241+ if (C > AA_CLASS_LAST)242242+ return false;243243+ return label_mediates(L, C);244244+}263245264246void aa_labelset_destroy(struct aa_labelset *ls);265247void aa_labelset_init(struct aa_labelset *ls);···427415{428416 if (l)429417 kref_put(&l->count, aa_label_kref);418418+}419419+420420+/* wrapper fn to indicate semantics of the check */421421+static inline bool __aa_subj_label_is_cached(struct aa_label *subj_label,422422+ struct aa_label *obj_label)423423+{424424+ return aa_label_is_subset(obj_label, subj_label);430425}431426432427
+33-13
security/apparmor/include/lib.h
···1919extern struct aa_dfa *stacksplitdfa;20202121/*2222- * DEBUG remains global (no per profile flag) since it is mostly used in sysctl2323- * which is not related to profile accesses.2424- */2525-2626-#define DEBUG_ON (aa_g_debug)2727-/*2822 * split individual debug cases out in preparation for finer grained2923 * debug controls in the future.3024 */3131-#define AA_DEBUG_LABEL DEBUG_ON3225#define dbg_printk(__fmt, __args...) pr_debug(__fmt, ##__args)3333-#define AA_DEBUG(fmt, args...) \2626+2727+#define DEBUG_NONE 02828+#define DEBUG_LABEL_ABS_ROOT 12929+#define DEBUG_LABEL 23030+#define DEBUG_DOMAIN 43131+#define DEBUG_POLICY 83232+#define DEBUG_INTERFACE 0x103333+3434+#define DEBUG_ALL 0x1f /* update if new DEBUG_X added */3535+#define DEBUG_PARSE_ERROR (-1)3636+3737+#define DEBUG_ON (aa_g_debug != DEBUG_NONE)3838+#define DEBUG_ABS_ROOT (aa_g_debug & DEBUG_LABEL_ABS_ROOT)3939+4040+#define AA_DEBUG(opt, fmt, args...) \3441 do { \3535- if (DEBUG_ON) \3636- pr_debug_ratelimited("AppArmor: " fmt, ##args); \4242+ if (aa_g_debug & opt) \4343+ pr_warn_ratelimited("%s: " fmt, __func__, ##args); \3744 } while (0)4545+#define AA_DEBUG_LABEL(LAB, X, fmt, args...) \4646+do { \4747+ if ((LAB)->flags & FLAG_DEBUG1) \4848+ AA_DEBUG(X, fmt, args); \4949+} while (0)38503951#define AA_WARN(X) WARN((X), "APPARMOR WARN %s: %s\n", __func__, #X)4052···6048#define AA_BUG_FMT(X, fmt, args...) \6149 WARN((X), "AppArmor WARN %s: (" #X "): " fmt, __func__, ##args)6250#else6363-#define AA_BUG_FMT(X, fmt, args...) no_printk(fmt, ##args)5151+#define AA_BUG_FMT(X, fmt, args...) \5252+ do { \5353+ BUILD_BUG_ON_INVALID(X); \5454+ no_printk(fmt, ##args); \5555+ } while (0)6456#endif5757+5858+int aa_parse_debug_params(const char *str);5959+int aa_print_debug_params(char *buffer);65606661#define AA_ERROR(fmt, args...) \6762 pr_err_ratelimited("AppArmor: " fmt, ##args)···125106};126107127108void aa_free_str_table(struct aa_str_table *table);109109+bool aa_resize_str_table(struct aa_str_table *t, int newsize, gfp_t gfp);128110129111struct counted_str {130112 struct kref count;···171151172152/**173153 * basename - find the last component of an hname174174- * @name: hname to find the base profile name component of (NOT NULL)154154+ * @hname: hname to find the base profile name component of (NOT NULL)175155 *176156 * Returns: the tail (base profile name) name component of an hname177157 */···301281 } \302282__done: \303283 if (!__new_) \304304- AA_DEBUG("label build failed\n"); \284284+ AA_DEBUG(DEBUG_LABEL, "label build failed\n"); \305285 (__new_); \306286})307287
+4-6
security/apparmor/include/match.h
···1717#define DFA_START 1181819192020-/**2020+/*2121 * The format used for transition tables is based on the GNU flex table2222 * file format (--tables-file option; see Table File Format in the flex2323 * info pages and the flex sources for documentation). The magic number···137137138138void aa_dfa_free_kref(struct kref *kref);139139140140-#define WB_HISTORY_SIZE 24140140+/* This needs to be a power of 2 */141141+#define WB_HISTORY_SIZE 32141142struct match_workbuf {142142- unsigned int count;143143 unsigned int pos;144144 unsigned int len;145145- unsigned int size; /* power of 2, same as history size */146146- unsigned int history[WB_HISTORY_SIZE];145145+ aa_state_t history[WB_HISTORY_SIZE];147146};148147#define DEFINE_MATCH_WB(N) \149148struct match_workbuf N = { \150150- .count = 0, \151149 .pos = 0, \152150 .len = 0, \153151}
···13131414enum path_flags {1515 PATH_IS_DIR = 0x1, /* path is a directory */1616+ PATH_SOCK_COND = 0x2,1617 PATH_CONNECT_PATH = 0x4, /* connect disconnected paths to / */1718 PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */1819 PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */
+4-4
security/apparmor/include/perms.h
···101101102102/**103103 * aa_perms_accum_raw - accumulate perms with out masking off overlapping perms104104- * @accum - perms struct to accumulate into105105- * @addend - perms struct to add to @accum104104+ * @accum: perms struct to accumulate into105105+ * @addend: perms struct to add to @accum106106 */107107static inline void aa_perms_accum_raw(struct aa_perms *accum,108108 struct aa_perms *addend)···128128129129/**130130 * aa_perms_accum - accumulate perms, masking off overlapping perms131131- * @accum - perms struct to accumulate into132132- * @addend - perms struct to add to @accum131131+ * @accum: perms struct to accumulate into132132+ * @addend: perms struct to add to @accum133133 */134134static inline void aa_perms_accum(struct aa_perms *accum,135135 struct aa_perms *addend)
+45-18
security/apparmor/include/policy.h
···59596060#define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2)61616262+/* flags in the dfa accept2 table */6363+enum dfa_accept_flags {6464+ ACCEPT_FLAG_OWNER = 1,6565+};6666+6267/*6368 * FIXME: currently need a clean way to replace and remove profiles as a6469 * set. It should be done at the namespace level.···129124 kref_put(&pdb->count, aa_pdb_free_kref);130125}131126127127+/* lookup perm that doesn't have and object conditional */132128static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy,133129 aa_state_t state)134130{···140134141135 return &(policy->perms[index]);142136}143143-144137145138/* struct aa_data - generic data structure146139 * key: name for retrieving this data···165160 * @secmark: secmark label match info166161 */167162struct aa_ruleset {168168- struct list_head list;169169-170163 int size;171164172165 /* TODO: merge policy and file */···177174 int secmark_count;178175 struct aa_secmark *secmark;179176};177177+180178181179/* struct aa_attachment - data and rules for a profiles attachment182180 * @list:···197193198194/* struct aa_profile - basic confinement data199195 * @base - base components of the profile (name, refcount, lists, lock ...)200200- * @label - label this profile is an extension of201196 * @parent: parent of profile202197 * @ns: namespace the profile is in203198 * @rename: optional profile name that this profile renamed···204201 * @audit: the auditing mode of the profile205202 * @mode: the enforcement mode of the profile206203 * @path_flags: flags controlling path generation behavior204204+ * @signal: the signal that should be used when kill is used207205 * @disconnected: what to prepend if attach_disconnected is specified208206 * @attach: attachment rules for the profile209207 * @rules: rules to be enforced210208 *209209+ * learning_cache: the accesses learned in complain mode210210+ * raw_data: rawdata of the loaded profile policy211211+ * hash: cryptographic hash of the profile211212 * @dents: dentries for the profiles file entries in apparmorfs212213 * @dirname: name of the profile dir in apparmorfs214214+ * @dents: set of dentries associated with the profile213215 * @data: hashtable for free-form policy aa_data216216+ * @label - label this profile is an extension of217217+ * @rules - label with the rule vec on its end214218 *215219 * The AppArmor profile contains the basic confinement data. Each profile216220 * has a name, and exists in a namespace. The @name and @exec_match are···241231 enum audit_mode audit;242232 long mode;243233 u32 path_flags;234234+ int signal;244235 const char *disconnected;245236246237 struct aa_attachment attach;247247- struct list_head rules;248238249239 struct aa_loaddata *rawdata;250240 unsigned char *hash;251241 char *dirname;252242 struct dentry *dents[AAFS_PROF_SIZEOF];253243 struct rhashtable *data;244244+245245+ int n_rules;246246+ /* special - variable length must be last entry in profile */254247 struct aa_label label;255248};256249···311298 rules->policy->start[0], &class, 1);312299}313300314314-static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF)301301+static inline aa_state_t RULE_MEDIATES_v9NET(struct aa_ruleset *rules)315302{316316- aa_state_t state = RULE_MEDIATES(rules, AA_CLASS_NET);317317- __be16 be_af = cpu_to_be16(AF);318318-319319- if (!state)320320- return DFA_NOMATCH;321321- return aa_dfa_match_len(rules->policy->dfa, state, (char *) &be_af, 2);303303+ return RULE_MEDIATES(rules, AA_CLASS_NETV9);322304}323305324324-static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head,325325- unsigned char class)306306+static inline aa_state_t RULE_MEDIATES_NET(struct aa_ruleset *rules)326307{327327- struct aa_ruleset *rule;308308+ /* can not use RULE_MEDIATE_v9AF here, because AF match fail309309+ * can not be distiguished from class match fail, and we only310310+ * fallback to checking older class on class match failure311311+ */312312+ aa_state_t state = RULE_MEDIATES(rules, AA_CLASS_NETV9);328313329329- /* TODO: change to list walk */330330- rule = list_first_entry(head, typeof(*rule), list);331331- return RULE_MEDIATES(rule, class);314314+ /* fallback and check v7/8 if v9 is NOT mediated */315315+ if (!state)316316+ state = RULE_MEDIATES(rules, AA_CLASS_NET);317317+318318+ return state;319319+}320320+321321+322322+void aa_compute_profile_mediates(struct aa_profile *profile);323323+static inline bool profile_mediates(struct aa_profile *profile,324324+ unsigned char class)325325+{326326+ return label_mediates(&profile->label, class);327327+}328328+329329+static inline bool profile_mediates_safe(struct aa_profile *profile,330330+ unsigned char class)331331+{332332+ return label_mediates_safe(&profile->label, class);332333}333334334335/**
+1-5
security/apparmor/include/sig_names.h
···11#include <linux/signal.h>22-33-#define SIGUNKNOWN 044-#define MAXMAPPED_SIG 3555-#define MAXMAPPED_SIGNAME (MAXMAPPED_SIG + 1)66-#define SIGRT_BASE 12822+#include "signal.h"7384/* provide a mapping of arch signal to internal signal # for mediation95 * those that are always an alias SIGCLD for SIGCLHD and SIGPOLL for SIGIO
···88 * Copyright 2009-2017 Canonical Ltd.99 */10101111+#include "include/af_unix.h"1112#include "include/apparmor.h"1213#include "include/audit.h"1314#include "include/cred.h"···22212322struct aa_sfs_entry aa_sfs_entry_network[] = {2423 AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK),2424+ { }2525+};2626+2727+struct aa_sfs_entry aa_sfs_entry_networkv9[] = {2828+ AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK),2929+ AA_SFS_FILE_BOOLEAN("af_unix", 1),2530 { }2631};2732···7366 "unknown",7467};75686969+static void audit_unix_addr(struct audit_buffer *ab, const char *str,7070+ struct sockaddr_un *addr, int addrlen)7171+{7272+ int len = unix_addr_len(addrlen);7373+7474+ if (!addr || len <= 0) {7575+ audit_log_format(ab, " %s=none", str);7676+ } else if (addr->sun_path[0]) {7777+ audit_log_format(ab, " %s=", str);7878+ audit_log_untrustedstring(ab, addr->sun_path);7979+ } else {8080+ audit_log_format(ab, " %s=\"@", str);8181+ if (audit_string_contains_control(&addr->sun_path[1], len - 1))8282+ audit_log_n_hex(ab, &addr->sun_path[1], len - 1);8383+ else8484+ audit_log_format(ab, "%.*s", len - 1,8585+ &addr->sun_path[1]);8686+ audit_log_format(ab, "\"");8787+ }8888+}8989+9090+static void audit_unix_sk_addr(struct audit_buffer *ab, const char *str,9191+ const struct sock *sk)9292+{9393+ const struct unix_sock *u = unix_sk(sk);9494+9595+ if (u && u->addr) {9696+ int addrlen;9797+ struct sockaddr_un *addr = aa_sunaddr(u, &addrlen);9898+9999+ audit_unix_addr(ab, str, addr, addrlen);100100+ } else {101101+ audit_unix_addr(ab, str, NULL, 0);102102+103103+ }104104+}7610577106/* audit callback for net specific fields */78107void audit_net_cb(struct audit_buffer *ab, void *va)···11673 struct common_audit_data *sa = va;11774 struct apparmor_audit_data *ad = aad(sa);11875119119- if (address_family_names[sa->u.net->family])7676+ if (address_family_names[ad->common.u.net->family])12077 audit_log_format(ab, " family=\"%s\"",121121- address_family_names[sa->u.net->family]);7878+ address_family_names[ad->common.u.net->family]);12279 else12380 audit_log_format(ab, " family=\"unknown(%d)\"",124124- sa->u.net->family);8181+ ad->common.u.net->family);12582 if (sock_type_names[ad->net.type])12683 audit_log_format(ab, " sock_type=\"%s\"",12784 sock_type_names[ad->net.type]);···14198 net_mask_names, NET_PERMS_MASK);14299 }143100 }101101+ if (ad->common.u.net->family == PF_UNIX) {102102+ if (ad->net.addr || !ad->common.u.net->sk)103103+ audit_unix_addr(ab, "addr",104104+ unix_addr(ad->net.addr),105105+ ad->net.addrlen);106106+ else107107+ audit_unix_sk_addr(ab, "addr", ad->common.u.net->sk);108108+ if (ad->request & NET_PEER_MASK) {109109+ audit_unix_addr(ab, "peer_addr",110110+ unix_addr(ad->net.peer.addr),111111+ ad->net.peer.addrlen);112112+ }113113+ }144114 if (ad->peer) {145115 audit_log_format(ab, " peer=");146116 aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer,···161105 }162106}163107108108+/* standard permission lookup pattern - supports early bailout */109109+int aa_do_perms(struct aa_profile *profile, struct aa_policydb *policy,110110+ aa_state_t state, u32 request,111111+ struct aa_perms *p, struct apparmor_audit_data *ad)112112+{113113+ struct aa_perms perms;114114+115115+ AA_BUG(!profile);116116+ AA_BUG(!policy);117117+118118+119119+ if (state || !p)120120+ p = aa_lookup_perms(policy, state);121121+ perms = *p;122122+ aa_apply_modes_to_perms(profile, &perms);123123+ return aa_check_perms(profile, &perms, request, ad,124124+ audit_net_cb);125125+}126126+127127+/* only continue match if128128+ * insufficient current perms at current state129129+ * indicates there are more perms in later state130130+ * Returns: perms struct if early match131131+ */132132+static struct aa_perms *early_match(struct aa_policydb *policy,133133+ aa_state_t state, u32 request)134134+{135135+ struct aa_perms *p;136136+137137+ p = aa_lookup_perms(policy, state);138138+ if (((p->allow & request) != request) && (p->allow & AA_CONT_MATCH))139139+ return NULL;140140+ return p;141141+}142142+143143+static aa_state_t aa_dfa_match_be16(struct aa_dfa *dfa, aa_state_t state,144144+ u16 data)145145+{146146+ __be16 buffer = cpu_to_be16(data);147147+148148+ return aa_dfa_match_len(dfa, state, (char *) &buffer, 2);149149+}150150+151151+/**152152+ * aa_match_to_prot - match the af, type, protocol triplet153153+ * @policy: policy being matched154154+ * @state: state to start in155155+ * @request: permissions being requested, ignored if @p == NULL156156+ * @af: socket address family157157+ * @type: socket type158158+ * @protocol: socket protocol159159+ * @p: output - pointer to permission associated with match160160+ * @info: output - pointer to string describing failure161161+ *162162+ * RETURNS: state match stopped in.163163+ *164164+ * If @(p) is assigned a value the returned state will be the165165+ * corresponding state. Will not set @p on failure or if match completes166166+ * only if an early match occurs167167+ */168168+aa_state_t aa_match_to_prot(struct aa_policydb *policy, aa_state_t state,169169+ u32 request, u16 af, int type, int protocol,170170+ struct aa_perms **p, const char **info)171171+{172172+ state = aa_dfa_match_be16(policy->dfa, state, (u16)af);173173+ if (!state) {174174+ *info = "failed af match";175175+ return state;176176+ }177177+ state = aa_dfa_match_be16(policy->dfa, state, (u16)type);178178+ if (state) {179179+ if (p)180180+ *p = early_match(policy, state, request);181181+ if (!p || !*p) {182182+ state = aa_dfa_match_be16(policy->dfa, state, (u16)protocol);183183+ if (!state)184184+ *info = "failed protocol match";185185+ }186186+ } else {187187+ *info = "failed type match";188188+ }189189+190190+ return state;191191+}192192+164193/* Generic af perm */165194int aa_profile_af_perm(struct aa_profile *profile,166195 struct apparmor_audit_data *ad, u32 request, u16 family,167167- int type)196196+ int type, int protocol)168197{169169- struct aa_ruleset *rules = list_first_entry(&profile->rules,170170- typeof(*rules), list);171171- struct aa_perms perms = { };198198+ struct aa_ruleset *rules = profile->label.rules[0];199199+ struct aa_perms *p = NULL;172200 aa_state_t state;173173- __be16 buffer[2];174201175202 AA_BUG(family >= AF_MAX);176203 AA_BUG(type < 0 || type >= SOCK_MAX);204204+ AA_BUG(profile_unconfined(profile));177205178206 if (profile_unconfined(profile))179207 return 0;180180- state = RULE_MEDIATES(rules, AA_CLASS_NET);208208+ state = RULE_MEDIATES_NET(rules);181209 if (!state)182210 return 0;183183-184184- buffer[0] = cpu_to_be16(family);185185- buffer[1] = cpu_to_be16((u16) type);186186- state = aa_dfa_match_len(rules->policy->dfa, state, (char *) &buffer,187187- 4);188188- perms = *aa_lookup_perms(rules->policy, state);189189- aa_apply_modes_to_perms(profile, &perms);190190-191191- return aa_check_perms(profile, &perms, request, ad, audit_net_cb);211211+ state = aa_match_to_prot(rules->policy, state, request, family, type,212212+ protocol, &p, &ad->info);213213+ return aa_do_perms(profile, rules->policy, state, request, p, ad);192214}193215194216int aa_af_perm(const struct cred *subj_cred, struct aa_label *label,195217 const char *op, u32 request, u16 family, int type, int protocol)196218{197219 struct aa_profile *profile;198198- DEFINE_AUDIT_NET(ad, op, NULL, family, type, protocol);220220+ DEFINE_AUDIT_NET(ad, op, subj_cred, NULL, family, type, protocol);199221200222 return fn_for_each_confined(label, profile,201223 aa_profile_af_perm(profile, &ad, request, family,202202- type));224224+ type, protocol));203225}204226205227static int aa_label_sk_perm(const struct cred *subj_cred,···291157 AA_BUG(!label);292158 AA_BUG(!sk);293159294294- if (ctx->label != kernel_t && !unconfined(label)) {160160+ if (rcu_access_pointer(ctx->label) != kernel_t && !unconfined(label)) {295161 struct aa_profile *profile;296296- DEFINE_AUDIT_SK(ad, op, sk);162162+ DEFINE_AUDIT_SK(ad, op, subj_cred, sk);297163298164 ad.subj_cred = subj_cred;299165 error = fn_for_each_confined(label, profile,···321187322188323189int aa_sock_file_perm(const struct cred *subj_cred, struct aa_label *label,324324- const char *op, u32 request, struct socket *sock)190190+ const char *op, u32 request, struct file *file)325191{192192+ struct socket *sock = (struct socket *) file->private_data;193193+326194 AA_BUG(!label);327195 AA_BUG(!sock);328196 AA_BUG(!sock->sk);329197198198+ if (sock->sk->sk_family == PF_UNIX)199199+ return aa_unix_file_perm(subj_cred, label, op, request, file);330200 return aa_label_sk_perm(subj_cred, label, op, request, sock->sk);331201}332202···361223{362224 int i, ret;363225 struct aa_perms perms = { };364364- struct aa_ruleset *rules = list_first_entry(&profile->rules,365365- typeof(*rules), list);226226+ struct aa_ruleset *rules = profile->label.rules[0];366227367228 if (rules->secmark_count == 0)368229 return 0;···394257 u32 secid, const struct sock *sk)395258{396259 struct aa_profile *profile;397397- DEFINE_AUDIT_SK(ad, op, sk);260260+ DEFINE_AUDIT_SK(ad, op, NULL, sk);398261399262 return fn_for_each_confined(label, profile,400263 aa_secmark_perm(profile, request, secid,
+65-28
security/apparmor/policy.c
···243243{244244 int i;245245246246+ if (!rules)247247+ return;248248+246249 aa_put_pdb(rules->file);247250 aa_put_pdb(rules->policy);248251 aa_free_cap_rules(&rules->caps);···262259 struct aa_ruleset *rules;263260264261 rules = kzalloc(sizeof(*rules), gfp);265265- if (rules)266266- INIT_LIST_HEAD(&rules->list);267262268263 return rules;269264}···278277 */279278void aa_free_profile(struct aa_profile *profile)280279{281281- struct aa_ruleset *rule, *tmp;282280 struct rhashtable *rht;283281284284- AA_DEBUG("%s(%p)\n", __func__, profile);282282+ AA_DEBUG(DEBUG_POLICY, "%s(%p)\n", __func__, profile);285283286284 if (!profile)287285 return;···299299 * at this point there are no tasks that can have a reference300300 * to rules301301 */302302- list_for_each_entry_safe(rule, tmp, &profile->rules, list) {303303- list_del_init(&rule->list);304304- free_ruleset(rule);305305- }302302+ for (int i = 0; i < profile->n_rules; i++)303303+ free_ruleset(profile->label.rules[i]);304304+306305 kfree_sensitive(profile->dirname);307306308307 if (profile->data) {···330331 gfp_t gfp)331332{332333 struct aa_profile *profile;333333- struct aa_ruleset *rules;334334335335- /* freed by free_profile - usually through aa_put_profile */336336- profile = kzalloc(struct_size(profile, label.vec, 2), gfp);335335+ /* freed by free_profile - usually through aa_put_profile336336+ * this adds space for a single ruleset in the rules section of the337337+ * label338338+ */339339+ profile = kzalloc(struct_size(profile, label.rules, 1), gfp);337340 if (!profile)338341 return NULL;339342···344343 if (!aa_label_init(&profile->label, 1, gfp))345344 goto fail;346345347347- INIT_LIST_HEAD(&profile->rules);348348-349346 /* allocate the first ruleset, but leave it empty */350350- rules = aa_alloc_ruleset(gfp);351351- if (!rules)347347+ profile->label.rules[0] = aa_alloc_ruleset(gfp);348348+ if (!profile->label.rules[0])352349 goto fail;353353- list_add(&rules->list, &profile->rules);350350+ profile->n_rules = 1;354351355352 /* update being set needed by fs interface */356353 if (!proxy) {···363364 profile->label.flags |= FLAG_PROFILE;364365 profile->label.vec[0] = profile;365366367367+ profile->signal = SIGKILL;366368 /* refcount released by caller */367369 return profile;368370···371371 aa_free_profile(profile);372372373373 return NULL;374374+}375375+376376+static inline bool ANY_RULE_MEDIATES(struct aa_profile *profile,377377+ unsigned char class)378378+{379379+ int i;380380+381381+ for (i = 0; i < profile->n_rules; i++) {382382+ if (RULE_MEDIATES(profile->label.rules[i], class))383383+ return true;384384+ }385385+ return false;386386+}387387+388388+/* set of rules that are mediated by unconfined */389389+static int unconfined_mediates[] = { AA_CLASS_NS, AA_CLASS_IO_URING, 0 };390390+391391+/* must be called after profile rulesets and start information is setup */392392+void aa_compute_profile_mediates(struct aa_profile *profile)393393+{394394+ int c;395395+396396+ if (profile_unconfined(profile)) {397397+ int *pos;398398+399399+ for (pos = unconfined_mediates; *pos; pos++) {400400+ if (ANY_RULE_MEDIATES(profile, *pos))401401+ profile->label.mediates |= ((u64) 1) << AA_CLASS_NS;402402+ }403403+ return;404404+ }405405+ for (c = 0; c <= AA_CLASS_LAST; c++) {406406+ if (ANY_RULE_MEDIATES(profile, c))407407+ profile->label.mediates |= ((u64) 1) << c;408408+ }374409}375410376411/* TODO: profile accounting - setup in remove */···498463}499464500465/**501501- * __create_missing_ancestors - create place holders for missing ancestores466466+ * __create_missing_ancestors - create place holders for missing ancestors502467 * @ns: namespace to lookup profile in (NOT NULL)503468 * @hname: hierarchical profile name to find parent of (NOT NULL)504469 * @gfp: type of allocation.···656621 /* TODO: ideally we should inherit abi from parent */657622 profile->label.flags |= FLAG_NULL;658623 profile->attach.xmatch = aa_get_pdb(nullpdb);659659- rules = list_first_entry(&profile->rules, typeof(*rules), list);624624+ rules = profile->label.rules[0];660625 rules->file = aa_get_pdb(nullpdb);661626 rules->policy = aa_get_pdb(nullpdb);627627+ aa_compute_profile_mediates(profile);662628663629 if (parent) {664630 profile->path_flags = parent->path_flags;665665-631631+ /* override/inherit what is mediated from parent */632632+ profile->label.mediates = parent->label.mediates;666633 /* released on free_profile */667634 rcu_assign_pointer(profile->parent, aa_get_profile(parent));668635 profile->ns = aa_get_ns(parent->ns);···870833 bool capable = policy_ns_capable(subj_cred, label, user_ns,871834 CAP_MAC_ADMIN) == 0;872835873873- AA_DEBUG("cap_mac_admin? %d\n", capable);874874- AA_DEBUG("policy locked? %d\n", aa_g_lock_policy);836836+ AA_DEBUG(DEBUG_POLICY, "cap_mac_admin? %d\n", capable);837837+ AA_DEBUG(DEBUG_POLICY, "policy locked? %d\n", aa_g_lock_policy);875838876839 return aa_policy_view_capable(subj_cred, label, ns) && capable &&877840 !aa_g_lock_policy;···880843bool aa_current_policy_view_capable(struct aa_ns *ns)881844{882845 struct aa_label *label;883883- bool res;846846+ bool needput, res;884847885885- label = __begin_current_label_crit_section();848848+ label = __begin_current_label_crit_section(&needput);886849 res = aa_policy_view_capable(current_cred(), label, ns);887887- __end_current_label_crit_section(label);850850+ __end_current_label_crit_section(label, needput);888851889852 return res;890853}···892855bool aa_current_policy_admin_capable(struct aa_ns *ns)893856{894857 struct aa_label *label;895895- bool res;858858+ bool needput, res;896859897897- label = __begin_current_label_crit_section();860860+ label = __begin_current_label_crit_section(&needput);898861 res = aa_policy_admin_capable(current_cred(), label, ns);899899- __end_current_label_crit_section(label);862862+ __end_current_label_crit_section(label, needput);900863901864 return res;902865}···11051068 goto out;1106106911071070 /* ensure that profiles are all for the same ns11081108- * TODO: update locking to remove this constaint. All profiles in10711071+ * TODO: update locking to remove this constraint. All profiles in11091072 * the load set must succeed as a set or the load will11101073 * fail. Sort ent list and take ns locks in hierarchy order11111074 */
+3-3
security/apparmor/policy_compat.c
···286286287287 AA_BUG(!dfa);288288289289- for (state = 0; state < state_count; state++)289289+ for (state = 0; state < state_count; state++) {290290 ACCEPT_TABLE(dfa)[state] = state * factor;291291- kvfree(dfa->tables[YYTD_ID_ACCEPT2]);292292- dfa->tables[YYTD_ID_ACCEPT2] = NULL;291291+ ACCEPT_TABLE2(dfa)[state] = factor > 1 ? ACCEPT_FLAG_OWNER : 0;292292+ }293293}294294295295/* TODO: merge different dfa mappings into single map_policy fn */
···8989 struct aa_profile *profile, unsigned int resource,9090 struct rlimit *new_rlim)9191{9292- struct aa_ruleset *rules = list_first_entry(&profile->rules,9393- typeof(*rules), list);9292+ struct aa_ruleset *rules = profile->label.rules[0];9493 int e = 0;95949695 if (rules->rlimits.mask & (1 << resource) && new_rlim->rlim_max >···164165 * to the lesser of the tasks hard limit and the init tasks soft limit165166 */166167 label_for_each_confined(i, old_l, old) {167167- struct aa_ruleset *rules = list_first_entry(&old->rules,168168- typeof(*rules),169169- list);168168+ struct aa_ruleset *rules = old->label.rules[0];170169 if (rules->rlimits.mask) {171170 int j;172171···182185183186 /* set any new hard limits as dictated by the new profile */184187 label_for_each_confined(i, new_l, new) {185185- struct aa_ruleset *rules = list_first_entry(&new->rules,186186- typeof(*rules),187187- list);188188+ struct aa_ruleset *rules = new->label.rules[0];188189 int j;189190190191 if (!rules->rlimits.mask)
···11+// SPDX-License-Identifier: GPL-2.0-or-later22+33+#define _GNU_SOURCE44+#include "../kselftest_harness.h"55+#include <errno.h>66+#include <setjmp.h>77+#include <signal.h>88+#include <stdbool.h>99+#include <stdio.h>1010+#include <stdlib.h>1111+#include <string.h>1212+#include <linux/mman.h>1313+#include <sys/syscall.h>1414+#include <unistd.h>1515+#include <sched.h>1616+#include "vm_util.h"1717+1818+#include "../pidfd/pidfd.h"1919+2020+FIXTURE(process_madvise)2121+{2222+ unsigned long page_size;2323+ pid_t child_pid;2424+ int remote_pidfd;2525+ int pidfd;2626+};2727+2828+FIXTURE_SETUP(process_madvise)2929+{3030+ self->page_size = (unsigned long)sysconf(_SC_PAGESIZE);3131+ self->pidfd = PIDFD_SELF;3232+ self->remote_pidfd = -1;3333+ self->child_pid = -1;3434+};3535+3636+FIXTURE_TEARDOWN_PARENT(process_madvise)3737+{3838+ /* This teardown is guaranteed to run, even if tests SKIP or ASSERT */3939+ if (self->child_pid > 0) {4040+ kill(self->child_pid, SIGKILL);4141+ waitpid(self->child_pid, NULL, 0);4242+ }4343+4444+ if (self->remote_pidfd >= 0)4545+ close(self->remote_pidfd);4646+}4747+4848+static ssize_t sys_process_madvise(int pidfd, const struct iovec *iovec,4949+ size_t vlen, int advice, unsigned int flags)5050+{5151+ return syscall(__NR_process_madvise, pidfd, iovec, vlen, advice, flags);5252+}5353+5454+/*5555+ * This test uses PIDFD_SELF to target the current process. The main5656+ * goal is to verify the basic behavior of process_madvise() with5757+ * a vector of non-contiguous memory ranges, not its cross-process5858+ * capabilities.5959+ */6060+TEST_F(process_madvise, basic)6161+{6262+ const unsigned long pagesize = self->page_size;6363+ const int madvise_pages = 4;6464+ struct iovec vec[madvise_pages];6565+ int pidfd = self->pidfd;6666+ ssize_t ret;6767+ char *map;6868+6969+ /*7070+ * Create a single large mapping. We will pick pages from this7171+ * mapping to advise on. This ensures we test non-contiguous iovecs.7272+ */7373+ map = mmap(NULL, pagesize * 10, PROT_READ | PROT_WRITE,7474+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);7575+ if (map == MAP_FAILED)7676+ SKIP(return, "mmap failed, not enough memory.\n");7777+7878+ /* Fill the entire region with a known pattern. */7979+ memset(map, 'A', pagesize * 10);8080+8181+ /*8282+ * Setup the iovec to point to 4 non-contiguous pages8383+ * within the mapping.8484+ */8585+ vec[0].iov_base = &map[0 * pagesize];8686+ vec[0].iov_len = pagesize;8787+ vec[1].iov_base = &map[3 * pagesize];8888+ vec[1].iov_len = pagesize;8989+ vec[2].iov_base = &map[5 * pagesize];9090+ vec[2].iov_len = pagesize;9191+ vec[3].iov_base = &map[8 * pagesize];9292+ vec[3].iov_len = pagesize;9393+9494+ ret = sys_process_madvise(pidfd, vec, madvise_pages, MADV_DONTNEED, 0);9595+ if (ret == -1 && errno == EPERM)9696+ SKIP(return,9797+ "process_madvise() unsupported or permission denied, try running as root.\n");9898+ else if (errno == EINVAL)9999+ SKIP(return,100100+ "process_madvise() unsupported or parameter invalid, please check arguments.\n");101101+102102+ /* The call should succeed and report the total bytes processed. */103103+ ASSERT_EQ(ret, madvise_pages * pagesize);104104+105105+ /* Check that advised pages are now zero. */106106+ for (int i = 0; i < madvise_pages; i++) {107107+ char *advised_page = (char *)vec[i].iov_base;108108+109109+ /* Content must be 0, not 'A'. */110110+ ASSERT_EQ(*advised_page, '\0');111111+ }112112+113113+ /* Check that an un-advised page in between is still 'A'. */114114+ char *unadvised_page = &map[1 * pagesize];115115+116116+ for (int i = 0; i < pagesize; i++)117117+ ASSERT_EQ(unadvised_page[i], 'A');118118+119119+ /* Cleanup. */120120+ ASSERT_EQ(munmap(map, pagesize * 10), 0);121121+}122122+123123+/*124124+ * This test deterministically validates process_madvise() with MADV_COLLAPSE125125+ * on a remote process, other advices are difficult to verify reliably.126126+ *127127+ * The test verifies that a memory region in a child process,128128+ * focus on process_madv remote result, only check addresses and lengths.129129+ * The correctness of the MADV_COLLAPSE can be found in the relevant test examples in khugepaged.130130+ */131131+TEST_F(process_madvise, remote_collapse)132132+{133133+ const unsigned long pagesize = self->page_size;134134+ long huge_page_size;135135+ int pipe_info[2];136136+ ssize_t ret;137137+ struct iovec vec;138138+139139+ struct child_info {140140+ pid_t pid;141141+ void *map_addr;142142+ } info;143143+144144+ huge_page_size = read_pmd_pagesize();145145+ if (huge_page_size <= 0)146146+ SKIP(return, "Could not determine a valid huge page size.\n");147147+148148+ ASSERT_EQ(pipe(pipe_info), 0);149149+150150+ self->child_pid = fork();151151+ ASSERT_NE(self->child_pid, -1);152152+153153+ if (self->child_pid == 0) {154154+ char *map;155155+ size_t map_size = 2 * huge_page_size;156156+157157+ close(pipe_info[0]);158158+159159+ map = mmap(NULL, map_size, PROT_READ | PROT_WRITE,160160+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);161161+ ASSERT_NE(map, MAP_FAILED);162162+163163+ /* Fault in as small pages */164164+ for (size_t i = 0; i < map_size; i += pagesize)165165+ map[i] = 'A';166166+167167+ /* Send info and pause */168168+ info.pid = getpid();169169+ info.map_addr = map;170170+ ret = write(pipe_info[1], &info, sizeof(info));171171+ ASSERT_EQ(ret, sizeof(info));172172+ close(pipe_info[1]);173173+174174+ pause();175175+ exit(0);176176+ }177177+178178+ close(pipe_info[1]);179179+180180+ /* Receive child info */181181+ ret = read(pipe_info[0], &info, sizeof(info));182182+ if (ret <= 0) {183183+ waitpid(self->child_pid, NULL, 0);184184+ SKIP(return, "Failed to read child info from pipe.\n");185185+ }186186+ ASSERT_EQ(ret, sizeof(info));187187+ close(pipe_info[0]);188188+ self->child_pid = info.pid;189189+190190+ self->remote_pidfd = syscall(__NR_pidfd_open, self->child_pid, 0);191191+ ASSERT_GE(self->remote_pidfd, 0);192192+193193+ vec.iov_base = info.map_addr;194194+ vec.iov_len = huge_page_size;195195+196196+ ret = sys_process_madvise(self->remote_pidfd, &vec, 1, MADV_COLLAPSE,197197+ 0);198198+ if (ret == -1) {199199+ if (errno == EINVAL)200200+ SKIP(return, "PROCESS_MADV_ADVISE is not supported.\n");201201+ else if (errno == EPERM)202202+ SKIP(return,203203+ "No process_madvise() permissions, try running as root.\n");204204+ return;205205+ }206206+207207+ ASSERT_EQ(ret, huge_page_size);208208+}209209+210210+/*211211+ * Test process_madvise() with a pidfd for a process that has already212212+ * exited to ensure correct error handling.213213+ */214214+TEST_F(process_madvise, exited_process_pidfd)215215+{216216+ const unsigned long pagesize = self->page_size;217217+ struct iovec vec;218218+ char *map;219219+ ssize_t ret;220220+221221+ map = mmap(NULL, pagesize, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1,222222+ 0);223223+ if (map == MAP_FAILED)224224+ SKIP(return, "mmap failed, not enough memory.\n");225225+226226+ vec.iov_base = map;227227+ vec.iov_len = pagesize;228228+229229+ /*230230+ * Using a pidfd for a process that has already exited should fail231231+ * with ESRCH.232232+ */233233+ self->child_pid = fork();234234+ ASSERT_NE(self->child_pid, -1);235235+236236+ if (self->child_pid == 0)237237+ exit(0);238238+239239+ self->remote_pidfd = syscall(__NR_pidfd_open, self->child_pid, 0);240240+ ASSERT_GE(self->remote_pidfd, 0);241241+242242+ /* Wait for the child to ensure it has terminated. */243243+ waitpid(self->child_pid, NULL, 0);244244+245245+ ret = sys_process_madvise(self->remote_pidfd, &vec, 1, MADV_DONTNEED,246246+ 0);247247+ ASSERT_EQ(ret, -1);248248+ ASSERT_EQ(errno, ESRCH);249249+}250250+251251+/*252252+ * Test process_madvise() with bad pidfds to ensure correct error253253+ * handling.254254+ */255255+TEST_F(process_madvise, bad_pidfd)256256+{257257+ const unsigned long pagesize = self->page_size;258258+ struct iovec vec;259259+ char *map;260260+ ssize_t ret;261261+262262+ map = mmap(NULL, pagesize, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1,263263+ 0);264264+ if (map == MAP_FAILED)265265+ SKIP(return, "mmap failed, not enough memory.\n");266266+267267+ vec.iov_base = map;268268+ vec.iov_len = pagesize;269269+270270+ /* Using an invalid fd number (-1) should fail with EBADF. */271271+ ret = sys_process_madvise(-1, &vec, 1, MADV_DONTNEED, 0);272272+ ASSERT_EQ(ret, -1);273273+ ASSERT_EQ(errno, EBADF);274274+275275+ /*276276+ * Using a valid fd that is not a pidfd (e.g. stdin) should fail277277+ * with EBADF.278278+ */279279+ ret = sys_process_madvise(STDIN_FILENO, &vec, 1, MADV_DONTNEED, 0);280280+ ASSERT_EQ(ret, -1);281281+ ASSERT_EQ(errno, EBADF);282282+}283283+284284+/*285285+ * Test that process_madvise() rejects vlen > UIO_MAXIOV.286286+ * The kernel should return -EINVAL when the number of iovecs exceeds 1024.287287+ */288288+TEST_F(process_madvise, invalid_vlen)289289+{290290+ const unsigned long pagesize = self->page_size;291291+ int pidfd = self->pidfd;292292+ struct iovec vec;293293+ char *map;294294+ ssize_t ret;295295+296296+ map = mmap(NULL, pagesize, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1,297297+ 0);298298+ if (map == MAP_FAILED)299299+ SKIP(return, "mmap failed, not enough memory.\n");300300+301301+ vec.iov_base = map;302302+ vec.iov_len = pagesize;303303+304304+ ret = sys_process_madvise(pidfd, &vec, 1025, MADV_DONTNEED, 0);305305+ ASSERT_EQ(ret, -1);306306+ ASSERT_EQ(errno, EINVAL);307307+308308+ /* Cleanup. */309309+ ASSERT_EQ(munmap(map, pagesize), 0);310310+}311311+312312+/*313313+ * Test process_madvise() with an invalid flag value. Currently, only a flag314314+ * value of 0 is supported. This test is reserved for the future, e.g., if315315+ * synchronous flags are added.316316+ */317317+TEST_F(process_madvise, flag)318318+{319319+ const unsigned long pagesize = self->page_size;320320+ unsigned int invalid_flag;321321+ int pidfd = self->pidfd;322322+ struct iovec vec;323323+ char *map;324324+ ssize_t ret;325325+326326+ map = mmap(NULL, pagesize, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1,327327+ 0);328328+ if (map == MAP_FAILED)329329+ SKIP(return, "mmap failed, not enough memory.\n");330330+331331+ vec.iov_base = map;332332+ vec.iov_len = pagesize;333333+334334+ invalid_flag = 0x80000000;335335+336336+ ret = sys_process_madvise(pidfd, &vec, 1, MADV_DONTNEED, invalid_flag);337337+ ASSERT_EQ(ret, -1);338338+ ASSERT_EQ(errno, EINVAL);339339+340340+ /* Cleanup. */341341+ ASSERT_EQ(munmap(map, pagesize), 0);342342+}343343+344344+TEST_HARNESS_MAIN
+5
tools/testing/selftests/mm/run_vmtests.sh
···6565 test pagemap_scan IOCTL6666- pfnmap6767 tests for VM_PFNMAP handling6868+- process_madv6969+ test for process_madv6870- cow6971 test copy-on-write semantics7072- thp···426424427425# MADV_POPULATE_READ and MADV_POPULATE_WRITE tests428426CATEGORY="madv_populate" run_test ./madv_populate427427+428428+# PROCESS_MADV test429429+CATEGORY="process_madv" run_test ./process_madv429430430431CATEGORY="vma_merge" run_test ./merge431432