M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions

View File

@ -0,0 +1,58 @@
include include/asm-generic/Kbuild.asm
header-y += registers.h
header-y += ucontext.h
header-y += user.h
generic-y += auxvec.h
generic-y += bug.h
generic-y += bugs.h
generic-y += cpumask.h
generic-y += cputime.h
generic-y += current.h
generic-y += device.h
generic-y += div64.h
generic-y += emergency-restart.h
generic-y += errno.h
generic-y += fb.h
generic-y += fcntl.h
generic-y += ftrace.h
generic-y += hardirq.h
generic-y += hw_irq.h
generic-y += ioctl.h
generic-y += ioctls.h
generic-y += iomap.h
generic-y += ipcbuf.h
generic-y += ipc.h
generic-y += irq_regs.h
generic-y += kdebug.h
generic-y += kmap_types.h
generic-y += local64.h
generic-y += local.h
generic-y += local.h
generic-y += mman.h
generic-y += msgbuf.h
generic-y += pci.h
generic-y += percpu.h
generic-y += poll.h
generic-y += posix_types.h
generic-y += resource.h
generic-y += rwsem.h
generic-y += scatterlist.h
generic-y += sections.h
generic-y += segment.h
generic-y += sembuf.h
generic-y += shmbuf.h
generic-y += shmparam.h
generic-y += siginfo.h
generic-y += socket.h
generic-y += sockios.h
generic-y += statfs.h
generic-y += stat.h
generic-y += termbits.h
generic-y += termios.h
generic-y += topology.h
generic-y += types.h
generic-y += ucontext.h
generic-y += unaligned.h
generic-y += xor.h

View File

@ -0,0 +1 @@
#include <generated/asm-offsets.h>

View File

@ -0,0 +1,165 @@
/*
* Atomic operations for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_ATOMIC_H
#define _ASM_ATOMIC_H
#include <linux/types.h>
#include <asm/cmpxchg.h>
#define ATOMIC_INIT(i) { (i) }
#define atomic_set(v, i) ((v)->counter = (i))
/**
* atomic_read - reads a word, atomically
* @v: pointer to atomic value
*
* Assumes all word reads on our architecture are atomic.
*/
#define atomic_read(v) ((v)->counter)
/**
* atomic_xchg - atomic
* @v: pointer to memory to change
* @new: new value (technically passed in a register -- see xchg)
*/
#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
/**
* atomic_cmpxchg - atomic compare-and-exchange values
* @v: pointer to value to change
* @old: desired old value to match
* @new: new value to put in
*
* Parameters are then pointer, value-in-register, value-in-register,
* and the output is the old value.
*
* Apparently this is complicated for archs that don't support
* the memw_locked like we do (or it's broken or whatever).
*
* Kind of the lynchpin of the rest of the generically defined routines.
* Remember V2 had that bug with dotnew predicate set by memw_locked.
*
* "old" is "expected" old val, __oldval is actual old value
*/
static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
{
int __oldval;
asm volatile(
"1: %0 = memw_locked(%1);\n"
" { P0 = cmp.eq(%0,%2);\n"
" if (!P0.new) jump:nt 2f; }\n"
" memw_locked(%1,P0) = %3;\n"
" if (!P0) jump 1b;\n"
"2:\n"
: "=&r" (__oldval)
: "r" (&v->counter), "r" (old), "r" (new)
: "memory", "p0"
);
return __oldval;
}
static inline int atomic_add_return(int i, atomic_t *v)
{
int output;
__asm__ __volatile__ (
"1: %0 = memw_locked(%1);\n"
" %0 = add(%0,%2);\n"
" memw_locked(%1,P3)=%0;\n"
" if !P3 jump 1b;\n"
: "=&r" (output)
: "r" (&v->counter), "r" (i)
: "memory", "p3"
);
return output;
}
#define atomic_add(i, v) atomic_add_return(i, (v))
static inline int atomic_sub_return(int i, atomic_t *v)
{
int output;
__asm__ __volatile__ (
"1: %0 = memw_locked(%1);\n"
" %0 = sub(%0,%2);\n"
" memw_locked(%1,P3)=%0\n"
" if !P3 jump 1b;\n"
: "=&r" (output)
: "r" (&v->counter), "r" (i)
: "memory", "p3"
);
return output;
}
#define atomic_sub(i, v) atomic_sub_return(i, (v))
/**
* atomic_add_unless - add unless the number is a given value
* @v: pointer to value
* @a: amount to add
* @u: unless value is equal to u
*
* Returns 1 if the add happened, 0 if it didn't.
*/
static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
int output, __oldval;
asm volatile(
"1: %0 = memw_locked(%2);"
" {"
" p3 = cmp.eq(%0, %4);"
" if (p3.new) jump:nt 2f;"
" %0 = add(%0, %3);"
" %1 = #0;"
" }"
" memw_locked(%2, p3) = %0;"
" {"
" if !p3 jump 1b;"
" %1 = #1;"
" }"
"2:"
: "=&r" (__oldval), "=&r" (output)
: "r" (v), "r" (a), "r" (u)
: "memory", "p3"
);
return output;
}
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
#define atomic_inc(v) atomic_add(1, (v))
#define atomic_dec(v) atomic_sub(1, (v))
#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
#define atomic_sub_and_test(i, v) (atomic_sub_return(i, (v)) == 0)
#define atomic_add_negative(i, v) (atomic_add_return(i, (v)) < 0)
#define atomic_inc_return(v) (atomic_add_return(1, v))
#define atomic_dec_return(v) (atomic_sub_return(1, v))
#endif

View File

@ -0,0 +1,41 @@
/*
* Memory barrier definitions for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_BARRIER_H
#define _ASM_BARRIER_H
#define rmb() barrier()
#define read_barrier_depends() barrier()
#define wmb() barrier()
#define mb() barrier()
#define smp_rmb() barrier()
#define smp_read_barrier_depends() barrier()
#define smp_wmb() barrier()
#define smp_mb() barrier()
#define smp_mb__before_atomic_dec() barrier()
#define smp_mb__after_atomic_dec() barrier()
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
/* Set a value and use a memory barrier. Used by the scheduler somewhere. */
#define set_mb(var, value) \
do { var = value; mb(); } while (0)
#endif /* _ASM_BARRIER_H */

View File

@ -0,0 +1,300 @@
/*
* Bit operations for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_BITOPS_H
#define _ASM_BITOPS_H
#include <linux/compiler.h>
#include <asm/byteorder.h>
#include <asm/atomic.h>
#ifdef __KERNEL__
#define smp_mb__before_clear_bit() barrier()
#define smp_mb__after_clear_bit() barrier()
/*
* The offset calculations for these are based on BITS_PER_LONG == 32
* (i.e. I get to shift by #5-2 (32 bits per long, 4 bytes per access),
* mask by 0x0000001F)
*
* Typically, R10 is clobbered for address, R11 bit nr, and R12 is temp
*/
/**
* test_and_clear_bit - clear a bit and return its old value
* @nr: bit number to clear
* @addr: pointer to memory
*/
static inline int test_and_clear_bit(int nr, volatile void *addr)
{
int oldval;
__asm__ __volatile__ (
" {R10 = %1; R11 = asr(%2,#5); }\n"
" {R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
"1: R12 = memw_locked(R10);\n"
" { P0 = tstbit(R12,R11); R12 = clrbit(R12,R11); }\n"
" memw_locked(R10,P1) = R12;\n"
" {if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
: "=&r" (oldval)
: "r" (addr), "r" (nr)
: "r10", "r11", "r12", "p0", "p1", "memory"
);
return oldval;
}
/**
* test_and_set_bit - set a bit and return its old value
* @nr: bit number to set
* @addr: pointer to memory
*/
static inline int test_and_set_bit(int nr, volatile void *addr)
{
int oldval;
__asm__ __volatile__ (
" {R10 = %1; R11 = asr(%2,#5); }\n"
" {R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
"1: R12 = memw_locked(R10);\n"
" { P0 = tstbit(R12,R11); R12 = setbit(R12,R11); }\n"
" memw_locked(R10,P1) = R12;\n"
" {if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
: "=&r" (oldval)
: "r" (addr), "r" (nr)
: "r10", "r11", "r12", "p0", "p1", "memory"
);
return oldval;
}
/**
* test_and_change_bit - toggle a bit and return its old value
* @nr: bit number to set
* @addr: pointer to memory
*/
static inline int test_and_change_bit(int nr, volatile void *addr)
{
int oldval;
__asm__ __volatile__ (
" {R10 = %1; R11 = asr(%2,#5); }\n"
" {R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
"1: R12 = memw_locked(R10);\n"
" { P0 = tstbit(R12,R11); R12 = togglebit(R12,R11); }\n"
" memw_locked(R10,P1) = R12;\n"
" {if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
: "=&r" (oldval)
: "r" (addr), "r" (nr)
: "r10", "r11", "r12", "p0", "p1", "memory"
);
return oldval;
}
/*
* Atomic, but doesn't care about the return value.
* Rewrite later to save a cycle or two.
*/
static inline void clear_bit(int nr, volatile void *addr)
{
test_and_clear_bit(nr, addr);
}
static inline void set_bit(int nr, volatile void *addr)
{
test_and_set_bit(nr, addr);
}
static inline void change_bit(int nr, volatile void *addr)
{
test_and_change_bit(nr, addr);
}
/*
* These are allowed to be non-atomic. In fact the generic flavors are
* in non-atomic.h. Would it be better to use intrinsics for this?
*
* OK, writes in our architecture do not invalidate LL/SC, so this has to
* be atomic, particularly for things like slab_lock and slab_unlock.
*
*/
static inline void __clear_bit(int nr, volatile unsigned long *addr)
{
test_and_clear_bit(nr, addr);
}
static inline void __set_bit(int nr, volatile unsigned long *addr)
{
test_and_set_bit(nr, addr);
}
static inline void __change_bit(int nr, volatile unsigned long *addr)
{
test_and_change_bit(nr, addr);
}
/* Apparently, at least some of these are allowed to be non-atomic */
static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
{
return test_and_clear_bit(nr, addr);
}
static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
{
return test_and_set_bit(nr, addr);
}
static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
{
return test_and_change_bit(nr, addr);
}
static inline int __test_bit(int nr, const volatile unsigned long *addr)
{
int retval;
asm volatile(
"{P0 = tstbit(%1,%2); if (P0.new) %0 = #1; if (!P0.new) %0 = #0;}\n"
: "=&r" (retval)
: "r" (addr[BIT_WORD(nr)]), "r" (nr % BITS_PER_LONG)
: "p0"
);
return retval;
}
#define test_bit(nr, addr) __test_bit(nr, addr)
/*
* ffz - find first zero in word.
* @word: The word to search
*
* Undefined if no zero exists, so code should check against ~0UL first.
*/
static inline long ffz(int x)
{
int r;
asm("%0 = ct1(%1);\n"
: "=&r" (r)
: "r" (x));
return r;
}
/*
* fls - find last (most-significant) bit set
* @x: the word to search
*
* This is defined the same way as ffs.
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
static inline long fls(int x)
{
int r;
asm("{ %0 = cl0(%1);}\n"
"%0 = sub(#32,%0);\n"
: "=&r" (r)
: "r" (x)
: "p0");
return r;
}
/*
* ffs - find first bit set
* @x: the word to search
*
* This is defined the same way as
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs).
*/
static inline long ffs(int x)
{
int r;
asm("{ P0 = cmp.eq(%1,#0); %0 = ct0(%1);}\n"
"{ if P0 %0 = #0; if !P0 %0 = add(%0,#1);}\n"
: "=&r" (r)
: "r" (x)
: "p0");
return r;
}
/*
* __ffs - find first bit in word.
* @word: The word to search
*
* Undefined if no bit exists, so code should check against 0 first.
*
* bits_per_long assumed to be 32
* numbering starts at 0 I think (instead of 1 like ffs)
*/
static inline unsigned long __ffs(unsigned long word)
{
int num;
asm("%0 = ct0(%1);\n"
: "=&r" (num)
: "r" (word));
return num;
}
/*
* __fls - find last (most-significant) set bit in a long word
* @word: the word to search
*
* Undefined if no set bit exists, so code should check against 0 first.
* bits_per_long assumed to be 32
*/
static inline unsigned long __fls(unsigned long word)
{
int num;
asm("%0 = cl0(%1);\n"
"%0 = sub(#31,%0);\n"
: "=&r" (num)
: "r" (word));
return num;
}
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/le.h>
#include <asm-generic/bitops/ext2-atomic.h>
#endif /* __KERNEL__ */
#endif

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __ASM_HEXAGON_BITSPERLONG_H
#define __ASM_HEXAGON_BITSPERLONG_H
#define __BITS_PER_LONG 32
#include <asm-generic/bitsperlong.h>
#endif

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_BYTEORDER_H
#define _ASM_BYTEORDER_H
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
# define __BYTEORDER_HAS_U64__
#endif
#include <linux/byteorder/little_endian.h>
#endif /* _ASM_BYTEORDER_H */

View File

@ -0,0 +1,34 @@
/*
* Cache definitions for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __ASM_CACHE_H
#define __ASM_CACHE_H
/* Bytes per L1 cache line */
#define L1_CACHE_SHIFT (5)
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#define __cacheline_aligned __aligned(L1_CACHE_BYTES)
#define ____cacheline_aligned __aligned(L1_CACHE_BYTES)
/* See http://kerneltrap.org/node/15100 */
#define __read_mostly
#endif

View File

