code:
/* SPDX-License-Identifier: GPL-2.0-only */

/*
 * ARCv2 supports 64-bit exclusive load (LLOCKD) / store (SCONDD)
 *  - The address HAS to be 64-bit aligned
 */

#ifndef _ASM_ARC_ATOMIC64_ARCV2_H
#define _ASM_ARC_ATOMIC64_ARCV2_H

typedef struct {
	s64 __aligned(8) counter;
} atomic64_t;

#define ATOMIC64_INIT(a) { (a) }

static inline s64 arch_atomic64_read(const atomic64_t *v)
{
	s64 val;

	__asm__ __volatile__(
	"	ldd   %0, [%1]	\n"
	: "=r"(val)
	: "r"(&v->counter));

	return val;
}

static inline void arch_atomic64_set(atomic64_t *v, s64 a)
{
	/*
	 * This could have been a simple assignment in "C" but would need
	 * explicit volatile. Otherwise gcc optimizers could elide the store
	 * which borked atomic64 self-test
	 * In the inline asm version, memory clobber needed for exact same
	 * reason, to tell gcc about the store.
	 *
	 * This however is not needed for sibling atomic64_add() etc since both
	 * load/store are explicitly done in inline asm. As long as API is used
	 * for each access, gcc has no way to optimize away any load/store
	 */
	__asm__ __volatile__(
	"	std   %0, [%1]	\n"
	:
	: "r"(a), "r"(&v->counter)
	: "memory");
}

#define ATOMIC64_OP(op, op1, op2)					\
static inline void arch_atomic64_##op(s64 a, atomic64_t *v)		\
{									\
	s64 val;							\
									\
	__asm__ __volatile__(						\
	"1:				\n"				\
	"	llockd  %0, [%1]	\n"				\
	"	" #op1 " %L0, %L0, %L2	\n"				\
	"	" #op2 " %H0, %H0, %H2	\n"				\
	"	scondd   %0, [%1]	\n"				\
	"	bnz     1b		\n"				\
	: "=&r"(val)							\
	: "r"(&v->counter), "ir"(a)					\
	: "cc");							\
}									\

#define ATOMIC64_OP_RETURN(op, op1, op2)		        	\
static inline s64 arch_atomic64_##op##_return_relaxed(s64 a, atomic64_t *v)	\
{									\
	s64 val;							\
									\
	__asm__ __volatile__(						\
	"1:				\n"				\
	"	llockd   %0, [%1]	\n"				\
	"	" #op1 " %L0, %L0, %L2	\n"				\
	"	" #op2 " %H0, %H0, %H2	\n"				\
	"	scondd   %0, [%1]	\n"				\
	"	bnz     1b		\n"				\
	: [val] "=&r"(val)						\
	: "r"(&v->counter), "ir"(a)					\
	: "cc");	/* memory clobber comes from smp_mb() */	\
									\
	return val;							\
}

#define arch_atomic64_add_return_relaxed	arch_atomic64_add_return_relaxed
#define arch_atomic64_sub_return_relaxed	arch_atomic64_sub_return_relaxed

#define ATOMIC64_FETCH_OP(op, op1, op2)		        		\
static inline s64 arch_atomic64_fetch_##op##_relaxed(s64 a, atomic64_t *v)	\
{									\
	s64 val, orig;							\
									\
	__asm__ __volatile__(						\
	"1:				\n"				\
	"	llockd   %0, [%2]	\n"				\
	"	" #op1 " %L1, %L0, %L3	\n"				\
	"	" #op2 " %H1, %H0, %H3	\n"				\
	"	scondd   %1, [%2]	\n"				\
	"	bnz     1b		\n"				\
	: "=&r"(orig), "=&r"(val)					\
	: "r"(&v->counter), "ir"(a)					\
	: "cc");	/* memory clobber comes from smp_mb() */	\
									\
	return orig;							\
}

#define arch_atomic64_fetch_add_relaxed		arch_atomic64_fetch_add_relaxed
#define arch_atomic64_fetch_sub_relaxed		arch_atomic64_fetch_sub_relaxed

#define arch_atomic64_fetch_and_relaxed		arch_atomic64_fetch_and_relaxed
#define arch_atomic64_fetch_andnot_relaxed	arch_atomic64_fetch_andnot_relaxed
#define arch_atomic64_fetch_or_relaxed		arch_atomic64_fetch_or_relaxed
#define arch_atomic64_fetch_xor_relaxed		arch_atomic64_fetch_xor_relaxed

#define ATOMIC64_OPS(op, op1, op2)					\
	ATOMIC64_OP(op, op1, op2)					\
	ATOMIC64_OP_RETURN(op, op1, op2)				\
	ATOMIC64_FETCH_OP(op, op1, op2)

ATOMIC64_OPS(add, add.f, adc)
ATOMIC64_OPS(sub, sub.f, sbc)

#undef ATOMIC64_OPS
#define ATOMIC64_OPS(op, op1, op2)					\
	ATOMIC64_OP(op, op1, op2)					\
	ATOMIC64_FETCH_OP(op, op1, op2)

ATOMIC64_OPS(and, and, and)
ATOMIC64_OPS(andnot, bic, bic)
ATOMIC64_OPS(or, or, or)
ATOMIC64_OPS(xor, xor, xor)

#define arch_atomic64_andnot		arch_atomic64_andnot

#undef ATOMIC64_OPS
#undef ATOMIC64_FETCH_OP
#undef ATOMIC64_OP_RETURN
#undef ATOMIC64_OP

static inline s64
arch_atomic64_cmpxchg(atomic64_t *ptr, s64 expected, s64 new)
{
	s64 prev;

	smp_mb();

	__asm__ __volatile__(
	"1:	llockd  %0, [%1]	\n"
	"	brne    %L0, %L2, 2f	\n"
	"	brne    %H0, %H2, 2f	\n"
	"	scondd  %3, [%1]	\n"
	"	bnz     1b		\n"
	"2:				\n"
	: "=&r"(prev)
	: "r"(ptr), "ir"(expected), "r"(new)
	: "cc");	/* memory clobber comes from smp_mb() */

	smp_mb();

	return prev;
}

static inline s64 arch_atomic64_xchg(atomic64_t *ptr, s64 new)
{
	s64 prev;

	smp_mb();

	__asm__ __volatile__(
	"1:	llockd  %0, [%1]	\n"
	"	scondd  %2, [%1]	\n"
	"	bnz     1b		\n"
	"2:				\n"
	: "=&r"(prev)
	: "r"(ptr), "r"(new)
	: "cc");	/* memory clobber comes from smp_mb() */

	smp_mb();

	return prev;
}

/**
 * arch_atomic64_dec_if_positive - decrement by 1 if old value positive
 * @v: pointer of type atomic64_t
 *
 * The function returns the old value of *v minus 1, even if
 * the atomic variable, v, was not decremented.
 */

static inline s64 arch_atomic64_dec_if_positive(atomic64_t *v)
{
	s64 val;

	smp_mb();

	__asm__ __volatile__(
	"1:	llockd  %0, [%1]	\n"
	"	sub.f   %L0, %L0, 1	# w0 - 1, set C on borrow\n"
	"	sub.c   %H0, %H0, 1	# if C set, w1 - 1\n"
	"	brlt    %H0, 0, 2f	\n"
	"	scondd  %0, [%1]	\n"
	"	bnz     1b		\n"
	"2:				\n"
	: "=&r"(val)
	: "r"(&v->counter)
	: "cc");	/* memory clobber comes from smp_mb() */

	smp_mb();

	return val;
}
#define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive

/**
 * arch_atomic64_fetch_add_unless - add unless the number is a given value
 * @v: pointer of type atomic64_t
 * @a: the amount to add to v...
 * @u: ...unless v is equal to u.
 *
 * Atomically adds @a to @v, if it was not @u.
 * Returns the old value of @v
 */
static inline s64 arch_atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u)
{
	s64 old, temp;

	smp_mb();

	__asm__ __volatile__(
	"1:	llockd  %0, [%2]	\n"
	"	brne	%L0, %L4, 2f	# continue to add since v != u \n"
	"	breq.d	%H0, %H4, 3f	# return since v == u \n"
	"2:				\n"
	"	add.f   %L1, %L0, %L3	\n"
	"	adc     %H1, %H0, %H3	\n"
	"	scondd  %1, [%2]	\n"
	"	bnz     1b		\n"
	"3:				\n"
	: "=&r"(old), "=&r" (temp)
	: "r"(&v->counter), "r"(a), "r"(u)
	: "cc");	/* memory clobber comes from smp_mb() */

	smp_mb();

	return old;
}
#define arch_atomic64_fetch_add_unless arch_atomic64_fetch_add_unless

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ASM_BARRIER_H
#define __ASM_BARRIER_H

#ifdef CONFIG_ISA_ARCV2

/*
 * ARCv2 based HS38 cores are in-order issue, but still weakly ordered
 * due to micro-arch buffering/queuing of load/store, cache hit vs. miss ...
 *
 * Explicit barrier provided by DMB instruction
 *  - Operand supports fine grained load/store/load+store semantics
 *  - Ensures that selected memory operation issued before it will complete
 *    before any subsequent memory operation of same type
 *  - DMB guarantees SMP as well as local barrier semantics
 *    (asm-generic/barrier.h ensures sane smp_*mb if not defined here, i.e.
 *    UP: barrier(), SMP: smp_*mb == *mb)
 *  - DSYNC provides DMB+completion_of_cache_bpu_maintenance_ops hence not needed
 *    in the general case. Plus it only provides full barrier.
 */

#define mb()	asm volatile("dmb 3\n" : : : "memory")
#define rmb()	asm volatile("dmb 1\n" : : : "memory")
#define wmb()	asm volatile("dmb 2\n" : : : "memory")

#else

/*
 * ARCompact based cores (ARC700) only have SYNC instruction which is super
 * heavy weight as it flushes the pipeline as well.
 * There are no real SMP implementations of such cores.
 */

#define mb()	asm volatile("sync\n" : : : "memory")

#endif

#include <asm-generic/barrier.h>

#endif

repo_name: angery/linux


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef _ASM_BITOPS_H
#define _ASM_BITOPS_H

#ifndef _LINUX_BITOPS_H
#error only <linux/bitops.h> can be included directly
#endif

#ifndef __ASSEMBLY__

#include <linux/types.h>
#include <linux/compiler.h>

#ifdef CONFIG_ISA_ARCOMPACT

/*
 * Count the number of zeros, starting from MSB
 * Helper for fls( ) friends
 * This is a pure count, so (1-32) or (0-31) doesn't apply
 * It could be 0 to 32, based on num of 0's in there
 * clz(0x8000_0000) = 0, clz(0xFFFF_FFFF)=0, clz(0) = 32, clz(1) = 31
 */
static inline __attribute__ ((const)) int clz(unsigned int x)
{
	unsigned int res;

	__asm__ __volatile__(
	"	norm.f  %0, %1		\n"
	"	mov.n   %0, 0		\n"
	"	add.p   %0, %0, 1	\n"
	: "=r"(res)
	: "r"(x)
	: "cc");

	return res;
}

static inline int constant_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))
		r -= 1;
	return r;
}

/*
 * fls = Find Last Set in word
 * @result: [1-32]
 * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
 */
static inline __attribute__ ((const)) int fls(unsigned int x)
{
	if (__builtin_constant_p(x))
	       return constant_fls(x);

	return 32 - clz(x);
}

/*
 * __fls: Similar to fls, but zero based (0-31)
 */
static inline __attribute__ ((const)) unsigned long __fls(unsigned long x)
{
	if (!x)
		return 0;
	else
		return fls(x) - 1;
}

/*
 * ffs = Find First Set in word (LSB to MSB)
 * @result: [1-32], 0 if all 0's
 */
#define ffs(x)	({ unsigned long __t = (x); fls(__t & -__t); })

/*
 * __ffs: Similar to ffs, but zero based (0-31)
 */
static inline __attribute__ ((const)) unsigned long __ffs(unsigned long word)
{
	if (!word)
		return word;

	return ffs(word) - 1;
}

#else	/* CONFIG_ISA_ARCV2 */

/*
 * fls = Find Last Set in word
 * @result: [1-32]
 * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
 */
static inline __attribute__ ((const)) int fls(unsigned int x)
{
	int n;

	asm volatile(
	"	fls.f	%0, %1		\n"  /* 0:31; 0(Z) if src 0 */
	"	add.nz	%0, %0, 1	\n"  /* 0:31 -> 1:32 */
	: "=r"(n)	/* Early clobber not needed */
	: "r"(x)
	: "cc");

	return n;
}

/*
 * __fls: Similar to fls, but zero based (0-31). Also 0 if no bit set
 */
static inline __attribute__ ((const)) unsigned long __fls(unsigned long x)
{
	/* FLS insn has exactly same semantics as the API */
	return	__builtin_arc_fls(x);
}

/*
 * ffs = Find First Set in word (LSB to MSB)
 * @result: [1-32], 0 if all 0's
 */
static inline __attribute__ ((const)) int ffs(unsigned int x)
{
	int n;

	asm volatile(
	"	ffs.f	%0, %1		\n"  /* 0:31; 31(Z) if src 0 */
	"	add.nz	%0, %0, 1	\n"  /* 0:31 -> 1:32 */
	"	mov.z	%0, 0		\n"  /* 31(Z)-> 0 */
	: "=r"(n)	/* Early clobber not needed */
	: "r"(x)
	: "cc");

	return n;
}

/*
 * __ffs: Similar to ffs, but zero based (0-31)
 */
static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x)
{
	unsigned long n;

	asm volatile(
	"	ffs.f	%0, %1		\n"  /* 0:31; 31(Z) if src 0 */
	"	mov.z	%0, 0		\n"  /* 31(Z)-> 0 */
	: "=r"(n)
	: "r"(x)
	: "cc");

	return n;

}

#endif	/* CONFIG_ISA_ARCOMPACT */

/*
 * ffz = Find First Zero in word.
 * @return:[0-31], 32 if all 1's
 */
#define ffz(x)	__ffs(~(x))

#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.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-setbit.h>

#endif /* !__ASSEMBLY__ */

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef _ASM_ARC_BUG_H
#define _ASM_ARC_BUG_H

#ifndef __ASSEMBLY__

#include <asm/ptrace.h>

struct task_struct;

void show_regs(struct pt_regs *regs);
void show_stacktrace(struct task_struct *tsk, struct pt_regs *regs,
		     const char *loglvl);
void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
			    unsigned long address);
void die(const char *str, struct pt_regs *regs, unsigned long address);

#define BUG()	do {								\
	pr_warn("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
	barrier_before_unreachable();						\
	__builtin_trap();							\
} while (0)

#define HAVE_ARCH_BUG

#include <asm-generic/bug.h>

#endif	/* !__ASSEMBLY__ */

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ARC_ASM_CACHE_H
#define __ARC_ASM_CACHE_H

