linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Nathan Lynch <nathanl@linux.ibm.com>
To: linuxppc-dev@lists.ozlabs.org
Cc: tyreld@linux.ibm.com, ajd@linux.ibm.com, aik@ozlabs.ru,
	aneesh.kumar@linux.ibm.com, brking@linux.ibm.com
Subject: [PATCH 6/6] powerpc/rtas: constrain user region allocation to RMA
Date: Thu, 14 Jan 2021 16:00:04 -0600	[thread overview]
Message-ID: <20210114220004.1138993-7-nathanl@linux.ibm.com> (raw)
In-Reply-To: <20210114220004.1138993-1-nathanl@linux.ibm.com>

Memory locations passed as arguments from the OS to RTAS usually need
to be addressable in 32-bit mode and must reside in the Real Mode
Area. On PAPR guests, the RMA starts at logical address 0 and is the
first logical memory block reported in the LPAR’s device tree.

On powerpc targets with RTAS, Linux makes available to user space a
region of memory suitable for arguments to be passed to RTAS via
sys_rtas(). This region (rtas_rmo_buf) is allocated via the memblock
API during boot in order to ensure that it satisfies the requirements
described above.

With radix MMU, the upper limit supplied to the memblock allocation
can exceed the bounds of the first logical memory block, since
ppc64_rma_size is ULONG_MAX and RTAS_INSTANTIATE_MAX is 1GB. (512MB is
a common size of the first memory block according to a small sample of
LPARs I have checked.) This leads to failures when user space invokes
an RTAS function that uses a work area, such as
ibm,configure-connector.

Alter the determination of the upper limit for rtas_rmo_buf's
allocation to consult the device tree directly, ensuring placement
within the RMA regardless of the MMU in use.

Signed-off-by: Nathan Lynch <nathanl@linux.ibm.com>
---
 arch/powerpc/kernel/rtas.c | 80 +++++++++++++++++++++++++++++++-------
 1 file changed, 65 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index da65faadbbb2..98dfb112f4df 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -1166,6 +1166,70 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
 	return 0;
 }
 
+/*
+ * Memory locations passed to RTAS must be in the RMA as described by
+ * the range in /memory@0.
+ */
+static phys_addr_t rtas_arg_addr_limit(void)
+{
+	unsigned int addr_cells;
+	unsigned int size_cells;
+	struct device_node *np;
+	const __be32 *prop;
+	u64 limit;
+	u64 base;
+
+	/* RTAS is instantiated in 32-bit mode. */
+	limit = 1ULL << 32;
+
+	/* Account for mem=. */
+	if (memory_limit != 0)
+		limit = min(limit, memory_limit);
+
+	np = of_find_node_by_path("/memory@0");
+	if (!np)
+		goto out;
+
+	prop = of_get_property(np, "reg", NULL);
+	if (!prop)
+		goto put;
+
+	addr_cells = of_n_addr_cells(np);
+	base = of_read_number(prop, addr_cells);
+	prop += addr_cells;
+	size_cells = of_n_size_cells(np);
+	limit = min(limit, of_read_number(prop, size_cells));
+put:
+	of_node_put(np);
+out:
+	pr_debug("%s: base = %#llx limit = %#llx", __func__, base, limit);
+
+	return limit;
+}
+
+static void __init rtas_user_region_setup(void)
+{
+	phys_addr_t limit, align, size;
+
+	limit = rtas_arg_addr_limit();
+	size = RTAS_USER_REGION_SIZE;
+
+	/*
+	 * Although work areas need only 4KB alignment, user space
+	 * accesses this region via mmap so it must be placed on a
+	 * page boundary.
+	 */
+	align = PAGE_SIZE;
+
+	rtas_rmo_buf = memblock_phys_alloc_range(size, align, 0, limit);
+	if (rtas_rmo_buf == 0) {
+		panic("Failed to allocate %llu bytes for user region below %pa\n",
+		      size, &limit);
+	}
+
+	pr_debug("RTAS user region allocated at %pa\n", &rtas_rmo_buf);
+}
+
 /*
  * Call early during boot, before mem init, to retrieve the RTAS
  * information from the device-tree and allocate the RMO buffer for userland
@@ -1173,7 +1237,6 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
  */
 void __init rtas_initialize(void)
 {
-	unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
 	u32 base, size, entry;
 	int no_base, no_size, no_entry;
 
@@ -1197,23 +1260,10 @@ void __init rtas_initialize(void)
 	no_entry = of_property_read_u32(rtas.dev, "linux,rtas-entry", &entry);
 	rtas.entry = no_entry ? rtas.base : entry;
 
-	/* If RTAS was found, allocate the RMO buffer for it and look for
-	 * the stop-self token if any
-	 */
-#ifdef CONFIG_PPC64
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		rtas_region = min(ppc64_rma_size, RTAS_INSTANTIATE_MAX);
-#endif
-	rtas_rmo_buf = memblock_phys_alloc_range(RTAS_USER_REGION_SIZE, PAGE_SIZE,
-						 0, rtas_region);
-	if (!rtas_rmo_buf)
-		panic("ERROR: RTAS: Failed to allocate %lx bytes below %pa\n",
-		      PAGE_SIZE, &rtas_region);
-
 #ifdef CONFIG_RTAS_ERROR_LOGGING
 	rtas_last_error_token = rtas_token("rtas-last-error");
 #endif
-
+	rtas_user_region_setup();
 	rtas_syscall_filter_init();
 }
 