@ -0,0 +1,99 @@
/*
* Cache flush operations for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_CACHEFLUSH_H
#define _ASM_CACHEFLUSH_H
#include <linux/cache.h>
#include <linux/mm.h>
#include <asm/string.h>
#include <asm-generic/cacheflush.h>
/* Cache flushing:
*
* - flush_cache_all() flushes entire cache
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
* - flush_cache_page(mm, vmaddr, pfn) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
* - flush_icache_range(start, end) flush a range of instructions
* - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
* - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
*
* Need to doublecheck which one is really needed for ptrace stuff to work.
*/
#define LINESIZE 32
#define LINEBITS 5
/*
* Flush Dcache range through current map.
*/
extern void flush_dcache_range(unsigned long start, unsigned long end);
/*
* Flush Icache range through current map.
*/
#undef flush_icache_range
extern void flush_icache_range(unsigned long start, unsigned long end);
/*
* Memory-management related flushes are there to ensure in non-physically
* indexed cache schemes that stale lines belonging to a given ASID aren't
* in the cache to confuse things. The prototype Hexagon Virtual Machine
* only uses a single ASID for all user-mode maps, which should
* mean that they aren't necessary. A brute-force, flush-everything
* implementation, with the name xxxxx_hexagon() is present in
* arch/hexagon/mm/cache.c, but let's not wire it up until we know
* it is needed.
*/
extern void flush_cache_all_hexagon(void);
/*
* This may or may not ever have to be non-null, depending on the
* virtual machine MMU. For a native kernel, it's definitiely a no-op
*
* This is also the place where deferred cache coherency stuff seems
* to happen, classically... but instead we do it like ia64 and
* clean the cache when the PTE is set.
*
*/
static inline void update_mmu_cache(struct vm_area_struct *vma,
unsigned long address, pte_t *ptep)
{
/* generic_ptrace_pokedata doesn't wind up here, does it? */
}
#undef copy_to_user_page
static inline void copy_to_user_page(struct vm_area_struct *vma,
struct page *page,
unsigned long vaddr,
void *dst, void *src, int len)
{
memcpy(dst, src, len);
if (vma->vm_flags & VM_EXEC) {
flush_icache_range((unsigned long) dst,
(unsigned long) dst + len);
}
}
extern void hexagon_inv_dcache_range(unsigned long start, unsigned long end);
extern void hexagon_clean_dcache_range(unsigned long start, unsigned long end);
#endif

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_CHECKSUM_H
#define _ASM_CHECKSUM_H
#define do_csum do_csum
unsigned int do_csum(const void *voidptr, int len);
/*
* the same as csum_partial, but copies from src while it
* checksums
*
* here even more important to align src and dst on a 32-bit (or even
* better 64-bit) boundary
*/
#define csum_partial_copy_nocheck csum_partial_copy_nocheck
__wsum csum_partial_copy_nocheck(const void *src, void *dst,
int len, __wsum sum);
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
#define csum_tcpudp_nofold csum_tcpudp_nofold
__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
unsigned short len, unsigned short proto, __wsum sum);
#define csum_tcpudp_magic csum_tcpudp_magic
__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
unsigned short len, unsigned short proto, __wsum sum);
#include <asm-generic/checksum.h>
#endif

View File

@ -0,0 +1,90 @@
/*
* xchg/cmpxchg operations for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_CMPXCHG_H
#define _ASM_CMPXCHG_H
/*
* __xchg - atomically exchange a register and a memory location
* @x: value to swap
* @ptr: pointer to memory
* @size: size of the value
*
* Only 4 bytes supported currently.
*
* Note: there was an errata for V2 about .new's and memw_locked.
*
*/
static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
int size)
{
unsigned long retval;
/* Can't seem to use printk or panic here, so just stop */
if (size != 4) do { asm volatile("brkpt;\n"); } while (1);
__asm__ __volatile__ (
"1: %0 = memw_locked(%1);\n" /* load into retval */
" memw_locked(%1,P0) = %2;\n" /* store into memory */
" if !P0 jump 1b;\n"
: "=&r" (retval)
: "r" (ptr), "r" (x)
: "memory", "p0"
);
return retval;
}
/*
* Atomically swap the contents of a register with memory. Should be atomic
* between multiple CPU's and within interrupts on the same CPU.
*/
#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
sizeof(*(ptr))))
/*
* see rt-mutex-design.txt; cmpxchg supposedly checks if *ptr == A and swaps.
* looks just like atomic_cmpxchg on our arch currently with a bunch of
* variable casting.
*/
#define __HAVE_ARCH_CMPXCHG 1
#define cmpxchg(ptr, old, new) \
({ \
__typeof__(ptr) __ptr = (ptr); \
__typeof__(*(ptr)) __old = (old); \
__typeof__(*(ptr)) __new = (new); \
__typeof__(*(ptr)) __oldval = 0; \
\
asm volatile( \
"1: %0 = memw_locked(%1);\n" \
" { P0 = cmp.eq(%0,%2);\n" \
" if (!P0.new) jump:nt 2f; }\n" \
" memw_locked(%1,p0) = %3;\n" \
" if (!P0) jump 1b;\n" \
"2:\n" \
: "=&r" (__oldval) \
: "r" (__ptr), "r" (__old), "r" (__new) \
: "memory", "p0" \
); \
__oldval; \
})
#endif /* _ASM_CMPXCHG_H */

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_DELAY_H
#define _ASM_DELAY_H
#include <asm/param.h>
extern void __udelay(unsigned long usecs);
#define udelay(usecs) __udelay((usecs))
#endif /* _ASM_DELAY_H */

View File

@ -0,0 +1,107 @@
/*
* DMA operations for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_DMA_MAPPING_H
#define _ASM_DMA_MAPPING_H
#include <linux/types.h>
#include <linux/cache.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/dma-debug.h>
#include <linux/dma-attrs.h>
#include <asm/io.h>
struct device;
extern int bad_dma_address;
extern struct dma_map_ops *dma_ops;
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
static inline struct dma_map_ops *get_dma_ops(struct device *dev)
{
if (unlikely(dev == NULL))
return NULL;
return dma_ops;
}
extern int dma_supported(struct device *dev, u64 mask);
extern int dma_set_mask(struct device *dev, u64 mask);
extern int dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction);
#include <asm-generic/dma-mapping-common.h>
static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
{
if (!dev->dma_mask)
return 0;
return addr + size - 1 <= *dev->dma_mask;
}
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
struct dma_map_ops *dma_ops = get_dma_ops(dev);
if (dma_ops->mapping_error)
return dma_ops->mapping_error(dev, dma_addr);
return (dma_addr == bad_dma_address);
}
#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
static inline void *dma_alloc_attrs(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag,
struct dma_attrs *attrs)
{
void *ret;
struct dma_map_ops *ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
ret = ops->alloc(dev, size, dma_handle, flag, attrs);
debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
return ret;
}
#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
static inline void dma_free_attrs(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t dma_handle,
struct dma_attrs *attrs)
{
struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
dma_ops->free(dev, size, cpu_addr, dma_handle, attrs);
debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
}
#endif

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_DMA_H
#define _ASM_DMA_H
#include <asm/io.h>
#define MAX_DMA_CHANNELS 1
#define MAX_DMA_ADDRESS (PAGE_OFFSET)
extern size_t hexagon_coherent_pool_size;
#endif

View File

@ -0,0 +1,229 @@
/*
* ELF definitions for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __ASM_ELF_H
#define __ASM_ELF_H
#include <asm/ptrace.h>
#include <asm/user.h>
/*
* This should really be in linux/elf-em.h.
*/
#define EM_HEXAGON 164 /* QUALCOMM Hexagon */
struct elf32_hdr;
/*
* ELF header e_flags defines.
*/
/* should have stuff like "CPU type" and maybe "ABI version", etc */
/* Hexagon relocations */
/* V2 */
#define R_HEXAGON_NONE 0
#define R_HEXAGON_B22_PCREL 1
#define R_HEXAGON_B15_PCREL 2
#define R_HEXAGON_B7_PCREL 3
#define R_HEXAGON_LO16 4
#define R_HEXAGON_HI16 5
#define R_HEXAGON_32 6
#define R_HEXAGON_16 7
#define R_HEXAGON_8 8
#define R_HEXAGON_GPREL16_0 9
#define R_HEXAGON_GPREL16_1 10
#define R_HEXAGON_GPREL16_2 11
#define R_HEXAGON_GPREL16_3 12
#define R_HEXAGON_HL16 13
/* V3 */
#define R_HEXAGON_B13_PCREL 14
/* V4 */
#define R_HEXAGON_B9_PCREL 15
/* V4 (extenders) */
#define R_HEXAGON_B32_PCREL_X 16
#define R_HEXAGON_32_6_X 17
/* V4 (extended) */
#define R_HEXAGON_B22_PCREL_X 18
#define R_HEXAGON_B15_PCREL_X 19
#define R_HEXAGON_B13_PCREL_X 20
#define R_HEXAGON_B9_PCREL_X 21
#define R_HEXAGON_B7_PCREL_X 22
#define R_HEXAGON_16_X 23
#define R_HEXAGON_12_X 24
#define R_HEXAGON_11_X 25
#define R_HEXAGON_10_X 26
#define R_HEXAGON_9_X 27
#define R_HEXAGON_8_X 28
#define R_HEXAGON_7_X 29
#define R_HEXAGON_6_X 30
/* V2 PIC */
#define R_HEXAGON_32_PCREL 31
#define R_HEXAGON_COPY 32
#define R_HEXAGON_GLOB_DAT 33
#define R_HEXAGON_JMP_SLOT 34
#define R_HEXAGON_RELATIVE 35
#define R_HEXAGON_PLT_B22_PCREL 36
#define R_HEXAGON_GOTOFF_LO16 37
#define R_HEXAGON_GOTOFF_HI16 38
#define R_HEXAGON_GOTOFF_32 39
#define R_HEXAGON_GOT_LO16 40
#define R_HEXAGON_GOT_HI16 41
#define R_HEXAGON_GOT_32 42
#define R_HEXAGON_GOT_16 43
/*
* ELF register definitions..
*/
typedef unsigned long elf_greg_t;
typedef struct user_regs_struct elf_gregset_t;
#define ELF_NGREG (sizeof(elf_gregset_t)/sizeof(unsigned long))
/* Placeholder */
typedef unsigned long elf_fpregset_t;
/*
* Bypass the whole "regsets" thing for now and use the define.
*/
#define ELF_CORE_COPY_REGS(DEST, REGS) \
do { \
DEST.r0 = REGS->r00; \
DEST.r1 = REGS->r01; \
DEST.r2 = REGS->r02; \
DEST.r3 = REGS->r03; \
DEST.r4 = REGS->r04; \
DEST.r5 = REGS->r05; \
DEST.r6 = REGS->r06; \
DEST.r7 = REGS->r07; \
DEST.r8 = REGS->r08; \
DEST.r9 = REGS->r09; \
DEST.r10 = REGS->r10; \
DEST.r11 = REGS->r11; \
DEST.r12 = REGS->r12; \
DEST.r13 = REGS->r13; \
DEST.r14 = REGS->r14; \
DEST.r15 = REGS->r15; \
DEST.r16 = REGS->r16; \
DEST.r17 = REGS->r17; \
DEST.r18 = REGS->r18; \
DEST.r19 = REGS->r19; \
DEST.r20 = REGS->r20; \
DEST.r21 = REGS->r21; \
DEST.r22 = REGS->r22; \
DEST.r23 = REGS->r23; \
DEST.r24 = REGS->r24; \
DEST.r25 = REGS->r25; \
DEST.r26 = REGS->r26; \
DEST.r27 = REGS->r27; \
DEST.r28 = REGS->r28; \
DEST.r29 = pt_psp(REGS); \
DEST.r30 = REGS->r30; \
DEST.r31 = REGS->r31; \
DEST.sa0 = REGS->sa0; \
DEST.lc0 = REGS->lc0; \
DEST.sa1 = REGS->sa1; \
DEST.lc1 = REGS->lc1; \
DEST.m0 = REGS->m0; \
DEST.m1 = REGS->m1; \
DEST.usr = REGS->usr; \
DEST.p3_0 = REGS->preds; \
DEST.gp = REGS->gp; \
DEST.ugp = REGS->ugp; \
DEST.pc = pt_elr(REGS); \
DEST.cause = pt_cause(REGS); \
DEST.badva = pt_badva(REGS); \
} while (0);
/*
* This is used to ensure we don't load something for the wrong architecture.
* Checks the machine and ABI type.
*/
#define elf_check_arch(hdr) ((hdr)->e_machine == EM_HEXAGON)
/*
* These are used to set parameters in the core dumps.
*/
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_HEXAGON
#ifdef CONFIG_HEXAGON_ARCH_V2
#define ELF_CORE_EFLAGS 0x1
#endif
#ifdef CONFIG_HEXAGON_ARCH_V3
#define ELF_CORE_EFLAGS 0x2
#endif
#ifdef CONFIG_HEXAGON_ARCH_V4
#define ELF_CORE_EFLAGS 0x3
#endif
/*
* Some architectures have ld.so set up a pointer to a function
* to be registered using atexit, to facilitate cleanup. So that
* static executables will be well-behaved, we would null the register
* in question here, in the pt_regs structure passed. For now,
* leave it a null macro.
*/
#define ELF_PLAT_INIT(regs, load_addr) do { } while (0)
#define USE_ELF_CORE_DUMP
#define CORE_DUMP_USE_REGSET
/* Hrm is this going to cause problems for changing PAGE_SIZE? */
#define ELF_EXEC_PAGESIZE 4096
/*
* 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 0x08000000UL
/*
* 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)
#ifdef __KERNEL__
#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
#endif
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
struct linux_binprm;
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp);
#endif

View File

@ -0,0 +1,28 @@
/*
* Process execution related definitions for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_EXEC_H
#define _ASM_EXEC_H
/* Should probably shoot for an 8-byte aligned stack pointer */
#define STACK_MASK (~7)
#define arch_align_stack(x) (x & STACK_MASK)
#endif /* _ASM_EXEC_H */

