Path: blob/master/arch/powerpc/kvm/book3s_hv_nestedv2.c
26439 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* Copyright 2023 Jordan Niethe, IBM Corp. <[email protected]>3*4* Authors:5* Jordan Niethe <[email protected]>6*7* Description: KVM functions specific to running on Book 3S8* processors as a NESTEDv2 guest.9*10*/1112#include "linux/blk-mq.h"13#include "linux/console.h"14#include "linux/gfp_types.h"15#include "linux/signal.h"16#include <linux/kernel.h>17#include <linux/kvm_host.h>18#include <linux/pgtable.h>1920#include <asm/kvm_ppc.h>21#include <asm/kvm_book3s.h>22#include <asm/hvcall.h>23#include <asm/pgalloc.h>24#include <asm/reg.h>25#include <asm/plpar_wrappers.h>26#include <asm/guest-state-buffer.h>27#include "trace_hv.h"2829struct static_key_false __kvmhv_is_nestedv2 __read_mostly;30EXPORT_SYMBOL_GPL(__kvmhv_is_nestedv2);313233static size_t34gs_msg_ops_kvmhv_nestedv2_config_get_size(struct kvmppc_gs_msg *gsm)35{36u16 ids[] = {37KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE,38KVMPPC_GSID_RUN_INPUT,39KVMPPC_GSID_RUN_OUTPUT,4041};42size_t size = 0;4344for (int i = 0; i < ARRAY_SIZE(ids); i++)45size += kvmppc_gse_total_size(kvmppc_gsid_size(ids[i]));46return size;47}4849static int50gs_msg_ops_kvmhv_nestedv2_config_fill_info(struct kvmppc_gs_buff *gsb,51struct kvmppc_gs_msg *gsm)52{53struct kvmhv_nestedv2_config *cfg;54int rc;5556cfg = gsm->data;5758if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE)) {59rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE,60cfg->vcpu_run_output_size);61if (rc < 0)62return rc;63}6465if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_INPUT)) {66rc = kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_INPUT,67cfg->vcpu_run_input_cfg);68if (rc < 0)69return rc;70}7172if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_OUTPUT)) {73rc = kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_OUTPUT,74cfg->vcpu_run_output_cfg);75if (rc < 0)76return rc;77}7879return 0;80}8182static int83gs_msg_ops_kvmhv_nestedv2_config_refresh_info(struct kvmppc_gs_msg *gsm,84struct kvmppc_gs_buff *gsb)85{86struct kvmhv_nestedv2_config *cfg;87struct kvmppc_gs_parser gsp = { 0 };88struct kvmppc_gs_elem *gse;89int rc;9091cfg = gsm->data;9293rc = kvmppc_gse_parse(&gsp, gsb);94if (rc < 0)95return rc;9697gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE);98if (gse)99cfg->vcpu_run_output_size = kvmppc_gse_get_u64(gse);100return 0;101}102103static struct kvmppc_gs_msg_ops config_msg_ops = {104.get_size = gs_msg_ops_kvmhv_nestedv2_config_get_size,105.fill_info = gs_msg_ops_kvmhv_nestedv2_config_fill_info,106.refresh_info = gs_msg_ops_kvmhv_nestedv2_config_refresh_info,107};108109static size_t gs_msg_ops_vcpu_get_size(struct kvmppc_gs_msg *gsm)110{111struct kvmppc_gs_bitmap gsbm = { 0 };112size_t size = 0;113u16 iden;114115kvmppc_gsbm_fill(&gsbm);116kvmppc_gsbm_for_each(&gsbm, iden)117{118switch (iden) {119case KVMPPC_GSID_HOST_STATE_SIZE:120case KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE:121case KVMPPC_GSID_PARTITION_TABLE:122case KVMPPC_GSID_PROCESS_TABLE:123case KVMPPC_GSID_RUN_INPUT:124case KVMPPC_GSID_RUN_OUTPUT:125/* Host wide counters */126case KVMPPC_GSID_L0_GUEST_HEAP:127case KVMPPC_GSID_L0_GUEST_HEAP_MAX:128case KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE:129case KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE_MAX:130case KVMPPC_GSID_L0_GUEST_PGTABLE_RECLAIM:131break;132default:133size += kvmppc_gse_total_size(kvmppc_gsid_size(iden));134}135}136return size;137}138139static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb,140struct kvmppc_gs_msg *gsm)141{142struct kvm_vcpu *vcpu;143vector128 v;144int rc, i;145u16 iden;146u32 arch_compat = 0;147148vcpu = gsm->data;149150kvmppc_gsm_for_each(gsm, iden)151{152rc = 0;153154if ((gsm->flags & KVMPPC_GS_FLAGS_WIDE) !=155(kvmppc_gsid_flags(iden) & KVMPPC_GS_FLAGS_WIDE))156continue;157158switch (iden) {159case KVMPPC_GSID_DSCR:160rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dscr);161break;162case KVMPPC_GSID_MMCRA:163rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.mmcra);164break;165case KVMPPC_GSID_HFSCR:166rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.hfscr);167break;168case KVMPPC_GSID_PURR:169rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.purr);170break;171case KVMPPC_GSID_SPURR:172rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.spurr);173break;174case KVMPPC_GSID_AMR:175rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.amr);176break;177case KVMPPC_GSID_UAMOR:178rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.uamor);179break;180case KVMPPC_GSID_SIAR:181rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.siar);182break;183case KVMPPC_GSID_SDAR:184rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.sdar);185break;186case KVMPPC_GSID_IAMR:187rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.iamr);188break;189case KVMPPC_GSID_DAWR0:190rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dawr0);191break;192case KVMPPC_GSID_DAWR1:193rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dawr1);194break;195case KVMPPC_GSID_DAWRX0:196rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.dawrx0);197break;198case KVMPPC_GSID_DAWRX1:199rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.dawrx1);200break;201case KVMPPC_GSID_DEXCR:202rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dexcr);203break;204case KVMPPC_GSID_HASHKEYR:205rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.hashkeyr);206break;207case KVMPPC_GSID_HASHPKEYR:208rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.hashpkeyr);209break;210case KVMPPC_GSID_CIABR:211rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ciabr);212break;213case KVMPPC_GSID_WORT:214rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.wort);215break;216case KVMPPC_GSID_PPR:217rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ppr);218break;219case KVMPPC_GSID_PSPB:220rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.pspb);221break;222case KVMPPC_GSID_TAR:223rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.tar);224break;225case KVMPPC_GSID_FSCR:226rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.fscr);227break;228case KVMPPC_GSID_EBBHR:229rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ebbhr);230break;231case KVMPPC_GSID_EBBRR:232rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ebbrr);233break;234case KVMPPC_GSID_BESCR:235rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.bescr);236break;237case KVMPPC_GSID_IC:238rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ic);239break;240case KVMPPC_GSID_CTRL:241rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ctrl);242break;243case KVMPPC_GSID_PIDR:244rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.pid);245break;246case KVMPPC_GSID_AMOR: {247u64 amor = ~0;248249rc = kvmppc_gse_put_u64(gsb, iden, amor);250break;251}252case KVMPPC_GSID_VRSAVE:253rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.vrsave);254break;255case KVMPPC_GSID_MMCR(0)... KVMPPC_GSID_MMCR(3):256i = iden - KVMPPC_GSID_MMCR(0);257rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.mmcr[i]);258break;259case KVMPPC_GSID_SIER(0)... KVMPPC_GSID_SIER(2):260i = iden - KVMPPC_GSID_SIER(0);261rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.sier[i]);262break;263case KVMPPC_GSID_PMC(0)... KVMPPC_GSID_PMC(5):264i = iden - KVMPPC_GSID_PMC(0);265rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.pmc[i]);266break;267case KVMPPC_GSID_GPR(0)... KVMPPC_GSID_GPR(31):268i = iden - KVMPPC_GSID_GPR(0);269rc = kvmppc_gse_put_u64(gsb, iden,270vcpu->arch.regs.gpr[i]);271break;272case KVMPPC_GSID_CR:273rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.regs.ccr);274break;275case KVMPPC_GSID_XER:276rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.regs.xer);277break;278case KVMPPC_GSID_CTR:279rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.regs.ctr);280break;281case KVMPPC_GSID_LR:282rc = kvmppc_gse_put_u64(gsb, iden,283vcpu->arch.regs.link);284break;285case KVMPPC_GSID_NIA:286rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.regs.nip);287break;288case KVMPPC_GSID_SRR0:289rc = kvmppc_gse_put_u64(gsb, iden,290vcpu->arch.shregs.srr0);291break;292case KVMPPC_GSID_SRR1:293rc = kvmppc_gse_put_u64(gsb, iden,294vcpu->arch.shregs.srr1);295break;296case KVMPPC_GSID_SPRG0:297rc = kvmppc_gse_put_u64(gsb, iden,298vcpu->arch.shregs.sprg0);299break;300case KVMPPC_GSID_SPRG1:301rc = kvmppc_gse_put_u64(gsb, iden,302vcpu->arch.shregs.sprg1);303break;304case KVMPPC_GSID_SPRG2:305rc = kvmppc_gse_put_u64(gsb, iden,306vcpu->arch.shregs.sprg2);307break;308case KVMPPC_GSID_SPRG3:309rc = kvmppc_gse_put_u64(gsb, iden,310vcpu->arch.shregs.sprg3);311break;312case KVMPPC_GSID_DAR:313rc = kvmppc_gse_put_u64(gsb, iden,314vcpu->arch.shregs.dar);315break;316case KVMPPC_GSID_DSISR:317rc = kvmppc_gse_put_u32(gsb, iden,318vcpu->arch.shregs.dsisr);319break;320case KVMPPC_GSID_MSR:321rc = kvmppc_gse_put_u64(gsb, iden,322vcpu->arch.shregs.msr);323break;324case KVMPPC_GSID_VTB:325rc = kvmppc_gse_put_u64(gsb, iden,326vcpu->arch.vcore->vtb);327break;328case KVMPPC_GSID_DPDES:329rc = kvmppc_gse_put_u64(gsb, iden,330vcpu->arch.vcore->dpdes);331break;332case KVMPPC_GSID_LPCR:333rc = kvmppc_gse_put_u64(gsb, iden,334vcpu->arch.vcore->lpcr);335break;336case KVMPPC_GSID_TB_OFFSET:337rc = kvmppc_gse_put_u64(gsb, iden,338vcpu->arch.vcore->tb_offset);339break;340case KVMPPC_GSID_FPSCR:341rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.fp.fpscr);342break;343case KVMPPC_GSID_VSRS(0)... KVMPPC_GSID_VSRS(31):344i = iden - KVMPPC_GSID_VSRS(0);345memcpy(&v, &vcpu->arch.fp.fpr[i],346sizeof(vcpu->arch.fp.fpr[i]));347rc = kvmppc_gse_put_vector128(gsb, iden, &v);348break;349#ifdef CONFIG_VSX350case KVMPPC_GSID_VSCR:351rc = kvmppc_gse_put_u32(gsb, iden,352vcpu->arch.vr.vscr.u[3]);353break;354case KVMPPC_GSID_VSRS(32)... KVMPPC_GSID_VSRS(63):355i = iden - KVMPPC_GSID_VSRS(32);356rc = kvmppc_gse_put_vector128(gsb, iden,357&vcpu->arch.vr.vr[i]);358break;359#endif360case KVMPPC_GSID_DEC_EXPIRY_TB: {361u64 dw;362363dw = vcpu->arch.dec_expires -364vcpu->arch.vcore->tb_offset;365rc = kvmppc_gse_put_u64(gsb, iden, dw);366break;367}368case KVMPPC_GSID_LOGICAL_PVR:369/*370* Though 'arch_compat == 0' would mean the default371* compatibility, arch_compat, being a Guest Wide372* Element, cannot be filled with a value of 0 in GSB373* as this would result into a kernel trap.374* Hence, when `arch_compat == 0`, arch_compat should375* default to L1's PVR.376*/377if (!vcpu->arch.vcore->arch_compat) {378if (cpu_has_feature(CPU_FTR_P11_PVR))379arch_compat = PVR_ARCH_31_P11;380else if (cpu_has_feature(CPU_FTR_ARCH_31))381arch_compat = PVR_ARCH_31;382else if (cpu_has_feature(CPU_FTR_ARCH_300))383arch_compat = PVR_ARCH_300;384} else {385arch_compat = vcpu->arch.vcore->arch_compat;386}387rc = kvmppc_gse_put_u32(gsb, iden, arch_compat);388break;389}390391if (rc < 0)392return rc;393}394395return 0;396}397398static int gs_msg_ops_vcpu_refresh_info(struct kvmppc_gs_msg *gsm,399struct kvmppc_gs_buff *gsb)400{401struct kvmppc_gs_parser gsp = { 0 };402struct kvmhv_nestedv2_io *io;403struct kvmppc_gs_bitmap *valids;404struct kvm_vcpu *vcpu;405struct kvmppc_gs_elem *gse;406vector128 v;407int rc, i;408u16 iden;409410vcpu = gsm->data;411412rc = kvmppc_gse_parse(&gsp, gsb);413if (rc < 0)414return rc;415416io = &vcpu->arch.nestedv2_io;417valids = &io->valids;418419kvmppc_gsp_for_each(&gsp, iden, gse)420{421switch (iden) {422case KVMPPC_GSID_DSCR:423vcpu->arch.dscr = kvmppc_gse_get_u64(gse);424break;425case KVMPPC_GSID_MMCRA:426vcpu->arch.mmcra = kvmppc_gse_get_u64(gse);427break;428case KVMPPC_GSID_HFSCR:429vcpu->arch.hfscr = kvmppc_gse_get_u64(gse);430break;431case KVMPPC_GSID_PURR:432vcpu->arch.purr = kvmppc_gse_get_u64(gse);433break;434case KVMPPC_GSID_SPURR:435vcpu->arch.spurr = kvmppc_gse_get_u64(gse);436break;437case KVMPPC_GSID_AMR:438vcpu->arch.amr = kvmppc_gse_get_u64(gse);439break;440case KVMPPC_GSID_UAMOR:441vcpu->arch.uamor = kvmppc_gse_get_u64(gse);442break;443case KVMPPC_GSID_SIAR:444vcpu->arch.siar = kvmppc_gse_get_u64(gse);445break;446case KVMPPC_GSID_SDAR:447vcpu->arch.sdar = kvmppc_gse_get_u64(gse);448break;449case KVMPPC_GSID_IAMR:450vcpu->arch.iamr = kvmppc_gse_get_u64(gse);451break;452case KVMPPC_GSID_DAWR0:453vcpu->arch.dawr0 = kvmppc_gse_get_u64(gse);454break;455case KVMPPC_GSID_DAWR1:456vcpu->arch.dawr1 = kvmppc_gse_get_u64(gse);457break;458case KVMPPC_GSID_DAWRX0:459vcpu->arch.dawrx0 = kvmppc_gse_get_u32(gse);460break;461case KVMPPC_GSID_DAWRX1:462vcpu->arch.dawrx1 = kvmppc_gse_get_u32(gse);463break;464case KVMPPC_GSID_DEXCR:465vcpu->arch.dexcr = kvmppc_gse_get_u64(gse);466break;467case KVMPPC_GSID_HASHKEYR:468vcpu->arch.hashkeyr = kvmppc_gse_get_u64(gse);469break;470case KVMPPC_GSID_HASHPKEYR:471vcpu->arch.hashpkeyr = kvmppc_gse_get_u64(gse);472break;473case KVMPPC_GSID_CIABR:474vcpu->arch.ciabr = kvmppc_gse_get_u64(gse);475break;476case KVMPPC_GSID_WORT:477vcpu->arch.wort = kvmppc_gse_get_u32(gse);478break;479case KVMPPC_GSID_PPR:480vcpu->arch.ppr = kvmppc_gse_get_u64(gse);481break;482case KVMPPC_GSID_PSPB:483vcpu->arch.pspb = kvmppc_gse_get_u32(gse);484break;485case KVMPPC_GSID_TAR:486vcpu->arch.tar = kvmppc_gse_get_u64(gse);487break;488case KVMPPC_GSID_FSCR:489vcpu->arch.fscr = kvmppc_gse_get_u64(gse);490break;491case KVMPPC_GSID_EBBHR:492vcpu->arch.ebbhr = kvmppc_gse_get_u64(gse);493break;494case KVMPPC_GSID_EBBRR:495vcpu->arch.ebbrr = kvmppc_gse_get_u64(gse);496break;497case KVMPPC_GSID_BESCR:498vcpu->arch.bescr = kvmppc_gse_get_u64(gse);499break;500case KVMPPC_GSID_IC:501vcpu->arch.ic = kvmppc_gse_get_u64(gse);502break;503case KVMPPC_GSID_CTRL:504vcpu->arch.ctrl = kvmppc_gse_get_u64(gse);505break;506case KVMPPC_GSID_PIDR:507vcpu->arch.pid = kvmppc_gse_get_u32(gse);508break;509case KVMPPC_GSID_AMOR:510break;511case KVMPPC_GSID_VRSAVE:512vcpu->arch.vrsave = kvmppc_gse_get_u32(gse);513break;514case KVMPPC_GSID_MMCR(0)... KVMPPC_GSID_MMCR(3):515i = iden - KVMPPC_GSID_MMCR(0);516vcpu->arch.mmcr[i] = kvmppc_gse_get_u64(gse);517break;518case KVMPPC_GSID_SIER(0)... KVMPPC_GSID_SIER(2):519i = iden - KVMPPC_GSID_SIER(0);520vcpu->arch.sier[i] = kvmppc_gse_get_u64(gse);521break;522case KVMPPC_GSID_PMC(0)... KVMPPC_GSID_PMC(5):523i = iden - KVMPPC_GSID_PMC(0);524vcpu->arch.pmc[i] = kvmppc_gse_get_u32(gse);525break;526case KVMPPC_GSID_GPR(0)... KVMPPC_GSID_GPR(31):527i = iden - KVMPPC_GSID_GPR(0);528vcpu->arch.regs.gpr[i] = kvmppc_gse_get_u64(gse);529break;530case KVMPPC_GSID_CR:531vcpu->arch.regs.ccr = kvmppc_gse_get_u32(gse);532break;533case KVMPPC_GSID_XER:534vcpu->arch.regs.xer = kvmppc_gse_get_u64(gse);535break;536case KVMPPC_GSID_CTR:537vcpu->arch.regs.ctr = kvmppc_gse_get_u64(gse);538break;539case KVMPPC_GSID_LR:540vcpu->arch.regs.link = kvmppc_gse_get_u64(gse);541break;542case KVMPPC_GSID_NIA:543vcpu->arch.regs.nip = kvmppc_gse_get_u64(gse);544break;545case KVMPPC_GSID_SRR0:546vcpu->arch.shregs.srr0 = kvmppc_gse_get_u64(gse);547break;548case KVMPPC_GSID_SRR1:549vcpu->arch.shregs.srr1 = kvmppc_gse_get_u64(gse);550break;551case KVMPPC_GSID_SPRG0:552vcpu->arch.shregs.sprg0 = kvmppc_gse_get_u64(gse);553break;554case KVMPPC_GSID_SPRG1:555vcpu->arch.shregs.sprg1 = kvmppc_gse_get_u64(gse);556break;557case KVMPPC_GSID_SPRG2:558vcpu->arch.shregs.sprg2 = kvmppc_gse_get_u64(gse);559break;560case KVMPPC_GSID_SPRG3:561vcpu->arch.shregs.sprg3 = kvmppc_gse_get_u64(gse);562break;563case KVMPPC_GSID_DAR:564vcpu->arch.shregs.dar = kvmppc_gse_get_u64(gse);565break;566case KVMPPC_GSID_DSISR:567vcpu->arch.shregs.dsisr = kvmppc_gse_get_u32(gse);568break;569case KVMPPC_GSID_MSR:570vcpu->arch.shregs.msr = kvmppc_gse_get_u64(gse);571break;572case KVMPPC_GSID_VTB:573vcpu->arch.vcore->vtb = kvmppc_gse_get_u64(gse);574break;575case KVMPPC_GSID_DPDES:576vcpu->arch.vcore->dpdes = kvmppc_gse_get_u64(gse);577break;578case KVMPPC_GSID_LPCR:579vcpu->arch.vcore->lpcr = kvmppc_gse_get_u64(gse);580break;581case KVMPPC_GSID_TB_OFFSET:582vcpu->arch.vcore->tb_offset = kvmppc_gse_get_u64(gse);583break;584case KVMPPC_GSID_FPSCR:585vcpu->arch.fp.fpscr = kvmppc_gse_get_u64(gse);586break;587case KVMPPC_GSID_VSRS(0)... KVMPPC_GSID_VSRS(31):588kvmppc_gse_get_vector128(gse, &v);589i = iden - KVMPPC_GSID_VSRS(0);590memcpy(&vcpu->arch.fp.fpr[i], &v,591sizeof(vcpu->arch.fp.fpr[i]));592break;593#ifdef CONFIG_VSX594case KVMPPC_GSID_VSCR:595vcpu->arch.vr.vscr.u[3] = kvmppc_gse_get_u32(gse);596break;597case KVMPPC_GSID_VSRS(32)... KVMPPC_GSID_VSRS(63):598i = iden - KVMPPC_GSID_VSRS(32);599kvmppc_gse_get_vector128(gse, &vcpu->arch.vr.vr[i]);600break;601#endif602case KVMPPC_GSID_HDAR:603vcpu->arch.fault_dar = kvmppc_gse_get_u64(gse);604break;605case KVMPPC_GSID_HDSISR:606vcpu->arch.fault_dsisr = kvmppc_gse_get_u32(gse);607break;608case KVMPPC_GSID_ASDR:609vcpu->arch.fault_gpa = kvmppc_gse_get_u64(gse);610break;611case KVMPPC_GSID_HEIR:612vcpu->arch.emul_inst = kvmppc_gse_get_u64(gse);613break;614case KVMPPC_GSID_DEC_EXPIRY_TB: {615u64 dw;616617dw = kvmppc_gse_get_u64(gse);618vcpu->arch.dec_expires =619dw + vcpu->arch.vcore->tb_offset;620break;621}622case KVMPPC_GSID_LOGICAL_PVR:623vcpu->arch.vcore->arch_compat = kvmppc_gse_get_u32(gse);624break;625default:626continue;627}628kvmppc_gsbm_set(valids, iden);629}630631return 0;632}633634static struct kvmppc_gs_msg_ops vcpu_message_ops = {635.get_size = gs_msg_ops_vcpu_get_size,636.fill_info = gs_msg_ops_vcpu_fill_info,637.refresh_info = gs_msg_ops_vcpu_refresh_info,638};639640static int kvmhv_nestedv2_host_create(struct kvm_vcpu *vcpu,641struct kvmhv_nestedv2_io *io)642{643struct kvmhv_nestedv2_config *cfg;644struct kvmppc_gs_buff *gsb, *vcpu_run_output, *vcpu_run_input;645unsigned long guest_id, vcpu_id;646struct kvmppc_gs_msg *gsm, *vcpu_message, *vcore_message;647int rc;648649cfg = &io->cfg;650guest_id = vcpu->kvm->arch.lpid;651vcpu_id = vcpu->vcpu_id;652653gsm = kvmppc_gsm_new(&config_msg_ops, cfg, KVMPPC_GS_FLAGS_WIDE,654GFP_KERNEL);655if (!gsm) {656rc = -ENOMEM;657goto err;658}659660gsb = kvmppc_gsb_new(kvmppc_gsm_size(gsm), guest_id, vcpu_id,661GFP_KERNEL);662if (!gsb) {663rc = -ENOMEM;664goto free_gsm;665}666667rc = kvmppc_gsb_receive_datum(gsb, gsm,668KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE);669if (rc < 0) {670pr_err("KVM-NESTEDv2: couldn't get vcpu run output buffer minimum size\n");671goto free_gsb;672}673674vcpu_run_output = kvmppc_gsb_new(cfg->vcpu_run_output_size, guest_id,675vcpu_id, GFP_KERNEL);676if (!vcpu_run_output) {677rc = -ENOMEM;678goto free_gsb;679}680681cfg->vcpu_run_output_cfg.address = kvmppc_gsb_paddress(vcpu_run_output);682cfg->vcpu_run_output_cfg.size = kvmppc_gsb_capacity(vcpu_run_output);683io->vcpu_run_output = vcpu_run_output;684685gsm->flags = 0;686rc = kvmppc_gsb_send_datum(gsb, gsm, KVMPPC_GSID_RUN_OUTPUT);687if (rc < 0) {688pr_err("KVM-NESTEDv2: couldn't set vcpu run output buffer\n");689goto free_gs_out;690}691692vcpu_message = kvmppc_gsm_new(&vcpu_message_ops, vcpu, 0, GFP_KERNEL);693if (!vcpu_message) {694rc = -ENOMEM;695goto free_gs_out;696}697kvmppc_gsm_include_all(vcpu_message);698699io->vcpu_message = vcpu_message;700701vcpu_run_input = kvmppc_gsb_new(kvmppc_gsm_size(vcpu_message), guest_id,702vcpu_id, GFP_KERNEL);703if (!vcpu_run_input) {704rc = -ENOMEM;705goto free_vcpu_message;706}707708io->vcpu_run_input = vcpu_run_input;709cfg->vcpu_run_input_cfg.address = kvmppc_gsb_paddress(vcpu_run_input);710cfg->vcpu_run_input_cfg.size = kvmppc_gsb_capacity(vcpu_run_input);711rc = kvmppc_gsb_send_datum(gsb, gsm, KVMPPC_GSID_RUN_INPUT);712if (rc < 0) {713pr_err("KVM-NESTEDv2: couldn't set vcpu run input buffer\n");714goto free_vcpu_run_input;715}716717vcore_message = kvmppc_gsm_new(&vcpu_message_ops, vcpu,718KVMPPC_GS_FLAGS_WIDE, GFP_KERNEL);719if (!vcore_message) {720rc = -ENOMEM;721goto free_vcpu_run_input;722}723724kvmppc_gsm_include_all(vcore_message);725kvmppc_gsbm_clear(&vcore_message->bitmap, KVMPPC_GSID_LOGICAL_PVR);726io->vcore_message = vcore_message;727728kvmppc_gsbm_fill(&io->valids);729kvmppc_gsm_free(gsm);730kvmppc_gsb_free(gsb);731return 0;732733free_vcpu_run_input:734kvmppc_gsb_free(vcpu_run_input);735free_vcpu_message:736kvmppc_gsm_free(vcpu_message);737free_gs_out:738kvmppc_gsb_free(vcpu_run_output);739free_gsb:740kvmppc_gsb_free(gsb);741free_gsm:742kvmppc_gsm_free(gsm);743err:744return rc;745}746747/**748* __kvmhv_nestedv2_mark_dirty() - mark a Guest State ID to be sent to the host749* @vcpu: vcpu750* @iden: guest state ID751*752* Mark a guest state ID as having been changed by the L1 host and thus753* the new value must be sent to the L0 hypervisor. See kvmhv_nestedv2_flush_vcpu()754*/755int __kvmhv_nestedv2_mark_dirty(struct kvm_vcpu *vcpu, u16 iden)756{757struct kvmhv_nestedv2_io *io;758struct kvmppc_gs_bitmap *valids;759struct kvmppc_gs_msg *gsm;760761if (!iden)762return 0;763764io = &vcpu->arch.nestedv2_io;765valids = &io->valids;766gsm = io->vcpu_message;767kvmppc_gsm_include(gsm, iden);768gsm = io->vcore_message;769kvmppc_gsm_include(gsm, iden);770kvmppc_gsbm_set(valids, iden);771return 0;772}773EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_mark_dirty);774775/**776* __kvmhv_nestedv2_cached_reload() - reload a Guest State ID from the host777* @vcpu: vcpu778* @iden: guest state ID779*780* Reload the value for the guest state ID from the L0 host into the L1 host.781* This is cached so that going out to the L0 host only happens if necessary.782*/783int __kvmhv_nestedv2_cached_reload(struct kvm_vcpu *vcpu, u16 iden)784{785struct kvmhv_nestedv2_io *io;786struct kvmppc_gs_bitmap *valids;787struct kvmppc_gs_buff *gsb;788struct kvmppc_gs_msg gsm;789int rc;790791if (!iden)792return 0;793794io = &vcpu->arch.nestedv2_io;795valids = &io->valids;796if (kvmppc_gsbm_test(valids, iden))797return 0;798799gsb = io->vcpu_run_input;800kvmppc_gsm_init(&gsm, &vcpu_message_ops, vcpu, kvmppc_gsid_flags(iden));801rc = kvmppc_gsb_receive_datum(gsb, &gsm, iden);802if (rc < 0) {803pr_err("KVM-NESTEDv2: couldn't get GSID: 0x%x\n", iden);804return rc;805}806return 0;807}808EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_cached_reload);809810/**811* kvmhv_nestedv2_flush_vcpu() - send modified Guest State IDs to the host812* @vcpu: vcpu813* @time_limit: hdec expiry tb814*815* Send the values marked by __kvmhv_nestedv2_mark_dirty() to the L0 host.816* Thread wide values are copied to the H_GUEST_RUN_VCPU input buffer. Guest817* wide values need to be sent with H_GUEST_SET first.818*819* The hdec tb offset is always sent to L0 host.820*/821int kvmhv_nestedv2_flush_vcpu(struct kvm_vcpu *vcpu, u64 time_limit)822{823struct kvmhv_nestedv2_io *io;824struct kvmppc_gs_buff *gsb;825struct kvmppc_gs_msg *gsm;826int rc;827828io = &vcpu->arch.nestedv2_io;829gsb = io->vcpu_run_input;830gsm = io->vcore_message;831rc = kvmppc_gsb_send_data(gsb, gsm);832if (rc < 0) {833pr_err("KVM-NESTEDv2: couldn't set guest wide elements\n");834return rc;835}836837gsm = io->vcpu_message;838kvmppc_gsb_reset(gsb);839rc = kvmppc_gsm_fill_info(gsm, gsb);840if (rc < 0) {841pr_err("KVM-NESTEDv2: couldn't fill vcpu run input buffer\n");842return rc;843}844845rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_HDEC_EXPIRY_TB, time_limit);846if (rc < 0)847return rc;848return 0;849}850EXPORT_SYMBOL_GPL(kvmhv_nestedv2_flush_vcpu);851852/**853* kvmhv_nestedv2_set_ptbl_entry() - send partition and process table state to854* L0 host855* @lpid: guest id856* @dw0: partition table double word857* @dw1: process table double word858*/859int kvmhv_nestedv2_set_ptbl_entry(unsigned long lpid, u64 dw0, u64 dw1)860{861struct kvmppc_gs_part_table patbl;862struct kvmppc_gs_proc_table prtbl;863struct kvmppc_gs_buff *gsb;864size_t size;865int rc;866867size = kvmppc_gse_total_size(868kvmppc_gsid_size(KVMPPC_GSID_PARTITION_TABLE)) +869kvmppc_gse_total_size(870kvmppc_gsid_size(KVMPPC_GSID_PROCESS_TABLE)) +871sizeof(struct kvmppc_gs_header);872gsb = kvmppc_gsb_new(size, lpid, 0, GFP_KERNEL);873if (!gsb)874return -ENOMEM;875876patbl.address = dw0 & RPDB_MASK;877patbl.ea_bits = ((((dw0 & RTS1_MASK) >> (RTS1_SHIFT - 3)) |878((dw0 & RTS2_MASK) >> RTS2_SHIFT)) +87931);880patbl.gpd_size = 1ul << ((dw0 & RPDS_MASK) + 3);881rc = kvmppc_gse_put_part_table(gsb, KVMPPC_GSID_PARTITION_TABLE, patbl);882if (rc < 0)883goto free_gsb;884885prtbl.address = dw1 & PRTB_MASK;886prtbl.gpd_size = 1ul << ((dw1 & PRTS_MASK) + 12);887rc = kvmppc_gse_put_proc_table(gsb, KVMPPC_GSID_PROCESS_TABLE, prtbl);888if (rc < 0)889goto free_gsb;890891rc = kvmppc_gsb_send(gsb, KVMPPC_GS_FLAGS_WIDE);892if (rc < 0) {893pr_err("KVM-NESTEDv2: couldn't set the PATE\n");894goto free_gsb;895}896897kvmppc_gsb_free(gsb);898return 0;899900free_gsb:901kvmppc_gsb_free(gsb);902return rc;903}904EXPORT_SYMBOL_GPL(kvmhv_nestedv2_set_ptbl_entry);905906/**907* kvmhv_nestedv2_set_vpa() - register L2 VPA with L0908* @vcpu: vcpu909* @vpa: L1 logical real address910*/911int kvmhv_nestedv2_set_vpa(struct kvm_vcpu *vcpu, unsigned long vpa)912{913struct kvmhv_nestedv2_io *io;914struct kvmppc_gs_buff *gsb;915int rc = 0;916917io = &vcpu->arch.nestedv2_io;918gsb = io->vcpu_run_input;919920kvmppc_gsb_reset(gsb);921rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_VPA, vpa);922if (rc < 0)923goto out;924925rc = kvmppc_gsb_send(gsb, 0);926if (rc < 0)927pr_err("KVM-NESTEDv2: couldn't register the L2 VPA (rc=%d)\n", rc);928929out:930kvmppc_gsb_reset(gsb);931return rc;932}933EXPORT_SYMBOL_GPL(kvmhv_nestedv2_set_vpa);934935/**936* kvmhv_nestedv2_parse_output() - receive values from H_GUEST_RUN_VCPU output937* @vcpu: vcpu938*939* Parse the output buffer from H_GUEST_RUN_VCPU to update vcpu.940*/941int kvmhv_nestedv2_parse_output(struct kvm_vcpu *vcpu)942{943struct kvmhv_nestedv2_io *io;944struct kvmppc_gs_buff *gsb;945struct kvmppc_gs_msg gsm;946947io = &vcpu->arch.nestedv2_io;948gsb = io->vcpu_run_output;949950vcpu->arch.fault_dar = 0;951vcpu->arch.fault_dsisr = 0;952vcpu->arch.fault_gpa = 0;953vcpu->arch.emul_inst = KVM_INST_FETCH_FAILED;954955kvmppc_gsm_init(&gsm, &vcpu_message_ops, vcpu, 0);956return kvmppc_gsm_refresh_info(&gsm, gsb);957}958EXPORT_SYMBOL_GPL(kvmhv_nestedv2_parse_output);959960static void kvmhv_nestedv2_host_free(struct kvm_vcpu *vcpu,961struct kvmhv_nestedv2_io *io)962{963kvmppc_gsm_free(io->vcpu_message);964kvmppc_gsm_free(io->vcore_message);965kvmppc_gsb_free(io->vcpu_run_input);966kvmppc_gsb_free(io->vcpu_run_output);967}968969int __kvmhv_nestedv2_reload_ptregs(struct kvm_vcpu *vcpu, struct pt_regs *regs)970{971struct kvmhv_nestedv2_io *io;972struct kvmppc_gs_bitmap *valids;973struct kvmppc_gs_buff *gsb;974struct kvmppc_gs_msg gsm;975int rc = 0;976977978io = &vcpu->arch.nestedv2_io;979valids = &io->valids;980981gsb = io->vcpu_run_input;982kvmppc_gsm_init(&gsm, &vcpu_message_ops, vcpu, 0);983984for (int i = 0; i < 32; i++) {985if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_GPR(i)))986kvmppc_gsm_include(&gsm, KVMPPC_GSID_GPR(i));987}988989if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_CR))990kvmppc_gsm_include(&gsm, KVMPPC_GSID_CR);991992if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_XER))993kvmppc_gsm_include(&gsm, KVMPPC_GSID_XER);994995if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_CTR))996kvmppc_gsm_include(&gsm, KVMPPC_GSID_CTR);997998if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_LR))999kvmppc_gsm_include(&gsm, KVMPPC_GSID_LR);10001001if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_NIA))1002kvmppc_gsm_include(&gsm, KVMPPC_GSID_NIA);10031004rc = kvmppc_gsb_receive_data(gsb, &gsm);1005if (rc < 0)1006pr_err("KVM-NESTEDv2: couldn't reload ptregs\n");10071008return rc;1009}1010EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_reload_ptregs);10111012int __kvmhv_nestedv2_mark_dirty_ptregs(struct kvm_vcpu *vcpu,1013struct pt_regs *regs)1014{1015for (int i = 0; i < 32; i++)1016kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_GPR(i));10171018kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_CR);1019kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_XER);1020kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_CTR);1021kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LR);1022kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_NIA);10231024return 0;1025}1026EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_mark_dirty_ptregs);10271028/**1029* kvmhv_nestedv2_vcpu_create() - create nested vcpu for the NESTEDv2 API1030* @vcpu: vcpu1031* @io: NESTEDv2 nested io state1032*1033* Parse the output buffer from H_GUEST_RUN_VCPU to update vcpu.1034*/1035int kvmhv_nestedv2_vcpu_create(struct kvm_vcpu *vcpu,1036struct kvmhv_nestedv2_io *io)1037{1038long rc;10391040rc = plpar_guest_create_vcpu(0, vcpu->kvm->arch.lpid, vcpu->vcpu_id);10411042if (rc != H_SUCCESS) {1043pr_err("KVM: Create Guest vcpu hcall failed, rc=%ld\n", rc);1044switch (rc) {1045case H_NOT_ENOUGH_RESOURCES:1046case H_ABORTED:1047return -ENOMEM;1048case H_AUTHORITY:1049return -EPERM;1050default:1051return -EINVAL;1052}1053}10541055rc = kvmhv_nestedv2_host_create(vcpu, io);10561057return rc;1058}1059EXPORT_SYMBOL_GPL(kvmhv_nestedv2_vcpu_create);10601061/**1062* kvmhv_nestedv2_vcpu_free() - free the NESTEDv2 state1063* @vcpu: vcpu1064* @io: NESTEDv2 nested io state1065*/1066void kvmhv_nestedv2_vcpu_free(struct kvm_vcpu *vcpu,1067struct kvmhv_nestedv2_io *io)1068{1069kvmhv_nestedv2_host_free(vcpu, io);1070}1071EXPORT_SYMBOL_GPL(kvmhv_nestedv2_vcpu_free);107210731074