#define RV_REG_TCC RV_REG_A6
 #define RV_REG_TCC_SAVED RV_REG_S6 /* Store A6 in S6 if program do calls */
+#define RV_REG_ARENA RV_REG_S7 /* For storing arena_vm_start */
 
 static const int regmap[] = {
        [BPF_REG_0] =   RV_REG_A5,
                emit_ld(RV_REG_S6, store_offset, RV_REG_SP, ctx);
                store_offset -= 8;
        }
+       if (ctx->arena_vm_start) {
+               emit_ld(RV_REG_ARENA, store_offset, RV_REG_SP, ctx);
+               store_offset -= 8;
+       }
 
        emit_addi(RV_REG_SP, RV_REG_SP, stack_adjust, ctx);
        /* Set return value. */
 
 #define BPF_FIXUP_OFFSET_MASK   GENMASK(26, 0)
 #define BPF_FIXUP_REG_MASK      GENMASK(31, 27)
+#define REG_DONT_CLEAR_MARKER  0       /* RV_REG_ZERO unused in pt_regmap */
 
 bool ex_handler_bpf(const struct exception_table_entry *ex,
                    struct pt_regs *regs)
        off_t offset = FIELD_GET(BPF_FIXUP_OFFSET_MASK, ex->fixup);
        int regs_offset = FIELD_GET(BPF_FIXUP_REG_MASK, ex->fixup);
 
-       *(unsigned long *)((void *)regs + pt_regmap[regs_offset]) = 0;
+       if (regs_offset != REG_DONT_CLEAR_MARKER)
+               *(unsigned long *)((void *)regs + pt_regmap[regs_offset]) = 0;
        regs->epc = (unsigned long)&ex->fixup - offset;
 
        return true;
        off_t fixup_offset;
 
        if (!ctx->insns || !ctx->ro_insns || !ctx->prog->aux->extable ||
-           (BPF_MODE(insn->code) != BPF_PROBE_MEM && BPF_MODE(insn->code) != BPF_PROBE_MEMSX))
+           (BPF_MODE(insn->code) != BPF_PROBE_MEM && BPF_MODE(insn->code) != BPF_PROBE_MEMSX &&
+            BPF_MODE(insn->code) != BPF_PROBE_MEM32))
                return 0;
 
        if (WARN_ON_ONCE(ctx->nexentries >= ctx->prog->aux->num_exentries))
        case BPF_LDX | BPF_PROBE_MEMSX | BPF_B:
        case BPF_LDX | BPF_PROBE_MEMSX | BPF_H:
        case BPF_LDX | BPF_PROBE_MEMSX | BPF_W:
