* [PATCH v9 01/13] powerpc/xive: Define xive_native_alloc_irq_on_chip()
From: Haren Myneni @ 2020-04-01 21:25 UTC (permalink / raw)
To: mpe
Cc: mikey, srikar, frederic.barrat, ajd, linux-kernel, npiggin, hch,
oohall, clg, sukadev, linuxppc-dev, herbert
In-Reply-To: <1585775978.10664.438.camel@hbabu-laptop>
This function allocates IRQ on a specific chip. VAS needs per chip
IRQ allocation and will have IRQ handler per VAS instance.
Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
---
arch/powerpc/include/asm/xive.h | 9 ++++++++-
arch/powerpc/sysdev/xive/native.c | 6 +++---
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/include/asm/xive.h b/arch/powerpc/include/asm/xive.h
index 93f982db..d08ea11 100644
--- a/arch/powerpc/include/asm/xive.h
+++ b/arch/powerpc/include/asm/xive.h
@@ -5,6 +5,8 @@
#ifndef _ASM_POWERPC_XIVE_H
#define _ASM_POWERPC_XIVE_H
+#include <asm/opal-api.h>
+
#define XIVE_INVALID_VP 0xffffffff
#ifdef CONFIG_PPC_XIVE
@@ -108,7 +110,6 @@ struct xive_q {
int xive_native_populate_irq_data(u32 hw_irq,
struct xive_irq_data *data);
void xive_cleanup_irq_data(struct xive_irq_data *xd);
-u32 xive_native_alloc_irq(void);
void xive_native_free_irq(u32 irq);
int xive_native_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq);
@@ -137,6 +138,12 @@ int xive_native_set_queue_state(u32 vp_id, uint32_t prio, u32 qtoggle,
u32 qindex);
int xive_native_get_vp_state(u32 vp_id, u64 *out_state);
bool xive_native_has_queue_state_support(void);
+extern u32 xive_native_alloc_irq_on_chip(u32 chip_id);
+
+static inline u32 xive_native_alloc_irq(void)
+{
+ return xive_native_alloc_irq_on_chip(OPAL_XIVE_ANY_CHIP);
+}
#else
diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c
index 0ff6b73..14d4406 100644
--- a/arch/powerpc/sysdev/xive/native.c
+++ b/arch/powerpc/sysdev/xive/native.c
@@ -279,12 +279,12 @@ static int xive_native_get_ipi(unsigned int cpu, struct xive_cpu *xc)
}
#endif /* CONFIG_SMP */
-u32 xive_native_alloc_irq(void)
+u32 xive_native_alloc_irq_on_chip(u32 chip_id)
{
s64 rc;
for (;;) {
- rc = opal_xive_allocate_irq(OPAL_XIVE_ANY_CHIP);
+ rc = opal_xive_allocate_irq(chip_id);
if (rc != OPAL_BUSY)
break;
msleep(OPAL_BUSY_DELAY_MS);
@@ -293,7 +293,7 @@ u32 xive_native_alloc_irq(void)
return 0;
return rc;
}
-EXPORT_SYMBOL_GPL(xive_native_alloc_irq);
+EXPORT_SYMBOL_GPL(xive_native_alloc_irq_on_chip);
void xive_native_free_irq(u32 irq)
{
--
1.8.3.1
^ permalink raw reply related
* [PATCH v9 00/13] powerpc/vas: Page fault handling for user space NX requests
From: Haren Myneni @ 2020-04-01 21:19 UTC (permalink / raw)
To: mpe, npiggin
Cc: mikey, herbert, frederic.barrat, srikar, linux-kernel, hch,
oohall, clg, sukadev, linuxppc-dev, ajd
On power9, Virtual Accelerator Switchboard (VAS) allows user space or
kernel to communicate with Nest Accelerator (NX) directly using COPY/PASTE
instructions. NX provides various functionalities such as compression,
encryption and etc. But only compression (842 and GZIP formats) is
supported in Linux kernel on power9.
842 compression driver (drivers/crypto/nx/nx-842-powernv.c)
is already included in Linux. Only GZIP support will be available from
user space.
Applications can issue GZIP compression / decompression requests to NX with
COPY/PASTE instructions. When NX is processing these requests, can hit
fault on the request buffer (not in memory). It issues an interrupt and
pastes fault CRB in fault FIFO. Expects kernel to handle this fault and
return credits for both send and fault windows after processing.
This patch series adds IRQ and fault window setup, and NX fault handling:
- Alloc IRQ and trigger port address, and configure IRQ per VAS instance.
- Set port# for each window to generate an interrupt when noticed fault.
- Set fault window and FIFO on which NX paste fault CRB.
- Setup IRQ thread fault handler per VAS instance.
- When receiving an interrupt, Read CRBs from fault FIFO and update
coprocessor_status_block (CSB) in the corresponding CRB with translation
failure (CSB_CC_TRANSLATION). After issuing NX requests, process polls
on CSB address. When it sees translation error, can touch the request
buffer to bring the page in to memory and reissue NX request.
- If copy_to_user fails on user space CSB address, OS sends SEGV signal.
Tested these patches with NX-GZIP enable patches and posted them as separate
patch series.
Patch 1: Define alloc IRQ per chip which is needed to alloc IRQ per VAS
instance.
Patch 2: Define nx_fault_stamp on which NX writes fault status for the fault
CRB
Patch 3: Alloc and setup IRQ and trigger port address for each VAS instance
Patches 4 & 5: Setup fault window and register NX per each VAS instance. This
window is used for NX to paste fault CRB in FIFO.
Patch 6: Reference to pid and mm so that pid is not used until window closed.
Needed for multi thread application where child can open a window
and can be used by parent it later.
Patch 7: Setup threaded IRQ handler per VAS
Patch 8: Process CRBs from fault FIFO and notify tasks by updating CSB or
through signals.
Patches 9 & 11: Return credits for send and fault windows after handling
faults.
Patches 10 & 13: Dump FIFO / CRB data and messages for error conditions
Patch 14:Fix closing send window after all credits are returned. This issue
happens only for user space requests. No page faults on kernel
request buffer.
Changelog:
V2:
- Use threaded IRQ instead of own kernel thread handler
- Use pswid instead of user space CSB address to find valid CRB
- Removed unused macros and other changes as suggested by Christoph Hellwig
V3:
- Rebased to 5.5-rc2
- Use struct pid * instead of pid_t for vas_window tgid
- Code cleanup as suggested by Christoph Hellwig
V4:
- Define xive alloc and get IRQ info based on chip ID and use these
functions for IRQ setup per VAS instance. It eliminates skiboot
dependency as suggested by Oliver.
V5:
- Do not update CSB if the process is exiting (patch8)
V6:
- Add interrupt handler instead of default one and return IRQ_HANDLED
if the fault handling thread is already in progress. (Patch7)
- Use platform send window ID and CCW[0] bit to find valid CRB in
fault FIFO (Patch7).
- Return fault address to user space in BE and other changes as
suggested by Michael Neuling. (patch8)
- Rebased to 5.6-rc4
V7:
- Fixed sparse warnings (patches 4, 9 and 10)
V8:
- Moved mm_context_remove_copro() before mmdrop() (patch6)
- Moved barrier before csb.flags store and add WARN_ON_ONCE() checks (patch8)
V9:
- Rebased to 5.6
- Changes based on Cedric's comments
- Removed "Define xive_native_alloc_get_irq_info()" patch and used
irq_get_handler_data() (patch3)
- Changes based on comments from Nicholas Piggin
- Moved "Taking PID reference" patch before setting VAS fault handler
patch
- Removed mutex_lock/unlock (patch7)
- Other cleanup changes
Haren Myneni (13):
powerpc/xive: Define xive_native_alloc_irq_on_chip()
powerpc/vas: Define nx_fault_stamp in coprocessor_request_block
powerpc/vas: Alloc and setup IRQ and trigger port address
powerpc/vas: Setup fault window per VAS instance
powerpc/vas: Register NX with fault window ID and IRQ port value
powerpc/vas: Take reference to PID and mm for user space windows
powerpc/vas: Setup thread IRQ handler per VAS instance
powerpc/vas: Update CSB and notify process for fault CRBs
powerpc/vas: Return credits after handling fault
powerpc/vas: Print CRB and FIFO values
powerpc/vas: Do not use default credits for receive window
powerpc/vas: Display process stuck message
powerpc/vas: Free send window in VAS instance after credits returned
arch/powerpc/include/asm/icswx.h | 20 +-
arch/powerpc/include/asm/xive.h | 9 +-
arch/powerpc/platforms/powernv/Makefile | 2 +-
arch/powerpc/platforms/powernv/vas-debug.c | 2 +-
arch/powerpc/platforms/powernv/vas-fault.c | 382 ++++++++++++++++++++++++++++
arch/powerpc/platforms/powernv/vas-window.c | 204 ++++++++++++++-
arch/powerpc/platforms/powernv/vas.c | 85 ++++++-
arch/powerpc/platforms/powernv/vas.h | 57 ++++-
arch/powerpc/sysdev/xive/native.c | 6 +-
9 files changed, 737 insertions(+), 30 deletions(-)
create mode 100644 arch/powerpc/platforms/powernv/vas-fault.c
--
1.8.3.1
^ permalink raw reply
* Re: [PATCH 0/2] powerpc: Remove support for ppc405/440 Xilinx platforms
From: Arnd Bergmann @ 2020-04-01 21:07 UTC (permalink / raw)
To: Segher Boessenkool
Cc: Mark Rutland, Kate Stewart, Desnes A. Nunes do Rosario,
Geert Uytterhoeven, open list:DOCUMENTATION,
ALSA Development Mailing List, dri-devel, Jaroslav Kysela,
Richard Fontana, Paul Mackerras, Miquel Raynal,
Mauro Carvalho Chehab, Fabio Estevam, Sasha Levin,
Stephen Rothwell, Jonathan Corbet, Masahiro Yamada, YueHaibing,
Michal Simek, Krzysztof Kozlowski, Allison Randal, Leonardo Bras,
DTML, Andrew Donnellan, Bartlomiej Zolnierkiewicz, Marc Zyngier,
Alistair Popple, Nicholas Piggin, Alexios Zavras, Mark Brown, git,
Linux Fbdev development list, Jonathan Cameron, Thomas Gleixner,
Andy Shevchenko, Linux ARM, Enrico Weigelt, Michal Simek, Wei Hu,
Christian Lamparter, Greg Kroah-Hartman, Nick Desaulniers,
Takashi Iwai, linux-kernel@vger.kernel.org, Armijn Hemel,
Rob Herring, linuxppc-dev, David S. Miller, Thiago Jung Bauermann
In-Reply-To: <20200331175123.GV22482@gate.crashing.org>
On Tue, Mar 31, 2020 at 7:51 PM Segher Boessenkool
<segher@kernel.crashing.org> wrote:
>
> On Tue, Mar 31, 2020 at 08:56:23AM +0200, Christophe Leroy wrote:
> > While we are at it, can we also remove the 601 ? This one is also full
> > of workarounds and diverges a bit from other 6xx.
> >
> > I'm unable to find its end of life date, but it was on the market in
> > 1994, so I guess it must be outdated by more than 10-15 yr old now ?
>
> There probably are still some people running Linux on 601 powermacs.
It could be marked as "BROKEN" for a year to find out for sure ;-)
Apparently there were only two or three models that are old enough to
have a 601 and new enough to run Linux with PCI and OF: 7200/8200
and 7500. These were sold for less than 18 months around 1996,
though one can still find them on eBay.
Arnd
^ permalink raw reply
* [PATCH v8 7/7] perf/tools/pmu-events/powerpc: Add hv_24x7 socket/chip level metric events
From: Kajol Jain @ 2020-04-01 20:33 UTC (permalink / raw)
To: acme, linuxppc-dev, mpe, sukadev
Cc: mark.rutland, maddy, peterz, yao.jin, mingo, kan.liang, ak,
alexander.shishkin, anju, mamatha4, ravi.bangoria, kjain, jmario,
namhyung, tglx, mpetlan, gregkh, linux-kernel, linux-perf-users,
jolsa
In-Reply-To: <20200401203340.31402-1-kjain@linux.ibm.com>
The hv_24×7 feature in IBM® POWER9™ processor-based servers provide the
facility to continuously collect large numbers of hardware performance
metrics efficiently and accurately.
This patch adds hv_24x7 metric file for different Socket/chip
resources.
Result:
power9 platform:
command:# ./perf stat --metric-only -M Memory_RD_BW_Chip -C 0 -I 1000
1.000096188 0.9 0.3
2.000285720 0.5 0.1
3.000424990 0.4 0.1
command:# ./perf stat --metric-only -M PowerBUS_Frequency -C 0 -I 1000
1.000097981 2.3 2.3
2.000291713 2.3 2.3
3.000421719 2.3 2.3
4.000550912 2.3 2.3
Signed-off-by: Kajol Jain <kjain@linux.ibm.com>
---
.../arch/powerpc/power9/nest_metrics.json | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/nest_metrics.json
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/nest_metrics.json b/tools/perf/pmu-events/arch/powerpc/power9/nest_metrics.json
new file mode 100644
index 000000000000..c121e526442a
--- /dev/null
+++ b/tools/perf/pmu-events/arch/powerpc/power9/nest_metrics.json
@@ -0,0 +1,19 @@
+[
+ {
+ "MetricExpr": "(hv_24x7@PM_MCS01_128B_RD_DISP_PORT01\\,chip\\=?@ + hv_24x7@PM_MCS01_128B_RD_DISP_PORT23\\,chip\\=?@ + hv_24x7@PM_MCS23_128B_RD_DISP_PORT01\\,chip\\=?@ + hv_24x7@PM_MCS23_128B_RD_DISP_PORT23\\,chip\\=?@)",
+ "MetricName": "Memory_RD_BW_Chip",
+ "MetricGroup": "Memory_BW",
+ "ScaleUnit": "1.6e-2MB"
+ },
+ {
+ "MetricExpr": "(hv_24x7@PM_MCS01_128B_WR_DISP_PORT01\\,chip\\=?@ + hv_24x7@PM_MCS01_128B_WR_DISP_PORT23\\,chip\\=?@ + hv_24x7@PM_MCS23_128B_WR_DISP_PORT01\\,chip\\=?@ + hv_24x7@PM_MCS23_128B_WR_DISP_PORT23\\,chip\\=?@ )",
+ "MetricName": "Memory_WR_BW_Chip",
+ "MetricGroup": "Memory_BW",
+ "ScaleUnit": "1.6e-2MB"
+ },
+ {
+ "MetricExpr": "(hv_24x7@PM_PB_CYC\\,chip\\=?@ )",
+ "MetricName": "PowerBUS_Frequency",
+ "ScaleUnit": "2.5e-7GHz"
+ }
+]
--
2.21.0
^ permalink raw reply related
* [PATCH v8 6/7] tools/perf: Enable Hz/hz prinitg for --metric-only option
From: Kajol Jain @ 2020-04-01 20:33 UTC (permalink / raw)
To: acme, linuxppc-dev, mpe, sukadev
Cc: mark.rutland, maddy, peterz, yao.jin, mingo, kan.liang, ak,
alexander.shishkin, anju, mamatha4, ravi.bangoria, kjain, jmario,
namhyung, tglx, mpetlan, gregkh, linux-kernel, linux-perf-users,
jolsa
In-Reply-To: <20200401203340.31402-1-kjain@linux.ibm.com>
Commit 54b5091606c18 ("perf stat: Implement --metric-only mode")
added function 'valid_only_metric()' which drops "Hz" or "hz",
if it is part of "ScaleUnit". This patch enable it since hv_24x7
supports couple of frequency events.
Signed-off-by: Kajol Jain <kjain@linux.ibm.com>
---
tools/perf/util/stat-display.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c
index 9e757d18d713..679aaa655824 100644
--- a/tools/perf/util/stat-display.c
+++ b/tools/perf/util/stat-display.c
@@ -237,8 +237,6 @@ static bool valid_only_metric(const char *unit)
if (!unit)
return false;
if (strstr(unit, "/sec") ||
- strstr(unit, "hz") ||
- strstr(unit, "Hz") ||
strstr(unit, "CPUs utilized"))
return false;
return true;
--
2.21.0
^ permalink raw reply related
* [PATCH v8 5/7] perf/tests/expr: Added test for runtime param in metric expression
From: Kajol Jain @ 2020-04-01 20:33 UTC (permalink / raw)
To: acme, linuxppc-dev, mpe, sukadev
Cc: mark.rutland, maddy, peterz, yao.jin, mingo, kan.liang, ak,
alexander.shishkin, anju, mamatha4, ravi.bangoria, kjain, jmario,
namhyung, tglx, mpetlan, gregkh, linux-kernel, linux-perf-users,
jolsa
In-Reply-To: <20200401203340.31402-1-kjain@linux.ibm.com>
Added test case for parsing "?" in metric expression.
Signed-off-by: Kajol Jain <kjain@linux.ibm.com>
---
tools/perf/tests/expr.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
index 516504cf0ea5..f9e8e5628836 100644
--- a/tools/perf/tests/expr.c
+++ b/tools/perf/tests/expr.c
@@ -59,6 +59,14 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused)
TEST_ASSERT_VAL("find other", !strcmp(other[2], "BOZO"));
TEST_ASSERT_VAL("find other", other[3] == NULL);
+ TEST_ASSERT_VAL("find other",
+ expr__find_other("EVENT1\\,param\\=?@ + EVENT2\\,param\\=?@", NULL,
+ &other, &num_other, 3) == 0);
+ TEST_ASSERT_VAL("find other", num_other == 2);
+ TEST_ASSERT_VAL("find other", !strcmp(other[0], "EVENT1,param=3/"));
+ TEST_ASSERT_VAL("find other", !strcmp(other[1], "EVENT2,param=3/"));
+ TEST_ASSERT_VAL("find other", other[2] == NULL);
+
for (i = 0; i < num_other; i++)
zfree(&other[i]);
free((void *)other);
--
2.21.0
^ permalink raw reply related
* [PATCH v8 4/7] perf/tools: Enhance JSON/metric infrastructure to handle "?"
From: Kajol Jain @ 2020-04-01 20:33 UTC (permalink / raw)
To: acme, linuxppc-dev, mpe, sukadev
Cc: mark.rutland, maddy, peterz, yao.jin, mingo, kan.liang, ak,
alexander.shishkin, anju, mamatha4, ravi.bangoria, kjain, jmario,
namhyung, tglx, mpetlan, gregkh, linux-kernel, linux-perf-users,
jolsa
In-Reply-To: <20200401203340.31402-1-kjain@linux.ibm.com>
Patch enhances current metric infrastructure to handle "?" in the metric
expression. The "?" can be use for parameters whose value not known while
creating metric events and which can be replace later at runtime to
the proper value. It also add flexibility to create multiple events out
of single metric event added in json file.
Patch adds function 'arch_get_runtimeparam' which is a arch specific
function, returns the count of metric events need to be created.
By default it return 1.
This infrastructure needed for hv_24x7 socket/chip level events.
"hv_24x7" chip level events needs specific chip-id to which the
data is requested. Function 'arch_get_runtimeparam' implemented
in header.c which extract number of sockets from sysfs file
"sockets" under "/sys/devices/hv_24x7/interface/".
With this patch basically we are trying to create as many metric events
as define by runtime_param.
For that one loop is added in function 'metricgroup__add_metric',
which create multiple events at run time depend on return value of
'arch_get_runtimeparam' and merge that event in 'group_list'.
To achieve that we are actually passing this parameter value as part of
`expr__find_other` function and changing "?" present in metric expression
with this value.
As in our json file, there gonna be single metric event, and out of
which we are creating multiple events.
To understand which data count belongs to which parameter value,
we also printing param value in generic_metric function.
For example,
command:# ./perf stat -M PowerBUS_Frequency -C 0 -I 1000
1.000101867 9,356,933 hv_24x7/pm_pb_cyc,chip=0/ # 2.3 GHz PowerBUS_Frequency_0
1.000101867 9,366,134 hv_24x7/pm_pb_cyc,chip=1/ # 2.3 GHz PowerBUS_Frequency_1
2.000314878 9,365,868 hv_24x7/pm_pb_cyc,chip=0/ # 2.3 GHz PowerBUS_Frequency_0
2.000314878 9,366,092 hv_24x7/pm_pb_cyc,chip=1/ # 2.3 GHz PowerBUS_Frequency_1
So, here _0 and _1 after PowerBUS_Frequency specify parameter value.
Signed-off-by: Kajol Jain <kjain@linux.ibm.com>
---
| 8 ++++++++
tools/perf/tests/expr.c | 8 ++++----
tools/perf/util/expr.c | 11 ++++++-----
tools/perf/util/expr.h | 5 +++--
tools/perf/util/expr.l | 27 +++++++++++++++++++-------
tools/perf/util/metricgroup.c | 28 ++++++++++++++++++++++++---
tools/perf/util/metricgroup.h | 2 ++
tools/perf/util/stat-shadow.c | 17 ++++++++++------
8 files changed, 79 insertions(+), 27 deletions(-)
--git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c
index 3b4cdfc5efd6..d4870074f14c 100644
--- a/tools/perf/arch/powerpc/util/header.c
+++ b/tools/perf/arch/powerpc/util/header.c
@@ -7,6 +7,8 @@
#include <string.h>
#include <linux/stringify.h>
#include "header.h"
+#include "metricgroup.h"
+#include <api/fs/fs.h>
#define mfspr(rn) ({unsigned long rval; \
asm volatile("mfspr %0," __stringify(rn) \
@@ -44,3 +46,9 @@ get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
return bufp;
}
+
+int arch_get_runtimeparam(void)
+{
+ int count;
+ return sysfs__read_int("/devices/hv_24x7/interface/sockets", &count) < 0 ? 1 : count;
+}
diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
index ea10fc4412c4..516504cf0ea5 100644
--- a/tools/perf/tests/expr.c
+++ b/tools/perf/tests/expr.c
@@ -10,7 +10,7 @@ static int test(struct expr_parse_ctx *ctx, const char *e, double val2)
{
double val;
- if (expr__parse(&val, ctx, e))
+ if (expr__parse(&val, ctx, e, 1))
TEST_ASSERT_VAL("parse test failed", 0);
TEST_ASSERT_VAL("unexpected value", val == val2);
return 0;
@@ -44,15 +44,15 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused)
return ret;
p = "FOO/0";
- ret = expr__parse(&val, &ctx, p);
+ ret = expr__parse(&val, &ctx, p, 1);
TEST_ASSERT_VAL("division by zero", ret == -1);
p = "BAR/";
- ret = expr__parse(&val, &ctx, p);
+ ret = expr__parse(&val, &ctx, p, 1);
TEST_ASSERT_VAL("missing operand", ret == -1);
TEST_ASSERT_VAL("find other",
- expr__find_other("FOO + BAR + BAZ + BOZO", "FOO", &other, &num_other) == 0);
+ expr__find_other("FOO + BAR + BAZ + BOZO", "FOO", &other, &num_other, 1) == 0);
TEST_ASSERT_VAL("find other", num_other == 3);
TEST_ASSERT_VAL("find other", !strcmp(other[0], "BAR"));
TEST_ASSERT_VAL("find other", !strcmp(other[1], "BAZ"));
diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c
index c3382d58cf40..aa631e37ad1e 100644
--- a/tools/perf/util/expr.c
+++ b/tools/perf/util/expr.c
@@ -27,10 +27,11 @@ void expr__ctx_init(struct expr_parse_ctx *ctx)
static int
__expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,
- int start)
+ int start, int runtime)
{
struct expr_scanner_ctx scanner_ctx = {
.start_token = start,
+ .runtime = runtime,
};
YY_BUFFER_STATE buffer;
void *scanner;
@@ -54,9 +55,9 @@ __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,
return ret;
}
-int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr)
+int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime)
{
- return __expr__parse(final_val, ctx, expr, EXPR_PARSE) ? -1 : 0;
+ return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0;
}
static bool
@@ -74,13 +75,13 @@ already_seen(const char *val, const char *one, const char **other,
}
int expr__find_other(const char *expr, const char *one, const char ***other,
- int *num_other)
+ int *num_other, int runtime)
{
int err, i = 0, j = 0;
struct expr_parse_ctx ctx;
expr__ctx_init(&ctx);
- err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER);
+ err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER, runtime);
if (err)
return -1;
diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h
index 0938ad166ece..87d627bb699b 100644
--- a/tools/perf/util/expr.h
+++ b/tools/perf/util/expr.h
@@ -17,12 +17,13 @@ struct expr_parse_ctx {
struct expr_scanner_ctx {
int start_token;
+ int runtime;
};
void expr__ctx_init(struct expr_parse_ctx *ctx);
void expr__add_id(struct expr_parse_ctx *ctx, const char *id, double val);
-int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr);
+int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime);
int expr__find_other(const char *expr, const char *one, const char ***other,
- int *num_other);
+ int *num_other, int runtime);
#endif
diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l
index 2582c2464938..74b9b59b1aa5 100644
--- a/tools/perf/util/expr.l
+++ b/tools/perf/util/expr.l
@@ -35,7 +35,7 @@ static int value(yyscan_t scanner, int base)
* Allow @ instead of / to be able to specify pmu/event/ without
* conflicts with normal division.
*/
-static char *normalize(char *str)
+static char *normalize(char *str, int runtime)
{
char *ret = str;
char *dst = str;
@@ -45,6 +45,19 @@ static char *normalize(char *str)
*dst++ = '/';
else if (*str == '\\')
*dst++ = *++str;
+ else if (*str == '?') {
+ char *paramval;
+ int i = 0;
+ int size = asprintf(¶mval, "%d", runtime);
+
+ if (size < 0)
+ *dst++ = '0';
+ else {
+ while (i < size)
+ *dst++ = paramval[i++];
+ free(paramval);
+ }
+ }
else
*dst++ = *str;
str++;
@@ -54,16 +67,16 @@ static char *normalize(char *str)
return ret;
}
-static int str(yyscan_t scanner, int token)
+static int str(yyscan_t scanner, int token, int runtime)
{
YYSTYPE *yylval = expr_get_lval(scanner);
char *text = expr_get_text(scanner);
- yylval->str = normalize(strdup(text));
+ yylval->str = normalize(strdup(text), runtime);
if (!yylval->str)
return EXPR_ERROR;
- yylval->str = normalize(yylval->str);
+ yylval->str = normalize(yylval->str, runtime);
return token;
}
%}
@@ -72,8 +85,8 @@ number [0-9]+
sch [-,=]
spec \\{sch}
-sym [0-9a-zA-Z_\.:@]+
-symbol {spec}*{sym}*{spec}*{sym}*
+sym [0-9a-zA-Z_\.:@?]+
+symbol {spec}*{sym}*{spec}*{sym}*{spec}*{sym}
%%
struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner);
@@ -93,7 +106,7 @@ if { return IF; }
else { return ELSE; }
#smt_on { return SMT_ON; }
{number} { return value(yyscanner, 10); }
-{symbol} { return str(yyscanner, ID); }
+{symbol} { return str(yyscanner, ID, sctx->runtime); }
"|" { return '|'; }
"^" { return '^'; }
"&" { return '&'; }
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c
index 7ad81c8177ea..b071df373f8b 100644
--- a/tools/perf/util/metricgroup.c
+++ b/tools/perf/util/metricgroup.c
@@ -90,6 +90,7 @@ struct egroup {
const char *metric_name;
const char *metric_expr;
const char *metric_unit;
+ int runtime;
};
static struct evsel *find_evsel_group(struct evlist *perf_evlist,
@@ -202,6 +203,7 @@ static int metricgroup__setup_events(struct list_head *groups,
expr->metric_name = eg->metric_name;
expr->metric_unit = eg->metric_unit;
expr->metric_events = metric_events;
+ expr->runtime = eg->runtime;
list_add(&expr->nd, &me->head);
}
@@ -485,15 +487,20 @@ static bool metricgroup__has_constraint(struct pmu_event *pe)
return false;
}
+int __weak arch_get_runtimeparam(void)
+{
+ return 1;
+}
+
static int __metricgroup__add_metric(struct strbuf *events,
- struct list_head *group_list, struct pmu_event *pe)
+ struct list_head *group_list, struct pmu_event *pe, int runtime)
{
const char **ids;
int idnum;
struct egroup *eg;
- if (expr__find_other(pe->metric_expr, NULL, &ids, &idnum) < 0)
+ if (expr__find_other(pe->metric_expr, NULL, &ids, &idnum, runtime) < 0)
return -EINVAL;
if (events->len > 0)
@@ -513,6 +520,7 @@ static int __metricgroup__add_metric(struct strbuf *events,
eg->metric_name = pe->metric_name;
eg->metric_expr = pe->metric_expr;
eg->metric_unit = pe->unit;
+ eg->runtime = runtime;
list_add_tail(&eg->nd, group_list);
return 0;
@@ -540,7 +548,21 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events,
pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name);
- ret = __metricgroup__add_metric(events, group_list, pe);
+ if (!strstr(pe->metric_expr, "?")) {
+ ret = __metricgroup__add_metric(events, group_list, pe, 1);
+ } else {
+ int j, count;
+
+ count = arch_get_runtimeparam();
+
+ /* This loop is added to create multiple
+ * events depend on count value and add
+ * those events to group_list.
+ */
+
+ for (j = 0; j < count; j++)
+ ret = __metricgroup__add_metric(events, group_list, pe, j);
+ }
if (ret == -ENOMEM)
break;
}
diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h
index 475c7f912864..6b09eb30b4ec 100644
--- a/tools/perf/util/metricgroup.h
+++ b/tools/perf/util/metricgroup.h
@@ -22,6 +22,7 @@ struct metric_expr {
const char *metric_name;
const char *metric_unit;
struct evsel **metric_events;
+ int runtime;
};
struct metric_event *metricgroup__lookup(struct rblist *metric_events,
@@ -34,4 +35,5 @@ int metricgroup__parse_groups(const struct option *opt,
void metricgroup__print(bool metrics, bool groups, char *filter,
bool raw, bool details);
bool metricgroup__has_metric(const char *metric);
+int arch_get_runtimeparam(void);
#endif
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 402af3e8d287..cf353ca591a5 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -336,7 +336,7 @@ void perf_stat__collect_metric_expr(struct evlist *evsel_list)
metric_events = counter->metric_events;
if (!metric_events) {
if (expr__find_other(counter->metric_expr, counter->name,
- &metric_names, &num_metric_names) < 0)
+ &metric_names, &num_metric_names, 1) < 0)
continue;
metric_events = calloc(sizeof(struct evsel *),
@@ -723,6 +723,7 @@ static void generic_metric(struct perf_stat_config *config,
char *name,
const char *metric_name,
const char *metric_unit,
+ int runtime,
double avg,
int cpu,
struct perf_stat_output_ctx *out,
@@ -777,7 +778,7 @@ static void generic_metric(struct perf_stat_config *config,
}
if (!metric_events[i]) {
- if (expr__parse(&ratio, &pctx, metric_expr) == 0) {
+ if (expr__parse(&ratio, &pctx, metric_expr, runtime) == 0) {
char *unit;
char metric_bf[64];
@@ -786,9 +787,13 @@ static void generic_metric(struct perf_stat_config *config,
&unit, &scale) >= 0) {
ratio *= scale;
}
-
- scnprintf(metric_bf, sizeof(metric_bf),
+ if (strstr(metric_expr, "?"))
+ scnprintf(metric_bf, sizeof(metric_bf),
+ "%s %s_%d", unit, metric_name, runtime);
+ else
+ scnprintf(metric_bf, sizeof(metric_bf),
"%s %s", unit, metric_name);
+
print_metric(config, ctxp, NULL, "%8.1f",
metric_bf, ratio);
} else {
@@ -1019,7 +1024,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
print_metric(config, ctxp, NULL, NULL, name, 0);
} else if (evsel->metric_expr) {
generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name,
- evsel->metric_name, NULL, avg, cpu, out, st);
+ evsel->metric_name, NULL, 1, avg, cpu, out, st);
} else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) {
char unit = 'M';
char unit_buf[10];
@@ -1048,7 +1053,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
out->new_line(config, ctxp);
generic_metric(config, mexp->metric_expr, mexp->metric_events,
evsel->name, mexp->metric_name,
- mexp->metric_unit, avg, cpu, out, st);
+ mexp->metric_unit, mexp->runtime, avg, cpu, out, st);
}
}
if (num == 0)
--
2.21.0
^ permalink raw reply related
* [PATCH v8 3/7] perf/tools: Refactoring metricgroup__add_metric function
From: Kajol Jain @ 2020-04-01 20:33 UTC (permalink / raw)
To: acme, linuxppc-dev, mpe, sukadev
Cc: mark.rutland, maddy, peterz, yao.jin, mingo, kan.liang, ak,
alexander.shishkin, anju, mamatha4, ravi.bangoria, kjain, jmario,
namhyung, tglx, mpetlan, gregkh, linux-kernel, linux-perf-users,
jolsa
In-Reply-To: <20200401203340.31402-1-kjain@linux.ibm.com>
This patch refactor metricgroup__add_metric function where
some part of it move to function metricgroup__add_metric_param.
No logic change.
Signed-off-by: Kajol Jain <kjain@linux.ibm.com>
---
tools/perf/util/metricgroup.c | 60 ++++++++++++++++++++---------------
1 file changed, 35 insertions(+), 25 deletions(-)
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c
index 926449a7cdbf..7ad81c8177ea 100644
--- a/tools/perf/util/metricgroup.c
+++ b/tools/perf/util/metricgroup.c
@@ -485,6 +485,39 @@ static bool metricgroup__has_constraint(struct pmu_event *pe)
return false;
}
+static int __metricgroup__add_metric(struct strbuf *events,
+ struct list_head *group_list, struct pmu_event *pe)
+{
+
+ const char **ids;
+ int idnum;
+ struct egroup *eg;
+
+ if (expr__find_other(pe->metric_expr, NULL, &ids, &idnum) < 0)
+ return -EINVAL;
+
+ if (events->len > 0)
+ strbuf_addf(events, ",");
+
+ if (metricgroup__has_constraint(pe))
+ metricgroup__add_metric_non_group(events, ids, idnum);
+ else
+ metricgroup__add_metric_weak_group(events, ids, idnum);
+
+ eg = malloc(sizeof(*eg));
+ if (!eg)
+ return -ENOMEM;
+
+ eg->ids = ids;
+ eg->idnum = idnum;
+ eg->metric_name = pe->metric_name;
+ eg->metric_expr = pe->metric_expr;
+ eg->metric_unit = pe->unit;
+ list_add_tail(&eg->nd, group_list);
+
+ return 0;
+}
+
static int metricgroup__add_metric(const char *metric, struct strbuf *events,
struct list_head *group_list)
{
@@ -504,35 +537,12 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events,
continue;
if (match_metric(pe->metric_group, metric) ||
match_metric(pe->metric_name, metric)) {
- const char **ids;
- int idnum;
- struct egroup *eg;
pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name);
- if (expr__find_other(pe->metric_expr,
- NULL, &ids, &idnum) < 0)
- continue;
- if (events->len > 0)
- strbuf_addf(events, ",");
-
- if (metricgroup__has_constraint(pe))
- metricgroup__add_metric_non_group(events, ids, idnum);
- else
- metricgroup__add_metric_weak_group(events, ids, idnum);
-
- eg = malloc(sizeof(struct egroup));
- if (!eg) {
- ret = -ENOMEM;
+ ret = __metricgroup__add_metric(events, group_list, pe);
+ if (ret == -ENOMEM)
break;
- }
- eg->ids = ids;
- eg->idnum = idnum;
- eg->metric_name = pe->metric_name;
- eg->metric_expr = pe->metric_expr;
- eg->metric_unit = pe->unit;
- list_add_tail(&eg->nd, group_list);
- ret = 0;
}
}
return ret;
--
2.21.0
^ permalink raw reply related
* [PATCH v8 2/7] perf expr: Add expr_scanner_ctx object
From: Kajol Jain @ 2020-04-01 20:33 UTC (permalink / raw)
To: acme, linuxppc-dev, mpe, sukadev
Cc: mark.rutland, maddy, peterz, yao.jin, mingo, kan.liang, ak,
alexander.shishkin, anju, mamatha4, ravi.bangoria, kjain, jmario,
namhyung, tglx, mpetlan, gregkh, linux-kernel, linux-perf-users,
jolsa
In-Reply-To: <20200401203340.31402-1-kjain@linux.ibm.com>
From: Jiri Olsa <jolsa@kernel.org>
Adding expr_scanner_ctx object to hold user data
for the expr scanner. Currently it holds only
start_token, Kajol Jain will use it to hold 24x7
runtime param.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/util/expr.c | 6 ++++--
tools/perf/util/expr.h | 4 ++++
tools/perf/util/expr.l | 10 +++++-----
3 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c
index c8ccc548a585..c3382d58cf40 100644
--- a/tools/perf/util/expr.c
+++ b/tools/perf/util/expr.c
@@ -3,7 +3,6 @@
#include <assert.h>
#include "expr.h"
#include "expr-bison.h"
-#define YY_EXTRA_TYPE int
#include "expr-flex.h"
#ifdef PARSER_DEBUG
@@ -30,11 +29,14 @@ static int
__expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,
int start)
{
+ struct expr_scanner_ctx scanner_ctx = {
+ .start_token = start,
+ };
YY_BUFFER_STATE buffer;
void *scanner;
int ret;
- ret = expr_lex_init_extra(start, &scanner);
+ ret = expr_lex_init_extra(&scanner_ctx, &scanner);
if (ret)
return ret;
diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h
index b9e53f2b5844..0938ad166ece 100644
--- a/tools/perf/util/expr.h
+++ b/tools/perf/util/expr.h
@@ -15,6 +15,10 @@ struct expr_parse_ctx {
struct expr_parse_id ids[MAX_PARSE_ID];
};
+struct expr_scanner_ctx {
+ int start_token;
+};
+
void expr__ctx_init(struct expr_parse_ctx *ctx);
void expr__add_id(struct expr_parse_ctx *ctx, const char *id, double val);
int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr);
diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l
index eaad29243c23..2582c2464938 100644
--- a/tools/perf/util/expr.l
+++ b/tools/perf/util/expr.l
@@ -76,13 +76,13 @@ sym [0-9a-zA-Z_\.:@]+
symbol {spec}*{sym}*{spec}*{sym}*
%%
- {
- int start_token;
+ struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner);
- start_token = expr_get_extra(yyscanner);
+ {
+ int start_token = sctx->start_token;
- if (start_token) {
- expr_set_extra(NULL, yyscanner);
+ if (sctx->start_token) {
+ sctx->start_token = 0;
return start_token;
}
}
--
2.21.0
^ permalink raw reply related
* [PATCH v8 1/7] perf expr: Add expr_ prefix for parse_ctx and parse_id
From: Kajol Jain @ 2020-04-01 20:33 UTC (permalink / raw)
To: acme, linuxppc-dev, mpe, sukadev
Cc: mark.rutland, maddy, peterz, yao.jin, mingo, kan.liang, ak,
alexander.shishkin, anju, mamatha4, ravi.bangoria, kjain, jmario,
namhyung, tglx, mpetlan, gregkh, linux-kernel, linux-perf-users,
jolsa
In-Reply-To: <20200401203340.31402-1-kjain@linux.ibm.com>
From: Jiri Olsa <jolsa@kernel.org>
Adding expr_ prefix for parse_ctx and parse_id,
to straighten out the expr* namespace.
There's no functional change.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/tests/expr.c | 4 ++--
tools/perf/util/expr.c | 10 +++++-----
tools/perf/util/expr.h | 12 ++++++------
tools/perf/util/expr.y | 6 +++---
tools/perf/util/stat-shadow.c | 2 +-
5 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
index 28313e59d6f6..ea10fc4412c4 100644
--- a/tools/perf/tests/expr.c
+++ b/tools/perf/tests/expr.c
@@ -6,7 +6,7 @@
#include <string.h>
#include <linux/zalloc.h>
-static int test(struct parse_ctx *ctx, const char *e, double val2)
+static int test(struct expr_parse_ctx *ctx, const char *e, double val2)
{
double val;
@@ -22,7 +22,7 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused)
const char **other;
double val;
int i, ret;
- struct parse_ctx ctx;
+ struct expr_parse_ctx ctx;
int num_other;
expr__ctx_init(&ctx);
diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c
index fd192ddf93c1..c8ccc548a585 100644
--- a/tools/perf/util/expr.c
+++ b/tools/perf/util/expr.c
@@ -11,7 +11,7 @@ extern int expr_debug;
#endif
/* Caller must make sure id is allocated */
-void expr__add_id(struct parse_ctx *ctx, const char *name, double val)
+void expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val)
{
int idx;
@@ -21,13 +21,13 @@ void expr__add_id(struct parse_ctx *ctx, const char *name, double val)
ctx->ids[idx].val = val;
}
-void expr__ctx_init(struct parse_ctx *ctx)
+void expr__ctx_init(struct expr_parse_ctx *ctx)
{
ctx->num_ids = 0;
}
static int
-__expr__parse(double *val, struct parse_ctx *ctx, const char *expr,
+__expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,
int start)
{
YY_BUFFER_STATE buffer;
@@ -52,7 +52,7 @@ __expr__parse(double *val, struct parse_ctx *ctx, const char *expr,
return ret;
}
-int expr__parse(double *final_val, struct parse_ctx *ctx, const char *expr)
+int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr)
{
return __expr__parse(final_val, ctx, expr, EXPR_PARSE) ? -1 : 0;
}
@@ -75,7 +75,7 @@ int expr__find_other(const char *expr, const char *one, const char ***other,
int *num_other)
{
int err, i = 0, j = 0;
- struct parse_ctx ctx;
+ struct expr_parse_ctx ctx;
expr__ctx_init(&ctx);
err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER);
diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h
index 9377538f4097..b9e53f2b5844 100644
--- a/tools/perf/util/expr.h
+++ b/tools/perf/util/expr.h
@@ -5,19 +5,19 @@
#define EXPR_MAX_OTHER 20
#define MAX_PARSE_ID EXPR_MAX_OTHER
-struct parse_id {
+struct expr_parse_id {
const char *name;
double val;
};
-struct parse_ctx {
+struct expr_parse_ctx {
int num_ids;
- struct parse_id ids[MAX_PARSE_ID];
+ struct expr_parse_id ids[MAX_PARSE_ID];
};
-void expr__ctx_init(struct parse_ctx *ctx);
-void expr__add_id(struct parse_ctx *ctx, const char *id, double val);
-int expr__parse(double *final_val, struct parse_ctx *ctx, const char *expr);
+void expr__ctx_init(struct expr_parse_ctx *ctx);
+void expr__add_id(struct expr_parse_ctx *ctx, const char *id, double val);
+int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr);
int expr__find_other(const char *expr, const char *one, const char ***other,
int *num_other);
diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y
index 4720cbe79357..cd17486c1c5d 100644
--- a/tools/perf/util/expr.y
+++ b/tools/perf/util/expr.y
@@ -15,7 +15,7 @@
%define api.pure full
%parse-param { double *final_val }
-%parse-param { struct parse_ctx *ctx }
+%parse-param { struct expr_parse_ctx *ctx }
%parse-param {void *scanner}
%lex-param {void* scanner}
@@ -39,14 +39,14 @@
%{
static void expr_error(double *final_val __maybe_unused,
- struct parse_ctx *ctx __maybe_unused,
+ struct expr_parse_ctx *ctx __maybe_unused,
void *scanner,
const char *s)
{
pr_debug("%s\n", s);
}
-static int lookup_id(struct parse_ctx *ctx, char *id, double *val)
+static int lookup_id(struct expr_parse_ctx *ctx, char *id, double *val)
{
int i;
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 0fd713d3674f..402af3e8d287 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -729,7 +729,7 @@ static void generic_metric(struct perf_stat_config *config,
struct runtime_stat *st)
{
print_metric_t print_metric = out->print_metric;
- struct parse_ctx pctx;
+ struct expr_parse_ctx pctx;
double ratio, scale;
int i;
void *ctxp = out->ctx;
--
2.21.0
^ permalink raw reply related
* [PATCH v8 0/7] powerpc/perf: Add json file metric support for the hv_24x7 socket/chip level events
From: Kajol Jain @ 2020-04-01 20:33 UTC (permalink / raw)
To: acme, linuxppc-dev, mpe, sukadev
Cc: mark.rutland, maddy, peterz, yao.jin, mingo, kan.liang, ak,
alexander.shishkin, anju, mamatha4, ravi.bangoria, kjain, jmario,
namhyung, tglx, mpetlan, gregkh, linux-kernel, linux-perf-users,
jolsa
Patchset adds json file metric support for the hv_24x7 socket/chip level
events. "hv_24x7" pmu interface events needs system dependent parameter
like socket/chip/core. For example, hv_24x7 chip level events needs
specific chip-id to which the data is requested should be added as part
of pmu events.
So to enable JSON file support to "hv_24x7" interface, patchset reads
total number of sockets details in sysfs under
"/sys/devices/hv_24x7/interface/".
Second patch of the patchset adds expr_scanner_ctx object to hold user
data for the expr scanner, which can be used to hold runtime parameter.
Patch 4 & 6 of the patchset handles perf tool plumbing needed to replace
the "?" character in the metric expression to proper value and hv_24x7
json metric file for different Socket/chip resources.
Patch set also enable Hz/hz prinitg for --metric-only option to print
metric data for bus frequency.
Applied and tested all these patches cleanly on top of jiri's flex changes
with the changes done by Kan Liang for "Support metric group constraint"
patchset and made required changes.
Also apply this patch on top of the fix patch send earlier
for printing metric name incase overlapping events.
https://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git/commit/?h=perf/core&id=37cd7f65bf71a48f25eeb6d9be5dacb20d008ea6
Changelog:
v7 -> v8
- Add test case for testing parsing of "?" in metric expression
- Reaname variables name to runtime
v6 -> v7
- Spit patchset into two patch series one for kernel changes and other
for tool side changes.
- Made changes Suggested by Jiri, including rather then reading runtime
parameter from metric name, actually add it in structure egroup and
metric_expr.
- As we don't need to read runtime parameter from metric name,
now I am not appending it and rather just printing it in
generic_metric function.
Kernel Side changes patch series: https://lkml.org/lkml/2020/3/27/58
v5 -> v6
- resolve compilation issue due to rearranging patch series.
- Rather then adding new function to take careof case for runtime param
in metricgroup__add_metric, using metricgroup__add_metric_param itself
for that work.
- Address some optimization suggested like using directly file path
rather then adding new macro in header.c
- Change commit message on patch where we are adding "?" support
by adding simple example.
v4 -> v5
- Using sysfs__read_int instead of sysfs__read_ull while reading
parameter value in powerpc/util/header.c file.
- Using asprintf rather then malloc and sprintf
Suggested by Arnaldo Carvalho de Melo
- Break patch 6 from previous version to two patch,
- One to add refactor current "metricgroup__add_metric" function
and another where actually "?" handling infra added.
- Add expr__runtimeparam as part of 'expr_scanner_ctx' struct
rather then making it global variable. Thanks Jiri for
adding this structure to hold user data for the expr scanner.
- Add runtime param as agrugement to function 'expr__find_other'
and 'expr__parse' and made changes on references accordingly.
v3 -> v4
- Apply these patch on top of Kan liang changes.
As suggested by Jiri.
v2 -> v3
- Remove setting event_count to 0 part in function 'h_24x7_event_read'
with comment rather then adding 0 to event_count value.
Suggested by: Sukadev Bhattiprolu
- Apply tool side changes require to replace "?" on Jiri's flex patch
series and made all require changes to make it compatible with added
flex change.
v1 -> v2
- Rename hv-24x7 metric json file as nest_metrics.json
Jiri Olsa (2):
perf expr: Add expr_ prefix for parse_ctx and parse_id
perf expr: Add expr_scanner_ctx object
Kajol Jain (5):
perf/tools: Refactoring metricgroup__add_metric function
perf/tools: Enhance JSON/metric infrastructure to handle "?"
perf/tests/expr: Added test for runtime param in metric expression
tools/perf: Enable Hz/hz prinitg for --metric-only option
perf/tools/pmu-events/powerpc: Add hv_24x7 socket/chip level metric
events
tools/perf/arch/powerpc/util/header.c | 8 ++
.../arch/powerpc/power9/nest_metrics.json | 19 +++++
tools/perf/tests/expr.c | 20 +++--
tools/perf/util/expr.c | 25 +++---
tools/perf/util/expr.h | 19 +++--
tools/perf/util/expr.l | 37 ++++++---
tools/perf/util/expr.y | 6 +-
tools/perf/util/metricgroup.c | 78 +++++++++++++------
tools/perf/util/metricgroup.h | 2 +
tools/perf/util/stat-display.c | 2 -
tools/perf/util/stat-shadow.c | 19 +++--
11 files changed, 164 insertions(+), 71 deletions(-)
create mode 100644 tools/perf/pmu-events/arch/powerpc/power9/nest_metrics.json
--
2.21.0
^ permalink raw reply
* Re: [PATCH v4 12/25] nvdimm/ocxl: Add register addresses & status values to the header
From: Dan Williams @ 2020-04-01 20:27 UTC (permalink / raw)
To: Alastair D'Silva
Cc: Madhavan Srinivasan, Alexey Kardashevskiy, Masahiro Yamada,
Oliver O'Halloran, Mauro Carvalho Chehab, Ira Weiny,
Rob Herring, Dave Jiang, linux-nvdimm, Aneesh Kumar K . V,
Krzysztof Kozlowski, Anju T Sudhakar, Mahesh Salgaonkar,
Andrew Donnellan, Arnd Bergmann, Greg Kurz, Nicholas Piggin,
Cédric Le Goater, Thomas Gleixner, Hari Bathini, Linux MM,
Greg Kroah-Hartman, Linux Kernel Mailing List, Vishal Verma,
Frederic Barrat, Paul Mackerras, Andrew Morton, linuxppc-dev,
David S. Miller
In-Reply-To: <20200327071202.2159885-13-alastair@d-silva.org>
On Sun, Mar 29, 2020 at 10:53 PM Alastair D'Silva <alastair@d-silva.org> wrote:
>
> These values have been taken from the device specifications.
Link to specification?
^ permalink raw reply
* Re: [PATCH v4 11/25] powerpc: Enable the OpenCAPI Persistent Memory driver for powernv_defconfig
From: Dan Williams @ 2020-04-01 20:26 UTC (permalink / raw)
To: Alastair D'Silva
Cc: Madhavan Srinivasan, Alexey Kardashevskiy, Masahiro Yamada,
Oliver O'Halloran, Mauro Carvalho Chehab, Ira Weiny,
Rob Herring, Dave Jiang, linux-nvdimm, Aneesh Kumar K . V,
Krzysztof Kozlowski, Anju T Sudhakar, Mahesh Salgaonkar,
Andrew Donnellan, Arnd Bergmann, Greg Kurz, Nicholas Piggin,
Cédric Le Goater, Thomas Gleixner, Hari Bathini, Linux MM,
Greg Kroah-Hartman, Linux Kernel Mailing List, Vishal Verma,
Frederic Barrat, Paul Mackerras, Andrew Morton, linuxppc-dev,
David S. Miller
In-Reply-To: <20200327071202.2159885-12-alastair@d-silva.org>
On Sun, Mar 29, 2020 at 10:23 PM Alastair D'Silva <alastair@d-silva.org> wrote:
>
> This patch enables the OpenCAPI Persistent Memory driver, as well
> as DAX support, for the 'powernv' defconfig.
>
> DAX is not a strict requirement for the functioning of the driver, but it
> is likely that a user will want to create a DAX device on top of their
> persistent memory device.
>
> Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
> Reviewed-by: Andrew Donnellan <ajd@linux.ibm.com>
> ---
> arch/powerpc/configs/powernv_defconfig | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig
> index 71749377d164..921d77bbd3d2 100644
> --- a/arch/powerpc/configs/powernv_defconfig
> +++ b/arch/powerpc/configs/powernv_defconfig
> @@ -348,3 +348,8 @@ CONFIG_KVM_BOOK3S_64=m
> CONFIG_KVM_BOOK3S_64_HV=m
> CONFIG_VHOST_NET=m
> CONFIG_PRINTK_TIME=y
> +CONFIG_ZONE_DEVICE=y
> +CONFIG_OCXL_PMEM=m
> +CONFIG_DEV_DAX=m
> +CONFIG_DEV_DAX_PMEM=m
> +CONFIG_FS_DAX=y
These options have dependencies. I think it would better to implement
a top-level configuration question called something like
PERSISTENT_MEMORY_ALL that goes and selects all the bus providers and
infrastructure and lets other defaults follow along. For example,
CONFIG_DEV_DAX could grow a "default LIBNVDIMM" and then
CONFIG_DEV_DAX_PMEM would default on as well. If
CONFIG_PERSISTENT_MEMORY_ALL selected all the bus providers and
ZONE_DEVICE then the Kconfig system could prompt you to where the
dependencies are not satisfied.
^ permalink raw reply
* Re: [PATCH v4 10/25] nvdimm: Add driver for OpenCAPI Persistent Memory
From: Dan Williams @ 2020-04-01 19:35 UTC (permalink / raw)
To: Alastair D'Silva
Cc: Madhavan Srinivasan, Alexey Kardashevskiy, Masahiro Yamada,
Oliver O'Halloran, Mauro Carvalho Chehab, Ira Weiny,
Rob Herring, Dave Jiang, linux-nvdimm, Aneesh Kumar K . V,
Krzysztof Kozlowski, Anju T Sudhakar, Mahesh Salgaonkar,
Andrew Donnellan, Arnd Bergmann, Greg Kurz, Nicholas Piggin,
Cédric Le Goater, Thomas Gleixner, Hari Bathini, Linux MM,
Greg Kroah-Hartman, Linux Kernel Mailing List, Vishal Verma,
Frederic Barrat, Paul Mackerras, Andrew Morton, linuxppc-dev,
David S. Miller
In-Reply-To: <CAPcyv4gQVuHLHy7YuEEk7uTtknTugwrDzosiVQm5bMoB9udPng@mail.gmail.com>
On Wed, Apr 1, 2020 at 1:49 AM Dan Williams <dan.j.williams@intel.com> wrote:
>
> On Sun, Mar 29, 2020 at 10:23 PM Alastair D'Silva <alastair@d-silva.org> wrote:
> >
> > This driver exposes LPC memory on OpenCAPI pmem cards
> > as an NVDIMM, allowing the existing nvram infrastructure
> > to be used.
> >
> > Namespace metadata is stored on the media itself, so
> > scm_reserve_metadata() maps 1 section's worth of PMEM storage
> > at the start to hold this. The rest of the PMEM range is registered
> > with libnvdimm as an nvdimm. ndctl_config_read/write/size() provide
> > callbacks to libnvdimm to access the metadata.
> >
> > Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
> > ---
> > drivers/nvdimm/Kconfig | 2 +
> > drivers/nvdimm/Makefile | 1 +
> > drivers/nvdimm/ocxl/Kconfig | 15 ++
> > drivers/nvdimm/ocxl/Makefile | 7 +
> > drivers/nvdimm/ocxl/main.c | 476 +++++++++++++++++++++++++++++++++
> > drivers/nvdimm/ocxl/ocxlpmem.h | 23 ++
> > 6 files changed, 524 insertions(+)
> > create mode 100644 drivers/nvdimm/ocxl/Kconfig
> > create mode 100644 drivers/nvdimm/ocxl/Makefile
> > create mode 100644 drivers/nvdimm/ocxl/main.c
> > create mode 100644 drivers/nvdimm/ocxl/ocxlpmem.h
> >
> > diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
> > index b7d1eb38b27d..368328637182 100644
> > --- a/drivers/nvdimm/Kconfig
> > +++ b/drivers/nvdimm/Kconfig
> > @@ -131,4 +131,6 @@ config NVDIMM_TEST_BUILD
> > core devm_memremap_pages() implementation and other
> > infrastructure.
> >
> > +source "drivers/nvdimm/ocxl/Kconfig"
> > +
> > endif
> > diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
> > index 29203f3d3069..bc02be11c794 100644
> > --- a/drivers/nvdimm/Makefile
> > +++ b/drivers/nvdimm/Makefile
> > @@ -33,3 +33,4 @@ libnvdimm-$(CONFIG_NVDIMM_KEYS) += security.o
> > TOOLS := ../../tools
> > TEST_SRC := $(TOOLS)/testing/nvdimm/test
> > obj-$(CONFIG_NVDIMM_TEST_BUILD) += $(TEST_SRC)/iomap.o
> > +obj-$(CONFIG_LIBNVDIMM) += ocxl/
> > diff --git a/drivers/nvdimm/ocxl/Kconfig b/drivers/nvdimm/ocxl/Kconfig
> > new file mode 100644
> > index 000000000000..c5d927520920
> > --- /dev/null
> > +++ b/drivers/nvdimm/ocxl/Kconfig
> > @@ -0,0 +1,15 @@
> > +# SPDX-License-Identifier: GPL-2.0-only
> > +if LIBNVDIMM
> > +
> > +config OCXL_PMEM
> > + tristate "OpenCAPI Persistent Memory"
> > + depends on LIBNVDIMM && PPC_POWERNV && PCI && EEH && ZONE_DEVICE && OCXL
>
> Does OXCL_PMEM itself have any CONFIG_ZONE_DEVICE dependencies? That's
> more a function of CONFIG_DEV_DAX and CONFIG_FS_DAX. Doesn't OCXL
> already depend on CONFIG_PCI?
>
>
> > + help
> > + Exposes devices that implement the OpenCAPI Storage Class Memory
> > + specification as persistent memory regions. You may also want
> > + DEV_DAX, DEV_DAX_PMEM & FS_DAX if you plan on using DAX devices
> > + stacked on top of this driver.
> > +
> > + Select N if unsure.
> > +
> > +endif
> > diff --git a/drivers/nvdimm/ocxl/Makefile b/drivers/nvdimm/ocxl/Makefile
> > new file mode 100644
> > index 000000000000..e0e8ade1987a
> > --- /dev/null
> > +++ b/drivers/nvdimm/ocxl/Makefile
> > @@ -0,0 +1,7 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +ccflags-$(CONFIG_PPC_WERROR) += -Werror
> > +
> > +obj-$(CONFIG_OCXL_PMEM) += ocxlpmem.o
> > +
> > +ocxlpmem-y := main.o
> > \ No newline at end of file
> > diff --git a/drivers/nvdimm/ocxl/main.c b/drivers/nvdimm/ocxl/main.c
> > new file mode 100644
> > index 000000000000..c0066fedf9cc
> > --- /dev/null
> > +++ b/drivers/nvdimm/ocxl/main.c
> > @@ -0,0 +1,476 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +// Copyright 2020 IBM Corp.
> > +
> > +/*
> > + * A driver for OpenCAPI devices that implement the Storage Class
> > + * Memory specification.
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <misc/ocxl.h>
> > +#include <linux/ndctl.h>
> > +#include <linux/mm_types.h>
> > +#include <linux/memory_hotplug.h>
> > +#include "ocxlpmem.h"
> > +
> > +static const struct pci_device_id pci_tbl[] = {
> > + { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0625), },
> > + { }
> > +};
> > +
> > +MODULE_DEVICE_TABLE(pci, pci_tbl);
> > +
> > +#define NUM_MINORS 256 // Total to reserve
> > +
> > +static dev_t ocxlpmem_dev;
> > +static struct class *ocxlpmem_class;
> > +static struct mutex minors_idr_lock;
> > +static struct idr minors_idr;
> > +
> > +/**
> > + * ndctl_config_write() - Handle a ND_CMD_SET_CONFIG_DATA command from ndctl
> > + * @ocxlpmem: the device metadata
> > + * @command: the incoming data to write
> > + * Return: 0 on success, negative on failure
> > + */
> > +static int ndctl_config_write(struct ocxlpmem *ocxlpmem,
> > + struct nd_cmd_set_config_hdr *command)
> > +{
> > + if (command->in_offset + command->in_length > LABEL_AREA_SIZE)
> > + return -EINVAL;
> > +
> > + memcpy_flushcache(ocxlpmem->metadata_addr + command->in_offset,
> > + command->in_buf, command->in_length);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * ndctl_config_read() - Handle a ND_CMD_GET_CONFIG_DATA command from ndctl
> > + * @ocxlpmem: the device metadata
> > + * @command: the read request
> > + * Return: 0 on success, negative on failure
> > + */
> > +static int ndctl_config_read(struct ocxlpmem *ocxlpmem,
> > + struct nd_cmd_get_config_data_hdr *command)
> > +{
> > + if (command->in_offset + command->in_length > LABEL_AREA_SIZE)
> > + return -EINVAL;
> > +
> > + memcpy_mcsafe(command->out_buf,
> > + ocxlpmem->metadata_addr + command->in_offset,
> > + command->in_length);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * ndctl_config_size() - Handle a ND_CMD_GET_CONFIG_SIZE command from ndctl
> > + * @command: the read request
> > + * Return: 0 on success, negative on failure
> > + */
> > +static int ndctl_config_size(struct nd_cmd_get_config_size *command)
> > +{
> > + command->status = 0;
> > + command->config_size = LABEL_AREA_SIZE;
> > + command->max_xfer = PAGE_SIZE;
> > +
> > + return 0;
> > +}
> > +
> > +static int ndctl(struct nvdimm_bus_descriptor *nd_desc,
> > + struct nvdimm *nvdimm,
> > + unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
> > +{
> > + struct ocxlpmem *ocxlpmem = container_of(nd_desc,
> > + struct ocxlpmem, bus_desc);
> > +
> > + switch (cmd) {
> > + case ND_CMD_GET_CONFIG_SIZE:
> > + *cmd_rc = ndctl_config_size(buf);
> > + return 0;
> > +
> > + case ND_CMD_GET_CONFIG_DATA:
> > + *cmd_rc = ndctl_config_read(ocxlpmem, buf);
> > + return 0;
> > +
> > + case ND_CMD_SET_CONFIG_DATA:
> > + *cmd_rc = ndctl_config_write(ocxlpmem, buf);
> > + return 0;
> > +
> > + default:
> > + return -ENOTTY;
> > + }
> > +}
> > +
> > +/**
> > + * reserve_metadata() - Reserve space for nvdimm metadata
> > + * @ocxlpmem: the device metadata
> > + * @lpc_mem: The resource representing the LPC memory of the OpenCAPI device
> > + */
> > +static int reserve_metadata(struct ocxlpmem *ocxlpmem,
> > + struct resource *lpc_mem)
> > +{
> > + ocxlpmem->metadata_addr = devm_memremap(&ocxlpmem->dev, lpc_mem->start,
> > + LABEL_AREA_SIZE, MEMREMAP_WB);
> > + if (IS_ERR(ocxlpmem->metadata_addr))
> > + return PTR_ERR(ocxlpmem->metadata_addr);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * register_lpc_mem() - Discover persistent memory on a device and register it with the NVDIMM subsystem
> > + * @ocxlpmem: the device metadata
> > + * Return: 0 on success
> > + */
> > +static int register_lpc_mem(struct ocxlpmem *ocxlpmem)
> > +{
> > + struct nd_region_desc region_desc;
> > + struct nd_mapping_desc nd_mapping_desc;
> > + struct resource *lpc_mem;
> > + const struct ocxl_afu_config *config;
> > + const struct ocxl_fn_config *fn_config;
> > + int rc;
> > + unsigned long nvdimm_cmd_mask = 0;
> > + unsigned long nvdimm_flags = 0;
> > + int target_node;
> > + char serial[16 + 1];
> > +
> > + // Set up the reserved metadata area
> > + rc = ocxl_afu_map_lpc_mem(ocxlpmem->ocxl_afu);
> > + if (rc < 0)
> > + return rc;
> > +
> > + lpc_mem = ocxl_afu_lpc_mem(ocxlpmem->ocxl_afu);
> > + if (!lpc_mem || !lpc_mem->start)
> > + return -EINVAL;
> > +
> > + config = ocxl_afu_config(ocxlpmem->ocxl_afu);
> > + fn_config = ocxl_function_config(ocxlpmem->ocxl_fn);
> > +
> > + rc = reserve_metadata(ocxlpmem, lpc_mem);
> > + if (rc)
> > + return rc;
> > +
> > + ocxlpmem->bus_desc.provider_name = "ocxlpmem";
> > + ocxlpmem->bus_desc.ndctl = ndctl;
> > + ocxlpmem->bus_desc.module = THIS_MODULE;
> > +
> > + ocxlpmem->nvdimm_bus = nvdimm_bus_register(&ocxlpmem->dev,
> > + &ocxlpmem->bus_desc);
> > + if (!ocxlpmem->nvdimm_bus)
> > + return -EINVAL;
> > +
> > + ocxlpmem->pmem_res.start = (u64)lpc_mem->start + LABEL_AREA_SIZE;
> > + ocxlpmem->pmem_res.end = (u64)lpc_mem->start + config->lpc_mem_size - 1;
> > + ocxlpmem->pmem_res.name = "OpenCAPI persistent memory";
> > +
> > + set_bit(ND_CMD_GET_CONFIG_SIZE, &nvdimm_cmd_mask);
> > + set_bit(ND_CMD_GET_CONFIG_DATA, &nvdimm_cmd_mask);
> > + set_bit(ND_CMD_SET_CONFIG_DATA, &nvdimm_cmd_mask);
> > +
> > + set_bit(NDD_ALIASING, &nvdimm_flags);
> > +
> > + snprintf(serial, sizeof(serial), "%llx", fn_config->serial);
> > + nd_mapping_desc.nvdimm = nvdimm_create(ocxlpmem->nvdimm_bus, ocxlpmem,
> > + NULL, nvdimm_flags,
> > + nvdimm_cmd_mask, 0, NULL);
> > + if (!nd_mapping_desc.nvdimm)
> > + return -ENOMEM;
> > +
> > + if (nvdimm_bus_check_dimm_count(ocxlpmem->nvdimm_bus, 1))
> > + return -EINVAL;
> > +
> > + nd_mapping_desc.start = ocxlpmem->pmem_res.start;
> > + nd_mapping_desc.size = resource_size(&ocxlpmem->pmem_res);
> > + nd_mapping_desc.position = 0;
> > +
> > + ocxlpmem->nd_set.cookie1 = fn_config->serial;
> > + ocxlpmem->nd_set.cookie2 = fn_config->serial;
> > +
> > + target_node = of_node_to_nid(ocxlpmem->pdev->dev.of_node);
> > +
> > + memset(®ion_desc, 0, sizeof(region_desc));
> > + region_desc.res = &ocxlpmem->pmem_res;
> > + region_desc.numa_node = NUMA_NO_NODE;
> > + region_desc.target_node = target_node;
> > + region_desc.num_mappings = 1;
> > + region_desc.mapping = &nd_mapping_desc;
> > + region_desc.nd_set = &ocxlpmem->nd_set;
> > +
> > + set_bit(ND_REGION_PAGEMAP, ®ion_desc.flags);
> > + /*
> > + * NB: libnvdimm copies the data from ndr_desc into it's own
> > + * structures so passing a stack pointer is fine.
> > + */
> > + ocxlpmem->nd_region = nvdimm_pmem_region_create(ocxlpmem->nvdimm_bus,
> > + ®ion_desc);
> > + if (!ocxlpmem->nd_region)
> > + return -EINVAL;
> > +
> > + dev_info(&ocxlpmem->dev,
> > + "Onlining %lluMB of persistent memory\n",
> > + nd_mapping_desc.size / SZ_1M);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * allocate_minor() - Allocate a minor number to use for an OpenCAPI pmem device
> > + * @ocxlpmem: the device metadata
> > + * Return: the allocated minor number
> > + */
> > +static int allocate_minor(struct ocxlpmem *ocxlpmem)
> > +{
> > + int minor;
> > +
> > + mutex_lock(&minors_idr_lock);
> > + minor = idr_alloc(&minors_idr, ocxlpmem, 0, NUM_MINORS, GFP_KERNEL);
> > + mutex_unlock(&minors_idr_lock);
> > + return minor;
> > +}
> > +
> > +static void free_minor(struct ocxlpmem *ocxlpmem)
> > +{
> > + mutex_lock(&minors_idr_lock);
> > + idr_remove(&minors_idr, MINOR(ocxlpmem->dev.devt));
> > + mutex_unlock(&minors_idr_lock);
> > +}
> > +
> > +/**
> > + * free_ocxlpmem() - Free all members of an ocxlpmem struct
> > + * @ocxlpmem: the device struct to clear
> > + */
> > +static void free_ocxlpmem(struct ocxlpmem *ocxlpmem)
> > +{
> > + int rc;
> > +
> > + free_minor(ocxlpmem);
> > +
> > + if (ocxlpmem->ocxl_context) {
> > + rc = ocxl_context_detach(ocxlpmem->ocxl_context);
> > + if (rc == -EBUSY)
> > + dev_warn(&ocxlpmem->dev, "Timeout detaching ocxl context\n");
> > + else
> > + ocxl_context_free(ocxlpmem->ocxl_context);
> > + }
> > +
> > + if (ocxlpmem->ocxl_afu)
> > + ocxl_afu_put(ocxlpmem->ocxl_afu);
> > +
> > + if (ocxlpmem->ocxl_fn)
> > + ocxl_function_close(ocxlpmem->ocxl_fn);
> > +
> > + pci_dev_put(ocxlpmem->pdev);
> > +
> > + kfree(ocxlpmem);
> > +}
> > +
> > +/**
> > + * free_ocxlpmem_dev() - Free an OpenCAPI persistent memory device
> > + * @dev: The device struct
> > + */
> > +static void free_ocxlpmem_dev(struct device *dev)
> > +{
> > + struct ocxlpmem *ocxlpmem = container_of(dev, struct ocxlpmem, dev);
> > +
> > + free_ocxlpmem(ocxlpmem);
> > +}
> > +
> > +/**
> > + * ocxlpmem_register() - Register an OpenCAPI pmem device with the kernel
> > + * @ocxlpmem: the device metadata
> > + * Return: 0 on success, negative on failure
> > + */
> > +static int ocxlpmem_register(struct ocxlpmem *ocxlpmem)
> > +{
> > + int rc;
> > + int minor = allocate_minor(ocxlpmem);
> > +
> > + if (minor < 0)
> > + return minor;
> > +
> > + ocxlpmem->dev.release = free_ocxlpmem_dev;
> > + rc = dev_set_name(&ocxlpmem->dev, "ocxlpmem%d", minor);
> > + if (rc < 0)
> > + return rc;
> > +
> > + ocxlpmem->dev.devt = MKDEV(MAJOR(ocxlpmem_dev), minor);
> > + ocxlpmem->dev.class = ocxlpmem_class;
> > + ocxlpmem->dev.parent = &ocxlpmem->pdev->dev;
> > +
> > + return device_register(&ocxlpmem->dev);
>
> You lost me, why does this need it's own ioctl path and device node?
> I'd expect you you'd tunnel the commands you need through the existing
> infrastructure ideally with an eye for cross-arch compatibility. This
> is a fundamental concern that probably has significant implications
> for what follows.
At a minimum this device registration should move to the end of the
patchset once all the libnvdimm generic enabling is done. Even then I
think the libnvdimm core has all the hooks you need to provide device
specific enabling *through* the existing interfaces. Have a look at
the how the ACPI NFIT bus driver provides "nfit/" scoped sysfs
attributes and tunnels "struct nd_cmd_pkg" ioctl invocations to either
the bus or "dimm" level device objects. The dimm security model is an
example of an implementation that wraps a libnvdimm-generic sysfs
front-end to an intel-specific-device backend. It would be unfortunate
to need to invent another ABI.
^ permalink raw reply
* Re: [PATCH v2 4/4] hugetlbfs: clean up command line processing
From: Randy Dunlap @ 2020-04-01 18:55 UTC (permalink / raw)
To: Mike Kravetz, linux-mm, linux-kernel, linux-arm-kernel,
linuxppc-dev, linux-riscv, linux-s390, sparclinux, linux-doc
Cc: Mina Almasry, Albert Ou, Andrew Morton, Vasily Gorbik,
Jonathan Corbet, Catalin Marinas, Dave Hansen, Heiko Carstens,
Christian Borntraeger, Ingo Molnar, Palmer Dabbelt, Paul Walmsley,
Paul Mackerras, Thomas Gleixner, Longpeng, Will Deacon,
David S . Miller
In-Reply-To: <20200401183819.20647-5-mike.kravetz@oracle.com>
On 4/1/20 11:38 AM, Mike Kravetz wrote:
> With all hugetlb page processing done in a single file clean up code.
> - Make code match desired semantics
> - Update documentation with semantics
> - Make all warnings and errors messages start with 'HugeTLB:'.
> - Consistently name command line parsing routines.
> - Check for hugepages_supported() before processing parameters.
> - Add comments to code
> - Describe some of the subtle interactions
> - Describe semantics of command line arguments
>
> Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
> ---
Hi Mike,
One nit, please see below:
> .../admin-guide/kernel-parameters.txt | 35 ++++---
> Documentation/admin-guide/mm/hugetlbpage.rst | 44 +++++++++
> mm/hugetlb.c | 96 +++++++++++++++----
> 3 files changed, 142 insertions(+), 33 deletions(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 1bd5454b5e5f..de653cfe1726 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -832,12 +832,15 @@
> See also Documentation/networking/decnet.txt.
>
> default_hugepagesz=
> - [same as hugepagesz=] The size of the default
> - HugeTLB page size. This is the size represented by
> - the legacy /proc/ hugepages APIs, used for SHM, and
> - default size when mounting hugetlbfs filesystems.
> - Defaults to the default architecture's huge page size
> - if not specified.
> + [HW] The size of the default HugeTLB page size. This
Drop one "size" above?
> + is the size represented by the legacy /proc/ hugepages
> + APIs. In addition, this is the default hugetlb size
> + used for shmget(), mmap() and mounting hugetlbfs
> + filesystems. If not specified, defaults to the
> + architecture's default huge page size. Huge page
> + sizes are architecture dependent. See also
> + Documentation/admin-guide/mm/hugetlbpage.rst.
> + Format: size[KMG]
--
~Randy
^ permalink raw reply
* [PATCH v2 0/4] Clean up hugetlb boot command line processing
From: Mike Kravetz @ 2020-04-01 18:38 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-doc
Cc: Mina Almasry, Albert Ou, Andrew Morton, Vasily Gorbik,
Jonathan Corbet, Catalin Marinas, Dave Hansen, Heiko Carstens,
Christian Borntraeger, Ingo Molnar, Palmer Dabbelt, Paul Walmsley,
Paul Mackerras, Thomas Gleixner, Longpeng, Will Deacon,
David S . Miller, Mike Kravetz
v2 -
Fix build errors with patch 1 (Will)
Change arch_hugetlb_valid_size arg to unsigned long and remove
irrelevant 'extern' keyword (Christophe)
Documentation and other misc changes (Randy, Christophe, Mina)
Do not process command line options if !hugepages_supported()
(Dave, but it sounds like we may want to additional changes to
hugepages_supported() for x86? If that is needed I would prefer
a separate patch.)
Longpeng(Mike) reported a weird message from hugetlb command line processing
and proposed a solution [1]. While the proposed patch does address the
specific issue, there are other related issues in command line processing.
As hugetlbfs evolved, updates to command line processing have been made to
meet immediate needs and not necessarily in a coordinated manner. The result
is that some processing is done in arch specific code, some is done in arch
independent code and coordination is problematic. Semantics can vary between
architectures.
The patch series does the following:
- Define arch specific arch_hugetlb_valid_size routine used to validate
passed huge page sizes.
- Move hugepagesz= command line parsing out of arch specific code and into
an arch independent routine.
- Clean up command line processing to follow desired semantics and
document those semantics.
[1] https://lore.kernel.org/linux-mm/20200305033014.1152-1-longpeng2@huawei.com
Mike Kravetz (4):
hugetlbfs: add arch_hugetlb_valid_size
hugetlbfs: move hugepagesz= parsing to arch independent code
hugetlbfs: remove hugetlb_add_hstate() warning for existing hstate
hugetlbfs: clean up command line processing
.../admin-guide/kernel-parameters.txt | 35 +++--
Documentation/admin-guide/mm/hugetlbpage.rst | 44 ++++++
arch/arm64/include/asm/hugetlb.h | 2 +
arch/arm64/mm/hugetlbpage.c | 30 +---
arch/powerpc/include/asm/hugetlb.h | 3 +
arch/powerpc/mm/hugetlbpage.c | 30 ++--
arch/riscv/include/asm/hugetlb.h | 3 +
arch/riscv/mm/hugetlbpage.c | 24 +--
arch/s390/include/asm/hugetlb.h | 3 +
arch/s390/mm/hugetlbpage.c | 24 +--
arch/sparc/include/asm/hugetlb.h | 3 +
arch/sparc/mm/init_64.c | 43 ++----
arch/x86/include/asm/hugetlb.h | 5 +
arch/x86/mm/hugetlbpage.c | 23 +--
include/linux/hugetlb.h | 8 +-
mm/hugetlb.c | 141 ++++++++++++++----
16 files changed, 252 insertions(+), 169 deletions(-)
--
2.25.1
^ permalink raw reply
* [PATCH v2 1/4] hugetlbfs: add arch_hugetlb_valid_size
From: Mike Kravetz @ 2020-04-01 18:38 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-doc
Cc: Mina Almasry, Albert Ou, Andrew Morton, Vasily Gorbik,
Jonathan Corbet, Catalin Marinas, Dave Hansen, Heiko Carstens,
Christian Borntraeger, Ingo Molnar, Palmer Dabbelt, Paul Walmsley,
Paul Mackerras, Thomas Gleixner, Longpeng, Will Deacon,
David S . Miller, Mike Kravetz
In-Reply-To: <20200401183819.20647-1-mike.kravetz@oracle.com>
The architecture independent routine hugetlb_default_setup sets up
the default huge pages size. It has no way to verify if the passed
value is valid, so it accepts it and attempts to validate at a later
time. This requires undocumented cooperation between the arch specific
and arch independent code.
For architectures that support more than one huge page size, provide
a routine arch_hugetlb_valid_size to validate a huge page size.
hugetlb_default_setup can use this to validate passed values.
arch_hugetlb_valid_size will also be used in a subsequent patch to
move processing of the "hugepagesz=" in arch specific code to a common
routine in arch independent code.
Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
---
arch/arm64/include/asm/hugetlb.h | 2 ++
arch/arm64/mm/hugetlbpage.c | 17 +++++++++++++----
arch/powerpc/include/asm/hugetlb.h | 3 +++
arch/powerpc/mm/hugetlbpage.c | 20 +++++++++++++-------
arch/riscv/include/asm/hugetlb.h | 3 +++
arch/riscv/mm/hugetlbpage.c | 26 +++++++++++++++++---------
arch/s390/include/asm/hugetlb.h | 3 +++
arch/s390/mm/hugetlbpage.c | 16 ++++++++++++----
arch/sparc/include/asm/hugetlb.h | 3 +++
arch/sparc/mm/init_64.c | 24 ++++++++++++++++--------
arch/x86/include/asm/hugetlb.h | 5 +++++
arch/x86/mm/hugetlbpage.c | 17 +++++++++++++----
include/linux/hugetlb.h | 7 +++++++
mm/hugetlb.c | 15 ++++++++++++---
14 files changed, 122 insertions(+), 39 deletions(-)
diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index 2eb6c234d594..81606223494f 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -59,6 +59,8 @@ extern void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
extern void set_huge_swap_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte, unsigned long sz);
#define set_huge_swap_pte_at set_huge_swap_pte_at
+bool __init arch_hugetlb_valid_size(unsigned long size);
+#define arch_hugetlb_valid_size arch_hugetlb_valid_size
#include <asm-generic/hugetlb.h>
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index bbeb6a5a6ba6..069b96ee2aec 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -462,17 +462,26 @@ static int __init hugetlbpage_init(void)
}
arch_initcall(hugetlbpage_init);
-static __init int setup_hugepagesz(char *opt)
+bool __init arch_hugetlb_valid_size(unsigned long size)
{
- unsigned long ps = memparse(opt, &opt);
-
- switch (ps) {
+ switch (size) {
#ifdef CONFIG_ARM64_4K_PAGES
case PUD_SIZE:
#endif
case CONT_PMD_SIZE:
case PMD_SIZE:
case CONT_PTE_SIZE:
+ return true;
+ }
+
+ return false;
+}
+
+static __init int setup_hugepagesz(char *opt)
+{
+ unsigned long ps = memparse(opt, &opt);
+
+ if (arch_hugetlb_valid_size(ps)) {
add_huge_page_size(ps);
return 1;
}
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h
index bd6504c28c2f..19b453ee1431 100644
--- a/arch/powerpc/include/asm/hugetlb.h
+++ b/arch/powerpc/include/asm/hugetlb.h
@@ -64,6 +64,9 @@ static inline void arch_clear_hugepage_flags(struct page *page)
{
}
+#define arch_hugetlb_valid_size arch_hugetlb_valid_size
+bool __init arch_hugetlb_valid_size(unsigned long size);
+
#include <asm-generic/hugetlb.h>
#else /* ! CONFIG_HUGETLB_PAGE */
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 33b3461d91e8..de54d2a37830 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -558,7 +558,7 @@ unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
return vma_kernel_pagesize(vma);
}
-static int __init add_huge_page_size(unsigned long long size)
+bool __init arch_hugetlb_valid_size(unsigned long size)
{
int shift = __ffs(size);
int mmu_psize;
@@ -566,20 +566,26 @@ static int __init add_huge_page_size(unsigned long long size)
/* Check that it is a page size supported by the hardware and
* that it fits within pagetable and slice limits. */
if (size <= PAGE_SIZE || !is_power_of_2(size))
- return -EINVAL;
+ return false;
mmu_psize = check_and_get_huge_psize(shift);
if (mmu_psize < 0)
- return -EINVAL;
+ return false;
BUG_ON(mmu_psize_defs[mmu_psize].shift != shift);
- /* Return if huge page size has already been setup */
- if (size_to_hstate(size))
- return 0;
+ return true;
+}
- hugetlb_add_hstate(shift - PAGE_SHIFT);
+static int __init add_huge_page_size(unsigned long long size)
+{
+ int shift = __ffs(size);
+
+ if (!arch_hugetlb_valid_size((unsigned long)size))
+ return -EINVAL;
+ if (!size_to_hstate(size))
+ hugetlb_add_hstate(shift - PAGE_SHIFT);
return 0;
}
diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h
index 728a5db66597..a6c414fa5b82 100644
--- a/arch/riscv/include/asm/hugetlb.h
+++ b/arch/riscv/include/asm/hugetlb.h
@@ -5,6 +5,9 @@
#include <asm-generic/hugetlb.h>
#include <asm/page.h>
+bool __init arch_hugetlb_valid_size(unsigned long size);
+#define arch_hugetlb_valid_size arch_hugetlb_valid_size
+
static inline int is_hugepage_only_range(struct mm_struct *mm,
unsigned long addr,
unsigned long len) {
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index a6189ed36c5f..da1f516bc451 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -12,21 +12,29 @@ int pmd_huge(pmd_t pmd)
return pmd_leaf(pmd);
}
+bool __init arch_hugetlb_valid_size(unsigned long size)
+{
+ if (size == HPAGE_SIZE)
+ return true;
+ else if (IS_ENABLED(CONFIG_64BIT) && size == PUD_SIZE)
+ return true;
+ else
+ return false;
+}
+
static __init int setup_hugepagesz(char *opt)
{
unsigned long ps = memparse(opt, &opt);
- if (ps == HPAGE_SIZE) {
- hugetlb_add_hstate(HPAGE_SHIFT - PAGE_SHIFT);
- } else if (IS_ENABLED(CONFIG_64BIT) && ps == PUD_SIZE) {
- hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
- } else {
- hugetlb_bad_size();
- pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
- return 0;
+ if (arch_hugetlb_valid_size(ps)) {
+ hugetlb_add_hstate(ilog2(ps) - PAGE_SHIFT);
+ return 1;
}
- return 1;
+ hugetlb_bad_size();
+ pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
+ return 0;
+
}
__setup("hugepagesz=", setup_hugepagesz);
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h
index de8f0bf5f238..f49981c00e72 100644
--- a/arch/s390/include/asm/hugetlb.h
+++ b/arch/s390/include/asm/hugetlb.h
@@ -15,6 +15,9 @@
#define hugetlb_free_pgd_range free_pgd_range
#define hugepages_supported() (MACHINE_HAS_EDAT1)
+bool __init arch_hugetlb_valid_size(unsigned long size);
+#define arch_hugetlb_valid_size arch_hugetlb_valid_size
+
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte);
pte_t huge_ptep_get(pte_t *ptep);
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index f01daddcbc5e..ac25b207624c 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -251,16 +251,24 @@ follow_huge_pud(struct mm_struct *mm, unsigned long address,
return pud_page(*pud) + ((address & ~PUD_MASK) >> PAGE_SHIFT);
}
+bool __init arch_hugetlb_valid_size(unsigned long size)
+{
+ if (MACHINE_HAS_EDAT1 && size == PMD_SIZE)
+ return true;
+ else if (MACHINE_HAS_EDAT2 && size == PUD_SIZE)
+ return true;
+ else
+ return false;
+}
+
static __init int setup_hugepagesz(char *opt)
{
unsigned long size;
char *string = opt;
size = memparse(opt, &opt);
- if (MACHINE_HAS_EDAT1 && size == PMD_SIZE) {
- hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
- } else if (MACHINE_HAS_EDAT2 && size == PUD_SIZE) {
- hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
+ if (arch_hugetlb_valid_size(size)) {
+ hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
} else {
hugetlb_bad_size();
pr_err("hugepagesz= specifies an unsupported page size %s\n",
diff --git a/arch/sparc/include/asm/hugetlb.h b/arch/sparc/include/asm/hugetlb.h
index 3963f80d1cb3..a88668b455d3 100644
--- a/arch/sparc/include/asm/hugetlb.h
+++ b/arch/sparc/include/asm/hugetlb.h
@@ -10,6 +10,9 @@ struct pud_huge_patch_entry {
unsigned int insn;
};
extern struct pud_huge_patch_entry __pud_huge_patch, __pud_huge_patch_end;
+
+bool __init arch_hugetlb_valid_size(unsigned long size);
+#define arch_hugetlb_valid_size arch_hugetlb_valid_size
#endif
#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 1cf0d666dea3..2bfe8e22b706 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -360,16 +360,11 @@ static void __init pud_huge_patch(void)
__asm__ __volatile__("flush %0" : : "r" (addr));
}
-static int __init setup_hugepagesz(char *string)
+bool __init arch_hugetlb_valid_size(unsigned long size)
{
- unsigned long long hugepage_size;
- unsigned int hugepage_shift;
+ unsigned int hugepage_shift = ilog2(size);
unsigned short hv_pgsz_idx;
unsigned int hv_pgsz_mask;
- int rc = 0;
-
- hugepage_size = memparse(string, &string);
- hugepage_shift = ilog2(hugepage_size);
switch (hugepage_shift) {
case HPAGE_16GB_SHIFT:
@@ -397,7 +392,20 @@ static int __init setup_hugepagesz(char *string)
hv_pgsz_mask = 0;
}
- if ((hv_pgsz_mask & cpu_pgsz_mask) == 0U) {
+ if ((hv_pgsz_mask & cpu_pgsz_mask) == 0U)
+ return false;
+
+ return true;
+}
+
+static int __init setup_hugepagesz(char *string)
+{
+ unsigned long long hugepage_size;
+ int rc = 0;
+
+ hugepage_size = memparse(string, &string);
+
+ if (!arch_hugetlb_valid_size((unsigned long)hugepage_size)) {
hugetlb_bad_size();
pr_err("hugepagesz=%llu not supported by MMU.\n",
hugepage_size);
diff --git a/arch/x86/include/asm/hugetlb.h b/arch/x86/include/asm/hugetlb.h
index f65cfb48cfdd..53ae4df41433 100644
--- a/arch/x86/include/asm/hugetlb.h
+++ b/arch/x86/include/asm/hugetlb.h
@@ -7,6 +7,11 @@
#define hugepages_supported() boot_cpu_has(X86_FEATURE_PSE)
+#ifdef CONFIG_X86_64
+bool __init arch_hugetlb_valid_size(unsigned long size);
+#define arch_hugetlb_valid_size arch_hugetlb_valid_size
+#endif
+
static inline int is_hugepage_only_range(struct mm_struct *mm,
unsigned long addr,
unsigned long len) {
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 5bfd5aef5378..1c4372bfe782 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -181,13 +181,22 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
#endif /* CONFIG_HUGETLB_PAGE */
#ifdef CONFIG_X86_64
+bool __init arch_hugetlb_valid_size(unsigned long size)
+{
+ if (size == PMD_SIZE)
+ return true;
+ else if (size == PUD_SIZE && boot_cpu_has(X86_FEATURE_GBPAGES))
+ return true;
+ else
+ return false;
+}
+
static __init int setup_hugepagesz(char *opt)
{
unsigned long ps = memparse(opt, &opt);
- if (ps == PMD_SIZE) {
- hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
- } else if (ps == PUD_SIZE && boot_cpu_has(X86_FEATURE_GBPAGES)) {
- hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
+
+ if (arch_hugetlb_valid_size(ps)) {
+ hugetlb_add_hstate(ilog2(ps) - PAGE_SHIFT);
} else {
hugetlb_bad_size();
printk(KERN_ERR "hugepagesz: Unsupported page size %lu M\n",
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 2fc9bc91894e..962bb1e6682b 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -688,6 +688,13 @@ static inline spinlock_t *huge_pte_lockptr(struct hstate *h,
return &mm->page_table_lock;
}
+#ifndef arch_hugetlb_valid_size
+static inline bool arch_hugetlb_valid_size(unsigned long size)
+{
+ return size == HPAGE_SIZE;
+}
+#endif
+
#ifndef hugepages_supported
/*
* Some platform decide whether they support huge pages at boot
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 38c3363b46e1..e9d9d179cf12 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3324,12 +3324,21 @@ static int __init hugetlb_nrpages_setup(char *s)
}
__setup("hugepages=", hugetlb_nrpages_setup);
-static int __init hugetlb_default_setup(char *s)
+static int __init default_hugepagesz_setup(char *s)
{
- default_hstate_size = memparse(s, &s);
+ unsigned long size;
+
+ size = (unsigned long)memparse(s, NULL);
+
+ if (!arch_hugetlb_valid_size(size)) {
+ pr_err("HugeTLB: unsupported default_hugepagesz %s\n", s);
+ return 0;
+ }
+
+ default_hstate_size = size;
return 1;
}
-__setup("default_hugepagesz=", hugetlb_default_setup);
+__setup("default_hugepagesz=", default_hugepagesz_setup);
static unsigned int cpuset_mems_nr(unsigned int *array)
{
--
2.25.1
^ permalink raw reply related
* [PATCH v2 3/4] hugetlbfs: remove hugetlb_add_hstate() warning for existing hstate
From: Mike Kravetz @ 2020-04-01 18:38 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-doc
Cc: Mina Almasry, Albert Ou, Andrew Morton, Vasily Gorbik,
Jonathan Corbet, Catalin Marinas, Dave Hansen, Heiko Carstens,
Christian Borntraeger, Ingo Molnar, Palmer Dabbelt, Paul Walmsley,
Paul Mackerras, Thomas Gleixner, Longpeng, Will Deacon,
David S . Miller, Mike Kravetz
In-Reply-To: <20200401183819.20647-1-mike.kravetz@oracle.com>
The routine hugetlb_add_hstate prints a warning if the hstate already
exists. This was originally done as part of kernel command line
parsing. If 'hugepagesz=' was specified more than once, the warning
pr_warn("hugepagesz= specified twice, ignoring\n");
would be printed.
Some architectures want to enable all huge page sizes. They would
call hugetlb_add_hstate for all supported sizes. However, this was
done after command line processing and as a result hstates could have
already been created for some sizes. To make sure no warning were
printed, there would often be code like:
if (!size_to_hstate(size)
hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT)
The only time we want to print the warning is as the result of command
line processing. So, remove the warning from hugetlb_add_hstate and
add it to the single arch independent routine processing "hugepagesz=".
After this, calls to size_to_hstate() in arch specific code can be
removed and hugetlb_add_hstate can be called without worrying about
warning messages.
Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
---
arch/arm64/mm/hugetlbpage.c | 16 ++++------------
arch/powerpc/mm/hugetlbpage.c | 3 +--
arch/riscv/mm/hugetlbpage.c | 2 +-
arch/sparc/mm/init_64.c | 19 ++++---------------
arch/x86/mm/hugetlbpage.c | 2 +-
mm/hugetlb.c | 9 ++++++---
6 files changed, 17 insertions(+), 34 deletions(-)
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index f706b821aba6..21fa98b51e00 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -441,22 +441,14 @@ void huge_ptep_clear_flush(struct vm_area_struct *vma,
clear_flush(vma->vm_mm, addr, ptep, pgsize, ncontig);
}
-static void __init add_huge_page_size(unsigned long size)
-{
- if (size_to_hstate(size))
- return;
-
- hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
-}
-
static int __init hugetlbpage_init(void)
{
#ifdef CONFIG_ARM64_4K_PAGES
- add_huge_page_size(PUD_SIZE);
+ hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
#endif
- add_huge_page_size(CONT_PMD_SIZE);
- add_huge_page_size(PMD_SIZE);
- add_huge_page_size(CONT_PTE_SIZE);
+ hugetlb_add_hstate(CONT_PMD_SHIFT - PAGE_SHIFT);
+ hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
+ hugetlb_add_hstate(CONT_PTE_SHIFT - PAGE_SHIFT);
return 0;
}
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 2c3fa0a7787b..4d5ed1093615 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -584,8 +584,7 @@ static int __init add_huge_page_size(unsigned long long size)
if (!arch_hugetlb_valid_size((unsigned long)size))
return -EINVAL;
- if (!size_to_hstate(size))
- hugetlb_add_hstate(shift - PAGE_SHIFT);
+ hugetlb_add_hstate(shift - PAGE_SHIFT);
return 0;
}
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index 4e5d7e9f0eef..932dadfdca54 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -26,7 +26,7 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
static __init int gigantic_pages_init(void)
{
/* With CONTIG_ALLOC, we can allocate gigantic pages at runtime */
- if (IS_ENABLED(CONFIG_64BIT) && !size_to_hstate(1UL << PUD_SHIFT))
+ if (IS_ENABLED(CONFIG_64BIT))
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
return 0;
}
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 4618f96fd30f..ae819a16d07a 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -325,23 +325,12 @@ static void __update_mmu_tsb_insert(struct mm_struct *mm, unsigned long tsb_inde
}
#ifdef CONFIG_HUGETLB_PAGE
-static void __init add_huge_page_size(unsigned long size)
-{
- unsigned int order;
-
- if (size_to_hstate(size))
- return;
-
- order = ilog2(size) - PAGE_SHIFT;
- hugetlb_add_hstate(order);
-}
-
static int __init hugetlbpage_init(void)
{
- add_huge_page_size(1UL << HPAGE_64K_SHIFT);
- add_huge_page_size(1UL << HPAGE_SHIFT);
- add_huge_page_size(1UL << HPAGE_256MB_SHIFT);
- add_huge_page_size(1UL << HPAGE_2GB_SHIFT);
+ hugetlb_add_hstate(HPAGE_64K_SHIFT - PAGE_SHIFT);
+ hugetlb_add_hstate(HPAGE_SHIFT - PAGE_SHIFT);
+ hugetlb_add_hstate(HPAGE_256MB_SHIFT - PAGE_SHIFT);
+ hugetlb_add_hstate(HPAGE_2GB_SHIFT - PAGE_SHIFT);
return 0;
}
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 937d640a89e3..cf5781142716 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -195,7 +195,7 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
static __init int gigantic_pages_init(void)
{
/* With compaction or CMA we can allocate gigantic pages at runtime */
- if (boot_cpu_has(X86_FEATURE_GBPAGES) && !size_to_hstate(1UL << PUD_SHIFT))
+ if (boot_cpu_has(X86_FEATURE_GBPAGES))
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
return 0;
}
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 02b13ee26790..72a4343509d5 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3216,8 +3216,7 @@ static int __init hugetlb_init(void)
}
default_hstate_size = HPAGE_SIZE;
- if (!size_to_hstate(default_hstate_size))
- hugetlb_add_hstate(HUGETLB_PAGE_ORDER);
+ hugetlb_add_hstate(HUGETLB_PAGE_ORDER);
}
default_hstate_idx = hstate_index(size_to_hstate(default_hstate_size));
if (default_hstate_max_huge_pages) {
@@ -3255,7 +3254,6 @@ void __init hugetlb_add_hstate(unsigned int order)
unsigned long i;
if (size_to_hstate(PAGE_SIZE << order)) {
- pr_warn("hugepagesz= specified twice, ignoring\n");
return;
}
BUG_ON(hugetlb_max_hstate >= HUGE_MAX_HSTATE);
@@ -3330,6 +3328,11 @@ static int __init hugepagesz_setup(char *s)
return 0;
}
+ if (size_to_hstate(size)) {
+ pr_warn("HugeTLB: hugepagesz %s specified twice, ignoring\n", s);
+ return 0;
+ }
+
hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
return 1;
}
--
2.25.1
^ permalink raw reply related
* [PATCH v2 4/4] hugetlbfs: clean up command line processing
From: Mike Kravetz @ 2020-04-01 18:38 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-doc
Cc: Mina Almasry, Albert Ou, Andrew Morton, Vasily Gorbik,
Jonathan Corbet, Catalin Marinas, Dave Hansen, Heiko Carstens,
Christian Borntraeger, Ingo Molnar, Palmer Dabbelt, Paul Walmsley,
Paul Mackerras, Thomas Gleixner, Longpeng, Will Deacon,
David S . Miller, Mike Kravetz
In-Reply-To: <20200401183819.20647-1-mike.kravetz@oracle.com>
With all hugetlb page processing done in a single file clean up code.
- Make code match desired semantics
- Update documentation with semantics
- Make all warnings and errors messages start with 'HugeTLB:'.
- Consistently name command line parsing routines.
- Check for hugepages_supported() before processing parameters.
- Add comments to code
- Describe some of the subtle interactions
- Describe semantics of command line arguments
Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
---
.../admin-guide/kernel-parameters.txt | 35 ++++---
Documentation/admin-guide/mm/hugetlbpage.rst | 44 +++++++++
mm/hugetlb.c | 96 +++++++++++++++----
3 files changed, 142 insertions(+), 33 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 1bd5454b5e5f..de653cfe1726 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -832,12 +832,15 @@
See also Documentation/networking/decnet.txt.
default_hugepagesz=
- [same as hugepagesz=] The size of the default
- HugeTLB page size. This is the size represented by
- the legacy /proc/ hugepages APIs, used for SHM, and
- default size when mounting hugetlbfs filesystems.
- Defaults to the default architecture's huge page size
- if not specified.
+ [HW] The size of the default HugeTLB page size. This
+ is the size represented by the legacy /proc/ hugepages
+ APIs. In addition, this is the default hugetlb size
+ used for shmget(), mmap() and mounting hugetlbfs
+ filesystems. If not specified, defaults to the
+ architecture's default huge page size. Huge page
+ sizes are architecture dependent. See also
+ Documentation/admin-guide/mm/hugetlbpage.rst.
+ Format: size[KMG]
deferred_probe_timeout=
[KNL] Debugging option to set a timeout in seconds for
@@ -1480,13 +1483,19 @@
If enabled, boot-time allocation of gigantic hugepages
is skipped.
- hugepages= [HW,X86-32,IA-64] HugeTLB pages to allocate at boot.
- hugepagesz= [HW,IA-64,PPC,X86-64] The size of the HugeTLB pages.
- On x86-64 and powerpc, this option can be specified
- multiple times interleaved with hugepages= to reserve
- huge pages of different sizes. Valid pages sizes on
- x86-64 are 2M (when the CPU supports "pse") and 1G
- (when the CPU supports the "pdpe1gb" cpuinfo flag).
+ hugepages= [HW] Number of HugeTLB pages to allocate at boot.
+ If this follows hugepagesz (below), it specifies
+ the number of pages of hugepagesz to be allocated.
+ Format: <integer>
+ hugepagesz=
+ [HW] The size of the HugeTLB pages. This is used in
+ conjunction with hugepages (above) to allocate huge
+ pages of a specific size at boot. The pair
+ hugepagesz=X hugepages=Y can be specified once for
+ each supported huge page size. Huge page sizes are
+ architecture dependent. See also
+ Documentation/admin-guide/mm/hugetlbpage.rst.
+ Format: size[KMG]
hung_task_panic=
[KNL] Should the hung task detector generate panics.
diff --git a/Documentation/admin-guide/mm/hugetlbpage.rst b/Documentation/admin-guide/mm/hugetlbpage.rst
index 1cc0bc78d10e..de340c586995 100644
--- a/Documentation/admin-guide/mm/hugetlbpage.rst
+++ b/Documentation/admin-guide/mm/hugetlbpage.rst
@@ -100,6 +100,50 @@ with a huge page size selection parameter "hugepagesz=<size>". <size> must
be specified in bytes with optional scale suffix [kKmMgG]. The default huge
page size may be selected with the "default_hugepagesz=<size>" boot parameter.
+Hugetlb boot command line parameter semantics
+hugepagesz - Specify a huge page size. Used in conjunction with hugepages
+ parameter to preallocate a number of huge pages of the specified
+ size. Hence, hugepagesz and hugepages are typically specified in
+ pairs such as:
+ hugepagesz=2M hugepages=512
+ hugepagesz can only be specified once on the command line for a
+ specific huge page size. Valid huge page sizes are architecture
+ dependent.
+hugepages - Specify the number of huge pages to preallocate. This typically
+ follows a valid hugepagesz parameter. However, if hugepages is the
+ first or only hugetlb command line parameter it specifies the number
+ of huge pages of default size to allocate. The number of huge pages
+ of default size specified in this manner can be overwritten by a
+ hugepagesz,hugepages parameter pair for the default size.
+ For example, on an architecture with 2M default huge page size:
+ hugepages=256 hugepagesz=2M hugepages=512
+ will result in 512 2M huge pages being allocated. If a hugepages
+ parameter is preceded by an invalid hugepagesz parameter, it will
+ be ignored.
+default_hugepagesz - Specify the default huge page size. This parameter can
+ only be specified once on the command line. No other hugetlb command
+ line parameter is associated with default_hugepagesz. Therefore, it
+ can appear anywhere on the command line. If hugepages= is the first
+ hugetlb command line parameter, the specified number of huge pages
+ will apply to the default huge page size specified with
+ default_hugepagesz. For example,
+ hugepages=512 default_hugepagesz=2M
+ will result in 512 2M huge pages being allocated. However, specifying
+ the number of default huge pages in this manner will not apply to
+ gigantic huge pages. For example,
+ hugepages=10 default_hugepagesz=1G
+ or
+ default_hugepagesz=1G hugepages=10
+ will NOT result in the allocation of 10 1G huge pages. In order to
+ preallocate gigantic huge pages, there must be hugepagesz, hugepages
+ parameter pair. For example,
+ hugepagesz=1G hugepages=10 default_hugepagesz=1G
+ or
+ default_hugepagesz=1G hugepagesz=1G hugepages=10
+ will result 10 1G huge pages being allocated and the default huge
+ page size will be set to 1G. Valid default huge page size is
+ architecture dependent.
+
When multiple huge page sizes are supported, ``/proc/sys/vm/nr_hugepages``
indicates the current number of pre-allocated huge pages of the default size.
Thus, one can use the following command to dynamically allocate/deallocate
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 72a4343509d5..74ef53f7c5a7 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3054,7 +3054,7 @@ static void __init hugetlb_sysfs_init(void)
err = hugetlb_sysfs_add_hstate(h, hugepages_kobj,
hstate_kobjs, &hstate_attr_group);
if (err)
- pr_err("Hugetlb: Unable to add hstate %s", h->name);
+ pr_err("HugeTLB: Unable to add hstate %s", h->name);
}
}
@@ -3158,7 +3158,7 @@ static void hugetlb_register_node(struct node *node)
nhs->hstate_kobjs,
&per_node_hstate_attr_group);
if (err) {
- pr_err("Hugetlb: Unable to add hstate %s for node %d\n",
+ pr_err("HugeTLB: Unable to add hstate %s for node %d\n",
h->name, node->dev.id);
hugetlb_unregister_node(node);
break;
@@ -3209,19 +3209,35 @@ static int __init hugetlb_init(void)
if (!hugepages_supported())
return 0;
- if (!size_to_hstate(default_hstate_size)) {
- if (default_hstate_size != 0) {
- pr_err("HugeTLB: unsupported default_hugepagesz %lu. Reverting to %lu\n",
- default_hstate_size, HPAGE_SIZE);
- }
-
+ /*
+ * Make sure HPAGE_SIZE (HUGETLB_PAGE_ORDER) hstate exists. Some
+ * architectures depend on setup being done here.
+ *
+ * If a valid default huge page size was specified on the command line,
+ * add associated hstate if necessary. If not, set default_hstate_size
+ * to default size. default_hstate_idx is used at runtime to identify
+ * the default huge page size/hstate.
+ */
+ hugetlb_add_hstate(HUGETLB_PAGE_ORDER);
+ if (default_hstate_size)
+ hugetlb_add_hstate(ilog2(default_hstate_size) - PAGE_SHIFT);
+ else
default_hstate_size = HPAGE_SIZE;
- hugetlb_add_hstate(HUGETLB_PAGE_ORDER);
- }
default_hstate_idx = hstate_index(size_to_hstate(default_hstate_size));
+
+ /*
+ * default_hstate_max_huge_pages != 0 indicates a count (hugepages=)
+ * specified before a size (hugepagesz=). Use this count for the
+ * default huge page size, unless a specific value was specified for
+ * this size in a hugepagesz/hugepages pair.
+ */
if (default_hstate_max_huge_pages) {
if (!default_hstate.max_huge_pages)
- default_hstate.max_huge_pages = default_hstate_max_huge_pages;
+ default_hstate.max_huge_pages =
+ default_hstate_max_huge_pages;
+ else
+ pr_warn("HugeTLB: First hugepages=%lu ignored\n",
+ default_hstate_max_huge_pages);
}
hugetlb_init_hstates();
@@ -3274,20 +3290,31 @@ void __init hugetlb_add_hstate(unsigned int order)
parsed_hstate = h;
}
-static int __init hugetlb_nrpages_setup(char *s)
+/*
+ * hugepages command line processing
+ * hugepages normally follows a valid hugepagsz specification. If not, ignore
+ * the hugepages value. hugepages can also be the first huge page command line
+ * option in which case it specifies the number of huge pages for the default
+ * size.
+ */
+static int __init hugepages_setup(char *s)
{
unsigned long *mhp;
static unsigned long *last_mhp;
+ if (!hugepages_supported()) {
+ pr_warn("HugeTLB: huge pages not supported, ignoring hugepages = %s\n", s);
+ return 0;
+ }
+
if (!parsed_valid_hugepagesz) {
- pr_warn("hugepages = %s preceded by "
- "an unsupported hugepagesz, ignoring\n", s);
+ pr_warn("HugeTLB: hugepages = %s preceded by an unsupported hugepagesz, ignoring\n", s);
parsed_valid_hugepagesz = true;
- return 1;
+ return 0;
}
/*
- * !hugetlb_max_hstate means we haven't parsed a hugepagesz= parameter yet,
- * so this hugepages= parameter goes to the "default hstate".
+ * !hugetlb_max_hstate means we haven't parsed a hugepagesz= parameter
+ * yet, so this hugepages= parameter goes to the "default hstate".
*/
else if (!hugetlb_max_hstate)
mhp = &default_hstate_max_huge_pages;
@@ -3295,8 +3322,8 @@ static int __init hugetlb_nrpages_setup(char *s)
mhp = &parsed_hstate->max_huge_pages;
if (mhp == last_mhp) {
- pr_warn("hugepages= specified twice without interleaving hugepagesz=, ignoring\n");
- return 1;
+ pr_warn("HugeTLB: hugepages= specified twice without interleaving hugepagesz=, ignoring hugepages=%s\n", s);
+ return 0;
}
if (sscanf(s, "%lu", mhp) <= 0)
@@ -3314,12 +3341,24 @@ static int __init hugetlb_nrpages_setup(char *s)
return 1;
}
-__setup("hugepages=", hugetlb_nrpages_setup);
+__setup("hugepages=", hugepages_setup);
+/*
+ * hugepagesz command line processing
+ * A specific huge page size can only be specified once with hugepagesz.
+ * hugepagesz is followed by hugepages on the command line. The global
+ * variable 'parsed_valid_hugepagesz' is used to determine if prior
+ * hugepagesz argument was valid.
+ */
static int __init hugepagesz_setup(char *s)
{
unsigned long size;
+ if (!hugepages_supported()) {
+ pr_warn("HugeTLB: huge pages not supported, ignoring hugepagesz = %s\n", s);
+ return 0;
+ }
+
size = (unsigned long)memparse(s, NULL);
if (!arch_hugetlb_valid_size(size)) {
@@ -3329,19 +3368,31 @@ static int __init hugepagesz_setup(char *s)
}
if (size_to_hstate(size)) {
+ parsed_valid_hugepagesz = false;
pr_warn("HugeTLB: hugepagesz %s specified twice, ignoring\n", s);
return 0;
}
+ parsed_valid_hugepagesz = true;
hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
return 1;
}
__setup("hugepagesz=", hugepagesz_setup);
+/*
+ * default_hugepagesz command line input
+ * Only one instance of default_hugepagesz allowed on command line. Do not
+ * add hstate here as that will confuse hugepagesz/hugepages processing.
+ */
static int __init default_hugepagesz_setup(char *s)
{
unsigned long size;
+ if (!hugepages_supported()) {
+ pr_warn("HugeTLB: huge pages not supported, ignoring default_hugepagesz = %s\n", s);
+ return 0;
+ }
+
size = (unsigned long)memparse(s, NULL);
if (!arch_hugetlb_valid_size(size)) {
@@ -3349,6 +3400,11 @@ static int __init default_hugepagesz_setup(char *s)
return 0;
}
+ if (default_hstate_size) {
+ pr_err("HugeTLB: default_hugepagesz previously specified, ignoring %s\n", s);
+ return 0;
+ }
+
default_hstate_size = size;
return 1;
}
--
2.25.1
^ permalink raw reply related
* [PATCH v2 2/4] hugetlbfs: move hugepagesz= parsing to arch independent code
From: Mike Kravetz @ 2020-04-01 18:38 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-doc
Cc: Mina Almasry, Albert Ou, Andrew Morton, Vasily Gorbik,
Jonathan Corbet, Catalin Marinas, Dave Hansen, Heiko Carstens,
Christian Borntraeger, Ingo Molnar, Palmer Dabbelt, Paul Walmsley,
Paul Mackerras, Thomas Gleixner, Longpeng, Will Deacon,
David S . Miller, Mike Kravetz
In-Reply-To: <20200401183819.20647-1-mike.kravetz@oracle.com>
Now that architectures provide arch_hugetlb_valid_size(), parsing
of "hugepagesz=" can be done in architecture independent code.
Create a single routine to handle hugepagesz= parsing and remove
all arch specific routines. We can also remove the interface
hugetlb_bad_size() as this is no longer used outside arch independent
code.
This also provides consistent behavior of hugetlbfs command line
options. The hugepagesz= option should only be specified once for
a specific size, but some architectures allow multiple instances.
This appears to be more of an oversight when code was added by some
architectures to set up ALL huge pages sizes.
Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
---
arch/arm64/mm/hugetlbpage.c | 15 ---------------
arch/powerpc/mm/hugetlbpage.c | 15 ---------------
arch/riscv/mm/hugetlbpage.c | 16 ----------------
arch/s390/mm/hugetlbpage.c | 18 ------------------
arch/sparc/mm/init_64.c | 22 ----------------------
arch/x86/mm/hugetlbpage.c | 16 ----------------
include/linux/hugetlb.h | 1 -
mm/hugetlb.c | 23 +++++++++++++++++------
8 files changed, 17 insertions(+), 109 deletions(-)
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 069b96ee2aec..f706b821aba6 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -476,18 +476,3 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
return false;
}
-
-static __init int setup_hugepagesz(char *opt)
-{
- unsigned long ps = memparse(opt, &opt);
-
- if (arch_hugetlb_valid_size(ps)) {
- add_huge_page_size(ps);
- return 1;
- }
-
- hugetlb_bad_size();
- pr_err("hugepagesz: Unsupported page size %lu K\n", ps >> 10);
- return 0;
-}
-__setup("hugepagesz=", setup_hugepagesz);
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index de54d2a37830..2c3fa0a7787b 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -589,21 +589,6 @@ static int __init add_huge_page_size(unsigned long long size)
return 0;
}
-static int __init hugepage_setup_sz(char *str)
-{
- unsigned long long size;
-
- size = memparse(str, &str);
-
- if (add_huge_page_size(size) != 0) {
- hugetlb_bad_size();
- pr_err("Invalid huge page size specified(%llu)\n", size);
- }
-
- return 1;
-}
-__setup("hugepagesz=", hugepage_setup_sz);
-
static int __init hugetlbpage_init(void)
{
bool configured = false;
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index da1f516bc451..4e5d7e9f0eef 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -22,22 +22,6 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
return false;
}
-static __init int setup_hugepagesz(char *opt)
-{
- unsigned long ps = memparse(opt, &opt);
-
- if (arch_hugetlb_valid_size(ps)) {
- hugetlb_add_hstate(ilog2(ps) - PAGE_SHIFT);
- return 1;
- }
-
- hugetlb_bad_size();
- pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
- return 0;
-
-}
-__setup("hugepagesz=", setup_hugepagesz);
-
#ifdef CONFIG_CONTIG_ALLOC
static __init int gigantic_pages_init(void)
{
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index ac25b207624c..242dfc0d462d 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -261,24 +261,6 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
return false;
}
-static __init int setup_hugepagesz(char *opt)
-{
- unsigned long size;
- char *string = opt;
-
- size = memparse(opt, &opt);
- if (arch_hugetlb_valid_size(size)) {
- hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
- } else {
- hugetlb_bad_size();
- pr_err("hugepagesz= specifies an unsupported page size %s\n",
- string);
- return 0;
- }
- return 1;
-}
-__setup("hugepagesz=", setup_hugepagesz);
-
static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags)
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 2bfe8e22b706..4618f96fd30f 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -397,28 +397,6 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
return true;
}
-
-static int __init setup_hugepagesz(char *string)
-{
- unsigned long long hugepage_size;
- int rc = 0;
-
- hugepage_size = memparse(string, &string);
-
- if (!arch_hugetlb_valid_size((unsigned long)hugepage_size)) {
- hugetlb_bad_size();
- pr_err("hugepagesz=%llu not supported by MMU.\n",
- hugepage_size);
- goto out;
- }
-
- add_huge_page_size(hugepage_size);
- rc = 1;
-
-out:
- return rc;
-}
-__setup("hugepagesz=", setup_hugepagesz);
#endif /* CONFIG_HUGETLB_PAGE */
void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 1c4372bfe782..937d640a89e3 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -191,22 +191,6 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
return false;
}
-static __init int setup_hugepagesz(char *opt)
-{
- unsigned long ps = memparse(opt, &opt);
-
- if (arch_hugetlb_valid_size(ps)) {
- hugetlb_add_hstate(ilog2(ps) - PAGE_SHIFT);
- } else {
- hugetlb_bad_size();
- printk(KERN_ERR "hugepagesz: Unsupported page size %lu M\n",
- ps >> 20);
- return 0;
- }
- return 1;
-}
-__setup("hugepagesz=", setup_hugepagesz);
-
#ifdef CONFIG_CONTIG_ALLOC
static __init int gigantic_pages_init(void)
{
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 962bb1e6682b..d40340b13198 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -519,7 +519,6 @@ int huge_add_to_page_cache(struct page *page, struct address_space *mapping,
int __init __alloc_bootmem_huge_page(struct hstate *h);
int __init alloc_bootmem_huge_page(struct hstate *h);
-void __init hugetlb_bad_size(void);
void __init hugetlb_add_hstate(unsigned order);
struct hstate *size_to_hstate(unsigned long size);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index e9d9d179cf12..02b13ee26790 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3249,12 +3249,6 @@ static int __init hugetlb_init(void)
}
subsys_initcall(hugetlb_init);
-/* Should be called on processing a hugepagesz=... option */
-void __init hugetlb_bad_size(void)
-{
- parsed_valid_hugepagesz = false;
-}
-
void __init hugetlb_add_hstate(unsigned int order)
{
struct hstate *h;
@@ -3324,6 +3318,23 @@ static int __init hugetlb_nrpages_setup(char *s)
}
__setup("hugepages=", hugetlb_nrpages_setup);
+static int __init hugepagesz_setup(char *s)
+{
+ unsigned long size;
+
+ size = (unsigned long)memparse(s, NULL);
+
+ if (!arch_hugetlb_valid_size(size)) {
+ parsed_valid_hugepagesz = false;
+ pr_err("HugeTLB: unsupported hugepagesz %s\n", s);
+ return 0;
+ }
+
+ hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
+ return 1;
+}
+__setup("hugepagesz=", hugepagesz_setup);
+
static int __init default_hugepagesz_setup(char *s)
{
unsigned long size;
--
2.25.1
^ permalink raw reply related
* Re: [PATCHv4] powerpc/crashkernel: take "mem=" option into account
From: Hari Bathini @ 2020-04-01 18:36 UTC (permalink / raw)
To: Pingfan Liu, linuxppc-dev; +Cc: kexec
In-Reply-To: <1585749644-4148-1-git-send-email-kernelfans@gmail.com>
On 01/04/20 7:30 PM, Pingfan Liu wrote:
> 'mem=" option is an easy way to put high pressure on memory during some
> test. Hence after applying the memory limit, instead of total mem, the
> actual usable memory should be considered when reserving mem for
> crashkernel. Otherwise the boot up may experience OOM issue.
>
> E.g. it would reserve 4G prior to the change and 512M afterward, if passing
> crashkernel="2G-4G:384M,4G-16G:512M,16G-64G:1G,64G-128G:2G,128G-:4G", and
> mem=5G on a 256G machine.
>
> This issue is powerpc specific because it puts higher priority on fadump
> and kdump reservation than on "mem=". Referring the following code:
> if (fadump_reserve_mem() == 0)
> reserve_crashkernel();
> ...
> /* Ensure that total memory size is page-aligned. */
> limit = ALIGN(memory_limit ?: memblock_phys_mem_size(), PAGE_SIZE);
> memblock_enforce_memory_limit(limit);
>
> While on other arches, the effect of "mem=" takes a higher priority and pass
> through memblock_phys_mem_size() before calling reserve_crashkernel().
>> Signed-off-by: Pingfan Liu <kernelfans@gmail.com>
> To: linuxppc-dev@lists.ozlabs.org
> Cc: Hari Bathini <hbathini@linux.ibm.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: kexec@lists.infradead.org
> ---
> v3 -> v4: fix total_mem_sz based on adjusted memory_limit
Thanks for the update.
Reviewed-by: Hari Bathini <hbathini@linux.ibm.com>
^ permalink raw reply
* Re: [RFC PATCH 3/4] powerpc ppc-opcode: move ppc instuction encoding from test_emulate_step
From: Naveen N. Rao @ 2020-04-01 16:51 UTC (permalink / raw)
To: Balamuruhan S, mpe
Cc: jniethe5, linuxppc-dev, sandipan, paulus, ravi.bangoria
In-Reply-To: <20200320081837.1016820-4-bala24@linux.ibm.com>
Balamuruhan S wrote:
> Few ppc instructions are encoded in test_emulate_step.c, consolidate them to
> ppc-opcode.h, fix redefintion errors in bpf_jit caused due to this consolidation.
> Reuse the macros from ppc-opcode.h
>
> Signed-off-by: Balamuruhan S <bala24@linux.ibm.com>
> ---
> arch/powerpc/include/asm/ppc-opcode.h | 34 ++++++
> arch/powerpc/lib/test_emulate_step.c | 155 ++++++++++----------------
> arch/powerpc/net/bpf_jit.h | 8 --
> arch/powerpc/net/bpf_jit32.h | 10 +-
> arch/powerpc/net/bpf_jit64.h | 4 +-
> arch/powerpc/net/bpf_jit_comp.c | 2 +-
> arch/powerpc/net/bpf_jit_comp64.c | 14 +--
> 7 files changed, 105 insertions(+), 122 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
> index ea5e0f864b20..2ed8a285f1ec 100644
> --- a/arch/powerpc/include/asm/ppc-opcode.h
> +++ b/arch/powerpc/include/asm/ppc-opcode.h
> @@ -76,6 +76,9 @@
> #define __REGA0_R30 30
> #define __REGA0_R31 31
>
> +#define IMM_L(i) ((uintptr_t)(i) & 0xffff)
> +#define IMM_DS(i) ((uintptr_t)(i) & 0xfffc)
> +
> /* opcode and xopcode for instructions */
> #define OP_TRAP 3
> #define OP_TRAP_64 2
> @@ -614,6 +617,37 @@
> ___PPC_RA(vra) | \
> ___PPC_RB(vrb) | __PPC_RC21)
>
> +#define PPC_ENCODE_LD(r, base, i) (PPC_INST_LD | ___PPC_RT(r) | \
> + ___PPC_RA(base) | IMM_DS(i))
> +#define PPC_ENCODE_LWZ(r, base, i) (PPC_INST_LWZ | ___PPC_RT(r) | \
> + ___PPC_RA(base) | IMM_L(i))
> +#define PPC_ENCODE_LWZX(t, a, b) (PPC_INST_LWZX | ___PPC_RT(t) | \
> + ___PPC_RA(a) | ___PPC_RB(b))
> +#define PPC_ENCODE_STD(r, base, i) (PPC_INST_STD | ___PPC_RS(r) | \
> + ___PPC_RA(base) | IMM_DS(i))
> +#define PPC_ENCODE_STDCX(s, a, b) (PPC_INST_STDCX | ___PPC_RS(s) | \
> + ___PPC_RA(a) | ___PPC_RB(b))
> +#define PPC_ENCODE_LFSX(t, a, b) (PPC_INST_LFSX | ___PPC_RT(t) | \
> + ___PPC_RA(a) | ___PPC_RB(b))
> +#define PPC_ENCODE_STFSX(s, a, b) (PPC_INST_STFSX | ___PPC_RS(s) | \
> + ___PPC_RA(a) | ___PPC_RB(b))
> +#define PPC_ENCODE_LFDX(t, a, b) (PPC_INST_LFDX | ___PPC_RT(t) | \
> + ___PPC_RA(a) | ___PPC_RB(b))
> +#define PPC_ENCODE_STFDX(s, a, b) (PPC_INST_STFDX | ___PPC_RS(s) | \
> + ___PPC_RA(a) | ___PPC_RB(b))
> +#define PPC_ENCODE_LVX(t, a, b) (PPC_INST_LVX | ___PPC_RT(t) | \
> + ___PPC_RA(a) | ___PPC_RB(b))
> +#define PPC_ENCODE_STVX(s, a, b) (PPC_INST_STVX | ___PPC_RS(s) | \
> + ___PPC_RA(a) | ___PPC_RB(b))
> +#define PPC_ENCODE_ADD(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \
> + ___PPC_RA(a) | ___PPC_RB(b))
> +#define PPC_ENCODE_ADD_DOT(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \
> + ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
> +#define PPC_ENCODE_ADDC(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) | \
> + ___PPC_RA(a) | ___PPC_RB(b))
> +#define PPC_ENCODE_ADDC_DOT(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) | \
> + ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
> +
> #define PPC_CP_ABORT stringify_in_c(.long PPC_ENCODE_CP_ABORT)
> #define PPC_COPY(a, b) stringify_in_c(.long PPC_ENCODE_COPY(a, b))
> #define PPC_DARN(t, l) stringify_in_c(.long PPC_ENCODE_DARN(t, l))
> diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c
> index 53df4146dd32..45b485edfee1 100644
> --- a/arch/powerpc/lib/test_emulate_step.c
> +++ b/arch/powerpc/lib/test_emulate_step.c
> @@ -12,49 +12,6 @@
> #include <asm/ppc-opcode.h>
> #include <asm/code-patching.h>
>
> -#define IMM_L(i) ((uintptr_t)(i) & 0xffff)
> -#define IMM_DS(i) ((uintptr_t)(i) & 0xfffc)
> -
> -/*
> - * Defined with TEST_ prefix so it does not conflict with other
> - * definitions.
> - */
> -#define TEST_LD(r, base, i) (PPC_INST_LD | ___PPC_RT(r) | \
> - ___PPC_RA(base) | IMM_DS(i))
> -#define TEST_LWZ(r, base, i) (PPC_INST_LWZ | ___PPC_RT(r) | \
> - ___PPC_RA(base) | IMM_L(i))
> -#define TEST_LWZX(t, a, b) (PPC_INST_LWZX | ___PPC_RT(t) | \
> - ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_STD(r, base, i) (PPC_INST_STD | ___PPC_RS(r) | \
> - ___PPC_RA(base) | IMM_DS(i))
> -#define TEST_LDARX(t, a, b, eh) (PPC_INST_LDARX | ___PPC_RT(t) | \
> - ___PPC_RA(a) | ___PPC_RB(b) | \
> - __PPC_EH(eh))
> -#define TEST_STDCX(s, a, b) (PPC_INST_STDCX | ___PPC_RS(s) | \
> - ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_LFSX(t, a, b) (PPC_INST_LFSX | ___PPC_RT(t) | \
> - ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_STFSX(s, a, b) (PPC_INST_STFSX | ___PPC_RS(s) | \
> - ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_LFDX(t, a, b) (PPC_INST_LFDX | ___PPC_RT(t) | \
> - ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_STFDX(s, a, b) (PPC_INST_STFDX | ___PPC_RS(s) | \
> - ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_LVX(t, a, b) (PPC_INST_LVX | ___PPC_RT(t) | \
> - ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_STVX(s, a, b) (PPC_INST_STVX | ___PPC_RS(s) | \
> - ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_LXVD2X(s, a, b) (PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b))
> -#define TEST_STXVD2X(s, a, b) (PPC_INST_STXVD2X | VSX_XX1((s), R##a, R##b))
> -#define TEST_ADD(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \
> - ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_ADD_DOT(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \
> - ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
> -#define TEST_ADDC(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) | \
> - ___PPC_RA(a) | ___PPC_RB(b))
> -#define TEST_ADDC_DOT(t, a, b) (PPC_INST_ADDC | ___PPC_RT(t) | \
> - ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
> -
> #define MAX_SUBTESTS 16
>
> #define IGNORE_GPR(n) (0x1UL << (n))
> @@ -104,7 +61,7 @@ static void __init test_ld(void)
> regs.gpr[3] = (unsigned long) &a;
>
> /* ld r5, 0(r3) */
> - stepped = emulate_step(®s, TEST_LD(5, 3, 0));
> + stepped = emulate_step(®s, PPC_ENCODE_LD(5, 3, 0));
>
> if (stepped == 1 && regs.gpr[5] == a)
> show_result("ld", "PASS");
> @@ -122,7 +79,7 @@ static void __init test_lwz(void)
> regs.gpr[3] = (unsigned long) &a;
>
> /* lwz r5, 0(r3) */
> - stepped = emulate_step(®s, TEST_LWZ(5, 3, 0));
> + stepped = emulate_step(®s, PPC_ENCODE_LWZ(5, 3, 0));
>
> if (stepped == 1 && regs.gpr[5] == a)
> show_result("lwz", "PASS");
> @@ -142,7 +99,7 @@ static void __init test_lwzx(void)
> regs.gpr[5] = 0x8765;
>
> /* lwzx r5, r3, r4 */
> - stepped = emulate_step(®s, TEST_LWZX(5, 3, 4));
> + stepped = emulate_step(®s, PPC_ENCODE_LWZX(5, 3, 4));
> if (stepped == 1 && regs.gpr[5] == a[2])
> show_result("lwzx", "PASS");
> else
> @@ -160,7 +117,7 @@ static void __init test_std(void)
> regs.gpr[5] = 0x5678;
>
> /* std r5, 0(r3) */
> - stepped = emulate_step(®s, TEST_STD(5, 3, 0));
> + stepped = emulate_step(®s, PPC_ENCODE_STD(5, 3, 0));
> if (stepped == 1 && regs.gpr[5] == a)
> show_result("std", "PASS");
> else
> @@ -185,7 +142,7 @@ static void __init test_ldarx_stdcx(void)
> regs.gpr[5] = 0x5678;
>
> /* ldarx r5, r3, r4, 0 */
> - stepped = emulate_step(®s, TEST_LDARX(5, 3, 4, 0));
> + stepped = emulate_step(®s, PPC_ENCODE_LDARX(5, 3, 4, 0));
>
> /*
> * Don't touch 'a' here. Touching 'a' can do Load/store
> @@ -203,7 +160,7 @@ static void __init test_ldarx_stdcx(void)
> regs.gpr[5] = 0x9ABC;
>
> /* stdcx. r5, r3, r4 */
> - stepped = emulate_step(®s, TEST_STDCX(5, 3, 4));
> + stepped = emulate_step(®s, PPC_ENCODE_STDCX(5, 3, 4));
>
> /*
> * Two possible scenarios that indicates successful emulation
> @@ -243,7 +200,7 @@ static void __init test_lfsx_stfsx(void)
> regs.gpr[4] = 0;
>
> /* lfsx frt10, r3, r4 */
> - stepped = emulate_step(®s, TEST_LFSX(10, 3, 4));
> + stepped = emulate_step(®s, PPC_ENCODE_LFSX(10, 3, 4));
>
> if (stepped == 1)
> show_result("lfsx", "PASS");
> @@ -256,7 +213,7 @@ static void __init test_lfsx_stfsx(void)
> c.a = 678.91;
>
> /* stfsx frs10, r3, r4 */
> - stepped = emulate_step(®s, TEST_STFSX(10, 3, 4));
> + stepped = emulate_step(®s, PPC_ENCODE_STFSX(10, 3, 4));
>
> if (stepped == 1 && c.b == cached_b)
> show_result("stfsx", "PASS");
> @@ -286,7 +243,7 @@ static void __init test_lfdx_stfdx(void)
> regs.gpr[4] = 0;
>
> /* lfdx frt10, r3, r4 */
> - stepped = emulate_step(®s, TEST_LFDX(10, 3, 4));
> + stepped = emulate_step(®s, PPC_ENCODE_LFDX(10, 3, 4));
>
> if (stepped == 1)
> show_result("lfdx", "PASS");
> @@ -299,7 +256,7 @@ static void __init test_lfdx_stfdx(void)
> c.a = 987654.32;
>
> /* stfdx frs10, r3, r4 */
> - stepped = emulate_step(®s, TEST_STFDX(10, 3, 4));
> + stepped = emulate_step(®s, PPC_ENCODE_STFDX(10, 3, 4));
>
> if (stepped == 1 && c.b == cached_b)
> show_result("stfdx", "PASS");
> @@ -345,7 +302,7 @@ static void __init test_lvx_stvx(void)
> regs.gpr[4] = 0;
>
> /* lvx vrt10, r3, r4 */
> - stepped = emulate_step(®s, TEST_LVX(10, 3, 4));
> + stepped = emulate_step(®s, PPC_ENCODE_LVX(10, 3, 4));
>
> if (stepped == 1)
> show_result("lvx", "PASS");
> @@ -361,7 +318,7 @@ static void __init test_lvx_stvx(void)
> c.b[3] = 498532;
>
> /* stvx vrs10, r3, r4 */
> - stepped = emulate_step(®s, TEST_STVX(10, 3, 4));
> + stepped = emulate_step(®s, PPC_ENCODE_STVX(10, 3, 4));
>
> if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
> cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
> @@ -402,7 +359,7 @@ static void __init test_lxvd2x_stxvd2x(void)
> regs.gpr[4] = 0;
>
> /* lxvd2x vsr39, r3, r4 */
> - stepped = emulate_step(®s, TEST_LXVD2X(39, 3, 4));
> + stepped = emulate_step(®s, PPC_ENCODE_LXVD2X(39, R3, R4));
>
> if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
> show_result("lxvd2x", "PASS");
> @@ -422,7 +379,7 @@ static void __init test_lxvd2x_stxvd2x(void)
> c.b[3] = 4;
>
> /* stxvd2x vsr39, r3, r4 */
> - stepped = emulate_step(®s, TEST_STXVD2X(39, 3, 4));
> + stepped = emulate_step(®s, PPC_ENCODE_STXVD2X(39, R3, R4));
>
> if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
> cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
> @@ -484,7 +441,7 @@ static struct compute_test compute_tests[] = {
> .subtests = {
> {
> .descr = "RA = LONG_MIN, RB = LONG_MIN",
> - .instr = TEST_ADD(20, 21, 22),
> + .instr = PPC_ENCODE_ADD(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MIN,
> .gpr[22] = LONG_MIN,
> @@ -492,7 +449,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = LONG_MIN, RB = LONG_MAX",
> - .instr = TEST_ADD(20, 21, 22),
> + .instr = PPC_ENCODE_ADD(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MIN,
> .gpr[22] = LONG_MAX,
> @@ -500,7 +457,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = LONG_MAX, RB = LONG_MAX",
> - .instr = TEST_ADD(20, 21, 22),
> + .instr = PPC_ENCODE_ADD(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MAX,
> .gpr[22] = LONG_MAX,
> @@ -508,7 +465,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
> - .instr = TEST_ADD(20, 21, 22),
> + .instr = PPC_ENCODE_ADD(20, 21, 22),
> .regs = {
> .gpr[21] = ULONG_MAX,
> .gpr[22] = ULONG_MAX,
> @@ -516,7 +473,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = ULONG_MAX, RB = 0x1",
> - .instr = TEST_ADD(20, 21, 22),
> + .instr = PPC_ENCODE_ADD(20, 21, 22),
> .regs = {
> .gpr[21] = ULONG_MAX,
> .gpr[22] = 0x1,
> @@ -524,7 +481,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = INT_MIN, RB = INT_MIN",
> - .instr = TEST_ADD(20, 21, 22),
> + .instr = PPC_ENCODE_ADD(20, 21, 22),
> .regs = {
> .gpr[21] = INT_MIN,
> .gpr[22] = INT_MIN,
> @@ -532,7 +489,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = INT_MIN, RB = INT_MAX",
> - .instr = TEST_ADD(20, 21, 22),
> + .instr = PPC_ENCODE_ADD(20, 21, 22),
> .regs = {
> .gpr[21] = INT_MIN,
> .gpr[22] = INT_MAX,
> @@ -540,7 +497,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = INT_MAX, RB = INT_MAX",
> - .instr = TEST_ADD(20, 21, 22),
> + .instr = PPC_ENCODE_ADD(20, 21, 22),
> .regs = {
> .gpr[21] = INT_MAX,
> .gpr[22] = INT_MAX,
> @@ -548,7 +505,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = UINT_MAX, RB = UINT_MAX",
> - .instr = TEST_ADD(20, 21, 22),
> + .instr = PPC_ENCODE_ADD(20, 21, 22),
> .regs = {
> .gpr[21] = UINT_MAX,
> .gpr[22] = UINT_MAX,
> @@ -556,7 +513,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = UINT_MAX, RB = 0x1",
> - .instr = TEST_ADD(20, 21, 22),
> + .instr = PPC_ENCODE_ADD(20, 21, 22),
> .regs = {
> .gpr[21] = UINT_MAX,
> .gpr[22] = 0x1,
> @@ -570,7 +527,7 @@ static struct compute_test compute_tests[] = {
> {
> .descr = "RA = LONG_MIN, RB = LONG_MIN",
> .flags = IGNORE_CCR,
> - .instr = TEST_ADD_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADD_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MIN,
> .gpr[22] = LONG_MIN,
> @@ -578,7 +535,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = LONG_MIN, RB = LONG_MAX",
> - .instr = TEST_ADD_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADD_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MIN,
> .gpr[22] = LONG_MAX,
> @@ -587,7 +544,7 @@ static struct compute_test compute_tests[] = {
> {
> .descr = "RA = LONG_MAX, RB = LONG_MAX",
> .flags = IGNORE_CCR,
> - .instr = TEST_ADD_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADD_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MAX,
> .gpr[22] = LONG_MAX,
> @@ -595,7 +552,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
> - .instr = TEST_ADD_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADD_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = ULONG_MAX,
> .gpr[22] = ULONG_MAX,
> @@ -603,7 +560,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = ULONG_MAX, RB = 0x1",
> - .instr = TEST_ADD_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADD_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = ULONG_MAX,
> .gpr[22] = 0x1,
> @@ -611,7 +568,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = INT_MIN, RB = INT_MIN",
> - .instr = TEST_ADD_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADD_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = INT_MIN,
> .gpr[22] = INT_MIN,
> @@ -619,7 +576,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = INT_MIN, RB = INT_MAX",
> - .instr = TEST_ADD_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADD_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = INT_MIN,
> .gpr[22] = INT_MAX,
> @@ -627,7 +584,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = INT_MAX, RB = INT_MAX",
> - .instr = TEST_ADD_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADD_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = INT_MAX,
> .gpr[22] = INT_MAX,
> @@ -635,7 +592,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = UINT_MAX, RB = UINT_MAX",
> - .instr = TEST_ADD_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADD_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = UINT_MAX,
> .gpr[22] = UINT_MAX,
> @@ -643,7 +600,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = UINT_MAX, RB = 0x1",
> - .instr = TEST_ADD_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADD_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = UINT_MAX,
> .gpr[22] = 0x1,
> @@ -656,7 +613,7 @@ static struct compute_test compute_tests[] = {
> .subtests = {
> {
> .descr = "RA = LONG_MIN, RB = LONG_MIN",
> - .instr = TEST_ADDC(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MIN,
> .gpr[22] = LONG_MIN,
> @@ -664,7 +621,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = LONG_MIN, RB = LONG_MAX",
> - .instr = TEST_ADDC(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MIN,
> .gpr[22] = LONG_MAX,
> @@ -672,7 +629,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = LONG_MAX, RB = LONG_MAX",
> - .instr = TEST_ADDC(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MAX,
> .gpr[22] = LONG_MAX,
> @@ -680,7 +637,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
> - .instr = TEST_ADDC(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC(20, 21, 22),
> .regs = {
> .gpr[21] = ULONG_MAX,
> .gpr[22] = ULONG_MAX,
> @@ -688,7 +645,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = ULONG_MAX, RB = 0x1",
> - .instr = TEST_ADDC(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC(20, 21, 22),
> .regs = {
> .gpr[21] = ULONG_MAX,
> .gpr[22] = 0x1,
> @@ -696,7 +653,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = INT_MIN, RB = INT_MIN",
> - .instr = TEST_ADDC(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC(20, 21, 22),
> .regs = {
> .gpr[21] = INT_MIN,
> .gpr[22] = INT_MIN,
> @@ -704,7 +661,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = INT_MIN, RB = INT_MAX",
> - .instr = TEST_ADDC(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC(20, 21, 22),
> .regs = {
> .gpr[21] = INT_MIN,
> .gpr[22] = INT_MAX,
> @@ -712,7 +669,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = INT_MAX, RB = INT_MAX",
> - .instr = TEST_ADDC(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC(20, 21, 22),
> .regs = {
> .gpr[21] = INT_MAX,
> .gpr[22] = INT_MAX,
> @@ -720,7 +677,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = UINT_MAX, RB = UINT_MAX",
> - .instr = TEST_ADDC(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC(20, 21, 22),
> .regs = {
> .gpr[21] = UINT_MAX,
> .gpr[22] = UINT_MAX,
> @@ -728,7 +685,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = UINT_MAX, RB = 0x1",
> - .instr = TEST_ADDC(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC(20, 21, 22),
> .regs = {
> .gpr[21] = UINT_MAX,
> .gpr[22] = 0x1,
> @@ -736,7 +693,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
> - .instr = TEST_ADDC(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MIN | (uint)INT_MIN,
> .gpr[22] = LONG_MIN | (uint)INT_MIN,
> @@ -750,7 +707,7 @@ static struct compute_test compute_tests[] = {
> {
> .descr = "RA = LONG_MIN, RB = LONG_MIN",
> .flags = IGNORE_CCR,
> - .instr = TEST_ADDC_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MIN,
> .gpr[22] = LONG_MIN,
> @@ -758,7 +715,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = LONG_MIN, RB = LONG_MAX",
> - .instr = TEST_ADDC_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MIN,
> .gpr[22] = LONG_MAX,
> @@ -767,7 +724,7 @@ static struct compute_test compute_tests[] = {
> {
> .descr = "RA = LONG_MAX, RB = LONG_MAX",
> .flags = IGNORE_CCR,
> - .instr = TEST_ADDC_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MAX,
> .gpr[22] = LONG_MAX,
> @@ -775,7 +732,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
> - .instr = TEST_ADDC_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = ULONG_MAX,
> .gpr[22] = ULONG_MAX,
> @@ -783,7 +740,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = ULONG_MAX, RB = 0x1",
> - .instr = TEST_ADDC_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = ULONG_MAX,
> .gpr[22] = 0x1,
> @@ -791,7 +748,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = INT_MIN, RB = INT_MIN",
> - .instr = TEST_ADDC_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = INT_MIN,
> .gpr[22] = INT_MIN,
> @@ -799,7 +756,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = INT_MIN, RB = INT_MAX",
> - .instr = TEST_ADDC_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = INT_MIN,
> .gpr[22] = INT_MAX,
> @@ -807,7 +764,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = INT_MAX, RB = INT_MAX",
> - .instr = TEST_ADDC_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = INT_MAX,
> .gpr[22] = INT_MAX,
> @@ -815,7 +772,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = UINT_MAX, RB = UINT_MAX",
> - .instr = TEST_ADDC_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = UINT_MAX,
> .gpr[22] = UINT_MAX,
> @@ -823,7 +780,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = UINT_MAX, RB = 0x1",
> - .instr = TEST_ADDC_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = UINT_MAX,
> .gpr[22] = 0x1,
> @@ -831,7 +788,7 @@ static struct compute_test compute_tests[] = {
> },
> {
> .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
> - .instr = TEST_ADDC_DOT(20, 21, 22),
> + .instr = PPC_ENCODE_ADDC_DOT(20, 21, 22),
> .regs = {
> .gpr[21] = LONG_MIN | (uint)INT_MIN,
> .gpr[22] = LONG_MIN | (uint)INT_MIN,
> diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
> index 55d4377ccfae..fdb09e0e16c0 100644
> --- a/arch/powerpc/net/bpf_jit.h
> +++ b/arch/powerpc/net/bpf_jit.h
> @@ -45,8 +45,6 @@
> #define PPC_ADDIS(d, a, i) EMIT(PPC_INST_ADDIS | \
> ___PPC_RT(d) | ___PPC_RA(a) | IMM_L(i))
> #define PPC_LIS(r, i) PPC_ADDIS(r, 0, i)
> -#define PPC_STD(r, base, i) EMIT(PPC_INST_STD | ___PPC_RS(r) | \
> - ___PPC_RA(base) | ((i) & 0xfffc))
> #define PPC_STDX(r, base, b) EMIT(PPC_INST_STDX | ___PPC_RS(r) | \
> ___PPC_RA(base) | ___PPC_RB(b))
> #define PPC_STDU(r, base, i) EMIT(PPC_INST_STDU | ___PPC_RS(r) | \
> @@ -62,12 +60,8 @@
>
> #define PPC_LBZ(r, base, i) EMIT(PPC_INST_LBZ | ___PPC_RT(r) | \
> ___PPC_RA(base) | IMM_L(i))
> -#define PPC_LD(r, base, i) EMIT(PPC_INST_LD | ___PPC_RT(r) | \
> - ___PPC_RA(base) | ((i) & 0xfffc))
> #define PPC_LDX(r, base, b) EMIT(PPC_INST_LDX | ___PPC_RT(r) | \
> ___PPC_RA(base) | ___PPC_RB(b))
> -#define PPC_LWZ(r, base, i) EMIT(PPC_INST_LWZ | ___PPC_RT(r) | \
> - ___PPC_RA(base) | IMM_L(i))
> #define PPC_LHZ(r, base, i) EMIT(PPC_INST_LHZ | ___PPC_RT(r) | \
> ___PPC_RA(base) | IMM_L(i))
> #define PPC_LHBRX(r, base, b) EMIT(PPC_INST_LHBRX | ___PPC_RT(r) | \
> @@ -100,8 +94,6 @@
>
> #define PPC_SUB(d, a, b) EMIT(PPC_INST_SUB | ___PPC_RT(d) | \
> ___PPC_RB(a) | ___PPC_RA(b))
> -#define PPC_ADD(d, a, b) EMIT(PPC_INST_ADD | ___PPC_RT(d) | \
> - ___PPC_RA(a) | ___PPC_RB(b))
> #define PPC_MULD(d, a, b) EMIT(PPC_INST_MULLD | ___PPC_RT(d) | \
> ___PPC_RA(a) | ___PPC_RB(b))
> #define PPC_MULW(d, a, b) EMIT(PPC_INST_MULLW | ___PPC_RT(d) | \
> diff --git a/arch/powerpc/net/bpf_jit32.h b/arch/powerpc/net/bpf_jit32.h
> index 4ec2a9f14f84..8a9f16a7262e 100644
> --- a/arch/powerpc/net/bpf_jit32.h
> +++ b/arch/powerpc/net/bpf_jit32.h
> @@ -76,13 +76,13 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
> else { PPC_ADDIS(r, base, IMM_HA(i)); \
> PPC_LBZ(r, r, IMM_L(i)); } } while(0)
>
> -#define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i); \
> +#define _OFFS(r, base, i) do { if ((i) < 32768) EMIT(PPC_ENCODE_LD(r, base, i)); \
^^^^^
Should be PPC_LD_OFFS. For the next version, please also build ppc32 and
booke codebase to confirm that your changes in those areas are fine.
PPC_ENCODE_* also looks quite verbose, so perhaps PPC_ENC_* might be
better. Otherwise, this patchset looks good to me and should help reuse
some of those macros, especially from the eBPF codebase.
Michael,
Can you let us know if this looks ok to you? Based on your feedback, we
will also update the eBPF codebase.
Thanks,
Naveen
^ permalink raw reply
* [PATCH 4.14 037/148] mm, slub: prevent kmalloc_node crashes and memory leaks
From: Greg Kroah-Hartman @ 2020-04-01 16:17 UTC (permalink / raw)
To: linux-kernel
Cc: Sachin Sant, Nathan Lynch, Srikar Dronamraju,
PUVICHAKRAVARTHY RAMACHANDRAN, Greg Kroah-Hartman, David Rientjes,
linuxppc-dev, stable, Bharata B Rao, Pekka Enberg, Linus Torvalds,
Kirill Tkhai, Joonsoo Kim, Andrew Morton, Michal Hocko,
Mel Gorman, Christopher Lameter, Vlastimil Babka
In-Reply-To: <20200401161552.245876366@linuxfoundation.org>
From: Vlastimil Babka <vbabka@suse.cz>
commit 0715e6c516f106ed553828a671d30ad9a3431536 upstream.
Sachin reports [1] a crash in SLUB __slab_alloc():
BUG: Kernel NULL pointer dereference on read at 0x000073b0
Faulting instruction address: 0xc0000000003d55f4
Oops: Kernel access of bad area, sig: 11 [#1]
LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries
Modules linked in:
CPU: 19 PID: 1 Comm: systemd Not tainted 5.6.0-rc2-next-20200218-autotest #1
NIP: c0000000003d55f4 LR: c0000000003d5b94 CTR: 0000000000000000
REGS: c0000008b37836d0 TRAP: 0300 Not tainted (5.6.0-rc2-next-20200218-autotest)
MSR: 8000000000009033 <SF,EE,ME,IR,DR,RI,LE> CR: 24004844 XER: 00000000
CFAR: c00000000000dec4 DAR: 00000000000073b0 DSISR: 40000000 IRQMASK: 1
GPR00: c0000000003d5b94 c0000008b3783960 c00000000155d400 c0000008b301f500
GPR04: 0000000000000dc0 0000000000000002 c0000000003443d8 c0000008bb398620
GPR08: 00000008ba2f0000 0000000000000001 0000000000000000 0000000000000000
GPR12: 0000000024004844 c00000001ec52a00 0000000000000000 0000000000000000
GPR16: c0000008a1b20048 c000000001595898 c000000001750c18 0000000000000002
GPR20: c000000001750c28 c000000001624470 0000000fffffffe0 5deadbeef0000122
GPR24: 0000000000000001 0000000000000dc0 0000000000000002 c0000000003443d8
GPR28: c0000008b301f500 c0000008bb398620 0000000000000000 c00c000002287180
NIP ___slab_alloc+0x1f4/0x760
LR __slab_alloc+0x34/0x60
Call Trace:
___slab_alloc+0x334/0x760 (unreliable)
__slab_alloc+0x34/0x60
__kmalloc_node+0x110/0x490
kvmalloc_node+0x58/0x110
mem_cgroup_css_online+0x108/0x270
online_css+0x48/0xd0
cgroup_apply_control_enable+0x2ec/0x4d0
cgroup_mkdir+0x228/0x5f0
kernfs_iop_mkdir+0x90/0xf0
vfs_mkdir+0x110/0x230
do_mkdirat+0xb0/0x1a0
system_call+0x5c/0x68
This is a PowerPC platform with following NUMA topology:
available: 2 nodes (0-1)
node 0 cpus:
node 0 size: 0 MB
node 0 free: 0 MB
node 1 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
node 1 size: 35247 MB
node 1 free: 30907 MB
node distances:
node 0 1
0: 10 40
1: 40 10
possible numa nodes: 0-31
This only happens with a mmotm patch "mm/memcontrol.c: allocate
shrinker_map on appropriate NUMA node" [2] which effectively calls
kmalloc_node for each possible node. SLUB however only allocates
kmem_cache_node on online N_NORMAL_MEMORY nodes, and relies on
node_to_mem_node to return such valid node for other nodes since commit
a561ce00b09e ("slub: fall back to node_to_mem_node() node if allocating
on memoryless node"). This is however not true in this configuration
where the _node_numa_mem_ array is not initialized for nodes 0 and 2-31,
thus it contains zeroes and get_partial() ends up accessing
non-allocated kmem_cache_node.
A related issue was reported by Bharata (originally by Ramachandran) [3]
where a similar PowerPC configuration, but with mainline kernel without
patch [2] ends up allocating large amounts of pages by kmalloc-1k
kmalloc-512. This seems to have the same underlying issue with
node_to_mem_node() not behaving as expected, and might probably also
lead to an infinite loop with CONFIG_SLUB_CPU_PARTIAL [4].
This patch should fix both issues by not relying on node_to_mem_node()
anymore and instead simply falling back to NUMA_NO_NODE, when
kmalloc_node(node) is attempted for a node that's not online, or has no
usable memory. The "usable memory" condition is also changed from
node_present_pages() to N_NORMAL_MEMORY node state, as that is exactly
the condition that SLUB uses to allocate kmem_cache_node structures.
The check in get_partial() is removed completely, as the checks in
___slab_alloc() are now sufficient to prevent get_partial() being
reached with an invalid node.
[1] https://lore.kernel.org/linux-next/3381CD91-AB3D-4773-BA04-E7A072A63968@linux.vnet.ibm.com/
[2] https://lore.kernel.org/linux-mm/fff0e636-4c36-ed10-281c-8cdb0687c839@virtuozzo.com/
[3] https://lore.kernel.org/linux-mm/20200317092624.GB22538@in.ibm.com/
[4] https://lore.kernel.org/linux-mm/088b5996-faae-8a56-ef9c-5b567125ae54@suse.cz/
Fixes: a561ce00b09e ("slub: fall back to node_to_mem_node() node if allocating on memoryless node")
Reported-by: Sachin Sant <sachinp@linux.vnet.ibm.com>
Reported-by: PUVICHAKRAVARTHY RAMACHANDRAN <puvichakravarthy@in.ibm.com>
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Tested-by: Sachin Sant <sachinp@linux.vnet.ibm.com>
Tested-by: Bharata B Rao <bharata@linux.ibm.com>
Reviewed-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Christopher Lameter <cl@linux.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: <stable@vger.kernel.org>
Link: http://lkml.kernel.org/r/20200320115533.9604-1-vbabka@suse.cz
Debugged-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
mm/slub.c | 26 +++++++++++++++++---------
1 file changed, 17 insertions(+), 9 deletions(-)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1923,8 +1923,6 @@ static void *get_partial(struct kmem_cac
if (node == NUMA_NO_NODE)
searchnode = numa_mem_id();
- else if (!node_present_pages(node))
- searchnode = node_to_mem_node(node);
object = get_partial_node(s, get_node(s, searchnode), c, flags);
if (object || node != NUMA_NO_NODE)
@@ -2521,17 +2519,27 @@ static void *___slab_alloc(struct kmem_c
struct page *page;
page = c->page;
- if (!page)
+ if (!page) {
+ /*
+ * if the node is not online or has no normal memory, just
+ * ignore the node constraint
+ */
+ if (unlikely(node != NUMA_NO_NODE &&
+ !node_state(node, N_NORMAL_MEMORY)))
+ node = NUMA_NO_NODE;
goto new_slab;
+ }
redo:
if (unlikely(!node_match(page, node))) {
- int searchnode = node;
-
- if (node != NUMA_NO_NODE && !node_present_pages(node))
- searchnode = node_to_mem_node(node);
-
- if (unlikely(!node_match(page, searchnode))) {
+ /*
+ * same as above but node_match() being false already
+ * implies node != NUMA_NO_NODE
+ */
+ if (!node_state(node, N_NORMAL_MEMORY)) {
+ node = NUMA_NO_NODE;
+ goto redo;
+ } else {
stat(s, ALLOC_NODE_MISMATCH);
deactivate_slab(s, page, c->freelist, c);
goto new_slab;
^ permalink raw reply
* [PATCH 4.9 026/102] mm, slub: prevent kmalloc_node crashes and memory leaks
From: Greg Kroah-Hartman @ 2020-04-01 16:17 UTC (permalink / raw)
To: linux-kernel
Cc: Sachin Sant, Nathan Lynch, Srikar Dronamraju,
PUVICHAKRAVARTHY RAMACHANDRAN, Greg Kroah-Hartman, David Rientjes,
linuxppc-dev, stable, Bharata B Rao, Pekka Enberg, Linus Torvalds,
Kirill Tkhai, Joonsoo Kim, Andrew Morton, Michal Hocko,
Mel Gorman, Christopher Lameter, Vlastimil Babka
In-Reply-To: <20200401161530.451355388@linuxfoundation.org>
From: Vlastimil Babka <vbabka@suse.cz>
commit 0715e6c516f106ed553828a671d30ad9a3431536 upstream.
Sachin reports [1] a crash in SLUB __slab_alloc():
BUG: Kernel NULL pointer dereference on read at 0x000073b0
Faulting instruction address: 0xc0000000003d55f4
Oops: Kernel access of bad area, sig: 11 [#1]
LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries
Modules linked in:
CPU: 19 PID: 1 Comm: systemd Not tainted 5.6.0-rc2-next-20200218-autotest #1
NIP: c0000000003d55f4 LR: c0000000003d5b94 CTR: 0000000000000000
REGS: c0000008b37836d0 TRAP: 0300 Not tainted (5.6.0-rc2-next-20200218-autotest)
MSR: 8000000000009033 <SF,EE,ME,IR,DR,RI,LE> CR: 24004844 XER: 00000000
CFAR: c00000000000dec4 DAR: 00000000000073b0 DSISR: 40000000 IRQMASK: 1
GPR00: c0000000003d5b94 c0000008b3783960 c00000000155d400 c0000008b301f500
GPR04: 0000000000000dc0 0000000000000002 c0000000003443d8 c0000008bb398620
GPR08: 00000008ba2f0000 0000000000000001 0000000000000000 0000000000000000
GPR12: 0000000024004844 c00000001ec52a00 0000000000000000 0000000000000000
GPR16: c0000008a1b20048 c000000001595898 c000000001750c18 0000000000000002
GPR20: c000000001750c28 c000000001624470 0000000fffffffe0 5deadbeef0000122
GPR24: 0000000000000001 0000000000000dc0 0000000000000002 c0000000003443d8
GPR28: c0000008b301f500 c0000008bb398620 0000000000000000 c00c000002287180
NIP ___slab_alloc+0x1f4/0x760
LR __slab_alloc+0x34/0x60
Call Trace:
___slab_alloc+0x334/0x760 (unreliable)
__slab_alloc+0x34/0x60
__kmalloc_node+0x110/0x490
kvmalloc_node+0x58/0x110
mem_cgroup_css_online+0x108/0x270
online_css+0x48/0xd0
cgroup_apply_control_enable+0x2ec/0x4d0
cgroup_mkdir+0x228/0x5f0
kernfs_iop_mkdir+0x90/0xf0
vfs_mkdir+0x110/0x230
do_mkdirat+0xb0/0x1a0
system_call+0x5c/0x68
This is a PowerPC platform with following NUMA topology:
available: 2 nodes (0-1)
node 0 cpus:
node 0 size: 0 MB
node 0 free: 0 MB
node 1 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
node 1 size: 35247 MB
node 1 free: 30907 MB
node distances:
node 0 1
0: 10 40
1: 40 10
possible numa nodes: 0-31
This only happens with a mmotm patch "mm/memcontrol.c: allocate
shrinker_map on appropriate NUMA node" [2] which effectively calls
kmalloc_node for each possible node. SLUB however only allocates
kmem_cache_node on online N_NORMAL_MEMORY nodes, and relies on
node_to_mem_node to return such valid node for other nodes since commit
a561ce00b09e ("slub: fall back to node_to_mem_node() node if allocating
on memoryless node"). This is however not true in this configuration
where the _node_numa_mem_ array is not initialized for nodes 0 and 2-31,
thus it contains zeroes and get_partial() ends up accessing
non-allocated kmem_cache_node.
A related issue was reported by Bharata (originally by Ramachandran) [3]
where a similar PowerPC configuration, but with mainline kernel without
patch [2] ends up allocating large amounts of pages by kmalloc-1k
kmalloc-512. This seems to have the same underlying issue with
node_to_mem_node() not behaving as expected, and might probably also
lead to an infinite loop with CONFIG_SLUB_CPU_PARTIAL [4].
This patch should fix both issues by not relying on node_to_mem_node()
anymore and instead simply falling back to NUMA_NO_NODE, when
kmalloc_node(node) is attempted for a node that's not online, or has no
usable memory. The "usable memory" condition is also changed from
node_present_pages() to N_NORMAL_MEMORY node state, as that is exactly
the condition that SLUB uses to allocate kmem_cache_node structures.
The check in get_partial() is removed completely, as the checks in
___slab_alloc() are now sufficient to prevent get_partial() being
reached with an invalid node.
[1] https://lore.kernel.org/linux-next/3381CD91-AB3D-4773-BA04-E7A072A63968@linux.vnet.ibm.com/
[2] https://lore.kernel.org/linux-mm/fff0e636-4c36-ed10-281c-8cdb0687c839@virtuozzo.com/
[3] https://lore.kernel.org/linux-mm/20200317092624.GB22538@in.ibm.com/
[4] https://lore.kernel.org/linux-mm/088b5996-faae-8a56-ef9c-5b567125ae54@suse.cz/
Fixes: a561ce00b09e ("slub: fall back to node_to_mem_node() node if allocating on memoryless node")
Reported-by: Sachin Sant <sachinp@linux.vnet.ibm.com>
Reported-by: PUVICHAKRAVARTHY RAMACHANDRAN <puvichakravarthy@in.ibm.com>
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Tested-by: Sachin Sant <sachinp@linux.vnet.ibm.com>
Tested-by: Bharata B Rao <bharata@linux.ibm.com>
Reviewed-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Christopher Lameter <cl@linux.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: <stable@vger.kernel.org>
Link: http://lkml.kernel.org/r/20200320115533.9604-1-vbabka@suse.cz
Debugged-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
mm/slub.c | 26 +++++++++++++++++---------
1 file changed, 17 insertions(+), 9 deletions(-)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1909,8 +1909,6 @@ static void *get_partial(struct kmem_cac
if (node == NUMA_NO_NODE)
searchnode = numa_mem_id();
- else if (!node_present_pages(node))
- searchnode = node_to_mem_node(node);
object = get_partial_node(s, get_node(s, searchnode), c, flags);
if (object || node != NUMA_NO_NODE)
@@ -2506,17 +2504,27 @@ static void *___slab_alloc(struct kmem_c
struct page *page;
page = c->page;
- if (!page)
+ if (!page) {
+ /*
+ * if the node is not online or has no normal memory, just
+ * ignore the node constraint
+ */
+ if (unlikely(node != NUMA_NO_NODE &&
+ !node_state(node, N_NORMAL_MEMORY)))
+ node = NUMA_NO_NODE;
goto new_slab;
+ }
redo:
if (unlikely(!node_match(page, node))) {
- int searchnode = node;
-
- if (node != NUMA_NO_NODE && !node_present_pages(node))
- searchnode = node_to_mem_node(node);
-
- if (unlikely(!node_match(page, searchnode))) {
+ /*
+ * same as above but node_match() being false already
+ * implies node != NUMA_NO_NODE
+ */
+ if (!node_state(node, N_NORMAL_MEMORY)) {
+ node = NUMA_NO_NODE;
+ goto redo;
+ } else {
stat(s, ALLOC_NODE_MISMATCH);
deactivate_slab(s, page, c->freelist);
c->page = NULL;
^ permalink raw reply
* [PATCH 4.4 24/91] mm, slub: prevent kmalloc_node crashes and memory leaks
From: Greg Kroah-Hartman @ 2020-04-01 16:17 UTC (permalink / raw)
To: linux-kernel
Cc: Sachin Sant, Nathan Lynch, Srikar Dronamraju,
PUVICHAKRAVARTHY RAMACHANDRAN, Greg Kroah-Hartman, David Rientjes,
linuxppc-dev, stable, Bharata B Rao, Pekka Enberg, Linus Torvalds,
Kirill Tkhai, Joonsoo Kim, Andrew Morton, Michal Hocko,
Mel Gorman, Christopher Lameter, Vlastimil Babka
In-Reply-To: <20200401161512.917494101@linuxfoundation.org>
From: Vlastimil Babka <vbabka@suse.cz>
commit 0715e6c516f106ed553828a671d30ad9a3431536 upstream.
Sachin reports [1] a crash in SLUB __slab_alloc():
BUG: Kernel NULL pointer dereference on read at 0x000073b0
Faulting instruction address: 0xc0000000003d55f4
Oops: Kernel access of bad area, sig: 11 [#1]
LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries
Modules linked in:
CPU: 19 PID: 1 Comm: systemd Not tainted 5.6.0-rc2-next-20200218-autotest #1
NIP: c0000000003d55f4 LR: c0000000003d5b94 CTR: 0000000000000000
REGS: c0000008b37836d0 TRAP: 0300 Not tainted (5.6.0-rc2-next-20200218-autotest)
MSR: 8000000000009033 <SF,EE,ME,IR,DR,RI,LE> CR: 24004844 XER: 00000000
CFAR: c00000000000dec4 DAR: 00000000000073b0 DSISR: 40000000 IRQMASK: 1
GPR00: c0000000003d5b94 c0000008b3783960 c00000000155d400 c0000008b301f500
GPR04: 0000000000000dc0 0000000000000002 c0000000003443d8 c0000008bb398620
GPR08: 00000008ba2f0000 0000000000000001 0000000000000000 0000000000000000
GPR12: 0000000024004844 c00000001ec52a00 0000000000000000 0000000000000000
GPR16: c0000008a1b20048 c000000001595898 c000000001750c18 0000000000000002
GPR20: c000000001750c28 c000000001624470 0000000fffffffe0 5deadbeef0000122
GPR24: 0000000000000001 0000000000000dc0 0000000000000002 c0000000003443d8
GPR28: c0000008b301f500 c0000008bb398620 0000000000000000 c00c000002287180
NIP ___slab_alloc+0x1f4/0x760
LR __slab_alloc+0x34/0x60
Call Trace:
___slab_alloc+0x334/0x760 (unreliable)
__slab_alloc+0x34/0x60
__kmalloc_node+0x110/0x490
kvmalloc_node+0x58/0x110
mem_cgroup_css_online+0x108/0x270
online_css+0x48/0xd0
cgroup_apply_control_enable+0x2ec/0x4d0
cgroup_mkdir+0x228/0x5f0
kernfs_iop_mkdir+0x90/0xf0
vfs_mkdir+0x110/0x230
do_mkdirat+0xb0/0x1a0
system_call+0x5c/0x68
This is a PowerPC platform with following NUMA topology:
available: 2 nodes (0-1)
node 0 cpus:
node 0 size: 0 MB
node 0 free: 0 MB
node 1 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
node 1 size: 35247 MB
node 1 free: 30907 MB
node distances:
node 0 1
0: 10 40
1: 40 10
possible numa nodes: 0-31
This only happens with a mmotm patch "mm/memcontrol.c: allocate
shrinker_map on appropriate NUMA node" [2] which effectively calls
kmalloc_node for each possible node. SLUB however only allocates
kmem_cache_node on online N_NORMAL_MEMORY nodes, and relies on
node_to_mem_node to return such valid node for other nodes since commit
a561ce00b09e ("slub: fall back to node_to_mem_node() node if allocating
on memoryless node"). This is however not true in this configuration
where the _node_numa_mem_ array is not initialized for nodes 0 and 2-31,
thus it contains zeroes and get_partial() ends up accessing
non-allocated kmem_cache_node.
A related issue was reported by Bharata (originally by Ramachandran) [3]
where a similar PowerPC configuration, but with mainline kernel without
patch [2] ends up allocating large amounts of pages by kmalloc-1k
kmalloc-512. This seems to have the same underlying issue with
node_to_mem_node() not behaving as expected, and might probably also
lead to an infinite loop with CONFIG_SLUB_CPU_PARTIAL [4].
This patch should fix both issues by not relying on node_to_mem_node()
anymore and instead simply falling back to NUMA_NO_NODE, when
kmalloc_node(node) is attempted for a node that's not online, or has no
usable memory. The "usable memory" condition is also changed from
node_present_pages() to N_NORMAL_MEMORY node state, as that is exactly
the condition that SLUB uses to allocate kmem_cache_node structures.
The check in get_partial() is removed completely, as the checks in
___slab_alloc() are now sufficient to prevent get_partial() being
reached with an invalid node.
[1] https://lore.kernel.org/linux-next/3381CD91-AB3D-4773-BA04-E7A072A63968@linux.vnet.ibm.com/
[2] https://lore.kernel.org/linux-mm/fff0e636-4c36-ed10-281c-8cdb0687c839@virtuozzo.com/
[3] https://lore.kernel.org/linux-mm/20200317092624.GB22538@in.ibm.com/
[4] https://lore.kernel.org/linux-mm/088b5996-faae-8a56-ef9c-5b567125ae54@suse.cz/
Fixes: a561ce00b09e ("slub: fall back to node_to_mem_node() node if allocating on memoryless node")
Reported-by: Sachin Sant <sachinp@linux.vnet.ibm.com>
Reported-by: PUVICHAKRAVARTHY RAMACHANDRAN <puvichakravarthy@in.ibm.com>
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Tested-by: Sachin Sant <sachinp@linux.vnet.ibm.com>
Tested-by: Bharata B Rao <bharata@linux.ibm.com>
Reviewed-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Christopher Lameter <cl@linux.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: <stable@vger.kernel.org>
Link: http://lkml.kernel.org/r/20200320115533.9604-1-vbabka@suse.cz
Debugged-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
mm/slub.c | 26 +++++++++++++++++---------
1 file changed, 17 insertions(+), 9 deletions(-)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1777,8 +1777,6 @@ static void *get_partial(struct kmem_cac
if (node == NUMA_NO_NODE)
searchnode = numa_mem_id();
- else if (!node_present_pages(node))
- searchnode = node_to_mem_node(node);
object = get_partial_node(s, get_node(s, searchnode), c, flags);
if (object || node != NUMA_NO_NODE)
@@ -2355,17 +2353,27 @@ static void *___slab_alloc(struct kmem_c
struct page *page;
page = c->page;
- if (!page)
+ if (!page) {
+ /*
+ * if the node is not online or has no normal memory, just
+ * ignore the node constraint
+ */
+ if (unlikely(node != NUMA_NO_NODE &&
+ !node_state(node, N_NORMAL_MEMORY)))
+ node = NUMA_NO_NODE;
goto new_slab;
+ }
redo:
if (unlikely(!node_match(page, node))) {
- int searchnode = node;
-
- if (node != NUMA_NO_NODE && !node_present_pages(node))
- searchnode = node_to_mem_node(node);
-
- if (unlikely(!node_match(page, searchnode))) {
+ /*
+ * same as above but node_match() being false already
+ * implies node != NUMA_NO_NODE
+ */
+ if (!node_state(node, N_NORMAL_MEMORY)) {
+ node = NUMA_NO_NODE;
+ goto redo;
+ } else {
stat(s, ALLOC_NODE_MISMATCH);
deactivate_slab(s, page, c->freelist);
c->page = NULL;
^ 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