| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright 2023 Jordan Niethe, IBM Corp. <jniethe5@gmail.com>
- *
- * Authors:
- * Jordan Niethe <jniethe5@gmail.com>
- *
- * Description: KVM functions specific to running on Book 3S
- * processors as a NESTEDv2 guest.
- *
- */
- #include "linux/blk-mq.h"
- #include "linux/console.h"
- #include "linux/gfp_types.h"
- #include "linux/signal.h"
- #include <linux/kernel.h>
- #include <linux/kvm_host.h>
- #include <linux/pgtable.h>
- #include <asm/kvm_ppc.h>
- #include <asm/kvm_book3s.h>
- #include <asm/hvcall.h>
- #include <asm/pgalloc.h>
- #include <asm/reg.h>
- #include <asm/plpar_wrappers.h>
- #include <asm/guest-state-buffer.h>
- #include "trace_hv.h"
- struct static_key_false __kvmhv_is_nestedv2 __read_mostly;
- EXPORT_SYMBOL_GPL(__kvmhv_is_nestedv2);
- static size_t
- gs_msg_ops_kvmhv_nestedv2_config_get_size(struct kvmppc_gs_msg *gsm)
- {
- u16 ids[] = {
- KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE,
- KVMPPC_GSID_RUN_INPUT,
- KVMPPC_GSID_RUN_OUTPUT,
- };
- size_t size = 0;
- for (int i = 0; i < ARRAY_SIZE(ids); i++)
- size += kvmppc_gse_total_size(kvmppc_gsid_size(ids[i]));
- return size;
- }
- static int
- gs_msg_ops_kvmhv_nestedv2_config_fill_info(struct kvmppc_gs_buff *gsb,
- struct kvmppc_gs_msg *gsm)
- {
- struct kvmhv_nestedv2_config *cfg;
- int rc;
- cfg = gsm->data;
- if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE)) {
- rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE,
- cfg->vcpu_run_output_size);
- if (rc < 0)
- return rc;
- }
- if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_INPUT)) {
- rc = kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_INPUT,
- cfg->vcpu_run_input_cfg);
- if (rc < 0)
- return rc;
- }
- if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_OUTPUT)) {
- rc = kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_OUTPUT,
- cfg->vcpu_run_output_cfg);
- if (rc < 0)
- return rc;
- }
- return 0;
- }
- static int
- gs_msg_ops_kvmhv_nestedv2_config_refresh_info(struct kvmppc_gs_msg *gsm,
- struct kvmppc_gs_buff *gsb)
- {
- struct kvmhv_nestedv2_config *cfg;
- struct kvmppc_gs_parser gsp = { 0 };
- struct kvmppc_gs_elem *gse;
- int rc;
- cfg = gsm->data;
- rc = kvmppc_gse_parse(&gsp, gsb);
- if (rc < 0)
- return rc;
- gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE);
- if (gse)
- cfg->vcpu_run_output_size = kvmppc_gse_get_u64(gse);
- return 0;
- }
- static struct kvmppc_gs_msg_ops config_msg_ops = {
- .get_size = gs_msg_ops_kvmhv_nestedv2_config_get_size,
- .fill_info = gs_msg_ops_kvmhv_nestedv2_config_fill_info,
- .refresh_info = gs_msg_ops_kvmhv_nestedv2_config_refresh_info,
- };
- static size_t gs_msg_ops_vcpu_get_size(struct kvmppc_gs_msg *gsm)
- {
- struct kvmppc_gs_bitmap gsbm = { 0 };
- size_t size = 0;
- u16 iden;
- kvmppc_gsbm_fill(&gsbm);
- kvmppc_gsbm_for_each(&gsbm, iden)
- {
- switch (iden) {
- case KVMPPC_GSID_HOST_STATE_SIZE:
- case KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE:
- case KVMPPC_GSID_PARTITION_TABLE:
- case KVMPPC_GSID_PROCESS_TABLE:
- case KVMPPC_GSID_RUN_INPUT:
- case KVMPPC_GSID_RUN_OUTPUT:
- /* Host wide counters */
- case KVMPPC_GSID_L0_GUEST_HEAP:
- case KVMPPC_GSID_L0_GUEST_HEAP_MAX:
- case KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE:
- case KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE_MAX:
- case KVMPPC_GSID_L0_GUEST_PGTABLE_RECLAIM:
- break;
- default:
- size += kvmppc_gse_total_size(kvmppc_gsid_size(iden));
- }
- }
- return size;
- }
- static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb,
- struct kvmppc_gs_msg *gsm)
- {
- struct kvm_vcpu *vcpu;
- vector128 v;
- int rc, i;
- u16 iden;
- u32 arch_compat = 0;
- vcpu = gsm->data;
- kvmppc_gsm_for_each(gsm, iden)
- {
- rc = 0;
- if ((gsm->flags & KVMPPC_GS_FLAGS_WIDE) !=
- (kvmppc_gsid_flags(iden) & KVMPPC_GS_FLAGS_WIDE))
- continue;
- switch (iden) {
- case KVMPPC_GSID_DSCR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dscr);
- break;
- case KVMPPC_GSID_MMCRA:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.mmcra);
- break;
- case KVMPPC_GSID_HFSCR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.hfscr);
- break;
- case KVMPPC_GSID_PURR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.purr);
- break;
- case KVMPPC_GSID_SPURR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.spurr);
- break;
- case KVMPPC_GSID_AMR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.amr);
- break;
- case KVMPPC_GSID_UAMOR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.uamor);
- break;
- case KVMPPC_GSID_SIAR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.siar);
- break;
- case KVMPPC_GSID_SDAR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.sdar);
- break;
- case KVMPPC_GSID_IAMR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.iamr);
- break;
- case KVMPPC_GSID_DAWR0:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dawr0);
- break;
- case KVMPPC_GSID_DAWR1:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dawr1);
- break;
- case KVMPPC_GSID_DAWRX0:
- rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.dawrx0);
- break;
- case KVMPPC_GSID_DAWRX1:
- rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.dawrx1);
- break;
- case KVMPPC_GSID_DEXCR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dexcr);
- break;
- case KVMPPC_GSID_HASHKEYR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.hashkeyr);
- break;
- case KVMPPC_GSID_HASHPKEYR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.hashpkeyr);
- break;
- case KVMPPC_GSID_CIABR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ciabr);
- break;
- case KVMPPC_GSID_WORT:
- rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.wort);
- break;
- case KVMPPC_GSID_PPR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ppr);
- break;
- case KVMPPC_GSID_PSPB:
- rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.pspb);
- break;
- case KVMPPC_GSID_TAR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.tar);
- break;
- case KVMPPC_GSID_FSCR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.fscr);
- break;
- case KVMPPC_GSID_EBBHR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ebbhr);
- break;
- case KVMPPC_GSID_EBBRR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ebbrr);
- break;
- case KVMPPC_GSID_BESCR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.bescr);
- break;
- case KVMPPC_GSID_IC:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ic);
- break;
- case KVMPPC_GSID_CTRL:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ctrl);
- break;
- case KVMPPC_GSID_PIDR:
- rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.pid);
- break;
- case KVMPPC_GSID_AMOR: {
- u64 amor = ~0;
- rc = kvmppc_gse_put_u64(gsb, iden, amor);
- break;
- }
- case KVMPPC_GSID_VRSAVE:
- rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.vrsave);
- break;
- case KVMPPC_GSID_MMCR(0)... KVMPPC_GSID_MMCR(3):
- i = iden - KVMPPC_GSID_MMCR(0);
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.mmcr[i]);
- break;
- case KVMPPC_GSID_SIER(0)... KVMPPC_GSID_SIER(2):
- i = iden - KVMPPC_GSID_SIER(0);
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.sier[i]);
- break;
- case KVMPPC_GSID_PMC(0)... KVMPPC_GSID_PMC(5):
- i = iden - KVMPPC_GSID_PMC(0);
- rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.pmc[i]);
- break;
- case KVMPPC_GSID_GPR(0)... KVMPPC_GSID_GPR(31):
- i = iden - KVMPPC_GSID_GPR(0);
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.regs.gpr[i]);
- break;
- case KVMPPC_GSID_CR:
- rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.regs.ccr);
- break;
- case KVMPPC_GSID_XER:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.regs.xer);
- break;
- case KVMPPC_GSID_CTR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.regs.ctr);
- break;
- case KVMPPC_GSID_LR:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.regs.link);
- break;
- case KVMPPC_GSID_NIA:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.regs.nip);
- break;
- case KVMPPC_GSID_SRR0:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.shregs.srr0);
- break;
- case KVMPPC_GSID_SRR1:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.shregs.srr1);
- break;
- case KVMPPC_GSID_SPRG0:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.shregs.sprg0);
- break;
- case KVMPPC_GSID_SPRG1:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.shregs.sprg1);
- break;
- case KVMPPC_GSID_SPRG2:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.shregs.sprg2);
- break;
- case KVMPPC_GSID_SPRG3:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.shregs.sprg3);
- break;
- case KVMPPC_GSID_DAR:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.shregs.dar);
- break;
- case KVMPPC_GSID_DSISR:
- rc = kvmppc_gse_put_u32(gsb, iden,
- vcpu->arch.shregs.dsisr);
- break;
- case KVMPPC_GSID_MSR:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.shregs.msr);
- break;
- case KVMPPC_GSID_VTB:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.vcore->vtb);
- break;
- case KVMPPC_GSID_DPDES:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.vcore->dpdes);
- break;
- case KVMPPC_GSID_LPCR:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.vcore->lpcr);
- break;
- case KVMPPC_GSID_TB_OFFSET:
- rc = kvmppc_gse_put_u64(gsb, iden,
- vcpu->arch.vcore->tb_offset);
- break;
- case KVMPPC_GSID_FPSCR:
- rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.fp.fpscr);
- break;
- case KVMPPC_GSID_VSRS(0)... KVMPPC_GSID_VSRS(31):
- i = iden - KVMPPC_GSID_VSRS(0);
- memcpy(&v, &vcpu->arch.fp.fpr[i],
- sizeof(vcpu->arch.fp.fpr[i]));
- rc = kvmppc_gse_put_vector128(gsb, iden, &v);
- break;
- #ifdef CONFIG_VSX
- case KVMPPC_GSID_VSCR:
- rc = kvmppc_gse_put_u32(gsb, iden,
- vcpu->arch.vr.vscr.u[3]);
- break;
- case KVMPPC_GSID_VSRS(32)... KVMPPC_GSID_VSRS(63):
- i = iden - KVMPPC_GSID_VSRS(32);
- rc = kvmppc_gse_put_vector128(gsb, iden,
- &vcpu->arch.vr.vr[i]);
- break;
- #endif
- case KVMPPC_GSID_DEC_EXPIRY_TB: {
- u64 dw;
- dw = vcpu->arch.dec_expires -
- vcpu->arch.vcore->tb_offset;
- rc = kvmppc_gse_put_u64(gsb, iden, dw);
- break;
- }
- case KVMPPC_GSID_LOGICAL_PVR:
- /*
- * Though 'arch_compat == 0' would mean the default
- * compatibility, arch_compat, being a Guest Wide
- * Element, cannot be filled with a value of 0 in GSB
- * as this would result into a kernel trap.
- * Hence, when `arch_compat == 0`, arch_compat should
- * default to L1's PVR.
- */
- if (!vcpu->arch.vcore->arch_compat) {
- if (cpu_has_feature(CPU_FTR_P11_PVR))
- arch_compat = PVR_ARCH_31_P11;
- else if (cpu_has_feature(CPU_FTR_ARCH_31))
- arch_compat = PVR_ARCH_31;
- else if (cpu_has_feature(CPU_FTR_ARCH_300))
- arch_compat = PVR_ARCH_300;
- } else {
- arch_compat = vcpu->arch.vcore->arch_compat;
- }
- rc = kvmppc_gse_put_u32(gsb, iden, arch_compat);
- break;
- }
- if (rc < 0)
- return rc;
- }
- return 0;
- }
- static int gs_msg_ops_vcpu_refresh_info(struct kvmppc_gs_msg *gsm,
- struct kvmppc_gs_buff *gsb)
- {
- struct kvmppc_gs_parser gsp = { 0 };
- struct kvmhv_nestedv2_io *io;
- struct kvmppc_gs_bitmap *valids;
- struct kvm_vcpu *vcpu;
- struct kvmppc_gs_elem *gse;
- vector128 v;
- int rc, i;
- u16 iden;
- vcpu = gsm->data;
- rc = kvmppc_gse_parse(&gsp, gsb);
- if (rc < 0)
- return rc;
- io = &vcpu->arch.nestedv2_io;
- valids = &io->valids;
- kvmppc_gsp_for_each(&gsp, iden, gse)
- {
- switch (iden) {
- case KVMPPC_GSID_DSCR:
- vcpu->arch.dscr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_MMCRA:
- vcpu->arch.mmcra = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_HFSCR:
- vcpu->arch.hfscr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_PURR:
- vcpu->arch.purr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_SPURR:
- vcpu->arch.spurr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_AMR:
- vcpu->arch.amr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_UAMOR:
- vcpu->arch.uamor = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_SIAR:
- vcpu->arch.siar = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_SDAR:
- vcpu->arch.sdar = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_IAMR:
- vcpu->arch.iamr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_DAWR0:
- vcpu->arch.dawr0 = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_DAWR1:
- vcpu->arch.dawr1 = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_DAWRX0:
- vcpu->arch.dawrx0 = kvmppc_gse_get_u32(gse);
- break;
- case KVMPPC_GSID_DAWRX1:
- vcpu->arch.dawrx1 = kvmppc_gse_get_u32(gse);
- break;
- case KVMPPC_GSID_DEXCR:
- vcpu->arch.dexcr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_HASHKEYR:
- vcpu->arch.hashkeyr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_HASHPKEYR:
- vcpu->arch.hashpkeyr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_CIABR:
- vcpu->arch.ciabr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_WORT:
- vcpu->arch.wort = kvmppc_gse_get_u32(gse);
- break;
- case KVMPPC_GSID_PPR:
- vcpu->arch.ppr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_PSPB:
- vcpu->arch.pspb = kvmppc_gse_get_u32(gse);
- break;
- case KVMPPC_GSID_TAR:
- vcpu->arch.tar = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_FSCR:
- vcpu->arch.fscr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_EBBHR:
- vcpu->arch.ebbhr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_EBBRR:
- vcpu->arch.ebbrr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_BESCR:
- vcpu->arch.bescr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_IC:
- vcpu->arch.ic = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_CTRL:
- vcpu->arch.ctrl = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_PIDR:
- vcpu->arch.pid = kvmppc_gse_get_u32(gse);
- break;
- case KVMPPC_GSID_AMOR:
- break;
- case KVMPPC_GSID_VRSAVE:
- vcpu->arch.vrsave = kvmppc_gse_get_u32(gse);
- break;
- case KVMPPC_GSID_MMCR(0)... KVMPPC_GSID_MMCR(3):
- i = iden - KVMPPC_GSID_MMCR(0);
- vcpu->arch.mmcr[i] = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_SIER(0)... KVMPPC_GSID_SIER(2):
- i = iden - KVMPPC_GSID_SIER(0);
- vcpu->arch.sier[i] = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_PMC(0)... KVMPPC_GSID_PMC(5):
- i = iden - KVMPPC_GSID_PMC(0);
- vcpu->arch.pmc[i] = kvmppc_gse_get_u32(gse);
- break;
- case KVMPPC_GSID_GPR(0)... KVMPPC_GSID_GPR(31):
- i = iden - KVMPPC_GSID_GPR(0);
- vcpu->arch.regs.gpr[i] = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_CR:
- vcpu->arch.regs.ccr = kvmppc_gse_get_u32(gse);
- break;
- case KVMPPC_GSID_XER:
- vcpu->arch.regs.xer = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_CTR:
- vcpu->arch.regs.ctr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_LR:
- vcpu->arch.regs.link = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_NIA:
- vcpu->arch.regs.nip = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_SRR0:
- vcpu->arch.shregs.srr0 = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_SRR1:
- vcpu->arch.shregs.srr1 = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_SPRG0:
- vcpu->arch.shregs.sprg0 = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_SPRG1:
- vcpu->arch.shregs.sprg1 = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_SPRG2:
- vcpu->arch.shregs.sprg2 = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_SPRG3:
- vcpu->arch.shregs.sprg3 = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_DAR:
- vcpu->arch.shregs.dar = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_DSISR:
- vcpu->arch.shregs.dsisr = kvmppc_gse_get_u32(gse);
- break;
- case KVMPPC_GSID_MSR:
- vcpu->arch.shregs.msr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_VTB:
- vcpu->arch.vcore->vtb = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_DPDES:
- vcpu->arch.vcore->dpdes = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_LPCR:
- vcpu->arch.vcore->lpcr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_TB_OFFSET:
- vcpu->arch.vcore->tb_offset = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_FPSCR:
- vcpu->arch.fp.fpscr = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_VSRS(0)... KVMPPC_GSID_VSRS(31):
- kvmppc_gse_get_vector128(gse, &v);
- i = iden - KVMPPC_GSID_VSRS(0);
- memcpy(&vcpu->arch.fp.fpr[i], &v,
- sizeof(vcpu->arch.fp.fpr[i]));
- break;
- #ifdef CONFIG_VSX
- case KVMPPC_GSID_VSCR:
- vcpu->arch.vr.vscr.u[3] = kvmppc_gse_get_u32(gse);
- break;
- case KVMPPC_GSID_VSRS(32)... KVMPPC_GSID_VSRS(63):
- i = iden - KVMPPC_GSID_VSRS(32);
- kvmppc_gse_get_vector128(gse, &vcpu->arch.vr.vr[i]);
- break;
- #endif
- case KVMPPC_GSID_HDAR:
- vcpu->arch.fault_dar = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_HDSISR:
- vcpu->arch.fault_dsisr = kvmppc_gse_get_u32(gse);
- break;
- case KVMPPC_GSID_ASDR:
- vcpu->arch.fault_gpa = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_HEIR:
- vcpu->arch.emul_inst = kvmppc_gse_get_u64(gse);
- break;
- case KVMPPC_GSID_DEC_EXPIRY_TB: {
- u64 dw;
- dw = kvmppc_gse_get_u64(gse);
- vcpu->arch.dec_expires =
- dw + vcpu->arch.vcore->tb_offset;
- break;
- }
- case KVMPPC_GSID_LOGICAL_PVR:
- vcpu->arch.vcore->arch_compat = kvmppc_gse_get_u32(gse);
- break;
- default:
- continue;
- }
- kvmppc_gsbm_set(valids, iden);
- }
- return 0;
- }
- static struct kvmppc_gs_msg_ops vcpu_message_ops = {
- .get_size = gs_msg_ops_vcpu_get_size,
- .fill_info = gs_msg_ops_vcpu_fill_info,
- .refresh_info = gs_msg_ops_vcpu_refresh_info,
- };
- static int kvmhv_nestedv2_host_create(struct kvm_vcpu *vcpu,
- struct kvmhv_nestedv2_io *io)
- {
- struct kvmhv_nestedv2_config *cfg;
- struct kvmppc_gs_buff *gsb, *vcpu_run_output, *vcpu_run_input;
- unsigned long guest_id, vcpu_id;
- struct kvmppc_gs_msg *gsm, *vcpu_message, *vcore_message;
- int rc;
- cfg = &io->cfg;
- guest_id = vcpu->kvm->arch.lpid;
- vcpu_id = vcpu->vcpu_id;
- gsm = kvmppc_gsm_new(&config_msg_ops, cfg, KVMPPC_GS_FLAGS_WIDE,
- GFP_KERNEL);
- if (!gsm) {
- rc = -ENOMEM;
- goto err;
- }
- gsb = kvmppc_gsb_new(kvmppc_gsm_size(gsm), guest_id, vcpu_id,
- GFP_KERNEL);
- if (!gsb) {
- rc = -ENOMEM;
- goto free_gsm;
- }
- rc = kvmppc_gsb_receive_datum(gsb, gsm,
- KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE);
- if (rc < 0) {
- pr_err("KVM-NESTEDv2: couldn't get vcpu run output buffer minimum size\n");
- goto free_gsb;
- }
- vcpu_run_output = kvmppc_gsb_new(cfg->vcpu_run_output_size, guest_id,
- vcpu_id, GFP_KERNEL);
- if (!vcpu_run_output) {
- rc = -ENOMEM;
- goto free_gsb;
- }
- cfg->vcpu_run_output_cfg.address = kvmppc_gsb_paddress(vcpu_run_output);
- cfg->vcpu_run_output_cfg.size = kvmppc_gsb_capacity(vcpu_run_output);
- io->vcpu_run_output = vcpu_run_output;
- gsm->flags = 0;
- rc = kvmppc_gsb_send_datum(gsb, gsm, KVMPPC_GSID_RUN_OUTPUT);
- if (rc < 0) {
- pr_err("KVM-NESTEDv2: couldn't set vcpu run output buffer\n");
- goto free_gs_out;
- }
- vcpu_message = kvmppc_gsm_new(&vcpu_message_ops, vcpu, 0, GFP_KERNEL);
- if (!vcpu_message) {
- rc = -ENOMEM;
- goto free_gs_out;
- }
- kvmppc_gsm_include_all(vcpu_message);
- io->vcpu_message = vcpu_message;
- vcpu_run_input = kvmppc_gsb_new(kvmppc_gsm_size(vcpu_message), guest_id,
- vcpu_id, GFP_KERNEL);
- if (!vcpu_run_input) {
- rc = -ENOMEM;
- goto free_vcpu_message;
- }
- io->vcpu_run_input = vcpu_run_input;
- cfg->vcpu_run_input_cfg.address = kvmppc_gsb_paddress(vcpu_run_input);
- cfg->vcpu_run_input_cfg.size = kvmppc_gsb_capacity(vcpu_run_input);
- rc = kvmppc_gsb_send_datum(gsb, gsm, KVMPPC_GSID_RUN_INPUT);
- if (rc < 0) {
- pr_err("KVM-NESTEDv2: couldn't set vcpu run input buffer\n");
- goto free_vcpu_run_input;
- }
- vcore_message = kvmppc_gsm_new(&vcpu_message_ops, vcpu,
- KVMPPC_GS_FLAGS_WIDE, GFP_KERNEL);
- if (!vcore_message) {
- rc = -ENOMEM;
- goto free_vcpu_run_input;
- }
- kvmppc_gsm_include_all(vcore_message);
- kvmppc_gsbm_clear(&vcore_message->bitmap, KVMPPC_GSID_LOGICAL_PVR);
- io->vcore_message = vcore_message;
- kvmppc_gsbm_fill(&io->valids);
- kvmppc_gsm_free(gsm);
- kvmppc_gsb_free(gsb);
- return 0;
- free_vcpu_run_input:
- kvmppc_gsb_free(vcpu_run_input);
- free_vcpu_message:
- kvmppc_gsm_free(vcpu_message);
- free_gs_out:
- kvmppc_gsb_free(vcpu_run_output);
- free_gsb:
- kvmppc_gsb_free(gsb);
- free_gsm:
- kvmppc_gsm_free(gsm);
- err:
- return rc;
- }
- /**
- * __kvmhv_nestedv2_mark_dirty() - mark a Guest State ID to be sent to the host
- * @vcpu: vcpu
- * @iden: guest state ID
- *
- * Mark a guest state ID as having been changed by the L1 host and thus
- * the new value must be sent to the L0 hypervisor. See kvmhv_nestedv2_flush_vcpu()
- */
- int __kvmhv_nestedv2_mark_dirty(struct kvm_vcpu *vcpu, u16 iden)
- {
- struct kvmhv_nestedv2_io *io;
- struct kvmppc_gs_bitmap *valids;
- struct kvmppc_gs_msg *gsm;
- if (!iden)
- return 0;
- io = &vcpu->arch.nestedv2_io;
- valids = &io->valids;
- gsm = io->vcpu_message;
- kvmppc_gsm_include(gsm, iden);
- gsm = io->vcore_message;
- kvmppc_gsm_include(gsm, iden);
- kvmppc_gsbm_set(valids, iden);
- return 0;
- }
- EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_mark_dirty);
- /**
- * __kvmhv_nestedv2_cached_reload() - reload a Guest State ID from the host
- * @vcpu: vcpu
- * @iden: guest state ID
- *
- * Reload the value for the guest state ID from the L0 host into the L1 host.
- * This is cached so that going out to the L0 host only happens if necessary.
- */
- int __kvmhv_nestedv2_cached_reload(struct kvm_vcpu *vcpu, u16 iden)
- {
- struct kvmhv_nestedv2_io *io;
- struct kvmppc_gs_bitmap *valids;
- struct kvmppc_gs_buff *gsb;
- struct kvmppc_gs_msg gsm;
- int rc;
- if (!iden)
- return 0;
- io = &vcpu->arch.nestedv2_io;
- valids = &io->valids;
- if (kvmppc_gsbm_test(valids, iden))
- return 0;
- gsb = io->vcpu_run_input;
- kvmppc_gsm_init(&gsm, &vcpu_message_ops, vcpu, kvmppc_gsid_flags(iden));
- rc = kvmppc_gsb_receive_datum(gsb, &gsm, iden);
- if (rc < 0) {
- pr_err("KVM-NESTEDv2: couldn't get GSID: 0x%x\n", iden);
- return rc;
- }
- return 0;
- }
- EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_cached_reload);
- /**
- * kvmhv_nestedv2_flush_vcpu() - send modified Guest State IDs to the host
- * @vcpu: vcpu
- * @time_limit: hdec expiry tb
- *
- * Send the values marked by __kvmhv_nestedv2_mark_dirty() to the L0 host.
- * Thread wide values are copied to the H_GUEST_RUN_VCPU input buffer. Guest
- * wide values need to be sent with H_GUEST_SET first.
- *
- * The hdec tb offset is always sent to L0 host.
- */
- int kvmhv_nestedv2_flush_vcpu(struct kvm_vcpu *vcpu, u64 time_limit)
- {
- struct kvmhv_nestedv2_io *io;
- struct kvmppc_gs_buff *gsb;
- struct kvmppc_gs_msg *gsm;
- int rc;
- io = &vcpu->arch.nestedv2_io;
- gsb = io->vcpu_run_input;
- gsm = io->vcore_message;
- rc = kvmppc_gsb_send_data(gsb, gsm);
- if (rc < 0) {
- pr_err("KVM-NESTEDv2: couldn't set guest wide elements\n");
- return rc;
- }
- gsm = io->vcpu_message;
- kvmppc_gsb_reset(gsb);
- rc = kvmppc_gsm_fill_info(gsm, gsb);
- if (rc < 0) {
- pr_err("KVM-NESTEDv2: couldn't fill vcpu run input buffer\n");
- return rc;
- }
- rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_HDEC_EXPIRY_TB, time_limit);
- if (rc < 0)
- return rc;
- return 0;
- }
- EXPORT_SYMBOL_GPL(kvmhv_nestedv2_flush_vcpu);
- /**
- * kvmhv_nestedv2_set_ptbl_entry() - send partition and process table state to
- * L0 host
- * @lpid: guest id
- * @dw0: partition table double word
- * @dw1: process table double word
- */
- int kvmhv_nestedv2_set_ptbl_entry(unsigned long lpid, u64 dw0, u64 dw1)
- {
- struct kvmppc_gs_part_table patbl;
- struct kvmppc_gs_proc_table prtbl;
- struct kvmppc_gs_buff *gsb;
- size_t size;
- int rc;
- size = kvmppc_gse_total_size(
- kvmppc_gsid_size(KVMPPC_GSID_PARTITION_TABLE)) +
- kvmppc_gse_total_size(
- kvmppc_gsid_size(KVMPPC_GSID_PROCESS_TABLE)) +
- sizeof(struct kvmppc_gs_header);
- gsb = kvmppc_gsb_new(size, lpid, 0, GFP_KERNEL);
- if (!gsb)
- return -ENOMEM;
- patbl.address = dw0 & RPDB_MASK;
- patbl.ea_bits = ((((dw0 & RTS1_MASK) >> (RTS1_SHIFT - 3)) |
- ((dw0 & RTS2_MASK) >> RTS2_SHIFT)) +
- 31);
- patbl.gpd_size = 1ul << ((dw0 & RPDS_MASK) + 3);
- rc = kvmppc_gse_put_part_table(gsb, KVMPPC_GSID_PARTITION_TABLE, patbl);
- if (rc < 0)
- goto free_gsb;
- prtbl.address = dw1 & PRTB_MASK;
- prtbl.gpd_size = 1ul << ((dw1 & PRTS_MASK) + 12);
- rc = kvmppc_gse_put_proc_table(gsb, KVMPPC_GSID_PROCESS_TABLE, prtbl);
- if (rc < 0)
- goto free_gsb;
- rc = kvmppc_gsb_send(gsb, KVMPPC_GS_FLAGS_WIDE);
- if (rc < 0) {
- pr_err("KVM-NESTEDv2: couldn't set the PATE\n");
- goto free_gsb;
- }
- kvmppc_gsb_free(gsb);
- return 0;
- free_gsb:
- kvmppc_gsb_free(gsb);
- return rc;
- }
- EXPORT_SYMBOL_GPL(kvmhv_nestedv2_set_ptbl_entry);
- /**
- * kvmhv_nestedv2_set_vpa() - register L2 VPA with L0
- * @vcpu: vcpu
- * @vpa: L1 logical real address
- */
- int kvmhv_nestedv2_set_vpa(struct kvm_vcpu *vcpu, unsigned long vpa)
- {
- struct kvmhv_nestedv2_io *io;
- struct kvmppc_gs_buff *gsb;
- int rc = 0;
- io = &vcpu->arch.nestedv2_io;
- gsb = io->vcpu_run_input;
- kvmppc_gsb_reset(gsb);
- rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_VPA, vpa);
- if (rc < 0)
- goto out;
- rc = kvmppc_gsb_send(gsb, 0);
- if (rc < 0)
- pr_err("KVM-NESTEDv2: couldn't register the L2 VPA (rc=%d)\n", rc);
- out:
- kvmppc_gsb_reset(gsb);
- return rc;
- }
- EXPORT_SYMBOL_GPL(kvmhv_nestedv2_set_vpa);
- /**
- * kvmhv_nestedv2_parse_output() - receive values from H_GUEST_RUN_VCPU output
- * @vcpu: vcpu
- *
- * Parse the output buffer from H_GUEST_RUN_VCPU to update vcpu.
- */
- int kvmhv_nestedv2_parse_output(struct kvm_vcpu *vcpu)
- {
- struct kvmhv_nestedv2_io *io;
- struct kvmppc_gs_buff *gsb;
- struct kvmppc_gs_msg gsm;
- io = &vcpu->arch.nestedv2_io;
- gsb = io->vcpu_run_output;
- vcpu->arch.fault_dar = 0;
- vcpu->arch.fault_dsisr = 0;
- vcpu->arch.fault_gpa = 0;
- vcpu->arch.emul_inst = KVM_INST_FETCH_FAILED;
- kvmppc_gsm_init(&gsm, &vcpu_message_ops, vcpu, 0);
- return kvmppc_gsm_refresh_info(&gsm, gsb);
- }
- EXPORT_SYMBOL_GPL(kvmhv_nestedv2_parse_output);
- static void kvmhv_nestedv2_host_free(struct kvm_vcpu *vcpu,
- struct kvmhv_nestedv2_io *io)
- {
- kvmppc_gsm_free(io->vcpu_message);
- kvmppc_gsm_free(io->vcore_message);
- kvmppc_gsb_free(io->vcpu_run_input);
- kvmppc_gsb_free(io->vcpu_run_output);
- }
- int __kvmhv_nestedv2_reload_ptregs(struct kvm_vcpu *vcpu, struct pt_regs *regs)
- {
- struct kvmhv_nestedv2_io *io;
- struct kvmppc_gs_bitmap *valids;
- struct kvmppc_gs_buff *gsb;
- struct kvmppc_gs_msg gsm;
- int rc = 0;
- io = &vcpu->arch.nestedv2_io;
- valids = &io->valids;
- gsb = io->vcpu_run_input;
- kvmppc_gsm_init(&gsm, &vcpu_message_ops, vcpu, 0);
- for (int i = 0; i < 32; i++) {
- if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_GPR(i)))
- kvmppc_gsm_include(&gsm, KVMPPC_GSID_GPR(i));
- }
- if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_CR))
- kvmppc_gsm_include(&gsm, KVMPPC_GSID_CR);
- if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_XER))
- kvmppc_gsm_include(&gsm, KVMPPC_GSID_XER);
- if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_CTR))
- kvmppc_gsm_include(&gsm, KVMPPC_GSID_CTR);
- if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_LR))
- kvmppc_gsm_include(&gsm, KVMPPC_GSID_LR);
- if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_NIA))
- kvmppc_gsm_include(&gsm, KVMPPC_GSID_NIA);
- rc = kvmppc_gsb_receive_data(gsb, &gsm);
- if (rc < 0)
- pr_err("KVM-NESTEDv2: couldn't reload ptregs\n");
- return rc;
- }
- EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_reload_ptregs);
- int __kvmhv_nestedv2_mark_dirty_ptregs(struct kvm_vcpu *vcpu,
- struct pt_regs *regs)
- {
- for (int i = 0; i < 32; i++)
- kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_GPR(i));
- kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_CR);
- kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_XER);
- kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_CTR);
- kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LR);
- kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_NIA);
- return 0;
- }
- EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_mark_dirty_ptregs);
- /**
- * kvmhv_nestedv2_vcpu_create() - create nested vcpu for the NESTEDv2 API
- * @vcpu: vcpu
- * @io: NESTEDv2 nested io state
- *
- * Parse the output buffer from H_GUEST_RUN_VCPU to update vcpu.
- */
- int kvmhv_nestedv2_vcpu_create(struct kvm_vcpu *vcpu,
- struct kvmhv_nestedv2_io *io)
- {
- long rc;
- rc = plpar_guest_create_vcpu(0, vcpu->kvm->arch.lpid, vcpu->vcpu_id);
- if (rc != H_SUCCESS) {
- pr_err("KVM: Create Guest vcpu hcall failed, rc=%ld\n", rc);
- switch (rc) {
- case H_NOT_ENOUGH_RESOURCES:
- case H_ABORTED:
- return -ENOMEM;
- case H_AUTHORITY:
- return -EPERM;
- default:
- return -EINVAL;
- }
- }
- rc = kvmhv_nestedv2_host_create(vcpu, io);
- return rc;
- }
- EXPORT_SYMBOL_GPL(kvmhv_nestedv2_vcpu_create);
- /**
- * kvmhv_nestedv2_vcpu_free() - free the NESTEDv2 state
- * @vcpu: vcpu
- * @io: NESTEDv2 nested io state
- */
- void kvmhv_nestedv2_vcpu_free(struct kvm_vcpu *vcpu,
- struct kvmhv_nestedv2_io *io)
- {
- kvmhv_nestedv2_host_free(vcpu, io);
- }
- EXPORT_SYMBOL_GPL(kvmhv_nestedv2_vcpu_free);
|