-- 
2.29.2


  parent reply	other threads:[~2021-01-14 22:09 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-14 21:59 [PATCH 0/6] powerpc/rtas: miscellaneous cleanups, user region allocation Nathan Lynch
2021-01-14 21:59 ` [PATCH 1/6] powerpc/rtas: improve ppc_rtas_rmo_buf_show documentation Nathan Lynch
2021-01-15  4:38   ` Alexey Kardashevskiy
2021-01-15  5:50   ` Andrew Donnellan
2021-01-14 22:00 ` [PATCH 2/6] powerpc/rtas-proc: remove unused RMO_READ_BUF_MAX Nathan Lynch
2021-01-15  4:38   ` Alexey Kardashevskiy
2021-01-15  5:52   ` Andrew Donnellan
2021-01-14 22:00 ` [PATCH 3/6] powerpc/rtas: remove ibm_suspend_me_token Nathan Lynch
2021-01-15  4:38   ` Alexey Kardashevskiy
2021-01-15  5:52   ` Andrew Donnellan
2021-01-14 22:00 ` [PATCH 4/6] powerpc/rtas: move syscall filter setup into separate function Nathan Lynch
2021-01-15  4:39   ` Alexey Kardashevskiy
2021-01-15 16:04     ` Nathan Lynch
2021-01-15  5:49   ` Andrew Donnellan
2021-01-14 22:00 ` [PATCH 5/6] powerpc/rtas: rename RTAS_RMOBUF_MAX to RTAS_USER_REGION_SIZE Nathan Lynch
2021-01-15  4:38   ` Alexey Kardashevskiy
2021-01-15 15:56     ` Nathan Lynch
2021-01-18  4:15       ` Alexey Kardashevskiy
2021-01-20  1:17         ` Nathan Lynch
2021-01-20  5:05           ` Alexey Kardashevskiy
2021-01-21 15:17             ` Nathan Lynch
2021-01-15  6:10   ` Andrew Donnellan
2021-01-15 12:04   ` kernel test robot
2021-01-14 22:00 ` Nathan Lynch [this message]
2021-01-15  4:38   ` [PATCH 6/6] powerpc/rtas: constrain user region allocation to RMA Alexey Kardashevskiy
2021-01-15 15:38     ` Nathan Lynch
2021-01-18  4:12       ` Alexey Kardashevskiy
2021-01-20  0:39         ` Nathan Lynch
2021-01-20  4:49           ` Alexey Kardashevskiy
2021-01-20 12:06           ` Michael Ellerman
2021-01-21 15:27             ` Nathan Lynch
2021-01-23  1:54               ` Alexey Kardashevskiy
2021-01-19  9:00   ` Michael Ellerman
2021-01-19 21:00     ` Nathan Lynch
2021-01-20 12:13       ` Michael Ellerman
2021-01-21  0:26         ` Nathan Lynch

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210114220004.1138993-7-nathanl@linux.ibm.com \
    --to=nathanl@linux.ibm.com \
    --cc=aik@ozlabs.ru \
    --cc=ajd@linux.ibm.com \
    --cc=aneesh.kumar@linux.ibm.com \
    --cc=brking@linux.ibm.com \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=tyreld@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).