From patchwork Mon Jun 6 17:04:56 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Will Deacon X-Patchwork-Id: 852802 Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p56H6dRw005306 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 6 Jun 2011 17:07:01 GMT Received: from canuck.infradead.org ([2001:4978:20e::1]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QTdG2-0008Ei-Om; Mon, 06 Jun 2011 17:06:31 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1QTdG1-0002bV-OG; Mon, 06 Jun 2011 17:06:29 +0000 Received: from cam-admin0.cambridge.arm.com ([217.140.96.50]) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1QTdEg-0002G9-Th for linux-arm-kernel@lists.infradead.org; Mon, 06 Jun 2011 17:05:08 +0000 Received: from localhost.localdomain (e102144-lin.cambridge.arm.com [10.1.69.60]) by cam-admin0.cambridge.arm.com (8.12.6/8.12.6) with ESMTP id p56H3lFD004674; Mon, 6 Jun 2011 18:03:47 +0100 (BST) From: Will Deacon To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 4/6] ARM: reset: add reset functionality for jumping to a physical address Date: Mon, 6 Jun 2011 18:04:56 +0100 Message-Id: <1307379898-14256-5-git-send-email-will.deacon@arm.com> X-Mailer: git-send-email 1.7.0.4 MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1307379898-14256-1-git-send-email-will.deacon@arm.com> References: <1307379898-14256-1-git-send-email-will.deacon@arm.com> X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110606_130507_330904_828F4830 X-CRM114-Status: GOOD ( 18.29 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.3.1 on canuck.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay domain Cc: frank.hofmann@tomtom.com, Will Deacon X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 06 Jun 2011 17:07:01 +0000 (UTC) Tools such as kexec and CPU hotplug require a way to reset the processor and branch to some code in physical space. This requires various bits of jiggery pokery with the caches and MMU which, when it goes wrong, tends to lock up the system. This patch implements a new function, arm_machine_reset, for consolidating this code in one place where it can be used by multiple subsystems. Signed-off-by: Will Deacon --- arch/arm/include/asm/system.h | 1 + arch/arm/kernel/process.c | 42 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 832888d..cd2a3cd 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -108,6 +108,7 @@ extern int cpu_architecture(void); extern void cpu_init(void); void arm_machine_restart(char mode, const char *cmd); +void arm_machine_reset(unsigned long reset_code_phys); extern void (*arm_pm_restart)(char str, const char *cmd); #define UDBG_UNDEFINED (1 << 0) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 5e1e541..0b46e9f 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -91,12 +91,8 @@ static int __init hlt_setup(char *__unused) __setup("nohlt", nohlt_setup); __setup("hlt", hlt_setup); -void arm_machine_restart(char mode, const char *cmd) +static void prepare_for_reboot(char mode) { - /* Disable interrupts first */ - local_irq_disable(); - local_fiq_disable(); - /* * Tell the mm system that we are going to reboot - * we may need it to insert some 1:1 mappings so that @@ -112,6 +108,15 @@ void arm_machine_restart(char mode, const char *cmd) /* Push out any further dirty data, and ensure cache is empty */ flush_cache_all(); +} + +void arm_machine_restart(char mode, const char *cmd) +{ + /* Disable interrupts first */ + local_irq_disable(); + local_fiq_disable(); + + prepare_for_reboot(mode); /* * Now call the architecture specific reboot code. @@ -127,6 +132,33 @@ void arm_machine_restart(char mode, const char *cmd) while (1); } +void arm_machine_reset(unsigned long reset_code_phys) +{ + unsigned long cpu_reset_end = PAGE_ALIGN((unsigned long)cpu_reset); + /* This is stricter than necessary but better to be safe than sorry. */ + BUG_ON(virt_to_phys((void *)cpu_reset_end) >= TASK_SIZE); + + /* Disable interrupts first */ + local_irq_disable(); + local_fiq_disable(); + + /* + * Clean and invalidate L2. + * This is racy, so we must be the last guy left. + */ + WARN_ON(num_online_cpus() > 1); + /* Flush while we still have locking available to us. */ + outer_flush_all(); + outer_disable(); + /* Data destroyed here will only be speculative. */ + outer_inv_all(); + + prepare_for_reboot(0); + + /* Switch to the identity mapping. */ + ((typeof(cpu_reset) *)virt_to_phys((void *)cpu_reset))(reset_code_phys); +} + /* * Function pointers to optional machine specific functions */