COMP(read.time_running);
                /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
                if (read_format & PERF_FORMAT_GROUP) {
-                       for (i = 0; i < s1->read.group.nr; i++)
-                               MCOMP(read.group.values[i]);
+                       for (i = 0; i < s1->read.group.nr; i++) {
+                               /* FIXME: check values without LOST */
+                               if (read_format & PERF_FORMAT_LOST)
+                                       MCOMP(read.group.values[i]);
+                       }
                } else {
                        COMP(read.one.id);
+                       if (read_format & PERF_FORMAT_LOST)
+                               COMP(read.one.lost);
                }
        }
 
                        .data   = (void *)aux_data,
                },
        };
-       struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},};
+       struct sample_read_value values[] = {{1, 5, 0}, {9, 3, 0}, {2, 7, 0}, {6, 4, 1},};
        struct perf_sample sample_out, sample_out_endian;
        size_t i, sz, bufsz;
        int err, ret = -1;
        } else {
                sample.read.one.value = 0x08789faeb786aa87ULL;
                sample.read.one.id    = 99;
+               sample.read.one.lost  = 1;
        }
 
        sz = perf_event__sample_event_size(&sample, sample_type, read_format);
  */
 static int test__sample_parsing(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
 {
-       const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15};
+       const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 28, 29, 30, 31};
        u64 sample_type;
        u64 sample_regs;
        size_t i;
 
 
 struct sample_read_value {
        u64 value;
-       u64 id;
+       u64 id;   /* only if PERF_FORMAT_ID */
+       u64 lost; /* only if PERF_FORMAT_LOST */
 };
 
 struct sample_read {
        };
 };
 
+static inline size_t sample_read_value_size(u64 read_format)
+{
+       /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
+       if (read_format & PERF_FORMAT_LOST)
+               return sizeof(struct sample_read_value);
+       else
+               return offsetof(struct sample_read_value, lost);
+}
+
+static inline struct sample_read_value *
+next_sample_read_value(struct sample_read_value *v, u64 read_format)
+{
+       return (void *)v + sample_read_value_size(read_format);
+}
+
+#define sample_read_group__for_each(v, nr, rf)         \
+       for (int __i = 0; __i < (int)nr; v = next_sample_read_value(v, rf), __i++)
+
 struct ip_callchain {
        u64 nr;
        u64 ips[];
 
 }
 
 static void evsel__set_count(struct evsel *counter, int cpu_map_idx, int thread,
-                            u64 val, u64 ena, u64 run)
+                            u64 val, u64 ena, u64 run, u64 lost)
 {
        struct perf_counts_values *count;
 
        count->val    = val;
        count->ena    = ena;
        count->run    = run;
+       count->lost   = lost;
 
        perf_counts__set_loaded(counter->counts, cpu_map_idx, thread, true);
 }
 {
        u64 read_format = leader->core.attr.read_format;
        struct sample_read_value *v;
-       u64 nr, ena = 0, run = 0, i;
+       u64 nr, ena = 0, run = 0, lost = 0;
 
        nr = *data++;
 
        if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
                run = *data++;
 
-       v = (struct sample_read_value *) data;
-
-       evsel__set_count(leader, cpu_map_idx, thread, v[0].value, ena, run);
-
-       for (i = 1; i < nr; i++) {
+       v = (void *)data;
+       sample_read_group__for_each(v, nr, read_format) {
                struct evsel *counter;
 
-               counter = evlist__id2evsel(leader->evlist, v[i].id);
+               counter = evlist__id2evsel(leader->evlist, v->id);
                if (!counter)
                        return -EINVAL;
 
-               evsel__set_count(counter, cpu_map_idx, thread, v[i].value, ena, run);
+               if (read_format & PERF_FORMAT_LOST)
+                       lost = v->lost;
+
+               evsel__set_count(counter, cpu_map_idx, thread, v->value, ena, run, lost);
        }
 
        return 0;
 
                        if (data->read.group.nr > max_group_nr)
                                return -EFAULT;
-                       sz = data->read.group.nr *
-                            sizeof(struct sample_read_value);
+
+                       sz = data->read.group.nr * sample_read_value_size(read_format);
                        OVERFLOW_CHECK(array, sz, max_size);
                        data->read.group.values =
                                        (struct sample_read_value *)array;
                        OVERFLOW_CHECK_u64(array);
                        data->read.one.id = *array;
                        array++;
+
+                       if (read_format & PERF_FORMAT_LOST) {
+                               OVERFLOW_CHECK_u64(array);
+                               data->read.one.lost = *array;
+                               array++;
+                       }
                }
        }
 
 
        return pylist;
 }
 
