From patchwork Sat May 2 11:36:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 1281673 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49DqD922cxz9sRf for ; Sat, 2 May 2020 23:07:53 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=CyJDezAF; dkim-atps=neutral Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 49DqD84cXWzDrQg for ; Sat, 2 May 2020 23:07:52 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::643; helo=mail-pl1-x643.google.com; envelope-from=npiggin@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=CyJDezAF; dkim-atps=neutral Received: from mail-pl1-x643.google.com (mail-pl1-x643.google.com [IPv6:2607:f8b0:4864:20::643]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 49DnDS2QSKzDr7J for ; Sat, 2 May 2020 21:38:00 +1000 (AEST) Received: by mail-pl1-x643.google.com with SMTP id w3so4698988plz.5 for ; Sat, 02 May 2020 04:37:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=grxRJ5s6YFHViXGJBy85nlsQKAZLuxpSCvzZfi/LTi0=; b=CyJDezAFm10KQPKiB4OEjk1n04soqOge496rBQX3YUh4iNIX96J/ye7aVbNXvClKPt R6dYhWUHvC8QMNyGnigaU00vSNpkxyMVtamFM7hs84t7yRNcWeqI1bTCSyptI8Rky0D6 s2YMxjppv8n9GwK38A0tx0dHjtnnsaSeCe6jGH0mVyi50EaiWDrOL97jF4zUogMu12Wj Jl0qqS9YsnyXGEgKF4G79PBt5KXSDQZBMS1Jj1b8S6NmnZzZRY4lyi7IlEI8igwouREF VacZaeJdBJHpHFa5L9qNq0evEjGbccM3Eavdl5ULCRreY9LsidXy/llyn2kI2MeS+8RY gFhg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=grxRJ5s6YFHViXGJBy85nlsQKAZLuxpSCvzZfi/LTi0=; b=CQj+JpbdBuMphRBmCQAAinxK89WlkFT38ltYIfBLvvYXUHO0W/JDQBO76KXEsxlfNC dkp1/Fx+PUwN6+j5UG6oF0ii8mBBzSeOqLrZRMyjjs4CeLHgWnJYItkr7NVfQeMANwq0 OPklfw2Dxe8elNc9Qeew4ya3mDnfA+atCOS1QCL7Vy5a/cwv7JHDclP4n9QTIh18dcjQ aYjzZg4TkFYcOX5gTGI9CG2mAHRd4r9Ziw+2+Xsedltq9yiZr6xDB/pEbLbFyC/Gedxk VaebdmDelOgX5AOq6eIJUqpJ9j6wOPsH1GoLbzQFILODpug2cojTtm9JRomPzLPrpbOa Npzw== X-Gm-Message-State: AGi0PuZi4o+ku6KosQO24gG6Bpw7Ed1xJlgTzdjdYdgN2wYmyQ8bb4Ac XKyopgCwPM1H3qnKCYJewfvG5FRQ X-Google-Smtp-Source: APiQypKxLr+e7FvJ69BM3Zf0fzkcIWyVoeCAzFVHXX1zZqQ2Yeal28f0ptqC71mgNs+lQQXs+/d/1w== X-Received: by 2002:a17:90a:1998:: with SMTP id 24mr5588429pji.0.1588419476994; Sat, 02 May 2020 04:37:56 -0700 (PDT) Received: from bobo.ozlabs.ibm.com ([203.220.177.17]) by smtp.gmail.com with ESMTPSA id e135sm4367513pfh.37.2020.05.02.04.37.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 04:37:56 -0700 (PDT) From: Nicholas Piggin To: skiboot@lists.ozlabs.org Date: Sat, 2 May 2020 21:36:49 +1000 Message-Id: <20200502113649.176329-10-npiggin@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20200502113649.176329-1-npiggin@gmail.com> References: <20200502113649.176329-1-npiggin@gmail.com> MIME-Version: 1.0 Subject: [Skiboot] [RFC PATCH 9/9] OPAL V4: local vm_map/unmap operations X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This implements vm_map/unmap API that an OS can provide. The per-CPU areas are advertised by OPAL_FIND_VM_AREA so page tables can be allocated ahead of time. The ops must not sleep or cause IPIs. This allows skiboot to run entirely in virtual mode and not have to drop to real mode to cope with vm_map(). Signed-off-by: Nicholas Piggin --- core/console-log.c | 2 +- core/opal.c | 37 ++++++++++++++++++++++ core/vm.c | 70 ++++++++++++++++++++++++++++++++++------- include/config.h | 1 + include/opal-api.h | 3 ++ include/opal-internal.h | 4 +++ include/skiboot.h | 1 + 7 files changed, 105 insertions(+), 13 deletions(-) diff --git a/core/console-log.c b/core/console-log.c index d73913894..2899c1c56 100644 --- a/core/console-log.c +++ b/core/console-log.c @@ -35,7 +35,7 @@ static int vprlog(int log_level, const char *fmt, va_list ap) if (log_level > (debug_descriptor.console_log_levels >> 4)) return 0; - if (opal_v4_os) { + if (os_ops.os_printf) { count = vsnprintf(buffer, sizeof(buffer), fmt, ap); os_printf(log_level, buffer); return count; diff --git a/core/opal.c b/core/opal.c index 5454cac67..bb71ac374 100644 --- a/core/opal.c +++ b/core/opal.c @@ -506,6 +506,12 @@ static int64_t opal_register_os_ops(struct opal_os_ops *ops, uint64_t size) set_opal_console_to_raw(); } + if (size >= 24) { + os_ops.os_vm_map = (void *)be64_to_cpu(ops->os_vm_map); + os_ops.os_vm_unmap = (void *)be64_to_cpu(ops->os_vm_unmap); + vm_resurrect(); + } + checksum_romem(); opal_v4_os = true; @@ -519,6 +525,37 @@ void os_printf(uint32_t log_level, const char *str) os_ops.os_printf(log_level, str); } +int64_t os_vm_map(uint64_t ea, uint64_t pa, uint64_t flags) +{ + struct cpu_thread *cpu = this_cpu(); + uint64_t msr = mfmsr(); + int64_t ret; + + if (msr != cpu->opal_call_msr) + mtmsrd(cpu->opal_call_msr, 0); + + ret = os_ops.os_vm_map(ea, pa, flags); + + if (msr != cpu->opal_call_msr) + mtmsrd(cpu->opal_call_msr, 0); + + return ret; +} + +void os_vm_unmap(uint64_t ea) +{ + struct cpu_thread *cpu = this_cpu(); + uint64_t msr = mfmsr(); + + if (msr != cpu->opal_call_msr) + mtmsrd(cpu->opal_call_msr, 0); + + os_ops.os_vm_unmap(ea); + + if (msr != cpu->opal_call_msr) + mtmsrd(cpu->opal_call_msr, 0); +} + void add_opal_node(void) { uint64_t base, entry, size; diff --git a/core/vm.c b/core/vm.c index b2830fccf..2ecfaeb44 100644 --- a/core/vm.c +++ b/core/vm.c @@ -35,6 +35,7 @@ static bool vm_globals_allocated = false; #define LOCAL_SLB_BASE GLOBAL_SLB_NR #define LOCAL_EA_PERCPU (SLB_SZ) +#define OS_LOCAL_EA_PERCPU (2ULL*1024*1024) #define LOCAL_EA_BEGIN 0x0008000000000000ULL #define LOCAL_EA_END 0x0009000000000000ULL @@ -485,13 +486,16 @@ void *vm_map(unsigned long addr, unsigned long len, bool rw) addr &= ~(PAGE_SIZE - 1); len = end - addr; - assert(len <= LOCAL_EA_PERCPU); + if (cpu_in_os()) + assert(len <= OS_LOCAL_EA_PERCPU); + else + assert(len <= LOCAL_EA_PERCPU); /* Can't do nested mappings */ assert(!c->vm_local_map_inuse); c->vm_local_map_inuse = true; - if (cpu_in_os() && c->vm_setup) { + if (cpu_in_os() && c->vm_setup && !os_ops.os_vm_map) { assert(c->opal_call_msr & (MSR_IR|MSR_DR)); newaddr = addr; mtmsr(c->opal_call_msr & ~MSR_DR); @@ -501,9 +505,10 @@ void *vm_map(unsigned long addr, unsigned long len, bool rw) } else { struct vm_map *new = &c->vm_local_map; - assert(!cpu_in_os()); - - newaddr = LOCAL_EA_BEGIN + LOCAL_EA_PERCPU * c->pir; + if (cpu_in_os()) + newaddr = LOCAL_EA_BEGIN + OS_LOCAL_EA_PERCPU * c->pir; + else + newaddr = LOCAL_EA_BEGIN + LOCAL_EA_PERCPU * c->pir; new->name = "local"; new->address = newaddr; @@ -513,6 +518,20 @@ void *vm_map(unsigned long addr, unsigned long len, bool rw) new->writeable = rw; new->executable = false; new->ci = false; + + if (cpu_in_os()) { + uint64_t ea, pa, flags; + + flags = vmm_os_map_flags(new); + + pa = new->pa; + ea = newaddr; + while (ea < newaddr + len) { + os_vm_map(ea, pa, flags); + ea += OS_PAGE_SIZE; + pa += OS_PAGE_SIZE; + } + } } return (void *)newaddr + offset; @@ -528,12 +547,15 @@ void vm_unmap(unsigned long addr, unsigned long len) addr &= ~(PAGE_SIZE - 1); len = end - addr; - assert(len <= LOCAL_EA_PERCPU); + if (cpu_in_os()) + assert(len <= OS_LOCAL_EA_PERCPU); + else + assert(len <= LOCAL_EA_PERCPU); assert(c->vm_local_map_inuse); c->vm_local_map_inuse = false; - if (cpu_in_os() && (c->opal_call_msr & (MSR_IR|MSR_DR))) { + if (cpu_in_os() && (c->opal_call_msr & (MSR_IR|MSR_DR)) && !os_ops.os_vm_map) { assert(!c->vm_setup); c->vm_setup = true; mtmsr(c->opal_call_msr); @@ -543,9 +565,10 @@ void vm_unmap(unsigned long addr, unsigned long len) struct vm_map *vmm; unsigned long ea; - assert(!cpu_in_os()); - - newaddr = LOCAL_EA_BEGIN + LOCAL_EA_PERCPU * c->pir; + if (cpu_in_os()) + newaddr = LOCAL_EA_BEGIN + OS_LOCAL_EA_PERCPU * c->pir; + else + newaddr = LOCAL_EA_BEGIN + LOCAL_EA_PERCPU * c->pir; vmm = &c->vm_local_map; assert(newaddr == vmm->address); @@ -554,8 +577,13 @@ void vm_unmap(unsigned long addr, unsigned long len) ea = newaddr; while (ea < newaddr + len) { - htab_remove(ea, true); - ea += PAGE_SIZE; + if (cpu_in_os()) { + os_vm_unmap(ea); + ea += OS_PAGE_SIZE; + } else { + htab_remove(ea, true); + ea += PAGE_SIZE; + } } } } @@ -987,6 +1015,24 @@ static int64_t opal_find_vm_area(uint64_t addr, struct opal_vm_area *opal_vm_are return OPAL_SUCCESS; } + if (addr < LOCAL_EA_BEGIN) { + opal_vm_area->address = cpu_to_be64(LOCAL_EA_BEGIN); + opal_vm_area->length = cpu_to_be64(cpu_max_pir * OS_LOCAL_EA_PERCPU); + opal_vm_area->pa = 0; + opal_vm_area->vm_flags = 0; + + printf("0x%016llx-0x%016llx flags=0 (per-cpu maps)\n", LOCAL_EA_BEGIN, LOCAL_EA_BEGIN + cpu_max_pir * OS_LOCAL_EA_PERCPU); + + return OPAL_SUCCESS; + } + return OPAL_EMPTY; } opal_call(OPAL_FIND_VM_AREA, opal_find_vm_area, 2); + +void vm_resurrect(void) +{ + /* OS takes over control of providing VM mappings */ + prlog(PR_NOTICE, "VMM: Rise from your grave!\n"); + print_maps(); +} diff --git a/include/config.h b/include/config.h index fd9521fa2..70608d120 100644 --- a/include/config.h +++ b/include/config.h @@ -6,6 +6,7 @@ /* Alignment to which skiboot lays out memory. */ #define PAGE_SIZE 0x10000 +#define OS_PAGE_SIZE 0x10000 #define HAVE_TYPEOF 1 #define HAVE_BUILTIN_TYPES_COMPATIBLE_P 1 diff --git a/include/opal-api.h b/include/opal-api.h index 139dc1d43..3c630f02e 100644 --- a/include/opal-api.h +++ b/include/opal-api.h @@ -1278,6 +1278,9 @@ struct opal_vm_area { struct opal_os_ops { __be64 os_printf; /* void printf(int32_t level, const char *str) */ + __be64 os_vm_map; /* void os_vm_map(uint64_t ea, uint64_t pa, uint64_t flags) */ + __be64 os_vm_unmap; /* static void os_vm_unmap(uint64_t ea) */ + }; #endif /* __ASSEMBLY__ */ diff --git a/include/opal-internal.h b/include/opal-internal.h index 64f372489..af5216639 100644 --- a/include/opal-internal.h +++ b/include/opal-internal.h @@ -20,12 +20,16 @@ struct opal_table_entry { struct os_ops { void (*os_printf)(uint32_t log_level, const char *str); + int64_t (*os_vm_map)(uint64_t ea, uint64_t pa, uint64_t flags); + void (*os_vm_unmap)(uint64_t ea); }; extern bool opal_v4_os; extern struct os_ops os_ops; extern void os_printf(uint32_t log_level, const char *str); +extern int64_t os_vm_map(uint64_t ea, uint64_t pa, uint64_t flags); +extern void os_vm_unmap(uint64_t ea); #ifdef __CHECKER__ #define __opal_func_test_arg(__func, __nargs) 0 diff --git a/include/skiboot.h b/include/skiboot.h index aacb425f7..5f0e3e0f7 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -362,5 +362,6 @@ bool vm_dslb(uint64_t nia, uint64_t dar); bool vm_islb(uint64_t nia); bool vm_dsi(uint64_t nia, uint64_t dar, uint32_t dsisr); bool vm_isi(uint64_t nia); +void vm_resurrect(void); #endif /* __SKIBOOT_H */