* [PATCH 2/5] powerpc: rtas: clean up time handling
From: Arnd Bergmann @ 2018-04-23 8:10 UTC (permalink / raw)
To: Michael Ellerman
Cc: Paul Mackerras, Benjamin Herrenschmidt, linuxppc-dev,
Arnd Bergmann, linux-kernel
In-Reply-To: <20180423081114.1813726-1-arnd@arndb.de>
The to_tm() helper function operates on a signed integer for the time,
so it will suffer from overflow in 2038, even on 64-bit kernels.
Rather than fix that function, this replaces its use in the rtas
procfs implementation with the standard rtc_time64_to_tm() helper
that is very similar but is not affected by the overflow.
In order to actually support long times, the parser function gets
changed to 64-bit user input and output as well. Note that the tm_mon
and tm_year representation is slightly different, so we have to manually
add an offset here.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/powerpc/kernel/rtas-proc.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index fb070d8cad07..80864b787745 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -280,7 +280,7 @@ static int __init proc_rtas_init(void)
__initcall(proc_rtas_init);
-static int parse_number(const char __user *p, size_t count, unsigned long *val)
+static int parse_number(const char __user *p, size_t count, u64 *val)
{
char buf[40];
char *end;
@@ -293,7 +293,7 @@ static int parse_number(const char __user *p, size_t count, unsigned long *val)
buf[count] = 0;
- *val = simple_strtoul(buf, &end, 10);
+ *val = simple_strtoull(buf, &end, 10);
if (*end && *end != '\n')
return -EINVAL;
@@ -307,17 +307,17 @@ static ssize_t ppc_rtas_poweron_write(struct file *file,
const char __user *buf, size_t count, loff_t *ppos)
{
struct rtc_time tm;
- unsigned long nowtime;
+ time64_t nowtime;
int error = parse_number(buf, count, &nowtime);
if (error)
return error;
power_on_time = nowtime; /* save the time */
- to_tm(nowtime, &tm);
+ rtc_time64_to_tm(nowtime, 0, &tm);
error = rtas_call(rtas_token("set-time-for-power-on"), 7, 1, NULL,
- tm.tm_year, tm.tm_mon, tm.tm_mday,
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */);
if (error)
printk(KERN_WARNING "error: setting poweron time returned: %s\n",
@@ -373,14 +373,14 @@ static ssize_t ppc_rtas_clock_write(struct file *file,
const char __user *buf, size_t count, loff_t *ppos)
{
struct rtc_time tm;
- unsigned long nowtime;
+ time64_t nowtime;
int error = parse_number(buf, count, &nowtime);
if (error)
return error;
- to_tm(nowtime, &tm);
+ rtc_time64_to_tm(nowtime, 0, &tm);
error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL,
- tm.tm_year, tm.tm_mon, tm.tm_mday,
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
if (error)
printk(KERN_WARNING "error: setting the clock returned: %s\n",
@@ -401,8 +401,8 @@ static int ppc_rtas_clock_show(struct seq_file *m, void *v)
unsigned int year, mon, day, hour, min, sec;
year = ret[0]; mon = ret[1]; day = ret[2];
hour = ret[3]; min = ret[4]; sec = ret[5];
- seq_printf(m, "%lu\n",
- mktime(year, mon, day, hour, min, sec));
+ seq_printf(m, "%lld\n",
+ mktime64(year, mon, day, hour, min, sec));
}
return 0;
}
@@ -731,7 +731,7 @@ static void get_location_code(struct seq_file *m, struct individual_sensor *s,
static ssize_t ppc_rtas_tone_freq_write(struct file *file,
const char __user *buf, size_t count, loff_t *ppos)
{
- unsigned long freq;
+ u64 freq;
int error = parse_number(buf, count, &freq);
if (error)
return error;
@@ -756,7 +756,7 @@ static int ppc_rtas_tone_freq_show(struct seq_file *m, void *v)
static ssize_t ppc_rtas_tone_volume_write(struct file *file,
const char __user *buf, size_t count, loff_t *ppos)
{
- unsigned long volume;
+ u64 volume;
int error = parse_number(buf, count, &volume);
if (error)
return error;
--
2.9.0
^ permalink raw reply related
* [PATCH 5/5] powerpc: remove unused to_tm() helper
From: Arnd Bergmann @ 2018-04-23 8:10 UTC (permalink / raw)
To: Michael Ellerman
Cc: Paul Mackerras, Benjamin Herrenschmidt, linuxppc-dev,
Arnd Bergmann, Geoff Levand, linux-kernel
In-Reply-To: <20180423081114.1813726-1-arnd@arndb.de>
to_tm() is now completely unused, the only reference being in the
_dump_time() helper that is also unused. This removes both, leaving
the rest of the powerpc RTC code y2038 safe to as far as the hardware
supports.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/powerpc/include/asm/time.h | 2 --
arch/powerpc/kernel/time.c | 50 ---------------------------------------
arch/powerpc/platforms/ps3/time.c | 24 -------------------
3 files changed, 76 deletions(-)
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h
index db546c034905..79bc9c3e4325 100644
--- a/arch/powerpc/include/asm/time.h
+++ b/arch/powerpc/include/asm/time.h
@@ -26,8 +26,6 @@ extern unsigned long tb_ticks_per_usec;
extern unsigned long tb_ticks_per_sec;
extern struct clock_event_device decrementer_clockevent;
-struct rtc_time;
-extern void to_tm(int tim, struct rtc_time * tm);
extern void tick_broadcast_ipi_handler(void);
extern void generic_calibrate_decr(void);
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index f9b0baa3fa2b..79bdeea85ab4 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -1138,56 +1138,6 @@ void __init time_init(void)
#endif
}
-
-#define FEBRUARY 2
-#define STARTOFTIME 1970
-#define SECDAY 86400L
-#define SECYR (SECDAY * 365)
-#define leapyear(year) ((year) % 4 == 0 && \
- ((year) % 100 != 0 || (year) % 400 == 0))
-#define days_in_year(a) (leapyear(a) ? 366 : 365)
-#define days_in_month(a) (month_days[(a) - 1])
-
-static int month_days[12] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-void to_tm(int tim, struct rtc_time * tm)
-{
- register int i;
- register long hms, day;
-
- day = tim / SECDAY;
- hms = tim % SECDAY;
-
- /* Hours, minutes, seconds are easy */
- tm->tm_hour = hms / 3600;
- tm->tm_min = (hms % 3600) / 60;
- tm->tm_sec = (hms % 3600) % 60;
-
- /* Number of years in days */
- for (i = STARTOFTIME; day >= days_in_year(i); i++)
- day -= days_in_year(i);
- tm->tm_year = i;
-
- /* Number of months in days left */
- if (leapyear(tm->tm_year))
- days_in_month(FEBRUARY) = 29;
- for (i = 1; day >= days_in_month(i); i++)
- day -= days_in_month(i);
- days_in_month(FEBRUARY) = 28;
- tm->tm_mon = i;
-
- /* Days are what is left over (+1) from all that. */
- tm->tm_mday = day + 1;
-
- /*
- * No-one uses the day of the week.
- */
- tm->tm_wday = -1;
-}
-EXPORT_SYMBOL(to_tm);
-
/*
* Divide a 128-bit dividend by a 32-bit divisor, leaving a 128 bit
* result.
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
index 9dac125c997e..08ca76e23d09 100644
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -28,30 +28,6 @@
#include "platform.h"
-#define dump_tm(_a) _dump_tm(_a, __func__, __LINE__)
-static void _dump_tm(const struct rtc_time *tm, const char* func, int line)
-{
- pr_debug("%s:%d tm_sec %d\n", func, line, tm->tm_sec);
- pr_debug("%s:%d tm_min %d\n", func, line, tm->tm_min);
- pr_debug("%s:%d tm_hour %d\n", func, line, tm->tm_hour);
- pr_debug("%s:%d tm_mday %d\n", func, line, tm->tm_mday);
- pr_debug("%s:%d tm_mon %d\n", func, line, tm->tm_mon);
- pr_debug("%s:%d tm_year %d\n", func, line, tm->tm_year);
- pr_debug("%s:%d tm_wday %d\n", func, line, tm->tm_wday);
-}
-
-#define dump_time(_a) _dump_time(_a, __func__, __LINE__)
-static void __maybe_unused _dump_time(int time, const char *func,
- int line)
-{
- struct rtc_time tm;
-
- to_tm(time, &tm);
-
- pr_debug("%s:%d time %d\n", func, line, time);
- _dump_tm(&tm, func, line);
-}
-
void __init ps3_calibrate_decr(void)
{
int result;
--
2.9.0
^ permalink raw reply related
* [PATCH 4/5] powerpc: use time64_t in update_persistent_clock
From: Arnd Bergmann @ 2018-04-23 8:10 UTC (permalink / raw)
To: Michael Ellerman
Cc: Paul Mackerras, Benjamin Herrenschmidt, linuxppc-dev,
Arnd Bergmann, linux-kernel
In-Reply-To: <20180423081114.1813726-1-arnd@arndb.de>
update_persistent_clock() is deprecated because it suffers from overflow
in 2038 on 32-bit architectures. This changes powerpc to use the
update_persistent_clock64() replacement, and to pass down 64-bit
timestamps consistently.
This is now simpler, as we no longer have to worry about the offset
numbers in tm_year and tm_mon that are different between the Linux
conventions and RTAS.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/powerpc/kernel/time.c | 6 ++----
arch/powerpc/platforms/8xx/m8xx_setup.c | 7 +++----
arch/powerpc/platforms/powermac/time.c | 17 ++++-------------
3 files changed, 9 insertions(+), 21 deletions(-)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index afb27962b396..f9b0baa3fa2b 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -781,16 +781,14 @@ void __init generic_calibrate_decr(void)
}
}
-int update_persistent_clock(struct timespec now)
+int update_persistent_clock64(struct timespec64 now)
{
struct rtc_time tm;
if (!ppc_md.set_rtc_time)
return -ENODEV;
- to_tm(now.tv_sec + 1 + timezone_offset, &tm);
- tm.tm_year -= 1900;
- tm.tm_mon -= 1;
+ rtc_time64_to_tm(now.tv_sec + 1 + timezone_offset, &tm);
return ppc_md.set_rtc_time(&tm);
}
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index d76daa90647b..027c42d8966c 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -169,15 +169,14 @@ int mpc8xx_set_rtc_time(struct rtc_time *tm)
{
sitk8xx_t __iomem *sys_tmr1;
sit8xx_t __iomem *sys_tmr2;
- int time;
+ time64_t time;
sys_tmr1 = immr_map(im_sitk);
sys_tmr2 = immr_map(im_sit);
- time = mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
+ time = rtc_tm_to_time64(tm);
out_be32(&sys_tmr1->sitk_rtck, KAPWR_KEY);
- out_be32(&sys_tmr2->sit_rtc, time);
+ out_be32(&sys_tmr2->sit_rtc, (u32)time);
out_be32(&sys_tmr1->sitk_rtck, ~KAPWR_KEY);
immr_unmap(sys_tmr2);
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index d5d1c452038e..7c968e46736f 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -84,15 +84,6 @@ long __init pmac_time_init(void)
return delta;
}
-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) || \
- defined(CONFIG_PMAC_SMU)
-static unsigned long from_rtc_time(struct rtc_time *tm)
-{
- return mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
-}
-#endif
-
#ifdef CONFIG_ADB_CUDA
static time64_t cuda_get_time(void)
{
@@ -115,10 +106,10 @@ static time64_t cuda_get_time(void)
static int cuda_set_rtc_time(struct rtc_time *tm)
{
- unsigned int nowtime;
+ time64_t nowtime;
struct adb_request req;
- nowtime = from_rtc_time(tm) + RTC_OFFSET;
+ nowtime = rtc_tm_to_time64(tm) + RTC_OFFSET;
if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
nowtime >> 24, nowtime >> 16, nowtime >> 8,
nowtime) < 0)
@@ -158,10 +149,10 @@ static time64_t pmu_get_time(void)
static int pmu_set_rtc_time(struct rtc_time *tm)
{
- unsigned int nowtime;
+ time64_t nowtime;
struct adb_request req;
- nowtime = from_rtc_time(tm) + RTC_OFFSET;
+ nowtime = rtc_tm_to_time64(tm) + RTC_OFFSET;
if (pmu_request(&req, NULL, 5, PMU_SET_RTC, nowtime >> 24,
nowtime >> 16, nowtime >> 8, nowtime) < 0)
return -ENXIO;
--
2.9.0
^ permalink raw reply related
* [PATCH 3/5] powerpc: use time64_t in read_persistent_clock
From: Arnd Bergmann @ 2018-04-23 8:10 UTC (permalink / raw)
To: Michael Ellerman
Cc: Paul Mackerras, Benjamin Herrenschmidt, linuxppc-dev,
Arnd Bergmann, Vitaly Bordug, Geoff Levand, linux-kernel
In-Reply-To: <20180423081114.1813726-1-arnd@arndb.de>
Looking through the remaining users of the deprecated mktime()
function, I found the powerpc rtc handlers, which use it in
place of rtc_tm_to_time64().
To clean this up, I'm changing over the read_persistent_clock()
function to the read_persistent_clock64() variant, and change
all the platform specific handlers along with it.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/powerpc/include/asm/machdep.h | 2 +-
arch/powerpc/include/asm/opal.h | 2 +-
arch/powerpc/include/asm/rtas.h | 2 +-
arch/powerpc/kernel/rtas-rtc.c | 4 ++--
arch/powerpc/kernel/time.c | 7 +++----
arch/powerpc/platforms/8xx/m8xx_setup.c | 4 +---
arch/powerpc/platforms/maple/maple.h | 2 +-
arch/powerpc/platforms/maple/time.c | 5 ++---
arch/powerpc/platforms/pasemi/pasemi.h | 2 +-
arch/powerpc/platforms/pasemi/time.c | 4 ++--
arch/powerpc/platforms/powermac/pmac.h | 2 +-
arch/powerpc/platforms/powermac/time.c | 31 +++++++++++--------------------
arch/powerpc/platforms/powernv/opal-rtc.c | 5 ++---
arch/powerpc/platforms/ps3/platform.h | 2 +-
arch/powerpc/platforms/ps3/time.c | 2 +-
15 files changed, 31 insertions(+), 45 deletions(-)
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index ffe7c71e1132..a47de82fb8e2 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -83,7 +83,7 @@ struct machdep_calls {
int (*set_rtc_time)(struct rtc_time *);
void (*get_rtc_time)(struct rtc_time *);
- unsigned long (*get_boot_time)(void);
+ time64_t (*get_boot_time)(void);
unsigned char (*rtc_read_val)(int addr);
void (*rtc_write_val)(int addr, unsigned char val);
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 03e1a920491e..fc211bd98e0f 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -325,7 +325,7 @@ extern int opal_async_wait_response_interruptible(uint64_t token,
extern int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data);
struct rtc_time;
-extern unsigned long opal_get_boot_time(void);
+extern time64_t opal_get_boot_time(void);
extern void opal_nvram_init(void);
extern void opal_flash_update_init(void);
extern void opal_flash_update_print_message(void);
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index ec9dd79398ee..71e393c46a49 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -361,7 +361,7 @@ extern int rtas_offline_cpus_mask(cpumask_var_t cpus);
extern int rtas_ibm_suspend_me(u64 handle);
struct rtc_time;
-extern unsigned long rtas_get_boot_time(void);
+extern time64_t rtas_get_boot_time(void);
extern void rtas_get_rtc_time(struct rtc_time *rtc_time);
extern int rtas_set_rtc_time(struct rtc_time *rtc_time);
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c
index 49600985c7ef..a28239b8b0c0 100644
--- a/arch/powerpc/kernel/rtas-rtc.c
+++ b/arch/powerpc/kernel/rtas-rtc.c
@@ -13,7 +13,7 @@
#define MAX_RTC_WAIT 5000 /* 5 sec */
#define RTAS_CLOCK_BUSY (-2)
-unsigned long __init rtas_get_boot_time(void)
+time64_t __init rtas_get_boot_time(void)
{
int ret[8];
int error;
@@ -38,7 +38,7 @@ unsigned long __init rtas_get_boot_time(void)
return 0;
}
- return mktime(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]);
+ return mktime64(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]);
}
/* NOTE: get_rtc_time will get an error if executed in interrupt context
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 360e71d455cc..afb27962b396 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -795,7 +795,7 @@ int update_persistent_clock(struct timespec now)
return ppc_md.set_rtc_time(&tm);
}
-static void __read_persistent_clock(struct timespec *ts)
+static void __read_persistent_clock(struct timespec64 *ts)
{
struct rtc_time tm;
static int first = 1;
@@ -819,11 +819,10 @@ static void __read_persistent_clock(struct timespec *ts)
}
ppc_md.get_rtc_time(&tm);
- ts->tv_sec = mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
+ ts->tv_sec = rtc_tm_to_time64(&tm);
}
-void read_persistent_clock(struct timespec *ts)
+void read_persistent_clock64(struct timespec64 *ts)
{
__read_persistent_clock(ts);
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index 2188d691a40f..d76daa90647b 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -192,9 +192,7 @@ void mpc8xx_get_rtc_time(struct rtc_time *tm)
/* Get time from the RTC. */
data = in_be32(&sys_tmr->sit_rtc);
- to_tm(data, tm);
- tm->tm_year -= 1900;
- tm->tm_mon -= 1;
+ rtc_time64_to_tm(data, tm);
immr_unmap(sys_tmr);
return;
}
diff --git a/arch/powerpc/platforms/maple/maple.h b/arch/powerpc/platforms/maple/maple.h
index d10f4af3a42e..4f358b55c341 100644
--- a/arch/powerpc/platforms/maple/maple.h
+++ b/arch/powerpc/platforms/maple/maple.h
@@ -6,7 +6,7 @@
*/
extern int maple_set_rtc_time(struct rtc_time *tm);
extern void maple_get_rtc_time(struct rtc_time *tm);
-extern unsigned long maple_get_boot_time(void);
+extern time64_t maple_get_boot_time(void);
extern void maple_calibrate_decr(void);
extern void maple_pci_init(void);
extern void maple_pci_irq_fixup(struct pci_dev *dev);
diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c
index cfddc87f81bf..d294617600b0 100644
--- a/arch/powerpc/platforms/maple/time.c
+++ b/arch/powerpc/platforms/maple/time.c
@@ -137,7 +137,7 @@ static struct resource rtc_iores = {
.flags = IORESOURCE_IO | IORESOURCE_BUSY,
};
-unsigned long __init maple_get_boot_time(void)
+time64_t __init maple_get_boot_time(void)
{
struct rtc_time tm;
struct device_node *rtcs;
@@ -170,7 +170,6 @@ unsigned long __init maple_get_boot_time(void)
request_resource(&ioport_resource, &rtc_iores);
maple_get_rtc_time(&tm);
- return mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
+ return rtc_tm_to_time66(&tm);
}
diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h
index 329d2a619254..70b56048ed1b 100644
--- a/arch/powerpc/platforms/pasemi/pasemi.h
+++ b/arch/powerpc/platforms/pasemi/pasemi.h
@@ -2,7 +2,7 @@
#ifndef _PASEMI_PASEMI_H
#define _PASEMI_PASEMI_H
-extern unsigned long pas_get_boot_time(void);
+extern time64_t pas_get_boot_time(void);
extern void pas_pci_init(void);
extern void pas_pci_irq_fixup(struct pci_dev *dev);
extern void pas_pci_dma_dev_setup(struct pci_dev *dev);
diff --git a/arch/powerpc/platforms/pasemi/time.c b/arch/powerpc/platforms/pasemi/time.c
index fa54351ac268..ea815254ee7b 100644
--- a/arch/powerpc/platforms/pasemi/time.c
+++ b/arch/powerpc/platforms/pasemi/time.c
@@ -21,8 +21,8 @@
#include <asm/time.h>
-unsigned long __init pas_get_boot_time(void)
+time64_t __init pas_get_boot_time(void)
{
/* Let's just return a fake date right now */
- return mktime(2006, 1, 1, 12, 0, 0);
+ return mktime64(2006, 1, 1, 12, 0, 0);
}
diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h
index 6f15b8804e9b..16a52afdb76e 100644
--- a/arch/powerpc/platforms/powermac/pmac.h
+++ b/arch/powerpc/platforms/powermac/pmac.h
@@ -15,7 +15,7 @@ struct rtc_time;
extern int pmac_newworld;
extern long pmac_time_init(void);
-extern unsigned long pmac_get_boot_time(void);
+extern time64_t pmac_get_boot_time(void);
extern void pmac_get_rtc_time(struct rtc_time *);
extern int pmac_set_rtc_time(struct rtc_time *);
extern void pmac_read_rtc_time(void);
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index 274af6fa388e..d5d1c452038e 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -84,15 +84,6 @@ long __init pmac_time_init(void)
return delta;
}
-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
-static void to_rtc_time(unsigned long now, struct rtc_time *tm)
-{
- to_tm(now, tm);
- tm->tm_year -= 1900;
- tm->tm_mon -= 1;
-}
-#endif
-
#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) || \
defined(CONFIG_PMAC_SMU)
static unsigned long from_rtc_time(struct rtc_time *tm)
@@ -103,10 +94,10 @@ static unsigned long from_rtc_time(struct rtc_time *tm)
#endif
#ifdef CONFIG_ADB_CUDA
-static unsigned long cuda_get_time(void)
+static time64_t cuda_get_time(void)
{
struct adb_request req;
- unsigned int now;
+ time64_t now;
if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
return 0;
@@ -117,10 +108,10 @@ static unsigned long cuda_get_time(void)
req.reply_len);
now = (req.reply[3] << 24) + (req.reply[4] << 16)
+ (req.reply[5] << 8) + req.reply[6];
- return ((unsigned long)now) - RTC_OFFSET;
+ return now - RTC_OFFSET;
}
-#define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm))
+#define cuda_get_rtc_time(tm) rtc_time64_to_tm(cuda_get_time(), (tm))
static int cuda_set_rtc_time(struct rtc_time *tm)
{
@@ -147,10 +138,10 @@ static int cuda_set_rtc_time(struct rtc_time *tm)
#endif
#ifdef CONFIG_ADB_PMU
-static unsigned long pmu_get_time(void)
+static time64_t pmu_get_time(void)
{
struct adb_request req;
- unsigned int now;
+ time64_t now;
if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
return 0;
@@ -160,10 +151,10 @@ static unsigned long pmu_get_time(void)
req.reply_len);
now = (req.reply[0] << 24) + (req.reply[1] << 16)
+ (req.reply[2] << 8) + req.reply[3];
- return ((unsigned long)now) - RTC_OFFSET;
+ return now - RTC_OFFSET;
}
-#define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm))
+#define pmu_get_rtc_time(tm) rtc_time64_to_tm(pmu_get_time(), (tm))
static int pmu_set_rtc_time(struct rtc_time *tm)
{
@@ -188,13 +179,13 @@ static int pmu_set_rtc_time(struct rtc_time *tm)
#endif
#ifdef CONFIG_PMAC_SMU
-static unsigned long smu_get_time(void)
+static time64_t smu_get_time(void)
{
struct rtc_time tm;
if (smu_get_rtc_time(&tm, 1))
return 0;
- return from_rtc_time(&tm);
+ return rtc_tm_to_time64(&tm);
}
#else
@@ -204,7 +195,7 @@ static unsigned long smu_get_time(void)
#endif
/* Can't be __init, it's called when suspending and resuming */
-unsigned long pmac_get_boot_time(void)
+time64_t pmac_get_boot_time(void)
{
/* Get the time from the RTC, used only at boot time */
switch (sys_ctrler) {
diff --git a/arch/powerpc/platforms/powernv/opal-rtc.c b/arch/powerpc/platforms/powernv/opal-rtc.c
index f8868864f373..f515c4a76900 100644
--- a/arch/powerpc/platforms/powernv/opal-rtc.c
+++ b/arch/powerpc/platforms/powernv/opal-rtc.c
@@ -34,7 +34,7 @@ static void opal_to_tm(u32 y_m_d, u64 h_m_s_ms, struct rtc_time *tm)
tm->tm_wday = -1;
}
-unsigned long __init opal_get_boot_time(void)
+time64_t __init opal_get_boot_time(void)
{
struct rtc_time tm;
u32 y_m_d;
@@ -59,8 +59,7 @@ unsigned long __init opal_get_boot_time(void)
y_m_d = be32_to_cpu(__y_m_d);
h_m_s_ms = be64_to_cpu(__h_m_s_ms);
opal_to_tm(y_m_d, h_m_s_ms, &tm);
- return mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
+ return rtc_tm_to_time64(&tm);
}
static __init int opal_time_init(void)
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h
index 1809cfc562ee..9bc68f913466 100644
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -57,7 +57,7 @@ static inline void ps3_smp_cleanup_cpu(int cpu) { }
/* time */
void __init ps3_calibrate_decr(void);
-unsigned long __init ps3_get_boot_time(void);
+time64_t __init ps3_get_boot_time(void);
void ps3_get_rtc_time(struct rtc_time *time);
int ps3_set_rtc_time(struct rtc_time *time);
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
index 11b45b58c81b..9dac125c997e 100644
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -76,7 +76,7 @@ static u64 read_rtc(void)
return rtc_val;
}
-unsigned long __init ps3_get_boot_time(void)
+time64_t __init ps3_get_boot_time(void)
{
return read_rtc() + ps3_os_area_get_rtc_diff();
}
--
2.9.0
^ permalink raw reply related
* [PATCH 1/5] powerpc: always enable RTC_LIB
From: Arnd Bergmann @ 2018-04-23 8:10 UTC (permalink / raw)
To: Michael Ellerman
Cc: Paul Mackerras, Benjamin Herrenschmidt, linuxppc-dev,
Arnd Bergmann, linux-kernel
In order to use the rtc_tm_to_time64() and rtc_time64_to_tm()
helper functions in later patches, we have to ensure that
CONFIG_RTC_LIB is always built-in.
Note that this symbol only controls a couple of helper functions,
not the actual RTC subsystem, which remains optional and is
enabled with CONFIG_RTC_CLASS.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/powerpc/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c32a181a7cbb..de2cda320fdd 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -232,6 +232,7 @@ config PPC
select OF_RESERVED_MEM
select OLD_SIGACTION if PPC32
select OLD_SIGSUSPEND
+ select RTC_LIB
select SPARSE_IRQ
select SYSCTL_EXCEPTION_TRACE
select VIRT_TO_BUS if !PPC64
--
2.9.0
^ permalink raw reply related
* Re: [PATCH v10 12/25] mm: cache some VMA fields in the vm_fault structure
From: Minchan Kim @ 2018-04-23 7:42 UTC (permalink / raw)
To: Laurent Dufour
Cc: akpm, mhocko, peterz, kirill, ak, dave, jack, Matthew Wilcox,
benh, mpe, paulus, Thomas Gleixner, Ingo Molnar, hpa, Will Deacon,
Sergey Senozhatsky, Andrea Arcangeli, Alexei Starovoitov,
kemi.wang, sergey.senozhatsky.work, Daniel Jordan, David Rientjes,
Jerome Glisse, Ganesh Mahendran, linux-kernel, linux-mm, haren,
khandual, npiggin, bsingharora, paulmck, Tim Chen, linuxppc-dev,
x86
In-Reply-To: <1523975611-15978-13-git-send-email-ldufour@linux.vnet.ibm.com>
On Tue, Apr 17, 2018 at 04:33:18PM +0200, Laurent Dufour wrote:
> When handling speculative page fault, the vma->vm_flags and
> vma->vm_page_prot fields are read once the page table lock is released. So
> there is no more guarantee that these fields would not change in our back.
> They will be saved in the vm_fault structure before the VMA is checked for
> changes.
Sorry. I cannot understand.
If it is changed under us, what happens? If it's critical, why cannot we
check with seqcounter?
Clearly, I'm not understanding the logic here. However, it's a global
change without CONFIG_SPF so I want to be more careful.
It would be better to describe why we need to sanpshot those values
into vm_fault rather than preventing the race.
Thanks.
>
> This patch also set the fields in hugetlb_no_page() and
> __collapse_huge_page_swapin even if it is not need for the callee.
>
> Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
> ---
> include/linux/mm.h | 10 ++++++++--
> mm/huge_memory.c | 6 +++---
> mm/hugetlb.c | 2 ++
> mm/khugepaged.c | 2 ++
> mm/memory.c | 50 ++++++++++++++++++++++++++------------------------
> mm/migrate.c | 2 +-
> 6 files changed, 42 insertions(+), 30 deletions(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index f6edd15563bc..c65205c8c558 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -367,6 +367,12 @@ struct vm_fault {
> * page table to avoid allocation from
> * atomic context.
> */
> + /*
> + * These entries are required when handling speculative page fault.
> + * This way the page handling is done using consistent field values.
> + */
> + unsigned long vma_flags;
> + pgprot_t vma_page_prot;
> };
>
> /* page entry size for vm->huge_fault() */
> @@ -687,9 +693,9 @@ void free_compound_page(struct page *page);
> * pte_mkwrite. But get_user_pages can cause write faults for mappings
> * that do not have writing enabled, when used by access_process_vm.
> */
> -static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
> +static inline pte_t maybe_mkwrite(pte_t pte, unsigned long vma_flags)
> {
> - if (likely(vma->vm_flags & VM_WRITE))
> + if (likely(vma_flags & VM_WRITE))
> pte = pte_mkwrite(pte);
> return pte;
> }
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index a3a1815f8e11..da2afda67e68 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -1194,8 +1194,8 @@ static int do_huge_pmd_wp_page_fallback(struct vm_fault *vmf, pmd_t orig_pmd,
>
> for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
> pte_t entry;
> - entry = mk_pte(pages[i], vma->vm_page_prot);
> - entry = maybe_mkwrite(pte_mkdirty(entry), vma);
> + entry = mk_pte(pages[i], vmf->vma_page_prot);
> + entry = maybe_mkwrite(pte_mkdirty(entry), vmf->vma_flags);
> memcg = (void *)page_private(pages[i]);
> set_page_private(pages[i], 0);
> page_add_new_anon_rmap(pages[i], vmf->vma, haddr, false);
> @@ -2168,7 +2168,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
> entry = pte_swp_mksoft_dirty(entry);
> } else {
> entry = mk_pte(page + i, READ_ONCE(vma->vm_page_prot));
> - entry = maybe_mkwrite(entry, vma);
> + entry = maybe_mkwrite(entry, vma->vm_flags);
> if (!write)
> entry = pte_wrprotect(entry);
> if (!young)
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 218679138255..774864153407 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -3718,6 +3718,8 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
> .vma = vma,
> .address = address,
> .flags = flags,
> + .vma_flags = vma->vm_flags,
> + .vma_page_prot = vma->vm_page_prot,
> /*
> * Hard to debug if it ends up being
> * used by a callee that assumes
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 0b28af4b950d..2b02a9f9589e 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -887,6 +887,8 @@ static bool __collapse_huge_page_swapin(struct mm_struct *mm,
> .flags = FAULT_FLAG_ALLOW_RETRY,
> .pmd = pmd,
> .pgoff = linear_page_index(vma, address),
> + .vma_flags = vma->vm_flags,
> + .vma_page_prot = vma->vm_page_prot,
> };
>
> /* we only decide to swapin, if there is enough young ptes */
> diff --git a/mm/memory.c b/mm/memory.c
> index f76f5027d251..2fb9920e06a5 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -1826,7 +1826,7 @@ static int insert_pfn(struct vm_area_struct *vma, unsigned long addr,
> out_mkwrite:
> if (mkwrite) {
> entry = pte_mkyoung(entry);
> - entry = maybe_mkwrite(pte_mkdirty(entry), vma);
> + entry = maybe_mkwrite(pte_mkdirty(entry), vma->vm_flags);
> }
>
> set_pte_at(mm, addr, pte, entry);
> @@ -2472,7 +2472,7 @@ static inline void wp_page_reuse(struct vm_fault *vmf)
>
> flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte));
> entry = pte_mkyoung(vmf->orig_pte);
> - entry = maybe_mkwrite(pte_mkdirty(entry), vma);
> + entry = maybe_mkwrite(pte_mkdirty(entry), vmf->vma_flags);
> if (ptep_set_access_flags(vma, vmf->address, vmf->pte, entry, 1))
> update_mmu_cache(vma, vmf->address, vmf->pte);
> pte_unmap_unlock(vmf->pte, vmf->ptl);
> @@ -2548,8 +2548,8 @@ static int wp_page_copy(struct vm_fault *vmf)
> inc_mm_counter_fast(mm, MM_ANONPAGES);
> }
> flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte));
> - entry = mk_pte(new_page, vma->vm_page_prot);
> - entry = maybe_mkwrite(pte_mkdirty(entry), vma);
> + entry = mk_pte(new_page, vmf->vma_page_prot);
> + entry = maybe_mkwrite(pte_mkdirty(entry), vmf->vma_flags);
> /*
> * Clear the pte entry and flush it first, before updating the
> * pte with the new entry. This will avoid a race condition
> @@ -2614,7 +2614,7 @@ static int wp_page_copy(struct vm_fault *vmf)
> * Don't let another task, with possibly unlocked vma,
> * keep the mlocked page.
> */
> - if (page_copied && (vma->vm_flags & VM_LOCKED)) {
> + if (page_copied && (vmf->vma_flags & VM_LOCKED)) {
> lock_page(old_page); /* LRU manipulation */
> if (PageMlocked(old_page))
> munlock_vma_page(old_page);
> @@ -2650,7 +2650,7 @@ static int wp_page_copy(struct vm_fault *vmf)
> */
> int finish_mkwrite_fault(struct vm_fault *vmf)
> {
> - WARN_ON_ONCE(!(vmf->vma->vm_flags & VM_SHARED));
> + WARN_ON_ONCE(!(vmf->vma_flags & VM_SHARED));
> if (!pte_map_lock(vmf))
> return VM_FAULT_RETRY;
> /*
> @@ -2752,7 +2752,7 @@ static int do_wp_page(struct vm_fault *vmf)
> * We should not cow pages in a shared writeable mapping.
> * Just mark the pages writable and/or call ops->pfn_mkwrite.
> */
> - if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
> + if ((vmf->vma_flags & (VM_WRITE|VM_SHARED)) ==
> (VM_WRITE|VM_SHARED))
> return wp_pfn_shared(vmf);
>
> @@ -2799,7 +2799,7 @@ static int do_wp_page(struct vm_fault *vmf)
> return VM_FAULT_WRITE;
> }
> unlock_page(vmf->page);
> - } else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
> + } else if (unlikely((vmf->vma_flags & (VM_WRITE|VM_SHARED)) ==
> (VM_WRITE|VM_SHARED))) {
> return wp_page_shared(vmf);
> }
> @@ -3078,9 +3078,9 @@ int do_swap_page(struct vm_fault *vmf)
>
> inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
> dec_mm_counter_fast(vma->vm_mm, MM_SWAPENTS);
> - pte = mk_pte(page, vma->vm_page_prot);
> + pte = mk_pte(page, vmf->vma_page_prot);
> if ((vmf->flags & FAULT_FLAG_WRITE) && reuse_swap_page(page, NULL)) {
> - pte = maybe_mkwrite(pte_mkdirty(pte), vma);
> + pte = maybe_mkwrite(pte_mkdirty(pte), vmf->vma_flags);
> vmf->flags &= ~FAULT_FLAG_WRITE;
> ret |= VM_FAULT_WRITE;
> exclusive = RMAP_EXCLUSIVE;
> @@ -3105,7 +3105,7 @@ int do_swap_page(struct vm_fault *vmf)
>
> swap_free(entry);
> if (mem_cgroup_swap_full(page) ||
> - (vma->vm_flags & VM_LOCKED) || PageMlocked(page))
> + (vmf->vma_flags & VM_LOCKED) || PageMlocked(page))
> try_to_free_swap(page);
> unlock_page(page);
> if (page != swapcache && swapcache) {
> @@ -3163,7 +3163,7 @@ static int do_anonymous_page(struct vm_fault *vmf)
> pte_t entry;
>
> /* File mapping without ->vm_ops ? */
> - if (vma->vm_flags & VM_SHARED)
> + if (vmf->vma_flags & VM_SHARED)
> return VM_FAULT_SIGBUS;
>
> /*
> @@ -3187,7 +3187,7 @@ static int do_anonymous_page(struct vm_fault *vmf)
> if (!(vmf->flags & FAULT_FLAG_WRITE) &&
> !mm_forbids_zeropage(vma->vm_mm)) {
> entry = pte_mkspecial(pfn_pte(my_zero_pfn(vmf->address),
> - vma->vm_page_prot));
> + vmf->vma_page_prot));
> if (!pte_map_lock(vmf))
> return VM_FAULT_RETRY;
> if (!pte_none(*vmf->pte))
> @@ -3220,8 +3220,8 @@ static int do_anonymous_page(struct vm_fault *vmf)
> */
> __SetPageUptodate(page);
>
> - entry = mk_pte(page, vma->vm_page_prot);
> - if (vma->vm_flags & VM_WRITE)
> + entry = mk_pte(page, vmf->vma_page_prot);
> + if (vmf->vma_flags & VM_WRITE)
> entry = pte_mkwrite(pte_mkdirty(entry));
>
> if (!pte_map_lock(vmf)) {
> @@ -3418,7 +3418,7 @@ static int do_set_pmd(struct vm_fault *vmf, struct page *page)
> for (i = 0; i < HPAGE_PMD_NR; i++)
> flush_icache_page(vma, page + i);
>
> - entry = mk_huge_pmd(page, vma->vm_page_prot);
> + entry = mk_huge_pmd(page, vmf->vma_page_prot);
> if (write)
> entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
>
> @@ -3492,11 +3492,11 @@ int alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
> return VM_FAULT_NOPAGE;
>
> flush_icache_page(vma, page);
> - entry = mk_pte(page, vma->vm_page_prot);
> + entry = mk_pte(page, vmf->vma_page_prot);
> if (write)
> - entry = maybe_mkwrite(pte_mkdirty(entry), vma);
> + entry = maybe_mkwrite(pte_mkdirty(entry), vmf->vma_flags);
> /* copy-on-write page */
> - if (write && !(vma->vm_flags & VM_SHARED)) {
> + if (write && !(vmf->vma_flags & VM_SHARED)) {
> inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
> page_add_new_anon_rmap(page, vma, vmf->address, false);
> mem_cgroup_commit_charge(page, memcg, false, false);
> @@ -3535,7 +3535,7 @@ int finish_fault(struct vm_fault *vmf)
>
> /* Did we COW the page? */
> if ((vmf->flags & FAULT_FLAG_WRITE) &&
> - !(vmf->vma->vm_flags & VM_SHARED))
> + !(vmf->vma_flags & VM_SHARED))
> page = vmf->cow_page;
> else
> page = vmf->page;
> @@ -3789,7 +3789,7 @@ static int do_fault(struct vm_fault *vmf)
> ret = VM_FAULT_SIGBUS;
> else if (!(vmf->flags & FAULT_FLAG_WRITE))
> ret = do_read_fault(vmf);
> - else if (!(vma->vm_flags & VM_SHARED))
> + else if (!(vmf->vma_flags & VM_SHARED))
> ret = do_cow_fault(vmf);
> else
> ret = do_shared_fault(vmf);
> @@ -3846,7 +3846,7 @@ static int do_numa_page(struct vm_fault *vmf)
> * accessible ptes, some can allow access by kernel mode.
> */
> pte = ptep_modify_prot_start(vma->vm_mm, vmf->address, vmf->pte);
> - pte = pte_modify(pte, vma->vm_page_prot);
> + pte = pte_modify(pte, vmf->vma_page_prot);
> pte = pte_mkyoung(pte);
> if (was_writable)
> pte = pte_mkwrite(pte);
> @@ -3880,7 +3880,7 @@ static int do_numa_page(struct vm_fault *vmf)
> * Flag if the page is shared between multiple address spaces. This
> * is later used when determining whether to group tasks together
> */
> - if (page_mapcount(page) > 1 && (vma->vm_flags & VM_SHARED))
> + if (page_mapcount(page) > 1 && (vmf->vma_flags & VM_SHARED))
> flags |= TNF_SHARED;
>
> last_cpupid = page_cpupid_last(page);
> @@ -3925,7 +3925,7 @@ static inline int wp_huge_pmd(struct vm_fault *vmf, pmd_t orig_pmd)
> return vmf->vma->vm_ops->huge_fault(vmf, PE_SIZE_PMD);
>
> /* COW handled on pte level: split pmd */
> - VM_BUG_ON_VMA(vmf->vma->vm_flags & VM_SHARED, vmf->vma);
> + VM_BUG_ON_VMA(vmf->vma_flags & VM_SHARED, vmf->vma);
> __split_huge_pmd(vmf->vma, vmf->pmd, vmf->address, false, NULL);
>
> return VM_FAULT_FALLBACK;
> @@ -4072,6 +4072,8 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
> .flags = flags,
> .pgoff = linear_page_index(vma, address),
> .gfp_mask = __get_fault_gfp_mask(vma),
> + .vma_flags = vma->vm_flags,
> + .vma_page_prot = vma->vm_page_prot,
> };
> unsigned int dirty = flags & FAULT_FLAG_WRITE;
> struct mm_struct *mm = vma->vm_mm;
> diff --git a/mm/migrate.c b/mm/migrate.c
> index bb6367d70a3e..44d7007cfc1c 100644
> --- a/mm/migrate.c
> +++ b/mm/migrate.c
> @@ -240,7 +240,7 @@ static bool remove_migration_pte(struct page *page, struct vm_area_struct *vma,
> */
> entry = pte_to_swp_entry(*pvmw.pte);
> if (is_write_migration_entry(entry))
> - pte = maybe_mkwrite(pte, vma);
> + pte = maybe_mkwrite(pte, vma->vm_flags);
>
> if (unlikely(is_zone_device_page(new))) {
> if (is_device_private_page(new)) {
> --
> 2.7.4
>
^ permalink raw reply
* Re: [PATCH v10 09/25] mm: protect VMA modifications using VMA sequence count
From: Minchan Kim @ 2018-04-23 7:19 UTC (permalink / raw)
To: Laurent Dufour
Cc: akpm, mhocko, peterz, kirill, ak, dave, jack, Matthew Wilcox,
benh, mpe, paulus, Thomas Gleixner, Ingo Molnar, hpa, Will Deacon,
Sergey Senozhatsky, Andrea Arcangeli, Alexei Starovoitov,
kemi.wang, sergey.senozhatsky.work, Daniel Jordan, David Rientjes,
Jerome Glisse, Ganesh Mahendran, linux-kernel, linux-mm, haren,
khandual, npiggin, bsingharora, paulmck, Tim Chen, linuxppc-dev,
x86
In-Reply-To: <1523975611-15978-10-git-send-email-ldufour@linux.vnet.ibm.com>
On Tue, Apr 17, 2018 at 04:33:15PM +0200, Laurent Dufour wrote:
> The VMA sequence count has been introduced to allow fast detection of
> VMA modification when running a page fault handler without holding
> the mmap_sem.
>
> This patch provides protection against the VMA modification done in :
> - madvise()
> - mpol_rebind_policy()
> - vma_replace_policy()
> - change_prot_numa()
> - mlock(), munlock()
> - mprotect()
> - mmap_region()
> - collapse_huge_page()
> - userfaultd registering services
>
> In addition, VMA fields which will be read during the speculative fault
> path needs to be written using WRITE_ONCE to prevent write to be split
> and intermediate values to be pushed to other CPUs.
>
> Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
> ---
> fs/proc/task_mmu.c | 5 ++++-
> fs/userfaultfd.c | 17 +++++++++++++----
> mm/khugepaged.c | 3 +++
> mm/madvise.c | 6 +++++-
> mm/mempolicy.c | 51 ++++++++++++++++++++++++++++++++++-----------------
> mm/mlock.c | 13 ++++++++-----
> mm/mmap.c | 22 +++++++++++++---------
> mm/mprotect.c | 4 +++-
> mm/swap_state.c | 8 ++++++--
> 9 files changed, 89 insertions(+), 40 deletions(-)
>
> diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
> index c486ad4b43f0..aeb417f28839 100644
> --- a/fs/proc/task_mmu.c
> +++ b/fs/proc/task_mmu.c
> @@ -1136,8 +1136,11 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
> goto out_mm;
> }
> for (vma = mm->mmap; vma; vma = vma->vm_next) {
> - vma->vm_flags &= ~VM_SOFTDIRTY;
> + vm_write_begin(vma);
> + WRITE_ONCE(vma->vm_flags,
> + vma->vm_flags & ~VM_SOFTDIRTY);
> vma_set_page_prot(vma);
> + vm_write_end(vma);
trivial:
I think It's tricky to maintain that VMA fields to be read during SPF should be
(READ|WRITE_ONCE). I think we need some accessor to read/write them rather than
raw accessing like like vma_set_page_prot. Maybe spf prefix would be helpful.
vma_spf_set_value(vma, vm_flags, val);
We also add some markers in vm_area_struct's fileds to indicate that
people shouldn't access those fields directly.
Just a thought.
> }
> downgrade_write(&mm->mmap_sem);
> diff --git a/mm/swap_state.c b/mm/swap_state.c
> index fe079756bb18..8a8a402ed59f 100644
> --- a/mm/swap_state.c
> +++ b/mm/swap_state.c
> @@ -575,6 +575,10 @@ static unsigned long swapin_nr_pages(unsigned long offset)
> * the readahead.
> *
> * Caller must hold down_read on the vma->vm_mm if vmf->vma is not NULL.
> + * This is needed to ensure the VMA will not be freed in our back. In the case
> + * of the speculative page fault handler, this cannot happen, even if we don't
> + * hold the mmap_sem. Callees are assumed to take care of reading VMA's fields
I guess reader would be curious on *why* is safe with SPF.
Comment about the why could be helpful for reviewer.
> + * using READ_ONCE() to read consistent values.
> */
> struct page *swap_cluster_readahead(swp_entry_t entry, gfp_t gfp_mask,
> struct vm_fault *vmf)
> @@ -668,9 +672,9 @@ static inline void swap_ra_clamp_pfn(struct vm_area_struct *vma,
> unsigned long *start,
> unsigned long *end)
> {
> - *start = max3(lpfn, PFN_DOWN(vma->vm_start),
> + *start = max3(lpfn, PFN_DOWN(READ_ONCE(vma->vm_start)),
> PFN_DOWN(faddr & PMD_MASK));
> - *end = min3(rpfn, PFN_DOWN(vma->vm_end),
> + *end = min3(rpfn, PFN_DOWN(READ_ONCE(vma->vm_end)),
> PFN_DOWN((faddr & PMD_MASK) + PMD_SIZE));
> }
>
> --
> 2.7.4
>
^ permalink raw reply
* Re: [PATCH v2 5/7] ocxl: Expose the thread_id needed for wait on p9
From: Andrew Donnellan @ 2018-04-23 7:16 UTC (permalink / raw)
To: Alastair D'Silva, linuxppc-dev
Cc: linux-kernel, linux-doc, mikey, vaibhav, aneesh.kumar, malat,
felix, pombredanne, sukadev, npiggin, gregkh, arnd, fbarrat,
corbet, Alastair D'Silva
In-Reply-To: <20180418010810.30937-6-alastair@au1.ibm.com>
On 18/04/18 11:08, Alastair D'Silva wrote:
> From: Alastair D'Silva <alastair@d-silva.org>
>
> In order to successfully issue as_notify, an AFU needs to know the TID
> to notify, which in turn means that this information should be
> available in userspace so it can be communicated to the AFU.
>
> Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
nitpicks below
Acked-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
> ---
> drivers/misc/ocxl/context.c | 5 +++-
> drivers/misc/ocxl/file.c | 53 +++++++++++++++++++++++++++++++++++++++
> drivers/misc/ocxl/link.c | 36 ++++++++++++++++++++++++++
> drivers/misc/ocxl/ocxl_internal.h | 1 +
> include/misc/ocxl.h | 9 +++++++
> include/uapi/misc/ocxl.h | 10 ++++++++
> 6 files changed, 113 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/misc/ocxl/context.c b/drivers/misc/ocxl/context.c
> index 909e8807824a..95f74623113e 100644
> --- a/drivers/misc/ocxl/context.c
> +++ b/drivers/misc/ocxl/context.c
> @@ -34,6 +34,8 @@ int ocxl_context_init(struct ocxl_context *ctx, struct ocxl_afu *afu,
> mutex_init(&ctx->xsl_error_lock);
> mutex_init(&ctx->irq_lock);
> idr_init(&ctx->irq_idr);
> + ctx->tidr = 0;
> +
> /*
> * Keep a reference on the AFU to make sure it's valid for the
> * duration of the life of the context
> @@ -65,6 +67,7 @@ int ocxl_context_attach(struct ocxl_context *ctx, u64 amr)
> {
> int rc;
>
> + // Locks both status & tidr
> mutex_lock(&ctx->status_mutex);
> if (ctx->status != OPENED) {
> rc = -EIO;
> @@ -72,7 +75,7 @@ int ocxl_context_attach(struct ocxl_context *ctx, u64 amr)
> }
>
> rc = ocxl_link_add_pe(ctx->afu->fn->link, ctx->pasid,
> - current->mm->context.id, 0, amr, current->mm,
> + current->mm->context.id, ctx->tidr, amr, current->mm,
> xsl_fault_error, ctx);
> if (rc)
> goto out;
> diff --git a/drivers/misc/ocxl/file.c b/drivers/misc/ocxl/file.c
> index 038509e5d031..eb409a469f21 100644
> --- a/drivers/misc/ocxl/file.c
> +++ b/drivers/misc/ocxl/file.c
> @@ -5,6 +5,8 @@
> #include <linux/sched/signal.h>
> #include <linux/uaccess.h>
> #include <uapi/misc/ocxl.h>
> +#include <asm/reg.h>
> +#include <asm/switch_to.h>
> #include "ocxl_internal.h"
>
>
> @@ -123,11 +125,55 @@ static long afu_ioctl_get_metadata(struct ocxl_context *ctx,
> return 0;
> }
>
> +#ifdef CONFIG_PPC64
> +static long afu_ioctl_enable_p9_wait(struct ocxl_context *ctx,
> + struct ocxl_ioctl_p9_wait __user *uarg)
> +{
> + struct ocxl_ioctl_p9_wait arg;
> +
> + memset(&arg, 0, sizeof(arg));
> +
> + if (cpu_has_feature(CPU_FTR_P9_TIDR)) {
> + enum ocxl_context_status status;
> +
> + // Locks both status & tidr
> + mutex_lock(&ctx->status_mutex);
> + if (!ctx->tidr) {
> + if (set_thread_tidr(current))
> + return -ENOENT;
> +
> + ctx->tidr = current->thread.tidr;
> + }
> +
> + status = ctx->status;
> + mutex_unlock(&ctx->status_mutex);
> +
> + if (status == ATTACHED) {
> + int rc;
> + struct link *link = ctx->afu->fn->link;
Declarations at the top
> +
> + rc = ocxl_link_update_pe(link, ctx->pasid, ctx->tidr);
> + if (rc)
> + return rc;
> + }
> +
> + arg.thread_id = ctx->tidr;
> + } else
> + return -ENOENT;
> +
> + if (copy_to_user(uarg, &arg, sizeof(arg)))
> + return -EFAULT;
> +
> + return 0;
> +}
> +#endif
> +
> #define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" : \
> x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" : \
> x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" : \
> x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" : \
> x == OCXL_IOCTL_GET_METADATA ? "GET_METADATA" : \
> + x == OCXL_IOCTL_ENABLE_P9_WAIT ? "ENABLE_P9_WAIT" : \
> "UNKNOWN")
>
> static long afu_ioctl(struct file *file, unsigned int cmd,
> @@ -186,6 +232,13 @@ static long afu_ioctl(struct file *file, unsigned int cmd,
> (struct ocxl_ioctl_metadata __user *) args);
> break;
>
> +#ifdef CONFIG_PPC64
> + case OCXL_IOCTL_ENABLE_P9_WAIT:
> + rc = afu_ioctl_enable_p9_wait(ctx,
> + (struct ocxl_ioctl_p9_wait __user *) args);
> + break;
> +#endif
> +
> default:
> rc = -EINVAL;
> }
> diff --git a/drivers/misc/ocxl/link.c b/drivers/misc/ocxl/link.c
> index 656e8610eec2..88876ae8f330 100644
> --- a/drivers/misc/ocxl/link.c
> +++ b/drivers/misc/ocxl/link.c
> @@ -544,6 +544,42 @@ int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr,
> }
> EXPORT_SYMBOL_GPL(ocxl_link_add_pe);
>
> +int ocxl_link_update_pe(void *link_handle, int pasid, __u16 tid)
> +{
> + struct link *link = (struct link *) link_handle;
> + struct spa *spa = link->spa;
> + struct ocxl_process_element *pe;
> + int pe_handle, rc;
> +
> + if (pasid > SPA_PASID_MAX)
> + return -EINVAL;
> +
> + pe_handle = pasid & SPA_PE_MASK;
> + pe = spa->spa_mem + pe_handle;
> +
> + mutex_lock(&spa->spa_lock);
> +
> + pe->tid = tid;
> +
> + /*
> + * The barrier makes sure the PE is updated
> + * before we clear the NPU context cache below, so that the
> + * old PE cannot be reloaded erroneously.
> + */
> + mb();
> +
> + /*
> + * hook to platform code
> + * On powerpc, the entry needs to be cleared from the context
> + * cache of the NPU.
> + */
> + rc = pnv_ocxl_spa_remove_pe_from_cache(link->platform_data, pe_handle);
> + WARN_ON(rc);
> +
> + mutex_unlock(&spa->spa_lock);
> + return rc;
> +}
> +
> int ocxl_link_remove_pe(void *link_handle, int pasid)
> {
> struct link *link = (struct link *) link_handle;
> diff --git a/drivers/misc/ocxl/ocxl_internal.h b/drivers/misc/ocxl/ocxl_internal.h
> index 5d421824afd9..6c6d4e61888e 100644
> --- a/drivers/misc/ocxl/ocxl_internal.h
> +++ b/drivers/misc/ocxl/ocxl_internal.h
> @@ -77,6 +77,7 @@ struct ocxl_context {
> struct ocxl_xsl_error xsl_error;
> struct mutex irq_lock;
> struct idr irq_idr;
> + __u16 tidr; // Thread ID used for P9 wait implementation
What's the difference between u16 and __u16...
> };
>
> struct ocxl_process_element {
> diff --git a/include/misc/ocxl.h b/include/misc/ocxl.h
> index 51ccf76db293..9ff6ddc28e22 100644
> --- a/include/misc/ocxl.h
> +++ b/include/misc/ocxl.h
> @@ -188,6 +188,15 @@ extern int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr,
> void (*xsl_err_cb)(void *data, u64 addr, u64 dsisr),
> void *xsl_err_data);
>
> +/**
> + * Update values within a Process Element
> + *
> + * link_handle: the link handle associated with the process element
> + * pasid: the PASID for the AFU context
> + * tid: the new thread id for the process element
> + */
> +extern int ocxl_link_update_pe(void *link_handle, int pasid, __u16 tid);
> +
> /*
> * Remove a Process Element from the Shared Process Area for a link
> */
> diff --git a/include/uapi/misc/ocxl.h b/include/uapi/misc/ocxl.h
> index 0af83d80fb3e..8d2748e69c84 100644
> --- a/include/uapi/misc/ocxl.h
> +++ b/include/uapi/misc/ocxl.h
> @@ -48,6 +48,15 @@ struct ocxl_ioctl_metadata {
> __u64 reserved[13]; // Total of 16*u64
> };
>
> +struct ocxl_ioctl_p9_wait {
> + __u16 thread_id; // The thread ID required to wake this thread
> + __u16 reserved1;
> + __u32 reserved2;
> + __u64 reserved3[3];
> +};
> +
> +};
> +
> struct ocxl_ioctl_irq_fd {
> __u64 irq_offset;
> __s32 eventfd;
> @@ -62,5 +71,6 @@ struct ocxl_ioctl_irq_fd {
> #define OCXL_IOCTL_IRQ_FREE _IOW(OCXL_MAGIC, 0x12, __u64)
> #define OCXL_IOCTL_IRQ_SET_FD _IOW(OCXL_MAGIC, 0x13, struct ocxl_ioctl_irq_fd)
> #define OCXL_IOCTL_GET_METADATA _IOR(OCXL_MAGIC, 0x14, struct ocxl_ioctl_metadata)
> +#define OCXL_IOCTL_ENABLE_P9_WAIT _IOR(OCXL_MAGIC, 0x15, struct ocxl_ioctl_p9_wait)
>
> #endif /* _UAPI_MISC_OCXL_H */
>
--
Andrew Donnellan OzLabs, ADL Canberra
andrew.donnellan@au1.ibm.com IBM Australia Limited
^ permalink raw reply
* Re: [PATCH] powerpc/mce: Fix a bug where mce loops on memory UE.
From: Balbir Singh @ 2018-04-23 6:51 UTC (permalink / raw)
To: Mahesh J Salgaonkar; +Cc: linuxppc-dev
In-Reply-To: <152445952887.3244.567606806755236868.stgit@jupiter.in.ibm.com>
On Mon, Apr 23, 2018 at 2:59 PM, Mahesh J Salgaonkar
<mahesh@linux.vnet.ibm.com> wrote:
> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>
> The current code extracts the physical address for UE errors and then
> hooks it up into memory failure infrastructure. On successful extraction
> of physical address it wrongly sets "handled = 1" which means this UE error
> has been recovered. Since MCE handler gets return value as handled = 1, it
> assumes that error has been recovered and goes back to same NIP. This causes
> MCE interrupt again and again in a loop leading to hard lockup.
>
> Also, initialize phys_addr to ULONG_MAX so that we don't end up queuing
> undesired page to hwpoison.
>
> Without this patch we see:
> [ 1476.541984] Severe Machine check interrupt [Recovered]
> [ 1476.541985] NIP: [000000001002588c] PID: 7109 Comm: find
> [ 1476.541986] Initiator: CPU
> [ 1476.541987] Error type: UE [Load/Store]
> [ 1476.541988] Effective address: 00007fffd2755940
> [ 1476.541989] Physical address: 000020181a080000
> [...]
> [ 1476.542003] Severe Machine check interrupt [Recovered]
> [ 1476.542004] NIP: [000000001002588c] PID: 7109 Comm: find
> [ 1476.542005] Initiator: CPU
> [ 1476.542006] Error type: UE [Load/Store]
> [ 1476.542006] Effective address: 00007fffd2755940
> [ 1476.542007] Physical address: 000020181a080000
> [ 1476.542010] Severe Machine check interrupt [Recovered]
> [ 1476.542012] NIP: [000000001002588c] PID: 7109 Comm: find
> [ 1476.542013] Initiator: CPU
> [ 1476.542014] Error type: UE [Load/Store]
> [ 1476.542015] Effective address: 00007fffd2755940
> [ 1476.542016] Physical address: 000020181a080000
> [ 1476.542448] Memory failure: 0x20181a08: recovery action for dirty LRU page: Recovered
> [ 1476.542452] Memory failure: 0x20181a08: already hardware poisoned
> [ 1476.542453] Memory failure: 0x20181a08: already hardware poisoned
> [ 1476.542454] Memory failure: 0x20181a08: already hardware poisoned
> [ 1476.542455] Memory failure: 0x20181a08: already hardware poisoned
> [ 1476.542456] Memory failure: 0x20181a08: already hardware poisoned
> [ 1476.542457] Memory failure: 0x20181a08: already hardware poisoned
> [...]
> [ 1490.972174] Watchdog CPU:38 Hard LOCKUP
>
> After this patch we see:
>
> [ 325.384336] Severe Machine check interrupt [Not recovered]
How did you test for this? If the error was recovered, shouldn't the
process have gotten
a SIGBUS and we should have prevented further access as a part of the handling
(memory_failure()). Do we just need a MF_MUST_KILL in the flags?
Why shouldn't we treat it as handled if we isolate the page?
Thanks,
Balbir Singh.
^ permalink raw reply
* Re: [PATCH v10 08/25] mm: VMA sequence count
From: Minchan Kim @ 2018-04-23 6:42 UTC (permalink / raw)
To: Laurent Dufour
Cc: akpm, mhocko, peterz, kirill, ak, dave, jack, Matthew Wilcox,
benh, mpe, paulus, Thomas Gleixner, Ingo Molnar, hpa, Will Deacon,
Sergey Senozhatsky, Andrea Arcangeli, Alexei Starovoitov,
kemi.wang, sergey.senozhatsky.work, Daniel Jordan, David Rientjes,
Jerome Glisse, Ganesh Mahendran, linux-kernel, linux-mm, haren,
khandual, npiggin, bsingharora, paulmck, Tim Chen, linuxppc-dev,
x86
In-Reply-To: <1523975611-15978-9-git-send-email-ldufour@linux.vnet.ibm.com>
On Tue, Apr 17, 2018 at 04:33:14PM +0200, Laurent Dufour wrote:
> From: Peter Zijlstra <peterz@infradead.org>
>
> Wrap the VMA modifications (vma_adjust/unmap_page_range) with sequence
> counts such that we can easily test if a VMA is changed.
So, seqcount is to protect modifying all attributes of vma?
>
> The unmap_page_range() one allows us to make assumptions about
> page-tables; when we find the seqcount hasn't changed we can assume
> page-tables are still valid.
Hmm, seqcount covers page-table, too.
Please describe what the seqcount want to protect.
>
> The flip side is that we cannot distinguish between a vma_adjust() and
> the unmap_page_range() -- where with the former we could have
> re-checked the vma bounds against the address.
>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
>
> [Port to 4.12 kernel]
> [Build depends on CONFIG_SPECULATIVE_PAGE_FAULT]
> [Introduce vm_write_* inline function depending on
> CONFIG_SPECULATIVE_PAGE_FAULT]
> [Fix lock dependency between mapping->i_mmap_rwsem and vma->vm_sequence by
> using vm_raw_write* functions]
> [Fix a lock dependency warning in mmap_region() when entering the error
> path]
> [move sequence initialisation INIT_VMA()]
> Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
> ---
> include/linux/mm.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
> include/linux/mm_types.h | 3 +++
> mm/memory.c | 2 ++
> mm/mmap.c | 31 +++++++++++++++++++++++++++++++
> 4 files changed, 80 insertions(+)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index efc1248b82bd..988daf7030c9 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1264,6 +1264,9 @@ struct zap_details {
> static inline void INIT_VMA(struct vm_area_struct *vma)
> {
> INIT_LIST_HEAD(&vma->anon_vma_chain);
> +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
> + seqcount_init(&vma->vm_sequence);
> +#endif
> }
>
> struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
> @@ -1386,6 +1389,47 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
> unmap_mapping_range(mapping, holebegin, holelen, 0);
> }
>
> +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
> +static inline void vm_write_begin(struct vm_area_struct *vma)
> +{
> + write_seqcount_begin(&vma->vm_sequence);
> +}
> +static inline void vm_write_begin_nested(struct vm_area_struct *vma,
> + int subclass)
> +{
> + write_seqcount_begin_nested(&vma->vm_sequence, subclass);
> +}
> +static inline void vm_write_end(struct vm_area_struct *vma)
> +{
> + write_seqcount_end(&vma->vm_sequence);
> +}
> +static inline void vm_raw_write_begin(struct vm_area_struct *vma)
> +{
> + raw_write_seqcount_begin(&vma->vm_sequence);
> +}
> +static inline void vm_raw_write_end(struct vm_area_struct *vma)
> +{
> + raw_write_seqcount_end(&vma->vm_sequence);
> +}
> +#else
> +static inline void vm_write_begin(struct vm_area_struct *vma)
> +{
> +}
> +static inline void vm_write_begin_nested(struct vm_area_struct *vma,
> + int subclass)
> +{
> +}
> +static inline void vm_write_end(struct vm_area_struct *vma)
> +{
> +}
> +static inline void vm_raw_write_begin(struct vm_area_struct *vma)
> +{
> +}
> +static inline void vm_raw_write_end(struct vm_area_struct *vma)
> +{
> +}
> +#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
> +
> extern int access_process_vm(struct task_struct *tsk, unsigned long addr,
> void *buf, int len, unsigned int gup_flags);
> extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> index 21612347d311..db5e9d630e7a 100644
> --- a/include/linux/mm_types.h
> +++ b/include/linux/mm_types.h
> @@ -335,6 +335,9 @@ struct vm_area_struct {
> struct mempolicy *vm_policy; /* NUMA policy for the VMA */
> #endif
> struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
> +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
> + seqcount_t vm_sequence;
> +#endif
> } __randomize_layout;
>
> struct core_thread {
> diff --git a/mm/memory.c b/mm/memory.c
> index f86efcb8e268..f7fed053df80 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -1503,6 +1503,7 @@ void unmap_page_range(struct mmu_gather *tlb,
> unsigned long next;
>
> BUG_ON(addr >= end);
The comment about saying it aims for page-table stability will help.
> + vm_write_begin(vma);
> tlb_start_vma(tlb, vma);
> pgd = pgd_offset(vma->vm_mm, addr);
> do {
> @@ -1512,6 +1513,7 @@ void unmap_page_range(struct mmu_gather *tlb,
> next = zap_p4d_range(tlb, vma, pgd, addr, next, details);
> } while (pgd++, addr = next, addr != end);
> tlb_end_vma(tlb, vma);
> + vm_write_end(vma);
> }
>
>
> diff --git a/mm/mmap.c b/mm/mmap.c
> index 8bd9ae1dfacc..813e49589ea1 100644
> --- a/mm/mmap.c
> +++ b/mm/mmap.c
> @@ -692,6 +692,30 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
> long adjust_next = 0;
> int remove_next = 0;
>
> + /*
> + * Why using vm_raw_write*() functions here to avoid lockdep's warning ?
> + *
> + * Locked is complaining about a theoretical lock dependency, involving
> + * 3 locks:
> + * mapping->i_mmap_rwsem --> vma->vm_sequence --> fs_reclaim
> + *
> + * Here are the major path leading to this dependency :
> + * 1. __vma_adjust() mmap_sem -> vm_sequence -> i_mmap_rwsem
> + * 2. move_vmap() mmap_sem -> vm_sequence -> fs_reclaim
> + * 3. __alloc_pages_nodemask() fs_reclaim -> i_mmap_rwsem
> + * 4. unmap_mapping_range() i_mmap_rwsem -> vm_sequence
> + *
> + * So there is no way to solve this easily, especially because in
> + * unmap_mapping_range() the i_mmap_rwsem is grab while the impacted
> + * VMAs are not yet known.
> + * However, the way the vm_seq is used is guarantying that we will
> + * never block on it since we just check for its value and never wait
> + * for it to move, see vma_has_changed() and handle_speculative_fault().
> + */
> + vm_raw_write_begin(vma);
> + if (next)
> + vm_raw_write_begin(next);
> +
> if (next && !insert) {
> struct vm_area_struct *exporter = NULL, *importer = NULL;
>
> @@ -902,6 +926,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
> anon_vma_merge(vma, next);
> mm->map_count--;
> mpol_put(vma_policy(next));
> + vm_raw_write_end(next);
> kmem_cache_free(vm_area_cachep, next);
> /*
> * In mprotect's case 6 (see comments on vma_merge),
> @@ -916,6 +941,8 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
> * "vma->vm_next" gap must be updated.
> */
> next = vma->vm_next;
> + if (next)
> + vm_raw_write_begin(next);
> } else {
> /*
> * For the scope of the comment "next" and
> @@ -962,6 +989,10 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
> if (insert && file)
> uprobe_mmap(insert);
>
> + if (next && next != vma)
> + vm_raw_write_end(next);
> + vm_raw_write_end(vma);
> +
> validate_mm(mm);
>
> return 0;
> --
> 2.7.4
>
^ permalink raw reply
* Re: [PATCH v10 06/25] mm: make pte_unmap_same compatible with SPF
From: Minchan Kim @ 2018-04-23 6:31 UTC (permalink / raw)
To: Laurent Dufour
Cc: akpm, mhocko, peterz, kirill, ak, dave, jack, Matthew Wilcox,
benh, mpe, paulus, Thomas Gleixner, Ingo Molnar, hpa, Will Deacon,
Sergey Senozhatsky, Andrea Arcangeli, Alexei Starovoitov,
kemi.wang, sergey.senozhatsky.work, Daniel Jordan, David Rientjes,
Jerome Glisse, Ganesh Mahendran, linux-kernel, linux-mm, haren,
khandual, npiggin, bsingharora, paulmck, Tim Chen, linuxppc-dev,
x86
In-Reply-To: <1523975611-15978-7-git-send-email-ldufour@linux.vnet.ibm.com>
On Tue, Apr 17, 2018 at 04:33:12PM +0200, Laurent Dufour wrote:
> pte_unmap_same() is making the assumption that the page table are still
> around because the mmap_sem is held.
> This is no more the case when running a speculative page fault and
> additional check must be made to ensure that the final page table are still
> there.
>
> This is now done by calling pte_spinlock() to check for the VMA's
> consistency while locking for the page tables.
>
> This is requiring passing a vm_fault structure to pte_unmap_same() which is
> containing all the needed parameters.
>
> As pte_spinlock() may fail in the case of a speculative page fault, if the
> VMA has been touched in our back, pte_unmap_same() should now return 3
> cases :
> 1. pte are the same (0)
> 2. pte are different (VM_FAULT_PTNOTSAME)
> 3. a VMA's changes has been detected (VM_FAULT_RETRY)
>
> The case 2 is handled by the introduction of a new VM_FAULT flag named
> VM_FAULT_PTNOTSAME which is then trapped in cow_user_page().
I don't see such logic in this patch.
Maybe you introduces it later? If so, please comment on it.
Or just return 0 in case of 2 without introducing VM_FAULT_PTNOTSAME.
> If VM_FAULT_RETRY is returned, it is passed up to the callers to retry the
> page fault while holding the mmap_sem.
>
> Acked-by: David Rientjes <rientjes@google.com>
> Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
> ---
> include/linux/mm.h | 1 +
> mm/memory.c | 39 ++++++++++++++++++++++++++++-----------
> 2 files changed, 29 insertions(+), 11 deletions(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 4d1aff80669c..714da99d77a3 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1208,6 +1208,7 @@ static inline void clear_page_pfmemalloc(struct page *page)
> #define VM_FAULT_NEEDDSYNC 0x2000 /* ->fault did not modify page tables
> * and needs fsync() to complete (for
> * synchronous page faults in DAX) */
> +#define VM_FAULT_PTNOTSAME 0x4000 /* Page table entries have changed */
>
> #define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \
> VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \
> diff --git a/mm/memory.c b/mm/memory.c
> index 0b9a51f80e0e..f86efcb8e268 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -2309,21 +2309,29 @@ static inline bool pte_map_lock(struct vm_fault *vmf)
> * parts, do_swap_page must check under lock before unmapping the pte and
> * proceeding (but do_wp_page is only called after already making such a check;
> * and do_anonymous_page can safely check later on).
> + *
> + * pte_unmap_same() returns:
> + * 0 if the PTE are the same
> + * VM_FAULT_PTNOTSAME if the PTE are different
> + * VM_FAULT_RETRY if the VMA has changed in our back during
> + * a speculative page fault handling.
> */
> -static inline int pte_unmap_same(struct mm_struct *mm, pmd_t *pmd,
> - pte_t *page_table, pte_t orig_pte)
> +static inline int pte_unmap_same(struct vm_fault *vmf)
> {
> - int same = 1;
> + int ret = 0;
> +
> #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
> if (sizeof(pte_t) > sizeof(unsigned long)) {
> - spinlock_t *ptl = pte_lockptr(mm, pmd);
> - spin_lock(ptl);
> - same = pte_same(*page_table, orig_pte);
> - spin_unlock(ptl);
> + if (pte_spinlock(vmf)) {
> + if (!pte_same(*vmf->pte, vmf->orig_pte))
> + ret = VM_FAULT_PTNOTSAME;
> + spin_unlock(vmf->ptl);
> + } else
> + ret = VM_FAULT_RETRY;
> }
> #endif
> - pte_unmap(page_table);
> - return same;
> + pte_unmap(vmf->pte);
> + return ret;
> }
>
> static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va, struct vm_area_struct *vma)
> @@ -2912,10 +2920,19 @@ int do_swap_page(struct vm_fault *vmf)
> pte_t pte;
> int locked;
> int exclusive = 0;
> - int ret = 0;
> + int ret;
>
> - if (!pte_unmap_same(vma->vm_mm, vmf->pmd, vmf->pte, vmf->orig_pte))
> + ret = pte_unmap_same(vmf);
> + if (ret) {
> + /*
> + * If pte != orig_pte, this means another thread did the
> + * swap operation in our back.
> + * So nothing else to do.
> + */
> + if (ret == VM_FAULT_PTNOTSAME)
> + ret = 0;
> goto out;
> + }
>
> entry = pte_to_swp_entry(vmf->orig_pte);
> if (unlikely(non_swap_entry(entry))) {
> --
> 2.7.4
>
^ permalink raw reply
* Re: [PATCH v10 01/25] mm: introduce CONFIG_SPECULATIVE_PAGE_FAULT
From: Minchan Kim @ 2018-04-23 5:58 UTC (permalink / raw)
To: Laurent Dufour
Cc: akpm, mhocko, peterz, kirill, ak, dave, jack, Matthew Wilcox,
benh, mpe, paulus, Thomas Gleixner, Ingo Molnar, hpa, Will Deacon,
Sergey Senozhatsky, Andrea Arcangeli, Alexei Starovoitov,
kemi.wang, sergey.senozhatsky.work, Daniel Jordan, David Rientjes,
Jerome Glisse, Ganesh Mahendran, linux-kernel, linux-mm, haren,
khandual, npiggin, bsingharora, paulmck, Tim Chen, linuxppc-dev,
x86
In-Reply-To: <1523975611-15978-2-git-send-email-ldufour@linux.vnet.ibm.com>
Hi Laurent,
I guess it's good timing to review. Guess LSF/MM goes so might change
a lot since then. :) Anyway, I grap a time to review.
On Tue, Apr 17, 2018 at 04:33:07PM +0200, Laurent Dufour wrote:
> This configuration variable will be used to build the code needed to
> handle speculative page fault.
>
> By default it is turned off, and activated depending on architecture
> support, SMP and MMU.
Can we have description in here why it depends on architecture?
>
> Suggested-by: Thomas Gleixner <tglx@linutronix.de>
> Suggested-by: David Rientjes <rientjes@google.com>
> Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
> ---
> mm/Kconfig | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/mm/Kconfig b/mm/Kconfig
> index d5004d82a1d6..5484dca11199 100644
> --- a/mm/Kconfig
> +++ b/mm/Kconfig
> @@ -752,3 +752,25 @@ config GUP_BENCHMARK
> performance of get_user_pages_fast().
>
> See tools/testing/selftests/vm/gup_benchmark.c
> +
> +config ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT
> + def_bool n
> +
> +config SPECULATIVE_PAGE_FAULT
> + bool "Speculative page faults"
> + default y
> + depends on ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT
> + depends on MMU && SMP
> + help
> + Try to handle user space page faults without holding the mmap_sem.
> +
> + This should allow better concurrency for massively threaded process
> + since the page fault handler will not wait for other threads memory
> + layout change to be done, assuming that this change is done in another
> + part of the process's memory space. This type of page fault is named
> + speculative page fault.
> +
> + If the speculative page fault fails because of a concurrency is
> + detected or because underlying PMD or PTE tables are not yet
> + allocating, it is failing its processing and a classic page fault
> + is then tried.
> --
> 2.7.4
>
^ permalink raw reply
* Re: [PATCH v4 3/7] powerpc/fadump: un-register fadump on kexec path.
From: Mahesh Jagannath Salgaonkar @ 2018-04-23 5:17 UTC (permalink / raw)
To: Nicholas Piggin
Cc: linuxppc-dev, Ananth Narayan, kernelfans, Aneesh Kumar K.V,
Hari Bathini, Nathan Fontenot, Anshuman Khandual,
Srikar Dronamraju
In-Reply-To: <20180422115858.776bac02@roar.ozlabs.ibm.com>
On 04/22/2018 07:28 AM, Nicholas Piggin wrote:
> On Fri, 20 Apr 2018 10:34:35 +0530
> Mahesh J Salgaonkar <mahesh@linux.vnet.ibm.com> wrote:
>
>> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>>
>> otherwise the fadump registration in new kexec-ed kernel complains that
>> fadump is already registered. This makes new kernel to continue using
>> fadump registered by previous kernel which may lead to invalid vmcore
>> generation. Hence this patch fixes this issue by un-registering fadump
>> in fadump_cleanup() which is called during kexec path so that new kernel
>> can register fadump with new valid values.
>
> Is this a bug fix that should go to previous kernels as well?
Yes.
>
>>
>> Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>> ---
>> arch/powerpc/kernel/fadump.c | 3 +++
>> 1 file changed, 3 insertions(+)
>>
>> diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
>> index 43bfa535d0ea..16b3e8c5cae0 100644
>> --- a/arch/powerpc/kernel/fadump.c
>> +++ b/arch/powerpc/kernel/fadump.c
>> @@ -1276,6 +1276,9 @@ void fadump_cleanup(void)
>> /* Invalidate the registration only if dump is active. */
>> if (fw_dump.dump_active) {
>> fadump_invalidate_dump(fdm_active);
>> + } else if (fw_dump.dump_registered) {
>> + /* Un-register Firmware-assisted dump if it was registered. */
>> + fadump_unregister_dump(&fdm);
>> }
>> }
>>
>>
>
^ permalink raw reply
* Re: [PATCH v4 1/7] powerpc/fadump: Move the metadata region to start of the reserved area.
From: Mahesh Jagannath Salgaonkar @ 2018-04-23 5:16 UTC (permalink / raw)
To: Nicholas Piggin
Cc: linuxppc-dev, Ananth Narayan, kernelfans, Aneesh Kumar K.V,
Hari Bathini, Nathan Fontenot, Anshuman Khandual,
Srikar Dronamraju
In-Reply-To: <20180422115816.701d0837@roar.ozlabs.ibm.com>
On 04/22/2018 07:28 AM, Nicholas Piggin wrote:
> On Fri, 20 Apr 2018 10:34:18 +0530
> Mahesh J Salgaonkar <mahesh@linux.vnet.ibm.com> wrote:
>
>> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>>
>> Currently the metadata region that holds crash info structure and ELF core
>> header is placed towards the end of reserved memory area. This patch places
>> it at the beginning of the reserved memory area. It also introduces
>> additional dump section called metadata section to communicate location
>> of metadata region to 2nd kernel. This patch also maintains the
>> compatibility between production/capture kernels irrespective of their
>> kernel versions. Both combination older/newer and newer/older works fine.
>
> Trying to look at the patches it might help me if you document reasons
> for why this change is made changelog, even if it may be obvious to
> someone who knows the code better.
Yeah, I should have mentioned that this patch provides the foundation
for CMA patch 4. With CMA reservation we now allocate metadata region
using cma_alloc() which always allocates metadata region at the start of
CMA reserved region. Earlier in v1, I had this change included along
with CMA reservation patch. But then to make things simpler for review I
did a logical split of movement of metadata region and CMA reservation
patch separately. I think I should order patch 1, 2 and 4 in a sequence
and Move patch3 to patch 1.
>
> I thought you could include the documentation change in this patch as
> well, but maybe that's a matter of preference.
Yeah that's how I prefer it :-), but that just me. But if it helps in
review I can fold it into 1.
Thanks,
-Mahesh.
^ permalink raw reply
* [PATCH] powerpc/mce: Fix a bug where mce loops on memory UE.
From: Mahesh J Salgaonkar @ 2018-04-23 4:59 UTC (permalink / raw)
To: linuxppc-dev
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
The current code extracts the physical address for UE errors and then
hooks it up into memory failure infrastructure. On successful extraction
of physical address it wrongly sets "handled = 1" which means this UE error
has been recovered. Since MCE handler gets return value as handled = 1, it
assumes that error has been recovered and goes back to same NIP. This causes
MCE interrupt again and again in a loop leading to hard lockup.
Also, initialize phys_addr to ULONG_MAX so that we don't end up queuing
undesired page to hwpoison.
Without this patch we see:
[ 1476.541984] Severe Machine check interrupt [Recovered]
[ 1476.541985] NIP: [000000001002588c] PID: 7109 Comm: find
[ 1476.541986] Initiator: CPU
[ 1476.541987] Error type: UE [Load/Store]
[ 1476.541988] Effective address: 00007fffd2755940
[ 1476.541989] Physical address: 000020181a080000
[...]
[ 1476.542003] Severe Machine check interrupt [Recovered]
[ 1476.542004] NIP: [000000001002588c] PID: 7109 Comm: find
[ 1476.542005] Initiator: CPU
[ 1476.542006] Error type: UE [Load/Store]
[ 1476.542006] Effective address: 00007fffd2755940
[ 1476.542007] Physical address: 000020181a080000
[ 1476.542010] Severe Machine check interrupt [Recovered]
[ 1476.542012] NIP: [000000001002588c] PID: 7109 Comm: find
[ 1476.542013] Initiator: CPU
[ 1476.542014] Error type: UE [Load/Store]
[ 1476.542015] Effective address: 00007fffd2755940
[ 1476.542016] Physical address: 000020181a080000
[ 1476.542448] Memory failure: 0x20181a08: recovery action for dirty LRU page: Recovered
[ 1476.542452] Memory failure: 0x20181a08: already hardware poisoned
[ 1476.542453] Memory failure: 0x20181a08: already hardware poisoned
[ 1476.542454] Memory failure: 0x20181a08: already hardware poisoned
[ 1476.542455] Memory failure: 0x20181a08: already hardware poisoned
[ 1476.542456] Memory failure: 0x20181a08: already hardware poisoned
[ 1476.542457] Memory failure: 0x20181a08: already hardware poisoned
[...]
[ 1490.972174] Watchdog CPU:38 Hard LOCKUP
After this patch we see:
[ 325.384336] Severe Machine check interrupt [Not recovered]
[ 325.384338] NIP: [00007fffaae585f4] PID: 7168 Comm: find
[ 325.384339] Initiator: CPU
[ 325.384341] Error type: UE [Load/Store]
[ 325.384343] Effective address: 00007fffaafe28ac
[ 325.384345] Physical address: 00002017c0bd0000
[ 325.384350] find[7168]: unhandled signal 7 at 00007fffaae585f4 nip 00007fffaae585f4 lr 00007fffaae585e0 code 4
[ 325.388574] Memory failure: 0x2017c0bd: recovery action for dirty LRU page: Recovered
Fixes: 01eaac2b0591 ("powerpc/mce: Hookup ierror (instruction) UE errors")
Fixes: ba41e1e1ccb9 ("powerpc/mce: Hookup derror (load/store) UE errors")
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
arch/powerpc/kernel/mce_power.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
index fe6fc63251fe..63b58ae5d601 100644
--- a/arch/powerpc/kernel/mce_power.c
+++ b/arch/powerpc/kernel/mce_power.c
@@ -441,7 +441,6 @@ static int mce_handle_ierror(struct pt_regs *regs,
if (pfn != ULONG_MAX) {
*phys_addr =
(pfn << PAGE_SHIFT);
- handled = 1;
}
}
}
@@ -532,9 +531,8 @@ static int mce_handle_derror(struct pt_regs *regs,
* kernel/exception-64s.h
*/
if (get_paca()->in_mce < MAX_MCE_DEPTH)
- if (!mce_find_instr_ea_and_pfn(regs, addr,
- phys_addr))
- handled = 1;
+ mce_find_instr_ea_and_pfn(regs, addr,
+ phys_addr);
}
found = 1;
}
@@ -572,7 +570,7 @@ static long mce_handle_error(struct pt_regs *regs,
const struct mce_ierror_table itable[])
{
struct mce_error_info mce_err = { 0 };
- uint64_t addr, phys_addr;
+ uint64_t addr, phys_addr = ULONG_MAX;
uint64_t srr1 = regs->msr;
long handled;
^ permalink raw reply related
* Re: [PATCH net] ibmvnic: Clean actual number of RX or TX pools
From: David Miller @ 2018-04-23 1:13 UTC (permalink / raw)
To: tlfalcon; +Cc: netdev, nfont, jallen, linuxppc-dev
In-Reply-To: <1524252332-10272-1-git-send-email-tlfalcon@linux.vnet.ibm.com>
From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
Date: Fri, 20 Apr 2018 14:25:32 -0500
> Avoid using value stored in the login response buffer when
> cleaning TX and RX buffer pools since these could be inconsistent
> depending on the device state. Instead use the field in the driver's
> private data that tracks the number of active pools.
>
> Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
Applied.
^ permalink raw reply
* Re: [PATCH] x86: ipc: fix x32 version of shmid64_ds and msqid64_ds
From: Arnd Bergmann @ 2018-04-22 20:17 UTC (permalink / raw)
To: H.J. Lu
Cc: Jeffrey Walton, the arch/x86 maintainers, Thomas Gleixner,
Ingo Molnar, Eric W . Biederman, y2038 Mailman List, LKML,
Linux API, linux-arch, GNU C Library, Deepa Dinamani, Al Viro,
Albert ARIBAUD, linux-s390, Martin Schwidefsky, Catalin Marinas,
Will Deacon, open list:RALINK MIPS ARCHITECTURE, James Hogan,
Ralf Baechle, linuxppc-dev, sparclinux, Ben Hutchings,
Daniel Schepler, Adam Borowski, John Paul Adrian Glaubitz,
# 3.4.x, H. Peter Anvin
In-Reply-To: <CAMe9rOrTzgDmCF+A7nYdGR6BHZBuK5SMnJxeRxBFQW00VmdXvg@mail.gmail.com>
On Sun, Apr 22, 2018 at 2:38 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Apr 20, 2018 at 7:38 AM, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Fri, Apr 20, 2018 at 3:53 PM, Jeffrey Walton <noloader@gmail.com> wrote:
>
> Glibc has correct header files for system calls. I have a very old
> program to check if Linux kernel header files are correct for user
> space:
>
> https://github.com/hjl-tools/linux-header
>
> It needs update to check uapi.
Simply running 'make' on a regular distro shows this output:
--- kernel.x32.out 2018-04-22 22:10:16.053432423 +0200
+++ glibc.x32.out 2018-04-22 22:10:16.073432838 +0200
@@ -10,9 +10,9 @@ size of daddr_t: 4
size of __ipc_pid_t: 4
size of struct ipc_perm: 48
size of mqd_t: 4
-size of struct msqid_ds: 144
+size of struct msqid_ds: 120
size of struct semid_ds: 104
-size of struct shmid_ds: 136
+size of struct shmid_ds: 112
size of struct shminfo: 72
size of struct timeval: 16
size of struct timespec: 16
@@ -22,8 +22,8 @@ size of struct mq_attr: 64
size of struct rlimit: 16
size of struct rusage: 144
size of struct stat: 144
-size of struct statfs: 64
-size of struct statfs64: 88
+size of struct statfs: 120
+size of struct statfs64: 120
size of struct timex: 208
size of struct msginfo: 32
size of struct msgbuf: 16
This seems plausible, the statfs structure clearly has the same problem
as msqid_ds/shmid_ds based on its usage of '__statfs_word' which is
now defined as '__u32' rather than '__kernel_long_t'.
It should be trivial to override __statfs_word from
arch/x86/include/uapi/asm/statfs.h
I've checked the other uses of __BITS_PER_LONG in the uapi
headers now, and all the others are either not relevant for x32
(either definition is fine) or it has to be __BITS_PER_LONG=32.
Arnd
^ permalink raw reply
* Re: [PATCH 0/6] tree-wide: simplify getting .drvdata
From: Vinod Koul @ 2018-04-22 16:11 UTC (permalink / raw)
To: Wolfram Sang; +Cc: dmaengine, linux-arm-kernel, linux-kernel, linuxppc-dev
In-Reply-To: <20180422091415.7587-1-wsa+renesas@sang-engineering.com>
On Sun, Apr 22, 2018 at 11:14:08AM +0200, Wolfram Sang wrote:
> I got tired of fixing this in Renesas drivers manually, so I took the big
> hammer. Remove this cumbersome code pattern which got copy-pasted too much
> already:
>
> - struct platform_device *pdev = to_platform_device(dev);
> - struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
> + struct ep93xx_keypad *keypad = dev_get_drvdata(dev);
>
> I send this out as one patch per directory per subsystem. I think they should
> be applied individually. If you prefer a broken out series per subsystem, I can
> provide this as well. Just mail me.
Applied all, thanks
--
~Vinod
^ permalink raw reply
* Re: [PATCH] x86: ipc: fix x32 version of shmid64_ds and msqid64_ds
From: H.J. Lu @ 2018-04-22 12:38 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Jeffrey Walton, the arch/x86 maintainers, Thomas Gleixner,
Ingo Molnar, Eric W . Biederman, y2038 Mailman List, LKML,
Linux API, linux-arch, GNU C Library, Deepa Dinamani, Al Viro,
Albert ARIBAUD, linux-s390, Martin Schwidefsky, Catalin Marinas,
Will Deacon, open list:RALINK MIPS ARCHITECTURE, James Hogan,
Ralf Baechle, linuxppc-dev, sparclinux, Ben Hutchings,
Daniel Schepler, Adam Borowski, Thorsten Glaser,
John Paul Adrian Glaubitz, # 3.4.x, H. Peter Anvin
In-Reply-To: <CAK8P3a0nL4B+t6BMRhr36RrZ_jDgwnY1BviNPD+cFzsUGeppmA@mail.gmail.com>
On Fri, Apr 20, 2018 at 7:38 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Fri, Apr 20, 2018 at 3:53 PM, Jeffrey Walton <noloader@gmail.com> wrote:
>>> +#if !defined(__x86_64__) || !defined(__ilp32__)
>>> #include <asm-generic/msgbuf.h>
>>> +#else
>>
>> I understand there's some progress having Clang compile the kernel.
>> Clang treats __ILP32__ and friends differently than GCC. I believe
>> ILP32 shows up just about everywhere there are 32-bit ints, longs and
>> pointers. You might find it on Aarch64 or you might find it on MIPS64
>> when using Clang.
>>
>> I think that means this may be a little suspicious:
>>
>> > +#if !defined(__x86_64__) || !defined(__ilp32__)
>>
>> I kind of felt LLVM was wandering away from the x32 ABI, but the LLVM
>> devs insisted they were within their purview. Also see
>> https://lists.llvm.org/pipermail/cfe-dev/2015-December/046300.html.
>>
>> Sorry about the top-post. I just wanted to pick out that one piece.
>
> It seems I made a typo and it needs to be __ILP32__ rather than
> __ilp32__ (corrected that locally, will resend once we have resolved
> this).
>
> Aside from that, the #if check seems to be correct to me: this
> is an x86-specific header, so it won't ever be seen on other
> architectures. On x86-32, __x86_64__ isn't set, so we don't care
> about whether __ilp32__ is set or not, and on x86-64 (lp64),
> __ilp32__ is never set, so we still get the asm-generic header.
>
Glibc has correct header files for system calls. I have a very old
program to check if Linux kernel header files are correct for user
space:
https://github.com/hjl-tools/linux-header
It needs update to check uapi.
--
H.J.
^ permalink raw reply
* Re: [PATCH 07/61] dma: simplify getting .drvdata
From: Wolfram Sang @ 2018-04-22 9:14 UTC (permalink / raw)
To: Vinod Koul
Cc: Wolfram Sang, linux-kernel, linux-renesas-soc, kernel-janitors,
Ludovic Desroches, Dan Williams, Li Yang, Zhang Wei,
Linus Walleij, linux-arm-kernel, dmaengine, linuxppc-dev
In-Reply-To: <20180422061733.GU6014@localhost>
[-- Attachment #1: Type: text/plain, Size: 367 bytes --]
On Sun, Apr 22, 2018 at 11:47:33AM +0530, Vinod Koul wrote:
> On Thu, Apr 19, 2018 at 04:05:37PM +0200, Wolfram Sang wrote:
> > We should get drvdata from struct device directly. Going via
> > platform_device is an unneeded step back and forth.
>
> Do you mind splitting this per driver please, that makes it easy to manage
> for me :)
No problem, done.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH 0/6] tree-wide: simplify getting .drvdata
From: Wolfram Sang @ 2018-04-22 9:14 UTC (permalink / raw)
To: dmaengine; +Cc: Wolfram Sang, linux-arm-kernel, linux-kernel, linuxppc-dev
I got tired of fixing this in Renesas drivers manually, so I took the big
hammer. Remove this cumbersome code pattern which got copy-pasted too much
already:
- struct platform_device *pdev = to_platform_device(dev);
- struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
+ struct ep93xx_keypad *keypad = dev_get_drvdata(dev);
I send this out as one patch per directory per subsystem. I think they should
be applied individually. If you prefer a broken out series per subsystem, I can
provide this as well. Just mail me.
A branch (tested by buildbot; only with all commits squashed into one commit
before) can be found here:
git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git coccinelle/get_drvdata
Open for other comments, suggestions, too, of course.
Here is the cocci-script I created:
@@
struct device* d;
identifier pdev;
expression *ptr;
@@
(
- struct platform_device *pdev = to_platform_device(d);
|
- struct platform_device *pdev;
...
- pdev = to_platform_device(d);
)
<... when != pdev
- &pdev->dev
+ d
...>
ptr =
- platform_get_drvdata(pdev)
+ dev_get_drvdata(d)
<... when != pdev
- &pdev->dev
+ d
...>
Kind regards,
Wolfram
Wolfram Sang (6):
dmaengine: at_hdmac: simplify getting .drvdata
dmaengine: at_xdmac: simplify getting .drvdata
dmaengine: fsldma: simplify getting .drvdata
dmaengine: idma64: simplify getting .drvdata
dmaengine: ste_dma40: simplify getting .drvdata
dmaengine: txx9dmac: simplify getting .drvdata
drivers/dma/at_hdmac.c | 9 +++------
drivers/dma/at_xdmac.c | 9 +++------
drivers/dma/fsldma.c | 6 ++----
drivers/dma/idma64.c | 6 ++----
drivers/dma/ste_dma40.c | 12 ++++--------
drivers/dma/txx9dmac.c | 8 +++-----
6 files changed, 17 insertions(+), 33 deletions(-)
--
2.11.0
^ permalink raw reply
* [PATCH 3/6] dmaengine: fsldma: simplify getting .drvdata
From: Wolfram Sang @ 2018-04-22 9:14 UTC (permalink / raw)
To: dmaengine
Cc: Wolfram Sang, Li Yang, Zhang Wei, Vinod Koul, Dan Williams,
linuxppc-dev, linux-kernel
In-Reply-To: <20180422091415.7587-1-wsa+renesas@sang-engineering.com>
We should get drvdata from struct device directly. Going via
platform_device is an unneeded step back and forth.
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
Build tested only. buildbot is happy. Please apply to your tree directly.
drivers/dma/fsldma.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 3eaece888e75..1117b5123a6f 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1328,8 +1328,7 @@ static int fsldma_of_remove(struct platform_device *op)
#ifdef CONFIG_PM
static int fsldma_suspend_late(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct fsldma_device *fdev = platform_get_drvdata(pdev);
+ struct fsldma_device *fdev = dev_get_drvdata(dev);
struct fsldma_chan *chan;
int i;
@@ -1360,8 +1359,7 @@ static int fsldma_suspend_late(struct device *dev)
static int fsldma_resume_early(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct fsldma_device *fdev = platform_get_drvdata(pdev);
+ struct fsldma_device *fdev = dev_get_drvdata(dev);
struct fsldma_chan *chan;
u32 mode;
int i;
--
2.11.0
^ permalink raw reply related
* Re: [PATCH 07/61] dma: simplify getting .drvdata
From: Vinod Koul @ 2018-04-22 6:17 UTC (permalink / raw)
To: Wolfram Sang
Cc: linux-kernel, linux-renesas-soc, kernel-janitors,
Ludovic Desroches, Dan Williams, Li Yang, Zhang Wei,
Linus Walleij, linux-arm-kernel, dmaengine, linuxppc-dev
In-Reply-To: <20180419140641.27926-8-wsa+renesas@sang-engineering.com>
On Thu, Apr 19, 2018 at 04:05:37PM +0200, Wolfram Sang wrote:
> We should get drvdata from struct device directly. Going via
> platform_device is an unneeded step back and forth.
Do you mind splitting this per driver please, that makes it easy to manage
for me :)
--
~Vinod
^ permalink raw reply
* Re: [PATCH v4 3/7] powerpc/fadump: un-register fadump on kexec path.
From: Nicholas Piggin @ 2018-04-22 1:58 UTC (permalink / raw)
To: Mahesh J Salgaonkar
Cc: linuxppc-dev, Ananth Narayan, kernelfans, Aneesh Kumar K.V,
Hari Bathini, Nathan Fontenot, Anshuman Khandual,
Srikar Dronamraju
In-Reply-To: <152420067500.31037.2795727017934578072.stgit@jupiter.in.ibm.com>
On Fri, 20 Apr 2018 10:34:35 +0530
Mahesh J Salgaonkar <mahesh@linux.vnet.ibm.com> wrote:
> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>
> otherwise the fadump registration in new kexec-ed kernel complains that
> fadump is already registered. This makes new kernel to continue using
> fadump registered by previous kernel which may lead to invalid vmcore
> generation. Hence this patch fixes this issue by un-registering fadump
> in fadump_cleanup() which is called during kexec path so that new kernel
> can register fadump with new valid values.
Is this a bug fix that should go to previous kernels as well?
>
> Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
> ---
> arch/powerpc/kernel/fadump.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
> index 43bfa535d0ea..16b3e8c5cae0 100644
> --- a/arch/powerpc/kernel/fadump.c
> +++ b/arch/powerpc/kernel/fadump.c
> @@ -1276,6 +1276,9 @@ void fadump_cleanup(void)
> /* Invalidate the registration only if dump is active. */
> if (fw_dump.dump_active) {
> fadump_invalidate_dump(fdm_active);
> + } else if (fw_dump.dump_registered) {
> + /* Un-register Firmware-assisted dump if it was registered. */
> + fadump_unregister_dump(&fdm);
> }
> }
>
>
^ permalink raw reply
* Re: [PATCH v4 1/7] powerpc/fadump: Move the metadata region to start of the reserved area.
From: Nicholas Piggin @ 2018-04-22 1:58 UTC (permalink / raw)
To: Mahesh J Salgaonkar
Cc: linuxppc-dev, Ananth Narayan, kernelfans, Aneesh Kumar K.V,
Hari Bathini, Nathan Fontenot, Anshuman Khandual,
Srikar Dronamraju
In-Reply-To: <152420065839.31037.9373191008433546810.stgit@jupiter.in.ibm.com>
On Fri, 20 Apr 2018 10:34:18 +0530
Mahesh J Salgaonkar <mahesh@linux.vnet.ibm.com> wrote:
> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>
> Currently the metadata region that holds crash info structure and ELF core
> header is placed towards the end of reserved memory area. This patch places
> it at the beginning of the reserved memory area. It also introduces
> additional dump section called metadata section to communicate location
> of metadata region to 2nd kernel. This patch also maintains the
> compatibility between production/capture kernels irrespective of their
> kernel versions. Both combination older/newer and newer/older works fine.
Trying to look at the patches it might help me if you document reasons
for why this change is made changelog, even if it may be obvious to
someone who knows the code better.
I thought you could include the documentation change in this patch as
well, but maybe that's a matter of preference.
Thanks,
Nick
^ 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