diff mbox

[for-next,7/9] coverage: introduce support for llvm profiling

Message ID 20171026091938.59247-8-roger.pau@citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

Roger Pau Monné Oct. 26, 2017, 9:19 a.m. UTC
Introduce the functionality in order to fill the hooks of the
cov_sysctl_ops struct.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Wei Liu <wei.liu2@citrix.com>
Cc: llvm-dev@lists.llvm.org
---
Note that the file that contains the helpers is under a BSD 2-clause
license. This is done so it can be shared with other OSes that use the
llvm/clang compiler.
---
 xen/common/coverage/Makefile |   2 +-
 xen/common/coverage/llvm.c   | 148 +++++++++++++++++++++++++++++++++++++++++++
 xen/include/public/sysctl.h  |   6 ++
 3 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 xen/common/coverage/llvm.c

Comments

Wei Liu Oct. 30, 2017, 4:48 p.m. UTC | #1
On Thu, Oct 26, 2017 at 10:19:36AM +0100, Roger Pau Monne wrote:
> Introduce the functionality in order to fill the hooks of the
> cov_sysctl_ops struct.
> 
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
> ---
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> Cc: George Dunlap <George.Dunlap@eu.citrix.com>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Tim Deegan <tim@xen.org>
> Cc: Wei Liu <wei.liu2@citrix.com>
> Cc: llvm-dev@lists.llvm.org
> ---
> Note that the file that contains the helpers is under a BSD 2-clause
> license. This is done so it can be shared with other OSes that use the
> llvm/clang compiler.

It would be helpful if you can put a reference to the original code
somewhere, either in commit message or in the comment section of the
file.

> ---
>  xen/common/coverage/Makefile |   2 +-
>  xen/common/coverage/llvm.c   | 148 +++++++++++++++++++++++++++++++++++++++++++
>  xen/include/public/sysctl.h  |   6 ++
>  3 files changed, 155 insertions(+), 1 deletion(-)
>  create mode 100644 xen/common/coverage/llvm.c
> 
> diff --git a/xen/common/coverage/Makefile b/xen/common/coverage/Makefile
> index e4541a1233..f2ffb2b8de 100644
> --- a/xen/common/coverage/Makefile
> +++ b/xen/common/coverage/Makefile
> @@ -11,5 +11,5 @@ obj-$(CONFIG_GCOV_FORMAT_AUTODETECT) += $(call cc-ifversion,lt,0x040700, \
>  						gcc_4_9.o, $(call cc-ifversion,lt,0x070000, \
>  						gcc_5.o, gcc_7.o))))
>  else
> -obj-y += coverage.o
> +obj-y += llvm.o coverage.o
>  endif
> diff --git a/xen/common/coverage/llvm.c b/xen/common/coverage/llvm.c
> new file mode 100644
> index 0000000000..c8905070a3
> --- /dev/null
> +++ b/xen/common/coverage/llvm.c
> +#include <xen/errno.h>
> +#include <xen/guest_access.h>
> +#include <xen/types.h>
> +#include <xen/coverage.h>
> +

