From patchwork Sun Feb 1 18:34:36 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jones X-Patchwork-Id: 5757361 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id CB472BF440 for ; Sun, 1 Feb 2015 18:35:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C16C6201F4 for ; Sun, 1 Feb 2015 18:35:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8F6E6201F5 for ; Sun, 1 Feb 2015 18:35:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753673AbbBASfL (ORCPT ); Sun, 1 Feb 2015 13:35:11 -0500 Received: from mx1.redhat.com ([209.132.183.28]:36240 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753769AbbBASfF (ORCPT ); Sun, 1 Feb 2015 13:35:05 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t11IZ3Fx001036 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Sun, 1 Feb 2015 13:35:03 -0500 Received: from hawk.usersys.redhat.com ([10.34.1.145]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t11IYnLY003050; Sun, 1 Feb 2015 13:35:01 -0500 From: Andrew Jones To: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org Cc: christoffer.dall@linaro.org, pbonzini@redhat.com Subject: [PATCH 08/18] arm/arm64: add per thread user_mode flag Date: Sun, 1 Feb 2015 19:34:36 +0100 Message-Id: <1422815686-24591-9-git-send-email-drjones@redhat.com> In-Reply-To: <1422815686-24591-1-git-send-email-drjones@redhat.com> References: <1422815686-24591-1-git-send-email-drjones@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP While current_mode() == USR_MODE works on armv7 from PL0 to check if we're in user mode, current_mode() would require reading a privileged register on armv8. To work around this, on arm64 we introduced a 'user_mode' variable. This variable needs to be per thread now. Rather than starting to pollute thread_info with a bunch of bools, create a flags field and a TIF_USER_MODE flag to replace it. Use it on armv7 too for consistency. Also, now that we need to create a thread_info initializer, add mpidr utilities for setting thread_info->cpu. Signed-off-by: Andrew Jones --- arm/cstart64.S | 16 +--------------- arm/selftest.c | 2 +- lib/arm/asm/processor.h | 11 +++++++++++ lib/arm/asm/thread_info.h | 13 +++++++++++-- lib/arm/processor.c | 14 ++++++++++++++ lib/arm/setup.c | 3 +++ lib/arm64/asm/processor.h | 14 +++++++++++++- lib/arm64/processor.c | 15 +++++++++++++-- 8 files changed, 67 insertions(+), 21 deletions(-) diff --git a/arm/cstart64.S b/arm/cstart64.S index 2fe15eb1d3972..58e4040cfb40f 100644 --- a/arm/cstart64.S +++ b/arm/cstart64.S @@ -156,13 +156,7 @@ asm_mmu_enable: mrs x2, spsr_el1 stp x1, x2, [sp, #S_PC] - and x2, x2, #PSR_MODE_MASK - cmp x2, #PSR_MODE_EL0t - b.ne 1f - adr x2, user_mode - str xzr, [x2] /* we're in kernel mode now */ - -1: mov x0, \vec + mov x0, \vec mov x1, sp mrs x2, esr_el1 bl do_handle_exception @@ -171,14 +165,6 @@ asm_mmu_enable: msr spsr_el1, x2 msr elr_el1, x1 - and x2, x2, #PSR_MODE_MASK - cmp x2, #PSR_MODE_EL0t - b.ne 1f - adr x2, user_mode - mov x1, #1 - str x1, [x2] /* we're going back to user mode */ - -1: .if \vec >= 8 ldr x1, [sp, #S_SP] msr sp_el0, x1 diff --git a/arm/selftest.c b/arm/selftest.c index 05ca7efe95f83..d77495747b08a 100644 --- a/arm/selftest.c +++ b/arm/selftest.c @@ -240,7 +240,7 @@ static enum vector check_vector_prep(void) { unsigned long daif; - if (user_mode) + if (is_user()) return EL0_SYNC_64; asm volatile("mrs %0, daif" : "=r" (daif) ::); diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h index 9c37db66640e8..f25e7eee3666c 100644 --- a/lib/arm/asm/processor.h +++ b/lib/arm/asm/processor.h @@ -33,6 +33,17 @@ static inline unsigned long current_cpsr(void) #define current_mode() (current_cpsr() & MODE_MASK) +static inline unsigned int get_mpidr(void) +{ + unsigned int mpidr; + asm volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (mpidr)); + return mpidr; +} + +/* Only support Aff0 for now, up to 4 cpus */ +#define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff)) + extern void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr); +extern bool is_user(void); #endif /* _ASMARM_PROCESSOR_H_ */ diff --git a/lib/arm/asm/thread_info.h b/lib/arm/asm/thread_info.h index ea86f142a7d93..17997e21d1274 100644 --- a/lib/arm/asm/thread_info.h +++ b/lib/arm/asm/thread_info.h @@ -11,17 +11,26 @@ #define THREAD_SIZE 16384 #define THREAD_START_SP (THREAD_SIZE - 16) +#define TIF_USER_MODE (1U << 0) + struct thread_info { int cpu; + unsigned int flags; char ext[0]; /* allow unit tests to add extended info */ }; +static inline struct thread_info *thread_info_sp(unsigned long sp) +{ + return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); +} + register unsigned long current_stack_pointer asm("sp"); static inline struct thread_info *current_thread_info(void) { - return (struct thread_info *) - (current_stack_pointer & ~(THREAD_SIZE - 1)); + return thread_info_sp(current_stack_pointer); } +extern void thread_info_init(struct thread_info *ti, unsigned int flags); + #endif /* _ASMARM_THREAD_INFO_H_ */ diff --git a/lib/arm/processor.c b/lib/arm/processor.c index d2fd597fcd139..8a514a29c063b 100644 --- a/lib/arm/processor.c +++ b/lib/arm/processor.c @@ -100,10 +100,19 @@ void do_handle_exception(enum vector v, struct pt_regs *regs) abort(); } +void thread_info_init(struct thread_info *ti, unsigned int flags) +{ + memset(ti, 0, sizeof(struct thread_info)); + ti->cpu = mpidr_to_cpu(get_mpidr()); + ti->flags = flags; +} + void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr) { sp_usr &= (~7UL); /* stack ptr needs 8-byte alignment */ + thread_info_init(thread_info_sp(sp_usr), TIF_USER_MODE); + asm volatile( "mrs r0, cpsr\n" "bic r0, #" xstr(MODE_MASK) "\n" @@ -115,3 +124,8 @@ void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr) "mov pc, %2\n" :: "r" (arg), "r" (sp_usr), "r" (func) : "r0"); } + +bool is_user(void) +{ + return current_thread_info()->flags & TIF_USER_MODE; +} diff --git a/lib/arm/setup.c b/lib/arm/setup.c index 8f58802e958ac..b30c8696f6539 100644 --- a/lib/arm/setup.c +++ b/lib/arm/setup.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -79,6 +80,8 @@ void setup(const void *fdt) io_init(); cpu_init(); + thread_info_init(current_thread_info(), 0); + assert(dt_get_bootargs(&bootargs) == 0); setup_args(bootargs); } diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h index d287f55b8dac6..c1326351d201f 100644 --- a/lib/arm64/asm/processor.h +++ b/lib/arm64/asm/processor.h @@ -60,8 +60,20 @@ static inline unsigned long current_level(void) return el & 0xc; } -extern bool user_mode; +#define DEFINE_GET_SYSREG32(reg) \ +static inline unsigned int get_##reg(void) \ +{ \ + unsigned int reg; \ + asm volatile("mrs %0, " #reg "_el1" : "=r" (reg)); \ + return reg; \ +} +DEFINE_GET_SYSREG32(mpidr) + +/* Only support Aff0 for now, gicv2 only */ +#define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff)) + extern void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr); +extern bool is_user(void); #endif /* !__ASSEMBLY__ */ #endif /* _ASMARM64_PROCESSOR_H_ */ diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c index 7f61b3fff281f..152767eecf062 100644 --- a/lib/arm64/processor.c +++ b/lib/arm64/processor.c @@ -168,12 +168,18 @@ void install_vector_handler(enum vector v, vector_fn fn) vector_handlers[v] = fn; } -bool user_mode; +void thread_info_init(struct thread_info *ti, unsigned int flags) +{ + memset(ti, 0, sizeof(struct thread_info)); + ti->cpu = mpidr_to_cpu(get_mpidr()); + ti->flags = flags; +} + void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr) { sp_usr &= (~15UL); /* stack ptr needs 16-byte alignment */ - user_mode = true; + thread_info_init(thread_info_sp(sp_usr), TIF_USER_MODE); asm volatile( "mov x0, %0\n" @@ -184,3 +190,8 @@ void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr) "eret\n" :: "r" (arg), "r" (sp_usr), "r" (func) : "x0", "x3"); } + +bool is_user(void) +{ + return current_thread_info()->flags & TIF_USER_MODE; +}