int fixup_prog2[MAX_FIXUPS];
        int fixup_map_in_map[MAX_FIXUPS];
        int fixup_cgroup_storage[MAX_FIXUPS];
+       int fixup_percpu_cgroup_storage[MAX_FIXUPS];
        const char *errstr;
        const char *errstr_unpriv;
        uint32_t retval;
                .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
        },
        {
-               "invalid per-cgroup storage access 3",
+               "invalid cgroup storage access 3",
                .insns = {
                        BPF_MOV64_IMM(BPF_REG_2, 0),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
                .errstr = "get_local_storage() doesn't support non-zero flags",
                .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
        },
+       {
+               "valid per-cpu cgroup storage access",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_local_storage),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_percpu_cgroup_storage = { 1 },
+               .result = ACCEPT,
+               .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+       },
+       {
+               "invalid per-cpu cgroup storage access 1",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_local_storage),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map1 = { 1 },
+               .result = REJECT,
+               .errstr = "cannot pass map_type 1 into func bpf_get_local_storage",
+               .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+       },
+       {
+               "invalid per-cpu cgroup storage access 2",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_LD_MAP_FD(BPF_REG_1, 1),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_local_storage),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "fd 1 is not pointing to valid bpf_map",
+               .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+       },
+       {
+               "invalid per-cpu cgroup storage access 3",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_local_storage),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 256),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_percpu_cgroup_storage = { 1 },
+               .result = REJECT,
+               .errstr = "invalid access to map value, value_size=64 off=256 size=4",
+               .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+       },
+       {
+               "invalid per-cpu cgroup storage access 4",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_local_storage),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, -2),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_cgroup_storage = { 1 },
+               .result = REJECT,
+               .errstr = "invalid access to map value, value_size=64 off=-2 size=4",
+               .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+       },
+       {
+               "invalid per-cpu cgroup storage access 5",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_2, 7),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_local_storage),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_percpu_cgroup_storage = { 1 },
+               .result = REJECT,
+               .errstr = "get_local_storage() doesn't support non-zero flags",
+               .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+       },
+       {
+               "invalid per-cpu cgroup storage access 6",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_local_storage),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_percpu_cgroup_storage = { 1 },
+               .result = REJECT,
+               .errstr = "get_local_storage() doesn't support non-zero flags",
+               .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+       },
        {
                "multiple registers share map_lookup_elem result",
                .insns = {
        return outer_map_fd;
 }
 
-static int create_cgroup_storage(void)
+static int create_cgroup_storage(bool percpu)
 {
+       enum bpf_map_type type = percpu ? BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE :
+               BPF_MAP_TYPE_CGROUP_STORAGE;
        int fd;
 
-       fd = bpf_create_map(BPF_MAP_TYPE_CGROUP_STORAGE,
-                           sizeof(struct bpf_cgroup_storage_key),
+       fd = bpf_create_map(type, sizeof(struct bpf_cgroup_storage_key),
                            TEST_DATA_LEN, 0, 0);
        if (fd < 0)
-               printf("Failed to create array '%s'!\n", strerror(errno));
+               printf("Failed to create cgroup storage '%s'!\n",
+                      strerror(errno));
 
        return fd;
 }
        int *fixup_prog2 = test->fixup_prog2;
        int *fixup_map_in_map = test->fixup_map_in_map;
        int *fixup_cgroup_storage = test->fixup_cgroup_storage;
+       int *fixup_percpu_cgroup_storage = test->fixup_percpu_cgroup_storage;
 
        if (test->fill_helper)
                test->fill_helper(test);
        }
 
        if (*fixup_cgroup_storage) {
-               map_fds[7] = create_cgroup_storage();
+               map_fds[7] = create_cgroup_storage(false);
                do {
                        prog[*fixup_cgroup_storage].imm = map_fds[7];
                        fixup_cgroup_storage++;
                } while (*fixup_cgroup_storage);
        }
+
+       if (*fixup_percpu_cgroup_storage) {
+               map_fds[8] = create_cgroup_storage(true);
+               do {
+                       prog[*fixup_percpu_cgroup_storage].imm = map_fds[8];
+                       fixup_percpu_cgroup_storage++;
+               } while (*fixup_percpu_cgroup_storage);
+       }
 }
 
 static void do_test_single(struct bpf_test *test, bool unpriv,