/* In case $$ not config, setup a dummy number for rest of kernel */
#ifndef CONFIG_ARC_CACHE_LINE_SHIFT
#define L1_CACHE_SHIFT		6
#else
#define L1_CACHE_SHIFT		CONFIG_ARC_CACHE_LINE_SHIFT
#endif

#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
#define CACHE_LINE_MASK		(~(L1_CACHE_BYTES - 1))

/*
 * ARC700 doesn't cache any access in top 1G (0xc000_0000 to 0xFFFF_FFFF)
 * Ideal for wiring memory mapped peripherals as we don't need to do
 * explicit uncached accesses (LD.di/ST.di) hence more portable drivers
 */
#define ARC_UNCACHED_ADDR_SPACE	0xc0000000

#ifndef __ASSEMBLY__

#include <linux/build_bug.h>

/* Uncached access macros */
#define arc_read_uncached_32(ptr)	\
({					\
	unsigned int __ret;		\
	__asm__ __volatile__(		\
	"	ld.di %0, [%1]	\n"	\
	: "=r"(__ret)			\
	: "r"(ptr));			\
	__ret;				\
})

#define arc_write_uncached_32(ptr, data)\
({					\
	__asm__ __volatile__(		\
	"	st.di %0, [%1]	\n"	\
	:				\
	: "r"(data), "r"(ptr));		\
})

/* Largest line length for either L1 or L2 is 128 bytes */
#define SMP_CACHE_BYTES		128
#define cache_line_size()	SMP_CACHE_BYTES
#define ARCH_DMA_MINALIGN	SMP_CACHE_BYTES

/*
 * Make sure slab-allocated buffers are 64-bit aligned when atomic64_t uses
 * ARCv2 64-bit atomics (LLOCKD/SCONDD). This guarantess runtime 64-bit
 * alignment for any atomic64_t embedded in buffer.
 * Default ARCH_SLAB_MINALIGN is __alignof__(long long) which has a relaxed
 * value of 4 (and not 8) in ARC ABI.
 */
#if defined(CONFIG_ARC_HAS_LL64) && defined(CONFIG_ARC_HAS_LLSC)
#define ARCH_SLAB_MINALIGN	8
#endif

extern int ioc_enable;
extern unsigned long perip_base, perip_end;

#endif	/* !__ASSEMBLY__ */

/* Instruction cache related Auxiliary registers */
#define ARC_REG_IC_BCR		0x77	/* Build Config reg */
#define ARC_REG_IC_IVIC		0x10
#define ARC_REG_IC_CTRL		0x11
#define ARC_REG_IC_IVIR		0x16
#define ARC_REG_IC_ENDR		0x17
#define ARC_REG_IC_IVIL		0x19
#define ARC_REG_IC_PTAG		0x1E
#define ARC_REG_IC_PTAG_HI	0x1F

/* Bit val in IC_CTRL */
#define IC_CTRL_DIS		0x1

/* Data cache related Auxiliary registers */
#define ARC_REG_DC_BCR		0x72	/* Build Config reg */
#define ARC_REG_DC_IVDC		0x47
#define ARC_REG_DC_CTRL		0x48
#define ARC_REG_DC_IVDL		0x4A
#define ARC_REG_DC_FLSH		0x4B
#define ARC_REG_DC_FLDL		0x4C
#define ARC_REG_DC_STARTR	0x4D
#define ARC_REG_DC_ENDR		0x4E
#define ARC_REG_DC_PTAG		0x5C
#define ARC_REG_DC_PTAG_HI	0x5F

/* Bit val in DC_CTRL */
#define DC_CTRL_DIS		0x001
#define DC_CTRL_INV_MODE_FLUSH	0x040
#define DC_CTRL_FLUSH_STATUS	0x100
#define DC_CTRL_RGN_OP_INV	0x200
#define DC_CTRL_RGN_OP_MSK	0x200

/*System-level cache (L2 cache) related Auxiliary registers */
#define ARC_REG_SLC_CFG		0x901
#define ARC_REG_SLC_CTRL	0x903
#define ARC_REG_SLC_FLUSH	0x904
#define ARC_REG_SLC_INVALIDATE	0x905
#define ARC_AUX_SLC_IVDL	0x910
#define ARC_AUX_SLC_FLDL	0x912
#define ARC_REG_SLC_RGN_START	0x914
#define ARC_REG_SLC_RGN_START1	0x915
#define ARC_REG_SLC_RGN_END	0x916
#define ARC_REG_SLC_RGN_END1	0x917

/* Bit val in SLC_CONTROL */
#define SLC_CTRL_DIS		0x001
#define SLC_CTRL_IM		0x040
#define SLC_CTRL_BUSY		0x100
#define SLC_CTRL_RGN_OP_INV	0x200

/* IO coherency related Auxiliary registers */
#define ARC_REG_IO_COH_ENABLE	0x500
#define ARC_IO_COH_ENABLE_BIT	BIT(0)
#define ARC_REG_IO_COH_PARTIAL	0x501
#define ARC_IO_COH_PARTIAL_BIT	BIT(0)
#define ARC_REG_IO_COH_AP0_BASE	0x508
#define ARC_REG_IO_COH_AP0_SIZE	0x509

#endif /* _ASM_CACHE_H */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 *
 *  vineetg: May 2011: for Non-aliasing VIPT D-cache following can be NOPs
 *   -flush_cache_dup_mm (fork)
 *   -likewise for flush_cache_mm (exit/execve)
 *   -likewise for flush_cache_{range,page} (munmap, exit, COW-break)
 *
 *  vineetg: April 2008
 *   -Added a critical CacheLine flush to copy_to_user_page( ) which
 *     was causing gdbserver to not setup breakpoints consistently
 */

#ifndef _ASM_CACHEFLUSH_H
#define _ASM_CACHEFLUSH_H

#include <linux/mm.h>
#include <asm/shmparam.h>

/*
 * Semantically we need this because icache doesn't snoop dcache/dma.
 * However ARC Cache flush requires paddr as well as vaddr, latter not available
 * in the flush_icache_page() API. So we no-op it but do the equivalent work
 * in update_mmu_cache()
 */
#define flush_icache_page(vma, page)

void flush_cache_all(void);

void flush_icache_range(unsigned long kstart, unsigned long kend);
void __sync_icache_dcache(phys_addr_t paddr, unsigned long vaddr, int len);
void __inv_icache_page(phys_addr_t paddr, unsigned long vaddr);
void __flush_dcache_page(phys_addr_t paddr, unsigned long vaddr);

#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1

void flush_dcache_page(struct page *page);

void dma_cache_wback_inv(phys_addr_t start, unsigned long sz);
void dma_cache_inv(phys_addr_t start, unsigned long sz);
void dma_cache_wback(phys_addr_t start, unsigned long sz);

#define flush_dcache_mmap_lock(mapping)		do { } while (0)
#define flush_dcache_mmap_unlock(mapping)	do { } while (0)

/* TBD: optimize this */
#define flush_cache_vmap(start, end)		flush_cache_all()
#define flush_cache_vunmap(start, end)		flush_cache_all()

#define flush_cache_dup_mm(mm)			/* called on fork (VIVT only) */

#ifndef CONFIG_ARC_CACHE_VIPT_ALIASING

#define flush_cache_mm(mm)			/* called on munmap/exit */
#define flush_cache_range(mm, u_vstart, u_vend)
#define flush_cache_page(vma, u_vaddr, pfn)	/* PF handling/COW-break */

#else	/* VIPT aliasing dcache */

/* To clear out stale userspace mappings */
void flush_cache_mm(struct mm_struct *mm);
void flush_cache_range(struct vm_area_struct *vma,
	unsigned long start,unsigned long end);
void flush_cache_page(struct vm_area_struct *vma,
	unsigned long user_addr, unsigned long page);

/*
 * To make sure that userspace mapping is flushed to memory before
 * get_user_pages() uses a kernel mapping to access the page
 */
#define ARCH_HAS_FLUSH_ANON_PAGE
void flush_anon_page(struct vm_area_struct *vma,
	struct page *page, unsigned long u_vaddr);

#endif	/* CONFIG_ARC_CACHE_VIPT_ALIASING */

/*
 * A new pagecache page has PG_arch_1 clear - thus dcache dirty by default
 * This works around some PIO based drivers which don't call flush_dcache_page
 * to record that they dirtied the dcache
 */
#define PG_dc_clean	PG_arch_1

#define CACHE_COLORS_NUM	4
#define CACHE_COLORS_MSK	(CACHE_COLORS_NUM - 1)
#define CACHE_COLOR(addr)	(((unsigned long)(addr) >> (PAGE_SHIFT)) & CACHE_COLORS_MSK)

/*
 * Simple wrapper over config option
 * Bootup code ensures that hardware matches kernel configuration
 */
static inline int cache_is_vipt_aliasing(void)
{
	return IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
}

/*
 * checks if two addresses (after page aligning) index into same cache set
 */
#define addr_not_cache_congruent(addr1, addr2)				\
({									\
	cache_is_vipt_aliasing() ? 					\
		(CACHE_COLOR(addr1) != CACHE_COLOR(addr2)) : 0;		\
})

#define copy_to_user_page(vma, page, vaddr, dst, src, len)		\
do {									\
	memcpy(dst, src, len);						\
	if (vma->vm_flags & VM_EXEC)					\
		__sync_icache_dcache((unsigned long)(dst), vaddr, len);	\
} while (0)

#define copy_from_user_page(vma, page, vaddr, dst, src, len)		\
	memcpy(dst, src, len);						\

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 *
 * Joern Rennecke  <joern.rennecke@embecosm.com>: Jan 2012
 *  -Insn Scheduling improvements to csum core routines.
 *      = csum_fold( ) largely derived from ARM version.
 *      = ip_fast_cum( ) to have module scheduling
 *  -gcc 4.4.x broke networking. Alias analysis needed to be primed.
 *   worked around by adding memory clobber to ip_fast_csum( )
 *
 * vineetg: May 2010
 *  -Rewrote ip_fast_cscum( ) and csum_fold( ) with fast inline asm
 */

#ifndef _ASM_ARC_CHECKSUM_H
#define _ASM_ARC_CHECKSUM_H

/*
 *	Fold a partial checksum
 *
 *  The 2 swords comprising the 32bit sum are added, any carry to 16th bit
 *  added back and final sword result inverted.
 */
static inline __sum16 csum_fold(__wsum s)
{
	unsigned int r = s << 16 | s >> 16;	/* ror */
	s = ~s;
	s -= r;
	return s >> 16;
}

/*
 *	This is a version of ip_compute_csum() optimized for IP headers,
 *	which always checksum on 4 octet boundaries.
 */
static inline __sum16
ip_fast_csum(const void *iph, unsigned int ihl)
{
	const void *ptr = iph;
	unsigned int tmp, tmp2, sum;

	__asm__(
	"	ld.ab  %0, [%3, 4]		\n"
	"	ld.ab  %2, [%3, 4]		\n"
	"	sub    %1, %4, 2		\n"
	"	lsr.f  lp_count, %1, 1		\n"
	"	bcc    0f			\n"
	"	add.f  %0, %0, %2		\n"
	"	ld.ab  %2, [%3, 4]		\n"
	"0:	lp     1f			\n"
	"	ld.ab  %1, [%3, 4]		\n"
	"	adc.f  %0, %0, %2		\n"
	"	ld.ab  %2, [%3, 4]		\n"
	"	adc.f  %0, %0, %1		\n"
	"1:	adc.f  %0, %0, %2		\n"
	"	add.cs %0,%0,1			\n"
	: "=&r"(sum), "=r"(tmp), "=&r"(tmp2), "+&r" (ptr)
	: "r"(ihl)
	: "cc", "lp_count", "memory");

	return csum_fold(sum);
}

/*
 * TCP pseudo Header is 12 bytes:
 * SA [4], DA [4], zeroes [1], Proto[1], TCP Seg(hdr+data) Len [2]
 */
static inline __wsum
csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len,
		   __u8 proto, __wsum sum)
{
	__asm__ __volatile__(
	"	add.f %0, %0, %1	\n"
	"	adc.f %0, %0, %2	\n"
	"	adc.f %0, %0, %3	\n"
	"	adc.f %0, %0, %4	\n"
	"	adc   %0, %0, 0		\n"
	: "+&r"(sum)
	: "r"(saddr), "r"(daddr),
#ifdef CONFIG_CPU_BIG_ENDIAN
	  "r"(len),
#else
	  "r"(len << 8),
#endif
	  "r"(htons(proto))
	: "cc");

	return sum;
}

#define csum_fold csum_fold
#define ip_fast_csum ip_fast_csum
#define csum_tcpudp_nofold csum_tcpudp_nofold

#include <asm-generic/checksum.h>

#endif /* _ASM_ARC_CHECKSUM_H */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ASM_ARC_CMPXCHG_H
#define __ASM_ARC_CMPXCHG_H

#include <linux/build_bug.h>
#include <linux/types.h>

#include <asm/barrier.h>
#include <asm/smp.h>

#ifdef CONFIG_ARC_HAS_LLSC

/*
 * if (*ptr == @old)
 *      *ptr = @new
 */
#define __cmpxchg(ptr, old, new)					\
({									\
	__typeof__(*(ptr)) _prev;					\
									\
	__asm__ __volatile__(						\
	"1:	llock  %0, [%1]	\n"					\
	"	brne   %0, %2, 2f	\n"				\
	"	scond  %3, [%1]	\n"					\
	"	bnz     1b		\n"				\
	"2:				\n"				\
	: "=&r"(_prev)	/* Early clobber prevent reg reuse */		\
	: "r"(ptr),	/* Not "m": llock only supports reg */		\
	  "ir"(old),							\
	  "r"(new)	/* Not "ir": scond can't take LIMM */		\
	: "cc",								\
	  "memory");	/* gcc knows memory is clobbered */		\
									\
	_prev;								\
})

#define arch_cmpxchg_relaxed(ptr, old, new)				\
({									\
	__typeof__(ptr) _p_ = (ptr);					\
	__typeof__(*(ptr)) _o_ = (old);					\
	__typeof__(*(ptr)) _n_ = (new);					\
	__typeof__(*(ptr)) _prev_;					\
									\
	switch(sizeof((_p_))) {						\
	case 4:								\
		_prev_ = __cmpxchg(_p_, _o_, _n_);			\
		break;							\
	default:							\
		BUILD_BUG();						\
	}								\
	_prev_;								\
})

#else

#define arch_cmpxchg(ptr, old, new)				        \
({									\
	volatile __typeof__(ptr) _p_ = (ptr);				\
	__typeof__(*(ptr)) _o_ = (old);					\
	__typeof__(*(ptr)) _n_ = (new);					\
	__typeof__(*(ptr)) _prev_;					\
	unsigned long __flags;						\
									\
	BUILD_BUG_ON(sizeof(_p_) != 4);					\
									\
	/*								\
	 * spin lock/unlock provide the needed smp_mb() before/after	\
	 */								\
	atomic_ops_lock(__flags);					\
	_prev_ = *_p_;							\
	if (_prev_ == _o_)						\
		*_p_ = _n_;						\
	atomic_ops_unlock(__flags);					\
	_prev_;								\
})