View File

@ -0,0 +1,73 @@
/*
* Fixmap support for Hexagon - enough to support highmem features
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_FIXMAP_H
#define _ASM_FIXMAP_H
/*
* A lot of the fixmap info is already in mem-layout.h
*/
#include <asm/mem-layout.h>
/*
* Full fixmap support involves set_fixmap() functions, but
* these may not be needed if all we're after is an area for
* highmem kernel mappings.
*/
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
extern void __this_fixmap_does_not_exist(void);
/**
* fix_to_virt -- "index to address" translation.
*
* If anyone tries to use the idx directly without translation,
* we catch the bug with a NULL-deference kernel oops. Illegal
* ranges of incoming indices are caught too.
*/
static inline unsigned long fix_to_virt(const unsigned int idx)
{
/*
* This branch gets completely eliminated after inlining,
* except when someone tries to use fixaddr indices in an
* illegal way. (such as mixing up address types or using
* out-of-range indices).
*
* If it doesn't get removed, the linker will complain
* loudly with a reasonably clear error message..
*/
if (idx >= __end_of_fixed_addresses)
__this_fixmap_does_not_exist();
return __fix_to_virt(idx);
}
static inline unsigned long virt_to_fix(const unsigned long vaddr)
{
BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
return __virt_to_fix(vaddr);
}
#define kmap_get_fixmap_pte(vaddr) \
pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), \
(vaddr)), (vaddr)), (vaddr))
#endif

View File

@ -0,0 +1,4 @@
/*
* If the FPU is used inside the kernel,
* kernel_fpu_end() will be defined here.
*/

View File

@ -0,0 +1,137 @@
#ifndef _ASM_HEXAGON_FUTEX_H
#define _ASM_HEXAGON_FUTEX_H
#ifdef __KERNEL__
#include <linux/futex.h>
#include <linux/uaccess.h>
#include <asm/errno.h>
/* XXX TODO-- need to add sync barriers! */
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
__asm__ __volatile( \
"1: %0 = memw_locked(%3);\n" \
/* For example: %1 = %4 */ \
insn \
"2: memw_locked(%3,p2) = %1;\n" \
" if !p2 jump 1b;\n" \
" %1 = #0;\n" \
"3:\n" \
".section .fixup,\"ax\"\n" \
"4: %1 = #%5;\n" \
" jump 3b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
".long 1b,4b,2b,4b\n" \
".previous\n" \
: "=&r" (oldval), "=&r" (ret), "+m" (*uaddr) \
: "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
: "p2", "memory")
static inline int
futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
{
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
return -EFAULT;
pagefault_disable();
switch (op) {
case FUTEX_OP_SET:
__futex_atomic_op("%1 = %4\n", ret, oldval, uaddr, oparg);
break;
case FUTEX_OP_ADD:
__futex_atomic_op("%1 = add(%0,%4)\n", ret, oldval, uaddr,
oparg);
break;
case FUTEX_OP_OR:
__futex_atomic_op("%1 = or(%0,%4)\n", ret, oldval, uaddr,
oparg);
break;
case FUTEX_OP_ANDN:
__futex_atomic_op("%1 = not(%4); %1 = and(%0,%1)\n", ret,
oldval, uaddr, oparg);
break;
case FUTEX_OP_XOR:
__futex_atomic_op("%1 = xor(%0,%4)\n", ret, oldval, uaddr,
oparg);
break;
default:
ret = -ENOSYS;
}
pagefault_enable();
if (!ret) {
switch (cmp) {
case FUTEX_OP_CMP_EQ:
ret = (oldval == cmparg);
break;
case FUTEX_OP_CMP_NE:
ret = (oldval != cmparg);
break;
case FUTEX_OP_CMP_LT:
ret = (oldval < cmparg);
break;
case FUTEX_OP_CMP_GE:
ret = (oldval >= cmparg);
break;
case FUTEX_OP_CMP_LE:
ret = (oldval <= cmparg);
break;
case FUTEX_OP_CMP_GT:
ret = (oldval > cmparg);
break;
default:
ret = -ENOSYS;
}
}
return ret;
}
static inline int
futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval,
u32 newval)
{
int prev;
int ret;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
__asm__ __volatile__ (
"1: %1 = memw_locked(%3)\n"
" {\n"
" p2 = cmp.eq(%1,%4)\n"
" if !p2.new jump:NT 3f\n"
" }\n"
"2: memw_locked(%3,p2) = %5\n"
" if !p2 jump 1b\n"
"3:\n"
".section .fixup,\"ax\"\n"
"4: %0 = #%6\n"
" jump 3b\n"
".previous\n"
".section __ex_table,\"a\"\n"
".long 1b,4b,2b,4b\n"
".previous\n"
: "+r" (ret), "=&r" (prev), "+m" (*uaddr)
: "r" (uaddr), "r" (oldval), "r" (newval), "i"(-EFAULT)
: "p2", "memory");
*uval = prev;
return ret;
}
#endif /* __KERNEL__ */
#endif /* _ASM_HEXAGON_FUTEX_H */

View File

@ -0,0 +1,281 @@
/*
* Declarations for to Hexagon Virtal Machine.
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef ASM_HEXAGON_VM_H
#define ASM_HEXAGON_VM_H
/*
* In principle, a Linux kernel for the VM could
* selectively define the virtual instructions
* as inline assembler macros, but for a first pass,
* we'll use subroutines for both the VM and the native
* kernels. It's costing a subroutine call/return,
* but it makes for a single set of entry points
* for tracing/debugging.
*/
/*
* Lets make this stuff visible only if configured,
* so we can unconditionally include the file.
*/
#ifndef __ASSEMBLY__
enum VM_CACHE_OPS {
ickill,
dckill,
l2kill,
dccleaninva,
icinva,
idsync,
fetch_cfg
};
enum VM_INT_OPS {
nop,
globen,
globdis,
locen,
locdis,
affinity,
get,
peek,
status,
post,
clear
};
extern void _K_VM_event_vector(void);
void __vmrte(void);
long __vmsetvec(void *);
long __vmsetie(long);
long __vmgetie(void);
long __vmintop(enum VM_INT_OPS, long, long, long, long);
long __vmclrmap(void *, unsigned long);
long __vmnewmap(void *);
long __vmcache(enum VM_CACHE_OPS op, unsigned long addr, unsigned long len);
unsigned long long __vmgettime(void);
long __vmsettime(unsigned long long);
long __vmstart(void *, void *);
void __vmstop(void);
long __vmwait(void);
void __vmyield(void);
long __vmvpid(void);
static inline long __vmcache_ickill(void)
{
return __vmcache(ickill, 0, 0);
}
static inline long __vmcache_dckill(void)
{
return __vmcache(dckill, 0, 0);
}
static inline long __vmcache_l2kill(void)
{
return __vmcache(l2kill, 0, 0);
}
static inline long __vmcache_dccleaninva(unsigned long addr, unsigned long len)
{
return __vmcache(dccleaninva, addr, len);
}
static inline long __vmcache_icinva(unsigned long addr, unsigned long len)
{
return __vmcache(icinva, addr, len);
}
static inline long __vmcache_idsync(unsigned long addr,
unsigned long len)
{
return __vmcache(idsync, addr, len);
}
static inline long __vmcache_fetch_cfg(unsigned long val)
{
return __vmcache(fetch_cfg, val, 0);
}
/* interrupt operations */
static inline long __vmintop_nop(void)
{
return __vmintop(nop, 0, 0, 0, 0);
}
static inline long __vmintop_globen(long i)
{
return __vmintop(globen, i, 0, 0, 0);
}
static inline long __vmintop_globdis(long i)
{
return __vmintop(globdis, i, 0, 0, 0);
}
static inline long __vmintop_locen(long i)
{
return __vmintop(locen, i, 0, 0, 0);
}
static inline long __vmintop_locdis(long i)
{
return __vmintop(locdis, i, 0, 0, 0);
}
static inline long __vmintop_affinity(long i, long cpu)
{
return __vmintop(locdis, i, cpu, 0, 0);
}
static inline long __vmintop_get(void)
{
return __vmintop(get, 0, 0, 0, 0);
}
static inline long __vmintop_peek(void)
{
return __vmintop(peek, 0, 0, 0, 0);
}
static inline long __vmintop_status(long i)
{
return __vmintop(status, i, 0, 0, 0);
}
static inline long __vmintop_post(long i)
{
return __vmintop(post, i, 0, 0, 0);
}
static inline long __vmintop_clear(long i)
{
return __vmintop(clear, i, 0, 0, 0);
}
#else /* Only assembly code should reference these */
#define HVM_TRAP1_VMRTE 1
#define HVM_TRAP1_VMSETVEC 2
#define HVM_TRAP1_VMSETIE 3
#define HVM_TRAP1_VMGETIE 4
#define HVM_TRAP1_VMINTOP 5
#define HVM_TRAP1_VMCLRMAP 10
#define HVM_TRAP1_VMNEWMAP 11
#define HVM_TRAP1_FORMERLY_VMWIRE 12
#define HVM_TRAP1_VMCACHE 13
#define HVM_TRAP1_VMGETTIME 14
#define HVM_TRAP1_VMSETTIME 15
#define HVM_TRAP1_VMWAIT 16
#define HVM_TRAP1_VMYIELD 17
#define HVM_TRAP1_VMSTART 18
#define HVM_TRAP1_VMSTOP 19
#define HVM_TRAP1_VMVPID 20
#define HVM_TRAP1_VMSETREGS 21
#define HVM_TRAP1_VMGETREGS 22
#endif /* __ASSEMBLY__ */
/*
* Constants for virtual instruction parameters and return values
*/
/* vmsetie arguments */
#define VM_INT_DISABLE 0
#define VM_INT_ENABLE 1
/* vmsetimask arguments */
#define VM_INT_UNMASK 0
#define VM_INT_MASK 1
#define VM_NEWMAP_TYPE_LINEAR 0
#define VM_NEWMAP_TYPE_PGTABLES 1
/*
* Event Record definitions useful to both C and Assembler
*/
/* VMEST Layout */
#define HVM_VMEST_UM_SFT 31
#define HVM_VMEST_UM_MSK 1
#define HVM_VMEST_IE_SFT 30
#define HVM_VMEST_IE_MSK 1
#define HVM_VMEST_EVENTNUM_SFT 16
#define HVM_VMEST_EVENTNUM_MSK 0xff
#define HVM_VMEST_CAUSE_SFT 0
#define HVM_VMEST_CAUSE_MSK 0xffff
/*
* The initial program gets to find a system environment descriptor
* on its stack when it begins exection. The first word is a version
* code to indicate what is there. Zero means nothing more.
*/
#define HEXAGON_VM_SED_NULL 0
/*
* Event numbers for vector binding
*/
#define HVM_EV_RESET 0
#define HVM_EV_MACHCHECK 1
#define HVM_EV_GENEX 2
#define HVM_EV_TRAP 8
#define HVM_EV_INTR 15
/* These shoud be nuked as soon as we know the VM is up to spec v0.1.1 */
#define HVM_EV_INTR_0 16
#define HVM_MAX_INTR 240
/*
* Cause values for General Exception
*/
#define HVM_GE_C_BUS 0x01
#define HVM_GE_C_XPROT 0x11
#define HVM_GE_C_XUSER 0x14
#define HVM_GE_C_INVI 0x15
#define HVM_GE_C_PRIVI 0x1B
#define HVM_GE_C_XMAL 0x1C
#define HVM_GE_C_RMAL 0x20
#define HVM_GE_C_WMAL 0x21
#define HVM_GE_C_RPROT 0x22
#define HVM_GE_C_WPROT 0x23
#define HVM_GE_C_RUSER 0x24
#define HVM_GE_C_WUSER 0x25
#define HVM_GE_C_CACHE 0x28
/*
* Cause codes for Machine Check
*/
#define HVM_MCHK_C_DOWN 0x00
#define HVM_MCHK_C_BADSP 0x01
#define HVM_MCHK_C_BADEX 0x02
#define HVM_MCHK_C_BADPT 0x03
#define HVM_MCHK_C_REGWR 0x29
#endif

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_HEXAGON_INTRINSICS_H
#define _ASM_HEXAGON_INTRINSICS_H
#define HEXAGON_P_vrmpyhacc_PP __builtin_HEXAGON_M2_vrmac_s0
#define HEXAGON_P_vrmpyh_PP __builtin_HEXAGON_M2_vrmpy_s0
#define HEXAGON_R_cl0_R __builtin_HEXAGON_S2_cl0
#endif

View File

