mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Linux 6.14-rc7
-----BEGIN PGP SIGNATURE----- iQFSBAABCAA8FiEEq68RxlopcLEwq+PEeb4+QwBBGIYFAmfXVtUeHHRvcnZhbGRz QGxpbnV4LWZvdW5kYXRpb24ub3JnAAoJEHm+PkMAQRiGN/sH/i5423Gt/z51gDjA s4v5Z7GaBJ9zOGBahn2RWFe72zytTqKrEJmMnGfguirs0atD1DtQj4WAP7iFKP+e WyO663X6HF7i5y37ja0Yd4PZc31hwtqzKH8LjBf8f8tTy8UsEVqumdi5A4sS9KTM qm4kTyyVEY9D/s7oRY8ywjDlRJtO6nT0aKMp4kAqNEbrNUYbilT/a0hgXcgSmPyB uIjmjL2fZfutxGI5LgfbaSHCa1ElmhvTvivOMpaAmZSGCRVHCKGgT0CTNnHyn/7C dB145JkRO4ZOUqirCdO4PE/23id3ajq9fcixJGBzAv7c45y+B3JZ1r2kAfKalE8/ qrOKLys= =8r7a -----END PGP SIGNATURE----- Merge tag 'v6.14-rc7' into x86/core, to pick up fixes Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
		
						commit
						89771319e0
					
				
					 507 changed files with 5913 additions and 2692 deletions
				
			
		
							
								
								
									
										3
									
								
								.mailmap
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								.mailmap
									
									
									
									
									
								
							| 
						 | 
					@ -88,7 +88,6 @@ Antonio Quartulli <antonio@mandelbit.com> <antonio@open-mesh.com>
 | 
				
			||||||
Antonio Quartulli <antonio@mandelbit.com> <antonio.quartulli@open-mesh.com>
 | 
					Antonio Quartulli <antonio@mandelbit.com> <antonio.quartulli@open-mesh.com>
 | 
				
			||||||
Antonio Quartulli <antonio@mandelbit.com> <ordex@autistici.org>
 | 
					Antonio Quartulli <antonio@mandelbit.com> <ordex@autistici.org>
 | 
				
			||||||
Antonio Quartulli <antonio@mandelbit.com> <ordex@ritirata.org>
 | 
					Antonio Quartulli <antonio@mandelbit.com> <ordex@ritirata.org>
 | 
				
			||||||
Antonio Quartulli <antonio@mandelbit.com> <antonio@openvpn.net>
 | 
					 | 
				
			||||||
Antonio Quartulli <antonio@mandelbit.com> <a@unstable.cc>
 | 
					Antonio Quartulli <antonio@mandelbit.com> <a@unstable.cc>
 | 
				
			||||||
Anup Patel <anup@brainfault.org> <anup.patel@wdc.com>
 | 
					Anup Patel <anup@brainfault.org> <anup.patel@wdc.com>
 | 
				
			||||||
Archit Taneja <archit@ti.com>
 | 
					Archit Taneja <archit@ti.com>
 | 
				
			||||||
| 
						 | 
					@ -282,6 +281,7 @@ Henrik Rydberg <rydberg@bitmath.org>
 | 
				
			||||||
Herbert Xu <herbert@gondor.apana.org.au>
 | 
					Herbert Xu <herbert@gondor.apana.org.au>
 | 
				
			||||||
Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
 | 
					Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
 | 
				
			||||||
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
 | 
					Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
 | 
				
			||||||
 | 
					Ike Panhc <ikepanhc@gmail.com> <ike.pan@canonical.com>
 | 
				
			||||||
J. Bruce Fields <bfields@fieldses.org> <bfields@redhat.com>
 | 
					J. Bruce Fields <bfields@fieldses.org> <bfields@redhat.com>
 | 
				
			||||||
J. Bruce Fields <bfields@fieldses.org> <bfields@citi.umich.edu>
 | 
					J. Bruce Fields <bfields@fieldses.org> <bfields@citi.umich.edu>
 | 
				
			||||||
Jacob Shin <Jacob.Shin@amd.com>
 | 
					Jacob Shin <Jacob.Shin@amd.com>
 | 
				
			||||||
| 
						 | 
					@ -692,6 +692,7 @@ Subbaraman Narayanamurthy <quic_subbaram@quicinc.com> <subbaram@codeaurora.org>
 | 
				
			||||||
Subhash Jadavani <subhashj@codeaurora.org>
 | 
					Subhash Jadavani <subhashj@codeaurora.org>
 | 
				
			||||||
Sudarshan Rajagopalan <quic_sudaraja@quicinc.com> <sudaraja@codeaurora.org>
 | 
					Sudarshan Rajagopalan <quic_sudaraja@quicinc.com> <sudaraja@codeaurora.org>
 | 
				
			||||||
Sudeep Holla <sudeep.holla@arm.com> Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
 | 
					Sudeep Holla <sudeep.holla@arm.com> Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
 | 
				
			||||||
 | 
					Sumit Garg <sumit.garg@kernel.org> <sumit.garg@linaro.org>
 | 
				
			||||||
Sumit Semwal <sumit.semwal@ti.com>
 | 
					Sumit Semwal <sumit.semwal@ti.com>
 | 
				
			||||||
Surabhi Vishnoi <quic_svishnoi@quicinc.com> <svishnoi@codeaurora.org>
 | 
					Surabhi Vishnoi <quic_svishnoi@quicinc.com> <svishnoi@codeaurora.org>
 | 
				
			||||||
Sven Eckelmann <sven@narfation.org> <seckelmann@datto.com>
 | 
					Sven Eckelmann <sven@narfation.org> <seckelmann@datto.com>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -176,7 +176,7 @@ Configuring the kernel
 | 
				
			||||||
                        values without prompting.
 | 
					                        values without prompting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     "make defconfig"   Create a ./.config file by using the default
 | 
					     "make defconfig"   Create a ./.config file by using the default
 | 
				
			||||||
                        symbol values from either arch/$ARCH/defconfig
 | 
					                        symbol values from either arch/$ARCH/configs/defconfig
 | 
				
			||||||
                        or arch/$ARCH/configs/${PLATFORM}_defconfig,
 | 
					                        or arch/$ARCH/configs/${PLATFORM}_defconfig,
 | 
				
			||||||
                        depending on the architecture.
 | 
					                        depending on the architecture.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,6 +212,17 @@ pid>/``).
 | 
				
			||||||
This value defaults to 0.
 | 
					This value defaults to 0.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					core_sort_vma
 | 
				
			||||||
 | 
					=============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The default coredump writes VMAs in address order. By setting
 | 
				
			||||||
 | 
					``core_sort_vma`` to 1, VMAs will be written from smallest size
 | 
				
			||||||
 | 
					to largest size. This is known to break at least elfutils, but
 | 
				
			||||||
 | 
					can be handy when dealing with very large (and truncated)
 | 
				
			||||||
 | 
					coredumps where the more useful debugging details are included
 | 
				
			||||||
 | 
					in the smaller VMAs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
core_uses_pid
 | 
					core_uses_pid
 | 
				
			||||||
=============
 | 
					=============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -146,6 +146,7 @@ properties:
 | 
				
			||||||
    maxItems: 2
 | 
					    maxItems: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pwm-names:
 | 
					  pwm-names:
 | 
				
			||||||
 | 
					    minItems: 1
 | 
				
			||||||
    items:
 | 
					    items:
 | 
				
			||||||
      - const: convst1
 | 
					      - const: convst1
 | 
				
			||||||
      - const: convst2
 | 
					      - const: convst2
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ properties:
 | 
				
			||||||
      - imagis,ist3038
 | 
					      - imagis,ist3038
 | 
				
			||||||
      - imagis,ist3038b
 | 
					      - imagis,ist3038b
 | 
				
			||||||
      - imagis,ist3038c
 | 
					      - imagis,ist3038c
 | 
				
			||||||
 | 
					      - imagis,ist3038h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  reg:
 | 
					  reg:
 | 
				
			||||||
    maxItems: 1
 | 
					    maxItems: 1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,8 +63,8 @@ what id ``k11000`` corresponds to in the second or third idmapping. The
 | 
				
			||||||
straightforward algorithm to use is to apply the inverse of the first idmapping,
 | 
					straightforward algorithm to use is to apply the inverse of the first idmapping,
 | 
				
			||||||
mapping ``k11000`` up to ``u1000``. Afterwards, we can map ``u1000`` down using
 | 
					mapping ``k11000`` up to ``u1000``. Afterwards, we can map ``u1000`` down using
 | 
				
			||||||
either the second idmapping mapping or third idmapping mapping. The second
 | 
					either the second idmapping mapping or third idmapping mapping. The second
 | 
				
			||||||
idmapping would map ``u1000`` down to ``21000``. The third idmapping would map
 | 
					idmapping would map ``u1000`` down to ``k21000``. The third idmapping would map
 | 
				
			||||||
``u1000`` down to ``u31000``.
 | 
					``u1000`` down to ``k31000``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If we were given the same task for the following three idmappings::
 | 
					If we were given the same task for the following three idmappings::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,7 +145,7 @@ Rust standard library source
 | 
				
			||||||
****************************
 | 
					****************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The Rust standard library source is required because the build system will
 | 
					The Rust standard library source is required because the build system will
 | 
				
			||||||
cross-compile ``core`` and ``alloc``.
 | 
					cross-compile ``core``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If ``rustup`` is being used, run::
 | 
					If ``rustup`` is being used, run::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,7 +97,7 @@ operator are also supported as usual, e.g.:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// ```
 | 
						/// ```
 | 
				
			||||||
	/// # use kernel::{spawn_work_item, workqueue};
 | 
						/// # use kernel::{spawn_work_item, workqueue};
 | 
				
			||||||
	/// spawn_work_item!(workqueue::system(), || pr_info!("x"))?;
 | 
						/// spawn_work_item!(workqueue::system(), || pr_info!("x\n"))?;
 | 
				
			||||||
	/// # Ok::<(), Error>(())
 | 
						/// # Ok::<(), Error>(())
 | 
				
			||||||
	/// ```
 | 
						/// ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,6 +102,9 @@ The system wide settings are configured under the /proc virtual file system:
 | 
				
			||||||
  * sched_rt_period_us takes values from 1 to INT_MAX.
 | 
					  * sched_rt_period_us takes values from 1 to INT_MAX.
 | 
				
			||||||
  * sched_rt_runtime_us takes values from -1 to sched_rt_period_us.
 | 
					  * sched_rt_runtime_us takes values from -1 to sched_rt_period_us.
 | 
				
			||||||
  * A run time of -1 specifies runtime == period, ie. no limit.
 | 
					  * A run time of -1 specifies runtime == period, ie. no limit.
 | 
				
			||||||
 | 
					  * sched_rt_runtime_us/sched_rt_period_us > 0.05 inorder to preserve
 | 
				
			||||||
 | 
					    bandwidth for fair dl_server. For accurate value check average of
 | 
				
			||||||
 | 
					    runtime/period in /sys/kernel/debug/sched/fair_server/cpuX/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2.2 Default behaviour
 | 
					2.2 Default behaviour
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										58
									
								
								MAINTAINERS
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								MAINTAINERS
									
									
									
									
									
								
							| 
						 | 
					@ -124,6 +124,7 @@ F:	include/net/ieee80211_radiotap.h
 | 
				
			||||||
F:	include/net/iw_handler.h
 | 
					F:	include/net/iw_handler.h
 | 
				
			||||||
F:	include/net/wext.h
 | 
					F:	include/net/wext.h
 | 
				
			||||||
F:	include/uapi/linux/nl80211.h
 | 
					F:	include/uapi/linux/nl80211.h
 | 
				
			||||||
 | 
					N:	include/uapi/linux/nl80211-.*
 | 
				
			||||||
F:	include/uapi/linux/wireless.h
 | 
					F:	include/uapi/linux/wireless.h
 | 
				
			||||||
F:	net/wireless/
 | 
					F:	net/wireless/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -514,7 +515,7 @@ F:	drivers/hwmon/adm1029.c
 | 
				
			||||||
ADM8211 WIRELESS DRIVER
 | 
					ADM8211 WIRELESS DRIVER
 | 
				
			||||||
L:	linux-wireless@vger.kernel.org
 | 
					L:	linux-wireless@vger.kernel.org
 | 
				
			||||||
S:	Orphan
 | 
					S:	Orphan
 | 
				
			||||||
F:	drivers/net/wireless/admtek/adm8211.*
 | 
					F:	drivers/net/wireless/admtek/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ADP1050 HARDWARE MONITOR DRIVER
 | 
					ADP1050 HARDWARE MONITOR DRIVER
 | 
				
			||||||
M:	Radu Sabau <radu.sabau@analog.com>
 | 
					M:	Radu Sabau <radu.sabau@analog.com>
 | 
				
			||||||
| 
						 | 
					@ -5775,6 +5776,7 @@ X:	drivers/clk/clkdev.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3)
 | 
					COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3)
 | 
				
			||||||
M:	Steve French <sfrench@samba.org>
 | 
					M:	Steve French <sfrench@samba.org>
 | 
				
			||||||
 | 
					M:	Steve French <smfrench@gmail.com>
 | 
				
			||||||
R:	Paulo Alcantara <pc@manguebit.com> (DFS, global name space)
 | 
					R:	Paulo Alcantara <pc@manguebit.com> (DFS, global name space)
 | 
				
			||||||
R:	Ronnie Sahlberg <ronniesahlberg@gmail.com> (directory leases, sparse files)
 | 
					R:	Ronnie Sahlberg <ronniesahlberg@gmail.com> (directory leases, sparse files)
 | 
				
			||||||
R:	Shyam Prasad N <sprasad@microsoft.com> (multichannel)
 | 
					R:	Shyam Prasad N <sprasad@microsoft.com> (multichannel)
 | 
				
			||||||
| 
						 | 
					@ -6206,7 +6208,7 @@ F:	Documentation/process/cve.rst
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CW1200 WLAN driver
 | 
					CW1200 WLAN driver
 | 
				
			||||||
S:	Orphan
 | 
					S:	Orphan
 | 
				
			||||||
F:	drivers/net/wireless/st/cw1200/
 | 
					F:	drivers/net/wireless/st/
 | 
				
			||||||
F:	include/linux/platform_data/net-cw1200.h
 | 
					F:	include/linux/platform_data/net-cw1200.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CX18 VIDEO4LINUX DRIVER
 | 
					CX18 VIDEO4LINUX DRIVER
 | 
				
			||||||
| 
						 | 
					@ -9442,14 +9444,11 @@ F:	include/linux/fscrypt.h
 | 
				
			||||||
F:	include/uapi/linux/fscrypt.h
 | 
					F:	include/uapi/linux/fscrypt.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FSI SUBSYSTEM
 | 
					FSI SUBSYSTEM
 | 
				
			||||||
M:	Jeremy Kerr <jk@ozlabs.org>
 | 
					M:	Eddie James <eajames@linux.ibm.com>
 | 
				
			||||||
M:	Joel Stanley <joel@jms.id.au>
 | 
					R:	Ninad Palsule <ninad@linux.ibm.com>
 | 
				
			||||||
R:	Alistar Popple <alistair@popple.id.au>
 | 
					 | 
				
			||||||
R:	Eddie James <eajames@linux.ibm.com>
 | 
					 | 
				
			||||||
L:	linux-fsi@lists.ozlabs.org
 | 
					L:	linux-fsi@lists.ozlabs.org
 | 
				
			||||||
S:	Supported
 | 
					S:	Supported
 | 
				
			||||||
Q:	http://patchwork.ozlabs.org/project/linux-fsi/list/
 | 
					Q:	http://patchwork.ozlabs.org/project/linux-fsi/list/
 | 
				
			||||||
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/joel/fsi.git
 | 
					 | 
				
			||||||
F:	drivers/fsi/
 | 
					F:	drivers/fsi/
 | 
				
			||||||
F:	include/linux/fsi*.h
 | 
					F:	include/linux/fsi*.h
 | 
				
			||||||
F:	include/trace/events/fsi*.h
 | 
					F:	include/trace/events/fsi*.h
 | 
				
			||||||
| 
						 | 
					@ -9830,7 +9829,6 @@ S:	Maintained
 | 
				
			||||||
F:	drivers/media/usb/go7007/
 | 
					F:	drivers/media/usb/go7007/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GOODIX TOUCHSCREEN
 | 
					GOODIX TOUCHSCREEN
 | 
				
			||||||
M:	Bastien Nocera <hadess@hadess.net>
 | 
					 | 
				
			||||||
M:	Hans de Goede <hdegoede@redhat.com>
 | 
					M:	Hans de Goede <hdegoede@redhat.com>
 | 
				
			||||||
L:	linux-input@vger.kernel.org
 | 
					L:	linux-input@vger.kernel.org
 | 
				
			||||||
S:	Maintained
 | 
					S:	Maintained
 | 
				
			||||||
| 
						 | 
					@ -11142,7 +11140,7 @@ S:	Maintained
 | 
				
			||||||
F:	drivers/i2c/busses/i2c-icy.c
 | 
					F:	drivers/i2c/busses/i2c-icy.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
IDEAPAD LAPTOP EXTRAS DRIVER
 | 
					IDEAPAD LAPTOP EXTRAS DRIVER
 | 
				
			||||||
M:	Ike Panhc <ike.pan@canonical.com>
 | 
					M:	Ike Panhc <ikepanhc@gmail.com>
 | 
				
			||||||
L:	platform-driver-x86@vger.kernel.org
 | 
					L:	platform-driver-x86@vger.kernel.org
 | 
				
			||||||
S:	Maintained
 | 
					S:	Maintained
 | 
				
			||||||
W:	http://launchpad.net/ideapad-laptop
 | 
					W:	http://launchpad.net/ideapad-laptop
 | 
				
			||||||
| 
						 | 
					@ -12655,7 +12653,9 @@ F:	tools/testing/selftests/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
KERNEL SMB3 SERVER (KSMBD)
 | 
					KERNEL SMB3 SERVER (KSMBD)
 | 
				
			||||||
M:	Namjae Jeon <linkinjeon@kernel.org>
 | 
					M:	Namjae Jeon <linkinjeon@kernel.org>
 | 
				
			||||||
 | 
					M:	Namjae Jeon <linkinjeon@samba.org>
 | 
				
			||||||
M:	Steve French <sfrench@samba.org>
 | 
					M:	Steve French <sfrench@samba.org>
 | 
				
			||||||
 | 
					M:	Steve French <smfrench@gmail.com>
 | 
				
			||||||
R:	Sergey Senozhatsky <senozhatsky@chromium.org>
 | 
					R:	Sergey Senozhatsky <senozhatsky@chromium.org>
 | 
				
			||||||
R:	Tom Talpey <tom@talpey.com>
 | 
					R:	Tom Talpey <tom@talpey.com>
 | 
				
			||||||
L:	linux-cifs@vger.kernel.org
 | 
					L:	linux-cifs@vger.kernel.org
 | 
				
			||||||
| 
						 | 
					@ -12872,7 +12872,7 @@ F:	include/keys/trusted_dcp.h
 | 
				
			||||||
F:	security/keys/trusted-keys/trusted_dcp.c
 | 
					F:	security/keys/trusted-keys/trusted_dcp.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
KEYS-TRUSTED-TEE
 | 
					KEYS-TRUSTED-TEE
 | 
				
			||||||
M:	Sumit Garg <sumit.garg@linaro.org>
 | 
					M:	Sumit Garg <sumit.garg@kernel.org>
 | 
				
			||||||
L:	linux-integrity@vger.kernel.org
 | 
					L:	linux-integrity@vger.kernel.org
 | 
				
			||||||
L:	keyrings@vger.kernel.org
 | 
					L:	keyrings@vger.kernel.org
 | 
				
			||||||
S:	Supported
 | 
					S:	Supported
 | 
				
			||||||
| 
						 | 
					@ -13994,6 +13994,7 @@ MARVELL LIBERTAS WIRELESS DRIVER
 | 
				
			||||||
L:	libertas-dev@lists.infradead.org
 | 
					L:	libertas-dev@lists.infradead.org
 | 
				
			||||||
S:	Orphan
 | 
					S:	Orphan
 | 
				
			||||||
F:	drivers/net/wireless/marvell/libertas/
 | 
					F:	drivers/net/wireless/marvell/libertas/
 | 
				
			||||||
 | 
					F:	drivers/net/wireless/marvell/libertas_tf/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MARVELL MACCHIATOBIN SUPPORT
 | 
					MARVELL MACCHIATOBIN SUPPORT
 | 
				
			||||||
M:	Russell King <linux@armlinux.org.uk>
 | 
					M:	Russell King <linux@armlinux.org.uk>
 | 
				
			||||||
| 
						 | 
					@ -15663,7 +15664,7 @@ M:	Ajay Singh <ajay.kathat@microchip.com>
 | 
				
			||||||
M:	Claudiu Beznea <claudiu.beznea@tuxon.dev>
 | 
					M:	Claudiu Beznea <claudiu.beznea@tuxon.dev>
 | 
				
			||||||
L:	linux-wireless@vger.kernel.org
 | 
					L:	linux-wireless@vger.kernel.org
 | 
				
			||||||
S:	Supported
 | 
					S:	Supported
 | 
				
			||||||
F:	drivers/net/wireless/microchip/wilc1000/
 | 
					F:	drivers/net/wireless/microchip/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MICROSEMI MIPS SOCS
 | 
					MICROSEMI MIPS SOCS
 | 
				
			||||||
M:	Alexandre Belloni <alexandre.belloni@bootlin.com>
 | 
					M:	Alexandre Belloni <alexandre.belloni@bootlin.com>
 | 
				
			||||||
| 
						 | 
					@ -16449,6 +16450,23 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git
 | 
				
			||||||
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git
 | 
					T:	git git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git
 | 
				
			||||||
F:	Documentation/devicetree/bindings/net/wireless/
 | 
					F:	Documentation/devicetree/bindings/net/wireless/
 | 
				
			||||||
F:	drivers/net/wireless/
 | 
					F:	drivers/net/wireless/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/ath/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/broadcom/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/intel/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/intersil/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/marvell/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/mediatek/mt76/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/mediatek/mt7601u/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/microchip/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/purelifi/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/quantenna/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/ralink/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/realtek/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/rsi/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/silabs/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/st/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/ti/
 | 
				
			||||||
 | 
					X:	drivers/net/wireless/zydas/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NETWORKING [DSA]
 | 
					NETWORKING [DSA]
 | 
				
			||||||
M:	Andrew Lunn <andrew@lunn.ch>
 | 
					M:	Andrew Lunn <andrew@lunn.ch>
 | 
				
			||||||
| 
						 | 
					@ -17672,7 +17690,7 @@ F:	Documentation/ABI/testing/sysfs-bus-optee-devices
 | 
				
			||||||
F:	drivers/tee/optee/
 | 
					F:	drivers/tee/optee/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER
 | 
					OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER
 | 
				
			||||||
M:	Sumit Garg <sumit.garg@linaro.org>
 | 
					M:	Sumit Garg <sumit.garg@kernel.org>
 | 
				
			||||||
L:	op-tee@lists.trustedfirmware.org
 | 
					L:	op-tee@lists.trustedfirmware.org
 | 
				
			||||||
S:	Maintained
 | 
					S:	Maintained
 | 
				
			||||||
F:	drivers/char/hw_random/optee-rng.c
 | 
					F:	drivers/char/hw_random/optee-rng.c
 | 
				
			||||||
| 
						 | 
					@ -17833,7 +17851,7 @@ M:	Christian Lamparter <chunkeey@googlemail.com>
 | 
				
			||||||
L:	linux-wireless@vger.kernel.org
 | 
					L:	linux-wireless@vger.kernel.org
 | 
				
			||||||
S:	Maintained
 | 
					S:	Maintained
 | 
				
			||||||
W:	https://wireless.wiki.kernel.org/en/users/Drivers/p54
 | 
					W:	https://wireless.wiki.kernel.org/en/users/Drivers/p54
 | 
				
			||||||
F:	drivers/net/wireless/intersil/p54/
 | 
					F:	drivers/net/wireless/intersil/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PACKET SOCKETS
 | 
					PACKET SOCKETS
 | 
				
			||||||
M:	Willem de Bruijn <willemdebruijn.kernel@gmail.com>
 | 
					M:	Willem de Bruijn <willemdebruijn.kernel@gmail.com>
 | 
				
			||||||
| 
						 | 
					@ -19110,7 +19128,7 @@ PURELIFI PLFXLC DRIVER
 | 
				
			||||||
M:	Srinivasan Raju <srini.raju@purelifi.com>
 | 
					M:	Srinivasan Raju <srini.raju@purelifi.com>
 | 
				
			||||||
L:	linux-wireless@vger.kernel.org
 | 
					L:	linux-wireless@vger.kernel.org
 | 
				
			||||||
S:	Supported
 | 
					S:	Supported
 | 
				
			||||||
F:	drivers/net/wireless/purelifi/plfxlc/
 | 
					F:	drivers/net/wireless/purelifi/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PVRUSB2 VIDEO4LINUX DRIVER
 | 
					PVRUSB2 VIDEO4LINUX DRIVER
 | 
				
			||||||
M:	Mike Isely <isely@pobox.com>
 | 
					M:	Mike Isely <isely@pobox.com>
 | 
				
			||||||
| 
						 | 
					@ -19661,7 +19679,7 @@ M:	Igor Mitsyanko <imitsyanko@quantenna.com>
 | 
				
			||||||
R:	Sergey Matyukevich <geomatsi@gmail.com>
 | 
					R:	Sergey Matyukevich <geomatsi@gmail.com>
 | 
				
			||||||
L:	linux-wireless@vger.kernel.org
 | 
					L:	linux-wireless@vger.kernel.org
 | 
				
			||||||
S:	Maintained
 | 
					S:	Maintained
 | 
				
			||||||
F:	drivers/net/wireless/quantenna
 | 
					F:	drivers/net/wireless/quantenna/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RADEON and AMDGPU DRM DRIVERS
 | 
					RADEON and AMDGPU DRM DRIVERS
 | 
				
			||||||
M:	Alex Deucher <alexander.deucher@amd.com>
 | 
					M:	Alex Deucher <alexander.deucher@amd.com>
 | 
				
			||||||
| 
						 | 
					@ -19741,7 +19759,7 @@ RALINK RT2X00 WIRELESS LAN DRIVER
 | 
				
			||||||
M:	Stanislaw Gruszka <stf_xl@wp.pl>
 | 
					M:	Stanislaw Gruszka <stf_xl@wp.pl>
 | 
				
			||||||
L:	linux-wireless@vger.kernel.org
 | 
					L:	linux-wireless@vger.kernel.org
 | 
				
			||||||
S:	Maintained
 | 
					S:	Maintained
 | 
				
			||||||
F:	drivers/net/wireless/ralink/rt2x00/
 | 
					F:	drivers/net/wireless/ralink/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RAMDISK RAM BLOCK DEVICE DRIVER
 | 
					RAMDISK RAM BLOCK DEVICE DRIVER
 | 
				
			||||||
M:	Jens Axboe <axboe@kernel.dk>
 | 
					M:	Jens Axboe <axboe@kernel.dk>
 | 
				
			||||||
| 
						 | 
					@ -21089,6 +21107,7 @@ F:	include/linux/clk/samsung.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SAMSUNG SPI DRIVERS
 | 
					SAMSUNG SPI DRIVERS
 | 
				
			||||||
M:	Andi Shyti <andi.shyti@kernel.org>
 | 
					M:	Andi Shyti <andi.shyti@kernel.org>
 | 
				
			||||||
 | 
					R:	Tudor Ambarus <tudor.ambarus@linaro.org>
 | 
				
			||||||
L:	linux-spi@vger.kernel.org
 | 
					L:	linux-spi@vger.kernel.org
 | 
				
			||||||
L:	linux-samsung-soc@vger.kernel.org
 | 
					L:	linux-samsung-soc@vger.kernel.org
 | 
				
			||||||
S:	Maintained
 | 
					S:	Maintained
 | 
				
			||||||
| 
						 | 
					@ -21499,7 +21518,6 @@ F:	include/linux/slimbus.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SFC NETWORK DRIVER
 | 
					SFC NETWORK DRIVER
 | 
				
			||||||
M:	Edward Cree <ecree.xilinx@gmail.com>
 | 
					M:	Edward Cree <ecree.xilinx@gmail.com>
 | 
				
			||||||
M:	Martin Habets <habetsm.xilinx@gmail.com>
 | 
					 | 
				
			||||||
L:	netdev@vger.kernel.org
 | 
					L:	netdev@vger.kernel.org
 | 
				
			||||||
L:	linux-net-drivers@amd.com
 | 
					L:	linux-net-drivers@amd.com
 | 
				
			||||||
S:	Maintained
 | 
					S:	Maintained
 | 
				
			||||||
| 
						 | 
					@ -21708,7 +21726,7 @@ SILICON LABS WIRELESS DRIVERS (for WFxxx series)
 | 
				
			||||||
M:	Jérôme Pouiller <jerome.pouiller@silabs.com>
 | 
					M:	Jérôme Pouiller <jerome.pouiller@silabs.com>
 | 
				
			||||||
S:	Supported
 | 
					S:	Supported
 | 
				
			||||||
F:	Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml
 | 
					F:	Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml
 | 
				
			||||||