#endif

/*
 * xchg
 */
#ifdef CONFIG_ARC_HAS_LLSC

#define __xchg(ptr, val)						\
({									\
	__asm__ __volatile__(						\
	"	ex  %0, [%1]	\n"	/* set new value */	        \
	: "+r"(val)							\
	: "r"(ptr)							\
	: "memory");							\
	_val_;		/* get old value */				\
})

#define arch_xchg_relaxed(ptr, val)					\
({									\
	__typeof__(ptr) _p_ = (ptr);					\
	__typeof__(*(ptr)) _val_ = (val);				\
									\
	switch(sizeof(*(_p_))) {					\
	case 4:								\
		_val_ = __xchg(_p_, _val_);				\
		break;							\
	default:							\
		BUILD_BUG();						\
	}								\
	_val_;								\
})

#else  /* !CONFIG_ARC_HAS_LLSC */

/*
 * EX instructions is baseline and present in !LLSC too. But in this
 * regime it still needs use @atomic_ops_lock spinlock to allow interop
 * with cmpxchg() which uses spinlock in !LLSC
 * (llist.h use xchg and cmpxchg on sama data)
 */

#define arch_xchg(ptr, val)					        \
({									\
	__typeof__(ptr) _p_ = (ptr);					\
	__typeof__(*(ptr)) _val_ = (val);				\
									\
	unsigned long __flags;						\
									\
	atomic_ops_lock(__flags);					\
									\
	__asm__ __volatile__(						\
	"	ex  %0, [%1]	\n"					\
	: "+r"(_val_)							\
	: "r"(_p_)							\
	: "memory");							\
									\
	atomic_ops_unlock(__flags);					\
	_val_;								\
})

#endif

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 *
 * Vineetg: May 16th, 2008
 *  - Current macro is now implemented as "global register" r25
 */

#ifndef _ASM_ARC_CURRENT_H
#define _ASM_ARC_CURRENT_H

#ifndef __ASSEMBLY__

#ifdef CONFIG_ARC_CURR_IN_REG

register struct task_struct *curr_arc asm("r25");
#define current (curr_arc)

#else
#include <asm-generic/current.h>
#endif /* ! CONFIG_ARC_CURR_IN_REG */

#endif /* ! __ASSEMBLY__ */

#endif /* _ASM_ARC_CURRENT_H */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 *
 * Delay routines using pre computed loops_per_jiffy value.
 *
 * vineetg: Feb 2012
 *  -Rewrote in "C" to avoid dealing with availability of H/w MPY
 *  -Also reduced the num of MPY operations from 3 to 2
 *
 * Amit Bhor: Codito Technologies 2004
 */

#ifndef __ASM_ARC_UDELAY_H
#define __ASM_ARC_UDELAY_H

#include <asm-generic/types.h>
#include <asm/param.h>		/* HZ */

extern unsigned long loops_per_jiffy;

static inline void __delay(unsigned long loops)
{
	__asm__ __volatile__(
	"	mov lp_count, %0	\n"
	"	lp  1f			\n"
	"	nop			\n"
	"1:				\n"
	:
        : "r"(loops)
        : "lp_count");
}

extern void __bad_udelay(void);

/*
 * Normal Math for computing loops in "N" usecs
 *  -we have precomputed @loops_per_jiffy
 *  -1 sec has HZ jiffies
 * loops per "N" usecs = ((loops_per_jiffy * HZ / 1000000) * N)
 *
 * Approximate Division by multiplication:
 *  -Mathematically if we multiply and divide a number by same value the
 *   result remains unchanged:  In this case, we use 2^32
 *  -> (loops_per_N_usec * 2^32 ) / 2^32
 *  -> (((loops_per_jiffy * HZ / 1000000) * N) * 2^32) / 2^32
 *  -> (loops_per_jiffy * HZ * N * 4295) / 2^32
 *
 *  -Divide by 2^32 is very simply right shift by 32
 *  -We simply need to ensure that the multiply per above eqn happens in
 *   64-bit precision (if CPU doesn't support it - gcc can emaulate it)
 */

static inline void __udelay(unsigned long usecs)
{
	unsigned long loops;

	/* (u64) cast ensures 64 bit MPY - real or emulated
	 * HZ * 4295 is pre-evaluated by gcc - hence only 2 mpy ops
	 */
	loops = ((u64) usecs * 4295 * HZ * loops_per_jiffy) >> 32;

	__delay(loops);
}

#define udelay(n) (__builtin_constant_p(n) ? ((n) > 20000 ? __bad_udelay() \
				: __udelay(n)) : __udelay(n))

#endif /* __ASM_ARC_UDELAY_H */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * several functions that help interpret ARC instructions
 * used for unaligned accesses, kprobes and kgdb
 *
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ARC_DISASM_H__
#define __ARC_DISASM_H__

enum {
	op_Bcc = 0, op_BLcc = 1, op_LD = 2, op_ST = 3, op_MAJOR_4 = 4,
	op_MAJOR_5 = 5, op_LD_ADD = 12, op_ADD_SUB_SHIFT = 13,
	op_ADD_MOV_CMP = 14, op_S = 15, op_LD_S = 16, op_LDB_S = 17,
	op_LDW_S = 18, op_LDWX_S = 19, op_ST_S = 20, op_STB_S = 21,
	op_STW_S = 22, op_Su5 = 23, op_SP = 24, op_GP = 25,
	op_Pcl = 26, op_MOV_S = 27, op_ADD_CMP = 28, op_BR_S = 29,
	op_B_S = 30, op_BL_S = 31
};

enum flow {
	noflow,
	direct_jump,
	direct_call,
	indirect_jump,
	indirect_call,
	invalid_instr
};

#define IS_BIT(word, n)		((word) & (1<<n))
#define BITS(word, s, e)	(((word) >> (s)) & (~((-2) << ((e) - (s)))))

#define MAJOR_OPCODE(word)	(BITS((word), 27, 31))
#define MINOR_OPCODE(word)	(BITS((word), 16, 21))
#define FIELD_A(word)		(BITS((word), 0, 5))
#define FIELD_B(word)		((BITS((word), 12, 14)<<3) | \
				(BITS((word), 24, 26)))
#define FIELD_C(word)		(BITS((word), 6, 11))
#define FIELD_u6(word)		FIELDC(word)
#define FIELD_s12(word)		sign_extend(((BITS((word), 0, 5) << 6) | \
					BITS((word), 6, 11)), 12)

/* note that for BL/BRcc these two macro's need another AND statement to mask
 * out bit 1 (make the result a multiple of 4) */
#define FIELD_s9(word)		sign_extend(((BITS(word, 15, 15) << 8) | \
					BITS(word, 16, 23)), 9)
#define FIELD_s21(word)		sign_extend(((BITS(word, 6, 15) << 11) | \
					(BITS(word, 17, 26) << 1)), 12)
#define FIELD_s25(word)		sign_extend(((BITS(word, 0, 3) << 21) | \
					(BITS(word, 6, 15) << 11) | \
					(BITS(word, 17, 26) << 1)), 12)

/* note: these operate on 16 bits! */
#define FIELD_S_A(word)		((BITS((word), 2, 2)<<3) | BITS((word), 0, 2))
#define FIELD_S_B(word)		((BITS((word), 10, 10)<<3) | \
				BITS((word), 8, 10))
#define FIELD_S_C(word)		((BITS((word), 7, 7)<<3) | BITS((word), 5, 7))
#define FIELD_S_H(word)		((BITS((word), 0, 2)<<3) | BITS((word), 5, 8))
#define FIELD_S_u5(word)	(BITS((word), 0, 4))
#define FIELD_S_u6(word)	(BITS((word), 0, 4) << 1)
#define FIELD_S_u7(word)	(BITS((word), 0, 4) << 2)
#define FIELD_S_u10(word)	(BITS((word), 0, 7) << 2)
#define FIELD_S_s7(word)	sign_extend(BITS((word), 0, 5) << 1, 9)
#define FIELD_S_s8(word)	sign_extend(BITS((word), 0, 7) << 1, 9)
#define FIELD_S_s9(word)	sign_extend(BITS((word), 0, 8), 9)
#define FIELD_S_s10(word)	sign_extend(BITS((word), 0, 8) << 1, 10)
#define FIELD_S_s11(word)	sign_extend(BITS((word), 0, 8) << 2, 11)
#define FIELD_S_s13(word)	sign_extend(BITS((word), 0, 10) << 2, 13)

#define STATUS32_L		0x00000100
#define REG_LIMM		62

struct disasm_state {
	/* generic info */
	unsigned long words[2];
	int instr_len;
	int major_opcode;
	/* info for branch/jump */
	int is_branch;
	int target;
	int delay_slot;
	enum flow flow;
	/* info for load/store */
	int src1, src2, src3, dest, wb_reg;
	int zz, aa, x, pref, di;
	int fault, write;
};

static inline int sign_extend(int value, int bits)
{
	if (IS_BIT(value, (bits - 1)))
		value |= (0xffffffff << bits);

	return value;
}

static inline int is_short_instr(unsigned long addr)
{
	uint16_t word = *((uint16_t *)addr);
	int opcode = (word >> 11) & 0x1F;
	return (opcode >= 0x0B);
}

void disasm_instr(unsigned long addr, struct disasm_state *state,
	int userspace, struct pt_regs *regs, struct callee_regs *cregs);
int disasm_next_pc(unsigned long pc, struct pt_regs *regs, struct callee_regs
	*cregs, unsigned long *fall_thru, unsigned long *target);
long get_reg(int reg, struct pt_regs *regs, struct callee_regs *cregs);
void set_reg(int reg, long val, struct pt_regs *regs,
		struct callee_regs *cregs);

#endif	/* __ARC_DISASM_H__ */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef ASM_ARC_DMA_H
#define ASM_ARC_DMA_H

#define MAX_DMA_ADDRESS 0xC0000000

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2020 Synopsys, Inc. (www.synopsys.com)
 *
 * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
 */
#ifndef __ASM_ARC_DSP_IMPL_H
#define __ASM_ARC_DSP_IMPL_H

#include <asm/dsp.h>

#define DSP_CTRL_DISABLED_ALL		0

#ifdef __ASSEMBLY__

/* clobbers r5 register */
.macro DSP_EARLY_INIT
#ifdef CONFIG_ISA_ARCV2
	lr	r5, [ARC_AUX_DSP_BUILD]
	bmsk	r5, r5, 7
	breq    r5, 0, 1f
	mov	r5, DSP_CTRL_DISABLED_ALL
	sr	r5, [ARC_AUX_DSP_CTRL]
1:
#endif
.endm

/* clobbers r10, r11 registers pair */
.macro DSP_SAVE_REGFILE_IRQ
#if defined(CONFIG_ARC_DSP_KERNEL)
	/*
	 * Drop any changes to DSP_CTRL made by userspace so userspace won't be
	 * able to break kernel - reset it to DSP_CTRL_DISABLED_ALL value
	 */
	mov	r10, DSP_CTRL_DISABLED_ALL
	sr	r10, [ARC_AUX_DSP_CTRL]

#elif defined(CONFIG_ARC_DSP_SAVE_RESTORE_REGS)
	/*
	 * Save DSP_CTRL register and reset it to value suitable for kernel
	 * (DSP_CTRL_DISABLED_ALL)
	 */
	mov	r10, DSP_CTRL_DISABLED_ALL
	aex	r10, [ARC_AUX_DSP_CTRL]
	st	r10, [sp, PT_DSP_CTRL]

#endif
.endm

/* clobbers r10, r11 registers pair */
.macro DSP_RESTORE_REGFILE_IRQ
#if defined(CONFIG_ARC_DSP_SAVE_RESTORE_REGS)
	ld	r10, [sp, PT_DSP_CTRL]
	sr	r10, [ARC_AUX_DSP_CTRL]

#endif
.endm

#else /* __ASEMBLY__ */

#include <linux/sched.h>
#include <asm/asserts.h>
#include <asm/switch_to.h>

#ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS

/*
 * As we save new and restore old AUX register value in the same place we
 * can optimize a bit and use AEX instruction (swap contents of an auxiliary
 * register with a core register) instead of LR + SR pair.
 */
#define AUX_SAVE_RESTORE(_saveto, _readfrom, _offt, _aux)		\
do {									\
	long unsigned int _scratch;					\
									\
	__asm__ __volatile__(						\
		"ld	%0, [%2, %4]			\n"		\
		"aex	%0, [%3]			\n"		\
		"st	%0, [%1, %4]			\n"		\
		:							\
		  "=&r" (_scratch)	/* must be early clobber */	\
		:							\
		   "r" (_saveto),					\
		   "r" (_readfrom),					\
		   "Ir" (_aux),						\
		   "Ir" (_offt)						\
		:							\
		  "memory"						\
	);								\
} while (0)

#define DSP_AUX_SAVE_RESTORE(_saveto, _readfrom, _aux)			\
	AUX_SAVE_RESTORE(_saveto, _readfrom,				\
		offsetof(struct dsp_callee_regs, _aux),			\
		ARC_AUX_##_aux)

static inline void dsp_save_restore(struct task_struct *prev,
					struct task_struct *next)
{
	long unsigned int *saveto = &prev->thread.dsp.ACC0_GLO;
	long unsigned int *readfrom = &next->thread.dsp.ACC0_GLO;

	DSP_AUX_SAVE_RESTORE(saveto, readfrom, ACC0_GLO);
	DSP_AUX_SAVE_RESTORE(saveto, readfrom, ACC0_GHI);

	DSP_AUX_SAVE_RESTORE(saveto, readfrom, DSP_BFLY0);
	DSP_AUX_SAVE_RESTORE(saveto, readfrom, DSP_FFT_CTRL);

#ifdef CONFIG_ARC_DSP_AGU_USERSPACE
	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_AP0);
	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_AP1);
	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_AP2);
	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_AP3);

	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_OS0);
	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_OS1);

	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_MOD0);
	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_MOD1);
	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_MOD2);
	DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_MOD3);
#endif /* CONFIG_ARC_DSP_AGU_USERSPACE */
}

#else /* !CONFIG_ARC_DSP_SAVE_RESTORE_REGS */
#define dsp_save_restore(p, n)
#endif /* CONFIG_ARC_DSP_SAVE_RESTORE_REGS */

static inline bool dsp_exist(void)
{
	struct bcr_generic bcr;

	READ_BCR(ARC_AUX_DSP_BUILD, bcr);
	return !!bcr.ver;
}

static inline bool agu_exist(void)
{
	struct bcr_generic bcr;

	READ_BCR(ARC_AUX_AGU_BUILD, bcr);
	return !!bcr.ver;
}

static inline void dsp_config_check(void)
{
	CHK_OPT_STRICT(CONFIG_ARC_DSP_HANDLED, dsp_exist());
	CHK_OPT_WEAK(CONFIG_ARC_DSP_AGU_USERSPACE, agu_exist());
}

