From: t30040867 tujipei@huawei.com
--- docs/schemas/domaincommon.rng | 68 ++++++++------ include/libvirt/libvirt-host.h | 2 + scripts/apibuild.py | 1 + scripts/check-aclrules.py | 1 + src/conf/domain_conf.c | 23 ++++- src/conf/domain_conf.h | 3 + src/driver-hypervisor.h | 5 + src/libvirt-host.c | 31 +++++++ src/libvirt_public.syms | 1 + src/qemu/qemu_command.c | 3 + src/qemu/qemu_driver.c | 139 ++++++++++++++++++++++++++++ src/remote/remote_daemon_dispatch.c | 23 +++++ src/remote/remote_driver.c | 29 ++++++ src/remote/remote_protocol.x | 16 +++- tools/virsh-host.c | 99 ++++++++++++++++++++ 15 files changed, 410 insertions(+), 34 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 764f826..a0a6412 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -460,38 +460,48 @@
<define name="launchSecurity"> <element name="launchSecurity"> - <attribute name="type"> - <value>sev</value> - </attribute> - <interleave> - <element name="cbitpos"> - <data type='unsignedInt'/> - </element> - <element name="reducedPhysBits"> - <data type='unsignedInt'/> - </element> - <element name="policy"> - <ref name='hexuint'/> - </element> - <optional> - <element name="handle"> - <ref name='unsignedInt'/> - </element> - </optional> - <optional> - <element name="dhCert"> - <data type="string"/> - </element> - </optional> - <optional> - <element name="session"> - <data type="string"/> - </element> - </optional> - </interleave> + <choice> + <group> + <attribute name="type"> + <value>sev</value> + </attribute> + <interleave> + <element name="cbitpos"> + <data type='unsignedInt'/> + </element> + <element name="reducedPhysBits"> + <data type='unsignedInt'/> + </element> + <element name="policy"> + <ref name='hexuint'/> + </element> + <optional> + <element name="handle"> + <ref name='unsignedInt'/> + </element> + </optional> + <optional> + <element name="dhCert"> + <data type="string"/> + </element> + </optional> + <optional> + <element name="session"> + <data type="string"/> + </element> + </optional> + </interleave> + </group> + <group> + <attribute name="type"> + <value>cvm</value> + </attribute> + </group> + </choice> </element> </define>
+ <!-- Enable or disable perf events for the domain. For each of the events the following rules apply: diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h index 6972834..2cec0bf 100644 --- a/include/libvirt/libvirt-host.h +++ b/include/libvirt/libvirt-host.h @@ -820,5 +820,7 @@ int virNodeAllocPages(virConnectPtr conn, unsigned int cellCount, unsigned int flags);
+char *virTmmGetMemoryInfo(virConnectPtr conn, + unsigned int detail);
#endif /* LIBVIRT_HOST_H */ diff --git a/scripts/apibuild.py b/scripts/apibuild.py index c98bcf6..7b7caeb 100755 --- a/scripts/apibuild.py +++ b/scripts/apibuild.py @@ -107,6 +107,7 @@ ignored_functions = { "virDomainMigrateConfirm3Params": "private function for migration", "virDomainMigratePrepareTunnel3Params": "private function for tunnelled migration", "virErrorCopyNew": "private", + "virTmmGetMemoryInfo": "private function for tmm", }
ignored_macros = { diff --git a/scripts/check-aclrules.py b/scripts/check-aclrules.py index e196f81..eae75fd 100755 --- a/scripts/check-aclrules.py +++ b/scripts/check-aclrules.py @@ -54,6 +54,7 @@ whitelist = { "localOnly": True, "domainQemuAttach": True, "domainHotpatchManage": True, + "tmmGetMemoryInfo": True, }
# XXX this vzDomainMigrateConfirm3Params looks diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5a04d1b..a5177dc 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1272,6 +1272,7 @@ VIR_ENUM_IMPL(virDomainLaunchSecurity, VIR_DOMAIN_LAUNCH_SECURITY_LAST, "", "sev", + "cvm", );
static virClassPtr virDomainObjClass; @@ -16821,6 +16822,7 @@ virDomainSEVDefParseXML(xmlNodePtr sevNode, def->sectype = virDomainLaunchSecurityTypeFromString(type); switch ((virDomainLaunchSecurity) def->sectype) { case VIR_DOMAIN_LAUNCH_SECURITY_SEV: + case VIR_DOMAIN_LAUNCH_SECURITY_CVM: break; case VIR_DOMAIN_LAUNCH_SECURITY_NONE: case VIR_DOMAIN_LAUNCH_SECURITY_LAST: @@ -22161,9 +22163,17 @@ virDomainDefParseXML(xmlDocPtr xml,
/* Check for SEV feature */ if ((node = virXPathNode("./launchSecurity", ctxt)) != NULL) { - def->sev = virDomainSEVDefParseXML(node, ctxt); - if (!def->sev) - goto error; + tmp = virXMLPropString(node, "type"); + if((virDomainLaunchSecurity)virDomainLaunchSecurityTypeFromString(tmp) == VIR_DOMAIN_LAUNCH_SECURITY_CVM) { + def->cvm = true; + } else { + def->sev = virDomainSEVDefParseXML(node, ctxt); + if(!def->sev) { + VIR_FREE(tmp); + goto error; + } + } + VIR_FREE(tmp); }
/* analysis of memory devices */ @@ -29826,7 +29836,12 @@ virDomainDefFormatInternalSetRootName(virDomainDefPtr def, if (def->keywrap) virDomainKeyWrapDefFormat(buf, def->keywrap);
- virDomainSEVDefFormat(buf, def->sev); + if (def->cvm) { + virBufferAddLit(buf, "<launchSecurity type='cvm'>\n"); + virBufferAddLit(buf, "</launchSecurity>\n"); + } else { + virDomainSEVDefFormat(buf, def->sev); + }
virBufferAdjustIndent(buf, -2); virBufferAsprintf(buf, "</%s>\n", rootname); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6d56ef0..c7abd61 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2365,6 +2365,7 @@ struct _virDomainKeyWrapDef { typedef enum { VIR_DOMAIN_LAUNCH_SECURITY_NONE, VIR_DOMAIN_LAUNCH_SECURITY_SEV, + VIR_DOMAIN_LAUNCH_SECURITY_CVM,
VIR_DOMAIN_LAUNCH_SECURITY_LAST, } virDomainLaunchSecurity; @@ -2578,6 +2579,8 @@ struct _virDomainDef {
/* SEV-specific domain */ virDomainSEVDefPtr sev; + // support for cvm + bool cvm;
/* Application-specific custom metadata */ xmlNodePtr metadata; diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index 82f8089..aa84813 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1402,6 +1402,10 @@ typedef int typedef struct _virHypervisorDriver virHypervisorDriver; typedef virHypervisorDriver *virHypervisorDriverPtr;
+typedef char * +(*virDrvTmmGetMemoryInfo)(virConnectPtr conn, + bool detail); + /** * _virHypervisorDriver: * @@ -1664,4 +1668,5 @@ struct _virHypervisorDriver { virDrvDomainBackupGetXMLDesc domainBackupGetXMLDesc; virDrvDomainHotpatchManage domainHotpatchManage; virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc; + virDrvTmmGetMemoryInfo tmmGetMemoryInfo; }; diff --git a/src/libvirt-host.c b/src/libvirt-host.c index bc3d1d2..e9585cc 100644 --- a/src/libvirt-host.c +++ b/src/libvirt-host.c @@ -1754,3 +1754,34 @@ virNodeGetSEVInfo(virConnectPtr conn, virDispatchError(conn); return -1; } + +/* + * virGetTmmMemoryInfo: + * @conn: pointer to the hypervisor connection + * + * If Tmm enable, then will fill the cotents of tmmMemoryInfo + * + * Returns string ptr in case of success, and NULL in case of failure. + */ +char * +virTmmGetMemoryInfo(virConnectPtr conn, + unsigned int detail) +{ + VIR_DEBUG("conn=%p", conn); + + virResetLastError(); + + virCheckConnectReturn(conn, NULL); + + if (conn->driver->tmmGetMemoryInfo) { + char *ret; + ret = conn->driver->tmmGetMemoryInfo(conn, detail); + if (!ret) + goto error; + return ret; + } + + error: + virDispatchError(conn); + return NULL; +} \ No newline at end of file diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index f006516..66e6fbd 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -877,5 +877,6 @@ LIBVIRT_6.2.0 { global: virDomainHotpatchManage; virDomainStartDirtyRateCalc; + virTmmGetMemoryInfo; } LIBVIRT_6.0.0; # .... define new API here using predicted next version number .... diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index bae0606..49bcab0 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7263,6 +7263,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
if (def->sev) virBufferAddLit(&buf, ",memory-encryption=sev0"); + //support for cvm + if (def->cvm) + virBufferAddLit(&buf, ",kvm-type=cvm");
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV)) { if (priv->pflash0) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 9cb14b0..98c55a3 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -23369,6 +23369,144 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, return ret; }
+static int +qemuTmmInfoListAppend(char ***targetInfoStrList, + char **infoStrList, + int targetNumaNum, + int *startIndex, + int maxListSize) +{ + char *numStart; + int numaNode, index, ret = 0; + + for (index = *startIndex; index < maxListSize; index++) { + if (strlen(infoStrList[index]) == 0) + break; + + numStart = strstr(infoStrList[index], "node "); + if (numStart) + virSkipToDigit((const char **)(&numStart)); + + ret = virStrToLong_i(numStart, &numStart, 10, &numaNode); + if (ret < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to get current numa node")); + return ret; + } + + if (numaNode == targetNumaNum) { + ret = virStringListAdd(targetInfoStrList, infoStrList[index]); + if (ret < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s [%d]", + _("Failed to get add info list member"), index); + return ret; + } + } else { + break; + } + } + + *startIndex = index; + + return ret; +} + +static char * +qemuTmmDetailInfoFormat(char *baseMeminfo, + char *slabInfo) +{ + int ret, i = 0, j = 0; + char *numStart, *numListStart, *format = NULL; + char **baseMeminfoSplits = virStringSplit(baseMeminfo, "\n", 0); + char **slabInfoSplits = virStringSplit(slabInfo, "\n", 0); + char **resultStrList = NULL; + int numaSize, numaIndex, headNumaNode; + ssize_t meminfoListSize = virStringListLength((const char * const *)baseMeminfoSplits); + ssize_t slabInfoSize = virStringListLength((const char * const *)slabInfoSplits); + + numStart = strchr(baseMeminfoSplits[i], ':'); + if (numStart) + virSkipToDigit((const char **)(&numStart)); + + numListStart = strchr(baseMeminfoSplits[i], '('); + if (numListStart) + virSkipToDigit((const char **)(&numListStart)); + + ret = virStrToLong_i(numStart, &numStart, 10, &numaSize); + if (ret < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to get available numa size")); + goto cleanup; + } + + ret = virStringListAdd(&resultStrList, baseMeminfoSplits[i++]); + if (ret < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s [%d]", + _("Failed to get add base memory info list member"), (i - 1)); + goto cleanup; + } + + for (numaIndex = 0; numaIndex < numaSize; numaIndex++, numListStart++) { + ret = virStrToLong_i(numListStart, &numListStart, 10, &headNumaNode); + if (ret < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to get current numa node")); + goto cleanup; + } + + ret = qemuTmmInfoListAppend(&resultStrList, baseMeminfoSplits, headNumaNode, &i, meminfoListSize); + if (ret < 0) + goto cleanup; + ret = qemuTmmInfoListAppend(&resultStrList, slabInfoSplits, headNumaNode, &j, slabInfoSize); + if (ret < 0) + goto cleanup; + } + + format = virStringListJoin((const char **)resultStrList, "\n"); + + cleanup: + virStringListFree(baseMeminfoSplits); + virStringListFree(slabInfoSplits); + virStringListFree(resultStrList); + return format; +} + +static char * +qemuTmmGetMemoryInfo(virConnectPtr conn G_GNUC_UNUSED, + bool detail) +{ + int maxLen = 10 * 1024; + char *meminfo = NULL; + g_autofree char *formatInfo = NULL; + g_autofree char *baseMeminfo = NULL; + g_autofree char *slabInfo = NULL; + g_autofree char *buddyInfo = NULL; + + if (virFileReadAll("/sys/kernel/tmm/memory_info", maxLen, &baseMeminfo) < 0) + goto end; + if (detail && virFileReadAll("/sys/kernel/tmm/slab_info", maxLen, &slabInfo) < 0) + goto end; + if (detail && virFileReadAll("/sys/kernel/tmm/buddy_info", maxLen, &buddyInfo) < 0) + goto end; + + if (detail) { + if (!virStringIsEmpty(baseMeminfo) && !virStringIsEmpty(slabInfo)) { + formatInfo = qemuTmmDetailInfoFormat(baseMeminfo, slabInfo); + if (formatInfo == NULL) + goto end; + } else { + formatInfo = g_strdup_printf(_("%s%s"), baseMeminfo, slabInfo); + } + + meminfo = g_strdup_printf(_("%s\n%s"), formatInfo, buddyInfo); + } else { + meminfo = g_strdup(baseMeminfo); + } + +end: + return meminfo; +} +
static virHypervisorDriver qemuHypervisorDriver = { .name = QEMU_DRIVER_NAME, @@ -23611,6 +23749,7 @@ static virHypervisorDriver qemuHypervisorDriver = { .domainBackupGetXMLDesc = qemuDomainBackupGetXMLDesc, /* 6.0.0 */ .domainHotpatchManage = qemuDomainHotpatchManage, /* 6.2.0 */ .domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 6.2.0 */ + .tmmGetMemoryInfo = qemuTmmGetMemoryInfo, /* 6.2.0 */ };
diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c index 0bbcc05..7e54f86 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -7268,6 +7268,29 @@ remoteDispatchNetworkPortGetParameters(virNetServerPtr server G_GNUC_UNUSED, return rv; }
+static int +remoteDispatchTmmGetMemoryInfo(virNetServerPtr server G_GNUC_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg G_GNUC_UNUSED, + virNetMessageErrorPtr rerr, + remote_tmm_get_memory_info_args *args, + remote_tmm_get_memory_info_ret *ret) +{ + int rv = -1; + char *meminfo = NULL; + virConnectPtr conn = remoteGetHypervisorConn(client); + + if (conn && (meminfo = virTmmGetMemoryInfo(conn, args->detail))) { + rv = 0; + ret->meminfo = meminfo; + } + + if (rv < 0) + virNetMessageSaveError(rerr); + + return rv; +} +
/*----- Helpers. -----*/
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 9c272b4..1237aa8 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8253,6 +8253,34 @@ remoteDomainGetGuestInfo(virDomainPtr dom, return rv; }
+static char * +remoteTmmGetMemoryInfo(virConnectPtr conn, + bool detail) +{ + char *rv = NULL; + struct private_data *priv = conn->privateData; + remote_tmm_get_memory_info_args args; + remote_tmm_get_memory_info_ret ret; + + remoteDriverLock(priv); + + args.detail = detail; + + memset(&ret, 0, sizeof(ret)); + + if (call(conn, priv, 0, REMOTE_PROC_TMM_GET_MEMORY_INFO, + (xdrproc_t)xdr_remote_tmm_get_memory_info_args, (char *)&args, + (xdrproc_t)xdr_remote_tmm_get_memory_info_ret, (char *)&ret) < 0) { + goto done; + } + + rv = ret.meminfo; + + done: + remoteDriverUnlock(priv); + return rv; +} + /* get_nonnull_domain and get_nonnull_network turn an on-wire * (name, uuid) pair into virDomainPtr or virNetworkPtr object. * These can return NULL if underlying memory allocations fail, @@ -8686,6 +8714,7 @@ static virHypervisorDriver hypervisor_driver = { .domainBackupGetXMLDesc = remoteDomainBackupGetXMLDesc, /* 6.0.0 */ .domainHotpatchManage = remoteDomainHotpatchManage, /* 6.2.0 */ .domainStartDirtyRateCalc = remoteDomainStartDirtyRateCalc, /* 6.2.0 */ + .tmmGetMemoryInfo = remoteTmmGetMemoryInfo /* 6.2.0 */ };
static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index d89cc1a..c47c9a0 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3789,6 +3789,14 @@ struct remote_domain_start_dirty_rate_calc_args { unsigned int flags; };
+struct remote_tmm_get_memory_info_args { + unsigned int detail; +}; + +struct remote_tmm_get_memory_info_ret { + remote_nonnull_string meminfo; +}; + /*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */ @@ -6698,5 +6706,11 @@ enum remote_procedure { * @generate: both * @acl: domain:read */ - REMOTE_PROC_DOMAIN_HOTPATCH_MANAGE = 800 + REMOTE_PROC_DOMAIN_HOTPATCH_MANAGE = 800, + + /** + * @generate: none + * @acl: connect:read + */ + REMOTE_PROC_TMM_GET_MEMORY_INFO = 900 }; diff --git a/tools/virsh-host.c b/tools/virsh-host.c index 67d5466..322134c 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -1799,6 +1799,99 @@ cmdHypervisorCPUBaseline(vshControl *ctl, return ret; }
+/* + * "securememinfo" command + */ + +static const vshCmdInfo info_tmm[] = { + {.name = "help", + .data = N_("Interaction with the tmm") + }, + {.name = "desc", + .data = N_("Call the host kernel dev which is provided for virsh to use receiving tmm informations.") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_tmm[] = { + {.name = "dev", + .type = VSH_OT_DATA, + .flags = VSH_OFLAG_REQ, + .help = N_("Device name of host kernel dev") + }, + {.name = "detail", + .type = VSH_OT_BOOL, + .help = N_("print detailed info if this option contained in cmd") + }, + {.name = NULL} +}; + +static bool +virshGetTmmMemoryInfo(vshControl *ctl, + const vshCmd *cmd) +{ + char *tmmMemoryInfo = NULL; + bool detail; + virshControlPtr priv = ctl->privData; + + detail = vshCommandOptBool(cmd, "detail"); + if (!(tmmMemoryInfo = virTmmGetMemoryInfo(priv->conn, (unsigned int)detail))) { + vshError(ctl, _("Get tmm_memory_info failed")); + return false; + } + + vshPrintExtra(ctl, _("%s"), tmmMemoryInfo); + + VIR_FREE(tmmMemoryInfo); + return true; +} + +typedef bool +(*virshTmmFunc)(vshControl *ctl, + const vshCmd *cmd); + +struct _virshTmmFuncInfo { + const char *devName; + virshTmmFunc funcPtr; +}; + +typedef struct _virshTmmFuncInfo virshTmmFuncInfo; + +static virshTmmFuncInfo virshTmmFuncMap[] = { + {"tmm_memory_info", virshGetTmmMemoryInfo}, +}; + +static bool +virshTmmRunFunc(vshControl *ctl, + const char *devName, + const vshCmd *cmd) +{ + int funcIndex; + + for (funcIndex = 0; funcIndex < sizeof(virshTmmFuncMap) / sizeof(virshTmmFuncInfo); funcIndex++) { + if (strcmp(devName, virshTmmFuncMap[funcIndex].devName) == 0) { + virshTmmFuncMap[funcIndex].funcPtr(ctl, cmd); + return true; + } + } + + vshError(ctl, _("Invalid dev name")); + return false; +} + +static bool +cmdTmm(vshControl *ctl, const vshCmd *cmd) +{ + const char *devName = NULL; + + if (vshCommandOptStringReq(ctl, cmd, "dev", &devName) < 0) + return false; + + if (!virshTmmRunFunc(ctl, devName, cmd)) + return false; + + return true; +}
const vshCmdDef hostAndHypervisorCmds[] = { {.name = "allocpages", @@ -1927,5 +2020,11 @@ const vshCmdDef hostAndHypervisorCmds[] = { .info = info_version, .flags = 0 }, + {.name = "tmm", + .handler = cmdTmm, + .opts = opts_tmm, + .info = info_tmm, + .flags = 0 + }, {.name = NULL} };