enum bpf_map_op_type {
        BPF_MAP_OP_SET_VALUE,
+       BPF_MAP_OP_SET_EVSEL,
 };
 
 enum bpf_map_key_type {
        enum bpf_map_key_type key_type;
        union {
                u64 value;
+               struct perf_evsel *evsel;
        } v;
 };
 
        return 0;
 }
 
+static struct bpf_map_op *
+bpf_map__add_newop(struct bpf_map *map)
+{
+       struct bpf_map_op *op;
+       int err;
+
+       op = bpf_map_op__new();
+       if (IS_ERR(op))
+               return op;
+
+       err = bpf_map__add_op(map, op);
+       if (err) {
+               bpf_map_op__delete(op);
+               return ERR_PTR(err);
+       }
+       return op;
+}
+
 static int
 __bpf_map__config_value(struct bpf_map *map,
                        struct parse_events_term *term)
                return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUESIZE;
        }
 
-       op = bpf_map_op__new();
+       op = bpf_map__add_newop(map);
        if (IS_ERR(op))
                return PTR_ERR(op);
        op->op_type = BPF_MAP_OP_SET_VALUE;
        op->v.value = term->val.num;
-
-       err = bpf_map__add_op(map, op);
-       if (err)
-               bpf_map_op__delete(op);
-       return err;
+       return 0;
 }
 
 static int
        }
 
        if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM) {
-               pr_debug("ERROR: wrong value type\n");
+               pr_debug("ERROR: wrong value type for 'value'\n");
                return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE;
        }
 
        return __bpf_map__config_value(map, term);
 }
 