+       /* LDX | PROBE_MEM32: dst = *(unsigned size *)(src + RV_REG_ARENA + off) */
+       case BPF_LDX | BPF_PROBE_MEM32 | BPF_B:
+       case BPF_LDX | BPF_PROBE_MEM32 | BPF_H:
+       case BPF_LDX | BPF_PROBE_MEM32 | BPF_W:
+       case BPF_LDX | BPF_PROBE_MEM32 | BPF_DW:
        {
                int insn_len, insns_start;
                bool sign_ext;
                sign_ext = BPF_MODE(insn->code) == BPF_MEMSX ||
                           BPF_MODE(insn->code) == BPF_PROBE_MEMSX;
 
+               if (BPF_MODE(insn->code) == BPF_PROBE_MEM32) {
+                       emit_add(RV_REG_T2, rs, RV_REG_ARENA, ctx);
+                       rs = RV_REG_T2;
+               }
+
                switch (BPF_SIZE(code)) {
                case BPF_B:
                        if (is_12b_int(off)) {
                emit_sd(RV_REG_T2, 0, RV_REG_T1, ctx);
                break;
 
+       case BPF_ST | BPF_PROBE_MEM32 | BPF_B:
+       case BPF_ST | BPF_PROBE_MEM32 | BPF_H:
+       case BPF_ST | BPF_PROBE_MEM32 | BPF_W:
+       case BPF_ST | BPF_PROBE_MEM32 | BPF_DW:
+       {
+               int insn_len, insns_start;
+
+               emit_add(RV_REG_T3, rd, RV_REG_ARENA, ctx);
+               rd = RV_REG_T3;
+
+               /* Load imm to a register then store it */
+               emit_imm(RV_REG_T1, imm, ctx);
+
+               switch (BPF_SIZE(code)) {
+               case BPF_B:
+                       if (is_12b_int(off)) {
+                               insns_start = ctx->ninsns;
+                               emit(rv_sb(rd, off, RV_REG_T1), ctx);
+                               insn_len = ctx->ninsns - insns_start;
+                               break;
+                       }
+
+                       emit_imm(RV_REG_T2, off, ctx);
+                       emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
+                       insns_start = ctx->ninsns;
+                       emit(rv_sb(RV_REG_T2, 0, RV_REG_T1), ctx);
+                       insn_len = ctx->ninsns - insns_start;
+                       break;
+               case BPF_H:
+                       if (is_12b_int(off)) {
+                               insns_start = ctx->ninsns;
+                               emit(rv_sh(rd, off, RV_REG_T1), ctx);
+                               insn_len = ctx->ninsns - insns_start;
+                               break;
+                       }
+
+                       emit_imm(RV_REG_T2, off, ctx);
+                       emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
+                       insns_start = ctx->ninsns;
+                       emit(rv_sh(RV_REG_T2, 0, RV_REG_T1), ctx);
+                       insn_len = ctx->ninsns - insns_start;
+                       break;
+               case BPF_W:
+                       if (is_12b_int(off)) {
+                               insns_start = ctx->ninsns;
+                               emit_sw(rd, off, RV_REG_T1, ctx);
+                               insn_len = ctx->ninsns - insns_start;
+                               break;
+                       }
+
+                       emit_imm(RV_REG_T2, off, ctx);
+                       emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
+                       insns_start = ctx->ninsns;
+                       emit_sw(RV_REG_T2, 0, RV_REG_T1, ctx);
+                       insn_len = ctx->ninsns - insns_start;
+                       break;
+               case BPF_DW:
+                       if (is_12b_int(off)) {
+                               insns_start = ctx->ninsns;
+                               emit_sd(rd, off, RV_REG_T1, ctx);
+                               insn_len = ctx->ninsns - insns_start;
+                               break;
+                       }
+
+                       emit_imm(RV_REG_T2, off, ctx);
+                       emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
+                       insns_start = ctx->ninsns;
+                       emit_sd(RV_REG_T2, 0, RV_REG_T1, ctx);
+                       insn_len = ctx->ninsns - insns_start;
+                       break;
+               }
+
+               ret = add_exception_handler(insn, ctx, REG_DONT_CLEAR_MARKER,
+                                           insn_len);
+               if (ret)
+                       return ret;
+
+               break;
+       }
+
        /* STX: *(size *)(dst + off) = src */
        case BPF_STX | BPF_MEM | BPF_B:
                if (is_12b_int(off)) {
                emit_atomic(rd, rs, off, imm,
                            BPF_SIZE(code) == BPF_DW, ctx);
                break;
+
+       case BPF_STX | BPF_PROBE_MEM32 | BPF_B:
+       case BPF_STX | BPF_PROBE_MEM32 | BPF_H:
+       case BPF_STX | BPF_PROBE_MEM32 | BPF_W:
+       case BPF_STX | BPF_PROBE_MEM32 | BPF_DW:
+       {
+               int insn_len, insns_start;
+
+               emit_add(RV_REG_T2, rd, RV_REG_ARENA, ctx);
+               rd = RV_REG_T2;
+
+               switch (BPF_SIZE(code)) {
+               case BPF_B:
+                       if (is_12b_int(off)) {
+                               insns_start = ctx->ninsns;
+                               emit(rv_sb(rd, off, rs), ctx);
+                               insn_len = ctx->ninsns - insns_start;
+                               break;
+                       }
+
+                       emit_imm(RV_REG_T1, off, ctx);
+                       emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+                       insns_start = ctx->ninsns;
+                       emit(rv_sb(RV_REG_T1, 0, rs), ctx);
+                       insn_len = ctx->ninsns - insns_start;
+                       break;
+               case BPF_H:
+                       if (is_12b_int(off)) {
+                               insns_start = ctx->ninsns;
+                               emit(rv_sh(rd, off, rs), ctx);
+                               insn_len = ctx->ninsns - insns_start;
+                               break;
+                       }
+
+                       emit_imm(RV_REG_T1, off, ctx);
+                       emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+                       insns_start = ctx->ninsns;
+                       emit(rv_sh(RV_REG_T1, 0, rs), ctx);
+                       insn_len = ctx->ninsns - insns_start;
+                       break;
+               case BPF_W:
+                       if (is_12b_int(off)) {
+                               insns_start = ctx->ninsns;
+                               emit_sw(rd, off, rs, ctx);
+                               insn_len = ctx->ninsns - insns_start;
+                               break;
+                       }
+
+                       emit_imm(RV_REG_T1, off, ctx);
+                       emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+                       insns_start = ctx->ninsns;
+                       emit_sw(RV_REG_T1, 0, rs, ctx);
+                       insn_len = ctx->ninsns - insns_start;
+                       break;
+               case BPF_DW:
+                       if (is_12b_int(off)) {
+                               insns_start = ctx->ninsns;
+                               emit_sd(rd, off, rs, ctx);
+                               insn_len = ctx->ninsns - insns_start;
+                               break;
+                       }
+
+                       emit_imm(RV_REG_T1, off, ctx);
+                       emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+                       insns_start = ctx->ninsns;
+                       emit_sd(RV_REG_T1, 0, rs, ctx);
+                       insn_len = ctx->ninsns - insns_start;
+                       break;
+               }
+
+               ret = add_exception_handler(insn, ctx, REG_DONT_CLEAR_MARKER,
+                                           insn_len);
+               if (ret)
+                       return ret;
+
+               break;
+       }
+
        default:
                pr_err("bpf-jit: unknown opcode %02x\n", code);
                return -EINVAL;
                stack_adjust += 8;
        if (seen_reg(RV_REG_S6, ctx))
                stack_adjust += 8;
+       if (ctx->arena_vm_start)
+               stack_adjust += 8;
 
        stack_adjust = round_up(stack_adjust, 16);
        stack_adjust += bpf_stack_adjust;
                emit_sd(RV_REG_SP, store_offset, RV_REG_S6, ctx);
                store_offset -= 8;
        }
+       if (ctx->arena_vm_start) {
+               emit_sd(RV_REG_SP, store_offset, RV_REG_ARENA, ctx);
+               store_offset -= 8;
+       }
 
        emit_addi(RV_REG_FP, RV_REG_SP, stack_adjust, ctx);
 
                emit_mv(RV_REG_TCC_SAVED, RV_REG_TCC, ctx);
 
        ctx->stack_size = stack_adjust;
+
+       if (ctx->arena_vm_start)
+               emit_imm(RV_REG_ARENA, ctx->arena_vm_start, ctx);
 }
 
 void bpf_jit_build_epilogue(struct rv_jit_context *ctx)