Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'uml-for-linus-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux

Pull UML updates from Richard Weinberger:

- Lots of cleanups, mostly from Benjamin Berg and Tiwei Bie

- Removal of unused code

- Fix for sparse warnings

- Cleanup around stub_exe()

* tag 'uml-for-linus-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux: (68 commits)
hostfs: Fix the NULL vs IS_ERR() bug for __filemap_get_folio()
um: move thread info into task
um: Always dump trace for specified task in show_stack
um: vector: Do not use drvdata in release
um: net: Do not use drvdata in release
um: ubd: Do not use drvdata in release
um: ubd: Initialize ubd's disk pointer in ubd_add
um: virtio_uml: query the number of vqs if supported
um: virtio_uml: fix call_fd IRQ allocation
um: virtio_uml: send SET_MEM_TABLE message with the exact size
um: remove broken double fault detection
um: remove duplicate UM_NSEC_PER_SEC definition
um: remove file sync for stub data
um: always include kconfig.h and compiler-version.h
um: set DONTDUMP and DONTFORK flags on KASAN shadow memory
um: fix sparse warnings in signal code
um: fix sparse warnings from regset refactor
um: Remove double zero check
um: fix stub exe build with CONFIG_GCOV
um: Use os_set_pdeathsig helper in winch thread/process
...