#endif /* __ASEMBLY__ */
#endif /* __ASM_ARC_DSP_IMPL_H */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2020 Synopsys, Inc. (www.synopsys.com)
 *
 * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
 */
#ifndef __ASM_ARC_DSP_H
#define __ASM_ARC_DSP_H

#ifndef __ASSEMBLY__

/*
 * DSP-related saved registers - need to be saved only when you are
 * scheduled out.
 * structure fields name must correspond to aux register defenitions for
 * automatic offset calculation in DSP_AUX_SAVE_RESTORE macros
 */
struct dsp_callee_regs {
	unsigned long ACC0_GLO, ACC0_GHI, DSP_BFLY0, DSP_FFT_CTRL;
#ifdef CONFIG_ARC_DSP_AGU_USERSPACE
	unsigned long AGU_AP0, AGU_AP1, AGU_AP2, AGU_AP3;
	unsigned long AGU_OS0, AGU_OS1;
	unsigned long AGU_MOD0, AGU_MOD1, AGU_MOD2, AGU_MOD3;
#endif
};

#endif /* !__ASSEMBLY__ */

#endif /* __ASM_ARC_DSP_H */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2016-17 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef _ASM_ARC_DWARF_H
#define _ASM_ARC_DWARF_H

#ifdef __ASSEMBLY__

#ifdef ARC_DW2_UNWIND_AS_CFI

#define CFI_STARTPROC	.cfi_startproc
#define CFI_ENDPROC	.cfi_endproc
#define CFI_DEF_CFA	.cfi_def_cfa
#define CFI_REGISTER	.cfi_register
#define CFI_REL_OFFSET	.cfi_rel_offset
#define CFI_UNDEFINED	.cfi_undefined

#else

#define CFI_IGNORE	#

#define CFI_STARTPROC	CFI_IGNORE
#define CFI_ENDPROC	CFI_IGNORE
#define CFI_DEF_CFA	CFI_IGNORE
#define CFI_REGISTER	CFI_IGNORE
#define CFI_REL_OFFSET	CFI_IGNORE
#define CFI_UNDEFINED	CFI_IGNORE

#endif	/* !ARC_DW2_UNWIND_AS_CFI */

#endif	/* __ASSEMBLY__ */

#endif	/* _ASM_ARC_DWARF_H */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ASM_ARC_ELF_H
#define __ASM_ARC_ELF_H

#include <linux/types.h>
#include <linux/elf-em.h>
#include <uapi/asm/elf.h>

#define EM_ARC_INUSE		(IS_ENABLED(CONFIG_ISA_ARCOMPACT) ? \
					EM_ARCOMPACT : EM_ARCV2)

/* ARC Relocations (kernel Modules only) */
#define  R_ARC_32		0x4
#define  R_ARC_32_ME		0x1B
#define  R_ARC_32_PCREL		0x31

/*to set parameters in the core dumps */
#define ELF_ARCH		EM_ARC_INUSE
#define ELF_CLASS		ELFCLASS32

#ifdef CONFIG_CPU_BIG_ENDIAN
#define ELF_DATA		ELFDATA2MSB
#else
#define ELF_DATA		ELFDATA2LSB
#endif

/*
 * To ensure that
 *  -we don't load something for the wrong architecture.
 *  -The userspace is using the correct syscall ABI
 */
struct elf32_hdr;
extern int elf_check_arch(const struct elf32_hdr *);
#define elf_check_arch	elf_check_arch

#define CORE_DUMP_USE_REGSET

#define ELF_EXEC_PAGESIZE	PAGE_SIZE

/*
 * This is the location that an ET_DYN program is loaded if exec'ed.  Typical
 * use of this is to invoke "./ld.so someprog" to test out a new version of
 * the loader.  We need to make sure that it is out of the way of the program
 * that it will "exec", and that there is sufficient room for the brk.
 */
#define ELF_ET_DYN_BASE		(2UL * TASK_SIZE / 3)

/*
 * When the program starts, a1 contains a pointer to a function to be
 * registered with atexit, as per the SVR4 ABI.  A value of 0 means we
 * have no such handler.
 */
#define ELF_PLAT_INIT(_r, load_addr)	((_r)->r0 = 0)

/*
 * This yields a mask that user programs can use to figure out what
 * instruction set this cpu supports.
 */
#define ELF_HWCAP	(0)

/*
 * This yields a string that ld.so will use to load implementation
 * specific libraries for optimization.  This is more specific in
 * intent than poking at uname or /proc/cpuinfo.
 */
#define ELF_PLATFORM	(NULL)

#endif


code:
/* SPDX-License-Identifier: GPL-2.0 */

#ifndef __ASM_ARC_ENTRY_ARCV2_H
#define __ASM_ARC_ENTRY_ARCV2_H

#include <asm/asm-offsets.h>
#include <asm/dsp-impl.h>
#include <asm/irqflags-arcv2.h>
#include <asm/thread_info.h>	/* For THREAD_SIZE */

/*
 * Interrupt/Exception stack layout (pt_regs) for ARCv2
 *   (End of struct aligned to end of page [unless nested])
 *
 *  INTERRUPT                          EXCEPTION
 *
 *    manual    ---------------------  manual
 *              |      orig_r0      |
 *              |      event/ECR    |
 *              |      bta          |
 *              |      user_r25     |
 *              |      gp           |
 *              |      fp           |
 *              |      sp           |
 *              |      r12          |
 *              |      r30          |
 *              |      r58          |
 *              |      r59          |
 *  hw autosave ---------------------
 *    optional  |      r0           |
 *              |      r1           |
 *              ~                   ~
 *              |      r9           |
 *              |      r10          |
 *              |      r11          |
 *              |      blink        |
 *              |      lpe          |
 *              |      lps          |
 *              |      lpc          |
 *              |      ei base      |
 *              |      ldi base     |
 *              |      jli base     |
 *              ---------------------
 *  hw autosave |       pc / eret   |
 *   mandatory  | stat32 / erstatus |
 *              ---------------------
 */

/*------------------------------------------------------------------------*/
.macro INTERRUPT_PROLOGUE

	; (A) Before jumping to Interrupt Vector, hardware micro-ops did following:
	;   1. SP auto-switched to kernel mode stack
	;   2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0)
	;   3. Auto save: (mandatory) Push PC and STAT32 on stack
	;                 hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE
	;   4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI
	;
	; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair

