Received: by 2002:a19:771d:0:0:0:0:0 with SMTP id s29csp1261212lfc; Wed, 1 Jun 2022 13:25:28 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzI+YNXORNfKPPbcfMz/mkv/G1g4m3G8nko2M8ebnH+m9nlgWn0kQvhi9ClUSa8ti07iume X-Received: by 2002:a17:90a:778c:b0:1df:56a5:8474 with SMTP id v12-20020a17090a778c00b001df56a58474mr36388967pjk.63.1654115128474; Wed, 01 Jun 2022 13:25:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1654115128; cv=none; d=google.com; s=arc-20160816; b=i0OJo3OyzzXLC5GVEFmbdp4Zr06HRDxjPTMq2GGiIQeOQSEJtIY9WZie+G86zF42OH YNeARLo2d/kmBkhvdSXDO8O7Z4rkOd6REuwkkLyzf/pz4QTkeLmAkRwryanPlAdP0qXR kEgQTxH5jIP0Rf/1wg+LbX4x6VTBNv8E2t/ljMZ2GFoyjUGXMpl27eih8ITBXuV92Y2+ 49KPbjdkZvirdmJURgBlRvvYAiN1uQ/gv45/GdcPda1dMUx1tqGEcn8Chhd3LxV3Si0x Au9R3TZFlZR9Zvnm8xUm6WEKWyPmluUBuFKUxEBLK9/Arh1dJmJoavJ9vfVXsoAOHUBv 0zEQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:subject:cc:to:from :date:references:in-reply-to:message-id:mime-version:user-agent :feedback-id:dkim-signature:dkim-signature; bh=ghDzRFLE4McY1g+Cvd+/LVHAFq/Lw6zZCgUwfq1b2nQ=; b=wN8mNPFP3nGggXjiKZcR7zPLs5YIJ18QK9UICo7Hn0HsbmCgLPYogDk6ziKjWFnEcU BCdO7bJl8aB+KR9tIoCDXOAmw19xDqSNrZ8jkHFHcqBKoifSiB+4dslk9AdE7Fa1RIi7 0Im38K9UVUrR+XTFj9FZsXvqV378PWNw/qO1I7mdHgljlCzmmutmDrVy9YhwfBG9UY4x F6izWr8FMnS/QsL3ilFz3Ofai52O7fwF3uxBVlEepFEDbjFAVInIEnqgYXJbVDu2pb1v eufVPu7Jn/x9zMEtiO1I52TWJtGKGO7+Y4dRmqmmI7fp05Umyxj4KjA15fLHMxY4p2Ne Qh7A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@flygoat.com header.s=fm2 header.b=t8UzcaCy; dkim=pass header.i=@messagingengine.com header.s=fm1 header.b=VF3ArCtl; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=flygoat.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id i10-20020a17090332ca00b001640aae96e8si3742543plr.317.2022.06.01.13.25.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Jun 2022 13:25:28 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@flygoat.com header.s=fm2 header.b=t8UzcaCy; dkim=pass header.i=@messagingengine.com header.s=fm1 header.b=VF3ArCtl; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=flygoat.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 990DE2514A8; Wed, 1 Jun 2022 12:37:09 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352879AbiFAMbv (ORCPT + 99 others); Wed, 1 Jun 2022 08:31:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43642 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352921AbiFAMbr (ORCPT ); Wed, 1 Jun 2022 08:31:47 -0400 Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 293D9B4C; Wed, 1 Jun 2022 05:31:42 -0700 (PDT) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 685705C026C; Wed, 1 Jun 2022 08:31:41 -0400 (EDT) Received: from imap44 ([10.202.2.94]) by compute4.internal (MEProxy); Wed, 01 Jun 2022 08:31:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=flygoat.com; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to; s=fm2; t=1654086701; x= 1654173101; bh=ghDzRFLE4McY1g+Cvd+/LVHAFq/Lw6zZCgUwfq1b2nQ=; b=t 8UzcaCybzP/nQJRd6gPyZTBfW4TMaQT+KMRn/E5TbgtdakPvxy0AJVwGYN6XWGZT C6GaLTZDVBQdE0Fdv62ktaY5N+L74kmWYrypWqs9j/q24sEsWFqQnk/7OLUkxdOz vNfGPO5O+zjHWuhgSd0/4NuWj0Z5ZB+FPn61D7ZSyg4lCT+kg1GNYD+sWhQ+XckI Dtdb67rOFAwv+Rd7U7jxNwZbKmB78zzRkTqUJYPfCHD40wjBu6YtLfs5xipIk/Ej NB7xrfCvHeaHKlGXhkSKR9RkDAqJVB4/ail2KnB5EdaXdnBZE8CeclnvwAcB9PZo L8xzvtv7+9jHWEeULp77w== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1654086701; x= 1654173101; bh=ghDzRFLE4McY1g+Cvd+/LVHAFq/Lw6zZCgUwfq1b2nQ=; b=V F3ArCtlZ2lCwn5VWXw8oUowirW2XIg8nmouQvQw7B1FizL8Brx2PM2zo77m7IYPU x7a997x80TuRaPemkvSCTq5XbZua6WLNXfVzWkHLbue+w554YuodDcedl9sXX9/v up/9hBXNllSlPYc5ogRZZSyHYZke4YTkYW99kSa4l/ao5khS1MH1g/LjNcZCpfhE koi26Mf14JTYRUD+7L0PSmOpXLqZrFrp5DVGTeH6Rh0Q0nnzPyEUbuROdJ30Bi+H Xfa1wp+VQLGl/xdX1CeAANpYCH/58pS431KHZY/pKJDuydisJh1YJyS7VHwFqLPS BD10jj82ZNhx3JKUyh8KQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrledtgdehudcutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpefofgggkfgjfhffhffvvefutgfgsehtqhertderreejnecuhfhrohhmpedflfhi rgiguhhnucgjrghnghdfuceojhhirgiguhhnrdihrghnghesfhhlhihgohgrthdrtghomh eqnecuggftrfgrthhtvghrnhepudefgeeftedugeehffdtheefgfevffelfefghefhjeeu geevtefhudduvdeihefgnecuvehluhhsthgvrhfuihiivgepudenucfrrghrrghmpehmrg hilhhfrhhomhepjhhirgiguhhnrdihrghnghesfhhlhihgohgrthdrtghomh X-ME-Proxy: Feedback-ID: ifd894703:Fastmail Received: by mailuser.nyi.internal (Postfix, from userid 501) id CEFD136A006D; Wed, 1 Jun 2022 08:31:40 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.7.0-alpha0-591-gfe6c3a2700-fm-20220427.001-gfe6c3a27 Mime-Version: 1.0 Message-Id: In-Reply-To: <20220601100005.2989022-19-chenhuacai@loongson.cn> References: <20220601100005.2989022-1-chenhuacai@loongson.cn> <20220601100005.2989022-19-chenhuacai@loongson.cn> Date: Wed, 01 Jun 2022 13:31:19 +0100 From: "Jiaxun Yang" To: "Huacai Chen" , "Arnd Bergmann" , "Andy Lutomirski" , "Thomas Gleixner" , "Peter Zijlstra" , "Andrew Morton" , "David Airlie" , "Jonathan Corbet" , "Linus Torvalds" Cc: linux-arch@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, "Xuefeng Li" , "Yanteng Si" , "Huacai Chen" , "Guo Ren" , "Xuerui Wang" , "Stephen Rothwell" , "WANG Xuerui" Subject: Re: [PATCH V12 18/24] LoongArch: Add misc common routines Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org =E5=9C=A82022=E5=B9=B46=E6=9C=881=E6=97=A5=E5=85=AD=E6=9C=88 =E4=B8=8A=E5= =8D=8810:59=EF=BC=8CHuacai Chen=E5=86=99=E9=81=93=EF=BC=9A > Add some misc common routines for LoongArch, including: asm-offsets > routines, futex functions, i/o memory access functions, frame-buffer > functions, procfs information display, etc. > > Reviewed-by: WANG Xuerui > Signed-off-by: Huacai Chen Reviewed-by: Jiaxun Yang > --- > arch/loongarch/include/asm/asm-offsets.h | 5 + > arch/loongarch/include/asm/fb.h | 23 ++ > arch/loongarch/include/asm/futex.h | 107 ++++++++++ > arch/loongarch/include/asm/io.h | 129 ++++++++++++ > arch/loongarch/kernel/asm-offsets.c | 254 +++++++++++++++++++++++ > arch/loongarch/kernel/io.c | 94 +++++++++ > arch/loongarch/kernel/proc.c | 122 +++++++++++ > 7 files changed, 734 insertions(+) > create mode 100644 arch/loongarch/include/asm/asm-offsets.h > create mode 100644 arch/loongarch/include/asm/fb.h > create mode 100644 arch/loongarch/include/asm/futex.h > create mode 100644 arch/loongarch/include/asm/io.h > create mode 100644 arch/loongarch/kernel/asm-offsets.c > create mode 100644 arch/loongarch/kernel/io.c > create mode 100644 arch/loongarch/kernel/proc.c > > diff --git a/arch/loongarch/include/asm/asm-offsets.h=20 > b/arch/loongarch/include/asm/asm-offsets.h > new file mode 100644 > index 000000000000..d9ad88d293e7 > --- /dev/null > +++ b/arch/loongarch/include/asm/asm-offsets.h > @@ -0,0 +1,5 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited > + */ > +#include > diff --git a/arch/loongarch/include/asm/fb.h=20 > b/arch/loongarch/include/asm/fb.h > new file mode 100644 > index 000000000000..3116bde8772d > --- /dev/null > +++ b/arch/loongarch/include/asm/fb.h > @@ -0,0 +1,23 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited > + */ > +#ifndef _ASM_FB_H_ > +#define _ASM_FB_H_ > + > +#include > +#include > +#include > + > +static inline void fb_pgprotect(struct file *file, struct=20 > vm_area_struct *vma, > + unsigned long off) > +{ > + vma->vm_page_prot =3D pgprot_writecombine(vma->vm_page_prot); > +} > + > +static inline int fb_is_primary_device(struct fb_info *info) > +{ > + return 0; > +} > + > +#endif /* _ASM_FB_H_ */ > diff --git a/arch/loongarch/include/asm/futex.h=20 > b/arch/loongarch/include/asm/futex.h > new file mode 100644 > index 000000000000..b27d55f92db7 > --- /dev/null > +++ b/arch/loongarch/include/asm/futex.h > @@ -0,0 +1,107 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited > + */ > +#ifndef _ASM_FUTEX_H > +#define _ASM_FUTEX_H > + > +#include > +#include > +#include > +#include > +#include > + > +#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ > +{ \ > + __asm__ __volatile__( \ > + "1: ll.w %1, %4 # __futex_atomic_op\n" \ > + " " insn " \n" \ > + "2: sc.w $t0, %2 \n" \ > + " beq $t0, $zero, 1b \n" \ > + "3: \n" \ > + " .section .fixup,\"ax\" \n" \ > + "4: li.w %0, %6 \n" \ > + " b 3b \n" \ > + " .previous \n" \ > + " .section __ex_table,\"a\" \n" \ > + " "__UA_ADDR "\t1b, 4b \n" \ > + " "__UA_ADDR "\t2b, 4b \n" \ > + " .previous \n" \ > + : "=3Dr" (ret), "=3D&r" (oldval), \ > + "=3DZC" (*uaddr) \ > + : "0" (0), "ZC" (*uaddr), "Jr" (oparg), \ > + "i" (-EFAULT) \ > + : "memory", "t0"); \ > +} > + > +static inline int > +arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user=20 > *uaddr) > +{ > + int oldval =3D 0, ret =3D 0; > + > + pagefault_disable(); > + > + switch (op) { > + case FUTEX_OP_SET: > + __futex_atomic_op("move $t0, %z5", ret, oldval, uaddr, oparg); > + break; > + case FUTEX_OP_ADD: > + __futex_atomic_op("add.w $t0, %1, %z5", ret, oldval, uaddr, oparg); > + break; > + case FUTEX_OP_OR: > + __futex_atomic_op("or $t0, %1, %z5", ret, oldval, uaddr, oparg); > + break; > + case FUTEX_OP_ANDN: > + __futex_atomic_op("and $t0, %1, %z5", ret, oldval, uaddr, ~oparg); > + break; > + case FUTEX_OP_XOR: > + __futex_atomic_op("xor $t0, %1, %z5", ret, oldval, uaddr, oparg); > + break; > + default: > + ret =3D -ENOSYS; > + } > + > + pagefault_enable(); > + > + if (!ret) > + *oval =3D oldval; > + > + return ret; > +} > + > +static inline int > +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32=20 > oldval, u32 newval) > +{ > + int ret =3D 0; > + u32 val =3D 0; > + > + if (!access_ok(uaddr, sizeof(u32))) > + return -EFAULT; > + > + __asm__ __volatile__( > + "# futex_atomic_cmpxchg_inatomic \n" > + "1: ll.w %1, %3 \n" > + " bne %1, %z4, 3f \n" > + " or $t0, %z5, $zero \n" > + "2: sc.w $t0, %2 \n" > + " beq $zero, $t0, 1b \n" > + "3: \n" > + " .section .fixup,\"ax\" \n" > + "4: li.d %0, %6 \n" > + " b 3b \n" > + " .previous \n" > + " .section __ex_table,\"a\" \n" > + " "__UA_ADDR "\t1b, 4b \n" > + " "__UA_ADDR "\t2b, 4b \n" > + " .previous \n" > + : "+r" (ret), "=3D&r" (val), "=3D" GCC_OFF_SMALL_ASM() (*uaddr) > + : GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval), > + "i" (-EFAULT) > + : "memory", "t0"); > + > + *uval =3D val; > + > + return ret; > +} > + > +#endif /* _ASM_FUTEX_H */ > diff --git a/arch/loongarch/include/asm/io.h=20 > b/arch/loongarch/include/asm/io.h > new file mode 100644 > index 000000000000..884599739b36 > --- /dev/null > +++ b/arch/loongarch/include/asm/io.h > @@ -0,0 +1,129 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited > + */ > +#ifndef _ASM_IO_H > +#define _ASM_IO_H > + > +#define ARCH_HAS_IOREMAP_WC > + > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* > + * On LoongArch, I/O ports mappring is following: > + * > + * | .... | > + * |-----------------------| > + * | pci io ports(64K~32M) | > + * |-----------------------| > + * | isa io ports(0 ~16K) | > + * PCI_IOBASE ->|-----------------------| > + * | .... | > + */ > +#define PCI_IOBASE ((void __iomem *)(vm_map_base + (2 * PAGE_SIZE))) > +#define PCI_IOSIZE SZ_32M > +#define ISA_IOSIZE SZ_16K > +#define IO_SPACE_LIMIT (PCI_IOSIZE - 1) > + > +/* > + * Change "struct page" to physical address. > + */ > +#define page_to_phys(page) ((phys_addr_t)page_to_pfn(page) <<=20 > PAGE_SHIFT) > + > +extern void __init __iomem *early_ioremap(u64 phys_addr, unsigned lon= g=20 > size); > +extern void __init early_iounmap(void __iomem *addr, unsigned long=20 > size); > + > +#define early_memremap early_ioremap > +#define early_memunmap early_iounmap > + > +static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned=20 > long size, > + unsigned long prot_val) > +{ > + if (prot_val =3D=3D _CACHE_CC) > + return (void __iomem *)(unsigned long)(CACHE_BASE + offset); > + else > + return (void __iomem *)(unsigned long)(UNCACHE_BASE + offset); > +} > + > +/* > + * ioremap - map bus memory into CPU space > + * @offset: bus address of the memory > + * @size: size of the resource to map > + * > + * ioremap performs a platform specific sequence of operations to > + * make bus memory CPU accessible via the readb/readw/readl/writeb/ > + * writew/writel functions and the other mmio helpers. The returned > + * address is not guaranteed to be usable directly as a virtual > + * address. > + */ > +#define ioremap(offset, size) \ > + ioremap_prot((offset), (size), _CACHE_SUC) > + > +/* > + * ioremap_wc - map bus memory into CPU space > + * @offset: bus address of the memory > + * @size: size of the resource to map > + * > + * ioremap_wc performs a platform specific sequence of operations to > + * make bus memory CPU accessible via the readb/readw/readl/writeb/ > + * writew/writel functions and the other mmio helpers. The returned > + * address is not guaranteed to be usable directly as a virtual > + * address. > + * > + * This version of ioremap ensures that the memory is marked uncachab= le > + * but accelerated by means of write-combining feature. It is=20 > specifically > + * useful for PCIe prefetchable windows, which may vastly improve a > + * communications performance. If it was determined on boot stage, wh= at > + * CPU CCA doesn't support WUC, the method shall fall-back to the > + * _CACHE_SUC option (see cpu_probe() method). > + */ > +#define ioremap_wc(offset, size) \ > + ioremap_prot((offset), (size), _CACHE_WUC) > + > +/* > + * ioremap_cache - map bus memory into CPU space > + * @offset: bus address of the memory > + * @size: size of the resource to map > + * > + * ioremap_cache performs a platform specific sequence of operations = to > + * make bus memory CPU accessible via the readb/readw/readl/writeb/ > + * writew/writel functions and the other mmio helpers. The returned > + * address is not guaranteed to be usable directly as a virtual > + * address. > + * > + * This version of ioremap ensures that the memory is marked cachable=20 > by > + * the CPU. Also enables full write-combining. Useful for some > + * memory-like regions on I/O busses. > + */ > +#define ioremap_cache(offset, size) \ > + ioremap_prot((offset), (size), _CACHE_CC) > + > +static inline void iounmap(const volatile void __iomem *addr) > +{ > +} > + > +#define mmiowb() asm volatile ("dbar 0" ::: "memory") > + > +/* > + * String version of I/O memory access operations. > + */ > +extern void __memset_io(volatile void __iomem *dst, int c, size_t=20 > count); > +extern void __memcpy_toio(volatile void __iomem *to, const void *from= ,=20 > size_t count); > +extern void __memcpy_fromio(void *to, const volatile void __iomem=20 > *from, size_t count); > +#define memset_io(c, v, l) __memset_io((c), (v), (l)) > +#define memcpy_fromio(a, c, l) __memcpy_fromio((a), (c), (l)) > +#define memcpy_toio(c, a, l) __memcpy_toio((c), (a), (l)) > + > +#include > + > +#endif /* _ASM_IO_H */ > diff --git a/arch/loongarch/kernel/asm-offsets.c=20 > b/arch/loongarch/kernel/asm-offsets.c > new file mode 100644 > index 000000000000..3531e3c60a6e > --- /dev/null > +++ b/arch/loongarch/kernel/asm-offsets.c > @@ -0,0 +1,254 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * asm-offsets.c: Calculate pt_regs and task_struct offsets. > + * > + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +void output_ptreg_defines(void) > +{ > + COMMENT("LoongArch pt_regs offsets."); > + OFFSET(PT_R0, pt_regs, regs[0]); > + OFFSET(PT_R1, pt_regs, regs[1]); > + OFFSET(PT_R2, pt_regs, regs[2]); > + OFFSET(PT_R3, pt_regs, regs[3]); > + OFFSET(PT_R4, pt_regs, regs[4]); > + OFFSET(PT_R5, pt_regs, regs[5]); > + OFFSET(PT_R6, pt_regs, regs[6]); > + OFFSET(PT_R7, pt_regs, regs[7]); > + OFFSET(PT_R8, pt_regs, regs[8]); > + OFFSET(PT_R9, pt_regs, regs[9]); > + OFFSET(PT_R10, pt_regs, regs[10]); > + OFFSET(PT_R11, pt_regs, regs[11]); > + OFFSET(PT_R12, pt_regs, regs[12]); > + OFFSET(PT_R13, pt_regs, regs[13]); > + OFFSET(PT_R14, pt_regs, regs[14]); > + OFFSET(PT_R15, pt_regs, regs[15]); > + OFFSET(PT_R16, pt_regs, regs[16]); > + OFFSET(PT_R17, pt_regs, regs[17]); > + OFFSET(PT_R18, pt_regs, regs[18]); > + OFFSET(PT_R19, pt_regs, regs[19]); > + OFFSET(PT_R20, pt_regs, regs[20]); > + OFFSET(PT_R21, pt_regs, regs[21]); > + OFFSET(PT_R22, pt_regs, regs[22]); > + OFFSET(PT_R23, pt_regs, regs[23]); > + OFFSET(PT_R24, pt_regs, regs[24]); > + OFFSET(PT_R25, pt_regs, regs[25]); > + OFFSET(PT_R26, pt_regs, regs[26]); > + OFFSET(PT_R27, pt_regs, regs[27]); > + OFFSET(PT_R28, pt_regs, regs[28]); > + OFFSET(PT_R29, pt_regs, regs[29]); > + OFFSET(PT_R30, pt_regs, regs[30]); > + OFFSET(PT_R31, pt_regs, regs[31]); > + OFFSET(PT_CRMD, pt_regs, csr_crmd); > + OFFSET(PT_PRMD, pt_regs, csr_prmd); > + OFFSET(PT_EUEN, pt_regs, csr_euen); > + OFFSET(PT_ECFG, pt_regs, csr_ecfg); > + OFFSET(PT_ESTAT, pt_regs, csr_estat); > + OFFSET(PT_ERA, pt_regs, csr_era); > + OFFSET(PT_BVADDR, pt_regs, csr_badvaddr); > + OFFSET(PT_ORIG_A0, pt_regs, orig_a0); > + DEFINE(PT_SIZE, sizeof(struct pt_regs)); > + BLANK(); > +} > + > +void output_task_defines(void) > +{ > + COMMENT("LoongArch task_struct offsets."); > + OFFSET(TASK_STATE, task_struct, __state); > + OFFSET(TASK_THREAD_INFO, task_struct, stack); > + OFFSET(TASK_FLAGS, task_struct, flags); > + OFFSET(TASK_MM, task_struct, mm); > + OFFSET(TASK_PID, task_struct, pid); > + DEFINE(TASK_STRUCT_SIZE, sizeof(struct task_struct)); > + BLANK(); > +} > + > +void output_thread_info_defines(void) > +{ > + COMMENT("LoongArch thread_info offsets."); > + OFFSET(TI_TASK, thread_info, task); > + OFFSET(TI_FLAGS, thread_info, flags); > + OFFSET(TI_TP_VALUE, thread_info, tp_value); > + OFFSET(TI_CPU, thread_info, cpu); > + OFFSET(TI_PRE_COUNT, thread_info, preempt_count); > + OFFSET(TI_REGS, thread_info, regs); > + DEFINE(_THREAD_SIZE, THREAD_SIZE); > + DEFINE(_THREAD_MASK, THREAD_MASK); > + DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE); > + DEFINE(_IRQ_STACK_START, IRQ_STACK_START); > + BLANK(); > +} > + > +void output_thread_defines(void) > +{ > + COMMENT("LoongArch specific thread_struct offsets."); > + OFFSET(THREAD_REG01, task_struct, thread.reg01); > + OFFSET(THREAD_REG03, task_struct, thread.reg03); > + OFFSET(THREAD_REG22, task_struct, thread.reg22); > + OFFSET(THREAD_REG23, task_struct, thread.reg23); > + OFFSET(THREAD_REG24, task_struct, thread.reg24); > + OFFSET(THREAD_REG25, task_struct, thread.reg25); > + OFFSET(THREAD_REG26, task_struct, thread.reg26); > + OFFSET(THREAD_REG27, task_struct, thread.reg27); > + OFFSET(THREAD_REG28, task_struct, thread.reg28); > + OFFSET(THREAD_REG29, task_struct, thread.reg29); > + OFFSET(THREAD_REG30, task_struct, thread.reg30); > + OFFSET(THREAD_REG31, task_struct, thread.reg31); > + OFFSET(THREAD_CSRCRMD, task_struct, > + thread.csr_crmd); > + OFFSET(THREAD_CSRPRMD, task_struct, > + thread.csr_prmd); > + OFFSET(THREAD_CSREUEN, task_struct, > + thread.csr_euen); > + OFFSET(THREAD_CSRECFG, task_struct, > + thread.csr_ecfg); > + > + OFFSET(THREAD_SCR0, task_struct, thread.scr0); > + OFFSET(THREAD_SCR1, task_struct, thread.scr1); > + OFFSET(THREAD_SCR2, task_struct, thread.scr2); > + OFFSET(THREAD_SCR3, task_struct, thread.scr3); > + > + OFFSET(THREAD_EFLAGS, task_struct, thread.eflags); > + > + OFFSET(THREAD_FPU, task_struct, thread.fpu); > + > + OFFSET(THREAD_BVADDR, task_struct, \ > + thread.csr_badvaddr); > + OFFSET(THREAD_ECODE, task_struct, \ > + thread.error_code); > + OFFSET(THREAD_TRAPNO, task_struct, thread.trap_nr); > + BLANK(); > +} > + > +void output_thread_fpu_defines(void) > +{ > + OFFSET(THREAD_FPR0, loongarch_fpu, fpr[0]); > + OFFSET(THREAD_FPR1, loongarch_fpu, fpr[1]); > + OFFSET(THREAD_FPR2, loongarch_fpu, fpr[2]); > + OFFSET(THREAD_FPR3, loongarch_fpu, fpr[3]); > + OFFSET(THREAD_FPR4, loongarch_fpu, fpr[4]); > + OFFSET(THREAD_FPR5, loongarch_fpu, fpr[5]); > + OFFSET(THREAD_FPR6, loongarch_fpu, fpr[6]); > + OFFSET(THREAD_FPR7, loongarch_fpu, fpr[7]); > + OFFSET(THREAD_FPR8, loongarch_fpu, fpr[8]); > + OFFSET(THREAD_FPR9, loongarch_fpu, fpr[9]); > + OFFSET(THREAD_FPR10, loongarch_fpu, fpr[10]); > + OFFSET(THREAD_FPR11, loongarch_fpu, fpr[11]); > + OFFSET(THREAD_FPR12, loongarch_fpu, fpr[12]); > + OFFSET(THREAD_FPR13, loongarch_fpu, fpr[13]); > + OFFSET(THREAD_FPR14, loongarch_fpu, fpr[14]); > + OFFSET(THREAD_FPR15, loongarch_fpu, fpr[15]); > + OFFSET(THREAD_FPR16, loongarch_fpu, fpr[16]); > + OFFSET(THREAD_FPR17, loongarch_fpu, fpr[17]); > + OFFSET(THREAD_FPR18, loongarch_fpu, fpr[18]); > + OFFSET(THREAD_FPR19, loongarch_fpu, fpr[19]); > + OFFSET(THREAD_FPR20, loongarch_fpu, fpr[20]); > + OFFSET(THREAD_FPR21, loongarch_fpu, fpr[21]); > + OFFSET(THREAD_FPR22, loongarch_fpu, fpr[22]); > + OFFSET(THREAD_FPR23, loongarch_fpu, fpr[23]); > + OFFSET(THREAD_FPR24, loongarch_fpu, fpr[24]); > + OFFSET(THREAD_FPR25, loongarch_fpu, fpr[25]); > + OFFSET(THREAD_FPR26, loongarch_fpu, fpr[26]); > + OFFSET(THREAD_FPR27, loongarch_fpu, fpr[27]); > + OFFSET(THREAD_FPR28, loongarch_fpu, fpr[28]); > + OFFSET(THREAD_FPR29, loongarch_fpu, fpr[29]); > + OFFSET(THREAD_FPR30, loongarch_fpu, fpr[30]); > + OFFSET(THREAD_FPR31, loongarch_fpu, fpr[31]); > + > + OFFSET(THREAD_FCSR, loongarch_fpu, fcsr); > + OFFSET(THREAD_FCC, loongarch_fpu, fcc); > + OFFSET(THREAD_VCSR, loongarch_fpu, vcsr); > + BLANK(); > +} > + > +void output_mm_defines(void) > +{ > + COMMENT("Size of struct page"); > + DEFINE(STRUCT_PAGE_SIZE, sizeof(struct page)); > + BLANK(); > + COMMENT("Linux mm_struct offsets."); > + OFFSET(MM_USERS, mm_struct, mm_users); > + OFFSET(MM_PGD, mm_struct, pgd); > + OFFSET(MM_CONTEXT, mm_struct, context); > + BLANK(); > + DEFINE(_PGD_T_SIZE, sizeof(pgd_t)); > + DEFINE(_PMD_T_SIZE, sizeof(pmd_t)); > + DEFINE(_PTE_T_SIZE, sizeof(pte_t)); > + BLANK(); > + DEFINE(_PGD_T_LOG2, PGD_T_LOG2); > +#ifndef __PAGETABLE_PMD_FOLDED > + DEFINE(_PMD_T_LOG2, PMD_T_LOG2); > +#endif > + DEFINE(_PTE_T_LOG2, PTE_T_LOG2); > + BLANK(); > + DEFINE(_PGD_ORDER, PGD_ORDER); > +#ifndef __PAGETABLE_PMD_FOLDED > + DEFINE(_PMD_ORDER, PMD_ORDER); > +#endif > + DEFINE(_PTE_ORDER, PTE_ORDER); > + BLANK(); > + DEFINE(_PMD_SHIFT, PMD_SHIFT); > + DEFINE(_PGDIR_SHIFT, PGDIR_SHIFT); > + BLANK(); > + DEFINE(_PTRS_PER_PGD, PTRS_PER_PGD); > + DEFINE(_PTRS_PER_PMD, PTRS_PER_PMD); > + DEFINE(_PTRS_PER_PTE, PTRS_PER_PTE); > + BLANK(); > + DEFINE(_PAGE_SHIFT, PAGE_SHIFT); > + DEFINE(_PAGE_SIZE, PAGE_SIZE); > + BLANK(); > +} > + > +void output_sc_defines(void) > +{ > + COMMENT("Linux sigcontext offsets."); > + OFFSET(SC_REGS, sigcontext, sc_regs); > + OFFSET(SC_PC, sigcontext, sc_pc); > + BLANK(); > +} > + > +void output_signal_defines(void) > +{ > + COMMENT("Linux signal numbers."); > + DEFINE(_SIGHUP, SIGHUP); > + DEFINE(_SIGINT, SIGINT); > + DEFINE(_SIGQUIT, SIGQUIT); > + DEFINE(_SIGILL, SIGILL); > + DEFINE(_SIGTRAP, SIGTRAP); > + DEFINE(_SIGIOT, SIGIOT); > + DEFINE(_SIGABRT, SIGABRT); > + DEFINE(_SIGFPE, SIGFPE); > + DEFINE(_SIGKILL, SIGKILL); > + DEFINE(_SIGBUS, SIGBUS); > + DEFINE(_SIGSEGV, SIGSEGV); > + DEFINE(_SIGSYS, SIGSYS); > + DEFINE(_SIGPIPE, SIGPIPE); > + DEFINE(_SIGALRM, SIGALRM); > + DEFINE(_SIGTERM, SIGTERM); > + DEFINE(_SIGUSR1, SIGUSR1); > + DEFINE(_SIGUSR2, SIGUSR2); > + DEFINE(_SIGCHLD, SIGCHLD); > + DEFINE(_SIGPWR, SIGPWR); > + DEFINE(_SIGWINCH, SIGWINCH); > + DEFINE(_SIGURG, SIGURG); > + DEFINE(_SIGIO, SIGIO); > + DEFINE(_SIGSTOP, SIGSTOP); > + DEFINE(_SIGTSTP, SIGTSTP); > + DEFINE(_SIGCONT, SIGCONT); > + DEFINE(_SIGTTIN, SIGTTIN); > + DEFINE(_SIGTTOU, SIGTTOU); > + DEFINE(_SIGVTALRM, SIGVTALRM); > + DEFINE(_SIGPROF, SIGPROF); > + DEFINE(_SIGXCPU, SIGXCPU); > + DEFINE(_SIGXFSZ, SIGXFSZ); > + BLANK(); > +} > diff --git a/arch/loongarch/kernel/io.c b/arch/loongarch/kernel/io.c > new file mode 100644 > index 000000000000..cb85bda5a6ad > --- /dev/null > +++ b/arch/loongarch/kernel/io.c > @@ -0,0 +1,94 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited > + */ > +#include > +#include > +#include > + > +/* > + * Copy data from IO memory space to "real" memory space. > + */ > +void __memcpy_fromio(void *to, const volatile void __iomem *from,=20 > size_t count) > +{ > + while (count && !IS_ALIGNED((unsigned long)from, 8)) { > + *(u8 *)to =3D __raw_readb(from); > + from++; > + to++; > + count--; > + } > + > + while (count >=3D 8) { > + *(u64 *)to =3D __raw_readq(from); > + from +=3D 8; > + to +=3D 8; > + count -=3D 8; > + } > + > + while (count) { > + *(u8 *)to =3D __raw_readb(from); > + from++; > + to++; > + count--; > + } > +} > +EXPORT_SYMBOL(__memcpy_fromio); > + > +/* > + * Copy data from "real" memory space to IO memory space. > + */ > +void __memcpy_toio(volatile void __iomem *to, const void *from, size_= t=20 > count) > +{ > + while (count && !IS_ALIGNED((unsigned long)to, 8)) { > + __raw_writeb(*(u8 *)from, to); > + from++; > + to++; > + count--; > + } > + > + while (count >=3D 8) { > + __raw_writeq(*(u64 *)from, to); > + from +=3D 8; > + to +=3D 8; > + count -=3D 8; > + } > + > + while (count) { > + __raw_writeb(*(u8 *)from, to); > + from++; > + to++; > + count--; > + } > +} > +EXPORT_SYMBOL(__memcpy_toio); > + > +/* > + * "memset" on IO memory space. > + */ > +void __memset_io(volatile void __iomem *dst, int c, size_t count) > +{ > + u64 qc =3D (u8)c; > + > + qc |=3D qc << 8; > + qc |=3D qc << 16; > + qc |=3D qc << 32; > + > + while (count && !IS_ALIGNED((unsigned long)dst, 8)) { > + __raw_writeb(c, dst); > + dst++; > + count--; > + } > + > + while (count >=3D 8) { > + __raw_writeq(qc, dst); > + dst +=3D 8; > + count -=3D 8; > + } > + > + while (count) { > + __raw_writeb(c, dst); > + dst++; > + count--; > + } > +} > +EXPORT_SYMBOL(__memset_io); > diff --git a/arch/loongarch/kernel/proc.c b/arch/loongarch/kernel/proc= .c > new file mode 100644 > index 000000000000..d25592a29196 > --- /dev/null > +++ b/arch/loongarch/kernel/proc.c > @@ -0,0 +1,122 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* > + * No lock; only written during early bootup by CPU 0. > + */ > +static RAW_NOTIFIER_HEAD(proc_cpuinfo_chain); > + > +int __ref register_proc_cpuinfo_notifier(struct notifier_block *nb) > +{ > + return raw_notifier_chain_register(&proc_cpuinfo_chain, nb); > +} > + > +int proc_cpuinfo_notifier_call_chain(unsigned long val, void *v) > +{ > + return raw_notifier_call_chain(&proc_cpuinfo_chain, val, v); > +} > + > +static int show_cpuinfo(struct seq_file *m, void *v) > +{ > + unsigned long n =3D (unsigned long) v - 1; > + unsigned int version =3D cpu_data[n].processor_id & 0xff; > + unsigned int fp_version =3D cpu_data[n].fpu_vers; > + struct proc_cpuinfo_notifier_args proc_cpuinfo_notifier_args; > + > + /* > + * For the first processor also print the system type > + */ > + if (n =3D=3D 0) > + seq_printf(m, "system type\t\t: %s\n\n", get_system_type()); > + > + seq_printf(m, "processor\t\t: %ld\n", n); > + seq_printf(m, "package\t\t\t: %d\n", cpu_data[n].package); > + seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core); > + seq_printf(m, "CPU Family\t\t: %s\n", __cpu_family[n]); > + seq_printf(m, "Model Name\t\t: %s\n", __cpu_full_name[n]); > + seq_printf(m, "CPU Revision\t\t: 0x%02x\n", version); > + seq_printf(m, "FPU Revision\t\t: 0x%02x\n", fp_version); > + seq_printf(m, "CPU MHz\t\t\t: %llu.%02llu\n", > + cpu_clock_freq / 1000000, (cpu_clock_freq / 10000) % 100); > + seq_printf(m, "BogoMIPS\t\t: %llu.%02llu\n", > + (lpj_fine * cpu_clock_freq / const_clock_freq) / (500000/HZ), > + ((lpj_fine * cpu_clock_freq / const_clock_freq) / (5000/HZ)) = %=20 > 100); > + seq_printf(m, "TLB Entries\t\t: %d\n", cpu_data[n].tlbsize); > + seq_printf(m, "Address Sizes\t\t: %d bits physical, %d bits=20 > virtual\n", > + cpu_pabits + 1, cpu_vabits + 1); > + > + seq_printf(m, "ISA\t\t\t:"); > + if (cpu_has_loongarch32) > + seq_printf(m, " loongarch32"); > + if (cpu_has_loongarch64) > + seq_printf(m, " loongarch64"); > + seq_printf(m, "\n"); > + > + seq_printf(m, "Features\t\t:"); > + if (cpu_has_cpucfg) seq_printf(m, " cpucfg"); > + if (cpu_has_lam) seq_printf(m, " lam"); > + if (cpu_has_ual) seq_printf(m, " ual"); > + if (cpu_has_fpu) seq_printf(m, " fpu"); > + if (cpu_has_lsx) seq_printf(m, " lsx"); > + if (cpu_has_lasx) seq_printf(m, " lasx"); > + if (cpu_has_complex) seq_printf(m, " complex"); > + if (cpu_has_crypto) seq_printf(m, " crypto"); > + if (cpu_has_lvz) seq_printf(m, " lvz"); > + if (cpu_has_lbt_x86) seq_printf(m, " lbt_x86"); > + if (cpu_has_lbt_arm) seq_printf(m, " lbt_arm"); > + if (cpu_has_lbt_mips) seq_printf(m, " lbt_mips"); > + seq_printf(m, "\n"); > + > + seq_printf(m, "Hardware Watchpoint\t: %s", > + cpu_has_watch ? "yes, " : "no\n"); > + if (cpu_has_watch) { > + seq_printf(m, "iwatch count: %d, dwatch count: %d\n", > + cpu_data[n].watch_ireg_count, cpu_data[n].watch_dreg_count); > + } > + > + proc_cpuinfo_notifier_args.m =3D m; > + proc_cpuinfo_notifier_args.n =3D n; > + > + raw_notifier_call_chain(&proc_cpuinfo_chain, 0, > + &proc_cpuinfo_notifier_args); > + > + seq_printf(m, "\n"); > + > + return 0; > +} > + > +static void *c_start(struct seq_file *m, loff_t *pos) > +{ > + unsigned long i =3D *pos; > + > + return i < NR_CPUS ? (void *)(i + 1) : NULL; > +} > + > +static void *c_next(struct seq_file *m, void *v, loff_t *pos) > +{ > + ++*pos; > + return c_start(m, pos); > +} > + > +static void c_stop(struct seq_file *m, void *v) > +{ > +} > + > +const struct seq_operations cpuinfo_op =3D { > + .start =3D c_start, > + .next =3D c_next, > + .stop =3D c_stop, > + .show =3D show_cpuinfo, > +}; > --=20 > 2.27.0 --=20 - Jiaxun