@ -0,0 +1,326 @@
/*
* IO definitions for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_IO_H
#define _ASM_IO_H
#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/vmalloc.h>
#include <asm/string.h>
#include <asm/mem-layout.h>
#include <asm/iomap.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
/*
* We don't have PCI yet.
* _IO_BASE is pointing at what should be unused virtual space.
*/
#define IO_SPACE_LIMIT 0xffff
#define _IO_BASE ((void __iomem *)0xfe000000)
extern int remap_area_pages(unsigned long start, unsigned long phys_addr,
unsigned long end, unsigned long flags);
extern void __iounmap(const volatile void __iomem *addr);
/* Defined in lib/io.c, needed for smc91x driver. */
extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen);
extern void __raw_readsl(const void __iomem *addr, void *data, int wordlen);
extern void __raw_writesl(void __iomem *addr, const void *data, int wordlen);
#define readsw(p, d, l) __raw_readsw(p, d, l)
#define writesw(p, d, l) __raw_writesw(p, d, l)
#define readsl(p, d, l) __raw_readsl(p, d, l)
#define writesl(p, d, l) __raw_writesl(p, d, l)
/*
* virt_to_phys - map virtual address to physical
* @address: address to map
*/
static inline unsigned long virt_to_phys(volatile void *address)
{
return __pa(address);
}
/*
* phys_to_virt - map physical address to virtual
* @address: address to map
*/
static inline void *phys_to_virt(unsigned long address)
{
return __va(address);
}
/*
* convert a physical pointer to a virtual kernel pointer for
* /dev/mem access.
*/
#define xlate_dev_kmem_ptr(p) __va(p)
#define xlate_dev_mem_ptr(p) __va(p)
/*
* IO port access primitives. Hexagon doesn't have special IO access
* instructions; all I/O is memory mapped.
*
* in/out are used for "ports", but we don't have "port instructions",
* so these are really just memory mapped too.
*/
/*
* readb - read byte from memory mapped device
* @addr: pointer to memory
*
* Operates on "I/O bus memory space"
*/
static inline u8 readb(const volatile void __iomem *addr)
{
u8 val;
asm volatile(
"%0 = memb(%1);"
: "=&r" (val)
: "r" (addr)
);
return val;
}
static inline u16 readw(const volatile void __iomem *addr)
{
u16 val;
asm volatile(
"%0 = memh(%1);"
: "=&r" (val)
: "r" (addr)
);
return val;
}
static inline u32 readl(const volatile void __iomem *addr)
{
u32 val;
asm volatile(
"%0 = memw(%1);"
: "=&r" (val)
: "r" (addr)
);
return val;
}
/*
* writeb - write a byte to a memory location
* @data: data to write to
* @addr: pointer to memory
*
*/
static inline void writeb(u8 data, volatile void __iomem *addr)
{
asm volatile(
"memb(%0) = %1;"
:
: "r" (addr), "r" (data)
: "memory"
);
}
static inline void writew(u16 data, volatile void __iomem *addr)
{
asm volatile(
"memh(%0) = %1;"
:
: "r" (addr), "r" (data)
: "memory"
);
}
static inline void writel(u32 data, volatile void __iomem *addr)
{
asm volatile(
"memw(%0) = %1;"
:
: "r" (addr), "r" (data)
: "memory"
);
}
#define __raw_writeb writeb
#define __raw_writew writew
#define __raw_writel writel
#define __raw_readb readb
#define __raw_readw readw
#define __raw_readl readl
/*
* Need an mtype somewhere in here, for cache type deals?
* This is probably too long for an inline.
*/
void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size);
static inline void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
{
return ioremap_nocache(phys_addr, size);
}
static inline void iounmap(volatile void __iomem *addr)
{
__iounmap(addr);
}
#define __raw_writel writel
static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
int count)
{
memcpy(dst, (void *) src, count);
}
static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
int count)
{
memcpy((void *) dst, src, count);
}
#define PCI_IO_ADDR (volatile void __iomem *)
/*
* inb - read byte from I/O port or something
* @port: address in I/O space
*
* Operates on "I/O bus I/O space"
*/
static inline u8 inb(unsigned long port)
{
return readb(_IO_BASE + (port & IO_SPACE_LIMIT));
}
static inline u16 inw(unsigned long port)
{
return readw(_IO_BASE + (port & IO_SPACE_LIMIT));
}
static inline u32 inl(unsigned long port)
{
return readl(_IO_BASE + (port & IO_SPACE_LIMIT));
}
/*
* outb - write a byte to a memory location
* @data: data to write to
* @addr: address in I/O space
*/
static inline void outb(u8 data, unsigned long port)
{
writeb(data, _IO_BASE + (port & IO_SPACE_LIMIT));
}
static inline void outw(u16 data, unsigned long port)
{
writew(data, _IO_BASE + (port & IO_SPACE_LIMIT));
}
static inline void outl(u32 data, unsigned long port)
{
writel(data, _IO_BASE + (port & IO_SPACE_LIMIT));
}
#define outb_p outb
#define outw_p outw
#define outl_p outl
#define inb_p inb
#define inw_p inw
#define inl_p inl
static inline void insb(unsigned long port, void *buffer, int count)
{
if (count) {
u8 *buf = buffer;
do {
u8 x = inb(port);
*buf++ = x;
} while (--count);
}
}
static inline void insw(unsigned long port, void *buffer, int count)
{
if (count) {
u16 *buf = buffer;
do {
u16 x = inw(port);
*buf++ = x;
} while (--count);
}
}
static inline void insl(unsigned long port, void *buffer, int count)
{
if (count) {
u32 *buf = buffer;
do {
u32 x = inw(port);
*buf++ = x;
} while (--count);
}
}
static inline void outsb(unsigned long port, const void *buffer, int count)
{
if (count) {
const u8 *buf = buffer;
do {
outb(*buf++, port);
} while (--count);
}
}
static inline void outsw(unsigned long port, const void *buffer, int count)
{
if (count) {
const u16 *buf = buffer;
do {
outw(*buf++, port);
} while (--count);
}
}
static inline void outsl(unsigned long port, const void *buffer, int count)
{
if (count) {
const u32 *buf = buffer;
do {
outl(*buf++, port);
} while (--count);
}
}
#define flush_write_buffers() do { } while (0)
#endif /* __KERNEL__ */
#endif

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_IRQ_H_
#define _ASM_IRQ_H_
/* Number of first-level interrupts associated with the CPU core. */
#define HEXAGON_CPUINTS 32
/*
* Must define NR_IRQS before including <asm-generic/irq.h>
* 64 == the two SIRC's, 176 == the two gpio's
*
* IRQ configuration is still in flux; defining this to a comfortably
* large number.
*/
#define NR_IRQS 512
#include <asm-generic/irq.h>
#endif

View File

@ -0,0 +1,62 @@
/*
* IRQ support for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_IRQFLAGS_H
#define _ASM_IRQFLAGS_H
#include <asm/hexagon_vm.h>
#include <linux/types.h>
static inline unsigned long arch_local_save_flags(void)
{
return __vmgetie();
}
static inline unsigned long arch_local_irq_save(void)
{
return __vmsetie(VM_INT_DISABLE);
}
static inline bool arch_irqs_disabled_flags(unsigned long flags)
{
return !flags;
}
static inline bool arch_irqs_disabled(void)
{
return !__vmgetie();
}
static inline void arch_local_irq_enable(void)
{
__vmsetie(VM_INT_ENABLE);
}
static inline void arch_local_irq_disable(void)
{
__vmsetie(VM_INT_DISABLE);
}
static inline void arch_local_irq_restore(unsigned long flags)
{
__vmsetie(flags);
}
#endif

View File

@ -0,0 +1,43 @@
/*
* arch/hexagon/include/asm/kgdb.h - Hexagon KGDB Support
*
* Copyright (c) 2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __HEXAGON_KGDB_H__
#define __HEXAGON_KGDB_H__
#define BREAK_INSTR_SIZE 4
#define CACHE_FLUSH_IS_SAFE 1
#define BUFMAX ((NUMREGBYTES * 2) + 512)
static inline void arch_kgdb_breakpoint(void)
{
asm("trap0(#0xDB)");
}
/* Registers:
* 32 gpr + sa0/1 + lc0/1 + m0/1 + gp + ugp + pred + pc = 42 total.
* vm regs = psp+elr+est+badva = 4
* syscall+restart = 2 more
* so 48 = 42 +4 + 2
*/
#define DBG_USER_REGS 42
#define DBG_MAX_REG_NUM (DBG_USER_REGS + 6)
#define NUMREGBYTES (DBG_MAX_REG_NUM*4)
#endif /* __HEXAGON_KGDB_H__ */

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __ASM_LINKAGE_H
#define __ASM_LINKAGE_H
#define __ALIGN .align 4
#define __ALIGN_STR ".align 4"
#endif

View File

@ -0,0 +1,112 @@
/*
* Memory layout definitions for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_HEXAGON_MEM_LAYOUT_H
#define _ASM_HEXAGON_MEM_LAYOUT_H
#include <linux/const.h>
/*
* Have to do this for ginormous numbers, else they get printed as
* negative numbers, which the linker no likey when you try to
* assign it to the location counter.
*/
#define PAGE_OFFSET _AC(0xc0000000, UL)
/*
* LOAD_ADDRESS is the physical/linear address of where in memory
* the kernel gets loaded. The 12 least significant bits must be zero (0)
* due to limitations on setting the EVB
*
*/
#ifndef LOAD_ADDRESS
#define LOAD_ADDRESS 0x00000000
#endif
#define TASK_SIZE (PAGE_OFFSET)
/* not sure how these are used yet */
#define STACK_TOP TASK_SIZE
#define STACK_TOP_MAX TASK_SIZE
#ifndef __ASSEMBLY__
enum fixed_addresses {
FIX_KMAP_BEGIN,
FIX_KMAP_END, /* check for per-cpuism */
__end_of_fixed_addresses
};
#define MIN_KERNEL_SEG 0x300 /* From 0xc0000000 */
extern int max_kernel_seg;
/*
* Start of vmalloc virtual address space for kernel;
* supposed to be based on the amount of physical memory available
*/
#define VMALLOC_START (PAGE_OFFSET + VMALLOC_OFFSET + \
(unsigned long)high_memory)
/* Gap between physical ram and vmalloc space for guard purposes. */
#define VMALLOC_OFFSET PAGE_SIZE
/*
* Create the space between VMALLOC_START and FIXADDR_TOP backwards
* from the ... "top".
*
* Permanent IO mappings will live at 0xfexx_xxxx
* Hypervisor occupies the last 16MB page at 0xffxxxxxx
*/
#define FIXADDR_TOP 0xfe000000
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
/*
* "permanent kernel mappings", defined as long-lasting mappings of
* high-memory page frames into the kernel address space.
*/
#define LAST_PKMAP PTRS_PER_PTE
#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
#define PKMAP_NR(virt) ((virt - PKMAP_BASE) >> PAGE_SHIFT)
#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
/*
* To the "left" of the fixed map space is the kmap space
*
* "Permanent Kernel Mappings"; fancy (or less fancy) PTE table
* that looks like it's actually walked.
* Need to check the alignment/shift usage; some archs use
* PMD_MASK on this value
*/
#define PKMAP_BASE (FIXADDR_START-PAGE_SIZE*LAST_PKMAP)
/*
* 2 pages of guard gap between where vmalloc area ends
* and pkmap_base begins.
*/
#define VMALLOC_END (PKMAP_BASE-PAGE_SIZE*2)
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_HEXAGON_MEM_LAYOUT_H */

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_MMU_H
#define _ASM_MMU_H
#include <asm/vdso.h>
/*
* Architecture-specific state for a mm_struct.
* For the Hexagon Virtual Machine, it can be a copy
* of the pointer to the page table base.
*/
struct mm_context {
unsigned long long generation;
unsigned long ptbase;
struct hexagon_vdso *vdso;
};
typedef struct mm_context mm_context_t;
#endif

View File

@ -0,0 +1,100 @@
/*
* MM context support for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_MMU_CONTEXT_H
#define _ASM_MMU_CONTEXT_H
#include <asm/setup.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/mem-layout.h>
static inline void destroy_context(struct mm_struct *mm)
{
}
/*
* VM port hides all TLB management, so "lazy TLB" isn't very
* meaningful. Even for ports to architectures with visble TLBs,
* this is almost invariably a null function.
*/
static inline void enter_lazy_tlb(struct mm_struct *mm,
struct task_struct *tsk)
{
}
/*
* Architecture-specific actions, if any, for memory map deactivation.
*/
static inline void deactivate_mm(struct task_struct *tsk,
struct mm_struct *mm)
{
}
/**
* init_new_context - initialize context related info for new mm_struct instance
* @tsk: pointer to a task struct
* @mm: pointer to a new mm struct
*/
static inline int init_new_context(struct task_struct *tsk,
struct mm_struct *mm)
{
/* mm->context is set up by pgd_alloc */
return 0;
}
/*
* Switch active mm context
*/
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
{
int l1;
/*
* For virtual machine, we have to update system map if it's been
* touched.
*/
if (next->context.generation < prev->context.generation) {
for (l1 = MIN_KERNEL_SEG; l1 <= max_kernel_seg; l1++)
next->pgd[l1] = init_mm.pgd[l1];
next->context.generation = prev->context.generation;
}
__vmnewmap((void *)next->context.ptbase);
}
/*
* Activate new memory map for task
*/
static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
{
unsigned long flags;
local_irq_save(flags);
switch_mm(prev, next, current_thread_info()->task);
local_irq_restore(flags);
}
/* Generic hooks for arch_dup_mmap and arch_exit_mmap */
#include <asm-generic/mm_hooks.h>
#endif

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_MODULE_H
#define _ASM_MODULE_H
#include <asm-generic/module.h>
#define MODULE_ARCH_VERMAGIC __stringify(PROCESSOR_MODEL_NAME) " "
#endif

View File

@ -0,0 +1,8 @@
/*
* Pull in the generic implementation for the mutex fastpath.
*
* TODO: implement optimized primitives instead, or leave the generic
* implementation in place, or pick the atomic_xchg() based generic
* implementation. (see asm-generic/mutex-xchg.h for details)
*/
#include <asm-generic/mutex-xchg.h>