#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
	; carve pt_regs on stack (case #3), PC/STAT32 already on stack
	sub	sp, sp, SZ_PT_REGS - 8

	__SAVE_REGFILE_HARD
#else
	; carve pt_regs on stack (case #4), which grew partially already
	sub	sp, sp, PT_r0
#endif

	__SAVE_REGFILE_SOFT
.endm

/*------------------------------------------------------------------------*/
.macro EXCEPTION_PROLOGUE

	; (A) Before jumping to Exception Vector, hardware micro-ops did following:
	;   1. SP auto-switched to kernel mode stack
	;   2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0)
	;
	; (B) Manually save the complete reg file below

	sub	sp, sp, SZ_PT_REGS	; carve pt_regs

	; _HARD saves r10 clobbered by _SOFT as scratch hence comes first

	__SAVE_REGFILE_HARD
	__SAVE_REGFILE_SOFT

	st	r0, [sp]	; orig_r0

	lr	r10, [eret]
	lr	r11, [erstatus]
	ST2	r10, r11, PT_ret

	lr	r10, [ecr]
	lr	r11, [erbta]
	ST2	r10, r11, PT_event

	; OUTPUT: r10 has ECR expected by EV_Trap
.endm

/*------------------------------------------------------------------------
 * This macro saves the registers manually which would normally be autosaved
 * by hardware on taken interrupts. It is used by
 *   - exception handlers (which don't have autosave)
 *   - interrupt autosave disabled due to CONFIG_ARC_IRQ_NO_AUTOSAVE
 */
.macro __SAVE_REGFILE_HARD

	ST2	r0,  r1,  PT_r0
	ST2	r2,  r3,  PT_r2
	ST2	r4,  r5,  PT_r4
	ST2	r6,  r7,  PT_r6
	ST2	r8,  r9,  PT_r8
	ST2	r10, r11, PT_r10

	st	blink, [sp, PT_blink]

	lr	r10, [lp_end]
	lr	r11, [lp_start]
	ST2	r10, r11, PT_lpe

	st	lp_count, [sp, PT_lpc]

	; skip JLI, LDI, EI for now
.endm

/*------------------------------------------------------------------------
 * This macros saves a bunch of other registers which can't be autosaved for
 * various reasons:
 *   - r12: the last caller saved scratch reg since hardware saves in pairs so r0-r11
 *   - r30: free reg, used by gcc as scratch
 *   - ACCL/ACCH pair when they exist
 */
.macro __SAVE_REGFILE_SOFT

	ST2	gp, fp, PT_r26		; gp (r26), fp (r27)

	st	r12, [sp, PT_sp + 4]
	st	r30, [sp, PT_sp + 8]

	; Saving pt_regs->sp correctly requires some extra work due to the way
	; Auto stack switch works
	;  - U mode: retrieve it from AUX_USER_SP
	;  - K mode: add the offset from current SP where H/w starts auto push
	;
	; 1. Utilize the fact that Z bit is set if Intr taken in U mode
	; 2. Upon entry SP is always saved (for any inspection, unwinding etc),
	;    but on return, restored only if U mode

	lr	r10, [AUX_USER_SP]	; U mode SP

	; ISA requires ADD.nz to have same dest and src reg operands
	mov.nz	r10, sp
	add.nz	r10, r10, SZ_PT_REGS	; K mode SP

	st	r10, [sp, PT_sp]	; SP (pt_regs->sp)

#ifdef CONFIG_ARC_CURR_IN_REG
	st	r25, [sp, PT_user_r25]
	GET_CURR_TASK_ON_CPU	r25
#endif

#ifdef CONFIG_ARC_HAS_ACCL_REGS
	ST2	r58, r59, PT_r58
#endif

	/* clobbers r10, r11 registers pair */
	DSP_SAVE_REGFILE_IRQ
.endm

/*------------------------------------------------------------------------*/
.macro __RESTORE_REGFILE_SOFT

	LD2	gp, fp, PT_r26		; gp (r26), fp (r27)

	ld	r12, [sp, PT_r12]
	ld	r30, [sp, PT_r30]

	; Restore SP (into AUX_USER_SP) only if returning to U mode
	;  - for K mode, it will be implicitly restored as stack is unwound
	;  - Z flag set on K is inverse of what hardware does on interrupt entry
	;    but that doesn't really matter
	bz	1f

	ld	r10, [sp, PT_sp]	; SP (pt_regs->sp)
	sr	r10, [AUX_USER_SP]
1:

#ifdef CONFIG_ARC_CURR_IN_REG
	ld	r25, [sp, PT_user_r25]
#endif

	/* clobbers r10, r11 registers pair */
	DSP_RESTORE_REGFILE_IRQ

#ifdef CONFIG_ARC_HAS_ACCL_REGS
	LD2	r58, r59, PT_r58
#endif
.endm

/*------------------------------------------------------------------------*/
.macro __RESTORE_REGFILE_HARD

	ld	blink, [sp, PT_blink]

	LD2	r10, r11, PT_lpe
	sr	r10, [lp_end]
	sr	r11, [lp_start]

	ld	r10, [sp, PT_lpc]	; lp_count can't be target of LD
	mov	lp_count, r10

	LD2	r0,  r1,  PT_r0
	LD2	r2,  r3,  PT_r2
	LD2	r4,  r5,  PT_r4
	LD2	r6,  r7,  PT_r6
	LD2	r8,  r9,  PT_r8
	LD2	r10, r11, PT_r10
.endm

/*------------------------------------------------------------------------*/
.macro INTERRUPT_EPILOGUE

	; INPUT: r0 has STAT32 of calling context
	; INPUT: Z flag set if returning to K mode

	; _SOFT clobbers r10 restored by _HARD hence the order

	__RESTORE_REGFILE_SOFT

#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
	__RESTORE_REGFILE_HARD

	; SP points to PC/STAT32: hw restores them despite NO_AUTOSAVE
	add	sp, sp, SZ_PT_REGS - 8
#else
	add	sp, sp, PT_r0
#endif

.endm

/*------------------------------------------------------------------------*/
.macro EXCEPTION_EPILOGUE

	; INPUT: r0 has STAT32 of calling context

	btst	r0, STATUS_U_BIT	; Z flag set if K, used in restoring SP

	ld	r10, [sp, PT_event + 4]
	sr	r10, [erbta]

	LD2	r10, r11, PT_ret
	sr	r10, [eret]
	sr	r11, [erstatus]

	__RESTORE_REGFILE_SOFT
	__RESTORE_REGFILE_HARD

	add	sp, sp, SZ_PT_REGS
.endm

.macro FAKE_RET_FROM_EXCPN
	lr      r9, [status32]
	bic     r9, r9, STATUS_AE_MASK
	or      r9, r9, STATUS_IE_MASK
	kflag   r9
.endm

/* Get thread_info of "current" tsk */
.macro GET_CURR_THR_INFO_FROM_SP  reg
	bmskn \reg, sp, THREAD_SHIFT - 1
.endm

/* Get CPU-ID of this core */
.macro  GET_CPU_ID  reg
	lr  \reg, [identity]
	xbfu \reg, \reg, 0xE8	/* 00111    01000 */
				/* M = 8-1  N = 8 */
.endm

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 *
 * Vineetg: March 2009 (Supporting 2 levels of Interrupts)
 *  Stack switching code can no longer reliably rely on the fact that
 *  if we are NOT in user mode, stack is switched to kernel mode.
 *  e.g. L2 IRQ interrupted a L1 ISR which had not yet completed
 *  it's prologue including stack switching from user mode
 *
 * Vineetg: Aug 28th 2008: Bug #94984
 *  -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
 *   Normally CPU does this automatically, however when doing FAKE rtie,
 *   we also need to explicitly do this. The problem in macros
 *   FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
 *   was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context
 *
 * Vineetg: May 5th 2008
 *  -Modified CALLEE_REG save/restore macros to handle the fact that
 *      r25 contains the kernel current task ptr
 *  - Defined Stack Switching Macro to be reused in all intr/excp hdlrs
 *  - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the
 *      address Write back load ld.ab instead of separate ld/add instn
 *
 * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
 */

#ifndef __ASM_ARC_ENTRY_COMPACT_H
#define __ASM_ARC_ENTRY_COMPACT_H

#include <asm/asm-offsets.h>
#include <asm/irqflags-compact.h>
#include <asm/thread_info.h>	/* For THREAD_SIZE */

/*--------------------------------------------------------------
 * Switch to Kernel Mode stack if SP points to User Mode stack
 *
 * Entry   : r9 contains pre-IRQ/exception/trap status32
 * Exit    : SP set to K mode stack
 *           SP at the time of entry (K/U) saved @ pt_regs->sp
 * Clobbers: r9
 *-------------------------------------------------------------*/

.macro SWITCH_TO_KERNEL_STK

	/* User Mode when this happened ? Yes: Proceed to switch stack */
	bbit1   r9, STATUS_U_BIT, 88f

	/* OK we were already in kernel mode when this event happened, thus can
	 * assume SP is kernel mode SP. _NO_ need to do any stack switching
	 */

#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
	/* However....
	 * If Level 2 Interrupts enabled, we may end up with a corner case:
	 * 1. User Task executing
	 * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode)
	 * 3. But before it could switch SP from USER to KERNEL stack
	 *      a L2 IRQ "Interrupts" L1
	 * Thay way although L2 IRQ happened in Kernel mode, stack is still
	 * not switched.
	 * To handle this, we may need to switch stack even if in kernel mode
	 * provided SP has values in range of USER mode stack ( < 0x7000_0000 )
	 */
	brlo sp, VMALLOC_START, 88f

	/* TODO: vineetg:
	 * We need to be a bit more cautious here. What if a kernel bug in
	 * L1 ISR, caused SP to go whaco (some small value which looks like
	 * USER stk) and then we take L2 ISR.
	 * Above brlo alone would treat it as a valid L1-L2 scenario
	 * instead of shouting around
	 * The only feasible way is to make sure this L2 happened in
	 * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
	 * L1 ISR before it switches stack
	 */

#endif

    /*------Intr/Ecxp happened in kernel mode, SP already setup ------ */
	/* save it nevertheless @ pt_regs->sp for uniformity */

	b.d	66f
	st	sp, [sp, PT_sp - SZ_PT_REGS]

88: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */

	GET_CURR_TASK_ON_CPU   r9

	/* With current tsk in r9, get it's kernel mode stack base */
	GET_TSK_STACK_BASE  r9, r9

	/* save U mode SP @ pt_regs->sp */
	st	sp, [r9, PT_sp - SZ_PT_REGS]

	/* final SP switch */
	mov	sp, r9
66:
.endm

/*------------------------------------------------------------
 * "FAKE" a rtie to return from CPU Exception context
 * This is to re-enable Exceptions within exception
 * Look at EV_ProtV to see how this is actually used
 *-------------------------------------------------------------*/

.macro FAKE_RET_FROM_EXCPN

	lr	r9, [status32]
	bclr	r9, r9, STATUS_AE_BIT
	or	r9, r9, (STATUS_E1_MASK|STATUS_E2_MASK)
	sr	r9, [erstatus]
	mov	r9, 55f
	sr	r9, [eret]
	rtie
55:
.endm

/*--------------------------------------------------------------
 * For early Exception/ISR Prologue, a core reg is temporarily needed to
 * code the rest of prolog (stack switching). This is done by stashing
 * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP).
 *
 * Before saving the full regfile - this reg is restored back, only
 * to be saved again on kernel mode stack, as part of pt_regs.
 *-------------------------------------------------------------*/
.macro PROLOG_FREEUP_REG	reg, mem
	st  \reg, [\mem]
.endm

.macro PROLOG_RESTORE_REG	reg, mem
	ld  \reg, [\mem]
.endm

/*--------------------------------------------------------------
 * Exception Entry prologue
 * -Switches stack to K mode (if not already)
 * -Saves the register file
 *
 * After this it is safe to call the "C" handlers
 *-------------------------------------------------------------*/
.macro EXCEPTION_PROLOGUE

	/* Need at least 1 reg to code the early exception prologue */
	PROLOG_FREEUP_REG r9, @ex_saved_reg1

	/* U/K mode at time of exception (stack not switched if already K) */
	lr  r9, [erstatus]

	/* ARC700 doesn't provide auto-stack switching */
	SWITCH_TO_KERNEL_STK

#ifdef CONFIG_ARC_CURR_IN_REG
	/* Treat r25 as scratch reg (save on stack) and load with "current" */
	PUSH    r25
	GET_CURR_TASK_ON_CPU   r25
#else
	sub     sp, sp, 4
#endif

	st.a	r0, [sp, -8]    /* orig_r0 needed for syscall (skip ECR slot) */
	sub	sp, sp, 4	/* skip pt_regs->sp, already saved above */

	/* Restore r9 used to code the early prologue */
	PROLOG_RESTORE_REG  r9, @ex_saved_reg1

	/* now we are ready to save the regfile */
	SAVE_R0_TO_R12
	PUSH	gp
	PUSH	fp
	PUSH	blink
	PUSHAX	eret
	PUSHAX	erstatus
	PUSH	lp_count
	PUSHAX	lp_end
	PUSHAX	lp_start
	PUSHAX	erbta

	lr	r10, [ecr]
	st      r10, [sp, PT_event]    /* EV_Trap expects r10 to have ECR */
.endm

/*--------------------------------------------------------------
 * Restore all registers used by system call or Exceptions
 * SP should always be pointing to the next free stack element
 * when entering this macro.
 *
 * NOTE:
 *
 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
 * for memory load operations. If used in that way interrupts are deffered
 * by hardware and that is not good.
 *-------------------------------------------------------------*/
.macro EXCEPTION_EPILOGUE

	POPAX	erbta
	POPAX	lp_start
	POPAX	lp_end

	POP	r9
	mov	lp_count, r9	;LD to lp_count is not allowed

	POPAX	erstatus
	POPAX	eret
	POP	blink
	POP	fp
	POP	gp
	RESTORE_R12_TO_R0

#ifdef CONFIG_ARC_CURR_IN_REG
	ld	r25, [sp, 12]
#endif
	ld  sp, [sp] /* restore original sp */
	/* orig_r0, ECR, user_r25 skipped automatically */
.endm

/* Dummy ECR values for Interrupts */
#define event_IRQ1		0x0031abcd
#define event_IRQ2		0x0032abcd

.macro INTERRUPT_PROLOGUE  LVL

	/* free up r9 as scratchpad */
	PROLOG_FREEUP_REG r9, @int\LVL\()_saved_reg

	/* Which mode (user/kernel) was the system in when intr occurred */
	lr  r9, [status32_l\LVL\()]

	SWITCH_TO_KERNEL_STK

#ifdef CONFIG_ARC_CURR_IN_REG
	/* Treat r25 as scratch reg (save on stack) and load with "current" */
	PUSH    r25
	GET_CURR_TASK_ON_CPU   r25
#else
	sub     sp, sp, 4
#endif

	PUSH	0x003\LVL\()abcd    /* Dummy ECR */
	sub	sp, sp, 8	    /* skip orig_r0 (not needed)
				       skip pt_regs->sp, already saved above */

	/* Restore r9 used to code the early prologue */
	PROLOG_RESTORE_REG  r9, @int\LVL\()_saved_reg

	SAVE_R0_TO_R12
	PUSH	gp
	PUSH	fp
	PUSH	blink
	PUSH	ilink\LVL\()
	PUSHAX	status32_l\LVL\()
	PUSH	lp_count
	PUSHAX	lp_end
	PUSHAX	lp_start
	PUSHAX	bta_l\LVL\()

.endm

/*--------------------------------------------------------------
 * Restore all registers used by interrupt handlers.
 *
 * NOTE:
 *
 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
 * for memory load operations. If used in that way interrupts are deffered
 * by hardware and that is not good.
 *-------------------------------------------------------------*/
.macro INTERRUPT_EPILOGUE  LVL

	POPAX	bta_l\LVL\()
	POPAX	lp_start
	POPAX	lp_end

	POP	r9
	mov	lp_count, r9	;LD to lp_count is not allowed

	POPAX	status32_l\LVL\()
	POP	ilink\LVL\()
	POP	blink
	POP	fp
	POP	gp
	RESTORE_R12_TO_R0

#ifdef CONFIG_ARC_CURR_IN_REG
	ld	r25, [sp, 12]
#endif
	ld  sp, [sp] /* restore original sp */
	/* orig_r0, ECR, user_r25 skipped automatically */
.endm

/* Get thread_info of "current" tsk */
.macro GET_CURR_THR_INFO_FROM_SP  reg
	bic \reg, sp, (THREAD_SIZE - 1)
.endm

/* Get CPU-ID of this core */
.macro  GET_CPU_ID  reg
	lr  \reg, [identity]
	lsr \reg, \reg, 8
	bmsk \reg, \reg, 7
.endm

#endif  /* __ASM_ARC_ENTRY_COMPACT_H */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ASM_ARC_ENTRY_H
#define __ASM_ARC_ENTRY_H

#include <asm/unistd.h>		/* For NR_syscalls defination */
#include <asm/arcregs.h>
#include <asm/ptrace.h>
#include <asm/processor.h>	/* For VMALLOC_START */
#include <asm/mmu.h>

#ifdef CONFIG_ISA_ARCOMPACT
#include <asm/entry-compact.h>	/* ISA specific bits */
#else
#include <asm/entry-arcv2.h>
#endif

/* Note on the LD/ST addr modes with addr reg wback
 *
 * LD.a same as LD.aw
 *
 * LD.a    reg1, [reg2, x]  => Pre Incr
 *      Eff Addr for load = [reg2 + x]
 *
 * LD.ab   reg1, [reg2, x]  => Post Incr
 *      Eff Addr for load = [reg2]
 */

.macro PUSH reg
	st.a	\reg, [sp, -4]
.endm

.macro PUSHAX aux
	lr	r9, [\aux]
	PUSH	r9
.endm

.macro POP reg
	ld.ab	\reg, [sp, 4]
.endm

.macro POPAX aux
	POP	r9
	sr	r9, [\aux]
.endm

/*--------------------------------------------------------------
 * Helpers to save/restore Scratch Regs:
 * used by Interrupt/Exception Prologue/Epilogue
 *-------------------------------------------------------------*/
.macro  SAVE_R0_TO_R12
	PUSH	r0
	PUSH	r1
	PUSH	r2
	PUSH	r3
	PUSH	r4
	PUSH	r5
	PUSH	r6
	PUSH	r7
	PUSH	r8
	PUSH	r9
	PUSH	r10
	PUSH	r11
	PUSH	r12
.endm

.macro RESTORE_R12_TO_R0
	POP	r12
	POP	r11
	POP	r10
	POP	r9
	POP	r8
	POP	r7
	POP	r6
	POP	r5
	POP	r4
	POP	r3
	POP	r2
	POP	r1
	POP	r0

.endm

/*--------------------------------------------------------------
 * Helpers to save/restore callee-saved regs:
 * used by several macros below
 *-------------------------------------------------------------*/
.macro SAVE_R13_TO_R24
	PUSH	r13
	PUSH	r14
	PUSH	r15
	PUSH	r16
	PUSH	r17
	PUSH	r18
	PUSH	r19
	PUSH	r20
	PUSH	r21
	PUSH	r22
	PUSH	r23
	PUSH	r24
.endm

.macro RESTORE_R24_TO_R13
	POP	r24
	POP	r23
	POP	r22
	POP	r21
	POP	r20
	POP	r19
	POP	r18
	POP	r17
	POP	r16
	POP	r15
	POP	r14
	POP	r13
.endm

/*--------------------------------------------------------------
 * Collect User Mode callee regs as struct callee_regs - needed by
 * fork/do_signal/unaligned-access-emulation.
 * (By default only scratch regs are saved on entry to kernel)
 *
 * Special handling for r25 if used for caching Task Pointer.
 * It would have been saved in task->thread.user_r25 already, but to keep
 * the interface same it is copied into regular r25 placeholder in
 * struct callee_regs.
 *-------------------------------------------------------------*/
.macro SAVE_CALLEE_SAVED_USER

	mov	r12, sp		; save SP as ref to pt_regs
	SAVE_R13_TO_R24

#ifdef CONFIG_ARC_CURR_IN_REG
	; Retrieve orig r25 and save it with rest of callee_regs
	ld	r12, [r12, PT_user_r25]
	PUSH	r12
#else
	PUSH	r25
#endif

.endm

/*--------------------------------------------------------------
 * Save kernel Mode callee regs at the time of Contect Switch.
 *
 * Special handling for r25 if used for caching Task Pointer.
 * Kernel simply skips saving it since it will be loaded with
 * incoming task pointer anyways
 *-------------------------------------------------------------*/
.macro SAVE_CALLEE_SAVED_KERNEL

	SAVE_R13_TO_R24

#ifdef CONFIG_ARC_CURR_IN_REG
	sub     sp, sp, 4
#else
	PUSH	r25
#endif
.endm

/*--------------------------------------------------------------
 * Opposite of SAVE_CALLEE_SAVED_KERNEL
 *-------------------------------------------------------------*/
.macro RESTORE_CALLEE_SAVED_KERNEL

#ifdef CONFIG_ARC_CURR_IN_REG
	add     sp, sp, 4  /* skip usual r25 placeholder */
#else
	POP	r25
#endif
	RESTORE_R24_TO_R13
.endm

/*--------------------------------------------------------------
 * Opposite of SAVE_CALLEE_SAVED_USER
 *
 * ptrace tracer or unaligned-access fixup might have changed a user mode
 * callee reg which is saved back to usual r25 storage location
 *-------------------------------------------------------------*/
.macro RESTORE_CALLEE_SAVED_USER

#ifdef CONFIG_ARC_CURR_IN_REG
	POP	r12
#else
	POP	r25
#endif
	RESTORE_R24_TO_R13

	; SP is back to start of pt_regs
#ifdef CONFIG_ARC_CURR_IN_REG
	st	r12, [sp, PT_user_r25]
#endif
.endm

/*--------------------------------------------------------------
 * Super FAST Restore callee saved regs by simply re-adjusting SP
 *-------------------------------------------------------------*/
.macro DISCARD_CALLEE_SAVED_USER
	add     sp, sp, SZ_CALLEE_REGS
.endm

/*-------------------------------------------------------------
 * given a tsk struct, get to the base of it's kernel mode stack
 * tsk->thread_info is really a PAGE, whose bottom hoists stack
 * which grows upwards towards thread_info
 *------------------------------------------------------------*/

.macro GET_TSK_STACK_BASE tsk, out

	/* Get task->thread_info (this is essentially start of a PAGE) */
	ld  \out, [\tsk, TASK_THREAD_INFO]

	/* Go to end of page where stack begins (grows upwards) */
	add2 \out, \out, (THREAD_SIZE)/4

.endm

/*
 * @reg [OUT] thread_info->flags of "current"
 */
.macro GET_CURR_THR_INFO_FLAGS  reg
	GET_CURR_THR_INFO_FROM_SP  \reg
	ld  \reg, [\reg, THREAD_INFO_FLAGS]
.endm

#ifdef CONFIG_SMP

/*-------------------------------------------------
 * Retrieve the current running task on this CPU
 * 1. Determine curr CPU id.
 * 2. Use it to index into _current_task[ ]
 */
.macro  GET_CURR_TASK_ON_CPU   reg
	GET_CPU_ID  \reg
	ld.as  \reg, [@_current_task, \reg]
.endm

/*-------------------------------------------------
 * Save a new task as the "current" task on this CPU
 * 1. Determine curr CPU id.
 * 2. Use it to index into _current_task[ ]
 *
 * Coded differently than GET_CURR_TASK_ON_CPU (which uses LD.AS)
 * because ST r0, [r1, offset] can ONLY have s9 @offset
 * while   LD can take s9 (4 byte insn) or LIMM (8 byte insn)
 */

.macro  SET_CURR_TASK_ON_CPU    tsk, tmp
	GET_CPU_ID  \tmp
	add2 \tmp, @_current_task, \tmp
	st   \tsk, [\tmp]
#ifdef CONFIG_ARC_CURR_IN_REG
	mov r25, \tsk
#endif

.endm

#else   /* Uniprocessor implementation of macros */

.macro  GET_CURR_TASK_ON_CPU    reg
	ld  \reg, [@_current_task]
.endm

.macro  SET_CURR_TASK_ON_CPU    tsk, tmp
	st  \tsk, [@_current_task]
#ifdef CONFIG_ARC_CURR_IN_REG
	mov r25, \tsk
#endif
.endm

#endif /* SMP / UNI */

/* ------------------------------------------------------------------
 * Get the ptr to some field of Current Task at @off in task struct
 *  -Uses r25 for Current task ptr if that is enabled
 */

#ifdef CONFIG_ARC_CURR_IN_REG

.macro GET_CURR_TASK_FIELD_PTR  off,  reg
	add \reg, r25, \off
.endm

#else

.macro GET_CURR_TASK_FIELD_PTR  off,  reg
	GET_CURR_TASK_ON_CPU  \reg
	add \reg, \reg, \off
.endm

#endif	/* CONFIG_ARC_CURR_IN_REG */

#endif  /* __ASM_ARC_ENTRY_H */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ASM_ARC_EXEC_H
#define __ASM_ARC_EXEC_H

/* Align to 16b */
#define arch_align_stack(p) ((unsigned long)(p) & ~0xf)

#endif


code:
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_FB_H_
#define _ASM_FB_H_

#include <linux/fb.h>
#include <linux/fs.h>
#include <asm/page.h>

static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
				unsigned long off)
{
	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
}