+1226 -1393
+21 -3
arch/um/Kconfig
··· 5 5 config UML 6 6 bool 7 7 default y 8 + select ARCH_WANTS_DYNAMIC_TASK_STRUCT 8 9 select ARCH_HAS_CPU_FINALIZE_INIT 9 10 select ARCH_HAS_FORTIFY_SOURCE 10 11 select ARCH_HAS_GCOV_PROFILE_ALL ··· 33 32 select HAVE_ARCH_VMAP_STACK 34 33 select HAVE_RUST 35 34 select ARCH_HAS_UBSAN 35 + select HAVE_ARCH_TRACEHOOK 36 + select THREAD_INFO_IN_TASK 36 37 37 38 config MMU 38 39 bool ··· 97 94 98 95 config STATIC_LINK 99 96 bool "Force a static link" 100 - depends on CC_CAN_LINK_STATIC_NO_RUNTIME_DEPS || !MAY_HAVE_RUNTIME_DEPS 97 + depends on !MAY_HAVE_RUNTIME_DEPS 101 98 help 102 99 This option gives you the ability to force a static link of UML. 103 100 Normally, UML is linked as a shared binary. This is inconvenient for ··· 212 209 213 210 config PGTABLE_LEVELS 214 211 int 215 - default 3 if 3_LEVEL_PGTABLES 216 - default 2 212 + default 4 if 64BIT 213 + default 2 if !64BIT 217 214 218 215 config UML_TIME_TRAVEL_SUPPORT 219 216 bool ··· 229 226 line help for more details. 230 227 231 228 It is safe to say Y, but you probably don't need this. 229 + 230 + config UML_MAX_USERSPACE_ITERATIONS 231 + int 232 + prompt "Maximum number of unscheduled userspace iterations" 233 + default 10000 234 + depends on UML_TIME_TRAVEL_SUPPORT 235 + help 236 + In UML inf-cpu and ext time-travel mode userspace can run without being 237 + interrupted. This will eventually overwhelm the kernel and create OOM 238 + situations (mainly RCU not running). This setting specifies the number 239 + of kernel/userspace switches (minor/major page fault, signal or syscall) 240 + for the same userspace thread before the sched_clock is advanced by a 241 + jiffie to trigger scheduling. 242 + 243 + Setting it to zero disables the feature. 232 244 233 245 config KASAN_SHADOW_OFFSET 234 246 hex
+5 -2
arch/um/Makefile
··· 61 61 $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ 62 62 -Dlongjmp=kernel_longjmp -Dsetjmp=kernel_setjmp \ 63 63 -Din6addr_loopback=kernel_in6addr_loopback \ 64 - -Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr 64 + -Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr \ 65 + -D__close_range=kernel__close_range 65 66 66 67 KBUILD_RUSTFLAGS += -Crelocation-model=pie 67 68 ··· 71 70 USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \ 72 71 $(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \ 73 72 -D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \ 74 - -idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__ 73 + -idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__ \ 74 + -include $(srctree)/include/linux/compiler-version.h \ 75 + -include $(srctree)/include/linux/kconfig.h 75 76 76 77 #This will adjust *FLAGS accordingly to the platform. 77 78 include $(srctree)/$(ARCH_DIR)/Makefile-os-Linux
+7 -7
arch/um/Makefile-skas
··· 3 3 # Licensed under the GPL 4 4 # 5 5 6 - GPROF_OPT += -pg 6 + export UM_GPROF_OPT += -pg 7 7 8 8 ifdef CONFIG_CC_IS_CLANG 9 - GCOV_OPT += -fprofile-instr-generate -fcoverage-mapping 9 + export UM_GCOV_OPT += -fprofile-instr-generate -fcoverage-mapping 10 10 else 11 - GCOV_OPT += -fprofile-arcs -ftest-coverage 11 + export UM_GCOV_OPT += -fprofile-arcs -ftest-coverage 12 12 endif 13 13 14 - CFLAGS-$(CONFIG_GCOV) += $(GCOV_OPT) 15 - CFLAGS-$(CONFIG_GPROF) += $(GPROF_OPT) 16 - LINK-$(CONFIG_GCOV) += $(GCOV_OPT) 17 - LINK-$(CONFIG_GPROF) += $(GPROF_OPT) 14 + CFLAGS-$(CONFIG_GCOV) += $(UM_GCOV_OPT) 15 + CFLAGS-$(CONFIG_GPROF) += $(UM_GPROF_OPT) 16 + LINK-$(CONFIG_GCOV) += $(UM_GCOV_OPT) 17 + LINK-$(CONFIG_GPROF) += $(UM_GPROF_OPT)
-1
arch/um/configs/i386_defconfig
··· 1 - CONFIG_3_LEVEL_PGTABLES=y 2 1 # CONFIG_COMPACTION is not set 3 2 CONFIG_BINFMT_MISC=m 4 3 CONFIG_HOSTFS=y
+2
arch/um/drivers/chan_user.c
··· 161 161 int count; 162 162 char c = 1; 163 163 164 + os_set_pdeathsig(); 165 + 164 166 pty_fd = data->pty_fd; 165 167 pipe_fd = data->pipe_fd; 166 168 count = write(pipe_fd, &c, sizeof(c));
+2
arch/um/drivers/hostaudio_kern.c
··· 48 48 #ifndef MODULE 49 49 static int set_dsp(char *name, int *add) 50 50 { 51 + *add = 0; 51 52 dsp = name; 52 53 return 0; 53 54 } ··· 57 56 58 57 static int set_mixer(char *name, int *add) 59 58 { 59 + *add = 0; 60 60 mixer = name; 61 61 return 0; 62 62 }
+1 -1
arch/um/drivers/net_kern.c
··· 336 336 337 337 static void net_device_release(struct device *dev) 338 338 { 339 - struct uml_net *device = dev_get_drvdata(dev); 339 + struct uml_net *device = container_of(dev, struct uml_net, pdev.dev); 340 340 struct net_device *netdev = device->dev; 341 341 struct uml_net_private *lp = netdev_priv(netdev); 342 342
+4 -1
arch/um/drivers/ubd_kern.c
··· 779 779 780 780 static void ubd_device_release(struct device *dev) 781 781 { 782 - struct ubd *ubd_dev = dev_get_drvdata(dev); 782 + struct ubd *ubd_dev = container_of(dev, struct ubd, pdev.dev); 783 783 784 784 blk_mq_free_tag_set(&ubd_dev->tag_set); 785 785 *ubd_dev = ((struct ubd) DEFAULT_UBD); ··· 897 897 err = device_add_disk(&ubd_dev->pdev.dev, disk, ubd_attr_groups); 898 898 if (err) 899 899 goto out_cleanup_disk; 900 + 901 + ubd_dev->disk = disk; 900 902 901 903 return 0; 902 904 ··· 1501 1499 { 1502 1500 int n, count, written, res; 1503 1501 1502 + os_set_pdeathsig(); 1504 1503 os_fix_helper_signals(); 1505 1504 1506 1505 while(1){
+2 -1
arch/um/drivers/vector_kern.c
··· 815 815 816 816 static void vector_device_release(struct device *dev) 817 817 { 818 - struct vector_device *device = dev_get_drvdata(dev); 818 + struct vector_device *device = 819 + container_of(dev, struct vector_device, pdev.dev); 819 820 struct net_device *netdev = device->dev; 820 821 821 822 list_del(&device->list);
+3 -1
arch/um/drivers/vhost_user.h
··· 10 10 /* Feature bits */ 11 11 #define VHOST_USER_F_PROTOCOL_FEATURES 30 12 12 /* Protocol feature bits */ 13 + #define VHOST_USER_PROTOCOL_F_MQ 0 13 14 #define VHOST_USER_PROTOCOL_F_REPLY_ACK 3 14 15 #define VHOST_USER_PROTOCOL_F_SLAVE_REQ 5 15 16 #define VHOST_USER_PROTOCOL_F_CONFIG 9 ··· 24 23 /* Supported transport features */ 25 24 #define VHOST_USER_SUPPORTED_F BIT_ULL(VHOST_USER_F_PROTOCOL_FEATURES) 26 25 /* Supported protocol features */ 27 - #define VHOST_USER_SUPPORTED_PROTOCOL_F (BIT_ULL(VHOST_USER_PROTOCOL_F_REPLY_ACK) | \ 26 + #define VHOST_USER_SUPPORTED_PROTOCOL_F (BIT_ULL(VHOST_USER_PROTOCOL_F_MQ) | \ 27 + BIT_ULL(VHOST_USER_PROTOCOL_F_REPLY_ACK) | \ 28 28 BIT_ULL(VHOST_USER_PROTOCOL_F_SLAVE_REQ) | \ 29 29 BIT_ULL(VHOST_USER_PROTOCOL_F_CONFIG) | \ 30 30 BIT_ULL(VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS))
+35 -16
arch/um/drivers/virtio_uml.c
··· 56 56 int sock, req_fd, irq; 57 57 u64 features; 58 58 u64 protocol_features; 59 + u64 max_vqs; 59 60 u8 status; 60 61 u8 registered:1; 61 62 u8 suspended:1; ··· 72 71 char name[32]; 73 72 bool suspended; 74 73 }; 75 - 76 - extern unsigned long long physmem_size, highmem; 77 74 78 75 #define vu_err(vu_dev, ...) dev_err(&(vu_dev)->pdev->dev, ##__VA_ARGS__) 79 76 ··· 342 343 protocol_features); 343 344 } 344 345 346 + static int vhost_user_get_queue_num(struct virtio_uml_device *vu_dev, 347 + u64 *queue_num) 348 + { 349 + int rc = vhost_user_send_no_payload(vu_dev, true, 350 + VHOST_USER_GET_QUEUE_NUM); 351 + 352 + if (rc) 353 + return rc; 354 + return vhost_user_recv_u64(vu_dev, queue_num); 355 + } 356 + 345 357 static void vhost_user_reply(struct virtio_uml_device *vu_dev, 346 358 struct vhost_user_msg *msg, int response) 347 359 { ··· 526 516 return rc; 527 517 } 528 518 519 + if (vu_dev->protocol_features & 520 + BIT_ULL(VHOST_USER_PROTOCOL_F_MQ)) { 521 + rc = vhost_user_get_queue_num(vu_dev, &vu_dev->max_vqs); 522 + if (rc) 523 + return rc; 524 + } else { 525 + vu_dev->max_vqs = U64_MAX; 526 + } 527 + 529 528 return 0; 530 529 } 531 530 ··· 644 625 { 645 626 struct vhost_user_msg msg = { 646 627 .header.request = VHOST_USER_SET_MEM_TABLE, 647 - .header.size = sizeof(msg.payload.mem_regions), 628 + .header.size = offsetof(typeof(msg.payload.mem_regions), regions[1]), 648 629 .payload.mem_regions.num = 1, 649 630 }; 650 631 unsigned long reserved = uml_reserved - uml_physmem; ··· 692 673 693 674 if (rc < 0) 694 675 return rc; 695 - if (highmem) { 696 - msg.payload.mem_regions.num++; 697 - rc = vhost_user_init_mem_region(__pa(end_iomem), highmem, 698 - &fds[1], &msg.payload.mem_regions.regions[1]); 699 - if (rc < 0) 700 - return rc; 701 - } 702 676 703 677 return vhost_user_send(vu_dev, false, &msg, fds, 704 678 msg.payload.mem_regions.num); ··· 909 897 { 910 898 struct virtio_uml_vq_info *info = vq->priv; 911 899 int call_fds[2]; 912 - int rc; 900 + int rc, irq; 913 901 914 902 /* no call FD needed/desired in this case */ 915 903 if (vu_dev->protocol_features & ··· 926 914 return rc; 927 915 928 916 info->call_fd = call_fds[0]; 929 - rc = um_request_irq(vu_dev->irq, info->call_fd, IRQ_READ, 930 - vu_interrupt, IRQF_SHARED, info->name, vq); 931 - if (rc < 0) 917 + irq = um_request_irq(vu_dev->irq, info->call_fd, IRQ_READ, 918 + vu_interrupt, IRQF_SHARED, info->name, vq); 919 + if (irq < 0) { 920 + rc = irq; 932 921 goto close_both; 922 + } 933 923 934 924 rc = vhost_user_set_vring_call(vu_dev, vq->index, call_fds[1]); 935 925 if (rc) 936 926 goto release_irq; 937 927 928 + vu_dev->irq = irq; 929 + 938 930 goto out; 939 931 940 932 release_irq: 941 - um_free_irq(vu_dev->irq, vq); 933 + um_free_irq(irq, vq); 942 934 close_both: 943 935 os_close_file(call_fds[0]); 944 936 out: ··· 1039 1023 struct virtqueue *vq; 1040 1024 1041 1025 /* not supported for now */ 1042 - if (WARN_ON(nvqs > 64)) 1026 + if (WARN(nvqs > 64 || nvqs > vu_dev->max_vqs, 1027 + "%d VQs requested, only up to 64 or %lld supported\n", 1028 + nvqs, vu_dev->max_vqs)) 1043 1029 return -EINVAL; 1044 1030 1045 1031 rc = vhost_user_set_mem_table(vu_dev); ··· 1228 1210 vu_dev->vdev.id.vendor = VIRTIO_DEV_ANY_ID; 1229 1211 vu_dev->pdev = pdev; 1230 1212 vu_dev->req_fd = -1; 1213 + vu_dev->irq = UM_IRQ_ALLOC; 1231 1214 1232 1215 time_travel_propagate_time(); 1233 1216
-1
arch/um/include/asm/Kbuild
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 generic-y += bug.h 3 3 generic-y += compat.h 4 - generic-y += current.h 5 4 generic-y += device.h 6 5 generic-y += dma-mapping.h 7 6 generic-y += emergency-restart.h
+23
arch/um/include/asm/current.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __ASM_CURRENT_H 3 + #define __ASM_CURRENT_H 4 + 5 + #include <linux/compiler.h> 6 + #include <linux/threads.h> 7 + 8 + #ifndef __ASSEMBLY__ 9 + 10 + struct task_struct; 11 + extern struct task_struct *cpu_tasks[NR_CPUS]; 12 + 13 + static __always_inline struct task_struct *get_current(void) 14 + { 15 + return cpu_tasks[0]; 16 + } 17 + 18 + 19 + #define current get_current() 20 + 21 + #endif /* __ASSEMBLY__ */ 22 + 23 + #endif /* __ASM_CURRENT_H */
+12 -28
arch/um/include/asm/page.h
··· 29 29 #define clear_user_page(page, vaddr, pg) clear_page(page) 30 30 #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) 31 31 32 - #if defined(CONFIG_3_LEVEL_PGTABLES) && !defined(CONFIG_64BIT) 33 - 34 - typedef struct { unsigned long pte; } pte_t; 35 - typedef struct { unsigned long pmd; } pmd_t; 36 - typedef struct { unsigned long pgd; } pgd_t; 37 - #define pte_val(p) ((p).pte) 38 - 39 - #define pte_get_bits(p, bits) ((p).pte & (bits)) 40 - #define pte_set_bits(p, bits) ((p).pte |= (bits)) 41 - #define pte_clear_bits(p, bits) ((p).pte &= ~(bits)) 42 - #define pte_copy(to, from) ({ (to).pte = (from).pte; }) 43 - #define pte_is_zero(p) (!((p).pte & ~_PAGE_NEWPAGE)) 44 - #define pte_set_val(p, phys, prot) \ 45 - ({ (p).pte = (phys) | pgprot_val(prot); }) 46 - 47 - #define pmd_val(x) ((x).pmd) 48 - #define __pmd(x) ((pmd_t) { (x) } ) 49 - 50 - typedef unsigned long long phys_t; 51 - 52 - #else 53 - 54 32 typedef struct { unsigned long pte; } pte_t; 55 33 typedef struct { unsigned long pgd; } pgd_t; 56 34 57 - #ifdef CONFIG_3_LEVEL_PGTABLES 35 + #if CONFIG_PGTABLE_LEVELS > 2 36 + 58 37 typedef struct { unsigned long pmd; } pmd_t; 59 38 #define pmd_val(x) ((x).pmd) 60 39 #define __pmd(x) ((pmd_t) { (x) } ) 61 - #endif 40 + 41 + #if CONFIG_PGTABLE_LEVELS > 3 42 + 43 + typedef struct { unsigned long pud; } pud_t; 44 + #define pud_val(x) ((x).pud) 45 + #define __pud(x) ((pud_t) { (x) } ) 46 + 47 + #endif /* CONFIG_PGTABLE_LEVELS > 3 */ 48 + #endif /* CONFIG_PGTABLE_LEVELS > 2 */ 62 49 63 50 #define pte_val(x) ((x).pte) 64 - 65 51 66 52 #define pte_get_bits(p, bits) ((p).pte & (bits)) 67 53 #define pte_set_bits(p, bits) ((p).pte |= (bits)) 68 54 #define pte_clear_bits(p, bits) ((p).pte &= ~(bits)) 69 55 #define pte_copy(to, from) ((to).pte = (from).pte) 70 - #define pte_is_zero(p) (!((p).pte & ~_PAGE_NEWPAGE)) 56 + #define pte_is_zero(p) (!((p).pte & ~_PAGE_NEEDSYNC)) 71 57 #define pte_set_val(p, phys, prot) (p).pte = (phys | pgprot_val(prot)) 72 58 73 59 typedef unsigned long phys_t; 74 - 75 - #endif 76 60 77 61 typedef struct { unsigned long pgprot; } pgprot_t; 78 62
+10 -1
arch/um/include/asm/pgalloc.h
··· 31 31 tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \ 32 32 } while (0) 33 33 34 - #ifdef CONFIG_3_LEVEL_PGTABLES 34 + #if CONFIG_PGTABLE_LEVELS > 2 35 35 36 36 #define __pmd_free_tlb(tlb, pmd, address) \ 37 37 do { \ ··· 39 39 tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pmd)); \ 40 40 } while (0) 41 41 42 + #if CONFIG_PGTABLE_LEVELS > 3 43 + 44 + #define __pud_free_tlb(tlb, pud, address) \ 45 + do { \ 46 + pagetable_pud_dtor(virt_to_ptdesc(pud)); \ 47 + tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pud)); \ 48 + } while (0) 49 + 50 + #endif 42 51 #endif 43 52 44 53 #endif
+1 -1
arch/um/include/asm/pgtable-2level.h
··· 31 31 printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), \ 32 32 pgd_val(e)) 33 33 34 - static inline int pgd_newpage(pgd_t pgd) { return 0; } 34 + static inline int pgd_needsync(pgd_t pgd) { return 0; } 35 35 static inline void pgd_mkuptodate(pgd_t pgd) { } 36 36 37 37 #define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
+39 -20
arch/um/include/asm/pgtable-3level.h arch/um/include/asm/pgtable-4level.h
··· 4 4 * Derived from include/asm-i386/pgtable.h 5 5 */ 6 6 7 - #ifndef __UM_PGTABLE_3LEVEL_H 8 - #define __UM_PGTABLE_3LEVEL_H 7 + #ifndef __UM_PGTABLE_4LEVEL_H 8 + #define __UM_PGTABLE_4LEVEL_H 9 9 10 - #include <asm-generic/pgtable-nopud.h> 10 + #include <asm-generic/pgtable-nop4d.h> 11 11 12 - /* PGDIR_SHIFT determines what a third-level page table entry can map */ 12 + /* PGDIR_SHIFT determines what a fourth-level page table entry can map */ 13 13 14 - #ifdef CONFIG_64BIT 15 - #define PGDIR_SHIFT 30 16 - #else 17 - #define PGDIR_SHIFT 31 18 - #endif 14 + #define PGDIR_SHIFT 39 19 15 #define PGDIR_SIZE (1UL << PGDIR_SHIFT) 20 16 #define PGDIR_MASK (~(PGDIR_SIZE-1)) 17 + 18 + /* PUD_SHIFT determines the size of the area a third-level page table can 19 + * map 20 + */ 21 + 22 + #define PUD_SHIFT 30 23 + #define PUD_SIZE (1UL << PUD_SHIFT) 24 + #define PUD_MASK (~(PUD_SIZE-1)) 21 25 22 26 /* PMD_SHIFT determines the size of the area a second-level page table can 23 27 * map ··· 36 32 */ 37 33 38 34 #define PTRS_PER_PTE 512 39 - #ifdef CONFIG_64BIT 40 35 #define PTRS_PER_PMD 512 36 + #define PTRS_PER_PUD 512 41 37 #define PTRS_PER_PGD 512 42 - #else 43 - #define PTRS_PER_PMD 1024 44 - #define PTRS_PER_PGD 1024 45 - #endif 46 38 47 39 #define USER_PTRS_PER_PGD ((TASK_SIZE + (PGDIR_SIZE - 1)) / PGDIR_SIZE) 48 40 ··· 48 48 #define pmd_ERROR(e) \ 49 49 printk("%s:%d: bad pmd %p(%016lx).\n", __FILE__, __LINE__, &(e), \ 50 50 pmd_val(e)) 51 + #define pud_ERROR(e) \ 52 + printk("%s:%d: bad pud %p(%016lx).\n", __FILE__, __LINE__, &(e), \ 53 + pud_val(e)) 51 54 #define pgd_ERROR(e) \ 52 55 printk("%s:%d: bad pgd %p(%016lx).\n", __FILE__, __LINE__, &(e), \ 53 56 pgd_val(e)) 54 57 55 - #define pud_none(x) (!(pud_val(x) & ~_PAGE_NEWPAGE)) 58 + #define pud_none(x) (!(pud_val(x) & ~_PAGE_NEEDSYNC)) 56 59 #define pud_bad(x) ((pud_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) 57 60 #define pud_present(x) (pud_val(x) & _PAGE_PRESENT) 58 61 #define pud_populate(mm, pud, pmd) \ ··· 63 60 64 61 #define set_pud(pudptr, pudval) (*(pudptr) = (pudval)) 65 62 66 - static inline int pgd_newpage(pgd_t pgd) 63 + #define p4d_none(x) (!(p4d_val(x) & ~_PAGE_NEEDSYNC)) 64 + #define p4d_bad(x) ((p4d_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) 65 + #define p4d_present(x) (p4d_val(x) & _PAGE_PRESENT) 66 + #define p4d_populate(mm, p4d, pud) \ 67 + set_p4d(p4d, __p4d(_PAGE_TABLE + __pa(pud))) 68 + 69 + #define set_p4d(p4dptr, p4dval) (*(p4dptr) = (p4dval)) 70 + 71 + 72 + static inline int pgd_needsync(pgd_t pgd) 67 73 { 68 - return(pgd_val(pgd) & _PAGE_NEWPAGE); 74 + return pgd_val(pgd) & _PAGE_NEEDSYNC; 69 75 } 70 76 71 - static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEWPAGE; } 77 + static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEEDSYNC; } 72 78 73 79 #define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval)) 74 80 75 81 static inline void pud_clear (pud_t *pud) 76 82 { 77 - set_pud(pud, __pud(_PAGE_NEWPAGE)); 83 + set_pud(pud, __pud(_PAGE_NEEDSYNC)); 84 + } 85 + 86 + static inline void p4d_clear (p4d_t *p4d) 87 + { 88 + set_p4d(p4d, __p4d(_PAGE_NEEDSYNC)); 78 89 } 79 90 80 91 #define pud_page(pud) phys_to_page(pud_val(pud) & PAGE_MASK) 81 92 #define pud_pgtable(pud) ((pmd_t *) __va(pud_val(pud) & PAGE_MASK)) 93 + 94 + #define p4d_page(p4d) phys_to_page(p4d_val(p4d) & PAGE_MASK) 95 + #define p4d_pgtable(p4d) ((pud_t *) __va(p4d_val(p4d) & PAGE_MASK)) 82 96 83 97 static inline unsigned long pte_pfn(pte_t pte) 84 98 { ··· 117 97 } 118 98 119 99 #endif 120 -
+30 -53
arch/um/include/asm/pgtable.h
··· 11 11 #include <asm/fixmap.h> 12 12 13 13 #define _PAGE_PRESENT 0x001 14 - #define _PAGE_NEWPAGE 0x002 15 - #define _PAGE_NEWPROT 0x004 14 + #define _PAGE_NEEDSYNC 0x002 16 15 #define _PAGE_RW 0x020 17 16 #define _PAGE_USER 0x040 18 17 #define _PAGE_ACCESSED 0x080 ··· 23 24 /* We borrow bit 10 to store the exclusive marker in swap PTEs. */ 24 25 #define _PAGE_SWP_EXCLUSIVE 0x400 25 26 26 - #ifdef CONFIG_3_LEVEL_PGTABLES 27 - #include <asm/pgtable-3level.h> 28 - #else 27 + #if CONFIG_PGTABLE_LEVELS == 4 28 + #include <asm/pgtable-4level.h> 29 + #elif CONFIG_PGTABLE_LEVELS == 2 29 30 #include <asm/pgtable-2level.h> 31 + #else 32 + #error "Unsupported number of page table levels" 30 33 #endif 31 34 32 35 extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; ··· 79 78 */ 80 79 #define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page) 81 80 82 - #define pte_clear(mm,addr,xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEWPAGE)) 81 + #define pte_clear(mm, addr, xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEEDSYNC)) 83 82 84 - #define pmd_none(x) (!((unsigned long)pmd_val(x) & ~_PAGE_NEWPAGE)) 83 + #define pmd_none(x) (!((unsigned long)pmd_val(x) & ~_PAGE_NEEDSYNC)) 85 84 #define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) 86 85 87 86 #define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) 88 - #define pmd_clear(xp) do { pmd_val(*(xp)) = _PAGE_NEWPAGE; } while (0) 87 + #define pmd_clear(xp) do { pmd_val(*(xp)) = _PAGE_NEEDSYNC; } while (0) 89 88 90 - #define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE) 91 - #define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE) 89 + #define pmd_needsync(x) (pmd_val(x) & _PAGE_NEEDSYNC) 90 + #define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEEDSYNC) 92 91 93 - #define pud_newpage(x) (pud_val(x) & _PAGE_NEWPAGE) 94 - #define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEWPAGE) 92 + #define pud_needsync(x) (pud_val(x) & _PAGE_NEEDSYNC) 93 + #define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEEDSYNC) 95 94 96 - #define p4d_newpage(x) (p4d_val(x) & _PAGE_NEWPAGE) 97 - #define p4d_mkuptodate(x) (p4d_val(x) &= ~_PAGE_NEWPAGE) 95 + #define p4d_needsync(x) (p4d_val(x) & _PAGE_NEEDSYNC) 96 + #define p4d_mkuptodate(x) (p4d_val(x) &= ~_PAGE_NEEDSYNC) 98 97 99 98 #define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT) 100 99 #define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK) ··· 145 144 return pte_get_bits(pte, _PAGE_ACCESSED); 146 145 } 147 146 148 - static inline int pte_newpage(pte_t pte) 147 + static inline int pte_needsync(pte_t pte) 149 148 { 150 - return pte_get_bits(pte, _PAGE_NEWPAGE); 151 - } 152 - 153 - static inline int pte_newprot(pte_t pte) 154 - { 155 - return(pte_present(pte) && (pte_get_bits(pte, _PAGE_NEWPROT))); 149 + return pte_get_bits(pte, _PAGE_NEEDSYNC); 156 150 } 157 151 158 152 /* ··· 155 159 * Flags setting section. 156 160 * ================================= 157 161 */ 158 - 159 - static inline pte_t pte_mknewprot(pte_t pte) 160 - { 161 - pte_set_bits(pte, _PAGE_NEWPROT); 162 - return(pte); 163 - } 164 162 165 163 static inline pte_t pte_mkclean(pte_t pte) 166 164 { ··· 170 180 171 181 static inline pte_t pte_wrprotect(pte_t pte) 172 182 { 173 - if (likely(pte_get_bits(pte, _PAGE_RW))) 174 - pte_clear_bits(pte, _PAGE_RW); 175 - else 176 - return pte; 177 - return(pte_mknewprot(pte)); 183 + pte_clear_bits(pte, _PAGE_RW); 184 + return pte; 178 185 } 179 186 180 187 static inline pte_t pte_mkread(pte_t pte) 181 188 { 182 - if (unlikely(pte_get_bits(pte, _PAGE_USER))) 183 - return pte; 184 189 pte_set_bits(pte, _PAGE_USER); 185 - return(pte_mknewprot(pte)); 190 + return pte; 186 191 } 187 192 188 193 static inline pte_t pte_mkdirty(pte_t pte) ··· 194 209 195 210 static inline pte_t pte_mkwrite_novma(pte_t pte) 196 211 { 197 - if (unlikely(pte_get_bits(pte, _PAGE_RW))) 198 - return pte; 199 212 pte_set_bits(pte, _PAGE_RW); 200 - return(pte_mknewprot(pte)); 213 + return pte; 201 214 } 202 215 203 216 static inline pte_t pte_mkuptodate(pte_t pte) 204 217 { 205 - pte_clear_bits(pte, _PAGE_NEWPAGE); 206 - if(pte_present(pte)) 207 - pte_clear_bits(pte, _PAGE_NEWPROT); 208 - return(pte); 218 + pte_clear_bits(pte, _PAGE_NEEDSYNC); 219 + return pte; 209 220 } 210 221 211 - static inline pte_t pte_mknewpage(pte_t pte) 222 + static inline pte_t pte_mkneedsync(pte_t pte) 212 223 { 213 - pte_set_bits(pte, _PAGE_NEWPAGE); 224 + pte_set_bits(pte, _PAGE_NEEDSYNC); 214 225 return(pte); 215 226 } 216 227 ··· 214 233 { 215 234 pte_copy(*pteptr, pteval); 216 235 217 - /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so 218 - * fix_range knows to unmap it. _PAGE_NEWPROT is specific to 219 - * mapped pages. 236 + /* If it's a swap entry, it needs to be marked _PAGE_NEEDSYNC so 237 + * update_pte_range knows to unmap it. 220 238 */ 221 239 222 - *pteptr = pte_mknewpage(*pteptr); 223 - if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr); 240 + *pteptr = pte_mkneedsync(*pteptr); 224 241 } 225 242 226 243 #define PFN_PTE_SHIFT PAGE_SHIFT ··· 258 279 #define __HAVE_ARCH_PTE_SAME 259 280 static inline int pte_same(pte_t pte_a, pte_t pte_b) 260 281 { 261 - return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEWPAGE); 282 + return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEEDSYNC); 262 283 } 263 284 264 285 /* ··· 273 294 ({ pte_t pte; \ 274 295 \ 275 296 pte_set_val(pte, page_to_phys(page), (pgprot)); \ 276 - if (pte_present(pte)) \ 277 - pte_mknewprot(pte_mknewpage(pte)); \ 278 297 pte;}) 279 298 280 299 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) ··· 306 329 * <--------------- offset ----------------> E < type -> 0 0 0 1 0 307 330 * 308 331 * E is the exclusive marker that is not stored in swap entries. 309 - * _PAGE_NEWPAGE (bit 1) is always set to 1 in set_pte(). 332 + * _PAGE_NEEDSYNC (bit 1) is always set to 1 in set_pte(). 310 333 */ 311 334 #define __swp_type(x) (((x).val >> 5) & 0x1f) 312 335 #define __swp_offset(x) ((x).val >> 11)
+3 -4
arch/um/include/asm/processor-generic.h
··· 20 20 struct mm_struct; 21 21 22 22 struct thread_struct { 23 - struct pt_regs regs; 24 23 struct pt_regs *segv_regs; 25 - void *fault_addr; 26 - jmp_buf *fault_catcher; 27 24 struct task_struct *prev_sched; 28 25 struct arch_thread arch; 29 26 jmp_buf switch_buf; ··· 30 33 void *arg; 31 34 } thread; 32 35 } request; 36 + 37 + /* Contains variable sized FP registers */ 38 + struct pt_regs regs; 33 39 }; 34 40 35 41 #define INIT_THREAD \ 36 42 { \ 37 43 .regs = EMPTY_REGS, \ 38 - .fault_addr = NULL, \ 39 44 .prev_sched = NULL, \ 40 45 .arch = INIT_ARCH_THREAD, \ 41 46 .request = { } \
-18
arch/um/include/asm/thread_info.h
··· 17 17 #include <sysdep/ptrace_user.h> 18 18 19 19 struct thread_info { 20 - struct task_struct *task; /* main task structure */ 21 20 unsigned long flags; /* low level flags */ 22 21 __u32 cpu; /* current CPU */ 23 22 int preempt_count; /* 0 => preemptable, 24 23 <0 => BUG */ 25 - struct thread_info *real_thread; /* Points to non-IRQ stack */ 26 - unsigned long aux_fp_regs[FP_SIZE]; /* auxiliary fp_regs to save/restore 27 - them out-of-band */ 28 24 }; 29 25 30 26 #define INIT_THREAD_INFO(tsk) \ 31 27 { \ 32 - .task = &tsk, \ 33 28 .flags = 0, \ 34 29 .cpu = 0, \ 35 30 .preempt_count = INIT_PREEMPT_COUNT, \ 36 - .real_thread = NULL, \ 37 - } 38 - 39 - /* how to get the thread information struct from C */ 40 - static inline struct thread_info *current_thread_info(void) 41 - { 42 - struct thread_info *ti; 43 - unsigned long mask = THREAD_SIZE - 1; 44 - void *p; 45 - 46 - asm volatile ("" : "=r" (p) : "0" (&ti)); 47 - ti = (struct thread_info *) (((unsigned long)p) & ~mask); 48 - return ti; 49 31 } 50 32 51 33 #endif
+2 -2
arch/um/include/asm/tlbflush.h
··· 9 9 #include <linux/mm.h> 10 10 11 11 /* 12 - * In UML, we need to sync the TLB over by using mmap/munmap/mprotect syscalls 13 - * from the process handling the MM (which can be the kernel itself). 12 + * In UML, we need to sync the TLB over by using mmap/munmap syscalls from 13 + * the process handling the MM (which can be the kernel itself). 14 14 * 15 15 * To track updates, we can hook into set_ptes and flush_tlb_*. With set_ptes 16 16 * we catch all PTE transitions where memory that was unusable becomes usable.
+4 -6
arch/um/include/shared/as-layout.h
··· 30 30 31 31 #include <sysdep/ptrace.h> 32 32 33 - struct cpu_task { 34 - void *task; 35 - }; 33 + struct task_struct; 34 + extern struct task_struct *cpu_tasks[]; 36 35 37 - extern struct cpu_task cpu_tasks[]; 36 + extern unsigned long long physmem_size; 38 37 39 38 extern unsigned long high_physmem; 40 39 extern unsigned long uml_physmem; 41 40 extern unsigned long uml_reserved; 42 41 extern unsigned long end_vm; 43 42 extern unsigned long start_vm; 44 - extern unsigned long long highmem; 45 43 46 44 extern unsigned long brk_start; 47 45 48 46 extern unsigned long host_task_size; 49 47 extern unsigned long stub_start; 50 48 51 - extern int linux_main(int argc, char **argv); 49 + extern int linux_main(int argc, char **argv, char **envp); 52 50 extern void uml_finishsetup(void); 53 51 54 52 struct siginfo;
-15
arch/um/include/shared/common-offsets.h
··· 6 6 DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE); 7 7 DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK); 8 8 DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT); 9 - DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); 10 9 11 10 DEFINE(UM_GFP_KERNEL, GFP_KERNEL); 12 11 DEFINE(UM_GFP_ATOMIC, GFP_ATOMIC); ··· 14 15 15 16 DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); 16 17 DEFINE(UM_NSEC_PER_USEC, NSEC_PER_USEC); 17 - 18 - #ifdef CONFIG_PRINTK 19 - DEFINE(UML_CONFIG_PRINTK, CONFIG_PRINTK); 20 - #endif 21 - #ifdef CONFIG_UML_X86 22 - DEFINE(UML_CONFIG_UML_X86, CONFIG_UML_X86); 23 - #endif 24 - #ifdef CONFIG_64BIT 25 - DEFINE(UML_CONFIG_64BIT, CONFIG_64BIT); 26 - #endif 27 - #ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT 28 - DEFINE(UML_CONFIG_UML_TIME_TRAVEL_SUPPORT, CONFIG_UML_TIME_TRAVEL_SUPPORT); 29 - #endif 30 -
-1
arch/um/include/shared/kern_util.h
··· 60 60 extern int singlestepping(void); 61 61 62 62 extern void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); 63 - extern void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs); 64 63 extern void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); 65 64 extern void fatal_sigsegv(void) __attribute__ ((noreturn)); 66 65
+2 -3
arch/um/include/shared/mem_user.h
··· 47 47 #define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1)) 48 48 49 49 extern unsigned long find_iomem(char *driver, unsigned long *len_out); 50 - extern void mem_total_pages(unsigned long physmem, unsigned long iomem, 51 - unsigned long highmem); 50 + extern void mem_total_pages(unsigned long physmem, unsigned long iomem); 52 51 extern void setup_physmem(unsigned long start, unsigned long usable, 53 - unsigned long len, unsigned long long highmem); 52 + unsigned long len); 54 53 extern void map_memory(unsigned long virt, unsigned long phys, 55 54 unsigned long len, int r, int w, int x); 56 55
+3 -12
arch/um/include/shared/os.h
··· 145 145 extern int os_get_ifname(int fd, char *namebuf); 146 146 extern int os_set_slip(int fd); 147 147 extern int os_mode_fd(int fd, int mode); 148 - extern int os_fsync_file(int fd); 149 148 150 149 extern int os_seek_file(int fd, unsigned long long offset); 151 150 extern int os_open_file(const char *file, struct openflags flags, int mode); ··· 198 199 extern void report_enomem(void); 199 200 200 201 /* process.c */ 201 - extern unsigned long os_process_pc(int pid); 202 - extern int os_process_parent(int pid); 203 202 extern void os_alarm_process(int pid); 204 - extern void os_stop_process(int pid); 205 203 extern void os_kill_process(int pid, int reap_child); 206 204 extern void os_kill_ptraced_process(int pid, int reap_child); 207 205 208 206 extern int os_getpid(void); 209 - extern int os_getpgrp(void); 210 207 211 208 extern void init_new_thread_signals(void); 212 209 ··· 214 219 extern int os_drop_memory(void *addr, int length); 215 220 extern int can_drop_memory(void); 216 221 extern int os_mincore(void *addr, unsigned long len); 222 + 223 + void os_set_pdeathsig(void); 217 224 218 225 /* execvp.c */ 219 226 extern int execvp_noalloc(char *buf, const char *file, char *const argv[]); ··· 241 244 extern void unblock_signals(void); 242 245 extern int um_set_signals(int enable); 243 246 extern int um_set_signals_trace(int enable); 244 - extern int os_is_signal_stack(void); 245 247 extern void deliver_alarm(void); 246 248 extern void register_pm_wake_signal(void); 247 249 extern void block_signals_hard(void); ··· 279 283 unsigned long len, int prot, int phys_fd, 280 284 unsigned long long offset); 281 285 int unmap(struct mm_id *mm_idp, unsigned long addr, unsigned long len); 282 - int protect(struct mm_id *mm_idp, unsigned long addr, 283 - unsigned long len, unsigned int prot); 284 286 285 287 /* skas/process.c */ 286 288 extern int is_skas_winch(int pid, int fd, void *data); 287 289 extern int start_userspace(unsigned long stub_stack); 288 - extern void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs); 290 + extern void userspace(struct uml_pt_regs *regs); 289 291 extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); 290 292 extern void switch_threads(jmp_buf *me, jmp_buf *you); 291 293 extern int start_idle_thread(void *stack, jmp_buf *switch_buf); ··· 322 328 323 329 /* tty.c */ 324 330 extern int get_pty(void); 325 - 326 - /* sys-$ARCH/task_size.c */ 327 - extern unsigned long os_get_top_address(void); 328 331 329 332 long syscall(long number, ...); 330 333
-6
arch/um/include/shared/registers.h
··· 8 8 9 9 #include <sysdep/ptrace.h> 10 10 11 - extern int save_i387_registers(int pid, unsigned long *fp_regs); 12 - extern int restore_i387_registers(int pid, unsigned long *fp_regs); 13 - extern int save_fp_registers(int pid, unsigned long *fp_regs); 14 - extern int restore_fp_registers(int pid, unsigned long *fp_regs); 15 - extern int save_fpx_registers(int pid, unsigned long *fp_regs); 16 - extern int restore_fpx_registers(int pid, unsigned long *fp_regs); 17 11 extern int init_pid_registers(int pid); 18 12 extern void get_safe_registers(unsigned long *regs, unsigned long *fp_regs); 19 13 extern int get_fp_registers(int pid, unsigned long *regs);
+11 -1
arch/um/include/shared/skas/stub-data.h
··· 12 12 #include <as-layout.h> 13 13 #include <sysdep/tls.h> 14 14 15 + struct stub_init_data { 16 + unsigned long stub_start; 17 + 18 + int stub_code_fd; 19 + unsigned long stub_code_offset; 20 + int stub_data_fd; 21 + unsigned long stub_data_offset; 22 + 23 + unsigned long segv_handler; 24 + }; 25 + 15 26 #define STUB_NEXT_SYSCALL(s) \ 16 27 ((struct stub_syscall *) (((unsigned long) s) + (s)->cmd_len)) 17 28 ··· 30 19 STUB_SYSCALL_UNSET = 0, 31 20 STUB_SYSCALL_MMAP, 32 21 STUB_SYSCALL_MUNMAP, 33 - STUB_SYSCALL_MPROTECT, 34 22 }; 35 23 36 24 struct stub_syscall {
+2 -3
arch/um/include/shared/timetravel.h
··· 12 12 TT_MODE_EXTERNAL, 13 13 }; 14 14 15 - #if defined(UML_CONFIG_UML_TIME_TRAVEL_SUPPORT) || \ 16 - defined(CONFIG_UML_TIME_TRAVEL_SUPPORT) 15 + #if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT) 17 16 extern enum time_travel_mode time_travel_mode; 18 17 extern int time_travel_should_print_bc_msg; 19 18 #else 20 19 #define time_travel_mode TT_MODE_OFF 21 20 #define time_travel_should_print_bc_msg 0 22 - #endif /* (UML_)CONFIG_UML_TIME_TRAVEL_SUPPORT */ 21 + #endif /* CONFIG_UML_TIME_TRAVEL_SUPPORT */ 23 22 24 23 void _time_travel_print_bc_msg(void); 25 24 static inline void time_travel_print_bc_msg(void)
+1 -1
arch/um/include/shared/user.h
··· 38 38 #define UM_KERN_DEBUG KERN_DEBUG 39 39 #define UM_KERN_CONT KERN_CONT 40 40 41 - #ifdef UML_CONFIG_PRINTK 41 + #if IS_ENABLED(CONFIG_PRINTK) 42 42 #define printk(...) _printk(__VA_ARGS__) 43 43 extern int _printk(const char *fmt, ...) 44 44 __attribute__ ((format (printf, 1, 2)));
+1
arch/um/kernel/dtb.c
··· 31 31 32 32 static int __init uml_dtb_setup(char *line, int *add) 33 33 { 34 + *add = 0; 34 35 dtb = line; 35 36 return 0; 36 37 }
+3 -2
arch/um/kernel/dyn.lds.S
··· 116 116 .fini_array : { *(.fini_array) } 117 117 .data : { 118 118 INIT_TASK_DATA(KERNEL_STACK_SIZE) 119 - . = ALIGN(KERNEL_STACK_SIZE); 120 - *(.data..init_irqstack) 121 119 DATA_DATA 122 120 *(.data.* .gnu.linkonce.d.*) 123 121 SORT(CONSTRUCTORS) ··· 176 178 177 179 DISCARDS 178 180 } 181 + 182 + ASSERT(__syscall_stub_end - __syscall_stub_start <= PAGE_SIZE, 183 + "STUB code must not be larger than one page");
+1
arch/um/kernel/initrd.c
··· 34 34 35 35 static int __init uml_initrd_setup(char *line, int *add) 36 36 { 37 + *add = 0; 37 38 initrd = line; 38 39 return 0; 39 40 }
-112
arch/um/kernel/irq.c
··· 674 674 /* Initialize EPOLL Loop */ 675 675 os_setup_epoll(); 676 676 } 677 - 678 - /* 679 - * IRQ stack entry and exit: 680 - * 681 - * Unlike i386, UML doesn't receive IRQs on the normal kernel stack 682 - * and switch over to the IRQ stack after some preparation. We use 683 - * sigaltstack to receive signals on a separate stack from the start. 684 - * These two functions make sure the rest of the kernel won't be too 685 - * upset by being on a different stack. The IRQ stack has a 686 - * thread_info structure at the bottom so that current et al continue 687 - * to work. 688 - * 689 - * to_irq_stack copies the current task's thread_info to the IRQ stack 690 - * thread_info and sets the tasks's stack to point to the IRQ stack. 691 - * 692 - * from_irq_stack copies the thread_info struct back (flags may have 693 - * been modified) and resets the task's stack pointer. 694 - * 695 - * Tricky bits - 696 - * 697 - * What happens when two signals race each other? UML doesn't block 698 - * signals with sigprocmask, SA_DEFER, or sa_mask, so a second signal 699 - * could arrive while a previous one is still setting up the 700 - * thread_info. 701 - * 702 - * There are three cases - 703 - * The first interrupt on the stack - sets up the thread_info and 704 - * handles the interrupt 705 - * A nested interrupt interrupting the copying of the thread_info - 706 - * can't handle the interrupt, as the stack is in an unknown state 707 - * A nested interrupt not interrupting the copying of the 708 - * thread_info - doesn't do any setup, just handles the interrupt 709 - * 710 - * The first job is to figure out whether we interrupted stack setup. 711 - * This is done by xchging the signal mask with thread_info->pending. 712 - * If the value that comes back is zero, then there is no setup in 713 - * progress, and the interrupt can be handled. If the value is 714 - * non-zero, then there is stack setup in progress. In order to have 715 - * the interrupt handled, we leave our signal in the mask, and it will 716 - * be handled by the upper handler after it has set up the stack. 717 - * 718 - * Next is to figure out whether we are the outer handler or a nested 719 - * one. As part of setting up the stack, thread_info->real_thread is 720 - * set to non-NULL (and is reset to NULL on exit). This is the 721 - * nesting indicator. If it is non-NULL, then the stack is already 722 - * set up and the handler can run. 723 - */ 724 - 725 - static unsigned long pending_mask; 726 - 727 - unsigned long to_irq_stack(unsigned long *mask_out) 728 - { 729 - struct thread_info *ti; 730 - unsigned long mask, old; 731 - int nested; 732 - 733 - mask = xchg(&pending_mask, *mask_out); 734 - if (mask != 0) { 735 - /* 736 - * If any interrupts come in at this point, we want to 737 - * make sure that their bits aren't lost by our 738 - * putting our bit in. So, this loop accumulates bits 739 - * until xchg returns the same value that we put in. 740 - * When that happens, there were no new interrupts, 741 - * and pending_mask contains a bit for each interrupt 742 - * that came in. 743 - */ 744 - old = *mask_out; 745 - do { 746 - old |= mask; 747 - mask = xchg(&pending_mask, old); 748 - } while (mask != old); 749 - return 1; 750 - } 751 - 752 - ti = current_thread_info(); 753 - nested = (ti->real_thread != NULL); 754 - if (!nested) { 755 - struct task_struct *task; 756 - struct thread_info *tti; 757 - 758 - task = cpu_tasks[ti->cpu].task; 759 - tti = task_thread_info(task); 760 - 761 - *ti = *tti; 762 - ti->real_thread = tti; 763 - task->stack = ti; 764 - } 765 - 766 - mask = xchg(&pending_mask, 0); 767 - *mask_out |= mask | nested; 768 - return 0; 769 - } 770 - 771 - unsigned long from_irq_stack(int nested) 772 - { 773 - struct thread_info *ti, *to; 774 - unsigned long mask; 775 - 776 - ti = current_thread_info(); 777 - 778 - pending_mask = 1; 779 - 780 - to = ti->real_thread; 781 - current->stack = to; 782 - ti->real_thread = NULL; 783 - *to = *ti; 784 - 785 - mask = xchg(&pending_mask, 0); 786 - return mask & ~1; 787 - } 788 -
+16 -4
arch/um/kernel/mem.c
··· 6 6 #include <linux/stddef.h> 7 7 #include <linux/module.h> 8 8 #include <linux/memblock.h> 9 - #include <linux/highmem.h> 10 9 #include <linux/mm.h> 11 10 #include <linux/swap.h> 12 11 #include <linux/slab.h> ··· 50 51 pgd_t swapper_pg_dir[PTRS_PER_PGD]; 51 52 52 53 /* Initialized at boot time, and readonly after that */ 53 - unsigned long long highmem; 54 - EXPORT_SYMBOL(highmem); 55 54 int kmalloc_ok = 0; 56 55 57 56 /* Used during early boot */ ··· 95 98 96 99 static void __init one_md_table_init(pud_t *pud) 97 100 { 98 - #ifdef CONFIG_3_LEVEL_PGTABLES 101 + #if CONFIG_PGTABLE_LEVELS > 2 99 102 pmd_t *pmd_table = (pmd_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE); 100 103 if (!pmd_table) 101 104 panic("%s: Failed to allocate %lu bytes align=%lx\n", ··· 103 106 104 107 set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table))); 105 108 BUG_ON(pmd_table != pmd_offset(pud, 0)); 109 + #endif 110 + } 111 + 112 + static void __init one_ud_table_init(p4d_t *p4d) 113 + { 114 + #if CONFIG_PGTABLE_LEVELS > 3 115 + pud_t *pud_table = (pud_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE); 116 + if (!pud_table) 117 + panic("%s: Failed to allocate %lu bytes align=%lx\n", 118 + __func__, PAGE_SIZE, PAGE_SIZE); 119 + 120 + set_p4d(p4d, __p4d(_KERNPG_TABLE + (unsigned long) __pa(pud_table))); 121 + BUG_ON(pud_table != pud_offset(p4d, 0)); 106 122 #endif 107 123 } 108 124 ··· 136 126 137 127 for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { 138 128 p4d = p4d_offset(pgd, vaddr); 129 + if (p4d_none(*p4d)) 130 + one_ud_table_init(p4d); 139 131 pud = pud_offset(p4d, vaddr); 140 132 if (pud_none(*pud)) 141 133 one_md_table_init(pud);
+15 -24
arch/um/kernel/physmem.c
··· 22 22 unsigned long high_physmem; 23 23 EXPORT_SYMBOL(high_physmem); 24 24 25 - extern unsigned long long physmem_size; 26 - 27 - void __init mem_total_pages(unsigned long physmem, unsigned long iomem, 28 - unsigned long highmem) 25 + void __init mem_total_pages(unsigned long physmem, unsigned long iomem) 29 26 { 30 - unsigned long phys_pages, highmem_pages; 31 - unsigned long iomem_pages, total_pages; 27 + unsigned long phys_pages, iomem_pages, total_pages; 32 28 33 - phys_pages = physmem >> PAGE_SHIFT; 34 - iomem_pages = iomem >> PAGE_SHIFT; 35 - highmem_pages = highmem >> PAGE_SHIFT; 29 + phys_pages = physmem >> PAGE_SHIFT; 30 + iomem_pages = iomem >> PAGE_SHIFT; 36 31 37 - total_pages = phys_pages + iomem_pages + highmem_pages; 32 + total_pages = phys_pages + iomem_pages; 38 33 39 34 max_mapnr = total_pages; 40 35 } ··· 59 64 * @reserve_end: end address of the physical kernel memory. 60 65 * @len: Length of total physical memory that should be mapped/made 61 66 * available, in bytes. 62 - * @highmem: Number of highmem bytes that should be mapped/made available. 63 67 * 64 - * Creates an unlinked temporary file of size (len + highmem) and memory maps 68 + * Creates an unlinked temporary file of size (len) and memory maps 65 69 * it on the last executable image address (uml_reserved). 66 70 * 67 71 * The offset is needed as the length of the total physical memory 68 - * (len + highmem) includes the size of the memory used be the executable image, 72 + * (len) includes the size of the memory used be the executable image, 69 73 * but the mapped-to address is the last address of the executable image 70 74 * (uml_reserved == end address of executable image). 71 75 * ··· 72 78 * of all user space processes/kernel tasks. 73 79 */ 74 80 void __init setup_physmem(unsigned long start, unsigned long reserve_end, 75 - unsigned long len, unsigned long long highmem) 81 + unsigned long len) 76 82 { 77 83 unsigned long reserve = reserve_end - start; 78 - long map_size = len - reserve; 84 + unsigned long map_size = len - reserve; 79 85 int err; 80 86 81 - if(map_size <= 0) { 87 + if (len <= reserve) { 82 88 os_warn("Too few physical memory! Needed=%lu, given=%lu\n", 83 89 reserve, len); 84 90 exit(1); 85 91 } 86 92 87 - physmem_fd = create_mem_file(len + highmem); 93 + physmem_fd = create_mem_file(len); 88 94 89 95 err = os_map_memory((void *) reserve_end, physmem_fd, reserve, 90 96 map_size, 1, 1, 1); 91 97 if (err < 0) { 92 - os_warn("setup_physmem - mapping %ld bytes of memory at 0x%p " 98 + os_warn("setup_physmem - mapping %lu bytes of memory at 0x%p " 93 99 "failed - errno = %d\n", map_size, 94 100 (void *) reserve_end, err); 95 101 exit(1); ··· 101 107 */ 102 108 os_seek_file(physmem_fd, __pa(__syscall_stub_start)); 103 109 os_write_file(physmem_fd, __syscall_stub_start, PAGE_SIZE); 104 - os_fsync_file(physmem_fd); 105 110 106 - memblock_add(__pa(start), len + highmem); 111 + memblock_add(__pa(start), len); 107 112 memblock_reserve(__pa(start), reserve); 108 113 109 114 min_low_pfn = PFN_UP(__pa(reserve_end)); ··· 130 137 region = region->next; 131 138 } 132 139 } 133 - else if (phys < __pa(end_iomem) + highmem) { 134 - fd = physmem_fd; 135 - *offset_out = phys - iomem_size; 136 - } 137 140 138 141 return fd; 139 142 } ··· 138 149 static int __init uml_mem_setup(char *line, int *add) 139 150 { 140 151 char *retptr; 152 + 153 + *add = 0; 141 154 physmem_size = memparse(line,&retptr); 142 155 return 0; 143 156 }
+12 -12
arch/um/kernel/process.c
··· 43 43 * cares about its entry, so it's OK if another processor is modifying its 44 44 * entry. 45 45 */ 46 - struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { NULL } }; 46 + struct task_struct *cpu_tasks[NR_CPUS]; 47 + EXPORT_SYMBOL(cpu_tasks); 47 48 48 49 void free_stack(unsigned long stack, int order) 49 50 { ··· 65 64 66 65 static inline void set_current(struct task_struct *task) 67 66 { 68 - cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) { task }); 67 + cpu_tasks[task_thread_info(task)->cpu] = task; 69 68 } 70 69 71 70 struct task_struct *__switch_to(struct task_struct *from, struct task_struct *to) ··· 117 116 * callback returns only if the kernel thread execs a process 118 117 */ 119 118 fn(arg); 120 - userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs); 119 + userspace(&current->thread.regs.regs); 121 120 } 122 121 123 122 /* Called magically, see new_thread_handler above */ ··· 134 133 135 134 current->thread.prev_sched = NULL; 136 135 137 - userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs); 136 + userspace(&current->thread.regs.regs); 138 137 } 139 138 140 139 int copy_thread(struct task_struct * p, const struct kernel_clone_args *args) ··· 186 185 kmalloc_ok = 0; 187 186 initial_thread_cb_skas(proc, arg); 188 187 kmalloc_ok = save_kmalloc_ok; 188 + } 189 + 190 + int arch_dup_task_struct(struct task_struct *dst, 191 + struct task_struct *src) 192 + { 193 + memcpy(dst, src, arch_task_struct_size); 194 + return 0; 189 195 } 190 196 191 197 void um_idle_sleep(void) ··· 295 287 296 288 return 0; 297 289 } 298 - 299 - int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu) 300 - { 301 - int cpu = current_thread_info()->cpu; 302 - 303 - return save_i387_registers(userspace_pid[cpu], (unsigned long *) fpu); 304 - } 305 -
+2
arch/um/kernel/skas/.gitignore
··· 1 + stub_exe 2 + stub_exe.dbg
+36 -2
arch/um/kernel/skas/Makefile
··· 3 3 # Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 4 # 5 5 6 - obj-y := stub.o mmu.o process.o syscall.o uaccess.o 6 + obj-y := stub.o mmu.o process.o syscall.o uaccess.o \ 7 + stub_exe_embed.o 8 + 9 + # Stub executable 10 + 11 + stub_exe_objs-y := stub_exe.o 12 + 13 + stub_exe_objs := $(foreach F,$(stub_exe_objs-y),$(obj)/$F) 14 + 15 + # Object file containing the ELF executable 16 + $(obj)/stub_exe_embed.o: $(src)/stub_exe_embed.S $(obj)/stub_exe 17 + 18 + $(obj)/stub_exe.dbg: $(stub_exe_objs) FORCE 19 + $(call if_changed,stub_exe) 20 + 21 + $(obj)/stub_exe: OBJCOPYFLAGS := -S 22 + $(obj)/stub_exe: $(obj)/stub_exe.dbg FORCE 23 + $(call if_changed,objcopy) 24 + 25 + quiet_cmd_stub_exe = STUB_EXE $@ 26 + cmd_stub_exe = $(CC) -nostdlib -o $@ \ 27 + $(filter-out $(UM_GPROF_OPT) $(UM_GCOV_OPT),$(KBUILD_CFLAGS)) $(STUB_EXE_LDFLAGS) \ 28 + $(filter %.o,$^) 29 + 30 + STUB_EXE_LDFLAGS = -Wl,-n -static 31 + 32 + targets += stub_exe.dbg stub_exe $(stub_exe_objs-y) 33 + 34 + # end 7 35 8 36 # stub.o is in the stub, so it can't be built with profiling 9 37 # GCC hardened also auto-enables -fpic, but we need %ebx so it can't work -> 10 38 # disable it 11 39 12 40 CFLAGS_stub.o := $(CFLAGS_NO_HARDENING) 13 - UNPROFILE_OBJS := stub.o 41 + CFLAGS_stub_exe.o := $(CFLAGS_NO_HARDENING) 42 + 43 + # Clang will call memset() from __builtin_alloca() when stack variable 44 + # initialization is enabled, which is used in stub_exe.c. 45 + CFLAGS_stub_exe.o += $(call cc-option, -ftrivial-auto-var-init=uninitialized) 46 + 47 + UNPROFILE_OBJS := stub.o stub_exe.o 14 48 KCOV_INSTRUMENT := n 15 49 16 50 include $(srctree)/arch/um/scripts/Makefile.rules
+3 -25
arch/um/kernel/skas/mmu.c
··· 40 40 goto out_free; 41 41 } 42 42 43 - /* 44 - * Ensure the new MM is clean and nothing unwanted is mapped. 45 - * 46 - * TODO: We should clear the memory up to STUB_START to ensure there is 47 - * nothing mapped there, i.e. we (currently) have: 48 - * 49 - * |- user memory -|- unused -|- stub -|- unused -| 50 - * ^ TASK_SIZE ^ STUB_START 51 - * 52 - * Meaning we have two unused areas where we may still have valid 53 - * mappings from our internal clone(). That isn't really a problem as 54 - * userspace is not going to access them, but it is definitely not 55 - * correct. 56 - * 57 - * However, we are "lucky" and if rseq is configured, then on 32 bit 58 - * it will fall into the first empty range while on 64 bit it is going 59 - * to use an anonymous mapping in the second range. As such, things 60 - * continue to work for now as long as we don't start unmapping these 61 - * areas. 62 - * 63 - * Change this to STUB_START once we have a clean userspace. 64 - */ 65 - unmap(new_id, 0, TASK_SIZE); 43 + /* Ensure the new MM is clean and nothing unwanted is mapped */ 44 + unmap(new_id, 0, STUB_START); 66 45 67 46 return 0; 68 47 69 48 out_free: 70 - if (new_id->stack != 0) 71 - free_pages(new_id->stack, ilog2(STUB_DATA_PAGES)); 49 + free_pages(new_id->stack, ilog2(STUB_DATA_PAGES)); 72 50 out: 73 51 return ret; 74 52 }
+1 -3
arch/um/kernel/skas/process.c
··· 22 22 { 23 23 block_signals_trace(); 24 24 25 - cpu_tasks[0].task = current; 26 - 27 25 start_kernel(); 28 26 return 0; 29 27 } 30 28 31 29 extern int userspace_pid[]; 32 30 33 - extern char cpu0_irqstack[]; 31 + static char cpu0_irqstack[THREAD_SIZE] __aligned(THREAD_SIZE); 34 32 35 33 int __init start_uml(void) 36 34 {
-10
arch/um/kernel/skas/stub.c
··· 35 35 return -1; 36 36 } 37 37 break; 38 - case STUB_SYSCALL_MPROTECT: 39 - res = stub_syscall3(__NR_mprotect, 40 - sc->mem.addr, sc->mem.length, 41 - sc->mem.prot); 42 - if (res) { 43 - d->err = res; 44 - d->syscall_data_len = i; 45 - return -1; 46 - } 47 - break; 48 38 default: 49 39 d->err = -95; /* EOPNOTSUPP */ 50 40 d->syscall_data_len = i;
+95
arch/um/kernel/skas/stub_exe.c
··· 1 + #include <sys/ptrace.h> 2 + #include <sys/prctl.h> 3 + #include <asm/unistd.h> 4 + #include <sysdep/stub.h> 5 + #include <stub-data.h> 6 + 7 + void _start(void); 8 + 9 + noinline static void real_init(void) 10 + { 11 + struct stub_init_data init_data; 12 + unsigned long res; 13 + struct { 14 + void *ss_sp; 15 + int ss_flags; 16 + size_t ss_size; 17 + } stack = { 18 + .ss_size = STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, 19 + }; 20 + struct { 21 + void *sa_handler_; 22 + unsigned long sa_flags; 23 + void *sa_restorer; 24 + unsigned long long sa_mask; 25 + } sa = { 26 + /* Need to set SA_RESTORER (but the handler never returns) */ 27 + .sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO | 0x04000000, 28 + /* no need to mask any signals */ 29 + .sa_mask = 0, 30 + }; 31 + 32 + /* set a nice name */ 33 + stub_syscall2(__NR_prctl, PR_SET_NAME, (unsigned long)"uml-userspace"); 34 + 35 + /* Make sure this process dies if the kernel dies */ 36 + stub_syscall2(__NR_prctl, PR_SET_PDEATHSIG, SIGKILL); 37 + 38 + /* read information from STDIN and close it */ 39 + res = stub_syscall3(__NR_read, 0, 40 + (unsigned long)&init_data, sizeof(init_data)); 41 + if (res != sizeof(init_data)) 42 + stub_syscall1(__NR_exit, 10); 43 + 44 + stub_syscall1(__NR_close, 0); 45 + 46 + /* map stub code + data */ 47 + res = stub_syscall6(STUB_MMAP_NR, 48 + init_data.stub_start, UM_KERN_PAGE_SIZE, 49 + PROT_READ | PROT_EXEC, MAP_FIXED | MAP_SHARED, 50 + init_data.stub_code_fd, init_data.stub_code_offset); 51 + if (res != init_data.stub_start) 52 + stub_syscall1(__NR_exit, 11); 53 + 54 + res = stub_syscall6(STUB_MMAP_NR, 55 + init_data.stub_start + UM_KERN_PAGE_SIZE, 56 + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, 57 + PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, 58 + init_data.stub_data_fd, init_data.stub_data_offset); 59 + if (res != init_data.stub_start + UM_KERN_PAGE_SIZE) 60 + stub_syscall1(__NR_exit, 12); 61 + 62 + /* setup signal stack inside stub data */ 63 + stack.ss_sp = (void *)init_data.stub_start + UM_KERN_PAGE_SIZE; 64 + stub_syscall2(__NR_sigaltstack, (unsigned long)&stack, 0); 65 + 66 + /* register SIGSEGV handler */ 67 + sa.sa_handler_ = (void *) init_data.segv_handler; 68 + res = stub_syscall4(__NR_rt_sigaction, SIGSEGV, (unsigned long)&sa, 0, 69 + sizeof(sa.sa_mask)); 70 + if (res != 0) 71 + stub_syscall1(__NR_exit, 13); 72 + 73 + stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0); 74 + 75 + stub_syscall2(__NR_kill, stub_syscall0(__NR_getpid), SIGSTOP); 76 + 77 + stub_syscall1(__NR_exit, 14); 78 + 79 + __builtin_unreachable(); 80 + } 81 + 82 + __attribute__((naked)) void _start(void) 83 + { 84 + /* 85 + * Since the stack after exec() starts at the top-most address, 86 + * but that's exactly where we also want to map the stub data 87 + * and code, this must: 88 + * - push the stack by 1 code and STUB_DATA_PAGES data pages 89 + * - call real_init() 90 + * This way, real_init() can use the stack normally, while the 91 + * original stack further down (higher address) will become 92 + * inaccessible after the mmap() calls above. 93 + */ 94 + stub_start(real_init); 95 + }
+11
arch/um/kernel/skas/stub_exe_embed.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #include <linux/init.h> 3 + #include <linux/linkage.h> 4 + 5 + __INITDATA 6 + 7 + SYM_DATA_START(stub_exe_start) 8 + .incbin "arch/um/kernel/skas/stub_exe" 9 + SYM_DATA_END_LABEL(stub_exe_start, SYM_L_GLOBAL, stub_exe_end) 10 + 11 + __FINIT
+1 -7
arch/um/kernel/sysrq.c
··· 32 32 struct pt_regs *segv_regs = current->thread.segv_regs; 33 33 int i; 34 34 35 - if (!segv_regs && os_is_signal_stack()) { 36 - pr_err("Received SIGSEGV in SIGSEGV handler," 37 - " aborting stack trace!\n"); 38 - return; 39 - } 40 - 41 35 if (!stack) 42 36 stack = get_stack_pointer(task, segv_regs); 43 37 ··· 46 52 } 47 53 48 54 printk("%sCall Trace:\n", loglvl); 49 - dump_trace(current, &stackops, (void *)loglvl); 55 + dump_trace(task ?: current, &stackops, (void *)loglvl); 50 56 }
+20
arch/um/kernel/time.c
··· 25 25 #include <shared/init.h> 26 26 27 27 #ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT 28 + #include <linux/sched/clock.h> 29 + 28 30 enum time_travel_mode time_travel_mode; 29 31 EXPORT_SYMBOL_GPL(time_travel_mode); 30 32 ··· 48 46 static u16 time_travel_shm_id; 49 47 static struct um_timetravel_schedshm *time_travel_shm; 50 48 static union um_timetravel_schedshm_client *time_travel_shm_client; 49 + 50 + unsigned long tt_extra_sched_jiffies; 51 + 52 + notrace unsigned long long sched_clock(void) 53 + { 54 + return (unsigned long long)(jiffies - INITIAL_JIFFIES + 55 + tt_extra_sched_jiffies) 56 + * (NSEC_PER_SEC / HZ); 57 + } 51 58 52 59 static void time_travel_set_time(unsigned long long ns) 53 60 { ··· 454 443 { 455 444 time_travel_add_event(&time_travel_timer_event, 456 445 time_travel_time + time_travel_timer_interval); 446 + 447 + /* clock tick; decrease extra jiffies by keeping sched_clock constant */ 448 + if (tt_extra_sched_jiffies > 0) 449 + tt_extra_sched_jiffies -= 1; 450 + 457 451 deliver_alarm(); 458 452 } 459 453 ··· 610 594 611 595 static void time_travel_oneshot_timer(struct time_travel_event *e) 612 596 { 597 + /* clock tick; decrease extra jiffies by keeping sched_clock constant */ 598 + if (tt_extra_sched_jiffies > 0) 599 + tt_extra_sched_jiffies -= 1; 600 + 613 601 deliver_alarm(); 614 602 } 615 603
+30 -40
arch/um/kernel/tlb.c
··· 23 23 int phys_fd, unsigned long long offset); 24 24 int (*unmap)(struct mm_id *mm_idp, 25 25 unsigned long virt, unsigned long len); 26 - int (*mprotect)(struct mm_id *mm_idp, 27 - unsigned long virt, unsigned long len, 28 - unsigned int prot); 29 26 }; 30 27 31 28 static int kern_map(struct mm_id *mm_idp, ··· 41 44 return os_unmap_memory((void *)virt, len); 42 45 } 43 46 44 - static int kern_mprotect(struct mm_id *mm_idp, 45 - unsigned long virt, unsigned long len, 46 - unsigned int prot) 47 - { 48 - return os_protect_memory((void *)virt, len, 49 - prot & UM_PROT_READ, prot & UM_PROT_WRITE, 50 - 1); 51 - } 52 - 53 47 void report_enomem(void) 54 48 { 55 49 printk(KERN_ERR "UML ran out of memory on the host side! " ··· 53 65 struct vm_ops *ops) 54 66 { 55 67 pte_t *pte; 56 - int r, w, x, prot, ret = 0; 68 + int ret = 0; 57 69 58 70 pte = pte_offset_kernel(pmd, addr); 59 71 do { 60 - r = pte_read(*pte); 61 - w = pte_write(*pte); 62 - x = pte_exec(*pte); 63 - if (!pte_young(*pte)) { 64 - r = 0; 65 - w = 0; 66 - } else if (!pte_dirty(*pte)) 67 - w = 0; 72 + if (!pte_needsync(*pte)) 73 + continue; 68 74 69 - prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | 70 - (x ? UM_PROT_EXEC : 0)); 71 - if (pte_newpage(*pte)) { 72 - if (pte_present(*pte)) { 73 - __u64 offset; 74 - unsigned long phys = pte_val(*pte) & PAGE_MASK; 75 - int fd = phys_mapping(phys, &offset); 75 + if (pte_present(*pte)) { 76 + __u64 offset; 77 + unsigned long phys = pte_val(*pte) & PAGE_MASK; 78 + int fd = phys_mapping(phys, &offset); 79 + int r, w, x, prot; 76 80 77 - ret = ops->mmap(ops->mm_idp, addr, PAGE_SIZE, 78 - prot, fd, offset); 79 - } else 80 - ret = ops->unmap(ops->mm_idp, addr, PAGE_SIZE); 81 - } else if (pte_newprot(*pte)) 82 - ret = ops->mprotect(ops->mm_idp, addr, PAGE_SIZE, prot); 81 + r = pte_read(*pte); 82 + w = pte_write(*pte); 83 + x = pte_exec(*pte); 84 + if (!pte_young(*pte)) { 85 + r = 0; 86 + w = 0; 87 + } else if (!pte_dirty(*pte)) 88 + w = 0; 89 + 90 + prot = (r ? UM_PROT_READ : 0) | 91 + (w ? UM_PROT_WRITE : 0) | 92 + (x ? UM_PROT_EXEC : 0); 93 + 94 + ret = ops->mmap(ops->mm_idp, addr, PAGE_SIZE, 95 + prot, fd, offset); 96 + } else 97 + ret = ops->unmap(ops->mm_idp, addr, PAGE_SIZE); 98 + 83 99 *pte = pte_mkuptodate(*pte); 84 100 } while (pte++, addr += PAGE_SIZE, ((addr < end) && !ret)); 85 101 return ret; ··· 101 109 do { 102 110 next = pmd_addr_end(addr, end); 103 111 if (!pmd_present(*pmd)) { 104 - if (pmd_newpage(*pmd)) { 112 + if (pmd_needsync(*pmd)) { 105 113 ret = ops->unmap(ops->mm_idp, addr, 106 114 next - addr); 107 115 pmd_mkuptodate(*pmd); ··· 124 132 do { 125 133 next = pud_addr_end(addr, end); 126 134 if (!pud_present(*pud)) { 127 - if (pud_newpage(*pud)) { 135 + if (pud_needsync(*pud)) { 128 136 ret = ops->unmap(ops->mm_idp, addr, 129 137 next - addr); 130 138 pud_mkuptodate(*pud); ··· 147 155 do { 148 156 next = p4d_addr_end(addr, end); 149 157 if (!p4d_present(*p4d)) { 150 - if (p4d_newpage(*p4d)) { 158 + if (p4d_needsync(*p4d)) { 151 159 ret = ops->unmap(ops->mm_idp, addr, 152 160 next - addr); 153 161 p4d_mkuptodate(*p4d); ··· 172 180 if (mm == &init_mm) { 173 181 ops.mmap = kern_map; 174 182 ops.unmap = kern_unmap; 175 - ops.mprotect = kern_mprotect; 176 183 } else { 177 184 ops.mmap = map; 178 185 ops.unmap = unmap; 179 - ops.mprotect = protect; 180 186 } 181 187 182 188 pgd = pgd_offset(mm, addr); 183 189 do { 184 190 next = pgd_addr_end(addr, mm->context.sync_tlb_range_to); 185 191 if (!pgd_present(*pgd)) { 186 - if (pgd_newpage(*pgd)) { 192 + if (pgd_needsync(*pgd)) { 187 193 ret = ops.unmap(ops.mm_idp, addr, 188 194 next - addr); 189 195 pgd_mkuptodate(*pgd);
-16
arch/um/kernel/trap.c
··· 201 201 unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, 202 202 struct uml_pt_regs *regs) 203 203 { 204 - jmp_buf *catcher; 205 204 int si_code; 206 205 int err; 207 206 int is_write = FAULT_WRITE(fi); ··· 245 246 address = 0; 246 247 } 247 248 248 - catcher = current->thread.fault_catcher; 249 249 if (!err) 250 250 goto out; 251 - else if (catcher != NULL) { 252 - current->thread.fault_addr = (void *) address; 253 - UML_LONGJMP(catcher, 1); 254 - } 255 - else if (current->thread.fault_addr != NULL) 256 - panic("fault_addr set but no fault catcher"); 257 251 else if (!is_user && arch_fixup(ip, regs)) 258 252 goto out; 259 253 ··· 300 308 sig, code, err); 301 309 force_sig(sig); 302 310 } 303 - } 304 - 305 - void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs) 306 - { 307 - if (current->thread.fault_catcher != NULL) 308 - UML_LONGJMP(current->thread.fault_catcher, 1); 309 - else 310 - relay_signal(sig, si, regs); 311 311 } 312 312 313 313 void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
+40 -35
arch/um/kernel/um_arch.c
··· 65 65 66 66 EXPORT_SYMBOL(boot_cpu_data); 67 67 68 - union thread_union cpu0_irqstack 69 - __section(".data..init_irqstack") = 70 - { .thread_info = INIT_THREAD_INFO(init_task) }; 71 68 72 69 /* Changed in setup_arch, which is called in early boot */ 73 70 static char host_info[(__NEW_UTS_LEN + 1) * 5]; ··· 128 131 static int have_console __initdata; 129 132 130 133 /* Set in uml_mem_setup and modified in linux_main */ 131 - long long physmem_size = 64 * 1024 * 1024; 134 + unsigned long long physmem_size = 64 * 1024 * 1024; 132 135 EXPORT_SYMBOL(physmem_size); 133 136 134 137 static const char *usage_string = ··· 162 165 " devices and want to boot off something other than ubd0, you \n" 163 166 " would use something like:\n" 164 167 " root=/dev/ubd5\n\n" 165 - ); 166 - 167 - static int __init no_skas_debug_setup(char *line, int *add) 168 - { 169 - os_warn("'debug' is not necessary to gdb UML in skas mode - run\n"); 170 - os_warn("'gdb linux'\n"); 171 - 172 - return 0; 173 - } 174 - 175 - __uml_setup("debug", no_skas_debug_setup, 176 - "debug\n" 177 - " this flag is not needed to run gdb on UML in skas mode\n\n" 178 168 ); 179 169 180 170 static int __init uml_console_setup(char *line, int *add) ··· 241 257 242 258 void uml_finishsetup(void) 243 259 { 260 + cpu_tasks[0] = &init_task; 261 + 244 262 atomic_notifier_chain_register(&panic_notifier_list, 245 263 &panic_exit_notifier); 246 264 ··· 288 302 } 289 303 } 290 304 291 - int __init linux_main(int argc, char **argv) 305 + static unsigned long get_top_address(char **envp) 306 + { 307 + unsigned long top_addr = (unsigned long) &top_addr; 308 + int i; 309 + 310 + /* The earliest variable should be after the program name in ELF */ 311 + for (i = 0; envp[i]; i++) { 312 + if ((unsigned long) envp[i] > top_addr) 313 + top_addr = (unsigned long) envp[i]; 314 + } 315 + 316 + top_addr &= ~(UM_KERN_PAGE_SIZE - 1); 317 + top_addr += UM_KERN_PAGE_SIZE; 318 + 319 + return top_addr; 320 + } 321 + 322 + int __init linux_main(int argc, char **argv, char **envp) 292 323 { 293 324 unsigned long avail, diff; 294 325 unsigned long virtmem_size, max_physmem; ··· 327 324 if (have_console == 0) 328 325 add_arg(DEFAULT_COMMAND_LINE_CONSOLE); 329 326 330 - host_task_size = os_get_top_address(); 331 - /* reserve a few pages for the stubs (taking care of data alignment) */ 332 - /* align the data portion */ 333 - BUILD_BUG_ON(!is_power_of_2(STUB_DATA_PAGES)); 334 - stub_start = (host_task_size - 1) & ~(STUB_DATA_PAGES * PAGE_SIZE - 1); 327 + host_task_size = get_top_address(envp); 328 + /* reserve a few pages for the stubs */ 329 + stub_start = host_task_size - STUB_DATA_PAGES * PAGE_SIZE; 335 330 /* another page for the code portion */ 336 331 stub_start -= PAGE_SIZE; 337 332 host_task_size = stub_start; 333 + 334 + /* Limit TASK_SIZE to what is addressable by the page table */ 335 + task_size = host_task_size; 336 + if (task_size > (unsigned long long) PTRS_PER_PGD * PGDIR_SIZE) 337 + task_size = PTRS_PER_PGD * PGDIR_SIZE; 338 338 339 339 /* 340 340 * TASK_SIZE needs to be PGDIR_SIZE aligned or else exit_mmap craps 341 341 * out 342 342 */ 343 - task_size = host_task_size & PGDIR_MASK; 343 + task_size = task_size & PGDIR_MASK; 344 344 345 345 /* OS sanity checks that need to happen before the kernel runs */ 346 346 os_early_checks(); ··· 372 366 373 367 setup_machinename(init_utsname()->machine); 374 368 375 - highmem = 0; 369 + physmem_size = (physmem_size + PAGE_SIZE - 1) & PAGE_MASK; 376 370 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; 371 + 377 372 max_physmem = TASK_SIZE - uml_physmem - iomem_size - MIN_VMALLOC; 378 373 379 - /* 380 - * Zones have to begin on a 1 << MAX_PAGE_ORDER page boundary, 381 - * so this makes sure that's true for highmem 382 - */ 383 - max_physmem &= ~((1 << (PAGE_SHIFT + MAX_PAGE_ORDER)) - 1); 384 374 if (physmem_size + iomem_size > max_physmem) { 385 - highmem = physmem_size + iomem_size - max_physmem; 386 - physmem_size -= highmem; 375 + physmem_size = max_physmem - iomem_size; 376 + os_info("Physical memory size shrunk to %llu bytes\n", 377 + physmem_size); 387 378 } 388 379 389 380 high_physmem = uml_physmem + physmem_size; ··· 401 398 os_info("Kernel virtual memory size shrunk to %lu bytes\n", 402 399 virtmem_size); 403 400 401 + arch_task_struct_size = sizeof(struct task_struct) + host_fp_size; 402 + 404 403 os_flush_stdout(); 405 404 406 405 return start_uml(); ··· 417 412 { 418 413 u8 rng_seed[32]; 419 414 420 - stack_protections((unsigned long) &init_thread_info); 421 - setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); 422 - mem_total_pages(physmem_size, iomem_size, highmem); 415 + stack_protections((unsigned long) init_task.stack); 416 + setup_physmem(uml_physmem, uml_reserved, physmem_size); 417 + mem_total_pages(physmem_size, iomem_size); 423 418 uml_dtb_init(); 424 419 read_initrd(); 425 420
-2
arch/um/kernel/uml.lds.S
··· 77 77 .data : 78 78 { 79 79 INIT_TASK_DATA(KERNEL_STACK_SIZE) 80 - . = ALIGN(KERNEL_STACK_SIZE); 81 - *(.data..init_irqstack) 82 80 DATA_DATA 83 81 *(.gnu.linkonce.d*) 84 82 CONSTRUCTORS
+2
arch/um/os-Linux/Makefile
··· 12 12 13 13 CFLAGS_signal.o += -Wframe-larger-than=4096 14 14 15 + CFLAGS_main.o += -Wno-frame-larger-than 16 + 15 17 obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o 16 18 17 19 USER_OBJS := $(user-objs-y) elf_aux.o execvp.o file.o helper.o irq.o \
-6
arch/um/os-Linux/file.c
··· 255 255 { 256 256 close(fd); 257 257 } 258 - int os_fsync_file(int fd) 259 - { 260 - if (fsync(fd) < 0) 261 - return -errno; 262 - return 0; 263 - } 264 258 265 259 int os_seek_file(int fd, unsigned long long offset) 266 260 {
+18 -5
arch/um/os-Linux/main.c
··· 11 11 #include <signal.h> 12 12 #include <string.h> 13 13 #include <sys/resource.h> 14 + #include <sys/personality.h> 14 15 #include <as-layout.h> 15 16 #include <init.h> 16 17 #include <kern_util.h> ··· 109 108 char **new_argv; 110 109 int ret, i, err; 111 110 111 + /* Disable randomization and re-exec if it was changed successfully */ 112 + ret = personality(PER_LINUX | ADDR_NO_RANDOMIZE); 113 + if (ret >= 0 && (ret & (PER_LINUX | ADDR_NO_RANDOMIZE)) != 114 + (PER_LINUX | ADDR_NO_RANDOMIZE)) { 115 + char buf[4096] = {}; 116 + ssize_t ret; 117 + 118 + ret = readlink("/proc/self/exe", buf, sizeof(buf)); 119 + if (ret < 0 || ret >= sizeof(buf)) { 120 + perror("readlink failure"); 121 + exit(1); 122 + } 123 + execve(buf, argv, envp); 124 + } 125 + 112 126 set_stklim(); 113 127 114 128 setup_env_path(); ··· 156 140 #endif 157 141 158 142 change_sig(SIGPIPE, 0); 159 - ret = linux_main(argc, argv); 143 + ret = linux_main(argc, argv, envp); 160 144 161 145 /* 162 146 * Disable SIGPROF - I have no idea why libc doesn't do this or turn ··· 198 182 } 199 183 200 184 extern void *__real_malloc(int); 185 + extern void __real_free(void *); 201 186 202 187 /* workaround for -Wmissing-prototypes warnings */ 203 188 void *__wrap_malloc(int size); ··· 235 218 memset(ptr, 0, n * size); 236 219 return ptr; 237 220 } 238 - 239 - extern void __real_free(void *); 240 - 241 - extern unsigned long high_physmem; 242 221 243 222 void __wrap_free(void *ptr) 244 223 {
+13 -1
arch/um/os-Linux/mem.c
··· 39 39 strerror(errno)); 40 40 exit(1); 41 41 } 42 + 43 + if (madvise(start, len, MADV_DONTDUMP)) { 44 + os_info("Couldn't set MAD_DONTDUMP on shadow memory: %s\n.", 45 + strerror(errno)); 46 + exit(1); 47 + } 48 + 49 + if (madvise(start, len, MADV_DONTFORK)) { 50 + os_info("Couldn't set MADV_DONTFORK on shadow memory: %s\n.", 51 + strerror(errno)); 52 + exit(1); 53 + } 42 54 } 43 55 44 56 /* Set by make_tempfile() during early boot. */ 45 - static char *tempdir = NULL; 57 + char *tempdir = NULL; 46 58 47 59 /* Check if dir is on tmpfs. Return 0 if yes, -1 if no or error. */ 48 60 static int __init check_tmpfs(const char *dir)
+6 -82
arch/um/os-Linux/process.c
··· 12 12 #include <fcntl.h> 13 13 #include <sys/mman.h> 14 14 #include <sys/ptrace.h> 15 + #include <sys/prctl.h> 15 16 #include <sys/wait.h> 16 17 #include <asm/unistd.h> 17 18 #include <init.h> 18 19 #include <longjmp.h> 19 20 #include <os.h> 20 21 21 - #define ARBITRARY_ADDR -1 22 - #define FAILURE_PID -1 23 - 24 - #define STAT_PATH_LEN sizeof("/proc/#######/stat\0") 25 - #define COMM_SCANF "%*[^)])" 26 - 27 - unsigned long os_process_pc(int pid) 28 - { 29 - char proc_stat[STAT_PATH_LEN], buf[256]; 30 - unsigned long pc = ARBITRARY_ADDR; 31 - int fd, err; 32 - 33 - sprintf(proc_stat, "/proc/%d/stat", pid); 34 - fd = open(proc_stat, O_RDONLY, 0); 35 - if (fd < 0) { 36 - printk(UM_KERN_ERR "os_process_pc - couldn't open '%s', " 37 - "errno = %d\n", proc_stat, errno); 38 - goto out; 39 - } 40 - CATCH_EINTR(err = read(fd, buf, sizeof(buf))); 41 - if (err < 0) { 42 - printk(UM_KERN_ERR "os_process_pc - couldn't read '%s', " 43 - "err = %d\n", proc_stat, errno); 44 - goto out_close; 45 - } 46 - os_close_file(fd); 47 - pc = ARBITRARY_ADDR; 48 - if (sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " 49 - "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " 50 - "%*d %*d %*d %*d %*d %lu", &pc) != 1) 51 - printk(UM_KERN_ERR "os_process_pc - couldn't find pc in '%s'\n", 52 - buf); 53 - out_close: 54 - close(fd); 55 - out: 56 - return pc; 57 - } 58 - 59 - int os_process_parent(int pid) 60 - { 61 - char stat[STAT_PATH_LEN]; 62 - char data[256]; 63 - int parent = FAILURE_PID, n, fd; 64 - 65 - if (pid == -1) 66 - return parent; 67 - 68 - snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); 69 - fd = open(stat, O_RDONLY, 0); 70 - if (fd < 0) { 71 - printk(UM_KERN_ERR "Couldn't open '%s', errno = %d\n", stat, 72 - errno); 73 - return parent; 74 - } 75 - 76 - CATCH_EINTR(n = read(fd, data, sizeof(data))); 77 - close(fd); 78 - 79 - if (n < 0) { 80 - printk(UM_KERN_ERR "Couldn't read '%s', errno = %d\n", stat, 81 - errno); 82 - return parent; 83 - } 84 - 85 - parent = FAILURE_PID; 86 - n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent); 87 - if (n != 1) 88 - printk(UM_KERN_ERR "Failed to scan '%s'\n", data); 89 - 90 - return parent; 91 - } 92 - 93 22 void os_alarm_process(int pid) 94 23 { 95 24 kill(pid, SIGALRM); 96 - } 97 - 98 - void os_stop_process(int pid) 99 - { 100 - kill(pid, SIGSTOP); 101 25 } 102 26 103 27 void os_kill_process(int pid, int reap_child) ··· 52 128 int os_getpid(void) 53 129 { 54 130 return syscall(__NR_getpid); 55 - } 56 - 57 - int os_getpgrp(void) 58 - { 59 - return getpgrp(); 60 131 } 61 132 62 133 int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, ··· 203 284 signal(SIGHUP, SIG_IGN); 204 285 set_handler(SIGIO); 205 286 signal(SIGWINCH, SIG_IGN); 287 + } 288 + 289 + void os_set_pdeathsig(void) 290 + { 291 + prctl(PR_SET_PDEATHSIG, SIGKILL); 206 292 }
+8 -3
arch/um/os-Linux/registers.c
··· 10 10 #include <sysdep/ptrace.h> 11 11 #include <sysdep/ptrace_user.h> 12 12 #include <registers.h> 13 + #include <stdlib.h> 13 14 14 15 /* This is set once at boot time and not changed thereafter */ 15 16 16 17 static unsigned long exec_regs[MAX_REG_NR]; 17 - static unsigned long exec_fp_regs[FP_SIZE]; 18 + static unsigned long *exec_fp_regs; 18 19 19 20 int init_pid_registers(int pid) 20 21 { ··· 25 24 if (err < 0) 26 25 return -errno; 27 26 28 - arch_init_registers(pid); 27 + err = arch_init_registers(pid); 28 + if (err < 0) 29 + return err; 30 + 31 + exec_fp_regs = malloc(host_fp_size); 29 32 get_fp_registers(pid, exec_fp_regs); 30 33 return 0; 31 34 } ··· 39 34 memcpy(regs, exec_regs, sizeof(exec_regs)); 40 35 41 36 if (fp_regs) 42 - memcpy(fp_regs, exec_fp_regs, sizeof(exec_fp_regs)); 37 + memcpy(fp_regs, exec_fp_regs, host_fp_size); 43 38 }
+1
arch/um/os-Linux/sigio.c
··· 55 55 int i, n, respond_fd; 56 56 char c; 57 57 58 + os_set_pdeathsig(); 58 59 os_fix_helper_signals(); 59 60 fds = &current_poll; 60 61 while (1) {
+6 -49
arch/um/os-Linux/signal.c
··· 26 26 [SIGFPE] = relay_signal, 27 27 [SIGILL] = relay_signal, 28 28 [SIGWINCH] = winch, 29 - [SIGBUS] = bus_handler, 29 + [SIGBUS] = relay_signal, 30 30 [SIGSEGV] = segv_handler, 31 31 [SIGIO] = sigio_handler, 32 32 }; ··· 65 65 #define SIGALRM_MASK (1 << SIGALRM_BIT) 66 66 67 67 int signals_enabled; 68 - #ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT 68 + #if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT) 69 69 static int signals_blocked, signals_blocked_pending; 70 70 #endif 71 71 static unsigned int signals_pending; ··· 75 75 { 76 76 int enabled = signals_enabled; 77 77 78 - #ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT 78 + #if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT) 79 79 if ((signals_blocked || 80 80 __atomic_load_n(&signals_blocked_pending, __ATOMIC_SEQ_CST)) && 81 81 (sig == SIGIO)) { ··· 190 190 { 191 191 ucontext_t *uc = p; 192 192 mcontext_t *mc = &uc->uc_mcontext; 193 - unsigned long pending = 1UL << sig; 194 193 195 - do { 196 - int nested, bail; 197 - 198 - /* 199 - * pending comes back with one bit set for each 200 - * interrupt that arrived while setting up the stack, 201 - * plus a bit for this interrupt, plus the zero bit is 202 - * set if this is a nested interrupt. 203 - * If bail is true, then we interrupted another 204 - * handler setting up the stack. In this case, we 205 - * have to return, and the upper handler will deal 206 - * with this interrupt. 207 - */ 208 - bail = to_irq_stack(&pending); 209 - if (bail) 210 - return; 211 - 212 - nested = pending & 1; 213 - pending &= ~1; 214 - 215 - while ((sig = ffs(pending)) != 0){ 216 - sig--; 217 - pending &= ~(1 << sig); 218 - (*handlers[sig])(sig, (struct siginfo *)si, mc); 219 - } 220 - 221 - /* 222 - * Again, pending comes back with a mask of signals 223 - * that arrived while tearing down the stack. If this 224 - * is non-zero, we just go back, set up the stack 225 - * again, and handle the new interrupts. 226 - */ 227 - if (!nested) 228 - pending = from_irq_stack(nested); 229 - } while (pending); 194 + (*handlers[sig])(sig, (struct siginfo *)si, mc); 230 195 } 231 196 232 197 void set_handler(int sig) ··· 262 297 return; 263 298 264 299 signals_enabled = 1; 265 - #ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT 300 + #if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT) 266 301 deliver_time_travel_irqs(); 267 302 #endif 268 303 ··· 354 389 return ret; 355 390 } 356 391 357 - #ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT 392 + #if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT) 358 393 void mark_sigio_pending(void) 359 394 { 360 395 /* ··· 452 487 unblocking = false; 453 488 } 454 489 #endif 455 - 456 - int os_is_signal_stack(void) 457 - { 458 - stack_t ss; 459 - sigaltstack(NULL, &ss); 460 - 461 - return ss.ss_flags & SS_ONSTACK; 462 - }
-21
arch/um/os-Linux/skas/mem.c
··· 217 217 218 218 return 0; 219 219 } 220 - 221 - int protect(struct mm_id *mm_idp, unsigned long addr, unsigned long len, 222 - unsigned int prot) 223 - { 224 - struct stub_syscall *sc; 225 - 226 - /* Compress with previous syscall if that is possible */ 227 - sc = syscall_stub_get_previous(mm_idp, STUB_SYSCALL_MPROTECT, addr); 228 - if (sc && sc->mem.prot == prot) { 229 - sc->mem.length += len; 230 - return 0; 231 - } 232 - 233 - sc = syscall_stub_alloc(mm_idp); 234 - sc->syscall = STUB_SYSCALL_MPROTECT; 235 - sc->mem.addr = addr; 236 - sc->mem.length = len; 237 - sc->mem.prot = prot; 238 - 239 - return 0; 240 - }
+153 -72
arch/um/os-Linux/skas/process.c
··· 10 10 #include <sched.h> 11 11 #include <errno.h> 12 12 #include <string.h> 13 + #include <fcntl.h> 14 + #include <mem_user.h> 13 15 #include <sys/mman.h> 14 16 #include <sys/wait.h> 17 + #include <sys/stat.h> 15 18 #include <asm/unistd.h> 16 19 #include <as-layout.h> 17 20 #include <init.h> ··· 144 141 145 142 extern unsigned long current_stub_stack(void); 146 143 147 - static void get_skas_faultinfo(int pid, struct faultinfo *fi, unsigned long *aux_fp_regs) 144 + static void get_skas_faultinfo(int pid, struct faultinfo *fi) 148 145 { 149 146 int err; 150 147 151 - err = get_fp_registers(pid, aux_fp_regs); 152 - if (err < 0) { 153 - printk(UM_KERN_ERR "save_fp_registers returned %d\n", 154 - err); 155 - fatal_sigsegv(); 156 - } 157 148 err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); 158 149 if (err) { 159 150 printk(UM_KERN_ERR "Failed to continue stub, pid = %d, " ··· 161 164 * the stub stack page. We just have to copy it. 162 165 */ 163 166 memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); 164 - 165 - err = put_fp_registers(pid, aux_fp_regs); 166 - if (err < 0) { 167 - printk(UM_KERN_ERR "put_fp_registers returned %d\n", 168 - err); 169 - fatal_sigsegv(); 170 - } 171 167 } 172 168 173 - static void handle_segv(int pid, struct uml_pt_regs *regs, unsigned long *aux_fp_regs) 169 + static void handle_segv(int pid, struct uml_pt_regs *regs) 174 170 { 175 - get_skas_faultinfo(pid, &regs->faultinfo, aux_fp_regs); 171 + get_skas_faultinfo(pid, &regs->faultinfo); 176 172 segv(regs->faultinfo, 0, 1, NULL); 177 173 } 178 174 ··· 179 189 180 190 extern char __syscall_stub_start[]; 181 191 182 - /** 183 - * userspace_tramp() - userspace trampoline 184 - * @stack: pointer to the new userspace stack page 185 - * 186 - * The userspace trampoline is used to setup a new userspace process in start_userspace() after it was clone()'ed. 187 - * This function will run on a temporary stack page. 188 - * It ptrace()'es itself, then 189 - * Two pages are mapped into the userspace address space: 190 - * - STUB_CODE (with EXEC), which contains the skas stub code 191 - * - STUB_DATA (with R/W), which contains a data page that is used to transfer certain data between the UML userspace process and the UML kernel. 192 - * Also for the userspace process a SIGSEGV handler is installed to catch pagefaults in the userspace process. 193 - * And last the process stops itself to give control to the UML kernel for this userspace process. 194 - * 195 - * Return: Always zero, otherwise the current userspace process is ended with non null exit() call 196 - */ 192 + static int stub_exe_fd; 193 + 197 194 static int userspace_tramp(void *stack) 198 195 { 199 - struct sigaction sa; 200 - void *addr; 201 - int fd; 196 + char *const argv[] = { "uml-userspace", NULL }; 197 + int pipe_fds[2]; 202 198 unsigned long long offset; 203 - unsigned long segv_handler = STUB_CODE + 204 - (unsigned long) stub_segv_handler - 205 - (unsigned long) __syscall_stub_start; 199 + struct stub_init_data init_data = { 200 + .stub_start = STUB_START, 201 + .segv_handler = STUB_CODE + 202 + (unsigned long) stub_segv_handler - 203 + (unsigned long) __syscall_stub_start, 204 + }; 205 + struct iomem_region *iomem; 206 + int ret; 206 207 207 - ptrace(PTRACE_TRACEME, 0, 0, 0); 208 + init_data.stub_code_fd = phys_mapping(uml_to_phys(__syscall_stub_start), 209 + &offset); 210 + init_data.stub_code_offset = MMAP_OFFSET(offset); 208 211 209 - signal(SIGTERM, SIG_DFL); 210 - signal(SIGWINCH, SIG_IGN); 212 + init_data.stub_data_fd = phys_mapping(uml_to_phys(stack), &offset); 213 + init_data.stub_data_offset = MMAP_OFFSET(offset); 211 214 212 - fd = phys_mapping(uml_to_phys(__syscall_stub_start), &offset); 213 - addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE, 214 - PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); 215 - if (addr == MAP_FAILED) { 216 - os_info("mapping mmap stub at 0x%lx failed, errno = %d\n", 217 - STUB_CODE, errno); 218 - exit(1); 215 + /* Set CLOEXEC on all FDs and then unset on all memory related FDs */ 216 + close_range(0, ~0U, CLOSE_RANGE_CLOEXEC); 217 + 218 + fcntl(init_data.stub_data_fd, F_SETFD, 0); 219 + for (iomem = iomem_regions; iomem; iomem = iomem->next) 220 + fcntl(iomem->fd, F_SETFD, 0); 221 + 222 + /* Create a pipe for init_data (no CLOEXEC) and dup2 to STDIN */ 223 + if (pipe(pipe_fds)) 224 + exit(2); 225 + 226 + if (dup2(pipe_fds[0], 0) < 0) 227 + exit(3); 228 + close(pipe_fds[0]); 229 + 230 + /* Write init_data and close write side */ 231 + ret = write(pipe_fds[1], &init_data, sizeof(init_data)); 232 + close(pipe_fds[1]); 233 + 234 + if (ret != sizeof(init_data)) 235 + exit(4); 236 + 237 + execveat(stub_exe_fd, "", argv, NULL, AT_EMPTY_PATH); 238 + 239 + exit(5); 240 + } 241 + 242 + extern char stub_exe_start[]; 243 + extern char stub_exe_end[]; 244 + 245 + extern char *tempdir; 246 + 247 + #define STUB_EXE_NAME_TEMPLATE "/uml-userspace-XXXXXX" 248 + 249 + #ifndef MFD_EXEC 250 + #define MFD_EXEC 0x0010U 251 + #endif 252 + 253 + static int __init init_stub_exe_fd(void) 254 + { 255 + size_t written = 0; 256 + char *tmpfile = NULL; 257 + 258 + stub_exe_fd = memfd_create("uml-userspace", 259 + MFD_EXEC | MFD_CLOEXEC | MFD_ALLOW_SEALING); 260 + 261 + if (stub_exe_fd < 0) { 262 + printk(UM_KERN_INFO "Could not create executable memfd, using temporary file!"); 263 + 264 + tmpfile = malloc(strlen(tempdir) + 265 + strlen(STUB_EXE_NAME_TEMPLATE) + 1); 266 + if (tmpfile == NULL) 267 + panic("Failed to allocate memory for stub binary name"); 268 + 269 + strcpy(tmpfile, tempdir); 270 + strcat(tmpfile, STUB_EXE_NAME_TEMPLATE); 271 + 272 + stub_exe_fd = mkstemp(tmpfile); 273 + if (stub_exe_fd < 0) 274 + panic("Could not create temporary file for stub binary: %d", 275 + -errno); 219 276 } 220 277 221 - fd = phys_mapping(uml_to_phys(stack), &offset); 222 - addr = mmap((void *) STUB_DATA, 223 - STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, 224 - MAP_FIXED | MAP_SHARED, fd, offset); 225 - if (addr == MAP_FAILED) { 226 - os_info("mapping segfault stack at 0x%lx failed, errno = %d\n", 227 - STUB_DATA, errno); 228 - exit(1); 278 + while (written < stub_exe_end - stub_exe_start) { 279 + ssize_t res = write(stub_exe_fd, stub_exe_start + written, 280 + stub_exe_end - stub_exe_start - written); 281 + if (res < 0) { 282 + if (errno == EINTR) 283 + continue; 284 + 285 + if (tmpfile) 286 + unlink(tmpfile); 287 + panic("Failed write stub binary: %d", -errno); 288 + } 289 + 290 + written += res; 229 291 } 230 292 231 - set_sigstack((void *) STUB_DATA, STUB_DATA_PAGES * UM_KERN_PAGE_SIZE); 232 - sigemptyset(&sa.sa_mask); 233 - sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO; 234 - sa.sa_sigaction = (void *) segv_handler; 235 - sa.sa_restorer = NULL; 236 - if (sigaction(SIGSEGV, &sa, NULL) < 0) { 237 - os_info("%s - setting SIGSEGV handler failed - errno = %d\n", 238 - __func__, errno); 239 - exit(1); 293 + if (!tmpfile) { 294 + fcntl(stub_exe_fd, F_ADD_SEALS, 295 + F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_SEAL); 296 + } else { 297 + if (fchmod(stub_exe_fd, 00500) < 0) { 298 + unlink(tmpfile); 299 + panic("Could not make stub binary executable: %d", 300 + -errno); 301 + } 302 + 303 + close(stub_exe_fd); 304 + stub_exe_fd = open(tmpfile, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); 305 + if (stub_exe_fd < 0) { 306 + unlink(tmpfile); 307 + panic("Could not reopen stub binary: %d", -errno); 308 + } 309 + 310 + unlink(tmpfile); 311 + free(tmpfile); 240 312 } 241 313 242 - kill(os_getpid(), SIGSTOP); 243 314 return 0; 244 315 } 316 + __initcall(init_stub_exe_fd); 245 317 246 318 int userspace_pid[NR_CPUS]; 247 319 ··· 322 270 { 323 271 void *stack; 324 272 unsigned long sp; 325 - int pid, status, n, flags, err; 273 + int pid, status, n, err; 326 274 327 275 /* setup a temporary stack page */ 328 276 stack = mmap(NULL, UM_KERN_PAGE_SIZE, ··· 338 286 /* set stack pointer to the end of the stack page, so it can grow downwards */ 339 287 sp = (unsigned long)stack + UM_KERN_PAGE_SIZE; 340 288 341 - flags = CLONE_FILES | SIGCHLD; 342 - 343 289 /* clone into new userspace process */ 344 - pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); 290 + pid = clone(userspace_tramp, (void *) sp, 291 + CLONE_VFORK | CLONE_VM | SIGCHLD, 292 + (void *)stub_stack); 345 293 if (pid < 0) { 346 294 err = -errno; 347 295 printk(UM_KERN_ERR "%s : clone failed, errno = %d\n", ··· 388 336 return err; 389 337 } 390 338 391 - void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs) 339 + int unscheduled_userspace_iterations; 340 + extern unsigned long tt_extra_sched_jiffies; 341 + 342 + void userspace(struct uml_pt_regs *regs) 392 343 { 393 344 int err, status, op, pid = userspace_pid[0]; 394 345 siginfo_t si; ··· 400 345 interrupt_end(); 401 346 402 347 while (1) { 348 + /* 349 + * When we are in time-travel mode, userspace can theoretically 350 + * do a *lot* of work without being scheduled. The problem with 351 + * this is that it will prevent kernel bookkeeping (primarily 352 + * the RCU) from running and this can for example cause OOM 353 + * situations. 354 + * 355 + * This code accounts a jiffie against the scheduling clock 356 + * after the defined userspace iterations in the same thread. 357 + * By doing so the situation is effectively prevented. 358 + */ 359 + if (time_travel_mode == TT_MODE_INFCPU || 360 + time_travel_mode == TT_MODE_EXTERNAL) { 361 + #ifdef CONFIG_UML_MAX_USERSPACE_ITERATIONS 362 + if (CONFIG_UML_MAX_USERSPACE_ITERATIONS && 363 + unscheduled_userspace_iterations++ > 364 + CONFIG_UML_MAX_USERSPACE_ITERATIONS) { 365 + tt_extra_sched_jiffies += 1; 366 + unscheduled_userspace_iterations = 0; 367 + } 368 + #endif 369 + } 370 + 403 371 time_travel_print_bc_msg(); 404 372 405 373 current_mm_sync(); ··· 513 435 case SIGSEGV: 514 436 if (PTRACE_FULL_FAULTINFO) { 515 437 get_skas_faultinfo(pid, 516 - &regs->faultinfo, aux_fp_regs); 438 + &regs->faultinfo); 517 439 (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si, 518 440 regs); 519 441 } 520 - else handle_segv(pid, regs, aux_fp_regs); 442 + else handle_segv(pid, regs); 521 443 break; 522 444 case SIGTRAP + 0x80: 523 445 handle_trap(pid, regs); ··· 565 487 566 488 void switch_threads(jmp_buf *me, jmp_buf *you) 567 489 { 490 + unscheduled_userspace_iterations = 0; 491 + 568 492 if (UML_SETJMP(me) == 0) 569 493 UML_LONGJMP(you, 1); 570 494 } ··· 650 570 651 571 static int __init noreboot_cmd_param(char *str, int *add) 652 572 { 573 + *add = 0; 653 574 noreboot = true; 654 575 return 0; 655 576 }
+2
arch/um/os-Linux/umid.c
··· 358 358 359 359 static int __init set_uml_dir(char *name, int *add) 360 360 { 361 + *add = 0; 362 + 361 363 if (*name == '\0') { 362 364 os_warn("uml_dir can't be an empty string\n"); 363 365 return 0;
+2 -2
arch/um/os-Linux/util.c
··· 52 52 struct utsname host; 53 53 54 54 uname(&host); 55 - #ifdef UML_CONFIG_UML_X86 56 - # ifndef UML_CONFIG_64BIT 55 + #if IS_ENABLED(CONFIG_UML_X86) 56 + # if !IS_ENABLED(CONFIG_64BIT) 57 57 if (!strcmp(host.machine, "x86_64")) { 58 58 strcpy(machine_out, "i686"); 59 59 return;
+1 -11
arch/x86/um/Kconfig
··· 10 10 def_bool y 11 11 select ARCH_BINFMT_ELF_EXTRA_PHDRS if X86_32 12 12 select DCACHE_WORD_ACCESS 13 + select HAVE_EFFICIENT_UNALIGNED_ACCESS 13 14 14 15 config 64BIT 15 16 bool "64-bit kernel" if "$(SUBARCH)" = "x86" ··· 28 27 config X86_64 29 28 def_bool 64BIT 30 29 select MODULES_USE_ELF_RELA 31 - 32 - config 3_LEVEL_PGTABLES 33 - bool "Three-level pagetables" if !64BIT 34 - default 64BIT 35 - help 36 - Three-level pagetables will let UML have more than 4G of physical 37 - memory. All the memory that can't be mapped directly will be treated 38 - as high memory. 39 - 40 - However, this it experimental on 32-bit architectures, so if unsure say 41 - N (on x86-64 it's automatically enabled, instead, as it's safe there). 42 30 43 31 config ARCH_HAS_SC_SIGNALS 44 32 def_bool !64BIT
+1 -1
arch/x86/um/Makefile
··· 10 10 endif 11 11 12 12 obj-y = bugs_$(BITS).o delay.o fault.o \ 13 - ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \ 13 + ptrace.o ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \ 14 14 stub_segv.o \ 15 15 sys_call_table_$(BITS).o sysrq_$(BITS).o tls_$(BITS).o \ 16 16 mem_$(BITS).o subarch.o os-Linux/
+2
arch/x86/um/asm/elf.h
··· 8 8 #include <asm/user.h> 9 9 #include <skas.h> 10 10 11 + #define CORE_DUMP_USE_REGSET 12 + 11 13 #ifdef CONFIG_X86_32 12 14 13 15 #define R_386_NONE 0
+10
arch/x86/um/asm/ptrace.h
··· 2 2 #ifndef __UM_X86_PTRACE_H 3 3 #define __UM_X86_PTRACE_H 4 4 5 + /* This is here because signal.c needs the REGSET_FP_LEGACY definition */ 6 + enum { 7 + REGSET_GENERAL, 8 + #ifdef CONFIG_X86_32 9 + REGSET_FP_LEGACY, 10 + #endif 11 + REGSET_FP, 12 + REGSET_XSTATE, 13 + }; 14 + 5 15 #include <linux/compiler.h> 6 16 #ifndef CONFIG_X86_32 7 17 #define __FRAME_OFFSETS /* Needed to get the R* macros */
+1 -1
arch/x86/um/os-Linux/Makefile
··· 3 3 # Licensed under the GPL 4 4 # 5 5 6 - obj-y = registers.o task_size.o mcontext.o 6 + obj-y = registers.o mcontext.o 7 7 8 8 obj-$(CONFIG_X86_32) += tls.o 9 9
+36 -111
arch/x86/um/os-Linux/registers.c
··· 16 16 #include <asm/sigcontext.h> 17 17 #include <linux/elf.h> 18 18 #include <registers.h> 19 + #include <sys/mman.h> 19 20 20 - static int have_xstate_support; 21 - 22 - int save_i387_registers(int pid, unsigned long *fp_regs) 23 - { 24 - if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) 25 - return -errno; 26 - return 0; 27 - } 28 - 29 - int save_fp_registers(int pid, unsigned long *fp_regs) 30 - { 31 - #ifdef PTRACE_GETREGSET 32 - struct iovec iov; 33 - 34 - if (have_xstate_support) { 35 - iov.iov_base = fp_regs; 36 - iov.iov_len = FP_SIZE * sizeof(unsigned long); 37 - if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) 38 - return -errno; 39 - return 0; 40 - } else 41 - #endif 42 - return save_i387_registers(pid, fp_regs); 43 - } 44 - 45 - int restore_i387_registers(int pid, unsigned long *fp_regs) 46 - { 47 - if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) 48 - return -errno; 49 - return 0; 50 - } 51 - 52 - int restore_fp_registers(int pid, unsigned long *fp_regs) 53 - { 54 - #ifdef PTRACE_SETREGSET 55 - struct iovec iov; 56 - if (have_xstate_support) { 57 - iov.iov_base = fp_regs; 58 - iov.iov_len = FP_SIZE * sizeof(unsigned long); 59 - if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) 60 - return -errno; 61 - return 0; 62 - } else 63 - #endif 64 - return restore_i387_registers(pid, fp_regs); 65 - } 66 - 67 - #ifdef __i386__ 68 - int have_fpx_regs = 1; 69 - int save_fpx_registers(int pid, unsigned long *fp_regs) 70 - { 71 - if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0) 72 - return -errno; 73 - return 0; 74 - } 75 - 76 - int restore_fpx_registers(int pid, unsigned long *fp_regs) 77 - { 78 - if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0) 79 - return -errno; 80 - return 0; 81 - } 21 + unsigned long host_fp_size; 82 22 83 23 int get_fp_registers(int pid, unsigned long *regs) 84 24 { 85 - if (have_fpx_regs) 86 - return save_fpx_registers(pid, regs); 87 - else 88 - return save_fp_registers(pid, regs); 25 + struct iovec iov = { 26 + .iov_base = regs, 27 + .iov_len = host_fp_size, 28 + }; 29 + 30 + if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) 31 + return -errno; 32 + return 0; 89 33 } 90 34 91 35 int put_fp_registers(int pid, unsigned long *regs) 92 36 { 93 - if (have_fpx_regs) 94 - return restore_fpx_registers(pid, regs); 95 - else 96 - return restore_fp_registers(pid, regs); 37 + struct iovec iov = { 38 + .iov_base = regs, 39 + .iov_len = host_fp_size, 40 + }; 41 + 42 + if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) 43 + return -errno; 44 + return 0; 97 45 } 98 46 99 - void arch_init_registers(int pid) 47 + int arch_init_registers(int pid) 100 48 { 101 - struct user_fpxregs_struct fpx_regs; 102 - int err; 49 + struct iovec iov = { 50 + /* Just use plenty of space, it does not cost us anything */ 51 + .iov_len = 2 * 1024 * 1024, 52 + }; 53 + int ret; 103 54 104 - err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); 105 - if (!err) 106 - return; 55 + iov.iov_base = mmap(NULL, iov.iov_len, PROT_WRITE | PROT_READ, 56 + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 57 + if (iov.iov_base == MAP_FAILED) 58 + return -ENOMEM; 107 59 108 - if (errno != EIO) 109 - panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", 110 - errno); 60 + /* GDB has x86_xsave_length, which uses x86_cpuid_count */ 61 + ret = ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov); 62 + if (ret) 63 + ret = -errno; 64 + munmap(iov.iov_base, 2 * 1024 * 1024); 111 65 112 - have_fpx_regs = 0; 66 + host_fp_size = iov.iov_len; 67 + 68 + return ret; 113 69 } 114 - #else 115 - 116 - int get_fp_registers(int pid, unsigned long *regs) 117 - { 118 - return save_fp_registers(pid, regs); 119 - } 120 - 121 - int put_fp_registers(int pid, unsigned long *regs) 122 - { 123 - return restore_fp_registers(pid, regs); 124 - } 125 - 126 - void arch_init_registers(int pid) 127 - { 128 - #ifdef PTRACE_GETREGSET 129 - void * fp_regs; 130 - struct iovec iov; 131 - 132 - fp_regs = malloc(FP_SIZE * sizeof(unsigned long)); 133 - if(fp_regs == NULL) 134 - return; 135 - 136 - iov.iov_base = fp_regs; 137 - iov.iov_len = FP_SIZE * sizeof(unsigned long); 138 - if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0) 139 - have_xstate_support = 1; 140 - 141 - free(fp_regs); 142 - #endif 143 - } 144 - #endif 145 70 146 71 unsigned long get_thread_reg(int reg, jmp_buf *buf) 147 72 {
-151
arch/x86/um/os-Linux/task_size.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include <stdio.h> 3 - #include <stdlib.h> 4 - #include <signal.h> 5 - #include <sys/mman.h> 6 - #include <longjmp.h> 7 - 8 - #ifdef __i386__ 9 - 10 - static jmp_buf buf; 11 - 12 - static void segfault(int sig) 13 - { 14 - longjmp(buf, 1); 15 - } 16 - 17 - static int page_ok(unsigned long page) 18 - { 19 - unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT); 20 - unsigned long n = ~0UL; 21 - void *mapped = NULL; 22 - int ok = 0; 23 - 24 - /* 25 - * First see if the page is readable. If it is, it may still 26 - * be a VDSO, so we go on to see if it's writable. If not 27 - * then try mapping memory there. If that fails, then we're 28 - * still in the kernel area. As a sanity check, we'll fail if 29 - * the mmap succeeds, but gives us an address different from 30 - * what we wanted. 31 - */ 32 - if (setjmp(buf) == 0) 33 - n = *address; 34 - else { 35 - mapped = mmap(address, UM_KERN_PAGE_SIZE, 36 - PROT_READ | PROT_WRITE, 37 - MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 38 - if (mapped == MAP_FAILED) 39 - return 0; 40 - if (mapped != address) 41 - goto out; 42 - } 43 - 44 - /* 45 - * Now, is it writeable? If so, then we're in user address 46 - * space. If not, then try mprotecting it and try the write 47 - * again. 48 - */ 49 - if (setjmp(buf) == 0) { 50 - *address = n; 51 - ok = 1; 52 - goto out; 53 - } else if (mprotect(address, UM_KERN_PAGE_SIZE, 54 - PROT_READ | PROT_WRITE) != 0) 55 - goto out; 56 - 57 - if (setjmp(buf) == 0) { 58 - *address = n; 59 - ok = 1; 60 - } 61 - 62 - out: 63 - if (mapped != NULL) 64 - munmap(mapped, UM_KERN_PAGE_SIZE); 65 - return ok; 66 - } 67 - 68 - unsigned long os_get_top_address(void) 69 - { 70 - struct sigaction sa, old; 71 - unsigned long bottom = 0; 72 - /* 73 - * A 32-bit UML on a 64-bit host gets confused about the VDSO at 74 - * 0xffffe000. It is mapped, is readable, can be reprotected writeable 75 - * and written. However, exec discovers later that it can't be 76 - * unmapped. So, just set the highest address to be checked to just 77 - * below it. This might waste some address space on 4G/4G 32-bit 78 - * hosts, but shouldn't hurt otherwise. 79 - */ 80 - unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT; 81 - unsigned long test, original; 82 - 83 - printf("Locating the bottom of the address space ... "); 84 - fflush(stdout); 85 - 86 - /* 87 - * We're going to be longjmping out of the signal handler, so 88 - * SA_DEFER needs to be set. 89 - */ 90 - sa.sa_handler = segfault; 91 - sigemptyset(&sa.sa_mask); 92 - sa.sa_flags = SA_NODEFER; 93 - if (sigaction(SIGSEGV, &sa, &old)) { 94 - perror("os_get_top_address"); 95 - exit(1); 96 - } 97 - 98 - /* Manually scan the address space, bottom-up, until we find 99 - * the first valid page (or run out of them). 100 - */ 101 - for (bottom = 0; bottom < top; bottom++) { 102 - if (page_ok(bottom)) 103 - break; 104 - } 105 - 106 - /* If we've got this far, we ran out of pages. */ 107 - if (bottom == top) { 108 - fprintf(stderr, "Unable to determine bottom of address " 109 - "space.\n"); 110 - exit(1); 111 - } 112 - 113 - printf("0x%lx\n", bottom << UM_KERN_PAGE_SHIFT); 114 - printf("Locating the top of the address space ... "); 115 - fflush(stdout); 116 - 117 - original = bottom; 118 - 119 - /* This could happen with a 4G/4G split */ 120 - if (page_ok(top)) 121 - goto out; 122 - 123 - do { 124 - test = bottom + (top - bottom) / 2; 125 - if (page_ok(test)) 126 - bottom = test; 127 - else 128 - top = test; 129 - } while (top - bottom > 1); 130 - 131 - out: 132 - /* Restore the old SIGSEGV handling */ 133 - if (sigaction(SIGSEGV, &old, NULL)) { 134 - perror("os_get_top_address"); 135 - exit(1); 136 - } 137 - top <<= UM_KERN_PAGE_SHIFT; 138 - printf("0x%lx\n", top); 139 - 140 - return top; 141 - } 142 - 143 - #else 144 - 145 - unsigned long os_get_top_address(void) 146 - { 147 - /* The old value of CONFIG_TOP_ADDR */ 148 - return 0x7fc0002000; 149 - } 150 - 151 - #endif
+267
arch/x86/um/ptrace.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/sched.h> 4 + #include <linux/elf.h> 5 + #include <linux/regset.h> 6 + #include <asm/user32.h> 7 + #include <asm/sigcontext.h> 8 + 9 + #ifdef CONFIG_X86_32 10 + /* 11 + * FPU tag word conversions. 12 + */ 13 + 14 + static inline unsigned short twd_i387_to_fxsr(unsigned short twd) 15 + { 16 + unsigned int tmp; /* to avoid 16 bit prefixes in the code */ 17 + 18 + /* Transform each pair of bits into 01 (valid) or 00 (empty) */ 19 + tmp = ~twd; 20 + tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ 21 + /* and move the valid bits to the lower byte. */ 22 + tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ 23 + tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ 24 + tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ 25 + return tmp; 26 + } 27 + 28 + static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave) 29 + { 30 + struct _fpxreg *st = NULL; 31 + unsigned long twd = (unsigned long) fxsave->twd; 32 + unsigned long tag; 33 + unsigned long ret = 0xffff0000; 34 + int i; 35 + 36 + #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16) 37 + 38 + for (i = 0; i < 8; i++) { 39 + if (twd & 0x1) { 40 + st = (struct _fpxreg *) FPREG_ADDR(fxsave, i); 41 + 42 + switch (st->exponent & 0x7fff) { 43 + case 0x7fff: 44 + tag = 2; /* Special */ 45 + break; 46 + case 0x0000: 47 + if (!st->significand[0] && 48 + !st->significand[1] && 49 + !st->significand[2] && 50 + !st->significand[3]) { 51 + tag = 1; /* Zero */ 52 + } else { 53 + tag = 2; /* Special */ 54 + } 55 + break; 56 + default: 57 + if (st->significand[3] & 0x8000) 58 + tag = 0; /* Valid */ 59 + else 60 + tag = 2; /* Special */ 61 + break; 62 + } 63 + } else { 64 + tag = 3; /* Empty */ 65 + } 66 + ret |= (tag << (2 * i)); 67 + twd = twd >> 1; 68 + } 69 + return ret; 70 + } 71 + 72 + /* Get/set the old 32bit i387 registers (pre-FPX) */ 73 + static int fpregs_legacy_get(struct task_struct *target, 74 + const struct user_regset *regset, 75 + struct membuf to) 76 + { 77 + struct user_fxsr_struct *fxsave = (void *)target->thread.regs.regs.fp; 78 + int i; 79 + 80 + membuf_store(&to, (unsigned long)fxsave->cwd | 0xffff0000ul); 81 + membuf_store(&to, (unsigned long)fxsave->swd | 0xffff0000ul); 82 + membuf_store(&to, twd_fxsr_to_i387(fxsave)); 83 + membuf_store(&to, fxsave->fip); 84 + membuf_store(&to, fxsave->fcs | ((unsigned long)fxsave->fop << 16)); 85 + membuf_store(&to, fxsave->foo); 86 + membuf_store(&to, fxsave->fos); 87 + 88 + for (i = 0; i < 8; i++) 89 + membuf_write(&to, (void *)fxsave->st_space + i * 16, 10); 90 + 91 + return 0; 92 + } 93 + 94 + static int fpregs_legacy_set(struct task_struct *target, 95 + const struct user_regset *regset, 96 + unsigned int pos, unsigned int count, 97 + const void *kbuf, const void __user *ubuf) 98 + { 99 + struct user_fxsr_struct *fxsave = (void *)target->thread.regs.regs.fp; 100 + const struct user_i387_struct *from; 101 + struct user_i387_struct buf; 102 + int i; 103 + 104 + if (ubuf) { 105 + if (copy_from_user(&buf, ubuf, sizeof(buf))) 106 + return -EFAULT; 107 + from = &buf; 108 + } else { 109 + from = kbuf; 110 + } 111 + 112 + fxsave->cwd = (unsigned short)(from->cwd & 0xffff); 113 + fxsave->swd = (unsigned short)(from->swd & 0xffff); 114 + fxsave->twd = twd_i387_to_fxsr((unsigned short)(from->twd & 0xffff)); 115 + fxsave->fip = from->fip; 116 + fxsave->fop = (unsigned short)((from->fcs & 0xffff0000ul) >> 16); 117 + fxsave->fcs = (from->fcs & 0xffff); 118 + fxsave->foo = from->foo; 119 + fxsave->fos = from->fos; 120 + 121 + for (i = 0; i < 8; i++) { 122 + memcpy((void *)fxsave->st_space + i * 16, 123 + (void *)from->st_space + i * 10, 10); 124 + } 125 + 126 + return 0; 127 + } 128 + #endif 129 + 130 + static int genregs_get(struct task_struct *target, 131 + const struct user_regset *regset, 132 + struct membuf to) 133 + { 134 + int reg; 135 + 136 + for (reg = 0; to.left; reg++) 137 + membuf_store(&to, getreg(target, reg * sizeof(unsigned long))); 138 + return 0; 139 + } 140 + 141 + static int genregs_set(struct task_struct *target, 142 + const struct user_regset *regset, 143 + unsigned int pos, unsigned int count, 144 + const void *kbuf, const void __user *ubuf) 145 + { 146 + int ret = 0; 147 + 148 + if (kbuf) { 149 + const unsigned long *k = kbuf; 150 + 151 + while (count >= sizeof(*k) && !ret) { 152 + ret = putreg(target, pos, *k++); 153 + count -= sizeof(*k); 154 + pos += sizeof(*k); 155 + } 156 + } else { 157 + const unsigned long __user *u = ubuf; 158 + 159 + while (count >= sizeof(*u) && !ret) { 160 + unsigned long word; 161 + 162 + ret = __get_user(word, u++); 163 + if (ret) 164 + break; 165 + ret = putreg(target, pos, word); 166 + count -= sizeof(*u); 167 + pos += sizeof(*u); 168 + } 169 + } 170 + return ret; 171 + } 172 + 173 + static int generic_fpregs_active(struct task_struct *target, const struct user_regset *regset) 174 + { 175 + return regset->n; 176 + } 177 + 178 + static int generic_fpregs_get(struct task_struct *target, 179 + const struct user_regset *regset, 180 + struct membuf to) 181 + { 182 + void *fpregs = task_pt_regs(target)->regs.fp; 183 + 184 + membuf_write(&to, fpregs, regset->size * regset->n); 185 + return 0; 186 + } 187 + 188 + static int generic_fpregs_set(struct task_struct *target, 189 + const struct user_regset *regset, 190 + unsigned int pos, unsigned int count, 191 + const void *kbuf, const void __user *ubuf) 192 + { 193 + void *fpregs = task_pt_regs(target)->regs.fp; 194 + 195 + return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 196 + fpregs, 0, regset->size * regset->n); 197 + } 198 + 199 + static struct user_regset uml_regsets[] __ro_after_init = { 200 + [REGSET_GENERAL] = { 201 + .core_note_type = NT_PRSTATUS, 202 + .n = sizeof(struct user_regs_struct) / sizeof(long), 203 + .size = sizeof(long), 204 + .align = sizeof(long), 205 + .regset_get = genregs_get, 206 + .set = genregs_set 207 + }, 208 + #ifdef CONFIG_X86_32 209 + /* Old FP registers, they are needed in signal frames */ 210 + [REGSET_FP_LEGACY] = { 211 + .core_note_type = NT_PRFPREG, 212 + .n = sizeof(struct user_i387_ia32_struct) / sizeof(long), 213 + .size = sizeof(long), 214 + .align = sizeof(long), 215 + .active = generic_fpregs_active, 216 + .regset_get = fpregs_legacy_get, 217 + .set = fpregs_legacy_set, 218 + }, 219 + #endif 220 + [REGSET_FP] = { 221 + #ifdef CONFIG_X86_32 222 + .core_note_type = NT_PRXFPREG, 223 + .n = sizeof(struct user32_fxsr_struct) / sizeof(long), 224 + #else 225 + .core_note_type = NT_PRFPREG, 226 + .n = sizeof(struct user_i387_struct) / sizeof(long), 227 + #endif 228 + .size = sizeof(long), 229 + .align = sizeof(long), 230 + .active = generic_fpregs_active, 231 + .regset_get = generic_fpregs_get, 232 + .set = generic_fpregs_set, 233 + }, 234 + [REGSET_XSTATE] = { 235 + .core_note_type = NT_X86_XSTATE, 236 + .size = sizeof(long), 237 + .align = sizeof(long), 238 + .active = generic_fpregs_active, 239 + .regset_get = generic_fpregs_get, 240 + .set = generic_fpregs_set, 241 + }, 242 + /* TODO: Add TLS regset for 32bit */ 243 + }; 244 + 245 + static const struct user_regset_view user_uml_view = { 246 + #ifdef CONFIG_X86_32 247 + .name = "i386", .e_machine = EM_386, 248 + #else 249 + .name = "x86_64", .e_machine = EM_X86_64, 250 + #endif 251 + .regsets = uml_regsets, .n = ARRAY_SIZE(uml_regsets) 252 + }; 253 + 254 + const struct user_regset_view * 255 + task_user_regset_view(struct task_struct *tsk) 256 + { 257 + return &user_uml_view; 258 + } 259 + 260 + static int __init init_regset_xstate_info(void) 261 + { 262 + uml_regsets[REGSET_XSTATE].n = 263 + host_fp_size / uml_regsets[REGSET_XSTATE].size; 264 + 265 + return 0; 266 + } 267 + arch_initcall(init_regset_xstate_info);
+17 -67
arch/x86/um/ptrace_32.c
··· 6 6 #include <linux/mm.h> 7 7 #include <linux/sched.h> 8 8 #include <linux/uaccess.h> 9 + #include <linux/regset.h> 9 10 #include <asm/ptrace-abi.h> 10 11 #include <registers.h> 11 12 #include <skas.h> ··· 169 168 return put_user(tmp, (unsigned long __user *) data); 170 169 } 171 170 172 - static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 173 - { 174 - int err, n, cpu = task_cpu(child); 175 - struct user_i387_struct fpregs; 176 - 177 - err = save_i387_registers(userspace_pid[cpu], 178 - (unsigned long *) &fpregs); 179 - if (err) 180 - return err; 181 - 182 - n = copy_to_user(buf, &fpregs, sizeof(fpregs)); 183 - if(n > 0) 184 - return -EFAULT; 185 - 186 - return n; 187 - } 188 - 189 - static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 190 - { 191 - int n, cpu = task_cpu(child); 192 - struct user_i387_struct fpregs; 193 - 194 - n = copy_from_user(&fpregs, buf, sizeof(fpregs)); 195 - if (n > 0) 196 - return -EFAULT; 197 - 198 - return restore_i387_registers(userspace_pid[cpu], 199 - (unsigned long *) &fpregs); 200 - } 201 - 202 - static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) 203 - { 204 - int err, n, cpu = task_cpu(child); 205 - struct user_fxsr_struct fpregs; 206 - 207 - err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs); 208 - if (err) 209 - return err; 210 - 211 - n = copy_to_user(buf, &fpregs, sizeof(fpregs)); 212 - if(n > 0) 213 - return -EFAULT; 214 - 215 - return n; 216 - } 217 - 218 - static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) 219 - { 220 - int n, cpu = task_cpu(child); 221 - struct user_fxsr_struct fpregs; 222 - 223 - n = copy_from_user(&fpregs, buf, sizeof(fpregs)); 224 - if (n > 0) 225 - return -EFAULT; 226 - 227 - return restore_fpx_registers(userspace_pid[cpu], 228 - (unsigned long *) &fpregs); 229 - } 230 - 231 171 long subarch_ptrace(struct task_struct *child, long request, 232 172 unsigned long addr, unsigned long data) 233 173 { ··· 176 234 void __user *datap = (void __user *) data; 177 235 switch (request) { 178 236 case PTRACE_GETFPREGS: /* Get the child FPU state. */ 179 - ret = get_fpregs(datap, child); 180 - break; 237 + return copy_regset_to_user(child, task_user_regset_view(child), 238 + REGSET_FP_LEGACY, 239 + 0, sizeof(struct user_i387_struct), 240 + datap); 181 241 case PTRACE_SETFPREGS: /* Set the child FPU state. */ 182 - ret = set_fpregs(datap, child); 183 - break; 242 + return copy_regset_from_user(child, task_user_regset_view(child), 243 + REGSET_FP_LEGACY, 244 + 0, sizeof(struct user_i387_struct), 245 + datap); 184 246 case PTRACE_GETFPXREGS: /* Get the child FPU state. */ 185 - ret = get_fpxregs(datap, child); 186 - break; 247 + return copy_regset_to_user(child, task_user_regset_view(child), 248 + REGSET_FP, 249 + 0, sizeof(struct user_fxsr_struct), 250 + datap); 187 251 case PTRACE_SETFPXREGS: /* Set the child FPU state. */ 188 - ret = set_fpxregs(datap, child); 189 - break; 252 + return copy_regset_from_user(child, task_user_regset_view(child), 253 + REGSET_FP, 254 + 0, sizeof(struct user_fxsr_struct), 255 + datap); 190 256 default: 191 257 ret = -EIO; 192 258 }
+9 -34
arch/x86/um/ptrace_64.c
··· 8 8 #include <linux/mm.h> 9 9 #include <linux/sched.h> 10 10 #include <linux/errno.h> 11 + #include <linux/regset.h> 11 12 #define __FRAME_OFFSETS 12 13 #include <asm/ptrace.h> 13 14 #include <linux/uaccess.h> ··· 189 188 return put_user(tmp, (unsigned long *) data); 190 189 } 191 190 192 - static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 193 - { 194 - int err, n, cpu = ((struct thread_info *) child->stack)->cpu; 195 - struct user_i387_struct fpregs; 196 - 197 - err = save_i387_registers(userspace_pid[cpu], 198 - (unsigned long *) &fpregs); 199 - if (err) 200 - return err; 201 - 202 - n = copy_to_user(buf, &fpregs, sizeof(fpregs)); 203 - if (n > 0) 204 - return -EFAULT; 205 - 206 - return n; 207 - } 208 - 209 - static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 210 - { 211 - int n, cpu = ((struct thread_info *) child->stack)->cpu; 212 - struct user_i387_struct fpregs; 213 - 214 - n = copy_from_user(&fpregs, buf, sizeof(fpregs)); 215 - if (n > 0) 216 - return -EFAULT; 217 - 218 - return restore_i387_registers(userspace_pid[cpu], 219 - (unsigned long *) &fpregs); 220 - } 221 - 222 191 long subarch_ptrace(struct task_struct *child, long request, 223 192 unsigned long addr, unsigned long data) 224 193 { ··· 197 226 198 227 switch (request) { 199 228 case PTRACE_GETFPREGS: /* Get the child FPU state. */ 200 - ret = get_fpregs(datap, child); 201 - break; 229 + return copy_regset_to_user(child, task_user_regset_view(child), 230 + REGSET_FP, 231 + 0, sizeof(struct user_i387_struct), 232 + datap); 202 233 case PTRACE_SETFPREGS: /* Set the child FPU state. */ 203 - ret = set_fpregs(datap, child); 204 - break; 234 + return copy_regset_from_user(child, task_user_regset_view(child), 235 + REGSET_FP, 236 + 0, sizeof(struct user_i387_struct), 237 + datap); 205 238 case PTRACE_ARCH_PRCTL: 206 239 /* XXX Calls ptrace on the host - needs some SMP thinking */ 207 240 ret = arch_prctl(child, data, (void __user *) addr);
+7 -1
arch/x86/um/shared/sysdep/ptrace.h
··· 56 56 UPT_SYSCALL_ARG5(r), \ 57 57 UPT_SYSCALL_ARG6(r) } } ) 58 58 59 + extern unsigned long host_fp_size; 60 + 59 61 struct uml_pt_regs { 60 62 unsigned long gp[MAX_REG_NR]; 61 - unsigned long fp[MAX_FP_NR]; 62 63 struct faultinfo faultinfo; 63 64 long syscall; 64 65 int is_user; 66 + 67 + /* Dynamically sized FP registers (holds an XSTATE) */ 68 + unsigned long fp[]; 65 69 }; 66 70 67 71 #define EMPTY_UML_PT_REGS { } ··· 75 71 #define UPT_IS_USER(r) ((r)->is_user) 76 72 77 73 extern int user_context(unsigned long sp); 74 + 75 + extern int arch_init_registers(int pid); 78 76 79 77 #endif /* __SYSDEP_X86_PTRACE_H */
-4
arch/x86/um/shared/sysdep/ptrace_32.h
··· 6 6 #ifndef __SYSDEP_I386_PTRACE_H 7 7 #define __SYSDEP_I386_PTRACE_H 8 8 9 - #define MAX_FP_NR HOST_FPX_SIZE 10 - 11 9 #define UPT_SYSCALL_ARG1(r) UPT_BX(r) 12 10 #define UPT_SYSCALL_ARG2(r) UPT_CX(r) 13 11 #define UPT_SYSCALL_ARG3(r) UPT_DX(r) 14 12 #define UPT_SYSCALL_ARG4(r) UPT_SI(r) 15 13 #define UPT_SYSCALL_ARG5(r) UPT_DI(r) 16 14 #define UPT_SYSCALL_ARG6(r) UPT_BP(r) 17 - 18 - extern void arch_init_registers(int pid); 19 15 20 16 #endif
-4
arch/x86/um/shared/sysdep/ptrace_64.h
··· 8 8 #ifndef __SYSDEP_X86_64_PTRACE_H 9 9 #define __SYSDEP_X86_64_PTRACE_H 10 10 11 - #define MAX_FP_NR HOST_FP_SIZE 12 - 13 11 #define REGS_R8(r) ((r)[HOST_R8]) 14 12 #define REGS_R9(r) ((r)[HOST_R9]) 15 13 #define REGS_R10(r) ((r)[HOST_R10]) ··· 54 56 #define UPT_SYSCALL_ARG4(r) UPT_R10(r) 55 57 #define UPT_SYSCALL_ARG5(r) UPT_R8(r) 56 58 #define UPT_SYSCALL_ARG6(r) UPT_R9(r) 57 - 58 - extern void arch_init_registers(int pid); 59 59 60 60 #endif
-6
arch/x86/um/shared/sysdep/ptrace_user.h
··· 11 11 #define REGS_IP_INDEX HOST_IP 12 12 #define REGS_SP_INDEX HOST_SP 13 13 14 - #ifdef __i386__ 15 - #define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE) 16 - #else 17 - #define FP_SIZE HOST_FP_SIZE 18 - #endif 19 - 20 14 /* 21 15 * glibc before 2.27 does not include PTRACE_SYSEMU_SINGLESTEP in its enum, 22 16 * ensure we have a definition by (re-)defining it here.
+15 -3
arch/x86/um/shared/sysdep/stub_32.h
··· 112 112 unsigned long ret; 113 113 114 114 asm volatile ( 115 - "movl %%esp,%0 ;" 116 - "andl %1,%0" 115 + "call _here_%=;" 116 + "_here_%=:" 117 + "popl %0;" 118 + "andl %1, %0 ;" 119 + "addl %2, %0 ;" 117 120 : "=a" (ret) 118 - : "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1))); 121 + : "g" (~(UM_KERN_PAGE_SIZE - 1)), 122 + "g" (UM_KERN_PAGE_SIZE)); 119 123 120 124 return (void *)ret; 121 125 } 126 + 127 + #define stub_start(fn) \ 128 + asm volatile ( \ 129 + "subl %0,%%esp ;" \ 130 + "movl %1, %%eax ; " \ 131 + "call *%%eax ;" \ 132 + :: "i" ((1 + STUB_DATA_PAGES) * UM_KERN_PAGE_SIZE), \ 133 + "i" (&fn)) 122 134 #endif
+24 -3
arch/x86/um/shared/sysdep/stub_64.h
··· 28 28 return ret; 29 29 } 30 30 31 + static __always_inline long stub_syscall1(long syscall, long arg1) 32 + { 33 + long ret; 34 + 35 + __asm__ volatile (__syscall 36 + : "=a" (ret) 37 + : "0" (syscall), "D" (arg1) : __syscall_clobber ); 38 + 39 + return ret; 40 + } 41 + 31 42 static __always_inline long stub_syscall2(long syscall, long arg1, long arg2) 32 43 { 33 44 long ret; ··· 117 106 unsigned long ret; 118 107 119 108 asm volatile ( 120 - "movq %%rsp,%0 ;" 121 - "andq %1,%0" 109 + "lea 0(%%rip), %0;" 110 + "andq %1, %0 ;" 111 + "addq %2, %0 ;" 122 112 : "=a" (ret) 123 - : "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1))); 113 + : "g" (~(UM_KERN_PAGE_SIZE - 1)), 114 + "g" (UM_KERN_PAGE_SIZE)); 124 115 125 116 return (void *)ret; 126 117 } 118 + 119 + #define stub_start(fn) \ 120 + asm volatile ( \ 121 + "subq %0,%%rsp ;" \ 122 + "movq %1,%%rax ;" \ 123 + "call *%%rax ;" \ 124 + :: "i" ((1 + STUB_DATA_PAGES) * UM_KERN_PAGE_SIZE), \ 125 + "i" (&fn)) 127 126 #endif
+108 -228
arch/x86/um/signal.c
··· 16 16 #include <registers.h> 17 17 #include <skas.h> 18 18 19 + #include <linux/regset.h> 20 + #include <asm/sigframe.h> 21 + 19 22 #ifdef CONFIG_X86_32 20 - 21 - /* 22 - * FPU tag word conversions. 23 - */ 24 - 25 - static inline unsigned short twd_i387_to_fxsr(unsigned short twd) 26 - { 27 - unsigned int tmp; /* to avoid 16 bit prefixes in the code */ 28 - 29 - /* Transform each pair of bits into 01 (valid) or 00 (empty) */ 30 - tmp = ~twd; 31 - tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ 32 - /* and move the valid bits to the lower byte. */ 33 - tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ 34 - tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ 35 - tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ 36 - return tmp; 37 - } 38 - 39 - static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave) 40 - { 41 - struct _fpxreg *st = NULL; 42 - unsigned long twd = (unsigned long) fxsave->twd; 43 - unsigned long tag; 44 - unsigned long ret = 0xffff0000; 45 - int i; 46 - 47 - #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16) 48 - 49 - for (i = 0; i < 8; i++) { 50 - if (twd & 0x1) { 51 - st = (struct _fpxreg *) FPREG_ADDR(fxsave, i); 52 - 53 - switch (st->exponent & 0x7fff) { 54 - case 0x7fff: 55 - tag = 2; /* Special */ 56 - break; 57 - case 0x0000: 58 - if ( !st->significand[0] && 59 - !st->significand[1] && 60 - !st->significand[2] && 61 - !st->significand[3] ) { 62 - tag = 1; /* Zero */ 63 - } else { 64 - tag = 2; /* Special */ 65 - } 66 - break; 67 - default: 68 - if (st->significand[3] & 0x8000) { 69 - tag = 0; /* Valid */ 70 - } else { 71 - tag = 2; /* Special */ 72 - } 73 - break; 74 - } 75 - } else { 76 - tag = 3; /* Empty */ 77 - } 78 - ret |= (tag << (2 * i)); 79 - twd = twd >> 1; 80 - } 81 - return ret; 82 - } 83 - 84 - static int convert_fxsr_to_user(struct _fpstate __user *buf, 85 - struct user_fxsr_struct *fxsave) 86 - { 87 - unsigned long env[7]; 88 - struct _fpreg __user *to; 89 - struct _fpxreg *from; 90 - int i; 91 - 92 - env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul; 93 - env[1] = (unsigned long)fxsave->swd | 0xffff0000ul; 94 - env[2] = twd_fxsr_to_i387(fxsave); 95 - env[3] = fxsave->fip; 96 - env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); 97 - env[5] = fxsave->foo; 98 - env[6] = fxsave->fos; 99 - 100 - if (__copy_to_user(buf, env, 7 * sizeof(unsigned long))) 101 - return 1; 102 - 103 - to = &buf->_st[0]; 104 - from = (struct _fpxreg *) &fxsave->st_space[0]; 105 - for (i = 0; i < 8; i++, to++, from++) { 106 - unsigned long __user *t = (unsigned long __user *)to; 107 - unsigned long *f = (unsigned long *)from; 108 - 109 - if (__put_user(*f, t) || 110 - __put_user(*(f + 1), t + 1) || 111 - __put_user(from->exponent, &to->exponent)) 112 - return 1; 113 - } 114 - return 0; 115 - } 116 - 117 - static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave, 118 - struct _fpstate __user *buf) 119 - { 120 - unsigned long env[7]; 121 - struct _fpxreg *to; 122 - struct _fpreg __user *from; 123 - int i; 124 - 125 - if (copy_from_user( env, buf, 7 * sizeof(long))) 126 - return 1; 127 - 128 - fxsave->cwd = (unsigned short)(env[0] & 0xffff); 129 - fxsave->swd = (unsigned short)(env[1] & 0xffff); 130 - fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); 131 - fxsave->fip = env[3]; 132 - fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16); 133 - fxsave->fcs = (env[4] & 0xffff); 134 - fxsave->foo = env[5]; 135 - fxsave->fos = env[6]; 136 - 137 - to = (struct _fpxreg *) &fxsave->st_space[0]; 138 - from = &buf->_st[0]; 139 - for (i = 0; i < 8; i++, to++, from++) { 140 - unsigned long *t = (unsigned long *)to; 141 - unsigned long __user *f = (unsigned long __user *)from; 142 - 143 - if (__get_user(*t, f) || 144 - __get_user(*(t + 1), f + 1) || 145 - __get_user(to->exponent, &from->exponent)) 146 - return 1; 147 - } 148 - return 0; 149 - } 150 - 151 - extern int have_fpx_regs; 152 - 23 + struct _xstate_64 { 24 + struct _fpstate_64 fpstate; 25 + struct _header xstate_hdr; 26 + struct _ymmh_state ymmh; 27 + /* New processor state extensions go here: */ 28 + }; 29 + #else 30 + #define _xstate_64 _xstate 153 31 #endif 154 32 155 33 static int copy_sc_from_user(struct pt_regs *regs, 156 34 struct sigcontext __user *from) 157 35 { 36 + struct _xstate_64 __user *from_fp64; 158 37 struct sigcontext sc; 159 38 int err; 160 39 ··· 82 203 #undef GETREG 83 204 84 205 #ifdef CONFIG_X86_32 85 - if (have_fpx_regs) { 86 - struct user_fxsr_struct fpx; 87 - int pid = userspace_pid[current_thread_info()->cpu]; 88 - 89 - err = copy_from_user(&fpx, 90 - &((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0], 91 - sizeof(struct user_fxsr_struct)); 92 - if (err) 93 - return 1; 94 - 95 - err = convert_fxsr_from_user(&fpx, (void *)sc.fpstate); 96 - if (err) 97 - return 1; 98 - 99 - err = restore_fpx_registers(pid, (unsigned long *) &fpx); 100 - if (err < 0) { 101 - printk(KERN_ERR "copy_sc_from_user - " 102 - "restore_fpx_registers failed, errno = %d\n", 103 - -err); 104 - return 1; 105 - } 106 - } else 206 + from_fp64 = ((void __user *)sc.fpstate) + 207 + offsetof(struct _fpstate_32, _fxsr_env); 208 + #else 209 + from_fp64 = (void __user *)sc.fpstate; 107 210 #endif 108 - { 109 - err = copy_from_user(regs->regs.fp, (void *)sc.fpstate, 110 - sizeof(struct _xstate)); 111 - if (err) 112 - return 1; 113 - } 211 + 212 + err = copy_from_user(regs->regs.fp, from_fp64, host_fp_size); 213 + if (err) 214 + return 1; 215 + 216 + #ifdef CONFIG_X86_32 217 + /* Data is duplicated and this copy is the important one */ 218 + err = copy_regset_from_user(current, 219 + task_user_regset_view(current), 220 + REGSET_FP_LEGACY, 0, 221 + sizeof(struct user_i387_struct), 222 + (void __user *)sc.fpstate); 223 + if (err < 0) 224 + return err; 225 + #endif 226 + 114 227 return 0; 115 228 } 116 229 ··· 110 239 struct _xstate __user *to_fp, struct pt_regs *regs, 111 240 unsigned long mask) 112 241 { 242 + struct _xstate_64 __user *to_fp64; 113 243 struct sigcontext sc; 114 244 struct faultinfo * fi = &current->thread.arch.faultinfo; 115 245 int err; ··· 162 290 return 1; 163 291 164 292 #ifdef CONFIG_X86_32 165 - if (have_fpx_regs) { 166 - int pid = userspace_pid[current_thread_info()->cpu]; 167 - struct user_fxsr_struct fpx; 293 + err = copy_regset_to_user(current, 294 + task_user_regset_view(current), 295 + REGSET_FP_LEGACY, 0, 296 + sizeof(struct _fpstate_32), to_fp); 297 + if (err < 0) 298 + return err; 168 299 169 - err = save_fpx_registers(pid, (unsigned long *) &fpx); 170 - if (err < 0){ 171 - printk(KERN_ERR "copy_sc_to_user - save_fpx_registers " 172 - "failed, errno = %d\n", err); 173 - return 1; 174 - } 300 + __put_user(X86_FXSR_MAGIC, &to_fp->fpstate.magic); 175 301 176 - err = convert_fxsr_to_user(&to_fp->fpstate, &fpx); 177 - if (err) 178 - return 1; 302 + BUILD_BUG_ON(offsetof(struct _xstate, xstate_hdr) != 303 + offsetof(struct _xstate_64, xstate_hdr) + 304 + offsetof(struct _fpstate_32, _fxsr_env)); 305 + to_fp64 = (void __user *)to_fp + 306 + offsetof(struct _fpstate_32, _fxsr_env); 307 + #else 308 + to_fp64 = to_fp; 309 + #endif /* CONFIG_X86_32 */ 179 310 180 - err |= __put_user(fpx.swd, &to_fp->fpstate.status); 181 - err |= __put_user(X86_FXSR_MAGIC, &to_fp->fpstate.magic); 182 - if (err) 183 - return 1; 311 + if (copy_to_user(to_fp64, regs->regs.fp, host_fp_size)) 312 + return 1; 184 313 185 - if (copy_to_user(&to_fp->fpstate._fxsr_env[0], &fpx, 186 - sizeof(struct user_fxsr_struct))) 187 - return 1; 188 - } else 314 + /* 315 + * Put magic/size values for userspace. We do not bother to verify them 316 + * later on, however, userspace needs them should it try to read the 317 + * XSTATE data. And ptrace does not fill in these parts. 318 + */ 319 + BUILD_BUG_ON(sizeof(int) != FP_XSTATE_MAGIC2_SIZE); 320 + #ifdef CONFIG_X86_32 321 + __put_user(offsetof(struct _fpstate_32, _fxsr_env) + 322 + host_fp_size + FP_XSTATE_MAGIC2_SIZE, 323 + &to_fp64->fpstate.sw_reserved.extended_size); 324 + #else 325 + __put_user(host_fp_size + FP_XSTATE_MAGIC2_SIZE, 326 + &to_fp64->fpstate.sw_reserved.extended_size); 189 327 #endif 190 - { 191 - if (copy_to_user(to_fp, regs->regs.fp, sizeof(struct _xstate))) 192 - return 1; 193 - } 328 + __put_user(host_fp_size, &to_fp64->fpstate.sw_reserved.xstate_size); 329 + 330 + __put_user(FP_XSTATE_MAGIC1, &to_fp64->fpstate.sw_reserved.magic1); 331 + __put_user(FP_XSTATE_MAGIC2, 332 + (int __user *)((void __user *)to_fp64 + host_fp_size)); 194 333 195 334 return 0; 196 335 } ··· 219 336 return err; 220 337 } 221 338 222 - struct sigframe 223 - { 224 - char __user *pretcode; 225 - int sig; 226 - struct sigcontext sc; 227 - struct _xstate fpstate; 228 - unsigned long extramask[_NSIG_WORDS-1]; 229 - char retcode[8]; 230 - }; 231 - 232 - struct rt_sigframe 233 - { 234 - char __user *pretcode; 235 - int sig; 236 - struct siginfo __user *pinfo; 237 - void __user *puc; 238 - struct siginfo info; 239 - struct ucontext uc; 240 - struct _xstate fpstate; 241 - char retcode[8]; 242 - }; 243 - 244 339 int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig, 245 340 struct pt_regs *regs, sigset_t *mask) 246 341 { 342 + size_t math_size = offsetof(struct _fpstate_32, _fxsr_env) + 343 + host_fp_size + FP_XSTATE_MAGIC2_SIZE; 247 344 struct sigframe __user *frame; 248 345 void __user *restorer; 249 346 int err = 0, sig = ksig->sig; 347 + unsigned long fp_to; 250 348 251 349 /* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */ 252 350 stack_top = ((stack_top + 4) & -16UL) - 4; ··· 235 371 if (!access_ok(frame, sizeof(*frame))) 236 372 return 1; 237 373 374 + /* Add required space for math frame */ 375 + frame = (struct sigframe __user *)((unsigned long)frame - math_size); 376 + 238 377 restorer = frame->retcode; 239 378 if (ksig->ka.sa.sa_flags & SA_RESTORER) 240 379 restorer = ksig->ka.sa.sa_restorer; 241 380 242 - err |= __put_user(restorer, &frame->pretcode); 381 + err |= __put_user(restorer, (void __user * __user *)&frame->pretcode); 243 382 err |= __put_user(sig, &frame->sig); 244 - err |= copy_sc_to_user(&frame->sc, &frame->fpstate, regs, mask->sig[0]); 383 + 384 + fp_to = (unsigned long)frame + sizeof(*frame); 385 + 386 + err |= copy_sc_to_user(&frame->sc, 387 + (struct _xstate __user *)fp_to, 388 + regs, mask->sig[0]); 245 389 if (_NSIG_WORDS > 1) 246 390 err |= __copy_to_user(&frame->extramask, &mask->sig[1], 247 391 sizeof(frame->extramask)); ··· 279 407 int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig, 280 408 struct pt_regs *regs, sigset_t *mask) 281 409 { 410 + size_t math_size = offsetof(struct _fpstate_32, _fxsr_env) + 411 + host_fp_size + FP_XSTATE_MAGIC2_SIZE; 282 412 struct rt_sigframe __user *frame; 283 413 void __user *restorer; 284 414 int err = 0, sig = ksig->sig; 415 + unsigned long fp_to; 285 416 286 417 stack_top &= -8UL; 287 418 frame = (struct rt_sigframe __user *) stack_top - 1; 288 419 if (!access_ok(frame, sizeof(*frame))) 289 420 return 1; 290 421 422 + /* Add required space for math frame */ 423 + frame = (struct rt_sigframe __user *)((unsigned long)frame - math_size); 424 + 291 425 restorer = frame->retcode; 292 426 if (ksig->ka.sa.sa_flags & SA_RESTORER) 293 427 restorer = ksig->ka.sa.sa_restorer; 294 428 295 - err |= __put_user(restorer, &frame->pretcode); 429 + err |= __put_user(restorer, (void __user * __user *)&frame->pretcode); 296 430 err |= __put_user(sig, &frame->sig); 297 - err |= __put_user(&frame->info, &frame->pinfo); 298 - err |= __put_user(&frame->uc, &frame->puc); 431 + err |= __put_user(&frame->info, (void __user * __user *)&frame->pinfo); 432 + err |= __put_user(&frame->uc, (void __user * __user *)&frame->puc); 299 433 err |= copy_siginfo_to_user(&frame->info, &ksig->info); 300 - err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask, 301 - PT_REGS_SP(regs)); 434 + 435 + fp_to = (unsigned long)frame + sizeof(*frame); 436 + 437 + err |= copy_ucontext_to_user(&frame->uc, (struct _xstate __user *)fp_to, 438 + mask, PT_REGS_SP(regs)); 302 439 303 440 /* 304 441 * This is movl $,%eax ; int $0x80 ··· 359 478 360 479 #else 361 480 362 - struct rt_sigframe 363 - { 364 - char __user *pretcode; 365 - struct ucontext uc; 366 - struct siginfo info; 367 - struct _xstate fpstate; 368 - }; 369 - 370 481 int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig, 371 482 struct pt_regs *regs, sigset_t *set) 372 483 { 484 + unsigned long math_size = host_fp_size + FP_XSTATE_MAGIC2_SIZE; 373 485 struct rt_sigframe __user *frame; 374 486 int err = 0, sig = ksig->sig; 375 487 unsigned long fp_to; 376 488 377 489 frame = (struct rt_sigframe __user *) 378 490 round_down(stack_top - sizeof(struct rt_sigframe), 16); 491 + 492 + /* Add required space for math frame */ 493 + frame = (struct rt_sigframe __user *)((unsigned long)frame - math_size); 494 + 379 495 /* Subtract 128 for a red zone and 8 for proper alignment */ 380 496 frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); 381 497 382 - if (!access_ok(frame, sizeof(*frame))) 498 + if (!access_ok(frame, sizeof(*frame) + math_size)) 383 499 goto out; 384 500 385 501 if (ksig->ka.sa.sa_flags & SA_SIGINFO) { ··· 387 509 388 510 /* Create the ucontext. */ 389 511 err |= __put_user(0, &frame->uc.uc_flags); 390 - err |= __put_user(0, &frame->uc.uc_link); 512 + err |= __put_user(NULL, &frame->uc.uc_link); 391 513 err |= __save_altstack(&frame->uc.uc_stack, PT_REGS_SP(regs)); 392 - err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs, 393 - set->sig[0]); 394 514 395 - fp_to = (unsigned long)&frame->fpstate; 515 + fp_to = (unsigned long)frame + sizeof(*frame); 516 + 517 + err |= copy_sc_to_user(&frame->uc.uc_mcontext, 518 + (struct _xstate __user *)fp_to, 519 + regs, set->sig[0]); 396 520 397 521 err |= __put_user(fp_to, &frame->uc.uc_mcontext.fpstate); 398 522 if (sizeof(*set) == 16) { ··· 411 531 */ 412 532 /* x86-64 should always use SA_RESTORER. */ 413 533 if (ksig->ka.sa.sa_flags & SA_RESTORER) 414 - err |= __put_user((void *)ksig->ka.sa.sa_restorer, 534 + err |= __put_user((void __user *)ksig->ka.sa.sa_restorer, 415 535 &frame->pretcode); 416 536 else 417 537 /* could use a vstub here */
-8
arch/x86/um/user-offsets.c
··· 20 20 void foo(void) 21 21 { 22 22 #ifdef __i386__ 23 - DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct)); 24 - DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct)); 25 - 26 23 DEFINE(HOST_IP, EIP); 27 24 DEFINE(HOST_SP, UESP); 28 25 DEFINE(HOST_EFLAGS, EFL); ··· 38 41 DEFINE(HOST_GS, GS); 39 42 DEFINE(HOST_ORIG_AX, ORIG_EAX); 40 43 #else 41 - #ifdef FP_XSTATE_MAGIC1 42 - DEFINE_LONGS(HOST_FP_SIZE, 2696); 43 - #else 44 - DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); 45 - #endif 46 44 DEFINE_LONGS(HOST_BX, RBX); 47 45 DEFINE_LONGS(HOST_CX, RCX); 48 46 DEFINE_LONGS(HOST_DI, RDI);
+2 -3
arch/x86/um/vdso/Makefile
··· 56 56 quiet_cmd_vdso = VDSO $@ 57 57 cmd_vdso = $(CC) -nostdlib -o $@ \ 58 58 $(CC_FLAGS_LTO) $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \ 59 - -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \ 60 - sh $(src)/checkundef.sh '$(NM)' '$@' 59 + -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) 61 60 62 - VDSO_LDFLAGS = -fPIC -shared -Wl,--hash-style=sysv -z noexecstack 61 + VDSO_LDFLAGS = -fPIC -shared -Wl,--hash-style=sysv -z noexecstack -Wl,--no-undefined
-11
arch/x86/um/vdso/checkundef.sh
··· 1 - #!/bin/sh 2 - # SPDX-License-Identifier: GPL-2.0 3 - nm="$1" 4 - file="$2" 5 - $nm "$file" | grep '^ *U' > /dev/null 2>&1 6 - if [ $? -eq 1 ]; then 7 - exit 0 8 - else 9 - echo "$file: undefined symbols found" >&2 10 - exit 1 11 - fi
+3 -2
fs/hostfs/hostfs_kern.c
··· 57 57 { 58 58 char *ptr; 59 59 60 + *add = 0; 60 61 ptr = strchr(options, ','); 61 62 if (ptr != NULL) 62 63 *ptr++ = '\0'; ··· 472 471 473 472 *foliop = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN, 474 473 mapping_gfp_mask(mapping)); 475 - if (!*foliop) 476 - return -ENOMEM; 474 + if (IS_ERR(*foliop)) 475 + return PTR_ERR(*foliop); 477 476 return 0; 478 477 } 479 478