* Re: [Qemu-devel] [PATCH 3/3] monitor: add ability to dump SLB entries
From: Alexander Graf @ 2011-11-01 0:35 UTC (permalink / raw)
To: Nishanth Aravamudan; +Cc: qemu-ppc, qemu-devel
In-Reply-To: <20111031225340.GC4078@us.ibm.com>
On 31.10.2011, at 15:53, Nishanth Aravamudan wrote:
> On 31.10.2011 [15:14:12 +1100], David Gibson wrote:
>> Good points below. I forgot to CC Nish, the original patch author on
>> my post, so I've added him to the list now.
>>
>> Nish, can you correct these problems and resend the patch please?
>
> Yep, I'll work on this shortly.
>
>> On Mon, Oct 31, 2011 at 04:35:54AM +0100, Alexander Graf wrote:
>>>
>>> On 31.10.2011, at 04:16, David Gibson wrote:
>>>
>>>> From: Nishanth Aravamudan <nacc@us.ibm.com>
>>>>
>>>> When run with a PPC Book3S (server) CPU Currently 'info tlb' in the
>>>> qemu monitor reports "dump_mmu: unimplemented". However, during
>>>> bringup work, it can be quite handy to have the SLB entries, which are
>>>> available in the CPUPPCState. This patch adds an implementation of
>>>> info tlb for book3s, which dumps the SLB.
>>>>
>>>> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>>>> ---
>>>> target-ppc/helper.c | 32 +++++++++++++++++++++++++++-----
>>>> 1 files changed, 27 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/target-ppc/helper.c b/target-ppc/helper.c
>>>> index 137a494..29c7050 100644
>>>> --- a/target-ppc/helper.c
>>>> +++ b/target-ppc/helper.c
>>>> @@ -1545,14 +1545,36 @@ static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
>>>> }
>>>> }
>>>>
>>>> +static void mmubooks_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
>>>> + CPUState *env)
>>>> +{
>>>> + int i;
>>>> + uint64_t slbe, slbv;
>>>> +
>>>> + cpu_synchronize_state(env);
>>>> +
>>>> + cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n");
>>>> + for (i = 0; i < env->slb_nr; i++) {
>>>> + slbe = env->slb[i].esid;
>>>> + slbv = env->slb[i].vsid;
>>>
>>> From cpu.h:
>>>
>>> #if defined(TARGET_PPC64)
>>> /* Address space register */
>>> target_ulong asr;
>>> /* PowerPC 64 SLB area */
>>> ppc_slb_t slb[64];
>>> int slb_nr;
>>> #endif
>
> Being unfamiliar with qemu's coding style (and not immediately seeing it
> in CODING_STYLE), would the right approach be to wrap this definition in
> an #if defined(TARGET_PPC64)?
It's the only way to make it compile :)
>
>>>> + if (slbe == 0 && slbv == 0) {
>>>> + continue;
>>>> + }
>>>> + cpu_fprintf(f, "%d\t0x%016" PRIx64 "\t0x%016" PRIx64 "\n",
>>>> + i, slbe, slbv);
>>>> + }
>>>> +}
>>>> +
>>>> void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
>>>> {
>>>> - switch (env->mmu_model) {
>>>> - case POWERPC_MMU_BOOKE206:
>>>> + if (env->mmu_model == POWERPC_MMU_BOOKE206) {
>>>> mmubooke206_dump_mmu(f, cpu_fprintf, env);
>>>> - break;
>>>> - default:
>>>> - cpu_fprintf(f, "%s: unimplemented\n", __func__);
>>>> + } else {
>>>> + if ((env->mmu_model & POWERPC_MMU_64B) != 0) {
>>>
>>> I would actually prefer to explicitly keep the switch and match on
>>> all implementations explicitly. Also, have you verified this works
>>> without CONFIG_PPC64 set? In cpu.h I see the following:
>>>
>>> #if defined(TARGET_PPC64)
>>> #define POWERPC_MMU_64 0x00010000
>>> #define POWERPC_MMU_1TSEG 0x00020000
>>> /* 64 bits PowerPC MMU */
>>> POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001,
>>> /* 620 variant (no segment exceptions) */
>>> POWERPC_MMU_620 = POWERPC_MMU_64 | 0x00000002,
>>> /* Architecture 2.06 variant */
>>> POWERPC_MMU_2_06 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG | 0x00000003,
>>> #endif /* defined(TARGET_PPC64) */
>>>
>>> So POWERPC_MMU_64B shouldn't be defined for qemu-system-ppc.
>
> And similarly here, only have the MMU_2_06 and MMU_64B cases in the
> switch be defined #if defined(TARGET_PPC64)?
Yup :).
> Basically, asking if #ifdefs in the middle of functions are ok :)
It's the only valid way of making it work, yes. The alternative would be to drop all the TARGET_PPC64 ifdefery, but let's keep that for later.
Alex
^ permalink raw reply
* Re: linux-next 20111025: warnings in rcu_idle_exit_common()/rcu_idle_enter_common()
From: Paul E. McKenney @ 2011-11-01 0:34 UTC (permalink / raw)
To: Steven Rostedt
Cc: Wu Fengguang, linux-kernel@vger.kernel.org, Ingo Molnar,
Lai Jiangshan, Frederic Weisbecker, Carsten Emde
In-Reply-To: <1320075882.4793.4.camel@gandalf.stny.rr.com>
On Mon, Oct 31, 2011 at 11:44:42AM -0400, Steven Rostedt wrote:
> On Mon, 2011-10-31 at 05:19 -0700, Paul E. McKenney wrote:
> > On Mon, Oct 31, 2011 at 07:41:42PM +0800, Wu Fengguang wrote:
> > > On Mon, Oct 31, 2011 at 06:43:25PM +0800, Wu Fengguang wrote:
> > > > On Mon, Oct 31, 2011 at 05:51:52PM +0800, Paul E. McKenney wrote:
> > > > > On Mon, Oct 31, 2011 at 04:26:34PM +0800, Wu Fengguang wrote:
> > > > > > Hi Paul,
> > > > > >
> > > > > > I got two warnings in rcutree.c. The last working kernels are
> > > > > > linux-next 20111014 and linux v3.1.
> > > > >
> > > > > Interesting. Could you please enable RCU event tracing at boot?
> > > >
> > > > Sorry I cannot...possibly due to another ftrace bug.
> > > >
> > > > > The RCU event tracing is at tracing/events/rcu/enable relative to
> > > > > the debugfs mount point at runtime, if that helps.
> > > >
> > > > It's exactly that linux next 20111025 (comparing to 20111014) no
> > > > longer produces all the trace events that made me looking into the
> > > > dmesg and find the warning from RCU (rather than the expected warning
> > > > from ftrace).
> > > >
> > > > The trace output is now:
> > > >
> > > > # tracer: nop
> > > > #
> > > > # WARNING: FUNCTION TRACING IS CORRUPTED
> > > > # MAY BE MISSING FUNCTION EVENTS
> > > > # TASK-PID CPU# TIMESTAMP FUNCTION
> > > > # | | | | |
> > > > (nothing more)
> > >
> > > I checked the other test box and got the same warnings. Below is the
> > > full dmesg.
> > >
> > > No single trace output again..
> >
> > Hmmm... I wonder if it is too early during boot for tracing to work
> > correctly.
> >
> > Gah! I have rcu/next set ahead to commits that are not supposed to go
> > upstream yet. I reset it back to match the stuff that is targeted for
> > the current merge window. Still need to find the bug, of course.
> >
> > Anyone have any idea why the kworker thread might be trying to enter
> > the idle loop? The idle_cpu(smp_processor_id()) call believes that
> > this is not the idle task. Or does x86 allow non-idle tasks to enter
> > the idle loop? Or to be migrated off-CPU?
>
>
> It's not. Carsten Emde noticed what looked like a bug in ftrace last
> week at LinuxCon, and looking deeper at it, I found that the swapper
> task for all but CPU0 is named kworker. That's because kworker creates
> the idle task for all other CPUs besides CPU 0 and the idle task takes
> on kworker name.
>
> Carsten posted a patch last week too:
>
> https://lkml.org/lkml/2011/10/26/313
>
> I'm glad that this bug shows up outside of just ftrace :)
That makes one of us. ;-)
Fengguang, does Carsten's patch help?
Thanx, Paul
^ permalink raw reply
* Re: Sony DualShock3 - Detected but no events
From: Alon Bar-Lev @ 2011-11-01 0:31 UTC (permalink / raw)
To: Antonio Ospite; +Cc: linux-input
In-Reply-To: <20111101011854.5e0e87b561f6b18dcc09a988@studenti.unina.it>
Hello Antonio,
Thank you so much for your reply!
Unfortunately within the mbox there are no attachments, so I cannot
proceed and patch my bluez.
In the mean while I would like first to see it work with plain USB,
which should be much simpler, no?
If you connect the device to the USB port, does it work? Do yo see
activity when you do cat /dev/input/js0?
At Windows the following[1] drivers are working correctly in USB and
bluetooth....
Thanks!
Alon.
[1] http://www.motioninjoy.com/download
On Tue, Nov 1, 2011 at 2:18 AM, Antonio Ospite <ospite@studenti.unina.it> wrote:
> On Tue, 1 Nov 2011 01:04:37 +0200
> Alon Bar-Lev <alon.barlev@gmail.com> wrote:
>
>> Hello,
>>
>> I feel uncomfortable, as people reports that it does work...
>> Bluetooth pairing is not working and almost no documentation of
>> bluez-4 success....
>> So I thought starting in USB will be easier....
>>
>> I am using linux-3.1.0
>> When doing cat /dev/input/js0 or cat /dev/input/event15 or usbhid-dump
>> I get no activity.
>>
>> Can anyone please help? or acknowledge that it actually work?
>> Can I provide more information?
>
> Hi Alon, we were tracking the progress on:
>
> https://bugzilla.kernel.org/show_bug.cgi?id=40812
>
> but bugzilla on kernel.org is still down.
>
> The current situation is that it is working but patches needs to be
> applied to BlueZ, I copied the mails from the bugzilla reports here in
> this file:
>
> http://ao2.it/tmp/sixaxis_discussion_kernel.org_bugzilla.mbox
>
> where you will find instructions on how to make the Sixaxis work over
> BT.
>
> Keep in mind that the file is under /tmp on my server, so it will go
> away eventually.
>
> Ah you could help pushing linux-bluetooth people to review my changes
> and eventually apply them so we can have official support for
> Sixaxis/DS3 in BlueZ.
>
> Thanks,
> Antonio
>
> --
> Antonio Ospite
> http://ao2.it
>
> PGP public key ID: 0x4553B001
>
> A: Because it messes up the order in which people normally read text.
> See http://en.wikipedia.org/wiki/Posting_style
> Q: Why is top-posting such a bad thing?
>
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] Give up on edid retries when i2c bus is not responding
From: Eugeni Dodonov @ 2011-11-01 0:31 UTC (permalink / raw)
To: airlied; +Cc: dri-devel, Eugeni Dodonov
In-Reply-To: <1320107494-1835-1-git-send-email-eugeni.dodonov@intel.com>
This allows to avoid talking to a non-responding bus repeatedly until we
finally timeout after 15 attempts. We can do this by catching the -ENXIO
error, provided by i2c_algo_bit:bit_doAddress call.
Within the bit_doAddress we already try 3 times to get the edid data, so
if the routine tells us that bus is not responding, it is mostly pointless
to keep re-trying those attempts over and over again until we reach final
number of retries.
This change should fix https://bugs.freedesktop.org/show_bug.cgi?id=41059
and improve overall edid detection timing by 10-30% in most cases, and by
a much larger margin in case of phantom outputs (up to 30x in one worst
case).
Timing results for i915-powered machines for 'time xrandr' command:
Machine 1: from 0.840s to 0.290s
Machine 2: from 0.315s to 0.280s
Machine 3: from +/- 4s to 0.184s
Timing results for HD5770 with 'time xrandr' command:
Machine 4: from 3.210s to 1.060s
Reviewed-by: Chris Wilson <chris@hchris-wilson.co.uk>
Reviewed-by: Keith Packard <keithp@keithp.com>
Tested-by: Sean Finney <seanius@seanius.net>
Tested-by: Soren Hansen <soren@linux2go.dk>
Tested-by: Hernando Torque <sirius@sonnenkinder.org>
Tested-by: Mike Lothian <mike@fireburn.co.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=41059
Signed-off-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
---
drivers/gpu/drm/drm_edid.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 7425e5c..1bca6d7 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -265,6 +265,11 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
}
};
ret = i2c_transfer(adapter, msgs, 2);
+ if (ret == -ENXIO) {
+ DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n",
+ adapter->name);
+ break;
+ }
} while (ret != 2 && --retries);
return ret == 2 ? 0 : -1;
--
1.7.7.1
^ permalink raw reply related
* [PATCH] edid candidate for -next
From: Eugeni Dodonov @ 2011-11-01 0:31 UTC (permalink / raw)
To: airlied; +Cc: dri-devel
In-Reply-To: <CAPM=9txRAUs=ULRJ3OBBusnrjQo2VFzSWLvOQMktUXsNtD+gXQ@mail.gmail.com>
So as we all agree on this patch now, I updated it with all the Tested-by and
Reviewed-by.
Dave, I think it is good for pulling into -next now.
Thanks!
^ permalink raw reply
* Re: linux-next 20111025: warnings in rcu_idle_exit_common()/rcu_idle_enter_common()
From: Paul E. McKenney @ 2011-10-31 22:14 UTC (permalink / raw)
To: Wu Fengguang
Cc: Steven Rostedt, linux-kernel@vger.kernel.org, Ingo Molnar,
Lai Jiangshan, Frederic Weisbecker, peterz
In-Reply-To: <20111031123708.GA6839@localhost>
On Mon, Oct 31, 2011 at 08:37:08PM +0800, Wu Fengguang wrote:
> On Mon, Oct 31, 2011 at 08:31:25PM +0800, Wu Fengguang wrote:
> > On Mon, Oct 31, 2011 at 07:41:42PM +0800, Wu Fengguang wrote:
> > > On Mon, Oct 31, 2011 at 06:43:25PM +0800, Wu Fengguang wrote:
> > > > On Mon, Oct 31, 2011 at 05:51:52PM +0800, Paul E. McKenney wrote:
> > > > > On Mon, Oct 31, 2011 at 04:26:34PM +0800, Wu Fengguang wrote:
> > > > > > Hi Paul,
> > > > > >
> > > > > > I got two warnings in rcutree.c. The last working kernels are
> > > > > > linux-next 20111014 and linux v3.1.
> > > > >
> > > > > Interesting. Could you please enable RCU event tracing at boot?
> > > >
> > > > Sorry I cannot...possibly due to another ftrace bug.
> > > >
> > > > > The RCU event tracing is at tracing/events/rcu/enable relative to
> > > > > the debugfs mount point at runtime, if that helps.
> > > >
> > > > It's exactly that linux next 20111025 (comparing to 20111014) no
> > > > longer produces all the trace events that made me looking into the
> > > > dmesg and find the warning from RCU (rather than the expected warning
> > > > from ftrace).
> > > >
> > > > The trace output is now:
> > > >
> > > > # tracer: nop
> > > > #
> > > > # WARNING: FUNCTION TRACING IS CORRUPTED
> > > > # MAY BE MISSING FUNCTION EVENTS
> > > > # TASK-PID CPU# TIMESTAMP FUNCTION
> > > > # | | | | |
> > > > (nothing more)
> > >
> > > I checked the other test box and got the same warnings. Below is the
> > > full dmesg.
> >
> > Here is another dmesg showing the warnings inside kvm.
> >
> > btw, I turned on the ftrace self tests and it shows a warning, too.
>
> The trace events magically show up after enabling the ftrace self
> tests. Here are some of them collected in the original test box.
> Hope it helps.
Indeed it does!
Peter, I have been using "idle_cpu(smp_processor_id()))" to verify that
I really am running in the context of the idle task when RCU believes
that the current CPU has gone idle. This is apparently the wrong thing
to use, because it gives spurious warnings when bringing up the non-boot
CPUs on x86 under some configs -- the task running at that point appears
to be kworker/0:0 rather than an idle thread.
At other times I get the warning even though the trace-event system is
convinced that I am running in the context of an idle thread, for example,
as in the following trace output:
<idle>-0 [000] 29.985355: rcu_dyntick: Error on entry: not idle task 0
On the left, trace-events thinks that this is the idle task, but the
check idle_cpu(smp_processor_id())) says otherwise.
Help?
Thanx, Paul
^ permalink raw reply
* [PATCH v5 05/36] Hexagon: Add syscalls
From: Richard Kuo @ 2011-10-31 23:35 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Signed-off-by: Linas Vepstas <linas@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/syscall.h | 54 +++++++++++++++++++++
arch/hexagon/include/asm/unistd.h | 36 ++++++++++++++
arch/hexagon/kernel/syscall.c | 90 ++++++++++++++++++++++++++++++++++++
arch/hexagon/kernel/syscalltab.c | 32 +++++++++++++
4 files changed, 212 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/syscall.h
create mode 100644 arch/hexagon/include/asm/unistd.h
create mode 100644 arch/hexagon/kernel/syscall.c
create mode 100644 arch/hexagon/kernel/syscalltab.c
diff --git a/arch/hexagon/include/asm/syscall.h b/arch/hexagon/include/asm/syscall.h
new file mode 100644
index 0000000..3e7d61d
--- /dev/null
+++ b/arch/hexagon/include/asm/syscall.h
@@ -0,0 +1,54 @@
+/*
+ * Syscall support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_SYSCALL_H
+#define _ASM_HEXAGON_SYSCALL_H
+
+typedef long (*syscall_fn)(unsigned long, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long, unsigned long);
+
+asmlinkage int sys_execve(char __user *ufilename, char __user * __user *argv,
+ char __user * __user *envp);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+ unsigned long parent_tidp, unsigned long child_tidp);
+
+#define sys_execve sys_execve
+#define sys_clone sys_clone
+
+#include <asm-generic/syscalls.h>
+
+extern void *sys_call_table[];
+
+static inline long syscall_get_nr(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ return regs->r06;
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+ struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ unsigned long *args)
+{
+ BUG_ON(i + n > 6);
+ memcpy(args, &(®s->r00)[i], n * sizeof(args[0]));
+}
+#endif
diff --git a/arch/hexagon/include/asm/unistd.h b/arch/hexagon/include/asm/unistd.h
new file mode 100644
index 0000000..4d0ecde
--- /dev/null
+++ b/arch/hexagon/include/asm/unistd.h
@@ -0,0 +1,36 @@
+/*
+ * Syscall support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#if !defined(_ASM_HEXAGON_UNISTD_H) || defined(__SYSCALL)
+#define _ASM_HEXAGON_UNISTD_H
+
+/*
+ * The kernel pulls this unistd.h in three different ways:
+ * 1. the "normal" way which gets all the __NR defines
+ * 2. with __SYSCALL defined to produce function declarations
+ * 3. with __SYSCALL defined to produce syscall table initialization
+ * See also: syscalltab.c
+ */
+
+#define sys_mmap2 sys_mmap_pgoff
+
+#include <asm-generic/unistd.h>
+
+#endif
diff --git a/arch/hexagon/kernel/syscall.c b/arch/hexagon/kernel/syscall.c
new file mode 100644
index 0000000..620dd18
--- /dev/null
+++ b/arch/hexagon/kernel/syscall.c
@@ -0,0 +1,90 @@
+/*
+ * Hexagon system calls
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/unistd.h>
+#include <asm/mman.h>
+#include <asm/registers.h>
+
+/*
+ * System calls with architecture-specific wrappers.
+ * See signal.c for signal-related system call wrappers.
+ */
+
+asmlinkage int sys_execve(char __user *ufilename,
+ const char __user *const __user *argv,
+ const char __user *const __user *envp)
+{
+ struct pt_regs *pregs = current_thread_info()->regs;
+ char *filename;
+ int retval;
+
+ filename = getname(ufilename);
+ retval = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ return retval;
+
+ retval = do_execve(filename, argv, envp, pregs);
+ putname(filename);
+
+ return retval;
+}
+
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+ unsigned long parent_tidp, unsigned long child_tidp)
+{
+ struct pt_regs *pregs = current_thread_info()->regs;
+
+ if (!newsp)
+ newsp = pregs->SP;
+ return do_fork(clone_flags, newsp, pregs, 0, (int __user *)parent_tidp,
+ (int __user *)child_tidp);
+}
+
+/*
+ * Do a system call from the kernel, so as to have a proper pt_regs
+ * and recycle the sys_execvpe infrustructure.
+ */
+int kernel_execve(const char *filename,
+ const char *const argv[], const char *const envp[])
+{
+ register unsigned long __a0 asm("r0") = (unsigned long) filename;
+ register unsigned long __a1 asm("r1") = (unsigned long) argv;
+ register unsigned long __a2 asm("r2") = (unsigned long) envp;
+ int retval;
+
+ __asm__ volatile(
+ " R6 = #%4;\n"
+ " trap0(#1);\n"
+ " %0 = R0;\n"
+ : "=r" (retval)
+ : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve)
+ );
+
+ return retval;
+}
+EXPORT_SYMBOL(kernel_execve);
diff --git a/arch/hexagon/kernel/syscalltab.c b/arch/hexagon/kernel/syscalltab.c
new file mode 100644
index 0000000..c550f41
--- /dev/null
+++ b/arch/hexagon/kernel/syscalltab.c
@@ -0,0 +1,32 @@
+/*
+ * System call table for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+
+#include <asm/syscall.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+void *sys_call_table[__NR_syscalls] = {
+#include <asm/unistd.h>
+};
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 07/36] Hexagon: Add threadinfo
From: Richard Kuo @ 2011-10-31 23:36 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/thread_info.h | 154 ++++++++++++++++++++++++++++++++
1 files changed, 154 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/thread_info.h
diff --git a/arch/hexagon/include/asm/thread_info.h b/arch/hexagon/include/asm/thread_info.h
new file mode 100644
index 0000000..9c2934f
--- /dev/null
+++ b/arch/hexagon/include/asm/thread_info.h
@@ -0,0 +1,154 @@
+/*
+ * Thread support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#include <asm/registers.h>
+#include <asm/page.h>
+#endif
+
+#define THREAD_SHIFT 12
+#define THREAD_SIZE (1<<THREAD_SHIFT)
+
+#if THREAD_SHIFT >= PAGE_SHIFT
+#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
+#else /* don't use standard allocator */
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
+extern void free_thread_info(struct thread_info *ti);
+#endif
+
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+ unsigned long seg;
+} mm_segment_t;
+
+/*
+ * This is union'd with the "bottom" of the kernel stack.
+ * It keeps track of thread info which is handy for routines
+ * to access quickly.
+ */
+
+struct thread_info {
+ struct task_struct *task; /* main task structure */
+ struct exec_domain *exec_domain; /* execution domain */
+ unsigned long flags; /* low level flags */
+ __u32 cpu; /* current cpu */
+ int preempt_count; /* 0=>preemptible,<0=>BUG */
+ mm_segment_t addr_limit; /* segmentation sux */
+ /*
+ * used for syscalls somehow;
+ * seems to have a function pointer and four arguments
+ */
+ struct restart_block restart_block;
+ /* Points to the current pt_regs frame */
+ struct pt_regs *regs;
+ /*
+ * saved kernel sp at switch_to time;
+ * not sure if this is used (it's not in the VM model it seems;
+ * see thread_struct)
+ */
+ unsigned long sp;
+};
+
+#else /* !__ASSEMBLY__ */
+
+#include <asm/asm-offsets.h>
+
+#endif /* __ASSEMBLY__ */
+
+/* looks like "linux/hardirq.h" uses this. */
+
+#define PREEMPT_ACTIVE 0x10000000
+
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk) \
+{ \
+ .task = &tsk, \
+ .exec_domain = &default_exec_domain, \
+ .flags = 0, \
+ .cpu = 0, \
+ .preempt_count = 1, \
+ .addr_limit = KERNEL_DS, \
+ .restart_block = { \
+ .fn = do_no_restart_syscall, \
+ }, \
+ .sp = 0, \
+ .regs = NULL, \
+}
+
+#define init_thread_info (init_thread_union.thread_info)
+#define init_stack (init_thread_union.stack)
+
+/* Tacky preprocessor trickery */
+#define qqstr(s) qstr(s)
+#define qstr(s) #s
+#define QUOTED_THREADINFO_REG qqstr(THREADINFO_REG)
+
+register struct thread_info *__current_thread_info asm(QUOTED_THREADINFO_REG);
+#define current_thread_info() __current_thread_info
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files
+ * may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+
+#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
+#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
+#define TIF_SIGPENDING 2 /* signal pending */
+#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+#define TIF_SINGLESTEP 4 /* restore ss @ return to usr mode */
+#define TIF_IRET 5 /* return with iret */
+#define TIF_RESTORE_SIGMASK 6 /* restore sig mask in do_signal() */
+/* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_POLLING_NRFLAG 16
+#define TIF_MEMDIE 17 /* OOM killer killed process */
+
+#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
+#define _TIF_IRET (1 << TIF_IRET)
+#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
+
+/* work to do on interrupt/exception return - All but TIF_SYSCALL_TRACE */
+#define _TIF_WORK_MASK (0x0000FFFF & ~_TIF_SYSCALL_TRACE)
+
+/* work to do on any return to u-space */
+#define _TIF_ALLWORK_MASK 0x0000FFFF
+
+#endif /* __KERNEL__ */
+
+#endif
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 08/36] Hexagon: Add delay functions
From: Richard Kuo @ 2011-10-31 23:37 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/delay.h | 28 ++++++++++++++++++++++++++++
1 files changed, 28 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/delay.h
diff --git a/arch/hexagon/include/asm/delay.h b/arch/hexagon/include/asm/delay.h
new file mode 100644
index 0000000..9ab12e9
--- /dev/null
+++ b/arch/hexagon/include/asm/delay.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_DELAY_H
+#define _ASM_DELAY_H
+
+#include <asm/param.h>
+
+extern void __udelay(unsigned long usecs);
+
+#define udelay(usecs) __udelay((usecs))
+
+#endif /* _ASM_DELAY_H */
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* Re: Sony DualShock3 - Detected but no events
From: Antonio Ospite @ 2011-11-01 0:18 UTC (permalink / raw)
To: Alon Bar-Lev; +Cc: linux-input
In-Reply-To: <CAOazyz0GNJKFWNsaFiwheMjhBVJrcP-p8QBcsSvS3V97iuZFtQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1481 bytes --]
On Tue, 1 Nov 2011 01:04:37 +0200
Alon Bar-Lev <alon.barlev@gmail.com> wrote:
> Hello,
>
> I feel uncomfortable, as people reports that it does work...
> Bluetooth pairing is not working and almost no documentation of
> bluez-4 success....
> So I thought starting in USB will be easier....
>
> I am using linux-3.1.0
> When doing cat /dev/input/js0 or cat /dev/input/event15 or usbhid-dump
> I get no activity.
>
> Can anyone please help? or acknowledge that it actually work?
> Can I provide more information?
Hi Alon, we were tracking the progress on:
https://bugzilla.kernel.org/show_bug.cgi?id=40812
but bugzilla on kernel.org is still down.
The current situation is that it is working but patches needs to be
applied to BlueZ, I copied the mails from the bugzilla reports here in
this file:
http://ao2.it/tmp/sixaxis_discussion_kernel.org_bugzilla.mbox
where you will find instructions on how to make the Sixaxis work over
BT.
Keep in mind that the file is under /tmp on my server, so it will go
away eventually.
Ah you could help pushing linux-bluetooth people to review my changes
and eventually apply them so we can have official support for
Sixaxis/DS3 in BlueZ.
Thanks,
Antonio
--
Antonio Ospite
http://ao2.it
PGP public key ID: 0x4553B001
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* [PATCH v5 11/36] Hexagon: Add hypervisor interface
From: Richard Kuo @ 2011-10-31 23:39 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/hexagon_vm.h | 281 ++++++++++++++++++++
arch/hexagon/include/asm/vm_mmu.h | 111 ++++++++
arch/hexagon/kernel/vm_entry.S | 269 +++++++++++++++++++
arch/hexagon/kernel/vm_events.c | 101 ++++++++
arch/hexagon/kernel/vm_init_segtable.S | 442 ++++++++++++++++++++++++++++++++
arch/hexagon/kernel/vm_ops.S | 102 ++++++++
arch/hexagon/kernel/vm_switch.S | 95 +++++++
arch/hexagon/kernel/vm_vectors.S | 50 ++++
8 files changed, 1451 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/hexagon_vm.h
create mode 100644 arch/hexagon/include/asm/vm_mmu.h
create mode 100644 arch/hexagon/kernel/vm_entry.S
create mode 100644 arch/hexagon/kernel/vm_events.c
create mode 100644 arch/hexagon/kernel/vm_init_segtable.S
create mode 100644 arch/hexagon/kernel/vm_ops.S
create mode 100644 arch/hexagon/kernel/vm_switch.S
create mode 100644 arch/hexagon/kernel/vm_vectors.S
diff --git a/arch/hexagon/include/asm/hexagon_vm.h b/arch/hexagon/include/asm/hexagon_vm.h
new file mode 100644
index 0000000..182cb9d
--- /dev/null
+++ b/arch/hexagon/include/asm/hexagon_vm.h
@@ -0,0 +1,281 @@
+/*
+ * Declarations for to Hexagon Virtal Machine.
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef ASM_HEXAGON_VM_H
+#define ASM_HEXAGON_VM_H
+
+/*
+ * In principle, a Linux kernel for the VM could
+ * selectively define the virtual instructions
+ * as inline assembler macros, but for a first pass,
+ * we'll use subroutines for both the VM and the native
+ * kernels. It's costing a subroutine call/return,
+ * but it makes for a single set of entry points
+ * for tracing/debugging.
+ */
+
+/*
+ * Lets make this stuff visible only if configured,
+ * so we can unconditionally include the file.
+ */
+
+#ifndef __ASSEMBLY__
+
+enum VM_CACHE_OPS {
+ ickill,
+ dckill,
+ l2kill,
+ dccleaninva,
+ icinva,
+ idsync,
+ fetch_cfg
+};
+
+enum VM_INT_OPS {
+ nop,
+ globen,
+ globdis,
+ locen,
+ locdis,
+ affinity,
+ get,
+ peek,
+ status,
+ post,
+ clear
+};
+
+extern void _K_VM_event_vector(void);
+
+void __vmrte(void);
+long __vmsetvec(void *);
+long __vmsetie(long);
+long __vmgetie(void);
+long __vmintop(enum VM_INT_OPS, long, long, long, long);
+long __vmclrmap(void *, unsigned long);
+long __vmnewmap(void *);
+long __vmcache(enum VM_CACHE_OPS op, unsigned long addr, unsigned long len);
+unsigned long long __vmgettime(void);
+long __vmsettime(unsigned long long);
+long __vmstart(void *, void *);
+void __vmstop(void);
+long __vmwait(void);
+void __vmyield(void);
+long __vmvpid(void);
+
+static inline long __vmcache_ickill(void)
+{
+ return __vmcache(ickill, 0, 0);
+}
+
+static inline long __vmcache_dckill(void)
+{
+ return __vmcache(dckill, 0, 0);
+}
+
+static inline long __vmcache_l2kill(void)
+{
+ return __vmcache(l2kill, 0, 0);
+}
+
+static inline long __vmcache_dccleaninva(unsigned long addr, unsigned long len)
+{
+ return __vmcache(dccleaninva, addr, len);
+}
+
+static inline long __vmcache_icinva(unsigned long addr, unsigned long len)
+{
+ return __vmcache(icinva, addr, len);
+}
+
+static inline long __vmcache_idsync(unsigned long addr,
+ unsigned long len)
+{
+ return __vmcache(idsync, addr, len);
+}
+
+static inline long __vmcache_fetch_cfg(unsigned long val)
+{
+ return __vmcache(fetch_cfg, val, 0);
+}
+
+/* interrupt operations */
+
+static inline long __vmintop_nop(void)
+{
+ return __vmintop(nop, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_globen(long i)
+{
+ return __vmintop(globen, i, 0, 0, 0);
+}
+
+static inline long __vmintop_globdis(long i)
+{
+ return __vmintop(globdis, i, 0, 0, 0);
+}
+
+static inline long __vmintop_locen(long i)
+{
+ return __vmintop(locen, i, 0, 0, 0);
+}
+
+static inline long __vmintop_locdis(long i)
+{
+ return __vmintop(locdis, i, 0, 0, 0);
+}
+
+static inline long __vmintop_affinity(long i, long cpu)
+{
+ return __vmintop(locdis, i, cpu, 0, 0);
+}
+
+static inline long __vmintop_get(void)
+{
+ return __vmintop(get, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_peek(void)
+{
+ return __vmintop(peek, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_status(long i)
+{
+ return __vmintop(status, i, 0, 0, 0);
+}
+
+static inline long __vmintop_post(long i)
+{
+ return __vmintop(post, i, 0, 0, 0);
+}
+
+static inline long __vmintop_clear(long i)
+{
+ return __vmintop(clear, i, 0, 0, 0);
+}
+
+#else /* Only assembly code should reference these */
+
+#define HVM_TRAP1_VMRTE 1
+#define HVM_TRAP1_VMSETVEC 2
+#define HVM_TRAP1_VMSETIE 3
+#define HVM_TRAP1_VMGETIE 4
+#define HVM_TRAP1_VMINTOP 5
+#define HVM_TRAP1_VMCLRMAP 10
+#define HVM_TRAP1_VMNEWMAP 11
+#define HVM_TRAP1_FORMERLY_VMWIRE 12
+#define HVM_TRAP1_VMCACHE 13
+#define HVM_TRAP1_VMGETTIME 14
+#define HVM_TRAP1_VMSETTIME 15
+#define HVM_TRAP1_VMWAIT 16
+#define HVM_TRAP1_VMYIELD 17
+#define HVM_TRAP1_VMSTART 18
+#define HVM_TRAP1_VMSTOP 19
+#define HVM_TRAP1_VMVPID 20
+#define HVM_TRAP1_VMSETREGS 21
+#define HVM_TRAP1_VMGETREGS 22
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Constants for virtual instruction parameters and return values
+ */
+
+/* vmsetie arguments */
+
+#define VM_INT_DISABLE 0
+#define VM_INT_ENABLE 1
+
+/* vmsetimask arguments */
+
+#define VM_INT_UNMASK 0
+#define VM_INT_MASK 1
+
+#define VM_NEWMAP_TYPE_LINEAR 0
+#define VM_NEWMAP_TYPE_PGTABLES 1
+
+
+/*
+ * Event Record definitions useful to both C and Assembler
+ */
+
+/* VMEST Layout */
+
+#define HVM_VMEST_UM_SFT 31
+#define HVM_VMEST_UM_MSK 1
+#define HVM_VMEST_IE_SFT 30
+#define HVM_VMEST_IE_MSK 1
+#define HVM_VMEST_EVENTNUM_SFT 16
+#define HVM_VMEST_EVENTNUM_MSK 0xff
+#define HVM_VMEST_CAUSE_SFT 0
+#define HVM_VMEST_CAUSE_MSK 0xffff
+
+/*
+ * The initial program gets to find a system environment descriptor
+ * on its stack when it begins exection. The first word is a version
+ * code to indicate what is there. Zero means nothing more.
+ */
+
+#define HEXAGON_VM_SED_NULL 0
+
+/*
+ * Event numbers for vector binding
+ */
+
+#define HVM_EV_RESET 0
+#define HVM_EV_MACHCHECK 1
+#define HVM_EV_GENEX 2
+#define HVM_EV_TRAP 8
+#define HVM_EV_INTR 15
+/* These shoud be nuked as soon as we know the VM is up to spec v0.1.1 */
+#define HVM_EV_INTR_0 16
+#define HVM_MAX_INTR 240
+
+/*
+ * Cause values for General Exception
+ */
+
+#define HVM_GE_C_BUS 0x01
+#define HVM_GE_C_XPROT 0x11
+#define HVM_GE_C_XUSER 0x14
+#define HVM_GE_C_INVI 0x15
+#define HVM_GE_C_PRIVI 0x1B
+#define HVM_GE_C_XMAL 0x1C
+#define HVM_GE_C_RMAL 0x20
+#define HVM_GE_C_WMAL 0x21
+#define HVM_GE_C_RPROT 0x22
+#define HVM_GE_C_WPROT 0x23
+#define HVM_GE_C_RUSER 0x24
+#define HVM_GE_C_WUSER 0x25
+#define HVM_GE_C_CACHE 0x28
+
+/*
+ * Cause codes for Machine Check
+ */
+
+#define HVM_MCHK_C_DOWN 0x00
+#define HVM_MCHK_C_BADSP 0x01
+#define HVM_MCHK_C_BADEX 0x02
+#define HVM_MCHK_C_BADPT 0x03
+#define HVM_MCHK_C_REGWR 0x29
+
+#endif
diff --git a/arch/hexagon/include/asm/vm_mmu.h b/arch/hexagon/include/asm/vm_mmu.h
new file mode 100644
index 0000000..580462d
--- /dev/null
+++ b/arch/hexagon/include/asm/vm_mmu.h
@@ -0,0 +1,111 @@
+/*
+ * Hexagon VM page table entry definitions
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_VM_MMU_H
+#define _ASM_VM_MMU_H
+
+/*
+ * Shift, mask, and other constants for the Hexagon Virtual Machine
+ * page tables.
+ *
+ * Virtual machine MMU allows first-level entries to either be
+ * single-level lookup PTEs for very large pages, or PDEs pointing
+ * to second-level PTEs for smaller pages. If PTE is single-level,
+ * the least significant bits cannot be used as software bits to encode
+ * virtual memory subsystem information about the page, and that state
+ * must be maintained in some parallel data structure.
+ */
+
+/* S or Page Size field in PDE */
+#define __HVM_PDE_S (0x7 << 0)
+#define __HVM_PDE_S_4KB 0
+#define __HVM_PDE_S_16KB 1
+#define __HVM_PDE_S_64KB 2
+#define __HVM_PDE_S_256KB 3
+#define __HVM_PDE_S_1MB 4
+#define __HVM_PDE_S_4MB 5
+#define __HVM_PDE_S_16MB 6
+#define __HVM_PDE_S_INVALID 7
+
+/* Masks for L2 page table pointer, as function of page size */
+#define __HVM_PDE_PTMASK_4KB 0xfffff000
+#define __HVM_PDE_PTMASK_16KB 0xfffffc00
+#define __HVM_PDE_PTMASK_64KB 0xffffff00
+#define __HVM_PDE_PTMASK_256KB 0xffffffc0
+#define __HVM_PDE_PTMASK_1MB 0xfffffff0
+
+/*
+ * Virtual Machine PTE Bits/Fields
+ */
+#define __HVM_PTE_T (1<<4)
+#define __HVM_PTE_U (1<<5)
+#define __HVM_PTE_C (0x7<<6)
+#define __HVM_PTE_CVAL(pte) (((pte) & __HVM_PTE_C) >> 6)
+#define __HVM_PTE_R (1<<9)
+#define __HVM_PTE_W (1<<10)
+#define __HVM_PTE_X (1<<11)
+
+/*
+ * Cache Attributes, to be shifted as necessary for virtual/physical PTEs
+ */
+
+#define __HEXAGON_C_WB 0x0 /* Write-back, no L2 */
+#define __HEXAGON_C_WT 0x1 /* Write-through, no L2 */
+#define __HEXAGON_C_DEV 0x4 /* Device register space */
+#define __HEXAGON_C_WT_L2 0x5 /* Write-through, with L2 */
+/* this really should be #if CONFIG_HEXAGON_ARCH = 2 but that's not defined */
+#if defined(CONFIG_HEXAGON_COMET) || defined(CONFIG_QDSP6_ST1)
+#define __HEXAGON_C_UNC __HEXAGON_C_DEV
+#else
+#define __HEXAGON_C_UNC 0x6 /* Uncached memory */
+#endif
+#define __HEXAGON_C_WB_L2 0x7 /* Write-back, with L2 */
+
+/*
+ * This can be overriden, but we're defaulting to the most aggressive
+ * cache policy, the better to find bugs sooner.
+ */
+
+#define CACHE_DEFAULT __HEXAGON_C_WB_L2
+
+/* Masks for physical page address, as a function of page size */
+
+#define __HVM_PTE_PGMASK_4KB 0xfffff000
+#define __HVM_PTE_PGMASK_16KB 0xffffc000
+#define __HVM_PTE_PGMASK_64KB 0xffff0000
+#define __HVM_PTE_PGMASK_256KB 0xfffc0000
+#define __HVM_PTE_PGMASK_1MB 0xfff00000
+
+/* Masks for single-level large page lookups */
+
+#define __HVM_PTE_PGMASK_4MB 0xffc00000
+#define __HVM_PTE_PGMASK_16MB 0xff000000
+
+/*
+ * "Big kernel page mappings" (see vm_init_segtable.S)
+ * are currently 16MB
+ */
+
+#define BIG_KERNEL_PAGE_SHIFT 24
+#define BIG_KERNEL_PAGE_SIZE (1 << BIG_KERNEL_PAGE_SHIFT)
+
+
+
+#endif /* _ASM_VM_MMU_H */
diff --git a/arch/hexagon/kernel/vm_entry.S b/arch/hexagon/kernel/vm_entry.S
new file mode 100644
index 0000000..5b99066
--- /dev/null
+++ b/arch/hexagon/kernel/vm_entry.S
@@ -0,0 +1,269 @@
+/*
+ * Event entry/exit for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <asm/asm-offsets.h> /* assembly-safer versions of C defines */
+#include <asm/mem-layout.h> /* sigh, except for page_offset */
+#include <asm/hexagon_vm.h>
+#include <asm/thread_info.h>
+
+/*
+ * Entry into guest-mode Linux under Hexagon Virtual Machine.
+ * Stack pointer points to event record - build pt_regs on top of it,
+ * set up a plausible C stack frame, and dispatch to the C handler.
+ * On return, do vmrte virtual instruction with SP where we started.
+ *
+ * VM Spec 0.5 uses a trap to fetch HVM record now.
+ */
+
+/*
+ * Save full register state, while setting up thread_info struct
+ * pointer derived from kernel stack pointer in THREADINFO_REG
+ * register, putting prior thread_info.regs pointer in a callee-save
+ * register (R24, which had better not ever be assigned to THREADINFO_REG),
+ * and updating thread_info.regs to point to current stack frame,
+ * so as to support nested events in kernel mode.
+ *
+ * As this is common code, we set the pt_regs system call number
+ * to -1 for all events. It will be replaced with the system call
+ * number in the case where we decode a system call (trap0(#1)).
+ */
+
+#define save_pt_regs()\
+ memd(R0 + #_PT_R3130) = R31:30; \
+ { memw(R0 + #_PT_R2928) = R28; \
+ R31 = memw(R0 + #_PT_ER_VMPSP); }\
+ { memw(R0 + #(_PT_R2928 + 4)) = R31; \
+ R31 = ugp; } \
+ { memd(R0 + #_PT_R2726) = R27:26; \
+ R30 = gp ; } \
+ memd(R0 + #_PT_R2524) = R25:24; \
+ memd(R0 + #_PT_R2322) = R23:22; \
+ memd(R0 + #_PT_R2120) = R21:20; \
+ memd(R0 + #_PT_R1918) = R19:18; \
+ memd(R0 + #_PT_R1716) = R17:16; \
+ memd(R0 + #_PT_R1514) = R15:14; \
+ memd(R0 + #_PT_R1312) = R13:12; \
+ { memd(R0 + #_PT_R1110) = R11:10; \
+ R15 = lc0; } \
+ { memd(R0 + #_PT_R0908) = R9:8; \
+ R14 = sa0; } \
+ { memd(R0 + #_PT_R0706) = R7:6; \
+ R13 = lc1; } \
+ { memd(R0 + #_PT_R0504) = R5:4; \
+ R12 = sa1; } \
+ { memd(R0 + #_PT_UGPGP) = R31:30; \
+ R11 = m1; \
+ R2.H = #HI(_THREAD_SIZE); } \
+ { memd(R0 + #_PT_LC0SA0) = R15:14; \
+ R10 = m0; \
+ R2.L = #LO(_THREAD_SIZE); } \
+ { memd(R0 + #_PT_LC1SA1) = R13:12; \
+ R15 = p3:0; \
+ R2 = neg(R2); } \
+ { memd(R0 + #_PT_M1M0) = R11:10; \
+ R14 = usr; \
+ R2 = and(R0,R2); } \
+ { memd(R0 + #_PT_PREDSUSR) = R15:14; \
+ THREADINFO_REG = R2; } \
+ { r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \
+ memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \
+ R2 = #-1; } \
+ { memw(R0 + #_PT_SYSCALL_NR) = R2; \
+ R30 = #0; }
+
+/*
+ * Restore registers and thread_info.regs state. THREADINFO_REG
+ * is assumed to still be sane, and R24 to have been correctly
+ * preserved. Don't restore R29 (SP) until later.
+ */
+
+#define restore_pt_regs() \
+ { memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \
+ R15:14 = memd(R0 + #_PT_PREDSUSR); } \
+ { R11:10 = memd(R0 + #_PT_M1M0); \
+ p3:0 = R15; } \
+ { R13:12 = memd(R0 + #_PT_LC1SA1); \
+ usr = R14; } \
+ { R15:14 = memd(R0 + #_PT_LC0SA0); \
+ m1 = R11; } \
+ { R3:2 = memd(R0 + #_PT_R0302); \
+ m0 = R10; } \
+ { R5:4 = memd(R0 + #_PT_R0504); \
+ lc1 = R13; } \
+ { R7:6 = memd(R0 + #_PT_R0706); \
+ sa1 = R12; } \
+ { R9:8 = memd(R0 + #_PT_R0908); \
+ lc0 = R15; } \
+ { R11:10 = memd(R0 + #_PT_R1110); \
+ sa0 = R14; } \
+ { R13:12 = memd(R0 + #_PT_R1312); \
+ R15:14 = memd(R0 + #_PT_R1514); } \
+ { R17:16 = memd(R0 + #_PT_R1716); \
+ R19:18 = memd(R0 + #_PT_R1918); } \
+ { R21:20 = memd(R0 + #_PT_R2120); \
+ R23:22 = memd(R0 + #_PT_R2322); } \
+ { R25:24 = memd(R0 + #_PT_R2524); \
+ R27:26 = memd(R0 + #_PT_R2726); } \
+ R31:30 = memd(R0 + #_PT_UGPGP); \
+ { R28 = memw(R0 + #_PT_R2928); \
+ ugp = R31; } \
+ { R31:30 = memd(R0 + #_PT_R3130); \
+ gp = R30; }
+
+ /*
+ * Clears off enough space for the rest of pt_regs; evrec is a part
+ * of pt_regs in HVM mode. Save R0/R1, set handler's address in R1.
+ * R0 is the address of pt_regs and is the parameter to save_pt_regs.
+ */
+
+/*
+ * Since the HVM isn't automagically pushing the EVREC onto the stack anymore,
+ * we'll subract the entire size out and then fill it in ourselves.
+ * Need to save off R0, R1, R2, R3 immediately.
+ */
+
+#define vm_event_entry(CHandler) \
+ { \
+ R29 = add(R29, #-(_PT_REGS_SIZE)); \
+ memd(R29 + #(_PT_R0100 + -_PT_REGS_SIZE)) = R1:0; \
+ } \
+ { \
+ memd(R29 +#_PT_R0302) = R3:2; \
+ } \
+ trap1(#HVM_TRAP1_VMGETREGS); \
+ { \
+ memd(R29 + #_PT_ER_VMEL) = R1:0; \
+ R0 = R29; \
+ R1.L = #LO(CHandler); \
+ } \
+ { \
+ memd(R29 + #_PT_ER_VMPSP) = R3:2; \
+ R1.H = #HI(CHandler); \
+ jump event_dispatch; \
+ }
+
+.text
+ /*
+ * Do bulk save/restore in one place.
+ * Adds a jump to dispatch latency, but
+ * saves hundreds of bytes.
+ */
+
+event_dispatch:
+ save_pt_regs()
+ callr r1
+
+ /*
+ * If we were in kernel mode, we don't need to check scheduler
+ * or signals if CONFIG_PREEMPT is not set. If set, then it has
+ * to jump to a need_resched kind of block.
+ * BTW, CONFIG_PREEMPT is not supported yet.
+ */
+
+#ifdef CONFIG_PREEMPT
+ R0 = #VM_INT_DISABLE
+ trap1(#HVM_TRAP1_VMSETIE)
+#endif
+
+ /* "Nested control path" -- if the previous mode was kernel */
+ R0 = memw(R29 + #_PT_ER_VMEST);
+ P0 = tstbit(R0, #HVM_VMEST_UM_SFT);
+ if !P0 jump restore_all;
+ /*
+ * Returning from system call, normally coming back from user mode
+ */
+return_from_syscall:
+ /* Disable interrupts while checking TIF */
+ R0 = #VM_INT_DISABLE
+ trap1(#HVM_TRAP1_VMSETIE)
+
+ /*
+ * Coming back from the C-world, our thread info pointer
+ * should be in the designated register (usually R19)
+ */
+ R1.L = #LO(_TIF_ALLWORK_MASK)
+ {
+ R1.H = #HI(_TIF_ALLWORK_MASK);
+ R0 = memw(THREADINFO_REG + #_THREAD_INFO_FLAGS);
+ }
+
+ /*
+ * Compare against the "return to userspace" _TIF_WORK_MASK
+ */
+ R1 = and(R1,R0);
+ { P0 = cmp.eq(R1,#0); if (!P0.new) jump:t work_pending;}
+ jump restore_all; /* we're outta here! */
+
+work_pending:
+ {
+ P0 = tstbit(R1, #TIF_NEED_RESCHED);
+ if (!P0.new) jump:nt work_notifysig;
+ }
+ call schedule
+ jump return_from_syscall; /* check for more work */
+
+work_notifysig:
+ /* this is the part that's kind of fuzzy. */
+ R1 = and(R0, #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME));
+ P0 = cmp.eq(R1, #0);
+ if P0 jump restore_all
+ R1 = R0; /* unsigned long thread_info_flags */
+ R0 = R29; /* regs should still be at top of stack */
+ call do_notify_resume
+
+restore_all:
+ /* Disable interrupts, if they weren't already, before reg restore. */
+ R0 = #VM_INT_DISABLE
+ trap1(#HVM_TRAP1_VMSETIE)
+
+ /* do the setregs here for VM 0.5 */
+ /* R29 here should already be pointing at pt_regs */
+ R1:0 = memd(R29 + #_PT_ER_VMEL);
+ R3:2 = memd(R29 + #_PT_ER_VMPSP);
+ trap1(#HVM_TRAP1_VMSETREGS);
+
+ R0 = R29
+ restore_pt_regs()
+ R1:0 = memd(R29 + #_PT_R0100);
+ R29 = add(R29, #_PT_REGS_SIZE);
+ trap1(#HVM_TRAP1_VMRTE)
+ /* Notreached */
+
+ .globl _K_enter_genex
+_K_enter_genex:
+ vm_event_entry(do_genex)
+
+ .globl _K_enter_interrupt
+_K_enter_interrupt:
+ vm_event_entry(arch_do_IRQ)
+
+ .globl _K_enter_trap0
+_K_enter_trap0:
+ vm_event_entry(do_trap0)
+
+ .globl _K_enter_machcheck
+_K_enter_machcheck:
+ vm_event_entry(do_machcheck)
+
+
+ .globl ret_from_fork
+ret_from_fork:
+ call schedule_tail
+ jump return_from_syscall
diff --git a/arch/hexagon/kernel/vm_events.c b/arch/hexagon/kernel/vm_events.c
new file mode 100644
index 0000000..986a081
--- /dev/null
+++ b/arch/hexagon/kernel/vm_events.c
@@ -0,0 +1,101 @@
+/*
+ * Mostly IRQ support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/kernel.h>
+#include <asm/registers.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+#include <asm/system.h>
+
+/*
+ * show_regs - print pt_regs structure
+ * @regs: pointer to pt_regs
+ *
+ * To-do: add all the accessor definitions to registers.h
+ *
+ * Will make this routine a lot easier to write.
+ */
+void show_regs(struct pt_regs *regs)
+{
+ printk(KERN_EMERG "restart_r0: \t0x%08lx syscall_nr: %ld\n",
+ regs->restart_r0, regs->syscall_nr);
+ printk(KERN_EMERG "preds: \t\t0x%08lx\n", regs->preds);
+ printk(KERN_EMERG "lc0: \t0x%08lx sa0: 0x%08lx m0: 0x%08lx\n",
+ regs->lc0, regs->sa0, regs->m0);
+ printk(KERN_EMERG "lc1: \t0x%08lx sa1: 0x%08lx m1: 0x%08lx\n",
+ regs->lc1, regs->sa1, regs->m1);
+ printk(KERN_EMERG "gp: \t0x%08lx ugp: 0x%08lx usr: 0x%08lx\n",
+ regs->gp, regs->ugp, regs->usr);
+ printk(KERN_EMERG "r0: \t0x%08lx %08lx %08lx %08lx\n", regs->r00,
+ regs->r01,
+ regs->r02,
+ regs->r03);
+ printk(KERN_EMERG "r4: \t0x%08lx %08lx %08lx %08lx\n", regs->r04,
+ regs->r05,
+ regs->r06,
+ regs->r07);
+ printk(KERN_EMERG "r8: \t0x%08lx %08lx %08lx %08lx\n", regs->r08,
+ regs->r09,
+ regs->r10,
+ regs->r11);
+ printk(KERN_EMERG "r12: \t0x%08lx %08lx %08lx %08lx\n", regs->r12,
+ regs->r13,
+ regs->r14,
+ regs->r15);
+ printk(KERN_EMERG "r16: \t0x%08lx %08lx %08lx %08lx\n", regs->r16,
+ regs->r17,
+ regs->r18,
+ regs->r19);
+ printk(KERN_EMERG "r20: \t0x%08lx %08lx %08lx %08lx\n", regs->r20,
+ regs->r21,
+ regs->r22,
+ regs->r23);
+ printk(KERN_EMERG "r24: \t0x%08lx %08lx %08lx %08lx\n", regs->r24,
+ regs->r25,
+ regs->r26,
+ regs->r27);
+ printk(KERN_EMERG "r28: \t0x%08lx %08lx %08lx %08lx\n", regs->r28,
+ regs->r29,
+ regs->r30,
+ regs->r31);
+
+ printk(KERN_EMERG "elr: \t0x%08lx cause: 0x%08lx user_mode: %d\n",
+ pt_elr(regs), pt_cause(regs), user_mode(regs));
+ printk(KERN_EMERG "psp: \t0x%08lx badva: 0x%08lx int_enabled: %d\n",
+ pt_psp(regs), pt_badva(regs), ints_enabled(regs));
+}
+
+void dummy_handler(struct pt_regs *regs)
+{
+ unsigned int elr = pt_elr(regs);
+ printk(KERN_ERR "Unimplemented handler; ELR=0x%08x\n", elr);
+}
+
+
+void arch_do_IRQ(struct pt_regs *regs)
+{
+ int irq = pt_cause(regs);
+ struct pt_regs *old_regs = set_irq_regs(regs);
+
+ irq_enter();
+ generic_handle_irq(irq);
+ irq_exit();
+ set_irq_regs(old_regs);
+}
diff --git a/arch/hexagon/kernel/vm_init_segtable.S b/arch/hexagon/kernel/vm_init_segtable.S
new file mode 100644
index 0000000..aebb35b
--- /dev/null
+++ b/arch/hexagon/kernel/vm_init_segtable.S
@@ -0,0 +1,442 @@
+/*
+ * Initial page table for Linux kernel under Hexagon VM,
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+/*
+ * These tables are pre-computed and linked into kernel.
+ */
+
+#include <asm/vm_mmu.h>
+/* #include <asm/iomap.h> */
+
+/*
+ * Start with mapping PA=0 to both VA=0x0 and VA=0xc000000 as 16MB large pages.
+ * No user mode access, RWX, write-back cache. The entry needs
+ * to be replicated for all 4 virtual segments mapping to the page.
+ */
+
+/* "Big Kernel Page" */
+#define BKP(pa) (((pa) & __HVM_PTE_PGMASK_4MB) \
+ | __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+ | __HEXAGON_C_WB_L2 << 6 \
+ | __HVM_PDE_S_16MB)
+
+/* No cache version */
+
+#define BKPG_IO(pa) (((pa) & __HVM_PTE_PGMASK_16MB) \
+ | __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+ | __HVM_PDE_S_16MB | __HEXAGON_C_DEV << 6 )
+
+#define FOURK_IO(pa) (((pa) & __HVM_PTE_PGMASK_4KB) \
+ | __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+ | __HEXAGON_C_DEV << 6 )
+
+#define L2_PTR(pa) (((pa) & __HVM_PTE_PGMASK_4KB) \
+ | __HVM_PDE_S_4KB )
+
+#define X __HVM_PDE_S_INVALID
+
+ .p2align 12
+ .globl swapper_pg_dir
+ .globl _K_init_segtable
+swapper_pg_dir:
+/* VA 0x00000000 */
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/* VA 0x40000000 */
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/* VA 0x80000000 */
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/*0xa8*/.word X,X,X,X
+#ifdef CONFIG_COMET_EARLY_UART_DEBUG
+UART_PTE_ENTRY:
+/*0xa9*/.word BKPG_IO(0xa9000000),BKPG_IO(0xa9000000),BKPG_IO(0xa9000000),BKPG_IO(0xa9000000)
+#else
+/*0xa9*/.word X,X,X,X
+#endif
+/*0xaa*/.word X,X,X,X
+/*0xab*/.word X,X,X,X
+/*0xac*/.word X,X,X,X
+/*0xad*/.word X,X,X,X
+/*0xae*/.word X,X,X,X
+/*0xaf*/.word X,X,X,X
+/*0xb0*/.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+_K_init_segtable:
+/* VA 0xC0000000 */
+ .word BKP(0x00000000), BKP(0x00400000), BKP(0x00800000), BKP(0x00c00000)
+ .word BKP(0x01000000), BKP(0x01400000), BKP(0x01800000), BKP(0x01c00000)
+ .word BKP(0x02000000), BKP(0x02400000), BKP(0x02800000), BKP(0x02c00000)
+ .word BKP(0x03000000), BKP(0x03400000), BKP(0x03800000), BKP(0x03c00000)
+ .word BKP(0x04000000), BKP(0x04400000), BKP(0x04800000), BKP(0x04c00000)
+ .word BKP(0x05000000), BKP(0x05400000), BKP(0x05800000), BKP(0x05c00000)
+ .word BKP(0x06000000), BKP(0x06400000), BKP(0x06800000), BKP(0x06c00000)
+ .word BKP(0x07000000), BKP(0x07400000), BKP(0x07800000), BKP(0x07c00000)
+
+ .word BKP(0x08000000), BKP(0x08400000), BKP(0x08800000), BKP(0x08c00000)
+ .word BKP(0x09000000), BKP(0x09400000), BKP(0x09800000), BKP(0x09c00000)
+ .word BKP(0x0a000000), BKP(0x0a400000), BKP(0x0a800000), BKP(0x0ac00000)
+ .word BKP(0x0b000000), BKP(0x0b400000), BKP(0x0b800000), BKP(0x0bc00000)
+ .word BKP(0x0c000000), BKP(0x0c400000), BKP(0x0c800000), BKP(0x0cc00000)
+ .word BKP(0x0d000000), BKP(0x0d400000), BKP(0x0d800000), BKP(0x0dc00000)
+ .word BKP(0x0e000000), BKP(0x0e400000), BKP(0x0e800000), BKP(0x0ec00000)
+ .word BKP(0x0f000000), BKP(0x0f400000), BKP(0x0f800000), BKP(0x0fc00000)
+
+ .word BKP(0x10000000), BKP(0x10400000), BKP(0x10800000), BKP(0x10c00000)
+ .word BKP(0x11000000), BKP(0x11400000), BKP(0x11800000), BKP(0x11c00000)
+ .word BKP(0x12000000), BKP(0x12400000), BKP(0x12800000), BKP(0x12c00000)
+ .word BKP(0x13000000), BKP(0x13400000), BKP(0x13800000), BKP(0x13c00000)
+ .word BKP(0x14000000), BKP(0x14400000), BKP(0x14800000), BKP(0x14c00000)
+ .word BKP(0x15000000), BKP(0x15400000), BKP(0x15800000), BKP(0x15c00000)
+ .word BKP(0x16000000), BKP(0x16400000), BKP(0x16800000), BKP(0x16c00000)
+ .word BKP(0x17000000), BKP(0x17400000), BKP(0x17800000), BKP(0x17c00000)
+
+ .word BKP(0x18000000), BKP(0x18400000), BKP(0x18800000), BKP(0x18c00000)
+ .word BKP(0x19000000), BKP(0x19400000), BKP(0x19800000), BKP(0x19c00000)
+ .word BKP(0x1a000000), BKP(0x1a400000), BKP(0x1a800000), BKP(0x1ac00000)
+ .word BKP(0x1b000000), BKP(0x1b400000), BKP(0x1b800000), BKP(0x1bc00000)
+ .word BKP(0x1c000000), BKP(0x1c400000), BKP(0x1c800000), BKP(0x1cc00000)
+ .word BKP(0x1d000000), BKP(0x1d400000), BKP(0x1d800000), BKP(0x1dc00000)
+ .word BKP(0x1e000000), BKP(0x1e400000), BKP(0x1e800000), BKP(0x1ec00000)
+ .word BKP(0x1f000000), BKP(0x1f400000), BKP(0x1f800000), BKP(0x1fc00000)
+
+ .word BKP(0x20000000), BKP(0x20400000), BKP(0x20800000), BKP(0x20c00000)
+ .word BKP(0x21000000), BKP(0x21400000), BKP(0x21800000), BKP(0x21c00000)
+ .word BKP(0x22000000), BKP(0x22400000), BKP(0x22800000), BKP(0x22c00000)
+ .word BKP(0x23000000), BKP(0x23400000), BKP(0x23800000), BKP(0x23c00000)
+ .word BKP(0x24000000), BKP(0x24400000), BKP(0x24800000), BKP(0x24c00000)
+ .word BKP(0x25000000), BKP(0x25400000), BKP(0x25800000), BKP(0x25c00000)
+ .word BKP(0x26000000), BKP(0x26400000), BKP(0x26800000), BKP(0x26c00000)
+ .word BKP(0x27000000), BKP(0x27400000), BKP(0x27800000), BKP(0x27c00000)
+
+ .word BKP(0x28000000), BKP(0x28400000), BKP(0x28800000), BKP(0x28c00000)
+ .word BKP(0x29000000), BKP(0x29400000), BKP(0x29800000), BKP(0x29c00000)
+ .word BKP(0x2a000000), BKP(0x2a400000), BKP(0x2a800000), BKP(0x2ac00000)
+ .word BKP(0x2b000000), BKP(0x2b400000), BKP(0x2b800000), BKP(0x2bc00000)
+ .word BKP(0x2c000000), BKP(0x2c400000), BKP(0x2c800000), BKP(0x2cc00000)
+ .word BKP(0x2d000000), BKP(0x2d400000), BKP(0x2d800000), BKP(0x2dc00000)
+ .word BKP(0x2e000000), BKP(0x2e400000), BKP(0x2e800000), BKP(0x2ec00000)
+ .word BKP(0x2f000000), BKP(0x2f400000), BKP(0x2f800000), BKP(0x2fc00000)
+
+ .word BKP(0x30000000), BKP(0x30400000), BKP(0x30800000), BKP(0x30c00000)
+ .word BKP(0x31000000), BKP(0x31400000), BKP(0x31800000), BKP(0x31c00000)
+ .word BKP(0x32000000), BKP(0x32400000), BKP(0x32800000), BKP(0x32c00000)
+ .word BKP(0x33000000), BKP(0x33400000), BKP(0x33800000), BKP(0x33c00000)
+ .word BKP(0x34000000), BKP(0x34400000), BKP(0x34800000), BKP(0x34c00000)
+ .word BKP(0x35000000), BKP(0x35400000), BKP(0x35800000), BKP(0x35c00000)
+ .word BKP(0x36000000), BKP(0x36400000), BKP(0x36800000), BKP(0x36c00000)
+ .word BKP(0x37000000), BKP(0x37400000), BKP(0x37800000), BKP(0x37c00000)
+
+ .word BKP(0x38000000), BKP(0x38400000), BKP(0x38800000), BKP(0x38c00000)
+ .word BKP(0x39000000), BKP(0x39400000), BKP(0x39800000), BKP(0x39c00000)
+ .word BKP(0x3a000000), BKP(0x3a400000), BKP(0x3a800000), BKP(0x3ac00000)
+ .word BKP(0x3b000000), BKP(0x3b400000), BKP(0x3b800000), BKP(0x3bc00000)
+ .word BKP(0x3c000000), BKP(0x3c400000), BKP(0x3c800000), BKP(0x3cc00000)
+ .word BKP(0x3d000000), BKP(0x3d400000), BKP(0x3d800000), BKP(0x3dc00000)
+_K_io_map:
+ .word X,X,X,X /* 0x3e000000 - device IO early remap */
+ .word X,X,X,X /* 0x3f000000 - hypervisor space*/
+
+#if 0
+/*
+ * This is in here as an example for devices which need to be mapped really
+ * early.
+ */
+ .p2align 12
+ .globl _K_io_kmap
+ .globl _K_init_devicetable
+_K_init_devicetable: /* Should be 4MB worth of entries */
+ .word FOURK_IO(MSM_GPIO1_PHYS),FOURK_IO(MSM_GPIO2_PHYS),FOURK_IO(MSM_SIRC_PHYS),X
+ .word FOURK_IO(TLMM_GPIO1_PHYS),X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+#endif
diff --git a/arch/hexagon/kernel/vm_ops.S b/arch/hexagon/kernel/vm_ops.S
new file mode 100644
index 0000000..24d7fca
--- /dev/null
+++ b/arch/hexagon/kernel/vm_ops.S
@@ -0,0 +1,102 @@
+/*
+ * Hexagon VM instruction support
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/linkage.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * C wrappers for virtual machine "instructions". These
+ * could be, and perhaps some day will be, handled as in-line
+ * macros, but for tracing/debugging it's handy to have
+ * a single point of invocation for each of them.
+ * Conveniently, they take paramters and return values
+ * consistent with the ABI calling convention.
+ */
+
+ENTRY(__vmrte)
+ trap1(#HVM_TRAP1_VMRTE);
+ jumpr R31;
+
+ENTRY(__vmsetvec)
+ trap1(#HVM_TRAP1_VMSETVEC);
+ jumpr R31;
+
+ENTRY(__vmsetie)
+ trap1(#HVM_TRAP1_VMSETIE);
+ jumpr R31;
+
+ENTRY(__vmgetie)
+ trap1(#HVM_TRAP1_VMGETIE);
+ jumpr R31;
+
+ENTRY(__vmintop)
+ trap1(#HVM_TRAP1_VMINTOP);
+ jumpr R31;
+
+ENTRY(__vmclrmap)
+ trap1(#HVM_TRAP1_VMCLRMAP);
+ jumpr R31;
+
+ENTRY(__vmnewmap)
+ r1 = #VM_NEWMAP_TYPE_PGTABLES;
+ trap1(#HVM_TRAP1_VMNEWMAP);
+ jumpr R31;
+
+ENTRY(__vmcache)
+ trap1(#HVM_TRAP1_VMCACHE);
+ jumpr R31;
+
+ENTRY(__vmgettime)
+ trap1(#HVM_TRAP1_VMGETTIME);
+ jumpr R31;
+
+ENTRY(__vmsettime)
+ trap1(#HVM_TRAP1_VMSETTIME);
+ jumpr R31;
+
+ENTRY(__vmwait)
+ trap1(#HVM_TRAP1_VMWAIT);
+ jumpr R31;
+
+ENTRY(__vmyield)
+ trap1(#HVM_TRAP1_VMYIELD);
+ jumpr R31;
+
+ENTRY(__vmstart)
+ trap1(#HVM_TRAP1_VMSTART);
+ jumpr R31;
+
+ENTRY(__vmstop)
+ trap1(#HVM_TRAP1_VMSTOP);
+ jumpr R31;
+
+ENTRY(__vmvpid)
+ trap1(#HVM_TRAP1_VMVPID);
+ jumpr R31;
+
+/* Probably not actually going to use these; see vm_entry.S */
+
+ENTRY(__vmsetregs)
+ trap1(#HVM_TRAP1_VMSETREGS);
+ jumpr R31;
+
+ENTRY(__vmgetregs)
+ trap1(#HVM_TRAP1_VMGETREGS);
+ jumpr R31;
diff --git a/arch/hexagon/kernel/vm_switch.S b/arch/hexagon/kernel/vm_switch.S
new file mode 100644
index 0000000..0decf2f
--- /dev/null
+++ b/arch/hexagon/kernel/vm_switch.S
@@ -0,0 +1,95 @@
+/*
+ * Context switch support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <asm/asm-offsets.h>
+
+.text
+
+/*
+ * The register used as a fast-path thread information pointer
+ * is determined as a kernel configuration option. If it happens
+ * to be a callee-save register, we're going to be saving and
+ * restoring it twice here.
+ *
+ * This code anticipates a revised ABI where R20-23 are added
+ * to the set of callee-save registers, but this should be
+ * backward compatible to legacy tools.
+ */
+
+
+/*
+ * void switch_to(struct task_struct *prev,
+ * struct task_struct *next, struct task_struct *last);
+ */
+ .p2align 2
+ .globl __switch_to
+ .type __switch_to, @function
+
+/*
+ * When we exit the wormhole, we need to store the previous task
+ * in the new R0's pointer. Technically it should be R2, but they should
+ * be the same; seems like a legacy thing. In short, don't butcher
+ * R0, let it go back out unmolested.
+ */
+
+__switch_to:
+ /*
+ * Push callee-saves onto "prev" stack.
+ * Here, we're sneaky because the LR and FP
+ * storage of the thread_stack structure
+ * is automagically allocated by allocframe,
+ * so we pass struct size less 8.
+ */
+ allocframe(#(_SWITCH_STACK_SIZE - 8));
+ memd(R29+#(_SWITCH_R2726))=R27:26;
+ memd(R29+#(_SWITCH_R2524))=R25:24;
+ memd(R29+#(_SWITCH_R2322))=R23:22;
+ memd(R29+#(_SWITCH_R2120))=R21:20;
+ memd(R29+#(_SWITCH_R1918))=R19:18;
+ memd(R29+#(_SWITCH_R1716))=R17:16;
+ /* Stash thread_info pointer in task_struct */
+ memw(R0+#_TASK_THREAD_INFO) = THREADINFO_REG;
+ memw(R0 +#(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP)) = R29;
+ /* Switch to "next" stack and restore callee saves from there */
+ R29 = memw(R1 + #(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP));
+ {
+ R27:26 = memd(R29+#(_SWITCH_R2726));
+ R25:24 = memd(R29+#(_SWITCH_R2524));
+ }
+ {
+ R23:22 = memd(R29+#(_SWITCH_R2322));
+ R21:20 = memd(R29+#(_SWITCH_R2120));
+ }
+ {
+ R19:18 = memd(R29+#(_SWITCH_R1918));
+ R17:16 = memd(R29+#(_SWITCH_R1716));
+ }
+ {
+ /* THREADINFO_REG is currently one of the callee-saved regs
+ * above, and so be sure to re-load it last.
+ */
+ THREADINFO_REG = memw(R1 + #_TASK_THREAD_INFO);
+ R31:30 = memd(R29+#_SWITCH_FP);
+ }
+ {
+ R29 = add(R29,#_SWITCH_STACK_SIZE);
+ jumpr R31;
+ }
+ .size __switch_to, .-__switch_to
diff --git a/arch/hexagon/kernel/vm_vectors.S b/arch/hexagon/kernel/vm_vectors.S
new file mode 100644
index 0000000..ce77442
--- /dev/null
+++ b/arch/hexagon/kernel/vm_vectors.S
@@ -0,0 +1,50 @@
+/*
+ * Event jump tables
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <asm/hexagon_vm.h>
+
+.text
+
+/* This is registered early on to allow angel */
+.global _K_provisional_vec
+_K_provisional_vec:
+ jump 1f;
+ jump 1f;
+ jump 1f;
+ jump 1f;
+ jump 1f;
+ trap1(#HVM_TRAP1_VMRTE)
+ jump 1f;
+ jump 1f;
+
+
+.global _K_VM_event_vector
+_K_VM_event_vector:
+1:
+ jump 1b; /* Reset */
+ jump _K_enter_machcheck;
+ jump _K_enter_genex;
+ jump 1b; /* 3 Rsvd */
+ jump 1b; /* 4 Rsvd */
+ jump _K_enter_trap0;
+ jump 1b; /* 6 Rsvd */
+ jump _K_enter_interrupt;
+
+
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 12/36] Hexagon: Export ksyms defined in assembly files.
From: Richard Kuo @ 2011-10-31 23:40 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Linas Vepstas <linas@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/kernel/hexagon_ksyms.c | 42 +++++++++++++++++++++++++++++++++++
1 files changed, 42 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/kernel/hexagon_ksyms.c
diff --git a/arch/hexagon/kernel/hexagon_ksyms.c b/arch/hexagon/kernel/hexagon_ksyms.c
new file mode 100644
index 0000000..3528d05
--- /dev/null
+++ b/arch/hexagon/kernel/hexagon_ksyms.c
@@ -0,0 +1,42 @@
+/*
+ * Export of symbols defined in assembly files and/or libgcc.
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <asm/hexagon_vm.h>
+#include <asm/uaccess.h>
+
+EXPORT_SYMBOL(__copy_from_user_hexagon);
+EXPORT_SYMBOL(__copy_to_user_hexagon);
+EXPORT_SYMBOL(__vmgetie);
+EXPORT_SYMBOL(__vmsetie);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+
+#define DECLARE_EXPORT(name) \
+ extern void name(void); EXPORT_SYMBOL(name)
+
+/* Symbols found in libgcc that assorted kernel modules need */
+DECLARE_EXPORT(__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes);
+
+DECLARE_EXPORT(__hexagon_divsi3);
+DECLARE_EXPORT(__hexagon_modsi3);
+DECLARE_EXPORT(__hexagon_udivsi3);
+DECLARE_EXPORT(__hexagon_umodsi3);
+
+
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 14/36] Hexagon: Add signal functions
From: Richard Kuo @ 2011-10-31 23:41 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Signed-off-by: Linas Vepstas <linas@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/sigcontext.h | 33 +++
arch/hexagon/include/asm/signal.h | 26 +++
arch/hexagon/include/asm/vdso.h | 31 +++
arch/hexagon/kernel/signal.c | 345 +++++++++++++++++++++++++++++++++
arch/hexagon/kernel/trampoline.S | 35 ++++
arch/hexagon/kernel/vdso.c | 101 ++++++++++
6 files changed, 571 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/sigcontext.h
create mode 100644 arch/hexagon/include/asm/signal.h
create mode 100644 arch/hexagon/include/asm/vdso.h
create mode 100644 arch/hexagon/kernel/signal.c
create mode 100644 arch/hexagon/kernel/trampoline.S
create mode 100644 arch/hexagon/kernel/vdso.c
diff --git a/arch/hexagon/include/asm/sigcontext.h b/arch/hexagon/include/asm/sigcontext.h
new file mode 100644
index 0000000..ce6dcd9
--- /dev/null
+++ b/arch/hexagon/include/asm/sigcontext.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SIGCONTEXT_H
+#define _ASM_SIGCONTEXT_H
+
+#include <asm/user.h>
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked. Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+ struct user_regs_struct sc_regs;
+} __aligned(8);
+
+#endif
diff --git a/arch/hexagon/include/asm/signal.h b/arch/hexagon/include/asm/signal.h
new file mode 100644
index 0000000..471c056
--- /dev/null
+++ b/arch/hexagon/include/asm/signal.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SIGNAL_H
+#define _ASM_SIGNAL_H
+
+extern unsigned long __rt_sigtramp_template[2];
+
+#include <asm-generic/signal.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/vdso.h b/arch/hexagon/include/asm/vdso.h
new file mode 100644
index 0000000..2e429a3
--- /dev/null
+++ b/arch/hexagon/include/asm/vdso.h
@@ -0,0 +1,31 @@
+/*
+ * vDSO implementation for Hexagon
+ *
+ * Copyright (c) 2011, Code Aurora Forum. 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 */
+
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c
new file mode 100644
index 0000000..b45be31
--- /dev/null
+++ b/arch/hexagon/kernel/signal.c
@@ -0,0 +1,345 @@
+/*
+ * Signal support for Hexagon processor
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/linkage.h>
+#include <linux/syscalls.h>
+#include <linux/freezer.h>
+#include <linux/tracehook.h>
+#include <asm/registers.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+#include <asm/cacheflush.h>
+#include <asm/signal.h>
+#include <asm/vdso.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+struct rt_sigframe {
+ unsigned long tramp[2];
+ struct siginfo info;
+ struct ucontext uc;
+};
+
+static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+ size_t frame_size)
+{
+ unsigned long sp = regs->r29;
+
+ /* Switch to signal stack if appropriate */
+ if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1));
+}
+
+static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+ unsigned long tmp;
+ int err = 0;
+
+ err |= copy_to_user(&sc->sc_regs.r0, ®s->r00,
+ 32*sizeof(unsigned long));
+
+ err |= __put_user(regs->sa0, &sc->sc_regs.sa0);
+ err |= __put_user(regs->lc0, &sc->sc_regs.lc0);
+ err |= __put_user(regs->sa1, &sc->sc_regs.sa1);
+ err |= __put_user(regs->lc1, &sc->sc_regs.lc1);
+ err |= __put_user(regs->m0, &sc->sc_regs.m0);
+ err |= __put_user(regs->m1, &sc->sc_regs.m1);
+ err |= __put_user(regs->usr, &sc->sc_regs.usr);
+ err |= __put_user(regs->preds, &sc->sc_regs.p3_0);
+ err |= __put_user(regs->gp, &sc->sc_regs.gp);
+ err |= __put_user(regs->ugp, &sc->sc_regs.ugp);
+
+ tmp = pt_elr(regs); err |= __put_user(tmp, &sc->sc_regs.pc);
+ tmp = pt_cause(regs); err |= __put_user(tmp, &sc->sc_regs.cause);
+ tmp = pt_badva(regs); err |= __put_user(tmp, &sc->sc_regs.badva);
+
+ return err;
+}
+
+static int restore_sigcontext(struct pt_regs *regs,
+ struct sigcontext __user *sc)
+{
+ unsigned long tmp;
+ int err = 0;
+
+ err |= copy_from_user(®s->r00, &sc->sc_regs.r0,
+ 32 * sizeof(unsigned long));
+
+ err |= __get_user(regs->sa0, &sc->sc_regs.sa0);
+ err |= __get_user(regs->lc0, &sc->sc_regs.lc0);
+ err |= __get_user(regs->sa1, &sc->sc_regs.sa1);
+ err |= __get_user(regs->lc1, &sc->sc_regs.lc1);
+ err |= __get_user(regs->m0, &sc->sc_regs.m0);
+ err |= __get_user(regs->m1, &sc->sc_regs.m1);
+ err |= __get_user(regs->usr, &sc->sc_regs.usr);
+ err |= __get_user(regs->preds, &sc->sc_regs.p3_0);
+ err |= __get_user(regs->gp, &sc->sc_regs.gp);
+ err |= __get_user(regs->ugp, &sc->sc_regs.ugp);
+
+ err |= __get_user(tmp, &sc->sc_regs.pc); pt_set_elr(regs, tmp);
+
+ return err;
+}
+
+/*
+ * Setup signal stack frame with siginfo structure
+ */
+static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
+{
+ int err = 0;
+ struct rt_sigframe __user *frame;
+ struct hexagon_vdso *vdso = current->mm->context.vdso;
+
+ frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe)))
+ goto sigsegv;
+
+ if (copy_siginfo_to_user(&frame->info, info))
+ goto sigsegv;
+
+ /* The on-stack signal trampoline is no longer executed;
+ * however, the libgcc signal frame unwinding code checks for
+ * the presence of these two numeric magic values.
+ */
+ err |= __put_user(0x7800d166, &frame->tramp[0]);
+ err |= __put_user(0x5400c004, &frame->tramp[1]);
+ err |= setup_sigcontext(regs, &frame->uc.uc_mcontext);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ if (err)
+ goto sigsegv;
+
+ /* Load r0/r1 pair with signumber/siginfo pointer... */
+ regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32)
+ | (unsigned long long)signr;
+ regs->r02 = (unsigned long) &frame->uc;
+ regs->r31 = (unsigned long) vdso->rt_signal_trampoline;
+ pt_psp(regs) = (unsigned long) frame;
+ pt_set_elr(regs, (unsigned long)ka->sa.sa_handler);
+
+ return 0;
+
+sigsegv:
+ force_sigsegv(signr, current);
+ return -EFAULT;
+}
+
+/*
+ * Setup invocation of signal handler
+ */
+static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
+ sigset_t *oldset, struct pt_regs *regs)
+{
+ int rc;
+
+ /*
+ * If we're handling a signal that aborted a system call,
+ * set up the error return value before adding the signal
+ * frame to the stack.
+ */
+
+ if (regs->syscall_nr >= 0) {
+ switch (regs->r00) {
+ case -ERESTART_RESTARTBLOCK:
+ case -ERESTARTNOHAND:
+ regs->r00 = -EINTR;
+ break;
+ case -ERESTARTSYS:
+ if (!(ka->sa.sa_flags & SA_RESTART)) {
+ regs->r00 = -EINTR;
+ break;
+ }
+ /* Fall through */
+ case -ERESTARTNOINTR:
+ regs->r06 = regs->syscall_nr;
+ pt_set_elr(regs, pt_elr(regs) - 4);
+ regs->r00 = regs->restart_r0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Set up the stack frame; not doing the SA_SIGINFO thing. We
+ * only set up the rt_frame flavor.
+ */
+ rc = setup_rt_frame(sig, ka, info, oldset, regs);
+
+ /* If there was an error on setup, no signal was delivered. */
+ if (rc)
+ return rc;
+
+ spin_lock_irq(¤t->sighand->siglock);
+ sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(¤t->blocked, sig);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ return 0;
+}
+
+/*
+ * Called from return-from-event code.
+ */
+static void do_signal(struct pt_regs *regs)
+{
+ struct k_sigaction sigact;
+ siginfo_t info;
+ int signo;
+
+ if (!user_mode(regs))
+ return;
+
+ if (try_to_freeze())
+ goto no_signal;
+
+ signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
+
+ if (signo > 0) {
+ sigset_t *oldset;
+
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = ¤t->saved_sigmask;
+ else
+ oldset = ¤t->blocked;
+
+ if (handle_signal(signo, &info, &sigact, oldset, regs) == 0) {
+ /*
+ * Successful delivery case. The saved sigmask is
+ * stored in the signal frame, and will be restored
+ * by sigreturn. We can clear the TIF flag.
+ */
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+ tracehook_signal_handler(signo, &info, &sigact, regs,
+ test_thread_flag(TIF_SINGLESTEP));
+ }
+ return;
+ }
+
+no_signal:
+ /*
+ * If we came from a system call, handle the restart.
+ */
+ if (regs->syscall_nr >= 0) {
+ switch (regs->r00) {
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ regs->r06 = regs->syscall_nr;
+ break;
+ case -ERESTART_RESTARTBLOCK:
+ regs->r06 = __NR_restart_syscall;
+ break;
+ default:
+ goto no_restart;
+ }
+ pt_set_elr(regs, pt_elr(regs) - 4);
+ regs->r00 = regs->restart_r0;
+ }
+
+no_restart:
+ /* If there's no signal to deliver, put the saved sigmask back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
+ }
+}
+
+void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
+{
+ if (thread_info_flags & _TIF_SIGPENDING)
+ do_signal(regs);
+
+ if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+ clear_thread_flag(TIF_NOTIFY_RESUME);
+ if (current->replacement_session_keyring)
+ key_replace_session_keyring();
+ }
+}
+
+/*
+ * Architecture-specific wrappers for signal-related system calls
+ */
+asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+{
+ struct pt_regs *regs = current_thread_info()->regs;
+
+ return do_sigaltstack(uss, uoss, regs->r29);
+}
+
+asmlinkage int sys_rt_sigreturn(void)
+{
+ struct pt_regs *regs = current_thread_info()->regs;
+ struct rt_sigframe __user *frame;
+ sigset_t blocked;
+
+ frame = (struct rt_sigframe __user *)pt_psp(regs);
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked)))
+ goto badframe;
+
+ sigdelsetmask(&blocked, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+ current->blocked = blocked;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+ goto badframe;
+
+ /* Restore the user's stack as well */
+ pt_psp(regs) = regs->r29;
+
+ /*
+ * Leave a trace in the stack frame that this was a sigreturn.
+ * If the system call is to replay, we've already restored the
+ * number in the GPR slot and it will be regenerated on the
+ * new system call trap entry. Note that if restore_sigcontext()
+ * did something other than a bulk copy of the pt_regs struct,
+ * we could avoid this assignment by simply not overwriting
+ * regs->syscall_nr.
+ */
+ regs->syscall_nr = __NR_rt_sigreturn;
+
+ /*
+ * If we were meticulous, we'd only call this if we knew that
+ * we were actually going to use an alternate stack, and we'd
+ * consider any error to be fatal. What we do here, in common
+ * with many other architectures, is call it blindly and only
+ * consider the -EFAULT return case to be proof of a problem.
+ */
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, pt_psp(regs)) == -EFAULT)
+ goto badframe;
+
+ return 0;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
diff --git a/arch/hexagon/kernel/trampoline.S b/arch/hexagon/kernel/trampoline.S
new file mode 100644
index 0000000..06c36c0
--- /dev/null
+++ b/arch/hexagon/kernel/trampoline.S
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+/*
+ * Trampoline sequences to be copied onto user stack.
+ * This consumes a little more space than hand-assembling
+ * immediate constants for use in C, but is more portable
+ * to future tweaks to the Hexagon instruction set.
+ */
+
+#include <asm/unistd.h>
+
+/* Sig trampolines - call sys_sigreturn or sys_rt_sigreturn as appropriate */
+
+/* plain sigreturn is gone. */
+
+ .globl __rt_sigtramp_template
+__rt_sigtramp_template:
+ r6 = #__NR_rt_sigreturn;
+ trap0(#1);
diff --git a/arch/hexagon/kernel/vdso.c b/arch/hexagon/kernel/vdso.c
new file mode 100644
index 0000000..5ae4134
--- /dev/null
+++ b/arch/hexagon/kernel/vdso.c
@@ -0,0 +1,101 @@
+/*
+ * vDSO implementation for Hexagon
+ *
+ * Copyright (c) 2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+
+#include <asm/vdso.h>
+
+static struct page *vdso_page;
+
+/* Create a vDSO page holding the signal trampoline.
+ * We want this for a non-executable stack.
+ */
+static int __init vdso_init(void)
+{
+ struct hexagon_vdso *vdso;
+
+ vdso_page = alloc_page(GFP_KERNEL);
+ if (!vdso_page)
+ panic("Cannot allocate vdso");
+
+ vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
+ if (!vdso)
+ panic("Cannot map vdso");
+ clear_page(vdso);
+
+ /* Install the signal trampoline; currently looks like this:
+ * r6 = #__NR_rt_sigreturn;
+ * trap0(#1);
+ */
+ vdso->rt_signal_trampoline[0] = __rt_sigtramp_template[0];
+ vdso->rt_signal_trampoline[1] = __rt_sigtramp_template[1];
+
+ vunmap(vdso);
+
+ return 0;
+}
+arch_initcall(vdso_init);
+
+/*
+ * Called from binfmt_elf. Create a VMA for the vDSO page.
+ */
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+ int ret;
+ unsigned long vdso_base;
+ struct mm_struct *mm = current->mm;
+
+ down_write(&mm->mmap_sem);
+
+ /* Try to get it loaded right near ld.so/glibc. */
+ vdso_base = STACK_TOP;
+
+ vdso_base = get_unmapped_area(NULL, vdso_base, PAGE_SIZE, 0, 0);
+ if (IS_ERR_VALUE(vdso_base)) {
+ ret = vdso_base;
+ goto up_fail;
+ }
+
+ /* MAYWRITE to allow gdb to COW and set breakpoints. */
+ ret = install_special_mapping(mm, vdso_base, PAGE_SIZE,
+ VM_READ|VM_EXEC|
+ VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+ VM_ALWAYSDUMP,
+ &vdso_page);
+
+ if (ret)
+ goto up_fail;
+
+ mm->context.vdso = (void *)vdso_base;
+
+up_fail:
+ up_write(&mm->mmap_sem);
+ return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+ if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+ return "[vdso]";
+ return NULL;
+}
+
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 18/36] Hexagon: Add time and timer functions
From: Richard Kuo @ 2011-10-31 23:43 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/time.h | 29 ++++
arch/hexagon/include/asm/timer-regs.h | 39 +++++
arch/hexagon/kernel/time.c | 250 +++++++++++++++++++++++++++++++++
3 files changed, 318 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/time.h
create mode 100644 arch/hexagon/include/asm/timer-regs.h
create mode 100644 arch/hexagon/kernel/time.c
diff --git a/arch/hexagon/include/asm/time.h b/arch/hexagon/include/asm/time.h
new file mode 100644
index 0000000..081b82c
--- /dev/null
+++ b/arch/hexagon/include/asm/time.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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
diff --git a/arch/hexagon/include/asm/timer-regs.h b/arch/hexagon/include/asm/timer-regs.h
new file mode 100644
index 0000000..d80db23
--- /dev/null
+++ b/arch/hexagon/include/asm/timer-regs.h
@@ -0,0 +1,39 @@
+/*
+ * Timer support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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
diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c
new file mode 100644
index 0000000..6bee15c
--- /dev/null
+++ b/arch/hexagon/kernel/time.c
@@ -0,0 +1,250 @@
+/*
+ * Time related functions for Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/timer-regs.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * For the clocksource we need:
+ * pcycle frequency (600MHz)
+ * For the loops_per_jiffy we need:
+ * thread/cpu frequency (100MHz)
+ * And for the timer, we need:
+ * sleep clock rate
+ */
+
+cycles_t pcycle_freq_mhz;
+cycles_t thread_freq_mhz;
+cycles_t sleep_clk_freq;
+
+static struct resource rtos_timer_resources[] = {
+ {
+ .start = RTOS_TIMER_REGS_ADDR,
+ .end = RTOS_TIMER_REGS_ADDR+PAGE_SIZE-1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rtos_timer_device = {
+ .name = "rtos_timer",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtos_timer_resources),
+ .resource = rtos_timer_resources,
+};
+
+/* A lot of this stuff should move into a platform specific section. */
+struct adsp_hw_timer_struct {
+ u32 match; /* Match value */
+ u32 count;
+ u32 enable; /* [1] - CLR_ON_MATCH_EN, [0] - EN */
+ u32 clear; /* one-shot register that clears the count */
+};
+
+/* Look for "TCX0" for related constants. */
+static __iomem struct adsp_hw_timer_struct *rtos_timer;
+
+static cycle_t timer_get_cycles(struct clocksource *cs)
+{
+ return (cycle_t) __vmgettime();
+}
+
+static struct clocksource hexagon_clocksource = {
+ .name = "pcycles",
+ .rating = 250,
+ .read = timer_get_cycles,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int set_next_event(unsigned long delta, struct clock_event_device *evt)
+{
+ /* Assuming the timer will be disabled when we enter here. */
+
+ iowrite32(1, &rtos_timer->clear);
+ iowrite32(0, &rtos_timer->clear);
+
+ iowrite32(delta, &rtos_timer->match);
+ iowrite32(1 << TIMER_ENABLE, &rtos_timer->enable);
+ return 0;
+}
+
+/*
+ * Sets the mode (periodic, shutdown, oneshot, etc) of a timer.
+ */
+static void set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ /* XXX implement me */
+ default:
+ break;
+ }
+}
+
+#ifdef CONFIG_SMP
+/* Broadcast mechanism */
+static void broadcast(const struct cpumask *mask)
+{
+ send_ipi(mask, IPI_TIMER);
+}
+#endif
+
+static struct clock_event_device hexagon_clockevent_dev = {
+ .name = "clockevent",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 400,
+ .irq = RTOS_TIMER_INT,
+ .set_next_event = set_next_event,
+ .set_mode = set_mode,
+#ifdef CONFIG_SMP
+ .broadcast = broadcast,
+#endif
+};
+
+#ifdef CONFIG_SMP
+static DEFINE_PER_CPU(struct clock_event_device, clock_events);
+
+void setup_percpu_clockdev(void)
+{
+ int cpu = smp_processor_id();
+ struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+ struct clock_event_device *dummy_clock_dev =
+ &per_cpu(clock_events, cpu);
+
+ memcpy(dummy_clock_dev, ce_dev, sizeof(*dummy_clock_dev));
+ INIT_LIST_HEAD(&dummy_clock_dev->list);
+
+ dummy_clock_dev->features = CLOCK_EVT_FEAT_DUMMY;
+ dummy_clock_dev->cpumask = cpumask_of(cpu);
+ dummy_clock_dev->mode = CLOCK_EVT_MODE_UNUSED;
+
+ clockevents_register_device(dummy_clock_dev);
+}
+
+/* Called from smp.c for each CPU's timer ipi call */
+void ipi_timer(void)
+{
+ int cpu = smp_processor_id();
+ struct clock_event_device *ce_dev = &per_cpu(clock_events, cpu);
+
+ ce_dev->event_handler(ce_dev);
+}
+#endif /* CONFIG_SMP */
+
+static irqreturn_t timer_interrupt(int irq, void *devid)
+{
+ struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+
+ iowrite32(0, &rtos_timer->enable);
+ ce_dev->event_handler(ce_dev);
+
+ return IRQ_HANDLED;
+}
+
+/* This should also be pulled from devtree */
+static struct irqaction rtos_timer_intdesc = {
+ .handler = timer_interrupt,
+ .flags = IRQF_TIMER | IRQF_TRIGGER_RISING,
+ .name = "rtos_timer"
+};
+
+/*
+ * time_init_deferred - called by start_kernel to set up timer/clock source
+ *
+ * Install the IRQ handler for the clock, setup timers.
+ * This is done late, as that way, we can use ioremap().
+ *
+ * This runs just before the delay loop is calibrated, and
+ * is used for delay calibration.
+ */
+void __init time_init_deferred(void)
+{
+ struct resource *resource = NULL;
+ struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+ struct device_node *dn;
+ struct resource r;
+ int err;
+
+ ce_dev->cpumask = cpu_all_mask;
+
+ if (!resource)
+ resource = rtos_timer_device.resource;
+
+ /* ioremap here means this has to run later, after paging init */
+ rtos_timer = ioremap(resource->start, resource->end
+ - resource->start + 1);
+
+ if (!rtos_timer) {
+ release_mem_region(resource->start, resource->end
+ - resource->start + 1);
+ }
+ clocksource_register_khz(&hexagon_clocksource, pcycle_freq_mhz * 1000);
+
+ /* Note: the sim generic RTOS clock is apparently really 18750Hz */
+
+ /*
+ * Last arg is some guaranteed seconds for which the conversion will
+ * work without overflow.
+ */
+ clockevents_calc_mult_shift(ce_dev, sleep_clk_freq, 4);
+
+ ce_dev->max_delta_ns = clockevent_delta2ns(0x7fffffff, ce_dev);
+ ce_dev->min_delta_ns = clockevent_delta2ns(0xf, ce_dev);
+
+#ifdef CONFIG_SMP
+ setup_percpu_clockdev();
+#endif
+
+ clockevents_register_device(ce_dev);
+ setup_irq(ce_dev->irq, &rtos_timer_intdesc);
+}
+
+void __init time_init(void)
+{
+ late_time_init = time_init_deferred;
+}
+
+/*
+ * This could become parametric or perhaps even computed at run-time,
+ * but for now we take the observed simulator jitter.
+ */
+static long long fudgefactor = 350; /* Maybe lower if kernel optimized. */
+
+void __udelay(unsigned long usecs)
+{
+ unsigned long long start = __vmgettime();
+ unsigned long long finish = (pcycle_freq_mhz * usecs) - fudgefactor;
+
+ while ((__vmgettime() - start) < finish)
+ cpu_relax(); /* not sure how this improves readability */
+}
+EXPORT_SYMBOL(__udelay);
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 19/36] Hexagon: Add ptrace support
From: Richard Kuo @ 2011-10-31 23:43 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Signed-off-by: Linas Vepstas <linas@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/ptrace.h | 35 +++++++
arch/hexagon/kernel/ptrace.c | 180 +++++++++++++++++++++++++++++++++++++
2 files changed, 215 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/ptrace.h
create mode 100644 arch/hexagon/kernel/ptrace.c
diff --git a/arch/hexagon/include/asm/ptrace.h b/arch/hexagon/include/asm/ptrace.h
new file mode 100644
index 0000000..3d2f607
--- /dev/null
+++ b/arch/hexagon/include/asm/ptrace.h
@@ -0,0 +1,35 @@
+/*
+ * Ptrace definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PTRACE_H
+#define _ASM_PTRACE_H
+
+#include <asm/registers.h>
+
+#define instruction_pointer(regs) pt_elr(regs)
+#define user_stack_pointer(regs) ((regs)->r29)
+
+#define profile_pc(regs) instruction_pointer(regs)
+
+/* kprobe-based event tracer support */
+extern int regs_query_register_offset(const char *name);
+extern const char *regs_query_register_name(unsigned int offset);
+
+#endif
diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c
new file mode 100644
index 0000000..bea3f08
--- /dev/null
+++ b/arch/hexagon/kernel/ptrace.c
@@ -0,0 +1,180 @@
+/*
+ * Ptrace support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <generated/compile.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/regset.h>
+#include <linux/user.h>
+
+#include <asm/system.h>
+#include <asm/user.h>
+
+static int genregs_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+ unsigned int dummy;
+ struct pt_regs *regs = task_pt_regs(target);
+
+
+ if (!regs)
+ return -EIO;
+
+ /* The general idea here is that the copyout must happen in
+ * exactly the same order in which the userspace expects these
+ * regs. Now, the sequence in userspace does not match the
+ * sequence in the kernel, so everything past the 32 gprs
+ * happens one at a time.
+ */
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ ®s->r00, 0, 32*sizeof(unsigned long));
+
+#define ONEXT(KPT_REG, USR_REG) \
+ if (!ret) \
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, \
+ KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
+ offsetof(struct user_regs_struct, USR_REG) + \
+ sizeof(unsigned long));
+
+ /* Must be exactly same sequence as struct user_regs_struct */
+ ONEXT(®s->sa0, sa0);
+ ONEXT(®s->lc0, lc0);
+ ONEXT(®s->sa1, sa1);
+ ONEXT(®s->lc1, lc1);
+ ONEXT(®s->m0, m0);
+ ONEXT(®s->m1, m1);
+ ONEXT(®s->usr, usr);
+ ONEXT(®s->preds, p3_0);
+ ONEXT(®s->gp, gp);
+ ONEXT(®s->ugp, ugp);
+ ONEXT(&pt_elr(regs), pc);
+ dummy = pt_cause(regs);
+ ONEXT(&dummy, cause);
+ ONEXT(&pt_badva(regs), badva);
+
+ /* Pad the rest with zeros, if needed */
+ if (!ret)
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ offsetof(struct user_regs_struct, pad1), -1);
+ return ret;
+}
+
+static int genregs_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+ unsigned long bucket;
+ struct pt_regs *regs = task_pt_regs(target);
+
+ if (!regs)
+ return -EIO;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ ®s->r00, 0, 32*sizeof(unsigned long));
+
+#define INEXT(KPT_REG, USR_REG) \
+ if (!ret) \
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
+ KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
+ offsetof(struct user_regs_struct, USR_REG) + \
+ sizeof(unsigned long));
+
+ /* Must be exactly same sequence as struct user_regs_struct */
+ INEXT(®s->sa0, sa0);
+ INEXT(®s->lc0, lc0);
+ INEXT(®s->sa1, sa1);
+ INEXT(®s->lc1, lc1);
+ INEXT(®s->m0, m0);
+ INEXT(®s->m1, m1);
+ INEXT(®s->usr, usr);
+ INEXT(®s->preds, p3_0);
+ INEXT(®s->gp, gp);
+ INEXT(®s->ugp, ugp);
+ INEXT(&pt_elr(regs), pc);
+
+ /* CAUSE and BADVA aren't writeable. */
+ INEXT(&bucket, cause);
+ INEXT(&bucket, badva);
+
+ /* Ignore the rest, if needed */
+ if (!ret)
+ ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ offsetof(struct user_regs_struct, pad1), -1);
+
+ if (ret)
+ return ret;
+
+ /*
+ * This is special; SP is actually restored by the VM via the
+ * special event record which is set by the special trap.
+ */
+ regs->hvmer.vmpsp = regs->r29;
+ return 0;
+}
+
+enum hexagon_regset {
+ REGSET_GENERAL,
+};
+
+static const struct user_regset hexagon_regsets[] = {
+ [REGSET_GENERAL] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = ELF_NGREG,
+ .size = sizeof(unsigned long),
+ .align = sizeof(unsigned long),
+ .get = genregs_get,
+ .set = genregs_set,
+ },
+};
+
+static const struct user_regset_view hexagon_user_view = {
+ .name = UTS_MACHINE,
+ .e_machine = ELF_ARCH,
+ .ei_osabi = ELF_OSABI,
+ .regsets = hexagon_regsets,
+ .n = ARRAY_SIZE(hexagon_regsets)
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+ return &hexagon_user_view;
+}
+
+void ptrace_disable(struct task_struct *child)
+{
+ /* Boilerplate - resolves to null inline if no HW single-step */
+ user_disable_single_step(child);
+}
+
+long arch_ptrace(struct task_struct *child, long request,
+ unsigned long addr, unsigned long data)
+{
+ return ptrace_request(child, request, addr, data);
+}
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 21/36] Hexagon: Add SMP support
From: Richard Kuo @ 2011-10-31 23:46 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Signed-off-by: Linas Vepstas <linas@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/hexagon/include/asm/smp.h | 44 +++++++
arch/hexagon/kernel/smp.c | 276 ++++++++++++++++++++++++++++++++++++++++
arch/hexagon/kernel/topology.c | 52 ++++++++
3 files changed, 372 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/smp.h
create mode 100644 arch/hexagon/kernel/smp.c
create mode 100644 arch/hexagon/kernel/topology.c
diff --git a/arch/hexagon/include/asm/smp.h b/arch/hexagon/include/asm/smp.h
new file mode 100644
index 0000000..87c869a
--- /dev/null
+++ b/arch/hexagon/include/asm/smp.h
@@ -0,0 +1,44 @@
+/*
+ * SMP definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
+
+#include <linux/cpumask.h>
+
+#define raw_smp_processor_id() (current_thread_info()->cpu)
+
+enum ipi_message_type {
+ IPI_NOP = 0,
+ IPI_RESCHEDULE = 1,
+ IPI_CALL_FUNC,
+ IPI_CALL_FUNC_SINGLE,
+ IPI_CPU_STOP,
+ IPI_TIMER,
+};
+
+extern void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg);
+extern void smp_start_cpus(void);
+extern void arch_send_call_function_single_ipi(int cpu);
+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+
+extern void smp_vm_unmask_irq(void *info);
+
+#endif
diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c
new file mode 100644
index 0000000..c871a2c
--- /dev/null
+++ b/arch/hexagon/kernel/smp.c
@@ -0,0 +1,276 @@
+/*
+ * SMP support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+
+#include <asm/system.h> /* xchg */
+#include <asm/time.h> /* timer_interrupt */
+#include <asm/hexagon_vm.h>
+
+#define BASE_IPI_IRQ 26
+
+/*
+ * cpu_possible_map needs to be filled out prior to setup_per_cpu_areas
+ * (which is prior to any of our smp_prepare_cpu crap), in order to set
+ * up the... per_cpu areas.
+ */
+
+struct ipi_data {
+ unsigned long bits;
+};
+
+static DEFINE_PER_CPU(struct ipi_data, ipi_data);
+
+static inline void __handle_ipi(unsigned long *ops, struct ipi_data *ipi,
+ int cpu)
+{
+ unsigned long msg = 0;
+ do {
+ msg = find_next_bit(ops, BITS_PER_LONG, msg+1);
+
+ switch (msg) {
+
+ case IPI_TIMER:
+ ipi_timer();
+ break;
+
+ case IPI_CALL_FUNC:
+ generic_smp_call_function_interrupt();
+ break;
+
+ case IPI_CALL_FUNC_SINGLE:
+ generic_smp_call_function_single_interrupt();
+ break;
+
+ case IPI_CPU_STOP:
+ /*
+ * call vmstop()
+ */
+ __vmstop();
+ break;
+
+ case IPI_RESCHEDULE:
+ scheduler_ipi();
+ break;
+ }
+ } while (msg < BITS_PER_LONG);
+}
+
+/* Used for IPI call from other CPU's to unmask int */
+void smp_vm_unmask_irq(void *info)
+{
+ __vmintop_locen((long) info);
+}
+
+
+/*
+ * This is based on Alpha's IPI stuff.
+ * Supposed to take (int, void*) as args now.
+ * Specifically, first arg is irq, second is the irq_desc.
+ */
+
+irqreturn_t handle_ipi(int irq, void *desc)
+{
+ int cpu = smp_processor_id();
+ struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+ unsigned long ops;
+
+ while ((ops = xchg(&ipi->bits, 0)) != 0)
+ __handle_ipi(&ops, ipi, cpu);
+ return IRQ_HANDLED;
+}
+
+void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg)
+{
+ unsigned long flags;
+ unsigned long cpu;
+ unsigned long retval;
+
+ local_irq_save(flags);
+
+ for_each_cpu(cpu, cpumask) {
+ struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+
+ set_bit(msg, &ipi->bits);
+ /* Possible barrier here */
+ retval = __vmintop_post(BASE_IPI_IRQ+cpu);
+
+ if (retval != 0) {
+ printk(KERN_ERR "interrupt %ld not configured?\n",
+ BASE_IPI_IRQ+cpu);
+ }
+ }
+
+ local_irq_restore(flags);
+}
+
+static struct irqaction ipi_intdesc = {
+ .handler = handle_ipi,
+ .flags = IRQF_TRIGGER_RISING,
+ .name = "ipi_handler"
+};
+
+void __init smp_prepare_boot_cpu(void)
+{
+}
+
+/*
+ * interrupts should already be disabled from the VM
+ * SP should already be correct; need to set THREADINFO_REG
+ * to point to current thread info
+ */
+
+void __cpuinit start_secondary(void)
+{
+ unsigned int cpu;
+ unsigned long thread_ptr;
+
+ /* Calculate thread_info pointer from stack pointer */
+ __asm__ __volatile__(
+ "%0 = SP;\n"
+ : "=r" (thread_ptr)
+ );
+
+ thread_ptr = thread_ptr & ~(THREAD_SIZE-1);
+
+ __asm__ __volatile__(
+ QUOTED_THREADINFO_REG " = %0;\n"
+ :
+ : "r" (thread_ptr)
+ );
+
+ /* Set the memory struct */
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+
+ cpu = smp_processor_id();
+
+ setup_irq(BASE_IPI_IRQ + cpu, &ipi_intdesc);
+
+ /* Register the clock_event dummy */
+ setup_percpu_clockdev();
+
+ printk(KERN_INFO "%s cpu %d\n", __func__, current_thread_info()->cpu);
+
+ set_cpu_online(cpu, true);
+ while (!cpumask_test_cpu(cpu, cpu_active_mask))
+ cpu_relax();
+ local_irq_enable();
+
+ cpu_idle();
+}
+
+
+/*
+ * called once for each present cpu
+ * apparently starts up the CPU and then
+ * maintains control until "cpu_online(cpu)" is set.
+ */
+
+int __cpuinit __cpu_up(unsigned int cpu)
+{
+ struct task_struct *idle;
+ struct thread_info *thread;
+ void *stack_start;
+
+ /* Create new init task for the CPU */
+ idle = fork_idle(cpu);
+ if (IS_ERR(idle))
+ panic(KERN_ERR "fork_idle failed\n");
+
+ thread = (struct thread_info *)idle->stack;
+ thread->cpu = cpu;
+
+ /* Boot to the head. */
+ stack_start = ((void *) thread) + THREAD_SIZE;
+ __vmstart(start_secondary, stack_start);
+
+ while (!cpu_isset(cpu, cpu_online_map))
+ barrier();
+
+ return 0;
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+ int i;
+
+ /*
+ * should eventually have some sort of machine
+ * descriptor that has this stuff
+ */
+
+ /* Right now, let's just fake it. */
+ for (i = 0; i < max_cpus; i++)
+ cpu_set(i, cpu_present_map);
+
+ /* Also need to register the interrupts for IPI */
+ if (max_cpus > 1)
+ setup_irq(BASE_IPI_IRQ, &ipi_intdesc);
+}
+
+void smp_send_reschedule(int cpu)
+{
+ send_ipi(cpumask_of(cpu), IPI_RESCHEDULE);
+}
+
+void smp_send_stop(void)
+{
+ struct cpumask targets;
+ cpumask_copy(&targets, cpu_online_mask);
+ cpumask_clear_cpu(smp_processor_id(), &targets);
+ send_ipi(&targets, IPI_CPU_STOP);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+ send_ipi(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+}
+
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+ send_ipi(mask, IPI_CALL_FUNC);
+}
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+ return -EINVAL;
+}
+
+void smp_start_cpus(void)
+{
+ int i;
+
+ for (i = 0; i < NR_CPUS; i++)
+ cpu_set(i, cpu_possible_map);
+}
diff --git a/arch/hexagon/kernel/topology.c b/arch/hexagon/kernel/topology.c
new file mode 100644
index 0000000..ba44751
--- /dev/null
+++ b/arch/hexagon/kernel/topology.c
@@ -0,0 +1,52 @@
+/*
+ * CPU topology for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+#include <linux/percpu.h>
+
+/* Swiped from MIPS. */
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static int __init topology_init(void)
+{
+ int i, ret;
+
+ for_each_present_cpu(i) {
+
+ /*
+ * register_cpu takes a per_cpu pointer and
+ * just points it at another per_cpu struct...
+ */
+
+ ret = register_cpu(&per_cpu(cpu_devices, i), i);
+ if (ret)
+ printk(KERN_WARNING "topology_init: register_cpu %d "
+ "failed (%d)\n", i, ret);
+ }
+
+ return 0;
+}
+
+subsys_initcall(topology_init);
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 22/36] Hexagon: Add locking types and functions
From: Richard Kuo @ 2011-10-31 23:47 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/spinlock.h | 186 +++++++++++++++++++++++++++++
arch/hexagon/include/asm/spinlock_types.h | 42 +++++++
include/asm-generic/rwsem.h | 132 ++++++++++++++++++++
3 files changed, 360 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/spinlock.h
create mode 100644 arch/hexagon/include/asm/spinlock_types.h
create mode 100644 include/asm-generic/rwsem.h
diff --git a/arch/hexagon/include/asm/spinlock.h b/arch/hexagon/include/asm/spinlock.h
new file mode 100644
index 0000000..168a920
--- /dev/null
+++ b/arch/hexagon/include/asm/spinlock.h
@@ -0,0 +1,186 @@
+/*
+ * Spinlock support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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
diff --git a/arch/hexagon/include/asm/spinlock_types.h b/arch/hexagon/include/asm/spinlock_types.h
new file mode 100644
index 0000000..5e937af
--- /dev/null
+++ b/arch/hexagon/include/asm/spinlock_types.h
@@ -0,0 +1,42 @@
+/*
+ * Spinlock support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SPINLOCK_TYPES_H
+#define _ASM_SPINLOCK_TYPES_H
+
+#include <linux/version.h>
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned int lock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile unsigned int lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCK_UNLOCKED { 0 }
+
+#endif
diff --git a/include/asm-generic/rwsem.h b/include/asm-generic/rwsem.h
new file mode 100644
index 0000000..bb1e2cd
--- /dev/null
+++ b/include/asm-generic/rwsem.h
@@ -0,0 +1,132 @@
+#ifndef _ASM_POWERPC_RWSEM_H
+#define _ASM_POWERPC_RWSEM_H
+
+#ifndef _LINUX_RWSEM_H
+#error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead."
+#endif
+
+#ifdef __KERNEL__
+
+/*
+ * R/W semaphores for PPC using the stuff in lib/rwsem.c.
+ * Adapted largely from include/asm-i386/rwsem.h
+ * by Paul Mackerras <paulus@samba.org>.
+ */
+
+/*
+ * the semaphore definition
+ */
+#ifdef CONFIG_PPC64
+# define RWSEM_ACTIVE_MASK 0xffffffffL
+#else
+# define RWSEM_ACTIVE_MASK 0x0000ffffL
+#endif
+
+#define RWSEM_UNLOCKED_VALUE 0x00000000L
+#define RWSEM_ACTIVE_BIAS 0x00000001L
+#define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1)
+#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+
+/*
+ * lock for reading
+ */
+static inline void __down_read(struct rw_semaphore *sem)
+{
+ if (unlikely(atomic_long_inc_return((atomic_long_t *)&sem->count) <= 0))
+ rwsem_down_read_failed(sem);
+}
+
+static inline int __down_read_trylock(struct rw_semaphore *sem)
+{
+ long tmp;
+
+ while ((tmp = sem->count) >= 0) {
+ if (tmp == cmpxchg(&sem->count, tmp,
+ tmp + RWSEM_ACTIVE_READ_BIAS)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * lock for writing
+ */
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+{
+ long tmp;
+
+ tmp = atomic_long_add_return(RWSEM_ACTIVE_WRITE_BIAS,
+ (atomic_long_t *)&sem->count);
+ if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS))
+ rwsem_down_write_failed(sem);
+}
+
+static inline void __down_write(struct rw_semaphore *sem)
+{
+ __down_write_nested(sem, 0);
+}
+
+static inline int __down_write_trylock(struct rw_semaphore *sem)
+{
+ long tmp;
+
+ tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
+ RWSEM_ACTIVE_WRITE_BIAS);
+ return tmp == RWSEM_UNLOCKED_VALUE;
+}
+
+/*
+ * unlock after reading
+ */
+static inline void __up_read(struct rw_semaphore *sem)
+{
+ long tmp;
+
+ tmp = atomic_long_dec_return((atomic_long_t *)&sem->count);
+ if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0))
+ rwsem_wake(sem);
+}
+
+/*
+ * unlock after writing
+ */
+static inline void __up_write(struct rw_semaphore *sem)
+{
+ if (unlikely(atomic_long_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
+ (atomic_long_t *)&sem->count) < 0))
+ rwsem_wake(sem);
+}
+
+/*
+ * implement atomic add functionality
+ */
+static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
+{
+ atomic_long_add(delta, (atomic_long_t *)&sem->count);
+}
+
+/*
+ * downgrade write lock to read lock
+ */
+static inline void __downgrade_write(struct rw_semaphore *sem)
+{
+ long tmp;
+
+ tmp = atomic_long_add_return(-RWSEM_WAITING_BIAS,
+ (atomic_long_t *)&sem->count);
+ if (tmp < 0)
+ rwsem_downgrade_wake(sem);
+}
+
+/*
+ * implement exchange and add functionality
+ */
+static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
+{
+ return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_RWSEM_H */
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* Re: Multi-partition block layer behaviour
From: Shaohua Li @ 2011-11-01 0:29 UTC (permalink / raw)
To: Tiju Jacob; +Cc: linux-kernel@vger.kernel.org
In-Reply-To: <CADAg6uwi8bgo3gQuWPeTHeD44biRR4=0E0BjvZradQMtfMCigA@mail.gmail.com>
On Mon, 2011-10-31 at 18:21 +0800, Tiju Jacob wrote:
> >> ok, thanks. So this means the elevator is switching in the test. How
> >> about below patch:
> >>
> >> diff --git a/block/elevator.c b/block/elevator.c
> >> index a3b64bc..e14824a 100644
> >> --- a/block/elevator.c
> >> +++ b/block/elevator.c
> >> @@ -683,8 +683,13 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where)
> >> * - Usually, back inserted requests won't be merged
> >> * with anything. There's no point in delaying queue
> >> * processing.
> >> + * If elevator is switching, doesn't need run the queue.
> >> + * elevator switching will run it anyway. And this could
> >> + * cause warning since the code might run in atomic
> >> + * environment(blk_flush_plug_list() callbed in schedule())
> >> */
> >> - __blk_run_queue(q);
> >> + if (!test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags))
> >> + __blk_run_queue(q);
> >> break;
> >>
> >> case ELEVATOR_INSERT_SORT_MERGE:
> >>
> >>
> > oh, wait. We should have no this issue with latest kernel, because
> > blk_schedule_flush_plug is moved out of schedule atomic environment. please
> > try a latest kernel, for example, 3.1.
> >
>
> Even after applying the above patch, I am getting the same error. We
> have to use the linux 3.0.* kernel series. So is there a fix for the
> 3.0 series?
> We'll defenetly check with the 3.1 kernel and let know.
please ignore the patch. There is a fix in upstream:
9c40cef2b799f9b5e7fa5de4
and it's marked -stable, so it will go to 3.0 stable.
if 3.1 kernel doesn't work, please report back with a log.
Thanks,
Shaohua
^ permalink raw reply
* [PATCH v5 24/36] Hexagon: Provide basic implementation and/or stubs for I/O routines.
From: Richard Kuo @ 2011-10-31 23:48 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Signed-off-by: Linas Vepstas <linas@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/io.h | 326 +++++++++++++++++++++++++++++++++++++++++
arch/hexagon/lib/io.c | 91 ++++++++++++
2 files changed, 417 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/io.h
create mode 100644 arch/hexagon/lib/io.c
diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h
new file mode 100644
index 0000000..b3acc2c
--- /dev/null
+++ b/arch/hexagon/include/asm/io.h
@@ -0,0 +1,326 @@
+/*
+ * IO definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <asm/string.h>
+#include <asm/mem-layout.h>
+#include <asm/iomap.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+/*
+ * We don't have PCI yet.
+ * _IO_BASE is pointing at what should be unused virtual space.
+ */
+#define IO_SPACE_LIMIT 0xffff
+#define _IO_BASE ((void __iomem *)0xfe000000)
+
+extern int remap_area_pages(unsigned long start, unsigned long phys_addr,
+ unsigned long end, unsigned long flags);
+
+extern void __iounmap(const volatile void __iomem *addr);
+
+/* Defined in lib/io.c, needed for smc91x driver. */
+extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
+extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen);
+
+extern void __raw_readsl(const void __iomem *addr, void *data, int wordlen);
+extern void __raw_writesl(void __iomem *addr, const void *data, int wordlen);
+
+#define readsw(p, d, l) __raw_readsw(p, d, l)
+#define writesw(p, d, l) __raw_writesw(p, d, l)
+
+#define readsl(p, d, l) __raw_readsl(p, d, l)
+#define writesl(p, d, l) __raw_writesl(p, d, l)
+
+/*
+ * virt_to_phys - map virtual address to physical
+ * @address: address to map
+ */
+static inline unsigned long virt_to_phys(volatile void *address)
+{
+ return __pa(address);
+}
+
+/*
+ * phys_to_virt - map physical address to virtual
+ * @address: address to map
+ */
+static inline void *phys_to_virt(unsigned long address)
+{
+ return __va(address);
+}
+
+/*
+ * convert a physical pointer to a virtual kernel pointer for
+ * /dev/mem access.
+ */
+#define xlate_dev_kmem_ptr(p) __va(p)
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * IO port access primitives. Hexagon doesn't have special IO access
+ * instructions; all I/O is memory mapped.
+ *
+ * in/out are used for "ports", but we don't have "port instructions",
+ * so these are really just memory mapped too.
+ */
+
+/*
+ * readb - read byte from memory mapped device
+ * @addr: pointer to memory
+ *
+ * Operates on "I/O bus memory space"
+ */
+static inline u8 readb(const volatile void __iomem *addr)
+{
+ u8 val;
+ asm volatile(
+ "%0 = memb(%1);"
+ : "=&r" (val)
+ : "r" (addr)
+ );
+ return val;
+}
+
+static inline u16 readw(const volatile void __iomem *addr)
+{
+ u16 val;
+ asm volatile(
+ "%0 = memh(%1);"
+ : "=&r" (val)
+ : "r" (addr)
+ );
+ return val;
+}
+
+static inline u32 readl(const volatile void __iomem *addr)
+{
+ u32 val;
+ asm volatile(
+ "%0 = memw(%1);"
+ : "=&r" (val)
+ : "r" (addr)
+ );
+ return val;
+}
+
+/*
+ * writeb - write a byte to a memory location
+ * @data: data to write to
+ * @addr: pointer to memory
+ *
+ */
+static inline void writeb(u8 data, volatile void __iomem *addr)
+{
+ asm volatile(
+ "memb(%0) = %1;"
+ :
+ : "r" (addr), "r" (data)
+ : "memory"
+ );
+}
+
+static inline void writew(u16 data, volatile void __iomem *addr)
+{
+ asm volatile(
+ "memh(%0) = %1;"
+ :
+ : "r" (addr), "r" (data)
+ : "memory"
+ );
+
+}
+
+static inline void writel(u32 data, volatile void __iomem *addr)
+{
+ asm volatile(
+ "memw(%0) = %1;"
+ :
+ : "r" (addr), "r" (data)
+ : "memory"
+ );
+}
+
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+
+/*
+ * Need an mtype somewhere in here, for cache type deals?
+ * This is probably too long for an inline.
+ */
+void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size);
+
+static inline void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
+{
+ return ioremap_nocache(phys_addr, size);
+}
+
+static inline void iounmap(volatile void __iomem *addr)
+{
+ __iounmap(addr);
+}
+
+#define __raw_writel writel
+
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
+ int count)
+{
+ memcpy(dst, (void *) src, count);
+}
+
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
+ int count)
+{
+ memcpy((void *) dst, src, count);
+}
+
+#define PCI_IO_ADDR (volatile void __iomem *)
+
+/*
+ * inb - read byte from I/O port or something
+ * @port: address in I/O space
+ *
+ * Operates on "I/O bus I/O space"
+ */
+static inline u8 inb(unsigned long port)
+{
+ return readb(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline u16 inw(unsigned long port)
+{
+ return readw(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline u32 inl(unsigned long port)
+{
+ return readl(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+/*
+ * outb - write a byte to a memory location
+ * @data: data to write to
+ * @addr: address in I/O space
+ */
+static inline void outb(u8 data, unsigned long port)
+{
+ writeb(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline void outw(u16 data, unsigned long port)
+{
+ writew(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline void outl(u32 data, unsigned long port)
+{
+ writel(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+#define outb_p outb
+#define outw_p outw
+#define outl_p outl
+
+#define inb_p inb
+#define inw_p inw
+#define inl_p inl
+
+static inline void insb(unsigned long port, void *buffer, int count)
+{
+ if (count) {
+ u8 *buf = buffer;
+ do {
+ u8 x = inb(port);
+ *buf++ = x;
+ } while (--count);
+ }
+}
+
+static inline void insw(unsigned long port, void *buffer, int count)
+{
+ if (count) {
+ u16 *buf = buffer;
+ do {
+ u16 x = inw(port);
+ *buf++ = x;
+ } while (--count);
+ }
+}
+
+static inline void insl(unsigned long port, void *buffer, int count)
+{
+ if (count) {
+ u32 *buf = buffer;
+ do {
+ u32 x = inw(port);
+ *buf++ = x;
+ } while (--count);
+ }
+}
+
+static inline void outsb(unsigned long port, const void *buffer, int count)
+{
+ if (count) {
+ const u8 *buf = buffer;
+ do {
+ outb(*buf++, port);
+ } while (--count);
+ }
+}
+
+static inline void outsw(unsigned long port, const void *buffer, int count)
+{
+ if (count) {
+ const u16 *buf = buffer;
+ do {
+ outw(*buf++, port);
+ } while (--count);
+ }
+}
+
+static inline void outsl(unsigned long port, const void *buffer, int count)
+{
+ if (count) {
+ const u32 *buf = buffer;
+ do {
+ outl(*buf++, port);
+ } while (--count);
+ }
+}
+
+#define flush_write_buffers() do { } while (0)
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/arch/hexagon/lib/io.c b/arch/hexagon/lib/io.c
new file mode 100644
index 0000000..8ae47ba
--- /dev/null
+++ b/arch/hexagon/lib/io.c
@@ -0,0 +1,91 @@
+/*
+ * I/O access functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <asm/io.h>
+
+/* These are all FIFO routines! */
+
+/*
+ * __raw_readsw - read words a short at a time
+ * @addr: source address
+ * @data: data address
+ * @len: number of shorts to read
+ */
+void __raw_readsw(const void __iomem *addr, void *data, int len)
+{
+ const volatile short int *src = (short int *) addr;
+ short int *dst = (short int *) data;
+
+ if ((u32)data & 0x1)
+ panic("unaligned pointer to readsw");
+
+ while (len-- > 0)
+ *dst++ = *src;
+
+}
+
+/*
+ * __raw_writesw - read words a short at a time
+ * @addr: source address
+ * @data: data address
+ * @len: number of shorts to read
+ */
+void __raw_writesw(void __iomem *addr, const void *data, int len)
+{
+ const short int *src = (short int *)data;
+ volatile short int *dst = (short int *)addr;
+
+ if ((u32)data & 0x1)
+ panic("unaligned pointer to writesw");
+
+ while (len-- > 0)
+ *dst = *src++;
+
+
+}
+
+/* Pretty sure len is pre-adjusted for the length of the access already */
+void __raw_readsl(const void __iomem *addr, void *data, int len)
+{
+ const volatile long *src = (long *) addr;
+ long *dst = (long *) data;
+
+ if ((u32)data & 0x3)
+ panic("unaligned pointer to readsl");
+
+ while (len-- > 0)
+ *dst++ = *src;
+
+
+}
+
+void __raw_writesl(void __iomem *addr, const void *data, int len)
+{
+ const long *src = (long *)data;
+ volatile long *dst = (long *)addr;
+
+ if ((u32)data & 0x3)
+ panic("unaligned pointer to writesl");
+
+ while (len-- > 0)
+ *dst = *src++;
+
+
+}
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 25/36] Hexagon: Implement basic cache-flush support
From: Richard Kuo @ 2011-10-31 23:50 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/cache.h | 34 +++++++++
arch/hexagon/include/asm/cacheflush.h | 99 +++++++++++++++++++++++++
arch/hexagon/mm/cache.c | 128 +++++++++++++++++++++++++++++++++
3 files changed, 261 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/cache.h
create mode 100644 arch/hexagon/include/asm/cacheflush.h
create mode 100644 arch/hexagon/mm/cache.c
diff --git a/arch/hexagon/include/asm/cache.h b/arch/hexagon/include/asm/cache.h
new file mode 100644
index 0000000..0f01de2
--- /dev/null
+++ b/arch/hexagon/include/asm/cache.h
@@ -0,0 +1,34 @@
+/*
+ * Cache definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_CACHE_H
+#define __ASM_CACHE_H
+
+/* Bytes per L1 cache line */
+#define L1_CACHE_SHIFT (5)
+#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
+
+#define __cacheline_aligned __aligned(L1_CACHE_BYTES)
+#define ____cacheline_aligned __aligned(L1_CACHE_BYTES)
+
+/* See http://kerneltrap.org/node/15100 */
+#define __read_mostly
+
+#endif
diff --git a/arch/hexagon/include/asm/cacheflush.h b/arch/hexagon/include/asm/cacheflush.h
new file mode 100644
index 0000000..6865c1b
--- /dev/null
+++ b/arch/hexagon/include/asm/cacheflush.h
@@ -0,0 +1,99 @@
+/*
+ * Cache flush operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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
diff --git a/arch/hexagon/mm/cache.c b/arch/hexagon/mm/cache.c
new file mode 100644
index 0000000..c5cf6ee
--- /dev/null
+++ b/arch/hexagon/mm/cache.c
@@ -0,0 +1,128 @@
+/*
+ * Cache management functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/hexagon_vm.h>
+
+#define spanlines(start, end) \
+ (((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1)
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+ unsigned long lines = spanlines(start, end-1);
+ unsigned long i, flags;
+
+ start &= ~(LINESIZE - 1);
+
+ local_irq_save(flags);
+
+ for (i = 0; i < lines; i++) {
+ __asm__ __volatile__ (
+ " dccleaninva(%0); "
+ :
+ : "r" (start)
+ );
+ start += LINESIZE;
+ }
+ local_irq_restore(flags);
+}
+
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+ unsigned long lines = spanlines(start, end-1);
+ unsigned long i, flags;
+
+ start &= ~(LINESIZE - 1);
+
+ local_irq_save(flags);
+
+ for (i = 0; i < lines; i++) {
+ __asm__ __volatile__ (
+ " dccleana(%0); "
+ " icinva(%0); "
+ :
+ : "r" (start)
+ );
+ start += LINESIZE;
+ }
+ __asm__ __volatile__ (
+ "isync"
+ );
+ local_irq_restore(flags);
+}
+
+void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
+{
+ unsigned long lines = spanlines(start, end-1);
+ unsigned long i, flags;
+
+ start &= ~(LINESIZE - 1);
+
+ local_irq_save(flags);
+
+ for (i = 0; i < lines; i++) {
+ __asm__ __volatile__ (
+ " dccleana(%0); "
+ :
+ : "r" (start)
+ );
+ start += LINESIZE;
+ }
+ local_irq_restore(flags);
+}
+
+void hexagon_inv_dcache_range(unsigned long start, unsigned long end)
+{
+ unsigned long lines = spanlines(start, end-1);
+ unsigned long i, flags;
+
+ start &= ~(LINESIZE - 1);
+
+ local_irq_save(flags);
+
+ for (i = 0; i < lines; i++) {
+ __asm__ __volatile__ (
+ " dcinva(%0); "
+ :
+ : "r" (start)
+ );
+ start += LINESIZE;
+ }
+ local_irq_restore(flags);
+}
+
+
+
+
+/*
+ * This is just really brutal and shouldn't be used anyways,
+ * especially on V2. Left here just in case.
+ */
+void flush_cache_all_hexagon(void)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ __vmcache_ickill();
+ __vmcache_dckill();
+ __vmcache_l2kill();
+ local_irq_restore(flags);
+ mb();
+}
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 27/36] Hexagon: Provide DMA implementation
From: Richard Kuo @ 2011-10-31 23:52 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Signed-off-by: Linas Vepstas <linas@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/dma-mapping.h | 101 +++++++++++++++
arch/hexagon/include/asm/dma.h | 29 ++++
arch/hexagon/kernel/dma.c | 220 ++++++++++++++++++++++++++++++++
3 files changed, 350 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/dma-mapping.h
create mode 100644 arch/hexagon/include/asm/dma.h
create mode 100644 arch/hexagon/kernel/dma.c
diff --git a/arch/hexagon/include/asm/dma-mapping.h b/arch/hexagon/include/asm/dma-mapping.h
new file mode 100644
index 0000000..448b224
--- /dev/null
+++ b/arch/hexagon/include/asm/dma-mapping.h
@@ -0,0 +1,101 @@
+/*
+ * DMA operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_DMA_MAPPING_H
+#define _ASM_DMA_MAPPING_H
+
+#include <linux/types.h>
+#include <linux/cache.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-debug.h>
+#include <linux/dma-attrs.h>
+#include <asm/io.h>
+
+struct device;
+extern int bad_dma_address;
+
+extern struct dma_map_ops *dma_ops;
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+ if (unlikely(dev == NULL))
+ return NULL;
+
+ return dma_ops;
+}
+
+extern int dma_supported(struct device *dev, u64 mask);
+extern int dma_set_mask(struct device *dev, u64 mask);
+extern int dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
+extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+ enum dma_data_direction direction);
+
+#include <asm-generic/dma-mapping-common.h>
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+ if (!dev->dma_mask)
+ return 0;
+ return addr + size - 1 <= *dev->dma_mask;
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+ if (dma_ops->mapping_error)
+ return dma_ops->mapping_error(dev, dma_addr);
+
+ return (dma_addr == bad_dma_address);
+}
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+{
+ void *ret;
+ struct dma_map_ops *ops = get_dma_ops(dev);
+
+ BUG_ON(!dma_ops);
+
+ ret = ops->alloc_coherent(dev, size, dma_handle, flag);
+
+ debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
+
+ return ret;
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+{
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+ BUG_ON(!dma_ops);
+
+ dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+
+ debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+#endif
diff --git a/arch/hexagon/include/asm/dma.h b/arch/hexagon/include/asm/dma.h
new file mode 100644
index 0000000..da6d2f6
--- /dev/null
+++ b/arch/hexagon/include/asm/dma.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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
diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
new file mode 100644
index 0000000..e711ace
--- /dev/null
+++ b/arch/hexagon/kernel/dma.c
@@ -0,0 +1,220 @@
+/*
+ * DMA implementation for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/bootmem.h>
+#include <linux/genalloc.h>
+#include <asm/dma-mapping.h>
+
+struct dma_map_ops *dma_ops;
+EXPORT_SYMBOL(dma_ops);
+
+int bad_dma_address; /* globals are automatically initialized to zero */
+
+int dma_supported(struct device *dev, u64 mask)
+{
+ if (mask == DMA_BIT_MASK(32))
+ return 1;
+ else
+ return 0;
+}
+EXPORT_SYMBOL(dma_supported);
+
+int dma_set_mask(struct device *dev, u64 mask)
+{
+ if (!dev->dma_mask || !dma_supported(dev, mask))
+ return -EIO;
+
+ *dev->dma_mask = mask;
+
+ return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
+static struct gen_pool *coherent_pool;
+
+
+/* Allocates from a pool of uncached memory that was reserved at boot time */
+
+void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_addr, gfp_t flag)
+{
+ void *ret;
+
+ if (coherent_pool == NULL) {
+ coherent_pool = gen_pool_create(PAGE_SHIFT, -1);
+
+ if (coherent_pool == NULL)
+ panic("Can't create %s() memory pool!", __func__);
+ else
+ gen_pool_add(coherent_pool,
+ (PAGE_OFFSET + (max_low_pfn << PAGE_SHIFT)),
+ hexagon_coherent_pool_size, -1);
+ }
+
+ ret = (void *) gen_pool_alloc(coherent_pool, size);
+
+ if (ret) {
+ memset(ret, 0, size);
+ *dma_addr = (dma_addr_t) (ret - PAGE_OFFSET);
+ } else
+ *dma_addr = ~0;
+
+ return ret;
+}
+
+static void hexagon_free_coherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_addr)
+{
+ gen_pool_free(coherent_pool, (unsigned long) vaddr, size);
+}
+
+static int check_addr(const char *name, struct device *hwdev,
+ dma_addr_t bus, size_t size)
+{
+ if (hwdev && hwdev->dma_mask && !dma_capable(hwdev, bus, size)) {
+ if (*hwdev->dma_mask >= DMA_BIT_MASK(32))
+ printk(KERN_ERR
+ "%s: overflow %Lx+%zu of device mask %Lx\n",
+ name, (long long)bus, size,
+ (long long)*hwdev->dma_mask);
+ return 0;
+ }
+ return 1;
+}
+
+static int hexagon_map_sg(struct device *hwdev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct scatterlist *s;
+ int i;
+
+ WARN_ON(nents == 0 || sg[0].length == 0);
+
+ for_each_sg(sg, s, nents, i) {
+ s->dma_address = sg_phys(s);
+ if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
+ return 0;
+
+ s->dma_length = s->length;
+
+ flush_dcache_range(PAGE_OFFSET + s->dma_address,
+ PAGE_OFFSET + s->dma_address + s->length);
+ }
+
+ return nents;
+}
+
+/*
+ * address is virtual
+ */
+static inline void dma_sync(void *addr, size_t size,
+ enum dma_data_direction dir)
+{
+ switch (dir) {
+ case DMA_TO_DEVICE:
+ hexagon_clean_dcache_range((unsigned long) addr,
+ (unsigned long) addr + size);
+ break;
+ case DMA_FROM_DEVICE:
+ hexagon_inv_dcache_range((unsigned long) addr,
+ (unsigned long) addr + size);
+ break;
+ case DMA_BIDIRECTIONAL:
+ flush_dcache_range((unsigned long) addr,
+ (unsigned long) addr + size);
+ break;
+ default:
+ BUG();
+ }
+}
+
+static inline void *dma_addr_to_virt(dma_addr_t dma_addr)
+{
+ return phys_to_virt((unsigned long) dma_addr);
+}
+
+/**
+ * hexagon_map_page() - maps an address for device DMA
+ * @dev: pointer to DMA device
+ * @page: pointer to page struct of DMA memory
+ * @offset: offset within page
+ * @size: size of memory to map
+ * @dir: transfer direction
+ * @attrs: pointer to DMA attrs (not used)
+ *
+ * Called to map a memory address to a DMA address prior
+ * to accesses to/from device.
+ *
+ * We don't particularly have many hoops to jump through
+ * so far. Straight translation between phys and virtual.
+ *
+ * DMA is not cache coherent so sync is necessary; this
+ * seems to be a convenient place to do it.
+ *
+ */
+static dma_addr_t hexagon_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ dma_addr_t bus = page_to_phys(page) + offset;
+ WARN_ON(size == 0);
+
+ if (!check_addr("map_single", dev, bus, size))
+ return bad_dma_address;
+
+ dma_sync(dma_addr_to_virt(bus), size, dir);
+
+ return bus;
+}
+
+static void hexagon_sync_single_for_cpu(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
+{
+ dma_sync(dma_addr_to_virt(dma_handle), size, dir);
+}
+
+static void hexagon_sync_single_for_device(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
+{
+ dma_sync(dma_addr_to_virt(dma_handle), size, dir);
+}
+
+struct dma_map_ops hexagon_dma_ops = {
+ .alloc_coherent = hexagon_dma_alloc_coherent,
+ .free_coherent = hexagon_free_coherent,
+ .map_sg = hexagon_map_sg,
+ .map_page = hexagon_map_page,
+ .sync_single_for_cpu = hexagon_sync_single_for_cpu,
+ .sync_single_for_device = hexagon_sync_single_for_device,
+ .is_phys = 1,
+};
+
+void __init hexagon_dma_init(void)
+{
+ if (dma_ops)
+ return;
+
+ dma_ops = &hexagon_dma_ops;
+}
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 29/36] Hexagon: Add page table header files & etc.
From: Richard Kuo @ 2011-10-31 23:53 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Signed-off-by: Linas Vepstas <linas@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/fixmap.h | 73 +++++
arch/hexagon/include/asm/mmu.h | 37 +++
arch/hexagon/include/asm/mmu_context.h | 100 ++++++
arch/hexagon/include/asm/page.h | 157 ++++++++++
arch/hexagon/include/asm/pgalloc.h | 146 +++++++++
arch/hexagon/include/asm/pgtable.h | 518 ++++++++++++++++++++++++++++++++
arch/hexagon/mm/pgalloc.c | 25 ++
7 files changed, 1056 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/fixmap.h
create mode 100644 arch/hexagon/include/asm/mmu.h
create mode 100644 arch/hexagon/include/asm/mmu_context.h
create mode 100644 arch/hexagon/include/asm/page.h
create mode 100644 arch/hexagon/include/asm/pgalloc.h
create mode 100644 arch/hexagon/include/asm/pgtable.h
create mode 100644 arch/hexagon/mm/pgalloc.c
diff --git a/arch/hexagon/include/asm/fixmap.h b/arch/hexagon/include/asm/fixmap.h
new file mode 100644
index 0000000..b27f494
--- /dev/null
+++ b/arch/hexagon/include/asm/fixmap.h
@@ -0,0 +1,73 @@
+/*
+ * Fixmap support for Hexagon - enough to support highmem features
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+/*
+ * A lot of the fixmap info is already in mem-layout.h
+ */
+#include <asm/mem-layout.h>
+
+/*
+ * Full fixmap support involves set_fixmap() functions, but
+ * these may not be needed if all we're after is an area for
+ * highmem kernel mappings.
+ */
+#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
+extern void __this_fixmap_does_not_exist(void);
+
+/**
+ * fix_to_virt -- "index to address" translation.
+ *
+ * If anyone tries to use the idx directly without translation,
+ * we catch the bug with a NULL-deference kernel oops. Illegal
+ * ranges of incoming indices are caught too.
+ */
+static inline unsigned long fix_to_virt(const unsigned int idx)
+{
+ /*
+ * This branch gets completely eliminated after inlining,
+ * except when someone tries to use fixaddr indices in an
+ * illegal way. (such as mixing up address types or using
+ * out-of-range indices).
+ *
+ * If it doesn't get removed, the linker will complain
+ * loudly with a reasonably clear error message..
+ */
+ if (idx >= __end_of_fixed_addresses)
+ __this_fixmap_does_not_exist();
+
+ return __fix_to_virt(idx);
+}
+
+static inline unsigned long virt_to_fix(const unsigned long vaddr)
+{
+ BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+ return __virt_to_fix(vaddr);
+}
+
+#define kmap_get_fixmap_pte(vaddr) \
+ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), \
+ (vaddr)), (vaddr)), (vaddr))
+
+#endif
diff --git a/arch/hexagon/include/asm/mmu.h b/arch/hexagon/include/asm/mmu.h
new file mode 100644
index 0000000..30a5d8d
--- /dev/null
+++ b/arch/hexagon/include/asm/mmu.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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
diff --git a/arch/hexagon/include/asm/mmu_context.h b/arch/hexagon/include/asm/mmu_context.h
new file mode 100644
index 0000000..b4fe5a5
--- /dev/null
+++ b/arch/hexagon/include/asm/mmu_context.h
@@ -0,0 +1,100 @@
+/*
+ * MM context support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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
diff --git a/arch/hexagon/include/asm/page.h b/arch/hexagon/include/asm/page.h
new file mode 100644
index 0000000..edd9762
--- /dev/null
+++ b/arch/hexagon/include/asm/page.h
@@ -0,0 +1,157 @@
+/*
+ * Page management definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PAGE_H
+#define _ASM_PAGE_H
+
+#include <linux/const.h>
+
+/* This is probably not the most graceful way to handle this. */
+
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PAGE_SHIFT 12
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_4KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define PAGE_SHIFT 14
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_16KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define PAGE_SHIFT 16
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_64KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_256KB
+#define PAGE_SHIFT 18
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_256KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_1MB
+#define PAGE_SHIFT 20
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_1MB
+#endif
+
+/*
+ * These should be defined in hugetlb.h, but apparently not.
+ * "Huge" for us should be 4MB or 16MB, which are both represented
+ * in L1 PTE's. Right now, it's set up for 4MB.
+ */
+#ifdef CONFIG_HUGETLB_PAGE
+#define HPAGE_SHIFT 22
+#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE-1))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
+#define HVM_HUGEPAGE_SIZE 0x5
+#endif
+
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+/*
+ * This is for PFN_DOWN, which mm.h needs. Seems the right place to pull it in.
+ */
+#include <linux/pfn.h>
+
+/*
+ * We implement a two-level architecture-specific page table structure.
+ * Null intermediate page table level (pmd, pud) definitions will come from
+ * asm-generic/pagetable-nopmd.h and asm-generic/pagetable-nopud.h
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
+
+#define pte_val(x) ((x).pte)
+#define pgd_val(x) ((x).pgd)
+#define pgprot_val(x) ((x).pgprot)
+#define __pte(x) ((pte_t) { (x) })
+#define __pgd(x) ((pgd_t) { (x) })
+#define __pgprot(x) ((pgprot_t) { (x) })
+
+/*
+ * We need a __pa and a __va routine for kernel space.
+ * MIPS says they're only used during mem_init.
+ * also, check if we need a PHYS_OFFSET.
+ */
+#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
+
+/* The "page frame" descriptor is defined in linux/mm.h */
+struct page;
+
+/* Returns page frame descriptor for virtual address. */
+#define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(__pa(kaddr)))
+
+/* Default vm area behavior is non-executable. */
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#define pfn_valid(pfn) ((pfn) < max_mapnr)
+#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+/* Need to not use a define for linesize; may move this to another file. */
+static inline void clear_page(void *page)
+{
+ /* This can only be done on pages with L1 WB cache */
+ asm volatile(
+ " loop0(1f,%1);\n"
+ "1: { dczeroa(%0);\n"
+ " %0 = add(%0,#32); }:endloop0\n"
+ : "+r" (page)
+ : "r" (PAGE_SIZE/32)
+ : "lc0", "sa0", "memory"
+ );
+}
+
+#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
+
+/*
+ * Under assumption that kernel always "sees" user map...
+ */
+#define clear_user_page(page, vaddr, pg) clear_page(page)
+#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
+
+/*
+ * page_to_phys - convert page to physical address
+ * @page - pointer to page entry in mem_map
+ */
+#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
+
+/*
+ * For port to Hexagon Virtual Machine, MAYBE we check for attempts
+ * to reference reserved HVM space, but in any case, the VM will be
+ * protected.
+ */
+#define kern_addr_valid(addr) (1)
+
+#include <asm-generic/memory_model.h>
+/* XXX Todo: implement assembly-optimized version of getorder. */
+#include <asm-generic/getorder.h>
+
+#endif /* ifdef __ASSEMBLY__ */
+#endif /* ifdef __KERNEL__ */
+
+#endif
diff --git a/arch/hexagon/include/asm/pgalloc.h b/arch/hexagon/include/asm/pgalloc.h
new file mode 100644
index 0000000..13443c7
--- /dev/null
+++ b/arch/hexagon/include/asm/pgalloc.h
@@ -0,0 +1,146 @@
+/*
+ * Page table support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PGALLOC_H
+#define _ASM_PGALLOC_H
+
+#include <asm/mem-layout.h>
+#include <asm/atomic.h>
+
+#define check_pgt_cache() do {} while (0)
+
+extern unsigned long long kmap_generation;
+
+/*
+ * Page table creation interface
+ */
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+ pgd_t *pgd;
+
+ pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+
+ /*
+ * There may be better ways to do this, but to ensure
+ * that new address spaces always contain the kernel
+ * base mapping, and to ensure that the user area is
+ * initially marked invalid, initialize the new map
+ * map with a copy of the kernel's persistent map.
+ */
+
+ memcpy(pgd, swapper_pg_dir, PTRS_PER_PGD*sizeof(pgd_t *));
+ mm->context.generation = kmap_generation;
+
+ /* Physical version is what is passed to virtual machine on switch */
+ mm->context.ptbase = __pa(pgd);
+
+ return pgd;
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+ free_page((unsigned long) pgd);
+}
+
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
+ unsigned long address)
+{
+ struct page *pte;
+
+ pte = alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+
+ if (pte)
+ pgtable_page_ctor(pte);
+
+ return pte;
+}
+
+/* _kernel variant gets to use a different allocator */
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+ unsigned long address)
+{
+ gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
+ return (pte_t *) __get_free_page(flags);
+}
+
+static inline void pte_free(struct mm_struct *mm, struct page *pte)
+{
+ pgtable_page_dtor(pte);
+ __free_page(pte);
+}
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+ free_page((unsigned long)pte);
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+ pgtable_t pte)
+{
+ /*
+ * Conveniently, zero in 3 LSB means indirect 4K page table.
+ * Not so convenient when you're trying to vary the page size.
+ */
+ set_pmd(pmd, __pmd(((unsigned long)page_to_pfn(pte) << PAGE_SHIFT) |
+ HEXAGON_L1_PTE_SIZE));
+}
+
+/*
+ * Other architectures seem to have ways of making all processes
+ * share the same pmd's for their kernel mappings, but the v0.3
+ * Hexagon VM spec has a "monolithic" L1 table for user and kernel
+ * segments. We track "generations" of the kernel map to minimize
+ * overhead, and update the "slave" copies of the kernel mappings
+ * as part of switch_mm. However, we still need to update the
+ * kernel map of the active thread who's calling pmd_populate_kernel...
+ */
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+ pte_t *pte)
+{
+ extern spinlock_t kmap_gen_lock;
+ pmd_t *ppmd;
+ int pmdindex;
+
+ spin_lock(&kmap_gen_lock);
+ kmap_generation++;
+ mm->context.generation = kmap_generation;
+ current->active_mm->context.generation = kmap_generation;
+ spin_unlock(&kmap_gen_lock);
+
+ set_pmd(pmd, __pmd(((unsigned long)__pa(pte)) | HEXAGON_L1_PTE_SIZE));
+
+ /*
+ * Now the "slave" copy of the current thread.
+ * This is pointer arithmetic, not byte addresses!
+ */
+ pmdindex = (pgd_t *)pmd - mm->pgd;
+ ppmd = (pmd_t *)current->active_mm->pgd + pmdindex;
+ set_pmd(ppmd, __pmd(((unsigned long)__pa(pte)) | HEXAGON_L1_PTE_SIZE));
+ if (pmdindex > max_kernel_seg)
+ max_kernel_seg = pmdindex;
+}
+
+#define __pte_free_tlb(tlb, pte, addr) \
+do { \
+ pgtable_page_dtor((pte)); \
+ tlb_remove_page((tlb), (pte)); \
+} while (0)
+
+#endif
diff --git a/arch/hexagon/include/asm/pgtable.h b/arch/hexagon/include/asm/pgtable.h
new file mode 100644
index 0000000..ca619bf
--- /dev/null
+++ b/arch/hexagon/include/asm/pgtable.h
@@ -0,0 +1,518 @@
+/*
+ * Page table support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PGTABLE_H
+#define _ASM_PGTABLE_H
+
+/*
+ * Page table definitions for Qualcomm Hexagon processor.
+ */
+#include <linux/swap.h>
+#include <asm/page.h>
+#include <asm-generic/pgtable-nopmd.h>
+
+/* A handy thing to have if one has the RAM. Declared in head.S */
+extern unsigned long empty_zero_page;
+extern unsigned long zero_page_mask;
+
+/*
+ * The PTE model described here is that of the Hexagon Virtual Machine,
+ * which autonomously walks 2-level page tables. At a lower level, we
+ * also describe the RISCish software-loaded TLB entry structure of
+ * the underlying Hexagon processor. A kernel built to run on the
+ * virtual machine has no need to know about the underlying hardware.
+ */
+#include <asm/vm_mmu.h>
+
+/*
+ * To maximize the comfort level for the PTE manipulation macros,
+ * define the "well known" architecture-specific bits.
+ */
+#define _PAGE_READ __HVM_PTE_R
+#define _PAGE_WRITE __HVM_PTE_W
+#define _PAGE_EXECUTE __HVM_PTE_X
+#define _PAGE_USER __HVM_PTE_U
+
+/*
+ * We have a total of 4 "soft" bits available in the abstract PTE.
+ * The two mandatory software bits are Dirty and Accessed.
+ * To make nonlinear swap work according to the more recent
+ * model, we want a low order "Present" bit to indicate whether
+ * the PTE describes MMU programming or swap space.
+ */
+#define _PAGE_PRESENT (1<<0)
+#define _PAGE_DIRTY (1<<1)
+#define _PAGE_ACCESSED (1<<2)
+
+/*
+ * _PAGE_FILE is only meaningful if _PAGE_PRESENT is false, while
+ * _PAGE_DIRTY is only meaningful if _PAGE_PRESENT is true.
+ * So we can overload the bit...
+ */
+#define _PAGE_FILE _PAGE_DIRTY /* set: pagecache, unset = swap */
+
+/*
+ * For now, let's say that Valid and Present are the same thing.
+ * Alternatively, we could say that it's the "or" of R, W, and X
+ * permissions.
+ */
+#define _PAGE_VALID _PAGE_PRESENT
+
+/*
+ * We're not defining _PAGE_GLOBAL here, since there's no concept
+ * of global pages or ASIDs exposed to the Hexagon Virtual Machine,
+ * and we want to use the same page table structures and macros in
+ * the native kernel as we do in the virtual machine kernel.
+ * So we'll put up with a bit of inefficiency for now...
+ */
+
+/*
+ * Top "FOURTH" level (pgd), which for the Hexagon VM is really
+ * only the second from the bottom, pgd and pud both being collapsed.
+ * Each entry represents 4MB of virtual address space, 4K of table
+ * thus maps the full 4GB.
+ */
+#define PGDIR_SHIFT 22
+#define PTRS_PER_PGD 1024
+
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PTRS_PER_PTE 1024
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define PTRS_PER_PTE 256
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define PTRS_PER_PTE 64
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_256KB
+#define PTRS_PER_PTE 16
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_1MB
+#define PTRS_PER_PTE 4
+#endif
+
+/* Any bigger and the PTE disappears. */
+#define pgd_ERROR(e) \
+ printk(KERN_ERR "%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__,\
+ pgd_val(e))
+
+/*
+ * Page Protection Constants. Includes (in this variant) cache attributes.
+ */
+extern unsigned long _dflt_cache_att;
+
+#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _dflt_cache_att)
+#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_READ | _PAGE_EXECUTE | _dflt_cache_att)
+#define PAGE_COPY PAGE_READONLY
+#define PAGE_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_READ | _PAGE_EXECUTE | _dflt_cache_att)
+#define PAGE_COPY_EXEC PAGE_EXEC
+#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+ _PAGE_EXECUTE | _PAGE_WRITE | _dflt_cache_att)
+#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_READ | \
+ _PAGE_WRITE | _PAGE_EXECUTE | _dflt_cache_att)
+
+
+/*
+ * Aliases for mapping mmap() protection bits to page protections.
+ * These get used for static initialization, so using the _dflt_cache_att
+ * variable for the default cache attribute isn't workable. If the
+ * default gets changed at boot time, the boot option code has to
+ * update data structures like the protaction_map[] array.
+ */
+#define CACHEDEF (CACHE_DEFAULT << 6)
+
+/* Private (copy-on-write) page protections. */
+#define __P000 __pgprot(_PAGE_PRESENT | _PAGE_USER | CACHEDEF)
+#define __P001 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | CACHEDEF)
+#define __P010 __P000 /* Write-only copy-on-write */
+#define __P011 __P001 /* Read/Write copy-on-write */
+#define __P100 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_EXECUTE | CACHEDEF)
+#define __P101 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_EXECUTE | \
+ _PAGE_READ | CACHEDEF)
+#define __P110 __P100 /* Write/execute copy-on-write */
+#define __P111 __P101 /* Read/Write/Execute, copy-on-write */
+
+/* Shared page protections. */
+#define __S000 __P000
+#define __S001 __P001
+#define __S010 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_WRITE | CACHEDEF)
+#define __S011 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+ _PAGE_WRITE | CACHEDEF)
+#define __S100 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_EXECUTE | CACHEDEF)
+#define __S101 __P101
+#define __S110 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_EXECUTE | _PAGE_WRITE | CACHEDEF)
+#define __S111 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+ _PAGE_EXECUTE | _PAGE_WRITE | CACHEDEF)
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* located in head.S */
+
+/* Seems to be zero even in architectures where the zero page is firewalled? */
+#define FIRST_USER_ADDRESS 0
+#define pte_special(pte) 0
+#define pte_mkspecial(pte) (pte)
+
+/* HUGETLB not working currently */
+#ifdef CONFIG_HUGETLB_PAGE
+#define pte_mkhuge(pte) __pte((pte_val(pte) & ~0x3) | HVM_HUGEPAGE_SIZE)
+#endif
+
+/*
+ * For now, assume that higher-level code will do TLB/MMU invalidations
+ * and don't insert that overhead into this low-level function.
+ */
+extern void sync_icache_dcache(pte_t pte);
+
+#define pte_present_exec_user(pte) \
+ ((pte_val(pte) & (_PAGE_EXECUTE | _PAGE_USER)) == \
+ (_PAGE_EXECUTE | _PAGE_USER))
+
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+ /* should really be using pte_exec, if it weren't declared later. */
+ if (pte_present_exec_user(pteval))
+ sync_icache_dcache(pteval);
+
+ *ptep = pteval;
+}
+
+/*
+ * For the Hexagon Virtual Machine MMU (or its emulation), a null/invalid
+ * L1 PTE (PMD/PGD) has 7 in the least significant bits. For the L2 PTE
+ * (Linux PTE), the key is to have bits 11..9 all zero. We'd use 0x7
+ * as a universal null entry, but some of those least significant bits
+ * are interpreted by software.
+ */
+#define _NULL_PMD 0x7
+#define _NULL_PTE 0x0
+
+static inline void pmd_clear(pmd_t *pmd_entry_ptr)
+{
+ pmd_val(*pmd_entry_ptr) = _NULL_PMD;
+}
+
+/*
+ * Conveniently, a null PTE value is invalid.
+ */
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
+{
+ pte_val(*ptep) = _NULL_PTE;
+}
+
+#ifdef NEED_PMD_INDEX_DESPITE_BEING_2_LEVEL
+/**
+ * pmd_index - returns the index of the entry in the PMD page
+ * which would control the given virtual address
+ */
+#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+
+#endif
+
+/**
+ * pgd_index - returns the index of the entry in the PGD page
+ * which would control the given virtual address
+ *
+ * This returns the *index* for the address in the pgd_t
+ */
+#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+/*
+ * pgd_offset - find an offset in a page-table-directory
+ */
+#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
+
+/*
+ * pgd_offset_k - get kernel (init_mm) pgd entry pointer for addr
+ */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/**
+ * pmd_none - check if pmd_entry is mapped
+ * @pmd_entry: pmd entry
+ *
+ * MIPS checks it against that "invalid pte table" thing.
+ */
+static inline int pmd_none(pmd_t pmd)
+{
+ return pmd_val(pmd) == _NULL_PMD;
+}
+
+/**
+ * pmd_present - is there a page table behind this?
+ * Essentially the inverse of pmd_none. We maybe
+ * save an inline instruction by defining it this
+ * way, instead of simply "!pmd_none".
+ */
+static inline int pmd_present(pmd_t pmd)
+{
+ return pmd_val(pmd) != (unsigned long)_NULL_PMD;
+}
+
+/**
+ * pmd_bad - check if a PMD entry is "bad". That might mean swapped out.
+ * As we have no known cause of badness, it's null, as it is for many
+ * architectures.
+ */
+static inline int pmd_bad(pmd_t pmd)
+{
+ return 0;
+}
+
+/*
+ * pmd_page - converts a PMD entry to a page pointer
+ */
+#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+/**
+ * pte_none - check if pte is mapped
+ * @pte: pte_t entry
+ */
+static inline int pte_none(pte_t pte)
+{
+ return pte_val(pte) == _NULL_PTE;
+};
+
+/*
+ * pte_present - check if page is present
+ */
+static inline int pte_present(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_PRESENT;
+}
+
+/* mk_pte - make a PTE out of a page pointer and protection bits */
+#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
+
+/* pte_page - returns a page (frame pointer/descriptor?) based on a PTE */
+#define pte_page(x) pfn_to_page(pte_pfn(x))
+
+/* pte_mkold - mark PTE as not recently accessed */
+static inline pte_t pte_mkold(pte_t pte)
+{
+ pte_val(pte) &= ~_PAGE_ACCESSED;
+ return pte;
+}
+
+/* pte_mkyoung - mark PTE as recently accessed */
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_ACCESSED;
+ return pte;
+}
+
+/* pte_mkclean - mark page as in sync with backing store */
+static inline pte_t pte_mkclean(pte_t pte)
+{
+ pte_val(pte) &= ~_PAGE_DIRTY;
+ return pte;
+}
+
+/* pte_mkdirty - mark page as modified */
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_DIRTY;
+ return pte;
+}
+
+/* pte_young - "is PTE marked as accessed"? */
+static inline int pte_young(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_ACCESSED;
+}
+
+/* pte_dirty - "is PTE dirty?" */
+static inline int pte_dirty(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_DIRTY;
+}
+
+/* pte_modify - set protection bits on PTE */
+static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
+{
+ pte_val(pte) &= PAGE_MASK;
+ pte_val(pte) |= pgprot_val(prot);
+ return pte;
+}
+
+/* pte_wrprotect - mark page as not writable */
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+ pte_val(pte) &= ~_PAGE_WRITE;
+ return pte;
+}
+
+/* pte_mkwrite - mark page as writable */
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_WRITE;
+ return pte;
+}
+
+/* pte_mkexec - mark PTE as executable */
+static inline pte_t pte_mkexec(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_EXECUTE;
+ return pte;
+}
+
+/* pte_read - "is PTE marked as readable?" */
+static inline int pte_read(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_READ;
+}
+
+/* pte_write - "is PTE marked as writable?" */
+static inline int pte_write(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_WRITE;
+}
+
+
+/* pte_exec - "is PTE marked as executable?" */
+static inline int pte_exec(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_EXECUTE;
+}
+
+/* __pte_to_swp_entry - extract swap entry from PTE */
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+
+/* __swp_entry_to_pte - extract PTE from swap entry */
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+/* pfn_pte - convert page number and protection value to page table entry */
+#define pfn_pte(pfn, pgprot) __pte((pfn << PAGE_SHIFT) | pgprot_val(pgprot))
+
+/* pte_pfn - convert pte to page frame number */
+#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
+
+/*
+ * set_pte_at - update page table and do whatever magic may be
+ * necessary to make the underlying hardware/firmware take note.
+ *
+ * VM may require a virtual instruction to alert the MMU.
+ */
+#define set_pte_at(mm, addr, ptep, pte) set_pte(ptep, pte)
+
+/*
+ * May need to invoke the virtual machine as well...
+ */
+#define pte_unmap(pte) do { } while (0)
+#define pte_unmap_nested(pte) do { } while (0)
+
+/*
+ * pte_offset_map - returns the linear address of the page table entry
+ * corresponding to an address
+ */
+#define pte_offset_map(dir, address) \
+ ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
+
+#define pte_offset_map_nested(pmd, addr) pte_offset_map(pmd, addr)
+
+/* pte_offset_kernel - kernel version of pte_offset */
+#define pte_offset_kernel(dir, address) \
+ ((pte_t *) (unsigned long) __va(pmd_val(*dir) & PAGE_MASK) \
+ + __pte_offset(address))
+
+/* ZERO_PAGE - returns the globally shared zero page */
+#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
+
+#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+/* Nothing special about IO remapping at this point */
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+/* I think this is in case we have page table caches; needed by init/main.c */
+#define pgtable_cache_init() do { } while (0)
+
+/*
+ * Swap/file PTE definitions. If _PAGE_PRESENT is zero, the rest of the
+ * PTE is interpreted as swap information. Depending on the _PAGE_FILE
+ * bit, the remaining free bits are eitehr interpreted as a file offset
+ * or a swap type/offset tuple. Rather than have the TLB fill handler
+ * test _PAGE_PRESENT, we're going to reserve the permissions bits
+ * and set them to all zeros for swap entries, which speeds up the
+ * miss handler at the cost of 3 bits of offset. That trade-off can
+ * be revisited if necessary, but Hexagon processor architecture and
+ * target applications suggest a lot of TLB misses and not much swap space.
+ *
+ * Format of swap PTE:
+ * bit 0: Present (zero)
+ * bit 1: _PAGE_FILE (zero)
+ * bits 2-6: swap type (arch independent layer uses 5 bits max)
+ * bits 7-9: bits 2:0 of offset
+ * bits 10-12: effectively _PAGE_PROTNONE (all zero)
+ * bits 13-31: bits 21:3 of swap offset
+ *
+ * Format of file PTE:
+ * bit 0: Present (zero)
+ * bit 1: _PAGE_FILE (zero)
+ * bits 2-9: bits 7:0 of offset
+ * bits 10-12: effectively _PAGE_PROTNONE (all zero)
+ * bits 13-31: bits 26:8 of swap offset
+ *
+ * The split offset makes some of the following macros a little gnarly,
+ * but there's plenty of precedent for this sort of thing.
+ */
+#define PTE_FILE_MAX_BITS 27
+
+/* Used for swap PTEs */
+#define __swp_type(swp_pte) (((swp_pte).val >> 2) & 0x1f)
+
+#define __swp_offset(swp_pte) \
+ ((((swp_pte).val >> 7) & 0x7) | (((swp_pte).val >> 10) & 0x003ffff8))
+
+#define __swp_entry(type, offset) \
+ ((swp_entry_t) { \
+ ((type << 2) | \
+ ((offset & 0x3ffff8) << 10) | ((offset & 0x7) << 7)) })
+
+/* Used for file PTEs */
+#define pte_file(pte) \
+ ((pte_val(pte) & (_PAGE_FILE | _PAGE_PRESENT)) == _PAGE_FILE)
+
+#define pte_to_pgoff(pte) \
+ (((pte_val(pte) >> 2) & 0xff) | ((pte_val(pte) >> 5) & 0x07ffff00))
+
+#define pgoff_to_pte(off) \
+ ((pte_t) { ((((off) & 0x7ffff00) << 5) | (((off) & 0xff) << 2)\
+ | _PAGE_FILE) })
+
+/* Oh boy. There are a lot of possible arch overrides found in this file. */
+#include <asm-generic/pgtable.h>
+
+#endif
diff --git a/arch/hexagon/mm/pgalloc.c b/arch/hexagon/mm/pgalloc.c
new file mode 100644
index 0000000..5286f12
--- /dev/null
+++ b/arch/hexagon/mm/pgalloc.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/init.h>
+
+void __init pgtable_cache_init(void)
+{
+}
+
+
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 30/36] Hexagon: Add page-fault support.
From: Richard Kuo @ 2011-10-31 23:54 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Signed-off-by: Linas Vepstas <linas@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/include/asm/mem-layout.h | 112 +++++++++++++
arch/hexagon/include/asm/vm_fault.h | 26 +++
arch/hexagon/mm/init.c | 276 +++++++++++++++++++++++++++++++++
arch/hexagon/mm/vm_fault.c | 187 ++++++++++++++++++++++
4 files changed, 601 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/include/asm/mem-layout.h
create mode 100644 arch/hexagon/include/asm/vm_fault.h
create mode 100644 arch/hexagon/mm/init.c
create mode 100644 arch/hexagon/mm/vm_fault.c
diff --git a/arch/hexagon/include/asm/mem-layout.h b/arch/hexagon/include/asm/mem-layout.h
new file mode 100644
index 0000000..72e5dcd
--- /dev/null
+++ b/arch/hexagon/include/asm/mem-layout.h
@@ -0,0 +1,112 @@
+/*
+ * Memory layout definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_MEM_LAYOUT_H
+#define _ASM_HEXAGON_MEM_LAYOUT_H
+
+#include <linux/const.h>
+
+/*
+ * Have to do this for ginormous numbers, else they get printed as
+ * negative numbers, which the linker no likey when you try to
+ * assign it to the location counter.
+ */
+
+#define PAGE_OFFSET _AC(0xc0000000, UL)
+
+/*
+ * LOAD_ADDRESS is the physical/linear address of where in memory
+ * the kernel gets loaded. The 12 least significant bits must be zero (0)
+ * due to limitations on setting the EVB
+ *
+ */
+
+#ifndef LOAD_ADDRESS
+#define LOAD_ADDRESS 0x00000000
+#endif
+
+#define TASK_SIZE (PAGE_OFFSET)
+
+/* not sure how these are used yet */
+#define STACK_TOP TASK_SIZE
+#define STACK_TOP_MAX TASK_SIZE
+
+#ifndef __ASSEMBLY__
+enum fixed_addresses {
+ FIX_KMAP_BEGIN,
+ FIX_KMAP_END, /* check for per-cpuism */
+ __end_of_fixed_addresses
+};
+
+#define MIN_KERNEL_SEG 0x300 /* From 0xc0000000 */
+extern int max_kernel_seg;
+
+/*
+ * Start of vmalloc virtual address space for kernel;
+ * supposed to be based on the amount of physical memory available
+ */
+
+#define VMALLOC_START (PAGE_OFFSET + VMALLOC_OFFSET + \
+ (unsigned long)high_memory)
+
+/* Gap between physical ram and vmalloc space for guard purposes. */
+#define VMALLOC_OFFSET PAGE_SIZE
+
+/*
+ * Create the space between VMALLOC_START and FIXADDR_TOP backwards
+ * from the ... "top".
+ *
+ * Permanent IO mappings will live at 0xfexx_xxxx
+ * Hypervisor occupies the last 16MB page at 0xffxxxxxx
+ */
+
+#define FIXADDR_TOP 0xfe000000
+#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
+
+/*
+ * "permanent kernel mappings", defined as long-lasting mappings of
+ * high-memory page frames into the kernel address space.
+ */
+
+#define LAST_PKMAP PTRS_PER_PTE
+#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
+#define PKMAP_NR(virt) ((virt - PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+/*
+ * To the "left" of the fixed map space is the kmap space
+ *
+ * "Permanent Kernel Mappings"; fancy (or less fancy) PTE table
+ * that looks like it's actually walked.
+ * Need to check the alignment/shift usage; some archs use
+ * PMD_MASK on this value
+ */
+#define PKMAP_BASE (FIXADDR_START-PAGE_SIZE*LAST_PKMAP)
+
+/*
+ * 2 pages of guard gap between where vmalloc area ends
+ * and pkmap_base begins.
+ */
+#define VMALLOC_END (PKMAP_BASE-PAGE_SIZE*2)
+#endif /* !__ASSEMBLY__ */
+
+
+#endif /* _ASM_HEXAGON_MEM_LAYOUT_H */
diff --git a/arch/hexagon/include/asm/vm_fault.h b/arch/hexagon/include/asm/vm_fault.h
new file mode 100644
index 0000000..cacda36
--- /dev/null
+++ b/arch/hexagon/include/asm/vm_fault.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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
diff --git a/arch/hexagon/mm/init.c b/arch/hexagon/mm/init.c
new file mode 100644
index 0000000..b57d741
--- /dev/null
+++ b/arch/hexagon/mm/init.c
@@ -0,0 +1,276 @@
+/*
+ * Memory subsystem initialization for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <asm/atomic.h>
+#include <linux/highmem.h>
+#include <asm/tlb.h>
+#include <asm/sections.h>
+#include <asm/vm_mmu.h>
+
+/*
+ * Define a startpg just past the end of the kernel image and a lastpg
+ * that corresponds to the end of real or simulated platform memory.
+ */
+#define bootmem_startpg (PFN_UP(((unsigned long) _end) - PAGE_OFFSET))
+
+unsigned long bootmem_lastpg; /* Should be set by platform code */
+
+/* Set as variable to limit PMD copies */
+int max_kernel_seg = 0x303;
+
+/* think this should be (page_size-1) the way it's used...*/
+unsigned long zero_page_mask;
+
+/* indicate pfn's of high memory */
+unsigned long highstart_pfn, highend_pfn;
+
+/* struct mmu_gather defined in asm-generic.h; */
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+/* Default cache attribute for newly created page tables */
+unsigned long _dflt_cache_att = CACHEDEF;
+
+/*
+ * The current "generation" of kernel map, which should not roll
+ * over until Hell freezes over. Actual bound in years needs to be
+ * calculated to confirm.
+ */
+DEFINE_SPINLOCK(kmap_gen_lock);
+
+/* checkpatch says don't init this to 0. */
+unsigned long long kmap_generation;
+
+/*
+ * mem_init - initializes memory
+ *
+ * Frees up bootmem
+ * Fixes up more stuff for HIGHMEM
+ * Calculates and displays memory available/used
+ */
+void __init mem_init(void)
+{
+ /* No idea where this is actually declared. Seems to evade LXR. */
+ totalram_pages += free_all_bootmem();
+ num_physpages = bootmem_lastpg; /* seriously, what? */
+
+ printk(KERN_INFO "totalram_pages = %ld\n", totalram_pages);
+
+ /*
+ * To-Do: someone somewhere should wipe out the bootmem map
+ * after we're done?
+ */
+
+ /*
+ * This can be moved to some more virtual-memory-specific
+ * initialization hook at some point. Set the init_mm
+ * descriptors "context" value to point to the initial
+ * kernel segment table's physical address.
+ */
+ init_mm.context.ptbase = __pa(init_mm.pgd);
+}
+
+/*
+ * free_initmem - frees memory used by stuff declared with __init
+ *
+ * Todo: free pages between __init_begin and __init_end; possibly
+ * some devtree related stuff as well.
+ */
+void __init_refok free_initmem(void)
+{
+}
+
+/*
+ * free_initrd_mem - frees... initrd memory.
+ * @start - start of init memory
+ * @end - end of init memory
+ *
+ * Apparently has to be passed the address of the initrd memory.
+ *
+ * Wrapped by #ifdef CONFIG_BLKDEV_INITRD
+ */
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+}
+
+void sync_icache_dcache(pte_t pte)
+{
+ unsigned long addr;
+ struct page *page;
+
+ page = pte_page(pte);
+ addr = (unsigned long) page_address(page);
+
+ __vmcache_idsync(addr, PAGE_SIZE);
+}
+
+/*
+ * In order to set up page allocator "nodes",
+ * somebody has to call free_area_init() for UMA.
+ *
+ * In this mode, we only have one pg_data_t
+ * structure: contig_mem_data.
+ */
+void __init paging_init(void)
+{
+ unsigned long zones_sizes[MAX_NR_ZONES] = {0, };
+
+ /*
+ * This is not particularly well documented anywhere, but
+ * give ZONE_NORMAL all the memory, including the big holes
+ * left by the kernel+bootmem_map which are already left as reserved
+ * in the bootmem_map; free_area_init should see those bits and
+ * adjust accordingly.
+ */
+
+ zones_sizes[ZONE_NORMAL] = max_low_pfn;
+
+ free_area_init(zones_sizes); /* sets up the zonelists and mem_map */
+
+ /*
+ * Start of high memory area. Will probably need something more
+ * fancy if we... get more fancy.
+ */
+ high_memory = (void *)((bootmem_lastpg + 1) << PAGE_SHIFT);
+}
+
+#ifndef DMA_RESERVE
+#define DMA_RESERVE (4)
+#endif
+
+#define DMA_CHUNKSIZE (1<<22)
+#define DMA_RESERVED_BYTES (DMA_RESERVE * DMA_CHUNKSIZE)
+
+/*
+ * Pick out the memory size. We look for mem=size,
+ * where size is "size[KkMm]"
+ */
+static int __init early_mem(char *p)
+{
+ unsigned long size;
+ char *endp;
+
+ size = memparse(p, &endp);
+
+ bootmem_lastpg = PFN_DOWN(size);
+
+ return 0;
+}
+early_param("mem", early_mem);
+
+size_t hexagon_coherent_pool_size = (size_t) (DMA_RESERVE << 22);
+
+void __init setup_arch_memory(void)
+{
+ int bootmap_size;
+ /* XXX Todo: this probably should be cleaned up */
+ u32 *segtable = (u32 *) &swapper_pg_dir[0];
+ u32 *segtable_end;
+
+ /*
+ * Set up boot memory allocator
+ *
+ * The Gorman book also talks about these functions.
+ * This needs to change for highmem setups.
+ */
+
+ /* Memory size needs to be a multiple of 16M */
+ bootmem_lastpg = PFN_DOWN((bootmem_lastpg << PAGE_SHIFT) &
+ ~((BIG_KERNEL_PAGE_SIZE) - 1));
+
+ /*
+ * Reserve the top DMA_RESERVE bytes of RAM for DMA (uncached)
+ * memory allocation
+ */
+ bootmap_size = init_bootmem(bootmem_startpg, bootmem_lastpg -
+ PFN_DOWN(DMA_RESERVED_BYTES));
+
+ printk(KERN_INFO "bootmem_startpg: 0x%08lx\n", bootmem_startpg);
+ printk(KERN_INFO "bootmem_lastpg: 0x%08lx\n", bootmem_lastpg);
+ printk(KERN_INFO "bootmap_size: %d\n", bootmap_size);
+ printk(KERN_INFO "max_low_pfn: 0x%08lx\n", max_low_pfn);
+
+ /*
+ * The default VM page tables (will be) populated with
+ * VA=PA+PAGE_OFFSET mapping. We go in and invalidate entries
+ * higher than what we have memory for.
+ */
+
+ /* this is pointer arithmetic; each entry covers 4MB */
+ segtable = segtable + (PAGE_OFFSET >> 22);
+
+ /* this actually only goes to the end of the first gig */
+ segtable_end = segtable + (1<<(30-22));
+
+ /* Move forward to the start of empty pages */
+ segtable += bootmem_lastpg >> (22-PAGE_SHIFT);
+
+ {
+ int i;
+
+ for (i = 1 ; i <= DMA_RESERVE ; i++)
+ segtable[-i] = ((segtable[-i] & __HVM_PTE_PGMASK_4MB)
+ | __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X
+ | __HEXAGON_C_UNC << 6
+ | __HVM_PDE_S_4MB);
+ }
+
+ printk(KERN_INFO "clearing segtable from %p to %p\n", segtable,
+ segtable_end);
+ while (segtable < (segtable_end-8))
+ *(segtable++) = __HVM_PDE_S_INVALID;
+ /* stop the pointer at the device I/O 4MB page */
+
+ printk(KERN_INFO "segtable = %p (should be equal to _K_io_map)\n",
+ segtable);
+
+#if 0
+ /* Other half of the early device table from vm_init_segtable. */
+ printk(KERN_INFO "&_K_init_devicetable = 0x%08x\n",
+ (unsigned long) _K_init_devicetable-PAGE_OFFSET);
+ *segtable = ((u32) (unsigned long) _K_init_devicetable-PAGE_OFFSET) |
+ __HVM_PDE_S_4KB;
+ printk(KERN_INFO "*segtable = 0x%08x\n", *segtable);
+#endif
+
+ /*
+ * Free all the memory that wasn't taken up by the bootmap, the DMA
+ * reserve, or kernel itself.
+ */
+ free_bootmem(PFN_PHYS(bootmem_startpg)+bootmap_size,
+ PFN_PHYS(bootmem_lastpg - bootmem_startpg) - bootmap_size -
+ DMA_RESERVED_BYTES);
+
+ /*
+ * The bootmem allocator seemingly just lives to feed memory
+ * to the paging system
+ */
+ printk(KERN_INFO "PAGE_SIZE=%lu\n", PAGE_SIZE);
+ paging_init(); /* See Gorman Book, 2.3 */
+
+ /*
+ * At this point, the page allocator is kind of initialized, but
+ * apparently no pages are available (just like with the bootmem
+ * allocator), and need to be freed themselves via mem_init(),
+ * which is called by start_kernel() later on in the process
+ */
+}
diff --git a/arch/hexagon/mm/vm_fault.c b/arch/hexagon/mm/vm_fault.c
new file mode 100644
index 0000000..c10b76f
--- /dev/null
+++ b/arch/hexagon/mm/vm_fault.c
@@ -0,0 +1,187 @@
+/*
+ * Memory fault handling for Hexagon
+ *
+ * Copyright (c) 2010-2011 Code Aurora Forum. 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.
+ */
+
+/*
+ * Page fault handling for the Hexagon Virtual Machine.
+ * Can also be called by a native port emulating the HVM
+ * execptions.
+ */
+
+#include <asm/pgtable.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/module.h>
+#include <linux/hardirq.h>
+
+/*
+ * Decode of hardware exception sends us to one of several
+ * entry points. At each, we generate canonical arguments
+ * for handling by the abstract memory management code.
+ */
+#define FLT_IFETCH -1
+#define FLT_LOAD 0
+#define FLT_STORE 1
+
+
+/*
+ * Canonical page fault handler
+ */
+void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
+{
+ struct vm_area_struct *vma;
+ struct mm_struct *mm = current->mm;
+ siginfo_t info;
+ int si_code = SEGV_MAPERR;
+ int fault;
+ const struct exception_table_entry *fixup;
+
+ /*
+ * If we're in an interrupt or have no user context,
+ * then must not take the fault.
+ */
+ if (unlikely(in_interrupt() || !mm))
+ goto no_context;
+
+ local_irq_enable();
+
+ down_read(&mm->mmap_sem);
+ vma = find_vma(mm, address);
+ if (!vma)
+ goto bad_area;
+
+ if (vma->vm_start <= address)
+ goto good_area;
+
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+
+ if (expand_stack(vma, address))
+ goto bad_area;
+
+good_area:
+ /* Address space is OK. Now check access rights. */
+ si_code = SEGV_ACCERR;
+
+ switch (cause) {
+ case FLT_IFETCH:
+ if (!(vma->vm_flags & VM_EXEC))
+ goto bad_area;
+ break;
+ case FLT_LOAD:
+ if (!(vma->vm_flags & VM_READ))
+ goto bad_area;
+ break;
+ case FLT_STORE:
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ break;
+ }
+
+ fault = handle_mm_fault(mm, vma, address, (cause > 0));
+
+ /* The most common case -- we are done. */
+ if (likely(!(fault & VM_FAULT_ERROR))) {
+ if (fault & VM_FAULT_MAJOR)
+ current->maj_flt++;
+ else
+ current->min_flt++;
+
+ up_read(&mm->mmap_sem);
+ return;
+ }
+
+ up_read(&mm->mmap_sem);
+
+ /* Handle copyin/out exception cases */
+ if (!user_mode(regs))
+ goto no_context;
+
+ if (fault & VM_FAULT_OOM) {
+ pagefault_out_of_memory();
+ return;
+ }
+
+ /* User-mode address is in the memory map, but we are
+ * unable to fix up the page fault.
+ */
+ if (fault & VM_FAULT_SIGBUS) {
+ info.si_signo = SIGBUS;
+ info.si_code = BUS_ADRERR;
+ }
+ /* Address is not in the memory map */
+ else {
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_ACCERR;
+ }
+ info.si_errno = 0;
+ info.si_addr = (void __user *)address;
+ force_sig_info(info.si_code, &info, current);
+ return;
+
+bad_area:
+ up_read(&mm->mmap_sem);
+
+ if (user_mode(regs)) {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = si_code;
+ info.si_addr = (void *)address;
+ force_sig_info(SIGSEGV, &info, current);
+ return;
+ }
+ /* Kernel-mode fault falls through */
+
+no_context:
+ fixup = search_exception_tables(pt_elr(regs));
+ if (fixup) {
+ pt_set_elr(regs, fixup->fixup);
+ return;
+ }
+
+ /* Things are looking very, very bad now */
+ bust_spinlocks(1);
+ printk(KERN_EMERG "Unable to handle kernel paging request at "
+ "virtual address 0x%08lx, regs %p\n", address, regs);
+ die("Bad Kernel VA", regs, SIGKILL);
+}
+
+
+void read_protection_fault(struct pt_regs *regs)
+{
+ unsigned long badvadr = pt_badva(regs);
+
+ do_page_fault(badvadr, FLT_LOAD, regs);
+}
+
+void write_protection_fault(struct pt_regs *regs)
+{
+ unsigned long badvadr = pt_badva(regs);
+
+ do_page_fault(badvadr, FLT_STORE, regs);
+}
+
+void execute_protection_fault(struct pt_regs *regs)
+{
+ unsigned long badvadr = pt_badva(regs);
+
+ do_page_fault(badvadr, FLT_IFETCH, regs);
+}
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 32/36] Hexagon: Comet platform support
From: Richard Kuo @ 2011-10-31 23:55 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/configs/comet_defconfig | 85 ++++++++++++++++++++++++++++++++++
1 files changed, 85 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/configs/comet_defconfig
diff --git a/arch/hexagon/configs/comet_defconfig b/arch/hexagon/configs/comet_defconfig
new file mode 100644
index 0000000..e324f65
--- /dev/null
+++ b/arch/hexagon/configs/comet_defconfig
@@ -0,0 +1,85 @@
+CONFIG_SMP=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_HZ_100=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_CROSS_COMPILE="hexagon-"
+CONFIG_LOCALVERSION="-smp"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_PHYLIB=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_CONSOLE_TRANSLATIONS is not set
+CONFIG_LEGACY_PTY_COUNT=64
+# CONFIG_DEVKMEM is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_SPI=y
+CONFIG_SPI_DEBUG=y
+CONFIG_SPI_BITBANG=y
+# CONFIG_HWMON is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_LIBCRC32C=y
+CONFIG_FRAME_WARN=0
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* [PATCH v5 33/36] Hexagon: Add configuration and makefiles for the Hexagon architecture.
From: Richard Kuo @ 2011-10-31 23:55 UTC (permalink / raw)
To: torvalds, linux-kernel
Signed-off-by: Linas Vepstas <linas@codeaurora.org>
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
arch/hexagon/Kconfig | 220 +++++++++++++++++++++++++++++++++++++
arch/hexagon/Makefile | 59 ++++++++++
arch/hexagon/kernel/Makefile | 19 +++
arch/hexagon/kernel/asm-offsets.c | 104 +++++++++++++++++
arch/hexagon/kernel/vmlinux.lds.S | 93 ++++++++++++++++
arch/hexagon/lib/Makefile | 4 +
arch/hexagon/mm/Makefile | 7 +
7 files changed, 506 insertions(+), 0 deletions(-)
create mode 100644 arch/hexagon/Kconfig
create mode 100644 arch/hexagon/Makefile
create mode 100644 arch/hexagon/kernel/Makefile
create mode 100644 arch/hexagon/kernel/asm-offsets.c
create mode 100644 arch/hexagon/kernel/vmlinux.lds.S
create mode 100644 arch/hexagon/lib/Makefile
create mode 100644 arch/hexagon/mm/Makefile
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
new file mode 100644
index 0000000..02513c2
--- /dev/null
+++ b/arch/hexagon/Kconfig
@@ -0,0 +1,220 @@
+# Hexagon configuration
+comment "Linux Kernel Configuration for Hexagon"
+
+config HEXAGON
+ def_bool y
+ select HAVE_OPROFILE
+ select USE_GENERIC_SMP_HELPERS if SMP
+ # Other pending projects/to-do items.
+ # select HAVE_REGS_AND_STACK_ACCESS_API
+ # select HAVE_HW_BREAKPOINT if PERF_EVENTS
+ # select ARCH_HAS_CPU_IDLE_WAIT
+ # select ARCH_WANT_OPTIONAL_GPIOLIB
+ # select ARCH_REQUIRE_GPIOLIB
+ # select HAVE_CLK
+ # select IRQ_PER_CPU
+ select HAVE_IRQ_WORK
+ # select GENERIC_PENDING_IRQ if SMP
+ select GENERIC_ATOMIC64
+ select HAVE_PERF_EVENTS
+ select HAVE_GENERIC_HARDIRQS
+ select GENERIC_HARDIRQS_NO__DO_IRQ
+ select GENERIC_HARDIRQS_NO_DEPRECATED
+ # GENERIC_ALLOCATOR is used by dma_alloc_coherent()
+ select GENERIC_ALLOCATOR
+ select GENERIC_IRQ_SHOW
+ select HAVE_ARCH_KGDB
+ select HAVE_ARCH_TRACEHOOK
+ select NO_IOPORT
+ # mostly generic routines, with some accelerated ones
+ ---help---
+ Qualcomm Hexagon is a processor architecture designed for high
+ performance and low power across a wide variety of applications.
+
+config HEXAGON_ARCH_V1
+ bool
+
+config HEXAGON_ARCH_V2
+ bool
+
+config HEXAGON_ARCH_V3
+ bool
+
+config HEXAGON_ARCH_V4
+ bool
+
+config FRAME_POINTER
+ def_bool y
+
+config LOCKDEP_SUPPORT
+ def_bool y
+
+config PCI
+ def_bool n
+
+config EARLY_PRINTK
+ def_bool y
+
+config KTIME_SCALAR
+ def_bool y
+
+config MMU
+ def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+ def_bool y
+
+config GENERIC_CSUM
+ def_bool y
+
+#
+# Use the generic interrupt handling code in kernel/irq/:
+#
+config GENERIC_IRQ_PROBE
+ def_bool y
+
+config GENERIC_IOMAP
+ def_bool y
+
+#config ZONE_DMA
+# bool
+# default y
+
+config HAS_DMA
+ bool
+ select HAVE_DMA_ATTRS
+ default y
+
+config NEED_SG_DMA_LENGTH
+ def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+ def_bool n
+
+config RWSEM_XCHGADD_ALGORITHM
+ def_bool y
+
+config GENERIC_FIND_NEXT_BIT
+ def_bool y
+
+config GENERIC_HWEIGHT
+ def_bool y
+
+config GENERIC_TIME
+ def_bool y
+
+config GENERIC_CLOCKEVENTS
+ def_bool y
+
+config GENERIC_CLOCKEVENTS_BROADCAST
+ def_bool y
+
+config STACKTRACE_SUPPORT
+ def_bool y
+ select STACKTRACE
+
+config GENERIC_BUG
+ def_bool y
+ depends on BUG
+
+config BUG
+ def_bool y
+
+menu "Machine selection"
+
+choice
+ prompt "System type"
+ default HEXAGON_ARCH_V2
+
+config HEXAGON_COMET
+ bool "Comet Board"
+ select HEXAGON_ARCH_V2
+ ---help---
+ Support for the Comet platform.
+
+endchoice
+
+config HEXAGON_VM
+ def_bool y
+
+config CMDLINE
+ string "Default kernel command string"
+ default ""
+ help
+ On some platforms, there is currently no way for the boot loader
+ to pass arguments to the kernel. For these, you should supply some
+ command-line options at build time by entering them here. At a
+ minimum, you should specify the memory size and the root device
+ (e.g., mem=64M root=/dev/nfs).
+
+config HEXAGON_ANGEL_TRAPS
+ bool "Use Angel Traps"
+ default n
+ ---help---
+ Enable angel debug traps (for printk's).
+
+config SMP
+ bool "Multi-Processing support"
+ ---help---
+ Enables SMP support in the kernel. If unsure, say "Y"
+
+config NR_CPUS
+ int "Maximum number of CPUs" if SMP
+ range 2 6 if SMP
+ default "1" if !SMP
+ default "6" if SMP
+ ---help---
+ This allows you to specify the maximum number of CPUs which this
+ kernel will support. The maximum supported value is 6 and the
+ minimum value which makes sense is 2.
+
+ This is purely to save memory - each supported CPU adds
+ approximately eight kilobytes to the kernel image.
+
+choice
+ prompt "Kernel page size"
+ default PAGE_SIZE_4KB
+ ---help---
+ Changes the default page size; use with caution.
+
+config PAGE_SIZE_4KB
+ bool "4KB"
+
+config PAGE_SIZE_16KB
+ bool "16KB"
+
+config PAGE_SIZE_64KB
+ bool "64KB"
+
+config PAGE_SIZE_256KB
+ bool "256KB"
+
+endchoice
+
+source "mm/Kconfig"
+
+source "kernel/Kconfig.hz"
+source "kernel/time/Kconfig"
+
+config GENERIC_GPIO
+ bool "Generic GPIO support"
+ default n
+
+endmenu
+
+source "init/Kconfig"
+source "drivers/Kconfig"
+source "fs/Kconfig"
+
+menu "Executable File Formats"
+source "fs/Kconfig.binfmt"
+endmenu
+
+source "net/Kconfig"
+source "security/Kconfig"
+source "crypto/Kconfig"
+source "lib/Kconfig"
+
+menu "Kernel hacking"
+source "lib/Kconfig.debug"
+endmenu
diff --git a/arch/hexagon/Makefile b/arch/hexagon/Makefile
new file mode 100644
index 0000000..7ce9563
--- /dev/null
+++ b/arch/hexagon/Makefile
@@ -0,0 +1,59 @@
+# Makefile for the Hexagon arch
+
+KBUILD_DEFCONFIG = comet_defconfig
+
+# Do not use GP-relative jumps
+KBUILD_CFLAGS += -G0
+LDFLAGS_vmlinux += -G0
+
+# Do not use single-byte enums; these will overflow.
+KBUILD_CFLAGS += -fno-short-enums
+
+# Modules must use either long-calls, or use pic/plt.
+# Use long-calls for now, it's easier. And faster.
+# CFLAGS_MODULE += -fPIC
+# LDFLAGS_MODULE += -shared
+CFLAGS_MODULE += -mlong-calls
+
+cflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+cflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+cflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+cflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+aflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+aflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+aflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+aflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+ldflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+ldflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+ldflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+ldflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+KBUILD_CFLAGS += $(cflags-y)
+KBUILD_AFLAGS += $(aflags-y)
+
+# no KBUILD_LDFLAGS?
+LDFLAGS += $(ldflags-y)
+
+# Thread-info register will be r19. This value is not configureable;
+# it is hard-coded in several files.
+TIR_NAME := r19
+KBUILD_CFLAGS += -ffixed-$(TIR_NAME) -DTHREADINFO_REG=$(TIR_NAME) -D__linux__
+KBUILD_AFLAGS += -DTHREADINFO_REG=$(TIR_NAME)
+
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+libs-y += $(LIBGCC)
+
+head-y := arch/hexagon/kernel/head.o \
+ arch/hexagon/kernel/init_task.o
+
+core-y += arch/hexagon/kernel/ \
+ arch/hexagon/mm/ \
+ arch/hexagon/lib/
+
+# arch/hexagon/platform/common/
+#
+#core-$(CONFIG_HEXAGON_COMET) += arch/hexagon/platform/comet/
+#machine-$(CONFIG_HEXAGON_COMET) := comet
+
diff --git a/arch/hexagon/kernel/Makefile b/arch/hexagon/kernel/Makefile
new file mode 100644
index 0000000..27be2f6
--- /dev/null
+++ b/arch/hexagon/kernel/Makefile
@@ -0,0 +1,19 @@
+extra-y := head.o vmlinux.lds init_task.o
+
+obj-$(CONFIG_SMP) += smp.o topology.o
+
+obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o
+obj-y += process.o syscall.o trampoline.o reset.o ptrace.o
+obj-y += vdso.o
+
+obj-$(CONFIG_KGDB) += kgdb.o
+obj-$(CONFIG_MODULES) += module.o hexagon_ksyms.o
+
+# Modules required to work with the Hexagon Virtual Machine
+obj-y += vm_entry.o vm_events.o vm_switch.o vm_ops.o vm_init_segtable.o
+obj-y += vm_vectors.o
+
+obj-$(CONFIG_HAS_DMA) += dma.o
+
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
+
diff --git a/arch/hexagon/kernel/asm-offsets.c b/arch/hexagon/kernel/asm-offsets.c
new file mode 100644
index 0000000..89ffa51
--- /dev/null
+++ b/arch/hexagon/kernel/asm-offsets.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 1996 David S. Miller
+ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#include <linux/compat.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/kbuild.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+
+/* This file is used to produce asm/linkerscript constants from header
+ files typically used in c. Specifically, it generates asm-offsets.h */
+
+int main(void)
+{
+ COMMENT("This is a comment.");
+ /* might get these from somewhere else. */
+ DEFINE(_PAGE_SIZE, PAGE_SIZE);
+ DEFINE(_PAGE_SHIFT, PAGE_SHIFT);
+ BLANK();
+
+ COMMENT("Hexagon pt_regs definitions");
+ OFFSET(_PT_SYSCALL_NR, pt_regs, syscall_nr);
+ OFFSET(_PT_UGPGP, pt_regs, ugpgp);
+ OFFSET(_PT_R3130, pt_regs, r3130);
+ OFFSET(_PT_R2928, pt_regs, r2928);
+ OFFSET(_PT_R2726, pt_regs, r2726);
+ OFFSET(_PT_R2524, pt_regs, r2524);
+ OFFSET(_PT_R2322, pt_regs, r2322);
+ OFFSET(_PT_R2120, pt_regs, r2120);
+ OFFSET(_PT_R1918, pt_regs, r1918);
+ OFFSET(_PT_R1716, pt_regs, r1716);
+ OFFSET(_PT_R1514, pt_regs, r1514);
+ OFFSET(_PT_R1312, pt_regs, r1312);
+ OFFSET(_PT_R1110, pt_regs, r1110);
+ OFFSET(_PT_R0908, pt_regs, r0908);
+ OFFSET(_PT_R0706, pt_regs, r0706);
+ OFFSET(_PT_R0504, pt_regs, r0504);
+ OFFSET(_PT_R0302, pt_regs, r0302);
+ OFFSET(_PT_R0100, pt_regs, r0100);
+ OFFSET(_PT_LC0SA0, pt_regs, lc0sa0);
+ OFFSET(_PT_LC1SA1, pt_regs, lc1sa1);
+ OFFSET(_PT_M1M0, pt_regs, m1m0);
+ OFFSET(_PT_PREDSUSR, pt_regs, predsusr);
+ OFFSET(_PT_EVREC, pt_regs, hvmer);
+ OFFSET(_PT_ER_VMEL, pt_regs, hvmer.vmel);
+ OFFSET(_PT_ER_VMEST, pt_regs, hvmer.vmest);
+ OFFSET(_PT_ER_VMPSP, pt_regs, hvmer.vmpsp);
+ OFFSET(_PT_ER_VMBADVA, pt_regs, hvmer.vmbadva);
+ DEFINE(_PT_REGS_SIZE, sizeof(struct pt_regs));
+ BLANK();
+
+ COMMENT("Hexagon thread_info definitions");
+ OFFSET(_THREAD_INFO_FLAGS, thread_info, flags);
+ OFFSET(_THREAD_INFO_PT_REGS, thread_info, regs);
+ OFFSET(_THREAD_INFO_SP, thread_info, sp);
+ DEFINE(_THREAD_SIZE, THREAD_SIZE);
+ BLANK();
+
+ COMMENT("Hexagon hexagon_switch_stack definitions");
+ OFFSET(_SWITCH_R1716, hexagon_switch_stack, r1716);
+ OFFSET(_SWITCH_R1918, hexagon_switch_stack, r1918);
+ OFFSET(_SWITCH_R2120, hexagon_switch_stack, r2120);
+ OFFSET(_SWITCH_R2322, hexagon_switch_stack, r2322);
+
+ OFFSET(_SWITCH_R2524, hexagon_switch_stack, r2524);
+ OFFSET(_SWITCH_R2726, hexagon_switch_stack, r2726);
+ OFFSET(_SWITCH_FP, hexagon_switch_stack, fp);
+ OFFSET(_SWITCH_LR, hexagon_switch_stack, lr);
+ DEFINE(_SWITCH_STACK_SIZE, sizeof(struct hexagon_switch_stack));
+ BLANK();
+
+ COMMENT("Hexagon task_struct definitions");
+ OFFSET(_TASK_THREAD_INFO, task_struct, stack);
+ OFFSET(_TASK_STRUCT_THREAD, task_struct, thread);
+
+ COMMENT("Hexagon thread_struct definitions");
+ OFFSET(_THREAD_STRUCT_SWITCH_SP, thread_struct, switch_sp);
+
+ return 0;
+}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..362742f
--- /dev/null
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -0,0 +1,93 @@
+/*
+ * Linker script for Hexagon kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ */
+
+#define LOAD_OFFSET PAGE_OFFSET
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/asm-offsets.h> /* Most of the kernel defines are here */
+#include <asm/mem-layout.h> /* except for page_offset */
+#include <asm/cache.h> /* and now we're pulling cache line size */
+OUTPUT_ARCH(hexagon)
+ENTRY(stext)
+
+jiffies = jiffies_64;
+
+/*
+See asm-generic/vmlinux.lds.h for expansion of some of these macros.
+See asm-generic/sections.h for seemingly required labels.
+*/
+
+#define PAGE_SIZE _PAGE_SIZE
+
+/* This LOAD_OFFSET is temporary for debugging on the simulator; it may change
+ for hypervisor pseudo-physical memory. */
+
+
+SECTIONS
+{
+ . = PAGE_OFFSET + LOAD_ADDRESS;
+
+ __init_begin = .;
+ HEAD_TEXT_SECTION
+ INIT_TEXT_SECTION(PAGE_SIZE)
+ PERCPU_SECTION(L1_CACHE_BYTES)
+ __init_end = .;
+
+ . = ALIGN(_PAGE_SIZE);
+ _stext = .;
+ .text : AT(ADDR(.text) - LOAD_OFFSET) {
+ _text = .;
+ TEXT_TEXT
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ *(.fixup)
+ }
+ _etext = .;
+
+ INIT_DATA_SECTION(PAGE_SIZE)
+
+ _sdata = .;
+ RW_DATA_SECTION(32,PAGE_SIZE,PAGE_SIZE)
+ RO_DATA_SECTION(PAGE_SIZE)
+ _edata = .;
+
+ EXCEPTION_TABLE(16)
+ NOTES
+
+ BSS_SECTION(_PAGE_SIZE, _PAGE_SIZE, _PAGE_SIZE)
+
+ _end = .;
+
+ /DISCARD/ : {
+ EXIT_TEXT
+ EXIT_DATA
+ EXIT_CALL
+ }
+
+ STABS_DEBUG
+ DWARF_DEBUG
+
+}
+
+
+
+
+
diff --git a/arch/hexagon/lib/Makefile b/arch/hexagon/lib/Makefile
new file mode 100644
index 0000000..874655e
--- /dev/null
+++ b/arch/hexagon/lib/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for hexagon-specific library files.
+#
+obj-y = checksum.o io.o memcpy.o memset.o
diff --git a/arch/hexagon/mm/Makefile b/arch/hexagon/mm/Makefile
new file mode 100644
index 0000000..018be76
--- /dev/null
+++ b/arch/hexagon/mm/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Hexagon memory management subsystem
+#
+
+obj-y := init.o pgalloc.o ioremap.o uaccess.o vm_fault.o cache.o
+obj-y += copy_to_user.o copy_from_user.o strnlen_user.o vm_tlb.o
+
--
1.7.1
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.