/* If sampling all branches, there is nothing to filter */ if (((br_sel & X86_BR_ALL) == X86_BR_ALL) &&
((br_sel & X86_BR_TYPE_SAVE) != X86_BR_TYPE_SAVE))
fused_only = true;
for (i = 0; i < cpuc->lbr_stack.nr; i++) {
from = cpuc->lbr_entries[i].from;
to = cpuc->lbr_entries[i].to;
type = branch_type_fused(from, to, 0, &offset);
/* * Adjust the branch from address in case of instruction * fusion where it points to an instruction preceding the * actual branch
*/ if (offset) {
cpuc->lbr_entries[i].from += offset; if (fused_only) continue;
}
/* If type does not correspond, then discard */ if (type == X86_BR_NONE || (br_sel & type) != type) {
cpuc->lbr_entries[i].from = 0; /* mark invalid */
compress = true;
}
if ((br_sel & X86_BR_TYPE_SAVE) == X86_BR_TYPE_SAVE)
cpuc->lbr_entries[i].type = common_branch_type(type);
}
if (!compress) return;
/* Remove all invalid entries */ for (i = 0; i < cpuc->lbr_stack.nr; ) { if (!cpuc->lbr_entries[i].from) {
j = i; while (++j < cpuc->lbr_stack.nr)
cpuc->lbr_entries[j - 1] = cpuc->lbr_entries[j];
cpuc->lbr_stack.nr--; if (!cpuc->lbr_entries[i].from) continue;
}
i++;
}
}
for (i = 0; i < x86_pmu.lbr_nr; i++) {
entry.from.full = amd_pmu_lbr_get_from(i);
entry.to.full = amd_pmu_lbr_get_to(i);
/* * Check if a branch has been logged; if valid = 0, spec = 0 * then no branch was recorded; if reserved = 1 then an * erroneous branch was recorded (see Erratum 1452)
*/ if ((!entry.to.split.valid && !entry.to.split.spec) ||
entry.to.split.reserved) continue;
/* * Set branch speculation information using the status of * the valid and spec bits. * * When valid = 0, spec = 0, no branch was recorded and the * entry is discarded as seen above. * * When valid = 0, spec = 1, the recorded branch was * speculative but took the wrong path. * * When valid = 1, spec = 0, the recorded branch was * non-speculative but took the correct path. * * When valid = 1, spec = 1, the recorded branch was * speculative and took the correct path
*/
idx = (entry.to.split.valid << 1) | entry.to.split.spec;
br[out].spec = lbr_spec_map[idx];
out++;
}
cpuc->lbr_stack.nr = out;
/* * Internal register renaming always ensures that LBR From[0] and * LBR To[0] always represent the TOS
*/
cpuc->lbr_stack.hw_idx = 0;
/* Perform further software filtering */
amd_pmu_lbr_filter();
}
/* * A context switch can flip the address space and LBR entries are * not tagged with an identifier. Hence, branches cannot be resolved * from the old address space and the LBR records should be wiped.
*/ if (cpuc->lbr_users && sched_in)
amd_pmu_lbr_reset();
}
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.