Order.
Jan Beulich Nov. 8, 2017, 8:38 a.m. UTC | #2
>>> On 26.10.17 at 11:19, <roger.pau@citrix.com> wrote:
> --- /dev/null
> +++ b/xen/common/coverage/llvm.c
> @@ -0,0 +1,148 @@
> +/*
> + * Copyright (C) 2017 Citrix Systems R&D
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <xen/errno.h>
> +#include <xen/guest_access.h>
> +#include <xen/types.h>
> +#include <xen/coverage.h>
> +
> +#ifndef __clang__
> +#error "LLVM coverage selected without clang compiler"
> +#endif
> +
> +#define LLVM_PROFILE_MAGIC_64 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \
> +       (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 |  \
> +        (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129
> +#define LLVM_PROFILE_MAGIC_32 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \
> +       (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 |  \
> +        (uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129

Judging by the file having Xen style, I imply this isn't intended to
very closely match some other original. With that, parentheses
should be added around all the shift operations above.

> +#if __clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ == 9)

Is it certain that there's never going to be a 3.10? Otherwise
>= might be more suitable for the minor version check.

> +int __llvm_profile_runtime;

This isn't used anywhere - please add a brief comment explaining
the need for it (the more that its type being plain int is also
suspicious).

> +extern struct llvm_profile_data __start___llvm_prf_data;
> +extern struct llvm_profile_data __stop___llvm_prf_data;
> +extern uint64_t __start___llvm_prf_cnts;
> +extern uint64_t __stop___llvm_prf_cnts;
> +extern char __start___llvm_prf_names;
> +extern char __stop___llvm_prf_names;

I guess all of these really want to have [] added, making ...

> +static void *start_data = &__start___llvm_prf_data;
> +static void *end_data = &__stop___llvm_prf_data;
> +static void *start_counters = &__start___llvm_prf_cnts;
> +static void *end_counters = &__stop___llvm_prf_cnts;
> +static void *start_names = &__start___llvm_prf_names;
> +static void *end_names = &__stop___llvm_prf_names;

... the &s here unnecessary. But then - do these really need to
be statics (rather than #define-s)?

I would also guess that at least the names ones could be const.

> +static int dump(XEN_GUEST_HANDLE_PARAM(char) buffer, uint32_t *buf_size)
> +{
> +    struct llvm_profile_header header = {
> +#if BITS_PER_LONG == 64
> +        .magic = LLVM_PROFILE_MAGIC_64,
> +#else
> +        .magic = LLVM_PROFILE_MAGIC_32,
> +#endif

I think this should just be LLVM_PROFILE_MAGIC, with the #ifdef
moved to the #define-s.

> +        .version = LLVM_PROFILE_VERSION,
> +        .data_size = (end_data - start_data) / sizeof(struct llvm_profile_data),
> +        .counters_size = (end_counters - start_counters) / sizeof(uint64_t),
> +        .names_size = end_names - start_names,
> +        .counters_delta = (uintptr_t)start_counters,
> +        .names_delta = (uintptr_t)start_names,
> +        .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1,
> +    };
> +    unsigned int off = 0;
> +
> +#define APPEND_TO_BUFFER(src, size)                     \
> +({                                                      \
> +    if ( off + size > *buf_size )                       \

(size)

> +        return -ENOMEM;                                 \
> +    copy_to_guest_offset(buffer, off, src, size);       \
> +    off += size;                                        \

Ideally here too, albeit only the comma operator has lower
precedence, and that would require parenthesizing in the macro
invocation already (which is also why the arguments to
copy_to_guest_offset() explicitly do not need extra parentheses
added).

> +})
> +    APPEND_TO_BUFFER((char *)&header, sizeof(struct llvm_profile_header));

sizeof(header)

> +    APPEND_TO_BUFFER((char *)start_data, end_data - start_data);
> +    APPEND_TO_BUFFER((char *)start_counters, end_counters - start_counters);
> +    APPEND_TO_BUFFER((char *)start_names, end_names - start_names);

The casts should all be to const char*, and perhaps that would
better be done inside the macro anyway.

> +#undef APPEND_TO_BUFFER
> +
> +    clear_guest_offset(buffer, off, *buf_size - off);
> +
> +    return 0;
> +}
> +
> +struct cov_sysctl_ops cov_ops = {

const

> --- a/xen/include/public/sysctl.h
> +++ b/xen/include/public/sysctl.h
> @@ -646,6 +646,12 @@ struct xen_sysctl_scheduler_op {
>  
>  #define XEN_GCOV_FORMAT_MAGIC    0x58434f56 /* XCOV */

Hmm, shouldn't the private magic #define-s actually be put here
(in which case you'd indeed need to retain both 32- and 64-bit
variants)?

