staticstruct paicrypt_root { /* Anchor to per CPU data */
refcount_t refcnt; /* Overall active events */ struct paicrypt_mapptr __percpu *mapptr;
} paicrypt_root;
/* Free per CPU data when the last event is removed. */ staticvoid paicrypt_root_free(void)
{ if (refcount_dec_and_test(&paicrypt_root.refcnt)) {
free_percpu(paicrypt_root.mapptr);
paicrypt_root.mapptr = NULL;
}
debug_sprintf_event(cfm_dbg, 5, "%s root.refcount %d\n", __func__,
refcount_read(&paicrypt_root.refcnt));
}
/* *OninitializationoffirsteventalsoallocateperCPUdatadynamically. *Startwithanarrayofpointers,thearraysizeisthemaximumnumberof *CPUspossible,whichmightbelargerthanthenumberofCPUscurrently *online.
*/ staticint paicrypt_root_alloc(void)
{ if (!refcount_inc_not_zero(&paicrypt_root.refcnt)) { /* The memory is already zeroed. */
paicrypt_root.mapptr = alloc_percpu(struct paicrypt_mapptr); if (!paicrypt_root.mapptr) return -ENOMEM;
refcount_set(&paicrypt_root.refcnt, 1);
} return0;
}
/* Release the PMU if event is the last perf event */ static DEFINE_MUTEX(pai_reserve_mutex);
/* Adjust usage counters and remove allocated memory when all users are *gone.
*/ staticvoid paicrypt_event_destroy_cpu(struct perf_event *event, int cpu)
{ struct paicrypt_mapptr *mp = per_cpu_ptr(paicrypt_root.mapptr, cpu); struct paicrypt_map *cpump = mp->mapptr;
/* Might be called on different CPU than the one the event is intended for. */ staticint paicrypt_event_init(struct perf_event *event)
{ struct perf_event_attr *a = &event->attr; struct paicrypt_map *cpump; int rc = 0;
/* PAI crypto PMU registered as PERF_TYPE_RAW, check event type */ if (a->type != PERF_TYPE_RAW && event->pmu->type != a->type) return -ENOENT; /* PAI crypto event must be in valid range, try others if not */ if (a->config < PAI_CRYPTO_BASE ||
a->config > PAI_CRYPTO_BASE + paicrypt_cnt) return -ENOENT; /* Allow only CRYPTO_ALL for sampling */ if (a->sample_period && a->config != PAI_CRYPTO_BASE) return -EINVAL; /* Get a page to store last counter values for sampling */ if (a->sample_period) {
PAI_SAVE_AREA(event) = get_zeroed_page(GFP_KERNEL); if (!PAI_SAVE_AREA(event)) {
rc = -ENOMEM; goto out;
}
}
if (a->sample_period) {
a->sample_period = 1;
a->freq = 0; /* Register for paicrypt_sched_task() to be called */
event->attach_state |= PERF_ATTACH_SCHED_CB; /* Add raw data which contain the memory mapped counters */
a->sample_type |= PERF_SAMPLE_RAW; /* Turn off inheritance */
a->inherit = 0;
}
/* Create raw data and save it in buffer. Calculate the delta for each *counterbetweenthisinvocationandthelastinvocation. *Returnsnumberofbytescopied. *Savesonlyentrieswithpositivecounterdifferenceoftheform *2bytes:Numberofcounter *8bytes:Valueofcounter
*/ static size_t paicrypt_copy(struct pai_userdata *userdata, unsignedlong *page, unsignedlong *page_old, bool exclude_user, bool exclude_kernel)
{ int i, outidx = 0;
for (i = 1; i <= paicrypt_cnt; i++) {
u64 val = 0, val_old = 0;
if (!exclude_kernel) {
val += paicrypt_getctr(page, i, true);
val_old += paicrypt_getctr(page_old, i, true);
} if (!exclude_user) {
val += paicrypt_getctr(page, i, false);
val_old += paicrypt_getctr(page_old, i, false);
} if (val >= val_old)
val -= val_old; else
val = (~0ULL - val_old) + val + 1; if (val) {
userdata[outidx].num = i;
userdata[outidx].value = val;
outidx++;
}
} return outidx * sizeof(struct pai_userdata);
}
/* Check if there is data to be saved on schedule out of a task. */ staticvoid paicrypt_have_sample(struct perf_event *event, struct paicrypt_map *cpump)
{
size_t rawsize;
if (!event) /* No event active */ return;
rawsize = paicrypt_copy(cpump->save, cpump->page,
(unsignedlong *)PAI_SAVE_AREA(event),
event->attr.exclude_user,
event->attr.exclude_kernel); if (rawsize) /* No incremented counters */
paicrypt_push_sample(rawsize, cpump, event);
}
/* Check if there is data to be saved on schedule out of a task. */ staticvoid paicrypt_have_samples(void)
{ struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr); struct paicrypt_map *cpump = mp->mapptr; struct perf_event *event;
/* Called on schedule-in and schedule-out. No access to event structure, *butforsamplingonlyeventCRYPTO_ALLisallowed.
*/ staticvoid paicrypt_sched_task(struct perf_event_pmu_context *pmu_ctx, struct task_struct *task, bool sched_in)
{ /* We started with a clean page on event installation. So read out *resultsonschedule_outandifpagewasdirty,saveoldvalues.
*/ if (!sched_in)
paicrypt_have_samples();
}
/* Attribute definitions for paicrypt interface. As with other CPU *MeasurementFacilities,thereisoneattributepermappedcounter. *Thenumberofmappedcountersmayvarypermachinegeneration.Use *theQUERYPROCESSORACTIVITYCOUNTERINFORMATION(QPACI)instruction *todeterminethenumberofmappedcounters.Theinstructionsreturns *apositivenumber,whichisthehighestnumberofsupportedcounters. *Allcounterslessthanthisnumberarealsosupported,thereareno *holes.Areturnednumberofzeromeansnosupportformappedcounters. * *Theidentificationofthecounterisauniquenumber.Thechosenrange *is0x1000+offsetinmappedkernelpage. *AllCPUMeasurementFacilitycountersidentifiersmustbeuniqueand *thenumbersfrom0to496arealreadyusedfortheCPUMeasurement *Counterfacility.Numbers0xb0000,0xbc000and0xbd000arealready *usedfortheCPUMeasurementSamplingfacility.
*/
PMU_FORMAT_ATTR(event, "config:0-63");
rc = perf_pmu_register(&paicrypt, "pai_crypto", -1); if (rc) {
pr_err("Registering the pai_crypto PMU failed with rc=%i\n",
rc);
debug_unregister_view(cfm_dbg, &debug_sprintf_view);
debug_unregister(cfm_dbg); return rc;
} return0;
}
device_initcall(paicrypt_init);
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.18Bemerkung:
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.