diff options
Diffstat (limited to 'arch/loongarch')
| -rw-r--r-- | arch/loongarch/include/asm/kexec.h | 3 | ||||
| -rw-r--r-- | arch/loongarch/include/asm/pgtable.h | 4 | ||||
| -rw-r--r-- | arch/loongarch/include/asm/uaccess.h | 3 | ||||
| -rw-r--r-- | arch/loongarch/kvm/exit.c | 1 | ||||
| -rw-r--r-- | arch/loongarch/kvm/irqfd.c | 3 | ||||
| -rw-r--r-- | arch/loongarch/kvm/vcpu.c | 11 | ||||
| -rw-r--r-- | arch/loongarch/mm/pageattr.c | 2 | ||||
| -rw-r--r-- | arch/loongarch/net/bpf_jit.c | 28 |
8 files changed, 39 insertions, 16 deletions
diff --git a/arch/loongarch/include/asm/kexec.h b/arch/loongarch/include/asm/kexec.h index 209fa43222e1..6be136e9f0a0 100644 --- a/arch/loongarch/include/asm/kexec.h +++ b/arch/loongarch/include/asm/kexec.h @@ -41,6 +41,8 @@ struct kimage_arch { unsigned long systable_ptr; }; +struct kimage; + #ifdef CONFIG_KEXEC_FILE extern const struct kexec_file_ops kexec_efi_ops; extern const struct kexec_file_ops kexec_elf_ops; @@ -59,7 +61,6 @@ typedef void (*do_kexec_t)(unsigned long efi_boot, unsigned long start_addr, unsigned long first_ind_entry); -struct kimage; extern const unsigned char relocate_new_kernel[]; extern const size_t relocate_new_kernel_size; extern void kexec_reboot(void); diff --git a/arch/loongarch/include/asm/pgtable.h b/arch/loongarch/include/asm/pgtable.h index 2a0b63ae421f..223528c04d73 100644 --- a/arch/loongarch/include/asm/pgtable.h +++ b/arch/loongarch/include/asm/pgtable.h @@ -429,6 +429,8 @@ static inline pte_t pte_mkwrite_novma(pte_t pte) static inline pte_t pte_wrprotect(pte_t pte) { + if (pte_val(pte) & _PAGE_DIRTY) + pte_val(pte) |= _PAGE_MODIFIED; pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY); return pte; } @@ -535,6 +537,8 @@ static inline pmd_t pmd_mkwrite_novma(pmd_t pmd) static inline pmd_t pmd_wrprotect(pmd_t pmd) { + if (pmd_val(pmd) & _PAGE_DIRTY) + pmd_val(pmd) |= _PAGE_MODIFIED; pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_DIRTY); return pmd; } diff --git a/arch/loongarch/include/asm/uaccess.h b/arch/loongarch/include/asm/uaccess.h index 438269313e78..428f373feabf 100644 --- a/arch/loongarch/include/asm/uaccess.h +++ b/arch/loongarch/include/asm/uaccess.h @@ -292,8 +292,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n) return __copy_user((__force void *)to, from, n); } -#define INLINE_COPY_FROM_USER -#define INLINE_COPY_TO_USER +#define INLINE_COPY_USER /* * __clear_user: - Zero a block of memory in user space, with less checking. diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c index 3b95cd0f989b..264813d45cbe 100644 --- a/arch/loongarch/kvm/exit.c +++ b/arch/loongarch/kvm/exit.c @@ -103,7 +103,6 @@ static unsigned long kvm_emu_xchg_csr(struct kvm_vcpu *vcpu, int csrid, old = kvm_read_sw_gcsr(csr, csrid); val = (old & ~csr_mask) | (val & csr_mask); kvm_write_sw_gcsr(csr, csrid, val); - old = old & csr_mask; } else pr_warn_once("Unsupported csrxchg 0x%x with pc %lx\n", csrid, vcpu->arch.pc); diff --git a/arch/loongarch/kvm/irqfd.c b/arch/loongarch/kvm/irqfd.c index f4f953b22419..40ed1081c4b6 100644 --- a/arch/loongarch/kvm/irqfd.c +++ b/arch/loongarch/kvm/irqfd.c @@ -51,7 +51,8 @@ int kvm_set_routing_entry(struct kvm *kvm, e->irqchip.irqchip = ue->u.irqchip.irqchip; e->irqchip.pin = ue->u.irqchip.pin; - if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) + if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS || + e->irqchip.irqchip >= KVM_NR_IRQCHIPS) return -EINVAL; return 0; diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c index e28084c49e68..7f7f2b71f03a 100644 --- a/arch/loongarch/kvm/vcpu.c +++ b/arch/loongarch/kvm/vcpu.c @@ -1108,7 +1108,8 @@ static int kvm_loongarch_cpucfg_get_attr(struct kvm_vcpu *vcpu, return -ENXIO; } - put_user(val, uaddr); + if (put_user(val, uaddr)) + return -EFAULT; return ret; } @@ -1312,7 +1313,7 @@ int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) fpu->fcc = vcpu->arch.fpu.fcc; fpu->fcsr = vcpu->arch.fpu.fcsr; for (i = 0; i < NUM_FPU_REGS; i++) - memcpy(&fpu->fpr[i], &vcpu->arch.fpu.fpr[i], FPU_REG_WIDTH / 64); + memcpy(&fpu->fpr[i], &vcpu->arch.fpu.fpr[i], sizeof(union fpureg)); return 0; } @@ -1324,7 +1325,7 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) vcpu->arch.fpu.fcc = fpu->fcc; vcpu->arch.fpu.fcsr = fpu->fcsr; for (i = 0; i < NUM_FPU_REGS; i++) - memcpy(&vcpu->arch.fpu.fpr[i], &fpu->fpr[i], FPU_REG_WIDTH / 64); + memcpy(&vcpu->arch.fpu.fpr[i], &fpu->fpr[i], sizeof(union fpureg)); return 0; } @@ -1487,6 +1488,10 @@ void kvm_lose_fpu(struct kvm_vcpu *vcpu) int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq) { int intr = (int)irq->irq; + unsigned int vector = abs(intr); + + if (vector >= EXCCODE_INT_NUM) + return -EINVAL; if (intr > 0) kvm_queue_irq(vcpu, intr); diff --git a/arch/loongarch/mm/pageattr.c b/arch/loongarch/mm/pageattr.c index f5e910b68229..614ccc7afccb 100644 --- a/arch/loongarch/mm/pageattr.c +++ b/arch/loongarch/mm/pageattr.c @@ -234,5 +234,5 @@ int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid) clear = __pgprot(_PAGE_PRESENT | _PAGE_VALID); } - return __set_memory(addr, 1, set, clear); + return __set_memory(addr, nr, set, clear); } diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c index e14a8aa47fc8..e4966c178abc 100644 --- a/arch/loongarch/net/bpf_jit.c +++ b/arch/loongarch/net/bpf_jit.c @@ -9,7 +9,13 @@ #define LOONGARCH_MAX_REG_ARGS 8 +#define LOONGARCH_SAVE_RA_NINSNS 1 #define LOONGARCH_LONG_JUMP_NINSNS 5 +#define LOONGARCH_TCC_SLOT_NINSNS 1 + +#define LOONGARCH_PROLOGUE_SKIP_INSNS \ + (LOONGARCH_SAVE_RA_NINSNS + LOONGARCH_LONG_JUMP_NINSNS + LOONGARCH_TCC_SLOT_NINSNS) + #define LOONGARCH_LONG_JUMP_NBYTES (LOONGARCH_LONG_JUMP_NINSNS * 4) #define LOONGARCH_FENTRY_NINSNS 2 @@ -143,8 +149,13 @@ static void build_prologue(struct jit_ctx *ctx) stack_adjust = round_up(stack_adjust, 16); stack_adjust += bpf_stack_adjust; + /* + * Save the original return address to a temporary register to prevent + * it from being overwritten, then reserve space for the long jump and + * fentry trampoline slot for dynamically patching by ftrace at runtime. + * These instructions are bypassed during a tail call invocation. + */ move_reg(ctx, LOONGARCH_GPR_T0, LOONGARCH_GPR_RA); - /* Reserve space for the move_imm + jirl instruction */ for (i = 0; i < LOONGARCH_LONG_JUMP_NINSNS; i++) emit_insn(ctx, nop); @@ -253,10 +264,11 @@ static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call) emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_RA, 0); } else { /* - * Call the next bpf prog and skip the first instruction - * of TCC initialization. + * Tail call to the next BPF program, passing offset in number + * of instructions to jirl to bypass the initial setup slots. */ - emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 7); + emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, + LOONGARCH_GPR_T3, LOONGARCH_PROLOGUE_SKIP_INSNS); } } @@ -312,12 +324,12 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn) */ emit_insn(ctx, ldd, REG_TCC, LOONGARCH_GPR_SP, tcc_ptr_off); emit_insn(ctx, ldd, t3, REG_TCC, 0); - emit_insn(ctx, addid, t3, t3, 1); - emit_insn(ctx, std, t3, REG_TCC, 0); emit_insn(ctx, addid, t2, LOONGARCH_GPR_ZERO, MAX_TAIL_CALL_CNT); - if (emit_tailcall_jmp(ctx, BPF_JSGT, t3, t2, jmp_offset) < 0) + if (emit_tailcall_jmp(ctx, BPF_JSGE, t3, t2, jmp_offset) < 0) goto toofar; + emit_insn(ctx, addid, t3, t3, 1); + /* * prog = array->ptrs[index]; * if (!prog) @@ -330,6 +342,8 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn) if (emit_tailcall_jmp(ctx, BPF_JEQ, t2, LOONGARCH_GPR_ZERO, jmp_offset) < 0) goto toofar; + emit_insn(ctx, std, t3, REG_TCC, 0); + /* goto *(prog->bpf_func + 4); */ off = offsetof(struct bpf_prog, bpf_func); emit_insn(ctx, ldd, t3, t2, off); |