Jan
Roger Pau Monné Nov. 8, 2017, 8:56 a.m. UTC | #3
On Wed, Nov 08, 2017 at 01:38:59AM -0700, Jan Beulich wrote:
> >>> On 26.10.17 at 11:19, <roger.pau@citrix.com> wrote:
> > --- /dev/null
> > +++ b/xen/common/coverage/llvm.c
> > +#define LLVM_PROFILE_MAGIC_64 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \
> > +       (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 |  \
> > +        (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129
> > +#define LLVM_PROFILE_MAGIC_32 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \
> > +       (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 |  \
> > +        (uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
> 
> Judging by the file having Xen style, I imply this isn't intended to
> very closely match some other original. With that, parentheses
> should be added around all the shift operations above.
> 
> > +#if __clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ == 9)
> 
> Is it certain that there's never going to be a 3.10? Otherwise
> >= might be more suitable for the minor version check.

No, there's not going to be a clang 3.10.

> > +int __llvm_profile_runtime;
> 
> This isn't used anywhere - please add a brief comment explaining
> the need for it (the more that its type being plain int is also
> suspicious).

This is an internal symbol that must be present because Xen is not
linked against the run-time coverage library. It's described as an int
here:

https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#using-the-profiling-runtime-without-static-initializers

Without this symbol linkage fails.

> > +extern struct llvm_profile_data __start___llvm_prf_data;
> > +extern struct llvm_profile_data __stop___llvm_prf_data;
> > +extern uint64_t __start___llvm_prf_cnts;
> > +extern uint64_t __stop___llvm_prf_cnts;
> > +extern char __start___llvm_prf_names;
> > +extern char __stop___llvm_prf_names;
> 
> I guess all of these really want to have [] added, making ...
> 
> > +static void *start_data = &__start___llvm_prf_data;
> > +static void *end_data = &__stop___llvm_prf_data;
> > +static void *start_counters = &__start___llvm_prf_cnts;
> > +static void *end_counters = &__stop___llvm_prf_cnts;
> > +static void *start_names = &__start___llvm_prf_names;
> > +static void *end_names = &__stop___llvm_prf_names;
> 
> ... the &s here unnecessary. But then - do these really need to
> be statics (rather than #define-s)?
> 
> I would also guess that at least the names ones could be const.

Could make them defines indeed.

> > +    APPEND_TO_BUFFER((char *)start_data, end_data - start_data);
> > +    APPEND_TO_BUFFER((char *)start_counters, end_counters - start_counters);
> > +    APPEND_TO_BUFFER((char *)start_names, end_names - start_names);
> 
> The casts should all be to const char*, and perhaps that would
> better be done inside the macro anyway.

Seems better indeed.

> > --- a/xen/include/public/sysctl.h
> > +++ b/xen/include/public/sysctl.h
> > @@ -646,6 +646,12 @@ struct xen_sysctl_scheduler_op {
> >  
> >  #define XEN_GCOV_FORMAT_MAGIC    0x58434f56 /* XCOV */
> 
> Hmm, shouldn't the private magic #define-s actually be put here
> (in which case you'd indeed need to retain both 32- and 64-bit
> variants)?

I don't think so, here XEN_GCOV_FORMAT_MAGIC is a Xen specific gcov
magic number.

OTOH LLVM_PROFILE_MAGIC_{64/32} is an llvm defined magic number,
that's not under our control. Hence I don't think it should be
exported in Xen public headers.

Roger.
Jan Beulich Nov. 8, 2017, 11:08 a.m. UTC | #4
>>> On 08.11.17 at 09:56, <roger.pau@citrix.com> wrote:
> On Wed, Nov 08, 2017 at 01:38:59AM -0700, Jan Beulich wrote:
>> >>> On 26.10.17 at 11:19, <roger.pau@citrix.com> wrote:
>> > --- a/xen/include/public/sysctl.h
>> > +++ b/xen/include/public/sysctl.h
>> > @@ -646,6 +646,12 @@ struct xen_sysctl_scheduler_op {
>> >  
>> >  #define XEN_GCOV_FORMAT_MAGIC    0x58434f56 /* XCOV */
>> 
>> Hmm, shouldn't the private magic #define-s actually be put here
>> (in which case you'd indeed need to retain both 32- and 64-bit
>> variants)?
> 
> I don't think so, here XEN_GCOV_FORMAT_MAGIC is a Xen specific gcov
> magic number.
> 
> OTOH LLVM_PROFILE_MAGIC_{64/32} is an llvm defined magic number,
> that's not under our control. Hence I don't think it should be
> exported in Xen public headers.

Okay.

Jan
Vedant Kumar Nov. 9, 2017, 6:04 a.m. UTC | #5
- llvm-dev, since the code review can continue without that audience.

vedant

> On Nov 8, 2017, at 3:08 AM, Jan Beulich via llvm-dev <llvm-dev@lists.llvm.org> wrote:
> 
>>>> On 08.11.17 at 09:56, <roger.pau@citrix.com> wrote:
>> On Wed, Nov 08, 2017 at 01:38:59AM -0700, Jan Beulich wrote:
>>>>>> On 26.10.17 at 11:19, <roger.pau@citrix.com> wrote:
>>>> --- a/xen/include/public/sysctl.h
>>>> +++ b/xen/include/public/sysctl.h
>>>> @@ -646,6 +646,12 @@ struct xen_sysctl_scheduler_op {
>>>> 
>>>> #define XEN_GCOV_FORMAT_MAGIC    0x58434f56 /* XCOV */
>>> 
>>> Hmm, shouldn't the private magic #define-s actually be put here
>>> (in which case you'd indeed need to retain both 32- and 64-bit
>>> variants)?
>> 
>> I don't think so, here XEN_GCOV_FORMAT_MAGIC is a Xen specific gcov
>> magic number.
>> 
>> OTOH LLVM_PROFILE_MAGIC_{64/32} is an llvm defined magic number,
>> that's not under our control. Hence I don't think it should be
>> exported in Xen public headers.
> 
> Okay.
> 
> Jan
> 
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
diff mbox

Patch

diff --git a/xen/common/coverage/Makefile b/xen/common/coverage/Makefile
index e4541a1233..f2ffb2b8de 100644
--- a/xen/common/coverage/Makefile
+++ b/xen/common/coverage/Makefile
@@ -11,5 +11,5 @@  obj-$(CONFIG_GCOV_FORMAT_AUTODETECT) += $(call cc-ifversion,lt,0x040700, \
 						gcc_4_9.o, $(call cc-ifversion,lt,0x070000, \
 						gcc_5.o, gcc_7.o))))
 else
-obj-y += coverage.o
+obj-y += llvm.o coverage.o
 endif
diff --git a/xen/common/coverage/llvm.c b/xen/common/coverage/llvm.c
new file mode 100644
index 0000000000..c8905070a3
--- /dev/null
+++ b/xen/common/coverage/llvm.c
@@ -0,0 +1,148 @@ 
+/*
+ * Copyright (C) 2017 Citrix Systems R&D
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <xen/errno.h>
+#include <xen/guest_access.h>
+#include <xen/types.h>
+#include <xen/coverage.h>
+
+#ifndef __clang__
+#error "LLVM coverage selected without clang compiler"
+#endif
+
+#define LLVM_PROFILE_MAGIC_64 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \
+       (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 |  \
+        (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129
+#define LLVM_PROFILE_MAGIC_32 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \
+       (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 |  \
+        (uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
+
+#if __clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ == 9)
+#define LLVM_PROFILE_VERSION    4
+#define LLVM_PROFILE_NUM_KINDS  2
+#else
+#error "clang version not supported with coverage"
+#endif
+
+struct llvm_profile_data {
+    uint64_t name_ref;
+    uint64_t function_hash;
+    void *counter;
+    void *function;
+    void *values;
+    uint32_t nr_counters;
+    uint16_t nr_value_sites[LLVM_PROFILE_NUM_KINDS];
+};
+
+struct llvm_profile_header {
+    uint64_t magic;
+    uint64_t version;
+    uint64_t data_size;
+    uint64_t counters_size;
+    uint64_t names_size;
+    uint64_t counters_delta;
+    uint64_t names_delta;
+    uint64_t value_kind_last;
+};
+
+int __llvm_profile_runtime;
+
+extern struct llvm_profile_data __start___llvm_prf_data;
+extern struct llvm_profile_data __stop___llvm_prf_data;
+extern uint64_t __start___llvm_prf_cnts;
+extern uint64_t __stop___llvm_prf_cnts;
+extern char __start___llvm_prf_names;
+extern char __stop___llvm_prf_names;
+
+static void *start_data = &__start___llvm_prf_data;
+static void *end_data = &__stop___llvm_prf_data;
+static void *start_counters = &__start___llvm_prf_cnts;
+static void *end_counters = &__stop___llvm_prf_cnts;
+static void *start_names = &__start___llvm_prf_names;
+static void *end_names = &__stop___llvm_prf_names;
+
+static void reset_counters(void)
+{
+    memset(start_counters, 0, end_counters - start_counters);
+}
+
+static uint32_t get_size(void)
+{
+    return ROUNDUP(sizeof(struct llvm_profile_header) + end_data - start_data +
+                   end_counters - start_counters + end_names - start_names, 8);
+}
+
+static int dump(XEN_GUEST_HANDLE_PARAM(char) buffer, uint32_t *buf_size)
+{
+    struct llvm_profile_header header = {
+#if BITS_PER_LONG == 64
+        .magic = LLVM_PROFILE_MAGIC_64,
+#else
+        .magic = LLVM_PROFILE_MAGIC_32,
+#endif
+        .version = LLVM_PROFILE_VERSION,
+        .data_size = (end_data - start_data) / sizeof(struct llvm_profile_data),
+        .counters_size = (end_counters - start_counters) / sizeof(uint64_t),
+        .names_size = end_names - start_names,
+        .counters_delta = (uintptr_t)start_counters,
+        .names_delta = (uintptr_t)start_names,
+        .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1,
+    };
+    unsigned int off = 0;
+
+#define APPEND_TO_BUFFER(src, size)                     \
+({                                                      \
+    if ( off + size > *buf_size )                       \
+        return -ENOMEM;                                 \
+    copy_to_guest_offset(buffer, off, src, size);       \
+    off += size;                                        \
+})
+    APPEND_TO_BUFFER((char *)&header, sizeof(struct llvm_profile_header));
+    APPEND_TO_BUFFER((char *)start_data, end_data - start_data);
+    APPEND_TO_BUFFER((char *)start_counters, end_counters - start_counters);
+    APPEND_TO_BUFFER((char *)start_names, end_names - start_names);
+#undef APPEND_TO_BUFFER
+
+    clear_guest_offset(buffer, off, *buf_size - off);
+
+    return 0;
+}
+
+struct cov_sysctl_ops cov_ops = {
+    .get_size = get_size,
+    .reset_counters = reset_counters,
+    .dump = dump,
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 654b37cdce..62824b18f2 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -646,6 +646,12 @@  struct xen_sysctl_scheduler_op {
 
 #define XEN_GCOV_FORMAT_MAGIC    0x58434f56 /* XCOV */
 
+/*
+ * Ouput format of LLVM coverage data is just a raw stream, as would be
+ * written by the compiler_rt run time library into a .profraw file. There
+ * are no special Xen tags or delimiters because none are needed.
+ */
+
 #define XEN_SYSCTL_COV_get_size 0 /* Get total size of output data */
 #define XEN_SYSCTL_COV_read     1 /* Read output data */
 #define XEN_SYSCTL_COV_reset    2 /* Reset all counters */