static inline int fb_is_primary_device(struct fb_info *info)
{
	return 0;
}

#endif /* _ASM_FB_H_ */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2020 Synopsys, Inc. (www.synopsys.com)
 *
 */

#ifndef _ASM_ARC_FPU_H
#define _ASM_ARC_FPU_H

#ifdef CONFIG_ARC_FPU_SAVE_RESTORE

#include <asm/ptrace.h>

#ifdef CONFIG_ISA_ARCOMPACT

/* These DPFP regs need to be saved/restored across ctx-sw */
struct arc_fpu {
	struct {
		unsigned int l, h;
	} aux_dpfp[2];
};

#define fpu_init_task(regs)

#else

/*
 * ARCv2 FPU Control aux register
 *   - bits to enable Traps on Exceptions
 *   - Rounding mode
 *
 * ARCv2 FPU Status aux register
 *   - FPU exceptions flags (Inv, Div-by-Zero, overflow, underflow, inexact)
 *   - Flag Write Enable to clear flags explicitly (vs. by fpu instructions
 *     only
 */

struct arc_fpu {
	unsigned int ctrl, status;
};

extern void fpu_init_task(struct pt_regs *regs);

#endif	/* !CONFIG_ISA_ARCOMPACT */

struct task_struct;

extern void fpu_save_restore(struct task_struct *p, struct task_struct *n);

#else	/* !CONFIG_ARC_FPU_SAVE_RESTORE */

#define fpu_save_restore(p, n)
#define fpu_init_task(regs)

#endif	/* CONFIG_ARC_FPU_SAVE_RESTORE */

#endif	/* _ASM_ARC_FPU_H */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 *
 * Vineetg: August 2010: From Android kernel work
 */

#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H

#include <linux/futex.h>
#include <linux/preempt.h>
#include <linux/uaccess.h>
#include <asm/errno.h>

#ifdef CONFIG_ARC_HAS_LLSC

#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)\
							\
	smp_mb();					\
	__asm__ __volatile__(				\
	"1:	llock	%1, [%2]		\n"	\
		insn				"\n"	\
	"2:	scond	%0, [%2]		\n"	\
	"	bnz	1b			\n"	\
	"	mov %0, 0			\n"	\
	"3:					\n"	\
	"	.section .fixup,\"ax\"		\n"	\
	"	.align  4			\n"	\
	"4:	mov %0, %4			\n"	\
	"	j   3b				\n"	\
	"	.previous			\n"	\
	"	.section __ex_table,\"a\"	\n"	\
	"	.align  4			\n"	\
	"	.word   1b, 4b			\n"	\
	"	.word   2b, 4b			\n"	\
	"	.previous			\n"	\
							\
	: "=&r" (ret), "=&r" (oldval)			\
	: "r" (uaddr), "r" (oparg), "ir" (-EFAULT)	\
	: "cc", "memory");				\
	smp_mb()					\

#else	/* !CONFIG_ARC_HAS_LLSC */

#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)\
							\
	smp_mb();					\
	__asm__ __volatile__(				\
	"1:	ld	%1, [%2]		\n"	\
		insn				"\n"	\
	"2:	st	%0, [%2]		\n"	\
	"	mov %0, 0			\n"	\
	"3:					\n"	\
	"	.section .fixup,\"ax\"		\n"	\
	"	.align  4			\n"	\
	"4:	mov %0, %4			\n"	\
	"	j   3b				\n"	\
	"	.previous			\n"	\
	"	.section __ex_table,\"a\"	\n"	\
	"	.align  4			\n"	\
	"	.word   1b, 4b			\n"	\
	"	.word   2b, 4b			\n"	\
	"	.previous			\n"	\
							\
	: "=&r" (ret), "=&r" (oldval)			\
	: "r" (uaddr), "r" (oparg), "ir" (-EFAULT)	\
	: "cc", "memory");				\
	smp_mb()					\

#endif

static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
		u32 __user *uaddr)
{
	int oldval = 0, ret;

	if (!access_ok(uaddr, sizeof(u32)))
		return -EFAULT;

#ifndef CONFIG_ARC_HAS_LLSC
	preempt_disable();	/* to guarantee atomic r-m-w of futex op */
#endif

	switch (op) {
	case FUTEX_OP_SET:
		__futex_atomic_op("mov %0, %3", ret, oldval, uaddr, oparg);
		break;
	case FUTEX_OP_ADD:
		/* oldval = *uaddr; *uaddr += oparg ; ret = *uaddr */
		__futex_atomic_op("add %0, %1, %3", ret, oldval, uaddr, oparg);
		break;
	case FUTEX_OP_OR:
		__futex_atomic_op("or  %0, %1, %3", ret, oldval, uaddr, oparg);
		break;
	case FUTEX_OP_ANDN:
		__futex_atomic_op("bic %0, %1, %3", ret, oldval, uaddr, oparg);
		break;
	case FUTEX_OP_XOR:
		__futex_atomic_op("xor %0, %1, %3", ret, oldval, uaddr, oparg);
		break;
	default:
		ret = -ENOSYS;
	}

#ifndef CONFIG_ARC_HAS_LLSC
	preempt_enable();
#endif

	if (!ret)
		*oval = oldval;

	return ret;
}

/*
 * cmpxchg of futex (pagefaults disabled by caller)
 * Return 0 for success, -EFAULT otherwise
 */
static inline int
futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 expval,
			      u32 newval)
{
	int ret = 0;
	u32 existval;

	if (!access_ok(uaddr, sizeof(u32)))
		return -EFAULT;

#ifndef CONFIG_ARC_HAS_LLSC
	preempt_disable();	/* to guarantee atomic r-m-w of futex op */
#endif
	smp_mb();

	__asm__ __volatile__(
#ifdef CONFIG_ARC_HAS_LLSC
	"1:	llock	%1, [%4]		\n"
	"	brne	%1, %2, 3f		\n"
	"2:	scond	%3, [%4]		\n"
	"	bnz	1b			\n"
#else
	"1:	ld	%1, [%4]		\n"
	"	brne	%1, %2, 3f		\n"
	"2:	st	%3, [%4]		\n"
#endif
	"3:	\n"
	"	.section .fixup,\"ax\"	\n"
	"4:	mov %0, %5	\n"
	"	j   3b	\n"
	"	.previous	\n"
	"	.section __ex_table,\"a\"	\n"
	"	.align  4	\n"
	"	.word   1b, 4b	\n"
	"	.word   2b, 4b	\n"
	"	.previous\n"
	: "+&r"(ret), "=&r"(existval)
	: "r"(expval), "r"(newval), "r"(uaddr), "ir"(-EFAULT)
	: "cc", "memory");

	smp_mb();

#ifndef CONFIG_ARC_HAS_LLSC
	preempt_enable();
#endif
	*uval = existval;
	return ret;
}

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2015 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef _ASM_HIGHMEM_H
#define _ASM_HIGHMEM_H

#ifdef CONFIG_HIGHMEM

#include <uapi/asm/page.h>
#include <asm/kmap_size.h>

#define FIXMAP_SIZE		PGDIR_SIZE
#define PKMAP_SIZE		PGDIR_SIZE

/* start after vmalloc area */
#define FIXMAP_BASE		(PAGE_OFFSET - FIXMAP_SIZE - PKMAP_SIZE)

#define FIX_KMAP_SLOTS		(KM_MAX_IDX * NR_CPUS)
#define FIX_KMAP_BEGIN		(0UL)
#define FIX_KMAP_END		((FIX_KMAP_BEGIN + FIX_KMAP_SLOTS) - 1)

#define FIXADDR_TOP		(FIXMAP_BASE + (FIX_KMAP_END << PAGE_SHIFT))

/*
 * This should be converted to the asm-generic version, but of course this
 * is needlessly different from all other architectures. Sigh - tglx
 */
#define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
#define __virt_to_fix(x)	(((FIXADDR_TOP - ((x) & PAGE_MASK))) >> PAGE_SHIFT)

/* start after fixmap area */
#define PKMAP_BASE		(FIXMAP_BASE + FIXMAP_SIZE)
#define LAST_PKMAP		(PKMAP_SIZE >> PAGE_SHIFT)
#define LAST_PKMAP_MASK		(LAST_PKMAP - 1)
#define PKMAP_ADDR(nr)		(PKMAP_BASE + ((nr) << PAGE_SHIFT))
#define PKMAP_NR(virt)		(((virt) - PKMAP_BASE) >> PAGE_SHIFT)

#include <asm/cacheflush.h>

extern void kmap_init(void);

#define arch_kmap_local_post_unmap(vaddr)			\
	local_flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE)

static inline void flush_cache_kmaps(void)
{
	flush_cache_all();
}
#endif

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2013-15 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef _ASM_ARC_HUGEPAGE_H
#define _ASM_ARC_HUGEPAGE_H

#include <linux/types.h>
#include <asm-generic/pgtable-nopmd.h>

static inline pte_t pmd_pte(pmd_t pmd)
{
	return __pte(pmd_val(pmd));
}

static inline pmd_t pte_pmd(pte_t pte)
{
	return __pmd(pte_val(pte));
}

#define pmd_wrprotect(pmd)	pte_pmd(pte_wrprotect(pmd_pte(pmd)))
#define pmd_mkwrite(pmd)	pte_pmd(pte_mkwrite(pmd_pte(pmd)))
#define pmd_mkdirty(pmd)	pte_pmd(pte_mkdirty(pmd_pte(pmd)))
#define pmd_mkold(pmd)		pte_pmd(pte_mkold(pmd_pte(pmd)))
#define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
#define pmd_mkhuge(pmd)		pte_pmd(pte_mkhuge(pmd_pte(pmd)))
#define pmd_mkinvalid(pmd)	pte_pmd(pte_mknotpresent(pmd_pte(pmd)))
#define pmd_mkclean(pmd)	pte_pmd(pte_mkclean(pmd_pte(pmd)))

#define pmd_write(pmd)		pte_write(pmd_pte(pmd))
#define pmd_young(pmd)		pte_young(pmd_pte(pmd))
#define pmd_dirty(pmd)		pte_dirty(pmd_pte(pmd))

#define mk_pmd(page, prot)	pte_pmd(mk_pte(page, prot))

#define pmd_trans_huge(pmd)	(pmd_val(pmd) & _PAGE_HW_SZ)

#define pfn_pmd(pfn, prot)	(__pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))

static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
{
        /*
         * open-coded pte_modify() with additional retaining of HW_SZ bit
         * so that pmd_trans_huge() remains true for this PMD
         */
        return __pmd((pmd_val(pmd) & (_PAGE_CHG_MASK | _PAGE_HW_SZ)) | pgprot_val(newprot));
}

static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
			      pmd_t *pmdp, pmd_t pmd)
{
	*pmdp = pmd;
}

extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
				 pmd_t *pmd);

#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
extern void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
				unsigned long end);

/* We don't have hardware dirty/accessed bits, generic_pmdp_establish is fine.*/
#define pmdp_establish generic_pmdp_establish

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef _ASM_ARC_IO_H
#define _ASM_ARC_IO_H

#include <linux/types.h>
#include <asm/byteorder.h>
#include <asm/page.h>
#include <asm/unaligned.h>

#ifdef CONFIG_ISA_ARCV2
#include <asm/barrier.h>
#define __iormb()		rmb()
#define __iowmb()		wmb()
#else
#define __iormb()		do { } while (0)
#define __iowmb()		do { } while (0)
#endif

extern void __iomem *ioremap(phys_addr_t paddr, unsigned long size);
extern void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size,
				  unsigned long flags);
static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
{
	return (void __iomem *)port;
}

static inline void ioport_unmap(void __iomem *addr)
{
}

extern void iounmap(const volatile void __iomem *addr);

/*
 * io{read,write}{16,32}be() macros
 */
#define ioread16be(p)		({ u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
#define ioread32be(p)		({ u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })

#define iowrite16be(v,p)	({ __iowmb(); __raw_writew((__force u16)cpu_to_be16(v), p); })
#define iowrite32be(v,p)	({ __iowmb(); __raw_writel((__force u32)cpu_to_be32(v), p); })

/* Change struct page to physical address */
#define page_to_phys(page)		(page_to_pfn(page) << PAGE_SHIFT)

#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
	u8 b;

	__asm__ __volatile__(
	"	ldb%U1 %0, %1	\n"
	: "=r" (b)
	: "m" (*(volatile u8 __force *)addr)
	: "memory");

	return b;
}

#define __raw_readw __raw_readw
static inline u16 __raw_readw(const volatile void __iomem *addr)
{
	u16 s;

	__asm__ __volatile__(
	"	ldw%U1 %0, %1	\n"
	: "=r" (s)
	: "m" (*(volatile u16 __force *)addr)
	: "memory");

	return s;
}

#define __raw_readl __raw_readl
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
	u32 w;

	__asm__ __volatile__(
	"	ld%U1 %0, %1	\n"
	: "=r" (w)
	: "m" (*(volatile u32 __force *)addr)
	: "memory");

	return w;
}

