static struct bpf_insn *bpf_convert_data_end_access(const struct bpf_insn *si,
                                                    struct bpf_insn *insn)
 {
-       /* si->dst_reg = skb->data */
+       int reg;
+       int temp_reg_off = offsetof(struct sk_buff, cb) +
+                          offsetof(struct sk_skb_cb, temp_reg);
+
+       if (si->src_reg == si->dst_reg) {
+               /* We need an extra register, choose and save a register. */
+               reg = BPF_REG_9;
+               if (si->src_reg == reg || si->dst_reg == reg)
+                       reg--;
+               if (si->src_reg == reg || si->dst_reg == reg)
+                       reg--;
+               *insn++ = BPF_STX_MEM(BPF_DW, si->src_reg, reg, temp_reg_off);
+       } else {
+               reg = si->dst_reg;
+       }
+
+       /* reg = skb->data */
        *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, data),
-                             si->dst_reg, si->src_reg,
+                             reg, si->src_reg,
                              offsetof(struct sk_buff, data));
        /* AX = skb->len */
        *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, len),
                              BPF_REG_AX, si->src_reg,
                              offsetof(struct sk_buff, len));
-       /* si->dst_reg = skb->data + skb->len */
-       *insn++ = BPF_ALU64_REG(BPF_ADD, si->dst_reg, BPF_REG_AX);
+       /* reg = skb->data + skb->len */
+       *insn++ = BPF_ALU64_REG(BPF_ADD, reg, BPF_REG_AX);
        /* AX = skb->data_len */
        *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, data_len),
                              BPF_REG_AX, si->src_reg,
                              offsetof(struct sk_buff, data_len));
-       /* si->dst_reg = skb->data + skb->len - skb->data_len */
-       *insn++ = BPF_ALU64_REG(BPF_SUB, si->dst_reg, BPF_REG_AX);
+
+       /* reg = skb->data + skb->len - skb->data_len */
+       *insn++ = BPF_ALU64_REG(BPF_SUB, reg, BPF_REG_AX);
+
+       if (si->src_reg == si->dst_reg) {
+               /* Restore the saved register */
+               *insn++ = BPF_MOV64_REG(BPF_REG_AX, si->src_reg);
+               *insn++ = BPF_MOV64_REG(si->dst_reg, reg);
+               *insn++ = BPF_LDX_MEM(BPF_DW, reg, BPF_REG_AX, temp_reg_off);
+       }
 
        return insn;
 }