1*76ed9158SBenjamin Berg // SPDX-License-Identifier: GPL-2.0 2*76ed9158SBenjamin Berg /* 3*76ed9158SBenjamin Berg * Copyright (C) 2021 Benjamin Berg <benjamin@sipsolutions.net> 4*76ed9158SBenjamin Berg */ 5*76ed9158SBenjamin Berg 6*76ed9158SBenjamin Berg #include <sysdep/stub.h> 7*76ed9158SBenjamin Berg syscall_handler(struct stub_data * d)8*76ed9158SBenjamin Bergstatic __always_inline int syscall_handler(struct stub_data *d) 9*76ed9158SBenjamin Berg { 10*76ed9158SBenjamin Berg int i; 11*76ed9158SBenjamin Berg unsigned long res; 12*76ed9158SBenjamin Berg 13*76ed9158SBenjamin Berg for (i = 0; i < d->syscall_data_len; i++) { 14*76ed9158SBenjamin Berg struct stub_syscall *sc = &d->syscall_data[i]; 15*76ed9158SBenjamin Berg 16*76ed9158SBenjamin Berg switch (sc->syscall) { 17*76ed9158SBenjamin Berg case STUB_SYSCALL_MMAP: 18*76ed9158SBenjamin Berg res = stub_syscall6(STUB_MMAP_NR, 19*76ed9158SBenjamin Berg sc->mem.addr, sc->mem.length, 20*76ed9158SBenjamin Berg sc->mem.prot, 21*76ed9158SBenjamin Berg MAP_SHARED | MAP_FIXED, 22*76ed9158SBenjamin Berg sc->mem.fd, sc->mem.offset); 23*76ed9158SBenjamin Berg if (res != sc->mem.addr) { 24*76ed9158SBenjamin Berg d->err = res; 25*76ed9158SBenjamin Berg d->syscall_data_len = i; 26*76ed9158SBenjamin Berg return -1; 27*76ed9158SBenjamin Berg } 28*76ed9158SBenjamin Berg break; 29*76ed9158SBenjamin Berg case STUB_SYSCALL_MUNMAP: 30*76ed9158SBenjamin Berg res = stub_syscall2(__NR_munmap, 31*76ed9158SBenjamin Berg sc->mem.addr, sc->mem.length); 32*76ed9158SBenjamin Berg if (res) { 33*76ed9158SBenjamin Berg d->err = res; 34*76ed9158SBenjamin Berg d->syscall_data_len = i; 35*76ed9158SBenjamin Berg return -1; 36*76ed9158SBenjamin Berg } 37*76ed9158SBenjamin Berg break; 38*76ed9158SBenjamin Berg default: 39*76ed9158SBenjamin Berg d->err = -95; /* EOPNOTSUPP */ 40*76ed9158SBenjamin Berg d->syscall_data_len = i; 41*76ed9158SBenjamin Berg return -1; 42*76ed9158SBenjamin Berg } 43*76ed9158SBenjamin Berg } 44*76ed9158SBenjamin Berg 45*76ed9158SBenjamin Berg d->err = 0; 46*76ed9158SBenjamin Berg d->syscall_data_len = 0; 47*76ed9158SBenjamin Berg 48*76ed9158SBenjamin Berg return 0; 49*76ed9158SBenjamin Berg } 50*76ed9158SBenjamin Berg 51*76ed9158SBenjamin Berg void __section(".__syscall_stub") stub_syscall_handler(void)52*76ed9158SBenjamin Bergstub_syscall_handler(void) 53*76ed9158SBenjamin Berg { 54*76ed9158SBenjamin Berg struct stub_data *d = get_stub_data(); 55*76ed9158SBenjamin Berg 56*76ed9158SBenjamin Berg syscall_handler(d); 57*76ed9158SBenjamin Berg 58*76ed9158SBenjamin Berg trap_myself(); 59*76ed9158SBenjamin Berg } 60