From patchwork Sun Dec 24 10:07:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arbel Moshe X-Patchwork-Id: 10131919 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id AAF3C6019C for ; Sun, 24 Dec 2017 10:09:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 943A428C4D for ; Sun, 24 Dec 2017 10:09:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 88F3128C6A; Sun, 24 Dec 2017 10:09:08 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6CCF228C4D for ; Sun, 24 Dec 2017 10:09:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751894AbdLXKIz (ORCPT ); Sun, 24 Dec 2017 05:08:55 -0500 Received: from userp2120.oracle.com ([156.151.31.85]:32904 "EHLO userp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751323AbdLXKIy (ORCPT ); Sun, 24 Dec 2017 05:08:54 -0500 Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.21/8.16.0.21) with SMTP id vBOA7diL001265; Sun, 24 Dec 2017 10:08:51 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references; s=corp-2017-10-26; bh=aO1nPw2XjZIjLRhMuvUF3WbdFgcn3ApvdGf4yvZ34z4=; b=f+131mrTAhUtZGTQ+siOlNz6x6r9B+bCrQH9o8vY6YIlr69zj/79Z7dHBSE6KOu5MHyn e10b2AGwab88LPSMi9CgJ/JKU7x89n7b7w5ANpRXaET4EdH5sZ7+mGwbwxO2X0PnAEL5 hSnxnR+aggK+ZlwyZpW4LmYoDKSRhqsfI1GDiDRyWKL1oec5G/4vWHwgRp3q4X3cYhrZ XqwFfQeVm1ZKeJ2YM2F0b5/+K6aD0hu3EhUD03SxEu3elJTeozUHwYKPY4gzXJgxC+2d p2vYGXwp3706Esk7KRFZ6IDw3SagPUamv6BuLAU7dX/tSGUvHy2YNViJIT9yOnRo0Ovz Ig== Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp2120.oracle.com with ESMTP id 2f2a66g04k-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Sun, 24 Dec 2017 10:08:51 +0000 Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.14.4/8.14.4) with ESMTP id vBOA8okr028208 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Sun, 24 Dec 2017 10:08:50 GMT Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by aserv0121.oracle.com (8.14.4/8.13.8) with ESMTP id vBOA8ofQ009288; Sun, 24 Dec 2017 10:08:50 GMT Received: from spark.ravello.local (/213.57.127.2) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sun, 24 Dec 2017 02:08:49 -0800 From: Arbel Moshe To: pbonzini@redhat.com, rkrcmar@redhat.com, kvm@vger.kernel.org Cc: idan.brown@oracle.com, liran.alon@oracle.com, Arbel Moshe , Konrad Rzeszutek Wilk Subject: [PATCH 1/5] x86: Add utility to run function in User Mode Date: Sun, 24 Dec 2017 12:07:57 +0200 Message-Id: <20171224100801.145806-2-arbel.moshe@oracle.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171224100801.145806-1-arbel.moshe@oracle.com> References: <20171224100801.145806-1-arbel.moshe@oracle.com> X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=8754 signatures=668650 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1711220000 definitions=main-1712240137 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add usermode util that enables running a function in user mode. In addition, it enables catching an exception which is raised from the user-mode function. Signed-off-by: Arbel Moshe Reviewed-by: Liran Alon Signed-off-by: Konrad Rzeszutek Wilk --- lib/x86/usermode.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/x86/usermode.h | 30 ++++++++++++++ x86/Makefile.common | 1 + 3 files changed, 144 insertions(+) create mode 100644 lib/x86/usermode.c create mode 100644 lib/x86/usermode.h diff --git a/lib/x86/usermode.c b/lib/x86/usermode.c new file mode 100644 index 0000000..323d84d --- /dev/null +++ b/lib/x86/usermode.c @@ -0,0 +1,113 @@ +#include "x86/msr.h" +#include "x86/processor.h" +#include "x86/apic-defs.h" +#include "x86/apic.h" +#include "x86/desc.h" +#include "x86/isr.h" +#include "alloc.h" +#include "setjmp.h" +#include "usermode.h" + +#include "libcflat.h" +#include + +#define USERMODE_STACK_SIZE 0x2000 +#define RET_TO_KERNEL_IRQ 0x20 + +jmp_buf jmpbuf; + +static void restore_exec_to_jmpbuf(void) +{ + longjmp(jmpbuf, 1); +} + +static void restore_exec_to_jmpbuf_exception_handler(struct ex_regs *regs) +{ + /* longjmp must happen after iret, so do not do it now. */ + regs->rip = (unsigned long)&restore_exec_to_jmpbuf; + regs->cs = KERNEL_CS; +} + +uint64_t run_in_user(usermode_func func, unsigned int fault_vector, + uint64_t arg1, uint64_t arg2, uint64_t arg3, + uint64_t arg4, bool *raised_vector) +{ + extern char ret_to_kernel; + uint64_t rax = 0; + static unsigned char user_stack[USERMODE_STACK_SIZE]; + + *raised_vector = 0; + set_idt_entry(RET_TO_KERNEL_IRQ, &ret_to_kernel, 3); + handle_exception(fault_vector, + restore_exec_to_jmpbuf_exception_handler); + + if (setjmp(jmpbuf) != 0) { + *raised_vector = 1; + return 0; + } + + asm volatile ( + /* Backing Up Stack in rdi */ + "mov %%rsp, %%rdi\n\t" + /* Load user_ds to DS and ES */ + "mov %[user_ds], %%ax\n\t" + "mov %%ax, %%ds\n\t" + "mov %%ax, %%es\n\t" + /* IRET into user mode */ + "pushq %[user_ds]\n\t" + "pushq %[user_stack_top]\n\t" + "pushfq\n\t" + "pushq %[user_cs]\n\t" + "pushq $user_mode\n\t" + "iretq\n" + + "user_mode:\n\t" + /* Back up registers before invoking func */ + "push %%rbx\n\t" + "push %%rcx\n\t" + "push %%rdx\n\t" + "push %%r8\n\t" + "push %%r9\n\t" + "push %%r10\n\t" + "push %%r11\n\t" + "push %%rdi\n\t" + "push %%rsi\n\t" + /* Call user mode function */ + "mov %[arg1], %%rdi\n\t" + "mov %[arg2], %%rsi\n\t" + "mov %[arg3], %%rdx\n\t" + "mov %[arg4], %%rcx\n\t" + "call %[func]\n\t" + /* Restore registers */ + "pop %%rsi\n\t" + "pop %%rdi\n\t" + "pop %%r11\n\t" + "pop %%r10\n\t" + "pop %%r9\n\t" + "pop %%r8\n\t" + "pop %%rdx\n\t" + "pop %%rcx\n\t" + "pop %%rbx\n\t" + /* Return to kernel via system call */ + "int %[kernel_entry_vector]\n\t" + /* Kernel Mode */ + "ret_to_kernel:\n\t" + "mov %%rdi, %%rsp\n\t" + : + "+a"(rax) + : + [arg1]"m"(arg1), + [arg2]"m"(arg2), + [arg3]"m"(arg3), + [arg4]"m"(arg4), + [func]"m"(func), + [user_ds]"i"(USER_DS), + [user_cs]"i"(USER_CS), + [user_stack_top]"r"(user_stack + + sizeof(user_stack)), + [kernel_entry_vector]"i"(RET_TO_KERNEL_IRQ) + : + "rsi", "rdi", "rcx", "rdx"); + + return rax; +} diff --git a/lib/x86/usermode.h b/lib/x86/usermode.h new file mode 100644 index 0000000..4e005e6 --- /dev/null +++ b/lib/x86/usermode.h @@ -0,0 +1,30 @@ +#ifndef _USERMODE_H_ +#define _USERMODE_H_ + +#include "x86/msr.h" +#include "x86/processor.h" +#include "x86/apic-defs.h" +#include "x86/apic.h" +#include "x86/desc.h" +#include "x86/isr.h" +#include "alloc.h" +#include "setjmp.h" + +#include "libcflat.h" +#include + +typedef uint64_t (*usermode_func)(void); + +/* + * Run function in user mode + * Supports running functions with up to 4 arguments. + * fault_vector: exception vector that might get thrown during the function. + * raised_vector: outputs true if exception occurred. + * + * returns: return value returned by function, or 0 if an exception occurred. + */ +uint64_t run_in_user(usermode_func func, unsigned int fault_vector, + uint64_t arg1, uint64_t arg2, uint64_t arg3, + uint64_t arg4, bool *raised_vector); + +#endif diff --git a/x86/Makefile.common b/x86/Makefile.common index 5f7eac4..8a9d245 100644 --- a/x86/Makefile.common +++ b/x86/Makefile.common @@ -19,6 +19,7 @@ cflatobjs += lib/x86/desc.o cflatobjs += lib/x86/isr.o cflatobjs += lib/x86/acpi.o cflatobjs += lib/x86/stack.o +cflatobjs += lib/x86/usermode.o OBJDIRS += lib/x86