From bd0ab337ff8638bcaeb9a199c2f8d31aec7e3f0c Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 16 Jan 2025 14:11:47 +0100 Subject: s390/vfio-ap: Fix indentation in vfio_ap_mdev_ioctl() Remove any extra indentation to improve the code's readability. Signed-off-by: Thorsten Blum Reviewed-by: Anthony Krowiak Link: https://lore.kernel.org/r/20250116131146.105439-2-thorsten.blum@linux.dev Signed-off-by: Alexander Gordeev Signed-off-by: Vasily Gorbik --- drivers/s390/crypto/vfio_ap_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index a52c2690933f..155e19aef5df 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c @@ -2199,8 +2199,8 @@ static ssize_t vfio_ap_mdev_ioctl(struct vfio_device *vdev, ret = vfio_ap_mdev_reset_queues(matrix_mdev); break; case VFIO_DEVICE_GET_IRQ_INFO: - ret = vfio_ap_get_irq_info(arg); - break; + ret = vfio_ap_get_irq_info(arg); + break; case VFIO_DEVICE_SET_IRQS: ret = vfio_ap_set_irqs(matrix_mdev, arg); break; -- cgit v1.2.3-59-g8ed1b From e83188e1b65df15442388c3b19c6b9a9cdc60b7c Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 31 Jan 2025 16:57:02 +0100 Subject: s390/cio: Remove outdated email address The linux390@de.ibm.com email address is outdated. It has been removed from the MAINTAINERS file nearly 10 years ago with commit 64776820b4ff ("s390: remove generic email address from maintainers file"); remove one of the last remaining occurrences. Acked-by: Peter Oberparleiter Reviewed-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- drivers/s390/cio/crw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/s390/cio/crw.c b/drivers/s390/cio/crw.c index 4916dd0a7eb1..3285ce636c5c 100644 --- a/drivers/s390/cio/crw.c +++ b/drivers/s390/cio/crw.c @@ -77,9 +77,8 @@ repeat: if (unlikely(chain > 1)) { struct crw tmp_crw; - printk(KERN_WARNING"%s: Code does not support more " - "than two chained crws; please report to " - "linux390@de.ibm.com!\n", __func__); + printk(KERN_WARNING "%s: Code does not support more than two chained crws\n", + __func__); ccode = stcrw(&tmp_crw); printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, " "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", -- cgit v1.2.3-59-g8ed1b From 92d03904b26d330b9a20f3abaa9cb78e6aba2265 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Mon, 17 Feb 2025 11:06:13 +0100 Subject: s390/vfio-ap: Make mdev_types not look like a fake flex array The vfio-ap driver and the vfio parent device provided by it (matrix_dev) support just a single mdev_type, and this is not likely to change any time soon. Despite that matrix_dev->mdev_types started out as a C99 flexible array presumably as a typo, and since the typo messed up the allocation, commit e2c8cee9f489 ("s390/vfio-ap: Fix memory allocation for mdev_types array") changed it to an array of size 1. And to make things worse mdev_types happens to be the last member of struct ap_matrix_dev. Now the problem with that is that before C99 the usual way to get something similar to a flexible array member was to use a trailing array of size 0 or 1. This is what I called fake flex array. For a while now the community is trying to get rid of fake flex arrays. And while mdev_types is not a fake flex array but an array of size one (to match the mdev interfaces nicer), it can easily be and was mistaken for a fake flex array. So, let us make mdev_types a pointer to struct mdev_type and pass in the address of that pointer as the 4th formal parameter of mdev_register_parent(). Signed-off-by: Halil Pasic Reviewed-by: Anthony Krowiak Reviewed-by: Matthew Rosato Reviewed-by: Eric Farman Tested-by: Anthony Krowiak Link: https://lore.kernel.org/r/20250217100614.3043620-2-pasic@linux.ibm.com Signed-off-by: Vasily Gorbik --- drivers/s390/crypto/vfio_ap_ops.c | 4 ++-- drivers/s390/crypto/vfio_ap_private.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index 155e19aef5df..4c6a6d91a13f 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c @@ -2316,10 +2316,10 @@ int vfio_ap_mdev_register(void) matrix_dev->mdev_type.sysfs_name = VFIO_AP_MDEV_TYPE_HWVIRT; matrix_dev->mdev_type.pretty_name = VFIO_AP_MDEV_NAME_HWVIRT; - matrix_dev->mdev_types[0] = &matrix_dev->mdev_type; + matrix_dev->mdev_types = &matrix_dev->mdev_type; ret = mdev_register_parent(&matrix_dev->parent, &matrix_dev->device, &vfio_ap_matrix_driver, - matrix_dev->mdev_types, 1); + &matrix_dev->mdev_types, 1); if (ret) goto err_driver; return 0; diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h index 437a161c8659..9d16321777c8 100644 --- a/drivers/s390/crypto/vfio_ap_private.h +++ b/drivers/s390/crypto/vfio_ap_private.h @@ -53,7 +53,7 @@ struct ap_matrix_dev { struct mutex guests_lock; /* serializes access to each KVM guest */ struct mdev_parent parent; struct mdev_type mdev_type; - struct mdev_type *mdev_types[1]; + struct mdev_type *mdev_types; }; extern struct ap_matrix_dev *matrix_dev; -- cgit v1.2.3-59-g8ed1b From fd0c8b337579bd6720af4e07b2de3a01f58c608c Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Mon, 17 Feb 2025 11:06:14 +0100 Subject: s390/vfio-ccw: Make mdev_types not look like a fake flex array The vfio-ccw driver and the vfio parent device provided by it (parent) support just a single mdev_type, and this is not likely to change any time soon. To match the mdev interfaces nicely initially the choice was made that mdev_types (which gets passed into mdev_register_parent()) shall be an array of pointers to struct mdev_type with a single element, and to make things worse it ended up being the last member. Now the problem with that is that before C99 the usual way to get something similar to a flexible array member was to use a trailing array of size 0 or 1. This is what I called fake flex array. For a while now the community is trying to get rid of fake flex arrays. And while mdev_types was not a fake flex array but an array of size one, because it can easily be and probably was mistaken for a fake flex array it got converted into a real C99 flex array with a compile time known constant size of one. As per [1] it was established that "only fake flexible arrays should be transformed into C99 flex-array members". Since IMHO the entire point of flex arrays is being flexible about the array size at run time, a C99 flex array is a poor fit for mdev_types. But an array of a size one is a poor fit as well for the reason stated above, let us try to get rid of the flex array without introducing back the one sized array. So, lets make mdev_types a pointer to struct mdev_type and pass in the address of that pointer as the 4th formal parameter of mdev_register_parent(). [1] https://lore.kernel.org/lkml/85863d7a-2d8b-4c1b-b76a-e2f40834a7a8@embeddedor.com/ Signed-off-by: Halil Pasic Reviewed-by: Matthew Rosato Tested-by: Eric Farman Link: https://lore.kernel.org/r/20250217100614.3043620-3-pasic@linux.ibm.com Signed-off-by: Vasily Gorbik --- drivers/s390/cio/vfio_ccw_drv.c | 6 +++--- drivers/s390/cio/vfio_ccw_private.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 914dde041675..6ff5c9cfb7ed 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -171,7 +171,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) return -ENODEV; } - parent = kzalloc(struct_size(parent, mdev_types, 1), GFP_KERNEL); + parent = kzalloc(sizeof(*parent), GFP_KERNEL); if (!parent) return -ENOMEM; @@ -186,10 +186,10 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) parent->mdev_type.sysfs_name = "io"; parent->mdev_type.pretty_name = "I/O subchannel (Non-QDIO)"; - parent->mdev_types[0] = &parent->mdev_type; + parent->mdev_types = &parent->mdev_type; ret = mdev_register_parent(&parent->parent, &sch->dev, &vfio_ccw_mdev_driver, - parent->mdev_types, 1); + &parent->mdev_types, 1); if (ret) goto out_unreg; diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h index b62bbc5c6376..0501d4bbcdbd 100644 --- a/drivers/s390/cio/vfio_ccw_private.h +++ b/drivers/s390/cio/vfio_ccw_private.h @@ -79,7 +79,7 @@ struct vfio_ccw_parent { struct mdev_parent parent; struct mdev_type mdev_type; - struct mdev_type *mdev_types[]; + struct mdev_type *mdev_types; }; /** -- cgit v1.2.3-59-g8ed1b From 07d89045bffea30ef08b902c2441a3329e44f29d Mon Sep 17 00:00:00 2001 From: Rorie Reyes Date: Tue, 7 Jan 2025 13:36:45 -0500 Subject: s390/vfio-ap: Signal eventfd when guest AP configuration is changed In this patch, an eventfd object is created by the vfio_ap device driver and used to notify userspace when a guests's AP configuration is dynamically changed. Such changes may occur whenever: * An adapter, domain or control domain is assigned to or unassigned from a mediated device that is attached to the guest. * A queue assigned to the mediated device that is attached to a guest is bound to or unbound from the vfio_ap device driver. This can occur either by manually binding/unbinding the queue via the vfio_ap driver's sysfs bind/unbind attribute interfaces, or because an adapter, domain or control domain assigned to the mediated device is added to or removed from the host's AP configuration via an SE/HMC The purpose of this patch is to provide immediate notification of changes made to a guest's AP configuration by the vfio_ap driver. This will enable the guest to take immediate action rather than relying on polling or some other inefficient mechanism to detect changes to its AP configuration. Note that there are corresponding QEMU patches that will be shipped along with this patch (see vfio-ap: Report vfio-ap configuration changes) that will pick up the eventfd signal. Signed-off-by: Rorie Reyes Reviewed-by: Anthony Krowiak Tested-by: Anthony Krowiak Link: https://lore.kernel.org/r/20250107183645.90082-1-rreyes@linux.ibm.com Signed-off-by: Vasily Gorbik --- drivers/s390/crypto/vfio_ap_ops.c | 52 ++++++++++++++++++++++++++++++++++- drivers/s390/crypto/vfio_ap_private.h | 2 ++ include/uapi/linux/vfio.h | 1 + 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index 4c6a6d91a13f..571f5dcb49c5 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c @@ -650,13 +650,22 @@ static void vfio_ap_matrix_init(struct ap_config_info *info, matrix->adm_max = info->apxa ? info->nd : 15; } +static void signal_guest_ap_cfg_changed(struct ap_matrix_mdev *matrix_mdev) +{ + if (matrix_mdev->cfg_chg_trigger) + eventfd_signal(matrix_mdev->cfg_chg_trigger); +} + static void vfio_ap_mdev_update_guest_apcb(struct ap_matrix_mdev *matrix_mdev) { - if (matrix_mdev->kvm) + if (matrix_mdev->kvm) { kvm_arch_crypto_set_masks(matrix_mdev->kvm, matrix_mdev->shadow_apcb.apm, matrix_mdev->shadow_apcb.aqm, matrix_mdev->shadow_apcb.adm); + + signal_guest_ap_cfg_changed(matrix_mdev); + } } static bool vfio_ap_mdev_filter_cdoms(struct ap_matrix_mdev *matrix_mdev) @@ -792,6 +801,7 @@ static int vfio_ap_mdev_probe(struct mdev_device *mdev) if (ret) goto err_put_vdev; matrix_mdev->req_trigger = NULL; + matrix_mdev->cfg_chg_trigger = NULL; dev_set_drvdata(&mdev->dev, matrix_mdev); mutex_lock(&matrix_dev->mdevs_lock); list_add(&matrix_mdev->node, &matrix_dev->mdev_list); @@ -1860,6 +1870,7 @@ static void vfio_ap_mdev_unset_kvm(struct ap_matrix_mdev *matrix_mdev) get_update_locks_for_kvm(kvm); kvm_arch_crypto_clear_masks(kvm); + signal_guest_ap_cfg_changed(matrix_mdev); vfio_ap_mdev_reset_queues(matrix_mdev); kvm_put_kvm(kvm); matrix_mdev->kvm = NULL; @@ -2097,6 +2108,10 @@ static ssize_t vfio_ap_get_irq_info(unsigned long arg) info.count = 1; info.flags = VFIO_IRQ_INFO_EVENTFD; break; + case VFIO_AP_CFG_CHG_IRQ_INDEX: + info.count = 1; + info.flags = VFIO_IRQ_INFO_EVENTFD; + break; default: return -EINVAL; } @@ -2160,6 +2175,39 @@ static int vfio_ap_set_request_irq(struct ap_matrix_mdev *matrix_mdev, return 0; } +static int vfio_ap_set_cfg_change_irq(struct ap_matrix_mdev *matrix_mdev, unsigned long arg) +{ + s32 fd; + void __user *data; + unsigned long minsz; + struct eventfd_ctx *cfg_chg_trigger; + + minsz = offsetofend(struct vfio_irq_set, count); + data = (void __user *)(arg + minsz); + + if (get_user(fd, (s32 __user *)data)) + return -EFAULT; + + if (fd == -1) { + if (matrix_mdev->cfg_chg_trigger) + eventfd_ctx_put(matrix_mdev->cfg_chg_trigger); + matrix_mdev->cfg_chg_trigger = NULL; + } else if (fd >= 0) { + cfg_chg_trigger = eventfd_ctx_fdget(fd); + if (IS_ERR(cfg_chg_trigger)) + return PTR_ERR(cfg_chg_trigger); + + if (matrix_mdev->cfg_chg_trigger) + eventfd_ctx_put(matrix_mdev->cfg_chg_trigger); + + matrix_mdev->cfg_chg_trigger = cfg_chg_trigger; + } else { + return -EINVAL; + } + + return 0; +} + static int vfio_ap_set_irqs(struct ap_matrix_mdev *matrix_mdev, unsigned long arg) { @@ -2175,6 +2223,8 @@ static int vfio_ap_set_irqs(struct ap_matrix_mdev *matrix_mdev, switch (irq_set.index) { case VFIO_AP_REQ_IRQ_INDEX: return vfio_ap_set_request_irq(matrix_mdev, arg); + case VFIO_AP_CFG_CHG_IRQ_INDEX: + return vfio_ap_set_cfg_change_irq(matrix_mdev, arg); default: return -EINVAL; } diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h index 9d16321777c8..9bff666b0b35 100644 --- a/drivers/s390/crypto/vfio_ap_private.h +++ b/drivers/s390/crypto/vfio_ap_private.h @@ -105,6 +105,7 @@ struct ap_queue_table { * @mdev: the mediated device * @qtable: table of queues (struct vfio_ap_queue) assigned to the mdev * @req_trigger eventfd ctx for signaling userspace to return a device + * @cfg_chg_trigger eventfd ctx to signal AP config changed to userspace * @apm_add: bitmap of APIDs added to the host's AP configuration * @aqm_add: bitmap of APQIs added to the host's AP configuration * @adm_add: bitmap of control domain numbers added to the host's AP @@ -120,6 +121,7 @@ struct ap_matrix_mdev { struct mdev_device *mdev; struct ap_queue_table qtable; struct eventfd_ctx *req_trigger; + struct eventfd_ctx *cfg_chg_trigger; DECLARE_BITMAP(apm_add, AP_DEVICES); DECLARE_BITMAP(aqm_add, AP_DOMAINS); DECLARE_BITMAP(adm_add, AP_DOMAINS); diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index c8dbf8219c4f..a2d3e1ac6239 100644 --- a/include/uapi/linux/vfio.h +++ b/include/uapi/linux/vfio.h @@ -671,6 +671,7 @@ enum { */ enum { VFIO_AP_REQ_IRQ_INDEX, + VFIO_AP_CFG_CHG_IRQ_INDEX, VFIO_AP_NUM_IRQS }; -- cgit v1.2.3-59-g8ed1b From fa1518875286c94111bdaf1c7bae188c9c426c6b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 13 Feb 2025 13:57:33 +0100 Subject: s390: Sort mcount locations at build time For s390 the mcount_loc section of the kernel image contains the addresses of the mcount locations. All addresses will be adjusted with the same offset by the decompressor before the kernel is started. Therefore select HAVE_BUILDTIME_MCOUNT_SORT so that the entries of this section are sorted at build time. Given that the same offset is applied to all entries the section will be sorted in any case. Note that this was not possible before commit 778666df60f0 ("s390: compile relocatable kernel without -fPIE"). Since this commit all R_390_64 absolute relocations are handled in a special way: only the address of the to be changed location is put into a special section. For all those locations the same offset is applied as described above. Without that change it would have been necessary to also adjust the addend of all relocations which correspond to the mcount_loc section, when sorting the mcount_loc section. Reported-by: Steven Rostedt Closes: https://lore.kernel.org/r/20250210142647.083ff456@gandalf.local.home/ Signed-off-by: Heiko Carstens Acked-by: Vasily Gorbik Signed-off-by: Vasily Gorbik --- arch/s390/Kconfig | 1 + arch/s390/configs/debug_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 9c9ec08d78c7..acaa1d1c12b2 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -185,6 +185,7 @@ config S390 select HAVE_ARCH_TRANSPARENT_HUGEPAGE select HAVE_ARCH_VMAP_STACK select HAVE_ASM_MODVERSIONS + select HAVE_BUILDTIME_MCOUNT_SORT select HAVE_CMPXCHG_DOUBLE select HAVE_CMPXCHG_LOCAL select HAVE_DEBUG_KMEMLEAK diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index d6beec5292a0..a2b0444b7d6b 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -887,6 +887,7 @@ CONFIG_USER_EVENTS=y CONFIG_HIST_TRIGGERS=y CONFIG_FTRACE_STARTUP_TEST=y # CONFIG_EVENT_TRACE_STARTUP_TEST is not set +CONFIG_FTRACE_SORT_STARTUP_TEST=y CONFIG_SAMPLES=y CONFIG_SAMPLE_TRACE_PRINTK=m CONFIG_SAMPLE_FTRACE_DIRECT=m -- cgit v1.2.3-59-g8ed1b From fb5bbcdcc3eabd8e9061eac7c3223e3de640adfa Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 31 Jan 2025 16:11:38 +0100 Subject: s390/mm: Remove have_store_indication static key Whenever test_facility() is used with a constant facility number the generated code is identical to a static branch. Remove the extra initcall and static_branch_enable() handling for have_store_indication, and use test_facility() directly. Acked-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/mm/fault.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 9b681f74dccc..9c9d7840cb57 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -46,16 +45,6 @@ #include #include "../kernel/entry.h" -static DEFINE_STATIC_KEY_FALSE(have_store_indication); - -static int __init fault_init(void) -{ - if (test_facility(75)) - static_branch_enable(&have_store_indication); - return 0; -} -early_initcall(fault_init); - /* * Find out which address space caused the exception. */ @@ -81,7 +70,7 @@ static __always_inline bool fault_is_write(struct pt_regs *regs) { union teid teid = { .val = regs->int_parm_long }; - if (static_branch_likely(&have_store_indication)) + if (test_facility(75)) return teid.fsi == TEID_FSI_STORE; return false; } -- cgit v1.2.3-59-g8ed1b From c488f5187a24969b40fd08c3e9ead377c0cfb9b3 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 11 Feb 2025 20:19:26 +0100 Subject: s390/uaccess: Shorten raw_copy_from_user() / raw_copy_to_user() inline assemblies Add specific exception handler for copy_to_user() / copy_from_user() mvcos fault handling, which allows to shorten the inline assemblies to three instructions. On fault the exception handler adjusts the length used by the mvcos instruction in a way that the instruction completes with condition code zero, indicating the number of bytes copied with the input/output operand 'size'. This allows to calculate and return the number of bytes not copied, if any, like required. Loop and return value handling is changed to C so that the compiler may optimize the code. Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/asm-extable.h | 8 +++ arch/s390/include/asm/uaccess.h | 114 ++++++++++++++++-------------------- arch/s390/mm/extable.c | 47 +++++++++++++++ 3 files changed, 105 insertions(+), 64 deletions(-) diff --git a/arch/s390/include/asm/asm-extable.h b/arch/s390/include/asm/asm-extable.h index 2e829c16fd8a..d23ea0c94e4e 100644 --- a/arch/s390/include/asm/asm-extable.h +++ b/arch/s390/include/asm/asm-extable.h @@ -14,6 +14,8 @@ #define EX_TYPE_UA_LOAD_REGPAIR 6 #define EX_TYPE_ZEROPAD 7 #define EX_TYPE_FPC 8 +#define EX_TYPE_UA_MVCOS_TO 9 +#define EX_TYPE_UA_MVCOS_FROM 10 #define EX_DATA_REG_ERR_SHIFT 0 #define EX_DATA_REG_ERR GENMASK(3, 0) @@ -84,4 +86,10 @@ #define EX_TABLE_FPC(_fault, _target) \ __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_FPC, __stringify(%%r0), __stringify(%%r0), 0) +#define EX_TABLE_UA_MVCOS_TO(_fault, _target) \ + __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_MVCOS_TO, __stringify(%%r0), __stringify(%%r0), 0) + +#define EX_TABLE_UA_MVCOS_FROM(_fault, _target) \ + __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_MVCOS_FROM, __stringify(%%r0), __stringify(%%r0), 0) + #endif /* __ASM_EXTABLE_H */ diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index f5920163ee97..f9ace938743c 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -44,43 +44,42 @@ union oac { }; }; -static __always_inline __must_check unsigned long +#ifdef CONFIG_KMSAN +#define uaccess_kmsan_or_inline noinline __maybe_unused __no_sanitize_memory +#else +#define uaccess_kmsan_or_inline __always_inline +#endif + +static uaccess_kmsan_or_inline __must_check unsigned long raw_copy_from_user_key(void *to, const void __user *from, unsigned long size, unsigned long key) { - unsigned long rem; + unsigned long osize; union oac spec = { .oac2.key = key, .oac2.as = PSW_BITS_AS_SECONDARY, .oac2.k = 1, .oac2.a = 1, }; - - asm_inline volatile( - " lr %%r0,%[spec]\n" - "0: mvcos 0(%[to]),0(%[from]),%[size]\n" - "1: jz 5f\n" - " algr %[size],%[val]\n" - " slgr %[from],%[val]\n" - " slgr %[to],%[val]\n" - " j 0b\n" - "2: la %[rem],4095(%[from])\n" /* rem = from + 4095 */ - " nr %[rem],%[val]\n" /* rem = (from + 4095) & -4096 */ - " slgr %[rem],%[from]\n" - " clgr %[size],%[rem]\n" /* copy crosses next page boundary? */ - " jnh 6f\n" - "3: mvcos 0(%[to]),0(%[from]),%[rem]\n" - "4: slgr %[size],%[rem]\n" - " j 6f\n" - "5: lghi %[size],0\n" - "6:\n" - EX_TABLE(0b, 2b) - EX_TABLE(1b, 2b) - EX_TABLE(3b, 6b) - EX_TABLE(4b, 6b) - : [size] "+&a" (size), [from] "+&a" (from), [to] "+&a" (to), [rem] "=&a" (rem) - : [val] "a" (-4096UL), [spec] "d" (spec.val) - : "cc", "memory", "0"); - return size; + int cc; + + while (1) { + osize = size; + asm_inline volatile( + " lr %%r0,%[spec]\n" + "0: mvcos %[to],%[from],%[size]\n" + "1: nopr %%r7\n" + CC_IPM(cc) + EX_TABLE_UA_MVCOS_FROM(0b, 0b) + EX_TABLE_UA_MVCOS_FROM(1b, 0b) + : CC_OUT(cc, cc), [size] "+d" (size), [to] "=Q" (*(char *)to) + : [spec] "d" (spec.val), [from] "Q" (*(const char __user *)from) + : CC_CLOBBER_LIST("memory", "0")); + if (likely(CC_TRANSFORM(cc) == 0)) + return osize - size; + size -= 4096; + to += 4096; + from += 4096; + } } static __always_inline __must_check unsigned long @@ -89,43 +88,36 @@ raw_copy_from_user(void *to, const void __user *from, unsigned long n) return raw_copy_from_user_key(to, from, n, 0); } -static __always_inline __must_check unsigned long +static uaccess_kmsan_or_inline __must_check unsigned long raw_copy_to_user_key(void __user *to, const void *from, unsigned long size, unsigned long key) { - unsigned long rem; + unsigned long osize; union oac spec = { .oac1.key = key, .oac1.as = PSW_BITS_AS_SECONDARY, .oac1.k = 1, .oac1.a = 1, }; - - asm_inline volatile( - " lr %%r0,%[spec]\n" - "0: mvcos 0(%[to]),0(%[from]),%[size]\n" - "1: jz 5f\n" - " algr %[size],%[val]\n" - " slgr %[to],%[val]\n" - " slgr %[from],%[val]\n" - " j 0b\n" - "2: la %[rem],4095(%[to])\n" /* rem = to + 4095 */ - " nr %[rem],%[val]\n" /* rem = (to + 4095) & -4096 */ - " slgr %[rem],%[to]\n" - " clgr %[size],%[rem]\n" /* copy crosses next page boundary? */ - " jnh 6f\n" - "3: mvcos 0(%[to]),0(%[from]),%[rem]\n" - "4: slgr %[size],%[rem]\n" - " j 6f\n" - "5: lghi %[size],0\n" - "6:\n" - EX_TABLE(0b, 2b) - EX_TABLE(1b, 2b) - EX_TABLE(3b, 6b) - EX_TABLE(4b, 6b) - : [size] "+&a" (size), [to] "+&a" (to), [from] "+&a" (from), [rem] "=&a" (rem) - : [val] "a" (-4096UL), [spec] "d" (spec.val) - : "cc", "memory", "0"); - return size; + int cc; + + while (1) { + osize = size; + asm_inline volatile( + " lr %%r0,%[spec]\n" + "0: mvcos %[to],%[from],%[size]\n" + "1: nopr %%r7\n" + CC_IPM(cc) + EX_TABLE_UA_MVCOS_TO(0b, 0b) + EX_TABLE_UA_MVCOS_TO(1b, 0b) + : CC_OUT(cc, cc), [size] "+d" (size), [to] "=Q" (*(char __user *)to) + : [spec] "d" (spec.val), [from] "Q" (*(const char *)from) + : CC_CLOBBER_LIST("memory", "0")); + if (likely(CC_TRANSFORM(cc) == 0)) + return osize - size; + size -= 4096; + to += 4096; + from += 4096; + } } static __always_inline __must_check unsigned long @@ -158,12 +150,6 @@ copy_to_user_key(void __user *to, const void *from, unsigned long n, unsigned lo int __noreturn __put_user_bad(void); -#ifdef CONFIG_KMSAN -#define uaccess_kmsan_or_inline noinline __maybe_unused __no_sanitize_memory -#else -#define uaccess_kmsan_or_inline __always_inline -#endif - #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT #define DEFINE_PUT_USER_NOINSTR(type) \ diff --git a/arch/s390/mm/extable.c b/arch/s390/mm/extable.c index a046be1715cf..7498e858c401 100644 --- a/arch/s390/mm/extable.c +++ b/arch/s390/mm/extable.c @@ -73,6 +73,49 @@ static bool ex_handler_fpc(const struct exception_table_entry *ex, struct pt_reg return true; } +struct insn_ssf { + u64 opc1 : 8; + u64 r3 : 4; + u64 opc2 : 4; + u64 b1 : 4; + u64 d1 : 12; + u64 b2 : 4; + u64 d2 : 12; +} __packed; + +static bool ex_handler_ua_mvcos(const struct exception_table_entry *ex, + bool from, struct pt_regs *regs) +{ + unsigned long uaddr, remainder; + struct insn_ssf *insn; + + /* + * If the faulting user space access crossed a page boundary retry by + * limiting the access to the first page (adjust length accordingly). + * Then the mvcos instruction will either complete with condition code + * zero, or generate another fault where the user space access did not + * cross a page boundary. + * If the faulting user space access did not cross a page boundary set + * length to zero and retry. In this case no user space access will + * happen, and the mvcos instruction will complete with condition code + * zero. + * In both cases the instruction will complete with condition code + * zero (copying finished), and the register which contains the + * length, indicates the number of bytes copied. + */ + regs->psw.addr = extable_fixup(ex); + insn = (struct insn_ssf *)regs->psw.addr; + if (from) + uaddr = regs->gprs[insn->b2] + insn->d2; + else + uaddr = regs->gprs[insn->b1] + insn->d1; + remainder = PAGE_SIZE - (uaddr & (PAGE_SIZE - 1)); + if (regs->gprs[insn->r3] <= remainder) + remainder = 0; + regs->gprs[insn->r3] = remainder; + return true; +} + bool fixup_exception(struct pt_regs *regs) { const struct exception_table_entry *ex; @@ -95,6 +138,10 @@ bool fixup_exception(struct pt_regs *regs) return ex_handler_zeropad(ex, regs); case EX_TYPE_FPC: return ex_handler_fpc(ex, regs); + case EX_TYPE_UA_MVCOS_TO: + return ex_handler_ua_mvcos(ex, false, regs); + case EX_TYPE_UA_MVCOS_FROM: + return ex_handler_ua_mvcos(ex, true, regs); } panic("invalid exception table entry"); } -- cgit v1.2.3-59-g8ed1b From bc6029239c11df78433c2085d8c9ee0e1109dfd2 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 11 Feb 2025 20:19:27 +0100 Subject: s390/uaccess: Separate key uaccess functions Implement separate raw_copy_to_user_key() and raw_copy_from_user_key() functions, which allows to remove the open-coded operand access control handling from the normal raw_copy_to_user() / raw_copy_from_user() functions - they are simplified to use immediate instructions to load hard-coded operand access control values into register zero, which saves one instruction. Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/uaccess.h | 58 +++------------------------ arch/s390/lib/uaccess.c | 86 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 52 deletions(-) diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index f9ace938743c..87833f50fa52 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -22,28 +22,6 @@ void debug_user_asce(int exit); -union oac { - unsigned int val; - struct { - struct { - unsigned short key : 4; - unsigned short : 4; - unsigned short as : 2; - unsigned short : 4; - unsigned short k : 1; - unsigned short a : 1; - } oac1; - struct { - unsigned short key : 4; - unsigned short : 4; - unsigned short as : 2; - unsigned short : 4; - unsigned short k : 1; - unsigned short a : 1; - } oac2; - }; -}; - #ifdef CONFIG_KMSAN #define uaccess_kmsan_or_inline noinline __maybe_unused __no_sanitize_memory #else @@ -51,28 +29,22 @@ union oac { #endif static uaccess_kmsan_or_inline __must_check unsigned long -raw_copy_from_user_key(void *to, const void __user *from, unsigned long size, unsigned long key) +raw_copy_from_user(void *to, const void __user *from, unsigned long size) { unsigned long osize; - union oac spec = { - .oac2.key = key, - .oac2.as = PSW_BITS_AS_SECONDARY, - .oac2.k = 1, - .oac2.a = 1, - }; int cc; while (1) { osize = size; asm_inline volatile( - " lr %%r0,%[spec]\n" + " lhi %%r0,%[spec]\n" "0: mvcos %[to],%[from],%[size]\n" "1: nopr %%r7\n" CC_IPM(cc) EX_TABLE_UA_MVCOS_FROM(0b, 0b) EX_TABLE_UA_MVCOS_FROM(1b, 0b) : CC_OUT(cc, cc), [size] "+d" (size), [to] "=Q" (*(char *)to) - : [spec] "d" (spec.val), [from] "Q" (*(const char __user *)from) + : [spec] "I" (0x81), [from] "Q" (*(const char __user *)from) : CC_CLOBBER_LIST("memory", "0")); if (likely(CC_TRANSFORM(cc) == 0)) return osize - size; @@ -82,35 +54,23 @@ raw_copy_from_user_key(void *to, const void __user *from, unsigned long size, un } } -static __always_inline __must_check unsigned long -raw_copy_from_user(void *to, const void __user *from, unsigned long n) -{ - return raw_copy_from_user_key(to, from, n, 0); -} - static uaccess_kmsan_or_inline __must_check unsigned long -raw_copy_to_user_key(void __user *to, const void *from, unsigned long size, unsigned long key) +raw_copy_to_user(void __user *to, const void *from, unsigned long size) { unsigned long osize; - union oac spec = { - .oac1.key = key, - .oac1.as = PSW_BITS_AS_SECONDARY, - .oac1.k = 1, - .oac1.a = 1, - }; int cc; while (1) { osize = size; asm_inline volatile( - " lr %%r0,%[spec]\n" + " llilh %%r0,%[spec]\n" "0: mvcos %[to],%[from],%[size]\n" "1: nopr %%r7\n" CC_IPM(cc) EX_TABLE_UA_MVCOS_TO(0b, 0b) EX_TABLE_UA_MVCOS_TO(1b, 0b) : CC_OUT(cc, cc), [size] "+d" (size), [to] "=Q" (*(char __user *)to) - : [spec] "d" (spec.val), [from] "Q" (*(const char *)from) + : [spec] "I" (0x81), [from] "Q" (*(const char *)from) : CC_CLOBBER_LIST("memory", "0")); if (likely(CC_TRANSFORM(cc) == 0)) return osize - size; @@ -120,12 +80,6 @@ raw_copy_to_user_key(void __user *to, const void *from, unsigned long size, unsi } } -static __always_inline __must_check unsigned long -raw_copy_to_user(void __user *to, const void *from, unsigned long n) -{ - return raw_copy_to_user_key(to, from, n, 0); -} - unsigned long __must_check _copy_from_user_key(void *to, const void __user *from, unsigned long n, unsigned long key); diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c index f977b7c37efc..2c85068aebfe 100644 --- a/arch/s390/lib/uaccess.c +++ b/arch/s390/lib/uaccess.c @@ -31,6 +31,60 @@ void debug_user_asce(int exit) } #endif /*CONFIG_DEBUG_ENTRY */ +union oac { + unsigned int val; + struct { + struct { + unsigned short key : 4; + unsigned short : 4; + unsigned short as : 2; + unsigned short : 4; + unsigned short k : 1; + unsigned short a : 1; + } oac1; + struct { + unsigned short key : 4; + unsigned short : 4; + unsigned short as : 2; + unsigned short : 4; + unsigned short k : 1; + unsigned short a : 1; + } oac2; + }; +}; + +static uaccess_kmsan_or_inline __must_check unsigned long +raw_copy_from_user_key(void *to, const void __user *from, unsigned long size, unsigned long key) +{ + unsigned long osize; + union oac spec = { + .oac2.key = key, + .oac2.as = PSW_BITS_AS_SECONDARY, + .oac2.k = 1, + .oac2.a = 1, + }; + int cc; + + while (1) { + osize = size; + asm_inline volatile( + " lr %%r0,%[spec]\n" + "0: mvcos %[to],%[from],%[size]\n" + "1: nopr %%r7\n" + CC_IPM(cc) + EX_TABLE_UA_MVCOS_FROM(0b, 0b) + EX_TABLE_UA_MVCOS_FROM(1b, 0b) + : CC_OUT(cc, cc), [size] "+d" (size), [to] "=Q" (*(char *)to) + : [spec] "d" (spec.val), [from] "Q" (*(const char __user *)from) + : CC_CLOBBER_LIST("memory", "0")); + if (CC_TRANSFORM(cc) == 0) + return osize - size; + size -= 4096; + to += 4096; + from += 4096; + } +} + unsigned long _copy_from_user_key(void *to, const void __user *from, unsigned long n, unsigned long key) { @@ -48,6 +102,38 @@ unsigned long _copy_from_user_key(void *to, const void __user *from, } EXPORT_SYMBOL(_copy_from_user_key); +static uaccess_kmsan_or_inline __must_check unsigned long +raw_copy_to_user_key(void __user *to, const void *from, unsigned long size, unsigned long key) +{ + unsigned long osize; + union oac spec = { + .oac1.key = key, + .oac1.as = PSW_BITS_AS_SECONDARY, + .oac1.k = 1, + .oac1.a = 1, + }; + int cc; + + while (1) { + osize = size; + asm_inline volatile( + " lr %%r0,%[spec]\n" + "0: mvcos %[to],%[from],%[size]\n" + "1: nopr %%r7\n" + CC_IPM(cc) + EX_TABLE_UA_MVCOS_TO(0b, 0b) + EX_TABLE_UA_MVCOS_TO(1b, 0b) + : CC_OUT(cc, cc), [size] "+d" (size), [to] "=Q" (*(char __user *)to) + : [spec] "d" (spec.val), [from] "Q" (*(const char *)from) + : CC_CLOBBER_LIST("memory", "0")); + if (CC_TRANSFORM(cc) == 0) + return osize - size; + size -= 4096; + to += 4096; + from += 4096; + } +} + unsigned long _copy_to_user_key(void __user *to, const void *from, unsigned long n, unsigned long key) { -- cgit v1.2.3-59-g8ed1b From 10a79b6fdd1a4ead85d270bfa3ae0b7bb83020cf Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 11 Feb 2025 20:19:28 +0100 Subject: s390/uaccess: Define INLINE_COPY_FROM_USER and INLINE_COPY_TO_USER Inline copy_from_user() and copy_to_user(). With the shortened inline assemblies of raw_copy_to_user() and raw_copy_from_user() the additional kernel text size is acceptable, considering that this avoids function calls on hot paths. This increases the kernel text size by ~90kb (defconfig, gcc 14.2.0): add/remove: 13/4 grow/shrink: 650/14 up/down: 93484/-3254 (90230) Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/uaccess.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 87833f50fa52..333a2afc0d6f 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -28,6 +28,9 @@ void debug_user_asce(int exit); #define uaccess_kmsan_or_inline __always_inline #endif +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER + static uaccess_kmsan_or_inline __must_check unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long size) { -- cgit v1.2.3-59-g8ed1b From 88e87cb7b8f8afcf1776d5b8a3ddd17fe8d2a32f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 11 Feb 2025 20:19:29 +0100 Subject: s390/uaccess: Optimize raw_copy_from_user() / raw_copy_to_user() for constant sizes Avoid that the compiler generates an mvcos loop for constant sizes smaller than 4096 bytes. The mvcos instruction copies between zero and 4096 bytes (effective length) with one operation. Therefore it is not necessary to implement a loop for sizes smaller or equal to 4096 bytes. This reduces the kernel text size by ~50kb (defconfig, gcc 14.2.0): add/remove: 4/5 grow/shrink: 6/471 up/down: 2294/-51700 (-49406) Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/uaccess.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 333a2afc0d6f..b5712d690a93 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -49,6 +49,8 @@ raw_copy_from_user(void *to, const void __user *from, unsigned long size) : CC_OUT(cc, cc), [size] "+d" (size), [to] "=Q" (*(char *)to) : [spec] "I" (0x81), [from] "Q" (*(const char __user *)from) : CC_CLOBBER_LIST("memory", "0")); + if (__builtin_constant_p(osize) && osize <= 4096) + return osize - size; if (likely(CC_TRANSFORM(cc) == 0)) return osize - size; size -= 4096; @@ -75,6 +77,8 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long size) : CC_OUT(cc, cc), [size] "+d" (size), [to] "=Q" (*(char __user *)to) : [spec] "I" (0x81), [from] "Q" (*(const char *)from) : CC_CLOBBER_LIST("memory", "0")); + if (__builtin_constant_p(osize) && osize <= 4096) + return osize - size; if (likely(CC_TRANSFORM(cc) == 0)) return osize - size; size -= 4096; -- cgit v1.2.3-59-g8ed1b From ee487b0120fc0669ac5e454907c2d259a6da8f5e Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 11 Feb 2025 20:19:30 +0100 Subject: s390/uaccess: Inline __clear_user() Rework __clear_user() similar to raw_copy_from_user() / raw_copy_to_user() and inline the function saving the overhead of branches. Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/uaccess.h | 33 ++++++++++++++++++++++++++++----- arch/s390/lib/uaccess.c | 36 ------------------------------------ 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index b5712d690a93..f30ee6ddfece 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -13,6 +13,7 @@ /* * User space memory access functions */ +#include #include #include #include @@ -362,12 +363,34 @@ long __must_check strncpy_from_user(char *dst, const char __user *src, long coun long __must_check strnlen_user(const char __user *src, long count); -/* - * Zero Userspace - */ -unsigned long __must_check __clear_user(void __user *to, unsigned long size); +static uaccess_kmsan_or_inline __must_check unsigned long +__clear_user(void __user *to, unsigned long size) +{ + unsigned long osize; + int cc; + + while (1) { + osize = size; + asm_inline volatile( + " llilh %%r0,%[spec]\n" + "0: mvcos %[to],%[from],%[size]\n" + "1: nopr %%r7\n" + CC_IPM(cc) + EX_TABLE_UA_MVCOS_TO(0b, 0b) + EX_TABLE_UA_MVCOS_TO(1b, 0b) + : CC_OUT(cc, cc), [size] "+d" (size), [to] "=Q" (*(char __user *)to) + : [spec] "I" (0x81), [from] "Q" (*(const char *)empty_zero_page) + : CC_CLOBBER_LIST("memory", "0")); + if (__builtin_constant_p(osize) && osize <= 4096) + return osize - size; + if (CC_TRANSFORM(cc) == 0) + return osize - size; + size -= 4096; + to += 4096; + } +} -static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) +static __always_inline unsigned long __must_check clear_user(void __user *to, unsigned long n) { might_fault(); return __clear_user(to, n); diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c index 2c85068aebfe..cec20db88479 100644 --- a/arch/s390/lib/uaccess.c +++ b/arch/s390/lib/uaccess.c @@ -144,39 +144,3 @@ unsigned long _copy_to_user_key(void __user *to, const void *from, return raw_copy_to_user_key(to, from, n, key); } EXPORT_SYMBOL(_copy_to_user_key); - -unsigned long __clear_user(void __user *to, unsigned long size) -{ - unsigned long rem; - union oac spec = { - .oac1.as = PSW_BITS_AS_SECONDARY, - .oac1.a = 1, - }; - - asm volatile( - " lr 0,%[spec]\n" - "0: mvcos 0(%[to]),0(%[zeropg]),%[size]\n" - "1: jz 5f\n" - " algr %[size],%[val]\n" - " slgr %[to],%[val]\n" - " j 0b\n" - "2: la %[rem],4095(%[to])\n" /* rem = to + 4095 */ - " nr %[rem],%[val]\n" /* rem = (to + 4095) & -4096 */ - " slgr %[rem],%[to]\n" - " clgr %[size],%[rem]\n" /* copy crosses next page boundary? */ - " jnh 6f\n" - "3: mvcos 0(%[to]),0(%[zeropg]),%[rem]\n" - "4: slgr %[size],%[rem]\n" - " j 6f\n" - "5: slgr %[size],%[size]\n" - "6:\n" - EX_TABLE(0b, 2b) - EX_TABLE(1b, 2b) - EX_TABLE(3b, 6b) - EX_TABLE(4b, 6b) - : [size] "+&a" (size), [to] "+&a" (to), [rem] "=&a" (rem) - : [val] "a" (-4096UL), [zeropg] "a" (empty_zero_page), [spec] "d" (spec.val) - : "cc", "memory", "0"); - return size; -} -EXPORT_SYMBOL(__clear_user); -- cgit v1.2.3-59-g8ed1b From 4a66f273c3912e397005d9915d8c40340519dd53 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 4 Feb 2025 08:42:02 +0100 Subject: s390/zfcp: Remove outdated email address The linux390@de.ibm.com email address is outdated. It has been removed from the MAINTAINERS file nearly 10 years ago with commit 64776820b4ff ("s390: remove generic email address from maintainers file"). Change MODULE_AUTHOR() accordingly and also use the more common IBM Corporation company name. Reviewed-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- drivers/s390/scsi/zfcp_aux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index ab2f35bc294d..22074e81bd38 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -41,7 +41,7 @@ #define ZFCP_BUS_ID_SIZE 20 -MODULE_AUTHOR("IBM Deutschland Entwicklung GmbH - linux390@de.ibm.com"); +MODULE_AUTHOR("IBM Corporation"); MODULE_DESCRIPTION("FCP HBA driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 679b110bb662fc107f38ebd5088af56a156dd82f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:47 +0100 Subject: s390/cpufeature: Convert MACHINE_HAS_SEQ_INSN to cpu_has_seq_insn() Convert MACHINE_HAS_... to cpu_has_...() which uses test_facility() instead of testing the machine_flags lowcore member if the feature is present. test_facility() generates better code since it results in a static branch without accessing memory. The branch is patched via alternatives by the decompressor depending on the availability of the required facility. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/cpufeature.h | 4 ++++ arch/s390/include/asm/setup.h | 2 -- arch/s390/kernel/early.c | 2 -- arch/s390/kernel/ftrace.c | 11 ++++++----- arch/s390/kernel/kprobes.c | 5 +++-- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/arch/s390/include/asm/cpufeature.h b/arch/s390/include/asm/cpufeature.h index 931204613753..496d0758b902 100644 --- a/arch/s390/include/asm/cpufeature.h +++ b/arch/s390/include/asm/cpufeature.h @@ -9,6 +9,8 @@ #ifndef __ASM_S390_CPUFEATURE_H #define __ASM_S390_CPUFEATURE_H +#include + enum { S390_CPU_FEATURE_MSA, S390_CPU_FEATURE_VXRS, @@ -20,4 +22,6 @@ enum { int cpu_have_feature(unsigned int nr); +#define cpu_has_seq_insn() test_facility(85) + #endif /* __ASM_S390_CPUFEATURE_H */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 70b920b32827..50b943f30155 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -34,7 +34,6 @@ #define MACHINE_FLAG_SCC BIT(17) #define MACHINE_FLAG_PCI_MIO BIT(18) #define MACHINE_FLAG_RDP BIT(19) -#define MACHINE_FLAG_SEQ_INSN BIT(20) #define LPP_MAGIC BIT(31) #define LPP_PID_MASK _AC(0xffffffff, UL) @@ -96,7 +95,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_SCC (get_lowcore()->machine_flags & MACHINE_FLAG_SCC) #define MACHINE_HAS_PCI_MIO (get_lowcore()->machine_flags & MACHINE_FLAG_PCI_MIO) #define MACHINE_HAS_RDP (get_lowcore()->machine_flags & MACHINE_FLAG_RDP) -#define MACHINE_HAS_SEQ_INSN (get_lowcore()->machine_flags & MACHINE_FLAG_SEQ_INSN) /* * Console mode. Override with conmode= diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 2fa25164df7d..6cee9a74374c 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -269,8 +269,6 @@ static __init void detect_machine_facilities(void) } if (test_facility(194)) get_lowcore()->machine_flags |= MACHINE_FLAG_RDP; - if (test_facility(85)) - get_lowcore()->machine_flags |= MACHINE_FLAG_SEQ_INSN; } static inline void save_vector_registers(void) diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index 63ba6306632e..f2eb9686e033 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -69,7 +70,7 @@ static const char *ftrace_shared_hotpatch_trampoline(const char **end) bool ftrace_need_init_nop(void) { - return !MACHINE_HAS_SEQ_INSN; + return !cpu_has_seq_insn(); } int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) @@ -189,7 +190,7 @@ static int ftrace_modify_trampoline_call(struct dyn_ftrace *rec, int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, unsigned long addr) { - if (MACHINE_HAS_SEQ_INSN) + if (cpu_has_seq_insn()) return ftrace_patch_branch_insn(rec->ip, old_addr, addr); else return ftrace_modify_trampoline_call(rec, old_addr, addr); @@ -213,8 +214,8 @@ static int ftrace_patch_branch_mask(void *addr, u16 expected, bool enable) int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { - /* Expect brcl 0xf,... for the !MACHINE_HAS_SEQ_INSN case */ - if (MACHINE_HAS_SEQ_INSN) + /* Expect brcl 0xf,... for the !cpu_has_seq_insn() case */ + if (cpu_has_seq_insn()) return ftrace_patch_branch_insn(rec->ip, addr, 0); else return ftrace_patch_branch_mask((void *)rec->ip, 0xc0f4, false); @@ -234,7 +235,7 @@ static int ftrace_make_trampoline_call(struct dyn_ftrace *rec, unsigned long add int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) { - if (MACHINE_HAS_SEQ_INSN) + if (cpu_has_seq_insn()) return ftrace_patch_branch_insn(rec->ip, 0, addr); else return ftrace_make_trampoline_call(rec, addr); diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 8b80ea57125f..c450120b4474 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -153,7 +154,7 @@ void arch_arm_kprobe(struct kprobe *p) { struct swap_insn_args args = {.p = p, .arm_kprobe = 1}; - if (MACHINE_HAS_SEQ_INSN) { + if (cpu_has_seq_insn()) { swap_instruction(&args); text_poke_sync(); } else { @@ -166,7 +167,7 @@ void arch_disarm_kprobe(struct kprobe *p) { struct swap_insn_args args = {.p = p, .arm_kprobe = 0}; - if (MACHINE_HAS_SEQ_INSN) { + if (cpu_has_seq_insn()) { swap_instruction(&args); text_poke_sync(); } else { -- cgit v1.2.3-59-g8ed1b From 15a36036e792f4eec0fc59833dde688024e036fc Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:48 +0100 Subject: s390/cpufeature: Convert MACHINE_HAS_RDP to cpu_has_rdp() Convert MACHINE_HAS_... to cpu_has_...() which uses test_facility() instead of testing the machine_flags lowcore member if the feature is present. test_facility() generates better code since it results in a static branch without accessing memory. The branch is patched via alternatives by the decompressor depending on the availability of the required facility. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/cpufeature.h | 1 + arch/s390/include/asm/pgtable.h | 5 +++-- arch/s390/include/asm/setup.h | 2 -- arch/s390/kernel/early.c | 2 -- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/s390/include/asm/cpufeature.h b/arch/s390/include/asm/cpufeature.h index 496d0758b902..641a2780fd5a 100644 --- a/arch/s390/include/asm/cpufeature.h +++ b/arch/s390/include/asm/cpufeature.h @@ -22,6 +22,7 @@ enum { int cpu_have_feature(unsigned int nr); +#define cpu_has_rdp() test_facility(194) #define cpu_has_seq_insn() test_facility(85) #endif /* __ASM_S390_CPUFEATURE_H */ diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 3ca5af4cfe43..62452822676a 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -1339,7 +1340,7 @@ static inline void flush_tlb_fix_spurious_fault(struct vm_area_struct *vma, * PTE does not have _PAGE_PROTECT set, to avoid unnecessary overhead. * A local RDP can be used to do the flush. */ - if (MACHINE_HAS_RDP && !(pte_val(*ptep) & _PAGE_PROTECT)) + if (cpu_has_rdp() && !(pte_val(*ptep) & _PAGE_PROTECT)) __ptep_rdp(address, ptep, 0, 0, 1); } #define flush_tlb_fix_spurious_fault flush_tlb_fix_spurious_fault @@ -1354,7 +1355,7 @@ static inline int ptep_set_access_flags(struct vm_area_struct *vma, { if (pte_same(*ptep, entry)) return 0; - if (MACHINE_HAS_RDP && !mm_has_pgste(vma->vm_mm) && pte_allow_rdp(*ptep, entry)) + if (cpu_has_rdp() && !mm_has_pgste(vma->vm_mm) && pte_allow_rdp(*ptep, entry)) ptep_reset_dat_prot(vma->vm_mm, addr, ptep, entry); else ptep_xchg_direct(vma->vm_mm, addr, ptep, entry); diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 50b943f30155..07e7dab27dfa 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -33,7 +33,6 @@ #define MACHINE_FLAG_GS BIT(16) #define MACHINE_FLAG_SCC BIT(17) #define MACHINE_FLAG_PCI_MIO BIT(18) -#define MACHINE_FLAG_RDP BIT(19) #define LPP_MAGIC BIT(31) #define LPP_PID_MASK _AC(0xffffffff, UL) @@ -94,7 +93,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_GS (get_lowcore()->machine_flags & MACHINE_FLAG_GS) #define MACHINE_HAS_SCC (get_lowcore()->machine_flags & MACHINE_FLAG_SCC) #define MACHINE_HAS_PCI_MIO (get_lowcore()->machine_flags & MACHINE_FLAG_PCI_MIO) -#define MACHINE_HAS_RDP (get_lowcore()->machine_flags & MACHINE_FLAG_RDP) /* * Console mode. Override with conmode= diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 6cee9a74374c..f596a2eb428a 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -267,8 +267,6 @@ static __init void detect_machine_facilities(void) get_lowcore()->machine_flags |= MACHINE_FLAG_PCI_MIO; /* the control bit is set during PCI initialization */ } - if (test_facility(194)) - get_lowcore()->machine_flags |= MACHINE_FLAG_RDP; } static inline void save_vector_registers(void) -- cgit v1.2.3-59-g8ed1b From 42805261fcea809e1e76243dfc5218f6f12c1614 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:49 +0100 Subject: s390/cpufeature: Convert MACHINE_HAS_GS to cpu_has_gs() Convert MACHINE_HAS_... to cpu_has_...() which uses test_facility() instead of testing the machine_flags lowcore member if the feature is present. test_facility() generates better code since it results in a static branch without accessing memory. The branch is patched via alternatives by the decompressor depending on the availability of the required facility. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/cpufeature.h | 1 + arch/s390/include/asm/setup.h | 2 -- arch/s390/kernel/early.c | 2 -- arch/s390/kernel/guarded_storage.c | 3 ++- arch/s390/kernel/machine_kexec.c | 3 ++- arch/s390/kernel/nmi.c | 9 +++++---- arch/s390/kernel/processor.c | 3 ++- arch/s390/kernel/ptrace.c | 11 ++++++----- arch/s390/kernel/smp.c | 5 +++-- arch/s390/kvm/interrupt.c | 3 ++- arch/s390/kvm/kvm-s390.c | 5 +++-- 11 files changed, 26 insertions(+), 21 deletions(-) diff --git a/arch/s390/include/asm/cpufeature.h b/arch/s390/include/asm/cpufeature.h index 641a2780fd5a..e969f020f761 100644 --- a/arch/s390/include/asm/cpufeature.h +++ b/arch/s390/include/asm/cpufeature.h @@ -22,6 +22,7 @@ enum { int cpu_have_feature(unsigned int nr); +#define cpu_has_gs() test_facility(133) #define cpu_has_rdp() test_facility(194) #define cpu_has_seq_insn() test_facility(85) diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 07e7dab27dfa..e08f4295df14 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -30,7 +30,6 @@ #define MACHINE_FLAG_TLB_LC BIT(12) #define MACHINE_FLAG_TLB_GUEST BIT(14) #define MACHINE_FLAG_NX BIT(15) -#define MACHINE_FLAG_GS BIT(16) #define MACHINE_FLAG_SCC BIT(17) #define MACHINE_FLAG_PCI_MIO BIT(18) @@ -90,7 +89,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_TLB_LC (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_LC) #define MACHINE_HAS_TLB_GUEST (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_GUEST) #define MACHINE_HAS_NX (get_lowcore()->machine_flags & MACHINE_FLAG_NX) -#define MACHINE_HAS_GS (get_lowcore()->machine_flags & MACHINE_FLAG_GS) #define MACHINE_HAS_SCC (get_lowcore()->machine_flags & MACHINE_FLAG_SCC) #define MACHINE_HAS_PCI_MIO (get_lowcore()->machine_flags & MACHINE_FLAG_PCI_MIO) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index f596a2eb428a..9590921e8cdf 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -255,8 +255,6 @@ static __init void detect_machine_facilities(void) system_ctl_set_bit(0, CR0_VECTOR_BIT); if (test_facility(130)) get_lowcore()->machine_flags |= MACHINE_FLAG_NX; - if (test_facility(133)) - get_lowcore()->machine_flags |= MACHINE_FLAG_GS; if (test_facility(139) && (tod_clock_base.tod >> 63)) { /* Enabled signed clock comparator comparisons */ get_lowcore()->machine_flags |= MACHINE_FLAG_SCC; diff --git a/arch/s390/kernel/guarded_storage.c b/arch/s390/kernel/guarded_storage.c index 0b68168d9566..cf26d7a37425 100644 --- a/arch/s390/kernel/guarded_storage.c +++ b/arch/s390/kernel/guarded_storage.c @@ -4,6 +4,7 @@ * Author(s): Martin Schwidefsky */ +#include #include #include #include @@ -109,7 +110,7 @@ static int gs_broadcast(void) SYSCALL_DEFINE2(s390_guarded_storage, int, command, struct gs_cb __user *, gs_cb) { - if (!MACHINE_HAS_GS) + if (!cpu_has_gs()) return -EOPNOTSUPP; switch (command) { case GS_ENABLE: diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index 8f681ccfb83a..7962dba7bdea 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -94,7 +95,7 @@ static noinline void __machine_kdump(void *image) mcesa = __va(get_lowcore()->mcesad & MCESA_ORIGIN_MASK); if (cpu_has_vx()) save_vx_regs((__vector128 *) mcesa->vector_save_area); - if (MACHINE_HAS_GS) { + if (cpu_has_gs()) { local_ctl_store(2, &cr2_old.reg); cr2_new = cr2_old; cr2_new.gse = 1; diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index fbd218b6fc8e..3da371c144eb 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -45,7 +46,7 @@ static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck); static inline int nmi_needs_mcesa(void) { - return cpu_has_vx() || MACHINE_HAS_GS; + return cpu_has_vx() || cpu_has_gs(); } /* @@ -61,7 +62,7 @@ void __init nmi_alloc_mcesa_early(u64 *mcesad) if (!nmi_needs_mcesa()) return; *mcesad = __pa(&boot_mcesa); - if (MACHINE_HAS_GS) + if (cpu_has_gs()) *mcesad |= ilog2(MCESA_MAX_SIZE); } @@ -73,14 +74,14 @@ int nmi_alloc_mcesa(u64 *mcesad) *mcesad = 0; if (!nmi_needs_mcesa()) return 0; - size = MACHINE_HAS_GS ? MCESA_MAX_SIZE : MCESA_MIN_SIZE; + size = cpu_has_gs() ? MCESA_MAX_SIZE : MCESA_MIN_SIZE; origin = kmalloc(size, GFP_KERNEL); if (!origin) return -ENOMEM; /* The pointer is stored with mcesa_bits ORed in */ kmemleak_not_leak(origin); *mcesad = __pa(origin); - if (MACHINE_HAS_GS) + if (cpu_has_gs()) *mcesad |= ilog2(MCESA_MAX_SIZE); return 0; } diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 5ce9a795a0fe..c8ce8474d769 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -8,6 +8,7 @@ #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include +#include #include #include #include @@ -244,7 +245,7 @@ static int __init setup_hwcaps(void) elf_hwcap |= HWCAP_NNPA; /* guarded storage */ - if (MACHINE_HAS_GS) + if (cpu_has_gs()) elf_hwcap |= HWCAP_GS; if (MACHINE_HAS_PCI_MIO) diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 1cfed8b710b8..9ed3017bb968 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -75,7 +76,7 @@ void update_cr_regs(struct task_struct *task) } } /* Take care of enable/disable of guarded storage. */ - if (MACHINE_HAS_GS) { + if (cpu_has_gs()) { cr2_new.gse = 0; if (task->thread.gs_cb) cr2_new.gse = 1; @@ -1033,7 +1034,7 @@ static int s390_gs_cb_get(struct task_struct *target, { struct gs_cb *data = target->thread.gs_cb; - if (!MACHINE_HAS_GS) + if (!cpu_has_gs()) return -ENODEV; if (!data) return -ENODATA; @@ -1050,7 +1051,7 @@ static int s390_gs_cb_set(struct task_struct *target, struct gs_cb gs_cb = { }, *data = NULL; int rc; - if (!MACHINE_HAS_GS) + if (!cpu_has_gs()) return -ENODEV; if (!target->thread.gs_cb) { data = kzalloc(sizeof(*data), GFP_KERNEL); @@ -1087,7 +1088,7 @@ static int s390_gs_bc_get(struct task_struct *target, { struct gs_cb *data = target->thread.gs_bc_cb; - if (!MACHINE_HAS_GS) + if (!cpu_has_gs()) return -ENODEV; if (!data) return -ENODATA; @@ -1101,7 +1102,7 @@ static int s390_gs_bc_set(struct task_struct *target, { struct gs_cb *data = target->thread.gs_bc_cb; - if (!MACHINE_HAS_GS) + if (!cpu_has_gs()) return -ENODEV; if (!data) { data = kzalloc(sizeof(*data), GFP_KERNEL); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 7b08399b0846..2bf45d95165b 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -18,6 +18,7 @@ #define KMSG_COMPONENT "cpu" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include #include #include #include @@ -561,10 +562,10 @@ int smp_store_status(int cpu) if (__pcpu_sigp_relax(pcpu->address, SIGP_STORE_STATUS_AT_ADDRESS, pa) != SIGP_CC_ORDER_CODE_ACCEPTED) return -EIO; - if (!cpu_has_vx() && !MACHINE_HAS_GS) + if (!cpu_has_vx() && !cpu_has_gs()) return 0; pa = lc->mcesad & MCESA_ORIGIN_MASK; - if (MACHINE_HAS_GS) + if (cpu_has_gs()) pa |= lc->mcesad & MCESA_LC_MASK; if (__pcpu_sigp_relax(pcpu->address, SIGP_STORE_ADDITIONAL_STATUS, pa) != SIGP_CC_ORDER_CODE_ACCEPTED) diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 07ff0e10cb7f..2c1f69760e7e 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -10,6 +10,7 @@ #define KMSG_COMPONENT "kvm-s390" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include #include #include #include @@ -577,7 +578,7 @@ static int __write_machine_check(struct kvm_vcpu *vcpu, /* take care of lazy register loading */ kvm_s390_fpu_store(vcpu->run); save_access_regs(vcpu->run->s.regs.acrs); - if (MACHINE_HAS_GS && vcpu->arch.gs_enabled) + if (cpu_has_gs() && vcpu->arch.gs_enabled) save_gs_cb(current->thread.gs_cb); /* Extended save area */ diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index ebecb96bacce..703a6594cfaf 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -5171,7 +5172,7 @@ static void sync_regs_fmt2(struct kvm_vcpu *vcpu) vcpu->arch.sie_block->fpf &= ~FPF_BPBC; vcpu->arch.sie_block->fpf |= kvm_run->s.regs.bpbc ? FPF_BPBC : 0; } - if (MACHINE_HAS_GS) { + if (cpu_has_gs()) { preempt_disable(); local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT); if (current->thread.gs_cb) { @@ -5237,7 +5238,7 @@ static void store_regs_fmt2(struct kvm_vcpu *vcpu) kvm_run->s.regs.gbea = vcpu->arch.sie_block->gbea; kvm_run->s.regs.bpbc = (vcpu->arch.sie_block->fpf & FPF_BPBC) == FPF_BPBC; kvm_run->s.regs.diag318 = vcpu->arch.diag318_info.val; - if (MACHINE_HAS_GS) { + if (cpu_has_gs()) { preempt_disable(); local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT); if (vcpu->arch.gs_enabled) -- cgit v1.2.3-59-g8ed1b From b49ee5b38651643d9e643fb4c7465f4046022254 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:50 +0100 Subject: s390/cpufeature: Convert MACHINE_HAS_NX to cpu_has_nx() Convert MACHINE_HAS_... to cpu_has_...() which uses test_facility() instead of testing the machine_flags lowcore member if the feature is present. test_facility() generates better code since it results in a static branch without accessing memory. The branch is patched via alternatives by the decompressor depending on the availability of the required facility. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/startup.c | 2 +- arch/s390/include/asm/cpufeature.h | 1 + arch/s390/include/asm/setup.h | 2 -- arch/s390/kernel/early.c | 2 -- arch/s390/mm/dump_pagetables.c | 4 +++- arch/s390/mm/fault.c | 3 ++- arch/s390/mm/init.c | 3 ++- arch/s390/mm/pageattr.c | 3 ++- 8 files changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 885bd1dd2c82..55b8fad06b64 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -59,7 +59,7 @@ static void detect_facilities(void) page_noexec_mask = -1UL; segment_noexec_mask = -1UL; region_noexec_mask = -1UL; - if (!test_facility(130)) { + if (!cpu_has_nx()) { page_noexec_mask &= ~_PAGE_NOEXEC; segment_noexec_mask &= ~_SEGMENT_ENTRY_NOEXEC; region_noexec_mask &= ~_REGION_ENTRY_NOEXEC; diff --git a/arch/s390/include/asm/cpufeature.h b/arch/s390/include/asm/cpufeature.h index e969f020f761..64ff316a69e3 100644 --- a/arch/s390/include/asm/cpufeature.h +++ b/arch/s390/include/asm/cpufeature.h @@ -23,6 +23,7 @@ enum { int cpu_have_feature(unsigned int nr); #define cpu_has_gs() test_facility(133) +#define cpu_has_nx() test_facility(130) #define cpu_has_rdp() test_facility(194) #define cpu_has_seq_insn() test_facility(85) diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index e08f4295df14..914d694960e4 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -29,7 +29,6 @@ #define MACHINE_FLAG_TE BIT(11) #define MACHINE_FLAG_TLB_LC BIT(12) #define MACHINE_FLAG_TLB_GUEST BIT(14) -#define MACHINE_FLAG_NX BIT(15) #define MACHINE_FLAG_SCC BIT(17) #define MACHINE_FLAG_PCI_MIO BIT(18) @@ -88,7 +87,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_TE (get_lowcore()->machine_flags & MACHINE_FLAG_TE) #define MACHINE_HAS_TLB_LC (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_LC) #define MACHINE_HAS_TLB_GUEST (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_GUEST) -#define MACHINE_HAS_NX (get_lowcore()->machine_flags & MACHINE_FLAG_NX) #define MACHINE_HAS_SCC (get_lowcore()->machine_flags & MACHINE_FLAG_SCC) #define MACHINE_HAS_PCI_MIO (get_lowcore()->machine_flags & MACHINE_FLAG_PCI_MIO) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 9590921e8cdf..32a0983a0378 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -253,8 +253,6 @@ static __init void detect_machine_facilities(void) get_lowcore()->machine_flags |= MACHINE_FLAG_TLB_LC; if (test_facility(129)) system_ctl_set_bit(0, CR0_VECTOR_BIT); - if (test_facility(130)) - get_lowcore()->machine_flags |= MACHINE_FLAG_NX; if (test_facility(139) && (tod_clock_base.tod >> 63)) { /* Enabled signed clock comparator comparisons */ get_lowcore()->machine_flags |= MACHINE_FLAG_SCC; diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c index fa54f3bc0c8d..b60bc2b42871 100644 --- a/arch/s390/mm/dump_pagetables.c +++ b/arch/s390/mm/dump_pagetables.c @@ -1,4 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 + +#include #include #include #include @@ -167,7 +169,7 @@ bool ptdump_check_wx(void) }, }; - if (!MACHINE_HAS_NX) + if (!cpu_has_nx()) return true; ptdump_walk_pgd(&st.ptdump, &init_mm, NULL); if (st.wx_pages) { diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 9c9d7840cb57..13d8c44bf8ed 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -366,7 +367,7 @@ void do_protection_exception(struct pt_regs *regs) */ return handle_fault_error_nolock(regs, 0); } - if (unlikely(MACHINE_HAS_NX && teid.b56)) { + if (unlikely(cpu_has_nx() && teid.b56)) { regs->int_parm_long = (teid.addr * PAGE_SIZE) | (regs->psw.addr & PAGE_MASK); return handle_fault_error_nolock(regs, SEGV_ACCERR); } diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index f2298f7a3f21..6e325f81b89a 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -8,6 +8,7 @@ * Copyright (C) 1995 Linus Torvalds */ +#include #include #include #include @@ -117,7 +118,7 @@ void mark_rodata_ro(void) { unsigned long size = __end_ro_after_init - __start_ro_after_init; - if (MACHINE_HAS_NX) + if (cpu_has_nx()) system_ctl_set_bit(0, CR0_INSTRUCTION_EXEC_PROTECTION_BIT); __set_memory_ro(__start_ro_after_init, __end_ro_after_init); pr_info("Write protected read-only-after-init data: %luk\n", size >> 10); diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c index eae97fb61712..93c0ee36436e 100644 --- a/arch/s390/mm/pageattr.c +++ b/arch/s390/mm/pageattr.c @@ -3,6 +3,7 @@ * Copyright IBM Corp. 2011 * Author(s): Jan Glauber */ +#include #include #include #include @@ -373,7 +374,7 @@ int __set_memory(unsigned long addr, unsigned long numpages, unsigned long flags unsigned long end; int rc; - if (!MACHINE_HAS_NX) + if (!cpu_has_nx()) flags &= ~(SET_MEMORY_NX | SET_MEMORY_X); if (!flags) return 0; -- cgit v1.2.3-59-g8ed1b From 8e31fea55d28057c82aab85424b224fafa552b6c Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:51 +0100 Subject: s390/cpufeature: Convert MACHINE_HAS_TLB_LC to cpu_has_tlb_lc() Convert MACHINE_HAS_... to cpu_has_...() which uses test_facility() instead of testing the machine_flags lowcore member if the feature is present. test_facility() generates better code since it results in a static branch without accessing memory. The branch is patched via alternatives by the decompressor depending on the availability of the required facility. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/cpufeature.h | 1 + arch/s390/include/asm/setup.h | 2 -- arch/s390/kernel/early.c | 2 -- arch/s390/mm/pgtable.c | 7 ++++--- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/arch/s390/include/asm/cpufeature.h b/arch/s390/include/asm/cpufeature.h index 64ff316a69e3..6ba487a7c842 100644 --- a/arch/s390/include/asm/cpufeature.h +++ b/arch/s390/include/asm/cpufeature.h @@ -26,5 +26,6 @@ int cpu_have_feature(unsigned int nr); #define cpu_has_nx() test_facility(130) #define cpu_has_rdp() test_facility(194) #define cpu_has_seq_insn() test_facility(85) +#define cpu_has_tlb_lc() test_facility(51) #endif /* __ASM_S390_CPUFEATURE_H */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 914d694960e4..b117f3a4b4c2 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -27,7 +27,6 @@ #define MACHINE_FLAG_EDAT2 BIT(8) #define MACHINE_FLAG_TOPOLOGY BIT(10) #define MACHINE_FLAG_TE BIT(11) -#define MACHINE_FLAG_TLB_LC BIT(12) #define MACHINE_FLAG_TLB_GUEST BIT(14) #define MACHINE_FLAG_SCC BIT(17) #define MACHINE_FLAG_PCI_MIO BIT(18) @@ -85,7 +84,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_EDAT2 (get_lowcore()->machine_flags & MACHINE_FLAG_EDAT2) #define MACHINE_HAS_TOPOLOGY (get_lowcore()->machine_flags & MACHINE_FLAG_TOPOLOGY) #define MACHINE_HAS_TE (get_lowcore()->machine_flags & MACHINE_FLAG_TE) -#define MACHINE_HAS_TLB_LC (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_LC) #define MACHINE_HAS_TLB_GUEST (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_GUEST) #define MACHINE_HAS_SCC (get_lowcore()->machine_flags & MACHINE_FLAG_SCC) #define MACHINE_HAS_PCI_MIO (get_lowcore()->machine_flags & MACHINE_FLAG_PCI_MIO) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 32a0983a0378..1f22dd8094ec 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -249,8 +249,6 @@ static __init void detect_machine_facilities(void) get_lowcore()->machine_flags |= MACHINE_FLAG_TE; system_ctl_set_bit(0, CR0_TRANSACTIONAL_EXECUTION_BIT); } - if (test_facility(51)) - get_lowcore()->machine_flags |= MACHINE_FLAG_TLB_LC; if (test_facility(129)) system_ctl_set_bit(0, CR0_VECTOR_BIT); if (test_facility(139) && (tod_clock_base.tod >> 63)) { diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index f05e62e037c2..03cbe8ce05ca 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -4,6 +4,7 @@ * Author(s): Martin Schwidefsky */ +#include #include #include #include @@ -94,7 +95,7 @@ static inline pte_t ptep_flush_direct(struct mm_struct *mm, if (unlikely(pte_val(old) & _PAGE_INVALID)) return old; atomic_inc(&mm->context.flush_count); - if (MACHINE_HAS_TLB_LC && + if (cpu_has_tlb_lc() && cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) ptep_ipte_local(mm, addr, ptep, nodat); else @@ -411,7 +412,7 @@ static inline pmd_t pmdp_flush_direct(struct mm_struct *mm, if (pmd_val(old) & _SEGMENT_ENTRY_INVALID) return old; atomic_inc(&mm->context.flush_count); - if (MACHINE_HAS_TLB_LC && + if (cpu_has_tlb_lc() && cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) pmdp_idte_local(mm, addr, pmdp); else @@ -537,7 +538,7 @@ static inline pud_t pudp_flush_direct(struct mm_struct *mm, if (pud_val(old) & _REGION_ENTRY_INVALID) return old; atomic_inc(&mm->context.flush_count); - if (MACHINE_HAS_TLB_LC && + if (cpu_has_tlb_lc() && cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) pudp_idte_local(mm, addr, pudp); else -- cgit v1.2.3-59-g8ed1b From 5643195f2626bc7391720b77d9f7c9b068f4fbe0 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:52 +0100 Subject: s390/cpufeature: Convert MACHINE_HAS_TOPOLOGY to cpu_has_topology() Convert MACHINE_HAS_... to cpu_has_...() which uses test_facility() instead of testing the machine_flags lowcore member if the feature is present. test_facility() generates better code since it results in a static branch without accessing memory. The branch is patched via alternatives by the decompressor depending on the availability of the required facility. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/cpufeature.h | 1 + arch/s390/include/asm/setup.h | 2 -- arch/s390/kernel/early.c | 4 ++-- arch/s390/kernel/hiperdispatch.c | 3 ++- arch/s390/kernel/sysinfo.c | 5 +++-- arch/s390/kernel/topology.c | 19 ++++++++++--------- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/arch/s390/include/asm/cpufeature.h b/arch/s390/include/asm/cpufeature.h index 6ba487a7c842..5c7c535a3b5b 100644 --- a/arch/s390/include/asm/cpufeature.h +++ b/arch/s390/include/asm/cpufeature.h @@ -27,5 +27,6 @@ int cpu_have_feature(unsigned int nr); #define cpu_has_rdp() test_facility(194) #define cpu_has_seq_insn() test_facility(85) #define cpu_has_tlb_lc() test_facility(51) +#define cpu_has_topology() test_facility(11) #endif /* __ASM_S390_CPUFEATURE_H */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index b117f3a4b4c2..25f4d5b6e23b 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -25,7 +25,6 @@ #define MACHINE_FLAG_IDTE BIT(5) #define MACHINE_FLAG_EDAT1 BIT(7) #define MACHINE_FLAG_EDAT2 BIT(8) -#define MACHINE_FLAG_TOPOLOGY BIT(10) #define MACHINE_FLAG_TE BIT(11) #define MACHINE_FLAG_TLB_GUEST BIT(14) #define MACHINE_FLAG_SCC BIT(17) @@ -82,7 +81,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_IDTE (get_lowcore()->machine_flags & MACHINE_FLAG_IDTE) #define MACHINE_HAS_EDAT1 (get_lowcore()->machine_flags & MACHINE_FLAG_EDAT1) #define MACHINE_HAS_EDAT2 (get_lowcore()->machine_flags & MACHINE_FLAG_EDAT2) -#define MACHINE_HAS_TOPOLOGY (get_lowcore()->machine_flags & MACHINE_FLAG_TOPOLOGY) #define MACHINE_HAS_TE (get_lowcore()->machine_flags & MACHINE_FLAG_TE) #define MACHINE_HAS_TLB_GUEST (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_GUEST) #define MACHINE_HAS_SCC (get_lowcore()->machine_flags & MACHINE_FLAG_SCC) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 1f22dd8094ec..68685aa23c16 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -8,6 +8,7 @@ #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include +#include #include #include #include @@ -167,9 +168,8 @@ static __init void setup_topology(void) { int max_mnest; - if (!test_facility(11)) + if (!cpu_has_topology()) return; - get_lowcore()->machine_flags |= MACHINE_FLAG_TOPOLOGY; for (max_mnest = 6; max_mnest > 1; max_mnest--) { if (stsi(&sysinfo_page, 15, 1, max_mnest) == 0) break; diff --git a/arch/s390/kernel/hiperdispatch.c b/arch/s390/kernel/hiperdispatch.c index 7857a7e8e56c..e7b66d046e8d 100644 --- a/arch/s390/kernel/hiperdispatch.c +++ b/arch/s390/kernel/hiperdispatch.c @@ -45,6 +45,7 @@ * therefore delaying the throughput loss caused by using SMP threads. */ +#include #include #include #include @@ -87,7 +88,7 @@ static DECLARE_DELAYED_WORK(hd_capacity_work, hd_capacity_work_fn); static int hd_set_hiperdispatch_mode(int enable) { - if (!MACHINE_HAS_TOPOLOGY) + if (!cpu_has_topology()) enable = 0; if (hd_enabled == enable) return 0; diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index 88055f58fbda..a74154c6529e 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -5,6 +5,7 @@ * Martin Schwidefsky , */ +#include #include #include #include @@ -154,7 +155,7 @@ static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info) int i; seq_putc(m, '\n'); - if (!MACHINE_HAS_TOPOLOGY) + if (!cpu_has_topology()) return; if (stsi(info, 15, 1, topology_max_mnest)) return; @@ -559,7 +560,7 @@ static __init int stsi_init_debugfs(void) sf = &stsi_file[i]; debugfs_create_file(sf->name, 0400, stsi_root, NULL, sf->fops); } - if (IS_ENABLED(CONFIG_SCHED_TOPOLOGY) && MACHINE_HAS_TOPOLOGY) { + if (IS_ENABLED(CONFIG_SCHED_TOPOLOGY) && cpu_has_topology()) { char link_to[10]; sprintf(link_to, "15_1_%d", topology_mnest_limit()); diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 211cc8382e4a..3df048e190b1 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -6,6 +6,7 @@ #define KMSG_COMPONENT "cpu" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include #include #include #include @@ -240,7 +241,7 @@ int topology_set_cpu_management(int fc) { int cpu, rc; - if (!MACHINE_HAS_TOPOLOGY) + if (!cpu_has_topology()) return -EOPNOTSUPP; if (fc) rc = ptf(PTF_VERTICAL); @@ -315,13 +316,13 @@ static int __arch_update_cpu_topology(void) hd_status = 0; rc = 0; mutex_lock(&smp_cpu_state_mutex); - if (MACHINE_HAS_TOPOLOGY) { + if (cpu_has_topology()) { rc = 1; store_topology(info); tl_to_masks(info); } update_cpu_masks(); - if (!MACHINE_HAS_TOPOLOGY) + if (!cpu_has_topology()) topology_update_polarization_simple(); if (cpu_management == 1) hd_status = hd_enable_hiperdispatch(); @@ -376,7 +377,7 @@ static void set_topology_timer(void) void topology_expect_change(void) { - if (!MACHINE_HAS_TOPOLOGY) + if (!cpu_has_topology()) return; /* This is racy, but it doesn't matter since it is just a heuristic. * Worst case is that we poll in a higher frequency for a bit longer. @@ -500,7 +501,7 @@ int topology_cpu_init(struct cpu *cpu) int rc; rc = sysfs_create_group(&cpu->dev.kobj, &topology_cpu_attr_group); - if (rc || !MACHINE_HAS_TOPOLOGY) + if (rc || !cpu_has_topology()) return rc; rc = sysfs_create_group(&cpu->dev.kobj, &topology_extra_cpu_attr_group); if (rc) @@ -569,12 +570,12 @@ void __init topology_init_early(void) set_sched_topology(s390_topology); if (topology_mode == TOPOLOGY_MODE_UNINITIALIZED) { - if (MACHINE_HAS_TOPOLOGY) + if (cpu_has_topology()) topology_mode = TOPOLOGY_MODE_HW; else topology_mode = TOPOLOGY_MODE_SINGLE; } - if (!MACHINE_HAS_TOPOLOGY) + if (!cpu_has_topology()) goto out; tl_info = memblock_alloc_or_panic(PAGE_SIZE, PAGE_SIZE); info = tl_info; @@ -596,7 +597,7 @@ static inline int topology_get_mode(int enabled) { if (!enabled) return TOPOLOGY_MODE_SINGLE; - return MACHINE_HAS_TOPOLOGY ? TOPOLOGY_MODE_HW : TOPOLOGY_MODE_PACKAGE; + return cpu_has_topology() ? TOPOLOGY_MODE_HW : TOPOLOGY_MODE_PACKAGE; } static inline int topology_is_enabled(void) @@ -686,7 +687,7 @@ static int __init topology_init(void) int rc = 0; timer_setup(&topology_timer, topology_timer_fn, TIMER_DEFERRABLE); - if (MACHINE_HAS_TOPOLOGY) + if (cpu_has_topology()) set_topology_timer(); else topology_update_polarization_simple(); -- cgit v1.2.3-59-g8ed1b From 2e2ff71febfe30963deff1897b7d1d1ceb8628dd Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:53 +0100 Subject: s390/cpufeature: Convert MACHINE_HAS_EDAT1 to cpu_has_edat1() Convert MACHINE_HAS_... to cpu_has_...() which uses test_facility() instead of testing the machine_flags lowcore member if the feature is present. test_facility() generates better code since it results in a static branch without accessing memory. The branch is patched via alternatives by the decompressor depending on the availability of the required facility. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/boot.h | 1 - arch/s390/boot/startup.c | 4 +--- arch/s390/boot/vmem.c | 3 ++- arch/s390/include/asm/cpufeature.h | 1 + arch/s390/include/asm/hugetlb.h | 3 ++- arch/s390/include/asm/pgtable.h | 2 +- arch/s390/include/asm/setup.h | 2 -- arch/s390/kernel/early.c | 4 ---- arch/s390/kernel/processor.c | 2 +- arch/s390/mm/hugetlbpage.c | 5 +++-- arch/s390/mm/pageattr.c | 2 +- arch/s390/mm/vmem.c | 5 +++-- drivers/s390/char/sclp_cmd.c | 3 ++- 13 files changed, 17 insertions(+), 20 deletions(-) diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h index 69f261566a64..668d88fbeccb 100644 --- a/arch/s390/boot/boot.h +++ b/arch/s390/boot/boot.h @@ -12,7 +12,6 @@ #include struct machine_info { - unsigned char has_edat1 : 1; unsigned char has_edat2 : 1; }; diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 55b8fad06b64..124bf13dedf9 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -50,10 +50,8 @@ void error(char *x) static void detect_facilities(void) { - if (test_facility(8)) { - machine.has_edat1 = 1; + if (cpu_has_edat1()) local_ctl_set_bit(0, CR0_EDAT_BIT); - } if (test_facility(78)) machine.has_edat2 = 1; page_noexec_mask = -1UL; diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c index cfca94a8eac4..4d27428c5233 100644 --- a/arch/s390/boot/vmem.c +++ b/arch/s390/boot/vmem.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #define boot_fmt(fmt) "vmem: " fmt +#include #include #include #include @@ -330,7 +331,7 @@ static unsigned long try_get_large_pmd_pa(pmd_t *pm_dir, unsigned long addr, uns { unsigned long pa, size = end - addr; - if (!machine.has_edat1 || !large_page_mapping_allowed(mode) || + if (!cpu_has_edat1() || !large_page_mapping_allowed(mode) || !IS_ALIGNED(addr, PMD_SIZE) || (size < PMD_SIZE)) return INVALID_PHYS_ADDR; diff --git a/arch/s390/include/asm/cpufeature.h b/arch/s390/include/asm/cpufeature.h index 5c7c535a3b5b..f4f3ca95872f 100644 --- a/arch/s390/include/asm/cpufeature.h +++ b/arch/s390/include/asm/cpufeature.h @@ -22,6 +22,7 @@ enum { int cpu_have_feature(unsigned int nr); +#define cpu_has_edat1() test_facility(8) #define cpu_has_gs() test_facility(133) #define cpu_has_nx() test_facility(130) #define cpu_has_rdp() test_facility(194) diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h index 7c52acaf9f82..e42655a8e404 100644 --- a/arch/s390/include/asm/hugetlb.h +++ b/arch/s390/include/asm/hugetlb.h @@ -9,12 +9,13 @@ #ifndef _ASM_S390_HUGETLB_H #define _ASM_S390_HUGETLB_H +#include #include #include #include #include -#define hugepages_supported() (MACHINE_HAS_EDAT1) +#define hugepages_supported() cpu_has_edat1() #define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 62452822676a..fb757f5e220b 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -1891,7 +1891,7 @@ static inline int pmd_trans_huge(pmd_t pmd) #define has_transparent_hugepage has_transparent_hugepage static inline int has_transparent_hugepage(void) { - return MACHINE_HAS_EDAT1 ? 1 : 0; + return cpu_has_edat1() ? 1 : 0; } #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 25f4d5b6e23b..bd46e5206941 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -23,7 +23,6 @@ #define MACHINE_FLAG_DIAG9C BIT(3) #define MACHINE_FLAG_ESOP BIT(4) #define MACHINE_FLAG_IDTE BIT(5) -#define MACHINE_FLAG_EDAT1 BIT(7) #define MACHINE_FLAG_EDAT2 BIT(8) #define MACHINE_FLAG_TE BIT(11) #define MACHINE_FLAG_TLB_GUEST BIT(14) @@ -79,7 +78,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_DIAG9C (get_lowcore()->machine_flags & MACHINE_FLAG_DIAG9C) #define MACHINE_HAS_ESOP (get_lowcore()->machine_flags & MACHINE_FLAG_ESOP) #define MACHINE_HAS_IDTE (get_lowcore()->machine_flags & MACHINE_FLAG_IDTE) -#define MACHINE_HAS_EDAT1 (get_lowcore()->machine_flags & MACHINE_FLAG_EDAT1) #define MACHINE_HAS_EDAT2 (get_lowcore()->machine_flags & MACHINE_FLAG_EDAT2) #define MACHINE_HAS_TE (get_lowcore()->machine_flags & MACHINE_FLAG_TE) #define MACHINE_HAS_TLB_GUEST (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_GUEST) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 68685aa23c16..dd9c32e3cf1c 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -237,10 +237,6 @@ static __init void detect_diag9c(void) static __init void detect_machine_facilities(void) { - if (test_facility(8)) { - get_lowcore()->machine_flags |= MACHINE_FLAG_EDAT1; - system_ctl_set_bit(0, CR0_EDAT_BIT); - } if (test_facility(78)) get_lowcore()->machine_flags |= MACHINE_FLAG_EDAT2; if (test_facility(3)) diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index c8ce8474d769..4c751b6539f8 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -210,7 +210,7 @@ static int __init setup_hwcaps(void) elf_hwcap |= HWCAP_DFP; /* huge page support */ - if (MACHINE_HAS_EDAT1) + if (cpu_has_edat1()) elf_hwcap |= HWCAP_HPAGE; /* 64-bit register support for 31-bit processes */ diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c index d9ce199953de..380a42a34841 100644 --- a/arch/s390/mm/hugetlbpage.c +++ b/arch/s390/mm/hugetlbpage.c @@ -9,12 +9,13 @@ #define KMSG_COMPONENT "hugetlb" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt -#include +#include #include #include #include #include #include +#include /* * If the bit selected by single-bit bitmask "a" is set within "x", move @@ -248,7 +249,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm, bool __init arch_hugetlb_valid_size(unsigned long size) { - if (MACHINE_HAS_EDAT1 && size == PMD_SIZE) + if (cpu_has_edat1() && size == PMD_SIZE) return true; else if (MACHINE_HAS_EDAT2 && size == PUD_SIZE) return true; diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c index 93c0ee36436e..70c73fe96b39 100644 --- a/arch/s390/mm/pageattr.c +++ b/arch/s390/mm/pageattr.c @@ -28,7 +28,7 @@ void __storage_key_init_range(unsigned long start, unsigned long end) unsigned long boundary, size; while (start < end) { - if (MACHINE_HAS_EDAT1) { + if (cpu_has_edat1()) { /* set storage keys for a 1MB frame */ size = 1UL << 20; boundary = (start + size) & ~(size - 1); diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 8ead999e340b..d4d77e89741b 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -249,12 +250,12 @@ static int __ref modify_pmd_table(pud_t *pud, unsigned long addr, } else if (pmd_none(*pmd)) { if (IS_ALIGNED(addr, PMD_SIZE) && IS_ALIGNED(next, PMD_SIZE) && - MACHINE_HAS_EDAT1 && direct && + cpu_has_edat1() && direct && !debug_pagealloc_enabled()) { set_pmd(pmd, __pmd(__pa(addr) | prot)); pages++; continue; - } else if (!direct && MACHINE_HAS_EDAT1) { + } else if (!direct && cpu_has_edat1()) { void *new_page; /* diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index f905a6643a0f..9fcdce9bb35f 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -8,6 +8,7 @@ #define KMSG_COMPONENT "sclp_cmd" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include #include #include #include @@ -428,7 +429,7 @@ static void __init add_memory_merged(u16 rn) goto skip_add; for (addr = start; addr < start + size; addr += block_size) add_memory(0, addr, block_size, - MACHINE_HAS_EDAT1 ? + cpu_has_edat1() ? MHP_MEMMAP_ON_MEMORY | MHP_OFFLINE_INACCESSIBLE : MHP_NONE); skip_add: first_rn = rn; -- cgit v1.2.3-59-g8ed1b From 3f5eede6dfdd2cf9f4c0156ccee20bd0e5d927aa Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:54 +0100 Subject: s390/cpufeature: Convert MACHINE_HAS_EDAT2 to cpu_has_edat2() Convert MACHINE_HAS_... to cpu_has_...() which uses test_facility() instead of testing the machine_flags lowcore member if the feature is present. test_facility() generates better code since it results in a static branch without accessing memory. The branch is patched via alternatives by the decompressor depending on the availability of the required facility. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/boot.h | 4 ---- arch/s390/boot/startup.c | 4 ---- arch/s390/boot/vmem.c | 2 +- arch/s390/include/asm/cpufeature.h | 1 + arch/s390/include/asm/setup.h | 2 -- arch/s390/kernel/early.c | 2 -- arch/s390/kernel/setup.c | 2 +- arch/s390/mm/hugetlbpage.c | 2 +- arch/s390/mm/pageattr.c | 2 +- arch/s390/mm/vmem.c | 2 +- 10 files changed, 6 insertions(+), 17 deletions(-) diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h index 668d88fbeccb..f4af23c142cc 100644 --- a/arch/s390/boot/boot.h +++ b/arch/s390/boot/boot.h @@ -11,10 +11,6 @@ #include #include -struct machine_info { - unsigned char has_edat2 : 1; -}; - struct vmlinux_info { unsigned long entry; unsigned long image_size; /* does not include .bss */ diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 124bf13dedf9..72d48e1d67be 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -39,8 +39,6 @@ int __bootdata_preserved(relocate_lowcore); u64 __bootdata_preserved(stfle_fac_list[16]); struct oldmem_data __bootdata_preserved(oldmem_data); -struct machine_info machine; - void error(char *x) { boot_emerg("%s\n", x); @@ -52,8 +50,6 @@ static void detect_facilities(void) { if (cpu_has_edat1()) local_ctl_set_bit(0, CR0_EDAT_BIT); - if (test_facility(78)) - machine.has_edat2 = 1; page_noexec_mask = -1UL; segment_noexec_mask = -1UL; region_noexec_mask = -1UL; diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c index 4d27428c5233..1e87cffac2f1 100644 --- a/arch/s390/boot/vmem.c +++ b/arch/s390/boot/vmem.c @@ -315,7 +315,7 @@ static unsigned long try_get_large_pud_pa(pud_t *pu_dir, unsigned long addr, uns { unsigned long pa, size = end - addr; - if (!machine.has_edat2 || !large_page_mapping_allowed(mode) || + if (!cpu_has_edat2() || !large_page_mapping_allowed(mode) || !IS_ALIGNED(addr, PUD_SIZE) || (size < PUD_SIZE)) return INVALID_PHYS_ADDR; diff --git a/arch/s390/include/asm/cpufeature.h b/arch/s390/include/asm/cpufeature.h index f4f3ca95872f..dca25fd29f77 100644 --- a/arch/s390/include/asm/cpufeature.h +++ b/arch/s390/include/asm/cpufeature.h @@ -23,6 +23,7 @@ enum { int cpu_have_feature(unsigned int nr); #define cpu_has_edat1() test_facility(8) +#define cpu_has_edat2() test_facility(78) #define cpu_has_gs() test_facility(133) #define cpu_has_nx() test_facility(130) #define cpu_has_rdp() test_facility(194) diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index bd46e5206941..5e5536f586d0 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -23,7 +23,6 @@ #define MACHINE_FLAG_DIAG9C BIT(3) #define MACHINE_FLAG_ESOP BIT(4) #define MACHINE_FLAG_IDTE BIT(5) -#define MACHINE_FLAG_EDAT2 BIT(8) #define MACHINE_FLAG_TE BIT(11) #define MACHINE_FLAG_TLB_GUEST BIT(14) #define MACHINE_FLAG_SCC BIT(17) @@ -78,7 +77,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_DIAG9C (get_lowcore()->machine_flags & MACHINE_FLAG_DIAG9C) #define MACHINE_HAS_ESOP (get_lowcore()->machine_flags & MACHINE_FLAG_ESOP) #define MACHINE_HAS_IDTE (get_lowcore()->machine_flags & MACHINE_FLAG_IDTE) -#define MACHINE_HAS_EDAT2 (get_lowcore()->machine_flags & MACHINE_FLAG_EDAT2) #define MACHINE_HAS_TE (get_lowcore()->machine_flags & MACHINE_FLAG_TE) #define MACHINE_HAS_TLB_GUEST (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_GUEST) #define MACHINE_HAS_SCC (get_lowcore()->machine_flags & MACHINE_FLAG_SCC) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index dd9c32e3cf1c..73f8824971ac 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -237,8 +237,6 @@ static __init void detect_diag9c(void) static __init void detect_machine_facilities(void) { - if (test_facility(78)) - get_lowcore()->machine_flags |= MACHINE_FLAG_EDAT2; if (test_facility(3)) get_lowcore()->machine_flags |= MACHINE_FLAG_IDTE; if (test_facility(50) && test_facility(73)) { diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index d78bcfe707b5..c9dd34461625 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -961,7 +961,7 @@ void __init setup_arch(char **cmdline_p) setup_uv(); dma_contiguous_reserve(ident_map_size); vmcp_cma_reserve(); - if (MACHINE_HAS_EDAT2) + if (cpu_has_edat2()) hugetlb_cma_reserve(PUD_SHIFT - PAGE_SHIFT); reserve_crashkernel(); diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c index 380a42a34841..ddbe14bb808d 100644 --- a/arch/s390/mm/hugetlbpage.c +++ b/arch/s390/mm/hugetlbpage.c @@ -251,7 +251,7 @@ bool __init arch_hugetlb_valid_size(unsigned long size) { if (cpu_has_edat1() && size == PMD_SIZE) return true; - else if (MACHINE_HAS_EDAT2 && size == PUD_SIZE) + else if (cpu_has_edat2() && size == PUD_SIZE) return true; else return false; diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c index 70c73fe96b39..3a6041dda17a 100644 --- a/arch/s390/mm/pageattr.c +++ b/arch/s390/mm/pageattr.c @@ -64,7 +64,7 @@ static void pgt_set(unsigned long *old, unsigned long new, unsigned long addr, unsigned long *table, mask; mask = 0; - if (MACHINE_HAS_EDAT2) { + if (cpu_has_edat2()) { switch (dtt) { case CRDTE_DTT_REGION3: mask = ~(PTRS_PER_PUD * sizeof(pud_t) - 1); diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index d4d77e89741b..5d2d39f05d8c 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -336,7 +336,7 @@ static int modify_pud_table(p4d_t *p4d, unsigned long addr, unsigned long end, } else if (pud_none(*pud)) { if (IS_ALIGNED(addr, PUD_SIZE) && IS_ALIGNED(next, PUD_SIZE) && - MACHINE_HAS_EDAT2 && direct && + cpu_has_edat2() && direct && !debug_pagealloc_enabled()) { set_pud(pud, __pud(__pa(addr) | prot)); pages++; -- cgit v1.2.3-59-g8ed1b From 949b73c9902613bddb789d9375981afbffe596fc Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:55 +0100 Subject: s390/cpufeature: Convert MACHINE_HAS_IDTE to cpu_has_idte() Convert MACHINE_HAS_... to cpu_has_...() which uses test_facility() instead of testing the machine_flags lowcore member if the feature is present. test_facility() generates better code since it results in a static branch without accessing memory. The branch is patched via alternatives by the decompressor depending on the availability of the required facility. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/cpufeature.h | 1 + arch/s390/include/asm/setup.h | 2 -- arch/s390/include/asm/tlbflush.h | 5 +++-- arch/s390/kernel/early.c | 2 -- arch/s390/mm/gmap.c | 9 +++++---- arch/s390/mm/pageattr.c | 2 +- arch/s390/mm/pgtable.c | 4 ++-- 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/s390/include/asm/cpufeature.h b/arch/s390/include/asm/cpufeature.h index dca25fd29f77..026a43b86fd7 100644 --- a/arch/s390/include/asm/cpufeature.h +++ b/arch/s390/include/asm/cpufeature.h @@ -25,6 +25,7 @@ int cpu_have_feature(unsigned int nr); #define cpu_has_edat1() test_facility(8) #define cpu_has_edat2() test_facility(78) #define cpu_has_gs() test_facility(133) +#define cpu_has_idte() test_facility(3) #define cpu_has_nx() test_facility(130) #define cpu_has_rdp() test_facility(194) #define cpu_has_seq_insn() test_facility(85) diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 5e5536f586d0..668dd3e9435a 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -22,7 +22,6 @@ #define MACHINE_FLAG_LPAR BIT(2) #define MACHINE_FLAG_DIAG9C BIT(3) #define MACHINE_FLAG_ESOP BIT(4) -#define MACHINE_FLAG_IDTE BIT(5) #define MACHINE_FLAG_TE BIT(11) #define MACHINE_FLAG_TLB_GUEST BIT(14) #define MACHINE_FLAG_SCC BIT(17) @@ -76,7 +75,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_DIAG9C (get_lowcore()->machine_flags & MACHINE_FLAG_DIAG9C) #define MACHINE_HAS_ESOP (get_lowcore()->machine_flags & MACHINE_FLAG_ESOP) -#define MACHINE_HAS_IDTE (get_lowcore()->machine_flags & MACHINE_FLAG_IDTE) #define MACHINE_HAS_TE (get_lowcore()->machine_flags & MACHINE_FLAG_TE) #define MACHINE_HAS_TLB_GUEST (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_GUEST) #define MACHINE_HAS_SCC (get_lowcore()->machine_flags & MACHINE_FLAG_SCC) diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h index 9dfd46dd03c6..4a062317ca71 100644 --- a/arch/s390/include/asm/tlbflush.h +++ b/arch/s390/include/asm/tlbflush.h @@ -2,6 +2,7 @@ #ifndef _S390_TLBFLUSH_H #define _S390_TLBFLUSH_H +#include #include #include #include @@ -52,7 +53,7 @@ static inline void __tlb_flush_mm(struct mm_struct *mm) cpumask_copy(mm_cpumask(mm), &mm->context.cpu_attach_mask); barrier(); gmap_asce = READ_ONCE(mm->context.gmap_asce); - if (MACHINE_HAS_IDTE && gmap_asce != -1UL) { + if (cpu_has_idte() && gmap_asce != -1UL) { if (gmap_asce) __tlb_flush_idte(gmap_asce); __tlb_flush_idte(mm->context.asce); @@ -66,7 +67,7 @@ static inline void __tlb_flush_mm(struct mm_struct *mm) static inline void __tlb_flush_kernel(void) { - if (MACHINE_HAS_IDTE) + if (cpu_has_idte()) __tlb_flush_idte(init_mm.context.asce); else __tlb_flush_global(); diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 73f8824971ac..2af588670228 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -237,8 +237,6 @@ static __init void detect_diag9c(void) static __init void detect_machine_facilities(void) { - if (test_facility(3)) - get_lowcore()->machine_flags |= MACHINE_FLAG_IDTE; if (test_facility(50) && test_facility(73)) { get_lowcore()->machine_flags |= MACHINE_FLAG_TE; system_ctl_set_bit(0, CR0_TRANSACTIONAL_EXECUTION_BIT); diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index 94d927785800..7a2f5effd626 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c @@ -8,6 +8,7 @@ * Janosch Frank */ +#include #include #include #include @@ -135,7 +136,7 @@ EXPORT_SYMBOL_GPL(gmap_create); static void gmap_flush_tlb(struct gmap *gmap) { - if (MACHINE_HAS_IDTE) + if (cpu_has_idte()) __tlb_flush_idte(gmap->asce); else __tlb_flush_global(); @@ -2028,7 +2029,7 @@ static void gmap_pmdp_xchg(struct gmap *gmap, pmd_t *pmdp, pmd_t new, if (MACHINE_HAS_TLB_GUEST) __pmdp_idte(gaddr, (pmd_t *)pmdp, IDTE_GUEST_ASCE, gmap->asce, IDTE_GLOBAL); - else if (MACHINE_HAS_IDTE) + else if (cpu_has_idte()) __pmdp_idte(gaddr, (pmd_t *)pmdp, 0, 0, IDTE_GLOBAL); else __pmdp_csp(pmdp); @@ -2106,7 +2107,7 @@ void gmap_pmdp_idte_local(struct mm_struct *mm, unsigned long vmaddr) if (MACHINE_HAS_TLB_GUEST) __pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE, gmap->asce, IDTE_LOCAL); - else if (MACHINE_HAS_IDTE) + else if (cpu_has_idte()) __pmdp_idte(gaddr, pmdp, 0, 0, IDTE_LOCAL); *pmdp = __pmd(_SEGMENT_ENTRY_EMPTY); } @@ -2139,7 +2140,7 @@ void gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr) if (MACHINE_HAS_TLB_GUEST) __pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE, gmap->asce, IDTE_GLOBAL); - else if (MACHINE_HAS_IDTE) + else if (cpu_has_idte()) __pmdp_idte(gaddr, pmdp, 0, 0, IDTE_GLOBAL); else __pmdp_csp(pmdp); diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c index 3a6041dda17a..348e759840e7 100644 --- a/arch/s390/mm/pageattr.c +++ b/arch/s390/mm/pageattr.c @@ -78,7 +78,7 @@ static void pgt_set(unsigned long *old, unsigned long new, unsigned long addr, } table = (unsigned long *)((unsigned long)old & mask); crdte(*old, new, table, dtt, addr, get_lowcore()->kernel_asce.val); - } else if (MACHINE_HAS_IDTE) { + } else if (cpu_has_idte()) { cspg(old, *old, new); } else { csp((unsigned int *)old + 1, *old, new); diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 03cbe8ce05ca..ee3c4fec5055 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -392,7 +392,7 @@ static inline void pmdp_idte_global(struct mm_struct *mm, mm->context.asce, IDTE_GLOBAL); if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m) gmap_pmdp_idte_global(mm, addr); - } else if (MACHINE_HAS_IDTE) { + } else if (cpu_has_idte()) { __pmdp_idte(addr, pmdp, 0, 0, IDTE_GLOBAL); if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m) gmap_pmdp_idte_global(mm, addr); @@ -519,7 +519,7 @@ static inline void pudp_idte_global(struct mm_struct *mm, if (MACHINE_HAS_TLB_GUEST) __pudp_idte(addr, pudp, IDTE_NODAT | IDTE_GUEST_ASCE, mm->context.asce, IDTE_GLOBAL); - else if (MACHINE_HAS_IDTE) + else if (cpu_has_idte()) __pudp_idte(addr, pudp, 0, 0, IDTE_GLOBAL); else /* -- cgit v1.2.3-59-g8ed1b From b7e81efc2436c553ca29eae5f069480de3d9f975 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:56 +0100 Subject: s390: Static branches for machine features infrastructure Provide infrastructure which allows to generate machine_has_() functions, which are replacing the existing MACHINE_HAS_ macros. Such function usages generate a static branch depending on . The static branch is patched using an alternative. Each correlates with a bit set in the machine_features bit field. If the corresponding bit is set, the branch will be patched. In order to have any effect on branch patching feature bits must be set with set_machine_features() in the decompressor before alternatives patching of the kernel image. It is possible to use clear_machine_feature() and test_machine_feature() for machine features which cannot be completely detected within the decompressor, e.g. if common code command line parameters allow to enable or disable certain features. In such cases test_machine_feature() instead of machine_has_feature() must be used within the kernel. This results in a runtime check and not a static branch. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/alternative.h | 9 ++++- arch/s390/include/asm/machine.h | 76 +++++++++++++++++++++++++++++++++++++ arch/s390/kernel/alternative.c | 7 ++++ 3 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 arch/s390/include/asm/machine.h diff --git a/arch/s390/include/asm/alternative.h b/arch/s390/include/asm/alternative.h index 73e781b56bfe..67abef07ac93 100644 --- a/arch/s390/include/asm/alternative.h +++ b/arch/s390/include/asm/alternative.h @@ -32,8 +32,9 @@ #define ALT_CTX_ALL (ALT_CTX_EARLY | ALT_CTX_LATE) #define ALT_TYPE_FACILITY 0 -#define ALT_TYPE_SPEC 1 -#define ALT_TYPE_LOWCORE 2 +#define ALT_TYPE_FEATURE 1 +#define ALT_TYPE_SPEC 2 +#define ALT_TYPE_LOWCORE 3 #define ALT_DATA_SHIFT 0 #define ALT_TYPE_SHIFT 20 @@ -43,6 +44,10 @@ ALT_TYPE_FACILITY << ALT_TYPE_SHIFT | \ (facility) << ALT_DATA_SHIFT) +#define ALT_FEATURE(feature) (ALT_CTX_EARLY << ALT_CTX_SHIFT | \ + ALT_TYPE_FEATURE << ALT_TYPE_SHIFT | \ + (feature) << ALT_DATA_SHIFT) + #define ALT_SPEC(facility) (ALT_CTX_LATE << ALT_CTX_SHIFT | \ ALT_TYPE_SPEC << ALT_TYPE_SHIFT | \ (facility) << ALT_DATA_SHIFT) diff --git a/arch/s390/include/asm/machine.h b/arch/s390/include/asm/machine.h new file mode 100644 index 000000000000..bbe6c24bfc88 --- /dev/null +++ b/arch/s390/include/asm/machine.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright IBM Corp. 2024 + */ + +#ifndef __ASM_S390_MACHINE_H +#define __ASM_S390_MACHINE_H + +#ifndef __ASSEMBLY__ + +#include +#include + +extern unsigned long machine_features[1]; + +#define MAX_MFEATURE_BIT (sizeof(machine_features) * BITS_PER_BYTE) + +static inline void __set_machine_feature(unsigned int nr, unsigned long *mfeatures) +{ + if (nr >= MAX_MFEATURE_BIT) + return; + __set_bit(nr, mfeatures); +} + +static inline void set_machine_feature(unsigned int nr) +{ + __set_machine_feature(nr, machine_features); +} + +static inline void __clear_machine_feature(unsigned int nr, unsigned long *mfeatures) +{ + if (nr >= MAX_MFEATURE_BIT) + return; + __clear_bit(nr, mfeatures); +} + +static inline void clear_machine_feature(unsigned int nr) +{ + __clear_machine_feature(nr, machine_features); +} + +static bool __test_machine_feature(unsigned int nr, unsigned long *mfeatures) +{ + if (nr >= MAX_MFEATURE_BIT) + return false; + return test_bit(nr, mfeatures); +} + +static bool test_machine_feature(unsigned int nr) +{ + return __test_machine_feature(nr, machine_features); +} + +static __always_inline bool __test_machine_feature_constant(unsigned int nr) +{ + asm goto( + ALTERNATIVE("brcl 15,%l[l_no]", "brcl 0,0", ALT_FEATURE(%[nr])) + : + : [nr] "i" (nr) + : + : l_no); + return true; +l_no: + return false; +} + +#define DEFINE_MACHINE_HAS_FEATURE(name, feature) \ +static __always_inline bool machine_has_##name(void) \ +{ \ + if (!__is_defined(__DECOMPRESSOR) && __builtin_constant_p(feature)) \ + return __test_machine_feature_constant(feature); \ + return test_machine_feature(feature); \ +} + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_S390_MACHINE_H */ diff --git a/arch/s390/kernel/alternative.c b/arch/s390/kernel/alternative.c index 8d5d0de35de0..d3839fc0543d 100644 --- a/arch/s390/kernel/alternative.c +++ b/arch/s390/kernel/alternative.c @@ -5,6 +5,10 @@ #include #include #include +#include +#include + +unsigned long __bootdata_preserved(machine_features[1]); void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsigned int ctx) { @@ -23,6 +27,9 @@ void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsign case ALT_TYPE_FACILITY: replace = test_facility(a->data); break; + case ALT_TYPE_FEATURE: + replace = test_machine_feature(a->data); + break; case ALT_TYPE_SPEC: replace = nobp_enabled(); break; -- cgit v1.2.3-59-g8ed1b From e4da8249cf1e2aac1f2ca3d8bbe6c7589b4a7a13 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:57 +0100 Subject: s390/lowcore: Convert relocated lowcore alternative to machine feature Convert the explicit relocated lowcore alternative type to a more generic machine feature. This only reduces the number of alternative types, but has no impact on code generation. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/ipl_parm.c | 3 ++- arch/s390/boot/startup.c | 1 - arch/s390/boot/vmem.c | 3 ++- arch/s390/include/asm/abs_lowcore.h | 7 ------- arch/s390/include/asm/alternative.h | 4 ---- arch/s390/include/asm/lowcore.h | 7 ++++--- arch/s390/include/asm/machine.h | 6 ++++++ arch/s390/kernel/abs_lowcore.c | 1 - arch/s390/kernel/alternative.c | 3 --- arch/s390/kernel/entry.S | 3 ++- arch/s390/kernel/setup.c | 3 ++- 11 files changed, 18 insertions(+), 23 deletions(-) diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c index d3731f2983b7..13316bfa589c 100644 --- a/arch/s390/boot/ipl_parm.c +++ b/arch/s390/boot/ipl_parm.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -312,7 +313,7 @@ void parse_boot_command_line(void) } #endif if (!strcmp(param, "relocate_lowcore") && test_facility(193)) - relocate_lowcore = 1; + set_machine_feature(MFEATURE_LOWCORE); if (!strcmp(param, "earlyprintk")) boot_earlyprintk = true; if (!strcmp(param, "debug")) diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 72d48e1d67be..f8e6d7eb7cc2 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -34,7 +34,6 @@ unsigned long __bootdata_preserved(max_mappable); unsigned long __bootdata_preserved(page_noexec_mask); unsigned long __bootdata_preserved(segment_noexec_mask); unsigned long __bootdata_preserved(region_noexec_mask); -int __bootdata_preserved(relocate_lowcore); u64 __bootdata_preserved(stfle_fac_list[16]); struct oldmem_data __bootdata_preserved(oldmem_data); diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c index 1e87cffac2f1..1d073acd05a7 100644 --- a/arch/s390/boot/vmem.c +++ b/arch/s390/boot/vmem.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "decompressor.h" #include "boot.h" @@ -517,7 +518,7 @@ void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned l __arch_set_page_dat((void *)swapper_pg_dir, 1UL << CRST_ALLOC_ORDER); __arch_set_page_dat((void *)invalid_pg_dir, 1UL << CRST_ALLOC_ORDER); - if (relocate_lowcore) + if (machine_has_relocated_lowcore()) lowcore_address = LOWCORE_ALT_ADDRESS; /* diff --git a/arch/s390/include/asm/abs_lowcore.h b/arch/s390/include/asm/abs_lowcore.h index 004d17ea05cf..317c07c09ae4 100644 --- a/arch/s390/include/asm/abs_lowcore.h +++ b/arch/s390/include/asm/abs_lowcore.h @@ -25,11 +25,4 @@ static inline void put_abs_lowcore(struct lowcore *lc) put_cpu(); } -extern int relocate_lowcore; - -static inline int have_relocated_lowcore(void) -{ - return relocate_lowcore; -} - #endif /* _ASM_S390_ABS_LOWCORE_H */ diff --git a/arch/s390/include/asm/alternative.h b/arch/s390/include/asm/alternative.h index 67abef07ac93..c7bf60a541e9 100644 --- a/arch/s390/include/asm/alternative.h +++ b/arch/s390/include/asm/alternative.h @@ -34,7 +34,6 @@ #define ALT_TYPE_FACILITY 0 #define ALT_TYPE_FEATURE 1 #define ALT_TYPE_SPEC 2 -#define ALT_TYPE_LOWCORE 3 #define ALT_DATA_SHIFT 0 #define ALT_TYPE_SHIFT 20 @@ -52,9 +51,6 @@ ALT_TYPE_SPEC << ALT_TYPE_SHIFT | \ (facility) << ALT_DATA_SHIFT) -#define ALT_LOWCORE (ALT_CTX_EARLY << ALT_CTX_SHIFT | \ - ALT_TYPE_LOWCORE << ALT_TYPE_SHIFT) - #ifndef __ASSEMBLY__ #include diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 42a092fa1029..60c887cdbaec 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -10,6 +10,7 @@ #define _ASM_S390_LOWCORE_H #include +#include #include #include #include @@ -222,7 +223,7 @@ static __always_inline struct lowcore *get_lowcore(void) if (__is_defined(__DECOMPRESSOR)) return NULL; - asm(ALTERNATIVE("llilh %[lc],0", "llilh %[lc],%[alt]", ALT_LOWCORE) + asm(ALTERNATIVE("llilh %[lc],0", "llilh %[lc],%[alt]", ALT_FEATURE(MFEATURE_LOWCORE)) : [lc] "=d" (lc) : [alt] "i" (LOWCORE_ALT_ADDRESS >> 16)); return lc; @@ -240,13 +241,13 @@ static inline void set_prefix(__u32 address) .macro GET_LC reg ALTERNATIVE "llilh \reg,0", \ __stringify(llilh \reg, LOWCORE_ALT_ADDRESS >> 16), \ - ALT_LOWCORE + ALT_FEATURE(MFEATURE_LOWCORE) .endm .macro STMG_LC start, end, savearea ALTERNATIVE "stmg \start, \end, \savearea", \ __stringify(stmg \start, \end, LOWCORE_ALT_ADDRESS + \savearea), \ - ALT_LOWCORE + ALT_FEATURE(MFEATURE_LOWCORE) .endm #endif /* __ASSEMBLY__ */ diff --git a/arch/s390/include/asm/machine.h b/arch/s390/include/asm/machine.h index bbe6c24bfc88..bc30384d396d 100644 --- a/arch/s390/include/asm/machine.h +++ b/arch/s390/include/asm/machine.h @@ -6,6 +6,10 @@ #ifndef __ASM_S390_MACHINE_H #define __ASM_S390_MACHINE_H +#include + +#define MFEATURE_LOWCORE 0 + #ifndef __ASSEMBLY__ #include @@ -72,5 +76,7 @@ static __always_inline bool machine_has_##name(void) \ return test_machine_feature(feature); \ } +DEFINE_MACHINE_HAS_FEATURE(relocated_lowcore, MFEATURE_LOWCORE) + #endif /* __ASSEMBLY__ */ #endif /* __ASM_S390_MACHINE_H */ diff --git a/arch/s390/kernel/abs_lowcore.c b/arch/s390/kernel/abs_lowcore.c index 88f0b91d7a73..6252b7d115dd 100644 --- a/arch/s390/kernel/abs_lowcore.c +++ b/arch/s390/kernel/abs_lowcore.c @@ -5,7 +5,6 @@ #include unsigned long __bootdata_preserved(__abs_lowcore); -int __bootdata_preserved(relocate_lowcore); int abs_lowcore_map(int cpu, struct lowcore *lc, bool alloc) { diff --git a/arch/s390/kernel/alternative.c b/arch/s390/kernel/alternative.c index d3839fc0543d..2f56649bbde8 100644 --- a/arch/s390/kernel/alternative.c +++ b/arch/s390/kernel/alternative.c @@ -33,9 +33,6 @@ void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsign case ALT_TYPE_SPEC: replace = nobp_enabled(); break; - case ALT_TYPE_LOWCORE: - replace = have_relocated_lowcore(); - break; default: replace = false; } diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 4cc3408c4dac..c328e05b584c 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -29,6 +29,7 @@ #include #include #include +#include _LPP_OFFSET = __LC_LPP @@ -44,7 +45,7 @@ _LPP_OFFSET = __LC_LPP ALTERNATIVE_2 "b \lpswe;nopr", \ ".insn siy,0xeb0000000071,\address,0", ALT_FACILITY(193), \ __stringify(.insn siy,0xeb0000000071,LOWCORE_ALT_ADDRESS+\address,0), \ - ALT_LOWCORE + ALT_FEATURE(MFEATURE_LOWCORE) .endm .macro MBEAR reg, lowcore diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index c9dd34461625..ab8816cf2f8b 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -54,6 +54,7 @@ #include #include +#include #include #include #include @@ -911,7 +912,7 @@ void __init setup_arch(char **cmdline_p) if (!boot_earlyprintk) boot_rb_foreach(print_rb_entry); - if (have_relocated_lowcore()) + if (machine_has_relocated_lowcore()) pr_info("Lowcore relocated to 0x%px\n", get_lowcore()); log_component_list(); -- cgit v1.2.3-59-g8ed1b From a1a8da0dec77e0149b482698a2c1daab3a02ef7a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:58 +0100 Subject: s390/pci: Get rid of MACHINE_HAS_PCI_MIO Remove MACHINE_FLAG_PCI_MIO/MACHINE_HAS_PCI_MIO and implement the identical functionality with set_machine_feature(), clear_machine_feature() and test_machine_feature(). Acked-by: Niklas Schnelle Tested-by: Niklas Schnelle Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/startup.c | 3 +++ arch/s390/include/asm/machine.h | 1 + arch/s390/include/asm/setup.h | 2 -- arch/s390/kernel/early.c | 4 ---- arch/s390/kernel/processor.c | 3 ++- arch/s390/pci/pci.c | 5 +++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index f8e6d7eb7cc2..8081f06ad258 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,8 @@ static void detect_facilities(void) segment_noexec_mask &= ~_SEGMENT_ENTRY_NOEXEC; region_noexec_mask &= ~_REGION_ENTRY_NOEXEC; } + if (IS_ENABLED(CONFIG_PCI) && test_facility(153)) + set_machine_feature(MFEATURE_PCI_MIO); } static int cmma_test_essa(void) diff --git a/arch/s390/include/asm/machine.h b/arch/s390/include/asm/machine.h index bc30384d396d..488e5d641713 100644 --- a/arch/s390/include/asm/machine.h +++ b/arch/s390/include/asm/machine.h @@ -9,6 +9,7 @@ #include #define MFEATURE_LOWCORE 0 +#define MFEATURE_PCI_MIO 1 #ifndef __ASSEMBLY__ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 668dd3e9435a..5844f6e09162 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -25,7 +25,6 @@ #define MACHINE_FLAG_TE BIT(11) #define MACHINE_FLAG_TLB_GUEST BIT(14) #define MACHINE_FLAG_SCC BIT(17) -#define MACHINE_FLAG_PCI_MIO BIT(18) #define LPP_MAGIC BIT(31) #define LPP_PID_MASK _AC(0xffffffff, UL) @@ -78,7 +77,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_TE (get_lowcore()->machine_flags & MACHINE_FLAG_TE) #define MACHINE_HAS_TLB_GUEST (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_GUEST) #define MACHINE_HAS_SCC (get_lowcore()->machine_flags & MACHINE_FLAG_SCC) -#define MACHINE_HAS_PCI_MIO (get_lowcore()->machine_flags & MACHINE_FLAG_PCI_MIO) /* * Console mode. Override with conmode= diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 2af588670228..9e673dab7c11 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -249,10 +249,6 @@ static __init void detect_machine_facilities(void) clock_comparator_max = -1ULL >> 1; system_ctl_set_bit(0, CR0_CLOCK_COMPARATOR_SIGN_BIT); } - if (IS_ENABLED(CONFIG_PCI) && test_facility(153)) { - get_lowcore()->machine_flags |= MACHINE_FLAG_PCI_MIO; - /* the control bit is set during PCI initialization */ - } } static inline void save_vector_registers(void) diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 4c751b6539f8..487c943cbc4c 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -248,7 +249,7 @@ static int __init setup_hwcaps(void) if (cpu_has_gs()) elf_hwcap |= HWCAP_GS; - if (MACHINE_HAS_PCI_MIO) + if (test_machine_feature(MFEATURE_PCI_MIO)) elf_hwcap |= HWCAP_PCI_MIO; /* virtualization support */ diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 88f72745fa59..7410b22f2cf2 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -1073,7 +1074,7 @@ char * __init pcibios_setup(char *str) return NULL; } if (!strcmp(str, "nomio")) { - get_lowcore()->machine_flags &= ~MACHINE_FLAG_PCI_MIO; + clear_machine_feature(MFEATURE_PCI_MIO); return NULL; } if (!strcmp(str, "force_floating")) { @@ -1148,7 +1149,7 @@ static int __init pci_base_init(void) return 0; } - if (MACHINE_HAS_PCI_MIO) { + if (test_machine_feature(MFEATURE_PCI_MIO)) { static_branch_enable(&have_mio); system_ctl_set_bit(2, CR2_MIO_ADDRESSING_BIT); } -- cgit v1.2.3-59-g8ed1b From f931f67cfc274682aecc9f727eecc89779fc47b7 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:48:59 +0100 Subject: s390/time: Convert MACHINE_HAS_SCC to machine_has_scc() Use static branch(es) to implement and use machine_has_scc() instead of a runtime check via MACHINE_HAS_SCC. This comes with a cleanup of early time initialization: the initial tod_clock_base value is now passed via the bootdata mechanism, instead of using absolute lowcore as transport vehicle from the decompressor to the kernel. Also the early tod clock initialization is moved to the decompressor which allows to use a static branch with machine_has_scc() within the kernel. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/head.S | 5 +++-- arch/s390/boot/printk.c | 4 ++-- arch/s390/boot/startup.c | 24 ++++++++++++++++++++++++ arch/s390/include/asm/lowcore.h | 2 +- arch/s390/include/asm/machine.h | 2 ++ arch/s390/include/asm/setup.h | 2 -- arch/s390/include/asm/timex.h | 5 +++-- arch/s390/kernel/asm-offsets.c | 1 - arch/s390/kernel/early.c | 22 ---------------------- arch/s390/kernel/head64.S | 4 +--- arch/s390/kernel/time.c | 4 ++-- 11 files changed, 38 insertions(+), 37 deletions(-) diff --git a/arch/s390/boot/head.S b/arch/s390/boot/head.S index 0a47b16f6412..fe68c9253ea2 100644 --- a/arch/s390/boot/head.S +++ b/arch/s390/boot/head.S @@ -254,8 +254,9 @@ SYM_CODE_START_LOCAL(startup_normal) xc 0xf00(256),0xf00 larl %r13,.Lctl lctlg %c0,%c15,0(%r13) # load control registers - stcke __LC_BOOT_CLOCK - mvc __LC_LAST_UPDATE_CLOCK(8),__LC_BOOT_CLOCK+1 + larl %r13,tod_clock_base + stcke 0(%r13) + mvc __LC_LAST_UPDATE_CLOCK(8),1(%r13) larl %r13,6f spt 0(%r13) mvc __LC_LAST_UPDATE_TIMER(8),0(%r13) diff --git a/arch/s390/boot/printk.c b/arch/s390/boot/printk.c index b4c66fa667d5..8cf6331bc060 100644 --- a/arch/s390/boot/printk.c +++ b/arch/s390/boot/printk.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include "boot.h" @@ -199,8 +200,7 @@ static void boot_console_earlyprintk(const char *buf) static char *add_timestamp(char *buf) { #ifdef CONFIG_PRINTK_TIME - union tod_clock *boot_clock = (union tod_clock *)&get_lowcore()->boot_clock; - unsigned long ns = tod_to_ns(get_tod_clock() - boot_clock->tod); + unsigned long ns = tod_to_ns(__get_tod_clock_monotonic()); char ts[MAX_NUMLEN]; *buf++ = '['; diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 8081f06ad258..1c7367a338cd 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,8 @@ unsigned long __bootdata_preserved(max_mappable); unsigned long __bootdata_preserved(page_noexec_mask); unsigned long __bootdata_preserved(segment_noexec_mask); unsigned long __bootdata_preserved(region_noexec_mask); +union tod_clock __bootdata_preserved(tod_clock_base); +u64 __bootdata_preserved(clock_comparator_max) = -1UL; u64 __bootdata_preserved(stfle_fac_list[16]); struct oldmem_data __bootdata_preserved(oldmem_data); @@ -46,6 +49,20 @@ void error(char *x) disabled_wait(); } +static void reset_tod_clock(void) +{ + union tod_clock clk; + + if (store_tod_clock_ext_cc(&clk) == 0) + return; + /* TOD clock not running. Set the clock to Unix Epoch. */ + if (set_tod_clock(TOD_UNIX_EPOCH) || store_tod_clock_ext_cc(&clk)) + disabled_wait(); + memset(&tod_clock_base, 0, sizeof(tod_clock_base)); + tod_clock_base.tod = TOD_UNIX_EPOCH; + get_lowcore()->last_update_clock = TOD_UNIX_EPOCH; +} + static void detect_facilities(void) { if (cpu_has_edat1()) @@ -60,6 +77,13 @@ static void detect_facilities(void) } if (IS_ENABLED(CONFIG_PCI) && test_facility(153)) set_machine_feature(MFEATURE_PCI_MIO); + reset_tod_clock(); + if (test_facility(139) && (tod_clock_base.tod >> 63)) { + /* Enable signed clock comparator comparisons */ + set_machine_feature(MFEATURE_SCC); + clock_comparator_max = -1UL >> 1; + local_ctl_set_bit(0, CR0_CLOCK_COMPARATOR_SIGN_BIT); + } } static int cmma_test_essa(void) diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 60c887cdbaec..8067edd120eb 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -127,7 +127,7 @@ struct lowcore { __u64 int_clock; /* 0x0318 */ __u8 pad_0x0320[0x0328-0x0320]; /* 0x0320 */ __u64 clock_comparator; /* 0x0328 */ - __u64 boot_clock[2]; /* 0x0330 */ + __u8 pad_0x0330[0x0340-0x0330]; /* 0x0330 */ /* Current process. */ __u64 current_task; /* 0x0340 */ diff --git a/arch/s390/include/asm/machine.h b/arch/s390/include/asm/machine.h index 488e5d641713..e0a0e4121d08 100644 --- a/arch/s390/include/asm/machine.h +++ b/arch/s390/include/asm/machine.h @@ -10,6 +10,7 @@ #define MFEATURE_LOWCORE 0 #define MFEATURE_PCI_MIO 1 +#define MFEATURE_SCC 2 #ifndef __ASSEMBLY__ @@ -78,6 +79,7 @@ static __always_inline bool machine_has_##name(void) \ } DEFINE_MACHINE_HAS_FEATURE(relocated_lowcore, MFEATURE_LOWCORE) +DEFINE_MACHINE_HAS_FEATURE(scc, MFEATURE_SCC) #endif /* __ASSEMBLY__ */ #endif /* __ASM_S390_MACHINE_H */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 5844f6e09162..b1f6ea1e000a 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -24,7 +24,6 @@ #define MACHINE_FLAG_ESOP BIT(4) #define MACHINE_FLAG_TE BIT(11) #define MACHINE_FLAG_TLB_GUEST BIT(14) -#define MACHINE_FLAG_SCC BIT(17) #define LPP_MAGIC BIT(31) #define LPP_PID_MASK _AC(0xffffffff, UL) @@ -76,7 +75,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_ESOP (get_lowcore()->machine_flags & MACHINE_FLAG_ESOP) #define MACHINE_HAS_TE (get_lowcore()->machine_flags & MACHINE_FLAG_TE) #define MACHINE_HAS_TLB_GUEST (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_GUEST) -#define MACHINE_HAS_SCC (get_lowcore()->machine_flags & MACHINE_FLAG_SCC) /* * Console mode. Override with conmode= diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index a9460bd6555b..bed8d0b5a282 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -13,6 +13,7 @@ #include #include #include +#include #include /* The value of the TOD clock for 1.1.1970. */ @@ -267,7 +268,7 @@ static __always_inline u128 eitod_to_ns(u128 todval) */ static inline int tod_after(unsigned long a, unsigned long b) { - if (MACHINE_HAS_SCC) + if (machine_has_scc()) return (long) a > (long) b; return a > b; } @@ -281,7 +282,7 @@ static inline int tod_after(unsigned long a, unsigned long b) */ static inline int tod_after_eq(unsigned long a, unsigned long b) { - if (MACHINE_HAS_SCC) + if (machine_has_scc()) return (long) a >= (long) b; return a >= b; } diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 36709112ae7a..1242e7435647 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -122,7 +122,6 @@ int main(void) OFFSET(__LC_LAST_UPDATE_TIMER, lowcore, last_update_timer); OFFSET(__LC_LAST_UPDATE_CLOCK, lowcore, last_update_clock); OFFSET(__LC_INT_CLOCK, lowcore, int_clock); - OFFSET(__LC_BOOT_CLOCK, lowcore, boot_clock); OFFSET(__LC_CURRENT, lowcore, current_task); OFFSET(__LC_KERNEL_STACK, lowcore, kernel_stack); OFFSET(__LC_ASYNC_STACK, lowcore, async_stack); diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 9e673dab7c11..708f158cc60e 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -64,21 +64,6 @@ static void __init kasan_early_init(void) #endif } -static void __init reset_tod_clock(void) -{ - union tod_clock clk; - - if (store_tod_clock_ext_cc(&clk) == 0) - return; - /* TOD clock not running. Set the clock to Unix Epoch. */ - if (set_tod_clock(TOD_UNIX_EPOCH) || store_tod_clock_ext_cc(&clk)) - disabled_wait(); - - memset(&tod_clock_base, 0, sizeof(tod_clock_base)); - tod_clock_base.tod = TOD_UNIX_EPOCH; - get_lowcore()->last_update_clock = TOD_UNIX_EPOCH; -} - /* * Initialize storage key for kernel pages */ @@ -243,12 +228,6 @@ static __init void detect_machine_facilities(void) } if (test_facility(129)) system_ctl_set_bit(0, CR0_VECTOR_BIT); - if (test_facility(139) && (tod_clock_base.tod >> 63)) { - /* Enabled signed clock comparator comparisons */ - get_lowcore()->machine_flags |= MACHINE_FLAG_SCC; - clock_comparator_max = -1ULL >> 1; - system_ctl_set_bit(0, CR0_CLOCK_COMPARATOR_SIGN_BIT); - } } static inline void save_vector_registers(void) @@ -286,7 +265,6 @@ static void __init sort_amode31_extable(void) void __init startup_init(void) { kasan_early_init(); - reset_tod_clock(); time_early_init(); init_kernel_storage_key(); lockdep_off(); diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 396034b2fe67..7edb9ded199c 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -18,12 +18,10 @@ __HEAD SYM_CODE_START(startup_continue) - larl %r1,tod_clock_base - GET_LC %r2 - mvc 0(16,%r1),__LC_BOOT_CLOCK(%r2) # # Setup stack # + GET_LC %r2 larl %r14,init_task stg %r14,__LC_CURRENT(%r2) larl %r15,init_thread_union+STACK_INIT_OFFSET diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index e9f47c3a6197..ac58b1db40e6 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -54,10 +54,10 @@ #include #include "entry.h" -union tod_clock tod_clock_base __section(".data"); +union tod_clock __bootdata_preserved(tod_clock_base); EXPORT_SYMBOL_GPL(tod_clock_base); -u64 clock_comparator_max = -1ULL; +u64 __bootdata_preserved(clock_comparator_max); EXPORT_SYMBOL_GPL(clock_comparator_max); static DEFINE_PER_CPU(struct clock_event_device, comparators); -- cgit v1.2.3-59-g8ed1b From 17d3804808091e3942d2744dc8155a3a918d88c3 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:49:00 +0100 Subject: s390/tlb: Convert MACHINE_HAS_TLB_GUEST to machine_has_tlb_guest() Use static branch(es) to implement and use machine_has_tlb_guest() instead of a runtime check via MACHINE_HAS_TLB_GUEST. Also add sclp_early_detect_machine_features() in order to allow for feature detection from the decompressor. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/startup.c | 1 + arch/s390/include/asm/machine.h | 2 ++ arch/s390/include/asm/sclp.h | 1 + arch/s390/include/asm/setup.h | 2 -- arch/s390/include/asm/tlbflush.h | 3 ++- arch/s390/kvm/kvm-s390.c | 3 ++- arch/s390/mm/gmap.c | 7 ++++--- arch/s390/mm/pgtable.c | 13 +++++++------ drivers/s390/char/sclp_early.c | 2 -- drivers/s390/char/sclp_early_core.c | 11 +++++++++++ 10 files changed, 30 insertions(+), 15 deletions(-) diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 1c7367a338cd..4ef2622f3d30 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -482,6 +482,7 @@ void startup_kernel(void) read_ipl_report(); sclp_early_read_info(); + sclp_early_detect_machine_features(); detect_facilities(); cmma_init(); sanitize_prot_virt_host(); diff --git a/arch/s390/include/asm/machine.h b/arch/s390/include/asm/machine.h index e0a0e4121d08..33cb4403fc82 100644 --- a/arch/s390/include/asm/machine.h +++ b/arch/s390/include/asm/machine.h @@ -11,6 +11,7 @@ #define MFEATURE_LOWCORE 0 #define MFEATURE_PCI_MIO 1 #define MFEATURE_SCC 2 +#define MFEATURE_TLB_GUEST 3 #ifndef __ASSEMBLY__ @@ -80,6 +81,7 @@ static __always_inline bool machine_has_##name(void) \ DEFINE_MACHINE_HAS_FEATURE(relocated_lowcore, MFEATURE_LOWCORE) DEFINE_MACHINE_HAS_FEATURE(scc, MFEATURE_SCC) +DEFINE_MACHINE_HAS_FEATURE(tlb_guest, MFEATURE_TLB_GUEST) #endif /* __ASSEMBLY__ */ #endif /* __ASM_S390_MACHINE_H */ diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index 18f37dff03c9..1e62919bacf4 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -168,6 +168,7 @@ int sclp_early_read_storage_info(void); int sclp_early_get_core_info(struct sclp_core_info *info); void sclp_early_get_ipl_info(struct sclp_ipl_info *info); void sclp_early_detect(void); +void sclp_early_detect_machine_features(void); void sclp_early_printk(const char *s); void __sclp_early_printk(const char *s, unsigned int len); void sclp_emergency_printk(const char *s); diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index b1f6ea1e000a..bb9d701ec9a6 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -23,7 +23,6 @@ #define MACHINE_FLAG_DIAG9C BIT(3) #define MACHINE_FLAG_ESOP BIT(4) #define MACHINE_FLAG_TE BIT(11) -#define MACHINE_FLAG_TLB_GUEST BIT(14) #define LPP_MAGIC BIT(31) #define LPP_PID_MASK _AC(0xffffffff, UL) @@ -74,7 +73,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_DIAG9C (get_lowcore()->machine_flags & MACHINE_FLAG_DIAG9C) #define MACHINE_HAS_ESOP (get_lowcore()->machine_flags & MACHINE_FLAG_ESOP) #define MACHINE_HAS_TE (get_lowcore()->machine_flags & MACHINE_FLAG_TE) -#define MACHINE_HAS_TLB_GUEST (get_lowcore()->machine_flags & MACHINE_FLAG_TLB_GUEST) /* * Console mode. Override with conmode= diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h index 4a062317ca71..75491baa2197 100644 --- a/arch/s390/include/asm/tlbflush.h +++ b/arch/s390/include/asm/tlbflush.h @@ -6,6 +6,7 @@ #include #include #include +#include /* * Flush all TLB entries on the local CPU. @@ -23,7 +24,7 @@ static inline void __tlb_flush_idte(unsigned long asce) unsigned long opt; opt = IDTE_PTOA; - if (MACHINE_HAS_TLB_GUEST) + if (machine_has_tlb_guest()) opt |= IDTE_GUEST_ASCE; /* Global TLB flush for the mm */ asm volatile("idte 0,%1,%0" : : "a" (opt), "a" (asce) : "cc"); diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 703a6594cfaf..df21ea6fbd59 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -3397,7 +3398,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) /* we emulate STHYI in kvm */ set_kvm_facility(kvm->arch.model.fac_mask, 74); set_kvm_facility(kvm->arch.model.fac_list, 74); - if (MACHINE_HAS_TLB_GUEST) { + if (machine_has_tlb_guest()) { set_kvm_facility(kvm->arch.model.fac_mask, 147); set_kvm_facility(kvm->arch.model.fac_list, 147); } diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index 7a2f5effd626..0d7cce4f3e83 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -2026,7 +2027,7 @@ static void gmap_pmdp_xchg(struct gmap *gmap, pmd_t *pmdp, pmd_t new, gaddr &= HPAGE_MASK; pmdp_notify_gmap(gmap, pmdp, gaddr); new = clear_pmd_bit(new, __pgprot(_SEGMENT_ENTRY_GMAP_IN)); - if (MACHINE_HAS_TLB_GUEST) + if (machine_has_tlb_guest()) __pmdp_idte(gaddr, (pmd_t *)pmdp, IDTE_GUEST_ASCE, gmap->asce, IDTE_GLOBAL); else if (cpu_has_idte()) @@ -2104,7 +2105,7 @@ void gmap_pmdp_idte_local(struct mm_struct *mm, unsigned long vmaddr) WARN_ON(pmd_val(*pmdp) & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | _SEGMENT_ENTRY_GMAP_UC | _SEGMENT_ENTRY)); - if (MACHINE_HAS_TLB_GUEST) + if (machine_has_tlb_guest()) __pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE, gmap->asce, IDTE_LOCAL); else if (cpu_has_idte()) @@ -2137,7 +2138,7 @@ void gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr) WARN_ON(pmd_val(*pmdp) & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | _SEGMENT_ENTRY_GMAP_UC | _SEGMENT_ENTRY)); - if (MACHINE_HAS_TLB_GUEST) + if (machine_has_tlb_guest()) __pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE, gmap->asce, IDTE_GLOBAL); else if (cpu_has_idte()) diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index ee3c4fec5055..f6712781d8a1 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -24,6 +24,7 @@ #include #include #include +#include pgprot_t pgprot_writecombine(pgprot_t prot) { @@ -50,7 +51,7 @@ static inline void ptep_ipte_local(struct mm_struct *mm, unsigned long addr, { unsigned long opt, asce; - if (MACHINE_HAS_TLB_GUEST) { + if (machine_has_tlb_guest()) { opt = 0; asce = READ_ONCE(mm->context.gmap_asce); if (asce == 0UL || nodat) @@ -70,7 +71,7 @@ static inline void ptep_ipte_global(struct mm_struct *mm, unsigned long addr, { unsigned long opt, asce; - if (MACHINE_HAS_TLB_GUEST) { + if (machine_has_tlb_guest()) { opt = 0; asce = READ_ONCE(mm->context.gmap_asce); if (asce == 0UL || nodat) @@ -375,7 +376,7 @@ void ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, static inline void pmdp_idte_local(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp) { - if (MACHINE_HAS_TLB_GUEST) + if (machine_has_tlb_guest()) __pmdp_idte(addr, pmdp, IDTE_NODAT | IDTE_GUEST_ASCE, mm->context.asce, IDTE_LOCAL); else @@ -387,7 +388,7 @@ static inline void pmdp_idte_local(struct mm_struct *mm, static inline void pmdp_idte_global(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp) { - if (MACHINE_HAS_TLB_GUEST) { + if (machine_has_tlb_guest()) { __pmdp_idte(addr, pmdp, IDTE_NODAT | IDTE_GUEST_ASCE, mm->context.asce, IDTE_GLOBAL); if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m) @@ -506,7 +507,7 @@ EXPORT_SYMBOL(pmdp_xchg_lazy); static inline void pudp_idte_local(struct mm_struct *mm, unsigned long addr, pud_t *pudp) { - if (MACHINE_HAS_TLB_GUEST) + if (machine_has_tlb_guest()) __pudp_idte(addr, pudp, IDTE_NODAT | IDTE_GUEST_ASCE, mm->context.asce, IDTE_LOCAL); else @@ -516,7 +517,7 @@ static inline void pudp_idte_local(struct mm_struct *mm, static inline void pudp_idte_global(struct mm_struct *mm, unsigned long addr, pud_t *pudp) { - if (MACHINE_HAS_TLB_GUEST) + if (machine_has_tlb_guest()) __pudp_idte(addr, pudp, IDTE_NODAT | IDTE_GUEST_ASCE, mm->context.asce, IDTE_GLOBAL); else if (cpu_has_idte()) diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index d9d6edaf8de8..fc83f157c4e4 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -52,8 +52,6 @@ static void __init sclp_early_facilities_detect(void) sclp.has_zpci_lsi = !!(sccb->fac118 & 0x01); if (sccb->fac85 & 0x02) get_lowcore()->machine_flags |= MACHINE_FLAG_ESOP; - if (sccb->fac91 & 0x40) - get_lowcore()->machine_flags |= MACHINE_FLAG_TLB_GUEST; sclp.has_diag204_bif = !!(sccb->fac98 & 0x80); sclp.has_diag310 = !!(sccb->fac91 & 0x80); if (sccb->cpuoff > 134) { diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c index 5a5383cceb6f..d03ad01082d0 100644 --- a/drivers/s390/char/sclp_early_core.c +++ b/drivers/s390/char/sclp_early_core.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "sclp.h" #include "sclp_rw.h" @@ -335,6 +336,16 @@ int __init sclp_early_get_hsa_size(unsigned long *hsa_size) return 0; } +void __init sclp_early_detect_machine_features(void) +{ + struct read_info_sccb *sccb = &sclp_info_sccb; + + if (!sclp_info_sccb_valid) + return; + if (sccb->fac91 & 0x40) + set_machine_feature(MFEATURE_TLB_GUEST); +} + #define SCLP_STORAGE_INFO_FACILITY 0x0000400000000000UL void __weak __init add_physmem_online_range(u64 start, u64 end) {} -- cgit v1.2.3-59-g8ed1b From e82462fbb2cffbae0bf1b8bb15924cb18dba06a7 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:49:01 +0100 Subject: s390/tx: Convert MACHINE_HAS_TE to machine_has_tx() Use static branch(es) to implement and use machine_has_tx() instead of a runtime check with MACHINE_HAS_TE. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/startup.c | 4 ++++ arch/s390/include/asm/machine.h | 2 ++ arch/s390/include/asm/setup.h | 2 -- arch/s390/kernel/early.c | 4 ---- arch/s390/kernel/processor.c | 2 +- arch/s390/kernel/ptrace.c | 9 +++++---- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 4ef2622f3d30..50ae83aaef16 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -84,6 +84,10 @@ static void detect_facilities(void) clock_comparator_max = -1UL >> 1; local_ctl_set_bit(0, CR0_CLOCK_COMPARATOR_SIGN_BIT); } + if (test_facility(50) && test_facility(73)) { + set_machine_feature(MFEATURE_TX); + local_ctl_set_bit(0, CR0_TRANSACTIONAL_EXECUTION_BIT); + } } static int cmma_test_essa(void) diff --git a/arch/s390/include/asm/machine.h b/arch/s390/include/asm/machine.h index 33cb4403fc82..c31682d6c35d 100644 --- a/arch/s390/include/asm/machine.h +++ b/arch/s390/include/asm/machine.h @@ -12,6 +12,7 @@ #define MFEATURE_PCI_MIO 1 #define MFEATURE_SCC 2 #define MFEATURE_TLB_GUEST 3 +#define MFEATURE_TX 4 #ifndef __ASSEMBLY__ @@ -82,6 +83,7 @@ static __always_inline bool machine_has_##name(void) \ DEFINE_MACHINE_HAS_FEATURE(relocated_lowcore, MFEATURE_LOWCORE) DEFINE_MACHINE_HAS_FEATURE(scc, MFEATURE_SCC) DEFINE_MACHINE_HAS_FEATURE(tlb_guest, MFEATURE_TLB_GUEST) +DEFINE_MACHINE_HAS_FEATURE(tx, MFEATURE_TX) #endif /* __ASSEMBLY__ */ #endif /* __ASM_S390_MACHINE_H */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index bb9d701ec9a6..7762fb342c39 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -22,7 +22,6 @@ #define MACHINE_FLAG_LPAR BIT(2) #define MACHINE_FLAG_DIAG9C BIT(3) #define MACHINE_FLAG_ESOP BIT(4) -#define MACHINE_FLAG_TE BIT(11) #define LPP_MAGIC BIT(31) #define LPP_PID_MASK _AC(0xffffffff, UL) @@ -72,7 +71,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_DIAG9C (get_lowcore()->machine_flags & MACHINE_FLAG_DIAG9C) #define MACHINE_HAS_ESOP (get_lowcore()->machine_flags & MACHINE_FLAG_ESOP) -#define MACHINE_HAS_TE (get_lowcore()->machine_flags & MACHINE_FLAG_TE) /* * Console mode. Override with conmode= diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 708f158cc60e..cc4e3d4dc55f 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -222,10 +222,6 @@ static __init void detect_diag9c(void) static __init void detect_machine_facilities(void) { - if (test_facility(50) && test_facility(73)) { - get_lowcore()->machine_flags |= MACHINE_FLAG_TE; - system_ctl_set_bit(0, CR0_TRANSACTIONAL_EXECUTION_BIT); - } if (test_facility(129)) system_ctl_set_bit(0, CR0_VECTOR_BIT); } diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 487c943cbc4c..6594ded7b722 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -218,7 +218,7 @@ static int __init setup_hwcaps(void) elf_hwcap |= HWCAP_HIGH_GPRS; /* transactional execution */ - if (MACHINE_HAS_TE) + if (machine_has_tx()) elf_hwcap |= HWCAP_TE; /* vector */ diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 9ed3017bb968..e2acbbadc75e 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "entry.h" @@ -61,7 +62,7 @@ void update_cr_regs(struct task_struct *task) cr0_new = cr0_old; cr2_new = cr2_old; /* Take care of the enable/disable of transactional execution. */ - if (MACHINE_HAS_TE) { + if (machine_has_tx()) { /* Set or clear transaction execution TXC bit 8. */ cr0_new.tcx = 1; if (task->thread.per_flags & PER_FLAG_NO_TE) @@ -471,18 +472,18 @@ long arch_ptrace(struct task_struct *child, long request, case PTRACE_GET_LAST_BREAK: return put_user(child->thread.last_break, (unsigned long __user *)data); case PTRACE_ENABLE_TE: - if (!MACHINE_HAS_TE) + if (!machine_has_tx()) return -EIO; child->thread.per_flags &= ~PER_FLAG_NO_TE; return 0; case PTRACE_DISABLE_TE: - if (!MACHINE_HAS_TE) + if (!machine_has_tx()) return -EIO; child->thread.per_flags |= PER_FLAG_NO_TE; child->thread.per_flags &= ~PER_FLAG_TE_ABORT_RAND; return 0; case PTRACE_TE_ABORT_RAND: - if (!MACHINE_HAS_TE || (child->thread.per_flags & PER_FLAG_NO_TE)) + if (!machine_has_tx() || (child->thread.per_flags & PER_FLAG_NO_TE)) return -EIO; switch (data) { case 0UL: -- cgit v1.2.3-59-g8ed1b From aaab4a4ff3220ef4c3bd7d23c5017e5eabde8aa5 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:49:02 +0100 Subject: s390/kvm: Convert MACHINE_HAS_ESOP to machine_has_esop() Use static branch(es) to implement and use machine_has_esop() instead of a runtime check via MACHINE_HAS_ESOP. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/machine.h | 2 ++ arch/s390/include/asm/setup.h | 2 -- arch/s390/kvm/kvm-s390.c | 10 +++++----- arch/s390/mm/pgtable.c | 4 ++-- drivers/s390/char/sclp_early.c | 2 -- drivers/s390/char/sclp_early_core.c | 2 ++ 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/s390/include/asm/machine.h b/arch/s390/include/asm/machine.h index c31682d6c35d..dd61146d0a8d 100644 --- a/arch/s390/include/asm/machine.h +++ b/arch/s390/include/asm/machine.h @@ -13,6 +13,7 @@ #define MFEATURE_SCC 2 #define MFEATURE_TLB_GUEST 3 #define MFEATURE_TX 4 +#define MFEATURE_ESOP 5 #ifndef __ASSEMBLY__ @@ -84,6 +85,7 @@ DEFINE_MACHINE_HAS_FEATURE(relocated_lowcore, MFEATURE_LOWCORE) DEFINE_MACHINE_HAS_FEATURE(scc, MFEATURE_SCC) DEFINE_MACHINE_HAS_FEATURE(tlb_guest, MFEATURE_TLB_GUEST) DEFINE_MACHINE_HAS_FEATURE(tx, MFEATURE_TX) +DEFINE_MACHINE_HAS_FEATURE(esop, MFEATURE_ESOP) #endif /* __ASSEMBLY__ */ #endif /* __ASM_S390_MACHINE_H */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 7762fb342c39..a90260f80f62 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -21,7 +21,6 @@ #define MACHINE_FLAG_KVM BIT(1) #define MACHINE_FLAG_LPAR BIT(2) #define MACHINE_FLAG_DIAG9C BIT(3) -#define MACHINE_FLAG_ESOP BIT(4) #define LPP_MAGIC BIT(31) #define LPP_PID_MASK _AC(0xffffffff, UL) @@ -70,7 +69,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_IS_LPAR (get_lowcore()->machine_flags & MACHINE_FLAG_LPAR) #define MACHINE_HAS_DIAG9C (get_lowcore()->machine_flags & MACHINE_FLAG_DIAG9C) -#define MACHINE_HAS_ESOP (get_lowcore()->machine_flags & MACHINE_FLAG_ESOP) /* * Console mode. Override with conmode= diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index df21ea6fbd59..2bba097f7cb0 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -445,13 +445,13 @@ static void __init kvm_s390_cpu_feat_init(void) if (test_facility(201)) /* PFCR */ pfcr_query(&kvm_s390_available_subfunc.pfcr); - if (MACHINE_HAS_ESOP) + if (machine_has_esop()) allow_cpu_feat(KVM_S390_VM_CPU_FEAT_ESOP); /* * We need SIE support, ESOP (PROT_READ protection for gmap_shadow), * 64bit SCAO (SCA passthrough) and IDTE (for gmap_shadow unshadowing). */ - if (!sclp.has_sief2 || !MACHINE_HAS_ESOP || !sclp.has_64bscao || + if (!sclp.has_sief2 || !machine_has_esop() || !sclp.has_64bscao || !test_facility(3) || !nested) return; allow_cpu_feat(KVM_S390_VM_CPU_FEAT_SIEF2); @@ -640,7 +640,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = min_t(unsigned int, num_online_cpus(), r); break; case KVM_CAP_S390_COW: - r = MACHINE_HAS_ESOP; + r = machine_has_esop(); break; case KVM_CAP_S390_VECTOR_REGISTERS: r = test_facility(129); @@ -3894,8 +3894,8 @@ static int kvm_s390_vcpu_setup(struct kvm_vcpu *vcpu) kvm_s390_vcpu_setup_model(vcpu); - /* pgste_set_pte has special handling for !MACHINE_HAS_ESOP */ - if (MACHINE_HAS_ESOP) + /* pgste_set_pte has special handling for !machine_has_esop() */ + if (machine_has_esop()) vcpu->arch.sie_block->ecb |= ECB_HOSTPROTINT; if (test_kvm_facility(vcpu->kvm, 9)) vcpu->arch.sie_block->ecb |= ECB_SRSI; diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index f6712781d8a1..e20fd4c14562 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -212,7 +212,7 @@ static inline pgste_t pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry) if ((pte_val(entry) & _PAGE_PRESENT) && (pte_val(entry) & _PAGE_WRITE) && !(pte_val(entry) & _PAGE_INVALID)) { - if (!MACHINE_HAS_ESOP) { + if (!machine_has_esop()) { /* * Without enhanced suppression-on-protection force * the dirty bit on for all writable ptes. @@ -788,7 +788,7 @@ bool ptep_test_and_clear_uc(struct mm_struct *mm, unsigned long addr, pgste = pgste_pte_notify(mm, addr, ptep, pgste); nodat = !!(pgste_val(pgste) & _PGSTE_GPS_NODAT); ptep_ipte_global(mm, addr, ptep, nodat); - if (MACHINE_HAS_ESOP || !(pte_val(pte) & _PAGE_WRITE)) + if (machine_has_esop() || !(pte_val(pte) & _PAGE_WRITE)) pte = set_pte_bit(pte, __pgprot(_PAGE_PROTECT)); else pte = set_pte_bit(pte, __pgprot(_PAGE_INVALID)); diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index fc83f157c4e4..e58a1f8fc673 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -50,8 +50,6 @@ static void __init sclp_early_facilities_detect(void) sclp.has_aeni = !!(sccb->fac118 & 0x20); sclp.has_aisi = !!(sccb->fac118 & 0x10); sclp.has_zpci_lsi = !!(sccb->fac118 & 0x01); - if (sccb->fac85 & 0x02) - get_lowcore()->machine_flags |= MACHINE_FLAG_ESOP; sclp.has_diag204_bif = !!(sccb->fac98 & 0x80); sclp.has_diag310 = !!(sccb->fac91 & 0x80); if (sccb->cpuoff > 134) { diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c index d03ad01082d0..b5bd40f13c75 100644 --- a/drivers/s390/char/sclp_early_core.c +++ b/drivers/s390/char/sclp_early_core.c @@ -342,6 +342,8 @@ void __init sclp_early_detect_machine_features(void) if (!sclp_info_sccb_valid) return; + if (sccb->fac85 & 0x02) + set_machine_feature(MFEATURE_ESOP); if (sccb->fac91 & 0x40) set_machine_feature(MFEATURE_TLB_GUEST); } -- cgit v1.2.3-59-g8ed1b From c275169919d16c1db23324199b00a71e1e6ea950 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:49:03 +0100 Subject: s390/diag: Convert MACHINE_HAS_DIAG9C to machine_has_diag9c() Use static branch(es) to implement and use machine_has_diag9c() instead of a runtime check via MACHINE_HAS_DIAG9C. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/startup.c | 32 ++++++++++++++++++++++++++++++++ arch/s390/include/asm/machine.h | 2 ++ arch/s390/include/asm/setup.h | 3 --- arch/s390/kernel/early.c | 18 ------------------ arch/s390/kernel/smp.c | 3 ++- 5 files changed, 36 insertions(+), 22 deletions(-) diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 50ae83aaef16..41dda285ee2c 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -49,6 +49,37 @@ void error(char *x) disabled_wait(); } +static void detect_diag9c(void) +{ + unsigned long reg1, reg2; + unsigned int cpu; + int rc = 1; + psw_t old; + + cpu = stap(); + asm volatile( + " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" + " epsw %[reg1],%[reg2]\n" + " st %[reg1],0(%[psw_pgm])\n" + " st %[reg2],4(%[psw_pgm])\n" + " larl %[reg1],1f\n" + " stg %[reg1],8(%[psw_pgm])\n" + " diag %[cpu],0,0x9c\n" + " lhi %[rc],0\n" + "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" + : [reg1] "=&d" (reg1), + [reg2] "=&a" (reg2), + [rc] "+&d" (rc), + "+Q" (get_lowcore()->program_new_psw), + "=Q" (old) + : [psw_old] "a" (&old), + [psw_pgm] "a" (&get_lowcore()->program_new_psw), + [cpu] "d" (cpu) + : "cc", "memory"); + if (!rc) + set_machine_feature(MFEATURE_DIAG9C); +} + static void reset_tod_clock(void) { union tod_clock clk; @@ -488,6 +519,7 @@ void startup_kernel(void) sclp_early_read_info(); sclp_early_detect_machine_features(); detect_facilities(); + detect_diag9c(); cmma_init(); sanitize_prot_virt_host(); max_physmem_end = detect_max_physmem_end(); diff --git a/arch/s390/include/asm/machine.h b/arch/s390/include/asm/machine.h index dd61146d0a8d..4a1f1ab1888a 100644 --- a/arch/s390/include/asm/machine.h +++ b/arch/s390/include/asm/machine.h @@ -14,6 +14,7 @@ #define MFEATURE_TLB_GUEST 3 #define MFEATURE_TX 4 #define MFEATURE_ESOP 5 +#define MFEATURE_DIAG9C 6 #ifndef __ASSEMBLY__ @@ -86,6 +87,7 @@ DEFINE_MACHINE_HAS_FEATURE(scc, MFEATURE_SCC) DEFINE_MACHINE_HAS_FEATURE(tlb_guest, MFEATURE_TLB_GUEST) DEFINE_MACHINE_HAS_FEATURE(tx, MFEATURE_TX) DEFINE_MACHINE_HAS_FEATURE(esop, MFEATURE_ESOP) +DEFINE_MACHINE_HAS_FEATURE(diag9c, MFEATURE_DIAG9C) #endif /* __ASSEMBLY__ */ #endif /* __ASM_S390_MACHINE_H */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index a90260f80f62..f465f82a9dca 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -20,7 +20,6 @@ #define MACHINE_FLAG_VM BIT(0) #define MACHINE_FLAG_KVM BIT(1) #define MACHINE_FLAG_LPAR BIT(2) -#define MACHINE_FLAG_DIAG9C BIT(3) #define LPP_MAGIC BIT(31) #define LPP_PID_MASK _AC(0xffffffff, UL) @@ -68,8 +67,6 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_IS_KVM (get_lowcore()->machine_flags & MACHINE_FLAG_KVM) #define MACHINE_IS_LPAR (get_lowcore()->machine_flags & MACHINE_FLAG_LPAR) -#define MACHINE_HAS_DIAG9C (get_lowcore()->machine_flags & MACHINE_FLAG_DIAG9C) - /* * Console mode. Override with conmode= */ diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index cc4e3d4dc55f..59b15f6a0a02 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -203,23 +203,6 @@ static noinline __init void setup_lowcore_early(void) lc->return_mcck_lpswe = gen_lpswe(__LC_RETURN_MCCK_PSW); } -static __init void detect_diag9c(void) -{ - unsigned int cpu_address; - int rc; - - cpu_address = stap(); - diag_stat_inc(DIAG_STAT_X09C); - asm volatile( - " diag %2,0,0x9c\n" - "0: la %0,0\n" - "1:\n" - EX_TABLE(0b,1b) - : "=d" (rc) : "0" (-EOPNOTSUPP), "d" (cpu_address) : "cc"); - if (!rc) - get_lowcore()->machine_flags |= MACHINE_FLAG_DIAG9C; -} - static __init void detect_machine_facilities(void) { if (test_facility(129)) @@ -269,7 +252,6 @@ void __init startup_init(void) detect_machine_type(); setup_arch_string(); setup_boot_command_line(); - detect_diag9c(); detect_machine_facilities(); save_vector_registers(); setup_topology(); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 2bf45d95165b..f2f05c5277f4 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -417,7 +418,7 @@ EXPORT_SYMBOL(arch_vcpu_is_preempted); void notrace smp_yield_cpu(int cpu) { - if (!MACHINE_HAS_DIAG9C) + if (!machine_has_diag9c()) return; diag_stat_inc_norecursion(DIAG_STAT_X09C); asm volatile("diag %0,0,0x9c" -- cgit v1.2.3-59-g8ed1b From 9b06500008d0f73fede024cffe2263b8dc91e30d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:49:04 +0100 Subject: s390/sysinfo: Remove exception handling from __stsi() The exception handling for __stsi() was added in 2001 when it still was possible to run Linux on systems without LPAR hypervisor, and therefore without an stsi instruction. Given that this is not supported anymore remove the exception handling from the __stsi() inline assembly. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/sysinfo.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index a74154c6529e..a592f9509ce8 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -34,10 +34,9 @@ static inline int __stsi(void *sysinfo, int fc, int sel1, int sel2, int *lvl) " lr 0,%[r0]\n" " lr 1,%[r1]\n" " stsi 0(%[sysinfo])\n" - "0: jz 2f\n" - "1: lhi %[rc],%[retval]\n" - "2: lr %[r0],0\n" - EX_TABLE(0b, 1b) + " jz 0f\n" + " lhi %[rc],%[retval]\n" + "0: lr %[r0],0\n" : [r0] "+d" (r0), [rc] "+d" (rc) : [r1] "d" (sel2), [sysinfo] "a" (sysinfo), -- cgit v1.2.3-59-g8ed1b From a130b6d60bd690b6300bb176e08c4cd9b3ac276a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:49:05 +0100 Subject: s390/sysinfo: Cleanup stsi() inline assembly Merge stsi() and __stsi() and cleanup the inline assembly. This involves making use of the flag output constraint. Semantically the result is identical to before. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/sysinfo.c | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index a592f9509ce8..6c5baff46f91 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -22,30 +22,10 @@ #include #include #include +#include int topology_max_mnest; -static inline int __stsi(void *sysinfo, int fc, int sel1, int sel2, int *lvl) -{ - int r0 = (fc << 28) | sel1; - int rc = 0; - - asm volatile( - " lr 0,%[r0]\n" - " lr 1,%[r1]\n" - " stsi 0(%[sysinfo])\n" - " jz 0f\n" - " lhi %[rc],%[retval]\n" - "0: lr %[r0],0\n" - : [r0] "+d" (r0), [rc] "+d" (rc) - : [r1] "d" (sel2), - [sysinfo] "a" (sysinfo), - [retval] "K" (-EOPNOTSUPP) - : "cc", "0", "1", "memory"); - *lvl = ((unsigned int) r0) >> 28; - return rc; -} - /* * stsi - store system information * @@ -54,12 +34,21 @@ static inline int __stsi(void *sysinfo, int fc, int sel1, int sel2, int *lvl) */ int stsi(void *sysinfo, int fc, int sel1, int sel2) { - int lvl, rc; + int r0 = (fc << 28) | sel1; + int cc; - rc = __stsi(sysinfo, fc, sel1, sel2, &lvl); - if (rc) - return rc; - return fc ? 0 : lvl; + asm volatile( + " lr %%r0,%[r0]\n" + " lr %%r1,%[r1]\n" + " stsi %[sysinfo]\n" + " lr %[r0],%%r0\n" + CC_IPM(cc) + : CC_OUT(cc, cc), [r0] "+d" (r0), [sysinfo] "=Q" (*(char *)sysinfo) + : [r1] "d" (sel2) + : CC_CLOBBER_LIST("0", "1", "memory")); + if (cc == 3) + return -EOPNOTSUPP; + return fc ? 0 : (unsigned int)r0 >> 28; } EXPORT_SYMBOL(stsi); -- cgit v1.2.3-59-g8ed1b From 91d6e44221e871c6a2b6c4a67f52b62b36c441a3 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:49:06 +0100 Subject: s390/sysinfo: Move stsi() to header file Move stsi() inline assembly to header file so it is possible to use it also for the decompressor. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/sysinfo.h | 28 +++++++++++++++++++++++++++- arch/s390/kernel/sysinfo.c | 26 -------------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h index edca5a751df4..9088c5267f35 100644 --- a/arch/s390/include/asm/sysinfo.h +++ b/arch/s390/include/asm/sysinfo.h @@ -11,8 +11,34 @@ #ifndef __ASM_S390_SYSINFO_H #define __ASM_S390_SYSINFO_H -#include #include +#include +#include + +/* + * stsi - store system information + * + * Returns the current configuration level if function code 0 was specified. + * Otherwise returns 0 on success or a negative value on error. + */ +static inline int stsi(void *sysinfo, int fc, int sel1, int sel2) +{ + int r0 = (fc << 28) | sel1; + int cc; + + asm volatile( + " lr %%r0,%[r0]\n" + " lr %%r1,%[r1]\n" + " stsi %[sysinfo]\n" + " lr %[r0],%%r0\n" + CC_IPM(cc) + : CC_OUT(cc, cc), [r0] "+d" (r0), [sysinfo] "=Q" (*(char *)sysinfo) + : [r1] "d" (sel2) + : CC_CLOBBER_LIST("0", "1", "memory")); + if (cc == 3) + return -EOPNOTSUPP; + return fc ? 0 : (unsigned int)r0 >> 28; +} struct sysinfo_1_1_1 { unsigned char p:1; diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index 6c5baff46f91..d096a154cc40 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -26,32 +26,6 @@ int topology_max_mnest; -/* - * stsi - store system information - * - * Returns the current configuration level if function code 0 was specified. - * Otherwise returns 0 on success or a negative value on error. - */ -int stsi(void *sysinfo, int fc, int sel1, int sel2) -{ - int r0 = (fc << 28) | sel1; - int cc; - - asm volatile( - " lr %%r0,%[r0]\n" - " lr %%r1,%[r1]\n" - " stsi %[sysinfo]\n" - " lr %[r0],%%r0\n" - CC_IPM(cc) - : CC_OUT(cc, cc), [r0] "+d" (r0), [sysinfo] "=Q" (*(char *)sysinfo) - : [r1] "d" (sel2) - : CC_CLOBBER_LIST("0", "1", "memory")); - if (cc == 3) - return -EOPNOTSUPP; - return fc ? 0 : (unsigned int)r0 >> 28; -} -EXPORT_SYMBOL(stsi); - #ifdef CONFIG_PROC_FS static bool convert_ext_name(unsigned char encoding, char *name, size_t len) -- cgit v1.2.3-59-g8ed1b From 52109a067aaa96474a5b0f12aee60d73cf5f92e1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:49:07 +0100 Subject: s390: Convert MACHINE_IS_[LPAR|VM|KVM], etc, machine_is_[lpar|vm|kvm]() Move machine type detection to the decompressor and use static branches to implement and use machine_is_[lpar|vm|kvm]() instead of a runtime check via MACHINE_IS_[LPAR|VM|KVM]. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/startup.c | 23 +++++++++++++++++++++++ arch/s390/hypfs/hypfs_diag0c.c | 5 +++-- arch/s390/hypfs/hypfs_diag_fs.c | 3 ++- arch/s390/hypfs/hypfs_vm.c | 5 +++-- arch/s390/hypfs/inode.c | 5 +++-- arch/s390/include/asm/appldata.h | 3 ++- arch/s390/include/asm/machine.h | 10 ++++++++++ arch/s390/include/asm/setup.h | 11 ----------- arch/s390/kernel/early.c | 28 ++++------------------------ arch/s390/kernel/ipl.c | 21 +++++++++++---------- arch/s390/kernel/irq.c | 3 ++- arch/s390/kernel/machine_kexec.c | 3 ++- arch/s390/kernel/setup.c | 12 ++++++------ arch/s390/kernel/sysinfo.c | 3 ++- arch/s390/lib/spinlock.c | 7 ++++--- arch/s390/mm/extmem.c | 9 +++++---- drivers/s390/block/dasd.c | 3 ++- drivers/s390/block/dasd_devmap.c | 3 ++- drivers/s390/block/dasd_diag.c | 3 ++- drivers/s390/block/dasd_eckd.c | 3 ++- drivers/s390/char/con3215.c | 3 ++- drivers/s390/char/con3270.c | 3 ++- drivers/s390/char/hmcdrv_ftp.c | 6 ++++-- drivers/s390/char/monreader.c | 3 ++- drivers/s390/char/monwriter.c | 3 ++- drivers/s390/char/raw3270.c | 3 ++- drivers/s390/char/sclp.h | 7 ++++--- drivers/s390/char/sclp_early.c | 2 +- drivers/s390/char/sclp_tty.c | 4 ++-- drivers/s390/char/vmcp.c | 5 +++-- drivers/s390/char/vmlogrdr.c | 3 ++- drivers/s390/char/vmur.c | 3 ++- drivers/s390/cio/device_id.c | 3 ++- drivers/s390/crypto/ap_bus.c | 3 ++- drivers/s390/net/qeth_l2_main.c | 3 ++- drivers/s390/net/smsgiucv.c | 3 ++- drivers/s390/net/smsgiucv_app.c | 3 ++- drivers/tty/hvc/hvc_iucv.c | 7 ++++--- drivers/watchdog/diag288_wdt.c | 7 ++++--- net/iucv/af_iucv.c | 3 ++- net/iucv/iucv.c | 3 ++- 41 files changed, 140 insertions(+), 103 deletions(-) diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 41dda285ee2c..9c4b2b317af2 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,27 @@ void error(char *x) disabled_wait(); } +static char sysinfo_page[PAGE_SIZE] __aligned(PAGE_SIZE); + +static void detect_machine_type(void) +{ + struct sysinfo_3_2_2 *vmms = (struct sysinfo_3_2_2 *)&sysinfo_page; + + /* Check current-configuration-level */ + if (stsi(NULL, 0, 0, 0) <= 2) { + set_machine_feature(MFEATURE_LPAR); + return; + } + /* Get virtual-machine cpu information. */ + if (stsi(vmms, 3, 2, 2) || !vmms->count) + return; + /* Detect known hypervisors */ + if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3)) + set_machine_feature(MFEATURE_KVM); + else if (!memcmp(vmms->vm[0].cpi, "\xa9\x61\xe5\xd4", 4)) + set_machine_feature(MFEATURE_VM); +} + static void detect_diag9c(void) { unsigned long reg1, reg2; @@ -520,6 +542,7 @@ void startup_kernel(void) sclp_early_detect_machine_features(); detect_facilities(); detect_diag9c(); + detect_machine_type(); cmma_init(); sanitize_prot_virt_host(); max_physmem_end = detect_max_physmem_end(); diff --git a/arch/s390/hypfs/hypfs_diag0c.c b/arch/s390/hypfs/hypfs_diag0c.c index 4131f0daa5ea..61220e717af0 100644 --- a/arch/s390/hypfs/hypfs_diag0c.c +++ b/arch/s390/hypfs/hypfs_diag0c.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include "hypfs.h" @@ -107,7 +108,7 @@ static struct hypfs_dbfs_file dbfs_file_0c = { */ int __init hypfs_diag0c_init(void) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return 0; hypfs_dbfs_create_file(&dbfs_file_0c); return 0; @@ -118,7 +119,7 @@ int __init hypfs_diag0c_init(void) */ void hypfs_diag0c_exit(void) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return; hypfs_dbfs_remove_file(&dbfs_file_0c); } diff --git a/arch/s390/hypfs/hypfs_diag_fs.c b/arch/s390/hypfs/hypfs_diag_fs.c index 00a6d370a280..1e17e288cee4 100644 --- a/arch/s390/hypfs/hypfs_diag_fs.c +++ b/arch/s390/hypfs/hypfs_diag_fs.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include "hypfs_diag.h" @@ -382,7 +383,7 @@ static void diag224_delete_name_table(void) int __init __hypfs_diag_fs_init(void) { - if (MACHINE_IS_LPAR) + if (machine_is_lpar()) return diag224_get_name_table(); return 0; } diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c index 3db40ad853e0..4db2895e4da3 100644 --- a/arch/s390/hypfs/hypfs_vm.c +++ b/arch/s390/hypfs/hypfs_vm.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -121,7 +122,7 @@ static struct hypfs_dbfs_file dbfs_file_2fc = { int hypfs_vm_init(void) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return 0; if (diag2fc(0, all_guests, NULL) > 0) diag2fc_guest_query = all_guests; @@ -135,7 +136,7 @@ int hypfs_vm_init(void) void hypfs_vm_exit(void) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return; hypfs_dbfs_remove_file(&dbfs_file_2fc); } diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index d428635abf08..04ea1c03a5ff 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "hypfs.h" @@ -184,7 +185,7 @@ static ssize_t hypfs_write_iter(struct kiocb *iocb, struct iov_iter *from) goto out; } hypfs_delete_tree(sb->s_root); - if (MACHINE_IS_VM) + if (machine_is_vm()) rc = hypfs_vm_create_files(sb->s_root); else rc = hypfs_diag_create_files(sb->s_root); @@ -273,7 +274,7 @@ static int hypfs_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_root = root_dentry = d_make_root(root_inode); if (!root_dentry) return -ENOMEM; - if (MACHINE_IS_VM) + if (machine_is_vm()) rc = hypfs_vm_create_files(root_dentry); else rc = hypfs_diag_create_files(root_dentry); diff --git a/arch/s390/include/asm/appldata.h b/arch/s390/include/asm/appldata.h index a92ebbc7aa7a..99b2902c10fd 100644 --- a/arch/s390/include/asm/appldata.h +++ b/arch/s390/include/asm/appldata.h @@ -9,6 +9,7 @@ #define _ASM_S390_APPLDATA_H #include +#include #include #define APPLDATA_START_INTERVAL_REC 0x80 @@ -48,7 +49,7 @@ static inline int appldata_asm(struct appldata_parameter_list *parm_list, { int ry; - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return -EOPNOTSUPP; parm_list->diag = 0xdc; parm_list->function = fn; diff --git a/arch/s390/include/asm/machine.h b/arch/s390/include/asm/machine.h index 4a1f1ab1888a..54478caa5237 100644 --- a/arch/s390/include/asm/machine.h +++ b/arch/s390/include/asm/machine.h @@ -15,6 +15,9 @@ #define MFEATURE_TX 4 #define MFEATURE_ESOP 5 #define MFEATURE_DIAG9C 6 +#define MFEATURE_VM 7 +#define MFEATURE_KVM 8 +#define MFEATURE_LPAR 9 #ifndef __ASSEMBLY__ @@ -88,6 +91,13 @@ DEFINE_MACHINE_HAS_FEATURE(tlb_guest, MFEATURE_TLB_GUEST) DEFINE_MACHINE_HAS_FEATURE(tx, MFEATURE_TX) DEFINE_MACHINE_HAS_FEATURE(esop, MFEATURE_ESOP) DEFINE_MACHINE_HAS_FEATURE(diag9c, MFEATURE_DIAG9C) +DEFINE_MACHINE_HAS_FEATURE(vm, MFEATURE_VM) +DEFINE_MACHINE_HAS_FEATURE(kvm, MFEATURE_KVM) +DEFINE_MACHINE_HAS_FEATURE(lpar, MFEATURE_LPAR) + +#define machine_is_vm machine_has_vm +#define machine_is_kvm machine_has_kvm +#define machine_is_lpar machine_has_lpar #endif /* __ASSEMBLY__ */ #endif /* __ASM_S390_MACHINE_H */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index f465f82a9dca..031e881b4d88 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -13,13 +13,6 @@ #define PARMAREA 0x10400 #define COMMAND_LINE_SIZE CONFIG_COMMAND_LINE_SIZE -/* - * Machine features detected in early.c - */ - -#define MACHINE_FLAG_VM BIT(0) -#define MACHINE_FLAG_KVM BIT(1) -#define MACHINE_FLAG_LPAR BIT(2) #define LPP_MAGIC BIT(31) #define LPP_PID_MASK _AC(0xffffffff, UL) @@ -63,10 +56,6 @@ extern unsigned long max_mappable; /* The Write Back bit position in the physaddr is given by the SLPC PCI */ extern unsigned long mio_wb_bit_mask; -#define MACHINE_IS_VM (get_lowcore()->machine_flags & MACHINE_FLAG_VM) -#define MACHINE_IS_KVM (get_lowcore()->machine_flags & MACHINE_FLAG_KVM) -#define MACHINE_IS_LPAR (get_lowcore()->machine_flags & MACHINE_FLAG_LPAR) - /* * Console mode. Override with conmode= */ diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 59b15f6a0a02..fc30eb222ee9 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -82,26 +83,6 @@ static noinline __init void init_kernel_storage_key(void) static __initdata char sysinfo_page[PAGE_SIZE] __aligned(PAGE_SIZE); -static noinline __init void detect_machine_type(void) -{ - struct sysinfo_3_2_2 *vmms = (struct sysinfo_3_2_2 *)&sysinfo_page; - - /* Check current-configuration-level */ - if (stsi(NULL, 0, 0, 0) <= 2) { - get_lowcore()->machine_flags |= MACHINE_FLAG_LPAR; - return; - } - /* Get virtual-machine cpu information. */ - if (stsi(vmms, 3, 2, 2) || !vmms->count) - return; - - /* Detect known hypervisors */ - if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3)) - get_lowcore()->machine_flags |= MACHINE_FLAG_KVM; - else if (!memcmp(vmms->vm[0].cpi, "\xa9\x61\xe5\xd4", 4)) - get_lowcore()->machine_flags |= MACHINE_FLAG_VM; -} - /* Remove leading, trailing and double whitespace. */ static inline void strim_all(char *str) { @@ -142,9 +123,9 @@ static noinline __init void setup_arch_string(void) strim_all(hvstr); } else { sprintf(hvstr, "%s", - MACHINE_IS_LPAR ? "LPAR" : - MACHINE_IS_VM ? "z/VM" : - MACHINE_IS_KVM ? "KVM" : "unknown"); + machine_is_lpar() ? "LPAR" : + machine_is_vm() ? "z/VM" : + machine_is_kvm() ? "KVM" : "unknown"); } dump_stack_set_arch_desc("%s (%s)", mstr, hvstr); } @@ -249,7 +230,6 @@ void __init startup_init(void) lockdep_off(); sort_amode31_extable(); setup_lowcore_early(); - detect_machine_type(); setup_arch_string(); setup_boot_command_line(); detect_machine_facilities(); diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 69be2309cde0..8990e2dffcdf 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -685,7 +686,7 @@ static int __init ipl_init(void) goto out; switch (ipl_info.type) { case IPL_TYPE_CCW: - if (MACHINE_IS_VM) + if (machine_is_vm()) rc = sysfs_create_group(&ipl_kset->kobj, &ipl_ccw_attr_group_vm); else @@ -1272,7 +1273,7 @@ static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb) ipb->ccw.flags = IPL_PB0_FLAG_LOADPARM; /* VM PARM */ - if (MACHINE_IS_VM && ipl_block_valid && + if (machine_is_vm() && ipl_block_valid && (ipl_block.ccw.vm_flags & IPL_PB0_CCW_VM_FLAG_VP)) { ipb->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_VP; @@ -1286,7 +1287,7 @@ static int __init reipl_nss_init(void) { int rc; - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return 0; reipl_block_nss = (void *) get_zeroed_page(GFP_KERNEL); @@ -1311,8 +1312,8 @@ static int __init reipl_ccw_init(void) return -ENOMEM; rc = sysfs_create_group(&reipl_kset->kobj, - MACHINE_IS_VM ? &reipl_ccw_attr_group_vm - : &reipl_ccw_attr_group_lpar); + machine_is_vm() ? &reipl_ccw_attr_group_vm + : &reipl_ccw_attr_group_lpar); if (rc) return rc; @@ -1987,7 +1988,7 @@ static void vmcmd_run(struct shutdown_trigger *trigger) static int vmcmd_init(void) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return -EOPNOTSUPP; vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj); if (!vmcmd_kset) @@ -2264,7 +2265,7 @@ static void __init strncpy_skip_quote(char *dst, char *src, int n) static int __init vmcmd_on_reboot_setup(char *str) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return 1; strncpy_skip_quote(vmcmd_on_reboot, str, VMCMD_MAX_SIZE); vmcmd_on_reboot[VMCMD_MAX_SIZE] = 0; @@ -2275,7 +2276,7 @@ __setup("vmreboot=", vmcmd_on_reboot_setup); static int __init vmcmd_on_panic_setup(char *str) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return 1; strncpy_skip_quote(vmcmd_on_panic, str, VMCMD_MAX_SIZE); vmcmd_on_panic[VMCMD_MAX_SIZE] = 0; @@ -2286,7 +2287,7 @@ __setup("vmpanic=", vmcmd_on_panic_setup); static int __init vmcmd_on_halt_setup(char *str) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return 1; strncpy_skip_quote(vmcmd_on_halt, str, VMCMD_MAX_SIZE); vmcmd_on_halt[VMCMD_MAX_SIZE] = 0; @@ -2297,7 +2298,7 @@ __setup("vmhalt=", vmcmd_on_halt_setup); static int __init vmcmd_on_poff_setup(char *str) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return 1; strncpy_skip_quote(vmcmd_on_poff, str, VMCMD_MAX_SIZE); vmcmd_on_poff[VMCMD_MAX_SIZE] = 0; diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index ef7be599e1f7..d0a596f1c2f6 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -164,7 +165,7 @@ void noinstr do_io_irq(struct pt_regs *regs) do_irq_async(regs, THIN_INTERRUPT); else do_irq_async(regs, IO_INTERRUPT); - } while (MACHINE_IS_LPAR && irq_pending(regs)); + } while (machine_is_lpar() && irq_pending(regs)); irq_exit_rcu(); diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index 7962dba7bdea..baeb3dcfc1c8 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -179,7 +180,7 @@ void arch_kexec_unprotect_crashkres(void) static int machine_kexec_prepare_kdump(void) { #ifdef CONFIG_CRASH_DUMP - if (MACHINE_IS_VM) + if (machine_is_vm()) diag10_range(PFN_DOWN(crashk_res.start), PFN_DOWN(crashk_res.end - crashk_res.start + 1)); return 0; diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index ab8816cf2f8b..dc8ccc5e8edf 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -252,7 +252,7 @@ static void __init conmode_default(void) char query_buffer[1024]; char *ptr; - if (MACHINE_IS_VM) { + if (machine_is_vm()) { cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL); console_devno = simple_strtoul(query_buffer + 5, NULL, 16); ptr = strstr(query_buffer, "SUBCHANNEL ="); @@ -290,7 +290,7 @@ static void __init conmode_default(void) SET_CONSOLE_SCLP; #endif } - } else if (MACHINE_IS_KVM) { + } else if (machine_is_kvm()) { if (sclp.has_vt220 && IS_ENABLED(CONFIG_SCLP_VT220_CONSOLE)) SET_CONSOLE_VT220; else if (sclp.has_linemode && IS_ENABLED(CONFIG_SCLP_CONSOLE)) @@ -653,7 +653,7 @@ static void __init reserve_crashkernel(void) return; } - if (!oldmem_data.start && MACHINE_IS_VM) + if (!oldmem_data.start && machine_is_vm()) diag10_range(PFN_DOWN(crash_base), PFN_DOWN(crash_size)); crashk_res.start = crash_base; crashk_res.end = crash_base + crash_size - 1; @@ -899,12 +899,12 @@ void __init setup_arch(char **cmdline_p) /* * print what head.S has found out about the machine */ - if (MACHINE_IS_VM) + if (machine_is_vm()) pr_info("Linux is running as a z/VM " "guest operating system in 64-bit mode\n"); - else if (MACHINE_IS_KVM) + else if (machine_is_kvm()) pr_info("Linux is running under KVM in 64-bit mode\n"); - else if (MACHINE_IS_LPAR) + else if (machine_is_lpar()) pr_info("Linux is running natively in 64-bit mode\n"); else pr_info("Linux is running as a guest in 64-bit mode\n"); diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index d096a154cc40..1ea84e942bd4 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -378,7 +379,7 @@ static struct service_level service_level_vm = { static __init int create_proc_service_level(void) { proc_create_seq("service_levels", 0, NULL, &service_level_seq_ops); - if (MACHINE_IS_VM) + if (machine_is_vm()) register_service_level(&service_level_vm); return 0; } diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index a81a01c44927..9d5669d449f2 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -15,6 +15,7 @@ #include #include #include +#include #include int spin_retry = -1; @@ -212,7 +213,7 @@ static inline void arch_spin_lock_queued(arch_spinlock_t *lp) if (count-- >= 0) continue; count = spin_retry; - if (!MACHINE_IS_LPAR || arch_vcpu_is_preempted(owner - 1)) + if (!machine_is_lpar() || arch_vcpu_is_preempted(owner - 1)) smp_yield_cpu(owner - 1); } @@ -255,7 +256,7 @@ static inline void arch_spin_lock_classic(arch_spinlock_t *lp) if (count-- >= 0) continue; count = spin_retry; - if (!MACHINE_IS_LPAR || arch_vcpu_is_preempted(owner - 1)) + if (!machine_is_lpar() || arch_vcpu_is_preempted(owner - 1)) smp_yield_cpu(owner - 1); } } @@ -337,7 +338,7 @@ void arch_spin_relax(arch_spinlock_t *lp) cpu = READ_ONCE(lp->lock) & _Q_LOCK_CPU_MASK; if (!cpu) return; - if (MACHINE_IS_LPAR && !arch_vcpu_is_preempted(cpu - 1)) + if (machine_is_lpar() && !arch_vcpu_is_preempted(cpu - 1)) return; smp_yield_cpu(cpu - 1); } diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 4692136c0af1..a6b8b8ea9086 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -255,7 +256,7 @@ segment_type (char* name) int rc; struct dcss_segment seg; - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return -ENOSYS; dcss_mkname(name, seg.dcss_name); @@ -418,7 +419,7 @@ segment_load (char *name, int do_nonshared, unsigned long *addr, struct dcss_segment *seg; int rc; - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return -ENOSYS; mutex_lock(&dcss_lock); @@ -540,7 +541,7 @@ segment_unload(char *name) unsigned long dummy; struct dcss_segment *seg; - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return; mutex_lock(&dcss_lock); @@ -572,7 +573,7 @@ segment_save(char *name) char cmd2[80]; int i, response; - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return; mutex_lock(&dcss_lock); diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 3ed642f4f00d..31bfb49588c2 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -3382,7 +3383,7 @@ int dasd_device_is_ro(struct dasd_device *device) struct diag210 diag_data; int rc; - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return 0; ccw_device_get_id(device->cdev, &dev_id); memset(&diag_data, 0, sizeof(diag_data)); diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 71d8fb86139d..3bb69069dfc6 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -234,7 +235,7 @@ static int __init dasd_parse_keyword(char *keyword) return 0; } if (strncmp("nopav", keyword, length) == 0) { - if (MACHINE_IS_VM) + if (machine_is_vm()) pr_info("'nopav' is not supported on z/VM\n"); else { dasd_nopav = 1; diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 26812abddef1..8b39803cf94c 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -654,7 +655,7 @@ static struct dasd_discipline dasd_diag_discipline = { static int __init dasd_diag_init(void) { - if (!MACHINE_IS_VM) { + if (!machine_is_vm()) { pr_info("Discipline %s cannot be used without z/VM\n", dasd_diag_discipline.name); return -ENODEV; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 1ebe589b5185..88fa17aea2ec 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -1953,7 +1954,7 @@ static int dasd_eckd_validate_server(struct dasd_device *device, if (private->uid.type == UA_BASE_PAV_ALIAS || private->uid.type == UA_HYPER_PAV_ALIAS) return 0; - if (dasd_nopav || MACHINE_IS_VM) + if (dasd_nopav || machine_is_vm()) enable_pav = 0; else enable_pav = 1; diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index c763c50d1454..6a61c0a595d9 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -23,6 +23,7 @@ #include #include /* ASYNC_* flags */ #include +#include #include #include #include @@ -907,7 +908,7 @@ static int __init con3215_init(void) return -ENODEV; /* Set the console mode for VM */ - if (MACHINE_IS_VM) { + if (machine_is_vm()) { cpcmd("TERM CONMODE 3215", NULL, 0, NULL); cpcmd("TERM AUTOCR OFF", NULL, 0, NULL); } diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index ae1b9aa3a2b5..1a3190848670 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -2156,7 +2157,7 @@ con3270_init(void) return -ENODEV; /* Set the console mode for VM */ - if (MACHINE_IS_VM) { + if (machine_is_vm()) { cpcmd("TERM CONMODE 3270", NULL, 0, NULL); cpcmd("TERM AUTOCR OFF", NULL, 0, NULL); } diff --git a/drivers/s390/char/hmcdrv_ftp.c b/drivers/s390/char/hmcdrv_ftp.c index 02b6f394aec2..4e3c7ec6749b 100644 --- a/drivers/s390/char/hmcdrv_ftp.c +++ b/drivers/s390/char/hmcdrv_ftp.c @@ -17,6 +17,8 @@ #include #include +#include + #include "hmcdrv_ftp.h" #include "hmcdrv_cache.h" #include "sclp_ftp.h" @@ -308,9 +310,9 @@ int hmcdrv_ftp_startup(void) mutex_lock(&hmcdrv_ftp_mutex); /* block transfers while start-up */ if (hmcdrv_ftp_refcnt == 0) { - if (MACHINE_IS_VM) + if (machine_is_vm()) hmcdrv_ftp_funcs = &hmcdrv_ftp_zvm; - else if (MACHINE_IS_LPAR || MACHINE_IS_KVM) + else if (machine_is_lpar() || machine_is_kvm()) hmcdrv_ftp_funcs = &hmcdrv_ftp_lpar; else rc = -EOPNOTSUPP; diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 7207a7f5842a..2d9886651d9b 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -456,7 +457,7 @@ static int __init mon_init(void) { int rc; - if (!MACHINE_IS_VM) { + if (!machine_is_vm()) { pr_err("The z/VM *MONITOR record device driver cannot be " "loaded without z/VM\n"); return -ENODEV; diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index bc5193d81f9c..0fab1f025a94 100644 --- a/drivers/s390/char/monwriter.c +++ b/drivers/s390/char/monwriter.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -293,7 +294,7 @@ static struct miscdevice mon_dev = { static int __init mon_init(void) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return -ENODEV; /* * misc_register() has to be the last action in module_init(), because diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index ba3d7114b34f..d2ce7f80ae8d 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -618,7 +619,7 @@ static void raw3270_reset_device_cb(struct raw3270_request *rq, void *data) if (rq->rc) { /* Reset command failed. */ rp->state = RAW3270_STATE_INIT; - } else if (MACHINE_IS_VM) { + } else if (machine_is_vm()) { raw3270_size_device_vm(rp); raw3270_size_device_done(rp); } else { diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 07a6e8a7f05a..f7ca6e2f6d18 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -342,21 +343,21 @@ static inline int sclp_service_call(sclp_cmdw_t command, void *sccb) static inline unsigned char sclp_ascebc(unsigned char ch) { - return (MACHINE_IS_VM) ? _ascebc[ch] : _ascebc_500[ch]; + return (machine_is_vm()) ? _ascebc[ch] : _ascebc_500[ch]; } /* translate string from EBCDIC to ASCII */ static inline void sclp_ebcasc_str(char *str, int nr) { - (MACHINE_IS_VM) ? EBCASC(str, nr) : EBCASC_500(str, nr); + (machine_is_vm()) ? EBCASC(str, nr) : EBCASC_500(str, nr); } /* translate string from ASCII to EBCDIC */ static inline void sclp_ascebc_str(char *str, int nr) { - (MACHINE_IS_VM) ? ASCEBC(str, nr) : ASCEBC_500(str, nr); + (machine_is_vm()) ? ASCEBC(str, nr) : ASCEBC_500(str, nr); } static inline struct gds_vector * diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index e58a1f8fc673..93b2d20d720c 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -74,7 +74,7 @@ static void __init sclp_early_facilities_detect(void) sclp.hamax = U64_MAX; if (!sccb->hcpua) { - if (MACHINE_IS_VM) + if (machine_is_vm()) sclp.max_cores = 64; else sclp.max_cores = sccb->ncpurl; diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 892c18d2f87e..acd5ea0f7381 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -499,7 +499,7 @@ sclp_tty_init(void) int rc; /* z/VM multiplexes the line mode output on the 32xx screen */ - if (MACHINE_IS_VM && !CONSOLE_IS_SCLP) + if (machine_is_vm() && !CONSOLE_IS_SCLP) return 0; if (!sclp.has_linemode) return 0; @@ -524,7 +524,7 @@ sclp_tty_init(void) timer_setup(&sclp_tty_timer, sclp_tty_timeout, 0); sclp_ttybuf = NULL; sclp_tty_buffer_count = 0; - if (MACHINE_IS_VM) { + if (machine_is_vm()) { /* case input lines to lowercase */ sclp_tty_tolower = 1; } diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index c6d58335beb4..3a695c5bf77f 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -52,7 +53,7 @@ early_param("vmcp_cma", early_parse_vmcp_cma); void __init vmcp_cma_reserve(void) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return; cma_declare_contiguous(0, vmcp_cma_size, 0, 0, 0, false, "vmcp", &vmcp_cma); } @@ -254,7 +255,7 @@ static int __init vmcp_init(void) { int ret; - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return 0; vmcp_debug = debug_register("vmcp", 1, 1, 240); diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index b2d93a6e36c4..dac85294d2f5 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -809,7 +810,7 @@ static int __init vmlogrdr_init(void) int i; dev_t dev; - if (! MACHINE_IS_VM) { + if (!machine_is_vm()) { pr_err("not running under VM, driver not loaded.\n"); return -ENODEV; } diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index 90ba7a2b9cb4..0fd918769a4b 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -1009,7 +1010,7 @@ static int __init ur_init(void) int rc; dev_t dev; - if (!MACHINE_IS_VM) { + if (!machine_is_vm()) { pr_err("The %s cannot be loaded without z/VM\n", ur_banner); return -ENODEV; diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c index a512eac83485..d0f65d97dd4a 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -175,7 +176,7 @@ static void snsid_callback(struct ccw_device *cdev, void *data, int rc) struct senseid *senseid = &cdev->private->dma_area->senseid; int vm = 0; - if (rc && MACHINE_IS_VM) { + if (rc && machine_is_vm()) { /* Try diag 0x210 fallback on z/VM. */ snsid_init(cdev); if (diag210_get_dev_info(cdev) == 0) { diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 26e1ea1940ec..20cb8d272e56 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -2324,7 +2325,7 @@ static inline int __init ap_async_init(void) * Setup the high resolution poll timer. * If we are running under z/VM adjust polling to z/VM polling rate. */ - if (MACHINE_IS_VM) + if (machine_is_vm()) poll_high_timeout = 1500000; hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); ap_poll_timer.function = ap_poll_timeout; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 75910c0bcc2b..777404d66e0c 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -299,7 +300,7 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) QETH_CARD_TEXT(card, 2, "l2reqmac"); - if (MACHINE_IS_VM) { + if (machine_is_vm()) { rc = qeth_vm_request_mac(card); if (!rc) goto out; diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index c84ec2fbf99b..c68ba8dbc014 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include "smsgiucv.h" @@ -138,7 +139,7 @@ static int __init smsg_init(void) { int rc; - if (!MACHINE_IS_VM) { + if (!machine_is_vm()) { rc = -EPROTONOSUPPORT; goto out; } diff --git a/drivers/s390/net/smsgiucv_app.c b/drivers/s390/net/smsgiucv_app.c index cc44cbb0028b..4bd4d6bfc126 100644 --- a/drivers/s390/net/smsgiucv_app.c +++ b/drivers/s390/net/smsgiucv_app.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "smsgiucv.h" /* prefix used for SMSG registration */ @@ -153,7 +154,7 @@ static int __init smsgiucv_app_init(void) struct device_driver *smsgiucv_drv; int rc; - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return -ENODEV; smsgiucv_drv = driver_find(SMSGIUCV_DRV_NAME, &iucv_bus); diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c index ed4bf40278a7..4ca7472c38e0 100644 --- a/drivers/tty/hvc/hvc_iucv.c +++ b/drivers/tty/hvc/hvc_iucv.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "hvc_console.h" @@ -1240,7 +1241,7 @@ static int param_set_vmidfilter(const char *val, const struct kernel_param *kp) { int rc; - if (!MACHINE_IS_VM || !hvc_iucv_devices) + if (!machine_is_vm() || !hvc_iucv_devices) return -ENODEV; if (!val) @@ -1269,7 +1270,7 @@ static int param_get_vmidfilter(char *buffer, const struct kernel_param *kp) size_t index, len; void *start, *end; - if (!MACHINE_IS_VM || !hvc_iucv_devices) + if (!machine_is_vm() || !hvc_iucv_devices) return -ENODEV; rc = 0; @@ -1306,7 +1307,7 @@ static int __init hvc_iucv_init(void) if (!hvc_iucv_devices) return -ENODEV; - if (!MACHINE_IS_VM) { + if (!machine_is_vm()) { pr_notice("The z/VM IUCV HVC device driver cannot " "be used without z/VM\n"); rc = -ENODEV; diff --git a/drivers/watchdog/diag288_wdt.c b/drivers/watchdog/diag288_wdt.c index 4631d0a3866a..76dffc89c641 100644 --- a/drivers/watchdog/diag288_wdt.c +++ b/drivers/watchdog/diag288_wdt.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -110,7 +111,7 @@ static int wdt_start(struct watchdog_device *dev) int ret; unsigned int func; - if (MACHINE_IS_VM) { + if (machine_is_vm()) { func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL) : WDT_FUNC_INIT; ret = diag288_str(func, dev->timeout, wdt_cmd); @@ -136,7 +137,7 @@ static int wdt_ping(struct watchdog_device *dev) int ret; unsigned int func; - if (MACHINE_IS_VM) { + if (machine_is_vm()) { /* * It seems to be ok to z/VM to use the init function to * retrigger the watchdog. On LPAR WDT_FUNC_CHANGE must @@ -192,7 +193,7 @@ static int __init diag288_init(void) watchdog_set_nowayout(&wdt_dev, nowayout_info); - if (MACHINE_IS_VM) { + if (machine_is_vm()) { cmd_buf = kmalloc(MAX_CMDLEN, GFP_KERNEL); if (!cmd_buf) { pr_err("The watchdog cannot be initialized\n"); diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 7929df08d4e0..cc2b3c44bc05 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -2272,7 +2273,7 @@ static int __init afiucv_init(void) { int err; - if (MACHINE_IS_VM && IS_ENABLED(CONFIG_IUCV)) { + if (machine_is_vm() && IS_ENABLED(CONFIG_IUCV)) { cpcmd("QUERY USERID", iucv_userid, sizeof(iucv_userid), &err); if (unlikely(err)) { WARN_ON(err); diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index d3e9efab7f4b..83070a2e4485 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -1865,7 +1866,7 @@ static int __init iucv_init(void) { int rc; - if (!MACHINE_IS_VM) { + if (!machine_is_vm()) { rc = -EPROTONOSUPPORT; goto out; } -- cgit v1.2.3-59-g8ed1b From db14f78ecb02292e5013d7f46cf01be4d006262d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:49:08 +0100 Subject: s390/vx: Convert cpu_has_vx() to cpu feature function Instead of having a private cpu_has_vx() implementation use the new common cpu feature method. Move the facility detection to the decompressor so it matches all other cpu features. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/startup.c | 2 ++ arch/s390/include/asm/cpufeature.h | 1 + arch/s390/include/asm/fpu.h | 7 +------ arch/s390/kernel/early.c | 9 +-------- lib/raid6/s390vx.uc | 1 + 5 files changed, 6 insertions(+), 14 deletions(-) diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 9c4b2b317af2..98649e504989 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -141,6 +141,8 @@ static void detect_facilities(void) set_machine_feature(MFEATURE_TX); local_ctl_set_bit(0, CR0_TRANSACTIONAL_EXECUTION_BIT); } + if (cpu_has_vx()) + local_ctl_set_bit(0, CR0_VECTOR_BIT); } static int cmma_test_essa(void) diff --git a/arch/s390/include/asm/cpufeature.h b/arch/s390/include/asm/cpufeature.h index 026a43b86fd7..781f45e88821 100644 --- a/arch/s390/include/asm/cpufeature.h +++ b/arch/s390/include/asm/cpufeature.h @@ -31,5 +31,6 @@ int cpu_have_feature(unsigned int nr); #define cpu_has_seq_insn() test_facility(85) #define cpu_has_tlb_lc() test_facility(51) #define cpu_has_topology() test_facility(11) +#define cpu_has_vx() test_facility(129) #endif /* __ASM_S390_CPUFEATURE_H */ diff --git a/arch/s390/include/asm/fpu.h b/arch/s390/include/asm/fpu.h index c84cb33913e2..960c6c67ad6c 100644 --- a/arch/s390/include/asm/fpu.h +++ b/arch/s390/include/asm/fpu.h @@ -44,6 +44,7 @@ #ifndef _ASM_S390_FPU_H #define _ASM_S390_FPU_H +#include #include #include #include @@ -51,12 +52,6 @@ #include #include #include -#include - -static inline bool cpu_has_vx(void) -{ - return likely(test_facility(129)); -} enum { KERNEL_FPC_BIT = 0, diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index fc30eb222ee9..081f67abe05e 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -184,16 +184,10 @@ static noinline __init void setup_lowcore_early(void) lc->return_mcck_lpswe = gen_lpswe(__LC_RETURN_MCCK_PSW); } -static __init void detect_machine_facilities(void) -{ - if (test_facility(129)) - system_ctl_set_bit(0, CR0_VECTOR_BIT); -} - static inline void save_vector_registers(void) { #ifdef CONFIG_CRASH_DUMP - if (test_facility(129)) + if (cpu_has_vx()) save_vx_regs(boot_cpu_vector_save_area); #endif } @@ -232,7 +226,6 @@ void __init startup_init(void) setup_lowcore_early(); setup_arch_string(); setup_boot_command_line(); - detect_machine_facilities(); save_vector_registers(); setup_topology(); sclp_early_detect(); diff --git a/lib/raid6/s390vx.uc b/lib/raid6/s390vx.uc index 863e2d320938..8aa53eb2f395 100644 --- a/lib/raid6/s390vx.uc +++ b/lib/raid6/s390vx.uc @@ -11,6 +11,7 @@ * This file is postprocessed using unroll.awk. */ +#include #include #include -- cgit v1.2.3-59-g8ed1b From 841f35a08d4ae58322ed4e7fd68a50817d122602 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:49:09 +0100 Subject: s390/bear: Convert cpu_has_bear() to cpu feature function Get rid of the cpu_has_bear jump label and convert cpu_has_bear() to a cpu feature function using test_facility() and with that use a static branch. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/cpufeature.h | 1 + arch/s390/kernel/irq.c | 5 +++-- arch/s390/kernel/setup.c | 6 ------ arch/s390/kernel/syscall.c | 3 ++- arch/s390/kernel/traps.c | 3 ++- arch/s390/mm/dump_pagetables.c | 4 ++-- arch/s390/mm/vmem.c | 2 +- 7 files changed, 11 insertions(+), 13 deletions(-) diff --git a/arch/s390/include/asm/cpufeature.h b/arch/s390/include/asm/cpufeature.h index 781f45e88821..e08169bd63a5 100644 --- a/arch/s390/include/asm/cpufeature.h +++ b/arch/s390/include/asm/cpufeature.h @@ -22,6 +22,7 @@ enum { int cpu_have_feature(unsigned int nr); +#define cpu_has_bear() test_facility(193) #define cpu_has_edat1() test_facility(8) #define cpu_has_edat2() test_facility(78) #define cpu_has_gs() test_facility(133) diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index d0a596f1c2f6..17c074b11c51 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -150,7 +151,7 @@ void noinstr do_io_irq(struct pt_regs *regs) if (user_mode(regs)) { update_timer_sys(); - if (static_branch_likely(&cpu_has_bear)) + if (cpu_has_bear()) current->thread.last_break = regs->last_break; } @@ -186,7 +187,7 @@ void noinstr do_ext_irq(struct pt_regs *regs) if (user_mode(regs)) { update_timer_sys(); - if (static_branch_likely(&cpu_has_bear)) + if (cpu_has_bear()) current->thread.last_break = regs->last_break; } diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index dc8ccc5e8edf..b6686d63b754 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -181,8 +181,6 @@ unsigned long __bootdata_preserved(MODULES_END); struct lowcore *lowcore_ptr[NR_CPUS]; EXPORT_SYMBOL(lowcore_ptr); -DEFINE_STATIC_KEY_FALSE(cpu_has_bear); - /* * The Write Back bit position in the physaddr is given by the SLPC PCI. * Leaving the mask zero always uses write through which is safe @@ -982,10 +980,6 @@ void __init setup_arch(char **cmdline_p) numa_setup(); smp_detect_cpus(); topology_init_early(); - - if (test_facility(193)) - static_branch_enable(&cpu_has_bear); - setup_protection_map(); /* * Create kernel page tables. diff --git a/arch/s390/kernel/syscall.c b/arch/s390/kernel/syscall.c index 5ec28028315b..c8df656b08bc 100644 --- a/arch/s390/kernel/syscall.c +++ b/arch/s390/kernel/syscall.c @@ -12,6 +12,7 @@ * platform. */ +#include #include #include #include @@ -127,7 +128,7 @@ void noinstr __do_syscall(struct pt_regs *regs, int per_trap) regs->psw = get_lowcore()->svc_old_psw; regs->int_code = get_lowcore()->svc_int_code; update_timer_sys(); - if (static_branch_likely(&cpu_has_bear)) + if (cpu_has_bear()) current->thread.last_break = regs->last_break; local_irq_enable(); diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 24fee11b030d..a27053a405a7 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -15,6 +15,7 @@ */ #include "asm/irqflags.h" #include "asm/ptrace.h" +#include #include #include #include @@ -341,7 +342,7 @@ void noinstr __do_pgm_check(struct pt_regs *regs) if (user_mode(regs)) { update_timer_sys(); - if (!static_branch_likely(&cpu_has_bear)) { + if (!cpu_has_bear()) { if (regs->last_break < 4096) regs->last_break = 1; } diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c index b60bc2b42871..d3e943752fa0 100644 --- a/arch/s390/mm/dump_pagetables.c +++ b/arch/s390/mm/dump_pagetables.c @@ -84,7 +84,7 @@ static void note_prot_wx(struct pg_state *st, unsigned long addr) * in which case we have two lpswe instructions in lowcore that need * to be executable. */ - if (addr == PAGE_SIZE && (nospec_uses_trampoline() || !static_key_enabled(&cpu_has_bear))) + if (addr == PAGE_SIZE && (nospec_uses_trampoline() || !cpu_has_bear())) return; WARN_ONCE(IS_ENABLED(CONFIG_DEBUG_WX), "s390/mm: Found insecure W+X mapping at address %pS\n", @@ -178,7 +178,7 @@ bool ptdump_check_wx(void) return false; } else { pr_info("Checked W+X mappings: passed, no %sW+X pages found\n", - (nospec_uses_trampoline() || !static_key_enabled(&cpu_has_bear)) ? + (nospec_uses_trampoline() || !cpu_has_bear()) ? "unexpected " : ""); return true; diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 5d2d39f05d8c..448dd6ed1069 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -660,7 +660,7 @@ void __init vmem_map_init(void) * prefix page is used to return to the previous context with * an LPSWE instruction and therefore must be executable. */ - if (!static_key_enabled(&cpu_has_bear)) + if (!cpu_has_bear()) set_memory_x(0, 1); if (debug_pagealloc_enabled()) __set_memory_4k(__va(0), absolute_pointer(__va(0)) + ident_map_size); -- cgit v1.2.3-59-g8ed1b From 66ec751719d62c5c5eb7143af0a48e93ec079b5e Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:49:10 +0100 Subject: s390/setup: Add decompressor_handled_param() wrapper Make decompressor_handled_param() a wrapper for __decompressor_handled_param(). __decompressor_handled_param() now takes two parameters: a function name and a parameter name, which do not necessarily match. This allows to use characters like "-", which are not allowed in function names, for command line parameters which are handled by the decompressor and should be ignored by the kernel. Reviewed-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/early.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 081f67abe05e..8d0291c2b68c 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -38,12 +38,14 @@ #include #include "entry.h" -#define decompressor_handled_param(param) \ -static int __init ignore_decompressor_param_##param(char *s) \ +#define __decompressor_handled_param(func, param) \ +static int __init ignore_decompressor_param_##func(char *s) \ { \ return 0; \ } \ -early_param(#param, ignore_decompressor_param_##param) +early_param(#param, ignore_decompressor_param_##func) + +#define decompressor_handled_param(param) __decompressor_handled_param(param, param) decompressor_handled_param(mem); decompressor_handled_param(vmalloc); -- cgit v1.2.3-59-g8ed1b From f0f6db9ffe33d4f5abed2e9c522743a8c8686a0f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 7 Feb 2025 15:49:11 +0100 Subject: s390/alternatives: Add debug functionality Similar to x86 and loongarch add a "debug-alternative" command line parameter, which allows for alternative debugging. The parameter itself comes with architecture specific semantics: "debug-alternative" -> print debug message for every single alternative "debug-alternative=0;2" -> print debug message for all alternatives with type 0 and 2 "debug-alternative=0:0-7" -> print debug message for all alternatives with type 0 which have a facility number within the range of 0-7 "debug-alternative=0:!8;1" -> print debug message for all alternatives with type 0, for all facility numbers, except facility 8, and in addition print all alternatives with type 1 A defconfig build currently results in a kernel with more than 20.000 alternatives, where the majority is for the niai alternative (spinlocks), and the relocated lowcore alternative. The following kernel command like options limit alternative debug output, and enable dynamic debug messages: debug-alternative=0:!49;1:!0 earlyprintk bootdebug ignore_loglevel loglevel=8 dyndbg="file alternative.c +p" This results in output like this: alt: [0/ 11] 0000021b9ce8680c: c0f400000089 -> c00400000000 alt: [0/ 64] 0000021b9ce87e60: c0f400000043 -> c00400000000 alt: [0/133] 0000021b9ce88c56: c0f400000027 -> c00400000000 alt: [0/ 74] 0000021b9ce89410: c0f40000002a -> c00400000000 alt: [0/ 40] 0000021b9dc3720a: 47000000 -> b280d398 alt: [0/193] 0000021b9dc37306: 47000000 -> b201d2b0 alt: [0/193] 0000021b9dc37354: c00400000000 -> d20720c0d2b0 alt: [1/ 5] 0000038d720d7bf2: c0f400000016 -> c00400000000 With [/]
oldcode -> newcode Alternative data depends on the alternative type: for type 0 (ALT_TYPE_FACILITY) data is the facility. For type 1 (ALT_TYPE_FEATURE) data is the corresponding machine feature. Acked-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/alternative.c | 135 +++++++++++++++++++++++++++++++++++++++++ arch/s390/boot/boot.h | 1 + arch/s390/boot/ipl_parm.c | 3 + arch/s390/kernel/alternative.c | 55 +++++++++++++++-- arch/s390/kernel/early.c | 1 + 5 files changed, 190 insertions(+), 5 deletions(-) diff --git a/arch/s390/boot/alternative.c b/arch/s390/boot/alternative.c index abc08d2c873d..19ea7934b918 100644 --- a/arch/s390/boot/alternative.c +++ b/arch/s390/boot/alternative.c @@ -1,3 +1,138 @@ // SPDX-License-Identifier: GPL-2.0 +#define boot_fmt(fmt) "alt: " fmt +#include "boot.h" + +#define a_debug boot_debug #include "../kernel/alternative.c" + +static void alt_debug_all(int type) +{ + int i; + + switch (type) { + case ALT_TYPE_FACILITY: + for (i = 0; i < ARRAY_SIZE(alt_debug.facilities); i++) + alt_debug.facilities[i] = -1UL; + break; + case ALT_TYPE_FEATURE: + for (i = 0; i < ARRAY_SIZE(alt_debug.mfeatures); i++) + alt_debug.mfeatures[i] = -1UL; + break; + case ALT_TYPE_SPEC: + alt_debug.spec = 1; + break; + } +} + +static void alt_debug_modify(int type, unsigned int nr, bool clear) +{ + switch (type) { + case ALT_TYPE_FACILITY: + if (clear) + __clear_facility(nr, alt_debug.facilities); + else + __set_facility(nr, alt_debug.facilities); + break; + case ALT_TYPE_FEATURE: + if (clear) + __clear_machine_feature(nr, alt_debug.mfeatures); + else + __set_machine_feature(nr, alt_debug.mfeatures); + break; + } +} + +static char *alt_debug_parse(int type, char *str) +{ + unsigned long val, endval; + char *endp; + bool clear; + int i; + + if (*str == ':') { + str++; + } else { + alt_debug_all(type); + return str; + } + clear = false; + if (*str == '!') { + alt_debug_all(type); + clear = true; + str++; + } + while (*str) { + val = simple_strtoull(str, &endp, 0); + if (str == endp) + break; + str = endp; + if (*str == '-') { + str++; + endval = simple_strtoull(str, &endp, 0); + if (str == endp) + break; + str = endp; + while (val <= endval) { + alt_debug_modify(type, val, clear); + val++; + } + } else { + alt_debug_modify(type, val, clear); + } + if (*str != ',') + break; + str++; + } + return str; +} + +/* + * Use debug-alternative command line parameter for debugging: + * "debug-alternative" + * -> print debug message for every single alternative + * + * "debug-alternative=0;2" + * -> print debug message for all alternatives with type 0 and 2 + * + * "debug-alternative=0:0-7" + * -> print debug message for all alternatives with type 0 and with + * facility numbers within the range of 0-7 + * (if type 0 is ALT_TYPE_FACILITY) + * + * "debug-alternative=0:!8;1" + * -> print debug message for all alternatives with type 0, for all + * facility number, except facility 8, and in addition print all + * alternatives with type 1 + */ +void alt_debug_setup(char *str) +{ + unsigned long type; + char *endp; + int i; + + if (!str) { + alt_debug_all(ALT_TYPE_FACILITY); + alt_debug_all(ALT_TYPE_FEATURE); + alt_debug_all(ALT_TYPE_SPEC); + return; + } + while (*str) { + type = simple_strtoull(str, &endp, 0); + if (str == endp) + break; + str = endp; + switch (type) { + case ALT_TYPE_FACILITY: + case ALT_TYPE_FEATURE: + str = alt_debug_parse(type, str); + break; + case ALT_TYPE_SPEC: + alt_debug_all(ALT_TYPE_SPEC); + break; + } + if (*str != ';') + break; + str++; + } +} diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h index f4af23c142cc..bb6bd9d6d991 100644 --- a/arch/s390/boot/boot.h +++ b/arch/s390/boot/boot.h @@ -64,6 +64,7 @@ void parse_boot_command_line(void); void verify_facilities(void); void print_missing_facilities(void); void sclp_early_setup_buffer(void); +void alt_debug_setup(char *str); void print_pgm_check_info(void); unsigned long randomize_within_range(unsigned long size, unsigned long align, unsigned long min, unsigned long max); diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c index 13316bfa589c..86cfb16dd63d 100644 --- a/arch/s390/boot/ipl_parm.c +++ b/arch/s390/boot/ipl_parm.c @@ -296,6 +296,9 @@ void parse_boot_command_line(void) if (!strcmp(param, "facilities") && val) modify_fac_list(val); + if (!strcmp(param, "debug-alternative")) + alt_debug_setup(val); + if (!strcmp(param, "nokaslr")) __kaslr_enabled = 0; diff --git a/arch/s390/kernel/alternative.c b/arch/s390/kernel/alternative.c index 2f56649bbde8..90c0e6408992 100644 --- a/arch/s390/kernel/alternative.c +++ b/arch/s390/kernel/alternative.c @@ -1,6 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 +#ifndef pr_fmt +#define pr_fmt(fmt) "alt: " fmt +#endif + #include +#include #include #include #include @@ -8,38 +13,78 @@ #include #include +#ifndef a_debug +#define a_debug pr_debug +#endif + +#ifndef __kernel_va +#define __kernel_va(x) (void *)(x) +#endif + unsigned long __bootdata_preserved(machine_features[1]); +struct alt_debug { + unsigned long facilities[MAX_FACILITY_BIT / BITS_PER_LONG]; + unsigned long mfeatures[MAX_MFEATURE_BIT / BITS_PER_LONG]; + int spec; +}; + +static struct alt_debug __bootdata_preserved(alt_debug); + +static void alternative_dump(u8 *old, u8 *new, unsigned int len, unsigned int type, unsigned int data) +{ + char oinsn[33], ninsn[33]; + unsigned long kptr; + unsigned int pos; + + for (pos = 0; pos < len && 2 * pos < sizeof(oinsn) - 3; pos++) + hex_byte_pack(&oinsn[2 * pos], old[pos]); + oinsn[2 * pos] = 0; + for (pos = 0; pos < len && 2 * pos < sizeof(ninsn) - 3; pos++) + hex_byte_pack(&ninsn[2 * pos], new[pos]); + ninsn[2 * pos] = 0; + kptr = (unsigned long)__kernel_va(old); + a_debug("[%d/%3d] %016lx: %s -> %s\n", type, data, kptr, oinsn, ninsn); +} + void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsigned int ctx) { - u8 *instr, *replacement; + struct alt_debug *d; struct alt_instr *a; - bool replace; + bool debug, replace; + u8 *old, *new; /* * The scan order should be from start to end. A later scanned * alternative code can overwrite previously scanned alternative code. */ + d = &alt_debug; for (a = start; a < end; a++) { if (!(a->ctx & ctx)) continue; switch (a->type) { case ALT_TYPE_FACILITY: replace = test_facility(a->data); + debug = __test_facility(a->data, d->facilities); break; case ALT_TYPE_FEATURE: replace = test_machine_feature(a->data); + debug = __test_machine_feature(a->data, d->mfeatures); break; case ALT_TYPE_SPEC: replace = nobp_enabled(); + debug = d->spec; break; default: replace = false; + debug = false; } if (!replace) continue; - instr = (u8 *)&a->instr_offset + a->instr_offset; - replacement = (u8 *)&a->repl_offset + a->repl_offset; - s390_kernel_write(instr, replacement, a->instrlen); + old = (u8 *)&a->instr_offset + a->instr_offset; + new = (u8 *)&a->repl_offset + a->repl_offset; + if (debug) + alternative_dump(old, new, a->instrlen, a->type, a->data); + s390_kernel_write(old, new, a->instrlen); } } diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 8d0291c2b68c..b6d3c7a6209d 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -55,6 +55,7 @@ decompressor_handled_param(nokaslr); decompressor_handled_param(cmma); decompressor_handled_param(relocate_lowcore); decompressor_handled_param(bootdebug); +__decompressor_handled_param(debug_alternative, debug-alternative); #if IS_ENABLED(CONFIG_KVM) decompressor_handled_param(prot_virt); #endif -- cgit v1.2.3-59-g8ed1b From 3db42c75a921854a99db0a2775814fef97415bac Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Tue, 18 Feb 2025 10:52:16 +0800 Subject: s390/sclp: Add check for get_zeroed_page() Add check for the return value of get_zeroed_page() in sclp_console_init() to prevent null pointer dereference. Furthermore, to solve the memory leak caused by the loop allocation, add a free helper to do the free job. Signed-off-by: Haoxiang Li Acked-by: Heiko Carstens Link: https://lore.kernel.org/r/20250218025216.2421548-1-haoxiang_li2024@163.com Signed-off-by: Vasily Gorbik --- drivers/s390/char/sclp_con.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index e5d947c763ea..6a030ba38bf3 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c @@ -263,6 +263,19 @@ static struct console sclp_console = .index = 0 /* ttyS0 */ }; +/* + * Release allocated pages. + */ +static void __init __sclp_console_free_pages(void) +{ + struct list_head *page, *p; + + list_for_each_safe(page, p, &sclp_con_pages) { + list_del(page); + free_page((unsigned long)page); + } +} + /* * called by console_init() in drivers/char/tty_io.c at boot-time. */ @@ -282,6 +295,10 @@ sclp_console_init(void) /* Allocate pages for output buffering */ for (i = 0; i < sclp_console_pages; i++) { page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!page) { + __sclp_console_free_pages(); + return -ENOMEM; + } list_add_tail(page, &sclp_con_pages); } sclp_conbuf = NULL; -- cgit v1.2.3-59-g8ed1b From ad9bb8f049717d64c5e62b2a44954be9f681c65b Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Tue, 18 Feb 2025 11:41:04 +0800 Subject: s390/tty: Fix a potential memory leak bug The check for get_zeroed_page() leads to a direct return and overlooked the memory leak caused by loop allocation. Add a free helper to free spaces allocated by get_zeroed_page(). Signed-off-by: Haoxiang Li Acked-by: Heiko Carstens Link: https://lore.kernel.org/r/20250218034104.2436469-1-haoxiang_li2024@163.com Signed-off-by: Vasily Gorbik --- drivers/s390/char/sclp_tty.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index acd5ea0f7381..0a92d08830e7 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -490,6 +490,17 @@ static const struct tty_operations sclp_ops = { .flush_buffer = sclp_tty_flush_buffer, }; +/* Release allocated pages. */ +static void __init __sclp_tty_free_pages(void) +{ + struct list_head *page, *p; + + list_for_each_safe(page, p, &sclp_tty_pages) { + list_del(page); + free_page((unsigned long)page); + } +} + static int __init sclp_tty_init(void) { @@ -516,6 +527,7 @@ sclp_tty_init(void) for (i = 0; i < MAX_KMEM_PAGES; i++) { page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); if (page == NULL) { + __sclp_tty_free_pages(); tty_driver_kref_put(driver); return -ENOMEM; } -- cgit v1.2.3-59-g8ed1b From a702b633c0649eef5249e0355ecfb60567e4dbf2 Mon Sep 17 00:00:00 2001 From: Qasim Ijaz Date: Tue, 4 Feb 2025 16:25:08 +0000 Subject: s390/mm: Simplify gap clamping in mmap_base() using clamp() mmap_base() has logic to ensure that the variable "gap" stays within the range defined by "gap_min" and "gap_max". Replace this with the clamp() macro to shorten and simplify code. Signed-off-by: Qasim Ijaz Link: https://lore.kernel.org/r/20250204162508.12335-1-qasdev00@gmail.com Reviewed-by: Vasily Gorbik [gor@linux.ibm.com: also remove the gap_min and gap_max variables] Signed-off-by: Vasily Gorbik --- arch/s390/mm/mmap.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 76f376876e0d..40a526d28184 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -51,7 +51,6 @@ static inline unsigned long mmap_base(unsigned long rnd, { unsigned long gap = rlim_stack->rlim_cur; unsigned long pad = stack_maxrandom_size() + stack_guard_gap; - unsigned long gap_min, gap_max; /* Values close to RLIM_INFINITY can overflow. */ if (gap + pad > gap) @@ -61,13 +60,7 @@ static inline unsigned long mmap_base(unsigned long rnd, * Top of mmap area (just below the process stack). * Leave at least a ~128 MB hole. */ - gap_min = SZ_128M; - gap_max = (STACK_TOP / 6) * 5; - - if (gap < gap_min) - gap = gap_min; - else if (gap > gap_max) - gap = gap_max; + gap = clamp(gap, SZ_128M, (STACK_TOP / 6) * 5); return PAGE_ALIGN(STACK_TOP - gap - rnd); } -- cgit v1.2.3-59-g8ed1b From b337f6af6766da0790f8b50a1ca7ce67cfb5b69c Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 25 Feb 2025 09:47:34 +0100 Subject: s390: Use system header file variant of include directive A few include directives use the local search variant even though the files to be included aren't local. Therefore use the normal system header file variant of the include directive. Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/entry.S | 4 ++-- arch/s390/kernel/ptrace.c | 2 +- arch/s390/kernel/traps.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index c328e05b584c..ea4ddd37ea5a 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -622,7 +622,7 @@ SYM_DATA_END(daton_psw) .balign 8 #define SYSCALL(esame,emu) .quad __s390x_ ## esame SYM_DATA_START(sys_call_table) -#include "asm/syscall_table.h" +#include SYM_DATA_END(sys_call_table) #undef SYSCALL @@ -630,7 +630,7 @@ SYM_DATA_END(sys_call_table) #define SYSCALL(esame,emu) .quad __s390_ ## emu SYM_DATA_START(sys_call_table_emu) -#include "asm/syscall_table.h" +#include SYM_DATA_END(sys_call_table_emu) #undef SYSCALL #endif diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index e2acbbadc75e..6f2ae0be2298 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -7,7 +7,6 @@ * Martin Schwidefsky (schwidefsky@de.ibm.com) */ -#include "asm/ptrace.h" #include #include #include @@ -33,6 +32,7 @@ #include #include #include +#include #include #include "entry.h" diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index a27053a405a7..6db2c1466531 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -13,8 +13,6 @@ * 'Traps.c' handles hardware traps and faults after we have saved some * state in 'asm.s'. */ -#include "asm/irqflags.h" -#include "asm/ptrace.h" #include #include #include @@ -30,6 +28,8 @@ #include #include #include +#include +#include #include #include #include -- cgit v1.2.3-59-g8ed1b From a0a8f2b219627ba126e208ac67ded6756537af8f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 24 Feb 2025 15:59:03 +0100 Subject: s390/asm-offsets: Rename __LC_PGM_INT_CODE Avoid confusion and rename __LC_PGM_INT_CODE since it correlates to the pgm_code member of struct lowcore, and not the pgm_int_code member. Reviewed-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/asm-offsets.c | 2 +- arch/s390/kvm/interrupt.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 1242e7435647..c623888029fb 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -76,7 +76,7 @@ int main(void) OFFSET(__LC_EXT_CPU_ADDR, lowcore, ext_cpu_addr); OFFSET(__LC_EXT_INT_CODE, lowcore, ext_int_code); OFFSET(__LC_PGM_ILC, lowcore, pgm_ilc); - OFFSET(__LC_PGM_INT_CODE, lowcore, pgm_code); + OFFSET(__LC_PGM_CODE, lowcore, pgm_code); OFFSET(__LC_DATA_EXC_CODE, lowcore, data_exc_code); OFFSET(__LC_MON_CLASS_NR, lowcore, mon_class_num); OFFSET(__LC_PER_CODE, lowcore, per_code); diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 2c1f69760e7e..beb96989c661 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -949,8 +949,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu) rc |= put_guest_lc(vcpu, ilen, (u16 *) __LC_PGM_ILC); rc |= put_guest_lc(vcpu, vcpu->arch.sie_block->gbea, (u64 *) __LC_PGM_LAST_BREAK); - rc |= put_guest_lc(vcpu, pgm_info.code, - (u16 *)__LC_PGM_INT_CODE); + rc |= put_guest_lc(vcpu, pgm_info.code, (u16 *)__LC_PGM_CODE); rc |= write_guest_lc(vcpu, __LC_PGM_OLD_PSW, &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); rc |= read_guest_lc(vcpu, __LC_PGM_NEW_PSW, -- cgit v1.2.3-59-g8ed1b From b10ac5d77c323e4bdeed61c36312c994ad0cdbd1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 24 Feb 2025 15:59:04 +0100 Subject: s390/boot: Pass pt_regs to program check handler Setup a pt_regs structure on the stack, poplulate it in low level assembler code, and pass it to print_pgm_check_info(). This way there is no need to access then lowcore from print_pgm_check_info() anymore, and the function looks like a normal program check handler function. Acked-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/boot.h | 2 +- arch/s390/boot/head.S | 7 ++++++- arch/s390/boot/pgm_check_info.c | 17 +++++++---------- arch/s390/kernel/asm-offsets.c | 2 ++ 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h index bb6bd9d6d991..bc3432fffff2 100644 --- a/arch/s390/boot/boot.h +++ b/arch/s390/boot/boot.h @@ -65,7 +65,7 @@ void verify_facilities(void); void print_missing_facilities(void); void sclp_early_setup_buffer(void); void alt_debug_setup(char *str); -void print_pgm_check_info(void); +void print_pgm_check_info(struct pt_regs *regs); unsigned long randomize_within_range(unsigned long size, unsigned long align, unsigned long min, unsigned long max); void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned long asce_limit); diff --git a/arch/s390/boot/head.S b/arch/s390/boot/head.S index fe68c9253ea2..0a0afb915718 100644 --- a/arch/s390/boot/head.S +++ b/arch/s390/boot/head.S @@ -312,7 +312,12 @@ SYM_CODE_START_LOCAL(startup_pgm_check_handler) oi __LC_RETURN_PSW+1,0x2 # set wait state bit larl %r9,.Lold_psw_disabled_wait stg %r9,__LC_PGM_NEW_PSW+8 - larl %r15,_dump_info_stack_end-STACK_FRAME_OVERHEAD + larl %r15,_dump_info_stack_end-(STACK_FRAME_OVERHEAD+__PT_SIZE) + la %r2,STACK_FRAME_OVERHEAD(%r15) + mvc __PT_PSW(16,%r2),__LC_PSW_SAVE_AREA-4095(%r8) + mvc __PT_R0(128,%r2),__LC_GPREGS_SAVE_AREA-4095(%r8) + mvc __PT_LAST_BREAK(8,%r2),__LC_PGM_LAST_BREAK + mvc __PT_INT_CODE(4,%r2),__LC_PGM_INT_CODE brasl %r14,print_pgm_check_info .Lold_psw_disabled_wait: la %r8,4095 diff --git a/arch/s390/boot/pgm_check_info.c b/arch/s390/boot/pgm_check_info.c index 633f11600aab..e61ae4a15969 100644 --- a/arch/s390/boot/pgm_check_info.c +++ b/arch/s390/boot/pgm_check_info.c @@ -32,10 +32,10 @@ void print_stacktrace(unsigned long sp) } } -void print_pgm_check_info(void) +void print_pgm_check_info(struct pt_regs *regs) { - unsigned long *gpregs = (unsigned long *)get_lowcore()->gpregs_save_area; - struct psw_bits *psw = &psw_bits(get_lowcore()->psw_save_area); + struct psw_bits *psw = &psw_bits(regs->psw); + unsigned long *gpregs = regs->gprs; if (bootdebug) boot_rb_dump(); @@ -43,15 +43,13 @@ void print_pgm_check_info(void) if (!is_prot_virt_guest() && early_command_line[0]) boot_emerg("Kernel command line: %s\n", early_command_line); boot_emerg("Kernel fault: interruption code %04x ilc:%d\n", - get_lowcore()->pgm_code, get_lowcore()->pgm_ilc >> 1); + regs->int_code & 0xffff, regs->int_code >> 17); if (kaslr_enabled()) { boot_emerg("Kernel random base: %lx\n", __kaslr_offset); boot_emerg("Kernel random base phys: %lx\n", __kaslr_offset_phys); } boot_emerg("PSW : %016lx %016lx (%pS)\n", - get_lowcore()->psw_save_area.mask, - get_lowcore()->psw_save_area.addr, - (void *)get_lowcore()->psw_save_area.addr); + regs->psw.mask, regs->psw.addr, (void *)regs->psw.addr); boot_emerg(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x P:%x AS:%x CC:%x PM:%x RI:%x EA:%x\n", psw->per, psw->dat, psw->io, psw->ext, psw->key, psw->mcheck, psw->wait, psw->pstate, psw->as, psw->cc, psw->pm, psw->ri, psw->eaba); @@ -59,8 +57,7 @@ void print_pgm_check_info(void) boot_emerg(" %016lx %016lx %016lx %016lx\n", gpregs[4], gpregs[5], gpregs[6], gpregs[7]); boot_emerg(" %016lx %016lx %016lx %016lx\n", gpregs[8], gpregs[9], gpregs[10], gpregs[11]); boot_emerg(" %016lx %016lx %016lx %016lx\n", gpregs[12], gpregs[13], gpregs[14], gpregs[15]); - print_stacktrace(get_lowcore()->gpregs_save_area[15]); + print_stacktrace(gpregs[15]); boot_emerg("Last Breaking-Event-Address:\n"); - boot_emerg(" [<%016lx>] %pS\n", (unsigned long)get_lowcore()->pgm_last_break, - (void *)get_lowcore()->pgm_last_break); + boot_emerg(" [<%016lx>] %pS\n", regs->last_break, (void *)regs->last_break); } diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index c623888029fb..49bb197c8c81 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -49,6 +49,7 @@ int main(void) OFFSET(__PT_R14, pt_regs, gprs[14]); OFFSET(__PT_R15, pt_regs, gprs[15]); OFFSET(__PT_ORIG_GPR2, pt_regs, orig_gpr2); + OFFSET(__PT_INT_CODE, pt_regs, int_code); OFFSET(__PT_FLAGS, pt_regs, flags); OFFSET(__PT_CR1, pt_regs, cr1); OFFSET(__PT_LAST_BREAK, pt_regs, last_break); @@ -77,6 +78,7 @@ int main(void) OFFSET(__LC_EXT_INT_CODE, lowcore, ext_int_code); OFFSET(__LC_PGM_ILC, lowcore, pgm_ilc); OFFSET(__LC_PGM_CODE, lowcore, pgm_code); + OFFSET(__LC_PGM_INT_CODE, lowcore, pgm_int_code); OFFSET(__LC_DATA_EXC_CODE, lowcore, data_exc_code); OFFSET(__LC_MON_CLASS_NR, lowcore, mon_class_num); OFFSET(__LC_PER_CODE, lowcore, per_code); -- cgit v1.2.3-59-g8ed1b From 6067891b65cbf0068c2266d40a3a67df8535f72c Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 24 Feb 2025 15:59:05 +0100 Subject: s390/boot: Add exception table support The early boot code contains various open-coded inline assemblies with exception handling. In order to handle possible exceptions each of them changes the program check new psw, and restores it. In order to simplify the various inline assemblies add simple exception table support: the program check handler is called with a fully populated pt_regs on the stack and may change the psw and register members. When the program check handler returns the psw and registers from pt_regs will be used to continue execution. The program check handler searches the exception table for an entry which matches the address of the program check. If such an entry is found the psw address within pt_regs on the stack is replaced with a fixup address, and execution continues at the new address. If no entry is found the psw is changed to a disabled wait psw and execution stops. Before entering the C part of the program check handler the address of the program check new psw is replaced to a minimalistic handler. This is supposed to help against program check loops. If an exception happens while in program check processing the register contents of the original exception are restored and a disabled wait psw is loaded. Acked-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/Makefile | 2 +- arch/s390/boot/boot.h | 2 +- arch/s390/boot/head.S | 13 +++--- arch/s390/boot/pgm_check.c | 92 +++++++++++++++++++++++++++++++++++++++++ arch/s390/boot/pgm_check_info.c | 63 ---------------------------- arch/s390/boot/vmlinux.lds.S | 2 +- 6 files changed, 101 insertions(+), 73 deletions(-) create mode 100644 arch/s390/boot/pgm_check.c delete mode 100644 arch/s390/boot/pgm_check_info.c diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile index 8bc1308ac892..bee49626be4b 100644 --- a/arch/s390/boot/Makefile +++ b/arch/s390/boot/Makefile @@ -26,7 +26,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char obj-y := head.o als.o startup.o physmem_info.o ipl_parm.o ipl_report.o vmem.o obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o -obj-y += version.o pgm_check_info.o ctype.o ipl_data.o relocs.o alternative.o +obj-y += version.o pgm_check.o ctype.o ipl_data.o relocs.o alternative.o obj-y += uv.o printk.o obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o obj-y += $(if $(CONFIG_KERNEL_UNCOMPRESSED),,decompressor.o) info.o diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h index bc3432fffff2..e045cae6e80a 100644 --- a/arch/s390/boot/boot.h +++ b/arch/s390/boot/boot.h @@ -65,7 +65,7 @@ void verify_facilities(void); void print_missing_facilities(void); void sclp_early_setup_buffer(void); void alt_debug_setup(char *str); -void print_pgm_check_info(struct pt_regs *regs); +void do_pgm_check(struct pt_regs *regs); unsigned long randomize_within_range(unsigned long size, unsigned long align, unsigned long min, unsigned long max); void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned long asce_limit); diff --git a/arch/s390/boot/head.S b/arch/s390/boot/head.S index 0a0afb915718..0b511d5c030b 100644 --- a/arch/s390/boot/head.S +++ b/arch/s390/boot/head.S @@ -293,12 +293,6 @@ SYM_CODE_END(startup_normal) #include "head_kdump.S" -# -# This program check is active immediately after kernel start -# and until early_pgm_check_handler is set in kernel/early.c -# It simply saves general/control registers and psw in -# the save area and does disabled wait with a faulty address. -# SYM_CODE_START_LOCAL(startup_pgm_check_handler) stmg %r8,%r15,__LC_SAVE_AREA la %r8,4095 @@ -318,7 +312,12 @@ SYM_CODE_START_LOCAL(startup_pgm_check_handler) mvc __PT_R0(128,%r2),__LC_GPREGS_SAVE_AREA-4095(%r8) mvc __PT_LAST_BREAK(8,%r2),__LC_PGM_LAST_BREAK mvc __PT_INT_CODE(4,%r2),__LC_PGM_INT_CODE - brasl %r14,print_pgm_check_info + brasl %r14,do_pgm_check + larl %r9,startup_pgm_check_handler + stg %r9,__LC_PGM_NEW_PSW+8 + mvc __LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15) + lmg %r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15) + lpswe __LC_RETURN_PSW .Lold_psw_disabled_wait: la %r8,4095 lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r8) diff --git a/arch/s390/boot/pgm_check.c b/arch/s390/boot/pgm_check.c new file mode 100644 index 000000000000..fa621fa5bc02 --- /dev/null +++ b/arch/s390/boot/pgm_check.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "boot.h" + +void print_stacktrace(unsigned long sp) +{ + struct stack_info boot_stack = { STACK_TYPE_TASK, (unsigned long)_stack_start, + (unsigned long)_stack_end }; + bool first = true; + + boot_emerg("Call Trace:\n"); + while (!(sp & 0x7) && on_stack(&boot_stack, sp, sizeof(struct stack_frame))) { + struct stack_frame *sf = (struct stack_frame *)sp; + + if (first) + boot_emerg("(sp:%016lx [<%016lx>] %pS)\n", sp, sf->gprs[8], (void *)sf->gprs[8]); + else + boot_emerg(" sp:%016lx [<%016lx>] %pS\n", sp, sf->gprs[8], (void *)sf->gprs[8]); + if (sf->back_chain <= sp) + break; + sp = sf->back_chain; + first = false; + } +} + +extern struct exception_table_entry __start___ex_table[]; +extern struct exception_table_entry __stop___ex_table[]; + +static inline unsigned long extable_insn(const struct exception_table_entry *x) +{ + return (unsigned long)&x->insn + x->insn; +} + +static bool ex_handler(struct pt_regs *regs) +{ + const struct exception_table_entry *ex; + + for (ex = __start___ex_table; ex < __stop___ex_table; ex++) { + if (extable_insn(ex) != regs->psw.addr) + continue; + if (ex->type != EX_TYPE_FIXUP) + return false; + regs->psw.addr = extable_fixup(ex); + return true; + } + return false; +} + +void do_pgm_check(struct pt_regs *regs) +{ + struct psw_bits *psw = &psw_bits(regs->psw); + unsigned long *gpregs = regs->gprs; + + if (ex_handler(regs)) + return; + if (bootdebug) + boot_rb_dump(); + boot_emerg("Linux version %s\n", kernel_version); + if (!is_prot_virt_guest() && early_command_line[0]) + boot_emerg("Kernel command line: %s\n", early_command_line); + boot_emerg("Kernel fault: interruption code %04x ilc:%d\n", + regs->int_code & 0xffff, regs->int_code >> 17); + if (kaslr_enabled()) { + boot_emerg("Kernel random base: %lx\n", __kaslr_offset); + boot_emerg("Kernel random base phys: %lx\n", __kaslr_offset_phys); + } + boot_emerg("PSW : %016lx %016lx (%pS)\n", + regs->psw.mask, regs->psw.addr, (void *)regs->psw.addr); + boot_emerg(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x P:%x AS:%x CC:%x PM:%x RI:%x EA:%x\n", + psw->per, psw->dat, psw->io, psw->ext, psw->key, psw->mcheck, + psw->wait, psw->pstate, psw->as, psw->cc, psw->pm, psw->ri, psw->eaba); + boot_emerg("GPRS: %016lx %016lx %016lx %016lx\n", gpregs[0], gpregs[1], gpregs[2], gpregs[3]); + boot_emerg(" %016lx %016lx %016lx %016lx\n", gpregs[4], gpregs[5], gpregs[6], gpregs[7]); + boot_emerg(" %016lx %016lx %016lx %016lx\n", gpregs[8], gpregs[9], gpregs[10], gpregs[11]); + boot_emerg(" %016lx %016lx %016lx %016lx\n", gpregs[12], gpregs[13], gpregs[14], gpregs[15]); + print_stacktrace(gpregs[15]); + boot_emerg("Last Breaking-Event-Address:\n"); + boot_emerg(" [<%016lx>] %pS\n", regs->last_break, (void *)regs->last_break); + /* Convert to disabled wait PSW */ + psw->io = 0; + psw->ext = 0; + psw->wait = 1; +} diff --git a/arch/s390/boot/pgm_check_info.c b/arch/s390/boot/pgm_check_info.c deleted file mode 100644 index e61ae4a15969..000000000000 --- a/arch/s390/boot/pgm_check_info.c +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "boot.h" - -void print_stacktrace(unsigned long sp) -{ - struct stack_info boot_stack = { STACK_TYPE_TASK, (unsigned long)_stack_start, - (unsigned long)_stack_end }; - bool first = true; - - boot_emerg("Call Trace:\n"); - while (!(sp & 0x7) && on_stack(&boot_stack, sp, sizeof(struct stack_frame))) { - struct stack_frame *sf = (struct stack_frame *)sp; - - if (first) - boot_emerg("(sp:%016lx [<%016lx>] %pS)\n", sp, sf->gprs[8], (void *)sf->gprs[8]); - else - boot_emerg(" sp:%016lx [<%016lx>] %pS\n", sp, sf->gprs[8], (void *)sf->gprs[8]); - if (sf->back_chain <= sp) - break; - sp = sf->back_chain; - first = false; - } -} - -void print_pgm_check_info(struct pt_regs *regs) -{ - struct psw_bits *psw = &psw_bits(regs->psw); - unsigned long *gpregs = regs->gprs; - - if (bootdebug) - boot_rb_dump(); - boot_emerg("Linux version %s\n", kernel_version); - if (!is_prot_virt_guest() && early_command_line[0]) - boot_emerg("Kernel command line: %s\n", early_command_line); - boot_emerg("Kernel fault: interruption code %04x ilc:%d\n", - regs->int_code & 0xffff, regs->int_code >> 17); - if (kaslr_enabled()) { - boot_emerg("Kernel random base: %lx\n", __kaslr_offset); - boot_emerg("Kernel random base phys: %lx\n", __kaslr_offset_phys); - } - boot_emerg("PSW : %016lx %016lx (%pS)\n", - regs->psw.mask, regs->psw.addr, (void *)regs->psw.addr); - boot_emerg(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x P:%x AS:%x CC:%x PM:%x RI:%x EA:%x\n", - psw->per, psw->dat, psw->io, psw->ext, psw->key, psw->mcheck, - psw->wait, psw->pstate, psw->as, psw->cc, psw->pm, psw->ri, psw->eaba); - boot_emerg("GPRS: %016lx %016lx %016lx %016lx\n", gpregs[0], gpregs[1], gpregs[2], gpregs[3]); - boot_emerg(" %016lx %016lx %016lx %016lx\n", gpregs[4], gpregs[5], gpregs[6], gpregs[7]); - boot_emerg(" %016lx %016lx %016lx %016lx\n", gpregs[8], gpregs[9], gpregs[10], gpregs[11]); - boot_emerg(" %016lx %016lx %016lx %016lx\n", gpregs[12], gpregs[13], gpregs[14], gpregs[15]); - print_stacktrace(gpregs[15]); - boot_emerg("Last Breaking-Event-Address:\n"); - boot_emerg(" [<%016lx>] %pS\n", regs->last_break, (void *)regs->last_break); -} diff --git a/arch/s390/boot/vmlinux.lds.S b/arch/s390/boot/vmlinux.lds.S index 66670212a361..50988022f9ea 100644 --- a/arch/s390/boot/vmlinux.lds.S +++ b/arch/s390/boot/vmlinux.lds.S @@ -40,6 +40,7 @@ SECTIONS *(.rodata.*) _erodata = . ; } + EXCEPTION_TABLE(16) .got : { *(.got) } @@ -165,7 +166,6 @@ SECTIONS /DISCARD/ : { COMMON_DISCARDS *(.eh_frame) - *(__ex_table) *(*__ksymtab*) *(___kcrctab*) } -- cgit v1.2.3-59-g8ed1b From 68d699650b94b6b5617507fb939e6dce716b612d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 24 Feb 2025 15:59:06 +0100 Subject: s390/boot: Convert cmma_test_essa() to extable Shorten cmma_test_essa() and use regular EX_TABLE program check handling. Acked-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/startup.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 98649e504989..978a779a6d47 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -147,30 +147,17 @@ static void detect_facilities(void) static int cmma_test_essa(void) { - unsigned long reg1, reg2, tmp = 0; + unsigned long tmp = 0; int rc = 1; - psw_t old; /* Test ESSA_GET_STATE */ asm volatile( - " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" - " epsw %[reg1],%[reg2]\n" - " st %[reg1],0(%[psw_pgm])\n" - " st %[reg2],4(%[psw_pgm])\n" - " larl %[reg1],1f\n" - " stg %[reg1],8(%[psw_pgm])\n" " .insn rrf,0xb9ab0000,%[tmp],%[tmp],%[cmd],0\n" - " la %[rc],0\n" - "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" - : [reg1] "=&d" (reg1), - [reg2] "=&a" (reg2), - [rc] "+&d" (rc), - [tmp] "=&d" (tmp), - "+Q" (get_lowcore()->program_new_psw), - "=Q" (old) - : [psw_old] "a" (&old), - [psw_pgm] "a" (&get_lowcore()->program_new_psw), - [cmd] "i" (ESSA_GET_STATE) + "0: lhi %[rc],0\n" + "1:\n" + EX_TABLE(0b, 1b) + : [rc] "+d" (rc), [tmp] "+d" (tmp) + : [cmd] "i" (ESSA_GET_STATE) : "cc", "memory"); return rc; } -- cgit v1.2.3-59-g8ed1b From 0b4bf776f3394933c71e90dec376142561582a58 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 24 Feb 2025 15:59:07 +0100 Subject: s390/boot: Convert __diag260() to extable Shorten __diag260() and use regular EX_TABLE program check handling. Acked-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/physmem_info.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/arch/s390/boot/physmem_info.c b/arch/s390/boot/physmem_info.c index aa096ef68e8c..72be6453d08c 100644 --- a/arch/s390/boot/physmem_info.c +++ b/arch/s390/boot/physmem_info.c @@ -59,36 +59,22 @@ void add_physmem_online_range(u64 start, u64 end) static int __diag260(unsigned long rx1, unsigned long rx2) { - unsigned long reg1, reg2, ry; union register_pair rx; int cc, exception; - psw_t old; + unsigned long ry; rx.even = rx1; rx.odd = rx2; ry = 0x10; /* storage configuration */ exception = 1; asm volatile( - " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" - " epsw %[reg1],%[reg2]\n" - " st %[reg1],0(%[psw_pgm])\n" - " st %[reg2],4(%[psw_pgm])\n" - " larl %[reg1],1f\n" - " stg %[reg1],8(%[psw_pgm])\n" " diag %[rx],%[ry],0x260\n" - " lhi %[exc],0\n" - "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" + "0: lhi %[exc],0\n" + "1:\n" CC_IPM(cc) - : CC_OUT(cc, cc), - [exc] "+d" (exception), - [reg1] "=&d" (reg1), - [reg2] "=&a" (reg2), - [ry] "+&d" (ry), - "+Q" (get_lowcore()->program_new_psw), - "=Q" (old) - : [rx] "d" (rx.pair), - [psw_old] "a" (&old), - [psw_pgm] "a" (&get_lowcore()->program_new_psw) + EX_TABLE(0b, 1b) + : CC_OUT(cc, cc), [exc] "+d" (exception), [ry] "+d" (ry) + : [rx] "d" (rx.pair) : CC_CLOBBER_LIST("memory")); cc = exception ? -1 : CC_TRANSFORM(cc); return cc == 0 ? ry : -1; -- cgit v1.2.3-59-g8ed1b From 7063bb2900c4de261536f305ffde41732131072a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 24 Feb 2025 15:59:08 +0100 Subject: s390/boot: Convert tprot() to extable Shorten tprot() and use regular EX_TABLE program check handling. Acked-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/physmem_info.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/arch/s390/boot/physmem_info.c b/arch/s390/boot/physmem_info.c index 72be6453d08c..99f17efbf7d3 100644 --- a/arch/s390/boot/physmem_info.c +++ b/arch/s390/boot/physmem_info.c @@ -137,31 +137,17 @@ static int diag500_storage_limit(unsigned long *max_physmem_end) static int tprot(unsigned long addr) { - unsigned long reg1, reg2; int cc, exception; - psw_t old; exception = 1; asm volatile( - " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" - " epsw %[reg1],%[reg2]\n" - " st %[reg1],0(%[psw_pgm])\n" - " st %[reg2],4(%[psw_pgm])\n" - " larl %[reg1],1f\n" - " stg %[reg1],8(%[psw_pgm])\n" " tprot 0(%[addr]),0\n" - " lhi %[exc],0\n" - "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" + "0: lhi %[exc],0\n" + "1:\n" CC_IPM(cc) - : CC_OUT(cc, cc), - [exc] "+d" (exception), - [reg1] "=&d" (reg1), - [reg2] "=&a" (reg2), - "=Q" (get_lowcore()->program_new_psw.addr), - "=Q" (old) - : [psw_old] "a" (&old), - [psw_pgm] "a" (&get_lowcore()->program_new_psw), - [addr] "a" (addr) + EX_TABLE(0b, 1b) + : CC_OUT(cc, cc), [exc] "+d" (exception) + : [addr] "a" (addr) : CC_CLOBBER_LIST("memory")); cc = exception ? -EFAULT : CC_TRANSFORM(cc); return cc; -- cgit v1.2.3-59-g8ed1b From b1879e7ee7e2c1c93d5353829f4e71a6f70ffd47 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 24 Feb 2025 15:59:09 +0100 Subject: s390/boot: Convert diag500_storage_limit() to extable Shorten diag500_storage_limit() and use regular EX_TABLE program check handling. Acked-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/physmem_info.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/arch/s390/boot/physmem_info.c b/arch/s390/boot/physmem_info.c index 99f17efbf7d3..eb1badb93c40 100644 --- a/arch/s390/boot/physmem_info.c +++ b/arch/s390/boot/physmem_info.c @@ -104,29 +104,15 @@ static int diag260(void) static int diag500_storage_limit(unsigned long *max_physmem_end) { unsigned long storage_limit; - unsigned long reg1, reg2; - psw_t old; asm volatile( - " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" - " epsw %[reg1],%[reg2]\n" - " st %[reg1],0(%[psw_pgm])\n" - " st %[reg2],4(%[psw_pgm])\n" - " larl %[reg1],1f\n" - " stg %[reg1],8(%[psw_pgm])\n" - " lghi 1,%[subcode]\n" - " lghi 2,0\n" - " diag 2,4,0x500\n" - "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" - " lgr %[slimit],2\n" - : [reg1] "=&d" (reg1), - [reg2] "=&a" (reg2), - [slimit] "=d" (storage_limit), - "=Q" (get_lowcore()->program_new_psw), - "=Q" (old) - : [psw_old] "a" (&old), - [psw_pgm] "a" (&get_lowcore()->program_new_psw), - [subcode] "i" (DIAG500_SC_STOR_LIMIT) + " lghi %%r1,%[subcode]\n" + " lghi %%r2,0\n" + " diag %%r2,%%r4,0x500\n" + "0: lgr %[slimit],%%r2\n" + EX_TABLE(0b, 0b) + : [slimit] "=d" (storage_limit) + : [subcode] "i" (DIAG500_SC_STOR_LIMIT) : "memory", "1", "2"); if (!storage_limit) return -EINVAL; -- cgit v1.2.3-59-g8ed1b From 097cf5d57f1fce25bf9c840bc033ff95e5a9234a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 24 Feb 2025 15:59:10 +0100 Subject: s390/boot: Convert detect_diag9c() to extable Shorten detect_diag9c() and use regular EX_TABLE program check handling. Acked-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/startup.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 978a779a6d47..099b2327c781 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -73,30 +73,17 @@ static void detect_machine_type(void) static void detect_diag9c(void) { - unsigned long reg1, reg2; unsigned int cpu; int rc = 1; - psw_t old; cpu = stap(); asm volatile( - " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" - " epsw %[reg1],%[reg2]\n" - " st %[reg1],0(%[psw_pgm])\n" - " st %[reg2],4(%[psw_pgm])\n" - " larl %[reg1],1f\n" - " stg %[reg1],8(%[psw_pgm])\n" - " diag %[cpu],0,0x9c\n" - " lhi %[rc],0\n" - "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" - : [reg1] "=&d" (reg1), - [reg2] "=&a" (reg2), - [rc] "+&d" (rc), - "+Q" (get_lowcore()->program_new_psw), - "=Q" (old) - : [psw_old] "a" (&old), - [psw_pgm] "a" (&get_lowcore()->program_new_psw), - [cpu] "d" (cpu) + " diag %[cpu],%%r0,0x9c\n" + "0: lhi %[rc],0\n" + "1:\n" + EX_TABLE(0b, 1b) + : [rc] "+d" (rc) + : [cpu] "d" (cpu) : "cc", "memory"); if (!rc) set_machine_feature(MFEATURE_DIAG9C); -- cgit v1.2.3-59-g8ed1b From 9ef496ddf95e0410bf3003cf2415485879e536f4 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 24 Feb 2025 15:59:11 +0100 Subject: s390/boot: Convert __diag308() to extable Shorten __diag308() and use regular EX_TABLE program check handling. Acked-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/ipl_parm.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c index 86cfb16dd63d..b49c906b57dc 100644 --- a/arch/s390/boot/ipl_parm.c +++ b/arch/s390/boot/ipl_parm.c @@ -35,29 +35,14 @@ int vmalloc_size_set; static inline int __diag308(unsigned long subcode, void *addr) { - unsigned long reg1, reg2; - union register_pair r1; - psw_t old; + union register_pair r1 = { .even = (unsigned long)addr, .odd = 0 }; - r1.even = (unsigned long) addr; - r1.odd = 0; asm volatile( - " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" - " epsw %[reg1],%[reg2]\n" - " st %[reg1],0(%[psw_pgm])\n" - " st %[reg2],4(%[psw_pgm])\n" - " larl %[reg1],1f\n" - " stg %[reg1],8(%[psw_pgm])\n" " diag %[r1],%[subcode],0x308\n" - "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" - : [r1] "+&d" (r1.pair), - [reg1] "=&d" (reg1), - [reg2] "=&a" (reg2), - "+Q" (get_lowcore()->program_new_psw), - "=Q" (old) - : [subcode] "d" (subcode), - [psw_old] "a" (&old), - [psw_pgm] "a" (&get_lowcore()->program_new_psw) + "0:\n" + EX_TABLE(0b, 0b) + : [r1] "+d" (r1.pair) + : [subcode] "d" (subcode) : "cc", "memory"); return r1.odd; } -- cgit v1.2.3-59-g8ed1b From e9df614dad8ebe43ed15bef3b18789319a73e0f6 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 26 Feb 2025 11:03:04 +0100 Subject: s390/traps: Cleanup get_user() handling in illegal_op() The usage of get_user() in illegal_op() is quite unusual. Make the code more readable and get rid of unnecessary casts. The generated code is identical before/after this change. Reviewed-by: Sven Schnelle Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/traps.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 6db2c1466531..478c5871aefa 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -154,23 +154,23 @@ static void translation_specification_exception(struct pt_regs *regs) static void illegal_op(struct pt_regs *regs) { - __u8 opcode[6]; - __u16 __user *location; int is_uprobe_insn = 0; + u16 __user *location; int signal = 0; + u16 opcode; location = get_trap_ip(regs); if (user_mode(regs)) { - if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) + if (get_user(opcode, location)) return; - if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { + if (opcode == S390_BREAKPOINT_U16) { if (current->ptrace) force_sig_fault(SIGTRAP, TRAP_BRKPT, location); else signal = SIGILL; #ifdef CONFIG_UPROBES - } else if (*((__u16 *) opcode) == UPROBE_SWBP_INSN) { + } else if (opcode == UPROBE_SWBP_INSN) { is_uprobe_insn = 1; #endif } else -- cgit v1.2.3-59-g8ed1b From 5864614daf4a3e5dfa434e0f2f84e6d8cfe4126d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 26 Feb 2025 11:03:05 +0100 Subject: s390/traps: Use pr_emerg() instead of printk() Use pr_emerg() instead of printk() in case of a stack overflow, providing the emergency printk level. Also slightly adjust the printed text for pr_emerg() and panic(). Reviewed-by: Sven Schnelle Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/traps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 478c5871aefa..cabc38a38ae3 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -271,10 +271,10 @@ void kernel_stack_overflow(struct pt_regs *regs) */ kmsan_unpoison_entry_regs(regs); bust_spinlocks(1); - printk("Kernel stack overflow.\n"); + pr_emerg("Kernel stack overflow\n"); show_regs(regs); bust_spinlocks(0); - panic("Corrupt kernel stack, can't continue."); + panic("Corrupt kernel stack, cannot continue"); } NOKPROBE_SYMBOL(kernel_stack_overflow); -- cgit v1.2.3-59-g8ed1b From 8d5c2b495c10072df497252d73189a610a0721bd Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 26 Feb 2025 11:03:06 +0100 Subject: s390/traps: Get rid of superfluous cpu_has_vx() check If the vector facility is installed cpu_has_vx() is always true, if it is not installed the result is always false, and no vector exception can happen. Therefore remove the superfluous check. Reviewed-by: Sven Schnelle Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/traps.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index cabc38a38ae3..945522266037 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -198,11 +198,6 @@ static void vector_exception(struct pt_regs *regs) { int si_code, vic; - if (!cpu_has_vx()) { - do_trap(regs, SIGILL, ILL_ILLOPN, "illegal operation"); - return; - } - /* get vector interrupt code from fpc */ save_user_fpu_regs(); vic = (current->thread.ufpu.fpc & 0xf00) >> 8; -- cgit v1.2.3-59-g8ed1b From a9f24559d8e1423a27e0a25ebfdb6e51a8199a8b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 26 Feb 2025 11:03:07 +0100 Subject: s390/traps: Cleanup coding style Just some trivial whitespace and coding style changes. Reviewed-by: Sven Schnelle Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/traps.c | 79 +++++++++++++++--------------------------------- 1 file changed, 25 insertions(+), 54 deletions(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 945522266037..18dcc9280264 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -3,16 +3,12 @@ * S390 version * Copyright IBM Corp. 1999, 2000 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), - * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), + * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), * * Derived from "arch/i386/kernel/traps.c" * Copyright (C) 1991, 1992 Linus Torvalds */ -/* - * 'Traps.c' handles hardware traps and faults after we have saved some - * state in 'asm.s'. - */ #include #include #include @@ -43,7 +39,7 @@ static inline void __user *get_trap_ip(struct pt_regs *regs) address = current->thread.trap_tdb.data[3]; else address = regs->psw.addr; - return (void __user *) (address - (regs->int_code >> 16)); + return (void __user *)(address - (regs->int_code >> 16)); } #ifdef CONFIG_GENERIC_BUG @@ -58,16 +54,15 @@ void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str) if (user_mode(regs)) { force_sig_fault(si_signo, si_code, get_trap_ip(regs)); report_user_fault(regs, si_signo, 0); - } else { + } else { if (!fixup_exception(regs)) die(regs, str); - } + } } static void do_trap(struct pt_regs *regs, int si_signo, int si_code, char *str) { - if (notify_die(DIE_TRAP, str, regs, 0, - regs->int_code, si_signo) == NOTIFY_STOP) + if (notify_die(DIE_TRAP, str, regs, 0, regs->int_code, si_signo) == NOTIFY_STOP) return; do_report_trap(regs, si_signo, si_code, str); } @@ -79,8 +74,7 @@ void do_per_trap(struct pt_regs *regs) return; if (!current->ptrace) return; - force_sig_fault(SIGTRAP, TRAP_HWBKPT, - (void __force __user *) current->thread.per_event.address); + force_sig_fault(SIGTRAP, TRAP_HWBKPT, (void __force __user *)current->thread.per_event.address); } NOKPROBE_SYMBOL(do_per_trap); @@ -99,36 +93,25 @@ static void name(struct pt_regs *regs) \ do_trap(regs, signr, sicode, str); \ } -DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR, - "addressing exception") -DO_ERROR_INFO(execute_exception, SIGILL, ILL_ILLOPN, - "execute exception") -DO_ERROR_INFO(divide_exception, SIGFPE, FPE_INTDIV, - "fixpoint divide exception") -DO_ERROR_INFO(overflow_exception, SIGFPE, FPE_INTOVF, - "fixpoint overflow exception") -DO_ERROR_INFO(hfp_overflow_exception, SIGFPE, FPE_FLTOVF, - "HFP overflow exception") -DO_ERROR_INFO(hfp_underflow_exception, SIGFPE, FPE_FLTUND, - "HFP underflow exception") -DO_ERROR_INFO(hfp_significance_exception, SIGFPE, FPE_FLTRES, - "HFP significance exception") -DO_ERROR_INFO(hfp_divide_exception, SIGFPE, FPE_FLTDIV, - "HFP divide exception") -DO_ERROR_INFO(hfp_sqrt_exception, SIGFPE, FPE_FLTINV, - "HFP square root exception") -DO_ERROR_INFO(operand_exception, SIGILL, ILL_ILLOPN, - "operand exception") -DO_ERROR_INFO(privileged_op, SIGILL, ILL_PRVOPC, - "privileged operation") -DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN, - "special operation exception") -DO_ERROR_INFO(transaction_exception, SIGILL, ILL_ILLOPN, - "transaction constraint exception") +DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR, "addressing exception") +DO_ERROR_INFO(divide_exception, SIGFPE, FPE_INTDIV, "fixpoint divide exception") +DO_ERROR_INFO(execute_exception, SIGILL, ILL_ILLOPN, "execute exception") +DO_ERROR_INFO(hfp_divide_exception, SIGFPE, FPE_FLTDIV, "HFP divide exception") +DO_ERROR_INFO(hfp_overflow_exception, SIGFPE, FPE_FLTOVF, "HFP overflow exception") +DO_ERROR_INFO(hfp_significance_exception, SIGFPE, FPE_FLTRES, "HFP significance exception") +DO_ERROR_INFO(hfp_sqrt_exception, SIGFPE, FPE_FLTINV, "HFP square root exception") +DO_ERROR_INFO(hfp_underflow_exception, SIGFPE, FPE_FLTUND, "HFP underflow exception") +DO_ERROR_INFO(operand_exception, SIGILL, ILL_ILLOPN, "operand exception") +DO_ERROR_INFO(overflow_exception, SIGFPE, FPE_INTOVF, "fixpoint overflow exception") +DO_ERROR_INFO(privileged_op, SIGILL, ILL_PRVOPC, "privileged operation") +DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN, "special operation exception") +DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN, "specification exception"); +DO_ERROR_INFO(transaction_exception, SIGILL, ILL_ILLOPN, "transaction constraint exception") static inline void do_fp_trap(struct pt_regs *regs, __u32 fpc) { int si_code = 0; + /* FPC[2] is Data Exception Code */ if ((fpc & 0x00000300) == 0) { /* bits 6 and 7 of DXC are 0 iff IEEE exception */ @@ -160,7 +143,6 @@ static void illegal_op(struct pt_regs *regs) u16 opcode; location = get_trap_ip(regs); - if (user_mode(regs)) { if (get_user(opcode, location)) return; @@ -173,17 +155,17 @@ static void illegal_op(struct pt_regs *regs) } else if (opcode == UPROBE_SWBP_INSN) { is_uprobe_insn = 1; #endif - } else + } else { signal = SIGILL; + } } /* - * We got either an illegal op in kernel mode, or user space trapped + * This is either an illegal op in kernel mode, or user space trapped * on a uprobes illegal instruction. See if kprobes or uprobes picks * it up. If not, SIGILL. */ if (is_uprobe_insn || !user_mode(regs)) { - if (notify_die(DIE_BPT, "bpt", regs, 0, - 3, SIGTRAP) != NOTIFY_STOP) + if (notify_die(DIE_BPT, "bpt", regs, 0, 3, SIGTRAP) != NOTIFY_STOP) signal = SIGILL; } if (signal) @@ -191,9 +173,6 @@ static void illegal_op(struct pt_regs *regs) } NOKPROBE_SYMBOL(illegal_op); -DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN, - "specification exception"); - static void vector_exception(struct pt_regs *regs) { int si_code, vic; @@ -245,7 +224,6 @@ static void monitor_event_exception(struct pt_regs *regs) { if (user_mode(regs)) return; - switch (report_bug(regs->psw.addr - (regs->int_code >> 16), regs)) { case BUG_TRAP_TYPE_NONE: fixup_exception(regs); @@ -319,7 +297,6 @@ void noinstr __do_pgm_check(struct pt_regs *regs) teid.val = lc->trans_exc_code; regs->int_code = lc->pgm_int_code; regs->int_parm_long = teid.val; - /* * In case of a guest fault, short-circuit the fault handler and return. * This way the sie64a() function will return 0; fault address and @@ -332,9 +309,7 @@ void noinstr __do_pgm_check(struct pt_regs *regs) current->thread.gmap_int_code = regs->int_code & 0xffff; return; } - state = irqentry_enter(regs); - if (user_mode(regs)) { update_timer_sys(); if (!cpu_has_bear()) { @@ -343,12 +318,10 @@ void noinstr __do_pgm_check(struct pt_regs *regs) } current->thread.last_break = regs->last_break; } - if (lc->pgm_code & 0x0200) { /* transaction abort */ current->thread.trap_tdb = lc->pgm_tdb; } - if (lc->pgm_code & PGM_INT_CODE_PER) { if (user_mode(regs)) { struct per_event *ev = ¤t->thread.per_event; @@ -364,11 +337,9 @@ void noinstr __do_pgm_check(struct pt_regs *regs) goto out; } } - if (!irqs_disabled_flags(regs->psw.mask)) trace_hardirqs_on(); __arch_local_irq_ssm(regs->psw.mask & ~PSW_MASK_PER); - trapnr = regs->int_code & PGM_INT_CODE_MASK; if (trapnr) pgm_check_table[trapnr](regs); -- cgit v1.2.3-59-g8ed1b From f740a8b4df4faeda6cb595eddc5c486e4eedf573 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Thu, 27 Feb 2025 07:49:48 +0100 Subject: s390/traps: Change stack overflow message When the kernel stack pointer is pointing to invalid memory, a 'Kernel stack overflow' message is printed, which is misleading. Change the message to actually say that the stack pointer is invalid instead. Reviewed-by: Heiko Carstens Signed-off-by: Sven Schnelle Signed-off-by: Vasily Gorbik --- arch/s390/kernel/entry.S | 12 ++++++------ arch/s390/kernel/entry.h | 2 +- arch/s390/kernel/traps.c | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index ea4ddd37ea5a..b0c2356697fd 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -68,7 +68,7 @@ _LPP_OFFSET = __LC_LPP clg %r14,__LC_RESTART_STACK(\lowcore) je \oklabel la %r14,\savearea(\lowcore) - j stack_overflow + j stack_invalid .endm /* @@ -316,7 +316,7 @@ SYM_CODE_START(pgm_check_handler) tm __LC_PGM_ILC+3(%r13),0x80 # check for per exception jnz .Lpgm_svcper # -> single stepped svc 2: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) - # CHECK_VMAP_STACK branches to stack_overflow or 4f + # CHECK_VMAP_STACK branches to stack_invalid or 4f CHECK_VMAP_STACK __LC_SAVE_AREA,%r13,4f 3: lg %r15,__LC_KERNEL_STACK(%r13) 4: la %r11,STACK_FRAME_OVERHEAD(%r15) @@ -591,11 +591,11 @@ SYM_CODE_END(early_pgm_check_handler) .section .kprobes.text, "ax" /* - * The synchronous or the asynchronous stack overflowed. We are dead. + * The synchronous or the asynchronous stack pointer is invalid. We are dead. * No need to properly save the registers, we are going to panic anyway. * Setup a pt_regs so that show_trace can provide a good call trace. */ -SYM_CODE_START(stack_overflow) +SYM_CODE_START(stack_invalid) GET_LC %r15 lg %r15,__LC_NODAT_STACK(%r15) # change to panic stack la %r11,STACK_FRAME_OVERHEAD(%r15) @@ -605,8 +605,8 @@ SYM_CODE_START(stack_overflow) stg %r10,__PT_ORIG_GPR2(%r11) # store last break to orig_gpr2 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) lgr %r2,%r11 # pass pointer to pt_regs - jg kernel_stack_overflow -SYM_CODE_END(stack_overflow) + jg kernel_stack_invalid +SYM_CODE_END(stack_invalid) .section .data, "aw" .balign 4 diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index a1f28879c87e..dd55cc6bbc28 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h @@ -31,7 +31,7 @@ void do_secure_storage_access(struct pt_regs *regs); void do_non_secure_storage_access(struct pt_regs *regs); void do_secure_storage_violation(struct pt_regs *regs); void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str); -void kernel_stack_overflow(struct pt_regs * regs); +void kernel_stack_invalid(struct pt_regs *regs); void handle_signal32(struct ksignal *ksig, sigset_t *oldset, struct pt_regs *regs); diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 18dcc9280264..4daa3c76e999 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -236,7 +236,7 @@ static void monitor_event_exception(struct pt_regs *regs) } } -void kernel_stack_overflow(struct pt_regs *regs) +void kernel_stack_invalid(struct pt_regs *regs) { /* * Normally regs are unpoisoned by the generic entry code, but @@ -244,12 +244,12 @@ void kernel_stack_overflow(struct pt_regs *regs) */ kmsan_unpoison_entry_regs(regs); bust_spinlocks(1); - pr_emerg("Kernel stack overflow\n"); + pr_emerg("Kernel stack pointer invalid\n"); show_regs(regs); bust_spinlocks(0); - panic("Corrupt kernel stack, cannot continue"); + panic("Invalid kernel stack pointer, cannot continue"); } -NOKPROBE_SYMBOL(kernel_stack_overflow); +NOKPROBE_SYMBOL(kernel_stack_invalid); static void __init test_monitor_call(void) { -- cgit v1.2.3-59-g8ed1b From 08d95a12cd28009c2b4673f5f2e2cf65bc8d3402 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 28 Feb 2025 15:11:03 +0100 Subject: s390/atomic_ops: Let __atomic_add_const() variants always return void Depending on MARCH_HAS_Z196_FEATURES __atomic_add_const() returns void or the previous value before the atomic variant. Make sure that for both cases void is returned so potential incorrect usage results in both cases in a compile error. Reviewed-by: Juergen Christ Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/atomic_ops.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/s390/include/asm/atomic_ops.h b/arch/s390/include/asm/atomic_ops.h index 585678bbcd7a..21c26d842832 100644 --- a/arch/s390/include/asm/atomic_ops.h +++ b/arch/s390/include/asm/atomic_ops.h @@ -163,10 +163,10 @@ __ATOMIC64_OPS(__atomic64_xor, "xgr") #undef __ATOMIC64_OPS -#define __atomic_add_const(val, ptr) __atomic_add(val, ptr) -#define __atomic_add_const_barrier(val, ptr) __atomic_add(val, ptr) -#define __atomic64_add_const(val, ptr) __atomic64_add(val, ptr) -#define __atomic64_add_const_barrier(val, ptr) __atomic64_add(val, ptr) +#define __atomic_add_const(val, ptr) ((void)__atomic_add(val, ptr)) +#define __atomic_add_const_barrier(val, ptr) ((void)__atomic_add(val, ptr)) +#define __atomic64_add_const(val, ptr) ((void)__atomic64_add(val, ptr)) +#define __atomic64_add_const_barrier(val, ptr) ((void)__atomic64_add(val, ptr)) #endif /* MARCH_HAS_Z196_FEATURES */ -- cgit v1.2.3-59-g8ed1b From f8c425a94bad5bef4c31792de931470ab5e4bfae Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 4 Mar 2025 09:14:30 +0100 Subject: s390/mm: Use pgprot_val() instead of open coding Use pgprot_val() to get the page protection value, instead of accessing the structure member directly. The type of pgprot_t is supposed to be hidden from all users so that it can be changed; e.g. for STRICT_MM_TYPECHECKS. Reviewed-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/mm/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index f2298f7a3f21..c5164a96d2cf 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -285,7 +285,7 @@ int arch_add_memory(int nid, u64 start, u64 size, unsigned long size_pages = PFN_DOWN(size); int rc; - if (WARN_ON_ONCE(params->pgprot.pgprot != PAGE_KERNEL.pgprot)) + if (WARN_ON_ONCE(pgprot_val(params->pgprot) != pgprot_val(PAGE_KERNEL))) return -EINVAL; VM_BUG_ON(!mhp_range_allowed(start, size, true)); -- cgit v1.2.3-59-g8ed1b From bb2598c0d31bca8e57662b7d203e1876cd7f455f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 4 Mar 2025 09:14:31 +0100 Subject: s390/mm: Convert pgprot_val() into function Convert pgprot_val() into a function similar to other mm primitives like e.g. pte_val(). This disallows usage as an lvalue; however there aren't any such users left, except for some architecture specific ones. Reviewed-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/page.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 1ff145f7b52b..5a7d146e34d8 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h @@ -84,7 +84,11 @@ typedef struct { unsigned long p4d; } p4d_t; typedef struct { unsigned long pgd; } pgd_t; typedef pte_t *pgtable_t; -#define pgprot_val(x) ((x).pgprot) +static inline unsigned long pgprot_val(pgprot_t pgprot) +{ + return pgprot.pgprot; +} + #define pgste_val(x) ((x).pgste) static inline unsigned long pte_val(pte_t pte) @@ -112,13 +116,13 @@ static inline unsigned long pgd_val(pgd_t pgd) return pgd.pgd; } +#define __pgprot(x) ((pgprot_t) { (x) } ) #define __pgste(x) ((pgste_t) { (x) } ) #define __pte(x) ((pte_t) { (x) } ) #define __pmd(x) ((pmd_t) { (x) } ) #define __pud(x) ((pud_t) { (x) } ) #define __p4d(x) ((p4d_t) { (x) } ) #define __pgd(x) ((pgd_t) { (x) } ) -#define __pgprot(x) ((pgprot_t) { (x) } ) static inline void page_set_storage_key(unsigned long addr, unsigned char skey, int mapped) -- cgit v1.2.3-59-g8ed1b From 94d553ce576acc5f01f4368bc5188f45b56b6168 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 4 Mar 2025 09:14:32 +0100 Subject: s390/mm: Convert pgste_val() into function Similar to all other *_val() functions convert the last remaining architecture specific mm primitive pgste_val() into a function. Add set_pgste_bit() and clear_pgste_bit() helper functions which allow to clear and set pgste bits. This is also similar to e.g. set_pte_bit() and other helper functions. Acked-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/page.h | 5 ++++- arch/s390/include/asm/pgtable.h | 10 +++++++++ arch/s390/mm/pgtable.c | 50 ++++++++++++++++++++--------------------- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 5a7d146e34d8..8bd0901bdf9c 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h @@ -89,7 +89,10 @@ static inline unsigned long pgprot_val(pgprot_t pgprot) return pgprot.pgprot; } -#define pgste_val(x) ((x).pgste) +static inline unsigned long pgste_val(pgste_t pgste) +{ + return pgste.pgste; +} static inline unsigned long pte_val(pte_t pte) { diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 3ca5af4cfe43..144241dd218e 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -592,6 +592,16 @@ static inline int mm_alloc_pgste(struct mm_struct *mm) return 0; } +static inline pgste_t clear_pgste_bit(pgste_t pgste, unsigned long mask) +{ + return __pgste(pgste_val(pgste) & ~mask); +} + +static inline pgste_t set_pgste_bit(pgste_t pgste, unsigned long mask) +{ + return __pgste(pgste_val(pgste) | mask); +} + static inline pte_t clear_pte_bit(pte_t pte, pgprot_t prot) { return __pte(pte_val(pte) & ~pgprot_val(prot)); diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index f05e62e037c2..6d8ed561e568 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -173,10 +173,10 @@ static inline pgste_t pgste_update_all(pte_t pte, pgste_t pgste, skey = (unsigned long) page_get_storage_key(address); bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED); /* Transfer page changed & referenced bit to guest bits in pgste */ - pgste_val(pgste) |= bits << 48; /* GR bit & GC bit */ + pgste = set_pgste_bit(pgste, bits << 48); /* GR bit & GC bit */ /* Copy page access key and fetch protection bit to pgste */ - pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT); - pgste_val(pgste) |= (skey & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56; + pgste = clear_pgste_bit(pgste, PGSTE_ACC_BITS | PGSTE_FP_BIT); + pgste = set_pgste_bit(pgste, (skey & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56); #endif return pgste; @@ -220,7 +220,7 @@ static inline pgste_t pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry) } if (!(pte_val(entry) & _PAGE_PROTECT)) /* This pte allows write access, set user-dirty */ - pgste_val(pgste) |= PGSTE_UC_BIT; + pgste = set_pgste_bit(pgste, PGSTE_UC_BIT); } #endif set_pte(ptep, entry); @@ -236,7 +236,7 @@ static inline pgste_t pgste_pte_notify(struct mm_struct *mm, bits = pgste_val(pgste) & (PGSTE_IN_BIT | PGSTE_VSIE_BIT); if (bits) { - pgste_val(pgste) ^= bits; + pgste = __pgste(pgste_val(pgste) ^ bits); ptep_notify(mm, addr, ptep, bits); } #endif @@ -609,7 +609,7 @@ void ptep_set_pte_at(struct mm_struct *mm, unsigned long addr, /* the mm_has_pgste() check is done in set_pte_at() */ preempt_disable(); pgste = pgste_get_lock(ptep); - pgste_val(pgste) &= ~_PGSTE_GPS_ZERO; + pgste = clear_pgste_bit(pgste, _PGSTE_GPS_ZERO); pgste_set_key(ptep, pgste, entry, mm); pgste = pgste_set_pte(ptep, pgste, entry); pgste_set_unlock(ptep, pgste); @@ -622,7 +622,7 @@ void ptep_set_notify(struct mm_struct *mm, unsigned long addr, pte_t *ptep) preempt_disable(); pgste = pgste_get_lock(ptep); - pgste_val(pgste) |= PGSTE_IN_BIT; + pgste = set_pgste_bit(pgste, PGSTE_IN_BIT); pgste_set_unlock(ptep, pgste); preempt_enable(); } @@ -667,7 +667,7 @@ int ptep_force_prot(struct mm_struct *mm, unsigned long addr, entry = clear_pte_bit(entry, __pgprot(_PAGE_INVALID)); entry = set_pte_bit(entry, __pgprot(_PAGE_PROTECT)); } - pgste_val(pgste) |= bit; + pgste = set_pgste_bit(pgste, bit); pgste = pgste_set_pte(ptep, pgste, entry); pgste_set_unlock(ptep, pgste); return 0; @@ -687,7 +687,7 @@ int ptep_shadow_pte(struct mm_struct *mm, unsigned long saddr, if (!(pte_val(spte) & _PAGE_INVALID) && !((pte_val(spte) & _PAGE_PROTECT) && !(pte_val(pte) & _PAGE_PROTECT))) { - pgste_val(spgste) |= PGSTE_VSIE_BIT; + spgste = set_pgste_bit(spgste, PGSTE_VSIE_BIT); tpgste = pgste_get_lock(tptep); tpte = __pte((pte_val(spte) & PAGE_MASK) | (pte_val(pte) & _PAGE_PROTECT)); @@ -745,7 +745,7 @@ void ptep_zap_unused(struct mm_struct *mm, unsigned long addr, pte_clear(mm, addr, ptep); } if (reset) - pgste_val(pgste) &= ~(_PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT); + pgste = clear_pgste_bit(pgste, _PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT); pgste_set_unlock(ptep, pgste); preempt_enable(); } @@ -758,8 +758,8 @@ void ptep_zap_key(struct mm_struct *mm, unsigned long addr, pte_t *ptep) /* Clear storage key ACC and F, but set R/C */ preempt_disable(); pgste = pgste_get_lock(ptep); - pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT); - pgste_val(pgste) |= PGSTE_GR_BIT | PGSTE_GC_BIT; + pgste = clear_pgste_bit(pgste, PGSTE_ACC_BITS | PGSTE_FP_BIT); + pgste = set_pgste_bit(pgste, PGSTE_GR_BIT | PGSTE_GC_BIT); ptev = pte_val(*ptep); if (!(ptev & _PAGE_INVALID) && (ptev & _PAGE_WRITE)) page_set_storage_key(ptev & PAGE_MASK, PAGE_DEFAULT_KEY, 0); @@ -780,7 +780,7 @@ bool ptep_test_and_clear_uc(struct mm_struct *mm, unsigned long addr, pgste = pgste_get_lock(ptep); dirty = !!(pgste_val(pgste) & PGSTE_UC_BIT); - pgste_val(pgste) &= ~PGSTE_UC_BIT; + pgste = clear_pgste_bit(pgste, PGSTE_UC_BIT); pte = *ptep; if (dirty && (pte_val(pte) & _PAGE_PRESENT)) { pgste = pgste_pte_notify(mm, addr, ptep, pgste); @@ -842,11 +842,11 @@ again: if (!ptep) goto again; new = old = pgste_get_lock(ptep); - pgste_val(new) &= ~(PGSTE_GR_BIT | PGSTE_GC_BIT | - PGSTE_ACC_BITS | PGSTE_FP_BIT); + new = clear_pgste_bit(new, PGSTE_GR_BIT | PGSTE_GC_BIT | + PGSTE_ACC_BITS | PGSTE_FP_BIT); keyul = (unsigned long) key; - pgste_val(new) |= (keyul & (_PAGE_CHANGED | _PAGE_REFERENCED)) << 48; - pgste_val(new) |= (keyul & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56; + new = set_pgste_bit(new, (keyul & (_PAGE_CHANGED | _PAGE_REFERENCED)) << 48); + new = set_pgste_bit(new, (keyul & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56); if (!(pte_val(*ptep) & _PAGE_INVALID)) { unsigned long bits, skey; @@ -857,12 +857,12 @@ again: /* Set storage key ACC and FP */ page_set_storage_key(paddr, skey, !nq); /* Merge host changed & referenced into pgste */ - pgste_val(new) |= bits << 52; + new = set_pgste_bit(new, bits << 52); } /* changing the guest storage key is considered a change of the page */ if ((pgste_val(new) ^ pgste_val(old)) & (PGSTE_ACC_BITS | PGSTE_FP_BIT | PGSTE_GR_BIT | PGSTE_GC_BIT)) - pgste_val(new) |= PGSTE_UC_BIT; + new = set_pgste_bit(new, PGSTE_UC_BIT); pgste_set_unlock(ptep, new); pte_unmap_unlock(ptep, ptl); @@ -950,19 +950,19 @@ again: goto again; new = old = pgste_get_lock(ptep); /* Reset guest reference bit only */ - pgste_val(new) &= ~PGSTE_GR_BIT; + new = clear_pgste_bit(new, PGSTE_GR_BIT); if (!(pte_val(*ptep) & _PAGE_INVALID)) { paddr = pte_val(*ptep) & PAGE_MASK; cc = page_reset_referenced(paddr); /* Merge real referenced bit into host-set */ - pgste_val(new) |= ((unsigned long) cc << 53) & PGSTE_HR_BIT; + new = set_pgste_bit(new, ((unsigned long)cc << 53) & PGSTE_HR_BIT); } /* Reflect guest's logical view, not physical */ cc |= (pgste_val(old) & (PGSTE_GR_BIT | PGSTE_GC_BIT)) >> 49; /* Changing the guest storage key is considered a change of the page */ if ((pgste_val(new) ^ pgste_val(old)) & PGSTE_GR_BIT) - pgste_val(new) |= PGSTE_UC_BIT; + new = set_pgste_bit(new, PGSTE_UC_BIT); pgste_set_unlock(ptep, new); pte_unmap_unlock(ptep, ptl); @@ -1126,7 +1126,7 @@ int pgste_perform_essa(struct mm_struct *mm, unsigned long hva, int orc, if (res) pgstev |= _PGSTE_GPS_ZERO; - pgste_val(pgste) = pgstev; + pgste = __pgste(pgstev); pgste_set_unlock(ptep, pgste); pte_unmap_unlock(ptep, ptl); return res; @@ -1159,8 +1159,8 @@ int set_pgste_bits(struct mm_struct *mm, unsigned long hva, return -EFAULT; new = pgste_get_lock(ptep); - pgste_val(new) &= ~bits; - pgste_val(new) |= value & bits; + new = clear_pgste_bit(new, bits); + new = set_pgste_bit(new, value & bits); pgste_set_unlock(ptep, new); pte_unmap_unlock(ptep, ptl); -- cgit v1.2.3-59-g8ed1b From 03544866df1bc78fe740fc9d17816874ba7bde5a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 4 Mar 2025 09:14:33 +0100 Subject: s390/mm: Add configurable STRICT_MM_TYPECHECKS Add support for configurable STRICT_MM_TYPECHECKS. The s390 ABI defines that return values with complex types like structures and unions are returned in a return value buffer allocated by the caller. This is also true for small structures and unions which would fit into a register. On the other hand when such types are passed as arguments to functions they are passed in registers, if they are small enough. This leads to inefficient code when such a return value of a function call is then passed as argument to a subsequent function call. This is especially true for all mm types, like pte_t and others, which are only for type checking reasons defined as a structure. This however can be bypassed with the STRICT_MM_TYPECHECKS feature, which is used by a few other architectures, which seem to have the same problem. Add CONFIG_STRICT_MM_TYPECHECKS which can be used to change the type of pte_t and other structures. If the config option is not enabled the types are defined to unsigned long, allowing for better code generation, however there is no type checking anymore. If it is enabled the types are structures like before so that type checking is performed, but less efficient code is generated. The option is always enabled in debug_defconfig, and for convenience an mmtypes.config topic target is added, which allows to easily enable it, in case memory management code is changed. CONFIG_STRICT_MM_TYPECHECKS and STRICT_MM_TYPECHECKS are kept separate, since STRICT_MM_TYPECHECKS is common across architectures and common code. Therefore use the same define also for s390 code. Add CONFIG_STRICT_MM_TYPECHECKS to make it build time configurable. Reviewed-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/Kconfig.debug | 10 +++++++ arch/s390/configs/debug_defconfig | 1 + arch/s390/configs/mmtypes.config | 2 ++ arch/s390/include/asm/page.h | 60 +++++++++++++++++++-------------------- 4 files changed, 43 insertions(+), 30 deletions(-) create mode 100644 arch/s390/configs/mmtypes.config diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug index c4300ea4abf8..7955d7eee7d8 100644 --- a/arch/s390/Kconfig.debug +++ b/arch/s390/Kconfig.debug @@ -13,6 +13,16 @@ config DEBUG_ENTRY If unsure, say N. +config STRICT_MM_TYPECHECKS + bool "Strict Memory Management Type Checks" + depends on DEBUG_KERNEL + help + Enable strict type checking for memory management types like pte_t + and pmd_t. This generates slightly worse code and should be used + for debug builds. + + If unsure, say N. + config CIO_INJECT bool "CIO Inject interfaces" depends on DEBUG_KERNEL && DEBUG_FS diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index d6beec5292a0..e0d39aa03fc5 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -893,6 +893,7 @@ CONFIG_SAMPLE_FTRACE_DIRECT=m CONFIG_SAMPLE_FTRACE_DIRECT_MULTI=m CONFIG_SAMPLE_FTRACE_OPS=m CONFIG_DEBUG_ENTRY=y +CONFIG_STRICT_MM_TYPECHECKS=y CONFIG_CIO_INJECT=y CONFIG_KUNIT=m CONFIG_KUNIT_DEBUGFS=y diff --git a/arch/s390/configs/mmtypes.config b/arch/s390/configs/mmtypes.config new file mode 100644 index 000000000000..fe32b442d789 --- /dev/null +++ b/arch/s390/configs/mmtypes.config @@ -0,0 +1,2 @@ +# Help: Enable strict memory management typechecks +CONFIG_STRICT_MM_TYPECHECKS=y diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 8bd0901bdf9c..4e5dbabdf202 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h @@ -71,9 +71,11 @@ static inline void copy_page(void *to, void *from) #define vma_alloc_zeroed_movable_folio(vma, vaddr) \ vma_alloc_folio(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr) -/* - * These are used to make use of C type-checking.. - */ +#ifdef CONFIG_STRICT_MM_TYPECHECKS +#define STRICT_MM_TYPECHECKS +#endif + +#ifdef STRICT_MM_TYPECHECKS typedef struct { unsigned long pgprot; } pgprot_t; typedef struct { unsigned long pgste; } pgste_t; @@ -82,42 +84,40 @@ typedef struct { unsigned long pmd; } pmd_t; typedef struct { unsigned long pud; } pud_t; typedef struct { unsigned long p4d; } p4d_t; typedef struct { unsigned long pgd; } pgd_t; -typedef pte_t *pgtable_t; -static inline unsigned long pgprot_val(pgprot_t pgprot) -{ - return pgprot.pgprot; +#define DEFINE_PGVAL_FUNC(name) \ +static __always_inline unsigned long name ## _val(name ## _t name) \ +{ \ + return name.name; \ } -static inline unsigned long pgste_val(pgste_t pgste) -{ - return pgste.pgste; -} +#else /* STRICT_MM_TYPECHECKS */ -static inline unsigned long pte_val(pte_t pte) -{ - return pte.pte; -} +typedef unsigned long pgprot_t; +typedef unsigned long pgste_t; +typedef unsigned long pte_t; +typedef unsigned long pmd_t; +typedef unsigned long pud_t; +typedef unsigned long p4d_t; +typedef unsigned long pgd_t; -static inline unsigned long pmd_val(pmd_t pmd) -{ - return pmd.pmd; +#define DEFINE_PGVAL_FUNC(name) \ +static __always_inline unsigned long name ## _val(name ## _t name) \ +{ \ + return name; \ } -static inline unsigned long pud_val(pud_t pud) -{ - return pud.pud; -} +#endif /* STRICT_MM_TYPECHECKS */ -static inline unsigned long p4d_val(p4d_t p4d) -{ - return p4d.p4d; -} +DEFINE_PGVAL_FUNC(pgprot) +DEFINE_PGVAL_FUNC(pgste) +DEFINE_PGVAL_FUNC(pte) +DEFINE_PGVAL_FUNC(pmd) +DEFINE_PGVAL_FUNC(pud) +DEFINE_PGVAL_FUNC(p4d) +DEFINE_PGVAL_FUNC(pgd) -static inline unsigned long pgd_val(pgd_t pgd) -{ - return pgd.pgd; -} +typedef pte_t *pgtable_t; #define __pgprot(x) ((pgprot_t) { (x) } ) #define __pgste(x) ((pgste_t) { (x) } ) -- cgit v1.2.3-59-g8ed1b From c94bff63e49302d4ce36502a85a2710a67332a4f Mon Sep 17 00:00:00 2001 From: Niklas Schnelle Date: Fri, 21 Feb 2025 12:51:48 +0100 Subject: s390: Remove ioremap_wt() and pgprot_writethrough() It turns out that while s390 architecture calls its memory-I/O mapping variants write-through and write-back the implementation of ioremap_wt() and pgprot_writethrough() does not match Linux notion of ioremap_wt(). In particular Linux expects ioremap_wt() to be weaker still than ioremap_wc(), allowing not just gathering and re-ordering but also reads to be served from cache. Instead s390's implementation is equivalent to normal ioremap() while its ioremap_wc() allows re-ordering. Note that there are no known users of ioremap_wt() on s390 and the resulting behavior is in line with asm-generic defining ioremap_wt() as ioremap(), if undefined, so no breakage is expected. As s390 does not have a mapping type matching the Linux notion of ioremap_wt() and pgprot_writethrough(), simply drop them and rely on the asm-generic fallbacks instead. Fixes: b02002cc4c0f ("s390/pci: Implement ioremap_wc/prot() with MIO") Fixes: b43b3fff042d ("s390: mm: convert to GENERIC_IOREMAP") Acked-by: Heiko Carstens Signed-off-by: Niklas Schnelle Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/io.h | 2 -- arch/s390/include/asm/pgtable.h | 3 --- arch/s390/mm/pgtable.c | 10 ---------- 3 files changed, 15 deletions(-) diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h index fc9933a743d6..251e0372ccbd 100644 --- a/arch/s390/include/asm/io.h +++ b/arch/s390/include/asm/io.h @@ -34,8 +34,6 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr); #define ioremap_wc(addr, size) \ ioremap_prot((addr), (size), pgprot_val(pgprot_writecombine(PAGE_KERNEL))) -#define ioremap_wt(addr, size) \ - ioremap_prot((addr), (size), pgprot_val(pgprot_writethrough(PAGE_KERNEL))) static inline void __iomem *ioport_map(unsigned long port, unsigned int nr) { diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index fb757f5e220b..e9c2d81f11f8 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -1403,9 +1403,6 @@ void gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr); #define pgprot_writecombine pgprot_writecombine pgprot_t pgprot_writecombine(pgprot_t prot); -#define pgprot_writethrough pgprot_writethrough -pgprot_t pgprot_writethrough(pgprot_t prot); - #define PFN_PTE_SHIFT PAGE_SHIFT /* diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index e20fd4c14562..fa66246c1851 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -36,16 +36,6 @@ pgprot_t pgprot_writecombine(pgprot_t prot) } EXPORT_SYMBOL_GPL(pgprot_writecombine); -pgprot_t pgprot_writethrough(pgprot_t prot) -{ - /* - * mio_wb_bit_mask may be set on a different CPU, but it is only set - * once at init and only read afterwards. - */ - return __pgprot(pgprot_val(prot) & ~mio_wb_bit_mask); -} -EXPORT_SYMBOL_GPL(pgprot_writethrough); - static inline void ptep_ipte_local(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int nodat) { -- cgit v1.2.3-59-g8ed1b From cbf367d5b0aaf4b9d2d411a6cb1637148695fa53 Mon Sep 17 00:00:00 2001 From: Rorie Reyes Date: Tue, 4 Mar 2025 15:08:12 -0500 Subject: s390/vfio-ap: Notify userspace that guest's AP config changed when mdev removed The guest's AP configuration is cleared when the mdev is removed, so userspace must be notified that the AP configuration has changed. To this end, this patch: * Removes call to 'signal_guest_ap_cfg_changed()' function from the 'vfio_ap_mdev_unset_kvm()' function because it has no affect given it is called after the mdev fd is closed. * Adds call to 'signal_guest_ap_cfg_changed()' function to the 'vfio_ap_mdev_request()' function to notify userspace that the guest's AP configuration has changed before signaling the request to remove the mdev. Minor change - Fixed an indentation issue in function 'signal_guest_ap_cfg_changed()' Fixes: 07d89045bffe ("s390/vfio-ap: Signal eventfd when guest AP configuration is changed") Signed-off-by: Rorie Reyes Reviewed-by: Anthony Krowiak Link: https://lore.kernel.org/r/20250304200812.54556-1-rreyes@linux.ibm.com Signed-off-by: Vasily Gorbik --- drivers/s390/crypto/vfio_ap_ops.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index 571f5dcb49c5..bc8669b5c304 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c @@ -652,8 +652,8 @@ static void vfio_ap_matrix_init(struct ap_config_info *info, static void signal_guest_ap_cfg_changed(struct ap_matrix_mdev *matrix_mdev) { - if (matrix_mdev->cfg_chg_trigger) - eventfd_signal(matrix_mdev->cfg_chg_trigger); + if (matrix_mdev->cfg_chg_trigger) + eventfd_signal(matrix_mdev->cfg_chg_trigger); } static void vfio_ap_mdev_update_guest_apcb(struct ap_matrix_mdev *matrix_mdev) @@ -1870,7 +1870,6 @@ static void vfio_ap_mdev_unset_kvm(struct ap_matrix_mdev *matrix_mdev) get_update_locks_for_kvm(kvm); kvm_arch_crypto_clear_masks(kvm); - signal_guest_ap_cfg_changed(matrix_mdev); vfio_ap_mdev_reset_queues(matrix_mdev); kvm_put_kvm(kvm); matrix_mdev->kvm = NULL; @@ -2057,6 +2056,13 @@ static void vfio_ap_mdev_request(struct vfio_device *vdev, unsigned int count) matrix_mdev = container_of(vdev, struct ap_matrix_mdev, vdev); + get_update_locks_for_mdev(matrix_mdev); + + if (matrix_mdev->kvm) { + kvm_arch_crypto_clear_masks(matrix_mdev->kvm); + signal_guest_ap_cfg_changed(matrix_mdev); + } + if (matrix_mdev->req_trigger) { if (!(count % 10)) dev_notice_ratelimited(dev, @@ -2068,6 +2074,8 @@ static void vfio_ap_mdev_request(struct vfio_device *vdev, unsigned int count) dev_notice(dev, "No device request registered, blocked until released by user\n"); } + + release_update_locks_for_mdev(matrix_mdev); } static int vfio_ap_mdev_get_device_info(unsigned long arg) -- cgit v1.2.3-59-g8ed1b From 8751b6e9e4abf3603b567e871768eb8cca8ef91a Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Thu, 27 Feb 2025 08:22:07 +0100 Subject: s390/syscall: Simplify syscall_get_arguments() Replace the while loop and if statement with a simple for loop to make the code easier to understand. Signed-off-by: Sven Schnelle Reviewed-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/syscall.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h index 27e3d804b311..0213ec800b57 100644 --- a/arch/s390/include/asm/syscall.h +++ b/arch/s390/include/asm/syscall.h @@ -65,15 +65,13 @@ static inline void syscall_get_arguments(struct task_struct *task, unsigned long *args) { unsigned long mask = -1UL; - unsigned int n = 6; #ifdef CONFIG_COMPAT if (test_tsk_thread_flag(task, TIF_31BIT)) mask = 0xffffffff; #endif - while (n-- > 0) - if (n > 0) - args[n] = regs->gprs[2 + n] & mask; + for (int i = 1; i < 6; i++) + args[i] = regs->gprs[2 + i] & mask; args[0] = regs->orig_gpr2 & mask; } -- cgit v1.2.3-59-g8ed1b From 20de8f8d3178c695ed2f90bd81ff0b6df8cd32e8 Mon Sep 17 00:00:00 2001 From: joel granados Date: Thu, 6 Mar 2025 12:29:46 +0100 Subject: s390: Move s390 sysctls into their own file under arch/s390 Move s390 sysctls (spin_retry and userprocess_debug) into their own files under arch/s390. Create two new sysctl tables (2390_{fault,spin}_sysctl_table) which will be initialized with arch_initcall placing them after their original place in proc_root_init. This is part of a greater effort to move ctl tables into their respective subsystems which will reduce the merge conflicts in kernel/sysctl.c. Signed-off-by: joel granados Acked-by: Heiko Carstens Link: https://lore.kernel.org/r/20250306-jag-mv_ctltables-v2-6-71b243c8d3f8@kernel.org Signed-off-by: Vasily Gorbik --- arch/s390/lib/spinlock.c | 18 ++++++++++++++++++ arch/s390/mm/fault.c | 17 +++++++++++++++++ kernel/sysctl.c | 18 ------------------ 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index 9d5669d449f2..0c895c869ebd 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,23 @@ static int __init spin_retry_setup(char *str) } __setup("spin_retry=", spin_retry_setup); +static const struct ctl_table s390_spin_sysctl_table[] = { + { + .procname = "spin_retry", + .data = &spin_retry, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, +}; + +static int __init init_s390_spin_sysctls(void) +{ + register_sysctl_init("kernel", s390_spin_sysctl_table); + return 0; +} +arch_initcall(init_s390_spin_sysctls); + struct spin_wait { struct spin_wait *next, *prev; int node_id; diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 13d8c44bf8ed..31a763e05287 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -165,6 +165,23 @@ static void dump_fault_info(struct pt_regs *regs) int show_unhandled_signals = 1; +static const struct ctl_table s390_fault_sysctl_table[] = { + { + .procname = "userprocess_debug", + .data = &show_unhandled_signals, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, +}; + +static int __init init_s390_fault_sysctls(void) +{ + register_sysctl_init("kernel", s390_fault_sysctl_table); + return 0; +} +arch_initcall(init_s390_fault_sysctls); + void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault) { static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index cb57da499ebb..6c70fb3b2376 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1794,15 +1794,6 @@ static const struct ctl_table kern_table[] = { .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_MAXOLDUID, }, -#ifdef CONFIG_S390 - { - .procname = "userprocess_debug", - .data = &show_unhandled_signals, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, -#endif { .procname = "panic_on_oops", .data = &panic_on_oops, @@ -1897,15 +1888,6 @@ static const struct ctl_table kern_table[] = { .proc_handler = proc_dointvec, }, #endif -#if defined(CONFIG_S390) && defined(CONFIG_SMP) - { - .procname = "spin_retry", - .data = &spin_retry, - .maxlen = sizeof (int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, -#endif #if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86) { .procname = "acpi_video_flags", -- cgit v1.2.3-59-g8ed1b From 430693c836c3828c72db2e1b1a7d2ddc97509cb8 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 10 Mar 2025 10:33:38 +0100 Subject: s390/lowcore: Use inline qualifier for get_lowcore() inline assembly Use asm_inline to let the compiler know that the get_lowcore() inline assembly has the smallest possible size. The ALTERNATIVE construct is used to generate a single instruction, however the macro expands to multiple lines. GCC uses the number of lines of an inline assembly to count the number of instructions within an inline assembly, which then has an effect on inlining decisions. In order to avoid incorrect assumptions use asm_inline. The result is that more functions are inlined, which results in a small growth of the kernel image: add/remove: 59/480 grow/shrink: 854/647 up/down: 168780/-162394 (6386) Reviewed-by: Juergen Christ Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/lowcore.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 8067edd120eb..ada93ab7802a 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -223,9 +223,12 @@ static __always_inline struct lowcore *get_lowcore(void) if (__is_defined(__DECOMPRESSOR)) return NULL; - asm(ALTERNATIVE("llilh %[lc],0", "llilh %[lc],%[alt]", ALT_FEATURE(MFEATURE_LOWCORE)) - : [lc] "=d" (lc) - : [alt] "i" (LOWCORE_ALT_ADDRESS >> 16)); + asm_inline( + ALTERNATIVE(" llilh %[lc],0", + " llilh %[lc],%[alt]", + ALT_FEATURE(MFEATURE_LOWCORE)) + : [lc] "=d" (lc) + : [alt] "i" (LOWCORE_ALT_ADDRESS >> 16)); return lc; } -- cgit v1.2.3-59-g8ed1b From 65c07e91cc31700ca8484d3bcd96e49b0053b57b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 10 Mar 2025 10:33:39 +0100 Subject: s390/current: Implement current with inline assembly Implement current with an inline assembly, which makes use of the ALTERNATIVE macro, to read current from lowcore. Provide an alternative instruction with a different offset in case lowcore is relocated. This replaces sequences of two instructions with one instruction. Before: 100076: a5 1e 00 00 llilh %r1,0 10007a: e3 40 13 40 00 04 lg %r4,832(%r1) After: 100076: e3 10 03 40 00 04 lg %r1,832 Kernel image size change: add/remove: 3/17 grow/shrink: 166/2204 up/down: 7122/-24594 (-17472) Reviewed-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/current.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/s390/include/asm/current.h b/arch/s390/include/asm/current.h index d03a922c641e..f9529f7cf62c 100644 --- a/arch/s390/include/asm/current.h +++ b/arch/s390/include/asm/current.h @@ -11,9 +11,25 @@ #define _S390_CURRENT_H #include +#include struct task_struct; -#define current ((struct task_struct *const)get_lowcore()->current_task) +static __always_inline struct task_struct *get_current(void) +{ + unsigned long ptr, lc_current; + + lc_current = offsetof(struct lowcore, current_task); + asm_inline( + ALTERNATIVE(" lg %[ptr],%[offzero](%%r0)\n", + " lg %[ptr],%[offalt](%%r0)\n", + ALT_FEATURE(MFEATURE_LOWCORE)) + : [ptr] "=d" (ptr) + : [offzero] "i" (lc_current), + [offalt] "i" (lc_current + LOWCORE_ALT_ADDRESS)); + return (struct task_struct *)ptr; +} + +#define current get_current() #endif /* !(_S390_CURRENT_H) */ -- cgit v1.2.3-59-g8ed1b From 4797e9b5067e3682020b3f6745a929d690370be3 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 10 Mar 2025 10:33:40 +0100 Subject: s390/smp: Implement raw_smp_processor_id() with inline assembly Implement raw_smp_processor_id() with an inline assembly, which makes use of the ALTERNATIVE macro, to read cpu_nr from lowcore. Provide an alternative instruction with a different offset in case lowcore is relocated. This replaces sequences of two instructions with one instruction. Before: 1000b6: a5 1e 00 00 llilh %r1,0 1000ba: 58 20 13 a0 l %r2,928(%r1) After: 1000b6: e3 20 03 a0 00 58 ly %r2,928 Kernel image size change: add/remove: 753/755 grow/shrink: 230/1510 up/down: 30538/-35832 (-5294) Acked-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/smp.h | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index 7feca96c48c6..03f4d01664f8 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h @@ -7,11 +7,29 @@ #ifndef __ASM_SMP_H #define __ASM_SMP_H -#include -#include #include +#include +#include +#include + +static __always_inline unsigned int raw_smp_processor_id(void) +{ + unsigned long lc_cpu_nr; + unsigned int cpu; + + BUILD_BUG_ON(sizeof_field(struct lowcore, cpu_nr) != sizeof(cpu)); + lc_cpu_nr = offsetof(struct lowcore, cpu_nr); + asm_inline( + ALTERNATIVE(" ly %[cpu],%[offzero](%%r0)\n", + " ly %[cpu],%[offalt](%%r0)\n", + ALT_FEATURE(MFEATURE_LOWCORE)) + : [cpu] "=d" (cpu) + : [offzero] "i" (lc_cpu_nr), + [offalt] "i" (lc_cpu_nr + LOWCORE_ALT_ADDRESS), + "m" (((struct lowcore *)0)->cpu_nr)); + return cpu; +} -#define raw_smp_processor_id() (get_lowcore()->cpu_nr) #define arch_scale_cpu_capacity smp_cpu_get_capacity extern struct mutex smp_cpu_state_mutex; -- cgit v1.2.3-59-g8ed1b From b46525437e1728596fda558894011ce64e5b0a9f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 10 Mar 2025 10:33:41 +0100 Subject: s390/spinlock: Implement SPINLOCK_LOCKVAL with inline assembly Implement SPINLOCK_LOCKVAL with an inline assembly, which makes use of the ALTERNATIVE macro, to read spinlock_lockval from lowcore. Provide an alternative instruction with a different offset in case lowcore is relocated. This replaces sequences of two instructions with one instruction. Before: 10602a: a7 78 00 00 lhi %r7,0 10602e: a5 8e 00 00 llilh %r8,0 106032: 58 d0 83 ac l %r13,940(%r8) 106036: ba 7d b5 80 cs %r7,%r13,1408(%r11) After: 10602a: a7 88 00 00 lhi %r8,0 10602e: e3 70 03 ac 00 58 ly %r7,940 106034: ba 87 b5 80 cs %r8,%r7,1408(%r11) Kernel image size change: add/remove: 756/750 grow/shrink: 646/3435 up/down: 30778/-46326 (-15548) Acked-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/spinlock.h | 20 ++++++++++++++++++-- arch/s390/lib/spinlock.c | 6 +++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h index f87dd0a84855..f9935db9fd76 100644 --- a/arch/s390/include/asm/spinlock.h +++ b/arch/s390/include/asm/spinlock.h @@ -16,7 +16,23 @@ #include #include -#define SPINLOCK_LOCKVAL (get_lowcore()->spinlock_lockval) +static __always_inline unsigned int spinlock_lockval(void) +{ + unsigned long lc_lockval; + unsigned int lockval; + + BUILD_BUG_ON(sizeof_field(struct lowcore, spinlock_lockval) != sizeof(lockval)); + lc_lockval = offsetof(struct lowcore, spinlock_lockval); + asm_inline( + ALTERNATIVE(" ly %[lockval],%[offzero](%%r0)\n", + " ly %[lockval],%[offalt](%%r0)\n", + ALT_FEATURE(MFEATURE_LOWCORE)) + : [lockval] "=d" (lockval) + : [offzero] "i" (lc_lockval), + [offalt] "i" (lc_lockval + LOWCORE_ALT_ADDRESS), + "m" (((struct lowcore *)0)->spinlock_lockval)); + return lockval; +} extern int spin_retry; @@ -60,7 +76,7 @@ static inline int arch_spin_trylock_once(arch_spinlock_t *lp) int old = 0; barrier(); - return likely(arch_try_cmpxchg(&lp->lock, &old, SPINLOCK_LOCKVAL)); + return likely(arch_try_cmpxchg(&lp->lock, &old, spinlock_lockval())); } static inline void arch_spin_lock(arch_spinlock_t *lp) diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index 0c895c869ebd..ad9da4038511 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -160,7 +160,7 @@ static inline void arch_spin_lock_queued(arch_spinlock_t *lp) ix = get_lowcore()->spinlock_index++; barrier(); - lockval = SPINLOCK_LOCKVAL; /* cpu + 1 */ + lockval = spinlock_lockval(); /* cpu + 1 */ node = this_cpu_ptr(&spin_wait[ix]); node->prev = node->next = NULL; node_id = node->node_id; @@ -251,7 +251,7 @@ static inline void arch_spin_lock_classic(arch_spinlock_t *lp) { int lockval, old, new, owner, count; - lockval = SPINLOCK_LOCKVAL; /* cpu + 1 */ + lockval = spinlock_lockval(); /* cpu + 1 */ /* Pass the virtual CPU to the lock holder if it is not running */ owner = arch_spin_yield_target(READ_ONCE(lp->lock), NULL); @@ -290,7 +290,7 @@ EXPORT_SYMBOL(arch_spin_lock_wait); int arch_spin_trylock_retry(arch_spinlock_t *lp) { - int cpu = SPINLOCK_LOCKVAL; + int cpu = spinlock_lockval(); int owner, count; for (count = spin_retry; count > 0; count--) { -- cgit v1.2.3-59-g8ed1b From a0f2a8d05152512633b256459e9aceb7e588f372 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 10 Mar 2025 10:33:42 +0100 Subject: s390/syscall: Merge __do_syscall() and do_syscall() The compiler inlines do_syscall() into __do_syscall(). Therefore do this in C code as well, since this makes the code easier to understand. Also adjust and add various unlikely() and likely() annotations. Furthermore this allows to replace the separate exit_to_user_mode() and syscall_exit_to_user_mode_work() calls with a combined syscall_exit_to_user_mode() call which results in slightly better code. Acked-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/syscall.c | 47 +++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/arch/s390/kernel/syscall.c b/arch/s390/kernel/syscall.c index c8df656b08bc..535f3922ffa9 100644 --- a/arch/s390/kernel/syscall.c +++ b/arch/s390/kernel/syscall.c @@ -82,25 +82,35 @@ SYSCALL_DEFINE0(ni_syscall) return -ENOSYS; } -static void do_syscall(struct pt_regs *regs) +void noinstr __do_syscall(struct pt_regs *regs, int per_trap) { unsigned long nr; + add_random_kstack_offset(); + enter_from_user_mode(regs); + regs->psw = get_lowcore()->svc_old_psw; + regs->int_code = get_lowcore()->svc_int_code; + update_timer_sys(); + if (cpu_has_bear()) + current->thread.last_break = regs->last_break; + local_irq_enable(); + regs->orig_gpr2 = regs->gprs[2]; + if (unlikely(per_trap)) + set_thread_flag(TIF_PER_TRAP); + regs->flags = 0; + set_pt_regs_flag(regs, PIF_SYSCALL); nr = regs->int_code & 0xffff; - if (!nr) { + if (likely(!nr)) { nr = regs->gprs[1] & 0xffff; regs->int_code &= ~0xffffUL; regs->int_code |= nr; } - regs->gprs[2] = nr; - if (nr == __NR_restart_syscall && !(current->restart_block.arch_data & 1)) { regs->psw.addr = current->restart_block.arch_data; current->restart_block.arch_data = 1; } nr = syscall_enter_from_user_mode_work(regs, nr); - /* * In the s390 ptrace ABI, both the syscall number and the return value * use gpr2. However, userspace puts the syscall number either in the @@ -108,37 +118,14 @@ static void do_syscall(struct pt_regs *regs) * work, the ptrace code sets PIF_SYSCALL_RET_SET, which is checked here * and if set, the syscall will be skipped. */ - if (unlikely(test_and_clear_pt_regs_flag(regs, PIF_SYSCALL_RET_SET))) goto out; regs->gprs[2] = -ENOSYS; - if (likely(nr >= NR_syscalls)) + if (unlikely(nr >= NR_syscalls)) goto out; do { regs->gprs[2] = current->thread.sys_call_table[nr](regs); } while (test_and_clear_pt_regs_flag(regs, PIF_EXECVE_PGSTE_RESTART)); out: - syscall_exit_to_user_mode_work(regs); -} - -void noinstr __do_syscall(struct pt_regs *regs, int per_trap) -{ - add_random_kstack_offset(); - enter_from_user_mode(regs); - regs->psw = get_lowcore()->svc_old_psw; - regs->int_code = get_lowcore()->svc_int_code; - update_timer_sys(); - if (cpu_has_bear()) - current->thread.last_break = regs->last_break; - - local_irq_enable(); - regs->orig_gpr2 = regs->gprs[2]; - - if (per_trap) - set_thread_flag(TIF_PER_TRAP); - - regs->flags = 0; - set_pt_regs_flag(regs, PIF_SYSCALL); - do_syscall(regs); - exit_to_user_mode(); + syscall_exit_to_user_mode(regs); } -- cgit v1.2.3-59-g8ed1b From df4623fb53c2014e39a07801dd2ac49cb8701f44 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 10 Mar 2025 10:33:43 +0100 Subject: s390/lowcore: Use lghi instead llilh to clear register lghi is the fastest way to clear a register. Use that intead of llilh. Suggested-by: Juergen Christ Reviewed-by: Juergen Christ Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/lowcore.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index ada93ab7802a..1a31f1f93ed3 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -224,7 +224,7 @@ static __always_inline struct lowcore *get_lowcore(void) if (__is_defined(__DECOMPRESSOR)) return NULL; asm_inline( - ALTERNATIVE(" llilh %[lc],0", + ALTERNATIVE(" lghi %[lc],0", " llilh %[lc],%[alt]", ALT_FEATURE(MFEATURE_LOWCORE)) : [lc] "=d" (lc) @@ -242,7 +242,7 @@ static inline void set_prefix(__u32 address) #else /* __ASSEMBLY__ */ .macro GET_LC reg - ALTERNATIVE "llilh \reg,0", \ + ALTERNATIVE "lghi \reg,0", \ __stringify(llilh \reg, LOWCORE_ALT_ADDRESS >> 16), \ ALT_FEATURE(MFEATURE_LOWCORE) .endm -- cgit v1.2.3-59-g8ed1b From 9291ea091b29bb3e37c4b3416c7c1e49e472c7d5 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 10 Mar 2025 12:42:59 +0100 Subject: s390/tlb: Use mm_has_pgste() instead of mm_alloc_pgste() An mm has pgstes only after s390_enable_sie() has been called, while mm_alloc_pgste() may be always true (e.g. via sysctl setting). Limit the calls to gmap_unlink() in pte_free_tlb() to those cases where there might be something to unlink. Reviewed-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/tlb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h index 72655fd2d867..f20601995bb0 100644 --- a/arch/s390/include/asm/tlb.h +++ b/arch/s390/include/asm/tlb.h @@ -84,7 +84,7 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, tlb->mm->context.flush_mm = 1; tlb->freed_tables = 1; tlb->cleared_pmds = 1; - if (mm_alloc_pgste(tlb->mm)) + if (mm_has_pgste(tlb->mm)) gmap_unlink(tlb->mm, (unsigned long *)pte, address); tlb_remove_ptdesc(tlb, virt_to_ptdesc(pte)); } -- cgit v1.2.3-59-g8ed1b From 174cb82a5761f15f2c469672452b720d9f51cbd7 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 10 Mar 2025 12:43:00 +0100 Subject: s390: Remove 2k vs 4k page table leftovers Since commit d08d4e7cd6bf ("s390/mm: use full 4KB page for 2KB PTE") always 4k page tables are allocated, however there is still some (now) obsolete code left which deals with switching from 2k to 4k page tables for qemu/kvm processes. Reviewed-by: Alexander Gordeev Remove the not needed code. Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/Kconfig | 1 - arch/s390/include/asm/elf.h | 32 -------------------------------- arch/s390/include/asm/mmu.h | 3 --- arch/s390/include/asm/mmu_context.h | 3 --- arch/s390/include/asm/pgtable.h | 9 --------- arch/s390/include/asm/ptrace.h | 2 -- arch/s390/include/asm/thread_info.h | 2 -- arch/s390/kernel/syscall.c | 5 +---- arch/s390/mm/gmap.c | 3 --- 9 files changed, 1 insertion(+), 59 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index acaa1d1c12b2..2cea7963e955 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -73,7 +73,6 @@ config S390 imply IMA_SECURE_AND_OR_TRUSTED_BOOT select ALTERNATE_USER_ADDRESS_SPACE select ARCH_32BIT_USTAT_F_TINODE - select ARCH_BINFMT_ELF_STATE select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE select ARCH_ENABLE_MEMORY_HOTPLUG if SPARSEMEM select ARCH_ENABLE_MEMORY_HOTREMOVE diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index 8f2c23cc52b6..a03df312081e 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h @@ -158,9 +158,6 @@ enum { #define ELF_DATA ELFDATA2MSB #define ELF_ARCH EM_S390 -/* s390 specific phdr types */ -#define PT_S390_PGSTE 0x70000000 - /* * ELF register definitions.. */ @@ -191,35 +188,6 @@ typedef s390_compat_regs compat_elf_gregset_t; && (x)->e_ident[EI_CLASS] == ELF_CLASS) #define compat_start_thread start_thread31 -struct arch_elf_state { - int rc; -}; - -#define INIT_ARCH_ELF_STATE { .rc = 0 } - -#define arch_check_elf(ehdr, interp, interp_ehdr, state) (0) -#ifdef CONFIG_PGSTE -#define arch_elf_pt_proc(ehdr, phdr, elf, interp, state) \ -({ \ - struct arch_elf_state *_state = state; \ - if ((phdr)->p_type == PT_S390_PGSTE && \ - !page_table_allocate_pgste && \ - !test_thread_flag(TIF_PGSTE) && \ - !current->mm->context.alloc_pgste) { \ - set_thread_flag(TIF_PGSTE); \ - set_pt_regs_flag(task_pt_regs(current), \ - PIF_EXECVE_PGSTE_RESTART); \ - _state->rc = -EAGAIN; \ - } \ - _state->rc; \ -}) -#else -#define arch_elf_pt_proc(ehdr, phdr, elf, interp, state) \ -({ \ - (state)->rc; \ -}) -#endif - /* For SVR4/S390 the function pointer to be registered with `atexit` is passed in R14. */ #define ELF_PLAT_INIT(_r, load_addr) \ diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h index 4c2dc7abc285..f07e49b419ab 100644 --- a/arch/s390/include/asm/mmu.h +++ b/arch/s390/include/asm/mmu.h @@ -22,10 +22,7 @@ typedef struct { * The following bitfields need a down_write on the mm * semaphore when they are written to. As they are only * written once, they can be read without a lock. - * - * The mmu context allocates 4K page tables. */ - unsigned int alloc_pgste:1; /* The mmu context uses extended page tables. */ unsigned int has_pgste:1; /* The mmu context uses storage keys. */ diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index d56eb0a1f37b..88f84beebb9e 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h @@ -29,9 +29,6 @@ static inline int init_new_context(struct task_struct *tsk, mm->context.gmap_asce = 0; mm->context.flush_mm = 0; #ifdef CONFIG_PGSTE - mm->context.alloc_pgste = page_table_allocate_pgste || - test_thread_flag(TIF_PGSTE) || - (current->mm && current->mm->context.alloc_pgste); mm->context.has_pgste = 0; mm->context.uses_skeys = 0; mm->context.uses_cmm = 0; diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 01f14cf52255..f8a6b54986ec 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -584,15 +584,6 @@ static inline int mm_is_protected(struct mm_struct *mm) return 0; } -static inline int mm_alloc_pgste(struct mm_struct *mm) -{ -#ifdef CONFIG_PGSTE - if (unlikely(mm->context.alloc_pgste)) - return 1; -#endif - return 0; -} - static inline pgste_t clear_pgste_bit(pgste_t pgste, unsigned long mask) { return __pgste(pgste_val(pgste) & ~mask); diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index 788bc4467445..c66f3fc6daaf 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -12,13 +12,11 @@ #include #define PIF_SYSCALL 0 /* inside a system call */ -#define PIF_EXECVE_PGSTE_RESTART 1 /* restart execve for PGSTE binaries */ #define PIF_SYSCALL_RET_SET 2 /* return value was set via ptrace */ #define PIF_GUEST_FAULT 3 /* indicates program check in sie64a */ #define PIF_FTRACE_FULL_REGS 4 /* all register contents valid (ftrace) */ #define _PIF_SYSCALL BIT(PIF_SYSCALL) -#define _PIF_EXECVE_PGSTE_RESTART BIT(PIF_EXECVE_PGSTE_RESTART) #define _PIF_SYSCALL_RET_SET BIT(PIF_SYSCALL_RET_SET) #define _PIF_GUEST_FAULT BIT(PIF_GUEST_FAULT) #define _PIF_FTRACE_FULL_REGS BIT(PIF_FTRACE_FULL_REGS) diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index c33f7144d1b9..1ad5e82c2f65 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h @@ -67,7 +67,6 @@ void arch_setup_new_exec(void); #define TIF_NEED_RESCHED_LAZY 3 /* lazy rescheduling needed */ #define TIF_UPROBE 4 /* breakpointed or single-stepping */ #define TIF_PATCH_PENDING 5 /* pending live patching update */ -#define TIF_PGSTE 6 /* New mm's will use 4K page tables */ #define TIF_NOTIFY_SIGNAL 7 /* signal notifications exist */ #define TIF_GUARDED_STORAGE 8 /* load guarded storage control block */ #define TIF_ISOLATE_BP_GUEST 9 /* Run KVM guests with isolated BP */ @@ -89,7 +88,6 @@ void arch_setup_new_exec(void); #define _TIF_NEED_RESCHED_LAZY BIT(TIF_NEED_RESCHED_LAZY) #define _TIF_UPROBE BIT(TIF_UPROBE) #define _TIF_PATCH_PENDING BIT(TIF_PATCH_PENDING) -#define _TIF_PGSTE BIT(TIF_PGSTE) #define _TIF_NOTIFY_SIGNAL BIT(TIF_NOTIFY_SIGNAL) #define _TIF_GUARDED_STORAGE BIT(TIF_GUARDED_STORAGE) #define _TIF_ISOLATE_BP_GUEST BIT(TIF_ISOLATE_BP_GUEST) diff --git a/arch/s390/kernel/syscall.c b/arch/s390/kernel/syscall.c index 535f3922ffa9..4fee74553ca2 100644 --- a/arch/s390/kernel/syscall.c +++ b/arch/s390/kernel/syscall.c @@ -121,11 +121,8 @@ void noinstr __do_syscall(struct pt_regs *regs, int per_trap) if (unlikely(test_and_clear_pt_regs_flag(regs, PIF_SYSCALL_RET_SET))) goto out; regs->gprs[2] = -ENOSYS; - if (unlikely(nr >= NR_syscalls)) - goto out; - do { + if (likely(nr < NR_syscalls)) regs->gprs[2] = current->thread.sys_call_table[nr](regs); - } while (test_and_clear_pt_regs_flag(regs, PIF_EXECVE_PGSTE_RESTART)); out: syscall_exit_to_user_mode(regs); } diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index 0d7cce4f3e83..f412a9af13d0 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c @@ -2260,9 +2260,6 @@ int s390_enable_sie(void) /* Do we have pgstes? if yes, we are done */ if (mm_has_pgste(mm)) return 0; - /* Fail if the page tables are 2K */ - if (!mm_alloc_pgste(mm)) - return -EINVAL; mmap_write_lock(mm); mm->context.has_pgste = 1; /* split thp mappings and disable thp for future mappings */ -- cgit v1.2.3-59-g8ed1b From 46ba4d0bfcc1cafa2336cab03c02124ba0da0552 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 10 Mar 2025 12:43:01 +0100 Subject: s390/sysctl: Remove "vm/allocate_pgste" sysctl Remove the not needed "vm/allocate_pgste" sysctl. It has no effect anymore. However this is a user space visible change. It shouldn't cause any problems, however if it does this needs to be partially reverted. Note that some distributions set vm/allocate_pgste=1 in one of the various sysctl configuration files. Besides a warning about the (now) non-existent procfs file this doesn't cause any problems. Reviewed-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/pgalloc.h | 1 - arch/s390/mm/pgalloc.c | 25 ------------------------- 2 files changed, 26 deletions(-) diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h index b19b6ed2ab53..005497ffebda 100644 --- a/arch/s390/include/asm/pgalloc.h +++ b/arch/s390/include/asm/pgalloc.h @@ -26,7 +26,6 @@ unsigned long *page_table_alloc(struct mm_struct *); struct ptdesc *page_table_alloc_pgste(struct mm_struct *mm); void page_table_free(struct mm_struct *, unsigned long *); void page_table_free_pgste(struct ptdesc *ptdesc); -extern int page_table_allocate_pgste; static inline void crst_table_init(unsigned long *crst, unsigned long entry) { diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c index 30387a6e98ff..e3a6f8ae156c 100644 --- a/arch/s390/mm/pgalloc.c +++ b/arch/s390/mm/pgalloc.c @@ -16,31 +16,6 @@ #include #include -#ifdef CONFIG_PGSTE - -int page_table_allocate_pgste = 0; -EXPORT_SYMBOL(page_table_allocate_pgste); - -static const struct ctl_table page_table_sysctl[] = { - { - .procname = "allocate_pgste", - .data = &page_table_allocate_pgste, - .maxlen = sizeof(int), - .mode = S_IRUGO | S_IWUSR, - .proc_handler = proc_dointvec_minmax, - .extra1 = SYSCTL_ZERO, - .extra2 = SYSCTL_ONE, - }, -}; - -static int __init page_table_register_sysctl(void) -{ - return register_sysctl("vm", page_table_sysctl) ? 0 : -ENOMEM; -} -__initcall(page_table_register_sysctl); - -#endif /* CONFIG_PGSTE */ - unsigned long *crst_table_alloc(struct mm_struct *mm) { struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, CRST_ALLOC_ORDER); -- cgit v1.2.3-59-g8ed1b From 0d5b0a4c816cfd9fa5082b5fd71aaf96e7329dd2 Mon Sep 17 00:00:00 2001 From: WangYuli Date: Tue, 11 Mar 2025 11:08:24 +0800 Subject: s390/boot: Ignore vmlinux.map When building with CONFIG_VMLINUX_MAP=y, a decompressor vmlinux.map file is generated in the boot directory. Add this file to .gitignore to ensure Git does not track it. Signed-off-by: WangYuli Link: https://lore.kernel.org/r/F884C733016D6715+20250311030824.675683-1-wangyuli@uniontech.com Acked-by: Vasily Gorbik Signed-off-by: Vasily Gorbik --- arch/s390/boot/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/s390/boot/.gitignore b/arch/s390/boot/.gitignore index f5ef099e2fd3..af2a6a7bc028 100644 --- a/arch/s390/boot/.gitignore +++ b/arch/s390/boot/.gitignore @@ -5,4 +5,5 @@ relocs.S section_cmp.* vmlinux vmlinux.lds +vmlinux.map vmlinux.syms -- cgit v1.2.3-59-g8ed1b From d93a855c31b72637e19659bca613766eaa89d496 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Thu, 6 Mar 2025 19:12:54 +0100 Subject: s390/ptrace: Avoid KASAN false positives in regs_get_kernel_stack_nth() With recent ftrace changes, argument tracing has been added to the function tracer. As a result, ftrace opportunistically reads the first FTRACE_REGS_MAX_ARGS (i.e., 6) registers. On s390, only five arguments are passed in registers, and the 6-th is read from the stack. If a function has fewer than 6 arguments, the following KASAN report may be observed: BUG: KASAN: stack-out-of-bounds in regs_get_kernel_stack_nth+0xa8/0xb0 Read of size 8 at addr 00007f7fe066fdb8 by task swapper/31/0 CPU: 31 UID: 0 PID: 0 Comm: swapper/31 Not tainted 6.14.0-rc4-00006-g76fe0337c219 #16 Hardware name: IBM 3931 A01 704 (KVM/Linux) Call Trace: [<00007fffe0147224>] dump_stack_lvl+0x104/0x168 [<00007fffe011381c>] print_address_description.constprop.0+0x34/0x338 [<00007fffe0113b64>] print_report+0x44/0x138 [<00007fffe0ad9422>] kasan_report+0xc2/0x180 [<00007fffe0159ff8>] regs_get_kernel_stack_nth+0xa8/0xb0 [<00007fffe05ebeda>] trace_function+0x23a/0x4d0 [<00007fffe0615d32>] irqsoff_tracer_call+0xd2/0x110 [<00007fffe2b4e34c>] ftrace_common+0x1c/0x40 [<00007fffe0150826>] arch_cpu_idle_enter+0x6/0x10 [<00007fffe035a1c8>] do_idle+0x168/0x2e0 [<00007fffe035a9d0>] cpu_startup_entry+0x90/0xb0 [<00007fffe017d25a>] smp_start_secondary+0x3da/0x4e0 [<00007fffe2b4e20a>] restart_int_handler+0x72/0x88 no locks held by swapper/31/0. The buggy address belongs to stack of task swapper/31/0 and is located at offset 0 in frame: do_idle+0x0/0x2e0 This frame has 1 object: [32, 40) '__mask' The buggy address belongs to the virtual mapping at [00007f7fe0660000, 00007f7fe0671000) created by: dup_task_struct+0x66/0x4e0 The buggy address belongs to the physical page: page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x80f23 flags: 0x3ffff00000000000(node=0|zone=1|lastcpupid=0x1ffff) raw: 3ffff00000000000 0000000000000000 0000000000000122 0000000000000000 raw: 0000000000000000 0000000000000000 ffffffff00000001 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: 00007f7fe066fc80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00007f7fe066fd00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >00007f7fe066fd80: 00 00 00 00 00 00 00 f1 f1 f1 f1 00 f3 f3 f3 00 ^ 00007f7fe066fe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00007f7fe066fe80: 00 f1 f1 f1 f1 00 f2 f2 f2 00 00 f3 f3 00 00 00 The function regs_get_kernel_stack_nth() verifies that the requested argument is located on the stack, making it safe to read even if it is not actually present. Make use of READ_ONCE_NOCHECK() helper to silence KASAN reports in this case. Reviewed-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/ptrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 6f2ae0be2298..34b8d9e745df 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "entry.h" @@ -1573,5 +1574,5 @@ unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) addr = kernel_stack_pointer(regs) + n * sizeof(long); if (!regs_within_kernel_stack(regs, addr)) return 0; - return *(unsigned long *)addr; + return READ_ONCE_NOCHECK(addr); } -- cgit v1.2.3-59-g8ed1b From caa3cd5ccd016cb28294e2b7e21fe08831e9a877 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Thu, 13 Mar 2025 10:55:43 +0100 Subject: s390/kfence: Split kfence pool into 4k mappings in arch_kfence_init_pool() Since commit d08d4e7cd6bf ("s390/mm: use full 4KB page for 2KB PTE"), there is no longer any reason to avoid splitting the kfence pool into 4k mappings in arch_kfence_init_pool(). Remove the architecture-specific kfence_split_mapping(). Reviewed-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/kfence.h | 17 +++-------------- arch/s390/mm/init.c | 1 - 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/arch/s390/include/asm/kfence.h b/arch/s390/include/asm/kfence.h index e47fd8cbe701..e95e35eb8a3f 100644 --- a/arch/s390/include/asm/kfence.h +++ b/arch/s390/include/asm/kfence.h @@ -11,28 +11,17 @@ void __kernel_map_pages(struct page *page, int numpages, int enable); static __always_inline bool arch_kfence_init_pool(void) -{ - return true; -} - -#define arch_kfence_test_address(addr) ((addr) & PAGE_MASK) - -/* - * Do not split kfence pool to 4k mapping with arch_kfence_init_pool(), - * but earlier where page table allocations still happen with memblock. - * Reason is that arch_kfence_init_pool() gets called when the system - * is still in a limbo state - disabling and enabling bottom halves is - * not yet allowed, but that is what our page_table_alloc() would do. - */ -static __always_inline void kfence_split_mapping(void) { #ifdef CONFIG_KFENCE unsigned long pool_pages = KFENCE_POOL_SIZE >> PAGE_SHIFT; set_memory_4k((unsigned long)__kfence_pool, pool_pages); #endif + return true; } +#define arch_kfence_test_address(addr) ((addr) & PAGE_MASK) + static inline bool kfence_protect_page(unsigned long addr, bool protect) { __kernel_map_pages(virt_to_page((void *)addr), 1, !protect); diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 615ee245cb93..f4ac69506608 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -175,7 +175,6 @@ void __init mem_init(void) high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); pv_init(); - kfence_split_mapping(); /* this will put all low memory onto the freelists */ memblock_free_all(); -- cgit v1.2.3-59-g8ed1b From 0dafe9968ac7c78c67ee6bb2d970d413fb493b95 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 17 Mar 2025 16:22:35 +0100 Subject: s390: Use inline qualifier for all EX_TABLE and ALTERNATIVE inline assemblies Use asm_inline for all inline assemblies which make use of the EX_TABLE or ALTERNATIVE macros. These macros expand to many lines and the compiler assumes the number of lines within an inline assembly is the same as the number of instructions within an inline assembly. This has an effect on inlining and loop unrolling decisions. In order to avoid incorrect assumptions use asm_inline, which tells the compiler that an inline assembly has the smallest possible size. In order to avoid confusion when asm_inline should be used or not, since a couple of inline assemblies are quite large: the rule is to always use asm_inline whenever the EX_TABLE or ALTERNATIVE macro is used. In specific cases there may be reasons to not follow this guideline, but that should be documented with the corresponding code. Using the inline qualifier everywhere has only a small effect on the kernel image size: add/remove: 0/10 grow/shrink: 19/8 up/down: 1492/-1858 (-366) The only location where this seems to matter is load_unaligned_zeropad() from word-at-a-time.h where the compiler inlines more functions within the dcache code, which is indeed code where performance matters. Suggested-by: Juergen Christ Reviewed-by: Juergen Christ Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/ipl_parm.c | 2 +- arch/s390/boot/physmem_info.c | 6 +++--- arch/s390/boot/startup.c | 4 ++-- arch/s390/include/asm/cpu_mf.h | 6 +++--- arch/s390/include/asm/diag.h | 2 +- arch/s390/include/asm/processor.h | 6 +++++- arch/s390/include/asm/uaccess.h | 14 +++++++------- arch/s390/include/asm/word-at-a-time.h | 2 +- arch/s390/kernel/cert_store.c | 2 +- arch/s390/kernel/diag/diag.c | 4 ++-- arch/s390/kernel/ipl.c | 2 +- arch/s390/kernel/traps.c | 2 +- arch/s390/mm/pfault.c | 4 ++-- arch/s390/pci/pci_clp.c | 4 ++-- arch/s390/pci/pci_insn.c | 12 ++++++------ arch/s390/pci/pci_mmio.c | 6 +++--- drivers/s390/block/dasd_diag.c | 2 +- drivers/s390/char/diag_ftp.c | 2 +- drivers/s390/char/sclp.h | 2 +- drivers/s390/cio/ioasm.c | 8 ++++---- 20 files changed, 48 insertions(+), 44 deletions(-) diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c index b49c906b57dc..d04e9b89d14a 100644 --- a/arch/s390/boot/ipl_parm.c +++ b/arch/s390/boot/ipl_parm.c @@ -37,7 +37,7 @@ static inline int __diag308(unsigned long subcode, void *addr) { union register_pair r1 = { .even = (unsigned long)addr, .odd = 0 }; - asm volatile( + asm_inline volatile( " diag %[r1],%[subcode],0x308\n" "0:\n" EX_TABLE(0b, 0b) diff --git a/arch/s390/boot/physmem_info.c b/arch/s390/boot/physmem_info.c index eb1badb93c40..45e3d057cfaa 100644 --- a/arch/s390/boot/physmem_info.c +++ b/arch/s390/boot/physmem_info.c @@ -67,7 +67,7 @@ static int __diag260(unsigned long rx1, unsigned long rx2) rx.odd = rx2; ry = 0x10; /* storage configuration */ exception = 1; - asm volatile( + asm_inline volatile( " diag %[rx],%[ry],0x260\n" "0: lhi %[exc],0\n" "1:\n" @@ -105,7 +105,7 @@ static int diag500_storage_limit(unsigned long *max_physmem_end) { unsigned long storage_limit; - asm volatile( + asm_inline volatile( " lghi %%r1,%[subcode]\n" " lghi %%r2,0\n" " diag %%r2,%%r4,0x500\n" @@ -126,7 +126,7 @@ static int tprot(unsigned long addr) int cc, exception; exception = 1; - asm volatile( + asm_inline volatile( " tprot 0(%[addr]),0\n" "0: lhi %[exc],0\n" "1:\n" diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 099b2327c781..06316fb8e0fa 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -77,7 +77,7 @@ static void detect_diag9c(void) int rc = 1; cpu = stap(); - asm volatile( + asm_inline volatile( " diag %[cpu],%%r0,0x9c\n" "0: lhi %[rc],0\n" "1:\n" @@ -138,7 +138,7 @@ static int cmma_test_essa(void) int rc = 1; /* Test ESSA_GET_STATE */ - asm volatile( + asm_inline volatile( " .insn rrf,0xb9ab0000,%[tmp],%[tmp],%[cmd],0\n" "0: lhi %[rc],0\n" "1:\n" diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h index e1a279e0d6a6..1798fbd59068 100644 --- a/arch/s390/include/asm/cpu_mf.h +++ b/arch/s390/include/asm/cpu_mf.h @@ -171,7 +171,7 @@ static inline int qctri(struct cpumf_ctr_info *info) { int rc = -EINVAL; - asm volatile ( + asm_inline volatile ( "0: qctri %1\n" "1: lhi %0,0\n" "2:\n" @@ -185,7 +185,7 @@ static inline int lcctl(u64 ctl) { int cc; - asm volatile ( + asm_inline volatile ( " lcctl %[ctl]\n" CC_IPM(cc) : CC_OUT(cc, cc) @@ -200,7 +200,7 @@ static inline int __ecctr(u64 ctr, u64 *content) u64 _content; int cc; - asm volatile ( + asm_inline volatile ( " ecctr %[_content],%[ctr]\n" CC_IPM(cc) : CC_OUT(cc, cc), [_content] "=d" (_content) diff --git a/arch/s390/include/asm/diag.h b/arch/s390/include/asm/diag.h index 5790630e31f0..8db8db3b1018 100644 --- a/arch/s390/include/asm/diag.h +++ b/arch/s390/include/asm/diag.h @@ -66,7 +66,7 @@ static inline void diag10_range(unsigned long start_pfn, unsigned long num_pfn) end_addr = pfn_to_phys(start_pfn + num_pfn - 1); diag_stat_inc(DIAG_STAT_X010); - asm volatile( + asm_inline volatile( "0: diag %0,%1,0x10\n" "1: nopr %%r7\n" EX_TABLE(0b, 1b) diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 4f8d5592c298..d09a92db95f7 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -416,7 +416,11 @@ static __always_inline bool regs_irqs_disabled(struct pt_regs *regs) static __always_inline void bpon(void) { - asm volatile(ALTERNATIVE("nop", ".insn rrf,0xb2e80000,0,0,13,0", ALT_SPEC(82))); + asm_inline volatile( + ALTERNATIVE(" nop\n", + " .insn rrf,0xb2e80000,0,0,13,0\n", + ALT_SPEC(82)) + ); } #endif /* __ASSEMBLY__ */ diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index f30ee6ddfece..8629d70ec38b 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -147,7 +147,7 @@ __put_user_##type##_noinstr(unsigned type __user *to, \ { \ int rc; \ \ - asm volatile( \ + asm_inline volatile( \ " llilh %%r0,%[spec]\n" \ "0: mvcos %[to],%[from],%[size]\n" \ "1: lhi %[rc],0\n" \ @@ -263,7 +263,7 @@ __get_user_##type##_noinstr(unsigned type *to, \ { \ int rc; \ \ - asm volatile( \ + asm_inline volatile( \ " lhi %%r0,%[spec]\n" \ "0: mvcos %[to],%[from],%[size]\n" \ "1: lhi %[rc],0\n" \ @@ -490,7 +490,7 @@ static __always_inline int __cmpxchg_user_key(unsigned long address, void *uval, _old = ((unsigned int)old & 0xff) << shift; _new = ((unsigned int)new & 0xff) << shift; mask = ~(0xff << shift); - asm volatile( + asm_inline volatile( " spka 0(%[key])\n" " sacf 256\n" " llill %[count],%[max_loops]\n" @@ -538,7 +538,7 @@ static __always_inline int __cmpxchg_user_key(unsigned long address, void *uval, _old = ((unsigned int)old & 0xffff) << shift; _new = ((unsigned int)new & 0xffff) << shift; mask = ~(0xffff << shift); - asm volatile( + asm_inline volatile( " spka 0(%[key])\n" " sacf 256\n" " llill %[count],%[max_loops]\n" @@ -580,7 +580,7 @@ static __always_inline int __cmpxchg_user_key(unsigned long address, void *uval, case 4: { unsigned int prev = old; - asm volatile( + asm_inline volatile( " spka 0(%[key])\n" " sacf 256\n" "0: cs %[prev],%[new],%[address]\n" @@ -601,7 +601,7 @@ static __always_inline int __cmpxchg_user_key(unsigned long address, void *uval, case 8: { unsigned long prev = old; - asm volatile( + asm_inline volatile( " spka 0(%[key])\n" " sacf 256\n" "0: csg %[prev],%[new],%[address]\n" @@ -622,7 +622,7 @@ static __always_inline int __cmpxchg_user_key(unsigned long address, void *uval, case 16: { __uint128_t prev = old; - asm volatile( + asm_inline volatile( " spka 0(%[key])\n" " sacf 256\n" "0: cdsg %[prev],%[new],%[address]\n" diff --git a/arch/s390/include/asm/word-at-a-time.h b/arch/s390/include/asm/word-at-a-time.h index 203acd6e431b..eaa19dee7699 100644 --- a/arch/s390/include/asm/word-at-a-time.h +++ b/arch/s390/include/asm/word-at-a-time.h @@ -52,7 +52,7 @@ static inline unsigned long load_unaligned_zeropad(const void *addr) { unsigned long data; - asm volatile( + asm_inline volatile( "0: lg %[data],0(%[addr])\n" "1: nopr %%r7\n" EX_TABLE_ZEROPAD(0b, 1b, %[data], %[addr]) diff --git a/arch/s390/kernel/cert_store.c b/arch/s390/kernel/cert_store.c index bf983513dd33..03f3a1e52430 100644 --- a/arch/s390/kernel/cert_store.c +++ b/arch/s390/kernel/cert_store.c @@ -235,7 +235,7 @@ static int __diag320(unsigned long subcode, void *addr) { union register_pair rp = { .even = (unsigned long)addr, }; - asm volatile( + asm_inline volatile( " diag %[rp],%[subcode],0x320\n" "0: nopr %%r7\n" EX_TABLE(0b, 0b) diff --git a/arch/s390/kernel/diag/diag.c b/arch/s390/kernel/diag/diag.c index e15b8dee3228..56b862ba9be8 100644 --- a/arch/s390/kernel/diag/diag.c +++ b/arch/s390/kernel/diag/diag.c @@ -195,7 +195,7 @@ static inline int __diag204(unsigned long *subcode, unsigned long size, void *ad { union register_pair rp = { .even = *subcode, .odd = size }; - asm volatile( + asm_inline volatile( " diag %[addr],%[rp],0x204\n" "0: nopr %%r7\n" EX_TABLE(0b,0b) @@ -286,7 +286,7 @@ int diag224(void *ptr) int rc = -EOPNOTSUPP; diag_stat_inc(DIAG_STAT_X224); - asm volatile("\n" + asm_inline volatile("\n" " diag %[type],%[addr],0x224\n" "0: lhi %[rc],0\n" "1:\n" diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 8990e2dffcdf..3b9d9ccfad63 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -186,7 +186,7 @@ static inline int __diag308(unsigned long subcode, unsigned long addr) r1.even = addr; r1.odd = 0; - asm volatile( + asm_inline volatile( " diag %[r1],%[subcode],0x308\n" "0: nopr %%r7\n" EX_TABLE(0b,0b) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 4daa3c76e999..9705929d256f 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -257,7 +257,7 @@ static void __init test_monitor_call(void) if (!IS_ENABLED(CONFIG_BUG)) return; - asm volatile( + asm_inline volatile( " mc 0,0\n" "0: xgr %0,%0\n" "1:\n" diff --git a/arch/s390/mm/pfault.c b/arch/s390/mm/pfault.c index 1aac13bb8f53..b01e73f5b9b8 100644 --- a/arch/s390/mm/pfault.c +++ b/arch/s390/mm/pfault.c @@ -56,7 +56,7 @@ int __pfault_init(void) if (pfault_disable) return rc; diag_stat_inc(DIAG_STAT_X258); - asm volatile( + asm_inline volatile( " diag %[refbk],%[rc],0x258\n" "0: nopr %%r7\n" EX_TABLE(0b, 0b) @@ -78,7 +78,7 @@ void __pfault_fini(void) if (pfault_disable) return; diag_stat_inc(DIAG_STAT_X258); - asm volatile( + asm_inline volatile( " diag %[refbk],0,0x258\n" "0: nopr %%r7\n" EX_TABLE(0b, 0b) diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c index 14bf7e8d06b7..bf083176076d 100644 --- a/arch/s390/pci/pci_clp.c +++ b/arch/s390/pci/pci_clp.c @@ -56,7 +56,7 @@ static inline int clp_get_ilp(unsigned long *ilp) int cc, exception; exception = 1; - asm volatile ( + asm_inline volatile ( " .insn rrf,0xb9a00000,%[mask],%[cmd],8,0\n" "0: lhi %[exc],0\n" "1:\n" @@ -79,7 +79,7 @@ static __always_inline int clp_req(void *data, unsigned int lps) u64 ignored; exception = 1; - asm volatile ( + asm_inline volatile ( " .insn rrf,0xb9a00000,%[ign],%[req],0,%[lps]\n" "0: lhi %[exc],0\n" "1:\n" diff --git a/arch/s390/pci/pci_insn.c b/arch/s390/pci/pci_insn.c index f5a75ea7629a..eb978c8012be 100644 --- a/arch/s390/pci/pci_insn.c +++ b/arch/s390/pci/pci_insn.c @@ -160,7 +160,7 @@ static inline int ____pcilg(u64 *data, u64 req, u64 offset, u8 *status) u64 __data; exception = 1; - asm volatile ( + asm_inline volatile ( " .insn rre,0xb9d20000,%[data],%[req_off]\n" "0: lhi %[exc],0\n" "1:\n" @@ -229,7 +229,7 @@ static inline int __pcilg_mio(u64 *data, u64 ioaddr, u64 len, u8 *status) u64 __data; exception = 1; - asm volatile ( + asm_inline volatile ( " .insn rre,0xb9d60000,%[data],%[ioaddr_len]\n" "0: lhi %[exc],0\n" "1:\n" @@ -267,7 +267,7 @@ static inline int __pcistg(u64 data, u64 req, u64 offset, u8 *status) int cc, exception; exception = 1; - asm volatile ( + asm_inline volatile ( " .insn rre,0xb9d00000,%[data],%[req_off]\n" "0: lhi %[exc],0\n" "1:\n" @@ -321,7 +321,7 @@ static inline int __pcistg_mio(u64 data, u64 ioaddr, u64 len, u8 *status) int cc, exception; exception = 1; - asm volatile ( + asm_inline volatile ( " .insn rre,0xb9d40000,%[data],%[ioaddr_len]\n" "0: lhi %[exc],0\n" "1:\n" @@ -356,7 +356,7 @@ static inline int __pcistb(const u64 *data, u64 req, u64 offset, u8 *status) int cc, exception; exception = 1; - asm volatile ( + asm_inline volatile ( " .insn rsy,0xeb00000000d0,%[req],%[offset],%[data]\n" "0: lhi %[exc],0\n" "1:\n" @@ -410,7 +410,7 @@ static inline int __pcistb_mio(const u64 *data, u64 ioaddr, u64 len, u8 *status) int cc, exception; exception = 1; - asm volatile ( + asm_inline volatile ( " .insn rsy,0xeb00000000d4,%[len],%[ioaddr],%[data]\n" "0: lhi %[exc],0\n" "1:\n" diff --git a/arch/s390/pci/pci_mmio.c b/arch/s390/pci/pci_mmio.c index 46f99dc164ad..dc162c9951dd 100644 --- a/arch/s390/pci/pci_mmio.c +++ b/arch/s390/pci/pci_mmio.c @@ -34,7 +34,7 @@ static inline int __pcistb_mio_inuser( int cc, exception; exception = 1; - asm volatile ( + asm_inline volatile ( " sacf 256\n" "0: .insn rsy,0xeb00000000d4,%[len],%[ioaddr],%[src]\n" "1: lhi %[exc],0\n" @@ -64,7 +64,7 @@ static inline int __pcistg_mio_inuser( * address space. pcistg then uses the user mappings. */ exception = 1; - asm volatile ( + asm_inline volatile ( " sacf 256\n" "0: llgc %[tmp],0(%[src])\n" "4: sllg %[val],%[val],8\n" @@ -211,7 +211,7 @@ static inline int __pcilg_mio_inuser( * user address @dst */ exception = 1; - asm volatile ( + asm_inline volatile ( " sacf 256\n" "0: .insn rre,0xb9d60000,%[val],%[ioaddr_len]\n" "1: lhi %[exc],0\n" diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 8b39803cf94c..56f1af8a7ddd 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -76,7 +76,7 @@ static inline int __dia250(void *iob, int cmd) } addr_type; exception = 1; - asm volatile( + asm_inline volatile( " diag %[rx],%[cmd],0x250\n" "0: lhi %[exc],0\n" "1:\n" diff --git a/drivers/s390/char/diag_ftp.c b/drivers/s390/char/diag_ftp.c index 9418a9270d03..711f6982438e 100644 --- a/drivers/s390/char/diag_ftp.c +++ b/drivers/s390/char/diag_ftp.c @@ -106,7 +106,7 @@ static int diag_ftp_2c4(struct diag_ftp_ldfpl *fpl, int rc; diag_stat_inc(DIAG_STAT_X2C4); - asm volatile( + asm_inline volatile( " diag %[addr],%[cmd],0x2c4\n" "0: j 2f\n" "1: la %[rc],%[err]\n" diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index f7ca6e2f6d18..b31a680e0871 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -318,7 +318,7 @@ static inline int sclp_service_call(sclp_cmdw_t command, void *sccb) int cc, exception; exception = 1; - asm volatile( + asm_inline volatile( "0: .insn rre,0xb2200000,%[cmd],%[sccb]\n" /* servc */ "1: lhi %[exc],0\n" "2:\n" diff --git a/drivers/s390/cio/ioasm.c b/drivers/s390/cio/ioasm.c index 5ff1e51cddf3..a540045b64a6 100644 --- a/drivers/s390/cio/ioasm.c +++ b/drivers/s390/cio/ioasm.c @@ -22,7 +22,7 @@ static inline int __stsch(struct subchannel_id schid, struct schib *addr) int ccode, exception; exception = 1; - asm volatile( + asm_inline volatile( " lgr 1,%[r1]\n" " stsch %[addr]\n" "0: lhi %[exc],0\n" @@ -52,7 +52,7 @@ static inline int __msch(struct subchannel_id schid, struct schib *addr) int ccode, exception; exception = 1; - asm volatile( + asm_inline volatile( " lgr 1,%[r1]\n" " msch %[addr]\n" "0: lhi %[exc],0\n" @@ -106,7 +106,7 @@ static inline int __ssch(struct subchannel_id schid, union orb *addr) int ccode, exception; exception = 1; - asm volatile( + asm_inline volatile( " lgr 1,%[r1]\n" " ssch %[addr]\n" "0: lhi %[exc],0\n" @@ -178,7 +178,7 @@ int chsc(void *chsc_area) int cc, exception; exception = 1; - asm volatile( + asm_inline volatile( " .insn rre,0xb25f0000,%[chsc_area],0\n" "0: lhi %[exc],0\n" "1:\n" -- cgit v1.2.3-59-g8ed1b