View File

@ -0,0 +1,157 @@
/*
* Page management definitions for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_PAGE_H
#define _ASM_PAGE_H
#include <linux/const.h>
/* This is probably not the most graceful way to handle this. */
#ifdef CONFIG_PAGE_SIZE_4KB
#define PAGE_SHIFT 12
#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_4KB
#endif
#ifdef CONFIG_PAGE_SIZE_16KB
#define PAGE_SHIFT 14
#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_16KB
#endif
#ifdef CONFIG_PAGE_SIZE_64KB
#define PAGE_SHIFT 16
#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_64KB
#endif
#ifdef CONFIG_PAGE_SIZE_256KB
#define PAGE_SHIFT 18
#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_256KB
#endif
#ifdef CONFIG_PAGE_SIZE_1MB
#define PAGE_SHIFT 20
#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_1MB
#endif
/*
* These should be defined in hugetlb.h, but apparently not.
* "Huge" for us should be 4MB or 16MB, which are both represented
* in L1 PTE's. Right now, it's set up for 4MB.
*/
#ifdef CONFIG_HUGETLB_PAGE
#define HPAGE_SHIFT 22
#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE-1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
#define HVM_HUGEPAGE_SIZE 0x5
#endif
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
/*
* This is for PFN_DOWN, which mm.h needs. Seems the right place to pull it in.
*/
#include <linux/pfn.h>
/*
* We implement a two-level architecture-specific page table structure.
* Null intermediate page table level (pmd, pud) definitions will come from
* asm-generic/pagetable-nopmd.h and asm-generic/pagetable-nopud.h
*/
typedef struct { unsigned long pte; } pte_t;
typedef struct { unsigned long pgd; } pgd_t;
typedef struct { unsigned long pgprot; } pgprot_t;
typedef struct page *pgtable_t;
#define pte_val(x) ((x).pte)
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot)
#define __pte(x) ((pte_t) { (x) })
#define __pgd(x) ((pgd_t) { (x) })
#define __pgprot(x) ((pgprot_t) { (x) })
/*
* We need a __pa and a __va routine for kernel space.
* MIPS says they're only used during mem_init.
* also, check if we need a PHYS_OFFSET.
*/
#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
/* The "page frame" descriptor is defined in linux/mm.h */
struct page;
/* Returns page frame descriptor for virtual address. */
#define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(__pa(kaddr)))
/* Default vm area behavior is non-executable. */
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
/* Need to not use a define for linesize; may move this to another file. */
static inline void clear_page(void *page)
{
/* This can only be done on pages with L1 WB cache */
asm volatile(
" loop0(1f,%1);\n"
"1: { dczeroa(%0);\n"
" %0 = add(%0,#32); }:endloop0\n"
: "+r" (page)
: "r" (PAGE_SIZE/32)
: "lc0", "sa0", "memory"
);
}
#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
/*
* Under assumption that kernel always "sees" user map...
*/
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
/*
* page_to_phys - convert page to physical address
* @page - pointer to page entry in mem_map
*/
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
/*
* For port to Hexagon Virtual Machine, MAYBE we check for attempts
* to reference reserved HVM space, but in any case, the VM will be
* protected.
*/
#define kern_addr_valid(addr) (1)
#include <asm-generic/memory_model.h>
/* XXX Todo: implement assembly-optimized version of getorder. */
#include <asm-generic/getorder.h>
#endif /* ifdef __ASSEMBLY__ */
#endif /* ifdef __KERNEL__ */
#endif

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_PARAM_H
#define _ASM_PARAM_H
#define EXEC_PAGESIZE 16384
#include <asm-generic/param.h>
#endif

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_PERF_EVENT_H
#define _ASM_PERF_EVENT_H
#endif /* _ASM_PERF_EVENT_H */

View File

@ -0,0 +1,146 @@
/*
* Page table support for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_PGALLOC_H
#define _ASM_PGALLOC_H
#include <asm/mem-layout.h>
#include <asm/atomic.h>
#define check_pgt_cache() do {} while (0)
extern unsigned long long kmap_generation;
/*
* Page table creation interface
*/
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
pgd_t *pgd;
pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
/*
* There may be better ways to do this, but to ensure
* that new address spaces always contain the kernel
* base mapping, and to ensure that the user area is
* initially marked invalid, initialize the new map
* map with a copy of the kernel's persistent map.
*/
memcpy(pgd, swapper_pg_dir, PTRS_PER_PGD*sizeof(pgd_t *));
mm->context.generation = kmap_generation;
/* Physical version is what is passed to virtual machine on switch */
mm->context.ptbase = __pa(pgd);
return pgd;
}
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
free_page((unsigned long) pgd);
}
static inline struct page *pte_alloc_one(struct mm_struct *mm,
unsigned long address)
{
struct page *pte;
pte = alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
if (pte)
pgtable_page_ctor(pte);
return pte;
}
/* _kernel variant gets to use a different allocator */
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
unsigned long address)
{
gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
return (pte_t *) __get_free_page(flags);
}
static inline void pte_free(struct mm_struct *mm, struct page *pte)
{
pgtable_page_dtor(pte);
__free_page(pte);
}
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
free_page((unsigned long)pte);
}
static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
pgtable_t pte)
{
/*
* Conveniently, zero in 3 LSB means indirect 4K page table.
* Not so convenient when you're trying to vary the page size.
*/
set_pmd(pmd, __pmd(((unsigned long)page_to_pfn(pte) << PAGE_SHIFT) |
HEXAGON_L1_PTE_SIZE));
}
/*
* Other architectures seem to have ways of making all processes
* share the same pmd's for their kernel mappings, but the v0.3
* Hexagon VM spec has a "monolithic" L1 table for user and kernel
* segments. We track "generations" of the kernel map to minimize
* overhead, and update the "slave" copies of the kernel mappings
* as part of switch_mm. However, we still need to update the
* kernel map of the active thread who's calling pmd_populate_kernel...
*/
static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
pte_t *pte)
{
extern spinlock_t kmap_gen_lock;
pmd_t *ppmd;
int pmdindex;
spin_lock(&kmap_gen_lock);
kmap_generation++;
mm->context.generation = kmap_generation;
current->active_mm->context.generation = kmap_generation;
spin_unlock(&kmap_gen_lock);
set_pmd(pmd, __pmd(((unsigned long)__pa(pte)) | HEXAGON_L1_PTE_SIZE));
/*
* Now the "slave" copy of the current thread.
* This is pointer arithmetic, not byte addresses!
*/
pmdindex = (pgd_t *)pmd - mm->pgd;
ppmd = (pmd_t *)current->active_mm->pgd + pmdindex;
set_pmd(ppmd, __pmd(((unsigned long)__pa(pte)) | HEXAGON_L1_PTE_SIZE));
if (pmdindex > max_kernel_seg)
max_kernel_seg = pmdindex;
}
#define __pte_free_tlb(tlb, pte, addr) \
do { \
pgtable_page_dtor((pte)); \
tlb_remove_page((tlb), (pte)); \
} while (0)
#endif

View File