F:	drivers/net/wireless/silabs/wfx/
 | 
					F:	drivers/net/wireless/silabs/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SILICON MOTION SM712 FRAME BUFFER DRIVER
 | 
					SILICON MOTION SM712 FRAME BUFFER DRIVER
 | 
				
			||||||
M:	Sudip Mukherjee <sudipm.mukherjee@gmail.com>
 | 
					M:	Sudip Mukherjee <sudipm.mukherjee@gmail.com>
 | 
				
			||||||
| 
						 | 
					@ -23285,7 +23303,7 @@ F:	include/media/i2c/tw9910.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEE SUBSYSTEM
 | 
					TEE SUBSYSTEM
 | 
				
			||||||
M:	Jens Wiklander <jens.wiklander@linaro.org>
 | 
					M:	Jens Wiklander <jens.wiklander@linaro.org>
 | 
				
			||||||
R:	Sumit Garg <sumit.garg@linaro.org>
 | 
					R:	Sumit Garg <sumit.garg@kernel.org>
 | 
				
			||||||
L:	op-tee@lists.trustedfirmware.org
 | 
					L:	op-tee@lists.trustedfirmware.org
 | 
				
			||||||
S:	Maintained
 | 
					S:	Maintained
 | 
				
			||||||
F:	Documentation/ABI/testing/sysfs-class-tee
 | 
					F:	Documentation/ABI/testing/sysfs-class-tee
 | 
				
			||||||
| 
						 | 
					@ -26208,7 +26226,7 @@ F:	mm/zbud.c
 | 
				
			||||||
ZD1211RW WIRELESS DRIVER
 | 
					ZD1211RW WIRELESS DRIVER
 | 
				
			||||||
L:	linux-wireless@vger.kernel.org
 | 
					L:	linux-wireless@vger.kernel.org
 | 
				
			||||||
S:	Orphan
 | 
					S:	Orphan
 | 
				
			||||||
F:	drivers/net/wireless/zydas/zd1211rw/
 | 
					F:	drivers/net/wireless/zydas/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ZD1301 MEDIA DRIVER
 | 
					ZD1301 MEDIA DRIVER
 | 
				
			||||||
L:	linux-media@vger.kernel.org
 | 
					L:	linux-media@vger.kernel.org
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										7
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								Makefile
									
									
									
									
									
								
							| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
VERSION = 6
 | 
					VERSION = 6
 | 
				
			||||||
PATCHLEVEL = 14
 | 
					PATCHLEVEL = 14
 | 
				
			||||||
SUBLEVEL = 0
 | 
					SUBLEVEL = 0
 | 
				
			||||||
EXTRAVERSION = -rc5
 | 
					EXTRAVERSION = -rc7
 | 
				
			||||||
NAME = Baby Opossum Posse
 | 
					NAME = Baby Opossum Posse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# *DOCUMENTATION*
 | 
					# *DOCUMENTATION*
 | 
				
			||||||
| 
						 | 
					@ -1126,6 +1126,11 @@ endif
 | 
				
			||||||
KBUILD_USERCFLAGS  += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS))
 | 
					KBUILD_USERCFLAGS  += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS))
 | 
				
			||||||
KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS))
 | 
					KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# userspace programs are linked via the compiler, use the correct linker
 | 
				
			||||||
 | 
					ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_LD_IS_LLD),yy)
 | 
				
			||||||
 | 
					KBUILD_USERLDFLAGS += --ld-path=$(LD)
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# make the checker run with the right architecture
 | 
					# make the checker run with the right architecture
 | 
				
			||||||
CHECKFLAGS += --arch=$(ARCH)
 | 
					CHECKFLAGS += --arch=$(ARCH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@ static int do_adjust_pte(struct vm_area_struct *vma, unsigned long address,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
 | 
					static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
 | 
				
			||||||
		      unsigned long pfn, struct vm_fault *vmf)
 | 
							      unsigned long pfn, bool need_lock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	spinlock_t *ptl;
 | 
						spinlock_t *ptl;
 | 
				
			||||||
	pgd_t *pgd;
 | 
						pgd_t *pgd;
 | 
				
			||||||
| 
						 | 
					@ -99,12 +99,11 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
 | 
				
			||||||
	if (!pte)
 | 
						if (!pte)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (need_lock) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
	 * If we are using split PTE locks, then we need to take the page
 | 
							 * Use nested version here to indicate that we are already
 | 
				
			||||||
	 * lock here.  Otherwise we are using shared mm->page_table_lock
 | 
							 * holding one similar spinlock.
 | 
				
			||||||
	 * which is already locked, thus cannot take it.
 | 
					 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
	if (ptl != vmf->ptl) {
 | 
					 | 
				
			||||||
		spin_lock_nested(ptl, SINGLE_DEPTH_NESTING);
 | 
							spin_lock_nested(ptl, SINGLE_DEPTH_NESTING);
 | 
				
			||||||
		if (unlikely(!pmd_same(pmdval, pmdp_get_lockless(pmd)))) {
 | 
							if (unlikely(!pmd_same(pmdval, pmdp_get_lockless(pmd)))) {
 | 
				
			||||||
			pte_unmap_unlock(pte, ptl);
 | 
								pte_unmap_unlock(pte, ptl);
 | 
				
			||||||
| 
						 | 
					@ -114,7 +113,7 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = do_adjust_pte(vma, address, pfn, pte);
 | 
						ret = do_adjust_pte(vma, address, pfn, pte);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ptl != vmf->ptl)
 | 
						if (need_lock)
 | 
				
			||||||
		spin_unlock(ptl);
 | 
							spin_unlock(ptl);
 | 
				
			||||||
	pte_unmap(pte);
 | 
						pte_unmap(pte);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,9 +122,10 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
make_coherent(struct address_space *mapping, struct vm_area_struct *vma,
 | 
					make_coherent(struct address_space *mapping, struct vm_area_struct *vma,
 | 
				
			||||||
	      unsigned long addr, pte_t *ptep, unsigned long pfn,
 | 
						      unsigned long addr, pte_t *ptep, unsigned long pfn)
 | 
				
			||||||
	      struct vm_fault *vmf)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						const unsigned long pmd_start_addr = ALIGN_DOWN(addr, PMD_SIZE);
 | 
				
			||||||
 | 
						const unsigned long pmd_end_addr = pmd_start_addr + PMD_SIZE;
 | 
				
			||||||
	struct mm_struct *mm = vma->vm_mm;
 | 
						struct mm_struct *mm = vma->vm_mm;
 | 
				
			||||||
	struct vm_area_struct *mpnt;
 | 
						struct vm_area_struct *mpnt;
 | 
				
			||||||
	unsigned long offset;
 | 
						unsigned long offset;
 | 
				
			||||||
| 
						 | 
					@ -141,6 +141,14 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma,
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	flush_dcache_mmap_lock(mapping);
 | 
						flush_dcache_mmap_lock(mapping);
 | 
				
			||||||
	vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
 | 
						vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * If we are using split PTE locks, then we need to take the pte
 | 
				
			||||||
 | 
							 * lock. Otherwise we are using shared mm->page_table_lock which
 | 
				
			||||||
 | 
							 * is already locked, thus cannot take it.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							bool need_lock = IS_ENABLED(CONFIG_SPLIT_PTE_PTLOCKS);
 | 
				
			||||||
 | 
							unsigned long mpnt_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * If this VMA is not in our MM, we can ignore it.
 | 
							 * If this VMA is not in our MM, we can ignore it.
 | 
				
			||||||
		 * Note that we intentionally mask out the VMA
 | 
							 * Note that we intentionally mask out the VMA
 | 
				
			||||||
| 
						 | 
					@ -151,7 +159,12 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma,
 | 
				
			||||||
		if (!(mpnt->vm_flags & VM_MAYSHARE))
 | 
							if (!(mpnt->vm_flags & VM_MAYSHARE))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
 | 
							offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
 | 
				
			||||||
		aliases += adjust_pte(mpnt, mpnt->vm_start + offset, pfn, vmf);
 | 
							mpnt_addr = mpnt->vm_start + offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Avoid deadlocks by not grabbing the same PTE lock again. */
 | 
				
			||||||
 | 
							if (mpnt_addr >= pmd_start_addr && mpnt_addr < pmd_end_addr)
 | 
				
			||||||
 | 
								need_lock = false;
 | 
				
			||||||
 | 
							aliases += adjust_pte(mpnt, mpnt_addr, pfn, need_lock);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	flush_dcache_mmap_unlock(mapping);
 | 
						flush_dcache_mmap_unlock(mapping);
 | 
				
			||||||
	if (aliases)
 | 
						if (aliases)
 | 
				
			||||||
| 
						 | 
					@ -194,7 +207,7 @@ void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma,
 | 
				
			||||||
		__flush_dcache_folio(mapping, folio);
 | 
							__flush_dcache_folio(mapping, folio);
 | 
				
			||||||
	if (mapping) {
 | 
						if (mapping) {
 | 
				
			||||||
		if (cache_is_vivt())
 | 
							if (cache_is_vivt())
 | 
				
			||||||
			make_coherent(mapping, vma, addr, ptep, pfn, vmf);
 | 
								make_coherent(mapping, vma, addr, ptep, pfn);
 | 
				
			||||||
		else if (vma->vm_flags & VM_EXEC)
 | 
							else if (vma->vm_flags & VM_EXEC)
 | 
				
			||||||
			__flush_icache_all();
 | 
								__flush_icache_all();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,32 @@
 | 
				
			||||||
#include <asm/sysreg.h>
 | 
					#include <asm/sysreg.h>
 | 
				
			||||||
#include <linux/irqchip/arm-gic-v3.h>
 | 
					#include <linux/irqchip/arm-gic-v3.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.macro init_el2_hcr	val
 | 
				
			||||||
 | 
						mov_q	x0, \val
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Compliant CPUs advertise their VHE-onlyness with
 | 
				
			||||||
 | 
						 * ID_AA64MMFR4_EL1.E2H0 < 0. On such CPUs HCR_EL2.E2H is RES1, but it
 | 
				
			||||||
 | 
						 * can reset into an UNKNOWN state and might not read as 1 until it has
 | 
				
			||||||
 | 
						 * been initialized explicitly.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Fruity CPUs seem to have HCR_EL2.E2H set to RAO/WI, but
 | 
				
			||||||
 | 
						 * don't advertise it (they predate this relaxation).
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Initalize HCR_EL2.E2H so that later code can rely upon HCR_EL2.E2H
 | 
				
			||||||
 | 
						 * indicating whether the CPU is running in E2H mode.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						mrs_s	x1, SYS_ID_AA64MMFR4_EL1
 | 
				
			||||||
 | 
						sbfx	x1, x1, #ID_AA64MMFR4_EL1_E2H0_SHIFT, #ID_AA64MMFR4_EL1_E2H0_WIDTH
 | 
				
			||||||
 | 
						cmp	x1, #0
 | 
				
			||||||
 | 
						b.ge	.LnVHE_\@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						orr	x0, x0, #HCR_E2H
 | 
				
			||||||
 | 
					.LnVHE_\@:
 | 
				
			||||||
 | 
						msr	hcr_el2, x0
 | 
				
			||||||
 | 
						isb
 | 
				
			||||||
 | 
					.endm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.macro __init_el2_sctlr
 | 
					.macro __init_el2_sctlr
 | 
				
			||||||
	mov_q	x0, INIT_SCTLR_EL2_MMU_OFF
 | 
						mov_q	x0, INIT_SCTLR_EL2_MMU_OFF
 | 
				
			||||||
	msr	sctlr_el2, x0
 | 
						msr	sctlr_el2, x0
 | 
				
			||||||
| 
						 | 
					@ -244,11 +270,6 @@
 | 
				
			||||||
.Lskip_gcs_\@:
 | 
					.Lskip_gcs_\@:
 | 
				
			||||||
.endm
 | 
					.endm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.macro __init_el2_nvhe_prepare_eret
 | 
					 | 
				
			||||||
	mov	x0, #INIT_PSTATE_EL1
 | 
					 | 
				
			||||||
	msr	spsr_el2, x0
 | 
					 | 
				
			||||||
.endm
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.macro __init_el2_mpam
 | 
					.macro __init_el2_mpam
 | 
				
			||||||
	/* Memory Partitioning And Monitoring: disable EL2 traps */
 | 
						/* Memory Partitioning And Monitoring: disable EL2 traps */
 | 
				
			||||||
	mrs	x1, id_aa64pfr0_el1
 | 
						mrs	x1, id_aa64pfr0_el1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -396,33 +396,35 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
 | 
				
			||||||
#define __flush_tlb_range_op(op, start, pages, stride,			\
 | 
					#define __flush_tlb_range_op(op, start, pages, stride,			\
 | 
				
			||||||
				asid, tlb_level, tlbi_user, lpa2)	\
 | 
									asid, tlb_level, tlbi_user, lpa2)	\
 | 
				
			||||||
do {									\
 | 
					do {									\
 | 
				
			||||||
 | 
						typeof(start) __flush_start = start;				\
 | 
				
			||||||
 | 
						typeof(pages) __flush_pages = pages;				\
 | 
				
			||||||
	int num = 0;							\
 | 
						int num = 0;							\
 | 
				
			||||||
	int scale = 3;							\
 | 
						int scale = 3;							\
 | 
				
			||||||
	int shift = lpa2 ? 16 : PAGE_SHIFT;				\
 | 
						int shift = lpa2 ? 16 : PAGE_SHIFT;				\
 | 
				
			||||||
	unsigned long addr;						\
 | 
						unsigned long addr;						\
 | 
				
			||||||
									\
 | 
														\
 | 
				
			||||||
	while (pages > 0) {						\
 | 
						while (__flush_pages > 0) {					\
 | 
				
			||||||
		if (!system_supports_tlb_range() ||			\
 | 
							if (!system_supports_tlb_range() ||			\
 | 
				
			||||||
		    pages == 1 ||					\
 | 
							    __flush_pages == 1 ||				\
 | 
				
			||||||
		    (lpa2 && start != ALIGN(start, SZ_64K))) {		\
 | 
							    (lpa2 && __flush_start != ALIGN(__flush_start, SZ_64K))) {	\
 | 
				
			||||||
			addr = __TLBI_VADDR(start, asid);		\
 | 
								addr = __TLBI_VADDR(__flush_start, asid);	\
 | 
				
			||||||
			__tlbi_level(op, addr, tlb_level);		\
 | 
								__tlbi_level(op, addr, tlb_level);		\
 | 
				
			||||||
			if (tlbi_user)					\
 | 
								if (tlbi_user)					\
 | 
				
			||||||
				__tlbi_user_level(op, addr, tlb_level);	\
 | 
									__tlbi_user_level(op, addr, tlb_level);	\
 | 
				
			||||||
			start += stride;				\
 | 
								__flush_start += stride;			\
 | 
				
			||||||
			pages -= stride >> PAGE_SHIFT;			\
 | 
								__flush_pages -= stride >> PAGE_SHIFT;		\
 | 
				
			||||||
			continue;					\
 | 
								continue;					\
 | 
				
			||||||
		}							\
 | 
							}							\
 | 
				
			||||||
									\
 | 
														\
 | 
				
			||||||
		num = __TLBI_RANGE_NUM(pages, scale);			\
 | 
							num = __TLBI_RANGE_NUM(__flush_pages, scale);		\
 | 
				
			||||||
		if (num >= 0) {						\
 | 
							if (num >= 0) {						\
 | 
				
			||||||
			addr = __TLBI_VADDR_RANGE(start >> shift, asid, \
 | 
								addr = __TLBI_VADDR_RANGE(__flush_start >> shift, asid, \
 | 
				
			||||||
						scale, num, tlb_level);	\
 | 
											scale, num, tlb_level);	\
 | 
				
			||||||
			__tlbi(r##op, addr);				\
 | 
								__tlbi(r##op, addr);				\
 | 
				
			||||||
			if (tlbi_user)					\
 | 
								if (tlbi_user)					\
 | 
				
			||||||
				__tlbi_user(r##op, addr);		\
 | 
									__tlbi_user(r##op, addr);		\
 | 
				
			||||||
			start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
 | 
								__flush_start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
 | 
				
			||||||
			pages -= __TLBI_RANGE_PAGES(num, scale);	\
 | 
								__flush_pages -= __TLBI_RANGE_PAGES(num, scale);\
 | 
				
			||||||
		}							\
 | 
							}							\
 | 
				
			||||||
		scale--;						\
 | 
							scale--;						\
 | 
				
			||||||
	}								\
 | 
						}								\
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -298,25 +298,8 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL)
 | 
				
			||||||
	msr	sctlr_el2, x0
 | 
						msr	sctlr_el2, x0
 | 
				
			||||||
	isb
 | 
						isb
 | 
				
			||||||
0:
 | 
					0:
 | 
				
			||||||
	mov_q	x0, HCR_HOST_NVHE_FLAGS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Compliant CPUs advertise their VHE-onlyness with
 | 
					 | 
				
			||||||
	 * ID_AA64MMFR4_EL1.E2H0 < 0. HCR_EL2.E2H can be
 | 
					 | 
				
			||||||
	 * RES1 in that case. Publish the E2H bit early so that
 | 
					 | 
				
			||||||
	 * it can be picked up by the init_el2_state macro.
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * Fruity CPUs seem to have HCR_EL2.E2H set to RAO/WI, but
 | 
					 | 
				
			||||||
	 * don't advertise it (they predate this relaxation).
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	mrs_s	x1, SYS_ID_AA64MMFR4_EL1
 | 
					 | 
				
			||||||
	tbz	x1, #(ID_AA64MMFR4_EL1_E2H0_SHIFT + ID_AA64MMFR4_EL1_E2H0_WIDTH - 1), 1f
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	orr	x0, x0, #HCR_E2H
 | 
					 | 
				
			||||||
1:
 | 
					 | 
				
			||||||
	msr	hcr_el2, x0
 | 
					 | 
				
			||||||
	isb
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						init_el2_hcr	HCR_HOST_NVHE_FLAGS
 | 
				
			||||||
	init_el2_state
 | 
						init_el2_state
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Hypervisor stub */
 | 
						/* Hypervisor stub */
 | 
				
			||||||
| 
						 | 
					@ -339,7 +322,8 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL)
 | 
				
			||||||
	msr	sctlr_el1, x1
 | 
						msr	sctlr_el1, x1
 | 
				
			||||||
	mov	x2, xzr
 | 
						mov	x2, xzr
 | 
				
			||||||
3:
 | 
					3:
 | 
				
			||||||
	__init_el2_nvhe_prepare_eret
 | 
						mov	x0, #INIT_PSTATE_EL1
 | 
				
			||||||
 | 
						msr	spsr_el2, x0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mov	w0, #BOOT_CPU_MODE_EL2
 | 
						mov	w0, #BOOT_CPU_MODE_EL2
 | 
				
			||||||
	orr	x0, x0, x2
 | 
						orr	x0, x0, x2
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,8 +73,12 @@ __do_hyp_init:
 | 
				
			||||||
	eret
 | 
						eret
 | 
				
			||||||
SYM_CODE_END(__kvm_hyp_init)
 | 
					SYM_CODE_END(__kvm_hyp_init)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Initialize EL2 CPU state to sane values.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * HCR_EL2.E2H must have been initialized already.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
SYM_CODE_START_LOCAL(__kvm_init_el2_state)
 | 
					SYM_CODE_START_LOCAL(__kvm_init_el2_state)
 | 
				
			||||||
	/* Initialize EL2 CPU state to sane values. */
 | 
					 | 
				
			||||||
	init_el2_state				// Clobbers x0..x2
 | 
						init_el2_state				// Clobbers x0..x2
 | 
				
			||||||
	finalise_el2_state
 | 
						finalise_el2_state
 | 
				
			||||||
	ret
 | 
						ret
 | 
				
			||||||
| 
						 | 
					@ -206,9 +210,9 @@ SYM_CODE_START_LOCAL(__kvm_hyp_init_cpu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2:	msr	SPsel, #1			// We want to use SP_EL{1,2}
 | 
					2:	msr	SPsel, #1			// We want to use SP_EL{1,2}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bl	__kvm_init_el2_state
 | 
						init_el2_hcr	0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	__init_el2_nvhe_prepare_eret
 | 
						bl	__kvm_init_el2_state
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Enable MMU, set vectors and stack. */
 | 
						/* Enable MMU, set vectors and stack. */
 | 
				
			||||||
	mov	x0, x28
 | 
						mov	x0, x28
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -218,6 +218,9 @@ asmlinkage void __noreturn __kvm_host_psci_cpu_entry(bool is_cpu_on)
 | 
				
			||||||
	if (is_cpu_on)
 | 
						if (is_cpu_on)
 | 
				
			||||||
		release_boot_args(boot_args);
 | 
							release_boot_args(boot_args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						write_sysreg_el1(INIT_SCTLR_EL1_MMU_OFF, SYS_SCTLR);
 | 
				
			||||||
 | 
						write_sysreg(INIT_PSTATE_EL1, SPSR_EL2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	__host_enter(host_ctxt);
 | 
						__host_enter(host_ctxt);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1177,8 +1177,11 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
 | 
				
			||||||
		struct vmem_altmap *altmap)
 | 
							struct vmem_altmap *altmap)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END));
 | 
						WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END));
 | 
				
			||||||
 | 
						/* [start, end] should be within one section */
 | 
				
			||||||
 | 
						WARN_ON_ONCE(end - start > PAGES_PER_SECTION * sizeof(struct page));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES))
 | 
						if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES) ||
 | 
				
			||||||
 | 
						    (end - start < PAGES_PER_SECTION * sizeof(struct page)))
 | 
				
			||||||
		return vmemmap_populate_basepages(start, end, node, altmap);
 | 
							return vmemmap_populate_basepages(start, end, node, altmap);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return vmemmap_populate_hugepages(start, end, node, altmap);
 | 
							return vmemmap_populate_hugepages(start, end, node, altmap);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -249,18 +249,6 @@ static __init int setup_node(int pxm)
 | 
				
			||||||
	return acpi_map_pxm_to_node(pxm);
 | 
						return acpi_map_pxm_to_node(pxm);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Callback for SLIT parsing.  pxm_to_node() returns NUMA_NO_NODE for
 | 
					 | 
				
			||||||
 * I/O localities since SRAT does not list them.  I/O localities are
 | 
					 | 
				
			||||||
 * not supported at this point.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
