* [PATCH RFC PKS/PMEM 01/58] x86/pks: Add a global pkrs option
From: ira.weiny @ 2020-10-09 19:49 UTC (permalink / raw)
To: Andrew Morton, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Andy Lutomirski, Peter Zijlstra
Cc: linux-aio, linux-efi, kvm, linux-doc, linux-mmc, Dave Hansen,
dri-devel, linux-mm, target-devel, linux-mtd, linux-kselftest,
samba-technical, Ira Weiny, ceph-devel, drbd-dev, devel,
linux-cifs, linux-nilfs, linux-scsi, linux-nvdimm, linux-rdma,
x86, amd-gfx, linux-afs, cluster-devel, linux-cachefs,
intel-wired-lan, xen-devel, linux-ext4, Fenghua Yu, linux-um,
intel-gfx, ecryptfs, linux-erofs, reiserfs-devel, linux-block,
linux-bcache, Dan Williams, io-uring, linux-nfs, linux-ntfs-dev,
netdev, kexec, linux-kernel, linux-f2fs-devel, linux-fsdevel, bpf,
linuxppc-dev, linux-btrfs
In-Reply-To: <20201009195033.3208459-1-ira.weiny@intel.com>
From: Ira Weiny <ira.weiny@intel.com>
Some users, such as kmap(), sometimes requires PKS to be global.
However, updating all CPUs, and worse yet all threads is expensive.
Introduce a global PKRS state which is checked at critical times to
allow the state to enable access when global PKS is required. To
accomplish this with minimal locking; the code is carefully designed
with the following key concepts.
1) Borrow the idea of lazy TLB invalidations from the fault handler
code. When enabling PKS access we anticipate that other threads are
not yet running. However, if they are we catch the fault and clean
up the MSR value.
2) When disabling PKS access we force all MSR values across all CPU's.
This is required to block access as soon as possible.[1] However, it
is key that we never attempt to update the per-task PKS values
directly. See next point.
3) Per-task PKS values never get updated with global PKS values. This
is key to prevent locking requirements and a nearly intractable
problem of trying to update every task in the system. Here are a few
key points.
3a) The MSR value can be updated with the global PKS value if that
global value happened to change while the task was running.
3b) If the task was sleeping while the global PKS was updated then
the global value is added in when task's are scheduled.
3c) If the global PKS value restricts access the MSR is updated as
soon as possible[1] and the thread value is not updated which ensures
the thread does not retain the elevated privileges after a context
switch.
4) Follow on patches must be careful to preserve the separation of the
thread PKRS value and the MSR value.
5) Access Disable on any individual pkey is turned into (Access Disable
| Write Disable) to facilitate faster integration of the global value
into the thread local MSR through a simple '&' operation. Doing
otherwise would result in complicated individual bit manipulation for
each pkey.
[1] There is a race condition which is ignored which is required for
performance issues. This potentially allows access to a thread until
the end of it's time slice. After the context switch the global value
will be restored.
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
---
Documentation/core-api/protection-keys.rst | 11 +-
arch/x86/entry/common.c | 7 +
arch/x86/include/asm/pkeys.h | 6 +-
arch/x86/include/asm/pkeys_common.h | 8 +-
arch/x86/kernel/process.c | 74 +++++++-
arch/x86/mm/fault.c | 189 ++++++++++++++++-----
arch/x86/mm/pkeys.c | 88 ++++++++--
include/linux/pkeys.h | 6 +-
lib/pks/pks_test.c | 16 +-
9 files changed, 329 insertions(+), 76 deletions(-)
diff --git a/Documentation/core-api/protection-keys.rst b/Documentation/core-api/protection-keys.rst
index c60366921d60..9e8a98653e13 100644
--- a/Documentation/core-api/protection-keys.rst
+++ b/Documentation/core-api/protection-keys.rst
@@ -121,9 +121,9 @@ mapping adds that mapping to the protection domain.
int pks_key_alloc(const char * const pkey_user);
#define PAGE_KERNEL_PKEY(pkey)
#define _PAGE_KEY(pkey)
- void pks_mknoaccess(int pkey);
- void pks_mkread(int pkey);
- void pks_mkrdwr(int pkey);
+ void pks_mknoaccess(int pkey, bool global);
+ void pks_mkread(int pkey, bool global);
+ void pks_mkrdwr(int pkey, bool global);
void pks_key_free(int pkey);
pks_key_alloc() allocates keys dynamically to allow better use of the limited
@@ -141,7 +141,10 @@ _PAGE_KEY().
The pks_mk*() family of calls allows kernel users the ability to change the
protections for the domain identified by the pkey specified. 3 states are
available pks_mknoaccess(), pks_mkread(), and pks_mkrdwr() which set the access
-to none, read, and read/write respectively.
+to none, read, and read/write respectively. 'global' specifies that the
+protection should be set across all threads (logical CPU's) not just the
+current running thread/CPU. This increases the overhead of PKS and lessens the
+protection so it should be used sparingly.
Finally, pks_key_free() allows a user to return the key to the allocator for
use by others.
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 324a8fd5ac10..86ad32e0095e 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -261,12 +261,19 @@ noinstr void idtentry_exit_nmi(struct pt_regs *regs, irqentry_state_t *irq_state
* current running value and set the default PKRS value for the duration of the
* exception. Thus preventing exception handlers from having the elevated
* access of the interrupted task.
+ *
+ * NOTE That the thread saved PKRS must be preserved separately to ensure
+ * global overrides do not 'stick' on a thread.
*/
noinstr void irq_save_pkrs(irqentry_state_t *state)
{
if (!cpu_feature_enabled(X86_FEATURE_PKS))
return;
+ /*
+ * The thread_pkrs must be maintained separately to prevent global
+ * overrides from 'sticking' on a thread.
+ */
state->thread_pkrs = current->thread.saved_pkrs;
state->pkrs = this_cpu_read(pkrs_cache);
write_pkrs(INIT_PKRS_VALUE);
diff --git a/arch/x86/include/asm/pkeys.h b/arch/x86/include/asm/pkeys.h
index 79952216474e..cae0153a5480 100644
--- a/arch/x86/include/asm/pkeys.h
+++ b/arch/x86/include/asm/pkeys.h
@@ -143,9 +143,9 @@ u32 update_pkey_val(u32 pk_reg, int pkey, unsigned int flags);
int pks_key_alloc(const char *const pkey_user);
void pks_key_free(int pkey);
-void pks_mknoaccess(int pkey);
-void pks_mkread(int pkey);
-void pks_mkrdwr(int pkey);
+void pks_mknoaccess(int pkey, bool global);
+void pks_mkread(int pkey, bool global);
+void pks_mkrdwr(int pkey, bool global);
#endif /* CONFIG_ARCH_HAS_SUPERVISOR_PKEYS */
diff --git a/arch/x86/include/asm/pkeys_common.h b/arch/x86/include/asm/pkeys_common.h
index 8961e2ddd6ff..e380679ba1bb 100644
--- a/arch/x86/include/asm/pkeys_common.h
+++ b/arch/x86/include/asm/pkeys_common.h
@@ -6,7 +6,12 @@
#define PKR_WD_BIT 0x2
#define PKR_BITS_PER_PKEY 2
-#define PKR_AD_KEY(pkey) (PKR_AD_BIT << ((pkey) * PKR_BITS_PER_PKEY))
+/*
+ * We must define 11b as the default to make global overrides efficient.
+ * See arch/x86/kernel/process.c where the global pkrs is factored in during
+ * context switch.
+ */
+#define PKR_AD_KEY(pkey) ((PKR_WD_BIT | PKR_AD_BIT) << ((pkey) * PKR_BITS_PER_PKEY))
/*
* Define a default PKRS value for each task.
@@ -27,6 +32,7 @@
#define PKS_NUM_KEYS 16
#ifdef CONFIG_ARCH_HAS_SUPERVISOR_PKEYS
+extern u32 pkrs_global_cache;
DECLARE_PER_CPU(u32, pkrs_cache);
noinstr void write_pkrs(u32 new_pkrs);
#else
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index eb3a95a69392..58edd162d9cb 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -43,7 +43,7 @@
#include <asm/io_bitmap.h>
#include <asm/proto.h>
#include <asm/frame.h>
-#include <asm/pkeys_common.h>
+#include <linux/pkeys.h>
#include "process.h"
@@ -189,15 +189,83 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
}
#ifdef CONFIG_ARCH_HAS_SUPERVISOR_PKEYS
-DECLARE_PER_CPU(u32, pkrs_cache);
static inline void pks_init_task(struct task_struct *tsk)
{
/* New tasks get the most restrictive PKRS value */
tsk->thread.saved_pkrs = INIT_PKRS_VALUE;
}
+
+extern u32 pkrs_global_cache;
+
+/**
+ * The global PKRS value can only increase access. Because 01b and 11b both
+ * disable access. The following truth table is our desired result for each of
+ * the pkeys when we add in the global permissions.
+ *
+ * 00 R/W - Write enabled (all access)
+ * 10 Read - write disabled (Read only)
+ * 01 NO Acc - access disabled
+ * 11 NO Acc - also access disabled
+ *
+ * local global desired required
+ * result operation
+ * 00 00 00 &
+ * 00 10 00 &
+ * 00 01 00 &
+ * 00 11 00 &
+ *
+ * 10 00 00 &
+ * 10 10 10 &
+ * 10 01 10 ^ special case
+ * 10 11 10 &
+ *
+ * 01 00 00 &
+ * 01 10 10 ^ special case
+ * 01 01 01 &
+ * 01 11 01 &
+ *
+ * 11 00 00 &
+ * 11 10 10 &
+ * 11 01 01 &
+ * 11 11 11 &
+ *
+ * In order to eliminate the need to loop through each pkey and deal with the 2
+ * above special cases we force all 01b values to 11b through the API thus
+ * resulting in the simplified truth table below.
+ *
+ * 00 R/W - Write enabled (all access)
+ * 10 Read - write disabled (Read only)
+ * 01 NO Acc - access disabled
+ * (Not allowed in the API always use 11)
+ * 11 NO Acc - access disabled
+ *
+ * local global desired effective
+ * result operation
+ * 00 00 00 &
+ * 00 10 00 &
+ * 00 11 00 &
+ * 00 11 00 &
+ *
+ * 10 00 00 &
+ * 10 10 10 &
+ * 10 11 10 &
+ * 10 11 10 &
+ *
+ * 11 00 00 &
+ * 11 10 10 &
+ * 11 11 11 &
+ * 11 11 11 &
+ *
+ * 11 00 00 &
+ * 11 10 10 &
+ * 11 11 11 &
+ * 11 11 11 &
+ *
+ * Thus we can simply 'AND' in the global pkrs value.
+ */
static inline void pks_sched_in(void)
{
- write_pkrs(current->thread.saved_pkrs);
+ write_pkrs(current->thread.saved_pkrs & pkrs_global_cache);
}
#else
static inline void pks_init_task(struct task_struct *tsk) { }
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index dd5af9399131..4b4ff9efa298 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -32,6 +32,8 @@
#include <asm/pgtable_areas.h> /* VMALLOC_START, ... */
#include <asm/kvm_para.h> /* kvm_handle_async_pf */
+#include <asm-generic/mman-common.h>
+
#define CREATE_TRACE_POINTS
#include <asm/trace/exceptions.h>
@@ -995,9 +997,124 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
}
}
-static int spurious_kernel_fault_check(unsigned long error_code, pte_t *pte)
+#ifdef CONFIG_ARCH_HAS_SUPERVISOR_PKEYS
+/*
+ * check if we have had a 'global' pkey update. If so, handle this like a lazy
+ * TLB; fix up the local MSR and return
+ *
+ * See arch/x86/kernel/process.c for the explanation on how global is handled
+ * with a simple '&' operation.
+ *
+ * Also we don't update the current thread saved_pkrs because we don't want the
+ * global value to 'stick' with the thread. Rather we want this to be valid
+ * only for the remainder of this time slice. For subsequent time slices the
+ * global value will be factored in during schedule; see arch/x86/kernel/process.c
+ *
+ * Finally we have a trade off between performance and forcing a restriction of
+ * permissions across all CPUs on a global update.
+ *
+ * Given the following window.
+ *
+ * Global PKRS CPU #0 CPU #1
+ * cache MSR MSR
+ *
+ * | | |
+ * Global |----------\ | |
+ * Restriction | ------------> read | <= T1
+ * (on CPU #0) | | | |
+ * ------\ | | | |
+ * ------>| | | |
+ * | | | |
+ * Update CPU #1 |--------\ | | |
+ * | --------------\ | |
+ * | | --|------------>|
+ * Global remote | | | |
+ * MSR update | | | |
+ * (CPU 2-n) | | | |
+ * |-----> CPU's | v |
+ * local | (2-N) | local --\ |
+ * update | | update ------>|(Update <= T2
+ * ----------------\ | | Incorrect)
+ * | -----------\ | |
+ * | --->|(Update OK) |
+ * Context | | |
+ * Switch |----------\ | |
+ * | ------------> read |
+ * | | | |
+ * | | | |
+ * | | v |
+ * | | local --\ |
+ * | | update ------>|(Update
+ * | | | Correct)
+ *
+ * We allow for a larger window of the global pkey being open because global
+ * updates should be rare and we don't want to burden normal faults with having
+ * to read the global state.
+ */
+static bool global_pkey_is_enabled(pte_t *pte, bool is_write,
+ irqentry_state_t *irq_state)
+{
+ u8 pkey = pte_flags_pkey(pte->pte);
+ int pkey_shift = pkey * PKR_BITS_PER_PKEY;
+ u32 mask = (((1 << PKR_BITS_PER_PKEY) - 1) << pkey_shift);
+ u32 global = READ_ONCE(pkrs_global_cache);
+ u32 val;
+
+ /* Return early if global access is not valid */
+ val = (global & mask) >> pkey_shift;
+ if ((val & PKR_AD_BIT) || (is_write && (val & PKR_WD_BIT)))
+ return false;
+
+ irq_state->pkrs &= global;
+
+ return true;
+}
+
+#else /* !CONFIG_ARCH_HAS_SUPERVISOR_PKEYS */
+__always_inline bool global_pkey_is_enabled(pte_t *pte, bool is_write,
+ irqentry_state_t *irq_state)
+{
+ return false;
+}
+#endif /* CONFIG_ARCH_HAS_SUPERVISOR_PKEYS */
+
+#ifdef CONFIG_PKS_TESTING
+bool pks_test_callback(irqentry_state_t *irq_state);
+static bool handle_pks_testing(unsigned long hw_error_code, irqentry_state_t *irq_state)
+{
+ /*
+ * If we get a protection key exception it could be because we
+ * are running the PKS test. If so, pks_test_callback() will
+ * clear the protection mechanism and return true to indicate
+ * the fault was handled
+ */
+ return pks_test_callback(irq_state);
+}
+#else /* !CONFIG_PKS_TESTING */
+static bool handle_pks_testing(unsigned long hw_error_code, irqentry_state_t *irq_state)
+{
+ return false;
+}
+#endif /* CONFIG_PKS_TESTING */
+
+
+static int spurious_kernel_fault_check(unsigned long error_code, pte_t *pte,
+ irqentry_state_t *irq_state)
{
- if ((error_code & X86_PF_WRITE) && !pte_write(*pte))
+ bool is_write = (error_code & X86_PF_WRITE);
+
+ if (IS_ENABLED(CONFIG_ARCH_HAS_SUPERVISOR_PKEYS) &&
+ error_code & X86_PF_PK) {
+ if (global_pkey_is_enabled(pte, is_write, irq_state))
+ return 1;
+
+ if (handle_pks_testing(error_code, irq_state))
+ return 1;
+
+ return 0;
+ }
+
+ if (is_write && !pte_write(*pte))
return 0;
if ((error_code & X86_PF_INSTR) && !pte_exec(*pte))
@@ -1007,7 +1124,7 @@ static int spurious_kernel_fault_check(unsigned long error_code, pte_t *pte)
}
/*
- * Handle a spurious fault caused by a stale TLB entry.
+ * Handle a spurious fault caused by a stale TLB entry or a lazy PKRS update.
*
* This allows us to lazily refresh the TLB when increasing the
* permissions of a kernel page (RO -> RW or NX -> X). Doing it
@@ -1022,13 +1139,19 @@ static int spurious_kernel_fault_check(unsigned long error_code, pte_t *pte)
* There are no security implications to leaving a stale TLB when
* increasing the permissions on a page.
*
+ * Similarly, PKRS increases in permissions are done on a thread local level.
+ * But if the caller indicates the permission should be allowd globaly we can
+ * lazily update only those threads which fault and avoid a global IPI MSR
+ * update.
+ *
* Returns non-zero if a spurious fault was handled, zero otherwise.
*
* See Intel Developer's Manual Vol 3 Section 4.10.4.3, bullet 3
* (Optional Invalidation).
*/
static noinline int
-spurious_kernel_fault(unsigned long error_code, unsigned long address)
+spurious_kernel_fault(unsigned long error_code, unsigned long address,
+ irqentry_state_t *irq_state)
{
pgd_t *pgd;
p4d_t *p4d;
@@ -1038,17 +1161,19 @@ spurious_kernel_fault(unsigned long error_code, unsigned long address)
int ret;
/*
- * Only writes to RO or instruction fetches from NX may cause
- * spurious faults.
+ * Only PKey faults or writes to RO or instruction fetches from NX may
+ * cause spurious faults.
*
* These could be from user or supervisor accesses but the TLB
* is only lazily flushed after a kernel mapping protection
* change, so user accesses are not expected to cause spurious
* faults.
*/
- if (error_code != (X86_PF_WRITE | X86_PF_PROT) &&
- error_code != (X86_PF_INSTR | X86_PF_PROT))
- return 0;
+ if (!(error_code & X86_PF_PK)) {
+ if (error_code != (X86_PF_WRITE | X86_PF_PROT) &&
+ error_code != (X86_PF_INSTR | X86_PF_PROT))
+ return 0;
+ }
pgd = init_mm.pgd + pgd_index(address);
if (!pgd_present(*pgd))
@@ -1059,27 +1184,31 @@ spurious_kernel_fault(unsigned long error_code, unsigned long address)
return 0;
if (p4d_large(*p4d))
- return spurious_kernel_fault_check(error_code, (pte_t *) p4d);
+ return spurious_kernel_fault_check(error_code, (pte_t *) p4d,
+ irq_state);
pud = pud_offset(p4d, address);
if (!pud_present(*pud))
return 0;
if (pud_large(*pud))
- return spurious_kernel_fault_check(error_code, (pte_t *) pud);
+ return spurious_kernel_fault_check(error_code, (pte_t *) pud,
+ irq_state);
pmd = pmd_offset(pud, address);
if (!pmd_present(*pmd))
return 0;
if (pmd_large(*pmd))
- return spurious_kernel_fault_check(error_code, (pte_t *) pmd);
+ return spurious_kernel_fault_check(error_code, (pte_t *) pmd,
+ irq_state);
pte = pte_offset_kernel(pmd, address);
if (!pte_present(*pte))
return 0;
- ret = spurious_kernel_fault_check(error_code, pte);
+ ret = spurious_kernel_fault_check(error_code, pte,
+ irq_state);
if (!ret)
return 0;
@@ -1087,7 +1216,8 @@ spurious_kernel_fault(unsigned long error_code, unsigned long address)
* Make sure we have permissions in PMD.
* If not, then there's a bug in the page tables:
*/
- ret = spurious_kernel_fault_check(error_code, (pte_t *) pmd);
+ ret = spurious_kernel_fault_check(error_code, (pte_t *) pmd,
+ irq_state);
WARN_ONCE(!ret, "PMD has incorrect permission bits\n");
return ret;
@@ -1150,25 +1280,6 @@ static int fault_in_kernel_space(unsigned long address)
return address >= TASK_SIZE_MAX;
}
-#ifdef CONFIG_PKS_TESTING
-bool pks_test_callback(irqentry_state_t *irq_state);
-static bool handle_pks_testing(unsigned long hw_error_code, irqentry_state_t *irq_state)
-{
- /*
- * If we get a protection key exception it could be because we
- * are running the PKS test. If so, pks_test_callback() will
- * clear the protection mechanism and return true to indicate
- * the fault was handled.
- */
- return (hw_error_code & X86_PF_PK) && pks_test_callback(irq_state);
-}
-#else
-static bool handle_pks_testing(unsigned long hw_error_code, irqentry_state_t *irq_state)
-{
- return false;
-}
-#endif
-
/*
* Called for all faults where 'address' is part of the kernel address
* space. Might get called for faults that originate from *code* that
@@ -1186,9 +1297,6 @@ do_kern_addr_fault(struct pt_regs *regs, unsigned long hw_error_code,
!cpu_feature_enabled(X86_FEATURE_PKS))
WARN_ON_ONCE(hw_error_code & X86_PF_PK);
- if (handle_pks_testing(hw_error_code, irq_state))
- return;
-
#ifdef CONFIG_X86_32
/*
* We can fault-in kernel-space virtual memory on-demand. The
@@ -1220,8 +1328,11 @@ do_kern_addr_fault(struct pt_regs *regs, unsigned long hw_error_code,
}
#endif
- /* Was the fault spurious, caused by lazy TLB invalidation? */
- if (spurious_kernel_fault(hw_error_code, address))
+ /*
+ * Was the fault spurious; caused by lazy TLB invalidation or PKRS
+ * update?
+ */
+ if (spurious_kernel_fault(hw_error_code, address, irq_state))
return;
/* kprobes don't want to hook the spurious faults: */
@@ -1492,7 +1603,7 @@ DEFINE_IDTENTRY_RAW_ERRORCODE(exc_page_fault)
*
* Fingers crossed.
*
- * The async #PF handling code takes care of idtentry handling
+ * The async #PF handling code takes care of irqentry handling
* itself.
*/
if (kvm_handle_async_pf(regs, (u32)address))
diff --git a/arch/x86/mm/pkeys.c b/arch/x86/mm/pkeys.c
index 2431c68ef752..a45893069877 100644
--- a/arch/x86/mm/pkeys.c
+++ b/arch/x86/mm/pkeys.c
@@ -263,33 +263,84 @@ noinstr void write_pkrs(u32 new_pkrs)
}
EXPORT_SYMBOL_GPL(write_pkrs);
+/*
+ * NOTE: The pkrs_global_cache is _never_ stored in the per thread PKRS cache
+ * values [thread.saved_pkrs] by design
+ *
+ * This allows us to invalidate access on running threads immediately upon
+ * invalidate. Sleeping threads will not be enabled due to the algorithm
+ * during pkrs_sched_in()
+ */
+DEFINE_SPINLOCK(pkrs_global_cache_lock);
+u32 pkrs_global_cache = INIT_PKRS_VALUE;
+EXPORT_SYMBOL_GPL(pkrs_global_cache);
+
+static inline void update_global_pkrs(int pkey, unsigned long protection)
+{
+ int pkey_shift = pkey * PKR_BITS_PER_PKEY;
+ u32 mask = (((1 << PKR_BITS_PER_PKEY) - 1) << pkey_shift);
+ u32 old_val;
+
+ spin_lock(&pkrs_global_cache_lock);
+ old_val = (pkrs_global_cache & mask) >> pkey_shift;
+ pkrs_global_cache &= ~mask;
+ if (protection & PKEY_DISABLE_ACCESS)
+ pkrs_global_cache |= PKR_AD_BIT << pkey_shift;
+ if (protection & PKEY_DISABLE_WRITE)
+ pkrs_global_cache |= PKR_WD_BIT << pkey_shift;
+
+ /*
+ * If we are preventing access from the old value. Force the
+ * update on all running threads.
+ */
+ if (((old_val == 0) && protection) ||
+ ((old_val & PKR_WD_BIT) && (protection & PKEY_DISABLE_ACCESS))) {
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ u32 *ptr = per_cpu_ptr(&pkrs_cache, cpu);
+
+ *ptr = update_pkey_val(*ptr, pkey, protection);
+ wrmsrl_on_cpu(cpu, MSR_IA32_PKRS, *ptr);
+ put_cpu_ptr(ptr);
+ }
+ }
+ spin_unlock(&pkrs_global_cache_lock);
+}
+
/**
* Do not call this directly, see pks_mk*() below.
*
* @pkey: Key for the domain to change
* @protection: protection bits to be used
+ * @global: should this change be made globally or not.
*
* Protection utilizes the same protection bits specified for User pkeys
* PKEY_DISABLE_ACCESS
* PKEY_DISABLE_WRITE
*
*/
-static inline void pks_update_protection(int pkey, unsigned long protection)
+static inline void pks_update_protection(int pkey, unsigned long protection,
+ bool global)
{
- current->thread.saved_pkrs = update_pkey_val(current->thread.saved_pkrs,
- pkey, protection);
preempt_disable();
+ if (global)
+ update_global_pkrs(pkey, protection);
+
+ current->thread.saved_pkrs = update_pkey_val(current->thread.saved_pkrs, pkey,
+ protection);
write_pkrs(current->thread.saved_pkrs);
+
preempt_enable();
}
/**
* PKS access control functions
*
- * Change the access of the domain specified by the pkey. These are global
- * updates. They only affects the current running thread. It is undefined and
- * a bug for users to call this without having allocated a pkey and using it as
- * pkey here.
+ * Change the access of the domain specified by the pkey. These may be global
+ * updates depending on the value of global. It is undefined and a bug for
+ * users to call this without having allocated a pkey and using it as pkey
+ * here.
*
* pks_mknoaccess()
* Disable all access to the domain
@@ -299,23 +350,30 @@ static inline void pks_update_protection(int pkey, unsigned long protection)
* Make the domain Read/Write
*
* @pkey the pkey for which the access should change.
- *
+ * @global if true the access is enabled on all threads/logical cpus
*/
-void pks_mknoaccess(int pkey)
+void pks_mknoaccess(int pkey, bool global)
{
- pks_update_protection(pkey, PKEY_DISABLE_ACCESS);
+ /*
+ * We force disable access to be 11b
+ * (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)
+ * instaed of 01b See arch/x86/kernel/process.c where the global pkrs
+ * is factored in during context switch.
+ */
+ pks_update_protection(pkey, PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE,
+ global);
}
EXPORT_SYMBOL_GPL(pks_mknoaccess);
-void pks_mkread(int pkey)
+void pks_mkread(int pkey, bool global)
{
- pks_update_protection(pkey, PKEY_DISABLE_WRITE);
+ pks_update_protection(pkey, PKEY_DISABLE_WRITE, global);
}
EXPORT_SYMBOL_GPL(pks_mkread);
-void pks_mkrdwr(int pkey)
+void pks_mkrdwr(int pkey, bool global)
{
- pks_update_protection(pkey, 0);
+ pks_update_protection(pkey, 0, global);
}
EXPORT_SYMBOL_GPL(pks_mkrdwr);
@@ -377,7 +435,7 @@ void pks_key_free(int pkey)
return;
/* Restore to default of no access */
- pks_mknoaccess(pkey);
+ pks_mknoaccess(pkey, true);
pks_key_users[pkey] = NULL;
__clear_bit(pkey, &pks_key_allocation_map);
}
diff --git a/include/linux/pkeys.h b/include/linux/pkeys.h
index f9552bd9341f..8f3bfec83949 100644
--- a/include/linux/pkeys.h
+++ b/include/linux/pkeys.h
@@ -57,15 +57,15 @@ static inline int pks_key_alloc(const char * const pkey_user)
static inline void pks_key_free(int pkey)
{
}
-static inline void pks_mknoaccess(int pkey)
+static inline void pks_mknoaccess(int pkey, bool global)
{
WARN_ON_ONCE(1);
}
-static inline void pks_mkread(int pkey)
+static inline void pks_mkread(int pkey, bool global)
{
WARN_ON_ONCE(1);
}
-static inline void pks_mkrdwr(int pkey)
+static inline void pks_mkrdwr(int pkey, bool global)
{
WARN_ON_ONCE(1);
}
diff --git a/lib/pks/pks_test.c b/lib/pks/pks_test.c
index d7dbf92527bd..286c8b8457da 100644
--- a/lib/pks/pks_test.c
+++ b/lib/pks/pks_test.c
@@ -163,12 +163,12 @@ static void check_exception(irqentry_state_t *irq_state)
* Check we can update the value during exception without affecting the
* calling thread. The calling thread is checked after exception...
*/
- pks_mkrdwr(test_armed_key);
+ pks_mkrdwr(test_armed_key, false);
if (!check_pkrs(test_armed_key, 0)) {
pr_err(" FAIL: exception did not change register to 0\n");
test_exception_ctx->pass = false;
}
- pks_mknoaccess(test_armed_key);
+ pks_mknoaccess(test_armed_key, false);
if (!check_pkrs(test_armed_key, PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)) {
pr_err(" FAIL: exception did not change register to 0x3\n");
test_exception_ctx->pass = false;
@@ -314,13 +314,13 @@ static int run_access_test(struct pks_test_ctx *ctx,
{
switch (test->mode) {
case PKS_TEST_NO_ACCESS:
- pks_mknoaccess(ctx->pkey);
+ pks_mknoaccess(ctx->pkey, false);
break;
case PKS_TEST_RDWR:
- pks_mkrdwr(ctx->pkey);
+ pks_mkrdwr(ctx->pkey, false);
break;
case PKS_TEST_RDONLY:
- pks_mkread(ctx->pkey);
+ pks_mkread(ctx->pkey, false);
break;
default:
pr_err("BUG in test invalid mode\n");
@@ -476,7 +476,7 @@ static void run_exception_test(void)
goto free_context;
}
- pks_mkread(ctx->pkey);
+ pks_mkread(ctx->pkey, false);
spin_lock(&test_lock);
WRITE_ONCE(test_exception_ctx, ctx);
@@ -556,7 +556,7 @@ static void crash_it(void)
return;
}
- pks_mknoaccess(ctx->pkey);
+ pks_mknoaccess(ctx->pkey, false);
spin_lock(&test_lock);
WRITE_ONCE(test_armed_key, 0);
@@ -618,7 +618,7 @@ static ssize_t pks_write_file(struct file *file, const char __user *user_buf,
/* start of context switch test */
if (!strcmp(buf, "1")) {
/* Ensure a known state to test context switch */
- pks_mknoaccess(ctx->pkey);
+ pks_mknoaccess(ctx->pkey, false);
}
/* After context switch msr should be restored */
--
2.28.0.rc0.12.gb6a658bd00c9
^ permalink raw reply related
* [PATCH RFC PKS/PMEM 00/58] PMEM: Introduce stray write protection for PMEM
From: ira.weiny @ 2020-10-09 19:49 UTC (permalink / raw)
To: Andrew Morton, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Andy Lutomirski, Peter Zijlstra
Cc: linux-aio, linux-efi, kvm, linux-doc, linux-mmc, Dave Hansen,
dri-devel, linux-mm, target-devel, linux-mtd, linux-kselftest,
samba-technical, Ira Weiny, ceph-devel, drbd-dev, devel,
linux-cifs, linux-nilfs, linux-scsi, linux-nvdimm, linux-rdma,
x86, amd-gfx, linux-afs, cluster-devel, linux-cachefs,
intel-wired-lan, xen-devel, linux-ext4, Fenghua Yu, linux-um,
intel-gfx, ecryptfs, linux-erofs, reiserfs-devel, linux-block,
linux-bcache, Dan Williams, io-uring, linux-nfs, linux-ntfs-dev,
netdev, kexec, linux-kernel, linux-f2fs-devel, linux-fsdevel, bpf,
linuxppc-dev, linux-btrfs
From: Ira Weiny <ira.weiny@intel.com>
Should a stray write in the kernel occur persistent memory is affected more
than regular memory. A write to the wrong area of memory could result in
latent data corruption which will will persist after a reboot. PKS provides a
nice way to restrict access to persistent memory kernel mappings, while
providing fast access when needed.
Since the last RFC[1] this patch set has grown quite a bit. It now depends on
the core patches submitted separately.
https://lore.kernel.org/lkml/20201009194258.3207172-1-ira.weiny@intel.com/
And contained in the git tree here:
https://github.com/weiny2/linux-kernel/tree/pks-rfc-v3
However, functionally there is only 1 major change from the last RFC.
Specifically, kmap() is most often used within a single thread in a 'map/do
something/unmap' pattern. In fact this is the pattern used in ~90% of the
callers of kmap(). This pattern works very well for the pmem use case and the
testing which was done. However, there were another ~20-30 kmap users which do
not follow this pattern. Some of them seem to expect the mapping to be
'global' while others require a detailed audit to be sure.[2][3]
While we don't anticipate global mappings to pmem there is a danger in
changing the semantics of kmap(). Effectively, this would cause an unresolved
page fault with little to no information about why.
There were a number of options considered.
1) Attempt to change all the thread local kmap() calls to kmap_atomic()
2) Introduce a flags parameter to kmap() to indicate if the mapping should be
global or not
3) Change ~20-30 call sites to 'kmap_global()' to indicate that they require a
global mapping of the pages
4) Change ~209 call sites to 'kmap_thread()' to indicate that the mapping is to
be used within that thread of execution only
Option 1 is simply not feasible kmap_atomic() is not the same semantic as
kmap() within a single tread. Option 2 would require all of the call sites of
kmap() to change. Option 3 seems like a good minimal change but there is a
danger that new code may miss the semantic change of kmap() and not get the
behavior intended for future users. Therefore, option #4 was chosen.
To handle the global PKRS state in the most efficient manner possible. We
lazily override the thread specific PKRS key value only when needed because we
anticipate PKS to not be needed will not be needed most of the time. And even
when it is used 90% of the time it is a thread local call.
[1] https://lore.kernel.org/lkml/20200717072056.73134-1-ira.weiny@intel.com/
[2] The following list of callers continue calling kmap() (utilizing the global
PKRS). It would be nice if more of them could be converted to kmap_thread()
drivers/firewire/net.c: ptr = kmap(dev->broadcast_rcv_buffer.pages[u]);
drivers/gpu/drm/i915/gem/i915_gem_pages.c: return kmap(sg_page(sgt->sgl));
drivers/gpu/drm/ttm/ttm_bo_util.c: map->virtual = kmap(map->page);
drivers/infiniband/hw/qib/qib_user_sdma.c: mpage = kmap(page);
drivers/misc/vmw_vmci/vmci_host.c: context->notify = kmap(context->notify_page) + (uva & (PAGE_SIZE - 1));
drivers/misc/xilinx_sdfec.c: addr = kmap(pages[i]);
drivers/mmc/host/usdhi6rol0.c: host->pg.mapped = kmap(host->pg.page);
drivers/mmc/host/usdhi6rol0.c: host->pg.mapped = kmap(host->pg.page);
drivers/mmc/host/usdhi6rol0.c: host->pg.mapped = kmap(host->pg.page);
drivers/nvme/target/tcp.c: iov->iov_base = kmap(sg_page(sg)) + sg->offset + sg_offset;
drivers/scsi/libiscsi_tcp.c: segment->sg_mapped = kmap(sg_page(sg));
drivers/target/iscsi/iscsi_target.c: iov[i].iov_base = kmap(sg_page(sg)) + sg->offset + page_off;
drivers/target/target_core_transport.c: return kmap(sg_page(sg)) + sg->offset;
fs/btrfs/check-integrity.c: block_ctx->datav[i] = kmap(block_ctx->pagev[i]);
fs/ceph/dir.c: cache_ctl->dentries = kmap(cache_ctl->page);
fs/ceph/inode.c: ctl->dentries = kmap(ctl->page);
fs/erofs/zpvec.h: kmap_atomic(ctor->curr) : kmap(ctor->curr);
lib/scatterlist.c: miter->addr = kmap(miter->page) + miter->__offset;
net/ceph/pagelist.c: pl->mapped_tail = kmap(page);
net/ceph/pagelist.c: pl->mapped_tail = kmap(page);
virt/kvm/kvm_main.c: hva = kmap(page);
[3] The following appear to follow the same pattern as ext2 which was converted
after some code audit. So I _think_ they too could be converted to
k[un]map_thread().
fs/freevxfs/vxfs_subr.c|75| kmap(pp);
fs/jfs/jfs_metapage.c|102| kmap(page);
fs/jfs/jfs_metapage.c|156| kmap(page);
fs/minix/dir.c|72| kmap(page);
fs/nilfs2/dir.c|195| kmap(page);
fs/nilfs2/ifile.h|24| void *kaddr = kmap(ibh->b_page);
fs/ntfs/aops.h|78| kmap(page);
fs/ntfs/compress.c|574| kmap(page);
fs/qnx6/dir.c|32| kmap(page);
fs/qnx6/dir.c|58| kmap(*p = page);
fs/qnx6/inode.c|190| kmap(page);
fs/qnx6/inode.c|557| kmap(page);
fs/reiserfs/inode.c|2397| kmap(bh_result->b_page);
fs/reiserfs/xattr.c|444| kmap(page);
fs/sysv/dir.c|60| kmap(page);
fs/sysv/dir.c|262| kmap(page);
fs/ufs/dir.c|194| kmap(page);
fs/ufs/dir.c|562| kmap(page);
Ira Weiny (58):
x86/pks: Add a global pkrs option
x86/pks/test: Add testing for global option
memremap: Add zone device access protection
kmap: Add stray access protection for device pages
kmap: Introduce k[un]map_thread
kmap: Introduce k[un]map_thread debugging
drivers/drbd: Utilize new kmap_thread()
drivers/firmware_loader: Utilize new kmap_thread()
drivers/gpu: Utilize new kmap_thread()
drivers/rdma: Utilize new kmap_thread()
drivers/net: Utilize new kmap_thread()
fs/afs: Utilize new kmap_thread()
fs/btrfs: Utilize new kmap_thread()
fs/cifs: Utilize new kmap_thread()
fs/ecryptfs: Utilize new kmap_thread()
fs/gfs2: Utilize new kmap_thread()
fs/nilfs2: Utilize new kmap_thread()
fs/hfs: Utilize new kmap_thread()
fs/hfsplus: Utilize new kmap_thread()
fs/jffs2: Utilize new kmap_thread()
fs/nfs: Utilize new kmap_thread()
fs/f2fs: Utilize new kmap_thread()
fs/fuse: Utilize new kmap_thread()
fs/freevxfs: Utilize new kmap_thread()
fs/reiserfs: Utilize new kmap_thread()
fs/zonefs: Utilize new kmap_thread()
fs/ubifs: Utilize new kmap_thread()
fs/cachefiles: Utilize new kmap_thread()
fs/ntfs: Utilize new kmap_thread()
fs/romfs: Utilize new kmap_thread()
fs/vboxsf: Utilize new kmap_thread()
fs/hostfs: Utilize new kmap_thread()
fs/cramfs: Utilize new kmap_thread()
fs/erofs: Utilize new kmap_thread()
fs: Utilize new kmap_thread()
fs/ext2: Use ext2_put_page
fs/ext2: Utilize new kmap_thread()
fs/isofs: Utilize new kmap_thread()
fs/jffs2: Utilize new kmap_thread()
net: Utilize new kmap_thread()
drivers/target: Utilize new kmap_thread()
drivers/scsi: Utilize new kmap_thread()
drivers/mmc: Utilize new kmap_thread()
drivers/xen: Utilize new kmap_thread()
drivers/firmware: Utilize new kmap_thread()
drives/staging: Utilize new kmap_thread()
drivers/mtd: Utilize new kmap_thread()
drivers/md: Utilize new kmap_thread()
drivers/misc: Utilize new kmap_thread()
drivers/android: Utilize new kmap_thread()
kernel: Utilize new kmap_thread()
mm: Utilize new kmap_thread()
lib: Utilize new kmap_thread()
powerpc: Utilize new kmap_thread()
samples: Utilize new kmap_thread()
dax: Stray access protection for dax_direct_access()
nvdimm/pmem: Stray access protection for pmem->virt_addr
[dax|pmem]: Enable stray access protection
Documentation/core-api/protection-keys.rst | 11 +-
arch/powerpc/mm/mem.c | 4 +-
arch/x86/entry/common.c | 28 +++
arch/x86/include/asm/pkeys.h | 6 +-
arch/x86/include/asm/pkeys_common.h | 8 +-
arch/x86/kernel/process.c | 74 ++++++-
arch/x86/mm/fault.c | 193 ++++++++++++++----
arch/x86/mm/pkeys.c | 88 ++++++--
drivers/android/binder_alloc.c | 4 +-
drivers/base/firmware_loader/fallback.c | 4 +-
drivers/base/firmware_loader/main.c | 4 +-
drivers/block/drbd/drbd_main.c | 4 +-
drivers/block/drbd/drbd_receiver.c | 12 +-
drivers/dax/device.c | 2 +
drivers/dax/super.c | 2 +
drivers/firmware/efi/capsule-loader.c | 6 +-
drivers/firmware/efi/capsule.c | 4 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 12 +-
drivers/gpu/drm/gma500/gma_display.c | 4 +-
drivers/gpu/drm/gma500/mmu.c | 10 +-
drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 4 +-
.../drm/i915/gem/selftests/i915_gem_context.c | 4 +-
.../drm/i915/gem/selftests/i915_gem_mman.c | 8 +-
drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 4 +-
drivers/gpu/drm/i915/gt/intel_gtt.c | 4 +-
drivers/gpu/drm/i915/gt/shmem_utils.c | 4 +-
drivers/gpu/drm/i915/i915_gem.c | 8 +-
drivers/gpu/drm/i915/i915_gpu_error.c | 4 +-
drivers/gpu/drm/i915/selftests/i915_perf.c | 4 +-
drivers/gpu/drm/radeon/radeon_ttm.c | 4 +-
drivers/infiniband/hw/hfi1/sdma.c | 4 +-
drivers/infiniband/hw/i40iw/i40iw_cm.c | 10 +-
drivers/infiniband/sw/siw/siw_qp_tx.c | 14 +-
drivers/md/bcache/request.c | 4 +-
drivers/misc/vmw_vmci/vmci_queue_pair.c | 12 +-
drivers/mmc/host/mmc_spi.c | 4 +-
drivers/mmc/host/sdricoh_cs.c | 4 +-
drivers/mtd/mtd_blkdevs.c | 12 +-
drivers/net/ethernet/intel/igb/igb_ethtool.c | 4 +-
.../net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 4 +-
drivers/nvdimm/pmem.c | 6 +
drivers/scsi/ipr.c | 8 +-
drivers/scsi/pmcraid.c | 8 +-
drivers/staging/rts5208/rtsx_transport.c | 4 +-
drivers/target/target_core_iblock.c | 4 +-
drivers/target/target_core_rd.c | 4 +-
drivers/target/target_core_transport.c | 4 +-
drivers/xen/gntalloc.c | 4 +-
fs/afs/dir.c | 16 +-
fs/afs/dir_edit.c | 16 +-
fs/afs/mntpt.c | 4 +-
fs/afs/write.c | 4 +-
fs/aio.c | 4 +-
fs/binfmt_elf.c | 4 +-
fs/binfmt_elf_fdpic.c | 4 +-
fs/btrfs/check-integrity.c | 4 +-
fs/btrfs/compression.c | 4 +-
fs/btrfs/inode.c | 16 +-
fs/btrfs/lzo.c | 24 +--
fs/btrfs/raid56.c | 34 +--
fs/btrfs/reflink.c | 8 +-
fs/btrfs/send.c | 4 +-
fs/btrfs/zlib.c | 32 +--
fs/btrfs/zstd.c | 20 +-
fs/cachefiles/rdwr.c | 4 +-
fs/cifs/cifsencrypt.c | 6 +-
fs/cifs/file.c | 16 +-
fs/cifs/smb2ops.c | 8 +-
fs/cramfs/inode.c | 10 +-
fs/ecryptfs/crypto.c | 8 +-
fs/ecryptfs/read_write.c | 8 +-
fs/erofs/super.c | 4 +-
fs/erofs/xattr.c | 4 +-
fs/exec.c | 10 +-
fs/ext2/dir.c | 8 +-
fs/ext2/ext2.h | 8 +
fs/ext2/namei.c | 15 +-
fs/f2fs/f2fs.h | 8 +-
fs/freevxfs/vxfs_immed.c | 4 +-
fs/fuse/readdir.c | 4 +-
fs/gfs2/bmap.c | 4 +-
fs/gfs2/ops_fstype.c | 4 +-
fs/hfs/bnode.c | 14 +-
fs/hfs/btree.c | 20 +-
fs/hfsplus/bitmap.c | 20 +-
fs/hfsplus/bnode.c | 102 ++++-----
fs/hfsplus/btree.c | 18 +-
fs/hostfs/hostfs_kern.c | 12 +-
fs/io_uring.c | 4 +-
fs/isofs/compress.c | 4 +-
fs/jffs2/file.c | 8 +-
fs/jffs2/gc.c | 4 +-
fs/nfs/dir.c | 20 +-
fs/nilfs2/alloc.c | 34 +--
fs/nilfs2/cpfile.c | 4 +-
fs/ntfs/aops.c | 4 +-
fs/reiserfs/journal.c | 4 +-
fs/romfs/super.c | 4 +-
fs/splice.c | 4 +-
fs/ubifs/file.c | 16 +-
fs/vboxsf/file.c | 12 +-
fs/zonefs/super.c | 4 +-
include/linux/entry-common.h | 3 +
include/linux/highmem.h | 63 +++++-
include/linux/memremap.h | 1 +
include/linux/mm.h | 43 ++++
include/linux/pkeys.h | 6 +-
include/linux/sched.h | 8 +
include/trace/events/kmap_thread.h | 56 +++++
init/init_task.c | 6 +
kernel/fork.c | 18 ++
kernel/kexec_core.c | 8 +-
lib/Kconfig.debug | 8 +
lib/iov_iter.c | 12 +-
lib/pks/pks_test.c | 138 +++++++++++--
lib/test_bpf.c | 4 +-
lib/test_hmm.c | 8 +-
mm/Kconfig | 13 ++
mm/debug.c | 23 +++
mm/memory.c | 8 +-
mm/memremap.c | 90 ++++++++
mm/swapfile.c | 4 +-
mm/userfaultfd.c | 4 +-
net/ceph/messenger.c | 4 +-
net/core/datagram.c | 4 +-
net/core/sock.c | 8 +-
net/ipv4/ip_output.c | 4 +-
net/sunrpc/cache.c | 4 +-
net/sunrpc/xdr.c | 8 +-
net/tls/tls_device.c | 4 +-
samples/vfio-mdev/mbochs.c | 4 +-
131 files changed, 1284 insertions(+), 565 deletions(-)
create mode 100644 include/trace/events/kmap_thread.h
--
2.28.0.rc0.12.gb6a658bd00c9
^ permalink raw reply
* [PATCH v4 2/2] lkdtm/powerpc: Add SLB multihit test
From: Ganesh Goudar @ 2020-10-09 6:40 UTC (permalink / raw)
To: linuxppc-dev, mpe; +Cc: msuchanek, Ganesh Goudar, keescook, npiggin, mahesh
In-Reply-To: <20201009064005.19777-1-ganeshgr@linux.ibm.com>
To check machine check handling, add support to inject slb
multihit errors.
Cc: Kees Cook <keescook@chromium.org>
Reviewed-by: Michal Suchánek <msuchanek@suse.de>
Co-developed-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
Signed-off-by: Ganesh Goudar <ganeshgr@linux.ibm.com>
---
drivers/misc/lkdtm/Makefile | 1 +
drivers/misc/lkdtm/core.c | 3 +
drivers/misc/lkdtm/lkdtm.h | 3 +
drivers/misc/lkdtm/powerpc.c | 156 ++++++++++++++++++++++++
tools/testing/selftests/lkdtm/tests.txt | 1 +
5 files changed, 164 insertions(+)
create mode 100644 drivers/misc/lkdtm/powerpc.c
diff --git a/drivers/misc/lkdtm/Makefile b/drivers/misc/lkdtm/Makefile
index c70b3822013f..f37ecfb0a707 100644
--- a/drivers/misc/lkdtm/Makefile
+++ b/drivers/misc/lkdtm/Makefile
@@ -10,6 +10,7 @@ lkdtm-$(CONFIG_LKDTM) += rodata_objcopy.o
lkdtm-$(CONFIG_LKDTM) += usercopy.o
lkdtm-$(CONFIG_LKDTM) += stackleak.o
lkdtm-$(CONFIG_LKDTM) += cfi.o
+lkdtm-$(CONFIG_PPC64) += powerpc.o
KASAN_SANITIZE_stackleak.o := n
KCOV_INSTRUMENT_rodata.o := n
diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c
index a5e344df9166..8d5db42baa90 100644
--- a/drivers/misc/lkdtm/core.c
+++ b/drivers/misc/lkdtm/core.c
@@ -178,6 +178,9 @@ static const struct crashtype crashtypes[] = {
#ifdef CONFIG_X86_32
CRASHTYPE(DOUBLE_FAULT),
#endif
+#ifdef CONFIG_PPC64
+ CRASHTYPE(PPC_SLB_MULTIHIT),
+#endif
};
diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h
index 8878538b2c13..b305bd511ee5 100644
--- a/drivers/misc/lkdtm/lkdtm.h
+++ b/drivers/misc/lkdtm/lkdtm.h
@@ -104,4 +104,7 @@ void lkdtm_STACKLEAK_ERASING(void);
/* cfi.c */
void lkdtm_CFI_FORWARD_PROTO(void);
+/* powerpc.c */
+void lkdtm_PPC_SLB_MULTIHIT(void);
+
#endif
diff --git a/drivers/misc/lkdtm/powerpc.c b/drivers/misc/lkdtm/powerpc.c
new file mode 100644
index 000000000000..f388b53dccba
--- /dev/null
+++ b/drivers/misc/lkdtm/powerpc.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "lkdtm.h"
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+/* Gets index for new slb entry */
+static inline unsigned long get_slb_index(void)
+{
+ unsigned long index;
+
+ index = get_paca()->stab_rr;
+
+ /*
+ * simple round-robin replacement of slb starting at SLB_NUM_BOLTED.
+ */
+ if (index < (mmu_slb_size - 1))
+ index++;
+ else
+ index = SLB_NUM_BOLTED;
+ get_paca()->stab_rr = index;
+ return index;
+}
+
+#define slb_esid_mask(ssize) \
+ (((ssize) == MMU_SEGSIZE_256M) ? ESID_MASK : ESID_MASK_1T)
+
+/* Form the operand for slbmte */
+static inline unsigned long mk_esid_data(unsigned long ea, int ssize,
+ unsigned long slot)
+{
+ return (ea & slb_esid_mask(ssize)) | SLB_ESID_V | slot;
+}
+
+#define slb_vsid_shift(ssize) \
+ ((ssize) == MMU_SEGSIZE_256M ? SLB_VSID_SHIFT : SLB_VSID_SHIFT_1T)
+
+/* Form the operand for slbmte */
+static inline unsigned long mk_vsid_data(unsigned long ea, int ssize,
+ unsigned long flags)
+{
+ return (get_kernel_vsid(ea, ssize) << slb_vsid_shift(ssize)) | flags |
+ ((unsigned long)ssize << SLB_VSID_SSIZE_SHIFT);
+}
+
+/* Inserts new slb entry */
+static void insert_slb_entry(char *p, int ssize)
+{
+ unsigned long flags, entry;
+
+ flags = SLB_VSID_KERNEL | mmu_psize_defs[MMU_PAGE_64K].sllp;
+ preempt_disable();
+
+ entry = get_slb_index();
+ asm volatile("slbmte %0,%1" :
+ : "r" (mk_vsid_data((unsigned long)p, ssize, flags)),
+ "r" (mk_esid_data((unsigned long)p, ssize, entry))
+ : "memory");
+
+ entry = get_slb_index();
+ asm volatile("slbmte %0,%1" :
+ : "r" (mk_vsid_data((unsigned long)p, ssize, flags)),
+ "r" (mk_esid_data((unsigned long)p, ssize, entry))
+ : "memory");
+ preempt_enable();
+ /*
+ * This triggers exception, If handled correctly we must recover
+ * from this error.
+ */
+ p[0] = '!';
+}
+
+/* Inject slb multihit on vmalloc-ed address i.e 0xD00... */
+static void inject_vmalloc_slb_multihit(void)
+{
+ char *p;
+
+ p = vmalloc(2048);
+ if (!p)
+ return;
+
+ insert_slb_entry(p, MMU_SEGSIZE_1T);
+ vfree(p);
+}
+
+/* Inject slb multihit on kmalloc-ed address i.e 0xC00... */
+static void inject_kmalloc_slb_multihit(void)
+{
+ char *p;
+
+ p = kmalloc(2048, GFP_KERNEL);
+ if (!p)
+ return;
+
+ insert_slb_entry(p, MMU_SEGSIZE_1T);
+ kfree(p);
+}
+
+/*
+ * Few initial SLB entries are bolted. Add a test to inject
+ * multihit in bolted entry 0.
+ */
+static void insert_dup_slb_entry_0(void)
+{
+ unsigned long test_address = 0xC000000000000000;
+ volatile unsigned long *test_ptr;
+ unsigned long entry, i = 0;
+ unsigned long esid, vsid;
+
+ test_ptr = (unsigned long *)test_address;
+ preempt_disable();
+
+ asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i));
+ asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i));
+ entry = get_slb_index();
+
+ /* for i !=0 we would need to mask out the old entry number */
+ asm volatile("slbmte %0,%1" :
+ : "r" (vsid),
+ "r" (esid | entry)
+ : "memory");
+
+ asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i));
+ asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i));
+ entry = get_slb_index();
+
+ /* for i !=0 we would need to mask out the old entry number */
+ asm volatile("slbmte %0,%1" :
+ : "r" (vsid),
+ "r" (esid | entry)
+ : "memory");
+
+ pr_info("%s accessing test address 0x%lx: 0x%lx\n",
+ __func__, test_address, *test_ptr);
+
+ preempt_enable();
+}
+
+void lkdtm_PPC_SLB_MULTIHIT(void)
+{
+ if (mmu_has_feature(MMU_FTR_HPTE_TABLE)) {
+ pr_info("Injecting SLB multihit errors\n");
+ /*
+ * These need not be separate tests, And they do pretty
+ * much same thing. In any case we must recover from the
+ * errors introduced by these functions, machine would not
+ * survive these tests in case of failure to handle.
+ */
+ inject_vmalloc_slb_multihit();
+ inject_kmalloc_slb_multihit();
+ insert_dup_slb_entry_0();
+ pr_info("Recovered from SLB multihit errors\n");
+ } else {
+ pr_err("XFAIL: This test is for ppc64 and with hash mode MMU only\n");
+ }
+}
diff --git a/tools/testing/selftests/lkdtm/tests.txt b/tools/testing/selftests/lkdtm/tests.txt
index 9d266e79c6a2..7eb3cf91c89e 100644
--- a/tools/testing/selftests/lkdtm/tests.txt
+++ b/tools/testing/selftests/lkdtm/tests.txt
@@ -70,3 +70,4 @@ USERCOPY_KERNEL
USERCOPY_KERNEL_DS
STACKLEAK_ERASING OK: the rest of the thread stack is properly erased
CFI_FORWARD_PROTO
+PPC_SLB_MULTIHIT Recovered
--
2.26.2
^ permalink raw reply related
* [PATCH v4 1/2] powerpc/mce: remove nmi_enter/exit from real mode handler
From: Ganesh Goudar @ 2020-10-09 6:40 UTC (permalink / raw)
To: linuxppc-dev, mpe; +Cc: msuchanek, Ganesh Goudar, keescook, npiggin, mahesh
In-Reply-To: <20201009064005.19777-1-ganeshgr@linux.ibm.com>
Use of nmi_enter/exit in real mode handler causes the kernel to panic
and reboot on injecting slb mutihit on pseries machine running in hash
mmu mode, As these calls try to accesses memory outside RMO region in
real mode handler where translation is disabled.
Add check to not to use these calls on pseries machine running in hash
mmu mode.
Fixes: 116ac378bb3f ("powerpc/64s: machine check interrupt update NMI accounting")
Signed-off-by: Ganesh Goudar <ganeshgr@linux.ibm.com>
---
arch/powerpc/kernel/mce.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
index ada59f6c4298..63702c0badb9 100644
--- a/arch/powerpc/kernel/mce.c
+++ b/arch/powerpc/kernel/mce.c
@@ -591,12 +591,11 @@ EXPORT_SYMBOL_GPL(machine_check_print_event_info);
long notrace machine_check_early(struct pt_regs *regs)
{
long handled = 0;
- bool nested = in_nmi();
u8 ftrace_enabled = this_cpu_get_ftrace_enabled();
this_cpu_set_ftrace_enabled(0);
-
- if (!nested)
+ /* Do not use nmi_enter/exit for pseries hpte guest */
+ if (radix_enabled() || !firmware_has_feature(FW_FEATURE_LPAR))
nmi_enter();
hv_nmi_check_nonrecoverable(regs);
@@ -607,7 +606,7 @@ long notrace machine_check_early(struct pt_regs *regs)
if (ppc_md.machine_check_early)
handled = ppc_md.machine_check_early(regs);
- if (!nested)
+ if (radix_enabled() || !firmware_has_feature(FW_FEATURE_LPAR))
nmi_exit();
this_cpu_set_ftrace_enabled(ftrace_enabled);
--
2.26.2
^ permalink raw reply related
* [PATCH v4 0/2] powerpc/mce: Fix mce handler and add selftest
From: Ganesh Goudar @ 2020-10-09 6:40 UTC (permalink / raw)
To: linuxppc-dev, mpe; +Cc: msuchanek, Ganesh Goudar, keescook, npiggin, mahesh
This patch series fixes mce handling for pseries, Adds LKDTM test
for SLB multihit recovery and enables selftest for the same,
basically to test MCE handling on pseries/powernv machines running
in hash mmu mode.
v4:
* Use radix_enabled() to check if its in Hash or Radix mode.
* Use FW_FEATURE_LPAR instead of machine_is_pseries().
v3:
* Merging selftest changes with patch 2/2, Instead of having separate
patch.
* Minor improvements like adding enough comments, Makefile changes,
including header file and adding some prints.
v2:
* Remove in_nmi check before calling nmi_enter/exit,
as nesting is supported.
* Fix build errors and remove unused variables.
* Integrate error injection code into LKDTM.
* Add support to inject multihit in paca.
Ganesh Goudar (2):
powerpc/mce: remove nmi_enter/exit from real mode handler
lkdtm/powerpc: Add SLB multihit test
arch/powerpc/kernel/mce.c | 7 +-
drivers/misc/lkdtm/Makefile | 1 +
drivers/misc/lkdtm/core.c | 3 +
drivers/misc/lkdtm/lkdtm.h | 3 +
drivers/misc/lkdtm/powerpc.c | 156 ++++++++++++++++++++++++
tools/testing/selftests/lkdtm/tests.txt | 1 +
6 files changed, 167 insertions(+), 4 deletions(-)
create mode 100644 drivers/misc/lkdtm/powerpc.c
--
2.26.2
^ permalink raw reply
* Re: [PATCH v3 1/2] powerpc/mce: remove nmi_enter/exit from real mode handler
From: Ganesh @ 2020-10-09 6:33 UTC (permalink / raw)
To: linuxppc-dev, mpe; +Cc: msuchanek, keescook, npiggin, mahesh
In-Reply-To: <20201001175144.286189-2-ganeshgr@linux.ibm.com>
On 10/1/20 11:21 PM, Ganesh Goudar wrote:
> Use of nmi_enter/exit in real mode handler causes the kernel to panic
> and reboot on injecting slb mutihit on pseries machine running in hash
> mmu mode, As these calls try to accesses memory outside RMO region in
> real mode handler where translation is disabled.
>
> Add check to not to use these calls on pseries machine running in hash
> mmu mode.
>
> Fixes: 116ac378bb3f ("powerpc/64s: machine check interrupt update NMI accounting")
> Signed-off-by: Ganesh Goudar <ganeshgr@linux.ibm.com>
> ---
> arch/powerpc/kernel/mce.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
> index ada59f6c4298..3bf39dd5dd43 100644
> --- a/arch/powerpc/kernel/mce.c
> +++ b/arch/powerpc/kernel/mce.c
> @@ -591,12 +591,14 @@ EXPORT_SYMBOL_GPL(machine_check_print_event_info);
> long notrace machine_check_early(struct pt_regs *regs)
> {
> long handled = 0;
> - bool nested = in_nmi();
> + bool is_pseries_hpt_guest;
> u8 ftrace_enabled = this_cpu_get_ftrace_enabled();
>
> this_cpu_set_ftrace_enabled(0);
> -
> - if (!nested)
> + is_pseries_hpt_guest = machine_is(pseries) &&
> + mmu_has_feature(MMU_FTR_HPTE_TABLE);
> + /* Do not use nmi_enter/exit for pseries hpte guest */
> + if (!is_pseries_hpt_guest)
In an offline discussion mpe suggested to use radix_enabled() to check if it is
radix or hash, as MMU_FTR_HPTE_TABLE may be true on radix machines also and use
of FW_FEATURE_LPAR better than machine_is(pseries), sending v4 with these changes.
> nmi_enter();
>
> hv_nmi_check_nonrecoverable(regs);
> @@ -607,7 +609,7 @@ long notrace machine_check_early(struct pt_regs *regs)
> if (ppc_md.machine_check_early)
> handled = ppc_md.machine_check_early(regs);
>
> - if (!nested)
> + if (!is_pseries_hpt_guest)
> nmi_exit();
>
> this_cpu_set_ftrace_enabled(ftrace_enabled);
^ permalink raw reply
* Re: [PATCH] powerpc/papr_scm: Add PAPR command family to pass-through command-set
From: Michael Ellerman @ 2020-10-09 6:04 UTC (permalink / raw)
To: linux-nvdimm, linuxppc-dev, Vaibhav Jain; +Cc: Aneesh Kumar K . V
In-Reply-To: <20200913211904.24472-1-vaibhav@linux.ibm.com>
On Mon, 14 Sep 2020 02:49:04 +0530, Vaibhav Jain wrote:
> Add NVDIMM_FAMILY_PAPR to the list of valid 'dimm_family_mask'
> acceptable by papr_scm. This is needed as since commit
> 92fe2aa859f5 ("libnvdimm: Validate command family indices") libnvdimm
> performs a validation of 'nd_cmd_pkg.nd_family' received as part of
> ND_CMD_CALL processing to ensure only known command families can use
> the general ND_CMD_CALL pass-through functionality.
>
> [...]
Applied to powerpc/next.
[1/1] powerpc/papr_scm: Add PAPR command family to pass-through command-set
https://git.kernel.org/powerpc/c/13135b461cf205941308984bd3271ec7d403dc40
cheers
^ permalink raw reply
* Re: [PATCH] cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_reboot_notifier
From: Michael Ellerman @ 2020-10-09 6:04 UTC (permalink / raw)
To: Michael Ellerman, Srikar Dronamraju
Cc: linuxppc-dev, Pratik Rajesh Sampat, Daniel Axtens
In-Reply-To: <20200922080254.41497-1-srikar@linux.vnet.ibm.com>
On Tue, 22 Sep 2020 13:32:54 +0530, Srikar Dronamraju wrote:
> The patch avoids allocating cpufreq_policy on stack hence fixing frame
> size overflow in 'powernv_cpufreq_reboot_notifier'
>
> ./drivers/cpufreq/powernv-cpufreq.c: In function _powernv_cpufreq_reboot_notifier_:
> ./drivers/cpufreq/powernv-cpufreq.c:906:1: error: the frame size of 2064 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]
> }
> ^
> cc1: all warnings being treated as errors
> make[3]: *** [./scripts/Makefile.build:316: drivers/cpufreq/powernv-cpufreq.o] Error 1
> make[2]: *** [./scripts/Makefile.build:556: drivers/cpufreq] Error 2
> make[1]: *** [./Makefile:1072: drivers] Error 2
> make[1]: *** Waiting for unfinished jobs....
> make: *** [Makefile:157: sub-make] Error 2
Applied to powerpc/next.
[1/1] cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_reboot_notifier
https://git.kernel.org/powerpc/c/a2d0230b91f7e23ceb5d8fb6a9799f30517ec33a
cheers
^ permalink raw reply
* Re: [PATCH 1/2] powerpc/eeh: Delete eeh_pe->config_addr
From: Michael Ellerman @ 2020-10-09 6:04 UTC (permalink / raw)
To: Oliver O'Halloran, linuxppc-dev
In-Reply-To: <20201007040903.819081-1-oohall@gmail.com>
On Wed, 7 Oct 2020 15:09:02 +1100, Oliver O'Halloran wrote:
> The eeh_pe->config_addr field was supposed to be removed in
> commit 35d64734b643 ("powerpc/eeh: Clean up PE addressing") which made it
> largely unused. Finish the job.
Applied to powerpc/next.
[1/2] powerpc/eeh: Delete eeh_pe->config_addr
https://git.kernel.org/powerpc/c/269e583357df32d77368903214f10f43fa5d7a5f
[2/2] powerpc/pseries/eeh: Fix use of uninitialised variable
https://git.kernel.org/powerpc/c/8175bd580e629dcf9cc507794da774a6b8d3a9bd
cheers
^ permalink raw reply
* Re: [PATCH] powerpc/security: Fix link stack flush instruction
From: Michael Ellerman @ 2020-10-09 6:04 UTC (permalink / raw)
To: linuxppc-dev, Nicholas Piggin
In-Reply-To: <20201007080605.64423-1-npiggin@gmail.com>
On Wed, 7 Oct 2020 18:06:05 +1000, Nicholas Piggin wrote:
> The inline execution path for the hardware assisted branch flush
> instruction failed to set CTR to the correct value before bcctr,
> causing a crash when the feature is enabled.
Applied to powerpc/next.
[1/1] powerpc/security: Fix link stack flush instruction
https://git.kernel.org/powerpc/c/792254a77201453d9a77479e63dc216ad90462d2
cheers
^ permalink raw reply
* Re: [PATCH 1/5] powerpc/hv-gpci: Fix starting index value
From: Michael Ellerman @ 2020-10-09 6:04 UTC (permalink / raw)
To: linuxppc-dev, Kajol Jain, mpe; +Cc: suka, maddy
In-Reply-To: <20201003074943.338618-1-kjain@linux.ibm.com>
On Sat, 3 Oct 2020 13:19:39 +0530, Kajol Jain wrote:
> Commit 9e9f60108423f ("powerpc/perf/{hv-gpci, hv-common}: generate
> requests with counters annotated") adds a framework for defining
> gpci counters.
> In this patch, they adds starting_index value as '0xffffffffffffffff'.
> which is wrong as starting_index is of size 32 bits.
>
> Because of this, incase we try to run hv-gpci event we get error.
>
> [...]
Applied to powerpc/next.
[1/5] powerpc/perf/hv-gpci: Fix starting index value
https://git.kernel.org/powerpc/c/0f9866f7e85765bbda86666df56c92f377c3bc10
[2/5] Documentation/ABI: Add ABI documentation for hv-24x7 format
https://git.kernel.org/powerpc/c/264a034099b6e3c76fae85e75329373f3652a033
[3/5] Documentation/ABI: Add ABI documentation for hv-gpci format
https://git.kernel.org/powerpc/c/435387dd1f6fc03c64e3fdb4cc8737904c08a4db
[4/5] powerpc/perf/hv-gpci: Add cpu hotplug support
https://git.kernel.org/powerpc/c/dcb5cdf60a1fbbdb3b4dd2abc562206481f09ef1
[5/5] powerpc/hv-gpci: Add sysfs files inside hv-gpci device to show cpumask
https://git.kernel.org/powerpc/c/09b791d95559ef82542063333ecaa2ac9d57118e
cheers
^ permalink raw reply
* Re: [PATCH v3 1/8] powerpc: Remove SYNC on non 6xx
From: Michael Ellerman @ 2020-10-09 6:04 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Christophe Leroy
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <27951fa6c9a8f80724d1bc81a6117ac32343a55d.1601362098.git.christophe.leroy@csgroup.eu>
On Tue, 29 Sep 2020 06:48:31 +0000 (UTC), Christophe Leroy wrote:
> SYNC is usefull for Powerpc 601 only. On everything else,
> SYNC is empty.
>
> Remove it from code that is not made to run on 6xx.
Applied to powerpc/next.
[1/8] powerpc: Remove SYNC on non 6xx
https://git.kernel.org/powerpc/c/ca1d3443b4dd1e8f152bd6c881ddb3eb2996179a
[2/8] powerpc: Remove CONFIG_PPC601_SYNC_FIX
https://git.kernel.org/powerpc/c/e42a64002a507bf61e57106ed5323b1854371563
[3/8] powerpc: Drop SYNC_601() ISYNC_601() and SYNC()
https://git.kernel.org/powerpc/c/d2a5cd83ee984c0e9fc172d2df9591c264261a52
[4/8] powerpc: Remove PowerPC 601
https://git.kernel.org/powerpc/c/f0ed73f3fa2cdca65973659689ec9e46d99a5f60
[5/8] powerpc: Remove support for PowerPC 601
https://git.kernel.org/powerpc/c/8b14e1dff067195dca7a42321771437cb33a99e9
[6/8] powerpc: Tidy up a bit after removal of PowerPC 601.
https://git.kernel.org/powerpc/c/2e38ea486615bddbc7a42d002aee93a3a9e7a36f
[7/8] powerpc: Remove __USE_RTC()
https://git.kernel.org/powerpc/c/a4c5a355422920bcbfe3fd1f01aead2d3a2a820c
[8/8] powerpc: Remove get_tb_or_rtc()
https://git.kernel.org/powerpc/c/6601ec1c2ba929430f5585ce7f9d9960b0e0a01d
cheers
^ permalink raw reply
* Re: [PATCH] powerpc/time: Remove ifdef in get_dec() and set_dec()
From: Michael Ellerman @ 2020-10-09 6:04 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Christophe Leroy
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <3c9a6eb0fc040868ac59be66f338d08fd017668d.1601549945.git.christophe.leroy@csgroup.eu>
On Thu, 1 Oct 2020 10:59:19 +0000 (UTC), Christophe Leroy wrote:
> Move SPRN_PIT definition in reg.h.
>
> This allows to remove ifdef in get_dec() and set_dec() and
> makes them more readable.
Applied to powerpc/next.
[1/1] powerpc/time: Remove ifdef in get_dec() and set_dec()
https://git.kernel.org/powerpc/c/63f9d9df5ed0d4f3a2c0cd08730e1cae1edd11bf
cheers
^ permalink raw reply
* Re: [PATCH] powerpc/32s: Setup the early hash table at all time.
From: Michael Ellerman @ 2020-10-09 6:03 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Christophe Leroy
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <b8f8101c368b8a6451844a58d7bd7d83c14cf2aa.1601566529.git.christophe.leroy@csgroup.eu>
On Thu, 1 Oct 2020 15:35:38 +0000 (UTC), Christophe Leroy wrote:
> At the time being, an early hash table is set up when
> CONFIG_KASAN is selected.
>
> There is nothing wrong with setting such an early hash table
> all the time, even if it is not used. This is a statically
> allocated 256 kB table which lies in the init data section.
>
> [...]
Applied to powerpc/next.
[1/1] powerpc/32s: Setup the early hash table at all time.
https://git.kernel.org/powerpc/c/69a1593abdbcf03a76367320d929a8ae7a5e3d71
cheers
^ permalink raw reply
* Re: [PATCH 1/6] powerpc/time: Rename mftbl() to mftb()
From: Michael Ellerman @ 2020-10-09 6:03 UTC (permalink / raw)
To: Paul Mackerras, Benjamin Herrenschmidt, Michael Ellerman,
Christophe Leroy
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <94dc68d3d9ef9eb549796d4b938b6ba0305a049b.1601556145.git.christophe.leroy@csgroup.eu>
On Thu, 1 Oct 2020 12:42:39 +0000 (UTC), Christophe Leroy wrote:
> On PPC64, we have mftb().
> On PPC32, we have mftbl() and an #define mftb() mftbl().
>
> mftb() and mftbl() are equivalent, their purpose is to read the
> content of SPRN_TRBL, as returned by 'mftb' simplified instruction.
>
> binutils seems to define 'mftbl' instruction as an equivalent
> of 'mftb'.
>
> [...]
Applied to powerpc/next.
[1/6] powerpc/time: Rename mftbl() to mftb()
https://git.kernel.org/powerpc/c/15c102153e722cc6e0729764a7068c209a7469cd
[2/6] powerpc/time: Make mftb() common to PPC32 and PPC64
https://git.kernel.org/powerpc/c/ff125fbcd45d1706861579dbe66e31f5b3f1e779
[3/6] powerpc/time: Avoid using get_tbl() and get_tbu() internally
https://git.kernel.org/powerpc/c/942e89115b588b4b5df86930b5302a5c07b820ba
[4/6] powerpc/time: Remove get_tbu()
https://git.kernel.org/powerpc/c/e8d5bf30eafc37e31ce68bc7ccf1db970fe3cd04
[5/6] powerpc/time: Make get_tbl() common to PPC32 and PPC64
https://git.kernel.org/powerpc/c/1156a6285cd38e5a6987ddee3758e7954c56cb3d
[6/6] powerpc/time: Make get_tb() common to PPC32 and PPC64
https://git.kernel.org/powerpc/c/9686e431c683ee7b8aca0f3985c244aee3d9f30d
cheers
^ permalink raw reply
* Re: [PATCH 1/2] powerpc/32s: Rename head_32.S to head_book3s_32.S
From: Michael Ellerman @ 2020-10-09 6:03 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Christophe Leroy
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <319d379f696412681c66a987cc75e6abf8f958d2.1601975100.git.christophe.leroy@csgroup.eu>
On Tue, 6 Oct 2020 09:05:26 +0000 (UTC), Christophe Leroy wrote:
> Unlike PPC64 which had a single head_64.S, PPC32 are multiple ones.
> There is the head_32.S, selected by default based on the value of BITS
> and overridden based on some CONFIG_ values. This leads to thinking
> that it may be selected by different types of PPC32 platform but
> indeed it ends up being selected by book3s/32 only.
>
> Make that explicit by:
> - Not doing any default selection based on BITS.
> - Renaming head_32.S to head_book3s_32.S.
> - Get head_book3s_32.S selected only by CONFIG_PPC_BOOK3S_32.
Applied to powerpc/next.
[1/2] powerpc/32s: Rename head_32.S to head_book3s_32.S
https://git.kernel.org/powerpc/c/533090e5a980ad80bbe0961b4ed45a9bcf55cc0c
[2/2] powerpc/32s: Remove #ifdef CONFIG_PPC_BOOK3S_32 in head_book3s_32.S
https://git.kernel.org/powerpc/c/865418795a1dea1c2b58a5fd7b6bdcb93e0c36b8
cheers
^ permalink raw reply
* Re: [PATCH v3 0/4] Enable usage of larger LMB ( > 4G)
From: Michael Ellerman @ 2020-10-09 6:03 UTC (permalink / raw)
To: Aneesh Kumar K.V, linuxppc-dev, mpe; +Cc: nathanl
In-Reply-To: <20201007114836.282468-1-aneesh.kumar@linux.ibm.com>
On Wed, 7 Oct 2020 17:18:32 +0530, Aneesh Kumar K.V wrote:
> Changes from v2:
> * Don't use root addr and size cells during runtime. Walk up the
> device tree and use the first addr and size cells value (of_n_addr_cells()/
> of_n_size_cells())
>
> Aneesh Kumar K.V (4):
> powerpc/drmem: Make lmb_size 64 bit
> powerpc/memhotplug: Make lmb size 64bit
> powerpc/book3s64/radix: Make radix_mem_block_size 64bit
> powerpc/lmb-size: Use addr #size-cells value when fetching lmb-size
>
> [...]
Applied to powerpc/next.
[1/4] powerpc/drmem: Make lmb_size 64 bit
https://git.kernel.org/powerpc/c/ec72024e35dddb88a81e40071c87ceb18b5ee835
[2/4] powerpc/memhotplug: Make lmb size 64bit
https://git.kernel.org/powerpc/c/301d2ea6572386245c5d2d2dc85c3b5a737b85ac
[3/4] powerpc/book3s64/radix: Make radix_mem_block_size 64bit
https://git.kernel.org/powerpc/c/950805f4d90eda14325ceab56b0f00d034baa8bc
[4/4] powerpc/lmb-size: Use addr #size-cells value when fetching lmb-size
https://git.kernel.org/powerpc/c/fbf2f134c8c312d3166534a8bd6a1aaee6e9c7ef
cheers
^ permalink raw reply
* [PATCH] powerpc/8xx: Fix instruction TLB miss exception with perf enabled
From: Christophe Leroy @ 2020-10-09 5:36 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
When perf is enabled, r11 must also be restored when CONFIG_HUGETLBFS
is selected.
Fixes: a891c43b97d3 ("powerpc/8xx: Prepare handlers for _PAGE_HUGE for 512k pages.")
Cc: stable@vger.kernel.org
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
arch/powerpc/kernel/head_8xx.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 9f359d3fba74..32d85387bdc5 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -268,7 +268,7 @@ InstructionTLBMiss:
addi r10, r10, 1
stw r10, (itlb_miss_counter - PAGE_OFFSET)@l(0)
mfspr r10, SPRN_SPRG_SCRATCH0
-#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP)
+#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP) || defined(CONFIG_HUGETLBFS)
mfspr r11, SPRN_SPRG_SCRATCH1
#endif
rfi
--
2.25.0
^ permalink raw reply related
* Re: [PATCH] powerpc/powernv/dump: Fix race while processing OPAL dump
From: Michael Ellerman @ 2020-10-09 5:06 UTC (permalink / raw)
To: Vasant Hegde, linuxppc-dev; +Cc: Vasant Hegde, Mahesh Salgaonkar
In-Reply-To: <20201007101742.40757-1-hegdevasant@linux.vnet.ibm.com>
Vasant Hegde <hegdevasant@linux.vnet.ibm.com> writes:
> diff --git a/arch/powerpc/platforms/powernv/opal-dump.c b/arch/powerpc/platforms/powernv/opal-dump.c
> index 543c816fa99e..7e6eeedec32b 100644
> --- a/arch/powerpc/platforms/powernv/opal-dump.c
> +++ b/arch/powerpc/platforms/powernv/opal-dump.c
> @@ -346,21 +345,39 @@ static struct dump_obj *create_dump_obj(uint32_t id, size_t size,
> rc = kobject_add(&dump->kobj, NULL, "0x%x-0x%x", type, id);
> if (rc) {
> kobject_put(&dump->kobj);
> - return NULL;
> + return;
> }
>
> + /*
> + * As soon as the sysfs file for this dump is created/activated there is
> + * a chance the opal_errd daemon (or any userspace) might read and
> + * acknowledge the dump before kobject_uevent() is called. If that
> + * happens then there is a potential race between
> + * dump_ack_store->kobject_put() and kobject_uevent() which leads to a
> + * use-after-free of a kernfs object resulting in a kernel crash.
> + *
> + * To avoid that, we need to take a reference on behalf of the bin file,
> + * so that our reference remains valid while we call kobject_uevent().
> + * We then drop our reference before exiting the function, leaving the
> + * bin file to drop the last reference (if it hasn't already).
> + */
> +
> + /* Take a reference for the bin file */
> + kobject_get(&dump->kobj);
> rc = sysfs_create_bin_file(&dump->kobj, &dump->dump_attr);
> if (rc) {
> kobject_put(&dump->kobj);
> - return NULL;
> + /* Drop reference count taken for bin file */
> + kobject_put(&dump->kobj);
> + return;
> }
>
> pr_info("%s: New platform dump. ID = 0x%x Size %u\n",
> __func__, dump->id, dump->size);
>
> kobject_uevent(&dump->kobj, KOBJ_ADD);
> -
> - return dump;
> + /* Drop reference count taken for bin file */
> + kobject_put(&dump->kobj);
> }
I think this would be better if it was reworked along the lines of:
aea948bb80b4 ("powerpc/powernv/elog: Fix race while processing OPAL error log event.")
cheers
^ permalink raw reply
* Re: [PATCH] powerpc/powernv/elog: Reduce elog message severity
From: Michael Ellerman @ 2020-10-09 5:04 UTC (permalink / raw)
To: Vasant Hegde, linuxppc-dev; +Cc: Vasant Hegde, Mahesh Salgaonkar
In-Reply-To: <20201007101756.40811-1-hegdevasant@linux.vnet.ibm.com>
Vasant Hegde <hegdevasant@linux.vnet.ibm.com> writes:
> OPAL interrupts kernel whenever it has new error log. Kernel calls
> interrupt handler (elog_event()) to retrieve event. elog_event makes
> OPAL API call (opal_get_elog_size()) to retrieve elog info.
>
> In some case before kernel makes opal_get_elog_size() call, it gets interrupt
> again. So second time when elog_event() calls opal_get_elog_size API OPAL
> returns error.
Can you give more detail there? Do you have a stack trace?
We use IRQF_ONESHOT for elog_event(), which (I thought) meant it
shouldn't be called again until it has completed.
So I'm unclear how you're seeing the behaviour you describe.
cheers
> Its safe to ignore this error. Hence reduce the severity
> of log message.
>
> CC: Mahesh Salgaonkar <mahesh@linux.ibm.com>
> Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
> ---
> arch/powerpc/platforms/powernv/opal-elog.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/platforms/powernv/opal-elog.c b/arch/powerpc/platforms/powernv/opal-elog.c
> index 62ef7ad995da..67f435bb1ec4 100644
> --- a/arch/powerpc/platforms/powernv/opal-elog.c
> +++ b/arch/powerpc/platforms/powernv/opal-elog.c
> @@ -247,7 +247,7 @@ static irqreturn_t elog_event(int irq, void *data)
>
> rc = opal_get_elog_size(&id, &size, &type);
> if (rc != OPAL_SUCCESS) {
> - pr_err("ELOG: OPAL log info read failed\n");
> + pr_debug("ELOG: OPAL log info read failed\n");
> return IRQ_HANDLED;
> }
>
> --
> 2.26.2
^ permalink raw reply
* Re: linux-next: Fixes tag needs some work in the powerpc tree
From: Michael Ellerman @ 2020-10-09 4:27 UTC (permalink / raw)
To: Stephen Rothwell, PowerPC
Cc: Linux Next Mailing List, Srikar Dronamraju,
Linux Kernel Mailing List
In-Reply-To: <20201009075816.0cb5a86f@canb.auug.org.au>
Stephen Rothwell <sfr@canb.auug.org.au> writes:
> Hi all,
>
> In commit
>
> a2d0230b91f7 ("cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_reboot_notifier")
>
> Fixes tag
>
> Fixes: cf30af76 ("cpufreq: powernv: Set the cpus to nominal frequency during reboot/kexec")
Gah.
I've changed my scripts to make this a hard error when I'm applying
patches.
cheers
^ permalink raw reply
* Re: [PATCH 2/2] dt: Remove booting-without-of.rst
From: Michael Ellerman @ 2020-10-09 3:51 UTC (permalink / raw)
To: Rob Herring, devicetree
Cc: Thomas Bogendoerfer, Yoshinori Sato, Geert Uytterhoeven,
Jonathan Corbet, linux-sh, linuxppc-dev, x86, linux-doc,
linux-kernel, linux-mips, Rich Felker, Paul Mackerras,
H. Peter Anvin, Borislav Petkov, Thomas Gleixner,
Mauro Carvalho Chehab, Frank Rowand, Ingo Molnar
In-Reply-To: <20201008142420.2083861-2-robh@kernel.org>
Rob Herring <robh@kernel.org> writes:
> booting-without-of.rstt is an ancient document that first outlined
^
nit
> Flattened DeviceTree on PowerPC initially. The DT world has evolved a
> lot in the 15 years since and booting-without-of.rst is pretty stale.
> The name of the document itself is confusing if you don't understand the
> evolution from real 'OpenFirmware'. Most of what booting-without-of.rst
> contains is now in the DT specification (which evolved out of the
> ePAPR). The few things that weren't documented in the DT specification
> are now.
>
> All that remains is the boot entry details, so let's move these to arch
> specific documents. The exception is arm which already has the same
> details documented.
>
> Cc: Frank Rowand <frowand.list@gmail.com>
> Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
> Cc: Rich Felker <dalias@libc.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: x86@kernel.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-mips@vger.kernel.org
> Cc: linux-doc@vger.kernel.org
> Cc: linux-sh@vger.kernel.org
> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Signed-off-by: Rob Herring <robh@kernel.org>
> ---
> .../devicetree/booting-without-of.rst | 1585 -----------------
> Documentation/devicetree/index.rst | 1 -
> Documentation/mips/booting.rst | 28 +
> Documentation/mips/index.rst | 1 +
> Documentation/powerpc/booting.rst | 110 ++
LGTM.
Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
cheers
^ permalink raw reply
* [powerpc:next] BUILD SUCCESS a2d0230b91f7e23ceb5d8fb6a9799f30517ec33a
From: kernel test robot @ 2020-10-09 1:32 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
branch HEAD: a2d0230b91f7e23ceb5d8fb6a9799f30517ec33a cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_reboot_notifier
elapsed time: 870m
configs tested: 215
configs skipped: 2
The following configs have been built successfully.
More configs may be tested in the coming days.
gcc tested configs:
arm defconfig
arm64 allyesconfig
arm64 defconfig
arm allyesconfig
arm allmodconfig
arm colibri_pxa300_defconfig
m68k m5475evb_defconfig
mips fuloong2e_defconfig
arm exynos_defconfig
mips bigsur_defconfig
powerpc eiger_defconfig
mips rbtx49xx_defconfig
arm tegra_defconfig
powerpc icon_defconfig
powerpc mpc885_ads_defconfig
mips bmips_stb_defconfig
arm footbridge_defconfig
sh ap325rxa_defconfig
powerpc xes_mpc85xx_defconfig
m68k m5307c3_defconfig
arm mxs_defconfig
h8300 defconfig
nios2 defconfig
xtensa generic_kc705_defconfig
sh secureedge5410_defconfig
sh apsh4ad0a_defconfig
arm multi_v4t_defconfig
m68k sun3_defconfig
sh rsk7203_defconfig
sh kfr2r09-romimage_defconfig
c6x evmc6678_defconfig
powerpc ppc64e_defconfig
powerpc warp_defconfig
sh polaris_defconfig
arm sama5_defconfig
powerpc bamboo_defconfig
sh ecovec24_defconfig
m68k allmodconfig
arm ezx_defconfig
powerpc tqm8540_defconfig
arm imx_v6_v7_defconfig
arm pxa255-idp_defconfig
powerpc stx_gp3_defconfig
powerpc maple_defconfig
sh urquell_defconfig
powerpc mpc834x_itxgp_defconfig
powerpc ps3_defconfig
arm h3600_defconfig
powerpc mpc512x_defconfig
parisc allyesconfig
arm omap2plus_defconfig
m68k apollo_defconfig
powerpc g5_defconfig
mips ath25_defconfig
sh landisk_defconfig
mips decstation_defconfig
sparc defconfig
powerpc pseries_defconfig
arm netwinder_defconfig
arm ep93xx_defconfig
i386 alldefconfig
powerpc mpc834x_itx_defconfig
powerpc powernv_defconfig
powerpc mgcoge_defconfig
m68k mvme16x_defconfig
arc vdk_hs38_smp_defconfig
arc axs103_defconfig
powerpc storcenter_defconfig
sh dreamcast_defconfig
m68k m5275evb_defconfig
powerpc ppa8548_defconfig
openrisc or1ksim_defconfig
sh rsk7201_defconfig
riscv allnoconfig
arm pxa_defconfig
mips mtx1_defconfig
mips malta_defconfig
c6x allyesconfig
powerpc pmac32_defconfig
mips malta_kvm_defconfig
sh se7721_defconfig
arc haps_hs_smp_defconfig
sh r7780mp_defconfig
sh r7785rp_defconfig
um i386_defconfig
powerpc tqm8548_defconfig
sh se7712_defconfig
mips mpc30x_defconfig
powerpc kilauea_defconfig
powerpc makalu_defconfig
arm qcom_defconfig
arm rpc_defconfig
c6x alldefconfig
arm integrator_defconfig
sh sh7757lcr_defconfig
arm assabet_defconfig
sparc sparc32_defconfig
h8300 alldefconfig
arm viper_defconfig
powerpc ppc44x_defconfig
h8300 h8s-sim_defconfig
m68k m5249evb_defconfig
xtensa smp_lx200_defconfig
arm keystone_defconfig
arm cm_x300_defconfig
mips db1xxx_defconfig
powerpc ppc6xx_defconfig
riscv defconfig
powerpc ge_imp3a_defconfig
arm axm55xx_defconfig
powerpc ep88xc_defconfig
powerpc gamecube_defconfig
powerpc mpc832x_rdb_defconfig
arm aspeed_g5_defconfig
mips cu1000-neo_defconfig
sh se7619_defconfig
arm nhk8815_defconfig
i386 allyesconfig
arm bcm2835_defconfig
sh espt_defconfig
mips loongson3_defconfig
mips ip28_defconfig
arm shmobile_defconfig
powerpc arches_defconfig
powerpc ksi8560_defconfig
arm davinci_all_defconfig
powerpc allyesconfig
mips decstation_64_defconfig
powerpc kmeter1_defconfig
powerpc obs600_defconfig
mips capcella_defconfig
ia64 allmodconfig
ia64 defconfig
ia64 allyesconfig
m68k defconfig
m68k allyesconfig
arc allyesconfig
nds32 allnoconfig
nds32 defconfig
nios2 allyesconfig
csky defconfig
alpha defconfig
alpha allyesconfig
xtensa allyesconfig
h8300 allyesconfig
arc defconfig
sh allmodconfig
parisc defconfig
s390 allyesconfig
s390 defconfig
sparc allyesconfig
i386 defconfig
mips allyesconfig
mips allmodconfig
powerpc allmodconfig
powerpc allnoconfig
x86_64 randconfig-a004-20201008
x86_64 randconfig-a003-20201008
x86_64 randconfig-a005-20201008
x86_64 randconfig-a001-20201008
x86_64 randconfig-a002-20201008
x86_64 randconfig-a006-20201008
i386 randconfig-a006-20201008
i386 randconfig-a005-20201008
i386 randconfig-a001-20201008
i386 randconfig-a004-20201008
i386 randconfig-a002-20201008
i386 randconfig-a003-20201008
i386 randconfig-a006-20201009
i386 randconfig-a005-20201009
i386 randconfig-a001-20201009
i386 randconfig-a004-20201009
i386 randconfig-a002-20201009
i386 randconfig-a003-20201009
x86_64 randconfig-a012-20201009
x86_64 randconfig-a015-20201009
x86_64 randconfig-a013-20201009
x86_64 randconfig-a014-20201009
x86_64 randconfig-a011-20201009
x86_64 randconfig-a016-20201009
i386 randconfig-a015-20201009
i386 randconfig-a013-20201009
i386 randconfig-a014-20201009
i386 randconfig-a016-20201009
i386 randconfig-a011-20201009
i386 randconfig-a012-20201009
i386 randconfig-a015-20201008
i386 randconfig-a013-20201008
i386 randconfig-a014-20201008
i386 randconfig-a016-20201008
i386 randconfig-a011-20201008
i386 randconfig-a012-20201008
riscv nommu_k210_defconfig
riscv allyesconfig
riscv nommu_virt_defconfig
riscv rv32_defconfig
riscv allmodconfig
x86_64 rhel
x86_64 allyesconfig
x86_64 rhel-7.6-kselftests
x86_64 defconfig
x86_64 rhel-8.3
x86_64 kexec
clang tested configs:
x86_64 randconfig-a004-20201009
x86_64 randconfig-a003-20201009
x86_64 randconfig-a005-20201009
x86_64 randconfig-a001-20201009
x86_64 randconfig-a002-20201009
x86_64 randconfig-a006-20201009
x86_64 randconfig-a012-20201008
x86_64 randconfig-a015-20201008
x86_64 randconfig-a013-20201008
x86_64 randconfig-a014-20201008
x86_64 randconfig-a011-20201008
x86_64 randconfig-a016-20201008
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply
* [powerpc:merge] BUILD SUCCESS 118be7377c97e35c33819bcb3bbbae5a42a4ac43
From: kernel test robot @ 2020-10-09 1:32 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git merge
branch HEAD: 118be7377c97e35c33819bcb3bbbae5a42a4ac43 Automatic merge of 'next' into merge (2020-10-08 21:55)
elapsed time: 871m
configs tested: 176
configs skipped: 2
The following configs have been built successfully.
More configs may be tested in the coming days.
gcc tested configs:
arm defconfig
arm64 allyesconfig
arm64 defconfig
arm allyesconfig
arm allmodconfig
arm colibri_pxa300_defconfig
m68k m5475evb_defconfig
mips fuloong2e_defconfig
arm exynos_defconfig
mips bigsur_defconfig
powerpc eiger_defconfig
mips rbtx49xx_defconfig
arm tegra_defconfig
powerpc icon_defconfig
powerpc mpc885_ads_defconfig
mips bmips_stb_defconfig
arm footbridge_defconfig
sh ap325rxa_defconfig
powerpc xes_mpc85xx_defconfig
m68k m5307c3_defconfig
arm mxs_defconfig
h8300 defconfig
xtensa generic_kc705_defconfig
sh secureedge5410_defconfig
sh apsh4ad0a_defconfig
arm multi_v4t_defconfig
m68k sun3_defconfig
sh rsk7203_defconfig
sh kfr2r09-romimage_defconfig
c6x evmc6678_defconfig
powerpc ppc64e_defconfig
powerpc warp_defconfig
m68k allmodconfig
arm ezx_defconfig
powerpc tqm8540_defconfig
powerpc maple_defconfig
sh urquell_defconfig
powerpc mpc834x_itxgp_defconfig
powerpc ps3_defconfig
arm h3600_defconfig
powerpc mpc512x_defconfig
parisc allyesconfig
arm omap2plus_defconfig
m68k apollo_defconfig
powerpc g5_defconfig
mips ath25_defconfig
sh landisk_defconfig
mips decstation_defconfig
sparc defconfig
powerpc pseries_defconfig
arm netwinder_defconfig
arm ep93xx_defconfig
i386 alldefconfig
powerpc mpc834x_itx_defconfig
powerpc powernv_defconfig
powerpc mgcoge_defconfig
arm pxa_defconfig
mips mtx1_defconfig
mips malta_defconfig
powerpc pmac32_defconfig
arc haps_hs_smp_defconfig
sh r7780mp_defconfig
sh r7785rp_defconfig
um i386_defconfig
powerpc tqm8548_defconfig
sh se7712_defconfig
mips mpc30x_defconfig
powerpc kilauea_defconfig
powerpc makalu_defconfig
arm qcom_defconfig
arm rpc_defconfig
c6x alldefconfig
arm integrator_defconfig
sh sh7757lcr_defconfig
arm assabet_defconfig
sparc sparc32_defconfig
h8300 alldefconfig
arm viper_defconfig
powerpc ppc44x_defconfig
h8300 h8s-sim_defconfig
m68k m5249evb_defconfig
xtensa smp_lx200_defconfig
arm keystone_defconfig
powerpc ppc6xx_defconfig
riscv defconfig
powerpc ge_imp3a_defconfig
arm axm55xx_defconfig
powerpc ep88xc_defconfig
powerpc gamecube_defconfig
arm bcm2835_defconfig
sh espt_defconfig
mips loongson3_defconfig
powerpc cm5200_defconfig
sh sh7770_generic_defconfig
arm spitz_defconfig
arm iop32x_defconfig
mips ip28_defconfig
arm shmobile_defconfig
powerpc arches_defconfig
powerpc ksi8560_defconfig
powerpc ppa8548_defconfig
powerpc obs600_defconfig
mips capcella_defconfig
powerpc kmeter1_defconfig
openrisc or1ksim_defconfig
ia64 allmodconfig
ia64 defconfig
ia64 allyesconfig
m68k defconfig
m68k allyesconfig
nios2 defconfig
arc allyesconfig
nds32 allnoconfig
c6x allyesconfig
nds32 defconfig
nios2 allyesconfig
csky defconfig
alpha defconfig
alpha allyesconfig
xtensa allyesconfig
h8300 allyesconfig
arc defconfig
sh allmodconfig
parisc defconfig
s390 allyesconfig
s390 defconfig
i386 allyesconfig
sparc allyesconfig
i386 defconfig
mips allyesconfig
mips allmodconfig
powerpc allyesconfig
powerpc allmodconfig
powerpc allnoconfig
x86_64 randconfig-a004-20201008
x86_64 randconfig-a003-20201008
x86_64 randconfig-a005-20201008
x86_64 randconfig-a001-20201008
x86_64 randconfig-a002-20201008
x86_64 randconfig-a006-20201008
i386 randconfig-a006-20201008
i386 randconfig-a005-20201008
i386 randconfig-a001-20201008
i386 randconfig-a004-20201008
i386 randconfig-a002-20201008
i386 randconfig-a003-20201008
x86_64 randconfig-a012-20201009
x86_64 randconfig-a015-20201009
x86_64 randconfig-a013-20201009
x86_64 randconfig-a014-20201009
x86_64 randconfig-a011-20201009
x86_64 randconfig-a016-20201009
i386 randconfig-a015-20201008
i386 randconfig-a013-20201008
i386 randconfig-a014-20201008
i386 randconfig-a016-20201008
i386 randconfig-a011-20201008
i386 randconfig-a012-20201008
riscv nommu_k210_defconfig
riscv allyesconfig
riscv nommu_virt_defconfig
riscv allnoconfig
riscv rv32_defconfig
riscv allmodconfig
x86_64 rhel
x86_64 allyesconfig
x86_64 rhel-7.6-kselftests
x86_64 defconfig
x86_64 rhel-8.3
x86_64 kexec
clang tested configs:
x86_64 randconfig-a012-20201008
x86_64 randconfig-a015-20201008
x86_64 randconfig-a013-20201008
x86_64 randconfig-a014-20201008
x86_64 randconfig-a011-20201008
x86_64 randconfig-a016-20201008
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply
* Linux kernel: powerpc: RTAS calls can be used to compromise kernel integrity
From: Andrew Donnellan @ 2020-10-09 1:20 UTC (permalink / raw)
To: oss-security, linuxppc-dev
The Linux kernel for powerpc has an issue with the Run-Time Abstraction
Services (RTAS) interface, allowing root (or CAP_SYS_ADMIN users) in a
VM to overwrite some parts of memory, including kernel memory.
This issue impacts guests running on top of PowerVM or KVM hypervisors
(pseries platform), and does *not* impact bare-metal machines (powernv
platform).
Description
===========
The RTAS interface, defined in the Power Architecture Platform
Reference, provides various platform hardware services to operating
systems running on PAPR platforms (e.g. the "pseries" platform in Linux,
running in a LPAR/VM on PowerVM or KVM).
Some userspace daemons require access to certain RTAS calls for system
maintenance and monitoring purposes.
The kernel exposes a syscall, sys_rtas, that allows root (or any user
with CAP_SYS_ADMIN) to make arbitrary RTAS calls. For the RTAS calls
which require a work area, it allocates a buffer (the "RMO buffer") and
exposes the physical address in /proc so that the userspace tool can
pass addresses within that buffer as an argument to the RTAS call.
The syscall doesn't check that the work area arguments to RTAS calls are
within the RMO buffer, which makes it trivial to read and write to any
guest physical address within the LPAR's Real Memory Area, including
overwriting the guest kernel's text.
At the time the RTAS syscall interface was first developed, it was
generally assumed that root had unlimited ability to modify system
state, so this would not have been considered an integrity violation.
However, with the advent of Secure Boot, Lockdown etc, root should not
be able to arbitrarily modify the kernel text or read arbitrary kernel data.
Therefore, while this issue impacts all kernels since the RTAS interface
was first implemented, we are only considering it a vulnerability for
upstream kernels from 5.3 onwards, which is when the Lockdown LSM was
merged. Lockdown was widely included in pre-5.3 distribution kernels, so
distribution vendors should consider whether they need to backport the
patch to their pre-5.3 distro trees.
(A CVE for this issue is pending; we requested one some time ago but it
has not yet been assigned.)
Fixes
=====
A patch is currently in powerpc-next[0] and is expected to be included
in mainline kernel 5.10. The patch has not yet been backported to
upstream stable trees.
The approach taken by the patch is to maintain the existing RTAS
interface, but restrict requests to the list of RTAS calls actually used
by the librtas userspace library, and restrict work area pointer
arguments to the region within the RMO buffer.
All RTAS-using applications that we are aware of are system
management/monitoring tools, maintained by IBM, that use the librtas
library. We don't anticipate there being any real world legitimate
applications that require an RTAS call that isn't in the librtas list,
however if such an application exists, the filtering can be disabled by
a Kconfig option specified during kernel build.
Credit
======
Thanks to Daniel Axtens (IBM) for initial discovery of this issue.
[0]
https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/commit/?h=next&id=bd59380c5ba4147dcbaad3e582b55ccfd120b764
--
Andrew Donnellan OzLabs, ADL Canberra
ajd@linux.ibm.com IBM Australia Limited
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).