/*
 * {read,write}s{b,w,l}() repeatedly access the same IO address in
 * native endianness in 8-, 16-, 32-bit chunks {into,from} memory,
 * @count times
 */
#define __raw_readsx(t,f) \
static inline void __raw_reads##f(const volatile void __iomem *addr,	\
				  void *ptr, unsigned int count)	\
{									\
	bool is_aligned = ((unsigned long)ptr % ((t) / 8)) == 0;	\
	u##t *buf = ptr;						\
									\
	if (!count)							\
		return;							\
									\
	/* Some ARC CPU's don't support unaligned accesses */		\
	if (is_aligned) {						\
		do {							\
			u##t x = __raw_read##f(addr);			\
			*buf++ = x;					\
		} while (--count);					\
	} else {							\
		do {							\
			u##t x = __raw_read##f(addr);			\
			put_unaligned(x, buf++);			\
		} while (--count);					\
	}								\
}

#define __raw_readsb __raw_readsb
__raw_readsx(8, b)
#define __raw_readsw __raw_readsw
__raw_readsx(16, w)
#define __raw_readsl __raw_readsl
__raw_readsx(32, l)

#define __raw_writeb __raw_writeb
static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
{
	__asm__ __volatile__(
	"	stb%U1 %0, %1	\n"
	:
	: "r" (b), "m" (*(volatile u8 __force *)addr)
	: "memory");
}

#define __raw_writew __raw_writew
static inline void __raw_writew(u16 s, volatile void __iomem *addr)
{
	__asm__ __volatile__(
	"	stw%U1 %0, %1	\n"
	:
	: "r" (s), "m" (*(volatile u16 __force *)addr)
	: "memory");

}

#define __raw_writel __raw_writel
static inline void __raw_writel(u32 w, volatile void __iomem *addr)
{
	__asm__ __volatile__(
	"	st%U1 %0, %1	\n"
	:
	: "r" (w), "m" (*(volatile u32 __force *)addr)
	: "memory");

}

#define __raw_writesx(t,f)						\
static inline void __raw_writes##f(volatile void __iomem *addr, 	\
				   const void *ptr, unsigned int count)	\
{									\
	bool is_aligned = ((unsigned long)ptr % ((t) / 8)) == 0;	\
	const u##t *buf = ptr;						\
									\
	if (!count)							\
		return;							\
									\
	/* Some ARC CPU's don't support unaligned accesses */		\
	if (is_aligned) {						\
		do {							\
			__raw_write##f(*buf++, addr);			\
		} while (--count);					\
	} else {							\
		do {							\
			__raw_write##f(get_unaligned(buf++), addr);	\
		} while (--count);					\
	}								\
}

#define __raw_writesb __raw_writesb
__raw_writesx(8, b)
#define __raw_writesw __raw_writesw
__raw_writesx(16, w)
#define __raw_writesl __raw_writesl
__raw_writesx(32, l)

/*
 * MMIO can also get buffered/optimized in micro-arch, so barriers needed
 * Based on ARM model for the typical use case
 *
 *	<ST [DMA buffer]>
 *	<writel MMIO "go" reg>
 *  or:
 *	<readl MMIO "status" reg>
 *	<LD [DMA buffer]>
 *
 * http://lkml.kernel.org/r/20150622133656.GG1583@arm.com
 */
#define readb(c)		({ u8  __v = readb_relaxed(c); __iormb(); __v; })
#define readw(c)		({ u16 __v = readw_relaxed(c); __iormb(); __v; })
#define readl(c)		({ u32 __v = readl_relaxed(c); __iormb(); __v; })
#define readsb(p,d,l)		({ __raw_readsb(p,d,l); __iormb(); })
#define readsw(p,d,l)		({ __raw_readsw(p,d,l); __iormb(); })
#define readsl(p,d,l)		({ __raw_readsl(p,d,l); __iormb(); })

#define writeb(v,c)		({ __iowmb(); writeb_relaxed(v,c); })
#define writew(v,c)		({ __iowmb(); writew_relaxed(v,c); })
#define writel(v,c)		({ __iowmb(); writel_relaxed(v,c); })
#define writesb(p,d,l)		({ __iowmb(); __raw_writesb(p,d,l); })
#define writesw(p,d,l)		({ __iowmb(); __raw_writesw(p,d,l); })
#define writesl(p,d,l)		({ __iowmb(); __raw_writesl(p,d,l); })

/*
 * Relaxed API for drivers which can handle barrier ordering themselves
 *
 * Also these are defined to perform little endian accesses.
 * To provide the typical device register semantics of fixed endian,
 * swap the byte order for Big Endian
 *
 * http://lkml.kernel.org/r/201603100845.30602.arnd@arndb.de
 */
#define readb_relaxed(c)	__raw_readb(c)
#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
					__raw_readw(c)); __r; })
#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
					__raw_readl(c)); __r; })

#define writeb_relaxed(v,c)	__raw_writeb(v,c)
#define writew_relaxed(v,c)	__raw_writew((__force u16) cpu_to_le16(v),c)
#define writel_relaxed(v,c)	__raw_writel((__force u32) cpu_to_le32(v),c)

#include <asm-generic/io.h>

#endif /* _ASM_ARC_IO_H */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ASM_ARC_IRQ_H
#define __ASM_ARC_IRQ_H

/*
 * ARCv2 can support 240 interrupts in the core interrupts controllers and
 * 128 interrupts in IDU. Thus 512 virtual IRQs must be enough for most
 * configurations of boards.
 * This doesnt affect ARCompact, but we change it to same value
 */
#define NR_IRQS		512

/* Platform Independent IRQs */
#ifdef CONFIG_ISA_ARCV2
#define IPI_IRQ		19
#define SOFTIRQ_IRQ	21
#define FIRST_EXT_IRQ	24
#endif

#include <linux/interrupt.h>
#include <asm-generic/irq.h>

extern void arc_init_IRQ(void);

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ASM_IRQFLAGS_ARCV2_H
#define __ASM_IRQFLAGS_ARCV2_H

#include <asm/arcregs.h>

/* status32 Bits */
#define STATUS_AD_BIT	19   /* Disable Align chk: core supports non-aligned */
#define STATUS_IE_BIT	31

#define STATUS_AD_MASK		(1<<STATUS_AD_BIT)
#define STATUS_IE_MASK		(1<<STATUS_IE_BIT)

/* status32 Bits as encoded/expected by CLRI/SETI */
#define CLRI_STATUS_IE_BIT	4

#define CLRI_STATUS_E_MASK	0xF
#define CLRI_STATUS_IE_MASK	(1 << CLRI_STATUS_IE_BIT)

#define AUX_USER_SP		0x00D
#define AUX_IRQ_CTRL		0x00E
#define AUX_IRQ_ACT		0x043	/* Active Intr across all levels */
#define AUX_IRQ_LVL_PEND	0x200	/* Pending Intr across all levels */
#define AUX_IRQ_HINT		0x201	/* For generating Soft Interrupts */
#define AUX_IRQ_PRIORITY	0x206
#define ICAUSE			0x40a
#define AUX_IRQ_SELECT		0x40b
#define AUX_IRQ_ENABLE		0x40c

/* Was Intr taken in User Mode */
#define AUX_IRQ_ACT_BIT_U	31

/*
 * Hardware supports 16 priorities (0 highest, 15 lowest)
 * Linux by default runs at 1, priority 0 reserved for NMI style interrupts
 */
#define ARCV2_IRQ_DEF_PRIO	1

/* seed value for status register */
#ifdef CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS
#define __AD_ENB	STATUS_AD_MASK
#else
#define __AD_ENB	0
#endif

#define ISA_INIT_STATUS_BITS	(STATUS_IE_MASK | __AD_ENB | \
					(ARCV2_IRQ_DEF_PRIO << 1))

#ifndef __ASSEMBLY__

/*
 * Save IRQ state and disable IRQs
 */
static inline long arch_local_irq_save(void)
{
	unsigned long flags;

	__asm__ __volatile__("	clri %0	\n" : "=r" (flags) : : "memory");

	return flags;
}

/*
 * restore saved IRQ state
 */
static inline void arch_local_irq_restore(unsigned long flags)
{
	__asm__ __volatile__("	seti %0	\n" : : "r" (flags) : "memory");
}

/*
 * Unconditionally Enable IRQs
 */
static inline void arch_local_irq_enable(void)
{
	unsigned int irqact = read_aux_reg(AUX_IRQ_ACT);

	if (irqact & 0xffff)
		write_aux_reg(AUX_IRQ_ACT, irqact & ~0xffff);

	__asm__ __volatile__("	seti	\n" : : : "memory");
}

/*
 * Unconditionally Disable IRQs
 */
static inline void arch_local_irq_disable(void)
{
	__asm__ __volatile__("	clri	\n" : : : "memory");
}

/*
 * save IRQ state
 */
static inline long arch_local_save_flags(void)
{
	unsigned long temp;

	__asm__ __volatile__(
	"	lr  %0, [status32]	\n"
	: "=&r"(temp)
	:
	: "memory");

	/* To be compatible with irq_save()/irq_restore()
	 * encode the irq bits as expected by CLRI/SETI
	 * (this was needed to make CONFIG_TRACE_IRQFLAGS work)
	 */
	temp = (1 << 5) |
		((!!(temp & STATUS_IE_MASK)) << CLRI_STATUS_IE_BIT) |
		((temp >> 1) & CLRI_STATUS_E_MASK);
	return temp;
}

/*
 * Query IRQ state
 */
static inline int arch_irqs_disabled_flags(unsigned long flags)
{
	return !(flags & CLRI_STATUS_IE_MASK);
}

static inline int arch_irqs_disabled(void)
{
	return arch_irqs_disabled_flags(arch_local_save_flags());
}

static inline void arc_softirq_trigger(int irq)
{
	write_aux_reg(AUX_IRQ_HINT, irq);
}

static inline void arc_softirq_clear(int irq)
{
	write_aux_reg(AUX_IRQ_HINT, 0);
}

#else

#ifdef CONFIG_TRACE_IRQFLAGS

.macro TRACE_ASM_IRQ_DISABLE
	bl	trace_hardirqs_off
.endm

.macro TRACE_ASM_IRQ_ENABLE
	bl	trace_hardirqs_on
.endm

#else

.macro TRACE_ASM_IRQ_DISABLE
.endm

.macro TRACE_ASM_IRQ_ENABLE
.endm

#endif
.macro IRQ_DISABLE  scratch
	clri
	TRACE_ASM_IRQ_DISABLE
.endm

.macro IRQ_ENABLE  scratch
	TRACE_ASM_IRQ_ENABLE
	seti
.endm

#endif	/* __ASSEMBLY__ */

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ASM_IRQFLAGS_ARCOMPACT_H
#define __ASM_IRQFLAGS_ARCOMPACT_H

/* vineetg: March 2010 : local_irq_save( ) optimisation
 *  -Remove explicit mov of current status32 into reg, that is not needed
 *  -Use BIC  insn instead of INVERTED + AND
 *  -Conditionally disable interrupts (if they are not enabled, don't disable)
*/

#include <asm/arcregs.h>

/* status32 Reg bits related to Interrupt Handling */
#define STATUS_E1_BIT		1	/* Int 1 enable */
#define STATUS_E2_BIT		2	/* Int 2 enable */
#define STATUS_A1_BIT		3	/* Int 1 active */
#define STATUS_A2_BIT		4	/* Int 2 active */
#define STATUS_AE_BIT		5	/* Exception active */

#define STATUS_E1_MASK		(1<<STATUS_E1_BIT)
#define STATUS_E2_MASK		(1<<STATUS_E2_BIT)
#define STATUS_A1_MASK		(1<<STATUS_A1_BIT)
#define STATUS_A2_MASK		(1<<STATUS_A2_BIT)
#define STATUS_AE_MASK		(1<<STATUS_AE_BIT)
#define STATUS_IE_MASK		(STATUS_E1_MASK | STATUS_E2_MASK)

/* Other Interrupt Handling related Aux regs */
#define AUX_IRQ_LEV		0x200	/* IRQ Priority: L1 or L2 */
#define AUX_IRQ_HINT		0x201	/* For generating Soft Interrupts */
#define AUX_IRQ_LV12		0x43	/* interrupt level register */

#define AUX_IENABLE		0x40c
#define AUX_ITRIGGER		0x40d
#define AUX_IPULSE		0x415

#define ISA_INIT_STATUS_BITS	STATUS_IE_MASK

#ifndef __ASSEMBLY__

/******************************************************************
 * IRQ Control Macros
 *
 * All of them have "memory" clobber (compiler barrier) which is needed to
 * ensure that LD/ST requiring irq safetly (R-M-W when LLSC is not available)
 * are redone after IRQs are re-enabled (and gcc doesn't reuse stale register)
 *
 * Noted at the time of Abilis Timer List corruption
 *
 * Orig Bug + Rejected solution:
 * https://lore.kernel.org/lkml/1364553218-31255-1-git-send-email-vgupta@synopsys.com
 *
 * Reasoning:
 * https://lore.kernel.org/lkml/CA+55aFyFWjpSVQM6M266tKrG_ZXJzZ-nYejpmXYQXbrr42mGPQ@mail.gmail.com
 *
 ******************************************************************/

/*
 * Save IRQ state and disable IRQs
 */
static inline long arch_local_irq_save(void)
{
	unsigned long temp, flags;

	__asm__ __volatile__(
	"	lr  %1, [status32]	\n"
	"	bic %0, %1, %2		\n"
	"	and.f 0, %1, %2	\n"
	"	flag.nz %0		\n"
	: "=r"(temp), "=r"(flags)
	: "n"((STATUS_E1_MASK | STATUS_E2_MASK))
	: "memory", "cc");

	return flags;
}

/*
 * restore saved IRQ state
 */
static inline void arch_local_irq_restore(unsigned long flags)
{

	__asm__ __volatile__(
	"	flag %0			\n"
	:
	: "r"(flags)
	: "memory");
}

/*
 * Unconditionally Enable IRQs
 */
#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
extern void arch_local_irq_enable(void);
#else
static inline void arch_local_irq_enable(void)
{
	unsigned long temp;

	__asm__ __volatile__(
	"	lr   %0, [status32]	\n"
	"	or   %0, %0, %1		\n"
	"	flag %0			\n"
	: "=&r"(temp)
	: "n"((STATUS_E1_MASK | STATUS_E2_MASK))
	: "cc", "memory");
}
#endif

/*
 * Unconditionally Disable IRQs
 */
static inline void arch_local_irq_disable(void)
{
	unsigned long temp;

	__asm__ __volatile__(
	"	lr  %0, [status32]	\n"
	"	and %0, %0, %1		\n"
	"	flag %0			\n"
	: "=&r"(temp)
	: "n"(~(STATUS_E1_MASK | STATUS_E2_MASK))
	: "memory");
}

/*
 * save IRQ state
 */
