From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753012AbbCaXVG (ORCPT ); Tue, 31 Mar 2015 19:21:06 -0400 Received: from mail-wg0-f50.google.com ([74.125.82.50]:36555 "EHLO mail-wg0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752861AbbCaXUw (ORCPT ); Tue, 31 Mar 2015 19:20:52 -0400 From: Frederic Weisbecker To: LKML Cc: Frederic Weisbecker , "Paul E . McKenney" Subject: [PATCH 5/5] x86: Support reverse execution Date: Wed, 1 Apr 2015 01:20:36 +0200 Message-Id: <1427844036-1325-6-git-send-email-fweisbec@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1427844036-1325-1-git-send-email-fweisbec@gmail.com> References: <1427844036-1325-1-git-send-email-fweisbec@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Support reverse execution for negative number of CPUs. We might be able to implement that deeper with the function tracer. No-Yet-Signed-off-by: Frederic Weisbecker --- arch/x86/kernel/cpu/negative.c | 28 ++++++++++++++++++++++++++++ arch/x86/kernel/head64.c | 4 ++++ 2 files changed, 32 insertions(+) create mode 100644 arch/x86/kernel/cpu/negative.c diff --git a/arch/x86/kernel/cpu/negative.c b/arch/x86/kernel/cpu/negative.c new file mode 100644 index 0000000..3aff473 --- /dev/null +++ b/arch/x86/kernel/cpu/negative.c @@ -0,0 +1,28 @@ +/* Execute function in reverse for negative CPUs */ + +#define _ASM_RET 0xc3 +#define FUNC_MAX_SIZE 4096 +static DEFINE_PER_CPU(char, reverse_func_buf[FUNC_MAX_SIZE]); + +void execute_reverse_function(void *func) +{ + char *opcode = (char *)func; + int i = 0, j = FUNC_MAX_SIZE - 1; + void (*reverse_func)(void); + + /* + * Reverse copy the function. + * This assumes that every opcode is sizeof(char), + * there might be a few situations where that won't work + * but we'll fix them as soon as they get reported by users. + */ + while (1) { + reverse_func_buf[j--] = opcode[i]; + if (opcode[i++] == _ASM_RET) + break; + } + + reverse_func = &reverse_func_buf[FUNC_MAX_SIZE - 1]; + reverse_func(); +} + diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index c4f8d46..9ed2c88 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -197,5 +197,9 @@ void __init x86_64_start_reservations(char *real_mode_data) reserve_ebda_region(); +#if CONFIG_NR_CPUS >= 0 start_kernel(); +#else + execute_reverse_function(start_kernel); +#endif } -- 2.1.4