@ -0,0 +1,518 @@
/*
* Page table support for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_PGTABLE_H
#define _ASM_PGTABLE_H
/*
* Page table definitions for Qualcomm Hexagon processor.
*/
#include <linux/swap.h>
#include <asm/page.h>
#include <asm-generic/pgtable-nopmd.h>
/* A handy thing to have if one has the RAM. Declared in head.S */
extern unsigned long empty_zero_page;
extern unsigned long zero_page_mask;
/*
* The PTE model described here is that of the Hexagon Virtual Machine,
* which autonomously walks 2-level page tables. At a lower level, we
* also describe the RISCish software-loaded TLB entry structure of
* the underlying Hexagon processor. A kernel built to run on the
* virtual machine has no need to know about the underlying hardware.
*/
#include <asm/vm_mmu.h>
/*
* To maximize the comfort level for the PTE manipulation macros,
* define the "well known" architecture-specific bits.
*/
#define _PAGE_READ __HVM_PTE_R
#define _PAGE_WRITE __HVM_PTE_W
#define _PAGE_EXECUTE __HVM_PTE_X
#define _PAGE_USER __HVM_PTE_U
/*
* We have a total of 4 "soft" bits available in the abstract PTE.
* The two mandatory software bits are Dirty and Accessed.
* To make nonlinear swap work according to the more recent
* model, we want a low order "Present" bit to indicate whether
* the PTE describes MMU programming or swap space.
*/
#define _PAGE_PRESENT (1<<0)
#define _PAGE_DIRTY (1<<1)
#define _PAGE_ACCESSED (1<<2)
/*
* _PAGE_FILE is only meaningful if _PAGE_PRESENT is false, while
* _PAGE_DIRTY is only meaningful if _PAGE_PRESENT is true.
* So we can overload the bit...
*/
#define _PAGE_FILE _PAGE_DIRTY /* set: pagecache, unset = swap */
/*
* For now, let's say that Valid and Present are the same thing.
* Alternatively, we could say that it's the "or" of R, W, and X
* permissions.
*/
#define _PAGE_VALID _PAGE_PRESENT
/*
* We're not defining _PAGE_GLOBAL here, since there's no concept
* of global pages or ASIDs exposed to the Hexagon Virtual Machine,
* and we want to use the same page table structures and macros in
* the native kernel as we do in the virtual machine kernel.
* So we'll put up with a bit of inefficiency for now...
*/
/*
* Top "FOURTH" level (pgd), which for the Hexagon VM is really
* only the second from the bottom, pgd and pud both being collapsed.
* Each entry represents 4MB of virtual address space, 4K of table
* thus maps the full 4GB.
*/
#define PGDIR_SHIFT 22
#define PTRS_PER_PGD 1024
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
#ifdef CONFIG_PAGE_SIZE_4KB
#define PTRS_PER_PTE 1024
#endif
#ifdef CONFIG_PAGE_SIZE_16KB
#define PTRS_PER_PTE 256
#endif
#ifdef CONFIG_PAGE_SIZE_64KB
#define PTRS_PER_PTE 64
#endif
#ifdef CONFIG_PAGE_SIZE_256KB
#define PTRS_PER_PTE 16
#endif
#ifdef CONFIG_PAGE_SIZE_1MB
#define PTRS_PER_PTE 4
#endif
/* Any bigger and the PTE disappears. */
#define pgd_ERROR(e) \
printk(KERN_ERR "%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__,\
pgd_val(e))
/*
* Page Protection Constants. Includes (in this variant) cache attributes.
*/
extern unsigned long _dflt_cache_att;
#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_USER | \
_dflt_cache_att)
#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | \
_PAGE_READ | _PAGE_EXECUTE | _dflt_cache_att)
#define PAGE_COPY PAGE_READONLY
#define PAGE_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \
_PAGE_READ | _PAGE_EXECUTE | _dflt_cache_att)
#define PAGE_COPY_EXEC PAGE_EXEC
#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
_PAGE_EXECUTE | _PAGE_WRITE | _dflt_cache_att)
#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_READ | \
_PAGE_WRITE | _PAGE_EXECUTE | _dflt_cache_att)
/*
* Aliases for mapping mmap() protection bits to page protections.
* These get used for static initialization, so using the _dflt_cache_att
* variable for the default cache attribute isn't workable. If the
* default gets changed at boot time, the boot option code has to
* update data structures like the protaction_map[] array.
*/
#define CACHEDEF (CACHE_DEFAULT << 6)
/* Private (copy-on-write) page protections. */
#define __P000 __pgprot(_PAGE_PRESENT | _PAGE_USER | CACHEDEF)
#define __P001 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | CACHEDEF)
#define __P010 __P000 /* Write-only copy-on-write */
#define __P011 __P001 /* Read/Write copy-on-write */
#define __P100 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
_PAGE_EXECUTE | CACHEDEF)
#define __P101 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_EXECUTE | \
_PAGE_READ | CACHEDEF)
#define __P110 __P100 /* Write/execute copy-on-write */
#define __P111 __P101 /* Read/Write/Execute, copy-on-write */
/* Shared page protections. */
#define __S000 __P000
#define __S001 __P001
#define __S010 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
_PAGE_WRITE | CACHEDEF)
#define __S011 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
_PAGE_WRITE | CACHEDEF)
#define __S100 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
_PAGE_EXECUTE | CACHEDEF)
#define __S101 __P101
#define __S110 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
_PAGE_EXECUTE | _PAGE_WRITE | CACHEDEF)
#define __S111 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
_PAGE_EXECUTE | _PAGE_WRITE | CACHEDEF)
extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* located in head.S */
/* Seems to be zero even in architectures where the zero page is firewalled? */
#define FIRST_USER_ADDRESS 0
#define pte_special(pte) 0
#define pte_mkspecial(pte) (pte)
/* HUGETLB not working currently */
#ifdef CONFIG_HUGETLB_PAGE
#define pte_mkhuge(pte) __pte((pte_val(pte) & ~0x3) | HVM_HUGEPAGE_SIZE)
#endif
/*
* For now, assume that higher-level code will do TLB/MMU invalidations
* and don't insert that overhead into this low-level function.
*/
extern void sync_icache_dcache(pte_t pte);
#define pte_present_exec_user(pte) \
((pte_val(pte) & (_PAGE_EXECUTE | _PAGE_USER)) == \
(_PAGE_EXECUTE | _PAGE_USER))
static inline void set_pte(pte_t *ptep, pte_t pteval)
{
/* should really be using pte_exec, if it weren't declared later. */
if (pte_present_exec_user(pteval))
sync_icache_dcache(pteval);
*ptep = pteval;
}
/*
* For the Hexagon Virtual Machine MMU (or its emulation), a null/invalid
* L1 PTE (PMD/PGD) has 7 in the least significant bits. For the L2 PTE
* (Linux PTE), the key is to have bits 11..9 all zero. We'd use 0x7
* as a universal null entry, but some of those least significant bits
* are interpreted by software.
*/
#define _NULL_PMD 0x7
#define _NULL_PTE 0x0
static inline void pmd_clear(pmd_t *pmd_entry_ptr)
{
pmd_val(*pmd_entry_ptr) = _NULL_PMD;
}
/*
* Conveniently, a null PTE value is invalid.
*/
static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
{
pte_val(*ptep) = _NULL_PTE;
}
#ifdef NEED_PMD_INDEX_DESPITE_BEING_2_LEVEL
/**
* pmd_index - returns the index of the entry in the PMD page
* which would control the given virtual address
*/
#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
#endif
/**
* pgd_index - returns the index of the entry in the PGD page
* which would control the given virtual address
*
* This returns the *index* for the address in the pgd_t
*/
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
/*
* pgd_offset - find an offset in a page-table-directory
*/
#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
/*
* pgd_offset_k - get kernel (init_mm) pgd entry pointer for addr
*/
#define pgd_offset_k(address) pgd_offset(&init_mm, address)
/**
* pmd_none - check if pmd_entry is mapped
* @pmd_entry: pmd entry
*
* MIPS checks it against that "invalid pte table" thing.
*/
static inline int pmd_none(pmd_t pmd)
{
return pmd_val(pmd) == _NULL_PMD;
}
/**
* pmd_present - is there a page table behind this?
* Essentially the inverse of pmd_none. We maybe
* save an inline instruction by defining it this
* way, instead of simply "!pmd_none".
*/
static inline int pmd_present(pmd_t pmd)
{
return pmd_val(pmd) != (unsigned long)_NULL_PMD;
}
/**
* pmd_bad - check if a PMD entry is "bad". That might mean swapped out.
* As we have no known cause of badness, it's null, as it is for many
* architectures.
*/
static inline int pmd_bad(pmd_t pmd)
{
return 0;
}
/*
* pmd_page - converts a PMD entry to a page pointer
*/
#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
#define pmd_pgtable(pmd) pmd_page(pmd)
/**
* pte_none - check if pte is mapped
* @pte: pte_t entry
*/
static inline int pte_none(pte_t pte)
{
return pte_val(pte) == _NULL_PTE;
};
/*
* pte_present - check if page is present
*/
static inline int pte_present(pte_t pte)
{
return pte_val(pte) & _PAGE_PRESENT;
}
/* mk_pte - make a PTE out of a page pointer and protection bits */
#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
/* pte_page - returns a page (frame pointer/descriptor?) based on a PTE */
#define pte_page(x) pfn_to_page(pte_pfn(x))
/* pte_mkold - mark PTE as not recently accessed */
static inline pte_t pte_mkold(pte_t pte)
{
pte_val(pte) &= ~_PAGE_ACCESSED;
return pte;
}
/* pte_mkyoung - mark PTE as recently accessed */
static inline pte_t pte_mkyoung(pte_t pte)
{
pte_val(pte) |= _PAGE_ACCESSED;
return pte;
}
/* pte_mkclean - mark page as in sync with backing store */
static inline pte_t pte_mkclean(pte_t pte)
{
pte_val(pte) &= ~_PAGE_DIRTY;
return pte;
}
/* pte_mkdirty - mark page as modified */
static inline pte_t pte_mkdirty(pte_t pte)
{
pte_val(pte) |= _PAGE_DIRTY;
return pte;
}
/* pte_young - "is PTE marked as accessed"? */
static inline int pte_young(pte_t pte)
{
return pte_val(pte) & _PAGE_ACCESSED;
}
/* pte_dirty - "is PTE dirty?" */
static inline int pte_dirty(pte_t pte)
{
return pte_val(pte) & _PAGE_DIRTY;
}
/* pte_modify - set protection bits on PTE */
static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
{
pte_val(pte) &= PAGE_MASK;
pte_val(pte) |= pgprot_val(prot);
return pte;
}
/* pte_wrprotect - mark page as not writable */
static inline pte_t pte_wrprotect(pte_t pte)
{
pte_val(pte) &= ~_PAGE_WRITE;
return pte;
}
/* pte_mkwrite - mark page as writable */
static inline pte_t pte_mkwrite(pte_t pte)
{
pte_val(pte) |= _PAGE_WRITE;
return pte;
}
/* pte_mkexec - mark PTE as executable */
static inline pte_t pte_mkexec(pte_t pte)
{
pte_val(pte) |= _PAGE_EXECUTE;
return pte;
}
/* pte_read - "is PTE marked as readable?" */
static inline int pte_read(pte_t pte)
{
return pte_val(pte) & _PAGE_READ;
}
/* pte_write - "is PTE marked as writable?" */
static inline int pte_write(pte_t pte)
{
return pte_val(pte) & _PAGE_WRITE;
}
/* pte_exec - "is PTE marked as executable?" */
static inline int pte_exec(pte_t pte)
{
return pte_val(pte) & _PAGE_EXECUTE;
}
/* __pte_to_swp_entry - extract swap entry from PTE */
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
/* __swp_entry_to_pte - extract PTE from swap entry */
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
/* pfn_pte - convert page number and protection value to page table entry */
#define pfn_pte(pfn, pgprot) __pte((pfn << PAGE_SHIFT) | pgprot_val(pgprot))
/* pte_pfn - convert pte to page frame number */
#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
/*
* set_pte_at - update page table and do whatever magic may be
* necessary to make the underlying hardware/firmware take note.
*
* VM may require a virtual instruction to alert the MMU.
*/
#define set_pte_at(mm, addr, ptep, pte) set_pte(ptep, pte)
/*
* May need to invoke the virtual machine as well...
*/
#define pte_unmap(pte) do { } while (0)
#define pte_unmap_nested(pte) do { } while (0)
/*
* pte_offset_map - returns the linear address of the page table entry
* corresponding to an address
*/
#define pte_offset_map(dir, address) \
((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
#define pte_offset_map_nested(pmd, addr) pte_offset_map(pmd, addr)
/* pte_offset_kernel - kernel version of pte_offset */
#define pte_offset_kernel(dir, address) \
((pte_t *) (unsigned long) __va(pmd_val(*dir) & PAGE_MASK) \
+ __pte_offset(address))
/* ZERO_PAGE - returns the globally shared zero page */
#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
/* Nothing special about IO remapping at this point */
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
/* I think this is in case we have page table caches; needed by init/main.c */
#define pgtable_cache_init() do { } while (0)
/*
* Swap/file PTE definitions. If _PAGE_PRESENT is zero, the rest of the
* PTE is interpreted as swap information. Depending on the _PAGE_FILE
* bit, the remaining free bits are eitehr interpreted as a file offset
* or a swap type/offset tuple. Rather than have the TLB fill handler
* test _PAGE_PRESENT, we're going to reserve the permissions bits
* and set them to all zeros for swap entries, which speeds up the
* miss handler at the cost of 3 bits of offset. That trade-off can
* be revisited if necessary, but Hexagon processor architecture and
* target applications suggest a lot of TLB misses and not much swap space.
*
* Format of swap PTE:
* bit 0: Present (zero)
* bit 1: _PAGE_FILE (zero)
* bits 2-6: swap type (arch independent layer uses 5 bits max)
* bits 7-9: bits 2:0 of offset
* bits 10-12: effectively _PAGE_PROTNONE (all zero)
* bits 13-31: bits 21:3 of swap offset
*
* Format of file PTE:
* bit 0: Present (zero)
* bit 1: _PAGE_FILE (zero)
* bits 2-9: bits 7:0 of offset
* bits 10-12: effectively _PAGE_PROTNONE (all zero)
* bits 13-31: bits 26:8 of swap offset
*
* The split offset makes some of the following macros a little gnarly,
* but there's plenty of precedent for this sort of thing.
*/
#define PTE_FILE_MAX_BITS 27
/* Used for swap PTEs */
#define __swp_type(swp_pte) (((swp_pte).val >> 2) & 0x1f)
#define __swp_offset(swp_pte) \
((((swp_pte).val >> 7) & 0x7) | (((swp_pte).val >> 10) & 0x003ffff8))
#define __swp_entry(type, offset) \
((swp_entry_t) { \
((type << 2) | \
((offset & 0x3ffff8) << 10) | ((offset & 0x7) << 7)) })
/* Used for file PTEs */
#define pte_file(pte) \
((pte_val(pte) & (_PAGE_FILE | _PAGE_PRESENT)) == _PAGE_FILE)
#define pte_to_pgoff(pte) \
(((pte_val(pte) >> 2) & 0xff) | ((pte_val(pte) >> 5) & 0x07ffff00))
#define pgoff_to_pte(off) \
((pte_t) { ((((off) & 0x7ffff00) << 5) | (((off) & 0xff) << 2)\
| _PAGE_FILE) })
/* Oh boy. There are a lot of possible arch overrides found in this file. */
#include <asm-generic/pgtable.h>
#endif

View File

@ -0,0 +1,123 @@
/*
* Process/processor support for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_PROCESSOR_H
#define _ASM_PROCESSOR_H
#ifndef __ASSEMBLY__
#include <asm/mem-layout.h>
#include <asm/registers.h>
#include <asm/hexagon_vm.h>
/* must be a macro */
#define current_text_addr() ({ __label__ _l; _l: &&_l; })
/* task_struct, defined elsewhere, is the "process descriptor" */
struct task_struct;
/* this is defined in arch/process.c */
extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
extern unsigned long thread_saved_pc(struct task_struct *tsk);
extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
/*
* thread_struct is supposed to be for context switch data.
* Specifically, to hold the state necessary to perform switch_to...
*/
struct thread_struct {
void *switch_sp;
};
/*
* initializes thread_struct
* The only thing we have in there is switch_sp
* which doesn't really need to be initialized.
*/
#define INIT_THREAD { \
}
#define cpu_relax() __vmyield()
/*
* "Unlazying all lazy status" occurs here.
*/
static inline void prepare_to_copy(struct task_struct *tsk)
{
}
/*
* Decides where the kernel will search for a free chunk of vm space during
* mmaps.
* See also arch_get_unmapped_area.
* Doesn't affect if you have MAX_FIXED in the page flags set though...
*
* Apparently the convention is that ld.so will ask for "unmapped" private
* memory to be allocated SOMEWHERE, but it also asks for memory explicitly
* via MAP_FIXED at the lower * addresses starting at VA=0x0.
*
* If the two requests collide, you get authentic segfaulting action, so
* you have to kick the "unmapped" base requests higher up.
*/
#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE/3))
#define task_pt_regs(task) \
((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1)
#define KSTK_EIP(tsk) (pt_elr(task_pt_regs(tsk)))
#define KSTK_ESP(tsk) (pt_psp(task_pt_regs(tsk)))
/* Free all resources held by a thread; defined in process.c */
extern void release_thread(struct task_struct *dead_task);
/* Get wait channel for task P. */
extern unsigned long get_wchan(struct task_struct *p);
/* The following stuff is pretty HEXAGON specific. */
/* This is really just here for __switch_to.
Offsets are pulled via asm-offsets.c */
/*
* No real reason why VM and native switch stacks should be different.
* Ultimately this should merge. Note that Rev C. ABI called out only
* R24-27 as callee saved GPRs needing explicit attention (R29-31 being
* dealt with automagically by allocframe), but the current ABI has
* more, R16-R27. By saving more, the worst case is that we waste some
* cycles if building with the old compilers.
*/
struct hexagon_switch_stack {
unsigned long long r1716;
unsigned long long r1918;
unsigned long long r2120;
unsigned long long r2322;
unsigned long long r2524;
unsigned long long r2726;
unsigned long fp;
unsigned long lr;
};
#endif /* !__ASSEMBLY__ */
#endif

View File

@ -0,0 +1,35 @@
/*
* Ptrace definitions for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_PTRACE_H
#define _ASM_PTRACE_H
#include <asm/registers.h>
#define instruction_pointer(regs) pt_elr(regs)
#define user_stack_pointer(regs) ((regs)->r29)
#define profile_pc(regs) instruction_pointer(regs)
/* kprobe-based event tracer support */
extern int regs_query_register_offset(const char *name);
extern const char *regs_query_register_name(unsigned int offset);
#endif

View File

@ -0,0 +1,236 @@
/*
* Register definitions for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_REGISTERS_H
#define _ASM_REGISTERS_H
#define SP r29
#ifndef __ASSEMBLY__
/* See kernel/entry.S for further documentation. */
/*
* Entry code copies the event record out of guest registers into
* this structure (which is on the stack).
*/
struct hvm_event_record {
unsigned long vmel; /* Event Linkage (return address) */
unsigned long vmest; /* Event context - pre-event SSR values */
unsigned long vmpsp; /* Previous stack pointer */
unsigned long vmbadva; /* Bad virtual address for addressing events */
};
struct pt_regs {
long restart_r0; /* R0 checkpoint for syscall restart */
long syscall_nr; /* Only used in system calls */
union {
struct {
unsigned long usr;
unsigned long preds;
};
long long int predsusr;
};
union {
struct {
unsigned long m0;
unsigned long m1;
};
long long int m1m0;
};
union {
struct {
unsigned long sa1;
unsigned long lc1;
};
long long int lc1sa1;
};
union {
struct {
unsigned long sa0;
unsigned long lc0;
};
long long int lc0sa0;
};
union {
struct {
unsigned long gp;
unsigned long ugp;
};
long long int ugpgp;
};
/*
* Be extremely careful with rearranging these, if at all. Some code
* assumes the 32 registers exist exactly like this in memory;
* e.g. kernel/ptrace.c
* e.g. kernel/signal.c (restore_sigcontext)
*/
union {
struct {
unsigned long r00;
unsigned long r01;
};
long long int r0100;
};
union {
struct {
unsigned long r02;
unsigned long r03;
};
long long int r0302;
};
union {
struct {
unsigned long r04;
unsigned long r05;
};
long long int r0504;
};
union {
struct {
unsigned long r06;
unsigned long r07;
};
long long int r0706;
};
union {
struct {
unsigned long r08;
unsigned long r09;
};
long long int r0908;
};
union {
struct {
unsigned long r10;
unsigned long r11;
};
long long int r1110;
};
union {
struct {
unsigned long r12;
unsigned long r13;
};
long long int r1312;
};
union {
struct {
unsigned long r14;
unsigned long r15;
};
long long int r1514;
};
union {
struct {
unsigned long r16;
unsigned long r17;
};
long long int r1716;
};
union {
struct {
unsigned long r18;
unsigned long r19;
};
long long int r1918;
};
union {
struct {
unsigned long r20;
unsigned long r21;
};
long long int r2120;
};
union {
struct {
unsigned long r22;
unsigned long r23;
};
long long int r2322;
};
union {
struct {
unsigned long r24;
unsigned long r25;
};
long long int r2524;
};
union {
struct {
unsigned long r26;
unsigned long r27;
};
long long int r2726;
};
union {
struct {
unsigned long r28;
unsigned long r29;
};
long long int r2928;
};
union {
struct {
unsigned long r30;
unsigned long r31;
};
long long int r3130;
};
/* VM dispatch pushes event record onto stack - we can build on it */
struct hvm_event_record hvmer;
};
/* Defines to conveniently access the values */
/*
* As of the VM spec 0.5, these registers are now set/retrieved via a
* VM call. On the in-bound side, we just fetch the values
* at the entry points and stuff them into the old record in pt_regs.
* However, on the outbound side, probably at VM rte, we set the
* registers back.
*/
#define pt_elr(regs) ((regs)->hvmer.vmel)
#define pt_set_elr(regs, val) ((regs)->hvmer.vmel = (val))
#define pt_cause(regs) ((regs)->hvmer.vmest & (HVM_VMEST_CAUSE_MSK))
#define user_mode(regs) \
(((regs)->hvmer.vmest & (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT)) != 0)
#define ints_enabled(regs) \
(((regs)->hvmer.vmest & (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)) != 0)
#define pt_psp(regs) ((regs)->hvmer.vmpsp)
#define pt_badva(regs) ((regs)->hvmer.vmbadva)
#define pt_set_rte_sp(regs, sp) do {\
pt_psp(regs) = (sp);\
(regs)->SP = (unsigned long) &((regs)->hvmer);\
} while (0)
#define pt_set_kmode(regs) \
(regs)->hvmer.vmest = (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
#define pt_set_usermode(regs) \
(regs)->hvmer.vmest = (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT) \
| (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
#endif /* ifndef __ASSEMBLY */
#endif

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_SETUP_H
#define _ASM_SETUP_H
#include <linux/init.h>
#include <asm-generic/setup.h>
extern char external_cmdline_buffer;
void __init setup_arch_memory(void);
#endif

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_SIGCONTEXT_H
#define _ASM_SIGCONTEXT_H
#include <asm/user.h>
/*
* Signal context structure - contains all info to do with the state
* before the signal handler was invoked. Note: only add new entries
* to the end of the structure.
*/
struct sigcontext {
struct user_regs_struct sc_regs;
} __aligned(8);
#endif

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_SIGNAL_H
#define _ASM_SIGNAL_H
extern unsigned long __rt_sigtramp_template[2];
#include <asm-generic/signal.h>
#endif

View File

@ -0,0 +1,44 @@
/*
* SMP definitions for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __ASM_SMP_H
#define __ASM_SMP_H
#include <linux/cpumask.h>
#define raw_smp_processor_id() (current_thread_info()->cpu)
enum ipi_message_type {
IPI_NOP = 0,
IPI_RESCHEDULE = 1,
IPI_CALL_FUNC,
IPI_CALL_FUNC_SINGLE,
IPI_CPU_STOP,
IPI_TIMER,
};
extern void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg);
extern void smp_start_cpus(void);
extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
extern void smp_vm_unmask_irq(void *info);
#endif

View File

@ -0,0 +1,186 @@
/*
* Spinlock support for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_SPINLOCK_H
#define _ASM_SPINLOCK_H
#include <asm/irqflags.h>
/*
* This file is pulled in for SMP builds.
* Really need to check all the barrier stuff for "true" SMP
*/
/*
* Read locks:
* - load the lock value
* - increment it
* - if the lock value is still negative, go back and try again.
* - unsuccessful store is unsuccessful. Go back and try again. Loser.
* - successful store new lock value if positive -> lock acquired
*/
static inline void arch_read_lock(arch_rwlock_t *lock)
{
__asm__ __volatile__(
"1: R6 = memw_locked(%0);\n"
" { P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
" { if !P3 jump 1b; }\n"
" memw_locked(%0,P3) = R6;\n"
" { if !P3 jump 1b; }\n"
:
: "r" (&lock->lock)
: "memory", "r6", "p3"
);
}
static inline void arch_read_unlock(arch_rwlock_t *lock)
{
__asm__ __volatile__(
"1: R6 = memw_locked(%0);\n"
" R6 = add(R6,#-1);\n"
" memw_locked(%0,P3) = R6\n"
" if !P3 jump 1b;\n"
:
: "r" (&lock->lock)
: "memory", "r6", "p3"
);
}
/* I think this returns 0 on fail, 1 on success. */
static inline int arch_read_trylock(arch_rwlock_t *lock)
{
int temp;
__asm__ __volatile__(
" R6 = memw_locked(%1);\n"
" { %0 = #0; P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
" { if !P3 jump 1f; }\n"
" memw_locked(%1,P3) = R6;\n"
" { %0 = P3 }\n"
"1:\n"
: "=&r" (temp)
: "r" (&lock->lock)
: "memory", "r6", "p3"
);
return temp;
}
static inline int arch_read_can_lock(arch_rwlock_t *rwlock)
{
return rwlock->lock == 0;
}
static inline int arch_write_can_lock(arch_rwlock_t *rwlock)
{
return rwlock->lock == 0;
}
/* Stuffs a -1 in the lock value? */
static inline void arch_write_lock(arch_rwlock_t *lock)
{
__asm__ __volatile__(
"1: R6 = memw_locked(%0)\n"
" { P3 = cmp.eq(R6,#0); R6 = #-1;}\n"
" { if !P3 jump 1b; }\n"
" memw_locked(%0,P3) = R6;\n"
" { if !P3 jump 1b; }\n"
:
: "r" (&lock->lock)
: "memory", "r6", "p3"
);
}
static inline int arch_write_trylock(arch_rwlock_t *lock)
{
int temp;
__asm__ __volatile__(
" R6 = memw_locked(%1)\n"
" { %0 = #0; P3 = cmp.eq(R6,#0); R6 = #-1;}\n"
" { if !P3 jump 1f; }\n"
" memw_locked(%1,P3) = R6;\n"
" %0 = P3;\n"
"1:\n"
: "=&r" (temp)
: "r" (&lock->lock)
: "memory", "r6", "p3"
);
return temp;
}
static inline void arch_write_unlock(arch_rwlock_t *lock)
{
smp_mb();
lock->lock = 0;
}
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
__asm__ __volatile__(
"1: R6 = memw_locked(%0);\n"
" P3 = cmp.eq(R6,#0);\n"
" { if !P3 jump 1b; R6 = #1; }\n"
" memw_locked(%0,P3) = R6;\n"
" { if !P3 jump 1b; }\n"
:
: "r" (&lock->lock)
: "memory", "r6", "p3"
);
}
static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
smp_mb();
lock->lock = 0;
}
static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
{
int temp;
__asm__ __volatile__(
" R6 = memw_locked(%1);\n"
" P3 = cmp.eq(R6,#0);\n"
" { if !P3 jump 1f; R6 = #1; %0 = #0; }\n"
" memw_locked(%1,P3) = R6;\n"
" %0 = P3;\n"
"1:\n"
: "=&r" (temp)
: "r" (&lock->lock)
: "memory", "r6", "p3"
);
return temp;
}
/*
* SMP spinlocks are intended to allow only a single CPU at the lock
*/
#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
#define arch_spin_unlock_wait(lock) \
do {while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)
#define arch_spin_is_locked(x) ((x)->lock != 0)
#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
#endif

View File

@ -0,0 +1,42 @@
/*
* Spinlock support for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_SPINLOCK_TYPES_H
#define _ASM_SPINLOCK_TYPES_H
#include <linux/version.h>
#ifndef __LINUX_SPINLOCK_TYPES_H
# error "please don't include this file directly"
#endif
typedef struct {
volatile unsigned int lock;
} arch_spinlock_t;
#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
typedef struct {
volatile unsigned int lock;
} arch_rwlock_t;
#define __ARCH_RW_LOCK_UNLOCKED { 0 }
#endif

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_STRING_H_
#define _ASM_STRING_H_
#ifdef __KERNEL__
#define __HAVE_ARCH_MEMCPY
extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
/* ToDo: use dczeroa, accelerate the compiler-constant zero case */
#define __HAVE_ARCH_MEMSET
extern void *memset(void *__to, int c, size_t __n);
#endif
#endif /* _ASM_STRING_H_ */

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_SUSPEND_H
#define _ASM_SUSPEND_H
static inline int arch_prepare_suspend(void)
{
return 0;
}
#endif

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_SWAB_H
#define _ASM_SWAB_H
#define __SWAB_64_THRU_32__
#endif

View File

@ -0,0 +1,34 @@
/*
* Task switching definitions for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_SWITCH_TO_H
#define _ASM_SWITCH_TO_H
struct thread_struct;
extern struct task_struct *__switch_to(struct task_struct *,
struct task_struct *,
struct task_struct *);
#define switch_to(p, n, r) do {\
r = __switch_to((p), (n), (r));\
} while (0)
#endif /* _ASM_SWITCH_TO_H */

View File

@ -0,0 +1,54 @@
/*
* Syscall support for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_HEXAGON_SYSCALL_H
#define _ASM_HEXAGON_SYSCALL_H
typedef long (*syscall_fn)(unsigned long, unsigned long,
unsigned long, unsigned long,
unsigned long, unsigned long);
asmlinkage int sys_execve(char __user *ufilename, char __user * __user *argv,
char __user * __user *envp);
asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
unsigned long parent_tidp, unsigned long child_tidp);
#define sys_execve sys_execve
#define sys_clone sys_clone
#include <asm-generic/syscalls.h>
extern void *sys_call_table[];
static inline long syscall_get_nr(struct task_struct *task,
struct pt_regs *regs)
{
return regs->r06;
}
static inline void syscall_get_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
unsigned long *args)
{
BUG_ON(i + n > 6);
memcpy(args, &(&regs->r00)[i], n * sizeof(args[0]));
}
#endif

View File

@ -0,0 +1,154 @@
/*
* Thread support for the Hexagon architecture
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_THREAD_INFO_H
#define _ASM_THREAD_INFO_H
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#include <asm/processor.h>
#include <asm/registers.h>
#include <asm/page.h>
#endif
#define THREAD_SHIFT 12
#define THREAD_SIZE (1<<THREAD_SHIFT)
#if THREAD_SHIFT >= PAGE_SHIFT
#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
#else /* don't use standard allocator */
#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
extern void free_thread_info(struct thread_info *ti);
#endif
#ifndef __ASSEMBLY__
typedef struct {
unsigned long seg;
} mm_segment_t;
/*
* This is union'd with the "bottom" of the kernel stack.
* It keeps track of thread info which is handy for routines
* to access quickly.
*/
struct thread_info {
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
__u32 cpu; /* current cpu */
int preempt_count; /* 0=>preemptible,<0=>BUG */
mm_segment_t addr_limit; /* segmentation sux */
/*
* used for syscalls somehow;
* seems to have a function pointer and four arguments
*/
struct restart_block restart_block;
/* Points to the current pt_regs frame */
struct pt_regs *regs;
/*
* saved kernel sp at switch_to time;
* not sure if this is used (it's not in the VM model it seems;
* see thread_struct)
*/
unsigned long sp;
};
#else /* !__ASSEMBLY__ */
#include <asm/asm-offsets.h>
#endif /* __ASSEMBLY__ */
/* looks like "linux/hardirq.h" uses this. */
#define PREEMPT_ACTIVE 0x10000000
#ifndef __ASSEMBLY__
#define INIT_THREAD_INFO(tsk) \
{ \
.task = &tsk, \
.exec_domain = &default_exec_domain, \
.flags = 0, \
.cpu = 0, \
.preempt_count = 1, \
.addr_limit = KERNEL_DS, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
.sp = 0, \
.regs = NULL, \
}
#define init_thread_info (init_thread_union.thread_info)
#define init_stack (init_thread_union.stack)
/* Tacky preprocessor trickery */
#define qqstr(s) qstr(s)
#define qstr(s) #s
#define QUOTED_THREADINFO_REG qqstr(THREADINFO_REG)
register struct thread_info *__current_thread_info asm(QUOTED_THREADINFO_REG);
#define current_thread_info() __current_thread_info
#endif /* __ASSEMBLY__ */
/*
* thread information flags
* - these are process state flags that various assembly files
* may need to access
* - pending work-to-be-done flags are in LSW
* - other flags in MSW
*/
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_SINGLESTEP 4 /* restore ss @ return to usr mode */
#define TIF_IRET 5 /* return with iret */
#define TIF_RESTORE_SIGMASK 6 /* restore sig mask in do_signal() */
/* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_POLLING_NRFLAG 16
#define TIF_MEMDIE 17 /* OOM killer killed process */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_IRET (1 << TIF_IRET)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
/* work to do on interrupt/exception return - All but TIF_SYSCALL_TRACE */
#define _TIF_WORK_MASK (0x0000FFFF & ~_TIF_SYSCALL_TRACE)
/* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK 0x0000FFFF
#endif /* __KERNEL__ */
#endif

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef ASM_TIME_H
#define ASM_TIME_H
extern cycles_t pcycle_freq_mhz;
extern cycles_t thread_freq_mhz;
extern cycles_t sleep_clk_freq;
void setup_percpu_clockdev(void);
void ipi_timer(void);
#endif

View File

@ -0,0 +1,39 @@
/*
* Timer support for Hexagon
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_TIMER_REGS_H
#define _ASM_TIMER_REGS_H
/* This stuff should go into a platform specific file */
#define TCX0_CLK_RATE 19200
#define TIMER_ENABLE 0
#define TIMER_CLR_ON_MATCH 1
/*
* 8x50 HDD Specs 5-8. Simulator co-sim not fixed until
* release 1.1, and then it's "adjustable" and probably not defaulted.
*/
#define RTOS_TIMER_INT 3
#ifdef CONFIG_HEXAGON_COMET
#define RTOS_TIMER_REGS_ADDR 0xAB000000UL
#endif
#define SLEEP_CLK_RATE 32000
#endif

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_TIMEX_H
#define _ASM_TIMEX_H
#include <asm-generic/timex.h>
#include <asm/timer-regs.h>
/* Using TCX0 as our clock. CLOCK_TICK_RATE scheduled to be removed. */
#define CLOCK_TICK_RATE TCX0_CLK_RATE
#define ARCH_HAS_READ_CURRENT_TIMER
static inline int read_current_timer(unsigned long *timer_val)
{
*timer_val = (unsigned long) __vmgettime();
return 0;
}
#endif

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_TLB_H
#define _ASM_TLB_H
#include <linux/pagemap.h>
#include <asm/tlbflush.h>
/*
* We don't need any special per-pte or per-vma handling...
*/
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
/*
* .. because we flush the whole mm when it fills up
*/
#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
#include <asm-generic/tlb.h>
#endif

View File

@ -0,0 +1,58 @@
/*
* TLB flush support for Hexagon
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_TLBFLUSH_H
#define _ASM_TLBFLUSH_H
#include <linux/mm.h>
#include <asm/processor.h>
/*
* TLB flushing -- in "SMP", these routines get defined to be the
* ones from smp.c, else they are some local flavors.
*/
/*
* These functions are commonly macros, but in the interests of
* VM vs. native implementation and code size, we simply declare
* the function prototypes here.
*/
extern void tlb_flush_all(void);
extern void flush_tlb_mm(struct mm_struct *mm);
extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
extern void flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end);
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
extern void flush_tlb_one(unsigned long);
/*
* "This is called in munmap when we have freed up some page-table pages.
* We don't need to do anything here..."
*
* The VM kernel doesn't walk page tables, and they are passed to the VMM
* by logical address. There doesn't seem to be any possibility that they
* could be referenced by the VM kernel based on a stale mapping, since
* they would only be located by consulting the mm structure, and they
* will have been purged from that structure by the munmap. Seems like
* a noop on HVM as well.
*/
#define flush_tlb_pgtables(mm, start, end)
#endif