+static int
+__bpf_map__config_event(struct bpf_map *map,
+                       struct parse_events_term *term,
+                       struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel;
+       struct bpf_map_def def;
+       struct bpf_map_op *op;
+       const char *map_name;
+       int err;
+
+       map_name = bpf_map__get_name(map);
+       evsel = perf_evlist__find_evsel_by_str(evlist, term->val.str);
+       if (!evsel) {
+               pr_debug("Event (for '%s') '%s' doesn't exist\n",
+                        map_name, term->val.str);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT;
+       }
+
+       err = bpf_map__get_def(map, &def);
+       if (err) {
+               pr_debug("Unable to get map definition from '%s'\n",
+                        map_name);
+               return err;
+       }
+
+       /*
+        * No need to check key_size and value_size:
+        * kernel has already checked them.
+        */
+       if (def.type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) {
+               pr_debug("Map %s type is not BPF_MAP_TYPE_PERF_EVENT_ARRAY\n",
+                        map_name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
+       }
+
+       op = bpf_map__add_newop(map);
+       if (IS_ERR(op))
+               return PTR_ERR(op);
+       op->op_type = BPF_MAP_OP_SET_EVSEL;
+       op->v.evsel = evsel;
+       return 0;
+}
+
+static int
+bpf_map__config_event(struct bpf_map *map,
+                     struct parse_events_term *term,
+                     struct perf_evlist *evlist)
+{
+       if (!term->err_val) {
+               pr_debug("Config value not set\n");
+               return -BPF_LOADER_ERRNO__OBJCONF_CONF;
+       }
+
+       if (term->type_val != PARSE_EVENTS__TERM_TYPE_STR) {
+               pr_debug("ERROR: wrong value type for 'event'\n");
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE;
+       }
+
+       return __bpf_map__config_event(map, term, evlist);
+}
+
 struct bpf_obj_config__map_func {
        const char *config_opt;
        int (*config_func)(struct bpf_map *, struct parse_events_term *,
 
 struct bpf_obj_config__map_func bpf_obj_config__map_funcs[] = {
        {"value", bpf_map__config_value},
+       {"event", bpf_map__config_event},
 };
 
 static int
        list_for_each_entry(op, &priv->ops_list, list) {
                switch (def.type) {
                case BPF_MAP_TYPE_ARRAY:
+               case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
                        switch (op->key_type) {
                        case BPF_MAP_KEY_ALL:
                                err = foreach_key_array_all(func, arg, name,
        return err;
 }
 
+static int
+apply_config_evsel_for_key(const char *name, int map_fd, void *pkey,
+                          struct perf_evsel *evsel)
+{
+       struct xyarray *xy = evsel->fd;
+       struct perf_event_attr *attr;
+       unsigned int key, events;
+       bool check_pass = false;
+       int *evt_fd;
+       int err;
+
+       if (!xy) {
+               pr_debug("ERROR: evsel not ready for map %s\n", name);
+               return -BPF_LOADER_ERRNO__INTERNAL;
+       }
+
+       if (xy->row_size / xy->entry_size != 1) {
+               pr_debug("ERROR: Dimension of target event is incorrect for map %s\n",
+                        name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM;
+       }
+
+       attr = &evsel->attr;
+       if (attr->inherit) {
+               pr_debug("ERROR: Can't put inherit event into map %s\n", name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH;
+       }
+
+       if (attr->type == PERF_TYPE_RAW)
+               check_pass = true;
+       if (attr->type == PERF_TYPE_HARDWARE)
+               check_pass = true;
+       if (attr->type == PERF_TYPE_SOFTWARE &&
+                       attr->config == PERF_COUNT_SW_BPF_OUTPUT)
+               check_pass = true;
+       if (!check_pass) {
+               pr_debug("ERROR: Event type is wrong for map %s\n", name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE;
+       }
+
+       events = xy->entries / (xy->row_size / xy->entry_size);
+       key = *((unsigned int *)pkey);
+       if (key >= events) {
+               pr_debug("ERROR: there is no event %d for map %s\n",
+                        key, name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_MAPSIZE;
+       }
+       evt_fd = xyarray__entry(xy, key, 0);
+       err = bpf_map_update_elem(map_fd, pkey, evt_fd, BPF_ANY);
+       if (err && errno)
+               err = -errno;
+       return err;
+}
+
 static int
 apply_obj_config_map_for_key(const char *name, int map_fd,
                             struct bpf_map_def *pdef __maybe_unused,
                                                 pdef->value_size,
                                                 op->v.value);
                break;
+       case BPF_MAP_OP_SET_EVSEL:
+               err = apply_config_evsel_for_key(name, map_fd, pkey,
+                                                op->v.evsel);
+               break;
        default:
                pr_debug("ERROR: unknown value type for '%s'\n", name);
                err = -BPF_LOADER_ERRNO__INTERNAL;
        [ERRCODE_OFFSET(OBJCONF_MAP_TYPE)]      = "Incorrect map type",
        [ERRCODE_OFFSET(OBJCONF_MAP_KEYSIZE)]   = "Incorrect map key size",
        [ERRCODE_OFFSET(OBJCONF_MAP_VALUESIZE)] = "Incorrect map value size",
+       [ERRCODE_OFFSET(OBJCONF_MAP_NOEVT)]     = "Event not found for map setting",
+       [ERRCODE_OFFSET(OBJCONF_MAP_MAPSIZE)]   = "Invalid map size for event setting",
+       [ERRCODE_OFFSET(OBJCONF_MAP_EVTDIM)]    = "Event dimension too large",
+       [ERRCODE_OFFSET(OBJCONF_MAP_EVTINH)]    = "Doesn't support inherit event",
+       [ERRCODE_OFFSET(OBJCONF_MAP_EVTTYPE)]   = "Wrong event type for map",
 };
 
 static int
 int bpf__strerror_apply_obj_config(int err, char *buf, size_t size)
 {
        bpf__strerror_head(err, buf, size);
+       bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM,
+                           "Cannot set event to BPF map in multi-thread tracing");
+       bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH,
+                           "%s (Hint: use -i to turn off inherit)", emsg);
+       bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE,
+                           "Can only put raw, hardware and BPF output event into a BPF map");
        bpf__strerror_end(buf, size);
        return 0;
 }