On Mon, 20 Aug 2018 19:41:56 +1000
Nicholas Piggin <npig...@gmail.com> wrote:


> +long do_slb_fault(struct pt_regs *regs, unsigned long ea)
> +{
> +     unsigned long id = REGION_ID(ea);
> +
> +     /* IRQs are not reconciled here, so can't check irqs_disabled */
> +     VM_WARN_ON(mfmsr() & MSR_EE);
> +
> +     /*
> +      * SLB kernel faults must be very careful not to touch anything
> +      * that is not bolted. E.g., PACA and global variables are okay,
> +      * mm->context stuff is not.
> +      *
> +      * SLB user faults can access all of kernel memory, but must be
> +      * careful not to touch things like IRQ state because it is not
> +      * "reconciled" here. The difficulty is that we must use
> +      * fast_exception_return to return from kernel SLB faults without
> +      * looking at possible non-bolted memory. We could test user vs
> +      * kernel faults in the interrupt handler asm and do a full fault,
> +      * reconcile, ret_from_except for user faults which would make them
> +      * first class kernel code. But for performance it's probably nicer
> +      * if they go via fast_exception_return too.
> +      */
> +     if (id >= KERNEL_REGION_ID) {
> +             return slb_allocate_kernel(ea, id);
> +     } else {
> +             struct mm_struct *mm = current->mm;
> +
> +             if (unlikely(!mm))
> +                     return -EFAULT;
>  
> -     handle_multi_context_slb_miss(context, ea);
> -     exception_exit(prev_state);
> -     return;
> +             return slb_allocate_user(mm, ea);
> +     }
> +}
>  
> -slb_bad_addr:
> +void do_bad_slb_fault(struct pt_regs *regs, unsigned long ea, long err)
> +{
>       if (user_mode(regs))
>               _exception(SIGSEGV, regs, SEGV_BNDERR, ea);
>       else
>               bad_page_fault(regs, ea, SIGSEGV);
> -     exception_exit(prev_state);
>  }

I knew I forgot something -- forgot to test MSR[RI] here. That can be
done just by returning a different error from do_slb_fault if RI is
clear, and do_bad_slb_fault will call unrecoverable_exception() if it
sees that code.

Thanks,
Nick

Reply via email to