View File

@ -0,0 +1,29 @@
/*
* Trap support for Hexagon
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_HEXAGON_TRAPS_H
#define _ASM_HEXAGON_TRAPS_H
#include <asm/registers.h>
extern int die(const char *str, struct pt_regs *regs, long err);
extern int die_if_kernel(char *str, struct pt_regs *regs, long err);
#endif /* _ASM_HEXAGON_TRAPS_H */

View File

@ -0,0 +1,116 @@
/*
* User memory access support for Hexagon
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_UACCESS_H
#define _ASM_UACCESS_H
/*
* User space memory access functions
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/segment.h>
#include <asm/sections.h>
/*
* access_ok: - Checks if a user space pointer is valid
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that
* %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
* to write to a block, it is always safe to read from it.
* @addr: User space pointer to start of block to check
* @size: Size of block to check
*
* Context: User context only. This function may sleep.
*
* Checks if a pointer to a block of memory in user space is valid.
*
* Returns true (nonzero) if the memory block *may* be valid, false (zero)
* if it is definitely invalid.
*
* User address space in Hexagon, like x86, goes to 0xbfffffff, so the
* simple MSB-based tests used by MIPS won't work. Some further
* optimization is probably possible here, but for now, keep it
* reasonably simple and not *too* slow. After all, we've got the
* MMU for backup.
*/
#define VERIFY_READ 0
#define VERIFY_WRITE 1
#define __access_ok(addr, size) \
((get_fs().seg == KERNEL_DS.seg) || \
(((unsigned long)addr < get_fs().seg) && \
(unsigned long)size < (get_fs().seg - (unsigned long)addr)))
/*
* When a kernel-mode page fault is taken, the faulting instruction
* address is checked against a table of exception_table_entries.
* Each entry is a tuple of the address of an instruction that may
* be authorized to fault, and the address at which execution should
* be resumed instead of the faulting instruction, so as to effect
* a workaround.
*/
/* Assembly somewhat optimized copy routines */
unsigned long __copy_from_user_hexagon(void *to, const void __user *from,
unsigned long n);
unsigned long __copy_to_user_hexagon(void __user *to, const void *from,
unsigned long n);
#define __copy_from_user(to, from, n) __copy_from_user_hexagon(to, from, n)
#define __copy_to_user(to, from, n) __copy_to_user_hexagon(to, from, n)
/*
* XXX todo: some additonal performance gain is possible by
* implementing __copy_to/from_user_inatomic, which is much
* like __copy_to/from_user, but performs slightly less checking.
*/
__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count);
#define __clear_user(a, s) __clear_user_hexagon((a), (s))
#define __strncpy_from_user(dst, src, n) hexagon_strncpy_from_user(dst, src, n)
/* get around the ifndef in asm-generic/uaccess.h */
#define __strnlen_user __strnlen_user
extern long __strnlen_user(const char __user *src, long n);
static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
long n);
#include <asm-generic/uaccess.h>
/* Todo: an actual accelerated version of this. */
static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
long n)
{
long res = __strnlen_user(src, n);
/* return from strnlen can't be zero -- that would be rubbish. */
if (res > n) {
copy_from_user(dst, src, n);
return n;
} else {
copy_from_user(dst, src, res);
return res-1;
}
}
#endif

