|
38 | 38 | #include <asm/irq.h> |
39 | 39 | #include <asm/mmu_context.h> |
40 | 40 | #include <asm/facility.h> |
| 41 | +#include <asm/uv.h> |
41 | 42 | #include "../kernel/entry.h" |
42 | 43 |
|
43 | 44 | #define __FAIL_ADDR_MASK -4096L |
@@ -816,3 +817,80 @@ static int __init pfault_irq_init(void) |
816 | 817 | early_initcall(pfault_irq_init); |
817 | 818 |
|
818 | 819 | #endif /* CONFIG_PFAULT */ |
| 820 | + |
| 821 | +#if IS_ENABLED(CONFIG_PGSTE) |
| 822 | +void do_secure_storage_access(struct pt_regs *regs) |
| 823 | +{ |
| 824 | + unsigned long addr = regs->int_parm_long & __FAIL_ADDR_MASK; |
| 825 | + struct vm_area_struct *vma; |
| 826 | + struct mm_struct *mm; |
| 827 | + struct page *page; |
| 828 | + int rc; |
| 829 | + |
| 830 | + switch (get_fault_type(regs)) { |
| 831 | + case USER_FAULT: |
| 832 | + mm = current->mm; |
| 833 | + down_read(&mm->mmap_sem); |
| 834 | + vma = find_vma(mm, addr); |
| 835 | + if (!vma) { |
| 836 | + up_read(&mm->mmap_sem); |
| 837 | + do_fault_error(regs, VM_READ | VM_WRITE, VM_FAULT_BADMAP); |
| 838 | + break; |
| 839 | + } |
| 840 | + page = follow_page(vma, addr, FOLL_WRITE | FOLL_GET); |
| 841 | + if (IS_ERR_OR_NULL(page)) { |
| 842 | + up_read(&mm->mmap_sem); |
| 843 | + break; |
| 844 | + } |
| 845 | + if (arch_make_page_accessible(page)) |
| 846 | + send_sig(SIGSEGV, current, 0); |
| 847 | + put_page(page); |
| 848 | + up_read(&mm->mmap_sem); |
| 849 | + break; |
| 850 | + case KERNEL_FAULT: |
| 851 | + page = phys_to_page(addr); |
| 852 | + if (unlikely(!try_get_page(page))) |
| 853 | + break; |
| 854 | + rc = arch_make_page_accessible(page); |
| 855 | + put_page(page); |
| 856 | + if (rc) |
| 857 | + BUG(); |
| 858 | + break; |
| 859 | + case VDSO_FAULT: |
| 860 | + /* fallthrough */ |
| 861 | + case GMAP_FAULT: |
| 862 | + /* fallthrough */ |
| 863 | + default: |
| 864 | + do_fault_error(regs, VM_READ | VM_WRITE, VM_FAULT_BADMAP); |
| 865 | + WARN_ON_ONCE(1); |
| 866 | + } |
| 867 | +} |
| 868 | +NOKPROBE_SYMBOL(do_secure_storage_access); |
| 869 | + |
| 870 | +void do_non_secure_storage_access(struct pt_regs *regs) |
| 871 | +{ |
| 872 | + unsigned long gaddr = regs->int_parm_long & __FAIL_ADDR_MASK; |
| 873 | + struct gmap *gmap = (struct gmap *)S390_lowcore.gmap; |
| 874 | + |
| 875 | + if (get_fault_type(regs) != GMAP_FAULT) { |
| 876 | + do_fault_error(regs, VM_READ | VM_WRITE, VM_FAULT_BADMAP); |
| 877 | + WARN_ON_ONCE(1); |
| 878 | + return; |
| 879 | + } |
| 880 | + |
| 881 | + if (gmap_convert_to_secure(gmap, gaddr) == -EINVAL) |
| 882 | + send_sig(SIGSEGV, current, 0); |
| 883 | +} |
| 884 | +NOKPROBE_SYMBOL(do_non_secure_storage_access); |
| 885 | + |
| 886 | +#else |
| 887 | +void do_secure_storage_access(struct pt_regs *regs) |
| 888 | +{ |
| 889 | + default_trap_handler(regs); |
| 890 | +} |
| 891 | + |
| 892 | +void do_non_secure_storage_access(struct pt_regs *regs) |
| 893 | +{ |
| 894 | + default_trap_handler(regs); |
| 895 | +} |
| 896 | +#endif |
0 commit comments