* [PATCH RESEND v9] serial: stm32-usart: Add STM32 USART Driver
From: Maxime Coquelin @ 2015-06-10 19:19 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby,
linux-serial-u79uwXL29TY76Z2rM5mHXA
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA
This drivers adds support to the STM32 USART controller, which is a
standard serial driver.
Tested-by: Chanwoo Choi <cw00.choi-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Reviewed-by: Peter Hurley <peter-WaGBZJeGNqdsbIuE7sb01tBPR1lH4CV8@public.gmane.org>
Reviewed-by: Vladimir Zapolskiy <vladimir_zapolskiy-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
Reviewed-by: Andy Shevchenko <andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
drivers/tty/serial/Kconfig | 17 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/stm32-usart.c | 739 +++++++++++++++++++++++++++++++++++++++
include/uapi/linux/serial_core.h | 3 +
4 files changed, 760 insertions(+)
create mode 100644 drivers/tty/serial/stm32-usart.c
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index da45877..a74dabc 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1608,6 +1608,23 @@ config SERIAL_SPRD_CONSOLE
with "earlycon" on the kernel command line. The console is
enabled when early_param is processed.
+config SERIAL_STM32
+ tristate "STMicroelectronics STM32 serial port support"
+ select SERIAL_CORE
+ depends on ARM || COMPILE_TEST
+ help
+ This driver is for the on-chip Serial Controller on
+ STMicroelectronics STM32 MCUs.
+ USART supports Rx & Tx functionality.
+ It support all industry standard baud rates.
+
+ If unsure, say N.
+
+config SERIAL_STM32_CONSOLE
+ bool "Support for console on STM32"
+ depends on SERIAL_STM32=y
+ select SERIAL_CORE_CONSOLE
+
endmenu
config SERIAL_MCTRL_GPIO
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index d296cee2..5ab4111 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -92,6 +92,7 @@ obj-$(CONFIG_SERIAL_FSL_LPUART) += fsl_lpuart.o
obj-$(CONFIG_SERIAL_CONEXANT_DIGICOLOR) += digicolor-usart.o
obj-$(CONFIG_SERIAL_MEN_Z135) += men_z135_uart.o
obj-$(CONFIG_SERIAL_SPRD) += sprd_serial.o
+obj-$(CONFIG_SERIAL_STM32) += stm32-usart.o
# GPIOLIB helpers for modem control lines
obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
new file mode 100644
index 0000000..4a6eab6
--- /dev/null
+++ b/drivers/tty/serial/stm32-usart.c
@@ -0,0 +1,739 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Inspired by st-asc.c from STMicroelectronics (c)
+ */
+
+#if defined(CONFIG_SERIAL_STM32_USART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/serial_core.h>
+#include <linux/clk.h>
+
+#define DRIVER_NAME "stm32-usart"
+
+/* Register offsets */
+#define USART_SR 0x00
+#define USART_DR 0x04
+#define USART_BRR 0x08
+#define USART_CR1 0x0c
+#define USART_CR2 0x10
+#define USART_CR3 0x14
+#define USART_GTPR 0x18
+
+/* USART_SR */
+#define USART_SR_PE BIT(0)
+#define USART_SR_FE BIT(1)
+#define USART_SR_NF BIT(2)
+#define USART_SR_ORE BIT(3)
+#define USART_SR_IDLE BIT(4)
+#define USART_SR_RXNE BIT(5)
+#define USART_SR_TC BIT(6)
+#define USART_SR_TXE BIT(7)
+#define USART_SR_LBD BIT(8)
+#define USART_SR_CTS BIT(9)
+#define USART_SR_ERR_MASK (USART_SR_LBD | USART_SR_ORE | \
+ USART_SR_FE | USART_SR_PE)
+/* Dummy bits */
+#define USART_SR_DUMMY_RX BIT(16)
+
+/* USART_DR */
+#define USART_DR_MASK GENMASK(8, 0)
+
+/* USART_BRR */
+#define USART_BRR_DIV_F_MASK GENMASK(3, 0)
+#define USART_BRR_DIV_M_MASK GENMASK(15, 4)
+#define USART_BRR_DIV_M_SHIFT 4
+
+/* USART_CR1 */
+#define USART_CR1_SBK BIT(0)
+#define USART_CR1_RWU BIT(1)
+#define USART_CR1_RE BIT(2)
+#define USART_CR1_TE BIT(3)
+#define USART_CR1_IDLEIE BIT(4)
+#define USART_CR1_RXNEIE BIT(5)
+#define USART_CR1_TCIE BIT(6)
+#define USART_CR1_TXEIE BIT(7)
+#define USART_CR1_PEIE BIT(8)
+#define USART_CR1_PS BIT(9)
+#define USART_CR1_PCE BIT(10)
+#define USART_CR1_WAKE BIT(11)
+#define USART_CR1_M BIT(12)
+#define USART_CR1_UE BIT(13)
+#define USART_CR1_OVER8 BIT(15)
+#define USART_CR1_IE_MASK GENMASK(8, 4)
+
+/* USART_CR2 */
+#define USART_CR2_ADD_MASK GENMASK(3, 0)
+#define USART_CR2_LBDL BIT(5)
+#define USART_CR2_LBDIE BIT(6)
+#define USART_CR2_LBCL BIT(8)
+#define USART_CR2_CPHA BIT(9)
+#define USART_CR2_CPOL BIT(10)
+#define USART_CR2_CLKEN BIT(11)
+#define USART_CR2_STOP_2B BIT(13)
+#define USART_CR2_STOP_MASK GENMASK(13, 12)
+#define USART_CR2_LINEN BIT(14)
+
+/* USART_CR3 */
+#define USART_CR3_EIE BIT(0)
+#define USART_CR3_IREN BIT(1)
+#define USART_CR3_IRLP BIT(2)
+#define USART_CR3_HDSEL BIT(3)
+#define USART_CR3_NACK BIT(4)
+#define USART_CR3_SCEN BIT(5)
+#define USART_CR3_DMAR BIT(6)
+#define USART_CR3_DMAT BIT(7)
+#define USART_CR3_RTSE BIT(8)
+#define USART_CR3_CTSE BIT(9)
+#define USART_CR3_CTSIE BIT(10)
+#define USART_CR3_ONEBIT BIT(11)
+
+/* USART_GTPR */
+#define USART_GTPR_PSC_MASK GENMASK(7, 0)
+#define USART_GTPR_GT_MASK GENMASK(15, 8)
+
+#define DRIVER_NAME "stm32-usart"
+#define STM32_SERIAL_NAME "ttyS"
+#define STM32_MAX_PORTS 6
+
+struct stm32_port {
+ struct uart_port port;
+ struct clk *clk;
+ bool hw_flow_control;
+};
+
+static struct stm32_port stm32_ports[STM32_MAX_PORTS];
+static struct uart_driver stm32_usart_driver;
+
+static void stm32_stop_tx(struct uart_port *port);
+
+static inline struct stm32_port *to_stm32_port(struct uart_port *port)
+{
+ return container_of(port, struct stm32_port, port);
+}
+
+static void stm32_set_bits(struct uart_port *port, u32 reg, u32 bits)
+{
+ u32 val;
+
+ val = readl_relaxed(port->membase + reg);
+ val |= bits;
+ writel_relaxed(val, port->membase + reg);
+}
+
+static void stm32_clr_bits(struct uart_port *port, u32 reg, u32 bits)
+{
+ u32 val;
+
+ val = readl_relaxed(port->membase + reg);
+ val &= ~bits;
+ writel_relaxed(val, port->membase + reg);
+}
+
+static void stm32_receive_chars(struct uart_port *port)
+{
+ struct tty_port *tport = &port->state->port;
+ unsigned long c;
+ u32 sr;
+ char flag;
+
+ if (port->irq_wake)
+ pm_wakeup_event(tport->tty->dev, 0);
+
+ while ((sr = readl_relaxed(port->membase + USART_SR)) & USART_SR_RXNE) {
+ sr |= USART_SR_DUMMY_RX;
+ c = readl_relaxed(port->membase + USART_DR);
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+
+ if (sr & USART_SR_ERR_MASK) {
+ if (sr & USART_SR_LBD) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ continue;
+ } else if (sr & USART_SR_ORE) {
+ port->icount.overrun++;
+ } else if (sr & USART_SR_PE) {
+ port->icount.parity++;
+ } else if (sr & USART_SR_FE) {
+ port->icount.frame++;
+ }
+
+ sr &= port->read_status_mask;
+
+ if (sr & USART_SR_LBD)
+ flag = TTY_BREAK;
+ else if (sr & USART_SR_PE)
+ flag = TTY_PARITY;
+ else if (sr & USART_SR_FE)
+ flag = TTY_FRAME;
+ }
+
+ if (uart_handle_sysrq_char(port, c))
+ continue;
+ uart_insert_char(port, sr, USART_SR_ORE, c, flag);
+ }
+
+ spin_unlock(&port->lock);
+ tty_flip_buffer_push(tport);
+ spin_lock(&port->lock);
+}
+
+static void stm32_transmit_chars(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+
+ if (port->x_char) {
+ writel_relaxed(port->x_char, port->membase + USART_DR);
+ port->x_char = 0;
+ port->icount.tx++;
+ return;
+ }
+
+ if (uart_tx_stopped(port)) {
+ stm32_stop_tx(port);
+ return;
+ }
+
+ if (uart_circ_empty(xmit)) {
+ stm32_stop_tx(port);
+ return;
+ }
+
+ writel_relaxed(xmit->buf[xmit->tail], port->membase + USART_DR);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ stm32_stop_tx(port);
+}
+
+static irqreturn_t stm32_interrupt(int irq, void *ptr)
+{
+ struct uart_port *port = ptr;
+ u32 sr;
+
+ spin_lock(&port->lock);
+
+ sr = readl_relaxed(port->membase + USART_SR);
+
+ if (sr & USART_SR_RXNE)
+ stm32_receive_chars(port);
+
+ if (sr & USART_SR_TXE)
+ stm32_transmit_chars(port);
+
+ spin_unlock(&port->lock);
+
+ return IRQ_HANDLED;
+}
+
+static unsigned int stm32_tx_empty(struct uart_port *port)
+{
+ return readl_relaxed(port->membase + USART_SR) & USART_SR_TXE;
+}
+
+static void stm32_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
+ stm32_set_bits(port, USART_CR3, USART_CR3_RTSE);
+ else
+ stm32_clr_bits(port, USART_CR3, USART_CR3_RTSE);
+}
+
+static unsigned int stm32_get_mctrl(struct uart_port *port)
+{
+ /* This routine is used to get signals of: DCD, DSR, RI, and CTS */
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/* Transmit stop */
+static void stm32_stop_tx(struct uart_port *port)
+{
+ stm32_clr_bits(port, USART_CR1, USART_CR1_TXEIE);
+}
+
+/* There are probably characters waiting to be transmitted. */
+static void stm32_start_tx(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+
+ if (uart_circ_empty(xmit))
+ return;
+
+ stm32_set_bits(port, USART_CR1, USART_CR1_TXEIE | USART_CR1_TE);
+}
+
+/* Throttle the remote when input buffer is about to overflow. */
+static void stm32_throttle(struct uart_port *port)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ stm32_clr_bits(port, USART_CR1, USART_CR1_RXNEIE);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* Unthrottle the remote, the input buffer can now accept data. */
+static void stm32_unthrottle(struct uart_port *port)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ stm32_set_bits(port, USART_CR1, USART_CR1_RXNEIE);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* Receive stop */
+static void stm32_stop_rx(struct uart_port *port)
+{
+ stm32_clr_bits(port, USART_CR1, USART_CR1_RXNEIE);
+}
+
+/* Handle breaks - ignored by us */
+static void stm32_break_ctl(struct uart_port *port, int break_state)
+{
+}
+
+static int stm32_startup(struct uart_port *port)
+{
+ const char *name = to_platform_device(port->dev)->name;
+ u32 val;
+ int ret;
+
+ ret = request_irq(port->irq, stm32_interrupt, IRQF_NO_SUSPEND,
+ name, port);
+ if (ret)
+ return ret;
+
+ val = USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
+ stm32_set_bits(port, USART_CR1, val);
+
+ return 0;
+}
+
+static void stm32_shutdown(struct uart_port *port)
+{
+ u32 val;
+
+ val = USART_CR1_TXEIE | USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
+ stm32_set_bits(port, USART_CR1, val);
+
+ free_irq(port->irq, port);
+}
+
+static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ unsigned int baud;
+ u32 usartdiv, mantissa, fraction, oversampling;
+ tcflag_t cflag = termios->c_cflag;
+ u32 cr1, cr2, cr3;
+ unsigned long flags;
+
+ if (!stm32_port->hw_flow_control)
+ cflag &= ~CRTSCTS;
+
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 8);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* Stop serial port and reset value */
+ writel_relaxed(0, port->membase + USART_CR1);
+
+ cr1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE | USART_CR1_RXNEIE;
+ cr2 = 0;
+ cr3 = 0;
+
+ if (cflag & CSTOPB)
+ cr2 |= USART_CR2_STOP_2B;
+
+ if (cflag & PARENB) {
+ cr1 |= USART_CR1_PCE;
+ if ((cflag & CSIZE) == CS8)
+ cr1 |= USART_CR1_M;
+ }
+
+ if (cflag & PARODD)
+ cr1 |= USART_CR1_PS;
+
+ port->status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS);
+ if (cflag & CRTSCTS) {
+ port->status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;
+ cr3 |= USART_CR3_CTSE;
+ }
+
+ usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud);
+
+ /*
+ * The USART supports 16 or 8 times oversampling.
+ * By default we prefer 16 times oversampling, so that the receiver
+ * has a better tolerance to clock deviations.
+ * 8 times oversampling is only used to achieve higher speeds.
+ */
+ if (usartdiv < 16) {
+ oversampling = 8;
+ stm32_set_bits(port, USART_CR1, USART_CR1_OVER8);
+ } else {
+ oversampling = 16;
+ stm32_clr_bits(port, USART_CR1, USART_CR1_OVER8);
+ }
+
+ mantissa = (usartdiv / oversampling) << USART_BRR_DIV_M_SHIFT;
+ fraction = usartdiv % oversampling;
+ writel_relaxed(mantissa | fraction, port->membase + USART_BRR);
+
+ uart_update_timeout(port, cflag, baud);
+
+ port->read_status_mask = USART_SR_ORE;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= USART_SR_PE | USART_SR_FE;
+ if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
+ port->read_status_mask |= USART_SR_LBD;
+
+ /* Characters to ignore */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask = USART_SR_PE | USART_SR_FE;
+ if (termios->c_iflag & IGNBRK) {
+ port->ignore_status_mask |= USART_SR_LBD;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= USART_SR_ORE;
+ }
+
+ /* Ignore all characters if CREAD is not set */
+ if ((termios->c_cflag & CREAD) == 0)
+ port->ignore_status_mask |= USART_SR_DUMMY_RX;
+
+ writel_relaxed(cr3, port->membase + USART_CR3);
+ writel_relaxed(cr2, port->membase + USART_CR2);
+ writel_relaxed(cr1, port->membase + USART_CR1);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *stm32_type(struct uart_port *port)
+{
+ return (port->type == PORT_STM32) ? DRIVER_NAME : NULL;
+}
+
+static void stm32_release_port(struct uart_port *port)
+{
+}
+
+static int stm32_request_port(struct uart_port *port)
+{
+ return 0;
+}
+
+static void stm32_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE)
+ port->type = PORT_STM32;
+}
+
+static int
+stm32_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ /* No user changeable parameters */
+ return -EINVAL;
+}
+
+static void stm32_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+ struct stm32_port *stm32port = container_of(port,
+ struct stm32_port, port);
+ unsigned long flags = 0;
+
+ switch (state) {
+ case UART_PM_STATE_ON:
+ clk_prepare_enable(stm32port->clk);
+ break;
+ case UART_PM_STATE_OFF:
+ spin_lock_irqsave(&port->lock, flags);
+ stm32_clr_bits(port, USART_CR1, USART_CR1_UE);
+ spin_unlock_irqrestore(&port->lock, flags);
+ clk_disable_unprepare(stm32port->clk);
+ break;
+ }
+}
+
+static const struct uart_ops stm32_uart_ops = {
+ .tx_empty = stm32_tx_empty,
+ .set_mctrl = stm32_set_mctrl,
+ .get_mctrl = stm32_get_mctrl,
+ .stop_tx = stm32_stop_tx,
+ .start_tx = stm32_start_tx,
+ .throttle = stm32_throttle,
+ .unthrottle = stm32_unthrottle,
+ .stop_rx = stm32_stop_rx,
+ .break_ctl = stm32_break_ctl,
+ .startup = stm32_startup,
+ .shutdown = stm32_shutdown,
+ .set_termios = stm32_set_termios,
+ .pm = stm32_pm,
+ .type = stm32_type,
+ .release_port = stm32_release_port,
+ .request_port = stm32_request_port,
+ .config_port = stm32_config_port,
+ .verify_port = stm32_verify_port,
+};
+
+static int stm32_init_port(struct stm32_port *stm32port,
+ struct platform_device *pdev)
+{
+ struct uart_port *port = &stm32port->port;
+ struct resource *res;
+ int ret;
+
+ port->iotype = UPIO_MEM;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->ops = &stm32_uart_ops;
+ port->dev = &pdev->dev;
+ port->irq = platform_get_irq(pdev, 0);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ port->membase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(port->membase))
+ return PTR_ERR(port->membase);
+ port->mapbase = res->start;
+
+ spin_lock_init(&port->lock);
+
+ stm32port->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(stm32port->clk))
+ return PTR_ERR(stm32port->clk);
+
+ /* Ensure that clk rate is correct by enabling the clk */
+ ret = clk_prepare_enable(stm32port->clk);
+ if (ret)
+ return ret;
+
+ stm32port->port.uartclk = clk_get_rate(stm32port->clk);
+ if (!stm32port->port.uartclk)
+ ret = -EINVAL;
+
+ clk_disable_unprepare(stm32port->clk);
+
+ return ret;
+}
+
+static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int id;
+
+ if (!np)
+ return NULL;
+
+ id = of_alias_get_id(np, "serial");
+ if (id < 0)
+ id = 0;
+
+ if (WARN_ON(id >= STM32_MAX_PORTS))
+ return NULL;
+
+ stm32_ports[id].hw_flow_control = of_property_read_bool(np,
+ "auto-flow-control");
+ stm32_ports[id].port.line = id;
+ return &stm32_ports[id];
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id stm32_match[] = {
+ { .compatible = "st,stm32-usart", },
+ { .compatible = "st,stm32-uart", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, stm32_match);
+#endif
+
+static int stm32_serial_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct stm32_port *stm32port;
+
+ stm32port = stm32_of_get_stm32_port(pdev);
+ if (!stm32port)
+ return -ENODEV;
+
+ ret = stm32_init_port(stm32port, pdev);
+ if (ret)
+ return ret;
+
+ ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, &stm32port->port);
+
+ return 0;
+}
+
+static int stm32_serial_remove(struct platform_device *pdev)
+{
+ struct uart_port *port = platform_get_drvdata(pdev);
+
+ return uart_remove_one_port(&stm32_usart_driver, port);
+}
+
+
+#ifdef CONFIG_SERIAL_STM32_CONSOLE
+static void stm32_console_putchar(struct uart_port *port, int ch)
+{
+ while (!(readl_relaxed(port->membase + USART_SR) & USART_SR_TXE))
+ cpu_relax();
+
+ writel_relaxed(ch, port->membase + USART_DR);
+}
+
+static void stm32_console_write(struct console *co, const char *s, unsigned cnt)
+{
+ struct uart_port *port = &stm32_ports[co->index].port;
+ unsigned long flags;
+ u32 old_cr1, new_cr1;
+ int locked = 1;
+
+ local_irq_save(flags);
+ if (port->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&port->lock);
+ else
+ spin_lock(&port->lock);
+
+ /* Save and disable interrupts */
+ old_cr1 = readl_relaxed(port->membase + USART_CR1);
+ new_cr1 = old_cr1 & ~USART_CR1_IE_MASK;
+ writel_relaxed(new_cr1, port->membase + USART_CR1);
+
+ uart_console_write(port, s, cnt, stm32_console_putchar);
+
+ /* Restore interrupt state */
+ writel_relaxed(old_cr1, port->membase + USART_CR1);
+
+ if (locked)
+ spin_unlock(&port->lock);
+ local_irq_restore(flags);
+}
+
+static int stm32_console_setup(struct console *co, char *options)
+{
+ struct stm32_port *stm32port;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index >= STM32_MAX_PORTS)
+ return -ENODEV;
+
+ stm32port = &stm32_ports[co->index];
+
+ /*
+ * This driver does not support early console initialization
+ * (use ARM early printk support instead), so we only expect
+ * this to be called during the uart port registration when the
+ * driver gets probed and the port should be mapped at that point.
+ */
+ if (stm32port->port.mapbase == 0 || stm32port->port.membase == NULL)
+ return -ENXIO;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(&stm32port->port, co, baud, parity, bits, flow);
+}
+
+static struct console stm32_console = {
+ .name = STM32_SERIAL_NAME,
+ .device = uart_console_device,
+ .write = stm32_console_write,
+ .setup = stm32_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &stm32_usart_driver,
+};
+
+#define STM32_SERIAL_CONSOLE (&stm32_console)
+
+#else
+#define STM32_SERIAL_CONSOLE NULL
+#endif /* CONFIG_SERIAL_STM32_CONSOLE */
+
+static struct uart_driver stm32_usart_driver = {
+ .driver_name = DRIVER_NAME,
+ .dev_name = STM32_SERIAL_NAME,
+ .major = 0,
+ .minor = 0,
+ .nr = STM32_MAX_PORTS,
+ .cons = STM32_SERIAL_CONSOLE,
+};
+
+static struct platform_driver stm32_serial_driver = {
+ .probe = stm32_serial_probe,
+ .remove = stm32_serial_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = of_match_ptr(stm32_match),
+ },
+};
+
+static int __init usart_init(void)
+{
+ static char banner[] __initdata = "STM32 USART driver initialized";
+ int ret;
+
+ pr_info("%s\n", banner);
+
+ ret = uart_register_driver(&stm32_usart_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&stm32_serial_driver);
+ if (ret)
+ uart_unregister_driver(&stm32_usart_driver);
+
+ return ret;
+}
+
+static void __exit usart_exit(void)
+{
+ platform_driver_unregister(&stm32_serial_driver);
+ uart_unregister_driver(&stm32_usart_driver);
+}
+
+module_init(usart_init);
+module_exit(usart_exit);
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_DESCRIPTION("STMicroelectronics STM32 serial port driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index b212281..93ba148 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -258,4 +258,7 @@
/* Cris v10 / v32 SoC */
#define PORT_CRIS 112
+/* STM32 USART */
+#define PORT_STM32 113
+
#endif /* _UAPILINUX_SERIAL_CORE_H */
--
1.9.1
^ permalink raw reply related
* Re: [PATCH v5 17/21] libnvdimm: infrastructure for btt devices
From: Matthew Wilcox @ 2015-06-10 18:46 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Dan Williams, axboe, sfr, rafael, neilb, gregkh, linux-nvdimm,
linux-kernel, linux-acpi, linux-api, akpm, mingo
In-Reply-To: <20150609064200.GE9804@lst.de>
On Tue, Jun 09, 2015 at 08:42:00AM +0200, Christoph Hellwig wrote:
> > The BTT driver is the initial first consumer of this mechanism to allow
> > layering atomic sector update guarantees on top of nd_io capable
> > libnvdimm-block-devices, or their partitions.
>
> As mentioned during the last time of the review the layering here
> is complete broken. If you expose additional capabilities from a block
> device do it at the block device level. That is enhance the rw_page
> callback to allo byte sized access, add a capability flag on the queue,
> etc.
Don't screw up rw_page. The point of rw_page is to read or write a page
cache page. It can sleep, and it indicates success by using the page
flags. Don't try and scqueeze rw_bytes into it. If you want rw_bytes
to be a queue operation, that's one thing, but don't mess with rw_page.
^ permalink raw reply
* Re: [PATCH v5 18/21] nd_btt: atomic sector updates
From: Vishal Verma @ 2015-06-10 18:24 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Dan Williams, axboe, sfr, rafael, neilb, gregkh, linux-nvdimm,
linux-kernel, linux-acpi, linux-api, akpm, mingo
In-Reply-To: <20150610073434.GC3369@lst.de>
On Wed, 2015-06-10 at 09:34 +0200, Christoph Hellwig wrote:
> Hi Vishal,
>
> I'm mostly worried about handling scalability to large CPU counts
> properly. If you think this is the best way to handle it that fine,
> but please document the decisions on the changelog in a similar form
> to what you did below.
Thanks Christoph.
I'll update the changelog for the next version. Scalability and
performance are of course at the top of my head - this implementation is
a first shot at what we think will work best, but if there are
experiments/changes/data that show otherwise, I'll be more than happy to
incorporate those.
-Vishal
^ permalink raw reply
* Re: [PATCH v9 4/5] serial: stm32-usart: Add STM32 USART Driver
From: Greg Kroah-Hartman @ 2015-06-10 17:49 UTC (permalink / raw)
To: Maxime Coquelin
Cc: khilman-DgEjT+Ai2ygdnm+yROfE0A, Arnd Bergmann, Daniel Lezcano,
Daniel Thompson, Kamil Lulko, Uwe Kleine-König,
Andreas Färber, Geert Uytterhoeven, Rob Herring, Pawel Moll,
Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
Thomas Gleixner, Jiri Slaby,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <CALszF6AaS-i2MBF64mJKtY2h5Sb710Z50Mf8wHotUBysukfZbw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Wed, Jun 10, 2015 at 06:18:37PM +0200, Maxime Coquelin wrote:
> 2015-06-10 17:42 GMT+02:00 Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>:
> > On Wed, Jun 10, 2015 at 01:33:22PM +0200, Maxime Coquelin wrote:
> >> 2015-05-31 23:52 GMT+02:00 Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>:
> >> > On Fri, May 22, 2015 at 11:03:35PM +0200, Maxime Coquelin wrote:
> >> >> This drivers adds support to the STM32 USART controller, which is a
> >> >> standard serial driver.
> >> >>
> >> >> Tested-by: Chanwoo Choi <cw00.choi-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> >> >> Reviewed-by: Peter Hurley <peter-WaGBZJeGNqdsbIuE7sb01tBPR1lH4CV8@public.gmane.org>
> >> >> Reviewed-by: Vladimir Zapolskiy <vladimir_zapolskiy-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
> >> >> Reviewed-by: Andy Shevchenko <andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >> >> Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >> >
> >> > Acked-by: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
> >>
> >> Thanks Greg.
> >>
> >> Will you apply it to your tty tree for v4.2? Or it should go in
> >> someone else tree?
> >
> > It's not in my queue, I'm guessing it goes in through some other tree as
> > there are build dependancies here preventing me from taking it.
>
> There should not be any build dependencies.
> I just tested it on my x86 machine with COMPILE_TEST on both v4.1-rc1
> and tty-next branch.
> In both case it compiles without warnings.
Ok, then feel free to resend it as a stand-alone patch please and I will
queue it up.
thanks,
greg k-h
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v4] seccomp: add ptrace options for suspend/resume
From: Andy Lutomirski @ 2015-06-10 17:42 UTC (permalink / raw)
To: Serge Hallyn
Cc: Oleg Nesterov, Tycho Andersen,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux API,
Kees Cook, Will Drewry, Roland McGrath, Pavel Emelyanov
In-Reply-To: <20150610172931.GD4069@ubuntumail>
On Wed, Jun 10, 2015 at 10:29 AM, Serge Hallyn <serge.hallyn-GeWIH/nMZzLQT0dZR+AlfA@public.gmane.org> wrote:
> Quoting Andy Lutomirski (luto-kltTT9wpgjJwATOyAt5JVQ@public.gmane.org):
>> On Wed, Jun 10, 2015 at 9:31 AM, Oleg Nesterov <oleg-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>> > On 06/09, Andy Lutomirski wrote:
>> >>
>> >> On Tue, Jun 9, 2015 at 5:49 PM, Tycho Andersen
>> >> >
>> >> > @@ -556,6 +556,15 @@ static int ptrace_setoptions(struct task_struct *child, unsigned long data)
>> >> > if (data & ~(unsigned long)PTRACE_O_MASK)
>> >> > return -EINVAL;
>> >> >
>> >> > + if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) {
>> >
>> > Well, we should do this if
>> >
>> > (data & O_SUSPEND) && !(flags & O_SUSPEND)
>> >
>> > or at least if
>> >
>> > (data ^ flags) & O_SUSPEND
>> >
>> >
>> >> > + if (!config_enabled(CONFIG_CHECKPOINT_RESTORE) ||
>> >> > + !config_enabled(CONFIG_SECCOMP))
>> >> > + return -EINVAL;
>> >> > +
>> >> > + if (!capable(CAP_SYS_ADMIN))
>> >> > + return -EPERM;
>> >>
>> >> I tend to think that we should also require that current not be using
>> >> seccomp. Otherwise, in principle, there's a seccomp bypass for
>> >> privileged-but-seccomped programs.
>> >
>> > Andy, I simply can't understand why do we need any security check at all.
>> >
>> > OK, yes, in theory we can have a seccomped CAP_SYS_ADMIN process, seccomp
>> > doesn't filter ptrace, you hack that process and force it to attach to
>> > another CAP_SYS_ADMIN/seccomped process, etc, etc... Looks too paranoid
>> > to me.
>>
>> I've sometimes considered having privileged processes I write fork and
>> seccomp their child. Of course, if you're allowing ptrace through
>> your seccomp filter, you open a giant can of worms, but I think we
>> should take the more paranoid approach to start and relax it later as
>
> I really do intend to look at your old proposed tree for improving that...
> have only done a once-over so far, though.
Don't read it yet. It's unnecessarily complicated due to the mess
that is x86's entry code, and I want to clean up the entry code first.
--Andy
^ permalink raw reply
* Re: [PATCH v4] seccomp: add ptrace options for suspend/resume
From: Serge Hallyn @ 2015-06-10 17:29 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Oleg Nesterov, Tycho Andersen,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux API,
Kees Cook, Will Drewry, Roland McGrath, Pavel Emelyanov
In-Reply-To: <CALCETrX_GXgjPRXXT4jMZtjR6vMQrmYbk_OwrAoxaJWFT0+0Fw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Quoting Andy Lutomirski (luto-kltTT9wpgjJwATOyAt5JVQ@public.gmane.org):
> On Wed, Jun 10, 2015 at 9:31 AM, Oleg Nesterov <oleg-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> > On 06/09, Andy Lutomirski wrote:
> >>
> >> On Tue, Jun 9, 2015 at 5:49 PM, Tycho Andersen
> >> >
> >> > @@ -556,6 +556,15 @@ static int ptrace_setoptions(struct task_struct *child, unsigned long data)
> >> > if (data & ~(unsigned long)PTRACE_O_MASK)
> >> > return -EINVAL;
> >> >
> >> > + if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) {
> >
> > Well, we should do this if
> >
> > (data & O_SUSPEND) && !(flags & O_SUSPEND)
> >
> > or at least if
> >
> > (data ^ flags) & O_SUSPEND
> >
> >
> >> > + if (!config_enabled(CONFIG_CHECKPOINT_RESTORE) ||
> >> > + !config_enabled(CONFIG_SECCOMP))
> >> > + return -EINVAL;
> >> > +
> >> > + if (!capable(CAP_SYS_ADMIN))
> >> > + return -EPERM;
> >>
> >> I tend to think that we should also require that current not be using
> >> seccomp. Otherwise, in principle, there's a seccomp bypass for
> >> privileged-but-seccomped programs.
> >
> > Andy, I simply can't understand why do we need any security check at all.
> >
> > OK, yes, in theory we can have a seccomped CAP_SYS_ADMIN process, seccomp
> > doesn't filter ptrace, you hack that process and force it to attach to
> > another CAP_SYS_ADMIN/seccomped process, etc, etc... Looks too paranoid
> > to me.
>
> I've sometimes considered having privileged processes I write fork and
> seccomp their child. Of course, if you're allowing ptrace through
> your seccomp filter, you open a giant can of worms, but I think we
> should take the more paranoid approach to start and relax it later as
I really do intend to look at your old proposed tree for improving that...
have only done a once-over so far, though.
> needed. After all, for the intended use of this patch, stuff will
> break regardless of what we do if the ptracer is itself seccomped.
>
> I could be convinced that if the ptracer is outside seccomp then we
> shouldn't need the CAP_SYS_ADMIN check. That would at least make this
> work in a user namespace.
>
> >> > @@ -590,6 +590,10 @@ void secure_computing_strict(int this_syscall)
> >> > {
> >> > int mode = current->seccomp.mode;
> >> >
> >> > + if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
> >> > + unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
> >> > + return;
> >> > +
> >> > if (mode == 0)
> >> > return;
> >> > else if (mode == SECCOMP_MODE_STRICT)
> >> > @@ -691,6 +695,10 @@ u32 seccomp_phase1(struct seccomp_data *sd)
> >> > int this_syscall = sd ? sd->nr :
> >> > syscall_get_nr(current, task_pt_regs(current));
> >> >
> >> > + if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
> >> > + unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
> >> > + return SECCOMP_PHASE1_OK;
> >> > +
> >>
> >> If it's not hard, it might still be nice to try to fold this into
> >> mode. This code is rather hot. If it would be a mess, then don't
> >> worry about it for now.
> >
> > IMO, this would be a mess ;) At least compared to this simple patch.
> >
> > Suppose we add SECCOMP_MODE_SUSPENDED. Not only this adds the problems
> > with detach if the tracer dies.
> >
> > We need to change copy_seccomp(). And it is not clear what should we
> > do if the child is traced too.
> >
> > We need to change prctl_set_seccomp() paths.
> >
> > And even the "tracee->seccomp.mode = SECCOMP_MODE_SUSPENDED" code needs
> > some locking even if the tracee is stopped, we need to avoid the races
> > with SECCOMP_FILTER_FLAG_TSYNC from other threads.
> >
>
> Agreed. Let's hold off until this becomes a problem (if it ever does).
>
> --Andy
^ permalink raw reply
* Re: [PATCH v4] seccomp: add ptrace options for suspend/resume
From: Andy Lutomirski @ 2015-06-10 17:20 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Tycho Andersen,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux API,
Kees Cook, Will Drewry, Roland McGrath, Pavel Emelyanov,
Serge E. Hallyn
In-Reply-To: <20150610163149.GA5092-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
On Wed, Jun 10, 2015 at 9:31 AM, Oleg Nesterov <oleg-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> On 06/09, Andy Lutomirski wrote:
>>
>> On Tue, Jun 9, 2015 at 5:49 PM, Tycho Andersen
>> >
>> > @@ -556,6 +556,15 @@ static int ptrace_setoptions(struct task_struct *child, unsigned long data)
>> > if (data & ~(unsigned long)PTRACE_O_MASK)
>> > return -EINVAL;
>> >
>> > + if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) {
>
> Well, we should do this if
>
> (data & O_SUSPEND) && !(flags & O_SUSPEND)
>
> or at least if
>
> (data ^ flags) & O_SUSPEND
>
>
>> > + if (!config_enabled(CONFIG_CHECKPOINT_RESTORE) ||
>> > + !config_enabled(CONFIG_SECCOMP))
>> > + return -EINVAL;
>> > +
>> > + if (!capable(CAP_SYS_ADMIN))
>> > + return -EPERM;
>>
>> I tend to think that we should also require that current not be using
>> seccomp. Otherwise, in principle, there's a seccomp bypass for
>> privileged-but-seccomped programs.
>
> Andy, I simply can't understand why do we need any security check at all.
>
> OK, yes, in theory we can have a seccomped CAP_SYS_ADMIN process, seccomp
> doesn't filter ptrace, you hack that process and force it to attach to
> another CAP_SYS_ADMIN/seccomped process, etc, etc... Looks too paranoid
> to me.
I've sometimes considered having privileged processes I write fork and
seccomp their child. Of course, if you're allowing ptrace through
your seccomp filter, you open a giant can of worms, but I think we
should take the more paranoid approach to start and relax it later as
needed. After all, for the intended use of this patch, stuff will
break regardless of what we do if the ptracer is itself seccomped.
I could be convinced that if the ptracer is outside seccomp then we
shouldn't need the CAP_SYS_ADMIN check. That would at least make this
work in a user namespace.
>> > @@ -590,6 +590,10 @@ void secure_computing_strict(int this_syscall)
>> > {
>> > int mode = current->seccomp.mode;
>> >
>> > + if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
>> > + unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
>> > + return;
>> > +
>> > if (mode == 0)
>> > return;
>> > else if (mode == SECCOMP_MODE_STRICT)
>> > @@ -691,6 +695,10 @@ u32 seccomp_phase1(struct seccomp_data *sd)
>> > int this_syscall = sd ? sd->nr :
>> > syscall_get_nr(current, task_pt_regs(current));
>> >
>> > + if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
>> > + unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
>> > + return SECCOMP_PHASE1_OK;
>> > +
>>
>> If it's not hard, it might still be nice to try to fold this into
>> mode. This code is rather hot. If it would be a mess, then don't
>> worry about it for now.
>
> IMO, this would be a mess ;) At least compared to this simple patch.
>
> Suppose we add SECCOMP_MODE_SUSPENDED. Not only this adds the problems
> with detach if the tracer dies.
>
> We need to change copy_seccomp(). And it is not clear what should we
> do if the child is traced too.
>
> We need to change prctl_set_seccomp() paths.
>
> And even the "tracee->seccomp.mode = SECCOMP_MODE_SUSPENDED" code needs
> some locking even if the tracee is stopped, we need to avoid the races
> with SECCOMP_FILTER_FLAG_TSYNC from other threads.
>
Agreed. Let's hold off until this becomes a problem (if it ever does).
--Andy
^ permalink raw reply
* Re: Generic kernel features that need architecture(mips) support
From: Xose Vazquez Perez @ 2015-06-10 16:36 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, Ingo Molnar, linux-arch, linux-api, LKML
In-Reply-To: <20150610145804.GG2753@linux-mips.org>
On 06/10/2015 04:58 PM, Ralf Baechle wrote:
> How are the documentation files in Documentation/features/ maintained?
> They were automatically generated so I wonder if I have to take care
> of anything.
CC: Ingo and related ml.
^ permalink raw reply
* Re: [PATCH v4] seccomp: add ptrace options for suspend/resume
From: Oleg Nesterov @ 2015-06-10 16:31 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Tycho Andersen, linux-kernel@vger.kernel.org, Linux API,
Kees Cook, Will Drewry, Roland McGrath, Pavel Emelyanov,
Serge E. Hallyn
In-Reply-To: <CALCETrVuNzZRAw40reo_2ne9saO5KbbG-omFUQXDo=+XFhpuWA@mail.gmail.com>
On 06/09, Andy Lutomirski wrote:
>
> On Tue, Jun 9, 2015 at 5:49 PM, Tycho Andersen
> >
> > @@ -556,6 +556,15 @@ static int ptrace_setoptions(struct task_struct *child, unsigned long data)
> > if (data & ~(unsigned long)PTRACE_O_MASK)
> > return -EINVAL;
> >
> > + if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) {
Well, we should do this if
(data & O_SUSPEND) && !(flags & O_SUSPEND)
or at least if
(data ^ flags) & O_SUSPEND
> > + if (!config_enabled(CONFIG_CHECKPOINT_RESTORE) ||
> > + !config_enabled(CONFIG_SECCOMP))
> > + return -EINVAL;
> > +
> > + if (!capable(CAP_SYS_ADMIN))
> > + return -EPERM;
>
> I tend to think that we should also require that current not be using
> seccomp. Otherwise, in principle, there's a seccomp bypass for
> privileged-but-seccomped programs.
Andy, I simply can't understand why do we need any security check at all.
OK, yes, in theory we can have a seccomped CAP_SYS_ADMIN process, seccomp
doesn't filter ptrace, you hack that process and force it to attach to
another CAP_SYS_ADMIN/seccomped process, etc, etc... Looks too paranoid
to me.
But damn, I said many times that I won't argue ;)
> > @@ -590,6 +590,10 @@ void secure_computing_strict(int this_syscall)
> > {
> > int mode = current->seccomp.mode;
> >
> > + if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
> > + unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
> > + return;
> > +
> > if (mode == 0)
> > return;
> > else if (mode == SECCOMP_MODE_STRICT)
> > @@ -691,6 +695,10 @@ u32 seccomp_phase1(struct seccomp_data *sd)
> > int this_syscall = sd ? sd->nr :
> > syscall_get_nr(current, task_pt_regs(current));
> >
> > + if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
> > + unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
> > + return SECCOMP_PHASE1_OK;
> > +
>
> If it's not hard, it might still be nice to try to fold this into
> mode. This code is rather hot. If it would be a mess, then don't
> worry about it for now.
IMO, this would be a mess ;) At least compared to this simple patch.
Suppose we add SECCOMP_MODE_SUSPENDED. Not only this adds the problems
with detach if the tracer dies.
We need to change copy_seccomp(). And it is not clear what should we
do if the child is traced too.
We need to change prctl_set_seccomp() paths.
And even the "tracee->seccomp.mode = SECCOMP_MODE_SUSPENDED" code needs
some locking even if the tracee is stopped, we need to avoid the races
with SECCOMP_FILTER_FLAG_TSYNC from other threads.
Oleg.
^ permalink raw reply
* Re: [PATCH v9 4/5] serial: stm32-usart: Add STM32 USART Driver
From: Maxime Coquelin @ 2015-06-10 16:18 UTC (permalink / raw)
To: Greg Kroah-Hartman, khilman-DgEjT+Ai2ygdnm+yROfE0A
Cc: Arnd Bergmann, Daniel Lezcano, Daniel Thompson, Kamil Lulko,
Uwe Kleine-König, Andreas Färber, Geert Uytterhoeven,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Russell King, Thomas Gleixner, Jiri Slaby,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <20150610154240.GC22214-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
2015-06-10 17:42 GMT+02:00 Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>:
> On Wed, Jun 10, 2015 at 01:33:22PM +0200, Maxime Coquelin wrote:
>> 2015-05-31 23:52 GMT+02:00 Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>:
>> > On Fri, May 22, 2015 at 11:03:35PM +0200, Maxime Coquelin wrote:
>> >> This drivers adds support to the STM32 USART controller, which is a
>> >> standard serial driver.
>> >>
>> >> Tested-by: Chanwoo Choi <cw00.choi-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>> >> Reviewed-by: Peter Hurley <peter-WaGBZJeGNqdsbIuE7sb01tBPR1lH4CV8@public.gmane.org>
>> >> Reviewed-by: Vladimir Zapolskiy <vladimir_zapolskiy-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
>> >> Reviewed-by: Andy Shevchenko <andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> >> Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> >
>> > Acked-by: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
>>
>> Thanks Greg.
>>
>> Will you apply it to your tty tree for v4.2? Or it should go in
>> someone else tree?
>
> It's not in my queue, I'm guessing it goes in through some other tree as
> there are build dependancies here preventing me from taking it.
There should not be any build dependencies.
I just tested it on my x86 machine with COMPILE_TEST on both v4.1-rc1
and tty-next branch.
In both case it compiles without warnings.
If you still think it should go through another tree, is arm_soc's
next/drivers a good candidate?
Regards,
Maxime
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v5 12/21] libnvdimm: namespace indices: read and validate
From: Dan Williams @ 2015-06-10 15:54 UTC (permalink / raw)
To: Christoph Hellwig
Cc: linux-nvdimm@lists.01.org, Jens Axboe, Stephen Rothwell,
Rafael J. Wysocki, Neil Brown, Greg KH,
linux-kernel@vger.kernel.org, Ingo Molnar, Linux ACPI, jmoyer,
linux-api, Andrew Morton
In-Reply-To: <20150609063900.GD9804@lst.de>
On Mon, Jun 8, 2015 at 11:39 PM, Christoph Hellwig <hch@lst.de> wrote:
>> +#include <asm-generic/io-64-nonatomic-lo-hi.h>
>> +
>> +#ifndef __io_virt
>> +#define __io_virt(x) ((void __force *) (x))
>> +#endif
>
> NAK. driver code mus never include asm-generic headers directly,
> and __io_virt isn't something that's up to a driver to redefine either.
>
> I think we really need the memremap series in first before trying to
> do the things done in this patch.
I was abusing read[wlq] and write[wlq]. All this patch needs is a
conversion to use __leXXto_cpu and __cpu_to_leXX helpers.
^ permalink raw reply
* Re: [PATCH v9 4/5] serial: stm32-usart: Add STM32 USART Driver
From: Greg Kroah-Hartman @ 2015-06-10 15:42 UTC (permalink / raw)
To: Maxime Coquelin
Cc: Arnd Bergmann, Daniel Lezcano, Daniel Thompson, Kamil Lulko,
Uwe Kleine-König, Andreas Färber, Geert Uytterhoeven,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Russell King, Thomas Gleixner, Jiri Slaby,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <CALszF6B7_xOMvO9pRJJPNeR4JnOgAQAohSARDivzt2d1DQWP_Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Wed, Jun 10, 2015 at 01:33:22PM +0200, Maxime Coquelin wrote:
> 2015-05-31 23:52 GMT+02:00 Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>:
> > On Fri, May 22, 2015 at 11:03:35PM +0200, Maxime Coquelin wrote:
> >> This drivers adds support to the STM32 USART controller, which is a
> >> standard serial driver.
> >>
> >> Tested-by: Chanwoo Choi <cw00.choi-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> >> Reviewed-by: Peter Hurley <peter-WaGBZJeGNqdsbIuE7sb01tBPR1lH4CV8@public.gmane.org>
> >> Reviewed-by: Vladimir Zapolskiy <vladimir_zapolskiy-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
> >> Reviewed-by: Andy Shevchenko <andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >> Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >
> > Acked-by: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
>
> Thanks Greg.
>
> Will you apply it to your tty tree for v4.2? Or it should go in
> someone else tree?
It's not in my queue, I'm guessing it goes in through some other tree as
there are build dependancies here preventing me from taking it.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH v4] seccomp: add ptrace options for suspend/resume
From: Tycho Andersen @ 2015-06-10 15:19 UTC (permalink / raw)
To: Andy Lutomirski
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux API,
Kees Cook, Will Drewry, Roland McGrath, Oleg Nesterov,
Pavel Emelyanov, Serge E. Hallyn
In-Reply-To: <CALCETrVuNzZRAw40reo_2ne9saO5KbbG-omFUQXDo=+XFhpuWA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hi Andy,
On Tue, Jun 09, 2015 at 06:08:42PM -0700, Andy Lutomirski wrote:
>
> > + if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) {
> > + if (!config_enabled(CONFIG_CHECKPOINT_RESTORE) ||
> > + !config_enabled(CONFIG_SECCOMP))
> > + return -EINVAL;
> > +
> > + if (!capable(CAP_SYS_ADMIN))
> > + return -EPERM;
>
> I tend to think that we should also require that current not be using
> seccomp. Otherwise, in principle, there's a seccomp bypass for
> privileged-but-seccomped programs. In any event, CRIU isn't going to
> work well if you run the restorer under seccomp, since it'll start
> nesting in a manner that probably isn't desirable.
Ok, I can resend with that. (sorry Oleg :)
> > + }
> > +
> > /* Avoid intermediate state when all opts are cleared */
> > flags = child->ptrace;
> > flags &= ~(PTRACE_O_MASK << PT_OPT_FLAG_SHIFT);
> > diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> > index 980fd26..645e42d 100644
> > --- a/kernel/seccomp.c
> > +++ b/kernel/seccomp.c
> > @@ -590,6 +590,10 @@ void secure_computing_strict(int this_syscall)
> > {
> > int mode = current->seccomp.mode;
> >
> > + if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
> > + unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
> > + return;
> > +
> > if (mode == 0)
> > return;
> > else if (mode == SECCOMP_MODE_STRICT)
> > @@ -691,6 +695,10 @@ u32 seccomp_phase1(struct seccomp_data *sd)
> > int this_syscall = sd ? sd->nr :
> > syscall_get_nr(current, task_pt_regs(current));
> >
> > + if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
> > + unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
> > + return SECCOMP_PHASE1_OK;
> > +
>
> If it's not hard, it might still be nice to try to fold this into
> mode. This code is rather hot. If it would be a mess, then don't
> worry about it for now.
The part I'm not immediately clear on is what to do when the tracer
dies and the task is running. Oleg pointed out that we can't play with
TIF_SECCOMP (or we could, but restoring it in this case is
complicated), and I'm not sure if playing with ->seccomp.mode has any
similar complications. I /think/ it should be ok to just re-enable it,
but I'm not sure.
I'd like to leave this patch as is (modulo the extra check) for now.
I'm still looking at a way to export mode 2 filters, so there will
hopefully be more patches in this area soon and we can reexamine then.
Thanks for the review.
Tycho
^ permalink raw reply
* Re: [RFC PATCH 09/18] kthread: Make it easier to correctly sleep in iterant kthreads
From: Steven Rostedt @ 2015-06-10 14:07 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Petr Mladek, Andrew Morton, Oleg Nesterov, Tejun Heo, Ingo Molnar,
Richard Weinberger, David Woodhouse, linux-mtd, Trond Myklebust,
Anna Schumaker, linux-nfs, Chris Mason, Paul E. McKenney,
Thomas Gleixner, Linus Torvalds, Jiri Kosina, Borislav Petkov,
Michal Hocko, live-patching, linux-api, linux-kernel
In-Reply-To: <20150610090724.GD3644@twins.programming.kicks-ass.net>
On Wed, 10 Jun 2015 11:07:24 +0200
Peter Zijlstra <peterz@infradead.org> wrote:
> > Not to mention, tasks in TASK_UNINTERRUPTIBLE state for too long will
> > trigger hung task detection.
>
> Right, and I had not considered that, but it turns out the hung_task
> detector checks p->state == TASK_UNINTERRUPTIBLE, so TASK_IDLE is indeed
> safe from that.
Also, I would assume that TASK_IDLE only makes sense for kernel
threads, I wonder if we should add an assertion in schedule that
triggers if a task is scheduling with TASK_IDLE and is not a kernel
thread (has its own mm?)
-- Steve
^ permalink raw reply
* [RESEND PATCH V2 3/3] Add tests for lock on fault
From: Eric B Munson @ 2015-06-10 13:26 UTC (permalink / raw)
To: Andrew Morton
Cc: Eric B Munson, Shuah Khan, Michal Hocko,
linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1433942810-7852-1-git-send-email-emunson-JqFfY2XvxFXQT0dZR+AlfA@public.gmane.org>
Test the mmap() flag, the mlockall() flag, and ensure that mlock limits
are respected. Note that the limit test needs to be run a normal user.
Signed-off-by: Eric B Munson <emunson-JqFfY2XvxFXQT0dZR+AlfA@public.gmane.org>
Cc: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
Cc: Michal Hocko <mhocko-AlSwsSmVLrQ@public.gmane.org>
Cc: linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
tools/testing/selftests/vm/Makefile | 8 +-
tools/testing/selftests/vm/lock-on-fault.c | 145 ++++++++++++++++++++++++++++
tools/testing/selftests/vm/on-fault-limit.c | 47 +++++++++
tools/testing/selftests/vm/run_vmtests | 23 +++++
4 files changed, 222 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/vm/lock-on-fault.c
create mode 100644 tools/testing/selftests/vm/on-fault-limit.c
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index a5ce953..32f3d20 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -1,7 +1,13 @@
# Makefile for vm selftests
CFLAGS = -Wall
-BINARIES = hugepage-mmap hugepage-shm map_hugetlb thuge-gen hugetlbfstest
+BINARIES = hugepage-mmap
+BINARIES += hugepage-shm
+BINARIES += hugetlbfstest
+BINARIES += lock-on-fault
+BINARIES += map_hugetlb
+BINARIES += on-fault-limit
+BINARIES += thuge-gen
BINARIES += transhuge-stress
all: $(BINARIES)
diff --git a/tools/testing/selftests/vm/lock-on-fault.c b/tools/testing/selftests/vm/lock-on-fault.c
new file mode 100644
index 0000000..4659303
--- /dev/null
+++ b/tools/testing/selftests/vm/lock-on-fault.c
@@ -0,0 +1,145 @@
+#include <sys/mman.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#ifndef MCL_ONFAULT
+#define MCL_ONFAULT (MCL_FUTURE << 1)
+#endif
+
+#define PRESENT_BIT 0x8000000000000000
+#define PFN_MASK 0x007FFFFFFFFFFFFF
+#define UNEVICTABLE_BIT (1UL << 18)
+
+static int check_pageflags(void *map)
+{
+ FILE *file;
+ unsigned long pfn1;
+ unsigned long pfn2;
+ unsigned long offset1;
+ unsigned long offset2;
+ int ret = 1;
+
+ file = fopen("/proc/self/pagemap", "r");
+ if (!file) {
+ perror("fopen");
+ return ret;
+ }
+ offset1 = (unsigned long)map / getpagesize() * sizeof(unsigned long);
+ offset2 = ((unsigned long)map + getpagesize()) / getpagesize() * sizeof(unsigned long);
+ if (fseek(file, offset1, SEEK_SET)) {
+ perror("fseek");
+ goto out;
+ }
+
+ if (fread(&pfn1, sizeof(unsigned long), 1, file) != 1) {
+ perror("fread");
+ goto out;
+ }
+
+ if (fseek(file, offset2, SEEK_SET)) {
+ perror("fseek");
+ goto out;
+ }
+
+ if (fread(&pfn2, sizeof(unsigned long), 1, file) != 1) {
+ perror("fread");
+ goto out;
+ }
+
+ /* pfn2 should not be present */
+ if (pfn2 & PRESENT_BIT) {
+ printf("page map says 0x%lx\n", pfn2);
+ printf("present is 0x%lx\n", PRESENT_BIT);
+ goto out;
+ }
+
+ /* pfn1 should be present */
+ if ((pfn1 & PRESENT_BIT) == 0) {
+ printf("page map says 0x%lx\n", pfn1);
+ printf("present is 0x%lx\n", PRESENT_BIT);
+ goto out;
+ }
+
+ pfn1 &= PFN_MASK;
+ fclose(file);
+ file = fopen("/proc/kpageflags", "r");
+ if (!file) {
+ perror("fopen");
+ munmap(map, 2 * getpagesize());
+ return ret;
+ }
+
+ if (fseek(file, pfn1 * sizeof(unsigned long), SEEK_SET)) {
+ perror("fseek");
+ goto out;
+ }
+
+ if (fread(&pfn2, sizeof(unsigned long), 1, file) != 1) {
+ perror("fread");
+ goto out;
+ }
+
+ /* pfn2 now contains the entry from kpageflags for the first page, the
+ * unevictable bit should be set */
+ if ((pfn2 & UNEVICTABLE_BIT) == 0) {
+ printf("kpageflags says 0x%lx\n", pfn2);
+ printf("unevictable is 0x%lx\n", UNEVICTABLE_BIT);
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ fclose(file);
+ return ret;
+}
+
+static int test_mmap(int flags)
+{
+ int ret = 1;
+ void *map;
+
+ map = mmap(NULL, 2 * getpagesize(), PROT_READ | PROT_WRITE, flags, 0, 0);
+ if (map == MAP_FAILED) {
+ perror("mmap()");
+ return ret;
+ }
+
+ /* Write something into the first page to ensure it is present */
+ *(char *)map = 1;
+
+ ret = check_pageflags(map);
+
+ munmap(map, 2 * getpagesize());
+ return ret;
+}
+
+static int test_mlockall(void)
+{
+ int ret = 1;
+
+ if (mlockall(MCL_ONFAULT)) {
+ perror("mlockall");
+ return ret;
+ }
+
+ ret = test_mmap(MAP_PRIVATE | MAP_ANONYMOUS);
+ munlockall();
+ return ret;
+}
+
+#ifndef MAP_LOCKONFAULT
+#define MAP_LOCKONFAULT (MAP_HUGETLB << 1)
+#endif
+
+int main(int argc, char **argv)
+{
+ int ret = 0;
+
+ ret += test_mmap(MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKONFAULT);
+ ret += test_mlockall();
+ return ret;
+}
diff --git a/tools/testing/selftests/vm/on-fault-limit.c b/tools/testing/selftests/vm/on-fault-limit.c
new file mode 100644
index 0000000..ed2a109
--- /dev/null
+++ b/tools/testing/selftests/vm/on-fault-limit.c
@@ -0,0 +1,47 @@
+#include <sys/mman.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#ifndef MCL_ONFAULT
+#define MCL_ONFAULT (MCL_FUTURE << 1)
+#endif
+
+static int test_limit(void)
+{
+ int ret = 1;
+ struct rlimit lims;
+ void *map;
+
+ if (getrlimit(RLIMIT_MEMLOCK, &lims)) {
+ perror("getrlimit");
+ return ret;
+ }
+
+ if (mlockall(MCL_ONFAULT)) {
+ perror("mlockall");
+ return ret;
+ }
+
+ map = mmap(NULL, 2 * lims.rlim_max, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, 0, 0);
+ if (map != MAP_FAILED)
+ printf("mmap should have failed, but didn't\n");
+ else {
+ ret = 0;
+ munmap(map, 2 * lims.rlim_max);
+ }
+
+ munlockall();
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int ret = 0;
+
+ ret += test_limit();
+ return ret;
+}
diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
index c87b681..c1aecce 100755
--- a/tools/testing/selftests/vm/run_vmtests
+++ b/tools/testing/selftests/vm/run_vmtests
@@ -90,4 +90,27 @@ fi
umount $mnt
rm -rf $mnt
echo $nr_hugepgs > /proc/sys/vm/nr_hugepages
+
+echo "--------------------"
+echo "running lock-on-fault"
+echo "--------------------"
+./lock-on-fault
+if [ $? -ne 0 ]; then
+ echo "[FAIL]"
+ exitcode=1
+else
+ echo "[PASS]"
+fi
+
+echo "--------------------"
+echo "running on-fault-limit"
+echo "--------------------"
+sudo -u nobody ./on-fault-limit
+if [ $? -ne 0 ]; then
+ echo "[FAIL]"
+ exitcode=1
+else
+ echo "[PASS]"
+fi
+
exit $exitcode
--
1.9.1
^ permalink raw reply related
* [RESEND PATCH V2 2/3] Add mlockall flag for locking pages on fault
From: Eric B Munson @ 2015-06-10 13:26 UTC (permalink / raw)
To: Andrew Morton
Cc: Eric B Munson, Michal Hocko, linux-alpha, linux-kernel,
linux-mips, linux-parisc, linuxppc-dev, sparclinux, linux-xtensa,
linux-arch, linux-api, linux-mm
In-Reply-To: <1433942810-7852-1-git-send-email-emunson@akamai.com>
Building on the previous patch, extend mlockall() to give a process a
way to specify that pages should be locked when they are faulted in, but
that pre-faulting is not needed.
MCL_ONFAULT is preferrable to MCL_FUTURE for the use cases enumerated
in the previous patch becuase MCL_FUTURE will behave as if each mapping
was made with MAP_LOCKED, causing the entire mapping to be faulted in
when new space is allocated or mapped. MCL_ONFAULT allows the user to
delay the fault in cost of any given page until it is actually needed,
but then guarantees that that page will always be resident.
As with the mmap(MAP_LOCKONFAULT) case, the user is charged for the
mapping against the RLIMIT_MEMLOCK when the address space is allocated,
not when the page is faulted in. This decision was made to keep the
accounting checks out of the page fault path.
Signed-off-by: Eric B Munson <emunson@akamai.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: linux-alpha@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: linux-parisc@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: sparclinux@vger.kernel.org
Cc: linux-xtensa@linux-xtensa.org
Cc: linux-arch@vger.kernel.org
Cc: linux-api@vger.kernel.org
Cc: linux-mm@kvack.org
---
arch/alpha/include/uapi/asm/mman.h | 1 +
arch/mips/include/uapi/asm/mman.h | 1 +
arch/parisc/include/uapi/asm/mman.h | 1 +
arch/powerpc/include/uapi/asm/mman.h | 1 +
arch/sparc/include/uapi/asm/mman.h | 1 +
arch/tile/include/uapi/asm/mman.h | 1 +
arch/xtensa/include/uapi/asm/mman.h | 1 +
include/uapi/asm-generic/mman.h | 1 +
mm/mlock.c | 13 +++++++++----
9 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/arch/alpha/include/uapi/asm/mman.h b/arch/alpha/include/uapi/asm/mman.h
index 15e96e1..dfdaecf 100644
--- a/arch/alpha/include/uapi/asm/mman.h
+++ b/arch/alpha/include/uapi/asm/mman.h
@@ -38,6 +38,7 @@
#define MCL_CURRENT 8192 /* lock all currently mapped pages */
#define MCL_FUTURE 16384 /* lock all additions to address space */
+#define MCL_ONFAULT 32768 /* lock all pages that are faulted in */
#define MADV_NORMAL 0 /* no further special treatment */
#define MADV_RANDOM 1 /* expect random page references */
diff --git a/arch/mips/include/uapi/asm/mman.h b/arch/mips/include/uapi/asm/mman.h
index 47846a5..f0705ff 100644
--- a/arch/mips/include/uapi/asm/mman.h
+++ b/arch/mips/include/uapi/asm/mman.h
@@ -62,6 +62,7 @@
*/
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */
+#define MCL_ONFAULT 4 /* lock all pages that are faulted in */
#define MADV_NORMAL 0 /* no further special treatment */
#define MADV_RANDOM 1 /* expect random page references */
diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h
index 1514cd7..7c2eb85 100644
--- a/arch/parisc/include/uapi/asm/mman.h
+++ b/arch/parisc/include/uapi/asm/mman.h
@@ -32,6 +32,7 @@
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */
+#define MCL_ONFAULT 4 /* lock all pages that are faulted in */
#define MADV_NORMAL 0 /* no further special treatment */
#define MADV_RANDOM 1 /* expect random page references */
diff --git a/arch/powerpc/include/uapi/asm/mman.h b/arch/powerpc/include/uapi/asm/mman.h
index fce74fe..761137a 100644
--- a/arch/powerpc/include/uapi/asm/mman.h
+++ b/arch/powerpc/include/uapi/asm/mman.h
@@ -22,6 +22,7 @@
#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */
#define MCL_FUTURE 0x4000 /* lock all additions to address space */
+#define MCL_ONFAULT 0x8000 /* lock all pages that are faulted in */
#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
#define MAP_NONBLOCK 0x10000 /* do not block on IO */
diff --git a/arch/sparc/include/uapi/asm/mman.h b/arch/sparc/include/uapi/asm/mman.h
index 12425d8..dd027b8 100644
--- a/arch/sparc/include/uapi/asm/mman.h
+++ b/arch/sparc/include/uapi/asm/mman.h
@@ -17,6 +17,7 @@
#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */
#define MCL_FUTURE 0x4000 /* lock all additions to address space */
+#define MCL_ONFAULT 0x8000 /* lock all pages that are faulted in */
#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
#define MAP_NONBLOCK 0x10000 /* do not block on IO */
diff --git a/arch/tile/include/uapi/asm/mman.h b/arch/tile/include/uapi/asm/mman.h
index ec04eaf..0f7ae45 100644
--- a/arch/tile/include/uapi/asm/mman.h
+++ b/arch/tile/include/uapi/asm/mman.h
@@ -37,6 +37,7 @@
*/
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */
+#define MCL_ONFAULT 4 /* lock all pages that are faulted in */
#endif /* _ASM_TILE_MMAN_H */
diff --git a/arch/xtensa/include/uapi/asm/mman.h b/arch/xtensa/include/uapi/asm/mman.h
index 42d43cc..10fbbb7 100644
--- a/arch/xtensa/include/uapi/asm/mman.h
+++ b/arch/xtensa/include/uapi/asm/mman.h
@@ -75,6 +75,7 @@
*/
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */
+#define MCL_ONFAULT 4 /* lock all pages that are faulted in */
#define MADV_NORMAL 0 /* no further special treatment */
#define MADV_RANDOM 1 /* expect random page references */
diff --git a/include/uapi/asm-generic/mman.h b/include/uapi/asm-generic/mman.h
index fc4e586..7fb729b 100644
--- a/include/uapi/asm-generic/mman.h
+++ b/include/uapi/asm-generic/mman.h
@@ -18,5 +18,6 @@
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */
+#define MCL_ONFAULT 4 /* lock all pages that are faulted in */
#endif /* __ASM_GENERIC_MMAN_H */
diff --git a/mm/mlock.c b/mm/mlock.c
index 6fd2cf1..f15547f 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -579,7 +579,7 @@ static int do_mlock(unsigned long start, size_t len, int on)
/* Here we know that vma->vm_start <= nstart < vma->vm_end. */
- newflags = vma->vm_flags & ~VM_LOCKED;
+ newflags = vma->vm_flags & ~(VM_LOCKED | VM_LOCKONFAULT);
if (on)
newflags |= VM_LOCKED;
@@ -662,13 +662,17 @@ static int do_mlockall(int flags)
current->mm->def_flags |= VM_LOCKED;
else
current->mm->def_flags &= ~VM_LOCKED;
- if (flags == MCL_FUTURE)
+ if (flags & MCL_ONFAULT)
+ current->mm->def_flags |= VM_LOCKONFAULT;
+ else
+ current->mm->def_flags &= ~VM_LOCKONFAULT;
+ if (flags == MCL_FUTURE || flags == MCL_ONFAULT)
goto out;
for (vma = current->mm->mmap; vma ; vma = prev->vm_next) {
vm_flags_t newflags;
- newflags = vma->vm_flags & ~VM_LOCKED;
+ newflags = vma->vm_flags & ~(VM_LOCKED | VM_LOCKONFAULT);
if (flags & MCL_CURRENT)
newflags |= VM_LOCKED;
@@ -685,7 +689,8 @@ SYSCALL_DEFINE1(mlockall, int, flags)
unsigned long lock_limit;
int ret = -EINVAL;
- if (!flags || (flags & ~(MCL_CURRENT | MCL_FUTURE)))
+ if (!flags || (flags & ~(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT)) ||
+ ((flags & MCL_FUTURE) && (flags & MCL_ONFAULT)))
goto out;
ret = -EPERM;
--
1.9.1
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [RESEND PATCH V2 1/3] Add mmap flag to request pages are locked after page fault
From: Eric B Munson @ 2015-06-10 13:26 UTC (permalink / raw)
To: Andrew Morton
Cc: Eric B Munson, Michal Hocko, linux-alpha, linux-kernel,
linux-mips, linux-parisc, linuxppc-dev, sparclinux, linux-xtensa,
linux-mm, linux-arch, linux-api
In-Reply-To: <1433942810-7852-1-git-send-email-emunson@akamai.com>
The cost of faulting in all memory to be locked can be very high when
working with large mappings. If only portions of the mapping will be
used this can incur a high penalty for locking.
For the example of a large file, this is the usage pattern for a large
statical language model (probably applies to other statical or graphical
models as well). For the security example, any application transacting
in data that cannot be swapped out (credit card data, medical records,
etc).
This patch introduces the ability to request that pages are not
pre-faulted, but are placed on the unevictable LRU when they are finally
faulted in.
To keep accounting checks out of the page fault path, users are billed
for the entire mapping lock as if MAP_LOCKED was used.
Signed-off-by: Eric B Munson <emunson@akamai.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: linux-alpha@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: linux-parisc@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: sparclinux@vger.kernel.org
Cc: linux-xtensa@linux-xtensa.org
Cc: linux-mm@kvack.org
Cc: linux-arch@vger.kernel.org
Cc: linux-api@vger.kernel.org
---
arch/alpha/include/uapi/asm/mman.h | 1 +
arch/mips/include/uapi/asm/mman.h | 1 +
arch/parisc/include/uapi/asm/mman.h | 1 +
arch/powerpc/include/uapi/asm/mman.h | 1 +
arch/sparc/include/uapi/asm/mman.h | 1 +
arch/tile/include/uapi/asm/mman.h | 1 +
arch/xtensa/include/uapi/asm/mman.h | 1 +
include/linux/mm.h | 1 +
include/linux/mman.h | 3 ++-
include/uapi/asm-generic/mman.h | 1 +
mm/mmap.c | 4 ++--
mm/swap.c | 3 ++-
12 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/arch/alpha/include/uapi/asm/mman.h b/arch/alpha/include/uapi/asm/mman.h
index 0086b47..15e96e1 100644
--- a/arch/alpha/include/uapi/asm/mman.h
+++ b/arch/alpha/include/uapi/asm/mman.h
@@ -30,6 +30,7 @@
#define MAP_NONBLOCK 0x40000 /* do not block on IO */
#define MAP_STACK 0x80000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x100000 /* create a huge page mapping */
+#define MAP_LOCKONFAULT 0x200000 /* Lock pages after they are faulted in, do not prefault */
#define MS_ASYNC 1 /* sync memory asynchronously */
#define MS_SYNC 2 /* synchronous memory sync */
diff --git a/arch/mips/include/uapi/asm/mman.h b/arch/mips/include/uapi/asm/mman.h
index cfcb876..47846a5 100644
--- a/arch/mips/include/uapi/asm/mman.h
+++ b/arch/mips/include/uapi/asm/mman.h
@@ -48,6 +48,7 @@
#define MAP_NONBLOCK 0x20000 /* do not block on IO */
#define MAP_STACK 0x40000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
+#define MAP_LOCKONFAULT 0x100000 /* Lock pages after they are faulted in, do not prefault */
/*
* Flags for msync
diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h
index 294d251..1514cd7 100644
--- a/arch/parisc/include/uapi/asm/mman.h
+++ b/arch/parisc/include/uapi/asm/mman.h
@@ -24,6 +24,7 @@
#define MAP_NONBLOCK 0x20000 /* do not block on IO */
#define MAP_STACK 0x40000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
+#define MAP_LOCKONFAULT 0x100000 /* Lock pages after they are faulted in, do not prefault */
#define MS_SYNC 1 /* synchronous memory sync */
#define MS_ASYNC 2 /* sync memory asynchronously */
diff --git a/arch/powerpc/include/uapi/asm/mman.h b/arch/powerpc/include/uapi/asm/mman.h
index 6ea26df..fce74fe 100644
--- a/arch/powerpc/include/uapi/asm/mman.h
+++ b/arch/powerpc/include/uapi/asm/mman.h
@@ -27,5 +27,6 @@
#define MAP_NONBLOCK 0x10000 /* do not block on IO */
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
+#define MAP_LOCKONFAULT 0x80000 /* Lock pages after they are faulted in, do not prefault */
#endif /* _UAPI_ASM_POWERPC_MMAN_H */
diff --git a/arch/sparc/include/uapi/asm/mman.h b/arch/sparc/include/uapi/asm/mman.h
index 0b14df3..12425d8 100644
--- a/arch/sparc/include/uapi/asm/mman.h
+++ b/arch/sparc/include/uapi/asm/mman.h
@@ -22,6 +22,7 @@
#define MAP_NONBLOCK 0x10000 /* do not block on IO */
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
+#define MAP_LOCKONFAULT 0x80000 /* Lock pages after they are faulted in, do not prefault */
#endif /* _UAPI__SPARC_MMAN_H__ */
diff --git a/arch/tile/include/uapi/asm/mman.h b/arch/tile/include/uapi/asm/mman.h
index 81b8fc3..ec04eaf 100644
--- a/arch/tile/include/uapi/asm/mman.h
+++ b/arch/tile/include/uapi/asm/mman.h
@@ -29,6 +29,7 @@
#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
#define MAP_HUGETLB 0x4000 /* create a huge page mapping */
+#define MAP_LOCKONFAULT 0x8000 /* Lock pages after they are faulted in, do not prefault */
/*
diff --git a/arch/xtensa/include/uapi/asm/mman.h b/arch/xtensa/include/uapi/asm/mman.h
index 201aec0..42d43cc 100644
--- a/arch/xtensa/include/uapi/asm/mman.h
+++ b/arch/xtensa/include/uapi/asm/mman.h
@@ -55,6 +55,7 @@
#define MAP_NONBLOCK 0x20000 /* do not block on IO */
#define MAP_STACK 0x40000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
+#define MAP_LOCKONFAULT 0x100000 /* Lock pages after they are faulted in, do not prefault */
#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
# define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be
* uninitialized */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0755b9f..3e31457 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -126,6 +126,7 @@ extern unsigned int kobjsize(const void *objp);
#define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */
#define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */
+#define VM_LOCKONFAULT 0x00001000 /* Lock the pages covered when they are faulted in */
#define VM_LOCKED 0x00002000
#define VM_IO 0x00004000 /* Memory mapped I/O or similar */
diff --git a/include/linux/mman.h b/include/linux/mman.h
index 16373c8..437264b 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -86,7 +86,8 @@ calc_vm_flag_bits(unsigned long flags)
{
return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) |
_calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) |
- _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED );
+ _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ) |
+ _calc_vm_trans(flags, MAP_LOCKONFAULT,VM_LOCKONFAULT);
}
unsigned long vm_commit_limit(void);
diff --git a/include/uapi/asm-generic/mman.h b/include/uapi/asm-generic/mman.h
index e9fe6fd..fc4e586 100644
--- a/include/uapi/asm-generic/mman.h
+++ b/include/uapi/asm-generic/mman.h
@@ -12,6 +12,7 @@
#define MAP_NONBLOCK 0x10000 /* do not block on IO */
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
+#define MAP_LOCKONFAULT 0x80000 /* Lock pages after they are faulted in, do not prefault */
/* Bits [26:31] are reserved, see mman-common.h for MAP_HUGETLB usage */
diff --git a/mm/mmap.c b/mm/mmap.c
index bb50cac..ba1a6bf 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1233,7 +1233,7 @@ static inline int mlock_future_check(struct mm_struct *mm,
unsigned long locked, lock_limit;
/* mlock MCL_FUTURE? */
- if (flags & VM_LOCKED) {
+ if (flags & (VM_LOCKED | VM_LOCKONFAULT)) {
locked = len >> PAGE_SHIFT;
locked += mm->locked_vm;
lock_limit = rlimit(RLIMIT_MEMLOCK);
@@ -1301,7 +1301,7 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) |
mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
- if (flags & MAP_LOCKED)
+ if (flags & (MAP_LOCKED | MAP_LOCKONFAULT))
if (!can_do_mlock())
return -EPERM;
diff --git a/mm/swap.c b/mm/swap.c
index a7251a8..07c905e 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -711,7 +711,8 @@ void lru_cache_add_active_or_unevictable(struct page *page,
{
VM_BUG_ON_PAGE(PageLRU(page), page);
- if (likely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED)) {
+ if (likely((vma->vm_flags & (VM_LOCKED | VM_LOCKONFAULT)) == 0) ||
+ (vma->vm_flags & VM_SPECIAL)) {
SetPageActive(page);
lru_cache_add(page);
return;
--
1.9.1
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [RESEND PATCH V2 0/3] Allow user to request memory to be locked on page fault
From: Eric B Munson @ 2015-06-10 13:26 UTC (permalink / raw)
To: Andrew Morton
Cc: Eric B Munson, Shuah Khan, Michal Hocko, Michael Kerrisk,
linux-alpha, linux-kernel, linux-mips, linux-parisc, linuxppc-dev,
sparclinux, linux-xtensa, linux-mm, linux-arch, linux-api
mlock() allows a user to control page out of program memory, but this
comes at the cost of faulting in the entire mapping when it is
allocated. For large mappings where the entire area is not necessary
this is not ideal.
This series introduces new flags for mmap() and mlockall() that allow a
user to specify that the covered are should not be paged out, but only
after the memory has been used the first time.
There are two main use cases that this set covers. The first is the
security focussed mlock case. A buffer is needed that cannot be written
to swap. The maximum size is known, but on average the memory used is
significantly less than this maximum. With lock on fault, the buffer
is guaranteed to never be paged out without consuming the maximum size
every time such a buffer is created.
The second use case is focussed on performance. Portions of a large
file are needed and we want to keep the used portions in memory once
accessed. This is the case for large graphical models where the path
through the graph is not known until run time. The entire graph is
unlikely to be used in a given invocation, but once a node has been
used it needs to stay resident for further processing. Given these
constraints we have a number of options. We can potentially waste a
large amount of memory by mlocking the entire region (this can also
cause a significant stall at startup as the entire file is read in).
We can mlock every page as we access them without tracking if the page
is already resident but this introduces large overhead for each access.
The third option is mapping the entire region with PROT_NONE and using
a signal handler for SIGSEGV to mprotect(PROT_READ) and mlock() the
needed page. Doing this page at a time adds a significant performance
penalty. Batching can be used to mitigate this overhead, but in order
to safely avoid trying to mprotect pages outside of the mapping, the
boundaries of each mapping to be used in this way must be tracked and
available to the signal handler. This is precisely what the mm system
in the kernel should already be doing.
For mmap(MAP_LOCKONFAULT) the user is charged against RLIMIT_MEMLOCK
as if MAP_LOCKED was used, so when the VMA is created not when the pages
are faulted in. For mlockall(MCL_ON_FAULT) the user is charged as if
MCL_FUTURE was used. This decision was made to keep the accounting
checks out of the page fault path.
To illustrate the benefit of this patch I wrote a test program that
mmaps a 5 GB file filled with random data and then makes 15,000,000
accesses to random addresses in that mapping. The test program was run
20 times for each setup. Results are reported for two program portions,
setup and execution. The setup phase is calling mmap and optionally
mlock on the entire region. For most experiments this is trivial, but
it highlights the cost of faulting in the entire region. Results are
averages across the 20 runs in milliseconds.
mmap with MAP_LOCKED:
Setup avg: 11821.193
Processing avg: 3404.286
mmap with mlock() before each access:
Setup avg: 0.054
Processing avg: 34263.201
mmap with PROT_NONE and signal handler and batch size of 1 page:
With the default value in max_map_count, this gets ENOMEM as I attempt
to change the permissions, after upping the sysctl significantly I get:
Setup avg: 0.050
Processing avg: 67690.625
mmap with PROT_NONE and signal handler and batch size of 8 pages:
Setup avg: 0.098
Processing avg: 37344.197
mmap with PROT_NONE and signal handler and batch size of 16 pages:
Setup avg: 0.0548
Processing avg: 29295.669
mmap with MAP_LOCKONFAULT:
Setup avg: 0.073
Processing avg: 18392.136
The signal handler in the batch cases faulted in memory in two steps to
avoid having to know the start and end of the faulting mapping. The
first step covers the page that caused the fault as we know that it will
be possible to lock. The second step speculatively tries to mlock and
mprotect the batch size - 1 pages that follow. There may be a clever
way to avoid this without having the program track each mapping to be
covered by this handeler in a globally accessible structure, but I could
not find it. It should be noted that with a large enough batch size
this two step fault handler can still cause the program to crash if it
reaches far beyond the end of the mapping.
These results show that if the developer knows that a majority of the
mapping will be used, it is better to try and fault it in at once,
otherwise MAP_LOCKONFAULT is significantly faster.
The performance cost of these patches are minimal on the two benchmarks
I have tested (stream and kernbench). The following are the average
values across 20 runs of each benchmark after a warmup run whose
results were discarded.
Avg throughput in MB/s from stream using 1000000 element arrays
Test 4.1-rc2 4.1-rc2+lock-on-fault
Copy: 10,979.08 10,917.34
Scale: 11,094.45 11,023.01
Add: 12,487.29 12,388.65
Triad: 12,505.77 12,418.78
Kernbench optimal load
4.1-rc2 4.1-rc2+lock-on-fault
Elapsed Time 71.046 71.324
User Time 62.117 62.352
System Time 8.926 8.969
Context Switches 14531.9 14542.5
Sleeps 14935.9 14939
Eric B Munson (3):
Add mmap flag to request pages are locked after page fault
Add mlockall flag for locking pages on fault
Add tests for lock on fault
arch/alpha/include/uapi/asm/mman.h | 2 +
arch/mips/include/uapi/asm/mman.h | 2 +
arch/parisc/include/uapi/asm/mman.h | 2 +
arch/powerpc/include/uapi/asm/mman.h | 2 +
arch/sparc/include/uapi/asm/mman.h | 2 +
arch/tile/include/uapi/asm/mman.h | 2 +
arch/xtensa/include/uapi/asm/mman.h | 2 +
include/linux/mm.h | 1 +
include/linux/mman.h | 3 +-
include/uapi/asm-generic/mman.h | 2 +
mm/mlock.c | 13 ++-
mm/mmap.c | 4 +-
mm/swap.c | 3 +-
tools/testing/selftests/vm/Makefile | 8 +-
tools/testing/selftests/vm/lock-on-fault.c | 145 ++++++++++++++++++++++++++++
tools/testing/selftests/vm/on-fault-limit.c | 47 +++++++++
tools/testing/selftests/vm/run_vmtests | 23 +++++
17 files changed, 254 insertions(+), 9 deletions(-)
create mode 100644 tools/testing/selftests/vm/lock-on-fault.c
create mode 100644 tools/testing/selftests/vm/on-fault-limit.c
Cc: Shuah Khan <shuahkh@osg.samsung.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: linux-alpha@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: linux-parisc@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: sparclinux@vger.kernel.org
Cc: linux-xtensa@linux-xtensa.org
Cc: linux-mm@kvack.org
Cc: linux-arch@vger.kernel.org
Cc: linux-api@vger.kernel.org
--
1.9.1
^ permalink raw reply
* Re: [PATCH v9 4/5] serial: stm32-usart: Add STM32 USART Driver
From: Maxime Coquelin @ 2015-06-10 11:33 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Arnd Bergmann, Daniel Lezcano, Daniel Thompson, Kamil Lulko,
Uwe Kleine-König, Andreas Färber, Geert Uytterhoeven,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Russell King, Thomas Gleixner, Jiri Slaby,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <20150531215246.GA24174-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
2015-05-31 23:52 GMT+02:00 Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>:
> On Fri, May 22, 2015 at 11:03:35PM +0200, Maxime Coquelin wrote:
>> This drivers adds support to the STM32 USART controller, which is a
>> standard serial driver.
>>
>> Tested-by: Chanwoo Choi <cw00.choi-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>> Reviewed-by: Peter Hurley <peter-WaGBZJeGNqdsbIuE7sb01tBPR1lH4CV8@public.gmane.org>
>> Reviewed-by: Vladimir Zapolskiy <vladimir_zapolskiy-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
>> Reviewed-by: Andy Shevchenko <andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>
> Acked-by: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
Thanks Greg.
Will you apply it to your tty tree for v4.2? Or it should go in
someone else tree?
Regards,
Maxime
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH 00/18] kthreads/signal: Safer kthread API and signal handling
From: Peter Zijlstra @ 2015-06-10 10:40 UTC (permalink / raw)
To: Tejun Heo
Cc: Petr Mladek, Andrew Morton, Oleg Nesterov, Ingo Molnar,
Richard Weinberger, Steven Rostedt, David Woodhouse,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Trond Myklebust,
Anna Schumaker, linux-nfs-u79uwXL29TY76Z2rM5mHXA, Chris Mason,
Paul E. McKenney, Thomas Gleixner, Linus Torvalds, Jiri Kosina,
Borislav Petkov, Michal Hocko,
live-patching-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150609061446.GV21465-qYNAdHglDFBN0TnZuCh8vA@public.gmane.org>
On Tue, Jun 09, 2015 at 03:14:46PM +0900, Tejun Heo wrote:
> Hey, Peter.
>
> On Fri, Jun 05, 2015 at 06:22:16PM +0200, Peter Zijlstra wrote:
> > There's a lot more problems with workqueues:
> >
> > - they're not regular tasks and all the task controls don't work on
> > them. This means all things scheduler, like cpu-affinity, nice, and
> > RT/deadline scheduling policies. Instead there is some half baked
> > secondary interface for some of these.
>
> Because there's a pool of them and the workers come and go
> dynamically. There's no way around it. The attributes just have to
> be per-pool.
Sure, but there's a few possible ways to still make that work with the
regular syscall interfaces.
1) propagate the change to any one worker to all workers of the same
pool
2) have a common ancestor task for each pool, and allow changing that.
You can combine that with either the propagation like above, or a
rule that workers kill themselves if they observe their parent
changed (eg. check a attribute sequence count after each work).
> > But this also very much includes things like cgroups, which brings me
> > to the second point.
> >
> > - its oblivious to cgroups (as it is to RT priority for example) both
> > leading to priority inversion. A work enqueued from a deep/limited
> > cgroup does not inherit the task's cgroup. Instead this work is ran
> > from the root cgroup.
> >
> > This breaks cgroup isolation, more significantly so when a large part
> > of the actual work is done from workqueues (as some workloads end up
> > being). Instead of being able to control the work, it all ends up in
> > the root cgroup outside of control.
>
> cgroup support will surely be added but I'm not sure we can or should
> do inheritance automatically.
I think its a good default to inherit stuff from the task that queued
it.
> Using a different API doesn't solve the
> problem automatically either. A lot of kthreads are shared
> system-wide after all. We'll need an abstraction layer to deal with
> that no matter where we do it.
Yes, hardware threads are global, but so is the hardware. Those are not
a problem provided the thread map 1:1 with the actual devices and do not
service multiple devices from a single thread.
Once you start combining things you start to get all the above problems
all over again.
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH 09/18] kthread: Make it easier to correctly sleep in iterant kthreads
From: Peter Zijlstra @ 2015-06-10 9:07 UTC (permalink / raw)
To: Steven Rostedt
Cc: Petr Mladek, Andrew Morton, Oleg Nesterov, Tejun Heo, Ingo Molnar,
Richard Weinberger, David Woodhouse,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Trond Myklebust,
Anna Schumaker, linux-nfs-u79uwXL29TY76Z2rM5mHXA, Chris Mason,
Paul E. McKenney, Thomas Gleixner, Linus Torvalds, Jiri Kosina,
Borislav Petkov, Michal Hocko,
live-patching-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150608134810.3abd862b-f9ZlEuEWxVcJvu8Pb33WZ0EMvNT87kid@public.gmane.org>
On Mon, Jun 08, 2015 at 01:48:10PM -0400, Steven Rostedt wrote:
> > commit 80ed87c8a9ca0cad7ca66cf3bbdfb17559a66dcf
> > Author: Peter Zijlstra <peterz-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>
> > Date: Fri May 8 14:23:45 2015 +0200
> >
> > sched/wait: Introduce TASK_NOLOAD and TASK_IDLE
> >
> > Currently people use TASK_INTERRUPTIBLE to idle kthreads and wait for
> > 'work' because TASK_UNINTERRUPTIBLE contributes to the loadavg. Having
> > all idle kthreads contribute to the loadavg is somewhat silly.
>
> Not to mention, tasks in TASK_UNINTERRUPTIBLE state for too long will
> trigger hung task detection.
Right, and I had not considered that, but it turns out the hung_task
detector checks p->state == TASK_UNINTERRUPTIBLE, so TASK_IDLE is indeed
safe from that.
^ permalink raw reply
* Re: [RFC PATCH 09/18] kthread: Make it easier to correctly sleep in iterant kthreads
From: Peter Zijlstra @ 2015-06-10 9:05 UTC (permalink / raw)
To: Petr Mladek
Cc: Andrew Morton, Oleg Nesterov, Tejun Heo, Ingo Molnar,
Richard Weinberger, Steven Rostedt, David Woodhouse,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Trond Myklebust,
Anna Schumaker, linux-nfs-u79uwXL29TY76Z2rM5mHXA, Chris Mason,
Paul E. McKenney, Thomas Gleixner, Linus Torvalds, Jiri Kosina,
Borislav Petkov, Michal Hocko,
live-patching-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150609152526.GB9409-KsEp0d+Q8qECVLCxKZUutA@public.gmane.org>
On Tue, Jun 09, 2015 at 05:25:26PM +0200, Petr Mladek wrote:
> On Mon 2015-06-08 13:39:55, Peter Zijlstra wrote:
> > On Mon, 2015-06-08 at 12:01 +0200, Petr Mladek wrote:
> >
> > > Just to be sure. Do you suggest to use TASK_IDLE everywhere in
> > > kthreads or only when the uninterruptible sleep is really needed?
> >
> > Always, only use INTERRUPTIBLE when you're actually interruptible, that
> > is you want signals or such muck to terminate your wait.
>
> I like that TASK_IDLE clearly describes that the state of the task.
> I am just curious. Is there any particular advantage of using
> uninterruptible sleep over the interruptible one, please?
I think, given how all schedule() calls should be inside a loop testing
their sleep condition, and one has to assume spurious wakeups anyhow,
one can make an argument for removing the distinction.
That said, typically INTERRUPTIBLE means 'capable of handling signals
while waiting for $foo', and as said elsewhere in this thread, kthreads
should not really be having signals.
In that spirit, I think UNINTERRUPTIBLE is the right sleep.
> I ask because making freezable kthreads is quite tricky. You need to
> call try_to_freeze() after each schedule or call freezable_* variants
> of schedule(). I think that it is easy to make a mistake. I wonder if
> it might be more elegant to use interruptible sleep whenever possible,
> send the fake signal also to kthreads and force them moving into some
> location where the freeze is safe and handled.
I don't think that's really a concern here, you have an absolutely
perfect freeze point and freezable_schedule() is fine.
>
> > > IMHO, we should not use TASK_IDLE in freezable kthreads because
> > > it would break freezing.
> >
> > How so? The task is IDLE, its not doing anything.
>
> Well, it might cause the freeze. I have just double checked this
> with ubi_thread(). It calls set_freezable().
> I did the following change:
>
> diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
> index 16214d3d57a4..d528fa5e93ba 100644
> --- a/drivers/mtd/ubi/wl.c
> +++ b/drivers/mtd/ubi/wl.c
> @@ -1428,7 +1428,7 @@ int ubi_thread(void *u)
> spin_lock(&ubi->wl_lock);
> if (list_empty(&ubi->works) || ubi->ro_mode ||
> !ubi->thread_enabled || ubi_dbg_is_bgt_disabled(ubi)) {
> - set_current_state(TASK_INTERRUPTIBLE);
> + set_current_state(TASK_IDLE);
> spin_unlock(&ubi->wl_lock);
> schedule();
> continue;
> or use in ubi_thread()
>
> freezable_schedule()
This
> or always ignore freezing when the task sets TASK_IDLE.
Can't, because they might get woken up, in which case they need to end
up in the fridge.
> > And this is the arch typical freeze point if ever there was one, you're
> > checking kthread_stop, if we can terminate the kthread, we can certainly
> > get frozen.
>
> It makes sense. The tasks should be in some sane state when it goes
> into the idle state. I hope that people will not misuse it too much.
Do your utmost bestest to put in as many assertions as you can to avoid
abuse.
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v5 18/21] nd_btt: atomic sector updates
From: Christoph Hellwig @ 2015-06-10 7:34 UTC (permalink / raw)
To: Vishal Verma
Cc: Dan Williams, axboe-tSWWG44O7X1aa/9Udqfwiw,
sfr-3FnU+UHB4dNDw9hX6IcOSA, rafael-DgEjT+Ai2ygdnm+yROfE0A,
neilb-l3A5Bk7waGM, gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-acpi-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
mingo-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <1433874431.32607.37.camel-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Hi Vishal,
I'm mostly worried about handling scalability to large CPU counts
properly. If you think this is the best way to handle it that fine,
but please document the decisions on the changelog in a similar form
to what you did below.
^ permalink raw reply
* Re: [PATCH v5 05/21] libnvdimm: control (ioctl) messages for libnvdimm bus and dimm devices
From: Christoph Hellwig @ 2015-06-10 7:33 UTC (permalink / raw)
To: Dan Williams
Cc: Christoph Hellwig,
linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org, Jens Axboe,
Stephen Rothwell, Rafael J. Wysocki, Neil Brown, Greg KH,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Ingo Molnar,
Linux ACPI, jmoyer, linux-api-u79uwXL29TY76Z2rM5mHXA,
Andrew Morton
In-Reply-To: <CAPcyv4jmHpg4YrseBWH-k=achv4N-V8n2X0CkFw+-AFsiRuH8A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Mon, Jun 08, 2015 at 11:57:42PM -0700, Dan Williams wrote:
> Data payload size for one, these commands transfer more than a page
> worth of data at a time.
>
> Even if we killed the ioctl interface to userspace we still need all
> the ugly data marshaling code in the kernel to craft properly
> formatted ACPI _DSM messages. I try to share as much common
> infrastructure from the ACPI _DSM implementation to the ioctl
> interface (nd_cmd_dimm_desc() + nd_cmd_bus_desc()).
Ok. Not a fan of these dual interfaces but in this case they might be
justified.
^ permalink raw reply
* Re: [RFC PATCH 07/18] kthread: Make iterant kthreads freezable by default
From: Tejun Heo @ 2015-06-10 4:31 UTC (permalink / raw)
To: Petr Mladek
Cc: Andrew Morton, Oleg Nesterov, Ingo Molnar, Peter Zijlstra,
Richard Weinberger, Steven Rostedt, David Woodhouse,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Trond Myklebust,
Anna Schumaker, linux-nfs-u79uwXL29TY76Z2rM5mHXA, Chris Mason,
Paul E. McKenney, Thomas Gleixner, Linus Torvalds, Jiri Kosina,
Borislav Petkov, Michal Hocko,
live-patching-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150609155313.GC9409-KsEp0d+Q8qECVLCxKZUutA@public.gmane.org>
Hello, Petr.
On Tue, Jun 09, 2015 at 05:53:13PM +0200, Petr Mladek wrote:
> I think that the interaction with the hardware should be the reason to
> make them properly freezable. In the current state they are stopped at
> some random place, they might either miss some event from the hardware
> or the hardware might get resumed into another state and the kthread
> might wait forever.
Yes, IIUC, there are two classes of use cases where freezing kthreads
makes sense.
* While hibernating, freezing writeback workers and whoever else which
might issue IOs. This is because we have to thaw devices to issue
IOs to write out the prepared hibernation image. If new IOs are
issued from page cache or whereever when the devices are thawed for
writing out the hibernation image, the hibernation image and the
data on the disk deviate.
Note that this only works because currently none of the block
drivers which may be used to write out hibernation images depend on
freezable kthreads and hopefully nobody issues IOs from unfreezable
kthreads or bh or softirq, which, I think, can happen with
preallocated requests or bio based devices.
This is a very brittle approach. Instead of controlling things
where it actually can be controlled - the IO ingress point - we're
trying to control all its users with a pretty blunt tool while at
the same time depending on the fact that some of the low level
subsystems don't happen to make use of the said blunt tool.
I think what we should do is simply blocking all non-image IOs from
the block layer while writing out hibernation image. It'd be
simpler and a lot more reliable.
* Device drivers which interact with their devices in a fully
synchronous manner so that blocking the kthread always reliably
quiesces the device. For this to be true, the device shouldn't
carry over any state across the freezing points. There are drivers
which are actually like this and it works for them.
However, my impression is that people don't really scrutinize why
freezer works for a specific case and tend to spray them all over
and develop a fuzzy sense that freezing will somehow magically make
the driver ready for PM operatoins. It doesn't help that freezer is
such a blunt tool and our historical usage has always been fuzzy -
in the earlier days, we depended on freezer even when we knew it
wasn't sufficient probably because updating all subsystems and
drivers were such a huge undertaking and freezer kinda sorta works
in many cases.
IMHO we'd be a lot better served by blocking the kthread from PM
callbacks explicitly for these drivers to unify control points for
PM operations and make what's going on a lot more explicit. This
will surely involve a bit more boilerplate code but with the right
helpers it should be mostly trivial and I believe that it's likely
to encourage higher quality PM operations why getting rid of this
fuzzy feeling around the freezer.
For both cases, I don't really think kthread freezer is a good
solution. This is a blunt enough tool to hide problems in most but
not all cases while unnecessarily obscuring what's going on from
developers. I personally strongly think that we eventually need to
get rid of the kernel part of freezer.
> Also I think that freezing kthreads on some well defined location
> should help with reproducing and fixing problems.
>
> Note that _only_ kthreads using the _new API_ should be freezable by
> default. The move need to be done carefully. It is chance to review
> and clean up the freezer stuff.
>
> Of course, I might be too optimistic here.
I'm strongly against this. We really don't want to make it even
fuzzier. There are finite things which need to be controlled for PM
operations and I believe what we need to do is identifying them and
implementing explicit and clear control mechanisms for them, not
spreading this feel-good mechanism even more, further obscuring where
those points are.
This becomes the game of "is it frozen ENOUGH yet?" and that "enough"
is extremely difficult to determine as we're not looking at the choke
spots at all and freezable kthreads only cover part of kernel
activity. The fuzzy enoughness also actually inhibits development of
proper mechanisms - "I believe this is frozen ENOUGH at this point so
it is probably safe to assume that X, Y and Z aren't happening
anymore" and it usually is except when it's not.
Let's please not spread this even more.
> > In most cases, we want to implement proper power management callbacks
> > which plug new issuance of whatever work-unit the code is dealing with
> > and drain in-flight ones. Whether the worker threads are frozen or
> > not doesn't matter once that's implemented.
>
> I see. The power management is important here.
That's the only reason we have freezer at all.
> > It seems that people have been marking kthreads freezable w/o really
> > thinking about it - some of them are subtly broken due to missing
> > drainage of in-flight things while others simply don't need freezing
> > for correctness.
>
> I have similar feeling.
>
> > We do want to clean up freezer usage in the kernel but definitely do
> > not want to make kthreads freezable by default especially given that
> > the freezer essentially is one giant lockdep-less system-wide lock.
>
> I think that we both want to clean up freezing. I would like to make
> it more deterministic and you suggest to make it more relaxed.
> Do I understand it correctly?
I'm not sure I'm trying to make it more relaxed. I just don't want it
to spread uncontrolled.
Thanks a lot.
--
tejun
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ 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