From 039bd396a88b93edd0008cab8f0b2e597ec072cc Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 6 May 2022 09:18:15 +0800 Subject: [PATCH 01/71] sw64: remove unused header files Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- These header files have became unused for a long time. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/agp.h | 19 ---- arch/sw_64/include/asm/asm-prototypes.h | 1 - arch/sw_64/include/asm/compiler.h | 7 -- arch/sw_64/include/asm/console.h | 11 --- arch/sw_64/include/asm/elf.h | 6 +- arch/sw_64/include/asm/floppy.h | 116 ------------------------ arch/sw_64/include/asm/special_insns.h | 20 ---- arch/sw_64/include/uapi/asm/console.h | 51 ----------- 8 files changed, 2 insertions(+), 229 deletions(-) delete mode 100644 arch/sw_64/include/asm/agp.h delete mode 100644 arch/sw_64/include/asm/compiler.h delete mode 100644 arch/sw_64/include/asm/console.h delete mode 100644 arch/sw_64/include/asm/floppy.h delete mode 100644 arch/sw_64/include/asm/special_insns.h delete mode 100644 arch/sw_64/include/uapi/asm/console.h diff --git a/arch/sw_64/include/asm/agp.h b/arch/sw_64/include/asm/agp.h deleted file mode 100644 index e9d16888910e..000000000000 --- a/arch/sw_64/include/asm/agp.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_AGP_H -#define _ASM_SW64_AGP_H 1 - -#include - -/* dummy for now */ - -#define map_page_into_agp(page) -#define unmap_page_from_agp(page) -#define flush_agp_cache() mb() - -/* GATT allocation. Returns/accepts GATT kernel virtual address. */ -#define alloc_gatt_pages(order) \ - ((char *)__get_free_pages(GFP_KERNEL, (order))) -#define free_gatt_pages(table, order) \ - free_pages((unsigned long)(table), (order)) - -#endif diff --git a/arch/sw_64/include/asm/asm-prototypes.h b/arch/sw_64/include/asm/asm-prototypes.h index 21f4f494d74d..15bad8ef6883 100644 --- a/arch/sw_64/include/asm/asm-prototypes.h +++ b/arch/sw_64/include/asm/asm-prototypes.h @@ -4,7 +4,6 @@ #include #include -#include #include #include #include diff --git a/arch/sw_64/include/asm/compiler.h b/arch/sw_64/include/asm/compiler.h deleted file mode 100644 index 9a80aa6a0ba8..000000000000 --- a/arch/sw_64/include/asm/compiler.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_COMPILER_H -#define _ASM_SW64_COMPILER_H - -#include - -#endif /* _ASM_SW64_COMPILER_H */ diff --git a/arch/sw_64/include/asm/console.h b/arch/sw_64/include/asm/console.h deleted file mode 100644 index 0c01cb740bce..000000000000 --- a/arch/sw_64/include/asm/console.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_CONSOLE_H -#define _ASM_SW64_CONSOLE_H - -#include -#ifndef __ASSEMBLY__ -struct crb_struct; -extern int callback_init_done; -extern void callback_init(void); -#endif /* __ASSEMBLY__ */ -#endif /* _ASM_SW64_CONSOLE_H */ diff --git a/arch/sw_64/include/asm/elf.h b/arch/sw_64/include/asm/elf.h index 150629b0b615..abecc5653eba 100644 --- a/arch/sw_64/include/asm/elf.h +++ b/arch/sw_64/include/asm/elf.h @@ -3,7 +3,6 @@ #define _ASM_SW64_ELF_H #ifdef __KERNEL__ #include -#include #endif /* Special values for the st_other field in the symbol table. */ @@ -141,11 +140,10 @@ extern int dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task); /* * This yields a mask that user programs can use to figure out what - * instruction set this CPU supports. This is trivial on SW-64, - * but not so on other machines. + * instruction set this CPU supports. */ -#define ELF_HWCAP (~amask(-1)) +#define ELF_HWCAP 0 /* * This yields a string that ld.so will use to load implementation diff --git a/arch/sw_64/include/asm/floppy.h b/arch/sw_64/include/asm/floppy.h deleted file mode 100644 index f4646d99d80c..000000000000 --- a/arch/sw_64/include/asm/floppy.h +++ /dev/null @@ -1,116 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Architecture specific parts of the Floppy driver - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1995 - */ -#ifndef _ASM_SW64_FLOPPY_H -#define _ASM_SW64_FLOPPY_H - -#define fd_inb(port) inb_p(port) -#define fd_outb(value, port) outb_p(value, port) - -#define fd_enable_dma() enable_dma(FLOPPY_DMA) -#define fd_disable_dma() disable_dma(FLOPPY_DMA) -#define fd_request_dma() request_dma(FLOPPY_DMA, "floppy") -#define fd_free_dma() free_dma(FLOPPY_DMA) -#define fd_clear_dma_ff() clear_dma_ff(FLOPPY_DMA) -#define fd_set_dma_mode(mode) set_dma_mode(FLOPPY_DMA, mode) -#define fd_set_dma_addr(addr) set_dma_addr(FLOPPY_DMA, virt_to_bus(addr)) -#define fd_set_dma_count(count) set_dma_count(FLOPPY_DMA, count) -#define fd_enable_irq() enable_irq(FLOPPY_IRQ) -#define fd_disable_irq() disable_irq(FLOPPY_IRQ) -#define fd_cacheflush(addr, size) /* nothing */ -#define fd_request_irq() \ - request_irq(FLOPPY_IRQ, floppy_interrupt, 0, "floppy", NULL) -#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL) - -#ifdef CONFIG_PCI - -#include - -#define fd_dma_setup(addr, size, mode, io) \ - sw64_fd_dma_setup(addr, size, mode, io) - -static inline int -sw64_fd_dma_setup(char *addr, unsigned long size, int mode, int io) -{ - static unsigned long prev_size; - static dma_addr_t bus_addr; - static char *prev_addr; - static int prev_dir; - int dir; - - dir = (mode != DMA_MODE_READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE; - - if (bus_addr - && (addr != prev_addr || size != prev_size || dir != prev_dir)) { - /* different from last time -- unmap prev */ - bus_addr = 0; - } - - if (!bus_addr) /* need to map it */ - bus_addr = virt_to_bus(addr); - - /* remember this one as prev */ - prev_addr = addr; - prev_size = size; - prev_dir = dir; - - fd_clear_dma_ff(); - fd_cacheflush(addr, size); - fd_set_dma_mode(mode); - set_dma_addr(FLOPPY_DMA, bus_addr); - fd_set_dma_count(size); - virtual_dma_port = io; - fd_enable_dma(); - - return 0; -} - -#endif /* CONFIG_PCI */ - -inline void virtual_dma_init(void) -{ - /* Nothing to do on an sw64 */ -} - -static int FDC1 = 0x3f0; -static int FDC2 = -1; - -/* - * Again, the CMOS information doesn't work on the sw64.. - */ -#define FLOPPY0_TYPE 6 -#define FLOPPY1_TYPE 0 - -#define N_FDC 2 -#define N_DRIVE 8 - -/* - * Most sw64s have no problems with floppy DMA crossing 64k borders, - * except for certain ones, like XL and RUFFIAN. - * - * However, the test is simple and fast, and this *is* floppy, after all, - * so we do it for all platforms, just to make sure. - * - * This is advantageous in other circumstances as well, as in moving - * about the PCI DMA windows and forcing the floppy to start doing - * scatter-gather when it never had before, and there *is* a problem - * on that platform... ;-} - */ - -static inline unsigned long CROSS_64KB(void *a, unsigned long s) -{ - unsigned long p = (unsigned long)a; - - return ((p + s - 1) ^ p) & ~0xffffUL; -} - -#define EXTRA_FLOPPY_PARAMS - -#endif /* __ASM_SW64_FLOPPY_H */ diff --git a/arch/sw_64/include/asm/special_insns.h b/arch/sw_64/include/asm/special_insns.h deleted file mode 100644 index 7f5a52b20444..000000000000 --- a/arch/sw_64/include/asm/special_insns.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_SPECIAL_INSNS_H -#define _ASM_SW64_SPECIAL_INSNS_H - -enum amask_enum { - AMASK_BWX = (1UL << 0), - AMASK_FIX = (1UL << 1), - AMASK_CIX = (1UL << 2), - AMASK_MAX = (1UL << 8), - AMASK_PRECISE_TRAP = (1UL << 9), -}; - -#define amask(mask) \ -({ \ - unsigned long __amask, __input = (mask); \ - __asm__ ("mov %1, %0" : "=r"(__amask) : "rI"(__input)); \ - __amask; \ -}) - -#endif /* _ASM_SW64_SPECIAL_INSNS_H */ diff --git a/arch/sw_64/include/uapi/asm/console.h b/arch/sw_64/include/uapi/asm/console.h deleted file mode 100644 index a40cd7aeb31f..000000000000 --- a/arch/sw_64/include/uapi/asm/console.h +++ /dev/null @@ -1,51 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_ASM_SW64_CONSOLE_H -#define _UAPI_ASM_SW64_CONSOLE_H - -/* - * Console callback routine numbers - */ -#define CCB_GETC 0x01 -#define CCB_PUTS 0x02 -#define CCB_RESET_TERM 0x03 -#define CCB_SET_TERM_INT 0x04 -#define CCB_SET_TERM_CTL 0x05 -#define CCB_PROCESS_KEYCODE 0x06 -#define CCB_OPEN_CONSOLE 0x07 -#define CCB_CLOSE_CONSOLE 0x08 - -#define CCB_OPEN 0x10 -#define CCB_CLOSE 0x11 -#define CCB_IOCTL 0x12 -#define CCB_READ 0x13 -#define CCB_WRITE 0x14 - -#define CCB_SET_ENV 0x20 -#define CCB_RESET_ENV 0x21 -#define CCB_GET_ENV 0x22 -#define CCB_SAVE_ENV 0x23 - -#define CCB_PSWITCH 0x30 -#define CCB_BIOS_EMUL 0x32 - -/* - * Environment variable numbers - */ -#define ENV_AUTO_ACTION 0x01 -#define ENV_BOOT_DEV 0x02 -#define ENV_BOOTDEF_DEV 0x03 -#define ENV_BOOTED_DEV 0x04 -#define ENV_BOOT_FILE 0x05 -#define ENV_BOOTED_FILE 0x06 -#define ENV_BOOT_OSFLAGS 0x07 -#define ENV_BOOTED_OSFLAGS 0x08 -#define ENV_BOOT_RESET 0x09 -#define ENV_DUMP_DEV 0x0A -#define ENV_ENABLE_AUDIT 0x0B -#define ENV_LICENSE 0x0C -#define ENV_CHAR_SET 0x0D -#define ENV_LANGUAGE 0x0E -#define ENV_TTY_DEV 0x0F - - -#endif /* _UAPI_ASM_SW64_CONSOLE_H */ -- Gitee From 65d722507cd65bbf42f9c00d92c7016bc92968bf Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 6 May 2022 09:28:36 +0800 Subject: [PATCH 02/71] sw64: uapi: generate some uapi headers from generic ones Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- These uapi headers are proved to be the same with generic version. Herein we remove the arch-specific statfs.h and types.h to end support for old system. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/uapi/asm/Kbuild | 1 + arch/sw_64/include/uapi/asm/ipcbuf.h | 7 ---- arch/sw_64/include/uapi/asm/kvm_para.h | 7 ---- arch/sw_64/include/uapi/asm/msgbuf.h | 28 ---------------- arch/sw_64/include/uapi/asm/poll.h | 7 ---- arch/sw_64/include/uapi/asm/posix_types.h | 18 ----------- arch/sw_64/include/uapi/asm/sembuf.h | 23 ------------- arch/sw_64/include/uapi/asm/shmbuf.h | 39 ----------------------- arch/sw_64/include/uapi/asm/statfs.h | 9 ------ arch/sw_64/include/uapi/asm/types.h | 28 ---------------- 10 files changed, 1 insertion(+), 166 deletions(-) delete mode 100644 arch/sw_64/include/uapi/asm/ipcbuf.h delete mode 100644 arch/sw_64/include/uapi/asm/kvm_para.h delete mode 100644 arch/sw_64/include/uapi/asm/msgbuf.h delete mode 100644 arch/sw_64/include/uapi/asm/poll.h delete mode 100644 arch/sw_64/include/uapi/asm/posix_types.h delete mode 100644 arch/sw_64/include/uapi/asm/sembuf.h delete mode 100644 arch/sw_64/include/uapi/asm/shmbuf.h delete mode 100644 arch/sw_64/include/uapi/asm/statfs.h delete mode 100644 arch/sw_64/include/uapi/asm/types.h diff --git a/arch/sw_64/include/uapi/asm/Kbuild b/arch/sw_64/include/uapi/asm/Kbuild index a01bfb9600ec..15700040f138 100644 --- a/arch/sw_64/include/uapi/asm/Kbuild +++ b/arch/sw_64/include/uapi/asm/Kbuild @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 # UAPI Header export list +generic-y += kvm_para.h generated-y += unistd_64.h diff --git a/arch/sw_64/include/uapi/asm/ipcbuf.h b/arch/sw_64/include/uapi/asm/ipcbuf.h deleted file mode 100644 index 553cdb37052d..000000000000 --- a/arch/sw_64/include/uapi/asm/ipcbuf.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_ASM_SW64_IPCBUF_H -#define _UAPI_ASM_SW64_IPCBUF_H - -#include - -#endif diff --git a/arch/sw_64/include/uapi/asm/kvm_para.h b/arch/sw_64/include/uapi/asm/kvm_para.h deleted file mode 100644 index 3c0f9fa712ab..000000000000 --- a/arch/sw_64/include/uapi/asm/kvm_para.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_ASM_SW64_KVM_PARA_H -#define _UAPI_ASM_SW64_KVM_PARA_H - -#include - -#endif diff --git a/arch/sw_64/include/uapi/asm/msgbuf.h b/arch/sw_64/include/uapi/asm/msgbuf.h deleted file mode 100644 index b938df3664a0..000000000000 --- a/arch/sw_64/include/uapi/asm/msgbuf.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_ASM_SW64_MSGBUF_H -#define _UAPI_ASM_SW64_MSGBUF_H - -/* - * The msqid64_ds structure for sw64 architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 2 miscellaneous 64-bit values - */ - -struct msqid64_ds { - struct ipc64_perm msg_perm; - long msg_stime; /* last msgsnd time */ - long msg_rtime; /* last msgrcv time */ - long msg_ctime; /* last change time */ - unsigned long msg_cbytes; /* current number of bytes on queue */ - unsigned long msg_qnum; /* number of messages in queue */ - unsigned long msg_qbytes; /* max number of bytes on queue */ - __kernel_pid_t msg_lspid; /* pid of last msgsnd */ - __kernel_pid_t msg_lrpid; /* last receive pid */ - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _UAPI_ASM_SW64_MSGBUF_H */ diff --git a/arch/sw_64/include/uapi/asm/poll.h b/arch/sw_64/include/uapi/asm/poll.h deleted file mode 100644 index 114d0344e377..000000000000 --- a/arch/sw_64/include/uapi/asm/poll.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_ASM_SW64_POLL_H -#define _UAPI_ASM_SW64_POLL_H - -#include - -#endif diff --git a/arch/sw_64/include/uapi/asm/posix_types.h b/arch/sw_64/include/uapi/asm/posix_types.h deleted file mode 100644 index 182741aaa06e..000000000000 --- a/arch/sw_64/include/uapi/asm/posix_types.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_ASM_SW64_POSIX_TYPES_H -#define _UAPI_ASM_SW64_POSIX_TYPES_H - -/* - * This file is generally used by user-level software, so you need to - * be a little careful about namespace pollution etc. Also, we cannot - * assume GCC is being used. - */ - -typedef unsigned long __kernel_ino_t; -#define __kernel_ino_t __kernel_ino_t - -typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ - -#include - -#endif /* _UAPI_ASM_SW64_POSIX_TYPES_H */ diff --git a/arch/sw_64/include/uapi/asm/sembuf.h b/arch/sw_64/include/uapi/asm/sembuf.h deleted file mode 100644 index 08b0876e739c..000000000000 --- a/arch/sw_64/include/uapi/asm/sembuf.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_ASM_SW64_SEMBUF_H -#define _UAPI_ASM_SW64_SEMBUF_H - -/* - * The semid64_ds structure for sw64 architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 2 miscellaneous 64-bit values - */ - -struct semid64_ds { - struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ - long sem_otime; /* last semop time */ - long sem_ctime; /* last change time */ - unsigned long sem_nsems; /* no. of semaphores in array */ - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _UAPI_ASM_SW64_SEMBUF_H */ diff --git a/arch/sw_64/include/uapi/asm/shmbuf.h b/arch/sw_64/include/uapi/asm/shmbuf.h deleted file mode 100644 index 4572337bee02..000000000000 --- a/arch/sw_64/include/uapi/asm/shmbuf.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_ASM_SW64_SHMBUF_H -#define _UAPI_ASM_SW64_SHMBUF_H - -/* - * The shmid64_ds structure for sw64 architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 2 miscellaneous 64-bit values - */ - -struct shmid64_ds { - struct ipc64_perm shm_perm; /* operation perms */ - size_t shm_segsz; /* size of segment (bytes) */ - long shm_atime; /* last attach time */ - long shm_dtime; /* last detach time */ - long shm_ctime; /* last change time */ - __kernel_pid_t shm_cpid; /* pid of creator */ - __kernel_pid_t shm_lpid; /* pid of last operator */ - unsigned long shm_nattch; /* no. of current attaches */ - unsigned long __unused1; - unsigned long __unused2; -}; - -struct shminfo64 { - unsigned long shmmax; - unsigned long shmmin; - unsigned long shmmni; - unsigned long shmseg; - unsigned long shmall; - unsigned long __unused1; - unsigned long __unused2; - unsigned long __unused3; - unsigned long __unused4; -}; - -#endif /* _UAPI_ASM_SW64_SHMBUF_H */ diff --git a/arch/sw_64/include/uapi/asm/statfs.h b/arch/sw_64/include/uapi/asm/statfs.h deleted file mode 100644 index b92d719238d1..000000000000 --- a/arch/sw_64/include/uapi/asm/statfs.h +++ /dev/null @@ -1,9 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_ASM_SW64_STATFS_H -#define _UAPI_ASM_SW64_STATFS_H - -#include - -#include - -#endif diff --git a/arch/sw_64/include/uapi/asm/types.h b/arch/sw_64/include/uapi/asm/types.h deleted file mode 100644 index 750b5181c3de..000000000000 --- a/arch/sw_64/include/uapi/asm/types.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_ASM_SW64_TYPES_H -#define _UAPI_ASM_SW64_TYPES_H - -/* - * This file is never included by application software unless - * explicitly requested (e.g., via linux/types.h) in which case the - * application is Linux specific so (user-) name space pollution is - * not a major issue. However, for interoperability, libraries still - * need to be careful to avoid a name clashes. - */ - -/* - * This is here because we used to use l64 for sw64 and we don't want - * to impact user mode with our change to ll64 in the kernel. - * - * However, some user programs are fine with this. They can - * flag __SANE_USERSPACE_TYPES__ to get int-ll64.h here. - */ -#ifndef __KERNEL__ -#ifndef __SANE_USERSPACE_TYPES__ -#include -#else -#include -#endif /* __SANE_USERSPACE_TYPES__ */ -#endif /* __KERNEL__ */ - -#endif /* _UAPI_ASM_SW64_TYPES_H */ -- Gitee From e2c89aaa6b99586c72d55024e4c42c0a331864f6 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 6 May 2022 09:30:28 +0800 Subject: [PATCH 03/71] sw64: uapi: include generic param.h Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- Most macro definitions are the same with generic version. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/uapi/asm/param.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/arch/sw_64/include/uapi/asm/param.h b/arch/sw_64/include/uapi/asm/param.h index 16c4934c937e..d38e8202dd97 100644 --- a/arch/sw_64/include/uapi/asm/param.h +++ b/arch/sw_64/include/uapi/asm/param.h @@ -2,15 +2,8 @@ #ifndef _UAPI_ASM_SW64_PARAM_H #define _UAPI_ASM_SW64_PARAM_H -#define HZ 100 - #define EXEC_PAGESIZE 8192 -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - +#include #endif /* _UAPI_ASM_SW64_PARAM_H */ -- Gitee From 92f19473b28196492cbfd8153f8d48f2297a562a Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 6 May 2022 09:57:27 +0800 Subject: [PATCH 04/71] sw64: kapi: remove unused header-y from Kbuild Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/Kbuild | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/arch/sw_64/include/asm/Kbuild b/arch/sw_64/include/asm/Kbuild index e276ba366e68..a94a978edf3e 100644 --- a/arch/sw_64/include/asm/Kbuild +++ b/arch/sw_64/include/asm/Kbuild @@ -1,23 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 -header-y += compiler.h -header-y += console.h -header-y += fpu.h -header-y += gentrap.h -header-y += hmcall.h -header-y += reg.h -header-y += regdef.h -header-y += sysinfo.h -header-y += page.h -header-y += elf.h -generated-y += syscall_table.h +generic-y += clkdev.h generic-y += export.h generic-y += kvm_types.h -generic-y += rwsem.h - +generic-y += mcs_spinlock.h generic-y += qrwlock.h generic-y += qspinlock.h -generic-y += mcs_spinlock.h -generic-y += clkdev.h +generic-y += rwsem.h generic-y += scatterlist.h generic-y += user.h +generated-y += syscall_table.h -- Gitee From 927e8e16d604582a095d7c0ae9714f8050f0205d Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 6 May 2022 10:00:14 +0800 Subject: [PATCH 05/71] sw64: kapi: generate some kapi headers from generic ones Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- These kapi headers are proved to be the same with generic version. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/Kbuild | 7 +- arch/sw_64/include/asm/div64.h | 7 -- arch/sw_64/include/asm/emergency-restart.h | 7 -- arch/sw_64/include/asm/exec.h | 7 -- arch/sw_64/include/asm/irq_regs.h | 7 -- arch/sw_64/include/asm/kmap_types.h | 15 --- arch/sw_64/include/asm/local.h | 125 --------------------- arch/sw_64/include/asm/local64.h | 7 -- arch/sw_64/include/asm/param.h | 11 -- arch/sw_64/include/asm/parport.h | 19 ---- arch/sw_64/include/asm/preempt.h | 7 -- arch/sw_64/include/asm/seccomp.h | 15 --- arch/sw_64/include/asm/sections.h | 8 -- arch/sw_64/include/asm/segment.h | 7 -- arch/sw_64/include/asm/serial.h | 16 --- arch/sw_64/include/asm/shmparam.h | 7 -- arch/sw_64/include/asm/trace_clock.h | 10 -- arch/sw_64/include/asm/types.h | 7 -- arch/sw_64/include/asm/unaligned.h | 12 -- 19 files changed, 6 insertions(+), 295 deletions(-) delete mode 100644 arch/sw_64/include/asm/div64.h delete mode 100644 arch/sw_64/include/asm/emergency-restart.h delete mode 100644 arch/sw_64/include/asm/exec.h delete mode 100644 arch/sw_64/include/asm/irq_regs.h delete mode 100644 arch/sw_64/include/asm/kmap_types.h delete mode 100644 arch/sw_64/include/asm/local.h delete mode 100644 arch/sw_64/include/asm/local64.h delete mode 100644 arch/sw_64/include/asm/param.h delete mode 100644 arch/sw_64/include/asm/parport.h delete mode 100644 arch/sw_64/include/asm/preempt.h delete mode 100644 arch/sw_64/include/asm/seccomp.h delete mode 100644 arch/sw_64/include/asm/sections.h delete mode 100644 arch/sw_64/include/asm/segment.h delete mode 100644 arch/sw_64/include/asm/serial.h delete mode 100644 arch/sw_64/include/asm/shmparam.h delete mode 100644 arch/sw_64/include/asm/trace_clock.h delete mode 100644 arch/sw_64/include/asm/types.h delete mode 100644 arch/sw_64/include/asm/unaligned.h diff --git a/arch/sw_64/include/asm/Kbuild b/arch/sw_64/include/asm/Kbuild index a94a978edf3e..d08f0b08918e 100644 --- a/arch/sw_64/include/asm/Kbuild +++ b/arch/sw_64/include/asm/Kbuild @@ -3,10 +3,15 @@ generic-y += clkdev.h generic-y += export.h generic-y += kvm_types.h +generic-y += local64.h generic-y += mcs_spinlock.h +generic-y += param.h generic-y += qrwlock.h generic-y += qspinlock.h generic-y += rwsem.h -generic-y += scatterlist.h +generic-y += seccomp.h +generic-y += segment.h +generic-y += types.h generic-y += user.h + generated-y += syscall_table.h diff --git a/arch/sw_64/include/asm/div64.h b/arch/sw_64/include/asm/div64.h deleted file mode 100644 index 306581407ba5..000000000000 --- a/arch/sw_64/include/asm/div64.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_DIV64_H -#define _ASM_SW64_DIV64_H - -#include - -#endif diff --git a/arch/sw_64/include/asm/emergency-restart.h b/arch/sw_64/include/asm/emergency-restart.h deleted file mode 100644 index fabb33ebf0eb..000000000000 --- a/arch/sw_64/include/asm/emergency-restart.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_EMERGENCY_RESTART_H -#define _ASM_SW64_EMERGENCY_RESTART_H - -#include - -#endif /* _ASM_SW64_EMERGENCY_RESTART_H */ diff --git a/arch/sw_64/include/asm/exec.h b/arch/sw_64/include/asm/exec.h deleted file mode 100644 index 4a9cb71c5c47..000000000000 --- a/arch/sw_64/include/asm/exec.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_EXEC_H -#define _ASM_SW64_EXEC_H - -#define arch_align_stack(x) (x) - -#endif /* _ASM_SW64_EXEC_H */ diff --git a/arch/sw_64/include/asm/irq_regs.h b/arch/sw_64/include/asm/irq_regs.h deleted file mode 100644 index bba48f36a40f..000000000000 --- a/arch/sw_64/include/asm/irq_regs.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_IRQ_REGS_H -#define _ASM_SW64_IRQ_REGS_H - -#include - -#endif diff --git a/arch/sw_64/include/asm/kmap_types.h b/arch/sw_64/include/asm/kmap_types.h deleted file mode 100644 index 8e86b08dee94..000000000000 --- a/arch/sw_64/include/asm/kmap_types.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_KMAP_TYPES_H -#define _ASM_SW64_KMAP_TYPES_H - -/* Dummy header just to define km_type. */ - -#ifdef CONFIG_DEBUG_HIGHMEM -#define __WITH_KM_FENCE -#endif - -#include - -#undef __WITH_KM_FENCE - -#endif diff --git a/arch/sw_64/include/asm/local.h b/arch/sw_64/include/asm/local.h deleted file mode 100644 index 9144600f641d..000000000000 --- a/arch/sw_64/include/asm/local.h +++ /dev/null @@ -1,125 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_LOCAL_H -#define _ASM_SW64_LOCAL_H - -#include -#include - -typedef struct { - atomic_long_t a; -} local_t; - -#define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) } -#define local_read(l) atomic_long_read(&(l)->a) -#define local_set(l, i) atomic_long_set(&(l)->a, (i)) -#define local_inc(l) atomic_long_inc(&(l)->a) -#define local_dec(l) atomic_long_dec(&(l)->a) -#define local_add(i, l) atomic_long_add((i), (&(l)->a)) -#define local_sub(i, l) atomic_long_sub((i), (&(l)->a)) - -static inline long local_add_return(long i, local_t *l) -{ - long temp1, temp2, result, addr; - - __asm__ __volatile__( -#ifdef CONFIG_LOCK_MEMB - " memb\n" -#endif - " ldi %4, %2\n" - "1: lldl %0, 0(%4)\n" - " ldi %1, 1\n" - " wr_f %1\n" - " addl %0, %5, %3\n" - " addl %0, %5, %0\n" -#ifdef CONFIG_LOCK_FIXUP - " memb\n" -#endif - " lstl %0, 0(%4)\n" - " rd_f %0\n" - " beq %0, 2f\n" - ".subsection 2\n" - "2: br 1b\n" - ".previous" - : "=&r" (temp1), "=&r" (temp2), "=m" (l->a.counter), - "=&r" (result), "=&r" (addr) - : "Ir" (i), "m" (l->a.counter) : "memory"); - return result; -} - -static inline long local_sub_return(long i, local_t *l) -{ - long temp1, temp2, result, addr; - - __asm__ __volatile__( -#ifdef CONFIG_LOCK_MEMB - " memb\n" -#endif - " ldi %4, %2\n" - "1: lldl %0, 0(%4)\n" - " ldi %1, 1\n" - " wr_f %1\n" - " subl %0, %5, %3\n" - " subl %0, %5, %0\n" -#ifdef CONFIG_LOCK_FIXUP - " memb\n" -#endif - " lstl %0, 0(%4)\n" - " rd_f %0\n" - " beq %0, 2f\n" - ".subsection 2\n" - "2: br 1b\n" - ".previous" - : "=&r" (temp1), "=&r" (temp2), "=m" (l->a.counter), - "=&r" (result), "=&r" (addr) - : "Ir" (i), "m" (l->a.counter) : "memory"); - return result; -} - -#define local_cmpxchg(l, o, n) \ - (cmpxchg_local(&((l)->a.counter), (o), (n))) -#define local_xchg(l, n) (xchg_local(&((l)->a.counter), (n))) - -/** - * local_add_unless - add unless the number is a given value - * @l: pointer of type local_t - * @a: the amount to add to l... - * @u: ...unless l is equal to u. - * - * Atomically adds @a to @l, so long as it was not @u. - * Returns non-zero if @l was not @u, and zero otherwise. - */ -#define local_add_unless(l, a, u) \ -({ \ - long c, old; \ - c = local_read(l); \ - for (;;) { \ - if (unlikely(c == (u))) \ - break; \ - old = local_cmpxchg((l), c, c + (a)); \ - if (likely(old == c)) \ - break; \ - c = old; \ - } \ - c != (u); \ -}) -#define local_inc_not_zero(l) local_add_unless((l), 1, 0) - -#define local_add_negative(a, l) (local_add_return((a), (l)) < 0) - -#define local_dec_return(l) local_sub_return(1, (l)) - -#define local_inc_return(l) local_add_return(1, (l)) - -#define local_sub_and_test(i, l) (local_sub_return((i), (l)) == 0) - -#define local_inc_and_test(l) (local_add_return(1, (l)) == 0) - -#define local_dec_and_test(l) (local_sub_return(1, (l)) == 0) - -/* Verify if faster than atomic ops */ -#define __local_inc(l) ((l)->a.counter++) -#define __local_dec(l) ((l)->a.counter++) -#define __local_add(i, l) ((l)->a.counter += (i)) -#define __local_sub(i, l) ((l)->a.counter -= (i)) - -#endif /* _ASM_SW64_LOCAL_H */ diff --git a/arch/sw_64/include/asm/local64.h b/arch/sw_64/include/asm/local64.h deleted file mode 100644 index 4278133cd8fa..000000000000 --- a/arch/sw_64/include/asm/local64.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_LOCAL64_H -#define _ASM_SW64_LOCAL64_H - -#include - -#endif diff --git a/arch/sw_64/include/asm/param.h b/arch/sw_64/include/asm/param.h deleted file mode 100644 index 49c5d03a3370..000000000000 --- a/arch/sw_64/include/asm/param.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_PARAM_H -#define _ASM_SW64_PARAM_H - -#include - -#undef HZ -#define HZ CONFIG_HZ -#define USER_HZ 100 -#define CLOCKS_PER_SEC USER_HZ /* frequency at which times() counts */ -#endif /* _ASM_SW64_PARAM_H */ diff --git a/arch/sw_64/include/asm/parport.h b/arch/sw_64/include/asm/parport.h deleted file mode 100644 index 82b9a219b797..000000000000 --- a/arch/sw_64/include/asm/parport.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * parport.h: platform-specific PC-style parport initialisation - * - * Copyright (C) 1999, 2000 Tim Waugh - * - * This file should only be included by drivers/parport/parport_pc.c. - */ - -#ifndef _ASM_SW64_PARPORT_H -#define _ASM_SW64_PARPORT_H - -static int parport_pc_find_isa_ports(int autoirq, int autodma); -static int parport_pc_find_nonpci_ports(int autoirq, int autodma) -{ - return parport_pc_find_isa_ports(autoirq, autodma); -} - -#endif /* !(_ASM_SW64_PARPORT_H) */ diff --git a/arch/sw_64/include/asm/preempt.h b/arch/sw_64/include/asm/preempt.h deleted file mode 100644 index dc6643a43766..000000000000 --- a/arch/sw_64/include/asm/preempt.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_PREEMPT_H -#define _ASM_SW64_PREEMPT_H - -#include - -#endif /* _ASM_SW64_PREEMPT_H */ diff --git a/arch/sw_64/include/asm/seccomp.h b/arch/sw_64/include/asm/seccomp.h deleted file mode 100644 index db2f298862c3..000000000000 --- a/arch/sw_64/include/asm/seccomp.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * arch/sw_64/include/asm/seccomp.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef _ASM_SW64_SECCOMP_H -#define _ASM_SW64_SECCOMP_H - -#include -#include - -#endif /* _ASM_SW64_SECCOMP_H */ diff --git a/arch/sw_64/include/asm/sections.h b/arch/sw_64/include/asm/sections.h deleted file mode 100644 index 37dab4fde720..000000000000 --- a/arch/sw_64/include/asm/sections.h +++ /dev/null @@ -1,8 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_SECTIONS_H -#define _ASM_SW64_SECTIONS_H - -/* nothing to see, move along */ -#include - -#endif diff --git a/arch/sw_64/include/asm/segment.h b/arch/sw_64/include/asm/segment.h deleted file mode 100644 index dc90357765e5..000000000000 --- a/arch/sw_64/include/asm/segment.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_SEGMENT_H -#define _ASM_SW64_SEGMENT_H - -/* Only here because we have some old header files that expect it.. */ - -#endif diff --git a/arch/sw_64/include/asm/serial.h b/arch/sw_64/include/asm/serial.h deleted file mode 100644 index 059e603642b9..000000000000 --- a/arch/sw_64/include/asm/serial.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_SERIAL_H -#define _ASM_SW64_SERIAL_H - -#define BASE_BAUD (1843200 / 16) - -/* Standard COM flags (except for COM4, because of the 8514 problem) */ -#ifdef CONFIG_SERIAL_8250_DETECT_IRQ -#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ) -#define STD_COM4_FLAGS (UPF_BOOT_AUTOCONF | UPF_AUTO_IRQ) -#else -#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) -#define STD_COM4_FLAGS UPF_BOOT_AUTOCONF -#endif - -#endif /* _ASM_SW64_SERIAL_H */ diff --git a/arch/sw_64/include/asm/shmparam.h b/arch/sw_64/include/asm/shmparam.h deleted file mode 100644 index 15f71533b1ed..000000000000 --- a/arch/sw_64/include/asm/shmparam.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_SHMPARAM_H -#define _ASM_SW64_SHMPARAM_H - -#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ - -#endif /* _ASM_SW64_SHMPARAM_H */ diff --git a/arch/sw_64/include/asm/trace_clock.h b/arch/sw_64/include/asm/trace_clock.h deleted file mode 100644 index 57324215a837..000000000000 --- a/arch/sw_64/include/asm/trace_clock.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_TRACE_CLOCK_H -#define _ASM_SW64_TRACE_CLOCK_H - -#include -#include - -#define ARCH_TRACE_CLOCKS - -#endif /* _ASM_SW64_TRACE_CLOCK_H */ diff --git a/arch/sw_64/include/asm/types.h b/arch/sw_64/include/asm/types.h deleted file mode 100644 index 37d626269a02..000000000000 --- a/arch/sw_64/include/asm/types.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_TYPES_H -#define _ASM_SW64_TYPES_H - -#include - -#endif /* _ASM_SW64_TYPES_H */ diff --git a/arch/sw_64/include/asm/unaligned.h b/arch/sw_64/include/asm/unaligned.h deleted file mode 100644 index 91fdff923ce5..000000000000 --- a/arch/sw_64/include/asm/unaligned.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_UNALIGNED_H -#define _ASM_SW64_UNALIGNED_H - -#include -#include -#include - -#define get_unaligned __get_unaligned_le -#define put_unaligned __put_unaligned_le - -#endif /* _ASM_SW64_UNALIGNED_H */ -- Gitee From 6519c5195084b7326aa8a26584bb2e2b4d82f19c Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 6 May 2022 10:05:54 +0800 Subject: [PATCH 06/71] sw64: move ucontext.h to uapi Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- It's an important user interface which should be put in uapi. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/{ => uapi}/asm/ucontext.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename arch/sw_64/include/{ => uapi}/asm/ucontext.h (56%) diff --git a/arch/sw_64/include/asm/ucontext.h b/arch/sw_64/include/uapi/asm/ucontext.h similarity index 56% rename from arch/sw_64/include/asm/ucontext.h rename to arch/sw_64/include/uapi/asm/ucontext.h index d40eebe988ef..c5d6e24e3e5f 100644 --- a/arch/sw_64/include/asm/ucontext.h +++ b/arch/sw_64/include/uapi/asm/ucontext.h @@ -1,6 +1,6 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_SW64_UCONTEXT_H -#define _ASM_SW64_UCONTEXT_H +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_ASM_SW64_UCONTEXT_H +#define _UAPI_ASM_SW64_UCONTEXT_H struct ucontext { unsigned long uc_flags; @@ -11,4 +11,4 @@ struct ucontext { sigset_t uc_sigmask; /* mask last for extensibility */ }; -#endif /* _ASM_SW64_UCONTEXT_H */ +#endif /* _UAPI_ASM_SW64_UCONTEXT_H */ -- Gitee From dc6f31f83df3a0ff2a9da93ffb61aee3e58ae852 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 6 May 2022 10:30:09 +0800 Subject: [PATCH 07/71] sw64: kapi: remove redudant SMP_CACHE_BYTES Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- SMP_CACHE_BYTES is also defined in linux/cache.h, so remove the replicated one. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/cache.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/sw_64/include/asm/cache.h b/arch/sw_64/include/asm/cache.h index a59a74110884..1dca2e2e04a4 100644 --- a/arch/sw_64/include/asm/cache.h +++ b/arch/sw_64/include/asm/cache.h @@ -5,9 +5,7 @@ #ifndef _ASM_SW64_CACHE_H #define _ASM_SW64_CACHE_H -#define L1_CACHE_BYTES 128 #define L1_CACHE_SHIFT 7 - -#define SMP_CACHE_BYTES L1_CACHE_BYTES +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) #endif -- Gitee From cf28d11eff5d9edbb5330eed2e2bb3e75e4bc066 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 6 May 2022 10:45:56 +0800 Subject: [PATCH 08/71] sw64: kapi: remove unimplemented IPLs Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- There are only two IPLs so far on sw64. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/irqflags.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/sw_64/include/asm/irqflags.h b/arch/sw_64/include/asm/irqflags.h index 6101b6ad2e99..b4440f25a51d 100644 --- a/arch/sw_64/include/asm/irqflags.h +++ b/arch/sw_64/include/asm/irqflags.h @@ -5,14 +5,6 @@ #include #define IPL_MIN 0 -#define IPL_SW0 1 -#define IPL_SW1 2 -#define IPL_DEV0 3 -#define IPL_DEV1 4 -#define IPL_TIMER 5 -#define IPL_PERF 6 -#define IPL_POWERFAIL 6 -#define IPL_MCHECK 7 #define IPL_MAX 7 #define getipl() (rdps() & 7) -- Gitee From 211af39aab2e322ad14fd7727977946b29fff3ba Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 6 May 2022 11:09:36 +0800 Subject: [PATCH 09/71] sw64: kapi: include generic modules.h Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- This patch removes replicated macros which have been defined in generic version. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/module.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/arch/sw_64/include/asm/module.h b/arch/sw_64/include/asm/module.h index 55e6e333585f..d1663aab4097 100644 --- a/arch/sw_64/include/asm/module.h +++ b/arch/sw_64/include/asm/module.h @@ -2,18 +2,12 @@ #ifndef _ASM_SW64_MODULE_H #define _ASM_SW64_MODULE_H +#include + struct mod_arch_specific { unsigned int gotsecindex; }; -#define Elf_Sym Elf64_Sym -#define Elf_Shdr Elf64_Shdr -#define Elf_Ehdr Elf64_Ehdr -#define Elf_Phdr Elf64_Phdr -#define Elf_Dyn Elf64_Dyn -#define Elf_Rel Elf64_Rel -#define Elf_Rela Elf64_Rela - #define ARCH_SHF_SMALL SHF_SW64_GPREL #ifdef MODULE -- Gitee From fda97bdcd80c5dbced89f64ad340c18987fa39fb Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 6 May 2022 14:15:52 +0800 Subject: [PATCH 10/71] sw64: remove VGA_HOSE things Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- SW64 has nothing to do with CONFIG_VGA_HOSE. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 8 -------- arch/sw_64/include/asm/vga.h | 31 ------------------------------- 2 files changed, 39 deletions(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 472a916fd93e..8c5e87cb9b84 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -896,12 +896,4 @@ source "drivers/idle/Kconfig" endmenu -# DUMMY_CONSOLE may be defined in drivers/video/console/Kconfig -# but we also need it if VGA_HOSE is set -config DUMMY_CONSOLE - bool - depends on VGA_HOSE - default y - - source "arch/sw_64/kvm/Kconfig" diff --git a/arch/sw_64/include/asm/vga.h b/arch/sw_64/include/asm/vga.h index 28adb8b8b7f1..7268b5cd4bd8 100644 --- a/arch/sw_64/include/asm/vga.h +++ b/arch/sw_64/include/asm/vga.h @@ -49,37 +49,6 @@ extern void scr_memcpyw(u16 *d, const u16 *s, unsigned int count); #define vga_readb(a) readb((u8 __iomem *)(a)) #define vga_writeb(v, a) writeb(v, (u8 __iomem *)(a)) -#ifdef CONFIG_VGA_HOSE -#include -#include - -extern struct pci_controller *pci_vga_hose; - -#define __is_port_vga(a) \ - (((a) >= 0x3b0) && ((a) < 0x3e0) && \ - ((a) != 0x3b3) && ((a) != 0x3d3)) - -#define __is_mem_vga(a) \ - (((a) >= 0xa0000) && ((a) <= 0xc0000)) - -#define FIXUP_IOADDR_VGA(a) do { \ - if (pci_vga_hose && __is_port_vga(a)) \ - (a) += pci_vga_hose->io_space->start; \ -} while (0) - -#define FIXUP_MEMADDR_VGA(a) do { \ - if (pci_vga_hose && __is_mem_vga(a)) \ - (a) += pci_vga_hose->mem_space->start; \ -} while (0) - -#else /* CONFIG_VGA_HOSE */ -#define pci_vga_hose 0 -#define __is_port_vga(a) 0 -#define __is_mem_vga(a) 0 -#define FIXUP_IOADDR_VGA(a) -#define FIXUP_MEMADDR_VGA(a) -#endif /* CONFIG_VGA_HOSE */ - #define VGA_MAP_MEM(x, s) ((unsigned long)ioremap(x, s)) #endif -- Gitee From cfc38dc4ccccb5fd218eeb560bde21a42f381b91 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Sat, 7 May 2022 15:00:06 +0800 Subject: [PATCH 11/71] sw64: clean up unused pci iounmap operation Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- For sw64, IO address is mapped by direct mapping without pages. It doesn't have to do anything to unmap PCI MMIO. The result is that __is_mmio helper can be removed. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/io.h | 8 -------- arch/sw_64/kernel/pci.c | 4 ---- 2 files changed, 12 deletions(-) diff --git a/arch/sw_64/include/asm/io.h b/arch/sw_64/include/asm/io.h index 6796c64f94ae..cb6c7c1f4a6b 100644 --- a/arch/sw_64/include/asm/io.h +++ b/arch/sw_64/include/asm/io.h @@ -218,14 +218,6 @@ static inline int __is_ioaddr(unsigned long addr) #define __is_ioaddr(a) __is_ioaddr((unsigned long)(a)) -static inline int __is_mmio(const volatile void __iomem *xaddr) -{ - unsigned long addr = (unsigned long)xaddr; - - return (addr & 0x100000000UL) == 0; -} - - #define ioread16be(p) be16_to_cpu(ioread16(p)) #define ioread32be(p) be32_to_cpu(ioread32(p)) diff --git a/arch/sw_64/kernel/pci.c b/arch/sw_64/kernel/pci.c index 44264e3da18f..77bbd1b68176 100644 --- a/arch/sw_64/kernel/pci.c +++ b/arch/sw_64/kernel/pci.c @@ -358,12 +358,8 @@ asmlinkage long sys_pciconfig_iobase(long which, unsigned long bus, unsigned lon return -EOPNOTSUPP; } -/* Destroy an __iomem token. Not copied from lib/iomap.c. */ - void pci_iounmap(struct pci_dev *dev, void __iomem *addr) { - if (__is_mmio(addr)) - iounmap(addr); } EXPORT_SYMBOL(pci_iounmap); -- Gitee From 751e450b08b35f491121fa7f977f1234d1366a12 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Tue, 10 May 2022 13:50:33 +0800 Subject: [PATCH 12/71] sw64: kapi: use generic vga.h Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- The old arch-specific vga.h takes no effect now, so use the generic version. As a result, the arch-specific scr_memcpyw interface and __is_ioaddr helper can be removed too. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/io.h | 8 ------ arch/sw_64/include/asm/vga.h | 54 ------------------------------------ arch/sw_64/lib/iomap.c | 37 ------------------------ 3 files changed, 99 deletions(-) delete mode 100644 arch/sw_64/include/asm/vga.h diff --git a/arch/sw_64/include/asm/io.h b/arch/sw_64/include/asm/io.h index cb6c7c1f4a6b..e8e80c761467 100644 --- a/arch/sw_64/include/asm/io.h +++ b/arch/sw_64/include/asm/io.h @@ -211,14 +211,6 @@ static inline void __iounmap(volatile void __iomem *addr) #define iounmap __iounmap -static inline int __is_ioaddr(unsigned long addr) -{ - return addr >= (PAGE_OFFSET | IO_BASE); -} - -#define __is_ioaddr(a) __is_ioaddr((unsigned long)(a)) - - #define ioread16be(p) be16_to_cpu(ioread16(p)) #define ioread32be(p) be32_to_cpu(ioread32(p)) #define iowrite16be(v, p) iowrite16(cpu_to_be16(v), (p)) diff --git a/arch/sw_64/include/asm/vga.h b/arch/sw_64/include/asm/vga.h deleted file mode 100644 index 7268b5cd4bd8..000000000000 --- a/arch/sw_64/include/asm/vga.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Access to VGA videoram - * - * (c) 1998 Martin Mares - */ - -#ifndef _ASM_SW64_VGA_H -#define _ASM_SW64_VGA_H - -#include - -#define VT_BUF_HAVE_RW -#define VT_BUF_HAVE_MEMSETW -#define VT_BUF_HAVE_MEMCPYW - -static inline void scr_writew(u16 val, volatile u16 *addr) -{ - if (__is_ioaddr(addr)) - __raw_writew(val, (volatile u16 __iomem *) addr); - else - *addr = val; -} - -static inline u16 scr_readw(volatile const u16 *addr) -{ - if (__is_ioaddr(addr)) - return __raw_readw((volatile const u16 __iomem *) addr); - else - return *addr; -} - -static inline void scr_memsetw(u16 *s, u16 c, unsigned int count) -{ - if (__is_ioaddr(s)) - memsetw_io((u16 __iomem *) s, c, count); - else - memsetw(s, c, count); -} - -/* Do not trust that the usage will be correct; analyze the arguments. */ -extern void scr_memcpyw(u16 *d, const u16 *s, unsigned int count); - -/* - * ??? These are currently only used for downloading character sets. As - * such, they don't need memory barriers. Is this all they are intended - * to be used for? - */ -#define vga_readb(a) readb((u8 __iomem *)(a)) -#define vga_writeb(v, a) writeb(v, (u8 __iomem *)(a)) - -#define VGA_MAP_MEM(x, s) ((unsigned long)ioremap(x, s)) - -#endif diff --git a/arch/sw_64/lib/iomap.c b/arch/sw_64/lib/iomap.c index 39e3d5498ae6..6fb96a7d7119 100644 --- a/arch/sw_64/lib/iomap.c +++ b/arch/sw_64/lib/iomap.c @@ -457,43 +457,6 @@ void _memset_c_io(volatile void __iomem *to, unsigned long c, long count) } EXPORT_SYMBOL(_memset_c_io); -/* - * A version of memcpy used by the vga console routines to move data around - * arbitrarily between screen and main memory. - */ - -void -scr_memcpyw(u16 *d, const u16 *s, unsigned int count) -{ - const u16 __iomem *ios = (const u16 __iomem *) s; - u16 __iomem *iod = (u16 __iomem *) d; - int s_isio = __is_ioaddr(s); - int d_isio = __is_ioaddr(d); - u16 tmp; - - if (s_isio) { - if (d_isio) { - /* - * FIXME: Should handle unaligned ops and - * operation widening. - */ - - count /= 2; - while (count--) { - tmp = __raw_readw(ios++); - __raw_writew(tmp, iod++); - } - } else - memcpy_fromio(d, ios, count); - } else { - if (d_isio) - memcpy_toio(iod, s, count); - else - memcpy(d, s, count); - } -} -EXPORT_SYMBOL(scr_memcpyw); - void __iomem *ioport_map(unsigned long port, unsigned int size) { return ioportmap(port); -- Gitee From b5601cff08accb45befdd523b35337c96550c547 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Tue, 10 May 2022 14:21:21 +0800 Subject: [PATCH 13/71] sw64: remove unused IO_CONCAT Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- IO interface of chipset is wrapped as a hook in sw64_platform_ops. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/io.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/sw_64/include/asm/io.h b/arch/sw_64/include/asm/io.h index e8e80c761467..3138665133e1 100644 --- a/arch/sw_64/include/asm/io.h +++ b/arch/sw_64/include/asm/io.h @@ -64,13 +64,6 @@ static inline void * __deprecated bus_to_virt(unsigned long address) } #define isa_bus_to_virt bus_to_virt -/* - * There are different chipsets to interface the sw64 CPUs to the world. - */ - -#define IO_CONCAT(a, b) _IO_CONCAT(a, b) -#define _IO_CONCAT(a, b) a ## _ ## b - #include /* -- Gitee From a75d3cc4a8a08692bdfd9037c0ea97bbd8cdcd9c Mon Sep 17 00:00:00 2001 From: He Sheng Date: Tue, 10 May 2022 15:34:03 +0800 Subject: [PATCH 14/71] sw64: do not include sw64io.h in io.h Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- We consider io.h as a basic header which should be decoupled with platforms and chipsets, so it's better to remove sw64io.h from io.h, and do something necessary to make it build ok. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/chip/chip3/i2c-lib.c | 2 ++ arch/sw_64/include/asm/io.h | 10 ---------- arch/sw_64/include/asm/irq_impl.h | 2 ++ arch/sw_64/include/asm/sw64_init.h | 1 + arch/sw_64/kernel/pci_impl.h | 2 ++ arch/sw_64/kernel/proto.h | 1 + arch/sw_64/lib/iomap.c | 3 ++- 7 files changed, 10 insertions(+), 11 deletions(-) diff --git a/arch/sw_64/chip/chip3/i2c-lib.c b/arch/sw_64/chip/chip3/i2c-lib.c index ddf0a187ab5a..39b815022e69 100644 --- a/arch/sw_64/chip/chip3/i2c-lib.c +++ b/arch/sw_64/chip/chip3/i2c-lib.c @@ -19,6 +19,8 @@ #include #include +#include + #define CPLD_BUSNR 2 #ifndef _I2C_DEBUG_FLAG_ diff --git a/arch/sw_64/include/asm/io.h b/arch/sw_64/include/asm/io.h index 3138665133e1..fc11cb82f5b5 100644 --- a/arch/sw_64/include/asm/io.h +++ b/arch/sw_64/include/asm/io.h @@ -64,8 +64,6 @@ static inline void * __deprecated bus_to_virt(unsigned long address) } #define isa_bus_to_virt bus_to_virt -#include - /* * Generic IO read/write. These perform native-endian accesses. */ @@ -177,14 +175,6 @@ extern void outb(u8 b, unsigned long port); extern void outw(u16 b, unsigned long port); extern void outl(u32 b, unsigned long port); -/* - * Mapping from port numbers to __iomem space is pretty easy. - */ -static inline void __iomem *ioportmap(unsigned long addr) -{ - return sw64_platform->ioportmap(addr); -} - static inline void __iomem *__ioremap(phys_addr_t addr, size_t size, pgprot_t prot) { diff --git a/arch/sw_64/include/asm/irq_impl.h b/arch/sw_64/include/asm/irq_impl.h index 713267077142..3679793d8b65 100644 --- a/arch/sw_64/include/asm/irq_impl.h +++ b/arch/sw_64/include/asm/irq_impl.h @@ -11,6 +11,8 @@ #include #include +#include + #define SW64_PCIE0_INT_BASE 17 #define SW64_PCIE0_MSI_BASE 21 diff --git a/arch/sw_64/include/asm/sw64_init.h b/arch/sw_64/include/asm/sw64_init.h index 15842d22e5ba..2d9140605d0b 100644 --- a/arch/sw_64/include/asm/sw64_init.h +++ b/arch/sw_64/include/asm/sw64_init.h @@ -5,6 +5,7 @@ #include #include +#include struct sw64_early_init_ops { void (*setup_core_start)(struct cpumask *cpumask); diff --git a/arch/sw_64/kernel/pci_impl.h b/arch/sw_64/kernel/pci_impl.h index 8e541f28f4ce..6025145cb1c5 100644 --- a/arch/sw_64/kernel/pci_impl.h +++ b/arch/sw_64/kernel/pci_impl.h @@ -6,6 +6,8 @@ #ifndef _SW64_KERNEL_PCI_IMPL_H #define _SW64_KERNEL_PCI_IMPL_H +#include + struct pci_dev; struct pci_controller; diff --git a/arch/sw_64/kernel/proto.h b/arch/sw_64/kernel/proto.h index 1a729a8f21c3..9c99baaaf1d0 100644 --- a/arch/sw_64/kernel/proto.h +++ b/arch/sw_64/kernel/proto.h @@ -5,6 +5,7 @@ #include #include #include +#include /* ptrace.c */ extern int ptrace_set_bpt(struct task_struct *child); diff --git a/arch/sw_64/lib/iomap.c b/arch/sw_64/lib/iomap.c index 6fb96a7d7119..3a8d879ef070 100644 --- a/arch/sw_64/lib/iomap.c +++ b/arch/sw_64/lib/iomap.c @@ -6,6 +6,7 @@ #include #include +#include /* * Here comes the sw64 implementation of the IOMAP interfaces. @@ -459,7 +460,7 @@ EXPORT_SYMBOL(_memset_c_io); void __iomem *ioport_map(unsigned long port, unsigned int size) { - return ioportmap(port); + return sw64_platform->ioportmap(port); } EXPORT_SYMBOL(ioport_map); -- Gitee From 5e50a69788ed5bb9a512b098a3e1c7620c705e47 Mon Sep 17 00:00:00 2001 From: Zhou Qihang Date: Wed, 11 May 2022 10:53:06 +0800 Subject: [PATCH 15/71] sw64: iommu: work around iova mapping on pci bars Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5G5T3 -------------------------------- Since the RCs of SW64 chipset do not support Peer-to-Peer DMA, we used to return -EINVAL error on iova mampping on PCI BARs. However, it will cause driver loading errors when QEMU calls vfio module to passthrough PCI devices with this kind of BARs, shown as follows: > qemu-system-sw64: VFIO_MAP_DMA: -22 > qemu-system-sw64: vfio_dma_map(0x121c28020, 0x8800c0000000, 0x40000, 0x4165f21b2000) = -22 (Invalid argument) > qemu: hardware error: vfio: DMA mapping failed, unable to continue To fix this problem, this patch will return success on the iova mapping of PCI BARs that pretends to support this feature. Signed-off-by: Zhou Qihang Signed-off-by: Gu Zitao --- drivers/iommu/sw64/sunway_iommu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/sw64/sunway_iommu.c b/drivers/iommu/sw64/sunway_iommu.c index 8b851e0a0c20..5797adf8fbc5 100644 --- a/drivers/iommu/sw64/sunway_iommu.c +++ b/drivers/iommu/sw64/sunway_iommu.c @@ -1509,6 +1509,9 @@ sunway_iommu_iova_to_phys(struct iommu_domain *dom, dma_addr_t iova) struct sunway_iommu_domain *sdomain = to_sunway_domain(dom); unsigned long paddr, grn; + if (iova > SW64_BAR_ADDRESS) + return iova; + paddr = fetch_pte(sdomain, iova, PTE_LEVEL2_VAL); if ((paddr & SW64_IOMMU_ENTRY_VALID) == 0) @@ -1544,7 +1547,7 @@ sunway_iommu_map(struct iommu_domain *dom, unsigned long iova, * to avoid VFIO trying to map pci config space. */ if (iova > SW64_BAR_ADDRESS) - return -EINVAL; + return 0; mutex_lock(&sdomain->api_lock); ret = sunway_iommu_map_page(sdomain, iova, paddr, page_size); -- Gitee From fb2723595a7bee3a69596b60ce8038d5cee85384 Mon Sep 17 00:00:00 2001 From: Zhao Yihan Date: Wed, 11 May 2022 15:13:59 +0800 Subject: [PATCH 16/71] sw64: map address by OR operation in __va() Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- Signed-off-by: Zhao Yihan Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/page.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/page.h b/arch/sw_64/include/asm/page.h index 6e17d5e437c5..363785c9f082 100644 --- a/arch/sw_64/include/asm/page.h +++ b/arch/sw_64/include/asm/page.h @@ -46,7 +46,7 @@ extern unsigned long __phys_addr(unsigned long); #endif #define __pa(x) __phys_addr((unsigned long)(x)) -#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) +#define __va(x) ((void *)((unsigned long) (x) | PAGE_OFFSET)) #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) -- Gitee From 447e5cc179c5a24a1e99eb103737523f8b549137 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Thu, 12 May 2022 11:10:01 +0800 Subject: [PATCH 17/71] sw64: read host IO registers with rdio64 hmcall Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- The hmcall rdio64 can access IOR directly with its PA. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/chip/chip3/chip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/chip/chip3/chip.c b/arch/sw_64/chip/chip3/chip.c index 4d2f99cc6402..704588d7c3e1 100644 --- a/arch/sw_64/chip/chip3/chip.c +++ b/arch/sw_64/chip/chip3/chip.c @@ -54,7 +54,7 @@ static struct clocksource clocksource_longtime = { static u64 read_vtime(struct clocksource *cs) { u64 result; - unsigned long vtime_addr = PAGE_OFFSET | IO_BASE | LONG_TIME; + unsigned long vtime_addr = IO_BASE | LONG_TIME; result = rdio64(vtime_addr); return result; -- Gitee From 96259d7012ceb2b857d2f53c9921498365bd212e Mon Sep 17 00:00:00 2001 From: He Sheng Date: Thu, 12 May 2022 11:22:07 +0800 Subject: [PATCH 18/71] sw64: map logical address with __va() Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5G5YB -------------------------------- Although kmem and IO space are accessed with direct mapping on sw64, it's not a standard method to or PAGE_OFFSET and access it directly everywhere. This patch maps PA to VA with __va(). Besides, we change type of some variables to pointer to make the code clearer. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/chip/chip3/chip.c | 4 +- arch/sw_64/chip/chip3/i2c-lib.c | 24 +++++------ arch/sw_64/include/asm/pci.h | 4 +- arch/sw_64/include/asm/sw64io.h | 56 +++++++++++++------------- arch/sw_64/kernel/dup_print.c | 10 +++-- arch/sw_64/kernel/pci.c | 5 +-- arch/sw_64/kvm/kvm-sw64.c | 11 +++-- arch/sw_64/platform/platform_xuelang.c | 2 +- 8 files changed, 59 insertions(+), 57 deletions(-) diff --git a/arch/sw_64/chip/chip3/chip.c b/arch/sw_64/chip/chip3/chip.c index 704588d7c3e1..acd25fe99669 100644 --- a/arch/sw_64/chip/chip3/chip.c +++ b/arch/sw_64/chip/chip3/chip.c @@ -480,8 +480,8 @@ static void chip3_hose_init(struct pci_controller *hose) hose->dense_mem_base = pci_io_base; hose->dense_io_base = pci_io_base | PCI_LEGACY_IO; - hose->ep_config_space_base = PAGE_OFFSET | pci_io_base | PCI_EP_CFG; - hose->rc_config_space_base = PAGE_OFFSET | pci_io_base | PCI_RC_CFG; + hose->ep_config_space_base = __va(pci_io_base | PCI_EP_CFG); + hose->rc_config_space_base = __va(pci_io_base | PCI_RC_CFG); hose->mem_space->start = pci_io_base + PCI_32BIT_MEMIO; hose->mem_space->end = hose->mem_space->start + PCI_32BIT_MEMIO_SIZE - 1; diff --git a/arch/sw_64/chip/chip3/i2c-lib.c b/arch/sw_64/chip/chip3/i2c-lib.c index 39b815022e69..b3dcdcd32735 100644 --- a/arch/sw_64/chip/chip3/i2c-lib.c +++ b/arch/sw_64/chip/chip3/i2c-lib.c @@ -96,7 +96,7 @@ enum i2c_bus_operation { I2C_BUS_WRITE, }; -static uint64_t m_i2c_base_address; +static void __iomem *m_i2c_base_address; /* * This function get I2Cx controller base address @@ -104,18 +104,18 @@ static uint64_t m_i2c_base_address; * @param i2c_controller_index Bus Number of I2C controller. * @return I2C BAR. */ -uint64_t get_i2c_bar_addr(uint8_t i2c_controller_index) +void __iomem *get_i2c_bar_addr(uint8_t i2c_controller_index) { - uint64_t base_addr = 0; - - if (i2c_controller_index == 0) - base_addr = PAGE_OFFSET | IO_BASE | IIC0_BASE; - else if (i2c_controller_index == 1) - base_addr = PAGE_OFFSET | IO_BASE | IIC1_BASE; - else if (i2c_controller_index == 2) - base_addr = PAGE_OFFSET | IO_BASE | IIC2_BASE; - - return base_addr; + switch (i2c_controller_index) { + case 0: + return __va(IO_BASE | IIC0_BASE); + case 1: + return __va(IO_BASE | IIC1_BASE); + case 2: + return __va(IO_BASE | IIC2_BASE); + default: + return NULL; + } } void write_cpu_i2c_controller(uint64_t offset, uint32_t data) diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index ed875e0c3162..a90f80152470 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -34,8 +34,8 @@ struct pci_controller { unsigned long dense_io_base; /* This one's for the kernel only. It's in KSEG somewhere. */ - unsigned long ep_config_space_base; - unsigned long rc_config_space_base; + void __iomem *ep_config_space_base; + void __iomem *rc_config_space_base; unsigned long index; unsigned long node; diff --git a/arch/sw_64/include/asm/sw64io.h b/arch/sw_64/include/asm/sw64io.h index 7c032070acf0..e66aba66932b 100644 --- a/arch/sw_64/include/asm/sw64io.h +++ b/arch/sw_64/include/asm/sw64io.h @@ -11,20 +11,20 @@ extern void setup_chip_clocksource(void); #endif #define MK_RC_CFG(nid, idx) \ - (PAGE_OFFSET | SW64_PCI_IO_BASE((nid), (idx)) | PCI_RC_CFG) + (SW64_PCI_IO_BASE((nid), (idx)) | PCI_RC_CFG) #define MK_PIU_IOR0(nid, idx) \ - (PAGE_OFFSET | SW64_PCI_IO_BASE((nid), (idx)) | PCI_IOR0_BASE) + (SW64_PCI_IO_BASE((nid), (idx)) | PCI_IOR0_BASE) #define MK_PIU_IOR1(nid, idx) \ - (PAGE_OFFSET | SW64_PCI_IO_BASE((nid), (idx)) | PCI_IOR1_BASE) + (SW64_PCI_IO_BASE((nid), (idx)) | PCI_IOR1_BASE) static inline unsigned int -read_rc_conf(unsigned long node, unsigned long rc_index, - unsigned int conf_offset) +read_rc_conf(unsigned long node, unsigned long rc, + unsigned int offset) { - unsigned long addr; + void __iomem *addr; unsigned int value; - addr = MK_RC_CFG(node, rc_index) | conf_offset; + addr = __va(MK_RC_CFG(node, rc) | offset); value = *(volatile unsigned int *)addr; mb(); @@ -32,24 +32,24 @@ read_rc_conf(unsigned long node, unsigned long rc_index, } static inline void -write_rc_conf(unsigned long node, unsigned long rc_index, - unsigned int conf_offset, unsigned int data) +write_rc_conf(unsigned long node, unsigned long rc, + unsigned int offset, unsigned int data) { - unsigned long addr; + void __iomem *addr; - addr = MK_RC_CFG(node, rc_index) | conf_offset; + addr = __va(MK_RC_CFG(node, rc) | offset); *(unsigned int *)addr = data; mb(); } static inline unsigned long -read_piu_ior0(unsigned long node, unsigned long rc_index, +read_piu_ior0(unsigned long node, unsigned long rc, unsigned int reg) { - unsigned long addr; + void __iomem *addr; unsigned long value; - addr = MK_PIU_IOR0(node, rc_index) + reg; + addr = __va(MK_PIU_IOR0(node, rc) + reg); value = *(volatile unsigned long __iomem *)addr; mb(); @@ -57,23 +57,24 @@ read_piu_ior0(unsigned long node, unsigned long rc_index, } static inline void -write_piu_ior0(unsigned long node, unsigned long rc_index, +write_piu_ior0(unsigned long node, unsigned long rc, unsigned int reg, unsigned long data) { - unsigned long addr; + void __iomem *addr; - addr = MK_PIU_IOR0(node, rc_index) + reg; + addr = __va(MK_PIU_IOR0(node, rc) + reg); *(unsigned long __iomem *)addr = data; mb(); } static inline unsigned long -read_piu_ior1(unsigned long node, unsigned long rc_index, +read_piu_ior1(unsigned long node, unsigned long rc, unsigned int reg) { - unsigned long addr, value; + void __iomem *addr; + unsigned long value; - addr = MK_PIU_IOR1(node, rc_index) + reg; + addr = __va(MK_PIU_IOR1(node, rc) + reg); value = *(volatile unsigned long __iomem *)addr; mb(); @@ -81,12 +82,12 @@ read_piu_ior1(unsigned long node, unsigned long rc_index, } static inline void -write_piu_ior1(unsigned long node, unsigned long rc_index, +write_piu_ior1(unsigned long node, unsigned long rc, unsigned int reg, unsigned long data) { - unsigned long addr; + void __iomem *addr; - addr = MK_PIU_IOR1(node, rc_index) + reg; + addr = __va(MK_PIU_IOR1(node, rc) + reg); *(volatile unsigned long __iomem *)addr = data; mb(); } @@ -94,9 +95,10 @@ write_piu_ior1(unsigned long node, unsigned long rc_index, static inline unsigned long sw64_io_read(unsigned long node, unsigned long reg) { - unsigned long addr, value; + void __iomem *addr; + unsigned long value; - addr = PAGE_OFFSET | SW64_IO_BASE(node) | reg; + addr = __va(SW64_IO_BASE(node) | reg); value = *(volatile unsigned long __iomem *)addr; mb(); @@ -106,9 +108,9 @@ sw64_io_read(unsigned long node, unsigned long reg) static inline void sw64_io_write(unsigned long node, unsigned long reg, unsigned long data) { - unsigned long addr; + void __iomem *addr; - addr = PAGE_OFFSET | SW64_IO_BASE(node) | reg; + addr = __va(SW64_IO_BASE(node) | reg); *(volatile unsigned long __iomem *)addr = data; mb(); } diff --git a/arch/sw_64/kernel/dup_print.c b/arch/sw_64/kernel/dup_print.c index 1aa7710b5092..02639f40a4bc 100644 --- a/arch/sw_64/kernel/dup_print.c +++ b/arch/sw_64/kernel/dup_print.c @@ -4,6 +4,7 @@ #include #include +#include #ifdef CONFIG_SW64_RRK @@ -18,7 +19,7 @@ unsigned long sw64_printk_offset; * For output the kernel message on the console * with full-system emulator. */ -#define QEMU_PRINTF_BUFF_BASE (IO_BASE | MCU_BASE | 0x40000UL | PAGE_OFFSET) +#define QEMU_PRINTF_BUFF_BASE (IO_BASE | MCU_BASE | 0x40000UL) int sw64_printk(const char *fmt, va_list args) { @@ -38,9 +39,10 @@ int sw64_printk(const char *fmt, va_list args) } else { printed_len += vscnprintf(sw64_printk_buf, 1024, fmt, args); if (is_in_emul()) { - unsigned long write_addr = QEMU_PRINTF_BUFF_BASE; - *(unsigned long *)write_addr = (unsigned long)((((unsigned long)sw64_printk_buf) & 0xffffffffUL) - | ((unsigned long)printed_len << 32)); + void __iomem *addr = __va(QEMU_PRINTF_BUFF_BASE); + u64 data = ((u64)sw64_printk_buf & 0xffffffffUL) + | ((u64)printed_len << 32); + *(u64 *)addr = data; } } sw64_printk_offset += printed_len; diff --git a/arch/sw_64/kernel/pci.c b/arch/sw_64/kernel/pci.c index 77bbd1b68176..401ee0b781be 100644 --- a/arch/sw_64/kernel/pci.c +++ b/arch/sw_64/kernel/pci.c @@ -398,7 +398,7 @@ int sw6_pcie_read_rc_cfg(struct pci_bus *bus, unsigned int devfn, { u32 data; struct pci_controller *hose = bus->sysdata; - void __iomem *cfg_iobase = (void *)hose->rc_config_space_base; + void __iomem *cfg_iobase = hose->rc_config_space_base; if (IS_ENABLED(CONFIG_PCI_DEBUG)) pr_debug("rc read addr:%px bus %d, devfn %#x, where %#x size=%d\t", @@ -549,9 +549,8 @@ static void __iomem *sw6_pcie_map_bus(struct pci_bus *bus, return NULL; relbus = (bus->number << 24) | (devfn << 16) | where; - relbus |= PCI_EP_CFG; - cfg_iobase = (void *)(hose->ep_config_space_base | relbus); + cfg_iobase = hose->ep_config_space_base + relbus; if (IS_ENABLED(CONFIG_PCI_DEBUG)) pr_debug("addr:%px bus %d, devfn %d, where %d\n", diff --git a/arch/sw_64/kvm/kvm-sw64.c b/arch/sw_64/kvm/kvm-sw64.c index d651d26a957a..839ee83d57d5 100644 --- a/arch/sw_64/kvm/kvm-sw64.c +++ b/arch/sw_64/kvm/kvm-sw64.c @@ -311,7 +311,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, kvm->arch.host_phys_addr = (u64)addr; kvm->arch.size = round_up(mem->memory_size, 8<<20); - memset((void *)(PAGE_OFFSET + addr), 0, 0x2000000); + memset(__va(addr), 0, 0x2000000); return 0; } @@ -344,7 +344,7 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu) memset(&vcpu->arch.irqs_pending, 0, sizeof(vcpu->arch.irqs_pending)); if (vcpu->vcpu_id == 0) - memset((void *)(PAGE_OFFSET + addr), 0, 0x2000000); + memset(__va(addr), 0, 0x2000000); return 0; } @@ -432,18 +432,17 @@ void _debug_printk_vcpu(struct kvm_vcpu *vcpu) { unsigned long pc = vcpu->arch.regs.pc; unsigned long offset = vcpu->kvm->arch.host_phys_addr; - unsigned long pc_phys = PAGE_OFFSET | ((pc & 0x7fffffffUL) + offset); + unsigned int *pc_phys = __va((pc & 0x7fffffffUL) + offset); unsigned int insn; int opc, ra, disp16; - insn = *(unsigned int *)pc_phys; - + insn = *pc_phys; opc = (insn >> 26) & 0x3f; ra = (insn >> 21) & 0x1f; disp16 = insn & 0xffff; if (opc == 0x06 && disp16 == 0x1000) /* RD_F */ - pr_info("vcpu exit: pc = %#lx (%#lx), insn[%x] : rd_f r%d [%#lx]\n", + pr_info("vcpu exit: pc = %#lx (%px), insn[%x] : rd_f r%d [%#lx]\n", pc, pc_phys, insn, ra, vcpu_get_reg(vcpu, ra)); } diff --git a/arch/sw_64/platform/platform_xuelang.c b/arch/sw_64/platform/platform_xuelang.c index f0e33c664b0e..63a4b163e43e 100644 --- a/arch/sw_64/platform/platform_xuelang.c +++ b/arch/sw_64/platform/platform_xuelang.c @@ -54,7 +54,7 @@ static inline void __iomem *xuelang_ioportmap(unsigned long addr) addr = addr | io_offset; } - return (void __iomem *)(addr | PAGE_OFFSET); + return __va(addr); } struct sw64_platform_ops xuelang_ops = { -- Gitee From 53003aee7c6a44a565254b702fe73a0c44fa244b Mon Sep 17 00:00:00 2001 From: He Sheng Date: Thu, 12 May 2022 14:07:00 +0800 Subject: [PATCH 19/71] sw64: access IO space with readX/writeX Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5G5YB -------------------------------- It's more standard to access IO registers by calling readX/writeX interfaces. In addition, the code is easier to maintain. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/chip/chip3/i2c-lib.c | 15 +++++-------- arch/sw_64/include/asm/sw64io.h | 37 ++++++++------------------------- 2 files changed, 14 insertions(+), 38 deletions(-) diff --git a/arch/sw_64/chip/chip3/i2c-lib.c b/arch/sw_64/chip/chip3/i2c-lib.c index b3dcdcd32735..e70f0f0c9a56 100644 --- a/arch/sw_64/chip/chip3/i2c-lib.c +++ b/arch/sw_64/chip/chip3/i2c-lib.c @@ -118,19 +118,14 @@ void __iomem *get_i2c_bar_addr(uint8_t i2c_controller_index) } } -void write_cpu_i2c_controller(uint64_t offset, uint32_t data) +static inline void write_cpu_i2c_controller(uint64_t offset, uint32_t data) { - mb(); - *(volatile uint32_t *)(m_i2c_base_address + offset) = data; + writel(data, m_i2c_base_address + offset); } -uint32_t read_cpu_i2c_controller(uint64_t offset) +static inline uint32_t read_cpu_i2c_controller(uint64_t offset) { - uint32_t data; - - data = *(volatile uint32_t *)(m_i2c_base_address + offset); - mb(); - return data; + return readl(m_i2c_base_address + offset); } static int poll_for_status_set0(uint16_t status_bit) @@ -241,7 +236,7 @@ static int i2c_read(uint8_t reg_offset, uint8_t *buffer, uint32_t length) write_cpu_i2c_controller(DW_IC_DATA_CMD, DW_IC_CMD); if (poll_for_status_set0(DW_IC_STATUS_RFNE) == 0) - buffer[i] = *(uint8_t *) (m_i2c_base_address + DW_IC_DATA_CMD); + buffer[i] = readb(m_i2c_base_address + DW_IC_DATA_CMD); else pr_err("Read timeout line %d.\n", __LINE__); } diff --git a/arch/sw_64/include/asm/sw64io.h b/arch/sw_64/include/asm/sw64io.h index e66aba66932b..7d79a5b75090 100644 --- a/arch/sw_64/include/asm/sw64io.h +++ b/arch/sw_64/include/asm/sw64io.h @@ -2,6 +2,7 @@ #ifndef _ASM_SW64_SW64IO_H #define _ASM_SW64_SW64IO_H +#include #include extern void setup_chip_clocksource(void); @@ -22,13 +23,9 @@ read_rc_conf(unsigned long node, unsigned long rc, unsigned int offset) { void __iomem *addr; - unsigned int value; addr = __va(MK_RC_CFG(node, rc) | offset); - value = *(volatile unsigned int *)addr; - mb(); - - return value; + return readl(addr); } static inline void @@ -38,8 +35,7 @@ write_rc_conf(unsigned long node, unsigned long rc, void __iomem *addr; addr = __va(MK_RC_CFG(node, rc) | offset); - *(unsigned int *)addr = data; - mb(); + writel(data, addr); } static inline unsigned long @@ -47,13 +43,9 @@ read_piu_ior0(unsigned long node, unsigned long rc, unsigned int reg) { void __iomem *addr; - unsigned long value; addr = __va(MK_PIU_IOR0(node, rc) + reg); - value = *(volatile unsigned long __iomem *)addr; - mb(); - - return value; + return readq(addr); } static inline void @@ -63,8 +55,7 @@ write_piu_ior0(unsigned long node, unsigned long rc, void __iomem *addr; addr = __va(MK_PIU_IOR0(node, rc) + reg); - *(unsigned long __iomem *)addr = data; - mb(); + writeq(data, addr); } static inline unsigned long @@ -72,13 +63,9 @@ read_piu_ior1(unsigned long node, unsigned long rc, unsigned int reg) { void __iomem *addr; - unsigned long value; addr = __va(MK_PIU_IOR1(node, rc) + reg); - value = *(volatile unsigned long __iomem *)addr; - mb(); - - return value; + return readq(addr); } static inline void @@ -88,21 +75,16 @@ write_piu_ior1(unsigned long node, unsigned long rc, void __iomem *addr; addr = __va(MK_PIU_IOR1(node, rc) + reg); - *(volatile unsigned long __iomem *)addr = data; - mb(); + writeq(data, addr); } static inline unsigned long sw64_io_read(unsigned long node, unsigned long reg) { void __iomem *addr; - unsigned long value; addr = __va(SW64_IO_BASE(node) | reg); - value = *(volatile unsigned long __iomem *)addr; - mb(); - - return value; + return readq(addr); } static inline void @@ -111,7 +93,6 @@ sw64_io_write(unsigned long node, unsigned long reg, unsigned long data) void __iomem *addr; addr = __va(SW64_IO_BASE(node) | reg); - *(volatile unsigned long __iomem *)addr = data; - mb(); + writeq(data, addr); } #endif -- Gitee From 687ba666ce3a7f7c55eaa7b325d0ad928559798c Mon Sep 17 00:00:00 2001 From: He Sheng Date: Thu, 21 Apr 2022 17:13:53 +0800 Subject: [PATCH 20/71] sw64: add fpu state save/restore interfaces Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/Makefile | 2 +- arch/sw_64/kernel/fpu.S | 106 +++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 arch/sw_64/kernel/fpu.S diff --git a/arch/sw_64/kernel/Makefile b/arch/sw_64/kernel/Makefile index f6a2813b0466..293b360626f7 100644 --- a/arch/sw_64/kernel/Makefile +++ b/arch/sw_64/kernel/Makefile @@ -13,7 +13,7 @@ CFLAGS_REMOVE_insn.o = -pg CFLAGS_REMOVE_printk.o = -pg endif -obj-y := entry.o traps.o process.o sys_sw64.o irq.o \ +obj-y := entry.o fpu.o traps.o process.o sys_sw64.o irq.o \ irq_sw64.o signal.o setup.o ptrace.o time.o \ systbls.o dup_print.o tc.o \ insn.o early_init.o topology.o cacheinfo.o \ diff --git a/arch/sw_64/kernel/fpu.S b/arch/sw_64/kernel/fpu.S new file mode 100644 index 000000000000..25dcf4740525 --- /dev/null +++ b/arch/sw_64/kernel/fpu.S @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include +#include +#include + + .text + .set noat +ENTRY(__fpstate_save) + /* a0: prev task */ + ldi a0, TASK_THREAD(a0) + ldi t0, THREAD_CTX_FP(a0) + vstd $f0, CTX_FP_F0(t0) + vstd $f1, CTX_FP_F1(t0) + vstd $f2, CTX_FP_F2(t0) + vstd $f3, CTX_FP_F3(t0) + vstd $f4, CTX_FP_F4(t0) + vstd $f5, CTX_FP_F5(t0) + vstd $f6, CTX_FP_F6(t0) + vstd $f7, CTX_FP_F7(t0) + vstd $f8, CTX_FP_F8(t0) + vstd $f9, CTX_FP_F9(t0) + vstd $f10, CTX_FP_F10(t0) + vstd $f11, CTX_FP_F11(t0) + vstd $f12, CTX_FP_F12(t0) + vstd $f13, CTX_FP_F13(t0) + vstd $f14, CTX_FP_F14(t0) + vstd $f15, CTX_FP_F15(t0) + vstd $f16, CTX_FP_F16(t0) + vstd $f17, CTX_FP_F17(t0) + vstd $f18, CTX_FP_F18(t0) + vstd $f19, CTX_FP_F19(t0) + vstd $f20, CTX_FP_F20(t0) + vstd $f21, CTX_FP_F21(t0) + vstd $f22, CTX_FP_F22(t0) + vstd $f23, CTX_FP_F23(t0) + vstd $f24, CTX_FP_F24(t0) + vstd $f25, CTX_FP_F25(t0) + vstd $f26, CTX_FP_F26(t0) + vstd $f27, CTX_FP_F27(t0) + rfpcr $f0 + vstd $f28, CTX_FP_F28(t0) + vstd $f29, CTX_FP_F29(t0) + vstd $f30, CTX_FP_F30(t0) + fstd $f0, THREAD_FPCR(a0) + vldd $f0, CTX_FP_F0(t0) + ret +END(__fpstate_save) + +ENTRY(__fpstate_restore) + /* a0: next task */ + ldi a0, TASK_THREAD(a0) + fldd $f0, THREAD_FPCR(a0) + wfpcr $f0 + fimovd $f0, t1 + and t1, 0x3, t1 + beq t1, $setfpec_0 + subl t1, 0x1, t1 + beq t1, $setfpec_1 + subl t1, 0x1, t1 + beq t1, $setfpec_2 + setfpec3 + br $setfpec_over +$setfpec_0: + setfpec0 + br $setfpec_over +$setfpec_1: + setfpec1 + br $setfpec_over +$setfpec_2: + setfpec2 +$setfpec_over: + ldi t0, THREAD_CTX_FP(a0) + vldd $f0, CTX_FP_F0(t0) + vldd $f1, CTX_FP_F1(t0) + vldd $f2, CTX_FP_F2(t0) + vldd $f3, CTX_FP_F3(t0) + vldd $f4, CTX_FP_F4(t0) + vldd $f5, CTX_FP_F5(t0) + vldd $f6, CTX_FP_F6(t0) + vldd $f7, CTX_FP_F7(t0) + vldd $f8, CTX_FP_F8(t0) + vldd $f9, CTX_FP_F9(t0) + vldd $f10, CTX_FP_F10(t0) + vldd $f11, CTX_FP_F11(t0) + vldd $f12, CTX_FP_F12(t0) + vldd $f13, CTX_FP_F13(t0) + vldd $f14, CTX_FP_F14(t0) + vldd $f15, CTX_FP_F15(t0) + vldd $f16, CTX_FP_F16(t0) + vldd $f17, CTX_FP_F17(t0) + vldd $f18, CTX_FP_F18(t0) + vldd $f19, CTX_FP_F19(t0) + vldd $f20, CTX_FP_F20(t0) + vldd $f21, CTX_FP_F21(t0) + vldd $f22, CTX_FP_F22(t0) + vldd $f23, CTX_FP_F23(t0) + vldd $f24, CTX_FP_F24(t0) + vldd $f25, CTX_FP_F25(t0) + vldd $f26, CTX_FP_F26(t0) + vldd $f27, CTX_FP_F27(t0) + vldd $f28, CTX_FP_F28(t0) + vldd $f29, CTX_FP_F29(t0) + vldd $f30, CTX_FP_F30(t0) + ret +END(__fpstate_restore) -- Gitee From fa1cadd2b145b88c6ffb9fd8cd540967b5f7c067 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 22 Apr 2022 09:29:43 +0800 Subject: [PATCH 21/71] sw64: switch to generic fork like system calls Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- We put thread's callee-saved registers in thread_struct, and put exception callee-saved registers in pt_regs. For context switch, it switches fpu state first, and then switches integer registers in __switch_to. Because callee-saved registers are always saved and restored, it will cause a little overhead. As a result, the special sw64 fork like system calls are removed. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/processor.h | 3 + arch/sw_64/include/asm/switch_to.h | 37 +++++- arch/sw_64/include/uapi/asm/ptrace.h | 15 ++- arch/sw_64/kernel/asm-offsets.c | 16 +++ arch/sw_64/kernel/entry.S | 173 +++++++++++++++---------- arch/sw_64/kernel/process.c | 21 ++- arch/sw_64/kernel/syscalls/syscall.tbl | 6 +- 7 files changed, 175 insertions(+), 96 deletions(-) diff --git a/arch/sw_64/include/asm/processor.h b/arch/sw_64/include/asm/processor.h index 645c33a596ff..67d3b4368987 100644 --- a/arch/sw_64/include/asm/processor.h +++ b/arch/sw_64/include/asm/processor.h @@ -78,6 +78,9 @@ struct context_fpregs { struct thread_struct { struct context_fpregs ctx_fp; unsigned long fpcr; + /* Callee-saved registers */ + unsigned long ra; + unsigned long s[7]; /* s0 ~ s6 */ }; #define INIT_THREAD { } diff --git a/arch/sw_64/include/asm/switch_to.h b/arch/sw_64/include/asm/switch_to.h index 22045b247557..d503fc59390f 100644 --- a/arch/sw_64/include/asm/switch_to.h +++ b/arch/sw_64/include/asm/switch_to.h @@ -2,12 +2,41 @@ #ifndef _ASM_SW64_SWITCH_TO_H #define _ASM_SW64_SWITCH_TO_H -struct task_struct; -extern struct task_struct *__switch_to(unsigned long, struct task_struct *); +#include + +extern void __fpstate_save(struct task_struct *save_to); +extern void __fpstate_restore(struct task_struct *restore_from); +extern struct task_struct *__switch_to(unsigned long pcb, + struct task_struct *prev, struct task_struct *next); extern void restore_da_match_after_sched(void); -#define switch_to(P, N, L) \ + +static inline void fpstate_save(struct task_struct *task) +{ + if (likely(!(task->flags & PF_KTHREAD))) + __fpstate_save(task); +} + +static inline void fpstate_restore(struct task_struct *task) +{ + if (likely(!(task->flags & PF_KTHREAD))) + __fpstate_restore(task); +} + +static inline void __switch_to_aux(struct task_struct *prev, + struct task_struct *next) +{ + fpstate_save(prev); + fpstate_restore(next); +} + + +#define switch_to(prev, next, last) \ do { \ - (L) = __switch_to(virt_to_phys(&task_thread_info(N)->pcb), (P));\ + struct task_struct *__prev = (prev); \ + struct task_struct *__next = (next); \ + __u64 __nextpcb = virt_to_phys(&task_thread_info(__next)->pcb); \ + __switch_to_aux(__prev, __next); \ + (last) = __switch_to(__nextpcb, __prev, __next); \ check_mmu_context(); \ } while (0) diff --git a/arch/sw_64/include/uapi/asm/ptrace.h b/arch/sw_64/include/uapi/asm/ptrace.h index 96cb10891bea..4549e8d4bf57 100644 --- a/arch/sw_64/include/uapi/asm/ptrace.h +++ b/arch/sw_64/include/uapi/asm/ptrace.h @@ -9,12 +9,7 @@ * * NOTE! I want to minimize the overhead of system calls, so this * struct has as little information as possible. I does not have - * - * - floating point regs: the kernel doesn't change those - * - r9-15: saved by the C compiler - * - * This makes "fork()" and "exec()" a bit more complex, but should - * give us low system call latency. + * floating point regs, because the kernel doesn't change those */ struct pt_regs { @@ -27,6 +22,14 @@ struct pt_regs { unsigned long r6; unsigned long r7; unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; + /* r16 ~ r18 saved by hmcode */ unsigned long r19; unsigned long r20; unsigned long r21; diff --git a/arch/sw_64/kernel/asm-offsets.c b/arch/sw_64/kernel/asm-offsets.c index bea12d2d96fe..349bc5c4e2f1 100644 --- a/arch/sw_64/kernel/asm-offsets.c +++ b/arch/sw_64/kernel/asm-offsets.c @@ -72,6 +72,13 @@ void foo(void) DEFINE(PT_REGS_R6, offsetof(struct pt_regs, r6)); DEFINE(PT_REGS_R7, offsetof(struct pt_regs, r7)); DEFINE(PT_REGS_R8, offsetof(struct pt_regs, r8)); + DEFINE(PT_REGS_R9, offsetof(struct pt_regs, r9)); + DEFINE(PT_REGS_R10, offsetof(struct pt_regs, r10)); + DEFINE(PT_REGS_R11, offsetof(struct pt_regs, r11)); + DEFINE(PT_REGS_R12, offsetof(struct pt_regs, r12)); + DEFINE(PT_REGS_R13, offsetof(struct pt_regs, r13)); + DEFINE(PT_REGS_R14, offsetof(struct pt_regs, r14)); + DEFINE(PT_REGS_R15, offsetof(struct pt_regs, r15)); DEFINE(PT_REGS_R19, offsetof(struct pt_regs, r19)); DEFINE(PT_REGS_R20, offsetof(struct pt_regs, r20)); DEFINE(PT_REGS_R21, offsetof(struct pt_regs, r21)); @@ -258,4 +265,13 @@ void foo(void) DEFINE(CTX_FP_F29, offsetof(struct context_fpregs, f29)); DEFINE(CTX_FP_F30, offsetof(struct context_fpregs, f30)); BLANK(); + OFFSET(TASK_THREAD_RA, task_struct, thread.ra); + OFFSET(TASK_THREAD_S0, task_struct, thread.s[0]); + OFFSET(TASK_THREAD_S1, task_struct, thread.s[1]); + OFFSET(TASK_THREAD_S2, task_struct, thread.s[2]); + OFFSET(TASK_THREAD_S3, task_struct, thread.s[3]); + OFFSET(TASK_THREAD_S4, task_struct, thread.s[4]); + OFFSET(TASK_THREAD_S5, task_struct, thread.s[5]); + OFFSET(TASK_THREAD_S6, task_struct, thread.s[6]); + BLANK(); } diff --git a/arch/sw_64/kernel/entry.S b/arch/sw_64/kernel/entry.S index 6c40d2015439..ac62461aa9dc 100644 --- a/arch/sw_64/kernel/entry.S +++ b/arch/sw_64/kernel/entry.S @@ -21,52 +21,84 @@ * the hmcode-provided values are available to the signal handler. */ -#define SAVE_ALL \ - ldi $sp, -PT_REGS_PS($sp); \ - stl $0, PT_REGS_R0($sp); \ - stl $1, PT_REGS_R1($sp); \ - stl $2, PT_REGS_R2($sp); \ - stl $3, PT_REGS_R3($sp); \ - stl $4, PT_REGS_R4($sp); \ - stl $28, PT_REGS_R28($sp); \ - stl $5, PT_REGS_R5($sp); \ - stl $6, PT_REGS_R6($sp); \ - stl $7, PT_REGS_R7($sp); \ - stl $8, PT_REGS_R8($sp); \ - stl $19, PT_REGS_R19($sp); \ - stl $20, PT_REGS_R20($sp); \ - stl $21, PT_REGS_R21($sp); \ - stl $22, PT_REGS_R22($sp); \ - stl $23, PT_REGS_R23($sp); \ - stl $24, PT_REGS_R24($sp); \ - stl $25, PT_REGS_R25($sp); \ - stl $26, PT_REGS_R26($sp); \ - stl $27, PT_REGS_R27($sp); \ - stl $16, PT_REGS_TRAP_A0($sp); \ - stl $17, PT_REGS_TRAP_A1($sp); \ + .macro SAVE_COMMON_REGS + ldi $sp, -PT_REGS_PS($sp) + stl $0, PT_REGS_R0($sp) + stl $1, PT_REGS_R1($sp) + stl $2, PT_REGS_R2($sp) + stl $3, PT_REGS_R3($sp) + stl $4, PT_REGS_R4($sp) + stl $28, PT_REGS_R28($sp) + stl $5, PT_REGS_R5($sp) + stl $6, PT_REGS_R6($sp) + stl $7, PT_REGS_R7($sp) + stl $8, PT_REGS_R8($sp) + stl $19, PT_REGS_R19($sp) + stl $20, PT_REGS_R20($sp) + stl $21, PT_REGS_R21($sp) + stl $22, PT_REGS_R22($sp) + stl $23, PT_REGS_R23($sp) + stl $24, PT_REGS_R24($sp) + stl $25, PT_REGS_R25($sp) + stl $26, PT_REGS_R26($sp) + stl $27, PT_REGS_R27($sp) + stl $16, PT_REGS_TRAP_A0($sp) + stl $17, PT_REGS_TRAP_A1($sp) stl $18, PT_REGS_TRAP_A2($sp) + .endm -#define RESTORE_ALL \ - ldl $0, PT_REGS_R0($sp); \ - ldl $1, PT_REGS_R1($sp); \ - ldl $2, PT_REGS_R2($sp); \ - ldl $3, PT_REGS_R3($sp); \ - ldl $4, PT_REGS_R4($sp); \ - ldl $5, PT_REGS_R5($sp); \ - ldl $6, PT_REGS_R6($sp); \ - ldl $7, PT_REGS_R7($sp); \ - ldl $8, PT_REGS_R8($sp); \ - ldl $19, PT_REGS_R19($sp); \ - ldl $20, PT_REGS_R20($sp); \ - ldl $21, PT_REGS_R21($sp); \ - ldl $22, PT_REGS_R22($sp); \ - ldl $23, PT_REGS_R23($sp); \ - ldl $24, PT_REGS_R24($sp); \ - ldl $25, PT_REGS_R25($sp); \ - ldl $26, PT_REGS_R26($sp); \ - ldl $27, PT_REGS_R27($sp); \ - ldl $28, PT_REGS_R28($sp); \ + .macro RESTORE_COMMON_REGS + ldl $0, PT_REGS_R0($sp) + ldl $1, PT_REGS_R1($sp) + ldl $2, PT_REGS_R2($sp) + ldl $3, PT_REGS_R3($sp) + ldl $4, PT_REGS_R4($sp) + ldl $5, PT_REGS_R5($sp) + ldl $6, PT_REGS_R6($sp) + ldl $7, PT_REGS_R7($sp) + ldl $8, PT_REGS_R8($sp) + ldl $19, PT_REGS_R19($sp) + ldl $20, PT_REGS_R20($sp) + ldl $21, PT_REGS_R21($sp) + ldl $22, PT_REGS_R22($sp) + ldl $23, PT_REGS_R23($sp) + ldl $24, PT_REGS_R24($sp) + ldl $25, PT_REGS_R25($sp) + ldl $26, PT_REGS_R26($sp) + ldl $27, PT_REGS_R27($sp) + ldl $28, PT_REGS_R28($sp) ldi $sp, PT_REGS_PS($sp) + .endm + + .macro SAVE_CALLEE_REGS + stl $9, PT_REGS_R9($sp) + stl $10, PT_REGS_R10($sp) + stl $11, PT_REGS_R11($sp) + stl $12, PT_REGS_R12($sp) + stl $13, PT_REGS_R13($sp) + stl $14, PT_REGS_R14($sp) + stl $15, PT_REGS_R15($sp) + .endm + + .macro RESTORE_CALLEE_REGS + ldl $9, PT_REGS_R9($sp) + ldl $10, PT_REGS_R10($sp) + ldl $11, PT_REGS_R11($sp) + ldl $12, PT_REGS_R12($sp) + ldl $13, PT_REGS_R13($sp) + ldl $14, PT_REGS_R14($sp) + ldl $15, PT_REGS_R15($sp) + .endm + + .macro SAVE_ALL + SAVE_COMMON_REGS + SAVE_CALLEE_REGS + .endm + + .macro RESTORE_ALL + RESTORE_CALLEE_REGS + RESTORE_COMMON_REGS + .endm /* * Non-syscall kernel entry points. @@ -591,19 +623,42 @@ $setfpec_over: .end undo_switch_stack /* - * The meat of the context switch code. + * Integer register context switch + * The callee-saved registers must be saved and restored. + * + * a0: physical address of next task's pcb, used by hmcode + * a1: previous task_struct (must be preserved across the switch) + * a2: next task_struct + * + * The value of a1 must be preserved by this function, as that's how + * arguments are passed to schedule_tail. */ - .align 4 .globl __switch_to .ent __switch_to __switch_to: .prologue 0 - bsr $1, do_switch_stack + /* Save context into prev->thread */ + stl $26, TASK_THREAD_RA($17) + stl $9, TASK_THREAD_S0($17) + stl $10, TASK_THREAD_S1($17) + stl $11, TASK_THREAD_S2($17) + stl $12, TASK_THREAD_S3($17) + stl $13, TASK_THREAD_S4($17) + stl $14, TASK_THREAD_S5($17) + stl $15, TASK_THREAD_S6($17) + /* Restore context from next->thread */ + ldl $26, TASK_THREAD_RA($18) + ldl $9, TASK_THREAD_S0($18) + ldl $10, TASK_THREAD_S1($18) + ldl $11, TASK_THREAD_S2($18) + ldl $12, TASK_THREAD_S3($18) + ldl $13, TASK_THREAD_S4($18) + ldl $14, TASK_THREAD_S5($18) + ldl $15, TASK_THREAD_S6($18) sys_call HMC_swpctx ldi $8, 0x3fff bic $sp, $8, $8 - bsr $1, undo_switch_stack mov $17, $0 ret .end __switch_to @@ -637,30 +692,6 @@ ret_from_kernel_thread: br $31, ret_to_user .end ret_from_kernel_thread -/* - * Special system calls. Most of these are special in that they either - * have to play switch_stack games or in some way use the pt_regs struct. - */ - -.macro fork_like name - .align 4 - .globl sw64_\name - .ent sw64_\name -sw64_\name: - .prologue 0 - bsr $1, do_switch_stack - call $26, sys_\name - ldl $26, SWITCH_STACK_RA($sp) - ldi $sp, SWITCH_STACK_SIZE($sp) - ret - .end sw64_\name - .endm - -fork_like fork -fork_like vfork -fork_like clone -fork_like clone3 - .align 4 .globl sys_sigreturn .ent sys_sigreturn diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index 4192d50f5b0e..c6e87874af19 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -11,6 +11,7 @@ #include #include +#include #include "proto.h" @@ -158,19 +159,18 @@ copy_thread(unsigned long clone_flags, unsigned long usp, struct thread_info *childti = task_thread_info(p); struct pt_regs *childregs = task_pt_regs(p); struct pt_regs *regs = current_pt_regs(); - struct switch_stack *childstack, *stack; - childstack = ((struct switch_stack *) childregs) - 1; - childti->pcb.ksp = (unsigned long) childstack; + childti->pcb.ksp = (unsigned long) childregs; childti->pcb.flags = 7; /* set FEN, clear everything else */ + __fpstate_save(current); + p->thread = current->thread; if (unlikely(p->flags & PF_KTHREAD)) { /* kernel thread */ - memset(childstack, 0, - sizeof(struct switch_stack) + sizeof(struct pt_regs)); - childstack->r26 = (unsigned long) ret_from_kernel_thread; - childstack->r9 = usp; /* function */ - childstack->r10 = kthread_arg; + memset(childregs, 0, sizeof(struct pt_regs)); + p->thread.ra = (unsigned long) ret_from_kernel_thread; + p->thread.s[0] = usp; /* function */ + p->thread.s[1] = kthread_arg; childti->pcb.usp = 0; return 0; } @@ -189,10 +189,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, *childregs = *regs; childregs->r0 = 0; childregs->r19 = 0; - stack = ((struct switch_stack *) regs) - 1; - *childstack = *stack; - p->thread = current->thread; - childstack->r26 = (unsigned long) ret_from_fork; + p->thread.ra = (unsigned long) ret_from_fork; return 0; } diff --git a/arch/sw_64/kernel/syscalls/syscall.tbl b/arch/sw_64/kernel/syscalls/syscall.tbl index b9b93d70124d..42a179422b6b 100644 --- a/arch/sw_64/kernel/syscalls/syscall.tbl +++ b/arch/sw_64/kernel/syscalls/syscall.tbl @@ -73,7 +73,7 @@ 63 common getpgrp sys_getpgrp #64 is unused #65 is unused -66 common vfork sw64_vfork +66 common vfork sys_vfork 67 common stat sys_newstat 68 common lstat sys_newlstat #69 is unused @@ -289,7 +289,7 @@ 279 common fsmount sys_fsmount 280 common fspick sys_fspick 281 common pidfd_open sys_pidfd_open -282 common clone3 sw64_clone3 +282 common clone3 sys_clone3 283 common close_range sys_close_range 284 common openat2 sys_openat2 285 common pidfd_getfd sys_pidfd_getfd @@ -319,7 +319,7 @@ 309 common get_kernel_syms sys_ni_syscall 310 common syslog sys_syslog 311 common reboot sys_reboot -312 common clone sw64_clone +312 common clone sys_clone 313 common uselib sys_uselib 314 common mlock sys_mlock 315 common munlock sys_munlock -- Gitee From cf8d42cc0e6dc5fe55895a233aa95418a157145c Mon Sep 17 00:00:00 2001 From: He Sheng Date: Sun, 24 Apr 2022 09:11:52 +0800 Subject: [PATCH 22/71] sw64: remove r9_r15 argument of dik_show_regs and die_if_kernel Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/process.c | 2 +- arch/sw_64/kernel/proto.h | 4 ++-- arch/sw_64/kernel/ptrace.c | 2 +- arch/sw_64/kernel/traps.c | 27 ++++++++++++--------------- arch/sw_64/mm/fault.c | 8 ++++---- arch/sw_64/mm/init.c | 2 -- 6 files changed, 20 insertions(+), 25 deletions(-) diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index c6e87874af19..9a6812851b15 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -110,7 +110,7 @@ void show_regs(struct pt_regs *regs) { show_regs_print_info(KERN_DEFAULT); - dik_show_regs(regs, NULL); + dik_show_regs(regs); } /* diff --git a/arch/sw_64/kernel/proto.h b/arch/sw_64/kernel/proto.h index 9c99baaaf1d0..189074f8bd5c 100644 --- a/arch/sw_64/kernel/proto.h +++ b/arch/sw_64/kernel/proto.h @@ -12,8 +12,8 @@ extern int ptrace_set_bpt(struct task_struct *child); extern int ptrace_cancel_bpt(struct task_struct *child); /* traps.c */ -extern void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15); -extern void die_if_kernel(char *str, struct pt_regs *regs, long err, unsigned long *r9_15); +extern void dik_show_regs(struct pt_regs *regs); +extern void die_if_kernel(char *str, struct pt_regs *regs, long err); /* timer.c */ extern void setup_timer(void); diff --git a/arch/sw_64/kernel/ptrace.c b/arch/sw_64/kernel/ptrace.c index b06c98e9944b..3b29ff7114f7 100644 --- a/arch/sw_64/kernel/ptrace.c +++ b/arch/sw_64/kernel/ptrace.c @@ -521,7 +521,7 @@ int do_match(unsigned long address, unsigned long mmcsr, long cause, struct pt_r case MMCSR__DA_MATCH: case MMCSR__DV_MATCH: case MMCSR__DAV_MATCH: - dik_show_regs(regs, (unsigned long *)regs-15); + dik_show_regs(regs); if (!(current->ptrace & PT_PTRACED)) { printk(" pid %d %s not be ptraced, return\n", current->pid, current->comm); diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index 99cee58e886d..b7c4e45df87b 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -22,8 +22,7 @@ #include "proto.h" -void -dik_show_regs(struct pt_regs *regs, unsigned long *r9_15) +void dik_show_regs(struct pt_regs *regs) { printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx %s\n", regs->pc, regs->r26, regs->ps, print_tainted()); @@ -36,13 +35,12 @@ dik_show_regs(struct pt_regs *regs, unsigned long *r9_15) printk("t5 = %016lx t6 = %016lx t7 = %016lx\n", regs->r6, regs->r7, regs->r8); - if (r9_15) { - printk("s0 = %016lx s1 = %016lx s2 = %016lx\n", - r9_15[9], r9_15[10], r9_15[11]); - printk("s3 = %016lx s4 = %016lx s5 = %016lx\n", - r9_15[12], r9_15[13], r9_15[14]); - printk("s6 = %016lx\n", r9_15[15]); - } + printk("s0 = %016lx s1 = %016lx s2 = %016lx\n", + regs->r9, regs->r10, regs->r11); + printk("s3 = %016lx s4 = %016lx s5 = %016lx\n", + regs->r12, regs->r13, regs->r14); + printk("s6 = %016lx\n", + regs->r15); printk("a0 = %016lx a1 = %016lx a2 = %016lx\n", regs->r16, regs->r17, regs->r18); @@ -117,8 +115,7 @@ void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl) dik_show_trace(sp, loglvl); } -void -die_if_kernel(char *str, struct pt_regs *regs, long err, unsigned long *r9_15) +void die_if_kernel(char *str, struct pt_regs *regs, long err) { if (regs->ps & 8) return; @@ -126,7 +123,7 @@ die_if_kernel(char *str, struct pt_regs *regs, long err, unsigned long *r9_15) printk("CPU %d ", hard_smp_processor_id()); #endif printk("%s(%d): %s %ld\n", current->comm, task_pid_nr(current), str, err); - dik_show_regs(regs, r9_15); + dik_show_regs(regs); add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); dik_show_trace((unsigned long *)(regs+1), KERN_DEFAULT); dik_show_code((unsigned int *)regs->pc); @@ -178,7 +175,7 @@ do_entArith(unsigned long summary, unsigned long write_mask, if (si_code == 0) return; } - die_if_kernel("Arithmetic fault", regs, 0, NULL); + die_if_kernel("Arithmetic fault", regs, 0); force_sig_fault(SIGFPE, si_code, (void __user *)regs->pc, 0); } @@ -205,7 +202,7 @@ do_entIF(unsigned long inst_type, struct pt_regs *regs) return; } die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"), - regs, type, NULL); + regs, type); } switch (type) { @@ -297,7 +294,7 @@ do_entIF(unsigned long inst_type, struct pt_regs *regs) return; } if ((regs->ps & ~IPL_MAX) == 0) - die_if_kernel("Instruction fault", regs, type, NULL); + die_if_kernel("Instruction fault", regs, type); break; case 3: /* FEN fault */ diff --git a/arch/sw_64/mm/fault.c b/arch/sw_64/mm/fault.c index b580450893ba..9562bc3ba37f 100644 --- a/arch/sw_64/mm/fault.c +++ b/arch/sw_64/mm/fault.c @@ -31,8 +31,8 @@ static inline int notify_page_fault(struct pt_regs *regs, unsigned long mmcsr) } #endif -extern void die_if_kernel(char *, struct pt_regs *, long, unsigned long *); -extern void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15); +extern void die_if_kernel(char *, struct pt_regs *, long); +extern void dik_show_regs(struct pt_regs *regs); void show_all_vma(void) { @@ -305,7 +305,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, */ pr_alert("Unable to handle kernel paging request at virtual address %016lx\n", address); - die_if_kernel("Oops", regs, cause, (unsigned long *)regs - 16); + die_if_kernel("Oops", regs, cause); do_exit(SIGKILL); /* @@ -336,7 +336,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, if (unlikely(segv_debug_enabled)) { pr_info("fault: want to send_segv: pid %d, cause = %#lx, mmcsr = %#lx, address = %#lx, pc %#lx\n", current->pid, cause, mmcsr, address, regs->pc); - dik_show_regs(regs, (unsigned long *)regs-16); + dik_show_regs(regs); show_all_vma(); } diff --git a/arch/sw_64/mm/init.c b/arch/sw_64/mm/init.c index 7fcd3d834ba5..3593e4b13319 100644 --- a/arch/sw_64/mm/init.c +++ b/arch/sw_64/mm/init.c @@ -13,8 +13,6 @@ #include -extern void die_if_kernel(char *, struct pt_regs *, long); - struct mem_desc_t mem_desc; #ifndef CONFIG_NUMA struct numa_node_desc_t numa_nodes_desc[1]; -- Gitee From 9edfcf89f2df44eda3a312e0c958914f391a14cf Mon Sep 17 00:00:00 2001 From: He Sheng Date: Sun, 24 Apr 2022 09:52:46 +0800 Subject: [PATCH 23/71] sw64: remove switch_stack from entMM and entSys Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- This patch removes switch_stack and its usages in mm fault entry and system call entry. Note that ptrace accesses registers with struct pt_regs only since strace gave up a switch_stack trick. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/entry.S | 42 +++----------------------------------- arch/sw_64/kernel/ptrace.c | 12 ++--------- 2 files changed, 5 insertions(+), 49 deletions(-) diff --git a/arch/sw_64/kernel/entry.S b/arch/sw_64/kernel/entry.S index ac62461aa9dc..f843acd88249 100644 --- a/arch/sw_64/kernel/entry.S +++ b/arch/sw_64/kernel/entry.S @@ -133,31 +133,11 @@ entArith: .ent entMM entMM: SAVE_ALL -/* save $9 - $15 so the inline exception code can manipulate them. */ - subl $sp, SWITCH_STACK_RA, $sp - stl $9, SWITCH_STACK_R9($sp) - stl $10, SWITCH_STACK_R10($sp) - stl $11, SWITCH_STACK_R11($sp) - stl $12, SWITCH_STACK_R12($sp) - stl $13, SWITCH_STACK_R13($sp) - stl $14, SWITCH_STACK_R14($sp) - stl $15, SWITCH_STACK_R15($sp) - addl $sp, SWITCH_STACK_RA, $19 -/* handle the fault */ ldi $8, 0x3fff + ldi $26, ret_from_sys_call bic $sp, $8, $8 - call $26, do_page_fault -/* reload the registers after the exception code played. */ - ldl $9, SWITCH_STACK_R9($sp) - ldl $10, SWITCH_STACK_R10($sp) - ldl $11, SWITCH_STACK_R11($sp) - ldl $12, SWITCH_STACK_R12($sp) - ldl $13, SWITCH_STACK_R13($sp) - ldl $14, SWITCH_STACK_R14($sp) - ldl $15, SWITCH_STACK_R15($sp) - addl $sp, SWITCH_STACK_RA, $sp -/* finish up the syscall as normal. */ - br ret_from_sys_call + mov $sp, $19 + call $31, do_page_fault .end entMM .align 4 @@ -400,9 +380,7 @@ $work_resched: $work_notifysig: mov $sp, $16 - bsr $1, do_switch_stack call $26, do_work_pending - bsr $1, undo_switch_stack br restore_all .end work_pending @@ -416,14 +394,9 @@ $work_notifysig: .ent strace strace: /* set up signal stack, call syscall_trace */ - bsr $1, do_switch_stack mov $0, $9 mov $19, $10 call $26, syscall_trace_enter - mov $9, $18 - mov $10, $19 - bsr $1, undo_switch_stack - blt $0, $syscall_trace_failed /* get the system call number and the arguments back.. */ @@ -452,10 +425,7 @@ ret_from_straced: stl $31, PT_REGS_R19($sp) /* a3=0 => no error */ $strace_success: stl $0, PT_REGS_R0($sp) /* save return value */ - - bsr $1, do_switch_stack call $26, syscall_trace_leave - bsr $1, undo_switch_stack br $31, ret_from_sys_call .align 3 @@ -470,25 +440,19 @@ $strace_error: stl $0, PT_REGS_R0($sp) stl $1, PT_REGS_R19($sp) /* a3 for return */ - bsr $1, do_switch_stack mov $18, $9 /* save old syscall number */ mov $19, $10 /* save old a3 */ call $26, syscall_trace_leave mov $9, $18 mov $10, $19 - bsr $1, undo_switch_stack mov $31, $26 /* tell "ret_from_sys_call" we can restart */ br ret_from_sys_call $syscall_trace_failed: - bsr $1, do_switch_stack - mov $18, $9 - mov $19, $10 call $26, syscall_trace_leave mov $9, $18 mov $10, $19 - bsr $1, undo_switch_stack mov $31, $26 /* tell "ret_from_sys_call" we can restart */ br ret_from_sys_call .end strace diff --git a/arch/sw_64/kernel/ptrace.c b/arch/sw_64/kernel/ptrace.c index 3b29ff7114f7..097590b22a5a 100644 --- a/arch/sw_64/kernel/ptrace.c +++ b/arch/sw_64/kernel/ptrace.c @@ -33,10 +33,6 @@ * | frame generated by SAVE_ALL | | * | | v * +================================+ - * | | ^ - * | frame saved by do_switch_stack | | struct switch_stack - * | | v - * +================================+ */ /* @@ -59,18 +55,14 @@ enum { #define PT_REG(reg) \ (PAGE_SIZE * 2 - sizeof(struct pt_regs) + offsetof(struct pt_regs, reg)) -#define SW_REG(reg) \ - (PAGE_SIZE * 2 - sizeof(struct pt_regs) - sizeof(struct switch_stack) \ - + offsetof(struct switch_stack, reg)) - #define FP_REG(fp_regno, vector_regno) \ (fp_regno * 32 + vector_regno * 8) static int regoff[] = { PT_REG(r0), PT_REG(r1), PT_REG(r2), PT_REG(r3), PT_REG(r4), PT_REG(r5), PT_REG(r6), PT_REG(r7), - PT_REG(r8), SW_REG(r9), SW_REG(r10), SW_REG(r11), - SW_REG(r12), SW_REG(r13), SW_REG(r14), SW_REG(r15), + PT_REG(r8), PT_REG(r9), PT_REG(r10), PT_REG(r11), + PT_REG(r12), PT_REG(r13), PT_REG(r14), PT_REG(r15), PT_REG(r16), PT_REG(r17), PT_REG(r18), PT_REG(r19), PT_REG(r20), PT_REG(r21), PT_REG(r22), PT_REG(r23), PT_REG(r24), PT_REG(r25), PT_REG(r26), PT_REG(r27), -- Gitee From 40f13ed00ba08ca82c764d04f78fdf08d7583263 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Sun, 24 Apr 2022 12:01:24 +0800 Subject: [PATCH 24/71] sw64: remove switch_stack from signal handling Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- The new pt_regs struct holds r9 ~ r15, and it's sufficient to setup and restore sigcontext. Take care that fpregs state of current task should be saved and restored explicitly after switch_stack removed. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/entry.S | 8 ++------ arch/sw_64/kernel/signal.c | 38 ++++++++++++++++++-------------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/arch/sw_64/kernel/entry.S b/arch/sw_64/kernel/entry.S index f843acd88249..730346754ecc 100644 --- a/arch/sw_64/kernel/entry.S +++ b/arch/sw_64/kernel/entry.S @@ -663,12 +663,10 @@ sys_sigreturn: .prologue 0 ldi $9, ret_from_straced cmpult $26, $9, $9 - ldi $sp, -SWITCH_STACK_SIZE($sp) call $26, do_sigreturn bne $9, 1f call $26, syscall_trace_leave -1: br $1, undo_switch_stack - br ret_from_sys_call +1: br ret_from_sys_call .end sys_sigreturn .align 4 @@ -678,12 +676,10 @@ sys_rt_sigreturn: .prologue 0 ldi $9, ret_from_straced cmpult $26, $9, $9 - ldi $sp, -SWITCH_STACK_SIZE($sp) call $26, do_rt_sigreturn bne $9, 1f call $26, syscall_trace_leave -1: br $1, undo_switch_stack - br ret_from_sys_call +1: br ret_from_sys_call .end sys_rt_sigreturn .align 4 diff --git a/arch/sw_64/kernel/signal.c b/arch/sw_64/kernel/signal.c index dd0d8ff42420..887326812624 100644 --- a/arch/sw_64/kernel/signal.c +++ b/arch/sw_64/kernel/signal.c @@ -14,6 +14,7 @@ #include #include +#include #include "proto.h" @@ -22,8 +23,6 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -asmlinkage void ret_from_sys_call(void); - SYSCALL_DEFINE2(odd_sigprocmask, int, how, unsigned long, newmask) { sigset_t oldmask; @@ -64,13 +63,10 @@ static long restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) { unsigned long usp; - struct switch_stack *sw = (struct switch_stack *)regs - 1; long err = __get_user(regs->pc, &sc->sc_pc); current->restart_block.fn = do_no_restart_syscall; - sw->r26 = (unsigned long) ret_from_sys_call; - err |= __get_user(regs->r0, sc->sc_regs+0); err |= __get_user(regs->r1, sc->sc_regs+1); err |= __get_user(regs->r2, sc->sc_regs+2); @@ -80,13 +76,13 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) err |= __get_user(regs->r6, sc->sc_regs+6); err |= __get_user(regs->r7, sc->sc_regs+7); err |= __get_user(regs->r8, sc->sc_regs+8); - err |= __get_user(sw->r9, sc->sc_regs+9); - err |= __get_user(sw->r10, sc->sc_regs+10); - err |= __get_user(sw->r11, sc->sc_regs+11); - err |= __get_user(sw->r12, sc->sc_regs+12); - err |= __get_user(sw->r13, sc->sc_regs+13); - err |= __get_user(sw->r14, sc->sc_regs+14); - err |= __get_user(sw->r15, sc->sc_regs+15); + err |= __get_user(regs->r9, sc->sc_regs+9); + err |= __get_user(regs->r10, sc->sc_regs+10); + err |= __get_user(regs->r11, sc->sc_regs+11); + err |= __get_user(regs->r12, sc->sc_regs+12); + err |= __get_user(regs->r13, sc->sc_regs+13); + err |= __get_user(regs->r14, sc->sc_regs+14); + err |= __get_user(regs->r15, sc->sc_regs+15); err |= __get_user(regs->r16, sc->sc_regs+16); err |= __get_user(regs->r17, sc->sc_regs+17); err |= __get_user(regs->r18, sc->sc_regs+18); @@ -107,6 +103,8 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) err |= __copy_from_user(¤t->thread.ctx_fp, &sc->sc_fpregs, sizeof(struct context_fpregs)); err |= __get_user(current->thread.fpcr, &sc->sc_fpcr); + if (likely(!err)) + __fpstate_restore(current); return err; } @@ -191,7 +189,6 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, unsigned long sp) { - struct switch_stack *sw = (struct switch_stack *)regs - 1; long err = 0; err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack); @@ -208,13 +205,13 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, err |= __put_user(regs->r6, sc->sc_regs+6); err |= __put_user(regs->r7, sc->sc_regs+7); err |= __put_user(regs->r8, sc->sc_regs+8); - err |= __put_user(sw->r9, sc->sc_regs+9); - err |= __put_user(sw->r10, sc->sc_regs+10); - err |= __put_user(sw->r11, sc->sc_regs+11); - err |= __put_user(sw->r12, sc->sc_regs+12); - err |= __put_user(sw->r13, sc->sc_regs+13); - err |= __put_user(sw->r14, sc->sc_regs+14); - err |= __put_user(sw->r15, sc->sc_regs+15); + err |= __put_user(regs->r9, sc->sc_regs+9); + err |= __put_user(regs->r10, sc->sc_regs+10); + err |= __put_user(regs->r11, sc->sc_regs+11); + err |= __put_user(regs->r12, sc->sc_regs+12); + err |= __put_user(regs->r13, sc->sc_regs+13); + err |= __put_user(regs->r14, sc->sc_regs+14); + err |= __put_user(regs->r15, sc->sc_regs+15); err |= __put_user(regs->r16, sc->sc_regs+16); err |= __put_user(regs->r17, sc->sc_regs+17); err |= __put_user(regs->r18, sc->sc_regs+18); @@ -232,6 +229,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, err |= __put_user(sp, sc->sc_regs+30); err |= __put_user(0, sc->sc_regs+31); /* simd-fp */ + __fpstate_save(current); err |= __copy_to_user(&sc->sc_fpregs, ¤t->thread.ctx_fp, sizeof(struct context_fpregs)); err |= __put_user(current->thread.fpcr, &sc->sc_fpcr); -- Gitee From ba8c73ce31bd4d5375b0d005b1f89d46c73477dc Mon Sep 17 00:00:00 2001 From: He Sheng Date: Sun, 24 Apr 2022 16:51:34 +0800 Subject: [PATCH 25/71] sw64: dump callee-saved registers from pt_regs Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/process.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index 9a6812851b15..4e7a1418af30 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -199,9 +199,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, void dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti) { - /* switch stack follows right below pt_regs: */ - struct switch_stack *sw = ((struct switch_stack *) pt) - 1; - dest[0] = pt->r0; dest[1] = pt->r1; dest[2] = pt->r2; @@ -211,13 +208,13 @@ dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti) dest[6] = pt->r6; dest[7] = pt->r7; dest[8] = pt->r8; - dest[9] = sw->r9; - dest[10] = sw->r10; - dest[11] = sw->r11; - dest[12] = sw->r12; - dest[13] = sw->r13; - dest[14] = sw->r14; - dest[15] = sw->r15; + dest[9] = pt->r9; + dest[10] = pt->r10; + dest[11] = pt->r11; + dest[12] = pt->r12; + dest[13] = pt->r13; + dest[14] = pt->r14; + dest[15] = pt->r15; dest[16] = pt->r16; dest[17] = pt->r17; dest[18] = pt->r18; -- Gitee From c4c31c88e37cf8ad3a6797dba141c0ed162b5e93 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Sun, 24 Apr 2022 16:51:45 +0800 Subject: [PATCH 26/71] sw64: get blocked thread's frame pointer from thread_struct Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- The thread_struct holds all provided the thread blocked through a call to schedule(). $15 is the frame pointer in schedule() and it is saved at thread_struct.s[6]. With frame pointer, it can return saved PC of a blocked thread which assumes that the saved return address is the first long in the frame. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/process.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index 4e7a1418af30..1f093c5a5235 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -257,13 +257,6 @@ dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task) EXPORT_SYMBOL(dump_elf_task_fp); /* - * Return saved PC of a blocked thread. This assumes the frame - * pointer is the 6th saved long on the kernel stack and that the - * saved return address is the first long in the frame. This all - * holds provided the thread blocked through a call to schedule() ($15 - * is the frame pointer in schedule() and $15 is saved at offset 48 by - * entry.S:do_switch_stack). - * * Under heavy swap load I've seen this lose in an ugly way. So do * some extra sanity checking on the ranges we expect these pointers * to be in so that we can fail gracefully. This is just for ps after @@ -273,14 +266,14 @@ EXPORT_SYMBOL(dump_elf_task_fp); unsigned long thread_saved_pc(struct task_struct *t) { - unsigned long base = (unsigned long)task_stack_page(t); - unsigned long fp, sp = task_thread_info(t)->pcb.ksp; + unsigned long top, fp, sp; - if (sp > base && sp+6*8 < base + 16*1024) { - fp = ((unsigned long *)sp)[6]; - if (fp > sp && fp < base + 16*1024) - return *(unsigned long *)fp; - } + top = (unsigned long)task_stack_page(t) + 2 * PAGE_SIZE; + sp = task_thread_info(t)->pcb.ksp; + fp = t->thread.s[6]; + + if (fp > sp && fp < top) + return *(unsigned long *)fp; return 0; } @@ -289,7 +282,7 @@ unsigned long get_wchan(struct task_struct *p) { unsigned long schedule_frame; - unsigned long pc, base, sp; + unsigned long pc, top, sp; if (!p || p == current || p->state == TASK_RUNNING) return 0; @@ -305,10 +298,10 @@ get_wchan(struct task_struct *p) pc = thread_saved_pc(p); if (in_sched_functions(pc)) { - base = (unsigned long)task_stack_page(p); + top = (unsigned long)task_stack_page(p) + 2 * PAGE_SIZE; sp = task_thread_info(p)->pcb.ksp; - schedule_frame = ((unsigned long *)sp)[6]; - if (schedule_frame > sp && schedule_frame < base + 16*1024) + schedule_frame = p->thread.s[6]; + if (schedule_frame > sp && schedule_frame < top) return ((unsigned long *)schedule_frame)[12]; } return pc; -- Gitee From 72ed1e6e2775b868bb84d55f3c13ff8cd204d1d8 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Mon, 25 Apr 2022 12:57:28 +0800 Subject: [PATCH 27/71] sw64: remove switch_stack and allregs from entUna Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- It's simple to maintain unified register layout for user-mode and kernel-mode unaligned accesses. With the new struct pt_regs, we are able to make the exception handler cleaner. After that, the unused struct allregs can be cleaned up. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/asm-offsets.c | 41 ------------ arch/sw_64/kernel/entry.S | 109 +++++--------------------------- arch/sw_64/kernel/traps.c | 76 +++++----------------- 3 files changed, 33 insertions(+), 193 deletions(-) diff --git a/arch/sw_64/kernel/asm-offsets.c b/arch/sw_64/kernel/asm-offsets.c index 349bc5c4e2f1..0e8a814f47ce 100644 --- a/arch/sw_64/kernel/asm-offsets.c +++ b/arch/sw_64/kernel/asm-offsets.c @@ -111,47 +111,6 @@ void foo(void) DEFINE(SWITCH_STACK_RA, offsetof(struct switch_stack, r26)); BLANK(); - DEFINE(ALLREGS_SIZE, sizeof(struct allregs)); - DEFINE(ALLREGS_R0, offsetof(struct allregs, regs[0])); - DEFINE(ALLREGS_R1, offsetof(struct allregs, regs[1])); - DEFINE(ALLREGS_R2, offsetof(struct allregs, regs[2])); - DEFINE(ALLREGS_R3, offsetof(struct allregs, regs[3])); - DEFINE(ALLREGS_R4, offsetof(struct allregs, regs[4])); - DEFINE(ALLREGS_R5, offsetof(struct allregs, regs[5])); - DEFINE(ALLREGS_R6, offsetof(struct allregs, regs[6])); - DEFINE(ALLREGS_R7, offsetof(struct allregs, regs[7])); - DEFINE(ALLREGS_R8, offsetof(struct allregs, regs[8])); - DEFINE(ALLREGS_R9, offsetof(struct allregs, regs[9])); - DEFINE(ALLREGS_R10, offsetof(struct allregs, regs[10])); - DEFINE(ALLREGS_R11, offsetof(struct allregs, regs[11])); - DEFINE(ALLREGS_R12, offsetof(struct allregs, regs[12])); - DEFINE(ALLREGS_R13, offsetof(struct allregs, regs[13])); - DEFINE(ALLREGS_R14, offsetof(struct allregs, regs[14])); - DEFINE(ALLREGS_R15, offsetof(struct allregs, regs[15])); - DEFINE(ALLREGS_R16, offsetof(struct allregs, regs[16])); - DEFINE(ALLREGS_R17, offsetof(struct allregs, regs[17])); - DEFINE(ALLREGS_R18, offsetof(struct allregs, regs[18])); - DEFINE(ALLREGS_R19, offsetof(struct allregs, regs[19])); - DEFINE(ALLREGS_R20, offsetof(struct allregs, regs[20])); - DEFINE(ALLREGS_R21, offsetof(struct allregs, regs[21])); - DEFINE(ALLREGS_R22, offsetof(struct allregs, regs[22])); - DEFINE(ALLREGS_R23, offsetof(struct allregs, regs[23])); - DEFINE(ALLREGS_R24, offsetof(struct allregs, regs[24])); - DEFINE(ALLREGS_R25, offsetof(struct allregs, regs[25])); - DEFINE(ALLREGS_R26, offsetof(struct allregs, regs[26])); - DEFINE(ALLREGS_R27, offsetof(struct allregs, regs[27])); - DEFINE(ALLREGS_R28, offsetof(struct allregs, regs[28])); - DEFINE(ALLREGS_R29, offsetof(struct allregs, regs[29])); - DEFINE(ALLREGS_R30, offsetof(struct allregs, regs[30])); - DEFINE(ALLREGS_R31, offsetof(struct allregs, regs[31])); - DEFINE(ALLREGS_PS, offsetof(struct allregs, ps)); - DEFINE(ALLREGS_PC, offsetof(struct allregs, pc)); - DEFINE(ALLREGS_GP, offsetof(struct allregs, gp)); - DEFINE(ALLREGS_A0, offsetof(struct allregs, a0)); - DEFINE(ALLREGS_A1, offsetof(struct allregs, a1)); - DEFINE(ALLREGS_A2, offsetof(struct allregs, a2)); - BLANK(); - DEFINE(KVM_REGS_SIZE, sizeof(struct kvm_regs)); DEFINE(KVM_REGS_R0, offsetof(struct kvm_regs, r0)); DEFINE(KVM_REGS_R1, offsetof(struct kvm_regs, r1)); diff --git a/arch/sw_64/kernel/entry.S b/arch/sw_64/kernel/entry.S index 730346754ecc..f54b02c1b3a9 100644 --- a/arch/sw_64/kernel/entry.S +++ b/arch/sw_64/kernel/entry.S @@ -152,109 +152,32 @@ entIF: call $31, do_entIF .end entIF +/* + * Handle unalignment exception. + * We don't handle the "gp" register correctly, but if we fault on a + * gp-register unaligned load/store, something is _very_ wrong in the + * kernel anyway. + */ .align 4 .globl entUna .ent entUna entUna: - ldi $sp, -ALLREGS_PS($sp) - stl $0, ALLREGS_R0($sp) - ldl $0, ALLREGS_PS($sp) /* get PS */ - stl $1, ALLREGS_R1($sp) - stl $2, ALLREGS_R2($sp) - stl $3, ALLREGS_R3($sp) - and $0, 8, $0 /* user mode? */ - stl $4, ALLREGS_R4($sp) - bne $0, entUnaUser /* yup -> do user-level unaligned fault */ - stl $5, ALLREGS_R5($sp) - stl $6, ALLREGS_R6($sp) - stl $7, ALLREGS_R7($sp) - stl $8, ALLREGS_R8($sp) - stl $9, ALLREGS_R9($sp) - stl $10, ALLREGS_R10($sp) - stl $11, ALLREGS_R11($sp) - stl $12, ALLREGS_R12($sp) - stl $13, ALLREGS_R13($sp) - stl $14, ALLREGS_R14($sp) - stl $15, ALLREGS_R15($sp) - /* 16-18 HMCODE-saved */ - stl $19, ALLREGS_R19($sp) - stl $20, ALLREGS_R20($sp) - stl $21, ALLREGS_R21($sp) - stl $22, ALLREGS_R22($sp) - stl $23, ALLREGS_R23($sp) - stl $24, ALLREGS_R24($sp) - stl $25, ALLREGS_R25($sp) - stl $26, ALLREGS_R26($sp) - stl $27, ALLREGS_R27($sp) - stl $28, ALLREGS_R28($sp) - mov $sp, $19 - stl $gp, ALLREGS_R29($sp) + SAVE_ALL ldi $8, 0x3fff - stl $31, ALLREGS_R31($sp) bic $sp, $8, $8 + mov $sp, $19 + ldl $0, PT_REGS_PS($sp) + and $0, 8, $0 /* user mode ? */ + beq $0, 1f + ldi $26, ret_from_sys_call + call $31, do_entUnaUser /* return to ret_from_syscall */ +1: ldl $9, PT_REGS_GP($sp) call $26, do_entUna - ldl $0, ALLREGS_R0($sp) - ldl $1, ALLREGS_R1($sp) - ldl $2, ALLREGS_R2($sp) - ldl $3, ALLREGS_R3($sp) - ldl $4, ALLREGS_R4($sp) - ldl $5, ALLREGS_R5($sp) - ldl $6, ALLREGS_R6($sp) - ldl $7, ALLREGS_R7($sp) - ldl $8, ALLREGS_R8($sp) - ldl $9, ALLREGS_R9($sp) - ldl $10, ALLREGS_R10($sp) - ldl $11, ALLREGS_R11($sp) - ldl $12, ALLREGS_R12($sp) - ldl $13, ALLREGS_R13($sp) - ldl $14, ALLREGS_R14($sp) - ldl $15, ALLREGS_R15($sp) - /* 16-18 HMCODE-saved */ - ldl $19, ALLREGS_R19($sp) - ldl $20, ALLREGS_R20($sp) - ldl $21, ALLREGS_R21($sp) - ldl $22, ALLREGS_R22($sp) - ldl $23, ALLREGS_R23($sp) - ldl $24, ALLREGS_R24($sp) - ldl $25, ALLREGS_R25($sp) - ldl $26, ALLREGS_R26($sp) - ldl $27, ALLREGS_R27($sp) - ldl $28, ALLREGS_R28($sp) - ldl $gp, ALLREGS_R29($sp) - ldi $sp, ALLREGS_PS($sp) + stl $9, PT_REGS_GP($sp) + RESTORE_ALL sys_call HMC_rti .end entUna - .align 4 - .ent entUnaUser -entUnaUser: - ldl $0, ALLREGS_R0($sp) /* restore original $0 */ - ldi $sp, ALLREGS_PS($sp) /* pop entUna's stack frame */ - SAVE_ALL /* setup normal kernel stack */ - ldi $sp, -SWITCH_STACK_RA($sp) - stl $9, SWITCH_STACK_R9($sp) - stl $10, SWITCH_STACK_R10($sp) - stl $11, SWITCH_STACK_R11($sp) - stl $12, SWITCH_STACK_R12($sp) - stl $13, SWITCH_STACK_R13($sp) - stl $14, SWITCH_STACK_R14($sp) - stl $15, SWITCH_STACK_R15($sp) - ldi $8, 0x3fff - addl $sp, SWITCH_STACK_RA, $19 - bic $sp, $8, $8 - call $26, do_entUnaUser - ldl $9, SWITCH_STACK_R9($sp) - ldl $10, SWITCH_STACK_R10($sp) - ldl $11, SWITCH_STACK_R11($sp) - ldl $12, SWITCH_STACK_R12($sp) - ldl $13, SWITCH_STACK_R13($sp) - ldl $14, SWITCH_STACK_R14($sp) - ldl $15, SWITCH_STACK_R15($sp) - ldi $sp, SWITCH_STACK_RA($sp) - br ret_from_sys_call - .end entUnaUser - - /* * The system call entry point is special. Most importantly, it looks * like a function call to userspace as far as clobbered registers. We diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index b7c4e45df87b..6cd3ade905d1 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -321,41 +321,35 @@ do_entIF(unsigned long inst_type, struct pt_regs *regs) force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc, 0); } -/* - * entUna has a different register layout to be reasonably simple. It - * needs access to all the integer registers (the kernel doesn't use - * fp-regs), and it needs to have them in order for simpler access. - * - * Due to the non-standard register layout (and because we don't want - * to handle floating-point regs), user-mode unaligned accesses are - * handled separately by do_entUnaUser below. - * - * Oh, btw, we don't handle the "gp" register correctly, but if we fault - * on a gp-register unaligned load/store, something is _very_ wrong - * in the kernel anyway.. - */ -struct allregs { - unsigned long regs[32]; - unsigned long ps, pc, gp, a0, a1, a2; -}; - struct unaligned_stat { unsigned long count, va, pc; } unaligned[2]; /* Macro for exception fixup code to access integer registers. */ -#define una_reg(r) (_regs[(r) >= 16 && (r) <= 18 ? (r) + 19 : (r)]) +#define R(x) ((size_t) &((struct pt_regs *)0)->x) + +static int regoffsets[32] = { + R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8), + R(r9), R(r10), R(r11), R(r12), R(r13), R(r14), R(r15), + R(r16), R(r17), R(r18), + R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26), + R(r27), R(r28), R(gp), + 0, 0 +}; + +#undef R + +#define una_reg(r) (*(unsigned long *)((char *)regs + regoffsets[r])) asmlinkage void do_entUna(void *va, unsigned long opcode, unsigned long reg, - struct allregs *regs) + struct pt_regs *regs) { long error; unsigned long tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; unsigned long pc = regs->pc - 4; - unsigned long *_regs = regs->regs; const struct exception_table_entry *fixup; unaligned[0].count++; @@ -566,29 +560,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, printk("%s(%d): unhandled unaligned exception\n", current->comm, task_pid_nr(current)); - printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n", - pc, una_reg(26), regs->ps); - printk("r0 = %016lx r1 = %016lx r2 = %016lx\n", - una_reg(0), una_reg(1), una_reg(2)); - printk("r3 = %016lx r4 = %016lx r5 = %016lx\n", - una_reg(3), una_reg(4), una_reg(5)); - printk("r6 = %016lx r7 = %016lx r8 = %016lx\n", - una_reg(6), una_reg(7), una_reg(8)); - printk("r9 = %016lx r10= %016lx r11= %016lx\n", - una_reg(9), una_reg(10), una_reg(11)); - printk("r12= %016lx r13= %016lx r14= %016lx\n", - una_reg(12), una_reg(13), una_reg(14)); - printk("r15= %016lx\n", una_reg(15)); - printk("r16= %016lx r17= %016lx r18= %016lx\n", - una_reg(16), una_reg(17), una_reg(18)); - printk("r19= %016lx r20= %016lx r21= %016lx\n", - una_reg(19), una_reg(20), una_reg(21)); - printk("r22= %016lx r23= %016lx r24= %016lx\n", - una_reg(22), una_reg(23), una_reg(24)); - printk("r25= %016lx r27= %016lx r28= %016lx\n", - una_reg(25), una_reg(27), una_reg(28)); - printk("gp = %016lx sp = %p\n", regs->gp, regs+1); - + dik_show_regs(regs); dik_show_code((unsigned int *)pc); dik_show_trace((unsigned long *)(regs+1), KERN_DEFAULT); @@ -668,20 +640,6 @@ s_reg_to_mem(unsigned long s_reg) 1L << 0x2c | 1L << 0x2d | /* stw stl */ \ 1L << 0x0d | 1L << 0x0e) /* sth stb */ -#define R(x) ((size_t) &((struct pt_regs *)0)->x) - -static int unauser_reg_offsets[32] = { - R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8), - /* r9 ... r15 are stored in front of regs. */ - -56, -48, -40, -32, -24, -16, -8, - R(r16), R(r17), R(r18), - R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26), - R(r27), R(r28), R(gp), - 0, 0 -}; - -#undef R - asmlinkage void do_entUnaUser(void __user *va, unsigned long opcode, unsigned long reg, struct pt_regs *regs) @@ -734,7 +692,7 @@ do_entUnaUser(void __user *va, unsigned long opcode, /* it's an integer load/store */ if (reg < 30) { reg_addr = (unsigned long *) - ((char *)regs + unauser_reg_offsets[reg]); + ((char *)regs + regoffsets[reg]); } else if (reg == 30) { /* usp in HMCODE regs */ fake_reg = rdusp(); -- Gitee From b936d36d7ef16056e8b64dda3a0110a39a543bab Mon Sep 17 00:00:00 2001 From: He Sheng Date: Mon, 25 Apr 2022 15:09:11 +0800 Subject: [PATCH 28/71] sw64: remove switch_stack from __sw64_vcpu_run Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- Since r9~r15 have been added to struct pt_regs, it's okay to save and restore host callee-saved integer registers with pt_regs. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/entry.S | 57 +++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/arch/sw_64/kvm/entry.S b/arch/sw_64/kvm/entry.S index 76ebdda920cb..1e089da5378e 100644 --- a/arch/sw_64/kvm/entry.S +++ b/arch/sw_64/kvm/entry.S @@ -34,20 +34,15 @@ ENTRY(__sw64_vcpu_run) /* r18 = hcall args */ /* save host pt_regs to current kernel stack */ ldi sp, -PT_REGS_SIZE(sp) - - stl $8, PT_REGS_R8(sp) + stl $9, PT_REGS_R9(sp) + stl $10, PT_REGS_R10(sp) + stl $11, PT_REGS_R11(sp) + stl $12, PT_REGS_R12(sp) + stl $13, PT_REGS_R13(sp) + stl $14, PT_REGS_R14(sp) + stl $15, PT_REGS_R15(sp) stl $26, PT_REGS_R26(sp) - /* save host switch stack to current kernel stack */ - ldi sp, -SWITCH_STACK_SIZE(sp) - stl $9, SWITCH_STACK_R9(sp) - stl $10, SWITCH_STACK_R10(sp) - stl $11, SWITCH_STACK_R11(sp) - stl $12, SWITCH_STACK_R12(sp) - stl $13, SWITCH_STACK_R13(sp) - stl $14, SWITCH_STACK_R14(sp) - stl $15, SWITCH_STACK_R15(sp) - /* restore guest switch stack from guest kvm_regs struct */ ldl $0, KVM_REGS_R0($17) ldl $1, KVM_REGS_R1($17) @@ -203,23 +198,19 @@ $g_setfpec_over: stl $27, KVM_REGS_R27($17) stl $28, KVM_REGS_R28($17) - /* restore host switch stack from host sp */ - ldl $9, SWITCH_STACK_R9(sp) - ldl $10, SWITCH_STACK_R10(sp) - ldl $11, SWITCH_STACK_R11(sp) - ldl $12, SWITCH_STACK_R12(sp) - ldl $13, SWITCH_STACK_R13(sp) - ldl $14, SWITCH_STACK_R14(sp) - ldl $15, SWITCH_STACK_R15(sp) - - ldi sp, SWITCH_STACK_SIZE(sp) - /* restore host regs from host sp */ - ldl $8, PT_REGS_R8(sp) + ldl $9, PT_REGS_R9(sp) + ldl $10, PT_REGS_R10(sp) + ldl $11, PT_REGS_R11(sp) + ldl $12, PT_REGS_R12(sp) + ldl $13, PT_REGS_R13(sp) + ldl $14, PT_REGS_R14(sp) + ldl $15, PT_REGS_R15(sp) ldl $26, PT_REGS_R26(sp) - ldi sp, PT_REGS_SIZE(sp) + ldi $8, 0x3fff + bic sp, $8, $8 /* restore host fpregs */ ldl $1, TI_TASK($8) ldi $1, TASK_THREAD($1) @@ -261,25 +252,17 @@ $setfpec_over: /* Hmcode will setup in */ /* restore $16 $17 $18, do interrupt trick */ - ldi sp, -(HOST_INT_SIZE + PT_REGS_SIZE + SWITCH_STACK_SIZE)(sp) + ldi sp, -(HOST_INT_SIZE + PT_REGS_SIZE)(sp) ldl $16, HOST_INT_R16(sp) ldl $17, HOST_INT_R17(sp) ldl $18, HOST_INT_R18(sp) - ldi sp, (HOST_INT_SIZE + PT_REGS_SIZE + SWITCH_STACK_SIZE)(sp) + ldi sp, (HOST_INT_SIZE + PT_REGS_SIZE)(sp) - ldi $8, 0x3fff - bic sp, $8, $8 ldi $19, -PT_REGS_SIZE(sp) - - ldi $26, ret_from_do_entInt_noregs - call $31, do_entInt - - /* ret($0) indicate hcall number */ -ret_from_do_entInt_noregs: + call $26, do_entInt ldl $26, VCPU_RET_RA(sp) ldl $0, VCPU_RET_R0(sp) - - /* restore r16 - r19 */ $ret_to: + /* ret($0) indicate hcall number */ ldi sp, VCPU_RET_SIZE(sp) /* pop stack */ ret -- Gitee From b9b8f159d7d859a2a6d1fcfcfa49987af59f0c87 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Mon, 25 Apr 2022 13:39:10 +0800 Subject: [PATCH 29/71] sw64: remove other struct switch_stack things Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- Based on the previous series of patches, the do_switch_stack, undo_switch_stack and struct switch_stack become unused. Herein they are cleaned up. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/uapi/asm/ptrace.h | 15 ---- arch/sw_64/kernel/asm-offsets.c | 11 --- arch/sw_64/kernel/entry.S | 129 --------------------------- arch/sw_64/kernel/traps.c | 5 +- 4 files changed, 2 insertions(+), 158 deletions(-) diff --git a/arch/sw_64/include/uapi/asm/ptrace.h b/arch/sw_64/include/uapi/asm/ptrace.h index 4549e8d4bf57..deb7e4096c93 100644 --- a/arch/sw_64/include/uapi/asm/ptrace.h +++ b/arch/sw_64/include/uapi/asm/ptrace.h @@ -54,21 +54,6 @@ struct pt_regs { unsigned long r18; }; -/* - * This is the extended stack used by signal handlers and the context - * switcher: it's pushed after the normal "struct pt_regs". - */ -struct switch_stack { - unsigned long r9; - unsigned long r10; - unsigned long r11; - unsigned long r12; - unsigned long r13; - unsigned long r14; - unsigned long r15; - unsigned long r26; -}; - #define PTRACE_GETREGS 12 /* get general purpose registers */ #define PTRACE_SETREGS 13 /* set general purpose registers */ #define PTRACE_GETFPREGS 14 /* get floating-point registers */ diff --git a/arch/sw_64/kernel/asm-offsets.c b/arch/sw_64/kernel/asm-offsets.c index 0e8a814f47ce..5dc59346996f 100644 --- a/arch/sw_64/kernel/asm-offsets.c +++ b/arch/sw_64/kernel/asm-offsets.c @@ -100,17 +100,6 @@ void foo(void) DEFINE(PT_REGS_R18, offsetof(struct pt_regs, r18)); BLANK(); - DEFINE(SWITCH_STACK_SIZE, sizeof(struct switch_stack)); - DEFINE(SWITCH_STACK_R9, offsetof(struct switch_stack, r9)); - DEFINE(SWITCH_STACK_R10, offsetof(struct switch_stack, r10)); - DEFINE(SWITCH_STACK_R11, offsetof(struct switch_stack, r11)); - DEFINE(SWITCH_STACK_R12, offsetof(struct switch_stack, r12)); - DEFINE(SWITCH_STACK_R13, offsetof(struct switch_stack, r13)); - DEFINE(SWITCH_STACK_R14, offsetof(struct switch_stack, r14)); - DEFINE(SWITCH_STACK_R15, offsetof(struct switch_stack, r15)); - DEFINE(SWITCH_STACK_RA, offsetof(struct switch_stack, r26)); - BLANK(); - DEFINE(KVM_REGS_SIZE, sizeof(struct kvm_regs)); DEFINE(KVM_REGS_R0, offsetof(struct kvm_regs, r0)); DEFINE(KVM_REGS_R1, offsetof(struct kvm_regs, r1)); diff --git a/arch/sw_64/kernel/entry.S b/arch/sw_64/kernel/entry.S index f54b02c1b3a9..977c774ad799 100644 --- a/arch/sw_64/kernel/entry.S +++ b/arch/sw_64/kernel/entry.S @@ -380,135 +380,6 @@ $syscall_trace_failed: br ret_from_sys_call .end strace - .align 4 - .ent do_switch_stack -do_switch_stack: - ldi $sp, -SWITCH_STACK_SIZE($sp) - flds $f31, 0($sp) /* fillde hint */ - stl $9, SWITCH_STACK_R9($sp) - stl $10, SWITCH_STACK_R10($sp) - stl $11, SWITCH_STACK_R11($sp) - stl $12, SWITCH_STACK_R12($sp) - stl $13, SWITCH_STACK_R13($sp) - stl $14, SWITCH_STACK_R14($sp) - stl $15, SWITCH_STACK_R15($sp) - stl $26, SWITCH_STACK_RA($sp) - // SIMD-FP - ldl $9, TI_TASK($8) - ldi $9, TASK_THREAD($9) - ldi $10, THREAD_CTX_FP($9) - vstd $f0, CTX_FP_F0($10) - vstd $f1, CTX_FP_F1($10) - vstd $f2, CTX_FP_F2($10) - vstd $f3, CTX_FP_F3($10) - vstd $f4, CTX_FP_F4($10) - vstd $f5, CTX_FP_F5($10) - vstd $f6, CTX_FP_F6($10) - vstd $f7, CTX_FP_F7($10) - vstd $f8, CTX_FP_F8($10) - vstd $f9, CTX_FP_F9($10) - vstd $f10, CTX_FP_F10($10) - vstd $f11, CTX_FP_F11($10) - vstd $f12, CTX_FP_F12($10) - vstd $f13, CTX_FP_F13($10) - vstd $f14, CTX_FP_F14($10) - vstd $f15, CTX_FP_F15($10) - vstd $f16, CTX_FP_F16($10) - vstd $f17, CTX_FP_F17($10) - vstd $f18, CTX_FP_F18($10) - vstd $f19, CTX_FP_F19($10) - vstd $f20, CTX_FP_F20($10) - vstd $f21, CTX_FP_F21($10) - vstd $f22, CTX_FP_F22($10) - vstd $f23, CTX_FP_F23($10) - vstd $f24, CTX_FP_F24($10) - vstd $f25, CTX_FP_F25($10) - vstd $f26, CTX_FP_F26($10) - vstd $f27, CTX_FP_F27($10) - rfpcr $f0 - vstd $f28, CTX_FP_F28($10) - vstd $f29, CTX_FP_F29($10) - vstd $f30, CTX_FP_F30($10) - fstd $f0, THREAD_FPCR($9) - vldd $f0, CTX_FP_F0($10) - ldl $9, SWITCH_STACK_R9($sp) - ldl $10, SWITCH_STACK_R10($sp) - ret $31, ($1), 1 - .end do_switch_stack - - .align 4 - .ent undo_switch_stack -undo_switch_stack: -#ifdef CONFIG_SUBARCH_C3B - fillcs 0($sp) /* prefetch */ -#endif - ldl $11, SWITCH_STACK_R11($sp) - ldl $12, SWITCH_STACK_R12($sp) - ldl $13, SWITCH_STACK_R13($sp) - ldl $14, SWITCH_STACK_R14($sp) - ldl $15, SWITCH_STACK_R15($sp) - ldl $26, SWITCH_STACK_RA($sp) - // SIMD-FP - ldl $9, TI_TASK($8) - ldi $9, TASK_THREAD($9) - fldd $f0, THREAD_FPCR($9) - wfpcr $f0 - fimovd $f0, $10 - and $10, 0x3, $10 - beq $10, $setfpec_0 - subl $10, 0x1, $10 - beq $10, $setfpec_1 - subl $10, 0x1, $10 - beq $10, $setfpec_2 - setfpec3 - br $setfpec_over -$setfpec_0: - setfpec0 - br $setfpec_over -$setfpec_1: - setfpec1 - br $setfpec_over -$setfpec_2: - setfpec2 -$setfpec_over: - ldi $10, THREAD_CTX_FP($9) - vldd $f0, CTX_FP_F0($10) - vldd $f1, CTX_FP_F1($10) - vldd $f2, CTX_FP_F2($10) - vldd $f3, CTX_FP_F3($10) - vldd $f4, CTX_FP_F4($10) - vldd $f5, CTX_FP_F5($10) - vldd $f6, CTX_FP_F6($10) - vldd $f7, CTX_FP_F7($10) - vldd $f8, CTX_FP_F8($10) - vldd $f9, CTX_FP_F9($10) - vldd $f10, CTX_FP_F10($10) - vldd $f11, CTX_FP_F11($10) - vldd $f12, CTX_FP_F12($10) - vldd $f13, CTX_FP_F13($10) - vldd $f14, CTX_FP_F14($10) - vldd $f15, CTX_FP_F15($10) - vldd $f16, CTX_FP_F16($10) - vldd $f17, CTX_FP_F17($10) - vldd $f18, CTX_FP_F18($10) - vldd $f19, CTX_FP_F19($10) - vldd $f20, CTX_FP_F20($10) - vldd $f21, CTX_FP_F21($10) - vldd $f22, CTX_FP_F22($10) - vldd $f23, CTX_FP_F23($10) - vldd $f24, CTX_FP_F24($10) - vldd $f25, CTX_FP_F25($10) - vldd $f26, CTX_FP_F26($10) - vldd $f27, CTX_FP_F27($10) - vldd $f28, CTX_FP_F28($10) - vldd $f29, CTX_FP_F29($10) - vldd $f30, CTX_FP_F30($10) - ldl $9, SWITCH_STACK_R9($sp) - ldl $10, SWITCH_STACK_R10($sp) - ldi $sp, SWITCH_STACK_SIZE($sp) - ret $31, ($1), 1 - .end undo_switch_stack - /* * Integer register context switch * The callee-saved registers must be saved and restored. diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index 6cd3ade905d1..19fbf50b6ebc 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -300,9 +300,8 @@ do_entIF(unsigned long inst_type, struct pt_regs *regs) case 3: /* FEN fault */ /* * Irritating users can call HMC_clrfen to disable the - * FPU for the process. The kernel will then trap in - * do_switch_stack and undo_switch_stack when we try - * to save and restore the FP registers. + * FPU for the process. The kernel will then trap to + * save and restore the FP registers. * Given that GCC by default generates code that uses the * FP registers, HMC_clrfen is not useful except for DoS -- Gitee From ef588f6bce82bdeface18c414af7ffe0a97a1773 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Thu, 28 Apr 2022 09:32:24 +0800 Subject: [PATCH 30/71] sw64: access pt_regs with regoffsets where appropriate Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- The struct pt_regs of sw64 is a bit weird because r16~r18, r29 and r30 are saved at odd location by hmcode, which makes it complicated to reference them with regno. To improve maintainability, we map these regno(s) in an unified way. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/extable.h | 4 ++++ arch/sw_64/include/asm/ptrace.h | 3 +++ arch/sw_64/kernel/ptrace.c | 27 +++++++++++++-------------- arch/sw_64/kernel/traps.c | 31 +++++++------------------------ arch/sw_64/mm/fault.c | 6 +----- 5 files changed, 28 insertions(+), 43 deletions(-) diff --git a/arch/sw_64/include/asm/extable.h b/arch/sw_64/include/asm/extable.h index 12b50b68a0d2..ae753772a45a 100644 --- a/arch/sw_64/include/asm/extable.h +++ b/arch/sw_64/include/asm/extable.h @@ -52,4 +52,8 @@ struct exception_table_entry { (b)->fixup.unit = (tmp).fixup.unit; \ } while (0) +/* Macro for exception fixup code to access integer registers. */ +extern short regoffsets[]; +#define map_regs(r) (*(unsigned long *)((char *)regs + regoffsets[r])) + #endif diff --git a/arch/sw_64/include/asm/ptrace.h b/arch/sw_64/include/asm/ptrace.h index 74349a05b9e4..0f0de9a3f8ce 100644 --- a/arch/sw_64/include/asm/ptrace.h +++ b/arch/sw_64/include/asm/ptrace.h @@ -28,6 +28,9 @@ #define force_successful_syscall_return() (current_pt_regs()->r0 = 0) #define MAX_REG_OFFSET (offsetof(struct pt_regs, r18)) + +extern short regoffsets[]; + /** * regs_get_register() - get register value from its offset * @regs: pt_regs from which register value is gotten diff --git a/arch/sw_64/kernel/ptrace.c b/arch/sw_64/kernel/ptrace.c index 097590b22a5a..ce41d89a54cb 100644 --- a/arch/sw_64/kernel/ptrace.c +++ b/arch/sw_64/kernel/ptrace.c @@ -9,6 +9,7 @@ #include #include +#include #include "proto.h" @@ -52,23 +53,21 @@ enum { REG_GP = 29 }; -#define PT_REG(reg) \ - (PAGE_SIZE * 2 - sizeof(struct pt_regs) + offsetof(struct pt_regs, reg)) - #define FP_REG(fp_regno, vector_regno) \ (fp_regno * 32 + vector_regno * 8) -static int regoff[] = { - PT_REG(r0), PT_REG(r1), PT_REG(r2), PT_REG(r3), - PT_REG(r4), PT_REG(r5), PT_REG(r6), PT_REG(r7), - PT_REG(r8), PT_REG(r9), PT_REG(r10), PT_REG(r11), - PT_REG(r12), PT_REG(r13), PT_REG(r14), PT_REG(r15), - PT_REG(r16), PT_REG(r17), PT_REG(r18), PT_REG(r19), - PT_REG(r20), PT_REG(r21), PT_REG(r22), PT_REG(r23), - PT_REG(r24), PT_REG(r25), PT_REG(r26), PT_REG(r27), - PT_REG(r28), PT_REG(gp), -1, -1 +#define R(x) ((size_t) &((struct pt_regs *)0)->x) + +short regoffsets[32] = { + R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8), + R(r9), R(r10), R(r11), R(r12), R(r13), R(r14), R(r15), + R(r16), R(r17), R(r18), + R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26), + R(r27), R(r28), R(gp), 0, 0 }; +#undef R + #define PCB_OFF(var) offsetof(struct pcb_struct, var) static int pcboff[] = { @@ -104,7 +103,7 @@ get_reg_addr(struct task_struct *task, unsigned long regno) addr = (void *)task_thread_info(task) + pcboff[regno]; break; case REG_BASE ... REG_END: - addr = (void *)task_thread_info(task) + regoff[regno]; + addr = (void *)task_pt_regs(task) + regoffsets[regno]; break; case FPREG_BASE ... FPREG_END: fp_regno = regno - FPREG_BASE; @@ -128,7 +127,7 @@ get_reg_addr(struct task_struct *task, unsigned long regno) addr = (void *)&task->thread.fpcr; break; case PC: - addr = (void *)task_thread_info(task) + PT_REG(pc); + addr = (void *)task_pt_regs(task) + PT_REGS_PC; break; default: addr = &zero; diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index 19fbf50b6ebc..a61c851967a9 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -325,23 +325,6 @@ struct unaligned_stat { } unaligned[2]; -/* Macro for exception fixup code to access integer registers. */ -#define R(x) ((size_t) &((struct pt_regs *)0)->x) - -static int regoffsets[32] = { - R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8), - R(r9), R(r10), R(r11), R(r12), R(r13), R(r14), R(r15), - R(r16), R(r17), R(r18), - R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26), - R(r27), R(r28), R(gp), - 0, 0 -}; - -#undef R - -#define una_reg(r) (*(unsigned long *)((char *)regs + regoffsets[r])) - - asmlinkage void do_entUna(void *va, unsigned long opcode, unsigned long reg, struct pt_regs *regs) @@ -380,7 +363,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, if (error) goto got_exception; - una_reg(reg) = tmp1 | tmp2; + map_regs(reg) = tmp1 | tmp2; return; case 0x22: @@ -401,7 +384,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, if (error) goto got_exception; - una_reg(reg) = (int)(tmp1 | tmp2); + map_regs(reg) = (int)(tmp1 | tmp2); return; case 0x23: /* ldl */ @@ -422,7 +405,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, if (error) goto got_exception; - una_reg(reg) = tmp1 | tmp2; + map_regs(reg) = tmp1 | tmp2; return; case 0x29: /* sth */ @@ -440,7 +423,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, ".previous" : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) - : "r"(va), "r"(una_reg(reg)), "0"(0)); + : "r"(va), "r"(map_regs(reg)), "0"(0)); if (error) goto got_exception; @@ -472,7 +455,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, ".previous" : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) - : "r"(va), "r"(una_reg(reg)), "0"(0)); + : "r"(va), "r"(map_regs(reg)), "0"(0)); if (error) goto got_exception; @@ -524,7 +507,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, ".previous" : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4), "=&r"(tmp5), "=&r"(tmp6), "=&r"(tmp7), "=&r"(tmp8) - : "r"(va), "r"(una_reg(reg)), "0"(0)); + : "r"(va), "r"(map_regs(reg)), "0"(0)); if (error) goto got_exception; @@ -543,7 +526,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, if (fixup != 0) { unsigned long newpc; - newpc = fixup_exception(una_reg, fixup, pc); + newpc = fixup_exception(map_regs, fixup, pc); printk("Forwarding unaligned exception at %lx (%lx)\n", pc, newpc); diff --git a/arch/sw_64/mm/fault.c b/arch/sw_64/mm/fault.c index 9562bc3ba37f..9b0ad9eb5a3a 100644 --- a/arch/sw_64/mm/fault.c +++ b/arch/sw_64/mm/fault.c @@ -107,10 +107,6 @@ __load_new_mm_context(struct mm_struct *next_mm) * modify them. */ -/* Macro for exception fixup code to access integer registers. */ -#define dpf_reg(r) \ - (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 : \ - (r) <= 18 ? (r)+10 : (r)-10]) unsigned long show_va_to_pa(struct mm_struct *mm, unsigned long addr) { pgd_t *pgd = NULL; @@ -294,7 +290,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, if (fixup != 0) { unsigned long newpc; - newpc = fixup_exception(dpf_reg, fixup, regs->pc); + newpc = fixup_exception(map_regs, fixup, regs->pc); regs->pc = newpc; return; } -- Gitee From ca223ff216cdab7bb985b24221f92e1495ce4bc7 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Sat, 14 May 2022 11:07:13 +0800 Subject: [PATCH 31/71] sw64: move struct pt_regs to kapi ptrace.h Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- This struct should be invisible to user space, and we will define new regs struct for user in uapi later. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/ptrace.h | 47 +++++++++++++++++++++++++ arch/sw_64/include/uapi/asm/ptrace.h | 52 ---------------------------- 2 files changed, 47 insertions(+), 52 deletions(-) diff --git a/arch/sw_64/include/asm/ptrace.h b/arch/sw_64/include/asm/ptrace.h index 0f0de9a3f8ce..85f7a47fdee3 100644 --- a/arch/sw_64/include/asm/ptrace.h +++ b/arch/sw_64/include/asm/ptrace.h @@ -9,6 +9,53 @@ #include #include +/* + * This struct defines the way the registers are stored on the + * kernel stack during a system call or other kernel entry + */ + +struct pt_regs { + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long r3; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; + /* r16 ~ r18 saved by hmcode */ + unsigned long r19; + unsigned long r20; + unsigned long r21; + unsigned long r22; + unsigned long r23; + unsigned long r24; + unsigned long r25; + unsigned long r26; + unsigned long r27; + unsigned long r28; + unsigned long hae; +/* JRP - These are the values provided to a0-a2 by HMcode */ + unsigned long trap_a0; + unsigned long trap_a1; + unsigned long trap_a2; +/* These are saved by HMcode: */ + unsigned long ps; + unsigned long pc; + unsigned long gp; + unsigned long r16; + unsigned long r17; + unsigned long r18; +}; + #define arch_has_single_step() (1) #define user_mode(regs) (((regs)->ps & 8) != 0) #define instruction_pointer(regs) ((regs)->pc) diff --git a/arch/sw_64/include/uapi/asm/ptrace.h b/arch/sw_64/include/uapi/asm/ptrace.h index deb7e4096c93..ac7ce6b6510b 100644 --- a/arch/sw_64/include/uapi/asm/ptrace.h +++ b/arch/sw_64/include/uapi/asm/ptrace.h @@ -2,58 +2,6 @@ #ifndef _UAPI_ASM_SW64_PTRACE_H #define _UAPI_ASM_SW64_PTRACE_H - -/* - * This struct defines the way the registers are stored on the - * kernel stack during a system call or other kernel entry - * - * NOTE! I want to minimize the overhead of system calls, so this - * struct has as little information as possible. I does not have - * floating point regs, because the kernel doesn't change those - */ - -struct pt_regs { - unsigned long r0; - unsigned long r1; - unsigned long r2; - unsigned long r3; - unsigned long r4; - unsigned long r5; - unsigned long r6; - unsigned long r7; - unsigned long r8; - unsigned long r9; - unsigned long r10; - unsigned long r11; - unsigned long r12; - unsigned long r13; - unsigned long r14; - unsigned long r15; - /* r16 ~ r18 saved by hmcode */ - unsigned long r19; - unsigned long r20; - unsigned long r21; - unsigned long r22; - unsigned long r23; - unsigned long r24; - unsigned long r25; - unsigned long r26; - unsigned long r27; - unsigned long r28; - unsigned long hae; -/* JRP - These are the values provided to a0-a2 by HMcode */ - unsigned long trap_a0; - unsigned long trap_a1; - unsigned long trap_a2; -/* These are saved by HMcode: */ - unsigned long ps; - unsigned long pc; - unsigned long gp; - unsigned long r16; - unsigned long r17; - unsigned long r18; -}; - #define PTRACE_GETREGS 12 /* get general purpose registers */ #define PTRACE_SETREGS 13 /* set general purpose registers */ #define PTRACE_GETFPREGS 14 /* get floating-point registers */ -- Gitee From 2ac1d37a4635c4fd4fb9a98889bbeb7bfe9aef87 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Mon, 16 May 2022 10:31:57 +0800 Subject: [PATCH 32/71] sw64: avoid copying thread_struct twice Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- The thread_struct has been copied in dup_task_struct() by generic arch_dup_task_struct(), and it's unnecessary to be copied again in copy_thread(). This patch adds arch-specific implementation of arch_dup_task_struct() to reduce data copying. It does not have to save fpu state for a kernel thread, so call fpstate_save() instead of __fpstate_save() here to save fpu state on demand. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/process.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index 1f093c5a5235..6b5f0f3a8345 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -144,6 +144,13 @@ release_thread(struct task_struct *dead_task) { } +int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) +{ + fpstate_save(src); + *dst = *src; + return 0; +} + /* * Copy architecture-specific thread state */ @@ -162,8 +169,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, childti->pcb.ksp = (unsigned long) childregs; childti->pcb.flags = 7; /* set FEN, clear everything else */ - __fpstate_save(current); - p->thread = current->thread; if (unlikely(p->flags & PF_KTHREAD)) { /* kernel thread */ -- Gitee From cb3b05c7af85291bc8fa870f542a6176ee6b126a Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Mon, 16 May 2022 16:34:52 +0800 Subject: [PATCH 33/71] sw64: simplify __phys_addr and __virt_addr_valid Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- In these methods, the local variable `y` is redundant and can be removed. Signed-off-by: He Chuyue Signed-off-by: Gu Zitao --- arch/sw_64/mm/physaddr.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/arch/sw_64/mm/physaddr.c b/arch/sw_64/mm/physaddr.c index fbb489ae4db5..26769f0bf7bf 100644 --- a/arch/sw_64/mm/physaddr.c +++ b/arch/sw_64/mm/physaddr.c @@ -5,34 +5,30 @@ unsigned long __phys_addr(unsigned long x) { - unsigned long y = x; - - if (y >= __START_KERNEL_map) { - y -= __START_KERNEL_map; - VIRTUAL_BUG_ON(y >= KERNEL_IMAGE_SIZE); + if (x >= __START_KERNEL_map) { + x -= __START_KERNEL_map; + VIRTUAL_BUG_ON(x >= KERNEL_IMAGE_SIZE); } else { - VIRTUAL_BUG_ON(y < PAGE_OFFSET); - y -= PAGE_OFFSET; - VIRTUAL_BUG_ON(!phys_addr_valid(y)); + VIRTUAL_BUG_ON(x < PAGE_OFFSET); + x -= PAGE_OFFSET; + VIRTUAL_BUG_ON(!phys_addr_valid(x)); } - return y; + return x; } EXPORT_SYMBOL(__phys_addr); bool __virt_addr_valid(unsigned long x) { - unsigned long y = x; - - if (y >= __START_KERNEL_map) { - y -= __START_KERNEL_map; - if (y >= KERNEL_IMAGE_SIZE) + if (x >= __START_KERNEL_map) { + x -= __START_KERNEL_map; + if (x >= KERNEL_IMAGE_SIZE) return false; } else { - if (y < PAGE_OFFSET) + if (x < PAGE_OFFSET) return false; - y -= PAGE_OFFSET; + x -= PAGE_OFFSET; } - return pfn_valid(y >> PAGE_SHIFT); + return pfn_valid(x >> PAGE_SHIFT); } EXPORT_SYMBOL(__virt_addr_valid); -- Gitee From 5c841330a078634752deca6aaf3fd749f092a0eb Mon Sep 17 00:00:00 2001 From: He Sheng Date: Tue, 17 May 2022 15:05:15 +0800 Subject: [PATCH 34/71] sw64: simplify pgtable helpers Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- This patch: - Remove unused macros. - Rename some variables and macros to make them shorter. - Add pfn_to_virt and virt_to_pfn to make code cleaner. - Map vaddr by __va(). - Redefine mk_pte with pfn_to_pte. - Fix some wrong usages, like pgd_offset Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/mmu_context.h | 8 +-- arch/sw_64/include/asm/mmzone.h | 23 ------- arch/sw_64/include/asm/page.h | 3 + arch/sw_64/include/asm/pgalloc.h | 2 +- arch/sw_64/include/asm/pgtable.h | 91 +++++++++------------------- arch/sw_64/mm/fault.c | 6 +- arch/sw_64/mm/init.c | 2 +- 7 files changed, 40 insertions(+), 95 deletions(-) diff --git a/arch/sw_64/include/asm/mmu_context.h b/arch/sw_64/include/asm/mmu_context.h index e3d7ae7c873e..d6cd01d55712 100644 --- a/arch/sw_64/include/asm/mmu_context.h +++ b/arch/sw_64/include/asm/mmu_context.h @@ -131,7 +131,7 @@ switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm, * Always update the PCB PTBR. If next is kernel thread, it must * update PTBR. If next is user process, it's ok to update PTBR. */ - task_thread_info(next)->pcb.ptbr = (__pa(next_mm->pgd)) >> PAGE_SHIFT; + task_thread_info(next)->pcb.ptbr = virt_to_pfn(next_mm->pgd); load_asn_ptbr(task_thread_info(next)->pcb.asn, task_thread_info(next)->pcb.ptbr); } @@ -170,8 +170,7 @@ static inline int init_new_context(struct task_struct *tsk, for_each_possible_cpu(i) mm->context.asid[i] = 0; if (tsk != current) - task_thread_info(tsk)->pcb.ptbr - = (__pa(mm->pgd)) >> PAGE_SHIFT; + task_thread_info(tsk)->pcb.ptbr = virt_to_pfn(mm->pgd); return 0; } @@ -183,8 +182,7 @@ static inline void destroy_context(struct mm_struct *mm) static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { - task_thread_info(tsk)->pcb.ptbr - = (__pa(mm->pgd)) >> PAGE_SHIFT; + task_thread_info(tsk)->pcb.ptbr = virt_to_pfn(mm->pgd); } static inline int arch_dup_mmap(struct mm_struct *oldmm, diff --git a/arch/sw_64/include/asm/mmzone.h b/arch/sw_64/include/asm/mmzone.h index 924e33f6d326..4219015c5cfc 100644 --- a/arch/sw_64/include/asm/mmzone.h +++ b/arch/sw_64/include/asm/mmzone.h @@ -18,29 +18,6 @@ extern pg_data_t *node_data[]; extern int pa_to_nid(unsigned long pa); extern int pfn_valid(unsigned long pfn); -#define mk_pte(page, pgprot) \ -({ \ - pte_t pte; \ - unsigned long pfn; \ - \ - pfn = page_to_pfn(page) << _PTE_FLAGS_BITS; \ - pte_val(pte) = pfn | pgprot_val(pgprot); \ - \ - pte; \ -}) - -#define pte_page(x) \ -({ \ - unsigned long kvirt; \ - struct page *__xx; \ - \ - kvirt = (unsigned long)__va(pte_val(x) >> (_PTE_FLAGS_BITS-PAGE_SHIFT));\ - __xx = virt_to_page(kvirt); \ - \ - __xx; \ -}) - -#define page_to_pa(page) (page_to_pfn(page) << PAGE_SHIFT) #define pfn_to_nid(pfn) pa_to_nid(((u64)(pfn) << PAGE_SHIFT)) #endif /* CONFIG_DISCONTIGMEM */ diff --git a/arch/sw_64/include/asm/page.h b/arch/sw_64/include/asm/page.h index 363785c9f082..dc6a89c37231 100644 --- a/arch/sw_64/include/asm/page.h +++ b/arch/sw_64/include/asm/page.h @@ -50,6 +50,9 @@ extern unsigned long __phys_addr(unsigned long); #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) +#define virt_to_pfn(vaddr) (PHYS_PFN(__pa(vaddr))) +#define pfn_to_virt(pfn) (__va(PFN_PHYS(pfn))) + #ifdef CONFIG_FLATMEM #define pfn_valid(pfn) ((pfn) < max_mapnr) #endif /* CONFIG_FLATMEM */ diff --git a/arch/sw_64/include/asm/pgalloc.h b/arch/sw_64/include/asm/pgalloc.h index 3cfdcbef7ef8..9572b4709ff4 100644 --- a/arch/sw_64/include/asm/pgalloc.h +++ b/arch/sw_64/include/asm/pgalloc.h @@ -15,7 +15,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t pte) { - pmd_set(pmd, (pte_t *)(page_to_pa(pte) + PAGE_OFFSET)); + pmd_set(pmd, (pte_t *)__va(page_to_pa(pte))); } #define pmd_pgtable(pmd) pmd_page(pmd) diff --git a/arch/sw_64/include/asm/pgtable.h b/arch/sw_64/include/asm/pgtable.h index 590f15508e28..67637b4ddf1d 100644 --- a/arch/sw_64/include/asm/pgtable.h +++ b/arch/sw_64/include/asm/pgtable.h @@ -119,9 +119,8 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, #define __ACCESS_BITS (_PAGE_ACCESSED | _PAGE_KRE | _PAGE_URE) -#define _PFN_MASK 0xFFFFFFFFF0000000UL -#define _PFN_BITS 36 -#define _PTE_FLAGS_BITS (64 - _PFN_BITS) +#define _PFN_SHIFT 28 +#define _PFN_MASK ((-1UL) << _PFN_SHIFT) #define _PAGE_TABLE (_PAGE_VALID | __DIRTY_BITS | __ACCESS_BITS) #define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS | _PAGE_SPECIAL) @@ -181,53 +180,19 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, extern struct page *empty_zero_page; #define ZERO_PAGE(vaddr) (empty_zero_page) -/* number of bits that fit into a memory pointer */ -#define BITS_PER_PTR (8 * sizeof(unsigned long)) - -/* to align the pointer to a pointer address */ -#define PTR_MASK (~(sizeof(void *) - 1)) - -/* sizeof(void*)==1<> (PAGE_SHIFT - SIZEOF_PTR_LOG2) & PTR_MASK & ~PAGE_MASK) - -#define PHYS_TWIDDLE(pfn) (pfn) - -/* - * Conversion functions: convert a page and protection to a page entry, - * and a page entry and page directory to the page they refer to. - */ -#define page_to_pa(page) (page_to_pfn(page) << PAGE_SHIFT) - -#define pmd_pfn(pmd) (pmd_val(pmd) >> _PTE_FLAGS_BITS) -#define pte_pfn(pte) (pte_val(pte) >> _PTE_FLAGS_BITS) -#ifndef CONFIG_DISCONTIGMEM -#define pte_page(pte) pfn_to_page(pte_pfn(pte)) -#define mk_pte(page, pgprot) \ -({ \ - pte_t pte; \ - \ - pte_val(pte) = (page_to_pfn(page) << _PTE_FLAGS_BITS) | pgprot_val(pgprot); \ - pte; \ -}) -#endif - -static inline pte_t pfn_pte(unsigned long physpfn, pgprot_t pgprot) +static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) { pte_t pte; - pte_val(pte) = (PHYS_TWIDDLE(physpfn) << _PTE_FLAGS_BITS) | pgprot_val(pgprot); + pte_val(pte) = (pfn << _PFN_SHIFT) | pgprot_val(prot); return pte; } -static inline pmd_t pfn_pmd(unsigned long physpfn, pgprot_t pgprot) +static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot) { pmd_t pmd; - pmd_val(pmd) = (PHYS_TWIDDLE(physpfn) << _PTE_FLAGS_BITS) | pgprot_val(pgprot); + pmd_val(pmd) = (pfn << _PFN_SHIFT) | pgprot_val(prot); return pmd; } @@ -245,37 +210,48 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) static inline void pmd_set(pmd_t *pmdp, pte_t *ptep) { - pmd_val(*pmdp) = _PAGE_TABLE | (__pa(ptep) << (_PTE_FLAGS_BITS - PAGE_SHIFT)); + pmd_val(*pmdp) = _PAGE_TABLE | (virt_to_pfn(ptep) << _PFN_SHIFT); } static inline void pud_set(pud_t *pudp, pmd_t *pmdp) { - pud_val(*pudp) = _PAGE_TABLE | (__pa(pmdp) << (_PTE_FLAGS_BITS - PAGE_SHIFT)); + pud_val(*pudp) = _PAGE_TABLE | (virt_to_pfn(pmdp) << _PFN_SHIFT); } static inline void p4d_set(p4d_t *p4dp, pud_t *pudp) { - p4d_val(*p4dp) = _PAGE_TABLE | (__pa(pudp) << (_PTE_FLAGS_BITS - PAGE_SHIFT)); + p4d_val(*p4dp) = _PAGE_TABLE | (virt_to_pfn(pudp) << _PFN_SHIFT); } -static inline unsigned long -pmd_page_vaddr(pmd_t pmd) +static inline unsigned long pmd_page_vaddr(pmd_t pmd) { - return ((pmd_val(pmd) & _PFN_MASK) >> (_PTE_FLAGS_BITS-PAGE_SHIFT)) + PAGE_OFFSET; + return (unsigned long)pfn_to_virt(pmd_val(pmd) >> _PFN_SHIFT); } -#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> _PTE_FLAGS_BITS)) -#define pud_page(pud) (pfn_to_page(pud_val(pud) >> _PTE_FLAGS_BITS)) -#define p4d_page(p4d) (pfn_to_page(p4d_val(p4d) >> _PTE_FLAGS_BITS)) +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ +#define page_to_pa(page) (page_to_pfn(page) << PAGE_SHIFT) + +#define pmd_pfn(pmd) (pmd_val(pmd) >> _PFN_SHIFT) +#define pte_pfn(pte) (pte_val(pte) >> _PFN_SHIFT) + +#define pte_page(pte) pfn_to_page(pte_pfn(pte)) +#define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot) + +#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> _PFN_SHIFT)) +#define pud_page(pud) (pfn_to_page(pud_val(pud) >> _PFN_SHIFT)) +#define p4d_page(p4d) (pfn_to_page(p4d_val(p4d) >> _PFN_SHIFT)) static inline pud_t *p4d_pgtable(p4d_t p4d) { - return (pud_t *)(PAGE_OFFSET + ((p4d_val(p4d) & _PFN_MASK) >> (_PTE_FLAGS_BITS-PAGE_SHIFT))); + return (pud_t *)pfn_to_virt(p4d_val(p4d) >> _PFN_SHIFT); } static inline pmd_t *pud_pgtable(pud_t pud) { - return (pmd_t *)(PAGE_OFFSET + ((pud_val(pud) & _PFN_MASK) >> (_PTE_FLAGS_BITS-PAGE_SHIFT))); + return (pmd_t *)pfn_to_virt(pud_val(pud) >> _PFN_SHIFT); } static inline int pte_none(pte_t pte) @@ -566,7 +542,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, set_bit(_PAGE_BIT_FOW, (unsigned long *)pmdp); } -#define mk_pmd(page, pgprot) pfn_pmd(page_to_pfn(page), (pgprot)) +#define mk_pmd(page, prot) pfn_pmd(page_to_pfn(page), (prot)) #define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS extern int pmdp_set_access_flags(struct vm_area_struct *vma, @@ -586,15 +562,6 @@ extern int pmdp_clear_flush_young(struct vm_area_struct *vma, extern void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long addr, pmd_t *pmdp); -#define PAGE_DIR_OFFSET(tsk, address) pgd_offset((tsk), (address)) - -/* to find an entry in a kernel page-table-directory */ -#define pgd_offset_k(address) pgd_offset(&init_mm, (address)) - -/* to find an entry in a page-table-directory. */ -#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) -#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) - extern pgd_t swapper_pg_dir[1024]; /* diff --git a/arch/sw_64/mm/fault.c b/arch/sw_64/mm/fault.c index 9b0ad9eb5a3a..d596fc50772d 100644 --- a/arch/sw_64/mm/fault.c +++ b/arch/sw_64/mm/fault.c @@ -80,7 +80,7 @@ __load_new_mm_context(struct mm_struct *next_mm) pcb = ¤t_thread_info()->pcb; pcb->asn = mmc & HARDWARE_ASN_MASK; - pcb->ptbr = ((unsigned long) next_mm->pgd - PAGE_OFFSET) >> PAGE_SHIFT; + pcb->ptbr = virt_to_pfn(next_mm->pgd); __reload_thread(pcb); } @@ -122,7 +122,7 @@ unsigned long show_va_to_pa(struct mm_struct *mm, unsigned long addr) pr_debug("addr = %#lx, pgd = %#lx\n", addr, pgd_val(*pgd)); goto out; } - p4d = pgd_offset(pgd, addr); + p4d = p4d_offset(pgd, addr); if (p4d_none(*p4d)) { ret = 0; pr_debug("addr = %#lx, pgd = %#lx, p4d = %#lx\n", @@ -146,7 +146,7 @@ unsigned long show_va_to_pa(struct mm_struct *mm, unsigned long addr) } pte = pte_offset_map(pmd, addr); if (pte_present(*pte)) { - ret = ((unsigned long)__va(((pte_val(*pte) >> 32)) << PAGE_SHIFT)); + ret = (unsigned long)pfn_to_virt(pte_val(*pte) >> _PFN_SHIFT); pr_debug("addr = %#lx, pgd = %#lx, pud = %#lx, pmd = %#lx, pte = %#lx, ret = %#lx\n", addr, *(unsigned long *)pgd, *(unsigned long *)pud, *(unsigned long *)pmd, *(unsigned long *)pte, ret); diff --git a/arch/sw_64/mm/init.c b/arch/sw_64/mm/init.c index 3593e4b13319..cd3c0551b8f8 100644 --- a/arch/sw_64/mm/init.c +++ b/arch/sw_64/mm/init.c @@ -87,7 +87,7 @@ switch_to_system_map(void) * the last slot of the L1 page table. */ memset(swapper_pg_dir, 0, PAGE_SIZE); - newptbr = __pa(swapper_pg_dir) >> PAGE_SHIFT; + newptbr = virt_to_pfn(swapper_pg_dir); /* Also set up the real kernel PCB while we're at it. */ init_thread_info.pcb.ptbr = newptbr; -- Gitee From 9e08dc63c00d48adde62976841bcacf25409b88b Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Tue, 17 May 2022 09:43:30 +0800 Subject: [PATCH 35/71] sw64: check integrity for dtb passed by BIOS Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- If kernel image is so large that it corrupts dtb, system will break down early to give a message. Signed-off-by: He Chuyue Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index ca19445ac883..faae7cb3c5a1 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -565,8 +565,14 @@ static void __init setup_machine_fdt(void) /* Give a chance to select kernel builtin DTB firstly */ if (IS_ENABLED(CONFIG_SW64_BUILTIN_DTB)) dt_virt = (void *)__dtb_start; - else + else { dt_virt = (void *)sunway_boot_params->dtb_start; + if (dt_virt < (void *)__bss_stop) { + pr_emerg("BUG: DTB has been corrupted by kernel image!\n"); + while (true) + cpu_relax(); + } + } phys_addr = __phys_addr((unsigned long)dt_virt); if (!phys_addr_valid(phys_addr) || -- Gitee From 8d384996f080b31d8e7c0f3337952bf32921aa3a Mon Sep 17 00:00:00 2001 From: He Sheng Date: Tue, 17 May 2022 17:32:12 +0800 Subject: [PATCH 36/71] sw64: remove discontiguous memory support Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- Since sparse memory support works fine so far, discontiguous memory support can be removed to avoid confusion. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 9 -------- arch/sw_64/include/asm/mmzone.h | 7 ------- arch/sw_64/include/asm/pgtable.h | 7 ------- arch/sw_64/kernel/Makefile | 3 +-- arch/sw_64/kernel/core.c | 35 -------------------------------- arch/sw_64/mm/init.c | 12 ----------- 6 files changed, 1 insertion(+), 72 deletions(-) delete mode 100644 arch/sw_64/kernel/core.c diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 8c5e87cb9b84..2d7721acb529 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -649,15 +649,6 @@ config ARCH_SPARSEMEM_ENABLE depends on SMP select SPARSEMEM_VMEMMAP_ENABLE -config ARCH_DISCONTIGMEM_ENABLE - bool "Discontiguous Memory Support" - depends on SMP - help - Say Y to support efficient handling of discontiguous physical memory, - for architectures which are either NUMA (Non-Uniform Memory Access) - or have huge holes in the physical address space for other reasons. - See for more. - config NUMA bool "NUMA Support" depends on SMP && !FLATMEM diff --git a/arch/sw_64/include/asm/mmzone.h b/arch/sw_64/include/asm/mmzone.h index 4219015c5cfc..3849d26e3890 100644 --- a/arch/sw_64/include/asm/mmzone.h +++ b/arch/sw_64/include/asm/mmzone.h @@ -14,11 +14,4 @@ extern pg_data_t *node_data[]; #define NODE_DATA(nid) (node_data[(nid)]) #endif -#ifdef CONFIG_DISCONTIGMEM -extern int pa_to_nid(unsigned long pa); -extern int pfn_valid(unsigned long pfn); - -#define pfn_to_nid(pfn) pa_to_nid(((u64)(pfn) << PAGE_SHIFT)) -#endif /* CONFIG_DISCONTIGMEM */ - #endif /* _ASM_SW64_MMZONE_H */ diff --git a/arch/sw_64/include/asm/pgtable.h b/arch/sw_64/include/asm/pgtable.h index 67637b4ddf1d..76c782baf242 100644 --- a/arch/sw_64/include/asm/pgtable.h +++ b/arch/sw_64/include/asm/pgtable.h @@ -596,14 +596,7 @@ extern pgd_t swapper_pg_dir[1024]; #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -#if defined(CONFIG_FLATMEM) #define kern_addr_valid(addr) (1) -#elif defined(CONFIG_DISCONTIGMEM) -/* XXX: FIXME -- wli */ -#define kern_addr_valid(kaddr) (0) -#elif defined(CONFIG_SPARSEMEM) -#define kern_addr_valid(addr) (1) -#endif #define pte_ERROR(e) \ pr_err("%s: %d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e)) diff --git a/arch/sw_64/kernel/Makefile b/arch/sw_64/kernel/Makefile index 293b360626f7..c1e461e0ac56 100644 --- a/arch/sw_64/kernel/Makefile +++ b/arch/sw_64/kernel/Makefile @@ -15,7 +15,7 @@ endif obj-y := entry.o fpu.o traps.o process.o sys_sw64.o irq.o \ irq_sw64.o signal.o setup.o ptrace.o time.o \ - systbls.o dup_print.o tc.o \ + systbls.o dup_print.o tc.o timer.o \ insn.o early_init.o topology.o cacheinfo.o \ vdso.o vdso/ @@ -43,7 +43,6 @@ obj-y += kvm_cma.o endif # Core logic support -obj-$(CONFIG_SW64) += core.o timer.o obj-$(CONFIG_SW64_CPUFREQ) += platform.o clock.o obj-$(CONFIG_SW64_CPUAUTOPLUG) += cpuautoplug.o diff --git a/arch/sw_64/kernel/core.c b/arch/sw_64/kernel/core.c deleted file mode 100644 index e26b3a5faab2..000000000000 --- a/arch/sw_64/kernel/core.c +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include - -#ifdef CONFIG_DISCONTIGMEM -#ifdef CONFIG_NUMA -int pa_to_nid(unsigned long pa) -{ - int i = 0; - phys_addr_t pfn_base, pfn_size, pfn; - - pfn = pa >> PAGE_SHIFT; - for (i = 0; i < MAX_NUMNODES; i++) { - if (!NODE_DATA(i)) - continue; - - pfn_base = NODE_DATA(i)->node_start_pfn; - pfn_size = NODE_DATA(i)->node_spanned_pages; - - if (pfn >= pfn_base && pfn < pfn_base + pfn_size) - return i; - } - - pr_err("%s: pa %#lx does not belong to any node, return node 0\n", __func__, pa); - return 0; -} -EXPORT_SYMBOL(pa_to_nid); -#else /* !CONFIG_NUMA */ -int pa_to_nid(unsigned long pa) -{ - return 0; -} -EXPORT_SYMBOL(pa_to_nid); -#endif /* CONFIG_NUMA */ -#endif /* CONFIG_DISCONTIGMEM */ diff --git a/arch/sw_64/mm/init.c b/arch/sw_64/mm/init.c index cd3c0551b8f8..16d3da7beebe 100644 --- a/arch/sw_64/mm/init.c +++ b/arch/sw_64/mm/init.c @@ -244,18 +244,6 @@ void vmemmap_free(unsigned long start, unsigned long end, } #endif -#ifdef CONFIG_DISCONTIGMEM -int pfn_valid(unsigned long pfn) -{ - phys_addr_t addr = pfn << PAGE_SHIFT; - - if ((addr >> PAGE_SHIFT) != pfn) - return 0; - return memblock_is_map_memory(addr); -} -EXPORT_SYMBOL(pfn_valid); -#endif - #ifdef CONFIG_HAVE_MEMBLOCK #ifndef MIN_MEMBLOCK_ADDR #define MIN_MEMBLOCK_ADDR __pa(PAGE_OFFSET) -- Gitee From d351c1bdf7563b31109bf0a01feb015233a01f2d Mon Sep 17 00:00:00 2001 From: Zhu Donghong Date: Wed, 18 May 2022 15:23:55 +0800 Subject: [PATCH 37/71] irqchip: add sw64 chip3 builtin LPC interrupt controller driver Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5G7AK -------------------------------- This adds an irqchip driver for the secondary interrupt controllers based on sw64 chip3 cpu builtin LPC. Signed-off-by: Zhu Donghong Signed-off-by: Gu Zitao --- drivers/irqchip/Kconfig | 7 ++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-lpc.c | 137 +++++++++++++++++++++++++++++++++ drivers/mfd/lpc_sunway_chip3.c | 130 ------------------------------- 4 files changed, 145 insertions(+), 130 deletions(-) create mode 100644 drivers/irqchip/irq-lpc.c diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 375ba3b30b72..5bf6cf60999b 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -9,6 +9,13 @@ config SW64_INTC The INTC controls devices interrupts and connects them to each core's local interrupt controller. +config SW64_CHIP3_LPC + bool "SW64 Chip3 Buildin LPC Interrupt Controller" + depends on SW64_CHIP3 + help + This enables support for the LPC interrupt controller bultin in + on chip3 series. + config IRQCHIP def_bool y depends on OF_IRQ diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 4c78b0f64e6c..78eb12ab4d4c 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o obj-$(CONFIG_SW64_INTC) += irq-intc-v1.o +obj-$(CONFIG_SW64_CHIP3_LPC) += irq-lpc.o obj-$(CONFIG_ARM_GIC_PM) += irq-gic-pm.o obj-$(CONFIG_ARCH_REALVIEW) += irq-gic-realview.o obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o diff --git a/drivers/irqchip/irq-lpc.c b/drivers/irqchip/irq-lpc.c new file mode 100644 index 000000000000..1cbf87478242 --- /dev/null +++ b/drivers/irqchip/irq-lpc.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include + +#define LPC_NR_IRQS 16 +#define LPC_IRQ 0x4 +#define LPC_IRQ_MASK 0x8 + +struct lpc_intc_data { + struct irq_domain *domain; + struct irq_chip_generic *gc; +}; + +static void lpc_irq_mask_ack(struct irq_data *data) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); + struct irq_chip_type *ct = irq_data_get_chip_type(data); + unsigned int mask = data->mask; + + irq_gc_lock(gc); + *ct->mask_cache |= mask; + irq_reg_writel(gc, *ct->mask_cache, ct->regs.mask); + irq_reg_writel(gc, mask, ct->regs.ack); + irq_gc_unlock(gc); +} + +static void lpc_irq_handler(struct irq_desc *desc) +{ + struct lpc_intc_data *b = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + unsigned int irq; + u32 status; + + chained_irq_enter(chip, desc); + + status = irq_reg_readl(b->gc, LPC_IRQ); + + if (status == 0) { + raw_spin_lock(&desc->lock); + handle_bad_irq(desc); + raw_spin_unlock(&desc->lock); + goto out; + } + + while (status) { + irq = __ffs(status); + status &= ~BIT(irq); + generic_handle_irq(irq_find_mapping(b->domain, irq)); + } + +out: + chained_irq_exit(chip, desc); +} + +static int __init lpc_intc_of_init(struct device_node *np, + struct device_node *parent) +{ + unsigned int set = IRQ_NOPROBE | IRQ_LEVEL; + struct lpc_intc_data *data; + struct irq_chip_type *ct; + int parent_irq, ret; + void __iomem *base; + int hwirq = 0; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + base = of_iomap(np, 0); + if (!base) { + pr_err("failed to remap lpc intc registers\n"); + ret = -ENOMEM; + goto out_free; + } + + parent_irq = irq_of_parse_and_map(np, 0); + if (!parent_irq) { + pr_err("failed to find parent interrupt\n"); + ret = -EINVAL; + goto out_unmap; + } + + data->domain = irq_domain_add_linear(np, LPC_NR_IRQS, + &irq_generic_chip_ops, NULL); + if (!data->domain) { + ret = -ENOMEM; + goto out_unmap; + } + + /* Allocate a single Generic IRQ chip for this node */ + ret = irq_alloc_domain_generic_chips(data->domain, 16, 1, np->name, + handle_level_irq, 0, set, + IRQ_GC_INIT_MASK_CACHE); + if (ret) { + pr_err("failed to allocate generic irq chip\n"); + goto out_free_domain; + } + + /* Set the IRQ chaining logic */ + irq_set_chained_handler_and_data(parent_irq, + lpc_irq_handler, data); + + data->gc = irq_get_domain_generic_chip(data->domain, 0); + data->gc->reg_base = base; + data->gc->private = data; + + ct = data->gc->chip_types; + + ct->regs.ack = LPC_IRQ; + ct->regs.mask = LPC_IRQ_MASK; + ct->chip.irq_mask = irq_gc_mask_set_bit; + ct->chip.irq_unmask = irq_gc_mask_clr_bit; + ct->chip.irq_ack = irq_gc_ack_set_bit; + ct->chip.irq_mask_ack = lpc_irq_mask_ack; + + for (hwirq = 0 ; hwirq < 16 ; hwirq++) + irq_create_mapping(data->domain, hwirq); + + /* Enable LPC interrupts */ + writel(0xffffebdd, base + LPC_IRQ_MASK); + + return 0; + +out_free_domain: + irq_domain_remove(data->domain); +out_unmap: + iounmap(base); +out_free: + kfree(data); + return ret; +} +IRQCHIP_DECLARE(sw_lpc_intc, "sw64,lpc_intc", lpc_intc_of_init); diff --git a/drivers/mfd/lpc_sunway_chip3.c b/drivers/mfd/lpc_sunway_chip3.c index 793b557195c2..878aff87c992 100644 --- a/drivers/mfd/lpc_sunway_chip3.c +++ b/drivers/mfd/lpc_sunway_chip3.c @@ -75,53 +75,16 @@ enum { LPC_DMA_SWRST = 0x70, }; -enum { - LPC_IRQ0 = 0, /* 8254 Timer */ - LPC_IRQ1, /* Keyboard */ - LPC_IRQ2, /* Reserved */ - LPC_IRQ3, /* UART */ - LPC_IRQ4, /* UART */ - LPC_IRQ5, /* LPC Parallel Port2 */ - LPC_IRQ6, /* FDC-Floppy Disk Controller */ - LPC_IRQ7, /* LPT-Parallel Port1 */ - LPC_NR_IRQS, - LPC_IRQ8, /* RTC */ - LPC_IRQ9, /* Undefined */ - LPC_IRQ10, /* Undefined */ - LPC_IRQ11, /* Undefined */ - LPC_IRQ12, /* Mouse */ - LPC_IRQ13, /* Undefined */ - LPC_IRQ14, /* Undefined */ - LPC_IRQ15, /* Undefined */ -}; - struct lpc_chip3_adapter { void __iomem *hst_regs; struct device *dev; int irq; - struct irq_chip_generic *gc; unsigned int features; }; static struct resource superio_chip3_resources[] = { { .flags = IORESOURCE_IO, - }, { - .start = LPC_IRQ1, - .flags = IORESOURCE_IRQ, - .name = "i8042_kbd_irq", - }, { - .start = LPC_IRQ12, - .flags = IORESOURCE_IRQ, - .name = "i8042_aux_irq", - }, { - .start = LPC_IRQ5, - .flags = IORESOURCE_IRQ, - .name = "uart0_irq", - }, { - .start = LPC_IRQ4, - .flags = IORESOURCE_IRQ, - .name = "uart1_irq", } }; @@ -218,75 +181,9 @@ static void lpc_fw_flash_init(struct platform_device *pdev, } -static u32 lpc_do_irq(struct lpc_chip3_adapter *lpc_adapter) -{ - u32 irq_status = readl_relaxed(lpc_adapter->hst_regs + LPC_IRQ); - u32 ret = irq_status; - - DBG_LPC("%s irq_status=%#x\n", __func__, irq_status); - while (irq_status) { - int hwirq = fls(irq_status) - 1; - - generic_handle_irq(hwirq); - irq_status &= ~BIT(hwirq); - } - - lpc_writel(lpc_adapter->hst_regs, LPC_IRQ, ret); - return 1; -} - -static void lpc_irq_handler_mfd(struct irq_desc *desc) -{ - unsigned int irq = irq_desc_get_irq(desc); - struct lpc_chip3_adapter *lpc_adapter = irq_get_handler_data(irq); - u32 worked = 0; - - DBG_LPC("enter %s line:%d\n", __func__, __LINE__); - - worked = lpc_do_irq(lpc_adapter); - if (worked == IRQ_HANDLED) - dev_dbg(lpc_adapter->dev, "LPC irq handled.\n"); - - DBG_LPC("leave %s line:%d\n", __func__, __LINE__); -} - -static void lpc_unmask_interrupt_all(struct lpc_chip3_adapter *lpc_adapter) -{ - lpc_writel(lpc_adapter->hst_regs, LPC_IRQ_MASK, 0); -} - -static void lpc_irq_mask_ack(struct irq_data *d) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct irq_chip_type *ct = irq_data_get_chip_type(d); - u32 mask = d->mask; - - irq_gc_lock(gc); - *ct->mask_cache |= mask; - irq_reg_writel(gc, *ct->mask_cache, ct->regs.mask); - irq_reg_writel(gc, mask, ct->regs.ack); - irq_gc_unlock(gc); -} - -static void lpc_enable_irqs(struct lpc_chip3_adapter *lpc_adapter) -{ - int interrupt = 0; - - lpc_unmask_interrupt_all(lpc_adapter); - - interrupt = lpc_readl(lpc_adapter->hst_regs, LPC_IRQ); - - lpc_writel(lpc_adapter->hst_regs, LPC_CTL, 0x1600); - interrupt = lpc_readl(lpc_adapter->hst_regs, LPC_IRQ); -} - static int lpc_chip3_probe(struct platform_device *pdev) { int ret; - int num_ct = 1; - int irq_base; - struct irq_chip_generic *gc; - struct irq_chip_type *ct; struct lpc_chip3_adapter *lpc_adapter; struct resource *mem; @@ -312,32 +209,6 @@ static int lpc_chip3_probe(struct platform_device *pdev) lpc_adapter->dev = &pdev->dev; lpc_adapter->features = 0; - lpc_adapter->irq = platform_get_irq(pdev, 0); - if (lpc_adapter->irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); - return lpc_adapter->irq; /* -ENXIO */ - } - - irq_base = LPC_IRQ0; - gc = irq_alloc_generic_chip("LPC_CHIP3", num_ct, irq_base, - lpc_adapter->hst_regs, handle_level_irq); - - ct = gc->chip_types; - ct->regs.mask = LPC_IRQ_MASK; - ct->regs.ack = LPC_IRQ; - ct->chip.irq_mask = irq_gc_mask_set_bit; - ct->chip.irq_unmask = irq_gc_mask_clr_bit; - ct->chip.irq_ack = irq_gc_ack_set_bit; - ct->chip.irq_mask_ack = lpc_irq_mask_ack; - irq_setup_generic_chip(gc, IRQ_MSK(LPC_NR_IRQS), 0, 0, - IRQ_NOPROBE | IRQ_LEVEL); - - lpc_adapter->gc = gc; - - irq_set_handler_data(lpc_adapter->irq, lpc_adapter); - irq_set_chained_handler(lpc_adapter->irq, - (irq_flow_handler_t) lpc_irq_handler_mfd); - lpc_enable(lpc_adapter); lpc_mem_flash_init(pdev, lpc_adapter); @@ -350,7 +221,6 @@ static int lpc_chip3_probe(struct platform_device *pdev) goto out_dev; dev_info(lpc_adapter->dev, "probe succeed !\n"); - lpc_enable_irqs(lpc_adapter); return ret; -- Gitee From f920164998e475ee8dc6a3dc2be9d406c380acf3 Mon Sep 17 00:00:00 2001 From: Zhu Donghong Date: Wed, 18 May 2022 15:24:50 +0800 Subject: [PATCH 38/71] sw64: add builtin LPC interrupt controller to chip3.dts Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5G7AK -------------------------------- This adds corresponding devicetree binding for LPC interrupt controllers on chip3 series cpu. Signed-off-by: Zhu Donghong Signed-off-by: Gu Zitao --- arch/sw_64/boot/dts/chip3.dts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/boot/dts/chip3.dts b/arch/sw_64/boot/dts/chip3.dts index be2e91ee3279..082506393ac9 100644 --- a/arch/sw_64/boot/dts/chip3.dts +++ b/arch/sw_64/boot/dts/chip3.dts @@ -32,12 +32,20 @@ }; - intc: interrupt-controller{ + intc: interrupt-controller { compatible = "sw64,sw6_irq_controller"; interrupt-controller; #interrupt-cells = <1>; }; + lpc_intc: interrupt-controller@0x8037 { + compatible = "sw64,lpc_intc"; + reg = <0x8037 0x40000000 0x0 0x8000>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&intc>; + interrupts = <2>; + }; uart: serial0@8033 { #address-cells = <2>; @@ -176,10 +184,8 @@ lpc: lpc@0x8037 { #address-cells = <2>; #size-cells = <2>; - compatible = "sw,sw6b_lpc"; + compatible = "sunway,chip3_lpc"; reg = <0x8037 0x40000000 0x0 0x8000>; - interrupt-parent=<&intc>; - interrupts = <2>; status = "okay"; }; @@ -202,6 +208,8 @@ device_type = "ipmi"; compatible = "ipmi-bt"; reg = <0x8037 0x100000e4 0x0 0x10>; + interrupt-parent=<&lpc_intc>; + interrupts = <10>; reg-size = <1>; reg-spacing = <1>; reg-shift = <0>; -- Gitee From 6422b5c0dbd7b5602f449ccec702266cdde2b34e Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Thu, 19 May 2022 09:06:17 +0800 Subject: [PATCH 39/71] sw64: fix some structs related to pt_regs Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GF7A -------------------------------- Because of previous modifications to struct pt_regs, this patch fixes struct pt_regs_offset, dbg_reg_def and perf_event_sw64_regs to keep them consistent. Signed-off-by: He Chuyue Signed-off-by: Gu Zitao --- arch/sw_64/include/uapi/asm/perf_regs.h | 7 +++++++ arch/sw_64/kernel/kgdb.c | 14 +++++++------- arch/sw_64/kernel/ptrace.c | 7 +++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/arch/sw_64/include/uapi/asm/perf_regs.h b/arch/sw_64/include/uapi/asm/perf_regs.h index 426ae642fcc8..1378a7397951 100644 --- a/arch/sw_64/include/uapi/asm/perf_regs.h +++ b/arch/sw_64/include/uapi/asm/perf_regs.h @@ -13,6 +13,13 @@ enum perf_event_sw64_regs { PERF_REG_SW64_R6, PERF_REG_SW64_R7, PERF_REG_SW64_R8, + PERF_REG_SW64_R9, + PERF_REG_SW64_R10, + PERF_REG_SW64_R11, + PERF_REG_SW64_R12, + PERF_REG_SW64_R13, + PERF_REG_SW64_R14, + PERF_REG_SW64_R15, PERF_REG_SW64_R19, PERF_REG_SW64_R20, PERF_REG_SW64_R21, diff --git a/arch/sw_64/kernel/kgdb.c b/arch/sw_64/kernel/kgdb.c index 491f287eede9..ac2f397f1609 100644 --- a/arch/sw_64/kernel/kgdb.c +++ b/arch/sw_64/kernel/kgdb.c @@ -34,13 +34,13 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = { { "r7", 8, offsetof(struct pt_regs, r7)}, { "r8", 8, offsetof(struct pt_regs, r8)}, - { "r9", 8, -1 }, - { "r10", 8, -1 }, - { "r11", 8, -1 }, - { "r12", 8, -1 }, - { "r13", 8, -1 }, - { "r14", 8, -1 }, - { "r15", 8, -1 }, + { "r9", 8, offsetof(struct pt_regs, r9)}, + { "r10", 8, offsetof(struct pt_regs, r10)}, + { "r11", 8, offsetof(struct pt_regs, r11)}, + { "r12", 8, offsetof(struct pt_regs, r12)}, + { "r13", 8, offsetof(struct pt_regs, r13)}, + { "r14", 8, offsetof(struct pt_regs, r14)}, + { "r15", 8, offsetof(struct pt_regs, r15)}, { "r16", 8, offsetof(struct pt_regs, r16)}, { "r17", 8, offsetof(struct pt_regs, r17)}, diff --git a/arch/sw_64/kernel/ptrace.c b/arch/sw_64/kernel/ptrace.c index ce41d89a54cb..94809804e23e 100644 --- a/arch/sw_64/kernel/ptrace.c +++ b/arch/sw_64/kernel/ptrace.c @@ -619,6 +619,13 @@ static const struct pt_regs_offset regoffset_table[] = { REG_OFFSET_NAME(r6), REG_OFFSET_NAME(r7), REG_OFFSET_NAME(r8), + REG_OFFSET_NAME(r9), + REG_OFFSET_NAME(r10), + REG_OFFSET_NAME(r11), + REG_OFFSET_NAME(r12), + REG_OFFSET_NAME(r13), + REG_OFFSET_NAME(r14), + REG_OFFSET_NAME(r15), REG_OFFSET_NAME(r19), REG_OFFSET_NAME(r20), REG_OFFSET_NAME(r21), -- Gitee From 9fc89ea369a1953ee9ed8839a43df772eead479d Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Tue, 24 May 2022 16:03:40 +0800 Subject: [PATCH 40/71] sw64: perf: add exclude_user and exclude_kernel support Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56X48 -------------------------------- Although sw64 have no per-counter usr/os/guest/host bits, we can distinguish user and kernel by sample mode. Signed-off-by: He Chuyue Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/wrperfmon.h | 4 ++++ arch/sw_64/kernel/perf_event.c | 20 +++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/arch/sw_64/include/asm/wrperfmon.h b/arch/sw_64/include/asm/wrperfmon.h index eaa6735b5a25..098702573bfc 100644 --- a/arch/sw_64/include/asm/wrperfmon.h +++ b/arch/sw_64/include/asm/wrperfmon.h @@ -38,6 +38,10 @@ #define PC1_MIN 0x0 #define PC1_MAX 0x37 +#define SW64_PERFCTRL_KM 2 +#define SW64_PERFCTRL_UM 3 +#define SW64_PERFCTRL_AM 4 + /* pc0 events */ #define PC0_INSTRUCTIONS 0x0 #define PC0_BRANCH_INSTRUCTIONS 0x3 diff --git a/arch/sw_64/kernel/perf_event.c b/arch/sw_64/kernel/perf_event.c index d2975e17f666..0d49224ba058 100644 --- a/arch/sw_64/kernel/perf_event.c +++ b/arch/sw_64/kernel/perf_event.c @@ -457,8 +457,8 @@ static void sw64_pmu_start(struct perf_event *event, int flags) hwc->state = 0; - /* counting in all modes, for both counters */ - wrperfmon(PERFMON_CMD_PM, 4); + /* counting in selected modes, for both counters */ + wrperfmon(PERFMON_CMD_PM, hwc->config_base); if (hwc->idx == PERFMON_PC0) { wrperfmon(PERFMON_CMD_EVENT_PC0, hwc->event_base); wrperfmon(PERFMON_CMD_ENABLE, PERFMON_ENABLE_ARGS_PC0); @@ -519,9 +519,12 @@ static int __hw_perf_event_init(struct perf_event *event) const struct sw64_perf_event *event_type; - /* SW64 do not have per-counter usr/os/guest/host bits */ - if (event->attr.exclude_user || event->attr.exclude_kernel || - event->attr.exclude_hv || event->attr.exclude_idle || + /* + * SW64 does not have per-counter usr/os/guest/host bits, + * we can distinguish exclude_user and exclude_kernel by + * sample mode. + */ + if (event->attr.exclude_hv || event->attr.exclude_idle || event->attr.exclude_host || event->attr.exclude_guest) return -EINVAL; @@ -553,6 +556,13 @@ static int __hw_perf_event_init(struct perf_event *event) hwc->event_base = attr->config & 0xff; /* event selector */ } + hwc->config_base = SW64_PERFCTRL_AM; + + if (attr->exclude_user) + hwc->config_base = SW64_PERFCTRL_KM; + if (attr->exclude_kernel) + hwc->config_base = SW64_PERFCTRL_UM; + hwc->config = attr->config; if (!is_sampling_event(event)) -- Gitee From b9e3841445914e43ecf42975f2d8a8f3c8239e25 Mon Sep 17 00:00:00 2001 From: Hang Xiaoqian Date: Wed, 25 May 2022 10:54:25 +0800 Subject: [PATCH 41/71] sw64: change the value of physical_id in /proc/cpuinfo Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- The value of physical_id in /proc/cpuinfo should be the socket_id of the processor. Signed-off-by: Hang Xiaoqian Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index faae7cb3c5a1..4d39db5fb1ef 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -907,7 +907,7 @@ show_cpuinfo(struct seq_file *f, void *slot) "physical id\t: %d\n" "bogomips\t: %lu.%02lu\n", cpu_freq, cpu_data[i].tcache.size >> 10, - cpu_to_rcid(i), + cpu_topology[i].package_id, loops_per_jiffy / (500000/HZ), (loops_per_jiffy / (5000/HZ)) % 100); -- Gitee From 06ed664fca7dcb8963d9868472a4cbbb149edb27 Mon Sep 17 00:00:00 2001 From: Gu Zitao Date: Tue, 24 May 2022 15:28:27 +0800 Subject: [PATCH 42/71] sw64: add ARCH_TRACEHOOK and regset support Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5G7NL -------------------------------- By adding TRACEHOOK support, we can access register sets via PTRACE_GETREGSET and PTRACE_SETREGSET request. The user-visible regset struct user_pt_regs and user_fpsimd_state are added in this patch, and they can be accessed with NT_PRSTATUS and NT_PRFPREG respectively. Besides, PTRACE_{GET,SET}REGS and PTRACE_{GET,SET}FPREGS requests which are implemented in error have never been used on sw64, so we remove them completely. Signed-off-by: Gu Zitao Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 1 + arch/sw_64/include/uapi/asm/ptrace.h | 18 ++- arch/sw_64/kernel/ptrace.c | 194 +++++++++++++-------------- 3 files changed, 111 insertions(+), 102 deletions(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 2d7721acb529..0e32fc7e1f9a 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -68,6 +68,7 @@ config SW64 select ARCH_HAS_SG_CHAIN select IRQ_FORCED_THREADING select GENERIC_IRQ_MIGRATION if SMP + select HAVE_ARCH_TRACEHOOK select HAVE_FUNCTION_TRACER select HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD diff --git a/arch/sw_64/include/uapi/asm/ptrace.h b/arch/sw_64/include/uapi/asm/ptrace.h index ac7ce6b6510b..1169d87c4b9c 100644 --- a/arch/sw_64/include/uapi/asm/ptrace.h +++ b/arch/sw_64/include/uapi/asm/ptrace.h @@ -2,10 +2,20 @@ #ifndef _UAPI_ASM_SW64_PTRACE_H #define _UAPI_ASM_SW64_PTRACE_H -#define PTRACE_GETREGS 12 /* get general purpose registers */ -#define PTRACE_SETREGS 13 /* set general purpose registers */ -#define PTRACE_GETFPREGS 14 /* get floating-point registers */ -#define PTRACE_SETFPREGS 15 /* set floating-point registers */ +/* + * User structures for general purpose, floating point and debug registers. + */ +struct user_pt_regs { + __u64 regs[31]; + __u64 pc; + __u64 pstate; +}; + +struct user_fpsimd_state { + __u64 vregs[124]; + __u64 fpcr; +}; + /* PTRACE_ATTACH is 16 */ /* PTRACE_DETACH is 17 */ diff --git a/arch/sw_64/kernel/ptrace.c b/arch/sw_64/kernel/ptrace.c index 94809804e23e..94fba3569781 100644 --- a/arch/sw_64/kernel/ptrace.c +++ b/arch/sw_64/kernel/ptrace.c @@ -7,6 +7,8 @@ #include #include +#include +#include #include #include @@ -270,123 +272,131 @@ void ptrace_disable(struct task_struct *child) user_disable_single_step(child); } -int ptrace_getregs(struct task_struct *child, __s64 __user *data) +static int gpr_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) { - int ret, retval = 0; - int i; - unsigned long regval; + struct pt_regs *regs; + struct user_pt_regs uregs; + int i, ret; - if (!access_ok(data, sizeof(long) * 33)) - return -EIO; + regs = task_pt_regs(target); + for (i = 0; i < 30; i++) + uregs.regs[i] = *(__u64 *)((void *)regs + regoffsets[i]); + + uregs.regs[30] = task_thread_info(target)->pcb.usp; + uregs.pc = regs->pc; + uregs.pstate = regs->ps; + + ret = membuf_write(&to, &uregs, sizeof(uregs)); - /* r0-r15 */ - for (i = 0; i < 16; i++) { - regval = get_reg(child, i); - retval |= __put_user((long)regval, data + i); - } - /* r19-r28 */ - for (i = 19; i < 29; i++) { - regval = get_reg(child, i); - retval |= __put_user((long)regval, data + i - 3); - } - /*SP, PS ,PC,GP*/ - retval |= __put_user((long)(get_reg(child, REG_SP)), data + EF_SP); - retval |= __put_user((long)(get_reg(child, REG_PS)), data + EF_PS); - retval |= __put_user((long)(get_reg(child, REG_PC)), data + EF_PC); - retval |= __put_user((long)(get_reg(child, REG_GP)), data + EF_GP); - /* r16-r18 */ - retval |= __put_user((long)(get_reg(child, 16)), data + EF_A0); - retval |= __put_user((long)(get_reg(child, 17)), data + EF_A1); - retval |= __put_user((long)(get_reg(child, 18)), data + EF_A2); - - ret = retval ? -EIO : 0; return ret; } -int ptrace_setregs(struct task_struct *child, __s64 __user *data) +static int gpr_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) { - int ret, retval = 0; - int i; - unsigned long regval; + struct pt_regs *regs; + struct user_pt_regs uregs; + int i, ret; - if (!access_ok(data, sizeof(long) * 33)) - return -EIO; + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &uregs, 0, sizeof(uregs)); + if (ret) + return ret; + + regs = task_pt_regs(target); + for (i = 0; i < 30; i++) + *(__u64 *)((void *)regs + regoffsets[i]) = uregs.regs[i]; + + task_thread_info(target)->pcb.usp = uregs.regs[30]; + regs->pc = uregs.pc; + regs->ps = uregs.pstate; - /* r0-r15 */ - for (i = 0; i < 16; i++) { - retval |= __get_user(regval, data + i); - ret = put_reg(child, i, regval); - } - /* r19-r28 */ - for (i = 19; i < 29; i++) { - retval |= __get_user(regval, data + i - 3); - ret = put_reg(child, i, regval); - } - /*SP, PS ,PC,GP*/ - retval |= __get_user(regval, data + EF_SP); - ret = put_reg(child, REG_SP, regval); - retval |= __get_user(regval, data + EF_PS); - ret = put_reg(child, REG_PS, regval); - retval |= __get_user(regval, data + EF_PC); - ret = put_reg(child, REG_PC, regval); - retval |= __get_user(regval, data + EF_GP); - ret = put_reg(child, REG_GP, regval); - /* r16-r18 */ - retval |= __get_user(regval, data + EF_A0); - ret = put_reg(child, 16, regval); - retval |= __get_user(regval, data + EF_A1); - ret = put_reg(child, 17, regval); - retval |= __get_user(regval, data + EF_A2); - ret = put_reg(child, 18, regval); - - ret = retval ? -EIO : 0; return 0; } -int ptrace_getfpregs(struct task_struct *child, __s64 __user *data) +static int fpr_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) { - int ret, retval = 0; - int i; - unsigned long regval; + int ret; + struct user_fpsimd_state uregs; - if (!access_ok(data, sizeof(long) * 32)) - return -EIO; + memcpy(uregs.vregs, &target->thread.ctx_fp, + sizeof(struct context_fpregs)); - /* fp0-fp31 */ - for (i = 0; i < 32; i++) { - regval = get_reg(child, REG_F0 + i); - retval |= __put_user((long)regval, data + i); - } + uregs.fpcr = target->thread.fpcr; - ret = retval ? -EIO : 0; - return 0; + ret = membuf_write(&to, &uregs, sizeof(uregs)); + + return ret; } -int ptrace_setfpregs(struct task_struct *child, __s64 __user *data) +static int fpr_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) { - int ret, retval = 0; - int i; - unsigned long regval; + int ret; + struct user_fpsimd_state uregs; - if (!access_ok(data, sizeof(long) * 32)) - return -EIO; + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &uregs, 0, sizeof(uregs)); - /* fp0-fp31 */ - for (i = 0; i < 32; i++) { - retval |= __get_user(regval, data + i); - ret = put_reg(child, REG_F0 + i, regval); - } + if (ret) + return ret; + + memcpy(&target->thread.ctx_fp, uregs.vregs, + sizeof(struct context_fpregs)); + + target->thread.fpcr = uregs.fpcr; return ret; } +enum sw64_regset { + REGSET_GPR, + REGSET_FPR, +}; + +static const struct user_regset sw64_regsets[] = { + [REGSET_GPR] = { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(elf_greg_t), + .align = sizeof(elf_greg_t), + .regset_get = gpr_get, + .set = gpr_set + }, + [REGSET_FPR] = { + .core_note_type = NT_PRFPREG, + .n = sizeof(struct user_fpsimd_state) / sizeof(u64), + .size = sizeof(u64), + .align = sizeof(u64), + .regset_get = fpr_get, + .set = fpr_set + }, +}; + +static const struct user_regset_view user_sw64_view = { + .name = "sw64", .e_machine = EM_SW64, + .regsets = sw64_regsets, .n = ARRAY_SIZE(sw64_regsets) +}; + +const struct user_regset_view *task_user_regset_view(struct task_struct *task) +{ + return &user_sw64_view; +} + long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { unsigned long tmp; size_t copied; long ret; - void __user *datavp = (void __user *) data; switch (request) { /* When I and D space are separate, these will need to be fixed. */ @@ -416,18 +426,6 @@ long arch_ptrace(struct task_struct *child, long request, case PTRACE_POKEUSR: /* write the specified register */ ret = put_reg(child, addr, data); break; - case PTRACE_GETREGS: - ret = ptrace_getregs(child, datavp); - break; - case PTRACE_SETREGS: - ret = ptrace_setregs(child, datavp); - break; - case PTRACE_GETFPREGS: - ret = ptrace_getfpregs(child, datavp); - break; - case PTRACE_SETFPREGS: - ret = ptrace_setfpregs(child, datavp); - break; default: ret = ptrace_request(child, request, addr, data); break; -- Gitee From a9839e292f57d2e4f65e82e73d278fff9adff87e Mon Sep 17 00:00:00 2001 From: He Sheng Date: Thu, 26 May 2022 11:00:48 +0800 Subject: [PATCH 43/71] sw64: merge user_fpsimd_state into thread_struct Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5G7NL -------------------------------- The user_fpsimd_state struct has been defined to hold fpu state which is also held in thread_struct. To reuse this struct, this patch makes a little change to user_fpsimd_state, then replace struct context_fpregs and fpcr of thread_struct. This patch also moves definition of task_pt_regs and mm_segment_t to appropriate headers to avoid compile errors. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/processor.h | 45 +-------- arch/sw_64/include/asm/ptrace.h | 4 - arch/sw_64/include/asm/thread_info.h | 5 + arch/sw_64/include/uapi/asm/ptrace.h | 8 +- arch/sw_64/kernel/asm-offsets.c | 67 +++++++------- arch/sw_64/kernel/fpu.S | 134 +++++++++++++-------------- arch/sw_64/kernel/process.c | 2 +- arch/sw_64/kernel/ptrace.c | 51 +++------- arch/sw_64/kernel/signal.c | 13 +-- arch/sw_64/kvm/entry.S | 40 ++++---- 10 files changed, 155 insertions(+), 214 deletions(-) diff --git a/arch/sw_64/include/asm/processor.h b/arch/sw_64/include/asm/processor.h index 67d3b4368987..08e8cc8e5428 100644 --- a/arch/sw_64/include/asm/processor.h +++ b/arch/sw_64/include/asm/processor.h @@ -9,6 +9,10 @@ #define _ASM_SW64_PROCESSOR_H #include /* for ADDR_LIMIT_32BIT */ +#include + +#define task_pt_regs(task) \ + ((struct pt_regs *) (task_stack_page(task) + 2 * PAGE_SIZE) - 1) /* * Returns current instruction pointer ("program counter"). @@ -37,47 +41,8 @@ #define TASK_UNMAPPED_BASE \ ((current->personality & ADDR_LIMIT_32BIT) ? 0x40000000 : UNMAPPED_BASE) -typedef struct { - unsigned long seg; -} mm_segment_t; - -struct context_fpregs { - unsigned long f0[4]; - unsigned long f1[4]; - unsigned long f2[4]; - unsigned long f3[4]; - unsigned long f4[4]; - unsigned long f5[4]; - unsigned long f6[4]; - unsigned long f7[4]; - unsigned long f8[4]; - unsigned long f9[4]; - unsigned long f10[4]; - unsigned long f11[4]; - unsigned long f12[4]; - unsigned long f13[4]; - unsigned long f14[4]; - unsigned long f15[4]; - unsigned long f16[4]; - unsigned long f17[4]; - unsigned long f18[4]; - unsigned long f19[4]; - unsigned long f20[4]; - unsigned long f21[4]; - unsigned long f22[4]; - unsigned long f23[4]; - unsigned long f24[4]; - unsigned long f25[4]; - unsigned long f26[4]; - unsigned long f27[4]; - unsigned long f28[4]; - unsigned long f29[4]; - unsigned long f30[4]; -} __aligned(32); /* 256 bits aligned for simd */ - struct thread_struct { - struct context_fpregs ctx_fp; - unsigned long fpcr; + struct user_fpsimd_state fpstate; /* Callee-saved registers */ unsigned long ra; unsigned long s[7]; /* s0 ~ s6 */ diff --git a/arch/sw_64/include/asm/ptrace.h b/arch/sw_64/include/asm/ptrace.h index 85f7a47fdee3..ac9943015663 100644 --- a/arch/sw_64/include/asm/ptrace.h +++ b/arch/sw_64/include/asm/ptrace.h @@ -3,10 +3,8 @@ #define _ASM_SW64_PTRACE_H #include -#include #include #include -#include #include /* @@ -65,8 +63,6 @@ struct pt_regs { #define kernel_stack_pointer(regs) (((regs->ps) >> 4) & (TASK_SIZE - 1)) #define instruction_pointer_set(regs, val) ((regs)->pc = val) -#define task_pt_regs(task) \ - ((struct pt_regs *) (task_stack_page(task) + 2 * PAGE_SIZE) - 1) #define current_pt_regs() \ ((struct pt_regs *) ((char *)current_thread_info() + 2 * PAGE_SIZE) - 1) diff --git a/arch/sw_64/include/asm/thread_info.h b/arch/sw_64/include/asm/thread_info.h index cffb09fc6262..33b95f815448 100644 --- a/arch/sw_64/include/asm/thread_info.h +++ b/arch/sw_64/include/asm/thread_info.h @@ -9,6 +9,11 @@ #include #include +typedef struct { + unsigned long seg; +} mm_segment_t; + + struct pcb_struct { unsigned long ksp; unsigned long usp; diff --git a/arch/sw_64/include/uapi/asm/ptrace.h b/arch/sw_64/include/uapi/asm/ptrace.h index 1169d87c4b9c..a45b10b8914a 100644 --- a/arch/sw_64/include/uapi/asm/ptrace.h +++ b/arch/sw_64/include/uapi/asm/ptrace.h @@ -11,9 +11,15 @@ struct user_pt_regs { __u64 pstate; }; +/* 256 bits aligned for simd */ +struct fpreg { + __u64 v[4] __attribute__((aligned(32))); +}; + struct user_fpsimd_state { - __u64 vregs[124]; + struct fpreg fp[31]; __u64 fpcr; + __u64 __reserved[3]; }; /* PTRACE_ATTACH is 16 */ diff --git a/arch/sw_64/kernel/asm-offsets.c b/arch/sw_64/kernel/asm-offsets.c index 5dc59346996f..0c7e1e26eb05 100644 --- a/arch/sw_64/kernel/asm-offsets.c +++ b/arch/sw_64/kernel/asm-offsets.c @@ -178,40 +178,39 @@ void foo(void) DEFINE(HOST_INT_R16, offsetof(struct host_int_args, r16)); BLANK(); - DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); - DEFINE(THREAD_CTX_FP, offsetof(struct thread_struct, ctx_fp)); - DEFINE(THREAD_FPCR, offsetof(struct thread_struct, fpcr)); - DEFINE(CTX_FP_F0, offsetof(struct context_fpregs, f0)); - DEFINE(CTX_FP_F1, offsetof(struct context_fpregs, f1)); - DEFINE(CTX_FP_F2, offsetof(struct context_fpregs, f2)); - DEFINE(CTX_FP_F3, offsetof(struct context_fpregs, f3)); - DEFINE(CTX_FP_F4, offsetof(struct context_fpregs, f4)); - DEFINE(CTX_FP_F5, offsetof(struct context_fpregs, f5)); - DEFINE(CTX_FP_F6, offsetof(struct context_fpregs, f6)); - DEFINE(CTX_FP_F7, offsetof(struct context_fpregs, f7)); - DEFINE(CTX_FP_F8, offsetof(struct context_fpregs, f8)); - DEFINE(CTX_FP_F9, offsetof(struct context_fpregs, f9)); - DEFINE(CTX_FP_F10, offsetof(struct context_fpregs, f10)); - DEFINE(CTX_FP_F11, offsetof(struct context_fpregs, f11)); - DEFINE(CTX_FP_F12, offsetof(struct context_fpregs, f12)); - DEFINE(CTX_FP_F13, offsetof(struct context_fpregs, f13)); - DEFINE(CTX_FP_F14, offsetof(struct context_fpregs, f14)); - DEFINE(CTX_FP_F15, offsetof(struct context_fpregs, f15)); - DEFINE(CTX_FP_F16, offsetof(struct context_fpregs, f16)); - DEFINE(CTX_FP_F17, offsetof(struct context_fpregs, f17)); - DEFINE(CTX_FP_F18, offsetof(struct context_fpregs, f18)); - DEFINE(CTX_FP_F19, offsetof(struct context_fpregs, f19)); - DEFINE(CTX_FP_F20, offsetof(struct context_fpregs, f20)); - DEFINE(CTX_FP_F21, offsetof(struct context_fpregs, f21)); - DEFINE(CTX_FP_F22, offsetof(struct context_fpregs, f22)); - DEFINE(CTX_FP_F23, offsetof(struct context_fpregs, f23)); - DEFINE(CTX_FP_F24, offsetof(struct context_fpregs, f24)); - DEFINE(CTX_FP_F25, offsetof(struct context_fpregs, f25)); - DEFINE(CTX_FP_F26, offsetof(struct context_fpregs, f26)); - DEFINE(CTX_FP_F27, offsetof(struct context_fpregs, f27)); - DEFINE(CTX_FP_F28, offsetof(struct context_fpregs, f28)); - DEFINE(CTX_FP_F29, offsetof(struct context_fpregs, f29)); - DEFINE(CTX_FP_F30, offsetof(struct context_fpregs, f30)); + OFFSET(TASK_THREAD, task_struct, thread); + OFFSET(TASK_THREAD_F0, task_struct, thread.fpstate.fp[0]); + OFFSET(TASK_THREAD_F1, task_struct, thread.fpstate.fp[1]); + OFFSET(TASK_THREAD_F2, task_struct, thread.fpstate.fp[2]); + OFFSET(TASK_THREAD_F3, task_struct, thread.fpstate.fp[3]); + OFFSET(TASK_THREAD_F4, task_struct, thread.fpstate.fp[4]); + OFFSET(TASK_THREAD_F5, task_struct, thread.fpstate.fp[5]); + OFFSET(TASK_THREAD_F6, task_struct, thread.fpstate.fp[6]); + OFFSET(TASK_THREAD_F7, task_struct, thread.fpstate.fp[7]); + OFFSET(TASK_THREAD_F8, task_struct, thread.fpstate.fp[8]); + OFFSET(TASK_THREAD_F9, task_struct, thread.fpstate.fp[9]); + OFFSET(TASK_THREAD_F10, task_struct, thread.fpstate.fp[10]); + OFFSET(TASK_THREAD_F11, task_struct, thread.fpstate.fp[11]); + OFFSET(TASK_THREAD_F12, task_struct, thread.fpstate.fp[12]); + OFFSET(TASK_THREAD_F13, task_struct, thread.fpstate.fp[13]); + OFFSET(TASK_THREAD_F14, task_struct, thread.fpstate.fp[14]); + OFFSET(TASK_THREAD_F15, task_struct, thread.fpstate.fp[15]); + OFFSET(TASK_THREAD_F16, task_struct, thread.fpstate.fp[16]); + OFFSET(TASK_THREAD_F17, task_struct, thread.fpstate.fp[17]); + OFFSET(TASK_THREAD_F18, task_struct, thread.fpstate.fp[18]); + OFFSET(TASK_THREAD_F19, task_struct, thread.fpstate.fp[19]); + OFFSET(TASK_THREAD_F20, task_struct, thread.fpstate.fp[20]); + OFFSET(TASK_THREAD_F21, task_struct, thread.fpstate.fp[21]); + OFFSET(TASK_THREAD_F22, task_struct, thread.fpstate.fp[22]); + OFFSET(TASK_THREAD_F23, task_struct, thread.fpstate.fp[23]); + OFFSET(TASK_THREAD_F24, task_struct, thread.fpstate.fp[24]); + OFFSET(TASK_THREAD_F25, task_struct, thread.fpstate.fp[25]); + OFFSET(TASK_THREAD_F26, task_struct, thread.fpstate.fp[26]); + OFFSET(TASK_THREAD_F27, task_struct, thread.fpstate.fp[27]); + OFFSET(TASK_THREAD_F28, task_struct, thread.fpstate.fp[28]); + OFFSET(TASK_THREAD_F29, task_struct, thread.fpstate.fp[29]); + OFFSET(TASK_THREAD_F30, task_struct, thread.fpstate.fp[30]); + OFFSET(TASK_THREAD_FPCR, task_struct, thread.fpstate.fpcr); BLANK(); OFFSET(TASK_THREAD_RA, task_struct, thread.ra); OFFSET(TASK_THREAD_S0, task_struct, thread.s[0]); diff --git a/arch/sw_64/kernel/fpu.S b/arch/sw_64/kernel/fpu.S index 25dcf4740525..3cb3bfab08e8 100644 --- a/arch/sw_64/kernel/fpu.S +++ b/arch/sw_64/kernel/fpu.S @@ -8,49 +8,46 @@ .set noat ENTRY(__fpstate_save) /* a0: prev task */ - ldi a0, TASK_THREAD(a0) - ldi t0, THREAD_CTX_FP(a0) - vstd $f0, CTX_FP_F0(t0) - vstd $f1, CTX_FP_F1(t0) - vstd $f2, CTX_FP_F2(t0) - vstd $f3, CTX_FP_F3(t0) - vstd $f4, CTX_FP_F4(t0) - vstd $f5, CTX_FP_F5(t0) - vstd $f6, CTX_FP_F6(t0) - vstd $f7, CTX_FP_F7(t0) - vstd $f8, CTX_FP_F8(t0) - vstd $f9, CTX_FP_F9(t0) - vstd $f10, CTX_FP_F10(t0) - vstd $f11, CTX_FP_F11(t0) - vstd $f12, CTX_FP_F12(t0) - vstd $f13, CTX_FP_F13(t0) - vstd $f14, CTX_FP_F14(t0) - vstd $f15, CTX_FP_F15(t0) - vstd $f16, CTX_FP_F16(t0) - vstd $f17, CTX_FP_F17(t0) - vstd $f18, CTX_FP_F18(t0) - vstd $f19, CTX_FP_F19(t0) - vstd $f20, CTX_FP_F20(t0) - vstd $f21, CTX_FP_F21(t0) - vstd $f22, CTX_FP_F22(t0) - vstd $f23, CTX_FP_F23(t0) - vstd $f24, CTX_FP_F24(t0) - vstd $f25, CTX_FP_F25(t0) - vstd $f26, CTX_FP_F26(t0) - vstd $f27, CTX_FP_F27(t0) + vstd $f0, TASK_THREAD_F0(a0) + vstd $f1, TASK_THREAD_F1(a0) + vstd $f2, TASK_THREAD_F2(a0) + vstd $f3, TASK_THREAD_F3(a0) + vstd $f4, TASK_THREAD_F4(a0) + vstd $f5, TASK_THREAD_F5(a0) + vstd $f6, TASK_THREAD_F6(a0) + vstd $f7, TASK_THREAD_F7(a0) + vstd $f8, TASK_THREAD_F8(a0) + vstd $f9, TASK_THREAD_F9(a0) + vstd $f10, TASK_THREAD_F10(a0) + vstd $f11, TASK_THREAD_F11(a0) + vstd $f12, TASK_THREAD_F12(a0) + vstd $f13, TASK_THREAD_F13(a0) + vstd $f14, TASK_THREAD_F14(a0) + vstd $f15, TASK_THREAD_F15(a0) + vstd $f16, TASK_THREAD_F16(a0) + vstd $f17, TASK_THREAD_F17(a0) + vstd $f18, TASK_THREAD_F18(a0) + vstd $f19, TASK_THREAD_F19(a0) + vstd $f20, TASK_THREAD_F20(a0) + vstd $f21, TASK_THREAD_F21(a0) + vstd $f22, TASK_THREAD_F22(a0) + vstd $f23, TASK_THREAD_F23(a0) + vstd $f24, TASK_THREAD_F24(a0) + vstd $f25, TASK_THREAD_F25(a0) + vstd $f26, TASK_THREAD_F26(a0) + vstd $f27, TASK_THREAD_F27(a0) rfpcr $f0 - vstd $f28, CTX_FP_F28(t0) - vstd $f29, CTX_FP_F29(t0) - vstd $f30, CTX_FP_F30(t0) - fstd $f0, THREAD_FPCR(a0) - vldd $f0, CTX_FP_F0(t0) + vstd $f28, TASK_THREAD_F28(a0) + vstd $f29, TASK_THREAD_F29(a0) + vstd $f30, TASK_THREAD_F30(a0) + fstd $f0, TASK_THREAD_FPCR(a0) + vldd $f0, TASK_THREAD_F0(a0) ret END(__fpstate_save) ENTRY(__fpstate_restore) /* a0: next task */ - ldi a0, TASK_THREAD(a0) - fldd $f0, THREAD_FPCR(a0) + fldd $f0, TASK_THREAD_FPCR(a0) wfpcr $f0 fimovd $f0, t1 and t1, 0x3, t1 @@ -70,37 +67,36 @@ $setfpec_1: $setfpec_2: setfpec2 $setfpec_over: - ldi t0, THREAD_CTX_FP(a0) - vldd $f0, CTX_FP_F0(t0) - vldd $f1, CTX_FP_F1(t0) - vldd $f2, CTX_FP_F2(t0) - vldd $f3, CTX_FP_F3(t0) - vldd $f4, CTX_FP_F4(t0) - vldd $f5, CTX_FP_F5(t0) - vldd $f6, CTX_FP_F6(t0) - vldd $f7, CTX_FP_F7(t0) - vldd $f8, CTX_FP_F8(t0) - vldd $f9, CTX_FP_F9(t0) - vldd $f10, CTX_FP_F10(t0) - vldd $f11, CTX_FP_F11(t0) - vldd $f12, CTX_FP_F12(t0) - vldd $f13, CTX_FP_F13(t0) - vldd $f14, CTX_FP_F14(t0) - vldd $f15, CTX_FP_F15(t0) - vldd $f16, CTX_FP_F16(t0) - vldd $f17, CTX_FP_F17(t0) - vldd $f18, CTX_FP_F18(t0) - vldd $f19, CTX_FP_F19(t0) - vldd $f20, CTX_FP_F20(t0) - vldd $f21, CTX_FP_F21(t0) - vldd $f22, CTX_FP_F22(t0) - vldd $f23, CTX_FP_F23(t0) - vldd $f24, CTX_FP_F24(t0) - vldd $f25, CTX_FP_F25(t0) - vldd $f26, CTX_FP_F26(t0) - vldd $f27, CTX_FP_F27(t0) - vldd $f28, CTX_FP_F28(t0) - vldd $f29, CTX_FP_F29(t0) - vldd $f30, CTX_FP_F30(t0) + vldd $f0, TASK_THREAD_F0(a0) + vldd $f1, TASK_THREAD_F1(a0) + vldd $f2, TASK_THREAD_F2(a0) + vldd $f3, TASK_THREAD_F3(a0) + vldd $f4, TASK_THREAD_F4(a0) + vldd $f5, TASK_THREAD_F5(a0) + vldd $f6, TASK_THREAD_F6(a0) + vldd $f7, TASK_THREAD_F7(a0) + vldd $f8, TASK_THREAD_F8(a0) + vldd $f9, TASK_THREAD_F9(a0) + vldd $f10, TASK_THREAD_F10(a0) + vldd $f11, TASK_THREAD_F11(a0) + vldd $f12, TASK_THREAD_F12(a0) + vldd $f13, TASK_THREAD_F13(a0) + vldd $f14, TASK_THREAD_F14(a0) + vldd $f15, TASK_THREAD_F15(a0) + vldd $f16, TASK_THREAD_F16(a0) + vldd $f17, TASK_THREAD_F17(a0) + vldd $f18, TASK_THREAD_F18(a0) + vldd $f19, TASK_THREAD_F19(a0) + vldd $f20, TASK_THREAD_F20(a0) + vldd $f21, TASK_THREAD_F21(a0) + vldd $f22, TASK_THREAD_F22(a0) + vldd $f23, TASK_THREAD_F23(a0) + vldd $f24, TASK_THREAD_F24(a0) + vldd $f25, TASK_THREAD_F25(a0) + vldd $f26, TASK_THREAD_F26(a0) + vldd $f27, TASK_THREAD_F27(a0) + vldd $f28, TASK_THREAD_F28(a0) + vldd $f29, TASK_THREAD_F29(a0) + vldd $f30, TASK_THREAD_F30(a0) ret END(__fpstate_restore) diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index 6b5f0f3a8345..308675d29c04 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -256,7 +256,7 @@ EXPORT_SYMBOL(dump_elf_task); int dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task) { - memcpy(dest, &task->thread.ctx_fp, 32 * 8); + memcpy(dest, &task->thread.fpstate, 32 * 8); return 1; } EXPORT_SYMBOL(dump_elf_task_fp); diff --git a/arch/sw_64/kernel/ptrace.c b/arch/sw_64/kernel/ptrace.c index 94fba3569781..bdbd0d97a130 100644 --- a/arch/sw_64/kernel/ptrace.c +++ b/arch/sw_64/kernel/ptrace.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -55,9 +56,6 @@ enum { REG_GP = 29 }; -#define FP_REG(fp_regno, vector_regno) \ - (fp_regno * 32 + vector_regno * 8) - #define R(x) ((size_t) &((struct pt_regs *)0)->x) short regoffsets[32] = { @@ -91,8 +89,8 @@ static unsigned long zero; static unsigned long * get_reg_addr(struct task_struct *task, unsigned long regno) { - unsigned long *addr; - int fp_regno, vector_regno; + void *addr; + int fno, vno; switch (regno) { case USP: @@ -108,9 +106,8 @@ get_reg_addr(struct task_struct *task, unsigned long regno) addr = (void *)task_pt_regs(task) + regoffsets[regno]; break; case FPREG_BASE ... FPREG_END: - fp_regno = regno - FPREG_BASE; - vector_regno = 0; - addr = (void *)((unsigned long)&task->thread.ctx_fp + FP_REG(fp_regno, vector_regno)); + fno = regno - FPREG_BASE; + addr = &task->thread.fpstate.fp[fno].v[0]; break; case VECREG_BASE ... VECREG_END: /* @@ -121,12 +118,12 @@ get_reg_addr(struct task_struct *task, unsigned long regno) addr = &zero; break; } - fp_regno = (regno - VECREG_BASE) & 0x1f; - vector_regno = 1 + ((regno - VECREG_BASE) >> 5); - addr = (void *)((unsigned long)&task->thread.ctx_fp + FP_REG(fp_regno, vector_regno)); + fno = (regno - VECREG_BASE) & 0x1f; + vno = 1 + ((regno - VECREG_BASE) >> 5); + addr = &task->thread.fpstate.fp[fno].v[vno]; break; case FPCR: - addr = (void *)&task->thread.fpcr; + addr = &task->thread.fpstate.fpcr; break; case PC: addr = (void *)task_pt_regs(task) + PT_REGS_PC; @@ -322,17 +319,9 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset, struct membuf to) { - int ret; - struct user_fpsimd_state uregs; - - memcpy(uregs.vregs, &target->thread.ctx_fp, - sizeof(struct context_fpregs)); - - uregs.fpcr = target->thread.fpcr; - - ret = membuf_write(&to, &uregs, sizeof(uregs)); - return ret; + return membuf_write(&to, &target->thread.fpstate, + sizeof(struct user_fpsimd_state)); } static int fpr_set(struct task_struct *target, @@ -340,21 +329,9 @@ static int fpr_set(struct task_struct *target, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { - int ret; - struct user_fpsimd_state uregs; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - &uregs, 0, sizeof(uregs)); - - if (ret) - return ret; - - memcpy(&target->thread.ctx_fp, uregs.vregs, - sizeof(struct context_fpregs)); - - target->thread.fpcr = uregs.fpcr; - - return ret; + return user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &target->thread.fpstate, 0, + sizeof(struct user_fpsimd_state)); } enum sw64_regset { diff --git a/arch/sw_64/kernel/signal.c b/arch/sw_64/kernel/signal.c index 887326812624..6a6203ccb04f 100644 --- a/arch/sw_64/kernel/signal.c +++ b/arch/sw_64/kernel/signal.c @@ -100,9 +100,10 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) err |= __get_user(usp, sc->sc_regs+30); wrusp(usp); /* simd-fp */ - err |= __copy_from_user(¤t->thread.ctx_fp, - &sc->sc_fpregs, sizeof(struct context_fpregs)); - err |= __get_user(current->thread.fpcr, &sc->sc_fpcr); + err |= __copy_from_user(¤t->thread.fpstate, &sc->sc_fpregs, + offsetof(struct user_fpsimd_state, fpcr)); + err |= __get_user(current->thread.fpstate.fpcr, &sc->sc_fpcr); + if (likely(!err)) __fpstate_restore(current); @@ -230,9 +231,9 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, err |= __put_user(0, sc->sc_regs+31); /* simd-fp */ __fpstate_save(current); - err |= __copy_to_user(&sc->sc_fpregs, - ¤t->thread.ctx_fp, sizeof(struct context_fpregs)); - err |= __put_user(current->thread.fpcr, &sc->sc_fpcr); + err |= __copy_to_user(&sc->sc_fpregs, ¤t->thread.fpstate, + offsetof(struct user_fpsimd_state, fpcr)); + err |= __put_user(current->thread.fpstate.fpcr, &sc->sc_fpcr); err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0); err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1); diff --git a/arch/sw_64/kvm/entry.S b/arch/sw_64/kvm/entry.S index 1e089da5378e..0c02b68ee7d0 100644 --- a/arch/sw_64/kvm/entry.S +++ b/arch/sw_64/kvm/entry.S @@ -15,18 +15,16 @@ ENTRY(__sw64_vcpu_run) /* save host fpregs */ ldl $1, TI_TASK($8) - ldi $1, TASK_THREAD($1) rfpcr $f0 - fstd $f0, THREAD_FPCR($1) - ldi $1, THREAD_CTX_FP($1) - vstd $f2, CTX_FP_F2($1) - vstd $f3, CTX_FP_F3($1) - vstd $f4, CTX_FP_F4($1) - vstd $f5, CTX_FP_F5($1) - vstd $f6, CTX_FP_F6($1) - vstd $f7, CTX_FP_F7($1) - vstd $f8, CTX_FP_F8($1) - vstd $f9, CTX_FP_F9($1) + fstd $f0, TASK_THREAD_FPCR($1) + vstd $f2, TASK_THREAD_F2($1) + vstd $f3, TASK_THREAD_F3($1) + vstd $f4, TASK_THREAD_F4($1) + vstd $f5, TASK_THREAD_F5($1) + vstd $f6, TASK_THREAD_F6($1) + vstd $f7, TASK_THREAD_F7($1) + vstd $f8, TASK_THREAD_F8($1) + vstd $f9, TASK_THREAD_F9($1) ldi sp, -VCPU_RET_SIZE(sp) /* r16 = guest kvm_vcpu_arch.vcb struct pointer */ @@ -213,8 +211,7 @@ $g_setfpec_over: bic sp, $8, $8 /* restore host fpregs */ ldl $1, TI_TASK($8) - ldi $1, TASK_THREAD($1) - fldd $f0, THREAD_FPCR($1) + fldd $f0, TASK_THREAD_FPCR($1) wfpcr $f0 fimovd $f0, $2 and $2, 0x3, $2 @@ -234,15 +231,14 @@ $setfpec_1: $setfpec_2: setfpec2 $setfpec_over: - ldi $1, THREAD_CTX_FP($1) - vldd $f2, CTX_FP_F2($1) - vldd $f3, CTX_FP_F3($1) - vldd $f4, CTX_FP_F4($1) - vldd $f5, CTX_FP_F5($1) - vldd $f6, CTX_FP_F6($1) - vldd $f7, CTX_FP_F7($1) - vldd $f8, CTX_FP_F8($1) - vldd $f9, CTX_FP_F9($1) + vldd $f2, TASK_THREAD_F2($1) + vldd $f3, TASK_THREAD_F3($1) + vldd $f4, TASK_THREAD_F4($1) + vldd $f5, TASK_THREAD_F5($1) + vldd $f6, TASK_THREAD_F6($1) + vldd $f7, TASK_THREAD_F7($1) + vldd $f8, TASK_THREAD_F8($1) + vldd $f9, TASK_THREAD_F9($1) /* if $0 > 0, handle hcall */ bgt $0, $ret_to -- Gitee From 6a2490239e1f86c8009ab192e2361aa4f911da2e Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 27 May 2022 10:01:54 +0800 Subject: [PATCH 44/71] sw64: fix ptrace.h with types.h and NOT __ASSEMBLY__ Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- It may report compile errors on some user apps if linux/types.h is nowhere to be included. And a __ASSEMBLY__ guard makes it work if included by assembly codes. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/uapi/asm/ptrace.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/sw_64/include/uapi/asm/ptrace.h b/arch/sw_64/include/uapi/asm/ptrace.h index a45b10b8914a..80bad067fc15 100644 --- a/arch/sw_64/include/uapi/asm/ptrace.h +++ b/arch/sw_64/include/uapi/asm/ptrace.h @@ -2,6 +2,9 @@ #ifndef _UAPI_ASM_SW64_PTRACE_H #define _UAPI_ASM_SW64_PTRACE_H +#include + +#ifndef __ASSEMBLY__ /* * User structures for general purpose, floating point and debug registers. */ @@ -21,6 +24,7 @@ struct user_fpsimd_state { __u64 fpcr; __u64 __reserved[3]; }; +#endif /* PTRACE_ATTACH is 16 */ /* PTRACE_DETACH is 17 */ -- Gitee From 9941c328d6527b408479f70e782a40c706c277d1 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Fri, 27 May 2022 10:09:44 +0800 Subject: [PATCH 45/71] sw64: rewrite elf core copy interfaces Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- For gpreg, simplify dump method to make it easier to maintain. For fpreg, redefine elf_fpregset_t with struct user_fpsimd_state and add a arch-specific dump_fpu() method. Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/elf.h | 34 +++++-------------- arch/sw_64/kernel/process.c | 66 ++++++++---------------------------- 2 files changed, 23 insertions(+), 77 deletions(-) diff --git a/arch/sw_64/include/asm/elf.h b/arch/sw_64/include/asm/elf.h index abecc5653eba..8c858cff5573 100644 --- a/arch/sw_64/include/asm/elf.h +++ b/arch/sw_64/include/asm/elf.h @@ -55,23 +55,18 @@ #define EF_SW64_32BIT 1 /* All addresses are below 2GB */ /* - * ELF register definitions.. - */ - -/* - * The legacy version of makes gregset_t 46 entries long. - * I have no idea why that is so. For now, we just leave it at 33 - * (32 general regs + processor status word). + * ELF register definitions. + * + * For now, we just leave it at 33 (32 general regs + processor status word). */ #define ELF_NGREG 33 -#define ELF_NFPREG 32 - typedef unsigned long elf_greg_t; typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -typedef double elf_fpreg_t; -typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; +/* Same with user_fpsimd_state */ +#include +typedef struct user_fpsimd_state elf_fpregset_t; /* * This is used to ensure we don't load something for the wrong architecture. @@ -121,22 +116,9 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm, #ifdef __KERNEL__ struct pt_regs; -struct thread_info; struct task_struct; -extern void dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, - struct thread_info *ti); -#define ELF_CORE_COPY_REGS(DEST, REGS) \ - dump_elf_thread(DEST, REGS, current_thread_info()); - -/* Similar, but for a thread other than current. */ - -extern int dump_elf_task(elf_greg_t *dest, struct task_struct *task); -#define ELF_CORE_COPY_TASK_REGS(TASK, DEST) dump_elf_task(*(DEST), TASK) - -/* Similar, but for the FP registers. */ - -extern int dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task); -#define ELF_CORE_COPY_FPREGS(TASK, DEST) dump_elf_task_fp(*(DEST), TASK) +extern void sw64_elf_core_copy_regs(elf_greg_t *dest, struct pt_regs *pt); +#define ELF_CORE_COPY_REGS(DEST, REGS) sw64_elf_core_copy_regs(DEST, REGS); /* * This yields a mask that user programs can use to figure out what diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index 308675d29c04..7a7578d530c6 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -200,66 +200,30 @@ copy_thread(unsigned long clone_flags, unsigned long usp, /* * Fill in the user structure for a ELF core dump. + * @regs: should be signal_pt_regs() or task_pt_reg(task) */ -void -dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti) +void sw64_elf_core_copy_regs(elf_greg_t *dest, struct pt_regs *regs) { - dest[0] = pt->r0; - dest[1] = pt->r1; - dest[2] = pt->r2; - dest[3] = pt->r3; - dest[4] = pt->r4; - dest[5] = pt->r5; - dest[6] = pt->r6; - dest[7] = pt->r7; - dest[8] = pt->r8; - dest[9] = pt->r9; - dest[10] = pt->r10; - dest[11] = pt->r11; - dest[12] = pt->r12; - dest[13] = pt->r13; - dest[14] = pt->r14; - dest[15] = pt->r15; - dest[16] = pt->r16; - dest[17] = pt->r17; - dest[18] = pt->r18; - dest[19] = pt->r19; - dest[20] = pt->r20; - dest[21] = pt->r21; - dest[22] = pt->r22; - dest[23] = pt->r23; - dest[24] = pt->r24; - dest[25] = pt->r25; - dest[26] = pt->r26; - dest[27] = pt->r27; - dest[28] = pt->r28; - dest[29] = pt->gp; - dest[30] = ti == current_thread_info() ? rdusp() : ti->pcb.usp; - dest[31] = pt->pc; + int i; + struct thread_info *ti; - /* Once upon a time this was the PS value. Which is stupid - * since that is always 8 for usermode. Usurped for the more - * useful value of the thread's UNIQUE field. - */ - dest[32] = ti->pcb.unique; -} -EXPORT_SYMBOL(dump_elf_thread); + ti = (void *)((__u64)regs & ~(THREAD_SIZE - 1)); -int -dump_elf_task(elf_greg_t *dest, struct task_struct *task) -{ - dump_elf_thread(dest, task_pt_regs(task), task_thread_info(task)); - return 1; + for (i = 0; i < 30; i++) + dest[i] = *(__u64 *)((void *)regs + regoffsets[i]); + dest[30] = ti == current_thread_info() ? rdusp() : ti->pcb.usp; + dest[31] = regs->pc; + dest[32] = ti->pcb.unique; } -EXPORT_SYMBOL(dump_elf_task); +EXPORT_SYMBOL(sw64_elf_core_copy_regs); -int -dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task) +/* Fill in the fpu structure for a core dump. */ +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) { - memcpy(dest, &task->thread.fpstate, 32 * 8); + memcpy(fpu, ¤t->thread.fpstate, sizeof(*fpu)); return 1; } -EXPORT_SYMBOL(dump_elf_task_fp); +EXPORT_SYMBOL(dump_fpu); /* * Under heavy swap load I've seen this lose in an ugly way. So do -- Gitee From 4c651be01d70a2c0e3c6ac2c2821eac775f85aaa Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Tue, 31 May 2022 09:48:40 +0800 Subject: [PATCH 46/71] sw64: perf: add fp based stack trace support Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56X48 -------------------------------- It used to obtain return address of function by scanning entire stack which lead to inaccurate result. This patch adds fp based stack trace support to improve efficiency and accuracy. Because toolchain is not ready yet, we take CONFIG_FRAME_POINTER to activate this support, and it should be disabled by default. Signed-off-by: Wu Liliu Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/stacktrace.h | 72 +++++++++++++++++++++++++ arch/sw_64/kernel/perf_event.c | 66 +++++++++++++++++++---- arch/sw_64/kernel/stacktrace.c | 83 +++++++++++++++++++++++++++++ 3 files changed, 210 insertions(+), 11 deletions(-) create mode 100644 arch/sw_64/include/asm/stacktrace.h diff --git a/arch/sw_64/include/asm/stacktrace.h b/arch/sw_64/include/asm/stacktrace.h new file mode 100644 index 000000000000..813aa5e7a91d --- /dev/null +++ b/arch/sw_64/include/asm/stacktrace.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _ASM_SW64_STACKTRACE_H +#define _ASM_SW64_STACKTRACE_H + +#include +#include +#include +#include +#include + +struct stackframe { + unsigned long pc; + unsigned long fp; +}; + +enum stack_type { + STACK_TYPE_UNKNOWN, + STACK_TYPE_TASK, +}; + +struct stack_info { + unsigned long low; + unsigned long high; + enum stack_type type; +}; + +/* The form of the top of the frame on the stack */ +struct stack_frame { + unsigned long return_address; + struct stack_frame *next_frame; +}; + +extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame); +extern void walk_stackframe(struct task_struct *tsk, struct stackframe *frame, + int (*fn)(struct stackframe *, void *), void *data); + +static inline bool on_task_stack(struct task_struct *tsk, unsigned long sp, + struct stack_info *info) +{ + unsigned long low = (unsigned long)task_stack_page(tsk); + unsigned long high = low + THREAD_SIZE; + + if (sp < low || sp >= high) + return false; + + if (info) { + info->low = low; + info->high = high; + info->type = STACK_TYPE_TASK; + } + + return true; +} + +/* + * We can only safely access per-cpu stacks from current in a non-preemptible + * context. + */ +static inline bool on_accessible_stack(struct task_struct *tsk, + unsigned long sp, + struct stack_info *info) +{ + if (on_task_stack(tsk, sp, info)) + return true; + if (tsk != current || preemptible()) + return false; + + return false; +} + +#endif /* _ASM_SW64_STACKTRACE_H */ diff --git a/arch/sw_64/kernel/perf_event.c b/arch/sw_64/kernel/perf_event.c index 0d49224ba058..70f1f2781016 100644 --- a/arch/sw_64/kernel/perf_event.c +++ b/arch/sw_64/kernel/perf_event.c @@ -6,6 +6,7 @@ */ #include +#include /* For tracking PMCs and the hw events they monitor on each CPU. */ struct cpu_hw_events { @@ -247,10 +248,9 @@ static const struct sw64_perf_event *core3_map_cache_event(u64 config) */ static bool core3_raw_event_valid(u64 config) { - if ((config >= (PC0_RAW_BASE + PC0_MIN) && config <= (PC0_RAW_BASE + PC0_MAX)) || - (config >= (PC1_RAW_BASE + PC1_MIN) && config <= (PC1_RAW_BASE + PC1_MAX))) { + if ((config >= PC0_RAW_BASE && config <= (PC0_RAW_BASE + PC0_MAX)) || + (config >= PC1_RAW_BASE && config <= (PC1_RAW_BASE + PC1_MAX))) return true; - } pr_info("sw64 pmu: invalid raw event config %#llx\n", config); return false; @@ -697,6 +697,36 @@ bool valid_dy_addr(unsigned long addr) return ret; } +#ifdef CONFIG_FRAME_POINTER +void perf_callchain_user(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) +{ + + struct stack_frame frame; + unsigned long __user *fp; + int err; + + perf_callchain_store(entry, regs->pc); + + fp = (unsigned long __user *)regs->r15; + + while (entry->nr < entry->max_stack && (unsigned long)fp < current->mm->start_stack) { + if (!access_ok(fp, sizeof(frame))) + break; + + pagefault_disable(); + err = __copy_from_user_inatomic(&frame, fp, sizeof(frame)); + pagefault_enable(); + + if (err) + break; + + if (valid_utext_addr(frame.return_address) || valid_dy_addr(frame.return_address)) + perf_callchain_store(entry, frame.return_address); + fp = (void __user *)frame.next_frame; + } +} +#else /* !CONFIG_FRAME_POINTER */ void perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) { @@ -709,30 +739,44 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry, while (entry->nr < entry->max_stack && usp < current->mm->start_stack) { if (!access_ok(usp, 8)) break; + pagefault_disable(); err = __get_user(user_addr, (unsigned long *)usp); pagefault_enable(); + if (err) break; + if (valid_utext_addr(user_addr) || valid_dy_addr(user_addr)) perf_callchain_store(entry, user_addr); usp = usp + 8; } } +#endif/* CONFIG_FRAME_POINTER */ + +/* + * Gets called by walk_stackframe() for every stackframe. This will be called + * whist unwinding the stackframe and is like a subroutine return so we use + * the PC. + */ +static int callchain_trace(struct stackframe *frame, void *data) +{ + struct perf_callchain_entry_ctx *entry = data; + + perf_callchain_store(entry, frame->pc); + + return 0; +} void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) { - unsigned long *sp = (unsigned long *)current_thread_info()->pcb.ksp; - unsigned long addr; + struct stackframe frame; - perf_callchain_store(entry, regs->pc); + frame.fp = regs->r15; + frame.pc = regs->pc; - while (!kstack_end(sp) && entry->nr < entry->max_stack) { - addr = *sp++; - if (__kernel_text_address(addr)) - perf_callchain_store(entry, addr); - } + walk_stackframe(current, &frame, callchain_trace, entry); } /* diff --git a/arch/sw_64/kernel/stacktrace.c b/arch/sw_64/kernel/stacktrace.c index 41cdff5b4941..2671331717ba 100644 --- a/arch/sw_64/kernel/stacktrace.c +++ b/arch/sw_64/kernel/stacktrace.c @@ -8,7 +8,90 @@ #include #include #include +#include +#include +#include +/* + * sw_64 PCS assigns the frame pointer to r15. + * + * A simple function prologue looks like this: + * ldi sp,-xx(sp) + * stl ra,0(sp) + * stl fp,8(sp) + * mov sp,fp + * + * A simple function epilogue looks like this: + * mov fp,sp + * ldl ra,0(sp) + * ldl fp,8(sp) + * ldi sp,+xx(sp) + */ + +#ifdef CONFIG_FRAME_POINTER + +int unwind_frame(struct task_struct *tsk, struct stackframe *frame) +{ + unsigned long fp = frame->fp; + + if (fp & 0x7) + return -EINVAL; + + if (!tsk) + tsk = current; + + if (!on_accessible_stack(tsk, fp, NULL)) + return -EINVAL; + + frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); + frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8)); + + /* + * Frames created upon entry from user have NULL FP and PC values, so + * don't bother reporting these. Frames created by __noreturn functions + * might have a valid FP even if PC is bogus, so only terminate where + * both are NULL. + */ + if (!frame->fp && !frame->pc) + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL_GPL(unwind_frame); + +void walk_stackframe(struct task_struct *tsk, struct stackframe *frame, + int (*fn)(struct stackframe *, void *), void *data) +{ + while (1) { + int ret; + + if (fn(frame, data)) + break; + ret = unwind_frame(tsk, frame); + if (ret < 0) + break; + } +} +EXPORT_SYMBOL_GPL(walk_stackframe); + +#else /* !CONFIG_FRAME_POINTER */ +void walk_stackframe(struct task_struct *tsk, struct stackframe *frame, + int (*fn)(struct stackframe *, void *), void *data) +{ + unsigned long *sp = (unsigned long *)current_thread_info()->pcb.ksp; + unsigned long addr; + struct perf_callchain_entry_ctx *entry = data; + + perf_callchain_store(entry, frame->pc); + while (!kstack_end(sp) && entry->nr < entry->max_stack) { + addr = *sp++; + if (__kernel_text_address(addr)) + perf_callchain_store(entry, addr); + } +} +EXPORT_SYMBOL_GPL(walk_stackframe); + +#endif/* CONFIG_FRAME_POINTER */ /* * Save stack-backtrace addresses into a stack_trace buffer. -- Gitee From 42518209c039862f32068aeee497621aaac776ed Mon Sep 17 00:00:00 2001 From: Xu Chenjiao Date: Tue, 31 May 2022 14:11:10 +0800 Subject: [PATCH 47/71] sw64: fix compile errors for NOT chip3 Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I56QAM -------------------------------- IO register DEVINT_WKEN, DEVINTWK_INTEN, PME_ENABLE_INTD_CORE0 and AER_ENABLE_INTD_CORE0 are only defined in chip3. This will lead to compile errors if other chip is selected. To avoid these errors, we define default set_devint_wken() and set_pcieport_service_irq() as weak symbols. Signed-off-by: Xu Chenjiao Signed-off-by: Gu Zitao --- arch/sw_64/chip/chip3/chip.c | 16 ++++++++++++++++ arch/sw_64/kernel/pci.c | 15 ++++----------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/arch/sw_64/chip/chip3/chip.c b/arch/sw_64/chip/chip3/chip.c index acd25fe99669..b73afc9c62ac 100644 --- a/arch/sw_64/chip/chip3/chip.c +++ b/arch/sw_64/chip/chip3/chip.c @@ -90,6 +90,22 @@ void setup_chip_clocksource(void) #endif } +void set_devint_wken(int node) +{ + unsigned long val; + + /* enable INTD wakeup */ + val = 0x80; + sw64_io_write(node, DEVINT_WKEN, val); + sw64_io_write(node, DEVINTWK_INTEN, val); +} + +void set_pcieport_service_irq(int node, int index) +{ + write_piu_ior0(node, index, PMEINTCONFIG, PME_ENABLE_INTD_CORE0); + write_piu_ior0(node, index, AERERRINTCONFIG, AER_ENABLE_INTD_CORE0); +} + static int chip3_get_cpu_nums(void) { unsigned long trkmode; diff --git a/arch/sw_64/kernel/pci.c b/arch/sw_64/kernel/pci.c index 401ee0b781be..a004ea9fde7f 100644 --- a/arch/sw_64/kernel/pci.c +++ b/arch/sw_64/kernel/pci.c @@ -600,15 +600,7 @@ sw64_init_host(unsigned long node, unsigned long index) } } -static void set_devint_wken(int node) -{ - unsigned long val; - - /* enable INTD wakeup */ - val = 0x80; - sw64_io_write(node, DEVINT_WKEN, val); - sw64_io_write(node, DEVINTWK_INTEN, val); -} +void __weak set_devint_wken(int node) {} void __init sw64_init_arch(void) { @@ -651,6 +643,8 @@ void __init sw64_init_arch(void) } } +void __weak set_pcieport_service_irq(int node, int index) {} + static void __init sw64_init_intx(struct pci_controller *hose) { unsigned long int_conf, node, val_node; @@ -679,8 +673,7 @@ static void __init sw64_init_intx(struct pci_controller *hose) if (sw64_chip_init->pci_init.set_intx) sw64_chip_init->pci_init.set_intx(node, index, int_conf); - write_piu_ior0(node, index, PMEINTCONFIG, PME_ENABLE_INTD_CORE0); - write_piu_ior0(node, index, AERERRINTCONFIG, AER_ENABLE_INTD_CORE0); + set_pcieport_service_irq(node, index); } void __init sw64_init_irq(void) -- Gitee From afe00ca0c338c3a0828cc835f249e4b11906b632 Mon Sep 17 00:00:00 2001 From: Xiong Aifei Date: Mon, 6 Jun 2022 15:24:44 +0800 Subject: [PATCH 48/71] sw64: gpu: correct low-level mmio memset/memcpy direct calls Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GDKC -------------------------------- Driver codes of the direct calls, via the SIMD-optimized memset and memcpy functions, may raise DFAULT when using RX580 or R7 Series graphics card on sw64, so work around 'memset' references to '_memset_c_io' and 'memcpy' to 'memcpy_fromio'. Signed-off-by: Xiong Aifei Signed-off-by: Gu Zitao --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 12 ++++++++++++ drivers/gpu/drm/radeon/vce_v1_0.c | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index c36258d56b44..851d64e83166 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -1354,7 +1354,11 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev) return r; } +#if IS_ENABLED(CONFIG_SW64) + _memset_c_io(hpd, 0, mec_hpd_size); +#else memset(hpd, 0, mec_hpd_size); +#endif amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); @@ -4649,7 +4653,11 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) vi_srbm_select(adev, 0, 0, 0, 0); mutex_unlock(&adev->srbm_mutex); } else { +#if IS_ENABLED(CONFIG_SW64) + _memset_c_io((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); +#else memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); +#endif ((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; mutex_lock(&adev->srbm_mutex); @@ -4660,7 +4668,11 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); if (adev->gfx.mec.mqd_backup[mqd_idx]) +#if IS_ENABLED(CONFIG_SW64) + memcpy_fromio(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct vi_mqd_allocation)); +#else memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct vi_mqd_allocation)); +#endif } return 0; diff --git a/drivers/gpu/drm/radeon/vce_v1_0.c b/drivers/gpu/drm/radeon/vce_v1_0.c index bd75bbcf5bf6..fbd8a5d9a691 100644 --- a/drivers/gpu/drm/radeon/vce_v1_0.c +++ b/drivers/gpu/drm/radeon/vce_v1_0.c @@ -193,8 +193,13 @@ int vce_v1_0_load_fw(struct radeon_device *rdev, uint32_t *data) data[3] = sign->val[i].nonce[3]; data[4] = cpu_to_le32(le32_to_cpu(sign->len) + 64); +#if IS_ENABLED(CONFIG_SW64) + memset_io(&data[5], 0, 44); + memcpy_toio(&data[16], &sign[1], rdev->vce_fw->size - sizeof(*sign)); +#else memset(&data[5], 0, 44); memcpy(&data[16], &sign[1], rdev->vce_fw->size - sizeof(*sign)); +#endif data += (le32_to_cpu(sign->len) + 64) / 4; data[0] = sign->val[i].sigval[0]; -- Gitee From 852e6489f5d399a75ad6e755e60e9312a2e4300e Mon Sep 17 00:00:00 2001 From: Xu Chenjiao Date: Mon, 6 Jun 2022 16:50:04 +0800 Subject: [PATCH 49/71] sw64: pcie: fix lack of PME and AER interrupt service routines Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I56XUF -------------------------------- On SW64 platform, we used to enable PME and AER interrupt by default, however, there is a risk that no body cares the interrupt routine when CONFIG_PCIE_PME=n or CONFIG_PCIEAER=n. So let's fix this problem. Signed-off-by: Xu Chenjiao Signed-off-by: Gu Zitao --- arch/sw_64/chip/chip3/chip.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/arch/sw_64/chip/chip3/chip.c b/arch/sw_64/chip/chip3/chip.c index b73afc9c62ac..2103d93a53a2 100644 --- a/arch/sw_64/chip/chip3/chip.c +++ b/arch/sw_64/chip/chip3/chip.c @@ -102,8 +102,11 @@ void set_devint_wken(int node) void set_pcieport_service_irq(int node, int index) { - write_piu_ior0(node, index, PMEINTCONFIG, PME_ENABLE_INTD_CORE0); - write_piu_ior0(node, index, AERERRINTCONFIG, AER_ENABLE_INTD_CORE0); + if (IS_ENABLED(CONFIG_PCIE_PME)) + write_piu_ior0(node, index, PMEINTCONFIG, PME_ENABLE_INTD_CORE0); + + if (IS_ENABLED(CONFIG_PCIEAER)) + write_piu_ior0(node, index, AERERRINTCONFIG, AER_ENABLE_INTD_CORE0); } static int chip3_get_cpu_nums(void) @@ -438,7 +441,7 @@ extern struct pci_controller *hose_head, **hose_tail; static void sw6_handle_intx(unsigned int offset) { struct pci_controller *hose; - unsigned long value, pme_value, aer_value; + unsigned long value; hose = hose_head; for (hose = hose_head; hose; hose = hose->next) { @@ -451,15 +454,20 @@ static void sw6_handle_intx(unsigned int offset) write_piu_ior0(hose->node, hose->index, INTACONFIG + (offset << 7), value); } - pme_value = read_piu_ior0(hose->node, hose->index, PMEINTCONFIG); - aer_value = read_piu_ior0(hose->node, hose->index, AERERRINTCONFIG); - if ((pme_value >> 63) || (aer_value >> 63)) { - handle_irq(hose->service_irq); + if (IS_ENABLED(CONFIG_PCIE_PME)) { + value = read_piu_ior0(hose->node, hose->index, PMEINTCONFIG); + if (value >> 63) { + handle_irq(hose->service_irq); + write_piu_ior0(hose->node, hose->index, PMEINTCONFIG, value); + } + } - if (pme_value >> 63) - write_piu_ior0(hose->node, hose->index, PMEINTCONFIG, pme_value); - if (aer_value >> 63) - write_piu_ior0(hose->node, hose->index, AERERRINTCONFIG, aer_value); + if (IS_ENABLED(CONFIG_PCIEAER)) { + value = read_piu_ior0(hose->node, hose->index, AERERRINTCONFIG); + if (value >> 63) { + handle_irq(hose->service_irq); + write_piu_ior0(hose->node, hose->index, AERERRINTCONFIG, value); + } } if (hose->iommu_enable) { -- Gitee From e41f34b561b8485031080a07c2e19f22dceb06da Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Wed, 15 Jun 2022 16:54:25 +0800 Subject: [PATCH 50/71] sw64: fix dma features for zx200 Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I56OSP -------------------------------- The device controllers of ZX200 chipset are all the 32-bit DMA capable device, so we add pci quirk function hook to set dev.bus_dma_limit to DMA_BIT_MASK(32) for all devices on the chipset, besides when CONFIG_SUNWAY_IOMMU=n, all these devices will use swiotlb dma_ops. Signed-off-by: Zheng Chongzhen Signed-off-by: Gu Zitao --- arch/sw_64/kernel/pci.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/sw_64/kernel/pci.c b/arch/sw_64/kernel/pci.c index a004ea9fde7f..7cc8b7d2d43b 100644 --- a/arch/sw_64/kernel/pci.c +++ b/arch/sw_64/kernel/pci.c @@ -691,3 +691,16 @@ sw64_init_pci(void) { common_init_pci(); } + +static int setup_bus_dma_cb(struct pci_dev *pdev, void *data) +{ + pdev->dev.bus_dma_limit = DMA_BIT_MASK(32); + return 0; +} + +static void fix_bus_dma_limit(struct pci_dev *dev) +{ + pci_walk_bus(dev->subordinate, setup_bus_dma_cb, NULL); + pr_info("Set zx200 bus_dma_limit to 32-bit\n"); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ZHAOXIN, 0x071f, fix_bus_dma_limit); -- Gitee From aadce49276fe3cb5d65f9bd932522f5ac069564b Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Wed, 15 Jun 2022 17:40:59 +0800 Subject: [PATCH 51/71] sw64: iommu: fix iommu interrupt handler Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I56OSP -------------------------------- When porting ZX200 chipset driver on SW64 platform, we meet an IOMMU exception show as follows: iommu_interrupt, iommu_status = 0xc8014000dffe0000, devid 0xa00, dva 0xdffe0000, 1Unable to handle kernel paging request at virtual address 0000000000000040 CPU 0 swapper/0(0): Oops 0 pc = [] ra = [] ps = 0001 Not tainted pc is at iommu_interrupt+0x140/0x3e0 ra is at iommu_interrupt+0xe4/0x3e0 v0 = 0000000000000051 t0 = c8014000dffe0000 t1 = 0000000000000000 t2 = 0000000000000000 t3 = 0000000000000000 t4 = 0000000000000001 t5 = 0000000000000001 t6 = 0000000000000000 t7 = ffffffff82948000 s0 = fff00003ffff0400 s1 = 0000000000000001 s2 = 0000000000000a00 s3 = 0000000000000a00 s4 = 00000000dffe0000 s5 = fff0000100680e80 s6 = ffffffff8294ba70 a0 = 0000000000000001 a1 = 0000000000000001 a2 = ffffffff8294b790 a3 = ffffffff8294b7a8 a4 = 0000000000000000 a5 = ffffffff82c5fb7a t8 = 0000000000000001 t9 = fffffffffffcac48 t10 = 0000000000000000 t11= 0000000000000000 pv = ffffffff809f4f10 at = ffffffff82bff6c0 gp = ffffffff82c1f510 sp = (____ptrval____) The root cause is that the device which raises iommu exception is not in the device list, then reference a null sdev will cause a page fualt. To work around this problem, we apply this patch by just clearing IOMMUEXCPT_STATUS and then go on. BTW, why the device raise IOMMU exception is not a valid device ID, it's a puzzling problem. Signed-off-by: Zheng Chongzhen Signed-off-by: Gu Zitao --- drivers/iommu/sw64/sunway_iommu.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/sw64/sunway_iommu.c b/drivers/iommu/sw64/sunway_iommu.c index 5797adf8fbc5..b6c8f1272d28 100644 --- a/drivers/iommu/sw64/sunway_iommu.c +++ b/drivers/iommu/sw64/sunway_iommu.c @@ -648,10 +648,21 @@ irqreturn_t iommu_interrupt(int irq, void *dev) type = (iommu_status >> 59) & 0x7; devid = (iommu_status >> 37) & 0xffff; dva = iommu_status & 0xffffffff; - sdev = search_dev_data(devid); - sdomain = sdev->domain; pr_info("%s, iommu_status = %#lx, devid %#lx, dva %#lx, ", __func__, iommu_status, devid, dva); + + sdev = search_dev_data(devid); + if (sdev == NULL) { + pr_info("no such dev!!!\n"); + + iommu_status &= ~(1UL << 62); + write_piu_ior0(hose->node, hose->index, + IOMMUEXCPT_STATUS, iommu_status); + + return IRQ_HANDLED; + } + + sdomain = sdev->domain; switch (type) { case DTE_LEVEL1: pr_info("invalid level1 dte, addr:%#lx, val:%#lx\n", @@ -674,7 +685,6 @@ irqreturn_t iommu_interrupt(int irq, void *dev) fetch_pte(sdomain, dva, PTE_LEVEL2_VAL)); iommu_status &= ~(1UL << 62); - iommu_status = iommu_status | (1UL << 63); write_piu_ior0(hose->node, hose->index, IOMMUEXCPT_STATUS, iommu_status); break; -- Gitee From c1bf5440faf937aa402e5c08090537948dd99d60 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 7 Jun 2022 15:12:25 +0800 Subject: [PATCH 52/71] sw64: kvm: fix incorrect page_ref_count() call Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I56WV8 -------------------------------- The last page_ref_count() call will cause kernel panic if kvm memory pool is at the end of DRAM. This patch reorders the checks to avoid illegal atomic_read operation. Signed-off-by: Min Fanlei Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 4d39db5fb1ef..e20e215dd08a 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -1026,8 +1026,7 @@ static int __init sw64_kvm_pool_init(void) end_page = pfn_to_page((kvm_mem_base + kvm_mem_size - 1) >> PAGE_SHIFT); p = base_page; - while (page_ref_count(p) == 0 && - (unsigned long)p <= (unsigned long)end_page) { + while (p <= end_page && page_ref_count(p) == 0) { set_page_count(p, 1); page_mapcount_reset(p); SetPageReserved(p); -- Gitee From 3f5352084a8cc53cc8d555dcb20357138a37e276 Mon Sep 17 00:00:00 2001 From: Yang Qiang Date: Wed, 8 Jun 2022 09:35:37 +0800 Subject: [PATCH 53/71] sw64: dtb: check address validity with physical address Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GE5X -------------------------------- Due to sw64 ABI sepecification, a large kernel image may override the data structures of UEFI BIOS. To solve this problem, we have expanded UEFI BIOS to 1GB to make sure that runtime service code and data structures reside in the high address below 1GB which may be beyond ktext map. So fix it. Signed-off-by: Yang Qiang Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index e20e215dd08a..85d172c32239 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -560,22 +560,20 @@ static void __init setup_machine_fdt(void) #ifdef CONFIG_USE_OF void *dt_virt; const char *name; - unsigned long phys_addr; /* Give a chance to select kernel builtin DTB firstly */ if (IS_ENABLED(CONFIG_SW64_BUILTIN_DTB)) dt_virt = (void *)__dtb_start; else { dt_virt = (void *)sunway_boot_params->dtb_start; - if (dt_virt < (void *)__bss_stop) { + if (virt_to_phys(dt_virt) < virt_to_phys(__bss_stop)) { pr_emerg("BUG: DTB has been corrupted by kernel image!\n"); while (true) cpu_relax(); } } - phys_addr = __phys_addr((unsigned long)dt_virt); - if (!phys_addr_valid(phys_addr) || + if (!phys_addr_valid(virt_to_phys(dt_virt)) || !early_init_dt_scan(dt_virt)) { pr_crit("\n" "Error: invalid device tree blob at virtual address %px\n" -- Gitee From b9c01ee05c5fb17024d11bc058214f336718af3b Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Wed, 8 Jun 2022 09:38:24 +0800 Subject: [PATCH 54/71] sw64: perf: fix the number of supported raw events Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I56X48 -------------------------------- According to CORE3B core software interface manual, the performance counter PC_1 on sw64 supports event index up to 0x3d. Now fix it, and remove some unused macros from wrperfmon.h. Signed-off-by: He Chuyue Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/wrperfmon.h | 4 +--- arch/sw_64/kernel/perf_event.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/include/asm/wrperfmon.h b/arch/sw_64/include/asm/wrperfmon.h index 098702573bfc..15f7f6beb07c 100644 --- a/arch/sw_64/include/asm/wrperfmon.h +++ b/arch/sw_64/include/asm/wrperfmon.h @@ -33,10 +33,8 @@ #define PC0_RAW_BASE 0x0 #define PC1_RAW_BASE 0x100 -#define PC0_MIN 0x0 #define PC0_MAX 0xF -#define PC1_MIN 0x0 -#define PC1_MAX 0x37 +#define PC1_MAX 0x3D #define SW64_PERFCTRL_KM 2 #define SW64_PERFCTRL_UM 3 diff --git a/arch/sw_64/kernel/perf_event.c b/arch/sw_64/kernel/perf_event.c index 70f1f2781016..e9aae53a56f6 100644 --- a/arch/sw_64/kernel/perf_event.c +++ b/arch/sw_64/kernel/perf_event.c @@ -244,7 +244,7 @@ static const struct sw64_perf_event *core3_map_cache_event(u64 config) /* * r0xx for counter0, r1yy for counter1. - * According to the datasheet, 00 <= xx <= 0F, 00 <= yy <= 37 + * According to the datasheet, 00 <= xx <= 0F, 00 <= yy <= 3D */ static bool core3_raw_event_valid(u64 config) { -- Gitee From de13548b9a24e73d988b43fbad57f32cfb4adfd1 Mon Sep 17 00:00:00 2001 From: Zhu Donghong Date: Wed, 8 Jun 2022 09:49:30 +0800 Subject: [PATCH 55/71] drivers/irqchip: add sw64 interrupt controller support Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GDHC -------------------------------- Add a driver for the SW64 implementation of the CPU interrupt controller(INTC). In fact, the INTC is just a software simulated module to connect global interrupt sources to the local interrupt controller on each core. In addition, we rename irq-lpc.c and SW64_CHIP3_LPC config. Signed-off-by: Zhu Donghong Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 8 +- arch/sw_64/chip/chip3/Makefile | 1 - drivers/irqchip/Kconfig | 33 +++--- drivers/irqchip/Makefile | 4 +- drivers/irqchip/irq-intc-v1.c | 104 ------------------ .../irqchip/irq-sw64-intc-v2.c | 64 ++++++++++- .../{irq-lpc.c => irq-sw64-lpc-intc.c} | 0 7 files changed, 84 insertions(+), 130 deletions(-) delete mode 100644 drivers/irqchip/irq-intc-v1.c rename arch/sw_64/chip/chip3/irq_chip.c => drivers/irqchip/irq-sw64-intc-v2.c (59%) rename drivers/irqchip/{irq-lpc.c => irq-sw64-lpc-intc.c} (100%) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 0e32fc7e1f9a..ec6e583a5d9a 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -234,6 +234,7 @@ config PLATFORM_XUELANG depends on SW64_CHIP3 select SPARSE_IRQ select SYS_HAS_EARLY_PRINTK + select SW64_INTC_V2 help Sunway chip3 board chipset @@ -736,15 +737,10 @@ endmenu menu "Boot options" -config SW64_IRQ_CHIP - bool - config USE_OF bool "Flattened Device Tree support" - select GENERIC_IRQ_CHIP - select IRQ_DOMAIN - select SW64_IRQ_CHIP select OF + select IRQ_DOMAIN help Include support for flattened device tree machine descriptions. diff --git a/arch/sw_64/chip/chip3/Makefile b/arch/sw_64/chip/chip3/Makefile index 2b7b5790003f..ba0ab3f67f98 100644 --- a/arch/sw_64/chip/chip3/Makefile +++ b/arch/sw_64/chip/chip3/Makefile @@ -4,5 +4,4 @@ obj-y := chip.o i2c-lib.o obj-$(CONFIG_PCI) += pci-quirks.o obj-$(CONFIG_PCI_MSI) += msi.o vt_msi.o -obj-$(CONFIG_SW64_IRQ_CHIP) += irq_chip.o obj-$(CONFIG_CPUFREQ_DEBUGFS) += cpufreq_debugfs.o diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 5bf6cf60999b..dd35895c92f3 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -1,21 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only menu "IRQ chip support" -config SW64_INTC - bool "SW64 Platform-Level Interrupt Controller" - depends on ACPI && SW64 - help - This enables support for the INTC chip found in SW systems. - The INTC controls devices interrupts and connects them to each - core's local interrupt controller. - -config SW64_CHIP3_LPC - bool "SW64 Chip3 Buildin LPC Interrupt Controller" - depends on SW64_CHIP3 - help - This enables support for the LPC interrupt controller bultin in - on chip3 series. - config IRQCHIP def_bool y depends on OF_IRQ @@ -26,6 +11,24 @@ config ARM_GIC select GENERIC_IRQ_MULTI_HANDLER select GENERIC_IRQ_EFFECTIVE_AFF_MASK +config SW64_INTC_V2 + bool "SW64 Interrupt Controller V2" + depends on SW64_CHIP3 + default y + select GENERIC_IRQ_CHIP + select IRQ_DOMAIN + help + This enables support for the INTC chip found in SW CHIP3 systems. + The INTC controls devices interrupts and connects them to each + core's local interrupt controller. + +config SW64_LPC_INTC + bool "SW64 cpu builtin LPC Interrupt Controller" + depends on SW64_INTC_V2 + help + Say yes here to add support for the SW64 cpu builtin LPC + IRQ controller. + config ARM_GIC_PM bool depends on PM diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 78eb12ab4d4c..14a022c074ce 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -27,8 +27,8 @@ obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o -obj-$(CONFIG_SW64_INTC) += irq-intc-v1.o -obj-$(CONFIG_SW64_CHIP3_LPC) += irq-lpc.o +obj-$(CONFIG_SW64_INTC_V2) += irq-sw64-intc-v2.o +obj-$(CONFIG_SW64_LPC_INTC) += irq-sw64-lpc-intc.o obj-$(CONFIG_ARM_GIC_PM) += irq-gic-pm.o obj-$(CONFIG_ARCH_REALVIEW) += irq-gic-realview.o obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o diff --git a/drivers/irqchip/irq-intc-v1.c b/drivers/irqchip/irq-intc-v1.c deleted file mode 100644 index 4519e96526fb..000000000000 --- a/drivers/irqchip/irq-intc-v1.c +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -static void fake_irq_mask(struct irq_data *data) -{ -} - -static void fake_irq_unmask(struct irq_data *data) -{ -} - -static struct irq_chip onchip_intc = { - .name = "SW fake Intc", - .irq_mask = fake_irq_mask, - .irq_unmask = fake_irq_unmask, -}; - -static int sw_intc_domain_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hw) -{ - irq_set_chip_and_handler(irq, &onchip_intc, handle_level_irq); - irq_set_status_flags(irq, IRQ_LEVEL); - return 0; -} - -static const struct irq_domain_ops intc_irq_domain_ops = { - .xlate = irq_domain_xlate_onecell, - .map = sw_intc_domain_map, -}; - -#ifdef CONFIG_ACPI - -static int __init -intc_parse_madt(union acpi_subtable_headers *header, - const unsigned long end) -{ - struct acpi_madt_io_sapic *its_entry; - static struct irq_domain *root_domain; - int intc_irqs = 8, irq_base = NR_IRQS_LEGACY; - irq_hw_number_t hwirq_base = 0; - int irq_start = -1; - - its_entry = (struct acpi_madt_io_sapic *)header; - - intc_irqs -= hwirq_base; /* calculate # of irqs to allocate */ - - irq_base = irq_alloc_descs(irq_start, 16, intc_irqs, - numa_node_id()); - if (irq_base < 0) { - WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", - irq_start); - irq_base = irq_start; - } - - root_domain = irq_domain_add_legacy(NULL, intc_irqs, irq_base, - hwirq_base, &intc_irq_domain_ops, NULL); - - if (!root_domain) - pr_err("Failed to create irqdomain"); - - irq_set_default_host(root_domain); - - sw64_io_write(0, MCU_DVC_INT_EN, 0xff); - - return 0; -} - -static int __init acpi_intc_init(void) -{ - int count = 0; - - count = acpi_table_parse_madt(ACPI_MADT_TYPE_IO_SAPIC, - intc_parse_madt, 0); - - if (count <= 0) { - pr_err("No valid intc entries exist\n"); - return -EINVAL; - } - return 0; -} -#else -static int __init acpi_intc_init(void) -{ - return 0; -} -#endif - -static int __init intc_init(void) -{ - acpi_intc_init(); - - return 0; -} -subsys_initcall(intc_init); diff --git a/arch/sw_64/chip/chip3/irq_chip.c b/drivers/irqchip/irq-sw64-intc-v2.c similarity index 59% rename from arch/sw_64/chip/chip3/irq_chip.c rename to drivers/irqchip/irq-sw64-intc-v2.c index 24dfa1e1a898..8640c4aa9506 100644 --- a/arch/sw_64/chip/chip3/irq_chip.c +++ b/drivers/irqchip/irq-sw64-intc-v2.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 #include #include - -#include +#include +#include +#include +#include static void fake_irq_mask(struct irq_data *data) { @@ -32,6 +34,64 @@ static const struct irq_domain_ops sw64_intc_domain_ops = { .map = sw64_intc_domain_map, }; +static int __init +intc_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_io_sapic *its_entry; + static struct irq_domain *root_domain; + int intc_irqs = 8, irq_base = NR_IRQS_LEGACY; + irq_hw_number_t hwirq_base = 0; + int irq_start = -1; + + its_entry = (struct acpi_madt_io_sapic *)header; + + intc_irqs -= hwirq_base; /* calculate # of irqs to allocate */ + + irq_base = irq_alloc_descs(irq_start, 16, intc_irqs, + numa_node_id()); + if (irq_base < 0) { + WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", + irq_start); + irq_base = irq_start; + } + + root_domain = irq_domain_add_legacy(NULL, intc_irqs, irq_base, + hwirq_base, &sw64_intc_domain_ops, NULL); + + if (!root_domain) + pr_err("Failed to create irqdomain"); + + irq_set_default_host(root_domain); + + sw64_io_write(0, MCU_DVC_INT_EN, 0xff); + + return 0; +} + +static int __init acpi_intc_init(void) +{ + int count = 0; + + count = acpi_table_parse_madt(ACPI_MADT_TYPE_IO_SAPIC, + intc_parse_madt, 0); + + if (count <= 0) { + pr_err("No valid intc entries exist\n"); + return -EINVAL; + } + return 0; +} + +static int __init intc_init(void) +{ + acpi_intc_init(); + + return 0; +} + +subsys_initcall(intc_init); + static struct irq_domain *root_domain; static int __init diff --git a/drivers/irqchip/irq-lpc.c b/drivers/irqchip/irq-sw64-lpc-intc.c similarity index 100% rename from drivers/irqchip/irq-lpc.c rename to drivers/irqchip/irq-sw64-lpc-intc.c -- Gitee From 5384a3a3e7337b4953636b75c681ef0b0083ac0c Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Thu, 23 Jun 2022 14:11:05 +0800 Subject: [PATCH 56/71] sw64: fix __csum_and_copy when dest is not 8-byte aligned Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I56W9F -------------------------------- When destination is not 8-byte aligned, csum_partial_cfu_dest_unaligned() should be used to avoid kernel unaligned exception. Fixes: 2fcadd2861b4 ("sw64: optimize ip checksum calculation") Signed-off-by: Mao Minkai Signed-off-by: Gu Zitao --- arch/sw_64/lib/csum_partial_copy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/lib/csum_partial_copy.c b/arch/sw_64/lib/csum_partial_copy.c index 441ae5575de5..5e5274e82b2b 100644 --- a/arch/sw_64/lib/csum_partial_copy.c +++ b/arch/sw_64/lib/csum_partial_copy.c @@ -128,9 +128,9 @@ static __wsum __csum_and_copy(const void __user *src, void *dst, int len) (const unsigned long __user *) src, (unsigned long *) dst, len-8); } else { - checksum = csum_partial_cfu_dest_aligned( + checksum = csum_partial_cfu_dest_unaligned( (const unsigned long __user *) src, - (unsigned long *) dst, len-8); + (unsigned long *) dst, doff, len-8); } return (__force __wsum)from64to16(checksum); } -- Gitee From 12edb9430a3d902a0e8edb8c3d1489efda8205ad Mon Sep 17 00:00:00 2001 From: Xiong Aifei Date: Wed, 15 Jun 2022 16:36:00 +0800 Subject: [PATCH 57/71] sw64: gpu: replace '_memset_c_io' by 'memset_io' Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GDKC -------------------------------- Signed-off-by: Xiong Aifei Signed-off-by: Gu Zitao --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 4 ++-- drivers/gpu/drm/radeon/radeon_vce.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 851d64e83166..28c4e1fe5cd4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -1355,7 +1355,7 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev) } #if IS_ENABLED(CONFIG_SW64) - _memset_c_io(hpd, 0, mec_hpd_size); + memset_io(hpd, 0, mec_hpd_size); #else memset(hpd, 0, mec_hpd_size); #endif @@ -4654,7 +4654,7 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); } else { #if IS_ENABLED(CONFIG_SW64) - _memset_c_io((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); + memset_io((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); #else memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); #endif diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index 68cc5a347d3b..b9680d38d924 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c @@ -240,7 +240,7 @@ int radeon_vce_resume(struct radeon_device *rdev) } #ifdef __sw_64__ - _memset_c_io(cpu_addr, 0, radeon_bo_size(rdev->vce.vcpu_bo)); + memset_io(cpu_addr, 0, radeon_bo_size(rdev->vce.vcpu_bo)); #else memset(cpu_addr, 0, radeon_bo_size(rdev->vce.vcpu_bo)); #endif -- Gitee From fd62817c1d7a175e76ea65dbaeaa8bea72bfd012 Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Tue, 14 Jun 2022 16:40:12 +0800 Subject: [PATCH 58/71] sw64: perf: fix raw event count Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I56X48 -------------------------------- To read raw event count, perf stat calls sw64_pmu_start() to start the event and then calls sw64_perf_event_set_period() to set a new period to sample over. It used to initialize hwc.prev_count and PMC with different values and this will result in error sample values. To fix this problem, initialize them to 0 consistently. Signed-off-by: He Chuyue Signed-off-by: Gu Zitao --- arch/sw_64/kernel/perf_event.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/sw_64/kernel/perf_event.c b/arch/sw_64/kernel/perf_event.c index e9aae53a56f6..52ec34e33269 100644 --- a/arch/sw_64/kernel/perf_event.c +++ b/arch/sw_64/kernel/perf_event.c @@ -297,31 +297,33 @@ static int sw64_perf_event_set_period(struct perf_event *event, { long left = local64_read(&hwc->period_left); long period = hwc->sample_period; - int ret = 0; + int overflow = 0; + unsigned long value; if (unlikely(left <= -period)) { left = period; local64_set(&hwc->period_left, left); hwc->last_period = period; - ret = 1; + overflow = 1; } if (unlikely(left <= 0)) { left += period; local64_set(&hwc->period_left, left); hwc->last_period = period; - ret = 1; + overflow = 1; } if (left > (long)sw64_pmu->pmc_max_period) left = sw64_pmu->pmc_max_period; - local64_set(&hwc->prev_count, (unsigned long)(-left)); - sw64_write_pmc(idx, (unsigned long)(sw64_pmu->pmc_max_period - left)); + value = sw64_pmu->pmc_max_period - left; + local64_set(&hwc->prev_count, value); + sw64_write_pmc(idx, value); perf_event_update_userpage(event); - return ret; + return overflow; } /* -- Gitee From 248fac94e07c792a921d7f76c47f87c22b414ff6 Mon Sep 17 00:00:00 2001 From: Lu Feifei Date: Wed, 15 Jun 2022 14:59:23 +0800 Subject: [PATCH 59/71] sw64: add memhotplug support for guest os Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56WV8 -------------------------------- This patch introduces memory-hotplug support for guest os, and it should set CONFIG_KVM_MEMHOTLPUG=y on host to enable this feature. Currently, only 1GB memory-hotplug granularity is supported, and multiple granularity support will be implemented in the future. Signed-off-by: Lu Feifei Signed-off-by: Gu Zitao --- arch/sw_64/chip/chip3/chip.c | 5 + arch/sw_64/include/asm/hcall.h | 1 + arch/sw_64/include/asm/irq_impl.h | 1 + arch/sw_64/include/asm/kvm_asm.h | 3 + arch/sw_64/include/asm/kvm_host.h | 11 +- arch/sw_64/include/asm/memory.h | 1 + arch/sw_64/kvm/Kconfig | 7 + arch/sw_64/kvm/handle_exit.c | 5 + arch/sw_64/kvm/kvm-sw64.c | 113 ++++++++++++- arch/sw_64/mm/init.c | 9 ++ drivers/misc/Kconfig | 8 + drivers/misc/Makefile | 1 + drivers/misc/sunway-ged.c | 253 ++++++++++++++++++++++++++++++ 13 files changed, 410 insertions(+), 8 deletions(-) create mode 100644 drivers/misc/sunway-ged.c diff --git a/arch/sw_64/chip/chip3/chip.c b/arch/sw_64/chip/chip3/chip.c index 2103d93a53a2..02b369b2b37b 100644 --- a/arch/sw_64/chip/chip3/chip.c +++ b/arch/sw_64/chip/chip3/chip.c @@ -701,6 +701,11 @@ void handle_chip_irq(unsigned long type, unsigned long vector, handle_irq(type); set_irq_regs(old_regs); return; + case INT_VT_HOTPLUG: + old_regs = set_irq_regs(regs); + handle_irq(type); + set_irq_regs(old_regs); + return; case INT_PC0: perf_irq(PERFMON_PC0, regs); return; diff --git a/arch/sw_64/include/asm/hcall.h b/arch/sw_64/include/asm/hcall.h index 8117752b657e..b5438b477c87 100644 --- a/arch/sw_64/include/asm/hcall.h +++ b/arch/sw_64/include/asm/hcall.h @@ -18,6 +18,7 @@ enum HCALL_TYPE { HCALL_SWNET = 20, /* guest request swnet service */ HCALL_SWNET_IRQ = 21, /* guest request swnet intr */ HCALL_FATAL_ERROR = 22, /* guest fatal error, issued by hmcode */ + HCALL_MEMHOTPLUG = 23, /* guest memory hotplug event */ NR_HCALL }; diff --git a/arch/sw_64/include/asm/irq_impl.h b/arch/sw_64/include/asm/irq_impl.h index 3679793d8b65..b568efef6994 100644 --- a/arch/sw_64/include/asm/irq_impl.h +++ b/arch/sw_64/include/asm/irq_impl.h @@ -32,6 +32,7 @@ enum sw64_irq_type { INT_RTC = 9, INT_FAULT = 10, INT_VT_SERIAL = 12, + INT_VT_HOTPLUG = 13, INT_DEV = 17, INT_NMI = 18, INT_LEGACY = 31, diff --git a/arch/sw_64/include/asm/kvm_asm.h b/arch/sw_64/include/asm/kvm_asm.h index 4b851682188c..7e2c92ed4574 100644 --- a/arch/sw_64/include/asm/kvm_asm.h +++ b/arch/sw_64/include/asm/kvm_asm.h @@ -11,4 +11,7 @@ #define SW64_KVM_EXIT_RESTART 17 #define SW64_KVM_EXIT_FATAL_ERROR 22 +#ifdef CONFIG_KVM_MEMHOTPLUG +#define SW64_KVM_EXIT_MEMHOTPLUG 23 +#endif #endif /* _ASM_SW64_KVM_ASM_H */ diff --git a/arch/sw_64/include/asm/kvm_host.h b/arch/sw_64/include/asm/kvm_host.h index e4ebb993153c..6d292c086347 100644 --- a/arch/sw_64/include/asm/kvm_host.h +++ b/arch/sw_64/include/asm/kvm_host.h @@ -29,7 +29,7 @@ #include #define KVM_MAX_VCPUS 64 -#define KVM_USER_MEM_SLOTS 512 +#define KVM_USER_MEM_SLOTS 64 #define KVM_HALT_POLL_NS_DEFAULT 0 #define KVM_IRQCHIP_NUM_PINS 256 @@ -42,12 +42,16 @@ #define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE) struct kvm_arch_memory_slot { - + unsigned long host_phys_addr; + bool valid; }; struct kvm_arch { unsigned long host_phys_addr; unsigned long size; + + /* segment table */ + unsigned long *seg_pgd; }; @@ -100,6 +104,9 @@ struct kvm_vcpu_stat { u64 halt_poll_invalid; }; +#ifdef CONFIG_KVM_MEMHOTPLUG +void vcpu_mem_hotplug(struct kvm_vcpu *vcpu, unsigned long start_addr); +#endif int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, int exception_index, struct hcall_args *hargs); void vcpu_send_ipi(struct kvm_vcpu *vcpu, int target_vcpuid); diff --git a/arch/sw_64/include/asm/memory.h b/arch/sw_64/include/asm/memory.h index d3191165c7b5..b2b7492ae477 100644 --- a/arch/sw_64/include/asm/memory.h +++ b/arch/sw_64/include/asm/memory.h @@ -6,6 +6,7 @@ #include #endif +#define MIN_MEMORY_BLOCK_SIZE_VM_MEMHP (1UL << 30) #define NODE0_START (_TEXT_START - __START_KERNEL_map) #define MAX_PHYSMEM_BITS 48 diff --git a/arch/sw_64/kvm/Kconfig b/arch/sw_64/kvm/Kconfig index 230ac526911c..85323b48f564 100644 --- a/arch/sw_64/kvm/Kconfig +++ b/arch/sw_64/kvm/Kconfig @@ -42,6 +42,13 @@ config KVM_SW64_HOST Provides host support for SW64 processors. To compile this as a module, choose M here. +config KVM_MEMHOTPLUG + bool "Memory hotplug support for guest" + depends on KVM + help + Provides memory hotplug support for SW64 guest. + + source "drivers/vhost/Kconfig" endif # VIRTUALIZATION diff --git a/arch/sw_64/kvm/handle_exit.c b/arch/sw_64/kvm/handle_exit.c index 0d6806051fc7..5016bc0eddc2 100644 --- a/arch/sw_64/kvm/handle_exit.c +++ b/arch/sw_64/kvm/handle_exit.c @@ -34,6 +34,11 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, case SW64_KVM_EXIT_IPI: vcpu_send_ipi(vcpu, hargs->arg0); return 1; +#ifdef CONFIG_KVM_MEMHOTPLUG + case SW64_KVM_EXIT_MEMHOTPLUG: + vcpu_mem_hotplug(vcpu, hargs->arg0); + return 1; +#endif case SW64_KVM_EXIT_FATAL_ERROR: printk("Guest fatal error: Reason=[%lx], EXC_PC=[%lx], DVA=[%lx]", hargs->arg0, hargs->arg1, hargs->arg2); vcpu->run->exit_reason = KVM_EXIT_UNKNOWN; diff --git a/arch/sw_64/kvm/kvm-sw64.c b/arch/sw_64/kvm/kvm-sw64.c index 839ee83d57d5..af29d0ca8e7f 100644 --- a/arch/sw_64/kvm/kvm-sw64.c +++ b/arch/sw_64/kvm/kvm-sw64.c @@ -56,10 +56,18 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm, int irq extern int __sw64_vcpu_run(struct vcpucb *vcb, struct kvm_regs *regs, struct hcall_args *args); -static unsigned long get_vpcr(unsigned long machine_mem_offset, unsigned long memory_size, unsigned long vpn) +#ifdef CONFIG_KVM_MEMHOTPLUG +static u64 get_vpcr_memhp(u64 seg_base, u64 vpn) { - return (machine_mem_offset >> 23) | ((memory_size >> 23) << 16) | ((vpn & HARDWARE_VPN_MASK) << 44); + return seg_base | ((vpn & HARDWARE_VPN_MASK) << 44); } +#else +static u64 get_vpcr(u64 hpa_base, u64 mem_size, u64 vpn) +{ + return (hpa_base >> 23) | ((mem_size >> 23) << 16) + | ((vpn & HARDWARE_VPN_MASK) << 44); +} +#endif static unsigned long __get_new_vpn_context(struct kvm_vcpu *vcpu, long cpu) { @@ -212,12 +220,38 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) { +#ifdef CONFIG_KVM_MEMHOTPLUG + unsigned long *seg_pgd; + + if (kvm->arch.seg_pgd != NULL) { + kvm_err("kvm_arch already initialized?\n"); + return -EINVAL; + } + + seg_pgd = alloc_pages_exact(PAGE_SIZE, GFP_KERNEL | __GFP_ZERO); + if (!seg_pgd) + return -ENOMEM; + + kvm->arch.seg_pgd = seg_pgd; +#endif + return 0; } void kvm_arch_destroy_vm(struct kvm *kvm) { int i; +#ifdef CONFIG_KVM_MEMHOTPLUG + void *seg_pgd = NULL; + + if (kvm->arch.seg_pgd) { + seg_pgd = READ_ONCE(kvm->arch.seg_pgd); + kvm->arch.seg_pgd = NULL; + } + + if (seg_pgd) + free_pages_exact(seg_pgd, PAGE_SIZE); +#endif for (i = 0; i < KVM_MAX_VCPUS; ++i) { if (kvm->vcpus[i]) { @@ -227,7 +261,6 @@ void kvm_arch_destroy_vm(struct kvm *kvm) } atomic_set(&kvm->online_vcpus, 0); - } long kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) @@ -241,6 +274,22 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, return 0; } +#ifdef CONFIG_KVM_MEMHOTPLUG +static void setup_segment_table(struct kvm *kvm, + struct kvm_memory_slot *memslot, unsigned long addr, size_t size) +{ + unsigned long *seg_pgd = kvm->arch.seg_pgd; + unsigned int num_of_entry = size >> 30; + unsigned long base_hpa = addr >> 30; + int i; + + for (i = 0; i < num_of_entry; i++) { + *seg_pgd = base_hpa + i; + seg_pgd++; + } +} +#endif + int kvm_arch_prepare_memory_region(struct kvm *kvm, struct kvm_memory_slot *memslot, const struct kvm_userspace_memory_region *mem, @@ -253,8 +302,15 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, unsigned long ret; size_t size; - if (change == KVM_MR_FLAGS_ONLY) + if (change == KVM_MR_FLAGS_ONLY || change == KVM_MR_DELETE) + return 0; + +#ifndef CONFIG_KVM_MEMHOTPLUG + if (mem->guest_phys_addr) { + pr_info("%s, No KVM MEMHOTPLUG support!\n", __func__); return 0; + } +#endif if (test_bit(IO_MARK_BIT, &(mem->guest_phys_addr))) return 0; @@ -276,7 +332,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, if (!vm_file) { info = kzalloc(sizeof(struct vmem_info), GFP_KERNEL); - size = round_up(mem->memory_size, 8<<20); + size = round_up(mem->memory_size, 8 << 20); addr = gen_pool_alloc(sw64_kvm_pool, size); if (!addr) return -ENOMEM; @@ -291,6 +347,18 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, if (!vma) return -ENOMEM; +#ifdef CONFIG_KVM_MEMHOTPLUG + if (memslot->base_gfn == 0x0UL) { + setup_segment_table(kvm, memslot, addr, size); + kvm->arch.host_phys_addr = (u64)addr; + memslot->arch.host_phys_addr = addr; + } else { + /* used for memory hotplug */ + memslot->arch.host_phys_addr = addr; + memslot->arch.valid = false; + } +#endif + info->start = addr; info->size = size; vma->vm_private_data = (void *) info; @@ -308,8 +376,11 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, pr_info("guest phys addr = %#lx, size = %#lx\n", addr, vma->vm_end - vma->vm_start); + +#ifndef CONFIG_KVM_MEMHOTPLUG kvm->arch.host_phys_addr = (u64)addr; - kvm->arch.size = round_up(mem->memory_size, 8<<20); + kvm->arch.size = round_up(mem->memory_size, 8 << 20); +#endif memset(__va(addr), 0, 0x2000000); @@ -463,8 +534,14 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) /* Set guest vcb */ /* vpn will update later when vcpu is running */ if (vcpu->arch.vcb.vpcr == 0) { +#ifndef CONFIG_KVM_MEMHOTPLUG vcpu->arch.vcb.vpcr = get_vpcr(vcpu->kvm->arch.host_phys_addr, vcpu->kvm->arch.size, 0); +#else + unsigned long seg_base = virt_to_phys(vcpu->kvm->arch.seg_pgd); + + vcpu->arch.vcb.vpcr = get_vpcr_memhp(seg_base, 0); +#endif vcpu->arch.vcb.upcr = 0x7; } @@ -640,6 +717,30 @@ int kvm_dev_ioctl_check_extension(long ext) return r; } +#ifdef CONFIG_KVM_MEMHOTPLUG +void vcpu_mem_hotplug(struct kvm_vcpu *vcpu, unsigned long start_addr) +{ + struct kvm *kvm = vcpu->kvm; + struct kvm_memory_slot *slot; + unsigned long start_pfn = start_addr >> PAGE_SHIFT; + + kvm_for_each_memslot(slot, kvm_memslots(kvm)) { + if (start_pfn == slot->base_gfn) { + unsigned long *seg_pgd; + unsigned long num_of_entry = slot->npages >> 17; + unsigned long base_hpa = slot->arch.host_phys_addr; + int i; + + seg_pgd = kvm->arch.seg_pgd + (start_pfn >> 17); + for (i = 0; i < num_of_entry; i++) { + *seg_pgd = (base_hpa >> 30) + i; + seg_pgd++; + } + } + } +} +#endif + void vcpu_send_ipi(struct kvm_vcpu *vcpu, int target_vcpuid) { struct kvm_vcpu *target_vcpu = kvm_get_vcpu(vcpu->kvm, target_vcpuid); diff --git a/arch/sw_64/mm/init.c b/arch/sw_64/mm/init.c index 16d3da7beebe..82f2414ef7f7 100644 --- a/arch/sw_64/mm/init.c +++ b/arch/sw_64/mm/init.c @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -33,6 +34,14 @@ static pud_t vmalloc_pud[1024] __attribute__((__aligned__(PAGE_SIZE))); static phys_addr_t mem_start; static phys_addr_t mem_size_limit; +unsigned long memory_block_size_bytes(void) +{ + if (is_in_guest()) + return MIN_MEMORY_BLOCK_SIZE_VM_MEMHP; + else + return MIN_MEMORY_BLOCK_SIZE; +} + static int __init setup_mem_size(char *p) { char *oldp; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index fafa8b0d8099..140716083ab8 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -351,6 +351,14 @@ config HMC6352 This driver provides support for the Honeywell HMC6352 compass, providing configuration and heading data via sysfs. +config SUNWAY_GED + tristate "sunway generic device driver for memhotplug" + depends on SW64 + depends on MEMORY_HOTPLUG + help + This driver provides support for sunway generic device driver for + memhotplug, providing configuration and heading data via sysfs. + config DS1682 tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" depends on I2C diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index d23231e73330..3615763234a6 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_C2PORT) += c2port/ obj-$(CONFIG_HMC6352) += hmc6352.o +obj-$(CONFIG_SUNWAY_GED) += sunway-ged.o obj-y += eeprom/ obj-y += cb710/ obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o diff --git a/drivers/misc/sunway-ged.c b/drivers/misc/sunway-ged.c new file mode 100644 index 000000000000..b4e4ca315852 --- /dev/null +++ b/drivers/misc/sunway-ged.c @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* Generic Event Device for ACPI. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define OFFSET_START_ADDR 0 +#define OFFSET_LENGTH 8 +#define OFFSET_STATUS 16 +#define OFFSET_SLOT 24 + +/* Memory hotplug event */ +#define SUNWAY_MEMHOTPLUG_ADD 0x1 +#define SUNWAY_MEMHOTPLUG_REMOVE 0x2 + +struct sunway_memory_device { + struct sunway_ged_device *device; + unsigned int state; /* State of the memory device */ + struct list_head list; + + u64 start_addr; /* Memory Range start physical addr */ + u64 length; /* Memory Range length */ + u64 slot; /* Memory Range slot */ + unsigned int enabled:1; +}; + +struct sunway_ged_device { + struct device *dev; + void __iomem *membase; + void *driver_data; + spinlock_t lock; + struct list_head dev_list; +}; + +static int sunway_memory_enable_device(struct sunway_memory_device *mem_device) +{ + int num_enabled = 0; + int result = 0; + + if (mem_device->enabled) { /* just sanity check...*/ + num_enabled++; + goto out; + } + + /* + * If the memory block size is zero, please ignore it. + * Don't try to do the following memory hotplug flowchart. + */ + if (!mem_device->length) + goto out; + + lock_device_hotplug(); + /* suppose node = 0, fix me! */ + result = __add_memory(0, mem_device->start_addr, mem_device->length); + unlock_device_hotplug(); + /* + * If the memory block has been used by the kernel, add_memory() + * returns -EEXIST. If add_memory() returns the other error, it + * means that this memory block is not used by the kernel. + */ + if (result && result != -EEXIST) + goto out; + + mem_device->enabled = 1; + + /* + * Add num_enable even if add_memory() returns -EEXIST, so the + * device is bound to this driver. + */ + num_enabled++; +out: + if (!num_enabled) { + dev_err(mem_device->device->dev, "add_memory failed\n"); + return -EINVAL; + } + + return 0; +} + +static int sunway_memory_get_meminfo(struct sunway_memory_device *mem_device) +{ + struct sunway_ged_device *geddev; + + if (!mem_device) + return -EINVAL; + + if (mem_device->enabled) + return 0; + + geddev = mem_device->device; + + mem_device->start_addr = readq(geddev->membase + OFFSET_START_ADDR); + mem_device->length = readq(geddev->membase + OFFSET_LENGTH); + + return 0; +} + +static void sunway_memory_device_remove(struct sunway_ged_device *device) +{ + struct sunway_memory_device *mem_dev, *n; + unsigned long start_addr, length, slot; + + if (!device) + return; + + start_addr = readq(device->membase + OFFSET_START_ADDR); + length = readq(device->membase + OFFSET_LENGTH); + slot = readq(device->membase + OFFSET_SLOT); + + list_for_each_entry_safe(mem_dev, n, &device->dev_list, list) { + if (!mem_dev->enabled) + continue; + + if ((start_addr == mem_dev->start_addr) && + (length == mem_dev->length)) { + /* suppose node = 0, fix me! */ + remove_memory(0, start_addr, length); + list_del(&mem_dev->list); + kfree(mem_dev); + } + } + + writeq(slot, device->membase + OFFSET_SLOT); +} + +static int sunway_memory_device_add(struct sunway_ged_device *device) +{ + struct sunway_memory_device *mem_device; + int result; + + if (!device) + return -EINVAL; + + mem_device = kzalloc(sizeof(struct sunway_memory_device), GFP_KERNEL); + if (!mem_device) + return -ENOMEM; + + INIT_LIST_HEAD(&mem_device->list); + mem_device->device = device; + + /* Get the range from the IO */ + mem_device->start_addr = readq(device->membase + OFFSET_START_ADDR); + mem_device->length = readq(device->membase + OFFSET_LENGTH); + mem_device->slot = readq(device->membase + OFFSET_SLOT); + + result = sunway_memory_enable_device(mem_device); + if (result) { + dev_err(device->dev, "sunway_memory_enable_device() error\n"); + sunway_memory_device_remove(device); + + return result; + } + + list_add_tail(&mem_device->list, &device->dev_list); + dev_dbg(device->dev, "Memory device configured\n"); + + hcall(HCALL_MEMHOTPLUG, mem_device->start_addr, 0, 0); + + return 1; +} + +static irqreturn_t sunwayged_ist(int irq, void *data) +{ + struct sunway_ged_device *sunwayged_dev = data; + unsigned int status; + + status = readl(sunwayged_dev->membase + OFFSET_STATUS); + + /* through IO status to add or remove memory device */ + if (status & SUNWAY_MEMHOTPLUG_ADD) + sunway_memory_device_add(sunwayged_dev); + + if (status & SUNWAY_MEMHOTPLUG_REMOVE) + sunway_memory_device_remove(sunwayged_dev); + + return IRQ_HANDLED; +} + +static irqreturn_t sunwayged_irq_handler(int irq, void *data) +{ + return IRQ_WAKE_THREAD; +} + +static int sunwayged_probe(struct platform_device *pdev) +{ + struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + int irq = platform_get_irq(pdev, 0); + struct sunway_ged_device *geddev; + struct device *dev; + int irqflags; + + if (!regs) { + dev_err(dev, "no registers defined\n"); + return -EINVAL; + } + + geddev = devm_kzalloc(&pdev->dev, sizeof(*geddev), GFP_KERNEL); + if (!geddev) + return -ENOMEM; + + spin_lock_init(&geddev->lock); + geddev->membase = devm_ioremap(&pdev->dev, + regs->start, resource_size(regs)); + if (!geddev->membase) + return -ENOMEM; + + INIT_LIST_HEAD(&geddev->dev_list); + geddev->dev = &pdev->dev; + irqflags = IRQF_SHARED; + + if (request_threaded_irq(irq, sunwayged_irq_handler, sunwayged_ist, + irqflags, "SUNWAY:Ged", geddev)) { + dev_err(dev, "failed to setup event handler for irq %u\n", irq); + + return -EINVAL; + } + + platform_set_drvdata(pdev, geddev); + + return 0; +} + +static int sunwayged_remove(struct platform_device *pdev) +{ + return 0; +} + +static const struct of_device_id sunwayged_of_match[] = { + {.compatible = "sw6,sunway-ged", }, + { } +}; +MODULE_DEVICE_TABLE(of, sunwayged_of_match); + +static struct platform_driver sunwayged_platform_driver = { + .driver = { + .name = "sunway-ged", + .of_match_table = sunwayged_of_match, + }, + .probe = sunwayged_probe, + .remove = sunwayged_remove, +}; +module_platform_driver(sunwayged_platform_driver); + +MODULE_AUTHOR("Lu Feifei"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Sunway ged driver"); -- Gitee From 2d3b928eac96fa601080afba9282cac711edbcef Mon Sep 17 00:00:00 2001 From: Lu Feifei Date: Wed, 15 Jun 2022 14:59:51 +0800 Subject: [PATCH 60/71] sw64: add a misc device to chip_vt.dts for memory-hotplug Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56WV8 -------------------------------- This is an emulated device used to communicate with the memory-hotplug device on the qemu side, so the device is added to device tree for guest os. Signed-off-by: Lu Feifei Signed-off-by: Gu Zitao --- arch/sw_64/boot/dts/chip_vt.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/sw_64/boot/dts/chip_vt.dts b/arch/sw_64/boot/dts/chip_vt.dts index f0bcf1db1d08..abad29dee97e 100644 --- a/arch/sw_64/boot/dts/chip_vt.dts +++ b/arch/sw_64/boot/dts/chip_vt.dts @@ -34,5 +34,17 @@ clock-frequency = <24000000>; status = "okay"; }; + misc: misc0@8036 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sw6,sunway-ged"; + reg = <0x8036 0x0 0x0 0x20>; + interrupt-parent=<&intc>; + interrupts = <13>; + reg-shift = <0>; + reg-io-width = <8>; + clock-frequency = <24000000>; + status = "okay"; + }; }; }; -- Gitee From edb81706ec0dc4bc13c81b7ce08febe09bf2a471 Mon Sep 17 00:00:00 2001 From: Yang Qiang Date: Mon, 20 Jun 2022 14:23:56 +0800 Subject: [PATCH 61/71] sw64: pci: fix maximum bus number for pci scan Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GDR1 -------------------------------- When PCI devices enable SRIOV function, the previous policy that uses pci_find_bus to locate PCI bus from a given domain and bus number may return false PCI bus number, so this patch fixes this patch. Signed-off-by: Yang Qiang Signed-off-by: Gu Zitao --- arch/sw_64/chip/chip3/chip.c | 13 +++++++------ arch/sw_64/kernel/pci.c | 18 +++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/arch/sw_64/chip/chip3/chip.c b/arch/sw_64/chip/chip3/chip.c index 02b369b2b37b..84ca7ffcb2ef 100644 --- a/arch/sw_64/chip/chip3/chip.c +++ b/arch/sw_64/chip/chip3/chip.c @@ -178,18 +178,20 @@ int chip_pcie_configure(struct pci_controller *hose) struct pci_bus *bus, *top; struct list_head *next; unsigned int max_read_size, smallest_max_payload; - int max_payloadsize, iov_bus = 0; + int max_payloadsize; unsigned long rc_index, node; unsigned long piuconfig0, value; unsigned int pcie_caps_offset; unsigned int rc_conf_value; u16 devctl, new_values; bool rc_ari_disabled = false, found = false; + unsigned char bus_max_num; node = hose->node; rc_index = hose->index; smallest_max_payload = read_rc_conf(node, rc_index, RC_EXP_DEVCAP); smallest_max_payload &= PCI_EXP_DEVCAP_PAYLOAD; + bus_max_num = hose->busn_space->start; top = hose->bus; bus = top; @@ -200,6 +202,7 @@ int chip_pcie_configure(struct pci_controller *hose) /* end of this bus, go up or finish */ if (bus == top) break; + next = bus->self->bus_list.next; bus = bus->self->bus; continue; @@ -224,10 +227,8 @@ int chip_pcie_configure(struct pci_controller *hose) } } -#ifdef CONFIG_PCI_IOV - if (dev->is_physfn) - iov_bus += dev->sriov->max_VF_buses - dev->bus->number; -#endif + if (bus->busn_res.end > bus_max_num) + bus_max_num = bus->busn_res.end; /* Query device PCIe capability register */ pcie_caps_offset = dev->pcie_cap; @@ -306,7 +307,7 @@ int chip_pcie_configure(struct pci_controller *hose) pci_write_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL, devctl); } - return iov_bus; + return bus_max_num; } static int chip3_check_pci_vt_linkup(unsigned long node, unsigned long index) diff --git a/arch/sw_64/kernel/pci.c b/arch/sw_64/kernel/pci.c index 7cc8b7d2d43b..fcc6e0f02a93 100644 --- a/arch/sw_64/kernel/pci.c +++ b/arch/sw_64/kernel/pci.c @@ -221,7 +221,7 @@ void __init common_init_pci(void) struct pci_bus *bus; unsigned int init_busnr; int need_domain_info = 0; - int ret, iov_bus; + int ret; unsigned long offset; /* Scan all of the recorded PCI controllers. */ @@ -257,20 +257,20 @@ void __init common_init_pci(void) bus = hose->bus = bridge->bus; hose->need_domain_info = need_domain_info; - while (pci_find_bus(pci_domain_nr(bus), last_bus)) - last_bus++; if (is_in_host()) - iov_bus = chip_pcie_configure(hose); - last_bus += iov_bus; + last_bus = chip_pcie_configure(hose); + else + while (pci_find_bus(pci_domain_nr(bus), last_bus)) + last_bus++; - hose->last_busno = hose->busn_space->end = last_bus - 1; + hose->last_busno = hose->busn_space->end = last_bus; init_busnr = read_rc_conf(hose->node, hose->index, RC_PRIMARY_BUS); init_busnr &= ~(0xff << 16); - init_busnr |= (last_bus - 1) << 16; + init_busnr |= last_bus << 16; write_rc_conf(hose->node, hose->index, RC_PRIMARY_BUS, init_busnr); - pci_bus_update_busn_res_end(bus, last_bus - 1); - + pci_bus_update_busn_res_end(bus, last_bus); + last_bus++; } pcibios_claim_console_setup(); -- Gitee From b6bc5e6d316eb6e70a88ca730d2e099a8bad1bf7 Mon Sep 17 00:00:00 2001 From: Hang Xiaoqian Date: Mon, 20 Jun 2022 16:54:38 +0800 Subject: [PATCH 62/71] sw64: remove unaligned count Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GFNY -------------------------------- In the case of highly concurrent unaligned processing, unaligned count may cause severe cache thrashing. However, unaligned count is not required, so remove it to reduce cache thrashing. Signed-off-by: Hang Xiaoqian Signed-off-by: Gu Zitao --- arch/sw_64/kernel/Makefile | 2 +- arch/sw_64/kernel/traps.c | 13 -------- arch/sw_64/kernel/unaligned.c | 56 ----------------------------------- 3 files changed, 1 insertion(+), 70 deletions(-) delete mode 100644 arch/sw_64/kernel/unaligned.c diff --git a/arch/sw_64/kernel/Makefile b/arch/sw_64/kernel/Makefile index c1e461e0ac56..94b63d6a286b 100644 --- a/arch/sw_64/kernel/Makefile +++ b/arch/sw_64/kernel/Makefile @@ -31,7 +31,7 @@ obj-$(CONFIG_HIBERNATION) += hibernate_asm.o hibernate.o obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_PCI) += pci_common.o obj-$(CONFIG_RELOCATABLE) += relocate.o -obj-$(CONFIG_DEBUG_FS) += unaligned.o segvdbg.o +obj-$(CONFIG_DEBUG_FS) += segvdbg.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o ifndef CONFIG_PCI diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index a61c851967a9..d656eca5f961 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -320,11 +320,6 @@ do_entIF(unsigned long inst_type, struct pt_regs *regs) force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc, 0); } -struct unaligned_stat { - unsigned long count, va, pc; -} unaligned[2]; - - asmlinkage void do_entUna(void *va, unsigned long opcode, unsigned long reg, struct pt_regs *regs) @@ -334,10 +329,6 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, unsigned long pc = regs->pc - 4; const struct exception_table_entry *fixup; - unaligned[0].count++; - unaligned[0].va = (unsigned long) va; - unaligned[0].pc = pc; - /* * We don't want to use the generic get/put unaligned macros as * we want to trap exceptions. Only if we actually get an @@ -666,10 +657,6 @@ do_entUnaUser(void __user *va, unsigned long opcode, if ((unsigned long)va >= TASK_SIZE) goto give_sigsegv; - ++unaligned[1].count; - unaligned[1].va = (unsigned long)va; - unaligned[1].pc = regs->pc - 4; - if ((1L << opcode) & OP_INT_MASK) { /* it's an integer load/store */ if (reg < 30) { diff --git a/arch/sw_64/kernel/unaligned.c b/arch/sw_64/kernel/unaligned.c deleted file mode 100644 index a1bbdab4a266..000000000000 --- a/arch/sw_64/kernel/unaligned.c +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/* - * Copyright (C) 2020 Mao Minkai - * Author: Mao Minkai - * - * This code is taken from arch/mips/kernel/segment.c - * Copyright (C) 2013 Imagination Technologies Ltd. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include -#include - -static int show_unaligned(struct seq_file *sf, void *v) -{ - extern struct unaligned_stat { - unsigned long count, va, pc; - } unaligned[2]; - - seq_printf(sf, "kernel unaligned acc\t: %ld (pc=%lx, va=%lx)\n", unaligned[0].count, unaligned[0].pc, unaligned[0].va); - seq_printf(sf, "user unaligned acc\t: %ld (pc=%lx, va=%lx)\n", unaligned[1].count, unaligned[1].pc, unaligned[1].va); - - return 0; -} - -static int unaligned_open(struct inode *inode, struct file *file) -{ - return single_open(file, show_unaligned, NULL); -} - -static const struct file_operations unaligned_fops = { - .open = unaligned_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init unaligned_info(void) -{ - struct dentry *unaligned; - - if (!sw64_debugfs_dir) - return -ENODEV; - - unaligned = debugfs_create_file("unaligned", S_IRUGO, - sw64_debugfs_dir, NULL, - &unaligned_fops); - if (!unaligned) - return -ENOMEM; - return 0; -} -device_initcall(unaligned_info); -- Gitee From 993a93c8c4a7aa088c0157bddb10fda388fcdccb Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Mon, 20 Jun 2022 16:58:09 +0800 Subject: [PATCH 63/71] sw64: fix simd version of memset Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GFOO -------------------------------- In commit 20b900c4b7fb ("sw64: optimize simd version of memcpy and memset"), _nc instructions are used to improve performance, but the position of memb instruction in memset is wrong. Fix it. Fixes: 20b900c4b7fb ("sw64: optimize simd version of memcpy and memset") Signed-off-by: Mao Minkai Signed-off-by: Gu Zitao --- arch/sw_64/lib/deep-memset.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/lib/deep-memset.S b/arch/sw_64/lib/deep-memset.S index ed2171c56d4d..7fbd529c72a8 100644 --- a/arch/sw_64/lib/deep-memset.S +++ b/arch/sw_64/lib/deep-memset.S @@ -99,12 +99,11 @@ $mod32_aligned: .align 5 $mod32_loop_nc: subl $18, 64, $18 - blt $18, $mod32_tail + blt $18, $mod32_tail_memb vstd_nc $f10, 0($16) vstd_nc $f10, 32($16) addl $16, 64, $16 br $31, $mod32_loop_nc - memb # required for _nc store instructions .align 5 $mod32_loop: @@ -115,6 +114,8 @@ $mod32_loop: addl $16, 64, $16 br $31, $mod32_loop +$mod32_tail_memb: + memb # required for _nc store instructions $mod32_tail: vldd $f10, 0($4) addl $sp, 64, $sp -- Gitee From e73f0bffb26c59b5b3ff024b4194a3c6fe34a8dd Mon Sep 17 00:00:00 2001 From: Zhu Donghong Date: Tue, 21 Jun 2022 14:47:33 +0800 Subject: [PATCH 64/71] sw64: deliver a hot reset to Root Complex with plugin JMicron 585 card Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GFPA -------------------------------- On SW64 platform, JMicron 585 SATA card directly connected to Root Complex may raise DMA failure when reboot, so we force a hot reset to Root Complex to fix can not access JMicron 585 SATA card. Signed-off-by: Zhu Donghong Signed-off-by: Gu Zitao --- arch/sw_64/platform/platform_xuelang.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/sw_64/platform/platform_xuelang.c b/arch/sw_64/platform/platform_xuelang.c index 63a4b163e43e..ae8179b53b4c 100644 --- a/arch/sw_64/platform/platform_xuelang.c +++ b/arch/sw_64/platform/platform_xuelang.c @@ -26,9 +26,25 @@ extern void cpld_write(uint8_t slave_addr, uint8_t reg, uint8_t data); static void xuelang_kill_arch(int mode) { + struct pci_dev *pdev; + struct pci_controller *hose; + int val; + if (is_in_host()) { switch (mode) { case LINUX_REBOOT_CMD_RESTART: + pdev = pci_get_device(PCI_VENDOR_ID_JMICRON, + 0x0585, NULL); + if (pdev) { + hose = (struct pci_controller *)pdev->sysdata; + val = read_rc_conf(hose->node, hose->index, + RC_PORT_LINK_CTL); + write_rc_conf(hose->node, hose->index, + RC_PORT_LINK_CTL, val | 0x8); + write_rc_conf(hose->node, hose->index, + RC_PORT_LINK_CTL, val); + } + cpld_write(0x64, 0x00, 0xc3); mb(); break; -- Gitee From 9e0b719ccc16ce561eb8247e87f8a15f00ffaccf Mon Sep 17 00:00:00 2001 From: He Sheng Date: Wed, 21 Jul 2021 13:36:27 +0800 Subject: [PATCH 65/71] sw64: rename debugfs dir sw_64 to sw64 Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG -------------------------------- Signed-off-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 85d172c32239..0e93643539d3 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -976,7 +976,7 @@ static int __init debugfs_sw64(void) { struct dentry *d; - d = debugfs_create_dir("sw_64", NULL); + d = debugfs_create_dir("sw64", NULL); if (!d) return -ENOMEM; sw64_debugfs_dir = d; -- Gitee From 0115f679cddf65c65822b61208be17a141a72cfc Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Wed, 15 Jun 2022 11:00:09 +0800 Subject: [PATCH 66/71] sw64: reimplement show_stack() method Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GFQ0 -------------------------------- It used to show stack information by SP, that means it has nothing to do with task, which is unexpected. In order to show stack of task, we improve the implementation of show_stack(). However, the original task struct does not have sp, so we add it into thread_struct and do something necessary in __switch_to. Meanwhile, walk_stackframe() can be reused, so refactor related codes for better support. Signed-off-by: Wu Liliu Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/processor.h | 1 + arch/sw_64/include/asm/stacktrace.h | 4 +- arch/sw_64/kernel/asm-offsets.c | 1 + arch/sw_64/kernel/entry.S | 6 +++ arch/sw_64/kernel/perf_event.c | 12 ++--- arch/sw_64/kernel/process.c | 1 + arch/sw_64/kernel/stacktrace.c | 78 +++++++++++++++++++++++------ arch/sw_64/kernel/traps.c | 58 ++++----------------- 8 files changed, 85 insertions(+), 76 deletions(-) diff --git a/arch/sw_64/include/asm/processor.h b/arch/sw_64/include/asm/processor.h index 08e8cc8e5428..886f28635dd4 100644 --- a/arch/sw_64/include/asm/processor.h +++ b/arch/sw_64/include/asm/processor.h @@ -45,6 +45,7 @@ struct thread_struct { struct user_fpsimd_state fpstate; /* Callee-saved registers */ unsigned long ra; + unsigned long sp; unsigned long s[7]; /* s0 ~ s6 */ }; #define INIT_THREAD { } diff --git a/arch/sw_64/include/asm/stacktrace.h b/arch/sw_64/include/asm/stacktrace.h index 813aa5e7a91d..ed691a72573b 100644 --- a/arch/sw_64/include/asm/stacktrace.h +++ b/arch/sw_64/include/asm/stacktrace.h @@ -32,8 +32,8 @@ struct stack_frame { }; extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame); -extern void walk_stackframe(struct task_struct *tsk, struct stackframe *frame, - int (*fn)(struct stackframe *, void *), void *data); +extern void walk_stackframe(struct task_struct *tsk, struct pt_regs *regs, + int (*fn)(unsigned long, void *), void *data); static inline bool on_task_stack(struct task_struct *tsk, unsigned long sp, struct stack_info *info) diff --git a/arch/sw_64/kernel/asm-offsets.c b/arch/sw_64/kernel/asm-offsets.c index 0c7e1e26eb05..9e6c338a5edd 100644 --- a/arch/sw_64/kernel/asm-offsets.c +++ b/arch/sw_64/kernel/asm-offsets.c @@ -213,6 +213,7 @@ void foo(void) OFFSET(TASK_THREAD_FPCR, task_struct, thread.fpstate.fpcr); BLANK(); OFFSET(TASK_THREAD_RA, task_struct, thread.ra); + OFFSET(TASK_THREAD_SP, task_struct, thread.sp); OFFSET(TASK_THREAD_S0, task_struct, thread.s[0]); OFFSET(TASK_THREAD_S1, task_struct, thread.s[1]); OFFSET(TASK_THREAD_S2, task_struct, thread.s[2]); diff --git a/arch/sw_64/kernel/entry.S b/arch/sw_64/kernel/entry.S index 977c774ad799..f79c9a6ddf36 100644 --- a/arch/sw_64/kernel/entry.S +++ b/arch/sw_64/kernel/entry.S @@ -398,6 +398,7 @@ __switch_to: .prologue 0 /* Save context into prev->thread */ stl $26, TASK_THREAD_RA($17) + stl $30, TASK_THREAD_SP($17) stl $9, TASK_THREAD_S0($17) stl $10, TASK_THREAD_S1($17) stl $11, TASK_THREAD_S2($17) @@ -415,6 +416,11 @@ __switch_to: ldl $14, TASK_THREAD_S5($18) ldl $15, TASK_THREAD_S6($18) sys_call HMC_swpctx + /* + * SP has been saved and restored by HMC_swpctx, + * and restore it again here for future expansion. + */ + ldl $30, TASK_THREAD_SP($18) ldi $8, 0x3fff bic $sp, $8, $8 mov $17, $0 diff --git a/arch/sw_64/kernel/perf_event.c b/arch/sw_64/kernel/perf_event.c index 52ec34e33269..6e344239917b 100644 --- a/arch/sw_64/kernel/perf_event.c +++ b/arch/sw_64/kernel/perf_event.c @@ -761,24 +761,18 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry, * whist unwinding the stackframe and is like a subroutine return so we use * the PC. */ -static int callchain_trace(struct stackframe *frame, void *data) +static int callchain_trace(unsigned long pc, void *data) { struct perf_callchain_entry_ctx *entry = data; - perf_callchain_store(entry, frame->pc); - + perf_callchain_store(entry, pc); return 0; } void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) { - struct stackframe frame; - - frame.fp = regs->r15; - frame.pc = regs->pc; - - walk_stackframe(current, &frame, callchain_trace, entry); + walk_stackframe(NULL, regs, callchain_trace, entry); } /* diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index 7a7578d530c6..da721d4266ee 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -169,6 +169,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, childti->pcb.ksp = (unsigned long) childregs; childti->pcb.flags = 7; /* set FEN, clear everything else */ + p->thread.sp = (unsigned long) childregs; if (unlikely(p->flags & PF_KTHREAD)) { /* kernel thread */ diff --git a/arch/sw_64/kernel/stacktrace.c b/arch/sw_64/kernel/stacktrace.c index 2671331717ba..4e9acf99aaab 100644 --- a/arch/sw_64/kernel/stacktrace.c +++ b/arch/sw_64/kernel/stacktrace.c @@ -10,6 +10,8 @@ #include #include #include +#include + #include /* @@ -59,40 +61,84 @@ int unwind_frame(struct task_struct *tsk, struct stackframe *frame) } EXPORT_SYMBOL_GPL(unwind_frame); -void walk_stackframe(struct task_struct *tsk, struct stackframe *frame, - int (*fn)(struct stackframe *, void *), void *data) +void walk_stackframe(struct task_struct *tsk, struct pt_regs *regs, + int (*fn)(unsigned long, void *), void *data) { + unsigned long pc, fp; + + struct stackframe frame; + + if (regs) { + pc = regs->pc; + fp = regs->r15; + } else if (tsk == current || tsk == NULL) { + fp = (unsigned long)__builtin_frame_address(0); + pc = (unsigned long)walk_stackframe; + } else { + fp = tsk->thread.s[6]; + pc = tsk->thread.ra; + } + + if (!__kernel_text_address(pc) || fn(pc, data)) + return; + + frame.pc = pc; + frame.fp = fp; while (1) { int ret; - - if (fn(frame, data)) - break; - ret = unwind_frame(tsk, frame); + ret = unwind_frame(tsk, &frame); if (ret < 0) break; + + if (fn(frame.pc, data)) + break; } } EXPORT_SYMBOL_GPL(walk_stackframe); #else /* !CONFIG_FRAME_POINTER */ -void walk_stackframe(struct task_struct *tsk, struct stackframe *frame, - int (*fn)(struct stackframe *, void *), void *data) +void walk_stackframe(struct task_struct *tsk, struct pt_regs *regs, + int (*fn)(unsigned long, void *), void *data) { - unsigned long *sp = (unsigned long *)current_thread_info()->pcb.ksp; - unsigned long addr; - struct perf_callchain_entry_ctx *entry = data; + unsigned long *ksp; + unsigned long sp, pc; + + if (regs) { + sp = (unsigned long)(regs+1); + pc = regs->pc; + } else if (tsk == current || tsk == NULL) { + register unsigned long current_sp __asm__ ("$30"); + sp = current_sp; + pc = (unsigned long)walk_stackframe; + } else { + sp = tsk->thread.sp; + pc = tsk->thread.ra; + } - perf_callchain_store(entry, frame->pc); - while (!kstack_end(sp) && entry->nr < entry->max_stack) { - addr = *sp++; - if (__kernel_text_address(addr)) - perf_callchain_store(entry, addr); + ksp = (unsigned long *)sp; + + while (!kstack_end(ksp)) { + if (__kernel_text_address(pc) && fn(pc, data)) + break; + pc = (*ksp++) - 0x4; } } EXPORT_SYMBOL_GPL(walk_stackframe); #endif/* CONFIG_FRAME_POINTER */ +static int print_address_trace(unsigned long pc, void *data) +{ + print_ip_sym((const char *)data, pc); + return 0; +} + +void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl) +{ + pr_info("Trace:\n"); + walk_stackframe(task, NULL, print_address_trace, (void *)loglvl); +} + /* * Save stack-backtrace addresses into a stack_trace buffer. */ diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index d656eca5f961..4e95cab13daa 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -12,13 +12,20 @@ #include #include #include +#include #include +#include +#include +#include #include #include #include #include #include +#include +#include +#include #include "proto.h" @@ -68,53 +75,6 @@ dik_show_code(unsigned int *pc) printk("\n"); } -static void -dik_show_trace(unsigned long *sp, const char *loglvl) -{ - long i = 0; - unsigned long tmp; - - printk("%sTrace:\n", loglvl); - while (0x1ff8 & (unsigned long)sp) { - tmp = *sp; - sp++; - if (!__kernel_text_address(tmp)) - continue; - printk("%s[<%lx>] %pSR\n", loglvl, tmp, (void *)tmp); - if (i > 40) { - printk("%s ...", loglvl); - break; - } - } - printk("\n"); -} - -static int kstack_depth_to_print = 24; - -void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl) -{ - unsigned long *stack; - int i; - - /* - * debugging aid: "show_stack(NULL, NULL, KERN_EMERG);" prints the - * back trace for this cpu. - */ - if (sp == NULL) - sp = (unsigned long *)&sp; - - stack = sp; - for (i = 0; i < kstack_depth_to_print; i++) { - if (((long) stack & (THREAD_SIZE-1)) == 0) - break; - if (i && ((i % 4) == 0)) - printk("%s ", loglvl); - printk("%016lx ", *stack++); - } - printk("\n"); - dik_show_trace(sp, loglvl); -} - void die_if_kernel(char *str, struct pt_regs *regs, long err) { if (regs->ps & 8) @@ -125,7 +85,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) printk("%s(%d): %s %ld\n", current->comm, task_pid_nr(current), str, err); dik_show_regs(regs); add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); - dik_show_trace((unsigned long *)(regs+1), KERN_DEFAULT); + show_stack(current, NULL, KERN_EMERG); dik_show_code((unsigned int *)regs->pc); if (test_and_set_thread_flag(TIF_DIE_IF_KERNEL)) { @@ -535,7 +495,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, dik_show_regs(regs); dik_show_code((unsigned int *)pc); - dik_show_trace((unsigned long *)(regs+1), KERN_DEFAULT); + show_stack(current, NULL, KERN_EMERG); if (test_and_set_thread_flag(TIF_DIE_IF_KERNEL)) { printk("die_if_kernel recursion detected.\n"); -- Gitee From 8cc109c4a51ea3c343c15b47eb62d99d0adae211 Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Tue, 21 Jun 2022 14:19:58 +0800 Subject: [PATCH 67/71] sw64: reimplement get_wchan() Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GFUD -------------------------------- The get_wchan() always return 0 because `fp > sp` is false. This patch reimplements it entirely and fixes this error. Signed-off-by: Wu Liliu Signed-off-by: Gu Zitao --- arch/sw_64/kernel/process.c | 51 ---------------------------------- arch/sw_64/kernel/stacktrace.c | 22 +++++++++++++++ 2 files changed, 22 insertions(+), 51 deletions(-) diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index da721d4266ee..a75ae20205f3 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -226,57 +226,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) } EXPORT_SYMBOL(dump_fpu); -/* - * Under heavy swap load I've seen this lose in an ugly way. So do - * some extra sanity checking on the ranges we expect these pointers - * to be in so that we can fail gracefully. This is just for ps after - * all. -- r~ - */ - -unsigned long -thread_saved_pc(struct task_struct *t) -{ - unsigned long top, fp, sp; - - top = (unsigned long)task_stack_page(t) + 2 * PAGE_SIZE; - sp = task_thread_info(t)->pcb.ksp; - fp = t->thread.s[6]; - - if (fp > sp && fp < top) - return *(unsigned long *)fp; - - return 0; -} - -unsigned long -get_wchan(struct task_struct *p) -{ - unsigned long schedule_frame; - unsigned long pc, top, sp; - - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - /* - * This one depends on the frame size of schedule(). Do a - * "disass schedule" in gdb to find the frame size. Also, the - * code assumes that sleep_on() follows immediately after - * interruptible_sleep_on() and that add_timer() follows - * immediately after interruptible_sleep(). Ugly, isn't it? - * Maybe adding a wchan field to task_struct would be better, - * after all... - */ - - pc = thread_saved_pc(p); - if (in_sched_functions(pc)) { - top = (unsigned long)task_stack_page(p) + 2 * PAGE_SIZE; - sp = task_thread_info(p)->pcb.ksp; - schedule_frame = p->thread.s[6]; - if (schedule_frame > sp && schedule_frame < top) - return ((unsigned long *)schedule_frame)[12]; - } - return pc; -} - unsigned long arch_randomize_brk(struct mm_struct *mm) { return randomize_page(mm->brk, 0x02000000); diff --git a/arch/sw_64/kernel/stacktrace.c b/arch/sw_64/kernel/stacktrace.c index 4e9acf99aaab..b51b1500c736 100644 --- a/arch/sw_64/kernel/stacktrace.c +++ b/arch/sw_64/kernel/stacktrace.c @@ -172,3 +172,25 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) trace->entries[trace->nr_entries++] = ULONG_MAX; } EXPORT_SYMBOL_GPL(save_stack_trace_tsk); + +static int save_pc(unsigned long pc, void *data) +{ + unsigned long *p = data; + *p = 0; + + if (!in_sched_functions(pc)) + *p = pc; + + return *p; +} + +unsigned long get_wchan(struct task_struct *tsk) +{ + unsigned long pc; + + if (!tsk || tsk == current || tsk->state == TASK_RUNNING) + return 0; + walk_stackframe(tsk, NULL, save_pc, &pc); + + return pc; +} -- Gitee From a3266d177538c7304143e30f9c1c9de6cda945d4 Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Fri, 24 Jun 2022 14:12:33 +0800 Subject: [PATCH 68/71] sw64: reimplement save_stack_trace() Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GFQQ -------------------------------- It used to save stack-backtrace addresses by SP, which is inaccurate. In order to implement this function accurately, we provide two ways to support it. Signed-off-by: Wu Liliu Signed-off-by: Gu Zitao --- arch/sw_64/kernel/stacktrace.c | 62 ++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/arch/sw_64/kernel/stacktrace.c b/arch/sw_64/kernel/stacktrace.c index b51b1500c736..7b5ddc78bd6d 100644 --- a/arch/sw_64/kernel/stacktrace.c +++ b/arch/sw_64/kernel/stacktrace.c @@ -139,40 +139,58 @@ void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl) walk_stackframe(task, NULL, print_address_trace, (void *)loglvl); } +#ifdef CONFIG_STACKTRACE /* * Save stack-backtrace addresses into a stack_trace buffer. */ -void save_stack_trace(struct stack_trace *trace) +struct stack_trace_data { + struct stack_trace *trace; + unsigned int nosched; +}; + +int save_trace(unsigned long pc, void *d) { - save_stack_trace_tsk(current, trace); -} -EXPORT_SYMBOL_GPL(save_stack_trace); + struct stack_trace_data *data = d; + struct stack_trace *trace = data->trace; + + if (data->nosched && in_sched_functions(pc)) + return 0; + if (trace->skip > 0) { + trace->skip--; + return 0; + } + trace->entries[trace->nr_entries++] = pc; + return (trace->nr_entries >= trace->max_entries); +} -void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +static void __save_stack_trace(struct task_struct *tsk, + struct stack_trace *trace, unsigned int nosched) { - unsigned long *sp = (unsigned long *)task_thread_info(tsk)->pcb.ksp; - unsigned long addr; - - WARN_ON(trace->nr_entries || !trace->max_entries); - - while (!kstack_end(sp)) { - addr = *sp++; - if (__kernel_text_address(addr) && - !in_sched_functions(addr)) { - if (trace->skip > 0) - trace->skip--; - else - trace->entries[trace->nr_entries++] = addr; - if (trace->nr_entries >= trace->max_entries) - break; - } - } + struct stack_trace_data data; + + data.trace = trace; + data.nosched = nosched; + + walk_stackframe(tsk, NULL, save_trace, &data); + if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; } + +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + __save_stack_trace(tsk, trace, 1); +} EXPORT_SYMBOL_GPL(save_stack_trace_tsk); +void save_stack_trace(struct stack_trace *trace) +{ + __save_stack_trace(current, trace, 0); +} +EXPORT_SYMBOL_GPL(save_stack_trace); +#endif + static int save_pc(unsigned long pc, void *data) { unsigned long *p = data; -- Gitee From d14ec0e7e888b5ab16142e0a71da4d99183587b6 Mon Sep 17 00:00:00 2001 From: Wang Yuanheng Date: Mon, 27 Jun 2022 09:02:01 +0800 Subject: [PATCH 69/71] sw64: kvm: enable binding_vcpu debug dynamically Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GFR5 -------------------------------- Add a bool debugfs file /sys/kernel/debug/sw_64/bind_vcpu, you can echo 1/Y to enable bind vcpu, or echo 0/N to disable it. Determin which node to bind the core according to the physical address assigned to the guest. Signed-off-by: Wang Yuanheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/Makefile | 2 +- arch/sw_64/kernel/bindvcpu.c | 29 +++++++++++++++++++++++++++++ arch/sw_64/kvm/kvm-sw64.c | 13 ++++++++++++- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 arch/sw_64/kernel/bindvcpu.c diff --git a/arch/sw_64/kernel/Makefile b/arch/sw_64/kernel/Makefile index 94b63d6a286b..d4dc9e175d67 100644 --- a/arch/sw_64/kernel/Makefile +++ b/arch/sw_64/kernel/Makefile @@ -31,7 +31,7 @@ obj-$(CONFIG_HIBERNATION) += hibernate_asm.o hibernate.o obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_PCI) += pci_common.o obj-$(CONFIG_RELOCATABLE) += relocate.o -obj-$(CONFIG_DEBUG_FS) += segvdbg.o +obj-$(CONFIG_DEBUG_FS) += segvdbg.o bindvcpu.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o ifndef CONFIG_PCI diff --git a/arch/sw_64/kernel/bindvcpu.c b/arch/sw_64/kernel/bindvcpu.c new file mode 100644 index 000000000000..611c395c144b --- /dev/null +++ b/arch/sw_64/kernel/bindvcpu.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Wang Yuanheng + * Author: Wang Yuanheng + * + */ + +#include +#include +#include +#include +#include + +extern bool bind_vcpu_enabled; + +static int __init bind_vcpu_init(void) +{ + struct dentry *bindvcpu; + + if (!sw64_debugfs_dir) + return -ENODEV; + + bindvcpu = debugfs_create_bool("bind_vcpu", 0644, + sw64_debugfs_dir, &bind_vcpu_enabled); + if (!bindvcpu) + return -ENOMEM; + return 0; +} +late_initcall(bind_vcpu_init); diff --git a/arch/sw_64/kvm/kvm-sw64.c b/arch/sw_64/kvm/kvm-sw64.c index af29d0ca8e7f..de81f7efe01a 100644 --- a/arch/sw_64/kvm/kvm-sw64.c +++ b/arch/sw_64/kvm/kvm-sw64.c @@ -12,7 +12,7 @@ #include #include #include - +#include #include #include @@ -21,6 +21,7 @@ bool set_msi_flag; unsigned long sw64_kvm_last_vpn[NR_CPUS]; +__read_mostly bool bind_vcpu_enabled; #define cpu_last_vpn(cpuid) sw64_kvm_last_vpn[cpuid] #ifdef CONFIG_SUBARCH_C3B @@ -537,6 +538,16 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) #ifndef CONFIG_KVM_MEMHOTPLUG vcpu->arch.vcb.vpcr = get_vpcr(vcpu->kvm->arch.host_phys_addr, vcpu->kvm->arch.size, 0); + + if (unlikely(bind_vcpu_enabled)) { + int nid; + unsigned long end; + + end = vcpu->kvm->arch.host_phys_addr + vcpu->kvm->arch.size; + nid = pfn_to_nid(PHYS_PFN(vcpu->kvm->arch.host_phys_addr)); + if (pfn_to_nid(PHYS_PFN(end)) == nid) + set_cpus_allowed_ptr(vcpu->arch.tsk, node_to_cpumask_map[nid]); + } #else unsigned long seg_base = virt_to_phys(vcpu->kvm->arch.seg_pgd); -- Gitee From 0d22be5a4f5fb31a45fb4c55dde5037bfba3c572 Mon Sep 17 00:00:00 2001 From: Gu Zitao Date: Tue, 28 Jun 2022 08:51:26 +0800 Subject: [PATCH 70/71] sw64: rename CONFIG_HAVE_GENERIC_GUP to CONFIG_HAVE_FAST_GUP Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5GFRP -------------------------------- This patch is a backport of commit 67a929e097b7 ("mm: rename CONFIG_HAVE_GENERIC_GUP to CONFIG_HAVE_FAST_GUP"). In order to use the generic GUP, let's do the same. Signed-off-by: Gu Zitao Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index ec6e583a5d9a..cf2f6f00708c 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -7,7 +7,7 @@ config SW64 select HAVE_OPROFILE select HAVE_PCSPKR_PLATFORM select HAVE_PERF_EVENTS - select HAVE_GENERIC_GUP + select HAVE_FAST_GUP select GENERIC_CLOCKEVENTS select GENERIC_IRQ_PROBE select GENERIC_IRQ_LEGACY -- Gitee From ce6455155eeacae6557fe0142e69a6c288ac970e Mon Sep 17 00:00:00 2001 From: Zhou Xuemei Date: Thu, 7 Jul 2022 17:19:10 +0800 Subject: [PATCH 71/71] sw64: fix floating point register corruption Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GFS3 -------------------------------- When csum_partial_copy_from_user is called in an interrupt, __copy_from_user will modify floating point register f10-f15 without restore register value. This will cause the value of the userspace register to be corrupted. Use memcpy() instead when called from kernel space. Signed-off-by: Zhou Xuemei Signed-off-by: Gu Zitao --- arch/sw_64/lib/csum_partial_copy.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/lib/csum_partial_copy.c b/arch/sw_64/lib/csum_partial_copy.c index 5e5274e82b2b..742dd63cdb70 100644 --- a/arch/sw_64/lib/csum_partial_copy.c +++ b/arch/sw_64/lib/csum_partial_copy.c @@ -61,7 +61,11 @@ csum_partial_cfu_dest_aligned(const unsigned long __user *src, unsigned long checksum = ~0U; int err = 0; - err = __copy_from_user(dst, src, len+8); + if (likely(!uaccess_kernel())) + err = __copy_from_user(dst, src, len + 8); + else + memcpy(dst, src, len + 8); + while (len > 0) { word = *dst; checksum += word; @@ -89,7 +93,10 @@ csum_partial_cfu_dest_unaligned(const unsigned long __user *src, unsigned long checksum = ~0U; int err = 0; - err = __copy_from_user(dst, src, len+8); + if (likely(!uaccess_kernel())) + err = __copy_from_user(dst, src, len + 8); + else + memcpy(dst, src, len + 8); dst = (unsigned long *)((unsigned long)dst & (~7UL)); word = *dst; -- Gitee