-static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
+static PyObject *get_sample_value_as_tuple(struct sample_read_value *value,
+                                          u64 read_format)
 {
        PyObject *t;
 
-       t = PyTuple_New(2);
+       t = PyTuple_New(3);
        if (!t)
                Py_FatalError("couldn't create Python tuple");
        PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
        PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
+       if (read_format & PERF_FORMAT_LOST)
+               PyTuple_SetItem(t, 2, PyLong_FromUnsignedLongLong(value->lost));
+
        return t;
 }
 
                Py_FatalError("couldn't create Python list");
 
        if (read_format & PERF_FORMAT_GROUP) {
-               for (i = 0; i < sample->read.group.nr; i++) {
-                       PyObject *t = get_sample_value_as_tuple(&sample->read.group.values[i]);
+               struct sample_read_value *v = sample->read.group.values;
+
+               i = 0;
+               sample_read_group__for_each(v, sample->read.group.nr, read_format) {
+                       PyObject *t = get_sample_value_as_tuple(v, read_format);
                        PyList_SET_ITEM(values, i, t);
+                       i++;
                }
        } else {
-               PyObject *t = get_sample_value_as_tuple(&sample->read.one);
+               PyObject *t = get_sample_value_as_tuple(&sample->read.one,
+                                                       read_format);
                PyList_SET_ITEM(values, 0, t);
        }
        pydict_set_item_string_decref(dict_sample, "values", values);
 
                       sample->read.time_running);
 
        if (read_format & PERF_FORMAT_GROUP) {
-               u64 i;
+               struct sample_read_value *value = sample->read.group.values;
 
                printf(".... group nr %" PRIu64 "\n", sample->read.group.nr);
 
-               for (i = 0; i < sample->read.group.nr; i++) {
-                       struct sample_read_value *value;
-
-                       value = &sample->read.group.values[i];
+               sample_read_group__for_each(value, sample->read.group.nr, read_format) {
                        printf("..... id %016" PRIx64
-                              ", value %016" PRIx64 "\n",
+                              ", value %016" PRIx64,
                               value->id, value->value);
+                       if (read_format & PERF_FORMAT_LOST)
+                               printf(", lost %" PRIu64, value->lost);
+                       printf("\n");
                }
-       } else
-               printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n",
+       } else {
+               printf("..... id %016" PRIx64 ", value %016" PRIx64,
                        sample->read.one.id, sample->read.one.value);
+               if (read_format & PERF_FORMAT_LOST)
+                       printf(", lost %" PRIu64, sample->read.one.lost);
+               printf("\n");
+       }
 }
 
 static void dump_event(struct evlist *evlist, union perf_event *event,
 
        if (read_format & PERF_FORMAT_ID)
                printf("... id           : %" PRI_lu64 "\n", read_event->id);
+
+       if (read_format & PERF_FORMAT_LOST)
+               printf("... lost         : %" PRI_lu64 "\n", read_event->lost);
 }
 
 static struct machine *machines__find_for_cpumode(struct machines *machines,
                                struct perf_tool *tool,
                                union  perf_event *event,
                                struct perf_sample *sample,
-                               struct machine *machine)
+                               struct machine *machine,
+                               u64 read_format)
 {
        int ret = -EINVAL;
-       u64 i;
+       struct sample_read_value *v = sample->read.group.values;
 
-       for (i = 0; i < sample->read.group.nr; i++) {
-               ret = deliver_sample_value(evlist, tool, event, sample,
-                                          &sample->read.group.values[i],
+       sample_read_group__for_each(v, sample->read.group.nr, read_format) {
+               ret = deliver_sample_value(evlist, tool, event, sample, v,
                                           machine);
                if (ret)
                        break;
        /* For PERF_SAMPLE_READ we have either single or group mode. */
        if (read_format & PERF_FORMAT_GROUP)
                return deliver_sample_group(evlist, tool, event, sample,
-                                           machine);
+                                           machine, read_format);
        else
                return deliver_sample_value(evlist, tool, event, sample,
                                            &sample->read.one, machine);
 
                        result += sizeof(u64);
                /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
                if (read_format & PERF_FORMAT_GROUP) {
-                       sz = sample->read.group.nr *
-                            sizeof(struct sample_read_value);
-                       result += sz;
+                       sz = sample_read_value_size(read_format);
+                       result += sz * sample->read.group.nr;
                } else {
                        result += sizeof(u64);
+                       if (read_format & PERF_FORMAT_LOST)
+                               result += sizeof(u64);
                }
        }
 
        *array = data->weight;
 }
 
+static __u64 *copy_read_group_values(__u64 *array, __u64 read_format,
+                                    const struct perf_sample *sample)
+{
+       size_t sz = sample_read_value_size(read_format);
+       struct sample_read_value *v = sample->read.group.values;
+
+       sample_read_group__for_each(v, sample->read.group.nr, read_format) {
+               /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
+               memcpy(array, v, sz);
+               array = (void *)array + sz;
+       }
+       return array;
+}
+
 int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format,
                                  const struct perf_sample *sample)
 {
 
                /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
                if (read_format & PERF_FORMAT_GROUP) {
-                       sz = sample->read.group.nr *
-                            sizeof(struct sample_read_value);
-                       memcpy(array, sample->read.group.values, sz);
-                       array = (void *)array + sz;
+                       array = copy_read_group_values(array, read_format,
+                                                      sample);
                } else {
                        *array = sample->read.one.id;
                        array++;
+
+                       if (read_format & PERF_FORMAT_LOST) {
+                               *array = sample->read.one.lost;
+                               array++;
+                       }
                }
        }