* Re: [PATCH] powerpc: Remove inaccessible CMDLINE default
From: Christophe Leroy @ 2019-08-02 5:18 UTC (permalink / raw)
To: Chris Packham, benh, paulus, mpe; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20190802050232.22978-1-chris.packham@alliedtelesis.co.nz>
Le 02/08/2019 à 07:02, Chris Packham a écrit :
> Since commit cbe46bd4f510 ("powerpc: remove CONFIG_CMDLINE #ifdef mess")
> CONFIG_CMDLINE has always had a value regardless of CONNIG_CMDLINE_BOOL.
s/CONNIG/CONFIG/
>
> For example:
>
> $ make ARCH=powerpc defconfig
> $ cat .config
> # CONFIG_CMDLINE_BOOL is not set
> CONFIG_CMDLINE=""
>
> When enabling CONNIG_CMDLINE_BOOL this value is kept making the 'default
> "..." if CONNIG_CMDLINE_BOOL' ineffective.
s/CONNIG/CONFIG/
>
> $ ./scripts/config --enable CONFIG_CMDLINE_BOOL
> $ cat .config
> CONFIG_CMDLINE_BOOL=y
> CONFIG_CMDLINE=""
>
> Additionally all the in-tree powerpc defconfigs that set
> CONFIG_CMDLINE_BOOL=y also set CONFIG_CMDLINE to something else. For
> these reasons remove the inaccessible default.
>
> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
Reviewed-by: Christophe Leroy <christophe.leroy@c-s.fr>
> ---
> This should be independent of http://patchwork.ozlabs.org/patch/1140811/ but
> I've generated this patch on a stream that has it applied locally.
>
> arch/powerpc/Kconfig | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index d413fe1b4058..6fca6eba6aee 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -844,7 +844,6 @@ config CMDLINE_BOOL
>
> config CMDLINE
> string "Initial kernel command string" if CMDLINE_BOOL
> - default "console=ttyS0,9600 console=tty0 root=/dev/sda2" if CMDLINE_BOOL
> default ""
> help
> On some platforms, there is currently no way for the boot loader to
>
I think we could also get rid of CMDLINE_BOOL totally and use CMDLINE !=
"" instead.
Christophe
^ permalink raw reply
* [PATCH 3/3] powerpc/eeh: Fix crash when edev->pdev changes
From: Sam Bobroff @ 2019-08-02 6:32 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <cover.1564727543.git.sbobroff@linux.ibm.com>
If a PCI device is removed during eeh_pe_report_edev(), between the
calls to device_lock() and device_unlock(), edev->pdev will change and
cause a crash as the wrong mutex is released.
To correct this, hold the PCI rescan/remove lock while taking a copy
of edev->pdev and performing a get_device() on it. Use this value to
release the mutex, but also pass it through to the device driver's EEH
handlers so that they always see the same device.
Signed-off-by: Sam Bobroff <sbobroff@linux.ibm.com>
---
arch/powerpc/kernel/eeh_driver.c | 44 +++++++++++++++++++++-----------
1 file changed, 29 insertions(+), 15 deletions(-)
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 927b59d8a9e5..56841c6451e5 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -257,20 +257,27 @@ static void eeh_set_irq_state(struct eeh_pe *root, bool enable)
}
typedef enum pci_ers_result (*eeh_report_fn)(struct eeh_dev *,
+ struct pci_dev *,
struct pci_driver *);
static void eeh_pe_report_edev(struct eeh_dev *edev, eeh_report_fn fn,
enum pci_ers_result *result)
{
+ struct pci_dev *pdev;
struct pci_driver *driver;
enum pci_ers_result new_result;
- if (!edev->pdev) {
+ pci_lock_rescan_remove();
+ pdev = edev->pdev;
+ if (pdev)
+ get_device(&pdev->dev);
+ pci_unlock_rescan_remove();
+ if (!pdev) {
eeh_edev_info(edev, "no device");
return;
}
- device_lock(&edev->pdev->dev);
+ device_lock(&pdev->dev);
if (eeh_edev_actionable(edev)) {
- driver = eeh_pcid_get(edev->pdev);
+ driver = eeh_pcid_get(pdev);
if (!driver)
eeh_edev_info(edev, "no driver");
@@ -279,7 +286,7 @@ static void eeh_pe_report_edev(struct eeh_dev *edev, eeh_report_fn fn,
else if (edev->mode & EEH_DEV_NO_HANDLER)
eeh_edev_info(edev, "driver bound too late");
else {
- new_result = fn(edev, driver);
+ new_result = fn(edev, pdev, driver);
eeh_edev_info(edev, "%s driver reports: '%s'",
driver->name,
pci_ers_result_name(new_result));
@@ -288,12 +295,15 @@ static void eeh_pe_report_edev(struct eeh_dev *edev, eeh_report_fn fn,
new_result);
}
if (driver)
- eeh_pcid_put(edev->pdev);
+ eeh_pcid_put(pdev);
} else {
- eeh_edev_info(edev, "not actionable (%d,%d,%d)", !!edev->pdev,
+ eeh_edev_info(edev, "not actionable (%d,%d,%d)", !!pdev,
!eeh_dev_removed(edev), !eeh_pe_passed(edev->pe));
}
- device_unlock(&edev->pdev->dev);
+ device_unlock(&pdev->dev);
+ if (edev->pdev != pdev)
+ eeh_edev_warn(edev, "Device changed during processing!\n");
+ put_device(&pdev->dev);
}
static void eeh_pe_report(const char *name, struct eeh_pe *root,
@@ -320,20 +330,20 @@ static void eeh_pe_report(const char *name, struct eeh_pe *root,
* Report an EEH error to each device driver.
*/
static enum pci_ers_result eeh_report_error(struct eeh_dev *edev,
+ struct pci_dev *pdev,
struct pci_driver *driver)
{
enum pci_ers_result rc;
- struct pci_dev *dev = edev->pdev;
if (!driver->err_handler->error_detected)
return PCI_ERS_RESULT_NONE;
eeh_edev_info(edev, "Invoking %s->error_detected(IO frozen)",
driver->name);
- rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen);
+ rc = driver->err_handler->error_detected(pdev, pci_channel_io_frozen);
edev->in_error = true;
- pci_uevent_ers(dev, PCI_ERS_RESULT_NONE);
+ pci_uevent_ers(pdev, PCI_ERS_RESULT_NONE);
return rc;
}
@@ -346,12 +356,13 @@ static enum pci_ers_result eeh_report_error(struct eeh_dev *edev,
* are now enabled.
*/
static enum pci_ers_result eeh_report_mmio_enabled(struct eeh_dev *edev,
+ struct pci_dev *pdev,
struct pci_driver *driver)
{
if (!driver->err_handler->mmio_enabled)
return PCI_ERS_RESULT_NONE;
eeh_edev_info(edev, "Invoking %s->mmio_enabled()", driver->name);
- return driver->err_handler->mmio_enabled(edev->pdev);
+ return driver->err_handler->mmio_enabled(pdev);
}
/**
@@ -365,12 +376,13 @@ static enum pci_ers_result eeh_report_mmio_enabled(struct eeh_dev *edev,
* driver can work again while the device is recovered.
*/
static enum pci_ers_result eeh_report_reset(struct eeh_dev *edev,
+ struct pci_dev *pdev,
struct pci_driver *driver)
{
if (!driver->err_handler->slot_reset || !edev->in_error)
return PCI_ERS_RESULT_NONE;
eeh_edev_info(edev, "Invoking %s->slot_reset()", driver->name);
- return driver->err_handler->slot_reset(edev->pdev);
+ return driver->err_handler->slot_reset(pdev);
}
static void eeh_dev_restore_state(struct eeh_dev *edev, void *userdata)
@@ -410,13 +422,14 @@ static void eeh_dev_restore_state(struct eeh_dev *edev, void *userdata)
* to make the recovered device work again.
*/
static enum pci_ers_result eeh_report_resume(struct eeh_dev *edev,
+ struct pci_dev *pdev,
struct pci_driver *driver)
{
if (!driver->err_handler->resume || !edev->in_error)
return PCI_ERS_RESULT_NONE;
eeh_edev_info(edev, "Invoking %s->resume()", driver->name);
- driver->err_handler->resume(edev->pdev);
+ driver->err_handler->resume(pdev);
pci_uevent_ers(edev->pdev, PCI_ERS_RESULT_RECOVERED);
#ifdef CONFIG_PCI_IOV
@@ -435,6 +448,7 @@ static enum pci_ers_result eeh_report_resume(struct eeh_dev *edev,
* dead, and that no further recovery attempts will be made on it.
*/
static enum pci_ers_result eeh_report_failure(struct eeh_dev *edev,
+ struct pci_dev *pdev,
struct pci_driver *driver)
{
enum pci_ers_result rc;
@@ -444,10 +458,10 @@ static enum pci_ers_result eeh_report_failure(struct eeh_dev *edev,
eeh_edev_info(edev, "Invoking %s->error_detected(permanent failure)",
driver->name);
- rc = driver->err_handler->error_detected(edev->pdev,
+ rc = driver->err_handler->error_detected(pdev,
pci_channel_io_perm_failure);
- pci_uevent_ers(edev->pdev, PCI_ERS_RESULT_DISCONNECT);
+ pci_uevent_ers(pdev, PCI_ERS_RESULT_DISCONNECT);
return rc;
}
--
2.22.0.216.g00a2a96fc9
^ permalink raw reply related
* [PATCH 1/3] powerpc/eeh: Slightly simplify eeh_add_to_parent_pe()
From: Sam Bobroff @ 2019-08-02 6:32 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <cover.1564727543.git.sbobroff@linux.ibm.com>
Simplify some needlessly complicated boolean logic in
eeh_add_to_parent_pe().
Signed-off-by: Sam Bobroff <sbobroff@linux.ibm.com>
---
arch/powerpc/kernel/eeh_pe.c | 52 +++++++++++++++++++-----------------
1 file changed, 27 insertions(+), 25 deletions(-)
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c
index 317a31624526..236e6a667114 100644
--- a/arch/powerpc/kernel/eeh_pe.c
+++ b/arch/powerpc/kernel/eeh_pe.c
@@ -390,32 +390,34 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
* components.
*/
pe = eeh_pe_get(pdn->phb, edev->pe_config_addr, config_addr);
- if (pe && !(pe->type & EEH_PE_INVALID)) {
- /* Mark the PE as type of PCI bus */
- pe->type = EEH_PE_BUS;
- edev->pe = pe;
-
- /* Put the edev to PE */
- list_add_tail(&edev->entry, &pe->edevs);
- eeh_edev_dbg(edev, "Added to bus PE\n");
- return 0;
- } else if (pe && (pe->type & EEH_PE_INVALID)) {
- list_add_tail(&edev->entry, &pe->edevs);
- edev->pe = pe;
- /*
- * We're running to here because of PCI hotplug caused by
- * EEH recovery. We need clear EEH_PE_INVALID until the top.
- */
- parent = pe;
- while (parent) {
- if (!(parent->type & EEH_PE_INVALID))
- break;
- parent->type &= ~EEH_PE_INVALID;
- parent = parent->parent;
- }
+ if (pe) {
+ if (pe->type & EEH_PE_INVALID) {
+ list_add_tail(&edev->entry, &pe->edevs);
+ edev->pe = pe;
+ /*
+ * We're running to here because of PCI hotplug caused by
+ * EEH recovery. We need clear EEH_PE_INVALID until the top.
+ */
+ parent = pe;
+ while (parent) {
+ if (!(parent->type & EEH_PE_INVALID))
+ break;
+ parent->type &= ~EEH_PE_INVALID;
+ parent = parent->parent;
+ }
- eeh_edev_dbg(edev, "Added to device PE (parent: PE#%x)\n",
- pe->parent->addr);
+ eeh_edev_dbg(edev,
+ "Added to device PE (parent: PE#%x)\n",
+ pe->parent->addr);
+ } else {
+ /* Mark the PE as type of PCI bus */
+ pe->type = EEH_PE_BUS;
+ edev->pe = pe;
+
+ /* Put the edev to PE */
+ list_add_tail(&edev->entry, &pe->edevs);
+ eeh_edev_dbg(edev, "Added to bus PE\n");
+ }
return 0;
}
--
2.22.0.216.g00a2a96fc9
^ permalink raw reply related
* [PATCH 0/3] EEH fixes 4
From: Sam Bobroff @ 2019-08-02 6:32 UTC (permalink / raw)
To: linuxppc-dev
Hello Everyone,
Here are three small fixes to the upper level EEH code: two small cleanups
and a fix for a crash when PCI device removal races with EEH recovery.
(They are based on my last (unnamed) set of EEH fixes, which are not yet
upstream, but they should apply fairly easily without them if necessary.)
For the crash fix, I did consider holding the pci_rescan_remove lock for the
whole recovery phase but I was afraid that a driver may block for a long time
(I've seen five minutes) or even crash and leave the lock held forever.
Cheers,
Sam.
Sam Bobroff (3):
powerpc/eeh: Slightly simplify eeh_add_to_parent_pe()
powerpc/eeh: Remove unused return path from eeh_pe_dev_traverse()
powerpc/eeh: Fix crash when edev->pdev changes
arch/powerpc/include/asm/eeh.h | 6 +--
arch/powerpc/kernel/eeh.c | 16 +++----
arch/powerpc/kernel/eeh_driver.c | 70 ++++++++++++++++-------------
arch/powerpc/kernel/eeh_pe.c | 77 ++++++++++++++------------------
4 files changed, 82 insertions(+), 87 deletions(-)
--
2.22.0.216.g00a2a96fc9
^ permalink raw reply
* [PATCH 2/3] powerpc/eeh: Remove unused return path from eeh_pe_dev_traverse()
From: Sam Bobroff @ 2019-08-02 6:32 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <cover.1564727543.git.sbobroff@linux.ibm.com>
There are no users of the early-out return value from
eeh_pe_dev_traverse(), so remove it.
Signed-off-by: Sam Bobroff <sbobroff@linux.ibm.com>
---
arch/powerpc/include/asm/eeh.h | 6 +++---
arch/powerpc/kernel/eeh.c | 16 +++++-----------
arch/powerpc/kernel/eeh_driver.c | 26 +++++++++++---------------
arch/powerpc/kernel/eeh_pe.c | 25 +++++++------------------
4 files changed, 26 insertions(+), 47 deletions(-)
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index e1023a556721..10cb6342f60b 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -261,7 +261,7 @@ static inline bool eeh_state_active(int state)
== (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
}
-typedef void *(*eeh_edev_traverse_func)(struct eeh_dev *edev, void *flag);
+typedef void (*eeh_edev_traverse_func)(struct eeh_dev *edev, void *flag);
typedef void *(*eeh_pe_traverse_func)(struct eeh_pe *pe, void *flag);
void eeh_set_pe_aux_size(int size);
int eeh_phb_pe_create(struct pci_controller *phb);
@@ -275,8 +275,8 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev);
void eeh_pe_update_time_stamp(struct eeh_pe *pe);
void *eeh_pe_traverse(struct eeh_pe *root,
eeh_pe_traverse_func fn, void *flag);
-void *eeh_pe_dev_traverse(struct eeh_pe *root,
- eeh_edev_traverse_func fn, void *flag);
+void eeh_pe_dev_traverse(struct eeh_pe *root,
+ eeh_edev_traverse_func fn, void *flag);
void eeh_pe_restore_bars(struct eeh_pe *pe);
const char *eeh_pe_loc_get(struct eeh_pe *pe);
struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe);
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index b6683f367f7f..b7a884305ae5 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -696,7 +696,7 @@ int eeh_pci_enable(struct eeh_pe *pe, int function)
return rc;
}
-static void *eeh_disable_and_save_dev_state(struct eeh_dev *edev,
+static void eeh_disable_and_save_dev_state(struct eeh_dev *edev,
void *userdata)
{
struct pci_dev *pdev = eeh_dev_to_pci_dev(edev);
@@ -707,7 +707,7 @@ static void *eeh_disable_and_save_dev_state(struct eeh_dev *edev,
* state for the specified device
*/
if (!pdev || pdev == dev)
- return NULL;
+ return;
/* Ensure we have D0 power state */
pci_set_power_state(pdev, PCI_D0);
@@ -720,18 +720,16 @@ static void *eeh_disable_and_save_dev_state(struct eeh_dev *edev,
* interrupt from the device
*/
pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
-
- return NULL;
}
-static void *eeh_restore_dev_state(struct eeh_dev *edev, void *userdata)
+static void eeh_restore_dev_state(struct eeh_dev *edev, void *userdata)
{
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
struct pci_dev *pdev = eeh_dev_to_pci_dev(edev);
struct pci_dev *dev = userdata;
if (!pdev)
- return NULL;
+ return;
/* Apply customization from firmware */
if (pdn && eeh_ops->restore_config)
@@ -740,8 +738,6 @@ static void *eeh_restore_dev_state(struct eeh_dev *edev, void *userdata)
/* The caller should restore state for the specified device */
if (pdev != dev)
pci_restore_state(pdev);
-
- return NULL;
}
int eeh_restore_vf_config(struct pci_dn *pdn)
@@ -956,7 +952,7 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
* the indicated device and its children so that the bunch of the
* devices could be reset properly.
*/
-static void *eeh_set_dev_freset(struct eeh_dev *edev, void *flag)
+static void eeh_set_dev_freset(struct eeh_dev *edev, void *flag)
{
struct pci_dev *dev;
unsigned int *freset = (unsigned int *)flag;
@@ -964,8 +960,6 @@ static void *eeh_set_dev_freset(struct eeh_dev *edev, void *flag)
dev = eeh_dev_to_pci_dev(edev);
if (dev)
*freset |= dev->needs_freset;
-
- return NULL;
}
static void eeh_pe_refreeze_passed(struct eeh_pe *root)
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 670b6159cef1..927b59d8a9e5 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -198,12 +198,12 @@ static void eeh_enable_irq(struct eeh_dev *edev)
}
}
-static void *eeh_dev_save_state(struct eeh_dev *edev, void *userdata)
+static void eeh_dev_save_state(struct eeh_dev *edev, void *userdata)
{
struct pci_dev *pdev;
if (!edev)
- return NULL;
+ return;
/*
* We cannot access the config space on some adapters.
@@ -213,14 +213,13 @@ static void *eeh_dev_save_state(struct eeh_dev *edev, void *userdata)
* device is created.
*/
if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED))
- return NULL;
+ return;
pdev = eeh_dev_to_pci_dev(edev);
if (!pdev)
- return NULL;
+ return;
pci_save_state(pdev);
- return NULL;
}
static void eeh_set_channel_state(struct eeh_pe *root, enum pci_channel_state s)
@@ -374,12 +373,12 @@ static enum pci_ers_result eeh_report_reset(struct eeh_dev *edev,
return driver->err_handler->slot_reset(edev->pdev);
}
-static void *eeh_dev_restore_state(struct eeh_dev *edev, void *userdata)
+static void eeh_dev_restore_state(struct eeh_dev *edev, void *userdata)
{
struct pci_dev *pdev;
if (!edev)
- return NULL;
+ return;
/*
* The content in the config space isn't saved because
@@ -391,15 +390,14 @@ static void *eeh_dev_restore_state(struct eeh_dev *edev, void *userdata)
if (list_is_last(&edev->entry, &edev->pe->edevs))
eeh_pe_restore_bars(edev->pe);
- return NULL;
+ return;
}
pdev = eeh_dev_to_pci_dev(edev);
if (!pdev)
- return NULL;
+ return;
pci_restore_state(pdev);
- return NULL;
}
/**
@@ -478,7 +476,7 @@ static void *eeh_add_virt_device(struct eeh_dev *edev)
return NULL;
}
-static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata)
+static void eeh_rmv_device(struct eeh_dev *edev, void *userdata)
{
struct pci_driver *driver;
struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
@@ -493,7 +491,7 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata)
*/
if (!eeh_edev_actionable(edev) ||
(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE))
- return NULL;
+ return;
if (rmv_data) {
driver = eeh_pcid_get(dev);
@@ -502,7 +500,7 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata)
driver->err_handler->error_detected &&
driver->err_handler->slot_reset) {
eeh_pcid_put(dev);
- return NULL;
+ return;
}
eeh_pcid_put(dev);
}
@@ -535,8 +533,6 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata)
pci_stop_and_remove_bus_device(dev);
pci_unlock_rescan_remove();
}
-
- return NULL;
}
static void *eeh_pe_detach_dev(struct eeh_pe *pe, void *userdata)
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c
index 236e6a667114..1a6254bcf056 100644
--- a/arch/powerpc/kernel/eeh_pe.c
+++ b/arch/powerpc/kernel/eeh_pe.c
@@ -231,29 +231,22 @@ void *eeh_pe_traverse(struct eeh_pe *root,
* The function is used to traverse the devices of the specified
* PE and its child PEs.
*/
-void *eeh_pe_dev_traverse(struct eeh_pe *root,
+void eeh_pe_dev_traverse(struct eeh_pe *root,
eeh_edev_traverse_func fn, void *flag)
{
struct eeh_pe *pe;
struct eeh_dev *edev, *tmp;
- void *ret;
if (!root) {
pr_warn("%s: Invalid PE %p\n",
__func__, root);
- return NULL;
+ return;
}
/* Traverse root PE */
- eeh_for_each_pe(root, pe) {
- eeh_pe_for_each_dev(pe, edev, tmp) {
- ret = fn(edev, flag);
- if (ret)
- return ret;
- }
- }
-
- return NULL;
+ eeh_for_each_pe(root, pe)
+ eeh_pe_for_each_dev(pe, edev, tmp)
+ fn(edev, flag);
}
/**
@@ -604,13 +597,11 @@ void eeh_pe_mark_isolated(struct eeh_pe *root)
}
EXPORT_SYMBOL_GPL(eeh_pe_mark_isolated);
-static void *__eeh_pe_dev_mode_mark(struct eeh_dev *edev, void *flag)
+static void __eeh_pe_dev_mode_mark(struct eeh_dev *edev, void *flag)
{
int mode = *((int *)flag);
edev->mode |= mode;
-
- return NULL;
}
/**
@@ -829,7 +820,7 @@ static void eeh_restore_device_bars(struct eeh_dev *edev)
* the expansion ROM base address, the latency timer, and etc.
* from the saved values in the device node.
*/
-static void *eeh_restore_one_device_bars(struct eeh_dev *edev, void *flag)
+static void eeh_restore_one_device_bars(struct eeh_dev *edev, void *flag)
{
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
@@ -841,8 +832,6 @@ static void *eeh_restore_one_device_bars(struct eeh_dev *edev, void *flag)
if (eeh_ops->restore_config && pdn)
eeh_ops->restore_config(pdn);
-
- return NULL;
}
/**
--
2.22.0.216.g00a2a96fc9
^ permalink raw reply related
* Re: [PATCH 5/5] dma-mapping: remove ARCH_NO_COHERENT_DMA_MMAP
From: Christoph Hellwig @ 2019-08-02 7:03 UTC (permalink / raw)
To: Takashi Iwai, iommu, Marek Szyprowski
Cc: linux-xtensa, Michal Simek, linux-parisc, linux-sh, Robin Murphy,
x86, linux-kernel, linux-m68k, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20190725063401.29904-6-hch@lst.de>
Takashi,
any comments on the sounds/ side of this?
On Thu, Jul 25, 2019 at 08:34:01AM +0200, Christoph Hellwig wrote:
> Now that we never use a default ->mmap implementation, and non-coherent
> architectures can control the presence of ->mmap support by enabling
> ARCH_HAS_DMA_COHERENT_TO_PFN for the dma direct implementation there
> is no need for a global config option to control the availability
> of dma_common_mmap.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> arch/Kconfig | 3 ---
> arch/c6x/Kconfig | 1 -
> arch/m68k/Kconfig | 1 -
> arch/microblaze/Kconfig | 1 -
> arch/parisc/Kconfig | 1 -
> arch/sh/Kconfig | 1 -
> arch/xtensa/Kconfig | 1 -
> kernel/dma/mapping.c | 4 ----
> sound/core/pcm_native.c | 10 +---------
> 9 files changed, 1 insertion(+), 22 deletions(-)
>
> diff --git a/arch/Kconfig b/arch/Kconfig
> index a7b57dd42c26..ec2834206d08 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -790,9 +790,6 @@ config COMPAT_32BIT_TIME
> This is relevant on all 32-bit architectures, and 64-bit architectures
> as part of compat syscall handling.
>
> -config ARCH_NO_COHERENT_DMA_MMAP
> - bool
> -
> config ARCH_NO_PREEMPT
> bool
>
> diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig
> index b4fb61c83494..e65e8d82442a 100644
> --- a/arch/c6x/Kconfig
> +++ b/arch/c6x/Kconfig
> @@ -20,7 +20,6 @@ config C6X
> select OF_EARLY_FLATTREE
> select GENERIC_CLOCKEVENTS
> select MODULES_USE_ELF_RELA
> - select ARCH_NO_COHERENT_DMA_MMAP
> select MMU_GATHER_NO_RANGE if MMU
>
> config MMU
> diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
> index c518d695c376..614b355ae338 100644
> --- a/arch/m68k/Kconfig
> +++ b/arch/m68k/Kconfig
> @@ -8,7 +8,6 @@ config M68K
> select ARCH_HAS_DMA_PREP_COHERENT if HAS_DMA && MMU && !COLDFIRE
> select ARCH_HAS_SYNC_DMA_FOR_DEVICE if HAS_DMA
> select ARCH_MIGHT_HAVE_PC_PARPORT if ISA
> - select ARCH_NO_COHERENT_DMA_MMAP if !MMU
> select ARCH_NO_PREEMPT if !COLDFIRE
> select BINFMT_FLAT_ARGVP_ENVP_ON_STACK
> select DMA_DIRECT_REMAP if HAS_DMA && MMU && !COLDFIRE
> diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
> index d411de05b628..632c9477a0f6 100644
> --- a/arch/microblaze/Kconfig
> +++ b/arch/microblaze/Kconfig
> @@ -9,7 +9,6 @@ config MICROBLAZE
> select ARCH_HAS_SYNC_DMA_FOR_CPU
> select ARCH_HAS_SYNC_DMA_FOR_DEVICE
> select ARCH_MIGHT_HAVE_PC_PARPORT
> - select ARCH_NO_COHERENT_DMA_MMAP if !MMU
> select ARCH_WANT_IPC_PARSE_VERSION
> select BUILDTIME_EXTABLE_SORT
> select TIMER_OF
> diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
> index 6d732e451071..e9dd88b7f81e 100644
> --- a/arch/parisc/Kconfig
> +++ b/arch/parisc/Kconfig
> @@ -52,7 +52,6 @@ config PARISC
> select GENERIC_SCHED_CLOCK
> select HAVE_UNSTABLE_SCHED_CLOCK if SMP
> select GENERIC_CLOCKEVENTS
> - select ARCH_NO_COHERENT_DMA_MMAP
> select CPU_NO_EFFICIENT_FFS
> select NEED_DMA_MAP_STATE
> select NEED_SG_DMA_LENGTH
> diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
> index 6b1b5941b618..f356ee674d89 100644
> --- a/arch/sh/Kconfig
> +++ b/arch/sh/Kconfig
> @@ -5,7 +5,6 @@ config SUPERH
> select ARCH_HAS_PTE_SPECIAL
> select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
> select ARCH_MIGHT_HAVE_PC_PARPORT
> - select ARCH_NO_COHERENT_DMA_MMAP if !MMU
> select HAVE_PATA_PLATFORM
> select CLKDEV_LOOKUP
> select DMA_DECLARE_COHERENT
> diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
> index ebc135bda921..70653aed3005 100644
> --- a/arch/xtensa/Kconfig
> +++ b/arch/xtensa/Kconfig
> @@ -5,7 +5,6 @@ config XTENSA
> select ARCH_HAS_BINFMT_FLAT if !MMU
> select ARCH_HAS_SYNC_DMA_FOR_CPU
> select ARCH_HAS_SYNC_DMA_FOR_DEVICE
> - select ARCH_NO_COHERENT_DMA_MMAP if !MMU
> select ARCH_USE_QUEUED_RWLOCKS
> select ARCH_USE_QUEUED_SPINLOCKS
> select ARCH_WANT_FRAME_POINTERS
> diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
> index 7dff1829c8c5..815446f76995 100644
> --- a/kernel/dma/mapping.c
> +++ b/kernel/dma/mapping.c
> @@ -169,7 +169,6 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
> void *cpu_addr, dma_addr_t dma_addr, size_t size,
> unsigned long attrs)
> {
> -#ifndef CONFIG_ARCH_NO_COHERENT_DMA_MMAP
> unsigned long user_count = vma_pages(vma);
> unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> unsigned long off = vma->vm_pgoff;
> @@ -198,9 +197,6 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
>
> return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
> user_count << PAGE_SHIFT, vma->vm_page_prot);
> -#else
> - return -ENXIO;
> -#endif /* !CONFIG_ARCH_NO_COHERENT_DMA_MMAP */
> }
>
> /**
> diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> index 860543a4c840..2dadc708343a 100644
> --- a/sound/core/pcm_native.c
> +++ b/sound/core/pcm_native.c
> @@ -218,15 +218,7 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
>
> static bool hw_support_mmap(struct snd_pcm_substream *substream)
> {
> - if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
> - return false;
> - /* architecture supports dma_mmap_coherent()? */
> -#if defined(CONFIG_ARCH_NO_COHERENT_DMA_MMAP) || !defined(CONFIG_HAS_DMA)
> - if (!substream->ops->mmap &&
> - substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
> - return false;
> -#endif
> - return true;
> + return substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP;
> }
>
> static int constrain_mask_params(struct snd_pcm_substream *substream,
> --
> 2.20.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
---end quoted text---
^ permalink raw reply
* Re: [PATCH 1/1] pseries/hotplug-memory.c: Change rc variable to bool
From: David Hildenbrand @ 2019-08-02 7:18 UTC (permalink / raw)
To: Leonardo Bras, linuxppc-dev, linux-kernel
Cc: Rob Herring, Rafael J. Wysocki, YueHaibing, Mahesh Salgaonkar,
Paul Mackerras, Greg Kroah-Hartman, Nathan Fontenot,
Thomas Gleixner
In-Reply-To: <20190801231055.19603-1-leonardo@linux.ibm.com>
On 02.08.19 01:10, Leonardo Bras wrote:
> Changes the return variable to bool (as the return value) and
> avoids doing a ternary operation before returning.
>
> Also, since rc will always be true, there is no need to do
> rc &= bool, as (true && X) will result in X.
>
> Signed-off-by: Leonardo Bras <leonardo@linux.ibm.com>
> ---
> arch/powerpc/platforms/pseries/hotplug-memory.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
> index 8e700390f3d6..392deb4855e5 100644
> --- a/arch/powerpc/platforms/pseries/hotplug-memory.c
> +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
> @@ -338,7 +338,7 @@ static int pseries_remove_mem_node(struct device_node *np)
> static bool lmb_is_removable(struct drmem_lmb *lmb)
> {
> int i, scns_per_block;
> - int rc = 1;
> + bool rc = true;
> unsigned long pfn, block_sz;
> u64 phys_addr;
>
> @@ -363,11 +363,11 @@ static bool lmb_is_removable(struct drmem_lmb *lmb)
> if (!pfn_present(pfn))
> continue;
>
> - rc &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
> + rc = is_mem_section_removable(pfn, PAGES_PER_SECTION);
No, that's wrong.
If is_mem_section_removable() is false in the first iteration but true
in the last iteration, you would return true instead of false, which
introduced a bug. We have to AND all sub-results, not simply use the
last one.
> phys_addr += MIN_MEMORY_BLOCK_SIZE;
> }
>
> - return rc ? true : false;
> + return rc;
> }
>
> static int dlpar_add_lmb(struct drmem_lmb *);
>
--
Thanks,
David / dhildenb
^ permalink raw reply
* Re: [PATCH 1/1] pseries/hotplug-memory.c: Replace nested ifs by switch-case
From: David Hildenbrand @ 2019-08-02 7:21 UTC (permalink / raw)
To: Leonardo Bras, linuxppc-dev, linux-kernel
Cc: Nathan Lynch, Pavel Tatashin, Rob Herring, Greg Kroah-Hartman,
YueHaibing, Mahesh Salgaonkar, Paul Mackerras, Nathan Fontenot,
Andrew Morton
In-Reply-To: <20190801225251.17864-1-leonardo@linux.ibm.com>
On 02.08.19 00:52, Leonardo Bras wrote:
> I noticed these nested ifs can be easily replaced by switch-cases,
> which can improve readability.
>
> Signed-off-by: Leonardo Bras <leonardo@linux.ibm.com>
> ---
> .../platforms/pseries/hotplug-memory.c | 26 +++++++++++++------
> 1 file changed, 18 insertions(+), 8 deletions(-)
More LOC but seems to be the right thing to do
Reviewed-by: David Hildenbrand <david@redhat.com>
>
> diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
> index 46d0d35b9ca4..8e700390f3d6 100644
> --- a/arch/powerpc/platforms/pseries/hotplug-memory.c
> +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
> @@ -880,34 +880,44 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
>
> switch (hp_elog->action) {
> case PSERIES_HP_ELOG_ACTION_ADD:
> - if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) {
> + switch (hp_elog->id_type) {
> + case PSERIES_HP_ELOG_ID_DRC_COUNT:
> count = hp_elog->_drc_u.drc_count;
> rc = dlpar_memory_add_by_count(count);
> - } else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) {
> + break;
> + case PSERIES_HP_ELOG_ID_DRC_INDEX:
> drc_index = hp_elog->_drc_u.drc_index;
> rc = dlpar_memory_add_by_index(drc_index);
> - } else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_IC) {
> + break;
> + case PSERIES_HP_ELOG_ID_DRC_IC:
> count = hp_elog->_drc_u.ic.count;
> drc_index = hp_elog->_drc_u.ic.index;
> rc = dlpar_memory_add_by_ic(count, drc_index);
> - } else {
> + break;
> + default:
> rc = -EINVAL;
> + break;
> }
>
> break;
> case PSERIES_HP_ELOG_ACTION_REMOVE:
> - if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) {
> + switch (hp_elog->id_type) {
> + case PSERIES_HP_ELOG_ID_DRC_COUNT:
> count = hp_elog->_drc_u.drc_count;
> rc = dlpar_memory_remove_by_count(count);
> - } else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) {
> + break;
> + case PSERIES_HP_ELOG_ID_DRC_INDEX:
> drc_index = hp_elog->_drc_u.drc_index;
> rc = dlpar_memory_remove_by_index(drc_index);
> - } else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_IC) {
> + break;
> + case PSERIES_HP_ELOG_ID_DRC_IC:
> count = hp_elog->_drc_u.ic.count;
> drc_index = hp_elog->_drc_u.ic.index;
> rc = dlpar_memory_remove_by_ic(count, drc_index);
> - } else {
> + break;
> + default:
> rc = -EINVAL;
> + break;
> }
>
> break;
>
--
Thanks,
David / dhildenb
^ permalink raw reply
* Re: [PATCH 1/1] pseries/hotplug-memory.c: Change rc variable to bool
From: David Hildenbrand @ 2019-08-02 7:23 UTC (permalink / raw)
To: Leonardo Bras, linuxppc-dev, linux-kernel
Cc: Rob Herring, Rafael J. Wysocki, YueHaibing, Mahesh Salgaonkar,
Paul Mackerras, Greg Kroah-Hartman, Nathan Fontenot,
Thomas Gleixner
In-Reply-To: <69821502-a449-d1a8-c2e8-a1aa67cca02f@redhat.com>
On 02.08.19 09:18, David Hildenbrand wrote:
> On 02.08.19 01:10, Leonardo Bras wrote:
>> Changes the return variable to bool (as the return value) and
>> avoids doing a ternary operation before returning.
>>
>> Also, since rc will always be true, there is no need to do
>> rc &= bool, as (true && X) will result in X.
>>
>> Signed-off-by: Leonardo Bras <leonardo@linux.ibm.com>
>> ---
>> arch/powerpc/platforms/pseries/hotplug-memory.c | 6 +++---
>> 1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
>> index 8e700390f3d6..392deb4855e5 100644
>> --- a/arch/powerpc/platforms/pseries/hotplug-memory.c
>> +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
>> @@ -338,7 +338,7 @@ static int pseries_remove_mem_node(struct device_node *np)
>> static bool lmb_is_removable(struct drmem_lmb *lmb)
>> {
>> int i, scns_per_block;
>> - int rc = 1;
>> + bool rc = true;
>> unsigned long pfn, block_sz;
>> u64 phys_addr;
>>
>> @@ -363,11 +363,11 @@ static bool lmb_is_removable(struct drmem_lmb *lmb)
>> if (!pfn_present(pfn))
>> continue;
>>
>> - rc &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
>> + rc = is_mem_section_removable(pfn, PAGES_PER_SECTION);
>
> No, that's wrong.
>
> If is_mem_section_removable() is false in the first iteration but true
> in the last iteration, you would return true instead of false, which
> introduced a bug. We have to AND all sub-results, not simply use the
> last one.
BTW, including such subtle changes in a "Change rc variable to bool"
patch should be avoided.
--
Thanks,
David / dhildenb
^ permalink raw reply
* Re: [PATCH] dma-mapping: fix page attributes for dma_mmap_*
From: Christoph Hellwig @ 2019-08-02 8:14 UTC (permalink / raw)
To: Will Deacon
Cc: Shawn Anastasio, linuxppc-dev, Russell King, linux-kernel, iommu,
Catalin Marinas, Robin Murphy, Christoph Hellwig,
linux-arm-kernel
In-Reply-To: <20190801164411.kmsl4japtfkgvzxe@willie-the-truck>
On Thu, Aug 01, 2019 at 05:44:12PM +0100, Will Deacon wrote:
> > > Although arch_dma_mmap_pgprot() is a bit of a misnomer now that it only
> > > gets involved in the non-coherent case.
> >
> > A better name is welcome.
>
> How about arch_dma_noncoherent_mmap_pgprot() ? Too long?
Sounds a little long yes. And doesn't fix the additional problem that
we don't just it for mmap but also for the in-kernel remapping these
days.
> > But my worry is how this interacts with architectures that have an
> > uncached segment (mips, nios2, microblaze, extensa) where we'd have
> > the kernel access DMA_ATTR_WRITE_COMBINE mappigns using the uncached
> > segment, and userspace mmaps using pgprot_writecombine, which could
> > lead to aliasing issues. But then again mips already supports
> > DMA_ATTR_WRITE_COMBINE, so this must be ok somehow. I guess I'll
> > need to field that question to the relevant parties.
>
> Or it's always been busted and happens to work out in practice...
I've sent a ping to the mips folks. While we'are at it: arm64
and arm32 (optionally) map dma coherent allocations as write combine.
I suspect this hasn't always just been busted but intentional (of course!),
but is there any chance to get a quote from the arm architecture spec
on why this is fine as it looks rather confusion?
Also if we assume mips is buggy DMA_ATTR_WRITE_COMBINE really just seems
to be there for old arm platforms, which makes the scope pretty limited.
^ permalink raw reply
* Re: [PATCH 5/5] dma-mapping: remove ARCH_NO_COHERENT_DMA_MMAP
From: Takashi Iwai @ 2019-08-02 8:24 UTC (permalink / raw)
To: Christoph Hellwig
Cc: linux-xtensa, Michal Simek, linux-parisc, linux-sh, Takashi Iwai,
Robin Murphy, x86, linux-kernel, iommu, linux-m68k, linuxppc-dev,
linux-arm-kernel, Marek Szyprowski
In-Reply-To: <20190802070354.GA8280@lst.de>
On Fri, 02 Aug 2019 09:03:54 +0200,
Christoph Hellwig wrote:
>
> Takashi,
>
> any comments on the sounds/ side of this?
I wasn't careful enough to look at that change, sorry.
The code there tries to check whether dma_mmap_coherent() would always
fail on some platforms. Then the driver clears the mmap capability
flag at the device open time and notifies user-space to fall back to
the dumb read/write mode.
So I'm afraid that simply dropping the check would cause the behavior
regression, e.g. on PARISC.
Is there any simple way to test whether dma_mmap_coherent() would work
or not in general on the target platform? It's not necessarily in an
ifdef at all.
thanks,
Takashi
> On Thu, Jul 25, 2019 at 08:34:01AM +0200, Christoph Hellwig wrote:
> > Now that we never use a default ->mmap implementation, and non-coherent
> > architectures can control the presence of ->mmap support by enabling
> > ARCH_HAS_DMA_COHERENT_TO_PFN for the dma direct implementation there
> > is no need for a global config option to control the availability
> > of dma_common_mmap.
> >
> > Signed-off-by: Christoph Hellwig <hch@lst.de>
> > ---
> > arch/Kconfig | 3 ---
> > arch/c6x/Kconfig | 1 -
> > arch/m68k/Kconfig | 1 -
> > arch/microblaze/Kconfig | 1 -
> > arch/parisc/Kconfig | 1 -
> > arch/sh/Kconfig | 1 -
> > arch/xtensa/Kconfig | 1 -
> > kernel/dma/mapping.c | 4 ----
> > sound/core/pcm_native.c | 10 +---------
> > 9 files changed, 1 insertion(+), 22 deletions(-)
> >
> > diff --git a/arch/Kconfig b/arch/Kconfig
> > index a7b57dd42c26..ec2834206d08 100644
> > --- a/arch/Kconfig
> > +++ b/arch/Kconfig
> > @@ -790,9 +790,6 @@ config COMPAT_32BIT_TIME
> > This is relevant on all 32-bit architectures, and 64-bit architectures
> > as part of compat syscall handling.
> >
> > -config ARCH_NO_COHERENT_DMA_MMAP
> > - bool
> > -
> > config ARCH_NO_PREEMPT
> > bool
> >
> > diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig
> > index b4fb61c83494..e65e8d82442a 100644
> > --- a/arch/c6x/Kconfig
> > +++ b/arch/c6x/Kconfig
> > @@ -20,7 +20,6 @@ config C6X
> > select OF_EARLY_FLATTREE
> > select GENERIC_CLOCKEVENTS
> > select MODULES_USE_ELF_RELA
> > - select ARCH_NO_COHERENT_DMA_MMAP
> > select MMU_GATHER_NO_RANGE if MMU
> >
> > config MMU
> > diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
> > index c518d695c376..614b355ae338 100644
> > --- a/arch/m68k/Kconfig
> > +++ b/arch/m68k/Kconfig
> > @@ -8,7 +8,6 @@ config M68K
> > select ARCH_HAS_DMA_PREP_COHERENT if HAS_DMA && MMU && !COLDFIRE
> > select ARCH_HAS_SYNC_DMA_FOR_DEVICE if HAS_DMA
> > select ARCH_MIGHT_HAVE_PC_PARPORT if ISA
> > - select ARCH_NO_COHERENT_DMA_MMAP if !MMU
> > select ARCH_NO_PREEMPT if !COLDFIRE
> > select BINFMT_FLAT_ARGVP_ENVP_ON_STACK
> > select DMA_DIRECT_REMAP if HAS_DMA && MMU && !COLDFIRE
> > diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
> > index d411de05b628..632c9477a0f6 100644
> > --- a/arch/microblaze/Kconfig
> > +++ b/arch/microblaze/Kconfig
> > @@ -9,7 +9,6 @@ config MICROBLAZE
> > select ARCH_HAS_SYNC_DMA_FOR_CPU
> > select ARCH_HAS_SYNC_DMA_FOR_DEVICE
> > select ARCH_MIGHT_HAVE_PC_PARPORT
> > - select ARCH_NO_COHERENT_DMA_MMAP if !MMU
> > select ARCH_WANT_IPC_PARSE_VERSION
> > select BUILDTIME_EXTABLE_SORT
> > select TIMER_OF
> > diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
> > index 6d732e451071..e9dd88b7f81e 100644
> > --- a/arch/parisc/Kconfig
> > +++ b/arch/parisc/Kconfig
> > @@ -52,7 +52,6 @@ config PARISC
> > select GENERIC_SCHED_CLOCK
> > select HAVE_UNSTABLE_SCHED_CLOCK if SMP
> > select GENERIC_CLOCKEVENTS
> > - select ARCH_NO_COHERENT_DMA_MMAP
> > select CPU_NO_EFFICIENT_FFS
> > select NEED_DMA_MAP_STATE
> > select NEED_SG_DMA_LENGTH
> > diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
> > index 6b1b5941b618..f356ee674d89 100644
> > --- a/arch/sh/Kconfig
> > +++ b/arch/sh/Kconfig
> > @@ -5,7 +5,6 @@ config SUPERH
> > select ARCH_HAS_PTE_SPECIAL
> > select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
> > select ARCH_MIGHT_HAVE_PC_PARPORT
> > - select ARCH_NO_COHERENT_DMA_MMAP if !MMU
> > select HAVE_PATA_PLATFORM
> > select CLKDEV_LOOKUP
> > select DMA_DECLARE_COHERENT
> > diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
> > index ebc135bda921..70653aed3005 100644
> > --- a/arch/xtensa/Kconfig
> > +++ b/arch/xtensa/Kconfig
> > @@ -5,7 +5,6 @@ config XTENSA
> > select ARCH_HAS_BINFMT_FLAT if !MMU
> > select ARCH_HAS_SYNC_DMA_FOR_CPU
> > select ARCH_HAS_SYNC_DMA_FOR_DEVICE
> > - select ARCH_NO_COHERENT_DMA_MMAP if !MMU
> > select ARCH_USE_QUEUED_RWLOCKS
> > select ARCH_USE_QUEUED_SPINLOCKS
> > select ARCH_WANT_FRAME_POINTERS
> > diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
> > index 7dff1829c8c5..815446f76995 100644
> > --- a/kernel/dma/mapping.c
> > +++ b/kernel/dma/mapping.c
> > @@ -169,7 +169,6 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
> > void *cpu_addr, dma_addr_t dma_addr, size_t size,
> > unsigned long attrs)
> > {
> > -#ifndef CONFIG_ARCH_NO_COHERENT_DMA_MMAP
> > unsigned long user_count = vma_pages(vma);
> > unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> > unsigned long off = vma->vm_pgoff;
> > @@ -198,9 +197,6 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
> >
> > return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
> > user_count << PAGE_SHIFT, vma->vm_page_prot);
> > -#else
> > - return -ENXIO;
> > -#endif /* !CONFIG_ARCH_NO_COHERENT_DMA_MMAP */
> > }
> >
> > /**
> > diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> > index 860543a4c840..2dadc708343a 100644
> > --- a/sound/core/pcm_native.c
> > +++ b/sound/core/pcm_native.c
> > @@ -218,15 +218,7 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
> >
> > static bool hw_support_mmap(struct snd_pcm_substream *substream)
> > {
> > - if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
> > - return false;
> > - /* architecture supports dma_mmap_coherent()? */
> > -#if defined(CONFIG_ARCH_NO_COHERENT_DMA_MMAP) || !defined(CONFIG_HAS_DMA)
> > - if (!substream->ops->mmap &&
> > - substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
> > - return false;
> > -#endif
> > - return true;
> > + return substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP;
> > }
> >
> > static int constrain_mask_params(struct snd_pcm_substream *substream,
> > --
> > 2.20.1
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> ---end quoted text---
>
^ permalink raw reply
* Re: [PATCH v3 06/10] powerpc/fsl_booke/32: implement KASLR infrastructure
From: Diana Madalina Craciun @ 2019-08-02 8:41 UTC (permalink / raw)
To: Jason Yan, mpe@ellerman.id.au, linuxppc-dev@lists.ozlabs.org,
christophe.leroy@c-s.fr, benh@kernel.crashing.org,
paulus@samba.org, npiggin@gmail.com, keescook@chromium.org,
kernel-hardening@lists.openwall.com
Cc: wangkefeng.wang@huawei.com, linux-kernel@vger.kernel.org,
jingxiangfeng@huawei.com, zhaohongjiang@huawei.com,
thunder.leizhen@huawei.com, fanchengyang@huawei.com,
yebin10@huawei.com
In-Reply-To: <20190731094318.26538-7-yanaijie@huawei.com>
On 7/31/2019 12:27 PM, Jason Yan wrote:
> This patch add support to boot kernel from places other than KERNELBASE.
> Since CONFIG_RELOCATABLE has already supported, what we need to do is
> map or copy kernel to a proper place and relocate. Freescale Book-E
> parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
> entries are not suitable to map the kernel directly in a randomized
> region, so we chose to copy the kernel to a proper place and restart to
> relocate.
>
> The offset of the kernel was not randomized yet(a fixed 64M is set). We
> will randomize it in the next patch.
>
> Signed-off-by: Jason Yan <yanaijie@huawei.com>
> Cc: Diana Craciun <diana.craciun@nxp.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Christophe Leroy <christophe.leroy@c-s.fr>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Nicholas Piggin <npiggin@gmail.com>
> Cc: Kees Cook <keescook@chromium.org>
> ---
> arch/powerpc/Kconfig | 11 +++
> arch/powerpc/kernel/Makefile | 1 +
> arch/powerpc/kernel/early_32.c | 2 +-
> arch/powerpc/kernel/fsl_booke_entry_mapping.S | 13 ++-
> arch/powerpc/kernel/head_fsl_booke.S | 13 ++-
> arch/powerpc/kernel/kaslr_booke.c | 84 +++++++++++++++++++
> arch/powerpc/mm/mmu_decl.h | 6 ++
> arch/powerpc/mm/nohash/fsl_booke.c | 7 +-
> 8 files changed, 124 insertions(+), 13 deletions(-)
> create mode 100644 arch/powerpc/kernel/kaslr_booke.c
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 77f6ebf97113..755378887912 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -548,6 +548,17 @@ config RELOCATABLE
> setting can still be useful to bootwrappers that need to know the
> load address of the kernel (eg. u-boot/mkimage).
>
> +config RANDOMIZE_BASE
> + bool "Randomize the address of the kernel image"
> + depends on (FSL_BOOKE && FLATMEM && PPC32)
> + select RELOCATABLE
> + help
> + Randomizes the virtual address at which the kernel image is
> + loaded, as a security feature that deters exploit attempts
> + relying on knowledge of the location of kernel internals.
> +
> + If unsure, say N.
> +
> config RELOCATABLE_TEST
> bool "Test relocatable kernel"
> depends on (PPC64 && RELOCATABLE)
> diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
> index ea0c69236789..32f6c5b99307 100644
> --- a/arch/powerpc/kernel/Makefile
> +++ b/arch/powerpc/kernel/Makefile
> @@ -106,6 +106,7 @@ extra-$(CONFIG_PPC_8xx) := head_8xx.o
> extra-y += vmlinux.lds
>
> obj-$(CONFIG_RELOCATABLE) += reloc_$(BITS).o
> +obj-$(CONFIG_RANDOMIZE_BASE) += kaslr_booke.o
>
> obj-$(CONFIG_PPC32) += entry_32.o setup_32.o early_32.o
> obj-$(CONFIG_PPC64) += dma-iommu.o iommu.o
> diff --git a/arch/powerpc/kernel/early_32.c b/arch/powerpc/kernel/early_32.c
> index 3482118ffe76..fe8347cdc07d 100644
> --- a/arch/powerpc/kernel/early_32.c
> +++ b/arch/powerpc/kernel/early_32.c
> @@ -32,5 +32,5 @@ notrace unsigned long __init early_init(unsigned long dt_ptr)
>
> apply_feature_fixups();
>
> - return KERNELBASE + offset;
> + return kimage_vaddr + offset;
> }
> diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
> index de0980945510..6d2967673ac7 100644
> --- a/arch/powerpc/kernel/fsl_booke_entry_mapping.S
> +++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
> @@ -161,17 +161,16 @@ skpinv: addi r6,r6,1 /* Increment */
> lis r6,(MAS1_VALID|MAS1_IPROT)@h
> ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
> mtspr SPRN_MAS1,r6
> - lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_NEEDED)@h
> - ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_NEEDED)@l
> - mtspr SPRN_MAS2,r6
> + lis r6,MAS2_EPN_MASK(BOOK3E_PAGESZ_64M)@h
> + ori r6,r6,MAS2_EPN_MASK(BOOK3E_PAGESZ_64M)@l
> + and r6,r6,r20
> + ori r6,r6,M_IF_NEEDED@l
> + mtspr SPRN_MAS2,r6
> mtspr SPRN_MAS3,r8
> tlbwe
>
> /* 7. Jump to KERNELBASE mapping */
The code has changed, but the comment reflects the old code (it no
longer jumps to KERNELBASE, but to kimage_vaddr). This is true for step
6 as well.
> - lis r6,(KERNELBASE & ~0xfff)@h
> - ori r6,r6,(KERNELBASE & ~0xfff)@l
> - rlwinm r7,r25,0,0x03ffffff
> - add r6,r7,r6
> + mr r6,r20
>
> #elif defined(ENTRY_MAPPING_KEXEC_SETUP)
> /*
> diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
> index 2083382dd662..aa55832e7506 100644
> --- a/arch/powerpc/kernel/head_fsl_booke.S
> +++ b/arch/powerpc/kernel/head_fsl_booke.S
> @@ -155,6 +155,8 @@ _ENTRY(_start);
> */
>
> _ENTRY(__early_start)
> + LOAD_REG_ADDR_PIC(r20, kimage_vaddr)
> + lwz r20,0(r20)
>
> #define ENTRY_MAPPING_BOOT_SETUP
> #include "fsl_booke_entry_mapping.S"
> @@ -277,8 +279,8 @@ set_ivor:
> ori r6, r6, swapper_pg_dir@l
> lis r5, abatron_pteptrs@h
> ori r5, r5, abatron_pteptrs@l
> - lis r4, KERNELBASE@h
> - ori r4, r4, KERNELBASE@l
> + lis r3, kimage_vaddr@ha
> + lwz r4, kimage_vaddr@l(r3)
> stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */
> stw r6, 0(r5)
>
> @@ -1067,7 +1069,12 @@ __secondary_start:
> mr r5,r25 /* phys kernel start */
> rlwinm r5,r5,0,~0x3ffffff /* aligned 64M */
> subf r4,r5,r4 /* memstart_addr - phys kernel start */
> - li r5,0 /* no device tree */
> + lis r7,KERNELBASE@h
> + ori r7,r7,KERNELBASE@l
> + cmpw r20,r7 /* if kimage_vaddr != KERNELBASE, randomized */
> + beq 2f
> + li r4,0
> +2: li r5,0 /* no device tree */
> li r6,0 /* not boot cpu */
> bl restore_to_as0
>
> diff --git a/arch/powerpc/kernel/kaslr_booke.c b/arch/powerpc/kernel/kaslr_booke.c
> new file mode 100644
> index 000000000000..30f84c0321b2
> --- /dev/null
> +++ b/arch/powerpc/kernel/kaslr_booke.c
> @@ -0,0 +1,84 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2019 Jason Yan <yanaijie@huawei.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/signal.h>
> +#include <linux/sched.h>
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +#include <linux/ptrace.h>
> +#include <linux/mman.h>
> +#include <linux/mm.h>
> +#include <linux/swap.h>
> +#include <linux/stddef.h>
> +#include <linux/vmalloc.h>
> +#include <linux/init.h>
> +#include <linux/delay.h>
> +#include <linux/highmem.h>
> +#include <linux/memblock.h>
> +#include <asm/pgalloc.h>
> +#include <asm/prom.h>
> +#include <asm/io.h>
> +#include <asm/mmu_context.h>
> +#include <asm/pgtable.h>
> +#include <asm/mmu.h>
> +#include <linux/uaccess.h>
> +#include <asm/smp.h>
> +#include <asm/machdep.h>
> +#include <asm/setup.h>
> +#include <asm/paca.h>
> +#include <mm/mmu_decl.h>
> +
> +extern int is_second_reloc;
> +
> +static unsigned long __init kaslr_choose_location(void *dt_ptr, phys_addr_t size,
> + unsigned long kernel_sz)
> +{
> + /* return a fixed offset of 64M for now */
> + return SZ_64M;
> +}
> +
> +/*
> + * To see if we need to relocate the kernel to a random offset
> + * void *dt_ptr - address of the device tree
> + * phys_addr_t size - size of the first memory block
> + */
> +notrace void __init kaslr_early_init(void *dt_ptr, phys_addr_t size)
> +{
> + unsigned long tlb_virt;
> + phys_addr_t tlb_phys;
> + unsigned long offset;
> + unsigned long kernel_sz;
> +
> + kernel_sz = (unsigned long)_end - KERNELBASE;
> +
> + offset = kaslr_choose_location(dt_ptr, size, kernel_sz);
> +
> + if (offset == 0)
> + return;
> +
> + kimage_vaddr += offset;
> + kernstart_addr += offset;
> +
> + is_second_reloc = 1;
> +
> + if (offset >= SZ_64M) {
> + tlb_virt = round_down(kimage_vaddr, SZ_64M);
> + tlb_phys = round_down(kernstart_addr, SZ_64M);
> +
> + /* Create kernel map to relocate in */
> + create_tlb_entry(tlb_phys, tlb_virt, 1);
> + }
> +
> + /* Copy the kernel to it's new location and run */
> + memcpy((void *)kimage_vaddr, (void *)KERNELBASE, kernel_sz);
> +
> + reloc_kernel_entry(dt_ptr, kimage_vaddr);
> +}
> diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
> index 804da298beb3..9332772c8a66 100644
> --- a/arch/powerpc/mm/mmu_decl.h
> +++ b/arch/powerpc/mm/mmu_decl.h
> @@ -148,6 +148,12 @@ void reloc_kernel_entry(void *fdt, int addr);
> extern void loadcam_entry(unsigned int index);
> extern void loadcam_multi(int first_idx, int num, int tmp_idx);
>
> +#ifdef CONFIG_RANDOMIZE_BASE
> +void kaslr_early_init(void *dt_ptr, phys_addr_t size);
> +#else
> +static inline void kaslr_early_init(void *dt_ptr, phys_addr_t size) {}
> +#endif
> +
> struct tlbcam {
> u32 MAS0;
> u32 MAS1;
> diff --git a/arch/powerpc/mm/nohash/fsl_booke.c b/arch/powerpc/mm/nohash/fsl_booke.c
> index 556e3cd52a35..8d25a8dc965f 100644
> --- a/arch/powerpc/mm/nohash/fsl_booke.c
> +++ b/arch/powerpc/mm/nohash/fsl_booke.c
> @@ -263,7 +263,8 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,
> int __initdata is_second_reloc;
> notrace void __init relocate_init(u64 dt_ptr, phys_addr_t start)
> {
> - unsigned long base = KERNELBASE;
> + unsigned long base = kimage_vaddr;
> + phys_addr_t size;
>
> kernstart_addr = start;
> if (is_second_reloc) {
> @@ -291,7 +292,7 @@ notrace void __init relocate_init(u64 dt_ptr, phys_addr_t start)
> start &= ~0x3ffffff;
> base &= ~0x3ffffff;
> virt_phys_offset = base - start;
> - early_get_first_memblock_info(__va(dt_ptr), NULL);
> + early_get_first_memblock_info(__va(dt_ptr), &size);
> /*
> * We now get the memstart_addr, then we should check if this
> * address is the same as what the PAGE_OFFSET map to now. If
> @@ -316,6 +317,8 @@ notrace void __init relocate_init(u64 dt_ptr, phys_addr_t start)
> /* We should never reach here */
> panic("Relocation error");
> }
> +
> + kaslr_early_init(__va(dt_ptr), size);
> }
> #endif
> #endif
^ permalink raw reply
* Re: [PATCH v3 00/10] implement KASLR for powerpc/fsl_booke/32
From: Diana Madalina Craciun @ 2019-08-02 8:48 UTC (permalink / raw)
To: Jason Yan, mpe@ellerman.id.au, linuxppc-dev@lists.ozlabs.org,
christophe.leroy@c-s.fr, benh@kernel.crashing.org,
paulus@samba.org, npiggin@gmail.com, keescook@chromium.org,
kernel-hardening@lists.openwall.com
Cc: wangkefeng.wang@huawei.com, linux-kernel@vger.kernel.org,
jingxiangfeng@huawei.com, zhaohongjiang@huawei.com,
thunder.leizhen@huawei.com, fanchengyang@huawei.com,
yebin10@huawei.com
In-Reply-To: <20190731094318.26538-1-yanaijie@huawei.com>
Except for one comment in patch 06/10: Reviewed-by: Diana Craciun
<diana.craciun@nxp.com>
And also: Tested-by: Diana Craciun <diana.craciun@nxp.com>
Regards,
Diana
On 7/31/2019 12:26 PM, Jason Yan wrote:
> This series implements KASLR for powerpc/fsl_booke/32, as a security
> feature that deters exploit attempts relying on knowledge of the location
> of kernel internals.
>
> Since CONFIG_RELOCATABLE has already supported, what we need to do is
> map or copy kernel to a proper place and relocate. Freescale Book-E
> parts expect lowmem to be mapped by fixed TLB entries(TLB1). The TLB1
> entries are not suitable to map the kernel directly in a randomized
> region, so we chose to copy the kernel to a proper place and restart to
> relocate.
>
> Entropy is derived from the banner and timer base, which will change every
> build and boot. This not so much safe so additionally the bootloader may
> pass entropy via the /chosen/kaslr-seed node in device tree.
>
> We will use the first 512M of the low memory to randomize the kernel
> image. The memory will be split in 64M zones. We will use the lower 8
> bit of the entropy to decide the index of the 64M zone. Then we chose a
> 16K aligned offset inside the 64M zone to put the kernel in.
>
> KERNELBASE
>
> |--> 64M <--|
> | |
> +---------------+ +----------------+---------------+
> | |....| |kernel| | |
> +---------------+ +----------------+---------------+
> | |
> |-----> offset <-----|
>
> kimage_vaddr
>
> We also check if we will overlap with some areas like the dtb area, the
> initrd area or the crashkernel area. If we cannot find a proper area,
> kaslr will be disabled and boot from the original kernel.
>
> Changes since v2:
> - Remove unnecessary #ifdef
> - Use SZ_64M instead of0x4000000
> - Call early_init_dt_scan_chosen() to init boot_command_line
> - Rename kaslr_second_init() to kaslr_late_init()
>
> Changes since v1:
> - Remove some useless 'extern' keyword.
> - Replace EXPORT_SYMBOL with EXPORT_SYMBOL_GPL
> - Improve some assembly code
> - Use memzero_explicit instead of memset
> - Use boot_command_line and remove early_command_line
> - Do not print kaslr offset if kaslr is disabled
>
> Jason Yan (10):
> powerpc: unify definition of M_IF_NEEDED
> powerpc: move memstart_addr and kernstart_addr to init-common.c
> powerpc: introduce kimage_vaddr to store the kernel base
> powerpc/fsl_booke/32: introduce create_tlb_entry() helper
> powerpc/fsl_booke/32: introduce reloc_kernel_entry() helper
> powerpc/fsl_booke/32: implement KASLR infrastructure
> powerpc/fsl_booke/32: randomize the kernel image offset
> powerpc/fsl_booke/kaslr: clear the original kernel if randomized
> powerpc/fsl_booke/kaslr: support nokaslr cmdline parameter
> powerpc/fsl_booke/kaslr: dump out kernel offset information on panic
>
> arch/powerpc/Kconfig | 11 +
> arch/powerpc/include/asm/nohash/mmu-book3e.h | 10 +
> arch/powerpc/include/asm/page.h | 7 +
> arch/powerpc/kernel/Makefile | 1 +
> arch/powerpc/kernel/early_32.c | 2 +-
> arch/powerpc/kernel/exceptions-64e.S | 10 -
> arch/powerpc/kernel/fsl_booke_entry_mapping.S | 23 +-
> arch/powerpc/kernel/head_fsl_booke.S | 55 ++-
> arch/powerpc/kernel/kaslr_booke.c | 427 ++++++++++++++++++
> arch/powerpc/kernel/machine_kexec.c | 1 +
> arch/powerpc/kernel/misc_64.S | 5 -
> arch/powerpc/kernel/setup-common.c | 19 +
> arch/powerpc/mm/init-common.c | 7 +
> arch/powerpc/mm/init_32.c | 5 -
> arch/powerpc/mm/init_64.c | 5 -
> arch/powerpc/mm/mmu_decl.h | 10 +
> arch/powerpc/mm/nohash/fsl_booke.c | 8 +-
> 17 files changed, 558 insertions(+), 48 deletions(-)
> create mode 100644 arch/powerpc/kernel/kaslr_booke.c
>
^ permalink raw reply
* Re: [PATCH] dma-mapping: fix page attributes for dma_mmap_*
From: Will Deacon @ 2019-08-02 10:38 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Shawn Anastasio, linuxppc-dev, Russell King, linux-kernel, iommu,
Catalin Marinas, Robin Murphy, linux-arm-kernel
In-Reply-To: <20190802081441.GA9725@lst.de>
On Fri, Aug 02, 2019 at 10:14:41AM +0200, Christoph Hellwig wrote:
> On Thu, Aug 01, 2019 at 05:44:12PM +0100, Will Deacon wrote:
> > > > Although arch_dma_mmap_pgprot() is a bit of a misnomer now that it only
> > > > gets involved in the non-coherent case.
> > >
> > > A better name is welcome.
> >
> > How about arch_dma_noncoherent_mmap_pgprot() ? Too long?
>
> Sounds a little long yes. And doesn't fix the additional problem that
> we don't just it for mmap but also for the in-kernel remapping these
> days.
Hmm. Maybe just arch_dma_noncoherent_pgprot() then.
> > > But my worry is how this interacts with architectures that have an
> > > uncached segment (mips, nios2, microblaze, extensa) where we'd have
> > > the kernel access DMA_ATTR_WRITE_COMBINE mappigns using the uncached
> > > segment, and userspace mmaps using pgprot_writecombine, which could
> > > lead to aliasing issues. But then again mips already supports
> > > DMA_ATTR_WRITE_COMBINE, so this must be ok somehow. I guess I'll
> > > need to field that question to the relevant parties.
> >
> > Or it's always been busted and happens to work out in practice...
>
> I've sent a ping to the mips folks. While we'are at it: arm64
> and arm32 (optionally) map dma coherent allocations as write combine.
> I suspect this hasn't always just been busted but intentional (of course!),
> but is there any chance to get a quote from the arm architecture spec
> on why this is fine as it looks rather confusion?
So this boils down to a terminology mismatch. The Arm architecture doesn't have
anything called "write combine", so in Linux we instead provide what the Arm
architecture calls "Normal non-cacheable" memory for pgprot_writecombine().
Amongst other things, this memory type permits speculation, unaligned accesses
and merging of writes. I found something in the architecture spec about
non-cachable memory, but it's written in Armglish[1].
pgprot_noncached(), on the other hand, provides what the architecture calls
Strongly Ordered or Device-nGnRnE memory. This is intended for mapping MMIO
(i.e. PCI config space) and therefore forbids speculation, preserves access
size, requires strict alignment and also forces write responses to come from
the endpoint.
I think the naming mismatch is historical, but on arm64 we wanted to use the
same names as arm32 so that any drivers using these things directly would get
the same behaviour.
Will
[1]
B2.4.4 Implication of caches for the application programmer
[...]
Data coherency issues
Software can ensure the data coherency of caches in the following ways:
* By not using the caches in situations where coherency issues can arise.
This can be achieved by:
- Using Non-cacheable or, in some cases, Write-Through Cacheable memory.
- Not enabling caches in the system.
* By using cache maintenance instructions to manage the coherency issues
in software.
* By using hardware coherency mechanisms to ensure the coherency of data
accesses to memory for cacheable locations by observers within the
different shareability domains.
^ permalink raw reply
* [PATCH v2 00/44] powerpc/64s/exception: cleanup and macrofiy,
From: Nicholas Piggin @ 2019-08-02 10:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
This series is the combined outstanding series posted previously, plus
a change to a new way to define parameters for interrupt code
generation macros (which is a bit clunky but works better than
alternatives).
This is mostly the end result. There is still a few minor things that
could be done, and possibly we could add a "standard form" macro for
well behaved handlers that don't require any custom code, which blats
out everything (the real and virt vectors, KVM handler, and common
handler stuff) in one line after the definition block. But that's not
really important now.
After this we can start on actually improving the generated code.
Thanks,
Nick
Nicholas Piggin (44):
powerpc/64s/exception: machine check fwnmi remove HV case
powerpc/64s/exception: machine check remove bitrotted comment
powerpc/64s/exception: machine check fix KVM guest test
powerpc/64s/exception: machine check adjust RFI target
powerpc/64s/exception: machine check pseries should always run the
early handler
powerpc/64s/exception: machine check remove machine_check_pSeries_0
branch
powerpc/64s/exception: machine check use correct cfar for late handler
powerpc/64s/powernv: machine check dump SLB contents
powerpc/64s/pseries: machine check convert to use common event code
powerpc/64s/exception: machine check pseries should skip the late
handler for kernel MCEs
powerpc/64s/exception: machine check restructure to reuse common
macros
powerpc/64s/exception: machine check move tramp code
powerpc/64s/exception: simplify machine check early path
powerpc/64s/exception: machine check move unrecoverable handling out
of line
powerpc/64s/exception: untangle early machine check handler branch
powerpc/64s/exception: machine check improve labels and comments
powerpc/64s/exception: Fix DAR load for handle_page_fault error case
powerpc/64s/exception: move head-64.h exception code to
exception-64s.S
powerpc/64s/exception: Add EXC_HV_OR_STD, which selects HSRR if HVMODE
powerpc/64s/exception: Fix performance monitor virt handler
powerpc/64s/exception: remove 0xb00 handler
powerpc/64s/exception: Replace PROLOG macros and EXC helpers with a
gas macro
powerpc/64s/exception: remove EXCEPTION_PROLOG_0/1, rename _2
powerpc/64s/exception: Add the virt variant of the denorm interrupt
handler
powerpc/64s/exception: INT_HANDLER support HDAR/HDSISR and use it in
HDSI
powerpc/64s/exception: Add INT_KVM_HANDLER gas macro
powerpc/64s/exception: KVM_HANDLER reorder arguments to match other
macros
powerpc/64s/exception: Merge EXCEPTION_PROLOG_COMMON_2/3
powerpc/64s/exception: Add INT_COMMON gas macro to generate common
exception code
powerpc/64s/exception: Expand EXCEPTION_COMMON macro into caller
powerpc/64s/exception: Expand EXCEPTION_PROLOG_COMMON_1 and 2 into
caller
powerpc/64s/exception: INT_COMMON add DAR, DSISR, reconcile options
powerpc/64s/exception: move interrupt entry code above the common
handler
powerpc/64s/exception: program check handler do not branch into a
macro
powerpc/64s/exception: Remove pointless KVM handler name bifurcation
powerpc/64s/exception: reduce page fault unnecessary loads
powerpc/64s/exception: Introduce INT_DEFINE parameter block for code
generation
powerpc/64s/exception: Add GEN_COMMON macro that uses INT_DEFINE
parameters
powerpc/64s/exception: Add GEN_KVM macro that uses INT_DEFINE
parameters
powerpc/64s/exception: Expand EXC_COMMON and EXC_COMMON_ASYNC macros
powerpc/64s/exception: Move all interrupt handlers to new style code
gen macros
powerpc/64s/exception: Remove old INT_ENTRY macro
powerpc/64s/exception: Remove old INT_COMMON macro
powerpc/64s/exception: Remove old INT_KVM_HANDLER
arch/powerpc/include/asm/head-64.h | 41 -
arch/powerpc/include/asm/mce.h | 6 +
arch/powerpc/kernel/exceptions-64s.S | 2242 ++++++++++++++----------
arch/powerpc/kernel/mce.c | 40 +-
arch/powerpc/kernel/mce_power.c | 4 +
arch/powerpc/mm/book3s64/hash_utils.c | 4 +-
arch/powerpc/platforms/powernv/setup.c | 9 +
arch/powerpc/platforms/pseries/ras.c | 457 ++---
arch/powerpc/platforms/pseries/setup.c | 24 +-
9 files changed, 1600 insertions(+), 1227 deletions(-)
--
2.22.0
^ permalink raw reply
* [PATCH v2 01/44] powerpc/64s/exception: machine check fwnmi remove HV case
From: Nicholas Piggin @ 2019-08-02 10:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190802105709.27696-1-npiggin@gmail.com>
fwnmi does not trigger in HV mode, so remove always-true feature test.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index eee5bef736c8..f30eb1df7443 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1026,9 +1026,8 @@ TRAMP_REAL_BEGIN(machine_check_pSeries)
.globl machine_check_fwnmi
machine_check_fwnmi:
EXCEPTION_PROLOG_0 PACA_EXMC
-BEGIN_FTR_SECTION
b machine_check_common_early
-END_FTR_SECTION_IFCLR(CPU_FTR_HVMODE)
+
machine_check_pSeries_0:
EXCEPTION_PROLOG_1 EXC_STD, PACA_EXMC, 1, 0x200, 1, 1, 0
/*
--
2.22.0
^ permalink raw reply related
* [PATCH v2 02/44] powerpc/64s/exception: machine check remove bitrotted comment
From: Nicholas Piggin @ 2019-08-02 10:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190802105709.27696-1-npiggin@gmail.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 4 ----
1 file changed, 4 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index f30eb1df7443..6d8d21fa935f 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -933,10 +933,6 @@ EXC_COMMON_BEGIN(system_reset_common)
EXC_REAL_BEGIN(machine_check, 0x200, 0x100)
- /* This is moved out of line as it can be patched by FW, but
- * some code path might still want to branch into the original
- * vector
- */
EXCEPTION_PROLOG_0 PACA_EXMC
BEGIN_FTR_SECTION
b machine_check_common_early
--
2.22.0
^ permalink raw reply related
* [PATCH v2 03/44] powerpc/64s/exception: machine check fix KVM guest test
From: Nicholas Piggin @ 2019-08-02 10:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190802105709.27696-1-npiggin@gmail.com>
The machine_check_handle_early hypervisor guest test is skipped if
!HVMODE or MSR[HV]=0, which is wrong for PR or nested hypervisors
that could be running a guest in this state.
Test HSTATE_IN_GUEST up front and use that to branch out to the KVM
handler, then MSR[PR] alone can test for this kernel's userspace.
This matches all other interrupt handling.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 33 +++++++++++-----------------
1 file changed, 13 insertions(+), 20 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 6d8d21fa935f..e00cffb25517 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1108,11 +1108,8 @@ EXC_COMMON_BEGIN(machine_check_handle_early)
bl machine_check_early
std r3,RESULT(r1) /* Save result */
ld r12,_MSR(r1)
-BEGIN_FTR_SECTION
- b 4f
-END_FTR_SECTION_IFCLR(CPU_FTR_HVMODE)
-#ifdef CONFIG_PPC_P7_NAP
+#ifdef CONFIG_PPC_P7_NAP
/*
* Check if thread was in power saving mode. We come here when any
* of the following is true:
@@ -1128,30 +1125,26 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
#endif
- /*
- * Check if we are coming from hypervisor userspace. If yes then we
- * continue in host kernel in V mode to deliver the MC event.
- */
- rldicl. r11,r12,4,63 /* See if MC hit while in HV mode. */
- beq 5f
-4: andi. r11,r12,MSR_PR /* See if coming from user. */
- bne 9f /* continue in V mode if we are. */
-
-5:
#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
-BEGIN_FTR_SECTION
/*
- * We are coming from kernel context. Check if we are coming from
- * guest. if yes, then we can continue. We will fall through
- * do_kvm_200->kvmppc_interrupt to deliver the MC event to guest.
+ * Check if we are coming from guest. If yes, then run the normal
+ * exception handler which will take the do_kvm_200->kvmppc_interrupt
+ * branch to deliver the MC event to guest.
*/
lbz r11,HSTATE_IN_GUEST(r13)
cmpwi r11,0 /* Check if coming from guest */
bne 9f /* continue if we are. */
-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
#endif
+
+ /*
+ * Check if we are coming from userspace. If yes, then run the normal
+ * exception handler which will deliver the MC event to this kernel.
+ */
+ andi. r11,r12,MSR_PR /* See if coming from user. */
+ bne 9f /* continue in V mode if we are. */
+
/*
- * At this point we are not sure about what context we come from.
+ * At this point we are coming from kernel context.
* Queue up the MCE event and return from the interrupt.
* But before that, check if this is an un-recoverable exception.
* If yes, then stay on emergency stack and panic.
--
2.22.0
^ permalink raw reply related
* [PATCH v2 04/44] powerpc/64s/exception: machine check adjust RFI target
From: Nicholas Piggin @ 2019-08-02 10:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190802105709.27696-1-npiggin@gmail.com>
The host kernel delivery case for powernv does RFI_TO_USER_OR_KERNEL,
but should just use RFI_TO_KERNEL which makes it clear this is not a
user case.
This is not a bug because RFI_TO_USER_OR_KERNEL deals with kernel
returns just fine.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index e00cffb25517..dbd1a8c68636 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1184,7 +1184,7 @@ BEGIN_FTR_SECTION
*/
bl machine_check_queue_event
MACHINE_CHECK_HANDLER_WINDUP
- RFI_TO_USER_OR_KERNEL
+ RFI_TO_KERNEL
FTR_SECTION_ELSE
/*
* pSeries: Return from MC interrupt. Before that stay on emergency
--
2.22.0
^ permalink raw reply related
* [PATCH v2 05/44] powerpc/64s/exception: machine check pseries should always run the early handler
From: Nicholas Piggin @ 2019-08-02 10:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190802105709.27696-1-npiggin@gmail.com>
Now that pseries with fwnmi registered runs the early machine check
handler, there is no good reason to special case the non-fwnmi case
and skip the early handler. Reducing the code and number of paths is
a top priority for asm code, it's better to handle this in C where
possible (and the pseries early handler is a no-op if fwnmi is not
registered).
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 4 ----
1 file changed, 4 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index dbd1a8c68636..8188c4ce4a49 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -934,11 +934,7 @@ EXC_COMMON_BEGIN(system_reset_common)
EXC_REAL_BEGIN(machine_check, 0x200, 0x100)
EXCEPTION_PROLOG_0 PACA_EXMC
-BEGIN_FTR_SECTION
b machine_check_common_early
-FTR_SECTION_ELSE
- b machine_check_pSeries_0
-ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
EXC_REAL_END(machine_check, 0x200, 0x100)
EXC_VIRT_NONE(0x4200, 0x100)
TRAMP_REAL_BEGIN(machine_check_common_early)
--
2.22.0
^ permalink raw reply related
* [PATCH v2 06/44] powerpc/64s/exception: machine check remove machine_check_pSeries_0 branch
From: Nicholas Piggin @ 2019-08-02 10:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190802105709.27696-1-npiggin@gmail.com>
This label has only one caller, so unwind the branch and move it
inline. The location of the comment is adjusted to match similar
one in system reset.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 23 ++++++++++-------------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 8188c4ce4a49..6ec296762720 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1014,20 +1014,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
b 1b
b . /* prevent speculative execution */
-TRAMP_REAL_BEGIN(machine_check_pSeries)
- .globl machine_check_fwnmi
-machine_check_fwnmi:
+#ifdef CONFIG_PPC_PSERIES
+TRAMP_REAL_BEGIN(machine_check_fwnmi)
EXCEPTION_PROLOG_0 PACA_EXMC
b machine_check_common_early
-
-machine_check_pSeries_0:
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXMC, 1, 0x200, 1, 1, 0
- /*
- * MSR_RI is not enabled, because PACA_EXMC is being used, so a
- * nested machine check corrupts it. machine_check_common enables
- * MSR_RI.
- */
- EXCEPTION_PROLOG_2_REAL machine_check_common, EXC_STD, 0
+#endif
TRAMP_KVM_SKIP(PACA_EXMC, 0x200)
@@ -1197,7 +1188,13 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
/* Deliver the machine check to host kernel in V mode. */
MACHINE_CHECK_HANDLER_WINDUP
EXCEPTION_PROLOG_0 PACA_EXMC
- b machine_check_pSeries_0
+ EXCEPTION_PROLOG_1 EXC_STD, PACA_EXMC, 1, 0x200, 1, 1, 0
+ EXCEPTION_PROLOG_2_REAL machine_check_common, EXC_STD, 0
+ /*
+ * MSR_RI is not enabled, because PACA_EXMC is being used, so a
+ * nested machine check corrupts it. machine_check_common enables
+ * MSR_RI.
+ */
EXC_COMMON_BEGIN(unrecover_mce)
/* Invoke machine_check_exception to print MCE event and panic. */
--
2.22.0
^ permalink raw reply related
* [PATCH v2 07/44] powerpc/64s/exception: machine check use correct cfar for late handler
From: Nicholas Piggin @ 2019-08-02 10:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190802105709.27696-1-npiggin@gmail.com>
Bare metal machine checks run an "early" handler in real mode before
running the main handler which reports the event.
The main handler runs exactly as a normal interrupt handler, after the
"windup" which sets registers back as they were at interrupt entry.
CFAR does not get restored by the windup code, so that will be wrong
when the handler is run.
Restore the CFAR to the saved value before running the late handler.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 6ec296762720..16d4881108d5 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1186,6 +1186,10 @@ FTR_SECTION_ELSE
ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
9:
/* Deliver the machine check to host kernel in V mode. */
+BEGIN_FTR_SECTION
+ ld r10,ORIG_GPR3(r1)
+ mtspr SPRN_CFAR,r10
+END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
MACHINE_CHECK_HANDLER_WINDUP
EXCEPTION_PROLOG_0 PACA_EXMC
EXCEPTION_PROLOG_1 EXC_STD, PACA_EXMC, 1, 0x200, 1, 1, 0
--
2.22.0
^ permalink raw reply related
* [PATCH v2 08/44] powerpc/64s/powernv: machine check dump SLB contents
From: Nicholas Piggin @ 2019-08-02 10:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190802105709.27696-1-npiggin@gmail.com>
Re-use the code introduced in pseries to save and dump the contents
of the SLB in the case of an SLB involved machine check exception.
This patch also avoids allocating the SLB save array on pseries radix.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/mce.c | 6 ++++++
arch/powerpc/kernel/mce_power.c | 4 ++++
arch/powerpc/platforms/powernv/setup.c | 9 +++++++++
arch/powerpc/platforms/pseries/setup.c | 24 +++++++++++++-----------
4 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
index b18df633eae9..38b560f92d12 100644
--- a/arch/powerpc/kernel/mce.c
+++ b/arch/powerpc/kernel/mce.c
@@ -486,6 +486,12 @@ void machine_check_print_event_info(struct machine_check_event *evt,
subtype = evt->error_class < ARRAY_SIZE(mc_error_class) ?
mc_error_class[evt->error_class] : "Unknown";
printk("%sMCE: CPU%d: %s\n", level, evt->cpu, subtype);
+
+#ifdef CONFIG_PPC_BOOK3S_64
+ /* Display faulty slb contents for SLB errors. */
+ if (evt->error_type == MCE_ERROR_TYPE_SLB)
+ slb_dump_contents(local_paca->mce_faulty_slbs);
+#endif
}
EXPORT_SYMBOL_GPL(machine_check_print_event_info);
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
index a814d2dfb5b0..0ea47bc6fca0 100644
--- a/arch/powerpc/kernel/mce_power.c
+++ b/arch/powerpc/kernel/mce_power.c
@@ -397,6 +397,8 @@ static int mce_handle_ierror(struct pt_regs *regs,
/* attempt to correct the error */
switch (table[i].error_type) {
case MCE_ERROR_TYPE_SLB:
+ if (local_paca->in_mce == 1)
+ slb_save_contents(local_paca->mce_faulty_slbs);
handled = mce_flush(MCE_FLUSH_SLB);
break;
case MCE_ERROR_TYPE_ERAT:
@@ -482,6 +484,8 @@ static int mce_handle_derror(struct pt_regs *regs,
/* attempt to correct the error */
switch (table[i].error_type) {
case MCE_ERROR_TYPE_SLB:
+ if (local_paca->in_mce == 1)
+ slb_save_contents(local_paca->mce_faulty_slbs);
if (mce_flush(MCE_FLUSH_SLB))
handled = 1;
break;
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index a5e52f9eed3c..83498604d322 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -24,6 +24,7 @@
#include <linux/bug.h>
#include <linux/pci.h>
#include <linux/cpufreq.h>
+#include <linux/memblock.h>
#include <asm/machdep.h>
#include <asm/firmware.h>
@@ -166,6 +167,14 @@ static void __init pnv_init(void)
else
#endif
add_preferred_console("hvc", 0, NULL);
+
+ if (!radix_enabled()) {
+ int i;
+
+ /* Allocate per cpu area to save old slb contents during MCE */
+ for_each_possible_cpu(i)
+ paca_ptrs[i]->mce_faulty_slbs = memblock_alloc_node(mmu_slb_size, __alignof__(*paca_ptrs[i]->mce_faulty_slbs), cpu_to_node(i));
+ }
}
static void __init pnv_init_IRQ(void)
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index f5940cc71c37..5546c9562731 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -141,17 +141,19 @@ static void __init fwnmi_init(void)
}
#ifdef CONFIG_PPC_BOOK3S_64
- /* Allocate per cpu slb area to save old slb contents during MCE */
- size = sizeof(struct slb_entry) * mmu_slb_size * nr_cpus;
- slb_ptr = memblock_alloc_try_nid_raw(size, sizeof(struct slb_entry),
- MEMBLOCK_LOW_LIMIT, ppc64_rma_size,
- NUMA_NO_NODE);
- if (!slb_ptr)
- panic("Failed to allocate %zu bytes below %pa for slb area\n",
- size, &ppc64_rma_size);
-
- for_each_possible_cpu(i)
- paca_ptrs[i]->mce_faulty_slbs = slb_ptr + (mmu_slb_size * i);
+ if (!radix_enabled()) {
+ /* Allocate per cpu area to save old slb contents during MCE */
+ size = sizeof(struct slb_entry) * mmu_slb_size * nr_cpus;
+ slb_ptr = memblock_alloc_try_nid_raw(size,
+ sizeof(struct slb_entry), MEMBLOCK_LOW_LIMIT,
+ ppc64_rma_size, NUMA_NO_NODE);
+ if (!slb_ptr)
+ panic("Failed to allocate %zu bytes below %pa for slb area\n",
+ size, &ppc64_rma_size);
+
+ for_each_possible_cpu(i)
+ paca_ptrs[i]->mce_faulty_slbs = slb_ptr + (mmu_slb_size * i);
+ }
#endif
}
--
2.22.0
^ permalink raw reply related
* [PATCH v2 09/44] powerpc/64s/pseries: machine check convert to use common event code
From: Nicholas Piggin @ 2019-08-02 10:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190802105709.27696-1-npiggin@gmail.com>
The common machine_check_event data structures and queues are mostly
platform independent, with powernv decoding SRR1/DSISR/etc., into
machine_check_event objects.
This patch converts pseries to use this infrastructure by decoding
fwnmi/rtas data into machine_check_event objects.
This allows queueing to be used by a subsequent change to delay the
virtual mode handling of machine checks that occur in kernel space
where it is unsafe to switch immediately to virtual mode, similarly
to powernv.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/mce.h | 6 +
arch/powerpc/kernel/mce.c | 34 +-
arch/powerpc/platforms/pseries/ras.c | 457 +++++++++++----------------
3 files changed, 230 insertions(+), 267 deletions(-)
diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h
index a4c6a74ad2fb..6f56b2d350b2 100644
--- a/arch/powerpc/include/asm/mce.h
+++ b/arch/powerpc/include/asm/mce.h
@@ -30,6 +30,10 @@ enum MCE_Disposition {
enum MCE_Initiator {
MCE_INITIATOR_UNKNOWN = 0,
MCE_INITIATOR_CPU = 1,
+ MCE_INITIATOR_PCI = 2,
+ MCE_INITIATOR_ISA = 3,
+ MCE_INITIATOR_MEMORY= 4,
+ MCE_INITIATOR_POWERMGM = 5,
};
enum MCE_ErrorType {
@@ -41,6 +45,8 @@ enum MCE_ErrorType {
MCE_ERROR_TYPE_USER = 5,
MCE_ERROR_TYPE_RA = 6,
MCE_ERROR_TYPE_LINK = 7,
+ MCE_ERROR_TYPE_DCACHE = 8,
+ MCE_ERROR_TYPE_ICACHE = 9,
};
enum MCE_ErrorClass {
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
index 38b560f92d12..5b4f766a68e9 100644
--- a/arch/powerpc/kernel/mce.c
+++ b/arch/powerpc/kernel/mce.c
@@ -300,7 +300,7 @@ static void machine_check_process_queued_event(struct irq_work *work)
void machine_check_print_event_info(struct machine_check_event *evt,
bool user_mode, bool in_guest)
{
- const char *level, *sevstr, *subtype, *err_type;
+ const char *level, *sevstr, *subtype, *err_type, *initiator;
uint64_t ea = 0, pa = 0;
int n = 0;
char dar_str[50];
@@ -385,6 +385,28 @@ void machine_check_print_event_info(struct machine_check_event *evt,
break;
}
+ switch(evt->initiator) {
+ case MCE_INITIATOR_CPU:
+ initiator = "CPU";
+ break;
+ case MCE_INITIATOR_PCI:
+ initiator = "PCI";
+ break;
+ case MCE_INITIATOR_ISA:
+ initiator = "ISA";
+ break;
+ case MCE_INITIATOR_MEMORY:
+ initiator = "Memory";
+ break;
+ case MCE_INITIATOR_POWERMGM:
+ initiator = "Power Management";
+ break;
+ case MCE_INITIATOR_UNKNOWN:
+ default:
+ initiator = "Unknown";
+ break;
+ }
+
switch (evt->error_type) {
case MCE_ERROR_TYPE_UE:
err_type = "UE";
@@ -451,6 +473,14 @@ void machine_check_print_event_info(struct machine_check_event *evt,
if (evt->u.link_error.effective_address_provided)
ea = evt->u.link_error.effective_address;
break;
+ case MCE_ERROR_TYPE_DCACHE:
+ err_type = "D-Cache";
+ subtype = "Unknown";
+ break;
+ case MCE_ERROR_TYPE_ICACHE:
+ err_type = "I-Cache";
+ subtype = "Unknown";
+ break;
default:
case MCE_ERROR_TYPE_UNKNOWN:
err_type = "Unknown";
@@ -483,6 +513,8 @@ void machine_check_print_event_info(struct machine_check_event *evt,
level, evt->cpu, evt->srr0, (void *)evt->srr0, pa_str);
}
+ printk("%sMCE: CPU%d: Initiator %s\n", level, evt->cpu, initiator);
+
subtype = evt->error_class < ARRAY_SIZE(mc_error_class) ?
mc_error_class[evt->error_class] : "Unknown";
printk("%sMCE: CPU%d: %s\n", level, evt->cpu, subtype);
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index f16fdd0f71f7..e03c3389692e 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -76,6 +76,7 @@ struct pseries_mc_errorlog {
#define MC_ERROR_TYPE_UE 0x00
#define MC_ERROR_TYPE_SLB 0x01
#define MC_ERROR_TYPE_ERAT 0x02
+#define MC_ERROR_TYPE_UNKNOWN 0x03
#define MC_ERROR_TYPE_TLB 0x04
#define MC_ERROR_TYPE_D_CACHE 0x05
#define MC_ERROR_TYPE_I_CACHE 0x07
@@ -87,6 +88,9 @@ struct pseries_mc_errorlog {
#define MC_ERROR_UE_LOAD_STORE 3
#define MC_ERROR_UE_PAGE_TABLE_WALK_LOAD_STORE 4
+#define UE_EFFECTIVE_ADDR_PROVIDED 0x40
+#define UE_LOGICAL_ADDR_PROVIDED 0x20
+
#define MC_ERROR_SLB_PARITY 0
#define MC_ERROR_SLB_MULTIHIT 1
#define MC_ERROR_SLB_INDETERMINATE 2
@@ -113,27 +117,6 @@ static inline u8 rtas_mc_error_sub_type(const struct pseries_mc_errorlog *mlog)
}
}
-static
-inline u64 rtas_mc_get_effective_addr(const struct pseries_mc_errorlog *mlog)
-{
- __be64 addr = 0;
-
- switch (mlog->error_type) {
- case MC_ERROR_TYPE_UE:
- if (mlog->sub_err_type & 0x40)
- addr = mlog->effective_address;
- break;
- case MC_ERROR_TYPE_SLB:
- case MC_ERROR_TYPE_ERAT:
- case MC_ERROR_TYPE_TLB:
- if (mlog->sub_err_type & 0x80)
- addr = mlog->effective_address;
- default:
- break;
- }
- return be64_to_cpu(addr);
-}
-
/*
* Enable the hotplug interrupt late because processing them may touch other
* devices or systems (e.g. hugepages) that have not been initialized at the
@@ -511,160 +494,162 @@ int pSeries_system_reset_exception(struct pt_regs *regs)
return 0; /* need to perform reset */
}
-#define VAL_TO_STRING(ar, val) \
- (((val) < ARRAY_SIZE(ar)) ? ar[(val)] : "Unknown")
-static void pseries_print_mce_info(struct pt_regs *regs,
- struct rtas_error_log *errp)
+static int mce_handle_error(struct pt_regs *regs, struct rtas_error_log *errp)
{
- const char *level, *sevstr;
+ struct mce_error_info mce_err = { 0 };
+ unsigned long eaddr = 0, paddr = 0;
struct pseries_errorlog *pseries_log;
struct pseries_mc_errorlog *mce_log;
- u8 error_type, err_sub_type;
- u64 addr;
- u8 initiator = rtas_error_initiator(errp);
int disposition = rtas_error_disposition(errp);
+ int initiator = rtas_error_initiator(errp);
+ int severity = rtas_error_severity(errp);
+ u8 error_type, err_sub_type;
- static const char * const initiators[] = {
- [0] = "Unknown",
- [1] = "CPU",
- [2] = "PCI",
- [3] = "ISA",
- [4] = "Memory",
- [5] = "Power Mgmt",
- };
- static const char * const mc_err_types[] = {
- [0] = "UE",
- [1] = "SLB",
- [2] = "ERAT",
- [3] = "Unknown",
- [4] = "TLB",
- [5] = "D-Cache",
- [6] = "Unknown",
- [7] = "I-Cache",
- };
- static const char * const mc_ue_types[] = {
- [0] = "Indeterminate",
- [1] = "Instruction fetch",
- [2] = "Page table walk ifetch",
- [3] = "Load/Store",
- [4] = "Page table walk Load/Store",
- };
-
- /* SLB sub errors valid values are 0x0, 0x1, 0x2 */
- static const char * const mc_slb_types[] = {
- [0] = "Parity",
- [1] = "Multihit",
- [2] = "Indeterminate",
- };
-
- /* TLB and ERAT sub errors valid values are 0x1, 0x2, 0x3 */
- static const char * const mc_soft_types[] = {
- [0] = "Unknown",
- [1] = "Parity",
- [2] = "Multihit",
- [3] = "Indeterminate",
- };
-
- if (!rtas_error_extended(errp)) {
- pr_err("Machine check interrupt: Missing extended error log\n");
- return;
- }
+ if (initiator == RTAS_INITIATOR_UNKNOWN)
+ mce_err.initiator = MCE_INITIATOR_UNKNOWN;
+ else if (initiator == RTAS_INITIATOR_CPU)
+ mce_err.initiator = MCE_INITIATOR_CPU;
+ else if (initiator == RTAS_INITIATOR_PCI)
+ mce_err.initiator = MCE_INITIATOR_PCI;
+ else if (initiator == RTAS_INITIATOR_ISA)
+ mce_err.initiator = MCE_INITIATOR_ISA;
+ else if (initiator == RTAS_INITIATOR_MEMORY)
+ mce_err.initiator = MCE_INITIATOR_MEMORY;
+ else if (initiator == RTAS_INITIATOR_POWERMGM)
+ mce_err.initiator = MCE_INITIATOR_POWERMGM;
+ else
+ mce_err.initiator = MCE_INITIATOR_UNKNOWN;
+
+ if (severity == RTAS_SEVERITY_NO_ERROR)
+ mce_err.severity = MCE_SEV_NO_ERROR;
+ else if (severity == RTAS_SEVERITY_EVENT)
+ mce_err.severity = MCE_SEV_WARNING;
+ else if (severity == RTAS_SEVERITY_WARNING)
+ mce_err.severity = MCE_SEV_WARNING;
+ else if (severity == RTAS_SEVERITY_ERROR_SYNC)
+ mce_err.severity = MCE_SEV_SEVERE;
+ else if (severity == RTAS_SEVERITY_ERROR)
+ mce_err.severity = MCE_SEV_SEVERE;
+ else if (severity == RTAS_SEVERITY_FATAL)
+ mce_err.severity = MCE_SEV_FATAL;
+ else
+ mce_err.severity = MCE_SEV_FATAL;
+
+ if (severity <= RTAS_SEVERITY_ERROR_SYNC)
+ mce_err.sync_error = true;
+ else
+ mce_err.sync_error = false;
+
+ mce_err.error_type = MCE_ERROR_TYPE_UNKNOWN;
+ mce_err.error_class = MCE_ECLASS_UNKNOWN;
+
+ if (!rtas_error_extended(errp))
+ goto out;
pseries_log = get_pseries_errorlog(errp, PSERIES_ELOG_SECT_ID_MCE);
if (pseries_log == NULL)
- return;
+ goto out;
mce_log = (struct pseries_mc_errorlog *)pseries_log->data;
-
error_type = mce_log->error_type;
err_sub_type = rtas_mc_error_sub_type(mce_log);
- switch (rtas_error_severity(errp)) {
- case RTAS_SEVERITY_NO_ERROR:
- level = KERN_INFO;
- sevstr = "Harmless";
- break;
- case RTAS_SEVERITY_WARNING:
- level = KERN_WARNING;
- sevstr = "";
- break;
- case RTAS_SEVERITY_ERROR:
- case RTAS_SEVERITY_ERROR_SYNC:
- level = KERN_ERR;
- sevstr = "Severe";
- break;
- case RTAS_SEVERITY_FATAL:
- default:
- level = KERN_ERR;
- sevstr = "Fatal";
- break;
- }
+ switch (mce_log->error_type) {
+ case MC_ERROR_TYPE_UE:
+ mce_err.error_type = MCE_ERROR_TYPE_UE;
+ switch (err_sub_type) {
+ case MC_ERROR_UE_IFETCH:
+ mce_err.u.ue_error_type = MCE_UE_ERROR_IFETCH;
+ case MC_ERROR_UE_PAGE_TABLE_WALK_IFETCH:
+ mce_err.u.ue_error_type = MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH;
+ case MC_ERROR_UE_LOAD_STORE:
+ mce_err.u.ue_error_type = MCE_UE_ERROR_LOAD_STORE;
+ case MC_ERROR_UE_PAGE_TABLE_WALK_LOAD_STORE:
+ mce_err.u.ue_error_type = MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE;
+ case MC_ERROR_UE_INDETERMINATE:
+ default:
+ mce_err.u.ue_error_type = MCE_UE_ERROR_INDETERMINATE;
+ break;
+ }
+ if (mce_log->sub_err_type & UE_EFFECTIVE_ADDR_PROVIDED)
+ eaddr = be64_to_cpu(mce_log->effective_address);
-#ifdef CONFIG_PPC_BOOK3S_64
- /* Display faulty slb contents for SLB errors. */
- if (error_type == MC_ERROR_TYPE_SLB)
- slb_dump_contents(local_paca->mce_faulty_slbs);
-#endif
+ if (mce_log->sub_err_type & UE_LOGICAL_ADDR_PROVIDED) {
+ paddr = be64_to_cpu(mce_log->logical_address);
+ } else if (mce_log->sub_err_type & UE_EFFECTIVE_ADDR_PROVIDED) {
+ unsigned long pfn;
+
+ pfn = addr_to_pfn(regs, eaddr);
+ if (pfn != ULONG_MAX)
+ paddr = pfn << PAGE_SHIFT;
+ }
- printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
- disposition == RTAS_DISP_FULLY_RECOVERED ?
- "Recovered" : "Not recovered");
- if (user_mode(regs)) {
- printk("%s NIP: [%016lx] PID: %d Comm: %s\n", level,
- regs->nip, current->pid, current->comm);
- } else {
- printk("%s NIP [%016lx]: %pS\n", level, regs->nip,
- (void *)regs->nip);
- }
- printk("%s Initiator: %s\n", level,
- VAL_TO_STRING(initiators, initiator));
- switch (error_type) {
- case MC_ERROR_TYPE_UE:
- printk("%s Error type: %s [%s]\n", level,
- VAL_TO_STRING(mc_err_types, error_type),
- VAL_TO_STRING(mc_ue_types, err_sub_type));
break;
case MC_ERROR_TYPE_SLB:
- printk("%s Error type: %s [%s]\n", level,
- VAL_TO_STRING(mc_err_types, error_type),
- VAL_TO_STRING(mc_slb_types, err_sub_type));
+ mce_err.error_type = MCE_ERROR_TYPE_SLB;
+ switch (err_sub_type) {
+ case MC_ERROR_SLB_PARITY:
+ mce_err.u.slb_error_type = MCE_SLB_ERROR_PARITY;
+ break;
+ case MC_ERROR_SLB_MULTIHIT:
+ mce_err.u.slb_error_type = MCE_SLB_ERROR_MULTIHIT;
+ break;
+ case MC_ERROR_SLB_INDETERMINATE:
+ default:
+ mce_err.u.slb_error_type = MCE_SLB_ERROR_INDETERMINATE;
+ break;
+ }
+ if (mce_log->sub_err_type & 0x80)
+ eaddr = be64_to_cpu(mce_log->effective_address);
break;
case MC_ERROR_TYPE_ERAT:
+ mce_err.error_type = MCE_ERROR_TYPE_ERAT;
+ switch (err_sub_type) {
+ case MC_ERROR_ERAT_PARITY:
+ mce_err.u.erat_error_type = MCE_ERAT_ERROR_PARITY;
+ break;
+ case MC_ERROR_ERAT_MULTIHIT:
+ mce_err.u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT;
+ break;
+ case MC_ERROR_ERAT_INDETERMINATE:
+ default:
+ mce_err.u.erat_error_type = MCE_ERAT_ERROR_INDETERMINATE;
+ break;
+ }
+ if (mce_log->sub_err_type & 0x80)
+ eaddr = be64_to_cpu(mce_log->effective_address);
+ break;
case MC_ERROR_TYPE_TLB:
- printk("%s Error type: %s [%s]\n", level,
- VAL_TO_STRING(mc_err_types, error_type),
- VAL_TO_STRING(mc_soft_types, err_sub_type));
+ mce_err.error_type = MCE_ERROR_TYPE_TLB;
+ switch (err_sub_type) {
+ case MC_ERROR_TLB_PARITY:
+ mce_err.u.tlb_error_type = MCE_TLB_ERROR_PARITY;
+ break;
+ case MC_ERROR_TLB_MULTIHIT:
+ mce_err.u.tlb_error_type = MCE_TLB_ERROR_MULTIHIT;
+ break;
+ case MC_ERROR_TLB_INDETERMINATE:
+ default:
+ mce_err.u.tlb_error_type = MCE_TLB_ERROR_INDETERMINATE;
+ break;
+ }
+ if (mce_log->sub_err_type & 0x80)
+ eaddr = be64_to_cpu(mce_log->effective_address);
break;
+ case MC_ERROR_TYPE_D_CACHE:
+ mce_err.error_type = MCE_ERROR_TYPE_DCACHE;
+ break;
+ case MC_ERROR_TYPE_I_CACHE:
+ mce_err.error_type = MCE_ERROR_TYPE_DCACHE;
+ break;
+ case MC_ERROR_TYPE_UNKNOWN:
default:
- printk("%s Error type: %s\n", level,
- VAL_TO_STRING(mc_err_types, error_type));
+ mce_err.error_type = MCE_ERROR_TYPE_UNKNOWN;
break;
}
- addr = rtas_mc_get_effective_addr(mce_log);
- if (addr)
- printk("%s Effective address: %016llx\n", level, addr);
-}
-
-static int mce_handle_error(struct rtas_error_log *errp)
-{
- struct pseries_errorlog *pseries_log;
- struct pseries_mc_errorlog *mce_log;
- int disposition = rtas_error_disposition(errp);
- u8 error_type;
-
- if (!rtas_error_extended(errp))
- goto out;
-
- pseries_log = get_pseries_errorlog(errp, PSERIES_ELOG_SECT_ID_MCE);
- if (pseries_log == NULL)
- goto out;
-
- mce_log = (struct pseries_mc_errorlog *)pseries_log->data;
- error_type = mce_log->error_type;
-
#ifdef CONFIG_PPC_BOOK3S_64
if (disposition == RTAS_DISP_NOT_RECOVERED) {
switch (error_type) {
@@ -682,98 +667,24 @@ static int mce_handle_error(struct rtas_error_log *errp)
slb_save_contents(local_paca->mce_faulty_slbs);
flush_and_reload_slb();
disposition = RTAS_DISP_FULLY_RECOVERED;
- rtas_set_disposition_recovered(errp);
break;
default:
break;
}
+ } else if (disposition == RTAS_DISP_LIMITED_RECOVERY) {
+ /* Platform corrected itself but could be degraded */
+ printk(KERN_ERR "MCE: limited recovery, system may "
+ "be degraded\n");
+ disposition = RTAS_DISP_FULLY_RECOVERED;
}
#endif
out:
- return disposition;
-}
-
-#ifdef CONFIG_MEMORY_FAILURE
-
-static DEFINE_PER_CPU(int, rtas_ue_count);
-static DEFINE_PER_CPU(unsigned long, rtas_ue_paddr[MAX_MC_EVT]);
-
-#define UE_EFFECTIVE_ADDR_PROVIDED 0x40
-#define UE_LOGICAL_ADDR_PROVIDED 0x20
-
-
-static void pseries_hwpoison_work_fn(struct work_struct *work)
-{
- unsigned long paddr;
- int index;
-
- while (__this_cpu_read(rtas_ue_count) > 0) {
- index = __this_cpu_read(rtas_ue_count) - 1;
- paddr = __this_cpu_read(rtas_ue_paddr[index]);
- memory_failure(paddr >> PAGE_SHIFT, 0);
- __this_cpu_dec(rtas_ue_count);
- }
-}
+ save_mce_event(regs, disposition == RTAS_DISP_FULLY_RECOVERED,
+ &mce_err, regs->nip, eaddr, paddr);
-static DECLARE_WORK(hwpoison_work, pseries_hwpoison_work_fn);
-
-static void queue_ue_paddr(unsigned long paddr)
-{
- int index;
-
- index = __this_cpu_inc_return(rtas_ue_count) - 1;
- if (index >= MAX_MC_EVT) {
- __this_cpu_dec(rtas_ue_count);
- return;
- }
- this_cpu_write(rtas_ue_paddr[index], paddr);
- schedule_work(&hwpoison_work);
-}
-
-static void pseries_do_memory_failure(struct pt_regs *regs,
- struct pseries_mc_errorlog *mce_log)
-{
- unsigned long paddr;
-
- if (mce_log->sub_err_type & UE_LOGICAL_ADDR_PROVIDED) {
- paddr = be64_to_cpu(mce_log->logical_address);
- } else if (mce_log->sub_err_type & UE_EFFECTIVE_ADDR_PROVIDED) {
- unsigned long pfn;
-
- pfn = addr_to_pfn(regs,
- be64_to_cpu(mce_log->effective_address));
- if (pfn == ULONG_MAX)
- return;
- paddr = pfn << PAGE_SHIFT;
- } else {
- return;
- }
- queue_ue_paddr(paddr);
-}
-
-static void pseries_process_ue(struct pt_regs *regs,
- struct rtas_error_log *errp)
-{
- struct pseries_errorlog *pseries_log;
- struct pseries_mc_errorlog *mce_log;
-
- if (!rtas_error_extended(errp))
- return;
-
- pseries_log = get_pseries_errorlog(errp, PSERIES_ELOG_SECT_ID_MCE);
- if (!pseries_log)
- return;
-
- mce_log = (struct pseries_mc_errorlog *)pseries_log->data;
-
- if (mce_log->error_type == MC_ERROR_TYPE_UE)
- pseries_do_memory_failure(regs, mce_log);
+ return disposition;
}
-#else
-static inline void pseries_process_ue(struct pt_regs *regs,
- struct rtas_error_log *errp) { }
-#endif /*CONFIG_MEMORY_FAILURE */
/*
* Process MCE rtas errlog event.
@@ -795,49 +706,51 @@ static void mce_process_errlog_event(struct irq_work *work)
* Return 1 if corrected (or delivered a signal).
* Return 0 if there is nothing we can do.
*/
-static int recover_mce(struct pt_regs *regs, struct rtas_error_log *err)
+static int recover_mce(struct pt_regs *regs, struct machine_check_event *evt)
{
int recovered = 0;
- int disposition = rtas_error_disposition(err);
-
- pseries_print_mce_info(regs, err);
if (!(regs->msr & MSR_RI)) {
/* If MSR_RI isn't set, we cannot recover */
pr_err("Machine check interrupt unrecoverable: MSR(RI=0)\n");
recovered = 0;
-
- } else if (disposition == RTAS_DISP_FULLY_RECOVERED) {
+ } else if (evt->disposition == MCE_DISPOSITION_RECOVERED) {
/* Platform corrected itself */
recovered = 1;
+ } else if (evt->severity == MCE_SEV_FATAL) {
+ /* Fatal machine check */
+ pr_err("Machine check interrupt is fatal\n");
+ recovered = 0;
+ }
- } else if (disposition == RTAS_DISP_LIMITED_RECOVERY) {
- /* Platform corrected itself but could be degraded */
- printk(KERN_ERR "MCE: limited recovery, system may "
- "be degraded\n");
- recovered = 1;
-
- } else if (user_mode(regs) && !is_global_init(current) &&
- rtas_error_severity(err) == RTAS_SEVERITY_ERROR_SYNC) {
-
+ if (!recovered && evt->sync_error) {
/*
- * If we received a synchronous error when in userspace
- * kill the task. Firmware may report details of the fail
- * asynchronously, so we can't rely on the target and type
- * fields being valid here.
+ * Try to kill processes if we get a synchronous machine check
+ * (e.g., one caused by execution of this instruction). This
+ * will devolve into a panic if we try to kill init or are in
+ * an interrupt etc.
+ *
+ * TODO: Queue up this address for hwpoisioning later.
+ * TODO: This is not quite right for d-side machine
+ * checks ->nip is not necessarily the important
+ * address.
*/
- printk(KERN_ERR "MCE: uncorrectable error, killing task "
- "%s:%d\n", current->comm, current->pid);
-
- _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
- recovered = 1;
+ if ((user_mode(regs))) {
+ _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
+ recovered = 1;
+ } else if (die_will_crash()) {
+ /*
+ * die() would kill the kernel, so better to go via
+ * the platform reboot code that will log the
+ * machine check.
+ */
+ recovered = 0;
+ } else {
+ die("Machine check", regs, SIGBUS);
+ recovered = 1;
+ }
}
- pseries_process_ue(regs, err);
-
- /* Queue irq work to log this rtas event later. */
- irq_work_queue(&mce_errlog_process_work);
-
return recovered;
}
@@ -853,14 +766,21 @@ static int recover_mce(struct pt_regs *regs, struct rtas_error_log *err)
*/
int pSeries_machine_check_exception(struct pt_regs *regs)
{
- struct rtas_error_log *errp;
+ struct machine_check_event evt;
- if (fwnmi_active) {
- fwnmi_release_errinfo();
- errp = fwnmi_get_errlog();
- if (errp && recover_mce(regs, errp))
- return 1;
+ if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
+ return 0;
+
+ /* Print things out */
+ if (evt.version != MCE_V1) {
+ pr_err("Machine Check Exception, Unknown event version %d !\n",
+ evt.version);
+ return 0;
}
+ machine_check_print_event_info(&evt, user_mode(regs), false);
+
+ if (recover_mce(regs, &evt))
+ return 1;
return 0;
}
@@ -877,7 +797,12 @@ long pseries_machine_check_realmode(struct pt_regs *regs)
* to panic. Hence we will call it as soon as we go into
* virtual mode.
*/
- disposition = mce_handle_error(errp);
+ disposition = mce_handle_error(regs, errp);
+ fwnmi_release_errinfo();
+
+ /* Queue irq work to log this rtas event later. */
+ irq_work_queue(&mce_errlog_process_work);
+
if (disposition == RTAS_DISP_FULLY_RECOVERED)
return 1;
}
--
2.22.0
^ permalink raw reply related
* [PATCH v2 10/44] powerpc/64s/exception: machine check pseries should skip the late handler for kernel MCEs
From: Nicholas Piggin @ 2019-08-02 10:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190802105709.27696-1-npiggin@gmail.com>
The powernv machine check handler copes with taking a MCE from one of
three contexts, guest, kernel, and user. In each case the early
handler runs first on a special stack, then:
- The guest case branches to the KVM interrupt handler (via standard
interrupt macros).
- The user case will run the "late" handler which is like a normal
interrupt that runs in virtual mode and uses the regular kernel
stack.
- The kernel case queues the event and schedules it for processing
with irq work.
The last case is important, it must not enable virtual memory because
the MMU state may not be set up to deal with that (e.g., SLB might be
clear), it must not use the regular kernel stack for similar reasons
(e.g., might be in OPAL with OPAL stack in r1), and the kernel does
not expect anything to touch its stack if interrupts are disabled.
The pseries handler does not do this queueing, but instead it always
runs the late handler for host MCEs, which has some of the same
problems.
Now that pseries is using machine_check_events, change it to do the
same as powernv and queue events for kernel MCEs.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 22 ++--------------------
1 file changed, 2 insertions(+), 20 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 16d4881108d5..b83379cb6d23 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1163,7 +1163,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
cmpdi r3,0 /* see if we handled MCE successfully */
beq 1b /* if !handled then panic */
-BEGIN_FTR_SECTION
+
/*
* Return from MC interrupt.
* Queue up the MCE event so that we can log it later, while
@@ -1172,18 +1172,7 @@ BEGIN_FTR_SECTION
bl machine_check_queue_event
MACHINE_CHECK_HANDLER_WINDUP
RFI_TO_KERNEL
-FTR_SECTION_ELSE
- /*
- * pSeries: Return from MC interrupt. Before that stay on emergency
- * stack and call machine_check_exception to log the MCE event.
- */
- LOAD_HANDLER(r10,mce_return)
- mtspr SPRN_SRR0,r10
- ld r10,PACAKMSR(r13)
- mtspr SPRN_SRR1,r10
- RFI_TO_KERNEL
- b .
-ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
+
9:
/* Deliver the machine check to host kernel in V mode. */
BEGIN_FTR_SECTION
@@ -1212,13 +1201,6 @@ EXC_COMMON_BEGIN(unrecover_mce)
bl unrecoverable_exception
b 1b
-EXC_COMMON_BEGIN(mce_return)
- /* Invoke machine_check_exception to print MCE event and return. */
- addi r3,r1,STACK_FRAME_OVERHEAD
- bl machine_check_exception
- MACHINE_CHECK_HANDLER_WINDUP
- RFI_TO_KERNEL
- b .
EXC_REAL_BEGIN(data_access, 0x300, 0x80)
EXCEPTION_PROLOG_0 PACA_EXGEN
--
2.22.0
^ permalink raw reply related
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