View File

@ -0,0 +1,36 @@
/*
* Syscall support for Hexagon
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#if !defined(_ASM_HEXAGON_UNISTD_H) || defined(__SYSCALL)
#define _ASM_HEXAGON_UNISTD_H
/*
* The kernel pulls this unistd.h in three different ways:
* 1. the "normal" way which gets all the __NR defines
* 2. with __SYSCALL defined to produce function declarations
* 3. with __SYSCALL defined to produce syscall table initialization
* See also: syscalltab.c
*/
#define sys_mmap2 sys_mmap_pgoff
#include <asm-generic/unistd.h>
#endif

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef HEXAGON_ASM_USER_H
#define HEXAGON_ASM_USER_H
/*
* Layout for registers passed in elf core dumps to userspace.
*
* Basically a rearranged subset of "pt_regs".
*
* Interested parties: libc, gdb...
*/
struct user_regs_struct {
unsigned long r0;
unsigned long r1;
unsigned long r2;
unsigned long r3;
unsigned long r4;
unsigned long r5;
unsigned long r6;
unsigned long r7;
unsigned long r8;
unsigned long r9;
unsigned long r10;
unsigned long r11;
unsigned long r12;
unsigned long r13;
unsigned long r14;
unsigned long r15;
unsigned long r16;
unsigned long r17;
unsigned long r18;
unsigned long r19;
unsigned long r20;
unsigned long r21;
unsigned long r22;
unsigned long r23;
unsigned long r24;
unsigned long r25;
unsigned long r26;
unsigned long r27;
unsigned long r28;
unsigned long r29;
unsigned long r30;
unsigned long r31;
unsigned long sa0;
unsigned long lc0;
unsigned long sa1;
unsigned long lc1;
unsigned long m0;
unsigned long m1;
unsigned long usr;
unsigned long p3_0;
unsigned long gp;
unsigned long ugp;
unsigned long pc;
unsigned long cause;
unsigned long badva;
unsigned long pad1; /* pad out to 48 words total */
unsigned long pad2; /* pad out to 48 words total */
unsigned long pad3; /* pad out to 48 words total */
};
#endif

View File

@ -0,0 +1,30 @@
/*
* vDSO implementation for Hexagon
*
* Copyright (c) 2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __ASM_VDSO_H
#define __ASM_VDSO_H
#include <linux/types.h>
struct hexagon_vdso {
u32 rt_signal_trampoline[2];
};
#endif /* __ASM_VDSO_H */

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_HEXAGON_VM_FAULT_H
#define _ASM_HEXAGON_VM_FAULT_H
extern void execute_protection_fault(struct pt_regs *);
extern void write_protection_fault(struct pt_regs *);
extern void read_protection_fault(struct pt_regs *);
#endif

View File

@ -0,0 +1,111 @@
/*
* Hexagon VM page table entry definitions
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef _ASM_VM_MMU_H
#define _ASM_VM_MMU_H
/*
* Shift, mask, and other constants for the Hexagon Virtual Machine
* page tables.
*
* Virtual machine MMU allows first-level entries to either be
* single-level lookup PTEs for very large pages, or PDEs pointing
* to second-level PTEs for smaller pages. If PTE is single-level,
* the least significant bits cannot be used as software bits to encode
* virtual memory subsystem information about the page, and that state
* must be maintained in some parallel data structure.
*/
/* S or Page Size field in PDE */
#define __HVM_PDE_S (0x7 << 0)
#define __HVM_PDE_S_4KB 0
#define __HVM_PDE_S_16KB 1
#define __HVM_PDE_S_64KB 2
#define __HVM_PDE_S_256KB 3
#define __HVM_PDE_S_1MB 4
#define __HVM_PDE_S_4MB 5
#define __HVM_PDE_S_16MB 6
#define __HVM_PDE_S_INVALID 7
/* Masks for L2 page table pointer, as function of page size */
#define __HVM_PDE_PTMASK_4KB 0xfffff000
#define __HVM_PDE_PTMASK_16KB 0xfffffc00
#define __HVM_PDE_PTMASK_64KB 0xffffff00
#define __HVM_PDE_PTMASK_256KB 0xffffffc0
#define __HVM_PDE_PTMASK_1MB 0xfffffff0
/*
* Virtual Machine PTE Bits/Fields
*/
#define __HVM_PTE_T (1<<4)
#define __HVM_PTE_U (1<<5)
#define __HVM_PTE_C (0x7<<6)
#define __HVM_PTE_CVAL(pte) (((pte) & __HVM_PTE_C) >> 6)
#define __HVM_PTE_R (1<<9)
#define __HVM_PTE_W (1<<10)
#define __HVM_PTE_X (1<<11)
/*
* Cache Attributes, to be shifted as necessary for virtual/physical PTEs
*/
#define __HEXAGON_C_WB 0x0 /* Write-back, no L2 */
#define __HEXAGON_C_WT 0x1 /* Write-through, no L2 */
#define __HEXAGON_C_DEV 0x4 /* Device register space */
#define __HEXAGON_C_WT_L2 0x5 /* Write-through, with L2 */
/* this really should be #if CONFIG_HEXAGON_ARCH = 2 but that's not defined */
#if defined(CONFIG_HEXAGON_COMET) || defined(CONFIG_QDSP6_ST1)
#define __HEXAGON_C_UNC __HEXAGON_C_DEV
#else
#define __HEXAGON_C_UNC 0x6 /* Uncached memory */
#endif
#define __HEXAGON_C_WB_L2 0x7 /* Write-back, with L2 */
/*
* This can be overriden, but we're defaulting to the most aggressive
* cache policy, the better to find bugs sooner.
*/
#define CACHE_DEFAULT __HEXAGON_C_WB_L2
/* Masks for physical page address, as a function of page size */
#define __HVM_PTE_PGMASK_4KB 0xfffff000
#define __HVM_PTE_PGMASK_16KB 0xffffc000
#define __HVM_PTE_PGMASK_64KB 0xffff0000
#define __HVM_PTE_PGMASK_256KB 0xfffc0000
#define __HVM_PTE_PGMASK_1MB 0xfff00000
/* Masks for single-level large page lookups */
#define __HVM_PTE_PGMASK_4MB 0xffc00000
#define __HVM_PTE_PGMASK_16MB 0xff000000
/*
* "Big kernel page mappings" (see vm_init_segtable.S)
* are currently 16MB
*/
#define BIG_KERNEL_PAGE_SHIFT 24
#define BIG_KERNEL_PAGE_SIZE (1 << BIG_KERNEL_PAGE_SHIFT)
#endif /* _ASM_VM_MMU_H */