* Re: [PATCH v3 13/16] powerpc/watchpoint: Prepare handler to handle more than one watcnhpoint
From: Ravi Bangoria @ 2020-04-24 3:32 UTC (permalink / raw)
To: Christophe Leroy
Cc: apopple, mikey, Ravi Bangoria, peterz, oleg, npiggin,
linux-kernel, paulus, jolsa, fweisbec, naveen.n.rao, linuxppc-dev,
mingo
In-Reply-To: <67349339-03df-091a-47f0-78c1b14c5981@c-s.fr>
Hi Christophe,
>> @@ -101,14 +129,20 @@ static bool is_ptrace_bp(struct perf_event *bp)
>> */
>> void arch_unregister_hw_breakpoint(struct perf_event *bp)
>> {
>> + int i;
>> +
>
> This declaration should be in the block using it.
>
>> /*
>> * If the breakpoint is unregistered between a hw_breakpoint_handler()
>> * and the single_step_dabr_instruction(), then cleanup the breakpoint
>> * restoration variables to prevent dangling pointers.
>> * FIXME, this should not be using bp->ctx at all! Sayeth peterz.
>> */
>> - if (bp->ctx && bp->ctx->task && bp->ctx->task != ((void *)-1L))
>> - bp->ctx->task->thread.last_hit_ubp = NULL;
>> + if (bp->ctx && bp->ctx->task && bp->ctx->task != ((void *)-1L)) {
>
> Add declaration of 'int i' here.
How will that help? Keeping declaration at the start of function is also
common practice and I don't see any recommendation to move them inside
conditional block.
Thanks,
Ravi
^ permalink raw reply
* Re: [PATCH v3 12/16] powerpc/watchpoint: Use builtin ALIGN*() macros
From: Ravi Bangoria @ 2020-04-24 3:24 UTC (permalink / raw)
To: Christophe Leroy
Cc: apopple, mikey, Ravi Bangoria, peterz, oleg, npiggin,
linux-kernel, paulus, jolsa, fweisbec, naveen.n.rao, linuxppc-dev,
mingo
In-Reply-To: <a2d7abe8-44e0-9780-6603-00f16300c2ca@c-s.fr>
Hi Christophe,
>> max_len = DAWR_MAX_LEN;
>> /* DAWR region can't cross 512 bytes boundary */
>> - if ((start_addr >> 9) != (end_addr >> 9))
>> + if ((start_addr >> 9) != ((end_addr - 1) >> 9))
>
> What about:
> if (ALIGN(start_addr, SZ_512M) != ALIGN(end - 1, SZ_512M))
ok.
>
>> return -EINVAL;
>> } else if (IS_ENABLED(CONFIG_PPC_8xx)) {
>> /* 8xx can setup a range without limitation */
>> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
>> index aab82ab80dfa..06679adac447 100644
>> --- a/arch/powerpc/kernel/process.c
>> +++ b/arch/powerpc/kernel/process.c
>> @@ -800,12 +800,12 @@ static inline int set_breakpoint_8xx(struct arch_hw_breakpoint *brk)
>> unsigned long lctrl1 = LCTRL1_CTE_GT | LCTRL1_CTF_LT | LCTRL1_CRWE_RW |
>> LCTRL1_CRWF_RW;
>> unsigned long lctrl2 = LCTRL2_LW0EN | LCTRL2_LW0LADC | LCTRL2_SLW0EN;
>> - unsigned long start_addr = brk->address & ~HW_BREAKPOINT_ALIGN;
>> - unsigned long end_addr = (brk->address + brk->len - 1) | HW_BREAKPOINT_ALIGN;
>> + unsigned long start_addr = ALIGN_DOWN(brk->address, HW_BREAKPOINT_SIZE);
>> + unsigned long end_addr = ALIGN(brk->address + brk->len, HW_BREAKPOINT_SIZE);
>> if (start_addr == 0)
>> lctrl2 |= LCTRL2_LW0LA_F;
>> - else if (end_addr == ~0U)
>> + else if (end_addr - 1 == ~0U)
>
> What about:
> else if (end_addr == 0)
That's better.
Thanks,
Ravi
^ permalink raw reply
* Re: [PATCH] lib/mpi: Fix building for powerpc with clang
From: Michael Ellerman @ 2020-04-24 3:23 UTC (permalink / raw)
To: Nathan Chancellor, Herbert Xu
Cc: kbuild test robot, linux-kernel, clang-built-linux,
Paul Mackerras, linux-crypto, linuxppc-dev
In-Reply-To: <20200423163602.GA18872@ubuntu-s3-xlarge-x86>
Nathan Chancellor <natechancellor@gmail.com> writes:
> On Tue, Apr 14, 2020 at 11:57:31PM +1000, Herbert Xu wrote:
>> On Mon, Apr 13, 2020 at 12:50:42PM -0700, Nathan Chancellor wrote:
>> > 0day reports over and over on an powerpc randconfig with clang:
>> >
>> > lib/mpi/generic_mpih-mul1.c:37:13: error: invalid use of a cast in a
>> > inline asm context requiring an l-value: remove the cast or build with
>> > -fheinous-gnu-extensions
>> >
>> > Remove the superfluous casts, which have been done previously for x86
>> > and arm32 in commit dea632cadd12 ("lib/mpi: fix build with clang") and
>> > commit 7b7c1df2883d ("lib/mpi/longlong.h: fix building with 32-bit
>> > x86").
>> >
>> > Reported-by: kbuild test robot <lkp@intel.com>
>> > Link: https://github.com/ClangBuiltLinux/linux/issues/991
>> > Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
>>
>> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
>> --
>> Email: Herbert Xu <herbert@gondor.apana.org.au>
>> Home Page: http://gondor.apana.org.au/~herbert/
>> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
>
> Might be better for you to take this instead. 0day just tripped over
> this again.
Sorry I missed the ack. Will pick it up today.
cheers
^ permalink raw reply
* [Bug 199471] [Bisected][Regression] windfarm_pm* no longer gets automatically loaded when CONFIG_I2C_POWERMAC=y is set
From: bugzilla-daemon @ 2020-04-24 3:12 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <bug-199471-206035@https.bugzilla.kernel.org/>
https://bugzilla.kernel.org/show_bug.cgi?id=199471
--- Comment #23 from Michael Ellerman (michael@ellerman.id.au) ---
The memory leak is a separate issue, see bug #206695.
Can anyone verify that bcf3588d8ed fixes the original issue?
--
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply
* [PATCH v3, 5/5] powerpc: sysdev: support userspace access of fsl_85xx_sram
From: Wang Wenhu @ 2020-04-24 2:45 UTC (permalink / raw)
To: gregkh, arnd, linux-kernel, linuxppc-dev
Cc: robh, oss, kernel, paulus, Wang Wenhu
In-Reply-To: <20200424024554.30709-1-wenhu.wang@vivo.com>
New module which registers its memory allocation and free APIs to the
sram_dynamic module, which would create a device of struct sram_device
type to act as an interface for user level applications to access the
backend hardware device, fsl_85xx_cache_sram, which is drived by the
FSL_85XX_CACHE_SRAM module.
Signed-off-by: Wang Wenhu <wenhu.wang@vivo.com>
Cc: Christophe Leroy <christophe.leroy@c-s.fr>
Cc: Scott Wood <oss@buserror.net>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linuxppc-dev@lists.ozlabs.org
---
.../powerpc/include/asm/fsl_85xx_cache_sram.h | 4 ++
arch/powerpc/platforms/85xx/Kconfig | 10 +++++
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h | 6 +++
arch/powerpc/sysdev/fsl_85xx_cache_sram.c | 12 ++++++
arch/powerpc/sysdev/fsl_85xx_sram_uapi.c | 39 +++++++++++++++++++
6 files changed, 72 insertions(+)
create mode 100644 arch/powerpc/sysdev/fsl_85xx_sram_uapi.c
diff --git a/arch/powerpc/include/asm/fsl_85xx_cache_sram.h b/arch/powerpc/include/asm/fsl_85xx_cache_sram.h
index 0235a0447baa..99cb7e202c38 100644
--- a/arch/powerpc/include/asm/fsl_85xx_cache_sram.h
+++ b/arch/powerpc/include/asm/fsl_85xx_cache_sram.h
@@ -26,6 +26,10 @@ struct mpc85xx_cache_sram {
unsigned int size;
rh_info_t *rh;
spinlock_t lock;
+
+#ifdef CONFIG_FSL_85XX_SRAM_UAPI
+ struct device *dev;
+#endif
};
extern void mpc85xx_cache_sram_free(void *ptr);
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index fa3d29dcb57e..3a6f6af973eb 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -16,6 +16,16 @@ if FSL_SOC_BOOKE
if PPC32
+config FSL_85XX_SRAM_UAPI
+ tristate "Freescale MPC85xx SRAM UAPI Support"
+ depends on FSL_SOC_BOOKE && SRAM_DYNAMIC
+ select FSL_85XX_CACHE_SRAM
+ help
+ This registers a device of struct sram_device type which would act as
+ an interface for user level applications to access the Freescale 85xx
+ Cache-SRAM memory dynamically, meaning allocate on demand dynamically
+ while they are running.
+
config FSL_85XX_CACHE_SRAM
bool
select PPC_LIB_RHEAP
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index cb5a5bd2cef5..e71f82f0d2c3 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_FSL_CORENET_RCPM) += fsl_rcpm.o
obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
obj-$(CONFIG_FSL_GTM) += fsl_gtm.o
obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
+obj-$(CONFIG_FSL_85XX_SRAM_UAPI) += fsl_85xx_sram_uapi.o
obj-$(CONFIG_FSL_RIO) += fsl_rio.o fsl_rmu.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h b/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h
index ce370749add9..4930784d9852 100644
--- a/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h
+++ b/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h
@@ -10,6 +10,8 @@
#ifndef __FSL_85XX_CACHE_CTLR_H__
#define __FSL_85XX_CACHE_CTLR_H__
+#include <linux/platform_device.h>
+
#define L2CR_L2FI 0x40000000 /* L2 flash invalidate */
#define L2CR_L2IO 0x00200000 /* L2 instruction only */
#define L2CR_SRAM_ZERO 0x00000000 /* L2SRAM zero size */
@@ -81,6 +83,10 @@ struct sram_parameters {
phys_addr_t sram_offset;
};
+#ifdef CONFIG_FSL_85XX_SRAM_UAPI
+extern struct mpc85xx_cache_sram *mpc85xx_get_cache_sram(void);
+#endif
+
extern int instantiate_cache_sram(struct platform_device *dev,
struct sram_parameters sram_params);
extern void remove_cache_sram(struct platform_device *dev);
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
index 3de5ac8382c0..0156ea63a3a2 100644
--- a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
+++ b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
@@ -23,6 +23,14 @@
struct mpc85xx_cache_sram *cache_sram;
+
+#ifdef CONFIG_FSL_85XX_SRAM_UAPI
+struct mpc85xx_cache_sram *mpc85xx_get_cache_sram(void)
+{
+ return cache_sram;
+}
+#endif
+
void *mpc85xx_cache_sram_alloc(unsigned int size,
phys_addr_t *phys, unsigned int align)
{
@@ -115,6 +123,10 @@ int instantiate_cache_sram(struct platform_device *dev,
rh_attach_region(cache_sram->rh, 0, cache_sram->size);
spin_lock_init(&cache_sram->lock);
+#ifdef CONFIG_FSL_85XX_SRAM_UAPI
+ cache_sram->dev = &dev->dev;
+#endif
+
dev_info(&dev->dev, "[base:0x%llx, size:0x%x] configured and loaded\n",
(unsigned long long)cache_sram->base_phys, cache_sram->size);
diff --git a/arch/powerpc/sysdev/fsl_85xx_sram_uapi.c b/arch/powerpc/sysdev/fsl_85xx_sram_uapi.c
new file mode 100644
index 000000000000..60190bf3c8e9
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_85xx_sram_uapi.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Vivo Communication Technology Co. Ltd.
+ * Copyright (C) 2020 Wang Wenhu <wenhu.wang@vivo.com>
+ * All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sram_dynamic.h>
+#include <asm/fsl_85xx_cache_sram.h>
+#include "fsl_85xx_cache_ctlr.h"
+
+static struct sram_api mpc85xx_sram_api = {
+ .name = "mpc85xx_sram",
+ .alloc = mpc85xx_cache_sram_alloc,
+ .free = mpc85xx_cache_sram_free,
+};
+
+static int __init mpc85xx_sram_uapi_init(void)
+{
+ struct mpc85xx_cache_sram *sram = mpc85xx_get_cache_sram();
+
+ if (!sram)
+ return -ENODEV;
+
+ return sram_register_device(sram->dev, &mpc85xx_sram_api);
+}
+subsys_initcall(mpc85xx_sram_uapi_init);
+
+static void __exit mpc85xx_sram_uapi_exit(void)
+{
+ sram_unregister_device(&mpc85xx_sram_api);
+}
+module_exit(mpc85xx_sram_uapi_exit);
+
+MODULE_AUTHOR("Wang Wenhu <wenhu.wang@vivo.com>");
+MODULE_DESCRIPTION("MPC85xx SRAM User-Space API Support");
+MODULE_LICENSE("GPL v2");
--
2.17.1
^ permalink raw reply related
* [PATCH v3,4/5] misc: sram_dynamic for user level SRAM access
From: Wang Wenhu @ 2020-04-24 2:45 UTC (permalink / raw)
To: gregkh, arnd, linux-kernel, linuxppc-dev
Cc: robh, oss, kernel, paulus, Wang Wenhu
In-Reply-To: <20200424024554.30709-1-wenhu.wang@vivo.com>
A generic User-Kernel interface module that allows a misc device created
when a backend SRAM hardware device driver registers its APIs to support
file operations of ioctl and mmap for user space applications to allocate
SRAM memory, mmap it to process address space and free it then after.
It is extremely helpful for the user space applications that require
high performance memory accesses, such as embedded networking devices
that would process data in user space, and PowerPC e500 is one case.
Signed-off-by: Wang Wenhu <wenhu.wang@vivo.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christophe Leroy <christophe.leroy@c-s.fr>
Cc: Scott Wood <oss@buserror.net>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: linuxppc-dev@lists.ozlabs.org
---
Changes since v1: addressed comments from Arnd
* Changed the ioctl cmd definitions using _IO micros
* Export interfaces for HW-SRAM drivers to register apis to available list
* Modified allocation alignment to PAGE_SIZE
* Use phys_addr_t as type of SRAM resource size and offset
* Support compat_ioctl
* Misc device name:sram
* Use tristate for SRAM_UAPI
* Use postcore_initcall
Changes since v2: addressed comments from Arnd, greg and Scott
* Name the module with sram_dynamic in comparing with drivers/misc/sram.c
I tried to tie the sram_dynamic with the abstractions in sram.c as
Arnd suggested, and actually sram.c probes SRAM devices from devicetree
and manages them with different partitions and create memory pools which
are managed with genalloc functions.
Here sram_dynamic acts only as a interface to user space. A SRAM memory
pool is managed by the module that registers APIs to us, such as the
backend hardware driver of Freescale 85xx Cache-SRAM.
* Create one sram_device for each backend SRAM device(from Scott)
* Allow only one block of SRAM memory allocated to a file descriptor(from Scott)
* Add sysfs files for every allocated SRAM memory block
* More documentations(As Greg commented)
* Make uapi and non-uapi components apart(from Arnd and Greg)
Links:
v1: https://lore.kernel.org/lkml/20200418162157.50428-5-wenhu.wang@vivo.com/
v2: https://lore.kernel.org/lkml/20200420030538.101696-1-wenhu.wang@vivo.com/
UIO version:
v5: https://lore.kernel.org/lkml/20200417071616.44598-5-wenhu.wang@vivo.com/
---
drivers/misc/Kconfig | 11 +
drivers/misc/Makefile | 1 +
drivers/misc/sram_dynamic.c | 580 +++++++++++++++++++++++++++++++++++
drivers/misc/sram_uapi.c | 351 +++++++++++++++++++++
include/linux/sram_dynamic.h | 23 ++
include/uapi/linux/sram.h | 11 +
6 files changed, 977 insertions(+)
create mode 100644 drivers/misc/sram_dynamic.c
create mode 100644 drivers/misc/sram_uapi.c
create mode 100644 include/linux/sram_dynamic.h
create mode 100644 include/uapi/linux/sram.h
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 99e151475d8f..b7ad84e93855 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -465,6 +465,17 @@ config PVPANIC
a paravirtualized device provided by QEMU; it lets a virtual machine
(guest) communicate panic events to the host.
+config SRAM_DYNAMIC
+ tristate "Generic SRAM User Level Dynamic Access API support"
+ help
+ This driver allows you to create a misc device which could be used
+ as an interface to allocate SRAM memory from user level dynamically.
+
+ It is extremely helpful for some user space applications that require
+ high performance memory accesses.
+
+ If unsure, say N.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 9abf2923d831..c32085026d30 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/
obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o
obj-$(CONFIG_SRAM) += sram.o
obj-$(CONFIG_SRAM_EXEC) += sram-exec.o
+obj-$(CONFIG_SRAM_DYNAMIC) += sram_dynamic.o
obj-y += mic/
obj-$(CONFIG_GENWQE) += genwqe/
obj-$(CONFIG_ECHO) += echo/
diff --git a/drivers/misc/sram_dynamic.c b/drivers/misc/sram_dynamic.c
new file mode 100644
index 000000000000..ea2d4d92cccf
--- /dev/null
+++ b/drivers/misc/sram_dynamic.c
@@ -0,0 +1,580 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Vivo Communication Technology Co. Ltd.
+ * Copyright (C) 2020 Wang Wenhu <wenhu.wang@vivo.com>
+ * All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/cdev.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <uapi/linux/sram.h>
+#include <linux/sram_dynamic.h>
+
+#define SRAM_MAX_DEVICES (1U << MINORBITS)
+
+/**
+ * struct sram_res - allocated SRAM memory resource description.
+ *
+ * @virt: virtual memory address of the SRAM memory resource
+ * @phys: physical memory address of the SRAM memory resource
+ * @size: size of the SRAM memory resource
+ * @sdev: sram_device the resource belongs to
+ * @map: sysfs directory of the resource
+ */
+struct sram_res {
+ void __iomem *virt;
+ phys_addr_t phys;
+ __be64 size;
+ struct sram_device *sdev;
+ struct sram_map *map;
+};
+
+/**
+ * struct sram_device - character device that act as an User-Kernel interface.
+ *
+ * A sram_device is created when specific lower level hardware SRAM driver
+ * calls sram_register_device(). The SRAM hardware device is set as the
+ * parent of sram_device. Then user can create a file descriptor when they
+ * open specific sram_device. With the file descriptor, user could request
+ * SRAM memory through ioctl syscall. Available ioctl numbers are defined
+ * in "include/uapi/linux/sram.h".
+ *
+ * @dev: character device to be added to system during SRAM registration
+ * @owner: owner module of the device
+ * @minor: minor id of the character device
+ * @sa: APIs registered by SRAM hardware driver
+ * @map_dir: sysfs directory containing all the maps related to the SRAM
+ */
+struct sram_device {
+ struct device dev;
+ struct module *owner;
+ int minor;
+ struct sram_api *sa;
+ struct kobject *map_dir;
+};
+
+/**
+ * sysfs map attribute fields.
+ *
+ * When a block of SRAM memory is allocated for user, specific map
+ * directory related to it would be created, the dir routine is:
+ *
+ * /sys/class/sram/$sram_device/maps/map:$phys
+ *
+ * Within the directory are the offset and size files whose meanings
+ * are very apparent.
+ *
+ * Multiple directories could be created if different file descriptors are
+ * created by openning the SRAM device. A map directory is removed by calling
+ * sram_del_map_attr() when the memory is released.
+ */
+
+struct sram_map {
+ struct kobject kobj;
+ struct sram_res *res;
+};
+
+#define to_map(map) container_of(map, struct sram_map, kobj)
+
+static ssize_t map_addr_show(struct sram_map *map, char *buf)
+{
+ return sprintf(buf, "%llx\n", (unsigned long long)map->res->phys);
+}
+
+static ssize_t map_size_show(struct sram_map *map, char *buf)
+{
+ return sprintf(buf, "%llx\n", map->res->size);
+}
+
+struct map_sysfs_entry {
+ struct attribute attr;
+ ssize_t (*show)(struct sram_map *map, char *buf);
+ ssize_t (*store)(struct sram_map *map, const char *buf, size_t size);
+};
+
+static struct map_sysfs_entry addr_attribute =
+ __ATTR(addr, 0444, map_addr_show, NULL);
+static struct map_sysfs_entry size_attribute =
+ __ATTR(size, 0444, map_size_show, NULL);
+
+static struct attribute *attrs[] = {
+ &addr_attribute.attr,
+ &size_attribute.attr,
+ NULL, /* need to NULL terminate the list of attributes */
+};
+
+/* callback for kobject_put */
+static void map_release(struct kobject *kobj)
+{
+ struct sram_map *map = to_map(kobj);
+
+ kfree(map);
+}
+
+static ssize_t map_type_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct sram_map *map = to_map(kobj);
+ struct map_sysfs_entry *entry;
+
+ entry = container_of(attr, struct map_sysfs_entry, attr);
+
+ if (!entry->show)
+ return -EIO;
+
+ return entry->show(map, buf);
+}
+
+static const struct sysfs_ops map_sysfs_ops = {
+ .show = map_type_show,
+};
+
+static struct kobj_type map_attr_type = {
+ .release = map_release,
+ .sysfs_ops = &map_sysfs_ops,
+ .default_attrs = attrs,
+};
+
+static DEFINE_MUTEX(minor_lock);
+static int sram_major;
+static struct cdev *sram_cdev;
+static DEFINE_IDR(sram_idr);
+
+
+/**
+ * SRAM character device file operations.
+ *
+ * A file descriptor is allowed to request one and only one block of
+ * SRAM memory. An entry of struct sram_res is used to describe the
+ * allocated SRAM memory resource. If the allocation succeeds, the
+ * virt element of the entry is set to the virtual address pointing
+ * to the SRAM memory. So we use virt as the mark of whether a file
+ * descriptor related to the device is attached to a block of SRAM
+ * memory. Whenever the related SRAM memory block is released, the
+ * virt element is set to NULL.
+ */
+
+static int sram_open(struct inode *inode, struct file *filp)
+{
+ struct sram_res *res;
+ struct sram_device *sdev;
+
+ mutex_lock(&minor_lock);
+ sdev = idr_find(&sram_idr, iminor(inode));
+ mutex_unlock(&minor_lock);
+ if (!sdev)
+ return -ENODEV;
+
+ get_device(&sdev->dev);
+
+ if (!try_module_get(sdev->owner)) {
+ put_device(&sdev->dev);
+ return -ENODEV;
+ }
+
+ res = kzalloc(sizeof(*res), GFP_KERNEL);
+ if (!res) {
+ module_put(sdev->owner);
+ put_device(&sdev->dev);
+ return -ENOMEM;
+ }
+
+ res->sdev = sdev;
+
+ filp->private_data = res;
+
+ return 0;
+}
+
+static int sram_add_map_attr(struct sram_res *res)
+{
+ struct sram_device *sdev = res->sdev;
+ struct sram_map *map;
+ __be64 phys;
+ int ret;
+
+ map = kzalloc(sizeof(*map), GFP_KERNEL);
+ if (!map)
+ return -ENOMEM;
+
+ kobject_init(&map->kobj, &map_attr_type);
+
+ phys = res->phys;
+ ret = kobject_add(&map->kobj, sdev->map_dir, "map:%08llx", phys);
+ if (ret)
+ goto err_put;
+
+ ret = kobject_uevent(&map->kobj, KOBJ_ADD);
+ if (ret)
+ goto err_put;
+
+ map->res = res;
+ res->map = map;
+
+ return 0;
+err_put:
+ kobject_put(&map->kobj);
+ return ret;
+}
+
+static void sram_del_map_attr(struct sram_res *res)
+{
+ struct sram_map *map = res->map;
+
+ kobject_put(&map->kobj);
+}
+
+static long sram_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ struct sram_res *res = filp->private_data;
+ struct sram_device *sdev = res->sdev;
+ long ret = -ENOTTY;
+ __be64 size;
+
+ /**
+ * Two ioctl cmds are supported. SRAM_UAPI_IOC_ALLOC allows
+ * users to request SRAM memory resource, and on the opposite
+ * side, SRAM_UAPI_IOC_FREE is used for SRAM resource free.
+ *
+ * One and only one block of SRAM memory resource is allowed
+ * to be allocated and attached to a file descriptor, so we
+ * take size as the single in parameter of SRAM_UAPI_IOC_ALLOC
+ * ioctl operation. No parameter needs to be copy in or out for
+ * SRAM_UAPI_IOC_FREE operation.
+ *
+ * It's user's choice to decide how the memory block would be
+ * managed and used in user-space, such as a user may request a
+ * large block of memory and then take it as a memory pool for
+ * further allocations of user threads.
+ */
+
+ switch (cmd) {
+ case SRAM_UAPI_IOC_ALLOC:
+ if (res->virt)
+ return -EEXIST;
+
+ if (get_user(size, (__be64 __user *)arg) == -EFAULT)
+ return -EFAULT;
+
+ /**
+ * Size limitation is handled by the driver who
+ * registered the sram APIs.
+ */
+ if (!size || !PAGE_ALIGNED(size))
+ return -EINVAL;
+
+ res->virt = sdev->sa->alloc(size, &res->phys, PAGE_SIZE);
+ if (!res->virt)
+ return -ENOSPC;
+
+ res->size = size;
+
+ ret = sram_add_map_attr(res);
+ if (ret) {
+ sdev->sa->free(res->virt);
+ memset(res, 0, sizeof(*res));
+ return ret;
+ }
+ break;
+
+ case SRAM_UAPI_IOC_FREE:
+ if (res->virt) {
+ sram_del_map_attr(res);
+ sdev->sa->free(res->virt);
+ ret = 0;
+ } else {
+ ret = -EFAULT;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+static int sram_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct sram_res *res = filp->private_data;
+
+ if (!res->virt)
+ return -EFAULT;
+
+ if (vma->vm_end - vma->vm_start > res->size)
+ return -EINVAL;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ return remap_pfn_range(vma, vma->vm_start,
+ res->phys >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+}
+
+static int sram_release(struct inode *inodp, struct file *filp)
+{
+ struct sram_res *res = filp->private_data;
+ struct sram_device *sdev = res->sdev;
+
+ /**
+ * Should have been done with ioctl syscall, but we should still
+ * check and release the resource if res->virt is not NULL, in case
+ * that user did not do it apparently through ioctl syscall.
+ */
+ if (res->virt) {
+ sram_del_map_attr(res);
+ sdev->sa->free(res->virt);
+ }
+
+ kfree(res);
+
+ put_device(&sdev->dev);
+
+ module_put(sdev->owner);
+
+ return 0;
+}
+
+static const struct file_operations sram_fops = {
+ .owner = THIS_MODULE,
+ .open = sram_open,
+ .unlocked_ioctl = sram_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
+ .mmap = sram_mmap,
+ .release = sram_release,
+};
+
+static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", dev_name(dev));
+}
+static DEVICE_ATTR_RO(name);
+
+static struct attribute *sram_attrs[] = {
+ &dev_attr_name.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(sram);
+
+static bool sram_class_registered;
+
+static int sram_get_minor(struct sram_device *sdev)
+{
+ int ret = -ENOMEM;
+
+ mutex_lock(&minor_lock);
+ ret = idr_alloc(&sram_idr, sdev, 0, SRAM_MAX_DEVICES, GFP_KERNEL);
+ if (ret >= 0) {
+ sdev->minor = ret;
+ ret = 0;
+ }
+ mutex_unlock(&minor_lock);
+ return ret;
+}
+
+static void sram_free_minor(struct sram_device *sdev)
+{
+ mutex_lock(&minor_lock);
+ idr_remove(&sram_idr, sdev->minor);
+ mutex_unlock(&minor_lock);
+}
+
+/* SRAM class infrastructure */
+static struct class sram_class = {
+ .name = "sram",
+ .dev_groups = sram_groups,
+};
+
+static int sram_major_init(void)
+{
+ static const char *name = "sram";
+ struct cdev *cdev = NULL;
+ dev_t sram_dev = 0;
+ int ret;
+
+ ret = alloc_chrdev_region(&sram_dev, 0, SRAM_MAX_DEVICES, name);
+ if (ret)
+ return ret;
+
+ ret = -ENOMEM;
+ cdev = cdev_alloc();
+ if (!cdev)
+ goto out_unregister;
+
+ cdev->owner = THIS_MODULE;
+ cdev->ops = &sram_fops;
+ kobject_set_name(&cdev->kobj, "%s", name);
+
+ ret = cdev_add(cdev, sram_dev, SRAM_MAX_DEVICES);
+ if (ret)
+ goto out_put;
+
+ sram_major = MAJOR(sram_dev);
+ sram_cdev = cdev;
+ return 0;
+out_put:
+ kobject_put(&cdev->kobj);
+out_unregister:
+ unregister_chrdev_region(sram_dev, SRAM_MAX_DEVICES);
+ return ret;
+}
+
+static void sram_major_cleanup(void)
+{
+ unregister_chrdev_region(MKDEV(sram_major, 0), SRAM_MAX_DEVICES);
+ cdev_del(sram_cdev);
+}
+
+static int init_sram_class(void)
+{
+ int ret;
+
+ /* Allocate and add char device to the system. */
+ ret = sram_major_init();
+ if (ret)
+ goto exit;
+
+ ret = class_register(&sram_class);
+ if (ret) {
+ pr_err("class_register failed for sram\n");
+ goto err_class_register;
+ }
+
+ sram_class_registered = true;
+
+ return 0;
+
+err_class_register:
+ sram_major_cleanup();
+exit:
+ return ret;
+}
+
+static void release_sram_class(void)
+{
+ sram_class_registered = false;
+ class_unregister(&sram_class);
+ sram_major_cleanup();
+}
+
+static void sram_device_release(struct device *dev)
+{
+ struct sram_device *sdev = dev_get_drvdata(dev);
+
+ kfree(sdev);
+}
+
+/**
+ * sram_register_device() - register a new sram interface device
+ * @owner: module that creates the new device
+ * @parent: parent device
+ * @sa: sram device APIs for SRAM memory allocation and free
+ *
+ * Return: zero on success or a negative error code.
+ */
+int __sram_register_device(struct module *owner,
+ struct device *parent,
+ struct sram_api *sa)
+{
+ struct sram_device *sdev;
+ int ret = 0;
+
+ if (!sram_class_registered)
+ return -EPROBE_DEFER;
+
+ if (!parent || !sa || !sa->alloc || !sa->free)
+ return -EINVAL;
+
+ sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
+ if (!sdev)
+ return -ENOMEM;
+
+ sdev->owner = owner;
+ sdev->sa = sa;
+
+ ret = sram_get_minor(sdev);
+ if (ret) {
+ kfree(sdev);
+ return ret;
+ }
+
+ device_initialize(&sdev->dev);
+ sdev->dev.devt = MKDEV(sram_major, sdev->minor);
+ sdev->dev.class = &sram_class;
+ sdev->dev.parent = parent;
+ sdev->dev.release = sram_device_release;
+ dev_set_drvdata(&sdev->dev, sdev);
+
+ if (sa->name)
+ ret = dev_set_name(&sdev->dev, "%s", sa->name);
+ else
+ ret = dev_set_name(&sdev->dev, "sram%d", sdev->minor);
+ if (ret)
+ goto err_free;
+
+ ret = device_add(&sdev->dev);
+ if (ret)
+ goto err_free;
+
+ sdev->map_dir = kobject_create_and_add("maps", &sdev->dev.kobj);
+ if (!sdev->map_dir) {
+ ret = -ENOMEM;
+ goto err_device_del;
+ }
+
+ sa->sdev = sdev;
+
+ return 0;
+err_device_del:
+ device_del(&sdev->dev);
+err_free:
+ sram_free_minor(sdev);
+ put_device(&sdev->dev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__sram_register_device);
+
+/**
+ * sram_unregister_device() - unregister a sram interface device
+ * @sa: sram device APIs for SRAM memory allocation and free
+ */
+void sram_unregister_device(struct sram_api *sa)
+{
+ struct sram_device *sdev;
+
+ if (!sa || !sa->sdev)
+ return;
+
+ sdev = sa->sdev;
+
+ kobject_put(sdev->map_dir);
+
+ sram_free_minor(sdev);
+
+ sdev->sa = NULL;
+
+ device_unregister(&sdev->dev);
+}
+EXPORT_SYMBOL_GPL(sram_unregister_device);
+
+static int __init sram_uapi_init(void)
+{
+ return init_sram_class();
+}
+postcore_initcall(sram_uapi_init);
+
+static void __exit sram_uapi_exit(void)
+{
+ release_sram_class();
+ idr_destroy(&sram_idr);
+}
+module_exit(sram_uapi_exit);
+
+MODULE_AUTHOR("Wang Wenhu <wenhu.wang@vivo.com>");
+MODULE_DESCRIPTION("SRAM Dynamic Access User API Support");
+MODULE_ALIAS("platform:sram_dynamic");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/sram_uapi.c b/drivers/misc/sram_uapi.c
new file mode 100644
index 000000000000..057bb243f2c8
--- /dev/null
+++ b/drivers/misc/sram_uapi.c
@@ -0,0 +1,351 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Vivo Communication Technology Co. Ltd.
+ * Copyright (C) 2020 Wang Wenhu <wenhu.wang@vivo.com>
+ * All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sram_uapi.h>
+
+#define DRIVER_NAME "sram_uapi"
+
+struct res_info {
+ phys_addr_t offset;
+ phys_addr_t size;
+};
+
+struct sram_resource {
+ struct list_head list;
+ struct res_info info;
+ phys_addr_t phys;
+ void *virt;
+ struct vm_area_struct *vma;
+ struct sram_uapi *parent;
+};
+
+struct sram_uapi {
+ struct list_head res_list;
+ struct sram_api *sa;
+};
+
+static DEFINE_MUTEX(sram_api_list_lock);
+static LIST_HEAD(sram_api_list);
+
+long sram_api_register(struct sram_api *sa)
+{
+ struct sram_api *cur;
+
+ if (!sa || !sa->name || !sa->sram_alloc || !sa->sram_free)
+ return -EINVAL;
+
+ mutex_lock(&sram_api_list_lock);
+ list_for_each_entry(cur, &sram_api_list, list) {
+ if (cur->type == sa->type) {
+ pr_err("error sram %s type %d exists\n", sa->name,
+ sa->type);
+ mutex_unlock(&sram_api_list_lock);
+ return -EEXIST;
+ }
+ }
+
+ kref_init(&sa->kref);
+ list_add_tail(&sa->list, &sram_api_list);
+ pr_info("sram %s type %d registered\n", sa->name, sa->type);
+
+ mutex_unlock(&sram_api_list_lock);
+
+ return 0;
+};
+EXPORT_SYMBOL(sram_api_register);
+
+long sram_api_unregister(struct sram_api *sa)
+{
+ struct sram_api *cur, *tmp;
+ long ret = -ENODEV;
+
+ if (!sa || !sa->name || !sa->sram_alloc || !sa->sram_free)
+ return -EINVAL;
+
+ mutex_lock(&sram_api_list_lock);
+ list_for_each_entry_safe(cur, tmp, &sram_api_list, list) {
+ if (cur->type == sa->type && !strcmp(cur->name, sa->name)) {
+ if (kref_read(&cur->kref)) {
+ pr_err("error sram %s type %d is busy\n",
+ sa->name, sa->type);
+ ret = -EBUSY;
+ } else {
+ list_del(&cur->list);
+ pr_info("sram %s type %d unregistered\n",
+ sa->name, sa->type);
+ ret = 0;
+ }
+ break;
+ }
+ }
+ mutex_unlock(&sram_api_list_lock);
+
+ return ret;
+};
+EXPORT_SYMBOL(sram_api_unregister);
+
+static struct sram_api *get_sram_api_from_type(__u32 type)
+{
+ struct sram_api *cur;
+
+ mutex_lock(&sram_api_list_lock);
+ list_for_each_entry(cur, &sram_api_list, list) {
+ if (cur->type == type) {
+ kref_get(&cur->kref);
+ mutex_unlock(&sram_api_list_lock);
+ return cur;
+ }
+ }
+ mutex_unlock(&sram_api_list_lock);
+
+ return NULL;
+}
+
+static void sram_uapi_res_insert(struct sram_uapi *uapi,
+ struct sram_resource *res)
+{
+ struct sram_resource *cur, *tmp;
+ struct list_head *head = &uapi->res_list;
+
+ list_for_each_entry_safe(cur, tmp, head, list) {
+ if (&tmp->list != head &&
+ (cur->info.offset + cur->info.size + res->info.size <=
+ tmp->info.offset)) {
+ res->info.offset = cur->info.offset + cur->info.size;
+ res->parent = uapi;
+ list_add(&res->list, &cur->list);
+ return;
+ }
+ }
+
+ if (list_empty(head))
+ res->info.offset = 0;
+ else {
+ tmp = list_last_entry(head, struct sram_resource, list);
+ res->info.offset = tmp->info.offset + tmp->info.size;
+ }
+ list_add_tail(&res->list, head);
+}
+
+static struct sram_resource *sram_uapi_res_delete(struct sram_uapi *uapi,
+ struct res_info *info)
+{
+ struct sram_resource *res, *tmp;
+
+ list_for_each_entry_safe(res, tmp, &uapi->res_list, list) {
+ if (res->info.offset == info->offset) {
+ list_del(&res->list);
+ res->parent = NULL;
+ return res;
+ }
+ }
+
+ return NULL;
+}
+
+static struct sram_resource *sram_uapi_find_res(struct sram_uapi *uapi,
+ __u32 offset)
+{
+ struct sram_resource *res;
+
+ list_for_each_entry(res, &uapi->res_list, list) {
+ if (res->info.offset == offset)
+ return res;
+ }
+
+ return NULL;
+}
+
+static int sram_uapi_open(struct inode *inode, struct file *filp)
+{
+ struct sram_uapi *uapi;
+
+ uapi = kzalloc(sizeof(*uapi), GFP_KERNEL);
+ if (!uapi)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&uapi->res_list);
+ filp->private_data = uapi;
+
+ return 0;
+}
+
+static long sram_uapi_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sram_uapi *uapi = filp->private_data;
+ struct sram_resource *res;
+ struct res_info info;
+ long ret = -ENOIOCTLCMD;
+ int size;
+ __u32 type;
+
+ if (!uapi)
+ return ret;
+
+ switch (cmd) {
+ case SRAM_UAPI_IOC_SET_SRAM_TYPE:
+ if (uapi->sa)
+ return -EEXIST;
+
+ get_user(type, (const __u32 __user *)arg);
+ uapi->sa = get_sram_api_from_type(type);
+ if (uapi->sa)
+ ret = 0;
+ else
+ ret = -ENODEV;
+
+ break;
+
+ case SRAM_UAPI_IOC_ALLOC:
+ if (!uapi->sa)
+ return -EINVAL;
+
+ res = kzalloc(sizeof(*res), GFP_KERNEL);
+ if (!res)
+ return -ENOMEM;
+
+ size = copy_from_user((void *)&res->info,
+ (const void __user *)arg,
+ sizeof(res->info));
+ if (!PAGE_ALIGNED(res->info.size) || !res->info.size)
+ return -EINVAL;
+
+ res->virt = (void *)uapi->sa->sram_alloc(res->info.size,
+ &res->phys,
+ PAGE_SIZE);
+ if (!res->virt) {
+ kfree(res);
+ return -ENOMEM;
+ }
+
+ sram_uapi_res_insert(uapi, res);
+ size = copy_to_user((void __user *)arg,
+ (const void *)&res->info,
+ sizeof(res->info));
+
+ ret = 0;
+ break;
+
+ case SRAM_UAPI_IOC_FREE:
+ if (!uapi->sa)
+ return -EINVAL;
+
+ size = copy_from_user((void *)&info, (const void __user *)arg,
+ sizeof(info));
+
+ res = sram_uapi_res_delete(uapi, &info);
+ if (!res) {
+ pr_err("error no sram resource found\n");
+ return -EINVAL;
+ }
+
+ uapi->sa->sram_free(res->virt);
+ kfree(res);
+
+ ret = 0;
+ break;
+
+ default:
+ pr_err("error no cmd not supported\n");
+ break;
+ }
+
+ return ret;
+}
+
+static int sram_uapi_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct sram_uapi *uapi = filp->private_data;
+ struct sram_resource *res;
+
+ res = sram_uapi_find_res(uapi, vma->vm_pgoff);
+ if (!res)
+ return -EINVAL;
+
+ if (vma->vm_end - vma->vm_start > res->info.size)
+ return -EINVAL;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ return remap_pfn_range(vma, vma->vm_start,
+ res->phys >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+}
+
+static void sram_uapi_res_release(struct sram_uapi *uapi)
+{
+ struct sram_resource *res, *tmp;
+
+ list_for_each_entry_safe(res, tmp, &uapi->res_list, list) {
+ list_del(&res->list);
+ uapi->sa->sram_free(res->virt);
+ kfree(res);
+ }
+}
+
+static int sram_uapi_release(struct inode *inodp, struct file *filp)
+{
+ struct sram_uapi *uapi = filp->private_data;
+
+ sram_uapi_res_release(uapi);
+ if (uapi->sa)
+ kref_put(&uapi->sa->kref, NULL);
+
+ kfree(uapi);
+
+ return 0;
+}
+
+static const struct file_operations sram_uapi_ops = {
+ .owner = THIS_MODULE,
+ .open = sram_uapi_open,
+ .unlocked_ioctl = sram_uapi_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
+ .mmap = sram_uapi_mmap,
+ .release = sram_uapi_release,
+};
+
+static struct miscdevice sram_uapi_miscdev = {
+ MISC_DYNAMIC_MINOR,
+ "sram",
+ &sram_uapi_ops,
+};
+
+static int __init sram_uapi_init(void)
+{
+ int ret;
+
+ INIT_LIST_HEAD(&sram_api_list);
+ mutex_init(&sram_api_list_lock);
+
+ ret = misc_register(&sram_uapi_miscdev);
+ if (ret)
+ pr_err("failed to register sram uapi misc device\n");
+
+ return ret;
+}
+postcore_initcall(sram_uapi_init);
+
+static void __exit sram_uapi_exit(void)
+{
+ misc_deregister(&sram_uapi_miscdev);
+}
+module_exit(sram_uapi_exit);
+
+MODULE_AUTHOR("Wang Wenhu <wenhu.wang@vivo.com>");
+MODULE_DESCRIPTION("SRAM User API Driver");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/sram_dynamic.h b/include/linux/sram_dynamic.h
new file mode 100644
index 000000000000..c77e9e7b1151
--- /dev/null
+++ b/include/linux/sram_dynamic.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SRAM_DYNAMIC_H
+#define __SRAM_DYNAMIC_H
+
+struct sram_api {
+ const char *name;
+ struct sram_device *sdev;
+ void *(*alloc)(__u32 size, phys_addr_t *phys, __u32 align);
+ void (*free)(void *ptr);
+};
+
+extern int __must_check
+ __sram_register_device(struct module *owner,
+ struct device *parent,
+ struct sram_api *sa);
+
+/* Use a define to avoid include chaining to get THIS_MODULE */
+#define sram_register_device(parent, sa) \
+ __sram_register_device(THIS_MODULE, parent, sa)
+
+extern void sram_unregister_device(struct sram_api *sa);
+
+#endif /* __SRAM_DYNAMIC_H */
diff --git a/include/uapi/linux/sram.h b/include/uapi/linux/sram.h
new file mode 100644
index 000000000000..9b4a2615dbfe
--- /dev/null
+++ b/include/uapi/linux/sram.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SRAM_H
+#define __SRAM_H
+
+/* Allocate memory resource from SRAM */
+#define SRAM_UAPI_IOC_ALLOC _IOWR('S', 0, __be64)
+
+/* Free allocated memory resource to SRAM */
+#define SRAM_UAPI_IOC_FREE _IO('S', 1)
+
+#endif /* __SRAM_H */
--
2.17.1
^ permalink raw reply related
* [PATCH v3, 3/5] powerpc: sysdev: fix compile warning for fsl_85xx_cache_sram
From: Wang Wenhu @ 2020-04-24 2:45 UTC (permalink / raw)
To: gregkh, arnd, linux-kernel, linuxppc-dev
Cc: robh, oss, kernel, paulus, Wang Wenhu
In-Reply-To: <20200424024554.30709-1-wenhu.wang@vivo.com>
Function instantiate_cache_sram should not be linked into the init
section for its caller mpc85xx_l2ctlr_of_probe is none-__init.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christophe Leroy <christophe.leroy@c-s.fr>
Cc: Scott Wood <oss@buserror.net>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: linuxppc-dev@lists.ozlabs.org
Fixes: 6db92cc9d07d ("powerpc/85xx: add cache-sram support")
Reviewed-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Wang Wenhu <wenhu.wang@vivo.com>
---
No changes
---
arch/powerpc/sysdev/fsl_85xx_cache_sram.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
index be3aef4229d7..3de5ac8382c0 100644
--- a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
+++ b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
@@ -68,7 +68,7 @@ void mpc85xx_cache_sram_free(void *ptr)
}
EXPORT_SYMBOL(mpc85xx_cache_sram_free);
-int __init instantiate_cache_sram(struct platform_device *dev,
+int instantiate_cache_sram(struct platform_device *dev,
struct sram_parameters sram_params)
{
int ret = 0;
--
2.17.1
^ permalink raw reply related
* [PATCH v3, 2/5] powerpc: sysdev: fix compile error for fsl_85xx_cache_sram
From: Wang Wenhu @ 2020-04-24 2:45 UTC (permalink / raw)
To: gregkh, arnd, linux-kernel, linuxppc-dev
Cc: robh, oss, kernel, paulus, Wang Wenhu
In-Reply-To: <20200424024554.30709-1-wenhu.wang@vivo.com>
Include linux/io.h into fsl_85xx_cache_sram.c to fix the
implicit-declaration compile error when building Cache-Sram.
arch/powerpc/sysdev/fsl_85xx_cache_sram.c: In function ‘instantiate_cache_sram’:
arch/powerpc/sysdev/fsl_85xx_cache_sram.c:97:26: error: implicit declaration of function ‘ioremap_coherent’; did you mean ‘bitmap_complement’? [-Werror=implicit-function-declaration]
cache_sram->base_virt = ioremap_coherent(cache_sram->base_phys,
^~~~~~~~~~~~~~~~
bitmap_complement
arch/powerpc/sysdev/fsl_85xx_cache_sram.c:97:24: error: assignment makes pointer from integer without a cast [-Werror=int-conversion]
cache_sram->base_virt = ioremap_coherent(cache_sram->base_phys,
^
arch/powerpc/sysdev/fsl_85xx_cache_sram.c:123:2: error: implicit declaration of function ‘iounmap’; did you mean ‘roundup’? [-Werror=implicit-function-declaration]
iounmap(cache_sram->base_virt);
^~~~~~~
roundup
cc1: all warnings being treated as errors
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christophe Leroy <christophe.leroy@c-s.fr>
Cc: Scott Wood <oss@buserror.net>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: linuxppc-dev@lists.ozlabs.org
Fixes: 6db92cc9d07d ("powerpc/85xx: add cache-sram support")
Reviewed-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Wang Wenhu <wenhu.wang@vivo.com>
---
No changes
---
arch/powerpc/sysdev/fsl_85xx_cache_sram.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
index f6c665dac725..be3aef4229d7 100644
--- a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
+++ b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
@@ -17,6 +17,7 @@
#include <linux/of_platform.h>
#include <asm/pgtable.h>
#include <asm/fsl_85xx_cache_sram.h>
+#include <linux/io.h>
#include "fsl_85xx_cache_ctlr.h"
--
2.17.1
^ permalink raw reply related
* [PATCH v3,0/5] misc: generic user level sram dynamic access support
From: Wang Wenhu @ 2020-04-24 2:45 UTC (permalink / raw)
To: gregkh, arnd, linux-kernel, linuxppc-dev
Cc: robh, oss, kernel, paulus, Wang Wenhu
This series add a new misc module that act as an interface for user level
applications to access SRAM memory dynamically. Freescale 85xx Cache-SRAM
is exact an example.
This is extremely helpful for the user level applications that require
high performance memory accesses, such as some embedded networking devices
that need to process data in user space.
The series also fix the compile errors and warning of the freescale 85xx
Cache-SRAM driver, and implement a module to register the SRAM device to
sram_dynamic module, which enables its access for users in user space.
Changes since v1: addressed comments from Arnd
* Changed the ioctl cmd definitions using _IO micros
* Export interfaces for HW-SRAM drivers to register apis to available list
* Modified allocation alignment to PAGE_SIZE
* Use phys_addr_t as type of SRAM resource size and offset
* Support compat_ioctl
* Misc device name:sram
* Use tristate for SRAM_UAPI
* Use postcore_initcall
Changes since v2: addressed comments from Arnd, greg and Scott
* Name the module with sram_dynamic in comparing with drivers/misc/sram.c
I tried to tie the sram_dynamic with the abstractions in sram.c as
Arnd suggested, and actually sram.c probes SRAM devices from devicetree
and manages them with different partitions and create memory pools which
are managed with genalloc functions.
Here sram_dynamic acts only as a interface to user space. A SRAM memory
pool is managed by the module that registers APIs to us, such as the
backend hardware driver of Freescale 85xx Cache-SRAM.
* Create one sram_device for each backend SRAM device(from Scott)
* Allow only one block of SRAM memory allocated to a file descriptor(from Scott)
* Add sysfs files for every allocated SRAM memory block
* More documentations(As Greg commented)
* Make uapi and non-uapi components apart(from Arnd and Greg)
* Add a new module to register freescale 85xx Cache-SRAM APIs to the
sram_dynamic module
Wang Wenhu (5):
powerpc: sysdev: fix compile error for fsl_85xx_l2ctlr
powerpc: sysdev: fix compile error for fsl_85xx_cache_sram
powerpc: sysdev: fix compile warning for fsl_85xx_cache_sram
misc: sram_dynamic for user level SRAM access
powerpc: sysdev: support userspace access of fsl 85xx sram
.../powerpc/include/asm/fsl_85xx_cache_sram.h | 4 +
arch/powerpc/platforms/85xx/Kconfig | 10 +
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h | 6 +
arch/powerpc/sysdev/fsl_85xx_cache_sram.c | 15 +-
arch/powerpc/sysdev/fsl_85xx_l2ctlr.c | 1 +
arch/powerpc/sysdev/fsl_85xx_sram_uapi.c | 39 ++
drivers/misc/Kconfig | 11 +
drivers/misc/Makefile | 1 +
drivers/misc/sram_dynamic.c | 580 ++++++++++++++++++
drivers/misc/sram_uapi.c | 351 +++++++++++
include/linux/sram_dynamic.h | 23 +
include/uapi/linux/sram.h | 11 +
13 files changed, 1052 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/sysdev/fsl_85xx_sram_uapi.c
create mode 100644 drivers/misc/sram_dynamic.c
create mode 100644 drivers/misc/sram_uapi.c
create mode 100644 include/linux/sram_dynamic.h
create mode 100644 include/uapi/linux/sram.h
--
2.17.1
^ permalink raw reply
* [PATCH v3, 1/5] powerpc: sysdev: fix compile error for fsl_85xx_l2ctlr
From: Wang Wenhu @ 2020-04-24 2:45 UTC (permalink / raw)
To: gregkh, arnd, linux-kernel, linuxppc-dev
Cc: robh, oss, kernel, paulus, Wang Wenhu
In-Reply-To: <20200424024554.30709-1-wenhu.wang@vivo.com>
Include "linux/of_address.h" to fix the compile error for
mpc85xx_l2ctlr_of_probe() when compiling fsl_85xx_cache_sram.c.
CC arch/powerpc/sysdev/fsl_85xx_l2ctlr.o
arch/powerpc/sysdev/fsl_85xx_l2ctlr.c: In function ‘mpc85xx_l2ctlr_of_probe’:
arch/powerpc/sysdev/fsl_85xx_l2ctlr.c:90:11: error: implicit declaration of function ‘of_iomap’; did you mean ‘pci_iomap’? [-Werror=implicit-function-declaration]
l2ctlr = of_iomap(dev->dev.of_node, 0);
^~~~~~~~
pci_iomap
arch/powerpc/sysdev/fsl_85xx_l2ctlr.c:90:9: error: assignment makes pointer from integer without a cast [-Werror=int-conversion]
l2ctlr = of_iomap(dev->dev.of_node, 0);
^
cc1: all warnings being treated as errors
scripts/Makefile.build:267: recipe for target 'arch/powerpc/sysdev/fsl_85xx_l2ctlr.o' failed
make[2]: *** [arch/powerpc/sysdev/fsl_85xx_l2ctlr.o] Error 1
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christophe Leroy <christophe.leroy@c-s.fr>
Cc: Scott Wood <oss@buserror.net>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: linuxppc-dev@lists.ozlabs.org
Fixes: 6db92cc9d07d ("powerpc/85xx: add cache-sram support")
Reviewed-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Wang Wenhu <wenhu.wang@vivo.com>
---
No changes
---
arch/powerpc/sysdev/fsl_85xx_l2ctlr.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
index 2d0af0c517bb..7533572492f0 100644
--- a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
+++ b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_platform.h>
+#include <linux/of_address.h>
#include <asm/io.h>
#include "fsl_85xx_cache_ctlr.h"
--
2.17.1
^ permalink raw reply related
* Re: [PATCH 3/3] powerpc/module_64: Use special stub for _mcount() with -mprofile-kernel
From: Qian Cai @ 2020-04-24 1:19 UTC (permalink / raw)
To: Naveen N. Rao; +Cc: linuxppc-dev, Steven Rostedt
In-Reply-To: <8affd4298d22099bbd82544fab8185700a6222b1.1587488954.git.naveen.n.rao@linux.vnet.ibm.com>
> On Apr 21, 2020, at 1:35 PM, Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> wrote:
>
> Since commit c55d7b5e64265f ("powerpc: Remove STRICT_KERNEL_RWX
> incompatibility with RELOCATABLE"), powerpc kernels with
> -mprofile-kernel can crash in certain scenarios with a trace like below:
>
> BUG: Unable to handle kernel instruction fetch (NULL pointer?)
> Faulting instruction address: 0x00000000
> Oops: Kernel access of bad area, sig: 11 [#1]
> LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=256 DEBUG_PAGEALLOC NUMA PowerNV
> <snip>
> NIP [0000000000000000] 0x0
> LR [c0080000102c0048] ext4_iomap_end+0x8/0x30 [ext4]
> Call Trace:
> iomap_apply+0x20c/0x920 (unreliable)
> iomap_bmap+0xfc/0x160
> ext4_bmap+0xa4/0x180 [ext4]
> bmap+0x4c/0x80
> jbd2_journal_init_inode+0x44/0x1a0 [jbd2]
> ext4_load_journal+0x440/0x860 [ext4]
> ext4_fill_super+0x342c/0x3ab0 [ext4]
> mount_bdev+0x25c/0x290
> ext4_mount+0x28/0x50 [ext4]
> legacy_get_tree+0x4c/0xb0
> vfs_get_tree+0x4c/0x130
> do_mount+0xa18/0xc50
> sys_mount+0x158/0x180
> system_call+0x5c/0x68
>
> The NIP points to NULL, or a random location (data even), while the LR
> always points to the LEP of a function (with an offset of 8), indicating
> that something went wrong with ftrace. However, ftrace is not
> necessarily active when such crashes occur.
>
> The kernel OOPS sometimes follows a warning from ftrace indicating that
> some module functions could not be patched with a nop. Other times, if a
> module is loaded early during boot, instruction patching can fail due to
> a separate bug, but the error is not reported due to missing error
> reporting.
>
> In all the above cases when instruction patching fails, ftrace will be
> disabled but certain kernel module functions will be left with default
> calls to _mcount(). This is not a problem with ELFv1. However, with
> -mprofile-kernel, the default stub is problematic since it depends on a
> valid module TOC in r2. If the kernel (or a different module) calls into
> a function that does not use the TOC, the function won't have a prologue
> to setup the module TOC. When that function calls into _mcount(), we
> will end up in the relocation stub that will use the previous TOC, and
> end up trying to jump into a random location. From the above trace:
>
> iomap_apply+0x20c/0x920 [kernel TOC]
> |
> V
> ext4_iomap_end+0x8/0x30 [no GEP == kernel TOC]
> |
> V
> _mcount() stub
> [uses kernel TOC -> random entry]
>
> To address this, let's change over to using the special stub that is
> used for ftrace_[regs_]caller() for _mcount(). This ensures that we are
> not dependent on a valid module TOC in r2 for default _mcount()
> handling.
>
> Reported-by: Qian Cai <cai@lca.pw>
> Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Feel free to add,
Tested-by: Qian Cai <cai@lca.pw>
^ permalink raw reply
* Re: [PATCH 17/21] mm: free_area_init: allow defining max_zone_pfn in descending order
From: Baoquan He @ 2020-04-24 0:33 UTC (permalink / raw)
To: Mike Rapoport
Cc: Rich Felker, linux-ia64, linux-doc, Catalin Marinas,
Heiko Carstens, Michal Hocko, James E.J. Bottomley, Max Filippov,
Guo Ren, linux-csky, linux-parisc, sparclinux, linux-hexagon,
linux-riscv, Greg Ungerer, linux-arch, linux-s390, linux-snps-arc,
linux-c6x-dev, Brian Cain, Jonathan Corbet, linux-sh,
Helge Deller, x86, Russell King, Ley Foon Tan, Mike Rapoport,
Geert Uytterhoeven, linux-arm-kernel, Mark Salter, Matt Turner,
linux-mips, uclinux-h8-devel, linux-xtensa, linux-alpha, linux-um,
linux-m68k, Tony Luck, Greentime Hu, Paul Walmsley,
Stafford Horne, Guan Xuetao, Hoan Tran, Michal Simek,
Thomas Bogendoerfer, Yoshinori Sato, Nick Hu, linux-mm,
Vineet Gupta, linux-kernel, openrisc, Richard Weinberger,
Andrew Morton, linuxppc-dev, David S. Miller
In-Reply-To: <20200423055559.GF14260@kernel.org>
On 04/23/20 at 08:55am, Mike Rapoport wrote:
> On Thu, Apr 23, 2020 at 10:57:20AM +0800, Baoquan He wrote:
> > On 04/23/20 at 10:53am, Baoquan He wrote:
> > > On 04/12/20 at 10:48pm, Mike Rapoport wrote:
> > > > From: Mike Rapoport <rppt@linux.ibm.com>
> > > >
> > > > Some architectures (e.g. ARC) have the ZONE_HIGHMEM zone below the
> > > > ZONE_NORMAL. Allowing free_area_init() parse max_zone_pfn array even it is
> > > > sorted in descending order allows using free_area_init() on such
> > > > architectures.
> > > >
> > > > Add top -> down traversal of max_zone_pfn array in free_area_init() and use
> > > > the latter in ARC node/zone initialization.
> > >
> > > Or maybe leave ARC as is. The change in this patchset doesn't impact
> > > ARC's handling about zone initialization, leaving it as is can reduce
> > > the complication in implementation of free_area_init(), which is a
> > > common function. So I personally don't see a strong motivation to have
> > > this patch.
> >
> > OK, seems this patch is prepared to simplify free_area_init_node(), so
> > take back what I said at above.
> >
> > Then this looks necessary, even though it introduces special case into
> > common function free_area_init().
>
> The idea is to have a single free_area_init() for all architectures
> without keeping two completely different ways of calculating the zone
> extents.
> Another thing, is that with this we could eventually switch ARC from
> DISCONTIGMEM.
Yeah, I think uniting them into a single free_area_init() is a great
idea. Even though I had been through this patchset, when looked into
each of them, still may forget the detail in later patch :)
^ permalink raw reply
* [Bug 206695] kmemleak reports leaks in drivers/macintosh/windfarm
From: bugzilla-daemon @ 2020-04-24 0:30 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <bug-206695-206035@https.bugzilla.kernel.org/>
https://bugzilla.kernel.org/show_bug.cgi?id=206695
Dennis Clarke (dclarke@blastwave.org) changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |dclarke@blastwave.org
--- Comment #8 from Dennis Clarke (dclarke@blastwave.org) ---
123456789+123456789+123456789+123456789+123456789+123456789+123456789+
I will apply the patch and try with Linux 5.7-rc2 and post any results
seen.
Also this does close off : https://bugzilla.kernel.org/show_bug.cgi?id=199471
I see Wolfram Sang has commented there. OKay ... good stuff.
Dennis Clarke
--
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply
* [powerpc:fixes-test] BUILD SUCCESS feb8e960d780e170e992a70491eec9dd68f4dbf2
From: kbuild test robot @ 2020-04-23 23:04 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git fixes-test
branch HEAD: feb8e960d780e170e992a70491eec9dd68f4dbf2 powerpc/mm: Fix CONFIG_PPC_KUAP_DEBUG on PPC32
elapsed time: 1303m
configs tested: 221
configs skipped: 167
The following configs have been built successfully.
More configs may be tested in the coming days.
arm efm32_defconfig
arm at91_dt_defconfig
arm shmobile_defconfig
arm64 defconfig
arm exynos_defconfig
arm multi_v5_defconfig
arm sunxi_defconfig
arm multi_v7_defconfig
arm64 allyesconfig
arm allyesconfig
arm64 allmodconfig
arm allmodconfig
arm64 allnoconfig
arm allnoconfig
sparc allyesconfig
mips ar7_defconfig
um i386_defconfig
ia64 tiger_defconfig
i386 defconfig
riscv allmodconfig
i386 allnoconfig
i386 allyesconfig
i386 alldefconfig
i386 debian-10.3
ia64 allmodconfig
ia64 defconfig
ia64 allnoconfig
ia64 generic_defconfig
ia64 bigsur_defconfig
ia64 allyesconfig
ia64 alldefconfig
nios2 3c120_defconfig
nios2 10m50_defconfig
c6x evmc6678_defconfig
xtensa iss_defconfig
c6x allyesconfig
xtensa common_defconfig
openrisc simple_smp_defconfig
openrisc or1ksim_defconfig
h8300 h8s-sim_defconfig
h8300 edosk2674_defconfig
m68k m5475evb_defconfig
m68k allmodconfig
h8300 h8300h-sim_defconfig
m68k sun3_defconfig
m68k multi_defconfig
powerpc defconfig
powerpc ppc64_defconfig
powerpc rhel-kconfig
powerpc allnoconfig
arc defconfig
arc allyesconfig
microblaze mmu_defconfig
microblaze nommu_defconfig
mips fuloong2e_defconfig
mips malta_kvm_defconfig
mips allyesconfig
mips 64r6el_defconfig
mips allnoconfig
mips 32r2_defconfig
mips allmodconfig
mips malta_kvm_guest_defconfig
mips tb0287_defconfig
mips capcella_defconfig
mips ip32_defconfig
mips decstation_64_defconfig
mips loongson3_defconfig
mips ath79_defconfig
mips bcm63xx_defconfig
parisc allnoconfig
parisc generic-64bit_defconfig
parisc generic-32bit_defconfig
parisc allyesconfig
parisc allmodconfig
parisc randconfig-a001-20200423
alpha randconfig-a001-20200423
mips randconfig-a001-20200423
m68k randconfig-a001-20200423
riscv randconfig-a001-20200423
nds32 randconfig-a001-20200423
parisc randconfig-a001-20200422
mips randconfig-a001-20200422
alpha randconfig-a001-20200422
m68k randconfig-a001-20200422
riscv randconfig-a001-20200422
nds32 randconfig-a001-20200422
nios2 randconfig-a001-20200423
h8300 randconfig-a001-20200423
c6x randconfig-a001-20200423
sparc64 randconfig-a001-20200423
microblaze randconfig-a001-20200423
nios2 randconfig-a001-20200422
h8300 randconfig-a001-20200422
c6x randconfig-a001-20200422
sparc64 randconfig-a001-20200422
microblaze randconfig-a001-20200422
sh randconfig-a001-20200423
csky randconfig-a001-20200423
xtensa randconfig-a001-20200423
openrisc randconfig-a001-20200423
sh randconfig-a001-20200422
csky randconfig-a001-20200422
s390 randconfig-a001-20200422
xtensa randconfig-a001-20200422
openrisc randconfig-a001-20200422
i386 randconfig-b002-20200422
i386 randconfig-b001-20200422
x86_64 randconfig-b001-20200422
i386 randconfig-b003-20200422
x86_64 randconfig-b003-20200422
x86_64 randconfig-a001-20200422
i386 randconfig-a003-20200422
x86_64 randconfig-a003-20200422
i386 randconfig-a002-20200422
i386 randconfig-a001-20200422
x86_64 randconfig-a002-20200422
i386 randconfig-c002-20200423
i386 randconfig-c001-20200423
x86_64 randconfig-c002-20200423
x86_64 randconfig-c001-20200423
i386 randconfig-c003-20200423
x86_64 randconfig-c003-20200423
x86_64 randconfig-d001-20200423
x86_64 randconfig-d002-20200423
i386 randconfig-d002-20200423
i386 randconfig-d001-20200423
x86_64 randconfig-d003-20200423
i386 randconfig-d003-20200423
x86_64 randconfig-d002-20200422
i386 randconfig-d002-20200422
i386 randconfig-d001-20200422
i386 randconfig-d003-20200422
i386 randconfig-e003-20200422
x86_64 randconfig-e003-20200422
i386 randconfig-e002-20200422
i386 randconfig-e001-20200422
x86_64 randconfig-e001-20200422
x86_64 randconfig-e002-20200423
i386 randconfig-e003-20200423
x86_64 randconfig-e003-20200423
i386 randconfig-e002-20200423
i386 randconfig-e001-20200423
x86_64 randconfig-e001-20200423
i386 randconfig-f002-20200421
i386 randconfig-f003-20200421
x86_64 randconfig-f003-20200421
i386 randconfig-f001-20200421
x86_64 randconfig-f001-20200421
x86_64 randconfig-f002-20200422
i386 randconfig-f002-20200422
x86_64 randconfig-f003-20200422
i386 randconfig-f003-20200422
i386 randconfig-f001-20200422
x86_64 randconfig-f001-20200422
i386 randconfig-g003-20200422
x86_64 randconfig-g001-20200422
i386 randconfig-g001-20200422
x86_64 randconfig-g002-20200422
i386 randconfig-g002-20200422
x86_64 randconfig-g003-20200422
i386 randconfig-g003-20200424
i386 randconfig-g001-20200424
x86_64 randconfig-g001-20200424
x86_64 randconfig-g002-20200424
i386 randconfig-g002-20200424
x86_64 randconfig-g003-20200424
i386 randconfig-g003-20200423
x86_64 randconfig-g001-20200423
i386 randconfig-g001-20200423
i386 randconfig-g002-20200423
x86_64 randconfig-g003-20200423
i386 randconfig-h003-20200424
x86_64 randconfig-h001-20200424
x86_64 randconfig-h003-20200424
x86_64 randconfig-h002-20200424
i386 randconfig-h001-20200424
i386 randconfig-h002-20200424
i386 randconfig-h003-20200422
x86_64 randconfig-h001-20200422
x86_64 randconfig-h003-20200422
x86_64 randconfig-h002-20200422
i386 randconfig-h001-20200422
i386 randconfig-h002-20200422
i386 randconfig-h003-20200423
x86_64 randconfig-h002-20200423
i386 randconfig-h002-20200423
i386 randconfig-h001-20200423
sparc randconfig-a001-20200423
ia64 randconfig-a001-20200423
arm randconfig-a001-20200423
arm64 randconfig-a001-20200423
arc randconfig-a001-20200423
sparc randconfig-a001-20200422
ia64 randconfig-a001-20200422
powerpc randconfig-a001-20200422
arm randconfig-a001-20200422
arm64 randconfig-a001-20200422
arc randconfig-a001-20200422
riscv allyesconfig
riscv nommu_virt_defconfig
riscv allnoconfig
riscv defconfig
riscv rv32_defconfig
s390 zfcpdump_defconfig
s390 debug_defconfig
s390 allyesconfig
s390 allnoconfig
s390 allmodconfig
s390 alldefconfig
s390 defconfig
sh rsk7269_defconfig
sh allmodconfig
sh titan_defconfig
sh sh7785lcr_32bit_defconfig
sh allnoconfig
sparc defconfig
sparc64 defconfig
sparc64 allnoconfig
sparc64 allyesconfig
sparc64 allmodconfig
x86_64 rhel
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply
* Re: [PATCH v8 1/1] powerpc/powernv: Introduce support and parsing for self-save API
From: Gautham R Shenoy @ 2020-04-23 18:15 UTC (permalink / raw)
To: Pratik Rajesh Sampat
Cc: ego, pratik.r.sampat, linuxram, linux-kernel, linuxppc-dev,
oohall, skiboot
In-Reply-To: <20200423105557.29108-2-psampat@linux.ibm.com>
On Thu, Apr 23, 2020 at 04:25:57PM +0530, Pratik Rajesh Sampat wrote:
> This commit introduces and leverages the Self save API. The difference
> between self-save and self-restore is that the value to be saved for the
> SPR does not need to be passed to the call.
>
> Add the new Self Save OPAL API call in the list of OPAL calls.
>
> The device tree is parsed looking for the property "ibm,opal-self-save"
> If self-save is supported then for all SPRs self-save is invoked for all
> P9 supported registers. In the case self-save fails corresponding
> self-restore call is invoked as a fallback.
>
> Signed-off-by: Pratik Rajesh Sampat <psampat@linux.ibm.com>
A suggestion from the bisectability point of view though.
Since in this patch you are also invoking self_save API for a new SPR,
namely PTCR which was previously not present, I would suggest that you
move the PTCR changes to a different patch.
Otherwise, the patchset looks good to me
Reviewed-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
> ---
> arch/powerpc/include/asm/opal-api.h | 3 +-
> arch/powerpc/include/asm/opal.h | 1 +
> arch/powerpc/platforms/powernv/idle.c | 73 ++++++++++++++++++----
> arch/powerpc/platforms/powernv/opal-call.c | 1 +
> 4 files changed, 64 insertions(+), 14 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
> index 1dffa3cb16ba..7ba698369083 100644
> --- a/arch/powerpc/include/asm/opal-api.h
> +++ b/arch/powerpc/include/asm/opal-api.h
> @@ -214,7 +214,8 @@
> #define OPAL_SECVAR_GET 176
> #define OPAL_SECVAR_GET_NEXT 177
> #define OPAL_SECVAR_ENQUEUE_UPDATE 178
> -#define OPAL_LAST 178
> +#define OPAL_SLW_SELF_SAVE_REG 181
> +#define OPAL_LAST 181
>
> #define QUIESCE_HOLD 1 /* Spin all calls at entry */
> #define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
> diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
> index 9986ac34b8e2..a370b0e8d899 100644
> --- a/arch/powerpc/include/asm/opal.h
> +++ b/arch/powerpc/include/asm/opal.h
> @@ -204,6 +204,7 @@ int64_t opal_handle_hmi2(__be64 *out_flags);
> int64_t opal_register_dump_region(uint32_t id, uint64_t start, uint64_t end);
> int64_t opal_unregister_dump_region(uint32_t id);
> int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val);
> +int64_t opal_slw_self_save_reg(uint64_t cpu_pir, uint64_t sprn);
> int64_t opal_config_cpu_idle_state(uint64_t state, uint64_t flag);
> int64_t opal_pci_set_phb_cxl_mode(uint64_t phb_id, uint64_t mode, uint64_t pe_number);
> int64_t opal_pci_get_pbcq_tunnel_bar(uint64_t phb_id, uint64_t *addr);
> diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
> index 78599bca66c2..ada7ece24521 100644
> --- a/arch/powerpc/platforms/powernv/idle.c
> +++ b/arch/powerpc/platforms/powernv/idle.c
> @@ -32,6 +32,11 @@
> #define P9_STOP_SPR_MSR 2000
> #define P9_STOP_SPR_PSSCR 855
>
> +/* Caching the self-save functionality, lpcr, ptcr support */
> +DEFINE_STATIC_KEY_FALSE(self_save_available);
> +DEFINE_STATIC_KEY_FALSE(is_lpcr_self_save);
> +DEFINE_STATIC_KEY_FALSE(is_ptcr_self_save);
> +
> static u32 supported_cpuidle_states;
> struct pnv_idle_states_t *pnv_idle_states;
> int nr_pnv_idle_states;
> @@ -61,6 +66,35 @@ static bool deepest_stop_found;
>
> static unsigned long power7_offline_type;
>
> +/*
> + * Cache support for SPRs that support self-save as well as kernel save restore
> + * so that kernel does not duplicate efforts in saving and restoring SPRs
> + */
> +static void cache_spr_self_save_support(u64 sprn)
> +{
> + switch (sprn) {
> + case SPRN_LPCR:
> + static_branch_enable(&is_lpcr_self_save);
> + break;
> + case SPRN_PTCR:
> + static_branch_enable(&is_ptcr_self_save);
> + break;
> + }
> +}
> +
> +static int pnv_save_one_spr(u64 pir, u64 sprn, u64 val)
> +{
> + if (static_branch_likely(&self_save_available)) {
> + int rc = opal_slw_self_save_reg(pir, sprn);
> +
> + if (!rc) {
> + cache_spr_self_save_support(sprn);
> + return rc;
> + }
> + }
> + return opal_slw_set_reg(pir, sprn, val);
> +}
> +
> static int pnv_save_sprs_for_deep_states(void)
> {
> int cpu;
> @@ -72,6 +106,7 @@ static int pnv_save_sprs_for_deep_states(void)
> * same across all cpus.
> */
> uint64_t lpcr_val = mfspr(SPRN_LPCR);
> + uint64_t ptcr_val = mfspr(SPRN_PTCR);
> uint64_t hid0_val = mfspr(SPRN_HID0);
> uint64_t hid1_val = mfspr(SPRN_HID1);
> uint64_t hid4_val = mfspr(SPRN_HID4);
> @@ -84,30 +119,34 @@ static int pnv_save_sprs_for_deep_states(void)
> uint64_t pir = get_hard_smp_processor_id(cpu);
> uint64_t hsprg0_val = (uint64_t)paca_ptrs[cpu];
>
> - rc = opal_slw_set_reg(pir, SPRN_HSPRG0, hsprg0_val);
> + rc = pnv_save_one_spr(pir, SPRN_HSPRG0, hsprg0_val);
> if (rc != 0)
> return rc;
>
> - rc = opal_slw_set_reg(pir, SPRN_LPCR, lpcr_val);
> + rc = pnv_save_one_spr(pir, SPRN_LPCR, lpcr_val);
> if (rc != 0)
> return rc;
>
> + /*
> + * No need to check for failure, if firmware fails to save then
> + * kernel handles save-restore for PTCR
> + */
> + pnv_save_one_spr(pir, SPRN_PTCR, ptcr_val);
> +
> if (cpu_has_feature(CPU_FTR_ARCH_300)) {
> - rc = opal_slw_set_reg(pir, P9_STOP_SPR_MSR, msr_val);
> + rc = pnv_save_one_spr(pir, P9_STOP_SPR_MSR, msr_val);
> if (rc)
> return rc;
>
> - rc = opal_slw_set_reg(pir,
> + rc = pnv_save_one_spr(pir,
> P9_STOP_SPR_PSSCR, psscr_val);
> -
> if (rc)
> return rc;
> }
>
> /* HIDs are per core registers */
> if (cpu_thread_in_core(cpu) == 0) {
> -
> - rc = opal_slw_set_reg(pir, SPRN_HMEER, hmeer_val);
> + rc = pnv_save_one_spr(pir, SPRN_HMEER, hmeer_val);
> if (rc != 0)
> return rc;
>
> @@ -658,7 +697,8 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
> mmcr0 = mfspr(SPRN_MMCR0);
> }
> if ((psscr & PSSCR_RL_MASK) >= pnv_first_spr_loss_level) {
> - sprs.lpcr = mfspr(SPRN_LPCR);
> + if (!static_branch_unlikely(&is_lpcr_self_save))
> + sprs.lpcr = mfspr(SPRN_LPCR);
> sprs.hfscr = mfspr(SPRN_HFSCR);
> sprs.fscr = mfspr(SPRN_FSCR);
> sprs.pid = mfspr(SPRN_PID);
> @@ -672,7 +712,8 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
> sprs.mmcr1 = mfspr(SPRN_MMCR1);
> sprs.mmcr2 = mfspr(SPRN_MMCR2);
>
> - sprs.ptcr = mfspr(SPRN_PTCR);
> + if (!static_branch_unlikely(&is_ptcr_self_save))
> + sprs.ptcr = mfspr(SPRN_PTCR);
> sprs.rpr = mfspr(SPRN_RPR);
> sprs.tscr = mfspr(SPRN_TSCR);
> if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR))
> @@ -756,7 +797,8 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
> goto core_woken;
>
> /* Per-core SPRs */
> - mtspr(SPRN_PTCR, sprs.ptcr);
> + if (!static_branch_unlikely(&is_ptcr_self_save))
> + mtspr(SPRN_PTCR, sprs.ptcr);
> mtspr(SPRN_RPR, sprs.rpr);
> mtspr(SPRN_TSCR, sprs.tscr);
>
> @@ -777,7 +819,8 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
> atomic_unlock_and_stop_thread_idle();
>
> /* Per-thread SPRs */
> - mtspr(SPRN_LPCR, sprs.lpcr);
> + if (!static_branch_unlikely(&is_lpcr_self_save))
> + mtspr(SPRN_LPCR, sprs.lpcr);
> mtspr(SPRN_HFSCR, sprs.hfscr);
> mtspr(SPRN_FSCR, sprs.fscr);
> mtspr(SPRN_PID, sprs.pid);
> @@ -956,8 +999,10 @@ void pnv_program_cpu_hotplug_lpcr(unsigned int cpu, u64 lpcr_val)
> * Program the LPCR via stop-api only if the deepest stop state
> * can lose hypervisor context.
> */
> - if (supported_cpuidle_states & OPAL_PM_LOSE_FULL_CONTEXT)
> - opal_slw_set_reg(pir, SPRN_LPCR, lpcr_val);
> + if (supported_cpuidle_states & OPAL_PM_LOSE_FULL_CONTEXT) {
> + if (!static_branch_unlikely(&is_lpcr_self_save))
> + opal_slw_set_reg(pir, SPRN_LPCR, lpcr_val);
> + }
> }
>
> /*
> @@ -1298,6 +1343,8 @@ static int pnv_parse_cpuidle_dt(void)
> }
> for (i = 0; i < nr_idle_states; i++)
> pnv_idle_states[i].psscr_mask = temp_u64[i];
> + if (of_property_read_bool(np, "ibm,opal-self-save"))
> + static_branch_enable(&self_save_available);
> }
>
> /*
> diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c
> index 5cd0f52d258f..11e0ceb90de0 100644
> --- a/arch/powerpc/platforms/powernv/opal-call.c
> +++ b/arch/powerpc/platforms/powernv/opal-call.c
> @@ -223,6 +223,7 @@ OPAL_CALL(opal_handle_hmi, OPAL_HANDLE_HMI);
> OPAL_CALL(opal_handle_hmi2, OPAL_HANDLE_HMI2);
> OPAL_CALL(opal_config_cpu_idle_state, OPAL_CONFIG_CPU_IDLE_STATE);
> OPAL_CALL(opal_slw_set_reg, OPAL_SLW_SET_REG);
> +OPAL_CALL(opal_slw_self_save_reg, OPAL_SLW_SELF_SAVE_REG);
> OPAL_CALL(opal_register_dump_region, OPAL_REGISTER_DUMP_REGION);
> OPAL_CALL(opal_unregister_dump_region, OPAL_UNREGISTER_DUMP_REGION);
> OPAL_CALL(opal_pci_set_phb_cxl_mode, OPAL_PCI_SET_PHB_CAPI_MODE);
> --
> 2.17.1
>
^ permalink raw reply
* Re: [PATCH v8 3/3] Self save API integration
From: Gautham R Shenoy @ 2020-04-23 18:10 UTC (permalink / raw)
To: Pratik Rajesh Sampat
Cc: ego, pratik.r.sampat, linuxram, linux-kernel, linuxppc-dev,
oohall, skiboot
In-Reply-To: <20200423105438.29034-4-psampat@linux.ibm.com>
On Thu, Apr 23, 2020 at 04:24:38PM +0530, Pratik Rajesh Sampat wrote:
> The commit makes the self save API available outside the firmware by defining
> an OPAL wrapper.
> This wrapper has a similar interface to that of self restore and expects the
> cpu pir, SPR number, minus the value of that SPR to be passed in its
> paramters and returns OPAL_SUCCESS on success. It adds a device-tree
> node signifying support for self-save after verifying the stop API
> version compatibility.
>
> The commit also documents both the self-save and the self-restore API
> calls along with their working and usage.
>
> Signed-off-by: Pratik Rajesh Sampat <psampat@linux.ibm.com>
LGTM.
Reviewed-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
> ---
> doc/opal-api/opal-slw-self-save-reg-181.rst | 51 ++++++++++
> doc/opal-api/opal-slw-set-reg-100.rst | 5 +
> doc/power-management.rst | 48 +++++++++
> hw/slw.c | 106 ++++++++++++++++++++
> include/opal-api.h | 3 +-
> include/p9_stop_api.H | 18 ++++
> include/skiboot.h | 3 +
> 7 files changed, 233 insertions(+), 1 deletion(-)
> create mode 100644 doc/opal-api/opal-slw-self-save-reg-181.rst
>
> diff --git a/doc/opal-api/opal-slw-self-save-reg-181.rst b/doc/opal-api/opal-slw-self-save-reg-181.rst
> new file mode 100644
> index 00000000..f20e9b81
> --- /dev/null
> +++ b/doc/opal-api/opal-slw-self-save-reg-181.rst
> @@ -0,0 +1,51 @@
> +.. OPAL_SLW_SELF_SAVE_REG:
> +
> +OPAL_SLW_SELF_SAVE_REG
> +======================
> +
> +.. code-block:: c
> +
> + #define OPAL_SLW_SELF_SAVE_REG 181
> +
> + int64_t opal_slw_self_save_reg(uint64_t cpu_pir, uint64_t sprn);
> +
> +:ref:`OPAL_SLW_SELF_SAVE_REG` is used to inform low-level firmware to save
> +the current contents of the SPR before entering a state of loss and
> +also restore the content back on waking up from a deep stop state.
> +
> +An OPAL call `OPAL_SLW_SET_REG` exists which is similar in function as
> +saving and restoring the SPR, with one difference being that the value of the
> +SPR must also be supplied in the parameters.
> +Complete reference: doc/opal-api/opal-slw-set-reg-100.rst
> +
> +Parameters
> +----------
> +
> +``uint64_t cpu_pir``
> + This parameter specifies the pir of the cpu for which the call is being made.
> +``uint64_t sprn``
> + This parameter specifies the spr number as mentioned in p9_stop_api.H
> + The list of SPRs supported is as follows.
> + P9_STOP_SPR_DAWR,
> + P9_STOP_SPR_HSPRG0,
> + P9_STOP_SPR_LDBAR,
> + P9_STOP_SPR_LPCR,
> + P9_STOP_SPR_PSSCR,
> + P9_STOP_SPR_MSR,
> + P9_STOP_SPR_HRMOR,
> + P9_STOP_SPR_HMEER,
> + P9_STOP_SPR_PMCR,
> + P9_STOP_SPR_PTCR
> +
> + The property "ibm,opal-self-save" is supplied to the device tree to advterise
> + support.
> +
> +Returns
> +-------
> +
> +:ref:`OPAL_UNSUPPORTED`
> + If spr restore is not supported by pore engine.
> +:ref:`OPAL_PARAMETER`
> + Invalid handle for the pir/chip
> +:ref:`OPAL_SUCCESS`
> + On success
> diff --git a/doc/opal-api/opal-slw-set-reg-100.rst b/doc/opal-api/opal-slw-set-reg-100.rst
> index 2e8f1bd6..ee3e68ce 100644
> --- a/doc/opal-api/opal-slw-set-reg-100.rst
> +++ b/doc/opal-api/opal-slw-set-reg-100.rst
> @@ -21,6 +21,11 @@ In Power 9, it uses p9_stop_save_cpureg(), api provided by self restore code,
> to inform the spr with their corresponding values with which they
> must be restored.
>
> +An OPAL call `OPAL_SLW_SELF_SAVE_REG` exists which is similar in function
> +saving and restoring the SPR, with one difference being that the value of the
> +SPR doesn't need to be passed in the parameters, only with the SPR number
> +the firmware can identify, save and restore the values for the same.
> +Complete reference: doc/opal-api/opal-slw-self-save-reg-181.rst
>
> Parameters
> ----------
> diff --git a/doc/power-management.rst b/doc/power-management.rst
> index 76491a71..d6bd5358 100644
> --- a/doc/power-management.rst
> +++ b/doc/power-management.rst
> @@ -15,3 +15,51 @@ On boot, specific stop states can be disabled via setting a mask. For example,
> to disable all but stop 0,1,2, use ~0xE0000000. ::
>
> nvram -p ibm,skiboot --update-config opal-stop-state-disable-mask=0x1FFFFFFF
> +
> +Saving and restoring Special Purpose Registers(SPRs)
> +----------------------------------------------------
> +
> +When a CPU wakes up from a deep stop state which can result in
> +hypervisor state loss, all the SPRs are lost. The Linux Kernel expects
> +a small set of SPRs to contain an expected value when the CPU wakes up
> +from such a deep stop state. The microcode firmware provides the
> +following two APIs, collectively known as the stop-APIs, to allow the
> +kernel/OPAL to specify this set of SPRs and the value that they need
> +to be restored with on waking up from a deep stop state.
> +
> +Self-restore:
> +int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val);
> +The SPR number and the value of the that SPR must be restored with on
> +wakeup from the deep-stop state must be specified. When this call is
> +made, the microcode inserts instruction into the HOMER region to
> +restore the content of the SPR to the specified value on wakeup from a
> +deep-stop state. These instructions are executed by the CPU as soon as
> +it wakes up from a deep stop state. The call is to be made once per
> +SPR.
> +
> +Self-Save:
> +int64_t opal_slw_self_save_reg(uint64_t cpu_pir, uint64_t sprn);
> +Only the SPR number needs to be specified. When this call is made, the
> +microcode inserts instructions into the HOMER region to save the
> +current value of the SPR before the CPU goes to a deep stop state, and
> +restores the value back when the CPU wakes up from a deep stop state.
> +These instructions are correspondingly executed just before and after
> +the CPU goes/comes out of a deep stop state. This call can be made
> +once per SPR.
> +
> +The key difference between self-save and self-restore is the
> +use-case. If the Kernel expects the SPR to contain a particular value
> +on waking up from a deep-stop state, that wasn't the value of that SPR
> +before entering deep stop-state, then self-restore is preferable.
> +Also in a case where SPR does not change across the lifetime
> +self-restore is more efficient as when the value is same the memeory location
> +is not updated.
> +
> +When deep stop states are to be supported in an Ultravisor
> +environment, since HOMER is in a secure region, the stop-api cannot
> +update the HOMER if invoked from a context when the OPAL/Kernel is
> +executing without the ultravisor privilege. In this scenario, at the
> +time of early OPAL boot, while OPAL has ultravisor privileges, it can
> +make the self-save stop-api call for all the supported SPRs, so that
> +the microcode in the HOMER will always save and restore all the
> +supported SPRs during entry/exit from a deep stop state.
> diff --git a/hw/slw.c b/hw/slw.c
> index beb129a8..8423eeaf 100644
> --- a/hw/slw.c
> +++ b/hw/slw.c
> @@ -35,6 +35,43 @@ static bool slw_current_le = false;
> enum wakeup_engine_states wakeup_engine_state = WAKEUP_ENGINE_NOT_PRESENT;
> bool has_deep_states = false;
>
> +/**
> + * The struct and SPR list is partially consistent with libpore/p9_stop_api.c
> + */
> +/**
> + * @brief summarizes attributes associated with a SPR register.
> + */
> +typedef struct
> +{
> + uint32_t iv_sprId;
> + bool iv_isThreadScope;
> + uint32_t iv_saveMaskPos;
> +
> +} StopSprReg_t;
> +
> +/**
> + * @brief a true in the table below means register is of scope thread
> + * whereas a false meanse register is of scope core.
> + * The number is the bit position on a uint32_t mask
> + */
> +
> +static const StopSprReg_t g_sprRegister[] =
> +{
> + { P9_STOP_SPR_DAWR, true, 1 },
> + { P9_STOP_SPR_HSPRG0, true, 3 },
> + { P9_STOP_SPR_LDBAR, true, 4, },
> + { P9_STOP_SPR_LPCR, true, 5 },
> + { P9_STOP_SPR_PSSCR, true, 6 },
> + { P9_STOP_SPR_MSR, true, 7 },
> + { P9_STOP_SPR_HRMOR, false, 255 },
> + { P9_STOP_SPR_HID, false, 21 },
> + { P9_STOP_SPR_HMEER, false, 22 },
> + { P9_STOP_SPR_PMCR, false, 23 },
> + { P9_STOP_SPR_PTCR, false, 24 },
> +};
> +
> +static const uint32_t MAX_SPR_SUPPORTED = ARRAY_SIZE(g_sprRegister);
> +
> DEFINE_LOG_ENTRY(OPAL_RC_SLW_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_SLW,
> OPAL_PLATFORM_FIRMWARE, OPAL_PREDICTIVE_ERR_GENERAL,
> OPAL_NA);
> @@ -720,11 +757,14 @@ void add_cpu_idle_state_properties(void)
> struct cpu_idle_states *states;
> struct proc_chip *chip;
> int nr_states;
> + int rc;
>
> bool can_sleep = true;
> bool has_stop_inst = false;
> + bool has_self_save = true;
> u8 i;
>
> + u64 compVector = -1;
> fdt64_t *pm_ctrl_reg_val_buf;
> fdt64_t *pm_ctrl_reg_mask_buf;
> u32 supported_states_mask;
> @@ -766,6 +806,20 @@ void add_cpu_idle_state_properties(void)
> */
> chip = next_chip(NULL);
> assert(chip);
> + rc = proc_stop_api_discover_capability((void *) chip->homer_base,
> + &compVector);
> + if (rc == STOP_SAVE_ARG_INVALID_IMG) {
> + prlog(PR_DEBUG, "HOMER BASE INVALID\n");
> + return;
> + } else if (rc == STOP_SAVE_API_IMG_INCOMPATIBLE) {
> + prlog(PR_DEBUG, "STOP API running incompatible versions\n");
> + if ((compVector & SELF_RESTORE_VER_MISMATCH) == 0) {
> + prlog(PR_DEBUG, "Self-save API unsupported\n");
> + has_self_save = false;
> + }
> + }
> + if (has_self_save)
> + dt_add_property(power_mgt, "ibm,opal-self-save", NULL, 0);
> if (chip->type == PROC_CHIP_P9_NIMBUS ||
> chip->type == PROC_CHIP_P9_CUMULUS ||
> chip->type == PROC_CHIP_P9P) {
> @@ -1446,6 +1500,58 @@ int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val)
>
> opal_call(OPAL_SLW_SET_REG, opal_slw_set_reg, 3);
>
> +int64_t opal_slw_self_save_reg(uint64_t cpu_pir, uint64_t sprn)
> +{
> + struct cpu_thread * c = find_cpu_by_pir(cpu_pir);
> + uint32_t save_reg_vector = 0;
> + struct proc_chip * chip;
> + int rc;
> + int index;
> +
> + if (!c) {
> + prlog(PR_DEBUG, "SLW: Unknown thread with pir %x\n",
> + (u32) cpu_pir);
> + return OPAL_PARAMETER;
> + }
> +
> + chip = get_chip(c->chip_id);
> + if (!chip) {
> + prlog(PR_DEBUG, "SLW: Unknown chip for thread with pir %x\n",
> + (u32) cpu_pir);
> + return OPAL_PARAMETER;
> + }
> + if (proc_gen != proc_gen_p9 || !has_deep_states) {
> + prlog(PR_DEBUG, "SLW: Self-save feature unsupported\n");
> + return OPAL_UNSUPPORTED;
> + }
> + if (wakeup_engine_state != WAKEUP_ENGINE_PRESENT) {
> + log_simple_error(&e_info(OPAL_RC_SLW_REG),
> + "SLW: wakeup_engine in bad state=%d chip=%x\n",
> + wakeup_engine_state, chip->id);
> + return OPAL_INTERNAL_ERROR;
> + }
> + for (index = 0; index < MAX_SPR_SUPPORTED; ++index) {
> + if (sprn == (CpuReg_t) g_sprRegister[index].iv_sprId) {
> + save_reg_vector = PPC_BIT32(
> + g_sprRegister[index].iv_saveMaskPos);
> + break;
> + }
> + }
> + if (save_reg_vector == 0)
> + return OPAL_INTERNAL_ERROR;
> + rc = p9_stop_save_cpureg_control((void *) chip->homer_base,
> + cpu_pir, save_reg_vector);
> +
> + if (rc) {
> + log_simple_error(&e_info(OPAL_RC_SLW_REG),
> + "SLW: Failed to save vector %x for CPU %x\n",
> + save_reg_vector, c->pir);
> + return OPAL_INTERNAL_ERROR;
> + }
> + return OPAL_SUCCESS;
> +}
> +opal_call(OPAL_SLW_SELF_SAVE_REG, opal_slw_self_save_reg, 2);
> +
> void slw_init(void)
> {
> struct proc_chip *chip;
> diff --git a/include/opal-api.h b/include/opal-api.h
> index e90cab1e..1607a89b 100644
> --- a/include/opal-api.h
> +++ b/include/opal-api.h
> @@ -227,7 +227,8 @@
> #define OPAL_SECVAR_ENQUEUE_UPDATE 178
> #define OPAL_PHB_SET_OPTION 179
> #define OPAL_PHB_GET_OPTION 180
> -#define OPAL_LAST 180
> +#define OPAL_SLW_SELF_SAVE_REG 181
> +#define OPAL_LAST 181
>
> #define QUIESCE_HOLD 1 /* Spin all calls at entry */
> #define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
> diff --git a/include/p9_stop_api.H b/include/p9_stop_api.H
> index cb5ffd6f..09ce3dc1 100644
> --- a/include/p9_stop_api.H
> +++ b/include/p9_stop_api.H
> @@ -34,6 +34,8 @@
> ///
> /// @file p9_stop_api.H
> /// @brief describes STOP API which create/manipulate STOP image.
> +/// This header need not be consistent, however is a subset of the
> +/// libpore/p9_stop_api.H counterpart
> ///
> // *HWP HW Owner : Greg Still <stillgs@us.ibm.com>
> // *HWP FW Owner : Prem Shanker Jha <premjha2@in.ibm.com>
> @@ -58,6 +60,7 @@ typedef enum
> P9_STOP_SPR_HRMOR = 313, // core register
> P9_STOP_SPR_LPCR = 318, // thread register
> P9_STOP_SPR_HMEER = 337, // core register
> + P9_STOP_SPR_PTCR = 464, // core register
> P9_STOP_SPR_LDBAR = 850, // thread register
> P9_STOP_SPR_PSSCR = 855, // thread register
> P9_STOP_SPR_PMCR = 884, // core register
> @@ -247,6 +250,21 @@ StopReturnCode_t p9_stop_save_scom( void* const i_pImage,
> const ScomOperation_t i_operation,
> const ScomSection_t i_section );
>
> +/**
> + * @brief Facilitates self save and restore of a list of SPRs of a thread.
> + * @param[in] i_pImage points to the start of HOMER image of P9 chip.
> + * @param[in] i_pir PIR associated with thread
> + * @param[in] i_saveRegVector bit vector representing SPRs that needs to be restored.
> + * @return STOP_SAVE_SUCCESS if API succeeds, error code otherwise.
> + * @note SPR save vector is a bit vector. For each SPR supported,
> + * there is an associated bit position in the bit vector.Refer
> + * to definition of SprBitPositionList_t to determine bit position
> + * associated with a particular SPR.
> + */
> +StopReturnCode_t
> +p9_stop_save_cpureg_control( void* i_pImage, const uint64_t i_pir,
> + const uint32_t i_saveRegVector );
> +
> /**
> * @brief verifies if API is compatible of current HOMER image.
> * @param[in] i_pImage points to the start of HOMER image of P9 chip.
> diff --git a/include/skiboot.h b/include/skiboot.h
> index 30ff500c..9ced240e 100644
> --- a/include/skiboot.h
> +++ b/include/skiboot.h
> @@ -306,6 +306,9 @@ extern void nx_p9_rng_late_init(void);
> /* SLW reinit function for switching core settings */
> extern int64_t slw_reinit(uint64_t flags);
>
> +/* Self save SPR before entering the stop state */
> +extern int64_t opal_slw_self_save_reg(uint64_t cpu_pir, uint64_t sprn);
> +
> /* Patch SPR in SLW image */
> extern int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val);
>
> --
> 2.25.1
>
^ permalink raw reply
* Re: [musl] Powerpc Linux 'scv' system call ABI proposal take 2
From: Rich Felker @ 2020-04-23 17:42 UTC (permalink / raw)
To: Adhemerval Zanella
Cc: libc-dev, libc-alpha, linuxppc-dev, Nicholas Piggin, musl
In-Reply-To: <64d82a23-1f6e-2e6a-b7a9-0eeab8a53435@linaro.org>
On Thu, Apr 23, 2020 at 02:15:58PM -0300, Adhemerval Zanella wrote:
>
>
> On 23/04/2020 13:43, Rich Felker wrote:
> > On Thu, Apr 23, 2020 at 01:35:01PM -0300, Adhemerval Zanella wrote:
> >>
> >>
> >> On 23/04/2020 13:18, Rich Felker wrote:
> >>> On Thu, Apr 23, 2020 at 09:13:57AM -0300, Adhemerval Zanella wrote:
> >>>>
> >>>>
> >>>> On 22/04/2020 23:36, Rich Felker wrote:
> >>>>> On Wed, Apr 22, 2020 at 04:18:36PM +1000, Nicholas Piggin wrote:
> >>>>>> Yeah I had a bit of a play around with musl (which is very nice code I
> >>>>>> must say). The powerpc64 syscall asm is missing ctr clobber by the way.
> >>>>>> Fortunately adding it doesn't change code generation for me, but it
> >>>>>> should be fixed. glibc had the same bug at one point I think (probably
> >>>>>> due to syscall ABI documentation not existing -- something now lives in
> >>>>>> linux/Documentation/powerpc/syscall64-abi.rst).
> >>>>>
> >>>>> Do you know anywhere I can read about the ctr issue, possibly the
> >>>>> relevant glibc bug report? I'm not particularly familiar with ppc
> >>>>> register file (at least I have to refamiliarize myself every time I
> >>>>> work on this stuff) so it'd be nice to understand what's
> >>>>> potentially-wrong now.
> >>>>
> >>>> My understanding is the ctr issue only happens for vDSO calls where it
> >>>> fallback to a syscall in case an error (invalid argument, etc. and
> >>>> assuming if vDSO does not fallback to a syscall it always succeed).
> >>>> This makes the vDSO call on powerpc to have same same ABI constraint
> >>>> as a syscall, where it clobbers CR0.
> >>>
> >>> I think you mean "vsyscall", the old thing glibc used where there are
> >>> in-userspace implementations of some syscalls with call interfaces
> >>> roughly equivalent to a syscall. musl has never used this. It only
> >>> uses the actual exported functions from the vdso which have normal
> >>> external function call ABI.
> >>
> >> I wasn't thinking in vsyscall in fact, which afaik it is a x86 thing.
> >> The issue is indeed when calling the powerpc provided functions in
> >> vDSO, which musl might want to do eventually.
> >
> > AIUI (at least this is true for all other archs) the functions have
> > normal external function call ABI and calling them has nothing to do
> > with syscall mechanisms.
>
> My point is powerpc specifically does not follow it, since it issues a
> syscall in fallback and its semantic follow kernel syscalls (error
> signalled in cr0, r3 being always a positive value):
Oh, then I think we'll just ignore these unless the kernel can make
ones with a reasonable ABI. It's not worth having ppc-specific code
for this... It would be really nice if ones that actually behave like
functions could be added though.
> --
> V_FUNCTION_BEGIN(__kernel_clock_gettime)
> .cfi_startproc
> [...]
> /*
> * syscall fallback
> */
> 99:
> li r0,__NR_clock_gettime
> .cfi_restore lr
> sc
> blr
> .cfi_endproc
> V_FUNCTION_END(__kernel_clock_gettime)
>
>
> >
> > It looks like we're not using them right now and I'm not sure why. It
> > could be that there are ABI mismatch issues (are 32-bit ones
> > compatible with secure-plt? are 64-bit ones compatible with ELFv2?) or
> > just that nobody proposed adding them. Also as of 5.4 32-bit ppc
> > lacked time64 versions of them; not sure if this is fixed yet.
>
> For 64-bit it also have an issue where vDSO does not provide an OPD
> for ELFv1, which has bitten glibc while trying to implement an ifunc
> optimization. I don't recall any issue for ELFv2.
>
> For 32-bit I am not sure secure-plt will change anything, at least not
> on powerpc where we use the same strategy for 64-bit and use a
> mtctr/bctr directly.
Indeed, I don't think there's a secure-plt distinction unless you're
making outgoing calls to possibly-cross-DSO functions.
Rich
^ permalink raw reply
* Re: [musl] Powerpc Linux 'scv' system call ABI proposal take 2
From: Adhemerval Zanella @ 2020-04-23 17:15 UTC (permalink / raw)
To: Rich Felker; +Cc: libc-dev, libc-alpha, linuxppc-dev, Nicholas Piggin, musl
In-Reply-To: <20200423164314.GX11469@brightrain.aerifal.cx>
On 23/04/2020 13:43, Rich Felker wrote:
> On Thu, Apr 23, 2020 at 01:35:01PM -0300, Adhemerval Zanella wrote:
>>
>>
>> On 23/04/2020 13:18, Rich Felker wrote:
>>> On Thu, Apr 23, 2020 at 09:13:57AM -0300, Adhemerval Zanella wrote:
>>>>
>>>>
>>>> On 22/04/2020 23:36, Rich Felker wrote:
>>>>> On Wed, Apr 22, 2020 at 04:18:36PM +1000, Nicholas Piggin wrote:
>>>>>> Yeah I had a bit of a play around with musl (which is very nice code I
>>>>>> must say). The powerpc64 syscall asm is missing ctr clobber by the way.
>>>>>> Fortunately adding it doesn't change code generation for me, but it
>>>>>> should be fixed. glibc had the same bug at one point I think (probably
>>>>>> due to syscall ABI documentation not existing -- something now lives in
>>>>>> linux/Documentation/powerpc/syscall64-abi.rst).
>>>>>
>>>>> Do you know anywhere I can read about the ctr issue, possibly the
>>>>> relevant glibc bug report? I'm not particularly familiar with ppc
>>>>> register file (at least I have to refamiliarize myself every time I
>>>>> work on this stuff) so it'd be nice to understand what's
>>>>> potentially-wrong now.
>>>>
>>>> My understanding is the ctr issue only happens for vDSO calls where it
>>>> fallback to a syscall in case an error (invalid argument, etc. and
>>>> assuming if vDSO does not fallback to a syscall it always succeed).
>>>> This makes the vDSO call on powerpc to have same same ABI constraint
>>>> as a syscall, where it clobbers CR0.
>>>
>>> I think you mean "vsyscall", the old thing glibc used where there are
>>> in-userspace implementations of some syscalls with call interfaces
>>> roughly equivalent to a syscall. musl has never used this. It only
>>> uses the actual exported functions from the vdso which have normal
>>> external function call ABI.
>>
>> I wasn't thinking in vsyscall in fact, which afaik it is a x86 thing.
>> The issue is indeed when calling the powerpc provided functions in
>> vDSO, which musl might want to do eventually.
>
> AIUI (at least this is true for all other archs) the functions have
> normal external function call ABI and calling them has nothing to do
> with syscall mechanisms.
My point is powerpc specifically does not follow it, since it issues a
syscall in fallback and its semantic follow kernel syscalls (error
signalled in cr0, r3 being always a positive value):
--
V_FUNCTION_BEGIN(__kernel_clock_gettime)
.cfi_startproc
[...]
/*
* syscall fallback
*/
99:
li r0,__NR_clock_gettime
.cfi_restore lr
sc
blr
.cfi_endproc
V_FUNCTION_END(__kernel_clock_gettime)
>
> It looks like we're not using them right now and I'm not sure why. It
> could be that there are ABI mismatch issues (are 32-bit ones
> compatible with secure-plt? are 64-bit ones compatible with ELFv2?) or
> just that nobody proposed adding them. Also as of 5.4 32-bit ppc
> lacked time64 versions of them; not sure if this is fixed yet.
For 64-bit it also have an issue where vDSO does not provide an OPD
for ELFv1, which has bitten glibc while trying to implement an ifunc
optimization. I don't recall any issue for ELFv2.
For 32-bit I am not sure secure-plt will change anything, at least not
on powerpc where we use the same strategy for 64-bit and use a
mtctr/bctr directly.
^ permalink raw reply
* Re: [musl] Powerpc Linux 'scv' system call ABI proposal take 2
From: Rich Felker @ 2020-04-23 16:43 UTC (permalink / raw)
To: Adhemerval Zanella
Cc: libc-dev, libc-alpha, linuxppc-dev, Nicholas Piggin, musl
In-Reply-To: <3fe73604-7c92-e073-cbe7-abb4a8ae7c1a@linaro.org>
On Thu, Apr 23, 2020 at 01:35:01PM -0300, Adhemerval Zanella wrote:
>
>
> On 23/04/2020 13:18, Rich Felker wrote:
> > On Thu, Apr 23, 2020 at 09:13:57AM -0300, Adhemerval Zanella wrote:
> >>
> >>
> >> On 22/04/2020 23:36, Rich Felker wrote:
> >>> On Wed, Apr 22, 2020 at 04:18:36PM +1000, Nicholas Piggin wrote:
> >>>> Yeah I had a bit of a play around with musl (which is very nice code I
> >>>> must say). The powerpc64 syscall asm is missing ctr clobber by the way.
> >>>> Fortunately adding it doesn't change code generation for me, but it
> >>>> should be fixed. glibc had the same bug at one point I think (probably
> >>>> due to syscall ABI documentation not existing -- something now lives in
> >>>> linux/Documentation/powerpc/syscall64-abi.rst).
> >>>
> >>> Do you know anywhere I can read about the ctr issue, possibly the
> >>> relevant glibc bug report? I'm not particularly familiar with ppc
> >>> register file (at least I have to refamiliarize myself every time I
> >>> work on this stuff) so it'd be nice to understand what's
> >>> potentially-wrong now.
> >>
> >> My understanding is the ctr issue only happens for vDSO calls where it
> >> fallback to a syscall in case an error (invalid argument, etc. and
> >> assuming if vDSO does not fallback to a syscall it always succeed).
> >> This makes the vDSO call on powerpc to have same same ABI constraint
> >> as a syscall, where it clobbers CR0.
> >
> > I think you mean "vsyscall", the old thing glibc used where there are
> > in-userspace implementations of some syscalls with call interfaces
> > roughly equivalent to a syscall. musl has never used this. It only
> > uses the actual exported functions from the vdso which have normal
> > external function call ABI.
>
> I wasn't thinking in vsyscall in fact, which afaik it is a x86 thing.
> The issue is indeed when calling the powerpc provided functions in
> vDSO, which musl might want to do eventually.
AIUI (at least this is true for all other archs) the functions have
normal external function call ABI and calling them has nothing to do
with syscall mechanisms.
It looks like we're not using them right now and I'm not sure why. It
could be that there are ABI mismatch issues (are 32-bit ones
compatible with secure-plt? are 64-bit ones compatible with ELFv2?) or
just that nobody proposed adding them. Also as of 5.4 32-bit ppc
lacked time64 versions of them; not sure if this is fixed yet.
Rich
^ permalink raw reply
* Re: [PATCH] lib/mpi: Fix building for powerpc with clang
From: Nathan Chancellor @ 2020-04-23 16:36 UTC (permalink / raw)
To: Herbert Xu
Cc: kbuild test robot, linux-kernel, clang-built-linux,
Paul Mackerras, linux-crypto, linuxppc-dev
In-Reply-To: <20200414135731.GA8766@gondor.apana.org.au>
On Tue, Apr 14, 2020 at 11:57:31PM +1000, Herbert Xu wrote:
> On Mon, Apr 13, 2020 at 12:50:42PM -0700, Nathan Chancellor wrote:
> > 0day reports over and over on an powerpc randconfig with clang:
> >
> > lib/mpi/generic_mpih-mul1.c:37:13: error: invalid use of a cast in a
> > inline asm context requiring an l-value: remove the cast or build with
> > -fheinous-gnu-extensions
> >
> > Remove the superfluous casts, which have been done previously for x86
> > and arm32 in commit dea632cadd12 ("lib/mpi: fix build with clang") and
> > commit 7b7c1df2883d ("lib/mpi/longlong.h: fix building with 32-bit
> > x86").
> >
> > Reported-by: kbuild test robot <lkp@intel.com>
> > Link: https://github.com/ClangBuiltLinux/linux/issues/991
> > Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
>
> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
> --
> Email: Herbert Xu <herbert@gondor.apana.org.au>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Might be better for you to take this instead. 0day just tripped over
this again.
Cheers,
Nathan
^ permalink raw reply
* Re: [musl] Powerpc Linux 'scv' system call ABI proposal take 2
From: Adhemerval Zanella @ 2020-04-23 16:35 UTC (permalink / raw)
To: Rich Felker; +Cc: libc-dev, libc-alpha, linuxppc-dev, Nicholas Piggin, musl
In-Reply-To: <20200423161841.GU11469@brightrain.aerifal.cx>
On 23/04/2020 13:18, Rich Felker wrote:
> On Thu, Apr 23, 2020 at 09:13:57AM -0300, Adhemerval Zanella wrote:
>>
>>
>> On 22/04/2020 23:36, Rich Felker wrote:
>>> On Wed, Apr 22, 2020 at 04:18:36PM +1000, Nicholas Piggin wrote:
>>>> Yeah I had a bit of a play around with musl (which is very nice code I
>>>> must say). The powerpc64 syscall asm is missing ctr clobber by the way.
>>>> Fortunately adding it doesn't change code generation for me, but it
>>>> should be fixed. glibc had the same bug at one point I think (probably
>>>> due to syscall ABI documentation not existing -- something now lives in
>>>> linux/Documentation/powerpc/syscall64-abi.rst).
>>>
>>> Do you know anywhere I can read about the ctr issue, possibly the
>>> relevant glibc bug report? I'm not particularly familiar with ppc
>>> register file (at least I have to refamiliarize myself every time I
>>> work on this stuff) so it'd be nice to understand what's
>>> potentially-wrong now.
>>
>> My understanding is the ctr issue only happens for vDSO calls where it
>> fallback to a syscall in case an error (invalid argument, etc. and
>> assuming if vDSO does not fallback to a syscall it always succeed).
>> This makes the vDSO call on powerpc to have same same ABI constraint
>> as a syscall, where it clobbers CR0.
>
> I think you mean "vsyscall", the old thing glibc used where there are
> in-userspace implementations of some syscalls with call interfaces
> roughly equivalent to a syscall. musl has never used this. It only
> uses the actual exported functions from the vdso which have normal
> external function call ABI.
I wasn't thinking in vsyscall in fact, which afaik it is a x86 thing.
The issue is indeed when calling the powerpc provided functions in
vDSO, which musl might want to do eventually.
^ permalink raw reply
* Re: [musl] Powerpc Linux 'scv' system call ABI proposal take 2
From: Rich Felker @ 2020-04-23 16:18 UTC (permalink / raw)
To: Adhemerval Zanella
Cc: libc-dev, libc-alpha, linuxppc-dev, Nicholas Piggin, musl
In-Reply-To: <a972a0e4-25bd-9cf5-75ec-2eb993ef1b6a@linaro.org>
On Thu, Apr 23, 2020 at 09:13:57AM -0300, Adhemerval Zanella wrote:
>
>
> On 22/04/2020 23:36, Rich Felker wrote:
> > On Wed, Apr 22, 2020 at 04:18:36PM +1000, Nicholas Piggin wrote:
> >> Yeah I had a bit of a play around with musl (which is very nice code I
> >> must say). The powerpc64 syscall asm is missing ctr clobber by the way.
> >> Fortunately adding it doesn't change code generation for me, but it
> >> should be fixed. glibc had the same bug at one point I think (probably
> >> due to syscall ABI documentation not existing -- something now lives in
> >> linux/Documentation/powerpc/syscall64-abi.rst).
> >
> > Do you know anywhere I can read about the ctr issue, possibly the
> > relevant glibc bug report? I'm not particularly familiar with ppc
> > register file (at least I have to refamiliarize myself every time I
> > work on this stuff) so it'd be nice to understand what's
> > potentially-wrong now.
>
> My understanding is the ctr issue only happens for vDSO calls where it
> fallback to a syscall in case an error (invalid argument, etc. and
> assuming if vDSO does not fallback to a syscall it always succeed).
> This makes the vDSO call on powerpc to have same same ABI constraint
> as a syscall, where it clobbers CR0.
I think you mean "vsyscall", the old thing glibc used where there are
in-userspace implementations of some syscalls with call interfaces
roughly equivalent to a syscall. musl has never used this. It only
uses the actual exported functions from the vdso which have normal
external function call ABI.
Rich
^ permalink raw reply
* Re: [PATCH 1/3] powerpc: Properly return error code from do_patch_instruction()
From: Christophe Leroy @ 2020-04-23 16:21 UTC (permalink / raw)
To: Naveen N. Rao, linuxppc-dev; +Cc: Steven Rostedt
In-Reply-To: <b1dbbb34a389a6f59eb6c99102d94c0070ddaf98.1587654213.git.naveen.n.rao@linux.vnet.ibm.com>
Le 23/04/2020 à 17:09, Naveen N. Rao a écrit :
> With STRICT_KERNEL_RWX, we are currently ignoring return value from
> __patch_instruction() in do_patch_instruction(), resulting in the error
> not being propagated back. Fix the same.
Good patch.
Be aware that there is ongoing work which tend to wanting to replace
error reporting by BUG_ON() . See
https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=166003
>
> Fixes: 37bc3e5fd764f ("powerpc/lib/code-patching: Use alternate map for patch_instruction()")
> Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
> ---
> arch/powerpc/lib/code-patching.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
> index 3345f039a876..5c713a6c0bd8 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -138,7 +138,7 @@ static inline int unmap_patch_area(unsigned long addr)
>
> static int do_patch_instruction(unsigned int *addr, unsigned int instr)
> {
> - int err;
> + int err, rc = 0;
> unsigned int *patch_addr = NULL;
> unsigned long flags;
> unsigned long text_poke_addr;
> @@ -163,7 +163,7 @@ static int do_patch_instruction(unsigned int *addr, unsigned int instr)
> patch_addr = (unsigned int *)(text_poke_addr) +
> ((kaddr & ~PAGE_MASK) / sizeof(unsigned int));
>
> - __patch_instruction(addr, instr, patch_addr);
> + rc = __patch_instruction(addr, instr, patch_addr);
>
> err = unmap_patch_area(text_poke_addr);
> if (err)
> @@ -172,7 +172,7 @@ static int do_patch_instruction(unsigned int *addr, unsigned int instr)
> out:
> local_irq_restore(flags);
>
> - return err;
> + return rc ? rc : err;
That's not really consistent. __patch_instruction() and
unmap_patch_area() return a valid minus errno, while in case of
map_patch_area() failure, err has value -1
> }
> #else /* !CONFIG_STRICT_KERNEL_RWX */
>
>
Christophe
^ permalink raw reply
* Re: [PATCH 2/3] powerpc/ftrace: Simplify error checking when patching instructions
From: Christophe Leroy @ 2020-04-23 15:44 UTC (permalink / raw)
To: Naveen N. Rao, linuxppc-dev; +Cc: Steven Rostedt
In-Reply-To: <872c5c3d9cf6db8e52b2abcdd16d7ab61fce8070.1587654213.git.naveen.n.rao@linux.vnet.ibm.com>
Le 23/04/2020 à 17:09, Naveen N. Rao a écrit :
> Introduce a macro PATCH_INSN() to simplify instruction patching, and to
> make the error messages more uniform and useful:
> - print an error message that includes the original return value
> - print the function name and line numbers, so that the offending
> location is clear
> - always return -EPERM, which ftrace_bug() expects for proper error
> handling
>
> Also eliminate use of patch_branch() since most such uses already call
> create_branch() for error checking before patching. Instead, use the
> return value from create_branch() with PATCH_INSN().
I have the same comment here as for patch 3, this kind of macro hides
the return action and can be dangerous.
What about implementing a macro that takes an explicit label as third
argument and jump to that label in case of error ? On the same model as
unsafe_put_user() ?
Christophe
^ permalink raw reply
* Re: [PATCH 3/3] powerpc/kprobes: Check return value of patch_instruction()
From: Christophe Leroy @ 2020-04-23 15:41 UTC (permalink / raw)
To: Naveen N. Rao, linuxppc-dev; +Cc: Steven Rostedt
In-Reply-To: <3a132ac385340244b8d74179ac7bbbda7bf1f503.1587654213.git.naveen.n.rao@linux.vnet.ibm.com>
Le 23/04/2020 à 17:09, Naveen N. Rao a écrit :
> patch_instruction() can fail in some scenarios. Add appropriate error
> checking so that such failures are caught and logged, and suitable error
> code is returned.
>
> Fixes: d07df82c43be8 ("powerpc/kprobes: Move kprobes over to patch_instruction()")
> Fixes: f3eca95638931 ("powerpc/kprobes/optprobes: Use patch_instruction()")
> Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
> ---
> arch/powerpc/kernel/kprobes.c | 10 +++-
> arch/powerpc/kernel/optprobes.c | 99 ++++++++++++++++++++++++++-------
> 2 files changed, 87 insertions(+), 22 deletions(-)
>
> diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
> index 81efb605113e..4a297ae2bd87 100644
> --- a/arch/powerpc/kernel/kprobes.c
> +++ b/arch/powerpc/kernel/kprobes.c
> @@ -138,13 +138,19 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
>
> void arch_arm_kprobe(struct kprobe *p)
> {
> - patch_instruction(p->addr, BREAKPOINT_INSTRUCTION);
> + int rc = patch_instruction(p->addr, BREAKPOINT_INSTRUCTION);
> +
> + if (rc)
> + WARN("Failed to patch trap at 0x%pK: %d\n", (void *)p->addr, rc);
> }
> NOKPROBE_SYMBOL(arch_arm_kprobe);
>
> void arch_disarm_kprobe(struct kprobe *p)
> {
> - patch_instruction(p->addr, p->opcode);
> + int rc = patch_instruction(p->addr, p->opcode);
> +
> + if (rc)
> + WARN("Failed to remove trap at 0x%pK: %d\n", (void *)p->addr, rc);
> }
> NOKPROBE_SYMBOL(arch_disarm_kprobe);
>
> diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
> index 024f7aad1952..046485bb0a52 100644
> --- a/arch/powerpc/kernel/optprobes.c
> +++ b/arch/powerpc/kernel/optprobes.c
> @@ -139,52 +139,67 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op)
> }
> }
>
> +#define PATCH_INSN(addr, instr) \
> +do { \
> + int rc = patch_instruction((unsigned int *)(addr), instr); \
> + if (rc) { \
> + pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \
> + __func__, __LINE__, \
> + (void *)(addr), (void *)(addr), rc); \
> + return rc; \
> + } \
> +} while (0)
> +
I hate this kind of macro which hides the "return".
What about keeping the return action in the caller ?
Otherwise, what about implementing something based on the use of goto,
on the same model as unsafe_put_user() for instance ?
Christophe
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox