[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [RFC PATCH v1 05/10] pmu.h: introduce a stacktrace area
On 25.07.2025 17:06, Edwin Török wrote: > The guest always allocates a full page that is mapped for 'struct > xen_pmu_data' (there is no smaller mapping granularity). > > The existing struct contains a flexible array member that is used to > store architectural performance counters on Intel (their number is > dynamically determined from CPUID). > > AFAICT their number is currently limited to 32 due to the bitmap in the > CPUID only having 32 bits defined for this, although the cpuid has 8 > bits reserved to specify the number of these counters, so this may grow. > > For backwards compatibility and to leave as much room for future growth > in these counters as possible: the newly introduced hypervisor > stacktrace area will be stored at the end of the page. > > Conceptually this would've been: > ``` > struct xen_pmu_data_v2 { > union { > struct xen_pmu_data v1; > uint8_t pad[PAGE_SIZE - sizeof(struct xen_pmu_hv_stacktrace)]; > }; > struct xen_pmu_hv_stacktrace pmu_stack; > }; > ``` > > But that is not valid C due to the flexible array member in v1. And I fear it's not a good interface anyway. What's wrong with the caller dedicating another page to holding the stack trace related data? > There is code duplication in 'struct xen_pmu_arch_guest', > but xlat.h checker fails if I try to reuse that in the definition of > xen_pmu_arch_t. What exactly is this referring to? > --- a/xen/include/public/arch-x86/pmu.h > +++ b/xen/include/public/arch-x86/pmu.h > @@ -74,6 +74,23 @@ DEFINE_XEN_GUEST_HANDLE(xen_pmu_regs_t); > #define PMU_SAMPLE_REAL (1<<2) /* Sample is from realmode */ > #define PMU_SAMPLE_PV (1<<3) /* Sample from a PV guest */ > > +/* > + * Architecture-specific information describing the state of the guest at > + * the time of a PMU interrupt. > + */ > +struct xen_pmu_arch_guest { > + union { > + /* > + * Processor's registers at the time of interrupt. > + * WO for hypervisor, RO for guests. > + */ > + xen_pmu_regs_t regs; How's this related to stack traces? > @@ -129,67 +146,86 @@ struct xen_pmu_arch { > typedef struct xen_pmu_arch xen_pmu_arch_t; > DEFINE_XEN_GUEST_HANDLE(xen_pmu_arch_t); > > + Stray double blank lines. > /* Memory layout: > -* ╭─────────────────────╮ > -* │ struct xen_pmu_data │ > -* ╒══════════════╧═════════════════════╧═══════════════════════╕ ◁╮ > -* │ vcpu_id │ │ > -* ├────────────────────────────────────────────────────────────┤ │ > -* │ pcpu_id │ │ > -* ├────────────────────────────────────────────────────────────┤ │ > -* │ domain_id │ │ > -* ├────────────────────────────────────────────────────────────┤ │ > -* │██pad███████████████████████████████████████████████████████│ │ > -* ╞════╤═╤═══╤══════════════════╤══════════════════════════════╡ │ > -* │ pmu│ │ r │ regs │██pad█████████████████████████│ │ > -* ├────╯ ├───╯ (xen or guest) │██████████████████████████████│ │ > -* │ ╞══════════════════════╧══════════════════════════════╡ │ > -* │ │ pmu_flags │ │ > -* │ ╞═══╤════════════════════╤════════════════════════════╡ │ > -* │ │ l │ lapic_lvtpc │████████████████████████████│ │ > -* │ ├───╯ ███████████████████│██pad███████████████████████│ │ > -* │ │ ███████████████████│████████████████████████████│ │ > -* │ ╞═══╤═╤═══════╤═════╤════╪════╤═══════╤═══════════════╡ │ > -* │ │ c │ │ │ amd │ │ │ intel │ │█████│ │ > -* │ ├───┘ │ ╰─────╯ │ ╰───────╯ │█████│ │ > -* │ │ │ counter │ fixed_counters │█████│ │ > -* │ │ ├──────────────────┼──────────────────────┤█████│ │ > -* │ │ │ ctrls │ arch_counters │█████│ │ > -* │ │ ╞═════╤════════╤═══├──────────────────────┤█████│ │ > -* │ │ │ │ regs[] │ ┆│ global_ctrl │█████│ │ > -* │ │ │ └────────╯ ┆├──────────────────────┤█████│ │ > -* │ │ │struct ┆│ global_ovf_ctrl │█████│ │ > -* │ │ │xen_pmu_cntr_pair┆├──────────────────────┤█████│ │ > -* │ │ │[counters] ┆│ global_status │█████│ │ > -* │ │ │ ┆├──────────────────────┤█████│ │ > -* │ │ │ ┆│ fixed_ctrl │█████│ │ > -* │ │ │ ┆├──────────────────────┤█████│ │ > -* │ │ │ ┆│ ds_area │█████│ │ > -* │ │ │ ┆├──────────────────────┤█████│ │ > -* │ │ │ ┆│ pebs_enable │█pad█│ │ > -* │ │ │ ┆├──────────────────────┤█████│ │ > -* │ │ │ ▽│ debugctl │█████│ │ > -* │ │ │██████████████████╞═══════╤════════╤═════╡█████│ │ > -* │ │ │██████████████████│ │ regs[] │ ┆[0]│█████│ │ > -* │ │ │██████████████████│ └────────╯ ┆ │█████│ │ > -* │ │ │██████████████████│ uint64_t ┆ │█████│ │ > -* │ │ │██████████████████│ [fixed_counters] ┆ │█████│ │ > -* │ │ │██████████████████│ ┆ │█████│ │ > -* │ │ │██████████████████│ ┆ │█████│ │ > -* │ │ │██████████████████│ ─────────────────┆ │█████│ │ > -* │ │ │██████████████████│ struct ┆ │█████│ │ > -* │ │ │██████████████████│ xen_pmu_cntr_pair┆ │█████│ │ > -* │ │ ╘══════════════════╡ [arch_counters] ┆ ╞═════╡ │ > -* │ │ │ ┆ │ │ │ > -* │ │ │ ▽ │ │ │ > -* │ │ ╘══════════════════════╛ │ │ > -* │ ╘═════════════════════════════════════════════════════╡ │ > -* ╞════════════════════════════════════════════════════════════╡ │ > -* │████████████████████████████████████████████████████████████│ │ > -* ┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆ ┆ > -* ┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆ ┆ > -* │████████████████████████████████████████████████████████████│ │ PAGE_SIZE > -* ╘════════════════════════════════════════════════════════════╛ ◁╯ > + * ╭─────────────────────╮ > + * │ struct xen_pmu_data │ > + * ╒══════════════╧═════════════════════╧═══════════════════════╕ ◁╮ > + * │ vcpu_id │ │ > + * ├────────────────────────────────────────────────────────────┤ │ > + * │ pcpu_id │ │ > + * ├────────────────────────────────────────────────────────────┤ │ > + * │ domain_id │ │ > + * ├────────────────────────────────────────────────────────────┤ │ > + * │██pad███████████████████████████████████████████████████████│ │ > + * ╞════╤═╤═══╤══════════════════╤══════════════════════════════╡ │ > + * │ pmu│ │ r │ regs │██pad█████████████████████████│ │ > + * ├────╯ ├───╯ (xen or guest) │██████████████████████████████│ │ > + * │ ╞══════════════════════╧══════════════════════════════╡ │ > + * │ │ pmu_flags │ │ > + * │ ╞═══╤════════════════════╤════════════════════════════╡ │ > + * │ │ l │ lapic_lvtpc │████████████████████████████│ │ > + * │ ├───╯ ███████████████████│██pad███████████████████████│ │ > + * │ │ ███████████████████│████████████████████████████│ │ > + * │ ╞═══╤═╤═══════╤═════╤════╪════╤═══════╤═══════════════╡ │ > + * │ │ c │ │ │ amd │ │ │ intel │ │█████│ │ > + * │ ├───┘ │ ╰─────╯ │ ╰───────╯ │█████│ │ > + * │ │ │ counter │ fixed_counters │█████│ │ > + * │ │ ├──────────────────┼──────────────────────┤█████│ │ > + * │ │ │ ctrls │ arch_counters │█████│ │ > + * │ │ ╞═════╤════════╤═══├──────────────────────┤█████│ │ > + * │ │ │ │ regs[] │ ┆│ global_ctrl │█████│ │ > + * │ │ │ └────────╯ ┆├──────────────────────┤█████│ │ > + * │ │ │struct ┆│ global_ovf_ctrl │█████│ │ > + * │ │ │xen_pmu_cntr_pair┆├──────────────────────┤█████│ │ > + * │ │ │[counters] ┆│ global_status │█████│ │ > + * │ │ │ ┆├──────────────────────┤█████│ │ > + * │ │ │ ┆│ fixed_ctrl │█████│ │ > + * │ │ │ ┆├──────────────────────┤█████│ │ > + * │ │ │ ┆│ ds_area │█████│ │ > + * │ │ │ ┆├──────────────────────┤█████│ │ > + * │ │ │ ┆│ pebs_enable │█pad█│ │ > + * │ │ │ ┆├──────────────────────┤█████│ │ > + * │ │ │ ▽│ debugctl │█████│ │ > + * │ │ │██████████████████╞═══════╤════════╤═════╡█████│ │ > + * │ │ │██████████████████│ │ regs[] │ ┆[0]│█████│ │ > + * │ │ │██████████████████│ └────────╯ ┆ │█████│ │ > + * │ │ │██████████████████│ uint64_t ┆ │█████│ │ > + * │ │ │██████████████████│ [fixed_counters] ┆ │█████│ │ > + * │ │ │██████████████████│ ┆ │█████│ │ > + * │ │ │██████████████████│ ┆ │█████│ │ > + * │ │ │██████████████████│ ─────────────────┆ │█████│ │ > + * │ │ │██████████████████│ struct ┆ │█████│ │ > + * │ │ │██████████████████│ xen_pmu_cntr_pair┆ │█████│ │ > + * │ │ ╘══════════════════╡ [arch_counters] ┆ ╞═════╡ │ > + * │ │ │ ┆ │ │ │ > + * │ │ │ ▽ │ │ │ > + * │ │ ╘══════════════════════╛ │ │ > + * │ ╘═════════════════════════════════════════════════════╡ │ > + * ╞════════════════════════════════════════════════════════════╡ │ > + * │████████████████████████████████████████████████████████████│ │ > + * ┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆ ┆ > + * ┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆┆ ┆ > + * │████████████████████████████████████████████████████████████│ │ > + * |############################################################| | > + * |##########.------------------------------.##################| | > + * |##########| struct xen_pmu_hv_stacktrace |##################| | > + * +==========+==============================+==================+ | > + * | ^ [stacktrace_nr-1] | | > + * | : | | > + * | stacktrace[stacktrace_nr] : [0] | | > + * +------------------------------------------------------------+ | > + * | stacktrace_nr | | > + * +------------------------------------------------------------+ | > + * | guest_domain_id | | > + * +------------------------------------------------------------+ | > + * |##pad#######################################################| | > + * +=======+=+===+==================+===========================+ | > + * | guest | | r | regs |##pad######################| | > + * +-------. +---. (xen or guest) |###########################| | > + * | +======================+===========================+ | > + * | |##pad2############################################| | > PAGE_SIZE > + * +=========+==================================================+ <. > */ > > #endif /* __XEN_PUBLIC_ARCH_X86_PMU_H__ */ > @@ -202,4 +238,3 @@ DEFINE_XEN_GUEST_HANDLE(xen_pmu_arch_t); > * indent-tabs-mode: nil > * End: > */ > - Stray change? > @@ -120,6 +120,40 @@ struct xen_pmu_data { > xen_pmu_arch_t pmu; > }; > > +/* stacktrace entry populated from the end, > + * so stacktrace_nr == 1, means that stacktrace[PMU_MAX_STACKTRCE-1] is > valid. > + * This is done, so that PMU_MAX_STACKTRACE can be changed in the future, > without breaking the ABI. > + * The struct itself (and thus the stacktrace_nr field) will always be > placed at the end of a page. > + * > + * See arch-x86/pmu.h for an example memory layout on x86. > + * > + * */ > +#define PMU_MAX_STACKTRACE 127 > + > +/* WO for hypervisor, RO for guest */ > +struct xen_pmu_hv_stacktrace { > + uint64_t stacktrace[PMU_MAX_STACKTRACE]; > + uint64_t stacktrace_nr; > + > + /* Like xen_pmu_data.domain_id, but instead of DOMID_XEN always contains > the > + * domain that was interrupted (DOMID_SELF if it matches the sampling > + * domain). > + */ > + domid_t guest_domain_id; How's this related to stack traces? And how would it help associating back what vCPU the data belongs to? > + uint8_t pad[6]; > + > + /* When xen_pmu_data.domain_id == DOMID_XEN, this will contain > + * the registers of the guest that was interrupted. > + * This is useful for Dom0 kernel stacktraces, even if the interrupt > + * arrives while in Xen. > + * */ Nit: Indentation. Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |