]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
um: compress memory related stub syscalls while adding them
authorBenjamin Berg <benjamin.berg@intel.com>
Wed, 3 Jul 2024 13:45:29 +0000 (15:45 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 3 Jul 2024 15:09:49 +0000 (17:09 +0200)
To keep the number of syscalls that the stub has to do lower, compress
two consecutive syscalls of the same type if the second is just a
continuation of the first.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Link: https://patch.msgid.link/20240703134536.1161108-6-benjamin@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
arch/um/os-Linux/skas/mem.c

index 40be9085f65b5675e6c14398f1ed331b12aff422..32c61189110c8d0353cee370a7318bffe67bf65e 100644 (file)
@@ -151,12 +151,37 @@ struct stub_syscall *syscall_stub_alloc(struct mm_id *mm_idp)
        return sc;
 }
 
+static struct stub_syscall *syscall_stub_get_previous(struct mm_id *mm_idp,
+                                                     int syscall_type,
+                                                     unsigned long virt)
+{
+       if (mm_idp->syscall_data_len > 0) {
+               struct stub_data *proc_data = (void *) mm_idp->stack;
+               struct stub_syscall *sc;
+
+               sc = &proc_data->syscall_data[mm_idp->syscall_data_len - 1];
+
+               if (sc->syscall == syscall_type &&
+                   sc->mem.addr + sc->mem.length == virt)
+                       return sc;
+       }
+
+       return NULL;
+}
 
 void map(struct mm_id *mm_idp, unsigned long virt, unsigned long len, int prot,
        int phys_fd, unsigned long long offset)
 {
        struct stub_syscall *sc;
 
+       /* Compress with previous syscall if that is possible */
+       sc = syscall_stub_get_previous(mm_idp, STUB_SYSCALL_MMAP, virt);
+       if (sc && sc->mem.prot == prot && sc->mem.fd == phys_fd &&
+           sc->mem.offset == MMAP_OFFSET(offset - sc->mem.length)) {
+               sc->mem.length += len;
+               return;
+       }
+
        sc = syscall_stub_alloc(mm_idp);
        sc->syscall = STUB_SYSCALL_MMAP;
        sc->mem.addr = virt;
@@ -170,6 +195,13 @@ void unmap(struct mm_id *mm_idp, unsigned long addr, unsigned long len)
 {
        struct stub_syscall *sc;
 
+       /* Compress with previous syscall if that is possible */
+       sc = syscall_stub_get_previous(mm_idp, STUB_SYSCALL_MUNMAP, addr);
+       if (sc) {
+               sc->mem.length += len;
+               return;
+       }
+
        sc = syscall_stub_alloc(mm_idp);
        sc->syscall = STUB_SYSCALL_MUNMAP;
        sc->mem.addr = addr;
@@ -181,6 +213,13 @@ void protect(struct mm_id *mm_idp, unsigned long addr, unsigned long len,
 {
        struct stub_syscall *sc;
 
+       /* Compress with previous syscall if that is possible */
+       sc = syscall_stub_get_previous(mm_idp, STUB_SYSCALL_MPROTECT, addr);
+       if (sc && sc->mem.prot == prot) {
+               sc->mem.length += len;
+               return;
+       }
+
        sc = syscall_stub_alloc(mm_idp);
        sc->syscall = STUB_SYSCALL_MPROTECT;
        sc->mem.addr = addr;