static inline long arch_local_save_flags(void)
{
	unsigned long temp;

	__asm__ __volatile__(
	"	lr  %0, [status32]	\n"
	: "=&r"(temp)
	:
	: "memory");

	return temp;
}

/*
 * Query IRQ state
 */
static inline int arch_irqs_disabled_flags(unsigned long flags)
{
	return !(flags & (STATUS_E1_MASK
#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
			| STATUS_E2_MASK
#endif
		));
}

static inline int arch_irqs_disabled(void)
{
	return arch_irqs_disabled_flags(arch_local_save_flags());
}

#else

#ifdef CONFIG_TRACE_IRQFLAGS

.macro TRACE_ASM_IRQ_DISABLE
	bl	trace_hardirqs_off
.endm

.macro TRACE_ASM_IRQ_ENABLE
	bl	trace_hardirqs_on
.endm

#else

.macro TRACE_ASM_IRQ_DISABLE
.endm

.macro TRACE_ASM_IRQ_ENABLE
.endm

#endif

.macro IRQ_DISABLE  scratch
	lr	\scratch, [status32]
	bic	\scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
	flag	\scratch
	TRACE_ASM_IRQ_DISABLE
.endm

.macro IRQ_ENABLE  scratch
	TRACE_ASM_IRQ_ENABLE
	lr	\scratch, [status32]
	or	\scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
	flag	\scratch
.endm

#endif	/* __ASSEMBLY__ */

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ASM_ARC_IRQFLAGS_H
#define __ASM_ARC_IRQFLAGS_H

#ifdef CONFIG_ISA_ARCOMPACT
#include <asm/irqflags-compact.h>
#else
#include <asm/irqflags-arcv2.h>
#endif

#endif


code:
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_ARC_JUMP_LABEL_H
#define _ASM_ARC_JUMP_LABEL_H

#ifndef __ASSEMBLY__

#include <linux/stringify.h>
#include <linux/types.h>

#define JUMP_LABEL_NOP_SIZE 4

/*
 * NOTE about '.balign 4':
 *
 * To make atomic update of patched instruction available we need to guarantee
 * that this instruction doesn't cross L1 cache line boundary.
 *
 * As of today we simply align instruction which can be patched by 4 byte using
 * ".balign 4" directive. In that case patched instruction is aligned with one
 * 16-bit NOP_S if this is required.
 * However 'align by 4' directive is much stricter than it actually required.
 * It's enough that our 32-bit instruction don't cross L1 cache line boundary /
 * L1 I$ fetch block boundary which can be achieved by using
 * ".bundle_align_mode" assembler directive. That will save us from adding
 * useless NOP_S padding in most of the cases.
 *
 * TODO: switch to ".bundle_align_mode" directive using whin it will be
 * supported by ARC toolchain.
 */

static __always_inline bool arch_static_branch(struct static_key *key,
					       bool branch)
{
	asm_volatile_goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)"	\n"
		 "1:							\n"
		 "nop							\n"
		 ".pushsection __jump_table, \"aw\"			\n"
		 ".word 1b, %l[l_yes], %c0				\n"
		 ".popsection						\n"
		 : : "i" (&((char *)key)[branch]) : : l_yes);

	return false;
l_yes:
	return true;
}

static __always_inline bool arch_static_branch_jump(struct static_key *key,
						    bool branch)
{
	asm_volatile_goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)"	\n"
		 "1:							\n"
		 "b %l[l_yes]						\n"
		 ".pushsection __jump_table, \"aw\"			\n"
		 ".word 1b, %l[l_yes], %c0				\n"
		 ".popsection						\n"
		 : : "i" (&((char *)key)[branch]) : : l_yes);

	return false;
l_yes:
	return true;
}

typedef u32 jump_label_t;

struct jump_entry {
	jump_label_t code;
	jump_label_t target;
	jump_label_t key;
};

#endif  /* __ASSEMBLY__ */
#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef _ASM_ARC_KDEBUG_H
#define _ASM_ARC_KDEBUG_H

enum die_val {
	DIE_UNUSED,
	DIE_TRAP,
	DIE_IERR,
	DIE_OOPS
};

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * kgdb support for ARC
 *
 * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ARC_KGDB_H__
#define __ARC_KGDB_H__

#ifdef CONFIG_KGDB

#include <asm/ptrace.h>

/* to ensure compatibility with Linux 2.6.35, we don't implement the get/set
 * register API yet */
#undef DBG_MAX_REG_NUM

#define GDB_MAX_REGS		87

#define BREAK_INSTR_SIZE	2
#define CACHE_FLUSH_IS_SAFE	1
#define NUMREGBYTES		(GDB_MAX_REGS * 4)
#define BUFMAX			2048

static inline void arch_kgdb_breakpoint(void)
{
	__asm__ __volatile__ ("trap_s	0x4\n");
}

extern void kgdb_trap(struct pt_regs *regs);

/* This is the numbering of registers according to the GDB. See GDB's
 * arc-tdep.h for details.
 *
 * Registers are ordered for GDB 7.5. It is incompatible with GDB 6.8. */
enum arc_linux_regnums {
	_R0		= 0,
	_R1, _R2, _R3, _R4, _R5, _R6, _R7, _R8, _R9, _R10, _R11, _R12, _R13,
	_R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21, _R22, _R23, _R24,
	_R25, _R26,
	_FP		= 27,
	__SP		= 28,
	_R30		= 30,
	_BLINK		= 31,
	_LP_COUNT	= 60,
	_STOP_PC	= 64,
	_RET		= 64,
	_LP_START	= 65,
	_LP_END		= 66,
	_STATUS32	= 67,
	_ECR		= 76,
	_BTA		= 82,
};

#else
#define kgdb_trap(regs)
#endif

#endif	/* __ARC_KGDB_H__ */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef _ARC_KPROBES_H
#define _ARC_KPROBES_H

#include <asm-generic/kprobes.h>

#ifdef CONFIG_KPROBES

typedef u16 kprobe_opcode_t;

#define UNIMP_S_INSTRUCTION 0x79e0
#define TRAP_S_2_INSTRUCTION 0x785e

#define MAX_INSN_SIZE   8
#define MAX_STACK_SIZE  64

struct arch_specific_insn {
	int is_short;
	kprobe_opcode_t *t1_addr, *t2_addr;
	kprobe_opcode_t t1_opcode, t2_opcode;
};

#define flush_insn_slot(p)  do {  } while (0)

#define kretprobe_blacklist_size    0

struct kprobe;

void arch_remove_kprobe(struct kprobe *p);

int kprobe_exceptions_notify(struct notifier_block *self,
			     unsigned long val, void *data);

struct prev_kprobe {
	struct kprobe *kp;
	unsigned long status;
};

struct kprobe_ctlblk {
	unsigned int kprobe_status;
	struct prev_kprobe prev_kprobe;
};

int kprobe_fault_handler(struct pt_regs *regs, unsigned long cause);
void __kretprobe_trampoline(void);
void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
#else
#define trap_is_kprobe(address, regs)
#endif /* CONFIG_KPROBES */

#endif /* _ARC_KPROBES_H */


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef __ASM_LINKAGE_H
#define __ASM_LINKAGE_H

#include <asm/dwarf.h>

#ifdef __ASSEMBLY__

.macro ST2 e, o, off
#ifdef CONFIG_ARC_HAS_LL64
	std	\e, [sp, \off]
#else
	st	\e, [sp, \off]
	st	\o, [sp, \off+4]
#endif
.endm

.macro LD2 e, o, off
#ifdef CONFIG_ARC_HAS_LL64
	ldd	\e, [sp, \off]
#else
	ld	\e, [sp, \off]
	ld	\o, [sp, \off+4]
#endif
.endm

#define ASM_NL		 `	/* use '`' to mark new line in macro */
#define __ALIGN		.align 4
#define __ALIGN_STR	__stringify(__ALIGN)

/* annotation for data we want in DCCM - if enabled in .config */
.macro ARCFP_DATA nm
#ifdef CONFIG_ARC_HAS_DCCM
	.section .data.arcfp
#else
	.section .data
#endif
	.global \nm
.endm

/* annotation for data we want in DCCM - if enabled in .config */
.macro ARCFP_CODE
#ifdef CONFIG_ARC_HAS_ICCM
	.section .text.arcfp, "ax",@progbits
#else
	.section .text, "ax",@progbits
#endif
.endm

#define ENTRY_CFI(name)		\
	.globl name ASM_NL	\
	ALIGN ASM_NL 		\
	name: ASM_NL		\
	CFI_STARTPROC ASM_NL

#define END_CFI(name) 		\
	CFI_ENDPROC ASM_NL	\
	.size name, .-name

#else	/* !__ASSEMBLY__ */

#ifdef CONFIG_ARC_HAS_ICCM
#define __arcfp_code __section(".text.arcfp")
#else
#define __arcfp_code __section(".text")
#endif

#ifdef CONFIG_ARC_HAS_DCCM
#define __arcfp_data __section(".data.arcfp")
#else
#define __arcfp_data __section(".data")
#endif

#endif /* __ASSEMBLY__ */

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
 *
 * based on METAG mach/arch.h (which in turn was based on ARM)
 */

#ifndef _ASM_ARC_MACH_DESC_H_
#define _ASM_ARC_MACH_DESC_H_

/**
 * struct machine_desc - Board specific callbacks, called from ARC common code
 *	Provided by each ARC board using MACHINE_START()/MACHINE_END(), so
 *	a multi-platform kernel builds with array of such descriptors.
 *	We extend the early DT scan to also match the DT's "compatible" string
 *	against the @dt_compat of all such descriptors, and one with highest
 *	"DT score" is selected as global @machine_desc.
 *
 * @name:		Board/SoC name
 * @dt_compat:		Array of device tree 'compatible' strings
 * 			(XXX: although only 1st entry is looked at)
 * @init_early:		Very early callback [called from setup_arch()]
 * @init_per_cpu:	for each CPU as it is coming up (SMP as well as UP)
 * 			[(M):init_IRQ(), (o):start_kernel_secondary()]
 * @init_machine:	arch initcall level callback (e.g. populate static
 * 			platform devices or parse Devicetree)
 * @init_late:		Late initcall level callback
 *
 */
struct machine_desc {
	const char		*name;
	const char		**dt_compat;
	void			(*init_early)(void);
	void			(*init_per_cpu)(unsigned int);
	void			(*init_machine)(void);
	void			(*init_late)(void);

};

/*
 * Current machine - only accessible during boot.
 */
extern const struct machine_desc *machine_desc;

/*
 * Machine type table - also only accessible during boot
 */
extern const struct machine_desc __arch_info_begin[], __arch_info_end[];

/*
 * Set of macros to define architecture features.
 * This is built into a table by the linker.
 */
#define MACHINE_START(_type, _name)			\
static const struct machine_desc __mach_desc_##_type	\
__used __section(".arch.info.init") = {			\
	.name		= _name,

#define MACHINE_END				\
};

extern const struct machine_desc *setup_machine_fdt(void *dt);

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012, 2019-20 Synopsys, Inc. (www.synopsys.com)
 *
 * MMUv3 (arc700) / MMUv4 (archs) are software page walked and software managed.
 * This file contains the TLB access registers and commands
 */

#ifndef _ASM_ARC_MMU_ARCV2_H
#define _ASM_ARC_MMU_ARCV2_H

/*
 * TLB Management regs
 */
#define ARC_REG_MMU_BCR		0x06f

#ifdef CONFIG_ARC_MMU_V3
#define ARC_REG_TLBPD0		0x405
#define ARC_REG_TLBPD1		0x406
#define ARC_REG_TLBPD1HI	0	/* Dummy: allows common code */
#define ARC_REG_TLBINDEX	0x407
#define ARC_REG_TLBCOMMAND	0x408
#define ARC_REG_PID		0x409
#define ARC_REG_SCRATCH_DATA0	0x418
#else
#define ARC_REG_TLBPD0		0x460
#define ARC_REG_TLBPD1		0x461
#define ARC_REG_TLBPD1HI	0x463
#define ARC_REG_TLBINDEX	0x464
#define ARC_REG_TLBCOMMAND	0x465
#define ARC_REG_PID		0x468
#define ARC_REG_SCRATCH_DATA0	0x46c
#endif

/* Bits in MMU PID reg */
#define __TLB_ENABLE		(1 << 31)
#define __PROG_ENABLE		(1 << 30)
#define MMU_ENABLE		(__TLB_ENABLE | __PROG_ENABLE)

/* Bits in TLB Index reg */
#define TLB_LKUP_ERR		0x80000000

#ifdef CONFIG_ARC_MMU_V3
#define TLB_DUP_ERR		(TLB_LKUP_ERR | 0x00000001)
#else
#define TLB_DUP_ERR		(TLB_LKUP_ERR | 0x40000000)
#endif

/*
 * TLB Commands
 */
#define TLBWrite    		0x1
#define TLBRead     		0x2
#define TLBGetIndex 		0x3
#define TLBProbe    		0x4
#define TLBWriteNI		0x5  /* write JTLB without inv uTLBs */
#define TLBIVUTLB		0x6  /* explicitly inv uTLBs */

#ifdef CONFIG_ARC_MMU_V4
#define TLBInsertEntry		0x7
#define TLBDeleteEntry		0x8
#endif

/* Masks for actual TLB "PD"s */
#define PTE_BITS_IN_PD0		(_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_HW_SZ)
#define PTE_BITS_RWX		(_PAGE_EXECUTE | _PAGE_WRITE | _PAGE_READ)

#define PTE_BITS_NON_RWX_IN_PD1	(PAGE_MASK_PHYS | _PAGE_CACHEABLE)

#ifndef __ASSEMBLY__

struct mm_struct;
extern int pae40_exist_but_not_enab(void);

static inline int is_pae40_enabled(void)
{
	return IS_ENABLED(CONFIG_ARC_HAS_PAE40);
}

static inline void mmu_setup_asid(struct mm_struct *mm, unsigned long asid)
{
	write_aux_reg(ARC_REG_PID, asid | MMU_ENABLE);
}

static inline void mmu_setup_pgd(struct mm_struct *mm, void *pgd)
{
	/* PGD cached in MMU reg to avoid 3 mem lookups: task->mm->pgd */
#ifdef CONFIG_ISA_ARCV2
	write_aux_reg(ARC_REG_SCRATCH_DATA0, (unsigned int)pgd);
#endif
}

#else

.macro ARC_MMU_REENABLE reg
	lr \reg, [ARC_REG_PID]
	or \reg, \reg, MMU_ENABLE
	sr \reg, [ARC_REG_PID]
.endm

#endif /* !__ASSEMBLY__ */

#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#ifndef _ASM_ARC_MMU_H
#define _ASM_ARC_MMU_H

#ifndef __ASSEMBLY__

#include <linux/threads.h>	/* NR_CPUS */

typedef struct {
	unsigned long asid[NR_CPUS];	/* 8 bit MMU PID + Generation cycle */
} mm_context_t;

#endif

#include <asm/mmu-arcv2.h>

#endif