unsigned int numa_distance_cnt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline unsigned int get_numa_distances_cnt(struct acpi_table_slit *slit)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return slit->locality_count;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void __init numa_set_distance(int from, int to, int distance)
 | 
					void __init numa_set_distance(int from, int to, int distance)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if ((u8)distance != distance || (from == to && distance != LOCAL_DISTANCE)) {
 | 
						if ((u8)distance != distance || (from == to && distance != LOCAL_DISTANCE)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,14 +126,14 @@ void kexec_reboot(void)
 | 
				
			||||||
	/* All secondary cpus go to kexec_smp_wait */
 | 
						/* All secondary cpus go to kexec_smp_wait */
 | 
				
			||||||
	if (smp_processor_id() > 0) {
 | 
						if (smp_processor_id() > 0) {
 | 
				
			||||||
		relocated_kexec_smp_wait(NULL);
 | 
							relocated_kexec_smp_wait(NULL);
 | 
				
			||||||
		unreachable();
 | 
							BUG();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do_kexec = (void *)reboot_code_buffer;
 | 
						do_kexec = (void *)reboot_code_buffer;
 | 
				
			||||||
	do_kexec(efi_boot, cmdline_ptr, systable_ptr, start_addr, first_ind_entry);
 | 
						do_kexec(efi_boot, cmdline_ptr, systable_ptr, start_addr, first_ind_entry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unreachable();
 | 
						BUG();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -387,6 +387,9 @@ static void __init check_kernel_sections_mem(void)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void __init arch_mem_init(char **cmdline_p)
 | 
					static void __init arch_mem_init(char **cmdline_p)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						/* Recalculate max_low_pfn for "mem=xxx" */
 | 
				
			||||||
 | 
						max_pfn = max_low_pfn = PHYS_PFN(memblock_end_of_DRAM());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (usermem)
 | 
						if (usermem)
 | 
				
			||||||
		pr_info("User-defined physical RAM map overwrite\n");
 | 
							pr_info("User-defined physical RAM map overwrite\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@
 | 
				
			||||||
#include <linux/smp.h>
 | 
					#include <linux/smp.h>
 | 
				
			||||||
#include <linux/threads.h>
 | 
					#include <linux/threads.h>
 | 
				
			||||||
#include <linux/export.h>
 | 
					#include <linux/export.h>
 | 
				
			||||||
 | 
					#include <linux/suspend.h>
 | 
				
			||||||
#include <linux/syscore_ops.h>
 | 
					#include <linux/syscore_ops.h>
 | 
				
			||||||
#include <linux/time.h>
 | 
					#include <linux/time.h>
 | 
				
			||||||
#include <linux/tracepoint.h>
 | 
					#include <linux/tracepoint.h>
 | 
				
			||||||
| 
						 | 
					@ -423,7 +424,7 @@ void loongson_cpu_die(unsigned int cpu)
 | 
				
			||||||
	mb();
 | 
						mb();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void __noreturn arch_cpu_idle_dead(void)
 | 
					static void __noreturn idle_play_dead(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	register uint64_t addr;
 | 
						register uint64_t addr;
 | 
				
			||||||
	register void (*init_fn)(void);
 | 
						register void (*init_fn)(void);
 | 
				
			||||||
| 
						 | 
					@ -447,6 +448,50 @@ void __noreturn arch_cpu_idle_dead(void)
 | 
				
			||||||
	BUG();
 | 
						BUG();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_HIBERNATION
 | 
				
			||||||
 | 
					static void __noreturn poll_play_dead(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						register uint64_t addr;
 | 
				
			||||||
 | 
						register void (*init_fn)(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						idle_task_exit();
 | 
				
			||||||
 | 
						__this_cpu_write(cpu_state, CPU_DEAD);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__smp_mb();
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							__asm__ __volatile__("nop\n\t");
 | 
				
			||||||
 | 
							addr = iocsr_read64(LOONGARCH_IOCSR_MBUF0);
 | 
				
			||||||
 | 
						} while (addr == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						init_fn = (void *)TO_CACHE(addr);
 | 
				
			||||||
 | 
						iocsr_write32(0xffffffff, LOONGARCH_IOCSR_IPI_CLEAR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						init_fn();
 | 
				
			||||||
 | 
						BUG();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void (*play_dead)(void) = idle_play_dead;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void __noreturn arch_cpu_idle_dead(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						play_dead();
 | 
				
			||||||
 | 
						BUG(); /* play_dead() doesn't return */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_HIBERNATION
 | 
				
			||||||
 | 
					int hibernate_resume_nonboot_cpu_disable(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						play_dead = poll_play_dead;
 | 
				
			||||||
 | 
						ret = suspend_disable_secondary_cpus();
 | 
				
			||||||
 | 
						play_dead = idle_play_dead;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -669,6 +669,12 @@ static int kvm_handle_rdwr_fault(struct kvm_vcpu *vcpu, bool write)
 | 
				
			||||||
	struct kvm_run *run = vcpu->run;
 | 
						struct kvm_run *run = vcpu->run;
 | 
				
			||||||
	unsigned long badv = vcpu->arch.badv;
 | 
						unsigned long badv = vcpu->arch.badv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Inject ADE exception if exceed max GPA size */
 | 
				
			||||||
 | 
						if (unlikely(badv >= vcpu->kvm->arch.gpa_size)) {
 | 
				
			||||||
 | 
							kvm_queue_exception(vcpu, EXCCODE_ADE, EXSUBCODE_ADEM);
 | 
				
			||||||
 | 
							return RESUME_GUEST;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = kvm_handle_mm_fault(vcpu, badv, write);
 | 
						ret = kvm_handle_mm_fault(vcpu, badv, write);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		/* Treat as MMIO */
 | 
							/* Treat as MMIO */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -317,6 +317,13 @@ int kvm_arch_enable_virtualization_cpu(void)
 | 
				
			||||||
	kvm_debug("GCFG:%lx GSTAT:%lx GINTC:%lx GTLBC:%lx",
 | 
						kvm_debug("GCFG:%lx GSTAT:%lx GINTC:%lx GTLBC:%lx",
 | 
				
			||||||
		  read_csr_gcfg(), read_csr_gstat(), read_csr_gintc(), read_csr_gtlbc());
 | 
							  read_csr_gcfg(), read_csr_gstat(), read_csr_gintc(), read_csr_gtlbc());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * HW Guest CSR registers are lost after CPU suspend and resume.
 | 
				
			||||||
 | 
						 * Clear last_vcpu so that Guest CSR registers forced to reload
 | 
				
			||||||
 | 
						 * from vCPU SW state.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						this_cpu_ptr(vmcs)->last_vcpu = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -311,7 +311,7 @@ static int kvm_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret = RESUME_GUEST;
 | 
						int ret = RESUME_GUEST;
 | 
				
			||||||
	unsigned long estat = vcpu->arch.host_estat;
 | 
						unsigned long estat = vcpu->arch.host_estat;
 | 
				
			||||||
	u32 intr = estat & 0x1fff; /* Ignore NMI */
 | 
						u32 intr = estat & CSR_ESTAT_IS;
 | 
				
			||||||
	u32 ecode = (estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
 | 
						u32 ecode = (estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vcpu->mode = OUTSIDE_GUEST_MODE;
 | 
						vcpu->mode = OUTSIDE_GUEST_MODE;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,11 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 | 
				
			||||||
	if (kvm_pvtime_supported())
 | 
						if (kvm_pvtime_supported())
 | 
				
			||||||
		kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME);
 | 
							kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kvm->arch.gpa_size = BIT(cpu_vabits - 1);
 | 
						/*
 | 
				
			||||||
 | 
						 * cpu_vabits means user address space only (a half of total).
 | 
				
			||||||
 | 
						 * GPA size of VM is the same with the size of user address space.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						kvm->arch.gpa_size = BIT(cpu_vabits);
 | 
				
			||||||
	kvm->arch.root_level = CONFIG_PGTABLE_LEVELS - 1;
 | 
						kvm->arch.root_level = CONFIG_PGTABLE_LEVELS - 1;
 | 
				
			||||||
	kvm->arch.invalid_ptes[0] = 0;
 | 
						kvm->arch.invalid_ptes[0] = 0;
 | 
				
			||||||
	kvm->arch.invalid_ptes[1] = (unsigned long)invalid_pte_table;
 | 
						kvm->arch.invalid_ptes[1] = (unsigned long)invalid_pte_table;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
 | 
					 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#include <linux/export.h>
 | 
					#include <linux/export.h>
 | 
				
			||||||
 | 
					#include <linux/hugetlb.h>
 | 
				
			||||||
#include <linux/io.h>
 | 
					#include <linux/io.h>
 | 
				
			||||||
#include <linux/kfence.h>
 | 
					#include <linux/kfence.h>
 | 
				
			||||||
#include <linux/memblock.h>
 | 
					#include <linux/memblock.h>
 | 
				
			||||||
| 
						 | 
					@ -63,8 +64,11 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info.length = len;
 | 
						info.length = len;
 | 
				
			||||||
	info.align_mask = do_color_align ? (PAGE_MASK & SHM_ALIGN_MASK) : 0;
 | 
					 | 
				
			||||||
	info.align_offset = pgoff << PAGE_SHIFT;
 | 
						info.align_offset = pgoff << PAGE_SHIFT;
 | 
				
			||||||
 | 
						if (filp && is_file_hugepages(filp))
 | 
				
			||||||
 | 
							info.align_mask = huge_page_mask_align(filp);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							info.align_mask = do_color_align ? (PAGE_MASK & SHM_ALIGN_MASK) : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dir == DOWN) {
 | 
						if (dir == DOWN) {
 | 
				
			||||||
		info.flags = VM_UNMAPPED_AREA_TOPDOWN;
 | 
							info.flags = VM_UNMAPPED_AREA_TOPDOWN;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,8 +44,10 @@ static inline pgd_t * pgd_alloc(struct mm_struct *mm)
 | 
				
			||||||
	pgd_t *new_pgd;
 | 
						pgd_t *new_pgd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	new_pgd = __pgd_alloc(mm, 0);
 | 
						new_pgd = __pgd_alloc(mm, 0);
 | 
				
			||||||
 | 
						if (likely(new_pgd != NULL)) {
 | 
				
			||||||
		memcpy(new_pgd, swapper_pg_dir, PAGE_SIZE);
 | 
							memcpy(new_pgd, swapper_pg_dir, PAGE_SIZE);
 | 
				
			||||||
		memset(new_pgd, 0, (PAGE_OFFSET >> PGDIR_SHIFT));
 | 
							memset(new_pgd, 0, (PAGE_OFFSET >> PGDIR_SHIFT));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return new_pgd;
 | 
						return new_pgd;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@ config ARCH_SOPHGO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config ARCH_SPACEMIT
 | 
					config ARCH_SPACEMIT
 | 
				
			||||||
	bool "SpacemiT SoCs"
 | 
						bool "SpacemiT SoCs"
 | 
				
			||||||
 | 
						select PINCTRL
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  This enables support for SpacemiT SoC platform hardware.
 | 
						  This enables support for SpacemiT SoC platform hardware.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -266,12 +266,13 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
 | 
				
			||||||
		       struct ftrace_ops *op, struct ftrace_regs *fregs)
 | 
							       struct ftrace_ops *op, struct ftrace_regs *fregs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long *parent = &arch_ftrace_regs(fregs)->regs.gprs[14];
 | 
						unsigned long *parent = &arch_ftrace_regs(fregs)->regs.gprs[14];
 | 
				
			||||||
 | 
						unsigned long sp = arch_ftrace_regs(fregs)->regs.gprs[15];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (unlikely(ftrace_graph_is_dead()))
 | 
						if (unlikely(ftrace_graph_is_dead()))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	if (unlikely(atomic_read(¤t->tracing_graph_pause)))
 | 
						if (unlikely(atomic_read(¤t->tracing_graph_pause)))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	if (!function_graph_enter_regs(*parent, ip, 0, parent, fregs))
 | 
						if (!function_graph_enter_regs(*parent, ip, 0, (unsigned long *)sp, fregs))
 | 
				
			||||||
		*parent = (unsigned long)&return_to_handler;
 | 
							*parent = (unsigned long)&return_to_handler;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -285,10 +285,10 @@ static void __init test_monitor_call(void)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	asm volatile(
 | 
						asm volatile(
 | 
				
			||||||
		"	mc	0,0\n"
 | 
							"	mc	0,0\n"
 | 
				
			||||||
		"0:	xgr	%0,%0\n"
 | 
							"0:	lhi	%[val],0\n"
 | 
				
			||||||
		"1:\n"
 | 
							"1:\n"
 | 
				
			||||||
		EX_TABLE(0b,1b)
 | 
							EX_TABLE(0b, 1b)
 | 
				
			||||||
		: "+d" (val));
 | 
							: [val] "+d" (val));
 | 
				
			||||||
	if (!val)
 | 
						if (!val)
 | 
				
			||||||
		panic("Monitor call doesn't work!\n");
 | 
							panic("Monitor call doesn't work!\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1307,6 +1307,7 @@ config X86_REBOOTFIXUPS
 | 
				
			||||||
config MICROCODE
 | 
					config MICROCODE
 | 
				
			||||||
	def_bool y
 | 
						def_bool y
 | 
				
			||||||
	depends on CPU_SUP_AMD || CPU_SUP_INTEL
 | 
						depends on CPU_SUP_AMD || CPU_SUP_INTEL
 | 
				
			||||||
 | 
						select CRYPTO_LIB_SHA256 if CPU_SUP_AMD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config MICROCODE_INITRD32
 | 
					config MICROCODE_INITRD32
 | 
				
			||||||
	def_bool y
 | 
						def_bool y
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0
 | 
					// SPDX-License-Identifier: GPL-2.0
 | 
				
			||||||
#include "misc.h"
 | 
					#include "misc.h"
 | 
				
			||||||
#include <asm/bootparam.h>
 | 
					#include <asm/bootparam.h>
 | 
				
			||||||
 | 
					#include <asm/bootparam_utils.h>
 | 
				
			||||||
#include <asm/e820/types.h>
 | 
					#include <asm/e820/types.h>
 | 
				
			||||||
#include <asm/processor.h>
 | 
					#include <asm/processor.h>
 | 
				
			||||||
#include "pgtable.h"
 | 
					#include "pgtable.h"
 | 
				
			||||||
| 
						 | 
					@ -107,6 +108,7 @@ asmlinkage void configure_5level_paging(struct boot_params *bp, void *pgtable)
 | 
				
			||||||
	bool l5_required = false;
 | 
						bool l5_required = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Initialize boot_params. Required for cmdline_find_option_bool(). */
 | 
						/* Initialize boot_params. Required for cmdline_find_option_bool(). */
 | 
				
			||||||
 | 
						sanitize_boot_params(bp);
 | 
				
			||||||
	boot_params_ptr = bp;
 | 
						boot_params_ptr = bp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2853,19 +2853,8 @@ struct snp_msg_desc *snp_msg_alloc(void)
 | 
				
			||||||
	if (!mdesc->response)
 | 
						if (!mdesc->response)
 | 
				
			||||||
		goto e_free_request;
 | 
							goto e_free_request;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mdesc->certs_data = alloc_shared_pages(SEV_FW_BLOB_MAX_SIZE);
 | 
					 | 
				
			||||||
	if (!mdesc->certs_data)
 | 
					 | 
				
			||||||
		goto e_free_response;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* initial the input address for guest request */
 | 
					 | 
				
			||||||
	mdesc->input.req_gpa = __pa(mdesc->request);
 | 
					 | 
				
			||||||
	mdesc->input.resp_gpa = __pa(mdesc->response);
 | 
					 | 
				
			||||||
	mdesc->input.data_gpa = __pa(mdesc->certs_data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return mdesc;
 | 
						return mdesc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
e_free_response:
 | 
					 | 
				
			||||||
	free_shared_pages(mdesc->response, sizeof(struct snp_guest_msg));
 | 
					 | 
				
			||||||
e_free_request:
 | 
					e_free_request:
 | 
				
			||||||
	free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg));
 | 
						free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg));
 | 
				
			||||||
e_unmap:
 | 
					e_unmap:
 | 
				
			||||||
| 
						 | 
					@ -2885,7 +2874,6 @@ void snp_msg_free(struct snp_msg_desc *mdesc)
 | 
				
			||||||
	kfree(mdesc->ctx);
 | 
						kfree(mdesc->ctx);
 | 
				
			||||||
	free_shared_pages(mdesc->response, sizeof(struct snp_guest_msg));
 | 
						free_shared_pages(mdesc->response, sizeof(struct snp_guest_msg));
 | 
				
			||||||
	free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg));
 | 
						free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg));
 | 
				
			||||||
	free_shared_pages(mdesc->certs_data, SEV_FW_BLOB_MAX_SIZE);
 | 
					 | 
				
			||||||
	iounmap((__force void __iomem *)mdesc->secrets);
 | 
						iounmap((__force void __iomem *)mdesc->secrets);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(mdesc, 0, sizeof(*mdesc));
 | 
						memset(mdesc, 0, sizeof(*mdesc));
 | 
				
			||||||
| 
						 | 
					@ -3054,7 +3042,7 @@ static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_r
 | 
				
			||||||
	 * sequence number must be incremented or the VMPCK must be deleted to
 | 
						 * sequence number must be incremented or the VMPCK must be deleted to
 | 
				
			||||||
	 * prevent reuse of the IV.
 | 
						 * prevent reuse of the IV.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	rc = snp_issue_guest_request(req, &mdesc->input, rio);
 | 
						rc = snp_issue_guest_request(req, &req->input, rio);
 | 
				
			||||||
	switch (rc) {
 | 
						switch (rc) {
 | 
				
			||||||
	case -ENOSPC:
 | 
						case -ENOSPC:
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
| 
						 | 
					@ -3064,7 +3052,7 @@ static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_r
 | 
				
			||||||
		 * order to increment the sequence number and thus avoid
 | 
							 * order to increment the sequence number and thus avoid
 | 
				
			||||||
		 * IV reuse.
 | 
							 * IV reuse.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		override_npages = mdesc->input.data_npages;
 | 
							override_npages = req->input.data_npages;
 | 
				
			||||||
		req->exit_code	= SVM_VMGEXIT_GUEST_REQUEST;
 | 
							req->exit_code	= SVM_VMGEXIT_GUEST_REQUEST;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
| 
						 | 
					@ -3120,7 +3108,7 @@ static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_r
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (override_npages)
 | 
						if (override_npages)
 | 
				
			||||||
		mdesc->input.data_npages = override_npages;
 | 
							req->input.data_npages = override_npages;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -3158,6 +3146,11 @@ int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	memcpy(mdesc->request, &mdesc->secret_request, sizeof(mdesc->secret_request));
 | 
						memcpy(mdesc->request, &mdesc->secret_request, sizeof(mdesc->secret_request));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Initialize the input address for guest request */
 | 
				
			||||||
 | 
						req->input.req_gpa = __pa(mdesc->request);
 | 
				
			||||||
 | 
						req->input.resp_gpa = __pa(mdesc->response);
 | 
				
			||||||
 | 
						req->input.data_gpa = req->certs_data ? __pa(req->certs_data) : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = __handle_guest_request(mdesc, req, rio);
 | 
						rc = __handle_guest_request(mdesc, req, rio);
 | 
				
			||||||
	if (rc) {
 | 
						if (rc) {
 | 
				
			||||||
		if (rc == -EIO &&
 | 
							if (rc == -EIO &&
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,6 +30,7 @@ void __init hv_vtl_init_platform(void)
 | 
				
			||||||
	x86_platform.realmode_init = x86_init_noop;
 | 
						x86_platform.realmode_init = x86_init_noop;
 | 
				
			||||||
	x86_init.irqs.pre_vector_init = x86_init_noop;
 | 
						x86_init.irqs.pre_vector_init = x86_init_noop;
 | 
				
			||||||
	x86_init.timers.timer_init = x86_init_noop;
 | 
						x86_init.timers.timer_init = x86_init_noop;
 | 
				
			||||||
 | 
						x86_init.resources.probe_roms = x86_init_noop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Avoid searching for BIOS MP tables */
 | 
						/* Avoid searching for BIOS MP tables */
 | 
				
			||||||
	x86_init.mpparse.find_mptable = x86_init_noop;
 | 
						x86_init.mpparse.find_mptable = x86_init_noop;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -464,7 +464,6 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
 | 
				
			||||||
			   enum hv_mem_host_visibility visibility)
 | 
								   enum hv_mem_host_visibility visibility)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hv_gpa_range_for_visibility *input;
 | 
						struct hv_gpa_range_for_visibility *input;
 | 
				
			||||||
	u16 pages_processed;
 | 
					 | 
				
			||||||
	u64 hv_status;
 | 
						u64 hv_status;
 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -493,7 +492,7 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
 | 
				
			||||||
	memcpy((void *)input->gpa_page_list, pfn, count * sizeof(*pfn));
 | 
						memcpy((void *)input->gpa_page_list, pfn, count * sizeof(*pfn));
 | 
				
			||||||
	hv_status = hv_do_rep_hypercall(
 | 
						hv_status = hv_do_rep_hypercall(
 | 
				
			||||||
			HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY, count,
 | 
								HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY, count,
 | 
				
			||||||
			0, input, &pages_processed);
 | 
								0, input, NULL);
 | 
				
			||||||
	local_irq_restore(flags);
 | 
						local_irq_restore(flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (hv_result_success(hv_status))
 | 
						if (hv_result_success(hv_status))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -780,6 +780,7 @@ struct kvm_vcpu_arch {
 | 
				
			||||||
	u32 pkru;
 | 
						u32 pkru;
 | 
				
			||||||
	u32 hflags;
 | 
						u32 hflags;
 | 
				
			||||||
	u64 efer;
 | 
						u64 efer;
 | 
				
			||||||
 | 
						u64 host_debugctl;
 | 
				
			||||||
	u64 apic_base;
 | 
						u64 apic_base;
 | 
				
			||||||
	struct kvm_lapic *apic;    /* kernel irqchip context */
 | 
						struct kvm_lapic *apic;    /* kernel irqchip context */
 | 
				
			||||||
	bool load_eoi_exitmap_pending;
 | 
						bool load_eoi_exitmap_pending;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,17 +23,17 @@ typedef union {
 | 
				
			||||||
#define ARCH_PAGE_TABLE_SYNC_MASK	PGTBL_PMD_MODIFIED
 | 
					#define ARCH_PAGE_TABLE_SYNC_MASK	PGTBL_PMD_MODIFIED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * traditional i386 two-level paging structure:
 | 
					 * Traditional i386 two-level paging structure:
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PGDIR_SHIFT	22
 | 
					#define PGDIR_SHIFT	22
 | 
				
			||||||
#define PTRS_PER_PGD	1024
 | 
					#define PTRS_PER_PGD	1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * the i386 is two-level, so we don't really have any
 | 
					 * The i386 is two-level, so we don't really have any
 | 
				
			||||||
 * PMD directory physically.
 | 
					 * PMD directory physically:
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					#define PTRS_PER_PMD	1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PTRS_PER_PTE	1024
 | 
					#define PTRS_PER_PTE	1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -203,6 +203,9 @@ struct snp_guest_req {
 | 
				
			||||||
	unsigned int vmpck_id;
 | 
						unsigned int vmpck_id;
 | 
				
			||||||
	u8 msg_version;
 | 
						u8 msg_version;
 | 
				
			||||||
	u8 msg_type;
 | 
						u8 msg_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct snp_req_data input;
 | 
				
			||||||
 | 
						void *certs_data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -263,9 +266,6 @@ struct snp_msg_desc {
 | 
				
			||||||
	struct snp_guest_msg secret_request, secret_response;
 | 
						struct snp_guest_msg secret_request, secret_response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct snp_secrets_page *secrets;
 | 
						struct snp_secrets_page *secrets;
 | 
				
			||||||
	struct snp_req_data input;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void *certs_data;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct aesgcm_ctx *ctx;
 | 
						struct aesgcm_ctx *ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -143,7 +143,6 @@ bool __init early_is_amd_nb(u32 device)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct resource *amd_get_mmconfig_range(struct resource *res)
 | 
					struct resource *amd_get_mmconfig_range(struct resource *res)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32 address;
 | 
					 | 
				
			||||||
	u64 base, msr;
 | 
						u64 base, msr;
 | 
				
			||||||
	unsigned int segn_busn_bits;
 | 
						unsigned int segn_busn_bits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -151,13 +150,11 @@ struct resource *amd_get_mmconfig_range(struct resource *res)
 | 
				
			||||||
	    boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
 | 
						    boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* assume all cpus from fam10h have mmconfig */
 | 
						/* Assume CPUs from Fam10h have mmconfig, although not all VMs do */
 | 
				
			||||||
	if (boot_cpu_data.x86 < 0x10)
 | 
						if (boot_cpu_data.x86 < 0x10 ||
 | 
				
			||||||
 | 
						    rdmsrl_safe(MSR_FAM10H_MMIO_CONF_BASE, &msr))
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	address = MSR_FAM10H_MMIO_CONF_BASE;
 | 
					 | 
				
			||||||
	rdmsrl(address, msr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* mmconfig is not enabled */
 | 
						/* mmconfig is not enabled */
 | 
				
			||||||
	if (!(msr & FAM10H_MMIO_CONF_ENABLE))
 | 
						if (!(msr & FAM10H_MMIO_CONF_ENABLE))
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,14 +23,18 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/earlycpio.h>
 | 
					#include <linux/earlycpio.h>
 | 
				
			||||||
#include <linux/firmware.h>
 | 
					#include <linux/firmware.h>
 | 
				
			||||||
 | 
					#include <linux/bsearch.h>
 | 
				
			||||||
#include <linux/uaccess.h>
 | 
					#include <linux/uaccess.h>
 | 
				
			||||||
#include <linux/vmalloc.h>
 | 
					#include <linux/vmalloc.h>
 | 
				
			||||||
#include <linux/initrd.h>
 | 
					#include <linux/initrd.h>
 | 
				
			||||||
#include <linux/kernel.h>
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
#include <linux/pci.h>
 | 
					#include <linux/pci.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <crypto/sha2.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <asm/microcode.h>
 | 
					#include <asm/microcode.h>
 | 
				
			||||||
#include <asm/processor.h>
 | 
					#include <asm/processor.h>
 | 
				
			||||||
 | 
					#include <asm/cmdline.h>
 | 
				
			||||||
#include <asm/setup.h>
 | 
					#include <asm/setup.h>
 | 
				
			||||||
#include <asm/cpu.h>
 | 
					#include <asm/cpu.h>
 | 
				
			||||||
#include <asm/msr.h>
 | 
					#include <asm/msr.h>
 | 
				
			||||||
| 
						 | 
					@ -145,6 +149,113 @@ ucode_path[] __maybe_unused = "kernel/x86/microcode/AuthenticAMD.bin";
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static u32 bsp_cpuid_1_eax __ro_after_init;
 | 
					static u32 bsp_cpuid_1_eax __ro_after_init;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool sha_check = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct patch_digest {
 | 
				
			||||||
 | 
						u32 patch_id;
 | 
				
			||||||
 | 
						u8 sha256[SHA256_DIGEST_SIZE];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "amd_shas.c"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int cmp_id(const void *key, const void *elem)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct patch_digest *pd = (struct patch_digest *)elem;
 | 
				
			||||||
 | 
						u32 patch_id = *(u32 *)key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (patch_id == pd->patch_id)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						else if (patch_id < pd->patch_id)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool need_sha_check(u32 cur_rev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (cur_rev >> 8) {
 | 
				
			||||||
 | 
						case 0x80012: return cur_rev <= 0x800126f; break;
 | 
				
			||||||
 | 
						case 0x80082: return cur_rev <= 0x800820f; break;
 | 
				
			||||||
 | 
						case 0x83010: return cur_rev <= 0x830107c; break;
 | 
				
			||||||
 | 
						case 0x86001: return cur_rev <= 0x860010e; break;
 | 
				
			||||||
 | 
						case 0x86081: return cur_rev <= 0x8608108; break;
 | 
				
			||||||
 | 
						case 0x87010: return cur_rev <= 0x8701034; break;
 | 
				
			||||||
 | 
						case 0x8a000: return cur_rev <= 0x8a0000a; break;
 | 
				
			||||||
 | 
						case 0xa0010: return cur_rev <= 0xa00107a; break;
 | 
				
			||||||
 | 
						case 0xa0011: return cur_rev <= 0xa0011da; break;
 | 
				
			||||||
 | 
						case 0xa0012: return cur_rev <= 0xa001243; break;
 | 
				
			||||||
 | 
						case 0xa0082: return cur_rev <= 0xa00820e; break;
 | 
				
			||||||
 | 
						case 0xa1011: return cur_rev <= 0xa101153; break;
 | 
				
			||||||
 | 
						case 0xa1012: return cur_rev <= 0xa10124e; break;
 | 
				
			||||||
 | 
						case 0xa1081: return cur_rev <= 0xa108109; break;
 | 
				
			||||||
 | 
						case 0xa2010: return cur_rev <= 0xa20102f; break;
 | 
				
			||||||
 | 
						case 0xa2012: return cur_rev <= 0xa201212; break;
 | 
				
			||||||
 | 
						case 0xa4041: return cur_rev <= 0xa404109; break;
 | 
				
			||||||
 | 
						case 0xa5000: return cur_rev <= 0xa500013; break;
 | 
				
			||||||
 | 
						case 0xa6012: return cur_rev <= 0xa60120a; break;
 | 
				
			||||||
 | 
						case 0xa7041: return cur_rev <= 0xa704109; break;
 | 
				
			||||||
 | 
						case 0xa7052: return cur_rev <= 0xa705208; break;
 | 
				
			||||||
 | 
						case 0xa7080: return cur_rev <= 0xa708009; break;
 | 
				
			||||||
 | 
						case 0xa70c0: return cur_rev <= 0xa70C009; break;
 | 
				
			||||||
 | 
						case 0xaa001: return cur_rev <= 0xaa00116; break;
 | 
				
			||||||
 | 
						case 0xaa002: return cur_rev <= 0xaa00218; break;
 | 
				
			||||||
 | 
						default: break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pr_info("You should not be seeing this. Please send the following couple of lines to x86-<at>-kernel.org\n");
 | 
				
			||||||
 | 
						pr_info("CPUID(1).EAX: 0x%x, current revision: 0x%x\n", bsp_cpuid_1_eax, cur_rev);
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool verify_sha256_digest(u32 patch_id, u32 cur_rev, const u8 *data, unsigned int len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct patch_digest *pd = NULL;
 | 
				
			||||||
 | 
						u8 digest[SHA256_DIGEST_SIZE];
 | 
				
			||||||
 | 
						struct sha256_state s;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (x86_family(bsp_cpuid_1_eax) < 0x17 ||
 | 
				
			||||||
 | 
						    x86_family(bsp_cpuid_1_eax) > 0x19)
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!need_sha_check(cur_rev))
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!sha_check)
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pd = bsearch(&patch_id, phashes, ARRAY_SIZE(phashes), sizeof(struct patch_digest), cmp_id);
 | 
				
			||||||
 | 
						if (!pd) {
 | 
				
			||||||
 | 
							pr_err("No sha256 digest for patch ID: 0x%x found\n", patch_id);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sha256_init(&s);
 | 
				
			||||||
 | 
						sha256_update(&s, data, len);
 | 
				
			||||||
 | 
						sha256_final(&s, digest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (memcmp(digest, pd->sha256, sizeof(digest))) {
 | 
				
			||||||
 | 
							pr_err("Patch 0x%x SHA256 digest mismatch!\n", patch_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (i = 0; i < SHA256_DIGEST_SIZE; i++)
 | 
				
			||||||
 | 
								pr_cont("0x%x ", digest[i]);
 | 
				
			||||||
 | 
							pr_info("\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static u32 get_patch_level(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 rev, dummy __always_unused;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rev;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static union cpuid_1_eax ucode_rev_to_cpuid(unsigned int val)
 | 
					static union cpuid_1_eax ucode_rev_to_cpuid(unsigned int val)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	union zen_patch_rev p;
 | 
						union zen_patch_rev p;
 | 
				
			||||||
| 
						 | 
					@ -246,8 +357,7 @@ static bool verify_equivalence_table(const u8 *buf, size_t buf_size)
 | 
				
			||||||
 * On success, @sh_psize returns the patch size according to the section header,
 | 
					 * On success, @sh_psize returns the patch size according to the section header,
 | 
				
			||||||
 * to the caller.
 | 
					 * to the caller.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static bool
 | 
					static bool __verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize)
 | 
				
			||||||
__verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32 p_type, p_size;
 | 
						u32 p_type, p_size;
 | 
				
			||||||
	const u32 *hdr;
 | 
						const u32 *hdr;
 | 
				
			||||||
| 
						 | 
					@ -484,10 +594,13 @@ static void scan_containers(u8 *ucode, size_t size, struct cont_desc *desc)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize)
 | 
					static bool __apply_microcode_amd(struct microcode_amd *mc, u32 *cur_rev,
 | 
				
			||||||
 | 
									  unsigned int psize)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long p_addr = (unsigned long)&mc->hdr.data_code;
 | 
						unsigned long p_addr = (unsigned long)&mc->hdr.data_code;
 | 
				
			||||||
	u32 rev, dummy;
 | 
					
 | 
				
			||||||
 | 
						if (!verify_sha256_digest(mc->hdr.patch_id, *cur_rev, (const u8 *)p_addr, psize))
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr);
 | 
						native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -505,47 +618,13 @@ static bool __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* verify patch application was successful */
 | 
						/* verify patch application was successful */
 | 
				
			||||||
	native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
 | 
						*cur_rev = get_patch_level();
 | 
				
			||||||
 | 
						if (*cur_rev != mc->hdr.patch_id)
 | 
				
			||||||
	if (rev != mc->hdr.patch_id)
 | 
					 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Early load occurs before we can vmalloc(). So we look for the microcode
 | 
					 | 
				
			||||||
 * patch container file in initrd, traverse equivalent cpu table, look for a
 | 
					 | 
				
			||||||
 * matching microcode patch, and update, all in initrd memory in place.
 | 
					 | 
				
			||||||
 * When vmalloc() is available for use later -- on 64-bit during first AP load,
 | 
					 | 
				
			||||||
 * and on 32-bit during save_microcode_in_initrd_amd() -- we can call
 | 
					 | 
				
			||||||
 * load_microcode_amd() to save equivalent cpu table and microcode patches in
 | 
					 | 
				
			||||||
 * kernel heap memory.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Returns true if container found (sets @desc), false otherwise.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static bool early_apply_microcode(u32 old_rev, void *ucode, size_t size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct cont_desc desc = { 0 };
 | 
					 | 
				
			||||||
	struct microcode_amd *mc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	scan_containers(ucode, size, &desc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mc = desc.mc;
 | 
					 | 
				
			||||||
	if (!mc)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Allow application of the same revision to pick up SMT-specific
 | 
					 | 
				
			||||||
	 * changes even if the revision of the other SMT thread is already
 | 
					 | 
				
			||||||
	 * up-to-date.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (old_rev > mc->hdr.patch_id)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return __apply_microcode_amd(mc, desc.psize);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool get_builtin_microcode(struct cpio_data *cp)
 | 
					static bool get_builtin_microcode(struct cpio_data *cp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char fw_name[36] = "amd-ucode/microcode_amd.bin";
 | 
						char fw_name[36] = "amd-ucode/microcode_amd.bin";
 | 
				
			||||||
| 
						 | 
					@ -583,14 +662,35 @@ static bool __init find_blobs_in_containers(struct cpio_data *ret)
 | 
				
			||||||
	return found;
 | 
						return found;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Early load occurs before we can vmalloc(). So we look for the microcode
 | 
				
			||||||
 | 
					 * patch container file in initrd, traverse equivalent cpu table, look for a
 | 
				
			||||||
 | 
					 * matching microcode patch, and update, all in initrd memory in place.
 | 
				
			||||||
 | 
					 * When vmalloc() is available for use later -- on 64-bit during first AP load,
 | 
				
			||||||
 | 
					 * and on 32-bit during save_microcode_in_initrd() -- we can call
 | 
				
			||||||
 | 
					 * load_microcode_amd() to save equivalent cpu table and microcode patches in
 | 
				
			||||||
 | 
					 * kernel heap memory.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_eax)
 | 
					void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_eax)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct cont_desc desc = { };
 | 
				
			||||||
 | 
						struct microcode_amd *mc;
 | 
				
			||||||
	struct cpio_data cp = { };
 | 
						struct cpio_data cp = { };
 | 
				
			||||||
	u32 dummy;
 | 
						char buf[4];
 | 
				
			||||||
 | 
						u32 rev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cmdline_find_option(boot_command_line, "microcode.amd_sha_check", buf, 4)) {
 | 
				
			||||||
 | 
							if (!strncmp(buf, "off", 3)) {
 | 
				
			||||||
 | 
								sha_check = false;
 | 
				
			||||||
 | 
								pr_warn_once("It is a very very bad idea to disable the blobs SHA check!\n");
 | 
				
			||||||
 | 
								add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bsp_cpuid_1_eax = cpuid_1_eax;
 | 
						bsp_cpuid_1_eax = cpuid_1_eax;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->old_rev, dummy);
 | 
						rev = get_patch_level();
 | 
				
			||||||
 | 
						ed->old_rev = rev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Needed in load_microcode_amd() */
 | 
						/* Needed in load_microcode_amd() */
 | 
				
			||||||
	ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax;
 | 
						ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax;
 | 
				
			||||||
| 
						 | 
					@ -598,37 +698,23 @@ void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_
 | 
				
			||||||
	if (!find_blobs_in_containers(&cp))
 | 
						if (!find_blobs_in_containers(&cp))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (early_apply_microcode(ed->old_rev, cp.data, cp.size))
 | 
					 | 
				
			||||||
		native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init save_microcode_in_initrd(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned int cpuid_1_eax = native_cpuid_eax(1);
 | 
					 | 
				
			||||||
	struct cpuinfo_x86 *c = &boot_cpu_data;
 | 
					 | 
				
			||||||
	struct cont_desc desc = { 0 };
 | 
					 | 
				
			||||||
	enum ucode_state ret;
 | 
					 | 
				
			||||||
	struct cpio_data cp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!find_blobs_in_containers(&cp))
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	scan_containers(cp.data, cp.size, &desc);
 | 
						scan_containers(cp.data, cp.size, &desc);
 | 
				
			||||||
	if (!desc.mc)
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = _load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size);
 | 
						mc = desc.mc;
 | 
				
			||||||
	if (ret > UCODE_UPDATED)
 | 
						if (!mc)
 | 
				
			||||||
		return -EINVAL;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						/*
 | 
				
			||||||
 | 
						 * Allow application of the same revision to pick up SMT-specific
 | 
				
			||||||
 | 
						 * changes even if the revision of the other SMT thread is already
 | 
				
			||||||
 | 
						 * up-to-date.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (ed->old_rev > mc->hdr.patch_id)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (__apply_microcode_amd(mc, &rev, desc.psize))
 | 
				
			||||||
 | 
							ed->new_rev = rev;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
early_initcall(save_microcode_in_initrd);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline bool patch_cpus_equivalent(struct ucode_patch *p,
 | 
					static inline bool patch_cpus_equivalent(struct ucode_patch *p,
 | 
				
			||||||
					 struct ucode_patch *n,
 | 
										 struct ucode_patch *n,
 | 
				
			||||||
| 
						 | 
					@ -729,14 +815,9 @@ static void free_cache(void)
 | 
				
			||||||
static struct ucode_patch *find_patch(unsigned int cpu)
 | 
					static struct ucode_patch *find_patch(unsigned int cpu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 | 
						struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 | 
				
			||||||
	u32 rev, dummy __always_unused;
 | 
					 | 
				
			||||||
	u16 equiv_id = 0;
 | 
						u16 equiv_id = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* fetch rev if not populated yet: */
 | 
						uci->cpu_sig.rev = get_patch_level();
 | 
				
			||||||
	if (!uci->cpu_sig.rev) {
 | 
					 | 
				
			||||||
		rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
 | 
					 | 
				
			||||||
		uci->cpu_sig.rev = rev;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (x86_family(bsp_cpuid_1_eax) < 0x17) {
 | 
						if (x86_family(bsp_cpuid_1_eax) < 0x17) {
 | 
				
			||||||
		equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig);
 | 
							equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig);
 | 
				
			||||||
| 
						 | 
					@ -759,22 +840,20 @@ void reload_ucode_amd(unsigned int cpu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mc = p->data;
 | 
						mc = p->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
 | 
						rev = get_patch_level();
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (rev < mc->hdr.patch_id) {
 | 
						if (rev < mc->hdr.patch_id) {
 | 
				
			||||||
		if (__apply_microcode_amd(mc, p->size))
 | 
							if (__apply_microcode_amd(mc, &rev, p->size))
 | 
				
			||||||
			pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id);
 | 
								pr_info_once("reload revision: 0x%08x\n", rev);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
 | 
					static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct cpuinfo_x86 *c = &cpu_data(cpu);
 | 
					 | 
				
			||||||
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 | 
						struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 | 
				
			||||||
	struct ucode_patch *p;
 | 
						struct ucode_patch *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	csig->sig = cpuid_eax(0x00000001);
 | 
						csig->sig = cpuid_eax(0x00000001);
 | 
				
			||||||
	csig->rev = c->microcode;
 | 
						csig->rev = get_patch_level();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * a patch could have been loaded early, set uci->mc so that
 | 
						 * a patch could have been loaded early, set uci->mc so that
 | 
				
			||||||
| 
						 | 
					@ -815,7 +894,7 @@ static enum ucode_state apply_microcode_amd(int cpu)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!__apply_microcode_amd(mc_amd, p->size)) {
 | 
						if (!__apply_microcode_amd(mc_amd, &rev, p->size)) {
 | 
				
			||||||
		pr_err("CPU%d: update failed for patch_level=0x%08x\n",
 | 
							pr_err("CPU%d: update failed for patch_level=0x%08x\n",
 | 
				
			||||||
			cpu, mc_amd->hdr.patch_id);
 | 
								cpu, mc_amd->hdr.patch_id);
 | 
				
			||||||
		return UCODE_ERROR;
 | 
							return UCODE_ERROR;
 | 
				
			||||||
| 
						 | 
					@ -937,8 +1016,7 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Scan the blob in @data and add microcode patches to the cache. */
 | 
					/* Scan the blob in @data and add microcode patches to the cache. */
 | 
				
			||||||
static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
 | 
					static enum ucode_state __load_microcode_amd(u8 family, const u8 *data, size_t size)
 | 
				
			||||||
					     size_t size)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u8 *fw = (u8 *)data;
 | 
						u8 *fw = (u8 *)data;
 | 
				
			||||||
	size_t offset;
 | 
						size_t offset;
 | 
				
			||||||
| 
						 | 
					@ -996,7 +1074,7 @@ static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t siz
 | 
				
			||||||
	if (ret != UCODE_OK)
 | 
						if (ret != UCODE_OK)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for_each_node(nid) {
 | 
						for_each_node_with_cpus(nid) {
 | 
				
			||||||
		cpu = cpumask_first(cpumask_of_node(nid));
 | 
							cpu = cpumask_first(cpumask_of_node(nid));
 | 
				
			||||||
		c = &cpu_data(cpu);
 | 
							c = &cpu_data(cpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1013,6 +1091,32 @@ static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t siz
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __init save_microcode_in_initrd(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int cpuid_1_eax = native_cpuid_eax(1);
 | 
				
			||||||
 | 
						struct cpuinfo_x86 *c = &boot_cpu_data;
 | 
				
			||||||
 | 
						struct cont_desc desc = { 0 };
 | 
				
			||||||
 | 
						enum ucode_state ret;
 | 
				
			||||||
 | 
						struct cpio_data cp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!find_blobs_in_containers(&cp))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						scan_containers(cp.data, cp.size, &desc);
 | 
				
			||||||
 | 
						if (!desc.mc)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = _load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size);
 | 
				
			||||||
 | 
						if (ret > UCODE_UPDATED)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					early_initcall(save_microcode_in_initrd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * AMD microcode firmware naming convention, up to family 15h they are in
 | 
					 * AMD microcode firmware naming convention, up to family 15h they are in
 | 
				
			||||||
 * the legacy file:
 | 
					 * the legacy file:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										444
									
								
								arch/x86/kernel/cpu/microcode/amd_shas.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										444
									
								
								arch/x86/kernel/cpu/microcode/amd_shas.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,444 @@
 | 
				
			||||||
 | 
					/* Keep 'em sorted. */
 | 
				
			||||||
 | 
					static const struct patch_digest phashes[] = {
 | 
				
			||||||
 | 
					 { 0x8001227, {
 | 
				
			||||||
 | 
							0x99,0xc0,0x9b,0x2b,0xcc,0x9f,0x52,0x1b,
 | 
				
			||||||
 | 
							0x1a,0x5f,0x1d,0x83,0xa1,0x6c,0xc4,0x46,
 | 
				
			||||||
 | 
							0xe2,0x6c,0xda,0x73,0xfb,0x2d,0x23,0xa8,
 | 
				
			||||||
 | 
							0x77,0xdc,0x15,0x31,0x33,0x4a,0x46,0x18,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x8001250, {
 | 
				
			||||||
 | 
							0xc0,0x0b,0x6b,0x19,0xfd,0x5c,0x39,0x60,
 | 
				
			||||||
 | 
							0xd5,0xc3,0x57,0x46,0x54,0xe4,0xd1,0xaa,
 | 
				
			||||||
 | 
							0xa8,0xf7,0x1f,0xa8,0x6a,0x60,0x3e,0xe3,
 | 
				
			||||||
 | 
							0x27,0x39,0x8e,0x53,0x30,0xf8,0x49,0x19,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x800126e, {
 | 
				
			||||||
 | 
							0xf3,0x8b,0x2b,0xb6,0x34,0xe3,0xc8,0x2c,
 | 
				
			||||||
 | 
							0xef,0xec,0x63,0x6d,0xc8,0x76,0x77,0xb3,
 | 
				
			||||||
 | 
							0x25,0x5a,0xb7,0x52,0x8c,0x83,0x26,0xe6,
 | 
				
			||||||
 | 
							0x4c,0xbe,0xbf,0xe9,0x7d,0x22,0x6a,0x43,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x800126f, {
 | 
				
			||||||
 | 
							0x2b,0x5a,0xf2,0x9c,0xdd,0xd2,0x7f,0xec,
 | 
				
			||||||
 | 
							0xec,0x96,0x09,0x57,0xb0,0x96,0x29,0x8b,
 | 
				
			||||||
 | 
							0x2e,0x26,0x91,0xf0,0x49,0x33,0x42,0x18,
 | 
				
			||||||
 | 
							0xdd,0x4b,0x65,0x5a,0xd4,0x15,0x3d,0x33,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x800820d, {
 | 
				
			||||||
 | 
							0x68,0x98,0x83,0xcd,0x22,0x0d,0xdd,0x59,
 | 
				
			||||||
 | 
							0x73,0x2c,0x5b,0x37,0x1f,0x84,0x0e,0x67,
 | 
				
			||||||
 | 
							0x96,0x43,0x83,0x0c,0x46,0x44,0xab,0x7c,
 | 
				
			||||||
 | 
							0x7b,0x65,0x9e,0x57,0xb5,0x90,0x4b,0x0e,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x8301025, {
 | 
				
			||||||
 | 
							0xe4,0x7d,0xdb,0x1e,0x14,0xb4,0x5e,0x36,
 | 
				
			||||||
 | 
							0x8f,0x3e,0x48,0x88,0x3c,0x6d,0x76,0xa1,
 | 
				
			||||||
 | 
							0x59,0xc6,0xc0,0x72,0x42,0xdf,0x6c,0x30,
 | 
				
			||||||
 | 
							0x6f,0x0b,0x28,0x16,0x61,0xfc,0x79,0x77,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x8301055, {
 | 
				
			||||||
 | 
							0x81,0x7b,0x99,0x1b,0xae,0x2d,0x4f,0x9a,
 | 
				
			||||||
 | 
							0xef,0x13,0xce,0xb5,0x10,0xaf,0x6a,0xea,
 | 
				
			||||||
 | 
							0xe5,0xb0,0x64,0x98,0x10,0x68,0x34,0x3b,
 | 
				
			||||||
 | 
							0x9d,0x7a,0xd6,0x22,0x77,0x5f,0xb3,0x5b,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x8301072, {
 | 
				
			||||||
 | 
							0xcf,0x76,0xa7,0x1a,0x49,0xdf,0x2a,0x5e,
 | 
				
			||||||
 | 
							0x9e,0x40,0x70,0xe5,0xdd,0x8a,0xa8,0x28,
 | 
				
			||||||
 | 
							0x20,0xdc,0x91,0xd8,0x2c,0xa6,0xa0,0xb1,
 | 
				
			||||||
 | 
							0x2d,0x22,0x26,0x94,0x4b,0x40,0x85,0x30,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x830107a, {
 | 
				
			||||||
 | 
							0x2a,0x65,0x8c,0x1a,0x5e,0x07,0x21,0x72,
 | 
				
			||||||
 | 
							0xdf,0x90,0xa6,0x51,0x37,0xd3,0x4b,0x34,
 | 
				
			||||||
 | 
							0xc4,0xda,0x03,0xe1,0x8a,0x6c,0xfb,0x20,
 | 
				
			||||||
 | 
							0x04,0xb2,0x81,0x05,0xd4,0x87,0xf4,0x0a,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x830107b, {
 | 
				
			||||||
 | 
							0xb3,0x43,0x13,0x63,0x56,0xc1,0x39,0xad,
 | 
				
			||||||
 | 
							0x10,0xa6,0x2b,0xcc,0x02,0xe6,0x76,0x2a,
 | 
				
			||||||
 | 
							0x1e,0x39,0x58,0x3e,0x23,0x6e,0xa4,0x04,
 | 
				
			||||||
 | 
							0x95,0xea,0xf9,0x6d,0xc2,0x8a,0x13,0x19,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x830107c, {
 | 
				
			||||||
 | 
							0x21,0x64,0xde,0xfb,0x9f,0x68,0x96,0x47,
 | 
				
			||||||
 | 
							0x70,0x5c,0xe2,0x8f,0x18,0x52,0x6a,0xac,
 | 
				
			||||||
 | 
							0xa4,0xd2,0x2e,0xe0,0xde,0x68,0x66,0xc3,
 | 
				
			||||||
 | 
							0xeb,0x1e,0xd3,0x3f,0xbc,0x51,0x1d,0x38,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x860010d, {
 | 
				
			||||||
 | 
							0x86,0xb6,0x15,0x83,0xbc,0x3b,0x9c,0xe0,
 | 
				
			||||||
 | 
							0xb3,0xef,0x1d,0x99,0x84,0x35,0x15,0xf7,
 | 
				
			||||||
 | 
							0x7c,0x2a,0xc6,0x42,0xdb,0x73,0x07,0x5c,
 | 
				
			||||||
 | 
							0x7d,0xc3,0x02,0xb5,0x43,0x06,0x5e,0xf8,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x8608108, {
 | 
				
			||||||
 | 
							0x14,0xfe,0x57,0x86,0x49,0xc8,0x68,0xe2,
 | 
				
			||||||
 | 
							0x11,0xa3,0xcb,0x6e,0xff,0x6e,0xd5,0x38,
 | 
				
			||||||
 | 
							0xfe,0x89,0x1a,0xe0,0x67,0xbf,0xc4,0xcc,
 | 
				
			||||||
 | 
							0x1b,0x9f,0x84,0x77,0x2b,0x9f,0xaa,0xbd,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x8701034, {
 | 
				
			||||||
 | 
							0xc3,0x14,0x09,0xa8,0x9c,0x3f,0x8d,0x83,
 | 
				
			||||||
 | 
							0x9b,0x4c,0xa5,0xb7,0x64,0x8b,0x91,0x5d,
 | 
				
			||||||
 | 
							0x85,0x6a,0x39,0x26,0x1e,0x14,0x41,0xa8,
 | 
				
			||||||
 | 
							0x75,0xea,0xa6,0xf9,0xc9,0xd1,0xea,0x2b,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x8a00008, {
 | 
				
			||||||
 | 
							0xd7,0x2a,0x93,0xdc,0x05,0x2f,0xa5,0x6e,
 | 
				
			||||||
 | 
							0x0c,0x61,0x2c,0x07,0x9f,0x38,0xe9,0x8e,
 | 
				
			||||||
 | 
							0xef,0x7d,0x2a,0x05,0x4d,0x56,0xaf,0x72,
 | 
				
			||||||
 | 
							0xe7,0x56,0x47,0x6e,0x60,0x27,0xd5,0x8c,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0x8a0000a, {
 | 
				
			||||||
 | 
							0x73,0x31,0x26,0x22,0xd4,0xf9,0xee,0x3c,
 | 
				
			||||||
 | 
							0x07,0x06,0xe7,0xb9,0xad,0xd8,0x72,0x44,
 | 
				
			||||||
 | 
							0x33,0x31,0xaa,0x7d,0xc3,0x67,0x0e,0xdb,
 | 
				
			||||||
 | 
							0x47,0xb5,0xaa,0xbc,0xf5,0xbb,0xd9,0x20,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa00104c, {
 | 
				
			||||||
 | 
							0x3c,0x8a,0xfe,0x04,0x62,0xd8,0x6d,0xbe,
 | 
				
			||||||
 | 
							0xa7,0x14,0x28,0x64,0x75,0xc0,0xa3,0x76,
 | 
				
			||||||
 | 
							0xb7,0x92,0x0b,0x97,0x0a,0x8e,0x9c,0x5b,
 | 
				
			||||||
 | 
							0x1b,0xc8,0x9d,0x3a,0x1e,0x81,0x3d,0x3b,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa00104e, {
 | 
				
			||||||
 | 
							0xc4,0x35,0x82,0x67,0xd2,0x86,0xe5,0xb2,
 | 
				
			||||||
 | 
							0xfd,0x69,0x12,0x38,0xc8,0x77,0xba,0xe0,
 | 
				
			||||||
 | 
							0x70,0xf9,0x77,0x89,0x10,0xa6,0x74,0x4e,
 | 
				
			||||||
 | 
							0x56,0x58,0x13,0xf5,0x84,0x70,0x28,0x0b,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001053, {
 | 
				
			||||||
 | 
							0x92,0x0e,0xf4,0x69,0x10,0x3b,0xf9,0x9d,
 | 
				
			||||||
 | 
							0x31,0x1b,0xa6,0x99,0x08,0x7d,0xd7,0x25,
 | 
				
			||||||
 | 
							0x7e,0x1e,0x89,0xba,0x35,0x8d,0xac,0xcb,
 | 
				
			||||||
 | 
							0x3a,0xb4,0xdf,0x58,0x12,0xcf,0xc0,0xc3,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001058, {
 | 
				
			||||||
 | 
							0x33,0x7d,0xa9,0xb5,0x4e,0x62,0x13,0x36,
 | 
				
			||||||
 | 
							0xef,0x66,0xc9,0xbd,0x0a,0xa6,0x3b,0x19,
 | 
				
			||||||
 | 
							0xcb,0xf5,0xc2,0xc3,0x55,0x47,0x20,0xec,
 | 
				
			||||||
 | 
							0x1f,0x7b,0xa1,0x44,0x0e,0x8e,0xa4,0xb2,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001075, {
 | 
				
			||||||
 | 
							0x39,0x02,0x82,0xd0,0x7c,0x26,0x43,0xe9,
 | 
				
			||||||
 | 
							0x26,0xa3,0xd9,0x96,0xf7,0x30,0x13,0x0a,
 | 
				
			||||||
 | 
							0x8a,0x0e,0xac,0xe7,0x1d,0xdc,0xe2,0x0f,
 | 
				
			||||||
 | 
							0xcb,0x9e,0x8d,0xbc,0xd2,0xa2,0x44,0xe0,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001078, {
 | 
				
			||||||
 | 
							0x2d,0x67,0xc7,0x35,0xca,0xef,0x2f,0x25,
 | 
				
			||||||
 | 
							0x4c,0x45,0x93,0x3f,0x36,0x01,0x8c,0xce,
 | 
				
			||||||
 | 
							0xa8,0x5b,0x07,0xd3,0xc1,0x35,0x3c,0x04,
 | 
				
			||||||
 | 
							0x20,0xa2,0xfc,0xdc,0xe6,0xce,0x26,0x3e,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001079, {
 | 
				
			||||||
 | 
							0x43,0xe2,0x05,0x9c,0xfd,0xb7,0x5b,0xeb,
 | 
				
			||||||
 | 
							0x5b,0xe9,0xeb,0x3b,0x96,0xf4,0xe4,0x93,
 | 
				
			||||||
 | 
							0x73,0x45,0x3e,0xac,0x8d,0x3b,0xe4,0xdb,
 | 
				
			||||||
 | 
							0x10,0x31,0xc1,0xe4,0xa2,0xd0,0x5a,0x8a,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa00107a, {
 | 
				
			||||||
 | 
							0x5f,0x92,0xca,0xff,0xc3,0x59,0x22,0x5f,
 | 
				
			||||||
 | 
							0x02,0xa0,0x91,0x3b,0x4a,0x45,0x10,0xfd,
 | 
				
			||||||
 | 
							0x19,0xe1,0x8a,0x6d,0x9a,0x92,0xc1,0x3f,
 | 
				
			||||||
 | 
							0x75,0x78,0xac,0x78,0x03,0x1d,0xdb,0x18,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001143, {
 | 
				
			||||||
 | 
							0x56,0xca,0xf7,0x43,0x8a,0x4c,0x46,0x80,
 | 
				
			||||||
 | 
							0xec,0xde,0xe5,0x9c,0x50,0x84,0x9a,0x42,
 | 
				
			||||||
 | 
							0x27,0xe5,0x51,0x84,0x8f,0x19,0xc0,0x8d,
 | 
				
			||||||
 | 
							0x0c,0x25,0xb4,0xb0,0x8f,0x10,0xf3,0xf8,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001144, {
 | 
				
			||||||
 | 
							0x42,0xd5,0x9b,0xa7,0xd6,0x15,0x29,0x41,
 | 
				
			||||||
 | 
							0x61,0xc4,0x72,0x3f,0xf3,0x06,0x78,0x4b,
 | 
				
			||||||
 | 
							0x65,0xf3,0x0e,0xfa,0x9c,0x87,0xde,0x25,
 | 
				
			||||||
 | 
							0xbd,0xb3,0x9a,0xf4,0x75,0x13,0x53,0xdc,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa00115d, {
 | 
				
			||||||
 | 
							0xd4,0xc4,0x49,0x36,0x89,0x0b,0x47,0xdd,
 | 
				
			||||||
 | 
							0xfb,0x2f,0x88,0x3b,0x5f,0xf2,0x8e,0x75,
 | 
				
			||||||
 | 
							0xc6,0x6c,0x37,0x5a,0x90,0x25,0x94,0x3e,
 | 
				
			||||||
 | 
							0x36,0x9c,0xae,0x02,0x38,0x6c,0xf5,0x05,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001173, {
 | 
				
			||||||
 | 
							0x28,0xbb,0x9b,0xd1,0xa0,0xa0,0x7e,0x3a,
 | 
				
			||||||
 | 
							0x59,0x20,0xc0,0xa9,0xb2,0x5c,0xc3,0x35,
 | 
				
			||||||
 | 
							0x53,0x89,0xe1,0x4c,0x93,0x2f,0x1d,0xc3,
 | 
				
			||||||
 | 
							0xe5,0xf7,0xf3,0xc8,0x9b,0x61,0xaa,0x9e,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa0011a8, {
 | 
				
			||||||
 | 
							0x97,0xc6,0x16,0x65,0x99,0xa4,0x85,0x3b,
 | 
				
			||||||
 | 
							0xf6,0xce,0xaa,0x49,0x4a,0x3a,0xc5,0xb6,
 | 
				
			||||||
 | 
							0x78,0x25,0xbc,0x53,0xaf,0x5d,0xcf,0xf4,
 | 
				
			||||||
 | 
							0x23,0x12,0xbb,0xb1,0xbc,0x8a,0x02,0x2e,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa0011ce, {
 | 
				
			||||||
 | 
							0xcf,0x1c,0x90,0xa3,0x85,0x0a,0xbf,0x71,
 | 
				
			||||||
 | 
							0x94,0x0e,0x80,0x86,0x85,0x4f,0xd7,0x86,
 | 
				
			||||||
 | 
							0xae,0x38,0x23,0x28,0x2b,0x35,0x9b,0x4e,
 | 
				
			||||||
 | 
							0xfe,0xb8,0xcd,0x3d,0x3d,0x39,0xc9,0x6a,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa0011d1, {
 | 
				
			||||||
 | 
							0xdf,0x0e,0xca,0xde,0xf6,0xce,0x5c,0x1e,
 | 
				
			||||||
 | 
							0x4c,0xec,0xd7,0x71,0x83,0xcc,0xa8,0x09,
 | 
				
			||||||
 | 
							0xc7,0xc5,0xfe,0xb2,0xf7,0x05,0xd2,0xc5,
 | 
				
			||||||
 | 
							0x12,0xdd,0xe4,0xf3,0x92,0x1c,0x3d,0xb8,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa0011d3, {
 | 
				
			||||||
 | 
							0x91,0xe6,0x10,0xd7,0x57,0xb0,0x95,0x0b,
 | 
				
			||||||
 | 
							0x9a,0x24,0xee,0xf7,0xcf,0x56,0xc1,0xa6,
 | 
				
			||||||
 | 
							0x4a,0x52,0x7d,0x5f,0x9f,0xdf,0xf6,0x00,
 | 
				
			||||||
 | 
							0x65,0xf7,0xea,0xe8,0x2a,0x88,0xe2,0x26,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa0011d5, {
 | 
				
			||||||
 | 
							0xed,0x69,0x89,0xf4,0xeb,0x64,0xc2,0x13,
 | 
				
			||||||
 | 
							0xe0,0x51,0x1f,0x03,0x26,0x52,0x7d,0xb7,
 | 
				
			||||||
 | 
							0x93,0x5d,0x65,0xca,0xb8,0x12,0x1d,0x62,
 | 
				
			||||||
 | 
							0x0d,0x5b,0x65,0x34,0x69,0xb2,0x62,0x21,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001223, {
 | 
				
			||||||
 | 
							0xfb,0x32,0x5f,0xc6,0x83,0x4f,0x8c,0xb8,
 | 
				
			||||||
 | 
							0xa4,0x05,0xf9,0x71,0x53,0x01,0x16,0xc4,
 | 
				
			||||||
 | 
							0x83,0x75,0x94,0xdd,0xeb,0x7e,0xb7,0x15,
 | 
				
			||||||
 | 
							0x8e,0x3b,0x50,0x29,0x8a,0x9c,0xcc,0x45,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001224, {
 | 
				
			||||||
 | 
							0x0e,0x0c,0xdf,0xb4,0x89,0xee,0x35,0x25,
 | 
				
			||||||
 | 
							0xdd,0x9e,0xdb,0xc0,0x69,0x83,0x0a,0xad,
 | 
				
			||||||
 | 
							0x26,0xa9,0xaa,0x9d,0xfc,0x3c,0xea,0xf9,
 | 
				
			||||||
 | 
							0x6c,0xdc,0xd5,0x6d,0x8b,0x6e,0x85,0x4a,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001227, {
 | 
				
			||||||
 | 
							0xab,0xc6,0x00,0x69,0x4b,0x50,0x87,0xad,
 | 
				
			||||||
 | 
							0x5f,0x0e,0x8b,0xea,0x57,0x38,0xce,0x1d,
 | 
				
			||||||
 | 
							0x0f,0x75,0x26,0x02,0xf6,0xd6,0x96,0xe9,
 | 
				
			||||||
 | 
							0x87,0xb9,0xd6,0x20,0x27,0x7c,0xd2,0xe0,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001229, {
 | 
				
			||||||
 | 
							0x7f,0x49,0x49,0x48,0x46,0xa5,0x50,0xa6,
 | 
				
			||||||
 | 
							0x28,0x89,0x98,0xe2,0x9e,0xb4,0x7f,0x75,
 | 
				
			||||||
 | 
							0x33,0xa7,0x04,0x02,0xe4,0x82,0xbf,0xb4,
 | 
				
			||||||
 | 
							0xa5,0x3a,0xba,0x24,0x8d,0x31,0x10,0x1d,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa00122e, {
 | 
				
			||||||
 | 
							0x56,0x94,0xa9,0x5d,0x06,0x68,0xfe,0xaf,
 | 
				
			||||||
 | 
							0xdf,0x7a,0xff,0x2d,0xdf,0x74,0x0f,0x15,
 | 
				
			||||||
 | 
							0x66,0xfb,0x00,0xb5,0x51,0x97,0x9b,0xfa,
 | 
				
			||||||
 | 
							0xcb,0x79,0x85,0x46,0x25,0xb4,0xd2,0x10,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001231, {
 | 
				
			||||||
 | 
							0x0b,0x46,0xa5,0xfc,0x18,0x15,0xa0,0x9e,
 | 
				
			||||||
 | 
							0xa6,0xdc,0xb7,0xff,0x17,0xf7,0x30,0x64,
 | 
				
			||||||
 | 
							0xd4,0xda,0x9e,0x1b,0xc3,0xfc,0x02,0x3b,
 | 
				
			||||||
 | 
							0xe2,0xc6,0x0e,0x41,0x54,0xb5,0x18,0xdd,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001234, {
 | 
				
			||||||
 | 
							0x88,0x8d,0xed,0xab,0xb5,0xbd,0x4e,0xf7,
 | 
				
			||||||
 | 
							0x7f,0xd4,0x0e,0x95,0x34,0x91,0xff,0xcc,
 | 
				
			||||||
 | 
							0xfb,0x2a,0xcd,0xf7,0xd5,0xdb,0x4c,0x9b,
 | 
				
			||||||
 | 
							0xd6,0x2e,0x73,0x50,0x8f,0x83,0x79,0x1a,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001236, {
 | 
				
			||||||
 | 
							0x3d,0x30,0x00,0xb9,0x71,0xba,0x87,0x78,
 | 
				
			||||||
 | 
							0xa8,0x43,0x55,0xc4,0x26,0x59,0xcf,0x9d,
 | 
				
			||||||
 | 
							0x93,0xce,0x64,0x0e,0x8b,0x72,0x11,0x8b,
 | 
				
			||||||
 | 
							0xa3,0x8f,0x51,0xe9,0xca,0x98,0xaa,0x25,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa001238, {
 | 
				
			||||||
 | 
							0x72,0xf7,0x4b,0x0c,0x7d,0x58,0x65,0xcc,
 | 
				
			||||||
 | 
							0x00,0xcc,0x57,0x16,0x68,0x16,0xf8,0x2a,
 | 
				
			||||||
 | 
							0x1b,0xb3,0x8b,0xe1,0xb6,0x83,0x8c,0x7e,
 | 
				
			||||||
 | 
							0xc0,0xcd,0x33,0xf2,0x8d,0xf9,0xef,0x59,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa00820c, {
 | 
				
			||||||
 | 
							0xa8,0x0c,0x81,0xc0,0xa6,0x00,0xe7,0xf3,
 | 
				
			||||||
 | 
							0x5f,0x65,0xd3,0xb9,0x6f,0xea,0x93,0x63,
 | 
				
			||||||
 | 
							0xf1,0x8c,0x88,0x45,0xd7,0x82,0x80,0xd1,
 | 
				
			||||||
 | 
							0xe1,0x3b,0x8d,0xb2,0xf8,0x22,0x03,0xe2,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa10113e, {
 | 
				
			||||||
 | 
							0x05,0x3c,0x66,0xd7,0xa9,0x5a,0x33,0x10,
 | 
				
			||||||
 | 
							0x1b,0xf8,0x9c,0x8f,0xed,0xfc,0xa7,0xa0,
 | 
				
			||||||
 | 
							0x15,0xe3,0x3f,0x4b,0x1d,0x0d,0x0a,0xd5,
 | 
				
			||||||
 | 
							0xfa,0x90,0xc4,0xed,0x9d,0x90,0xaf,0x53,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa101144, {
 | 
				
			||||||
 | 
							0xb3,0x0b,0x26,0x9a,0xf8,0x7c,0x02,0x26,
 | 
				
			||||||
 | 
							0x35,0x84,0x53,0xa4,0xd3,0x2c,0x7c,0x09,
 | 
				
			||||||
 | 
							0x68,0x7b,0x96,0xb6,0x93,0xef,0xde,0xbc,
 | 
				
			||||||
 | 
							0xfd,0x4b,0x15,0xd2,0x81,0xd3,0x51,0x47,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa101148, {
 | 
				
			||||||
 | 
							0x20,0xd5,0x6f,0x40,0x4a,0xf6,0x48,0x90,
 | 
				
			||||||
 | 
							0xc2,0x93,0x9a,0xc2,0xfd,0xac,0xef,0x4f,
 | 
				
			||||||
 | 
							0xfa,0xc0,0x3d,0x92,0x3c,0x6d,0x01,0x08,
 | 
				
			||||||
 | 
							0xf1,0x5e,0xb0,0xde,0xb4,0x98,0xae,0xc4,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa10123e, {
 | 
				
			||||||
 | 
							0x03,0xb9,0x2c,0x76,0x48,0x93,0xc9,0x18,
 | 
				
			||||||
 | 
							0xfb,0x56,0xfd,0xf7,0xe2,0x1d,0xca,0x4d,
 | 
				
			||||||
 | 
							0x1d,0x13,0x53,0x63,0xfe,0x42,0x6f,0xfc,
 | 
				
			||||||
 | 
							0x19,0x0f,0xf1,0xfc,0xa7,0xdd,0x89,0x1b,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa101244, {
 | 
				
			||||||
 | 
							0x71,0x56,0xb5,0x9f,0x21,0xbf,0xb3,0x3c,
 | 
				
			||||||
 | 
							0x8c,0xd7,0x36,0xd0,0x34,0x52,0x1b,0xb1,
 | 
				
			||||||
 | 
							0x46,0x2f,0x04,0xf0,0x37,0xd8,0x1e,0x72,
 | 
				
			||||||
 | 
							0x24,0xa2,0x80,0x84,0x83,0x65,0x84,0xc0,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa101248, {
 | 
				
			||||||
 | 
							0xed,0x3b,0x95,0xa6,0x68,0xa7,0x77,0x3e,
 | 
				
			||||||
 | 
							0xfc,0x17,0x26,0xe2,0x7b,0xd5,0x56,0x22,
 | 
				
			||||||
 | 
							0x2c,0x1d,0xef,0xeb,0x56,0xdd,0xba,0x6e,
 | 
				
			||||||
 | 
							0x1b,0x7d,0x64,0x9d,0x4b,0x53,0x13,0x75,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa108108, {
 | 
				
			||||||
 | 
							0xed,0xc2,0xec,0xa1,0x15,0xc6,0x65,0xe9,
 | 
				
			||||||
 | 
							0xd0,0xef,0x39,0xaa,0x7f,0x55,0x06,0xc6,
 | 
				
			||||||
 | 
							0xf5,0xd4,0x3f,0x7b,0x14,0xd5,0x60,0x2c,
 | 
				
			||||||
 | 
							0x28,0x1e,0x9c,0x59,0x69,0x99,0x4d,0x16,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa20102d, {
 | 
				
			||||||
 | 
							0xf9,0x6e,0xf2,0x32,0xd3,0x0f,0x5f,0x11,
 | 
				
			||||||
 | 
							0x59,0xa1,0xfe,0xcc,0xcd,0x9b,0x42,0x89,
 | 
				
			||||||
 | 
							0x8b,0x89,0x2f,0xb5,0xbb,0x82,0xef,0x23,
 | 
				
			||||||
 | 
							0x8c,0xe9,0x19,0x3e,0xcc,0x3f,0x7b,0xb4,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa201210, {
 | 
				
			||||||
 | 
							0xe8,0x6d,0x51,0x6a,0x8e,0x72,0xf3,0xfe,
 | 
				
			||||||
 | 
							0x6e,0x16,0xbc,0x62,0x59,0x40,0x17,0xe9,
 | 
				
			||||||
 | 
							0x6d,0x3d,0x0e,0x6b,0xa7,0xac,0xe3,0x68,
 | 
				
			||||||
 | 
							0xf7,0x55,0xf0,0x13,0xbb,0x22,0xf6,0x41,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa404107, {
 | 
				
			||||||
 | 
							0xbb,0x04,0x4e,0x47,0xdd,0x5e,0x26,0x45,
 | 
				
			||||||
 | 
							0x1a,0xc9,0x56,0x24,0xa4,0x4c,0x82,0xb0,
 | 
				
			||||||
 | 
							0x8b,0x0d,0x9f,0xf9,0x3a,0xdf,0xc6,0x81,
 | 
				
			||||||
 | 
							0x13,0xbc,0xc5,0x25,0xe4,0xc5,0xc3,0x99,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa500011, {
 | 
				
			||||||
 | 
							0x23,0x3d,0x70,0x7d,0x03,0xc3,0xc4,0xf4,
 | 
				
			||||||
 | 
							0x2b,0x82,0xc6,0x05,0xda,0x80,0x0a,0xf1,
 | 
				
			||||||
 | 
							0xd7,0x5b,0x65,0x3a,0x7d,0xab,0xdf,0xa2,
 | 
				
			||||||
 | 
							0x11,0x5e,0x96,0x7e,0x71,0xe9,0xfc,0x74,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa601209, {
 | 
				
			||||||
 | 
							0x66,0x48,0xd4,0x09,0x05,0xcb,0x29,0x32,
 | 
				
			||||||
 | 
							0x66,0xb7,0x9a,0x76,0xcd,0x11,0xf3,0x30,
 | 
				
			||||||
 | 
							0x15,0x86,0xcc,0x5d,0x97,0x0f,0xc0,0x46,
 | 
				
			||||||
 | 
							0xe8,0x73,0xe2,0xd6,0xdb,0xd2,0x77,0x1d,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa704107, {
 | 
				
			||||||
 | 
							0xf3,0xc6,0x58,0x26,0xee,0xac,0x3f,0xd6,
 | 
				
			||||||
 | 
							0xce,0xa1,0x72,0x47,0x3b,0xba,0x2b,0x93,
 | 
				
			||||||
 | 
							0x2a,0xad,0x8e,0x6b,0xea,0x9b,0xb7,0xc2,
 | 
				
			||||||
 | 
							0x64,0x39,0x71,0x8c,0xce,0xe7,0x41,0x39,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa705206, {
 | 
				
			||||||
 | 
							0x8d,0xc0,0x76,0xbd,0x58,0x9f,0x8f,0xa4,
 | 
				
			||||||
 | 
							0x12,0x9d,0x21,0xfb,0x48,0x21,0xbc,0xe7,
 | 
				
			||||||
 | 
							0x67,0x6f,0x04,0x18,0xae,0x20,0x87,0x4b,
 | 
				
			||||||
 | 
							0x03,0x35,0xe9,0xbe,0xfb,0x06,0xdf,0xfc,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa708007, {
 | 
				
			||||||
 | 
							0x6b,0x76,0xcc,0x78,0xc5,0x8a,0xa3,0xe3,
 | 
				
			||||||
 | 
							0x32,0x2d,0x79,0xe4,0xc3,0x80,0xdb,0xb2,
 | 
				
			||||||
 | 
							0x07,0xaa,0x3a,0xe0,0x57,0x13,0x72,0x80,
 | 
				
			||||||
 | 
							0xdf,0x92,0x73,0x84,0x87,0x3c,0x73,0x93,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xa70c005, {
 | 
				
			||||||
 | 
							0x88,0x5d,0xfb,0x79,0x64,0xd8,0x46,0x3b,
 | 
				
			||||||
 | 
							0x4a,0x83,0x8e,0x77,0x7e,0xcf,0xb3,0x0f,
 | 
				
			||||||
 | 
							0x1f,0x1f,0xf1,0x97,0xeb,0xfe,0x56,0x55,
 | 
				
			||||||
 | 
							0xee,0x49,0xac,0xe1,0x8b,0x13,0xc5,0x13,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xaa00116, {
 | 
				
			||||||
 | 
							0xe8,0x4c,0x2c,0x88,0xa1,0xac,0x24,0x63,
 | 
				
			||||||
 | 
							0x65,0xe5,0xaa,0x2d,0x16,0xa9,0xc3,0xf5,
 | 
				
			||||||
 | 
							0xfe,0x1d,0x5e,0x65,0xc7,0xaa,0x92,0x4d,
 | 
				
			||||||
 | 
							0x91,0xee,0x76,0xbb,0x4c,0x66,0x78,0xc9,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xaa00212, {
 | 
				
			||||||
 | 
							0xbd,0x57,0x5d,0x0a,0x0a,0x30,0xc1,0x75,
 | 
				
			||||||
 | 
							0x95,0x58,0x5e,0x93,0x02,0x28,0x43,0x71,
 | 
				
			||||||
 | 
							0xed,0x42,0x29,0xc8,0xec,0x34,0x2b,0xb2,
 | 
				
			||||||
 | 
							0x1a,0x65,0x4b,0xfe,0x07,0x0f,0x34,0xa1,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xaa00213, {
 | 
				
			||||||
 | 
							0xed,0x58,0xb7,0x76,0x81,0x7f,0xd9,0x3a,
 | 
				
			||||||
 | 
							0x1a,0xff,0x8b,0x34,0xb8,0x4a,0x99,0x0f,
 | 
				
			||||||
 | 
							0x28,0x49,0x6c,0x56,0x2b,0xdc,0xb7,0xed,
 | 
				
			||||||
 | 
							0x96,0xd5,0x9d,0xc1,0x7a,0xd4,0x51,0x9b,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					 { 0xaa00215, {
 | 
				
			||||||
 | 
							0x55,0xd3,0x28,0xcb,0x87,0xa9,0x32,0xe9,
 | 
				
			||||||
 | 
							0x4e,0x85,0x4b,0x7c,0x6b,0xd5,0x7c,0xd4,
 | 
				
			||||||
 | 
							0x1b,0x51,0x71,0x3a,0x0e,0x0b,0xdc,0x9b,
 | 
				
			||||||
 | 
							0x68,0x2f,0x46,0xee,0xfe,0xc6,0x6d,0xef,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -100,14 +100,12 @@ extern bool force_minrev;
 | 
				
			||||||
#ifdef CONFIG_CPU_SUP_AMD
 | 
					#ifdef CONFIG_CPU_SUP_AMD
 | 
				
			||||||
void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family);
 | 
					void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family);
 | 
				
			||||||
void load_ucode_amd_ap(unsigned int family);
 | 
					void load_ucode_amd_ap(unsigned int family);
 | 
				
			||||||
int save_microcode_in_initrd_amd(unsigned int family);
 | 
					 | 
				
			||||||
void reload_ucode_amd(unsigned int cpu);
 | 
					void reload_ucode_amd(unsigned int cpu);
 | 
				
			||||||
struct microcode_ops *init_amd_microcode(void);
 | 
					struct microcode_ops *init_amd_microcode(void);
 | 
				
			||||||
void exit_amd_microcode(void);
 | 
					void exit_amd_microcode(void);
 | 
				
			||||||
#else /* CONFIG_CPU_SUP_AMD */
 | 
					#else /* CONFIG_CPU_SUP_AMD */
 | 
				
			||||||
static inline void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family) { }
 | 
					static inline void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family) { }
 | 
				
			||||||
static inline void load_ucode_amd_ap(unsigned int family) { }
 | 
					static inline void load_ucode_amd_ap(unsigned int family) { }
 | 
				
			||||||
static inline int save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
 | 
					 | 
				
			||||||
static inline void reload_ucode_amd(unsigned int cpu) { }
 | 
					static inline void reload_ucode_amd(unsigned int cpu) { }
 | 
				
			||||||
static inline struct microcode_ops *init_amd_microcode(void) { return NULL; }
 | 
					static inline struct microcode_ops *init_amd_microcode(void) { return NULL; }
 | 
				
			||||||
static inline void exit_amd_microcode(void) { }
 | 
					static inline void exit_amd_microcode(void) { }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -150,13 +150,15 @@ int __init sgx_drv_init(void)
 | 
				
			||||||
	u64 xfrm_mask;
 | 
						u64 xfrm_mask;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!cpu_feature_enabled(X86_FEATURE_SGX_LC))
 | 
						if (!cpu_feature_enabled(X86_FEATURE_SGX_LC)) {
 | 
				
			||||||
 | 
							pr_info("SGX disabled: SGX launch control CPU feature is not available, /dev/sgx_enclave disabled.\n");
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cpuid_count(SGX_CPUID, 0, &eax, &ebx, &ecx, &edx);
 | 
						cpuid_count(SGX_CPUID, 0, &eax, &ebx, &ecx, &edx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!(eax & 1))  {
 | 
						if (!(eax & 1))  {
 | 
				
			||||||
		pr_err("SGX disabled: SGX1 instruction support not available.\n");
 | 
							pr_info("SGX disabled: SGX1 instruction support not available, /dev/sgx_enclave disabled.\n");
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,8 +175,10 @@ int __init sgx_drv_init(void)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = misc_register(&sgx_dev_enclave);
 | 
						ret = misc_register(&sgx_dev_enclave);
 | 
				
			||||||
	if (ret)
 | 
						if (ret) {
 | 
				
			||||||
 | 
							pr_info("SGX disabled: Unable to register the /dev/sgx_enclave driver (%d).\n", ret);
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,6 +64,13 @@ static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs)
 | 
				
			||||||
	struct file *backing;
 | 
						struct file *backing;
 | 
				
			||||||
	long ret;
 | 
						long ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * ECREATE would detect this too, but checking here also ensures
 | 
				
			||||||
 | 
						 * that the 'encl_size' calculations below can never overflow.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (!is_power_of_2(secs->size))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	va_page = sgx_encl_grow(encl, true);
 | 
						va_page = sgx_encl_grow(encl, true);
 | 
				
			||||||
	if (IS_ERR(va_page))
 | 
						if (IS_ERR(va_page))
 | 
				
			||||||
		return PTR_ERR(va_page);
 | 
							return PTR_ERR(va_page);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@
 | 
				
			||||||
#include <linux/export.h>
 | 
					#include <linux/export.h>
 | 
				
			||||||
#include <linux/clocksource.h>
 | 
					#include <linux/clocksource.h>
 | 
				
			||||||
#include <linux/cpu.h>
 | 
					#include <linux/cpu.h>
 | 
				
			||||||
 | 
					#include <linux/efi.h>
 | 
				
			||||||
#include <linux/reboot.h>
 | 
					#include <linux/reboot.h>
 | 
				
			||||||
#include <linux/static_call.h>
 | 
					#include <linux/static_call.h>
 | 
				
			||||||
#include <asm/div64.h>
 | 
					#include <asm/div64.h>
 | 
				
			||||||
| 
						 | 
					@ -429,6 +430,9 @@ static void __init vmware_platform_setup(void)
 | 
				
			||||||
		pr_warn("Failed to get TSC freq from the hypervisor\n");
 | 
							pr_warn("Failed to get TSC freq from the hypervisor\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP) && !efi_enabled(EFI_BOOT))
 | 
				
			||||||
 | 
							x86_init.mpparse.find_mptable = mpparse_find_mptable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vmware_paravirt_ops_setup();
 | 
						vmware_paravirt_ops_setup();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_X86_IO_APIC
 | 
					#ifdef CONFIG_X86_IO_APIC
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1763,7 +1763,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		entry->ecx = entry->edx = 0;
 | 
							entry->ecx = entry->edx = 0;
 | 
				
			||||||
		if (!enable_pmu || !kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2)) {
 | 
							if (!enable_pmu || !kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2)) {
 | 
				
			||||||
			entry->eax = entry->ebx;
 | 
								entry->eax = entry->ebx = 0;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4590,6 +4590,8 @@ void sev_es_vcpu_reset(struct vcpu_svm *svm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void sev_es_prepare_switch_to_guest(struct vcpu_svm *svm, struct sev_es_save_area *hostsa)
 | 
					void sev_es_prepare_switch_to_guest(struct vcpu_svm *svm, struct sev_es_save_area *hostsa)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct kvm *kvm = svm->vcpu.kvm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * All host state for SEV-ES guests is categorized into three swap types
 | 
						 * All host state for SEV-ES guests is categorized into three swap types
 | 
				
			||||||
	 * based on how it is handled by hardware during a world switch:
 | 
						 * based on how it is handled by hardware during a world switch:
 | 
				
			||||||
| 
						 | 
					@ -4613,14 +4615,22 @@ void sev_es_prepare_switch_to_guest(struct vcpu_svm *svm, struct sev_es_save_are
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If DebugSwap is enabled, debug registers are loaded but NOT saved by
 | 
						 * If DebugSwap is enabled, debug registers are loaded but NOT saved by
 | 
				
			||||||
	 * the CPU (Type-B). If DebugSwap is disabled/unsupported, the CPU both
 | 
						 * the CPU (Type-B). If DebugSwap is disabled/unsupported, the CPU does
 | 
				
			||||||
	 * saves and loads debug registers (Type-A).
 | 
						 * not save or load debug registers.  Sadly, KVM can't prevent SNP
 | 
				
			||||||
 | 
						 * guests from lying about DebugSwap on secondary vCPUs, i.e. the
 | 
				
			||||||
 | 
						 * SEV_FEATURES provided at "AP Create" isn't guaranteed to match what
 | 
				
			||||||
 | 
						 * the guest has actually enabled (or not!) in the VMSA.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * If DebugSwap is *possible*, save the masks so that they're restored
 | 
				
			||||||
 | 
						 * if the guest enables DebugSwap.  But for the DRs themselves, do NOT
 | 
				
			||||||
 | 
						 * rely on the CPU to restore the host values; KVM will restore them as
 | 
				
			||||||
 | 
						 * needed in common code, via hw_breakpoint_restore().  Note, KVM does
 | 
				
			||||||
 | 
						 * NOT support virtualizing Breakpoint Extensions, i.e. the mask MSRs
 | 
				
			||||||
 | 
						 * don't need to be restored per se, KVM just needs to ensure they are
 | 
				
			||||||
 | 
						 * loaded with the correct values *if* the CPU writes the MSRs.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (sev_vcpu_has_debug_swap(svm)) {
 | 
						if (sev_vcpu_has_debug_swap(svm) ||
 | 
				
			||||||
		hostsa->dr0 = native_get_debugreg(0);
 | 
						    (sev_snp_guest(kvm) && cpu_feature_enabled(X86_FEATURE_DEBUG_SWAP))) {
 | 
				
			||||||
		hostsa->dr1 = native_get_debugreg(1);
 | 
					 | 
				
			||||||
		hostsa->dr2 = native_get_debugreg(2);
 | 
					 | 
				
			||||||
		hostsa->dr3 = native_get_debugreg(3);
 | 
					 | 
				
			||||||
		hostsa->dr0_addr_mask = amd_get_dr_addr_mask(0);
 | 
							hostsa->dr0_addr_mask = amd_get_dr_addr_mask(0);
 | 
				
			||||||
		hostsa->dr1_addr_mask = amd_get_dr_addr_mask(1);
 | 
							hostsa->dr1_addr_mask = amd_get_dr_addr_mask(1);
 | 
				
			||||||
		hostsa->dr2_addr_mask = amd_get_dr_addr_mask(2);
 | 
							hostsa->dr2_addr_mask = amd_get_dr_addr_mask(2);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3165,6 +3165,27 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
 | 
				
			||||||
			kvm_pr_unimpl_wrmsr(vcpu, ecx, data);
 | 
								kvm_pr_unimpl_wrmsr(vcpu, ecx, data);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * AMD changed the architectural behavior of bits 5:2.  On CPUs
 | 
				
			||||||
 | 
							 * without BusLockTrap, bits 5:2 control "external pins", but
 | 
				
			||||||
 | 
							 * on CPUs that support BusLockDetect, bit 2 enables BusLockTrap
 | 
				
			||||||
 | 
							 * and bits 5:3 are reserved-to-zero.  Sadly, old KVM allowed
 | 
				
			||||||
 | 
							 * the guest to set bits 5:2 despite not actually virtualizing
 | 
				
			||||||
 | 
							 * Performance-Monitoring/Breakpoint external pins.  Drop bits
 | 
				
			||||||
 | 
							 * 5:2 for backwards compatibility.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							data &= ~GENMASK(5, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Suppress BTF as KVM doesn't virtualize BTF, but there's no
 | 
				
			||||||
 | 
							 * way to communicate lack of support to the guest.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (data & DEBUGCTLMSR_BTF) {
 | 
				
			||||||
 | 
								kvm_pr_unimpl_wrmsr(vcpu, MSR_IA32_DEBUGCTLMSR, data);
 | 
				
			||||||
 | 
								data &= ~DEBUGCTLMSR_BTF;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (data & DEBUGCTL_RESERVED_BITS)
 | 
							if (data & DEBUGCTL_RESERVED_BITS)
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4189,6 +4210,18 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_in
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	guest_state_enter_irqoff();
 | 
						guest_state_enter_irqoff();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Set RFLAGS.IF prior to VMRUN, as the host's RFLAGS.IF at the time of
 | 
				
			||||||
 | 
						 * VMRUN controls whether or not physical IRQs are masked (KVM always
 | 
				
			||||||
 | 
						 * runs with V_INTR_MASKING_MASK).  Toggle RFLAGS.IF here to avoid the
 | 
				
			||||||
 | 
						 * temptation to do STI+VMRUN+CLI, as AMD CPUs bleed the STI shadow
 | 
				
			||||||
 | 
						 * into guest state if delivery of an event during VMRUN triggers a
 | 
				
			||||||
 | 
						 * #VMEXIT, and the guest_state transitions already tell lockdep that
 | 
				
			||||||
 | 
						 * IRQs are being enabled/disabled.  Note!  GIF=0 for the entirety of
 | 
				
			||||||
 | 
						 * this path, so IRQs aren't actually unmasked while running host code.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						raw_local_irq_enable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	amd_clear_divider();
 | 
						amd_clear_divider();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sev_es_guest(vcpu->kvm))
 | 
						if (sev_es_guest(vcpu->kvm))
 | 
				
			||||||
| 
						 | 
					@ -4197,6 +4230,8 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_in
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		__svm_vcpu_run(svm, spec_ctrl_intercepted);
 | 
							__svm_vcpu_run(svm, spec_ctrl_intercepted);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						raw_local_irq_disable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	guest_state_exit_irqoff();
 | 
						guest_state_exit_irqoff();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4253,6 +4288,16 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu,
 | 
				
			||||||
	clgi();
 | 
						clgi();
 | 
				
			||||||
	kvm_load_guest_xsave_state(vcpu);
 | 
						kvm_load_guest_xsave_state(vcpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Hardware only context switches DEBUGCTL if LBR virtualization is
 | 
				
			||||||
 | 
						 * enabled.  Manually load DEBUGCTL if necessary (and restore it after
 | 
				
			||||||
 | 
						 * VM-Exit), as running with the host's DEBUGCTL can negatively affect
 | 
				
			||||||
 | 
						 * guest state and can even be fatal, e.g. due to Bus Lock Detect.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (!(svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK) &&
 | 
				
			||||||
 | 
						    vcpu->arch.host_debugctl != svm->vmcb->save.dbgctl)
 | 
				
			||||||
 | 
							update_debugctlmsr(svm->vmcb->save.dbgctl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kvm_wait_lapic_expire(vcpu);
 | 
						kvm_wait_lapic_expire(vcpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -4280,6 +4325,10 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu,
 | 
				
			||||||
	if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
 | 
						if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
 | 
				
			||||||
		kvm_before_interrupt(vcpu, KVM_HANDLING_NMI);
 | 
							kvm_before_interrupt(vcpu, KVM_HANDLING_NMI);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK) &&
 | 
				
			||||||
 | 
						    vcpu->arch.host_debugctl != svm->vmcb->save.dbgctl)
 | 
				
			||||||
 | 
							update_debugctlmsr(vcpu->arch.host_debugctl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kvm_load_host_xsave_state(vcpu);
 | 
						kvm_load_host_xsave_state(vcpu);
 | 
				
			||||||
	stgi();
 | 
						stgi();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -584,7 +584,7 @@ static inline bool is_vnmi_enabled(struct vcpu_svm *svm)
 | 
				
			||||||
/* svm.c */
 | 
					/* svm.c */
 | 
				
			||||||
#define MSR_INVALID				0xffffffffU
 | 
					#define MSR_INVALID				0xffffffffU
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEBUGCTL_RESERVED_BITS (~(0x3fULL))
 | 
					#define DEBUGCTL_RESERVED_BITS (~DEBUGCTLMSR_LBR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern bool dump_invalid_vmcb;
 | 
					extern bool dump_invalid_vmcb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -170,12 +170,8 @@ SYM_FUNC_START(__svm_vcpu_run)
 | 
				
			||||||
	mov VCPU_RDI(%_ASM_DI), %_ASM_DI
 | 
						mov VCPU_RDI(%_ASM_DI), %_ASM_DI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Enter guest mode */
 | 
						/* Enter guest mode */
 | 
				
			||||||
	sti
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
3:	vmrun %_ASM_AX
 | 
					3:	vmrun %_ASM_AX
 | 
				
			||||||
4:
 | 
					4:
 | 
				
			||||||
	cli
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Pop @svm to RAX while it's the only available register. */
 | 
						/* Pop @svm to RAX while it's the only available register. */
 | 
				
			||||||
	pop %_ASM_AX
 | 
						pop %_ASM_AX
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -340,12 +336,8 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
 | 
				
			||||||
	mov KVM_VMCB_pa(%rax), %rax
 | 
						mov KVM_VMCB_pa(%rax), %rax
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Enter guest mode */
 | 
						/* Enter guest mode */
 | 
				
			||||||
	sti
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
1:	vmrun %rax
 | 
					1:	vmrun %rax
 | 
				
			||||||
 | 
					2:
 | 
				
			||||||
2:	cli
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
 | 
						/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
 | 
				
			||||||
	FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT
 | 
						FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1514,16 +1514,12 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu,
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 | 
					void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct vcpu_vmx *vmx = to_vmx(vcpu);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (vcpu->scheduled_out && !kvm_pause_in_guest(vcpu->kvm))
 | 
						if (vcpu->scheduled_out && !kvm_pause_in_guest(vcpu->kvm))
 | 
				
			||||||
		shrink_ple_window(vcpu);
 | 
							shrink_ple_window(vcpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vmx_vcpu_load_vmcs(vcpu, cpu, NULL);
 | 
						vmx_vcpu_load_vmcs(vcpu, cpu, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vmx_vcpu_pi_load(vcpu, cpu);
 | 
						vmx_vcpu_pi_load(vcpu, cpu);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	vmx->host_debugctlmsr = get_debugctlmsr();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void vmx_vcpu_put(struct kvm_vcpu *vcpu)
 | 
					void vmx_vcpu_put(struct kvm_vcpu *vcpu)
 | 
				
			||||||
| 
						 | 
					@ -7458,8 +7454,8 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* MSR_IA32_DEBUGCTLMSR is zeroed on vmexit. Restore it if needed */
 | 
						/* MSR_IA32_DEBUGCTLMSR is zeroed on vmexit. Restore it if needed */
 | 
				
			||||||
	if (vmx->host_debugctlmsr)
 | 
						if (vcpu->arch.host_debugctl)
 | 
				
			||||||
		update_debugctlmsr(vmx->host_debugctlmsr);
 | 
							update_debugctlmsr(vcpu->arch.host_debugctl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef CONFIG_X86_64
 | 
					#ifndef CONFIG_X86_64
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -340,8 +340,6 @@ struct vcpu_vmx {
 | 
				
			||||||
	/* apic deadline value in host tsc */
 | 
						/* apic deadline value in host tsc */
 | 
				
			||||||
	u64 hv_deadline_tsc;
 | 
						u64 hv_deadline_tsc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unsigned long host_debugctlmsr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Only bits masked by msr_ia32_feature_control_valid_bits can be set in
 | 
						 * Only bits masked by msr_ia32_feature_control_valid_bits can be set in
 | 
				
			||||||
	 * msr_ia32_feature_control. FEAT_CTL_LOCKED is always included
 | 
						 * msr_ia32_feature_control. FEAT_CTL_LOCKED is always included
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10968,6 +10968,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 | 
				
			||||||
		set_debugreg(0, 7);
 | 
							set_debugreg(0, 7);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vcpu->arch.host_debugctl = get_debugctlmsr();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	guest_timing_enter_irqoff();
 | 
						guest_timing_enter_irqoff();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (;;) {
 | 
						for (;;) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -682,7 +682,7 @@ static void utf16_le_to_7bit(const __le16 *in, unsigned int size, u8 *out)
 | 
				
			||||||
	out[size] = 0;
 | 
						out[size] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (i < size) {
 | 
						while (i < size) {
 | 
				
			||||||
		u8 c = le16_to_cpu(in[i]) & 0xff;
 | 
							u8 c = le16_to_cpu(in[i]) & 0x7f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (c && !isprint(c))
 | 
							if (c && !isprint(c))
 | 
				
			||||||
			c = '!';
 | 
								c = '!';
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,9 +21,15 @@ struct platform_profile_handler {
 | 
				
			||||||
	struct device dev;
 | 
						struct device dev;
 | 
				
			||||||
	int minor;
 | 
						int minor;
 | 
				
			||||||
	unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
 | 
						unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
 | 
				
			||||||
 | 
						unsigned long hidden_choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
 | 
				
			||||||
	const struct platform_profile_ops *ops;
 | 
						const struct platform_profile_ops *ops;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct aggregate_choices_data {
 | 
				
			||||||
 | 
						unsigned long aggregate[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
 | 
				
			||||||
 | 
						int count;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char * const profile_names[] = {
 | 
					static const char * const profile_names[] = {
 | 
				
			||||||
	[PLATFORM_PROFILE_LOW_POWER] = "low-power",
 | 
						[PLATFORM_PROFILE_LOW_POWER] = "low-power",
 | 
				
			||||||
	[PLATFORM_PROFILE_COOL] = "cool",
 | 
						[PLATFORM_PROFILE_COOL] = "cool",
 | 
				
			||||||
| 
						 | 
					@ -73,7 +79,7 @@ static int _store_class_profile(struct device *dev, void *data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lockdep_assert_held(&profile_lock);
 | 
						lockdep_assert_held(&profile_lock);
 | 
				
			||||||
	handler = to_pprof_handler(dev);
 | 
						handler = to_pprof_handler(dev);
 | 
				
			||||||
	if (!test_bit(*bit, handler->choices))
 | 
						if (!test_bit(*bit, handler->choices) && !test_bit(*bit, handler->hidden_choices))
 | 
				
			||||||
		return -EOPNOTSUPP;
 | 
							return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return handler->ops->profile_set(dev, *bit);
 | 
						return handler->ops->profile_set(dev, *bit);
 | 
				
			||||||
| 
						 | 
					@ -239,21 +245,44 @@ static const struct class platform_profile_class = {
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * _aggregate_choices - Aggregate the available profile choices
 | 
					 * _aggregate_choices - Aggregate the available profile choices
 | 
				
			||||||
 * @dev: The device
 | 
					 * @dev: The device
 | 
				
			||||||
 * @data: The available profile choices
 | 
					 * @arg: struct aggregate_choices_data
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Return: 0 on success, -errno on failure
 | 
					 * Return: 0 on success, -errno on failure
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int _aggregate_choices(struct device *dev, void *data)
 | 
					static int _aggregate_choices(struct device *dev, void *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						unsigned long tmp[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
 | 
				
			||||||
 | 
						struct aggregate_choices_data *data = arg;
 | 
				
			||||||
	struct platform_profile_handler *handler;
 | 
						struct platform_profile_handler *handler;
 | 
				
			||||||
	unsigned long *aggregate = data;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lockdep_assert_held(&profile_lock);
 | 
						lockdep_assert_held(&profile_lock);
 | 
				
			||||||
	handler = to_pprof_handler(dev);
 | 
						handler = to_pprof_handler(dev);
 | 
				
			||||||
	if (test_bit(PLATFORM_PROFILE_LAST, aggregate))
 | 
						bitmap_or(tmp, handler->choices, handler->hidden_choices, PLATFORM_PROFILE_LAST);
 | 
				
			||||||
		bitmap_copy(aggregate, handler->choices, PLATFORM_PROFILE_LAST);
 | 
						if (test_bit(PLATFORM_PROFILE_LAST, data->aggregate))
 | 
				
			||||||
 | 
							bitmap_copy(data->aggregate, tmp, PLATFORM_PROFILE_LAST);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		bitmap_and(aggregate, handler->choices, aggregate, PLATFORM_PROFILE_LAST);
 | 
							bitmap_and(data->aggregate, tmp, data->aggregate, PLATFORM_PROFILE_LAST);
 | 
				
			||||||
 | 
						data->count++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * _remove_hidden_choices - Remove hidden choices from aggregate data
 | 
				
			||||||
 | 
					 * @dev: The device
 | 
				
			||||||
 | 
					 * @arg: struct aggregate_choices_data
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, -errno on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int _remove_hidden_choices(struct device *dev, void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct aggregate_choices_data *data = arg;
 | 
				
			||||||
 | 
						struct platform_profile_handler *handler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lockdep_assert_held(&profile_lock);
 | 
				
			||||||
 | 
						handler = to_pprof_handler(dev);
 | 
				
			||||||
 | 
						bitmap_andnot(data->aggregate, handler->choices,
 | 
				
			||||||
 | 
							      handler->hidden_choices, PLATFORM_PROFILE_LAST);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -270,22 +299,31 @@ static ssize_t platform_profile_choices_show(struct device *dev,
 | 
				
			||||||
					     struct device_attribute *attr,
 | 
										     struct device_attribute *attr,
 | 
				
			||||||
					     char *buf)
 | 
										     char *buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long aggregate[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
 | 
						struct aggregate_choices_data data = {
 | 
				
			||||||
 | 
							.aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL },
 | 
				
			||||||
 | 
							.count = 0,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	set_bit(PLATFORM_PROFILE_LAST, aggregate);
 | 
						set_bit(PLATFORM_PROFILE_LAST, data.aggregate);
 | 
				
			||||||
	scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
 | 
						scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
 | 
				
			||||||
		err = class_for_each_device(&platform_profile_class, NULL,
 | 
							err = class_for_each_device(&platform_profile_class, NULL,
 | 
				
			||||||
					    aggregate, _aggregate_choices);
 | 
										    &data, _aggregate_choices);
 | 
				
			||||||
 | 
							if (err)
 | 
				
			||||||
 | 
								return err;
 | 
				
			||||||
 | 
							if (data.count == 1) {
 | 
				
			||||||
 | 
								err = class_for_each_device(&platform_profile_class, NULL,
 | 
				
			||||||
 | 
											    &data, _remove_hidden_choices);
 | 
				
			||||||
			if (err)
 | 
								if (err)
 | 
				
			||||||
				return err;
 | 
									return err;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* no profile handler registered any more */
 | 
						/* no profile handler registered any more */
 | 
				
			||||||
	if (bitmap_empty(aggregate, PLATFORM_PROFILE_LAST))
 | 
						if (bitmap_empty(data.aggregate, PLATFORM_PROFILE_LAST))
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return _commmon_choices_show(aggregate, buf);
 | 
						return _commmon_choices_show(data.aggregate, buf);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -373,7 +411,10 @@ static ssize_t platform_profile_store(struct device *dev,
 | 
				
			||||||
				      struct device_attribute *attr,
 | 
									      struct device_attribute *attr,
 | 
				
			||||||
				      const char *buf, size_t count)
 | 
									      const char *buf, size_t count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
 | 
						struct aggregate_choices_data data = {
 | 
				
			||||||
 | 
							.aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL },
 | 
				
			||||||
 | 
							.count = 0,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -381,13 +422,13 @@ static ssize_t platform_profile_store(struct device *dev,
 | 
				
			||||||
	i = sysfs_match_string(profile_names, buf);
 | 
						i = sysfs_match_string(profile_names, buf);
 | 
				
			||||||
	if (i < 0 || i == PLATFORM_PROFILE_CUSTOM)
 | 
						if (i < 0 || i == PLATFORM_PROFILE_CUSTOM)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	set_bit(PLATFORM_PROFILE_LAST, choices);
 | 
						set_bit(PLATFORM_PROFILE_LAST, data.aggregate);
 | 
				
			||||||
	scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
 | 
						scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
 | 
				
			||||||
		ret = class_for_each_device(&platform_profile_class, NULL,
 | 
							ret = class_for_each_device(&platform_profile_class, NULL,
 | 
				
			||||||
					    choices, _aggregate_choices);
 | 
										    &data, _aggregate_choices);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
		if (!test_bit(i, choices))
 | 
							if (!test_bit(i, data.aggregate))
 | 
				
			||||||
			return -EOPNOTSUPP;
 | 
								return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = class_for_each_device(&platform_profile_class, NULL, &i,
 | 
							ret = class_for_each_device(&platform_profile_class, NULL, &i,
 | 
				
			||||||
| 
						 | 
					@ -453,12 +494,15 @@ EXPORT_SYMBOL_GPL(platform_profile_notify);
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int platform_profile_cycle(void)
 | 
					int platform_profile_cycle(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct aggregate_choices_data data = {
 | 
				
			||||||
 | 
							.aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL },
 | 
				
			||||||
 | 
							.count = 0,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	enum platform_profile_option next = PLATFORM_PROFILE_LAST;
 | 
						enum platform_profile_option next = PLATFORM_PROFILE_LAST;
 | 
				
			||||||
	enum platform_profile_option profile = PLATFORM_PROFILE_LAST;
 | 
						enum platform_profile_option profile = PLATFORM_PROFILE_LAST;
 | 
				
			||||||
	unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
 | 
					 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	set_bit(PLATFORM_PROFILE_LAST, choices);
 | 
						set_bit(PLATFORM_PROFILE_LAST, data.aggregate);
 | 
				
			||||||
	scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
 | 
						scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
 | 
				
			||||||
		err = class_for_each_device(&platform_profile_class, NULL,
 | 
							err = class_for_each_device(&platform_profile_class, NULL,
 | 
				
			||||||
					    &profile, _aggregate_profiles);
 | 
										    &profile, _aggregate_profiles);
 | 
				
			||||||
| 
						 | 
					@ -470,14 +514,14 @@ int platform_profile_cycle(void)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err = class_for_each_device(&platform_profile_class, NULL,
 | 
							err = class_for_each_device(&platform_profile_class, NULL,
 | 
				
			||||||
					    choices, _aggregate_choices);
 | 
										    &data, _aggregate_choices);
 | 
				
			||||||
		if (err)
 | 
							if (err)
 | 
				
			||||||
			return err;
 | 
								return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* never iterate into a custom if all drivers supported it */
 | 
							/* never iterate into a custom if all drivers supported it */
 | 
				
			||||||
		clear_bit(PLATFORM_PROFILE_CUSTOM, choices);
 | 
							clear_bit(PLATFORM_PROFILE_CUSTOM, data.aggregate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		next = find_next_bit_wrap(choices,
 | 
							next = find_next_bit_wrap(data.aggregate,
 | 
				
			||||||
					  PLATFORM_PROFILE_LAST,
 | 
										  PLATFORM_PROFILE_LAST,
 | 
				
			||||||
					  profile + 1);
 | 
										  profile + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -532,6 +576,14 @@ struct device *platform_profile_register(struct device *dev, const char *name,
 | 
				
			||||||
		return ERR_PTR(-EINVAL);
 | 
							return ERR_PTR(-EINVAL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->hidden_choices) {
 | 
				
			||||||
 | 
							err = ops->hidden_choices(drvdata, pprof->hidden_choices);
 | 
				
			||||||
 | 
							if (err) {
 | 
				
			||||||
 | 
								dev_err(dev, "platform_profile hidden_choices failed\n");
 | 
				
			||||||
 | 
								return ERR_PTR(err);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	guard(mutex)(&profile_lock);
 | 
						guard(mutex)(&profile_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* create class interface for individual handler */
 | 
						/* create class interface for individual handler */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -274,6 +274,7 @@ static void binderfs_evict_inode(struct inode *inode)
 | 
				
			||||||
	mutex_unlock(&binderfs_minors_mutex);
 | 
						mutex_unlock(&binderfs_minors_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (refcount_dec_and_test(&device->ref)) {
 | 
						if (refcount_dec_and_test(&device->ref)) {
 | 
				
			||||||
 | 
							hlist_del_init(&device->hlist);
 | 
				
			||||||
		kfree(device->context.name);
 | 
							kfree(device->context.name);
 | 
				
			||||||
		kfree(device);
 | 
							kfree(device);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2079,6 +2079,7 @@ static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle,
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	sup_handle->flags &= ~FWNODE_FLAG_VISITED;
 | 
						sup_handle->flags &= ~FWNODE_FLAG_VISITED;
 | 
				
			||||||
	put_device(sup_dev);
 | 
						put_device(sup_dev);
 | 
				
			||||||
 | 
						put_device(con_dev);
 | 
				
			||||||
	put_device(par_dev);
 | 
						put_device(par_dev);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1549,7 +1549,7 @@ static int null_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
 | 
				
			||||||
		cmd = blk_mq_rq_to_pdu(req);
 | 
							cmd = blk_mq_rq_to_pdu(req);
 | 
				
			||||||
		cmd->error = null_process_cmd(cmd, req_op(req), blk_rq_pos(req),
 | 
							cmd->error = null_process_cmd(cmd, req_op(req), blk_rq_pos(req),
 | 
				
			||||||
						blk_rq_sectors(req));
 | 
											blk_rq_sectors(req));
 | 
				
			||||||
		if (!blk_mq_add_to_batch(req, iob, (__force int) cmd->error,
 | 
							if (!blk_mq_add_to_batch(req, iob, cmd->error != BLK_STS_OK,
 | 
				
			||||||
					 blk_mq_end_request_batch))
 | 
										 blk_mq_end_request_batch))
 | 
				
			||||||
			blk_mq_end_request(req, cmd->error);
 | 
								blk_mq_end_request(req, cmd->error);
 | 
				
			||||||
		nr++;
 | 
							nr++;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2715,9 +2715,12 @@ static int ublk_ctrl_set_params(struct ublk_device *ub,
 | 
				
			||||||
	if (ph.len > sizeof(struct ublk_params))
 | 
						if (ph.len > sizeof(struct ublk_params))
 | 
				
			||||||
		ph.len = sizeof(struct ublk_params);
 | 
							ph.len = sizeof(struct ublk_params);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* parameters can only be changed when device isn't live */
 | 
					 | 
				
			||||||
	mutex_lock(&ub->mutex);
 | 
						mutex_lock(&ub->mutex);
 | 
				
			||||||
	if (ub->dev_info.state == UBLK_S_DEV_LIVE) {
 | 
						if (test_bit(UB_STATE_USED, &ub->state)) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Parameters can only be changed when device hasn't
 | 
				
			||||||
 | 
							 * been started yet
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
		ret = -EACCES;
 | 
							ret = -EACCES;
 | 
				
			||||||
	} else if (copy_from_user(&ub->params, argp, ph.len)) {
 | 
						} else if (copy_from_user(&ub->params, argp, ph.len)) {
 | 
				
			||||||
		ret = -EFAULT;
 | 
							ret = -EFAULT;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1207,10 +1207,11 @@ static int virtblk_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((vbr = virtqueue_get_buf(vq->vq, &len)) != NULL) {
 | 
						while ((vbr = virtqueue_get_buf(vq->vq, &len)) != NULL) {
 | 
				
			||||||
		struct request *req = blk_mq_rq_from_pdu(vbr);
 | 
							struct request *req = blk_mq_rq_from_pdu(vbr);
 | 
				
			||||||
 | 
							u8 status = virtblk_vbr_status(vbr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		found++;
 | 
							found++;
 | 
				
			||||||
		if (!blk_mq_complete_request_remote(req) &&
 | 
							if (!blk_mq_complete_request_remote(req) &&
 | 
				
			||||||
		    !blk_mq_add_to_batch(req, iob, virtblk_vbr_status(vbr),
 | 
							    !blk_mq_add_to_batch(req, iob, status != VIRTIO_BLK_S_OK,
 | 
				
			||||||
					 virtblk_complete_batch))
 | 
										 virtblk_complete_batch))
 | 
				
			||||||
			virtblk_request_done(req);
 | 
								virtblk_request_done(req);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,6 +56,18 @@ config BT_HCIBTUSB_POLL_SYNC
 | 
				
			||||||
	  Say Y here to enable USB poll_sync for Bluetooth USB devices by
 | 
						  Say Y here to enable USB poll_sync for Bluetooth USB devices by
 | 
				
			||||||
	  default.
 | 
						  default.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config BT_HCIBTUSB_AUTO_ISOC_ALT
 | 
				
			||||||
 | 
						bool "Automatically adjust alternate setting for Isoc endpoints"
 | 
				
			||||||
 | 
						depends on BT_HCIBTUSB
 | 
				
			||||||
 | 
						default y if CHROME_PLATFORMS
 | 
				
			||||||
 | 
						help
 | 
				
			||||||
 | 
						  Say Y here to automatically adjusting the alternate setting for
 | 
				
			||||||
 | 
						  HCI_USER_CHANNEL whenever a SCO link is established.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  When enabled, btusb intercepts the HCI_EV_SYNC_CONN_COMPLETE packets
 | 
				
			||||||
 | 
						  and configures isoc endpoint alternate setting automatically when
 | 
				
			||||||
 | 
						  HCI_USER_CHANNEL is in use.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config BT_HCIBTUSB_BCM
 | 
					config BT_HCIBTUSB_BCM
 | 
				
			||||||
	bool "Broadcom protocol support"
 | 
						bool "Broadcom protocol support"
 | 
				
			||||||
	depends on BT_HCIBTUSB
 | 
						depends on BT_HCIBTUSB
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,7 @@ static bool force_scofix;
 | 
				
			||||||
static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND);
 | 
					static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND);
 | 
				
			||||||
static bool enable_poll_sync = IS_ENABLED(CONFIG_BT_HCIBTUSB_POLL_SYNC);
 | 
					static bool enable_poll_sync = IS_ENABLED(CONFIG_BT_HCIBTUSB_POLL_SYNC);
 | 
				
			||||||
static bool reset = true;
 | 
					static bool reset = true;
 | 
				
			||||||
 | 
					static bool auto_isoc_alt = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTO_ISOC_ALT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct usb_driver btusb_driver;
 | 
					static struct usb_driver btusb_driver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1085,6 +1086,42 @@ static inline void btusb_free_frags(struct btusb_data *data)
 | 
				
			||||||
	spin_unlock_irqrestore(&data->rxlock, flags);
 | 
						spin_unlock_irqrestore(&data->rxlock, flags);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void btusb_sco_connected(struct btusb_data *data, struct sk_buff *skb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hci_event_hdr *hdr = (void *) skb->data;
 | 
				
			||||||
 | 
						struct hci_ev_sync_conn_complete *ev =
 | 
				
			||||||
 | 
							(void *) skb->data + sizeof(*hdr);
 | 
				
			||||||
 | 
						struct hci_dev *hdev = data->hdev;
 | 
				
			||||||
 | 
						unsigned int notify_air_mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (skb->len < sizeof(*hdr) || hdr->evt != HCI_EV_SYNC_CONN_COMPLETE)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (skb->len != sizeof(*hdr) + sizeof(*ev) || ev->status)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (ev->air_mode) {
 | 
				
			||||||
 | 
						case BT_CODEC_CVSD:
 | 
				
			||||||
 | 
							notify_air_mode = HCI_NOTIFY_ENABLE_SCO_CVSD;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case BT_CODEC_TRANSPARENT:
 | 
				
			||||||
 | 
							notify_air_mode = HCI_NOTIFY_ENABLE_SCO_TRANSP;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bt_dev_info(hdev, "enabling SCO with air mode %u", ev->air_mode);
 | 
				
			||||||
 | 
						data->sco_num = 1;
 | 
				
			||||||
 | 
						data->air_mode = notify_air_mode;
 | 
				
			||||||
 | 
						schedule_work(&data->work);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
 | 
					static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (data->intr_interval) {
 | 
						if (data->intr_interval) {
 | 
				
			||||||
| 
						 | 
					@ -1092,6 +1129,10 @@ static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
 | 
				
			||||||
		schedule_delayed_work(&data->rx_work, 0);
 | 
							schedule_delayed_work(&data->rx_work, 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Configure altsetting for HCI_USER_CHANNEL on SCO connected */
 | 
				
			||||||
 | 
						if (auto_isoc_alt && hci_dev_test_flag(data->hdev, HCI_USER_CHANNEL))
 | 
				
			||||||
 | 
							btusb_sco_connected(data, skb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return data->recv_event(data->hdev, skb);
 | 
						return data->recv_event(data->hdev, skb);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3644,6 +3685,7 @@ static ssize_t force_poll_sync_write(struct file *file,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct file_operations force_poll_sync_fops = {
 | 
					static const struct file_operations force_poll_sync_fops = {
 | 
				
			||||||
 | 
						.owner		= THIS_MODULE,
 | 
				
			||||||
	.open		= simple_open,
 | 
						.open		= simple_open,
 | 
				
			||||||
	.read		= force_poll_sync_read,
 | 
						.read		= force_poll_sync_read,
 | 
				
			||||||
	.write		= force_poll_sync_write,
 | 
						.write		= force_poll_sync_write,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1095,8 +1095,9 @@ static void mhi_pci_recovery_work(struct work_struct *work)
 | 
				
			||||||
err_unprepare:
 | 
					err_unprepare:
 | 
				
			||||||
	mhi_unprepare_after_power_down(mhi_cntrl);
 | 
						mhi_unprepare_after_power_down(mhi_cntrl);
 | 
				
			||||||
err_try_reset:
 | 
					err_try_reset:
 | 
				
			||||||
	if (pci_reset_function(pdev))
 | 
						err = pci_try_reset_function(pdev);
 | 
				
			||||||
		dev_err(&pdev->dev, "Recovery failed\n");
 | 
						if (err)
 | 
				
			||||||
 | 
							dev_err(&pdev->dev, "Recovery failed: %d\n", err);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void health_check(struct timer_list *t)
 | 
					static void health_check(struct timer_list *t)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,9 +109,29 @@ static int simple_pm_bus_runtime_resume(struct device *dev)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int simple_pm_bus_suspend(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct simple_pm_bus *bus = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!bus)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pm_runtime_force_suspend(dev);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int simple_pm_bus_resume(struct device *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct simple_pm_bus *bus = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!bus)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pm_runtime_force_resume(dev);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct dev_pm_ops simple_pm_bus_pm_ops = {
 | 
					static const struct dev_pm_ops simple_pm_bus_pm_ops = {
 | 
				
			||||||
	RUNTIME_PM_OPS(simple_pm_bus_runtime_suspend, simple_pm_bus_runtime_resume, NULL)
 | 
						RUNTIME_PM_OPS(simple_pm_bus_runtime_suspend, simple_pm_bus_runtime_resume, NULL)
 | 
				
			||||||
	NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
 | 
						NOIRQ_SYSTEM_SLEEP_PM_OPS(simple_pm_bus_suspend, simple_pm_bus_resume)
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ONLY_BUS	((void *) 1) /* Match if the device is only a bus. */
 | 
					#define ONLY_BUS	((void *) 1) /* Match if the device is only a bus. */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -473,8 +473,12 @@ static ssize_t driver_override_show(struct device *dev,
 | 
				
			||||||
				    struct device_attribute *attr, char *buf)
 | 
									    struct device_attribute *attr, char *buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct cdx_device *cdx_dev = to_cdx_device(dev);
 | 
						struct cdx_device *cdx_dev = to_cdx_device(dev);
 | 
				
			||||||
 | 
						ssize_t len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return sysfs_emit(buf, "%s\n", cdx_dev->driver_override);
 | 
						device_lock(dev);
 | 
				
			||||||
 | 
						len = sysfs_emit(buf, "%s\n", cdx_dev->driver_override);
 | 
				
			||||||
 | 
						device_unlock(dev);
 | 
				
			||||||
 | 
						return len;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
static DEVICE_ATTR_RW(driver_override);
 | 
					static DEVICE_ATTR_RW(driver_override);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -264,8 +264,8 @@ int misc_register(struct miscdevice *misc)
 | 
				
			||||||
		device_create_with_groups(&misc_class, misc->parent, dev,
 | 
							device_create_with_groups(&misc_class, misc->parent, dev,
 | 
				
			||||||
					  misc, misc->groups, "%s", misc->name);
 | 
										  misc, misc->groups, "%s", misc->name);
 | 
				
			||||||
	if (IS_ERR(misc->this_device)) {
 | 
						if (IS_ERR(misc->this_device)) {
 | 
				
			||||||
		if (is_dynamic) {
 | 
					 | 
				
			||||||
		misc_minor_free(misc->minor);
 | 
							misc_minor_free(misc->minor);
 | 
				
			||||||
 | 
							if (is_dynamic) {
 | 
				
			||||||
			misc->minor = MISC_DYNAMIC_MINOR;
 | 
								misc->minor = MISC_DYNAMIC_MINOR;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err = PTR_ERR(misc->this_device);
 | 
							err = PTR_ERR(misc->this_device);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -923,14 +923,14 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pipe_lock(pipe);
 | 
						pipe_lock(pipe);
 | 
				
			||||||
	ret = 0;
 | 
						ret = 0;
 | 
				
			||||||
	if (pipe_empty(pipe->head, pipe->tail))
 | 
						if (pipe_is_empty(pipe))
 | 
				
			||||||
		goto error_out;
 | 
							goto error_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK);
 | 
						ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		goto error_out;
 | 
							goto error_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	occupancy = pipe_occupancy(pipe->head, pipe->tail);
 | 
						occupancy = pipe_buf_usage(pipe);
 | 
				
			||||||
	buf = alloc_buf(port->portdev->vdev, 0, occupancy);
 | 
						buf = alloc_buf(port->portdev->vdev, 0, occupancy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!buf) {
 | 
						if (!buf) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -827,7 +827,6 @@ static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = {
 | 
				
			||||||
			&disp_cc_mdss_byte0_clk_src.clkr.hw,
 | 
								&disp_cc_mdss_byte0_clk_src.clkr.hw,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		.num_parents = 1,
 | 
							.num_parents = 1,
 | 
				
			||||||
		.flags = CLK_SET_RATE_PARENT,
 | 
					 | 
				
			||||||
		.ops = &clk_regmap_div_ops,
 | 
							.ops = &clk_regmap_div_ops,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -842,7 +841,6 @@ static struct clk_regmap_div disp_cc_mdss_byte1_div_clk_src = {
 | 
				
			||||||
			&disp_cc_mdss_byte1_clk_src.clkr.hw,
 | 
								&disp_cc_mdss_byte1_clk_src.clkr.hw,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		.num_parents = 1,
 | 
							.num_parents = 1,
 | 
				
			||||||
		.flags = CLK_SET_RATE_PARENT,
 | 
					 | 
				
			||||||
		.ops = &clk_regmap_div_ops,
 | 
							.ops = &clk_regmap_div_ops,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -382,17 +382,9 @@ static const unsigned long cmu_top_clk_regs[] __initconst = {
 | 
				
			||||||
	EARLY_WAKEUP_DPU_DEST,
 | 
						EARLY_WAKEUP_DPU_DEST,
 | 
				
			||||||
	EARLY_WAKEUP_CSIS_DEST,
 | 
						EARLY_WAKEUP_CSIS_DEST,
 | 
				
			||||||
	EARLY_WAKEUP_SW_TRIG_APM,
 | 
						EARLY_WAKEUP_SW_TRIG_APM,
 | 
				
			||||||
	EARLY_WAKEUP_SW_TRIG_APM_SET,
 | 
					 | 
				
			||||||
	EARLY_WAKEUP_SW_TRIG_APM_CLEAR,
 | 
					 | 
				
			||||||
	EARLY_WAKEUP_SW_TRIG_CLUSTER0,
 | 
						EARLY_WAKEUP_SW_TRIG_CLUSTER0,
 | 
				
			||||||
	EARLY_WAKEUP_SW_TRIG_CLUSTER0_SET,
 | 
					 | 
				
			||||||
	EARLY_WAKEUP_SW_TRIG_CLUSTER0_CLEAR,
 | 
					 | 
				
			||||||
	EARLY_WAKEUP_SW_TRIG_DPU,
 | 
						EARLY_WAKEUP_SW_TRIG_DPU,
 | 
				
			||||||
	EARLY_WAKEUP_SW_TRIG_DPU_SET,
 | 
					 | 
				
			||||||
	EARLY_WAKEUP_SW_TRIG_DPU_CLEAR,
 | 
					 | 
				
			||||||
	EARLY_WAKEUP_SW_TRIG_CSIS,
 | 
						EARLY_WAKEUP_SW_TRIG_CSIS,
 | 
				
			||||||
	EARLY_WAKEUP_SW_TRIG_CSIS_SET,
 | 
					 | 
				
			||||||
	EARLY_WAKEUP_SW_TRIG_CSIS_CLEAR,
 | 
					 | 
				
			||||||
	CLK_CON_MUX_MUX_CLKCMU_BO_BUS,
 | 
						CLK_CON_MUX_MUX_CLKCMU_BO_BUS,
 | 
				
			||||||
	CLK_CON_MUX_MUX_CLKCMU_BUS0_BUS,
 | 
						CLK_CON_MUX_MUX_CLKCMU_BUS0_BUS,
 | 
				
			||||||
	CLK_CON_MUX_MUX_CLKCMU_BUS1_BUS,
 | 
						CLK_CON_MUX_MUX_CLKCMU_BUS1_BUS,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -206,6 +206,7 @@ static const struct clk_ops samsung_pll3000_clk_ops = {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
/* Maximum lock time can be 270 * PDIV cycles */
 | 
					/* Maximum lock time can be 270 * PDIV cycles */
 | 
				
			||||||
#define PLL35XX_LOCK_FACTOR	(270)
 | 
					#define PLL35XX_LOCK_FACTOR	(270)
 | 
				
			||||||
 | 
					#define PLL142XX_LOCK_FACTOR	(150)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PLL35XX_MDIV_MASK       (0x3FF)
 | 
					#define PLL35XX_MDIV_MASK       (0x3FF)
 | 
				
			||||||
#define PLL35XX_PDIV_MASK       (0x3F)
 | 
					#define PLL35XX_PDIV_MASK       (0x3F)
 | 
				
			||||||
| 
						 | 
					@ -272,6 +273,10 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Set PLL lock time. */
 | 
						/* Set PLL lock time. */
 | 
				
			||||||
 | 
						if (pll->type == pll_142xx)
 | 
				
			||||||
 | 
							writel_relaxed(rate->pdiv * PLL142XX_LOCK_FACTOR,
 | 
				
			||||||
 | 
								pll->lock_reg);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
		writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR,
 | 
							writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR,
 | 
				
			||||||
			pll->lock_reg);
 | 
								pll->lock_reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,10 +119,15 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf,
 | 
				
			||||||
	struct platform_device *pdev;
 | 
						struct platform_device *pdev;
 | 
				
			||||||
	int res, id;
 | 
						int res, id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!try_module_get(THIS_MODULE))
 | 
				
			||||||
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* kernfs guarantees string termination, so count + 1 is safe */
 | 
						/* kernfs guarantees string termination, so count + 1 is safe */
 | 
				
			||||||
	aggr = kzalloc(sizeof(*aggr) + count + 1, GFP_KERNEL);
 | 
						aggr = kzalloc(sizeof(*aggr) + count + 1, GFP_KERNEL);
 | 
				
			||||||
	if (!aggr)
 | 
						if (!aggr) {
 | 
				
			||||||
		return -ENOMEM;
 | 
							res = -ENOMEM;
 | 
				
			||||||
 | 
							goto put_module;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(aggr->args, buf, count + 1);
 | 
						memcpy(aggr->args, buf, count + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -161,6 +166,7 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	aggr->pdev = pdev;
 | 
						aggr->pdev = pdev;
 | 
				
			||||||
 | 
						module_put(THIS_MODULE);
 | 
				
			||||||
	return count;
 | 
						return count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
remove_table:
 | 
					remove_table:
 | 
				
			||||||
| 
						 | 
					@ -175,6 +181,8 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf,
 | 
				
			||||||
	kfree(aggr->lookups);
 | 
						kfree(aggr->lookups);
 | 
				
			||||||
free_ga:
 | 
					free_ga:
 | 
				
			||||||
	kfree(aggr);
 | 
						kfree(aggr);
 | 
				
			||||||
 | 
					put_module:
 | 
				
			||||||
 | 
						module_put(THIS_MODULE);
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -203,13 +211,19 @@ static ssize_t delete_device_store(struct device_driver *driver,
 | 
				
			||||||
	if (error)
 | 
						if (error)
 | 
				
			||||||
		return error;
 | 
							return error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!try_module_get(THIS_MODULE))
 | 
				
			||||||
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&gpio_aggregator_lock);
 | 
						mutex_lock(&gpio_aggregator_lock);
 | 
				
			||||||
	aggr = idr_remove(&gpio_aggregator_idr, id);
 | 
						aggr = idr_remove(&gpio_aggregator_idr, id);
 | 
				
			||||||
	mutex_unlock(&gpio_aggregator_lock);
 | 
						mutex_unlock(&gpio_aggregator_lock);
 | 
				
			||||||
	if (!aggr)
 | 
						if (!aggr) {
 | 
				
			||||||
 | 
							module_put(THIS_MODULE);
 | 
				
			||||||
		return -ENOENT;
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gpio_aggregator_free(aggr);
 | 
						gpio_aggregator_free(aggr);
 | 
				
			||||||
 | 
						module_put(THIS_MODULE);
 | 
				
			||||||
	return count;
 | 
						return count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
static DRIVER_ATTR_WO(delete_device);
 | 
					static DRIVER_ATTR_WO(delete_device);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@ struct gpio_rcar_info {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct gpio_rcar_priv {
 | 
					struct gpio_rcar_priv {
 | 
				
			||||||
	void __iomem *base;
 | 
						void __iomem *base;
 | 
				
			||||||
	spinlock_t lock;
 | 
						raw_spinlock_t lock;
 | 
				
			||||||
	struct device *dev;
 | 
						struct device *dev;
 | 
				
			||||||
	struct gpio_chip gpio_chip;
 | 
						struct gpio_chip gpio_chip;
 | 
				
			||||||
	unsigned int irq_parent;
 | 
						unsigned int irq_parent;
 | 
				
			||||||
| 
						 | 
					@ -123,7 +123,7 @@ static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p,
 | 
				
			||||||
	 * "Setting Level-Sensitive Interrupt Input Mode"
 | 
						 * "Setting Level-Sensitive Interrupt Input Mode"
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&p->lock, flags);
 | 
						raw_spin_lock_irqsave(&p->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Configure positive or negative logic in POSNEG */
 | 
						/* Configure positive or negative logic in POSNEG */
 | 
				
			||||||
	gpio_rcar_modify_bit(p, POSNEG, hwirq, !active_high_rising_edge);
 | 
						gpio_rcar_modify_bit(p, POSNEG, hwirq, !active_high_rising_edge);
 | 
				
			||||||
| 
						 | 
					@ -142,7 +142,7 @@ static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p,
 | 
				
			||||||
	if (!level_trigger)
 | 
						if (!level_trigger)
 | 
				
			||||||
		gpio_rcar_write(p, INTCLR, BIT(hwirq));
 | 
							gpio_rcar_write(p, INTCLR, BIT(hwirq));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_irqrestore(&p->lock, flags);
 | 
						raw_spin_unlock_irqrestore(&p->lock, flags);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type)
 | 
					static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type)
 | 
				
			||||||
| 
						 | 
					@ -246,7 +246,7 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip,
 | 
				
			||||||
	 * "Setting General Input Mode"
 | 
						 * "Setting General Input Mode"
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&p->lock, flags);
 | 
						raw_spin_lock_irqsave(&p->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Configure positive logic in POSNEG */
 | 
						/* Configure positive logic in POSNEG */
 | 
				
			||||||
	gpio_rcar_modify_bit(p, POSNEG, gpio, false);
 | 
						gpio_rcar_modify_bit(p, POSNEG, gpio, false);
 | 
				
			||||||
| 
						 | 
					@ -261,7 +261,7 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip,
 | 
				
			||||||
	if (p->info.has_outdtsel && output)
 | 
						if (p->info.has_outdtsel && output)
 | 
				
			||||||
		gpio_rcar_modify_bit(p, OUTDTSEL, gpio, false);
 | 
							gpio_rcar_modify_bit(p, OUTDTSEL, gpio, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_irqrestore(&p->lock, flags);
 | 
						raw_spin_unlock_irqrestore(&p->lock, flags);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int gpio_rcar_request(struct gpio_chip *chip, unsigned offset)
 | 
					static int gpio_rcar_request(struct gpio_chip *chip, unsigned offset)
 | 
				
			||||||
| 
						 | 
					@ -347,7 +347,7 @@ static int gpio_rcar_get_multiple(struct gpio_chip *chip, unsigned long *mask,
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&p->lock, flags);
 | 
						raw_spin_lock_irqsave(&p->lock, flags);
 | 
				
			||||||
	outputs = gpio_rcar_read(p, INOUTSEL);
 | 
						outputs = gpio_rcar_read(p, INOUTSEL);
 | 
				
			||||||
	m = outputs & bankmask;
 | 
						m = outputs & bankmask;
 | 
				
			||||||
	if (m)
 | 
						if (m)
 | 
				
			||||||
| 
						 | 
					@ -356,7 +356,7 @@ static int gpio_rcar_get_multiple(struct gpio_chip *chip, unsigned long *mask,
 | 
				
			||||||
	m = ~outputs & bankmask;
 | 
						m = ~outputs & bankmask;
 | 
				
			||||||
	if (m)
 | 
						if (m)
 | 
				
			||||||
		val |= gpio_rcar_read(p, INDT) & m;
 | 
							val |= gpio_rcar_read(p, INDT) & m;
 | 
				
			||||||
	spin_unlock_irqrestore(&p->lock, flags);
 | 
						raw_spin_unlock_irqrestore(&p->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bits[0] = val;
 | 
						bits[0] = val;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -367,9 +367,9 @@ static void gpio_rcar_set(struct gpio_chip *chip, unsigned offset, int value)
 | 
				
			||||||
	struct gpio_rcar_priv *p = gpiochip_get_data(chip);
 | 
						struct gpio_rcar_priv *p = gpiochip_get_data(chip);
 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&p->lock, flags);
 | 
						raw_spin_lock_irqsave(&p->lock, flags);
 | 
				
			||||||
	gpio_rcar_modify_bit(p, OUTDT, offset, value);
 | 
						gpio_rcar_modify_bit(p, OUTDT, offset, value);
 | 
				
			||||||
	spin_unlock_irqrestore(&p->lock, flags);
 | 
						raw_spin_unlock_irqrestore(&p->lock, flags);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gpio_rcar_set_multiple(struct gpio_chip *chip, unsigned long *mask,
 | 
					static void gpio_rcar_set_multiple(struct gpio_chip *chip, unsigned long *mask,
 | 
				
			||||||
| 
						 | 
					@ -386,12 +386,12 @@ static void gpio_rcar_set_multiple(struct gpio_chip *chip, unsigned long *mask,
 | 
				
			||||||
	if (!bankmask)
 | 
						if (!bankmask)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&p->lock, flags);
 | 
						raw_spin_lock_irqsave(&p->lock, flags);
 | 
				
			||||||
	val = gpio_rcar_read(p, OUTDT);
 | 
						val = gpio_rcar_read(p, OUTDT);
 | 
				
			||||||
	val &= ~bankmask;
 | 
						val &= ~bankmask;
 | 
				
			||||||
	val |= (bankmask & bits[0]);
 | 
						val |= (bankmask & bits[0]);
 | 
				
			||||||
	gpio_rcar_write(p, OUTDT, val);
 | 
						gpio_rcar_write(p, OUTDT, val);
 | 
				
			||||||
	spin_unlock_irqrestore(&p->lock, flags);
 | 
						raw_spin_unlock_irqrestore(&p->lock, flags);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset,
 | 
					static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset,
 | 
				
			||||||
| 
						 | 
					@ -468,7 +468,12 @@ static int gpio_rcar_parse_dt(struct gpio_rcar_priv *p, unsigned int *npins)
 | 
				
			||||||
	p->info = *info;
 | 
						p->info = *info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args);
 | 
						ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args);
 | 
				
			||||||
	*npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK;
 | 
						if (ret) {
 | 
				
			||||||
 | 
							*npins = RCAR_MAX_GPIO_PER_BANK;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							*npins = args.args[2];
 | 
				
			||||||
 | 
							of_node_put(args.np);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) {
 | 
						if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) {
 | 
				
			||||||
		dev_warn(p->dev, "Invalid number of gpio lines %u, using %u\n",
 | 
							dev_warn(p->dev, "Invalid number of gpio lines %u, using %u\n",
 | 
				
			||||||
| 
						 | 
					@ -505,7 +510,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p->dev = dev;
 | 
						p->dev = dev;
 | 
				
			||||||
	spin_lock_init(&p->lock);
 | 
						raw_spin_lock_init(&p->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Get device configuration from DT node */
 | 
						/* Get device configuration from DT node */
 | 
				
			||||||
	ret = gpio_rcar_parse_dt(p, &npins);
 | 
						ret = gpio_rcar_parse_dt(p, &npins);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2729,7 +2729,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
 | 
				
			||||||
	cdev->gdev = gpio_device_get(gdev);
 | 
						cdev->gdev = gpio_device_get(gdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cdev->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify;
 | 
						cdev->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify;
 | 
				
			||||||
	ret = atomic_notifier_chain_register(&gdev->line_state_notifier,
 | 
						scoped_guard(write_lock_irqsave, &gdev->line_state_lock)
 | 
				
			||||||
 | 
							ret = raw_notifier_chain_register(&gdev->line_state_notifier,
 | 
				
			||||||
						  &cdev->lineinfo_changed_nb);
 | 
											  &cdev->lineinfo_changed_nb);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto out_free_bitmap;
 | 
							goto out_free_bitmap;
 | 
				
			||||||
| 
						 | 
					@ -2754,7 +2755,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
 | 
				
			||||||
	blocking_notifier_chain_unregister(&gdev->device_notifier,
 | 
						blocking_notifier_chain_unregister(&gdev->device_notifier,
 | 
				
			||||||
					   &cdev->device_unregistered_nb);
 | 
										   &cdev->device_unregistered_nb);
 | 
				
			||||||
out_unregister_line_notifier:
 | 
					out_unregister_line_notifier:
 | 
				
			||||||
	atomic_notifier_chain_unregister(&gdev->line_state_notifier,
 | 
						scoped_guard(write_lock_irqsave, &gdev->line_state_lock)
 | 
				
			||||||
 | 
							raw_notifier_chain_unregister(&gdev->line_state_notifier,
 | 
				
			||||||
					      &cdev->lineinfo_changed_nb);
 | 
										      &cdev->lineinfo_changed_nb);
 | 
				
			||||||
out_free_bitmap:
 | 
					out_free_bitmap:
 | 
				
			||||||
	gpio_device_put(gdev);
 | 
						gpio_device_put(gdev);
 | 
				
			||||||
| 
						 | 
					@ -2779,7 +2781,8 @@ static int gpio_chrdev_release(struct inode *inode, struct file *file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	blocking_notifier_chain_unregister(&gdev->device_notifier,
 | 
						blocking_notifier_chain_unregister(&gdev->device_notifier,
 | 
				
			||||||
					   &cdev->device_unregistered_nb);
 | 
										   &cdev->device_unregistered_nb);
 | 
				
			||||||
	atomic_notifier_chain_unregister(&gdev->line_state_notifier,
 | 
						scoped_guard(write_lock_irqsave, &gdev->line_state_lock)
 | 
				
			||||||
 | 
							raw_notifier_chain_unregister(&gdev->line_state_notifier,
 | 
				
			||||||
					      &cdev->lineinfo_changed_nb);
 | 
										      &cdev->lineinfo_changed_nb);
 | 
				
			||||||
	bitmap_free(cdev->watched_lines);
 | 
						bitmap_free(cdev->watched_lines);
 | 
				
			||||||
	gpio_device_put(gdev);
 | 
						gpio_device_put(gdev);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1025,7 +1025,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ATOMIC_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
 | 
						rwlock_init(&gdev->line_state_lock);
 | 
				
			||||||
 | 
						RAW_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
 | 
				
			||||||
	BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
 | 
						BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = init_srcu_struct(&gdev->srcu);
 | 
						ret = init_srcu_struct(&gdev->srcu);
 | 
				
			||||||
| 
						 | 
					@ -1056,25 +1057,20 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		desc->gdev = gdev;
 | 
							desc->gdev = gdev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index)) {
 | 
					 | 
				
			||||||
			ret = gc->get_direction(gc, desc_index);
 | 
					 | 
				
			||||||
			if (ret < 0)
 | 
					 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
				 * FIXME: Bail-out here once all GPIO drivers
 | 
							 * We would typically want to check the return value of
 | 
				
			||||||
				 * are updated to not return errors in
 | 
							 * get_direction() here but we must not check the return value
 | 
				
			||||||
				 * situations that can be considered normal
 | 
							 * and bail-out as pin controllers can have pins configured to
 | 
				
			||||||
				 * operation.
 | 
							 * alternate functions and return -EINVAL. Also: there's no
 | 
				
			||||||
 | 
							 * need to take the SRCU lock here.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
				dev_warn(&gdev->dev,
 | 
							if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index))
 | 
				
			||||||
					 "%s: get_direction failed: %d\n",
 | 
								assign_bit(FLAG_IS_OUT, &desc->flags,
 | 
				
			||||||
					 __func__, ret);
 | 
									   !gc->get_direction(gc, desc_index));
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
			assign_bit(FLAG_IS_OUT, &desc->flags, !ret);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			assign_bit(FLAG_IS_OUT,
 | 
								assign_bit(FLAG_IS_OUT,
 | 
				
			||||||
				   &desc->flags, !gc->direction_input);
 | 
									   &desc->flags, !gc->direction_input);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = of_gpiochip_add(gc);
 | 
						ret = of_gpiochip_add(gc);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
| 
						 | 
					@ -4193,8 +4189,9 @@ EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action)
 | 
					void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	atomic_notifier_call_chain(&desc->gdev->line_state_notifier,
 | 
						guard(read_lock_irqsave)(&desc->gdev->line_state_lock);
 | 
				
			||||||
				   action, desc);
 | 
					
 | 
				
			||||||
 | 
						raw_notifier_call_chain(&desc->gdev->line_state_notifier, action, desc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@
 | 
				
			||||||
#include <linux/gpio/driver.h>
 | 
					#include <linux/gpio/driver.h>
 | 
				
			||||||
#include <linux/module.h>
 | 
					#include <linux/module.h>
 | 
				
			||||||
#include <linux/notifier.h>
 | 
					#include <linux/notifier.h>
 | 
				
			||||||
 | 
					#include <linux/spinlock.h>
 | 
				
			||||||
#include <linux/srcu.h>
 | 
					#include <linux/srcu.h>
 | 
				
			||||||
#include <linux/workqueue.h>
 | 
					#include <linux/workqueue.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +46,7 @@
 | 
				
			||||||
 * @list: links gpio_device:s together for traversal
 | 
					 * @list: links gpio_device:s together for traversal
 | 
				
			||||||
 * @line_state_notifier: used to notify subscribers about lines being
 | 
					 * @line_state_notifier: used to notify subscribers about lines being
 | 
				
			||||||
 *                       requested, released or reconfigured
 | 
					 *                       requested, released or reconfigured
 | 
				
			||||||
 | 
					 * @line_state_lock: RW-spinlock protecting the line state notifier
 | 
				
			||||||
 * @line_state_wq: used to emit line state events from a separate thread in
 | 
					 * @line_state_wq: used to emit line state events from a separate thread in
 | 
				
			||||||
 *                 process context
 | 
					 *                 process context
 | 
				
			||||||
 * @device_notifier: used to notify character device wait queues about the GPIO
 | 
					 * @device_notifier: used to notify character device wait queues about the GPIO
 | 
				
			||||||
| 
						 | 
					@ -72,7 +74,8 @@ struct gpio_device {
 | 
				
			||||||
	const char		*label;
 | 
						const char		*label;
 | 
				
			||||||
	void			*data;
 | 
						void			*data;
 | 
				
			||||||
	struct list_head        list;
 | 
						struct list_head        list;
 | 
				
			||||||
	struct atomic_notifier_head line_state_notifier;
 | 
						struct raw_notifier_head line_state_notifier;
 | 
				
			||||||
 | 
						rwlock_t		line_state_lock;
 | 
				
			||||||
	struct workqueue_struct	*line_state_wq;
 | 
						struct workqueue_struct	*line_state_wq;
 | 
				
			||||||
	struct blocking_notifier_head device_notifier;
 | 
						struct blocking_notifier_head device_notifier;
 | 
				
			||||||
	struct srcu_struct	srcu;
 | 
						struct srcu_struct	srcu;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2555,7 +2555,6 @@ static int amdgpu_pmops_freeze(struct device *dev)
 | 
				
			||||||
	int r;
 | 
						int r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r = amdgpu_device_suspend(drm_dev, true);
 | 
						r = amdgpu_device_suspend(drm_dev, true);
 | 
				
			||||||
	adev->in_s4 = false;
 | 
					 | 
				
			||||||
	if (r)
 | 
						if (r)
 | 
				
			||||||
		return r;
 | 
							return r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2567,8 +2566,13 @@ static int amdgpu_pmops_freeze(struct device *dev)
 | 
				
			||||||
static int amdgpu_pmops_thaw(struct device *dev)
 | 
					static int amdgpu_pmops_thaw(struct device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct drm_device *drm_dev = dev_get_drvdata(dev);
 | 
						struct drm_device *drm_dev = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
						struct amdgpu_device *adev = drm_to_adev(drm_dev);
 | 
				
			||||||
 | 
						int r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return amdgpu_device_resume(drm_dev, true);
 | 
						r = amdgpu_device_resume(drm_dev, true);
 | 
				
			||||||
 | 
						adev->in_s4 = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int amdgpu_pmops_poweroff(struct device *dev)
 | 
					static int amdgpu_pmops_poweroff(struct device *dev)
 | 
				
			||||||
| 
						 | 
					@ -2581,6 +2585,9 @@ static int amdgpu_pmops_poweroff(struct device *dev)
 | 
				
			||||||
static int amdgpu_pmops_restore(struct device *dev)
 | 
					static int amdgpu_pmops_restore(struct device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct drm_device *drm_dev = dev_get_drvdata(dev);
 | 
						struct drm_device *drm_dev = dev_get_drvdata(dev);
 | 
				
			||||||
 | 
						struct amdgpu_device *adev = drm_to_adev(drm_dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						adev->in_s4 = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return amdgpu_device_resume(drm_dev, true);
 | 
						return amdgpu_device_resume(drm_dev, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -528,8 +528,9 @@ static void gmc_v12_0_get_vm_pte(struct amdgpu_device *adev,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
 | 
						bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
 | 
				
			||||||
	coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT;
 | 
						coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT;
 | 
				
			||||||
	is_system = (bo->tbo.resource->mem_type == TTM_PL_TT) ||
 | 
						is_system = bo->tbo.resource &&
 | 
				
			||||||
		(bo->tbo.resource->mem_type == AMDGPU_PL_PREEMPT);
 | 
							(bo->tbo.resource->mem_type == TTM_PL_TT ||
 | 
				
			||||||
 | 
							 bo->tbo.resource->mem_type == AMDGPU_PL_PREEMPT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (bo && bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
 | 
						if (bo && bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
 | 
				
			||||||
		*flags |= AMDGPU_PTE_DCC;
 | 
							*flags |= AMDGPU_PTE_DCC;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -284,7 +284,7 @@ static int vce_v2_0_stop(struct amdgpu_device *adev)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCN);
 | 
						ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCE);
 | 
				
			||||||
	if (!ip_block)
 | 
						if (!ip_block)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1230,11 +1230,13 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
 | 
				
			||||||
		decrement_queue_count(dqm, qpd, q);
 | 
							decrement_queue_count(dqm, qpd, q);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (dqm->dev->kfd->shared_resources.enable_mes) {
 | 
							if (dqm->dev->kfd->shared_resources.enable_mes) {
 | 
				
			||||||
			retval = remove_queue_mes(dqm, q, qpd);
 | 
								int err;
 | 
				
			||||||
			if (retval) {
 | 
					
 | 
				
			||||||
 | 
								err = remove_queue_mes(dqm, q, qpd);
 | 
				
			||||||
 | 
								if (err) {
 | 
				
			||||||
				dev_err(dev, "Failed to evict queue %d\n",
 | 
									dev_err(dev, "Failed to evict queue %d\n",
 | 
				
			||||||
					q->properties.queue_id);
 | 
										q->properties.queue_id);
 | 
				
			||||||
				goto out;
 | 
									retval = err;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -266,8 +266,8 @@ int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_prope
 | 
				
			||||||
	/* EOP buffer is not required for all ASICs */
 | 
						/* EOP buffer is not required for all ASICs */
 | 
				
			||||||
	if (properties->eop_ring_buffer_address) {
 | 
						if (properties->eop_ring_buffer_address) {
 | 
				
			||||||
		if (properties->eop_ring_buffer_size != topo_dev->node_props.eop_buffer_size) {
 | 
							if (properties->eop_ring_buffer_size != topo_dev->node_props.eop_buffer_size) {
 | 
				
			||||||
			pr_debug("queue eop bo size 0x%lx not equal to node eop buf size 0x%x\n",
 | 
								pr_debug("queue eop bo size 0x%x not equal to node eop buf size 0x%x\n",
 | 
				
			||||||
				properties->eop_buf_bo->tbo.base.size,
 | 
									properties->eop_ring_buffer_size,
 | 
				
			||||||
				topo_dev->node_props.eop_buffer_size);
 | 
									topo_dev->node_props.eop_buffer_size);
 | 
				
			||||||
			err = -EINVAL;
 | 
								err = -EINVAL;
 | 
				
			||||||
			goto out_err_unreserve;
 | 
								goto out_err_unreserve;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -245,6 +245,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 | 
				
			||||||
static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector);
 | 
					static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector);
 | 
				
			||||||
static void handle_hpd_rx_irq(void *param);
 | 
					static void handle_hpd_rx_irq(void *param);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
 | 
				
			||||||
 | 
										 int bl_idx,
 | 
				
			||||||
 | 
										 u32 user_brightness);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool
 | 
					static bool
 | 
				
			||||||
is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
 | 
					is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
 | 
				
			||||||
				 struct drm_crtc_state *new_crtc_state);
 | 
									 struct drm_crtc_state *new_crtc_state);
 | 
				
			||||||
| 
						 | 
					@ -3371,8 +3375,19 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mutex_unlock(&dm->dc_lock);
 | 
							mutex_unlock(&dm->dc_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* set the backlight after a reset */
 | 
				
			||||||
 | 
							for (i = 0; i < dm->num_of_edps; i++) {
 | 
				
			||||||
 | 
								if (dm->backlight_dev[i])
 | 
				
			||||||
 | 
									amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* leave display off for S4 sequence */
 | 
				
			||||||
 | 
						if (adev->in_s4)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Recreate dc_state - DC invalidates it when setting power state to S3. */
 | 
						/* Recreate dc_state - DC invalidates it when setting power state to S3. */
 | 
				
			||||||
	dc_state_release(dm_state->context);
 | 
						dc_state_release(dm_state->context);
 | 
				
			||||||
	dm_state->context = dc_state_create(dm->dc, NULL);
 | 
						dm_state->context = dc_state_create(dm->dc, NULL);
 | 
				
			||||||
| 
						 | 
					@ -4906,6 +4921,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
 | 
				
			||||||
	dm->backlight_dev[aconnector->bl_idx] =
 | 
						dm->backlight_dev[aconnector->bl_idx] =
 | 
				
			||||||
		backlight_device_register(bl_name, aconnector->base.kdev, dm,
 | 
							backlight_device_register(bl_name, aconnector->base.kdev, dm,
 | 
				
			||||||
					  &amdgpu_dm_backlight_ops, &props);
 | 
										  &amdgpu_dm_backlight_ops, &props);
 | 
				
			||||||
 | 
						dm->brightness[aconnector->bl_idx] = props.brightness;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (IS_ERR(dm->backlight_dev[aconnector->bl_idx])) {
 | 
						if (IS_ERR(dm->backlight_dev[aconnector->bl_idx])) {
 | 
				
			||||||
		DRM_ERROR("DM: Backlight registration failed!\n");
 | 
							DRM_ERROR("DM: Backlight registration failed!\n");
 | 
				
			||||||
| 
						 | 
					@ -4973,7 +4989,6 @@ static void setup_backlight_device(struct amdgpu_display_manager *dm,
 | 
				
			||||||
	aconnector->bl_idx = bl_idx;
 | 
						aconnector->bl_idx = bl_idx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	amdgpu_dm_update_backlight_caps(dm, bl_idx);
 | 
						amdgpu_dm_update_backlight_caps(dm, bl_idx);
 | 
				
			||||||
	dm->brightness[bl_idx] = AMDGPU_MAX_BL_LEVEL;
 | 
					 | 
				
			||||||
	dm->backlight_link[bl_idx] = link;
 | 
						dm->backlight_link[bl_idx] = link;
 | 
				
			||||||
	dm->num_of_edps++;
 | 
						dm->num_of_edps++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -455,6 +455,7 @@ void hdcp_destroy(struct kobject *kobj, struct hdcp_workqueue *hdcp_work)
 | 
				
			||||||
	for (i = 0; i < hdcp_work->max_link; i++) {
 | 
						for (i = 0; i < hdcp_work->max_link; i++) {
 | 
				
			||||||
		cancel_delayed_work_sync(&hdcp_work[i].callback_dwork);
 | 
							cancel_delayed_work_sync(&hdcp_work[i].callback_dwork);
 | 
				
			||||||
		cancel_delayed_work_sync(&hdcp_work[i].watchdog_timer_dwork);
 | 
							cancel_delayed_work_sync(&hdcp_work[i].watchdog_timer_dwork);
 | 
				
			||||||
 | 
							cancel_delayed_work_sync(&hdcp_work[i].property_validate_dwork);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sysfs_remove_bin_file(kobj, &hdcp_work[0].attr);
 | 
						sysfs_remove_bin_file(kobj, &hdcp_work[0].attr);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -894,8 +894,16 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
 | 
				
			||||||
	struct drm_device *dev = adev_to_drm(adev);
 | 
						struct drm_device *dev = adev_to_drm(adev);
 | 
				
			||||||
	struct drm_connector *connector;
 | 
						struct drm_connector *connector;
 | 
				
			||||||
	struct drm_connector_list_iter iter;
 | 
						struct drm_connector_list_iter iter;
 | 
				
			||||||
 | 
						int irq_type;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* First, clear all hpd and hpdrx interrupts */
 | 
				
			||||||
 | 
						for (i = DC_IRQ_SOURCE_HPD1; i <= DC_IRQ_SOURCE_HPD6RX; i++) {
 | 
				
			||||||
 | 
							if (!dc_interrupt_set(adev->dm.dc, i, false))
 | 
				
			||||||
 | 
								drm_err(dev, "Failed to clear hpd(rx) source=%d on init\n",
 | 
				
			||||||
 | 
									i);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drm_connector_list_iter_begin(dev, &iter);
 | 
						drm_connector_list_iter_begin(dev, &iter);
 | 
				
			||||||
	drm_for_each_connector_iter(connector, &iter) {
 | 
						drm_for_each_connector_iter(connector, &iter) {
 | 
				
			||||||
		struct amdgpu_dm_connector *amdgpu_dm_connector;
 | 
							struct amdgpu_dm_connector *amdgpu_dm_connector;
 | 
				
			||||||
| 
						 | 
					@ -908,11 +916,32 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dc_link = amdgpu_dm_connector->dc_link;
 | 
							dc_link = amdgpu_dm_connector->dc_link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Get a base driver irq reference for hpd ints for the lifetime
 | 
				
			||||||
 | 
							 * of dm. Note that only hpd interrupt types are registered with
 | 
				
			||||||
 | 
							 * base driver; hpd_rx types aren't. IOW, amdgpu_irq_get/put on
 | 
				
			||||||
 | 
							 * hpd_rx isn't available. DM currently controls hpd_rx
 | 
				
			||||||
 | 
							 * explicitly with dc_interrupt_set()
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
		if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
 | 
							if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
 | 
				
			||||||
 | 
								irq_type = dc_link->irq_source_hpd - DC_IRQ_SOURCE_HPD1;
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * TODO: There's a mismatch between mode_info.num_hpd
 | 
				
			||||||
 | 
								 * and what bios reports as the # of connectors with hpd
 | 
				
			||||||
 | 
								 * sources. Since the # of hpd source types registered
 | 
				
			||||||
 | 
								 * with base driver == mode_info.num_hpd, we have to
 | 
				
			||||||
 | 
								 * fallback to dc_interrupt_set for the remaining types.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if (irq_type < adev->mode_info.num_hpd) {
 | 
				
			||||||
 | 
									if (amdgpu_irq_get(adev, &adev->hpd_irq, irq_type))
 | 
				
			||||||
 | 
										drm_err(dev, "DM_IRQ: Failed get HPD for source=%d)!\n",
 | 
				
			||||||
 | 
											dc_link->irq_source_hpd);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
				dc_interrupt_set(adev->dm.dc,
 | 
									dc_interrupt_set(adev->dm.dc,
 | 
				
			||||||
						 dc_link->irq_source_hpd,
 | 
											 dc_link->irq_source_hpd,
 | 
				
			||||||
						 true);
 | 
											 true);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) {
 | 
							if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) {
 | 
				
			||||||
			dc_interrupt_set(adev->dm.dc,
 | 
								dc_interrupt_set(adev->dm.dc,
 | 
				
			||||||
| 
						 | 
					@ -921,12 +950,6 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	drm_connector_list_iter_end(&iter);
 | 
						drm_connector_list_iter_end(&iter);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Update reference counts for HPDs */
 | 
					 | 
				
			||||||
	for (i = DC_IRQ_SOURCE_HPD1; i <= adev->mode_info.num_hpd; i++) {
 | 
					 | 
				
			||||||
		if (amdgpu_irq_get(adev, &adev->hpd_irq, i - DC_IRQ_SOURCE_HPD1))
 | 
					 | 
				
			||||||
			drm_err(dev, "DM_IRQ: Failed get HPD for source=%d)!\n", i);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -942,7 +965,7 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
 | 
				
			||||||
	struct drm_device *dev = adev_to_drm(adev);
 | 
						struct drm_device *dev = adev_to_drm(adev);
 | 
				
			||||||
	struct drm_connector *connector;
 | 
						struct drm_connector *connector;
 | 
				
			||||||
	struct drm_connector_list_iter iter;
 | 
						struct drm_connector_list_iter iter;
 | 
				
			||||||
	int i;
 | 
						int irq_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drm_connector_list_iter_begin(dev, &iter);
 | 
						drm_connector_list_iter_begin(dev, &iter);
 | 
				
			||||||
	drm_for_each_connector_iter(connector, &iter) {
 | 
						drm_for_each_connector_iter(connector, &iter) {
 | 
				
			||||||
| 
						 | 
					@ -956,10 +979,19 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
 | 
				
			||||||
		dc_link = amdgpu_dm_connector->dc_link;
 | 
							dc_link = amdgpu_dm_connector->dc_link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
 | 
							if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
 | 
				
			||||||
 | 
								irq_type = dc_link->irq_source_hpd - DC_IRQ_SOURCE_HPD1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* TODO: See same TODO in amdgpu_dm_hpd_init() */
 | 
				
			||||||
 | 
								if (irq_type < adev->mode_info.num_hpd) {
 | 
				
			||||||
 | 
									if (amdgpu_irq_put(adev, &adev->hpd_irq, irq_type))
 | 
				
			||||||
 | 
										drm_err(dev, "DM_IRQ: Failed put HPD for source=%d!\n",
 | 
				
			||||||
 | 
											dc_link->irq_source_hpd);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
				dc_interrupt_set(adev->dm.dc,
 | 
									dc_interrupt_set(adev->dm.dc,
 | 
				
			||||||
						 dc_link->irq_source_hpd,
 | 
											 dc_link->irq_source_hpd,
 | 
				
			||||||
						 false);
 | 
											 false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) {
 | 
							if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) {
 | 
				
			||||||
			dc_interrupt_set(adev->dm.dc,
 | 
								dc_interrupt_set(adev->dm.dc,
 | 
				
			||||||
| 
						 | 
					@ -968,10 +1000,4 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	drm_connector_list_iter_end(&iter);
 | 
						drm_connector_list_iter_end(&iter);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Update reference counts for HPDs */
 | 
					 | 
				
			||||||
	for (i = DC_IRQ_SOURCE_HPD1; i <= adev->mode_info.num_hpd; i++) {
 | 
					 | 
				
			||||||
		if (amdgpu_irq_put(adev, &adev->hpd_irq, i - DC_IRQ_SOURCE_HPD1))
 | 
					 | 
				
			||||||
			drm_err(dev, "DM_IRQ: Failed put HPD for source=%d!\n", i);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -277,8 +277,11 @@ static int amdgpu_dm_plane_validate_dcc(struct amdgpu_device *adev,
 | 
				
			||||||
	if (!dcc->enable)
 | 
						if (!dcc->enable)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN ||
 | 
						if (adev->family < AMDGPU_FAMILY_GC_12_0_0 &&
 | 
				
			||||||
	    !dc->cap_funcs.get_dcc_compression_cap)
 | 
						    format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!dc->cap_funcs.get_dcc_compression_cap)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	input.format = format;
 | 
						input.format = format;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1455,7 +1455,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
 | 
				
			||||||
	DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
 | 
						DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Invalid input */
 | 
						/* Invalid input */
 | 
				
			||||||
	if (!plane_state->dst_rect.width ||
 | 
						if (!plane_state ||
 | 
				
			||||||
 | 
								!plane_state->dst_rect.width ||
 | 
				
			||||||
			!plane_state->dst_rect.height ||
 | 
								!plane_state->dst_rect.height ||
 | 
				
			||||||
			!plane_state->src_rect.width ||
 | 
								!plane_state->src_rect.width ||
 | 
				
			||||||
			!plane_state->src_rect.height) {
 | 
								!plane_state->src_rect.height) {
 | 
				
			||||||
| 
						 | 
					@ -3389,6 +3390,9 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
 | 
				
			||||||
		case COLOR_DEPTH_121212:
 | 
							case COLOR_DEPTH_121212:
 | 
				
			||||||
			normalized_pix_clk = (pix_clk * 36) / 24;
 | 
								normalized_pix_clk = (pix_clk * 36) / 24;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case COLOR_DEPTH_141414:
 | 
				
			||||||
 | 
								normalized_pix_clk = (pix_clk * 42) / 24;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case COLOR_DEPTH_161616:
 | 
							case COLOR_DEPTH_161616:
 | 
				
			||||||
			normalized_pix_clk = (pix_clk * 48) / 24;
 | 
								normalized_pix_clk = (pix_clk * 48) / 24;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -239,6 +239,7 @@ static const struct timing_generator_funcs dce60_tg_funcs = {
 | 
				
			||||||
				dce60_timing_generator_enable_advanced_request,
 | 
									dce60_timing_generator_enable_advanced_request,
 | 
				
			||||||
		.configure_crc = dce60_configure_crc,
 | 
							.configure_crc = dce60_configure_crc,
 | 
				
			||||||
		.get_crc = dce110_get_crc,
 | 
							.get_crc = dce110_get_crc,
 | 
				
			||||||
 | 
							.is_two_pixels_per_container = dce110_is_two_pixels_per_container,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void dce60_timing_generator_construct(
 | 
					void dce60_timing_generator_construct(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1895,16 +1895,6 @@ static int smu_v14_0_allow_ih_interrupt(struct smu_context *smu)
 | 
				
			||||||
				    NULL);
 | 
									    NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int smu_v14_0_process_pending_interrupt(struct smu_context *smu)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_ACDC_BIT))
 | 
					 | 
				
			||||||
		ret = smu_v14_0_allow_ih_interrupt(smu);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int smu_v14_0_enable_thermal_alert(struct smu_context *smu)
 | 
					int smu_v14_0_enable_thermal_alert(struct smu_context *smu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
| 
						 | 
					@ -1916,7 +1906,7 @@ int smu_v14_0_enable_thermal_alert(struct smu_context *smu)
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return smu_v14_0_process_pending_interrupt(smu);
 | 
						return smu_v14_0_allow_ih_interrupt(smu);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int smu_v14_0_disable_thermal_alert(struct smu_context *smu)
 | 
					int smu_v14_0_disable_thermal_alert(struct smu_context *smu)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4025,6 +4025,22 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool primary_mstb_probing_is_done(struct drm_dp_mst_topology_mgr *mgr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool probing_done = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_lock(&mgr->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mgr->mst_primary && drm_dp_mst_topology_try_get_mstb(mgr->mst_primary)) {
 | 
				
			||||||
 | 
							probing_done = mgr->mst_primary->link_address_sent;
 | 
				
			||||||
 | 
							drm_dp_mst_topology_put_mstb(mgr->mst_primary);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_unlock(&mgr->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return probing_done;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline bool
 | 
					static inline bool
 | 
				
			||||||
drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr *mgr,
 | 
					drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr *mgr,
 | 
				
			||||||
			  struct drm_dp_pending_up_req *up_req)
 | 
								  struct drm_dp_pending_up_req *up_req)
 | 
				
			||||||
| 
						 | 
					@ -4055,9 +4071,13 @@ drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr *mgr,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* TODO: Add missing handler for DP_RESOURCE_STATUS_NOTIFY events */
 | 
						/* TODO: Add missing handler for DP_RESOURCE_STATUS_NOTIFY events */
 | 
				
			||||||
	if (msg->req_type == DP_CONNECTION_STATUS_NOTIFY) {
 | 
						if (msg->req_type == DP_CONNECTION_STATUS_NOTIFY) {
 | 
				
			||||||
 | 
							if (!primary_mstb_probing_is_done(mgr)) {
 | 
				
			||||||
 | 
								drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it.\n");
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
			dowork = drm_dp_mst_handle_conn_stat(mstb, &msg->u.conn_stat);
 | 
								dowork = drm_dp_mst_handle_conn_stat(mstb, &msg->u.conn_stat);
 | 
				
			||||||
			hotplug = true;
 | 
								hotplug = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drm_dp_mst_topology_put_mstb(mstb);
 | 
						drm_dp_mst_topology_put_mstb(mstb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4138,10 +4158,11 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
 | 
				
			||||||
	drm_dp_send_up_ack_reply(mgr, mst_primary, up_req->msg.req_type,
 | 
						drm_dp_send_up_ack_reply(mgr, mst_primary, up_req->msg.req_type,
 | 
				
			||||||
				 false);
 | 
									 false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						drm_dp_mst_topology_put_mstb(mst_primary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (up_req->msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
 | 
						if (up_req->msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
 | 
				
			||||||
		const struct drm_dp_connection_status_notify *conn_stat =
 | 
							const struct drm_dp_connection_status_notify *conn_stat =
 | 
				
			||||||
			&up_req->msg.u.conn_stat;
 | 
								&up_req->msg.u.conn_stat;
 | 
				
			||||||
		bool handle_csn;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		drm_dbg_kms(mgr->dev, "Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n",
 | 
							drm_dbg_kms(mgr->dev, "Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n",
 | 
				
			||||||
			    conn_stat->port_number,
 | 
								    conn_stat->port_number,
 | 
				
			||||||
| 
						 | 
					@ -4150,16 +4171,6 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
 | 
				
			||||||
			    conn_stat->message_capability_status,
 | 
								    conn_stat->message_capability_status,
 | 
				
			||||||
			    conn_stat->input_port,
 | 
								    conn_stat->input_port,
 | 
				
			||||||
			    conn_stat->peer_device_type);
 | 
								    conn_stat->peer_device_type);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		mutex_lock(&mgr->probe_lock);
 | 
					 | 
				
			||||||
		handle_csn = mst_primary->link_address_sent;
 | 
					 | 
				
			||||||
		mutex_unlock(&mgr->probe_lock);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (!handle_csn) {
 | 
					 | 
				
			||||||
			drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it.");
 | 
					 | 
				
			||||||
			kfree(up_req);
 | 
					 | 
				
			||||||
			goto out_put_primary;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else if (up_req->msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
 | 
						} else if (up_req->msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
 | 
				
			||||||
		const struct drm_dp_resource_status_notify *res_stat =
 | 
							const struct drm_dp_resource_status_notify *res_stat =
 | 
				
			||||||
			&up_req->msg.u.resource_stat;
 | 
								&up_req->msg.u.resource_stat;
 | 
				
			||||||
| 
						 | 
					@ -4174,9 +4185,6 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
 | 
				
			||||||
	list_add_tail(&up_req->next, &mgr->up_req_list);
 | 
						list_add_tail(&up_req->next, &mgr->up_req_list);
 | 
				
			||||||
	mutex_unlock(&mgr->up_req_lock);
 | 
						mutex_unlock(&mgr->up_req_lock);
 | 
				
			||||||
	queue_work(system_long_wq, &mgr->up_req_work);
 | 
						queue_work(system_long_wq, &mgr->up_req_work);
 | 
				
			||||||
 | 
					 | 
				
			||||||
out_put_primary:
 | 
					 | 
				
			||||||
	drm_dp_mst_topology_put_mstb(mst_primary);
 | 
					 | 
				
			||||||
out_clear_reply:
 | 
					out_clear_reply:
 | 
				
			||||||
	reset_msg_rx_state(&mgr->up_req_recv);
 | 
						reset_msg_rx_state(&mgr->up_req_recv);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -956,6 +956,10 @@ int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mode != DRM_MODE_DPMS_ON)
 | 
						if (mode != DRM_MODE_DPMS_ON)
 | 
				
			||||||
		mode = DRM_MODE_DPMS_OFF;
 | 
							mode = DRM_MODE_DPMS_OFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (connector->dpms == mode)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	connector->dpms = mode;
 | 
						connector->dpms = mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	crtc = connector->state->crtc;
 | 
						crtc = connector->state->crtc;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1427,6 +1427,10 @@ EXPORT_SYMBOL(drm_hdmi_connector_get_output_format_name);
 | 
				
			||||||
 * 	callback. For atomic drivers the remapping to the "ACTIVE" property is
 | 
					 * 	callback. For atomic drivers the remapping to the "ACTIVE" property is
 | 
				
			||||||
 * 	implemented in the DRM core.
 | 
					 * 	implemented in the DRM core.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * 	On atomic drivers any DPMS setproperty ioctl where the value does not
 | 
				
			||||||
 | 
					 * 	change is completely skipped, otherwise a full atomic commit will occur.
 | 
				
			||||||
 | 
					 * 	On legacy drivers the exact behavior is driver specific.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * 	Note that this property cannot be set through the MODE_ATOMIC ioctl,
 | 
					 * 	Note that this property cannot be set through the MODE_ATOMIC ioctl,
 | 
				
			||||||
 * 	userspace must use "ACTIVE" on the CRTC instead.
 | 
					 * 	userspace must use "ACTIVE" on the CRTC instead.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -545,7 +545,7 @@ fn add_segments(&mut self, segments: &[&Segment<'_>]) {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self.push(&mut offset, (MODE_STOP, 4));
 | 
					        self.push(&mut offset, (MODE_STOP, 4));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let pad_offset = (offset + 7) / 8;
 | 
					        let pad_offset = offset.div_ceil(8);
 | 
				
			||||||
        for i in pad_offset..self.version.max_data() {
 | 
					        for i in pad_offset..self.version.max_data() {
 | 
				
			||||||
            self.data[i] = PADDING[(i & 1) ^ (pad_offset & 1)];
 | 
					            self.data[i] = PADDING[(i & 1) ^ (pad_offset & 1)];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -659,7 +659,7 @@ struct QrImage<'a> {
 | 
				
			||||||
impl QrImage<'_> {
 | 
					impl QrImage<'_> {
 | 
				
			||||||
    fn new<'a, 'b>(em: &'b EncodedMsg<'b>, qrdata: &'a mut [u8]) -> QrImage<'a> {
 | 
					    fn new<'a, 'b>(em: &'b EncodedMsg<'b>, qrdata: &'a mut [u8]) -> QrImage<'a> {
 | 
				
			||||||
        let width = em.version.width();
 | 
					        let width = em.version.width();
 | 
				
			||||||
        let stride = (width + 7) / 8;
 | 
					        let stride = width.div_ceil(8);
 | 
				
			||||||
        let data = qrdata;
 | 
					        let data = qrdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut qr_image = QrImage {
 | 
					        let mut qr_image = QrImage {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -279,6 +279,11 @@ static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
 | 
				
			||||||
					    0, PCI_DEVFN(2, 0));
 | 
										    0, PCI_DEVFN(2, 0));
 | 
				
			||||||
	int ret = -1;
 | 
						int ret = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pci_gfx_root == NULL) {
 | 
				
			||||||
 | 
							WARN_ON(1);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Get the address of the platform config vbt */
 | 
						/* Get the address of the platform config vbt */
 | 
				
			||||||
	pci_read_config_dword(pci_gfx_root, 0xFC, &addr);
 | 
						pci_read_config_dword(pci_gfx_root, 0xFC, &addr);
 | 
				
			||||||
	pci_dev_put(pci_gfx_root);
 | 
						pci_dev_put(pci_gfx_root);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -154,6 +154,7 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_free_mmio:
 | 
					err_free_mmio:
 | 
				
			||||||
 | 
						iounmap(hv->vram);
 | 
				
			||||||
	vmbus_free_mmio(hv->mem->start, hv->fb_size);
 | 
						vmbus_free_mmio(hv->mem->start, hv->fb_size);
 | 
				
			||||||
err_vmbus_close:
 | 
					err_vmbus_close:
 | 
				
			||||||
	vmbus_close(hdev->channel);
 | 
						vmbus_close(hdev->channel);
 | 
				
			||||||
| 
						 | 
					@ -172,6 +173,7 @@ static void hyperv_vmbus_remove(struct hv_device *hdev)
 | 
				
			||||||
	vmbus_close(hdev->channel);
 | 
						vmbus_close(hdev->channel);
 | 
				
			||||||
	hv_set_drvdata(hdev, NULL);
 | 
						hv_set_drvdata(hdev, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						iounmap(hv->vram);
 | 
				
			||||||
	vmbus_free_mmio(hv->mem->start, hv->fb_size);
 | 
						vmbus_free_mmio(hv->mem->start, hv->fb_size);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7830,9 +7830,6 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	intel_program_dpkgc_latency(state);
 | 
						intel_program_dpkgc_latency(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (state->modeset)
 | 
					 | 
				
			||||||
		intel_set_cdclk_post_plane_update(state);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	intel_wait_for_vblank_workers(state);
 | 
						intel_wait_for_vblank_workers(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* FIXME: We should call drm_atomic_helper_commit_hw_done() here
 | 
						/* FIXME: We should call drm_atomic_helper_commit_hw_done() here
 | 
				
			||||||
| 
						 | 
					@ -7906,6 +7903,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 | 
				
			||||||
		intel_verify_planes(state);
 | 
							intel_verify_planes(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	intel_sagv_post_plane_update(state);
 | 
						intel_sagv_post_plane_update(state);
 | 
				
			||||||
 | 
						if (state->modeset)
 | 
				
			||||||
 | 
							intel_set_cdclk_post_plane_update(state);
 | 
				
			||||||
	intel_pmdemand_post_plane_update(state);
 | 
						intel_pmdemand_post_plane_update(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drm_atomic_helper_commit_hw_done(&state->base);
 | 
						drm_atomic_helper_commit_hw_done(&state->base);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1867,7 +1867,8 @@ intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id)
 | 
				
			||||||
	/* create encoders */
 | 
						/* create encoders */
 | 
				
			||||||
	mst_stream_encoders_create(dig_port);
 | 
						mst_stream_encoders_create(dig_port);
 | 
				
			||||||
	ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, display->drm,
 | 
						ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, display->drm,
 | 
				
			||||||
					   &intel_dp->aux, 16, 3, conn_base_id);
 | 
										   &intel_dp->aux, 16,
 | 
				
			||||||
 | 
										   INTEL_NUM_PIPES(display), conn_base_id);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		intel_dp->mst_mgr.cbs = NULL;
 | 
							intel_dp->mst_mgr.cbs = NULL;
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -164,6 +164,9 @@ static unsigned int tile_row_pages(const struct drm_i915_gem_object *obj)
 | 
				
			||||||
 * 4 - Support multiple fault handlers per object depending on object's
 | 
					 * 4 - Support multiple fault handlers per object depending on object's
 | 
				
			||||||
 *     backing storage (a.k.a. MMAP_OFFSET).
 | 
					 *     backing storage (a.k.a. MMAP_OFFSET).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * 5 - Support multiple partial mmaps(mmap part of BO + unmap a offset, multiple
 | 
				
			||||||
 | 
					 *     times with different size and offset).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * Restrictions:
 | 
					 * Restrictions:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *  * snoopable objects cannot be accessed via the GTT. It can cause machine
 | 
					 *  * snoopable objects cannot be accessed via the GTT. It can cause machine
 | 
				
			||||||
| 
						 | 
					@ -191,7 +194,7 @@ static unsigned int tile_row_pages(const struct drm_i915_gem_object *obj)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int i915_gem_mmap_gtt_version(void)
 | 
					int i915_gem_mmap_gtt_version(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 4;
 | 
						return 5;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline struct i915_gtt_view
 | 
					static inline struct i915_gtt_view
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -527,8 +527,10 @@ pvr_meta_vm_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
pvr_meta_vm_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 | 
					pvr_meta_vm_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	pvr_vm_unmap(pvr_dev->kernel_vm_ctx, fw_obj->fw_mm_node.start,
 | 
						struct pvr_gem_object *pvr_obj = fw_obj->gem;
 | 
				
			||||||
		     fw_obj->fw_mm_node.size);
 | 
					
 | 
				
			||||||
 | 
						pvr_vm_unmap_obj(pvr_dev->kernel_vm_ctx, pvr_obj,
 | 
				
			||||||
 | 
								 fw_obj->fw_mm_node.start, fw_obj->fw_mm_node.size);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool
 | 
					static bool
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -333,8 +333,8 @@ static int fw_trace_seq_show(struct seq_file *s, void *v)
 | 
				
			||||||
	if (sf_id == ROGUE_FW_SF_LAST)
 | 
						if (sf_id == ROGUE_FW_SF_LAST)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	timestamp = read_fw_trace(trace_seq_data, 1) |
 | 
						timestamp = ((u64)read_fw_trace(trace_seq_data, 1) << 32) |
 | 
				
			||||||
		((u64)read_fw_trace(trace_seq_data, 2) << 32);
 | 
							read_fw_trace(trace_seq_data, 2);
 | 
				
			||||||
	timestamp = (timestamp & ~ROGUE_FWT_TIMESTAMP_TIME_CLRMSK) >>
 | 
						timestamp = (timestamp & ~ROGUE_FWT_TIMESTAMP_TIME_CLRMSK) >>
 | 
				
			||||||
		ROGUE_FWT_TIMESTAMP_TIME_SHIFT;
 | 
							ROGUE_FWT_TIMESTAMP_TIME_SHIFT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,12 +109,20 @@ pvr_queue_fence_get_driver_name(struct dma_fence *f)
 | 
				
			||||||
	return PVR_DRIVER_NAME;
 | 
						return PVR_DRIVER_NAME;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void pvr_queue_fence_release_work(struct work_struct *w)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct pvr_queue_fence *fence = container_of(w, struct pvr_queue_fence, release_work);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pvr_context_put(fence->queue->ctx);
 | 
				
			||||||
 | 
						dma_fence_free(&fence->base);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pvr_queue_fence_release(struct dma_fence *f)
 | 
					static void pvr_queue_fence_release(struct dma_fence *f)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pvr_queue_fence *fence = container_of(f, struct pvr_queue_fence, base);
 | 
						struct pvr_queue_fence *fence = container_of(f, struct pvr_queue_fence, base);
 | 
				
			||||||
 | 
						struct pvr_device *pvr_dev = fence->queue->ctx->pvr_dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pvr_context_put(fence->queue->ctx);
 | 
						queue_work(pvr_dev->sched_wq, &fence->release_work);
 | 
				
			||||||
	dma_fence_free(f);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *
 | 
					static const char *
 | 
				
			||||||
| 
						 | 
					@ -268,6 +276,7 @@ pvr_queue_fence_init(struct dma_fence *f,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pvr_context_get(queue->ctx);
 | 
						pvr_context_get(queue->ctx);
 | 
				
			||||||
	fence->queue = queue;
 | 
						fence->queue = queue;
 | 
				
			||||||
 | 
						INIT_WORK(&fence->release_work, pvr_queue_fence_release_work);
 | 
				
			||||||
	dma_fence_init(&fence->base, fence_ops,
 | 
						dma_fence_init(&fence->base, fence_ops,
 | 
				
			||||||
		       &fence_ctx->lock, fence_ctx->id,
 | 
							       &fence_ctx->lock, fence_ctx->id,
 | 
				
			||||||
		       atomic_inc_return(&fence_ctx->seqno));
 | 
							       atomic_inc_return(&fence_ctx->seqno));
 | 
				
			||||||
| 
						 | 
					@ -304,6 +313,7 @@ pvr_queue_cccb_fence_init(struct dma_fence *fence, struct pvr_queue *queue)
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
pvr_queue_job_fence_init(struct dma_fence *fence, struct pvr_queue *queue)
 | 
					pvr_queue_job_fence_init(struct dma_fence *fence, struct pvr_queue *queue)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (!fence->ops)
 | 
				
			||||||
		pvr_queue_fence_init(fence, queue, &pvr_queue_job_fence_ops,
 | 
							pvr_queue_fence_init(fence, queue, &pvr_queue_job_fence_ops,
 | 
				
			||||||
				     &queue->job_fence_ctx);
 | 
									     &queue->job_fence_ctx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
		Reference in a new issue