From nobody Sat May 18 05:05:00 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1687258712; cv=none; d=zohomail.com; s=zohoarc; b=lms+1UWoHB09OnvZX5hmY+RPn+Yh2FD1iFGlXil+MhNUWGgnB3AGY1tVjMK50iJ5NVxI8bfhh0P3NnDPAQ4JojK+pWfBWJxgx/xS0WLOlh0hyVLb2KNflXDF48Y5fpidlYHnVWK4VFSmr8x/hRJj3akWKE9YHWvw7sSalOv9xLo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1687258712; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=+doDSOWQ/yYEapg3XaTRgcOqrIoUXvANsMUQVhLDyMA=; b=BxcMc0eLOG8hCpYAjRxVN9ztDuH3JTGWtwxdaBIuDFKBVBip+CouL+arx2r/LClSvqdv0+oifFxx5DanvZkwZUYGnNuA0K6/98y1La/M6x+pYeBhLspWDrCfZf/Tih9txekfSdLcUaAGOgocEa1xfrjg6Q+kik3alS+z5kN7tO8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1687258712815368.5621258178609; Tue, 20 Jun 2023 03:58:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qBZ3Z-0007FU-Rq; Tue, 20 Jun 2023 06:57:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qBZ3Y-0007ET-KZ; Tue, 20 Jun 2023 06:57:52 -0400 Received: from mail-pf1-x434.google.com ([2607:f8b0:4864:20::434]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qBZ3X-0000hz-0p; Tue, 20 Jun 2023 06:57:52 -0400 Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-6682909acadso1351387b3a.3; Tue, 20 Jun 2023 03:57:50 -0700 (PDT) Received: from wheely.local0.net ([124.170.190.103]) by smtp.gmail.com with ESMTPSA id n13-20020aa78a4d000000b0064fabbc047dsm1126412pfa.55.2023.06.20.03.57.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jun 2023 03:57:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1687258669; x=1689850669; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+doDSOWQ/yYEapg3XaTRgcOqrIoUXvANsMUQVhLDyMA=; b=RuWDoeE2SRjM73rbyhd6QEMqM9I+3QFYSwcVvF6B85HWv1tlKcn+Td8bImi6Rcz+sD KBXq5NckO74hkl77LR9/Ork7yfbSUJS77ukV0TPgOZ2tOVgcbKRHjOw4SE1aU3xCYr1P OnEP2KEzSKYIFR2TWOL5dSmD+iqnzk0eJvEjRJZGbHwTv9NcY5/bhIW5yGbpz8wQSp+X nMsrEWdFCejTdoXTL/A6dhgOCgXhUdMnO98hAXAVAJD2cLAFKz6FFezcZgL9yC90OEAz a5YxG6v04IbB4Vfuddjzcz8IisiQU4htznl8GxCViMczPGs3wCmllYny/HSLZJaaiKR+ gVvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1687258669; x=1689850669; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+doDSOWQ/yYEapg3XaTRgcOqrIoUXvANsMUQVhLDyMA=; b=Nq0DKQJN8xKqdgSdPz0GU3Lv0hkXXMCF1Oj7SDIET0m6uwfmrYc3nkH9FeNw4rqSg1 vZeXG/cAk8zkQfvje1aCL2NtjsppV2avDNxPlHAOECcEvnvJg/Dm2cD6GkIfcp33ZF7t YufhvRHgWfjveG9RpdzVhTILFPYl6z08Au4AIHXPb/GMZiLeWi9YN8bx4WUs5jMX3d6Y J2Q30YOYrDgf/0gvKruG658kO2pE42iVKIEqVv+Y9PmgAm0ER0zYx2JaHQ7y6Yjn+nE8 fJsco/DQCxItn1FQwop6200GGLcxDlWeoAYUwFdGGf4IH29uD59ntqiHF1O3jOiH6pOK HCEg== X-Gm-Message-State: AC+VfDwPH3DR4skjjq7ZjGIv18s73l5zcAXBpKek90Te1U30hHCfgx3D gch+3FFnVoJFLHLKUYlL7LRqDEkDWtc= X-Google-Smtp-Source: ACHHUZ5LSp4jZWtmh7mHwn7OWSY27v/HyqWbLFQzznfYRDAHN0r/MCkdDlmkpcKeOq/DoNu5td4WjA== X-Received: by 2002:a05:6a00:1407:b0:668:94a2:2ec7 with SMTP id l7-20020a056a00140700b0066894a22ec7mr1947562pfu.25.1687258669141; Tue, 20 Jun 2023 03:57:49 -0700 (PDT) From: Nicholas Piggin To: qemu-ppc@nongnu.org Cc: Nicholas Piggin , qemu-devel@nongnu.org, Harsh Prateek Bora , Daniel Henrique Barboza Subject: [PATCH v2 1/4] ppc/spapr: H_ENTER_NESTED should restore host XER ca field Date: Tue, 20 Jun 2023 20:57:34 +1000 Message-Id: <20230620105737.160451-2-npiggin@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230620105737.160451-1-npiggin@gmail.com> References: <20230620105737.160451-1-npiggin@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::434; envelope-from=npiggin@gmail.com; helo=mail-pf1-x434.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1687258713463100001 Content-Type: text/plain; charset="utf-8" Fix missing env->ca restore when going from L2 back to the host. Fixes: 120f738a467 ("spapr: implement nested-hv capability for the virtual = hypervisor") Reviewed-by: Harsh Prateek Bora Signed-off-by: Nicholas Piggin --- hw/ppc/spapr_hcall.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index b904755575..0582b524d1 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1773,6 +1773,7 @@ out_restore_l1: env->cfar =3D spapr_cpu->nested_host_state->cfar; env->xer =3D spapr_cpu->nested_host_state->xer; env->so =3D spapr_cpu->nested_host_state->so; + env->ca =3D spapr_cpu->nested_host_state->ca; env->ov =3D spapr_cpu->nested_host_state->ov; env->ov32 =3D spapr_cpu->nested_host_state->ov32; env->ca32 =3D spapr_cpu->nested_host_state->ca32; --=20 2.40.1 From nobody Sat May 18 05:05:00 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1687258690; cv=none; d=zohomail.com; s=zohoarc; b=juFo8o87h2N2cJtXCu/aEf5YxVO/2TE/uQAAwnBGOzcd8mKQeFvERIO4DsCGVPYZROOR/WozSkpmmXP9vblI42ShHsN63oD6TESUmUhBLQfhlJuqGQ0Hkct7or2qPdPAKBH/5j3CZxBcIhRSTpLU7eeGNTOD6iG7cJVT5xBr2EA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1687258690; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=yFlfiy1zGO5UYeiwXiPQNhhJp+VR3RnTyymo4nqOQIY=; b=W9geeZcKTcQZH7yGu4EdACj1TFAGoT+geZT1b+XHecogC3T7PQIx/vyv85MXyCDLRXNHM8TdWHLqSggTve2A+1vadK87DGjX5q1+KiDN0TVDHWhMNFYbfNH5BcYXwiLSgCKo9EuB6r518d4lB5fqA7m0fO1inq9o0zEU3i1619g= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1687258690763779.0104761529246; Tue, 20 Jun 2023 03:58:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qBZ3d-0007IG-NY; Tue, 20 Jun 2023 06:57:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qBZ3c-0007Hr-Gr; Tue, 20 Jun 2023 06:57:56 -0400 Received: from mail-pg1-x536.google.com ([2607:f8b0:4864:20::536]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qBZ3a-0000if-BS; Tue, 20 Jun 2023 06:57:56 -0400 Received: by mail-pg1-x536.google.com with SMTP id 41be03b00d2f7-543ae6ce8d1so3735551a12.2; Tue, 20 Jun 2023 03:57:53 -0700 (PDT) Received: from wheely.local0.net ([124.170.190.103]) by smtp.gmail.com with ESMTPSA id n13-20020aa78a4d000000b0064fabbc047dsm1126412pfa.55.2023.06.20.03.57.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jun 2023 03:57:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1687258672; x=1689850672; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=yFlfiy1zGO5UYeiwXiPQNhhJp+VR3RnTyymo4nqOQIY=; b=nDWASKygpgg+BVwo4cTHIckAIbwtRGulWtkxIpOKGjbytNkpw39gT8g24uCOsEXGgl 1PWEca/MUZVFeABuvoEdWJCnAsVhchcVddxWO2iKIKYYSJescm3EqWvzKlzSZvnf61xh 6NfwRFZT1RSUQ8hGV0vQi4oeysyXq+17m1cSaEaQdOtL1gFd7sfOkQnNhtiGEjAfEtsa J/2UFGhB0PkpmQ+HLcMsinArQLoOKeFkw+7ey0ev8p2Oom22yY8GFZS+GSdb5214EumF QvjOArtgPtEaTBy3NI4Q4u5P6KXLMYiwhRV1lp3m5wh05mvUri0m3uIpg6ENEKGXI6WI PXuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1687258672; x=1689850672; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=yFlfiy1zGO5UYeiwXiPQNhhJp+VR3RnTyymo4nqOQIY=; b=WlaUPZx0gFjQsTyv4F/QH9q5sRN75sn9bCcgHlBztedGLjf8/ZFkmzzB+BKrO7JxHM XtlChQMwjgEMzaymfI64/F/psxIGHOq3LOAQTbDhjbppJ0fcWVyg/WHkgT4IDR8se6ZU ykqj+GcnweM/7ehLM6FDZKO5y9bCR5evUROpUVjm6vldionBMCEcSzn5tP5K9ELuSJTo 9TJ5+5+USZgS2TEVPBuCOVnWYos7lMUFYgXEtZIBiNwECv9ZS/6Q0HpLaxTQwzLhauYv /AwLbTvr4pma/nIYwAZZYyqfZwiQPYHNHQczYBx7wYtUUUr1CLj6s7cZnmBb/1p+tmKH VFzw== X-Gm-Message-State: AC+VfDyrXpVntG50VloEhTkaVXOLaWZkYtcrlW3LA5E2HARWEWS81wbN rJMZysheklQKDPprGucN0+6YF8WUCXU= X-Google-Smtp-Source: ACHHUZ5lv0Lh/VfFHHus4/4FJBGaqcwyTeNPaQd7EHTDXptZ3zQLvmawgWRaCd2ywpqdD4HBysTJ9g== X-Received: by 2002:a05:6a20:144a:b0:122:d1c3:59ed with SMTP id a10-20020a056a20144a00b00122d1c359edmr502984pzi.40.1687258672228; Tue, 20 Jun 2023 03:57:52 -0700 (PDT) From: Nicholas Piggin To: qemu-ppc@nongnu.org Cc: Nicholas Piggin , qemu-devel@nongnu.org, Harsh Prateek Bora , Daniel Henrique Barboza Subject: [PATCH v2 2/4] ppc/spapr: Add a nested state struct Date: Tue, 20 Jun 2023 20:57:35 +1000 Message-Id: <20230620105737.160451-3-npiggin@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230620105737.160451-1-npiggin@gmail.com> References: <20230620105737.160451-1-npiggin@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::536; envelope-from=npiggin@gmail.com; helo=mail-pg1-x536.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1687258691582100005 Content-Type: text/plain; charset="utf-8" Rather than use a copy of CPUPPCState to store the host state while the environment has been switched to the L2, use a new struct for this purpose. Have helper functions to save and load this host state. Reviewed-by: Harsh Prateek Bora Signed-off-by: Nicholas Piggin --- hw/ppc/spapr_hcall.c | 150 ++++++++++++++++++++++++-------- include/hw/ppc/spapr_cpu_core.h | 5 +- 2 files changed, 115 insertions(+), 40 deletions(-) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 0582b524d1..d5b8d54692 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1546,6 +1546,112 @@ static target_ulong h_copy_tofrom_guest(PowerPCCPU = *cpu, return H_FUNCTION; } =20 +struct nested_ppc_state { + uint64_t gpr[32]; + uint64_t lr; + uint64_t ctr; + uint64_t cfar; + uint64_t msr; + uint64_t nip; + uint32_t cr; + + uint64_t xer; + + uint64_t lpcr; + uint64_t lpidr; + uint64_t pidr; + uint64_t pcr; + uint64_t dpdes; + uint64_t hfscr; + uint64_t srr0; + uint64_t srr1; + uint64_t sprg0; + uint64_t sprg1; + uint64_t sprg2; + uint64_t sprg3; + uint64_t ppr; + + int64_t tb_offset; +}; + +static void nested_save_state(struct nested_ppc_state *save, PowerPCCPU *c= pu) +{ + CPUPPCState *env =3D &cpu->env; + + memcpy(save->gpr, env->gpr, sizeof(save->gpr)); + + save->lr =3D env->lr; + save->ctr =3D env->ctr; + save->cfar =3D env->cfar; + save->msr =3D env->msr; + save->nip =3D env->nip; + + save->cr =3D ppc_get_cr(env); + save->xer =3D cpu_read_xer(env); + + save->lpcr =3D env->spr[SPR_LPCR]; + save->lpidr =3D env->spr[SPR_LPIDR]; + save->pcr =3D env->spr[SPR_PCR]; + save->dpdes =3D env->spr[SPR_DPDES]; + save->hfscr =3D env->spr[SPR_HFSCR]; + save->srr0 =3D env->spr[SPR_SRR0]; + save->srr1 =3D env->spr[SPR_SRR1]; + save->sprg0 =3D env->spr[SPR_SPRG0]; + save->sprg1 =3D env->spr[SPR_SPRG1]; + save->sprg2 =3D env->spr[SPR_SPRG2]; + save->sprg3 =3D env->spr[SPR_SPRG3]; + save->pidr =3D env->spr[SPR_BOOKS_PID]; + save->ppr =3D env->spr[SPR_PPR]; + + save->tb_offset =3D env->tb_env->tb_offset; +} + +static void nested_load_state(PowerPCCPU *cpu, struct nested_ppc_state *lo= ad) +{ + CPUState *cs =3D CPU(cpu); + CPUPPCState *env =3D &cpu->env; + + memcpy(env->gpr, load->gpr, sizeof(env->gpr)); + + env->lr =3D load->lr; + env->ctr =3D load->ctr; + env->cfar =3D load->cfar; + env->msr =3D load->msr; + env->nip =3D load->nip; + + ppc_set_cr(env, load->cr); + cpu_write_xer(env, load->xer); + + env->spr[SPR_LPCR] =3D load->lpcr; + env->spr[SPR_LPIDR] =3D load->lpidr; + env->spr[SPR_PCR] =3D load->pcr; + env->spr[SPR_DPDES] =3D load->dpdes; + env->spr[SPR_HFSCR] =3D load->hfscr; + env->spr[SPR_SRR0] =3D load->srr0; + env->spr[SPR_SRR1] =3D load->srr1; + env->spr[SPR_SPRG0] =3D load->sprg0; + env->spr[SPR_SPRG1] =3D load->sprg1; + env->spr[SPR_SPRG2] =3D load->sprg2; + env->spr[SPR_SPRG3] =3D load->sprg3; + env->spr[SPR_BOOKS_PID] =3D load->pidr; + env->spr[SPR_PPR] =3D load->ppr; + + env->tb_env->tb_offset =3D load->tb_offset; + + /* + * MSR updated, compute hflags and possible interrupts. + */ + hreg_compute_hflags(env); + ppc_maybe_interrupt(env); + + /* + * Nested HV does not tag TLB entries between L1 and L2, so must + * flush on transition. + */ + tlb_flush(cs); + env->reserve_addr =3D -1; /* Reset the reservation */ +} + /* * When this handler returns, the environment is switched to the L2 guest * and TCG begins running that. spapr_exit_nested() performs the switch fr= om @@ -1593,12 +1699,14 @@ static target_ulong h_enter_nested(PowerPCCPU *cpu, return H_PARAMETER; } =20 - spapr_cpu->nested_host_state =3D g_try_new(CPUPPCState, 1); + spapr_cpu->nested_host_state =3D g_try_new(struct nested_ppc_state, 1); if (!spapr_cpu->nested_host_state) { return H_NO_MEM; } =20 - memcpy(spapr_cpu->nested_host_state, env, sizeof(CPUPPCState)); + assert(env->spr[SPR_LPIDR] =3D=3D 0); + assert(env->spr[SPR_DPDES] =3D=3D 0); + nested_save_state(spapr_cpu->nested_host_state, cpu); =20 len =3D sizeof(*regs); regs =3D address_space_map(CPU(cpu)->as, regs_ptr, &len, false, @@ -1639,7 +1747,6 @@ static target_ulong h_enter_nested(PowerPCCPU *cpu, env->spr[SPR_DPDES] =3D hv_state.dpdes; env->spr[SPR_HFSCR] =3D hv_state.hfscr; hdec =3D hv_state.hdec_expiry - now; - spapr_cpu->nested_tb_offset =3D hv_state.tb_offset; /* TCG does not implement DAWR*, CIABR, PURR, SPURR, IC, VTB, HEIR SPR= s*/ env->spr[SPR_SRR0] =3D hv_state.srr0; env->spr[SPR_SRR1] =3D hv_state.srr1; @@ -1665,7 +1772,7 @@ static target_ulong h_enter_nested(PowerPCCPU *cpu, * and it's not obviously worth a new data structure to do it. */ =20 - env->tb_env->tb_offset +=3D spapr_cpu->nested_tb_offset; + env->tb_env->tb_offset +=3D hv_state.tb_offset; spapr_cpu->in_nested =3D true; =20 hreg_compute_hflags(env); @@ -1684,7 +1791,6 @@ static target_ulong h_enter_nested(PowerPCCPU *cpu, =20 void spapr_exit_nested(PowerPCCPU *cpu, int excp) { - CPUState *cs =3D CPU(cpu); CPUPPCState *env =3D &cpu->env; SpaprCpuState *spapr_cpu =3D spapr_cpu_state(cpu); target_ulong r3_return =3D env->excp_vectors[excp]; /* hcall return va= lue */ @@ -1766,34 +1872,8 @@ void spapr_exit_nested(PowerPCCPU *cpu, int excp) address_space_unmap(CPU(cpu)->as, regs, len, len, true); =20 out_restore_l1: - memcpy(env->gpr, spapr_cpu->nested_host_state->gpr, sizeof(env->gpr)); - env->lr =3D spapr_cpu->nested_host_state->lr; - env->ctr =3D spapr_cpu->nested_host_state->ctr; - memcpy(env->crf, spapr_cpu->nested_host_state->crf, sizeof(env->crf)); - env->cfar =3D spapr_cpu->nested_host_state->cfar; - env->xer =3D spapr_cpu->nested_host_state->xer; - env->so =3D spapr_cpu->nested_host_state->so; - env->ca =3D spapr_cpu->nested_host_state->ca; - env->ov =3D spapr_cpu->nested_host_state->ov; - env->ov32 =3D spapr_cpu->nested_host_state->ov32; - env->ca32 =3D spapr_cpu->nested_host_state->ca32; - env->msr =3D spapr_cpu->nested_host_state->msr; - env->nip =3D spapr_cpu->nested_host_state->nip; - assert(env->spr[SPR_LPIDR] !=3D 0); - env->spr[SPR_LPCR] =3D spapr_cpu->nested_host_state->spr[SPR_LPCR]; - env->spr[SPR_LPIDR] =3D spapr_cpu->nested_host_state->spr[SPR_LPIDR]; - env->spr[SPR_PCR] =3D spapr_cpu->nested_host_state->spr[SPR_PCR]; - env->spr[SPR_DPDES] =3D 0; - env->spr[SPR_HFSCR] =3D spapr_cpu->nested_host_state->spr[SPR_HFSCR]; - env->spr[SPR_SRR0] =3D spapr_cpu->nested_host_state->spr[SPR_SRR0]; - env->spr[SPR_SRR1] =3D spapr_cpu->nested_host_state->spr[SPR_SRR1]; - env->spr[SPR_SPRG0] =3D spapr_cpu->nested_host_state->spr[SPR_SPRG0]; - env->spr[SPR_SPRG1] =3D spapr_cpu->nested_host_state->spr[SPR_SPRG1]; - env->spr[SPR_SPRG2] =3D spapr_cpu->nested_host_state->spr[SPR_SPRG2]; - env->spr[SPR_SPRG3] =3D spapr_cpu->nested_host_state->spr[SPR_SPRG3]; - env->spr[SPR_BOOKS_PID] =3D spapr_cpu->nested_host_state->spr[SPR_BOOK= S_PID]; - env->spr[SPR_PPR] =3D spapr_cpu->nested_host_state->spr[SPR_PPR]; + nested_load_state(cpu, spapr_cpu->nested_host_state); =20 /* * Return the interrupt vector address from H_ENTER_NESTED to the L1 @@ -1801,14 +1881,8 @@ out_restore_l1: */ env->gpr[3] =3D r3_return; =20 - env->tb_env->tb_offset -=3D spapr_cpu->nested_tb_offset; spapr_cpu->in_nested =3D false; =20 - hreg_compute_hflags(env); - ppc_maybe_interrupt(env); - tlb_flush(cs); - env->reserve_addr =3D -1; /* Reset the reservation */ - g_free(spapr_cpu->nested_host_state); spapr_cpu->nested_host_state =3D NULL; } diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_cor= e.h index b560514560..69a52e39b8 100644 --- a/include/hw/ppc/spapr_cpu_core.h +++ b/include/hw/ppc/spapr_cpu_core.h @@ -41,6 +41,8 @@ void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ul= ong nip, target_ulong r1, target_ulong r3, target_ulong r4); =20 +struct nested_ppc_state; + typedef struct SpaprCpuState { uint64_t vpa_addr; uint64_t slb_shadow_addr, slb_shadow_size; @@ -51,8 +53,7 @@ typedef struct SpaprCpuState { =20 /* Fields for nested-HV support */ bool in_nested; /* true while the L2 is executing */ - CPUPPCState *nested_host_state; /* holds the L1 state while L2 execute= s */ - int64_t nested_tb_offset; /* L1->L2 TB offset */ + struct nested_ppc_state *nested_host_state; /* holds the L1 state whil= e L2 executes */ } SpaprCpuState; =20 static inline SpaprCpuState *spapr_cpu_state(PowerPCCPU *cpu) --=20 2.40.1 From nobody Sat May 18 05:05:00 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1687258737; cv=none; d=zohomail.com; s=zohoarc; b=X07+dY1WAFNk1cxEgCmBGchHzjavB7C0muswdmuf0/348Exc6DT9AFTTzXNsrlaZrSrGDbEwWW5PEUD97NvnLHLtgU+HqLGo+uEWAgwcWYtHg6P1ekwDrxzGzYRujGt9IBgKnaPU6pJTcMwYgA30IUmTMq2B9hFGU8bhGOe6P68= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1687258737; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=SWZnKJXRiJBNnfnp5cfb9V+MeQ+/jjMQ9HeaYGeoqGY=; b=FZOomgY5Wa/6hK75Sn9EORhs+W6sKgmrg0mlEjqWCwOhAh2f44w5j17N/OgIrrGnhd55CgPIoGAKY1NepfcmJLnBnPVeojtkblk4sENibhSWI/f7oM+7OpZcmu1rmfF4DqFgPgYIZiEZuH5SiwOJ9orIWce9w0mlwCOokTvkdqo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1687258737842121.586128453828; Tue, 20 Jun 2023 03:58:57 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qBZ3h-0007LV-ER; Tue, 20 Jun 2023 06:58:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qBZ3f-0007Jv-9d; Tue, 20 Jun 2023 06:57:59 -0400 Received: from mail-pf1-x432.google.com ([2607:f8b0:4864:20::432]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qBZ3d-0000j0-8f; Tue, 20 Jun 2023 06:57:59 -0400 Received: by mail-pf1-x432.google.com with SMTP id d2e1a72fcca58-668730696a4so1204192b3a.1; Tue, 20 Jun 2023 03:57:56 -0700 (PDT) Received: from wheely.local0.net ([124.170.190.103]) by smtp.gmail.com with ESMTPSA id n13-20020aa78a4d000000b0064fabbc047dsm1126412pfa.55.2023.06.20.03.57.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jun 2023 03:57:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1687258675; x=1689850675; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=SWZnKJXRiJBNnfnp5cfb9V+MeQ+/jjMQ9HeaYGeoqGY=; b=pNt8p5RIrAUXDITSwXx0QCLrBx1yQqE6QXNox+H1lZiOWatlIgNK9ClLK85wGGeh1b Wp0adU7+c9IvPzDproZ4RXq45mEYP/WoxRmv9CCZyaZ8ttEqwjcjfHrPvwPGMB6torG/ RLPh5y5dObo0j+5FfU+6pfuUiv0rB+3xY0RDZk+LEhAHB+uVH8+T7YoAD1cbUuTTzOYW 06Eq6uOfAKovAy7wlTln3pv/qkOWAHLphoFHXWh2oGlzdgJvkPu3rbHvqycWLUI3jPhu 1zVKRwPBU0VPqitBLVwNQiYHNGjEIYL9QMTj0HJg2VhIftL/e1xYSBLYYqrMPnWNG1wr 38Fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1687258675; x=1689850675; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=SWZnKJXRiJBNnfnp5cfb9V+MeQ+/jjMQ9HeaYGeoqGY=; b=JEiZ6luZwpJnnclLklVzyhhOTOos4Fy1+IUmabXuAFTz57DhKYHI/NBcgMI8B3shBH kL+QUf5zbUp9ohHdE3Tp+VptnoJ3Mz28kT3+VcFcyk5ijCx5f59UIsm/ECwtDkLGTY5o u4+smfpxr7W4mb1qV4P0fpDz+bPyYC50vKpdG0hDpEuLNu4XSOSeKVB9kqew7+sip3m+ fcKvusMjmSNJ4Fl1Ys/TOWZvfKtKAeBkUkk9CSjZ4ZQIHNMOmEniJjZdNEY/hQvzhMKz vP/uzzOX1YeYzL7CV2CDMyfFRNqJaT0TscPl8anMxKM2O3cbIPTdgk6bOi5UeRiW0s9i JWOg== X-Gm-Message-State: AC+VfDwdQYplKcIZoPivmkcXlQ6ynJCTFFMq6jAUbNJq9JzpXs5Di6J2 BCoSGNqwwlzVs1c1Wk1XL6HNIc9+Jnw= X-Google-Smtp-Source: ACHHUZ4uVuSNqCAsxnppzyrc81K+wNWQb4XqNKvfy0rZqdOE/tR1ur3qeMyBiKkmNgXCHyg3d5xspw== X-Received: by 2002:aa7:8882:0:b0:668:8c3c:3144 with SMTP id z2-20020aa78882000000b006688c3c3144mr3551234pfe.14.1687258675379; Tue, 20 Jun 2023 03:57:55 -0700 (PDT) From: Nicholas Piggin To: qemu-ppc@nongnu.org Cc: Nicholas Piggin , qemu-devel@nongnu.org, Harsh Prateek Bora , Daniel Henrique Barboza Subject: [PATCH v2 3/4] ppc/spapr: load and store l2 state with helper functions Date: Tue, 20 Jun 2023 20:57:36 +1000 Message-Id: <20230620105737.160451-4-npiggin@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230620105737.160451-1-npiggin@gmail.com> References: <20230620105737.160451-1-npiggin@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::432; envelope-from=npiggin@gmail.com; helo=mail-pf1-x432.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1687258739607100003 Content-Type: text/plain; charset="utf-8" Arguably this is just shuffling around register accesses, but one nice thing it does is allow the exit to save away the L2 state then switch the environment to the L1 before copying L2 data back to the L1, which logically flows more naturally and simplifies the error paths. Reviewed-by: Harsh Prateek Bora Signed-off-by: Nicholas Piggin --- hw/ppc/spapr_hcall.c | 164 ++++++++++++++++++++++--------------------- 1 file changed, 85 insertions(+), 79 deletions(-) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index d5b8d54692..54ad83a3e6 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1663,9 +1663,9 @@ static target_ulong h_enter_nested(PowerPCCPU *cpu, target_ulong *args) { PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); - CPUState *cs =3D CPU(cpu); CPUPPCState *env =3D &cpu->env; SpaprCpuState *spapr_cpu =3D spapr_cpu_state(cpu); + struct nested_ppc_state l2_state; target_ulong hv_ptr =3D args[0]; target_ulong regs_ptr =3D args[1]; target_ulong hdec, now =3D cpu_ppc_load_tbl(env); @@ -1699,6 +1699,10 @@ static target_ulong h_enter_nested(PowerPCCPU *cpu, return H_PARAMETER; } =20 + if (hv_state.lpid =3D=3D 0) { + return H_PARAMETER; + } + spapr_cpu->nested_host_state =3D g_try_new(struct nested_ppc_state, 1); if (!spapr_cpu->nested_host_state) { return H_NO_MEM; @@ -1717,46 +1721,49 @@ static target_ulong h_enter_nested(PowerPCCPU *cpu, return H_P2; } =20 - len =3D sizeof(env->gpr); + len =3D sizeof(l2_state.gpr); assert(len =3D=3D sizeof(regs->gpr)); - memcpy(env->gpr, regs->gpr, len); - - env->lr =3D regs->link; - env->ctr =3D regs->ctr; - cpu_write_xer(env, regs->xer); - ppc_set_cr(env, regs->ccr); + memcpy(l2_state.gpr, regs->gpr, len); =20 - env->msr =3D regs->msr; - env->nip =3D regs->nip; + l2_state.lr =3D regs->link; + l2_state.ctr =3D regs->ctr; + l2_state.xer =3D regs->xer; + l2_state.cr =3D regs->ccr; + l2_state.msr =3D regs->msr; + l2_state.nip =3D regs->nip; =20 address_space_unmap(CPU(cpu)->as, regs, len, len, false); =20 - env->cfar =3D hv_state.cfar; - - assert(env->spr[SPR_LPIDR] =3D=3D 0); - env->spr[SPR_LPIDR] =3D hv_state.lpid; + l2_state.cfar =3D hv_state.cfar; + l2_state.lpidr =3D hv_state.lpid; =20 lpcr_mask =3D LPCR_DPFD | LPCR_ILE | LPCR_AIL | LPCR_LD | LPCR_MER; lpcr =3D (env->spr[SPR_LPCR] & ~lpcr_mask) | (hv_state.lpcr & lpcr_mas= k); lpcr |=3D LPCR_HR | LPCR_UPRT | LPCR_GTSE | LPCR_HVICE | LPCR_HDICE; lpcr &=3D ~LPCR_LPES0; - env->spr[SPR_LPCR] =3D lpcr & pcc->lpcr_mask; + l2_state.lpcr =3D lpcr & pcc->lpcr_mask; =20 - env->spr[SPR_PCR] =3D hv_state.pcr; + l2_state.pcr =3D hv_state.pcr; /* hv_state.amor is not used */ - env->spr[SPR_DPDES] =3D hv_state.dpdes; - env->spr[SPR_HFSCR] =3D hv_state.hfscr; - hdec =3D hv_state.hdec_expiry - now; + l2_state.dpdes =3D hv_state.dpdes; + l2_state.hfscr =3D hv_state.hfscr; /* TCG does not implement DAWR*, CIABR, PURR, SPURR, IC, VTB, HEIR SPR= s*/ - env->spr[SPR_SRR0] =3D hv_state.srr0; - env->spr[SPR_SRR1] =3D hv_state.srr1; - env->spr[SPR_SPRG0] =3D hv_state.sprg[0]; - env->spr[SPR_SPRG1] =3D hv_state.sprg[1]; - env->spr[SPR_SPRG2] =3D hv_state.sprg[2]; - env->spr[SPR_SPRG3] =3D hv_state.sprg[3]; - env->spr[SPR_BOOKS_PID] =3D hv_state.pidr; - env->spr[SPR_PPR] =3D hv_state.ppr; + l2_state.srr0 =3D hv_state.srr0; + l2_state.srr1 =3D hv_state.srr1; + l2_state.sprg0 =3D hv_state.sprg[0]; + l2_state.sprg1 =3D hv_state.sprg[1]; + l2_state.sprg2 =3D hv_state.sprg[2]; + l2_state.sprg3 =3D hv_state.sprg[3]; + l2_state.pidr =3D hv_state.pidr; + l2_state.ppr =3D hv_state.ppr; + l2_state.tb_offset =3D env->tb_env->tb_offset + hv_state.tb_offset; =20 + /* + * Switch to the nested guest environment and start the "hdec" timer. + */ + nested_load_state(cpu, &l2_state); + + hdec =3D hv_state.hdec_expiry - now; cpu_ppc_hdecr_init(env); cpu_ppc_store_hdecr(env, hdec); =20 @@ -1772,14 +1779,8 @@ static target_ulong h_enter_nested(PowerPCCPU *cpu, * and it's not obviously worth a new data structure to do it. */ =20 - env->tb_env->tb_offset +=3D hv_state.tb_offset; spapr_cpu->in_nested =3D true; =20 - hreg_compute_hflags(env); - ppc_maybe_interrupt(env); - tlb_flush(cs); - env->reserve_addr =3D -1; /* Reset the reservation */ - /* * The spapr hcall helper sets env->gpr[3] to the return value, but at * this point the L1 is not returning from the hcall but rather we @@ -1793,49 +1794,69 @@ void spapr_exit_nested(PowerPCCPU *cpu, int excp) { CPUPPCState *env =3D &cpu->env; SpaprCpuState *spapr_cpu =3D spapr_cpu_state(cpu); - target_ulong r3_return =3D env->excp_vectors[excp]; /* hcall return va= lue */ + struct nested_ppc_state l2_state; target_ulong hv_ptr =3D spapr_cpu->nested_host_state->gpr[4]; target_ulong regs_ptr =3D spapr_cpu->nested_host_state->gpr[5]; + target_ulong hsrr0, hsrr1, hdar, asdr, hdsisr; struct kvmppc_hv_guest_state *hvstate; struct kvmppc_pt_regs *regs; hwaddr len; =20 assert(spapr_cpu->in_nested); =20 + nested_save_state(&l2_state, cpu); + hsrr0 =3D env->spr[SPR_HSRR0]; + hsrr1 =3D env->spr[SPR_HSRR1]; + hdar =3D env->spr[SPR_HDAR]; + hdsisr =3D env->spr[SPR_HDSISR]; + asdr =3D env->spr[SPR_ASDR]; + + /* + * Switch back to the host environment (including for any error). + */ + assert(env->spr[SPR_LPIDR] !=3D 0); + nested_load_state(cpu, spapr_cpu->nested_host_state); + env->gpr[3] =3D env->excp_vectors[excp]; /* hcall return value */ + cpu_ppc_hdecr_exit(env); =20 + spapr_cpu->in_nested =3D false; + + g_free(spapr_cpu->nested_host_state); + spapr_cpu->nested_host_state =3D NULL; + len =3D sizeof(*hvstate); hvstate =3D address_space_map(CPU(cpu)->as, hv_ptr, &len, true, MEMTXATTRS_UNSPECIFIED); if (len !=3D sizeof(*hvstate)) { address_space_unmap(CPU(cpu)->as, hvstate, len, 0, true); - r3_return =3D H_PARAMETER; - goto out_restore_l1; + env->gpr[3] =3D H_PARAMETER; + return; } =20 - hvstate->cfar =3D env->cfar; - hvstate->lpcr =3D env->spr[SPR_LPCR]; - hvstate->pcr =3D env->spr[SPR_PCR]; - hvstate->dpdes =3D env->spr[SPR_DPDES]; - hvstate->hfscr =3D env->spr[SPR_HFSCR]; + hvstate->cfar =3D l2_state.cfar; + hvstate->lpcr =3D l2_state.lpcr; + hvstate->pcr =3D l2_state.pcr; + hvstate->dpdes =3D l2_state.dpdes; + hvstate->hfscr =3D l2_state.hfscr; =20 if (excp =3D=3D POWERPC_EXCP_HDSI) { - hvstate->hdar =3D env->spr[SPR_HDAR]; - hvstate->hdsisr =3D env->spr[SPR_HDSISR]; - hvstate->asdr =3D env->spr[SPR_ASDR]; + hvstate->hdar =3D hdar; + hvstate->hdsisr =3D hdsisr; + hvstate->asdr =3D asdr; } else if (excp =3D=3D POWERPC_EXCP_HISI) { - hvstate->asdr =3D env->spr[SPR_ASDR]; + hvstate->asdr =3D asdr; } =20 /* HEIR should be implemented for HV mode and saved here. */ - hvstate->srr0 =3D env->spr[SPR_SRR0]; - hvstate->srr1 =3D env->spr[SPR_SRR1]; - hvstate->sprg[0] =3D env->spr[SPR_SPRG0]; - hvstate->sprg[1] =3D env->spr[SPR_SPRG1]; - hvstate->sprg[2] =3D env->spr[SPR_SPRG2]; - hvstate->sprg[3] =3D env->spr[SPR_SPRG3]; - hvstate->pidr =3D env->spr[SPR_BOOKS_PID]; - hvstate->ppr =3D env->spr[SPR_PPR]; + hvstate->srr0 =3D l2_state.srr0; + hvstate->srr1 =3D l2_state.srr1; + hvstate->sprg[0] =3D l2_state.sprg0; + hvstate->sprg[1] =3D l2_state.sprg1; + hvstate->sprg[2] =3D l2_state.sprg2; + hvstate->sprg[3] =3D l2_state.sprg3; + hvstate->pidr =3D l2_state.pidr; + hvstate->ppr =3D l2_state.ppr; =20 /* Is it okay to specify write length larger than actual data written?= */ address_space_unmap(CPU(cpu)->as, hvstate, len, len, true); @@ -1845,46 +1866,31 @@ void spapr_exit_nested(PowerPCCPU *cpu, int excp) MEMTXATTRS_UNSPECIFIED); if (!regs || len !=3D sizeof(*regs)) { address_space_unmap(CPU(cpu)->as, regs, len, 0, true); - r3_return =3D H_P2; - goto out_restore_l1; + env->gpr[3] =3D H_P2; + return; } =20 len =3D sizeof(env->gpr); assert(len =3D=3D sizeof(regs->gpr)); - memcpy(regs->gpr, env->gpr, len); + memcpy(regs->gpr, l2_state.gpr, len); =20 - regs->link =3D env->lr; - regs->ctr =3D env->ctr; - regs->xer =3D cpu_read_xer(env); - regs->ccr =3D ppc_get_cr(env); + regs->link =3D l2_state.lr; + regs->ctr =3D l2_state.ctr; + regs->xer =3D l2_state.xer; + regs->ccr =3D l2_state.cr; =20 if (excp =3D=3D POWERPC_EXCP_MCHECK || excp =3D=3D POWERPC_EXCP_RESET || excp =3D=3D POWERPC_EXCP_SYSCALL) { - regs->nip =3D env->spr[SPR_SRR0]; - regs->msr =3D env->spr[SPR_SRR1] & env->msr_mask; + regs->nip =3D l2_state.srr0; + regs->msr =3D l2_state.srr1 & env->msr_mask; } else { - regs->nip =3D env->spr[SPR_HSRR0]; - regs->msr =3D env->spr[SPR_HSRR1] & env->msr_mask; + regs->nip =3D hsrr0; + regs->msr =3D hsrr1 & env->msr_mask; } =20 /* Is it okay to specify write length larger than actual data written?= */ address_space_unmap(CPU(cpu)->as, regs, len, len, true); - -out_restore_l1: - assert(env->spr[SPR_LPIDR] !=3D 0); - nested_load_state(cpu, spapr_cpu->nested_host_state); - - /* - * Return the interrupt vector address from H_ENTER_NESTED to the L1 - * (or error code). - */ - env->gpr[3] =3D r3_return; - - spapr_cpu->in_nested =3D false; - - g_free(spapr_cpu->nested_host_state); - spapr_cpu->nested_host_state =3D NULL; } =20 static void hypercall_register_nested(void) --=20 2.40.1 From nobody Sat May 18 05:05:00 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1687258695; cv=none; d=zohomail.com; s=zohoarc; b=hL6Yl3v+uErqKvWfZ+hzRvB70qoAvoDTqxhFPHlCeUH3QSZuQRzcsbMHhJo3bQdCTJLAUmIVz0dPQNge31/OIE9+NIexqcFPGMlHkhX9/aSC7vOcks1t+YbMNBRsvOBiRvx9kE54CmtWQfnZIO04MkvzWu0OSwwQL+tu0wZ/OeU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1687258695; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=fBUPcgYF55gndpuRhYJezjb0GfPQRiw0a91yML9rvyM=; b=fsOl6l/ovU/aRbxuhjEifjUGevJdhd8m3HFKV55iLFbX9i0kUwQ1ptaNeaOj9bxKN1rxuq39YtFnrYjaNoQ5Eej/d9U6EwgCRM6L7pigYlz1WH6m4DR7rKb4Zv8YhfaiM8BBkO7t4VIRzzicOiVzY9ZRd5j34WbdNBBhS1Tz9LQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1687258695625755.2940218375976; Tue, 20 Jun 2023 03:58:15 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qBZ3l-0007Mm-Vh; Tue, 20 Jun 2023 06:58:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qBZ3k-0007MQ-Uy; Tue, 20 Jun 2023 06:58:04 -0400 Received: from mail-pf1-x434.google.com ([2607:f8b0:4864:20::434]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qBZ3h-0000jW-D3; Tue, 20 Jun 2023 06:58:04 -0400 Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-666ed230c81so3078995b3a.0; Tue, 20 Jun 2023 03:58:00 -0700 (PDT) Received: from wheely.local0.net ([124.170.190.103]) by smtp.gmail.com with ESMTPSA id n13-20020aa78a4d000000b0064fabbc047dsm1126412pfa.55.2023.06.20.03.57.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jun 2023 03:57:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1687258680; x=1689850680; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fBUPcgYF55gndpuRhYJezjb0GfPQRiw0a91yML9rvyM=; b=ljHWFhPM11g3DnpsuExpLw3taa6LkSGbRvO9Dhj8lZjXRTfO0w8zi6a5dqbvSAvcqZ vCys0/3cxfLG9TbtJIOOQASmjjsQM+gdFGjNSrv1WanVtjAkD84li5FUgT1lTXC1kdO1 onQD/R5QpgDjAhBX9+p9ZiM9/BOXzqC/cQsJPW+rCyEztY4kzejyaL2O2VhNI858mtKC dIYBBJh3k5+Mn7ILxxAmsjIvJevR+c5hl2nSD1Lz8ZF0qGyGb4dI/QHZTAf0K6HXhCdo TiAv04z9YGGJuOorPKgFUREnDVCNHI6ARasdMCotfeH7KGmEolFo352Qz87P98JvBn+O qWeg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1687258680; x=1689850680; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fBUPcgYF55gndpuRhYJezjb0GfPQRiw0a91yML9rvyM=; b=YOwaFXaQ6fQyru5ITiK6YBHBAK92X4YWB88bb7ICXbOXQn47byw7Le4rHK7CaGbJ9F BFlqpeRh/T0yf5FABjTMpNkUT9JKfo8+6FAfRW33s3s6xMfR8yl8/tLLP9qw5Nks1jaq XgsCl0ZuoEbEa4egfM2BDQeYfhI89A4IjBo+aey6XqNvru2zwj8FyRIYyRthni5kmIpi LNCj+nfjRv22GJtznkLXyVOBQwiboMtmaliUZBkfdkUBtQKRT7SYNl6mUsjeWsjFZGbJ CrWD4ER/nG1Y2HcwgNcEt/BxwZcQ6hrWDcX8mj5BlVn1t+wbJPC1DeK4tTDZ3gXon++G 51lA== X-Gm-Message-State: AC+VfDykUlU90hvmaGOgPtDHF4kw9vgRhCHYs3JyPhFusIzTDdZtGfZ4 OcUqMSUa0zqN5xhSl/4H1sDSPlKNQzM= X-Google-Smtp-Source: ACHHUZ5nrdED0woTENHnyJm8b7YFAV+xHSNv9h31qXBfqDs3bKHCU0UFVYdKkG4AbYl+QcWfa3Heeg== X-Received: by 2002:a05:6a00:1504:b0:668:7325:e184 with SMTP id q4-20020a056a00150400b006687325e184mr8288408pfu.16.1687258678988; Tue, 20 Jun 2023 03:57:58 -0700 (PDT) From: Nicholas Piggin To: qemu-ppc@nongnu.org Cc: Nicholas Piggin , qemu-devel@nongnu.org, Harsh Prateek Bora , Daniel Henrique Barboza Subject: [PATCH v2 4/4] ppc/spapr: Move spapr nested HV to a new file Date: Tue, 20 Jun 2023 20:57:37 +1000 Message-Id: <20230620105737.160451-5-npiggin@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230620105737.160451-1-npiggin@gmail.com> References: <20230620105737.160451-1-npiggin@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::434; envelope-from=npiggin@gmail.com; helo=mail-pf1-x434.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1687258697450100003 Content-Type: text/plain; charset="utf-8" Create spapr_nested.c for most of the nested HV implementation. Signed-off-by: Nicholas Piggin --- hw/ppc/meson.build | 1 + hw/ppc/spapr.c | 1 + hw/ppc/spapr_hcall.c | 416 +--------------------------------- hw/ppc/spapr_nested.c | 395 ++++++++++++++++++++++++++++++++ include/hw/ppc/spapr.h | 62 ----- include/hw/ppc/spapr_nested.h | 102 +++++++++ 6 files changed, 501 insertions(+), 476 deletions(-) create mode 100644 hw/ppc/spapr_nested.c create mode 100644 include/hw/ppc/spapr_nested.h diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build index c927337da0..a313d4b964 100644 --- a/hw/ppc/meson.build +++ b/hw/ppc/meson.build @@ -15,6 +15,7 @@ ppc_ss.add(when: 'CONFIG_PSERIES', if_true: files( 'spapr_vio.c', 'spapr_events.c', 'spapr_hcall.c', + 'spapr_nested.c', 'spapr_iommu.c', 'spapr_rtas.c', 'spapr_pci.c', diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index dcb7f1c70a..e55905a1f0 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -61,6 +61,7 @@ =20 #include "hw/ppc/fdt.h" #include "hw/ppc/spapr.h" +#include "hw/ppc/spapr_nested.h" #include "hw/ppc/spapr_vio.h" #include "hw/ppc/vof.h" #include "hw/qdev-properties.h" diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 54ad83a3e6..002ea0b7c1 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -13,6 +13,7 @@ #include "hw/ppc/ppc.h" #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_cpu_core.h" +#include "hw/ppc/spapr_nested.h" #include "mmu-hash64.h" #include "cpu-models.h" #include "trace.h" @@ -1498,430 +1499,17 @@ target_ulong spapr_hypercall(PowerPCCPU *cpu, targ= et_ulong opcode, } =20 #ifdef CONFIG_TCG -#define PRTS_MASK 0x1f - -static target_ulong h_set_ptbl(PowerPCCPU *cpu, - SpaprMachineState *spapr, - target_ulong opcode, - target_ulong *args) -{ - target_ulong ptcr =3D args[0]; - - if (!spapr_get_cap(spapr, SPAPR_CAP_NESTED_KVM_HV)) { - return H_FUNCTION; - } - - if ((ptcr & PRTS_MASK) + 12 - 4 > 12) { - return H_PARAMETER; - } - - spapr->nested_ptcr =3D ptcr; /* Save new partition table */ - - return H_SUCCESS; -} - -static target_ulong h_tlb_invalidate(PowerPCCPU *cpu, - SpaprMachineState *spapr, - target_ulong opcode, - target_ulong *args) -{ - /* - * The spapr virtual hypervisor nested HV implementation retains no L2 - * translation state except for TLB. And the TLB is always invalidated - * across L1<->L2 transitions, so nothing is required here. - */ - - return H_SUCCESS; -} - -static target_ulong h_copy_tofrom_guest(PowerPCCPU *cpu, - SpaprMachineState *spapr, - target_ulong opcode, - target_ulong *args) -{ - /* - * This HCALL is not required, L1 KVM will take a slow path and walk t= he - * page tables manually to do the data copy. - */ - return H_FUNCTION; -} - -struct nested_ppc_state { - uint64_t gpr[32]; - uint64_t lr; - uint64_t ctr; - uint64_t cfar; - uint64_t msr; - uint64_t nip; - uint32_t cr; - - uint64_t xer; - - uint64_t lpcr; - uint64_t lpidr; - uint64_t pidr; - uint64_t pcr; - uint64_t dpdes; - uint64_t hfscr; - uint64_t srr0; - uint64_t srr1; - uint64_t sprg0; - uint64_t sprg1; - uint64_t sprg2; - uint64_t sprg3; - uint64_t ppr; - - int64_t tb_offset; -}; - -static void nested_save_state(struct nested_ppc_state *save, PowerPCCPU *c= pu) -{ - CPUPPCState *env =3D &cpu->env; - - memcpy(save->gpr, env->gpr, sizeof(save->gpr)); - - save->lr =3D env->lr; - save->ctr =3D env->ctr; - save->cfar =3D env->cfar; - save->msr =3D env->msr; - save->nip =3D env->nip; - - save->cr =3D ppc_get_cr(env); - save->xer =3D cpu_read_xer(env); - - save->lpcr =3D env->spr[SPR_LPCR]; - save->lpidr =3D env->spr[SPR_LPIDR]; - save->pcr =3D env->spr[SPR_PCR]; - save->dpdes =3D env->spr[SPR_DPDES]; - save->hfscr =3D env->spr[SPR_HFSCR]; - save->srr0 =3D env->spr[SPR_SRR0]; - save->srr1 =3D env->spr[SPR_SRR1]; - save->sprg0 =3D env->spr[SPR_SPRG0]; - save->sprg1 =3D env->spr[SPR_SPRG1]; - save->sprg2 =3D env->spr[SPR_SPRG2]; - save->sprg3 =3D env->spr[SPR_SPRG3]; - save->pidr =3D env->spr[SPR_BOOKS_PID]; - save->ppr =3D env->spr[SPR_PPR]; - - save->tb_offset =3D env->tb_env->tb_offset; -} - -static void nested_load_state(PowerPCCPU *cpu, struct nested_ppc_state *lo= ad) -{ - CPUState *cs =3D CPU(cpu); - CPUPPCState *env =3D &cpu->env; - - memcpy(env->gpr, load->gpr, sizeof(env->gpr)); - - env->lr =3D load->lr; - env->ctr =3D load->ctr; - env->cfar =3D load->cfar; - env->msr =3D load->msr; - env->nip =3D load->nip; - - ppc_set_cr(env, load->cr); - cpu_write_xer(env, load->xer); - - env->spr[SPR_LPCR] =3D load->lpcr; - env->spr[SPR_LPIDR] =3D load->lpidr; - env->spr[SPR_PCR] =3D load->pcr; - env->spr[SPR_DPDES] =3D load->dpdes; - env->spr[SPR_HFSCR] =3D load->hfscr; - env->spr[SPR_SRR0] =3D load->srr0; - env->spr[SPR_SRR1] =3D load->srr1; - env->spr[SPR_SPRG0] =3D load->sprg0; - env->spr[SPR_SPRG1] =3D load->sprg1; - env->spr[SPR_SPRG2] =3D load->sprg2; - env->spr[SPR_SPRG3] =3D load->sprg3; - env->spr[SPR_BOOKS_PID] =3D load->pidr; - env->spr[SPR_PPR] =3D load->ppr; - - env->tb_env->tb_offset =3D load->tb_offset; - - /* - * MSR updated, compute hflags and possible interrupts. - */ - hreg_compute_hflags(env); - ppc_maybe_interrupt(env); - - /* - * Nested HV does not tag TLB entries between L1 and L2, so must - * flush on transition. - */ - tlb_flush(cs); - env->reserve_addr =3D -1; /* Reset the reservation */ -} - -/* - * When this handler returns, the environment is switched to the L2 guest - * and TCG begins running that. spapr_exit_nested() performs the switch fr= om - * L2 back to L1 and returns from the H_ENTER_NESTED hcall. - */ -static target_ulong h_enter_nested(PowerPCCPU *cpu, - SpaprMachineState *spapr, - target_ulong opcode, - target_ulong *args) -{ - PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); - CPUPPCState *env =3D &cpu->env; - SpaprCpuState *spapr_cpu =3D spapr_cpu_state(cpu); - struct nested_ppc_state l2_state; - target_ulong hv_ptr =3D args[0]; - target_ulong regs_ptr =3D args[1]; - target_ulong hdec, now =3D cpu_ppc_load_tbl(env); - target_ulong lpcr, lpcr_mask; - struct kvmppc_hv_guest_state *hvstate; - struct kvmppc_hv_guest_state hv_state; - struct kvmppc_pt_regs *regs; - hwaddr len; - - if (spapr->nested_ptcr =3D=3D 0) { - return H_NOT_AVAILABLE; - } - - len =3D sizeof(*hvstate); - hvstate =3D address_space_map(CPU(cpu)->as, hv_ptr, &len, false, - MEMTXATTRS_UNSPECIFIED); - if (len !=3D sizeof(*hvstate)) { - address_space_unmap(CPU(cpu)->as, hvstate, len, 0, false); - return H_PARAMETER; - } - - memcpy(&hv_state, hvstate, len); - - address_space_unmap(CPU(cpu)->as, hvstate, len, len, false); - - /* - * We accept versions 1 and 2. Version 2 fields are unused because TCG - * does not implement DAWR*. - */ - if (hv_state.version > HV_GUEST_STATE_VERSION) { - return H_PARAMETER; - } - - if (hv_state.lpid =3D=3D 0) { - return H_PARAMETER; - } - - spapr_cpu->nested_host_state =3D g_try_new(struct nested_ppc_state, 1); - if (!spapr_cpu->nested_host_state) { - return H_NO_MEM; - } - - assert(env->spr[SPR_LPIDR] =3D=3D 0); - assert(env->spr[SPR_DPDES] =3D=3D 0); - nested_save_state(spapr_cpu->nested_host_state, cpu); - - len =3D sizeof(*regs); - regs =3D address_space_map(CPU(cpu)->as, regs_ptr, &len, false, - MEMTXATTRS_UNSPECIFIED); - if (!regs || len !=3D sizeof(*regs)) { - address_space_unmap(CPU(cpu)->as, regs, len, 0, false); - g_free(spapr_cpu->nested_host_state); - return H_P2; - } - - len =3D sizeof(l2_state.gpr); - assert(len =3D=3D sizeof(regs->gpr)); - memcpy(l2_state.gpr, regs->gpr, len); - - l2_state.lr =3D regs->link; - l2_state.ctr =3D regs->ctr; - l2_state.xer =3D regs->xer; - l2_state.cr =3D regs->ccr; - l2_state.msr =3D regs->msr; - l2_state.nip =3D regs->nip; - - address_space_unmap(CPU(cpu)->as, regs, len, len, false); - - l2_state.cfar =3D hv_state.cfar; - l2_state.lpidr =3D hv_state.lpid; - - lpcr_mask =3D LPCR_DPFD | LPCR_ILE | LPCR_AIL | LPCR_LD | LPCR_MER; - lpcr =3D (env->spr[SPR_LPCR] & ~lpcr_mask) | (hv_state.lpcr & lpcr_mas= k); - lpcr |=3D LPCR_HR | LPCR_UPRT | LPCR_GTSE | LPCR_HVICE | LPCR_HDICE; - lpcr &=3D ~LPCR_LPES0; - l2_state.lpcr =3D lpcr & pcc->lpcr_mask; - - l2_state.pcr =3D hv_state.pcr; - /* hv_state.amor is not used */ - l2_state.dpdes =3D hv_state.dpdes; - l2_state.hfscr =3D hv_state.hfscr; - /* TCG does not implement DAWR*, CIABR, PURR, SPURR, IC, VTB, HEIR SPR= s*/ - l2_state.srr0 =3D hv_state.srr0; - l2_state.srr1 =3D hv_state.srr1; - l2_state.sprg0 =3D hv_state.sprg[0]; - l2_state.sprg1 =3D hv_state.sprg[1]; - l2_state.sprg2 =3D hv_state.sprg[2]; - l2_state.sprg3 =3D hv_state.sprg[3]; - l2_state.pidr =3D hv_state.pidr; - l2_state.ppr =3D hv_state.ppr; - l2_state.tb_offset =3D env->tb_env->tb_offset + hv_state.tb_offset; - - /* - * Switch to the nested guest environment and start the "hdec" timer. - */ - nested_load_state(cpu, &l2_state); - - hdec =3D hv_state.hdec_expiry - now; - cpu_ppc_hdecr_init(env); - cpu_ppc_store_hdecr(env, hdec); - - /* - * The hv_state.vcpu_token is not needed. It is used by the KVM - * implementation to remember which L2 vCPU last ran on which physical - * CPU so as to invalidate process scope translations if it is moved - * between physical CPUs. For now TLBs are always flushed on L1<->L2 - * transitions so this is not a problem. - * - * Could validate that the same vcpu_token does not attempt to run on - * different L1 vCPUs at the same time, but that would be a L1 KVM bug - * and it's not obviously worth a new data structure to do it. - */ - - spapr_cpu->in_nested =3D true; - - /* - * The spapr hcall helper sets env->gpr[3] to the return value, but at - * this point the L1 is not returning from the hcall but rather we - * start running the L2, so r3 must not be clobbered, so return env->g= pr[3] - * to leave it unchanged. - */ - return env->gpr[3]; -} - -void spapr_exit_nested(PowerPCCPU *cpu, int excp) -{ - CPUPPCState *env =3D &cpu->env; - SpaprCpuState *spapr_cpu =3D spapr_cpu_state(cpu); - struct nested_ppc_state l2_state; - target_ulong hv_ptr =3D spapr_cpu->nested_host_state->gpr[4]; - target_ulong regs_ptr =3D spapr_cpu->nested_host_state->gpr[5]; - target_ulong hsrr0, hsrr1, hdar, asdr, hdsisr; - struct kvmppc_hv_guest_state *hvstate; - struct kvmppc_pt_regs *regs; - hwaddr len; - - assert(spapr_cpu->in_nested); - - nested_save_state(&l2_state, cpu); - hsrr0 =3D env->spr[SPR_HSRR0]; - hsrr1 =3D env->spr[SPR_HSRR1]; - hdar =3D env->spr[SPR_HDAR]; - hdsisr =3D env->spr[SPR_HDSISR]; - asdr =3D env->spr[SPR_ASDR]; - - /* - * Switch back to the host environment (including for any error). - */ - assert(env->spr[SPR_LPIDR] !=3D 0); - nested_load_state(cpu, spapr_cpu->nested_host_state); - env->gpr[3] =3D env->excp_vectors[excp]; /* hcall return value */ - - cpu_ppc_hdecr_exit(env); - - spapr_cpu->in_nested =3D false; - - g_free(spapr_cpu->nested_host_state); - spapr_cpu->nested_host_state =3D NULL; - - len =3D sizeof(*hvstate); - hvstate =3D address_space_map(CPU(cpu)->as, hv_ptr, &len, true, - MEMTXATTRS_UNSPECIFIED); - if (len !=3D sizeof(*hvstate)) { - address_space_unmap(CPU(cpu)->as, hvstate, len, 0, true); - env->gpr[3] =3D H_PARAMETER; - return; - } - - hvstate->cfar =3D l2_state.cfar; - hvstate->lpcr =3D l2_state.lpcr; - hvstate->pcr =3D l2_state.pcr; - hvstate->dpdes =3D l2_state.dpdes; - hvstate->hfscr =3D l2_state.hfscr; - - if (excp =3D=3D POWERPC_EXCP_HDSI) { - hvstate->hdar =3D hdar; - hvstate->hdsisr =3D hdsisr; - hvstate->asdr =3D asdr; - } else if (excp =3D=3D POWERPC_EXCP_HISI) { - hvstate->asdr =3D asdr; - } - - /* HEIR should be implemented for HV mode and saved here. */ - hvstate->srr0 =3D l2_state.srr0; - hvstate->srr1 =3D l2_state.srr1; - hvstate->sprg[0] =3D l2_state.sprg0; - hvstate->sprg[1] =3D l2_state.sprg1; - hvstate->sprg[2] =3D l2_state.sprg2; - hvstate->sprg[3] =3D l2_state.sprg3; - hvstate->pidr =3D l2_state.pidr; - hvstate->ppr =3D l2_state.ppr; - - /* Is it okay to specify write length larger than actual data written?= */ - address_space_unmap(CPU(cpu)->as, hvstate, len, len, true); - - len =3D sizeof(*regs); - regs =3D address_space_map(CPU(cpu)->as, regs_ptr, &len, true, - MEMTXATTRS_UNSPECIFIED); - if (!regs || len !=3D sizeof(*regs)) { - address_space_unmap(CPU(cpu)->as, regs, len, 0, true); - env->gpr[3] =3D H_P2; - return; - } - - len =3D sizeof(env->gpr); - assert(len =3D=3D sizeof(regs->gpr)); - memcpy(regs->gpr, l2_state.gpr, len); - - regs->link =3D l2_state.lr; - regs->ctr =3D l2_state.ctr; - regs->xer =3D l2_state.xer; - regs->ccr =3D l2_state.cr; - - if (excp =3D=3D POWERPC_EXCP_MCHECK || - excp =3D=3D POWERPC_EXCP_RESET || - excp =3D=3D POWERPC_EXCP_SYSCALL) { - regs->nip =3D l2_state.srr0; - regs->msr =3D l2_state.srr1 & env->msr_mask; - } else { - regs->nip =3D hsrr0; - regs->msr =3D hsrr1 & env->msr_mask; - } - - /* Is it okay to specify write length larger than actual data written?= */ - address_space_unmap(CPU(cpu)->as, regs, len, len, true); -} - -static void hypercall_register_nested(void) -{ - spapr_register_hypercall(KVMPPC_H_SET_PARTITION_TABLE, h_set_ptbl); - spapr_register_hypercall(KVMPPC_H_ENTER_NESTED, h_enter_nested); - spapr_register_hypercall(KVMPPC_H_TLB_INVALIDATE, h_tlb_invalidate); - spapr_register_hypercall(KVMPPC_H_COPY_TOFROM_GUEST, h_copy_tofrom_gue= st); -} - static void hypercall_register_softmmu(void) { /* DO NOTHING */ } #else -void spapr_exit_nested(PowerPCCPU *cpu, int excp) -{ - g_assert_not_reached(); -} - static target_ulong h_softmmu(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong opcode, target_ulong *args) { g_assert_not_reached(); } =20 -static void hypercall_register_nested(void) -{ - /* DO NOTHING */ -} - static void hypercall_register_softmmu(void) { /* hcall-pft */ @@ -1991,7 +1579,7 @@ static void hypercall_register_types(void) =20 spapr_register_hypercall(KVMPPC_H_UPDATE_DT, h_update_dt); =20 - hypercall_register_nested(); + spapr_register_nested(); } =20 type_init(hypercall_register_types) diff --git a/hw/ppc/spapr_nested.c b/hw/ppc/spapr_nested.c new file mode 100644 index 0000000000..121aa96ddc --- /dev/null +++ b/hw/ppc/spapr_nested.c @@ -0,0 +1,395 @@ +#include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "exec/exec-all.h" +#include "helper_regs.h" +#include "hw/ppc/ppc.h" +#include "hw/ppc/spapr.h" +#include "hw/ppc/spapr_cpu_core.h" +#include "hw/ppc/spapr_nested.h" + +#ifdef CONFIG_TCG +#define PRTS_MASK 0x1f + +static target_ulong h_set_ptbl(PowerPCCPU *cpu, + SpaprMachineState *spapr, + target_ulong opcode, + target_ulong *args) +{ + target_ulong ptcr =3D args[0]; + + if (!spapr_get_cap(spapr, SPAPR_CAP_NESTED_KVM_HV)) { + return H_FUNCTION; + } + + if ((ptcr & PRTS_MASK) + 12 - 4 > 12) { + return H_PARAMETER; + } + + spapr->nested_ptcr =3D ptcr; /* Save new partition table */ + + return H_SUCCESS; +} + +static target_ulong h_tlb_invalidate(PowerPCCPU *cpu, + SpaprMachineState *spapr, + target_ulong opcode, + target_ulong *args) +{ + /* + * The spapr virtual hypervisor nested HV implementation retains no L2 + * translation state except for TLB. And the TLB is always invalidated + * across L1<->L2 transitions, so nothing is required here. + */ + + return H_SUCCESS; +} + +static target_ulong h_copy_tofrom_guest(PowerPCCPU *cpu, + SpaprMachineState *spapr, + target_ulong opcode, + target_ulong *args) +{ + /* + * This HCALL is not required, L1 KVM will take a slow path and walk t= he + * page tables manually to do the data copy. + */ + return H_FUNCTION; +} + +static void nested_save_state(struct nested_ppc_state *save, PowerPCCPU *c= pu) +{ + CPUPPCState *env =3D &cpu->env; + + memcpy(save->gpr, env->gpr, sizeof(save->gpr)); + + save->lr =3D env->lr; + save->ctr =3D env->ctr; + save->cfar =3D env->cfar; + save->msr =3D env->msr; + save->nip =3D env->nip; + + save->cr =3D ppc_get_cr(env); + save->xer =3D cpu_read_xer(env); + + save->lpcr =3D env->spr[SPR_LPCR]; + save->lpidr =3D env->spr[SPR_LPIDR]; + save->pcr =3D env->spr[SPR_PCR]; + save->dpdes =3D env->spr[SPR_DPDES]; + save->hfscr =3D env->spr[SPR_HFSCR]; + save->srr0 =3D env->spr[SPR_SRR0]; + save->srr1 =3D env->spr[SPR_SRR1]; + save->sprg0 =3D env->spr[SPR_SPRG0]; + save->sprg1 =3D env->spr[SPR_SPRG1]; + save->sprg2 =3D env->spr[SPR_SPRG2]; + save->sprg3 =3D env->spr[SPR_SPRG3]; + save->pidr =3D env->spr[SPR_BOOKS_PID]; + save->ppr =3D env->spr[SPR_PPR]; + + save->tb_offset =3D env->tb_env->tb_offset; +} + +static void nested_load_state(PowerPCCPU *cpu, struct nested_ppc_state *lo= ad) +{ + CPUState *cs =3D CPU(cpu); + CPUPPCState *env =3D &cpu->env; + + memcpy(env->gpr, load->gpr, sizeof(env->gpr)); + + env->lr =3D load->lr; + env->ctr =3D load->ctr; + env->cfar =3D load->cfar; + env->msr =3D load->msr; + env->nip =3D load->nip; + + ppc_set_cr(env, load->cr); + cpu_write_xer(env, load->xer); + + env->spr[SPR_LPCR] =3D load->lpcr; + env->spr[SPR_LPIDR] =3D load->lpidr; + env->spr[SPR_PCR] =3D load->pcr; + env->spr[SPR_DPDES] =3D load->dpdes; + env->spr[SPR_HFSCR] =3D load->hfscr; + env->spr[SPR_SRR0] =3D load->srr0; + env->spr[SPR_SRR1] =3D load->srr1; + env->spr[SPR_SPRG0] =3D load->sprg0; + env->spr[SPR_SPRG1] =3D load->sprg1; + env->spr[SPR_SPRG2] =3D load->sprg2; + env->spr[SPR_SPRG3] =3D load->sprg3; + env->spr[SPR_BOOKS_PID] =3D load->pidr; + env->spr[SPR_PPR] =3D load->ppr; + + env->tb_env->tb_offset =3D load->tb_offset; + + /* + * MSR updated, compute hflags and possible interrupts. + */ + hreg_compute_hflags(env); + ppc_maybe_interrupt(env); + + /* + * Nested HV does not tag TLB entries between L1 and L2, so must + * flush on transition. + */ + tlb_flush(cs); + env->reserve_addr =3D -1; /* Reset the reservation */ +} + +/* + * When this handler returns, the environment is switched to the L2 guest + * and TCG begins running that. spapr_exit_nested() performs the switch fr= om + * L2 back to L1 and returns from the H_ENTER_NESTED hcall. + */ +static target_ulong h_enter_nested(PowerPCCPU *cpu, + SpaprMachineState *spapr, + target_ulong opcode, + target_ulong *args) +{ + PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); + CPUPPCState *env =3D &cpu->env; + SpaprCpuState *spapr_cpu =3D spapr_cpu_state(cpu); + struct nested_ppc_state l2_state; + target_ulong hv_ptr =3D args[0]; + target_ulong regs_ptr =3D args[1]; + target_ulong hdec, now =3D cpu_ppc_load_tbl(env); + target_ulong lpcr, lpcr_mask; + struct kvmppc_hv_guest_state *hvstate; + struct kvmppc_hv_guest_state hv_state; + struct kvmppc_pt_regs *regs; + hwaddr len; + + if (spapr->nested_ptcr =3D=3D 0) { + return H_NOT_AVAILABLE; + } + + len =3D sizeof(*hvstate); + hvstate =3D address_space_map(CPU(cpu)->as, hv_ptr, &len, false, + MEMTXATTRS_UNSPECIFIED); + if (len !=3D sizeof(*hvstate)) { + address_space_unmap(CPU(cpu)->as, hvstate, len, 0, false); + return H_PARAMETER; + } + + memcpy(&hv_state, hvstate, len); + + address_space_unmap(CPU(cpu)->as, hvstate, len, len, false); + + /* + * We accept versions 1 and 2. Version 2 fields are unused because TCG + * does not implement DAWR*. + */ + if (hv_state.version > HV_GUEST_STATE_VERSION) { + return H_PARAMETER; + } + + if (hv_state.lpid =3D=3D 0) { + return H_PARAMETER; + } + + spapr_cpu->nested_host_state =3D g_try_new(struct nested_ppc_state, 1); + if (!spapr_cpu->nested_host_state) { + return H_NO_MEM; + } + + assert(env->spr[SPR_LPIDR] =3D=3D 0); + assert(env->spr[SPR_DPDES] =3D=3D 0); + nested_save_state(spapr_cpu->nested_host_state, cpu); + + len =3D sizeof(*regs); + regs =3D address_space_map(CPU(cpu)->as, regs_ptr, &len, false, + MEMTXATTRS_UNSPECIFIED); + if (!regs || len !=3D sizeof(*regs)) { + address_space_unmap(CPU(cpu)->as, regs, len, 0, false); + g_free(spapr_cpu->nested_host_state); + return H_P2; + } + + len =3D sizeof(l2_state.gpr); + assert(len =3D=3D sizeof(regs->gpr)); + memcpy(l2_state.gpr, regs->gpr, len); + + l2_state.lr =3D regs->link; + l2_state.ctr =3D regs->ctr; + l2_state.xer =3D regs->xer; + l2_state.cr =3D regs->ccr; + l2_state.msr =3D regs->msr; + l2_state.nip =3D regs->nip; + + address_space_unmap(CPU(cpu)->as, regs, len, len, false); + + l2_state.cfar =3D hv_state.cfar; + l2_state.lpidr =3D hv_state.lpid; + + lpcr_mask =3D LPCR_DPFD | LPCR_ILE | LPCR_AIL | LPCR_LD | LPCR_MER; + lpcr =3D (env->spr[SPR_LPCR] & ~lpcr_mask) | (hv_state.lpcr & lpcr_mas= k); + lpcr |=3D LPCR_HR | LPCR_UPRT | LPCR_GTSE | LPCR_HVICE | LPCR_HDICE; + lpcr &=3D ~LPCR_LPES0; + l2_state.lpcr =3D lpcr & pcc->lpcr_mask; + + l2_state.pcr =3D hv_state.pcr; + /* hv_state.amor is not used */ + l2_state.dpdes =3D hv_state.dpdes; + l2_state.hfscr =3D hv_state.hfscr; + /* TCG does not implement DAWR*, CIABR, PURR, SPURR, IC, VTB, HEIR SPR= s*/ + l2_state.srr0 =3D hv_state.srr0; + l2_state.srr1 =3D hv_state.srr1; + l2_state.sprg0 =3D hv_state.sprg[0]; + l2_state.sprg1 =3D hv_state.sprg[1]; + l2_state.sprg2 =3D hv_state.sprg[2]; + l2_state.sprg3 =3D hv_state.sprg[3]; + l2_state.pidr =3D hv_state.pidr; + l2_state.ppr =3D hv_state.ppr; + l2_state.tb_offset =3D env->tb_env->tb_offset + hv_state.tb_offset; + + /* + * Switch to the nested guest environment and start the "hdec" timer. + */ + nested_load_state(cpu, &l2_state); + + hdec =3D hv_state.hdec_expiry - now; + cpu_ppc_hdecr_init(env); + cpu_ppc_store_hdecr(env, hdec); + + /* + * The hv_state.vcpu_token is not needed. It is used by the KVM + * implementation to remember which L2 vCPU last ran on which physical + * CPU so as to invalidate process scope translations if it is moved + * between physical CPUs. For now TLBs are always flushed on L1<->L2 + * transitions so this is not a problem. + * + * Could validate that the same vcpu_token does not attempt to run on + * different L1 vCPUs at the same time, but that would be a L1 KVM bug + * and it's not obviously worth a new data structure to do it. + */ + + spapr_cpu->in_nested =3D true; + + /* + * The spapr hcall helper sets env->gpr[3] to the return value, but at + * this point the L1 is not returning from the hcall but rather we + * start running the L2, so r3 must not be clobbered, so return env->g= pr[3] + * to leave it unchanged. + */ + return env->gpr[3]; +} + +void spapr_exit_nested(PowerPCCPU *cpu, int excp) +{ + CPUPPCState *env =3D &cpu->env; + SpaprCpuState *spapr_cpu =3D spapr_cpu_state(cpu); + struct nested_ppc_state l2_state; + target_ulong hv_ptr =3D spapr_cpu->nested_host_state->gpr[4]; + target_ulong regs_ptr =3D spapr_cpu->nested_host_state->gpr[5]; + target_ulong hsrr0, hsrr1, hdar, asdr, hdsisr; + struct kvmppc_hv_guest_state *hvstate; + struct kvmppc_pt_regs *regs; + hwaddr len; + + assert(spapr_cpu->in_nested); + + nested_save_state(&l2_state, cpu); + hsrr0 =3D env->spr[SPR_HSRR0]; + hsrr1 =3D env->spr[SPR_HSRR1]; + hdar =3D env->spr[SPR_HDAR]; + hdsisr =3D env->spr[SPR_HDSISR]; + asdr =3D env->spr[SPR_ASDR]; + + /* + * Switch back to the host environment (including for any error). + */ + assert(env->spr[SPR_LPIDR] !=3D 0); + nested_load_state(cpu, spapr_cpu->nested_host_state); + env->gpr[3] =3D env->excp_vectors[excp]; /* hcall return value */ + + cpu_ppc_hdecr_exit(env); + + spapr_cpu->in_nested =3D false; + + g_free(spapr_cpu->nested_host_state); + spapr_cpu->nested_host_state =3D NULL; + + len =3D sizeof(*hvstate); + hvstate =3D address_space_map(CPU(cpu)->as, hv_ptr, &len, true, + MEMTXATTRS_UNSPECIFIED); + if (len !=3D sizeof(*hvstate)) { + address_space_unmap(CPU(cpu)->as, hvstate, len, 0, true); + env->gpr[3] =3D H_PARAMETER; + return; + } + + hvstate->cfar =3D l2_state.cfar; + hvstate->lpcr =3D l2_state.lpcr; + hvstate->pcr =3D l2_state.pcr; + hvstate->dpdes =3D l2_state.dpdes; + hvstate->hfscr =3D l2_state.hfscr; + + if (excp =3D=3D POWERPC_EXCP_HDSI) { + hvstate->hdar =3D hdar; + hvstate->hdsisr =3D hdsisr; + hvstate->asdr =3D asdr; + } else if (excp =3D=3D POWERPC_EXCP_HISI) { + hvstate->asdr =3D asdr; + } + + /* HEIR should be implemented for HV mode and saved here. */ + hvstate->srr0 =3D l2_state.srr0; + hvstate->srr1 =3D l2_state.srr1; + hvstate->sprg[0] =3D l2_state.sprg0; + hvstate->sprg[1] =3D l2_state.sprg1; + hvstate->sprg[2] =3D l2_state.sprg2; + hvstate->sprg[3] =3D l2_state.sprg3; + hvstate->pidr =3D l2_state.pidr; + hvstate->ppr =3D l2_state.ppr; + + /* Is it okay to specify write length larger than actual data written?= */ + address_space_unmap(CPU(cpu)->as, hvstate, len, len, true); + + len =3D sizeof(*regs); + regs =3D address_space_map(CPU(cpu)->as, regs_ptr, &len, true, + MEMTXATTRS_UNSPECIFIED); + if (!regs || len !=3D sizeof(*regs)) { + address_space_unmap(CPU(cpu)->as, regs, len, 0, true); + env->gpr[3] =3D H_P2; + return; + } + + len =3D sizeof(env->gpr); + assert(len =3D=3D sizeof(regs->gpr)); + memcpy(regs->gpr, l2_state.gpr, len); + + regs->link =3D l2_state.lr; + regs->ctr =3D l2_state.ctr; + regs->xer =3D l2_state.xer; + regs->ccr =3D l2_state.cr; + + if (excp =3D=3D POWERPC_EXCP_MCHECK || + excp =3D=3D POWERPC_EXCP_RESET || + excp =3D=3D POWERPC_EXCP_SYSCALL) { + regs->nip =3D l2_state.srr0; + regs->msr =3D l2_state.srr1 & env->msr_mask; + } else { + regs->nip =3D hsrr0; + regs->msr =3D hsrr1 & env->msr_mask; + } + + /* Is it okay to specify write length larger than actual data written?= */ + address_space_unmap(CPU(cpu)->as, regs, len, len, true); +} + +void spapr_register_nested(void) +{ + spapr_register_hypercall(KVMPPC_H_SET_PARTITION_TABLE, h_set_ptbl); + spapr_register_hypercall(KVMPPC_H_ENTER_NESTED, h_enter_nested); + spapr_register_hypercall(KVMPPC_H_TLB_INVALIDATE, h_tlb_invalidate); + spapr_register_hypercall(KVMPPC_H_COPY_TOFROM_GUEST, h_copy_tofrom_gue= st); +} +#else +void spapr_exit_nested(PowerPCCPU *cpu, int excp) +{ + g_assert_not_reached(); +} + +void spapr_register_nested(void) +{ + /* DO NOTHING */ +} +#endif diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index bd5a6c4780..538b2dfb89 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -621,66 +621,6 @@ struct SpaprMachineState { #define SVM_H_TPM_COMM 0xEF10 #define SVM_HCALL_MAX SVM_H_TPM_COMM =20 -/* - * Register state for entering a nested guest with H_ENTER_NESTED. - * New member must be added at the end. - */ -struct kvmppc_hv_guest_state { - uint64_t version; /* version of this structure layout, must be fi= rst */ - uint32_t lpid; - uint32_t vcpu_token; - /* These registers are hypervisor privileged (at least for writing) */ - uint64_t lpcr; - uint64_t pcr; - uint64_t amor; - uint64_t dpdes; - uint64_t hfscr; - int64_t tb_offset; - uint64_t dawr0; - uint64_t dawrx0; - uint64_t ciabr; - uint64_t hdec_expiry; - uint64_t purr; - uint64_t spurr; - uint64_t ic; - uint64_t vtb; - uint64_t hdar; - uint64_t hdsisr; - uint64_t heir; - uint64_t asdr; - /* These are OS privileged but need to be set late in guest entry */ - uint64_t srr0; - uint64_t srr1; - uint64_t sprg[4]; - uint64_t pidr; - uint64_t cfar; - uint64_t ppr; - /* Version 1 ends here */ - uint64_t dawr1; - uint64_t dawrx1; - /* Version 2 ends here */ -}; - -/* Latest version of hv_guest_state structure */ -#define HV_GUEST_STATE_VERSION 2 - -/* Linux 64-bit powerpc pt_regs struct, used by nested HV */ -struct kvmppc_pt_regs { - uint64_t gpr[32]; - uint64_t nip; - uint64_t msr; - uint64_t orig_gpr3; /* Used for restarting system calls */ - uint64_t ctr; - uint64_t link; - uint64_t xer; - uint64_t ccr; - uint64_t softe; /* Soft enabled/disabled */ - uint64_t trap; /* Reason for being here */ - uint64_t dar; /* Fault registers */ - uint64_t dsisr; /* on 4xx/Book-E used for ESR */ - uint64_t result; /* Result of a system call */ -}; - typedef struct SpaprDeviceTreeUpdateHeader { uint32_t version_id; } SpaprDeviceTreeUpdateHeader; @@ -698,8 +638,6 @@ void spapr_register_hypercall(target_ulong opcode, spap= r_hcall_fn fn); target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode, target_ulong *args); =20 -void spapr_exit_nested(PowerPCCPU *cpu, int excp); - target_ulong softmmu_resize_hpt_prepare(PowerPCCPU *cpu, SpaprMachineState= *spapr, target_ulong shift); target_ulong softmmu_resize_hpt_commit(PowerPCCPU *cpu, SpaprMachineState = *spapr, diff --git a/include/hw/ppc/spapr_nested.h b/include/hw/ppc/spapr_nested.h new file mode 100644 index 0000000000..d383486476 --- /dev/null +++ b/include/hw/ppc/spapr_nested.h @@ -0,0 +1,102 @@ +#ifndef HW_SPAPR_NESTED_H +#define HW_SPAPR_NESTED_H + +#include "qemu/osdep.h" +#include "target/ppc/cpu.h" + +/* + * Register state for entering a nested guest with H_ENTER_NESTED. + * New member must be added at the end. + */ +struct kvmppc_hv_guest_state { + uint64_t version; /* version of this structure layout, must be fi= rst */ + uint32_t lpid; + uint32_t vcpu_token; + /* These registers are hypervisor privileged (at least for writing) */ + uint64_t lpcr; + uint64_t pcr; + uint64_t amor; + uint64_t dpdes; + uint64_t hfscr; + int64_t tb_offset; + uint64_t dawr0; + uint64_t dawrx0; + uint64_t ciabr; + uint64_t hdec_expiry; + uint64_t purr; + uint64_t spurr; + uint64_t ic; + uint64_t vtb; + uint64_t hdar; + uint64_t hdsisr; + uint64_t heir; + uint64_t asdr; + /* These are OS privileged but need to be set late in guest entry */ + uint64_t srr0; + uint64_t srr1; + uint64_t sprg[4]; + uint64_t pidr; + uint64_t cfar; + uint64_t ppr; + /* Version 1 ends here */ + uint64_t dawr1; + uint64_t dawrx1; + /* Version 2 ends here */ +}; + +/* Latest version of hv_guest_state structure */ +#define HV_GUEST_STATE_VERSION 2 + +/* Linux 64-bit powerpc pt_regs struct, used by nested HV */ +struct kvmppc_pt_regs { + uint64_t gpr[32]; + uint64_t nip; + uint64_t msr; + uint64_t orig_gpr3; /* Used for restarting system calls */ + uint64_t ctr; + uint64_t link; + uint64_t xer; + uint64_t ccr; + uint64_t softe; /* Soft enabled/disabled */ + uint64_t trap; /* Reason for being here */ + uint64_t dar; /* Fault registers */ + uint64_t dsisr; /* on 4xx/Book-E used for ESR */ + uint64_t result; /* Result of a system call */ +}; + +/* + * nested_ppc_state is used to save the host CPU state before switching it= to + * the guest CPU state, to be restored on H_ENTER_NESTED exit. + */ +struct nested_ppc_state { + uint64_t gpr[32]; + uint64_t lr; + uint64_t ctr; + uint64_t cfar; + uint64_t msr; + uint64_t nip; + uint32_t cr; + + uint64_t xer; + + uint64_t lpcr; + uint64_t lpidr; + uint64_t pidr; + uint64_t pcr; + uint64_t dpdes; + uint64_t hfscr; + uint64_t srr0; + uint64_t srr1; + uint64_t sprg0; + uint64_t sprg1; + uint64_t sprg2; + uint64_t sprg3; + uint64_t ppr; + + int64_t tb_offset; +}; + +void spapr_register_nested(void); +void spapr_exit_nested(PowerPCCPU *cpu, int excp); + +#endif /* HW_SPAPR_NESTED_H */ --=20 2.40.1