mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-10 01:12:45 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
62
arch/hexagon/include/asm/Kbuild
Normal file
62
arch/hexagon/include/asm/Kbuild
Normal file
|
@ -0,0 +1,62 @@
|
|||
|
||||
header-y += ucontext.h
|
||||
|
||||
generic-y += auxvec.h
|
||||
generic-y += barrier.h
|
||||
generic-y += bug.h
|
||||
generic-y += bugs.h
|
||||
generic-y += clkdev.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 += hash.h
|
||||
generic-y += hw_irq.h
|
||||
generic-y += ioctl.h
|
||||
generic-y += ioctls.h
|
||||
generic-y += iomap.h
|
||||
generic-y += ipcbuf.h
|
||||
generic-y += irq_regs.h
|
||||
generic-y += irq_work.h
|
||||
generic-y += kdebug.h
|
||||
generic-y += kmap_types.h
|
||||
generic-y += local.h
|
||||
generic-y += local64.h
|
||||
generic-y += mcs_spinlock.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 += preempt.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 += serial.h
|
||||
generic-y += shmbuf.h
|
||||
generic-y += shmparam.h
|
||||
generic-y += siginfo.h
|
||||
generic-y += sizes.h
|
||||
generic-y += socket.h
|
||||
generic-y += sockios.h
|
||||
generic-y += stat.h
|
||||
generic-y += statfs.h
|
||||
generic-y += termbits.h
|
||||
generic-y += termios.h
|
||||
generic-y += topology.h
|
||||
generic-y += trace_clock.h
|
||||
generic-y += types.h
|
||||
generic-y += ucontext.h
|
||||
generic-y += unaligned.h
|
||||
generic-y += vga.h
|
||||
generic-y += xor.h
|
1
arch/hexagon/include/asm/asm-offsets.h
Normal file
1
arch/hexagon/include/asm/asm-offsets.h
Normal file
|
@ -0,0 +1 @@
|
|||
#include <generated/asm-offsets.h>
|
186
arch/hexagon/include/asm/atomic.h
Normal file
186
arch/hexagon/include/asm/atomic.h
Normal file
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Atomic operations for the Hexagon architecture
|
||||
*
|
||||
* Copyright (c) 2010-2013, 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>
|
||||
#include <asm/barrier.h>
|
||||
|
||||
#define ATOMIC_INIT(i) { (i) }
|
||||
|
||||
/* Normal writes in our arch don't clear lock reservations */
|
||||
|
||||
static inline void atomic_set(atomic_t *v, int new)
|
||||
{
|
||||
asm volatile(
|
||||
"1: r6 = memw_locked(%0);\n"
|
||||
" memw_locked(%0,p0) = %1;\n"
|
||||
" if (!P0) jump 1b;\n"
|
||||
:
|
||||
: "r" (&v->counter), "r" (new)
|
||||
: "memory", "p0", "r6"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
#define ATOMIC_OP(op) \
|
||||
static inline void atomic_##op(int i, atomic_t *v) \
|
||||
{ \
|
||||
int output; \
|
||||
\
|
||||
__asm__ __volatile__ ( \
|
||||
"1: %0 = memw_locked(%1);\n" \
|
||||
" %0 = "#op "(%0,%2);\n" \
|
||||
" memw_locked(%1,P3)=%0;\n" \
|
||||
" if !P3 jump 1b;\n" \
|
||||
: "=&r" (output) \
|
||||
: "r" (&v->counter), "r" (i) \
|
||||
: "memory", "p3" \
|
||||
); \
|
||||
} \
|
||||
|
||||
#define ATOMIC_OP_RETURN(op) \
|
||||
static inline int atomic_##op##_return(int i, atomic_t *v) \
|
||||
{ \
|
||||
int output; \
|
||||
\
|
||||
__asm__ __volatile__ ( \
|
||||
"1: %0 = memw_locked(%1);\n" \
|
||||
" %0 = "#op "(%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_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op)
|
||||
|
||||
ATOMIC_OPS(add)
|
||||
ATOMIC_OPS(sub)
|
||||
|
||||
#undef ATOMIC_OPS
|
||||
#undef ATOMIC_OP_RETURN
|
||||
#undef ATOMIC_OP
|
||||
|
||||
/**
|
||||
* __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 old value.
|
||||
*
|
||||
*/
|
||||
|
||||
static inline int __atomic_add_unless(atomic_t *v, int a, int u)
|
||||
{
|
||||
int __oldval;
|
||||
register int tmp;
|
||||
|
||||
asm volatile(
|
||||
"1: %0 = memw_locked(%2);"
|
||||
" {"
|
||||
" p3 = cmp.eq(%0, %4);"
|
||||
" if (p3.new) jump:nt 2f;"
|
||||
" %1 = add(%0, %3);"
|
||||
" }"
|
||||
" memw_locked(%2, p3) = %1;"
|
||||
" {"
|
||||
" if !p3 jump 1b;"
|
||||
" }"
|
||||
"2:"
|
||||
: "=&r" (__oldval), "=&r" (tmp)
|
||||
: "r" (v), "r" (a), "r" (u)
|
||||
: "memory", "p3"
|
||||
);
|
||||
return __oldval;
|
||||
}
|
||||
|
||||
#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
|
298
arch/hexagon/include/asm/bitops.h
Normal file
298
arch/hexagon/include/asm/bitops.h
Normal file
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
* 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>
|
||||
#include <asm/barrier.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/*
|
||||
* 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
|
34
arch/hexagon/include/asm/cache.h
Normal file
34
arch/hexagon/include/asm/cache.h
Normal 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://lwn.net/Articles/262554/ */
|
||||
#define __read_mostly
|
||||
|
||||
#endif
|
99
arch/hexagon/include/asm/cacheflush.h
Normal file
99
arch/hexagon/include/asm/cacheflush.h
Normal 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
|
50
arch/hexagon/include/asm/checksum.h
Normal file
50
arch/hexagon/include/asm/checksum.h
Normal 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
|
90
arch/hexagon/include/asm/cmpxchg.h
Normal file
90
arch/hexagon/include/asm/cmpxchg.h
Normal 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 */
|
29
arch/hexagon/include/asm/delay.h
Normal file
29
arch/hexagon/include/asm/delay.h
Normal 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_DELAY_H
|
||||
#define _ASM_DELAY_H
|
||||
|
||||
#include <asm/param.h>
|
||||
|
||||
extern void __delay(unsigned long cycles);
|
||||
extern void __udelay(unsigned long usecs);
|
||||
|
||||
#define udelay(usecs) __udelay((usecs))
|
||||
|
||||
#endif /* _ASM_DELAY_H */
|
106
arch/hexagon/include/asm/dma-mapping.h
Normal file
106
arch/hexagon/include/asm/dma-mapping.h
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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-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
|
29
arch/hexagon/include/asm/dma.h
Normal file
29
arch/hexagon/include/asm/dma.h
Normal 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
|
234
arch/hexagon/include/asm/elf.h
Normal file
234
arch/hexagon/include/asm/elf.h
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* ELF definitions for the Hexagon architecture
|
||||
*
|
||||
* Copyright (c) 2010-2013, 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.
|
||||
*/
|
||||
|
||||
#if CONFIG_HEXAGON_ARCH_VERSION >= 4
|
||||
#define CS_COPYREGS(DEST,REGS) \
|
||||
do {\
|
||||
DEST.cs0 = REGS->cs0;\
|
||||
DEST.cs1 = REGS->cs1;\
|
||||
} while (0)
|
||||
#else
|
||||
#define CS_COPYREGS(DEST,REGS)
|
||||
#endif
|
||||
|
||||
#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; \
|
||||
CS_COPYREGS(DEST,REGS); \
|
||||
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
|
||||
|
||||
#if CONFIG_HEXAGON_ARCH_VERSION == 2
|
||||
#define ELF_CORE_EFLAGS 0x1
|
||||
#endif
|
||||
|
||||
#if CONFIG_HEXAGON_ARCH_VERSION == 3
|
||||
#define ELF_CORE_EFLAGS 0x2
|
||||
#endif
|
||||
|
||||
#if CONFIG_HEXAGON_ARCH_VERSION == 4
|
||||
#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 PAGE_SIZE
|
||||
|
||||
/*
|
||||
* This is the location that an ET_DYN program is loaded if exec'ed. Typical
|
||||
* use of this is to invoke "./ld.so someprog" to test out a new version of
|
||||
* the loader. We need to make sure that it is out of the way of the program
|
||||
* that it will "exec", and that there is sufficient room for the brk.
|
||||
*/
|
||||
#define ELF_ET_DYN_BASE 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)
|
||||
|
||||
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
|
||||
struct linux_binprm;
|
||||
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
|
||||
int uses_interp);
|
||||
|
||||
|
||||
#endif
|
28
arch/hexagon/include/asm/exec.h
Normal file
28
arch/hexagon/include/asm/exec.h
Normal 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 */
|
35
arch/hexagon/include/asm/fixmap.h
Normal file
35
arch/hexagon/include/asm/fixmap.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
#include <asm-generic/fixmap.h>
|
||||
|
||||
#define kmap_get_fixmap_pte(vaddr) \
|
||||
pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), \
|
||||
(vaddr)), (vaddr)), (vaddr))
|
||||
|
||||
#endif
|
4
arch/hexagon/include/asm/fpu.h
Normal file
4
arch/hexagon/include/asm/fpu.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
/*
|
||||
* If the FPU is used inside the kernel,
|
||||
* kernel_fpu_end() will be defined here.
|
||||
*/
|
137
arch/hexagon/include/asm/futex.h
Normal file
137
arch/hexagon/include/asm/futex.h
Normal 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 */
|
289
arch/hexagon/include/asm/hexagon_vm.h
Normal file
289
arch/hexagon/include/asm/hexagon_vm.h
Normal file
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* Declarations for to Hexagon Virtal Machine.
|
||||
*
|
||||
* Copyright (c) 2010-2013, 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.
|
||||
*/
|
||||
|
||||
#define HVM_TRAP1_VMVERSION 0
|
||||
#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
|
||||
#define HVM_TRAP1_VMTIMEROP 24
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
enum VM_CACHE_OPS {
|
||||
hvmc_ickill,
|
||||
hvmc_dckill,
|
||||
hvmc_l2kill,
|
||||
hvmc_dccleaninva,
|
||||
hvmc_icinva,
|
||||
hvmc_idsync,
|
||||
hvmc_fetch_cfg
|
||||
};
|
||||
|
||||
enum VM_INT_OPS {
|
||||
hvmi_nop,
|
||||
hvmi_globen,
|
||||
hvmi_globdis,
|
||||
hvmi_locen,
|
||||
hvmi_locdis,
|
||||
hvmi_affinity,
|
||||
hvmi_get,
|
||||
hvmi_peek,
|
||||
hvmi_status,
|
||||
hvmi_post,
|
||||
hvmi_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(hvmc_ickill, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmcache_dckill(void)
|
||||
{
|
||||
return __vmcache(hvmc_dckill, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmcache_l2kill(void)
|
||||
{
|
||||
return __vmcache(hvmc_l2kill, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmcache_dccleaninva(unsigned long addr, unsigned long len)
|
||||
{
|
||||
return __vmcache(hvmc_dccleaninva, addr, len);
|
||||
}
|
||||
|
||||
static inline long __vmcache_icinva(unsigned long addr, unsigned long len)
|
||||
{
|
||||
return __vmcache(hvmc_icinva, addr, len);
|
||||
}
|
||||
|
||||
static inline long __vmcache_idsync(unsigned long addr,
|
||||
unsigned long len)
|
||||
{
|
||||
return __vmcache(hvmc_idsync, addr, len);
|
||||
}
|
||||
|
||||
static inline long __vmcache_fetch_cfg(unsigned long val)
|
||||
{
|
||||
return __vmcache(hvmc_fetch_cfg, val, 0);
|
||||
}
|
||||
|
||||
/* interrupt operations */
|
||||
|
||||
static inline long __vmintop_nop(void)
|
||||
{
|
||||
return __vmintop(hvmi_nop, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmintop_globen(long i)
|
||||
{
|
||||
return __vmintop(hvmi_globen, i, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmintop_globdis(long i)
|
||||
{
|
||||
return __vmintop(hvmi_globdis, i, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmintop_locen(long i)
|
||||
{
|
||||
return __vmintop(hvmi_locen, i, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmintop_locdis(long i)
|
||||
{
|
||||
return __vmintop(hvmi_locdis, i, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmintop_affinity(long i, long cpu)
|
||||
{
|
||||
return __vmintop(hvmi_affinity, i, cpu, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmintop_get(void)
|
||||
{
|
||||
return __vmintop(hvmi_get, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmintop_peek(void)
|
||||
{
|
||||
return __vmintop(hvmi_peek, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmintop_status(long i)
|
||||
{
|
||||
return __vmintop(hvmi_status, i, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmintop_post(long i)
|
||||
{
|
||||
return __vmintop(hvmi_post, i, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline long __vmintop_clear(long i)
|
||||
{
|
||||
return __vmintop(hvmi_clear, i, 0, 0, 0);
|
||||
}
|
||||
|
||||
#else /* Only assembly code should reference these */
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
* Constants for virtual instruction parameters and return values
|
||||
*/
|
||||
|
||||
/* vmnewmap arguments */
|
||||
|
||||
#define VM_TRANS_TYPE_LINEAR 0
|
||||
#define VM_TRANS_TYPE_TABLE 1
|
||||
#define VM_TLB_INVALIDATE_FALSE 0
|
||||
#define VM_TLB_INVALIDATE_TRUE 1
|
||||
|
||||
/* 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_SS_SFT 29
|
||||
#define HVM_VMEST_SS_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_WREG 0x1D
|
||||
#define HVM_GE_C_PCAL 0x1E
|
||||
#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
|
26
arch/hexagon/include/asm/intrinsics.h
Normal file
26
arch/hexagon/include/asm/intrinsics.h
Normal 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
|
342
arch/hexagon/include/asm/io.h
Normal file
342
arch/hexagon/include/asm/io.h
Normal file
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* IO definitions for the Hexagon architecture
|
||||
*
|
||||
* Copyright (c) 2010-2013, 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)
|
||||
|
||||
#define IOMEM(x) ((void __force __iomem *)(x))
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* http://comments.gmane.org/gmane.linux.ports.arm.kernel/117626
|
||||
*/
|
||||
|
||||
#define readb_relaxed __raw_readb
|
||||
#define readw_relaxed __raw_readw
|
||||
#define readl_relaxed __raw_readl
|
||||
|
||||
#define writeb_relaxed __raw_writeb
|
||||
#define writew_relaxed __raw_writew
|
||||
#define writel_relaxed __raw_writel
|
||||
|
||||
#define mmiowb()
|
||||
|
||||
/*
|
||||
* 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
|
36
arch/hexagon/include/asm/irq.h
Normal file
36
arch/hexagon/include/asm/irq.h
Normal 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
|
62
arch/hexagon/include/asm/irqflags.h
Normal file
62
arch/hexagon/include/asm/irqflags.h
Normal 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
|
44
arch/hexagon/include/asm/kgdb.h
Normal file
44
arch/hexagon/include/asm/kgdb.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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
|
||||
* also add cs0/1 = 2
|
||||
* so 48 = 42 + 4 + 2 + 2
|
||||
*/
|
||||
#define DBG_USER_REGS 42
|
||||
#define DBG_MAX_REG_NUM (DBG_USER_REGS + 8)
|
||||
#define NUMREGBYTES (DBG_MAX_REG_NUM*4)
|
||||
|
||||
#endif /* __HEXAGON_KGDB_H__ */
|
25
arch/hexagon/include/asm/linkage.h
Normal file
25
arch/hexagon/include/asm/linkage.h
Normal 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
|
120
arch/hexagon/include/asm/mem-layout.h
Normal file
120
arch/hexagon/include/asm/mem-layout.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Memory layout definitions for the Hexagon architecture
|
||||
*
|
||||
* Copyright (c) 2010-2013, 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)
|
||||
|
||||
/*
|
||||
* Compiling for a platform that needs a crazy physical offset
|
||||
* (like if the memory starts at 1GB and up) means we need
|
||||
* an actual PHYS_OFFSET. Should be set up in head.S.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_HEXAGON_PHYS_OFFSET
|
||||
#ifndef __ASSEMBLY__
|
||||
extern unsigned long __phys_offset;
|
||||
#endif
|
||||
#define PHYS_OFFSET __phys_offset
|
||||
#endif
|
||||
|
||||
#ifndef PHYS_OFFSET
|
||||
#define PHYS_OFFSET 0
|
||||
#endif
|
||||
|
||||
#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT)
|
||||
#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET
|
||||
|
||||
#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 (PAGE_OFFSET >> PGDIR_SHIFT) /* L1 shift is 22 bits */
|
||||
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 ((unsigned long) __va(high_memory + VMALLOC_OFFSET))
|
||||
|
||||
/* 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 */
|
37
arch/hexagon/include/asm/mmu.h
Normal file
37
arch/hexagon/include/asm/mmu.h
Normal 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
|
100
arch/hexagon/include/asm/mmu_context.h
Normal file
100
arch/hexagon/include/asm/mmu_context.h
Normal 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
|
26
arch/hexagon/include/asm/module.h
Normal file
26
arch/hexagon/include/asm/module.h
Normal 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
|
8
arch/hexagon/include/asm/mutex.h
Normal file
8
arch/hexagon/include/asm/mutex.h
Normal 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>
|
163
arch/hexagon/include/asm/page.h
Normal file
163
arch/hexagon/include/asm/page.h
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Page management definitions for the Hexagon architecture
|
||||
*
|
||||
* Copyright (c) 2010-2013, 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 + PHYS_OFFSET)
|
||||
#define __va(x) ((void *)((unsigned long)(x) - PHYS_OFFSET + 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)
|
||||
|
||||
#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
|
||||
#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
|
||||
|
||||
#define page_to_virt(page) __va(page_to_phys(page))
|
||||
|
||||
/*
|
||||
* 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/mem-layout.h>
|
||||
#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
|
22
arch/hexagon/include/asm/perf_event.h
Normal file
22
arch/hexagon/include/asm/perf_event.h
Normal 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 */
|
148
arch/hexagon/include/asm/pgalloc.h
Normal file
148
arch/hexagon/include/asm/pgalloc.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* 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)
|
||||
return NULL;
|
||||
if (!pgtable_page_ctor(pte)) {
|
||||
__free_page(pte);
|
||||
return NULL;
|
||||
}
|
||||
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
|
514
arch/hexagon/include/asm/pgtable.h
Normal file
514
arch/hexagon/include/asm/pgtable.h
Normal file
|
@ -0,0 +1,514 @@
|
|||
/*
|
||||
* 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))
|
||||
|
||||
/* 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
|
153
arch/hexagon/include/asm/processor.h
Normal file
153
arch/hexagon/include/asm/processor.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Process/processor support for the Hexagon architecture
|
||||
*
|
||||
* Copyright (c) 2010-2012, 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 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()
|
||||
#define cpu_relax_lowlatency() cpu_relax()
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
union {
|
||||
struct {
|
||||
unsigned long r16;
|
||||
unsigned long r17;
|
||||
};
|
||||
unsigned long long r1716;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
unsigned long r18;
|
||||
unsigned long r19;
|
||||
};
|
||||
unsigned long long r1918;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
unsigned long r20;
|
||||
unsigned long r21;
|
||||
};
|
||||
unsigned long long r2120;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
unsigned long r22;
|
||||
unsigned long r23;
|
||||
};
|
||||
unsigned long long r2322;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
unsigned long r24;
|
||||
unsigned long r25;
|
||||
};
|
||||
unsigned long long r2524;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
unsigned long r26;
|
||||
unsigned long r27;
|
||||
};
|
||||
unsigned long long r2726;
|
||||
};
|
||||
|
||||
unsigned long fp;
|
||||
unsigned long lr;
|
||||
};
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif
|
43
arch/hexagon/include/asm/smp.h
Normal file
43
arch/hexagon/include/asm/smp.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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_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
|
186
arch/hexagon/include/asm/spinlock.h
Normal file
186
arch/hexagon/include/asm/spinlock.h
Normal 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
|
40
arch/hexagon/include/asm/spinlock_types.h
Normal file
40
arch/hexagon/include/asm/spinlock_types.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
#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
|
32
arch/hexagon/include/asm/string.h
Normal file
32
arch/hexagon/include/asm/string.h
Normal 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_ */
|
27
arch/hexagon/include/asm/suspend.h
Normal file
27
arch/hexagon/include/asm/suspend.h
Normal 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
|
34
arch/hexagon/include/asm/switch_to.h
Normal file
34
arch/hexagon/include/asm/switch_to.h
Normal 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 */
|
46
arch/hexagon/include/asm/syscall.h
Normal file
46
arch/hexagon/include/asm/syscall.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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);
|
||||
|
||||
#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, &(®s->r00)[i], n * sizeof(args[0]));
|
||||
}
|
||||
#endif
|
137
arch/hexagon/include/asm/thread_info.h
Normal file
137
arch/hexagon/include/asm/thread_info.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* 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)
|
||||
#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
|
||||
|
||||
#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__ */
|
||||
|
||||
#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_RESTORE_SIGMASK 6 /* restore sig mask in do_signal() */
|
||||
/* true if poll_idle() is polling TIF_NEED_RESCHED */
|
||||
#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)
|
||||
|
||||
/* 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
|
29
arch/hexagon/include/asm/time.h
Normal file
29
arch/hexagon/include/asm/time.h
Normal 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
|
39
arch/hexagon/include/asm/timer-regs.h
Normal file
39
arch/hexagon/include/asm/timer-regs.h
Normal 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
|
36
arch/hexagon/include/asm/timex.h
Normal file
36
arch/hexagon/include/asm/timex.h
Normal 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
|
39
arch/hexagon/include/asm/tlb.h
Normal file
39
arch/hexagon/include/asm/tlb.h
Normal 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
|
58
arch/hexagon/include/asm/tlbflush.h
Normal file
58
arch/hexagon/include/asm/tlbflush.h
Normal 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
|
29
arch/hexagon/include/asm/traps.h
Normal file
29
arch/hexagon/include/asm/traps.h
Normal 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 */
|
116
arch/hexagon/include/asm/uaccess.h
Normal file
116
arch/hexagon/include/asm/uaccess.h
Normal 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
|
30
arch/hexagon/include/asm/vdso.h
Normal file
30
arch/hexagon/include/asm/vdso.h
Normal 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 */
|
26
arch/hexagon/include/asm/vm_fault.h
Normal file
26
arch/hexagon/include/asm/vm_fault.h
Normal 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
|
110
arch/hexagon/include/asm/vm_mmu.h
Normal file
110
arch/hexagon/include/asm/vm_mmu.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Hexagon VM page table entry definitions
|
||||
*
|
||||
* Copyright (c) 2010-2011,2013 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_UNC 0x6 /* Uncached memory */
|
||||
#if CONFIG_HEXAGON_ARCH_VERSION >= 2
|
||||
#define __HEXAGON_C_DEV 0x4 /* Device register space */
|
||||
#else
|
||||
#define __HEXAGON_C_DEV __HEXAGON_C_UNC
|
||||
#endif
|
||||
#define __HEXAGON_C_WT_L2 0x5 /* Write-through, with L2 */
|
||||
#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 */
|
Loading…
Add table
Add a link
Reference in a new issue