Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
# SPDX-License-Identifier: GPL-2.0
#
# asm headers that all architectures except um should have
# (This file is not included when SRCARCH=um since UML borrows several
# asm headers from the host architecture.)
mandatory-y += atomic.h
mandatory-y += archrandom.h
mandatory-y += barrier.h
mandatory-y += bitops.h
mandatory-y += bug.h
mandatory-y += cacheflush.h
mandatory-y += cfi.h
mandatory-y += checksum.h
mandatory-y += compat.h
mandatory-y += current.h
mandatory-y += delay.h
mandatory-y += device.h
mandatory-y += div64.h
mandatory-y += dma-mapping.h
mandatory-y += dma.h
mandatory-y += emergency-restart.h
mandatory-y += exec.h
mandatory-y += ftrace.h
mandatory-y += futex.h
mandatory-y += hardirq.h
mandatory-y += hw_irq.h
mandatory-y += io.h
mandatory-y += irq.h
mandatory-y += irq_regs.h
mandatory-y += irq_work.h
mandatory-y += kdebug.h
mandatory-y += kmap_size.h
mandatory-y += kprobes.h
mandatory-y += kvm_types.h
mandatory-y += linkage.h
mandatory-y += local.h
mandatory-y += local64.h
mandatory-y += mmiowb.h
mandatory-y += mmu.h
mandatory-y += mmu_context.h
mandatory-y += module.h
mandatory-y += module.lds.h
mandatory-y += msi.h
mandatory-y += pci.h
mandatory-y += percpu.h
mandatory-y += percpu_types.h
mandatory-y += pgalloc.h
mandatory-y += preempt.h
mandatory-y += rqspinlock.h
mandatory-y += runtime-const.h
mandatory-y += rwonce.h
mandatory-y += sections.h
mandatory-y += serial.h
mandatory-y += shmparam.h
mandatory-y += simd.h
mandatory-y += softirq_stack.h
mandatory-y += switch_to.h
mandatory-y += timex.h
mandatory-y += tlbflush.h
mandatory-y += topology.h
mandatory-y += trace_clock.h
mandatory-y += uaccess.h
mandatory-y += unwind_user.h
mandatory-y += vermagic.h
mandatory-y += vga.h
mandatory-y += video.h
mandatory-y += word-at-a-time.h
@@ -0,0 +1,48 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_ACCESS_OK_H__
#define __ASM_GENERIC_ACCESS_OK_H__
/*
* Checking whether a pointer is valid for user space access.
* These definitions work on most architectures, but overrides can
* be used where necessary.
*/
/*
* architectures with compat tasks have a variable TASK_SIZE and should
* override this to a constant.
*/
#ifndef TASK_SIZE_MAX
#define TASK_SIZE_MAX TASK_SIZE
#endif
#ifndef __access_ok
/*
* 'size' is a compile-time constant for most callers, so optimize for
* this case to turn the check into a single comparison against a constant
* limit and catch all possible overflows.
* On architectures with separate user address space (m68k, s390, parisc,
* sparc64) or those without an MMU, this should always return true.
*
* This version was originally contributed by Jonas Bonn for the
* OpenRISC architecture, and was found to be the most efficient
* for constant 'size' and 'limit' values.
*/
static inline int __access_ok(const void __user *ptr, unsigned long size)
{
unsigned long limit = TASK_SIZE_MAX;
unsigned long addr = (unsigned long)ptr;
if (IS_ENABLED(CONFIG_ALTERNATE_USER_ADDRESS_SPACE) ||
!IS_ENABLED(CONFIG_MMU))
return true;
return (size <= limit) && (addr <= (limit - size));
}
#endif
#ifndef access_ok
#define access_ok(addr, size) likely(__access_ok(addr, size))
#endif
#endif
+11
View File
@@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_AGP_H
#define _ASM_GENERIC_AGP_H
#include <asm/io.h>
#define map_page_into_agp(page) do {} while (0)
#define unmap_page_from_agp(page) do {} while (0)
#define flush_agp_cache() mb()
#endif /* _ASM_GENERIC_AGP_H */
@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_ARCHRANDOM_H__
#define __ASM_GENERIC_ARCHRANDOM_H__
static inline size_t __must_check arch_get_random_longs(unsigned long *v, size_t max_longs)
{
return 0;
}
static inline size_t __must_check arch_get_random_seed_longs(unsigned long *v, size_t max_longs)
{
return 0;
}
#endif
@@ -0,0 +1 @@
#include <generated/asm-offsets.h>
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/bitops.h>
#undef __memset
extern void *__memset(void *, int, __kernel_size_t);
#undef __memcpy
extern void *__memcpy(void *, const void *, __kernel_size_t);
#undef __memmove
extern void *__memmove(void *, const void *, __kernel_size_t);
#undef memset
extern void *memset(void *, int, __kernel_size_t);
#undef memcpy
extern void *memcpy(void *, const void *, __kernel_size_t);
#undef memmove
extern void *memmove(void *, const void *, __kernel_size_t);
+133
View File
@@ -0,0 +1,133 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Generic C implementation of atomic counter operations. Do not include in
* machine independent code.
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifndef __ASM_GENERIC_ATOMIC_H
#define __ASM_GENERIC_ATOMIC_H
#include <asm/cmpxchg.h>
#include <asm/barrier.h>
#ifdef CONFIG_SMP
/* we can build all atomic primitives from cmpxchg */
#define ATOMIC_OP(op, c_op) \
static inline void generic_atomic_##op(int i, atomic_t *v) \
{ \
int c, old; \
\
c = v->counter; \
while ((old = arch_cmpxchg(&v->counter, c, c c_op i)) != c) \
c = old; \
}
#define ATOMIC_OP_RETURN(op, c_op) \
static inline int generic_atomic_##op##_return(int i, atomic_t *v) \
{ \
int c, old; \
\
c = v->counter; \
while ((old = arch_cmpxchg(&v->counter, c, c c_op i)) != c) \
c = old; \
\
return c c_op i; \
}
#define ATOMIC_FETCH_OP(op, c_op) \
static inline int generic_atomic_fetch_##op(int i, atomic_t *v) \
{ \
int c, old; \
\
c = v->counter; \
while ((old = arch_cmpxchg(&v->counter, c, c c_op i)) != c) \
c = old; \
\
return c; \
}
#else
#include <linux/irqflags.h>
#define ATOMIC_OP(op, c_op) \
static inline void generic_atomic_##op(int i, atomic_t *v) \
{ \
unsigned long flags; \
\
raw_local_irq_save(flags); \
v->counter = v->counter c_op i; \
raw_local_irq_restore(flags); \
}
#define ATOMIC_OP_RETURN(op, c_op) \
static inline int generic_atomic_##op##_return(int i, atomic_t *v) \
{ \
unsigned long flags; \
int ret; \
\
raw_local_irq_save(flags); \
ret = (v->counter = v->counter c_op i); \
raw_local_irq_restore(flags); \
\
return ret; \
}
#define ATOMIC_FETCH_OP(op, c_op) \
static inline int generic_atomic_fetch_##op(int i, atomic_t *v) \
{ \
unsigned long flags; \
int ret; \
\
raw_local_irq_save(flags); \
ret = v->counter; \
v->counter = v->counter c_op i; \
raw_local_irq_restore(flags); \
\
return ret; \
}
#endif /* CONFIG_SMP */
ATOMIC_OP_RETURN(add, +)
ATOMIC_OP_RETURN(sub, -)
ATOMIC_FETCH_OP(add, +)
ATOMIC_FETCH_OP(sub, -)
ATOMIC_FETCH_OP(and, &)
ATOMIC_FETCH_OP(or, |)
ATOMIC_FETCH_OP(xor, ^)
ATOMIC_OP(add, +)
ATOMIC_OP(sub, -)
ATOMIC_OP(and, &)
ATOMIC_OP(or, |)
ATOMIC_OP(xor, ^)
#undef ATOMIC_FETCH_OP
#undef ATOMIC_OP_RETURN
#undef ATOMIC_OP
#define arch_atomic_add_return generic_atomic_add_return
#define arch_atomic_sub_return generic_atomic_sub_return
#define arch_atomic_fetch_add generic_atomic_fetch_add
#define arch_atomic_fetch_sub generic_atomic_fetch_sub
#define arch_atomic_fetch_and generic_atomic_fetch_and
#define arch_atomic_fetch_or generic_atomic_fetch_or
#define arch_atomic_fetch_xor generic_atomic_fetch_xor
#define arch_atomic_add generic_atomic_add
#define arch_atomic_sub generic_atomic_sub
#define arch_atomic_and generic_atomic_and
#define arch_atomic_or generic_atomic_or
#define arch_atomic_xor generic_atomic_xor
#define arch_atomic_read(v) READ_ONCE((v)->counter)
#define arch_atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
#endif /* __ASM_GENERIC_ATOMIC_H */
@@ -0,0 +1,75 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Generic implementation of 64-bit atomics using spinlocks,
* useful on processors that don't have 64-bit atomic instructions.
*
* Copyright © 2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
*/
#ifndef _ASM_GENERIC_ATOMIC64_H
#define _ASM_GENERIC_ATOMIC64_H
#include <linux/types.h>
typedef struct {
s64 __aligned(sizeof(s64)) counter;
} atomic64_t;
#define ATOMIC64_INIT(i) { (i) }
extern s64 generic_atomic64_read(const atomic64_t *v);
extern void generic_atomic64_set(atomic64_t *v, s64 i);
#define ATOMIC64_OP(op) \
extern void generic_atomic64_##op(s64 a, atomic64_t *v);
#define ATOMIC64_OP_RETURN(op) \
extern s64 generic_atomic64_##op##_return(s64 a, atomic64_t *v);
#define ATOMIC64_FETCH_OP(op) \
extern s64 generic_atomic64_fetch_##op(s64 a, atomic64_t *v);
#define ATOMIC64_OPS(op) ATOMIC64_OP(op) ATOMIC64_OP_RETURN(op) ATOMIC64_FETCH_OP(op)
ATOMIC64_OPS(add)
ATOMIC64_OPS(sub)
#undef ATOMIC64_OPS
#define ATOMIC64_OPS(op) ATOMIC64_OP(op) ATOMIC64_FETCH_OP(op)
ATOMIC64_OPS(and)
ATOMIC64_OPS(or)
ATOMIC64_OPS(xor)
#undef ATOMIC64_OPS
#undef ATOMIC64_FETCH_OP
#undef ATOMIC64_OP_RETURN
#undef ATOMIC64_OP
extern s64 generic_atomic64_dec_if_positive(atomic64_t *v);
extern s64 generic_atomic64_cmpxchg(atomic64_t *v, s64 o, s64 n);
extern s64 generic_atomic64_xchg(atomic64_t *v, s64 new);
extern s64 generic_atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u);
#define arch_atomic64_read generic_atomic64_read
#define arch_atomic64_set generic_atomic64_set
#define arch_atomic64_set_release generic_atomic64_set
#define arch_atomic64_add generic_atomic64_add
#define arch_atomic64_add_return generic_atomic64_add_return
#define arch_atomic64_fetch_add generic_atomic64_fetch_add
#define arch_atomic64_sub generic_atomic64_sub
#define arch_atomic64_sub_return generic_atomic64_sub_return
#define arch_atomic64_fetch_sub generic_atomic64_fetch_sub
#define arch_atomic64_and generic_atomic64_and
#define arch_atomic64_fetch_and generic_atomic64_fetch_and
#define arch_atomic64_or generic_atomic64_or
#define arch_atomic64_fetch_or generic_atomic64_fetch_or
#define arch_atomic64_xor generic_atomic64_xor
#define arch_atomic64_fetch_xor generic_atomic64_fetch_xor
#define arch_atomic64_dec_if_positive generic_atomic64_dec_if_positive
#define arch_atomic64_cmpxchg generic_atomic64_cmpxchg
#define arch_atomic64_xchg generic_atomic64_xchg
#define arch_atomic64_fetch_add_unless generic_atomic64_fetch_add_unless
#endif /* _ASM_GENERIC_ATOMIC64_H */
@@ -0,0 +1,42 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifdef __NR_chmod
__NR_chmod,
#endif
__NR_fchmod,
#ifdef __NR_chown
__NR_chown,
__NR_lchown,
#endif
#ifdef __NR_fchown
__NR_fchown,
#endif
__NR_setxattr,
#ifdef __NR_setxattrat
__NR_setxattrat,
#endif
__NR_lsetxattr,
__NR_fsetxattr,
__NR_removexattr,
#ifdef __NR_removexattrat
__NR_removexattrat,
#endif
__NR_lremovexattr,
__NR_fremovexattr,
#ifdef __NR_fchownat
__NR_fchownat,
__NR_fchmodat,
#endif
#ifdef __NR_fchmodat2
__NR_fchmodat2,
#endif
#ifdef __NR_chown32
__NR_chown32,
__NR_fchown32,
__NR_lchown32,
#endif
#ifdef __NR_link
__NR_link,
#endif
#ifdef __NR_linkat
__NR_linkat,
#endif
@@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifdef __NR_rename
__NR_rename,
#endif
#ifdef __NR_mkdir
__NR_mkdir,
#endif
#ifdef __NR_rmdir
__NR_rmdir,
#endif
#ifdef __NR_creat
__NR_creat,
#endif
#ifdef __NR_link
__NR_link,
#endif
#ifdef __NR_unlink
__NR_unlink,
#endif
#ifdef __NR_symlink
__NR_symlink,
#endif
#ifdef __NR_mknod
__NR_mknod,
#endif
#ifdef __NR_mkdirat
__NR_mkdirat,
__NR_mknodat,
__NR_unlinkat,
#ifdef __NR_renameat
__NR_renameat,
#endif
__NR_linkat,
__NR_symlinkat,
#endif
#ifdef __NR_renameat2
__NR_renameat2,
#endif
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifdef __NR_readlink
__NR_readlink,
#endif
__NR_quotactl,
__NR_listxattr,
#ifdef __NR_listxattrat
__NR_listxattrat,
#endif
__NR_llistxattr,
__NR_flistxattr,
__NR_getxattr,
#ifdef __NR_getxattrat
__NR_getxattrat,
#endif
__NR_lgetxattr,
__NR_fgetxattr,
#ifdef __NR_readlinkat
__NR_readlinkat,
#endif
@@ -0,0 +1,3 @@
__NR_kill,
__NR_tgkill,
__NR_tkill,
@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <asm-generic/audit_dir_write.h>
__NR_acct,
#ifdef __NR_swapon
__NR_swapon,
#endif
__NR_quotactl,
#ifdef __NR_truncate
__NR_truncate,
#endif
#ifdef __NR_truncate64
__NR_truncate64,
#endif
#ifdef __NR_ftruncate
__NR_ftruncate,
#endif
#ifdef __NR_ftruncate64
__NR_ftruncate64,
#endif
#ifdef __NR_bind
__NR_bind, /* bind can affect fs object only in one way... */
#endif
#ifdef __NR_fallocate
__NR_fallocate,
#endif
+306
View File
@@ -0,0 +1,306 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Generic barrier definitions.
*
* It should be possible to use these on really simple architectures,
* but it serves more as a starting point for new ports.
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifndef __ASM_GENERIC_BARRIER_H
#define __ASM_GENERIC_BARRIER_H
#ifndef __ASSEMBLY__
#include <linux/compiler.h>
#include <linux/kcsan-checks.h>
#include <asm/rwonce.h>
#ifndef nop
#define nop() asm volatile ("nop")
#endif
/*
* Architectures that want generic instrumentation can define __ prefixed
* variants of all barriers.
*/
#ifdef __mb
#define mb() do { kcsan_mb(); __mb(); } while (0)
#endif
#ifdef __rmb
#define rmb() do { kcsan_rmb(); __rmb(); } while (0)
#endif
#ifdef __wmb
#define wmb() do { kcsan_wmb(); __wmb(); } while (0)
#endif
#ifdef __dma_mb
#define dma_mb() do { kcsan_mb(); __dma_mb(); } while (0)
#endif
#ifdef __dma_rmb
#define dma_rmb() do { kcsan_rmb(); __dma_rmb(); } while (0)
#endif
#ifdef __dma_wmb
#define dma_wmb() do { kcsan_wmb(); __dma_wmb(); } while (0)
#endif
/*
* Force strict CPU ordering. And yes, this is required on UP too when we're
* talking to devices.
*
* Fall back to compiler barriers if nothing better is provided.
*/
#ifndef mb
#define mb() barrier()
#endif
#ifndef rmb
#define rmb() mb()
#endif
#ifndef wmb
#define wmb() mb()
#endif
#ifndef dma_mb
#define dma_mb() mb()
#endif
#ifndef dma_rmb
#define dma_rmb() rmb()
#endif
#ifndef dma_wmb
#define dma_wmb() wmb()
#endif
#ifndef __smp_mb
#define __smp_mb() mb()
#endif
#ifndef __smp_rmb
#define __smp_rmb() rmb()
#endif
#ifndef __smp_wmb
#define __smp_wmb() wmb()
#endif
#ifdef CONFIG_SMP
#ifndef smp_mb
#define smp_mb() do { kcsan_mb(); __smp_mb(); } while (0)
#endif
#ifndef smp_rmb
#define smp_rmb() do { kcsan_rmb(); __smp_rmb(); } while (0)
#endif
#ifndef smp_wmb
#define smp_wmb() do { kcsan_wmb(); __smp_wmb(); } while (0)
#endif
#else /* !CONFIG_SMP */
#ifndef smp_mb
#define smp_mb() barrier()
#endif
#ifndef smp_rmb
#define smp_rmb() barrier()
#endif
#ifndef smp_wmb
#define smp_wmb() barrier()
#endif
#endif /* CONFIG_SMP */
#ifndef __smp_store_mb
#define __smp_store_mb(var, value) do { WRITE_ONCE(var, value); __smp_mb(); } while (0)
#endif
#ifndef __smp_mb__before_atomic
#define __smp_mb__before_atomic() __smp_mb()
#endif
#ifndef __smp_mb__after_atomic
#define __smp_mb__after_atomic() __smp_mb()
#endif
#ifndef __smp_store_release
#define __smp_store_release(p, v) \
do { \
compiletime_assert_atomic_type(*p); \
__smp_mb(); \
WRITE_ONCE(*p, v); \
} while (0)
#endif
#ifndef __smp_load_acquire
#define __smp_load_acquire(p) \
({ \
__unqual_scalar_typeof(*p) ___p1 = READ_ONCE(*p); \
compiletime_assert_atomic_type(*p); \
__smp_mb(); \
(typeof(*p))___p1; \
})
#endif
#ifdef CONFIG_SMP
#ifndef smp_store_mb
#define smp_store_mb(var, value) do { kcsan_mb(); __smp_store_mb(var, value); } while (0)
#endif
#ifndef smp_mb__before_atomic
#define smp_mb__before_atomic() do { kcsan_mb(); __smp_mb__before_atomic(); } while (0)
#endif
#ifndef smp_mb__after_atomic
#define smp_mb__after_atomic() do { kcsan_mb(); __smp_mb__after_atomic(); } while (0)
#endif
#ifndef smp_store_release
#define smp_store_release(p, v) do { kcsan_release(); __smp_store_release(p, v); } while (0)
#endif
#ifndef smp_load_acquire
#define smp_load_acquire(p) __smp_load_acquire(p)
#endif
#else /* !CONFIG_SMP */
#ifndef smp_store_mb
#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); barrier(); } while (0)
#endif
#ifndef smp_mb__before_atomic
#define smp_mb__before_atomic() barrier()
#endif
#ifndef smp_mb__after_atomic
#define smp_mb__after_atomic() barrier()
#endif
#ifndef smp_store_release
#define smp_store_release(p, v) \
do { \
barrier(); \
WRITE_ONCE(*p, v); \
} while (0)
#endif
#ifndef smp_load_acquire
#define smp_load_acquire(p) \
({ \
__unqual_scalar_typeof(*p) ___p1 = READ_ONCE(*p); \
barrier(); \
(typeof(*p))___p1; \
})
#endif
#endif /* CONFIG_SMP */
/* Barriers for virtual machine guests when talking to an SMP host */
#define virt_mb() do { kcsan_mb(); __smp_mb(); } while (0)
#define virt_rmb() do { kcsan_rmb(); __smp_rmb(); } while (0)
#define virt_wmb() do { kcsan_wmb(); __smp_wmb(); } while (0)
#define virt_store_mb(var, value) do { kcsan_mb(); __smp_store_mb(var, value); } while (0)
#define virt_mb__before_atomic() do { kcsan_mb(); __smp_mb__before_atomic(); } while (0)
#define virt_mb__after_atomic() do { kcsan_mb(); __smp_mb__after_atomic(); } while (0)
#define virt_store_release(p, v) do { kcsan_release(); __smp_store_release(p, v); } while (0)
#define virt_load_acquire(p) __smp_load_acquire(p)
/**
* smp_acquire__after_ctrl_dep() - Provide ACQUIRE ordering after a control dependency
*
* A control dependency provides a LOAD->STORE order, the additional RMB
* provides LOAD->LOAD order, together they provide LOAD->{LOAD,STORE} order,
* aka. (load)-ACQUIRE.
*
* Architectures that do not do load speculation can have this be barrier().
*/
#ifndef smp_acquire__after_ctrl_dep
#define smp_acquire__after_ctrl_dep() smp_rmb()
#endif
/**
* smp_cond_load_relaxed() - (Spin) wait for cond with no ordering guarantees
* @ptr: pointer to the variable to wait on
* @cond_expr: boolean expression to wait for
*
* Equivalent to using READ_ONCE() on the condition variable.
*
* Due to C lacking lambda expressions we load the value of *ptr into a
* pre-named variable @VAL to be used in @cond.
*/
#ifndef smp_cond_load_relaxed
#define smp_cond_load_relaxed(ptr, cond_expr) ({ \
typeof(ptr) __PTR = (ptr); \
__unqual_scalar_typeof(*ptr) VAL; \
for (;;) { \
VAL = READ_ONCE(*__PTR); \
if (cond_expr) \
break; \
cpu_relax(); \
} \
(typeof(*ptr))VAL; \
})
#endif
/**
* smp_cond_load_acquire() - (Spin) wait for cond with ACQUIRE ordering
* @ptr: pointer to the variable to wait on
* @cond_expr: boolean expression to wait for
*
* Equivalent to using smp_load_acquire() on the condition variable but employs
* the control dependency of the wait to reduce the barrier on many platforms.
*/
#ifndef smp_cond_load_acquire
#define smp_cond_load_acquire(ptr, cond_expr) ({ \
__unqual_scalar_typeof(*ptr) _val; \
_val = smp_cond_load_relaxed(ptr, cond_expr); \
smp_acquire__after_ctrl_dep(); \
(typeof(*ptr))_val; \
})
#endif
/*
* pmem_wmb() ensures that all stores for which the modification
* are written to persistent storage by preceding instructions have
* updated persistent storage before any data access or data transfer
* caused by subsequent instructions is initiated.
*/
#ifndef pmem_wmb
#define pmem_wmb() wmb()
#endif
/*
* ioremap_wc() maps I/O memory as memory with write-combining attributes. For
* this kind of memory accesses, the CPU may wait for prior accesses to be
* merged with subsequent ones. In some situation, such wait is bad for the
* performance. io_stop_wc() can be used to prevent the merging of
* write-combining memory accesses before this macro with those after it.
*/
#ifndef io_stop_wc
#define io_stop_wc() do { } while (0)
#endif
/*
* Architectures that guarantee an implicit smp_mb() in switch_mm()
* can override smp_mb__after_switch_mm.
*/
#ifndef smp_mb__after_switch_mm
# define smp_mb__after_switch_mm() smp_mb()
#endif
#endif /* !__ASSEMBLY__ */
#endif /* __ASM_GENERIC_BARRIER_H */
+38
View File
@@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_BITOPS_H
#define __ASM_GENERIC_BITOPS_H
/*
* For the benefit of those who are trying to port Linux to another
* architecture, here are some C-language equivalents. They should
* generate reasonable code, so take a look at what your compiler spits
* out before rolling your own buggy implementation in assembly language.
*
* C language equivalents written by Theodore Ts'o, 9/26/92
*/
#include <linux/irqflags.h>
#include <linux/compiler.h>
#include <asm/barrier.h>
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/fls.h>
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#ifndef _LINUX_BITOPS_H
#error only <linux/bitops.h> can be included directly
#endif
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/atomic.h>
#include <asm-generic/bitops/non-atomic.h>
#include <asm-generic/bitops/le.h>
#include <asm-generic/bitops/ext2-atomic.h>
#endif /* __ASM_GENERIC_BITOPS_H */
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS___BITREV_H_
#define _ASM_GENERIC_BITOPS___BITREV_H_
#include <asm/types.h>
extern u8 const byte_rev_table[256];
static __always_inline __attribute_const__ u8 generic___bitrev8(u8 byte)
{
return byte_rev_table[byte];
}
static __always_inline __attribute_const__ u16 generic___bitrev16(u16 x)
{
return (generic___bitrev8(x & 0xff) << 8) | generic___bitrev8(x >> 8);
}
static __always_inline __attribute_const__ u32 generic___bitrev32(u32 x)
{
return (generic___bitrev16(x & 0xffff) << 16) | generic___bitrev16(x >> 16);
}
#endif /* _ASM_GENERIC_BITOPS___BITREV_H_ */
@@ -0,0 +1,48 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS___FFS_H_
#define _ASM_GENERIC_BITOPS___FFS_H_
#include <asm/types.h>
/**
* generic___ffs - find first bit in word.
* @word: The word to search
*
* Undefined if no bit exists, so code should check against 0 first.
*/
static __always_inline __attribute_const__ unsigned int generic___ffs(unsigned long word)
{
unsigned int num = 0;
#if BITS_PER_LONG == 64
if ((word & 0xffffffff) == 0) {
num += 32;
word >>= 32;
}
#endif
if ((word & 0xffff) == 0) {
num += 16;
word >>= 16;
}
if ((word & 0xff) == 0) {
num += 8;
word >>= 8;
}
if ((word & 0xf) == 0) {
num += 4;
word >>= 4;
}
if ((word & 0x3) == 0) {
num += 2;
word >>= 2;
}
if ((word & 0x1) == 0)
num += 1;
return num;
}
#ifndef __HAVE_ARCH___FFS
#define __ffs(word) generic___ffs(word)
#endif
#endif /* _ASM_GENERIC_BITOPS___FFS_H_ */
@@ -0,0 +1,48 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS___FLS_H_
#define _ASM_GENERIC_BITOPS___FLS_H_
#include <asm/types.h>
/**
* generic___fls - find last (most-significant) set bit in a long word
* @word: the word to search
*
* Undefined if no set bit exists, so code should check against 0 first.
*/
static __always_inline __attribute_const__ unsigned int generic___fls(unsigned long word)
{
unsigned int num = BITS_PER_LONG - 1;
#if BITS_PER_LONG == 64
if (!(word & (~0ul << 32))) {
num -= 32;
word <<= 32;
}
#endif
if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
num -= 16;
word <<= 16;
}
if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
num -= 8;
word <<= 8;
}
if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
num -= 4;
word <<= 4;
}
if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
num -= 2;
word <<= 2;
}
if (!(word & (~0ul << (BITS_PER_LONG-1))))
num -= 1;
return num;
}
#ifndef __HAVE_ARCH___FLS
#define __fls(word) generic___fls(word)
#endif
#endif /* _ASM_GENERIC_BITOPS___FLS_H_ */
@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_ARCH_HWEIGHT_H_
#define _ASM_GENERIC_BITOPS_ARCH_HWEIGHT_H_
#include <asm/types.h>
static inline unsigned int __arch_hweight32(unsigned int w)
{
return __sw_hweight32(w);
}
static inline unsigned int __arch_hweight16(unsigned int w)
{
return __sw_hweight16(w);
}
static inline unsigned int __arch_hweight8(unsigned int w)
{
return __sw_hweight8(w);
}
static inline unsigned long __arch_hweight64(__u64 w)
{
return __sw_hweight64(w);
}
#endif /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */
@@ -0,0 +1,70 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_ATOMIC_H_
#define _ASM_GENERIC_BITOPS_ATOMIC_H_
#include <linux/atomic.h>
#include <linux/compiler.h>
#include <asm/barrier.h>
/*
* Implementation of atomic bitops using atomic-fetch ops.
* See Documentation/atomic_bitops.txt for details.
*/
static __always_inline void
arch_set_bit(unsigned int nr, volatile unsigned long *p)
{
p += BIT_WORD(nr);
raw_atomic_long_or(BIT_MASK(nr), (atomic_long_t *)p);
}
static __always_inline void
arch_clear_bit(unsigned int nr, volatile unsigned long *p)
{
p += BIT_WORD(nr);
raw_atomic_long_andnot(BIT_MASK(nr), (atomic_long_t *)p);
}
static __always_inline void
arch_change_bit(unsigned int nr, volatile unsigned long *p)
{
p += BIT_WORD(nr);
raw_atomic_long_xor(BIT_MASK(nr), (atomic_long_t *)p);
}
static __always_inline int
arch_test_and_set_bit(unsigned int nr, volatile unsigned long *p)
{
long old;
unsigned long mask = BIT_MASK(nr);
p += BIT_WORD(nr);
old = raw_atomic_long_fetch_or(mask, (atomic_long_t *)p);
return !!(old & mask);
}
static __always_inline int
arch_test_and_clear_bit(unsigned int nr, volatile unsigned long *p)
{
long old;
unsigned long mask = BIT_MASK(nr);
p += BIT_WORD(nr);
old = raw_atomic_long_fetch_andnot(mask, (atomic_long_t *)p);
return !!(old & mask);
}
static __always_inline int
arch_test_and_change_bit(unsigned int nr, volatile unsigned long *p)
{
long old;
unsigned long mask = BIT_MASK(nr);
p += BIT_WORD(nr);
old = raw_atomic_long_fetch_xor(mask, (atomic_long_t *)p);
return !!(old & mask);
}
#include <asm-generic/bitops/instrumented-atomic.h>
#endif /* _ASM_GENERIC_BITOPS_ATOMIC_H */
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_BUILTIN___FFS_H_
#define _ASM_GENERIC_BITOPS_BUILTIN___FFS_H_
/**
* __ffs - find first bit in word.
* @word: The word to search
*
* Undefined if no bit exists, so code should check against 0 first.
*/
static __always_inline __attribute_const__ unsigned int __ffs(unsigned long word)
{
return __builtin_ctzl(word);
}
#endif
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_BUILTIN___FLS_H_
#define _ASM_GENERIC_BITOPS_BUILTIN___FLS_H_
/**
* __fls - find last (most-significant) set bit in a long word
* @word: the word to search
*
* Undefined if no set bit exists, so code should check against 0 first.
*/
static __always_inline __attribute_const__ unsigned int __fls(unsigned long word)
{
return (sizeof(word) * 8) - 1 - __builtin_clzl(word);
}
#endif
@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_BUILTIN_FFS_H_
#define _ASM_GENERIC_BITOPS_BUILTIN_FFS_H_
/**
* ffs - find first bit set
* @x: the word to search
*
* This is defined the same way as
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from ffz (man ffs).
*/
#define ffs(x) __builtin_ffs(x)
#endif
@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_BUILTIN_FLS_H_
#define _ASM_GENERIC_BITOPS_BUILTIN_FLS_H_
/**
* fls - find last (most-significant) bit set
* @x: the word to search
*
* This is defined the same way as ffs.
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
static __always_inline __attribute_const__ int fls(unsigned int x)
{
return x ? sizeof(x) * 8 - __builtin_clz(x) : 0;
}
#endif
@@ -0,0 +1,44 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_
#define _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_
/*
* Compile time versions of __arch_hweightN()
*/
#define __const_hweight8(w) \
((unsigned int) \
((!!((w) & (1ULL << 0))) + \
(!!((w) & (1ULL << 1))) + \
(!!((w) & (1ULL << 2))) + \
(!!((w) & (1ULL << 3))) + \
(!!((w) & (1ULL << 4))) + \
(!!((w) & (1ULL << 5))) + \
(!!((w) & (1ULL << 6))) + \
(!!((w) & (1ULL << 7)))))
#define __const_hweight16(w) (__const_hweight8(w) + __const_hweight8((w) >> 8 ))
#define __const_hweight32(w) (__const_hweight16(w) + __const_hweight16((w) >> 16))
#define __const_hweight64(w) (__const_hweight32(w) + __const_hweight32((w) >> 32))
/*
* Generic interface.
*/
#define hweight8(w) (__builtin_constant_p(w) ? __const_hweight8(w) : __arch_hweight8(w))
#define hweight16(w) (__builtin_constant_p(w) ? __const_hweight16(w) : __arch_hweight16(w))
#define hweight32(w) (__builtin_constant_p(w) ? __const_hweight32(w) : __arch_hweight32(w))
#define hweight64(w) (__builtin_constant_p(w) ? __const_hweight64(w) : __arch_hweight64(w))
/*
* Interface for known constant arguments
*/
#define HWEIGHT8(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight8(w))
#define HWEIGHT16(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight16(w))
#define HWEIGHT32(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight32(w))
#define HWEIGHT64(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight64(w))
/*
* Type invariant interface to the compile time constant hweight functions.
*/
#define HWEIGHT(w) HWEIGHT64((u64)w)
#endif /* _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_ */
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_EXT2_ATOMIC_SETBIT_H_
#define _ASM_GENERIC_BITOPS_EXT2_ATOMIC_SETBIT_H_
/*
* Atomic bitops based version of ext2 atomic bitops
*/
#define ext2_set_bit_atomic(l, nr, addr) test_and_set_bit_le(nr, addr)
#define ext2_clear_bit_atomic(l, nr, addr) test_and_clear_bit_le(nr, addr)
#endif /* _ASM_GENERIC_BITOPS_EXT2_ATOMIC_SETBIT_H_ */
@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_EXT2_ATOMIC_H_
#define _ASM_GENERIC_BITOPS_EXT2_ATOMIC_H_
/*
* Spinlock based version of ext2 atomic bitops
*/
#define ext2_set_bit_atomic(lock, nr, addr) \
({ \
int ret; \
spin_lock(lock); \
ret = __test_and_set_bit_le(nr, addr); \
spin_unlock(lock); \
ret; \
})
#define ext2_clear_bit_atomic(lock, nr, addr) \
({ \
int ret; \
spin_lock(lock); \
ret = __test_and_clear_bit_le(nr, addr); \
spin_unlock(lock); \
ret; \
})
#endif /* _ASM_GENERIC_BITOPS_EXT2_ATOMIC_H_ */
@@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_FFS_H_
#define _ASM_GENERIC_BITOPS_FFS_H_
/**
* generic_ffs - find first bit set
* @x: the word to search
*
* This is defined the same way as
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from ffz (man ffs).
*/
static inline __attribute_const__ int generic_ffs(int x)
{
int r = 1;
if (!x)
return 0;
if (!(x & 0xffff)) {
x >>= 16;
r += 16;
}
if (!(x & 0xff)) {
x >>= 8;
r += 8;
}
if (!(x & 0xf)) {
x >>= 4;
r += 4;
}
if (!(x & 3)) {
x >>= 2;
r += 2;
}
if (!(x & 1)) {
x >>= 1;
r += 1;
}
return r;
}
#ifndef __HAVE_ARCH_FFS
#define ffs(x) generic_ffs(x)
#endif
#endif /* _ASM_GENERIC_BITOPS_FFS_H_ */
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_FFZ_H_
#define _ASM_GENERIC_BITOPS_FFZ_H_
/*
* ffz - find first zero in word.
* @word: The word to search
*
* Undefined if no zero exists, so code should check against ~0UL first.
*/
#define ffz(x) __ffs(~(x))
#endif /* _ASM_GENERIC_BITOPS_FFZ_H_ */
@@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_FLS_H_
#define _ASM_GENERIC_BITOPS_FLS_H_
/**
* generic_fls - find last (most-significant) bit set
* @x: the word to search
*
* This is defined the same way as ffs.
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
static __always_inline __attribute_const__ int generic_fls(unsigned int x)
{
int r = 32;
if (!x)
return 0;
if (!(x & 0xffff0000u)) {
x <<= 16;
r -= 16;
}
if (!(x & 0xff000000u)) {
x <<= 8;
r -= 8;
}
if (!(x & 0xf0000000u)) {
x <<= 4;
r -= 4;
}
if (!(x & 0xc0000000u)) {
x <<= 2;
r -= 2;
}
if (!(x & 0x80000000u)) {
x <<= 1;
r -= 1;
}
return r;
}
#ifndef __HAVE_ARCH_FLS
#define fls(x) generic_fls(x)
#endif
#endif /* _ASM_GENERIC_BITOPS_FLS_H_ */
@@ -0,0 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_FLS64_H_
#define _ASM_GENERIC_BITOPS_FLS64_H_
#include <asm/types.h>
/**
* fls64 - find last set bit in a 64-bit word
* @x: the word to search
*
* This is defined in a similar way as the libc and compiler builtin
* ffsll, but returns the position of the most significant set bit.
*
* fls64(value) returns 0 if value is 0 or the position of the last
* set bit if value is nonzero. The last (most significant) bit is
* at position 64.
*/
#if BITS_PER_LONG == 32
static __always_inline __attribute_const__ int fls64(__u64 x)
{
__u32 h = x >> 32;
if (h)
return fls(h) + 32;
return fls(x);
}
#elif BITS_PER_LONG == 64
static __always_inline __attribute_const__ int fls64(__u64 x)
{
if (x == 0)
return 0;
return __fls(x) + 1;
}
#else
#error BITS_PER_LONG not 32 or 64
#endif
#endif /* _ASM_GENERIC_BITOPS_FLS64_H_ */
@@ -0,0 +1,175 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H
#define __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H
#include <linux/bits.h>
#include <asm/barrier.h>
#ifndef _LINUX_BITOPS_H
#error only <linux/bitops.h> can be included directly
#endif
/*
* Generic definitions for bit operations, should not be used in regular code
* directly.
*/
/**
* generic___set_bit - Set a bit in memory
* @nr: the bit to set
* @addr: the address to start counting from
*
* Unlike set_bit(), this function is non-atomic and may be reordered.
* If it's called on the same region of memory simultaneously, the effect
* may be that only one operation succeeds.
*/
static __always_inline void
generic___set_bit(unsigned long nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
*p |= mask;
}
static __always_inline void
generic___clear_bit(unsigned long nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
*p &= ~mask;
}
/**
* generic___change_bit - Toggle a bit in memory
* @nr: the bit to change
* @addr: the address to start counting from
*
* Unlike change_bit(), this function is non-atomic and may be reordered.
* If it's called on the same region of memory simultaneously, the effect
* may be that only one operation succeeds.
*/
static __always_inline void
generic___change_bit(unsigned long nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
*p ^= mask;
}
/**
* generic___test_and_set_bit - Set a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
*
* This operation is non-atomic and can be reordered.
* If two examples of this operation race, one can appear to succeed
* but actually fail. You must protect multiple accesses with a lock.
*/
static __always_inline bool
generic___test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old = *p;
*p = old | mask;
return (old & mask) != 0;
}
/**
* generic___test_and_clear_bit - Clear a bit and return its old value
* @nr: Bit to clear
* @addr: Address to count from
*
* This operation is non-atomic and can be reordered.
* If two examples of this operation race, one can appear to succeed
* but actually fail. You must protect multiple accesses with a lock.
*/
static __always_inline bool
generic___test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old = *p;
*p = old & ~mask;
return (old & mask) != 0;
}
/* WARNING: non atomic and it can be reordered! */
static __always_inline bool
generic___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old = *p;
*p = old ^ mask;
return (old & mask) != 0;
}
/**
* generic_test_bit - Determine whether a bit is set
* @nr: bit number to test
* @addr: Address to start counting from
*/
static __always_inline bool
generic_test_bit(unsigned long nr, const volatile unsigned long *addr)
{
/*
* Unlike the bitops with the '__' prefix above, this one *is* atomic,
* so `volatile` must always stay here with no cast-aways. See
* `Documentation/atomic_bitops.txt` for the details.
*/
return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
}
/**
* generic_test_bit_acquire - Determine, with acquire semantics, whether a bit is set
* @nr: bit number to test
* @addr: Address to start counting from
*/
static __always_inline bool
generic_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
{
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
return 1UL & (smp_load_acquire(p) >> (nr & (BITS_PER_LONG-1)));
}
/*
* const_*() definitions provide good compile-time optimizations when
* the passed arguments can be resolved at compile time.
*/
#define const___set_bit generic___set_bit
#define const___clear_bit generic___clear_bit
#define const___change_bit generic___change_bit
#define const___test_and_set_bit generic___test_and_set_bit
#define const___test_and_clear_bit generic___test_and_clear_bit
#define const___test_and_change_bit generic___test_and_change_bit
#define const_test_bit_acquire generic_test_bit_acquire
/**
* const_test_bit - Determine whether a bit is set
* @nr: bit number to test
* @addr: Address to start counting from
*
* A version of generic_test_bit() which discards the `volatile` qualifier to
* allow a compiler to optimize code harder. Non-atomic and to be called only
* for testing compile-time constants, e.g. by the corresponding macros, not
* directly from "regular" code.
*/
static __always_inline bool
const_test_bit(unsigned long nr, const volatile unsigned long *addr)
{
const unsigned long *p = (const unsigned long *)addr + BIT_WORD(nr);
unsigned long mask = BIT_MASK(nr);
unsigned long val = *p;
return !!(val & mask);
}
#endif /* __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H */
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_HWEIGHT_H_
#define _ASM_GENERIC_BITOPS_HWEIGHT_H_
#include <asm-generic/bitops/arch_hweight.h>
#include <asm-generic/bitops/const_hweight.h>
#endif /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */
@@ -0,0 +1,103 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This file provides wrappers with sanitizer instrumentation for atomic bit
* operations.
*
* To use this functionality, an arch's bitops.h file needs to define each of
* the below bit operations with an arch_ prefix (e.g. arch_set_bit(),
* arch___set_bit(), etc.).
*/
#ifndef _ASM_GENERIC_BITOPS_INSTRUMENTED_ATOMIC_H
#define _ASM_GENERIC_BITOPS_INSTRUMENTED_ATOMIC_H
#include <linux/instrumented.h>
/**
* set_bit - Atomically set a bit in memory
* @nr: the bit to set
* @addr: the address to start counting from
*
* This is a relaxed atomic operation (no implied memory barriers).
*
* Note that @nr may be almost arbitrarily large; this function is not
* restricted to acting on a single-word quantity.
*/
static __always_inline void set_bit(long nr, volatile unsigned long *addr)
{
instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long));
arch_set_bit(nr, addr);
}
/**
* clear_bit - Clears a bit in memory
* @nr: Bit to clear
* @addr: Address to start counting from
*
* This is a relaxed atomic operation (no implied memory barriers).
*/
static __always_inline void clear_bit(long nr, volatile unsigned long *addr)
{
instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long));
arch_clear_bit(nr, addr);
}
/**
* change_bit - Toggle a bit in memory
* @nr: Bit to change
* @addr: Address to start counting from
*
* This is a relaxed atomic operation (no implied memory barriers).
*
* Note that @nr may be almost arbitrarily large; this function is not
* restricted to acting on a single-word quantity.
*/
static __always_inline void change_bit(long nr, volatile unsigned long *addr)
{
instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long));
arch_change_bit(nr, addr);
}
/**
* test_and_set_bit - Set a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
*
* This is an atomic fully-ordered operation (implied full memory barrier).
*/
static __always_inline bool test_and_set_bit(long nr, volatile unsigned long *addr)
{
kcsan_mb();
instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long));
return arch_test_and_set_bit(nr, addr);
}
/**
* test_and_clear_bit - Clear a bit and return its old value
* @nr: Bit to clear
* @addr: Address to count from
*
* This is an atomic fully-ordered operation (implied full memory barrier).
*/
static __always_inline bool test_and_clear_bit(long nr, volatile unsigned long *addr)
{
kcsan_mb();
instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long));
return arch_test_and_clear_bit(nr, addr);
}
/**
* test_and_change_bit - Change a bit and return its old value
* @nr: Bit to change
* @addr: Address to count from
*
* This is an atomic fully-ordered operation (implied full memory barrier).
*/
static __always_inline bool test_and_change_bit(long nr, volatile unsigned long *addr)
{
kcsan_mb();
instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long));
return arch_test_and_change_bit(nr, addr);
}
#endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_ATOMIC_H */
@@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This file provides wrappers with sanitizer instrumentation for bit
* locking operations.
*
* To use this functionality, an arch's bitops.h file needs to define each of
* the below bit operations with an arch_ prefix (e.g. arch_set_bit(),
* arch___set_bit(), etc.).
*/
#ifndef _ASM_GENERIC_BITOPS_INSTRUMENTED_LOCK_H
#define _ASM_GENERIC_BITOPS_INSTRUMENTED_LOCK_H
#include <linux/instrumented.h>
/**
* clear_bit_unlock - Clear a bit in memory, for unlock
* @nr: the bit to set
* @addr: the address to start counting from
*
* This operation is atomic and provides release barrier semantics.
*/
static inline void clear_bit_unlock(long nr, volatile unsigned long *addr)
{
kcsan_release();
instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long));
arch_clear_bit_unlock(nr, addr);
}
/**
* __clear_bit_unlock - Clears a bit in memory
* @nr: Bit to clear
* @addr: Address to start counting from
*
* This is a non-atomic operation but implies a release barrier before the
* memory operation. It can be used for an unlock if no other CPUs can
* concurrently modify other bits in the word.
*/
static inline void __clear_bit_unlock(long nr, volatile unsigned long *addr)
{
kcsan_release();
instrument_write(addr + BIT_WORD(nr), sizeof(long));
arch___clear_bit_unlock(nr, addr);
}
/**
* test_and_set_bit_lock - Set a bit and return its old value, for lock
* @nr: Bit to set
* @addr: Address to count from
*
* This operation is atomic and provides acquire barrier semantics if
* the returned value is 0.
* It can be used to implement bit locks.
*/
static inline bool test_and_set_bit_lock(long nr, volatile unsigned long *addr)
{
instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long));
return arch_test_and_set_bit_lock(nr, addr);
}
/**
* xor_unlock_is_negative_byte - XOR a single byte in memory and test if
* it is negative, for unlock.
* @mask: Change the bits which are set in this mask.
* @addr: The address of the word containing the byte to change.
*
* Changes some of bits 0-6 in the word pointed to by @addr.
* This operation is atomic and provides release barrier semantics.
* Used to optimise some folio operations which are commonly paired
* with an unlock or end of writeback. Bit 7 is used as PG_waiters to
* indicate whether anybody is waiting for the unlock.
*
* Return: Whether the top bit of the byte is set.
*/
static inline bool xor_unlock_is_negative_byte(unsigned long mask,
volatile unsigned long *addr)
{
kcsan_release();
instrument_atomic_write(addr, sizeof(long));
return arch_xor_unlock_is_negative_byte(mask, addr);
}
#endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_LOCK_H */
@@ -0,0 +1,157 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This file provides wrappers with sanitizer instrumentation for non-atomic
* bit operations.
*
* To use this functionality, an arch's bitops.h file needs to define each of
* the below bit operations with an arch_ prefix (e.g. arch_set_bit(),
* arch___set_bit(), etc.).
*/
#ifndef _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H
#define _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H
#include <linux/instrumented.h>
/**
* ___set_bit - Set a bit in memory
* @nr: the bit to set
* @addr: the address to start counting from
*
* Unlike set_bit(), this function is non-atomic. If it is called on the same
* region of memory concurrently, the effect may be that only one operation
* succeeds.
*/
static __always_inline void
___set_bit(unsigned long nr, volatile unsigned long *addr)
{
instrument_write(addr + BIT_WORD(nr), sizeof(long));
arch___set_bit(nr, addr);
}
/**
* ___clear_bit - Clears a bit in memory
* @nr: the bit to clear
* @addr: the address to start counting from
*
* Unlike clear_bit(), this function is non-atomic. If it is called on the same
* region of memory concurrently, the effect may be that only one operation
* succeeds.
*/
static __always_inline void
___clear_bit(unsigned long nr, volatile unsigned long *addr)
{
instrument_write(addr + BIT_WORD(nr), sizeof(long));
arch___clear_bit(nr, addr);
}
/**
* ___change_bit - Toggle a bit in memory
* @nr: the bit to change
* @addr: the address to start counting from
*
* Unlike change_bit(), this function is non-atomic. If it is called on the same
* region of memory concurrently, the effect may be that only one operation
* succeeds.
*/
static __always_inline void
___change_bit(unsigned long nr, volatile unsigned long *addr)
{
instrument_write(addr + BIT_WORD(nr), sizeof(long));
arch___change_bit(nr, addr);
}
static __always_inline void __instrument_read_write_bitop(long nr, volatile unsigned long *addr)
{
if (IS_ENABLED(CONFIG_KCSAN_ASSUME_PLAIN_WRITES_ATOMIC)) {
/*
* We treat non-atomic read-write bitops a little more special.
* Given the operations here only modify a single bit, assuming
* non-atomicity of the writer is sufficient may be reasonable
* for certain usage (and follows the permissible nature of the
* assume-plain-writes-atomic rule):
* 1. report read-modify-write races -> check read;
* 2. do not report races with marked readers, but do report
* races with unmarked readers -> check "atomic" write.
*/
kcsan_check_read(addr + BIT_WORD(nr), sizeof(long));
/*
* Use generic write instrumentation, in case other sanitizers
* or tools are enabled alongside KCSAN.
*/
instrument_write(addr + BIT_WORD(nr), sizeof(long));
} else {
instrument_read_write(addr + BIT_WORD(nr), sizeof(long));
}
}
/**
* ___test_and_set_bit - Set a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
*
* This operation is non-atomic. If two instances of this operation race, one
* can appear to succeed but actually fail.
*/
static __always_inline bool
___test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
{
__instrument_read_write_bitop(nr, addr);
return arch___test_and_set_bit(nr, addr);
}
/**
* ___test_and_clear_bit - Clear a bit and return its old value
* @nr: Bit to clear
* @addr: Address to count from
*
* This operation is non-atomic. If two instances of this operation race, one
* can appear to succeed but actually fail.
*/
static __always_inline bool
___test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
{
__instrument_read_write_bitop(nr, addr);
return arch___test_and_clear_bit(nr, addr);
}
/**
* ___test_and_change_bit - Change a bit and return its old value
* @nr: Bit to change
* @addr: Address to count from
*
* This operation is non-atomic. If two instances of this operation race, one
* can appear to succeed but actually fail.
*/
static __always_inline bool
___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
{
__instrument_read_write_bitop(nr, addr);
return arch___test_and_change_bit(nr, addr);
}
/**
* _test_bit - Determine whether a bit is set
* @nr: bit number to test
* @addr: Address to start counting from
*/
static __always_inline bool
_test_bit(unsigned long nr, const volatile unsigned long *addr)
{
instrument_atomic_read(addr + BIT_WORD(nr), sizeof(long));
return arch_test_bit(nr, addr);
}
/**
* _test_bit_acquire - Determine, with acquire semantics, whether a bit is set
* @nr: bit number to test
* @addr: Address to start counting from
*/
static __always_inline bool
_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
{
instrument_atomic_read(addr + BIT_WORD(nr), sizeof(long));
return arch_test_bit_acquire(nr, addr);
}
#endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H */
@@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_LE_H_
#define _ASM_GENERIC_BITOPS_LE_H_
#include <asm/types.h>
#include <asm/byteorder.h>
#if defined(__LITTLE_ENDIAN)
#define BITOP_LE_SWIZZLE 0
#elif defined(__BIG_ENDIAN)
#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7)
#endif
static inline int test_bit_le(int nr, const void *addr)
{
return test_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline void set_bit_le(int nr, void *addr)
{
set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline void clear_bit_le(int nr, void *addr)
{
clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline void __set_bit_le(int nr, void *addr)
{
__set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline void __clear_bit_le(int nr, void *addr)
{
__clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline int test_and_set_bit_le(int nr, void *addr)
{
return test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline int test_and_clear_bit_le(int nr, void *addr)
{
return test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline int __test_and_set_bit_le(int nr, void *addr)
{
return __test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline int __test_and_clear_bit_le(int nr, void *addr)
{
return __test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
#endif /* _ASM_GENERIC_BITOPS_LE_H_ */
@@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_LOCK_H_
#define _ASM_GENERIC_BITOPS_LOCK_H_
#include <linux/atomic.h>
#include <linux/compiler.h>
#include <asm/barrier.h>
/**
* arch_test_and_set_bit_lock - Set a bit and return its old value, for lock
* @nr: Bit to set
* @addr: Address to count from
*
* This operation is atomic and provides acquire barrier semantics if
* the returned value is 0.
* It can be used to implement bit locks.
*/
static __always_inline int
arch_test_and_set_bit_lock(unsigned int nr, volatile unsigned long *addr)
{
long old;
unsigned long mask = BIT_MASK(nr);
addr += BIT_WORD(nr);
if (READ_ONCE(*addr) & mask)
return 1;
old = raw_atomic_long_fetch_or_acquire(mask, (atomic_long_t *)addr);
return !!(old & mask);
}
/**
* arch_clear_bit_unlock - Clear a bit in memory, for unlock
* @nr: the bit to set
* @addr: the address to start counting from
*
* This operation is atomic and provides release barrier semantics.
*/
static __always_inline void
arch_clear_bit_unlock(unsigned int nr, volatile unsigned long *addr)
{
addr += BIT_WORD(nr);
raw_atomic_long_fetch_andnot_release(BIT_MASK(nr), (atomic_long_t *)addr);
}
/**
* arch___clear_bit_unlock - Clear a bit in memory, for unlock
* @nr: the bit to set
* @addr: the address to start counting from
*
* A weaker form of clear_bit_unlock() as used by __bit_lock_unlock(). If all
* the bits in the word are protected by this lock some archs can use weaker
* ops to safely unlock.
*
* See for example x86's implementation.
*/
static inline void
arch___clear_bit_unlock(unsigned int nr, volatile unsigned long *addr)
{
unsigned long old;
addr += BIT_WORD(nr);
old = READ_ONCE(*addr);
old &= ~BIT_MASK(nr);
raw_atomic_long_set_release((atomic_long_t *)addr, old);
}
#ifndef arch_xor_unlock_is_negative_byte
static inline bool arch_xor_unlock_is_negative_byte(unsigned long mask,
volatile unsigned long *p)
{
long old;
old = raw_atomic_long_fetch_xor_release(mask, (atomic_long_t *)p);
return !!(old & BIT(7));
}
#endif
#include <asm-generic/bitops/instrumented-lock.h>
#endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
#define _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
#include <asm-generic/bitops/generic-non-atomic.h>
#define arch___set_bit generic___set_bit
#define arch___clear_bit generic___clear_bit
#define arch___change_bit generic___change_bit
#define arch___test_and_set_bit generic___test_and_set_bit
#define arch___test_and_clear_bit generic___test_and_clear_bit
#define arch___test_and_change_bit generic___test_and_change_bit
#define arch_test_bit generic_test_bit
#define arch_test_bit_acquire generic_test_bit_acquire
#include <asm-generic/bitops/non-instrumented-non-atomic.h>
#endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */
@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_BITOPS_NON_INSTRUMENTED_NON_ATOMIC_H
#define __ASM_GENERIC_BITOPS_NON_INSTRUMENTED_NON_ATOMIC_H
#define ___set_bit arch___set_bit
#define ___clear_bit arch___clear_bit
#define ___change_bit arch___change_bit
#define ___test_and_set_bit arch___test_and_set_bit
#define ___test_and_clear_bit arch___test_and_clear_bit
#define ___test_and_change_bit arch___test_and_change_bit
#define _test_bit arch_test_bit
#define _test_bit_acquire arch_test_bit_acquire
#endif /* __ASM_GENERIC_BITOPS_NON_INSTRUMENTED_NON_ATOMIC_H */
@@ -0,0 +1,32 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BITOPS_SCHED_H_
#define _ASM_GENERIC_BITOPS_SCHED_H_
#include <linux/compiler.h> /* unlikely() */
#include <asm/types.h>
/*
* Every architecture must define this function. It's the fastest
* way of searching a 100-bit bitmap. It's guaranteed that at least
* one of the 100 bits is cleared.
*/
static inline int sched_find_first_bit(const unsigned long *b)
{
#if BITS_PER_LONG == 64
if (b[0])
return __ffs(b[0]);
return __ffs(b[1]) + 64;
#elif BITS_PER_LONG == 32
if (b[0])
return __ffs(b[0]);
if (b[1])
return __ffs(b[1]) + 32;
if (b[2])
return __ffs(b[2]) + 64;
return __ffs(b[3]) + 96;
#else
#error BITS_PER_LONG not defined
#endif
}
#endif /* _ASM_GENERIC_BITOPS_SCHED_H_ */
@@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_BITS_PER_LONG
#define __ASM_GENERIC_BITS_PER_LONG
#include <uapi/asm-generic/bitsperlong.h>
#ifdef CONFIG_64BIT
#define BITS_PER_LONG 64
#else
#define BITS_PER_LONG 32
#endif /* CONFIG_64BIT */
/*
* FIXME: The check currently breaks x86-64 build, so it's
* temporarily disabled. Please fix x86-64 and reenable
*/
#if 0 && BITS_PER_LONG != __BITS_PER_LONG
#error Inconsistent word size. Check asm/bitsperlong.h
#endif
#if __CHAR_BIT__ * __SIZEOF_LONG__ != __BITS_PER_LONG
#error Inconsistent word size. Check asm/bitsperlong.h
#endif
#ifndef __ASSEMBLER__
_Static_assert(sizeof(long) * 8 == __BITS_PER_LONG,
"Inconsistent word size. Check asm/bitsperlong.h");
#endif
#ifndef BITS_PER_LONG_LONG
#define BITS_PER_LONG_LONG 64
#endif
/*
* small_const_nbits(n) is true precisely when it is known at compile-time
* that BITMAP_SIZE(n) is 1, i.e. 1 <= n <= BITS_PER_LONG. This allows
* various bit/bitmap APIs to provide a fast inline implementation. Bitmaps
* of size 0 are very rare, and a compile-time-known-size 0 is most likely
* a sign of error. They will be handled correctly by the bit/bitmap APIs,
* but using the out-of-line functions, so that the inline implementations
* can unconditionally dereference the pointer(s).
*/
#define small_const_nbits(nbits) \
(__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG && (nbits) > 0)
#endif /* __ASM_GENERIC_BITS_PER_LONG */
+263
View File
@@ -0,0 +1,263 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_BUG_H
#define _ASM_GENERIC_BUG_H
#include <linux/compiler.h>
#include <linux/instrumentation.h>
#include <linux/once_lite.h>
#define CUT_HERE "------------[ cut here ]------------\n"
#ifdef CONFIG_GENERIC_BUG
#define BUGFLAG_WARNING (1 << 0)
#define BUGFLAG_ONCE (1 << 1)
#define BUGFLAG_DONE (1 << 2)
#define BUGFLAG_NO_CUT_HERE (1 << 3) /* CUT_HERE already sent */
#define BUGFLAG_ARGS (1 << 4)
#define BUGFLAG_TAINT(taint) ((taint) << 8)
#define BUG_GET_TAINT(bug) ((bug)->flags >> 8)
#endif
#ifndef WARN_CONDITION_STR
#ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED
# define WARN_CONDITION_STR(cond_str) "[" cond_str "] "
#else
# define WARN_CONDITION_STR(cond_str)
#endif
#endif /* WARN_CONDITION_STR */
#ifndef __ASSEMBLY__
#include <linux/panic.h>
#include <linux/printk.h>
struct warn_args;
struct pt_regs;
void __warn(const char *file, int line, void *caller, unsigned taint,
struct pt_regs *regs, struct warn_args *args);
#ifdef CONFIG_BUG
#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
#define BUG_REL(type, name) type name
#else
#define BUG_REL(type, name) signed int name##_disp
#endif
#ifdef CONFIG_GENERIC_BUG
struct bug_entry {
BUG_REL(unsigned long, bug_addr);
#ifdef HAVE_ARCH_BUG_FORMAT
BUG_REL(const char *, format);
#endif
#ifdef CONFIG_DEBUG_BUGVERBOSE
BUG_REL(const char *, file);
unsigned short line;
#endif
unsigned short flags;
};
#endif /* CONFIG_GENERIC_BUG */
/*
* Don't use BUG() or BUG_ON() unless there's really no way out; one
* example might be detecting data structure corruption in the middle
* of an operation that can't be backed out of. If the (sub)system
* can somehow continue operating, perhaps with reduced functionality,
* it's probably not BUG-worthy.
*
* If you're tempted to BUG(), think again: is completely giving up
* really the *only* solution? There are usually better options, where
* users don't need to reboot ASAP and can mostly shut down cleanly.
*/
#ifndef HAVE_ARCH_BUG
#define BUG() do { \
printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
barrier_before_unreachable(); \
panic("BUG!"); \
} while (0)
#endif
#ifndef HAVE_ARCH_BUG_ON
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
#endif
/*
* WARN(), WARN_ON(), WARN_ON_ONCE(), and so on can be used to report
* significant kernel issues that need prompt attention if they should ever
* appear at runtime.
*
* Do not use these macros when checking for invalid external inputs
* (e.g. invalid system call arguments, or invalid data coming from
* network/devices), and on transient conditions like ENOMEM or EAGAIN.
* These macros should be used for recoverable kernel issues only.
* For invalid external inputs, transient conditions, etc use
* pr_err[_once/_ratelimited]() followed by dump_stack(), if necessary.
* Do not include "BUG"/"WARNING" in format strings manually to make these
* conditions distinguishable from kernel issues.
*
* Use the versions with printk format strings to provide better diagnostics.
*/
extern __printf(4, 5)
void warn_slowpath_fmt(const char *file, const int line, unsigned taint,
const char *fmt, ...);
extern __printf(1, 2) void __warn_printk(const char *fmt, ...);
#ifdef __WARN_FLAGS
#define __WARN() __WARN_FLAGS("", BUGFLAG_TAINT(TAINT_WARN))
#ifndef WARN_ON
#define WARN_ON(condition) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN_FLAGS(#condition, \
BUGFLAG_TAINT(TAINT_WARN)); \
unlikely(__ret_warn_on); \
})
#endif
#ifndef WARN_ON_ONCE
#define WARN_ON_ONCE(condition) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN_FLAGS(#condition, \
BUGFLAG_ONCE | \
BUGFLAG_TAINT(TAINT_WARN)); \
unlikely(__ret_warn_on); \
})
#endif
#endif /* __WARN_FLAGS */
#if defined(__WARN_FLAGS) && !defined(__WARN_printf)
#define __WARN_printf(taint, arg...) do { \
instrumentation_begin(); \
__warn_printk(arg); \
__WARN_FLAGS("", BUGFLAG_NO_CUT_HERE | BUGFLAG_TAINT(taint));\
instrumentation_end(); \
} while (0)
#endif
#ifndef __WARN_printf
#define __WARN_printf(taint, arg...) do { \
instrumentation_begin(); \
warn_slowpath_fmt(__FILE__, __LINE__, taint, arg); \
instrumentation_end(); \
} while (0)
#endif
#ifndef __WARN
#define __WARN() __WARN_printf(TAINT_WARN, NULL)
#endif
/* used internally by panic.c */
#ifndef WARN_ON
#define WARN_ON(condition) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN(); \
unlikely(__ret_warn_on); \
})
#endif
#ifndef WARN
#define WARN(condition, format...) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN_printf(TAINT_WARN, format); \
unlikely(__ret_warn_on); \
})
#endif
#define WARN_TAINT(condition, taint, format...) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN_printf(taint, format); \
unlikely(__ret_warn_on); \
})
#ifndef WARN_ON_ONCE
#define WARN_ON_ONCE(condition) \
DO_ONCE_LITE_IF(condition, WARN_ON, 1)
#endif
#ifndef WARN_ONCE
#define WARN_ONCE(condition, format...) \
DO_ONCE_LITE_IF(condition, WARN, 1, format)
#endif
#define WARN_TAINT_ONCE(condition, taint, format...) \
DO_ONCE_LITE_IF(condition, WARN_TAINT, 1, taint, format)
#else /* !CONFIG_BUG */
#ifndef HAVE_ARCH_BUG
#define BUG() do { \
do {} while (1); \
unreachable(); \
} while (0)
#endif
#ifndef HAVE_ARCH_BUG_ON
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
#endif
#ifndef HAVE_ARCH_WARN_ON
#define WARN_ON(condition) ({ \
int __ret_warn_on = !!(condition); \
unlikely(__ret_warn_on); \
})
#endif
#ifndef WARN
#define WARN(condition, format...) ({ \
int __ret_warn_on = !!(condition); \
no_printk(format); \
unlikely(__ret_warn_on); \
})
#endif
#define WARN_ON_ONCE(condition) WARN_ON(condition)
#define WARN_ONCE(condition, format...) WARN(condition, format)
#define WARN_TAINT(condition, taint, format...) WARN(condition, format)
#define WARN_TAINT_ONCE(condition, taint, format...) WARN(condition, format)
#endif
/*
* WARN_ON_SMP() is for cases that the warning is either
* meaningless for !SMP or may even cause failures.
* It can also be used with values that are only defined
* on SMP:
*
* struct foo {
* [...]
* #ifdef CONFIG_SMP
* int bar;
* #endif
* };
*
* void func(struct foo *zoot)
* {
* WARN_ON_SMP(!zoot->bar);
*
* For CONFIG_SMP, WARN_ON_SMP() should act the same as WARN_ON(),
* and should be a nop and return false for uniprocessor.
*
* if (WARN_ON_SMP(x)) returns true only when CONFIG_SMP is set
* and x is true.
*/
#ifdef CONFIG_SMP
# define WARN_ON_SMP(x) WARN_ON(x)
#else
/*
* Use of ({0;}) because WARN_ON_SMP(x) may be used either as
* a stand alone line statement or as a condition in an if ()
* statement.
* A simple "0" would cause gcc to give a "statement has no effect"
* warning.
*/
# define WARN_ON_SMP(x) ({0;})
#endif
#endif /* __ASSEMBLY__ */
#endif
+13
View File
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_CACHE_H
#define __ASM_GENERIC_CACHE_H
/*
* 32 bytes appears to be the most common cache line size,
* so make that the default here. Architectures with larger
* cache lines need to provide their own cache.h.
*/
#define L1_CACHE_SHIFT 5
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#endif /* __ASM_GENERIC_CACHE_H */
@@ -0,0 +1,127 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_CACHEFLUSH_H
#define _ASM_GENERIC_CACHEFLUSH_H
#include <linux/instrumented.h>
struct mm_struct;
struct vm_area_struct;
struct page;
struct address_space;
/*
* The cache doesn't need to be flushed when TLB entries change when
* the cache is mapped to physical memory, not virtual memory
*/
#ifndef flush_cache_all
static inline void flush_cache_all(void)
{
}
#endif
#ifndef flush_cache_mm
static inline void flush_cache_mm(struct mm_struct *mm)
{
}
#endif
#ifndef flush_cache_dup_mm
static inline void flush_cache_dup_mm(struct mm_struct *mm)
{
}
#endif
#ifndef flush_cache_range
static inline void flush_cache_range(struct vm_area_struct *vma,
unsigned long start,
unsigned long end)
{
}
#endif
#ifndef flush_cache_page
static inline void flush_cache_page(struct vm_area_struct *vma,
unsigned long vmaddr,
unsigned long pfn)
{
}
#endif
#ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
static inline void flush_dcache_page(struct page *page)
{
}
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
#endif
#ifndef flush_dcache_mmap_lock
static inline void flush_dcache_mmap_lock(struct address_space *mapping)
{
}
#endif
#ifndef flush_dcache_mmap_unlock
static inline void flush_dcache_mmap_unlock(struct address_space *mapping)
{
}
#endif
#ifndef flush_icache_range
static inline void flush_icache_range(unsigned long start, unsigned long end)
{
}
#endif
#ifndef flush_icache_user_range
#define flush_icache_user_range flush_icache_range
#endif
#ifndef flush_icache_user_page
static inline void flush_icache_user_page(struct vm_area_struct *vma,
struct page *page,
unsigned long addr, int len)
{
}
#endif
#ifndef flush_cache_vmap
static inline void flush_cache_vmap(unsigned long start, unsigned long end)
{
}
#endif
#ifndef flush_cache_vmap_early
static inline void flush_cache_vmap_early(unsigned long start, unsigned long end)
{
}
#endif
#ifndef flush_cache_vunmap
static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
{
}
#endif
#ifndef copy_to_user_page
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
instrument_copy_to_user((void __user *)dst, src, len); \
memcpy(dst, src, len); \
flush_icache_user_page(vma, page, vaddr, len); \
} while (0)
#endif
#ifndef copy_from_user_page
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
do { \
instrument_copy_from_user_before(dst, (void __user *)src, \
len); \
memcpy(dst, src, len); \
instrument_copy_from_user_after(dst, (void __user *)src, len, \
0); \
} while (0)
#endif
#endif /* _ASM_GENERIC_CACHEFLUSH_H */
+5
View File
@@ -0,0 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_CFI_H
#define __ASM_GENERIC_CFI_H
#endif /* __ASM_GENERIC_CFI_H */
@@ -0,0 +1,65 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_CHECKSUM_H
#define __ASM_GENERIC_CHECKSUM_H
#include <linux/bitops.h>
/*
* computes the checksum of a memory block at buff, length len,
* and adds in "sum" (32-bit)
*
* returns a 32-bit number suitable for feeding into itself
* or csum_tcpudp_magic
*
* this function must be called with even lengths, except
* for the last fragment, which may be odd
*
* it's best to have buff aligned on a 32-bit boundary
*/
extern __wsum csum_partial(const void *buff, int len, __wsum sum);
#ifndef ip_fast_csum
/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
#endif
#ifndef csum_fold
/*
* Fold a partial checksum
*/
static inline __sum16 csum_fold(__wsum csum)
{
u32 sum = (__force u32)csum;
return (__force __sum16)((~sum - ror32(sum, 16)) >> 16);
}
#endif
#ifndef csum_tcpudp_nofold
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
extern __wsum
csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len,
__u8 proto, __wsum sum);
#endif
#ifndef csum_tcpudp_magic
static inline __sum16
csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len,
__u8 proto, __wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
}
#endif
/*
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
extern __sum16 ip_compute_csum(const void *buff, int len);
#endif /* __ASM_GENERIC_CHECKSUM_H */
@@ -0,0 +1,68 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_CMPXCHG_LOCAL_H
#define __ASM_GENERIC_CMPXCHG_LOCAL_H
#include <linux/types.h>
#include <linux/irqflags.h>
extern unsigned long wrong_size_cmpxchg(volatile void *ptr)
__noreturn;
/*
* Generic version of __cmpxchg_local (disables interrupts). Takes an unsigned
* long parameter, supporting various types of architectures.
*/
static inline unsigned long __generic_cmpxchg_local(volatile void *ptr,
unsigned long old, unsigned long new, int size)
{
unsigned long flags, prev;
/*
* Sanity checking, compile-time.
*/
if (size == 8 && sizeof(unsigned long) != 8)
wrong_size_cmpxchg(ptr);
raw_local_irq_save(flags);
switch (size) {
case 1: prev = *(u8 *)ptr;
if (prev == (old & 0xffu))
*(u8 *)ptr = (new & 0xffu);
break;
case 2: prev = *(u16 *)ptr;
if (prev == (old & 0xffffu))
*(u16 *)ptr = (new & 0xffffu);
break;
case 4: prev = *(u32 *)ptr;
if (prev == (old & 0xffffffffu))
*(u32 *)ptr = (new & 0xffffffffu);
break;
case 8: prev = *(u64 *)ptr;
if (prev == old)
*(u64 *)ptr = (u64)new;
break;
default:
wrong_size_cmpxchg(ptr);
}
raw_local_irq_restore(flags);
return prev;
}
/*
* Generic version of __cmpxchg64_local. Takes an u64 parameter.
*/
static inline u64 __generic_cmpxchg64_local(volatile void *ptr,
u64 old, u64 new)
{
u64 prev;
unsigned long flags;
raw_local_irq_save(flags);
prev = *(u64 *)ptr;
if (prev == old)
*(u64 *)ptr = new;
raw_local_irq_restore(flags);
return prev;
}
#endif
+115
View File
@@ -0,0 +1,115 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Generic UP xchg and cmpxchg using interrupt disablement. Does not
* support SMP.
*/
#ifndef __ASM_GENERIC_CMPXCHG_H
#define __ASM_GENERIC_CMPXCHG_H
#ifdef CONFIG_SMP
#error "Cannot use generic cmpxchg on SMP"
#endif
#include <linux/types.h>
#include <linux/irqflags.h>
/*
* This function doesn't exist, so you'll get a linker error if
* something tries to do an invalidly-sized xchg().
*/
extern void __generic_xchg_called_with_bad_pointer(void);
static inline
unsigned long __generic_xchg(unsigned long x, volatile void *ptr, int size)
{
unsigned long ret, flags;
switch (size) {
case 1:
#ifdef __xchg_u8
return __xchg_u8(x, ptr);
#else
local_irq_save(flags);
ret = *(volatile u8 *)ptr;
*(volatile u8 *)ptr = (x & 0xffu);
local_irq_restore(flags);
return ret;
#endif /* __xchg_u8 */
case 2:
#ifdef __xchg_u16
return __xchg_u16(x, ptr);
#else
local_irq_save(flags);
ret = *(volatile u16 *)ptr;
*(volatile u16 *)ptr = (x & 0xffffu);
local_irq_restore(flags);
return ret;
#endif /* __xchg_u16 */
case 4:
#ifdef __xchg_u32
return __xchg_u32(x, ptr);
#else
local_irq_save(flags);
ret = *(volatile u32 *)ptr;
*(volatile u32 *)ptr = (x & 0xffffffffu);
local_irq_restore(flags);
return ret;
#endif /* __xchg_u32 */
#ifdef CONFIG_64BIT
case 8:
#ifdef __xchg_u64
return __xchg_u64(x, ptr);
#else
local_irq_save(flags);
ret = *(volatile u64 *)ptr;
*(volatile u64 *)ptr = x;
local_irq_restore(flags);
return ret;
#endif /* __xchg_u64 */
#endif /* CONFIG_64BIT */
default:
__generic_xchg_called_with_bad_pointer();
return x;
}
}
#define generic_xchg(ptr, x) ({ \
((__typeof__(*(ptr))) \
__generic_xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))); \
})
/*
* Atomic compare and exchange.
*/
#include <asm-generic/cmpxchg-local.h>
#define generic_cmpxchg_local(ptr, o, n) ({ \
((__typeof__(*(ptr)))__generic_cmpxchg_local((ptr), (unsigned long)(o), \
(unsigned long)(n), sizeof(*(ptr)))); \
})
#define generic_cmpxchg64_local(ptr, o, n) \
__generic_cmpxchg64_local((ptr), (o), (n))
#ifndef arch_xchg
#define arch_xchg generic_xchg
#endif
#ifndef arch_cmpxchg_local
#define arch_cmpxchg_local generic_cmpxchg_local
#endif
#ifndef arch_cmpxchg64_local
#define arch_cmpxchg64_local generic_cmpxchg64_local
#endif
#define arch_cmpxchg arch_cmpxchg_local
#define arch_cmpxchg64 arch_cmpxchg64_local
#endif /* __ASM_GENERIC_CMPXCHG_H */
@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __ASM_GENERIC_CODETAG_LDS_H
#define __ASM_GENERIC_CODETAG_LDS_H
#ifdef CONFIG_MEM_ALLOC_PROFILING
#define IF_MEM_ALLOC_PROFILING(...) __VA_ARGS__
#else
#define IF_MEM_ALLOC_PROFILING(...)
#endif
#define SECTION_WITH_BOUNDARIES(_name) \
. = ALIGN(8); \
__start_##_name = .; \
KEEP(*(_name)) \
__stop_##_name = .;
#define CODETAG_SECTIONS() \
IF_MEM_ALLOC_PROFILING(SECTION_WITH_BOUNDARIES(alloc_tags))
#define MOD_SEPARATE_CODETAG_SECTION(_name) \
.codetag.##_name 0 : { \
SECTION_WITH_BOUNDARIES(_name) \
}
/*
* For codetags which might be used after module unload, therefore might stay
* longer in memory. Each such codetag type has its own section so that we can
* unload them individually once unused.
*/
#define MOD_SEPARATE_CODETAG_SECTIONS() \
IF_MEM_ALLOC_PROFILING(MOD_SEPARATE_CODETAG_SECTION(alloc_tags))
#endif /* __ASM_GENERIC_CODETAG_LDS_H */
+168
View File
@@ -0,0 +1,168 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_COMPAT_H
#define __ASM_GENERIC_COMPAT_H
#ifndef COMPAT_USER_HZ
#define COMPAT_USER_HZ 100
#endif
#ifndef COMPAT_RLIM_INFINITY
#define COMPAT_RLIM_INFINITY 0xffffffff
#endif
#ifndef COMPAT_OFF_T_MAX
#define COMPAT_OFF_T_MAX 0x7fffffff
#endif
#ifndef compat_arg_u64
#ifndef CONFIG_CPU_BIG_ENDIAN
#define compat_arg_u64(name) u32 name##_lo, u32 name##_hi
#define compat_arg_u64_dual(name) u32, name##_lo, u32, name##_hi
#else
#define compat_arg_u64(name) u32 name##_hi, u32 name##_lo
#define compat_arg_u64_dual(name) u32, name##_hi, u32, name##_lo
#endif
#define compat_arg_u64_glue(name) (((u64)name##_lo & 0xffffffffUL) | \
((u64)name##_hi << 32))
#endif /* compat_arg_u64 */
/* These types are common across all compat ABIs */
typedef u32 compat_size_t;
typedef s32 compat_ssize_t;
typedef s32 compat_clock_t;
typedef s32 compat_pid_t;
typedef u32 compat_ino_t;
typedef s32 compat_off_t;
typedef s64 compat_loff_t;
typedef s32 compat_daddr_t;
typedef s32 compat_timer_t;
typedef s32 compat_key_t;
typedef s16 compat_short_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
typedef u16 compat_ushort_t;
typedef u32 compat_uint_t;
typedef u32 compat_ulong_t;
typedef u32 compat_uptr_t;
typedef u32 compat_caddr_t;
typedef u32 compat_aio_context_t;
typedef u32 compat_old_sigset_t;
#ifndef __compat_uid_t
typedef u32 __compat_uid_t;
typedef u32 __compat_gid_t;
#endif
#ifndef __compat_uid32_t
typedef u32 __compat_uid32_t;
typedef u32 __compat_gid32_t;
#endif
#ifndef compat_mode_t
typedef u32 compat_mode_t;
#endif
#ifdef CONFIG_COMPAT_FOR_U64_ALIGNMENT
typedef s64 __attribute__((aligned(4))) compat_s64;
typedef u64 __attribute__((aligned(4))) compat_u64;
#else
typedef s64 compat_s64;
typedef u64 compat_u64;
#endif
#ifndef _COMPAT_NSIG
typedef u32 compat_sigset_word;
#define _COMPAT_NSIG _NSIG
#define _COMPAT_NSIG_BPW 32
#endif
#ifndef compat_dev_t
typedef u32 compat_dev_t;
#endif
#ifndef compat_ipc_pid_t
typedef s32 compat_ipc_pid_t;
#endif
#ifndef compat_fsid_t
typedef __kernel_fsid_t compat_fsid_t;
#endif
#ifndef compat_statfs
struct compat_statfs {
compat_int_t f_type;
compat_int_t f_bsize;
compat_int_t f_blocks;
compat_int_t f_bfree;
compat_int_t f_bavail;
compat_int_t f_files;
compat_int_t f_ffree;
compat_fsid_t f_fsid;
compat_int_t f_namelen;
compat_int_t f_frsize;
compat_int_t f_flags;
compat_int_t f_spare[4];
};
#endif
#ifndef compat_ipc64_perm
struct compat_ipc64_perm {
compat_key_t key;
__compat_uid32_t uid;
__compat_gid32_t gid;
__compat_uid32_t cuid;
__compat_gid32_t cgid;
compat_mode_t mode;
unsigned char __pad1[4 - sizeof(compat_mode_t)];
compat_ushort_t seq;
compat_ushort_t __pad2;
compat_ulong_t unused1;
compat_ulong_t unused2;
};
struct compat_semid64_ds {
struct compat_ipc64_perm sem_perm;
compat_ulong_t sem_otime;
compat_ulong_t sem_otime_high;
compat_ulong_t sem_ctime;
compat_ulong_t sem_ctime_high;
compat_ulong_t sem_nsems;
compat_ulong_t __unused3;
compat_ulong_t __unused4;
};
struct compat_msqid64_ds {
struct compat_ipc64_perm msg_perm;
compat_ulong_t msg_stime;
compat_ulong_t msg_stime_high;
compat_ulong_t msg_rtime;
compat_ulong_t msg_rtime_high;
compat_ulong_t msg_ctime;
compat_ulong_t msg_ctime_high;
compat_ulong_t msg_cbytes;
compat_ulong_t msg_qnum;
compat_ulong_t msg_qbytes;
compat_pid_t msg_lspid;
compat_pid_t msg_lrpid;
compat_ulong_t __unused4;
compat_ulong_t __unused5;
};
struct compat_shmid64_ds {
struct compat_ipc64_perm shm_perm;
compat_size_t shm_segsz;
compat_ulong_t shm_atime;
compat_ulong_t shm_atime_high;
compat_ulong_t shm_dtime;
compat_ulong_t shm_dtime_high;
compat_ulong_t shm_ctime;
compat_ulong_t shm_ctime_high;
compat_pid_t shm_cpid;
compat_pid_t shm_lpid;
compat_ulong_t shm_nattch;
compat_ulong_t __unused4;
compat_ulong_t __unused5;
};
#endif
#endif
+12
View File
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_CURRENT_H
#define __ASM_GENERIC_CURRENT_H
#ifndef __ASSEMBLY__
#include <linux/thread_info.h>
#define get_current() (current_thread_info()->task)
#define current get_current()
#endif
#endif /* __ASM_GENERIC_CURRENT_H */
+87
View File
@@ -0,0 +1,87 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_DELAY_H
#define __ASM_GENERIC_DELAY_H
#include <linux/math.h>
#include <vdso/time64.h>
/* Undefined functions to get compile-time errors */
extern void __bad_udelay(void);
extern void __bad_ndelay(void);
extern void __udelay(unsigned long usecs);
extern void __ndelay(unsigned long nsecs);
extern void __const_udelay(unsigned long xloops);
extern void __delay(unsigned long loops);
/*
* The microseconds/nanosecond delay multiplicators are used to convert a
* constant microseconds/nanoseconds value to a value which can be used by the
* architectures specific implementation to transform it into loops.
*/
#define UDELAY_CONST_MULT ((unsigned long)DIV_ROUND_UP(1ULL << 32, USEC_PER_SEC))
#define NDELAY_CONST_MULT ((unsigned long)DIV_ROUND_UP(1ULL << 32, NSEC_PER_SEC))
/*
* The maximum constant udelay/ndelay value picked out of thin air to prevent
* too long constant udelays/ndelays.
*/
#define DELAY_CONST_MAX 20000
/**
* udelay - Inserting a delay based on microseconds with busy waiting
* @usec: requested delay in microseconds
*
* When delaying in an atomic context ndelay(), udelay() and mdelay() are the
* only valid variants of delaying/sleeping to go with.
*
* When inserting delays in non atomic context which are shorter than the time
* which is required to queue e.g. an hrtimer and to enter then the scheduler,
* it is also valuable to use udelay(). But it is not simple to specify a
* generic threshold for this which will fit for all systems. An approximation
* is a threshold for all delays up to 10 microseconds.
*
* When having a delay which is larger than the architecture specific
* %MAX_UDELAY_MS value, please make sure mdelay() is used. Otherwise a overflow
* risk is given.
*
* Please note that ndelay(), udelay() and mdelay() may return early for several
* reasons (https://lists.openwall.net/linux-kernel/2011/01/09/56):
*
* #. computed loops_per_jiffy too low (due to the time taken to execute the
* timer interrupt.)
* #. cache behaviour affecting the time it takes to execute the loop function.
* #. CPU clock rate changes.
*/
static __always_inline void udelay(unsigned long usec)
{
if (__builtin_constant_p(usec)) {
if (usec >= DELAY_CONST_MAX)
__bad_udelay();
else
__const_udelay(usec * UDELAY_CONST_MULT);
} else {
__udelay(usec);
}
}
/**
* ndelay - Inserting a delay based on nanoseconds with busy waiting
* @nsec: requested delay in nanoseconds
*
* See udelay() for basic information about ndelay() and it's variants.
*/
static __always_inline void ndelay(unsigned long nsec)
{
if (__builtin_constant_p(nsec)) {
if (nsec >= DELAY_CONST_MAX)
__bad_ndelay();
else
__const_udelay(nsec * NDELAY_CONST_MULT);
} else {
__ndelay(nsec);
}
}
#define ndelay(x) ndelay(x)
#endif /* __ASM_GENERIC_DELAY_H */
+14
View File
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Arch specific extensions to struct device
*/
#ifndef _ASM_GENERIC_DEVICE_H
#define _ASM_GENERIC_DEVICE_H
struct dev_archdata {
};
struct pdev_archdata {
};
#endif /* _ASM_GENERIC_DEVICE_H */
+210
View File
@@ -0,0 +1,210 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_DIV64_H
#define _ASM_GENERIC_DIV64_H
/*
* Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
* Based on former asm-ppc/div64.h and asm-m68knommu/div64.h
*
* Optimization for constant divisors on 32-bit machines:
* Copyright (C) 2006-2015 Nicolas Pitre
*
* The semantics of do_div() is, in C++ notation, observing that the name
* is a function-like macro and the n parameter has the semantics of a C++
* reference:
*
* uint32_t do_div(uint64_t &n, uint32_t base)
* {
* uint32_t remainder = n % base;
* n = n / base;
* return remainder;
* }
*
* NOTE: macro parameter n is evaluated multiple times,
* beware of side effects!
*/
#include <linux/types.h>
#include <linux/compiler.h>
#if BITS_PER_LONG == 64
/**
* do_div - returns 2 values: calculate remainder and update new dividend
* @n: uint64_t dividend (will be updated)
* @base: uint32_t divisor
*
* Summary:
* ``uint32_t remainder = n % base;``
* ``n = n / base;``
*
* Return: (uint32_t)remainder
*
* NOTE: macro parameter @n is evaluated multiple times,
* beware of side effects!
*/
# define do_div(n,base) ({ \
uint32_t __base = (base); \
uint32_t __rem; \
__rem = ((uint64_t)(n)) % __base; \
(n) = ((uint64_t)(n)) / __base; \
__rem; \
})
#elif BITS_PER_LONG == 32
#include <linux/log2.h>
/*
* If the divisor happens to be constant, we determine the appropriate
* inverse at compile time to turn the division into a few inline
* multiplications which ought to be much faster.
*
* (It is unfortunate that gcc doesn't perform all this internally.)
*/
#define __div64_const32(n, ___b) \
({ \
/* \
* Multiplication by reciprocal of b: n / b = n * (p / b) / p \
* \
* We rely on the fact that most of this code gets optimized \
* away at compile time due to constant propagation and only \
* a few multiplication instructions should remain. \
* Hence this monstrous macro (static inline doesn't always \
* do the trick here). \
*/ \
uint64_t ___res, ___x, ___t, ___m, ___n = (n); \
uint32_t ___p; \
bool ___bias = false; \
\
/* determine MSB of b */ \
___p = 1 << ilog2(___b); \
\
/* compute m = ((p << 64) + b - 1) / b */ \
___m = (~0ULL / ___b) * ___p; \
___m += (((~0ULL % ___b + 1) * ___p) + ___b - 1) / ___b; \
\
/* one less than the dividend with highest result */ \
___x = ~0ULL / ___b * ___b - 1; \
\
/* test our ___m with res = m * x / (p << 64) */ \
___res = (___m & 0xffffffff) * (___x & 0xffffffff); \
___t = (___m & 0xffffffff) * (___x >> 32) + (___res >> 32); \
___res = (___m >> 32) * (___x >> 32) + (___t >> 32); \
___t = (___m >> 32) * (___x & 0xffffffff) + (___t & 0xffffffff);\
___res = (___res + (___t >> 32)) / ___p; \
\
/* Now validate what we've got. */ \
if (___res != ___x / ___b) { \
/* \
* We can't get away without a bias to compensate \
* for bit truncation errors. To avoid it we'd need an \
* additional bit to represent m which would overflow \
* a 64-bit variable. \
* \
* Instead we do m = p / b and n / b = (n * m + m) / p. \
*/ \
___bias = true; \
/* Compute m = (p << 64) / b */ \
___m = (~0ULL / ___b) * ___p; \
___m += ((~0ULL % ___b + 1) * ___p) / ___b; \
} \
\
/* Reduce m / p to help avoid overflow handling later. */ \
___p /= (___m & -___m); \
___m /= (___m & -___m); \
\
/* \
* Perform (m_bias + m * n) / (1 << 64). \
* From now on there will be actual runtime code generated. \
*/ \
___res = __arch_xprod_64(___m, ___n, ___bias); \
\
___res /= ___p; \
})
#ifndef __arch_xprod_64
/*
* Default C implementation for __arch_xprod_64()
*
* Prototype: uint64_t __arch_xprod_64(const uint64_t m, uint64_t n, bool bias)
* Semantic: retval = ((bias ? m : 0) + m * n) >> 64
*
* The product is a 128-bit value, scaled down to 64 bits.
* Hoping for compile-time optimization of conditional code.
* Architectures may provide their own optimized assembly implementation.
*/
#ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
static __always_inline
#else
static inline
#endif
uint64_t __arch_xprod_64(const uint64_t m, uint64_t n, bool bias)
{
uint32_t m_lo = m;
uint32_t m_hi = m >> 32;
uint32_t n_lo = n;
uint32_t n_hi = n >> 32;
uint64_t x, y;
/* Determine if overflow handling can be dispensed with. */
bool no_ovf = __builtin_constant_p(m) &&
((m >> 32) + (m & 0xffffffff) < 0x100000000);
if (no_ovf) {
x = (uint64_t)m_lo * n_lo + (bias ? m : 0);
x >>= 32;
x += (uint64_t)m_lo * n_hi;
x += (uint64_t)m_hi * n_lo;
x >>= 32;
x += (uint64_t)m_hi * n_hi;
} else {
x = (uint64_t)m_lo * n_lo + (bias ? m_lo : 0);
y = (uint64_t)m_lo * n_hi + (uint32_t)(x >> 32) + (bias ? m_hi : 0);
x = (uint64_t)m_hi * n_hi + (uint32_t)(y >> 32);
y = (uint64_t)m_hi * n_lo + (uint32_t)y;
x += (uint32_t)(y >> 32);
}
return x;
}
#endif
#ifndef __div64_32
extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
#endif
/* The unnecessary pointer compare is there
* to check for type safety (n must be 64bit)
*/
# define do_div(n,base) ({ \
uint32_t __base = (base); \
uint32_t __rem; \
(void)(((typeof((n)) *)0) == ((uint64_t *)0)); \
if (__builtin_constant_p(__base) && \
is_power_of_2(__base)) { \
__rem = (n) & (__base - 1); \
(n) >>= ilog2(__base); \
} else if (__builtin_constant_p(__base) && \
__base != 0) { \
uint32_t __res_lo, __n_lo = (n); \
(n) = __div64_const32(n, __base); \
/* the remainder can be computed with 32-bit regs */ \
__res_lo = (n); \
__rem = __n_lo - __res_lo * __base; \
} else if (likely(((n) >> 32) == 0)) { \
__rem = (uint32_t)(n) % __base; \
(n) = (uint32_t)(n) / __base; \
} else { \
__rem = __div64_32(&(n), __base); \
} \
__rem; \
})
#else /* BITS_PER_LONG == ?? */
# error do_div() does not yet support the C64
#endif /* BITS_PER_LONG */
#endif /* _ASM_GENERIC_DIV64_H */
@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_DMA_MAPPING_H
#define _ASM_GENERIC_DMA_MAPPING_H
static inline const struct dma_map_ops *get_arch_dma_ops(void)
{
return NULL;
}
#endif /* _ASM_GENERIC_DMA_MAPPING_H */
+16
View File
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_DMA_H
#define __ASM_GENERIC_DMA_H
/*
* This file traditionally describes the i8237 PC style DMA controller.
* Most architectures don't have these any more and can get the minimal
* implementation from kernel/dma.c by not defining MAX_DMA_CHANNELS.
*
* Some code relies on seeing MAX_DMA_ADDRESS though.
*/
#define MAX_DMA_ADDRESS PAGE_OFFSET
extern int request_dma(unsigned int dmanr, const char *device_id);
extern void free_dma(unsigned int dmanr);
#endif /* __ASM_GENERIC_DMA_H */
@@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_EARLY_IOREMAP_H_
#define _ASM_EARLY_IOREMAP_H_
#include <linux/types.h>
/*
* early_ioremap() and early_iounmap() are for temporary early boot-time
* mappings, before the real ioremap() is functional.
*/
extern void __iomem *early_ioremap(resource_size_t phys_addr,
unsigned long size);
extern void *early_memremap(resource_size_t phys_addr,
unsigned long size);
extern void *early_memremap_ro(resource_size_t phys_addr,
unsigned long size);
extern void *early_memremap_prot(resource_size_t phys_addr,
unsigned long size, unsigned long prot_val);
extern void early_iounmap(void __iomem *addr, unsigned long size);
extern void early_memunmap(void *addr, unsigned long size);
#if defined(CONFIG_GENERIC_EARLY_IOREMAP) && defined(CONFIG_MMU)
/* Arch-specific initialization */
extern void early_ioremap_init(void);
/* Generic initialization called by architecture code */
extern void early_ioremap_setup(void);
/*
* Called as last step in paging_init() so library can act
* accordingly for subsequent map/unmap requests.
*/
extern void early_ioremap_reset(void);
/*
* Early copy from unmapped memory to kernel mapped memory.
*/
extern int copy_from_early_mem(void *dest, phys_addr_t src,
unsigned long size);
#else
static inline void early_ioremap_init(void) { }
static inline void early_ioremap_setup(void) { }
static inline void early_ioremap_reset(void) { }
#endif
#endif /* _ASM_EARLY_IOREMAP_H_ */
@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_EMERGENCY_RESTART_H
#define _ASM_GENERIC_EMERGENCY_RESTART_H
static inline void machine_emergency_restart(void)
{
machine_restart(NULL);
}
#endif /* _ASM_GENERIC_EMERGENCY_RESTART_H */
@@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_ERROR_INJECTION_H
#define _ASM_GENERIC_ERROR_INJECTION_H
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
enum {
EI_ETYPE_NULL, /* Return NULL if failure */
EI_ETYPE_ERRNO, /* Return -ERRNO if failure */
EI_ETYPE_ERRNO_NULL, /* Return -ERRNO or NULL if failure */
EI_ETYPE_TRUE, /* Return true if failure */
};
struct error_injection_entry {
unsigned long addr;
int etype;
};
struct pt_regs;
#ifdef CONFIG_FUNCTION_ERROR_INJECTION
/*
* Whitelist generating macro. Specify functions which can be error-injectable
* using this macro. If you unsure what is required for the error-injectable
* functions, please read Documentation/fault-injection/fault-injection.rst
* 'Error Injectable Functions' section.
*/
#define ALLOW_ERROR_INJECTION(fname, _etype) \
static struct error_injection_entry __used \
__section("_error_injection_whitelist") \
_eil_addr_##fname = { \
.addr = (unsigned long)fname, \
.etype = EI_ETYPE_##_etype, \
}
void override_function_with_return(struct pt_regs *regs);
#else
#define ALLOW_ERROR_INJECTION(fname, _etype)
static inline void override_function_with_return(struct pt_regs *regs) { }
#endif
#endif
#endif /* _ASM_GENERIC_ERROR_INJECTION_H */
+15
View File
@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Generic process execution definitions.
*
* It should be possible to use these on really simple architectures,
* but it serves more as a starting point for new ports.
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifndef __ASM_GENERIC_EXEC_H
#define __ASM_GENERIC_EXEC_H
#define arch_align_stack(x) (x)
#endif /* __ASM_GENERIC_EXEC_H */
+27
View File
@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_EXTABLE_H
#define __ASM_GENERIC_EXTABLE_H
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
* the address at which the program should continue. No registers are
* modified, so it is entirely up to the continuation code to figure out
* what to do.
*
* All the routines below use bits of fixup code that are out of line
* with the main instruction path. This means when everything is well,
* we don't even have to jump over them. Further, they do not intrude
* on our cache or tlb entries.
*/
struct exception_table_entry
{
unsigned long insn, fixup;
};
struct pt_regs;
extern int fixup_exception(struct pt_regs *regs);
#endif
+101
View File
@@ -0,0 +1,101 @@
/*
* fixmap.h: compile-time virtual memory allocation
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1998 Ingo Molnar
*
* Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
* x86_32 and x86_64 integration by Gustavo F. Padovan, February 2009
* Break out common bits to asm-generic by Mark Salter, November 2013
*/
#ifndef __ASM_GENERIC_FIXMAP_H
#define __ASM_GENERIC_FIXMAP_H
#include <linux/bug.h>
#include <linux/mm_types.h>
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
#ifndef __ASSEMBLY__
/*
* 'index to address' translation. If anyone tries to use the idx
* directly without translation, we catch the bug with a NULL-deference
* kernel oops. Illegal ranges of incoming indices are caught too.
*/
static __always_inline unsigned long fix_to_virt(const unsigned int idx)
{
BUILD_BUG_ON(idx >= __end_of_fixed_addresses);
return __fix_to_virt(idx);
}
static inline unsigned long virt_to_fix(const unsigned long vaddr)
{
BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
return __virt_to_fix(vaddr);
}
/*
* Provide some reasonable defaults for page flags.
* Not all architectures use all of these different types and some
* architectures use different names.
*/
#ifndef FIXMAP_PAGE_NORMAL
#define FIXMAP_PAGE_NORMAL PAGE_KERNEL
#endif
#if !defined(FIXMAP_PAGE_RO) && defined(PAGE_KERNEL_RO)
#define FIXMAP_PAGE_RO PAGE_KERNEL_RO
#endif
#ifndef FIXMAP_PAGE_NOCACHE
#define FIXMAP_PAGE_NOCACHE PAGE_KERNEL_NOCACHE
#endif
#ifndef FIXMAP_PAGE_IO
#define FIXMAP_PAGE_IO PAGE_KERNEL_IO
#endif
#ifndef FIXMAP_PAGE_CLEAR
#define FIXMAP_PAGE_CLEAR __pgprot(0)
#endif
#ifndef set_fixmap
#define set_fixmap(idx, phys) \
__set_fixmap(idx, phys, FIXMAP_PAGE_NORMAL)
#endif
#ifndef clear_fixmap
#define clear_fixmap(idx) \
__set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR)
#endif
/* Return a pointer with offset calculated */
#define __set_fixmap_offset(idx, phys, flags) \
({ \
unsigned long ________addr; \
__set_fixmap(idx, phys, flags); \
________addr = fix_to_virt(idx) + ((phys) & (PAGE_SIZE - 1)); \
________addr; \
})
#define set_fixmap_offset(idx, phys) \
__set_fixmap_offset(idx, phys, FIXMAP_PAGE_NORMAL)
/*
* Some hardware wants to get fixmapped without caching.
*/
#define set_fixmap_nocache(idx, phys) \
__set_fixmap(idx, phys, FIXMAP_PAGE_NOCACHE)
#define set_fixmap_offset_nocache(idx, phys) \
__set_fixmap_offset(idx, phys, FIXMAP_PAGE_NOCACHE)
/*
* Some fixmaps are for IO
*/
#define set_fixmap_io(idx, phys) \
__set_fixmap(idx, phys, FIXMAP_PAGE_IO)
#endif /* __ASSEMBLY__ */
#endif /* __ASM_GENERIC_FIXMAP_H */
+26
View File
@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_FLAT_H
#define _ASM_GENERIC_FLAT_H
#include <linux/uaccess.h>
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
u32 *addr)
{
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
return copy_from_user(addr, rp, 4) ? -EFAULT : 0;
#else
return get_user(*addr, rp);
#endif
}
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
{
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
return copy_to_user(rp, &addr, 4) ? -EFAULT : 0;
#else
return put_user(addr, rp);
#endif
}
#endif /* _ASM_GENERIC_FLAT_H */
+46
View File
@@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Generic arch dependent fprobe macros.
*/
#ifndef __ASM_GENERIC_FPROBE_H__
#define __ASM_GENERIC_FPROBE_H__
#include <linux/bits.h>
#ifdef CONFIG_64BIT
/*
* Encoding the size and the address of fprobe into one 64bit entry.
* The 32bit architectures should use 2 entries to store those info.
*/
#define ARCH_DEFINE_ENCODE_FPROBE_HEADER
#define FPROBE_HEADER_MSB_SIZE_SHIFT (BITS_PER_LONG - FPROBE_DATA_SIZE_BITS)
#define FPROBE_HEADER_MSB_MASK \
GENMASK(FPROBE_HEADER_MSB_SIZE_SHIFT - 1, 0)
/*
* By default, this expects the MSBs in the address of kprobe is 0xf.
* If any arch needs another fixed pattern (e.g. s390 is zero filled),
* override this.
*/
#define FPROBE_HEADER_MSB_PATTERN \
GENMASK(BITS_PER_LONG - 1, FPROBE_HEADER_MSB_SIZE_SHIFT)
#define arch_fprobe_header_encodable(fp) \
(((unsigned long)(fp) & ~FPROBE_HEADER_MSB_MASK) == \
FPROBE_HEADER_MSB_PATTERN)
#define arch_encode_fprobe_header(fp, size) \
(((unsigned long)(fp) & FPROBE_HEADER_MSB_MASK) | \
((unsigned long)(size) << FPROBE_HEADER_MSB_SIZE_SHIFT))
#define arch_decode_fprobe_header_size(val) \
((unsigned long)(val) >> FPROBE_HEADER_MSB_SIZE_SHIFT)
#define arch_decode_fprobe_header_fp(val) \
((struct fprobe *)(((unsigned long)(val) & FPROBE_HEADER_MSB_MASK) | \
FPROBE_HEADER_MSB_PATTERN))
#endif /* CONFIG_64BIT */
#endif /* __ASM_GENERIC_FPROBE_H__ */
+13
View File
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* linux/include/asm-generic/ftrace.h
*/
#ifndef __ASM_GENERIC_FTRACE_H__
#define __ASM_GENERIC_FTRACE_H__
/*
* Not all architectures need their own ftrace.h, the most
* common definitions are already in linux/ftrace.h.
*/
#endif /* __ASM_GENERIC_FTRACE_H__ */
+123
View File
@@ -0,0 +1,123 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_FUTEX_H
#define _ASM_GENERIC_FUTEX_H
#include <linux/futex.h>
#include <linux/uaccess.h>
#include <asm/errno.h>
#ifndef futex_atomic_cmpxchg_inatomic
#ifndef CONFIG_SMP
/*
* The following implementation only for uniprocessor machines.
* It relies on preempt_disable() ensuring mutual exclusion.
*
*/
#define futex_atomic_cmpxchg_inatomic(uval, uaddr, oldval, newval) \
futex_atomic_cmpxchg_inatomic_local(uval, uaddr, oldval, newval)
#define arch_futex_atomic_op_inuser(op, oparg, oval, uaddr) \
futex_atomic_op_inuser_local(op, oparg, oval, uaddr)
#endif /* CONFIG_SMP */
#endif
/**
* futex_atomic_op_inuser_local() - Atomic arithmetic operation with constant
* argument and comparison of the previous
* futex value with another constant.
*
* @op: operation to execute
* @oparg: argument of the operation
* @oval: previous value at @uaddr on successful return
* @uaddr: pointer to user space address
*
* Return:
* 0 - On success
* -EFAULT - User access resulted in a page fault
* -EAGAIN - Atomic operation was unable to complete due to contention
* -ENOSYS - Operation not supported
*/
static inline int
futex_atomic_op_inuser_local(int op, u32 oparg, int *oval, u32 __user *uaddr)
{
int oldval, ret;
u32 tmp;
preempt_disable();
ret = -EFAULT;
if (unlikely(get_user(oldval, uaddr) != 0))
goto out_pagefault_enable;
ret = 0;
tmp = oldval;
switch (op) {
case FUTEX_OP_SET:
tmp = oparg;
break;
case FUTEX_OP_ADD:
tmp += oparg;
break;
case FUTEX_OP_OR:
tmp |= oparg;
break;
case FUTEX_OP_ANDN:
tmp &= ~oparg;
break;
case FUTEX_OP_XOR:
tmp ^= oparg;
break;
default:
ret = -ENOSYS;
}
if (ret == 0 && unlikely(put_user(tmp, uaddr) != 0))
ret = -EFAULT;
out_pagefault_enable:
preempt_enable();
if (ret == 0)
*oval = oldval;
return ret;
}
/**
* futex_atomic_cmpxchg_inatomic_local() - Compare and exchange the content of the
* uaddr with newval if the current value is
* oldval.
* @uval: pointer to store content of @uaddr
* @uaddr: pointer to user space address
* @oldval: old value
* @newval: new value to store to @uaddr
*
* Return:
* 0 - On success
* -EFAULT - User access resulted in a page fault
* -EAGAIN - Atomic operation was unable to complete due to contention
*/
static inline int
futex_atomic_cmpxchg_inatomic_local(u32 *uval, u32 __user *uaddr,
u32 oldval, u32 newval)
{
u32 val;
preempt_disable();
if (unlikely(get_user(val, uaddr) != 0)) {
preempt_enable();
return -EFAULT;
}
if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) {
preempt_enable();
return -EFAULT;
}
*uval = val;
preempt_enable();
return 0;
}
#endif
@@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_GETORDER_H
#define __ASM_GENERIC_GETORDER_H
#ifndef __ASSEMBLY__
#include <linux/compiler.h>
#include <linux/log2.h>
/**
* get_order - Determine the allocation order of a memory size
* @size: The size for which to get the order
*
* Determine the allocation order of a particular sized block of memory. This
* is on a logarithmic scale, where:
*
* 0 -> 2^0 * PAGE_SIZE and below
* 1 -> 2^1 * PAGE_SIZE to 2^0 * PAGE_SIZE + 1
* 2 -> 2^2 * PAGE_SIZE to 2^1 * PAGE_SIZE + 1
* 3 -> 2^3 * PAGE_SIZE to 2^2 * PAGE_SIZE + 1
* 4 -> 2^4 * PAGE_SIZE to 2^3 * PAGE_SIZE + 1
* ...
*
* The order returned is used to find the smallest allocation granule required
* to hold an object of the specified size.
*
* The result is undefined if the size is 0.
*/
static __always_inline __attribute_const__ int get_order(unsigned long size)
{
if (__builtin_constant_p(size)) {
if (!size)
return BITS_PER_LONG - PAGE_SHIFT;
if (size < (1UL << PAGE_SHIFT))
return 0;
return ilog2((size) - 1) - PAGE_SHIFT + 1;
}
size--;
size >>= PAGE_SHIFT;
#if BITS_PER_LONG == 32
return fls(size);
#else
return fls64(size);
#endif
}
#endif /* __ASSEMBLY__ */
#endif /* __ASM_GENERIC_GETORDER_H */
+26
View File
@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_HARDIRQ_H
#define __ASM_GENERIC_HARDIRQ_H
#include <linux/cache.h>
#include <linux/threads.h>
typedef struct {
unsigned int __softirq_pending;
#ifdef ARCH_WANTS_NMI_IRQSTAT
unsigned int __nmi_count;
#endif
} ____cacheline_aligned irq_cpustat_t;
DECLARE_PER_CPU_ALIGNED(irq_cpustat_t, irq_stat);
#include <linux/irq.h>
#ifndef ack_bad_irq
static inline void ack_bad_irq(unsigned int irq)
{
printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
}
#endif
#endif /* __ASM_GENERIC_HARDIRQ_H */
+131
View File
@@ -0,0 +1,131 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_HUGETLB_H
#define _ASM_GENERIC_HUGETLB_H
#include <linux/swap.h>
#include <linux/swapops.h>
static inline unsigned long huge_pte_write(pte_t pte)
{
return pte_write(pte);
}
static inline unsigned long huge_pte_dirty(pte_t pte)
{
return pte_dirty(pte);
}
static inline pte_t huge_pte_mkwrite(pte_t pte)
{
return pte_mkwrite_novma(pte);
}
#ifndef __HAVE_ARCH_HUGE_PTE_WRPROTECT
static inline pte_t huge_pte_wrprotect(pte_t pte)
{
return pte_wrprotect(pte);
}
#endif
static inline pte_t huge_pte_mkdirty(pte_t pte)
{
return pte_mkdirty(pte);
}
static inline pte_t huge_pte_modify(pte_t pte, pgprot_t newprot)
{
return pte_modify(pte, newprot);
}
#ifndef __HAVE_ARCH_HUGE_PTE_MKUFFD_WP
static inline pte_t huge_pte_mkuffd_wp(pte_t pte)
{
return huge_pte_wrprotect(pte_mkuffd_wp(pte));
}
#endif
#ifndef __HAVE_ARCH_HUGE_PTE_CLEAR_UFFD_WP
static inline pte_t huge_pte_clear_uffd_wp(pte_t pte)
{
return pte_clear_uffd_wp(pte);
}
#endif
#ifndef __HAVE_ARCH_HUGE_PTE_UFFD_WP
static inline int huge_pte_uffd_wp(pte_t pte)
{
return pte_uffd_wp(pte);
}
#endif
#ifndef __HAVE_ARCH_HUGE_PTE_CLEAR
static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, unsigned long sz)
{
pte_clear(mm, addr, ptep);
}
#endif
#ifndef __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte, unsigned long sz)
{
set_pte_at(mm, addr, ptep, pte);
}
#endif
#ifndef __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
unsigned long addr, pte_t *ptep, unsigned long sz)
{
return ptep_get_and_clear(mm, addr, ptep);
}
#endif
#ifndef __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep)
{
return ptep_clear_flush(vma, addr, ptep);
}
#endif
#ifndef __HAVE_ARCH_HUGE_PTE_NONE
static inline int huge_pte_none(pte_t pte)
{
return pte_none(pte);
}
#endif
#ifndef __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
{
ptep_set_wrprotect(mm, addr, ptep);
}
#endif
#ifndef __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep,
pte_t pte, int dirty)
{
return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
}
#endif
#ifndef __HAVE_ARCH_HUGE_PTEP_GET
static inline pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
return ptep_get(ptep);
}
#endif
#ifndef __HAVE_ARCH_GIGANTIC_PAGE_RUNTIME_SUPPORTED
static inline bool gigantic_page_runtime_supported(void)
{
return IS_ENABLED(CONFIG_ARCH_HAS_GIGANTIC_PAGE);
}
#endif /* __HAVE_ARCH_GIGANTIC_PAGE_RUNTIME_SUPPORTED */
#endif /* _ASM_GENERIC_HUGETLB_H */
+9
View File
@@ -0,0 +1,9 @@
#ifndef __ASM_GENERIC_HW_IRQ_H
#define __ASM_GENERIC_HW_IRQ_H
/*
* hw_irq.h has internal declarations for the low-level interrupt
* controller, like the original i8259A.
* In general, this is not needed for new architectures.
*/
#endif /* __ASM_GENERIC_HW_IRQ_H */
@@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* asm-generic/int-ll64.h
*
* Integer declarations for architectures which use "long long"
* for 64-bit types.
*/
#ifndef _ASM_GENERIC_INT_LL64_H
#define _ASM_GENERIC_INT_LL64_H
#include <uapi/asm-generic/int-ll64.h>
#ifndef __ASSEMBLY__
typedef __s8 s8;
typedef __u8 u8;
typedef __s16 s16;
typedef __u16 u16;
typedef __s32 s32;
typedef __u32 u32;
typedef __s64 s64;
typedef __u64 u64;
#define S8_C(x) x
#define U8_C(x) x ## U
#define S16_C(x) x
#define U16_C(x) x ## U
#define S32_C(x) x
#define U32_C(x) x ## U
#define S64_C(x) x ## LL
#define U64_C(x) x ## ULL
#else /* __ASSEMBLY__ */
#define S8_C(x) x
#define U8_C(x) x
#define S16_C(x) x
#define U16_C(x) x
#define S32_C(x) x
#define U32_C(x) x
#define S64_C(x) x
#define U64_C(x) x
#endif /* __ASSEMBLY__ */
#endif /* _ASM_GENERIC_INT_LL64_H */
File diff suppressed because it is too large Load Diff
+18
View File
@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_IOCTL_H
#define _ASM_GENERIC_IOCTL_H
#include <uapi/asm-generic/ioctl.h>
#ifdef __CHECKER__
#define _IOC_TYPECHECK(t) (sizeof(t))
#else
/* provoke compile error for invalid uses of size argument */
extern unsigned int __invalid_size_argument_for_IOC;
#define _IOC_TYPECHECK(t) \
((sizeof(t) == sizeof(t[1]) && \
sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
sizeof(t) : __invalid_size_argument_for_IOC)
#endif
#endif /* _ASM_GENERIC_IOCTL_H */
+95
View File
@@ -0,0 +1,95 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __GENERIC_IO_H
#define __GENERIC_IO_H
#include <linux/linkage.h>
#include <asm/byteorder.h>
/*
* These are the "generic" interfaces for doing new-style
* memory-mapped or PIO accesses. Architectures may do
* their own arch-optimized versions, these just act as
* wrappers around the old-style IO register access functions:
* read[bwl]/write[bwl]/in[bwl]/out[bwl]
*
* Don't include this directly, include it from <asm/io.h>.
*/
/*
* Read/write from/to an (offsettable) iomem cookie. It might be a PIO
* access or a MMIO access, these functions don't care. The info is
* encoded in the hardware mapping set up by the mapping functions
* (or the cookie itself, depending on implementation and hw).
*
* The generic routines just encode the PIO/MMIO as part of the
* cookie, and coldly assume that the MMIO IO mappings are not
* in the low address range. Architectures for which this is not
* true can't use this generic implementation.
*/
extern unsigned int ioread8(const void __iomem *);
extern unsigned int ioread16(const void __iomem *);
extern unsigned int ioread16be(const void __iomem *);
extern unsigned int ioread32(const void __iomem *);
extern unsigned int ioread32be(const void __iomem *);
extern u64 __ioread64_lo_hi(const void __iomem *addr);
extern u64 __ioread64_hi_lo(const void __iomem *addr);
extern u64 __ioread64be_lo_hi(const void __iomem *addr);
extern u64 __ioread64be_hi_lo(const void __iomem *addr);
extern void iowrite8(u8, void __iomem *);
extern void iowrite16(u16, void __iomem *);
extern void iowrite16be(u16, void __iomem *);
extern void iowrite32(u32, void __iomem *);
extern void iowrite32be(u32, void __iomem *);
extern void __iowrite64_lo_hi(u64 val, void __iomem *addr);
extern void __iowrite64_hi_lo(u64 val, void __iomem *addr);
extern void __iowrite64be_lo_hi(u64 val, void __iomem *addr);
extern void __iowrite64be_hi_lo(u64 val, void __iomem *addr);
/*
* "string" versions of the above. Note that they
* use native byte ordering for the accesses (on
* the assumption that IO and memory agree on a
* byte order, and CPU byteorder is irrelevant).
*
* They do _not_ update the port address. If you
* want MMIO that copies stuff laid out in MMIO
* memory across multiple ports, use "memcpy_toio()"
* and friends.
*/
extern void ioread8_rep(const void __iomem *port, void *buf, unsigned long count);
extern void ioread16_rep(const void __iomem *port, void *buf, unsigned long count);
extern void ioread32_rep(const void __iomem *port, void *buf, unsigned long count);
extern void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count);
extern void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count);
extern void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count);
#ifdef CONFIG_HAS_IOPORT_MAP
/* Create a virtual mapping cookie for an IO port range */
extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
extern void ioport_unmap(void __iomem *);
#endif
#ifndef ioremap_wc
#define ioremap_wc ioremap
#endif
#ifndef ioremap_wt
#define ioremap_wt ioremap
#endif
#ifndef ioremap_np
/* See the comment in asm-generic/io.h about ioremap_np(). */
#define ioremap_np ioremap_np
static inline void __iomem *ioremap_np(phys_addr_t offset, size_t size)
{
return NULL;
}
#endif
#include <asm-generic/pci_iomap.h>
#endif
+19
View File
@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_IRQ_H
#define __ASM_GENERIC_IRQ_H
/*
* NR_IRQS is the upper bound of how many interrupts can be handled
* in the platform. It is used to size the static irq_map array,
* so don't make it too big.
*/
#ifndef NR_IRQS
#define NR_IRQS 64
#endif
static inline int irq_canonicalize(int irq)
{
return irq;
}
#endif /* __ASM_GENERIC_IRQ_H */
@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Fallback per-CPU frame pointer holder
*
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifndef _ASM_GENERIC_IRQ_REGS_H
#define _ASM_GENERIC_IRQ_REGS_H
#include <linux/percpu.h>
/*
* Per-cpu current frame pointer - the location of the last exception frame on
* the stack
*/
DECLARE_PER_CPU(struct pt_regs *, __irq_regs);
static inline struct pt_regs *get_irq_regs(void)
{
return __this_cpu_read(__irq_regs);
}
static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
{
struct pt_regs *old_regs;
old_regs = __this_cpu_read(__irq_regs);
__this_cpu_write(__irq_regs, new_regs);
return old_regs;
}
#endif /* _ASM_GENERIC_IRQ_REGS_H */
@@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_IRQ_WORK_H
#define __ASM_IRQ_WORK_H
static inline bool arch_irq_work_has_interrupt(void)
{
return false;
}
#endif /* __ASM_IRQ_WORK_H */
@@ -0,0 +1,67 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_IRQFLAGS_H
#define __ASM_GENERIC_IRQFLAGS_H
/*
* All architectures should implement at least the first two functions,
* usually inline assembly will be the best way.
*/
#ifndef ARCH_IRQ_DISABLED
#define ARCH_IRQ_DISABLED 0
#define ARCH_IRQ_ENABLED 1
#endif
/* read interrupt enabled status */
#ifndef arch_local_save_flags
unsigned long arch_local_save_flags(void);
#endif
/* set interrupt enabled status */
#ifndef arch_local_irq_restore
void arch_local_irq_restore(unsigned long flags);
#endif
/* get status and disable interrupts */
#ifndef arch_local_irq_save
static inline unsigned long arch_local_irq_save(void)
{
unsigned long flags;
flags = arch_local_save_flags();
arch_local_irq_restore(ARCH_IRQ_DISABLED);
return flags;
}
#endif
/* test flags */
#ifndef arch_irqs_disabled_flags
static inline int arch_irqs_disabled_flags(unsigned long flags)
{
return flags == ARCH_IRQ_DISABLED;
}
#endif
/* unconditionally enable interrupts */
#ifndef arch_local_irq_enable
static inline void arch_local_irq_enable(void)
{
arch_local_irq_restore(ARCH_IRQ_ENABLED);
}
#endif
/* unconditionally disable interrupts */
#ifndef arch_local_irq_disable
static inline void arch_local_irq_disable(void)
{
arch_local_irq_restore(ARCH_IRQ_DISABLED);
}
#endif
/* test hardware interrupt enable bit */
#ifndef arch_irqs_disabled
static inline int arch_irqs_disabled(void)
{
return arch_irqs_disabled_flags(arch_local_save_flags());
}
#endif
#endif /* __ASM_GENERIC_IRQFLAGS_H */
+10
View File
@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_KDEBUG_H
#define _ASM_GENERIC_KDEBUG_H
enum die_val {
DIE_UNUSED,
DIE_OOPS = 1,
};
#endif /* _ASM_GENERIC_KDEBUG_H */
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_KMAP_SIZE_H
#define _ASM_GENERIC_KMAP_SIZE_H
/* For debug this provides guard pages between the maps */
#ifdef CONFIG_DEBUG_KMAP_LOCAL
# define KM_MAX_IDX 33
#else
# define KM_MAX_IDX 16
#endif
#endif
+26
View File
@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_KPROBES_H
#define _ASM_GENERIC_KPROBES_H
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
#ifdef CONFIG_KPROBES
/*
* Blacklist ganerating macro. Specify functions which is not probed
* by using this macro.
*/
# define __NOKPROBE_SYMBOL(fname) \
static unsigned long __used \
__section("_kprobe_blacklist") \
_kbl_addr_##fname = (unsigned long)fname;
# define NOKPROBE_SYMBOL(fname) __NOKPROBE_SYMBOL(fname)
/* Use this to forbid a kprobes attach on very low level functions */
# define __kprobes notrace __section(".kprobes.text")
# define nokprobe_inline __always_inline
#else
# define NOKPROBE_SYMBOL(fname)
# define __kprobes
# define nokprobe_inline inline
#endif
#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
#endif /* _ASM_GENERIC_KPROBES_H */
@@ -0,0 +1,32 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_KVM_PARA_H
#define _ASM_GENERIC_KVM_PARA_H
#include <uapi/asm-generic/kvm_para.h>
/*
* This function is used by architectures that support kvm to avoid issuing
* false soft lockup messages.
*/
static inline bool kvm_check_and_clear_guest_paused(void)
{
return false;
}
static inline unsigned int kvm_arch_para_features(void)
{
return 0;
}
static inline unsigned int kvm_arch_para_hints(void)
{
return 0;
}
static inline bool kvm_para_available(void)
{
return false;
}
#endif
@@ -0,0 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_KVM_TYPES_H
#define _ASM_GENERIC_KVM_TYPES_H
#endif
@@ -0,0 +1,8 @@
#ifndef __ASM_GENERIC_LINKAGE_H
#define __ASM_GENERIC_LINKAGE_H
/*
* linux/linkage.h provides reasonable defaults.
* an architecture can override them by providing its own version.
*/
#endif /* __ASM_GENERIC_LINKAGE_H */
+57
View File
@@ -0,0 +1,57 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_LOCAL_H
#define _ASM_GENERIC_LOCAL_H
#include <linux/percpu.h>
#include <linux/atomic.h>
#include <asm/types.h>
/*
* A signed long type for operations which are atomic for a single CPU.
* Usually used in combination with per-cpu variables.
*
* This is the default implementation, which uses atomic_long_t. Which is
* rather pointless. The whole point behind local_t is that some processors
* can perform atomic adds and subtracts in a manner which is atomic wrt IRQs
* running on this CPU. local_t allows exploitation of such capabilities.
*/
/* Implement in terms of atomics. */
/* Don't use typedef: don't want them to be mixed with atomic_t's. */
typedef struct
{
atomic_long_t a;
} local_t;
#define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) }
#define local_read(l) atomic_long_read(&(l)->a)
#define local_set(l,i) atomic_long_set((&(l)->a),(i))
#define local_inc(l) atomic_long_inc(&(l)->a)
#define local_dec(l) atomic_long_dec(&(l)->a)
#define local_add(i,l) atomic_long_add((i),(&(l)->a))
#define local_sub(i,l) atomic_long_sub((i),(&(l)->a))
#define local_sub_and_test(i, l) atomic_long_sub_and_test((i), (&(l)->a))
#define local_dec_and_test(l) atomic_long_dec_and_test(&(l)->a)
#define local_inc_and_test(l) atomic_long_inc_and_test(&(l)->a)
#define local_add_negative(i, l) atomic_long_add_negative((i), (&(l)->a))
#define local_add_return(i, l) atomic_long_add_return((i), (&(l)->a))
#define local_sub_return(i, l) atomic_long_sub_return((i), (&(l)->a))
#define local_inc_return(l) atomic_long_inc_return(&(l)->a)
#define local_cmpxchg(l, o, n) atomic_long_cmpxchg((&(l)->a), (o), (n))
#define local_try_cmpxchg(l, po, n) atomic_long_try_cmpxchg((&(l)->a), (po), (n))
#define local_xchg(l, n) atomic_long_xchg((&(l)->a), (n))
#define local_add_unless(l, _a, u) atomic_long_add_unless((&(l)->a), (_a), (u))
#define local_inc_not_zero(l) atomic_long_inc_not_zero(&(l)->a)
/* Non-atomic variants, ie. preemption disabled and won't be touched
* in interrupt, etc. Some archs can optimize this case well. */
#define __local_inc(l) local_set((l), local_read(l) + 1)
#define __local_dec(l) local_set((l), local_read(l) - 1)
#define __local_add(i,l) local_set((l), local_read(l) + (i))
#define __local_sub(i,l) local_set((l), local_read(l) - (i))
#endif /* _ASM_GENERIC_LOCAL_H */
+107
View File
@@ -0,0 +1,107 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_LOCAL64_H
#define _ASM_GENERIC_LOCAL64_H
#include <linux/percpu.h>
#include <asm/types.h>
/*
* A signed long type for operations which are atomic for a single CPU.
* Usually used in combination with per-cpu variables.
*
* This is the default implementation, which uses atomic64_t. Which is
* rather pointless. The whole point behind local64_t is that some processors
* can perform atomic adds and subtracts in a manner which is atomic wrt IRQs
* running on this CPU. local64_t allows exploitation of such capabilities.
*/
/* Implement in terms of atomics. */
#if BITS_PER_LONG == 64
#include <asm/local.h>
typedef struct {
local_t a;
} local64_t;
#define LOCAL64_INIT(i) { LOCAL_INIT(i) }
#define local64_read(l) local_read(&(l)->a)
#define local64_set(l,i) local_set((&(l)->a),(i))
#define local64_inc(l) local_inc(&(l)->a)
#define local64_dec(l) local_dec(&(l)->a)
#define local64_add(i,l) local_add((i),(&(l)->a))
#define local64_sub(i,l) local_sub((i),(&(l)->a))
#define local64_sub_and_test(i, l) local_sub_and_test((i), (&(l)->a))
#define local64_dec_and_test(l) local_dec_and_test(&(l)->a)
#define local64_inc_and_test(l) local_inc_and_test(&(l)->a)
#define local64_add_negative(i, l) local_add_negative((i), (&(l)->a))
#define local64_add_return(i, l) local_add_return((i), (&(l)->a))
#define local64_sub_return(i, l) local_sub_return((i), (&(l)->a))
#define local64_inc_return(l) local_inc_return(&(l)->a)
static inline s64 local64_cmpxchg(local64_t *l, s64 old, s64 new)
{
return local_cmpxchg(&l->a, old, new);
}
static inline bool local64_try_cmpxchg(local64_t *l, s64 *old, s64 new)
{
return local_try_cmpxchg(&l->a, (long *)old, new);
}
#define local64_xchg(l, n) local_xchg((&(l)->a), (n))
#define local64_add_unless(l, _a, u) local_add_unless((&(l)->a), (_a), (u))
#define local64_inc_not_zero(l) local_inc_not_zero(&(l)->a)
/* Non-atomic variants, ie. preemption disabled and won't be touched
* in interrupt, etc. Some archs can optimize this case well. */
#define __local64_inc(l) local64_set((l), local64_read(l) + 1)
#define __local64_dec(l) local64_set((l), local64_read(l) - 1)
#define __local64_add(i,l) local64_set((l), local64_read(l) + (i))
#define __local64_sub(i,l) local64_set((l), local64_read(l) - (i))
#else /* BITS_PER_LONG != 64 */
#include <linux/atomic.h>
/* Don't use typedef: don't want them to be mixed with atomic_t's. */
typedef struct {
atomic64_t a;
} local64_t;
#define LOCAL64_INIT(i) { ATOMIC_LONG_INIT(i) }
#define local64_read(l) atomic64_read(&(l)->a)
#define local64_set(l,i) atomic64_set((&(l)->a),(i))
#define local64_inc(l) atomic64_inc(&(l)->a)
#define local64_dec(l) atomic64_dec(&(l)->a)
#define local64_add(i,l) atomic64_add((i),(&(l)->a))
#define local64_sub(i,l) atomic64_sub((i),(&(l)->a))
#define local64_sub_and_test(i, l) atomic64_sub_and_test((i), (&(l)->a))
#define local64_dec_and_test(l) atomic64_dec_and_test(&(l)->a)
#define local64_inc_and_test(l) atomic64_inc_and_test(&(l)->a)
#define local64_add_negative(i, l) atomic64_add_negative((i), (&(l)->a))
#define local64_add_return(i, l) atomic64_add_return((i), (&(l)->a))
#define local64_sub_return(i, l) atomic64_sub_return((i), (&(l)->a))
#define local64_inc_return(l) atomic64_inc_return(&(l)->a)
#define local64_cmpxchg(l, o, n) atomic64_cmpxchg((&(l)->a), (o), (n))
#define local64_try_cmpxchg(l, po, n) atomic64_try_cmpxchg((&(l)->a), (po), (n))
#define local64_xchg(l, n) atomic64_xchg((&(l)->a), (n))
#define local64_add_unless(l, _a, u) atomic64_add_unless((&(l)->a), (_a), (u))
#define local64_inc_not_zero(l) atomic64_inc_not_zero(&(l)->a)
/* Non-atomic variants, ie. preemption disabled and won't be touched
* in interrupt, etc. Some archs can optimize this case well. */
#define __local64_inc(l) local64_set((l), local64_read(l) + 1)
#define __local64_dec(l) local64_set((l), local64_read(l) - 1)
#define __local64_add(i,l) local64_set((l), local64_read(l) + (i))
#define __local64_sub(i,l) local64_set((l), local64_read(l) - (i))
#endif /* BITS_PER_LONG != 64 */
#endif /* _ASM_GENERIC_LOCAL64_H */
@@ -0,0 +1,78 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021 Intel Corporation
* Author: johannes@sipsolutions.net
*/
#ifndef _LOGIC_IO_H
#define _LOGIC_IO_H
#include <linux/types.h>
/* include this file into asm/io.h */
#ifdef CONFIG_INDIRECT_IOMEM
#ifdef CONFIG_INDIRECT_IOMEM_FALLBACK
/*
* If you want emulated IO memory to fall back to 'normal' IO memory
* if a region wasn't registered as emulated, then you need to have
* all of the real_* functions implemented.
*/
#if !defined(real_ioremap) || !defined(real_iounmap) || \
!defined(real_raw_readb) || !defined(real_raw_writeb) || \
!defined(real_raw_readw) || !defined(real_raw_writew) || \
!defined(real_raw_readl) || !defined(real_raw_writel) || \
(defined(CONFIG_64BIT) && \
(!defined(real_raw_readq) || !defined(real_raw_writeq))) || \
!defined(real_memset_io) || \
!defined(real_memcpy_fromio) || \
!defined(real_memcpy_toio)
#error "Must provide fallbacks for real IO memory access"
#endif /* defined ... */
#endif /* CONFIG_INDIRECT_IOMEM_FALLBACK */
#define ioremap ioremap
void __iomem *ioremap(phys_addr_t offset, size_t size);
#define iounmap iounmap
void iounmap(void volatile __iomem *addr);
#define __raw_readb __raw_readb
u8 __raw_readb(const volatile void __iomem *addr);
#define __raw_readw __raw_readw
u16 __raw_readw(const volatile void __iomem *addr);
#define __raw_readl __raw_readl
u32 __raw_readl(const volatile void __iomem *addr);
#ifdef CONFIG_64BIT
#define __raw_readq __raw_readq
u64 __raw_readq(const volatile void __iomem *addr);
#endif /* CONFIG_64BIT */
#define __raw_writeb __raw_writeb
void __raw_writeb(u8 value, volatile void __iomem *addr);
#define __raw_writew __raw_writew
void __raw_writew(u16 value, volatile void __iomem *addr);
#define __raw_writel __raw_writel
void __raw_writel(u32 value, volatile void __iomem *addr);
#ifdef CONFIG_64BIT
#define __raw_writeq __raw_writeq
void __raw_writeq(u64 value, volatile void __iomem *addr);
#endif /* CONFIG_64BIT */
#define memset_io memset_io
void memset_io(volatile void __iomem *addr, int value, size_t size);
#define memcpy_fromio memcpy_fromio
void memcpy_fromio(void *buffer, const volatile void __iomem *addr,
size_t size);
#define memcpy_toio memcpy_toio
void memcpy_toio(volatile void __iomem *addr, const void *buffer, size_t size);
#endif /* CONFIG_INDIRECT_IOMEM */
#endif /* _LOGIC_IO_H */
@@ -0,0 +1,19 @@
#ifndef __ASM_MCS_SPINLOCK_H
#define __ASM_MCS_SPINLOCK_H
struct mcs_spinlock {
struct mcs_spinlock *next;
int locked; /* 1 if lock acquired */
int count; /* nesting count, see qspinlock.c */
};
/*
* Architectures can define their own:
*
* arch_mcs_spin_lock_contended(l)
* arch_mcs_spin_unlock_contended(l)
*
* See kernel/locking/mcs_spinlock.c.
*/
#endif /* __ASM_MCS_SPINLOCK_H */
@@ -0,0 +1,91 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_MEMORY_MODEL_H
#define __ASM_MEMORY_MODEL_H
#include <linux/pfn.h>
#ifndef __ASSEMBLY__
/*
* supports 3 memory models.
*/
#if defined(CONFIG_FLATMEM)
#ifndef ARCH_PFN_OFFSET
#define ARCH_PFN_OFFSET (0UL)
#endif
#define __pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET))
#define __page_to_pfn(page) ((unsigned long)((page) - mem_map) + \
ARCH_PFN_OFFSET)
/* avoid <linux/mm.h> include hell */
extern unsigned long max_mapnr;
#ifndef pfn_valid
static inline int pfn_valid(unsigned long pfn)
{
unsigned long pfn_offset = ARCH_PFN_OFFSET;
return pfn >= pfn_offset && (pfn - pfn_offset) < max_mapnr;
}
#define pfn_valid pfn_valid
#ifndef for_each_valid_pfn
#define for_each_valid_pfn(pfn, start_pfn, end_pfn) \
for ((pfn) = max_t(unsigned long, (start_pfn), ARCH_PFN_OFFSET); \
(pfn) < min_t(unsigned long, (end_pfn), \
ARCH_PFN_OFFSET + max_mapnr); \
(pfn)++)
#endif /* for_each_valid_pfn */
#endif /* valid_pfn */
#elif defined(CONFIG_SPARSEMEM_VMEMMAP)
/* memmap is virtually contiguous. */
#define __pfn_to_page(pfn) (vmemmap + (pfn))
#define __page_to_pfn(page) (unsigned long)((page) - vmemmap)
#elif defined(CONFIG_SPARSEMEM)
/*
* Note: section's mem_map is encoded to reflect its start_pfn.
* section[i].section_mem_map == mem_map's address - start_pfn;
*/
#define __page_to_pfn(pg) \
({ const struct page *__pg = (pg); \
int __sec = memdesc_section(__pg->flags); \
(unsigned long)(__pg - __section_mem_map_addr(__nr_to_section(__sec))); \
})
#define __pfn_to_page(pfn) \
({ unsigned long __pfn = (pfn); \
struct mem_section *__sec = __pfn_to_section(__pfn); \
__section_mem_map_addr(__sec) + __pfn; \
})
#endif /* CONFIG_FLATMEM/SPARSEMEM */
/*
* Convert a physical address to a Page Frame Number and back
*/
#define __phys_to_pfn(paddr) PHYS_PFN(paddr)
#define __pfn_to_phys(pfn) PFN_PHYS(pfn)
#define page_to_pfn __page_to_pfn
#define pfn_to_page __pfn_to_page
#ifdef CONFIG_DEBUG_VIRTUAL
#define page_to_phys(page) \
({ \
unsigned long __pfn = page_to_pfn(page); \
\
WARN_ON_ONCE(!pfn_valid(__pfn)); \
PFN_PHYS(__pfn); \
})
#else
#define page_to_phys(page) PFN_PHYS(page_to_pfn(page))
#endif /* CONFIG_DEBUG_VIRTUAL */
#define phys_to_page(phys) pfn_to_page(PHYS_PFN(phys))
#endif /* __ASSEMBLY__ */
#endif
@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Define generic no-op hooks for arch_dup_mmap and arch_exit_mmap
* to be included in asm-FOO/mmu_context.h for any arch FOO which
* doesn't need to hook these.
*/
#ifndef _ASM_GENERIC_MM_HOOKS_H
#define _ASM_GENERIC_MM_HOOKS_H
static inline int arch_dup_mmap(struct mm_struct *oldmm,
struct mm_struct *mm)
{
return 0;
}
static inline void arch_exit_mmap(struct mm_struct *mm)
{
}
static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
bool write, bool execute, bool foreign)
{
/* by default, allow everything */
return true;
}
#endif /* _ASM_GENERIC_MM_HOOKS_H */
+65
View File
@@ -0,0 +1,65 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_MMIOWB_H
#define __ASM_GENERIC_MMIOWB_H
/*
* Generic implementation of mmiowb() tracking for spinlocks.
*
* If your architecture doesn't ensure that writes to an I/O peripheral
* within two spinlocked sections on two different CPUs are seen by the
* peripheral in the order corresponding to the lock handover, then you
* need to follow these FIVE easy steps:
*
* 1. Implement mmiowb() (and arch_mmiowb_state() if you're fancy)
* in asm/mmiowb.h, then #include this file
* 2. Ensure your I/O write accessors call mmiowb_set_pending()
* 3. Select ARCH_HAS_MMIOWB
* 4. Untangle the resulting mess of header files
* 5. Complain to your architects
*/
#ifdef CONFIG_MMIOWB
#include <linux/compiler.h>
#include <asm-generic/mmiowb_types.h>
#ifndef arch_mmiowb_state
#include <asm/percpu.h>
#include <asm/smp.h>
DECLARE_PER_CPU(struct mmiowb_state, __mmiowb_state);
#define __mmiowb_state() raw_cpu_ptr(&__mmiowb_state)
#else
#define __mmiowb_state() arch_mmiowb_state()
#endif /* arch_mmiowb_state */
static inline void mmiowb_set_pending(void)
{
struct mmiowb_state *ms = __mmiowb_state();
if (likely(ms->nesting_count))
ms->mmiowb_pending = ms->nesting_count;
}
static inline void mmiowb_spin_lock(void)
{
struct mmiowb_state *ms = __mmiowb_state();
ms->nesting_count++;
}
static inline void mmiowb_spin_unlock(void)
{
struct mmiowb_state *ms = __mmiowb_state();
if (unlikely(ms->mmiowb_pending)) {
ms->mmiowb_pending = 0;
mmiowb();
}
ms->nesting_count--;
}
#else
#define mmiowb_set_pending() do { } while (0)
#define mmiowb_spin_lock() do { } while (0)
#define mmiowb_spin_unlock() do { } while (0)
#endif /* CONFIG_MMIOWB */
#endif /* __ASM_GENERIC_MMIOWB_H */
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_MMIOWB_TYPES_H
#define __ASM_GENERIC_MMIOWB_TYPES_H
#include <linux/types.h>
struct mmiowb_state {
u16 nesting_count;
u16 mmiowb_pending;
};
#endif /* __ASM_GENERIC_MMIOWB_TYPES_H */
+20
View File
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_MMU_H
#define __ASM_GENERIC_MMU_H
/*
* This is the mmu.h header for nommu implementations.
* Architectures with an MMU need something more complex.
*/
#ifndef __ASSEMBLY__
typedef struct {
unsigned long end_brk;
#ifdef CONFIG_BINFMT_ELF_FDPIC
unsigned long exec_fdpic_loadmap;
unsigned long interp_fdpic_loadmap;
#endif
} mm_context_t;
#endif
#endif /* __ASM_GENERIC_MMU_H */
@@ -0,0 +1,76 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_MMU_CONTEXT_H
#define __ASM_GENERIC_MMU_CONTEXT_H
/*
* Generic hooks to implement no-op functionality.
*/
struct task_struct;
struct mm_struct;
/*
* enter_lazy_tlb - Called when "tsk" is about to enter lazy TLB mode.
*
* @mm: the currently active mm context which is becoming lazy
* @tsk: task which is entering lazy tlb
*
* tsk->mm will be NULL
*/
#ifndef enter_lazy_tlb
static inline void enter_lazy_tlb(struct mm_struct *mm,
struct task_struct *tsk)
{
}
#endif
/**
* init_new_context - Initialize context of a new mm_struct.
* @tsk: task struct for the mm
* @mm: the new mm struct
* @return: 0 on success, -errno on failure
*/
#ifndef init_new_context
static inline int init_new_context(struct task_struct *tsk,
struct mm_struct *mm)
{
return 0;
}
#endif
/**
* destroy_context - Undo init_new_context when the mm is going away
* @mm: old mm struct
*/
#ifndef destroy_context
static inline void destroy_context(struct mm_struct *mm)
{
}
#endif
/**
* activate_mm - called after exec switches the current task to a new mm, to switch to it
* @prev_mm: previous mm of this task
* @next_mm: new mm
*/
#ifndef activate_mm
static inline void activate_mm(struct mm_struct *prev_mm,
struct mm_struct *next_mm)
{
switch_mm(prev_mm, next_mm, current);
}
#endif
/**
* dectivate_mm - called when an mm is released after exit or exec switches away from it
* @tsk: the task
* @mm: the old mm
*/
#ifndef deactivate_mm
static inline void deactivate_mm(struct task_struct *tsk,
struct mm_struct *mm)
{
}
#endif
#endif /* __ASM_GENERIC_MMU_CONTEXT_H */
+5
View File
@@ -0,0 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_GENERIC_MMZONE_H
#define _ASM_GENERIC_MMZONE_H
#endif
+41
View File
@@ -0,0 +1,41 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_MODULE_H
#define __ASM_GENERIC_MODULE_H
/*
* Many architectures just need a simple module
* loader without arch specific data.
*/
#ifndef CONFIG_HAVE_MOD_ARCH_SPECIFIC
struct mod_arch_specific
{
};
#endif
#ifdef CONFIG_64BIT
#define Elf_Shdr Elf64_Shdr
#define Elf_Phdr Elf64_Phdr
#define Elf_Sym Elf64_Sym
#define Elf_Dyn Elf64_Dyn
#define Elf_Ehdr Elf64_Ehdr
#define Elf_Addr Elf64_Addr
#define Elf_Rel Elf64_Rel
#define Elf_Rela Elf64_Rela
#define ELF_R_TYPE(X) ELF64_R_TYPE(X)
#define ELF_R_SYM(X) ELF64_R_SYM(X)
#else /* CONFIG_64BIT */
#define Elf_Shdr Elf32_Shdr
#define Elf_Phdr Elf32_Phdr
#define Elf_Sym Elf32_Sym
#define Elf_Dyn Elf32_Dyn
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Addr Elf32_Addr
#define Elf_Rel Elf32_Rel
#define Elf_Rela Elf32_Rela
#define ELF_R_TYPE(X) ELF32_R_TYPE(X)
#define ELF_R_SYM(X) ELF32_R_SYM(X)
#endif
#endif /* __ASM_GENERIC_MODULE_H */
@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __ASM_GENERIC_MODULE_LDS_H
#define __ASM_GENERIC_MODULE_LDS_H
/*
* <asm/module.lds.h> can specify arch-specific sections for linking modules.
* Empty for the asm-generic header.
*/
#endif /* __ASM_GENERIC_MODULE_LDS_H */
+396
View File
@@ -0,0 +1,396 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Linux-specific definitions for managing interactions with Microsoft's
* Hyper-V hypervisor. The definitions in this file are architecture
* independent. See arch/<arch>/include/asm/mshyperv.h for definitions
* that are specific to architecture <arch>.
*
* Definitions that are derived from Hyper-V code or headers should not go in
* this file, but should instead go in the relevant files in include/hyperv.
*
* Copyright (C) 2019, Microsoft, Inc.
*
* Author : Michael Kelley <mikelley@microsoft.com>
*/
#ifndef _ASM_GENERIC_MSHYPERV_H
#define _ASM_GENERIC_MSHYPERV_H
#include <linux/types.h>
#include <linux/atomic.h>
#include <linux/bitops.h>
#include <acpi/acpi_numa.h>
#include <linux/cpumask.h>
#include <linux/nmi.h>
#include <asm/ptrace.h>
#include <hyperv/hvhdk.h>
#define VTPM_BASE_ADDRESS 0xfed40000
enum hv_partition_type {
HV_PARTITION_TYPE_GUEST,
HV_PARTITION_TYPE_ROOT,
HV_PARTITION_TYPE_L1VH,
};
struct ms_hyperv_info {
u32 features;
u32 priv_high;
u32 ext_features;
u32 misc_features;
u32 hints;
u32 nested_features;
u32 max_vp_index;
u32 max_lp_index;
u8 vtl;
union {
u32 isolation_config_a;
struct {
u32 paravisor_present : 1;
u32 reserved_a1 : 31;
};
};
union {
u32 isolation_config_b;
struct {
u32 cvm_type : 4;
u32 reserved_b1 : 1;
u32 shared_gpa_boundary_active : 1;
u32 shared_gpa_boundary_bits : 6;
u32 reserved_b2 : 20;
};
};
u64 shared_gpa_boundary;
bool msi_ext_dest_id;
bool confidential_vmbus_available;
};
extern struct ms_hyperv_info ms_hyperv;
extern bool hv_nested;
extern u64 hv_current_partition_id;
extern enum hv_partition_type hv_curr_partition_type;
extern void * __percpu *hyperv_pcpu_input_arg;
extern void * __percpu *hyperv_pcpu_output_arg;
u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr);
u64 hv_do_fast_hypercall8(u16 control, u64 input8);
u64 hv_do_fast_hypercall16(u16 control, u64 input1, u64 input2);
bool hv_isolation_type_snp(void);
bool hv_isolation_type_tdx(void);
/*
* On architectures where Hyper-V doesn't support AEOI (e.g., ARM64),
* it doesn't provide a recommendation flag and AEOI must be disabled.
*/
static inline bool hv_recommend_using_aeoi(void)
{
#ifdef HV_DEPRECATING_AEOI_RECOMMENDED
return !(ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED);
#else
return false;
#endif
}
static inline struct hv_proximity_domain_info hv_numa_node_to_pxm_info(int node)
{
struct hv_proximity_domain_info pxm_info = {};
if (node != NUMA_NO_NODE) {
pxm_info.domain_id = node_to_pxm(node);
pxm_info.flags.proximity_info_valid = 1;
pxm_info.flags.proximity_preferred = 1;
}
return pxm_info;
}
/* Helper functions that provide a consistent pattern for checking Hyper-V hypercall status. */
static inline int hv_result(u64 status)
{
return status & HV_HYPERCALL_RESULT_MASK;
}
static inline bool hv_result_success(u64 status)
{
return hv_result(status) == HV_STATUS_SUCCESS;
}
static inline unsigned int hv_repcomp(u64 status)
{
/* Bits [43:32] of status have 'Reps completed' data. */
return (status & HV_HYPERCALL_REP_COMP_MASK) >>
HV_HYPERCALL_REP_COMP_OFFSET;
}
/*
* Rep hypercalls. Callers of this functions are supposed to ensure that
* rep_count, varhead_size, and rep_start comply with Hyper-V hypercall
* definition.
*/
static inline u64 hv_do_rep_hypercall_ex(u16 code, u16 rep_count,
u16 varhead_size, u16 rep_start,
void *input, void *output)
{
u64 control = code;
u64 status;
u16 rep_comp;
control |= (u64)varhead_size << HV_HYPERCALL_VARHEAD_OFFSET;
control |= (u64)rep_count << HV_HYPERCALL_REP_COMP_OFFSET;
control |= (u64)rep_start << HV_HYPERCALL_REP_START_OFFSET;
do {
status = hv_do_hypercall(control, input, output);
if (!hv_result_success(status))
return status;
rep_comp = hv_repcomp(status);
control &= ~HV_HYPERCALL_REP_START_MASK;
control |= (u64)rep_comp << HV_HYPERCALL_REP_START_OFFSET;
touch_nmi_watchdog();
} while (rep_comp < rep_count);
return status;
}
/* For the typical case where rep_start is 0 */
static inline u64 hv_do_rep_hypercall(u16 code, u16 rep_count, u16 varhead_size,
void *input, void *output)
{
return hv_do_rep_hypercall_ex(code, rep_count, varhead_size, 0,
input, output);
}
/* Generate the guest OS identifier as described in the Hyper-V TLFS */
static inline u64 hv_generate_guest_id(u64 kernel_version)
{
u64 guest_id;
guest_id = (((u64)HV_LINUX_VENDOR_ID) << 48);
guest_id |= (kernel_version << 16);
return guest_id;
}
int hv_get_hypervisor_version(union hv_hypervisor_version_info *info);
void hv_setup_vmbus_handler(void (*handler)(void));
void hv_remove_vmbus_handler(void);
void hv_setup_stimer0_handler(void (*handler)(void));
void hv_remove_stimer0_handler(void);
void hv_setup_kexec_handler(void (*handler)(void));
void hv_remove_kexec_handler(void);
void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
void hv_remove_crash_handler(void);
void hv_setup_mshv_handler(void (*handler)(void));
#if IS_ENABLED(CONFIG_HYPERV)
/*
* Hypervisor's notion of virtual processor ID is different from
* Linux' notion of CPU ID. This information can only be retrieved
* in the context of the calling CPU. Setup a map for easy access
* to this information.
*/
extern u32 *hv_vp_index;
extern u32 hv_max_vp_index;
extern u64 (*hv_read_reference_counter)(void);
/* Sentinel value for an uninitialized entry in hv_vp_index array */
#define VP_INVAL U32_MAX
int __init hv_common_init(void);
void __init hv_get_partition_id(void);
void __init hv_common_free(void);
void __init ms_hyperv_late_init(void);
int hv_common_cpu_init(unsigned int cpu);
int hv_common_cpu_die(unsigned int cpu);
void hv_identify_partition_type(void);
/**
* hv_cpu_number_to_vp_number() - Map CPU to VP.
* @cpu_number: CPU number in Linux terms
*
* This function returns the mapping between the Linux processor
* number and the hypervisor's virtual processor number, useful
* in making hypercalls and such that talk about specific
* processors.
*
* Return: Virtual processor number in Hyper-V terms
*/
static inline int hv_cpu_number_to_vp_number(int cpu_number)
{
return hv_vp_index[cpu_number];
}
static inline int __cpumask_to_vpset(struct hv_vpset *vpset,
const struct cpumask *cpus,
bool (*func)(int cpu))
{
int cpu, vcpu, vcpu_bank, vcpu_offset, nr_bank = 1;
int max_vcpu_bank = hv_max_vp_index / HV_VCPUS_PER_SPARSE_BANK;
/* vpset.valid_bank_mask can represent up to HV_MAX_SPARSE_VCPU_BANKS banks */
if (max_vcpu_bank >= HV_MAX_SPARSE_VCPU_BANKS)
return 0;
/*
* Clear all banks up to the maximum possible bank as hv_tlb_flush_ex
* structs are not cleared between calls, we risk flushing unneeded
* vCPUs otherwise.
*/
for (vcpu_bank = 0; vcpu_bank <= max_vcpu_bank; vcpu_bank++)
vpset->bank_contents[vcpu_bank] = 0;
/*
* Some banks may end up being empty but this is acceptable.
*/
for_each_cpu(cpu, cpus) {
if (func && func(cpu))
continue;
vcpu = hv_cpu_number_to_vp_number(cpu);
if (vcpu == VP_INVAL)
return -1;
vcpu_bank = vcpu / HV_VCPUS_PER_SPARSE_BANK;
vcpu_offset = vcpu % HV_VCPUS_PER_SPARSE_BANK;
__set_bit(vcpu_offset, (unsigned long *)
&vpset->bank_contents[vcpu_bank]);
if (vcpu_bank >= nr_bank)
nr_bank = vcpu_bank + 1;
}
vpset->valid_bank_mask = GENMASK_ULL(nr_bank - 1, 0);
return nr_bank;
}
/*
* Convert a Linux cpumask into a Hyper-V VPset. In the _skip variant,
* 'func' is called for each CPU present in cpumask. If 'func' returns
* true, that CPU is skipped -- i.e., that CPU from cpumask is *not*
* added to the Hyper-V VPset. If 'func' is NULL, no CPUs are
* skipped.
*/
static inline int cpumask_to_vpset(struct hv_vpset *vpset,
const struct cpumask *cpus)
{
return __cpumask_to_vpset(vpset, cpus, NULL);
}
static inline int cpumask_to_vpset_skip(struct hv_vpset *vpset,
const struct cpumask *cpus,
bool (*func)(int cpu))
{
return __cpumask_to_vpset(vpset, cpus, func);
}
#define _hv_status_fmt(fmt) "%s: Hyper-V status: %#x = %s: " fmt
#define hv_status_printk(level, status, fmt, ...) \
do { \
u64 __status = (status); \
pr_##level(_hv_status_fmt(fmt), __func__, hv_result(__status), \
hv_result_to_string(__status), ##__VA_ARGS__); \
} while (0)
#define hv_status_err(status, fmt, ...) \
hv_status_printk(err, status, fmt, ##__VA_ARGS__)
#define hv_status_debug(status, fmt, ...) \
hv_status_printk(debug, status, fmt, ##__VA_ARGS__)
const char *hv_result_to_string(u64 hv_status);
int hv_result_to_errno(u64 status);
void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die);
bool hv_is_hyperv_initialized(void);
bool hv_is_hibernation_supported(void);
enum hv_isolation_type hv_get_isolation_type(void);
bool hv_is_isolation_supported(void);
bool hv_isolation_type_snp(void);
u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size);
u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2);
void hv_enable_coco_interrupt(unsigned int cpu, unsigned int vector, bool set);
void hv_para_set_sint_proxy(bool enable);
u64 hv_para_get_synic_register(unsigned int reg);
void hv_para_set_synic_register(unsigned int reg, u64 val);
void hyperv_cleanup(void);
bool hv_query_ext_cap(u64 cap_query);
void hv_setup_dma_ops(struct device *dev, bool coherent);
#else /* CONFIG_HYPERV */
static inline void hv_identify_partition_type(void) {}
static inline bool hv_is_hyperv_initialized(void) { return false; }
static inline bool hv_is_hibernation_supported(void) { return false; }
static inline void hyperv_cleanup(void) {}
static inline void ms_hyperv_late_init(void) {}
static inline bool hv_is_isolation_supported(void) { return false; }
static inline enum hv_isolation_type hv_get_isolation_type(void)
{
return HV_ISOLATION_TYPE_NONE;
}
#endif /* CONFIG_HYPERV */
#if IS_ENABLED(CONFIG_MSHV_ROOT)
static inline bool hv_root_partition(void)
{
return hv_curr_partition_type == HV_PARTITION_TYPE_ROOT;
}
static inline bool hv_l1vh_partition(void)
{
return hv_curr_partition_type == HV_PARTITION_TYPE_L1VH;
}
static inline bool hv_parent_partition(void)
{
return hv_root_partition() || hv_l1vh_partition();
}
bool hv_result_needs_memory(u64 status);
int hv_deposit_memory_node(int node, u64 partition_id, u64 status);
int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages);
int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id);
int hv_call_notify_all_processors_started(void);
bool hv_lp_exists(u32 lp_index);
int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags);
#else /* CONFIG_MSHV_ROOT */
static inline bool hv_root_partition(void) { return false; }
static inline bool hv_l1vh_partition(void) { return false; }
static inline bool hv_parent_partition(void) { return false; }
static inline bool hv_result_needs_memory(u64 status) { return false; }
static inline int hv_deposit_memory_node(int node, u64 partition_id, u64 status)
{
return -EOPNOTSUPP;
}
static inline int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
{
return -EOPNOTSUPP;
}
static inline int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id)
{
return -EOPNOTSUPP;
}
static inline int hv_call_notify_all_processors_started(void)
{
return -EOPNOTSUPP;
}
static inline bool hv_lp_exists(u32 lp_index)
{
return false;
}
static inline int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
{
return -EOPNOTSUPP;
}
#endif /* CONFIG_MSHV_ROOT */
static inline int hv_deposit_memory(u64 partition_id, u64 status)
{
return hv_deposit_memory_node(NUMA_NO_NODE, partition_id, status);
}
#if IS_ENABLED(CONFIG_HYPERV_VTL_MODE)
u8 __init get_vtl(void);
#else
static inline u8 get_vtl(void) { return 0; }
#endif
#endif
+42
View File
@@ -0,0 +1,42 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_GENERIC_MSI_H
#define __ASM_GENERIC_MSI_H
#include <linux/types.h>
#ifdef CONFIG_GENERIC_MSI_IRQ
#ifndef NUM_MSI_ALLOC_SCRATCHPAD_REGS
# define NUM_MSI_ALLOC_SCRATCHPAD_REGS 2
#endif
struct msi_desc;
/**
* struct msi_alloc_info - Default structure for MSI interrupt allocation.
* @desc: Pointer to msi descriptor
* @hwirq: Associated hw interrupt number in the domain
* @scratchpad: Storage for implementation specific scratch data
*
* Architectures can provide their own implementation by not including
* asm-generic/msi.h into their arch specific header file.
*/
typedef struct msi_alloc_info {
struct msi_desc *desc;
irq_hw_number_t hwirq;
unsigned long flags;
union {
unsigned long ul;
void *ptr;
} scratchpad[NUM_MSI_ALLOC_SCRATCHPAD_REGS];
} msi_alloc_info_t;
/* Device generating MSIs is proxying for another device */
#define MSI_ALLOC_FLAGS_PROXY_DEVICE (1UL << 0)
#define MSI_ALLOC_FLAGS_FIXED_MSG_DATA (1UL << 1)
#define GENERIC_MSI_DOMAIN_OPS 1
#endif /* CONFIG_GENERIC_MSI_IRQ */
#endif

Some files were not shown because too many files have changed in this diff Show More